xref: /titanic_44/usr/src/uts/common/io/aac/aac.c (revision 308903890e892f9c21ee582e3a52fdd67e52870b)
1 /*
2  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
3  * Use is subject to license terms.
4  */
5 
6 /*
7  * Copyright 2005-06 Adaptec, Inc.
8  * Copyright (c) 2005-06 Adaptec Inc., Achim Leubner
9  * Copyright (c) 2000 Michael Smith
10  * Copyright (c) 2001 Scott Long
11  * Copyright (c) 2000 BSDi
12  * All rights reserved.
13  *
14  * Redistribution and use in source and binary forms, with or without
15  * modification, are permitted provided that the following conditions
16  * are met:
17  * 1. Redistributions of source code must retain the above copyright
18  *    notice, this list of conditions and the following disclaimer.
19  * 2. Redistributions in binary form must reproduce the above copyright
20  *    notice, this list of conditions and the following disclaimer in the
21  *    documentation and/or other materials provided with the distribution.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  */
35 #pragma ident	"%Z%%M%	%I%	%E% SMI"
36 
37 #include <sys/modctl.h>
38 #include <sys/conf.h>
39 #include <sys/cmn_err.h>
40 #include <sys/ddi.h>
41 #include <sys/devops.h>
42 #include <sys/pci.h>
43 #include <sys/types.h>
44 #include <sys/ddidmareq.h>
45 #include <sys/scsi/scsi.h>
46 #include <sys/ksynch.h>
47 #include <sys/sunddi.h>
48 #include <sys/byteorder.h>
49 #include "aac_regs.h"
50 #include "aac.h"
51 
52 /*
53  * FMA header files
54  */
55 #include <sys/ddifm.h>
56 #include <sys/fm/protocol.h>
57 #include <sys/fm/util.h>
58 #include <sys/fm/io/ddi.h>
59 
60 /*
61  * For minor nodes created by the SCSA framework, minor numbers are
62  * formed by left-shifting instance by INST_MINOR_SHIFT and OR in a
63  * number less than 64.
64  *
65  * To support cfgadm, need to confirm the SCSA framework by creating
66  * devctl/scsi and driver specific minor nodes under SCSA format,
67  * and calling scsi_hba_xxx() functions aacordingly.
68  */
69 
70 #define	AAC_MINOR		32
71 #define	INST2AAC(x)		(((x) << INST_MINOR_SHIFT) | AAC_MINOR)
72 #define	AAC_SCSA_MINOR(x)	((x) & TRAN_MINOR_MASK)
73 #define	AAC_IS_SCSA_NODE(x)	((x) == DEVCTL_MINOR || (x) == SCSI_MINOR)
74 
75 #define	AAC_TRAN2SOFTS(tran) ((struct aac_softstate *)(tran)->tran_hba_private)
76 #define	AAC_DIP2TRAN(dip)	((scsi_hba_tran_t *)ddi_get_driver_private(dip))
77 #define	AAC_DIP2SOFTS(dip)	(AAC_TRAN2SOFTS(AAC_DIP2TRAN(dip)))
78 #define	PKT2AC(pkt)		((struct aac_cmd *)(pkt)->pkt_ha_private)
79 #define	AAC_BUSYWAIT(cond, timeout /* in millisecond */) { \
80 		if (!(cond)) { \
81 			int count = (timeout) * 10; \
82 			while (count) { \
83 				drv_usecwait(100); \
84 				if (cond) \
85 					break; \
86 				count--; \
87 			} \
88 			(timeout) = (count + 9) / 10; \
89 		} \
90 	}
91 
92 #define	AAC_SENSE_DATA_DESCR_LEN \
93 	(sizeof (struct scsi_descr_sense_hdr) + \
94 	sizeof (struct scsi_information_sense_descr))
95 #define	AAC_ARQ64_LENGTH \
96 	(sizeof (struct scsi_arq_status) + \
97 	AAC_SENSE_DATA_DESCR_LEN - SENSE_LENGTH)
98 
99 /* NOTE: GETG4ADDRTL(cdbp) is int32_t */
100 #define	AAC_GETGXADDR(cmdlen, cdbp) \
101 	((cmdlen == 6) ? GETG0ADDR(cdbp) : \
102 	(cmdlen == 10) ? (uint32_t)GETG1ADDR(cdbp) : \
103 	((uint64_t)GETG4ADDR(cdbp) << 32) | (uint32_t)GETG4ADDRTL(cdbp))
104 
105 #define	AAC_CDB_INQUIRY_CMDDT	0x02
106 #define	AAC_CDB_INQUIRY_EVPD	0x01
107 #define	AAC_VPD_PAGE_CODE	1
108 #define	AAC_VPD_PAGE_LENGTH	3
109 #define	AAC_VPD_PAGE_DATA	4
110 #define	AAC_VPD_ID_CODESET	0
111 #define	AAC_VPD_ID_TYPE		1
112 #define	AAC_VPD_ID_LENGTH	3
113 #define	AAC_VPD_ID_DATA		4
114 
115 /* Return the size of FIB with data part type data_type */
116 #define	AAC_FIB_SIZEOF(data_type) \
117 	(sizeof (struct aac_fib_header) + sizeof (data_type))
118 /* Return the container size defined in mir */
119 #define	AAC_MIR_SIZE(softs, acc, mir) \
120 	(((softs)->flags & AAC_FLAGS_LBA_64BIT) ? \
121 	(uint64_t)ddi_get32((acc), &(mir)->MntObj.Capacity) + \
122 	((uint64_t)ddi_get32((acc), &(mir)->MntObj.CapacityHigh) << 32) : \
123 	(uint64_t)ddi_get32((acc), &(mir)->MntObj.Capacity))
124 
125 /* The last entry of aac_cards[] is for unknown cards */
126 #define	AAC_UNKNOWN_CARD \
127 	(sizeof (aac_cards) / sizeof (struct aac_card_type) - 1)
128 #define	CARD_IS_UNKNOWN(i)	(i == AAC_UNKNOWN_CARD)
129 #define	BUF_IS_READ(bp)		((bp)->b_flags & B_READ)
130 #define	AAC_IS_Q_EMPTY(q)	((q)->q_head == NULL)
131 #define	AAC_CMDQ(acp)		(!((acp)->flags & AAC_CMD_SYNC))
132 
133 #define	PCI_MEM_GET32(softs, off) \
134 	ddi_get32((softs)->pci_mem_handle, \
135 	    (uint32_t *)((softs)->pci_mem_base_vaddr + (off)))
136 #define	PCI_MEM_PUT32(softs, off, val) \
137 	ddi_put32((softs)->pci_mem_handle, \
138 	    (uint32_t *)((softs)->pci_mem_base_vaddr + (off)), \
139 	    (uint32_t)(val))
140 #define	PCI_MEM_GET16(softs, off) \
141 	ddi_get16((softs)->pci_mem_handle, \
142 	(uint16_t *)((softs)->pci_mem_base_vaddr + (off)))
143 #define	PCI_MEM_PUT16(softs, off, val) \
144 	ddi_put16((softs)->pci_mem_handle, \
145 	(uint16_t *)((softs)->pci_mem_base_vaddr + (off)), (uint16_t)(val))
146 /* Write host data at valp to device mem[off] repeatedly count times */
147 #define	PCI_MEM_REP_PUT8(softs, off, valp, count) \
148 	ddi_rep_put8((softs)->pci_mem_handle, (uint8_t *)(valp), \
149 	    (uint8_t *)((softs)->pci_mem_base_vaddr + (off)), \
150 	    count, DDI_DEV_AUTOINCR)
151 /* Read device data at mem[off] to host addr valp repeatedly count times */
152 #define	PCI_MEM_REP_GET8(softs, off, valp, count) \
153 	ddi_rep_get8((softs)->pci_mem_handle, (uint8_t *)(valp), \
154 	    (uint8_t *)((softs)->pci_mem_base_vaddr + (off)), \
155 	    count, DDI_DEV_AUTOINCR)
156 #define	AAC_GET_FIELD8(acc, d, s, field) \
157 	(d)->field = ddi_get8(acc, (uint8_t *)&(s)->field)
158 #define	AAC_GET_FIELD32(acc, d, s, field) \
159 	(d)->field = ddi_get32(acc, (uint32_t *)&(s)->field)
160 #define	AAC_GET_FIELD64(acc, d, s, field) \
161 	(d)->field = ddi_get64(acc, (uint64_t *)&(s)->field)
162 #define	AAC_REP_GET_FIELD8(acc, d, s, field, r) \
163 	ddi_rep_get8((acc), (uint8_t *)&(d)->field, \
164 	    (uint8_t *)&(s)->field, (r), DDI_DEV_AUTOINCR)
165 #define	AAC_REP_GET_FIELD32(acc, d, s, field, r) \
166 	ddi_rep_get32((acc), (uint32_t *)&(d)->field, \
167 	    (uint32_t *)&(s)->field, (r), DDI_DEV_AUTOINCR)
168 
169 #define	AAC_ENABLE_INTR(softs) { \
170 		if (softs->flags & AAC_FLAGS_NEW_COMM) \
171 			PCI_MEM_PUT32(softs, AAC_OIMR, ~AAC_DB_INTR_NEW); \
172 		else \
173 			PCI_MEM_PUT32(softs, AAC_OIMR, ~AAC_DB_INTR_BITS); \
174 	}
175 
176 #define	AAC_DISABLE_INTR(softs)		PCI_MEM_PUT32(softs, AAC_OIMR, ~0)
177 #define	AAC_STATUS_CLR(softs, mask)	PCI_MEM_PUT32(softs, AAC_ODBR, mask)
178 #define	AAC_STATUS_GET(softs)		PCI_MEM_GET32(softs, AAC_ODBR)
179 #define	AAC_NOTIFY(softs, val)		PCI_MEM_PUT32(softs, AAC_IDBR, val)
180 #define	AAC_OUTB_GET(softs)		PCI_MEM_GET32(softs, AAC_OQUE)
181 #define	AAC_OUTB_SET(softs, val)	PCI_MEM_PUT32(softs, AAC_OQUE, val)
182 #define	AAC_FWSTATUS_GET(softs)	\
183 	((softs)->aac_if.aif_get_fwstatus(softs))
184 #define	AAC_MAILBOX_GET(softs, mb) \
185 	((softs)->aac_if.aif_get_mailbox((softs), (mb)))
186 #define	AAC_MAILBOX_SET(softs, cmd, arg0, arg1, arg2, arg3) \
187 	((softs)->aac_if.aif_set_mailbox((softs), (cmd), \
188 	    (arg0), (arg1), (arg2), (arg3)))
189 
190 #define	AAC_THROTTLE_DRAIN	-1
191 
192 #define	AAC_QUIESCE_TICK	1	/* 1 second */
193 #define	AAC_QUIESCE_TIMEOUT	60	/* 60 seconds */
194 #define	AAC_DEFAULT_TICK	10	/* 10 seconds */
195 #define	AAC_SYNC_TICK		(30*60)	/* 30 minutes */
196 
197 /* Poll time for aac_do_poll_io() */
198 #define	AAC_POLL_TIME		60	/* 60 seconds */
199 
200 /*
201  * Hardware access functions
202  */
203 static int aac_rx_get_fwstatus(struct aac_softstate *);
204 static int aac_rx_get_mailbox(struct aac_softstate *, int);
205 static void aac_rx_set_mailbox(struct aac_softstate *, uint32_t, uint32_t,
206     uint32_t, uint32_t, uint32_t);
207 static int aac_rkt_get_fwstatus(struct aac_softstate *);
208 static int aac_rkt_get_mailbox(struct aac_softstate *, int);
209 static void aac_rkt_set_mailbox(struct aac_softstate *, uint32_t, uint32_t,
210     uint32_t, uint32_t, uint32_t);
211 
212 /*
213  * SCSA function prototypes
214  */
215 static int aac_attach(dev_info_t *, ddi_attach_cmd_t);
216 static int aac_detach(dev_info_t *, ddi_detach_cmd_t);
217 static int aac_reset(dev_info_t *, ddi_reset_cmd_t);
218 
219 /*
220  * Interrupt handler functions
221  */
222 static uint_t aac_intr_old(caddr_t);
223 static uint_t aac_intr_new(caddr_t);
224 static uint_t aac_softintr(caddr_t);
225 
226 /*
227  * Internal functions in attach
228  */
229 static int aac_check_card_type(struct aac_softstate *);
230 static int aac_check_firmware(struct aac_softstate *);
231 static int aac_common_attach(struct aac_softstate *);
232 static void aac_common_detach(struct aac_softstate *);
233 static int aac_probe_containers(struct aac_softstate *);
234 static int aac_alloc_comm_space(struct aac_softstate *);
235 static int aac_setup_comm_space(struct aac_softstate *);
236 static void aac_free_comm_space(struct aac_softstate *);
237 static int aac_hba_setup(struct aac_softstate *);
238 
239 /*
240  * Sync FIB operation functions
241  */
242 int aac_sync_mbcommand(struct aac_softstate *, uint32_t, uint32_t,
243     uint32_t, uint32_t, uint32_t, uint32_t *);
244 static int aac_sync_fib(struct aac_softstate *, uint16_t, uint16_t);
245 
246 /*
247  * Command queue operation functions
248  */
249 static void aac_cmd_initq(struct aac_cmd_queue *);
250 static void aac_cmd_enqueue(struct aac_cmd_queue *, struct aac_cmd *);
251 static struct aac_cmd *aac_cmd_dequeue(struct aac_cmd_queue *);
252 static void aac_cmd_delete(struct aac_cmd_queue *, struct aac_cmd *);
253 
254 /*
255  * FIB queue operation functions
256  */
257 static int aac_fib_enqueue(struct aac_softstate *, int, uint32_t, uint32_t);
258 static int aac_fib_dequeue(struct aac_softstate *, int, int *);
259 
260 /*
261  * Slot operation functions
262  */
263 static int aac_create_slots(struct aac_softstate *);
264 static void aac_destroy_slots(struct aac_softstate *);
265 static void aac_alloc_fibs(struct aac_softstate *);
266 static void aac_destroy_fibs(struct aac_softstate *);
267 static struct aac_slot *aac_get_slot(struct aac_softstate *);
268 static void aac_release_slot(struct aac_softstate *, struct aac_slot *);
269 static int aac_alloc_fib(struct aac_softstate *, struct aac_slot *);
270 static void aac_free_fib(struct aac_slot *);
271 
272 /*
273  * Internal functions
274  */
275 static void aac_cmd_fib_header(struct aac_softstate *, struct aac_slot *,
276     uint16_t, uint16_t);
277 static void aac_cmd_fib_rawio(struct aac_softstate *, struct aac_cmd *);
278 static void aac_cmd_fib_brw64(struct aac_softstate *, struct aac_cmd *);
279 static void aac_cmd_fib_brw(struct aac_softstate *, struct aac_cmd *);
280 static void aac_cmd_fib_sync(struct aac_softstate *, struct aac_cmd *);
281 static void aac_cmd_fib_scsi32(struct aac_softstate *, struct aac_cmd *);
282 static void aac_cmd_fib_scsi64(struct aac_softstate *, struct aac_cmd *);
283 static void aac_start_waiting_io(struct aac_softstate *);
284 static void aac_drain_comp_q(struct aac_softstate *);
285 int aac_do_io(struct aac_softstate *, struct aac_cmd *);
286 static int aac_do_poll_io(struct aac_softstate *, struct aac_cmd *);
287 static int aac_do_sync_io(struct aac_softstate *, struct aac_cmd *);
288 static int aac_send_command(struct aac_softstate *, struct aac_slot *);
289 static void aac_cmd_timeout(struct aac_softstate *);
290 static int aac_dma_sync_ac(struct aac_cmd *);
291 static int aac_shutdown(struct aac_softstate *);
292 static int aac_reset_adapter(struct aac_softstate *);
293 static int aac_do_quiesce(struct aac_softstate *softs);
294 static int aac_do_unquiesce(struct aac_softstate *softs);
295 static void aac_unhold_bus(struct aac_softstate *, int);
296 static void aac_set_throttle(struct aac_softstate *, struct aac_container *,
297     int, int);
298 
299 /*
300  * Adapter Initiated FIB handling function
301  */
302 static int aac_handle_aif(struct aac_softstate *, struct aac_fib *);
303 
304 /*
305  * Timeout handling thread function
306  */
307 static void aac_daemon(void *);
308 
309 /*
310  * IOCTL interface related functions
311  */
312 static int aac_open(dev_t *, int, int, cred_t *);
313 static int aac_close(dev_t, int, int, cred_t *);
314 static int aac_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
315 extern int aac_do_ioctl(struct aac_softstate *, dev_t, int, intptr_t, int);
316 
317 /*
318  * FMA Prototypes
319  */
320 static void aac_fm_init(struct aac_softstate *);
321 static void aac_fm_fini(struct aac_softstate *);
322 static int aac_fm_error_cb(dev_info_t *, ddi_fm_error_t *, const void *);
323 int aac_check_acc_handle(ddi_acc_handle_t);
324 int aac_check_dma_handle(ddi_dma_handle_t);
325 void aac_fm_ereport(struct aac_softstate *, char *);
326 
327 #ifdef DEBUG
328 /*
329  * UART	debug output support
330  */
331 
332 #define	AAC_PRINT_BUFFER_SIZE		512
333 #define	AAC_PRINT_TIMEOUT		250	/* 1/4 sec. = 250 msec. */
334 
335 #define	AAC_FW_DBG_STRLEN_OFFSET	0x00
336 #define	AAC_FW_DBG_FLAGS_OFFSET		0x04
337 #define	AAC_FW_DBG_BLED_OFFSET		0x08
338 
339 static int aac_get_fw_debug_buffer(struct aac_softstate *);
340 static void aac_print_scmd(struct aac_softstate *, struct aac_cmd *);
341 static void aac_print_aif(struct aac_softstate *, struct aac_aif_command *);
342 
343 static char aac_prt_buf[AAC_PRINT_BUFFER_SIZE];
344 static char aac_fmt[] = " %s";
345 static char aac_fmt_header[] = " %s.%d: %s";
346 static kmutex_t aac_prt_mutex;
347 
348 /*
349  * Debug flags to be put into the softstate flags field
350  * when initialized
351  */
352 uint32_t aac_debug_flags =
353 /*    AACDB_FLAGS_KERNEL_PRINT | */
354 /*    AACDB_FLAGS_FW_PRINT |	*/
355 /*    AACDB_FLAGS_MISC |	*/
356 /*    AACDB_FLAGS_FUNC1 |	*/
357 /*    AACDB_FLAGS_FUNC2 |	*/
358 /*    AACDB_FLAGS_SCMD |	*/
359 /*    AACDB_FLAGS_AIF |		*/
360 /*    AACDB_FLAGS_FIB |		*/
361 /*    AACDB_FLAGS_IOCTL |	*/
362 0;
363 
364 #endif /* DEBUG */
365 
366 static struct cb_ops aac_cb_ops = {
367 	aac_open,	/* open */
368 	aac_close,	/* close */
369 	nodev,		/* strategy */
370 	nodev,		/* print */
371 	nodev,		/* dump */
372 	nodev,		/* read */
373 	nodev,		/* write */
374 	aac_ioctl,	/* ioctl */
375 	nodev,		/* devmap */
376 	nodev,		/* mmap */
377 	nodev,		/* segmap */
378 	nochpoll,	/* poll */
379 	ddi_prop_op,	/* cb_prop_op */
380 	NULL,		/* streamtab */
381 	D_64BIT | D_NEW | D_MP | D_HOTPLUG,	/* cb_flag */
382 	CB_REV,		/* cb_rev */
383 	nodev,		/* async I/O read entry point */
384 	nodev		/* async I/O write entry point */
385 };
386 
387 static struct dev_ops aac_dev_ops = {
388 	DEVO_REV,
389 	0,
390 	nodev,
391 	nulldev,
392 	nulldev,
393 	aac_attach,
394 	aac_detach,
395 	aac_reset,
396 	&aac_cb_ops,
397 	NULL,
398 	NULL
399 };
400 
401 static struct modldrv aac_modldrv = {
402 	&mod_driverops,
403 	"AAC Driver " AAC_DRIVER_VERSION,
404 	&aac_dev_ops,
405 };
406 
407 static struct modlinkage aac_modlinkage = {
408 	MODREV_1,
409 	&aac_modldrv,
410 	NULL
411 };
412 
413 static struct aac_softstate  *aac_softstatep;
414 
415 /*
416  * Supported card list
417  * ordered in vendor id, subvendor id, subdevice id, and device id
418  */
419 static struct aac_card_type aac_cards[] = {
420 	{0x1028, 0x1, 0x1028, 0x1, AAC_HWIF_I960RX,
421 	    AAC_FLAGS_NO4GB | AAC_FLAGS_34SG, AAC_TYPE_SCSI,
422 	    "Dell", "PERC 3/Di"},
423 	{0x1028, 0x2, 0x1028, 0x2, AAC_HWIF_I960RX,
424 	    AAC_FLAGS_NO4GB | AAC_FLAGS_34SG, AAC_TYPE_SCSI,
425 	    "Dell", "PERC 3/Di"},
426 	{0x1028, 0x3, 0x1028, 0x3, AAC_HWIF_I960RX,
427 	    AAC_FLAGS_NO4GB | AAC_FLAGS_34SG, AAC_TYPE_SCSI,
428 	    "Dell", "PERC 3/Si"},
429 	{0x1028, 0x8, 0x1028, 0xcf, AAC_HWIF_I960RX,
430 	    AAC_FLAGS_NO4GB | AAC_FLAGS_34SG, AAC_TYPE_SCSI,
431 	    "Dell", "PERC 3/Di"},
432 	{0x1028, 0x4, 0x1028, 0xd0, AAC_HWIF_I960RX,
433 	    AAC_FLAGS_NO4GB | AAC_FLAGS_34SG, AAC_TYPE_SCSI,
434 	    "Dell", "PERC 3/Si"},
435 	{0x1028, 0x2, 0x1028, 0xd1, AAC_HWIF_I960RX,
436 	    AAC_FLAGS_NO4GB | AAC_FLAGS_34SG, AAC_TYPE_SCSI,
437 	    "Dell", "PERC 3/Di"},
438 	{0x1028, 0x2, 0x1028, 0xd9, AAC_HWIF_I960RX,
439 	    AAC_FLAGS_NO4GB | AAC_FLAGS_34SG, AAC_TYPE_SCSI,
440 	    "Dell", "PERC 3/Di"},
441 	{0x1028, 0xa, 0x1028, 0x106, AAC_HWIF_I960RX,
442 	    AAC_FLAGS_NO4GB | AAC_FLAGS_34SG, AAC_TYPE_SCSI,
443 	    "Dell", "PERC 3/Di"},
444 	{0x1028, 0xa, 0x1028, 0x11b, AAC_HWIF_I960RX,
445 	    AAC_FLAGS_NO4GB | AAC_FLAGS_34SG, AAC_TYPE_SCSI,
446 	    "Dell", "PERC 3/Di"},
447 	{0x1028, 0xa, 0x1028, 0x121, AAC_HWIF_I960RX,
448 	    AAC_FLAGS_NO4GB | AAC_FLAGS_34SG, AAC_TYPE_SCSI,
449 	    "Dell", "PERC 3/Di"},
450 	{0x9005, 0x285, 0x1028, 0x287, AAC_HWIF_I960RX,
451 	    AAC_FLAGS_NO4GB | AAC_FLAGS_34SG | AAC_FLAGS_256FIBS, AAC_TYPE_SCSI,
452 	    "Dell", "PERC 320/DC"},
453 	{0x9005, 0x285, 0x1028, 0x291, AAC_HWIF_I960RX,
454 	    AAC_FLAGS_17SG, AAC_TYPE_SATA, "Dell", "CERC SR2"},
455 
456 	{0x9005, 0x285, 0x1014, 0x2f2, AAC_HWIF_I960RX,
457 	    0, AAC_TYPE_SCSI, "IBM", "ServeRAID 8i"},
458 	{0x9005, 0x285, 0x1014, 0x34d, AAC_HWIF_I960RX,
459 	    0, AAC_TYPE_SAS, "IBM", "ServeRAID 8s"},
460 	{0x9005, 0x286, 0x1014, 0x9580, AAC_HWIF_RKT,
461 	    0, AAC_TYPE_SAS, "IBM", "ServeRAID 8k"},
462 
463 	{0x9005, 0x285, 0x103c, 0x3227, AAC_HWIF_I960RX,
464 	    AAC_FLAGS_17SG, AAC_TYPE_SATA, "Adaptec", "2610SA"},
465 	{0x9005, 0x285, 0xe11, 0x295, AAC_HWIF_I960RX,
466 	    AAC_FLAGS_17SG, AAC_TYPE_SATA, "Adaptec", "2610SA"},
467 
468 	{0x9005, 0x285, 0x9005, 0x285, AAC_HWIF_I960RX,
469 	    AAC_FLAGS_NO4GB | AAC_FLAGS_34SG | AAC_FLAGS_256FIBS, AAC_TYPE_SCSI,
470 	    "Adaptec", "2200S"},
471 	{0x9005, 0x285, 0x9005, 0x286, AAC_HWIF_I960RX,
472 	    AAC_FLAGS_NO4GB | AAC_FLAGS_34SG | AAC_FLAGS_256FIBS, AAC_TYPE_SCSI,
473 	    "Adaptec", "2120S"},
474 	{0x9005, 0x285, 0x9005, 0x287, AAC_HWIF_I960RX,
475 	    AAC_FLAGS_NO4GB | AAC_FLAGS_34SG | AAC_FLAGS_256FIBS, AAC_TYPE_SCSI,
476 	    "Adaptec", "2200S"},
477 	{0x9005, 0x285, 0x9005, 0x288, AAC_HWIF_I960RX,
478 	    0, AAC_TYPE_SCSI, "Adaptec", "3230S"},
479 	{0x9005, 0x285, 0x9005, 0x289, AAC_HWIF_I960RX,
480 	    0, AAC_TYPE_SCSI, "Adaptec", "3240S"},
481 	{0x9005, 0x285, 0x9005, 0x28a, AAC_HWIF_I960RX,
482 	    0, AAC_TYPE_SCSI, "Adaptec", "2020ZCR"},
483 	{0x9005, 0x285, 0x9005, 0x28b, AAC_HWIF_I960RX,
484 	    0, AAC_TYPE_SCSI, "Adaptec", "2025ZCR"},
485 	{0x9005, 0x286, 0x9005, 0x28c, AAC_HWIF_RKT,
486 	    0, AAC_TYPE_SCSI, "Adaptec", "2230S"},
487 	{0x9005, 0x286, 0x9005, 0x28d, AAC_HWIF_RKT,
488 	    0, AAC_TYPE_SCSI, "Adaptec", "2130S"},
489 	{0x9005, 0x285, 0x9005, 0x28e, AAC_HWIF_I960RX,
490 	    0, AAC_TYPE_SATA, "Adaptec", "2020SA"},
491 	{0x9005, 0x285, 0x9005, 0x28f, AAC_HWIF_I960RX,
492 	    0, AAC_TYPE_SATA, "Adaptec", "2025SA"},
493 	{0x9005, 0x285, 0x9005, 0x290, AAC_HWIF_I960RX,
494 	    AAC_FLAGS_17SG, AAC_TYPE_SATA, "Adaptec", "2410SA"},
495 	{0x9005, 0x285, 0x9005, 0x292, AAC_HWIF_I960RX,
496 	    AAC_FLAGS_17SG, AAC_TYPE_SATA, "Adaptec", "2810SA"},
497 	{0x9005, 0x285, 0x9005, 0x293, AAC_HWIF_I960RX,
498 	    AAC_FLAGS_17SG, AAC_TYPE_SATA, "Adaptec", "21610SA"},
499 	{0x9005, 0x285, 0x9005, 0x294, AAC_HWIF_I960RX,
500 	    0, AAC_TYPE_SATA, "Adaptec", "2026ZCR"},
501 	{0x9005, 0x285, 0x9005, 0x296, AAC_HWIF_I960RX,
502 	    0, AAC_TYPE_SCSI, "Adaptec", "2240S"},
503 	{0x9005, 0x285, 0x9005, 0x297, AAC_HWIF_I960RX,
504 	    0, AAC_TYPE_SAS, "Adaptec", "4005SAS"},
505 	{0x9005, 0x285, 0x9005, 0x298, AAC_HWIF_I960RX,
506 	    0, AAC_TYPE_SAS, "Adaptec", "RAID 4000"},
507 	{0x9005, 0x285, 0x9005, 0x299, AAC_HWIF_I960RX,
508 	    0, AAC_TYPE_SAS, "Adaptec", "4800SAS"},
509 	{0x9005, 0x285, 0x9005, 0x29a, AAC_HWIF_I960RX,
510 	    0, AAC_TYPE_SAS, "Adaptec", "4805SAS"},
511 	{0x9005, 0x286, 0x9005, 0x29b, AAC_HWIF_RKT,
512 	    0, AAC_TYPE_SATA, "Adaptec", "2820SA"},
513 	{0x9005, 0x286, 0x9005, 0x29c, AAC_HWIF_RKT,
514 	    0, AAC_TYPE_SATA, "Adaptec", "2620SA"},
515 	{0x9005, 0x286, 0x9005, 0x29d, AAC_HWIF_RKT,
516 	    0, AAC_TYPE_SATA, "Adaptec", "2420SA"},
517 	{0x9005, 0x286, 0x9005, 0x29e, AAC_HWIF_RKT,
518 	    0, AAC_TYPE_SATA, "ICP", "9024RO"},
519 	{0x9005, 0x286, 0x9005, 0x29f, AAC_HWIF_RKT,
520 	    0, AAC_TYPE_SATA, "ICP", "9014RO"},
521 	{0x9005, 0x286, 0x9005, 0x2a0, AAC_HWIF_RKT,
522 	    0, AAC_TYPE_SATA, "ICP", "9047MA"},
523 	{0x9005, 0x286, 0x9005, 0x2a1, AAC_HWIF_RKT,
524 	    0, AAC_TYPE_SATA, "ICP", "9087MA"},
525 	{0x9005, 0x285, 0x9005, 0x2a4, AAC_HWIF_I960RX,
526 	    0, AAC_TYPE_SAS, "ICP", "9085LI"},
527 	{0x9005, 0x285, 0x9005, 0x2a5, AAC_HWIF_I960RX,
528 	    0, AAC_TYPE_SAS, "ICP", "5085BR"},
529 	{0x9005, 0x286, 0x9005, 0x2a6, AAC_HWIF_RKT,
530 	    0, AAC_TYPE_SATA, "ICP", "9067MA"},
531 	{0x9005, 0x285, 0x9005, 0x2b5, AAC_HWIF_I960RX,
532 	    0, AAC_TYPE_SAS, "Adaptec", "RAID 5445"},
533 	{0x9005, 0x285, 0x9005, 0x2b6, AAC_HWIF_I960RX,
534 	    0, AAC_TYPE_SAS, "Adaptec", "RAID 5805"},
535 	{0x9005, 0x285, 0x9005, 0x2b7, AAC_HWIF_I960RX,
536 	    0, AAC_TYPE_SAS, "Adaptec", "RAID 5085"},
537 	{0x9005, 0x285, 0x9005, 0x2b8, AAC_HWIF_I960RX,
538 	    0, AAC_TYPE_SAS, "ICP", "RAID ICP5445SL"},
539 	{0x9005, 0x285, 0x9005, 0x2b9, AAC_HWIF_I960RX,
540 	    0, AAC_TYPE_SAS, "ICP", "RAID ICP5085SL"},
541 	{0x9005, 0x285, 0x9005, 0x2ba, AAC_HWIF_I960RX,
542 	    0, AAC_TYPE_SAS, "ICP", "RAID ICP5805SL"},
543 
544 	{0, 0, 0, 0, AAC_HWIF_UNKNOWN,
545 	    0, AAC_TYPE_UNKNOWN, "Unknown", "AAC card"},
546 };
547 
548 /*
549  * Hardware access functions for i960 based cards
550  */
551 static struct aac_interface aac_rx_interface = {
552 	aac_rx_get_fwstatus,
553 	aac_rx_get_mailbox,
554 	aac_rx_set_mailbox
555 };
556 
557 /*
558  * Hardware access functions for Rocket based cards
559  */
560 static struct aac_interface aac_rkt_interface = {
561 	aac_rkt_get_fwstatus,
562 	aac_rkt_get_mailbox,
563 	aac_rkt_set_mailbox
564 };
565 
566 ddi_device_acc_attr_t aac_acc_attr = {
567 	DDI_DEVICE_ATTR_V0,
568 	DDI_STRUCTURE_LE_ACC,
569 	DDI_STRICTORDER_ACC,
570 	DDI_FLAGERR_ACC
571 };
572 
573 static struct {
574 	int	size;
575 	int	notify;
576 } aac_qinfo[] = {
577 	{AAC_HOST_NORM_CMD_ENTRIES, AAC_DB_COMMAND_NOT_FULL},
578 	{AAC_HOST_HIGH_CMD_ENTRIES, 0},
579 	{AAC_ADAP_NORM_CMD_ENTRIES, AAC_DB_COMMAND_READY},
580 	{AAC_ADAP_HIGH_CMD_ENTRIES, 0},
581 	{AAC_HOST_NORM_RESP_ENTRIES, AAC_DB_RESPONSE_NOT_FULL},
582 	{AAC_HOST_HIGH_RESP_ENTRIES, 0},
583 	{AAC_ADAP_NORM_RESP_ENTRIES, AAC_DB_RESPONSE_READY},
584 	{AAC_ADAP_HIGH_RESP_ENTRIES, 0}
585 };
586 
587 /*
588  * Default aac dma attributes
589  */
590 static ddi_dma_attr_t aac_dma_attr = {
591 	DMA_ATTR_V0,
592 	0,		/* lowest usable address */
593 	0xffffffffull,	/* high DMA address range */
594 	0xffffffffull,	/* DMA counter register */
595 	AAC_DMA_ALIGN,	/* DMA address alignment */
596 	1,		/* DMA burstsizes */
597 	1,		/* min effective DMA size */
598 	0xffffffffull,	/* max DMA xfer size */
599 	0xffffffffull,	/* segment boundary */
600 	1,		/* s/g list length */
601 	AAC_BLK_SIZE,	/* granularity of device */
602 	DDI_DMA_FLAGERR	/* DMA transfer flags */
603 };
604 
605 static int aac_tick = AAC_DEFAULT_TICK;	/* tick for the internal timer */
606 static uint32_t aac_timebase = 0;	/* internal timer in seconds */
607 static uint32_t aac_sync_time = 0;	/* next time to sync. with firmware */
608 
609 /*
610  * Warlock directives
611  *
612  * Different variables with the same types have to be protected by the
613  * same mutex; otherwise, warlock will complain with "variables don't
614  * seem to be protected consistently". For example,
615  * aac_softstate::{q_wait, q_comp} are type of aac_cmd_queue, and protected
616  * by aac_softstate::{io_lock, q_comp_mutex} respectively. We have to
617  * declare them as protected explictly at aac_cmd_dequeue().
618  */
619 _NOTE(SCHEME_PROTECTS_DATA("unique per pkt", scsi_pkt scsi_cdb scsi_status \
620     scsi_arq_status scsi_descr_sense_hdr scsi_information_sense_descr \
621     mode_format mode_geometry mode_header aac_cmd))
622 _NOTE(SCHEME_PROTECTS_DATA("unique per aac_cmd", aac_fib ddi_dma_cookie_t \
623     aac_sge))
624 _NOTE(SCHEME_PROTECTS_DATA("unique per aac_fib", aac_blockread aac_blockwrite \
625     aac_blockread64 aac_raw_io aac_sg_entry aac_sg_entry64 aac_sg_entryraw \
626     aac_sg_table aac_srb))
627 _NOTE(SCHEME_PROTECTS_DATA("unique to sync fib and cdb", scsi_inquiry))
628 _NOTE(SCHEME_PROTECTS_DATA("stable data", scsi_device scsi_address))
629 
630 int
631 _init(void)
632 {
633 	int rval = 0;
634 
635 #ifdef DEBUG
636 	mutex_init(&aac_prt_mutex, NULL, MUTEX_DRIVER, NULL);
637 #endif
638 	DBCALLED(NULL, 1);
639 
640 	if ((rval = ddi_soft_state_init((void *)&aac_softstatep,
641 	    sizeof (struct aac_softstate), 0)) != 0)
642 		goto error;
643 
644 	if ((rval = scsi_hba_init(&aac_modlinkage)) != 0) {
645 		ddi_soft_state_fini((void *)&aac_softstatep);
646 		goto error;
647 	}
648 
649 	if ((rval = mod_install(&aac_modlinkage)) != 0) {
650 		ddi_soft_state_fini((void *)&aac_softstatep);
651 		scsi_hba_fini(&aac_modlinkage);
652 		goto error;
653 	}
654 	return (rval);
655 
656 error:
657 	AACDB_PRINT(NULL, CE_WARN, "Mod init error!");
658 #ifdef DEBUG
659 	mutex_destroy(&aac_prt_mutex);
660 #endif
661 	return (rval);
662 }
663 
664 int
665 _info(struct modinfo *modinfop)
666 {
667 	DBCALLED(NULL, 1);
668 	return (mod_info(&aac_modlinkage, modinfop));
669 }
670 
671 /*
672  * An HBA driver cannot be unload unless you reboot,
673  * so this function will be of no use.
674  */
675 int
676 _fini(void)
677 {
678 	int rval;
679 
680 	DBCALLED(NULL, 1);
681 
682 	if ((rval = mod_remove(&aac_modlinkage)) != 0)
683 		goto error;
684 
685 	scsi_hba_fini(&aac_modlinkage);
686 	ddi_soft_state_fini((void *)&aac_softstatep);
687 #ifdef DEBUG
688 	mutex_destroy(&aac_prt_mutex);
689 #endif
690 	return (0);
691 
692 error:
693 	AACDB_PRINT(NULL, CE_WARN, "AAC is busy, cannot unload!");
694 	return (rval);
695 }
696 
697 static int
698 aac_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
699 {
700 	int instance, i;
701 	struct aac_softstate *softs = NULL;
702 	int attach_state = 0;
703 
704 	DBCALLED(NULL, 1);
705 
706 	switch (cmd) {
707 	case DDI_ATTACH:
708 		break;
709 	case DDI_RESUME:
710 		return (DDI_FAILURE);
711 	default:
712 		return (DDI_FAILURE);
713 	}
714 
715 	instance = ddi_get_instance(dip);
716 
717 	/* Get soft state */
718 	if (ddi_soft_state_zalloc(aac_softstatep, instance) != DDI_SUCCESS) {
719 		AACDB_PRINT(softs, CE_WARN, "Cannot alloc soft state");
720 		goto error;
721 	}
722 	softs = ddi_get_soft_state(aac_softstatep, instance);
723 	attach_state |= AAC_ATTACH_SOFTSTATE_ALLOCED;
724 
725 	softs->instance = instance;
726 	softs->devinfo_p = dip;
727 	softs->buf_dma_attr = softs->addr_dma_attr = aac_dma_attr;
728 	softs->addr_dma_attr.dma_attr_granular = 1;
729 	softs->card = AAC_UNKNOWN_CARD;
730 #ifdef DEBUG
731 	softs->debug_flags = aac_debug_flags;
732 #endif
733 
734 	/* Check the card type */
735 	if (aac_check_card_type(softs) == AACERR) {
736 		AACDB_PRINT(softs, CE_WARN, "Card not supported");
737 		goto error;
738 	}
739 	/* We have found the right card and everything is OK */
740 	attach_state |= AAC_ATTACH_CARD_DETECTED;
741 
742 	/*
743 	 * Initialize FMA
744 	 */
745 	softs->fm_capabilities = ddi_getprop(DDI_DEV_T_ANY, softs->devinfo_p,
746 	    DDI_PROP_CANSLEEP | DDI_PROP_DONTPASS, "fm-capable",
747 	    DDI_FM_EREPORT_CAPABLE | DDI_FM_ACCCHK_CAPABLE |
748 	    DDI_FM_DMACHK_CAPABLE | DDI_FM_ERRCB_CAPABLE);
749 
750 	aac_fm_init(softs);
751 
752 	/* Map PCI mem space */
753 	if (ddi_regs_map_setup(dip, 1,
754 	    (caddr_t *)&softs->pci_mem_base_vaddr, 0,
755 	    softs->map_size_min, &aac_acc_attr,
756 	    &softs->pci_mem_handle) != DDI_SUCCESS)
757 		goto error;
758 
759 	softs->map_size = softs->map_size_min;
760 	attach_state |= AAC_ATTACH_PCI_MEM_MAPPED;
761 
762 	AAC_DISABLE_INTR(softs);
763 
764 	if (ddi_intr_hilevel(dip, 0)) {
765 		AACDB_PRINT(softs, CE_WARN,
766 		    "High level interrupt is not supported!");
767 		goto error;
768 	}
769 
770 	/* Init mutexes */
771 	if (ddi_get_iblock_cookie(dip, 0, &softs->iblock_cookie) !=
772 	    DDI_SUCCESS) {
773 		AACDB_PRINT(softs, CE_WARN,
774 		    "Can not get interrupt block cookie!");
775 		goto error;
776 	}
777 	mutex_init(&softs->q_comp_mutex, NULL,
778 	    MUTEX_DRIVER, (void *)softs->iblock_cookie);
779 	cv_init(&softs->event, NULL, CV_DRIVER, NULL);
780 	mutex_init(&softs->aifq_mutex, NULL,
781 	    MUTEX_DRIVER, (void *)softs->iblock_cookie);
782 	cv_init(&softs->aifv, NULL, CV_DRIVER, NULL);
783 	cv_init(&softs->drain_cv, NULL, CV_DRIVER, NULL);
784 	mutex_init(&softs->io_lock, NULL, MUTEX_DRIVER,
785 	    (void *)softs->iblock_cookie);
786 	attach_state |= AAC_ATTACH_KMUTEX_INITED;
787 
788 	/*
789 	 * Everything has been set up till now,
790 	 * we will do some common attach.
791 	 */
792 	if (aac_common_attach(softs) == AACERR)
793 		goto error;
794 	attach_state |= AAC_ATTACH_COMM_SPACE_SETUP;
795 
796 	/* Init the cmd queues */
797 	for (i = 0; i < AAC_CMDQ_NUM; i++)
798 		aac_cmd_initq(&softs->q_wait[i]);
799 	aac_cmd_initq(&softs->q_busy);
800 	aac_cmd_initq(&softs->q_comp);
801 
802 	if (aac_hba_setup(softs) != AACOK)
803 		goto error;
804 	attach_state |= AAC_ATTACH_SCSI_TRAN_SETUP;
805 
806 	/* Connect interrupt handlers */
807 	if (ddi_add_softintr(dip, DDI_SOFTINT_LOW, &softs->softint_id,
808 	    NULL, NULL, aac_softintr, (caddr_t)softs) != DDI_SUCCESS) {
809 		AACDB_PRINT(softs, CE_WARN,
810 		    "Can not setup soft interrupt handler!");
811 		goto error;
812 	}
813 	attach_state |= AAC_ATTACH_SOFT_INTR_SETUP;
814 
815 	if (ddi_add_intr(dip, 0, &softs->iblock_cookie,
816 	    (ddi_idevice_cookie_t *)0,
817 	    (softs->flags & AAC_FLAGS_NEW_COMM) ?
818 	    aac_intr_new : aac_intr_old, (caddr_t)softs) != DDI_SUCCESS) {
819 		AACDB_PRINT(softs, CE_WARN, "Can not setup interrupt handler!");
820 		goto error;
821 	}
822 	attach_state |= AAC_ATTACH_HARD_INTR_SETUP;
823 
824 	/* Create devctl/scsi nodes for cfgadm */
825 	if (ddi_create_minor_node(dip, "devctl", S_IFCHR,
826 	    INST2DEVCTL(instance), DDI_NT_SCSI_NEXUS, 0) != DDI_SUCCESS) {
827 		AACDB_PRINT(softs, CE_WARN, "failed to create devctl node");
828 		goto error;
829 	}
830 	attach_state |= AAC_ATTACH_CREATE_DEVCTL;
831 
832 	if (ddi_create_minor_node(dip, "scsi", S_IFCHR, INST2SCSI(instance),
833 	    DDI_NT_SCSI_ATTACHMENT_POINT, 0) != DDI_SUCCESS) {
834 		AACDB_PRINT(softs, CE_WARN, "failed to create scsi node");
835 		goto error;
836 	}
837 	attach_state |= AAC_ATTACH_CREATE_SCSI;
838 
839 	/* Create aac node for app. to issue ioctls */
840 	if (ddi_create_minor_node(dip, "aac", S_IFCHR, INST2AAC(instance),
841 	    DDI_PSEUDO, 0) != DDI_SUCCESS) {
842 		AACDB_PRINT(softs, CE_WARN, "failed to create aac node");
843 		goto error;
844 	}
845 
846 	aac_unhold_bus(softs, AAC_IOCMD_SYNC | AAC_IOCMD_ASYNC);
847 	softs->state = AAC_STATE_RUN;
848 
849 	/* Create a thread for command timeout */
850 	softs->timeout_id = timeout(aac_daemon, (void *)softs,
851 	    (60 * drv_usectohz(1000000)));
852 
853 	/* Common attach is OK, so we are attached! */
854 	AAC_ENABLE_INTR(softs);
855 	ddi_report_dev(dip);
856 	AACDB_PRINT(softs, CE_NOTE, "aac attached ok");
857 	return (DDI_SUCCESS);
858 
859 error:
860 	if (attach_state & AAC_ATTACH_CREATE_SCSI)
861 		ddi_remove_minor_node(dip, "scsi");
862 	if (attach_state & AAC_ATTACH_CREATE_DEVCTL)
863 		ddi_remove_minor_node(dip, "devctl");
864 	if (attach_state & AAC_ATTACH_COMM_SPACE_SETUP)
865 		aac_common_detach(softs);
866 	if (attach_state & AAC_ATTACH_SCSI_TRAN_SETUP) {
867 		(void) scsi_hba_detach(dip);
868 		scsi_hba_tran_free(AAC_DIP2TRAN(dip));
869 	}
870 	if (attach_state & AAC_ATTACH_HARD_INTR_SETUP)
871 		ddi_remove_intr(dip, 0, softs->iblock_cookie);
872 	if (attach_state & AAC_ATTACH_SOFT_INTR_SETUP)
873 		ddi_remove_softintr(softs->softint_id);
874 	if (attach_state & AAC_ATTACH_KMUTEX_INITED) {
875 		mutex_destroy(&softs->q_comp_mutex);
876 		cv_destroy(&softs->event);
877 		mutex_destroy(&softs->aifq_mutex);
878 		cv_destroy(&softs->aifv);
879 		cv_destroy(&softs->drain_cv);
880 		mutex_destroy(&softs->io_lock);
881 	}
882 	if (attach_state & AAC_ATTACH_PCI_MEM_MAPPED)
883 		ddi_regs_map_free(&softs->pci_mem_handle);
884 	aac_fm_fini(softs);
885 	if (attach_state & AAC_ATTACH_CARD_DETECTED)
886 		softs->card = AACERR;
887 	if (attach_state & AAC_ATTACH_SOFTSTATE_ALLOCED)
888 		ddi_soft_state_free(aac_softstatep, instance);
889 	return (DDI_FAILURE);
890 }
891 
892 static int
893 aac_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
894 {
895 	scsi_hba_tran_t *tran = AAC_DIP2TRAN(dip);
896 	struct aac_softstate *softs = AAC_TRAN2SOFTS(tran);
897 
898 	DBCALLED(softs, 1);
899 
900 	switch (cmd) {
901 	case DDI_DETACH:
902 		break;
903 	case DDI_SUSPEND:
904 		return (DDI_FAILURE);
905 	default:
906 		return (DDI_FAILURE);
907 	}
908 
909 	mutex_enter(&softs->io_lock);
910 	AAC_DISABLE_INTR(softs);
911 	softs->state = AAC_STATE_STOPPED;
912 
913 	mutex_exit(&softs->io_lock);
914 	(void) untimeout(softs->timeout_id);
915 	mutex_enter(&softs->io_lock);
916 	softs->timeout_id = 0;
917 
918 	ddi_remove_minor_node(dip, "aac");
919 	ddi_remove_minor_node(dip, "scsi");
920 	ddi_remove_minor_node(dip, "devctl");
921 
922 	mutex_exit(&softs->io_lock);
923 	ddi_remove_intr(dip, 0, softs->iblock_cookie);
924 	ddi_remove_softintr(softs->softint_id);
925 
926 	aac_common_detach(softs);
927 
928 	(void) scsi_hba_detach(dip);
929 	scsi_hba_tran_free(tran);
930 
931 	mutex_destroy(&softs->q_comp_mutex);
932 	cv_destroy(&softs->event);
933 	mutex_destroy(&softs->aifq_mutex);
934 	cv_destroy(&softs->aifv);
935 	cv_destroy(&softs->drain_cv);
936 	mutex_destroy(&softs->io_lock);
937 
938 	ddi_regs_map_free(&softs->pci_mem_handle);
939 	aac_fm_fini(softs);
940 	softs->hwif = AAC_HWIF_UNKNOWN;
941 	softs->card = AAC_UNKNOWN_CARD;
942 	ddi_soft_state_free(aac_softstatep, ddi_get_instance(dip));
943 
944 	return (DDI_SUCCESS);
945 }
946 
947 /*ARGSUSED*/
948 static int
949 aac_reset(dev_info_t *dip, ddi_reset_cmd_t cmd)
950 {
951 	struct aac_softstate *softs = AAC_DIP2SOFTS(dip);
952 
953 	DBCALLED(softs, 1);
954 
955 	mutex_enter(&softs->io_lock);
956 	(void) aac_shutdown(softs);
957 	mutex_exit(&softs->io_lock);
958 
959 	return (DDI_SUCCESS);
960 }
961 
962 /*
963  * Bring the controller down to a dormant state and detach all child devices.
964  * This function is called before detach or system shutdown.
965  * Note: we can assume that the q_wait on the controller is empty, as we
966  * won't allow shutdown if any device is open.
967  */
968 static int
969 aac_shutdown(struct aac_softstate *softs)
970 {
971 	ddi_acc_handle_t acc = softs->sync_slot.fib_acc_handle;
972 	struct aac_close_command *cc = (struct aac_close_command *) \
973 	    &softs->sync_slot.fibp->data[0];
974 	int rval;
975 
976 	ddi_put32(acc, &cc->Command, VM_CloseAll);
977 	ddi_put32(acc, &cc->ContainerId, 0xfffffffful);
978 
979 	/* Flush all caches, set FW to write through mode */
980 	rval = aac_sync_fib(softs, ContainerCommand,
981 	    AAC_FIB_SIZEOF(struct aac_close_command));
982 
983 	AACDB_PRINT(softs, CE_NOTE,
984 	    "shutting down aac %s", (rval == AACOK) ? "ok" : "fail");
985 	return (rval);
986 }
987 
988 static uint_t
989 aac_softintr(caddr_t arg)
990 {
991 	struct aac_softstate *softs = (struct aac_softstate *)arg;
992 
993 	if (!AAC_IS_Q_EMPTY(&softs->q_comp)) {
994 		aac_drain_comp_q(softs);
995 		return (DDI_INTR_CLAIMED);
996 	} else {
997 		return (DDI_INTR_UNCLAIMED);
998 	}
999 }
1000 
1001 /*
1002  * Setup auto sense data for pkt
1003  */
1004 static void
1005 aac_set_arq_data(struct scsi_pkt *pkt, uchar_t key,
1006     uchar_t add_code, uchar_t qual_code, uint64_t info)
1007 {
1008 	struct scsi_arq_status *arqstat;
1009 
1010 	pkt->pkt_state |= STATE_GOT_STATUS | STATE_ARQ_DONE;
1011 
1012 	arqstat = (struct scsi_arq_status *)(pkt->pkt_scbp);
1013 	arqstat->sts_status.sts_chk = 1; /* CHECK CONDITION */
1014 	arqstat->sts_rqpkt_reason = CMD_CMPLT;
1015 	arqstat->sts_rqpkt_resid = 0;
1016 	arqstat->sts_rqpkt_state =
1017 	    STATE_GOT_BUS |
1018 	    STATE_GOT_TARGET |
1019 	    STATE_SENT_CMD |
1020 	    STATE_XFERRED_DATA;
1021 	arqstat->sts_rqpkt_statistics = 0;
1022 
1023 	if (info <= 0xfffffffful) {
1024 		arqstat->sts_sensedata.es_valid = 1;
1025 		arqstat->sts_sensedata.es_class = CLASS_EXTENDED_SENSE;
1026 		arqstat->sts_sensedata.es_code = CODE_FMT_FIXED_CURRENT;
1027 		arqstat->sts_sensedata.es_key = key;
1028 		arqstat->sts_sensedata.es_add_code = add_code;
1029 		arqstat->sts_sensedata.es_qual_code = qual_code;
1030 
1031 		arqstat->sts_sensedata.es_info_1 = (info >> 24) & 0xFF;
1032 		arqstat->sts_sensedata.es_info_2 = (info >> 16) & 0xFF;
1033 		arqstat->sts_sensedata.es_info_3 = (info >>  8) & 0xFF;
1034 		arqstat->sts_sensedata.es_info_4 = info & 0xFF;
1035 	} else { /* 64-bit LBA */
1036 		struct scsi_descr_sense_hdr *dsp;
1037 		struct scsi_information_sense_descr *isd;
1038 
1039 		dsp = (struct scsi_descr_sense_hdr *)&arqstat->sts_sensedata;
1040 		dsp->ds_class = CLASS_EXTENDED_SENSE;
1041 		dsp->ds_code = CODE_FMT_DESCR_CURRENT;
1042 		dsp->ds_key = key;
1043 		dsp->ds_add_code = add_code;
1044 		dsp->ds_qual_code = qual_code;
1045 		dsp->ds_addl_sense_length =
1046 		    sizeof (struct scsi_information_sense_descr);
1047 
1048 		isd = (struct scsi_information_sense_descr *)(dsp+1);
1049 		isd->isd_descr_type = DESCR_INFORMATION;
1050 		isd->isd_valid = 1;
1051 		isd->isd_information[0] = (info >> 56) & 0xFF;
1052 		isd->isd_information[1] = (info >> 48) & 0xFF;
1053 		isd->isd_information[2] = (info >> 40) & 0xFF;
1054 		isd->isd_information[3] = (info >> 32) & 0xFF;
1055 		isd->isd_information[4] = (info >> 24) & 0xFF;
1056 		isd->isd_information[5] = (info >> 16) & 0xFF;
1057 		isd->isd_information[6] = (info >>  8) & 0xFF;
1058 		isd->isd_information[7] = (info) & 0xFF;
1059 	}
1060 }
1061 
1062 /*
1063  * Setup auto sense data for HARDWARE ERROR
1064  */
1065 static void
1066 aac_set_arq_data_hwerr(struct aac_cmd *acp)
1067 {
1068 	union scsi_cdb *cdbp;
1069 	uint64_t err_blkno;
1070 
1071 	cdbp = (union scsi_cdb *)acp->pkt->pkt_cdbp;
1072 	err_blkno = AAC_GETGXADDR(acp->cmdlen, cdbp);
1073 	aac_set_arq_data(acp->pkt, KEY_HARDWARE_ERROR, 0x00, 0x00, err_blkno);
1074 }
1075 
1076 /*
1077  * Setup auto sense data for UNIT ATTENTION
1078  */
1079 /*ARGSUSED*/
1080 static void
1081 aac_set_arq_data_reset(struct aac_softstate *softs, struct aac_cmd *acp)
1082 {
1083 	struct aac_container *dvp = acp->dvp;
1084 
1085 	if (dvp->reset) {
1086 		dvp->reset = 0;
1087 		aac_set_arq_data(acp->pkt, KEY_UNIT_ATTENTION, 0x29, 0x02, 0);
1088 	}
1089 }
1090 
1091 /*
1092  * Send a command to the adapter in New Comm. interface
1093  */
1094 static int
1095 aac_send_command(struct aac_softstate *softs, struct aac_slot *slotp)
1096 {
1097 	uint32_t index, device;
1098 
1099 	index = PCI_MEM_GET32(softs, AAC_IQUE);
1100 	if (index == 0xffffffffUL) {
1101 		index = PCI_MEM_GET32(softs, AAC_IQUE);
1102 		if (index == 0xffffffffUL)
1103 			return (AACERR);
1104 	}
1105 
1106 	device = index;
1107 	PCI_MEM_PUT32(softs, device,
1108 	    (uint32_t)(slotp->fib_phyaddr & 0xfffffffful));
1109 	device += 4;
1110 	PCI_MEM_PUT32(softs, device, (uint32_t)(slotp->fib_phyaddr >> 32));
1111 	device += 4;
1112 	PCI_MEM_PUT32(softs, device, slotp->acp->fib_size);
1113 	PCI_MEM_PUT32(softs, AAC_IQUE, index);
1114 	return (AACOK);
1115 }
1116 
1117 static void
1118 aac_end_io(struct aac_softstate *softs, struct aac_cmd *acp)
1119 {
1120 	struct aac_container *dvp = acp->dvp;
1121 	int q = AAC_CMDQ(acp);
1122 
1123 	if (acp->slotp) { /* outstanding cmd */
1124 		aac_release_slot(softs, acp->slotp);
1125 		acp->slotp = NULL;
1126 		if (dvp) {
1127 			dvp->ncmds[q]--;
1128 			if (dvp->throttle[q] == AAC_THROTTLE_DRAIN &&
1129 			    dvp->ncmds[q] == 0 && q == AAC_CMDQ_ASYNC)
1130 				aac_set_throttle(softs, dvp, q,
1131 				    softs->total_slots);
1132 		}
1133 		softs->bus_ncmds[q]--;
1134 		(void) aac_cmd_delete(&softs->q_busy, acp);
1135 	} else { /* cmd in waiting queue */
1136 		aac_cmd_delete(&softs->q_wait[q], acp);
1137 	}
1138 
1139 	if (!(acp->flags & (AAC_CMD_NO_CB | AAC_CMD_NO_INTR))) { /* async IO */
1140 		mutex_enter(&softs->q_comp_mutex);
1141 		aac_cmd_enqueue(&softs->q_comp, acp);
1142 		mutex_exit(&softs->q_comp_mutex);
1143 	} else if (acp->flags & AAC_CMD_NO_CB) { /* sync IO */
1144 		cv_broadcast(&softs->event);
1145 	}
1146 }
1147 
1148 static void
1149 aac_handle_io(struct aac_softstate *softs, int index)
1150 {
1151 	struct aac_slot *slotp;
1152 	struct aac_cmd *acp;
1153 	uint32_t fast;
1154 
1155 	fast = index & AAC_SENDERADDR_MASK_FAST_RESPONSE;
1156 	index >>= 2;
1157 
1158 	/* Make sure firmware reported index is valid */
1159 	ASSERT(index >= 0 && index < softs->total_slots);
1160 	slotp = &softs->io_slot[index];
1161 	ASSERT(slotp->index == index);
1162 	acp = slotp->acp;
1163 	ASSERT(acp != NULL && acp->slotp == slotp);
1164 
1165 	acp->flags |= AAC_CMD_CMPLT;
1166 	(void) ddi_dma_sync(slotp->fib_dma_handle, 0, 0, DDI_DMA_SYNC_FORCPU);
1167 
1168 	if (aac_check_dma_handle(slotp->fib_dma_handle) == DDI_SUCCESS) {
1169 		/*
1170 		 * For fast response IO, the firmware do not return any FIB
1171 		 * data, so we need to fill in the FIB status and state so that
1172 		 * FIB users can handle it correctly.
1173 		 */
1174 		if (fast) {
1175 			uint32_t state;
1176 
1177 			state = ddi_get32(slotp->fib_acc_handle,
1178 			    &slotp->fibp->Header.XferState);
1179 			/*
1180 			 * Update state for CPU not for device, no DMA sync
1181 			 * needed
1182 			 */
1183 			ddi_put32(slotp->fib_acc_handle,
1184 			    &slotp->fibp->Header.XferState,
1185 			    state | AAC_FIBSTATE_DONEADAP);
1186 			ddi_put32(slotp->fib_acc_handle,
1187 			    (uint32_t *)&slotp->fibp->data[0], ST_OK);
1188 		}
1189 
1190 		/* Handle completed ac */
1191 		acp->ac_comp(softs, acp);
1192 	} else {
1193 		ddi_fm_service_impact(softs->devinfo_p, DDI_SERVICE_UNAFFECTED);
1194 		acp->flags |= AAC_CMD_ERR;
1195 		if (acp->pkt) {
1196 			acp->pkt->pkt_reason = CMD_TRAN_ERR;
1197 			acp->pkt->pkt_statistics = 0;
1198 		}
1199 	}
1200 	aac_end_io(softs, acp);
1201 }
1202 
1203 /*
1204  * Interrupt handler for New Comm. interface
1205  * New Comm. interface use a different mechanism for interrupt. No explict
1206  * message queues, and driver need only accesses the mapped PCI mem space to
1207  * find the completed FIB or AIF.
1208  */
1209 static int
1210 aac_process_intr_new(struct aac_softstate *softs)
1211 {
1212 	uint32_t index;
1213 
1214 	index = AAC_OUTB_GET(softs);
1215 	if (index == 0xfffffffful)
1216 		index = AAC_OUTB_GET(softs);
1217 	if (aac_check_acc_handle(softs->pci_mem_handle) != DDI_SUCCESS) {
1218 		ddi_fm_service_impact(softs->devinfo_p, DDI_SERVICE_UNAFFECTED);
1219 		return (DDI_INTR_UNCLAIMED);
1220 	}
1221 	if (index != 0xfffffffful) {
1222 		do {
1223 			if ((index & AAC_SENDERADDR_MASK_AIF) == 0) {
1224 				aac_handle_io(softs, index);
1225 			} else if (index != 0xfffffffeul) {
1226 				struct aac_fib *fibp;	/* FIB in AIF queue */
1227 				uint16_t fib_size, fib_size0;
1228 
1229 				/*
1230 				 * 0xfffffffe means that the controller wants
1231 				 * more work, ignore it for now. Otherwise,
1232 				 * AIF received.
1233 				 */
1234 				index &= ~2;
1235 
1236 				mutex_enter(&softs->aifq_mutex);
1237 				/*
1238 				 * Copy AIF from adapter to the empty AIF slot
1239 				 */
1240 				fibp = &softs->aifq[softs->aifq_idx].d;
1241 				fib_size0 = PCI_MEM_GET16(softs, index + \
1242 				    offsetof(struct aac_fib, Header.Size));
1243 				fib_size = (fib_size0 > AAC_FIB_SIZE) ?
1244 				    AAC_FIB_SIZE : fib_size0;
1245 				PCI_MEM_REP_GET8(softs, index, fibp,
1246 				    fib_size);
1247 
1248 				if (aac_check_acc_handle(softs-> \
1249 				    pci_mem_handle) == DDI_SUCCESS)
1250 					(void) aac_handle_aif(softs, fibp);
1251 				else
1252 					ddi_fm_service_impact(softs->devinfo_p,
1253 					    DDI_SERVICE_UNAFFECTED);
1254 				mutex_exit(&softs->aifq_mutex);
1255 
1256 				/*
1257 				 * AIF memory is owned by the adapter, so let it
1258 				 * know that we are done with it.
1259 				 */
1260 				AAC_OUTB_SET(softs, index);
1261 				AAC_STATUS_CLR(softs, AAC_DB_RESPONSE_READY);
1262 			}
1263 
1264 			index = AAC_OUTB_GET(softs);
1265 		} while (index != 0xfffffffful);
1266 
1267 		/*
1268 		 * Process waiting cmds before start new ones to
1269 		 * ensure first IOs are serviced first.
1270 		 */
1271 		aac_start_waiting_io(softs);
1272 		return (AAC_DB_COMMAND_READY);
1273 	} else {
1274 		return (0);
1275 	}
1276 }
1277 
1278 static uint_t
1279 aac_intr_new(caddr_t arg)
1280 {
1281 	struct aac_softstate *softs = (struct aac_softstate *)arg;
1282 	uint_t rval;
1283 
1284 	mutex_enter(&softs->io_lock);
1285 	if (aac_process_intr_new(softs))
1286 		rval = DDI_INTR_CLAIMED;
1287 	else
1288 		rval = DDI_INTR_UNCLAIMED;
1289 	mutex_exit(&softs->io_lock);
1290 
1291 	aac_drain_comp_q(softs);
1292 	return (rval);
1293 }
1294 
1295 /*
1296  * Interrupt handler for old interface
1297  * Explicit message queues are used to send FIB to and get completed FIB from
1298  * the adapter. Driver and adapter maitain the queues in the producer/consumer
1299  * manner. The driver has to query the queues to find the completed FIB.
1300  */
1301 static int
1302 aac_process_intr_old(struct aac_softstate *softs)
1303 {
1304 	uint16_t status;
1305 
1306 	status = AAC_STATUS_GET(softs);
1307 	if (aac_check_acc_handle(softs->pci_mem_handle) != DDI_SUCCESS) {
1308 		ddi_fm_service_impact(softs->devinfo_p, DDI_SERVICE_UNAFFECTED);
1309 		return (DDI_INTR_UNCLAIMED);
1310 	}
1311 	if (status & AAC_DB_RESPONSE_READY) {
1312 		int slot_idx;
1313 
1314 		/* ACK the intr */
1315 		AAC_STATUS_CLR(softs, AAC_DB_RESPONSE_READY);
1316 		(void) AAC_STATUS_GET(softs);
1317 		while (aac_fib_dequeue(softs, AAC_HOST_NORM_RESP_Q,
1318 		    &slot_idx) == AACOK)
1319 			aac_handle_io(softs, slot_idx);
1320 
1321 		/*
1322 		 * Process waiting cmds before start new ones to
1323 		 * ensure first IOs are serviced first.
1324 		 */
1325 		aac_start_waiting_io(softs);
1326 		return (AAC_DB_RESPONSE_READY);
1327 	} else if (status & AAC_DB_COMMAND_READY) {
1328 		int aif_idx;
1329 
1330 		AAC_STATUS_CLR(softs, AAC_DB_COMMAND_READY);
1331 		(void) AAC_STATUS_GET(softs);
1332 		if (aac_fib_dequeue(softs, AAC_HOST_NORM_CMD_Q, &aif_idx) ==
1333 		    AACOK) {
1334 			ddi_acc_handle_t acc = softs->comm_space_acc_handle;
1335 			struct aac_fib *fibp;	/* FIB in AIF queue */
1336 			struct aac_fib *fibp0;	/* FIB in communication space */
1337 			uint16_t fib_size, fib_size0;
1338 			uint32_t fib_xfer_state;
1339 			uint32_t addr, size;
1340 
1341 			ASSERT((aif_idx >= 0) && (aif_idx < AAC_ADAPTER_FIBS));
1342 
1343 #define	AAC_SYNC_AIF(softs, aif_idx, type) \
1344 	{ (void) ddi_dma_sync((softs)->comm_space_dma_handle, \
1345 	    offsetof(struct aac_comm_space, \
1346 	    adapter_fibs[(aif_idx)]), AAC_FIB_SIZE, \
1347 	    (type)); }
1348 
1349 			mutex_enter(&softs->aifq_mutex);
1350 			/* Copy AIF from adapter to the empty AIF slot */
1351 			fibp = &softs->aifq[softs->aifq_idx].d;
1352 			AAC_SYNC_AIF(softs, aif_idx, DDI_DMA_SYNC_FORCPU);
1353 			fibp0 = &softs->comm_space->adapter_fibs[aif_idx];
1354 			fib_size0 = ddi_get16(acc, &fibp0->Header.Size);
1355 			fib_size = (fib_size0 > AAC_FIB_SIZE) ?
1356 			    AAC_FIB_SIZE : fib_size0;
1357 			ddi_rep_get8(acc, (uint8_t *)fibp, (uint8_t *)fibp0,
1358 			    fib_size, DDI_DEV_AUTOINCR);
1359 
1360 			(void) aac_handle_aif(softs, fibp);
1361 			mutex_exit(&softs->aifq_mutex);
1362 
1363 			/* Complete AIF back to adapter with good status */
1364 			fib_xfer_state = LE_32(fibp->Header.XferState);
1365 			if (fib_xfer_state & AAC_FIBSTATE_FROMADAP) {
1366 				ddi_put32(acc, &fibp0->Header.XferState,
1367 				    fib_xfer_state | AAC_FIBSTATE_DONEHOST);
1368 				ddi_put32(acc, (uint32_t *)&fibp0->data[0],
1369 				    ST_OK);
1370 				if (fib_size0 > AAC_FIB_SIZE)
1371 					ddi_put16(acc, &fibp0->Header.Size,
1372 					    AAC_FIB_SIZE);
1373 				AAC_SYNC_AIF(softs, aif_idx,
1374 				    DDI_DMA_SYNC_FORDEV);
1375 			}
1376 
1377 			/* Put the AIF response on the response queue */
1378 			addr = ddi_get32(acc,
1379 			    &softs->comm_space->adapter_fibs[aif_idx]. \
1380 			    Header.SenderFibAddress);
1381 			size = (uint32_t)ddi_get16(acc,
1382 			    &softs->comm_space->adapter_fibs[aif_idx]. \
1383 			    Header.Size);
1384 			ddi_put32(acc,
1385 			    &softs->comm_space->adapter_fibs[aif_idx]. \
1386 			    Header.ReceiverFibAddress, addr);
1387 			if (aac_fib_enqueue(softs, AAC_ADAP_NORM_RESP_Q,
1388 			    addr, size) == AACERR)
1389 				cmn_err(CE_NOTE, "!AIF ack failed");
1390 		}
1391 		return (AAC_DB_COMMAND_READY);
1392 	} else if (status & AAC_DB_PRINTF_READY) {
1393 		/* ACK the intr */
1394 		AAC_STATUS_CLR(softs, AAC_DB_PRINTF_READY);
1395 		(void) AAC_STATUS_GET(softs);
1396 		(void) ddi_dma_sync(softs->comm_space_dma_handle,
1397 		    offsetof(struct aac_comm_space, adapter_print_buf),
1398 		    AAC_ADAPTER_PRINT_BUFSIZE, DDI_DMA_SYNC_FORCPU);
1399 		if (aac_check_dma_handle(softs->comm_space_dma_handle) ==
1400 		    DDI_SUCCESS)
1401 			cmn_err(CE_NOTE, "MSG From Adapter: %s",
1402 			    softs->comm_space->adapter_print_buf);
1403 		else
1404 			ddi_fm_service_impact(softs->devinfo_p,
1405 			    DDI_SERVICE_UNAFFECTED);
1406 		AAC_NOTIFY(softs, AAC_DB_PRINTF_READY);
1407 		return (AAC_DB_PRINTF_READY);
1408 	} else if (status & AAC_DB_COMMAND_NOT_FULL) {
1409 		/*
1410 		 * Without these two condition statements, the OS could hang
1411 		 * after a while, especially if there are a lot of AIF's to
1412 		 * handle, for instance if a drive is pulled from an array
1413 		 * under heavy load.
1414 		 */
1415 		AAC_STATUS_CLR(softs, AAC_DB_COMMAND_NOT_FULL);
1416 		return (AAC_DB_COMMAND_NOT_FULL);
1417 	} else if (status & AAC_DB_RESPONSE_NOT_FULL) {
1418 		AAC_STATUS_CLR(softs, AAC_DB_COMMAND_NOT_FULL);
1419 		AAC_STATUS_CLR(softs, AAC_DB_RESPONSE_NOT_FULL);
1420 		return (AAC_DB_RESPONSE_NOT_FULL);
1421 	} else {
1422 		return (0);
1423 	}
1424 }
1425 
1426 static uint_t
1427 aac_intr_old(caddr_t arg)
1428 {
1429 	struct aac_softstate *softs = (struct aac_softstate *)arg;
1430 	int rval;
1431 
1432 	mutex_enter(&softs->io_lock);
1433 	if (aac_process_intr_old(softs))
1434 		rval = DDI_INTR_CLAIMED;
1435 	else
1436 		rval = DDI_INTR_UNCLAIMED;
1437 	mutex_exit(&softs->io_lock);
1438 
1439 	aac_drain_comp_q(softs);
1440 	return (rval);
1441 }
1442 
1443 /*
1444  * Set pkt_reason and OR in pkt_statistics flag
1445  */
1446 static void
1447 aac_set_pkt_reason(struct aac_softstate *softs, struct aac_cmd *acp,
1448     uchar_t reason, uint_t stat)
1449 {
1450 #ifndef __lock_lint
1451 	_NOTE(ARGUNUSED(softs))
1452 #endif
1453 	AACDB_PRINT(softs, CE_NOTE, "acp=0x%p, reason=%x, stat=%x",
1454 	    (void *)acp, reason, stat);
1455 	if (acp->pkt->pkt_reason == CMD_CMPLT)
1456 		acp->pkt->pkt_reason = reason;
1457 	acp->pkt->pkt_statistics |= stat;
1458 }
1459 
1460 /*
1461  * Handle a finished pkt of soft SCMD
1462  */
1463 static void
1464 aac_soft_callback(struct aac_softstate *softs, struct aac_cmd *acp)
1465 {
1466 	ASSERT(acp->pkt);
1467 
1468 	acp->flags |= AAC_CMD_CMPLT;
1469 
1470 	acp->pkt->pkt_state |= STATE_GOT_BUS | STATE_GOT_TARGET | \
1471 	    STATE_SENT_CMD;
1472 	if (acp->pkt->pkt_state & STATE_XFERRED_DATA)
1473 		acp->pkt->pkt_resid = 0;
1474 
1475 	/* AAC_CMD_NO_INTR means no complete callback */
1476 	if (!(acp->flags & AAC_CMD_NO_INTR)) {
1477 		mutex_enter(&softs->q_comp_mutex);
1478 		aac_cmd_enqueue(&softs->q_comp, acp);
1479 		mutex_exit(&softs->q_comp_mutex);
1480 		ddi_trigger_softintr(softs->softint_id);
1481 	}
1482 }
1483 
1484 /*
1485  * Handlers for completed IOs, common to aac_intr_new() and aac_intr_old()
1486  */
1487 
1488 /*
1489  * Handle completed logical device IO command
1490  */
1491 /*ARGSUSED*/
1492 static void
1493 aac_ld_complete(struct aac_softstate *softs, struct aac_cmd *acp)
1494 {
1495 	struct aac_slot *slotp = acp->slotp;
1496 	struct aac_blockread_response *resp;
1497 	uint32_t status;
1498 
1499 	ASSERT(!(acp->flags & AAC_CMD_SYNC));
1500 	ASSERT(!(acp->flags & AAC_CMD_NO_CB));
1501 
1502 	/*
1503 	 * block_read/write has a similar response header, use blockread
1504 	 * response for both.
1505 	 */
1506 	resp = (struct aac_blockread_response *)&slotp->fibp->data[0];
1507 	status = ddi_get32(slotp->fib_acc_handle, &resp->Status);
1508 	if (status == ST_OK) {
1509 		acp->pkt->pkt_resid = 0;
1510 		acp->pkt->pkt_state |= STATE_XFERRED_DATA;
1511 	} else {
1512 		aac_set_arq_data_hwerr(acp);
1513 	}
1514 }
1515 
1516 /*
1517  * Handle completed IOCTL command
1518  */
1519 /*ARGSUSED*/
1520 void
1521 aac_ioctl_complete(struct aac_softstate *softs, struct aac_cmd *acp)
1522 {
1523 	struct aac_slot *slotp = acp->slotp;
1524 
1525 	/*
1526 	 * NOTE: Both aac_ioctl_send_fib() and aac_send_raw_srb()
1527 	 * may wait on softs->event, so use cv_broadcast() instead
1528 	 * of cv_signal().
1529 	 */
1530 	ASSERT(acp->flags & AAC_CMD_SYNC);
1531 	ASSERT(acp->flags & AAC_CMD_NO_CB);
1532 
1533 	/* Get the size of the response FIB from its FIB.Header.Size field */
1534 	acp->fib_size = ddi_get16(slotp->fib_acc_handle,
1535 	    &slotp->fibp->Header.Size);
1536 
1537 	ASSERT(acp->fib_size <= softs->aac_max_fib_size);
1538 	ddi_rep_get8(slotp->fib_acc_handle, (uint8_t *)acp->fibp,
1539 	    (uint8_t *)slotp->fibp, acp->fib_size, DDI_DEV_AUTOINCR);
1540 }
1541 
1542 /*
1543  * Handle completed Flush command
1544  */
1545 /*ARGSUSED*/
1546 static void
1547 aac_synccache_complete(struct aac_softstate *softs, struct aac_cmd *acp)
1548 {
1549 	struct aac_slot *slotp = acp->slotp;
1550 	ddi_acc_handle_t acc = slotp->fib_acc_handle;
1551 	struct aac_synchronize_reply *resp;
1552 	uint32_t status;
1553 
1554 	ASSERT(!(acp->flags & AAC_CMD_SYNC));
1555 
1556 	resp = (struct aac_synchronize_reply *)&slotp->fibp->data[0];
1557 	status = ddi_get32(acc, &resp->Status);
1558 	if (status != CT_OK)
1559 		aac_set_arq_data_hwerr(acp);
1560 }
1561 
1562 /*
1563  * Access PCI space to see if the driver can support the card
1564  */
1565 static int
1566 aac_check_card_type(struct aac_softstate *softs)
1567 {
1568 	ddi_acc_handle_t pci_config_handle;
1569 	int card_index;
1570 	uint32_t pci_cmd;
1571 
1572 	/* Map pci configuration space */
1573 	if ((pci_config_setup(softs->devinfo_p, &pci_config_handle)) !=
1574 	    DDI_SUCCESS) {
1575 		AACDB_PRINT(softs, CE_WARN, "Cannot setup pci config space");
1576 		return (AACERR);
1577 	}
1578 
1579 	softs->vendid = pci_config_get16(pci_config_handle, PCI_CONF_VENID);
1580 	softs->devid = pci_config_get16(pci_config_handle, PCI_CONF_DEVID);
1581 	softs->subvendid = pci_config_get16(pci_config_handle,
1582 	    PCI_CONF_SUBVENID);
1583 	softs->subsysid = pci_config_get16(pci_config_handle,
1584 	    PCI_CONF_SUBSYSID);
1585 
1586 	card_index = 0;
1587 	while (!CARD_IS_UNKNOWN(card_index)) {
1588 		if ((aac_cards[card_index].vendor == softs->vendid) &&
1589 		    (aac_cards[card_index].device == softs->devid) &&
1590 		    (aac_cards[card_index].subvendor == softs->subvendid) &&
1591 		    (aac_cards[card_index].subsys == softs->subsysid)) {
1592 			break;
1593 		}
1594 		card_index++;
1595 	}
1596 
1597 	softs->card = card_index;
1598 	softs->hwif = aac_cards[card_index].hwif;
1599 
1600 	/*
1601 	 * Unknown aac card
1602 	 * do a generic match based on the VendorID and DeviceID to
1603 	 * support the new cards in the aac family
1604 	 */
1605 	if (CARD_IS_UNKNOWN(card_index)) {
1606 		if (softs->vendid != 0x9005) {
1607 			AACDB_PRINT(softs, CE_WARN,
1608 			    "Unknown vendor 0x%x", softs->vendid);
1609 			goto error;
1610 		}
1611 		switch (softs->devid) {
1612 		case 0x285:
1613 			softs->hwif = AAC_HWIF_I960RX;
1614 			break;
1615 		case 0x286:
1616 			softs->hwif = AAC_HWIF_RKT;
1617 			break;
1618 		default:
1619 			AACDB_PRINT(softs, CE_WARN,
1620 			    "Unknown device \"pci9005,%x\"", softs->devid);
1621 			goto error;
1622 		}
1623 	}
1624 
1625 	/* Set hardware dependent interface */
1626 	switch (softs->hwif) {
1627 	case AAC_HWIF_I960RX:
1628 		softs->aac_if = aac_rx_interface;
1629 		softs->map_size_min = AAC_MAP_SIZE_MIN_RX;
1630 		break;
1631 	case AAC_HWIF_RKT:
1632 		softs->aac_if = aac_rkt_interface;
1633 		softs->map_size_min = AAC_MAP_SIZE_MIN_RKT;
1634 		break;
1635 	default:
1636 		AACDB_PRINT(softs, CE_WARN,
1637 		    "Unknown hardware interface %d", softs->hwif);
1638 		goto error;
1639 	}
1640 
1641 	/* Set card names */
1642 	(void *)strncpy(softs->vendor_name, aac_cards[card_index].vid,
1643 	    AAC_VENDOR_LEN);
1644 	(void *)strncpy(softs->product_name, aac_cards[card_index].desc,
1645 	    AAC_PRODUCT_LEN);
1646 
1647 	/* Set up quirks */
1648 	softs->flags = aac_cards[card_index].quirks;
1649 
1650 	/* Force the busmaster enable bit on */
1651 	pci_cmd = pci_config_get16(pci_config_handle, PCI_CONF_COMM);
1652 	if ((pci_cmd & PCI_COMM_ME) == 0) {
1653 		pci_cmd |= PCI_COMM_ME;
1654 		pci_config_put16(pci_config_handle, PCI_CONF_COMM, pci_cmd);
1655 		pci_cmd = pci_config_get16(pci_config_handle, PCI_CONF_COMM);
1656 		if ((pci_cmd & PCI_COMM_ME) == 0) {
1657 			cmn_err(CE_CONT, "?Cannot enable busmaster bit");
1658 			goto error;
1659 		}
1660 	}
1661 
1662 	/* Set memory base to map */
1663 	softs->pci_mem_base_paddr = 0xfffffff0UL & \
1664 	    pci_config_get32(pci_config_handle, PCI_CONF_BASE0);
1665 
1666 	pci_config_teardown(&pci_config_handle);
1667 
1668 	return (AACOK); /* card type detected */
1669 error:
1670 	pci_config_teardown(&pci_config_handle);
1671 	return (AACERR); /* no matched card found */
1672 }
1673 
1674 /*
1675  * Check the firmware to determine the features to support and the FIB
1676  * parameters to use.
1677  */
1678 static int
1679 aac_check_firmware(struct aac_softstate *softs)
1680 {
1681 	uint32_t options;
1682 	uint32_t atu_size;
1683 	ddi_acc_handle_t pci_handle;
1684 	char *pci_mbr;
1685 	uint32_t max_fibs;
1686 	uint32_t max_fib_size;
1687 	uint32_t sg_tablesize;
1688 	uint32_t max_sectors;
1689 	uint32_t status;
1690 
1691 	/* Get supported options */
1692 	if ((aac_sync_mbcommand(softs, AAC_MONKER_GETINFO, 0, 0, 0, 0,
1693 	    &status)) != AACOK) {
1694 		if (status != SRB_STATUS_INVALID_REQUEST) {
1695 			cmn_err(CE_CONT,
1696 			    "?Fatal error: request adapter info error");
1697 			return (AACERR);
1698 		}
1699 		options = 0;
1700 		atu_size = 0;
1701 	} else {
1702 		options = AAC_MAILBOX_GET(softs, 1);
1703 		atu_size = AAC_MAILBOX_GET(softs, 2);
1704 	}
1705 
1706 	if (softs->state & AAC_STATE_RESET) {
1707 		if ((softs->support_opt == options) &&
1708 		    (softs->atu_size == atu_size))
1709 			return (AACOK);
1710 
1711 		cmn_err(CE_WARN,
1712 		    "?Fatal error: firmware changed, system needs reboot");
1713 		return (AACERR);
1714 	}
1715 
1716 	/*
1717 	 * The following critical settings are initialized only once during
1718 	 * driver attachment.
1719 	 */
1720 	softs->support_opt = options;
1721 	softs->atu_size = atu_size;
1722 
1723 	/* Process supported options */
1724 	if ((options & AAC_SUPPORTED_4GB_WINDOW) != 0 &&
1725 	    (softs->flags & AAC_FLAGS_NO4GB) == 0) {
1726 		AACDB_PRINT(softs, CE_NOTE, "!Enable FIB map 4GB window");
1727 		softs->flags |= AAC_FLAGS_4GB_WINDOW;
1728 	} else {
1729 		/*
1730 		 * Quirk AAC_FLAGS_NO4GB is for FIB address and thus comm space
1731 		 * only. IO is handled by the DMA engine which does not suffer
1732 		 * from the ATU window programming workarounds necessary for
1733 		 * CPU copy operations.
1734 		 */
1735 		softs->addr_dma_attr.dma_attr_addr_lo = 0x2000ull;
1736 		softs->addr_dma_attr.dma_attr_addr_hi = 0x7fffffffull;
1737 	}
1738 
1739 	if ((options & AAC_SUPPORTED_SGMAP_HOST64) != 0) {
1740 		AACDB_PRINT(softs, CE_NOTE, "!Enable SG map 64-bit address");
1741 		softs->buf_dma_attr.dma_attr_addr_hi = 0xffffffffffffffffull;
1742 		softs->buf_dma_attr.dma_attr_seg = 0xffffffffffffffffull;
1743 		softs->flags |= AAC_FLAGS_SG_64BIT;
1744 	}
1745 
1746 	if (options & AAC_SUPPORTED_64BIT_ARRAYSIZE) {
1747 		softs->flags |= AAC_FLAGS_ARRAY_64BIT;
1748 		AACDB_PRINT(softs, CE_NOTE, "!Enable 64-bit array size");
1749 	}
1750 
1751 	/* Read preferred settings */
1752 	max_fib_size = 0;
1753 	if ((aac_sync_mbcommand(softs, AAC_MONKER_GETCOMMPREF,
1754 	    0, 0, 0, 0, NULL)) == AACOK) {
1755 		options = AAC_MAILBOX_GET(softs, 1);
1756 		max_fib_size = (options & 0xffff);
1757 		max_sectors = (options >> 16) << 1;
1758 		options = AAC_MAILBOX_GET(softs, 2);
1759 		sg_tablesize = (options >> 16);
1760 		options = AAC_MAILBOX_GET(softs, 3);
1761 		max_fibs = (options & 0xffff);
1762 	}
1763 
1764 	/* Enable new comm. and rawio at the same time */
1765 	if ((softs->support_opt & AAC_SUPPORTED_NEW_COMM) &&
1766 	    (max_fib_size != 0)) {
1767 		if ((atu_size > softs->map_size) &&
1768 		    (ddi_regs_map_setup(softs->devinfo_p, 1,
1769 		    (caddr_t *)&pci_mbr, 0, atu_size, &aac_acc_attr,
1770 		    &pci_handle) == DDI_SUCCESS)) {
1771 			ddi_regs_map_free(&softs->pci_mem_handle);
1772 			softs->pci_mem_handle = pci_handle;
1773 			softs->pci_mem_base_vaddr = pci_mbr;
1774 			softs->map_size = atu_size;
1775 		}
1776 		if (atu_size == softs->map_size) {
1777 			softs->flags |= AAC_FLAGS_NEW_COMM;
1778 			AACDB_PRINT(softs, CE_NOTE,
1779 			    "!Enable New Comm. interface");
1780 		}
1781 	}
1782 
1783 	/* Set FIB parameters */
1784 	if (softs->flags & AAC_FLAGS_NEW_COMM) {
1785 		softs->aac_max_fibs = max_fibs;
1786 		softs->aac_max_fib_size = max_fib_size;
1787 		softs->aac_max_sectors = max_sectors;
1788 		softs->aac_sg_tablesize = sg_tablesize;
1789 
1790 		softs->flags |= AAC_FLAGS_RAW_IO;
1791 		AACDB_PRINT(softs, CE_NOTE, "!Enable RawIO");
1792 	} else {
1793 		softs->aac_max_fibs =
1794 		    (softs->flags & AAC_FLAGS_256FIBS) ? 256 : 512;
1795 		softs->aac_max_fib_size = AAC_FIB_SIZE;
1796 		softs->aac_max_sectors = 128;	/* 64K */
1797 		if (softs->flags & AAC_FLAGS_17SG)
1798 			softs->aac_sg_tablesize = 17;
1799 		else if (softs->flags & AAC_FLAGS_34SG)
1800 			softs->aac_sg_tablesize = 34;
1801 		else if (softs->flags & AAC_FLAGS_SG_64BIT)
1802 			softs->aac_sg_tablesize = (AAC_FIB_DATASIZE -
1803 			    sizeof (struct aac_blockwrite64) +
1804 			    sizeof (struct aac_sg_entry64)) /
1805 			    sizeof (struct aac_sg_entry64);
1806 		else
1807 			softs->aac_sg_tablesize = (AAC_FIB_DATASIZE -
1808 			    sizeof (struct aac_blockwrite) +
1809 			    sizeof (struct aac_sg_entry)) /
1810 			    sizeof (struct aac_sg_entry);
1811 	}
1812 
1813 	if ((softs->flags & AAC_FLAGS_RAW_IO) &&
1814 	    (softs->flags & AAC_FLAGS_ARRAY_64BIT)) {
1815 		softs->flags |= AAC_FLAGS_LBA_64BIT;
1816 		AACDB_PRINT(softs, CE_NOTE, "!Enable 64-bit array");
1817 	}
1818 	softs->buf_dma_attr.dma_attr_sgllen = softs->aac_sg_tablesize;
1819 	softs->buf_dma_attr.dma_attr_maxxfer = softs->aac_max_sectors << 9;
1820 	/*
1821 	 * 64K maximum segment size in scatter gather list is controlled by
1822 	 * the NEW_COMM bit in the adapter information. If not set, the card
1823 	 * can only accept a maximum of 64K. It is not recommended to permit
1824 	 * more than 128KB of total transfer size to the adapters because
1825 	 * performance is negatively impacted.
1826 	 *
1827 	 * For new comm, segment size equals max xfer size. For old comm,
1828 	 * we use 64K for both.
1829 	 */
1830 	softs->buf_dma_attr.dma_attr_count_max =
1831 	    softs->buf_dma_attr.dma_attr_maxxfer - 1;
1832 
1833 	/* Setup FIB operations for logical devices */
1834 	if (softs->flags & AAC_FLAGS_RAW_IO)
1835 		softs->aac_cmd_fib = aac_cmd_fib_rawio;
1836 	else if (softs->flags & AAC_FLAGS_SG_64BIT)
1837 		softs->aac_cmd_fib = aac_cmd_fib_brw64;
1838 	else
1839 		softs->aac_cmd_fib = aac_cmd_fib_brw;
1840 	softs->aac_cmd_fib_scsi = (softs->flags & AAC_FLAGS_SG_64BIT) ? \
1841 	    aac_cmd_fib_scsi64 : aac_cmd_fib_scsi32;
1842 
1843 	/* 64-bit LBA needs descriptor format sense data */
1844 	softs->slen = sizeof (struct scsi_arq_status);
1845 	if ((softs->flags & AAC_FLAGS_LBA_64BIT) &&
1846 	    softs->slen < AAC_ARQ64_LENGTH)
1847 		softs->slen = AAC_ARQ64_LENGTH;
1848 
1849 	AACDB_PRINT(softs, CE_NOTE,
1850 	    "!max_fibs %d max_fibsize 0x%x max_sectors %d max_sg %d",
1851 	    softs->aac_max_fibs, softs->aac_max_fib_size,
1852 	    softs->aac_max_sectors, softs->aac_sg_tablesize);
1853 
1854 	return (AACOK);
1855 }
1856 
1857 static void
1858 aac_fsa_rev(struct aac_softstate *softs, struct FsaRev *fsarev0,
1859     struct FsaRev *fsarev1)
1860 {
1861 	ddi_acc_handle_t acc = softs->comm_space_acc_handle;
1862 
1863 	AAC_GET_FIELD8(acc, fsarev1, fsarev0, external.comp.dash);
1864 	AAC_GET_FIELD8(acc, fsarev1, fsarev0, external.comp.type);
1865 	AAC_GET_FIELD8(acc, fsarev1, fsarev0, external.comp.minor);
1866 	AAC_GET_FIELD8(acc, fsarev1, fsarev0, external.comp.major);
1867 	AAC_GET_FIELD32(acc, fsarev1, fsarev0, buildNumber);
1868 }
1869 
1870 /*
1871  * The following function comes from Adaptec:
1872  *
1873  * Query adapter information and supplement adapter information
1874  */
1875 static int
1876 aac_get_adapter_info(struct aac_softstate *softs,
1877     struct aac_adapter_info *ainfr, struct aac_supplement_adapter_info *sinfr)
1878 {
1879 	ddi_acc_handle_t acc = softs->sync_slot.fib_acc_handle;
1880 	struct aac_fib *fibp = softs->sync_slot.fibp;
1881 	struct aac_adapter_info *ainfp;
1882 	struct aac_supplement_adapter_info *sinfp;
1883 
1884 	ddi_put8(acc, &fibp->data[0], 0);
1885 	if (aac_sync_fib(softs, RequestAdapterInfo,
1886 	    sizeof (struct aac_fib_header)) != AACOK) {
1887 		AACDB_PRINT(softs, CE_WARN, "RequestAdapterInfo failed");
1888 		return (AACERR);
1889 	}
1890 	ainfp = (struct aac_adapter_info *)fibp->data;
1891 	if (ainfr) {
1892 		AAC_GET_FIELD32(acc, ainfr, ainfp, SupportedOptions);
1893 		AAC_GET_FIELD32(acc, ainfr, ainfp, PlatformBase);
1894 		AAC_GET_FIELD32(acc, ainfr, ainfp, CpuArchitecture);
1895 		AAC_GET_FIELD32(acc, ainfr, ainfp, CpuVariant);
1896 		AAC_GET_FIELD32(acc, ainfr, ainfp, ClockSpeed);
1897 		AAC_GET_FIELD32(acc, ainfr, ainfp, ExecutionMem);
1898 		AAC_GET_FIELD32(acc, ainfr, ainfp, BufferMem);
1899 		AAC_GET_FIELD32(acc, ainfr, ainfp, TotalMem);
1900 		aac_fsa_rev(softs, &ainfp->KernelRevision,
1901 		    &ainfr->KernelRevision);
1902 		aac_fsa_rev(softs, &ainfp->MonitorRevision,
1903 		    &ainfr->MonitorRevision);
1904 		aac_fsa_rev(softs, &ainfp->HardwareRevision,
1905 		    &ainfr->HardwareRevision);
1906 		aac_fsa_rev(softs, &ainfp->BIOSRevision,
1907 		    &ainfr->BIOSRevision);
1908 		AAC_GET_FIELD32(acc, ainfr, ainfp, ClusteringEnabled);
1909 		AAC_GET_FIELD32(acc, ainfr, ainfp, ClusterChannelMask);
1910 		AAC_GET_FIELD64(acc, ainfr, ainfp, SerialNumber);
1911 		AAC_GET_FIELD32(acc, ainfr, ainfp, batteryPlatform);
1912 		AAC_GET_FIELD32(acc, ainfr, ainfp, SupportedOptions);
1913 		AAC_GET_FIELD32(acc, ainfr, ainfp, OemVariant);
1914 	}
1915 	if (sinfr) {
1916 		if (!(softs->support_opt &
1917 		    AAC_SUPPORTED_SUPPLEMENT_ADAPTER_INFO)) {
1918 			AACDB_PRINT(softs, CE_WARN,
1919 			    "SupplementAdapterInfo not supported");
1920 			return (AACERR);
1921 		}
1922 		ddi_put8(acc, &fibp->data[0], 0);
1923 		if (aac_sync_fib(softs, RequestSupplementAdapterInfo,
1924 		    sizeof (struct aac_fib_header)) != AACOK) {
1925 			AACDB_PRINT(softs, CE_WARN,
1926 			    "RequestSupplementAdapterInfo failed");
1927 			return (AACERR);
1928 		}
1929 		sinfp = (struct aac_supplement_adapter_info *)fibp->data;
1930 		AAC_REP_GET_FIELD8(acc, sinfr, sinfp, AdapterTypeText[0], 17+1);
1931 		AAC_REP_GET_FIELD8(acc, sinfr, sinfp, Pad[0], 2);
1932 		AAC_GET_FIELD32(acc, sinfr, sinfp, FlashMemoryByteSize);
1933 		AAC_GET_FIELD32(acc, sinfr, sinfp, FlashImageId);
1934 		AAC_GET_FIELD32(acc, sinfr, sinfp, MaxNumberPorts);
1935 		AAC_GET_FIELD32(acc, sinfr, sinfp, Version);
1936 		AAC_GET_FIELD32(acc, sinfr, sinfp, FeatureBits);
1937 		AAC_GET_FIELD8(acc, sinfr, sinfp, SlotNumber);
1938 		AAC_REP_GET_FIELD8(acc, sinfr, sinfp, ReservedPad0[0], 3);
1939 		AAC_REP_GET_FIELD8(acc, sinfr, sinfp, BuildDate[0], 12);
1940 		AAC_GET_FIELD32(acc, sinfr, sinfp, CurrentNumberPorts);
1941 		AAC_REP_GET_FIELD8(acc, sinfr, sinfp, VpdInfo,
1942 		    sizeof (struct vpd_info));
1943 		aac_fsa_rev(softs, &sinfp->FlashFirmwareRevision,
1944 		    &sinfr->FlashFirmwareRevision);
1945 		AAC_GET_FIELD32(acc, sinfr, sinfp, RaidTypeMorphOptions);
1946 		aac_fsa_rev(softs, &sinfp->FlashFirmwareBootRevision,
1947 		    &sinfr->FlashFirmwareBootRevision);
1948 		AAC_REP_GET_FIELD8(acc, sinfr, sinfp, MfgPcbaSerialNo,
1949 		    MFG_PCBA_SERIAL_NUMBER_WIDTH);
1950 		AAC_REP_GET_FIELD8(acc, sinfr, sinfp, MfgWWNName[0],
1951 		    MFG_WWN_WIDTH);
1952 		AAC_REP_GET_FIELD32(acc, sinfr, sinfp, ReservedGrowth[0], 2);
1953 	}
1954 	return (AACOK);
1955 }
1956 
1957 /*
1958  * The following function comes from Adaptec:
1959  *
1960  * Routine to be called during initialization of communications with
1961  * the adapter to handle possible adapter configuration issues. When
1962  * the adapter first boots up, it examines attached drives, etc, and
1963  * potentially comes up with a new or revised configuration (relative to
1964  * what's stored in it's NVRAM). Additionally it may discover problems
1965  * that make the current physical configuration unworkable (currently
1966  * applicable only to cluster configuration issues).
1967  *
1968  * If there are no configuration issues or the issues are considered
1969  * trival by the adapter, it will set it's configuration status to
1970  * "FSACT_CONTINUE" and execute the "commit confiuguration" action
1971  * automatically on it's own.
1972  *
1973  * However, if there are non-trivial issues, the adapter will set it's
1974  * internal configuration status to "FSACT_PAUSE" or "FASCT_ABORT"
1975  * and wait for some agent on the host to issue the "\ContainerCommand
1976  * \VM_ContainerConfig\CT_COMMIT_CONFIG" FIB command to cause the
1977  * adapter to commit the new/updated configuration and enable
1978  * un-inhibited operation.  The host agent should first issue the
1979  * "\ContainerCommand\VM_ContainerConfig\CT_GET_CONFIG_STATUS" FIB
1980  * command to obtain information about config issues detected by
1981  * the adapter.
1982  *
1983  * Normally the adapter's PC BIOS will execute on the host following
1984  * adapter poweron and reset and will be responsible for querring the
1985  * adapter with CT_GET_CONFIG_STATUS and issuing the CT_COMMIT_CONFIG
1986  * command if appropriate.
1987  *
1988  * However, with the introduction of IOP reset support, the adapter may
1989  * boot up without the benefit of the adapter's PC BIOS host agent.
1990  * This routine is intended to take care of these issues in situations
1991  * where BIOS doesn't execute following adapter poweron or reset.  The
1992  * CT_COMMIT_CONFIG command is a no-op if it's already been issued, so
1993  * there is no harm in doing this when it's already been done.
1994  */
1995 static int
1996 aac_handle_adapter_config_issues(struct aac_softstate *softs)
1997 {
1998 	ddi_acc_handle_t acc = softs->sync_slot.fib_acc_handle;
1999 	struct aac_fib *fibp = softs->sync_slot.fibp;
2000 	struct aac_Container *cmd;
2001 	struct aac_Container_resp *resp;
2002 	struct aac_cf_status_header *cfg_sts_hdr;
2003 	uint32_t resp_status;
2004 	uint32_t ct_status;
2005 	uint32_t cfg_stat_action;
2006 	int rval;
2007 
2008 	/* Get adapter config status */
2009 	cmd = (struct aac_Container *)&fibp->data[0];
2010 
2011 	bzero(cmd, sizeof (*cmd) - CT_PACKET_SIZE);
2012 	ddi_put32(acc, &cmd->Command, VM_ContainerConfig);
2013 	ddi_put32(acc, &cmd->CTCommand.command, CT_GET_CONFIG_STATUS);
2014 	ddi_put32(acc, &cmd->CTCommand.param[CNT_SIZE],
2015 	    sizeof (struct aac_cf_status_header));
2016 	rval = aac_sync_fib(softs, ContainerCommand,
2017 	    AAC_FIB_SIZEOF(struct aac_Container));
2018 	resp = (struct aac_Container_resp *)cmd;
2019 	cfg_sts_hdr = (struct aac_cf_status_header *)resp->CTResponse.data;
2020 
2021 	resp_status = ddi_get32(acc, &resp->Status);
2022 	ct_status = ddi_get32(acc, &resp->CTResponse.param[0]);
2023 	if ((rval == AACOK) && (resp_status == 0) && (ct_status == CT_OK)) {
2024 		cfg_stat_action = ddi_get32(acc, &cfg_sts_hdr->action);
2025 
2026 		/* Commit configuration if it's reasonable to do so. */
2027 		if (cfg_stat_action <= CFACT_PAUSE) {
2028 			bzero(cmd, sizeof (*cmd) - CT_PACKET_SIZE);
2029 			ddi_put32(acc, &cmd->Command, VM_ContainerConfig);
2030 			ddi_put32(acc, &cmd->CTCommand.command,
2031 			    CT_COMMIT_CONFIG);
2032 			rval = aac_sync_fib(softs, ContainerCommand,
2033 			    AAC_FIB_SIZEOF(struct aac_Container));
2034 
2035 			resp_status = ddi_get32(acc, &resp->Status);
2036 			ct_status = ddi_get32(acc, &resp->CTResponse.param[0]);
2037 			if ((rval == AACOK) && (resp_status == 0) &&
2038 			    (ct_status == CT_OK))
2039 				/* Successful completion */
2040 				rval = AACMPE_OK;
2041 			else
2042 				/* Auto-commit aborted due to error(s). */
2043 				rval = AACMPE_COMMIT_CONFIG;
2044 		} else {
2045 			/*
2046 			 * Auto-commit aborted due to adapter indicating
2047 			 * configuration issue(s) too dangerous to auto-commit.
2048 			 */
2049 			rval = AACMPE_CONFIG_STATUS;
2050 		}
2051 	} else {
2052 		cmn_err(CE_WARN, "!Configuration issue, auto-commit aborted");
2053 		rval = AACMPE_CONFIG_STATUS;
2054 	}
2055 	return (rval);
2056 }
2057 
2058 /*
2059  * Hardware initialization and resource allocation
2060  */
2061 static int
2062 aac_common_attach(struct aac_softstate *softs)
2063 {
2064 	uint32_t status;
2065 	int i;
2066 
2067 	DBCALLED(softs, 1);
2068 
2069 	/*
2070 	 * Do a little check here to make sure there aren't any outstanding
2071 	 * FIBs in the message queue. At this point there should not be and
2072 	 * if there are they are probably left over from another instance of
2073 	 * the driver like when the system crashes and the crash dump driver
2074 	 * gets loaded.
2075 	 */
2076 	while (AAC_OUTB_GET(softs) != 0xfffffffful)
2077 		;
2078 
2079 	/*
2080 	 * Wait the card to complete booting up before do anything that
2081 	 * attempts to communicate with it.
2082 	 */
2083 	status = AAC_FWSTATUS_GET(softs);
2084 	if (status == AAC_SELF_TEST_FAILED || status == AAC_KERNEL_PANIC)
2085 		goto error;
2086 	i = AAC_FWUP_TIMEOUT * 1000; /* set timeout */
2087 	AAC_BUSYWAIT(AAC_FWSTATUS_GET(softs) & AAC_KERNEL_UP_AND_RUNNING, i);
2088 	if (i == 0) {
2089 		cmn_err(CE_CONT, "?Fatal error: controller not ready");
2090 		aac_fm_ereport(softs, DDI_FM_DEVICE_NO_RESPONSE);
2091 		ddi_fm_service_impact(softs->devinfo_p, DDI_SERVICE_LOST);
2092 		goto error;
2093 	}
2094 
2095 	/* Read and set card supported options and settings */
2096 	if (aac_check_firmware(softs) == AACERR) {
2097 		aac_fm_ereport(softs, DDI_FM_DEVICE_NO_RESPONSE);
2098 		ddi_fm_service_impact(softs->devinfo_p, DDI_SERVICE_LOST);
2099 		goto error;
2100 	}
2101 
2102 	/* Clear out all interrupts */
2103 	AAC_STATUS_CLR(softs, ~0);
2104 
2105 	/* Setup communication space with the card */
2106 	if (softs->comm_space_dma_handle == NULL) {
2107 		if (aac_alloc_comm_space(softs) != AACOK)
2108 			goto error;
2109 	}
2110 	if (aac_setup_comm_space(softs) != AACOK) {
2111 		cmn_err(CE_CONT, "?Setup communication space failed");
2112 		aac_fm_ereport(softs, DDI_FM_DEVICE_NO_RESPONSE);
2113 		ddi_fm_service_impact(softs->devinfo_p, DDI_SERVICE_LOST);
2114 		goto error;
2115 	}
2116 
2117 #ifdef DEBUG
2118 	if (aac_get_fw_debug_buffer(softs) != AACOK)
2119 		cmn_err(CE_CONT, "?firmware UART trace not supported");
2120 #endif
2121 
2122 	/* Allocate slots */
2123 	if ((softs->total_slots == 0) && (aac_create_slots(softs) != AACOK)) {
2124 		cmn_err(CE_CONT, "?Fatal error: slots allocate failed");
2125 		goto error;
2126 	}
2127 	AACDB_PRINT(softs, CE_NOTE, "%d slots allocated", softs->total_slots);
2128 
2129 	/* Allocate FIBs */
2130 	if (softs->total_fibs < softs->total_slots) {
2131 		aac_alloc_fibs(softs);
2132 		if (softs->total_fibs == 0)
2133 			goto error;
2134 		AACDB_PRINT(softs, CE_NOTE, "%d fibs allocated",
2135 		    softs->total_fibs);
2136 	}
2137 
2138 	/* Get adapter names */
2139 	if (CARD_IS_UNKNOWN(softs->card)) {
2140 		struct aac_supplement_adapter_info sinf;
2141 
2142 		if (aac_get_adapter_info(softs, NULL, &sinf) != AACOK) {
2143 			cmn_err(CE_CONT, "?Query adapter information failed");
2144 		} else {
2145 			char *p, *p0, *p1;
2146 
2147 			/*
2148 			 * Now find the controller name in supp_adapter_info->
2149 			 * AdapterTypeText. Use the first word as the vendor
2150 			 * and the other words as the product name.
2151 			 */
2152 			AACDB_PRINT(softs, CE_NOTE, "sinf.AdapterTypeText = "
2153 			    "\"%s\"", sinf.AdapterTypeText);
2154 			p = sinf.AdapterTypeText;
2155 			p0 = p1 = NULL;
2156 			/* Skip heading spaces */
2157 			while (*p && (*p == ' ' || *p == '\t'))
2158 				p++;
2159 			p0 = p;
2160 			while (*p && (*p != ' ' && *p != '\t'))
2161 				p++;
2162 			/* Remove middle spaces */
2163 			while (*p && (*p == ' ' || *p == '\t'))
2164 				*p++ = 0;
2165 			p1 = p;
2166 			/* Remove trailing spaces */
2167 			p = p1 + strlen(p1) - 1;
2168 			while (p > p1 && (*p == ' ' || *p == '\t'))
2169 				*p-- = 0;
2170 			if (*p0 && *p1) {
2171 				(void *)strncpy(softs->vendor_name, p0,
2172 				    AAC_VENDOR_LEN);
2173 				(void *)strncpy(softs->product_name, p1,
2174 				    AAC_PRODUCT_LEN);
2175 			} else {
2176 				cmn_err(CE_WARN,
2177 				    "?adapter name mis-formatted\n");
2178 				if (*p0)
2179 					(void *)strncpy(softs->product_name,
2180 					    p0, AAC_PRODUCT_LEN);
2181 			}
2182 		}
2183 	}
2184 
2185 	cmn_err(CE_NOTE,
2186 	    "!aac driver %d.%02d.%02d-%d, found card: " \
2187 	    "%s %s(pci0x%x.%x.%x.%x) at 0x%x",
2188 	    AAC_DRIVER_MAJOR_VERSION,
2189 	    AAC_DRIVER_MINOR_VERSION,
2190 	    AAC_DRIVER_BUGFIX_LEVEL,
2191 	    AAC_DRIVER_BUILD,
2192 	    softs->vendor_name, softs->product_name,
2193 	    softs->vendid, softs->devid, softs->subvendid, softs->subsysid,
2194 	    softs->pci_mem_base_paddr);
2195 
2196 	/* Perform acceptance of adapter-detected config changes if possible */
2197 	if (aac_handle_adapter_config_issues(softs) != AACMPE_OK) {
2198 		cmn_err(CE_CONT, "?Handle adapter config issues failed");
2199 		aac_fm_ereport(softs, DDI_FM_DEVICE_NO_RESPONSE);
2200 		ddi_fm_service_impact(softs->devinfo_p, DDI_SERVICE_LOST);
2201 		goto error;
2202 	}
2203 
2204 	/* Setup containers */
2205 	bzero(softs->containers, sizeof (struct aac_container) * AAC_MAX_LD);
2206 	softs->container_count = 0;
2207 	if (aac_probe_containers(softs) != AACOK) {
2208 		cmn_err(CE_CONT, "?Fatal error: get container info error");
2209 		goto error;
2210 	}
2211 
2212 	/* Check dma & acc handles allocated in attach */
2213 	if (aac_check_dma_handle(softs->comm_space_dma_handle) != DDI_SUCCESS) {
2214 		ddi_fm_service_impact(softs->devinfo_p, DDI_SERVICE_LOST);
2215 		goto error;
2216 	}
2217 
2218 	if (aac_check_acc_handle(softs->pci_mem_handle) != DDI_SUCCESS) {
2219 		ddi_fm_service_impact(softs->devinfo_p, DDI_SERVICE_LOST);
2220 		goto error;
2221 	}
2222 
2223 	for (i = 0; i < softs->total_slots; i++) {
2224 		if (aac_check_dma_handle(softs->io_slot[i].fib_dma_handle) !=
2225 		    DDI_SUCCESS) {
2226 			ddi_fm_service_impact(softs->devinfo_p,
2227 			    DDI_SERVICE_LOST);
2228 			goto error;
2229 		}
2230 	}
2231 
2232 	return (AACOK);
2233 
2234 error:
2235 	if (softs->state & AAC_STATE_RESET)
2236 		return (AACERR);
2237 	if (softs->total_fibs > 0)
2238 		aac_destroy_fibs(softs);
2239 	if (softs->total_slots > 0)
2240 		aac_destroy_slots(softs);
2241 	if (softs->comm_space_dma_handle)
2242 		aac_free_comm_space(softs);
2243 	return (AACERR);
2244 }
2245 
2246 /*
2247  * Hardware shutdown and resource release
2248  */
2249 static void
2250 aac_common_detach(struct aac_softstate *softs)
2251 {
2252 	DBCALLED(softs, 1);
2253 
2254 	(void) aac_shutdown(softs);
2255 
2256 	aac_destroy_fibs(softs);
2257 	aac_destroy_slots(softs);
2258 	aac_free_comm_space(softs);
2259 }
2260 
2261 /*
2262  * Send a synchronous command to the controller and wait for a result.
2263  * Indicate if the controller completed the command with an error status.
2264  */
2265 int
2266 aac_sync_mbcommand(struct aac_softstate *softs, uint32_t cmd,
2267     uint32_t arg0, uint32_t arg1, uint32_t arg2, uint32_t arg3,
2268     uint32_t *statusp)
2269 {
2270 	int timeout;
2271 	uint32_t status;
2272 
2273 	if (statusp != NULL)
2274 		*statusp = SRB_STATUS_SUCCESS;
2275 
2276 	/* Fill in mailbox */
2277 	AAC_MAILBOX_SET(softs, cmd, arg0, arg1, arg2, arg3);
2278 
2279 	/* Ensure the sync command doorbell flag is cleared */
2280 	AAC_STATUS_CLR(softs, AAC_DB_SYNC_COMMAND);
2281 
2282 	/* Then set it to signal the adapter */
2283 	AAC_NOTIFY(softs, AAC_DB_SYNC_COMMAND);
2284 
2285 	/* Spin waiting for the command to complete */
2286 	timeout = AAC_IMMEDIATE_TIMEOUT * 1000;
2287 	AAC_BUSYWAIT(AAC_STATUS_GET(softs) & AAC_DB_SYNC_COMMAND, timeout);
2288 	if (!timeout) {
2289 		AACDB_PRINT(softs, CE_WARN,
2290 		    "Sync command timed out after %d seconds (0x%x)!",
2291 		    AAC_IMMEDIATE_TIMEOUT, AAC_FWSTATUS_GET(softs));
2292 		return (AACERR);
2293 	}
2294 
2295 	/* Clear the completion flag */
2296 	AAC_STATUS_CLR(softs, AAC_DB_SYNC_COMMAND);
2297 
2298 	/* Get the command status */
2299 	status = AAC_MAILBOX_GET(softs, 0);
2300 	if (statusp != NULL)
2301 		*statusp = status;
2302 	if (status != SRB_STATUS_SUCCESS) {
2303 		AACDB_PRINT(softs, CE_WARN,
2304 		    "Sync command fail: status = 0x%x", status);
2305 		return (AACERR);
2306 	}
2307 
2308 	return (AACOK);
2309 }
2310 
2311 /*
2312  * Send a synchronous FIB to the adapter and wait for its completion
2313  */
2314 static int
2315 aac_sync_fib(struct aac_softstate *softs, uint16_t cmd, uint16_t fibsize)
2316 {
2317 	struct aac_slot *slotp = &softs->sync_slot;
2318 	ddi_dma_handle_t dma = slotp->fib_dma_handle;
2319 	uint32_t status;
2320 	int rval;
2321 
2322 	/* Sync fib only supports 512 bytes */
2323 	if (fibsize > AAC_FIB_SIZE)
2324 		return (AACERR);
2325 
2326 	/*
2327 	 * Setup sync fib
2328 	 * Need not reinitialize FIB header if it's already been filled
2329 	 * by others like aac_cmd_fib_scsi as aac_cmd.
2330 	 */
2331 	if (slotp->acp == NULL)
2332 		aac_cmd_fib_header(softs, slotp, cmd, fibsize);
2333 
2334 	(void) ddi_dma_sync(dma, offsetof(struct aac_comm_space, sync_fib),
2335 	    fibsize, DDI_DMA_SYNC_FORDEV);
2336 
2337 	/* Give the FIB to the controller, wait for a response. */
2338 	rval = aac_sync_mbcommand(softs, AAC_MONKER_SYNCFIB,
2339 	    slotp->fib_phyaddr, 0, 0, 0, &status);
2340 	if (rval == AACERR) {
2341 		AACDB_PRINT(softs, CE_WARN,
2342 		    "Send sync fib to controller failed");
2343 		return (AACERR);
2344 	}
2345 
2346 	(void) ddi_dma_sync(dma, offsetof(struct aac_comm_space, sync_fib),
2347 	    AAC_FIB_SIZE, DDI_DMA_SYNC_FORCPU);
2348 
2349 	if ((aac_check_acc_handle(softs->pci_mem_handle) != DDI_SUCCESS) ||
2350 	    (aac_check_dma_handle(dma) != DDI_SUCCESS)) {
2351 		ddi_fm_service_impact(softs->devinfo_p, DDI_SERVICE_UNAFFECTED);
2352 		return (AACERR);
2353 	}
2354 
2355 	return (AACOK);
2356 }
2357 
2358 static void
2359 aac_cmd_initq(struct aac_cmd_queue *q)
2360 {
2361 	q->q_head = NULL;
2362 	q->q_tail = (struct aac_cmd *)&q->q_head;
2363 }
2364 
2365 /*
2366  * Remove a cmd from the head of q
2367  */
2368 static struct aac_cmd *
2369 aac_cmd_dequeue(struct aac_cmd_queue *q)
2370 {
2371 	struct aac_cmd *acp;
2372 
2373 	_NOTE(ASSUMING_PROTECTED(*q))
2374 
2375 	if ((acp = q->q_head) != NULL) {
2376 		if ((q->q_head = acp->next) != NULL)
2377 			acp->next = NULL;
2378 		else
2379 			q->q_tail = (struct aac_cmd *)&q->q_head;
2380 		acp->prev = NULL;
2381 	}
2382 	return (acp);
2383 }
2384 
2385 /*
2386  * Add a cmd to the tail of q
2387  */
2388 static void
2389 aac_cmd_enqueue(struct aac_cmd_queue *q, struct aac_cmd *acp)
2390 {
2391 	ASSERT(acp->next == NULL);
2392 	acp->prev = q->q_tail;
2393 	q->q_tail->next = acp;
2394 	q->q_tail = acp;
2395 }
2396 
2397 /*
2398  * Remove the cmd ac from q
2399  */
2400 static void
2401 aac_cmd_delete(struct aac_cmd_queue *q, struct aac_cmd *acp)
2402 {
2403 	if (acp->prev) {
2404 		if ((acp->prev->next = acp->next) != NULL) {
2405 			acp->next->prev = acp->prev;
2406 			acp->next = NULL;
2407 		} else {
2408 			q->q_tail = acp->prev;
2409 		}
2410 		acp->prev = NULL;
2411 	}
2412 	/* ac is not in the queue */
2413 }
2414 
2415 /*
2416  * Atomically insert an entry into the nominated queue, returns 0 on success or
2417  * AACERR if the queue is full.
2418  *
2419  * Note: it would be more efficient to defer notifying the controller in
2420  *	 the case where we may be inserting several entries in rapid succession,
2421  *	 but implementing this usefully may be difficult (it would involve a
2422  *	 separate queue/notify interface).
2423  */
2424 static int
2425 aac_fib_enqueue(struct aac_softstate *softs, int queue, uint32_t fib_addr,
2426     uint32_t fib_size)
2427 {
2428 	ddi_dma_handle_t dma = softs->comm_space_dma_handle;
2429 	ddi_acc_handle_t acc = softs->comm_space_acc_handle;
2430 	uint32_t pi, ci;
2431 
2432 	DBCALLED(softs, 2);
2433 
2434 	ASSERT(queue == AAC_ADAP_NORM_CMD_Q || queue == AAC_ADAP_NORM_RESP_Q);
2435 
2436 	/* Get the producer/consumer indices */
2437 	(void) ddi_dma_sync(dma, (uint8_t *)softs->qtablep->qt_qindex[queue] - \
2438 	    (uint8_t *)softs->comm_space, sizeof (uint32_t) * 2,
2439 	    DDI_DMA_SYNC_FORCPU);
2440 	if (aac_check_dma_handle(dma) != DDI_SUCCESS) {
2441 		ddi_fm_service_impact(softs->devinfo_p, DDI_SERVICE_UNAFFECTED);
2442 		return (AACERR);
2443 	}
2444 
2445 	pi = ddi_get32(acc,
2446 	    &softs->qtablep->qt_qindex[queue][AAC_PRODUCER_INDEX]);
2447 	ci = ddi_get32(acc,
2448 	    &softs->qtablep->qt_qindex[queue][AAC_CONSUMER_INDEX]);
2449 
2450 	/*
2451 	 * Wrap the queue first before we check the queue to see
2452 	 * if it is full
2453 	 */
2454 	if (pi >= aac_qinfo[queue].size)
2455 		pi = 0;
2456 
2457 	/* XXX queue full */
2458 	if ((pi + 1) == ci)
2459 		return (AACERR);
2460 
2461 	/* Fill in queue entry */
2462 	ddi_put32(acc, &((softs->qentries[queue] + pi)->aq_fib_size), fib_size);
2463 	ddi_put32(acc, &((softs->qentries[queue] + pi)->aq_fib_addr), fib_addr);
2464 	(void) ddi_dma_sync(dma, (uint8_t *)(softs->qentries[queue] + pi) - \
2465 	    (uint8_t *)softs->comm_space, sizeof (struct aac_queue_entry),
2466 	    DDI_DMA_SYNC_FORDEV);
2467 
2468 	/* Update producer index */
2469 	ddi_put32(acc, &softs->qtablep->qt_qindex[queue][AAC_PRODUCER_INDEX],
2470 	    pi + 1);
2471 	(void) ddi_dma_sync(dma,
2472 	    (uint8_t *)&softs->qtablep->qt_qindex[queue][AAC_PRODUCER_INDEX] - \
2473 	    (uint8_t *)softs->comm_space, sizeof (uint32_t),
2474 	    DDI_DMA_SYNC_FORDEV);
2475 
2476 	if (aac_qinfo[queue].notify != 0)
2477 		AAC_NOTIFY(softs, aac_qinfo[queue].notify);
2478 	return (AACOK);
2479 }
2480 
2481 /*
2482  * Atomically remove one entry from the nominated queue, returns 0 on
2483  * success or AACERR if the queue is empty.
2484  */
2485 static int
2486 aac_fib_dequeue(struct aac_softstate *softs, int queue, int *idxp)
2487 {
2488 	ddi_acc_handle_t acc = softs->comm_space_acc_handle;
2489 	ddi_dma_handle_t dma = softs->comm_space_dma_handle;
2490 	uint32_t pi, ci;
2491 	int unfull = 0;
2492 
2493 	DBCALLED(softs, 2);
2494 
2495 	ASSERT(idxp);
2496 
2497 	/* Get the producer/consumer indices */
2498 	(void) ddi_dma_sync(dma, (uint8_t *)softs->qtablep->qt_qindex[queue] - \
2499 	    (uint8_t *)softs->comm_space, sizeof (uint32_t) * 2,
2500 	    DDI_DMA_SYNC_FORCPU);
2501 	pi = ddi_get32(acc,
2502 	    &softs->qtablep->qt_qindex[queue][AAC_PRODUCER_INDEX]);
2503 	ci = ddi_get32(acc,
2504 	    &softs->qtablep->qt_qindex[queue][AAC_CONSUMER_INDEX]);
2505 
2506 	/* Check for queue empty */
2507 	if (ci == pi)
2508 		return (AACERR);
2509 
2510 	if (pi >= aac_qinfo[queue].size)
2511 		pi = 0;
2512 
2513 	/* Check for queue full */
2514 	if (ci == pi + 1)
2515 		unfull = 1;
2516 
2517 	/*
2518 	 * The controller does not wrap the queue,
2519 	 * so we have to do it by ourselves
2520 	 */
2521 	if (ci >= aac_qinfo[queue].size)
2522 		ci = 0;
2523 
2524 	/* Fetch the entry */
2525 	(void) ddi_dma_sync(dma, (uint8_t *)(softs->qentries[queue] + pi) - \
2526 	    (uint8_t *)softs->comm_space, sizeof (struct aac_queue_entry),
2527 	    DDI_DMA_SYNC_FORCPU);
2528 	if (aac_check_dma_handle(dma) != DDI_SUCCESS) {
2529 		ddi_fm_service_impact(softs->devinfo_p, DDI_SERVICE_UNAFFECTED);
2530 		return (AACERR);
2531 	}
2532 
2533 	switch (queue) {
2534 	case AAC_HOST_NORM_RESP_Q:
2535 	case AAC_HOST_HIGH_RESP_Q:
2536 		*idxp = ddi_get32(acc,
2537 		    &(softs->qentries[queue] + ci)->aq_fib_addr);
2538 		break;
2539 
2540 	case AAC_HOST_NORM_CMD_Q:
2541 	case AAC_HOST_HIGH_CMD_Q:
2542 		*idxp = ddi_get32(acc,
2543 		    &(softs->qentries[queue] + ci)->aq_fib_addr) / AAC_FIB_SIZE;
2544 		break;
2545 
2546 	default:
2547 		cmn_err(CE_NOTE, "!Invalid queue in aac_fib_dequeue()");
2548 		return (AACERR);
2549 	}
2550 
2551 	/* Update consumer index */
2552 	ddi_put32(acc, &softs->qtablep->qt_qindex[queue][AAC_CONSUMER_INDEX],
2553 	    ci + 1);
2554 	(void) ddi_dma_sync(dma,
2555 	    (uint8_t *)&softs->qtablep->qt_qindex[queue][AAC_CONSUMER_INDEX] - \
2556 	    (uint8_t *)softs->comm_space, sizeof (uint32_t),
2557 	    DDI_DMA_SYNC_FORDEV);
2558 
2559 	if (unfull && aac_qinfo[queue].notify != 0)
2560 		AAC_NOTIFY(softs, aac_qinfo[queue].notify);
2561 	return (AACOK);
2562 }
2563 
2564 /*
2565  * Request information of the container cid
2566  */
2567 static struct aac_mntinforesp *
2568 aac_get_container_info(struct aac_softstate *softs, int cid)
2569 {
2570 	ddi_acc_handle_t acc = softs->sync_slot.fib_acc_handle;
2571 	struct aac_fib *fibp = softs->sync_slot.fibp;
2572 	struct aac_mntinfo *mi = (struct aac_mntinfo *)&fibp->data[0];
2573 	struct aac_mntinforesp *mir;
2574 
2575 	ddi_put32(acc, &mi->Command, /* Use 64-bit LBA if enabled */
2576 	    (softs->flags & AAC_FLAGS_LBA_64BIT) ?
2577 	    VM_NameServe64 : VM_NameServe);
2578 	ddi_put32(acc, &mi->MntType, FT_FILESYS);
2579 	ddi_put32(acc, &mi->MntCount, cid);
2580 
2581 	if (aac_sync_fib(softs, ContainerCommand,
2582 	    AAC_FIB_SIZEOF(struct aac_mntinfo)) == AACERR) {
2583 		AACDB_PRINT(softs, CE_WARN, "Error probe container %d", cid);
2584 		return (NULL);
2585 	}
2586 
2587 	mir = (struct aac_mntinforesp *)&fibp->data[0];
2588 	if (ddi_get32(acc, &mir->Status) == ST_OK)
2589 		return (mir);
2590 	return (NULL);
2591 }
2592 
2593 static int
2594 aac_get_container_count(struct aac_softstate *softs, int *count)
2595 {
2596 	ddi_acc_handle_t acc = softs->sync_slot.fib_acc_handle;
2597 	struct aac_mntinforesp *mir;
2598 
2599 	if ((mir = aac_get_container_info(softs, 0)) == NULL)
2600 		return (AACERR);
2601 	*count = ddi_get32(acc, &mir->MntRespCount);
2602 	if (*count > AAC_MAX_LD) {
2603 		AACDB_PRINT(softs, CE_CONT,
2604 		    "container count(%d) > AAC_MAX_LD", *count);
2605 		return (AACERR);
2606 	}
2607 	return (AACOK);
2608 }
2609 
2610 static int
2611 aac_get_container_uid(struct aac_softstate *softs, uint32_t cid, uint32_t *uid)
2612 {
2613 	ddi_acc_handle_t acc = softs->sync_slot.fib_acc_handle;
2614 	struct aac_Container *ct = (struct aac_Container *) \
2615 	    &softs->sync_slot.fibp->data[0];
2616 
2617 	bzero(ct, sizeof (*ct) - CT_PACKET_SIZE);
2618 	ddi_put32(acc, &ct->Command, VM_ContainerConfig);
2619 	ddi_put32(acc, &ct->CTCommand.command, CT_CID_TO_32BITS_UID);
2620 	ddi_put32(acc, &ct->CTCommand.param[0], cid);
2621 
2622 	if (aac_sync_fib(softs, ContainerCommand,
2623 	    AAC_FIB_SIZEOF(struct aac_Container)) == AACERR)
2624 		return (AACERR);
2625 	if (ddi_get32(acc, &ct->CTCommand.param[0]) != CT_OK)
2626 		return (AACERR);
2627 
2628 	*uid = ddi_get32(acc, &ct->CTCommand.param[1]);
2629 	return (AACOK);
2630 }
2631 
2632 static int
2633 aac_probe_container(struct aac_softstate *softs, uint32_t cid)
2634 {
2635 	struct aac_container *dvp = &softs->containers[cid];
2636 	ddi_acc_handle_t acc = softs->sync_slot.fib_acc_handle;
2637 	struct aac_mntinforesp *mir;
2638 	uint64_t size;
2639 	uint32_t uid;
2640 
2641 	/* Get container basic info */
2642 	if ((mir = aac_get_container_info(softs, cid)) == NULL)
2643 		return (AACERR);
2644 
2645 	if (ddi_get32(acc, &mir->MntObj.VolType) == CT_NONE) {
2646 		if (dvp->valid) {
2647 			AACDB_PRINT(softs, CE_NOTE,
2648 			    ">>> Container %d deleted", cid);
2649 			dvp->valid = 0;
2650 		}
2651 	} else {
2652 		size = AAC_MIR_SIZE(softs, acc, mir);
2653 		AACDB_PRINT(softs, CE_NOTE, "Container #%d found: " \
2654 		    "size=0x%x.%08x, type=%d, name=%s",
2655 		    cid,
2656 		    ddi_get32(acc, &mir->MntObj.CapacityHigh),
2657 		    ddi_get32(acc, &mir->MntObj.Capacity),
2658 		    ddi_get32(acc, &mir->MntObj.VolType),
2659 		    mir->MntObj.FileSystemName);
2660 
2661 		/* Get container UID */
2662 		if (aac_get_container_uid(softs, cid, &uid) == AACERR) {
2663 			AACDB_PRINT(softs, CE_CONT,
2664 			    "query container %d uid failed", cid);
2665 			return (AACERR);
2666 		}
2667 		AACDB_PRINT(softs, CE_CONT, "uid=0x%08x", uid);
2668 
2669 		if (dvp->valid) {
2670 			if (dvp->uid != uid) {
2671 				AACDB_PRINT(softs, CE_WARN,
2672 				    ">>> Container %u uid changed to %d",
2673 				    cid, uid);
2674 				dvp->uid = uid;
2675 			}
2676 			if (dvp->size != size) {
2677 				AACDB_PRINT(softs, CE_NOTE,
2678 				    ">>> Container %u size changed to %"PRIu64,
2679 				    cid, size);
2680 				dvp->size = size;
2681 			}
2682 		} else { /* Init new container */
2683 			AACDB_PRINT(softs, CE_NOTE,
2684 			    ">>> Container %d added", cid);
2685 			dvp->valid = 1;
2686 
2687 			dvp->cid = cid;
2688 			dvp->uid = uid;
2689 			dvp->size = size;
2690 			dvp->locked = 0;
2691 			dvp->deleted = 0;
2692 		}
2693 	}
2694 	return (AACOK);
2695 }
2696 
2697 /*
2698  * Do a rescan of all the possible containers and update the container list
2699  * with newly online/offline containers.
2700  */
2701 static int
2702 aac_probe_containers(struct aac_softstate *softs)
2703 {
2704 	int i, count, total;
2705 
2706 	/* Loop over possible containers */
2707 	count = softs->container_count;
2708 	if (aac_get_container_count(softs, &count) == AACERR)
2709 		return (AACERR);
2710 	for (i = total = 0; i < count; i++) {
2711 		if (aac_probe_container(softs, i) == AACOK)
2712 			total++;
2713 	}
2714 	if (count < softs->container_count) {
2715 		struct aac_container *dvp;
2716 
2717 		for (dvp = &softs->containers[count];
2718 		    dvp < &softs->containers[softs->container_count]; dvp++) {
2719 			if (dvp->valid == 0)
2720 				continue;
2721 			AACDB_PRINT(softs, CE_NOTE, ">>> Container %d deleted",
2722 			    dvp->cid);
2723 			dvp->valid = 0;
2724 		}
2725 	}
2726 	softs->container_count = count;
2727 	AACDB_PRINT(softs, CE_CONT, "?Total %d container(s) found", total);
2728 	return (AACOK);
2729 }
2730 
2731 static int
2732 aac_alloc_comm_space(struct aac_softstate *softs)
2733 {
2734 	size_t rlen;
2735 	ddi_dma_cookie_t cookie;
2736 	uint_t cookien;
2737 
2738 	/* Allocate DMA for comm. space */
2739 	if (ddi_dma_alloc_handle(
2740 	    softs->devinfo_p,
2741 	    &softs->addr_dma_attr,
2742 	    DDI_DMA_SLEEP,
2743 	    NULL,
2744 	    &softs->comm_space_dma_handle) != DDI_SUCCESS) {
2745 		AACDB_PRINT(softs, CE_WARN,
2746 		    "Cannot alloc dma handle for communication area");
2747 		goto error;
2748 	}
2749 	if (ddi_dma_mem_alloc(
2750 	    softs->comm_space_dma_handle,
2751 	    sizeof (struct aac_comm_space),
2752 	    &aac_acc_attr,
2753 	    DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
2754 	    DDI_DMA_SLEEP,
2755 	    NULL,
2756 	    (caddr_t *)&softs->comm_space,
2757 	    &rlen,
2758 	    &softs->comm_space_acc_handle) != DDI_SUCCESS) {
2759 		AACDB_PRINT(softs, CE_WARN,
2760 		    "Cannot alloc mem for communication area");
2761 		goto error;
2762 	}
2763 	if (ddi_dma_addr_bind_handle(
2764 	    softs->comm_space_dma_handle,
2765 	    NULL,
2766 	    (caddr_t)softs->comm_space,
2767 	    sizeof (struct aac_comm_space),
2768 	    DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
2769 	    DDI_DMA_SLEEP,
2770 	    NULL,
2771 	    &cookie,
2772 	    &cookien) != DDI_DMA_MAPPED) {
2773 		AACDB_PRINT(softs, CE_WARN,
2774 		    "DMA bind failed for communication area");
2775 		goto error;
2776 	}
2777 	softs->comm_space_phyaddr = cookie.dmac_address;
2778 
2779 	/* Setup sync FIB space */
2780 	softs->sync_slot.fibp = &softs->comm_space->sync_fib;
2781 	softs->sync_slot.fib_phyaddr = softs->comm_space_phyaddr + \
2782 	    offsetof(struct aac_comm_space, sync_fib);
2783 	softs->sync_slot.fib_acc_handle = softs->comm_space_acc_handle;
2784 	softs->sync_slot.fib_dma_handle = softs->comm_space_dma_handle;
2785 
2786 	return (AACOK);
2787 error:
2788 	if (softs->comm_space_acc_handle) {
2789 		ddi_dma_mem_free(&softs->comm_space_acc_handle);
2790 		softs->comm_space_acc_handle = NULL;
2791 	}
2792 	if (softs->comm_space_dma_handle) {
2793 		ddi_dma_free_handle(&softs->comm_space_dma_handle);
2794 		softs->comm_space_dma_handle = NULL;
2795 	}
2796 	return (AACERR);
2797 }
2798 
2799 static void
2800 aac_free_comm_space(struct aac_softstate *softs)
2801 {
2802 	softs->sync_slot.fibp = NULL;
2803 	softs->sync_slot.fib_phyaddr = NULL;
2804 	softs->sync_slot.fib_acc_handle = NULL;
2805 	softs->sync_slot.fib_dma_handle = NULL;
2806 
2807 	(void) ddi_dma_unbind_handle(softs->comm_space_dma_handle);
2808 	ddi_dma_mem_free(&softs->comm_space_acc_handle);
2809 	softs->comm_space_acc_handle = NULL;
2810 	ddi_dma_free_handle(&softs->comm_space_dma_handle);
2811 	softs->comm_space_dma_handle = NULL;
2812 	softs->comm_space_phyaddr = NULL;
2813 }
2814 
2815 /*
2816  * Initialize the data structures that are required for the communication
2817  * interface to operate
2818  */
2819 static int
2820 aac_setup_comm_space(struct aac_softstate *softs)
2821 {
2822 	ddi_dma_handle_t dma = softs->comm_space_dma_handle;
2823 	ddi_acc_handle_t acc = softs->comm_space_acc_handle;
2824 	uint32_t comm_space_phyaddr;
2825 	struct aac_adapter_init *initp;
2826 	int qoffset;
2827 
2828 	comm_space_phyaddr = softs->comm_space_phyaddr;
2829 
2830 	/* Setup adapter init struct */
2831 	initp = &softs->comm_space->init_data;
2832 	bzero(initp, sizeof (struct aac_adapter_init));
2833 
2834 	ddi_put32(acc, &initp->InitStructRevision, AAC_INIT_STRUCT_REVISION);
2835 	ddi_put32(acc, &initp->HostElapsedSeconds, ddi_get_time());
2836 
2837 	/* Setup new/old comm. specific data */
2838 	if (softs->flags & AAC_FLAGS_RAW_IO) {
2839 		ddi_put32(acc, &initp->InitStructRevision,
2840 		    AAC_INIT_STRUCT_REVISION_4);
2841 		ddi_put32(acc, &initp->InitFlags,
2842 		    (softs->flags & AAC_FLAGS_NEW_COMM) ?
2843 		    AAC_INIT_FLAGS_NEW_COMM_SUPPORTED : 0);
2844 		/* Setup the preferred settings */
2845 		ddi_put32(acc, &initp->MaxIoCommands, softs->aac_max_fibs);
2846 		ddi_put32(acc, &initp->MaxIoSize,
2847 		    (softs->aac_max_sectors << 9));
2848 		ddi_put32(acc, &initp->MaxFibSize, softs->aac_max_fib_size);
2849 	} else {
2850 		/*
2851 		 * Tells the adapter about the physical location of various
2852 		 * important shared data structures
2853 		 */
2854 		ddi_put32(acc, &initp->AdapterFibsPhysicalAddress,
2855 		    comm_space_phyaddr + \
2856 		    offsetof(struct aac_comm_space, adapter_fibs));
2857 		ddi_put32(acc, &initp->AdapterFibsVirtualAddress, 0);
2858 		ddi_put32(acc, &initp->AdapterFibAlign, AAC_FIB_SIZE);
2859 		ddi_put32(acc, &initp->AdapterFibsSize,
2860 		    AAC_ADAPTER_FIBS * AAC_FIB_SIZE);
2861 		ddi_put32(acc, &initp->PrintfBufferAddress,
2862 		    comm_space_phyaddr + \
2863 		    offsetof(struct aac_comm_space, adapter_print_buf));
2864 		ddi_put32(acc, &initp->PrintfBufferSize,
2865 		    AAC_ADAPTER_PRINT_BUFSIZE);
2866 		ddi_put32(acc, &initp->MiniPortRevision,
2867 		    AAC_INIT_STRUCT_MINIPORT_REVISION);
2868 		ddi_put32(acc, &initp->HostPhysMemPages, AAC_MAX_PFN);
2869 
2870 		qoffset = (comm_space_phyaddr + \
2871 		    offsetof(struct aac_comm_space, qtable)) % \
2872 		    AAC_QUEUE_ALIGN;
2873 		if (qoffset)
2874 			qoffset = AAC_QUEUE_ALIGN - qoffset;
2875 		softs->qtablep = (struct aac_queue_table *) \
2876 		    ((char *)&softs->comm_space->qtable + qoffset);
2877 		ddi_put32(acc, &initp->CommHeaderAddress, comm_space_phyaddr + \
2878 		    offsetof(struct aac_comm_space, qtable) + qoffset);
2879 
2880 		/* Init queue table */
2881 		ddi_put32(acc, &softs->qtablep-> \
2882 		    qt_qindex[AAC_HOST_NORM_CMD_Q][AAC_PRODUCER_INDEX],
2883 		    AAC_HOST_NORM_CMD_ENTRIES);
2884 		ddi_put32(acc, &softs->qtablep-> \
2885 		    qt_qindex[AAC_HOST_NORM_CMD_Q][AAC_CONSUMER_INDEX],
2886 		    AAC_HOST_NORM_CMD_ENTRIES);
2887 		ddi_put32(acc, &softs->qtablep-> \
2888 		    qt_qindex[AAC_HOST_HIGH_CMD_Q][AAC_PRODUCER_INDEX],
2889 		    AAC_HOST_HIGH_CMD_ENTRIES);
2890 		ddi_put32(acc, &softs->qtablep-> \
2891 		    qt_qindex[AAC_HOST_HIGH_CMD_Q][AAC_CONSUMER_INDEX],
2892 		    AAC_HOST_HIGH_CMD_ENTRIES);
2893 		ddi_put32(acc, &softs->qtablep-> \
2894 		    qt_qindex[AAC_ADAP_NORM_CMD_Q][AAC_PRODUCER_INDEX],
2895 		    AAC_ADAP_NORM_CMD_ENTRIES);
2896 		ddi_put32(acc, &softs->qtablep-> \
2897 		    qt_qindex[AAC_ADAP_NORM_CMD_Q][AAC_CONSUMER_INDEX],
2898 		    AAC_ADAP_NORM_CMD_ENTRIES);
2899 		ddi_put32(acc, &softs->qtablep-> \
2900 		    qt_qindex[AAC_ADAP_HIGH_CMD_Q][AAC_PRODUCER_INDEX],
2901 		    AAC_ADAP_HIGH_CMD_ENTRIES);
2902 		ddi_put32(acc, &softs->qtablep-> \
2903 		    qt_qindex[AAC_ADAP_HIGH_CMD_Q][AAC_CONSUMER_INDEX],
2904 		    AAC_ADAP_HIGH_CMD_ENTRIES);
2905 		ddi_put32(acc, &softs->qtablep-> \
2906 		    qt_qindex[AAC_HOST_NORM_RESP_Q][AAC_PRODUCER_INDEX],
2907 		    AAC_HOST_NORM_RESP_ENTRIES);
2908 		ddi_put32(acc, &softs->qtablep-> \
2909 		    qt_qindex[AAC_HOST_NORM_RESP_Q][AAC_CONSUMER_INDEX],
2910 		    AAC_HOST_NORM_RESP_ENTRIES);
2911 		ddi_put32(acc, &softs->qtablep-> \
2912 		    qt_qindex[AAC_HOST_HIGH_RESP_Q][AAC_PRODUCER_INDEX],
2913 		    AAC_HOST_HIGH_RESP_ENTRIES);
2914 		ddi_put32(acc, &softs->qtablep-> \
2915 		    qt_qindex[AAC_HOST_HIGH_RESP_Q][AAC_CONSUMER_INDEX],
2916 		    AAC_HOST_HIGH_RESP_ENTRIES);
2917 		ddi_put32(acc, &softs->qtablep-> \
2918 		    qt_qindex[AAC_ADAP_NORM_RESP_Q][AAC_PRODUCER_INDEX],
2919 		    AAC_ADAP_NORM_RESP_ENTRIES);
2920 		ddi_put32(acc, &softs->qtablep-> \
2921 		    qt_qindex[AAC_ADAP_NORM_RESP_Q][AAC_CONSUMER_INDEX],
2922 		    AAC_ADAP_NORM_RESP_ENTRIES);
2923 		ddi_put32(acc, &softs->qtablep-> \
2924 		    qt_qindex[AAC_ADAP_HIGH_RESP_Q][AAC_PRODUCER_INDEX],
2925 		    AAC_ADAP_HIGH_RESP_ENTRIES);
2926 		ddi_put32(acc, &softs->qtablep-> \
2927 		    qt_qindex[AAC_ADAP_HIGH_RESP_Q][AAC_CONSUMER_INDEX],
2928 		    AAC_ADAP_HIGH_RESP_ENTRIES);
2929 
2930 		/* Init queue entries */
2931 		softs->qentries[AAC_HOST_NORM_CMD_Q] =
2932 		    &softs->qtablep->qt_HostNormCmdQueue[0];
2933 		softs->qentries[AAC_HOST_HIGH_CMD_Q] =
2934 		    &softs->qtablep->qt_HostHighCmdQueue[0];
2935 		softs->qentries[AAC_ADAP_NORM_CMD_Q] =
2936 		    &softs->qtablep->qt_AdapNormCmdQueue[0];
2937 		softs->qentries[AAC_ADAP_HIGH_CMD_Q] =
2938 		    &softs->qtablep->qt_AdapHighCmdQueue[0];
2939 		softs->qentries[AAC_HOST_NORM_RESP_Q] =
2940 		    &softs->qtablep->qt_HostNormRespQueue[0];
2941 		softs->qentries[AAC_HOST_HIGH_RESP_Q] =
2942 		    &softs->qtablep->qt_HostHighRespQueue[0];
2943 		softs->qentries[AAC_ADAP_NORM_RESP_Q] =
2944 		    &softs->qtablep->qt_AdapNormRespQueue[0];
2945 		softs->qentries[AAC_ADAP_HIGH_RESP_Q] =
2946 		    &softs->qtablep->qt_AdapHighRespQueue[0];
2947 	}
2948 	(void) ddi_dma_sync(dma, 0, 0, DDI_DMA_SYNC_FORDEV);
2949 
2950 	/* Send init structure to the card */
2951 	if (aac_sync_mbcommand(softs, AAC_MONKER_INITSTRUCT,
2952 	    comm_space_phyaddr + \
2953 	    offsetof(struct aac_comm_space, init_data),
2954 	    0, 0, 0, NULL) == AACERR) {
2955 		AACDB_PRINT(softs, CE_WARN,
2956 		    "Cannot send init structure to adapter");
2957 		return (AACERR);
2958 	}
2959 
2960 	return (AACOK);
2961 }
2962 
2963 static uchar_t *
2964 aac_vendor_id(struct aac_softstate *softs, uchar_t *buf)
2965 {
2966 	(void) memset(buf, ' ', AAC_VENDOR_LEN);
2967 	bcopy(softs->vendor_name, buf, strlen(softs->vendor_name));
2968 	return (buf + AAC_VENDOR_LEN);
2969 }
2970 
2971 static uchar_t *
2972 aac_product_id(struct aac_softstate *softs, uchar_t *buf)
2973 {
2974 	(void) memset(buf, ' ', AAC_PRODUCT_LEN);
2975 	bcopy(softs->product_name, buf, strlen(softs->product_name));
2976 	return (buf + AAC_PRODUCT_LEN);
2977 }
2978 
2979 /*
2980  * Construct unit serial number from container uid
2981  */
2982 static uchar_t *
2983 aac_lun_serialno(struct aac_softstate *softs, int tgt, uchar_t *buf)
2984 {
2985 	int i, d;
2986 	uint32_t uid = softs->containers[tgt].uid;
2987 
2988 	for (i = 7; i >= 0; i--) {
2989 		d = uid & 0xf;
2990 		buf[i] = d > 9 ? 'A' + (d - 0xa) : '0' + d;
2991 		uid >>= 4;
2992 	}
2993 	return (buf + 8);
2994 }
2995 
2996 /*
2997  * SPC-3 7.5 INQUIRY command implementation
2998  */
2999 static void
3000 aac_inquiry(struct aac_softstate *softs, struct scsi_pkt *pkt,
3001     union scsi_cdb *cdbp, struct buf *bp)
3002 {
3003 	int tgt = pkt->pkt_address.a_target;
3004 	char *b_addr = NULL;
3005 	uchar_t page = cdbp->cdb_opaque[2];
3006 
3007 	if (cdbp->cdb_opaque[1] & AAC_CDB_INQUIRY_CMDDT) {
3008 		/* Command Support Data is not supported */
3009 		aac_set_arq_data(pkt, KEY_ILLEGAL_REQUEST, 0x24, 0x00, 0);
3010 		return;
3011 	}
3012 
3013 	if (bp && bp->b_un.b_addr && bp->b_bcount) {
3014 		if (bp->b_flags & (B_PHYS | B_PAGEIO))
3015 			bp_mapin(bp);
3016 		b_addr = bp->b_un.b_addr;
3017 	}
3018 
3019 	if (cdbp->cdb_opaque[1] & AAC_CDB_INQUIRY_EVPD) {
3020 		uchar_t *vpdp = (uchar_t *)b_addr;
3021 		uchar_t *idp, *sp;
3022 
3023 		/* SPC-3 8.4 Vital product data parameters */
3024 		switch (page) {
3025 		case 0x00:
3026 			/* Supported VPD pages */
3027 			if (vpdp == NULL ||
3028 			    bp->b_bcount < (AAC_VPD_PAGE_DATA + 3))
3029 				return;
3030 			bzero(vpdp, AAC_VPD_PAGE_LENGTH);
3031 			vpdp[AAC_VPD_PAGE_CODE] = 0x00;
3032 			vpdp[AAC_VPD_PAGE_LENGTH] = 3;
3033 
3034 			vpdp[AAC_VPD_PAGE_DATA] = 0x00;
3035 			vpdp[AAC_VPD_PAGE_DATA + 1] = 0x80;
3036 			vpdp[AAC_VPD_PAGE_DATA + 2] = 0x83;
3037 
3038 			pkt->pkt_state |= STATE_XFERRED_DATA;
3039 			break;
3040 
3041 		case 0x80:
3042 			/* Unit serial number page */
3043 			if (vpdp == NULL ||
3044 			    bp->b_bcount < (AAC_VPD_PAGE_DATA + 8))
3045 				return;
3046 			bzero(vpdp, AAC_VPD_PAGE_LENGTH);
3047 			vpdp[AAC_VPD_PAGE_CODE] = 0x80;
3048 			vpdp[AAC_VPD_PAGE_LENGTH] = 8;
3049 
3050 			sp = &vpdp[AAC_VPD_PAGE_DATA];
3051 			(void) aac_lun_serialno(softs, tgt, sp);
3052 
3053 			pkt->pkt_state |= STATE_XFERRED_DATA;
3054 			break;
3055 
3056 		case 0x83:
3057 			/* Device identification page */
3058 			if (vpdp == NULL ||
3059 			    bp->b_bcount < (AAC_VPD_PAGE_DATA + 32))
3060 				return;
3061 			bzero(vpdp, AAC_VPD_PAGE_LENGTH);
3062 			vpdp[AAC_VPD_PAGE_CODE] = 0x83;
3063 
3064 			idp = &vpdp[AAC_VPD_PAGE_DATA];
3065 			bzero(idp, AAC_VPD_ID_LENGTH);
3066 			idp[AAC_VPD_ID_CODESET] = 0x02;
3067 			idp[AAC_VPD_ID_TYPE] = 0x01;
3068 
3069 			/*
3070 			 * SPC-3 Table 111 - Identifier type
3071 			 * One recommanded method of constructing the remainder
3072 			 * of identifier field is to concatenate the product
3073 			 * identification field from the standard INQUIRY data
3074 			 * field and the product serial number field from the
3075 			 * unit serial number page.
3076 			 */
3077 			sp = &idp[AAC_VPD_ID_DATA];
3078 			sp = aac_vendor_id(softs, sp);
3079 			sp = aac_product_id(softs, sp);
3080 			sp = aac_lun_serialno(softs, tgt, sp);
3081 			idp[AAC_VPD_ID_LENGTH] = sp - &idp[AAC_VPD_ID_DATA];
3082 
3083 			vpdp[AAC_VPD_PAGE_LENGTH] =
3084 			    sp - &vpdp[AAC_VPD_PAGE_DATA];
3085 			pkt->pkt_state |= STATE_XFERRED_DATA;
3086 			break;
3087 
3088 		default:
3089 			aac_set_arq_data(pkt, KEY_ILLEGAL_REQUEST,
3090 			    0x24, 0x00, 0);
3091 			break;
3092 		}
3093 	} else {
3094 		struct scsi_inquiry *inqp = (struct scsi_inquiry *)b_addr;
3095 		size_t len = sizeof (struct scsi_inquiry);
3096 
3097 		if (page != 0) {
3098 			aac_set_arq_data(pkt, KEY_ILLEGAL_REQUEST,
3099 			    0x24, 0x00, 0);
3100 			return;
3101 		}
3102 		if (inqp == NULL || bp->b_bcount < len)
3103 			return;
3104 
3105 		bzero(inqp, len);
3106 		inqp->inq_len = AAC_ADDITIONAL_LEN;
3107 		inqp->inq_ansi = AAC_ANSI_VER;
3108 		inqp->inq_rdf = AAC_RESP_DATA_FORMAT;
3109 		(void) aac_vendor_id(softs, (uchar_t *)inqp->inq_vid);
3110 		(void) aac_product_id(softs, (uchar_t *)inqp->inq_pid);
3111 		bcopy("V1.0", inqp->inq_revision, 4);
3112 		inqp->inq_cmdque = 1; /* enable tagged-queuing */
3113 		/*
3114 		 * For "sd-max-xfer-size" property which may impact performance
3115 		 * when IO threads increase.
3116 		 */
3117 		inqp->inq_wbus32 = 1;
3118 
3119 		pkt->pkt_state |= STATE_XFERRED_DATA;
3120 	}
3121 }
3122 
3123 /*
3124  * SPC-3 7.10 MODE SENSE command implementation
3125  */
3126 static void
3127 aac_mode_sense(struct aac_softstate *softs, struct scsi_pkt *pkt,
3128     union scsi_cdb *cdbp, struct buf *bp, int capacity)
3129 {
3130 	uchar_t pagecode;
3131 	struct mode_header *headerp;
3132 	struct mode_header_g1 *g1_headerp;
3133 	unsigned int ncyl;
3134 	caddr_t sense_data;
3135 	caddr_t next_page;
3136 	size_t sdata_size;
3137 	size_t pages_size;
3138 	int unsupport_page = 0;
3139 
3140 	ASSERT(cdbp->scc_cmd == SCMD_MODE_SENSE ||
3141 	    cdbp->scc_cmd == SCMD_MODE_SENSE_G1);
3142 
3143 	if (!(bp && bp->b_un.b_addr && bp->b_bcount))
3144 		return;
3145 
3146 	if (bp->b_flags & (B_PHYS | B_PAGEIO))
3147 		bp_mapin(bp);
3148 	pkt->pkt_state |= STATE_XFERRED_DATA;
3149 	pagecode = cdbp->cdb_un.sg.scsi[0] & 0x3F;
3150 
3151 	/* calculate the size of needed buffer */
3152 	if (cdbp->scc_cmd == SCMD_MODE_SENSE)
3153 		sdata_size = MODE_HEADER_LENGTH;
3154 	else /* must be SCMD_MODE_SENSE_G1 */
3155 		sdata_size = MODE_HEADER_LENGTH_G1;
3156 
3157 	pages_size = 0;
3158 	switch (pagecode) {
3159 	case SD_MODE_SENSE_PAGE3_CODE:
3160 		pages_size += sizeof (struct mode_format);
3161 		break;
3162 
3163 	case SD_MODE_SENSE_PAGE4_CODE:
3164 		pages_size += sizeof (struct mode_geometry);
3165 		break;
3166 
3167 	case MODEPAGE_CTRL_MODE:
3168 		if (softs->flags & AAC_FLAGS_LBA_64BIT) {
3169 			pages_size += sizeof (struct mode_control_scsi3);
3170 		} else {
3171 			unsupport_page = 1;
3172 		}
3173 		break;
3174 
3175 	case MODEPAGE_ALLPAGES:
3176 		if (softs->flags & AAC_FLAGS_LBA_64BIT) {
3177 			pages_size += sizeof (struct mode_format) +
3178 			    sizeof (struct mode_geometry) +
3179 			    sizeof (struct mode_control_scsi3);
3180 		} else {
3181 			pages_size += sizeof (struct mode_format) +
3182 			    sizeof (struct mode_geometry);
3183 		}
3184 		break;
3185 
3186 	default:
3187 		/* unsupported pages */
3188 		unsupport_page = 1;
3189 	}
3190 
3191 	/* allocate buffer to fill the send data */
3192 	sdata_size += pages_size;
3193 	sense_data = kmem_zalloc(sdata_size, KM_SLEEP);
3194 
3195 	if (cdbp->scc_cmd == SCMD_MODE_SENSE) {
3196 		headerp = (struct mode_header *)sense_data;
3197 		headerp->length = MODE_HEADER_LENGTH + pages_size -
3198 		    sizeof (headerp->length);
3199 		headerp->bdesc_length = 0;
3200 		next_page = sense_data + sizeof (struct mode_header);
3201 	} else {
3202 		g1_headerp = (struct mode_header_g1 *)sense_data;
3203 		headerp->length = BE_16(MODE_HEADER_LENGTH_G1 + pages_size -
3204 		    sizeof (headerp->length));
3205 		g1_headerp->bdesc_length = 0;
3206 		next_page = sense_data + sizeof (struct mode_header_g1);
3207 	}
3208 
3209 	if (unsupport_page)
3210 		goto finish;
3211 
3212 	if (pagecode == SD_MODE_SENSE_PAGE3_CODE ||
3213 	    pagecode == MODEPAGE_ALLPAGES) {
3214 		/* SBC-3 7.1.3.3 Format device page */
3215 		struct mode_format *page3p;
3216 
3217 		page3p = (struct mode_format *)next_page;
3218 		page3p->mode_page.code = SD_MODE_SENSE_PAGE3_CODE;
3219 		page3p->mode_page.length = sizeof (struct mode_format);
3220 		page3p->data_bytes_sect = BE_16(AAC_SECTOR_SIZE);
3221 		page3p->sect_track = BE_16(AAC_SECTORS_PER_TRACK);
3222 
3223 		next_page += sizeof (struct mode_format);
3224 	}
3225 
3226 	if (pagecode == SD_MODE_SENSE_PAGE4_CODE ||
3227 	    pagecode == MODEPAGE_ALLPAGES) {
3228 		/* SBC-3 7.1.3.8 Rigid disk device geometry page */
3229 		struct mode_geometry *page4p;
3230 
3231 		page4p = (struct mode_geometry *)next_page;
3232 		page4p->mode_page.code = SD_MODE_SENSE_PAGE4_CODE;
3233 		page4p->mode_page.length = sizeof (struct mode_geometry);
3234 		page4p->heads = AAC_NUMBER_OF_HEADS;
3235 		page4p->rpm = BE_16(AAC_ROTATION_SPEED);
3236 		ncyl = capacity / (AAC_NUMBER_OF_HEADS * AAC_SECTORS_PER_TRACK);
3237 		page4p->cyl_lb = ncyl & 0xff;
3238 		page4p->cyl_mb = (ncyl >> 8) & 0xff;
3239 		page4p->cyl_ub = (ncyl >> 16) & 0xff;
3240 
3241 		next_page += sizeof (struct mode_geometry);
3242 	}
3243 
3244 	if ((pagecode == MODEPAGE_CTRL_MODE || pagecode == MODEPAGE_ALLPAGES) &&
3245 	    softs->flags & AAC_FLAGS_LBA_64BIT) {
3246 		/* 64-bit LBA need large sense data */
3247 		struct mode_control_scsi3 *mctl;
3248 
3249 		mctl = (struct mode_control_scsi3 *)next_page;
3250 		mctl->mode_page.code = MODEPAGE_CTRL_MODE;
3251 		mctl->mode_page.length =
3252 		    sizeof (struct mode_control_scsi3) -
3253 		    sizeof (struct mode_page);
3254 		mctl->d_sense = 1;
3255 	}
3256 
3257 finish:
3258 	/* copyout the valid data. */
3259 	bcopy(sense_data, bp->b_un.b_addr, min(sdata_size, bp->b_bcount));
3260 	kmem_free(sense_data, sdata_size);
3261 }
3262 
3263 /*ARGSUSED*/
3264 static int
3265 aac_tran_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
3266     scsi_hba_tran_t *tran, struct scsi_device *sd)
3267 {
3268 	struct aac_softstate *softs = AAC_TRAN2SOFTS(tran);
3269 #if defined(DEBUG) || defined(__lock_lint)
3270 	int ctl = ddi_get_instance(softs->devinfo_p);
3271 #endif
3272 	int tgt = sd->sd_address.a_target;
3273 	int lun = sd->sd_address.a_lun;
3274 	struct aac_container *dvp;
3275 
3276 	DBCALLED(softs, 2);
3277 
3278 	if ((0 > tgt) || (tgt >= AAC_MAX_LD)) {
3279 		AACDB_PRINT(softs, CE_NOTE,
3280 		    "aac_tran_tgt_init: c%t%dL%d out", ctl, tgt, lun);
3281 		return (DDI_FAILURE);
3282 	}
3283 
3284 	/*
3285 	 * Only support container that has been detected and valid
3286 	 */
3287 	mutex_enter(&softs->io_lock);
3288 	dvp = &softs->containers[tgt];
3289 	if (dvp->valid && lun == 0) {
3290 		AACDB_PRINT_TRAN(softs, "aac_tran_tgt_init: c%t%dL%d ok",
3291 		    ctl, tgt, lun);
3292 		mutex_exit(&softs->io_lock);
3293 		return (DDI_SUCCESS);
3294 	} else {
3295 		AACDB_PRINT_TRAN(softs, "aac_tran_tgt_init: c%t%dL%d",
3296 		    ctl, tgt, lun);
3297 		mutex_exit(&softs->io_lock);
3298 		return (DDI_FAILURE);
3299 	}
3300 }
3301 
3302 /*
3303  * Check if the firmware is Up And Running. If it is in the Kernel Panic
3304  * state, (BlinkLED code + 1) is returned.
3305  *    0 -- firmware up and running
3306  *   -1 -- firmware dead
3307  *   >0 -- firmware kernel panic
3308  */
3309 static int
3310 aac_check_adapter_health(struct aac_softstate *softs)
3311 {
3312 	int rval;
3313 
3314 	rval = PCI_MEM_GET32(softs, AAC_OMR0);
3315 
3316 	if (rval & AAC_KERNEL_UP_AND_RUNNING) {
3317 		rval = 0;
3318 	} else if (rval & AAC_KERNEL_PANIC) {
3319 		cmn_err(CE_WARN, "firmware panic");
3320 		rval = ((rval >> 16) & 0xff) + 1; /* avoid 0 as return value */
3321 	} else {
3322 		cmn_err(CE_WARN, "firmware dead");
3323 		rval = -1;
3324 	}
3325 	return (rval);
3326 }
3327 
3328 static void
3329 aac_abort_iocmd(struct aac_softstate *softs, struct aac_cmd *acp,
3330     uchar_t reason)
3331 {
3332 	acp->flags |= AAC_CMD_ABORT;
3333 
3334 	if (acp->pkt) {
3335 		/*
3336 		 * Each lun should generate a unit attention
3337 		 * condition when reset.
3338 		 * Phys. drives are treated as logical ones
3339 		 * during error recovery.
3340 		 */
3341 		if (softs->flags & AAC_STATE_RESET)
3342 			aac_set_arq_data_reset(softs, acp);
3343 
3344 		switch (reason) {
3345 		case CMD_TIMEOUT:
3346 			aac_set_pkt_reason(softs, acp, CMD_TIMEOUT,
3347 			    STAT_TIMEOUT | STAT_BUS_RESET);
3348 			break;
3349 		case CMD_RESET:
3350 			/* aac support only RESET_ALL */
3351 			aac_set_pkt_reason(softs, acp, CMD_RESET,
3352 			    STAT_BUS_RESET);
3353 			break;
3354 		case CMD_ABORTED:
3355 			aac_set_pkt_reason(softs, acp, CMD_ABORTED,
3356 			    STAT_ABORTED);
3357 			break;
3358 		}
3359 	}
3360 	aac_end_io(softs, acp);
3361 }
3362 
3363 /*
3364  * Abort all the pending commands of type iocmd or just the command pkt
3365  * corresponding to pkt
3366  */
3367 static void
3368 aac_abort_iocmds(struct aac_softstate *softs, int iocmd, struct scsi_pkt *pkt,
3369     int reason)
3370 {
3371 	struct aac_cmd *ac_arg, *acp;
3372 	int i;
3373 
3374 	if (pkt == NULL) {
3375 		ac_arg = NULL;
3376 	} else {
3377 		ac_arg = PKT2AC(pkt);
3378 		iocmd = (ac_arg->flags & AAC_CMD_SYNC) ?
3379 		    AAC_IOCMD_SYNC : AAC_IOCMD_ASYNC;
3380 	}
3381 
3382 	/*
3383 	 * a) outstanding commands on the controller
3384 	 * Note: should abort outstanding commands only after one
3385 	 * IOP reset has been done.
3386 	 */
3387 	if (iocmd & AAC_IOCMD_OUTSTANDING) {
3388 		struct aac_cmd *acp;
3389 
3390 		for (i = 0; i < AAC_MAX_LD; i++) {
3391 			if (softs->containers[i].valid)
3392 				softs->containers[i].reset = 1;
3393 		}
3394 		while ((acp = softs->q_busy.q_head) != NULL)
3395 			aac_abort_iocmd(softs, acp, reason);
3396 	}
3397 
3398 	/* b) commands in the waiting queues */
3399 	for (i = 0; i < AAC_CMDQ_NUM; i++) {
3400 		if (iocmd & (1 << i)) {
3401 			if (ac_arg) {
3402 				aac_abort_iocmd(softs, ac_arg, reason);
3403 			} else {
3404 				while ((acp = softs->q_wait[i].q_head) != NULL)
3405 					aac_abort_iocmd(softs, acp, reason);
3406 			}
3407 		}
3408 	}
3409 }
3410 
3411 /*
3412  * The draining thread is shared among quiesce threads. It terminates
3413  * when the adapter is quiesced or stopped by aac_stop_drain().
3414  */
3415 static void
3416 aac_check_drain(void *arg)
3417 {
3418 	struct aac_softstate *softs = arg;
3419 
3420 	mutex_enter(&softs->io_lock);
3421 	if (softs->ndrains) {
3422 		/*
3423 		 * If both ASYNC and SYNC bus throttle are held,
3424 		 * wake up threads only when both are drained out.
3425 		 */
3426 		if ((softs->bus_throttle[AAC_CMDQ_ASYNC] > 0 ||
3427 		    softs->bus_ncmds[AAC_CMDQ_ASYNC] == 0) &&
3428 		    (softs->bus_throttle[AAC_CMDQ_SYNC] > 0 ||
3429 		    softs->bus_ncmds[AAC_CMDQ_SYNC] == 0))
3430 			cv_broadcast(&softs->drain_cv);
3431 		else
3432 			softs->drain_timeid = timeout(aac_check_drain, softs,
3433 			    AAC_QUIESCE_TICK * drv_usectohz(1000000));
3434 	}
3435 	mutex_exit(&softs->io_lock);
3436 }
3437 
3438 /*
3439  * If not draining the outstanding cmds, drain them. Otherwise,
3440  * only update ndrains.
3441  */
3442 static void
3443 aac_start_drain(struct aac_softstate *softs)
3444 {
3445 	if (softs->ndrains == 0) {
3446 		softs->drain_timeid = timeout(aac_check_drain, softs,
3447 		    AAC_QUIESCE_TICK * drv_usectohz(1000000));
3448 	}
3449 	softs->ndrains++;
3450 }
3451 
3452 /*
3453  * Stop the draining thread when no other threads use it any longer.
3454  * Side effect: io_lock may be released in the middle.
3455  */
3456 static void
3457 aac_stop_drain(struct aac_softstate *softs)
3458 {
3459 	softs->ndrains--;
3460 	if (softs->ndrains == 0) {
3461 		if (softs->drain_timeid != 0) {
3462 			timeout_id_t tid = softs->drain_timeid;
3463 
3464 			softs->drain_timeid = 0;
3465 			mutex_exit(&softs->io_lock);
3466 			(void) untimeout(tid);
3467 			mutex_enter(&softs->io_lock);
3468 		}
3469 	}
3470 }
3471 
3472 /*
3473  * The following function comes from Adaptec:
3474  *
3475  * Once do an IOP reset, basically the driver have to re-initialize the card
3476  * as if up from a cold boot, and the driver is responsible for any IO that
3477  * is outstanding to the adapter at the time of the IOP RESET. And prepare
3478  * for IOP RESET by making the init code modular with the ability to call it
3479  * from multiple places.
3480  */
3481 static int
3482 aac_reset_adapter(struct aac_softstate *softs)
3483 {
3484 	int health;
3485 	uint32_t status;
3486 	int rval = AACERR;
3487 
3488 	DBCALLED(softs, 1);
3489 
3490 	ASSERT(softs->state & AAC_STATE_RESET);
3491 
3492 	ddi_fm_acc_err_clear(softs->pci_mem_handle, DDI_FME_VER0);
3493 	/* Disable interrupt */
3494 	AAC_DISABLE_INTR(softs);
3495 
3496 	health = aac_check_adapter_health(softs);
3497 	if (health == -1) {
3498 		ddi_fm_service_impact(softs->devinfo_p, DDI_SERVICE_LOST);
3499 		goto finish;
3500 	}
3501 	if (health == 0) /* flush drives if possible */
3502 		(void) aac_shutdown(softs);
3503 
3504 	/* Execute IOP reset */
3505 	if ((aac_sync_mbcommand(softs, AAC_IOP_RESET, 0, 0, 0, 0,
3506 	    &status)) != AACOK) {
3507 		ddi_acc_handle_t acc = softs->comm_space_acc_handle;
3508 		struct aac_fib *fibp;
3509 		struct aac_pause_command *pc;
3510 
3511 		if ((status & 0xf) == 0xf) {
3512 			uint32_t wait_count;
3513 
3514 			/*
3515 			 * Sunrise Lake has dual cores and we must drag the
3516 			 * other core with us to reset simultaneously. There
3517 			 * are 2 bits in the Inbound Reset Control and Status
3518 			 * Register (offset 0x38) of the Sunrise Lake to reset
3519 			 * the chip without clearing out the PCI configuration
3520 			 * info (COMMAND & BARS).
3521 			 */
3522 			PCI_MEM_PUT32(softs, AAC_IRCSR, AAC_IRCSR_CORES_RST);
3523 
3524 			/*
3525 			 * We need to wait for 5 seconds before accessing the MU
3526 			 * again 10000 * 100us = 1000,000us = 1000ms = 1s
3527 			 */
3528 			wait_count = 5 * 10000;
3529 			while (wait_count) {
3530 				drv_usecwait(100); /* delay 100 microseconds */
3531 				wait_count--;
3532 			}
3533 		} else {
3534 			if (status == SRB_STATUS_INVALID_REQUEST)
3535 				cmn_err(CE_WARN, "!IOP_RESET not supported");
3536 			else /* probably timeout */
3537 				cmn_err(CE_WARN, "!IOP_RESET failed");
3538 
3539 			/* Unwind aac_shutdown() */
3540 			fibp = softs->sync_slot.fibp;
3541 			pc = (struct aac_pause_command *)&fibp->data[0];
3542 
3543 			bzero(pc, sizeof (*pc));
3544 			ddi_put32(acc, &pc->Command, VM_ContainerConfig);
3545 			ddi_put32(acc, &pc->Type, CT_PAUSE_IO);
3546 			ddi_put32(acc, &pc->Timeout, 1);
3547 			ddi_put32(acc, &pc->Min, 1);
3548 			ddi_put32(acc, &pc->NoRescan, 1);
3549 
3550 			(void) aac_sync_fib(softs, ContainerCommand,
3551 			    AAC_FIB_SIZEOF(struct aac_pause_command));
3552 
3553 			ddi_fm_service_impact(softs->devinfo_p,
3554 			    DDI_SERVICE_LOST);
3555 			goto finish;
3556 		}
3557 	}
3558 
3559 	/*
3560 	 * Re-read and renegotiate the FIB parameters, as one of the actions
3561 	 * that can result from an IOP reset is the running of a new firmware
3562 	 * image.
3563 	 */
3564 	if (aac_common_attach(softs) != AACOK)
3565 		goto finish;
3566 
3567 	rval = AACOK;
3568 
3569 finish:
3570 	AAC_ENABLE_INTR(softs);
3571 	return (rval);
3572 }
3573 
3574 static void
3575 aac_set_throttle(struct aac_softstate *softs, struct aac_container *dvp, int q,
3576     int throttle)
3577 {
3578 	/*
3579 	 * If the bus is draining/quiesced, no changes to the throttles
3580 	 * are allowed. All throttles should have been set to 0.
3581 	 */
3582 	if ((softs->state & AAC_STATE_QUIESCED) || softs->ndrains)
3583 		return;
3584 	dvp->throttle[q] = throttle;
3585 }
3586 
3587 static void
3588 aac_hold_bus(struct aac_softstate *softs, int iocmds)
3589 {
3590 	int i, q;
3591 
3592 	/* Hold bus by holding every device on the bus */
3593 	for (q = 0; q < AAC_CMDQ_NUM; q++) {
3594 		if (iocmds & (1 << q)) {
3595 			softs->bus_throttle[q] = 0;
3596 			for (i = 0; i < AAC_MAX_LD; i++)
3597 				aac_set_throttle(softs, &softs->containers[i],
3598 				    q, 0);
3599 		}
3600 	}
3601 }
3602 
3603 static void
3604 aac_unhold_bus(struct aac_softstate *softs, int iocmds)
3605 {
3606 	int i, q;
3607 
3608 	for (q = 0; q < AAC_CMDQ_NUM; q++) {
3609 		if (iocmds & (1 << q)) {
3610 			/*
3611 			 * Should not unhold AAC_IOCMD_ASYNC bus, if it has been
3612 			 * quiesced or being drained by possibly some quiesce
3613 			 * threads.
3614 			 */
3615 			if (q == AAC_CMDQ_ASYNC && ((softs->state &
3616 			    AAC_STATE_QUIESCED) || softs->ndrains))
3617 				continue;
3618 			softs->bus_throttle[q] = softs->total_slots;
3619 			for (i = 0; i < AAC_MAX_LD; i++)
3620 				aac_set_throttle(softs, &softs->containers[i],
3621 				    q, softs->total_slots);
3622 		}
3623 	}
3624 }
3625 
3626 static int
3627 aac_do_reset(struct aac_softstate *softs)
3628 {
3629 	int health;
3630 	int rval;
3631 
3632 	softs->state |= AAC_STATE_RESET;
3633 	health = aac_check_adapter_health(softs);
3634 
3635 	/*
3636 	 * Hold off new io commands and wait all outstanding io
3637 	 * commands to complete.
3638 	 */
3639 	if (health == 0 && (softs->bus_ncmds[AAC_CMDQ_SYNC] ||
3640 	    softs->bus_ncmds[AAC_CMDQ_ASYNC])) {
3641 		/*
3642 		 * Give the adapter up to AAC_QUIESCE_TIMEOUT more seconds
3643 		 * to complete the outstanding io commands
3644 		 */
3645 		int timeout = AAC_QUIESCE_TIMEOUT * 1000 * 10;
3646 		int (*intr_handler)(struct aac_softstate *);
3647 
3648 		aac_hold_bus(softs, AAC_IOCMD_SYNC | AAC_IOCMD_ASYNC);
3649 		/*
3650 		 * Poll the adapter by ourselves in case interrupt is disabled
3651 		 * and to avoid releasing the io_lock.
3652 		 */
3653 		intr_handler = (softs->flags & AAC_FLAGS_NEW_COMM) ?
3654 		    aac_process_intr_new : aac_process_intr_old;
3655 		while ((softs->bus_ncmds[AAC_CMDQ_SYNC] ||
3656 		    softs->bus_ncmds[AAC_CMDQ_ASYNC]) && timeout) {
3657 			drv_usecwait(100);
3658 			(void) intr_handler(softs);
3659 			timeout--;
3660 		}
3661 		aac_unhold_bus(softs, AAC_IOCMD_SYNC | AAC_IOCMD_ASYNC);
3662 	}
3663 
3664 	/*
3665 	 * If a longer waiting time still can't drain all outstanding io
3666 	 * commands, do IOP reset.
3667 	 */
3668 	if (softs->bus_ncmds[AAC_CMDQ_SYNC] ||
3669 	    softs->bus_ncmds[AAC_CMDQ_ASYNC]) {
3670 		if ((rval = aac_reset_adapter(softs)) != AACOK)
3671 			softs->state |= AAC_STATE_DEAD;
3672 	} else {
3673 		rval = AACOK;
3674 	}
3675 
3676 	softs->state &= ~AAC_STATE_RESET;
3677 	return (rval);
3678 }
3679 
3680 static int
3681 aac_tran_reset(struct scsi_address *ap, int level)
3682 {
3683 	struct aac_softstate *softs = AAC_TRAN2SOFTS(ap->a_hba_tran);
3684 	int rval;
3685 
3686 	DBCALLED(softs, 1);
3687 
3688 	if (level != RESET_ALL) {
3689 		cmn_err(CE_NOTE, "!reset target/lun not supported");
3690 		return (0);
3691 	}
3692 
3693 	mutex_enter(&softs->io_lock);
3694 	rval = (aac_do_reset(softs) == AACOK) ? 1 : 0;
3695 	if (rval == 1 && !ddi_in_panic()) {
3696 		aac_abort_iocmds(softs, AAC_IOCMD_OUTSTANDING | AAC_IOCMD_ASYNC,
3697 		    NULL, CMD_RESET);
3698 		aac_start_waiting_io(softs);
3699 	} else {
3700 		/* Abort IOCTL cmds when system panic or adapter dead */
3701 		aac_abort_iocmds(softs, AAC_IOCMD_ALL, NULL, CMD_RESET);
3702 	}
3703 	mutex_exit(&softs->io_lock);
3704 
3705 	aac_drain_comp_q(softs);
3706 	return (rval);
3707 }
3708 
3709 static int
3710 aac_tran_abort(struct scsi_address *ap, struct scsi_pkt *pkt)
3711 {
3712 	struct aac_softstate *softs = AAC_TRAN2SOFTS(ap->a_hba_tran);
3713 
3714 	DBCALLED(softs, 1);
3715 
3716 	mutex_enter(&softs->io_lock);
3717 	aac_abort_iocmds(softs, 0, pkt, CMD_ABORTED);
3718 	mutex_exit(&softs->io_lock);
3719 
3720 	aac_drain_comp_q(softs);
3721 	return (1);
3722 }
3723 
3724 void
3725 aac_free_dmamap(struct aac_cmd *acp)
3726 {
3727 	/* Free dma mapping */
3728 	if (acp->flags & AAC_CMD_DMA_VALID) {
3729 		ASSERT(acp->buf_dma_handle);
3730 		(void) ddi_dma_unbind_handle(acp->buf_dma_handle);
3731 		acp->flags &= ~AAC_CMD_DMA_VALID;
3732 	}
3733 
3734 	if (acp->abp != NULL) { /* free non-aligned buf DMA */
3735 		ASSERT(acp->buf_dma_handle);
3736 		if ((acp->flags & AAC_CMD_BUF_WRITE) == 0 && acp->bp)
3737 			ddi_rep_get8(acp->abh, (uint8_t *)acp->bp->b_un.b_addr,
3738 			    (uint8_t *)acp->abp, acp->bp->b_bcount,
3739 			    DDI_DEV_AUTOINCR);
3740 		ddi_dma_mem_free(&acp->abh);
3741 		acp->abp = NULL;
3742 	}
3743 
3744 	if (acp->buf_dma_handle) {
3745 		ddi_dma_free_handle(&acp->buf_dma_handle);
3746 		acp->buf_dma_handle = NULL;
3747 	}
3748 }
3749 
3750 static void
3751 aac_unknown_scmd(struct aac_softstate *softs, struct aac_cmd *acp)
3752 {
3753 	AACDB_PRINT(softs, CE_CONT, "SCMD 0x%x not supported",
3754 	    ((union scsi_cdb *)acp->pkt->pkt_cdbp)->scc_cmd);
3755 	aac_free_dmamap(acp);
3756 	aac_set_arq_data(acp->pkt, KEY_ILLEGAL_REQUEST, 0x20, 0x00, 0);
3757 	aac_soft_callback(softs, acp);
3758 }
3759 
3760 /*
3761  * Handle command to logical device
3762  */
3763 static int
3764 aac_tran_start_ld(struct aac_softstate *softs, struct aac_cmd *acp)
3765 {
3766 	struct aac_container *dvp;
3767 	struct scsi_pkt *pkt;
3768 	union scsi_cdb *cdbp;
3769 	struct buf *bp;
3770 	int rval;
3771 
3772 	dvp = acp->dvp;
3773 	pkt = acp->pkt;
3774 	cdbp = (union scsi_cdb *)pkt->pkt_cdbp;
3775 	bp = acp->bp;
3776 
3777 	switch (cdbp->scc_cmd) {
3778 	case SCMD_INQUIRY: /* inquiry */
3779 		aac_free_dmamap(acp);
3780 		aac_inquiry(softs, pkt, cdbp, bp);
3781 		aac_soft_callback(softs, acp);
3782 		rval = TRAN_ACCEPT;
3783 		break;
3784 
3785 	case SCMD_READ_CAPACITY: /* read capacity */
3786 		if (bp && bp->b_un.b_addr && bp->b_bcount) {
3787 			struct scsi_capacity cap;
3788 			uint64_t last_lba;
3789 
3790 			/* check 64-bit LBA */
3791 			last_lba = dvp->size - 1;
3792 			if (last_lba > 0xffffffffull) {
3793 				cap.capacity = 0xfffffffful;
3794 			} else {
3795 				cap.capacity = BE_32(last_lba);
3796 			}
3797 			cap.lbasize = BE_32(AAC_SECTOR_SIZE);
3798 
3799 			aac_free_dmamap(acp);
3800 			if (bp->b_flags & (B_PHYS|B_PAGEIO))
3801 				bp_mapin(bp);
3802 			bcopy(&cap, bp->b_un.b_addr, min(bp->b_bcount, 8));
3803 			pkt->pkt_state |= STATE_XFERRED_DATA;
3804 		}
3805 		aac_soft_callback(softs, acp);
3806 		rval = TRAN_ACCEPT;
3807 		break;
3808 
3809 	case SCMD_SVC_ACTION_IN_G4: /* read capacity 16 */
3810 		/* Check if containers need 64-bit LBA support */
3811 		if (cdbp->cdb_opaque[1] == SSVC_ACTION_READ_CAPACITY_G4) {
3812 			if (bp && bp->b_un.b_addr && bp->b_bcount) {
3813 				struct scsi_capacity_16 cap16;
3814 				int cap_len = sizeof (struct scsi_capacity_16);
3815 
3816 				bzero(&cap16, cap_len);
3817 				cap16.sc_capacity = BE_64(dvp->size);
3818 				cap16.sc_lbasize = BE_32(AAC_SECTOR_SIZE);
3819 
3820 				aac_free_dmamap(acp);
3821 				if (bp->b_flags & (B_PHYS | B_PAGEIO))
3822 					bp_mapin(bp);
3823 				bcopy(&cap16, bp->b_un.b_addr,
3824 				    min(bp->b_bcount, cap_len));
3825 				pkt->pkt_state |= STATE_XFERRED_DATA;
3826 			}
3827 			aac_soft_callback(softs, acp);
3828 		} else {
3829 			aac_unknown_scmd(softs, acp);
3830 		}
3831 		rval = TRAN_ACCEPT;
3832 		break;
3833 
3834 	case SCMD_READ_G4: /* read_16 */
3835 	case SCMD_WRITE_G4: /* write_16 */
3836 		if (softs->flags & AAC_FLAGS_RAW_IO) {
3837 			/* NOTE: GETG4ADDRTL(cdbp) is int32_t */
3838 			acp->blkno = ((uint64_t) \
3839 			    GETG4ADDR(cdbp) << 32) | \
3840 			    (uint32_t)GETG4ADDRTL(cdbp);
3841 			goto do_io;
3842 		}
3843 		AACDB_PRINT(softs, CE_WARN, "64-bit LBA not supported");
3844 		aac_unknown_scmd(softs, acp);
3845 		rval = TRAN_ACCEPT;
3846 		break;
3847 
3848 	case SCMD_READ: /* read_6 */
3849 	case SCMD_WRITE: /* write_6 */
3850 		acp->blkno = GETG0ADDR(cdbp);
3851 		goto do_io;
3852 
3853 	case SCMD_READ_G1: /* read_10 */
3854 	case SCMD_WRITE_G1: /* write_10 */
3855 		acp->blkno = (uint32_t)GETG1ADDR(cdbp);
3856 do_io:
3857 		if (acp->flags & AAC_CMD_DMA_VALID) {
3858 			uint64_t cnt_size = dvp->size;
3859 
3860 			/*
3861 			 * If LBA > array size AND rawio, the
3862 			 * adapter may hang. So check it before
3863 			 * sending.
3864 			 * NOTE: (blkno + blkcnt) may overflow
3865 			 */
3866 			if ((acp->blkno < cnt_size) &&
3867 			    ((acp->blkno + acp->bcount /
3868 			    AAC_BLK_SIZE) <= cnt_size)) {
3869 				rval = aac_do_io(softs, acp);
3870 			} else {
3871 			/*
3872 			 * Request exceeds the capacity of disk,
3873 			 * set error block number to last LBA
3874 			 * + 1.
3875 			 */
3876 				aac_set_arq_data(pkt,
3877 				    KEY_ILLEGAL_REQUEST, 0x21,
3878 				    0x00, cnt_size);
3879 				aac_soft_callback(softs, acp);
3880 				rval = TRAN_ACCEPT;
3881 			}
3882 		} else if (acp->bcount == 0) {
3883 			/* For 0 length IO, just return ok */
3884 			aac_soft_callback(softs, acp);
3885 			rval = TRAN_ACCEPT;
3886 		} else {
3887 			rval = TRAN_BADPKT;
3888 		}
3889 		break;
3890 
3891 	case SCMD_MODE_SENSE: /* mode_sense_6 */
3892 	case SCMD_MODE_SENSE_G1: { /* mode_sense_10 */
3893 		int capacity;
3894 
3895 		aac_free_dmamap(acp);
3896 		if (dvp->size > 0xffffffffull)
3897 			capacity = 0xfffffffful; /* 64-bit LBA */
3898 		else
3899 			capacity = dvp->size;
3900 		aac_mode_sense(softs, pkt, cdbp, bp, capacity);
3901 		aac_soft_callback(softs, acp);
3902 		rval = TRAN_ACCEPT;
3903 		break;
3904 	}
3905 
3906 	case SCMD_TEST_UNIT_READY:
3907 	case SCMD_REQUEST_SENSE:
3908 	case SCMD_FORMAT:
3909 	case SCMD_START_STOP:
3910 		aac_free_dmamap(acp);
3911 		if (bp && bp->b_un.b_addr && bp->b_bcount) {
3912 			if (acp->flags & AAC_CMD_BUF_READ) {
3913 				if (bp->b_flags & (B_PHYS|B_PAGEIO))
3914 					bp_mapin(bp);
3915 				bzero(bp->b_un.b_addr, bp->b_bcount);
3916 			}
3917 			pkt->pkt_state |= STATE_XFERRED_DATA;
3918 		}
3919 		aac_soft_callback(softs, acp);
3920 		rval = TRAN_ACCEPT;
3921 		break;
3922 
3923 	case SCMD_SYNCHRONIZE_CACHE:
3924 		acp->flags |= AAC_CMD_NTAG;
3925 		acp->aac_cmd_fib = aac_cmd_fib_sync;
3926 		acp->ac_comp = aac_synccache_complete;
3927 		rval = aac_do_io(softs, acp);
3928 		break;
3929 
3930 	case SCMD_DOORLOCK:
3931 		aac_free_dmamap(acp);
3932 		dvp->locked = (pkt->pkt_cdbp[4] & 0x01) ? 1 : 0;
3933 		aac_soft_callback(softs, acp);
3934 		rval = TRAN_ACCEPT;
3935 		break;
3936 
3937 	default: /* unknown command */
3938 		aac_unknown_scmd(softs, acp);
3939 		rval = TRAN_ACCEPT;
3940 		break;
3941 	}
3942 
3943 	return (rval);
3944 }
3945 
3946 static int
3947 aac_tran_start(struct scsi_address *ap, struct scsi_pkt *pkt)
3948 {
3949 	struct aac_softstate *softs = AAC_TRAN2SOFTS(ap->a_hba_tran);
3950 	struct aac_cmd *acp = PKT2AC(pkt);
3951 	struct aac_container *dvp = acp->dvp;
3952 	int rval;
3953 
3954 	DBCALLED(softs, 2);
3955 
3956 	/*
3957 	 * Reinitialize some fields of ac and pkt; the packet may
3958 	 * have been resubmitted
3959 	 */
3960 	acp->flags &= AAC_CMD_CONSISTENT | AAC_CMD_DMA_PARTIAL | \
3961 	    AAC_CMD_BUF_READ | AAC_CMD_BUF_WRITE | AAC_CMD_DMA_VALID;
3962 	acp->timeout = acp->pkt->pkt_time;
3963 	if (pkt->pkt_flags & FLAG_NOINTR)
3964 		acp->flags |= AAC_CMD_NO_INTR;
3965 	pkt->pkt_reason = CMD_CMPLT;
3966 	pkt->pkt_state = 0;
3967 	pkt->pkt_statistics = 0;
3968 	*pkt->pkt_scbp = 0; /* clear arq scsi_status */
3969 
3970 	if (acp->flags & AAC_CMD_DMA_VALID) {
3971 		pkt->pkt_resid = acp->bcount;
3972 		/* Consistent packets need to be sync'ed first */
3973 		if ((acp->flags & AAC_CMD_CONSISTENT) &&
3974 		    (acp->flags & AAC_CMD_BUF_WRITE))
3975 			if (aac_dma_sync_ac(acp) != AACOK) {
3976 				ddi_fm_service_impact(softs->devinfo_p,
3977 				    DDI_SERVICE_UNAFFECTED);
3978 				return (TRAN_BADPKT);
3979 			}
3980 	} else {
3981 		pkt->pkt_resid = 0;
3982 	}
3983 
3984 	mutex_enter(&softs->io_lock);
3985 	AACDB_PRINT_SCMD(softs, acp);
3986 	if (dvp->valid && ap->a_lun == 0 && !(softs->state & AAC_STATE_DEAD)) {
3987 		rval = aac_tran_start_ld(softs, acp);
3988 	} else {
3989 		AACDB_PRINT(softs, CE_WARN,
3990 		    "Cannot send cmd to target t%dL%d: %s",
3991 		    ap->a_target, ap->a_lun,
3992 		    (softs->state & AAC_STATE_DEAD) ?
3993 		    "adapter dead" : "target invalid");
3994 		rval = TRAN_FATAL_ERROR;
3995 	}
3996 	mutex_exit(&softs->io_lock);
3997 	return (rval);
3998 }
3999 
4000 static int
4001 aac_tran_getcap(struct scsi_address *ap, char *cap, int whom)
4002 {
4003 	struct aac_softstate *softs = AAC_TRAN2SOFTS(ap->a_hba_tran);
4004 	struct aac_container *dvp;
4005 	int rval;
4006 
4007 	DBCALLED(softs, 2);
4008 
4009 	/* We don't allow inquiring about capabilities for other targets */
4010 	if (cap == NULL || whom == 0) {
4011 		AACDB_PRINT(softs, CE_WARN,
4012 		    "GetCap> %s not supported: whom=%d", cap, whom);
4013 		return (-1);
4014 	}
4015 
4016 	mutex_enter(&softs->io_lock);
4017 	dvp = &softs->containers[ap->a_target];
4018 	if (!dvp->valid || (ap->a_lun != 0)) {
4019 		mutex_exit(&softs->io_lock);
4020 		AACDB_PRINT(softs, CE_WARN, "Bad target t%dL%d to getcap",
4021 		    ap->a_target, ap->a_lun);
4022 		return (-1);
4023 	}
4024 
4025 	switch (scsi_hba_lookup_capstr(cap)) {
4026 	case SCSI_CAP_ARQ: /* auto request sense */
4027 		rval = 1;
4028 		break;
4029 	case SCSI_CAP_UNTAGGED_QING:
4030 	case SCSI_CAP_TAGGED_QING:
4031 		rval = 1;
4032 		break;
4033 	case SCSI_CAP_DMA_MAX:
4034 		rval = softs->buf_dma_attr.dma_attr_maxxfer;
4035 		break;
4036 	default:
4037 		rval = -1;
4038 		break;
4039 	}
4040 	mutex_exit(&softs->io_lock);
4041 
4042 	AACDB_PRINT_TRAN(softs, "GetCap> %s t%dL%d: rval=%d",
4043 	    cap, ap->a_target, ap->a_lun, rval);
4044 	return (rval);
4045 }
4046 
4047 /*ARGSUSED*/
4048 static int
4049 aac_tran_setcap(struct scsi_address *ap, char *cap, int value, int whom)
4050 {
4051 	struct aac_softstate *softs = AAC_TRAN2SOFTS(ap->a_hba_tran);
4052 	struct aac_container *dvp;
4053 	int rval;
4054 
4055 	DBCALLED(softs, 2);
4056 
4057 	/* We don't allow inquiring about capabilities for other targets */
4058 	if (cap == NULL || whom == 0) {
4059 		AACDB_PRINT(softs, CE_WARN,
4060 		    "SetCap> %s not supported: whom=%d", cap, whom);
4061 		return (-1);
4062 	}
4063 
4064 	mutex_enter(&softs->io_lock);
4065 	dvp = &softs->containers[ap->a_target];
4066 	if (!dvp->valid || (ap->a_lun != 0)) {
4067 		mutex_exit(&softs->io_lock);
4068 		AACDB_PRINT(softs, CE_WARN, "Bad target t%dL%d to setcap",
4069 		    ap->a_target, ap->a_lun);
4070 		return (-1);
4071 	}
4072 
4073 	switch (scsi_hba_lookup_capstr(cap)) {
4074 	case SCSI_CAP_ARQ:
4075 		/* Force auto request sense */
4076 		rval = (value == 1) ? 1 : 0;
4077 		break;
4078 	case SCSI_CAP_UNTAGGED_QING:
4079 	case SCSI_CAP_TAGGED_QING:
4080 		rval = (value == 1) ? 1 : 0;
4081 		break;
4082 	default:
4083 		rval = -1;
4084 		break;
4085 	}
4086 	mutex_exit(&softs->io_lock);
4087 
4088 	AACDB_PRINT_TRAN(softs, "SetCap> %s t%dL%d val=%d: rval=%d",
4089 	    cap, ap->a_target, ap->a_lun, value, rval);
4090 	return (rval);
4091 }
4092 
4093 static void
4094 aac_tran_destroy_pkt(struct scsi_address *ap, struct scsi_pkt *pkt)
4095 {
4096 	struct aac_cmd *acp = PKT2AC(pkt);
4097 
4098 	DBCALLED(NULL, 2);
4099 
4100 	if (acp->sgt) {
4101 		kmem_free(acp->sgt, sizeof (struct aac_sge) * \
4102 		    acp->left_cookien);
4103 	}
4104 	aac_free_dmamap(acp);
4105 	ASSERT(acp->slotp == NULL);
4106 	scsi_hba_pkt_free(ap, pkt);
4107 }
4108 
4109 int
4110 aac_cmd_dma_alloc(struct aac_softstate *softs, struct aac_cmd *acp,
4111     struct buf *bp, int flags, int (*cb)(), caddr_t arg)
4112 {
4113 	int kf = (cb == SLEEP_FUNC) ? KM_SLEEP : KM_NOSLEEP;
4114 	uint_t oldcookiec;
4115 	int bioerr;
4116 	int rval;
4117 
4118 	oldcookiec = acp->left_cookien;
4119 
4120 	/* Move window to build s/g map */
4121 	if (acp->total_nwin > 0) {
4122 		if (++acp->cur_win < acp->total_nwin) {
4123 			off_t off;
4124 			size_t len;
4125 
4126 			rval = ddi_dma_getwin(acp->buf_dma_handle, acp->cur_win,
4127 			    &off, &len, &acp->cookie, &acp->left_cookien);
4128 			if (rval == DDI_SUCCESS)
4129 				goto get_dma_cookies;
4130 			AACDB_PRINT(softs, CE_WARN,
4131 			    "ddi_dma_getwin() fail %d", rval);
4132 			return (NULL);
4133 		}
4134 		AACDB_PRINT(softs, CE_WARN, "Nothing to transfer");
4135 		return (NULL);
4136 	}
4137 
4138 	/* We need to transfer data, so we alloc DMA resources for this pkt */
4139 	if (bp && bp->b_bcount != 0 && !(acp->flags & AAC_CMD_DMA_VALID)) {
4140 		uint_t dma_flags = 0;
4141 		struct aac_sge *sge;
4142 
4143 		/*
4144 		 * We will still use this point to fake some
4145 		 * infomation in tran_start
4146 		 */
4147 		acp->bp = bp;
4148 
4149 		/* Set dma flags */
4150 		if (BUF_IS_READ(bp)) {
4151 			dma_flags |= DDI_DMA_READ;
4152 			acp->flags |= AAC_CMD_BUF_READ;
4153 		} else {
4154 			dma_flags |= DDI_DMA_WRITE;
4155 			acp->flags |= AAC_CMD_BUF_WRITE;
4156 		}
4157 		if (flags & PKT_CONSISTENT)
4158 			dma_flags |= DDI_DMA_CONSISTENT;
4159 		if (flags & PKT_DMA_PARTIAL)
4160 			dma_flags |= DDI_DMA_PARTIAL;
4161 
4162 		/* Alloc buf dma handle */
4163 		if (!acp->buf_dma_handle) {
4164 			rval = ddi_dma_alloc_handle(softs->devinfo_p,
4165 			    &softs->buf_dma_attr, cb, arg,
4166 			    &acp->buf_dma_handle);
4167 			if (rval != DDI_SUCCESS) {
4168 				AACDB_PRINT(softs, CE_WARN,
4169 				    "Can't allocate DMA handle, errno=%d",
4170 				    rval);
4171 				goto error_out;
4172 			}
4173 		}
4174 
4175 		/* Bind buf */
4176 		if (((uintptr_t)bp->b_un.b_addr & AAC_DMA_ALIGN_MASK) == 0) {
4177 			rval = ddi_dma_buf_bind_handle(acp->buf_dma_handle,
4178 			    bp, dma_flags, cb, arg, &acp->cookie,
4179 			    &acp->left_cookien);
4180 		} else {
4181 			size_t bufsz;
4182 
4183 			AACDB_PRINT_TRAN(softs,
4184 			    "non-aligned buffer: addr=0x%p, cnt=%lu",
4185 			    (void *)bp->b_un.b_addr, bp->b_bcount);
4186 			if (bp->b_flags & (B_PAGEIO|B_PHYS))
4187 				bp_mapin(bp);
4188 
4189 			rval = ddi_dma_mem_alloc(acp->buf_dma_handle,
4190 			    AAC_ROUNDUP(bp->b_bcount, AAC_DMA_ALIGN),
4191 			    &aac_acc_attr, DDI_DMA_STREAMING,
4192 			    cb, arg, &acp->abp, &bufsz, &acp->abh);
4193 
4194 			if (rval != DDI_SUCCESS) {
4195 				AACDB_PRINT(softs, CE_NOTE,
4196 				    "Cannot alloc DMA to non-aligned buf");
4197 				bioerr = 0;
4198 				goto error_out;
4199 			}
4200 
4201 			if (acp->flags & AAC_CMD_BUF_WRITE)
4202 				ddi_rep_put8(acp->abh,
4203 				    (uint8_t *)bp->b_un.b_addr,
4204 				    (uint8_t *)acp->abp, bp->b_bcount,
4205 				    DDI_DEV_AUTOINCR);
4206 
4207 			rval = ddi_dma_addr_bind_handle(acp->buf_dma_handle,
4208 			    NULL, acp->abp, bufsz, dma_flags, cb, arg,
4209 			    &acp->cookie, &acp->left_cookien);
4210 		}
4211 
4212 		switch (rval) {
4213 		case DDI_DMA_PARTIAL_MAP:
4214 			if (ddi_dma_numwin(acp->buf_dma_handle,
4215 			    &acp->total_nwin) == DDI_FAILURE) {
4216 				AACDB_PRINT(softs, CE_WARN,
4217 				    "Cannot get number of DMA windows");
4218 				bioerr = 0;
4219 				goto error_out;
4220 			}
4221 			AACDB_PRINT_TRAN(softs, "buf bind, %d seg(s)",
4222 			    acp->left_cookien);
4223 			acp->cur_win = 0;
4224 			break;
4225 
4226 		case DDI_DMA_MAPPED:
4227 			AACDB_PRINT_TRAN(softs, "buf bind, %d seg(s)",
4228 			    acp->left_cookien);
4229 			acp->cur_win = 0;
4230 			acp->total_nwin = 1;
4231 			break;
4232 
4233 		case DDI_DMA_NORESOURCES:
4234 			bioerr = 0;
4235 			AACDB_PRINT(softs, CE_WARN,
4236 			    "Cannot bind buf for DMA: DDI_DMA_NORESOURCES");
4237 			goto error_out;
4238 		case DDI_DMA_BADATTR:
4239 		case DDI_DMA_NOMAPPING:
4240 			bioerr = EFAULT;
4241 			AACDB_PRINT(softs, CE_WARN,
4242 			    "Cannot bind buf for DMA: DDI_DMA_NOMAPPING");
4243 			goto error_out;
4244 		case DDI_DMA_TOOBIG:
4245 			bioerr = EINVAL;
4246 			AACDB_PRINT(softs, CE_WARN,
4247 			    "Cannot bind buf for DMA: DDI_DMA_TOOBIG(%d)",
4248 			    bp->b_bcount);
4249 			goto error_out;
4250 		default:
4251 			bioerr = EINVAL;
4252 			AACDB_PRINT(softs, CE_WARN,
4253 			    "Cannot bind buf for DMA: %d", rval);
4254 			goto error_out;
4255 		}
4256 		acp->flags |= AAC_CMD_DMA_VALID;
4257 
4258 get_dma_cookies:
4259 		ASSERT(acp->left_cookien > 0);
4260 		if (acp->left_cookien > softs->aac_sg_tablesize) {
4261 			AACDB_PRINT(softs, CE_NOTE, "large cookiec received %d",
4262 			    acp->left_cookien);
4263 			bioerr = EINVAL;
4264 			goto error_out;
4265 		}
4266 		if (oldcookiec != acp->left_cookien && acp->sgt != NULL) {
4267 			kmem_free(acp->sgt, sizeof (struct aac_sge) * \
4268 			    oldcookiec);
4269 			acp->sgt = NULL;
4270 		}
4271 		if (acp->sgt == NULL) {
4272 			acp->sgt = kmem_alloc(sizeof (struct aac_sge) * \
4273 			    acp->left_cookien, kf);
4274 			if (acp->sgt == NULL) {
4275 				AACDB_PRINT(softs, CE_WARN,
4276 				    "sgt kmem_alloc fail");
4277 				bioerr = ENOMEM;
4278 				goto error_out;
4279 			}
4280 		}
4281 
4282 		sge = &acp->sgt[0];
4283 		sge->bcount = acp->cookie.dmac_size;
4284 		sge->addr.ad64.lo = AAC_LS32(acp->cookie.dmac_laddress);
4285 		sge->addr.ad64.hi = AAC_MS32(acp->cookie.dmac_laddress);
4286 		acp->bcount = acp->cookie.dmac_size;
4287 		for (sge++; sge < &acp->sgt[acp->left_cookien]; sge++) {
4288 			ddi_dma_nextcookie(acp->buf_dma_handle, &acp->cookie);
4289 			sge->bcount = acp->cookie.dmac_size;
4290 			sge->addr.ad64.lo = AAC_LS32(acp->cookie.dmac_laddress);
4291 			sge->addr.ad64.hi = AAC_MS32(acp->cookie.dmac_laddress);
4292 			acp->bcount += acp->cookie.dmac_size;
4293 		}
4294 
4295 		/*
4296 		 * Note: The old DMA engine do not correctly handle
4297 		 * dma_attr_maxxfer attribute. So we have to ensure
4298 		 * it by ourself.
4299 		 */
4300 		if (acp->bcount > softs->buf_dma_attr.dma_attr_maxxfer) {
4301 			AACDB_PRINT(softs, CE_NOTE,
4302 			    "large xfer size received %d\n", acp->bcount);
4303 			bioerr = EINVAL;
4304 			goto error_out;
4305 		}
4306 
4307 		acp->total_xfer += acp->bcount;
4308 
4309 		if (acp->pkt) {
4310 			/* Return remaining byte count */
4311 			acp->pkt->pkt_resid = bp->b_bcount - acp->total_xfer;
4312 
4313 			AACDB_PRINT_TRAN(softs,
4314 			    "bp=0x%p, xfered=%d/%d, resid=%d",
4315 			    (void *)bp->b_un.b_addr, (int)acp->total_xfer,
4316 			    (int)bp->b_bcount, (int)acp->pkt->pkt_resid);
4317 
4318 			ASSERT(acp->pkt->pkt_resid >= 0);
4319 		}
4320 	}
4321 	return (AACOK);
4322 
4323 error_out:
4324 	bioerror(bp, bioerr);
4325 	return (AACERR);
4326 }
4327 
4328 static struct scsi_pkt *
4329 aac_tran_init_pkt(struct scsi_address *ap, struct scsi_pkt *pkt,
4330     struct buf *bp, int cmdlen, int statuslen, int tgtlen, int flags,
4331     int (*callback)(), caddr_t arg)
4332 {
4333 	struct aac_softstate *softs = AAC_TRAN2SOFTS(ap->a_hba_tran);
4334 	struct aac_cmd *acp, *new_acp;
4335 
4336 	DBCALLED(softs, 2);
4337 
4338 	/* Allocate pkt */
4339 	if (pkt == NULL) {
4340 		int slen;
4341 
4342 		/* Force auto request sense */
4343 		slen = (statuslen > softs->slen) ? statuslen : softs->slen;
4344 		pkt = scsi_hba_pkt_alloc(softs->devinfo_p, ap, cmdlen,
4345 		    slen, tgtlen, sizeof (struct aac_cmd), callback, arg);
4346 		if (pkt == NULL) {
4347 			AACDB_PRINT(softs, CE_WARN, "Alloc scsi pkt failed");
4348 			return (NULL);
4349 		}
4350 		acp = new_acp = PKT2AC(pkt);
4351 		acp->pkt = pkt;
4352 		acp->cmdlen = cmdlen;
4353 
4354 		acp->dvp = &softs->containers[ap->a_target];
4355 		acp->aac_cmd_fib = softs->aac_cmd_fib;
4356 		acp->ac_comp = aac_ld_complete;
4357 	} else {
4358 		acp = PKT2AC(pkt);
4359 		new_acp = NULL;
4360 	}
4361 
4362 	if (aac_cmd_dma_alloc(softs, acp, bp, flags, callback, arg) == AACOK)
4363 		return (pkt);
4364 
4365 	if (new_acp)
4366 		aac_tran_destroy_pkt(ap, pkt);
4367 	return (NULL);
4368 }
4369 
4370 /*
4371  * tran_sync_pkt(9E) - explicit DMA synchronization
4372  */
4373 /*ARGSUSED*/
4374 static void
4375 aac_tran_sync_pkt(struct scsi_address *ap, struct scsi_pkt *pkt)
4376 {
4377 	struct aac_cmd *acp = PKT2AC(pkt);
4378 
4379 	DBCALLED(NULL, 2);
4380 
4381 	if (aac_dma_sync_ac(acp) != AACOK)
4382 		ddi_fm_service_impact(
4383 		    (AAC_TRAN2SOFTS(ap->a_hba_tran))->devinfo_p,
4384 		    DDI_SERVICE_UNAFFECTED);
4385 }
4386 
4387 /*
4388  * tran_dmafree(9E) - deallocate DMA resources allocated for command
4389  */
4390 /*ARGSUSED*/
4391 static void
4392 aac_tran_dmafree(struct scsi_address *ap, struct scsi_pkt *pkt)
4393 {
4394 	struct aac_cmd *acp = PKT2AC(pkt);
4395 
4396 	DBCALLED(NULL, 2);
4397 
4398 	aac_free_dmamap(acp);
4399 }
4400 
4401 static int
4402 aac_do_quiesce(struct aac_softstate *softs)
4403 {
4404 	aac_hold_bus(softs, AAC_IOCMD_ASYNC);
4405 	if (softs->bus_ncmds[AAC_CMDQ_ASYNC]) {
4406 		aac_start_drain(softs);
4407 		do {
4408 			if (cv_wait_sig(&softs->drain_cv,
4409 			    &softs->io_lock) == 0) {
4410 				/* Quiesce has been interrupted */
4411 				aac_stop_drain(softs);
4412 				aac_unhold_bus(softs, AAC_IOCMD_ASYNC);
4413 				aac_start_waiting_io(softs);
4414 				return (AACERR);
4415 			}
4416 		} while (softs->bus_ncmds[AAC_CMDQ_ASYNC]);
4417 		aac_stop_drain(softs);
4418 	}
4419 
4420 	softs->state |= AAC_STATE_QUIESCED;
4421 	return (AACOK);
4422 }
4423 
4424 static int
4425 aac_tran_quiesce(dev_info_t *dip)
4426 {
4427 	struct aac_softstate *softs = AAC_DIP2SOFTS(dip);
4428 	int rval;
4429 
4430 	DBCALLED(softs, 1);
4431 
4432 	mutex_enter(&softs->io_lock);
4433 	if (aac_do_quiesce(softs) == AACOK)
4434 		rval = 0;
4435 	else
4436 		rval = 1;
4437 	mutex_exit(&softs->io_lock);
4438 	return (rval);
4439 }
4440 
4441 static int
4442 aac_do_unquiesce(struct aac_softstate *softs)
4443 {
4444 	softs->state &= ~AAC_STATE_QUIESCED;
4445 	aac_unhold_bus(softs, AAC_IOCMD_ASYNC);
4446 
4447 	aac_start_waiting_io(softs);
4448 	return (AACOK);
4449 }
4450 
4451 static int
4452 aac_tran_unquiesce(dev_info_t *dip)
4453 {
4454 	struct aac_softstate *softs = AAC_DIP2SOFTS(dip);
4455 	int rval;
4456 
4457 	DBCALLED(softs, 1);
4458 
4459 	mutex_enter(&softs->io_lock);
4460 	if (aac_do_unquiesce(softs) == AACOK)
4461 		rval = 0;
4462 	else
4463 		rval = 1;
4464 	mutex_exit(&softs->io_lock);
4465 	return (rval);
4466 }
4467 
4468 static int
4469 aac_hba_setup(struct aac_softstate *softs)
4470 {
4471 	scsi_hba_tran_t *hba_tran;
4472 	int rval;
4473 
4474 	hba_tran = scsi_hba_tran_alloc(softs->devinfo_p, SCSI_HBA_CANSLEEP);
4475 	if (hba_tran == NULL)
4476 		return (AACERR);
4477 	hba_tran->tran_hba_private = softs;
4478 	hba_tran->tran_tgt_init = aac_tran_tgt_init;
4479 	hba_tran->tran_tgt_probe = scsi_hba_probe;
4480 	hba_tran->tran_start = aac_tran_start;
4481 	hba_tran->tran_getcap = aac_tran_getcap;
4482 	hba_tran->tran_setcap = aac_tran_setcap;
4483 	hba_tran->tran_init_pkt = aac_tran_init_pkt;
4484 	hba_tran->tran_destroy_pkt = aac_tran_destroy_pkt;
4485 	hba_tran->tran_reset = aac_tran_reset;
4486 	hba_tran->tran_abort = aac_tran_abort;
4487 	hba_tran->tran_sync_pkt = aac_tran_sync_pkt;
4488 	hba_tran->tran_dmafree = aac_tran_dmafree;
4489 	hba_tran->tran_quiesce = aac_tran_quiesce;
4490 	hba_tran->tran_unquiesce = aac_tran_unquiesce;
4491 	rval = scsi_hba_attach_setup(softs->devinfo_p, &softs->buf_dma_attr,
4492 	    hba_tran, 0);
4493 	if (rval != DDI_SUCCESS) {
4494 		scsi_hba_tran_free(hba_tran);
4495 		AACDB_PRINT(softs, CE_WARN, "aac_hba_setup failed");
4496 		return (AACERR);
4497 	}
4498 
4499 	return (AACOK);
4500 }
4501 
4502 /*
4503  * FIB setup operations
4504  */
4505 
4506 /*
4507  * Init FIB header
4508  */
4509 static void
4510 aac_cmd_fib_header(struct aac_softstate *softs, struct aac_slot *slotp,
4511     uint16_t cmd, uint16_t fib_size)
4512 {
4513 	ddi_acc_handle_t acc = slotp->fib_acc_handle;
4514 	struct aac_fib *fibp = slotp->fibp;
4515 	uint32_t xfer_state;
4516 
4517 	xfer_state =
4518 	    AAC_FIBSTATE_HOSTOWNED |
4519 	    AAC_FIBSTATE_INITIALISED |
4520 	    AAC_FIBSTATE_EMPTY |
4521 	    AAC_FIBSTATE_FROMHOST |
4522 	    AAC_FIBSTATE_REXPECTED |
4523 	    AAC_FIBSTATE_NORM;
4524 	if (slotp->acp && !(slotp->acp->flags & AAC_CMD_SYNC)) {
4525 		xfer_state |=
4526 		    AAC_FIBSTATE_ASYNC |
4527 		    AAC_FIBSTATE_FAST_RESPONSE /* enable fast io */;
4528 		ddi_put16(acc, &fibp->Header.SenderSize,
4529 		    softs->aac_max_fib_size);
4530 	} else {
4531 		ddi_put16(acc, &fibp->Header.SenderSize, AAC_FIB_SIZE);
4532 	}
4533 
4534 	ddi_put32(acc, &fibp->Header.XferState, xfer_state);
4535 	ddi_put16(acc, &fibp->Header.Command, cmd);
4536 	ddi_put8(acc, &fibp->Header.StructType, AAC_FIBTYPE_TFIB);
4537 	ddi_put8(acc, &fibp->Header.Flags, 0); /* don't care */
4538 	ddi_put16(acc, &fibp->Header.Size, fib_size);
4539 	ddi_put32(acc, &fibp->Header.SenderFibAddress, (slotp->index << 2));
4540 	ddi_put32(acc, &fibp->Header.ReceiverFibAddress, slotp->fib_phyaddr);
4541 	ddi_put32(acc, &fibp->Header.SenderData, 0); /* don't care */
4542 }
4543 
4544 /*
4545  * Init FIB for raw IO command
4546  */
4547 static void
4548 aac_cmd_fib_rawio(struct aac_softstate *softs, struct aac_cmd *acp)
4549 {
4550 	ddi_acc_handle_t acc = acp->slotp->fib_acc_handle;
4551 	struct aac_raw_io *io = (struct aac_raw_io *)&acp->slotp->fibp->data[0];
4552 	struct aac_sg_entryraw *sgp;
4553 	struct aac_sge *sge;
4554 
4555 	/* Calculate FIB size */
4556 	acp->fib_size = sizeof (struct aac_fib_header) + \
4557 	    sizeof (struct aac_raw_io) + (acp->left_cookien - 1) * \
4558 	    sizeof (struct aac_sg_entryraw);
4559 
4560 	aac_cmd_fib_header(softs, acp->slotp, RawIo, acp->fib_size);
4561 
4562 	ddi_put16(acc, &io->Flags, (acp->flags & AAC_CMD_BUF_READ) ? 1 : 0);
4563 	ddi_put16(acc, &io->BpTotal, 0);
4564 	ddi_put16(acc, &io->BpComplete, 0);
4565 
4566 	ddi_put32(acc, AAC_LO32(&io->BlockNumber), AAC_LS32(acp->blkno));
4567 	ddi_put32(acc, AAC_HI32(&io->BlockNumber), AAC_MS32(acp->blkno));
4568 	ddi_put16(acc, &io->ContainerId,
4569 	    ((struct aac_container *)acp->dvp)->cid);
4570 
4571 	/* Fill SG table */
4572 	ddi_put32(acc, &io->SgMapRaw.SgCount, acp->left_cookien);
4573 	ddi_put32(acc, &io->ByteCount, acp->bcount);
4574 
4575 	for (sge = &acp->sgt[0], sgp = &io->SgMapRaw.SgEntryRaw[0];
4576 	    sge < &acp->sgt[acp->left_cookien]; sge++, sgp++) {
4577 		ddi_put32(acc, AAC_LO32(&sgp->SgAddress), sge->addr.ad64.lo);
4578 		ddi_put32(acc, AAC_HI32(&sgp->SgAddress), sge->addr.ad64.hi);
4579 		ddi_put32(acc, &sgp->SgByteCount, sge->bcount);
4580 		sgp->Next = 0;
4581 		sgp->Prev = 0;
4582 		sgp->Flags = 0;
4583 	}
4584 }
4585 
4586 /* Init FIB for 64-bit block IO command */
4587 static void
4588 aac_cmd_fib_brw64(struct aac_softstate *softs, struct aac_cmd *acp)
4589 {
4590 	ddi_acc_handle_t acc = acp->slotp->fib_acc_handle;
4591 	struct aac_blockread64 *br = (struct aac_blockread64 *) \
4592 	    &acp->slotp->fibp->data[0];
4593 	struct aac_sg_entry64 *sgp;
4594 	struct aac_sge *sge;
4595 
4596 	acp->fib_size = sizeof (struct aac_fib_header) + \
4597 	    sizeof (struct aac_blockread64) + (acp->left_cookien - 1) * \
4598 	    sizeof (struct aac_sg_entry64);
4599 
4600 	aac_cmd_fib_header(softs, acp->slotp, ContainerCommand64,
4601 	    acp->fib_size);
4602 
4603 	/*
4604 	 * The definitions for aac_blockread64 and aac_blockwrite64
4605 	 * are the same.
4606 	 */
4607 	ddi_put32(acc, &br->BlockNumber, (uint32_t)acp->blkno);
4608 	ddi_put16(acc, &br->ContainerId,
4609 	    ((struct aac_container *)acp->dvp)->cid);
4610 	ddi_put32(acc, &br->Command, (acp->flags & AAC_CMD_BUF_READ) ?
4611 	    VM_CtHostRead64 : VM_CtHostWrite64);
4612 	ddi_put16(acc, &br->Pad, 0);
4613 	ddi_put16(acc, &br->Flags, 0);
4614 
4615 	/* Fill SG table */
4616 	ddi_put32(acc, &br->SgMap64.SgCount, acp->left_cookien);
4617 	ddi_put16(acc, &br->SectorCount, acp->bcount / AAC_BLK_SIZE);
4618 
4619 	for (sge = &acp->sgt[0], sgp = &br->SgMap64.SgEntry64[0];
4620 	    sge < &acp->sgt[acp->left_cookien]; sge++, sgp++) {
4621 		ddi_put32(acc, AAC_LO32(&sgp->SgAddress), sge->addr.ad64.lo);
4622 		ddi_put32(acc, AAC_HI32(&sgp->SgAddress), sge->addr.ad64.hi);
4623 		ddi_put32(acc, &sgp->SgByteCount, sge->bcount);
4624 	}
4625 }
4626 
4627 /* Init FIB for block IO command */
4628 static void
4629 aac_cmd_fib_brw(struct aac_softstate *softs, struct aac_cmd *acp)
4630 {
4631 	ddi_acc_handle_t acc = acp->slotp->fib_acc_handle;
4632 	struct aac_blockread *br = (struct aac_blockread *) \
4633 	    &acp->slotp->fibp->data[0];
4634 	struct aac_sg_entry *sgp;
4635 	struct aac_sge *sge = &acp->sgt[0];
4636 
4637 	if (acp->flags & AAC_CMD_BUF_READ) {
4638 		acp->fib_size = sizeof (struct aac_fib_header) + \
4639 		    sizeof (struct aac_blockread) + (acp->left_cookien - 1) * \
4640 		    sizeof (struct aac_sg_entry);
4641 
4642 		ddi_put32(acc, &br->Command, VM_CtBlockRead);
4643 		ddi_put32(acc, &br->SgMap.SgCount, acp->left_cookien);
4644 		sgp = &br->SgMap.SgEntry[0];
4645 	} else {
4646 		struct aac_blockwrite *bw = (struct aac_blockwrite *)br;
4647 
4648 		acp->fib_size = sizeof (struct aac_fib_header) + \
4649 		    sizeof (struct aac_blockwrite) + (acp->left_cookien - 1) * \
4650 		    sizeof (struct aac_sg_entry);
4651 
4652 		ddi_put32(acc, &bw->Command, VM_CtBlockWrite);
4653 		ddi_put32(acc, &bw->Stable, CUNSTABLE);
4654 		ddi_put32(acc, &bw->SgMap.SgCount, acp->left_cookien);
4655 		sgp = &bw->SgMap.SgEntry[0];
4656 	}
4657 	aac_cmd_fib_header(softs, acp->slotp, ContainerCommand, acp->fib_size);
4658 
4659 	/*
4660 	 * aac_blockread and aac_blockwrite have the similar
4661 	 * structure head, so use br for bw here
4662 	 */
4663 	ddi_put32(acc, &br->BlockNumber, (uint32_t)acp->blkno);
4664 	ddi_put32(acc, &br->ContainerId,
4665 	    ((struct aac_container *)acp->dvp)->cid);
4666 	ddi_put32(acc, &br->ByteCount, acp->bcount);
4667 
4668 	/* Fill SG table */
4669 	for (sge = &acp->sgt[0];
4670 	    sge < &acp->sgt[acp->left_cookien]; sge++, sgp++) {
4671 		ddi_put32(acc, &sgp->SgAddress, sge->addr.ad32);
4672 		ddi_put32(acc, &sgp->SgByteCount, sge->bcount);
4673 	}
4674 }
4675 
4676 /*ARGSUSED*/
4677 void
4678 aac_cmd_fib_copy(struct aac_softstate *softs, struct aac_cmd *acp)
4679 {
4680 	struct aac_slot *slotp = acp->slotp;
4681 	struct aac_fib *fibp = slotp->fibp;
4682 	ddi_acc_handle_t acc = slotp->fib_acc_handle;
4683 
4684 	ddi_rep_put8(acc, (uint8_t *)acp->fibp, (uint8_t *)fibp,
4685 	    acp->fib_size,   /* only copy data of needed length */
4686 	    DDI_DEV_AUTOINCR);
4687 	ddi_put32(acc, &fibp->Header.ReceiverFibAddress, slotp->fib_phyaddr);
4688 	ddi_put32(acc, &fibp->Header.SenderFibAddress, slotp->index << 2);
4689 }
4690 
4691 static void
4692 aac_cmd_fib_sync(struct aac_softstate *softs, struct aac_cmd *acp)
4693 {
4694 	struct aac_slot *slotp = acp->slotp;
4695 	ddi_acc_handle_t acc = slotp->fib_acc_handle;
4696 	struct aac_synchronize_command *sync =
4697 	    (struct aac_synchronize_command *)&slotp->fibp->data[0];
4698 
4699 	acp->fib_size = sizeof (struct aac_fib_header) + \
4700 	    sizeof (struct aac_synchronize_command);
4701 
4702 	aac_cmd_fib_header(softs, slotp, ContainerCommand, acp->fib_size);
4703 	ddi_put32(acc, &sync->Command, VM_ContainerConfig);
4704 	ddi_put32(acc, &sync->Type, (uint32_t)CT_FLUSH_CACHE);
4705 	ddi_put32(acc, &sync->Cid, ((struct aac_container *)acp->dvp)->cid);
4706 	ddi_put32(acc, &sync->Count,
4707 	    sizeof (((struct aac_synchronize_reply *)0)->Data));
4708 }
4709 
4710 /*
4711  * Init FIB for pass-through SCMD
4712  */
4713 static void
4714 aac_cmd_fib_srb(struct aac_cmd *acp)
4715 {
4716 	struct aac_slot *slotp = acp->slotp;
4717 	ddi_acc_handle_t acc = slotp->fib_acc_handle;
4718 	struct aac_srb *srb = (struct aac_srb *)&slotp->fibp->data[0];
4719 	struct aac_srb *srb0 = (struct aac_srb *)&acp->fibp->data[0];
4720 
4721 	ddi_put32(acc, &srb->function, SRBF_ExecuteScsi);
4722 	ddi_put32(acc, &srb->retry_limit, 0);
4723 	ddi_put32(acc, &srb->cdb_size, acp->cmdlen);
4724 	ddi_put32(acc, &srb->timeout, 0); /* use driver timeout */
4725 
4726 	ddi_put32(acc, &srb->flags, srb0->flags);
4727 	ddi_put32(acc, &srb->channel, srb0->channel);
4728 	ddi_put32(acc, &srb->id, srb0->id);
4729 	ddi_put32(acc, &srb->lun, srb0->lun);
4730 	ddi_rep_put8(acc, srb0->cdb, srb->cdb, acp->cmdlen, DDI_DEV_AUTOINCR);
4731 }
4732 
4733 static void
4734 aac_cmd_fib_scsi32(struct aac_softstate *softs, struct aac_cmd *acp)
4735 {
4736 	ddi_acc_handle_t acc = acp->slotp->fib_acc_handle;
4737 	struct aac_srb *srb = (struct aac_srb *)&acp->slotp->fibp->data[0];
4738 	struct aac_sg_entry *sgp;
4739 	struct aac_sge *sge;
4740 
4741 	acp->fib_size = sizeof (struct aac_fib_header) + \
4742 	    sizeof (struct aac_srb) - sizeof (struct aac_sg_entry) + \
4743 	    acp->left_cookien * sizeof (struct aac_sg_entry);
4744 
4745 	/* Fill FIB and SRB headers, and copy cdb */
4746 	aac_cmd_fib_header(softs, acp->slotp, ScsiPortCommand, acp->fib_size);
4747 	aac_cmd_fib_srb(acp);
4748 
4749 	/* Fill SG table */
4750 	ddi_put32(acc, &srb->sg.SgCount, acp->left_cookien);
4751 	ddi_put32(acc, &srb->count, acp->bcount);
4752 
4753 	for (sge = &acp->sgt[0], sgp = &srb->sg.SgEntry[0];
4754 	    sge < &acp->sgt[acp->left_cookien]; sge++, sgp++) {
4755 		ddi_put32(acc, &sgp->SgAddress, sge->addr.ad32);
4756 		ddi_put32(acc, &sgp->SgByteCount, sge->bcount);
4757 	}
4758 }
4759 
4760 static void
4761 aac_cmd_fib_scsi64(struct aac_softstate *softs, struct aac_cmd *acp)
4762 {
4763 	ddi_acc_handle_t acc = acp->slotp->fib_acc_handle;
4764 	struct aac_srb *srb = (struct aac_srb *)&acp->slotp->fibp->data[0];
4765 	struct aac_sg_entry64 *sgp;
4766 	struct aac_sge *sge;
4767 
4768 	acp->fib_size = sizeof (struct aac_fib_header) + \
4769 	    sizeof (struct aac_srb) - sizeof (struct aac_sg_entry) + \
4770 	    acp->left_cookien * sizeof (struct aac_sg_entry64);
4771 
4772 	/* Fill FIB and SRB headers, and copy cdb */
4773 	aac_cmd_fib_header(softs, acp->slotp, ScsiPortCommandU64,
4774 	    acp->fib_size);
4775 	aac_cmd_fib_srb(acp);
4776 
4777 	/* Fill SG table */
4778 	ddi_put32(acc, &srb->sg.SgCount, acp->left_cookien);
4779 	ddi_put32(acc, &srb->count, acp->bcount);
4780 
4781 	for (sge = &acp->sgt[0],
4782 	    sgp = &((struct aac_sg_table64 *)&srb->sg)->SgEntry64[0];
4783 	    sge < &acp->sgt[acp->left_cookien]; sge++, sgp++) {
4784 		ddi_put32(acc, AAC_LO32(&sgp->SgAddress), sge->addr.ad64.lo);
4785 		ddi_put32(acc, AAC_HI32(&sgp->SgAddress), sge->addr.ad64.hi);
4786 		ddi_put32(acc, &sgp->SgByteCount, sge->bcount);
4787 	}
4788 }
4789 
4790 static int
4791 aac_cmd_slot_bind(struct aac_softstate *softs, struct aac_cmd *acp)
4792 {
4793 	struct aac_slot *slotp;
4794 
4795 	if (slotp = aac_get_slot(softs)) {
4796 		acp->slotp = slotp;
4797 		slotp->acp = acp;
4798 		acp->aac_cmd_fib(softs, acp);
4799 		(void) ddi_dma_sync(slotp->fib_dma_handle, 0, 0,
4800 		    DDI_DMA_SYNC_FORDEV);
4801 		return (AACOK);
4802 	}
4803 	return (AACERR);
4804 }
4805 
4806 static int
4807 aac_bind_io(struct aac_softstate *softs, struct aac_cmd *acp)
4808 {
4809 	struct aac_container *dvp = acp->dvp;
4810 	int q = AAC_CMDQ(acp);
4811 
4812 	if (dvp) {
4813 		if (dvp->ncmds[q] < dvp->throttle[q]) {
4814 			if (!(acp->flags & AAC_CMD_NTAG) ||
4815 			    dvp->ncmds[q] == 0) {
4816 do_bind:
4817 				return (aac_cmd_slot_bind(softs, acp));
4818 			}
4819 			ASSERT(q == AAC_CMDQ_ASYNC);
4820 			aac_set_throttle(softs, dvp, AAC_CMDQ_ASYNC,
4821 			    AAC_THROTTLE_DRAIN);
4822 		}
4823 	} else {
4824 		if (softs->bus_ncmds[q] < softs->bus_throttle[q])
4825 			goto do_bind;
4826 	}
4827 	return (AACERR);
4828 }
4829 
4830 static void
4831 aac_start_io(struct aac_softstate *softs, struct aac_cmd *acp)
4832 {
4833 	struct aac_slot *slotp = acp->slotp;
4834 	int q = AAC_CMDQ(acp);
4835 	int rval;
4836 
4837 	/* Set ac and pkt */
4838 	if (acp->pkt) { /* ac from ioctl has no pkt */
4839 		acp->pkt->pkt_state |=
4840 		    STATE_GOT_BUS | STATE_GOT_TARGET | STATE_SENT_CMD;
4841 	}
4842 	if (acp->timeout) /* 0 indicates no timeout */
4843 		acp->timeout += aac_timebase + aac_tick;
4844 
4845 	if (acp->dvp)
4846 		acp->dvp->ncmds[q]++;
4847 	softs->bus_ncmds[q]++;
4848 	aac_cmd_enqueue(&softs->q_busy, acp);
4849 
4850 	if (softs->flags & AAC_FLAGS_NEW_COMM) {
4851 		rval = aac_send_command(softs, slotp);
4852 	} else {
4853 		/*
4854 		 * If fib can not be enqueued, the adapter is in an abnormal
4855 		 * state, there will be no interrupt to us.
4856 		 */
4857 		rval = aac_fib_enqueue(softs, AAC_ADAP_NORM_CMD_Q,
4858 		    slotp->fib_phyaddr, acp->fib_size);
4859 	}
4860 
4861 	if (aac_check_dma_handle(slotp->fib_dma_handle) != DDI_SUCCESS)
4862 		ddi_fm_service_impact(softs->devinfo_p, DDI_SERVICE_UNAFFECTED);
4863 
4864 	/*
4865 	 * NOTE: We send command only when slots availabe, so should never
4866 	 * reach here.
4867 	 */
4868 	if (rval != AACOK) {
4869 		AACDB_PRINT(softs, CE_NOTE, "SCMD send failed");
4870 		if (acp->pkt) {
4871 			acp->pkt->pkt_state &= ~STATE_SENT_CMD;
4872 			aac_set_pkt_reason(softs, acp, CMD_INCOMPLETE, 0);
4873 		}
4874 		aac_end_io(softs, acp);
4875 		if (!(acp->flags & (AAC_CMD_NO_INTR | AAC_CMD_NO_CB)))
4876 			ddi_trigger_softintr(softs->softint_id);
4877 	}
4878 }
4879 
4880 static void
4881 aac_start_waitq(struct aac_softstate *softs, struct aac_cmd_queue *q)
4882 {
4883 	struct aac_cmd *acp, *next_acp;
4884 
4885 	/* Serve as many waiting io's as possible */
4886 	for (acp = q->q_head; acp; acp = next_acp) {
4887 		next_acp = acp->next;
4888 		if (aac_bind_io(softs, acp) == AACOK) {
4889 			aac_cmd_delete(q, acp);
4890 			aac_start_io(softs, acp);
4891 		}
4892 		if (softs->free_io_slot_head == NULL)
4893 			break;
4894 	}
4895 }
4896 
4897 static void
4898 aac_start_waiting_io(struct aac_softstate *softs)
4899 {
4900 	/*
4901 	 * Sync FIB io is served before async FIB io so that io requests
4902 	 * sent by interactive userland commands get responded asap.
4903 	 */
4904 	if (softs->q_wait[AAC_CMDQ_SYNC].q_head)
4905 		aac_start_waitq(softs, &softs->q_wait[AAC_CMDQ_SYNC]);
4906 	if (softs->q_wait[AAC_CMDQ_ASYNC].q_head)
4907 		aac_start_waitq(softs, &softs->q_wait[AAC_CMDQ_ASYNC]);
4908 }
4909 
4910 static void
4911 aac_drain_comp_q(struct aac_softstate *softs)
4912 {
4913 	struct aac_cmd *acp;
4914 	struct scsi_pkt *pkt;
4915 
4916 	/*CONSTCOND*/
4917 	while (1) {
4918 		mutex_enter(&softs->q_comp_mutex);
4919 		acp = aac_cmd_dequeue(&softs->q_comp);
4920 		mutex_exit(&softs->q_comp_mutex);
4921 		if (acp != NULL) {
4922 			ASSERT(acp->pkt != NULL);
4923 			pkt = acp->pkt;
4924 
4925 			if (pkt->pkt_reason == CMD_CMPLT) {
4926 				/*
4927 				 * Consistent packets need to be sync'ed first
4928 				 */
4929 				if ((acp->flags & AAC_CMD_CONSISTENT) &&
4930 				    (acp->flags & AAC_CMD_BUF_READ)) {
4931 					if (aac_dma_sync_ac(acp) != AACOK) {
4932 						ddi_fm_service_impact(
4933 						    softs->devinfo_p,
4934 						    DDI_SERVICE_UNAFFECTED);
4935 						pkt->pkt_reason = CMD_TRAN_ERR;
4936 						pkt->pkt_statistics = 0;
4937 					}
4938 				}
4939 				if ((aac_check_acc_handle(softs-> \
4940 				    comm_space_acc_handle) != DDI_SUCCESS) ||
4941 				    (aac_check_acc_handle(softs-> \
4942 				    pci_mem_handle) != DDI_SUCCESS)) {
4943 					ddi_fm_service_impact(softs->devinfo_p,
4944 					    DDI_SERVICE_UNAFFECTED);
4945 					ddi_fm_acc_err_clear(softs-> \
4946 					    pci_mem_handle, DDI_FME_VER0);
4947 					pkt->pkt_reason = CMD_TRAN_ERR;
4948 					pkt->pkt_statistics = 0;
4949 				}
4950 				if (aac_check_dma_handle(softs-> \
4951 				    comm_space_dma_handle) != DDI_SUCCESS) {
4952 					ddi_fm_service_impact(softs->devinfo_p,
4953 					    DDI_SERVICE_UNAFFECTED);
4954 					pkt->pkt_reason = CMD_TRAN_ERR;
4955 					pkt->pkt_statistics = 0;
4956 				}
4957 			}
4958 			(*pkt->pkt_comp)(pkt);
4959 		} else {
4960 			break;
4961 		}
4962 	}
4963 }
4964 
4965 static int
4966 aac_alloc_fib(struct aac_softstate *softs, struct aac_slot *slotp)
4967 {
4968 	size_t rlen;
4969 	ddi_dma_cookie_t cookie;
4970 	uint_t cookien;
4971 
4972 	/* Allocate FIB dma resource */
4973 	if (ddi_dma_alloc_handle(
4974 	    softs->devinfo_p,
4975 	    &softs->addr_dma_attr,
4976 	    DDI_DMA_SLEEP,
4977 	    NULL,
4978 	    &slotp->fib_dma_handle) != DDI_SUCCESS) {
4979 		AACDB_PRINT(softs, CE_WARN,
4980 		    "Cannot alloc dma handle for slot fib area");
4981 		goto error;
4982 	}
4983 	if (ddi_dma_mem_alloc(
4984 	    slotp->fib_dma_handle,
4985 	    softs->aac_max_fib_size,
4986 	    &aac_acc_attr,
4987 	    DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
4988 	    DDI_DMA_SLEEP,
4989 	    NULL,
4990 	    (caddr_t *)&slotp->fibp,
4991 	    &rlen,
4992 	    &slotp->fib_acc_handle) != DDI_SUCCESS) {
4993 		AACDB_PRINT(softs, CE_WARN,
4994 		    "Cannot alloc mem for slot fib area");
4995 		goto error;
4996 	}
4997 	if (ddi_dma_addr_bind_handle(
4998 	    slotp->fib_dma_handle,
4999 	    NULL,
5000 	    (caddr_t)slotp->fibp,
5001 	    softs->aac_max_fib_size,
5002 	    DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
5003 	    DDI_DMA_SLEEP,
5004 	    NULL,
5005 	    &cookie,
5006 	    &cookien) != DDI_DMA_MAPPED) {
5007 		AACDB_PRINT(softs, CE_WARN,
5008 		    "dma bind failed for slot fib area");
5009 		goto error;
5010 	}
5011 
5012 	/* Check dma handles allocated in fib attach */
5013 	if (aac_check_dma_handle(slotp->fib_dma_handle) != DDI_SUCCESS) {
5014 		ddi_fm_service_impact(softs->devinfo_p, DDI_SERVICE_LOST);
5015 		goto error;
5016 	}
5017 
5018 	/* Check acc handles allocated in fib attach */
5019 	if (aac_check_acc_handle(slotp->fib_acc_handle) != DDI_SUCCESS) {
5020 		ddi_fm_service_impact(softs->devinfo_p, DDI_SERVICE_LOST);
5021 		goto error;
5022 	}
5023 
5024 	slotp->fib_phyaddr = cookie.dmac_laddress;
5025 	return (AACOK);
5026 
5027 error:
5028 	if (slotp->fib_acc_handle) {
5029 		ddi_dma_mem_free(&slotp->fib_acc_handle);
5030 		slotp->fib_acc_handle = NULL;
5031 	}
5032 	if (slotp->fib_dma_handle) {
5033 		ddi_dma_free_handle(&slotp->fib_dma_handle);
5034 		slotp->fib_dma_handle = NULL;
5035 	}
5036 	return (AACERR);
5037 }
5038 
5039 static void
5040 aac_free_fib(struct aac_slot *slotp)
5041 {
5042 	(void) ddi_dma_unbind_handle(slotp->fib_dma_handle);
5043 	ddi_dma_mem_free(&slotp->fib_acc_handle);
5044 	slotp->fib_acc_handle = NULL;
5045 	ddi_dma_free_handle(&slotp->fib_dma_handle);
5046 	slotp->fib_dma_handle = NULL;
5047 	slotp->fib_phyaddr = 0;
5048 }
5049 
5050 static void
5051 aac_alloc_fibs(struct aac_softstate *softs)
5052 {
5053 	int i;
5054 	struct aac_slot *slotp;
5055 
5056 	for (i = 0; i < softs->total_slots &&
5057 	    softs->total_fibs < softs->total_slots; i++) {
5058 		slotp = &(softs->io_slot[i]);
5059 		if (slotp->fib_phyaddr)
5060 			continue;
5061 		if (aac_alloc_fib(softs, slotp) != AACOK)
5062 			break;
5063 
5064 		/* Insert the slot to the free slot list */
5065 		aac_release_slot(softs, slotp);
5066 		softs->total_fibs++;
5067 	}
5068 }
5069 
5070 static void
5071 aac_destroy_fibs(struct aac_softstate *softs)
5072 {
5073 	struct aac_slot *slotp;
5074 
5075 	while ((slotp = softs->free_io_slot_head) != NULL) {
5076 		ASSERT(slotp->fib_phyaddr);
5077 		softs->free_io_slot_head = slotp->next;
5078 		aac_free_fib(slotp);
5079 		ASSERT(slotp->index == (slotp - softs->io_slot));
5080 		softs->total_fibs--;
5081 	}
5082 	ASSERT(softs->total_fibs == 0);
5083 }
5084 
5085 static int
5086 aac_create_slots(struct aac_softstate *softs)
5087 {
5088 	int i;
5089 
5090 	softs->total_slots = softs->aac_max_fibs;
5091 	softs->io_slot = kmem_zalloc(sizeof (struct aac_slot) * \
5092 	    softs->total_slots, KM_SLEEP);
5093 	if (softs->io_slot == NULL) {
5094 		AACDB_PRINT(softs, CE_WARN, "Cannot allocate slot");
5095 		return (AACERR);
5096 	}
5097 	for (i = 0; i < softs->total_slots; i++)
5098 		softs->io_slot[i].index = i;
5099 	softs->free_io_slot_head = NULL;
5100 	softs->total_fibs = 0;
5101 	return (AACOK);
5102 }
5103 
5104 static void
5105 aac_destroy_slots(struct aac_softstate *softs)
5106 {
5107 	ASSERT(softs->free_io_slot_head == NULL);
5108 
5109 	kmem_free(softs->io_slot, sizeof (struct aac_slot) * \
5110 	    softs->total_slots);
5111 	softs->io_slot = NULL;
5112 	softs->total_slots = 0;
5113 }
5114 
5115 struct aac_slot *
5116 aac_get_slot(struct aac_softstate *softs)
5117 {
5118 	struct aac_slot *slotp;
5119 
5120 	if ((slotp = softs->free_io_slot_head) != NULL) {
5121 		softs->free_io_slot_head = slotp->next;
5122 		slotp->next = NULL;
5123 	}
5124 	return (slotp);
5125 }
5126 
5127 static void
5128 aac_release_slot(struct aac_softstate *softs, struct aac_slot *slotp)
5129 {
5130 	ASSERT((slotp->index >= 0) && (slotp->index < softs->total_slots));
5131 	ASSERT(slotp == &softs->io_slot[slotp->index]);
5132 
5133 	slotp->acp = NULL;
5134 	slotp->next = softs->free_io_slot_head;
5135 	softs->free_io_slot_head = slotp;
5136 }
5137 
5138 int
5139 aac_do_io(struct aac_softstate *softs, struct aac_cmd *acp)
5140 {
5141 	if (aac_bind_io(softs, acp) == AACOK)
5142 		aac_start_io(softs, acp);
5143 	else
5144 		aac_cmd_enqueue(&softs->q_wait[AAC_CMDQ(acp)], acp);
5145 
5146 	if (!(acp->flags & (AAC_CMD_NO_CB | AAC_CMD_NO_INTR)))
5147 		return (TRAN_ACCEPT);
5148 	/*
5149 	 * Because sync FIB is always 512 bytes and used for critical
5150 	 * functions, async FIB is used for poll IO.
5151 	 */
5152 	if (acp->flags & AAC_CMD_NO_INTR) {
5153 		if (aac_do_poll_io(softs, acp) == AACOK)
5154 			return (TRAN_ACCEPT);
5155 	} else {
5156 		if (aac_do_sync_io(softs, acp) == AACOK)
5157 			return (TRAN_ACCEPT);
5158 	}
5159 	return (TRAN_BADPKT);
5160 }
5161 
5162 static int
5163 aac_do_poll_io(struct aac_softstate *softs, struct aac_cmd *acp)
5164 {
5165 	int (*intr_handler)(struct aac_softstate *);
5166 
5167 	/*
5168 	 * Interrupt is disabled, we have to poll the adapter by ourselves.
5169 	 */
5170 	intr_handler = (softs->flags & AAC_FLAGS_NEW_COMM) ?
5171 	    aac_process_intr_new : aac_process_intr_old;
5172 	while (!(acp->flags & (AAC_CMD_CMPLT | AAC_CMD_ABORT))) {
5173 		int i = AAC_POLL_TIME * 1000;
5174 
5175 		AAC_BUSYWAIT((intr_handler(softs) != AAC_DB_RESPONSE_READY), i);
5176 		if (i == 0)
5177 			aac_cmd_timeout(softs);
5178 	}
5179 
5180 	ddi_trigger_softintr(softs->softint_id);
5181 
5182 	if ((acp->flags & AAC_CMD_CMPLT) && !(acp->flags & AAC_CMD_ERR))
5183 		return (AACOK);
5184 	return (AACERR);
5185 }
5186 
5187 static int
5188 aac_do_sync_io(struct aac_softstate *softs, struct aac_cmd *acp)
5189 {
5190 	ASSERT(softs && acp);
5191 
5192 	while (!(acp->flags & (AAC_CMD_CMPLT | AAC_CMD_ABORT)))
5193 		cv_wait(&softs->event, &softs->io_lock);
5194 
5195 	if (acp->flags & AAC_CMD_CMPLT)
5196 		return (AACOK);
5197 	return (AACERR);
5198 }
5199 
5200 static int
5201 aac_dma_sync_ac(struct aac_cmd *acp)
5202 {
5203 	if (acp->buf_dma_handle) {
5204 		if (acp->flags & AAC_CMD_BUF_WRITE) {
5205 			if (acp->abp != NULL)
5206 				ddi_rep_put8(acp->abh,
5207 				    (uint8_t *)acp->bp->b_un.b_addr,
5208 				    (uint8_t *)acp->abp, acp->bp->b_bcount,
5209 				    DDI_DEV_AUTOINCR);
5210 			(void) ddi_dma_sync(acp->buf_dma_handle, 0, 0,
5211 			    DDI_DMA_SYNC_FORDEV);
5212 		} else {
5213 			(void) ddi_dma_sync(acp->buf_dma_handle, 0, 0,
5214 			    DDI_DMA_SYNC_FORCPU);
5215 			if (aac_check_dma_handle(acp->buf_dma_handle) !=
5216 			    DDI_SUCCESS)
5217 				return (AACERR);
5218 			if (acp->abp != NULL)
5219 				ddi_rep_get8(acp->abh,
5220 				    (uint8_t *)acp->bp->b_un.b_addr,
5221 				    (uint8_t *)acp->abp, acp->bp->b_bcount,
5222 				    DDI_DEV_AUTOINCR);
5223 		}
5224 	}
5225 	return (AACOK);
5226 }
5227 
5228 /*
5229  * The following function comes from Adaptec:
5230  *
5231  * When driver sees a particular event that means containers are changed, it
5232  * will rescan containers. However a change may not be complete until some
5233  * other event is received. For example, creating or deleting an array will
5234  * incur as many as six AifEnConfigChange events which would generate six
5235  * container rescans. To diminish rescans, driver set a flag to wait for
5236  * another particular event. When sees that events come in, it will do rescan.
5237  */
5238 static int
5239 aac_handle_aif(struct aac_softstate *softs, struct aac_fib *fibp)
5240 {
5241 	ddi_acc_handle_t acc = softs->comm_space_acc_handle;
5242 	uint16_t fib_command;
5243 	struct aac_aif_command *aif;
5244 	int en_type;
5245 	int devcfg_needed;
5246 	int current, next;
5247 
5248 	fib_command = LE_16(fibp->Header.Command);
5249 	if (fib_command != AifRequest) {
5250 		cmn_err(CE_NOTE, "!Unknown command from controller: 0x%x",
5251 		    fib_command);
5252 		return (AACERR);
5253 	}
5254 
5255 	/* Update internal container state */
5256 	aif = (struct aac_aif_command *)&fibp->data[0];
5257 
5258 	AACDB_PRINT_AIF(softs, aif);
5259 	devcfg_needed = 0;
5260 	en_type = LE_32((uint32_t)aif->data.EN.type);
5261 
5262 	switch (LE_32((uint32_t)aif->command)) {
5263 	case AifCmdDriverNotify: {
5264 		int cid = LE_32(aif->data.EN.data.ECC.container[0]);
5265 
5266 		switch (en_type) {
5267 		case AifDenMorphComplete:
5268 		case AifDenVolumeExtendComplete:
5269 			if (softs->containers[cid].valid)
5270 				softs->devcfg_wait_on = AifEnConfigChange;
5271 			break;
5272 		}
5273 		if (softs->devcfg_wait_on == en_type)
5274 			devcfg_needed = 1;
5275 		break;
5276 	}
5277 
5278 	case AifCmdEventNotify:
5279 		switch (en_type) {
5280 		case AifEnAddContainer:
5281 		case AifEnDeleteContainer:
5282 			softs->devcfg_wait_on = AifEnConfigChange;
5283 			break;
5284 		case AifEnContainerChange:
5285 			if (!softs->devcfg_wait_on)
5286 				softs->devcfg_wait_on = AifEnConfigChange;
5287 			break;
5288 		case AifEnContainerEvent:
5289 			if (ddi_get32(acc, &aif-> \
5290 			    data.EN.data.ECE.eventType) == CT_PUP_MISSING_DRIVE)
5291 				devcfg_needed = 1;
5292 			break;
5293 		}
5294 		if (softs->devcfg_wait_on == en_type)
5295 			devcfg_needed = 1;
5296 		break;
5297 
5298 	case AifCmdJobProgress:
5299 		if (LE_32((uint32_t)aif->data.PR[0].jd.type) == AifJobCtrZero) {
5300 			int pr_status;
5301 			uint32_t pr_ftick, pr_ctick;
5302 
5303 			pr_status = LE_32((uint32_t)aif->data.PR[0].status);
5304 			pr_ctick = LE_32(aif->data.PR[0].currentTick);
5305 			pr_ftick = LE_32(aif->data.PR[0].finalTick);
5306 
5307 			if ((pr_ctick == pr_ftick) ||
5308 			    (pr_status == AifJobStsSuccess))
5309 				softs->devcfg_wait_on = AifEnContainerChange;
5310 			else if ((pr_ctick == 0) &&
5311 			    (pr_status == AifJobStsRunning))
5312 				softs->devcfg_wait_on = AifEnContainerChange;
5313 		}
5314 		break;
5315 	}
5316 
5317 	if (devcfg_needed)
5318 		(void) aac_probe_containers(softs);
5319 
5320 	/* Modify AIF contexts */
5321 	current = softs->aifq_idx;
5322 	next = (current + 1) % AAC_AIFQ_LENGTH;
5323 	if (next == 0) {
5324 		struct aac_fib_context *ctx;
5325 
5326 		softs->aifq_wrap = 1;
5327 		for (ctx = softs->fibctx; ctx; ctx = ctx->next) {
5328 			if (next == ctx->ctx_idx) {
5329 				ctx->ctx_filled = 1;
5330 			} else if (current == ctx->ctx_idx && ctx->ctx_filled) {
5331 				ctx->ctx_idx = next;
5332 				AACDB_PRINT(softs, CE_NOTE,
5333 				    "-- AIF queue(%x) overrun", ctx->unique);
5334 			}
5335 		}
5336 	}
5337 	softs->aifq_idx = next;
5338 
5339 	/* Wakeup applications */
5340 	cv_broadcast(&softs->aifv);
5341 	return (AACOK);
5342 }
5343 
5344 /*
5345  * Timeout recovery
5346  */
5347 static void
5348 aac_cmd_timeout(struct aac_softstate *softs)
5349 {
5350 	/*
5351 	 * Besides the firmware in unhealthy state, an overloaded
5352 	 * adapter may also incur pkt timeout.
5353 	 * There is a chance for an adapter with a slower IOP to take
5354 	 * longer than 60 seconds to process the commands, such as when
5355 	 * to perform IOs. So the adapter is doing a build on a RAID-5
5356 	 * while being required longer completion times should be
5357 	 * tolerated.
5358 	 */
5359 	if (aac_do_reset(softs) == AACOK) {
5360 		aac_abort_iocmds(softs, AAC_IOCMD_OUTSTANDING, NULL,
5361 		    CMD_RESET);
5362 		aac_start_waiting_io(softs);
5363 	} else {
5364 		/* Abort all waiting cmds when adapter is dead */
5365 		aac_abort_iocmds(softs, AAC_IOCMD_ALL, NULL,
5366 		    CMD_TIMEOUT);
5367 	}
5368 }
5369 
5370 /*
5371  * The following function comes from Adaptec:
5372  *
5373  * Time sync. command added to synchronize time with firmware every 30
5374  * minutes (required for correct AIF timestamps etc.)
5375  */
5376 static int
5377 aac_sync_tick(struct aac_softstate *softs)
5378 {
5379 	ddi_acc_handle_t acc = softs->sync_slot.fib_acc_handle;
5380 	struct aac_fib *fibp = softs->sync_slot.fibp;
5381 
5382 	ddi_put32(acc, (uint32_t *)&fibp->data[0], ddi_get_time());
5383 	return (aac_sync_fib(softs, SendHostTime, AAC_FIB_SIZEOF(uint32_t)));
5384 }
5385 
5386 static void
5387 aac_daemon(void *arg)
5388 {
5389 	struct aac_softstate *softs = (struct aac_softstate *)arg;
5390 	struct aac_cmd *acp;
5391 
5392 	DBCALLED(softs, 2);
5393 
5394 	mutex_enter(&softs->io_lock);
5395 	/* Check slot for timeout pkts */
5396 	aac_timebase += aac_tick;
5397 	for (acp = softs->q_busy.q_head; acp; acp = acp->next) {
5398 		if (acp->timeout) {
5399 			if (acp->timeout <= aac_timebase) {
5400 				aac_cmd_timeout(softs);
5401 				ddi_trigger_softintr(softs->softint_id);
5402 			}
5403 			break;
5404 		}
5405 	}
5406 
5407 	/* Time sync. with firmware every AAC_SYNC_TICK */
5408 	if (aac_sync_time <= aac_timebase) {
5409 		aac_sync_time = aac_timebase;
5410 		if (aac_sync_tick(softs) != AACOK)
5411 			aac_sync_time += aac_tick << 1; /* retry shortly */
5412 		else
5413 			aac_sync_time += AAC_SYNC_TICK;
5414 	}
5415 
5416 	if ((softs->state & AAC_STATE_RUN) && (softs->timeout_id != 0))
5417 		softs->timeout_id = timeout(aac_daemon, (void *)softs,
5418 		    (aac_tick * drv_usectohz(1000000)));
5419 	mutex_exit(&softs->io_lock);
5420 }
5421 
5422 /*
5423  * Architecture dependent functions
5424  */
5425 static int
5426 aac_rx_get_fwstatus(struct aac_softstate *softs)
5427 {
5428 	return (PCI_MEM_GET32(softs, AAC_OMR0));
5429 }
5430 
5431 static int
5432 aac_rx_get_mailbox(struct aac_softstate *softs, int mb)
5433 {
5434 	return (PCI_MEM_GET32(softs, AAC_RX_MAILBOX + mb * 4));
5435 }
5436 
5437 static void
5438 aac_rx_set_mailbox(struct aac_softstate *softs, uint32_t cmd,
5439     uint32_t arg0, uint32_t arg1, uint32_t arg2, uint32_t arg3)
5440 {
5441 	PCI_MEM_PUT32(softs, AAC_RX_MAILBOX, cmd);
5442 	PCI_MEM_PUT32(softs, AAC_RX_MAILBOX + 4, arg0);
5443 	PCI_MEM_PUT32(softs, AAC_RX_MAILBOX + 8, arg1);
5444 	PCI_MEM_PUT32(softs, AAC_RX_MAILBOX + 12, arg2);
5445 	PCI_MEM_PUT32(softs, AAC_RX_MAILBOX + 16, arg3);
5446 }
5447 
5448 static int
5449 aac_rkt_get_fwstatus(struct aac_softstate *softs)
5450 {
5451 	return (PCI_MEM_GET32(softs, AAC_OMR0));
5452 }
5453 
5454 static int
5455 aac_rkt_get_mailbox(struct aac_softstate *softs, int mb)
5456 {
5457 	return (PCI_MEM_GET32(softs, AAC_RKT_MAILBOX + mb *4));
5458 }
5459 
5460 static void
5461 aac_rkt_set_mailbox(struct aac_softstate *softs, uint32_t cmd,
5462     uint32_t arg0, uint32_t arg1, uint32_t arg2, uint32_t arg3)
5463 {
5464 	PCI_MEM_PUT32(softs, AAC_RKT_MAILBOX, cmd);
5465 	PCI_MEM_PUT32(softs, AAC_RKT_MAILBOX + 4, arg0);
5466 	PCI_MEM_PUT32(softs, AAC_RKT_MAILBOX + 8, arg1);
5467 	PCI_MEM_PUT32(softs, AAC_RKT_MAILBOX + 12, arg2);
5468 	PCI_MEM_PUT32(softs, AAC_RKT_MAILBOX + 16, arg3);
5469 }
5470 
5471 /*
5472  * cb_ops functions
5473  */
5474 static int
5475 aac_open(dev_t *devp, int flag, int otyp, cred_t *cred)
5476 {
5477 	struct aac_softstate *softs;
5478 	int minor0, minor;
5479 	int instance;
5480 
5481 	DBCALLED(NULL, 2);
5482 
5483 	if (otyp != OTYP_BLK && otyp != OTYP_CHR)
5484 		return (EINVAL);
5485 
5486 	minor0 = getminor(*devp);
5487 	minor = AAC_SCSA_MINOR(minor0);
5488 
5489 	if (AAC_IS_SCSA_NODE(minor))
5490 		return (scsi_hba_open(devp, flag, otyp, cred));
5491 
5492 	instance = MINOR2INST(minor0);
5493 	if (instance >= AAC_MAX_ADAPTERS)
5494 		return (ENXIO);
5495 
5496 	softs = ddi_get_soft_state(aac_softstatep, instance);
5497 	if (softs == NULL)
5498 		return (ENXIO);
5499 
5500 	return (0);
5501 }
5502 
5503 /*ARGSUSED*/
5504 static int
5505 aac_close(dev_t dev, int flag, int otyp, cred_t *cred)
5506 {
5507 	int minor0, minor;
5508 	int instance;
5509 
5510 	DBCALLED(NULL, 2);
5511 
5512 	if (otyp != OTYP_BLK && otyp != OTYP_CHR)
5513 		return (EINVAL);
5514 
5515 	minor0 = getminor(dev);
5516 	minor = AAC_SCSA_MINOR(minor0);
5517 
5518 	if (AAC_IS_SCSA_NODE(minor))
5519 		return (scsi_hba_close(dev, flag, otyp, cred));
5520 
5521 	instance = MINOR2INST(minor0);
5522 	if (instance >= AAC_MAX_ADAPTERS)
5523 		return (ENXIO);
5524 
5525 	return (0);
5526 }
5527 
5528 static int
5529 aac_ioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *cred_p,
5530     int *rval_p)
5531 {
5532 	struct aac_softstate *softs;
5533 	int minor0, minor;
5534 	int instance;
5535 
5536 	DBCALLED(NULL, 2);
5537 
5538 	if (drv_priv(cred_p) != 0)
5539 		return (EPERM);
5540 
5541 	minor0 = getminor(dev);
5542 	minor = AAC_SCSA_MINOR(minor0);
5543 
5544 	if (AAC_IS_SCSA_NODE(minor))
5545 		return (scsi_hba_ioctl(dev, cmd, arg, flag, cred_p, rval_p));
5546 
5547 	instance = MINOR2INST(minor0);
5548 	if (instance < AAC_MAX_ADAPTERS) {
5549 		softs = ddi_get_soft_state(aac_softstatep, instance);
5550 		return (aac_do_ioctl(softs, dev, cmd, arg, flag));
5551 	}
5552 	return (ENXIO);
5553 }
5554 
5555 /*
5556  * The IO fault service error handling callback function
5557  */
5558 /*ARGSUSED*/
5559 static int
5560 aac_fm_error_cb(dev_info_t *dip, ddi_fm_error_t *err, const void *impl_data)
5561 {
5562 	/*
5563 	 * as the driver can always deal with an error in any dma or
5564 	 * access handle, we can just return the fme_status value.
5565 	 */
5566 	pci_ereport_post(dip, err, NULL);
5567 	return (err->fme_status);
5568 }
5569 
5570 /*
5571  * aac_fm_init - initialize fma capabilities and register with IO
5572  *               fault services.
5573  */
5574 static void
5575 aac_fm_init(struct aac_softstate *softs)
5576 {
5577 	/*
5578 	 * Need to change iblock to priority for new MSI intr
5579 	 */
5580 	ddi_iblock_cookie_t fm_ibc;
5581 
5582 	/* Only register with IO Fault Services if we have some capability */
5583 	if (softs->fm_capabilities) {
5584 		/* Adjust access and dma attributes for FMA */
5585 		aac_acc_attr.devacc_attr_access = DDI_FLAGERR_ACC;
5586 		softs->buf_dma_attr.dma_attr_flags = DDI_DMA_FLAGERR;
5587 		softs->addr_dma_attr.dma_attr_flags = DDI_DMA_FLAGERR;
5588 
5589 		/*
5590 		 * Register capabilities with IO Fault Services.
5591 		 * fm_capabilities will be updated to indicate
5592 		 * capabilities actually supported (not requested.)
5593 		 */
5594 		ddi_fm_init(softs->devinfo_p, &softs->fm_capabilities, &fm_ibc);
5595 
5596 		/*
5597 		 * Initialize pci ereport capabilities if ereport
5598 		 * capable (should always be.)
5599 		 */
5600 		if (DDI_FM_EREPORT_CAP(softs->fm_capabilities) ||
5601 		    DDI_FM_ERRCB_CAP(softs->fm_capabilities)) {
5602 			pci_ereport_setup(softs->devinfo_p);
5603 		}
5604 
5605 		/*
5606 		 * Register error callback if error callback capable.
5607 		 */
5608 		if (DDI_FM_ERRCB_CAP(softs->fm_capabilities)) {
5609 			ddi_fm_handler_register(softs->devinfo_p,
5610 			    aac_fm_error_cb, (void *) softs);
5611 		}
5612 	} else {
5613 		/* Clear FMA if no capabilities */
5614 		aac_acc_attr.devacc_attr_access = DDI_DEFAULT_ACC;
5615 		softs->buf_dma_attr.dma_attr_flags = 0;
5616 		softs->addr_dma_attr.dma_attr_flags = 0;
5617 	}
5618 }
5619 
5620 /*
5621  * aac_fm_fini - Releases fma capabilities and un-registers with IO
5622  *               fault services.
5623  */
5624 static void
5625 aac_fm_fini(struct aac_softstate *softs)
5626 {
5627 	/* Only unregister FMA capabilities if registered */
5628 	if (softs->fm_capabilities) {
5629 		/*
5630 		 * Un-register error callback if error callback capable.
5631 		 */
5632 		if (DDI_FM_ERRCB_CAP(softs->fm_capabilities)) {
5633 			ddi_fm_handler_unregister(softs->devinfo_p);
5634 		}
5635 
5636 		/*
5637 		 * Release any resources allocated by pci_ereport_setup()
5638 		 */
5639 		if (DDI_FM_EREPORT_CAP(softs->fm_capabilities) ||
5640 		    DDI_FM_ERRCB_CAP(softs->fm_capabilities)) {
5641 			pci_ereport_teardown(softs->devinfo_p);
5642 		}
5643 
5644 		/* Unregister from IO Fault Services */
5645 		ddi_fm_fini(softs->devinfo_p);
5646 	}
5647 }
5648 
5649 int
5650 aac_check_acc_handle(ddi_acc_handle_t handle)
5651 {
5652 	ddi_fm_error_t de;
5653 
5654 	ddi_fm_acc_err_get(handle, &de, DDI_FME_VERSION);
5655 	return (de.fme_status);
5656 }
5657 
5658 int
5659 aac_check_dma_handle(ddi_dma_handle_t handle)
5660 {
5661 	ddi_fm_error_t de;
5662 
5663 	ddi_fm_dma_err_get(handle, &de, DDI_FME_VERSION);
5664 	return (de.fme_status);
5665 }
5666 
5667 void
5668 aac_fm_ereport(struct aac_softstate *softs, char *detail)
5669 {
5670 	uint64_t ena;
5671 	char buf[FM_MAX_CLASS];
5672 
5673 	(void) snprintf(buf, FM_MAX_CLASS, "%s.%s", DDI_FM_DEVICE, detail);
5674 	ena = fm_ena_generate(0, FM_ENA_FMT1);
5675 	if (DDI_FM_EREPORT_CAP(softs->fm_capabilities)) {
5676 		ddi_fm_ereport_post(softs->devinfo_p, buf, ena, DDI_NOSLEEP,
5677 		    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERSION, NULL);
5678 	}
5679 }
5680 
5681 #ifdef DEBUG
5682 
5683 /* -------------------------debug aid functions-------------------------- */
5684 
5685 #define	AAC_FIB_CMD_KEY_STRINGS \
5686 	TestCommandResponse, "TestCommandResponse", \
5687 	TestAdapterCommand, "TestAdapterCommand", \
5688 	LastTestCommand, "LastTestCommand", \
5689 	ReinitHostNormCommandQueue, "ReinitHostNormCommandQueue", \
5690 	ReinitHostHighCommandQueue, "ReinitHostHighCommandQueue", \
5691 	ReinitHostHighRespQueue, "ReinitHostHighRespQueue", \
5692 	ReinitHostNormRespQueue, "ReinitHostNormRespQueue", \
5693 	ReinitAdapNormCommandQueue, "ReinitAdapNormCommandQueue", \
5694 	ReinitAdapHighCommandQueue, "ReinitAdapHighCommandQueue", \
5695 	ReinitAdapHighRespQueue, "ReinitAdapHighRespQueue", \
5696 	ReinitAdapNormRespQueue, "ReinitAdapNormRespQueue", \
5697 	InterfaceShutdown, "InterfaceShutdown", \
5698 	DmaCommandFib, "DmaCommandFib", \
5699 	StartProfile, "StartProfile", \
5700 	TermProfile, "TermProfile", \
5701 	SpeedTest, "SpeedTest", \
5702 	TakeABreakPt, "TakeABreakPt", \
5703 	RequestPerfData, "RequestPerfData", \
5704 	SetInterruptDefTimer, "SetInterruptDefTimer", \
5705 	SetInterruptDefCount, "SetInterruptDefCount", \
5706 	GetInterruptDefStatus, "GetInterruptDefStatus", \
5707 	LastCommCommand, "LastCommCommand", \
5708 	NuFileSystem, "NuFileSystem", \
5709 	UFS, "UFS", \
5710 	HostFileSystem, "HostFileSystem", \
5711 	LastFileSystemCommand, "LastFileSystemCommand", \
5712 	ContainerCommand, "ContainerCommand", \
5713 	ContainerCommand64, "ContainerCommand64", \
5714 	ClusterCommand, "ClusterCommand", \
5715 	ScsiPortCommand, "ScsiPortCommand", \
5716 	ScsiPortCommandU64, "ScsiPortCommandU64", \
5717 	AifRequest, "AifRequest", \
5718 	CheckRevision, "CheckRevision", \
5719 	FsaHostShutdown, "FsaHostShutdown", \
5720 	RequestAdapterInfo, "RequestAdapterInfo", \
5721 	IsAdapterPaused, "IsAdapterPaused", \
5722 	SendHostTime, "SendHostTime", \
5723 	LastMiscCommand, "LastMiscCommand"
5724 
5725 #define	AAC_CTVM_SUBCMD_KEY_STRINGS \
5726 	VM_Null, "VM_Null", \
5727 	VM_NameServe, "VM_NameServe", \
5728 	VM_ContainerConfig, "VM_ContainerConfig", \
5729 	VM_Ioctl, "VM_Ioctl", \
5730 	VM_FilesystemIoctl, "VM_FilesystemIoctl", \
5731 	VM_CloseAll, "VM_CloseAll", \
5732 	VM_CtBlockRead, "VM_CtBlockRead", \
5733 	VM_CtBlockWrite, "VM_CtBlockWrite", \
5734 	VM_SliceBlockRead, "VM_SliceBlockRead", \
5735 	VM_SliceBlockWrite, "VM_SliceBlockWrite", \
5736 	VM_DriveBlockRead, "VM_DriveBlockRead", \
5737 	VM_DriveBlockWrite, "VM_DriveBlockWrite", \
5738 	VM_EnclosureMgt, "VM_EnclosureMgt", \
5739 	VM_Unused, "VM_Unused", \
5740 	VM_CtBlockVerify, "VM_CtBlockVerify", \
5741 	VM_CtPerf, "VM_CtPerf", \
5742 	VM_CtBlockRead64, "VM_CtBlockRead64", \
5743 	VM_CtBlockWrite64, "VM_CtBlockWrite64", \
5744 	VM_CtBlockVerify64, "VM_CtBlockVerify64", \
5745 	VM_CtHostRead64, "VM_CtHostRead64", \
5746 	VM_CtHostWrite64, "VM_CtHostWrite64", \
5747 	VM_NameServe64, "VM_NameServe64"
5748 
5749 #define	AAC_CT_SUBCMD_KEY_STRINGS \
5750 	CT_Null, "CT_Null", \
5751 	CT_GET_SLICE_COUNT, "CT_GET_SLICE_COUNT", \
5752 	CT_GET_PARTITION_COUNT, "CT_GET_PARTITION_COUNT", \
5753 	CT_GET_PARTITION_INFO, "CT_GET_PARTITION_INFO", \
5754 	CT_GET_CONTAINER_COUNT, "CT_GET_CONTAINER_COUNT", \
5755 	CT_GET_CONTAINER_INFO_OLD, "CT_GET_CONTAINER_INFO_OLD", \
5756 	CT_WRITE_MBR, "CT_WRITE_MBR", \
5757 	CT_WRITE_PARTITION, "CT_WRITE_PARTITION", \
5758 	CT_UPDATE_PARTITION, "CT_UPDATE_PARTITION", \
5759 	CT_UNLOAD_CONTAINER, "CT_UNLOAD_CONTAINER", \
5760 	CT_CONFIG_SINGLE_PRIMARY, "CT_CONFIG_SINGLE_PRIMARY", \
5761 	CT_READ_CONFIG_AGE, "CT_READ_CONFIG_AGE", \
5762 	CT_WRITE_CONFIG_AGE, "CT_WRITE_CONFIG_AGE", \
5763 	CT_READ_SERIAL_NUMBER, "CT_READ_SERIAL_NUMBER", \
5764 	CT_ZERO_PAR_ENTRY, "CT_ZERO_PAR_ENTRY", \
5765 	CT_READ_MBR, "CT_READ_MBR", \
5766 	CT_READ_PARTITION, "CT_READ_PARTITION", \
5767 	CT_DESTROY_CONTAINER, "CT_DESTROY_CONTAINER", \
5768 	CT_DESTROY2_CONTAINER, "CT_DESTROY2_CONTAINER", \
5769 	CT_SLICE_SIZE, "CT_SLICE_SIZE", \
5770 	CT_CHECK_CONFLICTS, "CT_CHECK_CONFLICTS", \
5771 	CT_MOVE_CONTAINER, "CT_MOVE_CONTAINER", \
5772 	CT_READ_LAST_DRIVE, "CT_READ_LAST_DRIVE", \
5773 	CT_WRITE_LAST_DRIVE, "CT_WRITE_LAST_DRIVE", \
5774 	CT_UNMIRROR, "CT_UNMIRROR", \
5775 	CT_MIRROR_DELAY, "CT_MIRROR_DELAY", \
5776 	CT_GEN_MIRROR, "CT_GEN_MIRROR", \
5777 	CT_GEN_MIRROR2, "CT_GEN_MIRROR2", \
5778 	CT_TEST_CONTAINER, "CT_TEST_CONTAINER", \
5779 	CT_MOVE2, "CT_MOVE2", \
5780 	CT_SPLIT, "CT_SPLIT", \
5781 	CT_SPLIT2, "CT_SPLIT2", \
5782 	CT_SPLIT_BROKEN, "CT_SPLIT_BROKEN", \
5783 	CT_SPLIT_BROKEN2, "CT_SPLIT_BROKEN2", \
5784 	CT_RECONFIG, "CT_RECONFIG", \
5785 	CT_BREAK2, "CT_BREAK2", \
5786 	CT_BREAK, "CT_BREAK", \
5787 	CT_MERGE2, "CT_MERGE2", \
5788 	CT_MERGE, "CT_MERGE", \
5789 	CT_FORCE_ERROR, "CT_FORCE_ERROR", \
5790 	CT_CLEAR_ERROR, "CT_CLEAR_ERROR", \
5791 	CT_ASSIGN_FAILOVER, "CT_ASSIGN_FAILOVER", \
5792 	CT_CLEAR_FAILOVER, "CT_CLEAR_FAILOVER", \
5793 	CT_GET_FAILOVER_DATA, "CT_GET_FAILOVER_DATA", \
5794 	CT_VOLUME_ADD, "CT_VOLUME_ADD", \
5795 	CT_VOLUME_ADD2, "CT_VOLUME_ADD2", \
5796 	CT_MIRROR_STATUS, "CT_MIRROR_STATUS", \
5797 	CT_COPY_STATUS, "CT_COPY_STATUS", \
5798 	CT_COPY, "CT_COPY", \
5799 	CT_UNLOCK_CONTAINER, "CT_UNLOCK_CONTAINER", \
5800 	CT_LOCK_CONTAINER, "CT_LOCK_CONTAINER", \
5801 	CT_MAKE_READ_ONLY, "CT_MAKE_READ_ONLY", \
5802 	CT_MAKE_READ_WRITE, "CT_MAKE_READ_WRITE", \
5803 	CT_CLEAN_DEAD, "CT_CLEAN_DEAD", \
5804 	CT_ABORT_MIRROR_COMMAND, "CT_ABORT_MIRROR_COMMAND", \
5805 	CT_SET, "CT_SET", \
5806 	CT_GET, "CT_GET", \
5807 	CT_GET_NVLOG_ENTRY, "CT_GET_NVLOG_ENTRY", \
5808 	CT_GET_DELAY, "CT_GET_DELAY", \
5809 	CT_ZERO_CONTAINER_SPACE, "CT_ZERO_CONTAINER_SPACE", \
5810 	CT_GET_ZERO_STATUS, "CT_GET_ZERO_STATUS", \
5811 	CT_SCRUB, "CT_SCRUB", \
5812 	CT_GET_SCRUB_STATUS, "CT_GET_SCRUB_STATUS", \
5813 	CT_GET_SLICE_INFO, "CT_GET_SLICE_INFO", \
5814 	CT_GET_SCSI_METHOD, "CT_GET_SCSI_METHOD", \
5815 	CT_PAUSE_IO, "CT_PAUSE_IO", \
5816 	CT_RELEASE_IO, "CT_RELEASE_IO", \
5817 	CT_SCRUB2, "CT_SCRUB2", \
5818 	CT_MCHECK, "CT_MCHECK", \
5819 	CT_CORRUPT, "CT_CORRUPT", \
5820 	CT_GET_TASK_COUNT, "CT_GET_TASK_COUNT", \
5821 	CT_PROMOTE, "CT_PROMOTE", \
5822 	CT_SET_DEAD, "CT_SET_DEAD", \
5823 	CT_CONTAINER_OPTIONS, "CT_CONTAINER_OPTIONS", \
5824 	CT_GET_NV_PARAM, "CT_GET_NV_PARAM", \
5825 	CT_GET_PARAM, "CT_GET_PARAM", \
5826 	CT_NV_PARAM_SIZE, "CT_NV_PARAM_SIZE", \
5827 	CT_COMMON_PARAM_SIZE, "CT_COMMON_PARAM_SIZE", \
5828 	CT_PLATFORM_PARAM_SIZE, "CT_PLATFORM_PARAM_SIZE", \
5829 	CT_SET_NV_PARAM, "CT_SET_NV_PARAM", \
5830 	CT_ABORT_SCRUB, "CT_ABORT_SCRUB", \
5831 	CT_GET_SCRUB_ERROR, "CT_GET_SCRUB_ERROR", \
5832 	CT_LABEL_CONTAINER, "CT_LABEL_CONTAINER", \
5833 	CT_CONTINUE_DATA, "CT_CONTINUE_DATA", \
5834 	CT_STOP_DATA, "CT_STOP_DATA", \
5835 	CT_GET_PARTITION_TABLE, "CT_GET_PARTITION_TABLE", \
5836 	CT_GET_DISK_PARTITIONS, "CT_GET_DISK_PARTITIONS", \
5837 	CT_GET_MISC_STATUS, "CT_GET_MISC_STATUS", \
5838 	CT_GET_CONTAINER_PERF_INFO, "CT_GET_CONTAINER_PERF_INFO", \
5839 	CT_GET_TIME, "CT_GET_TIME", \
5840 	CT_READ_DATA, "CT_READ_DATA", \
5841 	CT_CTR, "CT_CTR", \
5842 	CT_CTL, "CT_CTL", \
5843 	CT_DRAINIO, "CT_DRAINIO", \
5844 	CT_RELEASEIO, "CT_RELEASEIO", \
5845 	CT_GET_NVRAM, "CT_GET_NVRAM", \
5846 	CT_GET_MEMORY, "CT_GET_MEMORY", \
5847 	CT_PRINT_CT_LOG, "CT_PRINT_CT_LOG", \
5848 	CT_ADD_LEVEL, "CT_ADD_LEVEL", \
5849 	CT_NV_ZERO, "CT_NV_ZERO", \
5850 	CT_READ_SIGNATURE, "CT_READ_SIGNATURE", \
5851 	CT_THROTTLE_ON, "CT_THROTTLE_ON", \
5852 	CT_THROTTLE_OFF, "CT_THROTTLE_OFF", \
5853 	CT_GET_THROTTLE_STATS, "CT_GET_THROTTLE_STATS", \
5854 	CT_MAKE_SNAPSHOT, "CT_MAKE_SNAPSHOT", \
5855 	CT_REMOVE_SNAPSHOT, "CT_REMOVE_SNAPSHOT", \
5856 	CT_WRITE_USER_FLAGS, "CT_WRITE_USER_FLAGS", \
5857 	CT_READ_USER_FLAGS, "CT_READ_USER_FLAGS", \
5858 	CT_MONITOR, "CT_MONITOR", \
5859 	CT_GEN_MORPH, "CT_GEN_MORPH", \
5860 	CT_GET_SNAPSHOT_INFO, "CT_GET_SNAPSHOT_INFO", \
5861 	CT_CACHE_SET, "CT_CACHE_SET", \
5862 	CT_CACHE_STAT, "CT_CACHE_STAT", \
5863 	CT_TRACE_START, "CT_TRACE_START", \
5864 	CT_TRACE_STOP, "CT_TRACE_STOP", \
5865 	CT_TRACE_ENABLE, "CT_TRACE_ENABLE", \
5866 	CT_TRACE_DISABLE, "CT_TRACE_DISABLE", \
5867 	CT_FORCE_CORE_DUMP, "CT_FORCE_CORE_DUMP", \
5868 	CT_SET_SERIAL_NUMBER, "CT_SET_SERIAL_NUMBER", \
5869 	CT_RESET_SERIAL_NUMBER, "CT_RESET_SERIAL_NUMBER", \
5870 	CT_ENABLE_RAID5, "CT_ENABLE_RAID5", \
5871 	CT_CLEAR_VALID_DUMP_FLAG, "CT_CLEAR_VALID_DUMP_FLAG", \
5872 	CT_GET_MEM_STATS, "CT_GET_MEM_STATS", \
5873 	CT_GET_CORE_SIZE, "CT_GET_CORE_SIZE", \
5874 	CT_CREATE_CONTAINER_OLD, "CT_CREATE_CONTAINER_OLD", \
5875 	CT_STOP_DUMPS, "CT_STOP_DUMPS", \
5876 	CT_PANIC_ON_TAKE_A_BREAK, "CT_PANIC_ON_TAKE_A_BREAK", \
5877 	CT_GET_CACHE_STATS, "CT_GET_CACHE_STATS", \
5878 	CT_MOVE_PARTITION, "CT_MOVE_PARTITION", \
5879 	CT_FLUSH_CACHE, "CT_FLUSH_CACHE", \
5880 	CT_READ_NAME, "CT_READ_NAME", \
5881 	CT_WRITE_NAME, "CT_WRITE_NAME", \
5882 	CT_TOSS_CACHE, "CT_TOSS_CACHE", \
5883 	CT_LOCK_DRAINIO, "CT_LOCK_DRAINIO", \
5884 	CT_CONTAINER_OFFLINE, "CT_CONTAINER_OFFLINE", \
5885 	CT_SET_CACHE_SIZE, "CT_SET_CACHE_SIZE", \
5886 	CT_CLEAN_SHUTDOWN_STATUS, "CT_CLEAN_SHUTDOWN_STATUS", \
5887 	CT_CLEAR_DISKLOG_ON_DISK, "CT_CLEAR_DISKLOG_ON_DISK", \
5888 	CT_CLEAR_ALL_DISKLOG, "CT_CLEAR_ALL_DISKLOG", \
5889 	CT_CACHE_FAVOR, "CT_CACHE_FAVOR", \
5890 	CT_READ_PASSTHRU_MBR, "CT_READ_PASSTHRU_MBR", \
5891 	CT_SCRUB_NOFIX, "CT_SCRUB_NOFIX", \
5892 	CT_SCRUB2_NOFIX, "CT_SCRUB2_NOFIX", \
5893 	CT_FLUSH, "CT_FLUSH", \
5894 	CT_REBUILD, "CT_REBUILD", \
5895 	CT_FLUSH_CONTAINER, "CT_FLUSH_CONTAINER", \
5896 	CT_RESTART, "CT_RESTART", \
5897 	CT_GET_CONFIG_STATUS, "CT_GET_CONFIG_STATUS", \
5898 	CT_TRACE_FLAG, "CT_TRACE_FLAG", \
5899 	CT_RESTART_MORPH, "CT_RESTART_MORPH", \
5900 	CT_GET_TRACE_INFO, "CT_GET_TRACE_INFO", \
5901 	CT_GET_TRACE_ITEM, "CT_GET_TRACE_ITEM", \
5902 	CT_COMMIT_CONFIG, "CT_COMMIT_CONFIG", \
5903 	CT_CONTAINER_EXISTS, "CT_CONTAINER_EXISTS", \
5904 	CT_GET_SLICE_FROM_DEVT, "CT_GET_SLICE_FROM_DEVT", \
5905 	CT_OPEN_READ_WRITE, "CT_OPEN_READ_WRITE", \
5906 	CT_WRITE_MEMORY_BLOCK, "CT_WRITE_MEMORY_BLOCK", \
5907 	CT_GET_CACHE_PARAMS, "CT_GET_CACHE_PARAMS", \
5908 	CT_CRAZY_CACHE, "CT_CRAZY_CACHE", \
5909 	CT_GET_PROFILE_STRUCT, "CT_GET_PROFILE_STRUCT", \
5910 	CT_SET_IO_TRACE_FLAG, "CT_SET_IO_TRACE_FLAG", \
5911 	CT_GET_IO_TRACE_STRUCT, "CT_GET_IO_TRACE_STRUCT", \
5912 	CT_CID_TO_64BITS_UID, "CT_CID_TO_64BITS_UID", \
5913 	CT_64BITS_UID_TO_CID, "CT_64BITS_UID_TO_CID", \
5914 	CT_PAR_TO_64BITS_UID, "CT_PAR_TO_64BITS_UID", \
5915 	CT_CID_TO_32BITS_UID, "CT_CID_TO_32BITS_UID", \
5916 	CT_32BITS_UID_TO_CID, "CT_32BITS_UID_TO_CID", \
5917 	CT_PAR_TO_32BITS_UID, "CT_PAR_TO_32BITS_UID", \
5918 	CT_SET_FAILOVER_OPTION, "CT_SET_FAILOVER_OPTION", \
5919 	CT_GET_FAILOVER_OPTION, "CT_GET_FAILOVER_OPTION", \
5920 	CT_STRIPE_ADD2, "CT_STRIPE_ADD2", \
5921 	CT_CREATE_VOLUME_SET, "CT_CREATE_VOLUME_SET", \
5922 	CT_CREATE_STRIPE_SET, "CT_CREATE_STRIPE_SET", \
5923 	CT_VERIFY_CONTAINER, "CT_VERIFY_CONTAINER", \
5924 	CT_IS_CONTAINER_DEAD, "CT_IS_CONTAINER_DEAD", \
5925 	CT_GET_CONTAINER_OPTION, "CT_GET_CONTAINER_OPTION", \
5926 	CT_GET_SNAPSHOT_UNUSED_STRUCT, "CT_GET_SNAPSHOT_UNUSED_STRUCT", \
5927 	CT_CLEAR_SNAPSHOT_UNUSED_STRUCT, "CT_CLEAR_SNAPSHOT_UNUSED_STRUCT", \
5928 	CT_GET_CONTAINER_INFO, "CT_GET_CONTAINER_INFO", \
5929 	CT_CREATE_CONTAINER, "CT_CREATE_CONTAINER", \
5930 	CT_CHANGE_CREATIONINFO, "CT_CHANGE_CREATIONINFO", \
5931 	CT_CHECK_CONFLICT_UID, "CT_CHECK_CONFLICT_UID", \
5932 	CT_CONTAINER_UID_CHECK, "CT_CONTAINER_UID_CHECK", \
5933 	CT_IS_CONTAINER_MEATADATA_STANDARD, \
5934 	    "CT_IS_CONTAINER_MEATADATA_STANDARD", \
5935 	CT_IS_SLICE_METADATA_STANDARD, "CT_IS_SLICE_METADATA_STANDARD", \
5936 	CT_GET_IMPORT_COUNT, "CT_GET_IMPORT_COUNT", \
5937 	CT_CANCEL_ALL_IMPORTS, "CT_CANCEL_ALL_IMPORTS", \
5938 	CT_GET_IMPORT_INFO, "CT_GET_IMPORT_INFO", \
5939 	CT_IMPORT_ARRAY, "CT_IMPORT_ARRAY", \
5940 	CT_GET_LOG_SIZE, "CT_GET_LOG_SIZE", \
5941 	CT_ALARM_GET_STATE, "CT_ALARM_GET_STATE", \
5942 	CT_ALARM_SET_STATE, "CT_ALARM_SET_STATE", \
5943 	CT_ALARM_ON_OFF, "CT_ALARM_ON_OFF", \
5944 	CT_GET_EE_OEM_ID, "CT_GET_EE_OEM_ID", \
5945 	CT_GET_PPI_HEADERS, "CT_GET_PPI_HEADERS", \
5946 	CT_GET_PPI_DATA, "CT_GET_PPI_DATA", \
5947 	CT_GET_PPI_ENTRIES, "CT_GET_PPI_ENTRIES", \
5948 	CT_DELETE_PPI_BUNDLE, "CT_DELETE_PPI_BUNDLE", \
5949 	CT_GET_PARTITION_TABLE_2, "CT_GET_PARTITION_TABLE_2", \
5950 	CT_GET_PARTITION_INFO_2, "CT_GET_PARTITION_INFO_2", \
5951 	CT_GET_DISK_PARTITIONS_2, "CT_GET_DISK_PARTITIONS_2", \
5952 	CT_QUIESCE_ADAPTER, "CT_QUIESCE_ADAPTER", \
5953 	CT_CLEAR_PPI_TABLE, "CT_CLEAR_PPI_TABLE"
5954 
5955 #define	AAC_CL_SUBCMD_KEY_STRINGS \
5956 	CL_NULL, "CL_NULL", \
5957 	DS_INIT, "DS_INIT", \
5958 	DS_RESCAN, "DS_RESCAN", \
5959 	DS_CREATE, "DS_CREATE", \
5960 	DS_DELETE, "DS_DELETE", \
5961 	DS_ADD_DISK, "DS_ADD_DISK", \
5962 	DS_REMOVE_DISK, "DS_REMOVE_DISK", \
5963 	DS_MOVE_DISK, "DS_MOVE_DISK", \
5964 	DS_TAKE_OWNERSHIP, "DS_TAKE_OWNERSHIP", \
5965 	DS_RELEASE_OWNERSHIP, "DS_RELEASE_OWNERSHIP", \
5966 	DS_FORCE_OWNERSHIP, "DS_FORCE_OWNERSHIP", \
5967 	DS_GET_DISK_SET_PARAM, "DS_GET_DISK_SET_PARAM", \
5968 	DS_GET_DRIVE_PARAM, "DS_GET_DRIVE_PARAM", \
5969 	DS_GET_SLICE_PARAM, "DS_GET_SLICE_PARAM", \
5970 	DS_GET_DISK_SETS, "DS_GET_DISK_SETS", \
5971 	DS_GET_DRIVES, "DS_GET_DRIVES", \
5972 	DS_SET_DISK_SET_PARAM, "DS_SET_DISK_SET_PARAM", \
5973 	DS_ONLINE, "DS_ONLINE", \
5974 	DS_OFFLINE, "DS_OFFLINE", \
5975 	DS_ONLINE_CONTAINERS, "DS_ONLINE_CONTAINERS", \
5976 	DS_FSAPRINT, "DS_FSAPRINT", \
5977 	CL_CFG_SET_HOST_IDS, "CL_CFG_SET_HOST_IDS", \
5978 	CL_CFG_SET_PARTNER_HOST_IDS, "CL_CFG_SET_PARTNER_HOST_IDS", \
5979 	CL_CFG_GET_CLUSTER_CONFIG, "CL_CFG_GET_CLUSTER_CONFIG", \
5980 	CC_CLI_CLEAR_MESSAGE_BUFFER, "CC_CLI_CLEAR_MESSAGE_BUFFER", \
5981 	CC_SRV_CLEAR_MESSAGE_BUFFER, "CC_SRV_CLEAR_MESSAGE_BUFFER", \
5982 	CC_CLI_SHOW_MESSAGE_BUFFER, "CC_CLI_SHOW_MESSAGE_BUFFER", \
5983 	CC_SRV_SHOW_MESSAGE_BUFFER, "CC_SRV_SHOW_MESSAGE_BUFFER", \
5984 	CC_CLI_SEND_MESSAGE, "CC_CLI_SEND_MESSAGE", \
5985 	CC_SRV_SEND_MESSAGE, "CC_SRV_SEND_MESSAGE", \
5986 	CC_CLI_GET_MESSAGE, "CC_CLI_GET_MESSAGE", \
5987 	CC_SRV_GET_MESSAGE, "CC_SRV_GET_MESSAGE", \
5988 	CC_SEND_TEST_MESSAGE, "CC_SEND_TEST_MESSAGE", \
5989 	CC_GET_BUSINFO, "CC_GET_BUSINFO", \
5990 	CC_GET_PORTINFO, "CC_GET_PORTINFO", \
5991 	CC_GET_NAMEINFO, "CC_GET_NAMEINFO", \
5992 	CC_GET_CONFIGINFO, "CC_GET_CONFIGINFO", \
5993 	CQ_QUORUM_OP, "CQ_QUORUM_OP"
5994 
5995 #define	AAC_AIF_SUBCMD_KEY_STRINGS \
5996 	AifCmdEventNotify, "AifCmdEventNotify", \
5997 	AifCmdJobProgress, "AifCmdJobProgress", \
5998 	AifCmdAPIReport, "AifCmdAPIReport", \
5999 	AifCmdDriverNotify, "AifCmdDriverNotify", \
6000 	AifReqJobList, "AifReqJobList", \
6001 	AifReqJobsForCtr, "AifReqJobsForCtr", \
6002 	AifReqJobsForScsi, "AifReqJobsForScsi", \
6003 	AifReqJobReport, "AifReqJobReport", \
6004 	AifReqTerminateJob, "AifReqTerminateJob", \
6005 	AifReqSuspendJob, "AifReqSuspendJob", \
6006 	AifReqResumeJob, "AifReqResumeJob", \
6007 	AifReqSendAPIReport, "AifReqSendAPIReport", \
6008 	AifReqAPIJobStart, "AifReqAPIJobStart", \
6009 	AifReqAPIJobUpdate, "AifReqAPIJobUpdate", \
6010 	AifReqAPIJobFinish, "AifReqAPIJobFinish"
6011 
6012 #define	AAC_IOCTL_SUBCMD_KEY_STRINGS \
6013 	Reserved_IOCTL, "Reserved_IOCTL", \
6014 	GetDeviceHandle, "GetDeviceHandle", \
6015 	BusTargetLun_to_DeviceHandle, "BusTargetLun_to_DeviceHandle", \
6016 	DeviceHandle_to_BusTargetLun, "DeviceHandle_to_BusTargetLun", \
6017 	RescanBus, "RescanBus", \
6018 	GetDeviceProbeInfo, "GetDeviceProbeInfo", \
6019 	GetDeviceCapacity, "GetDeviceCapacity", \
6020 	GetContainerProbeInfo, "GetContainerProbeInfo", \
6021 	GetRequestedMemorySize, "GetRequestedMemorySize", \
6022 	GetBusInfo, "GetBusInfo", \
6023 	GetVendorSpecific, "GetVendorSpecific", \
6024 	EnhancedGetDeviceProbeInfo, "EnhancedGetDeviceProbeInfo", \
6025 	EnhancedGetBusInfo, "EnhancedGetBusInfo", \
6026 	SetupExtendedCounters, "SetupExtendedCounters", \
6027 	GetPerformanceCounters, "GetPerformanceCounters", \
6028 	ResetPerformanceCounters, "ResetPerformanceCounters", \
6029 	ReadModePage, "ReadModePage", \
6030 	WriteModePage, "WriteModePage", \
6031 	ReadDriveParameter, "ReadDriveParameter", \
6032 	WriteDriveParameter, "WriteDriveParameter", \
6033 	ResetAdapter, "ResetAdapter", \
6034 	ResetBus, "ResetBus", \
6035 	ResetBusDevice, "ResetBusDevice", \
6036 	ExecuteSrb, "ExecuteSrb", \
6037 	Create_IO_Task, "Create_IO_Task", \
6038 	Delete_IO_Task, "Delete_IO_Task", \
6039 	Get_IO_Task_Info, "Get_IO_Task_Info", \
6040 	Check_Task_Progress, "Check_Task_Progress", \
6041 	InjectError, "InjectError", \
6042 	GetDeviceDefectCounts, "GetDeviceDefectCounts", \
6043 	GetDeviceDefectInfo, "GetDeviceDefectInfo", \
6044 	GetDeviceStatus, "GetDeviceStatus", \
6045 	ClearDeviceStatus, "ClearDeviceStatus", \
6046 	DiskSpinControl, "DiskSpinControl", \
6047 	DiskSmartControl, "DiskSmartControl", \
6048 	WriteSame, "WriteSame", \
6049 	ReadWriteLong, "ReadWriteLong", \
6050 	FormatUnit, "FormatUnit", \
6051 	TargetDeviceControl, "TargetDeviceControl", \
6052 	TargetChannelControl, "TargetChannelControl", \
6053 	FlashNewCode, "FlashNewCode", \
6054 	DiskCheck, "DiskCheck", \
6055 	RequestSense, "RequestSense", \
6056 	DiskPERControl, "DiskPERControl", \
6057 	Read10, "Read10", \
6058 	Write10, "Write10"
6059 
6060 #define	AAC_AIFEN_KEY_STRINGS \
6061 	AifEnGeneric, "Generic", \
6062 	AifEnTaskComplete, "TaskComplete", \
6063 	AifEnConfigChange, "Config change", \
6064 	AifEnContainerChange, "Container change", \
6065 	AifEnDeviceFailure, "device failed", \
6066 	AifEnMirrorFailover, "Mirror failover", \
6067 	AifEnContainerEvent, "container event", \
6068 	AifEnFileSystemChange, "File system changed", \
6069 	AifEnConfigPause, "Container pause event", \
6070 	AifEnConfigResume, "Container resume event", \
6071 	AifEnFailoverChange, "Failover space assignment changed", \
6072 	AifEnRAID5RebuildDone, "RAID5 rebuild finished", \
6073 	AifEnEnclosureManagement, "Enclosure management event", \
6074 	AifEnBatteryEvent, "battery event", \
6075 	AifEnAddContainer, "Add container", \
6076 	AifEnDeleteContainer, "Delete container", \
6077 	AifEnSMARTEvent, "SMART Event", \
6078 	AifEnBatteryNeedsRecond, "battery needs reconditioning", \
6079 	AifEnClusterEvent, "cluster event", \
6080 	AifEnDiskSetEvent, "disk set event occured", \
6081 	AifDenMorphComplete, "morph operation completed", \
6082 	AifDenVolumeExtendComplete, "VolumeExtendComplete"
6083 
6084 struct aac_key_strings {
6085 	int key;
6086 	char *message;
6087 };
6088 
6089 extern struct scsi_key_strings scsi_cmds[];
6090 
6091 static struct aac_key_strings aac_fib_cmds[] = {
6092 	AAC_FIB_CMD_KEY_STRINGS,
6093 	-1,			NULL
6094 };
6095 
6096 static struct aac_key_strings aac_ctvm_subcmds[] = {
6097 	AAC_CTVM_SUBCMD_KEY_STRINGS,
6098 	-1,			NULL
6099 };
6100 
6101 static struct aac_key_strings aac_ct_subcmds[] = {
6102 	AAC_CT_SUBCMD_KEY_STRINGS,
6103 	-1,			NULL
6104 };
6105 
6106 static struct aac_key_strings aac_cl_subcmds[] = {
6107 	AAC_CL_SUBCMD_KEY_STRINGS,
6108 	-1,			NULL
6109 };
6110 
6111 static struct aac_key_strings aac_aif_subcmds[] = {
6112 	AAC_AIF_SUBCMD_KEY_STRINGS,
6113 	-1,			NULL
6114 };
6115 
6116 static struct aac_key_strings aac_ioctl_subcmds[] = {
6117 	AAC_IOCTL_SUBCMD_KEY_STRINGS,
6118 	-1,			NULL
6119 };
6120 
6121 static struct aac_key_strings aac_aifens[] = {
6122 	AAC_AIFEN_KEY_STRINGS,
6123 	-1,			NULL
6124 };
6125 
6126 /*
6127  * The following function comes from Adaptec:
6128  *
6129  * Get the firmware print buffer parameters from the firmware,
6130  * if the command was successful map in the address.
6131  */
6132 static int
6133 aac_get_fw_debug_buffer(struct aac_softstate *softs)
6134 {
6135 	if (aac_sync_mbcommand(softs, AAC_MONKER_GETDRVPROP,
6136 	    0, 0, 0, 0, NULL) == AACOK) {
6137 		uint32_t mondrv_buf_paddrl = AAC_MAILBOX_GET(softs, 1);
6138 		uint32_t mondrv_buf_paddrh = AAC_MAILBOX_GET(softs, 2);
6139 		uint32_t mondrv_buf_size = AAC_MAILBOX_GET(softs, 3);
6140 		uint32_t mondrv_hdr_size = AAC_MAILBOX_GET(softs, 4);
6141 
6142 		if (mondrv_buf_size) {
6143 			uint32_t offset = mondrv_buf_paddrl - \
6144 			    softs->pci_mem_base_paddr;
6145 
6146 			/*
6147 			 * See if the address is already mapped in, and
6148 			 * if so set it up from the base address
6149 			 */
6150 			if ((mondrv_buf_paddrh == 0) &&
6151 			    (offset + mondrv_buf_size < softs->map_size)) {
6152 				mutex_enter(&aac_prt_mutex);
6153 				softs->debug_buf_offset = offset;
6154 				softs->debug_header_size = mondrv_hdr_size;
6155 				softs->debug_buf_size = mondrv_buf_size;
6156 				softs->debug_fw_flags = 0;
6157 				softs->debug_flags &= ~AACDB_FLAGS_FW_PRINT;
6158 				mutex_exit(&aac_prt_mutex);
6159 
6160 				return (AACOK);
6161 			}
6162 		}
6163 	}
6164 	return (AACERR);
6165 }
6166 
6167 int
6168 aac_dbflag_on(struct aac_softstate *softs, int flag)
6169 {
6170 	int debug_flags = softs ? softs->debug_flags : aac_debug_flags;
6171 
6172 	return ((debug_flags & (AACDB_FLAGS_FW_PRINT | \
6173 	    AACDB_FLAGS_KERNEL_PRINT)) && (debug_flags & flag));
6174 }
6175 
6176 static void
6177 aac_cmn_err(struct aac_softstate *softs, uint_t lev, char sl, int noheader)
6178 {
6179 	if (noheader) {
6180 		if (sl) {
6181 			aac_fmt[0] = sl;
6182 			cmn_err(lev, aac_fmt, aac_prt_buf);
6183 		} else {
6184 			cmn_err(lev, &aac_fmt[1], aac_prt_buf);
6185 		}
6186 	} else {
6187 		if (sl) {
6188 			aac_fmt_header[0] = sl;
6189 			cmn_err(lev, aac_fmt_header,
6190 			    softs->vendor_name, softs->instance,
6191 			    aac_prt_buf);
6192 		} else {
6193 			cmn_err(lev, &aac_fmt_header[1],
6194 			    softs->vendor_name, softs->instance,
6195 			    aac_prt_buf);
6196 		}
6197 	}
6198 }
6199 
6200 /*
6201  * The following function comes from Adaptec:
6202  *
6203  * Format and print out the data passed in to UART or console
6204  * as specified by debug flags.
6205  */
6206 void
6207 aac_printf(struct aac_softstate *softs, uint_t lev, const char *fmt, ...)
6208 {
6209 	va_list args;
6210 	char sl; /* system log character */
6211 
6212 	mutex_enter(&aac_prt_mutex);
6213 	/* Set up parameters and call sprintf function to format the data */
6214 	if (strchr("^!?", fmt[0]) == NULL) {
6215 		sl = 0;
6216 	} else {
6217 		sl = fmt[0];
6218 		fmt++;
6219 	}
6220 	va_start(args, fmt);
6221 	(void) vsprintf(aac_prt_buf, fmt, args);
6222 	va_end(args);
6223 
6224 	/* Make sure the softs structure has been passed in for this section */
6225 	if (softs) {
6226 		if ((softs->debug_flags & AACDB_FLAGS_FW_PRINT) &&
6227 		    /* If we are set up for a Firmware print */
6228 		    (softs->debug_buf_size)) {
6229 			uint32_t count, i;
6230 
6231 			/* Make sure the string size is within boundaries */
6232 			count = strlen(aac_prt_buf);
6233 			if (count > softs->debug_buf_size)
6234 				count = (uint16_t)softs->debug_buf_size;
6235 
6236 			/*
6237 			 * Wait for no more than AAC_PRINT_TIMEOUT for the
6238 			 * previous message length to clear (the handshake).
6239 			 */
6240 			for (i = 0; i < AAC_PRINT_TIMEOUT; i++) {
6241 				if (!PCI_MEM_GET32(softs,
6242 				    softs->debug_buf_offset + \
6243 				    AAC_FW_DBG_STRLEN_OFFSET))
6244 					break;
6245 
6246 				drv_usecwait(1000);
6247 			}
6248 
6249 			/*
6250 			 * If the length is clear, copy over the message, the
6251 			 * flags, and the length. Make sure the length is the
6252 			 * last because that is the signal for the Firmware to
6253 			 * pick it up.
6254 			 */
6255 			if (!PCI_MEM_GET32(softs, softs->debug_buf_offset + \
6256 			    AAC_FW_DBG_STRLEN_OFFSET)) {
6257 				PCI_MEM_REP_PUT8(softs,
6258 				    softs->debug_buf_offset + \
6259 				    softs->debug_header_size,
6260 				    aac_prt_buf, count);
6261 				PCI_MEM_PUT32(softs,
6262 				    softs->debug_buf_offset + \
6263 				    AAC_FW_DBG_FLAGS_OFFSET,
6264 				    softs->debug_fw_flags);
6265 				PCI_MEM_PUT32(softs,
6266 				    softs->debug_buf_offset + \
6267 				    AAC_FW_DBG_STRLEN_OFFSET, count);
6268 			} else {
6269 				cmn_err(CE_WARN, "UART output fail");
6270 				softs->debug_flags &= ~AACDB_FLAGS_FW_PRINT;
6271 			}
6272 		}
6273 
6274 		/*
6275 		 * If the Kernel Debug Print flag is set, send it off
6276 		 * to the Kernel Debugger
6277 		 */
6278 		if (softs->debug_flags & AACDB_FLAGS_KERNEL_PRINT)
6279 			aac_cmn_err(softs, lev, sl,
6280 			    (softs->debug_flags & AACDB_FLAGS_NO_HEADERS));
6281 	} else {
6282 		/* Driver not initialized yet, no firmware or header output */
6283 		if (aac_debug_flags & AACDB_FLAGS_KERNEL_PRINT)
6284 			aac_cmn_err(softs, lev, sl, 1);
6285 	}
6286 	mutex_exit(&aac_prt_mutex);
6287 }
6288 
6289 /*
6290  * Translate command number to description string
6291  */
6292 static char *
6293 aac_cmd_name(int cmd, struct aac_key_strings *cmdlist)
6294 {
6295 	int i;
6296 
6297 	for (i = 0; cmdlist[i].key != -1; i++) {
6298 		if (cmd == cmdlist[i].key)
6299 			return (cmdlist[i].message);
6300 	}
6301 	return (NULL);
6302 }
6303 
6304 static void
6305 aac_print_scmd(struct aac_softstate *softs, struct aac_cmd *acp)
6306 {
6307 	struct scsi_pkt *pkt = acp->pkt;
6308 	struct scsi_address *ap = &pkt->pkt_address;
6309 	int ctl = ddi_get_instance(softs->devinfo_p);
6310 	int tgt = ap->a_target;
6311 	int lun = ap->a_lun;
6312 	union scsi_cdb *cdbp = (union scsi_cdb *)pkt->pkt_cdbp;
6313 	uchar_t cmd = cdbp->scc_cmd;
6314 	char *desc;
6315 
6316 	if ((desc = aac_cmd_name(cmd,
6317 	    (struct aac_key_strings *)scsi_cmds)) == NULL) {
6318 		aac_printf(softs, CE_NOTE,
6319 		    "SCMD> Unknown(0x%2x) --> c%dt%dL%d",
6320 		    cmd, ctl, tgt, lun);
6321 		return;
6322 	}
6323 
6324 	switch (cmd) {
6325 	case SCMD_READ:
6326 	case SCMD_WRITE:
6327 		aac_printf(softs, CE_NOTE,
6328 		    "SCMD> %s 0x%x[%d] %s --> c%dt%dL%d",
6329 		    desc, GETG0ADDR(cdbp), GETG0COUNT(cdbp),
6330 		    (acp->flags & AAC_CMD_NO_INTR) ? "poll" : "intr",
6331 		    ctl, tgt, lun);
6332 		break;
6333 	case SCMD_READ_G1:
6334 	case SCMD_WRITE_G1:
6335 		aac_printf(softs, CE_NOTE,
6336 		    "SCMD> %s 0x%x[%d] %s --> c%dt%dL%d",
6337 		    desc, GETG1ADDR(cdbp), GETG1COUNT(cdbp),
6338 		    (acp->flags & AAC_CMD_NO_INTR) ? "poll" : "intr",
6339 		    ctl, tgt, lun);
6340 		break;
6341 	case SCMD_READ_G4:
6342 	case SCMD_WRITE_G4:
6343 		aac_printf(softs, CE_NOTE,
6344 		    "SCMD> %s 0x%x.%08x[%d] %s --> c%dt%dL%d",
6345 		    desc, GETG4ADDR(cdbp), GETG4ADDRTL(cdbp),
6346 		    GETG4COUNT(cdbp),
6347 		    (acp->flags & AAC_CMD_NO_INTR) ? "poll" : "intr",
6348 		    ctl, tgt, lun);
6349 		break;
6350 	default:
6351 		aac_printf(softs, CE_NOTE, "SCMD> %s --> c%dt%dL%d",
6352 		    desc, ctl, tgt, lun);
6353 	}
6354 }
6355 
6356 void
6357 aac_print_fib(struct aac_softstate *softs, struct aac_fib *fibp)
6358 {
6359 	uint16_t fib_size;
6360 	int32_t fib_cmd, sub_cmd;
6361 	char *cmdstr, *subcmdstr;
6362 	struct aac_Container *pContainer;
6363 
6364 	fib_cmd = LE_16(fibp->Header.Command);
6365 	cmdstr = aac_cmd_name(fib_cmd, aac_fib_cmds);
6366 	sub_cmd = -1;
6367 	subcmdstr = NULL;
6368 
6369 	switch (fib_cmd) {
6370 	case ContainerCommand:
6371 		pContainer = (struct aac_Container *)fibp->data;
6372 		sub_cmd = LE_32(pContainer->Command);
6373 		subcmdstr = aac_cmd_name(sub_cmd, aac_ctvm_subcmds);
6374 		if (subcmdstr == NULL)
6375 			break;
6376 		fib_cmd = sub_cmd;
6377 		cmdstr = subcmdstr;
6378 		sub_cmd = -1;
6379 		subcmdstr = NULL;
6380 
6381 		switch (pContainer->Command) {
6382 		case VM_ContainerConfig:
6383 			sub_cmd = LE_32(pContainer->CTCommand.command);
6384 			subcmdstr = aac_cmd_name(sub_cmd, aac_ct_subcmds);
6385 			if (subcmdstr == NULL)
6386 				break;
6387 			aac_printf(softs, CE_NOTE, "FIB> %s (0x%x, 0x%x, 0x%x)",
6388 			    subcmdstr,
6389 			    LE_32(pContainer->CTCommand.param[0]),
6390 			    LE_32(pContainer->CTCommand.param[1]),
6391 			    LE_32(pContainer->CTCommand.param[2]));
6392 			return;
6393 		case VM_Ioctl:
6394 			sub_cmd = LE_32(((int32_t *)pContainer)[4]);
6395 			subcmdstr = aac_cmd_name(sub_cmd, aac_ioctl_subcmds);
6396 			break;
6397 		}
6398 		break;
6399 
6400 	case ClusterCommand:
6401 		sub_cmd = LE_32(((int32_t *)fibp->data)[0]);
6402 		subcmdstr = aac_cmd_name(sub_cmd, aac_cl_subcmds);
6403 		break;
6404 
6405 	case AifRequest:
6406 		sub_cmd = LE_32(((int32_t *)fibp->data)[0]);
6407 		subcmdstr = aac_cmd_name(sub_cmd, aac_aif_subcmds);
6408 		break;
6409 
6410 	default:
6411 		break;
6412 	}
6413 
6414 	fib_size = LE_16(fibp->Header.Size);
6415 	if (subcmdstr)
6416 		aac_printf(softs, CE_NOTE, "FIB> %s, sz=%d",
6417 		    subcmdstr, fib_size);
6418 	else if (cmdstr && sub_cmd == -1)
6419 		aac_printf(softs, CE_NOTE, "FIB> %s, sz=%d",
6420 		    cmdstr, fib_size);
6421 	else if (cmdstr)
6422 		aac_printf(softs, CE_NOTE, "FIB> %s: Unknown(0x%x), sz=%d",
6423 		    cmdstr, sub_cmd, fib_size);
6424 	else
6425 		aac_printf(softs, CE_NOTE, "FIB> Unknown(0x%x), sz=%d",
6426 		    fib_cmd, fib_size);
6427 }
6428 
6429 static void
6430 aac_print_aif(struct aac_softstate *softs, struct aac_aif_command *aif)
6431 {
6432 	int aif_command;
6433 	uint32_t aif_seqnumber;
6434 	int aif_en_type;
6435 	char *str;
6436 
6437 	aif_command = LE_32(aif->command);
6438 	aif_seqnumber = LE_32(aif->seqNumber);
6439 	aif_en_type = LE_32(aif->data.EN.type);
6440 
6441 	switch (aif_command) {
6442 	case AifCmdEventNotify:
6443 		str = aac_cmd_name(aif_en_type, aac_aifens);
6444 		if (str)
6445 			aac_printf(softs, CE_NOTE, "AIF! %s", str);
6446 		else
6447 			aac_printf(softs, CE_NOTE, "AIF! Unknown(0x%x)",
6448 			    aif_en_type);
6449 		break;
6450 
6451 	case AifCmdJobProgress:
6452 		switch (LE_32(aif->data.PR[0].status)) {
6453 		case AifJobStsSuccess:
6454 			str = "success"; break;
6455 		case AifJobStsFinished:
6456 			str = "finished"; break;
6457 		case AifJobStsAborted:
6458 			str = "aborted"; break;
6459 		case AifJobStsFailed:
6460 			str = "failed"; break;
6461 		case AifJobStsSuspended:
6462 			str = "suspended"; break;
6463 		case AifJobStsRunning:
6464 			str = "running"; break;
6465 		default:
6466 			str = "unknown"; break;
6467 		}
6468 		aac_printf(softs, CE_NOTE,
6469 		    "AIF! JobProgress (%d) - %s (%d, %d)",
6470 		    aif_seqnumber, str,
6471 		    LE_32(aif->data.PR[0].currentTick),
6472 		    LE_32(aif->data.PR[0].finalTick));
6473 		break;
6474 
6475 	case AifCmdAPIReport:
6476 		aac_printf(softs, CE_NOTE, "AIF! APIReport (%d)",
6477 		    aif_seqnumber);
6478 		break;
6479 
6480 	case AifCmdDriverNotify:
6481 		aac_printf(softs, CE_NOTE, "AIF! DriverNotify (%d)",
6482 		    aif_seqnumber);
6483 		break;
6484 
6485 	default:
6486 		aac_printf(softs, CE_NOTE, "AIF! AIF %d (%d)",
6487 		    aif_command, aif_seqnumber);
6488 		break;
6489 	}
6490 }
6491 
6492 #endif /* DEBUG */
6493