summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoshua M. Clulow <jmc@joyent.com>2016-02-29 12:39:09 +0000
committerJoshua M. Clulow <jmc@joyent.com>2016-07-06 16:25:17 +0000
commitc3b58fd859e47742b9e811e92a621698849fcd0b (patch)
tree13c9ba4fbfe6e4c02357d66b801ab110fc4252e7
parenteb1a2ded8c853329cb42a322e537fbef32fd14af (diff)
downloadillumos-joyent-c3b58fd859e47742b9e811e92a621698849fcd0b.tar.gz
XXX some refactoring of attach, mappings, etc
-rw-r--r--usr/src/uts/common/Makefile.files2
-rw-r--r--usr/src/uts/common/io/cpqary3/cpqary3.c809
-rw-r--r--usr/src/uts/common/io/cpqary3/cpqary3.h117
-rw-r--r--usr/src/uts/common/io/cpqary3/cpqary3_ciss.h123
-rw-r--r--usr/src/uts/common/io/cpqary3/cpqary3_device.c256
-rw-r--r--usr/src/uts/common/io/cpqary3/cpqary3_interrupts.c102
-rw-r--r--usr/src/uts/common/io/cpqary3/cpqary3_ioctl.c170
-rw-r--r--usr/src/uts/common/io/cpqary3/cpqary3_ioctl.h29
-rw-r--r--usr/src/uts/common/io/cpqary3/cpqary3_isr.c77
-rw-r--r--usr/src/uts/common/io/cpqary3/cpqary3_scsi.c6
-rw-r--r--usr/src/uts/common/io/cpqary3/cpqary3_talk2ctlr.c248
-rw-r--r--usr/src/uts/common/io/cpqary3/cpqary3_transport.c23
-rw-r--r--usr/src/uts/common/io/cpqary3/cpqary3_util.c154
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)&regp, &reglen) != 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 **)&regs, &regslen) !=
+ 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;