17c478bd9Sstevel@tonic-gate /*
23fced439Szhongyan gu - Sun Microsystems - Beijing China * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
37c478bd9Sstevel@tonic-gate */
4830d82f7Spl
57c478bd9Sstevel@tonic-gate /*
6*3fe80ca4SDan Cross * Copyright 2023 Oxide Computer Company
715c07adcSJohn Levon * Copyright (c) 2018, Joyent, Inc.
858bc78c7SXin Chen * Copyright 2005-08 Adaptec, Inc.
958bc78c7SXin Chen * Copyright (c) 2005-08 Adaptec Inc., Achim Leubner
107c478bd9Sstevel@tonic-gate * Copyright (c) 2000 Michael Smith
117c478bd9Sstevel@tonic-gate * Copyright (c) 2001 Scott Long
127c478bd9Sstevel@tonic-gate * Copyright (c) 2000 BSDi
137c478bd9Sstevel@tonic-gate * All rights reserved.
147c478bd9Sstevel@tonic-gate *
157c478bd9Sstevel@tonic-gate * Redistribution and use in source and binary forms, with or without
167c478bd9Sstevel@tonic-gate * modification, are permitted provided that the following conditions
177c478bd9Sstevel@tonic-gate * are met:
187c478bd9Sstevel@tonic-gate * 1. Redistributions of source code must retain the above copyright
197c478bd9Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer.
207c478bd9Sstevel@tonic-gate * 2. Redistributions in binary form must reproduce the above copyright
217c478bd9Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer in the
227c478bd9Sstevel@tonic-gate * documentation and/or other materials provided with the distribution.
237c478bd9Sstevel@tonic-gate *
247c478bd9Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
257c478bd9Sstevel@tonic-gate * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
267c478bd9Sstevel@tonic-gate * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
277c478bd9Sstevel@tonic-gate * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
287c478bd9Sstevel@tonic-gate * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29830d82f7Spl * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30830d82f7Spl * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
317c478bd9Sstevel@tonic-gate * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
327c478bd9Sstevel@tonic-gate * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
337c478bd9Sstevel@tonic-gate * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
347c478bd9Sstevel@tonic-gate * SUCH DAMAGE.
357c478bd9Sstevel@tonic-gate */
367c478bd9Sstevel@tonic-gate #include <sys/modctl.h>
377c478bd9Sstevel@tonic-gate #include <sys/conf.h>
387c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h>
397c478bd9Sstevel@tonic-gate #include <sys/ddi.h>
407c478bd9Sstevel@tonic-gate #include <sys/devops.h>
417c478bd9Sstevel@tonic-gate #include <sys/pci.h>
427c478bd9Sstevel@tonic-gate #include <sys/types.h>
437c478bd9Sstevel@tonic-gate #include <sys/ddidmareq.h>
447c478bd9Sstevel@tonic-gate #include <sys/scsi/scsi.h>
457c478bd9Sstevel@tonic-gate #include <sys/ksynch.h>
467c478bd9Sstevel@tonic-gate #include <sys/sunddi.h>
477c478bd9Sstevel@tonic-gate #include <sys/byteorder.h>
487c478bd9Sstevel@tonic-gate #include "aac_regs.h"
497c478bd9Sstevel@tonic-gate #include "aac.h"
507c478bd9Sstevel@tonic-gate
517675db54Syw /*
527675db54Syw * FMA header files
537675db54Syw */
547675db54Syw #include <sys/ddifm.h>
557675db54Syw #include <sys/fm/protocol.h>
567675db54Syw #include <sys/fm/util.h>
577675db54Syw #include <sys/fm/io/ddi.h>
587675db54Syw
59830d82f7Spl /*
60830d82f7Spl * For minor nodes created by the SCSA framework, minor numbers are
61830d82f7Spl * formed by left-shifting instance by INST_MINOR_SHIFT and OR in a
62830d82f7Spl * number less than 64.
63830d82f7Spl *
64830d82f7Spl * To support cfgadm, need to confirm the SCSA framework by creating
65830d82f7Spl * devctl/scsi and driver specific minor nodes under SCSA format,
66830d82f7Spl * and calling scsi_hba_xxx() functions aacordingly.
67830d82f7Spl */
687c478bd9Sstevel@tonic-gate
69830d82f7Spl #define AAC_MINOR 32
70830d82f7Spl #define INST2AAC(x) (((x) << INST_MINOR_SHIFT) | AAC_MINOR)
71830d82f7Spl #define AAC_SCSA_MINOR(x) ((x) & TRAN_MINOR_MASK)
72830d82f7Spl #define AAC_IS_SCSA_NODE(x) ((x) == DEVCTL_MINOR || (x) == SCSI_MINOR)
737c478bd9Sstevel@tonic-gate
7458bc78c7SXin Chen #define SD2TRAN(sd) ((sd)->sd_address.a_hba_tran)
757c478bd9Sstevel@tonic-gate #define AAC_TRAN2SOFTS(tran) ((struct aac_softstate *)(tran)->tran_hba_private)
76c9487164Spl #define AAC_DIP2TRAN(dip) ((scsi_hba_tran_t *)ddi_get_driver_private(dip))
77c9487164Spl #define AAC_DIP2SOFTS(dip) (AAC_TRAN2SOFTS(AAC_DIP2TRAN(dip)))
7858bc78c7SXin Chen #define SD2AAC(sd) (AAC_TRAN2SOFTS(SD2TRAN(sd)))
7958bc78c7SXin Chen #define AAC_PD(t) ((t) - AAC_MAX_LD)
8058bc78c7SXin Chen #define AAC_DEV(softs, t) (((t) < AAC_MAX_LD) ? \
8158bc78c7SXin Chen &(softs)->containers[(t)].dev : \
8258bc78c7SXin Chen ((t) < AAC_MAX_DEV(softs)) ? \
8358bc78c7SXin Chen &(softs)->nondasds[AAC_PD(t)].dev : NULL)
8458bc78c7SXin Chen #define AAC_DEVCFG_BEGIN(softs, tgt) \
8558bc78c7SXin Chen aac_devcfg((softs), (tgt), 1)
8658bc78c7SXin Chen #define AAC_DEVCFG_END(softs, tgt) \
8758bc78c7SXin Chen aac_devcfg((softs), (tgt), 0)
88c9487164Spl #define PKT2AC(pkt) ((struct aac_cmd *)(pkt)->pkt_ha_private)
89382c8bcaSpl #define AAC_BUSYWAIT(cond, timeout /* in millisecond */) { \
90382c8bcaSpl if (!(cond)) { \
91382c8bcaSpl int count = (timeout) * 10; \
92382c8bcaSpl while (count) { \
93382c8bcaSpl drv_usecwait(100); \
94382c8bcaSpl if (cond) \
95382c8bcaSpl break; \
96382c8bcaSpl count--; \
977c478bd9Sstevel@tonic-gate } \
98382c8bcaSpl (timeout) = (count + 9) / 10; \
997c478bd9Sstevel@tonic-gate } \
100382c8bcaSpl }
101830d82f7Spl
102c9487164Spl #define AAC_SENSE_DATA_DESCR_LEN \
103c9487164Spl (sizeof (struct scsi_descr_sense_hdr) + \
104830d82f7Spl sizeof (struct scsi_information_sense_descr))
105d7c5bf88Spl #define AAC_ARQ64_LENGTH \
106d7c5bf88Spl (sizeof (struct scsi_arq_status) + \
107d7c5bf88Spl AAC_SENSE_DATA_DESCR_LEN - SENSE_LENGTH)
108d7c5bf88Spl
109830d82f7Spl /* NOTE: GETG4ADDRTL(cdbp) is int32_t */
110830d82f7Spl #define AAC_GETGXADDR(cmdlen, cdbp) \
111830d82f7Spl ((cmdlen == 6) ? GETG0ADDR(cdbp) : \
112830d82f7Spl (cmdlen == 10) ? (uint32_t)GETG1ADDR(cdbp) : \
113830d82f7Spl ((uint64_t)GETG4ADDR(cdbp) << 32) | (uint32_t)GETG4ADDRTL(cdbp))
114830d82f7Spl
115830d82f7Spl #define AAC_CDB_INQUIRY_CMDDT 0x02
116830d82f7Spl #define AAC_CDB_INQUIRY_EVPD 0x01
117830d82f7Spl #define AAC_VPD_PAGE_CODE 1
118830d82f7Spl #define AAC_VPD_PAGE_LENGTH 3
119830d82f7Spl #define AAC_VPD_PAGE_DATA 4
120830d82f7Spl #define AAC_VPD_ID_CODESET 0
121830d82f7Spl #define AAC_VPD_ID_TYPE 1
122830d82f7Spl #define AAC_VPD_ID_LENGTH 3
123830d82f7Spl #define AAC_VPD_ID_DATA 4
124830d82f7Spl
12558bc78c7SXin Chen #define AAC_SCSI_RPTLUNS_HEAD_SIZE 0x08
12658bc78c7SXin Chen #define AAC_SCSI_RPTLUNS_ADDR_SIZE 0x08
12758bc78c7SXin Chen #define AAC_SCSI_RPTLUNS_ADDR_MASK 0xC0
12858bc78c7SXin Chen /* 00b - peripheral device addressing method */
12958bc78c7SXin Chen #define AAC_SCSI_RPTLUNS_ADDR_PERIPHERAL 0x00
13058bc78c7SXin Chen /* 01b - flat space addressing method */
13158bc78c7SXin Chen #define AAC_SCSI_RPTLUNS_ADDR_FLAT_SPACE 0x40
13258bc78c7SXin Chen /* 10b - logical unit addressing method */
13358bc78c7SXin Chen #define AAC_SCSI_RPTLUNS_ADDR_LOGICAL_UNIT 0x80
13458bc78c7SXin Chen
135942c5e3cSpl /* Return the size of FIB with data part type data_type */
136942c5e3cSpl #define AAC_FIB_SIZEOF(data_type) \
137942c5e3cSpl (sizeof (struct aac_fib_header) + sizeof (data_type))
138942c5e3cSpl /* Return the container size defined in mir */
139942c5e3cSpl #define AAC_MIR_SIZE(softs, acc, mir) \
140830d82f7Spl (((softs)->flags & AAC_FLAGS_LBA_64BIT) ? \
141942c5e3cSpl (uint64_t)ddi_get32((acc), &(mir)->MntObj.Capacity) + \
142942c5e3cSpl ((uint64_t)ddi_get32((acc), &(mir)->MntObj.CapacityHigh) << 32) : \
143942c5e3cSpl (uint64_t)ddi_get32((acc), &(mir)->MntObj.Capacity))
144830d82f7Spl
145d937e6ebSpl /* The last entry of aac_cards[] is for unknown cards */
146d937e6ebSpl #define AAC_UNKNOWN_CARD \
147d937e6ebSpl (sizeof (aac_cards) / sizeof (struct aac_card_type) - 1)
148d937e6ebSpl #define CARD_IS_UNKNOWN(i) (i == AAC_UNKNOWN_CARD)
149d937e6ebSpl #define BUF_IS_READ(bp) ((bp)->b_flags & B_READ)
150c9487164Spl #define AAC_IS_Q_EMPTY(q) ((q)->q_head == NULL)
151382c8bcaSpl #define AAC_CMDQ(acp) (!((acp)->flags & AAC_CMD_SYNC))
1527c478bd9Sstevel@tonic-gate
153c9487164Spl #define PCI_MEM_GET32(softs, off) \
154c9487164Spl ddi_get32((softs)->pci_mem_handle, \
155a74f7440Spl (void *)((softs)->pci_mem_base_vaddr + (off)))
156c9487164Spl #define PCI_MEM_PUT32(softs, off, val) \
157c9487164Spl ddi_put32((softs)->pci_mem_handle, \
158a74f7440Spl (void *)((softs)->pci_mem_base_vaddr + (off)), \
1591dd0a2dbSpl (uint32_t)(val))
160942c5e3cSpl #define PCI_MEM_GET16(softs, off) \
161942c5e3cSpl ddi_get16((softs)->pci_mem_handle, \
162a74f7440Spl (void *)((softs)->pci_mem_base_vaddr + (off)))
163942c5e3cSpl #define PCI_MEM_PUT16(softs, off, val) \
164942c5e3cSpl ddi_put16((softs)->pci_mem_handle, \
165a74f7440Spl (void *)((softs)->pci_mem_base_vaddr + (off)), (uint16_t)(val))
166942c5e3cSpl /* Write host data at valp to device mem[off] repeatedly count times */
1671dd0a2dbSpl #define PCI_MEM_REP_PUT8(softs, off, valp, count) \
1681dd0a2dbSpl ddi_rep_put8((softs)->pci_mem_handle, (uint8_t *)(valp), \
1691dd0a2dbSpl (uint8_t *)((softs)->pci_mem_base_vaddr + (off)), \
1701dd0a2dbSpl count, DDI_DEV_AUTOINCR)
171942c5e3cSpl /* Read device data at mem[off] to host addr valp repeatedly count times */
172942c5e3cSpl #define PCI_MEM_REP_GET8(softs, off, valp, count) \
173942c5e3cSpl ddi_rep_get8((softs)->pci_mem_handle, (uint8_t *)(valp), \
174942c5e3cSpl (uint8_t *)((softs)->pci_mem_base_vaddr + (off)), \
175942c5e3cSpl count, DDI_DEV_AUTOINCR)
176942c5e3cSpl #define AAC_GET_FIELD8(acc, d, s, field) \
177942c5e3cSpl (d)->field = ddi_get8(acc, (uint8_t *)&(s)->field)
178942c5e3cSpl #define AAC_GET_FIELD32(acc, d, s, field) \
179942c5e3cSpl (d)->field = ddi_get32(acc, (uint32_t *)&(s)->field)
180942c5e3cSpl #define AAC_GET_FIELD64(acc, d, s, field) \
181942c5e3cSpl (d)->field = ddi_get64(acc, (uint64_t *)&(s)->field)
182942c5e3cSpl #define AAC_REP_GET_FIELD8(acc, d, s, field, r) \
183942c5e3cSpl ddi_rep_get8((acc), (uint8_t *)&(d)->field, \
184942c5e3cSpl (uint8_t *)&(s)->field, (r), DDI_DEV_AUTOINCR)
185942c5e3cSpl #define AAC_REP_GET_FIELD32(acc, d, s, field, r) \
186942c5e3cSpl ddi_rep_get32((acc), (uint32_t *)&(d)->field, \
187942c5e3cSpl (uint32_t *)&(s)->field, (r), DDI_DEV_AUTOINCR)
1887c478bd9Sstevel@tonic-gate
189382c8bcaSpl #define AAC_ENABLE_INTR(softs) { \
190830d82f7Spl if (softs->flags & AAC_FLAGS_NEW_COMM) \
191830d82f7Spl PCI_MEM_PUT32(softs, AAC_OIMR, ~AAC_DB_INTR_NEW); \
192830d82f7Spl else \
193830d82f7Spl PCI_MEM_PUT32(softs, AAC_OIMR, ~AAC_DB_INTR_BITS); \
1941ee13a44SXinChen softs->state |= AAC_STATE_INTR; \
195382c8bcaSpl }
196382c8bcaSpl
1971ee13a44SXinChen #define AAC_DISABLE_INTR(softs) { \
1981ee13a44SXinChen PCI_MEM_PUT32(softs, AAC_OIMR, ~0); \
1991ee13a44SXinChen softs->state &= ~AAC_STATE_INTR; \
2001ee13a44SXinChen }
201c9487164Spl #define AAC_STATUS_CLR(softs, mask) PCI_MEM_PUT32(softs, AAC_ODBR, mask)
202c9487164Spl #define AAC_STATUS_GET(softs) PCI_MEM_GET32(softs, AAC_ODBR)
203c9487164Spl #define AAC_NOTIFY(softs, val) PCI_MEM_PUT32(softs, AAC_IDBR, val)
204c9487164Spl #define AAC_OUTB_GET(softs) PCI_MEM_GET32(softs, AAC_OQUE)
205c9487164Spl #define AAC_OUTB_SET(softs, val) PCI_MEM_PUT32(softs, AAC_OQUE, val)
206830d82f7Spl #define AAC_FWSTATUS_GET(softs) \
207c9487164Spl ((softs)->aac_if.aif_get_fwstatus(softs))
208830d82f7Spl #define AAC_MAILBOX_GET(softs, mb) \
209830d82f7Spl ((softs)->aac_if.aif_get_mailbox((softs), (mb)))
210830d82f7Spl #define AAC_MAILBOX_SET(softs, cmd, arg0, arg1, arg2, arg3) \
211830d82f7Spl ((softs)->aac_if.aif_set_mailbox((softs), (cmd), \
212c9487164Spl (arg0), (arg1), (arg2), (arg3)))
213830d82f7Spl
214f42c2f53Szhongyan gu - Sun Microsystems - Beijing China #define AAC_MGT_SLOT_NUM 2
215382c8bcaSpl #define AAC_THROTTLE_DRAIN -1
216382c8bcaSpl
217382c8bcaSpl #define AAC_QUIESCE_TICK 1 /* 1 second */
21858bc78c7SXin Chen #define AAC_QUIESCE_TIMEOUT 180 /* 180 seconds */
219382c8bcaSpl #define AAC_DEFAULT_TICK 10 /* 10 seconds */
220942c5e3cSpl #define AAC_SYNC_TICK (30*60) /* 30 minutes */
221832e0b5aSpl
222d7c5bf88Spl /* Poll time for aac_do_poll_io() */
223382c8bcaSpl #define AAC_POLL_TIME 60 /* 60 seconds */
224d7c5bf88Spl
22558bc78c7SXin Chen /* IOP reset */
22658bc78c7SXin Chen #define AAC_IOP_RESET_SUCCEED 0 /* IOP reset succeed */
22758bc78c7SXin Chen #define AAC_IOP_RESET_FAILED -1 /* IOP reset failed */
22858bc78c7SXin Chen #define AAC_IOP_RESET_ABNORMAL -2 /* Reset operation abnormal */
22958bc78c7SXin Chen
230d937e6ebSpl /*
231d937e6ebSpl * Hardware access functions
232d937e6ebSpl */
233830d82f7Spl static int aac_rx_get_fwstatus(struct aac_softstate *);
234830d82f7Spl static int aac_rx_get_mailbox(struct aac_softstate *, int);
235942c5e3cSpl static void aac_rx_set_mailbox(struct aac_softstate *, uint32_t, uint32_t,
236942c5e3cSpl uint32_t, uint32_t, uint32_t);
237830d82f7Spl static int aac_rkt_get_fwstatus(struct aac_softstate *);
238830d82f7Spl static int aac_rkt_get_mailbox(struct aac_softstate *, int);
239830d82f7Spl static void aac_rkt_set_mailbox(struct aac_softstate *, uint32_t, uint32_t,
240c9487164Spl uint32_t, uint32_t, uint32_t);
241830d82f7Spl
2427c478bd9Sstevel@tonic-gate /*
2437c478bd9Sstevel@tonic-gate * SCSA function prototypes
2447c478bd9Sstevel@tonic-gate */
2457c478bd9Sstevel@tonic-gate static int aac_attach(dev_info_t *, ddi_attach_cmd_t);
2467c478bd9Sstevel@tonic-gate static int aac_detach(dev_info_t *, ddi_detach_cmd_t);
247830d82f7Spl static int aac_reset(dev_info_t *, ddi_reset_cmd_t);
24819397407SSherry Moore static int aac_quiesce(dev_info_t *);
249f42c2f53Szhongyan gu - Sun Microsystems - Beijing China static int aac_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **);
2507c478bd9Sstevel@tonic-gate
2517c478bd9Sstevel@tonic-gate /*
252d7c5bf88Spl * Interrupt handler functions
2537c478bd9Sstevel@tonic-gate */
254b6094a86Sjd static int aac_query_intrs(struct aac_softstate *, int);
255b6094a86Sjd static int aac_add_intrs(struct aac_softstate *);
256b6094a86Sjd static void aac_remove_intrs(struct aac_softstate *);
257f42c2f53Szhongyan gu - Sun Microsystems - Beijing China static int aac_enable_intrs(struct aac_softstate *);
258f42c2f53Szhongyan gu - Sun Microsystems - Beijing China static int aac_disable_intrs(struct aac_softstate *);
259b4a8b33bSToomas Soome static uint_t aac_intr_old(caddr_t, caddr_t);
260b4a8b33bSToomas Soome static uint_t aac_intr_new(caddr_t, caddr_t);
2617c478bd9Sstevel@tonic-gate static uint_t aac_softintr(caddr_t);
2627c478bd9Sstevel@tonic-gate
2637c478bd9Sstevel@tonic-gate /*
264d7c5bf88Spl * Internal functions in attach
2657c478bd9Sstevel@tonic-gate */
2667c478bd9Sstevel@tonic-gate static int aac_check_card_type(struct aac_softstate *);
267830d82f7Spl static int aac_check_firmware(struct aac_softstate *);
2687c478bd9Sstevel@tonic-gate static int aac_common_attach(struct aac_softstate *);
269830d82f7Spl static void aac_common_detach(struct aac_softstate *);
270942c5e3cSpl static int aac_probe_containers(struct aac_softstate *);
271830d82f7Spl static int aac_alloc_comm_space(struct aac_softstate *);
2727c478bd9Sstevel@tonic-gate static int aac_setup_comm_space(struct aac_softstate *);
273830d82f7Spl static void aac_free_comm_space(struct aac_softstate *);
2747c478bd9Sstevel@tonic-gate static int aac_hba_setup(struct aac_softstate *);
2757c478bd9Sstevel@tonic-gate
276d937e6ebSpl /*
277d937e6ebSpl * Sync FIB operation functions
278d937e6ebSpl */
279d937e6ebSpl int aac_sync_mbcommand(struct aac_softstate *, uint32_t, uint32_t,
280c9487164Spl uint32_t, uint32_t, uint32_t, uint32_t *);
281942c5e3cSpl static int aac_sync_fib(struct aac_softstate *, uint16_t, uint16_t);
2827c478bd9Sstevel@tonic-gate
2837c478bd9Sstevel@tonic-gate /*
284382c8bcaSpl * Command queue operation functions
2857c478bd9Sstevel@tonic-gate */
286382c8bcaSpl static void aac_cmd_initq(struct aac_cmd_queue *);
2877c478bd9Sstevel@tonic-gate static void aac_cmd_enqueue(struct aac_cmd_queue *, struct aac_cmd *);
2887c478bd9Sstevel@tonic-gate static struct aac_cmd *aac_cmd_dequeue(struct aac_cmd_queue *);
289382c8bcaSpl static void aac_cmd_delete(struct aac_cmd_queue *, struct aac_cmd *);
2907c478bd9Sstevel@tonic-gate
2917c478bd9Sstevel@tonic-gate /*
292c9487164Spl * FIB queue operation functions
2937c478bd9Sstevel@tonic-gate */
294d7c5bf88Spl static int aac_fib_enqueue(struct aac_softstate *, int, uint32_t, uint32_t);
295d7c5bf88Spl static int aac_fib_dequeue(struct aac_softstate *, int, int *);
2967c478bd9Sstevel@tonic-gate
2977c478bd9Sstevel@tonic-gate /*
298c9487164Spl * Slot operation functions
2997c478bd9Sstevel@tonic-gate */
3007c478bd9Sstevel@tonic-gate static int aac_create_slots(struct aac_softstate *);
3017c478bd9Sstevel@tonic-gate static void aac_destroy_slots(struct aac_softstate *);
302942c5e3cSpl static void aac_alloc_fibs(struct aac_softstate *);
303d7c5bf88Spl static void aac_destroy_fibs(struct aac_softstate *);
3047c478bd9Sstevel@tonic-gate static struct aac_slot *aac_get_slot(struct aac_softstate *);
305830d82f7Spl static void aac_release_slot(struct aac_softstate *, struct aac_slot *);
306830d82f7Spl static int aac_alloc_fib(struct aac_softstate *, struct aac_slot *);
307830d82f7Spl static void aac_free_fib(struct aac_slot *);
3087c478bd9Sstevel@tonic-gate
3097c478bd9Sstevel@tonic-gate /*
310d7c5bf88Spl * Internal functions
3117c478bd9Sstevel@tonic-gate */
312f42c2f53Szhongyan gu - Sun Microsystems - Beijing China static void aac_cmd_fib_header(struct aac_softstate *, struct aac_cmd *,
313f42c2f53Szhongyan gu - Sun Microsystems - Beijing China uint16_t);
314942c5e3cSpl static void aac_cmd_fib_rawio(struct aac_softstate *, struct aac_cmd *);
315942c5e3cSpl static void aac_cmd_fib_brw64(struct aac_softstate *, struct aac_cmd *);
316942c5e3cSpl static void aac_cmd_fib_brw(struct aac_softstate *, struct aac_cmd *);
317942c5e3cSpl static void aac_cmd_fib_sync(struct aac_softstate *, struct aac_cmd *);
318942c5e3cSpl static void aac_cmd_fib_scsi32(struct aac_softstate *, struct aac_cmd *);
319942c5e3cSpl static void aac_cmd_fib_scsi64(struct aac_softstate *, struct aac_cmd *);
320b40e8a89Szhongyan gu - Sun Microsystems - Beijing China static void aac_cmd_fib_startstop(struct aac_softstate *, struct aac_cmd *);
3217c478bd9Sstevel@tonic-gate static void aac_start_waiting_io(struct aac_softstate *);
3227c478bd9Sstevel@tonic-gate static void aac_drain_comp_q(struct aac_softstate *);
323d7c5bf88Spl int aac_do_io(struct aac_softstate *, struct aac_cmd *);
324f42c2f53Szhongyan gu - Sun Microsystems - Beijing China static int aac_sync_fib_slot_bind(struct aac_softstate *, struct aac_cmd *);
325f42c2f53Szhongyan gu - Sun Microsystems - Beijing China static void aac_sync_fib_slot_release(struct aac_softstate *, struct aac_cmd *);
326f42c2f53Szhongyan gu - Sun Microsystems - Beijing China static void aac_start_io(struct aac_softstate *, struct aac_cmd *);
3277c478bd9Sstevel@tonic-gate static int aac_do_poll_io(struct aac_softstate *, struct aac_cmd *);
328382c8bcaSpl static int aac_do_sync_io(struct aac_softstate *, struct aac_cmd *);
329d937e6ebSpl static int aac_send_command(struct aac_softstate *, struct aac_slot *);
33058bc78c7SXin Chen static void aac_cmd_timeout(struct aac_softstate *, struct aac_cmd *);
3317675db54Syw static int aac_dma_sync_ac(struct aac_cmd *);
332830d82f7Spl static int aac_shutdown(struct aac_softstate *);
333830d82f7Spl static int aac_reset_adapter(struct aac_softstate *);
334382c8bcaSpl static int aac_do_quiesce(struct aac_softstate *softs);
335382c8bcaSpl static int aac_do_unquiesce(struct aac_softstate *softs);
336382c8bcaSpl static void aac_unhold_bus(struct aac_softstate *, int);
33758bc78c7SXin Chen static void aac_set_throttle(struct aac_softstate *, struct aac_device *,
338382c8bcaSpl int, int);
339830d82f7Spl
340830d82f7Spl /*
341d937e6ebSpl * Adapter Initiated FIB handling function
342830d82f7Spl */
3430749e8deSXin Chen - Sun Microsystems - Beijing China static void aac_save_aif(struct aac_softstate *, ddi_acc_handle_t,
3440749e8deSXin Chen - Sun Microsystems - Beijing China struct aac_fib *, int);
3450749e8deSXin Chen - Sun Microsystems - Beijing China static int aac_handle_aif(struct aac_softstate *, struct aac_aif_command *);
3467c478bd9Sstevel@tonic-gate
3477c478bd9Sstevel@tonic-gate /*
3480749e8deSXin Chen - Sun Microsystems - Beijing China * Event handling related functions
3497c478bd9Sstevel@tonic-gate */
3500749e8deSXin Chen - Sun Microsystems - Beijing China static void aac_timer(void *);
3510749e8deSXin Chen - Sun Microsystems - Beijing China static void aac_event_thread(struct aac_softstate *);
3520749e8deSXin Chen - Sun Microsystems - Beijing China static void aac_event_disp(struct aac_softstate *, int);
3537c478bd9Sstevel@tonic-gate
354830d82f7Spl /*
355d937e6ebSpl * IOCTL interface related functions
356830d82f7Spl */
357830d82f7Spl static int aac_open(dev_t *, int, int, cred_t *);
358830d82f7Spl static int aac_close(dev_t, int, int, cred_t *);
359830d82f7Spl static int aac_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
360942c5e3cSpl extern int aac_do_ioctl(struct aac_softstate *, dev_t, int, intptr_t, int);
361830d82f7Spl
3627675db54Syw /*
3637675db54Syw * FMA Prototypes
3647675db54Syw */
3657675db54Syw static void aac_fm_init(struct aac_softstate *);
3667675db54Syw static void aac_fm_fini(struct aac_softstate *);
3677675db54Syw static int aac_fm_error_cb(dev_info_t *, ddi_fm_error_t *, const void *);
3687675db54Syw int aac_check_acc_handle(ddi_acc_handle_t);
3697675db54Syw int aac_check_dma_handle(ddi_dma_handle_t);
3707675db54Syw void aac_fm_ereport(struct aac_softstate *, char *);
3717675db54Syw
37258bc78c7SXin Chen /*
37358bc78c7SXin Chen * Auto enumeration functions
37458bc78c7SXin Chen */
37558bc78c7SXin Chen static dev_info_t *aac_find_child(struct aac_softstate *, uint16_t, uint8_t);
37658bc78c7SXin Chen static int aac_tran_bus_config(dev_info_t *, uint_t, ddi_bus_config_op_t,
37758bc78c7SXin Chen void *, dev_info_t **);
3780749e8deSXin Chen - Sun Microsystems - Beijing China static int aac_handle_dr(struct aac_softstate *, int, int, int);
3790749e8deSXin Chen - Sun Microsystems - Beijing China
3800749e8deSXin Chen - Sun Microsystems - Beijing China extern pri_t minclsyspri;
38158bc78c7SXin Chen
3821dd0a2dbSpl #ifdef DEBUG
3831dd0a2dbSpl /*
3841dd0a2dbSpl * UART debug output support
3851dd0a2dbSpl */
3861dd0a2dbSpl
3871dd0a2dbSpl #define AAC_PRINT_BUFFER_SIZE 512
3881dd0a2dbSpl #define AAC_PRINT_TIMEOUT 250 /* 1/4 sec. = 250 msec. */
3891dd0a2dbSpl
3901dd0a2dbSpl #define AAC_FW_DBG_STRLEN_OFFSET 0x00
3911dd0a2dbSpl #define AAC_FW_DBG_FLAGS_OFFSET 0x04
3921dd0a2dbSpl #define AAC_FW_DBG_BLED_OFFSET 0x08
3931dd0a2dbSpl
3941dd0a2dbSpl static int aac_get_fw_debug_buffer(struct aac_softstate *);
3951dd0a2dbSpl static void aac_print_scmd(struct aac_softstate *, struct aac_cmd *);
3961dd0a2dbSpl static void aac_print_aif(struct aac_softstate *, struct aac_aif_command *);
3971dd0a2dbSpl
3981dd0a2dbSpl static char aac_prt_buf[AAC_PRINT_BUFFER_SIZE];
399942c5e3cSpl static char aac_fmt[] = " %s";
400942c5e3cSpl static char aac_fmt_header[] = " %s.%d: %s";
4011dd0a2dbSpl static kmutex_t aac_prt_mutex;
4021dd0a2dbSpl
4031dd0a2dbSpl /*
4041dd0a2dbSpl * Debug flags to be put into the softstate flags field
4051dd0a2dbSpl * when initialized
4061dd0a2dbSpl */
4071dd0a2dbSpl uint32_t aac_debug_flags =
4081dd0a2dbSpl /* AACDB_FLAGS_KERNEL_PRINT | */
4091dd0a2dbSpl /* AACDB_FLAGS_FW_PRINT | */
4101dd0a2dbSpl /* AACDB_FLAGS_MISC | */
4111dd0a2dbSpl /* AACDB_FLAGS_FUNC1 | */
4121dd0a2dbSpl /* AACDB_FLAGS_FUNC2 | */
4131dd0a2dbSpl /* AACDB_FLAGS_SCMD | */
4141dd0a2dbSpl /* AACDB_FLAGS_AIF | */
4151dd0a2dbSpl /* AACDB_FLAGS_FIB | */
4161dd0a2dbSpl /* AACDB_FLAGS_IOCTL | */
4171dd0a2dbSpl 0;
41858bc78c7SXin Chen uint32_t aac_debug_fib_flags =
41958bc78c7SXin Chen /* AACDB_FLAGS_FIB_RW | */
42058bc78c7SXin Chen /* AACDB_FLAGS_FIB_IOCTL | */
42158bc78c7SXin Chen /* AACDB_FLAGS_FIB_SRB | */
42258bc78c7SXin Chen /* AACDB_FLAGS_FIB_SYNC | */
42358bc78c7SXin Chen /* AACDB_FLAGS_FIB_HEADER | */
42458bc78c7SXin Chen /* AACDB_FLAGS_FIB_TIMEOUT | */
42558bc78c7SXin Chen 0;
4261dd0a2dbSpl
4271dd0a2dbSpl #endif /* DEBUG */
4281dd0a2dbSpl
429830d82f7Spl static struct cb_ops aac_cb_ops = {
430830d82f7Spl aac_open, /* open */
431830d82f7Spl aac_close, /* close */
432830d82f7Spl nodev, /* strategy */
433830d82f7Spl nodev, /* print */
434830d82f7Spl nodev, /* dump */
435830d82f7Spl nodev, /* read */
436830d82f7Spl nodev, /* write */
437830d82f7Spl aac_ioctl, /* ioctl */
438830d82f7Spl nodev, /* devmap */
439830d82f7Spl nodev, /* mmap */
440830d82f7Spl nodev, /* segmap */
441830d82f7Spl nochpoll, /* poll */
442d7c5bf88Spl ddi_prop_op, /* cb_prop_op */
443830d82f7Spl NULL, /* streamtab */
444830d82f7Spl D_64BIT | D_NEW | D_MP | D_HOTPLUG, /* cb_flag */
445830d82f7Spl CB_REV, /* cb_rev */
446830d82f7Spl nodev, /* async I/O read entry point */
447830d82f7Spl nodev /* async I/O write entry point */
448830d82f7Spl };
449830d82f7Spl
4507c478bd9Sstevel@tonic-gate static struct dev_ops aac_dev_ops = {
4517c478bd9Sstevel@tonic-gate DEVO_REV,
4527c478bd9Sstevel@tonic-gate 0,
453f42c2f53Szhongyan gu - Sun Microsystems - Beijing China aac_getinfo,
4547c478bd9Sstevel@tonic-gate nulldev,
4557c478bd9Sstevel@tonic-gate nulldev,
4567c478bd9Sstevel@tonic-gate aac_attach,
4577c478bd9Sstevel@tonic-gate aac_detach,
458830d82f7Spl aac_reset,
459830d82f7Spl &aac_cb_ops,
4607c478bd9Sstevel@tonic-gate NULL,
46119397407SSherry Moore NULL,
46219397407SSherry Moore aac_quiesce,
4637c478bd9Sstevel@tonic-gate };
4647c478bd9Sstevel@tonic-gate
4657c478bd9Sstevel@tonic-gate static struct modldrv aac_modldrv = {
4667c478bd9Sstevel@tonic-gate &mod_driverops,
467832e0b5aSpl "AAC Driver " AAC_DRIVER_VERSION,
4687c478bd9Sstevel@tonic-gate &aac_dev_ops,
4697c478bd9Sstevel@tonic-gate };
4707c478bd9Sstevel@tonic-gate
4717c478bd9Sstevel@tonic-gate static struct modlinkage aac_modlinkage = {
4727c478bd9Sstevel@tonic-gate MODREV_1,
4737c478bd9Sstevel@tonic-gate &aac_modldrv,
4747c478bd9Sstevel@tonic-gate NULL
4757c478bd9Sstevel@tonic-gate };
4767c478bd9Sstevel@tonic-gate
4777c478bd9Sstevel@tonic-gate static struct aac_softstate *aac_softstatep;
4787c478bd9Sstevel@tonic-gate
479830d82f7Spl /*
480d937e6ebSpl * Supported card list
481d937e6ebSpl * ordered in vendor id, subvendor id, subdevice id, and device id
482830d82f7Spl */
4837c478bd9Sstevel@tonic-gate static struct aac_card_type aac_cards[] = {
484d937e6ebSpl {0x1028, 0x1, 0x1028, 0x1, AAC_HWIF_I960RX,
485382c8bcaSpl AAC_FLAGS_NO4GB | AAC_FLAGS_34SG, AAC_TYPE_SCSI,
486382c8bcaSpl "Dell", "PERC 3/Di"},
487d937e6ebSpl {0x1028, 0x2, 0x1028, 0x2, AAC_HWIF_I960RX,
488382c8bcaSpl AAC_FLAGS_NO4GB | AAC_FLAGS_34SG, AAC_TYPE_SCSI,
489382c8bcaSpl "Dell", "PERC 3/Di"},
490d937e6ebSpl {0x1028, 0x3, 0x1028, 0x3, AAC_HWIF_I960RX,
491382c8bcaSpl AAC_FLAGS_NO4GB | AAC_FLAGS_34SG, AAC_TYPE_SCSI,
492382c8bcaSpl "Dell", "PERC 3/Si"},
493830d82f7Spl {0x1028, 0x8, 0x1028, 0xcf, AAC_HWIF_I960RX,
494382c8bcaSpl AAC_FLAGS_NO4GB | AAC_FLAGS_34SG, AAC_TYPE_SCSI,
495382c8bcaSpl "Dell", "PERC 3/Di"},
496d937e6ebSpl {0x1028, 0x4, 0x1028, 0xd0, AAC_HWIF_I960RX,
497382c8bcaSpl AAC_FLAGS_NO4GB | AAC_FLAGS_34SG, AAC_TYPE_SCSI,
498382c8bcaSpl "Dell", "PERC 3/Si"},
499d937e6ebSpl {0x1028, 0x2, 0x1028, 0xd1, AAC_HWIF_I960RX,
500382c8bcaSpl AAC_FLAGS_NO4GB | AAC_FLAGS_34SG, AAC_TYPE_SCSI,
501382c8bcaSpl "Dell", "PERC 3/Di"},
502830d82f7Spl {0x1028, 0x2, 0x1028, 0xd9, AAC_HWIF_I960RX,
503382c8bcaSpl AAC_FLAGS_NO4GB | AAC_FLAGS_34SG, AAC_TYPE_SCSI,
504382c8bcaSpl "Dell", "PERC 3/Di"},
505d937e6ebSpl {0x1028, 0xa, 0x1028, 0x106, AAC_HWIF_I960RX,
506382c8bcaSpl AAC_FLAGS_NO4GB | AAC_FLAGS_34SG, AAC_TYPE_SCSI,
507382c8bcaSpl "Dell", "PERC 3/Di"},
508d937e6ebSpl {0x1028, 0xa, 0x1028, 0x11b, AAC_HWIF_I960RX,
509382c8bcaSpl AAC_FLAGS_NO4GB | AAC_FLAGS_34SG, AAC_TYPE_SCSI,
510382c8bcaSpl "Dell", "PERC 3/Di"},
511d937e6ebSpl {0x1028, 0xa, 0x1028, 0x121, AAC_HWIF_I960RX,
512382c8bcaSpl AAC_FLAGS_NO4GB | AAC_FLAGS_34SG, AAC_TYPE_SCSI,
513382c8bcaSpl "Dell", "PERC 3/Di"},
514d937e6ebSpl {0x9005, 0x285, 0x1028, 0x287, AAC_HWIF_I960RX,
515382c8bcaSpl AAC_FLAGS_NO4GB | AAC_FLAGS_34SG | AAC_FLAGS_256FIBS, AAC_TYPE_SCSI,
516c9487164Spl "Dell", "PERC 320/DC"},
517d937e6ebSpl {0x9005, 0x285, 0x1028, 0x291, AAC_HWIF_I960RX,
518382c8bcaSpl AAC_FLAGS_17SG, AAC_TYPE_SATA, "Dell", "CERC SR2"},
519d937e6ebSpl
520d937e6ebSpl {0x9005, 0x285, 0x1014, 0x2f2, AAC_HWIF_I960RX,
521c9487164Spl 0, AAC_TYPE_SCSI, "IBM", "ServeRAID 8i"},
522d937e6ebSpl {0x9005, 0x285, 0x1014, 0x34d, AAC_HWIF_I960RX,
523c9487164Spl 0, AAC_TYPE_SAS, "IBM", "ServeRAID 8s"},
524d937e6ebSpl {0x9005, 0x286, 0x1014, 0x9580, AAC_HWIF_RKT,
525c9487164Spl 0, AAC_TYPE_SAS, "IBM", "ServeRAID 8k"},
526830d82f7Spl
527d937e6ebSpl {0x9005, 0x285, 0x103c, 0x3227, AAC_HWIF_I960RX,
528382c8bcaSpl AAC_FLAGS_17SG, AAC_TYPE_SATA, "Adaptec", "2610SA"},
529382c8bcaSpl {0x9005, 0x285, 0xe11, 0x295, AAC_HWIF_I960RX,
530382c8bcaSpl AAC_FLAGS_17SG, AAC_TYPE_SATA, "Adaptec", "2610SA"},
531d937e6ebSpl
532d937e6ebSpl {0x9005, 0x285, 0x9005, 0x285, AAC_HWIF_I960RX,
533382c8bcaSpl AAC_FLAGS_NO4GB | AAC_FLAGS_34SG | AAC_FLAGS_256FIBS, AAC_TYPE_SCSI,
534c9487164Spl "Adaptec", "2200S"},
535d937e6ebSpl {0x9005, 0x285, 0x9005, 0x286, AAC_HWIF_I960RX,
536382c8bcaSpl AAC_FLAGS_NO4GB | AAC_FLAGS_34SG | AAC_FLAGS_256FIBS, AAC_TYPE_SCSI,
537c9487164Spl "Adaptec", "2120S"},
538830d82f7Spl {0x9005, 0x285, 0x9005, 0x287, AAC_HWIF_I960RX,
539382c8bcaSpl AAC_FLAGS_NO4GB | AAC_FLAGS_34SG | AAC_FLAGS_256FIBS, AAC_TYPE_SCSI,
540c9487164Spl "Adaptec", "2200S"},
541830d82f7Spl {0x9005, 0x285, 0x9005, 0x288, AAC_HWIF_I960RX,
542c9487164Spl 0, AAC_TYPE_SCSI, "Adaptec", "3230S"},
543830d82f7Spl {0x9005, 0x285, 0x9005, 0x289, AAC_HWIF_I960RX,
544c9487164Spl 0, AAC_TYPE_SCSI, "Adaptec", "3240S"},
545830d82f7Spl {0x9005, 0x285, 0x9005, 0x28a, AAC_HWIF_I960RX,
546c9487164Spl 0, AAC_TYPE_SCSI, "Adaptec", "2020ZCR"},
547830d82f7Spl {0x9005, 0x285, 0x9005, 0x28b, AAC_HWIF_I960RX,
548c9487164Spl 0, AAC_TYPE_SCSI, "Adaptec", "2025ZCR"},
549830d82f7Spl {0x9005, 0x286, 0x9005, 0x28c, AAC_HWIF_RKT,
550c9487164Spl 0, AAC_TYPE_SCSI, "Adaptec", "2230S"},
551830d82f7Spl {0x9005, 0x286, 0x9005, 0x28d, AAC_HWIF_RKT,
552c9487164Spl 0, AAC_TYPE_SCSI, "Adaptec", "2130S"},
553830d82f7Spl {0x9005, 0x285, 0x9005, 0x28e, AAC_HWIF_I960RX,
554c9487164Spl 0, AAC_TYPE_SATA, "Adaptec", "2020SA"},
555830d82f7Spl {0x9005, 0x285, 0x9005, 0x28f, AAC_HWIF_I960RX,
556c9487164Spl 0, AAC_TYPE_SATA, "Adaptec", "2025SA"},
557d937e6ebSpl {0x9005, 0x285, 0x9005, 0x290, AAC_HWIF_I960RX,
558382c8bcaSpl AAC_FLAGS_17SG, AAC_TYPE_SATA, "Adaptec", "2410SA"},
559830d82f7Spl {0x9005, 0x285, 0x9005, 0x292, AAC_HWIF_I960RX,
560382c8bcaSpl AAC_FLAGS_17SG, AAC_TYPE_SATA, "Adaptec", "2810SA"},
561830d82f7Spl {0x9005, 0x285, 0x9005, 0x293, AAC_HWIF_I960RX,
562382c8bcaSpl AAC_FLAGS_17SG, AAC_TYPE_SATA, "Adaptec", "21610SA"},
563830d82f7Spl {0x9005, 0x285, 0x9005, 0x294, AAC_HWIF_I960RX,
564c9487164Spl 0, AAC_TYPE_SATA, "Adaptec", "2026ZCR"},
565830d82f7Spl {0x9005, 0x285, 0x9005, 0x296, AAC_HWIF_I960RX,
566c9487164Spl 0, AAC_TYPE_SCSI, "Adaptec", "2240S"},
567830d82f7Spl {0x9005, 0x285, 0x9005, 0x297, AAC_HWIF_I960RX,
568c9487164Spl 0, AAC_TYPE_SAS, "Adaptec", "4005SAS"},
569830d82f7Spl {0x9005, 0x285, 0x9005, 0x298, AAC_HWIF_I960RX,
570c9487164Spl 0, AAC_TYPE_SAS, "Adaptec", "RAID 4000"},
571830d82f7Spl {0x9005, 0x285, 0x9005, 0x299, AAC_HWIF_I960RX,
572c9487164Spl 0, AAC_TYPE_SAS, "Adaptec", "4800SAS"},
573830d82f7Spl {0x9005, 0x285, 0x9005, 0x29a, AAC_HWIF_I960RX,
574c9487164Spl 0, AAC_TYPE_SAS, "Adaptec", "4805SAS"},
575830d82f7Spl {0x9005, 0x286, 0x9005, 0x29b, AAC_HWIF_RKT,
576c9487164Spl 0, AAC_TYPE_SATA, "Adaptec", "2820SA"},
577830d82f7Spl {0x9005, 0x286, 0x9005, 0x29c, AAC_HWIF_RKT,
578c9487164Spl 0, AAC_TYPE_SATA, "Adaptec", "2620SA"},
579830d82f7Spl {0x9005, 0x286, 0x9005, 0x29d, AAC_HWIF_RKT,
580c9487164Spl 0, AAC_TYPE_SATA, "Adaptec", "2420SA"},
581830d82f7Spl {0x9005, 0x286, 0x9005, 0x29e, AAC_HWIF_RKT,
582c9487164Spl 0, AAC_TYPE_SATA, "ICP", "9024RO"},
583830d82f7Spl {0x9005, 0x286, 0x9005, 0x29f, AAC_HWIF_RKT,
584c9487164Spl 0, AAC_TYPE_SATA, "ICP", "9014RO"},
585830d82f7Spl {0x9005, 0x286, 0x9005, 0x2a0, AAC_HWIF_RKT,
586c9487164Spl 0, AAC_TYPE_SATA, "ICP", "9047MA"},
587830d82f7Spl {0x9005, 0x286, 0x9005, 0x2a1, AAC_HWIF_RKT,
588c9487164Spl 0, AAC_TYPE_SATA, "ICP", "9087MA"},
589830d82f7Spl {0x9005, 0x285, 0x9005, 0x2a4, AAC_HWIF_I960RX,
590c9487164Spl 0, AAC_TYPE_SAS, "ICP", "9085LI"},
591830d82f7Spl {0x9005, 0x285, 0x9005, 0x2a5, AAC_HWIF_I960RX,
592c9487164Spl 0, AAC_TYPE_SAS, "ICP", "5085BR"},
593830d82f7Spl {0x9005, 0x286, 0x9005, 0x2a6, AAC_HWIF_RKT,
594c9487164Spl 0, AAC_TYPE_SATA, "ICP", "9067MA"},
595830d82f7Spl {0x9005, 0x285, 0x9005, 0x2b5, AAC_HWIF_I960RX,
596c9487164Spl 0, AAC_TYPE_SAS, "Adaptec", "RAID 5445"},
597830d82f7Spl {0x9005, 0x285, 0x9005, 0x2b6, AAC_HWIF_I960RX,
598c9487164Spl 0, AAC_TYPE_SAS, "Adaptec", "RAID 5805"},
599830d82f7Spl {0x9005, 0x285, 0x9005, 0x2b7, AAC_HWIF_I960RX,
600c9487164Spl 0, AAC_TYPE_SAS, "Adaptec", "RAID 5085"},
601832e0b5aSpl {0x9005, 0x285, 0x9005, 0x2b8, AAC_HWIF_I960RX,
602c9487164Spl 0, AAC_TYPE_SAS, "ICP", "RAID ICP5445SL"},
603832e0b5aSpl {0x9005, 0x285, 0x9005, 0x2b9, AAC_HWIF_I960RX,
604c9487164Spl 0, AAC_TYPE_SAS, "ICP", "RAID ICP5085SL"},
605832e0b5aSpl {0x9005, 0x285, 0x9005, 0x2ba, AAC_HWIF_I960RX,
606c9487164Spl 0, AAC_TYPE_SAS, "ICP", "RAID ICP5805SL"},
607830d82f7Spl
608830d82f7Spl {0, 0, 0, 0, AAC_HWIF_UNKNOWN,
609c9487164Spl 0, AAC_TYPE_UNKNOWN, "Unknown", "AAC card"},
610c9487164Spl };
611c9487164Spl
612c9487164Spl /*
613c9487164Spl * Hardware access functions for i960 based cards
614c9487164Spl */
615c9487164Spl static struct aac_interface aac_rx_interface = {
616c9487164Spl aac_rx_get_fwstatus,
617c9487164Spl aac_rx_get_mailbox,
618c9487164Spl aac_rx_set_mailbox
619c9487164Spl };
620c9487164Spl
621c9487164Spl /*
622c9487164Spl * Hardware access functions for Rocket based cards
623c9487164Spl */
624c9487164Spl static struct aac_interface aac_rkt_interface = {
625c9487164Spl aac_rkt_get_fwstatus,
626c9487164Spl aac_rkt_get_mailbox,
627c9487164Spl aac_rkt_set_mailbox
6287c478bd9Sstevel@tonic-gate };
6297c478bd9Sstevel@tonic-gate
630830d82f7Spl ddi_device_acc_attr_t aac_acc_attr = {
631837c1ac4SStephen Hanson DDI_DEVICE_ATTR_V1,
6327c478bd9Sstevel@tonic-gate DDI_STRUCTURE_LE_ACC,
633837c1ac4SStephen Hanson DDI_STRICTORDER_ACC,
634837c1ac4SStephen Hanson DDI_DEFAULT_ACC
6357c478bd9Sstevel@tonic-gate };
6367c478bd9Sstevel@tonic-gate
6377c478bd9Sstevel@tonic-gate static struct {
6387c478bd9Sstevel@tonic-gate int size;
6397c478bd9Sstevel@tonic-gate int notify;
6407c478bd9Sstevel@tonic-gate } aac_qinfo[] = {
6417c478bd9Sstevel@tonic-gate {AAC_HOST_NORM_CMD_ENTRIES, AAC_DB_COMMAND_NOT_FULL},
6427c478bd9Sstevel@tonic-gate {AAC_HOST_HIGH_CMD_ENTRIES, 0},
6437c478bd9Sstevel@tonic-gate {AAC_ADAP_NORM_CMD_ENTRIES, AAC_DB_COMMAND_READY},
6447c478bd9Sstevel@tonic-gate {AAC_ADAP_HIGH_CMD_ENTRIES, 0},
6457c478bd9Sstevel@tonic-gate {AAC_HOST_NORM_RESP_ENTRIES, AAC_DB_RESPONSE_NOT_FULL},
6467c478bd9Sstevel@tonic-gate {AAC_HOST_HIGH_RESP_ENTRIES, 0},
6477c478bd9Sstevel@tonic-gate {AAC_ADAP_NORM_RESP_ENTRIES, AAC_DB_RESPONSE_READY},
6487c478bd9Sstevel@tonic-gate {AAC_ADAP_HIGH_RESP_ENTRIES, 0}
6497c478bd9Sstevel@tonic-gate };
6507c478bd9Sstevel@tonic-gate
651830d82f7Spl /*
652830d82f7Spl * Default aac dma attributes
653830d82f7Spl */
654382c8bcaSpl static ddi_dma_attr_t aac_dma_attr = {
655c9487164Spl DMA_ATTR_V0,
656382c8bcaSpl 0, /* lowest usable address */
657c9487164Spl 0xffffffffull, /* high DMA address range */
658382c8bcaSpl 0xffffffffull, /* DMA counter register */
659c9487164Spl AAC_DMA_ALIGN, /* DMA address alignment */
660c9487164Spl 1, /* DMA burstsizes */
661c9487164Spl 1, /* min effective DMA size */
662c9487164Spl 0xffffffffull, /* max DMA xfer size */
663c9487164Spl 0xffffffffull, /* segment boundary */
664382c8bcaSpl 1, /* s/g list length */
665c9487164Spl AAC_BLK_SIZE, /* granularity of device */
66658bc78c7SXin Chen 0 /* DMA transfer flags */
66758bc78c7SXin Chen };
66858bc78c7SXin Chen
669382c8bcaSpl static int aac_tick = AAC_DEFAULT_TICK; /* tick for the internal timer */
670382c8bcaSpl static uint32_t aac_timebase = 0; /* internal timer in seconds */
671382c8bcaSpl
672382c8bcaSpl /*
673382c8bcaSpl * Warlock directives
674382c8bcaSpl *
675382c8bcaSpl * Different variables with the same types have to be protected by the
676382c8bcaSpl * same mutex; otherwise, warlock will complain with "variables don't
677382c8bcaSpl * seem to be protected consistently". For example,
678382c8bcaSpl * aac_softstate::{q_wait, q_comp} are type of aac_cmd_queue, and protected
679382c8bcaSpl * by aac_softstate::{io_lock, q_comp_mutex} respectively. We have to
680382c8bcaSpl * declare them as protected explictly at aac_cmd_dequeue().
681382c8bcaSpl */
682382c8bcaSpl _NOTE(SCHEME_PROTECTS_DATA("unique per pkt", scsi_pkt scsi_cdb scsi_status \
683382c8bcaSpl scsi_arq_status scsi_descr_sense_hdr scsi_information_sense_descr \
684382c8bcaSpl mode_format mode_geometry mode_header aac_cmd))
685942c5e3cSpl _NOTE(SCHEME_PROTECTS_DATA("unique per aac_cmd", aac_fib ddi_dma_cookie_t \
686942c5e3cSpl aac_sge))
687382c8bcaSpl _NOTE(SCHEME_PROTECTS_DATA("unique per aac_fib", aac_blockread aac_blockwrite \
688382c8bcaSpl aac_blockread64 aac_raw_io aac_sg_entry aac_sg_entry64 aac_sg_entryraw \
689382c8bcaSpl aac_sg_table aac_srb))
690382c8bcaSpl _NOTE(SCHEME_PROTECTS_DATA("unique to sync fib and cdb", scsi_inquiry))
691382c8bcaSpl _NOTE(SCHEME_PROTECTS_DATA("stable data", scsi_device scsi_address))
69258bc78c7SXin Chen _NOTE(SCHEME_PROTECTS_DATA("unique to scsi_transport", buf))
6937c478bd9Sstevel@tonic-gate
6947c478bd9Sstevel@tonic-gate int
_init(void)6957c478bd9Sstevel@tonic-gate _init(void)
6967c478bd9Sstevel@tonic-gate {
697c9487164Spl int rval = 0;
6987c478bd9Sstevel@tonic-gate
6991dd0a2dbSpl #ifdef DEBUG
7001dd0a2dbSpl mutex_init(&aac_prt_mutex, NULL, MUTEX_DRIVER, NULL);
7011dd0a2dbSpl #endif
7021dd0a2dbSpl DBCALLED(NULL, 1);
703830d82f7Spl
704c9487164Spl if ((rval = ddi_soft_state_init((void *)&aac_softstatep,
705c9487164Spl sizeof (struct aac_softstate), 0)) != 0)
7067c478bd9Sstevel@tonic-gate goto error;
7077c478bd9Sstevel@tonic-gate
708c9487164Spl if ((rval = scsi_hba_init(&aac_modlinkage)) != 0) {
709c9487164Spl ddi_soft_state_fini((void *)&aac_softstatep);
7107c478bd9Sstevel@tonic-gate goto error;
7117c478bd9Sstevel@tonic-gate }
7127c478bd9Sstevel@tonic-gate
713c9487164Spl if ((rval = mod_install(&aac_modlinkage)) != 0) {
714c9487164Spl ddi_soft_state_fini((void *)&aac_softstatep);
7157c478bd9Sstevel@tonic-gate scsi_hba_fini(&aac_modlinkage);
7167c478bd9Sstevel@tonic-gate goto error;
7177c478bd9Sstevel@tonic-gate }
718c9487164Spl return (rval);
719830d82f7Spl
7207c478bd9Sstevel@tonic-gate error:
7211dd0a2dbSpl AACDB_PRINT(NULL, CE_WARN, "Mod init error!");
7221dd0a2dbSpl #ifdef DEBUG
7231dd0a2dbSpl mutex_destroy(&aac_prt_mutex);
7241dd0a2dbSpl #endif
725c9487164Spl return (rval);
7267c478bd9Sstevel@tonic-gate }
7277c478bd9Sstevel@tonic-gate
7287c478bd9Sstevel@tonic-gate int
_info(struct modinfo * modinfop)7297c478bd9Sstevel@tonic-gate _info(struct modinfo *modinfop)
7307c478bd9Sstevel@tonic-gate {
7311dd0a2dbSpl DBCALLED(NULL, 1);
7327c478bd9Sstevel@tonic-gate return (mod_info(&aac_modlinkage, modinfop));
7337c478bd9Sstevel@tonic-gate }
7347c478bd9Sstevel@tonic-gate
7357c478bd9Sstevel@tonic-gate /*
736830d82f7Spl * An HBA driver cannot be unload unless you reboot,
737830d82f7Spl * so this function will be of no use.
7387c478bd9Sstevel@tonic-gate */
7397c478bd9Sstevel@tonic-gate int
_fini(void)7407c478bd9Sstevel@tonic-gate _fini(void)
7417c478bd9Sstevel@tonic-gate {
742c9487164Spl int rval;
7437c478bd9Sstevel@tonic-gate
7441dd0a2dbSpl DBCALLED(NULL, 1);
745830d82f7Spl
746c9487164Spl if ((rval = mod_remove(&aac_modlinkage)) != 0)
7477c478bd9Sstevel@tonic-gate goto error;
7487c478bd9Sstevel@tonic-gate
7497c478bd9Sstevel@tonic-gate scsi_hba_fini(&aac_modlinkage);
750c9487164Spl ddi_soft_state_fini((void *)&aac_softstatep);
7511dd0a2dbSpl #ifdef DEBUG
7521dd0a2dbSpl mutex_destroy(&aac_prt_mutex);
7531dd0a2dbSpl #endif
7547c478bd9Sstevel@tonic-gate return (0);
755830d82f7Spl
7567c478bd9Sstevel@tonic-gate error:
7571dd0a2dbSpl AACDB_PRINT(NULL, CE_WARN, "AAC is busy, cannot unload!");
758c9487164Spl return (rval);
7597c478bd9Sstevel@tonic-gate }
7607c478bd9Sstevel@tonic-gate
7617c478bd9Sstevel@tonic-gate static int
aac_attach(dev_info_t * dip,ddi_attach_cmd_t cmd)7627c478bd9Sstevel@tonic-gate aac_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
7637c478bd9Sstevel@tonic-gate {
764382c8bcaSpl int instance, i;
7651dd0a2dbSpl struct aac_softstate *softs = NULL;
7667c478bd9Sstevel@tonic-gate int attach_state = 0;
76758bc78c7SXin Chen char *data;
7687c478bd9Sstevel@tonic-gate
7691dd0a2dbSpl DBCALLED(NULL, 1);
7707c478bd9Sstevel@tonic-gate
7717c478bd9Sstevel@tonic-gate switch (cmd) {
772830d82f7Spl case DDI_ATTACH:
773830d82f7Spl break;
774830d82f7Spl case DDI_RESUME:
775830d82f7Spl return (DDI_FAILURE);
776830d82f7Spl default:
777830d82f7Spl return (DDI_FAILURE);
7787c478bd9Sstevel@tonic-gate }
7797c478bd9Sstevel@tonic-gate
7807c478bd9Sstevel@tonic-gate instance = ddi_get_instance(dip);
7817c478bd9Sstevel@tonic-gate
782830d82f7Spl /* Get soft state */
7837c478bd9Sstevel@tonic-gate if (ddi_soft_state_zalloc(aac_softstatep, instance) != DDI_SUCCESS) {
7841dd0a2dbSpl AACDB_PRINT(softs, CE_WARN, "Cannot alloc soft state");
7857c478bd9Sstevel@tonic-gate goto error;
7867c478bd9Sstevel@tonic-gate }
7877c478bd9Sstevel@tonic-gate softs = ddi_get_soft_state(aac_softstatep, instance);
788d937e6ebSpl attach_state |= AAC_ATTACH_SOFTSTATE_ALLOCED;
7897c478bd9Sstevel@tonic-gate
790382c8bcaSpl softs->instance = instance;
791d937e6ebSpl softs->devinfo_p = dip;
792382c8bcaSpl softs->buf_dma_attr = softs->addr_dma_attr = aac_dma_attr;
793382c8bcaSpl softs->addr_dma_attr.dma_attr_granular = 1;
79458bc78c7SXin Chen softs->acc_attr = aac_acc_attr;
795837c1ac4SStephen Hanson softs->reg_attr = aac_acc_attr;
796d937e6ebSpl softs->card = AAC_UNKNOWN_CARD;
7971dd0a2dbSpl #ifdef DEBUG
7981dd0a2dbSpl softs->debug_flags = aac_debug_flags;
79958bc78c7SXin Chen softs->debug_fib_flags = aac_debug_fib_flags;
8001dd0a2dbSpl #endif
801830d82f7Spl
80258bc78c7SXin Chen /* Initialize FMA */
80358bc78c7SXin Chen aac_fm_init(softs);
80458bc78c7SXin Chen
805830d82f7Spl /* Check the card type */
806d937e6ebSpl if (aac_check_card_type(softs) == AACERR) {
8071dd0a2dbSpl AACDB_PRINT(softs, CE_WARN, "Card not supported");
8087c478bd9Sstevel@tonic-gate goto error;
809830d82f7Spl }
810830d82f7Spl /* We have found the right card and everything is OK */
811830d82f7Spl attach_state |= AAC_ATTACH_CARD_DETECTED;
812830d82f7Spl
813830d82f7Spl /* Map PCI mem space */
814830d82f7Spl if (ddi_regs_map_setup(dip, 1,
8151dd0a2dbSpl (caddr_t *)&softs->pci_mem_base_vaddr, 0,
816837c1ac4SStephen Hanson softs->map_size_min, &softs->reg_attr,
817c9487164Spl &softs->pci_mem_handle) != DDI_SUCCESS)
818830d82f7Spl goto error;
819830d82f7Spl
820830d82f7Spl softs->map_size = softs->map_size_min;
821830d82f7Spl attach_state |= AAC_ATTACH_PCI_MEM_MAPPED;
8227c478bd9Sstevel@tonic-gate
8237c478bd9Sstevel@tonic-gate AAC_DISABLE_INTR(softs);
8247c478bd9Sstevel@tonic-gate
825f42c2f53Szhongyan gu - Sun Microsystems - Beijing China /* Init mutexes and condvars */
8260749e8deSXin Chen - Sun Microsystems - Beijing China mutex_init(&softs->io_lock, NULL, MUTEX_DRIVER,
8270749e8deSXin Chen - Sun Microsystems - Beijing China DDI_INTR_PRI(softs->intr_pri));
8280749e8deSXin Chen - Sun Microsystems - Beijing China mutex_init(&softs->q_comp_mutex, NULL, MUTEX_DRIVER,
8290749e8deSXin Chen - Sun Microsystems - Beijing China DDI_INTR_PRI(softs->intr_pri));
8300749e8deSXin Chen - Sun Microsystems - Beijing China mutex_init(&softs->time_mutex, NULL, MUTEX_DRIVER,
8310749e8deSXin Chen - Sun Microsystems - Beijing China DDI_INTR_PRI(softs->intr_pri));
8320749e8deSXin Chen - Sun Microsystems - Beijing China mutex_init(&softs->ev_lock, NULL, MUTEX_DRIVER,
8330749e8deSXin Chen - Sun Microsystems - Beijing China DDI_INTR_PRI(softs->intr_pri));
8340749e8deSXin Chen - Sun Microsystems - Beijing China mutex_init(&softs->aifq_mutex, NULL,
835b6094a86Sjd MUTEX_DRIVER, DDI_INTR_PRI(softs->intr_pri));
836830d82f7Spl cv_init(&softs->event, NULL, CV_DRIVER, NULL);
8371ee13a44SXinChen cv_init(&softs->sync_fib_cv, NULL, CV_DRIVER, NULL);
838382c8bcaSpl cv_init(&softs->drain_cv, NULL, CV_DRIVER, NULL);
8390749e8deSXin Chen - Sun Microsystems - Beijing China cv_init(&softs->event_wait_cv, NULL, CV_DRIVER, NULL);
8400749e8deSXin Chen - Sun Microsystems - Beijing China cv_init(&softs->event_disp_cv, NULL, CV_DRIVER, NULL);
8410749e8deSXin Chen - Sun Microsystems - Beijing China cv_init(&softs->aifq_cv, NULL, CV_DRIVER, NULL);
842830d82f7Spl attach_state |= AAC_ATTACH_KMUTEX_INITED;
843830d82f7Spl
844f42c2f53Szhongyan gu - Sun Microsystems - Beijing China /* Init the cmd queues */
845f42c2f53Szhongyan gu - Sun Microsystems - Beijing China for (i = 0; i < AAC_CMDQ_NUM; i++)
846f42c2f53Szhongyan gu - Sun Microsystems - Beijing China aac_cmd_initq(&softs->q_wait[i]);
847f42c2f53Szhongyan gu - Sun Microsystems - Beijing China aac_cmd_initq(&softs->q_busy);
848f42c2f53Szhongyan gu - Sun Microsystems - Beijing China aac_cmd_initq(&softs->q_comp);
849f42c2f53Szhongyan gu - Sun Microsystems - Beijing China
85058bc78c7SXin Chen /* Check for legacy device naming support */
85158bc78c7SXin Chen softs->legacy = 1; /* default to use legacy name */
85258bc78c7SXin Chen if ((ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, 0,
85358bc78c7SXin Chen "legacy-name-enable", &data) == DDI_SUCCESS)) {
85458bc78c7SXin Chen if (strcmp(data, "no") == 0) {
85558bc78c7SXin Chen AACDB_PRINT(softs, CE_NOTE, "legacy-name disabled");
85658bc78c7SXin Chen softs->legacy = 0;
85758bc78c7SXin Chen }
85858bc78c7SXin Chen ddi_prop_free(data);
85958bc78c7SXin Chen }
86058bc78c7SXin Chen
861830d82f7Spl /*
862830d82f7Spl * Everything has been set up till now,
863830d82f7Spl * we will do some common attach.
864830d82f7Spl */
865f42c2f53Szhongyan gu - Sun Microsystems - Beijing China mutex_enter(&softs->io_lock);
866f42c2f53Szhongyan gu - Sun Microsystems - Beijing China if (aac_common_attach(softs) == AACERR) {
867f42c2f53Szhongyan gu - Sun Microsystems - Beijing China mutex_exit(&softs->io_lock);
868830d82f7Spl goto error;
869f42c2f53Szhongyan gu - Sun Microsystems - Beijing China }
870f42c2f53Szhongyan gu - Sun Microsystems - Beijing China mutex_exit(&softs->io_lock);
871830d82f7Spl attach_state |= AAC_ATTACH_COMM_SPACE_SETUP;
872830d82f7Spl
87372888e72Speng liu - Sun Microsystems - Beijing China /* Check for buf breakup support */
87472888e72Speng liu - Sun Microsystems - Beijing China if ((ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, 0,
87572888e72Speng liu - Sun Microsystems - Beijing China "breakup-enable", &data) == DDI_SUCCESS)) {
87672888e72Speng liu - Sun Microsystems - Beijing China if (strcmp(data, "yes") == 0) {
87772888e72Speng liu - Sun Microsystems - Beijing China AACDB_PRINT(softs, CE_NOTE, "buf breakup enabled");
87872888e72Speng liu - Sun Microsystems - Beijing China softs->flags |= AAC_FLAGS_BRKUP;
87972888e72Speng liu - Sun Microsystems - Beijing China }
88072888e72Speng liu - Sun Microsystems - Beijing China ddi_prop_free(data);
88172888e72Speng liu - Sun Microsystems - Beijing China }
88272888e72Speng liu - Sun Microsystems - Beijing China softs->dma_max = softs->buf_dma_attr.dma_attr_maxxfer;
88372888e72Speng liu - Sun Microsystems - Beijing China if (softs->flags & AAC_FLAGS_BRKUP) {
88472888e72Speng liu - Sun Microsystems - Beijing China softs->dma_max = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
88572888e72Speng liu - Sun Microsystems - Beijing China DDI_PROP_DONTPASS, "dma-max", softs->dma_max);
88672888e72Speng liu - Sun Microsystems - Beijing China }
88772888e72Speng liu - Sun Microsystems - Beijing China
888830d82f7Spl if (aac_hba_setup(softs) != AACOK)
889830d82f7Spl goto error;
890830d82f7Spl attach_state |= AAC_ATTACH_SCSI_TRAN_SETUP;
8917c478bd9Sstevel@tonic-gate
892830d82f7Spl /* Create devctl/scsi nodes for cfgadm */
893830d82f7Spl if (ddi_create_minor_node(dip, "devctl", S_IFCHR,
894c9487164Spl INST2DEVCTL(instance), DDI_NT_SCSI_NEXUS, 0) != DDI_SUCCESS) {
8951dd0a2dbSpl AACDB_PRINT(softs, CE_WARN, "failed to create devctl node");
8967c478bd9Sstevel@tonic-gate goto error;
897830d82f7Spl }
898830d82f7Spl attach_state |= AAC_ATTACH_CREATE_DEVCTL;
8997c478bd9Sstevel@tonic-gate
900c9487164Spl if (ddi_create_minor_node(dip, "scsi", S_IFCHR, INST2SCSI(instance),
901c9487164Spl DDI_NT_SCSI_ATTACHMENT_POINT, 0) != DDI_SUCCESS) {
9021dd0a2dbSpl AACDB_PRINT(softs, CE_WARN, "failed to create scsi node");
9037c478bd9Sstevel@tonic-gate goto error;
904830d82f7Spl }
905830d82f7Spl attach_state |= AAC_ATTACH_CREATE_SCSI;
906830d82f7Spl
907c9487164Spl /* Create aac node for app. to issue ioctls */
908c9487164Spl if (ddi_create_minor_node(dip, "aac", S_IFCHR, INST2AAC(instance),
909c9487164Spl DDI_PSEUDO, 0) != DDI_SUCCESS) {
9101dd0a2dbSpl AACDB_PRINT(softs, CE_WARN, "failed to create aac node");
911830d82f7Spl goto error;
912830d82f7Spl }
9137c478bd9Sstevel@tonic-gate
9140749e8deSXin Chen - Sun Microsystems - Beijing China /* Common attach is OK, so we are attached! */
9150749e8deSXin Chen - Sun Microsystems - Beijing China softs->state |= AAC_STATE_RUN;
9160749e8deSXin Chen - Sun Microsystems - Beijing China
9170749e8deSXin Chen - Sun Microsystems - Beijing China /* Create event thread */
9180749e8deSXin Chen - Sun Microsystems - Beijing China softs->fibctx_p = &softs->aifctx;
9190749e8deSXin Chen - Sun Microsystems - Beijing China if ((softs->event_thread = thread_create(NULL, 0, aac_event_thread,
9200749e8deSXin Chen - Sun Microsystems - Beijing China softs, 0, &p0, TS_RUN, minclsyspri)) == NULL) {
9210749e8deSXin Chen - Sun Microsystems - Beijing China AACDB_PRINT(softs, CE_WARN, "aif thread create failed");
9220749e8deSXin Chen - Sun Microsystems - Beijing China softs->state &= ~AAC_STATE_RUN;
92358bc78c7SXin Chen goto error;
92458bc78c7SXin Chen }
92558bc78c7SXin Chen
926382c8bcaSpl aac_unhold_bus(softs, AAC_IOCMD_SYNC | AAC_IOCMD_ASYNC);
927382c8bcaSpl
928830d82f7Spl /* Create a thread for command timeout */
9290749e8deSXin Chen - Sun Microsystems - Beijing China softs->timeout_id = timeout(aac_timer, (void *)softs,
9300749e8deSXin Chen - Sun Microsystems - Beijing China (aac_tick * drv_usectohz(1000000)));
931830d82f7Spl
932830d82f7Spl /* Common attach is OK, so we are attached! */
9337c478bd9Sstevel@tonic-gate ddi_report_dev(dip);
9341dd0a2dbSpl AACDB_PRINT(softs, CE_NOTE, "aac attached ok");
9357c478bd9Sstevel@tonic-gate return (DDI_SUCCESS);
9367c478bd9Sstevel@tonic-gate
9377c478bd9Sstevel@tonic-gate error:
938830d82f7Spl if (attach_state & AAC_ATTACH_CREATE_SCSI)
939830d82f7Spl ddi_remove_minor_node(dip, "scsi");
940830d82f7Spl if (attach_state & AAC_ATTACH_CREATE_DEVCTL)
941830d82f7Spl ddi_remove_minor_node(dip, "devctl");
942830d82f7Spl if (attach_state & AAC_ATTACH_COMM_SPACE_SETUP)
943830d82f7Spl aac_common_detach(softs);
944830d82f7Spl if (attach_state & AAC_ATTACH_SCSI_TRAN_SETUP) {
9457c478bd9Sstevel@tonic-gate (void) scsi_hba_detach(dip);
946c9487164Spl scsi_hba_tran_free(AAC_DIP2TRAN(dip));
9477c478bd9Sstevel@tonic-gate }
948830d82f7Spl if (attach_state & AAC_ATTACH_KMUTEX_INITED) {
9490749e8deSXin Chen - Sun Microsystems - Beijing China mutex_destroy(&softs->io_lock);
950382c8bcaSpl mutex_destroy(&softs->q_comp_mutex);
9510749e8deSXin Chen - Sun Microsystems - Beijing China mutex_destroy(&softs->time_mutex);
9520749e8deSXin Chen - Sun Microsystems - Beijing China mutex_destroy(&softs->ev_lock);
9530749e8deSXin Chen - Sun Microsystems - Beijing China mutex_destroy(&softs->aifq_mutex);
954830d82f7Spl cv_destroy(&softs->event);
9551ee13a44SXinChen cv_destroy(&softs->sync_fib_cv);
956382c8bcaSpl cv_destroy(&softs->drain_cv);
9570749e8deSXin Chen - Sun Microsystems - Beijing China cv_destroy(&softs->event_wait_cv);
9580749e8deSXin Chen - Sun Microsystems - Beijing China cv_destroy(&softs->event_disp_cv);
9590749e8deSXin Chen - Sun Microsystems - Beijing China cv_destroy(&softs->aifq_cv);
9607c478bd9Sstevel@tonic-gate }
961830d82f7Spl if (attach_state & AAC_ATTACH_PCI_MEM_MAPPED)
9627c478bd9Sstevel@tonic-gate ddi_regs_map_free(&softs->pci_mem_handle);
9637675db54Syw aac_fm_fini(softs);
964830d82f7Spl if (attach_state & AAC_ATTACH_CARD_DETECTED)
9657c478bd9Sstevel@tonic-gate softs->card = AACERR;
966830d82f7Spl if (attach_state & AAC_ATTACH_SOFTSTATE_ALLOCED)
9677c478bd9Sstevel@tonic-gate ddi_soft_state_free(aac_softstatep, instance);
9687c478bd9Sstevel@tonic-gate return (DDI_FAILURE);
9697c478bd9Sstevel@tonic-gate }
9707c478bd9Sstevel@tonic-gate
9717c478bd9Sstevel@tonic-gate static int
aac_detach(dev_info_t * dip,ddi_detach_cmd_t cmd)9727c478bd9Sstevel@tonic-gate aac_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
9737c478bd9Sstevel@tonic-gate {
974c9487164Spl scsi_hba_tran_t *tran = AAC_DIP2TRAN(dip);
975c9487164Spl struct aac_softstate *softs = AAC_TRAN2SOFTS(tran);
9767c478bd9Sstevel@tonic-gate
9771dd0a2dbSpl DBCALLED(softs, 1);
9787c478bd9Sstevel@tonic-gate
9797c478bd9Sstevel@tonic-gate switch (cmd) {
980830d82f7Spl case DDI_DETACH:
981830d82f7Spl break;
982830d82f7Spl case DDI_SUSPEND:
983830d82f7Spl return (DDI_FAILURE);
984830d82f7Spl default:
985830d82f7Spl return (DDI_FAILURE);
9867c478bd9Sstevel@tonic-gate }
9877c478bd9Sstevel@tonic-gate
988382c8bcaSpl mutex_enter(&softs->io_lock);
989382c8bcaSpl AAC_DISABLE_INTR(softs);
990830d82f7Spl softs->state = AAC_STATE_STOPPED;
991382c8bcaSpl
992382c8bcaSpl ddi_remove_minor_node(dip, "aac");
993382c8bcaSpl ddi_remove_minor_node(dip, "scsi");
994382c8bcaSpl ddi_remove_minor_node(dip, "devctl");
995382c8bcaSpl mutex_exit(&softs->io_lock);
996830d82f7Spl
997830d82f7Spl aac_common_detach(softs);
998830d82f7Spl
999f42c2f53Szhongyan gu - Sun Microsystems - Beijing China mutex_enter(&softs->io_lock);
10007c478bd9Sstevel@tonic-gate (void) scsi_hba_detach(dip);
10017c478bd9Sstevel@tonic-gate scsi_hba_tran_free(tran);
1002f42c2f53Szhongyan gu - Sun Microsystems - Beijing China mutex_exit(&softs->io_lock);
1003382c8bcaSpl
10040749e8deSXin Chen - Sun Microsystems - Beijing China /* Stop timer */
10050749e8deSXin Chen - Sun Microsystems - Beijing China mutex_enter(&softs->time_mutex);
10060749e8deSXin Chen - Sun Microsystems - Beijing China if (softs->timeout_id) {
10070749e8deSXin Chen - Sun Microsystems - Beijing China timeout_id_t tid = softs->timeout_id;
10080749e8deSXin Chen - Sun Microsystems - Beijing China softs->timeout_id = 0;
10090749e8deSXin Chen - Sun Microsystems - Beijing China
10100749e8deSXin Chen - Sun Microsystems - Beijing China mutex_exit(&softs->time_mutex);
10110749e8deSXin Chen - Sun Microsystems - Beijing China (void) untimeout(tid);
10120749e8deSXin Chen - Sun Microsystems - Beijing China mutex_enter(&softs->time_mutex);
10130749e8deSXin Chen - Sun Microsystems - Beijing China }
10140749e8deSXin Chen - Sun Microsystems - Beijing China mutex_exit(&softs->time_mutex);
10150749e8deSXin Chen - Sun Microsystems - Beijing China
10160749e8deSXin Chen - Sun Microsystems - Beijing China /* Destroy event thread */
10170749e8deSXin Chen - Sun Microsystems - Beijing China mutex_enter(&softs->ev_lock);
10180749e8deSXin Chen - Sun Microsystems - Beijing China cv_signal(&softs->event_disp_cv);
10190749e8deSXin Chen - Sun Microsystems - Beijing China cv_wait(&softs->event_wait_cv, &softs->ev_lock);
10200749e8deSXin Chen - Sun Microsystems - Beijing China mutex_exit(&softs->ev_lock);
10210749e8deSXin Chen - Sun Microsystems - Beijing China
10220749e8deSXin Chen - Sun Microsystems - Beijing China cv_destroy(&softs->aifq_cv);
10230749e8deSXin Chen - Sun Microsystems - Beijing China cv_destroy(&softs->event_disp_cv);
10240749e8deSXin Chen - Sun Microsystems - Beijing China cv_destroy(&softs->event_wait_cv);
10250749e8deSXin Chen - Sun Microsystems - Beijing China cv_destroy(&softs->drain_cv);
10261ee13a44SXinChen cv_destroy(&softs->sync_fib_cv);
10270749e8deSXin Chen - Sun Microsystems - Beijing China cv_destroy(&softs->event);
1028830d82f7Spl mutex_destroy(&softs->aifq_mutex);
10290749e8deSXin Chen - Sun Microsystems - Beijing China mutex_destroy(&softs->ev_lock);
10300749e8deSXin Chen - Sun Microsystems - Beijing China mutex_destroy(&softs->time_mutex);
10310749e8deSXin Chen - Sun Microsystems - Beijing China mutex_destroy(&softs->q_comp_mutex);
1032382c8bcaSpl mutex_destroy(&softs->io_lock);
1033830d82f7Spl
10347c478bd9Sstevel@tonic-gate ddi_regs_map_free(&softs->pci_mem_handle);
10357675db54Syw aac_fm_fini(softs);
1036d937e6ebSpl softs->hwif = AAC_HWIF_UNKNOWN;
1037d937e6ebSpl softs->card = AAC_UNKNOWN_CARD;
1038c9487164Spl ddi_soft_state_free(aac_softstatep, ddi_get_instance(dip));
10397c478bd9Sstevel@tonic-gate
10407c478bd9Sstevel@tonic-gate return (DDI_SUCCESS);
10417c478bd9Sstevel@tonic-gate }
10427c478bd9Sstevel@tonic-gate
1043830d82f7Spl /*ARGSUSED*/
1044830d82f7Spl static int
aac_reset(dev_info_t * dip,ddi_reset_cmd_t cmd)1045830d82f7Spl aac_reset(dev_info_t *dip, ddi_reset_cmd_t cmd)
1046830d82f7Spl {
1047c9487164Spl struct aac_softstate *softs = AAC_DIP2SOFTS(dip);
1048830d82f7Spl
10491dd0a2dbSpl DBCALLED(softs, 1);
1050830d82f7Spl
1051942c5e3cSpl mutex_enter(&softs->io_lock);
10521ee13a44SXinChen AAC_DISABLE_INTR(softs);
1053830d82f7Spl (void) aac_shutdown(softs);
1054942c5e3cSpl mutex_exit(&softs->io_lock);
1055830d82f7Spl
1056830d82f7Spl return (DDI_SUCCESS);
1057830d82f7Spl }
1058830d82f7Spl
105919397407SSherry Moore /*
106019397407SSherry Moore * quiesce(9E) entry point.
106119397407SSherry Moore *
106219397407SSherry Moore * This function is called when the system is single-threaded at high
106319397407SSherry Moore * PIL with preemption disabled. Therefore, this function must not be
106419397407SSherry Moore * blocked.
106519397407SSherry Moore *
106619397407SSherry Moore * This function returns DDI_SUCCESS on success, or DDI_FAILURE on failure.
106719397407SSherry Moore * DDI_FAILURE indicates an error condition and should almost never happen.
106819397407SSherry Moore */
106919397407SSherry Moore static int
aac_quiesce(dev_info_t * dip)107019397407SSherry Moore aac_quiesce(dev_info_t *dip)
107119397407SSherry Moore {
107219397407SSherry Moore struct aac_softstate *softs = AAC_DIP2SOFTS(dip);
107319397407SSherry Moore
107419397407SSherry Moore if (softs == NULL)
107519397407SSherry Moore return (DDI_FAILURE);
107619397407SSherry Moore
10770749e8deSXin Chen - Sun Microsystems - Beijing China _NOTE(ASSUMING_PROTECTED(softs->state))
107819397407SSherry Moore AAC_DISABLE_INTR(softs);
107919397407SSherry Moore
108019397407SSherry Moore return (DDI_SUCCESS);
108119397407SSherry Moore }
108219397407SSherry Moore
1083f42c2f53Szhongyan gu - Sun Microsystems - Beijing China /* ARGSUSED */
1084f42c2f53Szhongyan gu - Sun Microsystems - Beijing China static int
aac_getinfo(dev_info_t * self,ddi_info_cmd_t infocmd,void * arg,void ** result)1085f42c2f53Szhongyan gu - Sun Microsystems - Beijing China aac_getinfo(dev_info_t *self, ddi_info_cmd_t infocmd, void *arg,
1086f42c2f53Szhongyan gu - Sun Microsystems - Beijing China void **result)
1087f42c2f53Szhongyan gu - Sun Microsystems - Beijing China {
1088f42c2f53Szhongyan gu - Sun Microsystems - Beijing China int error = DDI_SUCCESS;
1089f42c2f53Szhongyan gu - Sun Microsystems - Beijing China
1090f42c2f53Szhongyan gu - Sun Microsystems - Beijing China switch (infocmd) {
1091f42c2f53Szhongyan gu - Sun Microsystems - Beijing China case DDI_INFO_DEVT2INSTANCE:
1092f42c2f53Szhongyan gu - Sun Microsystems - Beijing China *result = (void *)(intptr_t)(MINOR2INST(getminor((dev_t)arg)));
1093f42c2f53Szhongyan gu - Sun Microsystems - Beijing China break;
1094f42c2f53Szhongyan gu - Sun Microsystems - Beijing China default:
1095f42c2f53Szhongyan gu - Sun Microsystems - Beijing China error = DDI_FAILURE;
1096f42c2f53Szhongyan gu - Sun Microsystems - Beijing China }
1097f42c2f53Szhongyan gu - Sun Microsystems - Beijing China return (error);
1098f42c2f53Szhongyan gu - Sun Microsystems - Beijing China }
1099f42c2f53Szhongyan gu - Sun Microsystems - Beijing China
1100830d82f7Spl /*
1101830d82f7Spl * Bring the controller down to a dormant state and detach all child devices.
1102830d82f7Spl * This function is called before detach or system shutdown.
1103830d82f7Spl * Note: we can assume that the q_wait on the controller is empty, as we
1104830d82f7Spl * won't allow shutdown if any device is open.
1105830d82f7Spl */
1106830d82f7Spl static int
aac_shutdown(struct aac_softstate * softs)1107830d82f7Spl aac_shutdown(struct aac_softstate *softs)
1108830d82f7Spl {
1109f42c2f53Szhongyan gu - Sun Microsystems - Beijing China ddi_acc_handle_t acc;
1110f42c2f53Szhongyan gu - Sun Microsystems - Beijing China struct aac_close_command *cc;
1111c9487164Spl int rval;
1112830d82f7Spl
1113f42c2f53Szhongyan gu - Sun Microsystems - Beijing China (void) aac_sync_fib_slot_bind(softs, &softs->sync_ac);
1114f42c2f53Szhongyan gu - Sun Microsystems - Beijing China acc = softs->sync_ac.slotp->fib_acc_handle;
1115f42c2f53Szhongyan gu - Sun Microsystems - Beijing China
1116f42c2f53Szhongyan gu - Sun Microsystems - Beijing China cc = (struct aac_close_command *)&softs->sync_ac.slotp->fibp->data[0];
1117f42c2f53Szhongyan gu - Sun Microsystems - Beijing China
1118942c5e3cSpl ddi_put32(acc, &cc->Command, VM_CloseAll);
1119942c5e3cSpl ddi_put32(acc, &cc->ContainerId, 0xfffffffful);
1120830d82f7Spl
1121c9487164Spl /* Flush all caches, set FW to write through mode */
1122942c5e3cSpl rval = aac_sync_fib(softs, ContainerCommand,
1123942c5e3cSpl AAC_FIB_SIZEOF(struct aac_close_command));
1124f42c2f53Szhongyan gu - Sun Microsystems - Beijing China aac_sync_fib_slot_release(softs, &softs->sync_ac);
1125830d82f7Spl
11261dd0a2dbSpl AACDB_PRINT(softs, CE_NOTE,
11271dd0a2dbSpl "shutting down aac %s", (rval == AACOK) ? "ok" : "fail");
1128c9487164Spl return (rval);
1129830d82f7Spl }
1130830d82f7Spl
11317c478bd9Sstevel@tonic-gate static uint_t
aac_softintr(caddr_t arg)11327c478bd9Sstevel@tonic-gate aac_softintr(caddr_t arg)
11337c478bd9Sstevel@tonic-gate {
1134a74f7440Spl struct aac_softstate *softs = (void *)arg;
11357c478bd9Sstevel@tonic-gate
11367c478bd9Sstevel@tonic-gate if (!AAC_IS_Q_EMPTY(&softs->q_comp)) {
11377c478bd9Sstevel@tonic-gate aac_drain_comp_q(softs);
1138c9487164Spl }
1139f42c2f53Szhongyan gu - Sun Microsystems - Beijing China return (DDI_INTR_CLAIMED);
11407c478bd9Sstevel@tonic-gate }
11417c478bd9Sstevel@tonic-gate
1142830d82f7Spl /*
1143830d82f7Spl * Setup auto sense data for pkt
1144830d82f7Spl */
1145d937e6ebSpl static void
aac_set_arq_data(struct scsi_pkt * pkt,uchar_t key,uchar_t add_code,uchar_t qual_code,uint64_t info)1146830d82f7Spl aac_set_arq_data(struct scsi_pkt *pkt, uchar_t key,
1147c9487164Spl uchar_t add_code, uchar_t qual_code, uint64_t info)
11487c478bd9Sstevel@tonic-gate {
114958bc78c7SXin Chen struct scsi_arq_status *arqstat = (void *)(pkt->pkt_scbp);
11507c478bd9Sstevel@tonic-gate
115158bc78c7SXin Chen *pkt->pkt_scbp = STATUS_CHECK; /* CHECK CONDITION */
115258bc78c7SXin Chen pkt->pkt_state |= STATE_ARQ_DONE;
1153830d82f7Spl
115458bc78c7SXin Chen *(uint8_t *)&arqstat->sts_rqpkt_status = STATUS_GOOD;
11557c478bd9Sstevel@tonic-gate arqstat->sts_rqpkt_reason = CMD_CMPLT;
11567c478bd9Sstevel@tonic-gate arqstat->sts_rqpkt_resid = 0;
1157830d82f7Spl arqstat->sts_rqpkt_state =
1158c9487164Spl STATE_GOT_BUS |
1159c9487164Spl STATE_GOT_TARGET |
1160c9487164Spl STATE_SENT_CMD |
1161c9487164Spl STATE_XFERRED_DATA;
11627c478bd9Sstevel@tonic-gate arqstat->sts_rqpkt_statistics = 0;
1163830d82f7Spl
1164c9487164Spl if (info <= 0xfffffffful) {
1165830d82f7Spl arqstat->sts_sensedata.es_valid = 1;
1166830d82f7Spl arqstat->sts_sensedata.es_class = CLASS_EXTENDED_SENSE;
1167830d82f7Spl arqstat->sts_sensedata.es_code = CODE_FMT_FIXED_CURRENT;
1168830d82f7Spl arqstat->sts_sensedata.es_key = key;
1169830d82f7Spl arqstat->sts_sensedata.es_add_code = add_code;
1170830d82f7Spl arqstat->sts_sensedata.es_qual_code = qual_code;
1171830d82f7Spl
1172830d82f7Spl arqstat->sts_sensedata.es_info_1 = (info >> 24) & 0xFF;
1173830d82f7Spl arqstat->sts_sensedata.es_info_2 = (info >> 16) & 0xFF;
1174830d82f7Spl arqstat->sts_sensedata.es_info_3 = (info >> 8) & 0xFF;
1175830d82f7Spl arqstat->sts_sensedata.es_info_4 = info & 0xFF;
1176830d82f7Spl } else { /* 64-bit LBA */
1177830d82f7Spl struct scsi_descr_sense_hdr *dsp;
1178830d82f7Spl struct scsi_information_sense_descr *isd;
1179830d82f7Spl
1180830d82f7Spl dsp = (struct scsi_descr_sense_hdr *)&arqstat->sts_sensedata;
1181830d82f7Spl dsp->ds_class = CLASS_EXTENDED_SENSE;
1182830d82f7Spl dsp->ds_code = CODE_FMT_DESCR_CURRENT;
1183830d82f7Spl dsp->ds_key = key;
1184830d82f7Spl dsp->ds_add_code = add_code;
1185830d82f7Spl dsp->ds_qual_code = qual_code;
1186830d82f7Spl dsp->ds_addl_sense_length =
1187c9487164Spl sizeof (struct scsi_information_sense_descr);
1188830d82f7Spl
1189830d82f7Spl isd = (struct scsi_information_sense_descr *)(dsp+1);
1190830d82f7Spl isd->isd_descr_type = DESCR_INFORMATION;
1191830d82f7Spl isd->isd_valid = 1;
1192830d82f7Spl isd->isd_information[0] = (info >> 56) & 0xFF;
1193830d82f7Spl isd->isd_information[1] = (info >> 48) & 0xFF;
1194830d82f7Spl isd->isd_information[2] = (info >> 40) & 0xFF;
1195830d82f7Spl isd->isd_information[3] = (info >> 32) & 0xFF;
1196830d82f7Spl isd->isd_information[4] = (info >> 24) & 0xFF;
1197830d82f7Spl isd->isd_information[5] = (info >> 16) & 0xFF;
1198830d82f7Spl isd->isd_information[6] = (info >> 8) & 0xFF;
1199830d82f7Spl isd->isd_information[7] = (info) & 0xFF;
1200830d82f7Spl }
1201830d82f7Spl }
1202830d82f7Spl
1203830d82f7Spl /*
1204830d82f7Spl * Setup auto sense data for HARDWARE ERROR
1205830d82f7Spl */
1206830d82f7Spl static void
aac_set_arq_data_hwerr(struct aac_cmd * acp)1207830d82f7Spl aac_set_arq_data_hwerr(struct aac_cmd *acp)
1208830d82f7Spl {
1209830d82f7Spl union scsi_cdb *cdbp;
1210830d82f7Spl uint64_t err_blkno;
1211830d82f7Spl
1212a74f7440Spl cdbp = (void *)acp->pkt->pkt_cdbp;
1213830d82f7Spl err_blkno = AAC_GETGXADDR(acp->cmdlen, cdbp);
1214830d82f7Spl aac_set_arq_data(acp->pkt, KEY_HARDWARE_ERROR, 0x00, 0x00, err_blkno);
1215830d82f7Spl }
1216830d82f7Spl
1217830d82f7Spl /*
1218830d82f7Spl * Send a command to the adapter in New Comm. interface
1219830d82f7Spl */
1220830d82f7Spl static int
aac_send_command(struct aac_softstate * softs,struct aac_slot * slotp)1221830d82f7Spl aac_send_command(struct aac_softstate *softs, struct aac_slot *slotp)
1222830d82f7Spl {
1223830d82f7Spl uint32_t index, device;
1224830d82f7Spl
1225830d82f7Spl index = PCI_MEM_GET32(softs, AAC_IQUE);
1226942c5e3cSpl if (index == 0xffffffffUL) {
1227830d82f7Spl index = PCI_MEM_GET32(softs, AAC_IQUE);
1228942c5e3cSpl if (index == 0xffffffffUL)
1229942c5e3cSpl return (AACERR);
1230942c5e3cSpl }
1231830d82f7Spl
1232830d82f7Spl device = index;
1233830d82f7Spl PCI_MEM_PUT32(softs, device,
1234c9487164Spl (uint32_t)(slotp->fib_phyaddr & 0xfffffffful));
1235830d82f7Spl device += 4;
1236830d82f7Spl PCI_MEM_PUT32(softs, device, (uint32_t)(slotp->fib_phyaddr >> 32));
1237830d82f7Spl device += 4;
1238942c5e3cSpl PCI_MEM_PUT32(softs, device, slotp->acp->fib_size);
1239830d82f7Spl PCI_MEM_PUT32(softs, AAC_IQUE, index);
1240830d82f7Spl return (AACOK);
12417c478bd9Sstevel@tonic-gate }
12427c478bd9Sstevel@tonic-gate
1243382c8bcaSpl static void
aac_end_io(struct aac_softstate * softs,struct aac_cmd * acp)1244382c8bcaSpl aac_end_io(struct aac_softstate *softs, struct aac_cmd *acp)
1245382c8bcaSpl {
124658bc78c7SXin Chen struct aac_device *dvp = acp->dvp;
1247382c8bcaSpl int q = AAC_CMDQ(acp);
1248382c8bcaSpl
1249382c8bcaSpl if (acp->slotp) { /* outstanding cmd */
1250f42c2f53Szhongyan gu - Sun Microsystems - Beijing China if (!(acp->flags & AAC_CMD_IN_SYNC_SLOT)) {
1251f42c2f53Szhongyan gu - Sun Microsystems - Beijing China aac_release_slot(softs, acp->slotp);
1252f42c2f53Szhongyan gu - Sun Microsystems - Beijing China acp->slotp = NULL;
1253f42c2f53Szhongyan gu - Sun Microsystems - Beijing China }
1254382c8bcaSpl if (dvp) {
1255382c8bcaSpl dvp->ncmds[q]--;
1256382c8bcaSpl if (dvp->throttle[q] == AAC_THROTTLE_DRAIN &&
1257382c8bcaSpl dvp->ncmds[q] == 0 && q == AAC_CMDQ_ASYNC)
1258382c8bcaSpl aac_set_throttle(softs, dvp, q,
1259382c8bcaSpl softs->total_slots);
1260f42c2f53Szhongyan gu - Sun Microsystems - Beijing China /*
1261f42c2f53Szhongyan gu - Sun Microsystems - Beijing China * Setup auto sense data for UNIT ATTENTION
1262f42c2f53Szhongyan gu - Sun Microsystems - Beijing China * Each lun should generate a unit attention
1263f42c2f53Szhongyan gu - Sun Microsystems - Beijing China * condition when reset.
1264f42c2f53Szhongyan gu - Sun Microsystems - Beijing China * Phys. drives are treated as logical ones
1265f42c2f53Szhongyan gu - Sun Microsystems - Beijing China * during error recovery.
1266f42c2f53Szhongyan gu - Sun Microsystems - Beijing China */
1267f42c2f53Szhongyan gu - Sun Microsystems - Beijing China if (dvp->type == AAC_DEV_LD) {
1268f42c2f53Szhongyan gu - Sun Microsystems - Beijing China struct aac_container *ctp =
1269f42c2f53Szhongyan gu - Sun Microsystems - Beijing China (struct aac_container *)dvp;
1270f42c2f53Szhongyan gu - Sun Microsystems - Beijing China if (ctp->reset == 0)
1271f42c2f53Szhongyan gu - Sun Microsystems - Beijing China goto noreset;
1272f42c2f53Szhongyan gu - Sun Microsystems - Beijing China
1273f42c2f53Szhongyan gu - Sun Microsystems - Beijing China AACDB_PRINT(softs, CE_NOTE,
1274f42c2f53Szhongyan gu - Sun Microsystems - Beijing China "Unit attention: reset");
1275f42c2f53Szhongyan gu - Sun Microsystems - Beijing China ctp->reset = 0;
1276f42c2f53Szhongyan gu - Sun Microsystems - Beijing China aac_set_arq_data(acp->pkt, KEY_UNIT_ATTENTION,
1277f42c2f53Szhongyan gu - Sun Microsystems - Beijing China 0x29, 0x02, 0);
1278f42c2f53Szhongyan gu - Sun Microsystems - Beijing China }
1279382c8bcaSpl }
1280f42c2f53Szhongyan gu - Sun Microsystems - Beijing China noreset:
1281382c8bcaSpl softs->bus_ncmds[q]--;
1282f42c2f53Szhongyan gu - Sun Microsystems - Beijing China aac_cmd_delete(&softs->q_busy, acp);
1283382c8bcaSpl } else { /* cmd in waiting queue */
1284382c8bcaSpl aac_cmd_delete(&softs->q_wait[q], acp);
1285382c8bcaSpl }
1286382c8bcaSpl
1287382c8bcaSpl if (!(acp->flags & (AAC_CMD_NO_CB | AAC_CMD_NO_INTR))) { /* async IO */
1288382c8bcaSpl mutex_enter(&softs->q_comp_mutex);
1289382c8bcaSpl aac_cmd_enqueue(&softs->q_comp, acp);
1290382c8bcaSpl mutex_exit(&softs->q_comp_mutex);
1291382c8bcaSpl } else if (acp->flags & AAC_CMD_NO_CB) { /* sync IO */
1292382c8bcaSpl cv_broadcast(&softs->event);
1293382c8bcaSpl }
1294382c8bcaSpl }
1295382c8bcaSpl
1296d7c5bf88Spl static void
aac_handle_io(struct aac_softstate * softs,int index)1297d7c5bf88Spl aac_handle_io(struct aac_softstate *softs, int index)
1298d7c5bf88Spl {
1299d7c5bf88Spl struct aac_slot *slotp;
1300d7c5bf88Spl struct aac_cmd *acp;
1301d7c5bf88Spl uint32_t fast;
1302d7c5bf88Spl
1303d7c5bf88Spl fast = index & AAC_SENDERADDR_MASK_FAST_RESPONSE;
1304d7c5bf88Spl index >>= 2;
1305d7c5bf88Spl
1306d7c5bf88Spl /* Make sure firmware reported index is valid */
1307d7c5bf88Spl ASSERT(index >= 0 && index < softs->total_slots);
1308d7c5bf88Spl slotp = &softs->io_slot[index];
1309d7c5bf88Spl ASSERT(slotp->index == index);
1310d7c5bf88Spl acp = slotp->acp;
131158bc78c7SXin Chen
131258bc78c7SXin Chen if (acp == NULL || acp->slotp != slotp) {
131358bc78c7SXin Chen cmn_err(CE_WARN,
131458bc78c7SXin Chen "Firmware error: invalid slot index received from FW");
131558bc78c7SXin Chen return;
131658bc78c7SXin Chen }
1317d7c5bf88Spl
1318382c8bcaSpl acp->flags |= AAC_CMD_CMPLT;
1319d7c5bf88Spl (void) ddi_dma_sync(slotp->fib_dma_handle, 0, 0, DDI_DMA_SYNC_FORCPU);
1320d7c5bf88Spl
1321382c8bcaSpl if (aac_check_dma_handle(slotp->fib_dma_handle) == DDI_SUCCESS) {
1322382c8bcaSpl /*
1323382c8bcaSpl * For fast response IO, the firmware do not return any FIB
1324382c8bcaSpl * data, so we need to fill in the FIB status and state so that
1325382c8bcaSpl * FIB users can handle it correctly.
1326382c8bcaSpl */
1327382c8bcaSpl if (fast) {
1328382c8bcaSpl uint32_t state;
13297675db54Syw
1330942c5e3cSpl state = ddi_get32(slotp->fib_acc_handle,
1331942c5e3cSpl &slotp->fibp->Header.XferState);
1332382c8bcaSpl /*
1333382c8bcaSpl * Update state for CPU not for device, no DMA sync
1334382c8bcaSpl * needed
1335382c8bcaSpl */
1336942c5e3cSpl ddi_put32(slotp->fib_acc_handle,
1337942c5e3cSpl &slotp->fibp->Header.XferState,
1338942c5e3cSpl state | AAC_FIBSTATE_DONEADAP);
1339942c5e3cSpl ddi_put32(slotp->fib_acc_handle,
1340a74f7440Spl (void *)&slotp->fibp->data[0], ST_OK);
1341382c8bcaSpl }
1342d7c5bf88Spl
1343382c8bcaSpl /* Handle completed ac */
1344382c8bcaSpl acp->ac_comp(softs, acp);
1345382c8bcaSpl } else {
1346382c8bcaSpl ddi_fm_service_impact(softs->devinfo_p, DDI_SERVICE_UNAFFECTED);
1347382c8bcaSpl acp->flags |= AAC_CMD_ERR;
1348382c8bcaSpl if (acp->pkt) {
1349382c8bcaSpl acp->pkt->pkt_reason = CMD_TRAN_ERR;
1350382c8bcaSpl acp->pkt->pkt_statistics = 0;
1351382c8bcaSpl }
1352d7c5bf88Spl }
1353382c8bcaSpl aac_end_io(softs, acp);
1354d7c5bf88Spl }
1355d7c5bf88Spl
1356830d82f7Spl /*
1357830d82f7Spl * Interrupt handler for New Comm. interface
1358830d82f7Spl * New Comm. interface use a different mechanism for interrupt. No explict
1359830d82f7Spl * message queues, and driver need only accesses the mapped PCI mem space to
1360830d82f7Spl * find the completed FIB or AIF.
1361830d82f7Spl */
1362382c8bcaSpl static int
aac_process_intr_new(struct aac_softstate * softs)1363382c8bcaSpl aac_process_intr_new(struct aac_softstate *softs)
13647c478bd9Sstevel@tonic-gate {
1365c9487164Spl uint32_t index;
1366830d82f7Spl
1367830d82f7Spl index = AAC_OUTB_GET(softs);
1368c9487164Spl if (index == 0xfffffffful)
1369830d82f7Spl index = AAC_OUTB_GET(softs);
13707675db54Syw if (aac_check_acc_handle(softs->pci_mem_handle) != DDI_SUCCESS) {
13717675db54Syw ddi_fm_service_impact(softs->devinfo_p, DDI_SERVICE_UNAFFECTED);
137258bc78c7SXin Chen return (0);
13737675db54Syw }
1374382c8bcaSpl if (index != 0xfffffffful) {
1375382c8bcaSpl do {
1376382c8bcaSpl if ((index & AAC_SENDERADDR_MASK_AIF) == 0) {
1377382c8bcaSpl aac_handle_io(softs, index);
1378382c8bcaSpl } else if (index != 0xfffffffeul) {
1379382c8bcaSpl struct aac_fib *fibp; /* FIB in AIF queue */
13800749e8deSXin Chen - Sun Microsystems - Beijing China uint16_t fib_size;
1381830d82f7Spl
1382382c8bcaSpl /*
1383382c8bcaSpl * 0xfffffffe means that the controller wants
1384382c8bcaSpl * more work, ignore it for now. Otherwise,
1385382c8bcaSpl * AIF received.
1386382c8bcaSpl */
1387382c8bcaSpl index &= ~2;
1388382c8bcaSpl
13890749e8deSXin Chen - Sun Microsystems - Beijing China fibp = (struct aac_fib *)(softs-> \
13900749e8deSXin Chen - Sun Microsystems - Beijing China pci_mem_base_vaddr + index);
13910749e8deSXin Chen - Sun Microsystems - Beijing China fib_size = PCI_MEM_GET16(softs, index + \
1392942c5e3cSpl offsetof(struct aac_fib, Header.Size));
13930749e8deSXin Chen - Sun Microsystems - Beijing China
13940749e8deSXin Chen - Sun Microsystems - Beijing China aac_save_aif(softs, softs->pci_mem_handle,
13950749e8deSXin Chen - Sun Microsystems - Beijing China fibp, fib_size);
1396382c8bcaSpl
1397382c8bcaSpl /*
1398382c8bcaSpl * AIF memory is owned by the adapter, so let it
1399382c8bcaSpl * know that we are done with it.
1400382c8bcaSpl */
1401382c8bcaSpl AAC_OUTB_SET(softs, index);
1402382c8bcaSpl AAC_STATUS_CLR(softs, AAC_DB_RESPONSE_READY);
1403382c8bcaSpl }
1404382c8bcaSpl
1405382c8bcaSpl index = AAC_OUTB_GET(softs);
1406382c8bcaSpl } while (index != 0xfffffffful);
1407382c8bcaSpl
1408382c8bcaSpl /*
1409382c8bcaSpl * Process waiting cmds before start new ones to
1410382c8bcaSpl * ensure first IOs are serviced first.
1411382c8bcaSpl */
1412382c8bcaSpl aac_start_waiting_io(softs);
1413382c8bcaSpl return (AAC_DB_COMMAND_READY);
1414382c8bcaSpl } else {
1415382c8bcaSpl return (0);
1416382c8bcaSpl }
1417382c8bcaSpl }
1418382c8bcaSpl
1419382c8bcaSpl static uint_t
aac_intr_new(caddr_t arg,caddr_t arg1 __unused)1420b4a8b33bSToomas Soome aac_intr_new(caddr_t arg, caddr_t arg1 __unused)
1421382c8bcaSpl {
1422a74f7440Spl struct aac_softstate *softs = (void *)arg;
1423382c8bcaSpl uint_t rval;
1424382c8bcaSpl
1425382c8bcaSpl mutex_enter(&softs->io_lock);
1426382c8bcaSpl if (aac_process_intr_new(softs))
1427382c8bcaSpl rval = DDI_INTR_CLAIMED;
1428382c8bcaSpl else
1429382c8bcaSpl rval = DDI_INTR_UNCLAIMED;
1430382c8bcaSpl mutex_exit(&softs->io_lock);
1431830d82f7Spl
1432382c8bcaSpl aac_drain_comp_q(softs);
1433382c8bcaSpl return (rval);
1434830d82f7Spl }
1435830d82f7Spl
1436830d82f7Spl /*
1437830d82f7Spl * Interrupt handler for old interface
1438830d82f7Spl * Explicit message queues are used to send FIB to and get completed FIB from
1439830d82f7Spl * the adapter. Driver and adapter maitain the queues in the producer/consumer
1440830d82f7Spl * manner. The driver has to query the queues to find the completed FIB.
1441830d82f7Spl */
1442382c8bcaSpl static int
aac_process_intr_old(struct aac_softstate * softs)1443382c8bcaSpl aac_process_intr_old(struct aac_softstate *softs)
1444830d82f7Spl {
14457c478bd9Sstevel@tonic-gate uint16_t status;
14467c478bd9Sstevel@tonic-gate
14477c478bd9Sstevel@tonic-gate status = AAC_STATUS_GET(softs);
14487675db54Syw if (aac_check_acc_handle(softs->pci_mem_handle) != DDI_SUCCESS) {
14497675db54Syw ddi_fm_service_impact(softs->devinfo_p, DDI_SERVICE_UNAFFECTED);
14507675db54Syw return (DDI_INTR_UNCLAIMED);
14517675db54Syw }
1452830d82f7Spl if (status & AAC_DB_RESPONSE_READY) {
1453d7c5bf88Spl int slot_idx;
1454d7c5bf88Spl
1455830d82f7Spl /* ACK the intr */
14567c478bd9Sstevel@tonic-gate AAC_STATUS_CLR(softs, AAC_DB_RESPONSE_READY);
14577c478bd9Sstevel@tonic-gate (void) AAC_STATUS_GET(softs);
1458382c8bcaSpl while (aac_fib_dequeue(softs, AAC_HOST_NORM_RESP_Q,
1459382c8bcaSpl &slot_idx) == AACOK)
1460382c8bcaSpl aac_handle_io(softs, slot_idx);
1461830d82f7Spl
1462382c8bcaSpl /*
1463382c8bcaSpl * Process waiting cmds before start new ones to
1464382c8bcaSpl * ensure first IOs are serviced first.
1465382c8bcaSpl */
14667c478bd9Sstevel@tonic-gate aac_start_waiting_io(softs);
1467382c8bcaSpl return (AAC_DB_RESPONSE_READY);
14687c478bd9Sstevel@tonic-gate } else if (status & AAC_DB_COMMAND_READY) {
1469d7c5bf88Spl int aif_idx;
1470d7c5bf88Spl
14717c478bd9Sstevel@tonic-gate AAC_STATUS_CLR(softs, AAC_DB_COMMAND_READY);
14727c478bd9Sstevel@tonic-gate (void) AAC_STATUS_GET(softs);
1473382c8bcaSpl if (aac_fib_dequeue(softs, AAC_HOST_NORM_CMD_Q, &aif_idx) ==
1474382c8bcaSpl AACOK) {
1475942c5e3cSpl ddi_acc_handle_t acc = softs->comm_space_acc_handle;
14760749e8deSXin Chen - Sun Microsystems - Beijing China struct aac_fib *fibp; /* FIB in communication space */
14770749e8deSXin Chen - Sun Microsystems - Beijing China uint16_t fib_size;
1478942c5e3cSpl uint32_t fib_xfer_state;
1479d7c5bf88Spl uint32_t addr, size;
1480d7c5bf88Spl
1481d7c5bf88Spl ASSERT((aif_idx >= 0) && (aif_idx < AAC_ADAPTER_FIBS));
1482382c8bcaSpl
1483942c5e3cSpl #define AAC_SYNC_AIF(softs, aif_idx, type) \
1484942c5e3cSpl { (void) ddi_dma_sync((softs)->comm_space_dma_handle, \
1485942c5e3cSpl offsetof(struct aac_comm_space, \
1486942c5e3cSpl adapter_fibs[(aif_idx)]), AAC_FIB_SIZE, \
1487942c5e3cSpl (type)); }
1488942c5e3cSpl
1489942c5e3cSpl /* Copy AIF from adapter to the empty AIF slot */
1490942c5e3cSpl AAC_SYNC_AIF(softs, aif_idx, DDI_DMA_SYNC_FORCPU);
14910749e8deSXin Chen - Sun Microsystems - Beijing China fibp = &softs->comm_space->adapter_fibs[aif_idx];
14920749e8deSXin Chen - Sun Microsystems - Beijing China fib_size = ddi_get16(acc, &fibp->Header.Size);
1493942c5e3cSpl
14940749e8deSXin Chen - Sun Microsystems - Beijing China aac_save_aif(softs, acc, fibp, fib_size);
1495d7c5bf88Spl
1496d7c5bf88Spl /* Complete AIF back to adapter with good status */
1497942c5e3cSpl fib_xfer_state = LE_32(fibp->Header.XferState);
1498942c5e3cSpl if (fib_xfer_state & AAC_FIBSTATE_FROMADAP) {
14990749e8deSXin Chen - Sun Microsystems - Beijing China ddi_put32(acc, &fibp->Header.XferState,
1500942c5e3cSpl fib_xfer_state | AAC_FIBSTATE_DONEHOST);
15010749e8deSXin Chen - Sun Microsystems - Beijing China ddi_put32(acc, (void *)&fibp->data[0], ST_OK);
15020749e8deSXin Chen - Sun Microsystems - Beijing China if (fib_size > AAC_FIB_SIZE)
15030749e8deSXin Chen - Sun Microsystems - Beijing China ddi_put16(acc, &fibp->Header.Size,
1504942c5e3cSpl AAC_FIB_SIZE);
1505942c5e3cSpl AAC_SYNC_AIF(softs, aif_idx,
1506942c5e3cSpl DDI_DMA_SYNC_FORDEV);
1507d7c5bf88Spl }
1508d7c5bf88Spl
1509d7c5bf88Spl /* Put the AIF response on the response queue */
1510942c5e3cSpl addr = ddi_get32(acc,
1511942c5e3cSpl &softs->comm_space->adapter_fibs[aif_idx]. \
1512942c5e3cSpl Header.SenderFibAddress);
1513942c5e3cSpl size = (uint32_t)ddi_get16(acc,
1514942c5e3cSpl &softs->comm_space->adapter_fibs[aif_idx]. \
1515942c5e3cSpl Header.Size);
1516942c5e3cSpl ddi_put32(acc,
1517942c5e3cSpl &softs->comm_space->adapter_fibs[aif_idx]. \
1518942c5e3cSpl Header.ReceiverFibAddress, addr);
1519d7c5bf88Spl if (aac_fib_enqueue(softs, AAC_ADAP_NORM_RESP_Q,
1520d7c5bf88Spl addr, size) == AACERR)
1521830d82f7Spl cmn_err(CE_NOTE, "!AIF ack failed");
1522830d82f7Spl }
1523382c8bcaSpl return (AAC_DB_COMMAND_READY);
1524382c8bcaSpl } else if (status & AAC_DB_PRINTF_READY) {
1525382c8bcaSpl /* ACK the intr */
1526382c8bcaSpl AAC_STATUS_CLR(softs, AAC_DB_PRINTF_READY);
1527382c8bcaSpl (void) AAC_STATUS_GET(softs);
1528382c8bcaSpl (void) ddi_dma_sync(softs->comm_space_dma_handle,
1529942c5e3cSpl offsetof(struct aac_comm_space, adapter_print_buf),
1530382c8bcaSpl AAC_ADAPTER_PRINT_BUFSIZE, DDI_DMA_SYNC_FORCPU);
1531382c8bcaSpl if (aac_check_dma_handle(softs->comm_space_dma_handle) ==
1532382c8bcaSpl DDI_SUCCESS)
1533382c8bcaSpl cmn_err(CE_NOTE, "MSG From Adapter: %s",
1534382c8bcaSpl softs->comm_space->adapter_print_buf);
1535382c8bcaSpl else
1536382c8bcaSpl ddi_fm_service_impact(softs->devinfo_p,
1537382c8bcaSpl DDI_SERVICE_UNAFFECTED);
1538382c8bcaSpl AAC_NOTIFY(softs, AAC_DB_PRINTF_READY);
1539382c8bcaSpl return (AAC_DB_PRINTF_READY);
1540830d82f7Spl } else if (status & AAC_DB_COMMAND_NOT_FULL) {
1541830d82f7Spl /*
1542830d82f7Spl * Without these two condition statements, the OS could hang
1543830d82f7Spl * after a while, especially if there are a lot of AIF's to
1544830d82f7Spl * handle, for instance if a drive is pulled from an array
1545830d82f7Spl * under heavy load.
1546830d82f7Spl */
1547830d82f7Spl AAC_STATUS_CLR(softs, AAC_DB_COMMAND_NOT_FULL);
1548382c8bcaSpl return (AAC_DB_COMMAND_NOT_FULL);
1549830d82f7Spl } else if (status & AAC_DB_RESPONSE_NOT_FULL) {
1550830d82f7Spl AAC_STATUS_CLR(softs, AAC_DB_COMMAND_NOT_FULL);
1551830d82f7Spl AAC_STATUS_CLR(softs, AAC_DB_RESPONSE_NOT_FULL);
1552382c8bcaSpl return (AAC_DB_RESPONSE_NOT_FULL);
1553c9487164Spl } else {
1554382c8bcaSpl return (0);
1555c9487164Spl }
15567c478bd9Sstevel@tonic-gate }
15577c478bd9Sstevel@tonic-gate
1558382c8bcaSpl static uint_t
aac_intr_old(caddr_t arg,caddr_t arg1 __unused)1559b4a8b33bSToomas Soome aac_intr_old(caddr_t arg, caddr_t arg1 __unused)
1560382c8bcaSpl {
1561a74f7440Spl struct aac_softstate *softs = (void *)arg;
1562382c8bcaSpl int rval;
1563382c8bcaSpl
1564382c8bcaSpl mutex_enter(&softs->io_lock);
1565382c8bcaSpl if (aac_process_intr_old(softs))
1566382c8bcaSpl rval = DDI_INTR_CLAIMED;
1567382c8bcaSpl else
1568382c8bcaSpl rval = DDI_INTR_UNCLAIMED;
1569382c8bcaSpl mutex_exit(&softs->io_lock);
1570382c8bcaSpl
1571382c8bcaSpl aac_drain_comp_q(softs);
1572382c8bcaSpl return (rval);
1573382c8bcaSpl }
1574382c8bcaSpl
1575b6094a86Sjd /*
1576b6094a86Sjd * Query FIXED or MSI interrupts
1577b6094a86Sjd */
1578b6094a86Sjd static int
aac_query_intrs(struct aac_softstate * softs,int intr_type)1579b6094a86Sjd aac_query_intrs(struct aac_softstate *softs, int intr_type)
1580b6094a86Sjd {
1581b6094a86Sjd dev_info_t *dip = softs->devinfo_p;
1582f42c2f53Szhongyan gu - Sun Microsystems - Beijing China int avail, actual, count;
1583b6094a86Sjd int i, flag, ret;
1584b6094a86Sjd
1585b6094a86Sjd AACDB_PRINT(softs, CE_NOTE,
1586b6094a86Sjd "aac_query_intrs:interrupt type 0x%x", intr_type);
1587b6094a86Sjd
1588b6094a86Sjd /* Get number of interrupts */
1589b6094a86Sjd ret = ddi_intr_get_nintrs(dip, intr_type, &count);
1590b6094a86Sjd if ((ret != DDI_SUCCESS) || (count == 0)) {
1591b6094a86Sjd AACDB_PRINT(softs, CE_WARN,
1592b6094a86Sjd "ddi_intr_get_nintrs() failed, ret %d count %d",
1593b6094a86Sjd ret, count);
1594b6094a86Sjd return (DDI_FAILURE);
1595b6094a86Sjd }
1596b6094a86Sjd
1597b6094a86Sjd /* Get number of available interrupts */
1598b6094a86Sjd ret = ddi_intr_get_navail(dip, intr_type, &avail);
1599b6094a86Sjd if ((ret != DDI_SUCCESS) || (avail == 0)) {
1600b6094a86Sjd AACDB_PRINT(softs, CE_WARN,
1601b6094a86Sjd "ddi_intr_get_navail() failed, ret %d avail %d",
1602b6094a86Sjd ret, avail);
1603b6094a86Sjd return (DDI_FAILURE);
1604b6094a86Sjd }
1605b6094a86Sjd
1606b6094a86Sjd AACDB_PRINT(softs, CE_NOTE,
1607b6094a86Sjd "ddi_intr_get_nvail returned %d, navail() returned %d",
1608b6094a86Sjd count, avail);
1609b6094a86Sjd
1610b6094a86Sjd /* Allocate an array of interrupt handles */
1611f42c2f53Szhongyan gu - Sun Microsystems - Beijing China softs->intr_size = count * sizeof (ddi_intr_handle_t);
1612f42c2f53Szhongyan gu - Sun Microsystems - Beijing China softs->htable = kmem_alloc(softs->intr_size, KM_SLEEP);
1613b6094a86Sjd
1614b6094a86Sjd if (intr_type == DDI_INTR_TYPE_MSI) {
1615b6094a86Sjd count = 1; /* only one vector needed by now */
1616b6094a86Sjd flag = DDI_INTR_ALLOC_STRICT;
1617b6094a86Sjd } else { /* must be DDI_INTR_TYPE_FIXED */
1618b6094a86Sjd flag = DDI_INTR_ALLOC_NORMAL;
1619b6094a86Sjd }
1620b6094a86Sjd
1621b6094a86Sjd /* Call ddi_intr_alloc() */
1622b6094a86Sjd ret = ddi_intr_alloc(dip, softs->htable, intr_type, 0,
1623b6094a86Sjd count, &actual, flag);
1624b6094a86Sjd
1625b6094a86Sjd if ((ret != DDI_SUCCESS) || (actual == 0)) {
1626b6094a86Sjd AACDB_PRINT(softs, CE_WARN,
1627b6094a86Sjd "ddi_intr_alloc() failed, ret = %d", ret);
1628b6094a86Sjd actual = 0;
1629b6094a86Sjd goto error;
1630b6094a86Sjd }
1631b6094a86Sjd
1632b6094a86Sjd if (actual < count) {
1633b6094a86Sjd AACDB_PRINT(softs, CE_NOTE,
1634b6094a86Sjd "Requested: %d, Received: %d", count, actual);
1635b6094a86Sjd goto error;
1636b6094a86Sjd }
1637b6094a86Sjd
1638b6094a86Sjd softs->intr_cnt = actual;
1639b6094a86Sjd
1640b6094a86Sjd /* Get priority for first msi, assume remaining are all the same */
1641b6094a86Sjd if ((ret = ddi_intr_get_pri(softs->htable[0],
1642b6094a86Sjd &softs->intr_pri)) != DDI_SUCCESS) {
1643b6094a86Sjd AACDB_PRINT(softs, CE_WARN,
1644b6094a86Sjd "ddi_intr_get_pri() failed, ret = %d", ret);
1645b6094a86Sjd goto error;
1646b6094a86Sjd }
1647b6094a86Sjd
1648b6094a86Sjd /* Test for high level mutex */
1649b6094a86Sjd if (softs->intr_pri >= ddi_intr_get_hilevel_pri()) {
1650b6094a86Sjd AACDB_PRINT(softs, CE_WARN,
1651b6094a86Sjd "aac_query_intrs: Hi level interrupt not supported");
1652b6094a86Sjd goto error;
1653b6094a86Sjd }
1654b6094a86Sjd
1655b6094a86Sjd return (DDI_SUCCESS);
1656b6094a86Sjd
1657b6094a86Sjd error:
1658b6094a86Sjd /* Free already allocated intr */
1659b6094a86Sjd for (i = 0; i < actual; i++)
1660b6094a86Sjd (void) ddi_intr_free(softs->htable[i]);
1661b6094a86Sjd
1662f42c2f53Szhongyan gu - Sun Microsystems - Beijing China kmem_free(softs->htable, softs->intr_size);
1663b6094a86Sjd return (DDI_FAILURE);
1664b6094a86Sjd }
1665b6094a86Sjd
1666349b53ddSStuart Maybee
1667b6094a86Sjd /*
1668b6094a86Sjd * Register FIXED or MSI interrupts, and enable them
1669b6094a86Sjd */
1670b6094a86Sjd static int
aac_add_intrs(struct aac_softstate * softs)1671b6094a86Sjd aac_add_intrs(struct aac_softstate *softs)
1672b6094a86Sjd {
1673b6094a86Sjd int i, ret;
1674f42c2f53Szhongyan gu - Sun Microsystems - Beijing China int actual;
1675b6094a86Sjd ddi_intr_handler_t *aac_intr;
1676b6094a86Sjd
1677b6094a86Sjd actual = softs->intr_cnt;
1678b4a8b33bSToomas Soome aac_intr = ((softs->flags & AAC_FLAGS_NEW_COMM) ?
1679b6094a86Sjd aac_intr_new : aac_intr_old);
1680b6094a86Sjd
1681b6094a86Sjd /* Call ddi_intr_add_handler() */
1682b6094a86Sjd for (i = 0; i < actual; i++) {
1683b6094a86Sjd if ((ret = ddi_intr_add_handler(softs->htable[i],
1684b6094a86Sjd aac_intr, (caddr_t)softs, NULL)) != DDI_SUCCESS) {
1685b6094a86Sjd cmn_err(CE_WARN,
1686b6094a86Sjd "ddi_intr_add_handler() failed ret = %d", ret);
1687b6094a86Sjd
1688b6094a86Sjd /* Free already allocated intr */
1689b6094a86Sjd for (i = 0; i < actual; i++)
1690b6094a86Sjd (void) ddi_intr_free(softs->htable[i]);
1691b6094a86Sjd
1692f42c2f53Szhongyan gu - Sun Microsystems - Beijing China kmem_free(softs->htable, softs->intr_size);
1693b6094a86Sjd return (DDI_FAILURE);
1694b6094a86Sjd }
1695b6094a86Sjd }
1696b6094a86Sjd
1697b6094a86Sjd if ((ret = ddi_intr_get_cap(softs->htable[0], &softs->intr_cap))
1698b6094a86Sjd != DDI_SUCCESS) {
1699b6094a86Sjd cmn_err(CE_WARN, "ddi_intr_get_cap() failed, ret = %d", ret);
1700b6094a86Sjd
1701b6094a86Sjd /* Free already allocated intr */
1702b6094a86Sjd for (i = 0; i < actual; i++)
1703b6094a86Sjd (void) ddi_intr_free(softs->htable[i]);
1704b6094a86Sjd
1705f42c2f53Szhongyan gu - Sun Microsystems - Beijing China kmem_free(softs->htable, softs->intr_size);
1706b6094a86Sjd return (DDI_FAILURE);
1707b6094a86Sjd }
1708b6094a86Sjd
1709b6094a86Sjd return (DDI_SUCCESS);
1710b6094a86Sjd }
1711b6094a86Sjd
1712b6094a86Sjd /*
1713b6094a86Sjd * Unregister FIXED or MSI interrupts
1714b6094a86Sjd */
1715b6094a86Sjd static void
aac_remove_intrs(struct aac_softstate * softs)1716b6094a86Sjd aac_remove_intrs(struct aac_softstate *softs)
1717b6094a86Sjd {
1718b6094a86Sjd int i;
1719b6094a86Sjd
1720b6094a86Sjd /* Disable all interrupts */
1721f42c2f53Szhongyan gu - Sun Microsystems - Beijing China (void) aac_disable_intrs(softs);
1722b6094a86Sjd /* Call ddi_intr_remove_handler() */
1723b6094a86Sjd for (i = 0; i < softs->intr_cnt; i++) {
1724b6094a86Sjd (void) ddi_intr_remove_handler(softs->htable[i]);
1725b6094a86Sjd (void) ddi_intr_free(softs->htable[i]);
1726b6094a86Sjd }
1727b6094a86Sjd
1728f42c2f53Szhongyan gu - Sun Microsystems - Beijing China kmem_free(softs->htable, softs->intr_size);
1729f42c2f53Szhongyan gu - Sun Microsystems - Beijing China }
1730f42c2f53Szhongyan gu - Sun Microsystems - Beijing China
1731f42c2f53Szhongyan gu - Sun Microsystems - Beijing China static int
aac_enable_intrs(struct aac_softstate * softs)1732f42c2f53Szhongyan gu - Sun Microsystems - Beijing China aac_enable_intrs(struct aac_softstate *softs)
1733f42c2f53Szhongyan gu - Sun Microsystems - Beijing China {
1734f42c2f53Szhongyan gu - Sun Microsystems - Beijing China int rval = AACOK;
1735f42c2f53Szhongyan gu - Sun Microsystems - Beijing China
1736f42c2f53Szhongyan gu - Sun Microsystems - Beijing China if (softs->intr_cap & DDI_INTR_FLAG_BLOCK) {
1737f42c2f53Szhongyan gu - Sun Microsystems - Beijing China /* for MSI block enable */
1738f42c2f53Szhongyan gu - Sun Microsystems - Beijing China if (ddi_intr_block_enable(softs->htable, softs->intr_cnt) !=
1739f42c2f53Szhongyan gu - Sun Microsystems - Beijing China DDI_SUCCESS)
1740f42c2f53Szhongyan gu - Sun Microsystems - Beijing China rval = AACERR;
1741f42c2f53Szhongyan gu - Sun Microsystems - Beijing China } else {
1742f42c2f53Szhongyan gu - Sun Microsystems - Beijing China int i;
1743f42c2f53Szhongyan gu - Sun Microsystems - Beijing China
1744f42c2f53Szhongyan gu - Sun Microsystems - Beijing China /* Call ddi_intr_enable() for legacy/MSI non block enable */
1745f42c2f53Szhongyan gu - Sun Microsystems - Beijing China for (i = 0; i < softs->intr_cnt; i++) {
1746f42c2f53Szhongyan gu - Sun Microsystems - Beijing China if (ddi_intr_enable(softs->htable[i]) != DDI_SUCCESS)
1747f42c2f53Szhongyan gu - Sun Microsystems - Beijing China rval = AACERR;
1748f42c2f53Szhongyan gu - Sun Microsystems - Beijing China }
1749f42c2f53Szhongyan gu - Sun Microsystems - Beijing China }
1750f42c2f53Szhongyan gu - Sun Microsystems - Beijing China return (rval);
1751f42c2f53Szhongyan gu - Sun Microsystems - Beijing China }
1752f42c2f53Szhongyan gu - Sun Microsystems - Beijing China
1753f42c2f53Szhongyan gu - Sun Microsystems - Beijing China static int
aac_disable_intrs(struct aac_softstate * softs)1754f42c2f53Szhongyan gu - Sun Microsystems - Beijing China aac_disable_intrs(struct aac_softstate *softs)
1755f42c2f53Szhongyan gu - Sun Microsystems - Beijing China {
1756f42c2f53Szhongyan gu - Sun Microsystems - Beijing China int rval = AACOK;
1757f42c2f53Szhongyan gu - Sun Microsystems - Beijing China
1758f42c2f53Szhongyan gu - Sun Microsystems - Beijing China if (softs->intr_cap & DDI_INTR_FLAG_BLOCK) {
1759f42c2f53Szhongyan gu - Sun Microsystems - Beijing China /* Call ddi_intr_block_disable() */
1760f42c2f53Szhongyan gu - Sun Microsystems - Beijing China if (ddi_intr_block_disable(softs->htable, softs->intr_cnt) !=
1761f42c2f53Szhongyan gu - Sun Microsystems - Beijing China DDI_SUCCESS)
1762f42c2f53Szhongyan gu - Sun Microsystems - Beijing China rval = AACERR;
1763f42c2f53Szhongyan gu - Sun Microsystems - Beijing China } else {
1764f42c2f53Szhongyan gu - Sun Microsystems - Beijing China int i;
1765f42c2f53Szhongyan gu - Sun Microsystems - Beijing China
1766f42c2f53Szhongyan gu - Sun Microsystems - Beijing China for (i = 0; i < softs->intr_cnt; i++) {
1767f42c2f53Szhongyan gu - Sun Microsystems - Beijing China if (ddi_intr_disable(softs->htable[i]) != DDI_SUCCESS)
1768f42c2f53Szhongyan gu - Sun Microsystems - Beijing China rval = AACERR;
1769f42c2f53Szhongyan gu - Sun Microsystems - Beijing China }
1770f42c2f53Szhongyan gu - Sun Microsystems - Beijing China }
1771f42c2f53Szhongyan gu - Sun Microsystems - Beijing China return (rval);
1772b6094a86Sjd }
1773b6094a86Sjd
1774d7c5bf88Spl /*
1775d7c5bf88Spl * Set pkt_reason and OR in pkt_statistics flag
1776d7c5bf88Spl */
1777d7c5bf88Spl static void
aac_set_pkt_reason(struct aac_softstate * softs,struct aac_cmd * acp,uchar_t reason,uint_t stat)1778d7c5bf88Spl aac_set_pkt_reason(struct aac_softstate *softs, struct aac_cmd *acp,
1779d7c5bf88Spl uchar_t reason, uint_t stat)
1780d7c5bf88Spl {
1781382c8bcaSpl #ifndef __lock_lint
1782d7c5bf88Spl _NOTE(ARGUNUSED(softs))
1783382c8bcaSpl #endif
1784d7c5bf88Spl if (acp->pkt->pkt_reason == CMD_CMPLT)
1785d7c5bf88Spl acp->pkt->pkt_reason = reason;
1786d7c5bf88Spl acp->pkt->pkt_statistics |= stat;
1787d7c5bf88Spl }
1788d7c5bf88Spl
1789830d82f7Spl /*
1790d7c5bf88Spl * Handle a finished pkt of soft SCMD
1791830d82f7Spl */
1792830d82f7Spl static void
aac_soft_callback(struct aac_softstate * softs,struct aac_cmd * acp)1793d7c5bf88Spl aac_soft_callback(struct aac_softstate *softs, struct aac_cmd *acp)
1794830d82f7Spl {
1795d7c5bf88Spl ASSERT(acp->pkt);
1796830d82f7Spl
1797d7c5bf88Spl acp->flags |= AAC_CMD_CMPLT;
1798830d82f7Spl
1799d7c5bf88Spl acp->pkt->pkt_state |= STATE_GOT_BUS | STATE_GOT_TARGET | \
180058bc78c7SXin Chen STATE_SENT_CMD | STATE_GOT_STATUS;
1801d7c5bf88Spl if (acp->pkt->pkt_state & STATE_XFERRED_DATA)
1802d7c5bf88Spl acp->pkt->pkt_resid = 0;
1803830d82f7Spl
1804d7c5bf88Spl /* AAC_CMD_NO_INTR means no complete callback */
1805c9487164Spl if (!(acp->flags & AAC_CMD_NO_INTR)) {
1806382c8bcaSpl mutex_enter(&softs->q_comp_mutex);
1807c9487164Spl aac_cmd_enqueue(&softs->q_comp, acp);
1808382c8bcaSpl mutex_exit(&softs->q_comp_mutex);
1809830d82f7Spl ddi_trigger_softintr(softs->softint_id);
1810830d82f7Spl }
1811830d82f7Spl }
1812830d82f7Spl
1813830d82f7Spl /*
1814c9487164Spl * Handlers for completed IOs, common to aac_intr_new() and aac_intr_old()
1815830d82f7Spl */
1816d7c5bf88Spl
1817d7c5bf88Spl /*
1818d7c5bf88Spl * Handle completed logical device IO command
1819d7c5bf88Spl */
1820382c8bcaSpl /*ARGSUSED*/
1821830d82f7Spl static void
aac_ld_complete(struct aac_softstate * softs,struct aac_cmd * acp)1822d7c5bf88Spl aac_ld_complete(struct aac_softstate *softs, struct aac_cmd *acp)
1823830d82f7Spl {
1824d7c5bf88Spl struct aac_slot *slotp = acp->slotp;
1825d7c5bf88Spl struct aac_blockread_response *resp;
1826942c5e3cSpl uint32_t status;
1827830d82f7Spl
1828382c8bcaSpl ASSERT(!(acp->flags & AAC_CMD_SYNC));
1829382c8bcaSpl ASSERT(!(acp->flags & AAC_CMD_NO_CB));
1830382c8bcaSpl
183158bc78c7SXin Chen acp->pkt->pkt_state |= STATE_GOT_STATUS;
183258bc78c7SXin Chen
1833d7c5bf88Spl /*
1834d7c5bf88Spl * block_read/write has a similar response header, use blockread
1835d7c5bf88Spl * response for both.
1836d7c5bf88Spl */
1837382c8bcaSpl resp = (struct aac_blockread_response *)&slotp->fibp->data[0];
1838942c5e3cSpl status = ddi_get32(slotp->fib_acc_handle, &resp->Status);
1839942c5e3cSpl if (status == ST_OK) {
1840382c8bcaSpl acp->pkt->pkt_resid = 0;
1841382c8bcaSpl acp->pkt->pkt_state |= STATE_XFERRED_DATA;
1842d7c5bf88Spl } else {
1843382c8bcaSpl aac_set_arq_data_hwerr(acp);
1844d7c5bf88Spl }
1845d7c5bf88Spl }
1846832e0b5aSpl
184758bc78c7SXin Chen /*
184858bc78c7SXin Chen * Handle completed phys. device IO command
184958bc78c7SXin Chen */
185058bc78c7SXin Chen static void
aac_pd_complete(struct aac_softstate * softs,struct aac_cmd * acp)185158bc78c7SXin Chen aac_pd_complete(struct aac_softstate *softs, struct aac_cmd *acp)
185258bc78c7SXin Chen {
185358bc78c7SXin Chen ddi_acc_handle_t acc = acp->slotp->fib_acc_handle;
185458bc78c7SXin Chen struct aac_fib *fibp = acp->slotp->fibp;
185558bc78c7SXin Chen struct scsi_pkt *pkt = acp->pkt;
185658bc78c7SXin Chen struct aac_srb_reply *resp;
185758bc78c7SXin Chen uint32_t resp_status;
185858bc78c7SXin Chen
185958bc78c7SXin Chen ASSERT(!(acp->flags & AAC_CMD_SYNC));
186058bc78c7SXin Chen ASSERT(!(acp->flags & AAC_CMD_NO_CB));
186158bc78c7SXin Chen
186258bc78c7SXin Chen resp = (struct aac_srb_reply *)&fibp->data[0];
186358bc78c7SXin Chen resp_status = ddi_get32(acc, &resp->status);
186458bc78c7SXin Chen
186558bc78c7SXin Chen /* First check FIB status */
186658bc78c7SXin Chen if (resp_status == ST_OK) {
186758bc78c7SXin Chen uint32_t scsi_status;
186858bc78c7SXin Chen uint32_t srb_status;
186958bc78c7SXin Chen uint32_t data_xfer_length;
187058bc78c7SXin Chen
187158bc78c7SXin Chen scsi_status = ddi_get32(acc, &resp->scsi_status);
187258bc78c7SXin Chen srb_status = ddi_get32(acc, &resp->srb_status);
187358bc78c7SXin Chen data_xfer_length = ddi_get32(acc, &resp->data_xfer_length);
187458bc78c7SXin Chen
187558bc78c7SXin Chen *pkt->pkt_scbp = (uint8_t)scsi_status;
187658bc78c7SXin Chen pkt->pkt_state |= STATE_GOT_STATUS;
187758bc78c7SXin Chen if (scsi_status == STATUS_GOOD) {
187858bc78c7SXin Chen uchar_t cmd = ((union scsi_cdb *)(void *)
187958bc78c7SXin Chen (pkt->pkt_cdbp))->scc_cmd;
188058bc78c7SXin Chen
188158bc78c7SXin Chen /* Next check SRB status */
188258bc78c7SXin Chen switch (srb_status & 0x3f) {
188358bc78c7SXin Chen case SRB_STATUS_DATA_OVERRUN:
188458bc78c7SXin Chen AACDB_PRINT(softs, CE_NOTE, "DATA_OVERRUN: " \
188558bc78c7SXin Chen "scmd=%d, xfer=%d, buflen=%d",
188658bc78c7SXin Chen (uint32_t)cmd, data_xfer_length,
188758bc78c7SXin Chen acp->bcount);
188858bc78c7SXin Chen
188958bc78c7SXin Chen switch (cmd) {
189058bc78c7SXin Chen case SCMD_READ:
189158bc78c7SXin Chen case SCMD_WRITE:
189258bc78c7SXin Chen case SCMD_READ_G1:
189358bc78c7SXin Chen case SCMD_WRITE_G1:
189458bc78c7SXin Chen case SCMD_READ_G4:
189558bc78c7SXin Chen case SCMD_WRITE_G4:
189658bc78c7SXin Chen case SCMD_READ_G5:
189758bc78c7SXin Chen case SCMD_WRITE_G5:
189858bc78c7SXin Chen aac_set_pkt_reason(softs, acp,
189958bc78c7SXin Chen CMD_DATA_OVR, 0);
190058bc78c7SXin Chen break;
190158bc78c7SXin Chen }
190258bc78c7SXin Chen /*FALLTHRU*/
190358bc78c7SXin Chen case SRB_STATUS_ERROR_RECOVERY:
190458bc78c7SXin Chen case SRB_STATUS_PENDING:
190558bc78c7SXin Chen case SRB_STATUS_SUCCESS:
190658bc78c7SXin Chen /*
190758bc78c7SXin Chen * pkt_resid should only be calculated if the
190858bc78c7SXin Chen * status is ERROR_RECOVERY/PENDING/SUCCESS/
190958bc78c7SXin Chen * OVERRUN/UNDERRUN
191058bc78c7SXin Chen */
191158bc78c7SXin Chen if (data_xfer_length) {
191258bc78c7SXin Chen pkt->pkt_state |= STATE_XFERRED_DATA;
191358bc78c7SXin Chen pkt->pkt_resid = acp->bcount - \
191458bc78c7SXin Chen data_xfer_length;
191558bc78c7SXin Chen ASSERT(pkt->pkt_resid >= 0);
191658bc78c7SXin Chen }
191758bc78c7SXin Chen break;
191858bc78c7SXin Chen case SRB_STATUS_ABORTED:
191958bc78c7SXin Chen AACDB_PRINT(softs, CE_NOTE,
192058bc78c7SXin Chen "SRB_STATUS_ABORTED, xfer=%d, resid=%d",
192158bc78c7SXin Chen data_xfer_length, pkt->pkt_resid);
192258bc78c7SXin Chen aac_set_pkt_reason(softs, acp, CMD_ABORTED,
192358bc78c7SXin Chen STAT_ABORTED);
192458bc78c7SXin Chen break;
192558bc78c7SXin Chen case SRB_STATUS_ABORT_FAILED:
192658bc78c7SXin Chen AACDB_PRINT(softs, CE_NOTE,
192758bc78c7SXin Chen "SRB_STATUS_ABORT_FAILED, xfer=%d, " \
192858bc78c7SXin Chen "resid=%d", data_xfer_length,
192958bc78c7SXin Chen pkt->pkt_resid);
193058bc78c7SXin Chen aac_set_pkt_reason(softs, acp, CMD_ABORT_FAIL,
193158bc78c7SXin Chen 0);
193258bc78c7SXin Chen break;
193358bc78c7SXin Chen case SRB_STATUS_PARITY_ERROR:
193458bc78c7SXin Chen AACDB_PRINT(softs, CE_NOTE,
193558bc78c7SXin Chen "SRB_STATUS_PARITY_ERROR, xfer=%d, " \
193658bc78c7SXin Chen "resid=%d", data_xfer_length,
193758bc78c7SXin Chen pkt->pkt_resid);
193858bc78c7SXin Chen aac_set_pkt_reason(softs, acp, CMD_PER_FAIL, 0);
193958bc78c7SXin Chen break;
194058bc78c7SXin Chen case SRB_STATUS_NO_DEVICE:
194158bc78c7SXin Chen case SRB_STATUS_INVALID_PATH_ID:
194258bc78c7SXin Chen case SRB_STATUS_INVALID_TARGET_ID:
194358bc78c7SXin Chen case SRB_STATUS_INVALID_LUN:
194458bc78c7SXin Chen case SRB_STATUS_SELECTION_TIMEOUT:
194558bc78c7SXin Chen #ifdef DEBUG
194658bc78c7SXin Chen if (AAC_DEV_IS_VALID(acp->dvp)) {
194758bc78c7SXin Chen AACDB_PRINT(softs, CE_NOTE,
194858bc78c7SXin Chen "SRB_STATUS_NO_DEVICE(%d), " \
194958bc78c7SXin Chen "xfer=%d, resid=%d ",
195058bc78c7SXin Chen srb_status & 0x3f,
195158bc78c7SXin Chen data_xfer_length, pkt->pkt_resid);
195258bc78c7SXin Chen }
195358bc78c7SXin Chen #endif
195458bc78c7SXin Chen aac_set_pkt_reason(softs, acp, CMD_DEV_GONE, 0);
195558bc78c7SXin Chen break;
195658bc78c7SXin Chen case SRB_STATUS_COMMAND_TIMEOUT:
195758bc78c7SXin Chen case SRB_STATUS_TIMEOUT:
195858bc78c7SXin Chen AACDB_PRINT(softs, CE_NOTE,
195958bc78c7SXin Chen "SRB_STATUS_COMMAND_TIMEOUT, xfer=%d, " \
196058bc78c7SXin Chen "resid=%d", data_xfer_length,
196158bc78c7SXin Chen pkt->pkt_resid);
196258bc78c7SXin Chen aac_set_pkt_reason(softs, acp, CMD_TIMEOUT,
196358bc78c7SXin Chen STAT_TIMEOUT);
196458bc78c7SXin Chen break;
196558bc78c7SXin Chen case SRB_STATUS_BUS_RESET:
196658bc78c7SXin Chen AACDB_PRINT(softs, CE_NOTE,
196758bc78c7SXin Chen "SRB_STATUS_BUS_RESET, xfer=%d, " \
196858bc78c7SXin Chen "resid=%d", data_xfer_length,
196958bc78c7SXin Chen pkt->pkt_resid);
197058bc78c7SXin Chen aac_set_pkt_reason(softs, acp, CMD_RESET,
197158bc78c7SXin Chen STAT_BUS_RESET);
197258bc78c7SXin Chen break;
197358bc78c7SXin Chen default:
197458bc78c7SXin Chen AACDB_PRINT(softs, CE_NOTE, "srb_status=%d, " \
197558bc78c7SXin Chen "xfer=%d, resid=%d", srb_status & 0x3f,
197658bc78c7SXin Chen data_xfer_length, pkt->pkt_resid);
197758bc78c7SXin Chen aac_set_pkt_reason(softs, acp, CMD_TRAN_ERR, 0);
197858bc78c7SXin Chen break;
197958bc78c7SXin Chen }
198058bc78c7SXin Chen } else if (scsi_status == STATUS_CHECK) {
198158bc78c7SXin Chen /* CHECK CONDITION */
198258bc78c7SXin Chen struct scsi_arq_status *arqstat =
198358bc78c7SXin Chen (void *)(pkt->pkt_scbp);
198458bc78c7SXin Chen uint32_t sense_data_size;
198558bc78c7SXin Chen
198658bc78c7SXin Chen pkt->pkt_state |= STATE_ARQ_DONE;
198758bc78c7SXin Chen
198858bc78c7SXin Chen *(uint8_t *)&arqstat->sts_rqpkt_status = STATUS_GOOD;
198958bc78c7SXin Chen arqstat->sts_rqpkt_reason = CMD_CMPLT;
199058bc78c7SXin Chen arqstat->sts_rqpkt_resid = 0;
199158bc78c7SXin Chen arqstat->sts_rqpkt_state =
199258bc78c7SXin Chen STATE_GOT_BUS |
199358bc78c7SXin Chen STATE_GOT_TARGET |
199458bc78c7SXin Chen STATE_SENT_CMD |
199558bc78c7SXin Chen STATE_XFERRED_DATA;
199658bc78c7SXin Chen arqstat->sts_rqpkt_statistics = 0;
199758bc78c7SXin Chen
199858bc78c7SXin Chen sense_data_size = ddi_get32(acc,
199958bc78c7SXin Chen &resp->sense_data_size);
200058bc78c7SXin Chen ASSERT(sense_data_size <= AAC_SENSE_BUFFERSIZE);
200158bc78c7SXin Chen AACDB_PRINT(softs, CE_NOTE,
200258bc78c7SXin Chen "CHECK CONDITION: sense len=%d, xfer len=%d",
200358bc78c7SXin Chen sense_data_size, data_xfer_length);
200458bc78c7SXin Chen
200558bc78c7SXin Chen if (sense_data_size > SENSE_LENGTH)
200658bc78c7SXin Chen sense_data_size = SENSE_LENGTH;
200758bc78c7SXin Chen ddi_rep_get8(acc, (uint8_t *)&arqstat->sts_sensedata,
200858bc78c7SXin Chen (uint8_t *)resp->sense_data, sense_data_size,
200958bc78c7SXin Chen DDI_DEV_AUTOINCR);
201058bc78c7SXin Chen } else {
201158bc78c7SXin Chen AACDB_PRINT(softs, CE_WARN, "invaild scsi status: " \
201258bc78c7SXin Chen "scsi_status=%d, srb_status=%d",
201358bc78c7SXin Chen scsi_status, srb_status);
201458bc78c7SXin Chen aac_set_pkt_reason(softs, acp, CMD_TRAN_ERR, 0);
201558bc78c7SXin Chen }
201658bc78c7SXin Chen } else {
201758bc78c7SXin Chen AACDB_PRINT(softs, CE_NOTE, "SRB failed: fib status %d",
201858bc78c7SXin Chen resp_status);
201958bc78c7SXin Chen aac_set_pkt_reason(softs, acp, CMD_TRAN_ERR, 0);
202058bc78c7SXin Chen }
202158bc78c7SXin Chen }
202258bc78c7SXin Chen
2023d7c5bf88Spl /*
2024d7c5bf88Spl * Handle completed IOCTL command
2025d7c5bf88Spl */
2026382c8bcaSpl /*ARGSUSED*/
2027d7c5bf88Spl void
aac_ioctl_complete(struct aac_softstate * softs,struct aac_cmd * acp)2028d7c5bf88Spl aac_ioctl_complete(struct aac_softstate *softs, struct aac_cmd *acp)
2029d7c5bf88Spl {
2030d7c5bf88Spl struct aac_slot *slotp = acp->slotp;
2031830d82f7Spl
2032382c8bcaSpl /*
2033382c8bcaSpl * NOTE: Both aac_ioctl_send_fib() and aac_send_raw_srb()
2034382c8bcaSpl * may wait on softs->event, so use cv_broadcast() instead
2035382c8bcaSpl * of cv_signal().
2036382c8bcaSpl */
2037382c8bcaSpl ASSERT(acp->flags & AAC_CMD_SYNC);
2038382c8bcaSpl ASSERT(acp->flags & AAC_CMD_NO_CB);
2039382c8bcaSpl
2040d7c5bf88Spl /* Get the size of the response FIB from its FIB.Header.Size field */
2041942c5e3cSpl acp->fib_size = ddi_get16(slotp->fib_acc_handle,
2042942c5e3cSpl &slotp->fibp->Header.Size);
2043830d82f7Spl
2044d7c5bf88Spl ASSERT(acp->fib_size <= softs->aac_max_fib_size);
2045942c5e3cSpl ddi_rep_get8(slotp->fib_acc_handle, (uint8_t *)acp->fibp,
2046942c5e3cSpl (uint8_t *)slotp->fibp, acp->fib_size, DDI_DEV_AUTOINCR);
2047382c8bcaSpl }
2048832e0b5aSpl
2049f42c2f53Szhongyan gu - Sun Microsystems - Beijing China /*
2050f42c2f53Szhongyan gu - Sun Microsystems - Beijing China * Handle completed sync fib command
2051f42c2f53Szhongyan gu - Sun Microsystems - Beijing China */
2052f42c2f53Szhongyan gu - Sun Microsystems - Beijing China /*ARGSUSED*/
2053f42c2f53Szhongyan gu - Sun Microsystems - Beijing China void
aac_sync_complete(struct aac_softstate * softs,struct aac_cmd * acp)2054f42c2f53Szhongyan gu - Sun Microsystems - Beijing China aac_sync_complete(struct aac_softstate *softs, struct aac_cmd *acp)
2055f42c2f53Szhongyan gu - Sun Microsystems - Beijing China {
2056f42c2f53Szhongyan gu - Sun Microsystems - Beijing China }
2057f42c2f53Szhongyan gu - Sun Microsystems - Beijing China
2058382c8bcaSpl /*
2059382c8bcaSpl * Handle completed Flush command
2060382c8bcaSpl */
2061382c8bcaSpl /*ARGSUSED*/
2062382c8bcaSpl static void
aac_synccache_complete(struct aac_softstate * softs,struct aac_cmd * acp)2063382c8bcaSpl aac_synccache_complete(struct aac_softstate *softs, struct aac_cmd *acp)
2064382c8bcaSpl {
2065382c8bcaSpl struct aac_slot *slotp = acp->slotp;
2066382c8bcaSpl ddi_acc_handle_t acc = slotp->fib_acc_handle;
2067382c8bcaSpl struct aac_synchronize_reply *resp;
2068382c8bcaSpl uint32_t status;
2069832e0b5aSpl
2070382c8bcaSpl ASSERT(!(acp->flags & AAC_CMD_SYNC));
2071382c8bcaSpl
207258bc78c7SXin Chen acp->pkt->pkt_state |= STATE_GOT_STATUS;
207358bc78c7SXin Chen
2074382c8bcaSpl resp = (struct aac_synchronize_reply *)&slotp->fibp->data[0];
2075382c8bcaSpl status = ddi_get32(acc, &resp->Status);
2076382c8bcaSpl if (status != CT_OK)
2077382c8bcaSpl aac_set_arq_data_hwerr(acp);
2078830d82f7Spl }
2079830d82f7Spl
20801ee13a44SXinChen /*ARGSUSED*/
2081b40e8a89Szhongyan gu - Sun Microsystems - Beijing China static void
aac_startstop_complete(struct aac_softstate * softs,struct aac_cmd * acp)2082b40e8a89Szhongyan gu - Sun Microsystems - Beijing China aac_startstop_complete(struct aac_softstate *softs, struct aac_cmd *acp)
2083b40e8a89Szhongyan gu - Sun Microsystems - Beijing China {
2084b40e8a89Szhongyan gu - Sun Microsystems - Beijing China struct aac_slot *slotp = acp->slotp;
2085b40e8a89Szhongyan gu - Sun Microsystems - Beijing China ddi_acc_handle_t acc = slotp->fib_acc_handle;
2086b40e8a89Szhongyan gu - Sun Microsystems - Beijing China struct aac_Container_resp *resp;
2087b40e8a89Szhongyan gu - Sun Microsystems - Beijing China uint32_t status;
2088b40e8a89Szhongyan gu - Sun Microsystems - Beijing China
2089b40e8a89Szhongyan gu - Sun Microsystems - Beijing China ASSERT(!(acp->flags & AAC_CMD_SYNC));
2090b40e8a89Szhongyan gu - Sun Microsystems - Beijing China
2091b40e8a89Szhongyan gu - Sun Microsystems - Beijing China acp->pkt->pkt_state |= STATE_GOT_STATUS;
2092b40e8a89Szhongyan gu - Sun Microsystems - Beijing China
2093b40e8a89Szhongyan gu - Sun Microsystems - Beijing China resp = (struct aac_Container_resp *)&slotp->fibp->data[0];
2094b40e8a89Szhongyan gu - Sun Microsystems - Beijing China status = ddi_get32(acc, &resp->Status);
2095b40e8a89Szhongyan gu - Sun Microsystems - Beijing China if (status != 0) {
2096b40e8a89Szhongyan gu - Sun Microsystems - Beijing China AACDB_PRINT(softs, CE_WARN, "Cannot start/stop a unit");
2097b40e8a89Szhongyan gu - Sun Microsystems - Beijing China aac_set_arq_data_hwerr(acp);
2098b40e8a89Szhongyan gu - Sun Microsystems - Beijing China }
2099b40e8a89Szhongyan gu - Sun Microsystems - Beijing China }
2100b40e8a89Szhongyan gu - Sun Microsystems - Beijing China
2101830d82f7Spl /*
2102830d82f7Spl * Access PCI space to see if the driver can support the card
2103830d82f7Spl */
21047c478bd9Sstevel@tonic-gate static int
aac_check_card_type(struct aac_softstate * softs)21057c478bd9Sstevel@tonic-gate aac_check_card_type(struct aac_softstate *softs)
21067c478bd9Sstevel@tonic-gate {
2107d937e6ebSpl ddi_acc_handle_t pci_config_handle;
2108d937e6ebSpl int card_index;
21097c478bd9Sstevel@tonic-gate uint32_t pci_cmd;
21107c478bd9Sstevel@tonic-gate
2111830d82f7Spl /* Map pci configuration space */
2112c9487164Spl if ((pci_config_setup(softs->devinfo_p, &pci_config_handle)) !=
2113c9487164Spl DDI_SUCCESS) {
21141dd0a2dbSpl AACDB_PRINT(softs, CE_WARN, "Cannot setup pci config space");
21157c478bd9Sstevel@tonic-gate return (AACERR);
21167c478bd9Sstevel@tonic-gate }
21177c478bd9Sstevel@tonic-gate
21181cea6be9Sxc softs->vendid = pci_config_get16(pci_config_handle, PCI_CONF_VENID);
21191cea6be9Sxc softs->devid = pci_config_get16(pci_config_handle, PCI_CONF_DEVID);
21201cea6be9Sxc softs->subvendid = pci_config_get16(pci_config_handle,
21211cea6be9Sxc PCI_CONF_SUBVENID);
21221cea6be9Sxc softs->subsysid = pci_config_get16(pci_config_handle,
21231cea6be9Sxc PCI_CONF_SUBSYSID);
21241cea6be9Sxc
2125d937e6ebSpl card_index = 0;
2126d937e6ebSpl while (!CARD_IS_UNKNOWN(card_index)) {
21271cea6be9Sxc if ((aac_cards[card_index].vendor == softs->vendid) &&
21281cea6be9Sxc (aac_cards[card_index].device == softs->devid) &&
21291cea6be9Sxc (aac_cards[card_index].subvendor == softs->subvendid) &&
21301cea6be9Sxc (aac_cards[card_index].subsys == softs->subsysid)) {
21317c478bd9Sstevel@tonic-gate break;
21327c478bd9Sstevel@tonic-gate }
2133d937e6ebSpl card_index++;
21347c478bd9Sstevel@tonic-gate }
21357c478bd9Sstevel@tonic-gate
2136d937e6ebSpl softs->card = card_index;
2137d937e6ebSpl softs->hwif = aac_cards[card_index].hwif;
2138d937e6ebSpl
2139d937e6ebSpl /*
2140d937e6ebSpl * Unknown aac card
2141d937e6ebSpl * do a generic match based on the VendorID and DeviceID to
2142d937e6ebSpl * support the new cards in the aac family
2143d937e6ebSpl */
2144d937e6ebSpl if (CARD_IS_UNKNOWN(card_index)) {
21451cea6be9Sxc if (softs->vendid != 0x9005) {
21461dd0a2dbSpl AACDB_PRINT(softs, CE_WARN,
21471cea6be9Sxc "Unknown vendor 0x%x", softs->vendid);
2148d937e6ebSpl goto error;
21497c478bd9Sstevel@tonic-gate }
21501cea6be9Sxc switch (softs->devid) {
2151d937e6ebSpl case 0x285:
2152d937e6ebSpl softs->hwif = AAC_HWIF_I960RX;
2153d937e6ebSpl break;
2154d937e6ebSpl case 0x286:
2155d937e6ebSpl softs->hwif = AAC_HWIF_RKT;
2156d937e6ebSpl break;
2157d937e6ebSpl default:
21581dd0a2dbSpl AACDB_PRINT(softs, CE_WARN,
21591cea6be9Sxc "Unknown device \"pci9005,%x\"", softs->devid);
21607c478bd9Sstevel@tonic-gate goto error;
21617c478bd9Sstevel@tonic-gate }
2162d937e6ebSpl }
2163d937e6ebSpl
2164d937e6ebSpl /* Set hardware dependent interface */
2165d937e6ebSpl switch (softs->hwif) {
2166d937e6ebSpl case AAC_HWIF_I960RX:
2167d937e6ebSpl softs->aac_if = aac_rx_interface;
2168d937e6ebSpl softs->map_size_min = AAC_MAP_SIZE_MIN_RX;
2169d937e6ebSpl break;
2170d937e6ebSpl case AAC_HWIF_RKT:
2171d937e6ebSpl softs->aac_if = aac_rkt_interface;
2172d937e6ebSpl softs->map_size_min = AAC_MAP_SIZE_MIN_RKT;
2173d937e6ebSpl break;
2174d937e6ebSpl default:
21751dd0a2dbSpl AACDB_PRINT(softs, CE_WARN,
21761dd0a2dbSpl "Unknown hardware interface %d", softs->hwif);
2177d937e6ebSpl goto error;
2178d937e6ebSpl }
2179d937e6ebSpl
2180d937e6ebSpl /* Set card names */
2181d937e6ebSpl (void *)strncpy(softs->vendor_name, aac_cards[card_index].vid,
2182c9487164Spl AAC_VENDOR_LEN);
2183d937e6ebSpl (void *)strncpy(softs->product_name, aac_cards[card_index].desc,
2184c9487164Spl AAC_PRODUCT_LEN);
2185d937e6ebSpl
2186d937e6ebSpl /* Set up quirks */
2187d937e6ebSpl softs->flags = aac_cards[card_index].quirks;
2188d937e6ebSpl
2189d937e6ebSpl /* Force the busmaster enable bit on */
2190d937e6ebSpl pci_cmd = pci_config_get16(pci_config_handle, PCI_CONF_COMM);
2191d937e6ebSpl if ((pci_cmd & PCI_COMM_ME) == 0) {
2192d937e6ebSpl pci_cmd |= PCI_COMM_ME;
2193c9487164Spl pci_config_put16(pci_config_handle, PCI_CONF_COMM, pci_cmd);
2194c9487164Spl pci_cmd = pci_config_get16(pci_config_handle, PCI_CONF_COMM);
2195d937e6ebSpl if ((pci_cmd & PCI_COMM_ME) == 0) {
2196c9487164Spl cmn_err(CE_CONT, "?Cannot enable busmaster bit");
2197d937e6ebSpl goto error;
2198d937e6ebSpl }
2199d937e6ebSpl }
2200d937e6ebSpl
2201d937e6ebSpl /* Set memory base to map */
22021dd0a2dbSpl softs->pci_mem_base_paddr = 0xfffffff0UL & \
22031dd0a2dbSpl pci_config_get32(pci_config_handle, PCI_CONF_BASE0);
22047c478bd9Sstevel@tonic-gate
22057c478bd9Sstevel@tonic-gate pci_config_teardown(&pci_config_handle);
2206d937e6ebSpl
2207d937e6ebSpl return (AACOK); /* card type detected */
22087c478bd9Sstevel@tonic-gate error:
22097c478bd9Sstevel@tonic-gate pci_config_teardown(&pci_config_handle);
2210830d82f7Spl return (AACERR); /* no matched card found */
22117c478bd9Sstevel@tonic-gate }
22127c478bd9Sstevel@tonic-gate
2213f42c2f53Szhongyan gu - Sun Microsystems - Beijing China /*
2214f42c2f53Szhongyan gu - Sun Microsystems - Beijing China * Do the usual interrupt handler setup stuff.
2215f42c2f53Szhongyan gu - Sun Microsystems - Beijing China */
2216f42c2f53Szhongyan gu - Sun Microsystems - Beijing China static int
aac_register_intrs(struct aac_softstate * softs)2217f42c2f53Szhongyan gu - Sun Microsystems - Beijing China aac_register_intrs(struct aac_softstate *softs)
2218f42c2f53Szhongyan gu - Sun Microsystems - Beijing China {
2219f42c2f53Szhongyan gu - Sun Microsystems - Beijing China dev_info_t *dip;
2220f42c2f53Szhongyan gu - Sun Microsystems - Beijing China int intr_types;
2221f42c2f53Szhongyan gu - Sun Microsystems - Beijing China
2222f42c2f53Szhongyan gu - Sun Microsystems - Beijing China ASSERT(softs->devinfo_p);
2223f42c2f53Szhongyan gu - Sun Microsystems - Beijing China dip = softs->devinfo_p;
2224f42c2f53Szhongyan gu - Sun Microsystems - Beijing China
2225f42c2f53Szhongyan gu - Sun Microsystems - Beijing China /* Get the type of device intrrupts */
2226f42c2f53Szhongyan gu - Sun Microsystems - Beijing China if (ddi_intr_get_supported_types(dip, &intr_types) != DDI_SUCCESS) {
2227f42c2f53Szhongyan gu - Sun Microsystems - Beijing China AACDB_PRINT(softs, CE_WARN,
2228f42c2f53Szhongyan gu - Sun Microsystems - Beijing China "ddi_intr_get_supported_types() failed");
2229f42c2f53Szhongyan gu - Sun Microsystems - Beijing China return (AACERR);
2230f42c2f53Szhongyan gu - Sun Microsystems - Beijing China }
2231f42c2f53Szhongyan gu - Sun Microsystems - Beijing China AACDB_PRINT(softs, CE_NOTE,
2232f42c2f53Szhongyan gu - Sun Microsystems - Beijing China "ddi_intr_get_supported_types() ret: 0x%x", intr_types);
2233f42c2f53Szhongyan gu - Sun Microsystems - Beijing China
2234f42c2f53Szhongyan gu - Sun Microsystems - Beijing China /* Query interrupt, and alloc/init all needed struct */
2235f42c2f53Szhongyan gu - Sun Microsystems - Beijing China if (intr_types & DDI_INTR_TYPE_MSI) {
2236f42c2f53Szhongyan gu - Sun Microsystems - Beijing China if (aac_query_intrs(softs, DDI_INTR_TYPE_MSI)
2237f42c2f53Szhongyan gu - Sun Microsystems - Beijing China != DDI_SUCCESS) {
2238f42c2f53Szhongyan gu - Sun Microsystems - Beijing China AACDB_PRINT(softs, CE_WARN,
2239f42c2f53Szhongyan gu - Sun Microsystems - Beijing China "MSI interrupt query failed");
2240f42c2f53Szhongyan gu - Sun Microsystems - Beijing China return (AACERR);
2241f42c2f53Szhongyan gu - Sun Microsystems - Beijing China }
2242f42c2f53Szhongyan gu - Sun Microsystems - Beijing China softs->intr_type = DDI_INTR_TYPE_MSI;
2243f42c2f53Szhongyan gu - Sun Microsystems - Beijing China } else if (intr_types & DDI_INTR_TYPE_FIXED) {
2244f42c2f53Szhongyan gu - Sun Microsystems - Beijing China if (aac_query_intrs(softs, DDI_INTR_TYPE_FIXED)
2245f42c2f53Szhongyan gu - Sun Microsystems - Beijing China != DDI_SUCCESS) {
2246f42c2f53Szhongyan gu - Sun Microsystems - Beijing China AACDB_PRINT(softs, CE_WARN,
2247f42c2f53Szhongyan gu - Sun Microsystems - Beijing China "FIXED interrupt query failed");
2248f42c2f53Szhongyan gu - Sun Microsystems - Beijing China return (AACERR);
2249f42c2f53Szhongyan gu - Sun Microsystems - Beijing China }
2250f42c2f53Szhongyan gu - Sun Microsystems - Beijing China softs->intr_type = DDI_INTR_TYPE_FIXED;
2251f42c2f53Szhongyan gu - Sun Microsystems - Beijing China } else {
2252f42c2f53Szhongyan gu - Sun Microsystems - Beijing China AACDB_PRINT(softs, CE_WARN,
2253f42c2f53Szhongyan gu - Sun Microsystems - Beijing China "Device cannot suppport both FIXED and MSI interrupts");
2254f42c2f53Szhongyan gu - Sun Microsystems - Beijing China return (AACERR);
2255f42c2f53Szhongyan gu - Sun Microsystems - Beijing China }
2256f42c2f53Szhongyan gu - Sun Microsystems - Beijing China
2257f42c2f53Szhongyan gu - Sun Microsystems - Beijing China /* Connect interrupt handlers */
2258f42c2f53Szhongyan gu - Sun Microsystems - Beijing China if (aac_add_intrs(softs) != DDI_SUCCESS) {
2259f42c2f53Szhongyan gu - Sun Microsystems - Beijing China AACDB_PRINT(softs, CE_WARN,
2260f42c2f53Szhongyan gu - Sun Microsystems - Beijing China "Interrupt registration failed, intr type: %s",
2261f42c2f53Szhongyan gu - Sun Microsystems - Beijing China softs->intr_type == DDI_INTR_TYPE_MSI ? "MSI" : "FIXED");
2262f42c2f53Szhongyan gu - Sun Microsystems - Beijing China return (AACERR);
2263f42c2f53Szhongyan gu - Sun Microsystems - Beijing China }
2264f42c2f53Szhongyan gu - Sun Microsystems - Beijing China (void) aac_enable_intrs(softs);
2265f42c2f53Szhongyan gu - Sun Microsystems - Beijing China
2266f42c2f53Szhongyan gu - Sun Microsystems - Beijing China if (ddi_add_softintr(dip, DDI_SOFTINT_LOW, &softs->softint_id,
2267f42c2f53Szhongyan gu - Sun Microsystems - Beijing China NULL, NULL, aac_softintr, (caddr_t)softs) != DDI_SUCCESS) {
2268f42c2f53Szhongyan gu - Sun Microsystems - Beijing China AACDB_PRINT(softs, CE_WARN,
2269f42c2f53Szhongyan gu - Sun Microsystems - Beijing China "Can not setup soft interrupt handler!");
2270f42c2f53Szhongyan gu - Sun Microsystems - Beijing China aac_remove_intrs(softs);
2271f42c2f53Szhongyan gu - Sun Microsystems - Beijing China return (AACERR);
2272f42c2f53Szhongyan gu - Sun Microsystems - Beijing China }
2273f42c2f53Szhongyan gu - Sun Microsystems - Beijing China
2274f42c2f53Szhongyan gu - Sun Microsystems - Beijing China return (AACOK);
2275f42c2f53Szhongyan gu - Sun Microsystems - Beijing China }
2276f42c2f53Szhongyan gu - Sun Microsystems - Beijing China
2277f42c2f53Szhongyan gu - Sun Microsystems - Beijing China static void
aac_unregister_intrs(struct aac_softstate * softs)2278f42c2f53Szhongyan gu - Sun Microsystems - Beijing China aac_unregister_intrs(struct aac_softstate *softs)
2279f42c2f53Szhongyan gu - Sun Microsystems - Beijing China {
2280f42c2f53Szhongyan gu - Sun Microsystems - Beijing China aac_remove_intrs(softs);
2281f42c2f53Szhongyan gu - Sun Microsystems - Beijing China ddi_remove_softintr(softs->softint_id);
2282f42c2f53Szhongyan gu - Sun Microsystems - Beijing China }
2283f42c2f53Szhongyan gu - Sun Microsystems - Beijing China
2284830d82f7Spl /*
2285830d82f7Spl * Check the firmware to determine the features to support and the FIB
2286830d82f7Spl * parameters to use.
2287830d82f7Spl */
22887c478bd9Sstevel@tonic-gate static int
aac_check_firmware(struct aac_softstate * softs)2289830d82f7Spl aac_check_firmware(struct aac_softstate *softs)
22907c478bd9Sstevel@tonic-gate {
2291830d82f7Spl uint32_t options;
2292830d82f7Spl uint32_t atu_size;
2293830d82f7Spl ddi_acc_handle_t pci_handle;
229458bc78c7SXin Chen uint8_t *data;
2295830d82f7Spl uint32_t max_fibs;
2296830d82f7Spl uint32_t max_fib_size;
2297830d82f7Spl uint32_t sg_tablesize;
2298830d82f7Spl uint32_t max_sectors;
2299830d82f7Spl uint32_t status;
2300830d82f7Spl
2301c9ffe217SToomas Soome max_fibs = 0;
2302c9ffe217SToomas Soome max_sectors = 0;
2303c9ffe217SToomas Soome sg_tablesize = 0;
2304c9ffe217SToomas Soome
2305830d82f7Spl /* Get supported options */
2306c9487164Spl if ((aac_sync_mbcommand(softs, AAC_MONKER_GETINFO, 0, 0, 0, 0,
2307c9487164Spl &status)) != AACOK) {
2308c9487164Spl if (status != SRB_STATUS_INVALID_REQUEST) {
2309830d82f7Spl cmn_err(CE_CONT,
2310c9487164Spl "?Fatal error: request adapter info error");
2311830d82f7Spl return (AACERR);
2312830d82f7Spl }
2313830d82f7Spl options = 0;
2314830d82f7Spl atu_size = 0;
2315830d82f7Spl } else {
2316830d82f7Spl options = AAC_MAILBOX_GET(softs, 1);
2317830d82f7Spl atu_size = AAC_MAILBOX_GET(softs, 2);
2318830d82f7Spl }
23197c478bd9Sstevel@tonic-gate
2320382c8bcaSpl if (softs->state & AAC_STATE_RESET) {
2321830d82f7Spl if ((softs->support_opt == options) &&
2322c9487164Spl (softs->atu_size == atu_size))
2323830d82f7Spl return (AACOK);
2324830d82f7Spl
2325830d82f7Spl cmn_err(CE_WARN,
2326c9487164Spl "?Fatal error: firmware changed, system needs reboot");
2327830d82f7Spl return (AACERR);
23287c478bd9Sstevel@tonic-gate }
23297c478bd9Sstevel@tonic-gate
2330c9487164Spl /*
2331c9487164Spl * The following critical settings are initialized only once during
2332c9487164Spl * driver attachment.
2333c9487164Spl */
2334830d82f7Spl softs->support_opt = options;
2335830d82f7Spl softs->atu_size = atu_size;
2336830d82f7Spl
2337830d82f7Spl /* Process supported options */
2338830d82f7Spl if ((options & AAC_SUPPORTED_4GB_WINDOW) != 0 &&
2339c9487164Spl (softs->flags & AAC_FLAGS_NO4GB) == 0) {
23401cea6be9Sxc AACDB_PRINT(softs, CE_NOTE, "!Enable FIB map 4GB window");
2341830d82f7Spl softs->flags |= AAC_FLAGS_4GB_WINDOW;
2342382c8bcaSpl } else {
2343382c8bcaSpl /*
2344382c8bcaSpl * Quirk AAC_FLAGS_NO4GB is for FIB address and thus comm space
2345382c8bcaSpl * only. IO is handled by the DMA engine which does not suffer
2346382c8bcaSpl * from the ATU window programming workarounds necessary for
2347382c8bcaSpl * CPU copy operations.
2348382c8bcaSpl */
2349382c8bcaSpl softs->addr_dma_attr.dma_attr_addr_lo = 0x2000ull;
2350382c8bcaSpl softs->addr_dma_attr.dma_attr_addr_hi = 0x7fffffffull;
23517c478bd9Sstevel@tonic-gate }
2352830d82f7Spl
2353830d82f7Spl if ((options & AAC_SUPPORTED_SGMAP_HOST64) != 0) {
23541cea6be9Sxc AACDB_PRINT(softs, CE_NOTE, "!Enable SG map 64-bit address");
2355830d82f7Spl softs->buf_dma_attr.dma_attr_addr_hi = 0xffffffffffffffffull;
2356830d82f7Spl softs->buf_dma_attr.dma_attr_seg = 0xffffffffffffffffull;
2357830d82f7Spl softs->flags |= AAC_FLAGS_SG_64BIT;
2358830d82f7Spl }
2359830d82f7Spl
2360830d82f7Spl if (options & AAC_SUPPORTED_64BIT_ARRAYSIZE) {
2361830d82f7Spl softs->flags |= AAC_FLAGS_ARRAY_64BIT;
23621cea6be9Sxc AACDB_PRINT(softs, CE_NOTE, "!Enable 64-bit array size");
2363830d82f7Spl }
2364830d82f7Spl
236558bc78c7SXin Chen if (options & AAC_SUPPORTED_NONDASD) {
236658bc78c7SXin Chen if ((ddi_prop_lookup_string(DDI_DEV_T_ANY, softs->devinfo_p, 0,
236758bc78c7SXin Chen "nondasd-enable", (char **)&data) == DDI_SUCCESS)) {
236858bc78c7SXin Chen if (strcmp((char *)data, "yes") == 0) {
236958bc78c7SXin Chen AACDB_PRINT(softs, CE_NOTE,
237058bc78c7SXin Chen "!Enable Non-DASD access");
237158bc78c7SXin Chen softs->flags |= AAC_FLAGS_NONDASD;
237258bc78c7SXin Chen }
237358bc78c7SXin Chen ddi_prop_free(data);
237458bc78c7SXin Chen }
237558bc78c7SXin Chen }
237658bc78c7SXin Chen
2377830d82f7Spl /* Read preferred settings */
2378830d82f7Spl max_fib_size = 0;
2379830d82f7Spl if ((aac_sync_mbcommand(softs, AAC_MONKER_GETCOMMPREF,
2380c9487164Spl 0, 0, 0, 0, NULL)) == AACOK) {
2381830d82f7Spl options = AAC_MAILBOX_GET(softs, 1);
2382830d82f7Spl max_fib_size = (options & 0xffff);
2383830d82f7Spl max_sectors = (options >> 16) << 1;
2384830d82f7Spl options = AAC_MAILBOX_GET(softs, 2);
2385830d82f7Spl sg_tablesize = (options >> 16);
2386830d82f7Spl options = AAC_MAILBOX_GET(softs, 3);
2387830d82f7Spl max_fibs = (options & 0xffff);
2388830d82f7Spl }
2389830d82f7Spl
2390830d82f7Spl /* Enable new comm. and rawio at the same time */
2391830d82f7Spl if ((softs->support_opt & AAC_SUPPORTED_NEW_COMM) &&
2392c9487164Spl (max_fib_size != 0)) {
239358bc78c7SXin Chen /* read out and save PCI MBR */
2394830d82f7Spl if ((atu_size > softs->map_size) &&
2395c9487164Spl (ddi_regs_map_setup(softs->devinfo_p, 1,
2396837c1ac4SStephen Hanson (caddr_t *)&data, 0, atu_size, &softs->reg_attr,
2397c9487164Spl &pci_handle) == DDI_SUCCESS)) {
2398830d82f7Spl ddi_regs_map_free(&softs->pci_mem_handle);
2399830d82f7Spl softs->pci_mem_handle = pci_handle;
240058bc78c7SXin Chen softs->pci_mem_base_vaddr = data;
2401830d82f7Spl softs->map_size = atu_size;
2402830d82f7Spl }
2403830d82f7Spl if (atu_size == softs->map_size) {
2404830d82f7Spl softs->flags |= AAC_FLAGS_NEW_COMM;
24051cea6be9Sxc AACDB_PRINT(softs, CE_NOTE,
24061cea6be9Sxc "!Enable New Comm. interface");
2407830d82f7Spl }
2408830d82f7Spl }
2409830d82f7Spl
2410830d82f7Spl /* Set FIB parameters */
2411830d82f7Spl if (softs->flags & AAC_FLAGS_NEW_COMM) {
2412830d82f7Spl softs->aac_max_fibs = max_fibs;
2413830d82f7Spl softs->aac_max_fib_size = max_fib_size;
2414830d82f7Spl softs->aac_max_sectors = max_sectors;
2415830d82f7Spl softs->aac_sg_tablesize = sg_tablesize;
2416830d82f7Spl
2417830d82f7Spl softs->flags |= AAC_FLAGS_RAW_IO;
24181cea6be9Sxc AACDB_PRINT(softs, CE_NOTE, "!Enable RawIO");
2419830d82f7Spl } else {
2420830d82f7Spl softs->aac_max_fibs =
2421c9487164Spl (softs->flags & AAC_FLAGS_256FIBS) ? 256 : 512;
2422942c5e3cSpl softs->aac_max_fib_size = AAC_FIB_SIZE;
2423382c8bcaSpl softs->aac_max_sectors = 128; /* 64K */
2424382c8bcaSpl if (softs->flags & AAC_FLAGS_17SG)
2425382c8bcaSpl softs->aac_sg_tablesize = 17;
2426382c8bcaSpl else if (softs->flags & AAC_FLAGS_34SG)
2427382c8bcaSpl softs->aac_sg_tablesize = 34;
2428830d82f7Spl else if (softs->flags & AAC_FLAGS_SG_64BIT)
2429830d82f7Spl softs->aac_sg_tablesize = (AAC_FIB_DATASIZE -
2430c9487164Spl sizeof (struct aac_blockwrite64) +
2431c9487164Spl sizeof (struct aac_sg_entry64)) /
2432c9487164Spl sizeof (struct aac_sg_entry64);
2433830d82f7Spl else
2434830d82f7Spl softs->aac_sg_tablesize = (AAC_FIB_DATASIZE -
2435c9487164Spl sizeof (struct aac_blockwrite) +
2436c9487164Spl sizeof (struct aac_sg_entry)) /
2437c9487164Spl sizeof (struct aac_sg_entry);
2438830d82f7Spl }
2439830d82f7Spl
2440830d82f7Spl if ((softs->flags & AAC_FLAGS_RAW_IO) &&
2441c9487164Spl (softs->flags & AAC_FLAGS_ARRAY_64BIT)) {
2442830d82f7Spl softs->flags |= AAC_FLAGS_LBA_64BIT;
24431cea6be9Sxc AACDB_PRINT(softs, CE_NOTE, "!Enable 64-bit array");
2444830d82f7Spl }
2445830d82f7Spl softs->buf_dma_attr.dma_attr_sgllen = softs->aac_sg_tablesize;
2446830d82f7Spl softs->buf_dma_attr.dma_attr_maxxfer = softs->aac_max_sectors << 9;
2447382c8bcaSpl /*
2448382c8bcaSpl * 64K maximum segment size in scatter gather list is controlled by
2449382c8bcaSpl * the NEW_COMM bit in the adapter information. If not set, the card
2450382c8bcaSpl * can only accept a maximum of 64K. It is not recommended to permit
2451382c8bcaSpl * more than 128KB of total transfer size to the adapters because
2452382c8bcaSpl * performance is negatively impacted.
2453382c8bcaSpl *
2454382c8bcaSpl * For new comm, segment size equals max xfer size. For old comm,
2455382c8bcaSpl * we use 64K for both.
2456382c8bcaSpl */
2457382c8bcaSpl softs->buf_dma_attr.dma_attr_count_max =
2458382c8bcaSpl softs->buf_dma_attr.dma_attr_maxxfer - 1;
2459830d82f7Spl
246058bc78c7SXin Chen /* Setup FIB operations */
2461d7c5bf88Spl if (softs->flags & AAC_FLAGS_RAW_IO)
2462d7c5bf88Spl softs->aac_cmd_fib = aac_cmd_fib_rawio;
2463d7c5bf88Spl else if (softs->flags & AAC_FLAGS_SG_64BIT)
2464d7c5bf88Spl softs->aac_cmd_fib = aac_cmd_fib_brw64;
2465d7c5bf88Spl else
2466d7c5bf88Spl softs->aac_cmd_fib = aac_cmd_fib_brw;
2467942c5e3cSpl softs->aac_cmd_fib_scsi = (softs->flags & AAC_FLAGS_SG_64BIT) ? \
2468942c5e3cSpl aac_cmd_fib_scsi64 : aac_cmd_fib_scsi32;
2469d7c5bf88Spl
2470d7c5bf88Spl /* 64-bit LBA needs descriptor format sense data */
2471d7c5bf88Spl softs->slen = sizeof (struct scsi_arq_status);
2472d7c5bf88Spl if ((softs->flags & AAC_FLAGS_LBA_64BIT) &&
2473d7c5bf88Spl softs->slen < AAC_ARQ64_LENGTH)
2474d7c5bf88Spl softs->slen = AAC_ARQ64_LENGTH;
2475d7c5bf88Spl
24761cea6be9Sxc AACDB_PRINT(softs, CE_NOTE,
2477c9487164Spl "!max_fibs %d max_fibsize 0x%x max_sectors %d max_sg %d",
2478c9487164Spl softs->aac_max_fibs, softs->aac_max_fib_size,
2479c9487164Spl softs->aac_max_sectors, softs->aac_sg_tablesize);
2480830d82f7Spl
2481830d82f7Spl return (AACOK);
2482830d82f7Spl }
2483830d82f7Spl
2484942c5e3cSpl static void
aac_fsa_rev(struct aac_softstate * softs,struct FsaRev * fsarev0,struct FsaRev * fsarev1)2485942c5e3cSpl aac_fsa_rev(struct aac_softstate *softs, struct FsaRev *fsarev0,
2486942c5e3cSpl struct FsaRev *fsarev1)
2487942c5e3cSpl {
2488f42c2f53Szhongyan gu - Sun Microsystems - Beijing China ddi_acc_handle_t acc = softs->sync_ac.slotp->fib_acc_handle;
2489942c5e3cSpl
2490942c5e3cSpl AAC_GET_FIELD8(acc, fsarev1, fsarev0, external.comp.dash);
2491942c5e3cSpl AAC_GET_FIELD8(acc, fsarev1, fsarev0, external.comp.type);
2492942c5e3cSpl AAC_GET_FIELD8(acc, fsarev1, fsarev0, external.comp.minor);
2493942c5e3cSpl AAC_GET_FIELD8(acc, fsarev1, fsarev0, external.comp.major);
2494942c5e3cSpl AAC_GET_FIELD32(acc, fsarev1, fsarev0, buildNumber);
2495942c5e3cSpl }
2496942c5e3cSpl
2497d937e6ebSpl /*
2498d937e6ebSpl * The following function comes from Adaptec:
2499d937e6ebSpl *
2500d937e6ebSpl * Query adapter information and supplement adapter information
2501d937e6ebSpl */
2502d937e6ebSpl static int
aac_get_adapter_info(struct aac_softstate * softs,struct aac_adapter_info * ainfr,struct aac_supplement_adapter_info * sinfr)2503d937e6ebSpl aac_get_adapter_info(struct aac_softstate *softs,
2504942c5e3cSpl struct aac_adapter_info *ainfr, struct aac_supplement_adapter_info *sinfr)
2505d937e6ebSpl {
2506f42c2f53Szhongyan gu - Sun Microsystems - Beijing China struct aac_cmd *acp = &softs->sync_ac;
2507f42c2f53Szhongyan gu - Sun Microsystems - Beijing China ddi_acc_handle_t acc;
2508f42c2f53Szhongyan gu - Sun Microsystems - Beijing China struct aac_fib *fibp;
2509d937e6ebSpl struct aac_adapter_info *ainfp;
2510d937e6ebSpl struct aac_supplement_adapter_info *sinfp;
2511f42c2f53Szhongyan gu - Sun Microsystems - Beijing China int rval;
2512f42c2f53Szhongyan gu - Sun Microsystems - Beijing China
2513f42c2f53Szhongyan gu - Sun Microsystems - Beijing China (void) aac_sync_fib_slot_bind(softs, acp);
2514f42c2f53Szhongyan gu - Sun Microsystems - Beijing China acc = acp->slotp->fib_acc_handle;
2515f42c2f53Szhongyan gu - Sun Microsystems - Beijing China fibp = acp->slotp->fibp;
2516d937e6ebSpl
2517942c5e3cSpl ddi_put8(acc, &fibp->data[0], 0);
2518942c5e3cSpl if (aac_sync_fib(softs, RequestAdapterInfo,
25193fced439Szhongyan gu - Sun Microsystems - Beijing China AAC_FIB_SIZEOF(struct aac_adapter_info)) != AACOK) {
25201dd0a2dbSpl AACDB_PRINT(softs, CE_WARN, "RequestAdapterInfo failed");
2521f42c2f53Szhongyan gu - Sun Microsystems - Beijing China rval = AACERR;
2522f42c2f53Szhongyan gu - Sun Microsystems - Beijing China goto finish;
2523d937e6ebSpl }
2524c9487164Spl ainfp = (struct aac_adapter_info *)fibp->data;
2525d937e6ebSpl if (ainfr) {
2526942c5e3cSpl AAC_GET_FIELD32(acc, ainfr, ainfp, SupportedOptions);
2527942c5e3cSpl AAC_GET_FIELD32(acc, ainfr, ainfp, PlatformBase);
2528942c5e3cSpl AAC_GET_FIELD32(acc, ainfr, ainfp, CpuArchitecture);
2529942c5e3cSpl AAC_GET_FIELD32(acc, ainfr, ainfp, CpuVariant);
2530942c5e3cSpl AAC_GET_FIELD32(acc, ainfr, ainfp, ClockSpeed);
2531942c5e3cSpl AAC_GET_FIELD32(acc, ainfr, ainfp, ExecutionMem);
2532942c5e3cSpl AAC_GET_FIELD32(acc, ainfr, ainfp, BufferMem);
2533942c5e3cSpl AAC_GET_FIELD32(acc, ainfr, ainfp, TotalMem);
2534942c5e3cSpl aac_fsa_rev(softs, &ainfp->KernelRevision,
2535942c5e3cSpl &ainfr->KernelRevision);
2536942c5e3cSpl aac_fsa_rev(softs, &ainfp->MonitorRevision,
2537942c5e3cSpl &ainfr->MonitorRevision);
2538942c5e3cSpl aac_fsa_rev(softs, &ainfp->HardwareRevision,
2539942c5e3cSpl &ainfr->HardwareRevision);
2540942c5e3cSpl aac_fsa_rev(softs, &ainfp->BIOSRevision,
2541942c5e3cSpl &ainfr->BIOSRevision);
2542942c5e3cSpl AAC_GET_FIELD32(acc, ainfr, ainfp, ClusteringEnabled);
2543942c5e3cSpl AAC_GET_FIELD32(acc, ainfr, ainfp, ClusterChannelMask);
2544942c5e3cSpl AAC_GET_FIELD64(acc, ainfr, ainfp, SerialNumber);
2545942c5e3cSpl AAC_GET_FIELD32(acc, ainfr, ainfp, batteryPlatform);
2546942c5e3cSpl AAC_GET_FIELD32(acc, ainfr, ainfp, SupportedOptions);
2547942c5e3cSpl AAC_GET_FIELD32(acc, ainfr, ainfp, OemVariant);
2548d937e6ebSpl }
2549d937e6ebSpl if (sinfr) {
2550d937e6ebSpl if (!(softs->support_opt &
2551c9487164Spl AAC_SUPPORTED_SUPPLEMENT_ADAPTER_INFO)) {
25521dd0a2dbSpl AACDB_PRINT(softs, CE_WARN,
25531dd0a2dbSpl "SupplementAdapterInfo not supported");
2554f42c2f53Szhongyan gu - Sun Microsystems - Beijing China rval = AACERR;
2555f42c2f53Szhongyan gu - Sun Microsystems - Beijing China goto finish;
2556d937e6ebSpl }
2557942c5e3cSpl ddi_put8(acc, &fibp->data[0], 0);
2558942c5e3cSpl if (aac_sync_fib(softs, RequestSupplementAdapterInfo,
25593fced439Szhongyan gu - Sun Microsystems - Beijing China AAC_FIB_SIZEOF(struct aac_supplement_adapter_info))
25603fced439Szhongyan gu - Sun Microsystems - Beijing China != AACOK) {
25611dd0a2dbSpl AACDB_PRINT(softs, CE_WARN,
25621dd0a2dbSpl "RequestSupplementAdapterInfo failed");
2563f42c2f53Szhongyan gu - Sun Microsystems - Beijing China rval = AACERR;
2564f42c2f53Szhongyan gu - Sun Microsystems - Beijing China goto finish;
2565d937e6ebSpl }
2566c9487164Spl sinfp = (struct aac_supplement_adapter_info *)fibp->data;
2567942c5e3cSpl AAC_REP_GET_FIELD8(acc, sinfr, sinfp, AdapterTypeText[0], 17+1);
2568942c5e3cSpl AAC_REP_GET_FIELD8(acc, sinfr, sinfp, Pad[0], 2);
2569942c5e3cSpl AAC_GET_FIELD32(acc, sinfr, sinfp, FlashMemoryByteSize);
2570942c5e3cSpl AAC_GET_FIELD32(acc, sinfr, sinfp, FlashImageId);
2571942c5e3cSpl AAC_GET_FIELD32(acc, sinfr, sinfp, MaxNumberPorts);
2572942c5e3cSpl AAC_GET_FIELD32(acc, sinfr, sinfp, Version);
2573942c5e3cSpl AAC_GET_FIELD32(acc, sinfr, sinfp, FeatureBits);
2574942c5e3cSpl AAC_GET_FIELD8(acc, sinfr, sinfp, SlotNumber);
2575942c5e3cSpl AAC_REP_GET_FIELD8(acc, sinfr, sinfp, ReservedPad0[0], 3);
2576942c5e3cSpl AAC_REP_GET_FIELD8(acc, sinfr, sinfp, BuildDate[0], 12);
2577942c5e3cSpl AAC_GET_FIELD32(acc, sinfr, sinfp, CurrentNumberPorts);
2578942c5e3cSpl AAC_REP_GET_FIELD8(acc, sinfr, sinfp, VpdInfo,
2579942c5e3cSpl sizeof (struct vpd_info));
2580942c5e3cSpl aac_fsa_rev(softs, &sinfp->FlashFirmwareRevision,
2581942c5e3cSpl &sinfr->FlashFirmwareRevision);
2582942c5e3cSpl AAC_GET_FIELD32(acc, sinfr, sinfp, RaidTypeMorphOptions);
2583942c5e3cSpl aac_fsa_rev(softs, &sinfp->FlashFirmwareBootRevision,
2584942c5e3cSpl &sinfr->FlashFirmwareBootRevision);
2585942c5e3cSpl AAC_REP_GET_FIELD8(acc, sinfr, sinfp, MfgPcbaSerialNo,
2586942c5e3cSpl MFG_PCBA_SERIAL_NUMBER_WIDTH);
2587942c5e3cSpl AAC_REP_GET_FIELD8(acc, sinfr, sinfp, MfgWWNName[0],
2588942c5e3cSpl MFG_WWN_WIDTH);
2589b40e8a89Szhongyan gu - Sun Microsystems - Beijing China AAC_GET_FIELD32(acc, sinfr, sinfp, SupportedOptions2);
2590b40e8a89Szhongyan gu - Sun Microsystems - Beijing China AAC_GET_FIELD32(acc, sinfr, sinfp, ExpansionFlag);
2591b40e8a89Szhongyan gu - Sun Microsystems - Beijing China if (sinfr->ExpansionFlag == 1) {
2592b40e8a89Szhongyan gu - Sun Microsystems - Beijing China AAC_GET_FIELD32(acc, sinfr, sinfp, FeatureBits3);
2593b40e8a89Szhongyan gu - Sun Microsystems - Beijing China AAC_GET_FIELD32(acc, sinfr, sinfp,
2594b40e8a89Szhongyan gu - Sun Microsystems - Beijing China SupportedPerformanceMode);
2595b40e8a89Szhongyan gu - Sun Microsystems - Beijing China AAC_REP_GET_FIELD32(acc, sinfr, sinfp,
2596b40e8a89Szhongyan gu - Sun Microsystems - Beijing China ReservedGrowth[0], 80);
2597b40e8a89Szhongyan gu - Sun Microsystems - Beijing China }
2598d937e6ebSpl }
2599f42c2f53Szhongyan gu - Sun Microsystems - Beijing China rval = AACOK;
2600f42c2f53Szhongyan gu - Sun Microsystems - Beijing China finish:
2601f42c2f53Szhongyan gu - Sun Microsystems - Beijing China aac_sync_fib_slot_release(softs, acp);
2602f42c2f53Szhongyan gu - Sun Microsystems - Beijing China return (rval);
2603d937e6ebSpl }
2604d937e6ebSpl
260558bc78c7SXin Chen static int
aac_get_bus_info(struct aac_softstate * softs,uint32_t * bus_max,uint32_t * tgt_max)260658bc78c7SXin Chen aac_get_bus_info(struct aac_softstate *softs, uint32_t *bus_max,
260758bc78c7SXin Chen uint32_t *tgt_max)
260858bc78c7SXin Chen {
2609f42c2f53Szhongyan gu - Sun Microsystems - Beijing China struct aac_cmd *acp = &softs->sync_ac;
2610f42c2f53Szhongyan gu - Sun Microsystems - Beijing China ddi_acc_handle_t acc;
2611f42c2f53Szhongyan gu - Sun Microsystems - Beijing China struct aac_fib *fibp;
261258bc78c7SXin Chen struct aac_ctcfg *c_cmd;
261358bc78c7SXin Chen struct aac_ctcfg_resp *c_resp;
261458bc78c7SXin Chen uint32_t scsi_method_id;
261558bc78c7SXin Chen struct aac_bus_info *cmd;
261658bc78c7SXin Chen struct aac_bus_info_response *resp;
261758bc78c7SXin Chen int rval;
261858bc78c7SXin Chen
2619f42c2f53Szhongyan gu - Sun Microsystems - Beijing China (void) aac_sync_fib_slot_bind(softs, acp);
2620f42c2f53Szhongyan gu - Sun Microsystems - Beijing China acc = acp->slotp->fib_acc_handle;
2621f42c2f53Szhongyan gu - Sun Microsystems - Beijing China fibp = acp->slotp->fibp;
2622f42c2f53Szhongyan gu - Sun Microsystems - Beijing China
262358bc78c7SXin Chen /* Detect MethodId */
262458bc78c7SXin Chen c_cmd = (struct aac_ctcfg *)&fibp->data[0];
262558bc78c7SXin Chen ddi_put32(acc, &c_cmd->Command, VM_ContainerConfig);
262658bc78c7SXin Chen ddi_put32(acc, &c_cmd->cmd, CT_GET_SCSI_METHOD);
262758bc78c7SXin Chen ddi_put32(acc, &c_cmd->param, 0);
262858bc78c7SXin Chen rval = aac_sync_fib(softs, ContainerCommand,
262958bc78c7SXin Chen AAC_FIB_SIZEOF(struct aac_ctcfg));
263058bc78c7SXin Chen c_resp = (struct aac_ctcfg_resp *)&fibp->data[0];
263158bc78c7SXin Chen if (rval != AACOK || ddi_get32(acc, &c_resp->Status) != 0) {
263258bc78c7SXin Chen AACDB_PRINT(softs, CE_WARN,
263358bc78c7SXin Chen "VM_ContainerConfig command fail");
2634f42c2f53Szhongyan gu - Sun Microsystems - Beijing China rval = AACERR;
2635f42c2f53Szhongyan gu - Sun Microsystems - Beijing China goto finish;
263658bc78c7SXin Chen }
263758bc78c7SXin Chen scsi_method_id = ddi_get32(acc, &c_resp->param);
263858bc78c7SXin Chen
263958bc78c7SXin Chen /* Detect phys. bus count and max. target id first */
264058bc78c7SXin Chen cmd = (struct aac_bus_info *)&fibp->data[0];
264158bc78c7SXin Chen ddi_put32(acc, &cmd->Command, VM_Ioctl);
264258bc78c7SXin Chen ddi_put32(acc, &cmd->ObjType, FT_DRIVE); /* physical drive */
264358bc78c7SXin Chen ddi_put32(acc, &cmd->MethodId, scsi_method_id);
264458bc78c7SXin Chen ddi_put32(acc, &cmd->ObjectId, 0);
264558bc78c7SXin Chen ddi_put32(acc, &cmd->CtlCmd, GetBusInfo);
264658bc78c7SXin Chen /*
264758bc78c7SXin Chen * For VM_Ioctl, the firmware uses the Header.Size filled from the
264858bc78c7SXin Chen * driver as the size to be returned. Therefore the driver has to use
264958bc78c7SXin Chen * sizeof (struct aac_bus_info_response) because it is greater than
265058bc78c7SXin Chen * sizeof (struct aac_bus_info).
265158bc78c7SXin Chen */
265258bc78c7SXin Chen rval = aac_sync_fib(softs, ContainerCommand,
265358bc78c7SXin Chen AAC_FIB_SIZEOF(struct aac_bus_info_response));
265458bc78c7SXin Chen resp = (struct aac_bus_info_response *)cmd;
265558bc78c7SXin Chen
265658bc78c7SXin Chen /* Scan all coordinates with INQUIRY */
265758bc78c7SXin Chen if ((rval != AACOK) || (ddi_get32(acc, &resp->Status) != 0)) {
265858bc78c7SXin Chen AACDB_PRINT(softs, CE_WARN, "GetBusInfo command fail");
2659f42c2f53Szhongyan gu - Sun Microsystems - Beijing China rval = AACERR;
2660f42c2f53Szhongyan gu - Sun Microsystems - Beijing China goto finish;
266158bc78c7SXin Chen }
266258bc78c7SXin Chen *bus_max = ddi_get32(acc, &resp->BusCount);
266358bc78c7SXin Chen *tgt_max = ddi_get32(acc, &resp->TargetsPerBus);
2664f42c2f53Szhongyan gu - Sun Microsystems - Beijing China
2665f42c2f53Szhongyan gu - Sun Microsystems - Beijing China finish:
2666f42c2f53Szhongyan gu - Sun Microsystems - Beijing China aac_sync_fib_slot_release(softs, acp);
266758bc78c7SXin Chen return (AACOK);
266858bc78c7SXin Chen }
266958bc78c7SXin Chen
2670830d82f7Spl /*
2671830d82f7Spl * The following function comes from Adaptec:
2672830d82f7Spl *
2673830d82f7Spl * Routine to be called during initialization of communications with
2674830d82f7Spl * the adapter to handle possible adapter configuration issues. When
2675830d82f7Spl * the adapter first boots up, it examines attached drives, etc, and
2676830d82f7Spl * potentially comes up with a new or revised configuration (relative to
2677830d82f7Spl * what's stored in it's NVRAM). Additionally it may discover problems
2678830d82f7Spl * that make the current physical configuration unworkable (currently
2679830d82f7Spl * applicable only to cluster configuration issues).
2680830d82f7Spl *
2681830d82f7Spl * If there are no configuration issues or the issues are considered
2682830d82f7Spl * trival by the adapter, it will set it's configuration status to
2683830d82f7Spl * "FSACT_CONTINUE" and execute the "commit confiuguration" action
2684830d82f7Spl * automatically on it's own.
2685830d82f7Spl *
2686830d82f7Spl * However, if there are non-trivial issues, the adapter will set it's
2687830d82f7Spl * internal configuration status to "FSACT_PAUSE" or "FASCT_ABORT"
2688830d82f7Spl * and wait for some agent on the host to issue the "\ContainerCommand
2689830d82f7Spl * \VM_ContainerConfig\CT_COMMIT_CONFIG" FIB command to cause the
2690830d82f7Spl * adapter to commit the new/updated configuration and enable
2691830d82f7Spl * un-inhibited operation. The host agent should first issue the
2692830d82f7Spl * "\ContainerCommand\VM_ContainerConfig\CT_GET_CONFIG_STATUS" FIB
2693830d82f7Spl * command to obtain information about config issues detected by
2694830d82f7Spl * the adapter.
2695830d82f7Spl *
2696830d82f7Spl * Normally the adapter's PC BIOS will execute on the host following
2697830d82f7Spl * adapter poweron and reset and will be responsible for querring the
2698830d82f7Spl * adapter with CT_GET_CONFIG_STATUS and issuing the CT_COMMIT_CONFIG
2699830d82f7Spl * command if appropriate.
2700830d82f7Spl *
2701830d82f7Spl * However, with the introduction of IOP reset support, the adapter may
2702830d82f7Spl * boot up without the benefit of the adapter's PC BIOS host agent.
2703830d82f7Spl * This routine is intended to take care of these issues in situations
2704830d82f7Spl * where BIOS doesn't execute following adapter poweron or reset. The
2705830d82f7Spl * CT_COMMIT_CONFIG command is a no-op if it's already been issued, so
2706830d82f7Spl * there is no harm in doing this when it's already been done.
2707830d82f7Spl */
2708830d82f7Spl static int
aac_handle_adapter_config_issues(struct aac_softstate * softs)2709830d82f7Spl aac_handle_adapter_config_issues(struct aac_softstate *softs)
2710830d82f7Spl {
2711f42c2f53Szhongyan gu - Sun Microsystems - Beijing China struct aac_cmd *acp = &softs->sync_ac;
2712f42c2f53Szhongyan gu - Sun Microsystems - Beijing China ddi_acc_handle_t acc;
2713f42c2f53Szhongyan gu - Sun Microsystems - Beijing China struct aac_fib *fibp;
2714830d82f7Spl struct aac_Container *cmd;
2715c9487164Spl struct aac_Container_resp *resp;
2716830d82f7Spl struct aac_cf_status_header *cfg_sts_hdr;
2717942c5e3cSpl uint32_t resp_status;
2718942c5e3cSpl uint32_t ct_status;
2719830d82f7Spl uint32_t cfg_stat_action;
2720c9487164Spl int rval;
2721830d82f7Spl
2722f42c2f53Szhongyan gu - Sun Microsystems - Beijing China (void) aac_sync_fib_slot_bind(softs, acp);
2723f42c2f53Szhongyan gu - Sun Microsystems - Beijing China acc = acp->slotp->fib_acc_handle;
2724f42c2f53Szhongyan gu - Sun Microsystems - Beijing China fibp = acp->slotp->fibp;
2725f42c2f53Szhongyan gu - Sun Microsystems - Beijing China
2726c9487164Spl /* Get adapter config status */
2727c9487164Spl cmd = (struct aac_Container *)&fibp->data[0];
2728830d82f7Spl
2729382c8bcaSpl bzero(cmd, sizeof (*cmd) - CT_PACKET_SIZE);
2730942c5e3cSpl ddi_put32(acc, &cmd->Command, VM_ContainerConfig);
2731942c5e3cSpl ddi_put32(acc, &cmd->CTCommand.command, CT_GET_CONFIG_STATUS);
2732942c5e3cSpl ddi_put32(acc, &cmd->CTCommand.param[CNT_SIZE],
2733942c5e3cSpl sizeof (struct aac_cf_status_header));
2734942c5e3cSpl rval = aac_sync_fib(softs, ContainerCommand,
2735942c5e3cSpl AAC_FIB_SIZEOF(struct aac_Container));
2736c9487164Spl resp = (struct aac_Container_resp *)cmd;
2737c9487164Spl cfg_sts_hdr = (struct aac_cf_status_header *)resp->CTResponse.data;
2738c9487164Spl
2739942c5e3cSpl resp_status = ddi_get32(acc, &resp->Status);
2740942c5e3cSpl ct_status = ddi_get32(acc, &resp->CTResponse.param[0]);
2741942c5e3cSpl if ((rval == AACOK) && (resp_status == 0) && (ct_status == CT_OK)) {
2742942c5e3cSpl cfg_stat_action = ddi_get32(acc, &cfg_sts_hdr->action);
2743830d82f7Spl
2744c9487164Spl /* Commit configuration if it's reasonable to do so. */
2745830d82f7Spl if (cfg_stat_action <= CFACT_PAUSE) {
2746942c5e3cSpl bzero(cmd, sizeof (*cmd) - CT_PACKET_SIZE);
2747942c5e3cSpl ddi_put32(acc, &cmd->Command, VM_ContainerConfig);
2748942c5e3cSpl ddi_put32(acc, &cmd->CTCommand.command,
2749942c5e3cSpl CT_COMMIT_CONFIG);
2750942c5e3cSpl rval = aac_sync_fib(softs, ContainerCommand,
2751942c5e3cSpl AAC_FIB_SIZEOF(struct aac_Container));
2752942c5e3cSpl
2753942c5e3cSpl resp_status = ddi_get32(acc, &resp->Status);
2754942c5e3cSpl ct_status = ddi_get32(acc, &resp->CTResponse.param[0]);
2755942c5e3cSpl if ((rval == AACOK) && (resp_status == 0) &&
2756942c5e3cSpl (ct_status == CT_OK))
2757c9487164Spl /* Successful completion */
2758c9487164Spl rval = AACMPE_OK;
2759c9487164Spl else
2760c9487164Spl /* Auto-commit aborted due to error(s). */
2761c9487164Spl rval = AACMPE_COMMIT_CONFIG;
2762830d82f7Spl } else {
2763830d82f7Spl /*
2764830d82f7Spl * Auto-commit aborted due to adapter indicating
2765830d82f7Spl * configuration issue(s) too dangerous to auto-commit.
2766830d82f7Spl */
2767c9487164Spl rval = AACMPE_CONFIG_STATUS;
2768830d82f7Spl }
2769830d82f7Spl } else {
2770830d82f7Spl cmn_err(CE_WARN, "!Configuration issue, auto-commit aborted");
2771c9487164Spl rval = AACMPE_CONFIG_STATUS;
2772830d82f7Spl }
2773f42c2f53Szhongyan gu - Sun Microsystems - Beijing China
2774f42c2f53Szhongyan gu - Sun Microsystems - Beijing China aac_sync_fib_slot_release(softs, acp);
2775c9487164Spl return (rval);
2776830d82f7Spl }
2777830d82f7Spl
2778830d82f7Spl /*
2779830d82f7Spl * Hardware initialization and resource allocation
2780830d82f7Spl */
2781830d82f7Spl static int
aac_common_attach(struct aac_softstate * softs)2782830d82f7Spl aac_common_attach(struct aac_softstate *softs)
2783830d82f7Spl {
2784382c8bcaSpl uint32_t status;
2785830d82f7Spl int i;
27860749e8deSXin Chen - Sun Microsystems - Beijing China struct aac_supplement_adapter_info sinf;
2787830d82f7Spl
27881dd0a2dbSpl DBCALLED(softs, 1);
2789830d82f7Spl
2790d7c5bf88Spl /*
2791d7c5bf88Spl * Do a little check here to make sure there aren't any outstanding
2792d7c5bf88Spl * FIBs in the message queue. At this point there should not be and
2793d7c5bf88Spl * if there are they are probably left over from another instance of
2794d7c5bf88Spl * the driver like when the system crashes and the crash dump driver
2795d7c5bf88Spl * gets loaded.
2796d7c5bf88Spl */
2797d7c5bf88Spl while (AAC_OUTB_GET(softs) != 0xfffffffful)
2798d7c5bf88Spl ;
2799d7c5bf88Spl
2800830d82f7Spl /*
2801830d82f7Spl * Wait the card to complete booting up before do anything that
2802830d82f7Spl * attempts to communicate with it.
2803830d82f7Spl */
2804382c8bcaSpl status = AAC_FWSTATUS_GET(softs);
2805382c8bcaSpl if (status == AAC_SELF_TEST_FAILED || status == AAC_KERNEL_PANIC)
2806382c8bcaSpl goto error;
2807382c8bcaSpl i = AAC_FWUP_TIMEOUT * 1000; /* set timeout */
2808382c8bcaSpl AAC_BUSYWAIT(AAC_FWSTATUS_GET(softs) & AAC_KERNEL_UP_AND_RUNNING, i);
2809382c8bcaSpl if (i == 0) {
2810830d82f7Spl cmn_err(CE_CONT, "?Fatal error: controller not ready");
28117675db54Syw aac_fm_ereport(softs, DDI_FM_DEVICE_NO_RESPONSE);
28127675db54Syw ddi_fm_service_impact(softs->devinfo_p, DDI_SERVICE_LOST);
2813830d82f7Spl goto error;
2814830d82f7Spl }
2815830d82f7Spl
2816830d82f7Spl /* Read and set card supported options and settings */
28177675db54Syw if (aac_check_firmware(softs) == AACERR) {
28187675db54Syw aac_fm_ereport(softs, DDI_FM_DEVICE_NO_RESPONSE);
28197675db54Syw ddi_fm_service_impact(softs->devinfo_p, DDI_SERVICE_LOST);
2820830d82f7Spl goto error;
28217675db54Syw }
2822830d82f7Spl
2823f42c2f53Szhongyan gu - Sun Microsystems - Beijing China /* Add interrupt handlers */
2824f42c2f53Szhongyan gu - Sun Microsystems - Beijing China if (aac_register_intrs(softs) == AACERR) {
2825f42c2f53Szhongyan gu - Sun Microsystems - Beijing China cmn_err(CE_CONT,
2826f42c2f53Szhongyan gu - Sun Microsystems - Beijing China "?Fatal error: interrupts register failed");
2827f42c2f53Szhongyan gu - Sun Microsystems - Beijing China goto error;
2828f42c2f53Szhongyan gu - Sun Microsystems - Beijing China }
28297c478bd9Sstevel@tonic-gate
28307c478bd9Sstevel@tonic-gate /* Setup communication space with the card */
2831830d82f7Spl if (softs->comm_space_dma_handle == NULL) {
2832830d82f7Spl if (aac_alloc_comm_space(softs) != AACOK)
2833830d82f7Spl goto error;
2834830d82f7Spl }
28357c478bd9Sstevel@tonic-gate if (aac_setup_comm_space(softs) != AACOK) {
28367c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "?Setup communication space failed");
28377675db54Syw aac_fm_ereport(softs, DDI_FM_DEVICE_NO_RESPONSE);
28387675db54Syw ddi_fm_service_impact(softs->devinfo_p, DDI_SERVICE_LOST);
28397c478bd9Sstevel@tonic-gate goto error;
28407c478bd9Sstevel@tonic-gate }
28417c478bd9Sstevel@tonic-gate
28421dd0a2dbSpl #ifdef DEBUG
2843942c5e3cSpl if (aac_get_fw_debug_buffer(softs) != AACOK)
28441dd0a2dbSpl cmn_err(CE_CONT, "?firmware UART trace not supported");
28451dd0a2dbSpl #endif
28461dd0a2dbSpl
2847830d82f7Spl /* Allocate slots */
2848c9487164Spl if ((softs->total_slots == 0) && (aac_create_slots(softs) != AACOK)) {
2849830d82f7Spl cmn_err(CE_CONT, "?Fatal error: slots allocate failed");
2850830d82f7Spl goto error;
2851830d82f7Spl }
28521dd0a2dbSpl AACDB_PRINT(softs, CE_NOTE, "%d slots allocated", softs->total_slots);
2853830d82f7Spl
2854830d82f7Spl /* Allocate FIBs */
2855942c5e3cSpl if (softs->total_fibs < softs->total_slots) {
2856942c5e3cSpl aac_alloc_fibs(softs);
2857942c5e3cSpl if (softs->total_fibs == 0)
2858942c5e3cSpl goto error;
2859942c5e3cSpl AACDB_PRINT(softs, CE_NOTE, "%d fibs allocated",
2860942c5e3cSpl softs->total_fibs);
2861830d82f7Spl }
2862830d82f7Spl
2863f42c2f53Szhongyan gu - Sun Microsystems - Beijing China AAC_STATUS_CLR(softs, ~0); /* Clear out all interrupts */
2864f42c2f53Szhongyan gu - Sun Microsystems - Beijing China AAC_ENABLE_INTR(softs); /* Enable the interrupts we can handle */
2865f42c2f53Szhongyan gu - Sun Microsystems - Beijing China
28660749e8deSXin Chen - Sun Microsystems - Beijing China if (aac_get_adapter_info(softs, NULL, &sinf) == AACOK) {
28673fced439Szhongyan gu - Sun Microsystems - Beijing China softs->feature_bits = sinf.FeatureBits;
28683fced439Szhongyan gu - Sun Microsystems - Beijing China softs->support_opt2 = sinf.SupportedOptions2;
28693fced439Szhongyan gu - Sun Microsystems - Beijing China
28700749e8deSXin Chen - Sun Microsystems - Beijing China /* Get adapter names */
28710749e8deSXin Chen - Sun Microsystems - Beijing China if (CARD_IS_UNKNOWN(softs->card)) {
2872d937e6ebSpl char *p, *p0, *p1;
2873d937e6ebSpl
2874d937e6ebSpl /*
2875d937e6ebSpl * Now find the controller name in supp_adapter_info->
2876d937e6ebSpl * AdapterTypeText. Use the first word as the vendor
2877d937e6ebSpl * and the other words as the product name.
2878d937e6ebSpl */
28791dd0a2dbSpl AACDB_PRINT(softs, CE_NOTE, "sinf.AdapterTypeText = "
28801dd0a2dbSpl "\"%s\"", sinf.AdapterTypeText);
2881d937e6ebSpl p = sinf.AdapterTypeText;
2882d937e6ebSpl p0 = p1 = NULL;
2883d937e6ebSpl /* Skip heading spaces */
2884d937e6ebSpl while (*p && (*p == ' ' || *p == '\t'))
2885d937e6ebSpl p++;
2886d937e6ebSpl p0 = p;
2887d937e6ebSpl while (*p && (*p != ' ' && *p != '\t'))
2888d937e6ebSpl p++;
2889d937e6ebSpl /* Remove middle spaces */
2890d937e6ebSpl while (*p && (*p == ' ' || *p == '\t'))
2891d937e6ebSpl *p++ = 0;
2892d937e6ebSpl p1 = p;
2893d937e6ebSpl /* Remove trailing spaces */
2894d937e6ebSpl p = p1 + strlen(p1) - 1;
2895d937e6ebSpl while (p > p1 && (*p == ' ' || *p == '\t'))
2896d937e6ebSpl *p-- = 0;
2897d937e6ebSpl if (*p0 && *p1) {
2898d937e6ebSpl (void *)strncpy(softs->vendor_name, p0,
2899c9487164Spl AAC_VENDOR_LEN);
2900d937e6ebSpl (void *)strncpy(softs->product_name, p1,
2901c9487164Spl AAC_PRODUCT_LEN);
2902d937e6ebSpl } else {
2903d937e6ebSpl cmn_err(CE_WARN,
2904c9487164Spl "?adapter name mis-formatted\n");
2905d937e6ebSpl if (*p0)
2906d937e6ebSpl (void *)strncpy(softs->product_name,
2907c9487164Spl p0, AAC_PRODUCT_LEN);
2908d937e6ebSpl }
2909d937e6ebSpl }
29100749e8deSXin Chen - Sun Microsystems - Beijing China } else {
29110749e8deSXin Chen - Sun Microsystems - Beijing China cmn_err(CE_CONT, "?Query adapter information failed");
2912d937e6ebSpl }
2913d937e6ebSpl
29140749e8deSXin Chen - Sun Microsystems - Beijing China
29151cea6be9Sxc cmn_err(CE_NOTE,
29161cea6be9Sxc "!aac driver %d.%02d.%02d-%d, found card: " \
29171cea6be9Sxc "%s %s(pci0x%x.%x.%x.%x) at 0x%x",
29181cea6be9Sxc AAC_DRIVER_MAJOR_VERSION,
29191cea6be9Sxc AAC_DRIVER_MINOR_VERSION,
29201cea6be9Sxc AAC_DRIVER_BUGFIX_LEVEL,
29211cea6be9Sxc AAC_DRIVER_BUILD,
29221cea6be9Sxc softs->vendor_name, softs->product_name,
29231cea6be9Sxc softs->vendid, softs->devid, softs->subvendid, softs->subsysid,
29241cea6be9Sxc softs->pci_mem_base_paddr);
29251cea6be9Sxc
2926830d82f7Spl /* Perform acceptance of adapter-detected config changes if possible */
2927830d82f7Spl if (aac_handle_adapter_config_issues(softs) != AACMPE_OK) {
2928830d82f7Spl cmn_err(CE_CONT, "?Handle adapter config issues failed");
29297675db54Syw aac_fm_ereport(softs, DDI_FM_DEVICE_NO_RESPONSE);
29307675db54Syw ddi_fm_service_impact(softs->devinfo_p, DDI_SERVICE_LOST);
2931830d82f7Spl goto error;
2932830d82f7Spl }
2933830d82f7Spl
293458bc78c7SXin Chen /* Setup containers (logical devices) */
2935942c5e3cSpl if (aac_probe_containers(softs) != AACOK) {
29367c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "?Fatal error: get container info error");
29377c478bd9Sstevel@tonic-gate goto error;
29387c478bd9Sstevel@tonic-gate }
29397c478bd9Sstevel@tonic-gate
29403fced439Szhongyan gu - Sun Microsystems - Beijing China /* Check for JBOD support. Default disable */
29413fced439Szhongyan gu - Sun Microsystems - Beijing China char *data;
29423fced439Szhongyan gu - Sun Microsystems - Beijing China if (softs->feature_bits & AAC_FEATURE_SUPPORTED_JBOD) {
29433fced439Szhongyan gu - Sun Microsystems - Beijing China if ((ddi_prop_lookup_string(DDI_DEV_T_ANY, softs->devinfo_p,
29443fced439Szhongyan gu - Sun Microsystems - Beijing China 0, "jbod-enable", &data) == DDI_SUCCESS)) {
29453fced439Szhongyan gu - Sun Microsystems - Beijing China if (strcmp(data, "yes") == 0) {
29463fced439Szhongyan gu - Sun Microsystems - Beijing China AACDB_PRINT(softs, CE_NOTE,
29473fced439Szhongyan gu - Sun Microsystems - Beijing China "Enable JBOD access");
29483fced439Szhongyan gu - Sun Microsystems - Beijing China softs->flags |= AAC_FLAGS_JBOD;
29493fced439Szhongyan gu - Sun Microsystems - Beijing China }
29503fced439Szhongyan gu - Sun Microsystems - Beijing China ddi_prop_free(data);
29513fced439Szhongyan gu - Sun Microsystems - Beijing China }
29523fced439Szhongyan gu - Sun Microsystems - Beijing China }
29533fced439Szhongyan gu - Sun Microsystems - Beijing China
295458bc78c7SXin Chen /* Setup phys. devices */
29553fced439Szhongyan gu - Sun Microsystems - Beijing China if (softs->flags & (AAC_FLAGS_NONDASD | AAC_FLAGS_JBOD)) {
295658bc78c7SXin Chen uint32_t bus_max, tgt_max;
295758bc78c7SXin Chen uint32_t bus, tgt;
295858bc78c7SXin Chen int index;
295958bc78c7SXin Chen
296058bc78c7SXin Chen if (aac_get_bus_info(softs, &bus_max, &tgt_max) != AACOK) {
296158bc78c7SXin Chen cmn_err(CE_CONT, "?Fatal error: get bus info error");
296258bc78c7SXin Chen goto error;
296358bc78c7SXin Chen }
296458bc78c7SXin Chen AACDB_PRINT(softs, CE_NOTE, "bus_max=%d, tgt_max=%d",
296558bc78c7SXin Chen bus_max, tgt_max);
296658bc78c7SXin Chen if (bus_max != softs->bus_max || tgt_max != softs->tgt_max) {
296758bc78c7SXin Chen if (softs->state & AAC_STATE_RESET) {
296858bc78c7SXin Chen cmn_err(CE_WARN,
296958bc78c7SXin Chen "?Fatal error: bus map changed");
297058bc78c7SXin Chen goto error;
297158bc78c7SXin Chen }
297258bc78c7SXin Chen softs->bus_max = bus_max;
297358bc78c7SXin Chen softs->tgt_max = tgt_max;
297458bc78c7SXin Chen if (softs->nondasds) {
297558bc78c7SXin Chen kmem_free(softs->nondasds, AAC_MAX_PD(softs) * \
297658bc78c7SXin Chen sizeof (struct aac_nondasd));
297758bc78c7SXin Chen }
297858bc78c7SXin Chen softs->nondasds = kmem_zalloc(AAC_MAX_PD(softs) * \
297958bc78c7SXin Chen sizeof (struct aac_nondasd), KM_SLEEP);
298058bc78c7SXin Chen
298158bc78c7SXin Chen index = 0;
298258bc78c7SXin Chen for (bus = 0; bus < softs->bus_max; bus++) {
298358bc78c7SXin Chen for (tgt = 0; tgt < softs->tgt_max; tgt++) {
298458bc78c7SXin Chen struct aac_nondasd *dvp =
298558bc78c7SXin Chen &softs->nondasds[index++];
298658bc78c7SXin Chen dvp->dev.type = AAC_DEV_PD;
298758bc78c7SXin Chen dvp->bus = bus;
298858bc78c7SXin Chen dvp->tid = tgt;
298958bc78c7SXin Chen }
299058bc78c7SXin Chen }
299158bc78c7SXin Chen }
299258bc78c7SXin Chen }
299358bc78c7SXin Chen
29947675db54Syw /* Check dma & acc handles allocated in attach */
29957675db54Syw if (aac_check_dma_handle(softs->comm_space_dma_handle) != DDI_SUCCESS) {
29967675db54Syw ddi_fm_service_impact(softs->devinfo_p, DDI_SERVICE_LOST);
29977675db54Syw goto error;
29987675db54Syw }
29997675db54Syw
30007675db54Syw if (aac_check_acc_handle(softs->pci_mem_handle) != DDI_SUCCESS) {
30017675db54Syw ddi_fm_service_impact(softs->devinfo_p, DDI_SERVICE_LOST);
30027675db54Syw goto error;
30037675db54Syw }
30047675db54Syw
30057675db54Syw for (i = 0; i < softs->total_slots; i++) {
30067675db54Syw if (aac_check_dma_handle(softs->io_slot[i].fib_dma_handle) !=
30077675db54Syw DDI_SUCCESS) {
30087675db54Syw ddi_fm_service_impact(softs->devinfo_p,
30097675db54Syw DDI_SERVICE_LOST);
30107675db54Syw goto error;
30117675db54Syw }
30127675db54Syw }
30137675db54Syw
30147c478bd9Sstevel@tonic-gate return (AACOK);
30157c478bd9Sstevel@tonic-gate error:
3016382c8bcaSpl if (softs->state & AAC_STATE_RESET)
3017830d82f7Spl return (AACERR);
301858bc78c7SXin Chen if (softs->nondasds) {
301958bc78c7SXin Chen kmem_free(softs->nondasds, AAC_MAX_PD(softs) * \
302058bc78c7SXin Chen sizeof (struct aac_nondasd));
302158bc78c7SXin Chen softs->nondasds = NULL;
302258bc78c7SXin Chen }
3023d7c5bf88Spl if (softs->total_fibs > 0)
3024d7c5bf88Spl aac_destroy_fibs(softs);
3025830d82f7Spl if (softs->total_slots > 0)
3026830d82f7Spl aac_destroy_slots(softs);
3027830d82f7Spl if (softs->comm_space_dma_handle)
3028830d82f7Spl aac_free_comm_space(softs);
30297c478bd9Sstevel@tonic-gate return (AACERR);
30307c478bd9Sstevel@tonic-gate }
30317c478bd9Sstevel@tonic-gate
3032830d82f7Spl /*
3033830d82f7Spl * Hardware shutdown and resource release
3034830d82f7Spl */
3035830d82f7Spl static void
aac_common_detach(struct aac_softstate * softs)3036830d82f7Spl aac_common_detach(struct aac_softstate *softs)
3037830d82f7Spl {
30381dd0a2dbSpl DBCALLED(softs, 1);
3039830d82f7Spl
3040f42c2f53Szhongyan gu - Sun Microsystems - Beijing China aac_unregister_intrs(softs);
3041f42c2f53Szhongyan gu - Sun Microsystems - Beijing China
3042f42c2f53Szhongyan gu - Sun Microsystems - Beijing China mutex_enter(&softs->io_lock);
3043830d82f7Spl (void) aac_shutdown(softs);
3044830d82f7Spl
304558bc78c7SXin Chen if (softs->nondasds) {
304658bc78c7SXin Chen kmem_free(softs->nondasds, AAC_MAX_PD(softs) * \
304758bc78c7SXin Chen sizeof (struct aac_nondasd));
304858bc78c7SXin Chen softs->nondasds = NULL;
304958bc78c7SXin Chen }
3050d7c5bf88Spl aac_destroy_fibs(softs);
3051830d82f7Spl aac_destroy_slots(softs);
3052830d82f7Spl aac_free_comm_space(softs);
3053f42c2f53Szhongyan gu - Sun Microsystems - Beijing China mutex_exit(&softs->io_lock);
3054830d82f7Spl }
3055830d82f7Spl
3056830d82f7Spl /*
3057830d82f7Spl * Send a synchronous command to the controller and wait for a result.
3058830d82f7Spl * Indicate if the controller completed the command with an error status.
3059830d82f7Spl */
3060830d82f7Spl int
aac_sync_mbcommand(struct aac_softstate * softs,uint32_t cmd,uint32_t arg0,uint32_t arg1,uint32_t arg2,uint32_t arg3,uint32_t * statusp)30617c478bd9Sstevel@tonic-gate aac_sync_mbcommand(struct aac_softstate *softs, uint32_t cmd,
3062c9487164Spl uint32_t arg0, uint32_t arg1, uint32_t arg2, uint32_t arg3,
3063c9487164Spl uint32_t *statusp)
30647c478bd9Sstevel@tonic-gate {
3065382c8bcaSpl int timeout;
30667c478bd9Sstevel@tonic-gate uint32_t status;
30677c478bd9Sstevel@tonic-gate
3068830d82f7Spl if (statusp != NULL)
3069c9487164Spl *statusp = SRB_STATUS_SUCCESS;
3070830d82f7Spl
3071830d82f7Spl /* Fill in mailbox */
30727c478bd9Sstevel@tonic-gate AAC_MAILBOX_SET(softs, cmd, arg0, arg1, arg2, arg3);
30737c478bd9Sstevel@tonic-gate
3074830d82f7Spl /* Ensure the sync command doorbell flag is cleared */
30757c478bd9Sstevel@tonic-gate AAC_STATUS_CLR(softs, AAC_DB_SYNC_COMMAND);
30767c478bd9Sstevel@tonic-gate
3077830d82f7Spl /* Then set it to signal the adapter */
30787c478bd9Sstevel@tonic-gate AAC_NOTIFY(softs, AAC_DB_SYNC_COMMAND);
30797c478bd9Sstevel@tonic-gate
3080830d82f7Spl /* Spin waiting for the command to complete */
3081382c8bcaSpl timeout = AAC_IMMEDIATE_TIMEOUT * 1000;
3082382c8bcaSpl AAC_BUSYWAIT(AAC_STATUS_GET(softs) & AAC_DB_SYNC_COMMAND, timeout);
3083382c8bcaSpl if (!timeout) {
30841dd0a2dbSpl AACDB_PRINT(softs, CE_WARN,
3085c9487164Spl "Sync command timed out after %d seconds (0x%x)!",
30861dd0a2dbSpl AAC_IMMEDIATE_TIMEOUT, AAC_FWSTATUS_GET(softs));
3087830d82f7Spl return (AACERR);
30887c478bd9Sstevel@tonic-gate }
30897c478bd9Sstevel@tonic-gate
3090830d82f7Spl /* Clear the completion flag */
30917c478bd9Sstevel@tonic-gate AAC_STATUS_CLR(softs, AAC_DB_SYNC_COMMAND);
30927c478bd9Sstevel@tonic-gate
3093830d82f7Spl /* Get the command status */
30947c478bd9Sstevel@tonic-gate status = AAC_MAILBOX_GET(softs, 0);
30957c478bd9Sstevel@tonic-gate if (statusp != NULL)
30967c478bd9Sstevel@tonic-gate *statusp = status;
3097c9487164Spl if (status != SRB_STATUS_SUCCESS) {
30981dd0a2dbSpl AACDB_PRINT(softs, CE_WARN,
30991dd0a2dbSpl "Sync command fail: status = 0x%x", status);
3100830d82f7Spl return (AACERR);
3101830d82f7Spl }
3102830d82f7Spl
31037c478bd9Sstevel@tonic-gate return (AACOK);
31047c478bd9Sstevel@tonic-gate }
31057c478bd9Sstevel@tonic-gate
3106830d82f7Spl /*
3107830d82f7Spl * Send a synchronous FIB to the adapter and wait for its completion
3108830d82f7Spl */
31097c478bd9Sstevel@tonic-gate static int
aac_sync_fib(struct aac_softstate * softs,uint16_t cmd,uint16_t fibsize)3110942c5e3cSpl aac_sync_fib(struct aac_softstate *softs, uint16_t cmd, uint16_t fibsize)
31117c478bd9Sstevel@tonic-gate {
3112f42c2f53Szhongyan gu - Sun Microsystems - Beijing China struct aac_cmd *acp = &softs->sync_ac;
31137c478bd9Sstevel@tonic-gate
31141ee13a44SXinChen acp->flags = AAC_CMD_SYNC | AAC_CMD_IN_SYNC_SLOT;
31151ee13a44SXinChen if (softs->state & AAC_STATE_INTR)
31161ee13a44SXinChen acp->flags |= AAC_CMD_NO_CB;
31171ee13a44SXinChen else
31181ee13a44SXinChen acp->flags |= AAC_CMD_NO_INTR;
31191ee13a44SXinChen
3120f42c2f53Szhongyan gu - Sun Microsystems - Beijing China acp->ac_comp = aac_sync_complete;
3121f42c2f53Szhongyan gu - Sun Microsystems - Beijing China acp->timeout = AAC_SYNC_TIMEOUT;
3122f42c2f53Szhongyan gu - Sun Microsystems - Beijing China acp->fib_size = fibsize;
31231ee13a44SXinChen
3124942c5e3cSpl /*
3125f42c2f53Szhongyan gu - Sun Microsystems - Beijing China * Only need to setup sync fib header, caller should have init
3126f42c2f53Szhongyan gu - Sun Microsystems - Beijing China * fib data
3127942c5e3cSpl */
3128f42c2f53Szhongyan gu - Sun Microsystems - Beijing China aac_cmd_fib_header(softs, acp, cmd);
312958bc78c7SXin Chen
31301ee13a44SXinChen (void) ddi_dma_sync(acp->slotp->fib_dma_handle, 0, fibsize,
31311ee13a44SXinChen DDI_DMA_SYNC_FORDEV);
3132830d82f7Spl
31331ee13a44SXinChen aac_start_io(softs, acp);
31347675db54Syw
31351ee13a44SXinChen if (softs->state & AAC_STATE_INTR)
31361ee13a44SXinChen return (aac_do_sync_io(softs, acp));
31371ee13a44SXinChen else
31381ee13a44SXinChen return (aac_do_poll_io(softs, acp));
31397c478bd9Sstevel@tonic-gate }
31407c478bd9Sstevel@tonic-gate
3141382c8bcaSpl static void
aac_cmd_initq(struct aac_cmd_queue * q)3142382c8bcaSpl aac_cmd_initq(struct aac_cmd_queue *q)
3143382c8bcaSpl {
3144382c8bcaSpl q->q_head = NULL;
3145382c8bcaSpl q->q_tail = (struct aac_cmd *)&q->q_head;
3146382c8bcaSpl }
3147382c8bcaSpl
3148830d82f7Spl /*
3149c9487164Spl * Remove a cmd from the head of q
3150830d82f7Spl */
31517c478bd9Sstevel@tonic-gate static struct aac_cmd *
aac_cmd_dequeue(struct aac_cmd_queue * q)31527c478bd9Sstevel@tonic-gate aac_cmd_dequeue(struct aac_cmd_queue *q)
31537c478bd9Sstevel@tonic-gate {
3154382c8bcaSpl struct aac_cmd *acp;
3155382c8bcaSpl
3156382c8bcaSpl _NOTE(ASSUMING_PROTECTED(*q))
3157c9487164Spl
3158382c8bcaSpl if ((acp = q->q_head) != NULL) {
3159382c8bcaSpl if ((q->q_head = acp->next) != NULL)
3160382c8bcaSpl acp->next = NULL;
3161382c8bcaSpl else
3162382c8bcaSpl q->q_tail = (struct aac_cmd *)&q->q_head;
3163382c8bcaSpl acp->prev = NULL;
31647c478bd9Sstevel@tonic-gate }
3165382c8bcaSpl return (acp);
31667c478bd9Sstevel@tonic-gate }
31677c478bd9Sstevel@tonic-gate
3168830d82f7Spl /*
3169830d82f7Spl * Add a cmd to the tail of q
3170830d82f7Spl */
31717c478bd9Sstevel@tonic-gate static void
aac_cmd_enqueue(struct aac_cmd_queue * q,struct aac_cmd * acp)3172c9487164Spl aac_cmd_enqueue(struct aac_cmd_queue *q, struct aac_cmd *acp)
31737c478bd9Sstevel@tonic-gate {
3174382c8bcaSpl ASSERT(acp->next == NULL);
3175382c8bcaSpl acp->prev = q->q_tail;
3176382c8bcaSpl q->q_tail->next = acp;
3177c9487164Spl q->q_tail = acp;
3178382c8bcaSpl }
3179382c8bcaSpl
3180382c8bcaSpl /*
3181382c8bcaSpl * Remove the cmd ac from q
3182382c8bcaSpl */
3183382c8bcaSpl static void
aac_cmd_delete(struct aac_cmd_queue * q,struct aac_cmd * acp)3184382c8bcaSpl aac_cmd_delete(struct aac_cmd_queue *q, struct aac_cmd *acp)
3185382c8bcaSpl {
3186382c8bcaSpl if (acp->prev) {
3187382c8bcaSpl if ((acp->prev->next = acp->next) != NULL) {
3188382c8bcaSpl acp->next->prev = acp->prev;
3189382c8bcaSpl acp->next = NULL;
3190382c8bcaSpl } else {
3191382c8bcaSpl q->q_tail = acp->prev;
3192382c8bcaSpl }
3193382c8bcaSpl acp->prev = NULL;
3194382c8bcaSpl }
3195382c8bcaSpl /* ac is not in the queue */
31967c478bd9Sstevel@tonic-gate }
31977c478bd9Sstevel@tonic-gate
3198830d82f7Spl /*
3199830d82f7Spl * Atomically insert an entry into the nominated queue, returns 0 on success or
3200830d82f7Spl * AACERR if the queue is full.
3201830d82f7Spl *
3202830d82f7Spl * Note: it would be more efficient to defer notifying the controller in
3203830d82f7Spl * the case where we may be inserting several entries in rapid succession,
3204830d82f7Spl * but implementing this usefully may be difficult (it would involve a
3205830d82f7Spl * separate queue/notify interface).
3206830d82f7Spl */
32077c478bd9Sstevel@tonic-gate static int
aac_fib_enqueue(struct aac_softstate * softs,int queue,uint32_t fib_addr,uint32_t fib_size)3208d7c5bf88Spl aac_fib_enqueue(struct aac_softstate *softs, int queue, uint32_t fib_addr,
3209d7c5bf88Spl uint32_t fib_size)
32107c478bd9Sstevel@tonic-gate {
3211942c5e3cSpl ddi_dma_handle_t dma = softs->comm_space_dma_handle;
3212942c5e3cSpl ddi_acc_handle_t acc = softs->comm_space_acc_handle;
32137c478bd9Sstevel@tonic-gate uint32_t pi, ci;
32147c478bd9Sstevel@tonic-gate
32151dd0a2dbSpl DBCALLED(softs, 2);
32167c478bd9Sstevel@tonic-gate
3217d7c5bf88Spl ASSERT(queue == AAC_ADAP_NORM_CMD_Q || queue == AAC_ADAP_NORM_RESP_Q);
32187c478bd9Sstevel@tonic-gate
3219830d82f7Spl /* Get the producer/consumer indices */
3220a74f7440Spl (void) ddi_dma_sync(dma, (uintptr_t)softs->qtablep->qt_qindex[queue] - \
3221a74f7440Spl (uintptr_t)softs->comm_space, sizeof (uint32_t) * 2,
32227675db54Syw DDI_DMA_SYNC_FORCPU);
3223942c5e3cSpl if (aac_check_dma_handle(dma) != DDI_SUCCESS) {
32247675db54Syw ddi_fm_service_impact(softs->devinfo_p, DDI_SERVICE_UNAFFECTED);
32257675db54Syw return (AACERR);
32267675db54Syw }
32277675db54Syw
3228942c5e3cSpl pi = ddi_get32(acc,
3229942c5e3cSpl &softs->qtablep->qt_qindex[queue][AAC_PRODUCER_INDEX]);
3230942c5e3cSpl ci = ddi_get32(acc,
3231942c5e3cSpl &softs->qtablep->qt_qindex[queue][AAC_CONSUMER_INDEX]);
3232830d82f7Spl
3233830d82f7Spl /*
3234830d82f7Spl * Wrap the queue first before we check the queue to see
3235830d82f7Spl * if it is full
3236830d82f7Spl */
3237830d82f7Spl if (pi >= aac_qinfo[queue].size)
3238830d82f7Spl pi = 0;
3239830d82f7Spl
3240830d82f7Spl /* XXX queue full */
3241382c8bcaSpl if ((pi + 1) == ci)
3242830d82f7Spl return (AACERR);
3243830d82f7Spl
3244830d82f7Spl /* Fill in queue entry */
3245942c5e3cSpl ddi_put32(acc, &((softs->qentries[queue] + pi)->aq_fib_size), fib_size);
3246942c5e3cSpl ddi_put32(acc, &((softs->qentries[queue] + pi)->aq_fib_addr), fib_addr);
3247a74f7440Spl (void) ddi_dma_sync(dma, (uintptr_t)(softs->qentries[queue] + pi) - \
3248a74f7440Spl (uintptr_t)softs->comm_space, sizeof (struct aac_queue_entry),
3249942c5e3cSpl DDI_DMA_SYNC_FORDEV);
3250830d82f7Spl
3251830d82f7Spl /* Update producer index */
3252942c5e3cSpl ddi_put32(acc, &softs->qtablep->qt_qindex[queue][AAC_PRODUCER_INDEX],
3253942c5e3cSpl pi + 1);
3254942c5e3cSpl (void) ddi_dma_sync(dma,
3255a74f7440Spl (uintptr_t)&softs->qtablep->qt_qindex[queue][AAC_PRODUCER_INDEX] - \
3256a74f7440Spl (uintptr_t)softs->comm_space, sizeof (uint32_t),
32577675db54Syw DDI_DMA_SYNC_FORDEV);
3258830d82f7Spl
3259830d82f7Spl if (aac_qinfo[queue].notify != 0)
3260830d82f7Spl AAC_NOTIFY(softs, aac_qinfo[queue].notify);
3261830d82f7Spl return (AACOK);
3262830d82f7Spl }
3263830d82f7Spl
3264830d82f7Spl /*
3265830d82f7Spl * Atomically remove one entry from the nominated queue, returns 0 on
3266830d82f7Spl * success or AACERR if the queue is empty.
3267830d82f7Spl */
3268830d82f7Spl static int
aac_fib_dequeue(struct aac_softstate * softs,int queue,int * idxp)3269d7c5bf88Spl aac_fib_dequeue(struct aac_softstate *softs, int queue, int *idxp)
3270830d82f7Spl {
3271942c5e3cSpl ddi_acc_handle_t acc = softs->comm_space_acc_handle;
3272942c5e3cSpl ddi_dma_handle_t dma = softs->comm_space_dma_handle;
3273d7c5bf88Spl uint32_t pi, ci;
3274d7c5bf88Spl int unfull = 0;
3275830d82f7Spl
32761dd0a2dbSpl DBCALLED(softs, 2);
32777c478bd9Sstevel@tonic-gate
3278d7c5bf88Spl ASSERT(idxp);
3279d7c5bf88Spl
3280830d82f7Spl /* Get the producer/consumer indices */
3281a74f7440Spl (void) ddi_dma_sync(dma, (uintptr_t)softs->qtablep->qt_qindex[queue] - \
3282a74f7440Spl (uintptr_t)softs->comm_space, sizeof (uint32_t) * 2,
32837675db54Syw DDI_DMA_SYNC_FORCPU);
3284942c5e3cSpl pi = ddi_get32(acc,
3285942c5e3cSpl &softs->qtablep->qt_qindex[queue][AAC_PRODUCER_INDEX]);
3286942c5e3cSpl ci = ddi_get32(acc,
3287942c5e3cSpl &softs->qtablep->qt_qindex[queue][AAC_CONSUMER_INDEX]);
32887c478bd9Sstevel@tonic-gate
3289830d82f7Spl /* Check for queue empty */
3290382c8bcaSpl if (ci == pi)
3291382c8bcaSpl return (AACERR);
32927c478bd9Sstevel@tonic-gate
3293830d82f7Spl if (pi >= aac_qinfo[queue].size)
3294830d82f7Spl pi = 0;
3295382c8bcaSpl
3296830d82f7Spl /* Check for queue full */
32977c478bd9Sstevel@tonic-gate if (ci == pi + 1)
32987c478bd9Sstevel@tonic-gate unfull = 1;
32997c478bd9Sstevel@tonic-gate
33007c478bd9Sstevel@tonic-gate /*
3301830d82f7Spl * The controller does not wrap the queue,
33027c478bd9Sstevel@tonic-gate * so we have to do it by ourselves
33037c478bd9Sstevel@tonic-gate */
33047c478bd9Sstevel@tonic-gate if (ci >= aac_qinfo[queue].size)
33057c478bd9Sstevel@tonic-gate ci = 0;
33067c478bd9Sstevel@tonic-gate
3307830d82f7Spl /* Fetch the entry */
3308a74f7440Spl (void) ddi_dma_sync(dma, (uintptr_t)(softs->qentries[queue] + pi) - \
3309a74f7440Spl (uintptr_t)softs->comm_space, sizeof (struct aac_queue_entry),
33107675db54Syw DDI_DMA_SYNC_FORCPU);
3311942c5e3cSpl if (aac_check_dma_handle(dma) != DDI_SUCCESS) {
33127675db54Syw ddi_fm_service_impact(softs->devinfo_p, DDI_SERVICE_UNAFFECTED);
3313382c8bcaSpl return (AACERR);
33147675db54Syw }
33157675db54Syw
3316830d82f7Spl switch (queue) {
3317d7c5bf88Spl case AAC_HOST_NORM_RESP_Q:
3318d7c5bf88Spl case AAC_HOST_HIGH_RESP_Q:
3319942c5e3cSpl *idxp = ddi_get32(acc,
3320942c5e3cSpl &(softs->qentries[queue] + ci)->aq_fib_addr);
3321d7c5bf88Spl break;
3322d7c5bf88Spl
3323830d82f7Spl case AAC_HOST_NORM_CMD_Q:
3324830d82f7Spl case AAC_HOST_HIGH_CMD_Q:
3325942c5e3cSpl *idxp = ddi_get32(acc,
3326942c5e3cSpl &(softs->qentries[queue] + ci)->aq_fib_addr) / AAC_FIB_SIZE;
3327830d82f7Spl break;
3328830d82f7Spl
3329830d82f7Spl default:
3330830d82f7Spl cmn_err(CE_NOTE, "!Invalid queue in aac_fib_dequeue()");
3331382c8bcaSpl return (AACERR);
3332830d82f7Spl }
33337c478bd9Sstevel@tonic-gate
3334830d82f7Spl /* Update consumer index */
3335942c5e3cSpl ddi_put32(acc, &softs->qtablep->qt_qindex[queue][AAC_CONSUMER_INDEX],
3336942c5e3cSpl ci + 1);
3337942c5e3cSpl (void) ddi_dma_sync(dma,
3338a74f7440Spl (uintptr_t)&softs->qtablep->qt_qindex[queue][AAC_CONSUMER_INDEX] - \
3339a74f7440Spl (uintptr_t)softs->comm_space, sizeof (uint32_t),
33407675db54Syw DDI_DMA_SYNC_FORDEV);
3341382c8bcaSpl
3342830d82f7Spl if (unfull && aac_qinfo[queue].notify != 0)
3343830d82f7Spl AAC_NOTIFY(softs, aac_qinfo[queue].notify);
3344382c8bcaSpl return (AACOK);
3345830d82f7Spl }
3346830d82f7Spl
3347830d82f7Spl static struct aac_mntinforesp *
aac_get_mntinfo(struct aac_softstate * softs,int cid)3348f42c2f53Szhongyan gu - Sun Microsystems - Beijing China aac_get_mntinfo(struct aac_softstate *softs, int cid)
3349830d82f7Spl {
3350f42c2f53Szhongyan gu - Sun Microsystems - Beijing China ddi_acc_handle_t acc = softs->sync_ac.slotp->fib_acc_handle;
3351f42c2f53Szhongyan gu - Sun Microsystems - Beijing China struct aac_fib *fibp = softs->sync_ac.slotp->fibp;
3352942c5e3cSpl struct aac_mntinfo *mi = (struct aac_mntinfo *)&fibp->data[0];
33537675db54Syw struct aac_mntinforesp *mir;
3354830d82f7Spl
3355942c5e3cSpl ddi_put32(acc, &mi->Command, /* Use 64-bit LBA if enabled */
3356c9487164Spl (softs->flags & AAC_FLAGS_LBA_64BIT) ?
3357942c5e3cSpl VM_NameServe64 : VM_NameServe);
3358942c5e3cSpl ddi_put32(acc, &mi->MntType, FT_FILESYS);
3359942c5e3cSpl ddi_put32(acc, &mi->MntCount, cid);
3360830d82f7Spl
3361942c5e3cSpl if (aac_sync_fib(softs, ContainerCommand,
3362942c5e3cSpl AAC_FIB_SIZEOF(struct aac_mntinfo)) == AACERR) {
33631dd0a2dbSpl AACDB_PRINT(softs, CE_WARN, "Error probe container %d", cid);
3364830d82f7Spl return (NULL);
3365830d82f7Spl }
3366830d82f7Spl
33677675db54Syw mir = (struct aac_mntinforesp *)&fibp->data[0];
3368942c5e3cSpl if (ddi_get32(acc, &mir->Status) == ST_OK)
33697675db54Syw return (mir);
33707675db54Syw return (NULL);
3371830d82f7Spl }
33727c478bd9Sstevel@tonic-gate
3373382c8bcaSpl static int
aac_get_container_count(struct aac_softstate * softs,int * count)3374942c5e3cSpl aac_get_container_count(struct aac_softstate *softs, int *count)
3375830d82f7Spl {
3376f42c2f53Szhongyan gu - Sun Microsystems - Beijing China ddi_acc_handle_t acc;
3377942c5e3cSpl struct aac_mntinforesp *mir;
3378f42c2f53Szhongyan gu - Sun Microsystems - Beijing China int rval;
3379830d82f7Spl
3380f42c2f53Szhongyan gu - Sun Microsystems - Beijing China (void) aac_sync_fib_slot_bind(softs, &softs->sync_ac);
3381f42c2f53Szhongyan gu - Sun Microsystems - Beijing China acc = softs->sync_ac.slotp->fib_acc_handle;
3382f42c2f53Szhongyan gu - Sun Microsystems - Beijing China
3383f42c2f53Szhongyan gu - Sun Microsystems - Beijing China if ((mir = aac_get_mntinfo(softs, 0)) == NULL) {
3384f42c2f53Szhongyan gu - Sun Microsystems - Beijing China rval = AACERR;
3385f42c2f53Szhongyan gu - Sun Microsystems - Beijing China goto finish;
3386f42c2f53Szhongyan gu - Sun Microsystems - Beijing China }
3387942c5e3cSpl *count = ddi_get32(acc, &mir->MntRespCount);
3388942c5e3cSpl if (*count > AAC_MAX_LD) {
3389942c5e3cSpl AACDB_PRINT(softs, CE_CONT,
3390942c5e3cSpl "container count(%d) > AAC_MAX_LD", *count);
3391f42c2f53Szhongyan gu - Sun Microsystems - Beijing China rval = AACERR;
3392f42c2f53Szhongyan gu - Sun Microsystems - Beijing China goto finish;
3393942c5e3cSpl }
3394f42c2f53Szhongyan gu - Sun Microsystems - Beijing China rval = AACOK;
3395f42c2f53Szhongyan gu - Sun Microsystems - Beijing China
3396f42c2f53Szhongyan gu - Sun Microsystems - Beijing China finish:
3397f42c2f53Szhongyan gu - Sun Microsystems - Beijing China aac_sync_fib_slot_release(softs, &softs->sync_ac);
3398f42c2f53Szhongyan gu - Sun Microsystems - Beijing China return (rval);
3399830d82f7Spl }
3400830d82f7Spl
3401942c5e3cSpl static int
aac_get_container_uid(struct aac_softstate * softs,uint32_t cid,uint32_t * uid)3402942c5e3cSpl aac_get_container_uid(struct aac_softstate *softs, uint32_t cid, uint32_t *uid)
3403830d82f7Spl {
3404f42c2f53Szhongyan gu - Sun Microsystems - Beijing China ddi_acc_handle_t acc = softs->sync_ac.slotp->fib_acc_handle;
3405942c5e3cSpl struct aac_Container *ct = (struct aac_Container *) \
3406f42c2f53Szhongyan gu - Sun Microsystems - Beijing China &softs->sync_ac.slotp->fibp->data[0];
3407382c8bcaSpl
3408942c5e3cSpl bzero(ct, sizeof (*ct) - CT_PACKET_SIZE);
3409942c5e3cSpl ddi_put32(acc, &ct->Command, VM_ContainerConfig);
3410942c5e3cSpl ddi_put32(acc, &ct->CTCommand.command, CT_CID_TO_32BITS_UID);
3411942c5e3cSpl ddi_put32(acc, &ct->CTCommand.param[0], cid);
3412942c5e3cSpl
3413942c5e3cSpl if (aac_sync_fib(softs, ContainerCommand,
3414942c5e3cSpl AAC_FIB_SIZEOF(struct aac_Container)) == AACERR)
3415942c5e3cSpl return (AACERR);
3416942c5e3cSpl if (ddi_get32(acc, &ct->CTCommand.param[0]) != CT_OK)
3417942c5e3cSpl return (AACERR);
3418942c5e3cSpl
3419942c5e3cSpl *uid = ddi_get32(acc, &ct->CTCommand.param[1]);
3420942c5e3cSpl return (AACOK);
34217c478bd9Sstevel@tonic-gate }
34227c478bd9Sstevel@tonic-gate
3423f42c2f53Szhongyan gu - Sun Microsystems - Beijing China /*
3424f42c2f53Szhongyan gu - Sun Microsystems - Beijing China * Request information of the container cid
3425f42c2f53Szhongyan gu - Sun Microsystems - Beijing China */
3426f42c2f53Szhongyan gu - Sun Microsystems - Beijing China static struct aac_mntinforesp *
aac_get_container_info(struct aac_softstate * softs,int cid)3427f42c2f53Szhongyan gu - Sun Microsystems - Beijing China aac_get_container_info(struct aac_softstate *softs, int cid)
3428f42c2f53Szhongyan gu - Sun Microsystems - Beijing China {
3429f42c2f53Szhongyan gu - Sun Microsystems - Beijing China ddi_acc_handle_t acc = softs->sync_ac.slotp->fib_acc_handle;
3430f42c2f53Szhongyan gu - Sun Microsystems - Beijing China struct aac_mntinforesp *mir;
3431f42c2f53Szhongyan gu - Sun Microsystems - Beijing China int rval_uid;
3432f42c2f53Szhongyan gu - Sun Microsystems - Beijing China uint32_t uid;
3433f42c2f53Szhongyan gu - Sun Microsystems - Beijing China
3434f42c2f53Szhongyan gu - Sun Microsystems - Beijing China /* Get container UID first so that it will not overwrite mntinfo */
3435f42c2f53Szhongyan gu - Sun Microsystems - Beijing China rval_uid = aac_get_container_uid(softs, cid, &uid);
3436f42c2f53Szhongyan gu - Sun Microsystems - Beijing China
3437f42c2f53Szhongyan gu - Sun Microsystems - Beijing China /* Get container basic info */
3438f42c2f53Szhongyan gu - Sun Microsystems - Beijing China if ((mir = aac_get_mntinfo(softs, cid)) == NULL) {
3439f42c2f53Szhongyan gu - Sun Microsystems - Beijing China AACDB_PRINT(softs, CE_CONT,
3440f42c2f53Szhongyan gu - Sun Microsystems - Beijing China "query container %d info failed", cid);
3441f42c2f53Szhongyan gu - Sun Microsystems - Beijing China return (NULL);
3442f42c2f53Szhongyan gu - Sun Microsystems - Beijing China }
3443f42c2f53Szhongyan gu - Sun Microsystems - Beijing China if (ddi_get32(acc, &mir->MntObj.VolType) == CT_NONE)
3444f42c2f53Szhongyan gu - Sun Microsystems - Beijing China return (mir);
3445f42c2f53Szhongyan gu - Sun Microsystems - Beijing China if (rval_uid != AACOK) {
3446f42c2f53Szhongyan gu - Sun Microsystems - Beijing China AACDB_PRINT(softs, CE_CONT,
3447f42c2f53Szhongyan gu - Sun Microsystems - Beijing China "query container %d uid failed", cid);
3448f42c2f53Szhongyan gu - Sun Microsystems - Beijing China return (NULL);
3449f42c2f53Szhongyan gu - Sun Microsystems - Beijing China }
3450f42c2f53Szhongyan gu - Sun Microsystems - Beijing China
3451f42c2f53Szhongyan gu - Sun Microsystems - Beijing China ddi_put32(acc, &mir->Status, uid);
3452f42c2f53Szhongyan gu - Sun Microsystems - Beijing China return (mir);
3453f42c2f53Szhongyan gu - Sun Microsystems - Beijing China }
3454f42c2f53Szhongyan gu - Sun Microsystems - Beijing China
34550749e8deSXin Chen - Sun Microsystems - Beijing China static enum aac_cfg_event
aac_probe_container(struct aac_softstate * softs,uint32_t cid)3456942c5e3cSpl aac_probe_container(struct aac_softstate *softs, uint32_t cid)
34577c478bd9Sstevel@tonic-gate {
34580749e8deSXin Chen - Sun Microsystems - Beijing China enum aac_cfg_event event = AAC_CFG_NULL_NOEXIST;
3459942c5e3cSpl struct aac_container *dvp = &softs->containers[cid];
3460830d82f7Spl struct aac_mntinforesp *mir;
34610749e8deSXin Chen - Sun Microsystems - Beijing China ddi_acc_handle_t acc;
3462f42c2f53Szhongyan gu - Sun Microsystems - Beijing China
3463f42c2f53Szhongyan gu - Sun Microsystems - Beijing China (void) aac_sync_fib_slot_bind(softs, &softs->sync_ac);
3464f42c2f53Szhongyan gu - Sun Microsystems - Beijing China acc = softs->sync_ac.slotp->fib_acc_handle;
34657c478bd9Sstevel@tonic-gate
3466942c5e3cSpl /* Get container basic info */
3467f42c2f53Szhongyan gu - Sun Microsystems - Beijing China if ((mir = aac_get_container_info(softs, cid)) == NULL) {
34680749e8deSXin Chen - Sun Microsystems - Beijing China /* AAC_CFG_NULL_NOEXIST */
3469f42c2f53Szhongyan gu - Sun Microsystems - Beijing China goto finish;
3470f42c2f53Szhongyan gu - Sun Microsystems - Beijing China }
3471830d82f7Spl
3472942c5e3cSpl if (ddi_get32(acc, &mir->MntObj.VolType) == CT_NONE) {
347358bc78c7SXin Chen if (AAC_DEV_IS_VALID(&dvp->dev)) {
3474942c5e3cSpl AACDB_PRINT(softs, CE_NOTE,
3475942c5e3cSpl ">>> Container %d deleted", cid);
347658bc78c7SXin Chen dvp->dev.flags &= ~AAC_DFLAG_VALID;
34770749e8deSXin Chen - Sun Microsystems - Beijing China event = AAC_CFG_DELETE;
3478942c5e3cSpl }
34790749e8deSXin Chen - Sun Microsystems - Beijing China /* AAC_CFG_NULL_NOEXIST */
3480942c5e3cSpl } else {
34810749e8deSXin Chen - Sun Microsystems - Beijing China uint64_t size;
34820749e8deSXin Chen - Sun Microsystems - Beijing China uint32_t uid;
34830749e8deSXin Chen - Sun Microsystems - Beijing China
34840749e8deSXin Chen - Sun Microsystems - Beijing China event = AAC_CFG_NULL_EXIST;
34850749e8deSXin Chen - Sun Microsystems - Beijing China
3486942c5e3cSpl size = AAC_MIR_SIZE(softs, acc, mir);
3487f42c2f53Szhongyan gu - Sun Microsystems - Beijing China uid = ddi_get32(acc, &mir->Status);
348858bc78c7SXin Chen if (AAC_DEV_IS_VALID(&dvp->dev)) {
3489942c5e3cSpl if (dvp->uid != uid) {
3490942c5e3cSpl AACDB_PRINT(softs, CE_WARN,
3491942c5e3cSpl ">>> Container %u uid changed to %d",
3492942c5e3cSpl cid, uid);
3493942c5e3cSpl dvp->uid = uid;
34940749e8deSXin Chen - Sun Microsystems - Beijing China event = AAC_CFG_CHANGE;
3495942c5e3cSpl }
3496942c5e3cSpl if (dvp->size != size) {
3497942c5e3cSpl AACDB_PRINT(softs, CE_NOTE,
3498942c5e3cSpl ">>> Container %u size changed to %"PRIu64,
3499942c5e3cSpl cid, size);
3500942c5e3cSpl dvp->size = size;
35010749e8deSXin Chen - Sun Microsystems - Beijing China event = AAC_CFG_CHANGE;
3502942c5e3cSpl }
3503942c5e3cSpl } else { /* Init new container */
3504942c5e3cSpl AACDB_PRINT(softs, CE_NOTE,
350558bc78c7SXin Chen ">>> Container %d added: " \
350658bc78c7SXin Chen "size=0x%x.%08x, type=%d, name=%s",
350758bc78c7SXin Chen cid,
350858bc78c7SXin Chen ddi_get32(acc, &mir->MntObj.CapacityHigh),
350958bc78c7SXin Chen ddi_get32(acc, &mir->MntObj.Capacity),
351058bc78c7SXin Chen ddi_get32(acc, &mir->MntObj.VolType),
351158bc78c7SXin Chen mir->MntObj.FileSystemName);
351258bc78c7SXin Chen dvp->dev.flags |= AAC_DFLAG_VALID;
351358bc78c7SXin Chen dvp->dev.type = AAC_DEV_LD;
35147c478bd9Sstevel@tonic-gate
3515942c5e3cSpl dvp->cid = cid;
3516942c5e3cSpl dvp->uid = uid;
3517942c5e3cSpl dvp->size = size;
3518942c5e3cSpl dvp->locked = 0;
3519942c5e3cSpl dvp->deleted = 0;
35200749e8deSXin Chen - Sun Microsystems - Beijing China
35210749e8deSXin Chen - Sun Microsystems - Beijing China event = AAC_CFG_ADD;
3522942c5e3cSpl }
3523942c5e3cSpl }
3524f42c2f53Szhongyan gu - Sun Microsystems - Beijing China
3525f42c2f53Szhongyan gu - Sun Microsystems - Beijing China finish:
3526f42c2f53Szhongyan gu - Sun Microsystems - Beijing China aac_sync_fib_slot_release(softs, &softs->sync_ac);
35270749e8deSXin Chen - Sun Microsystems - Beijing China return (event);
35287c478bd9Sstevel@tonic-gate }
35297c478bd9Sstevel@tonic-gate
3530830d82f7Spl /*
3531830d82f7Spl * Do a rescan of all the possible containers and update the container list
353258bc78c7SXin Chen * with newly online/offline containers, and prepare for autoconfiguration.
3533830d82f7Spl */
3534942c5e3cSpl static int
aac_probe_containers(struct aac_softstate * softs)3535942c5e3cSpl aac_probe_containers(struct aac_softstate *softs)
3536830d82f7Spl {
3537942c5e3cSpl int i, count, total;
3538830d82f7Spl
3539942c5e3cSpl /* Loop over possible containers */
3540942c5e3cSpl count = softs->container_count;
3541942c5e3cSpl if (aac_get_container_count(softs, &count) == AACERR)
3542942c5e3cSpl return (AACERR);
35430749e8deSXin Chen - Sun Microsystems - Beijing China
3544942c5e3cSpl for (i = total = 0; i < count; i++) {
35450749e8deSXin Chen - Sun Microsystems - Beijing China enum aac_cfg_event event = aac_probe_container(softs, i);
35460749e8deSXin Chen - Sun Microsystems - Beijing China if ((event != AAC_CFG_NULL_NOEXIST) &&
35470749e8deSXin Chen - Sun Microsystems - Beijing China (event != AAC_CFG_NULL_EXIST)) {
35480749e8deSXin Chen - Sun Microsystems - Beijing China (void) aac_handle_dr(softs, i, -1, event);
3549942c5e3cSpl total++;
35500749e8deSXin Chen - Sun Microsystems - Beijing China }
3551942c5e3cSpl }
35520749e8deSXin Chen - Sun Microsystems - Beijing China
3553830d82f7Spl if (count < softs->container_count) {
3554942c5e3cSpl struct aac_container *dvp;
3555942c5e3cSpl
3556942c5e3cSpl for (dvp = &softs->containers[count];
3557942c5e3cSpl dvp < &softs->containers[softs->container_count]; dvp++) {
355858bc78c7SXin Chen if (!AAC_DEV_IS_VALID(&dvp->dev))
3559830d82f7Spl continue;
35601dd0a2dbSpl AACDB_PRINT(softs, CE_NOTE, ">>> Container %d deleted",
3561382c8bcaSpl dvp->cid);
356258bc78c7SXin Chen dvp->dev.flags &= ~AAC_DFLAG_VALID;
35630749e8deSXin Chen - Sun Microsystems - Beijing China (void) aac_handle_dr(softs, dvp->cid, -1,
35640749e8deSXin Chen - Sun Microsystems - Beijing China AAC_CFG_DELETE);
3565830d82f7Spl }
3566830d82f7Spl }
35670749e8deSXin Chen - Sun Microsystems - Beijing China
3568942c5e3cSpl softs->container_count = count;
3569942c5e3cSpl AACDB_PRINT(softs, CE_CONT, "?Total %d container(s) found", total);
3570942c5e3cSpl return (AACOK);
3571830d82f7Spl }
3572830d82f7Spl
35733fced439Szhongyan gu - Sun Microsystems - Beijing China static int
aac_probe_jbod(struct aac_softstate * softs,int tgt,int event)35743fced439Szhongyan gu - Sun Microsystems - Beijing China aac_probe_jbod(struct aac_softstate *softs, int tgt, int event)
35753fced439Szhongyan gu - Sun Microsystems - Beijing China {
35763ce33fb0SHengqing Hu ASSERT(AAC_MAX_LD <= tgt);
35773ce33fb0SHengqing Hu ASSERT(tgt < AAC_MAX_DEV(softs));
35783fced439Szhongyan gu - Sun Microsystems - Beijing China struct aac_device *dvp;
35793fced439Szhongyan gu - Sun Microsystems - Beijing China dvp = AAC_DEV(softs, tgt);
35803fced439Szhongyan gu - Sun Microsystems - Beijing China
35813fced439Szhongyan gu - Sun Microsystems - Beijing China switch (event) {
35823fced439Szhongyan gu - Sun Microsystems - Beijing China case AAC_CFG_ADD:
35833fced439Szhongyan gu - Sun Microsystems - Beijing China AACDB_PRINT(softs, CE_NOTE,
35843fced439Szhongyan gu - Sun Microsystems - Beijing China ">>> Jbod %d added", tgt - AAC_MAX_LD);
35853fced439Szhongyan gu - Sun Microsystems - Beijing China dvp->flags |= AAC_DFLAG_VALID;
35863fced439Szhongyan gu - Sun Microsystems - Beijing China dvp->type = AAC_DEV_PD;
35873fced439Szhongyan gu - Sun Microsystems - Beijing China break;
35883fced439Szhongyan gu - Sun Microsystems - Beijing China case AAC_CFG_DELETE:
35893fced439Szhongyan gu - Sun Microsystems - Beijing China AACDB_PRINT(softs, CE_NOTE,
35903fced439Szhongyan gu - Sun Microsystems - Beijing China ">>> Jbod %d deleted", tgt - AAC_MAX_LD);
35913fced439Szhongyan gu - Sun Microsystems - Beijing China dvp->flags &= ~AAC_DFLAG_VALID;
35923fced439Szhongyan gu - Sun Microsystems - Beijing China break;
35933fced439Szhongyan gu - Sun Microsystems - Beijing China default:
35943fced439Szhongyan gu - Sun Microsystems - Beijing China return (AACERR);
35953fced439Szhongyan gu - Sun Microsystems - Beijing China }
35963fced439Szhongyan gu - Sun Microsystems - Beijing China (void) aac_handle_dr(softs, tgt, 0, event);
35973fced439Szhongyan gu - Sun Microsystems - Beijing China return (AACOK);
35983fced439Szhongyan gu - Sun Microsystems - Beijing China }
35993fced439Szhongyan gu - Sun Microsystems - Beijing China
36007c478bd9Sstevel@tonic-gate static int
aac_alloc_comm_space(struct aac_softstate * softs)3601830d82f7Spl aac_alloc_comm_space(struct aac_softstate *softs)
36027c478bd9Sstevel@tonic-gate {
36037c478bd9Sstevel@tonic-gate size_t rlen;
36047c478bd9Sstevel@tonic-gate ddi_dma_cookie_t cookie;
36057c478bd9Sstevel@tonic-gate uint_t cookien;
36067c478bd9Sstevel@tonic-gate
3607830d82f7Spl /* Allocate DMA for comm. space */
36087c478bd9Sstevel@tonic-gate if (ddi_dma_alloc_handle(
3609c9487164Spl softs->devinfo_p,
3610c9487164Spl &softs->addr_dma_attr,
3611c9487164Spl DDI_DMA_SLEEP,
3612c9487164Spl NULL,
3613c9487164Spl &softs->comm_space_dma_handle) != DDI_SUCCESS) {
36141dd0a2dbSpl AACDB_PRINT(softs, CE_WARN,
36151dd0a2dbSpl "Cannot alloc dma handle for communication area");
36167c478bd9Sstevel@tonic-gate goto error;
36177c478bd9Sstevel@tonic-gate }
36187c478bd9Sstevel@tonic-gate if (ddi_dma_mem_alloc(
3619c9487164Spl softs->comm_space_dma_handle,
3620c9487164Spl sizeof (struct aac_comm_space),
362158bc78c7SXin Chen &softs->acc_attr,
3622c9487164Spl DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
3623c9487164Spl DDI_DMA_SLEEP,
3624c9487164Spl NULL,
3625c9487164Spl (caddr_t *)&softs->comm_space,
3626c9487164Spl &rlen,
3627c9487164Spl &softs->comm_space_acc_handle) != DDI_SUCCESS) {
36281dd0a2dbSpl AACDB_PRINT(softs, CE_WARN,
36291dd0a2dbSpl "Cannot alloc mem for communication area");
36307c478bd9Sstevel@tonic-gate goto error;
36317c478bd9Sstevel@tonic-gate }
36327c478bd9Sstevel@tonic-gate if (ddi_dma_addr_bind_handle(
3633c9487164Spl softs->comm_space_dma_handle,
3634c9487164Spl NULL,
3635c9487164Spl (caddr_t)softs->comm_space,
3636c9487164Spl sizeof (struct aac_comm_space),
3637c9487164Spl DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
3638c9487164Spl DDI_DMA_SLEEP,
3639c9487164Spl NULL,
3640c9487164Spl &cookie,
3641c9487164Spl &cookien) != DDI_DMA_MAPPED) {
36421dd0a2dbSpl AACDB_PRINT(softs, CE_WARN,
36431dd0a2dbSpl "DMA bind failed for communication area");
36447c478bd9Sstevel@tonic-gate goto error;
36457c478bd9Sstevel@tonic-gate }
3646830d82f7Spl softs->comm_space_phyaddr = cookie.dmac_address;
3647830d82f7Spl
3648830d82f7Spl return (AACOK);
36497c478bd9Sstevel@tonic-gate error:
36507c478bd9Sstevel@tonic-gate if (softs->comm_space_acc_handle) {
36517c478bd9Sstevel@tonic-gate ddi_dma_mem_free(&softs->comm_space_acc_handle);
36527c478bd9Sstevel@tonic-gate softs->comm_space_acc_handle = NULL;
36537c478bd9Sstevel@tonic-gate }
36547c478bd9Sstevel@tonic-gate if (softs->comm_space_dma_handle) {
36557c478bd9Sstevel@tonic-gate ddi_dma_free_handle(&softs->comm_space_dma_handle);
36567c478bd9Sstevel@tonic-gate softs->comm_space_dma_handle = NULL;
36577c478bd9Sstevel@tonic-gate }
36587c478bd9Sstevel@tonic-gate return (AACERR);
36597c478bd9Sstevel@tonic-gate }
36607c478bd9Sstevel@tonic-gate
36617c478bd9Sstevel@tonic-gate static void
aac_free_comm_space(struct aac_softstate * softs)3662830d82f7Spl aac_free_comm_space(struct aac_softstate *softs)
3663830d82f7Spl {
3664942c5e3cSpl
3665830d82f7Spl (void) ddi_dma_unbind_handle(softs->comm_space_dma_handle);
3666830d82f7Spl ddi_dma_mem_free(&softs->comm_space_acc_handle);
3667830d82f7Spl softs->comm_space_acc_handle = NULL;
3668830d82f7Spl ddi_dma_free_handle(&softs->comm_space_dma_handle);
3669830d82f7Spl softs->comm_space_dma_handle = NULL;
367048e2f283SToomas Soome softs->comm_space_phyaddr = 0;
3671830d82f7Spl }
3672830d82f7Spl
3673830d82f7Spl /*
3674830d82f7Spl * Initialize the data structures that are required for the communication
3675830d82f7Spl * interface to operate
3676830d82f7Spl */
3677830d82f7Spl static int
aac_setup_comm_space(struct aac_softstate * softs)3678830d82f7Spl aac_setup_comm_space(struct aac_softstate *softs)
3679830d82f7Spl {
3680942c5e3cSpl ddi_dma_handle_t dma = softs->comm_space_dma_handle;
3681942c5e3cSpl ddi_acc_handle_t acc = softs->comm_space_acc_handle;
3682830d82f7Spl uint32_t comm_space_phyaddr;
3683830d82f7Spl struct aac_adapter_init *initp;
3684830d82f7Spl int qoffset;
3685830d82f7Spl
3686830d82f7Spl comm_space_phyaddr = softs->comm_space_phyaddr;
3687830d82f7Spl
3688830d82f7Spl /* Setup adapter init struct */
3689830d82f7Spl initp = &softs->comm_space->init_data;
3690830d82f7Spl bzero(initp, sizeof (struct aac_adapter_init));
3691942c5e3cSpl
3692942c5e3cSpl ddi_put32(acc, &initp->InitStructRevision, AAC_INIT_STRUCT_REVISION);
3693942c5e3cSpl ddi_put32(acc, &initp->HostElapsedSeconds, ddi_get_time());
3694830d82f7Spl
3695830d82f7Spl /* Setup new/old comm. specific data */
3696830d82f7Spl if (softs->flags & AAC_FLAGS_RAW_IO) {
3697b40e8a89Szhongyan gu - Sun Microsystems - Beijing China uint32_t init_flags = 0;
3698b40e8a89Szhongyan gu - Sun Microsystems - Beijing China
3699b40e8a89Szhongyan gu - Sun Microsystems - Beijing China if (softs->flags & AAC_FLAGS_NEW_COMM)
3700b40e8a89Szhongyan gu - Sun Microsystems - Beijing China init_flags |= AAC_INIT_FLAGS_NEW_COMM_SUPPORTED;
3701b40e8a89Szhongyan gu - Sun Microsystems - Beijing China /* AAC_SUPPORTED_POWER_MANAGEMENT */
3702b40e8a89Szhongyan gu - Sun Microsystems - Beijing China init_flags |= AAC_INIT_FLAGS_DRIVER_SUPPORTS_PM;
3703b40e8a89Szhongyan gu - Sun Microsystems - Beijing China init_flags |= AAC_INIT_FLAGS_DRIVER_USES_UTC_TIME;
3704b40e8a89Szhongyan gu - Sun Microsystems - Beijing China
3705942c5e3cSpl ddi_put32(acc, &initp->InitStructRevision,
3706942c5e3cSpl AAC_INIT_STRUCT_REVISION_4);
3707b40e8a89Szhongyan gu - Sun Microsystems - Beijing China ddi_put32(acc, &initp->InitFlags, init_flags);
3708830d82f7Spl /* Setup the preferred settings */
3709942c5e3cSpl ddi_put32(acc, &initp->MaxIoCommands, softs->aac_max_fibs);
3710942c5e3cSpl ddi_put32(acc, &initp->MaxIoSize,
3711942c5e3cSpl (softs->aac_max_sectors << 9));
3712942c5e3cSpl ddi_put32(acc, &initp->MaxFibSize, softs->aac_max_fib_size);
3713830d82f7Spl } else {
3714830d82f7Spl /*
3715830d82f7Spl * Tells the adapter about the physical location of various
3716830d82f7Spl * important shared data structures
3717830d82f7Spl */
3718942c5e3cSpl ddi_put32(acc, &initp->AdapterFibsPhysicalAddress,
3719942c5e3cSpl comm_space_phyaddr + \
3720942c5e3cSpl offsetof(struct aac_comm_space, adapter_fibs));
3721942c5e3cSpl ddi_put32(acc, &initp->AdapterFibsVirtualAddress, 0);
3722942c5e3cSpl ddi_put32(acc, &initp->AdapterFibAlign, AAC_FIB_SIZE);
3723942c5e3cSpl ddi_put32(acc, &initp->AdapterFibsSize,
3724942c5e3cSpl AAC_ADAPTER_FIBS * AAC_FIB_SIZE);
3725942c5e3cSpl ddi_put32(acc, &initp->PrintfBufferAddress,
3726942c5e3cSpl comm_space_phyaddr + \
3727942c5e3cSpl offsetof(struct aac_comm_space, adapter_print_buf));
3728942c5e3cSpl ddi_put32(acc, &initp->PrintfBufferSize,
3729942c5e3cSpl AAC_ADAPTER_PRINT_BUFSIZE);
3730942c5e3cSpl ddi_put32(acc, &initp->MiniPortRevision,
3731942c5e3cSpl AAC_INIT_STRUCT_MINIPORT_REVISION);
3732942c5e3cSpl ddi_put32(acc, &initp->HostPhysMemPages, AAC_MAX_PFN);
3733830d82f7Spl
3734830d82f7Spl qoffset = (comm_space_phyaddr + \
3735942c5e3cSpl offsetof(struct aac_comm_space, qtable)) % \
3736c9487164Spl AAC_QUEUE_ALIGN;
3737830d82f7Spl if (qoffset)
3738830d82f7Spl qoffset = AAC_QUEUE_ALIGN - qoffset;
3739830d82f7Spl softs->qtablep = (struct aac_queue_table *) \
3740c9487164Spl ((char *)&softs->comm_space->qtable + qoffset);
3741942c5e3cSpl ddi_put32(acc, &initp->CommHeaderAddress, comm_space_phyaddr + \
3742942c5e3cSpl offsetof(struct aac_comm_space, qtable) + qoffset);
3743830d82f7Spl
3744830d82f7Spl /* Init queue table */
3745942c5e3cSpl ddi_put32(acc, &softs->qtablep-> \
3746942c5e3cSpl qt_qindex[AAC_HOST_NORM_CMD_Q][AAC_PRODUCER_INDEX],
3747942c5e3cSpl AAC_HOST_NORM_CMD_ENTRIES);
3748942c5e3cSpl ddi_put32(acc, &softs->qtablep-> \
3749942c5e3cSpl qt_qindex[AAC_HOST_NORM_CMD_Q][AAC_CONSUMER_INDEX],
3750942c5e3cSpl AAC_HOST_NORM_CMD_ENTRIES);
3751942c5e3cSpl ddi_put32(acc, &softs->qtablep-> \
3752942c5e3cSpl qt_qindex[AAC_HOST_HIGH_CMD_Q][AAC_PRODUCER_INDEX],
3753942c5e3cSpl AAC_HOST_HIGH_CMD_ENTRIES);
3754942c5e3cSpl ddi_put32(acc, &softs->qtablep-> \
3755942c5e3cSpl qt_qindex[AAC_HOST_HIGH_CMD_Q][AAC_CONSUMER_INDEX],
3756942c5e3cSpl AAC_HOST_HIGH_CMD_ENTRIES);
3757942c5e3cSpl ddi_put32(acc, &softs->qtablep-> \
3758942c5e3cSpl qt_qindex[AAC_ADAP_NORM_CMD_Q][AAC_PRODUCER_INDEX],
3759942c5e3cSpl AAC_ADAP_NORM_CMD_ENTRIES);
3760942c5e3cSpl ddi_put32(acc, &softs->qtablep-> \
3761942c5e3cSpl qt_qindex[AAC_ADAP_NORM_CMD_Q][AAC_CONSUMER_INDEX],
3762942c5e3cSpl AAC_ADAP_NORM_CMD_ENTRIES);
3763942c5e3cSpl ddi_put32(acc, &softs->qtablep-> \
3764942c5e3cSpl qt_qindex[AAC_ADAP_HIGH_CMD_Q][AAC_PRODUCER_INDEX],
3765942c5e3cSpl AAC_ADAP_HIGH_CMD_ENTRIES);
3766942c5e3cSpl ddi_put32(acc, &softs->qtablep-> \
3767942c5e3cSpl qt_qindex[AAC_ADAP_HIGH_CMD_Q][AAC_CONSUMER_INDEX],
3768942c5e3cSpl AAC_ADAP_HIGH_CMD_ENTRIES);
3769942c5e3cSpl ddi_put32(acc, &softs->qtablep-> \
3770942c5e3cSpl qt_qindex[AAC_HOST_NORM_RESP_Q][AAC_PRODUCER_INDEX],
3771942c5e3cSpl AAC_HOST_NORM_RESP_ENTRIES);
3772942c5e3cSpl ddi_put32(acc, &softs->qtablep-> \
3773942c5e3cSpl qt_qindex[AAC_HOST_NORM_RESP_Q][AAC_CONSUMER_INDEX],
3774942c5e3cSpl AAC_HOST_NORM_RESP_ENTRIES);
3775942c5e3cSpl ddi_put32(acc, &softs->qtablep-> \
3776942c5e3cSpl qt_qindex[AAC_HOST_HIGH_RESP_Q][AAC_PRODUCER_INDEX],
3777942c5e3cSpl AAC_HOST_HIGH_RESP_ENTRIES);
3778942c5e3cSpl ddi_put32(acc, &softs->qtablep-> \
3779942c5e3cSpl qt_qindex[AAC_HOST_HIGH_RESP_Q][AAC_CONSUMER_INDEX],
3780942c5e3cSpl AAC_HOST_HIGH_RESP_ENTRIES);
3781942c5e3cSpl ddi_put32(acc, &softs->qtablep-> \
3782942c5e3cSpl qt_qindex[AAC_ADAP_NORM_RESP_Q][AAC_PRODUCER_INDEX],
3783942c5e3cSpl AAC_ADAP_NORM_RESP_ENTRIES);
3784942c5e3cSpl ddi_put32(acc, &softs->qtablep-> \
3785942c5e3cSpl qt_qindex[AAC_ADAP_NORM_RESP_Q][AAC_CONSUMER_INDEX],
3786942c5e3cSpl AAC_ADAP_NORM_RESP_ENTRIES);
3787942c5e3cSpl ddi_put32(acc, &softs->qtablep-> \
3788942c5e3cSpl qt_qindex[AAC_ADAP_HIGH_RESP_Q][AAC_PRODUCER_INDEX],
3789942c5e3cSpl AAC_ADAP_HIGH_RESP_ENTRIES);
3790942c5e3cSpl ddi_put32(acc, &softs->qtablep-> \
3791942c5e3cSpl qt_qindex[AAC_ADAP_HIGH_RESP_Q][AAC_CONSUMER_INDEX],
3792942c5e3cSpl AAC_ADAP_HIGH_RESP_ENTRIES);
3793830d82f7Spl
3794830d82f7Spl /* Init queue entries */
3795830d82f7Spl softs->qentries[AAC_HOST_NORM_CMD_Q] =
3796c9487164Spl &softs->qtablep->qt_HostNormCmdQueue[0];
3797830d82f7Spl softs->qentries[AAC_HOST_HIGH_CMD_Q] =
3798c9487164Spl &softs->qtablep->qt_HostHighCmdQueue[0];
3799830d82f7Spl softs->qentries[AAC_ADAP_NORM_CMD_Q] =
3800c9487164Spl &softs->qtablep->qt_AdapNormCmdQueue[0];
3801830d82f7Spl softs->qentries[AAC_ADAP_HIGH_CMD_Q] =
3802c9487164Spl &softs->qtablep->qt_AdapHighCmdQueue[0];
3803830d82f7Spl softs->qentries[AAC_HOST_NORM_RESP_Q] =
3804c9487164Spl &softs->qtablep->qt_HostNormRespQueue[0];
3805830d82f7Spl softs->qentries[AAC_HOST_HIGH_RESP_Q] =
3806c9487164Spl &softs->qtablep->qt_HostHighRespQueue[0];
3807830d82f7Spl softs->qentries[AAC_ADAP_NORM_RESP_Q] =
3808c9487164Spl &softs->qtablep->qt_AdapNormRespQueue[0];
3809830d82f7Spl softs->qentries[AAC_ADAP_HIGH_RESP_Q] =
3810c9487164Spl &softs->qtablep->qt_AdapHighRespQueue[0];
3811830d82f7Spl }
3812942c5e3cSpl (void) ddi_dma_sync(dma, 0, 0, DDI_DMA_SYNC_FORDEV);
3813830d82f7Spl
3814830d82f7Spl /* Send init structure to the card */
3815c9487164Spl if (aac_sync_mbcommand(softs, AAC_MONKER_INITSTRUCT,
3816c9487164Spl comm_space_phyaddr + \
3817942c5e3cSpl offsetof(struct aac_comm_space, init_data),
3818c9487164Spl 0, 0, 0, NULL) == AACERR) {
38191dd0a2dbSpl AACDB_PRINT(softs, CE_WARN,
38201dd0a2dbSpl "Cannot send init structure to adapter");
3821830d82f7Spl return (AACERR);
3822830d82f7Spl }
3823830d82f7Spl
3824830d82f7Spl return (AACOK);
3825830d82f7Spl }
3826830d82f7Spl
3827830d82f7Spl static uchar_t *
aac_vendor_id(struct aac_softstate * softs,uchar_t * buf)3828830d82f7Spl aac_vendor_id(struct aac_softstate *softs, uchar_t *buf)
3829830d82f7Spl {
3830d937e6ebSpl (void) memset(buf, ' ', AAC_VENDOR_LEN);
3831d937e6ebSpl bcopy(softs->vendor_name, buf, strlen(softs->vendor_name));
3832d937e6ebSpl return (buf + AAC_VENDOR_LEN);
3833830d82f7Spl }
3834830d82f7Spl
3835830d82f7Spl static uchar_t *
aac_product_id(struct aac_softstate * softs,uchar_t * buf)3836830d82f7Spl aac_product_id(struct aac_softstate *softs, uchar_t *buf)
3837830d82f7Spl {
3838d937e6ebSpl (void) memset(buf, ' ', AAC_PRODUCT_LEN);
3839d937e6ebSpl bcopy(softs->product_name, buf, strlen(softs->product_name));
3840d937e6ebSpl return (buf + AAC_PRODUCT_LEN);
3841830d82f7Spl }
3842830d82f7Spl
3843830d82f7Spl /*
3844830d82f7Spl * Construct unit serial number from container uid
3845830d82f7Spl */
3846830d82f7Spl static uchar_t *
aac_lun_serialno(struct aac_softstate * softs,int tgt,uchar_t * buf)3847830d82f7Spl aac_lun_serialno(struct aac_softstate *softs, int tgt, uchar_t *buf)
3848830d82f7Spl {
3849830d82f7Spl int i, d;
385058bc78c7SXin Chen uint32_t uid;
385158bc78c7SXin Chen
385258bc78c7SXin Chen ASSERT(tgt >= 0 && tgt < AAC_MAX_LD);
3853830d82f7Spl
385458bc78c7SXin Chen uid = softs->containers[tgt].uid;
3855830d82f7Spl for (i = 7; i >= 0; i--) {
3856830d82f7Spl d = uid & 0xf;
3857830d82f7Spl buf[i] = d > 9 ? 'A' + (d - 0xa) : '0' + d;
3858830d82f7Spl uid >>= 4;
3859830d82f7Spl }
3860830d82f7Spl return (buf + 8);
3861830d82f7Spl }
3862830d82f7Spl
3863830d82f7Spl /*
3864830d82f7Spl * SPC-3 7.5 INQUIRY command implementation
3865830d82f7Spl */
3866830d82f7Spl static void
aac_inquiry(struct aac_softstate * softs,struct scsi_pkt * pkt,union scsi_cdb * cdbp,struct buf * bp)3867830d82f7Spl aac_inquiry(struct aac_softstate *softs, struct scsi_pkt *pkt,
3868c9487164Spl union scsi_cdb *cdbp, struct buf *bp)
3869830d82f7Spl {
3870830d82f7Spl int tgt = pkt->pkt_address.a_target;
3871830d82f7Spl char *b_addr = NULL;
3872830d82f7Spl uchar_t page = cdbp->cdb_opaque[2];
3873830d82f7Spl
3874830d82f7Spl if (cdbp->cdb_opaque[1] & AAC_CDB_INQUIRY_CMDDT) {
3875830d82f7Spl /* Command Support Data is not supported */
3876830d82f7Spl aac_set_arq_data(pkt, KEY_ILLEGAL_REQUEST, 0x24, 0x00, 0);
3877830d82f7Spl return;
3878830d82f7Spl }
3879830d82f7Spl
3880830d82f7Spl if (bp && bp->b_un.b_addr && bp->b_bcount) {
3881830d82f7Spl if (bp->b_flags & (B_PHYS | B_PAGEIO))
3882830d82f7Spl bp_mapin(bp);
3883830d82f7Spl b_addr = bp->b_un.b_addr;
3884830d82f7Spl }
3885830d82f7Spl
3886830d82f7Spl if (cdbp->cdb_opaque[1] & AAC_CDB_INQUIRY_EVPD) {
3887830d82f7Spl uchar_t *vpdp = (uchar_t *)b_addr;
3888830d82f7Spl uchar_t *idp, *sp;
3889830d82f7Spl
3890830d82f7Spl /* SPC-3 8.4 Vital product data parameters */
3891830d82f7Spl switch (page) {
3892830d82f7Spl case 0x00:
3893830d82f7Spl /* Supported VPD pages */
389451ccf66eSjd if (vpdp == NULL ||
389551ccf66eSjd bp->b_bcount < (AAC_VPD_PAGE_DATA + 3))
3896830d82f7Spl return;
3897830d82f7Spl bzero(vpdp, AAC_VPD_PAGE_LENGTH);
3898830d82f7Spl vpdp[AAC_VPD_PAGE_CODE] = 0x00;
3899830d82f7Spl vpdp[AAC_VPD_PAGE_LENGTH] = 3;
3900830d82f7Spl
3901830d82f7Spl vpdp[AAC_VPD_PAGE_DATA] = 0x00;
3902830d82f7Spl vpdp[AAC_VPD_PAGE_DATA + 1] = 0x80;
3903830d82f7Spl vpdp[AAC_VPD_PAGE_DATA + 2] = 0x83;
3904830d82f7Spl
3905830d82f7Spl pkt->pkt_state |= STATE_XFERRED_DATA;
3906830d82f7Spl break;
3907830d82f7Spl
3908830d82f7Spl case 0x80:
3909830d82f7Spl /* Unit serial number page */
391051ccf66eSjd if (vpdp == NULL ||
391151ccf66eSjd bp->b_bcount < (AAC_VPD_PAGE_DATA + 8))
3912830d82f7Spl return;
3913830d82f7Spl bzero(vpdp, AAC_VPD_PAGE_LENGTH);
3914830d82f7Spl vpdp[AAC_VPD_PAGE_CODE] = 0x80;
3915830d82f7Spl vpdp[AAC_VPD_PAGE_LENGTH] = 8;
3916830d82f7Spl
3917830d82f7Spl sp = &vpdp[AAC_VPD_PAGE_DATA];
3918830d82f7Spl (void) aac_lun_serialno(softs, tgt, sp);
3919830d82f7Spl
3920830d82f7Spl pkt->pkt_state |= STATE_XFERRED_DATA;
3921830d82f7Spl break;
3922830d82f7Spl
3923830d82f7Spl case 0x83:
3924830d82f7Spl /* Device identification page */
392551ccf66eSjd if (vpdp == NULL ||
392651ccf66eSjd bp->b_bcount < (AAC_VPD_PAGE_DATA + 32))
3927830d82f7Spl return;
3928830d82f7Spl bzero(vpdp, AAC_VPD_PAGE_LENGTH);
3929830d82f7Spl vpdp[AAC_VPD_PAGE_CODE] = 0x83;
3930830d82f7Spl
3931830d82f7Spl idp = &vpdp[AAC_VPD_PAGE_DATA];
3932830d82f7Spl bzero(idp, AAC_VPD_ID_LENGTH);
3933830d82f7Spl idp[AAC_VPD_ID_CODESET] = 0x02;
3934830d82f7Spl idp[AAC_VPD_ID_TYPE] = 0x01;
3935830d82f7Spl
3936830d82f7Spl /*
3937830d82f7Spl * SPC-3 Table 111 - Identifier type
3938830d82f7Spl * One recommanded method of constructing the remainder
3939830d82f7Spl * of identifier field is to concatenate the product
3940830d82f7Spl * identification field from the standard INQUIRY data
3941830d82f7Spl * field and the product serial number field from the
3942830d82f7Spl * unit serial number page.
3943830d82f7Spl */
3944830d82f7Spl sp = &idp[AAC_VPD_ID_DATA];
3945830d82f7Spl sp = aac_vendor_id(softs, sp);
3946830d82f7Spl sp = aac_product_id(softs, sp);
3947830d82f7Spl sp = aac_lun_serialno(softs, tgt, sp);
3948a74f7440Spl idp[AAC_VPD_ID_LENGTH] = (uintptr_t)sp - \
3949a74f7440Spl (uintptr_t)&idp[AAC_VPD_ID_DATA];
3950830d82f7Spl
3951a74f7440Spl vpdp[AAC_VPD_PAGE_LENGTH] = (uintptr_t)sp - \
3952a74f7440Spl (uintptr_t)&vpdp[AAC_VPD_PAGE_DATA];
3953830d82f7Spl pkt->pkt_state |= STATE_XFERRED_DATA;
3954830d82f7Spl break;
3955830d82f7Spl
3956830d82f7Spl default:
3957830d82f7Spl aac_set_arq_data(pkt, KEY_ILLEGAL_REQUEST,
3958c9487164Spl 0x24, 0x00, 0);
3959830d82f7Spl break;
3960830d82f7Spl }
3961830d82f7Spl } else {
3962c9487164Spl struct scsi_inquiry *inqp = (struct scsi_inquiry *)b_addr;
3963830d82f7Spl size_t len = sizeof (struct scsi_inquiry);
3964830d82f7Spl
3965830d82f7Spl if (page != 0) {
3966830d82f7Spl aac_set_arq_data(pkt, KEY_ILLEGAL_REQUEST,
3967c9487164Spl 0x24, 0x00, 0);
3968830d82f7Spl return;
3969830d82f7Spl }
397051ccf66eSjd if (inqp == NULL || bp->b_bcount < len)
3971830d82f7Spl return;
3972830d82f7Spl
3973830d82f7Spl bzero(inqp, len);
3974830d82f7Spl inqp->inq_len = AAC_ADDITIONAL_LEN;
3975830d82f7Spl inqp->inq_ansi = AAC_ANSI_VER;
3976830d82f7Spl inqp->inq_rdf = AAC_RESP_DATA_FORMAT;
3977830d82f7Spl (void) aac_vendor_id(softs, (uchar_t *)inqp->inq_vid);
3978830d82f7Spl (void) aac_product_id(softs, (uchar_t *)inqp->inq_pid);
3979830d82f7Spl bcopy("V1.0", inqp->inq_revision, 4);
3980830d82f7Spl inqp->inq_cmdque = 1; /* enable tagged-queuing */
3981830d82f7Spl /*
3982830d82f7Spl * For "sd-max-xfer-size" property which may impact performance
3983830d82f7Spl * when IO threads increase.
3984830d82f7Spl */
3985830d82f7Spl inqp->inq_wbus32 = 1;
3986830d82f7Spl
3987830d82f7Spl pkt->pkt_state |= STATE_XFERRED_DATA;
3988830d82f7Spl }
3989830d82f7Spl }
3990830d82f7Spl
3991830d82f7Spl /*
3992830d82f7Spl * SPC-3 7.10 MODE SENSE command implementation
3993830d82f7Spl */
3994830d82f7Spl static void
aac_mode_sense(struct aac_softstate * softs,struct scsi_pkt * pkt,union scsi_cdb * cdbp,struct buf * bp,int capacity)3995830d82f7Spl aac_mode_sense(struct aac_softstate *softs, struct scsi_pkt *pkt,
3996c9487164Spl union scsi_cdb *cdbp, struct buf *bp, int capacity)
39977c478bd9Sstevel@tonic-gate {
39987c478bd9Sstevel@tonic-gate uchar_t pagecode;
39997c478bd9Sstevel@tonic-gate struct mode_header *headerp;
400051ccf66eSjd struct mode_header_g1 *g1_headerp;
40017c478bd9Sstevel@tonic-gate unsigned int ncyl;
400251ccf66eSjd caddr_t sense_data;
400351ccf66eSjd caddr_t next_page;
400451ccf66eSjd size_t sdata_size;
400551ccf66eSjd size_t pages_size;
400651ccf66eSjd int unsupport_page = 0;
400751ccf66eSjd
400851ccf66eSjd ASSERT(cdbp->scc_cmd == SCMD_MODE_SENSE ||
400951ccf66eSjd cdbp->scc_cmd == SCMD_MODE_SENSE_G1);
40107c478bd9Sstevel@tonic-gate
40117c478bd9Sstevel@tonic-gate if (!(bp && bp->b_un.b_addr && bp->b_bcount))
40127c478bd9Sstevel@tonic-gate return;
40137c478bd9Sstevel@tonic-gate
40147c478bd9Sstevel@tonic-gate if (bp->b_flags & (B_PHYS | B_PAGEIO))
40157c478bd9Sstevel@tonic-gate bp_mapin(bp);
4016830d82f7Spl pkt->pkt_state |= STATE_XFERRED_DATA;
401751ccf66eSjd pagecode = cdbp->cdb_un.sg.scsi[0] & 0x3F;
401851ccf66eSjd
401951ccf66eSjd /* calculate the size of needed buffer */
402051ccf66eSjd if (cdbp->scc_cmd == SCMD_MODE_SENSE)
402151ccf66eSjd sdata_size = MODE_HEADER_LENGTH;
402251ccf66eSjd else /* must be SCMD_MODE_SENSE_G1 */
402351ccf66eSjd sdata_size = MODE_HEADER_LENGTH_G1;
40247c478bd9Sstevel@tonic-gate
402551ccf66eSjd pages_size = 0;
40267c478bd9Sstevel@tonic-gate switch (pagecode) {
40277c478bd9Sstevel@tonic-gate case SD_MODE_SENSE_PAGE3_CODE:
402851ccf66eSjd pages_size += sizeof (struct mode_format);
402951ccf66eSjd break;
403051ccf66eSjd
403151ccf66eSjd case SD_MODE_SENSE_PAGE4_CODE:
403251ccf66eSjd pages_size += sizeof (struct mode_geometry);
403351ccf66eSjd break;
403451ccf66eSjd
403551ccf66eSjd case MODEPAGE_CTRL_MODE:
403651ccf66eSjd if (softs->flags & AAC_FLAGS_LBA_64BIT) {
403751ccf66eSjd pages_size += sizeof (struct mode_control_scsi3);
403851ccf66eSjd } else {
403951ccf66eSjd unsupport_page = 1;
404051ccf66eSjd }
404151ccf66eSjd break;
404251ccf66eSjd
404351ccf66eSjd case MODEPAGE_ALLPAGES:
404451ccf66eSjd if (softs->flags & AAC_FLAGS_LBA_64BIT) {
404551ccf66eSjd pages_size += sizeof (struct mode_format) +
404651ccf66eSjd sizeof (struct mode_geometry) +
404751ccf66eSjd sizeof (struct mode_control_scsi3);
404851ccf66eSjd } else {
404951ccf66eSjd pages_size += sizeof (struct mode_format) +
405051ccf66eSjd sizeof (struct mode_geometry);
405151ccf66eSjd }
405251ccf66eSjd break;
405351ccf66eSjd
405451ccf66eSjd default:
405551ccf66eSjd /* unsupported pages */
405651ccf66eSjd unsupport_page = 1;
405751ccf66eSjd }
405851ccf66eSjd
405951ccf66eSjd /* allocate buffer to fill the send data */
406051ccf66eSjd sdata_size += pages_size;
406151ccf66eSjd sense_data = kmem_zalloc(sdata_size, KM_SLEEP);
406251ccf66eSjd
406351ccf66eSjd if (cdbp->scc_cmd == SCMD_MODE_SENSE) {
406451ccf66eSjd headerp = (struct mode_header *)sense_data;
406551ccf66eSjd headerp->length = MODE_HEADER_LENGTH + pages_size -
406651ccf66eSjd sizeof (headerp->length);
406751ccf66eSjd headerp->bdesc_length = 0;
406851ccf66eSjd next_page = sense_data + sizeof (struct mode_header);
406951ccf66eSjd } else {
4070a74f7440Spl g1_headerp = (void *)sense_data;
4071b6094a86Sjd g1_headerp->length = BE_16(MODE_HEADER_LENGTH_G1 + pages_size -
4072b6094a86Sjd sizeof (g1_headerp->length));
407351ccf66eSjd g1_headerp->bdesc_length = 0;
407451ccf66eSjd next_page = sense_data + sizeof (struct mode_header_g1);
407551ccf66eSjd }
407651ccf66eSjd
407751ccf66eSjd if (unsupport_page)
407851ccf66eSjd goto finish;
407951ccf66eSjd
408051ccf66eSjd if (pagecode == SD_MODE_SENSE_PAGE3_CODE ||
408151ccf66eSjd pagecode == MODEPAGE_ALLPAGES) {
408251ccf66eSjd /* SBC-3 7.1.3.3 Format device page */
408351ccf66eSjd struct mode_format *page3p;
408451ccf66eSjd
4085a74f7440Spl page3p = (void *)next_page;
40867c478bd9Sstevel@tonic-gate page3p->mode_page.code = SD_MODE_SENSE_PAGE3_CODE;
40877c478bd9Sstevel@tonic-gate page3p->mode_page.length = sizeof (struct mode_format);
40887c478bd9Sstevel@tonic-gate page3p->data_bytes_sect = BE_16(AAC_SECTOR_SIZE);
40897c478bd9Sstevel@tonic-gate page3p->sect_track = BE_16(AAC_SECTORS_PER_TRACK);
40907c478bd9Sstevel@tonic-gate
409151ccf66eSjd next_page += sizeof (struct mode_format);
409251ccf66eSjd }
409351ccf66eSjd
409451ccf66eSjd if (pagecode == SD_MODE_SENSE_PAGE4_CODE ||
409551ccf66eSjd pagecode == MODEPAGE_ALLPAGES) {
409651ccf66eSjd /* SBC-3 7.1.3.8 Rigid disk device geometry page */
409751ccf66eSjd struct mode_geometry *page4p;
409851ccf66eSjd
4099a74f7440Spl page4p = (void *)next_page;
41007c478bd9Sstevel@tonic-gate page4p->mode_page.code = SD_MODE_SENSE_PAGE4_CODE;
41017c478bd9Sstevel@tonic-gate page4p->mode_page.length = sizeof (struct mode_geometry);
41027c478bd9Sstevel@tonic-gate page4p->heads = AAC_NUMBER_OF_HEADS;
41037c478bd9Sstevel@tonic-gate page4p->rpm = BE_16(AAC_ROTATION_SPEED);
41047c478bd9Sstevel@tonic-gate ncyl = capacity / (AAC_NUMBER_OF_HEADS * AAC_SECTORS_PER_TRACK);
41057c478bd9Sstevel@tonic-gate page4p->cyl_lb = ncyl & 0xff;
41067c478bd9Sstevel@tonic-gate page4p->cyl_mb = (ncyl >> 8) & 0xff;
41077c478bd9Sstevel@tonic-gate page4p->cyl_ub = (ncyl >> 16) & 0xff;
41087c478bd9Sstevel@tonic-gate
410951ccf66eSjd next_page += sizeof (struct mode_geometry);
411051ccf66eSjd }
4111830d82f7Spl
411251ccf66eSjd if ((pagecode == MODEPAGE_CTRL_MODE || pagecode == MODEPAGE_ALLPAGES) &&
411351ccf66eSjd softs->flags & AAC_FLAGS_LBA_64BIT) {
411451ccf66eSjd /* 64-bit LBA need large sense data */
411551ccf66eSjd struct mode_control_scsi3 *mctl;
411651ccf66eSjd
4117a74f7440Spl mctl = (void *)next_page;
411851ccf66eSjd mctl->mode_page.code = MODEPAGE_CTRL_MODE;
411951ccf66eSjd mctl->mode_page.length =
412051ccf66eSjd sizeof (struct mode_control_scsi3) -
412151ccf66eSjd sizeof (struct mode_page);
412251ccf66eSjd mctl->d_sense = 1;
41237c478bd9Sstevel@tonic-gate }
412451ccf66eSjd
412551ccf66eSjd finish:
412651ccf66eSjd /* copyout the valid data. */
412751ccf66eSjd bcopy(sense_data, bp->b_un.b_addr, min(sdata_size, bp->b_bcount));
412851ccf66eSjd kmem_free(sense_data, sdata_size);
41297c478bd9Sstevel@tonic-gate }
41307c478bd9Sstevel@tonic-gate
413158bc78c7SXin Chen static int
aac_name_node(dev_info_t * dip,char * name,int len)413258bc78c7SXin Chen aac_name_node(dev_info_t *dip, char *name, int len)
413358bc78c7SXin Chen {
413458bc78c7SXin Chen int tgt, lun;
413558bc78c7SXin Chen
413658bc78c7SXin Chen tgt = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
413758bc78c7SXin Chen DDI_PROP_DONTPASS, "target", -1);
413858bc78c7SXin Chen if (tgt == -1)
413958bc78c7SXin Chen return (DDI_FAILURE);
414058bc78c7SXin Chen lun = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
414158bc78c7SXin Chen DDI_PROP_DONTPASS, "lun", -1);
414258bc78c7SXin Chen if (lun == -1)
414358bc78c7SXin Chen return (DDI_FAILURE);
414458bc78c7SXin Chen
414558bc78c7SXin Chen (void) snprintf(name, len, "%x,%x", tgt, lun);
414658bc78c7SXin Chen return (DDI_SUCCESS);
414758bc78c7SXin Chen }
414858bc78c7SXin Chen
41497c478bd9Sstevel@tonic-gate /*ARGSUSED*/
41507c478bd9Sstevel@tonic-gate static int
aac_tran_tgt_init(dev_info_t * hba_dip,dev_info_t * tgt_dip,scsi_hba_tran_t * tran,struct scsi_device * sd)41517c478bd9Sstevel@tonic-gate aac_tran_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
4152c9487164Spl scsi_hba_tran_t *tran, struct scsi_device *sd)
41537c478bd9Sstevel@tonic-gate {
4154c9487164Spl struct aac_softstate *softs = AAC_TRAN2SOFTS(tran);
4155942c5e3cSpl #if defined(DEBUG) || defined(__lock_lint)
4156942c5e3cSpl int ctl = ddi_get_instance(softs->devinfo_p);
4157942c5e3cSpl #endif
415858bc78c7SXin Chen uint16_t tgt = sd->sd_address.a_target;
415958bc78c7SXin Chen uint8_t lun = sd->sd_address.a_lun;
416058bc78c7SXin Chen struct aac_device *dvp;
41617c478bd9Sstevel@tonic-gate
41621dd0a2dbSpl DBCALLED(softs, 2);
41637c478bd9Sstevel@tonic-gate
416458bc78c7SXin Chen if (ndi_dev_is_persistent_node(tgt_dip) == 0) {
416558bc78c7SXin Chen /*
416658bc78c7SXin Chen * If no persistent node exist, we don't allow .conf node
416758bc78c7SXin Chen * to be created.
416858bc78c7SXin Chen */
416958bc78c7SXin Chen if (aac_find_child(softs, tgt, lun) != NULL) {
417058bc78c7SXin Chen if (ndi_merge_node(tgt_dip, aac_name_node) !=
417158bc78c7SXin Chen DDI_SUCCESS)
417258bc78c7SXin Chen /* Create this .conf node */
417358bc78c7SXin Chen return (DDI_SUCCESS);
417458bc78c7SXin Chen }
4175fd4ae32fSyf return (DDI_FAILURE);
4176830d82f7Spl }
4177c9487164Spl
4178c9487164Spl /*
417958bc78c7SXin Chen * Only support container/phys. device that has been
418058bc78c7SXin Chen * detected and valid
4181c9487164Spl */
4182382c8bcaSpl mutex_enter(&softs->io_lock);
418358bc78c7SXin Chen if (tgt >= AAC_MAX_DEV(softs)) {
418458bc78c7SXin Chen AACDB_PRINT_TRAN(softs,
418558bc78c7SXin Chen "aac_tran_tgt_init: c%dt%dL%d out", ctl, tgt, lun);
4186382c8bcaSpl mutex_exit(&softs->io_lock);
41877c478bd9Sstevel@tonic-gate return (DDI_FAILURE);
4188830d82f7Spl }
418958bc78c7SXin Chen
419058bc78c7SXin Chen if (tgt < AAC_MAX_LD) {
419158bc78c7SXin Chen dvp = (struct aac_device *)&softs->containers[tgt];
419258bc78c7SXin Chen if (lun != 0 || !AAC_DEV_IS_VALID(dvp)) {
419358bc78c7SXin Chen AACDB_PRINT_TRAN(softs, "aac_tran_tgt_init: c%dt%dL%d",
419458bc78c7SXin Chen ctl, tgt, lun);
419558bc78c7SXin Chen mutex_exit(&softs->io_lock);
419658bc78c7SXin Chen return (DDI_FAILURE);
419758bc78c7SXin Chen }
419858bc78c7SXin Chen /*
419958bc78c7SXin Chen * Save the tgt_dip for the given target if one doesn't exist
420058bc78c7SXin Chen * already. Dip's for non-existance tgt's will be cleared in
420158bc78c7SXin Chen * tgt_free.
420258bc78c7SXin Chen */
420358bc78c7SXin Chen if (softs->containers[tgt].dev.dip == NULL &&
420458bc78c7SXin Chen strcmp(ddi_driver_name(sd->sd_dev), "sd") == 0)
420558bc78c7SXin Chen softs->containers[tgt].dev.dip = tgt_dip;
420658bc78c7SXin Chen } else {
420758bc78c7SXin Chen dvp = (struct aac_device *)&softs->nondasds[AAC_PD(tgt)];
42083fced439Szhongyan gu - Sun Microsystems - Beijing China /*
42093fced439Szhongyan gu - Sun Microsystems - Beijing China * Save the tgt_dip for the given target if one doesn't exist
42103fced439Szhongyan gu - Sun Microsystems - Beijing China * already. Dip's for non-existance tgt's will be cleared in
42113fced439Szhongyan gu - Sun Microsystems - Beijing China * tgt_free.
42123fced439Szhongyan gu - Sun Microsystems - Beijing China */
42133fced439Szhongyan gu - Sun Microsystems - Beijing China
42143fced439Szhongyan gu - Sun Microsystems - Beijing China if (softs->nondasds[AAC_PD(tgt)].dev.dip == NULL &&
42153fced439Szhongyan gu - Sun Microsystems - Beijing China strcmp(ddi_driver_name(sd->sd_dev), "sd") == 0)
42163fced439Szhongyan gu - Sun Microsystems - Beijing China softs->nondasds[AAC_PD(tgt)].dev.dip = tgt_dip;
421758bc78c7SXin Chen }
421858bc78c7SXin Chen
421972888e72Speng liu - Sun Microsystems - Beijing China if (softs->flags & AAC_FLAGS_BRKUP) {
422072888e72Speng liu - Sun Microsystems - Beijing China if (ndi_prop_update_int(DDI_DEV_T_NONE, tgt_dip,
422172888e72Speng liu - Sun Microsystems - Beijing China "buf_break", 1) != DDI_PROP_SUCCESS) {
422272888e72Speng liu - Sun Microsystems - Beijing China cmn_err(CE_CONT, "unable to create "
422372888e72Speng liu - Sun Microsystems - Beijing China "property for t%dL%d (buf_break)", tgt, lun);
422472888e72Speng liu - Sun Microsystems - Beijing China }
42259c57abc8Ssrivijitha dugganapalli }
422672888e72Speng liu - Sun Microsystems - Beijing China
422758bc78c7SXin Chen AACDB_PRINT(softs, CE_NOTE,
422858bc78c7SXin Chen "aac_tran_tgt_init: c%dt%dL%d ok (%s)", ctl, tgt, lun,
422958bc78c7SXin Chen (dvp->type == AAC_DEV_PD) ? "pd" : "ld");
423058bc78c7SXin Chen mutex_exit(&softs->io_lock);
423158bc78c7SXin Chen return (DDI_SUCCESS);
423258bc78c7SXin Chen }
423358bc78c7SXin Chen
423458bc78c7SXin Chen static void
aac_tran_tgt_free(dev_info_t * hba_dip,dev_info_t * tgt_dip,scsi_hba_tran_t * hba_tran,struct scsi_device * sd)423558bc78c7SXin Chen aac_tran_tgt_free(dev_info_t *hba_dip, dev_info_t *tgt_dip,
423658bc78c7SXin Chen scsi_hba_tran_t *hba_tran, struct scsi_device *sd)
423758bc78c7SXin Chen {
423858bc78c7SXin Chen #ifndef __lock_lint
423958bc78c7SXin Chen _NOTE(ARGUNUSED(hba_dip, tgt_dip, hba_tran))
424058bc78c7SXin Chen #endif
424158bc78c7SXin Chen
424258bc78c7SXin Chen struct aac_softstate *softs = SD2AAC(sd);
424358bc78c7SXin Chen int tgt = sd->sd_address.a_target;
424458bc78c7SXin Chen
424558bc78c7SXin Chen mutex_enter(&softs->io_lock);
424658bc78c7SXin Chen if (tgt < AAC_MAX_LD) {
424758bc78c7SXin Chen if (softs->containers[tgt].dev.dip == tgt_dip)
424858bc78c7SXin Chen softs->containers[tgt].dev.dip = NULL;
424958bc78c7SXin Chen } else {
42503fced439Szhongyan gu - Sun Microsystems - Beijing China if (softs->nondasds[AAC_PD(tgt)].dev.dip == tgt_dip)
42513fced439Szhongyan gu - Sun Microsystems - Beijing China softs->nondasds[AAC_PD(tgt)].dev.dip = NULL;
425258bc78c7SXin Chen softs->nondasds[AAC_PD(tgt)].dev.flags &= ~AAC_DFLAG_VALID;
425358bc78c7SXin Chen }
425458bc78c7SXin Chen mutex_exit(&softs->io_lock);
42557c478bd9Sstevel@tonic-gate }
42567c478bd9Sstevel@tonic-gate
42577c478bd9Sstevel@tonic-gate /*
4258830d82f7Spl * Check if the firmware is Up And Running. If it is in the Kernel Panic
4259830d82f7Spl * state, (BlinkLED code + 1) is returned.
4260830d82f7Spl * 0 -- firmware up and running
4261830d82f7Spl * -1 -- firmware dead
4262830d82f7Spl * >0 -- firmware kernel panic
4263830d82f7Spl */
4264830d82f7Spl static int
aac_check_adapter_health(struct aac_softstate * softs)4265830d82f7Spl aac_check_adapter_health(struct aac_softstate *softs)
4266830d82f7Spl {
4267c9487164Spl int rval;
4268830d82f7Spl
4269c9487164Spl rval = PCI_MEM_GET32(softs, AAC_OMR0);
4270830d82f7Spl
4271942c5e3cSpl if (rval & AAC_KERNEL_UP_AND_RUNNING) {
4272c9487164Spl rval = 0;
4273942c5e3cSpl } else if (rval & AAC_KERNEL_PANIC) {
4274942c5e3cSpl cmn_err(CE_WARN, "firmware panic");
4275c9487164Spl rval = ((rval >> 16) & 0xff) + 1; /* avoid 0 as return value */
4276942c5e3cSpl } else {
4277942c5e3cSpl cmn_err(CE_WARN, "firmware dead");
4278c9487164Spl rval = -1;
4279942c5e3cSpl }
4280c9487164Spl return (rval);
4281830d82f7Spl }
4282830d82f7Spl
4283382c8bcaSpl static void
aac_abort_iocmd(struct aac_softstate * softs,struct aac_cmd * acp,uchar_t reason)4284382c8bcaSpl aac_abort_iocmd(struct aac_softstate *softs, struct aac_cmd *acp,
4285382c8bcaSpl uchar_t reason)
4286830d82f7Spl {
4287382c8bcaSpl acp->flags |= AAC_CMD_ABORT;
4288830d82f7Spl
4289382c8bcaSpl if (acp->pkt) {
429058bc78c7SXin Chen if (acp->slotp) { /* outstanding cmd */
429158bc78c7SXin Chen acp->pkt->pkt_state |= STATE_GOT_STATUS;
429258bc78c7SXin Chen }
4293382c8bcaSpl
4294382c8bcaSpl switch (reason) {
4295382c8bcaSpl case CMD_TIMEOUT:
429658bc78c7SXin Chen AACDB_PRINT(softs, CE_NOTE, "CMD_TIMEOUT: acp=0x%p",
429758bc78c7SXin Chen acp);
4298382c8bcaSpl aac_set_pkt_reason(softs, acp, CMD_TIMEOUT,
4299382c8bcaSpl STAT_TIMEOUT | STAT_BUS_RESET);
4300382c8bcaSpl break;
4301382c8bcaSpl case CMD_RESET:
4302382c8bcaSpl /* aac support only RESET_ALL */
430358bc78c7SXin Chen AACDB_PRINT(softs, CE_NOTE, "CMD_RESET: acp=0x%p", acp);
4304382c8bcaSpl aac_set_pkt_reason(softs, acp, CMD_RESET,
4305382c8bcaSpl STAT_BUS_RESET);
4306382c8bcaSpl break;
4307382c8bcaSpl case CMD_ABORTED:
430858bc78c7SXin Chen AACDB_PRINT(softs, CE_NOTE, "CMD_ABORTED: acp=0x%p",
430958bc78c7SXin Chen acp);
4310382c8bcaSpl aac_set_pkt_reason(softs, acp, CMD_ABORTED,
4311382c8bcaSpl STAT_ABORTED);
4312830d82f7Spl break;
4313382c8bcaSpl }
4314830d82f7Spl }
4315382c8bcaSpl aac_end_io(softs, acp);
4316830d82f7Spl }
4317830d82f7Spl
4318832e0b5aSpl /*
4319382c8bcaSpl * Abort all the pending commands of type iocmd or just the command pkt
4320382c8bcaSpl * corresponding to pkt
4321832e0b5aSpl */
4322830d82f7Spl static void
aac_abort_iocmds(struct aac_softstate * softs,int iocmd,struct scsi_pkt * pkt,int reason)4323382c8bcaSpl aac_abort_iocmds(struct aac_softstate *softs, int iocmd, struct scsi_pkt *pkt,
4324382c8bcaSpl int reason)
4325830d82f7Spl {
4326382c8bcaSpl struct aac_cmd *ac_arg, *acp;
4327830d82f7Spl int i;
4328830d82f7Spl
4329382c8bcaSpl if (pkt == NULL) {
4330382c8bcaSpl ac_arg = NULL;
4331382c8bcaSpl } else {
4332382c8bcaSpl ac_arg = PKT2AC(pkt);
4333382c8bcaSpl iocmd = (ac_arg->flags & AAC_CMD_SYNC) ?
4334382c8bcaSpl AAC_IOCMD_SYNC : AAC_IOCMD_ASYNC;
4335382c8bcaSpl }
4336830d82f7Spl
4337382c8bcaSpl /*
4338382c8bcaSpl * a) outstanding commands on the controller
4339382c8bcaSpl * Note: should abort outstanding commands only after one
4340382c8bcaSpl * IOP reset has been done.
4341382c8bcaSpl */
4342832e0b5aSpl if (iocmd & AAC_IOCMD_OUTSTANDING) {
4343382c8bcaSpl struct aac_cmd *acp;
4344382c8bcaSpl
4345c9487164Spl for (i = 0; i < AAC_MAX_LD; i++) {
434658bc78c7SXin Chen if (AAC_DEV_IS_VALID(&softs->containers[i].dev))
4347942c5e3cSpl softs->containers[i].reset = 1;
4348c9487164Spl }
4349382c8bcaSpl while ((acp = softs->q_busy.q_head) != NULL)
4350382c8bcaSpl aac_abort_iocmd(softs, acp, reason);
4351382c8bcaSpl }
4352382c8bcaSpl
4353382c8bcaSpl /* b) commands in the waiting queues */
4354382c8bcaSpl for (i = 0; i < AAC_CMDQ_NUM; i++) {
4355382c8bcaSpl if (iocmd & (1 << i)) {
4356382c8bcaSpl if (ac_arg) {
4357382c8bcaSpl aac_abort_iocmd(softs, ac_arg, reason);
4358832e0b5aSpl } else {
4359382c8bcaSpl while ((acp = softs->q_wait[i].q_head) != NULL)
4360382c8bcaSpl aac_abort_iocmd(softs, acp, reason);
4361832e0b5aSpl }
4362832e0b5aSpl }
4363832e0b5aSpl }
4364382c8bcaSpl }
4365830d82f7Spl
4366382c8bcaSpl /*
4367382c8bcaSpl * The draining thread is shared among quiesce threads. It terminates
4368382c8bcaSpl * when the adapter is quiesced or stopped by aac_stop_drain().
4369382c8bcaSpl */
4370382c8bcaSpl static void
aac_check_drain(void * arg)4371382c8bcaSpl aac_check_drain(void *arg)
4372382c8bcaSpl {
4373382c8bcaSpl struct aac_softstate *softs = arg;
4374832e0b5aSpl
4375382c8bcaSpl mutex_enter(&softs->io_lock);
4376382c8bcaSpl if (softs->ndrains) {
437758bc78c7SXin Chen softs->drain_timeid = 0;
4378382c8bcaSpl /*
4379382c8bcaSpl * If both ASYNC and SYNC bus throttle are held,
4380382c8bcaSpl * wake up threads only when both are drained out.
4381382c8bcaSpl */
4382382c8bcaSpl if ((softs->bus_throttle[AAC_CMDQ_ASYNC] > 0 ||
4383382c8bcaSpl softs->bus_ncmds[AAC_CMDQ_ASYNC] == 0) &&
4384382c8bcaSpl (softs->bus_throttle[AAC_CMDQ_SYNC] > 0 ||
4385382c8bcaSpl softs->bus_ncmds[AAC_CMDQ_SYNC] == 0))
4386382c8bcaSpl cv_broadcast(&softs->drain_cv);
4387382c8bcaSpl else
4388382c8bcaSpl softs->drain_timeid = timeout(aac_check_drain, softs,
4389382c8bcaSpl AAC_QUIESCE_TICK * drv_usectohz(1000000));
4390832e0b5aSpl }
4391382c8bcaSpl mutex_exit(&softs->io_lock);
4392382c8bcaSpl }
4393832e0b5aSpl
4394382c8bcaSpl /*
4395382c8bcaSpl * If not draining the outstanding cmds, drain them. Otherwise,
4396382c8bcaSpl * only update ndrains.
4397382c8bcaSpl */
4398382c8bcaSpl static void
aac_start_drain(struct aac_softstate * softs)4399382c8bcaSpl aac_start_drain(struct aac_softstate *softs)
4400382c8bcaSpl {
4401382c8bcaSpl if (softs->ndrains == 0) {
440258bc78c7SXin Chen ASSERT(softs->drain_timeid == 0);
4403382c8bcaSpl softs->drain_timeid = timeout(aac_check_drain, softs,
4404382c8bcaSpl AAC_QUIESCE_TICK * drv_usectohz(1000000));
4405382c8bcaSpl }
4406382c8bcaSpl softs->ndrains++;
4407382c8bcaSpl }
4408832e0b5aSpl
4409382c8bcaSpl /*
4410382c8bcaSpl * Stop the draining thread when no other threads use it any longer.
4411382c8bcaSpl * Side effect: io_lock may be released in the middle.
4412382c8bcaSpl */
4413382c8bcaSpl static void
aac_stop_drain(struct aac_softstate * softs)4414382c8bcaSpl aac_stop_drain(struct aac_softstate *softs)
4415382c8bcaSpl {
4416382c8bcaSpl softs->ndrains--;
4417382c8bcaSpl if (softs->ndrains == 0) {
4418382c8bcaSpl if (softs->drain_timeid != 0) {
4419382c8bcaSpl timeout_id_t tid = softs->drain_timeid;
4420382c8bcaSpl
4421382c8bcaSpl softs->drain_timeid = 0;
4422382c8bcaSpl mutex_exit(&softs->io_lock);
4423382c8bcaSpl (void) untimeout(tid);
4424382c8bcaSpl mutex_enter(&softs->io_lock);
4425830d82f7Spl }
4426830d82f7Spl }
4427830d82f7Spl }
4428830d82f7Spl
4429830d82f7Spl /*
4430830d82f7Spl * The following function comes from Adaptec:
44317c478bd9Sstevel@tonic-gate *
4432830d82f7Spl * Once do an IOP reset, basically the driver have to re-initialize the card
4433830d82f7Spl * as if up from a cold boot, and the driver is responsible for any IO that
4434830d82f7Spl * is outstanding to the adapter at the time of the IOP RESET. And prepare
4435830d82f7Spl * for IOP RESET by making the init code modular with the ability to call it
4436830d82f7Spl * from multiple places.
44377c478bd9Sstevel@tonic-gate */
4438830d82f7Spl static int
aac_reset_adapter(struct aac_softstate * softs)4439830d82f7Spl aac_reset_adapter(struct aac_softstate *softs)
4440830d82f7Spl {
4441830d82f7Spl int health;
4442830d82f7Spl uint32_t status;
444358bc78c7SXin Chen int rval = AAC_IOP_RESET_FAILED;
4444830d82f7Spl
44451dd0a2dbSpl DBCALLED(softs, 1);
4446830d82f7Spl
4447382c8bcaSpl ASSERT(softs->state & AAC_STATE_RESET);
4448830d82f7Spl
44497675db54Syw ddi_fm_acc_err_clear(softs->pci_mem_handle, DDI_FME_VER0);
4450830d82f7Spl /* Disable interrupt */
4451830d82f7Spl AAC_DISABLE_INTR(softs);
4452830d82f7Spl
4453830d82f7Spl health = aac_check_adapter_health(softs);
44547675db54Syw if (health == -1) {
44557675db54Syw ddi_fm_service_impact(softs->devinfo_p, DDI_SERVICE_LOST);
4456830d82f7Spl goto finish;
44577675db54Syw }
4458830d82f7Spl if (health == 0) /* flush drives if possible */
4459830d82f7Spl (void) aac_shutdown(softs);
4460830d82f7Spl
4461830d82f7Spl /* Execute IOP reset */
4462c9487164Spl if ((aac_sync_mbcommand(softs, AAC_IOP_RESET, 0, 0, 0, 0,
4463c9487164Spl &status)) != AACOK) {
4464f42c2f53Szhongyan gu - Sun Microsystems - Beijing China ddi_acc_handle_t acc;
4465c9487164Spl struct aac_fib *fibp;
4466830d82f7Spl struct aac_pause_command *pc;
4467830d82f7Spl
4468382c8bcaSpl if ((status & 0xf) == 0xf) {
4469382c8bcaSpl uint32_t wait_count;
4470830d82f7Spl
4471382c8bcaSpl /*
4472382c8bcaSpl * Sunrise Lake has dual cores and we must drag the
4473382c8bcaSpl * other core with us to reset simultaneously. There
4474382c8bcaSpl * are 2 bits in the Inbound Reset Control and Status
4475382c8bcaSpl * Register (offset 0x38) of the Sunrise Lake to reset
4476382c8bcaSpl * the chip without clearing out the PCI configuration
4477382c8bcaSpl * info (COMMAND & BARS).
4478382c8bcaSpl */
4479382c8bcaSpl PCI_MEM_PUT32(softs, AAC_IRCSR, AAC_IRCSR_CORES_RST);
4480382c8bcaSpl
4481382c8bcaSpl /*
4482382c8bcaSpl * We need to wait for 5 seconds before accessing the MU
4483382c8bcaSpl * again 10000 * 100us = 1000,000us = 1000ms = 1s
4484382c8bcaSpl */
4485382c8bcaSpl wait_count = 5 * 10000;
4486382c8bcaSpl while (wait_count) {
4487382c8bcaSpl drv_usecwait(100); /* delay 100 microseconds */
4488382c8bcaSpl wait_count--;
4489382c8bcaSpl }
4490382c8bcaSpl } else {
4491382c8bcaSpl if (status == SRB_STATUS_INVALID_REQUEST)
4492382c8bcaSpl cmn_err(CE_WARN, "!IOP_RESET not supported");
4493382c8bcaSpl else /* probably timeout */
4494382c8bcaSpl cmn_err(CE_WARN, "!IOP_RESET failed");
4495382c8bcaSpl
4496382c8bcaSpl /* Unwind aac_shutdown() */
4497f42c2f53Szhongyan gu - Sun Microsystems - Beijing China (void) aac_sync_fib_slot_bind(softs, &softs->sync_ac);
4498f42c2f53Szhongyan gu - Sun Microsystems - Beijing China acc = softs->sync_ac.slotp->fib_acc_handle;
4499f42c2f53Szhongyan gu - Sun Microsystems - Beijing China
4500f42c2f53Szhongyan gu - Sun Microsystems - Beijing China fibp = softs->sync_ac.slotp->fibp;
4501382c8bcaSpl pc = (struct aac_pause_command *)&fibp->data[0];
4502382c8bcaSpl
4503382c8bcaSpl bzero(pc, sizeof (*pc));
4504942c5e3cSpl ddi_put32(acc, &pc->Command, VM_ContainerConfig);
4505942c5e3cSpl ddi_put32(acc, &pc->Type, CT_PAUSE_IO);
4506942c5e3cSpl ddi_put32(acc, &pc->Timeout, 1);
4507942c5e3cSpl ddi_put32(acc, &pc->Min, 1);
4508942c5e3cSpl ddi_put32(acc, &pc->NoRescan, 1);
4509382c8bcaSpl
4510942c5e3cSpl (void) aac_sync_fib(softs, ContainerCommand,
4511942c5e3cSpl AAC_FIB_SIZEOF(struct aac_pause_command));
4512f42c2f53Szhongyan gu - Sun Microsystems - Beijing China aac_sync_fib_slot_release(softs, &softs->sync_ac);
4513382c8bcaSpl
451458bc78c7SXin Chen if (aac_check_adapter_health(softs) != 0)
451558bc78c7SXin Chen ddi_fm_service_impact(softs->devinfo_p,
451658bc78c7SXin Chen DDI_SERVICE_LOST);
451758bc78c7SXin Chen else
451858bc78c7SXin Chen /*
451958bc78c7SXin Chen * IOP reset not supported or IOP not reseted
452058bc78c7SXin Chen */
452158bc78c7SXin Chen rval = AAC_IOP_RESET_ABNORMAL;
4522382c8bcaSpl goto finish;
4523382c8bcaSpl }
4524830d82f7Spl }
4525830d82f7Spl
4526830d82f7Spl /*
4527830d82f7Spl * Re-read and renegotiate the FIB parameters, as one of the actions
4528830d82f7Spl * that can result from an IOP reset is the running of a new firmware
4529830d82f7Spl * image.
4530830d82f7Spl */
4531830d82f7Spl if (aac_common_attach(softs) != AACOK)
4532830d82f7Spl goto finish;
4533830d82f7Spl
453458bc78c7SXin Chen rval = AAC_IOP_RESET_SUCCEED;
4535830d82f7Spl
4536830d82f7Spl finish:
4537830d82f7Spl AAC_ENABLE_INTR(softs);
4538830d82f7Spl return (rval);
4539830d82f7Spl }
4540830d82f7Spl
4541382c8bcaSpl static void
aac_set_throttle(struct aac_softstate * softs,struct aac_device * dvp,int q,int throttle)454258bc78c7SXin Chen aac_set_throttle(struct aac_softstate *softs, struct aac_device *dvp, int q,
4543382c8bcaSpl int throttle)
4544382c8bcaSpl {
4545382c8bcaSpl /*
4546382c8bcaSpl * If the bus is draining/quiesced, no changes to the throttles
4547382c8bcaSpl * are allowed. All throttles should have been set to 0.
4548382c8bcaSpl */
4549382c8bcaSpl if ((softs->state & AAC_STATE_QUIESCED) || softs->ndrains)
4550382c8bcaSpl return;
4551382c8bcaSpl dvp->throttle[q] = throttle;
4552382c8bcaSpl }
4553382c8bcaSpl
4554382c8bcaSpl static void
aac_hold_bus(struct aac_softstate * softs,int iocmds)4555382c8bcaSpl aac_hold_bus(struct aac_softstate *softs, int iocmds)
4556382c8bcaSpl {
4557382c8bcaSpl int i, q;
4558382c8bcaSpl
4559382c8bcaSpl /* Hold bus by holding every device on the bus */
4560382c8bcaSpl for (q = 0; q < AAC_CMDQ_NUM; q++) {
4561382c8bcaSpl if (iocmds & (1 << q)) {
4562382c8bcaSpl softs->bus_throttle[q] = 0;
4563382c8bcaSpl for (i = 0; i < AAC_MAX_LD; i++)
456458bc78c7SXin Chen aac_set_throttle(softs,
456558bc78c7SXin Chen &softs->containers[i].dev, q, 0);
456658bc78c7SXin Chen for (i = 0; i < AAC_MAX_PD(softs); i++)
456758bc78c7SXin Chen aac_set_throttle(softs,
456858bc78c7SXin Chen &softs->nondasds[i].dev, q, 0);
4569382c8bcaSpl }
4570382c8bcaSpl }
4571382c8bcaSpl }
4572382c8bcaSpl
4573382c8bcaSpl static void
aac_unhold_bus(struct aac_softstate * softs,int iocmds)4574382c8bcaSpl aac_unhold_bus(struct aac_softstate *softs, int iocmds)
4575382c8bcaSpl {
4576f42c2f53Szhongyan gu - Sun Microsystems - Beijing China int i, q, max_throttle;
4577382c8bcaSpl
4578382c8bcaSpl for (q = 0; q < AAC_CMDQ_NUM; q++) {
4579382c8bcaSpl if (iocmds & (1 << q)) {
4580382c8bcaSpl /*
4581382c8bcaSpl * Should not unhold AAC_IOCMD_ASYNC bus, if it has been
4582382c8bcaSpl * quiesced or being drained by possibly some quiesce
4583382c8bcaSpl * threads.
4584382c8bcaSpl */
4585382c8bcaSpl if (q == AAC_CMDQ_ASYNC && ((softs->state &
4586382c8bcaSpl AAC_STATE_QUIESCED) || softs->ndrains))
4587382c8bcaSpl continue;
4588f42c2f53Szhongyan gu - Sun Microsystems - Beijing China if (q == AAC_CMDQ_ASYNC)
4589f42c2f53Szhongyan gu - Sun Microsystems - Beijing China max_throttle = softs->total_slots -
4590f42c2f53Szhongyan gu - Sun Microsystems - Beijing China AAC_MGT_SLOT_NUM;
4591f42c2f53Szhongyan gu - Sun Microsystems - Beijing China else
4592f42c2f53Szhongyan gu - Sun Microsystems - Beijing China max_throttle = softs->total_slots - 1;
4593f42c2f53Szhongyan gu - Sun Microsystems - Beijing China softs->bus_throttle[q] = max_throttle;
4594382c8bcaSpl for (i = 0; i < AAC_MAX_LD; i++)
459558bc78c7SXin Chen aac_set_throttle(softs,
459658bc78c7SXin Chen &softs->containers[i].dev,
4597f42c2f53Szhongyan gu - Sun Microsystems - Beijing China q, max_throttle);
459858bc78c7SXin Chen for (i = 0; i < AAC_MAX_PD(softs); i++)
459958bc78c7SXin Chen aac_set_throttle(softs, &softs->nondasds[i].dev,
4600f42c2f53Szhongyan gu - Sun Microsystems - Beijing China q, max_throttle);
4601382c8bcaSpl }
4602382c8bcaSpl }
4603382c8bcaSpl }
4604382c8bcaSpl
4605830d82f7Spl static int
aac_do_reset(struct aac_softstate * softs)4606830d82f7Spl aac_do_reset(struct aac_softstate *softs)
4607830d82f7Spl {
4608382c8bcaSpl int health;
4609382c8bcaSpl int rval;
4610830d82f7Spl
4611382c8bcaSpl softs->state |= AAC_STATE_RESET;
4612382c8bcaSpl health = aac_check_adapter_health(softs);
4613830d82f7Spl
4614830d82f7Spl /*
4615382c8bcaSpl * Hold off new io commands and wait all outstanding io
4616382c8bcaSpl * commands to complete.
4617830d82f7Spl */
461858bc78c7SXin Chen if (health == 0) {
461958bc78c7SXin Chen int sync_cmds = softs->bus_ncmds[AAC_CMDQ_SYNC];
462058bc78c7SXin Chen int async_cmds = softs->bus_ncmds[AAC_CMDQ_ASYNC];
462158bc78c7SXin Chen
462258bc78c7SXin Chen if (sync_cmds == 0 && async_cmds == 0) {
462358bc78c7SXin Chen rval = AAC_IOP_RESET_SUCCEED;
462458bc78c7SXin Chen goto finish;
462558bc78c7SXin Chen }
4626382c8bcaSpl /*
4627382c8bcaSpl * Give the adapter up to AAC_QUIESCE_TIMEOUT more seconds
4628382c8bcaSpl * to complete the outstanding io commands
4629382c8bcaSpl */
4630382c8bcaSpl int timeout = AAC_QUIESCE_TIMEOUT * 1000 * 10;
4631382c8bcaSpl int (*intr_handler)(struct aac_softstate *);
4632382c8bcaSpl
4633382c8bcaSpl aac_hold_bus(softs, AAC_IOCMD_SYNC | AAC_IOCMD_ASYNC);
4634382c8bcaSpl /*
4635382c8bcaSpl * Poll the adapter by ourselves in case interrupt is disabled
4636382c8bcaSpl * and to avoid releasing the io_lock.
4637382c8bcaSpl */
4638382c8bcaSpl intr_handler = (softs->flags & AAC_FLAGS_NEW_COMM) ?
4639382c8bcaSpl aac_process_intr_new : aac_process_intr_old;
4640382c8bcaSpl while ((softs->bus_ncmds[AAC_CMDQ_SYNC] ||
4641382c8bcaSpl softs->bus_ncmds[AAC_CMDQ_ASYNC]) && timeout) {
4642382c8bcaSpl drv_usecwait(100);
4643382c8bcaSpl (void) intr_handler(softs);
4644382c8bcaSpl timeout--;
4645382c8bcaSpl }
4646382c8bcaSpl aac_unhold_bus(softs, AAC_IOCMD_SYNC | AAC_IOCMD_ASYNC);
464758bc78c7SXin Chen
464858bc78c7SXin Chen if (softs->bus_ncmds[AAC_CMDQ_SYNC] == 0 &&
464958bc78c7SXin Chen softs->bus_ncmds[AAC_CMDQ_ASYNC] == 0) {
465058bc78c7SXin Chen /* Cmds drained out */
465158bc78c7SXin Chen rval = AAC_IOP_RESET_SUCCEED;
465258bc78c7SXin Chen goto finish;
465358bc78c7SXin Chen } else if (softs->bus_ncmds[AAC_CMDQ_SYNC] < sync_cmds ||
465458bc78c7SXin Chen softs->bus_ncmds[AAC_CMDQ_ASYNC] < async_cmds) {
465558bc78c7SXin Chen /* Cmds not drained out, adapter overloaded */
465658bc78c7SXin Chen rval = AAC_IOP_RESET_ABNORMAL;
465758bc78c7SXin Chen goto finish;
465858bc78c7SXin Chen }
4659832e0b5aSpl }
4660830d82f7Spl
4661382c8bcaSpl /*
466258bc78c7SXin Chen * If a longer waiting time still can't drain any outstanding io
4663382c8bcaSpl * commands, do IOP reset.
4664382c8bcaSpl */
466558bc78c7SXin Chen if ((rval = aac_reset_adapter(softs)) == AAC_IOP_RESET_FAILED)
466658bc78c7SXin Chen softs->state |= AAC_STATE_DEAD;
4667830d82f7Spl
466858bc78c7SXin Chen finish:
4669382c8bcaSpl softs->state &= ~AAC_STATE_RESET;
4670c9487164Spl return (rval);
4671830d82f7Spl }
4672830d82f7Spl
46737c478bd9Sstevel@tonic-gate static int
aac_tran_reset(struct scsi_address * ap,int level)46747c478bd9Sstevel@tonic-gate aac_tran_reset(struct scsi_address *ap, int level)
46757c478bd9Sstevel@tonic-gate {
4676c9487164Spl struct aac_softstate *softs = AAC_TRAN2SOFTS(ap->a_hba_tran);
4677382c8bcaSpl int rval;
46787c478bd9Sstevel@tonic-gate
46791dd0a2dbSpl DBCALLED(softs, 1);
4680830d82f7Spl
4681830d82f7Spl if (level != RESET_ALL) {
4682830d82f7Spl cmn_err(CE_NOTE, "!reset target/lun not supported");
4683830d82f7Spl return (0);
4684830d82f7Spl }
4685830d82f7Spl
4686382c8bcaSpl mutex_enter(&softs->io_lock);
468758bc78c7SXin Chen switch (rval = aac_do_reset(softs)) {
468858bc78c7SXin Chen case AAC_IOP_RESET_SUCCEED:
4689382c8bcaSpl aac_abort_iocmds(softs, AAC_IOCMD_OUTSTANDING | AAC_IOCMD_ASYNC,
4690382c8bcaSpl NULL, CMD_RESET);
4691382c8bcaSpl aac_start_waiting_io(softs);
469258bc78c7SXin Chen break;
469358bc78c7SXin Chen case AAC_IOP_RESET_FAILED:
469458bc78c7SXin Chen /* Abort IOCTL cmds when adapter is dead */
4695382c8bcaSpl aac_abort_iocmds(softs, AAC_IOCMD_ALL, NULL, CMD_RESET);
469658bc78c7SXin Chen break;
469758bc78c7SXin Chen case AAC_IOP_RESET_ABNORMAL:
469858bc78c7SXin Chen aac_start_waiting_io(softs);
4699382c8bcaSpl }
4700382c8bcaSpl mutex_exit(&softs->io_lock);
4701830d82f7Spl
4702382c8bcaSpl aac_drain_comp_q(softs);
470358bc78c7SXin Chen return (rval == 0);
47047c478bd9Sstevel@tonic-gate }
47057c478bd9Sstevel@tonic-gate
4706830d82f7Spl static int
aac_tran_abort(struct scsi_address * ap,struct scsi_pkt * pkt)4707830d82f7Spl aac_tran_abort(struct scsi_address *ap, struct scsi_pkt *pkt)
47087c478bd9Sstevel@tonic-gate {
4709c9487164Spl struct aac_softstate *softs = AAC_TRAN2SOFTS(ap->a_hba_tran);
47107c478bd9Sstevel@tonic-gate
47111dd0a2dbSpl DBCALLED(softs, 1);
4712830d82f7Spl
4713382c8bcaSpl mutex_enter(&softs->io_lock);
4714382c8bcaSpl aac_abort_iocmds(softs, 0, pkt, CMD_ABORTED);
4715382c8bcaSpl mutex_exit(&softs->io_lock);
4716830d82f7Spl
4717382c8bcaSpl aac_drain_comp_q(softs);
4718830d82f7Spl return (1);
47197c478bd9Sstevel@tonic-gate }
47207c478bd9Sstevel@tonic-gate
4721d7c5bf88Spl void
aac_free_dmamap(struct aac_cmd * acp)4722c9487164Spl aac_free_dmamap(struct aac_cmd *acp)
47237c478bd9Sstevel@tonic-gate {
4724830d82f7Spl /* Free dma mapping */
4725c9487164Spl if (acp->flags & AAC_CMD_DMA_VALID) {
4726c9487164Spl ASSERT(acp->buf_dma_handle);
4727c9487164Spl (void) ddi_dma_unbind_handle(acp->buf_dma_handle);
4728c9487164Spl acp->flags &= ~AAC_CMD_DMA_VALID;
4729832e0b5aSpl }
4730832e0b5aSpl
4731c9487164Spl if (acp->abp != NULL) { /* free non-aligned buf DMA */
4732c9487164Spl ASSERT(acp->buf_dma_handle);
4733d7c5bf88Spl if ((acp->flags & AAC_CMD_BUF_WRITE) == 0 && acp->bp)
4734d7c5bf88Spl ddi_rep_get8(acp->abh, (uint8_t *)acp->bp->b_un.b_addr,
4735d7c5bf88Spl (uint8_t *)acp->abp, acp->bp->b_bcount,
4736d7c5bf88Spl DDI_DEV_AUTOINCR);
4737c9487164Spl ddi_dma_mem_free(&acp->abh);
4738c9487164Spl acp->abp = NULL;
4739832e0b5aSpl }
4740832e0b5aSpl
4741c9487164Spl if (acp->buf_dma_handle) {
4742c9487164Spl ddi_dma_free_handle(&acp->buf_dma_handle);
4743c9487164Spl acp->buf_dma_handle = NULL;
47447c478bd9Sstevel@tonic-gate }
47457c478bd9Sstevel@tonic-gate }
47467c478bd9Sstevel@tonic-gate
4747382c8bcaSpl static void
aac_unknown_scmd(struct aac_softstate * softs,struct aac_cmd * acp)4748382c8bcaSpl aac_unknown_scmd(struct aac_softstate *softs, struct aac_cmd *acp)
4749382c8bcaSpl {
4750382c8bcaSpl AACDB_PRINT(softs, CE_CONT, "SCMD 0x%x not supported",
4751a74f7440Spl ((union scsi_cdb *)(void *)acp->pkt->pkt_cdbp)->scc_cmd);
4752382c8bcaSpl aac_free_dmamap(acp);
4753382c8bcaSpl aac_set_arq_data(acp->pkt, KEY_ILLEGAL_REQUEST, 0x20, 0x00, 0);
4754382c8bcaSpl aac_soft_callback(softs, acp);
4755382c8bcaSpl }
4756382c8bcaSpl
4757382c8bcaSpl /*
4758382c8bcaSpl * Handle command to logical device
4759382c8bcaSpl */
47607c478bd9Sstevel@tonic-gate static int
aac_tran_start_ld(struct aac_softstate * softs,struct aac_cmd * acp)4761382c8bcaSpl aac_tran_start_ld(struct aac_softstate *softs, struct aac_cmd *acp)
47627c478bd9Sstevel@tonic-gate {
4763382c8bcaSpl struct aac_container *dvp;
4764382c8bcaSpl struct scsi_pkt *pkt;
47657c478bd9Sstevel@tonic-gate union scsi_cdb *cdbp;
4766c9487164Spl struct buf *bp;
4767c9487164Spl int rval;
4768830d82f7Spl
476958bc78c7SXin Chen dvp = (struct aac_container *)acp->dvp;
4770382c8bcaSpl pkt = acp->pkt;
4771a74f7440Spl cdbp = (void *)pkt->pkt_cdbp;
4772d7c5bf88Spl bp = acp->bp;
4773d7c5bf88Spl
4774382c8bcaSpl switch (cdbp->scc_cmd) {
4775830d82f7Spl case SCMD_INQUIRY: /* inquiry */
4776c9487164Spl aac_free_dmamap(acp);
4777830d82f7Spl aac_inquiry(softs, pkt, cdbp, bp);
4778d7c5bf88Spl aac_soft_callback(softs, acp);
4779c9487164Spl rval = TRAN_ACCEPT;
4780830d82f7Spl break;
47817c478bd9Sstevel@tonic-gate
4782830d82f7Spl case SCMD_READ_CAPACITY: /* read capacity */
4783830d82f7Spl if (bp && bp->b_un.b_addr && bp->b_bcount) {
4784830d82f7Spl struct scsi_capacity cap;
4785832e0b5aSpl uint64_t last_lba;
47867c478bd9Sstevel@tonic-gate
4787830d82f7Spl /* check 64-bit LBA */
4788382c8bcaSpl last_lba = dvp->size - 1;
4789832e0b5aSpl if (last_lba > 0xffffffffull) {
4790c9487164Spl cap.capacity = 0xfffffffful;
4791832e0b5aSpl } else {
4792832e0b5aSpl cap.capacity = BE_32(last_lba);
4793832e0b5aSpl }
4794830d82f7Spl cap.lbasize = BE_32(AAC_SECTOR_SIZE);
4795830d82f7Spl
4796c9487164Spl aac_free_dmamap(acp);
4797d937e6ebSpl if (bp->b_flags & (B_PHYS|B_PAGEIO))
4798830d82f7Spl bp_mapin(bp);
479951ccf66eSjd bcopy(&cap, bp->b_un.b_addr, min(bp->b_bcount, 8));
4800830d82f7Spl pkt->pkt_state |= STATE_XFERRED_DATA;
4801830d82f7Spl }
4802d7c5bf88Spl aac_soft_callback(softs, acp);
4803c9487164Spl rval = TRAN_ACCEPT;
4804830d82f7Spl break;
4805830d82f7Spl
4806830d82f7Spl case SCMD_SVC_ACTION_IN_G4: /* read capacity 16 */
4807830d82f7Spl /* Check if containers need 64-bit LBA support */
4808382c8bcaSpl if (cdbp->cdb_opaque[1] == SSVC_ACTION_READ_CAPACITY_G4) {
4809382c8bcaSpl if (bp && bp->b_un.b_addr && bp->b_bcount) {
4810382c8bcaSpl struct scsi_capacity_16 cap16;
4811382c8bcaSpl int cap_len = sizeof (struct scsi_capacity_16);
4812382c8bcaSpl
4813382c8bcaSpl bzero(&cap16, cap_len);
4814b6094a86Sjd cap16.sc_capacity = BE_64(dvp->size - 1);
4815382c8bcaSpl cap16.sc_lbasize = BE_32(AAC_SECTOR_SIZE);
4816382c8bcaSpl
4817382c8bcaSpl aac_free_dmamap(acp);
4818382c8bcaSpl if (bp->b_flags & (B_PHYS | B_PAGEIO))
4819382c8bcaSpl bp_mapin(bp);
482051ccf66eSjd bcopy(&cap16, bp->b_un.b_addr,
482151ccf66eSjd min(bp->b_bcount, cap_len));
4822382c8bcaSpl pkt->pkt_state |= STATE_XFERRED_DATA;
4823382c8bcaSpl }
4824382c8bcaSpl aac_soft_callback(softs, acp);
4825382c8bcaSpl } else {
4826382c8bcaSpl aac_unknown_scmd(softs, acp);
4827830d82f7Spl }
4828c9487164Spl rval = TRAN_ACCEPT;
4829830d82f7Spl break;
4830830d82f7Spl
4831830d82f7Spl case SCMD_READ_G4: /* read_16 */
4832830d82f7Spl case SCMD_WRITE_G4: /* write_16 */
4833d7c5bf88Spl if (softs->flags & AAC_FLAGS_RAW_IO) {
4834d7c5bf88Spl /* NOTE: GETG4ADDRTL(cdbp) is int32_t */
4835d7c5bf88Spl acp->blkno = ((uint64_t) \
4836d7c5bf88Spl GETG4ADDR(cdbp) << 32) | \
4837d7c5bf88Spl (uint32_t)GETG4ADDRTL(cdbp);
4838d7c5bf88Spl goto do_io;
4839830d82f7Spl }
4840d7c5bf88Spl AACDB_PRINT(softs, CE_WARN, "64-bit LBA not supported");
4841382c8bcaSpl aac_unknown_scmd(softs, acp);
4842382c8bcaSpl rval = TRAN_ACCEPT;
4843382c8bcaSpl break;
4844830d82f7Spl
4845830d82f7Spl case SCMD_READ: /* read_6 */
4846830d82f7Spl case SCMD_WRITE: /* write_6 */
4847d7c5bf88Spl acp->blkno = GETG0ADDR(cdbp);
4848d7c5bf88Spl goto do_io;
4849c9487164Spl
485058bc78c7SXin Chen case SCMD_READ_G5: /* read_12 */
485158bc78c7SXin Chen case SCMD_WRITE_G5: /* write_12 */
485258bc78c7SXin Chen acp->blkno = GETG5ADDR(cdbp);
485358bc78c7SXin Chen goto do_io;
485458bc78c7SXin Chen
4855d7c5bf88Spl case SCMD_READ_G1: /* read_10 */
4856d7c5bf88Spl case SCMD_WRITE_G1: /* write_10 */
4857d7c5bf88Spl acp->blkno = (uint32_t)GETG1ADDR(cdbp);
4858d7c5bf88Spl do_io:
4859d7c5bf88Spl if (acp->flags & AAC_CMD_DMA_VALID) {
4860942c5e3cSpl uint64_t cnt_size = dvp->size;
4861c9487164Spl
4862d7c5bf88Spl /*
4863d7c5bf88Spl * If LBA > array size AND rawio, the
4864d7c5bf88Spl * adapter may hang. So check it before
4865d7c5bf88Spl * sending.
4866d7c5bf88Spl * NOTE: (blkno + blkcnt) may overflow
4867d7c5bf88Spl */
4868d7c5bf88Spl if ((acp->blkno < cnt_size) &&
4869d7c5bf88Spl ((acp->blkno + acp->bcount /
4870d7c5bf88Spl AAC_BLK_SIZE) <= cnt_size)) {
4871d7c5bf88Spl rval = aac_do_io(softs, acp);
4872830d82f7Spl } else {
4873830d82f7Spl /*
4874d7c5bf88Spl * Request exceeds the capacity of disk,
4875d7c5bf88Spl * set error block number to last LBA
4876d7c5bf88Spl * + 1.
4877830d82f7Spl */
4878d7c5bf88Spl aac_set_arq_data(pkt,
4879d7c5bf88Spl KEY_ILLEGAL_REQUEST, 0x21,
4880d7c5bf88Spl 0x00, cnt_size);
4881d7c5bf88Spl aac_soft_callback(softs, acp);
4882c9487164Spl rval = TRAN_ACCEPT;
4883c9487164Spl }
4884d7c5bf88Spl } else if (acp->bcount == 0) {
4885d7c5bf88Spl /* For 0 length IO, just return ok */
4886d7c5bf88Spl aac_soft_callback(softs, acp);
4887d7c5bf88Spl rval = TRAN_ACCEPT;
4888830d82f7Spl } else {
4889d7c5bf88Spl rval = TRAN_BADPKT;
4890830d82f7Spl }
4891830d82f7Spl break;
4892830d82f7Spl
4893830d82f7Spl case SCMD_MODE_SENSE: /* mode_sense_6 */
4894d7c5bf88Spl case SCMD_MODE_SENSE_G1: { /* mode_sense_10 */
4895d7c5bf88Spl int capacity;
4896d7c5bf88Spl
4897c9487164Spl aac_free_dmamap(acp);
4898382c8bcaSpl if (dvp->size > 0xffffffffull)
4899c9487164Spl capacity = 0xfffffffful; /* 64-bit LBA */
4900830d82f7Spl else
4901382c8bcaSpl capacity = dvp->size;
4902830d82f7Spl aac_mode_sense(softs, pkt, cdbp, bp, capacity);
4903d7c5bf88Spl aac_soft_callback(softs, acp);
4904c9487164Spl rval = TRAN_ACCEPT;
4905830d82f7Spl break;
4906d7c5bf88Spl }
4907830d82f7Spl
4908b40e8a89Szhongyan gu - Sun Microsystems - Beijing China case SCMD_START_STOP:
4909b40e8a89Szhongyan gu - Sun Microsystems - Beijing China if (softs->support_opt2 & AAC_SUPPORTED_POWER_MANAGEMENT) {
4910b40e8a89Szhongyan gu - Sun Microsystems - Beijing China acp->aac_cmd_fib = aac_cmd_fib_startstop;
4911b40e8a89Szhongyan gu - Sun Microsystems - Beijing China acp->ac_comp = aac_startstop_complete;
4912b40e8a89Szhongyan gu - Sun Microsystems - Beijing China rval = aac_do_io(softs, acp);
4913b40e8a89Szhongyan gu - Sun Microsystems - Beijing China break;
4914b40e8a89Szhongyan gu - Sun Microsystems - Beijing China }
4915b40e8a89Szhongyan gu - Sun Microsystems - Beijing China /* FALLTHRU */
4916830d82f7Spl case SCMD_TEST_UNIT_READY:
4917830d82f7Spl case SCMD_REQUEST_SENSE:
4918830d82f7Spl case SCMD_FORMAT:
4919c9487164Spl aac_free_dmamap(acp);
4920830d82f7Spl if (bp && bp->b_un.b_addr && bp->b_bcount) {
4921c9487164Spl if (acp->flags & AAC_CMD_BUF_READ) {
4922830d82f7Spl if (bp->b_flags & (B_PHYS|B_PAGEIO))
4923830d82f7Spl bp_mapin(bp);
4924830d82f7Spl bzero(bp->b_un.b_addr, bp->b_bcount);
4925830d82f7Spl }
4926830d82f7Spl pkt->pkt_state |= STATE_XFERRED_DATA;
4927830d82f7Spl }
4928d7c5bf88Spl aac_soft_callback(softs, acp);
4929c9487164Spl rval = TRAN_ACCEPT;
4930830d82f7Spl break;
4931830d82f7Spl
4932942c5e3cSpl case SCMD_SYNCHRONIZE_CACHE:
4933382c8bcaSpl acp->flags |= AAC_CMD_NTAG;
4934942c5e3cSpl acp->aac_cmd_fib = aac_cmd_fib_sync;
4935382c8bcaSpl acp->ac_comp = aac_synccache_complete;
4936382c8bcaSpl rval = aac_do_io(softs, acp);
4937382c8bcaSpl break;
4938382c8bcaSpl
4939830d82f7Spl case SCMD_DOORLOCK:
4940c9487164Spl aac_free_dmamap(acp);
4941942c5e3cSpl dvp->locked = (pkt->pkt_cdbp[4] & 0x01) ? 1 : 0;
4942d7c5bf88Spl aac_soft_callback(softs, acp);
4943c9487164Spl rval = TRAN_ACCEPT;
4944830d82f7Spl break;
4945830d82f7Spl
4946830d82f7Spl default: /* unknown command */
4947382c8bcaSpl aac_unknown_scmd(softs, acp);
4948c9487164Spl rval = TRAN_ACCEPT;
4949830d82f7Spl break;
49507c478bd9Sstevel@tonic-gate }
49517c478bd9Sstevel@tonic-gate
4952382c8bcaSpl return (rval);
4953382c8bcaSpl }
4954382c8bcaSpl
4955382c8bcaSpl static int
aac_tran_start(struct scsi_address * ap,struct scsi_pkt * pkt)4956382c8bcaSpl aac_tran_start(struct scsi_address *ap, struct scsi_pkt *pkt)
4957382c8bcaSpl {
4958382c8bcaSpl struct aac_softstate *softs = AAC_TRAN2SOFTS(ap->a_hba_tran);
4959382c8bcaSpl struct aac_cmd *acp = PKT2AC(pkt);
496058bc78c7SXin Chen struct aac_device *dvp = acp->dvp;
4961382c8bcaSpl int rval;
4962382c8bcaSpl
4963382c8bcaSpl DBCALLED(softs, 2);
4964382c8bcaSpl
4965382c8bcaSpl /*
4966382c8bcaSpl * Reinitialize some fields of ac and pkt; the packet may
4967382c8bcaSpl * have been resubmitted
4968382c8bcaSpl */
4969382c8bcaSpl acp->flags &= AAC_CMD_CONSISTENT | AAC_CMD_DMA_PARTIAL | \
4970382c8bcaSpl AAC_CMD_BUF_READ | AAC_CMD_BUF_WRITE | AAC_CMD_DMA_VALID;
4971382c8bcaSpl acp->timeout = acp->pkt->pkt_time;
4972382c8bcaSpl if (pkt->pkt_flags & FLAG_NOINTR)
4973382c8bcaSpl acp->flags |= AAC_CMD_NO_INTR;
497458bc78c7SXin Chen #ifdef DEBUG
497558bc78c7SXin Chen acp->fib_flags = AACDB_FLAGS_FIB_SCMD;
497658bc78c7SXin Chen #endif
4977382c8bcaSpl pkt->pkt_reason = CMD_CMPLT;
4978382c8bcaSpl pkt->pkt_state = 0;
4979382c8bcaSpl pkt->pkt_statistics = 0;
498058bc78c7SXin Chen *pkt->pkt_scbp = STATUS_GOOD; /* clear arq scsi_status */
4981382c8bcaSpl
4982382c8bcaSpl if (acp->flags & AAC_CMD_DMA_VALID) {
4983382c8bcaSpl pkt->pkt_resid = acp->bcount;
4984382c8bcaSpl /* Consistent packets need to be sync'ed first */
4985382c8bcaSpl if ((acp->flags & AAC_CMD_CONSISTENT) &&
4986382c8bcaSpl (acp->flags & AAC_CMD_BUF_WRITE))
4987382c8bcaSpl if (aac_dma_sync_ac(acp) != AACOK) {
4988382c8bcaSpl ddi_fm_service_impact(softs->devinfo_p,
4989382c8bcaSpl DDI_SERVICE_UNAFFECTED);
4990382c8bcaSpl return (TRAN_BADPKT);
4991382c8bcaSpl }
4992382c8bcaSpl } else {
4993382c8bcaSpl pkt->pkt_resid = 0;
4994382c8bcaSpl }
4995382c8bcaSpl
4996382c8bcaSpl mutex_enter(&softs->io_lock);
4997382c8bcaSpl AACDB_PRINT_SCMD(softs, acp);
499858bc78c7SXin Chen if ((dvp->flags & (AAC_DFLAG_VALID | AAC_DFLAG_CONFIGURING)) &&
499958bc78c7SXin Chen !(softs->state & AAC_STATE_DEAD)) {
500058bc78c7SXin Chen if (dvp->type == AAC_DEV_LD) {
500158bc78c7SXin Chen if (ap->a_lun == 0)
500258bc78c7SXin Chen rval = aac_tran_start_ld(softs, acp);
500358bc78c7SXin Chen else
500458bc78c7SXin Chen goto error;
500558bc78c7SXin Chen } else {
500658bc78c7SXin Chen rval = aac_do_io(softs, acp);
500758bc78c7SXin Chen }
5008382c8bcaSpl } else {
500958bc78c7SXin Chen error:
501058bc78c7SXin Chen #ifdef DEBUG
501158bc78c7SXin Chen if (!(softs->state & AAC_STATE_DEAD)) {
501258bc78c7SXin Chen AACDB_PRINT_TRAN(softs,
501358bc78c7SXin Chen "Cannot send cmd to target t%dL%d: %s",
501458bc78c7SXin Chen ap->a_target, ap->a_lun,
501558bc78c7SXin Chen "target invalid");
501658bc78c7SXin Chen } else {
501758bc78c7SXin Chen AACDB_PRINT(softs, CE_WARN,
501858bc78c7SXin Chen "Cannot send cmd to target t%dL%d: %s",
501958bc78c7SXin Chen ap->a_target, ap->a_lun,
502058bc78c7SXin Chen "adapter dead");
502158bc78c7SXin Chen }
502258bc78c7SXin Chen #endif
5023382c8bcaSpl rval = TRAN_FATAL_ERROR;
5024382c8bcaSpl }
5025382c8bcaSpl mutex_exit(&softs->io_lock);
5026c9487164Spl return (rval);
50277c478bd9Sstevel@tonic-gate }
50287c478bd9Sstevel@tonic-gate
50297c478bd9Sstevel@tonic-gate static int
aac_tran_getcap(struct scsi_address * ap,char * cap,int whom)50307c478bd9Sstevel@tonic-gate aac_tran_getcap(struct scsi_address *ap, char *cap, int whom)
50317c478bd9Sstevel@tonic-gate {
5032c9487164Spl struct aac_softstate *softs = AAC_TRAN2SOFTS(ap->a_hba_tran);
503358bc78c7SXin Chen struct aac_device *dvp;
5034c9487164Spl int rval;
50357c478bd9Sstevel@tonic-gate
50361dd0a2dbSpl DBCALLED(softs, 2);
50377c478bd9Sstevel@tonic-gate
50387c478bd9Sstevel@tonic-gate /* We don't allow inquiring about capabilities for other targets */
50397c478bd9Sstevel@tonic-gate if (cap == NULL || whom == 0) {
50401dd0a2dbSpl AACDB_PRINT(softs, CE_WARN,
50411dd0a2dbSpl "GetCap> %s not supported: whom=%d", cap, whom);
50427c478bd9Sstevel@tonic-gate return (-1);
50437c478bd9Sstevel@tonic-gate }
50447c478bd9Sstevel@tonic-gate
5045382c8bcaSpl mutex_enter(&softs->io_lock);
504658bc78c7SXin Chen dvp = AAC_DEV(softs, ap->a_target);
504758bc78c7SXin Chen if (dvp == NULL || !AAC_DEV_IS_VALID(dvp)) {
5048382c8bcaSpl mutex_exit(&softs->io_lock);
504958bc78c7SXin Chen AACDB_PRINT_TRAN(softs, "Bad target t%dL%d to getcap",
5050942c5e3cSpl ap->a_target, ap->a_lun);
50517c478bd9Sstevel@tonic-gate return (-1);
50527c478bd9Sstevel@tonic-gate }
50537c478bd9Sstevel@tonic-gate
50547c478bd9Sstevel@tonic-gate switch (scsi_hba_lookup_capstr(cap)) {
5055830d82f7Spl case SCSI_CAP_ARQ: /* auto request sense */
50567c478bd9Sstevel@tonic-gate rval = 1;
50577c478bd9Sstevel@tonic-gate break;
5058830d82f7Spl case SCSI_CAP_UNTAGGED_QING:
5059830d82f7Spl case SCSI_CAP_TAGGED_QING:
5060830d82f7Spl rval = 1;
50617c478bd9Sstevel@tonic-gate break;
5062942c5e3cSpl case SCSI_CAP_DMA_MAX:
506372888e72Speng liu - Sun Microsystems - Beijing China rval = softs->dma_max;
5064942c5e3cSpl break;
50657c478bd9Sstevel@tonic-gate default:
50667c478bd9Sstevel@tonic-gate rval = -1;
50677c478bd9Sstevel@tonic-gate break;
50687c478bd9Sstevel@tonic-gate }
5069382c8bcaSpl mutex_exit(&softs->io_lock);
5070382c8bcaSpl
50711dd0a2dbSpl AACDB_PRINT_TRAN(softs, "GetCap> %s t%dL%d: rval=%d",
50721dd0a2dbSpl cap, ap->a_target, ap->a_lun, rval);
50737c478bd9Sstevel@tonic-gate return (rval);
50747c478bd9Sstevel@tonic-gate }
50757c478bd9Sstevel@tonic-gate
50767c478bd9Sstevel@tonic-gate /*ARGSUSED*/
50777c478bd9Sstevel@tonic-gate static int
aac_tran_setcap(struct scsi_address * ap,char * cap,int value,int whom)5078c9487164Spl aac_tran_setcap(struct scsi_address *ap, char *cap, int value, int whom)
50797c478bd9Sstevel@tonic-gate {
5080c9487164Spl struct aac_softstate *softs = AAC_TRAN2SOFTS(ap->a_hba_tran);
508158bc78c7SXin Chen struct aac_device *dvp;
5082c9487164Spl int rval;
50837c478bd9Sstevel@tonic-gate
50841dd0a2dbSpl DBCALLED(softs, 2);
50857c478bd9Sstevel@tonic-gate
50867c478bd9Sstevel@tonic-gate /* We don't allow inquiring about capabilities for other targets */
50877c478bd9Sstevel@tonic-gate if (cap == NULL || whom == 0) {
50881dd0a2dbSpl AACDB_PRINT(softs, CE_WARN,
50891dd0a2dbSpl "SetCap> %s not supported: whom=%d", cap, whom);
5090830d82f7Spl return (-1);
5091830d82f7Spl }
5092830d82f7Spl
5093382c8bcaSpl mutex_enter(&softs->io_lock);
509458bc78c7SXin Chen dvp = AAC_DEV(softs, ap->a_target);
509558bc78c7SXin Chen if (dvp == NULL || !AAC_DEV_IS_VALID(dvp)) {
5096382c8bcaSpl mutex_exit(&softs->io_lock);
509758bc78c7SXin Chen AACDB_PRINT_TRAN(softs, "Bad target t%dL%d to setcap",
5098942c5e3cSpl ap->a_target, ap->a_lun);
50997c478bd9Sstevel@tonic-gate return (-1);
51007c478bd9Sstevel@tonic-gate }
51017c478bd9Sstevel@tonic-gate
51027c478bd9Sstevel@tonic-gate switch (scsi_hba_lookup_capstr(cap)) {
51037c478bd9Sstevel@tonic-gate case SCSI_CAP_ARQ:
5104942c5e3cSpl /* Force auto request sense */
5105830d82f7Spl rval = (value == 1) ? 1 : 0;
51067c478bd9Sstevel@tonic-gate break;
5107830d82f7Spl case SCSI_CAP_UNTAGGED_QING:
5108830d82f7Spl case SCSI_CAP_TAGGED_QING:
5109830d82f7Spl rval = (value == 1) ? 1 : 0;
5110830d82f7Spl break;
51117c478bd9Sstevel@tonic-gate default:
51127c478bd9Sstevel@tonic-gate rval = -1;
51137c478bd9Sstevel@tonic-gate break;
51147c478bd9Sstevel@tonic-gate }
5115382c8bcaSpl mutex_exit(&softs->io_lock);
51167c478bd9Sstevel@tonic-gate
51171dd0a2dbSpl AACDB_PRINT_TRAN(softs, "SetCap> %s t%dL%d val=%d: rval=%d",
51181dd0a2dbSpl cap, ap->a_target, ap->a_lun, value, rval);
51197c478bd9Sstevel@tonic-gate return (rval);
51207c478bd9Sstevel@tonic-gate }
51217c478bd9Sstevel@tonic-gate
51227c478bd9Sstevel@tonic-gate static void
aac_tran_destroy_pkt(struct scsi_address * ap,struct scsi_pkt * pkt)5123c9487164Spl aac_tran_destroy_pkt(struct scsi_address *ap, struct scsi_pkt *pkt)
51247c478bd9Sstevel@tonic-gate {
5125c9487164Spl struct aac_cmd *acp = PKT2AC(pkt);
51267c478bd9Sstevel@tonic-gate
51271dd0a2dbSpl DBCALLED(NULL, 2);
51287c478bd9Sstevel@tonic-gate
5129942c5e3cSpl if (acp->sgt) {
5130942c5e3cSpl kmem_free(acp->sgt, sizeof (struct aac_sge) * \
5131942c5e3cSpl acp->left_cookien);
5132d7c5bf88Spl }
5133c9487164Spl aac_free_dmamap(acp);
5134c9487164Spl ASSERT(acp->slotp == NULL);
51357c478bd9Sstevel@tonic-gate scsi_hba_pkt_free(ap, pkt);
51367c478bd9Sstevel@tonic-gate }
51377c478bd9Sstevel@tonic-gate
5138942c5e3cSpl int
aac_cmd_dma_alloc(struct aac_softstate * softs,struct aac_cmd * acp,struct buf * bp,int flags,int (* cb)(),caddr_t arg)5139942c5e3cSpl aac_cmd_dma_alloc(struct aac_softstate *softs, struct aac_cmd *acp,
5140942c5e3cSpl struct buf *bp, int flags, int (*cb)(), caddr_t arg)
51417c478bd9Sstevel@tonic-gate {
5142942c5e3cSpl int kf = (cb == SLEEP_FUNC) ? KM_SLEEP : KM_NOSLEEP;
5143942c5e3cSpl uint_t oldcookiec;
5144c9ffe217SToomas Soome int bioerr = 0;
5145c9487164Spl int rval;
51467c478bd9Sstevel@tonic-gate
5147942c5e3cSpl oldcookiec = acp->left_cookien;
51487c478bd9Sstevel@tonic-gate
5149942c5e3cSpl /* Move window to build s/g map */
5150942c5e3cSpl if (acp->total_nwin > 0) {
5151942c5e3cSpl if (++acp->cur_win < acp->total_nwin) {
5152942c5e3cSpl off_t off;
5153942c5e3cSpl size_t len;
5154c9487164Spl
5155942c5e3cSpl rval = ddi_dma_getwin(acp->buf_dma_handle, acp->cur_win,
5156942c5e3cSpl &off, &len, &acp->cookie, &acp->left_cookien);
5157942c5e3cSpl if (rval == DDI_SUCCESS)
5158942c5e3cSpl goto get_dma_cookies;
5159942c5e3cSpl AACDB_PRINT(softs, CE_WARN,
5160942c5e3cSpl "ddi_dma_getwin() fail %d", rval);
516158bc78c7SXin Chen return (AACERR);
51627c478bd9Sstevel@tonic-gate }
5163942c5e3cSpl AACDB_PRINT(softs, CE_WARN, "Nothing to transfer");
516458bc78c7SXin Chen return (AACERR);
5165942c5e3cSpl }
5166942c5e3cSpl
5167942c5e3cSpl /* We need to transfer data, so we alloc DMA resources for this pkt */
5168942c5e3cSpl if (bp && bp->b_bcount != 0 && !(acp->flags & AAC_CMD_DMA_VALID)) {
5169942c5e3cSpl uint_t dma_flags = 0;
5170942c5e3cSpl struct aac_sge *sge;
5171830d82f7Spl
51727c478bd9Sstevel@tonic-gate /*
5173830d82f7Spl * We will still use this point to fake some
5174830d82f7Spl * infomation in tran_start
51757c478bd9Sstevel@tonic-gate */
5176c9487164Spl acp->bp = bp;
51777c478bd9Sstevel@tonic-gate
5178830d82f7Spl /* Set dma flags */
51797c478bd9Sstevel@tonic-gate if (BUF_IS_READ(bp)) {
51807c478bd9Sstevel@tonic-gate dma_flags |= DDI_DMA_READ;
5181c9487164Spl acp->flags |= AAC_CMD_BUF_READ;
51827c478bd9Sstevel@tonic-gate } else {
51837c478bd9Sstevel@tonic-gate dma_flags |= DDI_DMA_WRITE;
5184c9487164Spl acp->flags |= AAC_CMD_BUF_WRITE;
51857c478bd9Sstevel@tonic-gate }
51867c478bd9Sstevel@tonic-gate if (flags & PKT_CONSISTENT)
51877c478bd9Sstevel@tonic-gate dma_flags |= DDI_DMA_CONSISTENT;
51887c478bd9Sstevel@tonic-gate if (flags & PKT_DMA_PARTIAL)
51897c478bd9Sstevel@tonic-gate dma_flags |= DDI_DMA_PARTIAL;
51907c478bd9Sstevel@tonic-gate
5191830d82f7Spl /* Alloc buf dma handle */
5192942c5e3cSpl if (!acp->buf_dma_handle) {
5193c9487164Spl rval = ddi_dma_alloc_handle(softs->devinfo_p,
5194d7c5bf88Spl &softs->buf_dma_attr, cb, arg,
5195c9487164Spl &acp->buf_dma_handle);
5196942c5e3cSpl if (rval != DDI_SUCCESS) {
5197942c5e3cSpl AACDB_PRINT(softs, CE_WARN,
5198942c5e3cSpl "Can't allocate DMA handle, errno=%d",
5199942c5e3cSpl rval);
5200942c5e3cSpl goto error_out;
5201942c5e3cSpl }
52027c478bd9Sstevel@tonic-gate }
52037c478bd9Sstevel@tonic-gate
5204830d82f7Spl /* Bind buf */
5205942c5e3cSpl if (((uintptr_t)bp->b_un.b_addr & AAC_DMA_ALIGN_MASK) == 0) {
5206c9487164Spl rval = ddi_dma_buf_bind_handle(acp->buf_dma_handle,
5207942c5e3cSpl bp, dma_flags, cb, arg, &acp->cookie,
5208942c5e3cSpl &acp->left_cookien);
5209830d82f7Spl } else {
5210830d82f7Spl size_t bufsz;
5211830d82f7Spl
52121dd0a2dbSpl AACDB_PRINT_TRAN(softs,
5213c9487164Spl "non-aligned buffer: addr=0x%p, cnt=%lu",
52141dd0a2dbSpl (void *)bp->b_un.b_addr, bp->b_bcount);
5215830d82f7Spl if (bp->b_flags & (B_PAGEIO|B_PHYS))
5216830d82f7Spl bp_mapin(bp);
5217830d82f7Spl
5218c9487164Spl rval = ddi_dma_mem_alloc(acp->buf_dma_handle,
5219c9487164Spl AAC_ROUNDUP(bp->b_bcount, AAC_DMA_ALIGN),
522058bc78c7SXin Chen &softs->acc_attr, DDI_DMA_STREAMING,
5221d7c5bf88Spl cb, arg, &acp->abp, &bufsz, &acp->abh);
5222830d82f7Spl
5223c9487164Spl if (rval != DDI_SUCCESS) {
52241dd0a2dbSpl AACDB_PRINT(softs, CE_NOTE,
52251dd0a2dbSpl "Cannot alloc DMA to non-aligned buf");
5226942c5e3cSpl bioerr = 0;
5227830d82f7Spl goto error_out;
5228830d82f7Spl }
5229830d82f7Spl
5230c9487164Spl if (acp->flags & AAC_CMD_BUF_WRITE)
5231942c5e3cSpl ddi_rep_put8(acp->abh,
5232942c5e3cSpl (uint8_t *)bp->b_un.b_addr,
5233942c5e3cSpl (uint8_t *)acp->abp, bp->b_bcount,
5234942c5e3cSpl DDI_DEV_AUTOINCR);
5235830d82f7Spl
5236c9487164Spl rval = ddi_dma_addr_bind_handle(acp->buf_dma_handle,
5237d7c5bf88Spl NULL, acp->abp, bufsz, dma_flags, cb, arg,
5238d7c5bf88Spl &acp->cookie, &acp->left_cookien);
5239830d82f7Spl }
5240830d82f7Spl
5241c9487164Spl switch (rval) {
52427c478bd9Sstevel@tonic-gate case DDI_DMA_PARTIAL_MAP:
5243c9487164Spl if (ddi_dma_numwin(acp->buf_dma_handle,
5244c9487164Spl &acp->total_nwin) == DDI_FAILURE) {
52451dd0a2dbSpl AACDB_PRINT(softs, CE_WARN,
52461dd0a2dbSpl "Cannot get number of DMA windows");
5247942c5e3cSpl bioerr = 0;
52487c478bd9Sstevel@tonic-gate goto error_out;
52497c478bd9Sstevel@tonic-gate }
5250942c5e3cSpl AACDB_PRINT_TRAN(softs, "buf bind, %d seg(s)",
52511dd0a2dbSpl acp->left_cookien);
5252c9487164Spl acp->cur_win = 0;
52537c478bd9Sstevel@tonic-gate break;
52547c478bd9Sstevel@tonic-gate
52557c478bd9Sstevel@tonic-gate case DDI_DMA_MAPPED:
5256942c5e3cSpl AACDB_PRINT_TRAN(softs, "buf bind, %d seg(s)",
52571dd0a2dbSpl acp->left_cookien);
5258c9487164Spl acp->cur_win = 0;
5259c9487164Spl acp->total_nwin = 1;
52607c478bd9Sstevel@tonic-gate break;
52617c478bd9Sstevel@tonic-gate
5262832e0b5aSpl case DDI_DMA_NORESOURCES:
5263942c5e3cSpl bioerr = 0;
52641dd0a2dbSpl AACDB_PRINT(softs, CE_WARN,
52651dd0a2dbSpl "Cannot bind buf for DMA: DDI_DMA_NORESOURCES");
5266832e0b5aSpl goto error_out;
5267832e0b5aSpl case DDI_DMA_BADATTR:
5268832e0b5aSpl case DDI_DMA_NOMAPPING:
5269942c5e3cSpl bioerr = EFAULT;
52701dd0a2dbSpl AACDB_PRINT(softs, CE_WARN,
52711dd0a2dbSpl "Cannot bind buf for DMA: DDI_DMA_NOMAPPING");
5272832e0b5aSpl goto error_out;
5273832e0b5aSpl case DDI_DMA_TOOBIG:
5274942c5e3cSpl bioerr = EINVAL;
5275942c5e3cSpl AACDB_PRINT(softs, CE_WARN,
5276942c5e3cSpl "Cannot bind buf for DMA: DDI_DMA_TOOBIG(%d)",
5277942c5e3cSpl bp->b_bcount);
5278942c5e3cSpl goto error_out;
52797c478bd9Sstevel@tonic-gate default:
5280942c5e3cSpl bioerr = EINVAL;
52811dd0a2dbSpl AACDB_PRINT(softs, CE_WARN,
52821dd0a2dbSpl "Cannot bind buf for DMA: %d", rval);
5283832e0b5aSpl goto error_out;
52847c478bd9Sstevel@tonic-gate }
5285942c5e3cSpl acp->flags |= AAC_CMD_DMA_VALID;
5286d7c5bf88Spl
5287942c5e3cSpl get_dma_cookies:
5288942c5e3cSpl ASSERT(acp->left_cookien > 0);
5289942c5e3cSpl if (acp->left_cookien > softs->aac_sg_tablesize) {
5290942c5e3cSpl AACDB_PRINT(softs, CE_NOTE, "large cookiec received %d",
5291942c5e3cSpl acp->left_cookien);
5292942c5e3cSpl bioerr = EINVAL;
5293942c5e3cSpl goto error_out;
5294942c5e3cSpl }
5295942c5e3cSpl if (oldcookiec != acp->left_cookien && acp->sgt != NULL) {
5296942c5e3cSpl kmem_free(acp->sgt, sizeof (struct aac_sge) * \
5297942c5e3cSpl oldcookiec);
5298942c5e3cSpl acp->sgt = NULL;
5299942c5e3cSpl }
5300942c5e3cSpl if (acp->sgt == NULL) {
5301942c5e3cSpl acp->sgt = kmem_alloc(sizeof (struct aac_sge) * \
5302942c5e3cSpl acp->left_cookien, kf);
5303942c5e3cSpl if (acp->sgt == NULL) {
5304d7c5bf88Spl AACDB_PRINT(softs, CE_WARN,
5305942c5e3cSpl "sgt kmem_alloc fail");
5306942c5e3cSpl bioerr = ENOMEM;
5307942c5e3cSpl goto error_out;
5308d7c5bf88Spl }
5309d7c5bf88Spl }
5310d7c5bf88Spl
5311942c5e3cSpl sge = &acp->sgt[0];
5312942c5e3cSpl sge->bcount = acp->cookie.dmac_size;
5313942c5e3cSpl sge->addr.ad64.lo = AAC_LS32(acp->cookie.dmac_laddress);
5314942c5e3cSpl sge->addr.ad64.hi = AAC_MS32(acp->cookie.dmac_laddress);
5315942c5e3cSpl acp->bcount = acp->cookie.dmac_size;
5316942c5e3cSpl for (sge++; sge < &acp->sgt[acp->left_cookien]; sge++) {
5317942c5e3cSpl ddi_dma_nextcookie(acp->buf_dma_handle, &acp->cookie);
5318942c5e3cSpl sge->bcount = acp->cookie.dmac_size;
5319942c5e3cSpl sge->addr.ad64.lo = AAC_LS32(acp->cookie.dmac_laddress);
5320942c5e3cSpl sge->addr.ad64.hi = AAC_MS32(acp->cookie.dmac_laddress);
5321942c5e3cSpl acp->bcount += acp->cookie.dmac_size;
5322942c5e3cSpl }
5323d7c5bf88Spl
5324942c5e3cSpl /*
5325942c5e3cSpl * Note: The old DMA engine do not correctly handle
5326942c5e3cSpl * dma_attr_maxxfer attribute. So we have to ensure
5327942c5e3cSpl * it by ourself.
5328942c5e3cSpl */
5329942c5e3cSpl if (acp->bcount > softs->buf_dma_attr.dma_attr_maxxfer) {
5330942c5e3cSpl AACDB_PRINT(softs, CE_NOTE,
5331942c5e3cSpl "large xfer size received %d\n", acp->bcount);
5332942c5e3cSpl bioerr = EINVAL;
5333d7c5bf88Spl goto error_out;
5334d7c5bf88Spl }
5335942c5e3cSpl
5336942c5e3cSpl acp->total_xfer += acp->bcount;
5337942c5e3cSpl
5338942c5e3cSpl if (acp->pkt) {
5339942c5e3cSpl /* Return remaining byte count */
534058bc78c7SXin Chen if (acp->total_xfer <= bp->b_bcount) {
534158bc78c7SXin Chen acp->pkt->pkt_resid = bp->b_bcount - \
534258bc78c7SXin Chen acp->total_xfer;
534358bc78c7SXin Chen } else {
534458bc78c7SXin Chen /*
534558bc78c7SXin Chen * Allocated DMA size is greater than the buf
534658bc78c7SXin Chen * size of bp. This is caused by devices like
534758bc78c7SXin Chen * tape. we have extra bytes allocated, but
534858bc78c7SXin Chen * the packet residual has to stay correct.
534958bc78c7SXin Chen */
535058bc78c7SXin Chen acp->pkt->pkt_resid = 0;
535158bc78c7SXin Chen }
5352942c5e3cSpl AACDB_PRINT_TRAN(softs,
5353942c5e3cSpl "bp=0x%p, xfered=%d/%d, resid=%d",
5354942c5e3cSpl (void *)bp->b_un.b_addr, (int)acp->total_xfer,
5355942c5e3cSpl (int)bp->b_bcount, (int)acp->pkt->pkt_resid);
5356942c5e3cSpl }
5357d7c5bf88Spl }
5358942c5e3cSpl return (AACOK);
5359d7c5bf88Spl
5360942c5e3cSpl error_out:
5361942c5e3cSpl bioerror(bp, bioerr);
5362942c5e3cSpl return (AACERR);
5363942c5e3cSpl }
5364d7c5bf88Spl
5365942c5e3cSpl static struct scsi_pkt *
aac_tran_init_pkt(struct scsi_address * ap,struct scsi_pkt * pkt,struct buf * bp,int cmdlen,int statuslen,int tgtlen,int flags,int (* callback)(),caddr_t arg)5366942c5e3cSpl aac_tran_init_pkt(struct scsi_address *ap, struct scsi_pkt *pkt,
5367942c5e3cSpl struct buf *bp, int cmdlen, int statuslen, int tgtlen, int flags,
5368942c5e3cSpl int (*callback)(), caddr_t arg)
5369942c5e3cSpl {
5370942c5e3cSpl struct aac_softstate *softs = AAC_TRAN2SOFTS(ap->a_hba_tran);
5371942c5e3cSpl struct aac_cmd *acp, *new_acp;
5372830d82f7Spl
5373942c5e3cSpl DBCALLED(softs, 2);
5374830d82f7Spl
5375942c5e3cSpl /* Allocate pkt */
5376942c5e3cSpl if (pkt == NULL) {
5377942c5e3cSpl int slen;
5378830d82f7Spl
5379942c5e3cSpl /* Force auto request sense */
5380942c5e3cSpl slen = (statuslen > softs->slen) ? statuslen : softs->slen;
5381942c5e3cSpl pkt = scsi_hba_pkt_alloc(softs->devinfo_p, ap, cmdlen,
5382942c5e3cSpl slen, tgtlen, sizeof (struct aac_cmd), callback, arg);
5383942c5e3cSpl if (pkt == NULL) {
5384942c5e3cSpl AACDB_PRINT(softs, CE_WARN, "Alloc scsi pkt failed");
5385942c5e3cSpl return (NULL);
5386942c5e3cSpl }
5387942c5e3cSpl acp = new_acp = PKT2AC(pkt);
5388942c5e3cSpl acp->pkt = pkt;
5389942c5e3cSpl acp->cmdlen = cmdlen;
5390942c5e3cSpl
539158bc78c7SXin Chen if (ap->a_target < AAC_MAX_LD) {
539258bc78c7SXin Chen acp->dvp = &softs->containers[ap->a_target].dev;
539358bc78c7SXin Chen acp->aac_cmd_fib = softs->aac_cmd_fib;
539458bc78c7SXin Chen acp->ac_comp = aac_ld_complete;
539558bc78c7SXin Chen } else {
539658bc78c7SXin Chen _NOTE(ASSUMING_PROTECTED(softs->nondasds))
539758bc78c7SXin Chen
539858bc78c7SXin Chen acp->dvp = &softs->nondasds[AAC_PD(ap->a_target)].dev;
539958bc78c7SXin Chen acp->aac_cmd_fib = softs->aac_cmd_fib_scsi;
540058bc78c7SXin Chen acp->ac_comp = aac_pd_complete;
540158bc78c7SXin Chen }
5402942c5e3cSpl } else {
5403942c5e3cSpl acp = PKT2AC(pkt);
5404942c5e3cSpl new_acp = NULL;
5405942c5e3cSpl }
5406942c5e3cSpl
5407942c5e3cSpl if (aac_cmd_dma_alloc(softs, acp, bp, flags, callback, arg) == AACOK)
5408942c5e3cSpl return (pkt);
5409832e0b5aSpl
5410c9487164Spl if (new_acp)
5411d7c5bf88Spl aac_tran_destroy_pkt(ap, pkt);
5412832e0b5aSpl return (NULL);
54137c478bd9Sstevel@tonic-gate }
54147c478bd9Sstevel@tonic-gate
54157c478bd9Sstevel@tonic-gate /*
54167c478bd9Sstevel@tonic-gate * tran_sync_pkt(9E) - explicit DMA synchronization
54177c478bd9Sstevel@tonic-gate */
54187c478bd9Sstevel@tonic-gate /*ARGSUSED*/
54197c478bd9Sstevel@tonic-gate static void
aac_tran_sync_pkt(struct scsi_address * ap,struct scsi_pkt * pkt)54207c478bd9Sstevel@tonic-gate aac_tran_sync_pkt(struct scsi_address *ap, struct scsi_pkt *pkt)
54217c478bd9Sstevel@tonic-gate {
5422c9487164Spl struct aac_cmd *acp = PKT2AC(pkt);
54237c478bd9Sstevel@tonic-gate
54241dd0a2dbSpl DBCALLED(NULL, 2);
54257c478bd9Sstevel@tonic-gate
54267675db54Syw if (aac_dma_sync_ac(acp) != AACOK)
54277675db54Syw ddi_fm_service_impact(
54287675db54Syw (AAC_TRAN2SOFTS(ap->a_hba_tran))->devinfo_p,
54297675db54Syw DDI_SERVICE_UNAFFECTED);
54307c478bd9Sstevel@tonic-gate }
54317c478bd9Sstevel@tonic-gate
54327c478bd9Sstevel@tonic-gate /*
54337c478bd9Sstevel@tonic-gate * tran_dmafree(9E) - deallocate DMA resources allocated for command
54347c478bd9Sstevel@tonic-gate */
54357c478bd9Sstevel@tonic-gate /*ARGSUSED*/
54367c478bd9Sstevel@tonic-gate static void
aac_tran_dmafree(struct scsi_address * ap,struct scsi_pkt * pkt)54377c478bd9Sstevel@tonic-gate aac_tran_dmafree(struct scsi_address *ap, struct scsi_pkt *pkt)
54387c478bd9Sstevel@tonic-gate {
5439c9487164Spl struct aac_cmd *acp = PKT2AC(pkt);
54407c478bd9Sstevel@tonic-gate
54411dd0a2dbSpl DBCALLED(NULL, 2);
54427c478bd9Sstevel@tonic-gate
5443c9487164Spl aac_free_dmamap(acp);
54447c478bd9Sstevel@tonic-gate }
54457c478bd9Sstevel@tonic-gate
5446382c8bcaSpl static int
aac_do_quiesce(struct aac_softstate * softs)5447382c8bcaSpl aac_do_quiesce(struct aac_softstate *softs)
5448382c8bcaSpl {
5449382c8bcaSpl aac_hold_bus(softs, AAC_IOCMD_ASYNC);
5450382c8bcaSpl if (softs->bus_ncmds[AAC_CMDQ_ASYNC]) {
5451382c8bcaSpl aac_start_drain(softs);
5452382c8bcaSpl do {
5453382c8bcaSpl if (cv_wait_sig(&softs->drain_cv,
5454382c8bcaSpl &softs->io_lock) == 0) {
5455382c8bcaSpl /* Quiesce has been interrupted */
5456382c8bcaSpl aac_stop_drain(softs);
5457382c8bcaSpl aac_unhold_bus(softs, AAC_IOCMD_ASYNC);
5458382c8bcaSpl aac_start_waiting_io(softs);
5459382c8bcaSpl return (AACERR);
5460382c8bcaSpl }
5461382c8bcaSpl } while (softs->bus_ncmds[AAC_CMDQ_ASYNC]);
5462382c8bcaSpl aac_stop_drain(softs);
5463382c8bcaSpl }
5464382c8bcaSpl
5465382c8bcaSpl softs->state |= AAC_STATE_QUIESCED;
5466382c8bcaSpl return (AACOK);
5467382c8bcaSpl }
5468382c8bcaSpl
54697c478bd9Sstevel@tonic-gate static int
aac_tran_quiesce(dev_info_t * dip)54707c478bd9Sstevel@tonic-gate aac_tran_quiesce(dev_info_t *dip)
54717c478bd9Sstevel@tonic-gate {
5472c9487164Spl struct aac_softstate *softs = AAC_DIP2SOFTS(dip);
5473382c8bcaSpl int rval;
5474830d82f7Spl
54751dd0a2dbSpl DBCALLED(softs, 1);
5476830d82f7Spl
5477382c8bcaSpl mutex_enter(&softs->io_lock);
5478382c8bcaSpl if (aac_do_quiesce(softs) == AACOK)
5479c9487164Spl rval = 0;
5480382c8bcaSpl else
5481382c8bcaSpl rval = 1;
5482382c8bcaSpl mutex_exit(&softs->io_lock);
5483c9487164Spl return (rval);
54847c478bd9Sstevel@tonic-gate }
54857c478bd9Sstevel@tonic-gate
5486382c8bcaSpl static int
aac_do_unquiesce(struct aac_softstate * softs)5487382c8bcaSpl aac_do_unquiesce(struct aac_softstate *softs)
5488382c8bcaSpl {
5489382c8bcaSpl softs->state &= ~AAC_STATE_QUIESCED;
5490382c8bcaSpl aac_unhold_bus(softs, AAC_IOCMD_ASYNC);
5491382c8bcaSpl
5492382c8bcaSpl aac_start_waiting_io(softs);
5493382c8bcaSpl return (AACOK);
5494382c8bcaSpl }
5495382c8bcaSpl
54967c478bd9Sstevel@tonic-gate static int
aac_tran_unquiesce(dev_info_t * dip)54977c478bd9Sstevel@tonic-gate aac_tran_unquiesce(dev_info_t *dip)
54987c478bd9Sstevel@tonic-gate {
5499c9487164Spl struct aac_softstate *softs = AAC_DIP2SOFTS(dip);
5500382c8bcaSpl int rval;
5501830d82f7Spl
55021dd0a2dbSpl DBCALLED(softs, 1);
5503830d82f7Spl
5504382c8bcaSpl mutex_enter(&softs->io_lock);
5505382c8bcaSpl if (aac_do_unquiesce(softs) == AACOK)
5506382c8bcaSpl rval = 0;
5507382c8bcaSpl else
5508382c8bcaSpl rval = 1;
5509382c8bcaSpl mutex_exit(&softs->io_lock);
5510382c8bcaSpl return (rval);
55117c478bd9Sstevel@tonic-gate }
55127c478bd9Sstevel@tonic-gate
55137c478bd9Sstevel@tonic-gate static int
aac_hba_setup(struct aac_softstate * softs)55147c478bd9Sstevel@tonic-gate aac_hba_setup(struct aac_softstate *softs)
55157c478bd9Sstevel@tonic-gate {
5516c9487164Spl scsi_hba_tran_t *hba_tran;
5517c9487164Spl int rval;
55187c478bd9Sstevel@tonic-gate
55197c478bd9Sstevel@tonic-gate hba_tran = scsi_hba_tran_alloc(softs->devinfo_p, SCSI_HBA_CANSLEEP);
55207c478bd9Sstevel@tonic-gate if (hba_tran == NULL)
55217c478bd9Sstevel@tonic-gate return (AACERR);
55227c478bd9Sstevel@tonic-gate hba_tran->tran_hba_private = softs;
55237c478bd9Sstevel@tonic-gate hba_tran->tran_tgt_init = aac_tran_tgt_init;
552458bc78c7SXin Chen hba_tran->tran_tgt_free = aac_tran_tgt_free;
55257c478bd9Sstevel@tonic-gate hba_tran->tran_tgt_probe = scsi_hba_probe;
55267c478bd9Sstevel@tonic-gate hba_tran->tran_start = aac_tran_start;
55277c478bd9Sstevel@tonic-gate hba_tran->tran_getcap = aac_tran_getcap;
55287c478bd9Sstevel@tonic-gate hba_tran->tran_setcap = aac_tran_setcap;
55297c478bd9Sstevel@tonic-gate hba_tran->tran_init_pkt = aac_tran_init_pkt;
55307c478bd9Sstevel@tonic-gate hba_tran->tran_destroy_pkt = aac_tran_destroy_pkt;
55317c478bd9Sstevel@tonic-gate hba_tran->tran_reset = aac_tran_reset;
5532830d82f7Spl hba_tran->tran_abort = aac_tran_abort;
55337c478bd9Sstevel@tonic-gate hba_tran->tran_sync_pkt = aac_tran_sync_pkt;
55347c478bd9Sstevel@tonic-gate hba_tran->tran_dmafree = aac_tran_dmafree;
55357c478bd9Sstevel@tonic-gate hba_tran->tran_quiesce = aac_tran_quiesce;
55367c478bd9Sstevel@tonic-gate hba_tran->tran_unquiesce = aac_tran_unquiesce;
553758bc78c7SXin Chen hba_tran->tran_bus_config = aac_tran_bus_config;
5538c9487164Spl rval = scsi_hba_attach_setup(softs->devinfo_p, &softs->buf_dma_attr,
5539d7c5bf88Spl hba_tran, 0);
5540c9487164Spl if (rval != DDI_SUCCESS) {
55417c478bd9Sstevel@tonic-gate scsi_hba_tran_free(hba_tran);
55421dd0a2dbSpl AACDB_PRINT(softs, CE_WARN, "aac_hba_setup failed");
55437c478bd9Sstevel@tonic-gate return (AACERR);
55447c478bd9Sstevel@tonic-gate }
55457c478bd9Sstevel@tonic-gate
554658bc78c7SXin Chen softs->hba_tran = hba_tran;
55477c478bd9Sstevel@tonic-gate return (AACOK);
55487c478bd9Sstevel@tonic-gate }
55497c478bd9Sstevel@tonic-gate
5550d7c5bf88Spl /*
5551d7c5bf88Spl * FIB setup operations
5552d7c5bf88Spl */
5553d7c5bf88Spl
5554d7c5bf88Spl /*
5555d7c5bf88Spl * Init FIB header
5556d7c5bf88Spl */
5557d7c5bf88Spl static void
aac_cmd_fib_header(struct aac_softstate * softs,struct aac_cmd * acp,uint16_t cmd)5558f42c2f53Szhongyan gu - Sun Microsystems - Beijing China aac_cmd_fib_header(struct aac_softstate *softs, struct aac_cmd *acp,
5559f42c2f53Szhongyan gu - Sun Microsystems - Beijing China uint16_t cmd)
55607c478bd9Sstevel@tonic-gate {
5561f42c2f53Szhongyan gu - Sun Microsystems - Beijing China struct aac_slot *slotp = acp->slotp;
5562942c5e3cSpl ddi_acc_handle_t acc = slotp->fib_acc_handle;
5563942c5e3cSpl struct aac_fib *fibp = slotp->fibp;
5564942c5e3cSpl uint32_t xfer_state;
5565d7c5bf88Spl
5566942c5e3cSpl xfer_state =
5567c9487164Spl AAC_FIBSTATE_HOSTOWNED |
5568c9487164Spl AAC_FIBSTATE_INITIALISED |
5569c9487164Spl AAC_FIBSTATE_EMPTY |
55700749e8deSXin Chen - Sun Microsystems - Beijing China AAC_FIBSTATE_FAST_RESPONSE | /* enable fast io */
5571c9487164Spl AAC_FIBSTATE_FROMHOST |
5572c9487164Spl AAC_FIBSTATE_REXPECTED |
5573942c5e3cSpl AAC_FIBSTATE_NORM;
5574f42c2f53Szhongyan gu - Sun Microsystems - Beijing China
55750749e8deSXin Chen - Sun Microsystems - Beijing China if (!(acp->flags & AAC_CMD_SYNC))
55760749e8deSXin Chen - Sun Microsystems - Beijing China xfer_state |= AAC_FIBSTATE_ASYNC;
5577942c5e3cSpl
5578942c5e3cSpl ddi_put32(acc, &fibp->Header.XferState, xfer_state);
5579942c5e3cSpl ddi_put16(acc, &fibp->Header.Command, cmd);
5580942c5e3cSpl ddi_put8(acc, &fibp->Header.StructType, AAC_FIBTYPE_TFIB);
5581942c5e3cSpl ddi_put8(acc, &fibp->Header.Flags, 0); /* don't care */
5582f42c2f53Szhongyan gu - Sun Microsystems - Beijing China ddi_put16(acc, &fibp->Header.Size, acp->fib_size);
5583f42c2f53Szhongyan gu - Sun Microsystems - Beijing China ddi_put16(acc, &fibp->Header.SenderSize, softs->aac_max_fib_size);
5584942c5e3cSpl ddi_put32(acc, &fibp->Header.SenderFibAddress, (slotp->index << 2));
5585942c5e3cSpl ddi_put32(acc, &fibp->Header.ReceiverFibAddress, slotp->fib_phyaddr);
5586942c5e3cSpl ddi_put32(acc, &fibp->Header.SenderData, 0); /* don't care */
5587d7c5bf88Spl }
55887c478bd9Sstevel@tonic-gate
5589d7c5bf88Spl /*
5590d7c5bf88Spl * Init FIB for raw IO command
5591d7c5bf88Spl */
5592d7c5bf88Spl static void
aac_cmd_fib_rawio(struct aac_softstate * softs,struct aac_cmd * acp)5593942c5e3cSpl aac_cmd_fib_rawio(struct aac_softstate *softs, struct aac_cmd *acp)
5594d7c5bf88Spl {
5595942c5e3cSpl ddi_acc_handle_t acc = acp->slotp->fib_acc_handle;
5596942c5e3cSpl struct aac_raw_io *io = (struct aac_raw_io *)&acp->slotp->fibp->data[0];
5597942c5e3cSpl struct aac_sg_entryraw *sgp;
5598942c5e3cSpl struct aac_sge *sge;
5599942c5e3cSpl
5600942c5e3cSpl /* Calculate FIB size */
5601942c5e3cSpl acp->fib_size = sizeof (struct aac_fib_header) + \
5602942c5e3cSpl sizeof (struct aac_raw_io) + (acp->left_cookien - 1) * \
5603942c5e3cSpl sizeof (struct aac_sg_entryraw);
5604942c5e3cSpl
5605f42c2f53Szhongyan gu - Sun Microsystems - Beijing China aac_cmd_fib_header(softs, acp, RawIo);
5606942c5e3cSpl
5607942c5e3cSpl ddi_put16(acc, &io->Flags, (acp->flags & AAC_CMD_BUF_READ) ? 1 : 0);
5608942c5e3cSpl ddi_put16(acc, &io->BpTotal, 0);
5609942c5e3cSpl ddi_put16(acc, &io->BpComplete, 0);
5610942c5e3cSpl
5611942c5e3cSpl ddi_put32(acc, AAC_LO32(&io->BlockNumber), AAC_LS32(acp->blkno));
5612942c5e3cSpl ddi_put32(acc, AAC_HI32(&io->BlockNumber), AAC_MS32(acp->blkno));
5613942c5e3cSpl ddi_put16(acc, &io->ContainerId,
5614942c5e3cSpl ((struct aac_container *)acp->dvp)->cid);
5615942c5e3cSpl
5616942c5e3cSpl /* Fill SG table */
5617942c5e3cSpl ddi_put32(acc, &io->SgMapRaw.SgCount, acp->left_cookien);
5618942c5e3cSpl ddi_put32(acc, &io->ByteCount, acp->bcount);
5619942c5e3cSpl
5620942c5e3cSpl for (sge = &acp->sgt[0], sgp = &io->SgMapRaw.SgEntryRaw[0];
5621942c5e3cSpl sge < &acp->sgt[acp->left_cookien]; sge++, sgp++) {
5622942c5e3cSpl ddi_put32(acc, AAC_LO32(&sgp->SgAddress), sge->addr.ad64.lo);
5623942c5e3cSpl ddi_put32(acc, AAC_HI32(&sgp->SgAddress), sge->addr.ad64.hi);
5624942c5e3cSpl ddi_put32(acc, &sgp->SgByteCount, sge->bcount);
5625942c5e3cSpl sgp->Next = 0;
5626942c5e3cSpl sgp->Prev = 0;
5627942c5e3cSpl sgp->Flags = 0;
5628942c5e3cSpl }
5629942c5e3cSpl }
5630d7c5bf88Spl
5631942c5e3cSpl /* Init FIB for 64-bit block IO command */
5632942c5e3cSpl static void
aac_cmd_fib_brw64(struct aac_softstate * softs,struct aac_cmd * acp)5633942c5e3cSpl aac_cmd_fib_brw64(struct aac_softstate *softs, struct aac_cmd *acp)
5634942c5e3cSpl {
5635942c5e3cSpl ddi_acc_handle_t acc = acp->slotp->fib_acc_handle;
5636942c5e3cSpl struct aac_blockread64 *br = (struct aac_blockread64 *) \
5637942c5e3cSpl &acp->slotp->fibp->data[0];
5638942c5e3cSpl struct aac_sg_entry64 *sgp;
5639942c5e3cSpl struct aac_sge *sge;
5640d7c5bf88Spl
5641942c5e3cSpl acp->fib_size = sizeof (struct aac_fib_header) + \
5642942c5e3cSpl sizeof (struct aac_blockread64) + (acp->left_cookien - 1) * \
5643942c5e3cSpl sizeof (struct aac_sg_entry64);
5644d7c5bf88Spl
5645f42c2f53Szhongyan gu - Sun Microsystems - Beijing China aac_cmd_fib_header(softs, acp, ContainerCommand64);
5646d7c5bf88Spl
5647942c5e3cSpl /*
5648942c5e3cSpl * The definitions for aac_blockread64 and aac_blockwrite64
5649942c5e3cSpl * are the same.
5650942c5e3cSpl */
5651942c5e3cSpl ddi_put32(acc, &br->BlockNumber, (uint32_t)acp->blkno);
5652942c5e3cSpl ddi_put16(acc, &br->ContainerId,
5653942c5e3cSpl ((struct aac_container *)acp->dvp)->cid);
5654942c5e3cSpl ddi_put32(acc, &br->Command, (acp->flags & AAC_CMD_BUF_READ) ?
5655942c5e3cSpl VM_CtHostRead64 : VM_CtHostWrite64);
5656942c5e3cSpl ddi_put16(acc, &br->Pad, 0);
5657942c5e3cSpl ddi_put16(acc, &br->Flags, 0);
5658942c5e3cSpl
5659942c5e3cSpl /* Fill SG table */
5660942c5e3cSpl ddi_put32(acc, &br->SgMap64.SgCount, acp->left_cookien);
5661942c5e3cSpl ddi_put16(acc, &br->SectorCount, acp->bcount / AAC_BLK_SIZE);
5662942c5e3cSpl
5663942c5e3cSpl for (sge = &acp->sgt[0], sgp = &br->SgMap64.SgEntry64[0];
5664942c5e3cSpl sge < &acp->sgt[acp->left_cookien]; sge++, sgp++) {
5665942c5e3cSpl ddi_put32(acc, AAC_LO32(&sgp->SgAddress), sge->addr.ad64.lo);
5666942c5e3cSpl ddi_put32(acc, AAC_HI32(&sgp->SgAddress), sge->addr.ad64.hi);
5667942c5e3cSpl ddi_put32(acc, &sgp->SgByteCount, sge->bcount);
5668d7c5bf88Spl }
5669d7c5bf88Spl }
5670d7c5bf88Spl
5671942c5e3cSpl /* Init FIB for block IO command */
5672d7c5bf88Spl static void
aac_cmd_fib_brw(struct aac_softstate * softs,struct aac_cmd * acp)5673942c5e3cSpl aac_cmd_fib_brw(struct aac_softstate *softs, struct aac_cmd *acp)
5674d7c5bf88Spl {
5675942c5e3cSpl ddi_acc_handle_t acc = acp->slotp->fib_acc_handle;
5676942c5e3cSpl struct aac_blockread *br = (struct aac_blockread *) \
5677942c5e3cSpl &acp->slotp->fibp->data[0];
5678942c5e3cSpl struct aac_sg_entry *sgp;
5679942c5e3cSpl struct aac_sge *sge = &acp->sgt[0];
5680d7c5bf88Spl
5681942c5e3cSpl if (acp->flags & AAC_CMD_BUF_READ) {
5682d7c5bf88Spl acp->fib_size = sizeof (struct aac_fib_header) + \
5683942c5e3cSpl sizeof (struct aac_blockread) + (acp->left_cookien - 1) * \
5684942c5e3cSpl sizeof (struct aac_sg_entry);
5685382c8bcaSpl
5686942c5e3cSpl ddi_put32(acc, &br->Command, VM_CtBlockRead);
5687942c5e3cSpl ddi_put32(acc, &br->SgMap.SgCount, acp->left_cookien);
5688942c5e3cSpl sgp = &br->SgMap.SgEntry[0];
5689942c5e3cSpl } else {
5690942c5e3cSpl struct aac_blockwrite *bw = (struct aac_blockwrite *)br;
5691d7c5bf88Spl
5692942c5e3cSpl acp->fib_size = sizeof (struct aac_fib_header) + \
5693942c5e3cSpl sizeof (struct aac_blockwrite) + (acp->left_cookien - 1) * \
5694942c5e3cSpl sizeof (struct aac_sg_entry);
5695d7c5bf88Spl
5696942c5e3cSpl ddi_put32(acc, &bw->Command, VM_CtBlockWrite);
5697942c5e3cSpl ddi_put32(acc, &bw->Stable, CUNSTABLE);
5698942c5e3cSpl ddi_put32(acc, &bw->SgMap.SgCount, acp->left_cookien);
5699942c5e3cSpl sgp = &bw->SgMap.SgEntry[0];
5700942c5e3cSpl }
5701f42c2f53Szhongyan gu - Sun Microsystems - Beijing China aac_cmd_fib_header(softs, acp, ContainerCommand);
5702d7c5bf88Spl
5703942c5e3cSpl /*
5704942c5e3cSpl * aac_blockread and aac_blockwrite have the similar
5705942c5e3cSpl * structure head, so use br for bw here
5706942c5e3cSpl */
5707942c5e3cSpl ddi_put32(acc, &br->BlockNumber, (uint32_t)acp->blkno);
5708942c5e3cSpl ddi_put32(acc, &br->ContainerId,
5709942c5e3cSpl ((struct aac_container *)acp->dvp)->cid);
5710942c5e3cSpl ddi_put32(acc, &br->ByteCount, acp->bcount);
5711d7c5bf88Spl
5712942c5e3cSpl /* Fill SG table */
5713942c5e3cSpl for (sge = &acp->sgt[0];
5714942c5e3cSpl sge < &acp->sgt[acp->left_cookien]; sge++, sgp++) {
5715942c5e3cSpl ddi_put32(acc, &sgp->SgAddress, sge->addr.ad32);
5716942c5e3cSpl ddi_put32(acc, &sgp->SgByteCount, sge->bcount);
5717942c5e3cSpl }
5718942c5e3cSpl }
5719d7c5bf88Spl
5720942c5e3cSpl /*ARGSUSED*/
5721942c5e3cSpl void
aac_cmd_fib_copy(struct aac_softstate * softs,struct aac_cmd * acp)5722942c5e3cSpl aac_cmd_fib_copy(struct aac_softstate *softs, struct aac_cmd *acp)
5723942c5e3cSpl {
5724942c5e3cSpl struct aac_slot *slotp = acp->slotp;
5725942c5e3cSpl struct aac_fib *fibp = slotp->fibp;
5726942c5e3cSpl ddi_acc_handle_t acc = slotp->fib_acc_handle;
5727d7c5bf88Spl
5728942c5e3cSpl ddi_rep_put8(acc, (uint8_t *)acp->fibp, (uint8_t *)fibp,
5729942c5e3cSpl acp->fib_size, /* only copy data of needed length */
5730942c5e3cSpl DDI_DEV_AUTOINCR);
5731942c5e3cSpl ddi_put32(acc, &fibp->Header.ReceiverFibAddress, slotp->fib_phyaddr);
5732942c5e3cSpl ddi_put32(acc, &fibp->Header.SenderFibAddress, slotp->index << 2);
5733d7c5bf88Spl }
5734d7c5bf88Spl
5735d7c5bf88Spl static void
aac_cmd_fib_sync(struct aac_softstate * softs,struct aac_cmd * acp)5736942c5e3cSpl aac_cmd_fib_sync(struct aac_softstate *softs, struct aac_cmd *acp)
5737d7c5bf88Spl {
5738f42c2f53Szhongyan gu - Sun Microsystems - Beijing China ddi_acc_handle_t acc = acp->slotp->fib_acc_handle;
5739942c5e3cSpl struct aac_synchronize_command *sync =
5740f42c2f53Szhongyan gu - Sun Microsystems - Beijing China (struct aac_synchronize_command *)&acp->slotp->fibp->data[0];
5741942c5e3cSpl
5742f42c2f53Szhongyan gu - Sun Microsystems - Beijing China acp->fib_size = AAC_FIB_SIZEOF(struct aac_synchronize_command);
5743942c5e3cSpl
5744f42c2f53Szhongyan gu - Sun Microsystems - Beijing China aac_cmd_fib_header(softs, acp, ContainerCommand);
5745942c5e3cSpl ddi_put32(acc, &sync->Command, VM_ContainerConfig);
5746942c5e3cSpl ddi_put32(acc, &sync->Type, (uint32_t)CT_FLUSH_CACHE);
5747942c5e3cSpl ddi_put32(acc, &sync->Cid, ((struct aac_container *)acp->dvp)->cid);
5748942c5e3cSpl ddi_put32(acc, &sync->Count,
5749942c5e3cSpl sizeof (((struct aac_synchronize_reply *)0)->Data));
5750942c5e3cSpl }
5751d7c5bf88Spl
5752b40e8a89Szhongyan gu - Sun Microsystems - Beijing China /*
5753b40e8a89Szhongyan gu - Sun Microsystems - Beijing China * Start/Stop unit (Power Management)
5754b40e8a89Szhongyan gu - Sun Microsystems - Beijing China */
5755b40e8a89Szhongyan gu - Sun Microsystems - Beijing China static void
aac_cmd_fib_startstop(struct aac_softstate * softs,struct aac_cmd * acp)5756b40e8a89Szhongyan gu - Sun Microsystems - Beijing China aac_cmd_fib_startstop(struct aac_softstate *softs, struct aac_cmd *acp)
5757b40e8a89Szhongyan gu - Sun Microsystems - Beijing China {
5758f42c2f53Szhongyan gu - Sun Microsystems - Beijing China ddi_acc_handle_t acc = acp->slotp->fib_acc_handle;
5759b40e8a89Szhongyan gu - Sun Microsystems - Beijing China struct aac_Container *cmd =
5760f42c2f53Szhongyan gu - Sun Microsystems - Beijing China (struct aac_Container *)&acp->slotp->fibp->data[0];
5761b40e8a89Szhongyan gu - Sun Microsystems - Beijing China union scsi_cdb *cdbp = (void *)acp->pkt->pkt_cdbp;
5762b40e8a89Szhongyan gu - Sun Microsystems - Beijing China
5763b40e8a89Szhongyan gu - Sun Microsystems - Beijing China acp->fib_size = AAC_FIB_SIZEOF(struct aac_Container);
5764b40e8a89Szhongyan gu - Sun Microsystems - Beijing China
5765f42c2f53Szhongyan gu - Sun Microsystems - Beijing China aac_cmd_fib_header(softs, acp, ContainerCommand);
5766b40e8a89Szhongyan gu - Sun Microsystems - Beijing China bzero(cmd, sizeof (*cmd) - CT_PACKET_SIZE);
5767b40e8a89Szhongyan gu - Sun Microsystems - Beijing China ddi_put32(acc, &cmd->Command, VM_ContainerConfig);
5768b40e8a89Szhongyan gu - Sun Microsystems - Beijing China ddi_put32(acc, &cmd->CTCommand.command, CT_PM_DRIVER_SUPPORT);
5769b40e8a89Szhongyan gu - Sun Microsystems - Beijing China ddi_put32(acc, &cmd->CTCommand.param[0], cdbp->cdb_opaque[4] & 1 ? \
5770b40e8a89Szhongyan gu - Sun Microsystems - Beijing China AAC_PM_DRIVERSUP_START_UNIT : AAC_PM_DRIVERSUP_STOP_UNIT);
5771b40e8a89Szhongyan gu - Sun Microsystems - Beijing China ddi_put32(acc, &cmd->CTCommand.param[1],
5772b40e8a89Szhongyan gu - Sun Microsystems - Beijing China ((struct aac_container *)acp->dvp)->cid);
5773b40e8a89Szhongyan gu - Sun Microsystems - Beijing China ddi_put32(acc, &cmd->CTCommand.param[2], cdbp->cdb_opaque[1] & 1);
5774b40e8a89Szhongyan gu - Sun Microsystems - Beijing China }
5775b40e8a89Szhongyan gu - Sun Microsystems - Beijing China
5776942c5e3cSpl /*
5777942c5e3cSpl * Init FIB for pass-through SCMD
5778942c5e3cSpl */
5779942c5e3cSpl static void
aac_cmd_fib_srb(struct aac_cmd * acp)5780942c5e3cSpl aac_cmd_fib_srb(struct aac_cmd *acp)
5781942c5e3cSpl {
5782f42c2f53Szhongyan gu - Sun Microsystems - Beijing China ddi_acc_handle_t acc = acp->slotp->fib_acc_handle;
5783f42c2f53Szhongyan gu - Sun Microsystems - Beijing China struct aac_srb *srb = (struct aac_srb *)&acp->slotp->fibp->data[0];
578458bc78c7SXin Chen uint8_t *cdb;
5785942c5e3cSpl
5786942c5e3cSpl ddi_put32(acc, &srb->function, SRBF_ExecuteScsi);
5787942c5e3cSpl ddi_put32(acc, &srb->retry_limit, 0);
5788942c5e3cSpl ddi_put32(acc, &srb->cdb_size, acp->cmdlen);
5789942c5e3cSpl ddi_put32(acc, &srb->timeout, 0); /* use driver timeout */
579058bc78c7SXin Chen if (acp->fibp == NULL) {
579158bc78c7SXin Chen if (acp->flags & AAC_CMD_BUF_READ)
579258bc78c7SXin Chen ddi_put32(acc, &srb->flags, SRB_DataIn);
579358bc78c7SXin Chen else if (acp->flags & AAC_CMD_BUF_WRITE)
579458bc78c7SXin Chen ddi_put32(acc, &srb->flags, SRB_DataOut);
579558bc78c7SXin Chen ddi_put32(acc, &srb->channel,
579658bc78c7SXin Chen ((struct aac_nondasd *)acp->dvp)->bus);
579758bc78c7SXin Chen ddi_put32(acc, &srb->id, ((struct aac_nondasd *)acp->dvp)->tid);
579858bc78c7SXin Chen ddi_put32(acc, &srb->lun, 0);
579958bc78c7SXin Chen cdb = acp->pkt->pkt_cdbp;
580058bc78c7SXin Chen } else {
580158bc78c7SXin Chen struct aac_srb *srb0 = (struct aac_srb *)&acp->fibp->data[0];
5802942c5e3cSpl
580358bc78c7SXin Chen ddi_put32(acc, &srb->flags, srb0->flags);
580458bc78c7SXin Chen ddi_put32(acc, &srb->channel, srb0->channel);
580558bc78c7SXin Chen ddi_put32(acc, &srb->id, srb0->id);
580658bc78c7SXin Chen ddi_put32(acc, &srb->lun, srb0->lun);
580758bc78c7SXin Chen cdb = srb0->cdb;
580858bc78c7SXin Chen }
580958bc78c7SXin Chen ddi_rep_put8(acc, cdb, srb->cdb, acp->cmdlen, DDI_DEV_AUTOINCR);
5810942c5e3cSpl }
5811382c8bcaSpl
5812942c5e3cSpl static void
aac_cmd_fib_scsi32(struct aac_softstate * softs,struct aac_cmd * acp)5813942c5e3cSpl aac_cmd_fib_scsi32(struct aac_softstate *softs, struct aac_cmd *acp)
5814942c5e3cSpl {
5815942c5e3cSpl ddi_acc_handle_t acc = acp->slotp->fib_acc_handle;
5816942c5e3cSpl struct aac_srb *srb = (struct aac_srb *)&acp->slotp->fibp->data[0];
5817942c5e3cSpl struct aac_sg_entry *sgp;
5818942c5e3cSpl struct aac_sge *sge;
5819830d82f7Spl
5820942c5e3cSpl acp->fib_size = sizeof (struct aac_fib_header) + \
5821942c5e3cSpl sizeof (struct aac_srb) - sizeof (struct aac_sg_entry) + \
5822942c5e3cSpl acp->left_cookien * sizeof (struct aac_sg_entry);
58237c478bd9Sstevel@tonic-gate
5824942c5e3cSpl /* Fill FIB and SRB headers, and copy cdb */
5825f42c2f53Szhongyan gu - Sun Microsystems - Beijing China aac_cmd_fib_header(softs, acp, ScsiPortCommand);
5826942c5e3cSpl aac_cmd_fib_srb(acp);
5827c9487164Spl
5828942c5e3cSpl /* Fill SG table */
5829942c5e3cSpl ddi_put32(acc, &srb->sg.SgCount, acp->left_cookien);
5830942c5e3cSpl ddi_put32(acc, &srb->count, acp->bcount);
5831d7c5bf88Spl
5832942c5e3cSpl for (sge = &acp->sgt[0], sgp = &srb->sg.SgEntry[0];
5833942c5e3cSpl sge < &acp->sgt[acp->left_cookien]; sge++, sgp++) {
5834942c5e3cSpl ddi_put32(acc, &sgp->SgAddress, sge->addr.ad32);
5835942c5e3cSpl ddi_put32(acc, &sgp->SgByteCount, sge->bcount);
5836942c5e3cSpl }
5837942c5e3cSpl }
5838830d82f7Spl
5839942c5e3cSpl static void
aac_cmd_fib_scsi64(struct aac_softstate * softs,struct aac_cmd * acp)5840942c5e3cSpl aac_cmd_fib_scsi64(struct aac_softstate *softs, struct aac_cmd *acp)
5841942c5e3cSpl {
5842942c5e3cSpl ddi_acc_handle_t acc = acp->slotp->fib_acc_handle;
5843942c5e3cSpl struct aac_srb *srb = (struct aac_srb *)&acp->slotp->fibp->data[0];
5844942c5e3cSpl struct aac_sg_entry64 *sgp;
5845942c5e3cSpl struct aac_sge *sge;
5846942c5e3cSpl
5847942c5e3cSpl acp->fib_size = sizeof (struct aac_fib_header) + \
5848942c5e3cSpl sizeof (struct aac_srb) - sizeof (struct aac_sg_entry) + \
5849942c5e3cSpl acp->left_cookien * sizeof (struct aac_sg_entry64);
5850942c5e3cSpl
5851942c5e3cSpl /* Fill FIB and SRB headers, and copy cdb */
5852f42c2f53Szhongyan gu - Sun Microsystems - Beijing China aac_cmd_fib_header(softs, acp, ScsiPortCommandU64);
5853942c5e3cSpl aac_cmd_fib_srb(acp);
5854942c5e3cSpl
5855942c5e3cSpl /* Fill SG table */
5856942c5e3cSpl ddi_put32(acc, &srb->sg.SgCount, acp->left_cookien);
5857942c5e3cSpl ddi_put32(acc, &srb->count, acp->bcount);
5858942c5e3cSpl
5859942c5e3cSpl for (sge = &acp->sgt[0],
5860942c5e3cSpl sgp = &((struct aac_sg_table64 *)&srb->sg)->SgEntry64[0];
5861942c5e3cSpl sge < &acp->sgt[acp->left_cookien]; sge++, sgp++) {
5862942c5e3cSpl ddi_put32(acc, AAC_LO32(&sgp->SgAddress), sge->addr.ad64.lo);
5863942c5e3cSpl ddi_put32(acc, AAC_HI32(&sgp->SgAddress), sge->addr.ad64.hi);
5864942c5e3cSpl ddi_put32(acc, &sgp->SgByteCount, sge->bcount);
58657c478bd9Sstevel@tonic-gate }
58667c478bd9Sstevel@tonic-gate }
58677c478bd9Sstevel@tonic-gate
5868382c8bcaSpl static int
aac_cmd_slot_bind(struct aac_softstate * softs,struct aac_cmd * acp)5869382c8bcaSpl aac_cmd_slot_bind(struct aac_softstate *softs, struct aac_cmd *acp)
5870382c8bcaSpl {
5871382c8bcaSpl struct aac_slot *slotp;
5872382c8bcaSpl
5873382c8bcaSpl if (slotp = aac_get_slot(softs)) {
5874382c8bcaSpl acp->slotp = slotp;
5875382c8bcaSpl slotp->acp = acp;
5876942c5e3cSpl acp->aac_cmd_fib(softs, acp);
5877382c8bcaSpl (void) ddi_dma_sync(slotp->fib_dma_handle, 0, 0,
5878382c8bcaSpl DDI_DMA_SYNC_FORDEV);
5879382c8bcaSpl return (AACOK);
5880382c8bcaSpl }
5881382c8bcaSpl return (AACERR);
5882382c8bcaSpl }
5883382c8bcaSpl
5884382c8bcaSpl static int
aac_bind_io(struct aac_softstate * softs,struct aac_cmd * acp)5885382c8bcaSpl aac_bind_io(struct aac_softstate *softs, struct aac_cmd *acp)
5886382c8bcaSpl {
588758bc78c7SXin Chen struct aac_device *dvp = acp->dvp;
5888382c8bcaSpl int q = AAC_CMDQ(acp);
5889382c8bcaSpl
58901ee13a44SXinChen if (softs->bus_ncmds[q] < softs->bus_throttle[q]) {
58911ee13a44SXinChen if (dvp) {
58921ee13a44SXinChen if (dvp->ncmds[q] < dvp->throttle[q]) {
58931ee13a44SXinChen if (!(acp->flags & AAC_CMD_NTAG) ||
58941ee13a44SXinChen dvp->ncmds[q] == 0) {
58951ee13a44SXinChen return (aac_cmd_slot_bind(softs, acp));
58961ee13a44SXinChen }
58971ee13a44SXinChen ASSERT(q == AAC_CMDQ_ASYNC);
58981ee13a44SXinChen aac_set_throttle(softs, dvp, AAC_CMDQ_ASYNC,
58991ee13a44SXinChen AAC_THROTTLE_DRAIN);
5900382c8bcaSpl }
59011ee13a44SXinChen } else {
59021ee13a44SXinChen return (aac_cmd_slot_bind(softs, acp));
5903382c8bcaSpl }
5904382c8bcaSpl }
5905382c8bcaSpl return (AACERR);
5906382c8bcaSpl }
5907382c8bcaSpl
5908f42c2f53Szhongyan gu - Sun Microsystems - Beijing China static int
aac_sync_fib_slot_bind(struct aac_softstate * softs,struct aac_cmd * acp)5909f42c2f53Szhongyan gu - Sun Microsystems - Beijing China aac_sync_fib_slot_bind(struct aac_softstate *softs, struct aac_cmd *acp)
5910f42c2f53Szhongyan gu - Sun Microsystems - Beijing China {
5911f42c2f53Szhongyan gu - Sun Microsystems - Beijing China struct aac_slot *slotp;
5912f42c2f53Szhongyan gu - Sun Microsystems - Beijing China
59131ee13a44SXinChen while (softs->sync_ac.slotp)
59141ee13a44SXinChen cv_wait(&softs->sync_fib_cv, &softs->io_lock);
59151ee13a44SXinChen
5916f42c2f53Szhongyan gu - Sun Microsystems - Beijing China if (slotp = aac_get_slot(softs)) {
5917f42c2f53Szhongyan gu - Sun Microsystems - Beijing China ASSERT(acp->slotp == NULL);
5918f42c2f53Szhongyan gu - Sun Microsystems - Beijing China
5919f42c2f53Szhongyan gu - Sun Microsystems - Beijing China acp->slotp = slotp;
5920f42c2f53Szhongyan gu - Sun Microsystems - Beijing China slotp->acp = acp;
5921f42c2f53Szhongyan gu - Sun Microsystems - Beijing China return (AACOK);
5922f42c2f53Szhongyan gu - Sun Microsystems - Beijing China }
5923f42c2f53Szhongyan gu - Sun Microsystems - Beijing China return (AACERR);
5924f42c2f53Szhongyan gu - Sun Microsystems - Beijing China }
5925f42c2f53Szhongyan gu - Sun Microsystems - Beijing China
5926f42c2f53Szhongyan gu - Sun Microsystems - Beijing China static void
aac_sync_fib_slot_release(struct aac_softstate * softs,struct aac_cmd * acp)5927f42c2f53Szhongyan gu - Sun Microsystems - Beijing China aac_sync_fib_slot_release(struct aac_softstate *softs, struct aac_cmd *acp)
5928f42c2f53Szhongyan gu - Sun Microsystems - Beijing China {
5929f42c2f53Szhongyan gu - Sun Microsystems - Beijing China ASSERT(acp->slotp);
5930f42c2f53Szhongyan gu - Sun Microsystems - Beijing China
5931f42c2f53Szhongyan gu - Sun Microsystems - Beijing China aac_release_slot(softs, acp->slotp);
5932f42c2f53Szhongyan gu - Sun Microsystems - Beijing China acp->slotp->acp = NULL;
5933f42c2f53Szhongyan gu - Sun Microsystems - Beijing China acp->slotp = NULL;
59341ee13a44SXinChen
59351ee13a44SXinChen cv_signal(&softs->sync_fib_cv);
5936f42c2f53Szhongyan gu - Sun Microsystems - Beijing China }
5937f42c2f53Szhongyan gu - Sun Microsystems - Beijing China
5938830d82f7Spl static void
aac_start_io(struct aac_softstate * softs,struct aac_cmd * acp)5939382c8bcaSpl aac_start_io(struct aac_softstate *softs, struct aac_cmd *acp)
5940830d82f7Spl {
5941382c8bcaSpl struct aac_slot *slotp = acp->slotp;
5942382c8bcaSpl int q = AAC_CMDQ(acp);
5943c9487164Spl int rval;
5944830d82f7Spl
5945830d82f7Spl /* Set ac and pkt */
5946c9487164Spl if (acp->pkt) { /* ac from ioctl has no pkt */
5947382c8bcaSpl acp->pkt->pkt_state |=
5948d7c5bf88Spl STATE_GOT_BUS | STATE_GOT_TARGET | STATE_SENT_CMD;
5949c9487164Spl }
5950382c8bcaSpl if (acp->timeout) /* 0 indicates no timeout */
5951382c8bcaSpl acp->timeout += aac_timebase + aac_tick;
5952830d82f7Spl
5953382c8bcaSpl if (acp->dvp)
5954382c8bcaSpl acp->dvp->ncmds[q]++;
5955382c8bcaSpl softs->bus_ncmds[q]++;
5956382c8bcaSpl aac_cmd_enqueue(&softs->q_busy, acp);
5957830d82f7Spl
595858bc78c7SXin Chen AACDB_PRINT_FIB(softs, slotp);
595958bc78c7SXin Chen
5960830d82f7Spl if (softs->flags & AAC_FLAGS_NEW_COMM) {
5961c9487164Spl rval = aac_send_command(softs, slotp);
5962830d82f7Spl } else {
5963830d82f7Spl /*
5964830d82f7Spl * If fib can not be enqueued, the adapter is in an abnormal
5965830d82f7Spl * state, there will be no interrupt to us.
5966830d82f7Spl */
5967c9487164Spl rval = aac_fib_enqueue(softs, AAC_ADAP_NORM_CMD_Q,
5968942c5e3cSpl slotp->fib_phyaddr, acp->fib_size);
5969830d82f7Spl }
5970830d82f7Spl
59717675db54Syw if (aac_check_dma_handle(slotp->fib_dma_handle) != DDI_SUCCESS)
59727675db54Syw ddi_fm_service_impact(softs->devinfo_p, DDI_SERVICE_UNAFFECTED);
59737675db54Syw
5974830d82f7Spl /*
5975830d82f7Spl * NOTE: We send command only when slots availabe, so should never
5976830d82f7Spl * reach here.
5977830d82f7Spl */
5978c9487164Spl if (rval != AACOK) {
59791dd0a2dbSpl AACDB_PRINT(softs, CE_NOTE, "SCMD send failed");
5980d7c5bf88Spl if (acp->pkt) {
5981d7c5bf88Spl acp->pkt->pkt_state &= ~STATE_SENT_CMD;
5982d7c5bf88Spl aac_set_pkt_reason(softs, acp, CMD_INCOMPLETE, 0);
5983d7c5bf88Spl }
5984382c8bcaSpl aac_end_io(softs, acp);
5985382c8bcaSpl if (!(acp->flags & (AAC_CMD_NO_INTR | AAC_CMD_NO_CB)))
5986d7c5bf88Spl ddi_trigger_softintr(softs->softint_id);
5987830d82f7Spl }
5988830d82f7Spl }
5989830d82f7Spl
59907c478bd9Sstevel@tonic-gate static void
aac_start_waitq(struct aac_softstate * softs,struct aac_cmd_queue * q)5991382c8bcaSpl aac_start_waitq(struct aac_softstate *softs, struct aac_cmd_queue *q)
59927c478bd9Sstevel@tonic-gate {
5993382c8bcaSpl struct aac_cmd *acp, *next_acp;
59947c478bd9Sstevel@tonic-gate
5995830d82f7Spl /* Serve as many waiting io's as possible */
5996382c8bcaSpl for (acp = q->q_head; acp; acp = next_acp) {
5997382c8bcaSpl next_acp = acp->next;
5998382c8bcaSpl if (aac_bind_io(softs, acp) == AACOK) {
5999382c8bcaSpl aac_cmd_delete(q, acp);
6000382c8bcaSpl aac_start_io(softs, acp);
6001830d82f7Spl }
6002382c8bcaSpl if (softs->free_io_slot_head == NULL)
6003382c8bcaSpl break;
60047c478bd9Sstevel@tonic-gate }
60057c478bd9Sstevel@tonic-gate }
60067c478bd9Sstevel@tonic-gate
6007382c8bcaSpl static void
aac_start_waiting_io(struct aac_softstate * softs)6008382c8bcaSpl aac_start_waiting_io(struct aac_softstate *softs)
6009382c8bcaSpl {
6010382c8bcaSpl /*
6011382c8bcaSpl * Sync FIB io is served before async FIB io so that io requests
6012382c8bcaSpl * sent by interactive userland commands get responded asap.
6013382c8bcaSpl */
6014382c8bcaSpl if (softs->q_wait[AAC_CMDQ_SYNC].q_head)
6015382c8bcaSpl aac_start_waitq(softs, &softs->q_wait[AAC_CMDQ_SYNC]);
6016382c8bcaSpl if (softs->q_wait[AAC_CMDQ_ASYNC].q_head)
6017382c8bcaSpl aac_start_waitq(softs, &softs->q_wait[AAC_CMDQ_ASYNC]);
6018382c8bcaSpl }
6019382c8bcaSpl
60207c478bd9Sstevel@tonic-gate static void
aac_drain_comp_q(struct aac_softstate * softs)60217c478bd9Sstevel@tonic-gate aac_drain_comp_q(struct aac_softstate *softs)
60227c478bd9Sstevel@tonic-gate {
6023c9487164Spl struct aac_cmd *acp;
6024830d82f7Spl struct scsi_pkt *pkt;
60257c478bd9Sstevel@tonic-gate
6026382c8bcaSpl /*CONSTCOND*/
6027382c8bcaSpl while (1) {
6028382c8bcaSpl mutex_enter(&softs->q_comp_mutex);
6029382c8bcaSpl acp = aac_cmd_dequeue(&softs->q_comp);
6030382c8bcaSpl mutex_exit(&softs->q_comp_mutex);
6031382c8bcaSpl if (acp != NULL) {
6032382c8bcaSpl ASSERT(acp->pkt != NULL);
6033382c8bcaSpl pkt = acp->pkt;
6034830d82f7Spl
6035382c8bcaSpl if (pkt->pkt_reason == CMD_CMPLT) {
6036382c8bcaSpl /*
6037382c8bcaSpl * Consistent packets need to be sync'ed first
6038382c8bcaSpl */
6039382c8bcaSpl if ((acp->flags & AAC_CMD_CONSISTENT) &&
6040382c8bcaSpl (acp->flags & AAC_CMD_BUF_READ)) {
6041382c8bcaSpl if (aac_dma_sync_ac(acp) != AACOK) {
6042382c8bcaSpl ddi_fm_service_impact(
6043382c8bcaSpl softs->devinfo_p,
6044382c8bcaSpl DDI_SERVICE_UNAFFECTED);
6045382c8bcaSpl pkt->pkt_reason = CMD_TRAN_ERR;
6046382c8bcaSpl pkt->pkt_statistics = 0;
6047382c8bcaSpl }
6048382c8bcaSpl }
6049382c8bcaSpl if ((aac_check_acc_handle(softs-> \
6050382c8bcaSpl comm_space_acc_handle) != DDI_SUCCESS) ||
6051382c8bcaSpl (aac_check_acc_handle(softs-> \
6052382c8bcaSpl pci_mem_handle) != DDI_SUCCESS)) {
6053382c8bcaSpl ddi_fm_service_impact(softs->devinfo_p,
6054382c8bcaSpl DDI_SERVICE_UNAFFECTED);
6055382c8bcaSpl ddi_fm_acc_err_clear(softs-> \
6056382c8bcaSpl pci_mem_handle, DDI_FME_VER0);
6057382c8bcaSpl pkt->pkt_reason = CMD_TRAN_ERR;
6058382c8bcaSpl pkt->pkt_statistics = 0;
6059382c8bcaSpl }
6060382c8bcaSpl if (aac_check_dma_handle(softs-> \
6061382c8bcaSpl comm_space_dma_handle) != DDI_SUCCESS) {
60627675db54Syw ddi_fm_service_impact(softs->devinfo_p,
60637675db54Syw DDI_SERVICE_UNAFFECTED);
60647675db54Syw pkt->pkt_reason = CMD_TRAN_ERR;
60657675db54Syw pkt->pkt_statistics = 0;
60667675db54Syw }
60677675db54Syw }
60689c57abc8Ssrivijitha dugganapalli scsi_hba_pkt_comp(pkt);
6069382c8bcaSpl } else {
6070382c8bcaSpl break;
6071d7c5bf88Spl }
6072830d82f7Spl }
60737c478bd9Sstevel@tonic-gate }
60747c478bd9Sstevel@tonic-gate
60757c478bd9Sstevel@tonic-gate static int
aac_alloc_fib(struct aac_softstate * softs,struct aac_slot * slotp)6076830d82f7Spl aac_alloc_fib(struct aac_softstate *softs, struct aac_slot *slotp)
60777c478bd9Sstevel@tonic-gate {
60787c478bd9Sstevel@tonic-gate size_t rlen;
60797c478bd9Sstevel@tonic-gate ddi_dma_cookie_t cookie;
60807c478bd9Sstevel@tonic-gate uint_t cookien;
60817c478bd9Sstevel@tonic-gate
6082830d82f7Spl /* Allocate FIB dma resource */
6083830d82f7Spl if (ddi_dma_alloc_handle(
6084c9487164Spl softs->devinfo_p,
6085c9487164Spl &softs->addr_dma_attr,
6086c9487164Spl DDI_DMA_SLEEP,
6087c9487164Spl NULL,
6088c9487164Spl &slotp->fib_dma_handle) != DDI_SUCCESS) {
60891dd0a2dbSpl AACDB_PRINT(softs, CE_WARN,
60901dd0a2dbSpl "Cannot alloc dma handle for slot fib area");
6091830d82f7Spl goto error;
6092830d82f7Spl }
6093830d82f7Spl if (ddi_dma_mem_alloc(
6094c9487164Spl slotp->fib_dma_handle,
6095c9487164Spl softs->aac_max_fib_size,
609658bc78c7SXin Chen &softs->acc_attr,
6097c9487164Spl DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
6098c9487164Spl DDI_DMA_SLEEP,
6099c9487164Spl NULL,
6100c9487164Spl (caddr_t *)&slotp->fibp,
6101c9487164Spl &rlen,
6102c9487164Spl &slotp->fib_acc_handle) != DDI_SUCCESS) {
61031dd0a2dbSpl AACDB_PRINT(softs, CE_WARN,
61041dd0a2dbSpl "Cannot alloc mem for slot fib area");
6105830d82f7Spl goto error;
6106830d82f7Spl }
6107830d82f7Spl if (ddi_dma_addr_bind_handle(
6108c9487164Spl slotp->fib_dma_handle,
6109c9487164Spl NULL,
6110c9487164Spl (caddr_t)slotp->fibp,
6111c9487164Spl softs->aac_max_fib_size,
6112c9487164Spl DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
6113c9487164Spl DDI_DMA_SLEEP,
6114c9487164Spl NULL,
6115c9487164Spl &cookie,
6116c9487164Spl &cookien) != DDI_DMA_MAPPED) {
61171dd0a2dbSpl AACDB_PRINT(softs, CE_WARN,
61181dd0a2dbSpl "dma bind failed for slot fib area");
6119830d82f7Spl goto error;
6120830d82f7Spl }
61217675db54Syw
61227675db54Syw /* Check dma handles allocated in fib attach */
61237675db54Syw if (aac_check_dma_handle(slotp->fib_dma_handle) != DDI_SUCCESS) {
61247675db54Syw ddi_fm_service_impact(softs->devinfo_p, DDI_SERVICE_LOST);
61257675db54Syw goto error;
61267675db54Syw }
61277675db54Syw
61287675db54Syw /* Check acc handles allocated in fib attach */
61297675db54Syw if (aac_check_acc_handle(slotp->fib_acc_handle) != DDI_SUCCESS) {
61307675db54Syw ddi_fm_service_impact(softs->devinfo_p, DDI_SERVICE_LOST);
61317675db54Syw goto error;
61327675db54Syw }
61337675db54Syw
6134830d82f7Spl slotp->fib_phyaddr = cookie.dmac_laddress;
6135830d82f7Spl return (AACOK);
6136830d82f7Spl
6137830d82f7Spl error:
6138830d82f7Spl if (slotp->fib_acc_handle) {
6139830d82f7Spl ddi_dma_mem_free(&slotp->fib_acc_handle);
6140830d82f7Spl slotp->fib_acc_handle = NULL;
6141830d82f7Spl }
6142830d82f7Spl if (slotp->fib_dma_handle) {
6143830d82f7Spl ddi_dma_free_handle(&slotp->fib_dma_handle);
6144830d82f7Spl slotp->fib_dma_handle = NULL;
61457c478bd9Sstevel@tonic-gate }
6146830d82f7Spl return (AACERR);
61477c478bd9Sstevel@tonic-gate }
61487c478bd9Sstevel@tonic-gate
61497c478bd9Sstevel@tonic-gate static void
aac_free_fib(struct aac_slot * slotp)6150830d82f7Spl aac_free_fib(struct aac_slot *slotp)
6151830d82f7Spl {
6152830d82f7Spl (void) ddi_dma_unbind_handle(slotp->fib_dma_handle);
6153830d82f7Spl ddi_dma_mem_free(&slotp->fib_acc_handle);
6154830d82f7Spl slotp->fib_acc_handle = NULL;
6155830d82f7Spl ddi_dma_free_handle(&slotp->fib_dma_handle);
6156830d82f7Spl slotp->fib_dma_handle = NULL;
6157830d82f7Spl slotp->fib_phyaddr = 0;
6158830d82f7Spl }
6159830d82f7Spl
6160942c5e3cSpl static void
aac_alloc_fibs(struct aac_softstate * softs)6161942c5e3cSpl aac_alloc_fibs(struct aac_softstate *softs)
6162942c5e3cSpl {
6163942c5e3cSpl int i;
6164942c5e3cSpl struct aac_slot *slotp;
6165942c5e3cSpl
6166942c5e3cSpl for (i = 0; i < softs->total_slots &&
6167942c5e3cSpl softs->total_fibs < softs->total_slots; i++) {
6168942c5e3cSpl slotp = &(softs->io_slot[i]);
6169942c5e3cSpl if (slotp->fib_phyaddr)
6170942c5e3cSpl continue;
6171942c5e3cSpl if (aac_alloc_fib(softs, slotp) != AACOK)
6172942c5e3cSpl break;
6173942c5e3cSpl
6174942c5e3cSpl /* Insert the slot to the free slot list */
6175942c5e3cSpl aac_release_slot(softs, slotp);
6176942c5e3cSpl softs->total_fibs++;
6177942c5e3cSpl }
6178942c5e3cSpl }
6179942c5e3cSpl
6180d7c5bf88Spl static void
aac_destroy_fibs(struct aac_softstate * softs)6181d7c5bf88Spl aac_destroy_fibs(struct aac_softstate *softs)
6182d7c5bf88Spl {
6183382c8bcaSpl struct aac_slot *slotp;
6184d7c5bf88Spl
6185382c8bcaSpl while ((slotp = softs->free_io_slot_head) != NULL) {
6186382c8bcaSpl ASSERT(slotp->fib_phyaddr);
6187382c8bcaSpl softs->free_io_slot_head = slotp->next;
6188d7c5bf88Spl aac_free_fib(slotp);
6189382c8bcaSpl ASSERT(slotp->index == (slotp - softs->io_slot));
6190d7c5bf88Spl softs->total_fibs--;
6191d7c5bf88Spl }
6192d7c5bf88Spl ASSERT(softs->total_fibs == 0);
6193d7c5bf88Spl }
6194d7c5bf88Spl
6195830d82f7Spl static int
aac_create_slots(struct aac_softstate * softs)6196830d82f7Spl aac_create_slots(struct aac_softstate *softs)
61977c478bd9Sstevel@tonic-gate {
61987c478bd9Sstevel@tonic-gate int i;
61997c478bd9Sstevel@tonic-gate
6200942c5e3cSpl softs->total_slots = softs->aac_max_fibs;
6201830d82f7Spl softs->io_slot = kmem_zalloc(sizeof (struct aac_slot) * \
6202942c5e3cSpl softs->total_slots, KM_SLEEP);
6203830d82f7Spl if (softs->io_slot == NULL) {
62041dd0a2dbSpl AACDB_PRINT(softs, CE_WARN, "Cannot allocate slot");
6205830d82f7Spl return (AACERR);
62067c478bd9Sstevel@tonic-gate }
6207382c8bcaSpl for (i = 0; i < softs->total_slots; i++)
6208382c8bcaSpl softs->io_slot[i].index = i;
6209382c8bcaSpl softs->free_io_slot_head = NULL;
6210830d82f7Spl softs->total_fibs = 0;
6211830d82f7Spl return (AACOK);
6212830d82f7Spl }
6213830d82f7Spl
6214830d82f7Spl static void
aac_destroy_slots(struct aac_softstate * softs)6215830d82f7Spl aac_destroy_slots(struct aac_softstate *softs)
6216830d82f7Spl {
6217382c8bcaSpl ASSERT(softs->free_io_slot_head == NULL);
6218830d82f7Spl
6219830d82f7Spl kmem_free(softs->io_slot, sizeof (struct aac_slot) * \
6220c9487164Spl softs->total_slots);
6221830d82f7Spl softs->io_slot = NULL;
6222830d82f7Spl softs->total_slots = 0;
62237c478bd9Sstevel@tonic-gate }
62247c478bd9Sstevel@tonic-gate
6225830d82f7Spl struct aac_slot *
aac_get_slot(struct aac_softstate * softs)62267c478bd9Sstevel@tonic-gate aac_get_slot(struct aac_softstate *softs)
62277c478bd9Sstevel@tonic-gate {
6228382c8bcaSpl struct aac_slot *slotp;
62297c478bd9Sstevel@tonic-gate
6230382c8bcaSpl if ((slotp = softs->free_io_slot_head) != NULL) {
6231830d82f7Spl softs->free_io_slot_head = slotp->next;
6232382c8bcaSpl slotp->next = NULL;
62337c478bd9Sstevel@tonic-gate }
6234830d82f7Spl return (slotp);
6235830d82f7Spl }
62367c478bd9Sstevel@tonic-gate
6237382c8bcaSpl static void
aac_release_slot(struct aac_softstate * softs,struct aac_slot * slotp)6238830d82f7Spl aac_release_slot(struct aac_softstate *softs, struct aac_slot *slotp)
62397c478bd9Sstevel@tonic-gate {
6240382c8bcaSpl ASSERT((slotp->index >= 0) && (slotp->index < softs->total_slots));
6241382c8bcaSpl ASSERT(slotp == &softs->io_slot[slotp->index]);
62427c478bd9Sstevel@tonic-gate
6243830d82f7Spl slotp->acp = NULL;
6244382c8bcaSpl slotp->next = softs->free_io_slot_head;
6245382c8bcaSpl softs->free_io_slot_head = slotp;
62467c478bd9Sstevel@tonic-gate }
62477c478bd9Sstevel@tonic-gate
6248d7c5bf88Spl int
aac_do_io(struct aac_softstate * softs,struct aac_cmd * acp)6249d7c5bf88Spl aac_do_io(struct aac_softstate *softs, struct aac_cmd *acp)
6250d7c5bf88Spl {
6251382c8bcaSpl if (aac_bind_io(softs, acp) == AACOK)
6252382c8bcaSpl aac_start_io(softs, acp);
6253382c8bcaSpl else
6254382c8bcaSpl aac_cmd_enqueue(&softs->q_wait[AAC_CMDQ(acp)], acp);
6255382c8bcaSpl
6256382c8bcaSpl if (!(acp->flags & (AAC_CMD_NO_CB | AAC_CMD_NO_INTR)))
6257d7c5bf88Spl return (TRAN_ACCEPT);
6258382c8bcaSpl /*
6259382c8bcaSpl * Because sync FIB is always 512 bytes and used for critical
6260382c8bcaSpl * functions, async FIB is used for poll IO.
6261382c8bcaSpl */
6262382c8bcaSpl if (acp->flags & AAC_CMD_NO_INTR) {
6263382c8bcaSpl if (aac_do_poll_io(softs, acp) == AACOK)
6264382c8bcaSpl return (TRAN_ACCEPT);
6265382c8bcaSpl } else {
6266382c8bcaSpl if (aac_do_sync_io(softs, acp) == AACOK)
6267382c8bcaSpl return (TRAN_ACCEPT);
6268d7c5bf88Spl }
6269382c8bcaSpl return (TRAN_BADPKT);
6270d7c5bf88Spl }
6271d7c5bf88Spl
62727c478bd9Sstevel@tonic-gate static int
aac_do_poll_io(struct aac_softstate * softs,struct aac_cmd * acp)6273830d82f7Spl aac_do_poll_io(struct aac_softstate *softs, struct aac_cmd *acp)
62747c478bd9Sstevel@tonic-gate {
6275382c8bcaSpl int (*intr_handler)(struct aac_softstate *);
6276830d82f7Spl
6277830d82f7Spl /*
6278382c8bcaSpl * Interrupt is disabled, we have to poll the adapter by ourselves.
6279830d82f7Spl */
6280382c8bcaSpl intr_handler = (softs->flags & AAC_FLAGS_NEW_COMM) ?
6281382c8bcaSpl aac_process_intr_new : aac_process_intr_old;
6282382c8bcaSpl while (!(acp->flags & (AAC_CMD_CMPLT | AAC_CMD_ABORT))) {
6283382c8bcaSpl int i = AAC_POLL_TIME * 1000;
6284d7c5bf88Spl
6285382c8bcaSpl AAC_BUSYWAIT((intr_handler(softs) != AAC_DB_RESPONSE_READY), i);
6286382c8bcaSpl if (i == 0)
628758bc78c7SXin Chen aac_cmd_timeout(softs, acp);
62887c478bd9Sstevel@tonic-gate }
62897c478bd9Sstevel@tonic-gate
6290382c8bcaSpl ddi_trigger_softintr(softs->softint_id);
6291382c8bcaSpl
62927675db54Syw if ((acp->flags & AAC_CMD_CMPLT) && !(acp->flags & AAC_CMD_ERR))
6293d7c5bf88Spl return (AACOK);
6294d7c5bf88Spl return (AACERR);
62957c478bd9Sstevel@tonic-gate }
62967c478bd9Sstevel@tonic-gate
6297d7c5bf88Spl static int
aac_do_sync_io(struct aac_softstate * softs,struct aac_cmd * acp)6298382c8bcaSpl aac_do_sync_io(struct aac_softstate *softs, struct aac_cmd *acp)
62997c478bd9Sstevel@tonic-gate {
6300382c8bcaSpl ASSERT(softs && acp);
6301830d82f7Spl
6302382c8bcaSpl while (!(acp->flags & (AAC_CMD_CMPLT | AAC_CMD_ABORT)))
6303382c8bcaSpl cv_wait(&softs->event, &softs->io_lock);
6304830d82f7Spl
6305382c8bcaSpl if (acp->flags & AAC_CMD_CMPLT)
6306382c8bcaSpl return (AACOK);
6307382c8bcaSpl return (AACERR);
63087c478bd9Sstevel@tonic-gate }
63097c478bd9Sstevel@tonic-gate
63107675db54Syw static int
aac_dma_sync_ac(struct aac_cmd * acp)6311d7c5bf88Spl aac_dma_sync_ac(struct aac_cmd *acp)
63127c478bd9Sstevel@tonic-gate {
6313d7c5bf88Spl if (acp->buf_dma_handle) {
6314d7c5bf88Spl if (acp->flags & AAC_CMD_BUF_WRITE) {
6315d7c5bf88Spl if (acp->abp != NULL)
6316d7c5bf88Spl ddi_rep_put8(acp->abh,
6317d7c5bf88Spl (uint8_t *)acp->bp->b_un.b_addr,
6318d7c5bf88Spl (uint8_t *)acp->abp, acp->bp->b_bcount,
6319d7c5bf88Spl DDI_DEV_AUTOINCR);
6320d7c5bf88Spl (void) ddi_dma_sync(acp->buf_dma_handle, 0, 0,
6321d7c5bf88Spl DDI_DMA_SYNC_FORDEV);
6322d7c5bf88Spl } else {
6323d7c5bf88Spl (void) ddi_dma_sync(acp->buf_dma_handle, 0, 0,
6324d7c5bf88Spl DDI_DMA_SYNC_FORCPU);
63257675db54Syw if (aac_check_dma_handle(acp->buf_dma_handle) !=
63267675db54Syw DDI_SUCCESS)
63277675db54Syw return (AACERR);
6328d7c5bf88Spl if (acp->abp != NULL)
6329d7c5bf88Spl ddi_rep_get8(acp->abh,
6330d7c5bf88Spl (uint8_t *)acp->bp->b_un.b_addr,
6331d7c5bf88Spl (uint8_t *)acp->abp, acp->bp->b_bcount,
6332d7c5bf88Spl DDI_DEV_AUTOINCR);
6333d7c5bf88Spl }
6334d7c5bf88Spl }
63357675db54Syw return (AACOK);
63367c478bd9Sstevel@tonic-gate }
63377c478bd9Sstevel@tonic-gate
63380749e8deSXin Chen - Sun Microsystems - Beijing China /*
63390749e8deSXin Chen - Sun Microsystems - Beijing China * Copy AIF from adapter to the empty AIF slot and inform AIF threads
63400749e8deSXin Chen - Sun Microsystems - Beijing China */
63410749e8deSXin Chen - Sun Microsystems - Beijing China static void
aac_save_aif(struct aac_softstate * softs,ddi_acc_handle_t acc,struct aac_fib * fibp0,int fib_size0)63420749e8deSXin Chen - Sun Microsystems - Beijing China aac_save_aif(struct aac_softstate *softs, ddi_acc_handle_t acc,
63430749e8deSXin Chen - Sun Microsystems - Beijing China struct aac_fib *fibp0, int fib_size0)
63440749e8deSXin Chen - Sun Microsystems - Beijing China {
63450749e8deSXin Chen - Sun Microsystems - Beijing China struct aac_fib *fibp; /* FIB in AIF queue */
63460749e8deSXin Chen - Sun Microsystems - Beijing China int fib_size;
63470749e8deSXin Chen - Sun Microsystems - Beijing China uint16_t fib_command;
63480749e8deSXin Chen - Sun Microsystems - Beijing China int current, next;
63490749e8deSXin Chen - Sun Microsystems - Beijing China
63500749e8deSXin Chen - Sun Microsystems - Beijing China /* Ignore non AIF messages */
63510749e8deSXin Chen - Sun Microsystems - Beijing China fib_command = ddi_get16(acc, &fibp0->Header.Command);
63520749e8deSXin Chen - Sun Microsystems - Beijing China if (fib_command != AifRequest) {
63530749e8deSXin Chen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "!Unknown command from controller");
63540749e8deSXin Chen - Sun Microsystems - Beijing China return;
63550749e8deSXin Chen - Sun Microsystems - Beijing China }
63560749e8deSXin Chen - Sun Microsystems - Beijing China
63570749e8deSXin Chen - Sun Microsystems - Beijing China mutex_enter(&softs->aifq_mutex);
63580749e8deSXin Chen - Sun Microsystems - Beijing China
63590749e8deSXin Chen - Sun Microsystems - Beijing China /* Save AIF */
63600749e8deSXin Chen - Sun Microsystems - Beijing China fibp = &softs->aifq[softs->aifq_idx].d;
63610749e8deSXin Chen - Sun Microsystems - Beijing China fib_size = (fib_size0 > AAC_FIB_SIZE) ? AAC_FIB_SIZE : fib_size0;
63620749e8deSXin Chen - Sun Microsystems - Beijing China ddi_rep_get8(acc, (uint8_t *)fibp, (uint8_t *)fibp0, fib_size,
63630749e8deSXin Chen - Sun Microsystems - Beijing China DDI_DEV_AUTOINCR);
63640749e8deSXin Chen - Sun Microsystems - Beijing China
63650749e8deSXin Chen - Sun Microsystems - Beijing China if (aac_check_acc_handle(softs->pci_mem_handle) != DDI_SUCCESS) {
63660749e8deSXin Chen - Sun Microsystems - Beijing China ddi_fm_service_impact(softs->devinfo_p,
63670749e8deSXin Chen - Sun Microsystems - Beijing China DDI_SERVICE_UNAFFECTED);
63680749e8deSXin Chen - Sun Microsystems - Beijing China mutex_exit(&softs->aifq_mutex);
63690749e8deSXin Chen - Sun Microsystems - Beijing China return;
63700749e8deSXin Chen - Sun Microsystems - Beijing China }
63710749e8deSXin Chen - Sun Microsystems - Beijing China
63720749e8deSXin Chen - Sun Microsystems - Beijing China AACDB_PRINT_AIF(softs, (struct aac_aif_command *)&fibp->data[0]);
63730749e8deSXin Chen - Sun Microsystems - Beijing China
63740749e8deSXin Chen - Sun Microsystems - Beijing China /* Modify AIF contexts */
63750749e8deSXin Chen - Sun Microsystems - Beijing China current = softs->aifq_idx;
63760749e8deSXin Chen - Sun Microsystems - Beijing China next = (current + 1) % AAC_AIFQ_LENGTH;
63770749e8deSXin Chen - Sun Microsystems - Beijing China if (next == 0) {
63780749e8deSXin Chen - Sun Microsystems - Beijing China struct aac_fib_context *ctx_p;
63790749e8deSXin Chen - Sun Microsystems - Beijing China
63800749e8deSXin Chen - Sun Microsystems - Beijing China softs->aifq_wrap = 1;
63810749e8deSXin Chen - Sun Microsystems - Beijing China for (ctx_p = softs->fibctx_p; ctx_p; ctx_p = ctx_p->next) {
63820749e8deSXin Chen - Sun Microsystems - Beijing China if (next == ctx_p->ctx_idx) {
63830749e8deSXin Chen - Sun Microsystems - Beijing China ctx_p->ctx_flags |= AAC_CTXFLAG_FILLED;
63840749e8deSXin Chen - Sun Microsystems - Beijing China } else if (current == ctx_p->ctx_idx &&
63850749e8deSXin Chen - Sun Microsystems - Beijing China (ctx_p->ctx_flags & AAC_CTXFLAG_FILLED)) {
63860749e8deSXin Chen - Sun Microsystems - Beijing China ctx_p->ctx_idx = next;
63870749e8deSXin Chen - Sun Microsystems - Beijing China ctx_p->ctx_overrun++;
63880749e8deSXin Chen - Sun Microsystems - Beijing China }
63890749e8deSXin Chen - Sun Microsystems - Beijing China }
63900749e8deSXin Chen - Sun Microsystems - Beijing China }
63910749e8deSXin Chen - Sun Microsystems - Beijing China softs->aifq_idx = next;
63920749e8deSXin Chen - Sun Microsystems - Beijing China
63930749e8deSXin Chen - Sun Microsystems - Beijing China /* Wakeup AIF threads */
63940749e8deSXin Chen - Sun Microsystems - Beijing China cv_broadcast(&softs->aifq_cv);
63950749e8deSXin Chen - Sun Microsystems - Beijing China mutex_exit(&softs->aifq_mutex);
63960749e8deSXin Chen - Sun Microsystems - Beijing China
63970749e8deSXin Chen - Sun Microsystems - Beijing China /* Wakeup event thread to handle aif */
63980749e8deSXin Chen - Sun Microsystems - Beijing China aac_event_disp(softs, AAC_EVENT_AIF);
63990749e8deSXin Chen - Sun Microsystems - Beijing China }
64000749e8deSXin Chen - Sun Microsystems - Beijing China
64010749e8deSXin Chen - Sun Microsystems - Beijing China static int
aac_return_aif_common(struct aac_softstate * softs,struct aac_fib_context * ctx,struct aac_fib ** fibpp)64020749e8deSXin Chen - Sun Microsystems - Beijing China aac_return_aif_common(struct aac_softstate *softs, struct aac_fib_context *ctx,
64030749e8deSXin Chen - Sun Microsystems - Beijing China struct aac_fib **fibpp)
64040749e8deSXin Chen - Sun Microsystems - Beijing China {
64050749e8deSXin Chen - Sun Microsystems - Beijing China int current;
64060749e8deSXin Chen - Sun Microsystems - Beijing China
64070749e8deSXin Chen - Sun Microsystems - Beijing China current = ctx->ctx_idx;
64080749e8deSXin Chen - Sun Microsystems - Beijing China if (current == softs->aifq_idx &&
64090749e8deSXin Chen - Sun Microsystems - Beijing China !(ctx->ctx_flags & AAC_CTXFLAG_FILLED))
64100749e8deSXin Chen - Sun Microsystems - Beijing China return (EAGAIN); /* Empty */
64110749e8deSXin Chen - Sun Microsystems - Beijing China
64120749e8deSXin Chen - Sun Microsystems - Beijing China *fibpp = &softs->aifq[current].d;
64130749e8deSXin Chen - Sun Microsystems - Beijing China
64140749e8deSXin Chen - Sun Microsystems - Beijing China ctx->ctx_flags &= ~AAC_CTXFLAG_FILLED;
64150749e8deSXin Chen - Sun Microsystems - Beijing China ctx->ctx_idx = (current + 1) % AAC_AIFQ_LENGTH;
64160749e8deSXin Chen - Sun Microsystems - Beijing China return (0);
64170749e8deSXin Chen - Sun Microsystems - Beijing China }
64180749e8deSXin Chen - Sun Microsystems - Beijing China
64190749e8deSXin Chen - Sun Microsystems - Beijing China int
aac_return_aif(struct aac_softstate * softs,struct aac_fib_context * ctx,struct aac_fib ** fibpp)64200749e8deSXin Chen - Sun Microsystems - Beijing China aac_return_aif(struct aac_softstate *softs, struct aac_fib_context *ctx,
64210749e8deSXin Chen - Sun Microsystems - Beijing China struct aac_fib **fibpp)
64220749e8deSXin Chen - Sun Microsystems - Beijing China {
64230749e8deSXin Chen - Sun Microsystems - Beijing China int rval;
64240749e8deSXin Chen - Sun Microsystems - Beijing China
64250749e8deSXin Chen - Sun Microsystems - Beijing China mutex_enter(&softs->aifq_mutex);
64260749e8deSXin Chen - Sun Microsystems - Beijing China rval = aac_return_aif_common(softs, ctx, fibpp);
64270749e8deSXin Chen - Sun Microsystems - Beijing China mutex_exit(&softs->aifq_mutex);
64280749e8deSXin Chen - Sun Microsystems - Beijing China return (rval);
64290749e8deSXin Chen - Sun Microsystems - Beijing China }
64300749e8deSXin Chen - Sun Microsystems - Beijing China
64310749e8deSXin Chen - Sun Microsystems - Beijing China int
aac_return_aif_wait(struct aac_softstate * softs,struct aac_fib_context * ctx,struct aac_fib ** fibpp)64320749e8deSXin Chen - Sun Microsystems - Beijing China aac_return_aif_wait(struct aac_softstate *softs, struct aac_fib_context *ctx,
64330749e8deSXin Chen - Sun Microsystems - Beijing China struct aac_fib **fibpp)
64340749e8deSXin Chen - Sun Microsystems - Beijing China {
64350749e8deSXin Chen - Sun Microsystems - Beijing China int rval;
64360749e8deSXin Chen - Sun Microsystems - Beijing China
64370749e8deSXin Chen - Sun Microsystems - Beijing China mutex_enter(&softs->aifq_mutex);
64380749e8deSXin Chen - Sun Microsystems - Beijing China rval = aac_return_aif_common(softs, ctx, fibpp);
64390749e8deSXin Chen - Sun Microsystems - Beijing China if (rval == EAGAIN) {
64400749e8deSXin Chen - Sun Microsystems - Beijing China AACDB_PRINT(softs, CE_NOTE, "Waiting for AIF");
64410749e8deSXin Chen - Sun Microsystems - Beijing China rval = cv_wait_sig(&softs->aifq_cv, &softs->aifq_mutex);
64420749e8deSXin Chen - Sun Microsystems - Beijing China }
64430749e8deSXin Chen - Sun Microsystems - Beijing China mutex_exit(&softs->aifq_mutex);
64440749e8deSXin Chen - Sun Microsystems - Beijing China return ((rval > 0) ? 0 : EINTR);
64450749e8deSXin Chen - Sun Microsystems - Beijing China }
64460749e8deSXin Chen - Sun Microsystems - Beijing China
6447830d82f7Spl /*
6448830d82f7Spl * The following function comes from Adaptec:
6449830d82f7Spl *
6450830d82f7Spl * When driver sees a particular event that means containers are changed, it
6451830d82f7Spl * will rescan containers. However a change may not be complete until some
6452830d82f7Spl * other event is received. For example, creating or deleting an array will
6453830d82f7Spl * incur as many as six AifEnConfigChange events which would generate six
6454830d82f7Spl * container rescans. To diminish rescans, driver set a flag to wait for
6455830d82f7Spl * another particular event. When sees that events come in, it will do rescan.
6456830d82f7Spl */
6457830d82f7Spl static int
aac_handle_aif(struct aac_softstate * softs,struct aac_aif_command * aif)64580749e8deSXin Chen - Sun Microsystems - Beijing China aac_handle_aif(struct aac_softstate *softs, struct aac_aif_command *aif)
6459830d82f7Spl {
6460942c5e3cSpl ddi_acc_handle_t acc = softs->comm_space_acc_handle;
6461942c5e3cSpl int en_type;
6462830d82f7Spl int devcfg_needed;
64633fced439Szhongyan gu - Sun Microsystems - Beijing China int cid;
64643fced439Szhongyan gu - Sun Microsystems - Beijing China uint32_t bus_id, tgt_id;
64653fced439Szhongyan gu - Sun Microsystems - Beijing China enum aac_cfg_event event = AAC_CFG_NULL_EXIST;
6466830d82f7Spl
6467830d82f7Spl devcfg_needed = 0;
6468942c5e3cSpl en_type = LE_32((uint32_t)aif->data.EN.type);
6469830d82f7Spl
6470942c5e3cSpl switch (LE_32((uint32_t)aif->command)) {
6471d7c5bf88Spl case AifCmdDriverNotify: {
64723fced439Szhongyan gu - Sun Microsystems - Beijing China cid = LE_32(aif->data.EN.data.ECC.container[0]);
6473d7c5bf88Spl
6474942c5e3cSpl switch (en_type) {
6475830d82f7Spl case AifDenMorphComplete:
6476830d82f7Spl case AifDenVolumeExtendComplete:
647758bc78c7SXin Chen if (AAC_DEV_IS_VALID(&softs->containers[cid].dev))
6478830d82f7Spl softs->devcfg_wait_on = AifEnConfigChange;
6479830d82f7Spl break;
6480830d82f7Spl }
6481942c5e3cSpl if (softs->devcfg_wait_on == en_type)
6482830d82f7Spl devcfg_needed = 1;
6483830d82f7Spl break;
6484d7c5bf88Spl }
6485830d82f7Spl
6486830d82f7Spl case AifCmdEventNotify:
64873fced439Szhongyan gu - Sun Microsystems - Beijing China cid = LE_32(aif->data.EN.data.ECC.container[0]);
6488942c5e3cSpl switch (en_type) {
6489830d82f7Spl case AifEnAddContainer:
6490830d82f7Spl case AifEnDeleteContainer:
6491830d82f7Spl softs->devcfg_wait_on = AifEnConfigChange;
6492830d82f7Spl break;
6493830d82f7Spl case AifEnContainerChange:
6494830d82f7Spl if (!softs->devcfg_wait_on)
6495830d82f7Spl softs->devcfg_wait_on = AifEnConfigChange;
6496830d82f7Spl break;
6497830d82f7Spl case AifEnContainerEvent:
6498942c5e3cSpl if (ddi_get32(acc, &aif-> \
6499942c5e3cSpl data.EN.data.ECE.eventType) == CT_PUP_MISSING_DRIVE)
6500830d82f7Spl devcfg_needed = 1;
6501830d82f7Spl break;
65023fced439Szhongyan gu - Sun Microsystems - Beijing China case AifEnAddJBOD:
65033fced439Szhongyan gu - Sun Microsystems - Beijing China if (!(softs->flags & AAC_FLAGS_JBOD))
65043fced439Szhongyan gu - Sun Microsystems - Beijing China return (AACERR);
65053fced439Szhongyan gu - Sun Microsystems - Beijing China event = AAC_CFG_ADD;
65063fced439Szhongyan gu - Sun Microsystems - Beijing China bus_id = (cid >> 24) & 0xf;
65073fced439Szhongyan gu - Sun Microsystems - Beijing China tgt_id = cid & 0xffff;
65083fced439Szhongyan gu - Sun Microsystems - Beijing China break;
65093fced439Szhongyan gu - Sun Microsystems - Beijing China case AifEnDeleteJBOD:
65103fced439Szhongyan gu - Sun Microsystems - Beijing China if (!(softs->flags & AAC_FLAGS_JBOD))
65113fced439Szhongyan gu - Sun Microsystems - Beijing China return (AACERR);
65123fced439Szhongyan gu - Sun Microsystems - Beijing China event = AAC_CFG_DELETE;
65133fced439Szhongyan gu - Sun Microsystems - Beijing China bus_id = (cid >> 24) & 0xf;
65143fced439Szhongyan gu - Sun Microsystems - Beijing China tgt_id = cid & 0xffff;
65153fced439Szhongyan gu - Sun Microsystems - Beijing China break;
6516830d82f7Spl }
6517942c5e3cSpl if (softs->devcfg_wait_on == en_type)
6518830d82f7Spl devcfg_needed = 1;
6519830d82f7Spl break;
6520830d82f7Spl
6521830d82f7Spl case AifCmdJobProgress:
6522942c5e3cSpl if (LE_32((uint32_t)aif->data.PR[0].jd.type) == AifJobCtrZero) {
6523942c5e3cSpl int pr_status;
6524942c5e3cSpl uint32_t pr_ftick, pr_ctick;
6525942c5e3cSpl
6526942c5e3cSpl pr_status = LE_32((uint32_t)aif->data.PR[0].status);
6527942c5e3cSpl pr_ctick = LE_32(aif->data.PR[0].currentTick);
6528942c5e3cSpl pr_ftick = LE_32(aif->data.PR[0].finalTick);
6529942c5e3cSpl
6530942c5e3cSpl if ((pr_ctick == pr_ftick) ||
6531942c5e3cSpl (pr_status == AifJobStsSuccess))
6532830d82f7Spl softs->devcfg_wait_on = AifEnContainerChange;
6533942c5e3cSpl else if ((pr_ctick == 0) &&
6534942c5e3cSpl (pr_status == AifJobStsRunning))
6535830d82f7Spl softs->devcfg_wait_on = AifEnContainerChange;
6536830d82f7Spl }
6537830d82f7Spl break;
6538830d82f7Spl }
6539830d82f7Spl
654058bc78c7SXin Chen if (devcfg_needed) {
654158bc78c7SXin Chen softs->devcfg_wait_on = 0;
6542942c5e3cSpl (void) aac_probe_containers(softs);
654358bc78c7SXin Chen }
6544830d82f7Spl
65453fced439Szhongyan gu - Sun Microsystems - Beijing China if (event != AAC_CFG_NULL_EXIST) {
65463fced439Szhongyan gu - Sun Microsystems - Beijing China ASSERT(en_type == AifEnAddJBOD || en_type == AifEnDeleteJBOD);
65473fced439Szhongyan gu - Sun Microsystems - Beijing China (void) aac_probe_jbod(softs,
65483fced439Szhongyan gu - Sun Microsystems - Beijing China AAC_P2VTGT(softs, bus_id, tgt_id), event);
65493fced439Szhongyan gu - Sun Microsystems - Beijing China }
65500749e8deSXin Chen - Sun Microsystems - Beijing China return (AACOK);
65510749e8deSXin Chen - Sun Microsystems - Beijing China }
6552d7c5bf88Spl
65530749e8deSXin Chen - Sun Microsystems - Beijing China
65540749e8deSXin Chen - Sun Microsystems - Beijing China /*
65550749e8deSXin Chen - Sun Microsystems - Beijing China * Check and handle AIF events
65560749e8deSXin Chen - Sun Microsystems - Beijing China */
65570749e8deSXin Chen - Sun Microsystems - Beijing China static void
aac_aif_event(struct aac_softstate * softs)65580749e8deSXin Chen - Sun Microsystems - Beijing China aac_aif_event(struct aac_softstate *softs)
65590749e8deSXin Chen - Sun Microsystems - Beijing China {
65600749e8deSXin Chen - Sun Microsystems - Beijing China struct aac_fib *fibp;
65610749e8deSXin Chen - Sun Microsystems - Beijing China
65620749e8deSXin Chen - Sun Microsystems - Beijing China /*CONSTCOND*/
65630749e8deSXin Chen - Sun Microsystems - Beijing China while (1) {
65640749e8deSXin Chen - Sun Microsystems - Beijing China if (aac_return_aif(softs, &softs->aifctx, &fibp) != 0)
65650749e8deSXin Chen - Sun Microsystems - Beijing China break; /* No more AIFs to handle, end loop */
65660749e8deSXin Chen - Sun Microsystems - Beijing China
65670749e8deSXin Chen - Sun Microsystems - Beijing China /* AIF overrun, array create/delete may missed. */
65680749e8deSXin Chen - Sun Microsystems - Beijing China if (softs->aifctx.ctx_overrun) {
65690749e8deSXin Chen - Sun Microsystems - Beijing China softs->aifctx.ctx_overrun = 0;
6570830d82f7Spl }
6571830d82f7Spl
65720749e8deSXin Chen - Sun Microsystems - Beijing China /* AIF received, handle it */
65730749e8deSXin Chen - Sun Microsystems - Beijing China struct aac_aif_command *aifp =
65740749e8deSXin Chen - Sun Microsystems - Beijing China (struct aac_aif_command *)&fibp->data[0];
65750749e8deSXin Chen - Sun Microsystems - Beijing China uint32_t aif_command = LE_32((uint32_t)aifp->command);
65760749e8deSXin Chen - Sun Microsystems - Beijing China
65770749e8deSXin Chen - Sun Microsystems - Beijing China if (aif_command == AifCmdDriverNotify ||
65780749e8deSXin Chen - Sun Microsystems - Beijing China aif_command == AifCmdEventNotify ||
65790749e8deSXin Chen - Sun Microsystems - Beijing China aif_command == AifCmdJobProgress)
65800749e8deSXin Chen - Sun Microsystems - Beijing China (void) aac_handle_aif(softs, aifp);
65810749e8deSXin Chen - Sun Microsystems - Beijing China }
6582830d82f7Spl }
6583830d82f7Spl
6584382c8bcaSpl /*
6585382c8bcaSpl * Timeout recovery
6586382c8bcaSpl */
658758bc78c7SXin Chen /*ARGSUSED*/
6588382c8bcaSpl static void
aac_cmd_timeout(struct aac_softstate * softs,struct aac_cmd * acp)658958bc78c7SXin Chen aac_cmd_timeout(struct aac_softstate *softs, struct aac_cmd *acp)
6590382c8bcaSpl {
659158bc78c7SXin Chen #ifdef DEBUG
659258bc78c7SXin Chen acp->fib_flags |= AACDB_FLAGS_FIB_TIMEOUT;
659358bc78c7SXin Chen AACDB_PRINT(softs, CE_WARN, "acp %p timed out", acp);
659458bc78c7SXin Chen AACDB_PRINT_FIB(softs, acp->slotp);
659558bc78c7SXin Chen #endif
659658bc78c7SXin Chen
6597382c8bcaSpl /*
6598382c8bcaSpl * Besides the firmware in unhealthy state, an overloaded
6599382c8bcaSpl * adapter may also incur pkt timeout.
6600382c8bcaSpl * There is a chance for an adapter with a slower IOP to take
6601382c8bcaSpl * longer than 60 seconds to process the commands, such as when
6602382c8bcaSpl * to perform IOs. So the adapter is doing a build on a RAID-5
6603382c8bcaSpl * while being required longer completion times should be
6604382c8bcaSpl * tolerated.
6605382c8bcaSpl */
660658bc78c7SXin Chen switch (aac_do_reset(softs)) {
660758bc78c7SXin Chen case AAC_IOP_RESET_SUCCEED:
660858bc78c7SXin Chen aac_abort_iocmds(softs, AAC_IOCMD_OUTSTANDING, NULL, CMD_RESET);
6609382c8bcaSpl aac_start_waiting_io(softs);
661058bc78c7SXin Chen break;
661158bc78c7SXin Chen case AAC_IOP_RESET_FAILED:
6612382c8bcaSpl /* Abort all waiting cmds when adapter is dead */
661358bc78c7SXin Chen aac_abort_iocmds(softs, AAC_IOCMD_ALL, NULL, CMD_TIMEOUT);
661458bc78c7SXin Chen break;
661558bc78c7SXin Chen case AAC_IOP_RESET_ABNORMAL:
661658bc78c7SXin Chen aac_start_waiting_io(softs);
6617382c8bcaSpl }
6618382c8bcaSpl }
6619382c8bcaSpl
6620942c5e3cSpl /*
6621942c5e3cSpl * The following function comes from Adaptec:
6622942c5e3cSpl *
6623942c5e3cSpl * Time sync. command added to synchronize time with firmware every 30
6624942c5e3cSpl * minutes (required for correct AIF timestamps etc.)
6625942c5e3cSpl */
66260749e8deSXin Chen - Sun Microsystems - Beijing China static void
aac_sync_tick(struct aac_softstate * softs)6627942c5e3cSpl aac_sync_tick(struct aac_softstate *softs)
6628942c5e3cSpl {
6629f42c2f53Szhongyan gu - Sun Microsystems - Beijing China ddi_acc_handle_t acc;
6630f42c2f53Szhongyan gu - Sun Microsystems - Beijing China int rval;
6631f42c2f53Szhongyan gu - Sun Microsystems - Beijing China
66320749e8deSXin Chen - Sun Microsystems - Beijing China mutex_enter(&softs->time_mutex);
66330749e8deSXin Chen - Sun Microsystems - Beijing China ASSERT(softs->time_sync <= softs->timebase);
66340749e8deSXin Chen - Sun Microsystems - Beijing China softs->time_sync = 0;
66350749e8deSXin Chen - Sun Microsystems - Beijing China mutex_exit(&softs->time_mutex);
66360749e8deSXin Chen - Sun Microsystems - Beijing China
6637f42c2f53Szhongyan gu - Sun Microsystems - Beijing China /* Time sync. with firmware every AAC_SYNC_TICK */
6638f42c2f53Szhongyan gu - Sun Microsystems - Beijing China (void) aac_sync_fib_slot_bind(softs, &softs->sync_ac);
6639f42c2f53Szhongyan gu - Sun Microsystems - Beijing China acc = softs->sync_ac.slotp->fib_acc_handle;
6640942c5e3cSpl
6641f42c2f53Szhongyan gu - Sun Microsystems - Beijing China ddi_put32(acc, (void *)&softs->sync_ac.slotp->fibp->data[0],
6642f42c2f53Szhongyan gu - Sun Microsystems - Beijing China ddi_get_time());
6643f42c2f53Szhongyan gu - Sun Microsystems - Beijing China rval = aac_sync_fib(softs, SendHostTime, AAC_FIB_SIZEOF(uint32_t));
6644f42c2f53Szhongyan gu - Sun Microsystems - Beijing China aac_sync_fib_slot_release(softs, &softs->sync_ac);
66450749e8deSXin Chen - Sun Microsystems - Beijing China
66460749e8deSXin Chen - Sun Microsystems - Beijing China mutex_enter(&softs->time_mutex);
66470749e8deSXin Chen - Sun Microsystems - Beijing China softs->time_sync = softs->timebase;
66480749e8deSXin Chen - Sun Microsystems - Beijing China if (rval != AACOK)
66490749e8deSXin Chen - Sun Microsystems - Beijing China /* retry shortly */
66500749e8deSXin Chen - Sun Microsystems - Beijing China softs->time_sync += aac_tick << 1;
66510749e8deSXin Chen - Sun Microsystems - Beijing China else
66520749e8deSXin Chen - Sun Microsystems - Beijing China softs->time_sync += AAC_SYNC_TICK;
66530749e8deSXin Chen - Sun Microsystems - Beijing China mutex_exit(&softs->time_mutex);
6654942c5e3cSpl }
6655942c5e3cSpl
66560749e8deSXin Chen - Sun Microsystems - Beijing China /*
66570749e8deSXin Chen - Sun Microsystems - Beijing China * Timeout checking and handling
66580749e8deSXin Chen - Sun Microsystems - Beijing China */
66597c478bd9Sstevel@tonic-gate static void
aac_daemon(struct aac_softstate * softs)66600749e8deSXin Chen - Sun Microsystems - Beijing China aac_daemon(struct aac_softstate *softs)
66617c478bd9Sstevel@tonic-gate {
66620749e8deSXin Chen - Sun Microsystems - Beijing China int time_out; /* set if timeout happened */
66630749e8deSXin Chen - Sun Microsystems - Beijing China int time_adjust;
66640749e8deSXin Chen - Sun Microsystems - Beijing China uint32_t softs_timebase;
6665830d82f7Spl
66660749e8deSXin Chen - Sun Microsystems - Beijing China mutex_enter(&softs->time_mutex);
66670749e8deSXin Chen - Sun Microsystems - Beijing China ASSERT(softs->time_out <= softs->timebase);
66680749e8deSXin Chen - Sun Microsystems - Beijing China softs->time_out = 0;
66690749e8deSXin Chen - Sun Microsystems - Beijing China softs_timebase = softs->timebase;
66700749e8deSXin Chen - Sun Microsystems - Beijing China mutex_exit(&softs->time_mutex);
6671830d82f7Spl
66720749e8deSXin Chen - Sun Microsystems - Beijing China /* Check slots for timeout pkts */
66730749e8deSXin Chen - Sun Microsystems - Beijing China time_adjust = 0;
66740749e8deSXin Chen - Sun Microsystems - Beijing China do {
66750749e8deSXin Chen - Sun Microsystems - Beijing China struct aac_cmd *acp;
66760749e8deSXin Chen - Sun Microsystems - Beijing China
66770749e8deSXin Chen - Sun Microsystems - Beijing China time_out = 0;
66780749e8deSXin Chen - Sun Microsystems - Beijing China for (acp = softs->q_busy.q_head; acp; acp = acp->next) {
66790749e8deSXin Chen - Sun Microsystems - Beijing China if (acp->timeout == 0)
66800749e8deSXin Chen - Sun Microsystems - Beijing China continue;
66810749e8deSXin Chen - Sun Microsystems - Beijing China
66820749e8deSXin Chen - Sun Microsystems - Beijing China /*
66830749e8deSXin Chen - Sun Microsystems - Beijing China * If timeout happened, update outstanding cmds
66840749e8deSXin Chen - Sun Microsystems - Beijing China * to be checked later again.
66850749e8deSXin Chen - Sun Microsystems - Beijing China */
66860749e8deSXin Chen - Sun Microsystems - Beijing China if (time_adjust) {
66870749e8deSXin Chen - Sun Microsystems - Beijing China acp->timeout += time_adjust;
66880749e8deSXin Chen - Sun Microsystems - Beijing China continue;
66890749e8deSXin Chen - Sun Microsystems - Beijing China }
66900749e8deSXin Chen - Sun Microsystems - Beijing China
66910749e8deSXin Chen - Sun Microsystems - Beijing China if (acp->timeout <= softs_timebase) {
669258bc78c7SXin Chen aac_cmd_timeout(softs, acp);
66930749e8deSXin Chen - Sun Microsystems - Beijing China time_out = 1;
66940749e8deSXin Chen - Sun Microsystems - Beijing China time_adjust = aac_tick * drv_usectohz(1000000);
66950749e8deSXin Chen - Sun Microsystems - Beijing China break; /* timeout happened */
66960749e8deSXin Chen - Sun Microsystems - Beijing China } else {
66970749e8deSXin Chen - Sun Microsystems - Beijing China break; /* no timeout */
6698382c8bcaSpl }
6699830d82f7Spl }
67000749e8deSXin Chen - Sun Microsystems - Beijing China } while (time_out);
67017c478bd9Sstevel@tonic-gate
67020749e8deSXin Chen - Sun Microsystems - Beijing China mutex_enter(&softs->time_mutex);
67030749e8deSXin Chen - Sun Microsystems - Beijing China softs->time_out = softs->timebase + aac_tick;
67040749e8deSXin Chen - Sun Microsystems - Beijing China mutex_exit(&softs->time_mutex);
67050749e8deSXin Chen - Sun Microsystems - Beijing China }
67060749e8deSXin Chen - Sun Microsystems - Beijing China
67070749e8deSXin Chen - Sun Microsystems - Beijing China /*
67080749e8deSXin Chen - Sun Microsystems - Beijing China * The event thread handles various tasks serially for the other parts of
67090749e8deSXin Chen - Sun Microsystems - Beijing China * the driver, so that they can run fast.
67100749e8deSXin Chen - Sun Microsystems - Beijing China */
67110749e8deSXin Chen - Sun Microsystems - Beijing China static void
aac_event_thread(struct aac_softstate * softs)67120749e8deSXin Chen - Sun Microsystems - Beijing China aac_event_thread(struct aac_softstate *softs)
67130749e8deSXin Chen - Sun Microsystems - Beijing China {
67140749e8deSXin Chen - Sun Microsystems - Beijing China int run = 1;
67150749e8deSXin Chen - Sun Microsystems - Beijing China
67160749e8deSXin Chen - Sun Microsystems - Beijing China DBCALLED(softs, 1);
67170749e8deSXin Chen - Sun Microsystems - Beijing China
67180749e8deSXin Chen - Sun Microsystems - Beijing China mutex_enter(&softs->ev_lock);
67190749e8deSXin Chen - Sun Microsystems - Beijing China while (run) {
67200749e8deSXin Chen - Sun Microsystems - Beijing China int events;
67210749e8deSXin Chen - Sun Microsystems - Beijing China
67220749e8deSXin Chen - Sun Microsystems - Beijing China if ((events = softs->events) == 0) {
67230749e8deSXin Chen - Sun Microsystems - Beijing China cv_wait(&softs->event_disp_cv, &softs->ev_lock);
67240749e8deSXin Chen - Sun Microsystems - Beijing China events = softs->events;
67250749e8deSXin Chen - Sun Microsystems - Beijing China }
67260749e8deSXin Chen - Sun Microsystems - Beijing China softs->events = 0;
67270749e8deSXin Chen - Sun Microsystems - Beijing China mutex_exit(&softs->ev_lock);
67280749e8deSXin Chen - Sun Microsystems - Beijing China
67290749e8deSXin Chen - Sun Microsystems - Beijing China mutex_enter(&softs->io_lock);
67300749e8deSXin Chen - Sun Microsystems - Beijing China if ((softs->state & AAC_STATE_RUN) &&
67310749e8deSXin Chen - Sun Microsystems - Beijing China (softs->state & AAC_STATE_DEAD) == 0) {
67320749e8deSXin Chen - Sun Microsystems - Beijing China if (events & AAC_EVENT_TIMEOUT)
67330749e8deSXin Chen - Sun Microsystems - Beijing China aac_daemon(softs);
67340749e8deSXin Chen - Sun Microsystems - Beijing China if (events & AAC_EVENT_SYNCTICK)
67350749e8deSXin Chen - Sun Microsystems - Beijing China aac_sync_tick(softs);
67360749e8deSXin Chen - Sun Microsystems - Beijing China if (events & AAC_EVENT_AIF)
67370749e8deSXin Chen - Sun Microsystems - Beijing China aac_aif_event(softs);
67380749e8deSXin Chen - Sun Microsystems - Beijing China } else {
67390749e8deSXin Chen - Sun Microsystems - Beijing China run = 0;
67400749e8deSXin Chen - Sun Microsystems - Beijing China }
67410749e8deSXin Chen - Sun Microsystems - Beijing China mutex_exit(&softs->io_lock);
67420749e8deSXin Chen - Sun Microsystems - Beijing China
67430749e8deSXin Chen - Sun Microsystems - Beijing China mutex_enter(&softs->ev_lock);
6744942c5e3cSpl }
6745942c5e3cSpl
67460749e8deSXin Chen - Sun Microsystems - Beijing China cv_signal(&softs->event_wait_cv);
67470749e8deSXin Chen - Sun Microsystems - Beijing China mutex_exit(&softs->ev_lock);
67480749e8deSXin Chen - Sun Microsystems - Beijing China }
67490749e8deSXin Chen - Sun Microsystems - Beijing China
67500749e8deSXin Chen - Sun Microsystems - Beijing China /*
67510749e8deSXin Chen - Sun Microsystems - Beijing China * Internal timer. It is only responsbile for time counting and report time
67520749e8deSXin Chen - Sun Microsystems - Beijing China * related events. Events handling is done by aac_event_thread(), so that
67530749e8deSXin Chen - Sun Microsystems - Beijing China * the timer itself could be as precise as possible.
67540749e8deSXin Chen - Sun Microsystems - Beijing China */
67550749e8deSXin Chen - Sun Microsystems - Beijing China static void
aac_timer(void * arg)67560749e8deSXin Chen - Sun Microsystems - Beijing China aac_timer(void *arg)
67570749e8deSXin Chen - Sun Microsystems - Beijing China {
67580749e8deSXin Chen - Sun Microsystems - Beijing China struct aac_softstate *softs = arg;
67590749e8deSXin Chen - Sun Microsystems - Beijing China int events = 0;
67600749e8deSXin Chen - Sun Microsystems - Beijing China
67610749e8deSXin Chen - Sun Microsystems - Beijing China mutex_enter(&softs->time_mutex);
67620749e8deSXin Chen - Sun Microsystems - Beijing China
67630749e8deSXin Chen - Sun Microsystems - Beijing China /* If timer is being stopped, exit */
67640749e8deSXin Chen - Sun Microsystems - Beijing China if (softs->timeout_id) {
67650749e8deSXin Chen - Sun Microsystems - Beijing China softs->timeout_id = timeout(aac_timer, (void *)softs,
6766382c8bcaSpl (aac_tick * drv_usectohz(1000000)));
67670749e8deSXin Chen - Sun Microsystems - Beijing China } else {
67680749e8deSXin Chen - Sun Microsystems - Beijing China mutex_exit(&softs->time_mutex);
67690749e8deSXin Chen - Sun Microsystems - Beijing China return;
67700749e8deSXin Chen - Sun Microsystems - Beijing China }
67710749e8deSXin Chen - Sun Microsystems - Beijing China
67720749e8deSXin Chen - Sun Microsystems - Beijing China /* Time counting */
67730749e8deSXin Chen - Sun Microsystems - Beijing China softs->timebase += aac_tick;
67740749e8deSXin Chen - Sun Microsystems - Beijing China
67750749e8deSXin Chen - Sun Microsystems - Beijing China /* Check time related events */
67760749e8deSXin Chen - Sun Microsystems - Beijing China if (softs->time_out && softs->time_out <= softs->timebase)
67770749e8deSXin Chen - Sun Microsystems - Beijing China events |= AAC_EVENT_TIMEOUT;
67780749e8deSXin Chen - Sun Microsystems - Beijing China if (softs->time_sync && softs->time_sync <= softs->timebase)
67790749e8deSXin Chen - Sun Microsystems - Beijing China events |= AAC_EVENT_SYNCTICK;
67800749e8deSXin Chen - Sun Microsystems - Beijing China
67810749e8deSXin Chen - Sun Microsystems - Beijing China mutex_exit(&softs->time_mutex);
67820749e8deSXin Chen - Sun Microsystems - Beijing China
67830749e8deSXin Chen - Sun Microsystems - Beijing China if (events)
67840749e8deSXin Chen - Sun Microsystems - Beijing China aac_event_disp(softs, events);
67850749e8deSXin Chen - Sun Microsystems - Beijing China }
67860749e8deSXin Chen - Sun Microsystems - Beijing China
67870749e8deSXin Chen - Sun Microsystems - Beijing China /*
67880749e8deSXin Chen - Sun Microsystems - Beijing China * Dispatch events to daemon thread for handling
67890749e8deSXin Chen - Sun Microsystems - Beijing China */
67900749e8deSXin Chen - Sun Microsystems - Beijing China static void
aac_event_disp(struct aac_softstate * softs,int events)67910749e8deSXin Chen - Sun Microsystems - Beijing China aac_event_disp(struct aac_softstate *softs, int events)
67920749e8deSXin Chen - Sun Microsystems - Beijing China {
67930749e8deSXin Chen - Sun Microsystems - Beijing China mutex_enter(&softs->ev_lock);
67940749e8deSXin Chen - Sun Microsystems - Beijing China softs->events |= events;
67950749e8deSXin Chen - Sun Microsystems - Beijing China cv_broadcast(&softs->event_disp_cv);
67960749e8deSXin Chen - Sun Microsystems - Beijing China mutex_exit(&softs->ev_lock);
6797830d82f7Spl }
6798830d82f7Spl
6799830d82f7Spl /*
6800830d82f7Spl * Architecture dependent functions
6801830d82f7Spl */
6802830d82f7Spl static int
aac_rx_get_fwstatus(struct aac_softstate * softs)6803830d82f7Spl aac_rx_get_fwstatus(struct aac_softstate *softs)
6804830d82f7Spl {
6805942c5e3cSpl return (PCI_MEM_GET32(softs, AAC_OMR0));
6806830d82f7Spl }
6807830d82f7Spl
6808830d82f7Spl static int
aac_rx_get_mailbox(struct aac_softstate * softs,int mb)6809830d82f7Spl aac_rx_get_mailbox(struct aac_softstate *softs, int mb)
6810830d82f7Spl {
6811830d82f7Spl return (PCI_MEM_GET32(softs, AAC_RX_MAILBOX + mb * 4));
6812830d82f7Spl }
6813830d82f7Spl
6814830d82f7Spl static void
aac_rx_set_mailbox(struct aac_softstate * softs,uint32_t cmd,uint32_t arg0,uint32_t arg1,uint32_t arg2,uint32_t arg3)6815830d82f7Spl aac_rx_set_mailbox(struct aac_softstate *softs, uint32_t cmd,
6816c9487164Spl uint32_t arg0, uint32_t arg1, uint32_t arg2, uint32_t arg3)
6817830d82f7Spl {
6818830d82f7Spl PCI_MEM_PUT32(softs, AAC_RX_MAILBOX, cmd);
6819830d82f7Spl PCI_MEM_PUT32(softs, AAC_RX_MAILBOX + 4, arg0);
6820830d82f7Spl PCI_MEM_PUT32(softs, AAC_RX_MAILBOX + 8, arg1);
6821830d82f7Spl PCI_MEM_PUT32(softs, AAC_RX_MAILBOX + 12, arg2);
6822830d82f7Spl PCI_MEM_PUT32(softs, AAC_RX_MAILBOX + 16, arg3);
6823830d82f7Spl }
6824830d82f7Spl
6825830d82f7Spl static int
aac_rkt_get_fwstatus(struct aac_softstate * softs)6826830d82f7Spl aac_rkt_get_fwstatus(struct aac_softstate *softs)
6827830d82f7Spl {
6828942c5e3cSpl return (PCI_MEM_GET32(softs, AAC_OMR0));
6829830d82f7Spl }
6830830d82f7Spl
6831830d82f7Spl static int
aac_rkt_get_mailbox(struct aac_softstate * softs,int mb)6832830d82f7Spl aac_rkt_get_mailbox(struct aac_softstate *softs, int mb)
6833830d82f7Spl {
6834830d82f7Spl return (PCI_MEM_GET32(softs, AAC_RKT_MAILBOX + mb *4));
6835830d82f7Spl }
6836830d82f7Spl
6837830d82f7Spl static void
aac_rkt_set_mailbox(struct aac_softstate * softs,uint32_t cmd,uint32_t arg0,uint32_t arg1,uint32_t arg2,uint32_t arg3)6838830d82f7Spl aac_rkt_set_mailbox(struct aac_softstate *softs, uint32_t cmd,
6839c9487164Spl uint32_t arg0, uint32_t arg1, uint32_t arg2, uint32_t arg3)
6840830d82f7Spl {
6841830d82f7Spl PCI_MEM_PUT32(softs, AAC_RKT_MAILBOX, cmd);
6842830d82f7Spl PCI_MEM_PUT32(softs, AAC_RKT_MAILBOX + 4, arg0);
6843830d82f7Spl PCI_MEM_PUT32(softs, AAC_RKT_MAILBOX + 8, arg1);
6844830d82f7Spl PCI_MEM_PUT32(softs, AAC_RKT_MAILBOX + 12, arg2);
6845830d82f7Spl PCI_MEM_PUT32(softs, AAC_RKT_MAILBOX + 16, arg3);
6846830d82f7Spl }
6847830d82f7Spl
6848830d82f7Spl /*
6849830d82f7Spl * cb_ops functions
6850830d82f7Spl */
6851830d82f7Spl static int
aac_open(dev_t * devp,int flag,int otyp,cred_t * cred)6852830d82f7Spl aac_open(dev_t *devp, int flag, int otyp, cred_t *cred)
6853830d82f7Spl {
6854830d82f7Spl struct aac_softstate *softs;
6855830d82f7Spl int minor0, minor;
6856830d82f7Spl int instance;
6857830d82f7Spl
68581dd0a2dbSpl DBCALLED(NULL, 2);
6859830d82f7Spl
6860830d82f7Spl if (otyp != OTYP_BLK && otyp != OTYP_CHR)
6861830d82f7Spl return (EINVAL);
6862830d82f7Spl
6863830d82f7Spl minor0 = getminor(*devp);
6864830d82f7Spl minor = AAC_SCSA_MINOR(minor0);
6865830d82f7Spl
6866830d82f7Spl if (AAC_IS_SCSA_NODE(minor))
6867830d82f7Spl return (scsi_hba_open(devp, flag, otyp, cred));
6868830d82f7Spl
6869830d82f7Spl instance = MINOR2INST(minor0);
6870830d82f7Spl if (instance >= AAC_MAX_ADAPTERS)
6871830d82f7Spl return (ENXIO);
6872830d82f7Spl
6873830d82f7Spl softs = ddi_get_soft_state(aac_softstatep, instance);
6874830d82f7Spl if (softs == NULL)
6875830d82f7Spl return (ENXIO);
6876830d82f7Spl
6877830d82f7Spl return (0);
6878830d82f7Spl }
6879830d82f7Spl
6880830d82f7Spl /*ARGSUSED*/
6881830d82f7Spl static int
aac_close(dev_t dev,int flag,int otyp,cred_t * cred)6882830d82f7Spl aac_close(dev_t dev, int flag, int otyp, cred_t *cred)
6883830d82f7Spl {
6884830d82f7Spl int minor0, minor;
6885830d82f7Spl int instance;
6886830d82f7Spl
68871dd0a2dbSpl DBCALLED(NULL, 2);
6888830d82f7Spl
6889830d82f7Spl if (otyp != OTYP_BLK && otyp != OTYP_CHR)
6890830d82f7Spl return (EINVAL);
6891830d82f7Spl
6892830d82f7Spl minor0 = getminor(dev);
6893830d82f7Spl minor = AAC_SCSA_MINOR(minor0);
6894830d82f7Spl
6895830d82f7Spl if (AAC_IS_SCSA_NODE(minor))
6896830d82f7Spl return (scsi_hba_close(dev, flag, otyp, cred));
6897830d82f7Spl
6898830d82f7Spl instance = MINOR2INST(minor0);
6899830d82f7Spl if (instance >= AAC_MAX_ADAPTERS)
6900830d82f7Spl return (ENXIO);
69017c478bd9Sstevel@tonic-gate
6902830d82f7Spl return (0);
6903830d82f7Spl }
6904830d82f7Spl
6905830d82f7Spl static int
aac_ioctl(dev_t dev,int cmd,intptr_t arg,int flag,cred_t * cred_p,int * rval_p)6906c9487164Spl aac_ioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *cred_p,
6907c9487164Spl int *rval_p)
6908830d82f7Spl {
6909830d82f7Spl struct aac_softstate *softs;
6910830d82f7Spl int minor0, minor;
6911830d82f7Spl int instance;
6912830d82f7Spl
69131dd0a2dbSpl DBCALLED(NULL, 2);
6914830d82f7Spl
6915830d82f7Spl if (drv_priv(cred_p) != 0)
6916830d82f7Spl return (EPERM);
6917830d82f7Spl
6918830d82f7Spl minor0 = getminor(dev);
6919830d82f7Spl minor = AAC_SCSA_MINOR(minor0);
6920830d82f7Spl
6921830d82f7Spl if (AAC_IS_SCSA_NODE(minor))
6922830d82f7Spl return (scsi_hba_ioctl(dev, cmd, arg, flag, cred_p, rval_p));
6923830d82f7Spl
6924830d82f7Spl instance = MINOR2INST(minor0);
6925830d82f7Spl if (instance < AAC_MAX_ADAPTERS) {
6926830d82f7Spl softs = ddi_get_soft_state(aac_softstatep, instance);
6927942c5e3cSpl return (aac_do_ioctl(softs, dev, cmd, arg, flag));
6928830d82f7Spl }
6929830d82f7Spl return (ENXIO);
69307c478bd9Sstevel@tonic-gate }
69317c478bd9Sstevel@tonic-gate
69327675db54Syw /*
69337675db54Syw * The IO fault service error handling callback function
69347675db54Syw */
69357675db54Syw /*ARGSUSED*/
69367675db54Syw static int
aac_fm_error_cb(dev_info_t * dip,ddi_fm_error_t * err,const void * impl_data)69377675db54Syw aac_fm_error_cb(dev_info_t *dip, ddi_fm_error_t *err, const void *impl_data)
69387675db54Syw {
69397675db54Syw /*
69407675db54Syw * as the driver can always deal with an error in any dma or
69417675db54Syw * access handle, we can just return the fme_status value.
69427675db54Syw */
69437675db54Syw pci_ereport_post(dip, err, NULL);
69447675db54Syw return (err->fme_status);
69457675db54Syw }
69467675db54Syw
69477675db54Syw /*
69487675db54Syw * aac_fm_init - initialize fma capabilities and register with IO
69497675db54Syw * fault services.
69507675db54Syw */
69517675db54Syw static void
aac_fm_init(struct aac_softstate * softs)69527675db54Syw aac_fm_init(struct aac_softstate *softs)
69537675db54Syw {
69547675db54Syw /*
69557675db54Syw * Need to change iblock to priority for new MSI intr
69567675db54Syw */
69577675db54Syw ddi_iblock_cookie_t fm_ibc;
69587675db54Syw
695958bc78c7SXin Chen softs->fm_capabilities = ddi_getprop(DDI_DEV_T_ANY, softs->devinfo_p,
696058bc78c7SXin Chen DDI_PROP_CANSLEEP | DDI_PROP_DONTPASS, "fm-capable",
696158bc78c7SXin Chen DDI_FM_EREPORT_CAPABLE | DDI_FM_ACCCHK_CAPABLE |
696258bc78c7SXin Chen DDI_FM_DMACHK_CAPABLE | DDI_FM_ERRCB_CAPABLE);
696358bc78c7SXin Chen
69647675db54Syw /* Only register with IO Fault Services if we have some capability */
69657675db54Syw if (softs->fm_capabilities) {
69667675db54Syw /* Adjust access and dma attributes for FMA */
6967837c1ac4SStephen Hanson softs->reg_attr.devacc_attr_access = DDI_FLAGERR_ACC;
696858bc78c7SXin Chen softs->addr_dma_attr.dma_attr_flags |= DDI_DMA_FLAGERR;
696958bc78c7SXin Chen softs->buf_dma_attr.dma_attr_flags |= DDI_DMA_FLAGERR;
69707675db54Syw
69717675db54Syw /*
69727675db54Syw * Register capabilities with IO Fault Services.
69737675db54Syw * fm_capabilities will be updated to indicate
69747675db54Syw * capabilities actually supported (not requested.)
69757675db54Syw */
69767675db54Syw ddi_fm_init(softs->devinfo_p, &softs->fm_capabilities, &fm_ibc);
69777675db54Syw
69787675db54Syw /*
69797675db54Syw * Initialize pci ereport capabilities if ereport
69807675db54Syw * capable (should always be.)
69817675db54Syw */
69827675db54Syw if (DDI_FM_EREPORT_CAP(softs->fm_capabilities) ||
69837675db54Syw DDI_FM_ERRCB_CAP(softs->fm_capabilities)) {
69847675db54Syw pci_ereport_setup(softs->devinfo_p);
69857675db54Syw }
69867675db54Syw
69877675db54Syw /*
69887675db54Syw * Register error callback if error callback capable.
69897675db54Syw */
69907675db54Syw if (DDI_FM_ERRCB_CAP(softs->fm_capabilities)) {
69917675db54Syw ddi_fm_handler_register(softs->devinfo_p,
69927675db54Syw aac_fm_error_cb, (void *) softs);
69937675db54Syw }
69947675db54Syw }
69957675db54Syw }
69967675db54Syw
69977675db54Syw /*
69987675db54Syw * aac_fm_fini - Releases fma capabilities and un-registers with IO
69997675db54Syw * fault services.
70007675db54Syw */
70017675db54Syw static void
aac_fm_fini(struct aac_softstate * softs)70027675db54Syw aac_fm_fini(struct aac_softstate *softs)
70037675db54Syw {
70047675db54Syw /* Only unregister FMA capabilities if registered */
70057675db54Syw if (softs->fm_capabilities) {
70067675db54Syw /*
70077675db54Syw * Un-register error callback if error callback capable.
70087675db54Syw */
70097675db54Syw if (DDI_FM_ERRCB_CAP(softs->fm_capabilities)) {
70107675db54Syw ddi_fm_handler_unregister(softs->devinfo_p);
70117675db54Syw }
70127675db54Syw
70137675db54Syw /*
70147675db54Syw * Release any resources allocated by pci_ereport_setup()
70157675db54Syw */
70167675db54Syw if (DDI_FM_EREPORT_CAP(softs->fm_capabilities) ||
70177675db54Syw DDI_FM_ERRCB_CAP(softs->fm_capabilities)) {
70187675db54Syw pci_ereport_teardown(softs->devinfo_p);
70197675db54Syw }
70207675db54Syw
70217675db54Syw /* Unregister from IO Fault Services */
70227675db54Syw ddi_fm_fini(softs->devinfo_p);
702358bc78c7SXin Chen
702458bc78c7SXin Chen /* Adjust access and dma attributes for FMA */
7025837c1ac4SStephen Hanson softs->reg_attr.devacc_attr_access = DDI_DEFAULT_ACC;
702658bc78c7SXin Chen softs->addr_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR;
702758bc78c7SXin Chen softs->buf_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR;
70287675db54Syw }
70297675db54Syw }
70307675db54Syw
70317675db54Syw int
aac_check_acc_handle(ddi_acc_handle_t handle)70327675db54Syw aac_check_acc_handle(ddi_acc_handle_t handle)
70337675db54Syw {
70347675db54Syw ddi_fm_error_t de;
70357675db54Syw
70367675db54Syw ddi_fm_acc_err_get(handle, &de, DDI_FME_VERSION);
70377675db54Syw return (de.fme_status);
70387675db54Syw }
70397675db54Syw
70407675db54Syw int
aac_check_dma_handle(ddi_dma_handle_t handle)70417675db54Syw aac_check_dma_handle(ddi_dma_handle_t handle)
70427675db54Syw {
70437675db54Syw ddi_fm_error_t de;
70447675db54Syw
70457675db54Syw ddi_fm_dma_err_get(handle, &de, DDI_FME_VERSION);
70467675db54Syw return (de.fme_status);
70477675db54Syw }
70487675db54Syw
70497675db54Syw void
aac_fm_ereport(struct aac_softstate * softs,char * detail)70507675db54Syw aac_fm_ereport(struct aac_softstate *softs, char *detail)
70517675db54Syw {
70527675db54Syw uint64_t ena;
70537675db54Syw char buf[FM_MAX_CLASS];
70547675db54Syw
70557675db54Syw (void) snprintf(buf, FM_MAX_CLASS, "%s.%s", DDI_FM_DEVICE, detail);
70567675db54Syw ena = fm_ena_generate(0, FM_ENA_FMT1);
70577675db54Syw if (DDI_FM_EREPORT_CAP(softs->fm_capabilities)) {
70587675db54Syw ddi_fm_ereport_post(softs->devinfo_p, buf, ena, DDI_NOSLEEP,
70597675db54Syw FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERSION, NULL);
70607675db54Syw }
70617675db54Syw }
70627675db54Syw
706358bc78c7SXin Chen /*
706458bc78c7SXin Chen * Autoconfiguration support
706558bc78c7SXin Chen */
706658bc78c7SXin Chen static int
aac_parse_devname(char * devnm,int * tgt,int * lun)706758bc78c7SXin Chen aac_parse_devname(char *devnm, int *tgt, int *lun)
706858bc78c7SXin Chen {
706958bc78c7SXin Chen char devbuf[SCSI_MAXNAMELEN];
707058bc78c7SXin Chen char *addr;
707158bc78c7SXin Chen char *p, *tp, *lp;
707258bc78c7SXin Chen long num;
707358bc78c7SXin Chen
707458bc78c7SXin Chen /* Parse dev name and address */
707558bc78c7SXin Chen (void) strcpy(devbuf, devnm);
707658bc78c7SXin Chen addr = "";
707758bc78c7SXin Chen for (p = devbuf; *p != '\0'; p++) {
707858bc78c7SXin Chen if (*p == '@') {
707958bc78c7SXin Chen addr = p + 1;
708058bc78c7SXin Chen *p = '\0';
708158bc78c7SXin Chen } else if (*p == ':') {
708258bc78c7SXin Chen *p = '\0';
708358bc78c7SXin Chen break;
708458bc78c7SXin Chen }
708558bc78c7SXin Chen }
708658bc78c7SXin Chen
708758bc78c7SXin Chen /* Parse taget and lun */
708858bc78c7SXin Chen for (p = tp = addr, lp = NULL; *p != '\0'; p++) {
708958bc78c7SXin Chen if (*p == ',') {
709058bc78c7SXin Chen lp = p + 1;
709158bc78c7SXin Chen *p = '\0';
709258bc78c7SXin Chen break;
709358bc78c7SXin Chen }
709458bc78c7SXin Chen }
709558bc78c7SXin Chen if (tgt && tp) {
709658bc78c7SXin Chen if (ddi_strtol(tp, NULL, 0x10, &num))
709758bc78c7SXin Chen return (AACERR);
709858bc78c7SXin Chen *tgt = (int)num;
709958bc78c7SXin Chen }
710058bc78c7SXin Chen if (lun && lp) {
710158bc78c7SXin Chen if (ddi_strtol(lp, NULL, 0x10, &num))
710258bc78c7SXin Chen return (AACERR);
710358bc78c7SXin Chen *lun = (int)num;
710458bc78c7SXin Chen }
710558bc78c7SXin Chen return (AACOK);
710658bc78c7SXin Chen }
710758bc78c7SXin Chen
710858bc78c7SXin Chen static dev_info_t *
aac_find_child(struct aac_softstate * softs,uint16_t tgt,uint8_t lun)710958bc78c7SXin Chen aac_find_child(struct aac_softstate *softs, uint16_t tgt, uint8_t lun)
711058bc78c7SXin Chen {
711158bc78c7SXin Chen dev_info_t *child = NULL;
711258bc78c7SXin Chen char addr[SCSI_MAXNAMELEN];
711358bc78c7SXin Chen char tmp[MAXNAMELEN];
711458bc78c7SXin Chen
711558bc78c7SXin Chen if (tgt < AAC_MAX_LD) {
711658bc78c7SXin Chen if (lun == 0) {
711758bc78c7SXin Chen struct aac_device *dvp = &softs->containers[tgt].dev;
711858bc78c7SXin Chen
711958bc78c7SXin Chen child = dvp->dip;
712058bc78c7SXin Chen }
712158bc78c7SXin Chen } else {
712258bc78c7SXin Chen (void) sprintf(addr, "%x,%x", tgt, lun);
712358bc78c7SXin Chen for (child = ddi_get_child(softs->devinfo_p);
712458bc78c7SXin Chen child; child = ddi_get_next_sibling(child)) {
712558bc78c7SXin Chen /* We don't care about non-persistent node */
712658bc78c7SXin Chen if (ndi_dev_is_persistent_node(child) == 0)
712758bc78c7SXin Chen continue;
712858bc78c7SXin Chen
712958bc78c7SXin Chen if (aac_name_node(child, tmp, MAXNAMELEN) !=
713058bc78c7SXin Chen DDI_SUCCESS)
713158bc78c7SXin Chen continue;
713258bc78c7SXin Chen if (strcmp(addr, tmp) == 0)
713358bc78c7SXin Chen break;
713458bc78c7SXin Chen }
713558bc78c7SXin Chen }
713658bc78c7SXin Chen return (child);
713758bc78c7SXin Chen }
713858bc78c7SXin Chen
713958bc78c7SXin Chen static int
aac_config_child(struct aac_softstate * softs,struct scsi_device * sd,dev_info_t ** dipp)714058bc78c7SXin Chen aac_config_child(struct aac_softstate *softs, struct scsi_device *sd,
714158bc78c7SXin Chen dev_info_t **dipp)
714258bc78c7SXin Chen {
714358bc78c7SXin Chen char *nodename = NULL;
714458bc78c7SXin Chen char **compatible = NULL;
714558bc78c7SXin Chen int ncompatible = 0;
714658bc78c7SXin Chen char *childname;
714758bc78c7SXin Chen dev_info_t *ldip = NULL;
714858bc78c7SXin Chen int tgt = sd->sd_address.a_target;
714958bc78c7SXin Chen int lun = sd->sd_address.a_lun;
715058bc78c7SXin Chen int dtype = sd->sd_inq->inq_dtype & DTYPE_MASK;
715158bc78c7SXin Chen int rval;
715258bc78c7SXin Chen
715358bc78c7SXin Chen DBCALLED(softs, 2);
715458bc78c7SXin Chen
715558bc78c7SXin Chen scsi_hba_nodename_compatible_get(sd->sd_inq, NULL, dtype,
715658bc78c7SXin Chen NULL, &nodename, &compatible, &ncompatible);
715758bc78c7SXin Chen if (nodename == NULL) {
715858bc78c7SXin Chen AACDB_PRINT(softs, CE_WARN,
715958bc78c7SXin Chen "found no comptible driver for t%dL%d", tgt, lun);
716058bc78c7SXin Chen rval = NDI_FAILURE;
716158bc78c7SXin Chen goto finish;
716258bc78c7SXin Chen }
716358bc78c7SXin Chen childname = (softs->legacy && dtype == DTYPE_DIRECT) ? "sd" : nodename;
716458bc78c7SXin Chen
716558bc78c7SXin Chen /* Create dev node */
716658bc78c7SXin Chen rval = ndi_devi_alloc(softs->devinfo_p, childname, DEVI_SID_NODEID,
716758bc78c7SXin Chen &ldip);
716858bc78c7SXin Chen if (rval == NDI_SUCCESS) {
716958bc78c7SXin Chen if (ndi_prop_update_int(DDI_DEV_T_NONE, ldip, "target", tgt)
717058bc78c7SXin Chen != DDI_PROP_SUCCESS) {
717158bc78c7SXin Chen AACDB_PRINT(softs, CE_WARN, "unable to create "
717258bc78c7SXin Chen "property for t%dL%d (target)", tgt, lun);
717358bc78c7SXin Chen rval = NDI_FAILURE;
717458bc78c7SXin Chen goto finish;
717558bc78c7SXin Chen }
717658bc78c7SXin Chen if (ndi_prop_update_int(DDI_DEV_T_NONE, ldip, "lun", lun)
717758bc78c7SXin Chen != DDI_PROP_SUCCESS) {
717858bc78c7SXin Chen AACDB_PRINT(softs, CE_WARN, "unable to create "
717958bc78c7SXin Chen "property for t%dL%d (lun)", tgt, lun);
718058bc78c7SXin Chen rval = NDI_FAILURE;
718158bc78c7SXin Chen goto finish;
718258bc78c7SXin Chen }
718358bc78c7SXin Chen if (ndi_prop_update_string_array(DDI_DEV_T_NONE, ldip,
718458bc78c7SXin Chen "compatible", compatible, ncompatible)
718558bc78c7SXin Chen != DDI_PROP_SUCCESS) {
718658bc78c7SXin Chen AACDB_PRINT(softs, CE_WARN, "unable to create "
718758bc78c7SXin Chen "property for t%dL%d (compatible)", tgt, lun);
718858bc78c7SXin Chen rval = NDI_FAILURE;
718958bc78c7SXin Chen goto finish;
719058bc78c7SXin Chen }
719158bc78c7SXin Chen
719258bc78c7SXin Chen rval = ndi_devi_online(ldip, NDI_ONLINE_ATTACH);
719358bc78c7SXin Chen if (rval != NDI_SUCCESS) {
719458bc78c7SXin Chen AACDB_PRINT(softs, CE_WARN, "unable to online t%dL%d",
719558bc78c7SXin Chen tgt, lun);
719658bc78c7SXin Chen ndi_prop_remove_all(ldip);
719758bc78c7SXin Chen (void) ndi_devi_free(ldip);
719858bc78c7SXin Chen }
719958bc78c7SXin Chen }
720058bc78c7SXin Chen finish:
720158bc78c7SXin Chen if (dipp)
720258bc78c7SXin Chen *dipp = ldip;
720358bc78c7SXin Chen
720458bc78c7SXin Chen scsi_hba_nodename_compatible_free(nodename, compatible);
720558bc78c7SXin Chen return (rval);
720658bc78c7SXin Chen }
720758bc78c7SXin Chen
720858bc78c7SXin Chen /*ARGSUSED*/
720958bc78c7SXin Chen static int
aac_probe_lun(struct aac_softstate * softs,struct scsi_device * sd)721058bc78c7SXin Chen aac_probe_lun(struct aac_softstate *softs, struct scsi_device *sd)
721158bc78c7SXin Chen {
721258bc78c7SXin Chen int tgt = sd->sd_address.a_target;
721358bc78c7SXin Chen int lun = sd->sd_address.a_lun;
721458bc78c7SXin Chen
721558bc78c7SXin Chen DBCALLED(softs, 2);
721658bc78c7SXin Chen
721758bc78c7SXin Chen if (tgt < AAC_MAX_LD) {
72180749e8deSXin Chen - Sun Microsystems - Beijing China enum aac_cfg_event event;
721958bc78c7SXin Chen
722058bc78c7SXin Chen if (lun == 0) {
722158bc78c7SXin Chen mutex_enter(&softs->io_lock);
72220749e8deSXin Chen - Sun Microsystems - Beijing China event = aac_probe_container(softs, tgt);
722358bc78c7SXin Chen mutex_exit(&softs->io_lock);
72240749e8deSXin Chen - Sun Microsystems - Beijing China if ((event != AAC_CFG_NULL_NOEXIST) &&
72250749e8deSXin Chen - Sun Microsystems - Beijing China (event != AAC_CFG_DELETE)) {
722658bc78c7SXin Chen if (scsi_hba_probe(sd, NULL) ==
722758bc78c7SXin Chen SCSIPROBE_EXISTS)
722858bc78c7SXin Chen return (NDI_SUCCESS);
722958bc78c7SXin Chen }
723058bc78c7SXin Chen }
723158bc78c7SXin Chen return (NDI_FAILURE);
723258bc78c7SXin Chen } else {
723358bc78c7SXin Chen int dtype;
72343fced439Szhongyan gu - Sun Microsystems - Beijing China int qual; /* device qualifier */
723558bc78c7SXin Chen
723658bc78c7SXin Chen if (scsi_hba_probe(sd, NULL) != SCSIPROBE_EXISTS)
723758bc78c7SXin Chen return (NDI_FAILURE);
723858bc78c7SXin Chen
723958bc78c7SXin Chen dtype = sd->sd_inq->inq_dtype & DTYPE_MASK;
72403fced439Szhongyan gu - Sun Microsystems - Beijing China qual = dtype >> 5;
724158bc78c7SXin Chen
724258bc78c7SXin Chen AACDB_PRINT(softs, CE_NOTE,
724358bc78c7SXin Chen "Phys. device found: tgt %d dtype %d: %s",
724458bc78c7SXin Chen tgt, dtype, sd->sd_inq->inq_vid);
724558bc78c7SXin Chen
72463fced439Szhongyan gu - Sun Microsystems - Beijing China /* Only non-DASD and JBOD mode DASD are allowed exposed */
72473fced439Szhongyan gu - Sun Microsystems - Beijing China if (dtype == DTYPE_RODIRECT /* CDROM */ ||
72483fced439Szhongyan gu - Sun Microsystems - Beijing China dtype == DTYPE_SEQUENTIAL /* TAPE */ ||
72493fced439Szhongyan gu - Sun Microsystems - Beijing China dtype == DTYPE_ESI /* SES */) {
72503fced439Szhongyan gu - Sun Microsystems - Beijing China if (!(softs->flags & AAC_FLAGS_NONDASD))
72513fced439Szhongyan gu - Sun Microsystems - Beijing China return (NDI_FAILURE);
72523fced439Szhongyan gu - Sun Microsystems - Beijing China AACDB_PRINT(softs, CE_NOTE, "non-DASD %d found", tgt);
72533fced439Szhongyan gu - Sun Microsystems - Beijing China
72543fced439Szhongyan gu - Sun Microsystems - Beijing China } else if (dtype == DTYPE_DIRECT) {
72553fced439Szhongyan gu - Sun Microsystems - Beijing China if (!(softs->flags & AAC_FLAGS_JBOD) || qual != 0)
72563fced439Szhongyan gu - Sun Microsystems - Beijing China return (NDI_FAILURE);
72573fced439Szhongyan gu - Sun Microsystems - Beijing China AACDB_PRINT(softs, CE_NOTE, "JBOD DASD %d found", tgt);
72583fced439Szhongyan gu - Sun Microsystems - Beijing China }
725958bc78c7SXin Chen
726058bc78c7SXin Chen mutex_enter(&softs->io_lock);
726158bc78c7SXin Chen softs->nondasds[AAC_PD(tgt)].dev.flags |= AAC_DFLAG_VALID;
726258bc78c7SXin Chen mutex_exit(&softs->io_lock);
726358bc78c7SXin Chen return (NDI_SUCCESS);
726458bc78c7SXin Chen }
726558bc78c7SXin Chen }
726658bc78c7SXin Chen
726758bc78c7SXin Chen static int
aac_config_lun(struct aac_softstate * softs,uint16_t tgt,uint8_t lun,dev_info_t ** ldip)726858bc78c7SXin Chen aac_config_lun(struct aac_softstate *softs, uint16_t tgt, uint8_t lun,
726958bc78c7SXin Chen dev_info_t **ldip)
727058bc78c7SXin Chen {
727158bc78c7SXin Chen struct scsi_device sd;
727258bc78c7SXin Chen dev_info_t *child;
727358bc78c7SXin Chen int rval;
727458bc78c7SXin Chen
727558bc78c7SXin Chen DBCALLED(softs, 2);
727658bc78c7SXin Chen
727758bc78c7SXin Chen if ((child = aac_find_child(softs, tgt, lun)) != NULL) {
727858bc78c7SXin Chen if (ldip)
727958bc78c7SXin Chen *ldip = child;
728058bc78c7SXin Chen return (NDI_SUCCESS);
728158bc78c7SXin Chen }
728258bc78c7SXin Chen
728358bc78c7SXin Chen bzero(&sd, sizeof (struct scsi_device));
728458bc78c7SXin Chen sd.sd_address.a_hba_tran = softs->hba_tran;
728558bc78c7SXin Chen sd.sd_address.a_target = (uint16_t)tgt;
728658bc78c7SXin Chen sd.sd_address.a_lun = (uint8_t)lun;
728758bc78c7SXin Chen if ((rval = aac_probe_lun(softs, &sd)) == NDI_SUCCESS)
728858bc78c7SXin Chen rval = aac_config_child(softs, &sd, ldip);
7289f42c2f53Szhongyan gu - Sun Microsystems - Beijing China /* scsi_unprobe is blank now. Free buffer manually */
7290f42c2f53Szhongyan gu - Sun Microsystems - Beijing China if (sd.sd_inq) {
7291f42c2f53Szhongyan gu - Sun Microsystems - Beijing China kmem_free(sd.sd_inq, SUN_INQSIZE);
7292f42c2f53Szhongyan gu - Sun Microsystems - Beijing China sd.sd_inq = (struct scsi_inquiry *)NULL;
7293f42c2f53Szhongyan gu - Sun Microsystems - Beijing China }
729458bc78c7SXin Chen return (rval);
729558bc78c7SXin Chen }
729658bc78c7SXin Chen
729758bc78c7SXin Chen static int
aac_config_tgt(struct aac_softstate * softs,int tgt)729858bc78c7SXin Chen aac_config_tgt(struct aac_softstate *softs, int tgt)
729958bc78c7SXin Chen {
730058bc78c7SXin Chen struct scsi_address ap;
730158bc78c7SXin Chen struct buf *bp = NULL;
730258bc78c7SXin Chen int buf_len = AAC_SCSI_RPTLUNS_HEAD_SIZE + AAC_SCSI_RPTLUNS_ADDR_SIZE;
730358bc78c7SXin Chen int list_len = 0;
730458bc78c7SXin Chen int lun_total = 0;
730558bc78c7SXin Chen dev_info_t *ldip;
730658bc78c7SXin Chen int i;
730758bc78c7SXin Chen
730858bc78c7SXin Chen ap.a_hba_tran = softs->hba_tran;
730958bc78c7SXin Chen ap.a_target = (uint16_t)tgt;
731058bc78c7SXin Chen ap.a_lun = 0;
731158bc78c7SXin Chen
731258bc78c7SXin Chen for (i = 0; i < 2; i++) {
731358bc78c7SXin Chen struct scsi_pkt *pkt;
731458bc78c7SXin Chen uchar_t *cdb;
731558bc78c7SXin Chen uchar_t *p;
731658bc78c7SXin Chen uint32_t data;
731758bc78c7SXin Chen
731858bc78c7SXin Chen if (bp == NULL) {
731958bc78c7SXin Chen if ((bp = scsi_alloc_consistent_buf(&ap, NULL,
732058bc78c7SXin Chen buf_len, B_READ, NULL_FUNC, NULL)) == NULL)
732115c07adcSJohn Levon return (AACERR);
732258bc78c7SXin Chen }
732358bc78c7SXin Chen if ((pkt = scsi_init_pkt(&ap, NULL, bp, CDB_GROUP5,
732458bc78c7SXin Chen sizeof (struct scsi_arq_status), 0, PKT_CONSISTENT,
732558bc78c7SXin Chen NULL, NULL)) == NULL) {
732658bc78c7SXin Chen scsi_free_consistent_buf(bp);
732758bc78c7SXin Chen return (AACERR);
732858bc78c7SXin Chen }
732958bc78c7SXin Chen cdb = pkt->pkt_cdbp;
733058bc78c7SXin Chen bzero(cdb, CDB_GROUP5);
733158bc78c7SXin Chen cdb[0] = SCMD_REPORT_LUNS;
733258bc78c7SXin Chen
733358bc78c7SXin Chen /* Convert buffer len from local to LE_32 */
733458bc78c7SXin Chen data = buf_len;
733558bc78c7SXin Chen for (p = &cdb[9]; p > &cdb[5]; p--) {
733658bc78c7SXin Chen *p = data & 0xff;
733758bc78c7SXin Chen data >>= 8;
733858bc78c7SXin Chen }
733958bc78c7SXin Chen
734058bc78c7SXin Chen if (scsi_poll(pkt) < 0 ||
734158bc78c7SXin Chen ((struct scsi_status *)pkt->pkt_scbp)->sts_chk) {
734258bc78c7SXin Chen scsi_destroy_pkt(pkt);
734358bc78c7SXin Chen break;
734458bc78c7SXin Chen }
734558bc78c7SXin Chen
734658bc78c7SXin Chen /* Convert list_len from LE_32 to local */
734758bc78c7SXin Chen for (p = (uchar_t *)bp->b_un.b_addr;
734858bc78c7SXin Chen p < (uchar_t *)bp->b_un.b_addr + 4; p++) {
734958bc78c7SXin Chen data <<= 8;
735058bc78c7SXin Chen data |= *p;
735158bc78c7SXin Chen }
735258bc78c7SXin Chen list_len = data;
735358bc78c7SXin Chen if (buf_len < list_len + AAC_SCSI_RPTLUNS_HEAD_SIZE) {
735458bc78c7SXin Chen scsi_free_consistent_buf(bp);
735558bc78c7SXin Chen bp = NULL;
735658bc78c7SXin Chen buf_len = list_len + AAC_SCSI_RPTLUNS_HEAD_SIZE;
735758bc78c7SXin Chen }
735858bc78c7SXin Chen scsi_destroy_pkt(pkt);
735958bc78c7SXin Chen }
736058bc78c7SXin Chen if (i >= 2) {
736158bc78c7SXin Chen uint8_t *buf = (uint8_t *)(bp->b_un.b_addr +
736258bc78c7SXin Chen AAC_SCSI_RPTLUNS_HEAD_SIZE);
736358bc78c7SXin Chen
736458bc78c7SXin Chen for (i = 0; i < (list_len / AAC_SCSI_RPTLUNS_ADDR_SIZE); i++) {
736558bc78c7SXin Chen uint16_t lun;
736658bc78c7SXin Chen
736758bc78c7SXin Chen /* Determine report luns addressing type */
736858bc78c7SXin Chen switch (buf[0] & AAC_SCSI_RPTLUNS_ADDR_MASK) {
736958bc78c7SXin Chen /*
737058bc78c7SXin Chen * Vendors in the field have been found to be
737158bc78c7SXin Chen * concatenating bus/target/lun to equal the
737258bc78c7SXin Chen * complete lun value instead of switching to
737358bc78c7SXin Chen * flat space addressing
737458bc78c7SXin Chen */
737558bc78c7SXin Chen case AAC_SCSI_RPTLUNS_ADDR_PERIPHERAL:
737658bc78c7SXin Chen case AAC_SCSI_RPTLUNS_ADDR_LOGICAL_UNIT:
737758bc78c7SXin Chen case AAC_SCSI_RPTLUNS_ADDR_FLAT_SPACE:
737858bc78c7SXin Chen lun = ((buf[0] & 0x3f) << 8) | buf[1];
737958bc78c7SXin Chen if (lun > UINT8_MAX) {
738058bc78c7SXin Chen AACDB_PRINT(softs, CE_WARN,
738158bc78c7SXin Chen "abnormal lun number: %d", lun);
738258bc78c7SXin Chen break;
738358bc78c7SXin Chen }
738458bc78c7SXin Chen if (aac_config_lun(softs, tgt, lun, &ldip) ==
738558bc78c7SXin Chen NDI_SUCCESS)
738658bc78c7SXin Chen lun_total++;
738758bc78c7SXin Chen break;
738858bc78c7SXin Chen }
738958bc78c7SXin Chen
739058bc78c7SXin Chen buf += AAC_SCSI_RPTLUNS_ADDR_SIZE;
739158bc78c7SXin Chen }
739258bc78c7SXin Chen } else {
739358bc78c7SXin Chen /* The target may do not support SCMD_REPORT_LUNS. */
739458bc78c7SXin Chen if (aac_config_lun(softs, tgt, 0, &ldip) == NDI_SUCCESS)
739558bc78c7SXin Chen lun_total++;
739658bc78c7SXin Chen }
739758bc78c7SXin Chen scsi_free_consistent_buf(bp);
739858bc78c7SXin Chen return (lun_total);
739958bc78c7SXin Chen }
740058bc78c7SXin Chen
740158bc78c7SXin Chen static void
aac_devcfg(struct aac_softstate * softs,int tgt,int en)740258bc78c7SXin Chen aac_devcfg(struct aac_softstate *softs, int tgt, int en)
740358bc78c7SXin Chen {
740458bc78c7SXin Chen struct aac_device *dvp;
740558bc78c7SXin Chen
740658bc78c7SXin Chen mutex_enter(&softs->io_lock);
740758bc78c7SXin Chen dvp = AAC_DEV(softs, tgt);
740858bc78c7SXin Chen if (en)
740958bc78c7SXin Chen dvp->flags |= AAC_DFLAG_CONFIGURING;
741058bc78c7SXin Chen else
741158bc78c7SXin Chen dvp->flags &= ~AAC_DFLAG_CONFIGURING;
741258bc78c7SXin Chen mutex_exit(&softs->io_lock);
741358bc78c7SXin Chen }
741458bc78c7SXin Chen
741558bc78c7SXin Chen static int
aac_tran_bus_config(dev_info_t * parent,uint_t flags,ddi_bus_config_op_t op,void * arg,dev_info_t ** childp)741658bc78c7SXin Chen aac_tran_bus_config(dev_info_t *parent, uint_t flags, ddi_bus_config_op_t op,
741758bc78c7SXin Chen void *arg, dev_info_t **childp)
741858bc78c7SXin Chen {
741958bc78c7SXin Chen struct aac_softstate *softs;
7420c9ffe217SToomas Soome int rval = NDI_FAILURE;
742158bc78c7SXin Chen
742258bc78c7SXin Chen if ((softs = ddi_get_soft_state(aac_softstatep,
742358bc78c7SXin Chen ddi_get_instance(parent))) == NULL)
742458bc78c7SXin Chen return (NDI_FAILURE);
742558bc78c7SXin Chen
742658bc78c7SXin Chen /* Commands for bus config should be blocked as the bus is quiesced */
742758bc78c7SXin Chen mutex_enter(&softs->io_lock);
742858bc78c7SXin Chen if (softs->state & AAC_STATE_QUIESCED) {
742958bc78c7SXin Chen AACDB_PRINT(softs, CE_NOTE,
7430c9ffe217SToomas Soome "bus_config aborted because bus is quiesced");
743158bc78c7SXin Chen mutex_exit(&softs->io_lock);
743258bc78c7SXin Chen return (NDI_FAILURE);
743358bc78c7SXin Chen }
743458bc78c7SXin Chen mutex_exit(&softs->io_lock);
743558bc78c7SXin Chen
743658bc78c7SXin Chen DBCALLED(softs, 1);
743758bc78c7SXin Chen
743858bc78c7SXin Chen /* Hold the nexus across the bus_config */
7439*3fe80ca4SDan Cross ndi_devi_enter(parent);
744058bc78c7SXin Chen switch (op) {
744158bc78c7SXin Chen case BUS_CONFIG_ONE: {
744258bc78c7SXin Chen int tgt, lun;
744358bc78c7SXin Chen
744458bc78c7SXin Chen if (aac_parse_devname(arg, &tgt, &lun) != AACOK) {
744558bc78c7SXin Chen rval = NDI_FAILURE;
744658bc78c7SXin Chen break;
744758bc78c7SXin Chen }
74483fced439Szhongyan gu - Sun Microsystems - Beijing China if (tgt >= AAC_MAX_LD) {
74493fced439Szhongyan gu - Sun Microsystems - Beijing China if (tgt >= AAC_MAX_DEV(softs)) {
74503fced439Szhongyan gu - Sun Microsystems - Beijing China rval = NDI_FAILURE;
74513fced439Szhongyan gu - Sun Microsystems - Beijing China break;
74523fced439Szhongyan gu - Sun Microsystems - Beijing China }
74533fced439Szhongyan gu - Sun Microsystems - Beijing China }
745458bc78c7SXin Chen
745558bc78c7SXin Chen AAC_DEVCFG_BEGIN(softs, tgt);
745658bc78c7SXin Chen rval = aac_config_lun(softs, tgt, lun, childp);
745758bc78c7SXin Chen AAC_DEVCFG_END(softs, tgt);
745858bc78c7SXin Chen break;
745958bc78c7SXin Chen }
746058bc78c7SXin Chen
746158bc78c7SXin Chen case BUS_CONFIG_DRIVER:
746258bc78c7SXin Chen case BUS_CONFIG_ALL: {
746358bc78c7SXin Chen uint32_t bus, tgt;
746458bc78c7SXin Chen int index, total;
746558bc78c7SXin Chen
746658bc78c7SXin Chen for (tgt = 0; tgt < AAC_MAX_LD; tgt++) {
746758bc78c7SXin Chen AAC_DEVCFG_BEGIN(softs, tgt);
746858bc78c7SXin Chen (void) aac_config_lun(softs, tgt, 0, NULL);
746958bc78c7SXin Chen AAC_DEVCFG_END(softs, tgt);
747058bc78c7SXin Chen }
747158bc78c7SXin Chen
747258bc78c7SXin Chen /* Config the non-DASD devices connected to the card */
747358bc78c7SXin Chen total = 0;
747458bc78c7SXin Chen index = AAC_MAX_LD;
747558bc78c7SXin Chen for (bus = 0; bus < softs->bus_max; bus++) {
747658bc78c7SXin Chen AACDB_PRINT(softs, CE_NOTE, "bus %d:", bus);
747758bc78c7SXin Chen for (tgt = 0; tgt < softs->tgt_max; tgt++, index++) {
747858bc78c7SXin Chen AAC_DEVCFG_BEGIN(softs, index);
747958bc78c7SXin Chen if (aac_config_tgt(softs, index))
748058bc78c7SXin Chen total++;
748158bc78c7SXin Chen AAC_DEVCFG_END(softs, index);
748258bc78c7SXin Chen }
748358bc78c7SXin Chen }
748458bc78c7SXin Chen AACDB_PRINT(softs, CE_CONT,
748558bc78c7SXin Chen "?Total %d phys. device(s) found", total);
748658bc78c7SXin Chen rval = NDI_SUCCESS;
748758bc78c7SXin Chen break;
748858bc78c7SXin Chen }
748958bc78c7SXin Chen }
749058bc78c7SXin Chen
749158bc78c7SXin Chen if (rval == NDI_SUCCESS)
749258bc78c7SXin Chen rval = ndi_busop_bus_config(parent, flags, op, arg, childp, 0);
7493*3fe80ca4SDan Cross ndi_devi_exit(parent);
749458bc78c7SXin Chen return (rval);
749558bc78c7SXin Chen }
749658bc78c7SXin Chen
74970749e8deSXin Chen - Sun Microsystems - Beijing China /*ARGSUSED*/
74980749e8deSXin Chen - Sun Microsystems - Beijing China static int
aac_handle_dr(struct aac_softstate * softs,int tgt,int lun,int event)74990749e8deSXin Chen - Sun Microsystems - Beijing China aac_handle_dr(struct aac_softstate *softs, int tgt, int lun, int event)
750058bc78c7SXin Chen {
750158bc78c7SXin Chen struct aac_device *dvp;
750258bc78c7SXin Chen dev_info_t *dip;
750358bc78c7SXin Chen int valid;
750458bc78c7SXin Chen
750558bc78c7SXin Chen DBCALLED(softs, 1);
750658bc78c7SXin Chen
750758bc78c7SXin Chen /* Hold the nexus across the bus_config */
75080749e8deSXin Chen - Sun Microsystems - Beijing China dvp = AAC_DEV(softs, tgt);
750958bc78c7SXin Chen valid = AAC_DEV_IS_VALID(dvp);
751058bc78c7SXin Chen dip = dvp->dip;
75110749e8deSXin Chen - Sun Microsystems - Beijing China if (!(softs->state & AAC_STATE_RUN))
75120749e8deSXin Chen - Sun Microsystems - Beijing China return (AACERR);
751358bc78c7SXin Chen mutex_exit(&softs->io_lock);
751458bc78c7SXin Chen
75150749e8deSXin Chen - Sun Microsystems - Beijing China switch (event) {
75160749e8deSXin Chen - Sun Microsystems - Beijing China case AAC_CFG_ADD:
75170749e8deSXin Chen - Sun Microsystems - Beijing China case AAC_CFG_DELETE:
751858bc78c7SXin Chen /* Device onlined */
751958bc78c7SXin Chen if (dip == NULL && valid) {
7520*3fe80ca4SDan Cross ndi_devi_enter(softs->devinfo_p);
75210749e8deSXin Chen - Sun Microsystems - Beijing China (void) aac_config_lun(softs, tgt, 0, NULL);
752258bc78c7SXin Chen AACDB_PRINT(softs, CE_NOTE, "c%dt%dL%d onlined",
75230749e8deSXin Chen - Sun Microsystems - Beijing China softs->instance, tgt, lun);
7524*3fe80ca4SDan Cross ndi_devi_exit(softs->devinfo_p);
752558bc78c7SXin Chen }
752658bc78c7SXin Chen /* Device offlined */
752758bc78c7SXin Chen if (dip && !valid) {
752858bc78c7SXin Chen mutex_enter(&softs->io_lock);
752958bc78c7SXin Chen (void) aac_do_reset(softs);
753058bc78c7SXin Chen mutex_exit(&softs->io_lock);
753158bc78c7SXin Chen
753258bc78c7SXin Chen (void) ndi_devi_offline(dip, NDI_DEVI_REMOVE);
753358bc78c7SXin Chen AACDB_PRINT(softs, CE_NOTE, "c%dt%dL%d offlined",
75340749e8deSXin Chen - Sun Microsystems - Beijing China softs->instance, tgt, lun);
753558bc78c7SXin Chen }
753658bc78c7SXin Chen break;
753758bc78c7SXin Chen }
753858bc78c7SXin Chen
75390749e8deSXin Chen - Sun Microsystems - Beijing China mutex_enter(&softs->io_lock);
754058bc78c7SXin Chen return (AACOK);
754158bc78c7SXin Chen }
754258bc78c7SXin Chen
75431dd0a2dbSpl #ifdef DEBUG
75447c478bd9Sstevel@tonic-gate
75457c478bd9Sstevel@tonic-gate /* -------------------------debug aid functions-------------------------- */
7546830d82f7Spl
7547830d82f7Spl #define AAC_FIB_CMD_KEY_STRINGS \
7548830d82f7Spl TestCommandResponse, "TestCommandResponse", \
7549830d82f7Spl TestAdapterCommand, "TestAdapterCommand", \
7550830d82f7Spl LastTestCommand, "LastTestCommand", \
7551830d82f7Spl ReinitHostNormCommandQueue, "ReinitHostNormCommandQueue", \
7552830d82f7Spl ReinitHostHighCommandQueue, "ReinitHostHighCommandQueue", \
7553830d82f7Spl ReinitHostHighRespQueue, "ReinitHostHighRespQueue", \
7554830d82f7Spl ReinitHostNormRespQueue, "ReinitHostNormRespQueue", \
7555830d82f7Spl ReinitAdapNormCommandQueue, "ReinitAdapNormCommandQueue", \
7556830d82f7Spl ReinitAdapHighCommandQueue, "ReinitAdapHighCommandQueue", \
7557830d82f7Spl ReinitAdapHighRespQueue, "ReinitAdapHighRespQueue", \
7558830d82f7Spl ReinitAdapNormRespQueue, "ReinitAdapNormRespQueue", \
7559830d82f7Spl InterfaceShutdown, "InterfaceShutdown", \
7560830d82f7Spl DmaCommandFib, "DmaCommandFib", \
7561830d82f7Spl StartProfile, "StartProfile", \
7562830d82f7Spl TermProfile, "TermProfile", \
7563830d82f7Spl SpeedTest, "SpeedTest", \
7564830d82f7Spl TakeABreakPt, "TakeABreakPt", \
7565830d82f7Spl RequestPerfData, "RequestPerfData", \
7566830d82f7Spl SetInterruptDefTimer, "SetInterruptDefTimer", \
7567830d82f7Spl SetInterruptDefCount, "SetInterruptDefCount", \
7568830d82f7Spl GetInterruptDefStatus, "GetInterruptDefStatus", \
7569830d82f7Spl LastCommCommand, "LastCommCommand", \
7570830d82f7Spl NuFileSystem, "NuFileSystem", \
7571830d82f7Spl UFS, "UFS", \
7572830d82f7Spl HostFileSystem, "HostFileSystem", \
7573830d82f7Spl LastFileSystemCommand, "LastFileSystemCommand", \
7574830d82f7Spl ContainerCommand, "ContainerCommand", \
7575830d82f7Spl ContainerCommand64, "ContainerCommand64", \
7576830d82f7Spl ClusterCommand, "ClusterCommand", \
7577830d82f7Spl ScsiPortCommand, "ScsiPortCommand", \
7578830d82f7Spl ScsiPortCommandU64, "ScsiPortCommandU64", \
7579830d82f7Spl AifRequest, "AifRequest", \
7580830d82f7Spl CheckRevision, "CheckRevision", \
7581830d82f7Spl FsaHostShutdown, "FsaHostShutdown", \
7582830d82f7Spl RequestAdapterInfo, "RequestAdapterInfo", \
7583830d82f7Spl IsAdapterPaused, "IsAdapterPaused", \
7584830d82f7Spl SendHostTime, "SendHostTime", \
7585830d82f7Spl LastMiscCommand, "LastMiscCommand"
7586830d82f7Spl
7587830d82f7Spl #define AAC_CTVM_SUBCMD_KEY_STRINGS \
7588830d82f7Spl VM_Null, "VM_Null", \
7589830d82f7Spl VM_NameServe, "VM_NameServe", \
7590830d82f7Spl VM_ContainerConfig, "VM_ContainerConfig", \
7591830d82f7Spl VM_Ioctl, "VM_Ioctl", \
7592830d82f7Spl VM_FilesystemIoctl, "VM_FilesystemIoctl", \
7593830d82f7Spl VM_CloseAll, "VM_CloseAll", \
7594830d82f7Spl VM_CtBlockRead, "VM_CtBlockRead", \
7595830d82f7Spl VM_CtBlockWrite, "VM_CtBlockWrite", \
7596830d82f7Spl VM_SliceBlockRead, "VM_SliceBlockRead", \
7597830d82f7Spl VM_SliceBlockWrite, "VM_SliceBlockWrite", \
7598830d82f7Spl VM_DriveBlockRead, "VM_DriveBlockRead", \
7599830d82f7Spl VM_DriveBlockWrite, "VM_DriveBlockWrite", \
7600830d82f7Spl VM_EnclosureMgt, "VM_EnclosureMgt", \
7601830d82f7Spl VM_Unused, "VM_Unused", \
7602830d82f7Spl VM_CtBlockVerify, "VM_CtBlockVerify", \
7603830d82f7Spl VM_CtPerf, "VM_CtPerf", \
7604830d82f7Spl VM_CtBlockRead64, "VM_CtBlockRead64", \
7605830d82f7Spl VM_CtBlockWrite64, "VM_CtBlockWrite64", \
7606830d82f7Spl VM_CtBlockVerify64, "VM_CtBlockVerify64", \
7607830d82f7Spl VM_CtHostRead64, "VM_CtHostRead64", \
7608830d82f7Spl VM_CtHostWrite64, "VM_CtHostWrite64", \
7609830d82f7Spl VM_NameServe64, "VM_NameServe64"
7610830d82f7Spl
7611830d82f7Spl #define AAC_CT_SUBCMD_KEY_STRINGS \
7612830d82f7Spl CT_Null, "CT_Null", \
7613830d82f7Spl CT_GET_SLICE_COUNT, "CT_GET_SLICE_COUNT", \
7614830d82f7Spl CT_GET_PARTITION_COUNT, "CT_GET_PARTITION_COUNT", \
7615830d82f7Spl CT_GET_PARTITION_INFO, "CT_GET_PARTITION_INFO", \
7616830d82f7Spl CT_GET_CONTAINER_COUNT, "CT_GET_CONTAINER_COUNT", \
7617830d82f7Spl CT_GET_CONTAINER_INFO_OLD, "CT_GET_CONTAINER_INFO_OLD", \
7618830d82f7Spl CT_WRITE_MBR, "CT_WRITE_MBR", \
7619830d82f7Spl CT_WRITE_PARTITION, "CT_WRITE_PARTITION", \
7620830d82f7Spl CT_UPDATE_PARTITION, "CT_UPDATE_PARTITION", \
7621830d82f7Spl CT_UNLOAD_CONTAINER, "CT_UNLOAD_CONTAINER", \
7622830d82f7Spl CT_CONFIG_SINGLE_PRIMARY, "CT_CONFIG_SINGLE_PRIMARY", \
7623830d82f7Spl CT_READ_CONFIG_AGE, "CT_READ_CONFIG_AGE", \
7624830d82f7Spl CT_WRITE_CONFIG_AGE, "CT_WRITE_CONFIG_AGE", \
7625830d82f7Spl CT_READ_SERIAL_NUMBER, "CT_READ_SERIAL_NUMBER", \
7626830d82f7Spl CT_ZERO_PAR_ENTRY, "CT_ZERO_PAR_ENTRY", \
7627830d82f7Spl CT_READ_MBR, "CT_READ_MBR", \
7628830d82f7Spl CT_READ_PARTITION, "CT_READ_PARTITION", \
7629830d82f7Spl CT_DESTROY_CONTAINER, "CT_DESTROY_CONTAINER", \
7630830d82f7Spl CT_DESTROY2_CONTAINER, "CT_DESTROY2_CONTAINER", \
7631830d82f7Spl CT_SLICE_SIZE, "CT_SLICE_SIZE", \
7632830d82f7Spl CT_CHECK_CONFLICTS, "CT_CHECK_CONFLICTS", \
7633830d82f7Spl CT_MOVE_CONTAINER, "CT_MOVE_CONTAINER", \
7634830d82f7Spl CT_READ_LAST_DRIVE, "CT_READ_LAST_DRIVE", \
7635830d82f7Spl CT_WRITE_LAST_DRIVE, "CT_WRITE_LAST_DRIVE", \
7636830d82f7Spl CT_UNMIRROR, "CT_UNMIRROR", \
7637830d82f7Spl CT_MIRROR_DELAY, "CT_MIRROR_DELAY", \
7638830d82f7Spl CT_GEN_MIRROR, "CT_GEN_MIRROR", \
7639830d82f7Spl CT_GEN_MIRROR2, "CT_GEN_MIRROR2", \
7640830d82f7Spl CT_TEST_CONTAINER, "CT_TEST_CONTAINER", \
7641830d82f7Spl CT_MOVE2, "CT_MOVE2", \
7642830d82f7Spl CT_SPLIT, "CT_SPLIT", \
7643830d82f7Spl CT_SPLIT2, "CT_SPLIT2", \
7644830d82f7Spl CT_SPLIT_BROKEN, "CT_SPLIT_BROKEN", \
7645830d82f7Spl CT_SPLIT_BROKEN2, "CT_SPLIT_BROKEN2", \
7646830d82f7Spl CT_RECONFIG, "CT_RECONFIG", \
7647830d82f7Spl CT_BREAK2, "CT_BREAK2", \
7648830d82f7Spl CT_BREAK, "CT_BREAK", \
7649830d82f7Spl CT_MERGE2, "CT_MERGE2", \
7650830d82f7Spl CT_MERGE, "CT_MERGE", \
7651830d82f7Spl CT_FORCE_ERROR, "CT_FORCE_ERROR", \
7652830d82f7Spl CT_CLEAR_ERROR, "CT_CLEAR_ERROR", \
7653830d82f7Spl CT_ASSIGN_FAILOVER, "CT_ASSIGN_FAILOVER", \
7654830d82f7Spl CT_CLEAR_FAILOVER, "CT_CLEAR_FAILOVER", \
7655830d82f7Spl CT_GET_FAILOVER_DATA, "CT_GET_FAILOVER_DATA", \
7656830d82f7Spl CT_VOLUME_ADD, "CT_VOLUME_ADD", \
7657830d82f7Spl CT_VOLUME_ADD2, "CT_VOLUME_ADD2", \
7658830d82f7Spl CT_MIRROR_STATUS, "CT_MIRROR_STATUS", \
7659830d82f7Spl CT_COPY_STATUS, "CT_COPY_STATUS", \
7660830d82f7Spl CT_COPY, "CT_COPY", \
7661830d82f7Spl CT_UNLOCK_CONTAINER, "CT_UNLOCK_CONTAINER", \
7662830d82f7Spl CT_LOCK_CONTAINER, "CT_LOCK_CONTAINER", \
7663830d82f7Spl CT_MAKE_READ_ONLY, "CT_MAKE_READ_ONLY", \
7664830d82f7Spl CT_MAKE_READ_WRITE, "CT_MAKE_READ_WRITE", \
7665830d82f7Spl CT_CLEAN_DEAD, "CT_CLEAN_DEAD", \
7666830d82f7Spl CT_ABORT_MIRROR_COMMAND, "CT_ABORT_MIRROR_COMMAND", \
7667830d82f7Spl CT_SET, "CT_SET", \
7668830d82f7Spl CT_GET, "CT_GET", \
7669830d82f7Spl CT_GET_NVLOG_ENTRY, "CT_GET_NVLOG_ENTRY", \
7670830d82f7Spl CT_GET_DELAY, "CT_GET_DELAY", \
7671830d82f7Spl CT_ZERO_CONTAINER_SPACE, "CT_ZERO_CONTAINER_SPACE", \
7672830d82f7Spl CT_GET_ZERO_STATUS, "CT_GET_ZERO_STATUS", \
7673830d82f7Spl CT_SCRUB, "CT_SCRUB", \
7674830d82f7Spl CT_GET_SCRUB_STATUS, "CT_GET_SCRUB_STATUS", \
7675830d82f7Spl CT_GET_SLICE_INFO, "CT_GET_SLICE_INFO", \
7676830d82f7Spl CT_GET_SCSI_METHOD, "CT_GET_SCSI_METHOD", \
7677830d82f7Spl CT_PAUSE_IO, "CT_PAUSE_IO", \
7678830d82f7Spl CT_RELEASE_IO, "CT_RELEASE_IO", \
7679830d82f7Spl CT_SCRUB2, "CT_SCRUB2", \
7680830d82f7Spl CT_MCHECK, "CT_MCHECK", \
7681830d82f7Spl CT_CORRUPT, "CT_CORRUPT", \
7682830d82f7Spl CT_GET_TASK_COUNT, "CT_GET_TASK_COUNT", \
7683830d82f7Spl CT_PROMOTE, "CT_PROMOTE", \
7684830d82f7Spl CT_SET_DEAD, "CT_SET_DEAD", \
7685830d82f7Spl CT_CONTAINER_OPTIONS, "CT_CONTAINER_OPTIONS", \
7686830d82f7Spl CT_GET_NV_PARAM, "CT_GET_NV_PARAM", \
7687830d82f7Spl CT_GET_PARAM, "CT_GET_PARAM", \
7688830d82f7Spl CT_NV_PARAM_SIZE, "CT_NV_PARAM_SIZE", \
7689830d82f7Spl CT_COMMON_PARAM_SIZE, "CT_COMMON_PARAM_SIZE", \
7690830d82f7Spl CT_PLATFORM_PARAM_SIZE, "CT_PLATFORM_PARAM_SIZE", \
7691830d82f7Spl CT_SET_NV_PARAM, "CT_SET_NV_PARAM", \
7692830d82f7Spl CT_ABORT_SCRUB, "CT_ABORT_SCRUB", \
7693830d82f7Spl CT_GET_SCRUB_ERROR, "CT_GET_SCRUB_ERROR", \
7694830d82f7Spl CT_LABEL_CONTAINER, "CT_LABEL_CONTAINER", \
7695830d82f7Spl CT_CONTINUE_DATA, "CT_CONTINUE_DATA", \
7696830d82f7Spl CT_STOP_DATA, "CT_STOP_DATA", \
7697830d82f7Spl CT_GET_PARTITION_TABLE, "CT_GET_PARTITION_TABLE", \
7698830d82f7Spl CT_GET_DISK_PARTITIONS, "CT_GET_DISK_PARTITIONS", \
7699830d82f7Spl CT_GET_MISC_STATUS, "CT_GET_MISC_STATUS", \
7700830d82f7Spl CT_GET_CONTAINER_PERF_INFO, "CT_GET_CONTAINER_PERF_INFO", \
7701830d82f7Spl CT_GET_TIME, "CT_GET_TIME", \
7702830d82f7Spl CT_READ_DATA, "CT_READ_DATA", \
7703830d82f7Spl CT_CTR, "CT_CTR", \
7704830d82f7Spl CT_CTL, "CT_CTL", \
7705830d82f7Spl CT_DRAINIO, "CT_DRAINIO", \
7706830d82f7Spl CT_RELEASEIO, "CT_RELEASEIO", \
7707830d82f7Spl CT_GET_NVRAM, "CT_GET_NVRAM", \
7708830d82f7Spl CT_GET_MEMORY, "CT_GET_MEMORY", \
7709830d82f7Spl CT_PRINT_CT_LOG, "CT_PRINT_CT_LOG", \
7710830d82f7Spl CT_ADD_LEVEL, "CT_ADD_LEVEL", \
7711830d82f7Spl CT_NV_ZERO, "CT_NV_ZERO", \
7712830d82f7Spl CT_READ_SIGNATURE, "CT_READ_SIGNATURE", \
7713830d82f7Spl CT_THROTTLE_ON, "CT_THROTTLE_ON", \
7714830d82f7Spl CT_THROTTLE_OFF, "CT_THROTTLE_OFF", \
7715830d82f7Spl CT_GET_THROTTLE_STATS, "CT_GET_THROTTLE_STATS", \
7716830d82f7Spl CT_MAKE_SNAPSHOT, "CT_MAKE_SNAPSHOT", \
7717830d82f7Spl CT_REMOVE_SNAPSHOT, "CT_REMOVE_SNAPSHOT", \
7718830d82f7Spl CT_WRITE_USER_FLAGS, "CT_WRITE_USER_FLAGS", \
7719830d82f7Spl CT_READ_USER_FLAGS, "CT_READ_USER_FLAGS", \
7720830d82f7Spl CT_MONITOR, "CT_MONITOR", \
7721830d82f7Spl CT_GEN_MORPH, "CT_GEN_MORPH", \
7722830d82f7Spl CT_GET_SNAPSHOT_INFO, "CT_GET_SNAPSHOT_INFO", \
7723830d82f7Spl CT_CACHE_SET, "CT_CACHE_SET", \
7724830d82f7Spl CT_CACHE_STAT, "CT_CACHE_STAT", \
7725830d82f7Spl CT_TRACE_START, "CT_TRACE_START", \
7726830d82f7Spl CT_TRACE_STOP, "CT_TRACE_STOP", \
7727830d82f7Spl CT_TRACE_ENABLE, "CT_TRACE_ENABLE", \
7728830d82f7Spl CT_TRACE_DISABLE, "CT_TRACE_DISABLE", \
7729830d82f7Spl CT_FORCE_CORE_DUMP, "CT_FORCE_CORE_DUMP", \
7730830d82f7Spl CT_SET_SERIAL_NUMBER, "CT_SET_SERIAL_NUMBER", \
7731830d82f7Spl CT_RESET_SERIAL_NUMBER, "CT_RESET_SERIAL_NUMBER", \
7732830d82f7Spl CT_ENABLE_RAID5, "CT_ENABLE_RAID5", \
7733830d82f7Spl CT_CLEAR_VALID_DUMP_FLAG, "CT_CLEAR_VALID_DUMP_FLAG", \
7734830d82f7Spl CT_GET_MEM_STATS, "CT_GET_MEM_STATS", \
7735830d82f7Spl CT_GET_CORE_SIZE, "CT_GET_CORE_SIZE", \
7736830d82f7Spl CT_CREATE_CONTAINER_OLD, "CT_CREATE_CONTAINER_OLD", \
7737830d82f7Spl CT_STOP_DUMPS, "CT_STOP_DUMPS", \
7738830d82f7Spl CT_PANIC_ON_TAKE_A_BREAK, "CT_PANIC_ON_TAKE_A_BREAK", \
7739830d82f7Spl CT_GET_CACHE_STATS, "CT_GET_CACHE_STATS", \
7740830d82f7Spl CT_MOVE_PARTITION, "CT_MOVE_PARTITION", \
7741830d82f7Spl CT_FLUSH_CACHE, "CT_FLUSH_CACHE", \
7742830d82f7Spl CT_READ_NAME, "CT_READ_NAME", \
7743830d82f7Spl CT_WRITE_NAME, "CT_WRITE_NAME", \
7744830d82f7Spl CT_TOSS_CACHE, "CT_TOSS_CACHE", \
7745830d82f7Spl CT_LOCK_DRAINIO, "CT_LOCK_DRAINIO", \
7746830d82f7Spl CT_CONTAINER_OFFLINE, "CT_CONTAINER_OFFLINE", \
7747830d82f7Spl CT_SET_CACHE_SIZE, "CT_SET_CACHE_SIZE", \
7748830d82f7Spl CT_CLEAN_SHUTDOWN_STATUS, "CT_CLEAN_SHUTDOWN_STATUS", \
7749830d82f7Spl CT_CLEAR_DISKLOG_ON_DISK, "CT_CLEAR_DISKLOG_ON_DISK", \
7750830d82f7Spl CT_CLEAR_ALL_DISKLOG, "CT_CLEAR_ALL_DISKLOG", \
7751830d82f7Spl CT_CACHE_FAVOR, "CT_CACHE_FAVOR", \
7752830d82f7Spl CT_READ_PASSTHRU_MBR, "CT_READ_PASSTHRU_MBR", \
7753830d82f7Spl CT_SCRUB_NOFIX, "CT_SCRUB_NOFIX", \
7754830d82f7Spl CT_SCRUB2_NOFIX, "CT_SCRUB2_NOFIX", \
7755830d82f7Spl CT_FLUSH, "CT_FLUSH", \
7756830d82f7Spl CT_REBUILD, "CT_REBUILD", \
7757830d82f7Spl CT_FLUSH_CONTAINER, "CT_FLUSH_CONTAINER", \
7758830d82f7Spl CT_RESTART, "CT_RESTART", \
7759830d82f7Spl CT_GET_CONFIG_STATUS, "CT_GET_CONFIG_STATUS", \
7760830d82f7Spl CT_TRACE_FLAG, "CT_TRACE_FLAG", \
7761830d82f7Spl CT_RESTART_MORPH, "CT_RESTART_MORPH", \
7762830d82f7Spl CT_GET_TRACE_INFO, "CT_GET_TRACE_INFO", \
7763830d82f7Spl CT_GET_TRACE_ITEM, "CT_GET_TRACE_ITEM", \
7764830d82f7Spl CT_COMMIT_CONFIG, "CT_COMMIT_CONFIG", \
7765830d82f7Spl CT_CONTAINER_EXISTS, "CT_CONTAINER_EXISTS", \
7766830d82f7Spl CT_GET_SLICE_FROM_DEVT, "CT_GET_SLICE_FROM_DEVT", \
7767830d82f7Spl CT_OPEN_READ_WRITE, "CT_OPEN_READ_WRITE", \
7768830d82f7Spl CT_WRITE_MEMORY_BLOCK, "CT_WRITE_MEMORY_BLOCK", \
7769830d82f7Spl CT_GET_CACHE_PARAMS, "CT_GET_CACHE_PARAMS", \
7770830d82f7Spl CT_CRAZY_CACHE, "CT_CRAZY_CACHE", \
7771830d82f7Spl CT_GET_PROFILE_STRUCT, "CT_GET_PROFILE_STRUCT", \
7772830d82f7Spl CT_SET_IO_TRACE_FLAG, "CT_SET_IO_TRACE_FLAG", \
7773830d82f7Spl CT_GET_IO_TRACE_STRUCT, "CT_GET_IO_TRACE_STRUCT", \
7774830d82f7Spl CT_CID_TO_64BITS_UID, "CT_CID_TO_64BITS_UID", \
7775830d82f7Spl CT_64BITS_UID_TO_CID, "CT_64BITS_UID_TO_CID", \
7776830d82f7Spl CT_PAR_TO_64BITS_UID, "CT_PAR_TO_64BITS_UID", \
7777830d82f7Spl CT_CID_TO_32BITS_UID, "CT_CID_TO_32BITS_UID", \
7778830d82f7Spl CT_32BITS_UID_TO_CID, "CT_32BITS_UID_TO_CID", \
7779830d82f7Spl CT_PAR_TO_32BITS_UID, "CT_PAR_TO_32BITS_UID", \
7780830d82f7Spl CT_SET_FAILOVER_OPTION, "CT_SET_FAILOVER_OPTION", \
7781830d82f7Spl CT_GET_FAILOVER_OPTION, "CT_GET_FAILOVER_OPTION", \
7782830d82f7Spl CT_STRIPE_ADD2, "CT_STRIPE_ADD2", \
7783830d82f7Spl CT_CREATE_VOLUME_SET, "CT_CREATE_VOLUME_SET", \
7784830d82f7Spl CT_CREATE_STRIPE_SET, "CT_CREATE_STRIPE_SET", \
7785830d82f7Spl CT_VERIFY_CONTAINER, "CT_VERIFY_CONTAINER", \
7786830d82f7Spl CT_IS_CONTAINER_DEAD, "CT_IS_CONTAINER_DEAD", \
7787830d82f7Spl CT_GET_CONTAINER_OPTION, "CT_GET_CONTAINER_OPTION", \
7788830d82f7Spl CT_GET_SNAPSHOT_UNUSED_STRUCT, "CT_GET_SNAPSHOT_UNUSED_STRUCT", \
7789830d82f7Spl CT_CLEAR_SNAPSHOT_UNUSED_STRUCT, "CT_CLEAR_SNAPSHOT_UNUSED_STRUCT", \
7790830d82f7Spl CT_GET_CONTAINER_INFO, "CT_GET_CONTAINER_INFO", \
7791830d82f7Spl CT_CREATE_CONTAINER, "CT_CREATE_CONTAINER", \
7792830d82f7Spl CT_CHANGE_CREATIONINFO, "CT_CHANGE_CREATIONINFO", \
7793830d82f7Spl CT_CHECK_CONFLICT_UID, "CT_CHECK_CONFLICT_UID", \
7794830d82f7Spl CT_CONTAINER_UID_CHECK, "CT_CONTAINER_UID_CHECK", \
7795830d82f7Spl CT_IS_CONTAINER_MEATADATA_STANDARD, \
7796c9487164Spl "CT_IS_CONTAINER_MEATADATA_STANDARD", \
7797830d82f7Spl CT_IS_SLICE_METADATA_STANDARD, "CT_IS_SLICE_METADATA_STANDARD", \
7798830d82f7Spl CT_GET_IMPORT_COUNT, "CT_GET_IMPORT_COUNT", \
7799830d82f7Spl CT_CANCEL_ALL_IMPORTS, "CT_CANCEL_ALL_IMPORTS", \
7800830d82f7Spl CT_GET_IMPORT_INFO, "CT_GET_IMPORT_INFO", \
7801830d82f7Spl CT_IMPORT_ARRAY, "CT_IMPORT_ARRAY", \
7802830d82f7Spl CT_GET_LOG_SIZE, "CT_GET_LOG_SIZE", \
7803830d82f7Spl CT_ALARM_GET_STATE, "CT_ALARM_GET_STATE", \
7804830d82f7Spl CT_ALARM_SET_STATE, "CT_ALARM_SET_STATE", \
7805830d82f7Spl CT_ALARM_ON_OFF, "CT_ALARM_ON_OFF", \
7806830d82f7Spl CT_GET_EE_OEM_ID, "CT_GET_EE_OEM_ID", \
7807830d82f7Spl CT_GET_PPI_HEADERS, "CT_GET_PPI_HEADERS", \
7808830d82f7Spl CT_GET_PPI_DATA, "CT_GET_PPI_DATA", \
7809830d82f7Spl CT_GET_PPI_ENTRIES, "CT_GET_PPI_ENTRIES", \
7810830d82f7Spl CT_DELETE_PPI_BUNDLE, "CT_DELETE_PPI_BUNDLE", \
7811830d82f7Spl CT_GET_PARTITION_TABLE_2, "CT_GET_PARTITION_TABLE_2", \
7812830d82f7Spl CT_GET_PARTITION_INFO_2, "CT_GET_PARTITION_INFO_2", \
7813830d82f7Spl CT_GET_DISK_PARTITIONS_2, "CT_GET_DISK_PARTITIONS_2", \
7814830d82f7Spl CT_QUIESCE_ADAPTER, "CT_QUIESCE_ADAPTER", \
7815830d82f7Spl CT_CLEAR_PPI_TABLE, "CT_CLEAR_PPI_TABLE"
7816830d82f7Spl
7817830d82f7Spl #define AAC_CL_SUBCMD_KEY_STRINGS \
7818830d82f7Spl CL_NULL, "CL_NULL", \
7819830d82f7Spl DS_INIT, "DS_INIT", \
7820830d82f7Spl DS_RESCAN, "DS_RESCAN", \
7821830d82f7Spl DS_CREATE, "DS_CREATE", \
7822830d82f7Spl DS_DELETE, "DS_DELETE", \
7823830d82f7Spl DS_ADD_DISK, "DS_ADD_DISK", \
7824830d82f7Spl DS_REMOVE_DISK, "DS_REMOVE_DISK", \
7825830d82f7Spl DS_MOVE_DISK, "DS_MOVE_DISK", \
7826830d82f7Spl DS_TAKE_OWNERSHIP, "DS_TAKE_OWNERSHIP", \
7827830d82f7Spl DS_RELEASE_OWNERSHIP, "DS_RELEASE_OWNERSHIP", \
7828830d82f7Spl DS_FORCE_OWNERSHIP, "DS_FORCE_OWNERSHIP", \
7829830d82f7Spl DS_GET_DISK_SET_PARAM, "DS_GET_DISK_SET_PARAM", \
7830830d82f7Spl DS_GET_DRIVE_PARAM, "DS_GET_DRIVE_PARAM", \
7831830d82f7Spl DS_GET_SLICE_PARAM, "DS_GET_SLICE_PARAM", \
7832830d82f7Spl DS_GET_DISK_SETS, "DS_GET_DISK_SETS", \
7833830d82f7Spl DS_GET_DRIVES, "DS_GET_DRIVES", \
7834830d82f7Spl DS_SET_DISK_SET_PARAM, "DS_SET_DISK_SET_PARAM", \
7835830d82f7Spl DS_ONLINE, "DS_ONLINE", \
7836830d82f7Spl DS_OFFLINE, "DS_OFFLINE", \
7837830d82f7Spl DS_ONLINE_CONTAINERS, "DS_ONLINE_CONTAINERS", \
7838830d82f7Spl DS_FSAPRINT, "DS_FSAPRINT", \
7839830d82f7Spl CL_CFG_SET_HOST_IDS, "CL_CFG_SET_HOST_IDS", \
7840830d82f7Spl CL_CFG_SET_PARTNER_HOST_IDS, "CL_CFG_SET_PARTNER_HOST_IDS", \
7841830d82f7Spl CL_CFG_GET_CLUSTER_CONFIG, "CL_CFG_GET_CLUSTER_CONFIG", \
7842830d82f7Spl CC_CLI_CLEAR_MESSAGE_BUFFER, "CC_CLI_CLEAR_MESSAGE_BUFFER", \
7843830d82f7Spl CC_SRV_CLEAR_MESSAGE_BUFFER, "CC_SRV_CLEAR_MESSAGE_BUFFER", \
7844830d82f7Spl CC_CLI_SHOW_MESSAGE_BUFFER, "CC_CLI_SHOW_MESSAGE_BUFFER", \
7845830d82f7Spl CC_SRV_SHOW_MESSAGE_BUFFER, "CC_SRV_SHOW_MESSAGE_BUFFER", \
7846830d82f7Spl CC_CLI_SEND_MESSAGE, "CC_CLI_SEND_MESSAGE", \
7847830d82f7Spl CC_SRV_SEND_MESSAGE, "CC_SRV_SEND_MESSAGE", \
7848830d82f7Spl CC_CLI_GET_MESSAGE, "CC_CLI_GET_MESSAGE", \
7849830d82f7Spl CC_SRV_GET_MESSAGE, "CC_SRV_GET_MESSAGE", \
7850830d82f7Spl CC_SEND_TEST_MESSAGE, "CC_SEND_TEST_MESSAGE", \
7851830d82f7Spl CC_GET_BUSINFO, "CC_GET_BUSINFO", \
7852830d82f7Spl CC_GET_PORTINFO, "CC_GET_PORTINFO", \
7853830d82f7Spl CC_GET_NAMEINFO, "CC_GET_NAMEINFO", \
7854830d82f7Spl CC_GET_CONFIGINFO, "CC_GET_CONFIGINFO", \
7855830d82f7Spl CQ_QUORUM_OP, "CQ_QUORUM_OP"
7856830d82f7Spl
7857830d82f7Spl #define AAC_AIF_SUBCMD_KEY_STRINGS \
7858830d82f7Spl AifCmdEventNotify, "AifCmdEventNotify", \
7859830d82f7Spl AifCmdJobProgress, "AifCmdJobProgress", \
7860830d82f7Spl AifCmdAPIReport, "AifCmdAPIReport", \
7861830d82f7Spl AifCmdDriverNotify, "AifCmdDriverNotify", \
7862830d82f7Spl AifReqJobList, "AifReqJobList", \
7863830d82f7Spl AifReqJobsForCtr, "AifReqJobsForCtr", \
7864830d82f7Spl AifReqJobsForScsi, "AifReqJobsForScsi", \
7865830d82f7Spl AifReqJobReport, "AifReqJobReport", \
7866830d82f7Spl AifReqTerminateJob, "AifReqTerminateJob", \
7867830d82f7Spl AifReqSuspendJob, "AifReqSuspendJob", \
7868830d82f7Spl AifReqResumeJob, "AifReqResumeJob", \
7869830d82f7Spl AifReqSendAPIReport, "AifReqSendAPIReport", \
7870830d82f7Spl AifReqAPIJobStart, "AifReqAPIJobStart", \
7871830d82f7Spl AifReqAPIJobUpdate, "AifReqAPIJobUpdate", \
7872830d82f7Spl AifReqAPIJobFinish, "AifReqAPIJobFinish"
7873830d82f7Spl
7874830d82f7Spl #define AAC_IOCTL_SUBCMD_KEY_STRINGS \
7875830d82f7Spl Reserved_IOCTL, "Reserved_IOCTL", \
7876830d82f7Spl GetDeviceHandle, "GetDeviceHandle", \
7877830d82f7Spl BusTargetLun_to_DeviceHandle, "BusTargetLun_to_DeviceHandle", \
7878830d82f7Spl DeviceHandle_to_BusTargetLun, "DeviceHandle_to_BusTargetLun", \
7879830d82f7Spl RescanBus, "RescanBus", \
7880830d82f7Spl GetDeviceProbeInfo, "GetDeviceProbeInfo", \
7881830d82f7Spl GetDeviceCapacity, "GetDeviceCapacity", \
7882830d82f7Spl GetContainerProbeInfo, "GetContainerProbeInfo", \
7883830d82f7Spl GetRequestedMemorySize, "GetRequestedMemorySize", \
7884830d82f7Spl GetBusInfo, "GetBusInfo", \
7885830d82f7Spl GetVendorSpecific, "GetVendorSpecific", \
7886830d82f7Spl EnhancedGetDeviceProbeInfo, "EnhancedGetDeviceProbeInfo", \
7887830d82f7Spl EnhancedGetBusInfo, "EnhancedGetBusInfo", \
7888830d82f7Spl SetupExtendedCounters, "SetupExtendedCounters", \
7889830d82f7Spl GetPerformanceCounters, "GetPerformanceCounters", \
7890830d82f7Spl ResetPerformanceCounters, "ResetPerformanceCounters", \
7891830d82f7Spl ReadModePage, "ReadModePage", \
7892830d82f7Spl WriteModePage, "WriteModePage", \
7893830d82f7Spl ReadDriveParameter, "ReadDriveParameter", \
7894830d82f7Spl WriteDriveParameter, "WriteDriveParameter", \
7895830d82f7Spl ResetAdapter, "ResetAdapter", \
7896830d82f7Spl ResetBus, "ResetBus", \
7897830d82f7Spl ResetBusDevice, "ResetBusDevice", \
7898830d82f7Spl ExecuteSrb, "ExecuteSrb", \
7899830d82f7Spl Create_IO_Task, "Create_IO_Task", \
7900830d82f7Spl Delete_IO_Task, "Delete_IO_Task", \
7901830d82f7Spl Get_IO_Task_Info, "Get_IO_Task_Info", \
7902830d82f7Spl Check_Task_Progress, "Check_Task_Progress", \
7903830d82f7Spl InjectError, "InjectError", \
7904830d82f7Spl GetDeviceDefectCounts, "GetDeviceDefectCounts", \
7905830d82f7Spl GetDeviceDefectInfo, "GetDeviceDefectInfo", \
7906830d82f7Spl GetDeviceStatus, "GetDeviceStatus", \
7907830d82f7Spl ClearDeviceStatus, "ClearDeviceStatus", \
7908830d82f7Spl DiskSpinControl, "DiskSpinControl", \
7909830d82f7Spl DiskSmartControl, "DiskSmartControl", \
7910830d82f7Spl WriteSame, "WriteSame", \
7911830d82f7Spl ReadWriteLong, "ReadWriteLong", \
7912830d82f7Spl FormatUnit, "FormatUnit", \
7913830d82f7Spl TargetDeviceControl, "TargetDeviceControl", \
7914830d82f7Spl TargetChannelControl, "TargetChannelControl", \
7915830d82f7Spl FlashNewCode, "FlashNewCode", \
7916830d82f7Spl DiskCheck, "DiskCheck", \
7917830d82f7Spl RequestSense, "RequestSense", \
7918830d82f7Spl DiskPERControl, "DiskPERControl", \
7919830d82f7Spl Read10, "Read10", \
7920830d82f7Spl Write10, "Write10"
7921830d82f7Spl
7922830d82f7Spl #define AAC_AIFEN_KEY_STRINGS \
7923830d82f7Spl AifEnGeneric, "Generic", \
7924830d82f7Spl AifEnTaskComplete, "TaskComplete", \
7925830d82f7Spl AifEnConfigChange, "Config change", \
7926830d82f7Spl AifEnContainerChange, "Container change", \
7927830d82f7Spl AifEnDeviceFailure, "device failed", \
7928830d82f7Spl AifEnMirrorFailover, "Mirror failover", \
7929830d82f7Spl AifEnContainerEvent, "container event", \
7930830d82f7Spl AifEnFileSystemChange, "File system changed", \
7931830d82f7Spl AifEnConfigPause, "Container pause event", \
7932830d82f7Spl AifEnConfigResume, "Container resume event", \
7933830d82f7Spl AifEnFailoverChange, "Failover space assignment changed", \
7934830d82f7Spl AifEnRAID5RebuildDone, "RAID5 rebuild finished", \
7935830d82f7Spl AifEnEnclosureManagement, "Enclosure management event", \
7936830d82f7Spl AifEnBatteryEvent, "battery event", \
7937830d82f7Spl AifEnAddContainer, "Add container", \
7938830d82f7Spl AifEnDeleteContainer, "Delete container", \
7939830d82f7Spl AifEnSMARTEvent, "SMART Event", \
7940830d82f7Spl AifEnBatteryNeedsRecond, "battery needs reconditioning", \
7941830d82f7Spl AifEnClusterEvent, "cluster event", \
7942830d82f7Spl AifEnDiskSetEvent, "disk set event occured", \
7943830d82f7Spl AifDenMorphComplete, "morph operation completed", \
7944830d82f7Spl AifDenVolumeExtendComplete, "VolumeExtendComplete"
7945830d82f7Spl
7946830d82f7Spl struct aac_key_strings {
7947830d82f7Spl int key;
7948830d82f7Spl char *message;
7949830d82f7Spl };
7950830d82f7Spl
7951830d82f7Spl extern struct scsi_key_strings scsi_cmds[];
7952830d82f7Spl
7953830d82f7Spl static struct aac_key_strings aac_fib_cmds[] = {
7954830d82f7Spl AAC_FIB_CMD_KEY_STRINGS,
7955830d82f7Spl -1, NULL
7956830d82f7Spl };
7957830d82f7Spl
7958830d82f7Spl static struct aac_key_strings aac_ctvm_subcmds[] = {
7959830d82f7Spl AAC_CTVM_SUBCMD_KEY_STRINGS,
7960830d82f7Spl -1, NULL
7961830d82f7Spl };
7962830d82f7Spl
7963830d82f7Spl static struct aac_key_strings aac_ct_subcmds[] = {
7964830d82f7Spl AAC_CT_SUBCMD_KEY_STRINGS,
7965830d82f7Spl -1, NULL
7966830d82f7Spl };
7967830d82f7Spl
7968830d82f7Spl static struct aac_key_strings aac_cl_subcmds[] = {
7969830d82f7Spl AAC_CL_SUBCMD_KEY_STRINGS,
7970830d82f7Spl -1, NULL
7971830d82f7Spl };
7972830d82f7Spl
7973830d82f7Spl static struct aac_key_strings aac_aif_subcmds[] = {
7974830d82f7Spl AAC_AIF_SUBCMD_KEY_STRINGS,
7975830d82f7Spl -1, NULL
7976830d82f7Spl };
7977830d82f7Spl
7978830d82f7Spl static struct aac_key_strings aac_ioctl_subcmds[] = {
7979830d82f7Spl AAC_IOCTL_SUBCMD_KEY_STRINGS,
7980830d82f7Spl -1, NULL
7981830d82f7Spl };
7982830d82f7Spl
7983830d82f7Spl static struct aac_key_strings aac_aifens[] = {
7984830d82f7Spl AAC_AIFEN_KEY_STRINGS,
7985830d82f7Spl -1, NULL
79867c478bd9Sstevel@tonic-gate };
79877c478bd9Sstevel@tonic-gate
79881dd0a2dbSpl /*
79891dd0a2dbSpl * The following function comes from Adaptec:
79901dd0a2dbSpl *
79911dd0a2dbSpl * Get the firmware print buffer parameters from the firmware,
79921dd0a2dbSpl * if the command was successful map in the address.
79931dd0a2dbSpl */
79941dd0a2dbSpl static int
aac_get_fw_debug_buffer(struct aac_softstate * softs)79951dd0a2dbSpl aac_get_fw_debug_buffer(struct aac_softstate *softs)
79961dd0a2dbSpl {
79971dd0a2dbSpl if (aac_sync_mbcommand(softs, AAC_MONKER_GETDRVPROP,
79981dd0a2dbSpl 0, 0, 0, 0, NULL) == AACOK) {
79991dd0a2dbSpl uint32_t mondrv_buf_paddrl = AAC_MAILBOX_GET(softs, 1);
80001dd0a2dbSpl uint32_t mondrv_buf_paddrh = AAC_MAILBOX_GET(softs, 2);
80011dd0a2dbSpl uint32_t mondrv_buf_size = AAC_MAILBOX_GET(softs, 3);
80021dd0a2dbSpl uint32_t mondrv_hdr_size = AAC_MAILBOX_GET(softs, 4);
80031dd0a2dbSpl
80041dd0a2dbSpl if (mondrv_buf_size) {
80051dd0a2dbSpl uint32_t offset = mondrv_buf_paddrl - \
80061dd0a2dbSpl softs->pci_mem_base_paddr;
80071dd0a2dbSpl
80081dd0a2dbSpl /*
80091dd0a2dbSpl * See if the address is already mapped in, and
80101dd0a2dbSpl * if so set it up from the base address
80111dd0a2dbSpl */
80121dd0a2dbSpl if ((mondrv_buf_paddrh == 0) &&
80131dd0a2dbSpl (offset + mondrv_buf_size < softs->map_size)) {
8014942c5e3cSpl mutex_enter(&aac_prt_mutex);
80151dd0a2dbSpl softs->debug_buf_offset = offset;
80161dd0a2dbSpl softs->debug_header_size = mondrv_hdr_size;
80171dd0a2dbSpl softs->debug_buf_size = mondrv_buf_size;
80181dd0a2dbSpl softs->debug_fw_flags = 0;
8019942c5e3cSpl softs->debug_flags &= ~AACDB_FLAGS_FW_PRINT;
8020942c5e3cSpl mutex_exit(&aac_prt_mutex);
80211dd0a2dbSpl
80221dd0a2dbSpl return (AACOK);
80231dd0a2dbSpl }
80241dd0a2dbSpl }
80251dd0a2dbSpl }
80261dd0a2dbSpl return (AACERR);
80271dd0a2dbSpl }
80281dd0a2dbSpl
80291dd0a2dbSpl int
aac_dbflag_on(struct aac_softstate * softs,int flag)80301dd0a2dbSpl aac_dbflag_on(struct aac_softstate *softs, int flag)
80311dd0a2dbSpl {
80321dd0a2dbSpl int debug_flags = softs ? softs->debug_flags : aac_debug_flags;
80331dd0a2dbSpl
80341dd0a2dbSpl return ((debug_flags & (AACDB_FLAGS_FW_PRINT | \
80351dd0a2dbSpl AACDB_FLAGS_KERNEL_PRINT)) && (debug_flags & flag));
80361dd0a2dbSpl }
80371dd0a2dbSpl
8038942c5e3cSpl static void
aac_cmn_err(struct aac_softstate * softs,uint_t lev,char sl,int noheader)8039942c5e3cSpl aac_cmn_err(struct aac_softstate *softs, uint_t lev, char sl, int noheader)
8040942c5e3cSpl {
8041942c5e3cSpl if (noheader) {
8042942c5e3cSpl if (sl) {
8043942c5e3cSpl aac_fmt[0] = sl;
8044942c5e3cSpl cmn_err(lev, aac_fmt, aac_prt_buf);
8045942c5e3cSpl } else {
8046942c5e3cSpl cmn_err(lev, &aac_fmt[1], aac_prt_buf);
8047942c5e3cSpl }
8048942c5e3cSpl } else {
8049942c5e3cSpl if (sl) {
8050942c5e3cSpl aac_fmt_header[0] = sl;
8051942c5e3cSpl cmn_err(lev, aac_fmt_header,
8052942c5e3cSpl softs->vendor_name, softs->instance,
8053942c5e3cSpl aac_prt_buf);
8054942c5e3cSpl } else {
8055942c5e3cSpl cmn_err(lev, &aac_fmt_header[1],
8056942c5e3cSpl softs->vendor_name, softs->instance,
8057942c5e3cSpl aac_prt_buf);
8058942c5e3cSpl }
8059942c5e3cSpl }
8060942c5e3cSpl }
8061942c5e3cSpl
80621dd0a2dbSpl /*
80631dd0a2dbSpl * The following function comes from Adaptec:
80641dd0a2dbSpl *
80651dd0a2dbSpl * Format and print out the data passed in to UART or console
80661dd0a2dbSpl * as specified by debug flags.
80671dd0a2dbSpl */
80681dd0a2dbSpl void
aac_printf(struct aac_softstate * softs,uint_t lev,const char * fmt,...)80691dd0a2dbSpl aac_printf(struct aac_softstate *softs, uint_t lev, const char *fmt, ...)
80701dd0a2dbSpl {
80711dd0a2dbSpl va_list args;
8072942c5e3cSpl char sl; /* system log character */
80731dd0a2dbSpl
80741dd0a2dbSpl mutex_enter(&aac_prt_mutex);
8075942c5e3cSpl /* Set up parameters and call sprintf function to format the data */
8076942c5e3cSpl if (strchr("^!?", fmt[0]) == NULL) {
8077942c5e3cSpl sl = 0;
8078942c5e3cSpl } else {
8079942c5e3cSpl sl = fmt[0];
8080942c5e3cSpl fmt++;
8081942c5e3cSpl }
80821dd0a2dbSpl va_start(args, fmt);
80831dd0a2dbSpl (void) vsprintf(aac_prt_buf, fmt, args);
80841dd0a2dbSpl va_end(args);
80851dd0a2dbSpl
8086942c5e3cSpl /* Make sure the softs structure has been passed in for this section */
8087942c5e3cSpl if (softs) {
8088942c5e3cSpl if ((softs->debug_flags & AACDB_FLAGS_FW_PRINT) &&
8089942c5e3cSpl /* If we are set up for a Firmware print */
8090942c5e3cSpl (softs->debug_buf_size)) {
8091942c5e3cSpl uint32_t count, i;
80921dd0a2dbSpl
8093942c5e3cSpl /* Make sure the string size is within boundaries */
8094942c5e3cSpl count = strlen(aac_prt_buf);
8095942c5e3cSpl if (count > softs->debug_buf_size)
8096942c5e3cSpl count = (uint16_t)softs->debug_buf_size;
80971dd0a2dbSpl
8098942c5e3cSpl /*
8099942c5e3cSpl * Wait for no more than AAC_PRINT_TIMEOUT for the
8100942c5e3cSpl * previous message length to clear (the handshake).
8101942c5e3cSpl */
8102942c5e3cSpl for (i = 0; i < AAC_PRINT_TIMEOUT; i++) {
8103942c5e3cSpl if (!PCI_MEM_GET32(softs,
8104942c5e3cSpl softs->debug_buf_offset + \
8105942c5e3cSpl AAC_FW_DBG_STRLEN_OFFSET))
8106942c5e3cSpl break;
81071dd0a2dbSpl
8108942c5e3cSpl drv_usecwait(1000);
8109942c5e3cSpl }
8110942c5e3cSpl
8111942c5e3cSpl /*
8112942c5e3cSpl * If the length is clear, copy over the message, the
8113942c5e3cSpl * flags, and the length. Make sure the length is the
8114942c5e3cSpl * last because that is the signal for the Firmware to
8115942c5e3cSpl * pick it up.
8116942c5e3cSpl */
8117942c5e3cSpl if (!PCI_MEM_GET32(softs, softs->debug_buf_offset + \
8118942c5e3cSpl AAC_FW_DBG_STRLEN_OFFSET)) {
8119942c5e3cSpl PCI_MEM_REP_PUT8(softs,
8120942c5e3cSpl softs->debug_buf_offset + \
8121942c5e3cSpl softs->debug_header_size,
8122942c5e3cSpl aac_prt_buf, count);
8123942c5e3cSpl PCI_MEM_PUT32(softs,
8124942c5e3cSpl softs->debug_buf_offset + \
8125942c5e3cSpl AAC_FW_DBG_FLAGS_OFFSET,
8126942c5e3cSpl softs->debug_fw_flags);
8127942c5e3cSpl PCI_MEM_PUT32(softs,
8128942c5e3cSpl softs->debug_buf_offset + \
8129942c5e3cSpl AAC_FW_DBG_STRLEN_OFFSET, count);
8130942c5e3cSpl } else {
8131942c5e3cSpl cmn_err(CE_WARN, "UART output fail");
8132942c5e3cSpl softs->debug_flags &= ~AACDB_FLAGS_FW_PRINT;
8133942c5e3cSpl }
81341dd0a2dbSpl }
81351dd0a2dbSpl
81361dd0a2dbSpl /*
8137942c5e3cSpl * If the Kernel Debug Print flag is set, send it off
8138942c5e3cSpl * to the Kernel Debugger
81391dd0a2dbSpl */
8140942c5e3cSpl if (softs->debug_flags & AACDB_FLAGS_KERNEL_PRINT)
8141942c5e3cSpl aac_cmn_err(softs, lev, sl,
8142942c5e3cSpl (softs->debug_flags & AACDB_FLAGS_NO_HEADERS));
8143942c5e3cSpl } else {
8144942c5e3cSpl /* Driver not initialized yet, no firmware or header output */
8145942c5e3cSpl if (aac_debug_flags & AACDB_FLAGS_KERNEL_PRINT)
8146942c5e3cSpl aac_cmn_err(softs, lev, sl, 1);
81471dd0a2dbSpl }
81481dd0a2dbSpl mutex_exit(&aac_prt_mutex);
81491dd0a2dbSpl }
81501dd0a2dbSpl
8151830d82f7Spl /*
8152830d82f7Spl * Translate command number to description string
8153830d82f7Spl */
81547c478bd9Sstevel@tonic-gate static char *
aac_cmd_name(int cmd,struct aac_key_strings * cmdlist)8155830d82f7Spl aac_cmd_name(int cmd, struct aac_key_strings *cmdlist)
8156830d82f7Spl {
8157830d82f7Spl int i;
8158830d82f7Spl
8159830d82f7Spl for (i = 0; cmdlist[i].key != -1; i++) {
8160830d82f7Spl if (cmd == cmdlist[i].key)
8161830d82f7Spl return (cmdlist[i].message);
8162830d82f7Spl }
8163830d82f7Spl return (NULL);
8164830d82f7Spl }
8165830d82f7Spl
8166830d82f7Spl static void
aac_print_scmd(struct aac_softstate * softs,struct aac_cmd * acp)81671dd0a2dbSpl aac_print_scmd(struct aac_softstate *softs, struct aac_cmd *acp)
81687c478bd9Sstevel@tonic-gate {
81691dd0a2dbSpl struct scsi_pkt *pkt = acp->pkt;
8170830d82f7Spl struct scsi_address *ap = &pkt->pkt_address;
817158bc78c7SXin Chen int is_pd = 0;
81721dd0a2dbSpl int ctl = ddi_get_instance(softs->devinfo_p);
8173830d82f7Spl int tgt = ap->a_target;
8174830d82f7Spl int lun = ap->a_lun;
8175a74f7440Spl union scsi_cdb *cdbp = (void *)pkt->pkt_cdbp;
8176830d82f7Spl uchar_t cmd = cdbp->scc_cmd;
8177830d82f7Spl char *desc;
8178830d82f7Spl
817958bc78c7SXin Chen if (tgt >= AAC_MAX_LD) {
818058bc78c7SXin Chen is_pd = 1;
818158bc78c7SXin Chen ctl = ((struct aac_nondasd *)acp->dvp)->bus;
818258bc78c7SXin Chen tgt = ((struct aac_nondasd *)acp->dvp)->tid;
818358bc78c7SXin Chen lun = 0;
818458bc78c7SXin Chen }
818558bc78c7SXin Chen
8186830d82f7Spl if ((desc = aac_cmd_name(cmd,
8187c9487164Spl (struct aac_key_strings *)scsi_cmds)) == NULL) {
81881dd0a2dbSpl aac_printf(softs, CE_NOTE,
818958bc78c7SXin Chen "SCMD> Unknown(0x%2x) --> c%dt%dL%d %s",
819058bc78c7SXin Chen cmd, ctl, tgt, lun, is_pd ? "(pd)" : "");
8191830d82f7Spl return;
8192830d82f7Spl }
8193830d82f7Spl
81947c478bd9Sstevel@tonic-gate switch (cmd) {
8195830d82f7Spl case SCMD_READ:
8196830d82f7Spl case SCMD_WRITE:
81971dd0a2dbSpl aac_printf(softs, CE_NOTE,
819858bc78c7SXin Chen "SCMD> %s 0x%x[%d] %s --> c%dt%dL%d %s",
81991dd0a2dbSpl desc, GETG0ADDR(cdbp), GETG0COUNT(cdbp),
82001dd0a2dbSpl (acp->flags & AAC_CMD_NO_INTR) ? "poll" : "intr",
820158bc78c7SXin Chen ctl, tgt, lun, is_pd ? "(pd)" : "");
8202830d82f7Spl break;
8203830d82f7Spl case SCMD_READ_G1:
8204830d82f7Spl case SCMD_WRITE_G1:
82051dd0a2dbSpl aac_printf(softs, CE_NOTE,
820658bc78c7SXin Chen "SCMD> %s 0x%x[%d] %s --> c%dt%dL%d %s",
82071dd0a2dbSpl desc, GETG1ADDR(cdbp), GETG1COUNT(cdbp),
82081dd0a2dbSpl (acp->flags & AAC_CMD_NO_INTR) ? "poll" : "intr",
820958bc78c7SXin Chen ctl, tgt, lun, is_pd ? "(pd)" : "");
8210830d82f7Spl break;
8211830d82f7Spl case SCMD_READ_G4:
8212830d82f7Spl case SCMD_WRITE_G4:
82131dd0a2dbSpl aac_printf(softs, CE_NOTE,
821458bc78c7SXin Chen "SCMD> %s 0x%x.%08x[%d] %s --> c%dt%dL%d %s",
82151dd0a2dbSpl desc, GETG4ADDR(cdbp), GETG4ADDRTL(cdbp),
82161dd0a2dbSpl GETG4COUNT(cdbp),
82171dd0a2dbSpl (acp->flags & AAC_CMD_NO_INTR) ? "poll" : "intr",
821858bc78c7SXin Chen ctl, tgt, lun, is_pd ? "(pd)" : "");
821958bc78c7SXin Chen break;
822058bc78c7SXin Chen case SCMD_READ_G5:
822158bc78c7SXin Chen case SCMD_WRITE_G5:
822258bc78c7SXin Chen aac_printf(softs, CE_NOTE,
822358bc78c7SXin Chen "SCMD> %s 0x%x[%d] %s --> c%dt%dL%d %s",
822458bc78c7SXin Chen desc, GETG5ADDR(cdbp), GETG5COUNT(cdbp),
822558bc78c7SXin Chen (acp->flags & AAC_CMD_NO_INTR) ? "poll" : "intr",
822658bc78c7SXin Chen ctl, tgt, lun, is_pd ? "(pd)" : "");
8227830d82f7Spl break;
8228830d82f7Spl default:
822958bc78c7SXin Chen aac_printf(softs, CE_NOTE, "SCMD> %s --> c%dt%dL%d %s",
823058bc78c7SXin Chen desc, ctl, tgt, lun, is_pd ? "(pd)" : "");
8231830d82f7Spl }
8232830d82f7Spl }
8233830d82f7Spl
8234830d82f7Spl void
aac_print_fib(struct aac_softstate * softs,struct aac_slot * slotp)823558bc78c7SXin Chen aac_print_fib(struct aac_softstate *softs, struct aac_slot *slotp)
8236830d82f7Spl {
823758bc78c7SXin Chen struct aac_cmd *acp = slotp->acp;
823858bc78c7SXin Chen struct aac_fib *fibp = slotp->fibp;
823958bc78c7SXin Chen ddi_acc_handle_t acc = slotp->fib_acc_handle;
8240942c5e3cSpl uint16_t fib_size;
824158bc78c7SXin Chen uint32_t fib_cmd, sub_cmd;
8242830d82f7Spl char *cmdstr, *subcmdstr;
824358bc78c7SXin Chen char *caller;
824458bc78c7SXin Chen int i;
824558bc78c7SXin Chen
824658bc78c7SXin Chen if (acp) {
824758bc78c7SXin Chen if (!(softs->debug_fib_flags & acp->fib_flags))
824858bc78c7SXin Chen return;
824958bc78c7SXin Chen if (acp->fib_flags & AACDB_FLAGS_FIB_SCMD)
825058bc78c7SXin Chen caller = "SCMD";
825158bc78c7SXin Chen else if (acp->fib_flags & AACDB_FLAGS_FIB_IOCTL)
825258bc78c7SXin Chen caller = "IOCTL";
825358bc78c7SXin Chen else if (acp->fib_flags & AACDB_FLAGS_FIB_SRB)
825458bc78c7SXin Chen caller = "SRB";
825558bc78c7SXin Chen else
825658bc78c7SXin Chen return;
825758bc78c7SXin Chen } else {
825858bc78c7SXin Chen if (!(softs->debug_fib_flags & AACDB_FLAGS_FIB_SYNC))
825958bc78c7SXin Chen return;
826058bc78c7SXin Chen caller = "SYNC";
826158bc78c7SXin Chen }
8262830d82f7Spl
826358bc78c7SXin Chen fib_cmd = ddi_get16(acc, &fibp->Header.Command);
8264830d82f7Spl cmdstr = aac_cmd_name(fib_cmd, aac_fib_cmds);
826558bc78c7SXin Chen sub_cmd = (uint32_t)-1;
8266830d82f7Spl subcmdstr = NULL;
8267830d82f7Spl
826858bc78c7SXin Chen /* Print FIB header */
826958bc78c7SXin Chen if (softs->debug_fib_flags & AACDB_FLAGS_FIB_HEADER) {
827058bc78c7SXin Chen aac_printf(softs, CE_NOTE, "FIB> from %s", caller);
827158bc78c7SXin Chen aac_printf(softs, CE_NOTE, " XferState %d",
827258bc78c7SXin Chen ddi_get32(acc, &fibp->Header.XferState));
827358bc78c7SXin Chen aac_printf(softs, CE_NOTE, " Command %d",
827458bc78c7SXin Chen ddi_get16(acc, &fibp->Header.Command));
827558bc78c7SXin Chen aac_printf(softs, CE_NOTE, " StructType %d",
827658bc78c7SXin Chen ddi_get8(acc, &fibp->Header.StructType));
827758bc78c7SXin Chen aac_printf(softs, CE_NOTE, " Flags 0x%x",
827858bc78c7SXin Chen ddi_get8(acc, &fibp->Header.Flags));
827958bc78c7SXin Chen aac_printf(softs, CE_NOTE, " Size %d",
828058bc78c7SXin Chen ddi_get16(acc, &fibp->Header.Size));
828158bc78c7SXin Chen aac_printf(softs, CE_NOTE, " SenderSize %d",
828258bc78c7SXin Chen ddi_get16(acc, &fibp->Header.SenderSize));
828358bc78c7SXin Chen aac_printf(softs, CE_NOTE, " SenderAddr 0x%x",
828458bc78c7SXin Chen ddi_get32(acc, &fibp->Header.SenderFibAddress));
828558bc78c7SXin Chen aac_printf(softs, CE_NOTE, " RcvrAddr 0x%x",
828658bc78c7SXin Chen ddi_get32(acc, &fibp->Header.ReceiverFibAddress));
828758bc78c7SXin Chen aac_printf(softs, CE_NOTE, " SenderData 0x%x",
828858bc78c7SXin Chen ddi_get32(acc, &fibp->Header.SenderData));
828958bc78c7SXin Chen }
829058bc78c7SXin Chen
829158bc78c7SXin Chen /* Print FIB data */
8292830d82f7Spl switch (fib_cmd) {
8293830d82f7Spl case ContainerCommand:
829458bc78c7SXin Chen sub_cmd = ddi_get32(acc,
829558bc78c7SXin Chen (void *)&(((uint32_t *)(void *)&fibp->data[0])[0]));
8296830d82f7Spl subcmdstr = aac_cmd_name(sub_cmd, aac_ctvm_subcmds);
8297830d82f7Spl if (subcmdstr == NULL)
8298830d82f7Spl break;
8299830d82f7Spl
830058bc78c7SXin Chen switch (sub_cmd) {
830158bc78c7SXin Chen case VM_ContainerConfig: {
830258bc78c7SXin Chen struct aac_Container *pContainer =
830358bc78c7SXin Chen (struct aac_Container *)fibp->data;
830458bc78c7SXin Chen
830558bc78c7SXin Chen fib_cmd = sub_cmd;
830658bc78c7SXin Chen cmdstr = subcmdstr;
830758bc78c7SXin Chen sub_cmd = (uint32_t)-1;
830858bc78c7SXin Chen subcmdstr = NULL;
830958bc78c7SXin Chen
831058bc78c7SXin Chen sub_cmd = ddi_get32(acc,
831158bc78c7SXin Chen &pContainer->CTCommand.command);
8312830d82f7Spl subcmdstr = aac_cmd_name(sub_cmd, aac_ct_subcmds);
8313830d82f7Spl if (subcmdstr == NULL)
8314830d82f7Spl break;
83151dd0a2dbSpl aac_printf(softs, CE_NOTE, "FIB> %s (0x%x, 0x%x, 0x%x)",
8316c9487164Spl subcmdstr,
831758bc78c7SXin Chen ddi_get32(acc, &pContainer->CTCommand.param[0]),
831858bc78c7SXin Chen ddi_get32(acc, &pContainer->CTCommand.param[1]),
831958bc78c7SXin Chen ddi_get32(acc, &pContainer->CTCommand.param[2]));
8320830d82f7Spl return;
832158bc78c7SXin Chen }
832258bc78c7SXin Chen
8323830d82f7Spl case VM_Ioctl:
832458bc78c7SXin Chen fib_cmd = sub_cmd;
832558bc78c7SXin Chen cmdstr = subcmdstr;
832658bc78c7SXin Chen sub_cmd = (uint32_t)-1;
832758bc78c7SXin Chen subcmdstr = NULL;
832858bc78c7SXin Chen
832958bc78c7SXin Chen sub_cmd = ddi_get32(acc,
833058bc78c7SXin Chen (void *)&(((uint32_t *)(void *)&fibp->data[0])[4]));
8331830d82f7Spl subcmdstr = aac_cmd_name(sub_cmd, aac_ioctl_subcmds);
8332830d82f7Spl break;
833358bc78c7SXin Chen
833458bc78c7SXin Chen case VM_CtBlockRead:
833558bc78c7SXin Chen case VM_CtBlockWrite: {
833658bc78c7SXin Chen struct aac_blockread *br =
833758bc78c7SXin Chen (struct aac_blockread *)fibp->data;
833858bc78c7SXin Chen struct aac_sg_table *sg = &br->SgMap;
833958bc78c7SXin Chen uint32_t sgcount = ddi_get32(acc, &sg->SgCount);
834058bc78c7SXin Chen
834158bc78c7SXin Chen aac_printf(softs, CE_NOTE,
834258bc78c7SXin Chen "FIB> %s Container %d 0x%x/%d", subcmdstr,
834358bc78c7SXin Chen ddi_get32(acc, &br->ContainerId),
834458bc78c7SXin Chen ddi_get32(acc, &br->BlockNumber),
834558bc78c7SXin Chen ddi_get32(acc, &br->ByteCount));
834658bc78c7SXin Chen for (i = 0; i < sgcount; i++)
834758bc78c7SXin Chen aac_printf(softs, CE_NOTE,
834858bc78c7SXin Chen " %d: 0x%08x/%d", i,
834958bc78c7SXin Chen ddi_get32(acc, &sg->SgEntry[i].SgAddress),
835058bc78c7SXin Chen ddi_get32(acc, &sg->SgEntry[i]. \
835158bc78c7SXin Chen SgByteCount));
835258bc78c7SXin Chen return;
835358bc78c7SXin Chen }
8354830d82f7Spl }
8355830d82f7Spl break;
8356830d82f7Spl
835758bc78c7SXin Chen case ContainerCommand64: {
835858bc78c7SXin Chen struct aac_blockread64 *br =
835958bc78c7SXin Chen (struct aac_blockread64 *)fibp->data;
836058bc78c7SXin Chen struct aac_sg_table64 *sg = &br->SgMap64;
836158bc78c7SXin Chen uint32_t sgcount = ddi_get32(acc, &sg->SgCount);
836258bc78c7SXin Chen uint64_t sgaddr;
836358bc78c7SXin Chen
836458bc78c7SXin Chen sub_cmd = br->Command;
836558bc78c7SXin Chen subcmdstr = NULL;
836658bc78c7SXin Chen if (sub_cmd == VM_CtHostRead64)
836758bc78c7SXin Chen subcmdstr = "VM_CtHostRead64";
836858bc78c7SXin Chen else if (sub_cmd == VM_CtHostWrite64)
836958bc78c7SXin Chen subcmdstr = "VM_CtHostWrite64";
837058bc78c7SXin Chen else
837158bc78c7SXin Chen break;
837258bc78c7SXin Chen
837358bc78c7SXin Chen aac_printf(softs, CE_NOTE,
837458bc78c7SXin Chen "FIB> %s Container %d 0x%x/%d", subcmdstr,
837558bc78c7SXin Chen ddi_get16(acc, &br->ContainerId),
837658bc78c7SXin Chen ddi_get32(acc, &br->BlockNumber),
837758bc78c7SXin Chen ddi_get16(acc, &br->SectorCount));
837858bc78c7SXin Chen for (i = 0; i < sgcount; i++) {
837958bc78c7SXin Chen sgaddr = ddi_get64(acc,
838058bc78c7SXin Chen &sg->SgEntry64[i].SgAddress);
838158bc78c7SXin Chen aac_printf(softs, CE_NOTE,
838258bc78c7SXin Chen " %d: 0x%08x.%08x/%d", i,
838358bc78c7SXin Chen AAC_MS32(sgaddr), AAC_LS32(sgaddr),
838458bc78c7SXin Chen ddi_get32(acc, &sg->SgEntry64[i]. \
838558bc78c7SXin Chen SgByteCount));
838658bc78c7SXin Chen }
838758bc78c7SXin Chen return;
838858bc78c7SXin Chen }
838958bc78c7SXin Chen
839058bc78c7SXin Chen case RawIo: {
839158bc78c7SXin Chen struct aac_raw_io *io = (struct aac_raw_io *)fibp->data;
839258bc78c7SXin Chen struct aac_sg_tableraw *sg = &io->SgMapRaw;
839358bc78c7SXin Chen uint32_t sgcount = ddi_get32(acc, &sg->SgCount);
839458bc78c7SXin Chen uint64_t sgaddr;
839558bc78c7SXin Chen
839658bc78c7SXin Chen aac_printf(softs, CE_NOTE,
839758bc78c7SXin Chen "FIB> RawIo Container %d 0x%llx/%d 0x%x",
839858bc78c7SXin Chen ddi_get16(acc, &io->ContainerId),
839958bc78c7SXin Chen ddi_get64(acc, &io->BlockNumber),
840058bc78c7SXin Chen ddi_get32(acc, &io->ByteCount),
840158bc78c7SXin Chen ddi_get16(acc, &io->Flags));
840258bc78c7SXin Chen for (i = 0; i < sgcount; i++) {
840358bc78c7SXin Chen sgaddr = ddi_get64(acc, &sg->SgEntryRaw[i].SgAddress);
840458bc78c7SXin Chen aac_printf(softs, CE_NOTE, " %d: 0x%08x.%08x/%d", i,
840558bc78c7SXin Chen AAC_MS32(sgaddr), AAC_LS32(sgaddr),
840658bc78c7SXin Chen ddi_get32(acc, &sg->SgEntryRaw[i].SgByteCount));
840758bc78c7SXin Chen }
840858bc78c7SXin Chen return;
840958bc78c7SXin Chen }
841058bc78c7SXin Chen
8411830d82f7Spl case ClusterCommand:
841258bc78c7SXin Chen sub_cmd = ddi_get32(acc,
841358bc78c7SXin Chen (void *)&(((uint32_t *)(void *)fibp->data)[0]));
8414830d82f7Spl subcmdstr = aac_cmd_name(sub_cmd, aac_cl_subcmds);
8415830d82f7Spl break;
8416830d82f7Spl
8417830d82f7Spl case AifRequest:
841858bc78c7SXin Chen sub_cmd = ddi_get32(acc,
841958bc78c7SXin Chen (void *)&(((uint32_t *)(void *)fibp->data)[0]));
8420830d82f7Spl subcmdstr = aac_cmd_name(sub_cmd, aac_aif_subcmds);
8421830d82f7Spl break;
8422830d82f7Spl
8423830d82f7Spl default:
8424830d82f7Spl break;
8425830d82f7Spl }
8426830d82f7Spl
842758bc78c7SXin Chen fib_size = ddi_get16(acc, &(fibp->Header.Size));
8428830d82f7Spl if (subcmdstr)
84291dd0a2dbSpl aac_printf(softs, CE_NOTE, "FIB> %s, sz=%d",
8430942c5e3cSpl subcmdstr, fib_size);
843158bc78c7SXin Chen else if (cmdstr && sub_cmd == (uint32_t)-1)
84321dd0a2dbSpl aac_printf(softs, CE_NOTE, "FIB> %s, sz=%d",
8433942c5e3cSpl cmdstr, fib_size);
8434830d82f7Spl else if (cmdstr)
84351dd0a2dbSpl aac_printf(softs, CE_NOTE, "FIB> %s: Unknown(0x%x), sz=%d",
8436942c5e3cSpl cmdstr, sub_cmd, fib_size);
8437830d82f7Spl else
84381dd0a2dbSpl aac_printf(softs, CE_NOTE, "FIB> Unknown(0x%x), sz=%d",
8439942c5e3cSpl fib_cmd, fib_size);
8440830d82f7Spl }
8441830d82f7Spl
8442830d82f7Spl static void
aac_print_aif(struct aac_softstate * softs,struct aac_aif_command * aif)84431dd0a2dbSpl aac_print_aif(struct aac_softstate *softs, struct aac_aif_command *aif)
8444830d82f7Spl {
8445942c5e3cSpl int aif_command;
8446942c5e3cSpl uint32_t aif_seqnumber;
8447942c5e3cSpl int aif_en_type;
8448830d82f7Spl char *str;
8449830d82f7Spl
8450942c5e3cSpl aif_command = LE_32(aif->command);
8451942c5e3cSpl aif_seqnumber = LE_32(aif->seqNumber);
8452942c5e3cSpl aif_en_type = LE_32(aif->data.EN.type);
8453942c5e3cSpl
8454942c5e3cSpl switch (aif_command) {
8455830d82f7Spl case AifCmdEventNotify:
8456942c5e3cSpl str = aac_cmd_name(aif_en_type, aac_aifens);
8457830d82f7Spl if (str)
84581dd0a2dbSpl aac_printf(softs, CE_NOTE, "AIF! %s", str);
8459830d82f7Spl else
84601dd0a2dbSpl aac_printf(softs, CE_NOTE, "AIF! Unknown(0x%x)",
8461942c5e3cSpl aif_en_type);
8462830d82f7Spl break;
8463830d82f7Spl
8464830d82f7Spl case AifCmdJobProgress:
8465942c5e3cSpl switch (LE_32(aif->data.PR[0].status)) {
8466830d82f7Spl case AifJobStsSuccess:
8467830d82f7Spl str = "success"; break;
8468830d82f7Spl case AifJobStsFinished:
8469830d82f7Spl str = "finished"; break;
8470830d82f7Spl case AifJobStsAborted:
8471830d82f7Spl str = "aborted"; break;
8472830d82f7Spl case AifJobStsFailed:
8473830d82f7Spl str = "failed"; break;
8474830d82f7Spl case AifJobStsSuspended:
8475830d82f7Spl str = "suspended"; break;
8476830d82f7Spl case AifJobStsRunning:
8477830d82f7Spl str = "running"; break;
84787c478bd9Sstevel@tonic-gate default:
8479830d82f7Spl str = "unknown"; break;
8480830d82f7Spl }
84811dd0a2dbSpl aac_printf(softs, CE_NOTE,
84821dd0a2dbSpl "AIF! JobProgress (%d) - %s (%d, %d)",
8483942c5e3cSpl aif_seqnumber, str,
8484942c5e3cSpl LE_32(aif->data.PR[0].currentTick),
8485942c5e3cSpl LE_32(aif->data.PR[0].finalTick));
8486830d82f7Spl break;
8487830d82f7Spl
8488830d82f7Spl case AifCmdAPIReport:
84891dd0a2dbSpl aac_printf(softs, CE_NOTE, "AIF! APIReport (%d)",
8490942c5e3cSpl aif_seqnumber);
8491830d82f7Spl break;
8492830d82f7Spl
8493830d82f7Spl case AifCmdDriverNotify:
84941dd0a2dbSpl aac_printf(softs, CE_NOTE, "AIF! DriverNotify (%d)",
8495942c5e3cSpl aif_seqnumber);
8496830d82f7Spl break;
8497830d82f7Spl
8498830d82f7Spl default:
84991dd0a2dbSpl aac_printf(softs, CE_NOTE, "AIF! AIF %d (%d)",
8500942c5e3cSpl aif_command, aif_seqnumber);
8501830d82f7Spl break;
85027c478bd9Sstevel@tonic-gate }
85037c478bd9Sstevel@tonic-gate }
85047c478bd9Sstevel@tonic-gate
85051dd0a2dbSpl #endif /* DEBUG */
8506