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 #include <sys/sdt.h> 17*80c94ecdSKeith M Wesolowski #include "cpqary3.h" 18*80c94ecdSKeith M Wesolowski 19*80c94ecdSKeith M Wesolowski /* 20*80c94ecdSKeith M Wesolowski * Local Functions Definitions 21*80c94ecdSKeith M Wesolowski */ 22*80c94ecdSKeith M Wesolowski 23*80c94ecdSKeith M Wesolowski int cpqary3_target_geometry(struct scsi_address *); 24*80c94ecdSKeith M Wesolowski int8_t cpqary3_detect_target_geometry(cpqary3_t *); 25*80c94ecdSKeith M Wesolowski 26*80c94ecdSKeith M Wesolowski /* 27*80c94ecdSKeith M Wesolowski * Function : cpqary3_read_conf_file 28*80c94ecdSKeith M Wesolowski * Description : This routine reads the driver configuration file. 29*80c94ecdSKeith M Wesolowski * Called By : cpqary3_attach() 30*80c94ecdSKeith M Wesolowski * Parameters : device-information pointer, per_controller 31*80c94ecdSKeith M Wesolowski * Calls : None 32*80c94ecdSKeith M Wesolowski * Return Values: None 33*80c94ecdSKeith M Wesolowski */ 34*80c94ecdSKeith M Wesolowski void 35*80c94ecdSKeith M Wesolowski cpqary3_read_conf_file(dev_info_t *dip, cpqary3_t *cpqary3p) 36*80c94ecdSKeith M Wesolowski { 37*80c94ecdSKeith M Wesolowski char *ptr; 38*80c94ecdSKeith M Wesolowski 39*80c94ecdSKeith M Wesolowski cpqary3p->noe_support = 0; 40*80c94ecdSKeith M Wesolowski 41*80c94ecdSKeith M Wesolowski /* 42*80c94ecdSKeith M Wesolowski * Plugin the code necessary to read from driver's conf file. 43*80c94ecdSKeith M Wesolowski * As of now, we are not interested in reading the onf file 44*80c94ecdSKeith M Wesolowski * for any purpose. 45*80c94ecdSKeith M Wesolowski * 46*80c94ecdSKeith M Wesolowski * eg. : 47*80c94ecdSKeith M Wesolowski * 48*80c94ecdSKeith M Wesolowski * retvalue = ddi_getprop(DDI_DEV_T_NONE, dip, DDI_PROP_DONTPASS, 49*80c94ecdSKeith M Wesolowski * "cpqary3_online_debug", -1); 50*80c94ecdSKeith M Wesolowski */ 51*80c94ecdSKeith M Wesolowski 52*80c94ecdSKeith M Wesolowski /* 53*80c94ecdSKeith M Wesolowski * We are calling ddi_prop_lookup_string 54*80c94ecdSKeith M Wesolowski * which gets the property value, which is passed at 55*80c94ecdSKeith M Wesolowski * the grub menu. If the user wants to use the older 56*80c94ecdSKeith M Wesolowski * target mapping algorithm,(prior to 1.80)at the grub menu 57*80c94ecdSKeith M Wesolowski * "cpqary3_tgtmap=off" should be entered. if this 58*80c94ecdSKeith M Wesolowski * string is entered, then we will set the 59*80c94ecdSKeith M Wesolowski * value of the variable legacy_mapping to one, which 60*80c94ecdSKeith M Wesolowski * will be used in 61*80c94ecdSKeith M Wesolowski * cpqary3_detect_target_geometry() 62*80c94ecdSKeith M Wesolowski * and cpqary3_probe4LVs(), to decide on the 63*80c94ecdSKeith M Wesolowski * mapping algorithm 64*80c94ecdSKeith M Wesolowski */ 65*80c94ecdSKeith M Wesolowski 66*80c94ecdSKeith M Wesolowski if (ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, 0, 67*80c94ecdSKeith M Wesolowski "cpqary3_tgtmap", &ptr) == DDI_PROP_SUCCESS) { 68*80c94ecdSKeith M Wesolowski if (strcmp("off", ptr) == 0) { 69*80c94ecdSKeith M Wesolowski cpqary3p->legacy_mapping = 1; 70*80c94ecdSKeith M Wesolowski } 71*80c94ecdSKeith M Wesolowski ddi_prop_free(ptr); 72*80c94ecdSKeith M Wesolowski } 73*80c94ecdSKeith M Wesolowski 74*80c94ecdSKeith M Wesolowski if (ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, 0, 75*80c94ecdSKeith M Wesolowski "cpqary3_noesupport", &ptr) == DDI_PROP_SUCCESS) { 76*80c94ecdSKeith M Wesolowski if (strcmp("on", ptr) == 0) { 77*80c94ecdSKeith M Wesolowski cpqary3p->noe_support = 1; 78*80c94ecdSKeith M Wesolowski } 79*80c94ecdSKeith M Wesolowski if (strcmp("off", ptr) == 0) { 80*80c94ecdSKeith M Wesolowski cpqary3p->noe_support = 0; 81*80c94ecdSKeith M Wesolowski } 82*80c94ecdSKeith M Wesolowski ddi_prop_free(ptr); 83*80c94ecdSKeith M Wesolowski } 84*80c94ecdSKeith M Wesolowski } 85*80c94ecdSKeith M Wesolowski 86*80c94ecdSKeith M Wesolowski /* 87*80c94ecdSKeith M Wesolowski * Function : cpqary3_tick_hdlr 88*80c94ecdSKeith M Wesolowski * Description : This routine is called once in 60 seconds to detect any 89*80c94ecdSKeith M Wesolowski * command that is pending with the controller and has 90*80c94ecdSKeith M Wesolowski * timed out. 91*80c94ecdSKeith M Wesolowski * Once invoked, it re-initializes itself such that it is 92*80c94ecdSKeith M Wesolowski * invoked after an interval of 60 seconds. 93*80c94ecdSKeith M Wesolowski * Called By : kernel 94*80c94ecdSKeith M Wesolowski * Parameters : per_controller 95*80c94ecdSKeith M Wesolowski * Calls : None 96*80c94ecdSKeith M Wesolowski * Return Values: None 97*80c94ecdSKeith M Wesolowski */ 98*80c94ecdSKeith M Wesolowski void 99*80c94ecdSKeith M Wesolowski cpqary3_tick_hdlr(void *arg) 100*80c94ecdSKeith M Wesolowski { 101*80c94ecdSKeith M Wesolowski clock_t cpqary3_lbolt; 102*80c94ecdSKeith M Wesolowski clock_t cpqary3_ticks; 103*80c94ecdSKeith M Wesolowski cpqary3_t *ctlr; 104*80c94ecdSKeith M Wesolowski cpqary3_pkt_t *pktp; 105*80c94ecdSKeith M Wesolowski struct scsi_pkt *scsi_pktp; 106*80c94ecdSKeith M Wesolowski cpqary3_cmdpvt_t *local; 107*80c94ecdSKeith M Wesolowski volatile CfgTable_t *ctp; 108*80c94ecdSKeith M Wesolowski uint32_t i; 109*80c94ecdSKeith M Wesolowski uint32_t no_cmds = 0; 110*80c94ecdSKeith M Wesolowski 111*80c94ecdSKeith M Wesolowski /* 112*80c94ecdSKeith M Wesolowski * The per-controller shall be passed as argument. 113*80c94ecdSKeith M Wesolowski * Read the HeartBeat of the controller. 114*80c94ecdSKeith M Wesolowski * if the current heartbeat is the same as the one recorded earlier, 115*80c94ecdSKeith M Wesolowski * the f/w has locked up!!! 116*80c94ecdSKeith M Wesolowski */ 117*80c94ecdSKeith M Wesolowski 118*80c94ecdSKeith M Wesolowski if (NULL == (ctlr = (cpqary3_t *)arg)) 119*80c94ecdSKeith M Wesolowski return; 120*80c94ecdSKeith M Wesolowski 121*80c94ecdSKeith M Wesolowski ctp = (CfgTable_t *)ctlr->ct; 122*80c94ecdSKeith M Wesolowski 123*80c94ecdSKeith M Wesolowski /* CONTROLLER_LOCKUP */ 124*80c94ecdSKeith M Wesolowski if (ctlr->heartbeat == DDI_GET32(ctlr, &ctp->HeartBeat)) { 125*80c94ecdSKeith M Wesolowski if (ctlr->lockup_logged == CPQARY3_FALSE) { 126*80c94ecdSKeith M Wesolowski cmn_err(CE_WARN, "CPQary3 : " 127*80c94ecdSKeith M Wesolowski "%s HBA firmware Locked !!!", ctlr->hba_name); 128*80c94ecdSKeith M Wesolowski cmn_err(CE_WARN, "CPQary3 : " 129*80c94ecdSKeith M Wesolowski "Please reboot the system"); 130*80c94ecdSKeith M Wesolowski cpqary3_intr_onoff(ctlr, CPQARY3_INTR_DISABLE); 131*80c94ecdSKeith M Wesolowski if (ctlr->host_support & 0x4) 132*80c94ecdSKeith M Wesolowski cpqary3_lockup_intr_onoff(ctlr, 133*80c94ecdSKeith M Wesolowski CPQARY3_LOCKUP_INTR_DISABLE); 134*80c94ecdSKeith M Wesolowski ctlr->controller_lockup = CPQARY3_TRUE; 135*80c94ecdSKeith M Wesolowski ctlr->lockup_logged = CPQARY3_TRUE; 136*80c94ecdSKeith M Wesolowski } 137*80c94ecdSKeith M Wesolowski } 138*80c94ecdSKeith M Wesolowski /* CONTROLLER_LOCKUP */ 139*80c94ecdSKeith M Wesolowski no_cmds = (uint32_t)((ctlr->ctlr_maxcmds / 3) * 140*80c94ecdSKeith M Wesolowski NO_OF_CMDLIST_IN_A_BLK); 141*80c94ecdSKeith M Wesolowski mutex_enter(&ctlr->sw_mutex); 142*80c94ecdSKeith M Wesolowski 143*80c94ecdSKeith M Wesolowski for (i = 0; i < no_cmds; i++) { 144*80c94ecdSKeith M Wesolowski local = &ctlr->cmdmemlistp->pool[i]; 145*80c94ecdSKeith M Wesolowski ASSERT(local != NULL); 146*80c94ecdSKeith M Wesolowski pktp = MEM2PVTPKT(local); 147*80c94ecdSKeith M Wesolowski 148*80c94ecdSKeith M Wesolowski if (!pktp) 149*80c94ecdSKeith M Wesolowski continue; 150*80c94ecdSKeith M Wesolowski 151*80c94ecdSKeith M Wesolowski if ((local->cmdpvt_flag == CPQARY3_TIMEOUT) || 152*80c94ecdSKeith M Wesolowski (local->cmdpvt_flag == CPQARY3_RESET)) { 153*80c94ecdSKeith M Wesolowski continue; 154*80c94ecdSKeith M Wesolowski } 155*80c94ecdSKeith M Wesolowski 156*80c94ecdSKeith M Wesolowski if (local->occupied == CPQARY3_OCCUPIED) { 157*80c94ecdSKeith M Wesolowski scsi_pktp = pktp->scsi_cmd_pkt; 158*80c94ecdSKeith M Wesolowski cpqary3_lbolt = ddi_get_lbolt(); 159*80c94ecdSKeith M Wesolowski if ((scsi_pktp) && (scsi_pktp->pkt_time)) { 160*80c94ecdSKeith M Wesolowski cpqary3_ticks = cpqary3_lbolt - 161*80c94ecdSKeith M Wesolowski pktp->cmd_start_time; 162*80c94ecdSKeith M Wesolowski 163*80c94ecdSKeith M Wesolowski if ((drv_hztousec(cpqary3_ticks)/1000000) > 164*80c94ecdSKeith M Wesolowski scsi_pktp->pkt_time) { 165*80c94ecdSKeith M Wesolowski scsi_pktp->pkt_reason = CMD_TIMEOUT; 166*80c94ecdSKeith M Wesolowski scsi_pktp->pkt_statistics = 167*80c94ecdSKeith M Wesolowski STAT_TIMEOUT; 168*80c94ecdSKeith M Wesolowski scsi_pktp->pkt_state = STATE_GOT_BUS | 169*80c94ecdSKeith M Wesolowski STATE_GOT_TARGET | STATE_SENT_CMD; 170*80c94ecdSKeith M Wesolowski local->cmdpvt_flag = CPQARY3_TIMEOUT; 171*80c94ecdSKeith M Wesolowski 172*80c94ecdSKeith M Wesolowski /* This should always be the case */ 173*80c94ecdSKeith M Wesolowski if (scsi_pktp->pkt_comp) { 174*80c94ecdSKeith M Wesolowski mutex_exit(&ctlr->sw_mutex); 175*80c94ecdSKeith M Wesolowski (*scsi_pktp->pkt_comp) 176*80c94ecdSKeith M Wesolowski (scsi_pktp); 177*80c94ecdSKeith M Wesolowski mutex_enter(&ctlr->sw_mutex); 178*80c94ecdSKeith M Wesolowski continue; 179*80c94ecdSKeith M Wesolowski } 180*80c94ecdSKeith M Wesolowski } 181*80c94ecdSKeith M Wesolowski } 182*80c94ecdSKeith M Wesolowski } 183*80c94ecdSKeith M Wesolowski } 184*80c94ecdSKeith M Wesolowski 185*80c94ecdSKeith M Wesolowski ctlr->heartbeat = DDI_GET32(ctlr, &ctp->HeartBeat); 186*80c94ecdSKeith M Wesolowski mutex_exit(&ctlr->sw_mutex); 187*80c94ecdSKeith M Wesolowski ctlr->tick_tmout_id = timeout(cpqary3_tick_hdlr, 188*80c94ecdSKeith M Wesolowski (caddr_t)ctlr, drv_usectohz(CPQARY3_TICKTMOUT_VALUE)); 189*80c94ecdSKeith M Wesolowski } 190*80c94ecdSKeith M Wesolowski 191*80c94ecdSKeith M Wesolowski /* 192*80c94ecdSKeith M Wesolowski * Function : cpqary3_init_ctlr_resource 193*80c94ecdSKeith M Wesolowski * Description : This routine initializes the command list, initializes 194*80c94ecdSKeith M Wesolowski * the controller, enables the interrupt. 195*80c94ecdSKeith M Wesolowski * Called By : cpqary3_attach() 196*80c94ecdSKeith M Wesolowski * Parameters : per_controller 197*80c94ecdSKeith M Wesolowski * Calls : cpqary3_init_ctlr(), cpqary3_meminit(), 198*80c94ecdSKeith M Wesolowski * cpqary3_intr_onoff(), 199*80c94ecdSKeith M Wesolowski * Return Values: SUCCESS / FAILURE 200*80c94ecdSKeith M Wesolowski * [ Shall return failure if any of the mandatory 201*80c94ecdSKeith M Wesolowski * initializations / setup of resources fail ] 202*80c94ecdSKeith M Wesolowski */ 203*80c94ecdSKeith M Wesolowski uint16_t 204*80c94ecdSKeith M Wesolowski cpqary3_init_ctlr_resource(cpqary3_t *ctlr) 205*80c94ecdSKeith M Wesolowski { 206*80c94ecdSKeith M Wesolowski #ifdef CPQARY3_DEBUG_MEM 207*80c94ecdSKeith M Wesolowski int8_t i = 0; 208*80c94ecdSKeith M Wesolowski #endif 209*80c94ecdSKeith M Wesolowski 210*80c94ecdSKeith M Wesolowski /* 211*80c94ecdSKeith M Wesolowski * Initialize the Controller 212*80c94ecdSKeith M Wesolowski * Alocate Memory Pool for driver supported number of Commands 213*80c94ecdSKeith M Wesolowski * return if not successful 214*80c94ecdSKeith M Wesolowski * Allocate target structure for controller and initialize the same 215*80c94ecdSKeith M Wesolowski * Detect all existing targets and allocate target structure for each 216*80c94ecdSKeith M Wesolowski * Determine geometry for all existing targets 217*80c94ecdSKeith M Wesolowski * Initialize the condition variables 218*80c94ecdSKeith M Wesolowski */ 219*80c94ecdSKeith M Wesolowski 220*80c94ecdSKeith M Wesolowski RETURN_FAILURE_IF_NULL(ctlr); 221*80c94ecdSKeith M Wesolowski 222*80c94ecdSKeith M Wesolowski if (CPQARY3_FAILURE == cpqary3_init_ctlr(ctlr)) 223*80c94ecdSKeith M Wesolowski return ((CPQARY3_FAILURE)); 224*80c94ecdSKeith M Wesolowski 225*80c94ecdSKeith M Wesolowski if (CPQARY3_FAILURE == cpqary3_meminit(ctlr)) 226*80c94ecdSKeith M Wesolowski return ((CPQARY3_FAILURE)); 227*80c94ecdSKeith M Wesolowski 228*80c94ecdSKeith M Wesolowski 229*80c94ecdSKeith M Wesolowski #ifdef CPQARY3_DEBUG_MEM 230*80c94ecdSKeith M Wesolowski /* 231*80c94ecdSKeith M Wesolowski * This code is in place to test the memory management of this driver. 232*80c94ecdSKeith M Wesolowski * This block of code allocates and de-allocates memory as many number 233*80c94ecdSKeith M Wesolowski * of times as given in the for loop. 234*80c94ecdSKeith M Wesolowski * After the for loop is executed, it returns a failure, which in turn 235*80c94ecdSKeith M Wesolowski * would result in attach being failed. 236*80c94ecdSKeith M Wesolowski */ 237*80c94ecdSKeith M Wesolowski cmn_err(CE_CONT, "CPQary3 : _init_ctlr_resource : Testing memory \n"); 238*80c94ecdSKeith M Wesolowski for (i = 0; i < 15; i++) { 239*80c94ecdSKeith M Wesolowski if (CPQARY3_SUCCESS != cpqary3_meminit(ctlr)) { 240*80c94ecdSKeith M Wesolowski cmn_err(CE_CONT, "CPQary3 : meminit failed : " 241*80c94ecdSKeith M Wesolowski "attempt %d \n", i); 242*80c94ecdSKeith M Wesolowski return (CPQARY3_FAILURE); 243*80c94ecdSKeith M Wesolowski } 244*80c94ecdSKeith M Wesolowski cmn_err(CE_CONT, 245*80c94ecdSKeith M Wesolowski "CPQary3 : INIT successful : attempt %d \n", i); 246*80c94ecdSKeith M Wesolowski cpqary3_memfini(ctlr, CPQARY3_MEMLIST_DONE | 247*80c94ecdSKeith M Wesolowski CPQARY3_PHYCTGS_DONE | CPQARY3_CMDMEM_DONE); 248*80c94ecdSKeith M Wesolowski cmn_err(CE_CONT, 249*80c94ecdSKeith M Wesolowski "CPQary3 : FINI successful : attempt %d \n", i); 250*80c94ecdSKeith M Wesolowski } 251*80c94ecdSKeith M Wesolowski return (CPQARY3_FAILURE); 252*80c94ecdSKeith M Wesolowski #endif 253*80c94ecdSKeith M Wesolowski 254*80c94ecdSKeith M Wesolowski ctlr->cpqary3_tgtp[CTLR_SCSI_ID] = MEM_ZALLOC(sizeof (cpqary3_tgt_t)); 255*80c94ecdSKeith M Wesolowski if (!(ctlr->cpqary3_tgtp[CTLR_SCSI_ID])) { 256*80c94ecdSKeith M Wesolowski cmn_err(CE_WARN, "CPQary3: Target Initialization Failed"); 257*80c94ecdSKeith M Wesolowski cpqary3_memfini(ctlr, CPQARY3_MEMLIST_DONE | 258*80c94ecdSKeith M Wesolowski CPQARY3_PHYCTGS_DONE | CPQARY3_CMDMEM_DONE); 259*80c94ecdSKeith M Wesolowski return (CPQARY3_FAILURE); 260*80c94ecdSKeith M Wesolowski } 261*80c94ecdSKeith M Wesolowski ctlr->cpqary3_tgtp[CTLR_SCSI_ID]->type = CPQARY3_TARGET_CTLR; 262*80c94ecdSKeith M Wesolowski 263*80c94ecdSKeith M Wesolowski cpqary3_intr_onoff(ctlr, CPQARY3_INTR_DISABLE); 264*80c94ecdSKeith M Wesolowski 265*80c94ecdSKeith M Wesolowski /* 266*80c94ecdSKeith M Wesolowski * Initialize all condition variables : 267*80c94ecdSKeith M Wesolowski * for the immediate call back 268*80c94ecdSKeith M Wesolowski * for the disable noe 269*80c94ecdSKeith M Wesolowski * for fulsh cache 270*80c94ecdSKeith M Wesolowski * for probe device 271*80c94ecdSKeith M Wesolowski */ 272*80c94ecdSKeith M Wesolowski 273*80c94ecdSKeith M Wesolowski cv_init(&ctlr->cv_immediate_wait, NULL, CV_DRIVER, NULL); 274*80c94ecdSKeith M Wesolowski cv_init(&ctlr->cv_noe_wait, NULL, CV_DRIVER, NULL); 275*80c94ecdSKeith M Wesolowski cv_init(&ctlr->cv_flushcache_wait, NULL, CV_DRIVER, NULL); 276*80c94ecdSKeith M Wesolowski cv_init(&ctlr->cv_abort_wait, NULL, CV_DRIVER, NULL); 277*80c94ecdSKeith M Wesolowski cv_init(&ctlr->cv_ioctl_wait, NULL, CV_DRIVER, NULL); 278*80c94ecdSKeith M Wesolowski 279*80c94ecdSKeith M Wesolowski return (CPQARY3_SUCCESS); 280*80c94ecdSKeith M Wesolowski } 281*80c94ecdSKeith M Wesolowski 282*80c94ecdSKeith M Wesolowski /* 283*80c94ecdSKeith M Wesolowski * Function : cpqary3_target_geometry 284*80c94ecdSKeith M Wesolowski * Description : This function returns the geometry for the target. 285*80c94ecdSKeith M Wesolowski * Called By : cpqary3_getcap() 286*80c94ecdSKeith M Wesolowski * Parameters : Target SCSI address 287*80c94ecdSKeith M Wesolowski * Calls : None 288*80c94ecdSKeith M Wesolowski * Return Values: Device Geometry 289*80c94ecdSKeith M Wesolowski */ 290*80c94ecdSKeith M Wesolowski int 291*80c94ecdSKeith M Wesolowski cpqary3_target_geometry(struct scsi_address *sa) 292*80c94ecdSKeith M Wesolowski { 293*80c94ecdSKeith M Wesolowski cpqary3_t *ctlr = SA2CTLR(sa); 294*80c94ecdSKeith M Wesolowski cpqary3_tgt_t *tgtp = ctlr->cpqary3_tgtp[SA2TGT(sa)]; 295*80c94ecdSKeith M Wesolowski 296*80c94ecdSKeith M Wesolowski /* 297*80c94ecdSKeith M Wesolowski * The target CHS are stored in the per-target structure 298*80c94ecdSKeith M Wesolowski * during attach time. Use these values 299*80c94ecdSKeith M Wesolowski */ 300*80c94ecdSKeith M Wesolowski return ((tgtp->properties.drive.heads << 16) | 301*80c94ecdSKeith M Wesolowski tgtp->properties.drive.sectors); 302*80c94ecdSKeith M Wesolowski } 303*80c94ecdSKeith M Wesolowski 304*80c94ecdSKeith M Wesolowski /* 305*80c94ecdSKeith M Wesolowski * Function : cpqary3_synccmd_alloc 306*80c94ecdSKeith M Wesolowski * Description : This function allocates the DMA buffer for the commands 307*80c94ecdSKeith M Wesolowski * Called By : cpqary3_ioctl_send_bmiccmd(), 308*80c94ecdSKeith M Wesolowski * cpqary3_ioctl_send_scsicmd() 309*80c94ecdSKeith M Wesolowski * cpqary3_send_abortcmd(), cpqary3_flush_cache(), 310*80c94ecdSKeith M Wesolowski * cpqary3_probe4LVs(), cpqary3_probe4Tapes(), 311*80c94ecdSKeith M Wesolowski * cpqary3_detect_target_geometry() 312*80c94ecdSKeith M Wesolowski * Parameters : per_controller, buffer size 313*80c94ecdSKeith M Wesolowski * Calls : cpqary3_alloc_phyctgs_mem(), cpqary3_cmdlist_occupy() 314*80c94ecdSKeith M Wesolowski * Return Values: memp 315*80c94ecdSKeith M Wesolowski */ 316*80c94ecdSKeith M Wesolowski cpqary3_cmdpvt_t * 317*80c94ecdSKeith M Wesolowski cpqary3_synccmd_alloc(cpqary3_t *cpqary3p, size_t bufsz) 318*80c94ecdSKeith M Wesolowski { 319*80c94ecdSKeith M Wesolowski cpqary3_private_t *cmddmah = NULL; 320*80c94ecdSKeith M Wesolowski uint32_t dmabufpa = 0; /* XXX 32-bit pa? */ 321*80c94ecdSKeith M Wesolowski cpqary3_cmdpvt_t *memp = NULL; 322*80c94ecdSKeith M Wesolowski 323*80c94ecdSKeith M Wesolowski /* first, allocate any necessary dma buffers */ 324*80c94ecdSKeith M Wesolowski if (bufsz > 0) { 325*80c94ecdSKeith M Wesolowski cpqary3_phyctg_t *dmah = NULL; 326*80c94ecdSKeith M Wesolowski caddr_t dmabufva = NULL; 327*80c94ecdSKeith M Wesolowski 328*80c94ecdSKeith M Wesolowski /* first, allocate the command's dma handle */ 329*80c94ecdSKeith M Wesolowski cmddmah = (cpqary3_private_t *)MEM_ZALLOC(sizeof (*cmddmah)); 330*80c94ecdSKeith M Wesolowski if (cmddmah == NULL) { 331*80c94ecdSKeith M Wesolowski cmn_err(CE_WARN, "cpqary3_synccmd_alloc: " 332*80c94ecdSKeith M Wesolowski "no memory for cmddmah"); 333*80c94ecdSKeith M Wesolowski return (NULL); 334*80c94ecdSKeith M Wesolowski } 335*80c94ecdSKeith M Wesolowski 336*80c94ecdSKeith M Wesolowski /* next, allocate dma handle */ 337*80c94ecdSKeith M Wesolowski dmah = (cpqary3_phyctg_t *)MEM_ZALLOC(sizeof (*dmah)); 338*80c94ecdSKeith M Wesolowski if (dmah == NULL) { 339*80c94ecdSKeith M Wesolowski MEM_SFREE(cmddmah, sizeof (*cmddmah)); 340*80c94ecdSKeith M Wesolowski cmn_err(CE_WARN, "cpqary3_synccmd_alloc: " 341*80c94ecdSKeith M Wesolowski "no memory for dmah"); 342*80c94ecdSKeith M Wesolowski return (NULL); 343*80c94ecdSKeith M Wesolowski } 344*80c94ecdSKeith M Wesolowski /* now, allocate dma buffer */ 345*80c94ecdSKeith M Wesolowski dmabufva = cpqary3_alloc_phyctgs_mem(cpqary3p, bufsz, 346*80c94ecdSKeith M Wesolowski &dmabufpa, dmah); 347*80c94ecdSKeith M Wesolowski if (dmabufva == NULL) { 348*80c94ecdSKeith M Wesolowski MEM_SFREE(cmddmah, sizeof (*cmddmah)); 349*80c94ecdSKeith M Wesolowski cmn_err(CE_WARN, "cpqary3_synccmd_alloc: " 350*80c94ecdSKeith M Wesolowski "no memory for dma buf"); 351*80c94ecdSKeith M Wesolowski return (NULL); 352*80c94ecdSKeith M Wesolowski } 353*80c94ecdSKeith M Wesolowski bzero(dmabufva, bufsz); 354*80c94ecdSKeith M Wesolowski 355*80c94ecdSKeith M Wesolowski /* attach dma buffer to command dma handle */ 356*80c94ecdSKeith M Wesolowski cmddmah->sg = dmabufva; 357*80c94ecdSKeith M Wesolowski cmddmah->phyctgp = dmah; 358*80c94ecdSKeith M Wesolowski } 359*80c94ecdSKeith M Wesolowski 360*80c94ecdSKeith M Wesolowski /* next, allocate a command packet */ 361*80c94ecdSKeith M Wesolowski memp = cpqary3_cmdlist_occupy(cpqary3p); 362*80c94ecdSKeith M Wesolowski if (memp == NULL) { 363*80c94ecdSKeith M Wesolowski if (cmddmah != NULL) { 364*80c94ecdSKeith M Wesolowski cpqary3_free_phyctgs_mem(cmddmah->phyctgp, 365*80c94ecdSKeith M Wesolowski CPQARY3_FREE_PHYCTG_MEM); 366*80c94ecdSKeith M Wesolowski MEM_SFREE(cmddmah, sizeof (*cmddmah)); 367*80c94ecdSKeith M Wesolowski } 368*80c94ecdSKeith M Wesolowski cmn_err(CE_WARN, "cpqary3_synccmd_alloc: " 369*80c94ecdSKeith M Wesolowski "cannot get free command"); 370*80c94ecdSKeith M Wesolowski return (NULL); 371*80c94ecdSKeith M Wesolowski } 372*80c94ecdSKeith M Wesolowski memp->cmdpvt_flag = 0; 373*80c94ecdSKeith M Wesolowski memp->cmdlist_memaddr->Header.Tag.drvinfo_n_err = 374*80c94ecdSKeith M Wesolowski CPQARY3_SYNCCMD_SUCCESS; 375*80c94ecdSKeith M Wesolowski 376*80c94ecdSKeith M Wesolowski /* attach dma resources to command */ 377*80c94ecdSKeith M Wesolowski memp->driverdata = cmddmah; 378*80c94ecdSKeith M Wesolowski memp->cmdlist_memaddr->SG[0].Addr = dmabufpa; 379*80c94ecdSKeith M Wesolowski memp->cmdlist_memaddr->SG[0].Len = (uint32_t)bufsz; 380*80c94ecdSKeith M Wesolowski 381*80c94ecdSKeith M Wesolowski /* done */ 382*80c94ecdSKeith M Wesolowski return (memp); 383*80c94ecdSKeith M Wesolowski } 384*80c94ecdSKeith M Wesolowski 385*80c94ecdSKeith M Wesolowski /* 386*80c94ecdSKeith M Wesolowski * Function : cpqary3_synccmd_cleanup 387*80c94ecdSKeith M Wesolowski * Description : This routine cleans up the command 388*80c94ecdSKeith M Wesolowski * Called By : cpqary3_process_pkt(), cpqary3_synccmd_free() 389*80c94ecdSKeith M Wesolowski * Parameters : per_command_memory 390*80c94ecdSKeith M Wesolowski * Calls : cpqary3_free_phyctgs_mem(), cpqary3_cmdlist_release() 391*80c94ecdSKeith M Wesolowski * Return Values: none 392*80c94ecdSKeith M Wesolowski */ 393*80c94ecdSKeith M Wesolowski void 394*80c94ecdSKeith M Wesolowski cpqary3_synccmd_cleanup(cpqary3_cmdpvt_t *memp) 395*80c94ecdSKeith M Wesolowski { 396*80c94ecdSKeith M Wesolowski /* 397*80c94ecdSKeith M Wesolowski * ordinary users should not call this routine 398*80c94ecdSKeith M Wesolowski * (use cpqary3_synccmd_free() instead). this is 399*80c94ecdSKeith M Wesolowski * for use ONLY by cpqary3_synccmd_free() and 400*80c94ecdSKeith M Wesolowski * cpqary3_process_pkt(). 401*80c94ecdSKeith M Wesolowski */ 402*80c94ecdSKeith M Wesolowski 403*80c94ecdSKeith M Wesolowski if (memp->driverdata != NULL) { 404*80c94ecdSKeith M Wesolowski /* free dma resources */ 405*80c94ecdSKeith M Wesolowski cpqary3_free_phyctgs_mem(memp->driverdata->phyctgp, 406*80c94ecdSKeith M Wesolowski CPQARY3_FREE_PHYCTG_MEM); 407*80c94ecdSKeith M Wesolowski MEM_SFREE(memp->driverdata, sizeof (cpqary3_private_t)); 408*80c94ecdSKeith M Wesolowski memp->driverdata = NULL; 409*80c94ecdSKeith M Wesolowski } 410*80c94ecdSKeith M Wesolowski /* release command */ 411*80c94ecdSKeith M Wesolowski memp->cmdpvt_flag = 0; 412*80c94ecdSKeith M Wesolowski cpqary3_cmdlist_release(memp, CPQARY3_HOLD_SW_MUTEX); 413*80c94ecdSKeith M Wesolowski } 414*80c94ecdSKeith M Wesolowski 415*80c94ecdSKeith M Wesolowski /* 416*80c94ecdSKeith M Wesolowski * Function : cpqary3_synccmd_free 417*80c94ecdSKeith M Wesolowski * Description : This routine frees the command and the 418*80c94ecdSKeith M Wesolowski * associated resources. 419*80c94ecdSKeith M Wesolowski * Called By : cpqary3_ioctl_send_bmiccmd(), 420*80c94ecdSKeith M Wesolowski * cpqary3_ioctl_send_scsicmd() 421*80c94ecdSKeith M Wesolowski * cpqary3_send_abortcmd(), cpqary3_flush_cache(), 422*80c94ecdSKeith M Wesolowski * cpqary3_probe4LVs(), cpqary3_probe4Tapes(), 423*80c94ecdSKeith M Wesolowski * cpqary3_detect_target_geometry() 424*80c94ecdSKeith M Wesolowski * Parameters : per_controller, per_command_memory 425*80c94ecdSKeith M Wesolowski * Calls : cpqary3_synccmd_cleanup() 426*80c94ecdSKeith M Wesolowski * Return Values: NONE 427*80c94ecdSKeith M Wesolowski */ 428*80c94ecdSKeith M Wesolowski void 429*80c94ecdSKeith M Wesolowski cpqary3_synccmd_free(cpqary3_t *cpqary3p, cpqary3_cmdpvt_t *memp) 430*80c94ecdSKeith M Wesolowski { 431*80c94ecdSKeith M Wesolowski /* 432*80c94ecdSKeith M Wesolowski * so, the user is done with this command packet. 433*80c94ecdSKeith M Wesolowski * we have three possible scenarios here: 434*80c94ecdSKeith M Wesolowski * 435*80c94ecdSKeith M Wesolowski * 1) the command was never submitted to the controller 436*80c94ecdSKeith M Wesolowski * 437*80c94ecdSKeith M Wesolowski * or 438*80c94ecdSKeith M Wesolowski * 439*80c94ecdSKeith M Wesolowski * 2) the command has completed at the controller and has 440*80c94ecdSKeith M Wesolowski * been fully processed by the interrupt processing 441*80c94ecdSKeith M Wesolowski * mechanism and is no longer on the submitted or 442*80c94ecdSKeith M Wesolowski * retrieve queues. 443*80c94ecdSKeith M Wesolowski * 444*80c94ecdSKeith M Wesolowski * or 445*80c94ecdSKeith M Wesolowski * 446*80c94ecdSKeith M Wesolowski * 3) the command is not yet complete at the controller, 447*80c94ecdSKeith M Wesolowski * and/or hasn't made it through cpqary3_process_pkt() 448*80c94ecdSKeith M Wesolowski * yet. 449*80c94ecdSKeith M Wesolowski * 450*80c94ecdSKeith M Wesolowski * For cases (1) and (2), we can go ahead and free the 451*80c94ecdSKeith M Wesolowski * command and the associated resources. For case (3), we 452*80c94ecdSKeith M Wesolowski * must mark the command as no longer needed, and let 453*80c94ecdSKeith M Wesolowski * cpqary3_process_pkt() clean it up instead. 454*80c94ecdSKeith M Wesolowski */ 455*80c94ecdSKeith M Wesolowski 456*80c94ecdSKeith M Wesolowski mutex_enter(&(cpqary3p->sw_mutex)); 457*80c94ecdSKeith M Wesolowski if (memp->cmdpvt_flag == CPQARY3_SYNC_SUBMITTED) { 458*80c94ecdSKeith M Wesolowski /* 459*80c94ecdSKeith M Wesolowski * command is still pending (case #3 above). 460*80c94ecdSKeith M Wesolowski * mark the command as abandoned and let 461*80c94ecdSKeith M Wesolowski * cpqary3_process_pkt() clean it up. 462*80c94ecdSKeith M Wesolowski */ 463*80c94ecdSKeith M Wesolowski memp->cmdpvt_flag = CPQARY3_SYNC_TIMEOUT; 464*80c94ecdSKeith M Wesolowski mutex_exit(&(cpqary3p->sw_mutex)); 465*80c94ecdSKeith M Wesolowski return; 466*80c94ecdSKeith M Wesolowski } 467*80c94ecdSKeith M Wesolowski memp->cmdpvt_flag = 0; 468*80c94ecdSKeith M Wesolowski mutex_exit(&(cpqary3p->sw_mutex)); 469*80c94ecdSKeith M Wesolowski 470*80c94ecdSKeith M Wesolowski /* 471*80c94ecdSKeith M Wesolowski * command was either never submitted or has completed 472*80c94ecdSKeith M Wesolowski * (cases #1 and #2 above). so, clean it up. 473*80c94ecdSKeith M Wesolowski */ 474*80c94ecdSKeith M Wesolowski cpqary3_synccmd_cleanup(memp); 475*80c94ecdSKeith M Wesolowski 476*80c94ecdSKeith M Wesolowski /* done */ 477*80c94ecdSKeith M Wesolowski return; 478*80c94ecdSKeith M Wesolowski 479*80c94ecdSKeith M Wesolowski } /* cpqary3_synccmd_free() */ 480*80c94ecdSKeith M Wesolowski 481*80c94ecdSKeith M Wesolowski /* 482*80c94ecdSKeith M Wesolowski * Function : cpqary3_synccmd_send 483*80c94ecdSKeith M Wesolowski * Description : This routine sends the command to the controller 484*80c94ecdSKeith M Wesolowski * Called By : cpqary3_ioctl_send_bmiccmd(), 485*80c94ecdSKeith M Wesolowski * cpqary3_ioctl_send_scsicmd() 486*80c94ecdSKeith M Wesolowski * cpqary3_send_abortcmd(), cpqary3_flush_cache(), 487*80c94ecdSKeith M Wesolowski * cpqary3_probe4LVs(), cpqary3_probe4Tapes(), 488*80c94ecdSKeith M Wesolowski * cpqary3_detect_target_geometry() 489*80c94ecdSKeith M Wesolowski * Parameters : per_controller, per_command_memory, timeout value, 490*80c94ecdSKeith M Wesolowski * flag(wait for reply) 491*80c94ecdSKeith M Wesolowski * Calls : cpqary3_submit(), cpqary3_add2submitted_cmdq() 492*80c94ecdSKeith M Wesolowski * Return Values: SUCCESS / FAILURE 493*80c94ecdSKeith M Wesolowski */ 494*80c94ecdSKeith M Wesolowski int 495*80c94ecdSKeith M Wesolowski cpqary3_synccmd_send(cpqary3_t *cpqary3p, cpqary3_cmdpvt_t *memp, 496*80c94ecdSKeith M Wesolowski clock_t timeoutms, int flags) 497*80c94ecdSKeith M Wesolowski { 498*80c94ecdSKeith M Wesolowski clock_t absto = 0; /* absolute timeout */ 499*80c94ecdSKeith M Wesolowski int waitsig = 0; 500*80c94ecdSKeith M Wesolowski int rc = 0; 501*80c94ecdSKeith M Wesolowski kcondvar_t *cv = 0; 502*80c94ecdSKeith M Wesolowski 503*80c94ecdSKeith M Wesolowski /* compute absolute timeout, if necessary */ 504*80c94ecdSKeith M Wesolowski if (timeoutms > 0) 505*80c94ecdSKeith M Wesolowski absto = ddi_get_lbolt() + drv_usectohz(timeoutms * 1000); 506*80c94ecdSKeith M Wesolowski 507*80c94ecdSKeith M Wesolowski /* heed signals during wait? */ 508*80c94ecdSKeith M Wesolowski if (flags & CPQARY3_SYNCCMD_SEND_WAITSIG) 509*80c94ecdSKeith M Wesolowski waitsig = 1; 510*80c94ecdSKeith M Wesolowski 511*80c94ecdSKeith M Wesolowski /* acquire the sw mutex for our wait */ 512*80c94ecdSKeith M Wesolowski mutex_enter(&(cpqary3p->sw_mutex)); 513*80c94ecdSKeith M Wesolowski 514*80c94ecdSKeith M Wesolowski /* submit command to controller */ 515*80c94ecdSKeith M Wesolowski mutex_enter(&(cpqary3p->hw_mutex)); 516*80c94ecdSKeith M Wesolowski 517*80c94ecdSKeith M Wesolowski memp->cmdpvt_flag = CPQARY3_SYNC_SUBMITTED; 518*80c94ecdSKeith M Wesolowski memp->cmdlist_memaddr->Header.Tag.drvinfo_n_err = 519*80c94ecdSKeith M Wesolowski CPQARY3_SYNCCMD_SUCCESS; 520*80c94ecdSKeith M Wesolowski if (EIO == cpqary3_submit(cpqary3p, memp->cmdlist_phyaddr)) { 521*80c94ecdSKeith M Wesolowski mutex_exit(&(cpqary3p->hw_mutex)); 522*80c94ecdSKeith M Wesolowski mutex_exit(&(cpqary3p->sw_mutex)); 523*80c94ecdSKeith M Wesolowski rc = -1; 524*80c94ecdSKeith M Wesolowski return (rc); 525*80c94ecdSKeith M Wesolowski } 526*80c94ecdSKeith M Wesolowski mutex_exit(&(cpqary3p->hw_mutex)); 527*80c94ecdSKeith M Wesolowski 528*80c94ecdSKeith M Wesolowski /* wait for command completion, timeout, or signal */ 529*80c94ecdSKeith M Wesolowski while (memp->cmdpvt_flag == CPQARY3_SYNC_SUBMITTED) { 530*80c94ecdSKeith M Wesolowski kmutex_t *mt = &(cpqary3p->sw_mutex); 531*80c94ecdSKeith M Wesolowski 532*80c94ecdSKeith M Wesolowski cv = &(cpqary3p->cv_ioctl_wait); 533*80c94ecdSKeith M Wesolowski /* wait with the request behavior */ 534*80c94ecdSKeith M Wesolowski if (absto) { 535*80c94ecdSKeith M Wesolowski clock_t crc; 536*80c94ecdSKeith M Wesolowski if (waitsig) { 537*80c94ecdSKeith M Wesolowski crc = cv_timedwait_sig(cv, mt, absto); 538*80c94ecdSKeith M Wesolowski } else { 539*80c94ecdSKeith M Wesolowski crc = cv_timedwait(cv, mt, absto); 540*80c94ecdSKeith M Wesolowski } 541*80c94ecdSKeith M Wesolowski if (crc > 0) 542*80c94ecdSKeith M Wesolowski rc = 0; 543*80c94ecdSKeith M Wesolowski else 544*80c94ecdSKeith M Wesolowski rc = (-1); 545*80c94ecdSKeith M Wesolowski } else { 546*80c94ecdSKeith M Wesolowski if (waitsig) { 547*80c94ecdSKeith M Wesolowski rc = cv_wait_sig(cv, mt); 548*80c94ecdSKeith M Wesolowski if (rc > 0) 549*80c94ecdSKeith M Wesolowski rc = 0; 550*80c94ecdSKeith M Wesolowski else 551*80c94ecdSKeith M Wesolowski rc = (-1); 552*80c94ecdSKeith M Wesolowski } else { 553*80c94ecdSKeith M Wesolowski cv_wait(cv, mt); 554*80c94ecdSKeith M Wesolowski rc = 0; 555*80c94ecdSKeith M Wesolowski } 556*80c94ecdSKeith M Wesolowski } 557*80c94ecdSKeith M Wesolowski 558*80c94ecdSKeith M Wesolowski 559*80c94ecdSKeith M Wesolowski /* 560*80c94ecdSKeith M Wesolowski * if our wait was interrupted (timeout), 561*80c94ecdSKeith M Wesolowski * then break here 562*80c94ecdSKeith M Wesolowski */ 563*80c94ecdSKeith M Wesolowski if (rc) { 564*80c94ecdSKeith M Wesolowski break; 565*80c94ecdSKeith M Wesolowski } 566*80c94ecdSKeith M Wesolowski } 567*80c94ecdSKeith M Wesolowski 568*80c94ecdSKeith M Wesolowski /* our wait is done, so release the sw mutex */ 569*80c94ecdSKeith M Wesolowski mutex_exit(&(cpqary3p->sw_mutex)); 570*80c94ecdSKeith M Wesolowski 571*80c94ecdSKeith M Wesolowski /* return the results */ 572*80c94ecdSKeith M Wesolowski return (rc); 573*80c94ecdSKeith M Wesolowski } 574*80c94ecdSKeith M Wesolowski 575*80c94ecdSKeith M Wesolowski /* 576*80c94ecdSKeith M Wesolowski * Function : cpqary3_detect_target_geometry 577*80c94ecdSKeith M Wesolowski * Description : This function determines the geometry for all 578*80c94ecdSKeith M Wesolowski * the existing targets for the controller. 579*80c94ecdSKeith M Wesolowski * Called By : cpqary3_tgt_init() 580*80c94ecdSKeith M Wesolowski * Parameters : per controller 581*80c94ecdSKeith M Wesolowski * Calls : cpqary3_synccmd_alloc(), cpqary3_synccmd_send() 582*80c94ecdSKeith M Wesolowski * cpqary3_synccmd_free() 583*80c94ecdSKeith M Wesolowski * Return Values: SUCCESS / FAILURE 584*80c94ecdSKeith M Wesolowski * [ Shall return failure only if Memory constraints exist 585*80c94ecdSKeith M Wesolowski * or controller does not respond ] 586*80c94ecdSKeith M Wesolowski */ 587*80c94ecdSKeith M Wesolowski int8_t 588*80c94ecdSKeith M Wesolowski cpqary3_detect_target_geometry(cpqary3_t *ctlr) 589*80c94ecdSKeith M Wesolowski { 590*80c94ecdSKeith M Wesolowski int i; 591*80c94ecdSKeith M Wesolowski int8_t ld_count = 0; 592*80c94ecdSKeith M Wesolowski int8_t loop_cnt = 0; 593*80c94ecdSKeith M Wesolowski IdLogDrive *idlogdrive; 594*80c94ecdSKeith M Wesolowski CommandList_t *cmdlistp; 595*80c94ecdSKeith M Wesolowski cpqary3_cmdpvt_t *cpqary3_cmdpvtp; 596*80c94ecdSKeith M Wesolowski 597*80c94ecdSKeith M Wesolowski RETURN_FAILURE_IF_NULL(ctlr); 598*80c94ecdSKeith M Wesolowski 599*80c94ecdSKeith M Wesolowski /* 600*80c94ecdSKeith M Wesolowski * Occupy a Command List 601*80c94ecdSKeith M Wesolowski * Allocate Memory for return data 602*80c94ecdSKeith M Wesolowski * If error, RETURN 0. 603*80c94ecdSKeith M Wesolowski * get the Request Block from the CommandList 604*80c94ecdSKeith M Wesolowski * Fill in the Request Packet with the corresponding values 605*80c94ecdSKeith M Wesolowski * Submit the Command and Poll for its completion 606*80c94ecdSKeith M Wesolowski * If success, continue else RETURN 0 607*80c94ecdSKeith M Wesolowski */ 608*80c94ecdSKeith M Wesolowski 609*80c94ecdSKeith M Wesolowski /* Sync Changes */ 610*80c94ecdSKeith M Wesolowski cpqary3_cmdpvtp = cpqary3_synccmd_alloc(ctlr, sizeof (IdLogDrive)); 611*80c94ecdSKeith M Wesolowski if (cpqary3_cmdpvtp == NULL) 612*80c94ecdSKeith M Wesolowski return (CPQARY3_FAILURE); 613*80c94ecdSKeith M Wesolowski 614*80c94ecdSKeith M Wesolowski cmdlistp = cpqary3_cmdpvtp->cmdlist_memaddr; 615*80c94ecdSKeith M Wesolowski idlogdrive = (IdLogDrive *)cpqary3_cmdpvtp->driverdata->sg; 616*80c94ecdSKeith M Wesolowski /* Sync Changes */ 617*80c94ecdSKeith M Wesolowski 618*80c94ecdSKeith M Wesolowski 619*80c94ecdSKeith M Wesolowski /* Update Cmd Header */ 620*80c94ecdSKeith M Wesolowski cmdlistp->Header.SGList = 1; 621*80c94ecdSKeith M Wesolowski cmdlistp->Header.SGTotal = 1; 622*80c94ecdSKeith M Wesolowski cmdlistp->Header.Tag.drvinfo_n_err = CPQARY3_SYNCCMD_SUCCESS; 623*80c94ecdSKeith M Wesolowski 624*80c94ecdSKeith M Wesolowski /* Cmd Reques */ 625*80c94ecdSKeith M Wesolowski cmdlistp->Request.CDBLen = CPQARY3_CDBLEN_16; 626*80c94ecdSKeith M Wesolowski cmdlistp->Request.CDB[0] = 0x26; 627*80c94ecdSKeith M Wesolowski cmdlistp->Request.CDB[6] = BMIC_IDENTIFY_LOGICAL_DRIVE; 628*80c94ecdSKeith M Wesolowski cmdlistp->Request.CDB[7] = (sizeof (IdLogDrive) >> 8) & 0xff; 629*80c94ecdSKeith M Wesolowski cmdlistp->Request.CDB[8] = sizeof (IdLogDrive) & 0xff; 630*80c94ecdSKeith M Wesolowski cmdlistp->Request.Type.Type = CISS_TYPE_CMD; 631*80c94ecdSKeith M Wesolowski cmdlistp->Request.Type.Attribute = CISS_ATTR_HEADOFQUEUE; 632*80c94ecdSKeith M Wesolowski cmdlistp->Request.Type.Direction = CISS_XFER_READ; 633*80c94ecdSKeith M Wesolowski 634*80c94ecdSKeith M Wesolowski /* 635*80c94ecdSKeith M Wesolowski * For all the Targets that exist, issue an IDENTIFY LOGICAL DRIVE. 636*80c94ecdSKeith M Wesolowski * That returns values which includes the dsired Geometry also. 637*80c94ecdSKeith M Wesolowski * Update the Geometry in the per-target structure. 638*80c94ecdSKeith M Wesolowski * NOTE : When the loop is executed for i=controller's SCSI ID, just 639*80c94ecdSKeith M Wesolowski * increament by one so that we are talking to the next logical 640*80c94ecdSKeith M Wesolowski * drive in our per-target structure. 641*80c94ecdSKeith M Wesolowski */ 642*80c94ecdSKeith M Wesolowski 643*80c94ecdSKeith M Wesolowski /* 644*80c94ecdSKeith M Wesolowski * Depending upon the value of the variable legacy_mapping 645*80c94ecdSKeith M Wesolowski * set in cpqary3_attach(), 646*80c94ecdSKeith M Wesolowski * the target mapping algorithm to be used by the driver is decided. 647*80c94ecdSKeith M Wesolowski */ 648*80c94ecdSKeith M Wesolowski 649*80c94ecdSKeith M Wesolowski if (ctlr->legacy_mapping == 1) { 650*80c94ecdSKeith M Wesolowski loop_cnt = ((ctlr->num_of_targets > CTLR_SCSI_ID) ? 651*80c94ecdSKeith M Wesolowski (ctlr->num_of_targets + 1) : (ctlr->num_of_targets)); 652*80c94ecdSKeith M Wesolowski 653*80c94ecdSKeith M Wesolowski for (i = 0; i < loop_cnt; i++) { 654*80c94ecdSKeith M Wesolowski if (i == CTLR_SCSI_ID) /* Go to Next logical target */ 655*80c94ecdSKeith M Wesolowski i++; 656*80c94ecdSKeith M Wesolowski 657*80c94ecdSKeith M Wesolowski bzero(idlogdrive, sizeof (IdLogDrive)); 658*80c94ecdSKeith M Wesolowski cmdlistp->Request.CDB[1] = 659*80c94ecdSKeith M Wesolowski ctlr->cpqary3_tgtp[i]->logical_id; 660*80c94ecdSKeith M Wesolowski 661*80c94ecdSKeith M Wesolowski /* Always zero */ 662*80c94ecdSKeith M Wesolowski cmdlistp->Header.LUN.PhysDev.TargetId = 0; 663*80c94ecdSKeith M Wesolowski 664*80c94ecdSKeith M Wesolowski /* 665*80c94ecdSKeith M Wesolowski * Logical volume Id numbering scheme is as follows 666*80c94ecdSKeith M Wesolowski * 0x00000, 0x00001, ... - for Direct Attached 667*80c94ecdSKeith M Wesolowski * 0x10000, 0x10001, ... - If 1st Port of HBA is 668*80c94ecdSKeith M Wesolowski * connected to MSA20 / MSA500 669*80c94ecdSKeith M Wesolowski * 0x20000, 0x20001, ... - If 2nd Port of HBA is 670*80c94ecdSKeith M Wesolowski * connected to MSA20 / MSA500 671*80c94ecdSKeith M Wesolowski */ 672*80c94ecdSKeith M Wesolowski cmdlistp->Header.LUN.PhysDev.Bus = 673*80c94ecdSKeith M Wesolowski (ctlr->cpqary3_tgtp[i]->logical_id) >> 16; 674*80c94ecdSKeith M Wesolowski cmdlistp->Header.LUN.PhysDev.Mode = 675*80c94ecdSKeith M Wesolowski (cmdlistp->Header.LUN.PhysDev.Bus > 0) ? 676*80c94ecdSKeith M Wesolowski MASK_PERIPHERIAL_DEV_ADDR : PERIPHERIAL_DEV_ADDR; 677*80c94ecdSKeith M Wesolowski 678*80c94ecdSKeith M Wesolowski /* 679*80c94ecdSKeith M Wesolowski * Submit the command 680*80c94ecdSKeith M Wesolowski * Poll for its completion 681*80c94ecdSKeith M Wesolowski * If polling is not successful, something is wrong 682*80c94ecdSKeith M Wesolowski * with the controler 683*80c94ecdSKeith M Wesolowski * Return FAILURE (No point in continuing if h/w is 684*80c94ecdSKeith M Wesolowski * faulty !!!) 685*80c94ecdSKeith M Wesolowski */ 686*80c94ecdSKeith M Wesolowski 687*80c94ecdSKeith M Wesolowski /* PERF */ 688*80c94ecdSKeith M Wesolowski cpqary3_cmdpvtp->complete = cpqary3_synccmd_complete; 689*80c94ecdSKeith M Wesolowski /* PERF */ 690*80c94ecdSKeith M Wesolowski 691*80c94ecdSKeith M Wesolowski /* Sync Changes */ 692*80c94ecdSKeith M Wesolowski if (cpqary3_synccmd_send(ctlr, cpqary3_cmdpvtp, 90000, 693*80c94ecdSKeith M Wesolowski CPQARY3_SYNCCMD_SEND_WAITSIG) != 0) { 694*80c94ecdSKeith M Wesolowski /* Timed out */ 695*80c94ecdSKeith M Wesolowski cpqary3_synccmd_free(ctlr, cpqary3_cmdpvtp); 696*80c94ecdSKeith M Wesolowski return (CPQARY3_FAILURE); 697*80c94ecdSKeith M Wesolowski } 698*80c94ecdSKeith M Wesolowski if ((cpqary3_cmdpvtp-> 699*80c94ecdSKeith M Wesolowski cmdlist_memaddr->Header.Tag.drvinfo_n_err == 700*80c94ecdSKeith M Wesolowski CPQARY3_SYNCCMD_FAILURE) && 701*80c94ecdSKeith M Wesolowski (cpqary3_cmdpvtp->errorinfop->CommandStatus != 2)) { 702*80c94ecdSKeith M Wesolowski DTRACE_PROBE1(id_logdrv_fail, 703*80c94ecdSKeith M Wesolowski ErrorInfo_t *, cpqary3_cmdpvtp->errorinfop); 704*80c94ecdSKeith M Wesolowski cpqary3_synccmd_free(ctlr, cpqary3_cmdpvtp); 705*80c94ecdSKeith M Wesolowski return (CPQARY3_FAILURE); 706*80c94ecdSKeith M Wesolowski } 707*80c94ecdSKeith M Wesolowski /* Sync Changes */ 708*80c94ecdSKeith M Wesolowski 709*80c94ecdSKeith M Wesolowski ctlr->cpqary3_tgtp[i]->properties.drive.heads = 710*80c94ecdSKeith M Wesolowski idlogdrive->heads; 711*80c94ecdSKeith M Wesolowski ctlr->cpqary3_tgtp[i]->properties.drive.sectors = 712*80c94ecdSKeith M Wesolowski idlogdrive->sectors; 713*80c94ecdSKeith M Wesolowski 714*80c94ecdSKeith M Wesolowski DTRACE_PROBE2(tgt_geometry_detect, 715*80c94ecdSKeith M Wesolowski int, i, IdLogDrive *, idlogdrive); 716*80c94ecdSKeith M Wesolowski } 717*80c94ecdSKeith M Wesolowski } else { 718*80c94ecdSKeith M Wesolowski 719*80c94ecdSKeith M Wesolowski /* 720*80c94ecdSKeith M Wesolowski * Fix for QXCR1000446657: Logical drives are re numbered 721*80c94ecdSKeith M Wesolowski * after deleting a Logical drive. 722*80c94ecdSKeith M Wesolowski * introduced, new variable ld_count, which gets 723*80c94ecdSKeith M Wesolowski * incremented when the Target ID is found. 724*80c94ecdSKeith M Wesolowski * And for i=controller's SCSI ID and LDs with holes are found, 725*80c94ecdSKeith M Wesolowski * we continue talking to 726*80c94ecdSKeith M Wesolowski * the next logical drive in the per-target structure 727*80c94ecdSKeith M Wesolowski */ 728*80c94ecdSKeith M Wesolowski 729*80c94ecdSKeith M Wesolowski for (i = 0; ld_count < ctlr->num_of_targets; i++) { 730*80c94ecdSKeith M Wesolowski if (i == CTLR_SCSI_ID || 731*80c94ecdSKeith M Wesolowski ctlr->cpqary3_tgtp[i] == NULL) 732*80c94ecdSKeith M Wesolowski /* Go to the Next logical target */ 733*80c94ecdSKeith M Wesolowski continue; 734*80c94ecdSKeith M Wesolowski bzero(idlogdrive, sizeof (IdLogDrive)); 735*80c94ecdSKeith M Wesolowski cmdlistp->Request.CDB[1] = 736*80c94ecdSKeith M Wesolowski ctlr->cpqary3_tgtp[i]->logical_id; 737*80c94ecdSKeith M Wesolowski /* Always zero */ 738*80c94ecdSKeith M Wesolowski cmdlistp->Header.LUN.PhysDev.TargetId = 0; 739*80c94ecdSKeith M Wesolowski /* 740*80c94ecdSKeith M Wesolowski * Logical volume Id numbering scheme is as follows 741*80c94ecdSKeith M Wesolowski * 0x00000, 0x00001, ... - for Direct Attached 742*80c94ecdSKeith M Wesolowski * 0x10000, 0x10001, ... - If 1st Port of HBA is 743*80c94ecdSKeith M Wesolowski * connected to MSA20 / MSA500 744*80c94ecdSKeith M Wesolowski * 0x20000, 0x20001, ... - If 2nd Port of HBA is 745*80c94ecdSKeith M Wesolowski * connected to MSA20 / MSA500 746*80c94ecdSKeith M Wesolowski */ 747*80c94ecdSKeith M Wesolowski cmdlistp->Header.LUN.PhysDev.Bus = 748*80c94ecdSKeith M Wesolowski (ctlr->cpqary3_tgtp[i]->logical_id) >> 16; 749*80c94ecdSKeith M Wesolowski cmdlistp->Header.LUN.PhysDev.Mode = 750*80c94ecdSKeith M Wesolowski (cmdlistp->Header.LUN.PhysDev.Bus > 0) ? 751*80c94ecdSKeith M Wesolowski MASK_PERIPHERIAL_DEV_ADDR : PERIPHERIAL_DEV_ADDR; 752*80c94ecdSKeith M Wesolowski /* PERF */ 753*80c94ecdSKeith M Wesolowski cpqary3_cmdpvtp->complete = cpqary3_synccmd_complete; 754*80c94ecdSKeith M Wesolowski /* PERF */ 755*80c94ecdSKeith M Wesolowski 756*80c94ecdSKeith M Wesolowski /* 757*80c94ecdSKeith M Wesolowski * Submit the command 758*80c94ecdSKeith M Wesolowski * Poll for its completion 759*80c94ecdSKeith M Wesolowski * If polling is not successful, something is wrong 760*80c94ecdSKeith M Wesolowski * with the controler 761*80c94ecdSKeith M Wesolowski * Return FAILURE (No point in continuing if h/w is 762*80c94ecdSKeith M Wesolowski * faulty !!!) 763*80c94ecdSKeith M Wesolowski */ 764*80c94ecdSKeith M Wesolowski 765*80c94ecdSKeith M Wesolowski /* Sync Changes */ 766*80c94ecdSKeith M Wesolowski if (cpqary3_synccmd_send(ctlr, cpqary3_cmdpvtp, 90000, 767*80c94ecdSKeith M Wesolowski CPQARY3_SYNCCMD_SEND_WAITSIG) != 0) { 768*80c94ecdSKeith M Wesolowski /* Timed out */ 769*80c94ecdSKeith M Wesolowski cpqary3_synccmd_free(ctlr, cpqary3_cmdpvtp); 770*80c94ecdSKeith M Wesolowski return (CPQARY3_FAILURE); 771*80c94ecdSKeith M Wesolowski } 772*80c94ecdSKeith M Wesolowski if ((cpqary3_cmdpvtp-> 773*80c94ecdSKeith M Wesolowski cmdlist_memaddr->Header.Tag.drvinfo_n_err == 774*80c94ecdSKeith M Wesolowski CPQARY3_SYNCCMD_FAILURE) && 775*80c94ecdSKeith M Wesolowski (cpqary3_cmdpvtp->errorinfop->CommandStatus != 2)) { 776*80c94ecdSKeith M Wesolowski DTRACE_PROBE1(id_logdrv_fail, 777*80c94ecdSKeith M Wesolowski ErrorInfo_t *, cpqary3_cmdpvtp->errorinfop); 778*80c94ecdSKeith M Wesolowski cpqary3_synccmd_free(ctlr, cpqary3_cmdpvtp); 779*80c94ecdSKeith M Wesolowski return (CPQARY3_FAILURE); 780*80c94ecdSKeith M Wesolowski } 781*80c94ecdSKeith M Wesolowski /* Sync Changes */ 782*80c94ecdSKeith M Wesolowski 783*80c94ecdSKeith M Wesolowski ctlr->cpqary3_tgtp[i]->properties.drive.heads = 784*80c94ecdSKeith M Wesolowski idlogdrive->heads; 785*80c94ecdSKeith M Wesolowski ctlr->cpqary3_tgtp[i]->properties.drive.sectors = 786*80c94ecdSKeith M Wesolowski idlogdrive->sectors; 787*80c94ecdSKeith M Wesolowski 788*80c94ecdSKeith M Wesolowski DTRACE_PROBE2(tgt_geometry_detect, 789*80c94ecdSKeith M Wesolowski int, i, IdLogDrive *, idlogdrive); 790*80c94ecdSKeith M Wesolowski 791*80c94ecdSKeith M Wesolowski ld_count++; 792*80c94ecdSKeith M Wesolowski } 793*80c94ecdSKeith M Wesolowski } 794*80c94ecdSKeith M Wesolowski 795*80c94ecdSKeith M Wesolowski /* Sync Changes */ 796*80c94ecdSKeith M Wesolowski cpqary3_synccmd_free(ctlr, cpqary3_cmdpvtp); 797*80c94ecdSKeith M Wesolowski /* Sync Changes */ 798*80c94ecdSKeith M Wesolowski 799*80c94ecdSKeith M Wesolowski return (CPQARY3_SUCCESS); 800*80c94ecdSKeith M Wesolowski } 801