1 /* 2 * This file and its contents are supplied under the terms of the 3 * Common Development and Distribution License ("CDDL"), version 1.0. 4 * You may only use this file in accordance with the terms of version 5 * 1.0 of the CDDL. 6 * 7 * A full copy of the text of the CDDL should have accompanied this 8 * source. A copy of the CDDL is also available via the Internet at 9 * http://www.illumos.org/license/CDDL. 10 */ 11 12 /* 13 * Copyright (C) 2013 Hewlett-Packard Development Company, L.P. 14 */ 15 16 /* 17 * This module contains routines that program the controller. All 18 * operations viz., initialization of controller, submision & 19 * retrieval of commands, enabling & disabling of interrupts, 20 * checking interrupt status are performed here. 21 */ 22 23 #include <sys/sdt.h> 24 #include "cpqary3.h" 25 26 /* 27 * Local Functions Definitions 28 */ 29 uint8_t cpqary3_check_simple_ctlr_intr(cpqary3_t *cpqary3p); 30 uint8_t cpqary3_check_perf_ctlr_intr(cpqary3_t *cpqary3p); 31 uint8_t cpqary3_check_perf_e200_intr(cpqary3_t *cpqary3p); 32 uint8_t cpqary3_check_ctlr_init(cpqary3_t *); 33 34 /* 35 * Function : cpqary3_check_simple_ctlr_intr 36 * Description : This routine determines if the controller did interrupt. 37 * Called By : cpqary3_hw_isr() 38 * Parameters : per-controller 39 * Calls : None 40 * Return Values: SUCCESS : This controller did interrupt. 41 * FAILURE : It did not. 42 */ 43 uint8_t 44 cpqary3_check_simple_ctlr_intr(cpqary3_t *cpqary3p) 45 { 46 uint32_t intr_pending_mask = 0; 47 48 /* 49 * Read the Interrupt Status Register and 50 * if bit 3 is set, it indicates that we have completed commands 51 * in the controller 52 */ 53 intr_pending_mask = cpqary3p->bddef->bd_intrpendmask; 54 55 if (intr_pending_mask & 56 (ddi_get32(cpqary3p->isr_handle, (uint32_t *)cpqary3p->isr))) 57 return (CPQARY3_SUCCESS); 58 59 return (CPQARY3_FAILURE); 60 } 61 62 /* 63 * Function : cpqary3_check_perf_ctlr_intr 64 * Description : This routine determines if the 65 * controller did interrupt. 66 * Called By : cpqary3_hw_isr() 67 * Parameters : per-controller 68 * Calls : None 69 * Return Values: SUCCESS : This controller did interrupt. 70 * FAILURE : It did not. 71 */ 72 uint8_t 73 cpqary3_check_perf_ctlr_intr(cpqary3_t *cpqary3p) 74 { 75 /* 76 * Read the Interrupt Status Register and 77 * if bit 3 is set, it indicates that we have completed commands 78 * in the controller 79 */ 80 if (0x1 & (ddi_get32(cpqary3p->isr_handle, 81 (uint32_t *)cpqary3p->isr))) { 82 return (CPQARY3_SUCCESS); 83 } 84 85 return (CPQARY3_FAILURE); 86 } 87 88 /* 89 * Function : cpqary3_check_perf_e200_intr 90 * Description : This routine determines if the controller 91 * did interrupt. 92 * Called By : cpqary3_hw_isr() 93 * Parameters : per-controller 94 * Calls : None 95 * Return Values: SUCCESS : This controller did interrupt. 96 * FAILURE : It did not. 97 */ 98 uint8_t 99 cpqary3_check_perf_e200_intr(cpqary3_t *cpqary3p) 100 { 101 /* 102 * Read the Interrupt Status Register and 103 * if bit 3 is set, it indicates that we have completed commands 104 * in the controller 105 */ 106 if (0x4 & (ddi_get32(cpqary3p->isr_handle, 107 (uint32_t *)cpqary3p->isr))) { 108 return (CPQARY3_SUCCESS); 109 } 110 111 return (CPQARY3_FAILURE); 112 } 113 114 115 /* 116 * Function : cpqary3_retrieve 117 * Description : This routine retrieves the completed command from the 118 * controller reply queue. 119 * and processes the completed commands. 120 * Called By : cpqary3_sw_isr(), cpqary3_handle_flag_nointr() 121 * Parameters : per-controller 122 * Calls : packet completion routines 123 * Return Values: SUCCESS : A completed command has been retrieved 124 * and processed. 125 * FAILURE : No completed command was in the controller. 126 */ 127 uint8_t 128 cpqary3_retrieve(cpqary3_t *cpqary3p) 129 { 130 uint32_t tag; 131 uint32_t CmdsOutMax; 132 cpqary3_cmdpvt_t *cpqary3_cmdpvtp; 133 cpqary3_drvr_replyq_t *replyq_ptr; 134 135 /* 136 * Get the Reply Command List Addr 137 * Update the returned Tag in that particular command structure. 138 * If a valid one, de-q that from the SUBMITTED Q and 139 * enqueue that to the RETRIEVED Q. 140 */ 141 142 RETURN_FAILURE_IF_NULL(cpqary3p); 143 144 /* PERF */ 145 replyq_ptr = (cpqary3_drvr_replyq_t *)cpqary3p->drvr_replyq; 146 CmdsOutMax = cpqary3p->ctlr_maxcmds; 147 148 while ((replyq_ptr->replyq_headptr[0] & 0x01) == 149 replyq_ptr->cyclic_indicator) { 150 /* command has completed */ 151 /* Get the tag */ 152 153 tag = replyq_ptr->replyq_headptr[0]; 154 if ((tag >> CPQARY3_GET_MEM_TAG) >= (CmdsOutMax / 3) * 3) { 155 cmn_err(CE_WARN, 156 "CPQary3 : HBA returned Spurious Tag"); 157 return (CPQARY3_FAILURE); 158 } 159 160 cpqary3_cmdpvtp = &cpqary3p->cmdmemlistp->pool[ 161 tag >> CPQARY3_GET_MEM_TAG]; 162 cpqary3_cmdpvtp->cmdlist_memaddr-> 163 Header.Tag.drvinfo_n_err = (tag & 0xF) >> 1; 164 mutex_enter(&cpqary3p->sw_mutex); 165 cpqary3_cmdpvtp->complete(cpqary3_cmdpvtp); 166 mutex_exit(&cpqary3p->sw_mutex); 167 168 /* Traverse to the next command in reply queue */ 169 170 ++replyq_ptr->index; 171 if (replyq_ptr->index == replyq_ptr->max_index) { 172 replyq_ptr->index = 0; 173 /* Toggle at wraparound */ 174 replyq_ptr->cyclic_indicator = 175 (replyq_ptr->cyclic_indicator == 0) ? 1 : 0; 176 replyq_ptr->replyq_headptr = 177 /* LINTED: alignment */ 178 (uint32_t *)(replyq_ptr->replyq_start_addr); 179 } else { 180 replyq_ptr->replyq_headptr += 2; 181 } 182 } 183 /* PERF */ 184 185 return (CPQARY3_SUCCESS); 186 } 187 188 189 /* 190 * Function : cpqary3_poll_retrieve 191 * Description : This routine retrieves the completed command from the 192 * controller reply queue in poll mode. 193 * and processes the completed commands. 194 * Called By : cpqary3_poll 195 * Parameters : per-controller 196 * Calls : packet completion routines 197 * Return Values: If the polled command is completed, send back a success. 198 * If not return failure. 199 */ 200 uint8_t 201 cpqary3_poll_retrieve(cpqary3_t *cpqary3p, uint32_t poll_tag) 202 { 203 uint32_t tag; 204 uint32_t CmdsOutMax; 205 cpqary3_cmdpvt_t *cpqary3_cmdpvtp; 206 cpqary3_drvr_replyq_t *replyq_ptr; 207 uint32_t temp_tag; 208 uint8_t tag_flag = 0; 209 210 RETURN_FAILURE_IF_NULL(cpqary3p); 211 212 /* PERF */ 213 replyq_ptr = (cpqary3_drvr_replyq_t *)cpqary3p->drvr_replyq; 214 CmdsOutMax = cpqary3p->cmdmemlistp->max_memcnt; 215 216 if (!(cpqary3p->bddef->bd_flags & SA_BD_SAS)) { 217 while ((tag = ddi_get32(cpqary3p->opq_handle, 218 (uint32_t *)cpqary3p->opq)) != 0xFFFFFFFF) { 219 cpqary3_cmdpvtp = &cpqary3p->cmdmemlistp->pool[ 220 tag >> CPQARY3_GET_MEM_TAG]; 221 cpqary3_cmdpvtp->cmdlist_memaddr-> 222 Header.Tag.drvinfo_n_err = (tag & 0xF) >> 1; 223 temp_tag = cpqary3_cmdpvtp->tag.tag_value; 224 225 if (temp_tag == poll_tag) 226 tag_flag = 1; 227 cpqary3_cmdpvtp->complete(cpqary3_cmdpvtp); 228 } 229 } else { 230 while ((replyq_ptr->replyq_headptr[0] & 0x01) == 231 replyq_ptr->cyclic_indicator) { 232 /* command has completed */ 233 /* Get the tag */ 234 tag = replyq_ptr->replyq_headptr[0]; 235 236 if ((tag >> CPQARY3_GET_MEM_TAG) >= (CmdsOutMax/3)*3) { 237 cmn_err(CE_WARN, 238 "CPQary3 : HBA returned Spurious Tag"); 239 return (CPQARY3_FAILURE); 240 } 241 242 cpqary3_cmdpvtp = &cpqary3p->cmdmemlistp->pool[ 243 tag >> CPQARY3_GET_MEM_TAG]; 244 cpqary3_cmdpvtp->cmdlist_memaddr-> 245 Header.Tag.drvinfo_n_err = (tag & 0xF) >> 1; 246 temp_tag = cpqary3_cmdpvtp->tag.tag_value; 247 248 if (temp_tag == poll_tag) 249 tag_flag = 1; 250 251 cpqary3_cmdpvtp->complete(cpqary3_cmdpvtp); 252 253 /* Traverse to the next command in reply queue */ 254 ++replyq_ptr->index; 255 if (replyq_ptr->index == replyq_ptr->max_index) { 256 replyq_ptr->index = 0; 257 /* Toggle at wraparound */ 258 replyq_ptr->cyclic_indicator = 259 (replyq_ptr->cyclic_indicator == 0) ? 1 : 0; 260 replyq_ptr->replyq_headptr = 261 /* LINTED: alignment */ 262 (uint32_t *)(replyq_ptr->replyq_start_addr); 263 } else { 264 replyq_ptr->replyq_headptr += 2; 265 } 266 } 267 } 268 /* PERF */ 269 if (tag_flag) { 270 return (CPQARY3_SUCCESS); 271 } 272 273 return (CPQARY3_FAILURE); 274 } 275 276 /* 277 * Function : cpqary3_submit 278 * Description : This routine submits the command to the Inbound Post Q. 279 * Called By : cpqary3_transport(), cpqary3_send_NOE_command(), 280 * cpqary3_disable_NOE_command(), 281 * cpqary3_handle_flag_nointr(), 282 * cpqary3_tick_hdlr(), cpqary3_synccmd_send() 283 * Parameters : per-controller, physical address 284 * Calls : None 285 * Return Values: None 286 */ 287 int32_t 288 cpqary3_submit(cpqary3_t *cpqary3p, uint32_t cmd_phyaddr) 289 { 290 uint32_t phys_addr = 0; 291 uint8_t retval = 0; 292 293 /* 294 * Write the Physical Address of the command-to-be-submitted 295 * into the Controller's Inbound Post Q. 296 */ 297 298 ASSERT(cpqary3p != NULL); 299 300 #ifdef AMD64_DEBUG 301 { 302 char debug_char; 303 uint32_t tmp_cmd_phyaddr; 304 305 tmp_cmd_phyaddr = (uint32_t)(cmd_phyaddr & 0XFFFFFFFF); 306 307 cmn_err(CE_WARN, "CPQary3: cmd_phyaddr = %lX\n tmp_cmd_phyaddr = %lX", 308 cmd_phyaddr, tmp_cmd_phyaddr); 309 310 debug_enter(&debug_char); 311 ddi_put32(cpqary3p->ipq_handle, (uint32_t *)cpqary3p->ipq, cmd_phyaddr); 312 } 313 #endif 314 315 316 /* CONTROLLER_LOCKUP */ 317 if (cpqary3p->controller_lockup == CPQARY3_TRUE) { 318 retval = EIO; 319 return (retval); 320 } 321 /* CONTROLLER_LOCKUP */ 322 323 if (!(cpqary3p->bddef->bd_flags & SA_BD_SAS)) { 324 ddi_put32(cpqary3p->ipq_handle, 325 (uint32_t *)cpqary3p->ipq, cmd_phyaddr); 326 } else { 327 /* The driver always uses the 0th block fetch count always */ 328 phys_addr = cmd_phyaddr | 0 | 0x1; 329 ddi_put32(cpqary3p->ipq_handle, 330 (uint32_t *)cpqary3p->ipq, phys_addr); 331 } 332 333 /* PERF */ 334 335 /* 336 * Command submission can NEVER FAIL since the number of commands that 337 * can reside in the controller at any time is 1024 and our memory 338 * allocation is for 225 commands ONLY. Thus, at any given time the 339 * maximum number of commands in the controller is 225. 340 */ 341 342 /* CONTROLLER_LOCKUP */ 343 return (retval); 344 /* CONTROLLER_LOCKUP */ 345 346 } 347 348 349 /* 350 * Function : cpqary3_intr_onoff 351 * Description : This routine enables/disables the HBA interrupt. 352 * Called By : cpqary3_attach(), ry3_handle_flag_nointr(), 353 * cpqary3_tick_hdlr(), cpqary3_init_ctlr_resource() 354 * Parameters : per-controller, flag stating enable/disable 355 * Calls : None 356 * Return Values: None 357 */ 358 void 359 cpqary3_intr_onoff(cpqary3_t *cpqary3p, uint8_t flag) 360 { 361 uint32_t intr = 0; 362 uint32_t intr_mask = 0; 363 364 /* 365 * Enable or disable the interrupt based on the flag 366 * Read the Interrupt Mask Register first and then update it 367 * accordingly 368 */ 369 370 ASSERT(cpqary3p != NULL); 371 372 intr = ddi_get32(cpqary3p->imr_handle, (uint32_t *)cpqary3p->imr); 373 intr_mask = cpqary3p->bddef->bd_intrmask; 374 375 if (flag == CPQARY3_INTR_ENABLE) { 376 ddi_put32(cpqary3p->imr_handle, 377 (uint32_t *)cpqary3p->imr, intr & ~(intr_mask)); 378 } else { 379 ddi_put32(cpqary3p->imr_handle, 380 (uint32_t *)cpqary3p->imr, (intr | intr_mask)); 381 } 382 } 383 384 385 /* 386 * Function : cpqary3_lockup_intr_onoff 387 * Description : This routine enables/disables the lockup interrupt. 388 * Called By : cpqary3_attach(), cpqary3_handle_flag_nointr(), 389 * cpqary3_tick_hdlr(), cpqary3_hw_isr, 390 * cpqary3_init_ctlr_resource() 391 * Parameters : per-controller, flag stating enable/disable 392 * Calls : None 393 * Return Values: None 394 */ 395 void 396 cpqary3_lockup_intr_onoff(cpqary3_t *cpqary3p, uint8_t flag) 397 { 398 uint32_t intr = 0; 399 uint32_t intr_lockup_mask = 0; 400 401 /* 402 * Enable or disable the interrupt based on the flag 403 * Read the Interrupt Mask Register first and then update it 404 * accordingly 405 */ 406 407 ASSERT(cpqary3p != NULL); 408 409 intr = ddi_get32(cpqary3p->imr_handle, (uint32_t *)cpqary3p->imr); 410 intr_lockup_mask = cpqary3p->bddef->bd_lockup_intrmask; 411 412 if (flag == CPQARY3_INTR_ENABLE) { 413 ddi_put32(cpqary3p->imr_handle, 414 (uint32_t *)cpqary3p->imr, intr & ~(intr_lockup_mask)); 415 } else { 416 ddi_put32(cpqary3p->imr_handle, 417 (uint32_t *)cpqary3p->imr, (intr | intr_lockup_mask)); 418 } 419 } 420 421 /* 422 * Function : cpqary3_init_ctlr 423 * Description : This routine initialises the HBA to Simple Transport 424 * Method. Refer to CISS for more information. 425 * It checks the readiness of the HBA. 426 * Called By : cpqary3_init_ctlr_resource() 427 * Parameters : per-controller(), physical address() 428 * Calls : cpqary3_check_ctlr_init 429 * Return Values: SUCCESS / FAILURE 430 * [Shall return failure if the initialization of the 431 * controller to the Simple Transport Method fails] 432 */ 433 uint8_t 434 cpqary3_init_ctlr(cpqary3_t *cpqary3p) 435 { 436 uint8_t cntr; 437 uint8_t signature[4] = { 'C', 'I', 'S', 'S' }; 438 volatile CfgTable_t *ctp; 439 volatile CfgTrans_Perf_t *perf_cfg; 440 cpqary3_phyctg_t *cpqary3_phyctgp; 441 uint32_t phy_addr; 442 size_t cmd_size; 443 uint32_t queue_depth; 444 uint32_t CmdsOutMax; 445 uint32_t BlockFetchCnt[8]; 446 caddr_t replyq_start_addr = NULL; 447 /* SG */ 448 uint32_t max_blk_fetch_cnt = 0; 449 uint32_t max_sg_cnt = 0; 450 uint32_t optimal_sg = 0; 451 uint32_t optimal_sg_size = 0; 452 /* Header + Request + Error */ 453 uint32_t size_of_HRE = 0; 454 uint32_t size_of_cmdlist = 0; 455 /* SG */ 456 457 RETURN_FAILURE_IF_NULL(cpqary3p); 458 ctp = (CfgTable_t *)cpqary3p->ct; 459 perf_cfg = (CfgTrans_Perf_t *)cpqary3p->cp; 460 461 /* QUEUE CHANGES */ 462 cpqary3p->drvr_replyq = 463 (cpqary3_drvr_replyq_t *)MEM_ZALLOC(sizeof (cpqary3_drvr_replyq_t)); 464 /* QUEUE CHANGES */ 465 466 if (!cpqary3_check_ctlr_init(cpqary3p)) 467 return (CPQARY3_FAILURE); 468 469 DTRACE_PROBE1(ctlr_init_start, CfgTable_t *, ctp); 470 471 /* 472 * Validate the signature - should be "CISS" 473 * Use of cntr in the for loop does not suggest a counter - it just 474 * saves declaration of another variable. 475 */ 476 477 for (cntr = 0; cntr < 4; cntr++) { 478 if (DDI_GET8(cpqary3p, &ctp->Signature[cntr]) != 479 signature[cntr]) { 480 cmn_err(CE_WARN, "CPQary3 : Controller NOT ready"); 481 cmn_err(CE_WARN, "CPQary3 : _cpqary3_init_ctlr : " 482 "Signature not stamped"); 483 return (CPQARY3_FAILURE); 484 } 485 } 486 487 488 if (!(cpqary3p->bddef->bd_flags & SA_BD_SAS)) { 489 CmdsOutMax = DDI_GET32(cpqary3p, &ctp->CmdsOutMax); 490 491 if (CmdsOutMax == 0) { 492 cmn_err(CE_CONT, "CPQary3 : HBA Maximum Outstanding " 493 "Commands set to Zero\n"); 494 cmn_err(CE_CONT, "CPQary3 : Cannot continue driver " 495 "initialization \n"); 496 return (CPQARY3_FAILURE); 497 } 498 499 cpqary3p->ctlr_maxcmds = CmdsOutMax; 500 cpqary3p->sg_cnt = CPQARY3_SG_CNT; 501 502 queue_depth = cpqary3p->ctlr_maxcmds; 503 cmd_size = (8 * queue_depth); 504 /* QUEUE CHANGES */ 505 cpqary3p->drvr_replyq->cyclic_indicator = 506 CPQARY3_REPLYQ_INIT_CYCLIC_IND; 507 cpqary3p->drvr_replyq->simple_cyclic_indicator = 508 CPQARY3_REPLYQ_INIT_CYCLIC_IND; 509 cpqary3p->drvr_replyq->max_index = cpqary3p->ctlr_maxcmds; 510 cpqary3p->drvr_replyq->simple_index = 0; 511 replyq_start_addr = MEM_ZALLOC(cmd_size); 512 bzero(replyq_start_addr, cmd_size); 513 cpqary3p->drvr_replyq->replyq_headptr = 514 /* LINTED: alignment */ 515 (uint32_t *)replyq_start_addr; 516 cpqary3p->drvr_replyq->replyq_simple_ptr = 517 /* LINTED: alignment */ 518 (uint32_t *)replyq_start_addr; 519 cpqary3p->drvr_replyq->replyq_start_addr = replyq_start_addr; 520 521 /* PERF */ 522 523 /* 524 * Check for support of SIMPLE Transport Method 525 */ 526 if (!(DDI_GET32(cpqary3p, &ctp->TransportSupport) & 527 CFGTBL_XPORT_SIMPLE)) { 528 cmn_err(CE_WARN, "CPQary3 : Controller " 529 "NOT YET INITIALIZED"); 530 cmn_err(CE_CONT, "CPQary3 : For Hot Plug Operations, " 531 "try again later \n"); 532 return (CPQARY3_FAILURE); 533 } 534 535 /* 536 * Configuration Table Initialization 537 * Set bit 0 of InBound Door Bell Reg to inform the controller 538 * about the changes related to the Configuration table 539 */ 540 DTRACE_PROBE(cfgtable_init_start); 541 542 DDI_PUT32(cpqary3p, &ctp->HostWrite.TransportRequest, 543 CFGTBL_XPORT_SIMPLE); 544 ddi_put32(cpqary3p->idr_handle, (uint32_t *)cpqary3p->idr, 545 ddi_get32(cpqary3p->idr_handle, (uint32_t *)cpqary3p->idr) | 546 CFGTBL_CHANGE_REQ); 547 548 /* 549 * Check whether the controller is ready 550 */ 551 552 cntr = 0; 553 while (ddi_get32(cpqary3p->idr_handle, 554 (uint32_t *)cpqary3p->idr) & CFGTBL_ACC_CMDS) { 555 drv_usecwait(1000000); /* Wait for 1 Sec. */ 556 cntr++; 557 558 /* 559 * Wait for a maximum of 90 seconds. No f/w should take 560 * more than 90 secs to initialize. If the controller 561 * is not ready even after 90 secs, it suggests that 562 * something is wrong 563 * (wrt the controller, what else) !!! 564 */ 565 566 if (cntr > CISS_INIT_TIME) /* 1.30 Mins */ { 567 cmn_err(CE_CONT, "CPQary3 : Controller " 568 "Initialization Failed \n"); 569 return (CPQARY3_FAILURE); 570 } 571 } 572 573 DTRACE_PROBE(cfgtable_init_done); 574 575 /* 576 * Check whether controller accepts the requested method of 577 * transport 578 */ 579 if (!(DDI_GET32(cpqary3p, &ctp->TransportActive) & 580 CFGTBL_XPORT_SIMPLE)) { 581 cmn_err(CE_CONT, "CPQary3 : Failed to Initialize " 582 "Controller \n"); 583 cmn_err(CE_CONT, "CPQary3 : For Hot Plug Operations, " 584 "try again later\n"); 585 return (CPQARY3_FAILURE); 586 } 587 588 DTRACE_PROBE(ctlr_init_simple); 589 590 /* 591 * Check if Controller is ready to accept Commands 592 */ 593 594 if (!(DDI_GET32(cpqary3p, &ctp->TransportActive) & 595 CFGTBL_ACC_CMDS)) { 596 cmn_err(CE_CONT, "CPQary3: Controller NOT ready to " 597 "accept Commands \n"); 598 return (CPQARY3_FAILURE); 599 } 600 601 DTRACE_PROBE(ctlr_init_ready); 602 603 /* 604 * Check if the maximum number of oustanding commands for the 605 * initialized controller is something greater than Zero. 606 */ 607 608 CmdsOutMax = DDI_GET32(cpqary3p, &ctp->CmdsOutMax); 609 610 if (CmdsOutMax == 0) { 611 cmn_err(CE_CONT, "CPQary3 : HBA Maximum Outstanding " 612 "Commands set to Zero\n"); 613 cmn_err(CE_CONT, "CPQary3 : Cannot continue driver " 614 "initialization \n"); 615 return (CPQARY3_FAILURE); 616 } 617 cpqary3p->ctlr_maxcmds = CmdsOutMax; 618 619 /* 620 * Zero the Upper 32 Address in the Controller 621 */ 622 623 DDI_PUT32(cpqary3p, &ctp->HostWrite.Upper32Addr, 0x00000000); 624 cpqary3p->heartbeat = DDI_GET32(cpqary3p, &ctp->HeartBeat); 625 626 /* Set the controller interrupt check routine */ 627 cpqary3p->check_ctlr_intr = cpqary3_check_simple_ctlr_intr; 628 629 cpqary3p->host_support = 630 DDI_GET32(cpqary3p, &ctp->HostDrvrSupport); 631 DDI_PUT32(cpqary3p, &ctp->HostDrvrSupport, 632 (cpqary3p->host_support | 0x4)); 633 cpqary3p->host_support = 634 DDI_GET32(cpqary3p, &ctp->HostDrvrSupport); 635 636 cpqary3p->lockup_logged = CPQARY3_FALSE; 637 } else { 638 /* PERF */ 639 640 /* 641 * Check for support of PERF Transport Method 642 */ 643 if (!(DDI_GET32(cpqary3p, &ctp->TransportSupport) 644 & CFGTBL_XPORT_PERFORMANT)) { 645 cmn_err(CE_WARN, "CPQary3 : Controller " 646 "NOT YET INITIALIZED"); 647 cmn_err(CE_CONT, "CPQary3 : For Hot Plug Operations, " 648 "try again later \n"); 649 return (CPQARY3_FAILURE); 650 } 651 652 CmdsOutMax = DDI_GET32(cpqary3p, &ctp->MaxPerfModeCmdsOutMax); 653 if (CmdsOutMax == 0) 654 CmdsOutMax = DDI_GET32(cpqary3p, &ctp->CmdsOutMax); 655 if (CmdsOutMax == 0) { 656 cmn_err(CE_CONT, "CPQary3 : HBA Maximum Outstanding " 657 "Commands set to Zero\n"); 658 cmn_err(CE_CONT, "CPQary3 : Cannot continue driver " 659 "initialization \n"); 660 return (CPQARY3_FAILURE); 661 } 662 663 cpqary3p->ctlr_maxcmds = CmdsOutMax; 664 665 666 /* Initialize the Performant Method Transport Method Table */ 667 668 queue_depth = cpqary3p->ctlr_maxcmds; 669 670 DDI_PUT32_CP(cpqary3p, &perf_cfg->ReplyQSize, queue_depth); 671 DDI_PUT32_CP(cpqary3p, &perf_cfg->ReplyQCount, 1); 672 DDI_PUT32_CP(cpqary3p, &perf_cfg->ReplyQCntrAddrLow32, 0); 673 DDI_PUT32_CP(cpqary3p, &perf_cfg->ReplyQCntrAddrHigh32, 0); 674 675 cpqary3_phyctgp = 676 (cpqary3_phyctg_t *)MEM_ZALLOC(sizeof (cpqary3_phyctg_t)); 677 678 if (!cpqary3_phyctgp) { 679 cmn_err(CE_NOTE, 680 "CPQary3: Initial mem zalloc failed"); 681 return (CPQARY3_FAILURE); 682 } 683 cmd_size = (8 * queue_depth); 684 phy_addr = 0; 685 replyq_start_addr = cpqary3_alloc_phyctgs_mem(cpqary3p, 686 cmd_size, &phy_addr, cpqary3_phyctgp); 687 688 if (!replyq_start_addr) { 689 cmn_err(CE_WARN, "MEMALLOC returned failure"); 690 return (CPQARY3_FAILURE); 691 } 692 693 bzero(replyq_start_addr, cmd_size); 694 cpqary3p->drvr_replyq->replyq_headptr = 695 /* LINTED: alignment */ 696 (uint32_t *)replyq_start_addr; 697 cpqary3p->drvr_replyq->index = 0; 698 cpqary3p->drvr_replyq->max_index = queue_depth; 699 cpqary3p->drvr_replyq->replyq_start_addr = replyq_start_addr; 700 cpqary3p->drvr_replyq->cyclic_indicator = 701 CPQARY3_REPLYQ_INIT_CYCLIC_IND; 702 cpqary3p->drvr_replyq->replyq_start_paddr = phy_addr; 703 704 DDI_PUT32_CP(cpqary3p, &perf_cfg->ReplyQAddr0Low32, phy_addr); 705 DDI_PUT32_CP(cpqary3p, &perf_cfg->ReplyQAddr0High32, 0); 706 707 max_blk_fetch_cnt = 708 DDI_GET32(cpqary3p, &ctp->MaxBlockFetchCount); 709 710 /* 711 * For non-proton FW controllers, max_blk_fetch_count is not 712 * implemented in the firmware 713 */ 714 715 /* 716 * When blk fetch count is 0, FW auto fetches 564 bytes 717 * corresponding to an optimal S/G of 31 718 */ 719 if (max_blk_fetch_cnt == 0) { 720 BlockFetchCnt[0] = 35; 721 } else { 722 /* 723 * With MAX_PERF_SG_CNT set to 64, block fetch count 724 * is got by:(sizeof (CommandList_t) + 15)/16 725 */ 726 if (max_blk_fetch_cnt > 68) 727 BlockFetchCnt[0] = 68; 728 else 729 BlockFetchCnt[0] = max_blk_fetch_cnt; 730 } 731 732 DDI_PUT32_CP(cpqary3p, &perf_cfg->BlockFetchCnt[0], 733 BlockFetchCnt[0]); 734 DDI_PUT32(cpqary3p, &ctp->HostWrite.TransportRequest, 735 CFGTBL_XPORT_PERFORMANT); 736 ddi_put32(cpqary3p->idr_handle, (uint32_t *)cpqary3p->idr, 737 ddi_get32(cpqary3p->idr_handle, (uint32_t *)cpqary3p->idr) | 738 CFGTBL_CHANGE_REQ); 739 740 /* 741 * Check whether the controller is ready 742 */ 743 744 cntr = 0; 745 while (ddi_get32(cpqary3p->idr_handle, 746 (uint32_t *)cpqary3p->idr) & CFGTBL_ACC_CMDS) { 747 drv_usecwait(1000000); /* Wait for 1 Sec. */ 748 cntr++; 749 750 751 /* 752 * Wait for a maximum of 90 seconds. No f/w should take 753 * more than 90 secs to initialize. If the controller 754 * is not ready even after 90 secs, it suggests that 755 * something is wrong 756 * (wrt the controller, what else) !!! 757 */ 758 759 if (cntr > CISS_INIT_TIME) /* 1.30 Mins */ { 760 cmn_err(CE_CONT, "CPQary3 : Controller " 761 "Initialization Failed \n"); 762 return (CPQARY3_FAILURE); 763 } 764 } 765 766 /* 767 * Check whether controller accepts the requested method of 768 * transport 769 */ 770 771 if (!(DDI_GET32(cpqary3p, &ctp->TransportActive) & 772 CFGTBL_XPORT_PERFORMANT)) { 773 cmn_err(CE_NOTE, "CPQary3 : Failed to Initialize " 774 "Controller"); 775 cmn_err(CE_CONT, "CPQary3 : For Hot Plug Operations, " 776 "try again later\n"); 777 DTRACE_PROBE1(ctlr_init_perf_fail, CfgTable_t *, ctp); 778 return (CPQARY3_FAILURE); 779 } 780 781 DTRACE_PROBE(ctlr_init_simple); 782 783 /* 784 * Check if Controller is ready to accept Commands 785 */ 786 787 if (!(DDI_GET32(cpqary3p, &ctp->TransportActive) & 788 CFGTBL_ACC_CMDS)) { 789 cmn_err(CE_NOTE, "CPQary3: Controller NOT ready to " 790 "accept Commands"); 791 return (CPQARY3_FAILURE); 792 } 793 794 /* 795 * Check if the maximum number of oustanding commands for the 796 * initialized controller is something greater than Zero. 797 */ 798 799 CmdsOutMax = DDI_GET32(cpqary3p, &ctp->MaxPerfModeCmdsOutMax); 800 if (CmdsOutMax == 0) 801 CmdsOutMax = DDI_GET32(cpqary3p, &ctp->CmdsOutMax); 802 803 if (CmdsOutMax == 0) { 804 cmn_err(CE_NOTE, "CPQary3 : HBA Maximum Outstanding " 805 "Commands set to Zero"); 806 cmn_err(CE_NOTE, "CPQary3 : Cannot continue driver " 807 "initialization"); 808 return (CPQARY3_FAILURE); 809 } 810 811 cpqary3p->ctlr_maxcmds = CmdsOutMax; 812 813 /* SG */ 814 max_sg_cnt = DDI_GET32(cpqary3p, &ctp->MaxSGElements); 815 max_blk_fetch_cnt = 816 DDI_GET32(cpqary3p, &ctp->MaxBlockFetchCount); 817 818 /* 32 byte aligned - size_of_cmdlist */ 819 size_of_cmdlist = ((sizeof (CommandList_t) + 31) / 32) * 32; 820 size_of_HRE = size_of_cmdlist - 821 (sizeof (SGDescriptor_t) * CISS_MAXSGENTRIES); 822 823 if ((max_blk_fetch_cnt == 0) || (max_sg_cnt == 0) || 824 ((max_blk_fetch_cnt * 16) <= size_of_HRE)) { 825 cpqary3p->sg_cnt = CPQARY3_PERF_SG_CNT; 826 } else { 827 /* 828 * Get the optimal_sg - no of the SG's that will fit 829 * into the max_blk_fetch_cnt 830 */ 831 832 optimal_sg_size = 833 (max_blk_fetch_cnt * 16) - size_of_HRE; 834 835 if (optimal_sg_size < sizeof (SGDescriptor_t)) { 836 optimal_sg = CPQARY3_PERF_SG_CNT; 837 } else { 838 optimal_sg = 839 optimal_sg_size / sizeof (SGDescriptor_t); 840 } 841 842 cpqary3p->sg_cnt = MIN(max_sg_cnt, optimal_sg); 843 844 if (cpqary3p->sg_cnt > MAX_PERF_SG_CNT) 845 cpqary3p->sg_cnt = MAX_PERF_SG_CNT; 846 } 847 848 /* SG */ 849 850 /* 851 * Zero the Upper 32 Address in the Controller 852 */ 853 854 DDI_PUT32(cpqary3p, &ctp->HostWrite.Upper32Addr, 0x00000000); 855 cpqary3p->heartbeat = DDI_GET32(cpqary3p, &ctp->HeartBeat); 856 857 /* Set the controller interrupt check routine */ 858 859 if (cpqary3p->bddef->bd_is_e200) { 860 cpqary3p->check_ctlr_intr = 861 cpqary3_check_perf_e200_intr; 862 } else { 863 cpqary3p->check_ctlr_intr = 864 cpqary3_check_perf_ctlr_intr; 865 } 866 867 if ((!cpqary3p->bddef->bd_is_e200) && 868 (!cpqary3p->bddef->bd_is_ssll)) { 869 cpqary3p->host_support = 870 DDI_GET32(cpqary3p, &ctp->HostDrvrSupport); 871 DDI_PUT32(cpqary3p, &ctp->HostDrvrSupport, 872 (cpqary3p->host_support | 0x4)); 873 } 874 cpqary3p->host_support = 875 DDI_GET32(cpqary3p, &ctp->HostDrvrSupport); 876 cpqary3p->lockup_logged = CPQARY3_FALSE; 877 } 878 879 return (CPQARY3_SUCCESS); 880 } 881 882 /* 883 * Function : cpqary3_check_ctlr_init 884 * Description : This routine checks to see if the HBA is initialized. 885 * Called By : cpqary3_init_ctlr() 886 * Parameters : per-controller 887 * Calls : None 888 * Return Values: SUCCESS / FAILURE 889 */ 890 uint8_t 891 cpqary3_check_ctlr_init(cpqary3_t *cpqary3p) 892 { 893 int8_t retvalue; 894 uint16_t i; 895 uint32_t *ctlr_init; 896 ddi_acc_handle_t ctlr_init_handle; 897 extern ddi_device_acc_attr_t cpqary3_dev_attributes; 898 899 RETURN_FAILURE_IF_NULL(cpqary3p); 900 901 /* 902 * Set up the mapping for a Register at offset 0xB0 from I2O Bar 903 * The value 0xB0 taken from the CONFIGM utility. 904 * It should read 0xffff0000 if the controller is initialized. 905 * if not yet initialized, read it every second for 300 secs. 906 * If not set even after 300 secs, return FAILURE. 907 * If set, free the mapping and continue 908 */ 909 retvalue = ddi_regs_map_setup(cpqary3p->dip, INDEX_PCI_BASE0, 910 (caddr_t *)&ctlr_init, (offset_t)I2O_CTLR_INIT, 4, 911 &cpqary3_dev_attributes, &ctlr_init_handle); 912 913 if (retvalue != DDI_SUCCESS) { 914 if (DDI_REGS_ACC_CONFLICT == retvalue) 915 cmn_err(CE_WARN, 916 "CPQary3 : HBA Init Register Mapping Conflict"); 917 cmn_err(CE_WARN, 918 "CPQary3 : HBA Init Regsiter Mapping Failed"); 919 return (CPQARY3_FAILURE); 920 } 921 922 for (i = 0; i < 300; i++) { /* loop for 300 seconds */ 923 if (CISS_CTLR_INIT == ddi_get32(ctlr_init_handle, ctlr_init)) { 924 DTRACE_PROBE(ctlr_init_check_ready); 925 ddi_regs_map_free(&ctlr_init_handle); 926 break; 927 } else { 928 DTRACE_PROBE(ctlr_init_check_notready); 929 delay(drv_usectohz(1000000)); 930 } 931 } 932 933 if (i >= 300) { /* HBA not initialized even after 300 seconds !!! */ 934 ddi_regs_map_free(&ctlr_init_handle); 935 cmn_err(CE_WARN, "CPQary3 : %s NOT initialized !!! HBA may not " 936 "function properly. Please replace the hardware or check " 937 "the connections", cpqary3p->hba_name); 938 return (CPQARY3_FAILURE); 939 } 940 941 return (CPQARY3_SUCCESS); 942 } 943