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