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