180c94ecdSKeith M Wesolowski /*
280c94ecdSKeith M Wesolowski  * This file and its contents are supplied under the terms of the
380c94ecdSKeith M Wesolowski  * Common Development and Distribution License ("CDDL"), version 1.0.
480c94ecdSKeith M Wesolowski  * You may only use this file in accordance with the terms of version
580c94ecdSKeith M Wesolowski  * 1.0 of the CDDL.
680c94ecdSKeith M Wesolowski  *
780c94ecdSKeith M Wesolowski  * A full copy of the text of the CDDL should have accompanied this
880c94ecdSKeith M Wesolowski  * source.  A copy of the CDDL is also available via the Internet at
980c94ecdSKeith M Wesolowski  * http://www.illumos.org/license/CDDL.
1080c94ecdSKeith M Wesolowski  */
1180c94ecdSKeith M Wesolowski 
1280c94ecdSKeith M Wesolowski /*
1380c94ecdSKeith M Wesolowski  * Copyright (C) 2013 Hewlett-Packard Development Company, L.P.
1480c94ecdSKeith M Wesolowski  */
1580c94ecdSKeith M Wesolowski 
1680c94ecdSKeith M Wesolowski #include "cpqary3.h"
1780c94ecdSKeith M Wesolowski 
1880c94ecdSKeith M Wesolowski /*
1980c94ecdSKeith M Wesolowski  * Local Autoconfiguration Function Prototype Declations
2080c94ecdSKeith M Wesolowski  */
2180c94ecdSKeith M Wesolowski 
2280c94ecdSKeith M Wesolowski int cpqary3_attach(dev_info_t *, ddi_attach_cmd_t);
2380c94ecdSKeith M Wesolowski int cpqary3_detach(dev_info_t *, ddi_detach_cmd_t);
2480c94ecdSKeith M Wesolowski int cpqary3_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
2580c94ecdSKeith M Wesolowski 
2680c94ecdSKeith M Wesolowski /*
2780c94ecdSKeith M Wesolowski  * Local Functions Definitions
2880c94ecdSKeith M Wesolowski  */
2980c94ecdSKeith M Wesolowski 
3080c94ecdSKeith M Wesolowski static void cpqary3_cleanup(cpqary3_t *, uint32_t);
3180c94ecdSKeith M Wesolowski static uint8_t cpqary3_update_ctlrdetails(cpqary3_t *, uint32_t *);
3280c94ecdSKeith M Wesolowski int8_t cpqary3_detect_target_geometry(cpqary3_t *);
3380c94ecdSKeith M Wesolowski 
3480c94ecdSKeith M Wesolowski /*
3580c94ecdSKeith M Wesolowski  * External Variable Definitions
3680c94ecdSKeith M Wesolowski  */
3780c94ecdSKeith M Wesolowski 
3880c94ecdSKeith M Wesolowski extern cpqary3_driver_info_t gdriver_info;
3980c94ecdSKeith M Wesolowski 
4080c94ecdSKeith M Wesolowski /*
4180c94ecdSKeith M Wesolowski  * Global Variables Definitions
4280c94ecdSKeith M Wesolowski  */
4380c94ecdSKeith M Wesolowski 
44*b8aa3defSJoshua M. Clulow static char cpqary3_brief[]    =	"HP Smart Array (Legacy)";
4580c94ecdSKeith M Wesolowski void *cpqary3_state;
4680c94ecdSKeith M Wesolowski 
4780c94ecdSKeith M Wesolowski /* HPQaculi Changes */
4880c94ecdSKeith M Wesolowski 
4980c94ecdSKeith M Wesolowski /*
5080c94ecdSKeith M Wesolowski  * HBA minor number schema
5180c94ecdSKeith M Wesolowski  *
5280c94ecdSKeith M Wesolowski  * The minor numbers for any minor device nodes that we create are
5380c94ecdSKeith M Wesolowski  * governed by the SCSA framework.  We use the macros below to
5480c94ecdSKeith M Wesolowski  * fabricate minor numbers for nodes that we own.
5580c94ecdSKeith M Wesolowski  *
5680c94ecdSKeith M Wesolowski  * See sys/impl/transport.h for more info.
5780c94ecdSKeith M Wesolowski  */
5880c94ecdSKeith M Wesolowski 
5980c94ecdSKeith M Wesolowski /* Macro to extract interface from minor number */
6080c94ecdSKeith M Wesolowski #define	CPQARY3_MINOR2INTERFACE(_x)  ((_x) & (TRAN_MINOR_MASK))
6180c94ecdSKeith M Wesolowski 
6280c94ecdSKeith M Wesolowski /* Base of range assigned to HBAs: */
6380c94ecdSKeith M Wesolowski #define	SCSA_MINOR_HBABASE  (32)
6480c94ecdSKeith M Wesolowski 
6580c94ecdSKeith M Wesolowski /* Our minor nodes: */
6680c94ecdSKeith M Wesolowski #define	CPQARY3_MINOR  (0 + SCSA_MINOR_HBABASE)
6780c94ecdSKeith M Wesolowski 
6880c94ecdSKeith M Wesolowski /* Convenience macros to convert device instances to minor numbers */
6980c94ecdSKeith M Wesolowski #define	CPQARY3_INST2x(_i, _x)    (((_i) << INST_MINOR_SHIFT) | (_x))
7080c94ecdSKeith M Wesolowski #define	CPQARY3_INST2CPQARY3(_i)  CPQARY3_INST2x(_i, CPQARY3_MINOR)
7180c94ecdSKeith M Wesolowski 
7280c94ecdSKeith M Wesolowski /* HPQacucli Changes */
7380c94ecdSKeith M Wesolowski 
7480c94ecdSKeith M Wesolowski /*
7580c94ecdSKeith M Wesolowski  * The Driver DMA Limit structure.
7680c94ecdSKeith M Wesolowski  * Data used for SMART Integrated Array Controller shall be used.
7780c94ecdSKeith M Wesolowski  */
7880c94ecdSKeith M Wesolowski 
7980c94ecdSKeith M Wesolowski ddi_dma_attr_t cpqary3_dma_attr = {
8080c94ecdSKeith M Wesolowski 	DMA_ATTR_V0,		/* ddi_dma_attr version */
8180c94ecdSKeith M Wesolowski 	0,			/* Low Address */
8280c94ecdSKeith M Wesolowski 	0xFFFFFFFFFFFFFFFF,	/* High Address */
8380c94ecdSKeith M Wesolowski 	0x00FFFFFF,		/* Max DMA Counter register */
8480c94ecdSKeith M Wesolowski 	0x20,			/* Byte Alignment */
8580c94ecdSKeith M Wesolowski 	0x20,			/* Burst Sizes : 32 Byte */
8680c94ecdSKeith M Wesolowski 	DMA_UNIT_8,		/* Minimum DMA xfer Size */
8780c94ecdSKeith M Wesolowski 	0xFFFFFFFF,		/* Maximum DMA xfer Size */
8880c94ecdSKeith M Wesolowski 	/*
8980c94ecdSKeith M Wesolowski 	 * Segment boundary restrictions
9080c94ecdSKeith M Wesolowski 	 * The addr should not cross 4GB boundry.
9180c94ecdSKeith M Wesolowski 	 * This is required to address an issue
9280c94ecdSKeith M Wesolowski 	 * in the Surge ASIC, with earlier FW versions.
9380c94ecdSKeith M Wesolowski 	 */
9480c94ecdSKeith M Wesolowski 	0xFFFFFFFF,
9580c94ecdSKeith M Wesolowski 	CPQARY3_SG_CNT,		/* Scatter/Gather List Length */
9680c94ecdSKeith M Wesolowski 	512,			/* Device Granularity */
9780c94ecdSKeith M Wesolowski 	0			/* DMA flags */
9880c94ecdSKeith M Wesolowski };
9980c94ecdSKeith M Wesolowski 
10080c94ecdSKeith M Wesolowski /*
10180c94ecdSKeith M Wesolowski  * The Device Access Attribute Structure.
10280c94ecdSKeith M Wesolowski  */
10380c94ecdSKeith M Wesolowski 
10480c94ecdSKeith M Wesolowski ddi_device_acc_attr_t cpqary3_dev_attributes = {
10580c94ecdSKeith M Wesolowski 	DDI_DEVICE_ATTR_V0,
10680c94ecdSKeith M Wesolowski 	DDI_STRUCTURE_LE_ACC,
10780c94ecdSKeith M Wesolowski 	DDI_STRICTORDER_ACC
10880c94ecdSKeith M Wesolowski };
10980c94ecdSKeith M Wesolowski 
11080c94ecdSKeith M Wesolowski /*
11180c94ecdSKeith M Wesolowski  * Character-Block Operations Structure
11280c94ecdSKeith M Wesolowski  */
11380c94ecdSKeith M Wesolowski 
11480c94ecdSKeith M Wesolowski static struct cb_ops cpqary3_cb_ops = {
11580c94ecdSKeith M Wesolowski 	/* HPQacucli Changes */
11680c94ecdSKeith M Wesolowski 	scsi_hba_open,
11780c94ecdSKeith M Wesolowski 	scsi_hba_close,
11880c94ecdSKeith M Wesolowski 	/* HPQacucli Changes */
11980c94ecdSKeith M Wesolowski 	nodev,			/* cb_strategy */
12080c94ecdSKeith M Wesolowski 	nodev,			/* cb_print */
12180c94ecdSKeith M Wesolowski 	nodev,			/* cb_dump */
12280c94ecdSKeith M Wesolowski 	nodev,			/* cb_read */
12380c94ecdSKeith M Wesolowski 	nodev,			/* cb_write */
12480c94ecdSKeith M Wesolowski 	cpqary3_ioctl,		/* cb_ioctl */
12580c94ecdSKeith M Wesolowski 	nodev,			/* cb_devmap */
12680c94ecdSKeith M Wesolowski 	nodev,			/* cb_mmap */
12780c94ecdSKeith M Wesolowski 	nodev,			/* cb_segmap */
12880c94ecdSKeith M Wesolowski 	nochpoll,		/* cb_chpoll */
12980c94ecdSKeith M Wesolowski 	ddi_prop_op,		/* cb_prop_op */
13080c94ecdSKeith M Wesolowski 	NULL,			/* cb_stream */
13180c94ecdSKeith M Wesolowski 	(int)(D_NEW|D_MP),	/* cb_flag */
13280c94ecdSKeith M Wesolowski 	CB_REV,
13380c94ecdSKeith M Wesolowski 	nodev,
13480c94ecdSKeith M Wesolowski 	nodev
13580c94ecdSKeith M Wesolowski };
13680c94ecdSKeith M Wesolowski 
13780c94ecdSKeith M Wesolowski /*
13880c94ecdSKeith M Wesolowski  * Device Operations Structure
13980c94ecdSKeith M Wesolowski  */
14080c94ecdSKeith M Wesolowski 
14180c94ecdSKeith M Wesolowski static struct dev_ops cpqary3_dev_ops = {
14280c94ecdSKeith M Wesolowski 	DEVO_REV,		/* Driver Build Version */
14380c94ecdSKeith M Wesolowski 	0,			/* Driver reference count */
14480c94ecdSKeith M Wesolowski 	nodev,			/* Get Info */
14580c94ecdSKeith M Wesolowski 	nulldev,		/* Identify not required */
14680c94ecdSKeith M Wesolowski 	nulldev,		/* Probe, obselete for s2.6 and up */
14780c94ecdSKeith M Wesolowski 	cpqary3_attach,		/* Attach routine */
14880c94ecdSKeith M Wesolowski 	cpqary3_detach,		/* Detach routine */
14980c94ecdSKeith M Wesolowski 	nodev,			/* Reset */
15080c94ecdSKeith M Wesolowski 	&cpqary3_cb_ops,	/* Entry Points for C&B drivers */
15180c94ecdSKeith M Wesolowski 	NULL,			/* Bus ops */
15280c94ecdSKeith M Wesolowski 	nodev			/* cpqary3_power */
15380c94ecdSKeith M Wesolowski };
15480c94ecdSKeith M Wesolowski 
15580c94ecdSKeith M Wesolowski /*
15680c94ecdSKeith M Wesolowski  * Linkage structures
15780c94ecdSKeith M Wesolowski  */
15880c94ecdSKeith M Wesolowski 
15980c94ecdSKeith M Wesolowski static struct modldrv cpqary3_modldrv = {
16080c94ecdSKeith M Wesolowski 	&mod_driverops,		/* Module Type - driver */
16180c94ecdSKeith M Wesolowski 	cpqary3_brief,		/* Driver Desc */
16280c94ecdSKeith M Wesolowski 	&cpqary3_dev_ops	/* Driver Ops */
16380c94ecdSKeith M Wesolowski };
16480c94ecdSKeith M Wesolowski 
16580c94ecdSKeith M Wesolowski static struct modlinkage cpqary3_modlinkage = {
16680c94ecdSKeith M Wesolowski 	MODREV_1,		/* Loadable module rev. no. */
16780c94ecdSKeith M Wesolowski 	&cpqary3_modldrv, 	/* Loadable module */
16880c94ecdSKeith M Wesolowski 	NULL 			/* end */
16980c94ecdSKeith M Wesolowski };
17080c94ecdSKeith M Wesolowski 
17180c94ecdSKeith M Wesolowski 
17280c94ecdSKeith M Wesolowski /*
17380c94ecdSKeith M Wesolowski  * Function	:	_init
17480c94ecdSKeith M Wesolowski  * Description	:	This routine allocates soft state resources for the
17580c94ecdSKeith M Wesolowski  *			driver, registers the HBA with the system and
17680c94ecdSKeith M Wesolowski  *			adds the driver(loadable module).
17780c94ecdSKeith M Wesolowski  * Called By	:	Kernel
17880c94ecdSKeith M Wesolowski  * Parameters	:	None
17980c94ecdSKeith M Wesolowski  * Return Values:	0 / Non-Zero
18080c94ecdSKeith M Wesolowski  *			[as returned by the mod_install OS function]
18180c94ecdSKeith M Wesolowski  */
18280c94ecdSKeith M Wesolowski int
_init()18380c94ecdSKeith M Wesolowski _init()
18480c94ecdSKeith M Wesolowski {
18580c94ecdSKeith M Wesolowski 	int  retvalue;
18680c94ecdSKeith M Wesolowski 
18780c94ecdSKeith M Wesolowski 	/*
18880c94ecdSKeith M Wesolowski 	 * Allocate Soft State Resources; if failure, return.
18980c94ecdSKeith M Wesolowski 	 */
19080c94ecdSKeith M Wesolowski 	retvalue = ddi_soft_state_init(&cpqary3_state,
19180c94ecdSKeith M Wesolowski 	    sizeof (cpqary3_t), MAX_CTLRS);
19280c94ecdSKeith M Wesolowski 	VERIFY(retvalue == 0);
19380c94ecdSKeith M Wesolowski 
19480c94ecdSKeith M Wesolowski 	/*
19580c94ecdSKeith M Wesolowski 	 * Initialise the HBA Interface.
19680c94ecdSKeith M Wesolowski 	 */
19780c94ecdSKeith M Wesolowski 	if (!(retvalue = scsi_hba_init(&cpqary3_modlinkage))) {
19880c94ecdSKeith M Wesolowski 		/* Load the driver */
19980c94ecdSKeith M Wesolowski 		if ((retvalue = mod_install(&cpqary3_modlinkage))) {
20080c94ecdSKeith M Wesolowski 			/*
20180c94ecdSKeith M Wesolowski 			 * Failed to load the driver, undo HBA interface
20280c94ecdSKeith M Wesolowski 			 * and soft state allocation.
20380c94ecdSKeith M Wesolowski 			 */
20480c94ecdSKeith M Wesolowski 			scsi_hba_fini(&cpqary3_modlinkage);
20580c94ecdSKeith M Wesolowski 			ddi_soft_state_fini(&cpqary3_state);
20680c94ecdSKeith M Wesolowski 		}
20780c94ecdSKeith M Wesolowski 	} else {
20880c94ecdSKeith M Wesolowski 		/*
20980c94ecdSKeith M Wesolowski 		 * Failed to register HBA interface, undo all soft state
21080c94ecdSKeith M Wesolowski 		 * allocation
21180c94ecdSKeith M Wesolowski 		 */
21280c94ecdSKeith M Wesolowski 		ddi_soft_state_fini(&cpqary3_state);
21380c94ecdSKeith M Wesolowski 	}
21480c94ecdSKeith M Wesolowski 
21580c94ecdSKeith M Wesolowski 	return (retvalue);
21680c94ecdSKeith M Wesolowski }
21780c94ecdSKeith M Wesolowski 
21880c94ecdSKeith M Wesolowski /*
21980c94ecdSKeith M Wesolowski  * Function	: 	_fini
22080c94ecdSKeith M Wesolowski  * Description	: 	This routine removes the loadable module, cancels the
22180c94ecdSKeith M Wesolowski  *			HBA registration and deallocates soft state resources.
22280c94ecdSKeith M Wesolowski  * Called By	: 	Kernel
22380c94ecdSKeith M Wesolowski  * Parameters	: 	None
22480c94ecdSKeith M Wesolowski  * Return Values: 	0 - Success / Non-Zero - Failure
22580c94ecdSKeith M Wesolowski  *			[as returned by the mod_remove(OS provided) function]
22680c94ecdSKeith M Wesolowski  */
22780c94ecdSKeith M Wesolowski int
_fini()22880c94ecdSKeith M Wesolowski _fini()
22980c94ecdSKeith M Wesolowski {
23080c94ecdSKeith M Wesolowski 	int  retvalue;
23180c94ecdSKeith M Wesolowski 
23280c94ecdSKeith M Wesolowski 	/* Unload the Driver(loadable module) */
23380c94ecdSKeith M Wesolowski 
23480c94ecdSKeith M Wesolowski 	if ((retvalue = mod_remove(&cpqary3_modlinkage)) == 0) {
23580c94ecdSKeith M Wesolowski 
23680c94ecdSKeith M Wesolowski 		/* Cancel the registeration for the HBA Interface */
23780c94ecdSKeith M Wesolowski 		scsi_hba_fini(&cpqary3_modlinkage);
23880c94ecdSKeith M Wesolowski 
23980c94ecdSKeith M Wesolowski 		/* dealloacte soft state resources of the driver */
24080c94ecdSKeith M Wesolowski 		ddi_soft_state_fini(&cpqary3_state);
24180c94ecdSKeith M Wesolowski 	}
24280c94ecdSKeith M Wesolowski 
24380c94ecdSKeith M Wesolowski 	return (retvalue);
24480c94ecdSKeith M Wesolowski }
24580c94ecdSKeith M Wesolowski 
24680c94ecdSKeith M Wesolowski /*
24780c94ecdSKeith M Wesolowski  * Function	: 	_info
24880c94ecdSKeith M Wesolowski  * Description	: 	This routine returns information about the driver.
24980c94ecdSKeith M Wesolowski  * Called By	: 	Kernel
25080c94ecdSKeith M Wesolowski  * Parameters	: 	None
25180c94ecdSKeith M Wesolowski  * Return Values: 	0 / Non-Zero
25280c94ecdSKeith M Wesolowski  *			[as returned by mod_info(OS provided) function]
25380c94ecdSKeith M Wesolowski  */
25480c94ecdSKeith M Wesolowski int
_info(struct modinfo * modinfop)25580c94ecdSKeith M Wesolowski _info(struct modinfo *modinfop)
25680c94ecdSKeith M Wesolowski {
25780c94ecdSKeith M Wesolowski 	/*
25880c94ecdSKeith M Wesolowski 	 * Get the module information.
25980c94ecdSKeith M Wesolowski 	 */
26080c94ecdSKeith M Wesolowski 	return (mod_info(&cpqary3_modlinkage, modinfop));
26180c94ecdSKeith M Wesolowski }
26280c94ecdSKeith M Wesolowski 
26380c94ecdSKeith M Wesolowski 
26480c94ecdSKeith M Wesolowski /*
26580c94ecdSKeith M Wesolowski  * Function	: 	cpqary3_attach
26680c94ecdSKeith M Wesolowski  * Description	: 	This routine initializes the driver specific soft state
26780c94ecdSKeith M Wesolowski  *			structure, initializes the HBA, interrupt handlers,
26880c94ecdSKeith M Wesolowski  *			memory pool, timeout handler, various mutex, creates the
26980c94ecdSKeith M Wesolowski  *			minor node.
27080c94ecdSKeith M Wesolowski  * Called By	: 	kernel
27180c94ecdSKeith M Wesolowski  * Parameters	: 	dip, command for attach
27280c94ecdSKeith M Wesolowski  * Return Values: 	DDI_SUCCESS / DDI_FAILURE
27380c94ecdSKeith M Wesolowski  *			[Success on overall initialization & configuration
27480c94ecdSKeith M Wesolowski  *			being successful. Failure if any of the initialization
27580c94ecdSKeith M Wesolowski  *			or any driver-specific mandatory configuration fails]
27680c94ecdSKeith M Wesolowski  */
27780c94ecdSKeith M Wesolowski int
cpqary3_attach(dev_info_t * dip,ddi_attach_cmd_t attach_cmd)27880c94ecdSKeith M Wesolowski cpqary3_attach(dev_info_t *dip, ddi_attach_cmd_t attach_cmd)
27980c94ecdSKeith M Wesolowski {
28080c94ecdSKeith M Wesolowski 	int8_t		minor_node_name[14];
28180c94ecdSKeith M Wesolowski 	uint32_t	instance;
28280c94ecdSKeith M Wesolowski 	uint32_t	retvalue;
28380c94ecdSKeith M Wesolowski 	uint32_t	cleanstatus = 0;
28480c94ecdSKeith M Wesolowski 	cpqary3_t	*cpqary3p;		/* per-controller */
28580c94ecdSKeith M Wesolowski 	ddi_dma_attr_t	tmp_dma_attr;
28680c94ecdSKeith M Wesolowski 
28780c94ecdSKeith M Wesolowski 	/* Return Failure, If the Command is other than - DDI_ATTACH. */
28880c94ecdSKeith M Wesolowski 
28980c94ecdSKeith M Wesolowski 	if (attach_cmd != DDI_ATTACH)
29080c94ecdSKeith M Wesolowski 		return (DDI_FAILURE);
29180c94ecdSKeith M Wesolowski 
29280c94ecdSKeith M Wesolowski 	/* Get the Instance of the Device */
29380c94ecdSKeith M Wesolowski 
29480c94ecdSKeith M Wesolowski 	instance = ddi_get_instance(dip);
29580c94ecdSKeith M Wesolowski 
29680c94ecdSKeith M Wesolowski 	/* Allocate the per-device-instance soft state structure */
29780c94ecdSKeith M Wesolowski 
29880c94ecdSKeith M Wesolowski 	retvalue = ddi_soft_state_zalloc(cpqary3_state, instance);
29980c94ecdSKeith M Wesolowski 	VERIFY(retvalue == 0);
30080c94ecdSKeith M Wesolowski 
30180c94ecdSKeith M Wesolowski 	cleanstatus |= CPQARY3_SOFTSTATE_ALLOC_DONE;
30280c94ecdSKeith M Wesolowski 
30380c94ecdSKeith M Wesolowski 	/* Per Controller Pointer */
30480c94ecdSKeith M Wesolowski 	cpqary3p = ddi_get_soft_state(cpqary3_state, instance);
30580c94ecdSKeith M Wesolowski 	if (!cpqary3p) {
30680c94ecdSKeith M Wesolowski 		cmn_err(CE_WARN, "CPQary3: Soft State Retrieval Failed");
30780c94ecdSKeith M Wesolowski 		cpqary3_cleanup(cpqary3p, cleanstatus);
30880c94ecdSKeith M Wesolowski 		return (DDI_FAILURE);
30980c94ecdSKeith M Wesolowski 	}
31080c94ecdSKeith M Wesolowski 
31180c94ecdSKeith M Wesolowski 	/* Maintain a record in per-ctlr structure */
31280c94ecdSKeith M Wesolowski 	cpqary3p->dip = dip;
31380c94ecdSKeith M Wesolowski 	cpqary3p->instance = instance;
31480c94ecdSKeith M Wesolowski 
31580c94ecdSKeith M Wesolowski 	/* Get the User Configuration information from Driver's conf File */
31680c94ecdSKeith M Wesolowski 	cpqary3_read_conf_file(dip, cpqary3p);
31780c94ecdSKeith M Wesolowski 
31880c94ecdSKeith M Wesolowski 	/* Get and Map the HW Configuration */
31980c94ecdSKeith M Wesolowski 	retvalue = cpqary3_update_ctlrdetails(cpqary3p, &cleanstatus);
32080c94ecdSKeith M Wesolowski 	if (retvalue == CPQARY3_FAILURE) {
32180c94ecdSKeith M Wesolowski 		cpqary3_cleanup(cpqary3p, cleanstatus);
32280c94ecdSKeith M Wesolowski 		return (DDI_FAILURE);
32380c94ecdSKeith M Wesolowski 	}
32480c94ecdSKeith M Wesolowski 
32580c94ecdSKeith M Wesolowski 	/* Get the Cookie for hardware Interrupt Handler */
32680c94ecdSKeith M Wesolowski 	if (ddi_get_iblock_cookie(dip, 0, &cpqary3p->hw_iblock_cookie) !=
32780c94ecdSKeith M Wesolowski 	    DDI_SUCCESS) {
32880c94ecdSKeith M Wesolowski 		cpqary3_cleanup(cpqary3p, cleanstatus);
32980c94ecdSKeith M Wesolowski 		return (DDI_FAILURE);
33080c94ecdSKeith M Wesolowski 	}
33180c94ecdSKeith M Wesolowski 
33280c94ecdSKeith M Wesolowski 	/* Initialize Per Controller Mutex */
33380c94ecdSKeith M Wesolowski 	mutex_init(&cpqary3p->hw_mutex, NULL, MUTEX_DRIVER,
33480c94ecdSKeith M Wesolowski 	    (void *)cpqary3p->hw_iblock_cookie);
33580c94ecdSKeith M Wesolowski 
33680c94ecdSKeith M Wesolowski 	cleanstatus |= CPQARY3_MUTEX_INIT_DONE;
33780c94ecdSKeith M Wesolowski 
33880c94ecdSKeith M Wesolowski 	/* Get the Cookie for Soft(low level) Interrupt Handler */
33980c94ecdSKeith M Wesolowski 	if (ddi_get_soft_iblock_cookie(dip, DDI_SOFTINT_HIGH,
34080c94ecdSKeith M Wesolowski 	    &cpqary3p->sw_iblock_cookie) != DDI_SUCCESS) {
34180c94ecdSKeith M Wesolowski 		cpqary3_cleanup(cpqary3p, cleanstatus);
34280c94ecdSKeith M Wesolowski 		return (DDI_FAILURE);
34380c94ecdSKeith M Wesolowski 	}
34480c94ecdSKeith M Wesolowski 
34580c94ecdSKeith M Wesolowski 	/* Initialize the s/w Mutex */
34680c94ecdSKeith M Wesolowski 	mutex_init(&cpqary3p->sw_mutex, NULL, MUTEX_DRIVER,
34780c94ecdSKeith M Wesolowski 	    (void *)cpqary3p->sw_iblock_cookie);
34880c94ecdSKeith M Wesolowski 	cleanstatus |= CPQARY3_SW_MUTEX_INIT_DONE;
34980c94ecdSKeith M Wesolowski 
35080c94ecdSKeith M Wesolowski 	/* Initialize per Controller private details */
35180c94ecdSKeith M Wesolowski 	retvalue = cpqary3_init_ctlr_resource(cpqary3p);
35280c94ecdSKeith M Wesolowski 	if (retvalue != CPQARY3_SUCCESS) {
35380c94ecdSKeith M Wesolowski 		cpqary3_cleanup(cpqary3p, cleanstatus);
35480c94ecdSKeith M Wesolowski 		return (DDI_FAILURE);
35580c94ecdSKeith M Wesolowski 	}
35680c94ecdSKeith M Wesolowski 	cleanstatus |= CPQARY3_CTLR_CONFIG_DONE;
35780c94ecdSKeith M Wesolowski 
35880c94ecdSKeith M Wesolowski 	/*
35980c94ecdSKeith M Wesolowski 	 * Allocate HBA transport structure
36080c94ecdSKeith M Wesolowski 	 */
36180c94ecdSKeith M Wesolowski 	cpqary3p->hba_tran = scsi_hba_tran_alloc(dip, SCSI_HBA_CANSLEEP);
36280c94ecdSKeith M Wesolowski 	if (!cpqary3p->hba_tran) {
36380c94ecdSKeith M Wesolowski 		cpqary3_cleanup(cpqary3p, cleanstatus);
36480c94ecdSKeith M Wesolowski 		return (DDI_FAILURE);
36580c94ecdSKeith M Wesolowski 	}
36680c94ecdSKeith M Wesolowski 	cleanstatus |= CPQARY3_HBA_TRAN_ALLOC_DONE;
36780c94ecdSKeith M Wesolowski 
36880c94ecdSKeith M Wesolowski 	/*
36980c94ecdSKeith M Wesolowski 	 * Set private field for the HBA tran structure.
37080c94ecdSKeith M Wesolowski 	 * Initialise the HBA tran entry points.
37180c94ecdSKeith M Wesolowski 	 * Attach the controller to HBA.
37280c94ecdSKeith M Wesolowski 	 */
37380c94ecdSKeith M Wesolowski 	cpqary3_init_hbatran(cpqary3p);
37480c94ecdSKeith M Wesolowski 
37580c94ecdSKeith M Wesolowski 	/* PERF */
37680c94ecdSKeith M Wesolowski 	/* SG */
37780c94ecdSKeith M Wesolowski 	tmp_dma_attr = cpqary3_dma_attr;
37880c94ecdSKeith M Wesolowski 	tmp_dma_attr.dma_attr_sgllen = cpqary3p->sg_cnt;
37980c94ecdSKeith M Wesolowski 	/* SG */
38080c94ecdSKeith M Wesolowski 	/* PERF */
38180c94ecdSKeith M Wesolowski 	/*
38280c94ecdSKeith M Wesolowski 	 * Register the DMA attributes and the transport vectors
38380c94ecdSKeith M Wesolowski 	 * of each instance of the  HBA device.
38480c94ecdSKeith M Wesolowski 	 */
38580c94ecdSKeith M Wesolowski 	if (scsi_hba_attach_setup(dip, &tmp_dma_attr, cpqary3p->hba_tran,
38680c94ecdSKeith M Wesolowski 	    SCSI_HBA_TRAN_CLONE) == DDI_FAILURE) {
38780c94ecdSKeith M Wesolowski 		cpqary3_cleanup(cpqary3p, cleanstatus);
38880c94ecdSKeith M Wesolowski 		return (DDI_FAILURE);
38980c94ecdSKeith M Wesolowski 	}
39080c94ecdSKeith M Wesolowski 	cleanstatus |= CPQARY3_HBA_TRAN_ATTACH_DONE;
39180c94ecdSKeith M Wesolowski 
39280c94ecdSKeith M Wesolowski 	/*
39380c94ecdSKeith M Wesolowski 	 * Create a minor node for Ioctl interface.
39480c94ecdSKeith M Wesolowski 	 * The nomenclature used will be "cpqary3" immediately followed by
39580c94ecdSKeith M Wesolowski 	 * the current driver instance in the system.
39680c94ecdSKeith M Wesolowski 	 * for e.g.: 	for 0th instance : cpqary3,0
39780c94ecdSKeith M Wesolowski 	 * 				for 1st instance : cpqary3,1
39880c94ecdSKeith M Wesolowski 	 */
39980c94ecdSKeith M Wesolowski 
40080c94ecdSKeith M Wesolowski 	(void) sprintf(minor_node_name, "cpqary3,%d", instance);
40180c94ecdSKeith M Wesolowski 
40280c94ecdSKeith M Wesolowski 	/* HPQacucli Changes */
40380c94ecdSKeith M Wesolowski 	if (ddi_create_minor_node(dip, minor_node_name, S_IFCHR,
40480c94ecdSKeith M Wesolowski 	    CPQARY3_INST2CPQARY3(instance), DDI_NT_SCSI_NEXUS, 0) ==
40580c94ecdSKeith M Wesolowski 	    DDI_SUCCESS) {
40680c94ecdSKeith M Wesolowski 		/* HPQacucli Changes */
40780c94ecdSKeith M Wesolowski 		cleanstatus |= CPQARY3_CREATE_MINOR_NODE;
40880c94ecdSKeith M Wesolowski 	} else {
40980c94ecdSKeith M Wesolowski 		cmn_err(CE_NOTE, "CPQary3 : Failed to create minor node");
41080c94ecdSKeith M Wesolowski 		cpqary3_cleanup(cpqary3p, cleanstatus);
41180c94ecdSKeith M Wesolowski 		return (DDI_FAILURE);
41280c94ecdSKeith M Wesolowski 	}
41380c94ecdSKeith M Wesolowski 
41480c94ecdSKeith M Wesolowski 
41580c94ecdSKeith M Wesolowski 	/* Register a timeout driver-routine to be called every 2 secs */
41680c94ecdSKeith M Wesolowski 	cpqary3p->tick_tmout_id = timeout(cpqary3_tick_hdlr,
41780c94ecdSKeith M Wesolowski 	    (caddr_t)cpqary3p, drv_usectohz(CPQARY3_TICKTMOUT_VALUE));
41880c94ecdSKeith M Wesolowski 	cleanstatus |= CPQARY3_TICK_TMOUT_REGD;
41980c94ecdSKeith M Wesolowski 
42080c94ecdSKeith M Wesolowski 	/* Register Software Interrupt Handler */
42180c94ecdSKeith M Wesolowski 	if (ddi_add_softintr(dip,  DDI_SOFTINT_HIGH,
42280c94ecdSKeith M Wesolowski 	    &cpqary3p->cpqary3_softintr_id, &cpqary3p->sw_iblock_cookie, NULL,
42380c94ecdSKeith M Wesolowski 	    cpqary3_sw_isr, (caddr_t)cpqary3p) != DDI_SUCCESS) {
42480c94ecdSKeith M Wesolowski 		cpqary3_cleanup(cpqary3p, cleanstatus);
42580c94ecdSKeith M Wesolowski 		return (DDI_FAILURE);
42680c94ecdSKeith M Wesolowski 	}
42780c94ecdSKeith M Wesolowski 	cleanstatus |= CPQARY3_SW_INTR_HDLR_SET;
42880c94ecdSKeith M Wesolowski 
42980c94ecdSKeith M Wesolowski 	/* Register Interrupt Handler */
43080c94ecdSKeith M Wesolowski 	if (ddi_add_intr(dip, 0, &cpqary3p->hw_iblock_cookie, NULL,
43180c94ecdSKeith M Wesolowski 	    cpqary3_hw_isr, (caddr_t)cpqary3p) != DDI_SUCCESS) {
43280c94ecdSKeith M Wesolowski 		cpqary3_cleanup(cpqary3p, cleanstatus);
43380c94ecdSKeith M Wesolowski 		return (DDI_FAILURE);
43480c94ecdSKeith M Wesolowski 	}
43580c94ecdSKeith M Wesolowski 	cleanstatus |= CPQARY3_INTR_HDLR_SET;
43680c94ecdSKeith M Wesolowski 
43780c94ecdSKeith M Wesolowski 	/* Enable the Controller Interrupt */
43880c94ecdSKeith M Wesolowski 	cpqary3_intr_onoff(cpqary3p, CPQARY3_INTR_ENABLE);
43980c94ecdSKeith M Wesolowski 	if (cpqary3p->host_support & 0x4)
44080c94ecdSKeith M Wesolowski 		cpqary3_lockup_intr_onoff(cpqary3p, CPQARY3_LOCKUP_INTR_ENABLE);
44180c94ecdSKeith M Wesolowski 
44280c94ecdSKeith M Wesolowski 	/*
44380c94ecdSKeith M Wesolowski 	 * We have come with hmaeventd - which logs the storage events on
44480c94ecdSKeith M Wesolowski 	 * console as well as in IML. So we are commenting the NOE support in
44580c94ecdSKeith M Wesolowski 	 * the driver
44680c94ecdSKeith M Wesolowski 	 */
44780c94ecdSKeith M Wesolowski 
44880c94ecdSKeith M Wesolowski 	/* NOE */
44980c94ecdSKeith M Wesolowski 	if (cpqary3p->noe_support == 1) {
45080c94ecdSKeith M Wesolowski 		/* Enable the Notification on Event in this controller */
45180c94ecdSKeith M Wesolowski 		if (CPQARY3_SUCCESS ==
45280c94ecdSKeith M Wesolowski 		    cpqary3_send_NOE_command(cpqary3p,
45380c94ecdSKeith M Wesolowski 		    NULL, CPQARY3_NOE_INIT)) {
45480c94ecdSKeith M Wesolowski 			cleanstatus |= CPQARY3_NOE_INIT_DONE;
45580c94ecdSKeith M Wesolowski 		} else {
45680c94ecdSKeith M Wesolowski 			cmn_err(CE_CONT, "CPQary3 : Failed to initialize "
45780c94ecdSKeith M Wesolowski 			    "NOTIFICATION ON EVENT \n");
45880c94ecdSKeith M Wesolowski 		}
45980c94ecdSKeith M Wesolowski 	}
46080c94ecdSKeith M Wesolowski 	/* NOE */
46180c94ecdSKeith M Wesolowski 
46280c94ecdSKeith M Wesolowski 	/* Report that an Instance of the Driver is Attached Successfully */
46380c94ecdSKeith M Wesolowski 	ddi_report_dev(dip);
46480c94ecdSKeith M Wesolowski 
46580c94ecdSKeith M Wesolowski 	/*
46680c94ecdSKeith M Wesolowski 	 * Now update the num_ctlr
46780c94ecdSKeith M Wesolowski 	 * This is required for the agents
46880c94ecdSKeith M Wesolowski 	 */
46980c94ecdSKeith M Wesolowski 
47080c94ecdSKeith M Wesolowski 	gdriver_info.num_ctlr++;
47180c94ecdSKeith M Wesolowski 
47280c94ecdSKeith M Wesolowski 	return (DDI_SUCCESS);
47380c94ecdSKeith M Wesolowski 
47480c94ecdSKeith M Wesolowski }
47580c94ecdSKeith M Wesolowski 
47680c94ecdSKeith M Wesolowski /*
47780c94ecdSKeith M Wesolowski  * Function	: 	cpqary3_detach
47880c94ecdSKeith M Wesolowski  * Description	: 	This routine removes the state associated with a
47980c94ecdSKeith M Wesolowski  * 			given instance of a device node prior to the
48080c94ecdSKeith M Wesolowski  * 			removal of that instance from the system
48180c94ecdSKeith M Wesolowski  * Called By	: 	kernel
48280c94ecdSKeith M Wesolowski  * Parameters	: 	dip, command for detach
48380c94ecdSKeith M Wesolowski  * Return Values: 	DDI_SUCCESS / DDI_FAILURE
48480c94ecdSKeith M Wesolowski  *			[failure ONLY if the command sent with this function
48580c94ecdSKeith M Wesolowski  *			as a paramter is not DETACH]
48680c94ecdSKeith M Wesolowski  */
48780c94ecdSKeith M Wesolowski int
cpqary3_detach(dev_info_t * dip,ddi_detach_cmd_t detach_cmd)48880c94ecdSKeith M Wesolowski cpqary3_detach(dev_info_t *dip, ddi_detach_cmd_t detach_cmd)
48980c94ecdSKeith M Wesolowski {
49080c94ecdSKeith M Wesolowski 	cpqary3_t	*cpqary3p;
49180c94ecdSKeith M Wesolowski 	scsi_hba_tran_t	*hba_tran;
49280c94ecdSKeith M Wesolowski 
49380c94ecdSKeith M Wesolowski 	/* Return failure, If Command is not DDI_DETACH */
49480c94ecdSKeith M Wesolowski 
49580c94ecdSKeith M Wesolowski 	if (DDI_DETACH != detach_cmd)
49680c94ecdSKeith M Wesolowski 		return (DDI_FAILURE);
49780c94ecdSKeith M Wesolowski 
49880c94ecdSKeith M Wesolowski 	/*
49980c94ecdSKeith M Wesolowski 	 *  Get scsi_hba_tran structure.
50080c94ecdSKeith M Wesolowski 	 *  Get per controller structure.
50180c94ecdSKeith M Wesolowski 	 */
50280c94ecdSKeith M Wesolowski 
50380c94ecdSKeith M Wesolowski 	hba_tran = (scsi_hba_tran_t *)ddi_get_driver_private(dip);
50480c94ecdSKeith M Wesolowski 	cpqary3p = (cpqary3_t *)hba_tran->tran_hba_private;
50580c94ecdSKeith M Wesolowski 
50680c94ecdSKeith M Wesolowski 	/* Flush the cache */
50780c94ecdSKeith M Wesolowski 
50880c94ecdSKeith M Wesolowski 	cpqary3_flush_cache(cpqary3p);
50980c94ecdSKeith M Wesolowski 
51080c94ecdSKeith M Wesolowski 	/* Undo cpqary3_attach */
51180c94ecdSKeith M Wesolowski 
51280c94ecdSKeith M Wesolowski 	cpqary3_cleanup(cpqary3p, CPQARY3_CLEAN_ALL);
51380c94ecdSKeith M Wesolowski 
51480c94ecdSKeith M Wesolowski 	return (DDI_SUCCESS);
51580c94ecdSKeith M Wesolowski 
51680c94ecdSKeith M Wesolowski }
51780c94ecdSKeith M Wesolowski 
51880c94ecdSKeith M Wesolowski /*
51980c94ecdSKeith M Wesolowski  *	Function	: 	cpary3_ioctl
52080c94ecdSKeith M Wesolowski  *	Description	: 	This routine services ioctl requests.
52180c94ecdSKeith M Wesolowski  *	Called By	: 	kernel
52280c94ecdSKeith M Wesolowski  *	Parameters	: 	Too many to list. Please look below !!!
52380c94ecdSKeith M Wesolowski  *	Return Values:  	0 / EINVAL / EFAULT /
52480c94ecdSKeith M Wesolowski  *				[0 on normal successful completion of the ioctl
52580c94ecdSKeith M Wesolowski  *				request]
52680c94ecdSKeith M Wesolowski  */
52780c94ecdSKeith M Wesolowski int
cpqary3_ioctl(dev_t dev,int cmd,intptr_t arg,int mode,cred_t * credp,int * retvaluep)52880c94ecdSKeith M Wesolowski cpqary3_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp,
52980c94ecdSKeith M Wesolowski     int *retvaluep)
53080c94ecdSKeith M Wesolowski {
53180c94ecdSKeith M Wesolowski 	minor_t		cpqary3_minor_num;
53280c94ecdSKeith M Wesolowski 	cpqary3_t	*cpqary3p;
53380c94ecdSKeith M Wesolowski 	int		instance;
53480c94ecdSKeith M Wesolowski 
53580c94ecdSKeith M Wesolowski 	/*
53680c94ecdSKeith M Wesolowski 	 * Get the soft state structure for this instance
53780c94ecdSKeith M Wesolowski 	 * Return ENODEV if the structure does not exist.
53880c94ecdSKeith M Wesolowski 	 */
53980c94ecdSKeith M Wesolowski 
54080c94ecdSKeith M Wesolowski 	/*
54180c94ecdSKeith M Wesolowski 	 * minor() call used in cpqary3_ioctl() returns minor number of the
54280c94ecdSKeith M Wesolowski 	 * device which are in the
54380c94ecdSKeith M Wesolowski 	 * range 0-255. if the minor number of the device is greater than 255,
54480c94ecdSKeith M Wesolowski 	 * data will get truncated. so we are now using getminor(),
54580c94ecdSKeith M Wesolowski 	 * instead of minor()
54680c94ecdSKeith M Wesolowski 	 */
54780c94ecdSKeith M Wesolowski 
54880c94ecdSKeith M Wesolowski 	if (EINVAL == (cpqary3_minor_num = getminor(dev))) {
54980c94ecdSKeith M Wesolowski 		*retvaluep = ENODEV;
55080c94ecdSKeith M Wesolowski 		return (*retvaluep);
55180c94ecdSKeith M Wesolowski 	}
55280c94ecdSKeith M Wesolowski 
55380c94ecdSKeith M Wesolowski 	/* HPQacucli Changes */
55480c94ecdSKeith M Wesolowski 
55580c94ecdSKeith M Wesolowski 	/* get instance */
55680c94ecdSKeith M Wesolowski 	instance = MINOR2INST(cpqary3_minor_num);
55780c94ecdSKeith M Wesolowski 
55880c94ecdSKeith M Wesolowski 	cpqary3p = (cpqary3_t *)ddi_get_soft_state(cpqary3_state, instance);
55980c94ecdSKeith M Wesolowski 
56080c94ecdSKeith M Wesolowski 	/* HPQacucli Changes */
56180c94ecdSKeith M Wesolowski 
56280c94ecdSKeith M Wesolowski 	if (!cpqary3p) {
56380c94ecdSKeith M Wesolowski 		*retvaluep = ENODEV;
56480c94ecdSKeith M Wesolowski 		return (*retvaluep);
56580c94ecdSKeith M Wesolowski 	}
56680c94ecdSKeith M Wesolowski 
56780c94ecdSKeith M Wesolowski 	/* HPQacucli Changes */
56880c94ecdSKeith M Wesolowski 
56980c94ecdSKeith M Wesolowski 	/* check which interface is being requested */
57080c94ecdSKeith M Wesolowski 	if (CPQARY3_MINOR2INTERFACE(cpqary3_minor_num) != CPQARY3_MINOR) {
57180c94ecdSKeith M Wesolowski 		/* defer to SCSA */
57280c94ecdSKeith M Wesolowski 		return (scsi_hba_ioctl(dev, cmd, arg, mode, credp, retvaluep));
57380c94ecdSKeith M Wesolowski 	}
57480c94ecdSKeith M Wesolowski 
57580c94ecdSKeith M Wesolowski 	/* HPQacucli Changes */
57680c94ecdSKeith M Wesolowski 
57780c94ecdSKeith M Wesolowski 	switch (cmd) {
57880c94ecdSKeith M Wesolowski 		case CPQARY3_IOCTL_DRIVER_INFO:
57980c94ecdSKeith M Wesolowski 			*retvaluep =
58080c94ecdSKeith M Wesolowski 			    cpqary3_ioctl_driver_info(arg, mode);
58180c94ecdSKeith M Wesolowski 			break;
58280c94ecdSKeith M Wesolowski 
58380c94ecdSKeith M Wesolowski 		case CPQARY3_IOCTL_CTLR_INFO:
58480c94ecdSKeith M Wesolowski 			*retvaluep =
58580c94ecdSKeith M Wesolowski 			    cpqary3_ioctl_ctlr_info(arg, cpqary3p, mode);
58680c94ecdSKeith M Wesolowski 			break;
58780c94ecdSKeith M Wesolowski 
58880c94ecdSKeith M Wesolowski 		case CPQARY3_IOCTL_BMIC_PASS:
58980c94ecdSKeith M Wesolowski 			*retvaluep =
59080c94ecdSKeith M Wesolowski 			    cpqary3_ioctl_bmic_pass(arg, cpqary3p, mode);
59180c94ecdSKeith M Wesolowski 			break;
59280c94ecdSKeith M Wesolowski 
59380c94ecdSKeith M Wesolowski 		case CPQARY3_IOCTL_SCSI_PASS:
59480c94ecdSKeith M Wesolowski 			*retvaluep =
59580c94ecdSKeith M Wesolowski 			    cpqary3_ioctl_scsi_pass(arg, cpqary3p, mode);
59680c94ecdSKeith M Wesolowski 			break;
59780c94ecdSKeith M Wesolowski 
59880c94ecdSKeith M Wesolowski 		default:
59980c94ecdSKeith M Wesolowski 			*retvaluep = EINVAL;
60080c94ecdSKeith M Wesolowski 			break;
60180c94ecdSKeith M Wesolowski 	}
60280c94ecdSKeith M Wesolowski 		return (*retvaluep);
60380c94ecdSKeith M Wesolowski 
60480c94ecdSKeith M Wesolowski 
60580c94ecdSKeith M Wesolowski }
60680c94ecdSKeith M Wesolowski 
60780c94ecdSKeith M Wesolowski 
60880c94ecdSKeith M Wesolowski /*
60980c94ecdSKeith M Wesolowski  * Function	: 	cqpary3_cleanup
61080c94ecdSKeith M Wesolowski  * Description	: 	This routine frees all allocated resources.
61180c94ecdSKeith M Wesolowski  * Called By	: 	kernel
61280c94ecdSKeith M Wesolowski  * Parameters	: 	per-controller, bit-map(stating what all to clean)
61380c94ecdSKeith M Wesolowski  * Return Values: 	None
61480c94ecdSKeith M Wesolowski  */
61580c94ecdSKeith M Wesolowski static void
cpqary3_cleanup(cpqary3_t * cpqary3p,uint32_t status)61680c94ecdSKeith M Wesolowski cpqary3_cleanup(cpqary3_t *cpqary3p, uint32_t status)
61780c94ecdSKeith M Wesolowski {
61880c94ecdSKeith M Wesolowski 	int8_t		node_name[10];
61980c94ecdSKeith M Wesolowski 	clock_t		cpqary3_lbolt;
62080c94ecdSKeith M Wesolowski 	uint32_t	targ;
62180c94ecdSKeith M Wesolowski 
62280c94ecdSKeith M Wesolowski 	ASSERT(cpqary3p != NULL);
62380c94ecdSKeith M Wesolowski 
62480c94ecdSKeith M Wesolowski 	/*
62580c94ecdSKeith M Wesolowski 	 * Disable the NOE command
62680c94ecdSKeith M Wesolowski 	 * Free the Command Memory Pool
62780c94ecdSKeith M Wesolowski 	 * destroy all conditional variables
62880c94ecdSKeith M Wesolowski 	 */
62980c94ecdSKeith M Wesolowski 
63080c94ecdSKeith M Wesolowski 	/*
63180c94ecdSKeith M Wesolowski 	 * We have removed NOE functionality from the
63280c94ecdSKeith M Wesolowski 	 * driver. So commenting the below piece of code
63380c94ecdSKeith M Wesolowski 	 */
63480c94ecdSKeith M Wesolowski 
63580c94ecdSKeith M Wesolowski 	if (status & CPQARY3_NOE_INIT_DONE) {
63680c94ecdSKeith M Wesolowski 		if (CPQARY3_SUCCESS == cpqary3_disable_NOE_command(cpqary3p)) {
63780c94ecdSKeith M Wesolowski 			mutex_enter(&cpqary3p->hw_mutex);
63880c94ecdSKeith M Wesolowski 			cpqary3_lbolt = ddi_get_lbolt();
63980c94ecdSKeith M Wesolowski 			if (DDI_FAILURE ==
64080c94ecdSKeith M Wesolowski 			    cv_timedwait_sig(&cpqary3p->cv_noe_wait,
64180c94ecdSKeith M Wesolowski 			    &cpqary3p->hw_mutex,
64280c94ecdSKeith M Wesolowski 			    cpqary3_lbolt + drv_usectohz(3000000))) {
64380c94ecdSKeith M Wesolowski 				cmn_err(CE_NOTE,
64480c94ecdSKeith M Wesolowski 				    "CPQary3: Resume signal for disable NOE "
64580c94ecdSKeith M Wesolowski 				    "command not received \n");
64680c94ecdSKeith M Wesolowski 			}
64780c94ecdSKeith M Wesolowski 			mutex_exit(&cpqary3p->hw_mutex);
64880c94ecdSKeith M Wesolowski 		}
64980c94ecdSKeith M Wesolowski 	}
65080c94ecdSKeith M Wesolowski 
65180c94ecdSKeith M Wesolowski 	/*
65280c94ecdSKeith M Wesolowski 	 * Detach the device
65380c94ecdSKeith M Wesolowski 	 * Free / Release / Destroy the following entities/resources:
65480c94ecdSKeith M Wesolowski 	 * transport layer
65580c94ecdSKeith M Wesolowski 	 * h/w & s/w interrupt handlers
65680c94ecdSKeith M Wesolowski 	 * all mutex
65780c94ecdSKeith M Wesolowski 	 * timeout handler
65880c94ecdSKeith M Wesolowski 	 * target structure
65980c94ecdSKeith M Wesolowski 	 * minor node
66080c94ecdSKeith M Wesolowski 	 * soft state
66180c94ecdSKeith M Wesolowski 	 * any register/memory mapping
66280c94ecdSKeith M Wesolowski 	 */
66380c94ecdSKeith M Wesolowski 
66480c94ecdSKeith M Wesolowski 	if (status & CPQARY3_INTR_HDLR_SET)
66580c94ecdSKeith M Wesolowski 		ddi_remove_intr(cpqary3p->dip, 0, cpqary3p->hw_iblock_cookie);
66680c94ecdSKeith M Wesolowski 
66780c94ecdSKeith M Wesolowski 	if (status & CPQARY3_SW_INTR_HDLR_SET)
66880c94ecdSKeith M Wesolowski 		ddi_remove_softintr(cpqary3p->cpqary3_softintr_id);
66980c94ecdSKeith M Wesolowski 
67080c94ecdSKeith M Wesolowski 	if ((status & CPQARY3_TICK_TMOUT_REGD) && cpqary3p->tick_tmout_id) {
67180c94ecdSKeith M Wesolowski 		VERIFY(untimeout(cpqary3p->tick_tmout_id) >= 0);
67280c94ecdSKeith M Wesolowski 		cpqary3p->tick_tmout_id = NULL;
67380c94ecdSKeith M Wesolowski 	}
67480c94ecdSKeith M Wesolowski 
67580c94ecdSKeith M Wesolowski 	if (status & CPQARY3_CREATE_MINOR_NODE) {
67680c94ecdSKeith M Wesolowski 		(void) sprintf(node_name, "cpqary3%d", cpqary3p->instance);
67780c94ecdSKeith M Wesolowski 		ddi_remove_minor_node(cpqary3p->dip, node_name);
67880c94ecdSKeith M Wesolowski 	}
67980c94ecdSKeith M Wesolowski 
68080c94ecdSKeith M Wesolowski 	if (status & CPQARY3_HBA_TRAN_ATTACH_DONE)
68180c94ecdSKeith M Wesolowski 		(void) scsi_hba_detach(cpqary3p->dip);
68280c94ecdSKeith M Wesolowski 
68380c94ecdSKeith M Wesolowski 	if (status & CPQARY3_HBA_TRAN_ALLOC_DONE)
68480c94ecdSKeith M Wesolowski 		scsi_hba_tran_free(cpqary3p->hba_tran);
68580c94ecdSKeith M Wesolowski 
68680c94ecdSKeith M Wesolowski 	if (status & CPQARY3_CTLR_CONFIG_DONE) {
68780c94ecdSKeith M Wesolowski 		mutex_enter(&cpqary3p->hw_mutex);
68880c94ecdSKeith M Wesolowski 
68980c94ecdSKeith M Wesolowski 		cv_destroy(&cpqary3p->cv_abort_wait);
69080c94ecdSKeith M Wesolowski 		cv_destroy(&cpqary3p->cv_flushcache_wait);
69180c94ecdSKeith M Wesolowski 		cv_destroy(&cpqary3p->cv_noe_wait);
69280c94ecdSKeith M Wesolowski 		cv_destroy(&cpqary3p->cv_immediate_wait);
69380c94ecdSKeith M Wesolowski 		cv_destroy(&cpqary3p->cv_ioctl_wait);
69480c94ecdSKeith M Wesolowski 
69580c94ecdSKeith M Wesolowski 		for (targ = 0; targ < CPQARY3_MAX_TGT;  targ++) {
69680c94ecdSKeith M Wesolowski 			if (cpqary3p->cpqary3_tgtp[targ] == NULL)
69780c94ecdSKeith M Wesolowski 				continue;
69880c94ecdSKeith M Wesolowski 			MEM_SFREE(cpqary3p->cpqary3_tgtp[targ],
69980c94ecdSKeith M Wesolowski 			    sizeof (cpqary3_tgt_t));
70080c94ecdSKeith M Wesolowski 		}
70180c94ecdSKeith M Wesolowski 
70280c94ecdSKeith M Wesolowski 		mutex_exit(&cpqary3p->hw_mutex);
70380c94ecdSKeith M Wesolowski 
70480c94ecdSKeith M Wesolowski 		cpqary3_memfini(cpqary3p, CPQARY3_MEMLIST_DONE |
70580c94ecdSKeith M Wesolowski 		    CPQARY3_PHYCTGS_DONE | CPQARY3_CMDMEM_DONE);
70680c94ecdSKeith M Wesolowski 	}
70780c94ecdSKeith M Wesolowski 
70880c94ecdSKeith M Wesolowski 	if (status & CPQARY3_SW_MUTEX_INIT_DONE)
70980c94ecdSKeith M Wesolowski 		mutex_destroy(&cpqary3p->sw_mutex);
71080c94ecdSKeith M Wesolowski 
71180c94ecdSKeith M Wesolowski 	if (status & CPQARY3_MUTEX_INIT_DONE)
71280c94ecdSKeith M Wesolowski 		mutex_destroy(&cpqary3p->hw_mutex);
71380c94ecdSKeith M Wesolowski 
71480c94ecdSKeith M Wesolowski 	/*
71580c94ecdSKeith M Wesolowski 	 * If this flag is set, free all mapped registers
71680c94ecdSKeith M Wesolowski 	 */
71780c94ecdSKeith M Wesolowski 	if (status & CPQARY3_MEM_MAPPED) {
71880c94ecdSKeith M Wesolowski 		if (cpqary3p->idr_handle)
71980c94ecdSKeith M Wesolowski 			ddi_regs_map_free(&cpqary3p->idr_handle);
72080c94ecdSKeith M Wesolowski 		if (cpqary3p->isr_handle)
72180c94ecdSKeith M Wesolowski 			ddi_regs_map_free(&cpqary3p->isr_handle);
72280c94ecdSKeith M Wesolowski 		if (cpqary3p->imr_handle)
72380c94ecdSKeith M Wesolowski 			ddi_regs_map_free(&cpqary3p->imr_handle);
72480c94ecdSKeith M Wesolowski 		if (cpqary3p->ipq_handle)
72580c94ecdSKeith M Wesolowski 			ddi_regs_map_free(&cpqary3p->ipq_handle);
72680c94ecdSKeith M Wesolowski 		if (cpqary3p->opq_handle)
72780c94ecdSKeith M Wesolowski 			ddi_regs_map_free(&cpqary3p->opq_handle);
72880c94ecdSKeith M Wesolowski 		if (cpqary3p->ct_handle)
72980c94ecdSKeith M Wesolowski 			ddi_regs_map_free(&cpqary3p->ct_handle);
73080c94ecdSKeith M Wesolowski 	}
73180c94ecdSKeith M Wesolowski 
73280c94ecdSKeith M Wesolowski 	if (status & CPQARY3_SOFTSTATE_ALLOC_DONE) {
73380c94ecdSKeith M Wesolowski 		ddi_soft_state_free(cpqary3_state,
73480c94ecdSKeith M Wesolowski 		    ddi_get_instance(cpqary3p->dip));
73580c94ecdSKeith M Wesolowski 	}
73680c94ecdSKeith M Wesolowski }
73780c94ecdSKeith M Wesolowski 
73880c94ecdSKeith M Wesolowski /*
73980c94ecdSKeith M Wesolowski  * Function	: 	cpqary3_update_ctlrdetails
74080c94ecdSKeith M Wesolowski  * Description	: 	Performs Sanity check of the hw, Updates PCI Config
74180c94ecdSKeith M Wesolowski  *			Information, Verifies the supported board-id and
74280c94ecdSKeith M Wesolowski  *			Sets up a mapping for the Primary I2O Memory BAR and
74380c94ecdSKeith M Wesolowski  *			the Primary DRAM 1 BAR to access Host Interface
74480c94ecdSKeith M Wesolowski  *			registers and the Transport Configuration table.
74580c94ecdSKeith M Wesolowski  * Called By	: 	cpqary3_attach()
74680c94ecdSKeith M Wesolowski  * Parameters	: 	per-controller, bitmap (used for cleaning operations)
74780c94ecdSKeith M Wesolowski  * Return Values: 	SUCCESS / FAILURE
74880c94ecdSKeith M Wesolowski  *			[Success / failure depending upon the outcome of all
74980c94ecdSKeith M Wesolowski  *			checks and mapping. If any of them fail, a failure is
75080c94ecdSKeith M Wesolowski  *			sent back]
75180c94ecdSKeith M Wesolowski  */
75280c94ecdSKeith M Wesolowski static uint8_t
cpqary3_update_ctlrdetails(cpqary3_t * cpqary3p,uint32_t * cleanstatus)75380c94ecdSKeith M Wesolowski cpqary3_update_ctlrdetails(cpqary3_t *cpqary3p, uint32_t *cleanstatus)
75480c94ecdSKeith M Wesolowski {
75580c94ecdSKeith M Wesolowski 	int8_t			retvalue;
75680c94ecdSKeith M Wesolowski 	uint8_t			mem_bar0_set = 0;
75780c94ecdSKeith M Wesolowski 	uint8_t			mem_64_bar0_set = 0;
75880c94ecdSKeith M Wesolowski 	uint8_t			mem_bar1_set = 0;
75980c94ecdSKeith M Wesolowski 	uint8_t			mem_64_bar1_set = 0;
76080c94ecdSKeith M Wesolowski 	int32_t			reglen;
76180c94ecdSKeith M Wesolowski 	uint32_t		*regp;
76280c94ecdSKeith M Wesolowski 	uint32_t		mem_bar0 = 0;
76380c94ecdSKeith M Wesolowski 	uint32_t		mem_64_bar0;
76480c94ecdSKeith M Wesolowski 	uint32_t		mem_bar1 = 0;
76580c94ecdSKeith M Wesolowski 	uint32_t		mem_64_bar1 = 0;
76680c94ecdSKeith M Wesolowski 	uint32_t		ct_mem_bar = 0;
76780c94ecdSKeith M Wesolowski 	uint32_t		ct_cfgmem_val = 0;
76880c94ecdSKeith M Wesolowski 	uint32_t		ct_memoff_val = 0;
76980c94ecdSKeith M Wesolowski 	uint32_t		ct_cfg_bar = 0;
77080c94ecdSKeith M Wesolowski 	uint32_t		ct_mem_len = 0;
77180c94ecdSKeith M Wesolowski 	offset_t		map_len = 0;
77280c94ecdSKeith M Wesolowski 	uint32_t		regset_index;
77380c94ecdSKeith M Wesolowski 	ddi_acc_handle_t 	pci_handle;
77480c94ecdSKeith M Wesolowski 	uint32_t		*ct_cfg_offset;
77580c94ecdSKeith M Wesolowski 	ddi_acc_handle_t	ct_cfgoff_handle;
77680c94ecdSKeith M Wesolowski 	uint32_t		*ct_mem_offset;
77780c94ecdSKeith M Wesolowski 	ddi_acc_handle_t	ct_memoff_handle;
77880c94ecdSKeith M Wesolowski 
77980c94ecdSKeith M Wesolowski 	RETURN_FAILURE_IF_NULL(cpqary3p);
78080c94ecdSKeith M Wesolowski 
78180c94ecdSKeith M Wesolowski 	/*
78280c94ecdSKeith M Wesolowski 	 * Check if the bus, or part of the bus  that  the  device  is installed
78380c94ecdSKeith M Wesolowski 	 * on, permits the device to become a DMA master.
78480c94ecdSKeith M Wesolowski 	 * If our device is not permitted to become master, return
78580c94ecdSKeith M Wesolowski 	 */
78680c94ecdSKeith M Wesolowski 	if (ddi_slaveonly(cpqary3p->dip) == DDI_SUCCESS)
78780c94ecdSKeith M Wesolowski 		return (CPQARY3_FAILURE);
78880c94ecdSKeith M Wesolowski 
78980c94ecdSKeith M Wesolowski 	/*
79080c94ecdSKeith M Wesolowski 	 * Get the HW Configuration
79180c94ecdSKeith M Wesolowski 	 * Get Bus #, Dev # and Func # for this device
79280c94ecdSKeith M Wesolowski 	 * Free the memory that regp points towards after the
79380c94ecdSKeith M Wesolowski 	 * ddi_getlongprop() call
79480c94ecdSKeith M Wesolowski 	 */
79580c94ecdSKeith M Wesolowski 	if (ddi_getlongprop(DDI_DEV_T_NONE, cpqary3p->dip, DDI_PROP_DONTPASS,
79680c94ecdSKeith M Wesolowski 	    "reg", (caddr_t)&regp, &reglen) != DDI_PROP_SUCCESS)
79780c94ecdSKeith M Wesolowski 		return (CPQARY3_FAILURE);
79880c94ecdSKeith M Wesolowski 
79980c94ecdSKeith M Wesolowski 	cpqary3p->bus = PCI_REG_BUS_G(*regp);
80080c94ecdSKeith M Wesolowski 	cpqary3p->dev = PCI_REG_DEV_G(*regp);
80180c94ecdSKeith M Wesolowski 	cpqary3p->fun = PCI_REG_FUNC_G(*regp);
80280c94ecdSKeith M Wesolowski 
80380c94ecdSKeith M Wesolowski 	for (regset_index = 0; regset_index < reglen / 20; regset_index ++) {
80480c94ecdSKeith M Wesolowski 		if (PCI_REG_ADDR_G(*(regp + regset_index * 5)) == 0x2) {
80580c94ecdSKeith M Wesolowski 			if (!mem_bar0_set) {
80680c94ecdSKeith M Wesolowski 				mem_bar0 = regset_index;
80780c94ecdSKeith M Wesolowski 				mem_bar0_set = 1;
80880c94ecdSKeith M Wesolowski 			} else if (!mem_bar1_set) {
80980c94ecdSKeith M Wesolowski 				mem_bar1 = regset_index;
81080c94ecdSKeith M Wesolowski 				mem_bar1_set = 1;
81180c94ecdSKeith M Wesolowski 			}
81280c94ecdSKeith M Wesolowski 		}
81380c94ecdSKeith M Wesolowski 	}
81480c94ecdSKeith M Wesolowski 
81580c94ecdSKeith M Wesolowski 	mem_64_bar0 = mem_bar0;
81680c94ecdSKeith M Wesolowski 	mem_64_bar1 = mem_bar1;
81780c94ecdSKeith M Wesolowski 
81880c94ecdSKeith M Wesolowski 	for (regset_index = 0; regset_index < reglen / 20; regset_index ++) {
81980c94ecdSKeith M Wesolowski 		if (PCI_REG_ADDR_G(*(regp + regset_index * 5)) == 0x3) {
82080c94ecdSKeith M Wesolowski 			if (!mem_64_bar0_set) {
82180c94ecdSKeith M Wesolowski 				mem_64_bar0 = regset_index;
82280c94ecdSKeith M Wesolowski 				mem_64_bar0_set = 1;
82380c94ecdSKeith M Wesolowski 			} else if (!mem_64_bar1_set) {
82480c94ecdSKeith M Wesolowski 				mem_64_bar1 = regset_index;
82580c94ecdSKeith M Wesolowski 				mem_64_bar1_set = 1;
82680c94ecdSKeith M Wesolowski 			}
82780c94ecdSKeith M Wesolowski 		}
82880c94ecdSKeith M Wesolowski 	}
82980c94ecdSKeith M Wesolowski 
83080c94ecdSKeith M Wesolowski 	mem_bar0 = mem_64_bar0;
83180c94ecdSKeith M Wesolowski 	mem_bar1 = mem_64_bar1;
83280c94ecdSKeith M Wesolowski 
83380c94ecdSKeith M Wesolowski 	MEM_SFREE(regp, reglen);
83480c94ecdSKeith M Wesolowski 
83580c94ecdSKeith M Wesolowski 	/*
83680c94ecdSKeith M Wesolowski 	 * Setup resources to access the Local PCI Bus
83780c94ecdSKeith M Wesolowski 	 * If unsuccessful, return.
83880c94ecdSKeith M Wesolowski 	 * Else, read the following from the PCI space:
83980c94ecdSKeith M Wesolowski 	 * 	Sub-System Vendor ID
84080c94ecdSKeith M Wesolowski 	 * 	Sub-System Device ID
84180c94ecdSKeith M Wesolowski 	 * 	Interrupt Line
84280c94ecdSKeith M Wesolowski 	 * 	Command Register
84380c94ecdSKeith M Wesolowski 	 * Free the just allocated resources.
84480c94ecdSKeith M Wesolowski 	 */
84580c94ecdSKeith M Wesolowski 	if (pci_config_setup(cpqary3p->dip, &pci_handle) != DDI_SUCCESS)
84680c94ecdSKeith M Wesolowski 		return (CPQARY3_FAILURE);
84780c94ecdSKeith M Wesolowski 
84880c94ecdSKeith M Wesolowski 	cpqary3p->irq = pci_config_get8(pci_handle, PCI_CONF_ILINE);
84980c94ecdSKeith M Wesolowski 	cpqary3p->board_id =
85080c94ecdSKeith M Wesolowski 	    (pci_config_get16(pci_handle, PCI_CONF_SUBVENID) << 16)
85180c94ecdSKeith M Wesolowski 	    | pci_config_get16(pci_handle, PCI_CONF_SUBSYSID);
85280c94ecdSKeith M Wesolowski 
85380c94ecdSKeith M Wesolowski 	pci_config_teardown(&pci_handle);
85480c94ecdSKeith M Wesolowski 
85580c94ecdSKeith M Wesolowski 	/*
85680c94ecdSKeith M Wesolowski 	 * Verify Board Id
85780c94ecdSKeith M Wesolowski 	 * If unsupported boards are detected, return.
85880c94ecdSKeith M Wesolowski 	 * Update name for controller for driver use.
85980c94ecdSKeith M Wesolowski 	 */
86080c94ecdSKeith M Wesolowski 	cpqary3p->bddef = cpqary3_bd_getbybid(cpqary3p->board_id);
86180c94ecdSKeith M Wesolowski 	if (cpqary3p->bddef == NULL) {
86280c94ecdSKeith M Wesolowski 		cmn_err(CE_WARN,
86380c94ecdSKeith M Wesolowski 		    "CPQary3: <Bid 0x%X> Controller NOT Supported",
86480c94ecdSKeith M Wesolowski 		    cpqary3p->board_id);
86580c94ecdSKeith M Wesolowski 		return (CPQARY3_FAILURE);
86680c94ecdSKeith M Wesolowski 	}
86780c94ecdSKeith M Wesolowski 	map_len = cpqary3p->bddef->bd_maplen;
86880c94ecdSKeith M Wesolowski 	(void) strcpy(cpqary3p->hba_name, cpqary3p->bddef->bd_dispname);
86980c94ecdSKeith M Wesolowski 
87080c94ecdSKeith M Wesolowski 	/*
87180c94ecdSKeith M Wesolowski 	 * Set up a mapping for the following registers:
87280c94ecdSKeith M Wesolowski 	 * 	Inbound Doorbell
87380c94ecdSKeith M Wesolowski 	 * 	Outbound List Status
87480c94ecdSKeith M Wesolowski 	 * 	Outbound Interrupt Mask
87580c94ecdSKeith M Wesolowski 	 * 	Host Inbound Queue
87680c94ecdSKeith M Wesolowski 	 * 	Host Outbound Queue
87780c94ecdSKeith M Wesolowski 	 * 	Host Transport Configuration Table
87880c94ecdSKeith M Wesolowski 	 * Mapping of the above has been done in that order.
87980c94ecdSKeith M Wesolowski 	 */
88080c94ecdSKeith M Wesolowski 	retvalue = ddi_regs_map_setup(cpqary3p->dip,
88180c94ecdSKeith M Wesolowski 	    mem_bar0, /* INDEX_PCI_BASE0, */
88280c94ecdSKeith M Wesolowski 	    (caddr_t *)&cpqary3p->idr, (offset_t)I2O_IBDB_SET, map_len,
88380c94ecdSKeith M Wesolowski 	    &cpqary3_dev_attributes, &cpqary3p->idr_handle);
88480c94ecdSKeith M Wesolowski 
88580c94ecdSKeith M Wesolowski 	if (retvalue != DDI_SUCCESS) {
88680c94ecdSKeith M Wesolowski 		if (DDI_REGS_ACC_CONFLICT == retvalue) {
88780c94ecdSKeith M Wesolowski 			cmn_err(CE_WARN,
88880c94ecdSKeith M Wesolowski 			    "CPQary3 : Registers Mapping Conflict");
88980c94ecdSKeith M Wesolowski 		}
89080c94ecdSKeith M Wesolowski 		cmn_err(CE_WARN, "CPQary3 : Inbound Doorbell "
89180c94ecdSKeith M Wesolowski 		    "Register Mapping Failed");
89280c94ecdSKeith M Wesolowski 		return (CPQARY3_FAILURE);
89380c94ecdSKeith M Wesolowski 	}
89480c94ecdSKeith M Wesolowski 
89580c94ecdSKeith M Wesolowski 	/* PERF */
89680c94ecdSKeith M Wesolowski 	retvalue = ddi_regs_map_setup(cpqary3p->dip,
89780c94ecdSKeith M Wesolowski 	    mem_bar0, /* INDEX_PCI_BASE0, */
89880c94ecdSKeith M Wesolowski 	    (caddr_t *)&cpqary3p->odr, (offset_t)I2O_OBDB_STATUS, map_len,
89980c94ecdSKeith M Wesolowski 	    &cpqary3_dev_attributes, &cpqary3p->odr_handle);
90080c94ecdSKeith M Wesolowski 
90180c94ecdSKeith M Wesolowski 	if (retvalue != DDI_SUCCESS) {
90280c94ecdSKeith M Wesolowski 		if (DDI_REGS_ACC_CONFLICT == retvalue) {
90380c94ecdSKeith M Wesolowski 			cmn_err(CE_WARN,
90480c94ecdSKeith M Wesolowski 			    "CPQary3 : Registers Mapping Conflict");
90580c94ecdSKeith M Wesolowski 		}
90680c94ecdSKeith M Wesolowski 		cmn_err(CE_WARN,
90780c94ecdSKeith M Wesolowski 		    "CPQary3 : Outbound Doorbell Register Mapping Failed");
90880c94ecdSKeith M Wesolowski 		return (CPQARY3_FAILURE);
90980c94ecdSKeith M Wesolowski 	}
91080c94ecdSKeith M Wesolowski 
91180c94ecdSKeith M Wesolowski 	retvalue = ddi_regs_map_setup(cpqary3p->dip,
91280c94ecdSKeith M Wesolowski 	    mem_bar0, /* INDEX_PCI_BASE0, */
91380c94ecdSKeith M Wesolowski 	    (caddr_t *)&cpqary3p->odr_cl, (offset_t)I2O_OBDB_CLEAR, map_len,
91480c94ecdSKeith M Wesolowski 	    &cpqary3_dev_attributes, &cpqary3p->odr_cl_handle);
91580c94ecdSKeith M Wesolowski 
91680c94ecdSKeith M Wesolowski 	if (retvalue != DDI_SUCCESS) {
91780c94ecdSKeith M Wesolowski 		if (DDI_REGS_ACC_CONFLICT == retvalue) {
91880c94ecdSKeith M Wesolowski 			cmn_err(CE_WARN,
91980c94ecdSKeith M Wesolowski 			    "CPQary3 : Registers Mapping Conflict");
92080c94ecdSKeith M Wesolowski 		}
92180c94ecdSKeith M Wesolowski 		cmn_err(CE_WARN, "CPQary3 : Outbound Doorbell "
92280c94ecdSKeith M Wesolowski 		    "Register Clear Mapping Failed");
92380c94ecdSKeith M Wesolowski 		return (CPQARY3_FAILURE);
92480c94ecdSKeith M Wesolowski 	}
92580c94ecdSKeith M Wesolowski 
92680c94ecdSKeith M Wesolowski 	/* LOCKUP CODE */
92780c94ecdSKeith M Wesolowski 	retvalue = ddi_regs_map_setup(cpqary3p->dip,
92880c94ecdSKeith M Wesolowski 	    mem_bar0, /* INDEX_PCI_BASE0, */
92980c94ecdSKeith M Wesolowski 	    (caddr_t *)&cpqary3p->spr0, (offset_t)I2O_CTLR_INIT, map_len,
93080c94ecdSKeith M Wesolowski 	    &cpqary3_dev_attributes, &cpqary3p->spr0_handle);
93180c94ecdSKeith M Wesolowski 
93280c94ecdSKeith M Wesolowski 	if (retvalue != DDI_SUCCESS) {
93380c94ecdSKeith M Wesolowski 		if (DDI_REGS_ACC_CONFLICT == retvalue) {
93480c94ecdSKeith M Wesolowski 			cmn_err(CE_WARN,
93580c94ecdSKeith M Wesolowski 			    "CPQary3 : Registers Mapping Conflict");
93680c94ecdSKeith M Wesolowski 		}
93780c94ecdSKeith M Wesolowski 		cmn_err(CE_WARN,
93880c94ecdSKeith M Wesolowski 		    "CPQary3 : Scratch Pad register zero Mapping Failed");
93980c94ecdSKeith M Wesolowski 		return (CPQARY3_FAILURE);
94080c94ecdSKeith M Wesolowski 	}
94180c94ecdSKeith M Wesolowski 	/* LOCKUP CODE */
94280c94ecdSKeith M Wesolowski 	/* PERF */
94380c94ecdSKeith M Wesolowski 
94480c94ecdSKeith M Wesolowski 	*cleanstatus |= CPQARY3_MEM_MAPPED;
94580c94ecdSKeith M Wesolowski 
94680c94ecdSKeith M Wesolowski 	retvalue = ddi_regs_map_setup(cpqary3p->dip,
94780c94ecdSKeith M Wesolowski 	    mem_bar0, /* INDEX_PCI_BASE0, */
94880c94ecdSKeith M Wesolowski 	    (caddr_t *)&cpqary3p->isr, (offset_t)I2O_INT_STATUS, map_len,
94980c94ecdSKeith M Wesolowski 	    &cpqary3_dev_attributes, &cpqary3p->isr_handle);
95080c94ecdSKeith M Wesolowski 
95180c94ecdSKeith M Wesolowski 	if (retvalue != DDI_SUCCESS) {
95280c94ecdSKeith M Wesolowski 		if (retvalue == DDI_REGS_ACC_CONFLICT) {
95380c94ecdSKeith M Wesolowski 			cmn_err(CE_WARN,
95480c94ecdSKeith M Wesolowski 			    "CPQary3 : Registers Mapping Conflict");
95580c94ecdSKeith M Wesolowski 		}
95680c94ecdSKeith M Wesolowski 		cmn_err(CE_WARN,
95780c94ecdSKeith M Wesolowski 		    "CPQary3 : Interrupt Status Register Mapping Failed");
95880c94ecdSKeith M Wesolowski 		return (CPQARY3_FAILURE);
95980c94ecdSKeith M Wesolowski 	}
96080c94ecdSKeith M Wesolowski 
96180c94ecdSKeith M Wesolowski 	retvalue = ddi_regs_map_setup(cpqary3p->dip,
96280c94ecdSKeith M Wesolowski 	    mem_bar0, /* INDEX_PCI_BASE0, */
96380c94ecdSKeith M Wesolowski 	    (caddr_t *)&cpqary3p->imr, (offset_t)I2O_INT_MASK, map_len,
96480c94ecdSKeith M Wesolowski 	    &cpqary3_dev_attributes, &cpqary3p->imr_handle);
96580c94ecdSKeith M Wesolowski 
96680c94ecdSKeith M Wesolowski 	if (retvalue != DDI_SUCCESS) {
96780c94ecdSKeith M Wesolowski 		if (retvalue == DDI_REGS_ACC_CONFLICT) {
96880c94ecdSKeith M Wesolowski 			cmn_err(CE_WARN,
96980c94ecdSKeith M Wesolowski 			    "CPQary3 : Registers Mapping Conflict");
97080c94ecdSKeith M Wesolowski 		}
97180c94ecdSKeith M Wesolowski 		cmn_err(CE_WARN,
97280c94ecdSKeith M Wesolowski 		    "CPQary3 : Interrupt Mask Register Mapping Failed");
97380c94ecdSKeith M Wesolowski 		return (CPQARY3_FAILURE);
97480c94ecdSKeith M Wesolowski 	}
97580c94ecdSKeith M Wesolowski 
97680c94ecdSKeith M Wesolowski 	retvalue = ddi_regs_map_setup(cpqary3p->dip,
97780c94ecdSKeith M Wesolowski 	    mem_bar0, /* INDEX_PCI_BASE0, */
97880c94ecdSKeith M Wesolowski 	    (caddr_t *)&cpqary3p->ipq, (offset_t)I2O_IBPOST_Q, map_len,
97980c94ecdSKeith M Wesolowski 	    &cpqary3_dev_attributes, &cpqary3p->ipq_handle);
98080c94ecdSKeith M Wesolowski 
98180c94ecdSKeith M Wesolowski 	if (retvalue != DDI_SUCCESS) {
98280c94ecdSKeith M Wesolowski 		if (retvalue == DDI_REGS_ACC_CONFLICT) {
98380c94ecdSKeith M Wesolowski 			cmn_err(CE_WARN,
98480c94ecdSKeith M Wesolowski 			    "CPQary3 : Registers Mapping Conflict");
98580c94ecdSKeith M Wesolowski 		}
98680c94ecdSKeith M Wesolowski 		cmn_err(CE_WARN,
98780c94ecdSKeith M Wesolowski 		    "CPQary3 : Inbound Queue Register Mapping Failed");
98880c94ecdSKeith M Wesolowski 		return (CPQARY3_FAILURE);
98980c94ecdSKeith M Wesolowski 	}
99080c94ecdSKeith M Wesolowski 
99180c94ecdSKeith M Wesolowski 	retvalue = ddi_regs_map_setup(cpqary3p->dip,
99280c94ecdSKeith M Wesolowski 	    mem_bar0, /* INDEX_PCI_BASE0, */ (caddr_t *)&cpqary3p->opq,
99380c94ecdSKeith M Wesolowski 	    (offset_t)I2O_OBPOST_Q, map_len, &cpqary3_dev_attributes,
99480c94ecdSKeith M Wesolowski 	    &cpqary3p->opq_handle);
99580c94ecdSKeith M Wesolowski 
99680c94ecdSKeith M Wesolowski 	if (retvalue != DDI_SUCCESS) {
99780c94ecdSKeith M Wesolowski 		if (retvalue == DDI_REGS_ACC_CONFLICT) {
99880c94ecdSKeith M Wesolowski 			cmn_err(CE_WARN,
99980c94ecdSKeith M Wesolowski 			    "CPQary3 : Registers Mapping Conflict");
100080c94ecdSKeith M Wesolowski 		}
100180c94ecdSKeith M Wesolowski 		cmn_err(CE_WARN, "CPQary3 : Outbound Post Queue "
100280c94ecdSKeith M Wesolowski 		    "Register Mapping Failed");
100380c94ecdSKeith M Wesolowski 		return (CPQARY3_FAILURE);
100480c94ecdSKeith M Wesolowski 	}
100580c94ecdSKeith M Wesolowski 
100680c94ecdSKeith M Wesolowski 
100780c94ecdSKeith M Wesolowski 	/*
100880c94ecdSKeith M Wesolowski 	 * The config offset and memory offset have to be obtained in order to
100980c94ecdSKeith M Wesolowski 	 * locate the config table.
101080c94ecdSKeith M Wesolowski 	 */
101180c94ecdSKeith M Wesolowski 	retvalue = ddi_regs_map_setup(cpqary3p->dip,
101280c94ecdSKeith M Wesolowski 	    mem_bar0, /* INDEX_PCI_BASE0, */ (caddr_t *)&ct_cfg_offset,
101380c94ecdSKeith M Wesolowski 	    (offset_t)CT_CFG_OFFSET, map_len, &cpqary3_dev_attributes,
101480c94ecdSKeith M Wesolowski 	    &ct_cfgoff_handle);
101580c94ecdSKeith M Wesolowski 
101680c94ecdSKeith M Wesolowski 	if (retvalue != DDI_SUCCESS) {
101780c94ecdSKeith M Wesolowski 		if (retvalue == DDI_REGS_ACC_CONFLICT) {
101880c94ecdSKeith M Wesolowski 			cmn_err(CE_WARN,
101980c94ecdSKeith M Wesolowski 			    "CPQary3 : Registers Mapping Conflict");
102080c94ecdSKeith M Wesolowski 		}
102180c94ecdSKeith M Wesolowski 		cmn_err(CE_WARN, "CPQary3 : Configuration Table "
102280c94ecdSKeith M Wesolowski 		    "Register Mapping Failed");
102380c94ecdSKeith M Wesolowski 		return (CPQARY3_FAILURE);
102480c94ecdSKeith M Wesolowski 	}
102580c94ecdSKeith M Wesolowski 
102680c94ecdSKeith M Wesolowski 	retvalue = ddi_regs_map_setup(cpqary3p->dip,
102780c94ecdSKeith M Wesolowski 	    mem_bar0, /* INDEX_PCI_BASE0, */
102880c94ecdSKeith M Wesolowski 	    (caddr_t *)&ct_mem_offset, (offset_t)CT_MEM_OFFSET, map_len,
102980c94ecdSKeith M Wesolowski 	    &cpqary3_dev_attributes, &ct_memoff_handle);
103080c94ecdSKeith M Wesolowski 
103180c94ecdSKeith M Wesolowski 	if (retvalue != DDI_SUCCESS) {
103280c94ecdSKeith M Wesolowski 		if (retvalue == DDI_REGS_ACC_CONFLICT) {
103380c94ecdSKeith M Wesolowski 			cmn_err(CE_WARN,
103480c94ecdSKeith M Wesolowski 			    "CPQary3 : Registers Mapping Conflict");
103580c94ecdSKeith M Wesolowski 		}
103680c94ecdSKeith M Wesolowski 		cmn_err(CE_WARN, "CPQary3 : Configuration Table "
103780c94ecdSKeith M Wesolowski 		    "Register Mapping Failed");
103880c94ecdSKeith M Wesolowski 		return (CPQARY3_FAILURE);
103980c94ecdSKeith M Wesolowski 	}
104080c94ecdSKeith M Wesolowski 
104180c94ecdSKeith M Wesolowski 	ct_cfgmem_val = (uint32_t)ddi_get32(ct_cfgoff_handle, ct_cfg_offset);
104280c94ecdSKeith M Wesolowski 	ct_memoff_val = (uint32_t)ddi_get32(ct_memoff_handle, ct_mem_offset);
104380c94ecdSKeith M Wesolowski 
104480c94ecdSKeith M Wesolowski 	ddi_regs_map_free(&ct_cfgoff_handle);
104580c94ecdSKeith M Wesolowski 	ddi_regs_map_free(&ct_memoff_handle);
104680c94ecdSKeith M Wesolowski 
104780c94ecdSKeith M Wesolowski 	ct_cfg_bar = (ct_cfgmem_val & 0x0000ffff);
104880c94ecdSKeith M Wesolowski 	ct_mem_len = (ct_cfgmem_val & 0xffff0000);
104980c94ecdSKeith M Wesolowski 	ct_mem_len = (ct_mem_len >> 16);
105080c94ecdSKeith M Wesolowski 
105180c94ecdSKeith M Wesolowski 	if (ct_cfg_bar == 0x10) {
105280c94ecdSKeith M Wesolowski 		if (ct_mem_len) {
105380c94ecdSKeith M Wesolowski 			ct_mem_bar = mem_64_bar0;
105480c94ecdSKeith M Wesolowski 		} else {
105580c94ecdSKeith M Wesolowski 			ct_mem_bar = mem_bar0;
105680c94ecdSKeith M Wesolowski 		}
105780c94ecdSKeith M Wesolowski 
105880c94ecdSKeith M Wesolowski 	} else if (ct_cfg_bar == 0x14) {
105980c94ecdSKeith M Wesolowski 		if (ct_mem_len) {
106080c94ecdSKeith M Wesolowski 			ct_mem_bar = mem_64_bar1;
106180c94ecdSKeith M Wesolowski 		} else {
106280c94ecdSKeith M Wesolowski 			ct_mem_bar = mem_bar1;
106380c94ecdSKeith M Wesolowski 		}
106480c94ecdSKeith M Wesolowski 	} else {
106580c94ecdSKeith M Wesolowski 		return (CPQARY3_FAILURE);
106680c94ecdSKeith M Wesolowski 	}
106780c94ecdSKeith M Wesolowski 
106880c94ecdSKeith M Wesolowski 
106980c94ecdSKeith M Wesolowski 	/*
107080c94ecdSKeith M Wesolowski 	 * The Configuration Table(CT) shall be mapped in the form of a
107180c94ecdSKeith M Wesolowski 	 * structure since several members in the CT need to be accessed
107280c94ecdSKeith M Wesolowski 	 * to read and write.
107380c94ecdSKeith M Wesolowski 	 */
107480c94ecdSKeith M Wesolowski 	retvalue = ddi_regs_map_setup(cpqary3p->dip,
107580c94ecdSKeith M Wesolowski 	    ct_mem_bar, /* INDEX_PCI_BASE0/1, */
107680c94ecdSKeith M Wesolowski 	    (caddr_t *)&cpqary3p->ct, (offset_t)ct_memoff_val,
107780c94ecdSKeith M Wesolowski 	    sizeof (CfgTable_t), &cpqary3_dev_attributes, &cpqary3p->ct_handle);
107880c94ecdSKeith M Wesolowski 
107980c94ecdSKeith M Wesolowski 	if (retvalue != DDI_SUCCESS) {
108080c94ecdSKeith M Wesolowski 		if (retvalue == DDI_REGS_ACC_CONFLICT) {
108180c94ecdSKeith M Wesolowski 			cmn_err(CE_WARN,
108280c94ecdSKeith M Wesolowski 			    "CPQary3 : Registers Mapping Conflict");
108380c94ecdSKeith M Wesolowski 		}
108480c94ecdSKeith M Wesolowski 		cmn_err(CE_WARN, "CPQary3 : Configuration Table "
108580c94ecdSKeith M Wesolowski 		    "Register Mapping Failed");
108680c94ecdSKeith M Wesolowski 		return (CPQARY3_FAILURE);
108780c94ecdSKeith M Wesolowski 	}
108880c94ecdSKeith M Wesolowski 
108980c94ecdSKeith M Wesolowski 	/* PERF */
109080c94ecdSKeith M Wesolowski 
109180c94ecdSKeith M Wesolowski 	retvalue = ddi_regs_map_setup(cpqary3p->dip,
109280c94ecdSKeith M Wesolowski 	    ct_mem_bar, /* INDEX_PCI_BASE0/1, */
109380c94ecdSKeith M Wesolowski 	    (caddr_t *)&cpqary3p->cp,
109480c94ecdSKeith M Wesolowski 	    (offset_t)(ct_memoff_val + cpqary3p->ct->TransportMethodOffset),
109580c94ecdSKeith M Wesolowski 	    sizeof (CfgTrans_Perf_t), &cpqary3_dev_attributes,
109680c94ecdSKeith M Wesolowski 	    &cpqary3p->cp_handle);
109780c94ecdSKeith M Wesolowski 
109880c94ecdSKeith M Wesolowski 	if (retvalue != DDI_SUCCESS) {
109980c94ecdSKeith M Wesolowski 		if (retvalue == DDI_REGS_ACC_CONFLICT)
110080c94ecdSKeith M Wesolowski 			cmn_err(CE_WARN,
110180c94ecdSKeith M Wesolowski 			    "CPQary3 : Registers Mapping Conflict");
110280c94ecdSKeith M Wesolowski 		cmn_err(CE_WARN, "CPQary3 : Performant Transport Method Table "
110380c94ecdSKeith M Wesolowski 		    "Mapping Failed");
110480c94ecdSKeith M Wesolowski 		return (CPQARY3_FAILURE);
110580c94ecdSKeith M Wesolowski 	}
110680c94ecdSKeith M Wesolowski 
110780c94ecdSKeith M Wesolowski 	/* PERF */
110880c94ecdSKeith M Wesolowski 
110980c94ecdSKeith M Wesolowski 	return (CPQARY3_SUCCESS);
111080c94ecdSKeith M Wesolowski }
1111