diff options
author | Joshua M. Clulow <jmc@joyent.com> | 2016-02-29 12:39:09 +0000 |
---|---|---|
committer | Joshua M. Clulow <jmc@joyent.com> | 2016-07-06 16:25:17 +0000 |
commit | c3b58fd859e47742b9e811e92a621698849fcd0b (patch) | |
tree | 13c9ba4fbfe6e4c02357d66b801ab110fc4252e7 | |
parent | eb1a2ded8c853329cb42a322e537fbef32fd14af (diff) | |
download | illumos-joyent-c3b58fd859e47742b9e811e92a621698849fcd0b.tar.gz |
XXX some refactoring of attach, mappings, etc
-rw-r--r-- | usr/src/uts/common/Makefile.files | 2 | ||||
-rw-r--r-- | usr/src/uts/common/io/cpqary3/cpqary3.c | 809 | ||||
-rw-r--r-- | usr/src/uts/common/io/cpqary3/cpqary3.h | 117 | ||||
-rw-r--r-- | usr/src/uts/common/io/cpqary3/cpqary3_ciss.h | 123 | ||||
-rw-r--r-- | usr/src/uts/common/io/cpqary3/cpqary3_device.c | 256 | ||||
-rw-r--r-- | usr/src/uts/common/io/cpqary3/cpqary3_interrupts.c | 102 | ||||
-rw-r--r-- | usr/src/uts/common/io/cpqary3/cpqary3_ioctl.c | 170 | ||||
-rw-r--r-- | usr/src/uts/common/io/cpqary3/cpqary3_ioctl.h | 29 | ||||
-rw-r--r-- | usr/src/uts/common/io/cpqary3/cpqary3_isr.c | 77 | ||||
-rw-r--r-- | usr/src/uts/common/io/cpqary3/cpqary3_scsi.c | 6 | ||||
-rw-r--r-- | usr/src/uts/common/io/cpqary3/cpqary3_talk2ctlr.c | 248 | ||||
-rw-r--r-- | usr/src/uts/common/io/cpqary3/cpqary3_transport.c | 23 | ||||
-rw-r--r-- | usr/src/uts/common/io/cpqary3/cpqary3_util.c | 154 |
13 files changed, 795 insertions, 1321 deletions
diff --git a/usr/src/uts/common/Makefile.files b/usr/src/uts/common/Makefile.files index 6556ae4119..8139f2c022 100644 --- a/usr/src/uts/common/Makefile.files +++ b/usr/src/uts/common/Makefile.files @@ -2156,7 +2156,7 @@ DR_SAS_OBJS = dr_sas.o CPQARY3_OBJS = cpqary3.o cpqary3_talk2ctlr.o \ cpqary3_isr.o cpqary3_transport.o cpqary3_mem.o \ cpqary3_scsi.o cpqary3_util.o \ - cpqary3_bd.o + cpqary3_bd.o cpqary3_device.o cpqary3_interrupts.o # # ISCSI_INITIATOR module diff --git a/usr/src/uts/common/io/cpqary3/cpqary3.c b/usr/src/uts/common/io/cpqary3/cpqary3.c index 5482e5969e..9a587206d1 100644 --- a/usr/src/uts/common/io/cpqary3/cpqary3.c +++ b/usr/src/uts/common/io/cpqary3/cpqary3.c @@ -28,17 +28,9 @@ int cpqary3_ioctl(dev_t, int, intptr_t, int, cred_t *, int *); * Local Functions Definitions */ -static void cpqary3_cleanup(cpqary3_t *, uint32_t); +static void cpqary3_cleanup(cpqary3_t *); static uint8_t cpqary3_update_ctlrdetails(cpqary3_t *, uint32_t *); -int8_t cpqary3_detect_target_geometry(cpqary3_t *); - -/* - * External Variable Definitions - */ - -#if 0 -extern cpqary3_driver_info_t gdriver_info; -#endif +static int cpqary3_command_comparator(const void *, const void *); /* * Global Variables Definitions @@ -47,8 +39,6 @@ extern cpqary3_driver_info_t gdriver_info; static char cpqary3_brief[] = "HP Smart Array Driver"; void *cpqary3_state; -/* HPQaculi Changes */ - /* * HBA minor number schema * @@ -72,8 +62,6 @@ void *cpqary3_state; #define CPQARY3_INST2x(_i, _x) (((_i) << INST_MINOR_SHIFT) | (_x)) #define CPQARY3_INST2CPQARY3(_i) CPQARY3_INST2x(_i, CPQARY3_MINOR) -/* HPQacucli Changes */ - /* * The Driver DMA Limit structure. * Data used for SMART Integrated Array Controller shall be used. @@ -103,7 +91,6 @@ ddi_dma_attr_t cpqary3_dma_attr = { /* * The Device Access Attribute Structure. */ - ddi_device_acc_attr_t cpqary3_dev_attributes = { DDI_DEVICE_ATTR_V0, DDI_STRUCTURE_LE_ACC, @@ -113,7 +100,6 @@ ddi_device_acc_attr_t cpqary3_dev_attributes = { /* * Character-Block Operations Structure */ - static struct cb_ops cpqary3_cb_ops = { /* HPQacucli Changes */ scsi_hba_open, @@ -140,7 +126,6 @@ static struct cb_ops cpqary3_cb_ops = { /* * Device Operations Structure */ - static struct dev_ops cpqary3_dev_ops = { DEVO_REV, /* Driver Build Version */ 0, /* Driver reference count */ @@ -158,7 +143,6 @@ static struct dev_ops cpqary3_dev_ops = { /* * Linkage structures */ - static struct modldrv cpqary3_modldrv = { &mod_driverops, /* Module Type - driver */ cpqary3_brief, /* Driver Desc */ @@ -172,16 +156,6 @@ static struct modlinkage cpqary3_modlinkage = { }; -/* - * Function : _init - * Description : This routine allocates soft state resources for the - * driver, registers the HBA with the system and - * adds the driver(loadable module). - * Called By : Kernel - * Parameters : None - * Return Values: 0 / Non-Zero - * [as returned by the mod_install OS function] - */ int _init() { @@ -209,15 +183,7 @@ fail: return (r); } -/* - * Function : _fini - * Description : This routine removes the loadable module, cancels the - * HBA registration and deallocates soft state resources. - * Called By : Kernel - * Parameters : None - * Return Values: 0 - Success / Non-Zero - Failure - * [as returned by the mod_remove(OS provided) function] - */ + int _fini() { @@ -237,14 +203,7 @@ _fini() return (retvalue); } -/* - * Function : _info - * Description : This routine returns information about the driver. - * Called By : Kernel - * Parameters : None - * Return Values: 0 / Non-Zero - * [as returned by mod_info(OS provided) function] - */ + int _info(struct modinfo *modinfop) { @@ -255,97 +214,88 @@ _info(struct modinfo *modinfop) } -/* - * Function : cpqary3_attach - * Description : This routine initializes the driver specific soft state - * structure, initializes the HBA, interrupt handlers, - * memory pool, timeout handler, various mutex, creates the - * minor node. - * Called By : kernel - * Parameters : dip, command for attach - * Return Values: DDI_SUCCESS / DDI_FAILURE - * [Success on overall initialization & configuration - * being successful. Failure if any of the initialization - * or any driver-specific mandatory configuration fails] - */ int cpqary3_attach(dev_info_t *dip, ddi_attach_cmd_t attach_cmd) { int8_t minor_node_name[14]; uint32_t instance; uint32_t retvalue; - uint32_t cleanstatus = 0; cpqary3_t *cpq; /* per-controller */ ddi_dma_attr_t tmp_dma_attr; uint_t (*hw_isr)(caddr_t); + uint_t (*sw_isr)(caddr_t); - if (attach_cmd != DDI_ATTACH) + if (attach_cmd != DDI_ATTACH) { return (DDI_FAILURE); + } - /* Get the Instance of the Device */ + /* + * Allocate the per-controller soft state object and get + * a pointer to it. + */ instance = ddi_get_instance(dip); - - /* Allocate the per-device-instance soft state structure */ if (ddi_soft_state_zalloc(cpqary3_state, instance) != 0) { dev_err(dip, CE_WARN, "could not allocate soft state"); + return (DDI_FAILURE); } - cleanstatus |= CPQARY3_SOFTSTATE_ALLOC_DONE; - - /* Per Controller Pointer */ if ((cpq = ddi_get_soft_state(cpqary3_state, instance)) == NULL) { dev_err(dip, CE_WARN, "could not get soft state"); - cpqary3_cleanup(cpq, cleanstatus); + ddi_soft_state_free(cpqary3_state, instance); return (DDI_FAILURE); } - /* Maintain a record in per-ctlr structure */ + /* + * Initialise per-controller state object. + */ cpq->dip = dip; - cpq->instance = instance; - cpq->cpq_next_tag = 0x54321; - - /* Get the User Configuration information from Driver's conf File */ - cpqary3_read_conf_file(dip, cpq); + cpq->cpq_instance = instance; + cpq->cpq_next_tag = CPQARY3_MIN_TAG_NUMBER; + list_create(&cpq->cpq_commands, sizeof (cpqary3_command_t), + offsetof(cpqary3_command_t, cpcm_link)); + avl_create(&cpq->cpq_inflight, cpqary3_command_comparator, + sizeof (cpqary3_command_t), offsetof(cpqary3_command_t, + cpcm_node)); + cv_init(&cpq->cv_immediate_wait, NULL, CV_DRIVER, NULL); + cv_init(&cpq->cv_noe_wait, NULL, CV_DRIVER, NULL); + cv_init(&cpq->cv_flushcache_wait, NULL, CV_DRIVER, NULL); + cv_init(&cpq->cv_abort_wait, NULL, CV_DRIVER, NULL); + cv_init(&cpq->cv_ioctl_wait, NULL, CV_DRIVER, NULL); + cpq->cpqary3_tgtp[CTLR_SCSI_ID] = kmem_zalloc(sizeof (cpqary3_tgt_t), + KM_SLEEP); + cpq->cpqary3_tgtp[CTLR_SCSI_ID]->type = CPQARY3_TARGET_CTLR; + + cpq->cpq_init_level |= CPQARY3_INITLEVEL_BASIC; - /* Get and Map the HW Configuration */ - if (cpqary3_update_ctlrdetails(cpq, &cleanstatus) != CPQARY3_SUCCESS) { - dev_err(dip, CE_WARN, "cpqary3_update_ctlrdetails failed"); - cpqary3_cleanup(cpq, cleanstatus); - return (DDI_FAILURE); - } - - /* Get the Cookie for hardware Interrupt Handler */ - if (ddi_get_iblock_cookie(dip, 0, &cpq->hw_iblock_cookie) != - DDI_SUCCESS) { - dev_err(dip, CE_WARN, "ddi_get_iblock_cookie (hw) failed"); - cpqary3_cleanup(cpq, cleanstatus); + /* + * Perform basic device setup, including identifying the board, mapping + * the I2O registers and the Configuration Table. + */ + if (cpqary3_device_setup(cpq) != DDI_SUCCESS) { + dev_err(dip, CE_WARN, "device setup failed"); + cpqary3_cleanup(cpq); return (DDI_FAILURE); } - /* Initialize Per Controller Mutex */ - mutex_init(&cpq->hw_mutex, NULL, MUTEX_DRIVER, - (void *)cpq->hw_iblock_cookie); - cleanstatus |= CPQARY3_MUTEX_INIT_DONE; - - /* Get the Cookie for Soft(low level) Interrupt Handler */ - if (ddi_get_soft_iblock_cookie(dip, DDI_SOFTINT_HIGH, - &cpq->sw_iblock_cookie) != DDI_SUCCESS) { - dev_err(dip, CE_WARN, "ddi_get_iblock_cookie (sw) failed"); - cpqary3_cleanup(cpq, cleanstatus); + /* + * Select a Transport Method (e.g. Simple or Performant) and update + * the Configuration Table. This function also waits for the + * controller to be come ready. + */ + if (cpqary3_ctlr_init(cpq) != DDI_SUCCESS) { + dev_err(dip, CE_WARN, "controller initialisation failed"); + cpqary3_cleanup(cpq); return (DDI_FAILURE); } - /* Initialize the s/w Mutex */ - mutex_init(&cpq->sw_mutex, NULL, MUTEX_DRIVER, - (void *)cpq->sw_iblock_cookie); - cleanstatus |= CPQARY3_SW_MUTEX_INIT_DONE; - - /* Initialize per Controller private details */ - if (cpqary3_init_ctlr_resource(cpq) != CPQARY3_SUCCESS) { - dev_err(dip, CE_WARN, "cpqary3_init_ctlr_resource failed"); - cpqary3_cleanup(cpq, cleanstatus); + /* + * Now that we have selected a Transport Method, we can configure + * the appropriate interrupt handlers. + */ + if (cpqary3_interrupts_setup(cpq) != DDI_SUCCESS) { + dev_err(dip, CE_WARN, "interrupt handler setup failed"); + cpqary3_cleanup(cpq); return (DDI_FAILURE); } - cleanstatus |= CPQARY3_CTLR_CONFIG_DONE; /* * Allocate HBA transport structure @@ -353,10 +303,10 @@ cpqary3_attach(dev_info_t *dip, ddi_attach_cmd_t attach_cmd) if ((cpq->hba_tran = scsi_hba_tran_alloc(dip, SCSI_HBA_CANSLEEP)) == NULL) { dev_err(dip, CE_WARN, "scsi_hba_tran_alloc failed"); - cpqary3_cleanup(cpq, cleanstatus); + cpqary3_cleanup(cpq); return (DDI_FAILURE); } - cleanstatus |= CPQARY3_HBA_TRAN_ALLOC_DONE; + cpq->cpq_init_level |= CPQARY3_INITLEVEL_HBA_ALLOC; /* * Set private field for the HBA tran structure. @@ -366,7 +316,7 @@ cpqary3_attach(dev_info_t *dip, ddi_attach_cmd_t attach_cmd) cpqary3_init_hbatran(cpq); tmp_dma_attr = cpqary3_dma_attr; - tmp_dma_attr.dma_attr_sgllen = cpq->sg_cnt; + tmp_dma_attr.dma_attr_sgllen = cpq->cpq_sg_cnt; /* * Register the DMA attributes and the transport vectors @@ -375,10 +325,10 @@ cpqary3_attach(dev_info_t *dip, ddi_attach_cmd_t attach_cmd) if (scsi_hba_attach_setup(dip, &tmp_dma_attr, cpq->hba_tran, SCSI_HBA_TRAN_CLONE) == DDI_FAILURE) { dev_err(dip, CE_WARN, "scsi_hba_attach_setup failed"); - cpqary3_cleanup(cpq, cleanstatus); + cpqary3_cleanup(cpq); return (DDI_FAILURE); } - cleanstatus |= CPQARY3_HBA_TRAN_ATTACH_DONE; + cpq->cpq_init_level |= CPQARY3_INITLEVEL_HBA_ATTACH; /* * Create a minor node for Ioctl interface. @@ -387,58 +337,20 @@ cpqary3_attach(dev_info_t *dip, ddi_attach_cmd_t attach_cmd) * for e.g.: for 0th instance : cpqary3,0 * for 1st instance : cpqary3,1 */ - (void) sprintf(minor_node_name, "cpqary3,%d", instance); - /* HPQacucli Changes */ if (ddi_create_minor_node(dip, minor_node_name, S_IFCHR, - CPQARY3_INST2CPQARY3(instance), DDI_NT_SCSI_NEXUS, 0) == + CPQARY3_INST2CPQARY3(instance), DDI_NT_SCSI_NEXUS, 0) != DDI_SUCCESS) { - /* HPQacucli Changes */ - cleanstatus |= CPQARY3_CREATE_MINOR_NODE; - } else { cmn_err(CE_NOTE, "CPQary3 : Failed to create minor node"); - cpqary3_cleanup(cpq, cleanstatus); - return (DDI_FAILURE); - } - - /* Register Software Interrupt Handler */ - if (ddi_add_softintr(dip, DDI_SOFTINT_HIGH, - &cpq->cpqary3_softintr_id, &cpq->sw_iblock_cookie, NULL, - cpqary3_sw_isr, (caddr_t)cpq) != DDI_SUCCESS) { - dev_err(dip, CE_WARN, "ddi_add_softintr failed"); - cpqary3_cleanup(cpq, cleanstatus); + cpqary3_cleanup(cpq); return (DDI_FAILURE); } - cleanstatus |= CPQARY3_SW_INTR_HDLR_SET; - - /* - * Select the correct hardware interrupt service routine for the - * Transport Method we have configured: - */ - switch (cpq->cpq_ctlr_mode) { - case CPQARY3_CTLR_MODE_SIMPLE: - hw_isr = cpqary3_isr_hw_simple; - break; - case CPQARY3_CTLR_MODE_PERFORMANT: - hw_isr = cpqary3_isr_hw_performant; - break; - default: - panic("unknown controller mode"); - } - - /* Register Interrupt Handler */ - if (ddi_add_intr(dip, 0, &cpq->hw_iblock_cookie, NULL, hw_isr, - (caddr_t)cpq) != DDI_SUCCESS) { - dev_err(dip, CE_WARN, "ddi_add_intr (hw) failed"); - cpqary3_cleanup(cpq, cleanstatus); - return (DDI_FAILURE); - } - cleanstatus |= CPQARY3_INTR_HDLR_SET; + cpq->cpq_init_level |= CPQARY3_INITLEVEL_MINOR_NODE; /* Enable the Controller Interrupt */ cpqary3_intr_onoff(cpq, CPQARY3_INTR_ENABLE); - if (cpq->host_support & 0x4) { + if (cpq->cpq_host_support & 0x4) { cpqary3_lockup_intr_onoff(cpq, CPQARY3_LOCKUP_INTR_ENABLE); } @@ -447,13 +359,7 @@ cpqary3_attach(dev_info_t *dip, ddi_attach_cmd_t attach_cmd) */ cpq->cpq_periodic = ddi_periodic_add(cpqary3_periodic, cpq, 15 * NANOSEC, DDI_IPL_0); - cleanstatus |= CPQARY3_TICK_TMOUT_REGD; - - /* - * We have come with hmaeventd - which logs the storage events on - * console as well as in IML. So we are commenting the NOE support in - * the driver - */ + cpq->cpq_init_level |= CPQARY3_INITLEVEL_PERIODIC; /* * XXX OK, maybe later... @@ -477,30 +383,10 @@ cpqary3_attach(dev_info_t *dip, ddi_attach_cmd_t attach_cmd) /* Report that an Instance of the Driver is Attached Successfully */ ddi_report_dev(dip); - /* - * Now update the num_ctlr - * This is required for the agents - */ - -#if 0 - gdriver_info.num_ctlr++; -#endif - - dev_err(dip, CE_WARN, "attach complete"); return (DDI_SUCCESS); } -/* - * Function : cpqary3_detach - * Description : This routine removes the state associated with a - * given instance of a device node prior to the - * removal of that instance from the system - * Called By : kernel - * Parameters : dip, command for detach - * Return Values: DDI_SUCCESS / DDI_FAILURE - * [failure ONLY if the command sent with this function - * as a paramter is not DETACH] - */ + int cpqary3_detach(dev_info_t *dip, ddi_detach_cmd_t detach_cmd) { @@ -509,8 +395,9 @@ cpqary3_detach(dev_info_t *dip, ddi_detach_cmd_t detach_cmd) /* Return failure, If Command is not DDI_DETACH */ - if (DDI_DETACH != detach_cmd) + if (DDI_DETACH != detach_cmd) { return (DDI_FAILURE); + } /* * Get scsi_hba_tran structure. @@ -526,101 +413,54 @@ cpqary3_detach(dev_info_t *dip, ddi_detach_cmd_t detach_cmd) /* Undo cpqary3_attach */ - cpqary3_cleanup(cpqary3p, CPQARY3_CLEAN_ALL); + cpqary3_cleanup(cpqary3p); return (DDI_SUCCESS); } -/* - * Function : cpary3_ioctl - * Description : This routine services ioctl requests. - * Called By : kernel - * Parameters : Too many to list. Please look below !!! - * Return Values: 0 / EINVAL / EFAULT / - * [0 on normal successful completion of the ioctl - * request] - */ + int cpqary3_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp, - int *retvaluep) + int *rval) { - - minor_t cpqary3_minor_num; - cpqary3_t *cpqary3p; - int instance; + cpqary3_t *cpq; + minor_t cpqary3_minor_num; + int instance; + int status; /* - * Get the soft state structure for this instance - * Return ENODEV if the structure does not exist. + * XXX */ +#if 0 + if (secpolicy_sys_config(credp, B_FALSE) != 0) { + return (EPERM); + } +#endif /* - * minor() call used in cpqary3_ioctl() returns minor number of the - * device which are in the - * range 0-255. if the minor number of the device is greater than 255, - * data will get truncated. so we are now using getminor(), - * instead of minor() + * Fetch the soft state object for this instance. */ - - if (EINVAL == (cpqary3_minor_num = getminor(dev))) { - *retvaluep = ENODEV; - return (*retvaluep); - } - - /* HPQacucli Changes */ - - /* get instance */ - instance = MINOR2INST(cpqary3_minor_num); - - cpqary3p = (cpqary3_t *)ddi_get_soft_state(cpqary3_state, instance); - - /* HPQacucli Changes */ - - if (!cpqary3p) { - *retvaluep = ENODEV; - return (*retvaluep); + cpq = ddi_get_soft_state(cpqary3_state, MINOR2INST(getminor(dev))); + if (cpq == NULL) { + return (ENODEV); } - /* HPQacucli Changes */ - - /* check which interface is being requested */ - if (CPQARY3_MINOR2INTERFACE(cpqary3_minor_num) != CPQARY3_MINOR) { - /* defer to SCSA */ - return (scsi_hba_ioctl(dev, cmd, arg, mode, credp, retvaluep)); - } - - /* HPQacucli Changes */ - switch (cmd) { -#if 0 - case CPQARY3_IOCTL_DRIVER_INFO: - *retvaluep = - cpqary3_ioctl_driver_info(arg, mode); - break; - - case CPQARY3_IOCTL_CTLR_INFO: - *retvaluep = - cpqary3_ioctl_ctlr_info(arg, cpqary3p, mode); - break; - - case CPQARY3_IOCTL_BMIC_PASS: - *retvaluep = - cpqary3_ioctl_bmic_pass(arg, cpqary3p, mode); - break; - - case CPQARY3_IOCTL_SCSI_PASS: - *retvaluep = - cpqary3_ioctl_scsi_pass(arg, cpqary3p, mode); - break; + case CPQARY3_IOCTL_BMIC_PASS: + status = *rval = cpqary3_ioctl_bmic_pass(arg, cpq, mode); + break; -#endif - default: - *retvaluep = EINVAL; - break; + case CPQARY3_IOCTL_SCSI_PASS: + status = *rval = cpqary3_ioctl_scsi_pass(arg, cpq, mode); + break; + + default: + status = scsi_hba_ioctl(dev, cmd, arg, mode, credp, rval); + break; } - return (*retvaluep); + return (status); } @@ -632,7 +472,7 @@ cpqary3_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp, * Return Values: None */ static void -cpqary3_cleanup(cpqary3_t *cpqary3p, uint32_t status) +cpqary3_cleanup(cpqary3_t *cpqary3p) { int8_t node_name[10]; clock_t cpqary3_lbolt; @@ -672,41 +512,31 @@ cpqary3_cleanup(cpqary3_t *cpqary3p, uint32_t status) } #endif - /* - * Detach the device - * Free / Release / Destroy the following entities/resources: - * transport layer - * h/w & s/w interrupt handlers - * all mutex - * timeout handler - * target structure - * minor node - * soft state - * any register/memory mapping - */ + cpqary3_interrupts_teardown(cpqary3p); - if ((status & CPQARY3_TICK_TMOUT_REGD) && cpqary3p->cpq_periodic) { + if (cpqary3p->cpq_init_level & CPQARY3_INITLEVEL_PERIODIC) { ddi_periodic_delete(cpqary3p->cpq_periodic); + cpqary3p->cpq_init_level &= ~CPQARY3_INITLEVEL_PERIODIC; } - if (status & CPQARY3_INTR_HDLR_SET) - ddi_remove_intr(cpqary3p->dip, 0, cpqary3p->hw_iblock_cookie); - - if (status & CPQARY3_SW_INTR_HDLR_SET) - ddi_remove_softintr(cpqary3p->cpqary3_softintr_id); - - if (status & CPQARY3_CREATE_MINOR_NODE) { - (void) sprintf(node_name, "cpqary3%d", cpqary3p->instance); + if (cpqary3p->cpq_init_level & CPQARY3_INITLEVEL_MINOR_NODE) { + (void) sprintf(node_name, "cpqary3%d", + ddi_get_instance(cpqary3p->dip)); ddi_remove_minor_node(cpqary3p->dip, node_name); + cpqary3p->cpq_init_level &= ~CPQARY3_INITLEVEL_MINOR_NODE; } - if (status & CPQARY3_HBA_TRAN_ATTACH_DONE) + if (cpqary3p->cpq_init_level & CPQARY3_INITLEVEL_HBA_ATTACH) { (void) scsi_hba_detach(cpqary3p->dip); + cpqary3p->cpq_init_level &= ~CPQARY3_INITLEVEL_HBA_ATTACH; + } - if (status & CPQARY3_HBA_TRAN_ALLOC_DONE) + if (cpqary3p->cpq_init_level & CPQARY3_INITLEVEL_HBA_ALLOC) { scsi_hba_tran_free(cpqary3p->hba_tran); + cpqary3p->cpq_init_level &= ~CPQARY3_INITLEVEL_HBA_ALLOC; + } - if (status & CPQARY3_CTLR_CONFIG_DONE) { + if (cpqary3p->cpq_init_level & CPQARY3_INITLEVEL_BASIC) { mutex_enter(&cpqary3p->hw_mutex); cv_destroy(&cpqary3p->cv_abort_wait); @@ -720,418 +550,35 @@ cpqary3_cleanup(cpqary3_t *cpqary3p, uint32_t status) continue; kmem_free(cpqary3p->cpqary3_tgtp[targ], sizeof (cpqary3_tgt_t)); + cpqary3p->cpqary3_tgtp[targ] = NULL; } mutex_exit(&cpqary3p->hw_mutex); -#if 0 - cpqary3_memfini(cpqary3p, CPQARY3_MEMLIST_DONE | - CPQARY3_PHYCTGS_DONE | CPQARY3_CMDMEM_DONE); -#endif + /* + * XXX avl_destroy, list_destroy, etc + */ + cpqary3p->cpq_init_level &= ~CPQARY3_INITLEVEL_BASIC; } - if (status & CPQARY3_SW_MUTEX_INIT_DONE) - mutex_destroy(&cpqary3p->sw_mutex); - - if (status & CPQARY3_MUTEX_INIT_DONE) - mutex_destroy(&cpqary3p->hw_mutex); + cpqary3_device_teardown(cpqary3p); - /* - * If this flag is set, free all mapped registers - */ - if (status & CPQARY3_MEM_MAPPED) { - if (cpqary3p->idr_handle) - ddi_regs_map_free(&cpqary3p->idr_handle); - if (cpqary3p->isr_handle) - ddi_regs_map_free(&cpqary3p->isr_handle); - if (cpqary3p->imr_handle) - ddi_regs_map_free(&cpqary3p->imr_handle); - if (cpqary3p->ipq_handle) - ddi_regs_map_free(&cpqary3p->ipq_handle); - if (cpqary3p->opq_handle) - ddi_regs_map_free(&cpqary3p->opq_handle); - if (cpqary3p->ct_handle) - ddi_regs_map_free(&cpqary3p->ct_handle); - } + VERIFY0(cpqary3p->cpq_init_level); - if (status & CPQARY3_SOFTSTATE_ALLOC_DONE) { - ddi_soft_state_free(cpqary3_state, - ddi_get_instance(cpqary3p->dip)); - } + ddi_soft_state_free(cpqary3_state, ddi_get_instance(cpqary3p->dip)); } -/* - * Function : cpqary3_update_ctlrdetails - * Description : Performs Sanity check of the hw, Updates PCI Config - * Information, Verifies the supported board-id and - * Sets up a mapping for the Primary I2O Memory BAR and - * the Primary DRAM 1 BAR to access Host Interface - * registers and the Transport Configuration table. - * Called By : cpqary3_attach() - * Parameters : per-controller, bitmap (used for cleaning operations) - * Return Values: SUCCESS / FAILURE - * [Success / failure depending upon the outcome of all - * checks and mapping. If any of them fail, a failure is - * sent back] - */ -static uint8_t -cpqary3_update_ctlrdetails(cpqary3_t *cpqary3p, uint32_t *cleanstatus) +static int +cpqary3_command_comparator(const void *lp, const void *rp) { - int8_t retvalue; - uint8_t mem_bar0_set = 0; - uint8_t mem_64_bar0_set = 0; - uint8_t mem_bar1_set = 0; - uint8_t mem_64_bar1_set = 0; - int32_t reglen; - uint32_t *regp; - uint32_t mem_bar0 = 0; - uint32_t mem_64_bar0; - uint32_t mem_bar1 = 0; - uint32_t mem_64_bar1 = 0; - uint32_t ct_mem_bar = 0; - uint32_t ct_cfgmem_val = 0; - uint32_t ct_memoff_val = 0; - uint32_t ct_cfg_bar = 0; - uint32_t ct_mem_len = 0; - offset_t map_len = 0; - uint32_t regset_index; - ddi_acc_handle_t pci_handle; - uint32_t *ct_cfg_offset; - ddi_acc_handle_t ct_cfgoff_handle; - uint32_t *ct_mem_offset; - ddi_acc_handle_t ct_memoff_handle; - - RETURN_FAILURE_IF_NULL(cpqary3p); - - /* - * Check if the bus, or part of the bus that the device is installed - * on, permits the device to become a DMA master. - * If our device is not permitted to become master, return - */ - if (ddi_slaveonly(cpqary3p->dip) == DDI_SUCCESS) - return (CPQARY3_FAILURE); - - /* - * Get the HW Configuration - * Get Bus #, Dev # and Func # for this device - * Free the memory that regp points towards after the - * ddi_getlongprop() call - */ - if (ddi_getlongprop(DDI_DEV_T_NONE, cpqary3p->dip, DDI_PROP_DONTPASS, - "reg", (caddr_t)®p, ®len) != DDI_PROP_SUCCESS) - return (CPQARY3_FAILURE); - - cpqary3p->bus = PCI_REG_BUS_G(*regp); - cpqary3p->dev = PCI_REG_DEV_G(*regp); - cpqary3p->fun = PCI_REG_FUNC_G(*regp); - - for (regset_index = 0; regset_index < reglen / 20; regset_index ++) { - if (PCI_REG_ADDR_G(*(regp + regset_index * 5)) == 0x2) { - if (!mem_bar0_set) { - mem_bar0 = regset_index; - mem_bar0_set = 1; - } else if (!mem_bar1_set) { - mem_bar1 = regset_index; - mem_bar1_set = 1; - } - } - } - - mem_64_bar0 = mem_bar0; - mem_64_bar1 = mem_bar1; - - for (regset_index = 0; regset_index < reglen / 20; regset_index ++) { - if (PCI_REG_ADDR_G(*(regp + regset_index * 5)) == 0x3) { - if (!mem_64_bar0_set) { - mem_64_bar0 = regset_index; - mem_64_bar0_set = 1; - } else if (!mem_64_bar1_set) { - mem_64_bar1 = regset_index; - mem_64_bar1_set = 1; - } - } - } - - mem_bar0 = mem_64_bar0; - mem_bar1 = mem_64_bar1; - - kmem_free(regp, reglen); - - /* - * Setup resources to access the Local PCI Bus - * If unsuccessful, return. - * Else, read the following from the PCI space: - * Sub-System Vendor ID - * Sub-System Device ID - * Interrupt Line - * Command Register - * Free the just allocated resources. - */ - if (pci_config_setup(cpqary3p->dip, &pci_handle) != DDI_SUCCESS) - return (CPQARY3_FAILURE); - - cpqary3p->irq = pci_config_get8(pci_handle, PCI_CONF_ILINE); - cpqary3p->board_id = - (pci_config_get16(pci_handle, PCI_CONF_SUBVENID) << 16) - | pci_config_get16(pci_handle, PCI_CONF_SUBSYSID); - - pci_config_teardown(&pci_handle); - - /* - * Verify Board Id - * If unsupported boards are detected, return. - * Update name for controller for driver use. - */ - cpqary3p->bddef = cpqary3_bd_getbybid(cpqary3p->board_id); - if (cpqary3p->bddef == NULL) { - cmn_err(CE_WARN, - "CPQary3: <Bid 0x%X> Controller NOT Supported", - cpqary3p->board_id); - return (CPQARY3_FAILURE); - } - map_len = cpqary3p->bddef->bd_maplen; - (void) strcpy(cpqary3p->hba_name, cpqary3p->bddef->bd_dispname); - - dev_err(cpqary3p->dip, CE_WARN, "controller: %s", cpqary3p->hba_name); - - /* - * Set up a mapping for the following registers: - * Inbound Doorbell - * Outbound List Status - * Outbound Interrupt Mask - * Host Inbound Queue - * Host Outbound Queue - * Host Transport Configuration Table - * Mapping of the above has been done in that order. - */ - retvalue = ddi_regs_map_setup(cpqary3p->dip, - mem_bar0, /* INDEX_PCI_BASE0, */ - (caddr_t *)&cpqary3p->idr, (offset_t)I2O_INBOUND_DOORBELL, map_len, - &cpqary3_dev_attributes, &cpqary3p->idr_handle); - - if (retvalue != DDI_SUCCESS) { - if (DDI_REGS_ACC_CONFLICT == retvalue) { - cmn_err(CE_WARN, - "CPQary3 : Registers Mapping Conflict"); - } - cmn_err(CE_WARN, "CPQary3 : Inbound Doorbell " - "Register Mapping Failed"); - return (CPQARY3_FAILURE); - } + const cpqary3_command_t *l = lp; + const cpqary3_command_t *r = rp; - /* PERF */ - retvalue = ddi_regs_map_setup(cpqary3p->dip, - mem_bar0, /* INDEX_PCI_BASE0, */ - (caddr_t *)&cpqary3p->odr, (offset_t)I2O_OBDB_STATUS, map_len, - &cpqary3_dev_attributes, &cpqary3p->odr_handle); - - if (retvalue != DDI_SUCCESS) { - if (DDI_REGS_ACC_CONFLICT == retvalue) { - cmn_err(CE_WARN, - "CPQary3 : Registers Mapping Conflict"); - } - cmn_err(CE_WARN, - "CPQary3 : Outbound Doorbell Register Mapping Failed"); - return (CPQARY3_FAILURE); - } - - retvalue = ddi_regs_map_setup(cpqary3p->dip, - mem_bar0, /* INDEX_PCI_BASE0, */ - (caddr_t *)&cpqary3p->odr_cl, (offset_t)I2O_OBDB_CLEAR, map_len, - &cpqary3_dev_attributes, &cpqary3p->odr_cl_handle); - - if (retvalue != DDI_SUCCESS) { - if (DDI_REGS_ACC_CONFLICT == retvalue) { - cmn_err(CE_WARN, - "CPQary3 : Registers Mapping Conflict"); - } - cmn_err(CE_WARN, "CPQary3 : Outbound Doorbell " - "Register Clear Mapping Failed"); - return (CPQARY3_FAILURE); - } - - /* LOCKUP CODE */ - retvalue = ddi_regs_map_setup(cpqary3p->dip, - mem_bar0, /* INDEX_PCI_BASE0, */ - (caddr_t *)&cpqary3p->spr0, (offset_t)I2O_SCRATCHPAD, map_len, - &cpqary3_dev_attributes, &cpqary3p->spr0_handle); - - if (retvalue != DDI_SUCCESS) { - if (DDI_REGS_ACC_CONFLICT == retvalue) { - cmn_err(CE_WARN, - "CPQary3 : Registers Mapping Conflict"); - } - cmn_err(CE_WARN, - "CPQary3 : Scratch Pad register zero Mapping Failed"); - return (CPQARY3_FAILURE); - } - /* LOCKUP CODE */ - /* PERF */ - - *cleanstatus |= CPQARY3_MEM_MAPPED; - - retvalue = ddi_regs_map_setup(cpqary3p->dip, - mem_bar0, /* INDEX_PCI_BASE0, */ - (caddr_t *)&cpqary3p->isr, (offset_t)I2O_INT_STATUS, map_len, - &cpqary3_dev_attributes, &cpqary3p->isr_handle); - - if (retvalue != DDI_SUCCESS) { - if (retvalue == DDI_REGS_ACC_CONFLICT) { - cmn_err(CE_WARN, - "CPQary3 : Registers Mapping Conflict"); - } - cmn_err(CE_WARN, - "CPQary3 : Interrupt Status Register Mapping Failed"); - return (CPQARY3_FAILURE); - } - - retvalue = ddi_regs_map_setup(cpqary3p->dip, - mem_bar0, /* INDEX_PCI_BASE0, */ - (caddr_t *)&cpqary3p->imr, (offset_t)I2O_INT_MASK, map_len, - &cpqary3_dev_attributes, &cpqary3p->imr_handle); - - if (retvalue != DDI_SUCCESS) { - if (retvalue == DDI_REGS_ACC_CONFLICT) { - cmn_err(CE_WARN, - "CPQary3 : Registers Mapping Conflict"); - } - cmn_err(CE_WARN, - "CPQary3 : Interrupt Mask Register Mapping Failed"); - return (CPQARY3_FAILURE); - } - - retvalue = ddi_regs_map_setup(cpqary3p->dip, - mem_bar0, /* INDEX_PCI_BASE0, */ - (caddr_t *)&cpqary3p->ipq, (offset_t)I2O_IBPOST_Q, map_len, - &cpqary3_dev_attributes, &cpqary3p->ipq_handle); - - if (retvalue != DDI_SUCCESS) { - if (retvalue == DDI_REGS_ACC_CONFLICT) { - cmn_err(CE_WARN, - "CPQary3 : Registers Mapping Conflict"); - } - cmn_err(CE_WARN, - "CPQary3 : Inbound Queue Register Mapping Failed"); - return (CPQARY3_FAILURE); - } - - retvalue = ddi_regs_map_setup(cpqary3p->dip, - mem_bar0, /* INDEX_PCI_BASE0, */ (caddr_t *)&cpqary3p->opq, - (offset_t)I2O_OBPOST_Q, map_len, &cpqary3_dev_attributes, - &cpqary3p->opq_handle); - - if (retvalue != DDI_SUCCESS) { - if (retvalue == DDI_REGS_ACC_CONFLICT) { - cmn_err(CE_WARN, - "CPQary3 : Registers Mapping Conflict"); - } - cmn_err(CE_WARN, "CPQary3 : Outbound Post Queue " - "Register Mapping Failed"); - return (CPQARY3_FAILURE); - } - - - /* - * The config offset and memory offset have to be obtained in order to - * locate the config table. - */ - retvalue = ddi_regs_map_setup(cpqary3p->dip, - mem_bar0, /* INDEX_PCI_BASE0, */ (caddr_t *)&ct_cfg_offset, - (offset_t)CT_CFG_OFFSET, map_len, &cpqary3_dev_attributes, - &ct_cfgoff_handle); - - if (retvalue != DDI_SUCCESS) { - if (retvalue == DDI_REGS_ACC_CONFLICT) { - cmn_err(CE_WARN, - "CPQary3 : Registers Mapping Conflict"); - } - cmn_err(CE_WARN, "CPQary3 : Configuration Table " - "Register Mapping Failed"); - return (CPQARY3_FAILURE); - } - - retvalue = ddi_regs_map_setup(cpqary3p->dip, - mem_bar0, /* INDEX_PCI_BASE0, */ - (caddr_t *)&ct_mem_offset, (offset_t)CT_MEM_OFFSET, map_len, - &cpqary3_dev_attributes, &ct_memoff_handle); - - if (retvalue != DDI_SUCCESS) { - if (retvalue == DDI_REGS_ACC_CONFLICT) { - cmn_err(CE_WARN, - "CPQary3 : Registers Mapping Conflict"); - } - cmn_err(CE_WARN, "CPQary3 : Configuration Table " - "Register Mapping Failed"); - return (CPQARY3_FAILURE); - } - - ct_cfgmem_val = (uint32_t)ddi_get32(ct_cfgoff_handle, ct_cfg_offset); - ct_memoff_val = (uint32_t)ddi_get32(ct_memoff_handle, ct_mem_offset); - - ddi_regs_map_free(&ct_cfgoff_handle); - ddi_regs_map_free(&ct_memoff_handle); - - ct_cfg_bar = (ct_cfgmem_val & 0x0000ffff); - ct_mem_len = (ct_cfgmem_val & 0xffff0000); - ct_mem_len = (ct_mem_len >> 16); - - if (ct_cfg_bar == 0x10) { - if (ct_mem_len) { - ct_mem_bar = mem_64_bar0; - } else { - ct_mem_bar = mem_bar0; - } - - } else if (ct_cfg_bar == 0x14) { - if (ct_mem_len) { - ct_mem_bar = mem_64_bar1; - } else { - ct_mem_bar = mem_bar1; - } + if (l->cpcm_tag > r->cpcm_tag) { + return (1); + } else if (l->cpcm_tag < r->cpcm_tag) { + return (-1); } else { - return (CPQARY3_FAILURE); - } - - - /* - * The Configuration Table(CT) shall be mapped in the form of a - * structure since several members in the CT need to be accessed - * to read and write. - */ - retvalue = ddi_regs_map_setup(cpqary3p->dip, - ct_mem_bar, /* INDEX_PCI_BASE0/1, */ - (caddr_t *)&cpqary3p->ct, (offset_t)ct_memoff_val, - sizeof (CfgTable_t), &cpqary3_dev_attributes, &cpqary3p->ct_handle); - - if (retvalue != DDI_SUCCESS) { - if (retvalue == DDI_REGS_ACC_CONFLICT) { - cmn_err(CE_WARN, - "CPQary3 : Registers Mapping Conflict"); - } - cmn_err(CE_WARN, "CPQary3 : Configuration Table " - "Register Mapping Failed"); - return (CPQARY3_FAILURE); - } - - /* PERF */ - - retvalue = ddi_regs_map_setup(cpqary3p->dip, - ct_mem_bar, /* INDEX_PCI_BASE0/1, */ - (caddr_t *)&cpqary3p->cp, - (offset_t)(ct_memoff_val + cpqary3p->ct->TransportMethodOffset), - sizeof (CfgTrans_Perf_t), &cpqary3_dev_attributes, - &cpqary3p->cp_handle); - - if (retvalue != DDI_SUCCESS) { - if (retvalue == DDI_REGS_ACC_CONFLICT) - cmn_err(CE_WARN, - "CPQary3 : Registers Mapping Conflict"); - cmn_err(CE_WARN, "CPQary3 : Performant Transport Method Table " - "Mapping Failed"); - return (CPQARY3_FAILURE); + return (0); } - - /* PERF */ - - return (CPQARY3_SUCCESS); } diff --git a/usr/src/uts/common/io/cpqary3/cpqary3.h b/usr/src/uts/common/io/cpqary3/cpqary3.h index b2b937ea7c..3b902134f4 100644 --- a/usr/src/uts/common/io/cpqary3/cpqary3.h +++ b/usr/src/uts/common/io/cpqary3/cpqary3.h @@ -72,19 +72,33 @@ extern "C" { */ #define CPQARY3_HBA_TRAN_ALLOC_DONE 0x0001 #define CPQARY3_HBA_TRAN_ATTACH_DONE 0x0002 -#define CPQARY3_CTLR_CONFIG_DONE 0x0004 #define CPQARY3_INTR_HDLR_SET 0x0008 #define CPQARY3_CREATE_MINOR_NODE 0x0010 #define CPQARY3_SOFTSTATE_ALLOC_DONE 0x0020 #define CPQARY3_MUTEX_INIT_DONE 0x0040 #define CPQARY3_TICK_TMOUT_REGD 0x0080 -#define CPQARY3_MEM_MAPPED 0x0100 #define CPQARY3_SW_INTR_HDLR_SET 0x0200 #define CPQARY3_SW_MUTEX_INIT_DONE 0x0400 #define CPQARY3_NOE_INIT_DONE 0x0800 #define CPQARY3_CLEAN_ALL 0x0FFF +typedef enum cpqary3_init_level { + CPQARY3_INITLEVEL_BASIC = (0x1 << 0), + CPQARY3_INITLEVEL_I2O_MAPPED = (0x1 << 1), + CPQARY3_INITLEVEL_CFGTBL_MAPPED = (0x1 << 2), + CPQARY3_INITLEVEL_PERIODIC = (0x1 << 3), + CPQARY3_INITLEVEL_INT_HW_HANDLER = (0x1 << 4), + CPQARY3_INITLEVEL_INT_SW_HANDLER = (0x1 << 5), + CPQARY3_INITLEVEL_MUTEX = (0x1 << 6), + CPQARY3_INITLEVEL_MINOR_NODE = (0x1 << 7), + CPQARY3_INITLEVEL_HBA_ALLOC = (0x1 << 8), + CPQARY3_INITLEVEL_HBA_ATTACH = (0x1 << 9), +} cpqary3_init_level_t; + +#define CPQARY3_MIN_TAG_NUMBER 0x00000100 +#define CPQARY3_MAX_TAG_NUMBER 0x0fffffff + /* * Definitions to support waiting for the controller to converge on a * particular state; ready or not ready. These are used with @@ -293,19 +307,19 @@ typedef struct cpqary3 cpqary3_t; * Per Controller Structure */ struct cpqary3 { - /* System Dependent Entities */ - uint8_t bus; - uint8_t dev : 5; - uint8_t fun : 3; - uint32_t instance; dev_info_t *dip; + int cpq_instance; + + cpqary3_init_level_t cpq_init_level; - /* Controller Specific Information */ cpqary3_ctlr_mode_t cpq_ctlr_mode; - int8_t hba_name[38]; - ulong_t num_of_targets; - uint32_t board_id; - cpqary3_bd_t *bddef; + unsigned cpq_ntargets; + uint32_t cpq_board_id; + cpqary3_bd_t *cpq_board; + + uint32_t cpq_host_support; + uint32_t cpq_maxcmds; + uint32_t cpq_sg_cnt; /* * Controller Heartbeat Tracking @@ -319,6 +333,7 @@ struct cpqary3 { cpqary3_replyq_t cpq_replyq; avl_tree_t cpq_inflight; + list_t cpq_commands; /* List of all commands. */ /* Condition Variables used */ kcondvar_t cv_immediate_wait; @@ -335,10 +350,13 @@ struct cpqary3 { * Database for the per-controller Command Memory Pool * Target List for the per-controller */ - uint8_t irq; /* h/w IRQ */ - ddi_iblock_cookie_t hw_iblock_cookie; /* cookie for h/w intr */ + + + ddi_iblock_cookie_t cpq_int_hw_cookie; + ddi_iblock_cookie_t cpq_int_sw_cookie; + + kmutex_t hw_mutex; /* h/w mutex */ - ddi_iblock_cookie_t sw_iblock_cookie; /* cookie for s/w intr */ kmutex_t sw_mutex; /* s/w mutex */ ddi_softintr_t cpqary3_softintr_id; /* s/w intr identifier */ boolean_t cpq_swintr_flag; @@ -348,9 +366,6 @@ struct cpqary3 { cpqary3_cmdmemlist_t *cmdmemlistp; /* database - Memory Pool */ cpqary3_tgt_t *cpqary3_tgtp[CPQARY3_MAX_TGT]; - - uint8_t (*check_ctlr_intr)(cpqary3_t *); - /* * PCI Configuration Registers * 0x10 Primary I2O Memory BAR - for Host Interface @@ -368,49 +383,25 @@ struct cpqary3 { * 0x00 Configuration Table - for Controller Transport Layer */ - uint32_t *idr; - ddi_acc_handle_t idr_handle; - - /* LOCKUP CODE */ - uint32_t *spr0; - ddi_acc_handle_t spr0_handle; - /* LOCKUP CODE */ - - uint32_t *odr; - ddi_acc_handle_t odr_handle; - - uint32_t *odr_cl; - ddi_acc_handle_t odr_cl_handle; - - uint32_t *isr; - ddi_acc_handle_t isr_handle; - - uint32_t *imr; - ddi_acc_handle_t imr_handle; - - uint32_t *ipq; - ddi_acc_handle_t ipq_handle; - - uint32_t *opq; - ddi_acc_handle_t opq_handle; - - CfgTable_t *ct; - ddi_acc_handle_t ct_handle; + /* + * Access to the I2O Registers: + */ + unsigned cpq_i2o_bar; + caddr_t cpq_i2o_space; + ddi_acc_handle_t cpq_i2o_handle; - CfgTrans_Perf_t *cp; - ddi_acc_handle_t cp_handle; + /* + * Access to the Configuration Table: + */ + unsigned cpq_ct_bar; + uint32_t cpq_ct_baseaddr; + CfgTable_t *cpq_ct; + ddi_acc_handle_t cpq_ct_handle; uint32_t noe_support; - /* SG */ - uint32_t sg_cnt; - /* SG */ - uint32_t ctlr_maxcmds; - uint32_t host_support; uint8_t controller_lockup; uint8_t lockup_logged; uint32_t poll_flag; - - list_t cpq_commands; /* List of all commands. */ }; typedef struct cpqary3_command cpqary3_command_t; @@ -531,7 +522,6 @@ typedef struct cpqary3_ioctlreq { /* Driver function definitions */ void cpqary3_init_hbatran(cpqary3_t *); -void cpqary3_read_conf_file(dev_info_t *, cpqary3_t *); void cpqary3_periodic(void *); int cpqary3_flush_cache(cpqary3_t *); void cpqary3_intr_onoff(cpqary3_t *, uint8_t); @@ -552,6 +542,7 @@ int cpqary3_retrieve(cpqary3_t *); void cpqary3_retrieve_simple(cpqary3_t *, uint32_t, boolean_t *); void cpqary3_retrieve_performant(cpqary3_t *, uint32_t, boolean_t *); int cpqary3_target_geometry(struct scsi_address *); +int8_t cpqary3_detect_target_geometry(cpqary3_t *); uint8_t cpqary3_send_abortcmd(cpqary3_t *, uint16_t, CommandList_t *); void cpqary3_memfini(cpqary3_t *, uint8_t); int16_t cpqary3_meminit(cpqary3_t *); @@ -581,8 +572,11 @@ void cpqary3_synccmd_complete(cpqary3_command_t *); * Interrupt service routines. */ uint32_t cpqary3_isr_hw_simple(caddr_t); +uint32_t cpqary3_isr_sw_simple(caddr_t); uint32_t cpqary3_isr_hw_performant(caddr_t); -uint32_t cpqary3_sw_isr(caddr_t); +uint32_t cpqary3_isr_sw_performant(caddr_t); +int cpqary3_interrupts_setup(cpqary3_t *); +void cpqary3_interrupts_teardown(cpqary3_t *); /* * Controller initialisation routines. @@ -596,9 +590,16 @@ int cpqary3_ctlr_wait_for_state(cpqary3_t *, cpqary3_wait_state_t); cpqary3_command_t *cpqary3_command_alloc(cpqary3_t *); cpqary3_command_internal_t *cpqary3_command_internal_alloc(cpqary3_t *, size_t); void cpqary3_command_free(cpqary3_command_t *); - cpqary3_command_t *cpqary3_lookup_inflight(cpqary3_t *, uint32_t); +/* + * Device management routines. + */ +uint32_t cpqary3_get32(cpqary3_t *, offset_t); +void cpqary3_put32(cpqary3_t *, offset_t, uint32_t); +int cpqary3_device_setup(cpqary3_t *); +void cpqary3_device_teardown(cpqary3_t *); + #ifdef __cplusplus } diff --git a/usr/src/uts/common/io/cpqary3/cpqary3_ciss.h b/usr/src/uts/common/io/cpqary3/cpqary3_ciss.h index 31f95cb427..0202380aa5 100644 --- a/usr/src/uts/common/io/cpqary3/cpqary3_ciss.h +++ b/usr/src/uts/common/io/cpqary3/cpqary3_ciss.h @@ -21,8 +21,6 @@ extern "C" { #endif -#define CISS_VERSION "1.00" - /* General Boundary Defintions */ #define CISS_INIT_TIME 90 /* Driver Defined Value */ /* Duration to Wait for the */ @@ -33,50 +31,79 @@ extern "C" { #define CISS_MAXREPLYQS 256 /* Command Status Value */ -#define CISS_CMD_SUCCESS 0x00 -#define CISS_CMD_TARGET_STATUS 0x01 -#define CISS_CMD_DATA_UNDERRUN 0x02 -#define CISS_CMD_DATA_OVERRUN 0x03 -#define CISS_CMD_INVALID 0x04 -#define CISS_CMD_PROTOCOL_ERR 0x05 -#define CISS_CMD_HARDWARE_ERR 0x06 -#define CISS_CMD_CONNECTION_LOST 0x07 -#define CISS_CMD_ABORTED 0x08 -#define CISS_CMD_ABORT_FAILED 0x09 -#define CISS_CMD_UNSOLICITED_ABORT 0x0A -#define CISS_CMD_TIMEOUT 0x0B -#define CISS_CMD_UNABORTABLE 0x0C +#define CISS_CMD_SUCCESS 0x00 +#define CISS_CMD_TARGET_STATUS 0x01 +#define CISS_CMD_DATA_UNDERRUN 0x02 +#define CISS_CMD_DATA_OVERRUN 0x03 +#define CISS_CMD_INVALID 0x04 +#define CISS_CMD_PROTOCOL_ERR 0x05 +#define CISS_CMD_HARDWARE_ERR 0x06 +#define CISS_CMD_CONNECTION_LOST 0x07 +#define CISS_CMD_ABORTED 0x08 +#define CISS_CMD_ABORT_FAILED 0x09 +#define CISS_CMD_UNSOLICITED_ABORT 0x0a +#define CISS_CMD_TIMEOUT 0x0b +#define CISS_CMD_UNABORTABLE 0x0c /* Transfer Direction */ -#define CISS_XFER_NONE 0x00 -#define CISS_XFER_WRITE 0x01 -#define CISS_XFER_READ 0x02 -#define CISS_XFER_RSVD 0x03 +#define CISS_XFER_NONE 0x00 +#define CISS_XFER_WRITE 0x01 +#define CISS_XFER_READ 0x02 +#define CISS_XFER_RSVD 0x03 -#define CISS_ATTR_UNTAGGED 0x00 -#define CISS_ATTR_SIMPLE 0x04 -#define CISS_ATTR_HEADOFQUEUE 0x05 -#define CISS_ATTR_ORDERED 0x06 +#define CISS_ATTR_UNTAGGED 0x00 +#define CISS_ATTR_SIMPLE 0x04 +#define CISS_ATTR_HEADOFQUEUE 0x05 +#define CISS_ATTR_ORDERED 0x06 /* CDB Type */ -#define CISS_TYPE_CMD 0x00 -#define CISS_TYPE_MSG 0x01 - -/* Config Space Register Offsetsp */ -#define CFG_VENDORID 0x00 -#define CFG_DEVICEID 0x02 -#define CFG_I2OBAR 0x10 -#define CFG_MEM1BAR 0x14 - -/* I2O Space Register Offsets */ -#define I2O_INBOUND_DOORBELL 0x20 -#define I2O_INT_STATUS 0x30 -#define I2O_INT_MASK 0x34 -#define I2O_IBPOST_Q 0x40 -#define I2O_OBPOST_Q 0x44 -#define I2O_OBDB_STATUS 0x9C -#define I2O_OBDB_CLEAR 0xA0 -#define I2O_SCRATCHPAD 0xB0 +#define CISS_TYPE_CMD 0x00 +#define CISS_TYPE_MSG 0x01 + +/* + * I2O Space Register Offsets + * + * The name "I2O", and these register offsets, appear to be amongst the last + * vestiges of a long-defunct attempt at standardising mainframe-style I/O + * channels in the Intel server space: the Intelligent Input/Output (I2O) + * Architecture Specification. + * + * The draft of version 1.5 of this specification, in section "4.2.1.5.1 + * Extensions for PCI", suggests that the following are memory offsets into + * "the memory region specified by the first base address configuration + * register indicating memory space (offset 10h, 14h, and so forth)". These + * match up with the offsets of the first two BARs in a PCI configuration space + * type 0 header. + * + * The specification also calls out the Inbound Post List FIFO, write-only at + * offset 40h; the Outbound Post List FIFO, read-only at offset 44h; the + * Interrupt Status Register, at offset 30h; and the Interrupt Mask Register, + * at offset 34h. + * + * This ill-fated attempt to increase the proprietary complexity of (and + * presumably, thus, the gross margin on) computer systems folded at the turn + * of the century. The transport layer of this storage controller is all + * that's left of their religion. + */ +#define CISS_I2O_INBOUND_DOORBELL 0x20 +#define CISS_I2O_INTERRUPT_STATUS 0x30 +#define CISS_I2O_INTERRUPT_MASK 0x34 +#define CISS_I2O_INBOUND_POST_Q 0x40 +#define CISS_I2O_OUTBOUND_POST_Q 0x44 +#define CISS_I2O_OUTBOUND_DOORBELL_STATUS 0x9c +#define CISS_I2O_OUTBOUND_DOORBELL_CLEAR 0xa0 +#define CISS_I2O_SCRATCHPAD 0xb0 +#define CISS_I2O_CFGTBL_CFG_OFFSET 0xb4 +#define CISS_I2O_CFGTBL_MEM_OFFSET 0xb8 + +/* + * Rather than make a lot of small mappings for each part of the address + * space we wish to access, we will make one large mapping. If more + * offsets are added to the I2O list above, this space should be extended + * appropriately. + */ +#define CISS_I2O_MAP_BASE 0x20 +#define CISS_I2O_MAP_LIMIT 0x100 /* * The Scratchpad Register (I2O_SCRATCHPAD) is not mentioned in the CISS @@ -90,8 +117,8 @@ extern "C" { * Outbound Doorbell Register Values. * * These are read from the Outbound Doorbell Set/Status Register - * (I2O_OBDB_STATUS), but cleared by writing to the Clear - * Register (I2O_OBDB_CLEAR). + * (CISS_I2O_OUTBOUND_DOORBELL_STATUS), but cleared by writing to the Clear + * Register (CISS_I2O_OUTBOUND_DOORBELL_CLEAR). */ #define CISS_ODR_BIT_INTERRUPT (1UL << 0) #define CISS_ODR_BIT_LOCKUP (1UL << 1) @@ -100,7 +127,7 @@ extern "C" { * Inbound Doorbell Register Values. * * These are written to and read from the Inbound Doorbell Register - * (I2O_INBOUND_DOORBELL). + * (CISS_I2O_INBOUND_DOORBELL). */ #define CISS_IDR_BIT_CFGTBL_CHANGE (1UL << 0) @@ -120,14 +147,6 @@ extern "C" { #define CISS_CFGTBL_XPORT_PERFORMANT (1UL << 2) #define CISS_CFGTBL_XPORT_MEMQ (1UL << 4) -/* for hard reset of the controller */ -#define CISS_POWER_OFF 0x03 /* Self Defined */ -#define CISS_POWER_ON 0x00 /* Self Defined */ -#define CISS_POWER_REG_OFFSET 0xF4 /* Self Defined */ - -#define CT_CFG_OFFSET 0xB4 -#define CT_MEM_OFFSET 0xB8 - /* * STRUCTURES * Command List Structure diff --git a/usr/src/uts/common/io/cpqary3/cpqary3_device.c b/usr/src/uts/common/io/cpqary3/cpqary3_device.c new file mode 100644 index 0000000000..bf1d47d4ff --- /dev/null +++ b/usr/src/uts/common/io/cpqary3/cpqary3_device.c @@ -0,0 +1,256 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright 2016 Joyent, Inc. + */ + +#include "cpqary3.h" + +extern ddi_dma_attr_t cpqary3_dma_attr; +extern ddi_device_acc_attr_t cpqary3_dev_attributes; + +/* + * We must locate what the CISS specification describes as the "I2O + * registers". The Intelligent I/O (I2O) Architecture Specification describes + * this somewhat more coherently as "the memory region specified by the first + * base address configuration register indicating memory space (offset 10h, + * 14h, and so forth)". + */ +static int +cpqary3_locate_bar(cpqary3_t *cpq, pci_regspec_t *regs, unsigned nregs, + unsigned *i2o_bar) +{ + /* + * Locate the first memory-mapped BAR: + */ + for (unsigned i = 0; i < nregs; i++) { + unsigned type = regs[i].pci_phys_hi & PCI_ADDR_MASK; + unsigned bar = PCI_REG_REG_G(regs[i].pci_phys_hi); + + if (type == PCI_ADDR_MEM32) { + dev_err(cpq->dip, CE_WARN, "reg[%u]: bar found: %x", + i, bar); + *i2o_bar = i; + return (DDI_SUCCESS); + } + } + + return (DDI_FAILURE); +} + +static int +cpqary3_locate_cfgtbl(cpqary3_t *cpq, pci_regspec_t *regs, unsigned nregs, + unsigned *ct_bar, uint32_t *baseaddr) +{ + uint32_t cfg_offset, mem_offset; + unsigned want_type; + uint32_t want_bar; + + cfg_offset = cpqary3_get32(cpq, CISS_I2O_CFGTBL_CFG_OFFSET); + mem_offset = cpqary3_get32(cpq, CISS_I2O_CFGTBL_MEM_OFFSET); + + VERIFY(cfg_offset != 0xffffffff); + VERIFY(mem_offset != 0xffffffff); + + /* + * Locate the Configuration Table. Three different values read + * from two I2O registers allow us to determine the location: + * - the correct PCI BAR offset is in the low 16 bits of + * CISS_I2O_CFGTBL_CFG_OFFSET + * - bit 16 is 0 for a 32-bit space, and 1 for 64-bit + * - the memory offset from the base of this BAR is + * in CISS_I2O_CFGTBL_MEM_OFFSET + */ + want_bar = (cfg_offset & 0xffff); + want_type = (cfg_offset & (1UL << 16)) ? PCI_ADDR_MEM64 : + PCI_ADDR_MEM32; + + dev_err(cpq->dip, CE_WARN, "want BAR %x of type %s; offset %x", + want_bar, want_type == PCI_ADDR_MEM64 ? "MEM64" : "MEM32", + mem_offset); + + for (unsigned i = 0; i < nregs; i++) { + unsigned type = regs[i].pci_phys_hi & PCI_ADDR_MASK; + unsigned bar = PCI_REG_REG_G(regs[i].pci_phys_hi); + + if (type == want_type && bar == want_bar) { + dev_err(cpq->dip, CE_WARN, "reg[%u]: bar found: %x", + i, bar); + + *ct_bar = i; + *baseaddr = mem_offset; + return (DDI_SUCCESS); + } + } + + return (DDI_FAILURE); +} + +static int +cpqary3_map_device(cpqary3_t *cpq) +{ + pci_regspec_t *regs; + uint_t regslen, nregs; + int r = DDI_FAILURE; + + /* + * Get the list of PCI registers from the DDI property "regs": + */ + if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, cpq->dip, + DDI_PROP_DONTPASS, "reg", (int **)®s, ®slen) != + DDI_PROP_SUCCESS) { + dev_err(cpq->dip, CE_WARN, "could not load \"reg\" DDI prop"); + return (DDI_FAILURE); + } + nregs = regslen * sizeof (int) / sizeof (pci_regspec_t); + + if (cpqary3_locate_bar(cpq, regs, nregs, &cpq->cpq_i2o_bar) != + DDI_SUCCESS) { + dev_err(cpq->dip, CE_WARN, "did not find any memory BARs"); + goto out; + } + + /* + * Map enough of the I2O memory space to enable us to talk to the + * device. + */ + if (ddi_regs_map_setup(cpq->dip, cpq->cpq_i2o_bar, + &cpq->cpq_i2o_space, CISS_I2O_MAP_BASE, + CISS_I2O_MAP_LIMIT - CISS_I2O_MAP_BASE, + &cpqary3_dev_attributes, &cpq->cpq_i2o_handle) != DDI_SUCCESS) { + dev_err(cpq->dip, CE_WARN, "failed to map I2O registers"); + goto out; + } + cpq->cpq_init_level |= CPQARY3_INITLEVEL_I2O_MAPPED; + + if (cpqary3_locate_cfgtbl(cpq, regs, nregs, &cpq->cpq_ct_bar, + &cpq->cpq_ct_baseaddr) != DDI_SUCCESS) { + dev_err(cpq->dip, CE_WARN, "could not find config table"); + goto out; + } + + /* + * Map the Configuration Table. + */ + if (ddi_regs_map_setup(cpq->dip, cpq->cpq_ct_bar, + (caddr_t *)&cpq->cpq_ct, cpq->cpq_ct_baseaddr, + sizeof (CfgTable_t), &cpqary3_dev_attributes, + &cpq->cpq_ct_handle) != DDI_SUCCESS) { + dev_err(cpq->dip, CE_WARN, "could not map config table"); + goto out; + } + cpq->cpq_init_level |= CPQARY3_INITLEVEL_CFGTBL_MAPPED; + + r = DDI_SUCCESS; + +out: + ddi_prop_free(regs); + return (r); +} + +static int +cpqary3_identify_board(cpqary3_t *cpq) +{ + uint32_t board_id; + int vid, sid; + + /* + * Identify the board. The board ID is really a combination of the + * Subsystem Vendor ID and the Subsystem ID. This is described in the + * CISS Specification, section "6.2 Initialization". + */ + if ((vid = ddi_prop_get_int(DDI_DEV_T_ANY, cpq->dip, DDI_PROP_DONTPASS, + "subsystem-vendor-id", -1)) == -1 || + (sid = ddi_prop_get_int(DDI_DEV_T_ANY, cpq->dip, DDI_PROP_DONTPASS, + "subsystem-id", -1)) == -1) { + dev_err(cpq->dip, CE_WARN, "could not get subsystem id"); + return (DDI_FAILURE); + } + board_id = ((vid & 0xffff) << 16) | (sid & 0xffff); + + if ((cpq->cpq_board = cpqary3_bd_getbybid(board_id)) == NULL) { + dev_err(cpq->dip, CE_WARN, "unsupported controller; id %x", + board_id); + return (DDI_FAILURE); + } + cpq->cpq_board_id = board_id; + + /* + * XXX + */ + dev_err(cpq->dip, CE_WARN, "controller: %s", + cpq->cpq_board->bd_dispname); + + return (DDI_SUCCESS); +} + +int +cpqary3_device_setup(cpqary3_t *cpq) +{ + /* + * Ensure that the controller is installed in such a fashion that it + * may become a DMA master. + */ + if (ddi_slaveonly(cpq->dip) == DDI_SUCCESS) { + dev_err(cpq->dip, CE_WARN, "device cannot become DMA master"); + return (DDI_FAILURE); + } + + if (cpqary3_identify_board(cpq) != DDI_SUCCESS || + cpqary3_map_device(cpq) != DDI_SUCCESS) { + goto fail; + } + + return (DDI_SUCCESS); + +fail: + cpqary3_device_teardown(cpq); + return (DDI_FAILURE); +} + +void +cpqary3_device_teardown(cpqary3_t *cpq) +{ + if (cpq->cpq_init_level & CPQARY3_INITLEVEL_CFGTBL_MAPPED) { + ddi_regs_map_free(&cpq->cpq_ct_handle); + cpq->cpq_init_level &= ~CPQARY3_INITLEVEL_CFGTBL_MAPPED; + } + + if (cpq->cpq_init_level & CPQARY3_INITLEVEL_I2O_MAPPED) { + ddi_regs_map_free(&cpq->cpq_i2o_handle); + cpq->cpq_init_level &= ~CPQARY3_INITLEVEL_I2O_MAPPED; + } +} + +uint32_t +cpqary3_get32(cpqary3_t *cpq, offset_t off) +{ + uint32_t *addr = (uint32_t *)(cpq->cpq_i2o_space + + (off - CISS_I2O_MAP_BASE)); + + VERIFY(off >= CISS_I2O_MAP_BASE); + VERIFY(off < CISS_I2O_MAP_BASE + CISS_I2O_MAP_LIMIT); + + return (ddi_get32(cpq->cpq_i2o_handle, addr)); +} + +void +cpqary3_put32(cpqary3_t *cpq, offset_t off, uint32_t val) +{ + uint32_t *addr = (uint32_t *)(cpq->cpq_i2o_space + + (off - CISS_I2O_MAP_BASE)); + + VERIFY(off >= CISS_I2O_MAP_BASE); + VERIFY(off < CISS_I2O_MAP_BASE + CISS_I2O_MAP_LIMIT); + + return (ddi_put32(cpq->cpq_i2o_handle, addr, val)); +} diff --git a/usr/src/uts/common/io/cpqary3/cpqary3_interrupts.c b/usr/src/uts/common/io/cpqary3/cpqary3_interrupts.c new file mode 100644 index 0000000000..b21ea6bd02 --- /dev/null +++ b/usr/src/uts/common/io/cpqary3/cpqary3_interrupts.c @@ -0,0 +1,102 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright 2016 Joyent, Inc. + */ + +#include "cpqary3.h" + +int +cpqary3_interrupts_setup(cpqary3_t *cpq) +{ + uint_t (*hw_isr)(caddr_t); + uint_t (*sw_isr)(caddr_t); + + if (ddi_get_soft_iblock_cookie(cpq->dip, DDI_SOFTINT_HIGH, + &cpq->cpq_int_sw_cookie) != DDI_SUCCESS) { + dev_err(cpq->dip, CE_WARN, "ddi_get_soft_iblock_cookie failed"); + goto fail; + } + + if (ddi_get_iblock_cookie(cpq->dip, 0, &cpq->cpq_int_hw_cookie) != + DDI_SUCCESS) { + dev_err(cpq->dip, CE_WARN, "ddi_get_iblock_cookie (hw) failed"); + goto fail; + } + + mutex_init(&cpq->sw_mutex, NULL, MUTEX_DRIVER, + (void *)cpq->cpq_int_sw_cookie); + mutex_init(&cpq->hw_mutex, NULL, MUTEX_DRIVER, + (void *)cpq->cpq_int_hw_cookie); + cpq->cpq_init_level |= CPQARY3_INITLEVEL_MUTEX; + + /* + * Select the correct hardware interrupt service routine for the + * Transport Method we have configured: + */ + switch (cpq->cpq_ctlr_mode) { + case CPQARY3_CTLR_MODE_SIMPLE: + hw_isr = cpqary3_isr_hw_simple; + sw_isr = cpqary3_isr_sw_simple; + break; + case CPQARY3_CTLR_MODE_PERFORMANT: + hw_isr = cpqary3_isr_hw_performant; + sw_isr = cpqary3_isr_sw_performant; + break; + default: + panic("unknown controller mode"); + } + + if (ddi_add_softintr(cpq->dip, DDI_SOFTINT_HIGH, + &cpq->cpqary3_softintr_id, &cpq->cpq_int_sw_cookie, NULL, sw_isr, + (caddr_t)cpq) != DDI_SUCCESS) { + dev_err(cpq->dip, CE_WARN, "ddi_add_softintr failed"); + goto fail; + } + cpq->cpq_init_level |= CPQARY3_INITLEVEL_INT_SW_HANDLER; + + if (ddi_add_intr(cpq->dip, 0, &cpq->cpq_int_hw_cookie, NULL, hw_isr, + (caddr_t)cpq) != DDI_SUCCESS) { + dev_err(cpq->dip, CE_WARN, "ddi_add_intr (hw) failed"); + goto fail; + } + cpq->cpq_init_level |= CPQARY3_INITLEVEL_INT_HW_HANDLER; + + return (DDI_SUCCESS); + +fail: + cpqary3_interrupts_teardown(cpq); + return (DDI_FAILURE); +} + +void +cpqary3_interrupts_teardown(cpqary3_t *cpq) +{ + if (cpq->cpq_init_level & CPQARY3_INITLEVEL_INT_HW_HANDLER) { + ddi_remove_intr(cpq->dip, 0, cpq->cpq_int_hw_cookie); + + cpq->cpq_init_level &= ~CPQARY3_INITLEVEL_INT_HW_HANDLER; + } + + if (cpq->cpq_init_level & CPQARY3_INITLEVEL_INT_SW_HANDLER) { + ddi_remove_softintr(cpq->cpqary3_softintr_id); + + cpq->cpq_init_level &= ~CPQARY3_INITLEVEL_INT_SW_HANDLER; + } + + if (cpq->cpq_init_level & CPQARY3_INITLEVEL_MUTEX) { + mutex_destroy(&cpq->sw_mutex); + mutex_destroy(&cpq->hw_mutex); + + cpq->cpq_init_level &= ~CPQARY3_INITLEVEL_MUTEX; + } +} diff --git a/usr/src/uts/common/io/cpqary3/cpqary3_ioctl.c b/usr/src/uts/common/io/cpqary3/cpqary3_ioctl.c index 395a8f907f..cf74044730 100644 --- a/usr/src/uts/common/io/cpqary3/cpqary3_ioctl.c +++ b/usr/src/uts/common/io/cpqary3/cpqary3_ioctl.c @@ -15,8 +15,6 @@ /* * Supported IOCTLs : - * CPQARY3_IOCTL_DRIVER_INFO - to get driver details - * CPQARY3_IOCTL_CTLR_INFO - to get controller details * CPQARY3_IOCTL_BMIC_PASS - to pass BMIC commands * CPQARY3_IOCTL_SCSI_PASS - to pass SCSI commands */ @@ -43,174 +41,6 @@ cpqary3_driver_info_t gdriver_info = {0}; /* Function Definitions */ -/* - * Function : cpqary3_ioctl_driver_info - * Description : This routine will get major/ minor versions, Number of - * controllers detected & MAX Number of controllers - * supported - * Called By : cpqary3_ioctl - * Parameters : ioctl_reqp - address of the parameter sent from - * the application - * cpqary3p - address of the PerController structure - * mode - mode which comes from application - * Return Values: EFAULT on Failure, 0 on SUCCESS - */ -int32_t -cpqary3_ioctl_driver_info(uintptr_t ioctl_reqp, int mode) -{ - cpqary3_ioctl_request_t *request; - - request = (cpqary3_ioctl_request_t *) - MEM_ZALLOC(sizeof (cpqary3_ioctl_request_t)); - - if (NULL == request) - return (FAILURE); - - /* - * First let us copyin the ioctl_reqp user buffer to request(kernel) - * memory. This is very much recomended before we access any of the - * fields. - */ - if (ddi_copyin((void *)ioctl_reqp, (void *)request, - sizeof (cpqary3_ioctl_request_t), mode)) { - MEM_SFREE(request, sizeof (cpqary3_ioctl_request_t)); - return (EFAULT); - } - - /* - * Fill up the global structure "gdriver_info" memory. - * Fill this structure with available info, which will be copied - * back later - */ - - (void) strcpy(gdriver_info.name, "cpqary3"); - gdriver_info.version.minor = CPQARY3_MINOR_REV_NO; - gdriver_info.version.major = CPQARY3_MAJOR_REV_NO; - gdriver_info.version.dd = CPQARY3_REV_MONTH; - gdriver_info.version.mm = CPQARY3_REV_DATE; - gdriver_info.version.yyyy = CPQARY3_REV_YEAR; - gdriver_info.max_num_ctlr = MAX_CTLRS; - - /* - * First Copy out the driver_info structure - */ - - if (ddi_copyout((void *)&gdriver_info, (void *)(uintptr_t)request->argp, - sizeof (cpqary3_driver_info_t), mode)) { - MEM_SFREE(request, sizeof (cpqary3_ioctl_request_t)); - return (EFAULT); - } - - /* - * Copy out the request structure back - */ - - if (ddi_copyout((void *)request, (void *)ioctl_reqp, - sizeof (cpqary3_ioctl_request_t), mode)) { - MEM_SFREE(request, sizeof (cpqary3_ioctl_request_t)); - return (EFAULT); - } - - MEM_SFREE(request, sizeof (cpqary3_ioctl_request_t)); - - /* - * Everything looks fine. So return SUCCESS - */ - - return (SUCCESS); -} - -/* - * Function : cpqary3_ioctl_ctlr_info - * Description : This routine will get the controller related info, like - * board-id, subsystem-id, num of logical drives, - * slot number - * Called By : cpqary3_ioctl - * Parameters : ioctl_reqp - address of the parameter sent form the - * application - * cpqary3p - address of the PerController structure - * mode - mode which comes from application - * Return Values: EFAULT on Failure, 0 on SUCCESS - */ -int32_t -cpqary3_ioctl_ctlr_info(uintptr_t ioctl_reqp, cpqary3_t *cpqary3p, int mode) -{ - cpqary3_ioctl_request_t *request; - cpqary3_ctlr_info_t *ctlr_info; - - request = (cpqary3_ioctl_request_t *) - MEM_ZALLOC(sizeof (cpqary3_ioctl_request_t)); - - if (NULL == request) - return (FAILURE); - - /* - * First let us copyin the buffer to kernel memory. This is very much - * recomended before we access any of the fields. - */ - - if (ddi_copyin((void *) ioctl_reqp, (void *)request, - sizeof (cpqary3_ioctl_request_t), mode)) { - MEM_SFREE(request, sizeof (cpqary3_ioctl_request_t)); - return (EFAULT); - } - - ctlr_info = (cpqary3_ctlr_info_t *) - MEM_ZALLOC(sizeof (cpqary3_ctlr_info_t)); - - if (NULL == ctlr_info) { - MEM_SFREE(request, sizeof (cpqary3_ioctl_request_t)); - return (FAILURE); - } - - /* - * in the driver, board_id is actually subsystem_id - */ - - ctlr_info->subsystem_id = cpqary3p->board_id; - ctlr_info->bus = cpqary3p->bus; - ctlr_info->dev = cpqary3p->dev; - ctlr_info->fun = cpqary3p->fun; - ctlr_info->num_of_tgts = cpqary3p->num_of_targets; - ctlr_info->controller_instance = cpqary3p->instance; - - /* - * TODO: ctlr_info.slot_num has to be implemented - * state & board_id fields are kept for future implementation i - * if required! - */ - - /* - * First Copy out the ctlr_info structure - */ - - if (ddi_copyout((void *)ctlr_info, (void *)(uintptr_t)request->argp, - sizeof (cpqary3_ctlr_info_t), mode)) { - MEM_SFREE(ctlr_info, sizeof (cpqary3_ctlr_info_t)); - MEM_SFREE(request, sizeof (cpqary3_ioctl_request_t)); - return (EFAULT); - } - - /* - * Copy out the request structure back - */ - - if (ddi_copyout((void *)request, (void *)ioctl_reqp, - sizeof (cpqary3_ioctl_request_t), mode)) { - MEM_SFREE(ctlr_info, sizeof (cpqary3_ctlr_info_t)); - MEM_SFREE(request, sizeof (cpqary3_ioctl_request_t)); - return (EFAULT); - } - - MEM_SFREE(ctlr_info, sizeof (cpqary3_ctlr_info_t)); - MEM_SFREE(request, sizeof (cpqary3_ioctl_request_t)); - - /* - * Everything looks fine. So return SUCCESS - */ - - return (SUCCESS); -} /* * Function : cpqary3_ioctl_bmic_pass diff --git a/usr/src/uts/common/io/cpqary3/cpqary3_ioctl.h b/usr/src/uts/common/io/cpqary3/cpqary3_ioctl.h index a6a0a04f27..18a79a4c78 100644 --- a/usr/src/uts/common/io/cpqary3/cpqary3_ioctl.h +++ b/usr/src/uts/common/io/cpqary3/cpqary3_ioctl.h @@ -67,35 +67,6 @@ typedef struct cpqary3_ioctl_request { uint64_t argp; /* Data or data Buffer of the request */ } cpqary3_ioctl_request_t; -typedef struct cpqary3_drvrev { - uint8_t minor; /* Version info */ - uint8_t major; - uint8_t mm; /* Revision Date */ - uint8_t dd; - uint16_t yyyy; -} cpqary3_drvrev_t; - -typedef struct cpqary3_driver_info { - int8_t name[16]; /* Null Term. ASCII driver name */ - cpqary3_drvrev_t version; /* Driver version and revision */ - uint32_t num_ctlr; /* Num of ctlrs currently handled */ - uint32_t max_num_ctlr; /* Max num ctlrs supported */ - int8_t reserved[98]; /* Structure size = 128 bytes */ -} cpqary3_driver_info_t; - -typedef struct cpqary3_ctlr_info { - uint16_t state; /* currently set to active */ - uint32_t board_id; /* controllers board_id */ - uint32_t subsystem_id; /* controllers subsystem_id */ - uint8_t bus; /* controllers PCI Bus number */ - uint8_t dev : 5; /* 5 bit device number */ - uint8_t fun : 3; /* 3 bit function number */ - uint16_t slot_num; /* physical slot number */ - uint8_t num_of_tgts; /* No of Logical Drives */ - uint32_t controller_instance; /* Ap id number */ - int8_t reserved[109]; /* Structure size = 128 bytes */ -} cpqary3_ctlr_info_t; - typedef struct cpqary3_bmic_pass { uint8_t lun_addr[8]; /* 8 byte LUN address */ uint8_t cmd; /* BMIC command opcode */ diff --git a/usr/src/uts/common/io/cpqary3/cpqary3_isr.c b/usr/src/uts/common/io/cpqary3/cpqary3_isr.c index 5884fa1068..0fdcb88083 100644 --- a/usr/src/uts/common/io/cpqary3/cpqary3_isr.c +++ b/usr/src/uts/common/io/cpqary3/cpqary3_isr.c @@ -38,10 +38,10 @@ uint_t cpqary3_isr_hw_simple(caddr_t arg) { cpqary3_t *cpq = (cpqary3_t *)arg; - uint32_t isr = ddi_get32(cpq->isr_handle, cpq->isr); + uint32_t isr = cpqary3_get32(cpq, CISS_I2O_INTERRUPT_STATUS); mutex_enter(&cpq->hw_mutex); - if ((isr & cpq->bddef->bd_intrpendmask) == 0) { + if ((isr & cpq->cpq_board->bd_intrpendmask) == 0) { /* * Check to see if the firmware has come to rest. If it has, * this routine will panic the system. @@ -68,7 +68,7 @@ uint_t cpqary3_isr_hw_performant(caddr_t arg) { cpqary3_t *cpq = (cpqary3_t *)arg; - uint32_t isr = ddi_get32(cpq->isr_handle, cpq->isr); + uint32_t isr = cpqary3_get32(cpq, CISS_I2O_INTERRUPT_STATUS); if (isr == 0) { /* @@ -80,18 +80,19 @@ cpqary3_isr_hw_performant(caddr_t arg) return (DDI_INTR_UNCLAIMED); } - uint32_t odr = ddi_get32(cpq->odr_handle, cpq->odr); + uint32_t odr = cpqary3_get32(cpq, CISS_I2O_OUTBOUND_DOORBELL_STATUS); if ((odr & 0x1) != 0) { - uint32_t odr_cl = ddi_get32(cpq->odr_cl_handle, cpq->odr_cl); + uint32_t odr_cl = cpqary3_get32(cpq, + CISS_I2O_OUTBOUND_DOORBELL_CLEAR); odr_cl |= 0x1; - ddi_put32(cpq->odr_cl_handle, cpq->odr_cl, odr_cl); + cpqary3_put32(cpq, CISS_I2O_OUTBOUND_DOORBELL_CLEAR, odr_cl); /* * Read the status register again to ensure the write to clear * is flushed to the controller. */ - (void) ddi_get32(cpq->odr_handle, cpq->odr); + (void) cpqary3_get32(cpq, CISS_I2O_OUTBOUND_DOORBELL_STATUS); } cpqary3_trigger_sw_isr(cpq); @@ -99,26 +100,14 @@ cpqary3_isr_hw_performant(caddr_t arg) return (DDI_INTR_CLAIMED); } -/* - * Function : cpqary3_sw_isr - * Description : This routine determines if this instance of the - * software interrupt handler was triggered by its - * respective h/w interrupt handler and if affermative - * processes the completed commands. - * Called By : kernel (Triggered by : cpqary3_hw_isr) - * Parameters : per-controller - * Calls : cpqary3_retrieve() - * Return Values: DDI_INTR_CLAIMED/UNCLAIMED - * [We either CLAIM the interrupr or DON'T] - */ uint_t -cpqary3_sw_isr(caddr_t arg) +cpqary3_isr_sw_simple(caddr_t arg) { cpqary3_t *cpq = (cpqary3_t *)arg; /* * Confirm that the hardware interrupt routine scheduled this - * software interrupt, and if so, acknowledge it. + * software interrupt. */ mutex_enter(&cpq->sw_mutex); mutex_enter(&cpq->hw_mutex); @@ -128,28 +117,40 @@ cpqary3_sw_isr(caddr_t arg) return (DDI_INTR_UNCLAIMED); } - switch (cpq->cpq_ctlr_mode) { - case CPQARY3_CTLR_MODE_SIMPLE: - cpqary3_retrieve_simple(cpq, 0, NULL); - /* - * XXX need to manage interrupts better - */ - if (!cpq->cpq_intr_off) { - cpqary3_intr_onoff(cpq, CPQARY3_INTR_ENABLE); - } - goto complete; + cpqary3_retrieve_simple(cpq, 0, NULL); + + /* + * Unmask the controller inbound data interrupt. + */ + if (!cpq->cpq_intr_off) { + cpqary3_intr_onoff(cpq, CPQARY3_INTR_ENABLE); + } + + cpq->cpq_swintr_flag = B_FALSE; + mutex_exit(&cpq->hw_mutex); + mutex_exit(&cpq->sw_mutex); + return (DDI_INTR_CLAIMED); +} - case CPQARY3_CTLR_MODE_PERFORMANT: - cpqary3_retrieve_performant(cpq, 0, NULL); - goto complete; +uint_t +cpqary3_isr_sw_performant(caddr_t arg) +{ + cpqary3_t *cpq = (cpqary3_t *)arg; - case CPQARY3_CTLR_MODE_UNKNOWN: - break; + /* + * Confirm that the hardware interrupt routine scheduled this + * software interrupt. + */ + mutex_enter(&cpq->sw_mutex); + mutex_enter(&cpq->hw_mutex); + if (!cpq->cpq_swintr_flag) { + mutex_exit(&cpq->hw_mutex); + mutex_exit(&cpq->sw_mutex); + return (DDI_INTR_UNCLAIMED); } - panic("unknown controller mode"); + cpqary3_retrieve_performant(cpq, 0, NULL); -complete: cpq->cpq_swintr_flag = B_FALSE; mutex_exit(&cpq->hw_mutex); mutex_exit(&cpq->sw_mutex); diff --git a/usr/src/uts/common/io/cpqary3/cpqary3_scsi.c b/usr/src/uts/common/io/cpqary3/cpqary3_scsi.c index bc87d1a9f3..2122990649 100644 --- a/usr/src/uts/common/io/cpqary3/cpqary3_scsi.c +++ b/usr/src/uts/common/io/cpqary3/cpqary3_scsi.c @@ -357,8 +357,6 @@ cpqary3_probe4LVs(cpqary3_t *cpqary3p) DTRACE_PROBE2(rll_cmd_send, CommandList_t *, cmdlistp, cpqary3_cmdpvt_t *, cpcm); - cpcm->cpcm_complete = cpqary3_synccmd_complete; - if (cpqary3_synccmd_send(cpqary3p, cpcm, 90000, CPQARY3_SYNCCMD_SEND_WAITSIG) != 0) { cpqary3_synccmd_free(cpqary3p, cpcm); @@ -391,7 +389,7 @@ cpqary3_probe4LVs(cpqary3_t *cpqary3p) log_lun_no = MAX_LOGDRV; } - cpqary3p->num_of_targets = log_lun_no; + cpqary3p->cpq_ntargets = log_lun_no; DTRACE_PROBE1(update_lvlun_count, ulong_t, log_lun_no); /* @@ -586,7 +584,7 @@ cpqary3_probe4Tapes(cpqary3_t *cpqary3p) * if the controller is SAS or CISS and then assigning the value of the * TAPE BASE accordingly */ - if (cpqary3p->bddef->bd_flags & SA_BD_SAS) { + if (cpqary3p->cpq_board->bd_flags & SA_BD_SAS) { ii = 0x41; /* MAX_LOGDRV + 1 - 64 + 1 */ } else { ii = 0x21; /* MAX_LOGDRV + 1 - 32 + 1 */ diff --git a/usr/src/uts/common/io/cpqary3/cpqary3_talk2ctlr.c b/usr/src/uts/common/io/cpqary3/cpqary3_talk2ctlr.c index 66fc0dbd14..d72ffd2159 100644 --- a/usr/src/uts/common/io/cpqary3/cpqary3_talk2ctlr.c +++ b/usr/src/uts/common/io/cpqary3/cpqary3_talk2ctlr.c @@ -41,20 +41,19 @@ uint8_t cpqary3_check_perf_e200_intr(cpqary3_t *cpqary3p); * FAILURE : It did not. */ uint8_t -cpqary3_check_simple_ctlr_intr(cpqary3_t *cpqary3p) +cpqary3_check_simple_ctlr_intr(cpqary3_t *cpq) { - uint32_t intr_pending_mask = 0; + uint32_t intr_pending_mask = cpq->cpq_board->bd_intrpendmask; /* * Read the Interrupt Status Register and * if bit 3 is set, it indicates that we have completed commands * in the controller */ - intr_pending_mask = cpqary3p->bddef->bd_intrpendmask; - if (intr_pending_mask & - (ddi_get32(cpqary3p->isr_handle, (uint32_t *)cpqary3p->isr))) + cpqary3_get32(cpq, CISS_I2O_INTERRUPT_STATUS)) { return (CPQARY3_SUCCESS); + } return (CPQARY3_FAILURE); } @@ -70,15 +69,15 @@ cpqary3_check_simple_ctlr_intr(cpqary3_t *cpqary3p) * FAILURE : It did not. */ uint8_t -cpqary3_check_perf_ctlr_intr(cpqary3_t *cpqary3p) +cpqary3_check_perf_ctlr_intr(cpqary3_t *cpq) { /* * Read the Interrupt Status Register and * if bit 3 is set, it indicates that we have completed commands * in the controller + * XXX _which_ bit? */ - if (0x1 & (ddi_get32(cpqary3p->isr_handle, - (uint32_t *)cpqary3p->isr))) { + if (cpqary3_get32(cpq, CISS_I2O_INTERRUPT_STATUS) & 0x1) { return (CPQARY3_SUCCESS); } @@ -96,15 +95,14 @@ cpqary3_check_perf_ctlr_intr(cpqary3_t *cpqary3p) * FAILURE : It did not. */ uint8_t -cpqary3_check_perf_e200_intr(cpqary3_t *cpqary3p) +cpqary3_check_perf_e200_intr(cpqary3_t *cpq) { /* * Read the Interrupt Status Register and * if bit 3 is set, it indicates that we have completed commands * in the controller */ - if (0x4 & (ddi_get32(cpqary3p->isr_handle, - (uint32_t *)cpqary3p->isr))) { + if (cpqary3_get32(cpq, CISS_I2O_INTERRUPT_STATUS) & 0x4) { return (CPQARY3_SUCCESS); } @@ -119,11 +117,12 @@ void cpqary3_retrieve_simple(cpqary3_t *cpq, uint32_t watchfor, boolean_t *found) { uint32_t opq; + uint32_t none = 0xffffffff; VERIFY(MUTEX_HELD(&cpq->hw_mutex)); VERIFY(MUTEX_HELD(&cpq->sw_mutex)); - while ((opq = ddi_get32(cpq->opq_handle, cpq->opq)) != 0xffffffff) { + while ((opq = cpqary3_get32(cpq, CISS_I2O_OUTBOUND_POST_Q)) != none) { cpqary3_command_t *cpcm; uint32_t tag = opq >> 2; /* XXX */ @@ -198,11 +197,11 @@ cpqary3_retrieve(cpqary3_t *cpq) switch (cpq->cpq_ctlr_mode) { case CPQARY3_CTLR_MODE_SIMPLE: cpqary3_retrieve_simple(cpq, 0, NULL); - return (CPQARY3_SUCCESS); + return (DDI_SUCCESS); case CPQARY3_CTLR_MODE_PERFORMANT: cpqary3_retrieve_performant(cpq, 0, NULL); - return (CPQARY3_SUCCESS); + return (DDI_SUCCESS); case CPQARY3_CTLR_MODE_UNKNOWN: break; @@ -243,7 +242,7 @@ cpqary3_poll_retrieve(cpqary3_t *cpq, uint32_t poll_tag) panic("unknown controller mode"); } - return (found ? CPQARY3_SUCCESS : CPQARY3_FAILURE); + return (found ? DDI_SUCCESS : DDI_FAILURE); } /* @@ -293,7 +292,7 @@ cpqary3_submit(cpqary3_t *cpq, cpqary3_command_t *cpcm) switch (cpq->cpq_ctlr_mode) { case CPQARY3_CTLR_MODE_SIMPLE: - ddi_put32(cpq->ipq_handle, cpq->ipq, cpcm->cpcm_pa_cmd); + cpqary3_put32(cpq, CISS_I2O_INBOUND_POST_Q, cpcm->cpcm_pa_cmd); break; case CPQARY3_CTLR_MODE_PERFORMANT: @@ -303,7 +302,7 @@ cpqary3_submit(cpqary3_t *cpq, cpqary3_command_t *cpcm) * (NB: from spec, the 0x1 here sets "pull from host memory" * mode, and the 0 represents "pull just one command record" */ - ddi_put32(cpq->ipq_handle, cpq->ipq, + cpqary3_put32(cpq, CISS_I2O_INBOUND_POST_Q, cpcm->cpcm_pa_cmd | 0 | 0x1); break; @@ -330,7 +329,7 @@ cpqary3_intr_onoff(cpqary3_t *cpq, uint8_t flag) /* * Read the Interrupt Mask Register. */ - uint32_t imr = ddi_get32(cpq->imr_handle, cpq->imr); + uint32_t imr = cpqary3_get32(cpq, CISS_I2O_INTERRUPT_MASK); VERIFY(flag == CPQARY3_INTR_ENABLE || flag == CPQARY3_INTR_DISABLE); @@ -345,14 +344,14 @@ cpqary3_intr_onoff(cpqary3_t *cpq, uint8_t flag) default: if (flag == CPQARY3_INTR_ENABLE) { - imr &= ~cpq->bddef->bd_intrmask; + imr &= ~cpq->cpq_board->bd_intrmask; } else { - imr |= cpq->bddef->bd_intrmask; + imr |= cpq->cpq_board->bd_intrmask; } break; } - ddi_put32(cpq->imr_handle, cpq->imr, imr); + cpqary3_put32(cpq, CISS_I2O_INTERRUPT_MASK, imr); } /* @@ -366,26 +365,26 @@ cpqary3_intr_onoff(cpqary3_t *cpq, uint8_t flag) * Return Values: None */ void -cpqary3_lockup_intr_onoff(cpqary3_t *cpqary3p, uint8_t flag) +cpqary3_lockup_intr_onoff(cpqary3_t *cpq, uint8_t flag) { /* * Read the Interrupt Mask Register. */ - uint32_t imr = ddi_get32(cpqary3p->imr_handle, cpqary3p->imr); + uint32_t imr = cpqary3_get32(cpq, CISS_I2O_INTERRUPT_MASK); /* * Enable or disable firmware lockup interrupts from the controller * based on the flag. */ if (flag == CPQARY3_LOCKUP_INTR_ENABLE) { - imr &= ~cpqary3p->bddef->bd_lockup_intrmask; + imr &= ~cpq->cpq_board->bd_lockup_intrmask; } else { VERIFY(flag == CPQARY3_LOCKUP_INTR_DISABLE); - imr |= cpqary3p->bddef->bd_lockup_intrmask; + imr |= cpq->cpq_board->bd_lockup_intrmask; } - ddi_put32(cpqary3p->imr_handle, cpqary3p->imr, imr); + cpqary3_put32(cpq, CISS_I2O_INTERRUPT_MASK, imr); } /* @@ -393,31 +392,31 @@ cpqary3_lockup_intr_onoff(cpqary3_t *cpqary3p, uint8_t flag) * writing to the Inbound Doorbell Register. The controller will, after some * number of seconds, acknowledge this by clearing the bit. * - * If successful, return CPQARY3_SUCCESS. If the controller takes too long to - * acknowledge, return CPQARY3_FAILURE. + * If successful, return DDI_SUCCESS. If the controller takes too long to + * acknowledge, return DDI_FAILURE. */ static int -cpqary3_cfgtbl_flush(cpqary3_t *cpqary3p) +cpqary3_cfgtbl_flush(cpqary3_t *cpq) { /* * Read the current value of the Inbound Doorbell Register. */ - uint32_t idr = ddi_get32(cpqary3p->idr_handle, cpqary3p->idr); + uint32_t idr = cpqary3_get32(cpq, CISS_I2O_INBOUND_DOORBELL); /* * Signal the Configuration Table change to the controller. */ idr |= CISS_IDR_BIT_CFGTBL_CHANGE; - ddi_put32(cpqary3p->idr_handle, cpqary3p->idr, idr); + cpqary3_put32(cpq, CISS_I2O_INBOUND_DOORBELL, idr); /* * Wait for the controller to acknowledge the change. */ for (unsigned i = 0; i < CISS_INIT_TIME; i++) { - idr = ddi_get32(cpqary3p->idr_handle, cpqary3p->idr); + idr = cpqary3_get32(cpq, CISS_I2O_INBOUND_DOORBELL); if ((idr & CISS_IDR_BIT_CFGTBL_CHANGE) == 0) { - return (CPQARY3_SUCCESS); + return (DDI_SUCCESS); } /* @@ -426,13 +425,13 @@ cpqary3_cfgtbl_flush(cpqary3_t *cpqary3p) delay(drv_usectohz(1000000)); } - dev_err(cpqary3p->dip, CE_WARN, "time out expired before controller " + dev_err(cpq->dip, CE_WARN, "time out expired before controller " "configuration completed"); - return (CPQARY3_FAILURE); + return (DDI_FAILURE); } static int -cpqary3_cfgtbl_transport_has_support(cpqary3_t *cpqary3p, int xport) +cpqary3_cfgtbl_transport_has_support(cpqary3_t *cpq, int xport) { VERIFY(xport == CISS_CFGTBL_XPORT_SIMPLE || xport == CISS_CFGTBL_XPORT_PERFORMANT); @@ -441,35 +440,35 @@ cpqary3_cfgtbl_transport_has_support(cpqary3_t *cpqary3p, int xport) * Read the current value of the TransportSupport field in the * Configuration Table. */ - uint32_t xport_active = ddi_get32(cpqary3p->ct_handle, - &cpqary3p->ct->TransportSupport); + uint32_t xport_active = ddi_get32(cpq->cpq_ct_handle, + &cpq->cpq_ct->TransportSupport); /* * Check that the desired transport method is supported by the * controller: */ if ((xport_active & xport) == 0) { - dev_err(cpqary3p->dip, CE_WARN, "controller does not support " + dev_err(cpq->dip, CE_WARN, "controller does not support " "method \"%s\"", xport == CISS_CFGTBL_XPORT_SIMPLE ? "simple" : "performant"); - return (CPQARY3_FAILURE); + return (DDI_FAILURE); } - return (CPQARY3_SUCCESS); + return (DDI_SUCCESS); } static void -cpqary3_cfgtbl_transport_set(cpqary3_t *cpqary3p, int xport) +cpqary3_cfgtbl_transport_set(cpqary3_t *cpq, int xport) { VERIFY(xport == CISS_CFGTBL_XPORT_SIMPLE || xport == CISS_CFGTBL_XPORT_PERFORMANT); - ddi_put32(cpqary3p->ct_handle, - &cpqary3p->ct->HostWrite.TransportRequest, xport); + ddi_put32(cpq->cpq_ct_handle, + &cpq->cpq_ct->HostWrite.TransportRequest, xport); } static int -cpqary3_cfgtbl_transport_confirm(cpqary3_t *cpqary3p, int xport) +cpqary3_cfgtbl_transport_confirm(cpqary3_t *cpq, int xport) { VERIFY(xport == CISS_CFGTBL_XPORT_SIMPLE || xport == CISS_CFGTBL_XPORT_PERFORMANT); @@ -478,52 +477,52 @@ cpqary3_cfgtbl_transport_confirm(cpqary3_t *cpqary3p, int xport) * Read the current value of the TransportActive field in the * Configuration Table. */ - uint32_t xport_active = ddi_get32(cpqary3p->ct_handle, - &cpqary3p->ct->TransportActive); + uint32_t xport_active = ddi_get32(cpq->cpq_ct_handle, + &cpq->cpq_ct->TransportActive); /* * Check that the desired transport method is now active: */ if ((xport_active & xport) == 0) { - dev_err(cpqary3p->dip, CE_WARN, "failed to enable transport " + dev_err(cpq->dip, CE_WARN, "failed to enable transport " "method \"%s\"", xport == CISS_CFGTBL_XPORT_SIMPLE ? "simple" : "performant"); - return (CPQARY3_FAILURE); + return (DDI_FAILURE); } /* * Ensure that the controller is now ready to accept commands. */ if ((xport_active & CISS_CFGTBL_READY_FOR_COMMANDS) == 0) { - dev_err(cpqary3p->dip, CE_WARN, "controller not ready to " + dev_err(cpq->dip, CE_WARN, "controller not ready to " "accept commands"); - return (CPQARY3_FAILURE); + return (DDI_FAILURE); } - return (CPQARY3_SUCCESS); + return (DDI_SUCCESS); } -uint32_t +static uint32_t cpqary3_ctlr_get_cmdsoutmax(cpqary3_t *cpq) { uint32_t val; if (cpq->cpq_ctlr_mode == CPQARY3_CTLR_MODE_PERFORMANT) { - if ((val = ddi_get32(cpq->ct_handle, - &cpq->ct->MaxPerfModeCmdsOutMax)) != 0) { + if ((val = ddi_get32(cpq->cpq_ct_handle, + &cpq->cpq_ct->MaxPerfModeCmdsOutMax)) != 0) { return (val); } } - return (ddi_get32(cpq->ct_handle, &cpq->ct->CmdsOutMax)); + return (ddi_get32(cpq->cpq_ct_handle, &cpq->cpq_ct->CmdsOutMax)); } -uint32_t +static uint32_t cpqary3_ctlr_get_hostdrvsup(cpqary3_t *cpq) { - if ((!cpq->bddef->bd_is_e200) && (!cpq->bddef->bd_is_ssll)) { - uint32_t val = ddi_get32(cpq->ct_handle, - &cpq->ct->HostDrvrSupport); + if (!cpq->cpq_board->bd_is_e200 && !cpq->cpq_board->bd_is_ssll) { + uint32_t val = ddi_get32(cpq->cpq_ct_handle, + &cpq->cpq_ct->HostDrvrSupport); /* * XXX This is "bit 2" in the "Host Driver Specific Support" @@ -536,43 +535,57 @@ cpqary3_ctlr_get_hostdrvsup(cpqary3_t *cpq) */ val |= 0x04; - ddi_put32(cpq->ct_handle, &cpq->ct->HostDrvrSupport, val); + ddi_put32(cpq->cpq_ct_handle, &cpq->cpq_ct->HostDrvrSupport, + val); } - return (ddi_get32(cpq->ct_handle, &cpq->ct->HostDrvrSupport)); + return (ddi_get32(cpq->cpq_ct_handle, &cpq->cpq_ct->HostDrvrSupport)); } -int +static int cpqary3_ctlr_init_simple(cpqary3_t *cpq) { VERIFY(cpq->cpq_ctlr_mode == CPQARY3_CTLR_MODE_UNKNOWN); if (cpqary3_cfgtbl_transport_has_support(cpq, - CISS_CFGTBL_XPORT_SIMPLE) != CPQARY3_SUCCESS) { - return (ENOTTY); + CISS_CFGTBL_XPORT_SIMPLE) != DDI_SUCCESS) { + return (DDI_FAILURE); } cpq->cpq_ctlr_mode = CPQARY3_CTLR_MODE_SIMPLE; - if ((cpq->ctlr_maxcmds = cpqary3_ctlr_get_cmdsoutmax(cpq)) == 0) { + /* + * Disable device interrupts while we are setting up. + */ + cpqary3_intr_onoff(cpq, CPQARY3_INTR_DISABLE); + + if ((cpq->cpq_maxcmds = cpqary3_ctlr_get_cmdsoutmax(cpq)) == 0) { dev_err(cpq->dip, CE_WARN, "maximum outstanding commands set " "to zero"); - return (EPROTO); + return (DDI_FAILURE); } - cpq->sg_cnt = CPQARY3_SG_CNT; + /* + * XXX ? + */ + cpq->cpq_sg_cnt = CPQARY3_SG_CNT; + + /* + * Zero the upper 32 bits of the address in the Controller. + */ + ddi_put32(cpq->cpq_ct_handle, &cpq->cpq_ct->HostWrite.Upper32Addr, 0); /* * Set the Transport Method and flush the changes to the * Configuration Table. */ cpqary3_cfgtbl_transport_set(cpq, CISS_CFGTBL_XPORT_SIMPLE); - if (cpqary3_cfgtbl_flush(cpq) != CPQARY3_SUCCESS) { - return (EPROTO); + if (cpqary3_cfgtbl_flush(cpq) != DDI_SUCCESS) { + return (DDI_FAILURE); } if (cpqary3_cfgtbl_transport_confirm(cpq, - CISS_CFGTBL_XPORT_SIMPLE) != CPQARY3_SUCCESS) { - return (EPROTO); + CISS_CFGTBL_XPORT_SIMPLE) != DDI_SUCCESS) { + return (DDI_FAILURE); } /* @@ -580,33 +593,28 @@ cpqary3_ctlr_init_simple(cpqary3_t *cpq) * driver did. */ uint32_t check_again = cpqary3_ctlr_get_cmdsoutmax(cpq); - if (check_again != cpq->ctlr_maxcmds) { + if (check_again != cpq->cpq_maxcmds) { dev_err(cpq->dip, CE_WARN, "maximum outstanding commands " "changed during initialisation (was %u, now %u)", - cpq->ctlr_maxcmds, check_again); - return (EPROTO); + cpq->cpq_maxcmds, check_again); + return (DDI_FAILURE); } - /* - * Zero the upper 32 bits of the address in the Controller. - */ - ddi_put32(cpq->ct_handle, &cpq->ct->HostWrite.Upper32Addr, 0); - +#if 0 /* * Set the controller interrupt check routine. */ cpq->check_ctlr_intr = cpqary3_check_simple_ctlr_intr; +#endif - cpq->host_support = cpqary3_ctlr_get_hostdrvsup(cpq); - - return (0); + return (DDI_SUCCESS); } /* * XXX */ #if 0 -int +static int cpqary3_ctlr_init_performant(cpqary3_t *cpq) { cpqary3_replyq_t *cprq = &cpq->cpq_replyq; @@ -614,7 +622,7 @@ cpqary3_ctlr_init_performant(cpqary3_t *cpq) VERIFY(cpq->cpq_ctlr_mode == CPQARY3_CTLR_MODE_UNKNOWN); if (cpqary3_cfgtbl_transport_has_support(cpq, - CISS_CFGTBL_XPORT_PERFORMANT) != CPQARY3_SUCCESS) { + CISS_CFGTBL_XPORT_PERFORMANT) != DDI_SUCCESS) { return (ENOTTY); } cpq->cpq_ctlr_mode = CPQARY3_CTLR_MODE_PERFORMANT; @@ -688,12 +696,12 @@ cpqary3_ctlr_init_performant(cpqary3_t *cpq) * Configuration Table. */ cpqary3_cfgtbl_transport_set(cpq, CISS_CFGTBL_XPORT_PERFORMANT); - if (cpqary3_cfgtbl_flush(cpq) != CPQARY3_SUCCESS) { + if (cpqary3_cfgtbl_flush(cpq) != DDI_SUCCESS) { return (EPROTO); } if (cpqary3_cfgtbl_transport_confirm(cpq, - CISS_CFGTBL_XPORT_PERFORMANT) != CPQARY3_SUCCESS) { + CISS_CFGTBL_XPORT_PERFORMANT) != DDI_SUCCESS) { return (EPROTO); } @@ -750,45 +758,19 @@ cpqary3_ctlr_init_performant(cpqary3_t *cpq) DDI_PUT32(cpq, &ctp->HostWrite.Upper32Addr, 0x00000000); - /* Set the controller interrupt check routine */ - - if (cpq->bddef->bd_is_e200) { - cpq->check_ctlr_intr = cpqary3_check_perf_e200_intr; - } else { - cpq->check_ctlr_intr = cpqary3_check_perf_ctlr_intr; - } - - cpq->host_support = cpqary3_ctlr_get_hostdrvsup(cpq); - return (0); } #endif int -cpqary3_ctlr_init(cpqary3_t *cpqary3p) +cpqary3_ctlr_init(cpqary3_t *cpq) { - uint8_t signature[4] = { 'C', 'I', 'S', 'S' }; - CfgTable_t *ctp = cpqary3p->ct; - cpqary3_phyctg_t *cpqary3_phyctgp; - uint32_t phy_addr; - size_t cmd_size; - uint32_t queue_depth; - uint32_t CmdsOutMax; - uint32_t BlockFetchCnt[8]; - caddr_t replyq_start_addr = NULL; - /* SG */ - uint32_t max_blk_fetch_cnt = 0; - uint32_t max_sg_cnt = 0; - uint32_t optimal_sg = 0; - uint32_t optimal_sg_size = 0; - /* Header + Request + Error */ - uint32_t size_of_HRE = 0; - uint32_t size_of_cmdlist = 0; - /* SG */ + uint8_t signature[4] = { 'C', 'I', 'S', 'S' }; + CfgTable_t *ctp = cpq->cpq_ct; int e; - if ((e = cpqary3_ctlr_wait_for_state(cpqary3p, - CPQARY3_WAIT_STATE_READY) != 0)) { + if ((e = cpqary3_ctlr_wait_for_state(cpq, + CPQARY3_WAIT_STATE_READY) != DDI_SUCCESS)) { return (e); } @@ -798,17 +780,14 @@ cpqary3_ctlr_init(cpqary3_t *cpqary3p) * See: "9.1 Configuration Table" in CISS Specification. */ for (unsigned i = 0; i < 4; i++) { - if (ddi_get8(cpqary3p->ct_handle, &ctp->Signature[i]) != + if (ddi_get8(cpq->cpq_ct_handle, &cpq->cpq_ct->Signature[i]) != signature[i]) { - dev_err(cpqary3p->dip, CE_WARN, "invalid signature " + dev_err(cpq->dip, CE_WARN, "invalid signature " "detected"); - return (EPROTO); + return (DDI_FAILURE); } } - /* - * XXX Let's just do Simple mode for now... - */ #if 0 if (!(cpqary3p->bddef->bd_flags & SA_BD_SAS)) { if ((e = cpqary3_ctlr_init_simple(cpqary3p)) != 0) { @@ -820,18 +799,23 @@ cpqary3_ctlr_init(cpqary3_t *cpqary3p) } } #else - if ((e = cpqary3_ctlr_init_simple(cpqary3p)) != 0) { + /* + * XXX Let's just do Simple mode for now... + */ + if ((e = cpqary3_ctlr_init_simple(cpq)) != 0) { return (e); } #endif + cpq->cpq_host_support = cpqary3_ctlr_get_hostdrvsup(cpq); + /* * Read initial controller heartbeat value and mark the current * reading time. */ - cpqary3p->cpq_last_heartbeat = ddi_get32(cpqary3p->ct_handle, - &ctp->HeartBeat); - cpqary3p->cpq_last_heartbeat_lbolt = ddi_get_lbolt(); + cpq->cpq_last_heartbeat = ddi_get32(cpq->cpq_ct_handle, + &cpq->cpq_ct->HeartBeat); + cpq->cpq_last_heartbeat_lbolt = ddi_get_lbolt(); return (0); } @@ -852,18 +836,18 @@ cpqary3_ctlr_wait_for_state(cpqary3_t *cpq, cpqary3_wait_state_t state) * seconds, give up. */ for (unsigned i = 0; i < CPQARY3_WAIT_DELAY_SECONDS; i++) { - uint32_t spr = ddi_get32(cpq->spr0_handle, cpq->spr0); + uint32_t spr = cpqary3_get32(cpq, CISS_I2O_SCRATCHPAD); switch (state) { case CPQARY3_WAIT_STATE_READY: if (spr == CISS_SCRATCHPAD_INITIALISED) { - return (0); + return (DDI_SUCCESS); } break; case CPQARY3_WAIT_STATE_UNREADY: if (spr != CISS_SCRATCHPAD_INITIALISED) { - return (0); + return (DDI_SUCCESS); } break; } @@ -877,5 +861,5 @@ cpqary3_ctlr_wait_for_state(cpqary3_t *cpq, cpqary3_wait_state_t state) dev_err(cpq->dip, CE_WARN, "time out waiting for controller " "to enter state \"%s\"", state == CPQARY3_WAIT_STATE_READY ? "ready": "unready"); - return (ETIMEDOUT); + return (DDI_FAILURE); } diff --git a/usr/src/uts/common/io/cpqary3/cpqary3_transport.c b/usr/src/uts/common/io/cpqary3/cpqary3_transport.c index b729ae6022..15a751a2b0 100644 --- a/usr/src/uts/common/io/cpqary3/cpqary3_transport.c +++ b/usr/src/uts/common/io/cpqary3/cpqary3_transport.c @@ -121,7 +121,7 @@ cpqary3_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip, extern int8_t cpqary3_detect_target_geometry(cpqary3_t *); if ((CPQARY3_SUCCESS == cpqary3_probe4targets(ctlr)) && - (ctlr->num_of_targets > 0)) { + (ctlr->cpq_ntargets > 0)) { (void) cpqary3_detect_target_geometry(ctlr); } @@ -187,7 +187,7 @@ cpqary3_tgt_probe(struct scsi_device *sd, int (*waitfunc)()) cpqary3_t *ctlr = hba_tran->tran_hba_private; if ((CPQARY3_SUCCESS == cpqary3_probe4targets(ctlr)) && - (ctlr->num_of_targets > 0)) { + (ctlr->cpq_ntargets > 0)) { (void) cpqary3_detect_target_geometry(ctlr); } /* HPQacucli Changes */ @@ -345,10 +345,7 @@ cpqary3_dma_alloc(cpqary3_t *cpqary3p, struct scsi_pkt *scsi_pktp, } tmp_dma_attr = cpqary3_dma_attr; - - /* SG */ - tmp_dma_attr.dma_attr_sgllen = cpqary3p->sg_cnt; - /* SG */ + tmp_dma_attr.dma_attr_sgllen = cpqary3p->cpq_sg_cnt; cb = (callback == NULL_FUNC) ? DDI_DMA_DONTWAIT : DDI_DMA_SLEEP; @@ -429,7 +426,7 @@ cpqary3_dma_alloc(cpqary3_t *cpqary3p, struct scsi_pkt *scsi_pktp, cpqary3_pktp->cmd_dmacookies[i++].dmac_size; /* SG */ /* Check Out for Limits */ - if (i == cpqary3p->sg_cnt || + if (i == cpqary3p->cpq_sg_cnt || i == cpqary3_pktp->cmd_ncookies) break; /* SG */ @@ -529,7 +526,7 @@ cpqary3_dma_move(struct scsi_pkt *scsi_pktp, struct buf *bp, cpqary3_pktp->cmd_cookie++; /* SG */ /* no. of DATA SEGMENTS */ - if (i == cpqary3p->sg_cnt || + if (i == cpqary3p->cpq_sg_cnt || cpqary3_pktp->cmd_cookie == cpqary3_pktp->cmd_ncookies) { break; } @@ -607,7 +604,7 @@ cpqary3_transport(struct scsi_address *sa, struct scsi_pkt *scsi_pktp) DDI_DMA_SYNC_FORDEV); } - VERIFY(cpqary3_pktp->cmd_cookiecnt <= ctlr->sg_cnt); + VERIFY(cpqary3_pktp->cmd_cookiecnt <= ctlr->cpq_sg_cnt); cpcm->cpcm_complete = cpqary3_oscmd_complete; @@ -956,7 +953,7 @@ cpqary3_handle_flag_nointr(cpqary3_command_t *cpcm, struct scsi_pkt *scsi_pktp) mutex_enter(&ctlr->hw_mutex); ctlr->cpq_intr_off = B_TRUE; cpqary3_intr_onoff(ctlr, CPQARY3_INTR_DISABLE); - if (ctlr->host_support & 0x4) + if (ctlr->cpq_host_support & 0x4) cpqary3_lockup_intr_onoff(ctlr, CPQARY3_LOCKUP_INTR_DISABLE); while (avl_numnodes(&ctlr->cpq_inflight) > 0) { @@ -967,7 +964,7 @@ cpqary3_handle_flag_nointr(cpqary3_command_t *cpcm, struct scsi_pkt *scsi_pktp) if (cpqary3_submit(ctlr, cpcm) != 0) { ctlr->cpq_intr_off = B_FALSE; cpqary3_intr_onoff(ctlr, CPQARY3_INTR_ENABLE); - if (ctlr->host_support & 0x4) { + if (ctlr->cpq_host_support & 0x4) { cpqary3_lockup_intr_onoff(ctlr, CPQARY3_LOCKUP_INTR_ENABLE); } @@ -986,7 +983,7 @@ cpqary3_handle_flag_nointr(cpqary3_command_t *cpcm, struct scsi_pkt *scsi_pktp) ctlr->cpq_intr_off = B_FALSE; cpqary3_intr_onoff(ctlr, CPQARY3_INTR_ENABLE); - if (ctlr->host_support & 0x4) { + if (ctlr->cpq_host_support & 0x4) { cpqary3_lockup_intr_onoff(ctlr, CPQARY3_LOCKUP_INTR_ENABLE); } @@ -1000,7 +997,7 @@ cpqary3_handle_flag_nointr(cpqary3_command_t *cpcm, struct scsi_pkt *scsi_pktp) ctlr->cpq_intr_off = B_FALSE; cpqary3_intr_onoff(ctlr, CPQARY3_INTR_ENABLE); - if (ctlr->host_support & 0x4) { + if (ctlr->cpq_host_support & 0x4) { cpqary3_lockup_intr_onoff(ctlr, CPQARY3_LOCKUP_INTR_ENABLE); } diff --git a/usr/src/uts/common/io/cpqary3/cpqary3_util.c b/usr/src/uts/common/io/cpqary3/cpqary3_util.c index 650871870c..88d3a6852f 100644 --- a/usr/src/uts/common/io/cpqary3/cpqary3_util.c +++ b/usr/src/uts/common/io/cpqary3/cpqary3_util.c @@ -17,63 +17,14 @@ #include <sys/sdt.h> #include "cpqary3.h" -/* - * Local Functions Definitions - */ - -int cpqary3_target_geometry(struct scsi_address *); -int8_t cpqary3_detect_target_geometry(cpqary3_t *); - -/* - * Function : cpqary3_read_conf_file - * Description : This routine reads the driver configuration file. - * Called By : cpqary3_attach() - * Parameters : device-information pointer, per_controller - * Calls : None - * Return Values: None - */ -void -cpqary3_read_conf_file(dev_info_t *dip, cpqary3_t *cpqary3p) -{ - char *ptr; - - cpqary3p->noe_support = 0; - - /* - * Plugin the code necessary to read from driver's conf file. - * As of now, we are not interested in reading the onf file - * for any purpose. - * - * eg. : - * - * retvalue = ddi_getprop(DDI_DEV_T_NONE, dip, DDI_PROP_DONTPASS, - * "cpqary3_online_debug", -1); - */ - - /* - * We are calling ddi_prop_lookup_string - * which gets the property value, which is passed at - * the grub menu. - */ - if (ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, 0, - "cpqary3_noesupport", &ptr) == DDI_PROP_SUCCESS) { - if (strcmp("on", ptr) == 0) { - cpqary3p->noe_support = 1; - } - if (strcmp("off", ptr) == 0) { - cpqary3p->noe_support = 0; - } - ddi_prop_free(ptr); - } -} - void cpqary3_lockup_check(cpqary3_t *cpq) { /* * Read the current controller heartbeat value. */ - uint32_t heartbeat = ddi_get32(cpq->ct_handle, &cpq->ct->HeartBeat); + uint32_t heartbeat = ddi_get32(cpq->cpq_ct_handle, + &cpq->cpq_ct->HeartBeat); /* * Check to see if the value is the same as last time we looked: @@ -95,8 +46,8 @@ cpqary3_lockup_check(cpqary3_t *cpq) * If the firmware can tell it has flown off the rails, why not * simply reset the controller? */ - uint32_t odr = ddi_get32(cpq->odr_handle, cpq->odr); - uint32_t spr = ddi_get32(cpq->spr0_handle, cpq->spr0); + uint32_t odr = cpqary3_get32(cpq, CISS_I2O_OUTBOUND_DOORBELL_STATUS); + uint32_t spr = cpqary3_get32(cpq, CISS_I2O_SCRATCHPAD); if ((odr & CISS_ODR_BIT_LOCKUP) != 0) { dev_err(cpq->dip, CE_PANIC, "HP SmartArray firmware has " "reported a critical fault (odr %08x spr %08x)", @@ -129,6 +80,9 @@ cpqary3_periodic(void *arg) cpqary3_lockup_check(cpq); + mutex_enter(&cpq->hw_mutex); + mutex_exit(&cpq->hw_mutex); + /* * XXX This should be re-tooled to use "cpq_inflight". */ @@ -195,95 +149,6 @@ cpqary3_lookup_inflight(cpqary3_t *cpq, uint32_t tag) return (avl_find(&cpq->cpq_inflight, &srch, NULL)); } -static int -cpqary3_comparator(const void *lp, const void *rp) -{ - const cpqary3_command_t *l = lp; - const cpqary3_command_t *r = rp; - - if (l->cpcm_tag > r->cpcm_tag) { - return (1); - } else if (l->cpcm_tag < r->cpcm_tag) { - return (-1); - } else { - return (0); - } -} - -/* - * Function : cpqary3_init_ctlr_resource - * Description : This routine initializes the command list, initializes - * the controller, enables the interrupt. - * Called By : cpqary3_attach() - * Parameters : per_controller - * Calls : cpqary3_init_ctlr(), cpqary3_meminit(), - * cpqary3_intr_onoff(), - * Return Values: SUCCESS / FAILURE - * [ Shall return failure if any of the mandatory - * initializations / setup of resources fail ] - */ -uint16_t -cpqary3_init_ctlr_resource(cpqary3_t *ctlr) -{ - list_create(&ctlr->cpq_commands, sizeof (cpqary3_command_t), - offsetof(cpqary3_command_t, cpcm_link)); - avl_create(&ctlr->cpq_inflight, cpqary3_comparator, - sizeof (cpqary3_command_t), offsetof(cpqary3_command_t, cpcm_node)); - - /* - * Initialize the Controller - * Alocate Memory Pool for driver supported number of Commands - * return if not successful - * Allocate target structure for controller and initialize the same - * Detect all existing targets and allocate target structure for each - * Determine geometry for all existing targets - * Initialize the condition variables - */ - if (cpqary3_ctlr_init(ctlr) != 0) { - dev_err(ctlr->dip, CE_WARN, "cpqary3_ctlr_init failed"); - return (CPQARY3_FAILURE); - } - - /* - * XXX - */ -#if 0 - if (cpqary3_meminit(ctlr) != CPQARY3_SUCCESS) { - return (CPQARY3_FAILURE); - } -#endif - - ctlr->cpqary3_tgtp[CTLR_SCSI_ID] = kmem_zalloc(sizeof (cpqary3_tgt_t), - KM_NOSLEEP); - if (!(ctlr->cpqary3_tgtp[CTLR_SCSI_ID])) { - cmn_err(CE_WARN, "CPQary3: Target Initialization Failed"); -#if 0 - cpqary3_memfini(ctlr, CPQARY3_MEMLIST_DONE | - CPQARY3_PHYCTGS_DONE | CPQARY3_CMDMEM_DONE); -#endif - return (CPQARY3_FAILURE); - } - ctlr->cpqary3_tgtp[CTLR_SCSI_ID]->type = CPQARY3_TARGET_CTLR; - - cpqary3_intr_onoff(ctlr, CPQARY3_INTR_DISABLE); - - /* - * Initialize all condition variables : - * for the immediate call back - * for the disable noe - * for fulsh cache - * for probe device - */ - - cv_init(&ctlr->cv_immediate_wait, NULL, CV_DRIVER, NULL); - cv_init(&ctlr->cv_noe_wait, NULL, CV_DRIVER, NULL); - cv_init(&ctlr->cv_flushcache_wait, NULL, CV_DRIVER, NULL); - cv_init(&ctlr->cv_abort_wait, NULL, CV_DRIVER, NULL); - cv_init(&ctlr->cv_ioctl_wait, NULL, CV_DRIVER, NULL); - - return (CPQARY3_SUCCESS); -} - /* * Function : cpqary3_target_geometry * Description : This function returns the geometry for the target. @@ -328,6 +193,7 @@ cpqary3_synccmd_alloc(cpqary3_t *cpq, size_t bufsz) } cpcm->cpcm_type = CPQARY3_CMDTYPE_SYNCCMD; + cpcm->cpcm_complete = cpqary3_synccmd_complete; if (bufsz == 0) { return (cpcm); @@ -430,6 +296,8 @@ cpqary3_synccmd_send(cpqary3_t *cpqary3p, cpqary3_command_t *cpcm, boolean_t waitsig = B_FALSE; int rc = 0; + VERIFY(cpcm->cpcm_type == CPQARY3_CMDTYPE_SYNCCMD); + /* compute absolute timeout, if necessary */ if (timeoutms > 0) { absto = ddi_get_lbolt() + drv_usectohz(timeoutms * 1000); @@ -568,7 +436,7 @@ cpqary3_detect_target_geometry(cpqary3_t *ctlr) * the next logical drive in the per-target structure */ - for (i = 0; ld_count < ctlr->num_of_targets; i++) { + for (i = 0; ld_count < ctlr->cpq_ntargets; i++) { if (i == CTLR_SCSI_ID || ctlr->cpqary3_tgtp[i] == NULL) { /* Go to the Next logical target */ continue; |