1/*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 2004-07 Applied Micro Circuits Corporation. 5 * Copyright (c) 2004-05 Vinod Kashyap 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * 29 * $FreeBSD$ 30 */ 31 32/* 33 * AMCC'S 3ware driver for 9000 series storage controllers. 34 * 35 * Author: Vinod Kashyap 36 * Modifications by: Adam Radford 37 * Modifications by: Manjunath Ranganathaiah 38 */ 39 40 41/* 42 * Common Layer initialization functions. 43 */ 44 45 46#include "tw_osl_share.h" 47#include "tw_cl_share.h" 48#include "tw_cl_fwif.h" 49#include "tw_cl_ioctl.h" 50#include "tw_cl.h" 51#include "tw_cl_externs.h" 52#include "tw_osl_ioctl.h" 53 54 55/* 56 * Function name: tw_cl_ctlr_supported 57 * Description: Determines if a controller is supported. 58 * 59 * Input: vendor_id -- vendor id of the controller 60 * device_id -- device id of the controller 61 * Output: None 62 * Return value: TW_CL_TRUE-- controller supported 63 * TW_CL_FALSE-- controller not supported 64 */ 65TW_INT32 66tw_cl_ctlr_supported(TW_INT32 vendor_id, TW_INT32 device_id) 67{ 68 if ((vendor_id == TW_CL_VENDOR_ID) && 69 ((device_id == TW_CL_DEVICE_ID_9K) || 70 (device_id == TW_CL_DEVICE_ID_9K_X) || 71 (device_id == TW_CL_DEVICE_ID_9K_E) || 72 (device_id == TW_CL_DEVICE_ID_9K_SA))) 73 return(TW_CL_TRUE); 74 return(TW_CL_FALSE); 75} 76 77 78 79/* 80 * Function name: tw_cl_get_pci_bar_info 81 * Description: Returns PCI BAR info. 82 * 83 * Input: device_id -- device id of the controller 84 * bar_type -- type of PCI BAR in question 85 * Output: bar_num -- PCI BAR number corresponding to bar_type 86 * bar0_offset -- byte offset from BAR 0 (0x10 in 87 * PCI config space) 88 * bar_size -- size, in bytes, of the BAR in question 89 * Return value: 0 -- success 90 * non-zero -- failure 91 */ 92TW_INT32 93tw_cl_get_pci_bar_info(TW_INT32 device_id, TW_INT32 bar_type, 94 TW_INT32 *bar_num, TW_INT32 *bar0_offset, TW_INT32 *bar_size) 95{ 96 TW_INT32 error = TW_OSL_ESUCCESS; 97 98 switch(device_id) { 99 case TW_CL_DEVICE_ID_9K: 100 switch(bar_type) { 101 case TW_CL_BAR_TYPE_IO: 102 *bar_num = 0; 103 *bar0_offset = 0; 104 *bar_size = 4; 105 break; 106 107 case TW_CL_BAR_TYPE_MEM: 108 *bar_num = 1; 109 *bar0_offset = 0x4; 110 *bar_size = 8; 111 break; 112 113 case TW_CL_BAR_TYPE_SBUF: 114 *bar_num = 2; 115 *bar0_offset = 0xC; 116 *bar_size = 8; 117 break; 118 } 119 break; 120 121 case TW_CL_DEVICE_ID_9K_X: 122 case TW_CL_DEVICE_ID_9K_E: 123 case TW_CL_DEVICE_ID_9K_SA: 124 switch(bar_type) { 125 case TW_CL_BAR_TYPE_IO: 126 *bar_num = 2; 127 *bar0_offset = 0x10; 128 *bar_size = 4; 129 break; 130 131 case TW_CL_BAR_TYPE_MEM: 132 *bar_num = 1; 133 *bar0_offset = 0x8; 134 *bar_size = 8; 135 break; 136 137 case TW_CL_BAR_TYPE_SBUF: 138 *bar_num = 0; 139 *bar0_offset = 0; 140 *bar_size = 8; 141 break; 142 } 143 break; 144 145 default: 146 error = TW_OSL_ENOTTY; 147 break; 148 } 149 150 return(error); 151} 152 153 154 155/* 156 * Function name: tw_cl_get_mem_requirements 157 * Description: Provides info about Common Layer requirements for a 158 * controller, given the controller type (in 'flags'). 159 * Input: ctlr_handle -- controller handle 160 * flags -- more info passed by the OS Layer 161 * device_id -- device id of the controller 162 * max_simult_reqs -- maximum # of simultaneous 163 * requests that the OS Layer expects 164 * the Common Layer to support 165 * max_aens -- maximun # of AEN's needed to be supported 166 * Output: alignment -- alignment needed for all DMA'able 167 * buffers 168 * sg_size_factor -- every SG element should have a size 169 * that's a multiple of this number 170 * non_dma_mem_size -- # of bytes of memory needed for 171 * non-DMA purposes 172 * dma_mem_size -- # of bytes of DMA'able memory needed 173 * per_req_dma_mem_size -- # of bytes of DMA'able memory 174 * needed per request, if applicable 175 * per_req_non_dma_mem_size -- # of bytes of memory needed 176 * per request for non-DMA purposes, 177 * if applicable 178 * Output: None 179 * Return value: 0 -- success 180 * non-zero-- failure 181 */ 182TW_INT32 183tw_cl_get_mem_requirements(struct tw_cl_ctlr_handle *ctlr_handle, 184 TW_UINT32 flags, TW_INT32 device_id, TW_INT32 max_simult_reqs, 185 TW_INT32 max_aens, TW_UINT32 *alignment, TW_UINT32 *sg_size_factor, 186 TW_UINT32 *non_dma_mem_size, TW_UINT32 *dma_mem_size 187 ) 188{ 189 if (device_id == 0) 190 device_id = TW_CL_DEVICE_ID_9K; 191 192 if (max_simult_reqs > TW_CL_MAX_SIMULTANEOUS_REQUESTS) { 193 tw_cl_create_event(ctlr_handle, TW_CL_FALSE, 194 TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR, 195 0x1000, 0x1, TW_CL_SEVERITY_ERROR_STRING, 196 "Too many simultaneous requests to support!", 197 "requested = %d, supported = %d, error = %d\n", 198 max_simult_reqs, TW_CL_MAX_SIMULTANEOUS_REQUESTS, 199 TW_OSL_EBIG); 200 return(TW_OSL_EBIG); 201 } 202 203 *alignment = TWA_ALIGNMENT(device_id); 204 *sg_size_factor = TWA_SG_ELEMENT_SIZE_FACTOR(device_id); 205 206 /* 207 * Total non-DMA memory needed is the sum total of memory needed for 208 * the controller context, request packets (including the 1 needed for 209 * CL internal requests), and event packets. 210 */ 211 212 *non_dma_mem_size = sizeof(struct tw_cli_ctlr_context) + 213 (sizeof(struct tw_cli_req_context) * max_simult_reqs) + 214 (sizeof(struct tw_cl_event_packet) * max_aens); 215 216 217 /* 218 * Total DMA'able memory needed is the sum total of memory needed for 219 * all command packets (including the 1 needed for CL internal 220 * requests), and memory needed to hold the payload for internal 221 * requests. 222 */ 223 224 *dma_mem_size = (sizeof(struct tw_cl_command_packet) * 225 (max_simult_reqs)) + (TW_CLI_SECTOR_SIZE); 226 227 return(0); 228} 229 230 231 232/* 233 * Function name: tw_cl_init_ctlr 234 * Description: Initializes driver data structures for the controller. 235 * 236 * Input: ctlr_handle -- controller handle 237 * flags -- more info passed by the OS Layer 238 * device_id -- device id of the controller 239 * max_simult_reqs -- maximum # of simultaneous requests 240 * that the OS Layer expects the Common 241 * Layer to support 242 * max_aens -- maximun # of AEN's needed to be supported 243 * non_dma_mem -- ptr to allocated non-DMA memory 244 * dma_mem -- ptr to allocated DMA'able memory 245 * dma_mem_phys -- physical address of dma_mem 246 * Output: None 247 * Return value: 0 -- success 248 * non-zero-- failure 249 */ 250TW_INT32 251tw_cl_init_ctlr(struct tw_cl_ctlr_handle *ctlr_handle, TW_UINT32 flags, 252 TW_INT32 device_id, TW_INT32 max_simult_reqs, TW_INT32 max_aens, 253 TW_VOID *non_dma_mem, TW_VOID *dma_mem, TW_UINT64 dma_mem_phys 254 ) 255{ 256 struct tw_cli_ctlr_context *ctlr; 257 struct tw_cli_req_context *req; 258 TW_UINT8 *free_non_dma_mem; 259 TW_INT32 error = TW_OSL_ESUCCESS; 260 TW_INT32 i; 261 262 tw_cli_dbg_printf(3, ctlr_handle, tw_osl_cur_func(), "entered"); 263 264 if (flags & TW_CL_START_CTLR_ONLY) { 265 ctlr = (struct tw_cli_ctlr_context *) 266 (ctlr_handle->cl_ctlr_ctxt); 267 goto start_ctlr; 268 } 269 270 if (max_simult_reqs > TW_CL_MAX_SIMULTANEOUS_REQUESTS) { 271 tw_cl_create_event(ctlr_handle, TW_CL_FALSE, 272 TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR, 273 0x1000, 0x1, TW_CL_SEVERITY_ERROR_STRING, 274 "Too many simultaneous requests to support!", 275 "requested = %d, supported = %d, error = %d\n", 276 max_simult_reqs, TW_CL_MAX_SIMULTANEOUS_REQUESTS, 277 TW_OSL_EBIG); 278 return(TW_OSL_EBIG); 279 } 280 281 if ((non_dma_mem == TW_CL_NULL) || (dma_mem == TW_CL_NULL) 282 ) { 283 tw_cl_create_event(ctlr_handle, TW_CL_FALSE, 284 TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR, 285 0x1001, 0x1, TW_CL_SEVERITY_ERROR_STRING, 286 "Insufficient memory for Common Layer's internal usage", 287 "error = %d\n", TW_OSL_ENOMEM); 288 return(TW_OSL_ENOMEM); 289 } 290 291 tw_osl_memzero(non_dma_mem, sizeof(struct tw_cli_ctlr_context) + 292 (sizeof(struct tw_cli_req_context) * max_simult_reqs) + 293 (sizeof(struct tw_cl_event_packet) * max_aens)); 294 295 tw_osl_memzero(dma_mem, 296 (sizeof(struct tw_cl_command_packet) * 297 max_simult_reqs) + 298 TW_CLI_SECTOR_SIZE); 299 300 free_non_dma_mem = (TW_UINT8 *)non_dma_mem; 301 302 ctlr = (struct tw_cli_ctlr_context *)free_non_dma_mem; 303 free_non_dma_mem += sizeof(struct tw_cli_ctlr_context); 304 305 ctlr_handle->cl_ctlr_ctxt = ctlr; 306 ctlr->ctlr_handle = ctlr_handle; 307 308 ctlr->device_id = (TW_UINT32)device_id; 309 ctlr->arch_id = TWA_ARCH_ID(device_id); 310 ctlr->flags = flags; 311 ctlr->sg_size_factor = TWA_SG_ELEMENT_SIZE_FACTOR(device_id); 312 ctlr->max_simult_reqs = max_simult_reqs; 313 ctlr->max_aens_supported = max_aens; 314 315 /* Initialize queues of CL internal request context packets. */ 316 tw_cli_req_q_init(ctlr, TW_CLI_FREE_Q); 317 tw_cli_req_q_init(ctlr, TW_CLI_BUSY_Q); 318 tw_cli_req_q_init(ctlr, TW_CLI_PENDING_Q); 319 tw_cli_req_q_init(ctlr, TW_CLI_COMPLETE_Q); 320 tw_cli_req_q_init(ctlr, TW_CLI_RESET_Q); 321 322 /* Initialize all locks used by CL. */ 323 ctlr->gen_lock = &(ctlr->gen_lock_handle); 324 tw_osl_init_lock(ctlr_handle, "tw_cl_gen_lock", ctlr->gen_lock); 325 ctlr->io_lock = &(ctlr->io_lock_handle); 326 tw_osl_init_lock(ctlr_handle, "tw_cl_io_lock", ctlr->io_lock); 327 328 /* Initialize CL internal request context packets. */ 329 ctlr->req_ctxt_buf = (struct tw_cli_req_context *)free_non_dma_mem; 330 free_non_dma_mem += (sizeof(struct tw_cli_req_context) * 331 max_simult_reqs); 332 333 ctlr->cmd_pkt_buf = (struct tw_cl_command_packet *)dma_mem; 334 ctlr->cmd_pkt_phys = dma_mem_phys; 335 336 ctlr->internal_req_data = (TW_UINT8 *) 337 (ctlr->cmd_pkt_buf + 338 max_simult_reqs); 339 ctlr->internal_req_data_phys = ctlr->cmd_pkt_phys + 340 (sizeof(struct tw_cl_command_packet) * 341 max_simult_reqs); 342 343 for (i = 0; i < max_simult_reqs; i++) { 344 req = &(ctlr->req_ctxt_buf[i]); 345 346 req->cmd_pkt = &(ctlr->cmd_pkt_buf[i]); 347 req->cmd_pkt_phys = ctlr->cmd_pkt_phys + 348 (i * sizeof(struct tw_cl_command_packet)); 349 350 req->request_id = i; 351 req->ctlr = ctlr; 352 353 /* Insert request into the free queue. */ 354 tw_cli_req_q_insert_tail(req, TW_CLI_FREE_Q); 355 } 356 357 /* Initialize the AEN queue. */ 358 ctlr->aen_queue = (struct tw_cl_event_packet *)free_non_dma_mem; 359 360 361start_ctlr: 362 /* 363 * Disable interrupts. Interrupts will be enabled in tw_cli_start_ctlr 364 * (only) if initialization succeeded. 365 */ 366 tw_cli_disable_interrupts(ctlr); 367 368 /* Initialize the controller. */ 369 if ((error = tw_cli_start_ctlr(ctlr))) { 370 /* Soft reset the controller, and try one more time. */ 371 tw_cl_create_event(ctlr_handle, TW_CL_FALSE, 372 TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR, 373 0x1002, 0x1, TW_CL_SEVERITY_ERROR_STRING, 374 "Controller initialization failed. Retrying...", 375 "error = %d\n", error); 376 if ((error = tw_cli_soft_reset(ctlr))) { 377 tw_cl_create_event(ctlr_handle, TW_CL_FALSE, 378 TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR, 379 0x1003, 0x1, TW_CL_SEVERITY_ERROR_STRING, 380 "Controller soft reset failed", 381 "error = %d\n", error); 382 return(error); 383 } else if ((error = tw_cli_start_ctlr(ctlr))) { 384 tw_cl_create_event(ctlr_handle, TW_CL_FALSE, 385 TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR, 386 0x1004, 0x1, TW_CL_SEVERITY_ERROR_STRING, 387 "Controller initialization retry failed", 388 "error = %d\n", error); 389 return(error); 390 } 391 } 392 /* Notify some info about the controller to the OSL. */ 393 tw_cli_notify_ctlr_info(ctlr); 394 395 /* Mark the controller active. */ 396 ctlr->active = TW_CL_TRUE; 397 return(error); 398} 399 400/* 401 * Function name: tw_cli_start_ctlr 402 * Description: Establishes a logical connection with the controller. 403 * Determines whether or not the driver is compatible 404 * with the firmware on the controller, before proceeding 405 * to work with it. 406 * 407 * Input: ctlr -- ptr to per ctlr structure 408 * Output: None 409 * Return value: 0 -- success 410 * non-zero-- failure 411 */ 412TW_INT32 413tw_cli_start_ctlr(struct tw_cli_ctlr_context *ctlr) 414{ 415 TW_UINT16 fw_on_ctlr_srl = 0; 416 TW_UINT16 fw_on_ctlr_arch_id = 0; 417 TW_UINT16 fw_on_ctlr_branch = 0; 418 TW_UINT16 fw_on_ctlr_build = 0; 419 TW_UINT32 init_connect_result = 0; 420 TW_INT32 error = TW_OSL_ESUCCESS; 421 422 tw_cli_dbg_printf(3, ctlr->ctlr_handle, tw_osl_cur_func(), "entered"); 423 424 /* Wait for the controller to become ready. */ 425 if ((error = tw_cli_poll_status(ctlr, 426 TWA_STATUS_MICROCONTROLLER_READY, 427 TW_CLI_REQUEST_TIMEOUT_PERIOD))) { 428 tw_cl_create_event(ctlr->ctlr_handle, TW_CL_FALSE, 429 TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR, 430 0x1009, 0x1, TW_CL_SEVERITY_ERROR_STRING, 431 "Microcontroller not ready", 432 "error = %d", error); 433 return(error); 434 } 435 /* Drain the response queue. */ 436 if ((error = tw_cli_drain_response_queue(ctlr))) { 437 tw_cl_create_event(ctlr->ctlr_handle, TW_CL_FALSE, 438 TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR, 439 0x100A, 0x1, TW_CL_SEVERITY_ERROR_STRING, 440 "Can't drain response queue", 441 "error = %d", error); 442 return(error); 443 } 444 /* Establish a logical connection with the controller. */ 445 if ((error = tw_cli_init_connection(ctlr, 446 (TW_UINT16)(ctlr->max_simult_reqs), 447 TWA_EXTENDED_INIT_CONNECT, TWA_CURRENT_FW_SRL, 448 (TW_UINT16)(ctlr->arch_id), 449 TWA_CURRENT_FW_BRANCH(ctlr->arch_id), 450 TWA_CURRENT_FW_BUILD(ctlr->arch_id), 451 &fw_on_ctlr_srl, &fw_on_ctlr_arch_id, 452 &fw_on_ctlr_branch, &fw_on_ctlr_build, 453 &init_connect_result))) { 454 tw_cl_create_event(ctlr->ctlr_handle, TW_CL_FALSE, 455 TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR, 456 0x100B, 0x2, TW_CL_SEVERITY_WARNING_STRING, 457 "Can't initialize connection in current mode", 458 "error = %d", error); 459 return(error); 460 } 461 { 462 /* See if we can at least work with the firmware on the 463 * controller in the current mode. 464 */ 465 if (init_connect_result & TWA_CTLR_FW_COMPATIBLE) { 466 /* Yes, we can. Make note of the operating mode. */ 467 if (init_connect_result & TWA_CTLR_FW_SAME_OR_NEWER) { 468 ctlr->working_srl = TWA_CURRENT_FW_SRL; 469 ctlr->working_branch = 470 TWA_CURRENT_FW_BRANCH(ctlr->arch_id); 471 ctlr->working_build = 472 TWA_CURRENT_FW_BUILD(ctlr->arch_id); 473 } else { 474 ctlr->working_srl = fw_on_ctlr_srl; 475 ctlr->working_branch = fw_on_ctlr_branch; 476 ctlr->working_build = fw_on_ctlr_build; 477 } 478 } else { 479 /* 480 * No, we can't. See if we can at least work with 481 * it in the base mode. 482 */ 483 tw_cl_create_event(ctlr->ctlr_handle, TW_CL_FALSE, 484 TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR, 485 0x1010, 0x2, TW_CL_SEVERITY_WARNING_STRING, 486 "Driver/Firmware mismatch. " 487 "Negotiating for base level...", 488 " "); 489 if ((error = tw_cli_init_connection(ctlr, 490 (TW_UINT16)(ctlr->max_simult_reqs), 491 TWA_EXTENDED_INIT_CONNECT, 492 TWA_BASE_FW_SRL, 493 (TW_UINT16)(ctlr->arch_id), 494 TWA_BASE_FW_BRANCH, TWA_BASE_FW_BUILD, 495 &fw_on_ctlr_srl, &fw_on_ctlr_arch_id, 496 &fw_on_ctlr_branch, &fw_on_ctlr_build, 497 &init_connect_result))) { 498 tw_cl_create_event(ctlr->ctlr_handle, 499 TW_CL_FALSE, 500 TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR, 501 0x1011, 0x1, 502 TW_CL_SEVERITY_ERROR_STRING, 503 "Can't initialize connection in " 504 "base mode", 505 " "); 506 return(error); 507 } 508 if (!(init_connect_result & TWA_CTLR_FW_COMPATIBLE)) { 509 /* 510 * The firmware on the controller is not even 511 * compatible with our base mode. We cannot 512 * work with it. Bail... 513 */ 514 return(1); 515 } 516 /* 517 * We can work with this firmware, but only in 518 * base mode. 519 */ 520 ctlr->working_srl = TWA_BASE_FW_SRL; 521 ctlr->working_branch = TWA_BASE_FW_BRANCH; 522 ctlr->working_build = TWA_BASE_FW_BUILD; 523 ctlr->operating_mode = TWA_BASE_MODE; 524 } 525 ctlr->fw_on_ctlr_srl = fw_on_ctlr_srl; 526 ctlr->fw_on_ctlr_branch = fw_on_ctlr_branch; 527 ctlr->fw_on_ctlr_build = fw_on_ctlr_build; 528 } 529 530 /* Drain the AEN queue */ 531 if ((error = tw_cli_drain_aen_queue(ctlr))) 532 /* 533 * We will just print that we couldn't drain the AEN queue. 534 * There's no need to bail out. 535 */ 536 tw_cl_create_event(ctlr->ctlr_handle, TW_CL_FALSE, 537 TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR, 538 0x1014, 0x2, TW_CL_SEVERITY_WARNING_STRING, 539 "Can't drain AEN queue", 540 "error = %d", error); 541 542 /* Enable interrupts. */ 543 tw_cli_enable_interrupts(ctlr); 544 545 return(TW_OSL_ESUCCESS); 546} 547 548 549/* 550 * Function name: tw_cl_shutdown_ctlr 551 * Description: Closes logical connection with the controller. 552 * 553 * Input: ctlr -- ptr to per ctlr structure 554 * flags -- more info passed by the OS Layer 555 * Output: None 556 * Return value: 0 -- success 557 * non-zero-- failure 558 */ 559TW_INT32 560tw_cl_shutdown_ctlr(struct tw_cl_ctlr_handle *ctlr_handle, TW_UINT32 flags) 561{ 562 struct tw_cli_ctlr_context *ctlr = 563 (struct tw_cli_ctlr_context *)(ctlr_handle->cl_ctlr_ctxt); 564 TW_INT32 error; 565 566 tw_cli_dbg_printf(3, ctlr_handle, tw_osl_cur_func(), "entered"); 567 /* 568 * Mark the controller as inactive, disable any further interrupts, 569 * and notify the controller that we are going down. 570 */ 571 ctlr->active = TW_CL_FALSE; 572 573 tw_cli_disable_interrupts(ctlr); 574 575 /* Let the controller know that we are going down. */ 576 if ((error = tw_cli_init_connection(ctlr, TWA_SHUTDOWN_MESSAGE_CREDITS, 577 0, 0, 0, 0, 0, TW_CL_NULL, TW_CL_NULL, TW_CL_NULL, 578 TW_CL_NULL, TW_CL_NULL))) 579 tw_cl_create_event(ctlr_handle, TW_CL_FALSE, 580 TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR, 581 0x1015, 0x1, TW_CL_SEVERITY_ERROR_STRING, 582 "Can't close connection with controller", 583 "error = %d", error); 584 585 if (flags & TW_CL_STOP_CTLR_ONLY) 586 goto ret; 587 588 /* Destroy all locks used by CL. */ 589 tw_osl_destroy_lock(ctlr_handle, ctlr->gen_lock); 590 tw_osl_destroy_lock(ctlr_handle, ctlr->io_lock); 591 592ret: 593 return(error); 594} 595 596 597 598/* 599 * Function name: tw_cli_init_connection 600 * Description: Sends init_connection cmd to firmware 601 * 602 * Input: ctlr -- ptr to per ctlr structure 603 * message_credits -- max # of requests that we might send 604 * down simultaneously. This will be 605 * typically set to 256 at init-time or 606 * after a reset, and to 1 at shutdown-time 607 * set_features -- indicates if we intend to use 64-bit 608 * sg, also indicates if we want to do a 609 * basic or an extended init_connection; 610 * 611 * Note: The following input/output parameters are valid, only in case of an 612 * extended init_connection: 613 * 614 * current_fw_srl -- srl of fw we are bundled 615 * with, if any; 0 otherwise 616 * current_fw_arch_id -- arch_id of fw we are bundled 617 * with, if any; 0 otherwise 618 * current_fw_branch -- branch # of fw we are bundled 619 * with, if any; 0 otherwise 620 * current_fw_build -- build # of fw we are bundled 621 * with, if any; 0 otherwise 622 * Output: fw_on_ctlr_srl -- srl of fw on ctlr 623 * fw_on_ctlr_arch_id -- arch_id of fw on ctlr 624 * fw_on_ctlr_branch -- branch # of fw on ctlr 625 * fw_on_ctlr_build -- build # of fw on ctlr 626 * init_connect_result -- result bitmap of fw response 627 * Return value: 0 -- success 628 * non-zero-- failure 629 */ 630TW_INT32 631tw_cli_init_connection(struct tw_cli_ctlr_context *ctlr, 632 TW_UINT16 message_credits, TW_UINT32 set_features, 633 TW_UINT16 current_fw_srl, TW_UINT16 current_fw_arch_id, 634 TW_UINT16 current_fw_branch, TW_UINT16 current_fw_build, 635 TW_UINT16 *fw_on_ctlr_srl, TW_UINT16 *fw_on_ctlr_arch_id, 636 TW_UINT16 *fw_on_ctlr_branch, TW_UINT16 *fw_on_ctlr_build, 637 TW_UINT32 *init_connect_result) 638{ 639 struct tw_cli_req_context *req; 640 struct tw_cl_command_init_connect *init_connect; 641 TW_INT32 error = TW_OSL_EBUSY; 642 643 tw_cli_dbg_printf(3, ctlr->ctlr_handle, tw_osl_cur_func(), "entered"); 644 645 /* Get a request packet. */ 646 if ((req = tw_cli_get_request(ctlr 647 )) == TW_CL_NULL) 648 goto out; 649 650 req->flags |= TW_CLI_REQ_FLAGS_INTERNAL; 651 652 /* Build the cmd pkt. */ 653 init_connect = &(req->cmd_pkt->command.cmd_pkt_7k.init_connect); 654 655 req->cmd_pkt->cmd_hdr.header_desc.size_header = 128; 656 657 init_connect->res1__opcode = 658 BUILD_RES__OPCODE(0, TWA_FW_CMD_INIT_CONNECTION); 659 init_connect->request_id = 660 (TW_UINT8)(TW_CL_SWAP16(req->request_id)); 661 init_connect->message_credits = TW_CL_SWAP16(message_credits); 662 init_connect->features = TW_CL_SWAP32(set_features); 663 if (ctlr->flags & TW_CL_64BIT_ADDRESSES) 664 init_connect->features |= TW_CL_SWAP32(TWA_64BIT_SG_ADDRESSES); 665 if (set_features & TWA_EXTENDED_INIT_CONNECT) { 666 /* 667 * Fill in the extra fields needed for an extended 668 * init_connect. 669 */ 670 init_connect->size = 6; 671 init_connect->fw_srl = TW_CL_SWAP16(current_fw_srl); 672 init_connect->fw_arch_id = TW_CL_SWAP16(current_fw_arch_id); 673 init_connect->fw_branch = TW_CL_SWAP16(current_fw_branch); 674 init_connect->fw_build = TW_CL_SWAP16(current_fw_build); 675 } else 676 init_connect->size = 3; 677 678 /* Submit the command, and wait for it to complete. */ 679 error = tw_cli_submit_and_poll_request(req, 680 TW_CLI_REQUEST_TIMEOUT_PERIOD); 681 if (error) 682 goto out; 683 if ((error = init_connect->status)) { 684#if 0 685 tw_cli_create_ctlr_event(ctlr, 686 TW_CL_MESSAGE_SOURCE_CONTROLLER_ERROR, 687 &(req->cmd_pkt->cmd_hdr)); 688#endif // 0 689 goto out; 690 } 691 if (set_features & TWA_EXTENDED_INIT_CONNECT) { 692 *fw_on_ctlr_srl = TW_CL_SWAP16(init_connect->fw_srl); 693 *fw_on_ctlr_arch_id = TW_CL_SWAP16(init_connect->fw_arch_id); 694 *fw_on_ctlr_branch = TW_CL_SWAP16(init_connect->fw_branch); 695 *fw_on_ctlr_build = TW_CL_SWAP16(init_connect->fw_build); 696 *init_connect_result = TW_CL_SWAP32(init_connect->result); 697 } 698 tw_cli_req_q_insert_tail(req, TW_CLI_FREE_Q); 699 return(error); 700 701out: 702 tw_cl_create_event(ctlr->ctlr_handle, TW_CL_FALSE, 703 TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR, 704 0x1016, 0x1, TW_CL_SEVERITY_ERROR_STRING, 705 "init_connection failed", 706 "error = %d", error); 707 if (req) 708 tw_cli_req_q_insert_tail(req, TW_CLI_FREE_Q); 709 return(error); 710} 711 712 713