1942c5e3cSpl196000 /* 23fced439Szhongyan gu - Sun Microsystems - Beijing China * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. 3942c5e3cSpl196000 */ 4942c5e3cSpl196000 5942c5e3cSpl196000 /* 658bc78c7SXin Chen * Copyright 2005-08 Adaptec, Inc. 758bc78c7SXin Chen * Copyright (c) 2005-08 Adaptec Inc., Achim Leubner 8942c5e3cSpl196000 * Copyright (c) 2000 Michael Smith 9942c5e3cSpl196000 * Copyright (c) 2001 Scott Long 10942c5e3cSpl196000 * Copyright (c) 2000 BSDi 11942c5e3cSpl196000 * All rights reserved. 12942c5e3cSpl196000 * 13942c5e3cSpl196000 * Redistribution and use in source and binary forms, with or without 14942c5e3cSpl196000 * modification, are permitted provided that the following conditions 15942c5e3cSpl196000 * are met: 16942c5e3cSpl196000 * 1. Redistributions of source code must retain the above copyright 17942c5e3cSpl196000 * notice, this list of conditions and the following disclaimer. 18942c5e3cSpl196000 * 2. Redistributions in binary form must reproduce the above copyright 19942c5e3cSpl196000 * notice, this list of conditions and the following disclaimer in the 20942c5e3cSpl196000 * documentation and/or other materials provided with the distribution. 21942c5e3cSpl196000 * 22942c5e3cSpl196000 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 23942c5e3cSpl196000 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24942c5e3cSpl196000 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25942c5e3cSpl196000 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 26942c5e3cSpl196000 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27942c5e3cSpl196000 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28942c5e3cSpl196000 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29942c5e3cSpl196000 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30942c5e3cSpl196000 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31942c5e3cSpl196000 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32942c5e3cSpl196000 * SUCH DAMAGE. 33942c5e3cSpl196000 */ 34942c5e3cSpl196000 #include <sys/modctl.h> 35942c5e3cSpl196000 #include <sys/conf.h> 36942c5e3cSpl196000 #include <sys/cmn_err.h> 37942c5e3cSpl196000 #include <sys/ddi.h> 38942c5e3cSpl196000 #include <sys/devops.h> 39942c5e3cSpl196000 #include <sys/pci.h> 40942c5e3cSpl196000 #include <sys/types.h> 41942c5e3cSpl196000 #include <sys/ddidmareq.h> 42942c5e3cSpl196000 #include <sys/scsi/scsi.h> 43942c5e3cSpl196000 #include <sys/ksynch.h> 44942c5e3cSpl196000 #include <sys/sunddi.h> 45942c5e3cSpl196000 #include <sys/byteorder.h> 46942c5e3cSpl196000 #include "aac_regs.h" 47942c5e3cSpl196000 #include "aac.h" 48942c5e3cSpl196000 49942c5e3cSpl196000 /* 50942c5e3cSpl196000 * FMA header files 51942c5e3cSpl196000 */ 52942c5e3cSpl196000 #include <sys/ddifm.h> 53942c5e3cSpl196000 #include <sys/fm/protocol.h> 54942c5e3cSpl196000 #include <sys/fm/util.h> 55942c5e3cSpl196000 #include <sys/fm/io/ddi.h> 56942c5e3cSpl196000 57942c5e3cSpl196000 /* 58942c5e3cSpl196000 * For minor nodes created by the SCSA framework, minor numbers are 59942c5e3cSpl196000 * formed by left-shifting instance by INST_MINOR_SHIFT and OR in a 60942c5e3cSpl196000 * number less than 64. 61942c5e3cSpl196000 * 62942c5e3cSpl196000 * To support cfgadm, need to confirm the SCSA framework by creating 63942c5e3cSpl196000 * devctl/scsi and driver specific minor nodes under SCSA format, 64942c5e3cSpl196000 * and calling scsi_hba_xxx() functions aacordingly. 65942c5e3cSpl196000 */ 66942c5e3cSpl196000 67942c5e3cSpl196000 #define AAC_MINOR 32 68942c5e3cSpl196000 #define INST2AAC(x) (((x) << INST_MINOR_SHIFT) | AAC_MINOR) 69942c5e3cSpl196000 #define AAC_SCSA_MINOR(x) ((x) & TRAN_MINOR_MASK) 70942c5e3cSpl196000 #define AAC_IS_SCSA_NODE(x) ((x) == DEVCTL_MINOR || (x) == SCSI_MINOR) 71942c5e3cSpl196000 7258bc78c7SXin Chen #define SD2TRAN(sd) ((sd)->sd_address.a_hba_tran) 73942c5e3cSpl196000 #define AAC_TRAN2SOFTS(tran) ((struct aac_softstate *)(tran)->tran_hba_private) 74942c5e3cSpl196000 #define AAC_DIP2TRAN(dip) ((scsi_hba_tran_t *)ddi_get_driver_private(dip)) 75942c5e3cSpl196000 #define AAC_DIP2SOFTS(dip) (AAC_TRAN2SOFTS(AAC_DIP2TRAN(dip))) 7658bc78c7SXin Chen #define SD2AAC(sd) (AAC_TRAN2SOFTS(SD2TRAN(sd))) 7758bc78c7SXin Chen #define AAC_PD(t) ((t) - AAC_MAX_LD) 7858bc78c7SXin Chen #define AAC_DEV(softs, t) (((t) < AAC_MAX_LD) ? \ 7958bc78c7SXin Chen &(softs)->containers[(t)].dev : \ 8058bc78c7SXin Chen ((t) < AAC_MAX_DEV(softs)) ? \ 8158bc78c7SXin Chen &(softs)->nondasds[AAC_PD(t)].dev : NULL) 8258bc78c7SXin Chen #define AAC_DEVCFG_BEGIN(softs, tgt) \ 8358bc78c7SXin Chen aac_devcfg((softs), (tgt), 1) 8458bc78c7SXin Chen #define AAC_DEVCFG_END(softs, tgt) \ 8558bc78c7SXin Chen aac_devcfg((softs), (tgt), 0) 86942c5e3cSpl196000 #define PKT2AC(pkt) ((struct aac_cmd *)(pkt)->pkt_ha_private) 87942c5e3cSpl196000 #define AAC_BUSYWAIT(cond, timeout /* in millisecond */) { \ 88942c5e3cSpl196000 if (!(cond)) { \ 89942c5e3cSpl196000 int count = (timeout) * 10; \ 90942c5e3cSpl196000 while (count) { \ 91942c5e3cSpl196000 drv_usecwait(100); \ 92942c5e3cSpl196000 if (cond) \ 93942c5e3cSpl196000 break; \ 94942c5e3cSpl196000 count--; \ 95942c5e3cSpl196000 } \ 96942c5e3cSpl196000 (timeout) = (count + 9) / 10; \ 97942c5e3cSpl196000 } \ 98942c5e3cSpl196000 } 99942c5e3cSpl196000 100942c5e3cSpl196000 #define AAC_SENSE_DATA_DESCR_LEN \ 101942c5e3cSpl196000 (sizeof (struct scsi_descr_sense_hdr) + \ 102942c5e3cSpl196000 sizeof (struct scsi_information_sense_descr)) 103942c5e3cSpl196000 #define AAC_ARQ64_LENGTH \ 104942c5e3cSpl196000 (sizeof (struct scsi_arq_status) + \ 105942c5e3cSpl196000 AAC_SENSE_DATA_DESCR_LEN - SENSE_LENGTH) 106942c5e3cSpl196000 107942c5e3cSpl196000 /* NOTE: GETG4ADDRTL(cdbp) is int32_t */ 108942c5e3cSpl196000 #define AAC_GETGXADDR(cmdlen, cdbp) \ 109942c5e3cSpl196000 ((cmdlen == 6) ? GETG0ADDR(cdbp) : \ 110942c5e3cSpl196000 (cmdlen == 10) ? (uint32_t)GETG1ADDR(cdbp) : \ 111942c5e3cSpl196000 ((uint64_t)GETG4ADDR(cdbp) << 32) | (uint32_t)GETG4ADDRTL(cdbp)) 112942c5e3cSpl196000 113942c5e3cSpl196000 #define AAC_CDB_INQUIRY_CMDDT 0x02 114942c5e3cSpl196000 #define AAC_CDB_INQUIRY_EVPD 0x01 115942c5e3cSpl196000 #define AAC_VPD_PAGE_CODE 1 116942c5e3cSpl196000 #define AAC_VPD_PAGE_LENGTH 3 117942c5e3cSpl196000 #define AAC_VPD_PAGE_DATA 4 118942c5e3cSpl196000 #define AAC_VPD_ID_CODESET 0 119942c5e3cSpl196000 #define AAC_VPD_ID_TYPE 1 120942c5e3cSpl196000 #define AAC_VPD_ID_LENGTH 3 121942c5e3cSpl196000 #define AAC_VPD_ID_DATA 4 122942c5e3cSpl196000 12358bc78c7SXin Chen #define AAC_SCSI_RPTLUNS_HEAD_SIZE 0x08 12458bc78c7SXin Chen #define AAC_SCSI_RPTLUNS_ADDR_SIZE 0x08 12558bc78c7SXin Chen #define AAC_SCSI_RPTLUNS_ADDR_MASK 0xC0 12658bc78c7SXin Chen /* 00b - peripheral device addressing method */ 12758bc78c7SXin Chen #define AAC_SCSI_RPTLUNS_ADDR_PERIPHERAL 0x00 12858bc78c7SXin Chen /* 01b - flat space addressing method */ 12958bc78c7SXin Chen #define AAC_SCSI_RPTLUNS_ADDR_FLAT_SPACE 0x40 13058bc78c7SXin Chen /* 10b - logical unit addressing method */ 13158bc78c7SXin Chen #define AAC_SCSI_RPTLUNS_ADDR_LOGICAL_UNIT 0x80 13258bc78c7SXin Chen 133942c5e3cSpl196000 /* Return the size of FIB with data part type data_type */ 134942c5e3cSpl196000 #define AAC_FIB_SIZEOF(data_type) \ 135942c5e3cSpl196000 (sizeof (struct aac_fib_header) + sizeof (data_type)) 136942c5e3cSpl196000 /* Return the container size defined in mir */ 137942c5e3cSpl196000 #define AAC_MIR_SIZE(softs, acc, mir) \ 138942c5e3cSpl196000 (((softs)->flags & AAC_FLAGS_LBA_64BIT) ? \ 139942c5e3cSpl196000 (uint64_t)ddi_get32((acc), &(mir)->MntObj.Capacity) + \ 140942c5e3cSpl196000 ((uint64_t)ddi_get32((acc), &(mir)->MntObj.CapacityHigh) << 32) : \ 141942c5e3cSpl196000 (uint64_t)ddi_get32((acc), &(mir)->MntObj.Capacity)) 142942c5e3cSpl196000 143942c5e3cSpl196000 /* The last entry of aac_cards[] is for unknown cards */ 144942c5e3cSpl196000 #define AAC_UNKNOWN_CARD \ 145942c5e3cSpl196000 (sizeof (aac_cards) / sizeof (struct aac_card_type) - 1) 146942c5e3cSpl196000 #define CARD_IS_UNKNOWN(i) (i == AAC_UNKNOWN_CARD) 147942c5e3cSpl196000 #define BUF_IS_READ(bp) ((bp)->b_flags & B_READ) 148942c5e3cSpl196000 #define AAC_IS_Q_EMPTY(q) ((q)->q_head == NULL) 149942c5e3cSpl196000 #define AAC_CMDQ(acp) (!((acp)->flags & AAC_CMD_SYNC)) 150942c5e3cSpl196000 151942c5e3cSpl196000 #define PCI_MEM_GET32(softs, off) \ 152942c5e3cSpl196000 ddi_get32((softs)->pci_mem_handle, \ 153a74f7440Spl196000 (void *)((softs)->pci_mem_base_vaddr + (off))) 154942c5e3cSpl196000 #define PCI_MEM_PUT32(softs, off, val) \ 155942c5e3cSpl196000 ddi_put32((softs)->pci_mem_handle, \ 156a74f7440Spl196000 (void *)((softs)->pci_mem_base_vaddr + (off)), \ 157942c5e3cSpl196000 (uint32_t)(val)) 158942c5e3cSpl196000 #define PCI_MEM_GET16(softs, off) \ 159942c5e3cSpl196000 ddi_get16((softs)->pci_mem_handle, \ 160a74f7440Spl196000 (void *)((softs)->pci_mem_base_vaddr + (off))) 161942c5e3cSpl196000 #define PCI_MEM_PUT16(softs, off, val) \ 162942c5e3cSpl196000 ddi_put16((softs)->pci_mem_handle, \ 163a74f7440Spl196000 (void *)((softs)->pci_mem_base_vaddr + (off)), (uint16_t)(val)) 164942c5e3cSpl196000 /* Write host data at valp to device mem[off] repeatedly count times */ 165942c5e3cSpl196000 #define PCI_MEM_REP_PUT8(softs, off, valp, count) \ 166942c5e3cSpl196000 ddi_rep_put8((softs)->pci_mem_handle, (uint8_t *)(valp), \ 167942c5e3cSpl196000 (uint8_t *)((softs)->pci_mem_base_vaddr + (off)), \ 168942c5e3cSpl196000 count, DDI_DEV_AUTOINCR) 169942c5e3cSpl196000 /* Read device data at mem[off] to host addr valp repeatedly count times */ 170942c5e3cSpl196000 #define PCI_MEM_REP_GET8(softs, off, valp, count) \ 171942c5e3cSpl196000 ddi_rep_get8((softs)->pci_mem_handle, (uint8_t *)(valp), \ 172942c5e3cSpl196000 (uint8_t *)((softs)->pci_mem_base_vaddr + (off)), \ 173942c5e3cSpl196000 count, DDI_DEV_AUTOINCR) 174942c5e3cSpl196000 #define AAC_GET_FIELD8(acc, d, s, field) \ 175942c5e3cSpl196000 (d)->field = ddi_get8(acc, (uint8_t *)&(s)->field) 176942c5e3cSpl196000 #define AAC_GET_FIELD32(acc, d, s, field) \ 177942c5e3cSpl196000 (d)->field = ddi_get32(acc, (uint32_t *)&(s)->field) 178942c5e3cSpl196000 #define AAC_GET_FIELD64(acc, d, s, field) \ 179942c5e3cSpl196000 (d)->field = ddi_get64(acc, (uint64_t *)&(s)->field) 180942c5e3cSpl196000 #define AAC_REP_GET_FIELD8(acc, d, s, field, r) \ 181942c5e3cSpl196000 ddi_rep_get8((acc), (uint8_t *)&(d)->field, \ 182942c5e3cSpl196000 (uint8_t *)&(s)->field, (r), DDI_DEV_AUTOINCR) 183942c5e3cSpl196000 #define AAC_REP_GET_FIELD32(acc, d, s, field, r) \ 184942c5e3cSpl196000 ddi_rep_get32((acc), (uint32_t *)&(d)->field, \ 185942c5e3cSpl196000 (uint32_t *)&(s)->field, (r), DDI_DEV_AUTOINCR) 186942c5e3cSpl196000 187942c5e3cSpl196000 #define AAC_ENABLE_INTR(softs) { \ 188942c5e3cSpl196000 if (softs->flags & AAC_FLAGS_NEW_COMM) \ 189942c5e3cSpl196000 PCI_MEM_PUT32(softs, AAC_OIMR, ~AAC_DB_INTR_NEW); \ 190942c5e3cSpl196000 else \ 191942c5e3cSpl196000 PCI_MEM_PUT32(softs, AAC_OIMR, ~AAC_DB_INTR_BITS); \ 1921ee13a44SXinChen softs->state |= AAC_STATE_INTR; \ 193942c5e3cSpl196000 } 194942c5e3cSpl196000 1951ee13a44SXinChen #define AAC_DISABLE_INTR(softs) { \ 1961ee13a44SXinChen PCI_MEM_PUT32(softs, AAC_OIMR, ~0); \ 1971ee13a44SXinChen softs->state &= ~AAC_STATE_INTR; \ 1981ee13a44SXinChen } 199942c5e3cSpl196000 #define AAC_STATUS_CLR(softs, mask) PCI_MEM_PUT32(softs, AAC_ODBR, mask) 200942c5e3cSpl196000 #define AAC_STATUS_GET(softs) PCI_MEM_GET32(softs, AAC_ODBR) 201942c5e3cSpl196000 #define AAC_NOTIFY(softs, val) PCI_MEM_PUT32(softs, AAC_IDBR, val) 202942c5e3cSpl196000 #define AAC_OUTB_GET(softs) PCI_MEM_GET32(softs, AAC_OQUE) 203942c5e3cSpl196000 #define AAC_OUTB_SET(softs, val) PCI_MEM_PUT32(softs, AAC_OQUE, val) 204942c5e3cSpl196000 #define AAC_FWSTATUS_GET(softs) \ 205942c5e3cSpl196000 ((softs)->aac_if.aif_get_fwstatus(softs)) 206942c5e3cSpl196000 #define AAC_MAILBOX_GET(softs, mb) \ 207942c5e3cSpl196000 ((softs)->aac_if.aif_get_mailbox((softs), (mb))) 208942c5e3cSpl196000 #define AAC_MAILBOX_SET(softs, cmd, arg0, arg1, arg2, arg3) \ 209942c5e3cSpl196000 ((softs)->aac_if.aif_set_mailbox((softs), (cmd), \ 210942c5e3cSpl196000 (arg0), (arg1), (arg2), (arg3))) 211942c5e3cSpl196000 212f42c2f53Szhongyan gu - Sun Microsystems - Beijing China #define AAC_MGT_SLOT_NUM 2 213942c5e3cSpl196000 #define AAC_THROTTLE_DRAIN -1 214942c5e3cSpl196000 215942c5e3cSpl196000 #define AAC_QUIESCE_TICK 1 /* 1 second */ 21658bc78c7SXin Chen #define AAC_QUIESCE_TIMEOUT 180 /* 180 seconds */ 217942c5e3cSpl196000 #define AAC_DEFAULT_TICK 10 /* 10 seconds */ 218942c5e3cSpl196000 #define AAC_SYNC_TICK (30*60) /* 30 minutes */ 219942c5e3cSpl196000 220942c5e3cSpl196000 /* Poll time for aac_do_poll_io() */ 221942c5e3cSpl196000 #define AAC_POLL_TIME 60 /* 60 seconds */ 222942c5e3cSpl196000 22358bc78c7SXin Chen /* IOP reset */ 22458bc78c7SXin Chen #define AAC_IOP_RESET_SUCCEED 0 /* IOP reset succeed */ 22558bc78c7SXin Chen #define AAC_IOP_RESET_FAILED -1 /* IOP reset failed */ 22658bc78c7SXin Chen #define AAC_IOP_RESET_ABNORMAL -2 /* Reset operation abnormal */ 22758bc78c7SXin Chen 228942c5e3cSpl196000 /* 229942c5e3cSpl196000 * Hardware access functions 230942c5e3cSpl196000 */ 231942c5e3cSpl196000 static int aac_rx_get_fwstatus(struct aac_softstate *); 232942c5e3cSpl196000 static int aac_rx_get_mailbox(struct aac_softstate *, int); 233942c5e3cSpl196000 static void aac_rx_set_mailbox(struct aac_softstate *, uint32_t, uint32_t, 234942c5e3cSpl196000 uint32_t, uint32_t, uint32_t); 235942c5e3cSpl196000 static int aac_rkt_get_fwstatus(struct aac_softstate *); 236942c5e3cSpl196000 static int aac_rkt_get_mailbox(struct aac_softstate *, int); 237942c5e3cSpl196000 static void aac_rkt_set_mailbox(struct aac_softstate *, uint32_t, uint32_t, 238942c5e3cSpl196000 uint32_t, uint32_t, uint32_t); 239942c5e3cSpl196000 240942c5e3cSpl196000 /* 241942c5e3cSpl196000 * SCSA function prototypes 242942c5e3cSpl196000 */ 243942c5e3cSpl196000 static int aac_attach(dev_info_t *, ddi_attach_cmd_t); 244942c5e3cSpl196000 static int aac_detach(dev_info_t *, ddi_detach_cmd_t); 245942c5e3cSpl196000 static int aac_reset(dev_info_t *, ddi_reset_cmd_t); 24619397407SSherry Moore static int aac_quiesce(dev_info_t *); 247f42c2f53Szhongyan gu - Sun Microsystems - Beijing China static int aac_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **); 248942c5e3cSpl196000 249942c5e3cSpl196000 /* 250942c5e3cSpl196000 * Interrupt handler functions 251942c5e3cSpl196000 */ 252b6094a86Sjd218194 static int aac_query_intrs(struct aac_softstate *, int); 253b6094a86Sjd218194 static int aac_add_intrs(struct aac_softstate *); 254b6094a86Sjd218194 static void aac_remove_intrs(struct aac_softstate *); 255f42c2f53Szhongyan gu - Sun Microsystems - Beijing China static int aac_enable_intrs(struct aac_softstate *); 256f42c2f53Szhongyan gu - Sun Microsystems - Beijing China static int aac_disable_intrs(struct aac_softstate *); 257942c5e3cSpl196000 static uint_t aac_intr_old(caddr_t); 258942c5e3cSpl196000 static uint_t aac_intr_new(caddr_t); 259942c5e3cSpl196000 static uint_t aac_softintr(caddr_t); 260942c5e3cSpl196000 261942c5e3cSpl196000 /* 262942c5e3cSpl196000 * Internal functions in attach 263942c5e3cSpl196000 */ 264942c5e3cSpl196000 static int aac_check_card_type(struct aac_softstate *); 265942c5e3cSpl196000 static int aac_check_firmware(struct aac_softstate *); 266942c5e3cSpl196000 static int aac_common_attach(struct aac_softstate *); 267942c5e3cSpl196000 static void aac_common_detach(struct aac_softstate *); 268942c5e3cSpl196000 static int aac_probe_containers(struct aac_softstate *); 269942c5e3cSpl196000 static int aac_alloc_comm_space(struct aac_softstate *); 270942c5e3cSpl196000 static int aac_setup_comm_space(struct aac_softstate *); 271942c5e3cSpl196000 static void aac_free_comm_space(struct aac_softstate *); 272942c5e3cSpl196000 static int aac_hba_setup(struct aac_softstate *); 273942c5e3cSpl196000 274942c5e3cSpl196000 /* 275942c5e3cSpl196000 * Sync FIB operation functions 276942c5e3cSpl196000 */ 277942c5e3cSpl196000 int aac_sync_mbcommand(struct aac_softstate *, uint32_t, uint32_t, 278942c5e3cSpl196000 uint32_t, uint32_t, uint32_t, uint32_t *); 279942c5e3cSpl196000 static int aac_sync_fib(struct aac_softstate *, uint16_t, uint16_t); 280942c5e3cSpl196000 281942c5e3cSpl196000 /* 282942c5e3cSpl196000 * Command queue operation functions 283942c5e3cSpl196000 */ 284942c5e3cSpl196000 static void aac_cmd_initq(struct aac_cmd_queue *); 285942c5e3cSpl196000 static void aac_cmd_enqueue(struct aac_cmd_queue *, struct aac_cmd *); 286942c5e3cSpl196000 static struct aac_cmd *aac_cmd_dequeue(struct aac_cmd_queue *); 287942c5e3cSpl196000 static void aac_cmd_delete(struct aac_cmd_queue *, struct aac_cmd *); 288942c5e3cSpl196000 289942c5e3cSpl196000 /* 290942c5e3cSpl196000 * FIB queue operation functions 291942c5e3cSpl196000 */ 292942c5e3cSpl196000 static int aac_fib_enqueue(struct aac_softstate *, int, uint32_t, uint32_t); 293942c5e3cSpl196000 static int aac_fib_dequeue(struct aac_softstate *, int, int *); 294942c5e3cSpl196000 295942c5e3cSpl196000 /* 296942c5e3cSpl196000 * Slot operation functions 297942c5e3cSpl196000 */ 298942c5e3cSpl196000 static int aac_create_slots(struct aac_softstate *); 299942c5e3cSpl196000 static void aac_destroy_slots(struct aac_softstate *); 300942c5e3cSpl196000 static void aac_alloc_fibs(struct aac_softstate *); 301942c5e3cSpl196000 static void aac_destroy_fibs(struct aac_softstate *); 302942c5e3cSpl196000 static struct aac_slot *aac_get_slot(struct aac_softstate *); 303942c5e3cSpl196000 static void aac_release_slot(struct aac_softstate *, struct aac_slot *); 304942c5e3cSpl196000 static int aac_alloc_fib(struct aac_softstate *, struct aac_slot *); 305942c5e3cSpl196000 static void aac_free_fib(struct aac_slot *); 306942c5e3cSpl196000 307942c5e3cSpl196000 /* 308942c5e3cSpl196000 * Internal functions 309942c5e3cSpl196000 */ 310f42c2f53Szhongyan gu - Sun Microsystems - Beijing China static void aac_cmd_fib_header(struct aac_softstate *, struct aac_cmd *, 311f42c2f53Szhongyan gu - Sun Microsystems - Beijing China uint16_t); 312942c5e3cSpl196000 static void aac_cmd_fib_rawio(struct aac_softstate *, struct aac_cmd *); 313942c5e3cSpl196000 static void aac_cmd_fib_brw64(struct aac_softstate *, struct aac_cmd *); 314942c5e3cSpl196000 static void aac_cmd_fib_brw(struct aac_softstate *, struct aac_cmd *); 315942c5e3cSpl196000 static void aac_cmd_fib_sync(struct aac_softstate *, struct aac_cmd *); 316942c5e3cSpl196000 static void aac_cmd_fib_scsi32(struct aac_softstate *, struct aac_cmd *); 317942c5e3cSpl196000 static void aac_cmd_fib_scsi64(struct aac_softstate *, struct aac_cmd *); 318b40e8a89Szhongyan gu - Sun Microsystems - Beijing China static void aac_cmd_fib_startstop(struct aac_softstate *, struct aac_cmd *); 319942c5e3cSpl196000 static void aac_start_waiting_io(struct aac_softstate *); 320942c5e3cSpl196000 static void aac_drain_comp_q(struct aac_softstate *); 321942c5e3cSpl196000 int aac_do_io(struct aac_softstate *, struct aac_cmd *); 322f42c2f53Szhongyan gu - Sun Microsystems - Beijing China static int aac_sync_fib_slot_bind(struct aac_softstate *, struct aac_cmd *); 323f42c2f53Szhongyan gu - Sun Microsystems - Beijing China static void aac_sync_fib_slot_release(struct aac_softstate *, struct aac_cmd *); 324f42c2f53Szhongyan gu - Sun Microsystems - Beijing China static void aac_start_io(struct aac_softstate *, struct aac_cmd *); 325942c5e3cSpl196000 static int aac_do_poll_io(struct aac_softstate *, struct aac_cmd *); 326942c5e3cSpl196000 static int aac_do_sync_io(struct aac_softstate *, struct aac_cmd *); 327942c5e3cSpl196000 static int aac_send_command(struct aac_softstate *, struct aac_slot *); 32858bc78c7SXin Chen static void aac_cmd_timeout(struct aac_softstate *, struct aac_cmd *); 329942c5e3cSpl196000 static int aac_dma_sync_ac(struct aac_cmd *); 330942c5e3cSpl196000 static int aac_shutdown(struct aac_softstate *); 331942c5e3cSpl196000 static int aac_reset_adapter(struct aac_softstate *); 332942c5e3cSpl196000 static int aac_do_quiesce(struct aac_softstate *softs); 333942c5e3cSpl196000 static int aac_do_unquiesce(struct aac_softstate *softs); 334942c5e3cSpl196000 static void aac_unhold_bus(struct aac_softstate *, int); 33558bc78c7SXin Chen static void aac_set_throttle(struct aac_softstate *, struct aac_device *, 336942c5e3cSpl196000 int, int); 337942c5e3cSpl196000 338942c5e3cSpl196000 /* 339942c5e3cSpl196000 * Adapter Initiated FIB handling function 340942c5e3cSpl196000 */ 3410749e8deSXin Chen - Sun Microsystems - Beijing China static void aac_save_aif(struct aac_softstate *, ddi_acc_handle_t, 3420749e8deSXin Chen - Sun Microsystems - Beijing China struct aac_fib *, int); 3430749e8deSXin Chen - Sun Microsystems - Beijing China static int aac_handle_aif(struct aac_softstate *, struct aac_aif_command *); 344942c5e3cSpl196000 345942c5e3cSpl196000 /* 3460749e8deSXin Chen - Sun Microsystems - Beijing China * Event handling related functions 347942c5e3cSpl196000 */ 3480749e8deSXin Chen - Sun Microsystems - Beijing China static void aac_timer(void *); 3490749e8deSXin Chen - Sun Microsystems - Beijing China static void aac_event_thread(struct aac_softstate *); 3500749e8deSXin Chen - Sun Microsystems - Beijing China static void aac_event_disp(struct aac_softstate *, int); 351942c5e3cSpl196000 352942c5e3cSpl196000 /* 353942c5e3cSpl196000 * IOCTL interface related functions 354942c5e3cSpl196000 */ 355942c5e3cSpl196000 static int aac_open(dev_t *, int, int, cred_t *); 356942c5e3cSpl196000 static int aac_close(dev_t, int, int, cred_t *); 357942c5e3cSpl196000 static int aac_ioctl(dev_t, int, intptr_t, int, cred_t *, int *); 358942c5e3cSpl196000 extern int aac_do_ioctl(struct aac_softstate *, dev_t, int, intptr_t, int); 359942c5e3cSpl196000 360942c5e3cSpl196000 /* 361942c5e3cSpl196000 * FMA Prototypes 362942c5e3cSpl196000 */ 363942c5e3cSpl196000 static void aac_fm_init(struct aac_softstate *); 364942c5e3cSpl196000 static void aac_fm_fini(struct aac_softstate *); 365942c5e3cSpl196000 static int aac_fm_error_cb(dev_info_t *, ddi_fm_error_t *, const void *); 366942c5e3cSpl196000 int aac_check_acc_handle(ddi_acc_handle_t); 367942c5e3cSpl196000 int aac_check_dma_handle(ddi_dma_handle_t); 368942c5e3cSpl196000 void aac_fm_ereport(struct aac_softstate *, char *); 369942c5e3cSpl196000 37058bc78c7SXin Chen /* 37158bc78c7SXin Chen * Auto enumeration functions 37258bc78c7SXin Chen */ 37358bc78c7SXin Chen static dev_info_t *aac_find_child(struct aac_softstate *, uint16_t, uint8_t); 37458bc78c7SXin Chen static int aac_tran_bus_config(dev_info_t *, uint_t, ddi_bus_config_op_t, 37558bc78c7SXin Chen void *, dev_info_t **); 3760749e8deSXin Chen - Sun Microsystems - Beijing China static int aac_handle_dr(struct aac_softstate *, int, int, int); 3770749e8deSXin Chen - Sun Microsystems - Beijing China 3780749e8deSXin Chen - Sun Microsystems - Beijing China extern pri_t minclsyspri; 37958bc78c7SXin Chen 380942c5e3cSpl196000 #ifdef DEBUG 381942c5e3cSpl196000 /* 382942c5e3cSpl196000 * UART debug output support 383942c5e3cSpl196000 */ 384942c5e3cSpl196000 385942c5e3cSpl196000 #define AAC_PRINT_BUFFER_SIZE 512 386942c5e3cSpl196000 #define AAC_PRINT_TIMEOUT 250 /* 1/4 sec. = 250 msec. */ 387942c5e3cSpl196000 388942c5e3cSpl196000 #define AAC_FW_DBG_STRLEN_OFFSET 0x00 389942c5e3cSpl196000 #define AAC_FW_DBG_FLAGS_OFFSET 0x04 390942c5e3cSpl196000 #define AAC_FW_DBG_BLED_OFFSET 0x08 391942c5e3cSpl196000 392942c5e3cSpl196000 static int aac_get_fw_debug_buffer(struct aac_softstate *); 393942c5e3cSpl196000 static void aac_print_scmd(struct aac_softstate *, struct aac_cmd *); 394942c5e3cSpl196000 static void aac_print_aif(struct aac_softstate *, struct aac_aif_command *); 395942c5e3cSpl196000 396942c5e3cSpl196000 static char aac_prt_buf[AAC_PRINT_BUFFER_SIZE]; 397942c5e3cSpl196000 static char aac_fmt[] = " %s"; 398942c5e3cSpl196000 static char aac_fmt_header[] = " %s.%d: %s"; 399942c5e3cSpl196000 static kmutex_t aac_prt_mutex; 400942c5e3cSpl196000 401942c5e3cSpl196000 /* 402942c5e3cSpl196000 * Debug flags to be put into the softstate flags field 403942c5e3cSpl196000 * when initialized 404942c5e3cSpl196000 */ 405942c5e3cSpl196000 uint32_t aac_debug_flags = 406942c5e3cSpl196000 /* AACDB_FLAGS_KERNEL_PRINT | */ 407942c5e3cSpl196000 /* AACDB_FLAGS_FW_PRINT | */ 408942c5e3cSpl196000 /* AACDB_FLAGS_MISC | */ 409942c5e3cSpl196000 /* AACDB_FLAGS_FUNC1 | */ 410942c5e3cSpl196000 /* AACDB_FLAGS_FUNC2 | */ 411942c5e3cSpl196000 /* AACDB_FLAGS_SCMD | */ 412942c5e3cSpl196000 /* AACDB_FLAGS_AIF | */ 413942c5e3cSpl196000 /* AACDB_FLAGS_FIB | */ 414942c5e3cSpl196000 /* AACDB_FLAGS_IOCTL | */ 415942c5e3cSpl196000 0; 41658bc78c7SXin Chen uint32_t aac_debug_fib_flags = 41758bc78c7SXin Chen /* AACDB_FLAGS_FIB_RW | */ 41858bc78c7SXin Chen /* AACDB_FLAGS_FIB_IOCTL | */ 41958bc78c7SXin Chen /* AACDB_FLAGS_FIB_SRB | */ 42058bc78c7SXin Chen /* AACDB_FLAGS_FIB_SYNC | */ 42158bc78c7SXin Chen /* AACDB_FLAGS_FIB_HEADER | */ 42258bc78c7SXin Chen /* AACDB_FLAGS_FIB_TIMEOUT | */ 42358bc78c7SXin Chen 0; 424942c5e3cSpl196000 425942c5e3cSpl196000 #endif /* DEBUG */ 426942c5e3cSpl196000 427942c5e3cSpl196000 static struct cb_ops aac_cb_ops = { 428942c5e3cSpl196000 aac_open, /* open */ 429942c5e3cSpl196000 aac_close, /* close */ 430942c5e3cSpl196000 nodev, /* strategy */ 431942c5e3cSpl196000 nodev, /* print */ 432942c5e3cSpl196000 nodev, /* dump */ 433942c5e3cSpl196000 nodev, /* read */ 434942c5e3cSpl196000 nodev, /* write */ 435942c5e3cSpl196000 aac_ioctl, /* ioctl */ 436942c5e3cSpl196000 nodev, /* devmap */ 437942c5e3cSpl196000 nodev, /* mmap */ 438942c5e3cSpl196000 nodev, /* segmap */ 439942c5e3cSpl196000 nochpoll, /* poll */ 440942c5e3cSpl196000 ddi_prop_op, /* cb_prop_op */ 441942c5e3cSpl196000 NULL, /* streamtab */ 442942c5e3cSpl196000 D_64BIT | D_NEW | D_MP | D_HOTPLUG, /* cb_flag */ 443942c5e3cSpl196000 CB_REV, /* cb_rev */ 444942c5e3cSpl196000 nodev, /* async I/O read entry point */ 445942c5e3cSpl196000 nodev /* async I/O write entry point */ 446942c5e3cSpl196000 }; 447942c5e3cSpl196000 448942c5e3cSpl196000 static struct dev_ops aac_dev_ops = { 449942c5e3cSpl196000 DEVO_REV, 450942c5e3cSpl196000 0, 451f42c2f53Szhongyan gu - Sun Microsystems - Beijing China aac_getinfo, 452942c5e3cSpl196000 nulldev, 453942c5e3cSpl196000 nulldev, 454942c5e3cSpl196000 aac_attach, 455942c5e3cSpl196000 aac_detach, 456942c5e3cSpl196000 aac_reset, 457942c5e3cSpl196000 &aac_cb_ops, 458942c5e3cSpl196000 NULL, 45919397407SSherry Moore NULL, 46019397407SSherry Moore aac_quiesce, 461942c5e3cSpl196000 }; 462942c5e3cSpl196000 463942c5e3cSpl196000 static struct modldrv aac_modldrv = { 464942c5e3cSpl196000 &mod_driverops, 465942c5e3cSpl196000 "AAC Driver " AAC_DRIVER_VERSION, 466942c5e3cSpl196000 &aac_dev_ops, 467942c5e3cSpl196000 }; 468942c5e3cSpl196000 469942c5e3cSpl196000 static struct modlinkage aac_modlinkage = { 470942c5e3cSpl196000 MODREV_1, 471942c5e3cSpl196000 &aac_modldrv, 472942c5e3cSpl196000 NULL 473942c5e3cSpl196000 }; 474942c5e3cSpl196000 475942c5e3cSpl196000 static struct aac_softstate *aac_softstatep; 476942c5e3cSpl196000 477942c5e3cSpl196000 /* 478942c5e3cSpl196000 * Supported card list 479942c5e3cSpl196000 * ordered in vendor id, subvendor id, subdevice id, and device id 480942c5e3cSpl196000 */ 481942c5e3cSpl196000 static struct aac_card_type aac_cards[] = { 482942c5e3cSpl196000 {0x1028, 0x1, 0x1028, 0x1, AAC_HWIF_I960RX, 483942c5e3cSpl196000 AAC_FLAGS_NO4GB | AAC_FLAGS_34SG, AAC_TYPE_SCSI, 484942c5e3cSpl196000 "Dell", "PERC 3/Di"}, 485942c5e3cSpl196000 {0x1028, 0x2, 0x1028, 0x2, AAC_HWIF_I960RX, 486942c5e3cSpl196000 AAC_FLAGS_NO4GB | AAC_FLAGS_34SG, AAC_TYPE_SCSI, 487942c5e3cSpl196000 "Dell", "PERC 3/Di"}, 488942c5e3cSpl196000 {0x1028, 0x3, 0x1028, 0x3, AAC_HWIF_I960RX, 489942c5e3cSpl196000 AAC_FLAGS_NO4GB | AAC_FLAGS_34SG, AAC_TYPE_SCSI, 490942c5e3cSpl196000 "Dell", "PERC 3/Si"}, 491942c5e3cSpl196000 {0x1028, 0x8, 0x1028, 0xcf, AAC_HWIF_I960RX, 492942c5e3cSpl196000 AAC_FLAGS_NO4GB | AAC_FLAGS_34SG, AAC_TYPE_SCSI, 493942c5e3cSpl196000 "Dell", "PERC 3/Di"}, 494942c5e3cSpl196000 {0x1028, 0x4, 0x1028, 0xd0, AAC_HWIF_I960RX, 495942c5e3cSpl196000 AAC_FLAGS_NO4GB | AAC_FLAGS_34SG, AAC_TYPE_SCSI, 496942c5e3cSpl196000 "Dell", "PERC 3/Si"}, 497942c5e3cSpl196000 {0x1028, 0x2, 0x1028, 0xd1, AAC_HWIF_I960RX, 498942c5e3cSpl196000 AAC_FLAGS_NO4GB | AAC_FLAGS_34SG, AAC_TYPE_SCSI, 499942c5e3cSpl196000 "Dell", "PERC 3/Di"}, 500942c5e3cSpl196000 {0x1028, 0x2, 0x1028, 0xd9, AAC_HWIF_I960RX, 501942c5e3cSpl196000 AAC_FLAGS_NO4GB | AAC_FLAGS_34SG, AAC_TYPE_SCSI, 502942c5e3cSpl196000 "Dell", "PERC 3/Di"}, 503942c5e3cSpl196000 {0x1028, 0xa, 0x1028, 0x106, AAC_HWIF_I960RX, 504942c5e3cSpl196000 AAC_FLAGS_NO4GB | AAC_FLAGS_34SG, AAC_TYPE_SCSI, 505942c5e3cSpl196000 "Dell", "PERC 3/Di"}, 506942c5e3cSpl196000 {0x1028, 0xa, 0x1028, 0x11b, AAC_HWIF_I960RX, 507942c5e3cSpl196000 AAC_FLAGS_NO4GB | AAC_FLAGS_34SG, AAC_TYPE_SCSI, 508942c5e3cSpl196000 "Dell", "PERC 3/Di"}, 509942c5e3cSpl196000 {0x1028, 0xa, 0x1028, 0x121, AAC_HWIF_I960RX, 510942c5e3cSpl196000 AAC_FLAGS_NO4GB | AAC_FLAGS_34SG, AAC_TYPE_SCSI, 511942c5e3cSpl196000 "Dell", "PERC 3/Di"}, 512942c5e3cSpl196000 {0x9005, 0x285, 0x1028, 0x287, AAC_HWIF_I960RX, 513942c5e3cSpl196000 AAC_FLAGS_NO4GB | AAC_FLAGS_34SG | AAC_FLAGS_256FIBS, AAC_TYPE_SCSI, 514942c5e3cSpl196000 "Dell", "PERC 320/DC"}, 515942c5e3cSpl196000 {0x9005, 0x285, 0x1028, 0x291, AAC_HWIF_I960RX, 516942c5e3cSpl196000 AAC_FLAGS_17SG, AAC_TYPE_SATA, "Dell", "CERC SR2"}, 517942c5e3cSpl196000 518942c5e3cSpl196000 {0x9005, 0x285, 0x1014, 0x2f2, AAC_HWIF_I960RX, 519942c5e3cSpl196000 0, AAC_TYPE_SCSI, "IBM", "ServeRAID 8i"}, 520942c5e3cSpl196000 {0x9005, 0x285, 0x1014, 0x34d, AAC_HWIF_I960RX, 521942c5e3cSpl196000 0, AAC_TYPE_SAS, "IBM", "ServeRAID 8s"}, 522942c5e3cSpl196000 {0x9005, 0x286, 0x1014, 0x9580, AAC_HWIF_RKT, 523942c5e3cSpl196000 0, AAC_TYPE_SAS, "IBM", "ServeRAID 8k"}, 524942c5e3cSpl196000 525942c5e3cSpl196000 {0x9005, 0x285, 0x103c, 0x3227, AAC_HWIF_I960RX, 526942c5e3cSpl196000 AAC_FLAGS_17SG, AAC_TYPE_SATA, "Adaptec", "2610SA"}, 527942c5e3cSpl196000 {0x9005, 0x285, 0xe11, 0x295, AAC_HWIF_I960RX, 528942c5e3cSpl196000 AAC_FLAGS_17SG, AAC_TYPE_SATA, "Adaptec", "2610SA"}, 529942c5e3cSpl196000 530942c5e3cSpl196000 {0x9005, 0x285, 0x9005, 0x285, AAC_HWIF_I960RX, 531942c5e3cSpl196000 AAC_FLAGS_NO4GB | AAC_FLAGS_34SG | AAC_FLAGS_256FIBS, AAC_TYPE_SCSI, 532942c5e3cSpl196000 "Adaptec", "2200S"}, 533942c5e3cSpl196000 {0x9005, 0x285, 0x9005, 0x286, AAC_HWIF_I960RX, 534942c5e3cSpl196000 AAC_FLAGS_NO4GB | AAC_FLAGS_34SG | AAC_FLAGS_256FIBS, AAC_TYPE_SCSI, 535942c5e3cSpl196000 "Adaptec", "2120S"}, 536942c5e3cSpl196000 {0x9005, 0x285, 0x9005, 0x287, AAC_HWIF_I960RX, 537942c5e3cSpl196000 AAC_FLAGS_NO4GB | AAC_FLAGS_34SG | AAC_FLAGS_256FIBS, AAC_TYPE_SCSI, 538942c5e3cSpl196000 "Adaptec", "2200S"}, 539942c5e3cSpl196000 {0x9005, 0x285, 0x9005, 0x288, AAC_HWIF_I960RX, 540942c5e3cSpl196000 0, AAC_TYPE_SCSI, "Adaptec", "3230S"}, 541942c5e3cSpl196000 {0x9005, 0x285, 0x9005, 0x289, AAC_HWIF_I960RX, 542942c5e3cSpl196000 0, AAC_TYPE_SCSI, "Adaptec", "3240S"}, 543942c5e3cSpl196000 {0x9005, 0x285, 0x9005, 0x28a, AAC_HWIF_I960RX, 544942c5e3cSpl196000 0, AAC_TYPE_SCSI, "Adaptec", "2020ZCR"}, 545942c5e3cSpl196000 {0x9005, 0x285, 0x9005, 0x28b, AAC_HWIF_I960RX, 546942c5e3cSpl196000 0, AAC_TYPE_SCSI, "Adaptec", "2025ZCR"}, 547942c5e3cSpl196000 {0x9005, 0x286, 0x9005, 0x28c, AAC_HWIF_RKT, 548942c5e3cSpl196000 0, AAC_TYPE_SCSI, "Adaptec", "2230S"}, 549942c5e3cSpl196000 {0x9005, 0x286, 0x9005, 0x28d, AAC_HWIF_RKT, 550942c5e3cSpl196000 0, AAC_TYPE_SCSI, "Adaptec", "2130S"}, 551942c5e3cSpl196000 {0x9005, 0x285, 0x9005, 0x28e, AAC_HWIF_I960RX, 552942c5e3cSpl196000 0, AAC_TYPE_SATA, "Adaptec", "2020SA"}, 553942c5e3cSpl196000 {0x9005, 0x285, 0x9005, 0x28f, AAC_HWIF_I960RX, 554942c5e3cSpl196000 0, AAC_TYPE_SATA, "Adaptec", "2025SA"}, 555942c5e3cSpl196000 {0x9005, 0x285, 0x9005, 0x290, AAC_HWIF_I960RX, 556942c5e3cSpl196000 AAC_FLAGS_17SG, AAC_TYPE_SATA, "Adaptec", "2410SA"}, 557942c5e3cSpl196000 {0x9005, 0x285, 0x9005, 0x292, AAC_HWIF_I960RX, 558942c5e3cSpl196000 AAC_FLAGS_17SG, AAC_TYPE_SATA, "Adaptec", "2810SA"}, 559942c5e3cSpl196000 {0x9005, 0x285, 0x9005, 0x293, AAC_HWIF_I960RX, 560942c5e3cSpl196000 AAC_FLAGS_17SG, AAC_TYPE_SATA, "Adaptec", "21610SA"}, 561942c5e3cSpl196000 {0x9005, 0x285, 0x9005, 0x294, AAC_HWIF_I960RX, 562942c5e3cSpl196000 0, AAC_TYPE_SATA, "Adaptec", "2026ZCR"}, 563942c5e3cSpl196000 {0x9005, 0x285, 0x9005, 0x296, AAC_HWIF_I960RX, 564942c5e3cSpl196000 0, AAC_TYPE_SCSI, "Adaptec", "2240S"}, 565942c5e3cSpl196000 {0x9005, 0x285, 0x9005, 0x297, AAC_HWIF_I960RX, 566942c5e3cSpl196000 0, AAC_TYPE_SAS, "Adaptec", "4005SAS"}, 567942c5e3cSpl196000 {0x9005, 0x285, 0x9005, 0x298, AAC_HWIF_I960RX, 568942c5e3cSpl196000 0, AAC_TYPE_SAS, "Adaptec", "RAID 4000"}, 569942c5e3cSpl196000 {0x9005, 0x285, 0x9005, 0x299, AAC_HWIF_I960RX, 570942c5e3cSpl196000 0, AAC_TYPE_SAS, "Adaptec", "4800SAS"}, 571942c5e3cSpl196000 {0x9005, 0x285, 0x9005, 0x29a, AAC_HWIF_I960RX, 572942c5e3cSpl196000 0, AAC_TYPE_SAS, "Adaptec", "4805SAS"}, 573942c5e3cSpl196000 {0x9005, 0x286, 0x9005, 0x29b, AAC_HWIF_RKT, 574942c5e3cSpl196000 0, AAC_TYPE_SATA, "Adaptec", "2820SA"}, 575942c5e3cSpl196000 {0x9005, 0x286, 0x9005, 0x29c, AAC_HWIF_RKT, 576942c5e3cSpl196000 0, AAC_TYPE_SATA, "Adaptec", "2620SA"}, 577942c5e3cSpl196000 {0x9005, 0x286, 0x9005, 0x29d, AAC_HWIF_RKT, 578942c5e3cSpl196000 0, AAC_TYPE_SATA, "Adaptec", "2420SA"}, 579942c5e3cSpl196000 {0x9005, 0x286, 0x9005, 0x29e, AAC_HWIF_RKT, 580942c5e3cSpl196000 0, AAC_TYPE_SATA, "ICP", "9024RO"}, 581942c5e3cSpl196000 {0x9005, 0x286, 0x9005, 0x29f, AAC_HWIF_RKT, 582942c5e3cSpl196000 0, AAC_TYPE_SATA, "ICP", "9014RO"}, 583942c5e3cSpl196000 {0x9005, 0x286, 0x9005, 0x2a0, AAC_HWIF_RKT, 584942c5e3cSpl196000 0, AAC_TYPE_SATA, "ICP", "9047MA"}, 585942c5e3cSpl196000 {0x9005, 0x286, 0x9005, 0x2a1, AAC_HWIF_RKT, 586942c5e3cSpl196000 0, AAC_TYPE_SATA, "ICP", "9087MA"}, 587942c5e3cSpl196000 {0x9005, 0x285, 0x9005, 0x2a4, AAC_HWIF_I960RX, 588942c5e3cSpl196000 0, AAC_TYPE_SAS, "ICP", "9085LI"}, 589942c5e3cSpl196000 {0x9005, 0x285, 0x9005, 0x2a5, AAC_HWIF_I960RX, 590942c5e3cSpl196000 0, AAC_TYPE_SAS, "ICP", "5085BR"}, 591942c5e3cSpl196000 {0x9005, 0x286, 0x9005, 0x2a6, AAC_HWIF_RKT, 592942c5e3cSpl196000 0, AAC_TYPE_SATA, "ICP", "9067MA"}, 593942c5e3cSpl196000 {0x9005, 0x285, 0x9005, 0x2b5, AAC_HWIF_I960RX, 594942c5e3cSpl196000 0, AAC_TYPE_SAS, "Adaptec", "RAID 5445"}, 595942c5e3cSpl196000 {0x9005, 0x285, 0x9005, 0x2b6, AAC_HWIF_I960RX, 596942c5e3cSpl196000 0, AAC_TYPE_SAS, "Adaptec", "RAID 5805"}, 597942c5e3cSpl196000 {0x9005, 0x285, 0x9005, 0x2b7, AAC_HWIF_I960RX, 598942c5e3cSpl196000 0, AAC_TYPE_SAS, "Adaptec", "RAID 5085"}, 599942c5e3cSpl196000 {0x9005, 0x285, 0x9005, 0x2b8, AAC_HWIF_I960RX, 600942c5e3cSpl196000 0, AAC_TYPE_SAS, "ICP", "RAID ICP5445SL"}, 601942c5e3cSpl196000 {0x9005, 0x285, 0x9005, 0x2b9, AAC_HWIF_I960RX, 602942c5e3cSpl196000 0, AAC_TYPE_SAS, "ICP", "RAID ICP5085SL"}, 603942c5e3cSpl196000 {0x9005, 0x285, 0x9005, 0x2ba, AAC_HWIF_I960RX, 604942c5e3cSpl196000 0, AAC_TYPE_SAS, "ICP", "RAID ICP5805SL"}, 605942c5e3cSpl196000 606942c5e3cSpl196000 {0, 0, 0, 0, AAC_HWIF_UNKNOWN, 607942c5e3cSpl196000 0, AAC_TYPE_UNKNOWN, "Unknown", "AAC card"}, 608942c5e3cSpl196000 }; 609942c5e3cSpl196000 610942c5e3cSpl196000 /* 611942c5e3cSpl196000 * Hardware access functions for i960 based cards 612942c5e3cSpl196000 */ 613942c5e3cSpl196000 static struct aac_interface aac_rx_interface = { 614942c5e3cSpl196000 aac_rx_get_fwstatus, 615942c5e3cSpl196000 aac_rx_get_mailbox, 616942c5e3cSpl196000 aac_rx_set_mailbox 617942c5e3cSpl196000 }; 618942c5e3cSpl196000 619942c5e3cSpl196000 /* 620942c5e3cSpl196000 * Hardware access functions for Rocket based cards 621942c5e3cSpl196000 */ 622942c5e3cSpl196000 static struct aac_interface aac_rkt_interface = { 623942c5e3cSpl196000 aac_rkt_get_fwstatus, 624942c5e3cSpl196000 aac_rkt_get_mailbox, 625942c5e3cSpl196000 aac_rkt_set_mailbox 626942c5e3cSpl196000 }; 627942c5e3cSpl196000 628942c5e3cSpl196000 ddi_device_acc_attr_t aac_acc_attr = { 629837c1ac4SStephen Hanson DDI_DEVICE_ATTR_V1, 630942c5e3cSpl196000 DDI_STRUCTURE_LE_ACC, 631837c1ac4SStephen Hanson DDI_STRICTORDER_ACC, 632837c1ac4SStephen Hanson DDI_DEFAULT_ACC 633942c5e3cSpl196000 }; 634942c5e3cSpl196000 635942c5e3cSpl196000 static struct { 636942c5e3cSpl196000 int size; 637942c5e3cSpl196000 int notify; 638942c5e3cSpl196000 } aac_qinfo[] = { 639942c5e3cSpl196000 {AAC_HOST_NORM_CMD_ENTRIES, AAC_DB_COMMAND_NOT_FULL}, 640942c5e3cSpl196000 {AAC_HOST_HIGH_CMD_ENTRIES, 0}, 641942c5e3cSpl196000 {AAC_ADAP_NORM_CMD_ENTRIES, AAC_DB_COMMAND_READY}, 642942c5e3cSpl196000 {AAC_ADAP_HIGH_CMD_ENTRIES, 0}, 643942c5e3cSpl196000 {AAC_HOST_NORM_RESP_ENTRIES, AAC_DB_RESPONSE_NOT_FULL}, 644942c5e3cSpl196000 {AAC_HOST_HIGH_RESP_ENTRIES, 0}, 645942c5e3cSpl196000 {AAC_ADAP_NORM_RESP_ENTRIES, AAC_DB_RESPONSE_READY}, 646942c5e3cSpl196000 {AAC_ADAP_HIGH_RESP_ENTRIES, 0} 647942c5e3cSpl196000 }; 648942c5e3cSpl196000 649942c5e3cSpl196000 /* 650942c5e3cSpl196000 * Default aac dma attributes 651942c5e3cSpl196000 */ 652942c5e3cSpl196000 static ddi_dma_attr_t aac_dma_attr = { 653942c5e3cSpl196000 DMA_ATTR_V0, 654942c5e3cSpl196000 0, /* lowest usable address */ 655942c5e3cSpl196000 0xffffffffull, /* high DMA address range */ 656942c5e3cSpl196000 0xffffffffull, /* DMA counter register */ 657942c5e3cSpl196000 AAC_DMA_ALIGN, /* DMA address alignment */ 658942c5e3cSpl196000 1, /* DMA burstsizes */ 659942c5e3cSpl196000 1, /* min effective DMA size */ 660942c5e3cSpl196000 0xffffffffull, /* max DMA xfer size */ 661942c5e3cSpl196000 0xffffffffull, /* segment boundary */ 662942c5e3cSpl196000 1, /* s/g list length */ 663942c5e3cSpl196000 AAC_BLK_SIZE, /* granularity of device */ 66458bc78c7SXin Chen 0 /* DMA transfer flags */ 66558bc78c7SXin Chen }; 66658bc78c7SXin Chen 667942c5e3cSpl196000 static int aac_tick = AAC_DEFAULT_TICK; /* tick for the internal timer */ 668942c5e3cSpl196000 static uint32_t aac_timebase = 0; /* internal timer in seconds */ 669942c5e3cSpl196000 670942c5e3cSpl196000 /* 671942c5e3cSpl196000 * Warlock directives 672942c5e3cSpl196000 * 673942c5e3cSpl196000 * Different variables with the same types have to be protected by the 674942c5e3cSpl196000 * same mutex; otherwise, warlock will complain with "variables don't 675942c5e3cSpl196000 * seem to be protected consistently". For example, 676942c5e3cSpl196000 * aac_softstate::{q_wait, q_comp} are type of aac_cmd_queue, and protected 677942c5e3cSpl196000 * by aac_softstate::{io_lock, q_comp_mutex} respectively. We have to 678942c5e3cSpl196000 * declare them as protected explictly at aac_cmd_dequeue(). 679942c5e3cSpl196000 */ 680942c5e3cSpl196000 _NOTE(SCHEME_PROTECTS_DATA("unique per pkt", scsi_pkt scsi_cdb scsi_status \ 681942c5e3cSpl196000 scsi_arq_status scsi_descr_sense_hdr scsi_information_sense_descr \ 682942c5e3cSpl196000 mode_format mode_geometry mode_header aac_cmd)) 683942c5e3cSpl196000 _NOTE(SCHEME_PROTECTS_DATA("unique per aac_cmd", aac_fib ddi_dma_cookie_t \ 684942c5e3cSpl196000 aac_sge)) 685942c5e3cSpl196000 _NOTE(SCHEME_PROTECTS_DATA("unique per aac_fib", aac_blockread aac_blockwrite \ 686942c5e3cSpl196000 aac_blockread64 aac_raw_io aac_sg_entry aac_sg_entry64 aac_sg_entryraw \ 687942c5e3cSpl196000 aac_sg_table aac_srb)) 688942c5e3cSpl196000 _NOTE(SCHEME_PROTECTS_DATA("unique to sync fib and cdb", scsi_inquiry)) 689942c5e3cSpl196000 _NOTE(SCHEME_PROTECTS_DATA("stable data", scsi_device scsi_address)) 69058bc78c7SXin Chen _NOTE(SCHEME_PROTECTS_DATA("unique to scsi_transport", buf)) 691942c5e3cSpl196000 692942c5e3cSpl196000 int 693942c5e3cSpl196000 _init(void) 694942c5e3cSpl196000 { 695942c5e3cSpl196000 int rval = 0; 696942c5e3cSpl196000 697942c5e3cSpl196000 #ifdef DEBUG 698942c5e3cSpl196000 mutex_init(&aac_prt_mutex, NULL, MUTEX_DRIVER, NULL); 699942c5e3cSpl196000 #endif 700942c5e3cSpl196000 DBCALLED(NULL, 1); 701942c5e3cSpl196000 702942c5e3cSpl196000 if ((rval = ddi_soft_state_init((void *)&aac_softstatep, 703942c5e3cSpl196000 sizeof (struct aac_softstate), 0)) != 0) 704942c5e3cSpl196000 goto error; 705942c5e3cSpl196000 706942c5e3cSpl196000 if ((rval = scsi_hba_init(&aac_modlinkage)) != 0) { 707942c5e3cSpl196000 ddi_soft_state_fini((void *)&aac_softstatep); 708942c5e3cSpl196000 goto error; 709942c5e3cSpl196000 } 710942c5e3cSpl196000 711942c5e3cSpl196000 if ((rval = mod_install(&aac_modlinkage)) != 0) { 712942c5e3cSpl196000 ddi_soft_state_fini((void *)&aac_softstatep); 713942c5e3cSpl196000 scsi_hba_fini(&aac_modlinkage); 714942c5e3cSpl196000 goto error; 715942c5e3cSpl196000 } 716942c5e3cSpl196000 return (rval); 717942c5e3cSpl196000 718942c5e3cSpl196000 error: 719942c5e3cSpl196000 AACDB_PRINT(NULL, CE_WARN, "Mod init error!"); 720942c5e3cSpl196000 #ifdef DEBUG 721942c5e3cSpl196000 mutex_destroy(&aac_prt_mutex); 722942c5e3cSpl196000 #endif 723942c5e3cSpl196000 return (rval); 724942c5e3cSpl196000 } 725942c5e3cSpl196000 726942c5e3cSpl196000 int 727942c5e3cSpl196000 _info(struct modinfo *modinfop) 728942c5e3cSpl196000 { 729942c5e3cSpl196000 DBCALLED(NULL, 1); 730942c5e3cSpl196000 return (mod_info(&aac_modlinkage, modinfop)); 731942c5e3cSpl196000 } 732942c5e3cSpl196000 733942c5e3cSpl196000 /* 734942c5e3cSpl196000 * An HBA driver cannot be unload unless you reboot, 735942c5e3cSpl196000 * so this function will be of no use. 736942c5e3cSpl196000 */ 737942c5e3cSpl196000 int 738942c5e3cSpl196000 _fini(void) 739942c5e3cSpl196000 { 740942c5e3cSpl196000 int rval; 741942c5e3cSpl196000 742942c5e3cSpl196000 DBCALLED(NULL, 1); 743942c5e3cSpl196000 744942c5e3cSpl196000 if ((rval = mod_remove(&aac_modlinkage)) != 0) 745942c5e3cSpl196000 goto error; 746942c5e3cSpl196000 747942c5e3cSpl196000 scsi_hba_fini(&aac_modlinkage); 748942c5e3cSpl196000 ddi_soft_state_fini((void *)&aac_softstatep); 749942c5e3cSpl196000 #ifdef DEBUG 750942c5e3cSpl196000 mutex_destroy(&aac_prt_mutex); 751942c5e3cSpl196000 #endif 752942c5e3cSpl196000 return (0); 753942c5e3cSpl196000 754942c5e3cSpl196000 error: 755942c5e3cSpl196000 AACDB_PRINT(NULL, CE_WARN, "AAC is busy, cannot unload!"); 756942c5e3cSpl196000 return (rval); 757942c5e3cSpl196000 } 758942c5e3cSpl196000 759942c5e3cSpl196000 static int 760942c5e3cSpl196000 aac_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 761942c5e3cSpl196000 { 762942c5e3cSpl196000 int instance, i; 763942c5e3cSpl196000 struct aac_softstate *softs = NULL; 764942c5e3cSpl196000 int attach_state = 0; 76558bc78c7SXin Chen char *data; 766942c5e3cSpl196000 767942c5e3cSpl196000 DBCALLED(NULL, 1); 768942c5e3cSpl196000 769942c5e3cSpl196000 switch (cmd) { 770942c5e3cSpl196000 case DDI_ATTACH: 771942c5e3cSpl196000 break; 772942c5e3cSpl196000 case DDI_RESUME: 773942c5e3cSpl196000 return (DDI_FAILURE); 774942c5e3cSpl196000 default: 775942c5e3cSpl196000 return (DDI_FAILURE); 776942c5e3cSpl196000 } 777942c5e3cSpl196000 778942c5e3cSpl196000 instance = ddi_get_instance(dip); 779942c5e3cSpl196000 780942c5e3cSpl196000 /* Get soft state */ 781942c5e3cSpl196000 if (ddi_soft_state_zalloc(aac_softstatep, instance) != DDI_SUCCESS) { 782942c5e3cSpl196000 AACDB_PRINT(softs, CE_WARN, "Cannot alloc soft state"); 783942c5e3cSpl196000 goto error; 784942c5e3cSpl196000 } 785942c5e3cSpl196000 softs = ddi_get_soft_state(aac_softstatep, instance); 786942c5e3cSpl196000 attach_state |= AAC_ATTACH_SOFTSTATE_ALLOCED; 787942c5e3cSpl196000 788942c5e3cSpl196000 softs->instance = instance; 789942c5e3cSpl196000 softs->devinfo_p = dip; 790942c5e3cSpl196000 softs->buf_dma_attr = softs->addr_dma_attr = aac_dma_attr; 791942c5e3cSpl196000 softs->addr_dma_attr.dma_attr_granular = 1; 79258bc78c7SXin Chen softs->acc_attr = aac_acc_attr; 793837c1ac4SStephen Hanson softs->reg_attr = aac_acc_attr; 794942c5e3cSpl196000 softs->card = AAC_UNKNOWN_CARD; 795942c5e3cSpl196000 #ifdef DEBUG 796942c5e3cSpl196000 softs->debug_flags = aac_debug_flags; 79758bc78c7SXin Chen softs->debug_fib_flags = aac_debug_fib_flags; 798942c5e3cSpl196000 #endif 799942c5e3cSpl196000 80058bc78c7SXin Chen /* Initialize FMA */ 80158bc78c7SXin Chen aac_fm_init(softs); 80258bc78c7SXin Chen 803942c5e3cSpl196000 /* Check the card type */ 804942c5e3cSpl196000 if (aac_check_card_type(softs) == AACERR) { 805942c5e3cSpl196000 AACDB_PRINT(softs, CE_WARN, "Card not supported"); 806942c5e3cSpl196000 goto error; 807942c5e3cSpl196000 } 808942c5e3cSpl196000 /* We have found the right card and everything is OK */ 809942c5e3cSpl196000 attach_state |= AAC_ATTACH_CARD_DETECTED; 810942c5e3cSpl196000 811942c5e3cSpl196000 /* Map PCI mem space */ 812942c5e3cSpl196000 if (ddi_regs_map_setup(dip, 1, 813942c5e3cSpl196000 (caddr_t *)&softs->pci_mem_base_vaddr, 0, 814837c1ac4SStephen Hanson softs->map_size_min, &softs->reg_attr, 815942c5e3cSpl196000 &softs->pci_mem_handle) != DDI_SUCCESS) 816942c5e3cSpl196000 goto error; 817942c5e3cSpl196000 818942c5e3cSpl196000 softs->map_size = softs->map_size_min; 819942c5e3cSpl196000 attach_state |= AAC_ATTACH_PCI_MEM_MAPPED; 820942c5e3cSpl196000 821942c5e3cSpl196000 AAC_DISABLE_INTR(softs); 822942c5e3cSpl196000 823f42c2f53Szhongyan gu - Sun Microsystems - Beijing China /* Init mutexes and condvars */ 8240749e8deSXin Chen - Sun Microsystems - Beijing China mutex_init(&softs->io_lock, NULL, MUTEX_DRIVER, 8250749e8deSXin Chen - Sun Microsystems - Beijing China DDI_INTR_PRI(softs->intr_pri)); 8260749e8deSXin Chen - Sun Microsystems - Beijing China mutex_init(&softs->q_comp_mutex, NULL, MUTEX_DRIVER, 8270749e8deSXin Chen - Sun Microsystems - Beijing China DDI_INTR_PRI(softs->intr_pri)); 8280749e8deSXin Chen - Sun Microsystems - Beijing China mutex_init(&softs->time_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->ev_lock, NULL, MUTEX_DRIVER, 8310749e8deSXin Chen - Sun Microsystems - Beijing China DDI_INTR_PRI(softs->intr_pri)); 8320749e8deSXin Chen - Sun Microsystems - Beijing China mutex_init(&softs->aifq_mutex, NULL, 833b6094a86Sjd218194 MUTEX_DRIVER, DDI_INTR_PRI(softs->intr_pri)); 834942c5e3cSpl196000 cv_init(&softs->event, NULL, CV_DRIVER, NULL); 8351ee13a44SXinChen cv_init(&softs->sync_fib_cv, NULL, CV_DRIVER, NULL); 836942c5e3cSpl196000 cv_init(&softs->drain_cv, NULL, CV_DRIVER, NULL); 8370749e8deSXin Chen - Sun Microsystems - Beijing China cv_init(&softs->event_wait_cv, NULL, CV_DRIVER, NULL); 8380749e8deSXin Chen - Sun Microsystems - Beijing China cv_init(&softs->event_disp_cv, NULL, CV_DRIVER, NULL); 8390749e8deSXin Chen - Sun Microsystems - Beijing China cv_init(&softs->aifq_cv, NULL, CV_DRIVER, NULL); 840942c5e3cSpl196000 attach_state |= AAC_ATTACH_KMUTEX_INITED; 841942c5e3cSpl196000 842f42c2f53Szhongyan gu - Sun Microsystems - Beijing China /* Init the cmd queues */ 843f42c2f53Szhongyan gu - Sun Microsystems - Beijing China for (i = 0; i < AAC_CMDQ_NUM; i++) 844f42c2f53Szhongyan gu - Sun Microsystems - Beijing China aac_cmd_initq(&softs->q_wait[i]); 845f42c2f53Szhongyan gu - Sun Microsystems - Beijing China aac_cmd_initq(&softs->q_busy); 846f42c2f53Szhongyan gu - Sun Microsystems - Beijing China aac_cmd_initq(&softs->q_comp); 847f42c2f53Szhongyan gu - Sun Microsystems - Beijing China 84858bc78c7SXin Chen /* Check for legacy device naming support */ 84958bc78c7SXin Chen softs->legacy = 1; /* default to use legacy name */ 85058bc78c7SXin Chen if ((ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, 0, 85158bc78c7SXin Chen "legacy-name-enable", &data) == DDI_SUCCESS)) { 85258bc78c7SXin Chen if (strcmp(data, "no") == 0) { 85358bc78c7SXin Chen AACDB_PRINT(softs, CE_NOTE, "legacy-name disabled"); 85458bc78c7SXin Chen softs->legacy = 0; 85558bc78c7SXin Chen } 85658bc78c7SXin Chen ddi_prop_free(data); 85758bc78c7SXin Chen } 85858bc78c7SXin Chen 859942c5e3cSpl196000 /* 860942c5e3cSpl196000 * Everything has been set up till now, 861942c5e3cSpl196000 * we will do some common attach. 862942c5e3cSpl196000 */ 863f42c2f53Szhongyan gu - Sun Microsystems - Beijing China mutex_enter(&softs->io_lock); 864f42c2f53Szhongyan gu - Sun Microsystems - Beijing China if (aac_common_attach(softs) == AACERR) { 865f42c2f53Szhongyan gu - Sun Microsystems - Beijing China mutex_exit(&softs->io_lock); 866942c5e3cSpl196000 goto error; 867f42c2f53Szhongyan gu - Sun Microsystems - Beijing China } 868f42c2f53Szhongyan gu - Sun Microsystems - Beijing China mutex_exit(&softs->io_lock); 869942c5e3cSpl196000 attach_state |= AAC_ATTACH_COMM_SPACE_SETUP; 870942c5e3cSpl196000 87172888e72Speng liu - Sun Microsystems - Beijing China /* Check for buf breakup support */ 87272888e72Speng liu - Sun Microsystems - Beijing China if ((ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, 0, 87372888e72Speng liu - Sun Microsystems - Beijing China "breakup-enable", &data) == DDI_SUCCESS)) { 87472888e72Speng liu - Sun Microsystems - Beijing China if (strcmp(data, "yes") == 0) { 87572888e72Speng liu - Sun Microsystems - Beijing China AACDB_PRINT(softs, CE_NOTE, "buf breakup enabled"); 87672888e72Speng liu - Sun Microsystems - Beijing China softs->flags |= AAC_FLAGS_BRKUP; 87772888e72Speng liu - Sun Microsystems - Beijing China } 87872888e72Speng liu - Sun Microsystems - Beijing China ddi_prop_free(data); 87972888e72Speng liu - Sun Microsystems - Beijing China } 88072888e72Speng liu - Sun Microsystems - Beijing China softs->dma_max = softs->buf_dma_attr.dma_attr_maxxfer; 88172888e72Speng liu - Sun Microsystems - Beijing China if (softs->flags & AAC_FLAGS_BRKUP) { 88272888e72Speng liu - Sun Microsystems - Beijing China softs->dma_max = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 88372888e72Speng liu - Sun Microsystems - Beijing China DDI_PROP_DONTPASS, "dma-max", softs->dma_max); 88472888e72Speng liu - Sun Microsystems - Beijing China } 88572888e72Speng liu - Sun Microsystems - Beijing China 886942c5e3cSpl196000 if (aac_hba_setup(softs) != AACOK) 887942c5e3cSpl196000 goto error; 888942c5e3cSpl196000 attach_state |= AAC_ATTACH_SCSI_TRAN_SETUP; 889942c5e3cSpl196000 890942c5e3cSpl196000 /* Create devctl/scsi nodes for cfgadm */ 891942c5e3cSpl196000 if (ddi_create_minor_node(dip, "devctl", S_IFCHR, 892942c5e3cSpl196000 INST2DEVCTL(instance), DDI_NT_SCSI_NEXUS, 0) != DDI_SUCCESS) { 893942c5e3cSpl196000 AACDB_PRINT(softs, CE_WARN, "failed to create devctl node"); 894942c5e3cSpl196000 goto error; 895942c5e3cSpl196000 } 896942c5e3cSpl196000 attach_state |= AAC_ATTACH_CREATE_DEVCTL; 897942c5e3cSpl196000 898942c5e3cSpl196000 if (ddi_create_minor_node(dip, "scsi", S_IFCHR, INST2SCSI(instance), 899942c5e3cSpl196000 DDI_NT_SCSI_ATTACHMENT_POINT, 0) != DDI_SUCCESS) { 900942c5e3cSpl196000 AACDB_PRINT(softs, CE_WARN, "failed to create scsi node"); 901942c5e3cSpl196000 goto error; 902942c5e3cSpl196000 } 903942c5e3cSpl196000 attach_state |= AAC_ATTACH_CREATE_SCSI; 904942c5e3cSpl196000 905942c5e3cSpl196000 /* Create aac node for app. to issue ioctls */ 906942c5e3cSpl196000 if (ddi_create_minor_node(dip, "aac", S_IFCHR, INST2AAC(instance), 907942c5e3cSpl196000 DDI_PSEUDO, 0) != DDI_SUCCESS) { 908942c5e3cSpl196000 AACDB_PRINT(softs, CE_WARN, "failed to create aac node"); 909942c5e3cSpl196000 goto error; 910942c5e3cSpl196000 } 911942c5e3cSpl196000 9120749e8deSXin Chen - Sun Microsystems - Beijing China /* Common attach is OK, so we are attached! */ 9130749e8deSXin Chen - Sun Microsystems - Beijing China softs->state |= AAC_STATE_RUN; 9140749e8deSXin Chen - Sun Microsystems - Beijing China 9150749e8deSXin Chen - Sun Microsystems - Beijing China /* Create event thread */ 9160749e8deSXin Chen - Sun Microsystems - Beijing China softs->fibctx_p = &softs->aifctx; 9170749e8deSXin Chen - Sun Microsystems - Beijing China if ((softs->event_thread = thread_create(NULL, 0, aac_event_thread, 9180749e8deSXin Chen - Sun Microsystems - Beijing China softs, 0, &p0, TS_RUN, minclsyspri)) == NULL) { 9190749e8deSXin Chen - Sun Microsystems - Beijing China AACDB_PRINT(softs, CE_WARN, "aif thread create failed"); 9200749e8deSXin Chen - Sun Microsystems - Beijing China softs->state &= ~AAC_STATE_RUN; 92158bc78c7SXin Chen goto error; 92258bc78c7SXin Chen } 92358bc78c7SXin Chen 924942c5e3cSpl196000 aac_unhold_bus(softs, AAC_IOCMD_SYNC | AAC_IOCMD_ASYNC); 925942c5e3cSpl196000 926942c5e3cSpl196000 /* Create a thread for command timeout */ 9270749e8deSXin Chen - Sun Microsystems - Beijing China softs->timeout_id = timeout(aac_timer, (void *)softs, 9280749e8deSXin Chen - Sun Microsystems - Beijing China (aac_tick * drv_usectohz(1000000))); 929942c5e3cSpl196000 930942c5e3cSpl196000 /* Common attach is OK, so we are attached! */ 931942c5e3cSpl196000 ddi_report_dev(dip); 932942c5e3cSpl196000 AACDB_PRINT(softs, CE_NOTE, "aac attached ok"); 933942c5e3cSpl196000 return (DDI_SUCCESS); 934942c5e3cSpl196000 935942c5e3cSpl196000 error: 936942c5e3cSpl196000 if (attach_state & AAC_ATTACH_CREATE_SCSI) 937942c5e3cSpl196000 ddi_remove_minor_node(dip, "scsi"); 938942c5e3cSpl196000 if (attach_state & AAC_ATTACH_CREATE_DEVCTL) 939942c5e3cSpl196000 ddi_remove_minor_node(dip, "devctl"); 940942c5e3cSpl196000 if (attach_state & AAC_ATTACH_COMM_SPACE_SETUP) 941942c5e3cSpl196000 aac_common_detach(softs); 942942c5e3cSpl196000 if (attach_state & AAC_ATTACH_SCSI_TRAN_SETUP) { 943942c5e3cSpl196000 (void) scsi_hba_detach(dip); 944942c5e3cSpl196000 scsi_hba_tran_free(AAC_DIP2TRAN(dip)); 945942c5e3cSpl196000 } 946942c5e3cSpl196000 if (attach_state & AAC_ATTACH_KMUTEX_INITED) { 9470749e8deSXin Chen - Sun Microsystems - Beijing China mutex_destroy(&softs->io_lock); 948942c5e3cSpl196000 mutex_destroy(&softs->q_comp_mutex); 9490749e8deSXin Chen - Sun Microsystems - Beijing China mutex_destroy(&softs->time_mutex); 9500749e8deSXin Chen - Sun Microsystems - Beijing China mutex_destroy(&softs->ev_lock); 9510749e8deSXin Chen - Sun Microsystems - Beijing China mutex_destroy(&softs->aifq_mutex); 952942c5e3cSpl196000 cv_destroy(&softs->event); 9531ee13a44SXinChen cv_destroy(&softs->sync_fib_cv); 954942c5e3cSpl196000 cv_destroy(&softs->drain_cv); 9550749e8deSXin Chen - Sun Microsystems - Beijing China cv_destroy(&softs->event_wait_cv); 9560749e8deSXin Chen - Sun Microsystems - Beijing China cv_destroy(&softs->event_disp_cv); 9570749e8deSXin Chen - Sun Microsystems - Beijing China cv_destroy(&softs->aifq_cv); 958942c5e3cSpl196000 } 959942c5e3cSpl196000 if (attach_state & AAC_ATTACH_PCI_MEM_MAPPED) 960942c5e3cSpl196000 ddi_regs_map_free(&softs->pci_mem_handle); 961942c5e3cSpl196000 aac_fm_fini(softs); 962942c5e3cSpl196000 if (attach_state & AAC_ATTACH_CARD_DETECTED) 963942c5e3cSpl196000 softs->card = AACERR; 964942c5e3cSpl196000 if (attach_state & AAC_ATTACH_SOFTSTATE_ALLOCED) 965942c5e3cSpl196000 ddi_soft_state_free(aac_softstatep, instance); 966942c5e3cSpl196000 return (DDI_FAILURE); 967942c5e3cSpl196000 } 968942c5e3cSpl196000 969942c5e3cSpl196000 static int 970942c5e3cSpl196000 aac_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 971942c5e3cSpl196000 { 972942c5e3cSpl196000 scsi_hba_tran_t *tran = AAC_DIP2TRAN(dip); 973942c5e3cSpl196000 struct aac_softstate *softs = AAC_TRAN2SOFTS(tran); 974942c5e3cSpl196000 975942c5e3cSpl196000 DBCALLED(softs, 1); 976942c5e3cSpl196000 977942c5e3cSpl196000 switch (cmd) { 978942c5e3cSpl196000 case DDI_DETACH: 979942c5e3cSpl196000 break; 980942c5e3cSpl196000 case DDI_SUSPEND: 981942c5e3cSpl196000 return (DDI_FAILURE); 982942c5e3cSpl196000 default: 983942c5e3cSpl196000 return (DDI_FAILURE); 984942c5e3cSpl196000 } 985942c5e3cSpl196000 986942c5e3cSpl196000 mutex_enter(&softs->io_lock); 987942c5e3cSpl196000 AAC_DISABLE_INTR(softs); 988942c5e3cSpl196000 softs->state = AAC_STATE_STOPPED; 989942c5e3cSpl196000 990942c5e3cSpl196000 ddi_remove_minor_node(dip, "aac"); 991942c5e3cSpl196000 ddi_remove_minor_node(dip, "scsi"); 992942c5e3cSpl196000 ddi_remove_minor_node(dip, "devctl"); 993942c5e3cSpl196000 mutex_exit(&softs->io_lock); 994942c5e3cSpl196000 995942c5e3cSpl196000 aac_common_detach(softs); 996942c5e3cSpl196000 997f42c2f53Szhongyan gu - Sun Microsystems - Beijing China mutex_enter(&softs->io_lock); 998942c5e3cSpl196000 (void) scsi_hba_detach(dip); 999942c5e3cSpl196000 scsi_hba_tran_free(tran); 1000f42c2f53Szhongyan gu - Sun Microsystems - Beijing China mutex_exit(&softs->io_lock); 1001942c5e3cSpl196000 10020749e8deSXin Chen - Sun Microsystems - Beijing China /* Stop timer */ 10030749e8deSXin Chen - Sun Microsystems - Beijing China mutex_enter(&softs->time_mutex); 10040749e8deSXin Chen - Sun Microsystems - Beijing China if (softs->timeout_id) { 10050749e8deSXin Chen - Sun Microsystems - Beijing China timeout_id_t tid = softs->timeout_id; 10060749e8deSXin Chen - Sun Microsystems - Beijing China softs->timeout_id = 0; 10070749e8deSXin Chen - Sun Microsystems - Beijing China 10080749e8deSXin Chen - Sun Microsystems - Beijing China mutex_exit(&softs->time_mutex); 10090749e8deSXin Chen - Sun Microsystems - Beijing China (void) untimeout(tid); 10100749e8deSXin Chen - Sun Microsystems - Beijing China mutex_enter(&softs->time_mutex); 10110749e8deSXin Chen - Sun Microsystems - Beijing China } 10120749e8deSXin Chen - Sun Microsystems - Beijing China mutex_exit(&softs->time_mutex); 10130749e8deSXin Chen - Sun Microsystems - Beijing China 10140749e8deSXin Chen - Sun Microsystems - Beijing China /* Destroy event thread */ 10150749e8deSXin Chen - Sun Microsystems - Beijing China mutex_enter(&softs->ev_lock); 10160749e8deSXin Chen - Sun Microsystems - Beijing China cv_signal(&softs->event_disp_cv); 10170749e8deSXin Chen - Sun Microsystems - Beijing China cv_wait(&softs->event_wait_cv, &softs->ev_lock); 10180749e8deSXin Chen - Sun Microsystems - Beijing China mutex_exit(&softs->ev_lock); 10190749e8deSXin Chen - Sun Microsystems - Beijing China 10200749e8deSXin Chen - Sun Microsystems - Beijing China cv_destroy(&softs->aifq_cv); 10210749e8deSXin Chen - Sun Microsystems - Beijing China cv_destroy(&softs->event_disp_cv); 10220749e8deSXin Chen - Sun Microsystems - Beijing China cv_destroy(&softs->event_wait_cv); 1023942c5e3cSpl196000 cv_destroy(&softs->drain_cv); 10240749e8deSXin Chen - Sun Microsystems - Beijing China cv_destroy(&softs->sync_fib_cv); 10250749e8deSXin Chen - Sun Microsystems - Beijing China cv_destroy(&softs->event); 10260749e8deSXin Chen - Sun Microsystems - Beijing China mutex_destroy(&softs->aifq_mutex); 10270749e8deSXin Chen - Sun Microsystems - Beijing China mutex_destroy(&softs->ev_lock); 10280749e8deSXin Chen - Sun Microsystems - Beijing China mutex_destroy(&softs->time_mutex); 10290749e8deSXin Chen - Sun Microsystems - Beijing China mutex_destroy(&softs->q_comp_mutex); 1030942c5e3cSpl196000 mutex_destroy(&softs->io_lock); 1031942c5e3cSpl196000 1032942c5e3cSpl196000 ddi_regs_map_free(&softs->pci_mem_handle); 1033942c5e3cSpl196000 aac_fm_fini(softs); 1034942c5e3cSpl196000 softs->hwif = AAC_HWIF_UNKNOWN; 1035942c5e3cSpl196000 softs->card = AAC_UNKNOWN_CARD; 1036942c5e3cSpl196000 ddi_soft_state_free(aac_softstatep, ddi_get_instance(dip)); 1037942c5e3cSpl196000 1038942c5e3cSpl196000 return (DDI_SUCCESS); 1039942c5e3cSpl196000 } 1040942c5e3cSpl196000 1041942c5e3cSpl196000 /*ARGSUSED*/ 1042942c5e3cSpl196000 static int 1043942c5e3cSpl196000 aac_reset(dev_info_t *dip, ddi_reset_cmd_t cmd) 1044942c5e3cSpl196000 { 1045942c5e3cSpl196000 struct aac_softstate *softs = AAC_DIP2SOFTS(dip); 1046942c5e3cSpl196000 1047942c5e3cSpl196000 DBCALLED(softs, 1); 1048942c5e3cSpl196000 1049942c5e3cSpl196000 mutex_enter(&softs->io_lock); 10501ee13a44SXinChen AAC_DISABLE_INTR(softs); 1051942c5e3cSpl196000 (void) aac_shutdown(softs); 1052942c5e3cSpl196000 mutex_exit(&softs->io_lock); 1053942c5e3cSpl196000 1054942c5e3cSpl196000 return (DDI_SUCCESS); 1055942c5e3cSpl196000 } 1056942c5e3cSpl196000 1057942c5e3cSpl196000 /* 105819397407SSherry Moore * quiesce(9E) entry point. 105919397407SSherry Moore * 106019397407SSherry Moore * This function is called when the system is single-threaded at high 106119397407SSherry Moore * PIL with preemption disabled. Therefore, this function must not be 106219397407SSherry Moore * blocked. 106319397407SSherry Moore * 106419397407SSherry Moore * This function returns DDI_SUCCESS on success, or DDI_FAILURE on failure. 106519397407SSherry Moore * DDI_FAILURE indicates an error condition and should almost never happen. 106619397407SSherry Moore */ 106719397407SSherry Moore static int 106819397407SSherry Moore aac_quiesce(dev_info_t *dip) 106919397407SSherry Moore { 107019397407SSherry Moore struct aac_softstate *softs = AAC_DIP2SOFTS(dip); 107119397407SSherry Moore 107219397407SSherry Moore if (softs == NULL) 107319397407SSherry Moore return (DDI_FAILURE); 107419397407SSherry Moore 10750749e8deSXin Chen - Sun Microsystems - Beijing China _NOTE(ASSUMING_PROTECTED(softs->state)) 107619397407SSherry Moore AAC_DISABLE_INTR(softs); 107719397407SSherry Moore 107819397407SSherry Moore return (DDI_SUCCESS); 107919397407SSherry Moore } 108019397407SSherry Moore 1081f42c2f53Szhongyan gu - Sun Microsystems - Beijing China /* ARGSUSED */ 1082f42c2f53Szhongyan gu - Sun Microsystems - Beijing China static int 1083f42c2f53Szhongyan gu - Sun Microsystems - Beijing China aac_getinfo(dev_info_t *self, ddi_info_cmd_t infocmd, void *arg, 1084f42c2f53Szhongyan gu - Sun Microsystems - Beijing China void **result) 1085f42c2f53Szhongyan gu - Sun Microsystems - Beijing China { 1086f42c2f53Szhongyan gu - Sun Microsystems - Beijing China int error = DDI_SUCCESS; 1087f42c2f53Szhongyan gu - Sun Microsystems - Beijing China 1088f42c2f53Szhongyan gu - Sun Microsystems - Beijing China switch (infocmd) { 1089f42c2f53Szhongyan gu - Sun Microsystems - Beijing China case DDI_INFO_DEVT2INSTANCE: 1090f42c2f53Szhongyan gu - Sun Microsystems - Beijing China *result = (void *)(intptr_t)(MINOR2INST(getminor((dev_t)arg))); 1091f42c2f53Szhongyan gu - Sun Microsystems - Beijing China break; 1092f42c2f53Szhongyan gu - Sun Microsystems - Beijing China default: 1093f42c2f53Szhongyan gu - Sun Microsystems - Beijing China error = DDI_FAILURE; 1094f42c2f53Szhongyan gu - Sun Microsystems - Beijing China } 1095f42c2f53Szhongyan gu - Sun Microsystems - Beijing China return (error); 1096f42c2f53Szhongyan gu - Sun Microsystems - Beijing China } 1097f42c2f53Szhongyan gu - Sun Microsystems - Beijing China 109819397407SSherry Moore /* 1099942c5e3cSpl196000 * Bring the controller down to a dormant state and detach all child devices. 1100942c5e3cSpl196000 * This function is called before detach or system shutdown. 1101942c5e3cSpl196000 * Note: we can assume that the q_wait on the controller is empty, as we 1102942c5e3cSpl196000 * won't allow shutdown if any device is open. 1103942c5e3cSpl196000 */ 1104942c5e3cSpl196000 static int 1105942c5e3cSpl196000 aac_shutdown(struct aac_softstate *softs) 1106942c5e3cSpl196000 { 1107f42c2f53Szhongyan gu - Sun Microsystems - Beijing China ddi_acc_handle_t acc; 1108f42c2f53Szhongyan gu - Sun Microsystems - Beijing China struct aac_close_command *cc; 1109942c5e3cSpl196000 int rval; 1110942c5e3cSpl196000 1111f42c2f53Szhongyan gu - Sun Microsystems - Beijing China (void) aac_sync_fib_slot_bind(softs, &softs->sync_ac); 1112f42c2f53Szhongyan gu - Sun Microsystems - Beijing China acc = softs->sync_ac.slotp->fib_acc_handle; 1113f42c2f53Szhongyan gu - Sun Microsystems - Beijing China 1114f42c2f53Szhongyan gu - Sun Microsystems - Beijing China cc = (struct aac_close_command *)&softs->sync_ac.slotp->fibp->data[0]; 1115f42c2f53Szhongyan gu - Sun Microsystems - Beijing China 1116942c5e3cSpl196000 ddi_put32(acc, &cc->Command, VM_CloseAll); 1117942c5e3cSpl196000 ddi_put32(acc, &cc->ContainerId, 0xfffffffful); 1118942c5e3cSpl196000 1119942c5e3cSpl196000 /* Flush all caches, set FW to write through mode */ 1120942c5e3cSpl196000 rval = aac_sync_fib(softs, ContainerCommand, 1121942c5e3cSpl196000 AAC_FIB_SIZEOF(struct aac_close_command)); 1122f42c2f53Szhongyan gu - Sun Microsystems - Beijing China aac_sync_fib_slot_release(softs, &softs->sync_ac); 1123942c5e3cSpl196000 1124942c5e3cSpl196000 AACDB_PRINT(softs, CE_NOTE, 1125942c5e3cSpl196000 "shutting down aac %s", (rval == AACOK) ? "ok" : "fail"); 1126942c5e3cSpl196000 return (rval); 1127942c5e3cSpl196000 } 1128942c5e3cSpl196000 1129942c5e3cSpl196000 static uint_t 1130942c5e3cSpl196000 aac_softintr(caddr_t arg) 1131942c5e3cSpl196000 { 1132a74f7440Spl196000 struct aac_softstate *softs = (void *)arg; 1133942c5e3cSpl196000 1134942c5e3cSpl196000 if (!AAC_IS_Q_EMPTY(&softs->q_comp)) { 1135942c5e3cSpl196000 aac_drain_comp_q(softs); 1136942c5e3cSpl196000 } 1137f42c2f53Szhongyan gu - Sun Microsystems - Beijing China return (DDI_INTR_CLAIMED); 1138942c5e3cSpl196000 } 1139942c5e3cSpl196000 1140942c5e3cSpl196000 /* 1141942c5e3cSpl196000 * Setup auto sense data for pkt 1142942c5e3cSpl196000 */ 1143942c5e3cSpl196000 static void 1144942c5e3cSpl196000 aac_set_arq_data(struct scsi_pkt *pkt, uchar_t key, 1145942c5e3cSpl196000 uchar_t add_code, uchar_t qual_code, uint64_t info) 1146942c5e3cSpl196000 { 114758bc78c7SXin Chen struct scsi_arq_status *arqstat = (void *)(pkt->pkt_scbp); 1148942c5e3cSpl196000 114958bc78c7SXin Chen *pkt->pkt_scbp = STATUS_CHECK; /* CHECK CONDITION */ 115058bc78c7SXin Chen pkt->pkt_state |= STATE_ARQ_DONE; 1151942c5e3cSpl196000 115258bc78c7SXin Chen *(uint8_t *)&arqstat->sts_rqpkt_status = STATUS_GOOD; 1153942c5e3cSpl196000 arqstat->sts_rqpkt_reason = CMD_CMPLT; 1154942c5e3cSpl196000 arqstat->sts_rqpkt_resid = 0; 1155942c5e3cSpl196000 arqstat->sts_rqpkt_state = 1156942c5e3cSpl196000 STATE_GOT_BUS | 1157942c5e3cSpl196000 STATE_GOT_TARGET | 1158942c5e3cSpl196000 STATE_SENT_CMD | 1159942c5e3cSpl196000 STATE_XFERRED_DATA; 1160942c5e3cSpl196000 arqstat->sts_rqpkt_statistics = 0; 1161942c5e3cSpl196000 1162942c5e3cSpl196000 if (info <= 0xfffffffful) { 1163942c5e3cSpl196000 arqstat->sts_sensedata.es_valid = 1; 1164942c5e3cSpl196000 arqstat->sts_sensedata.es_class = CLASS_EXTENDED_SENSE; 1165942c5e3cSpl196000 arqstat->sts_sensedata.es_code = CODE_FMT_FIXED_CURRENT; 1166942c5e3cSpl196000 arqstat->sts_sensedata.es_key = key; 1167942c5e3cSpl196000 arqstat->sts_sensedata.es_add_code = add_code; 1168942c5e3cSpl196000 arqstat->sts_sensedata.es_qual_code = qual_code; 1169942c5e3cSpl196000 1170942c5e3cSpl196000 arqstat->sts_sensedata.es_info_1 = (info >> 24) & 0xFF; 1171942c5e3cSpl196000 arqstat->sts_sensedata.es_info_2 = (info >> 16) & 0xFF; 1172942c5e3cSpl196000 arqstat->sts_sensedata.es_info_3 = (info >> 8) & 0xFF; 1173942c5e3cSpl196000 arqstat->sts_sensedata.es_info_4 = info & 0xFF; 1174942c5e3cSpl196000 } else { /* 64-bit LBA */ 1175942c5e3cSpl196000 struct scsi_descr_sense_hdr *dsp; 1176942c5e3cSpl196000 struct scsi_information_sense_descr *isd; 1177942c5e3cSpl196000 1178942c5e3cSpl196000 dsp = (struct scsi_descr_sense_hdr *)&arqstat->sts_sensedata; 1179942c5e3cSpl196000 dsp->ds_class = CLASS_EXTENDED_SENSE; 1180942c5e3cSpl196000 dsp->ds_code = CODE_FMT_DESCR_CURRENT; 1181942c5e3cSpl196000 dsp->ds_key = key; 1182942c5e3cSpl196000 dsp->ds_add_code = add_code; 1183942c5e3cSpl196000 dsp->ds_qual_code = qual_code; 1184942c5e3cSpl196000 dsp->ds_addl_sense_length = 1185942c5e3cSpl196000 sizeof (struct scsi_information_sense_descr); 1186942c5e3cSpl196000 1187942c5e3cSpl196000 isd = (struct scsi_information_sense_descr *)(dsp+1); 1188942c5e3cSpl196000 isd->isd_descr_type = DESCR_INFORMATION; 1189942c5e3cSpl196000 isd->isd_valid = 1; 1190942c5e3cSpl196000 isd->isd_information[0] = (info >> 56) & 0xFF; 1191942c5e3cSpl196000 isd->isd_information[1] = (info >> 48) & 0xFF; 1192942c5e3cSpl196000 isd->isd_information[2] = (info >> 40) & 0xFF; 1193942c5e3cSpl196000 isd->isd_information[3] = (info >> 32) & 0xFF; 1194942c5e3cSpl196000 isd->isd_information[4] = (info >> 24) & 0xFF; 1195942c5e3cSpl196000 isd->isd_information[5] = (info >> 16) & 0xFF; 1196942c5e3cSpl196000 isd->isd_information[6] = (info >> 8) & 0xFF; 1197942c5e3cSpl196000 isd->isd_information[7] = (info) & 0xFF; 1198942c5e3cSpl196000 } 1199942c5e3cSpl196000 } 1200942c5e3cSpl196000 1201942c5e3cSpl196000 /* 1202942c5e3cSpl196000 * Setup auto sense data for HARDWARE ERROR 1203942c5e3cSpl196000 */ 1204942c5e3cSpl196000 static void 1205942c5e3cSpl196000 aac_set_arq_data_hwerr(struct aac_cmd *acp) 1206942c5e3cSpl196000 { 1207942c5e3cSpl196000 union scsi_cdb *cdbp; 1208942c5e3cSpl196000 uint64_t err_blkno; 1209942c5e3cSpl196000 1210a74f7440Spl196000 cdbp = (void *)acp->pkt->pkt_cdbp; 1211942c5e3cSpl196000 err_blkno = AAC_GETGXADDR(acp->cmdlen, cdbp); 1212942c5e3cSpl196000 aac_set_arq_data(acp->pkt, KEY_HARDWARE_ERROR, 0x00, 0x00, err_blkno); 1213942c5e3cSpl196000 } 1214942c5e3cSpl196000 1215942c5e3cSpl196000 /* 1216942c5e3cSpl196000 * Send a command to the adapter in New Comm. interface 1217942c5e3cSpl196000 */ 1218942c5e3cSpl196000 static int 1219942c5e3cSpl196000 aac_send_command(struct aac_softstate *softs, struct aac_slot *slotp) 1220942c5e3cSpl196000 { 1221942c5e3cSpl196000 uint32_t index, device; 1222942c5e3cSpl196000 1223942c5e3cSpl196000 index = PCI_MEM_GET32(softs, AAC_IQUE); 1224942c5e3cSpl196000 if (index == 0xffffffffUL) { 1225942c5e3cSpl196000 index = PCI_MEM_GET32(softs, AAC_IQUE); 1226942c5e3cSpl196000 if (index == 0xffffffffUL) 1227942c5e3cSpl196000 return (AACERR); 1228942c5e3cSpl196000 } 1229942c5e3cSpl196000 1230942c5e3cSpl196000 device = index; 1231942c5e3cSpl196000 PCI_MEM_PUT32(softs, device, 1232942c5e3cSpl196000 (uint32_t)(slotp->fib_phyaddr & 0xfffffffful)); 1233942c5e3cSpl196000 device += 4; 1234942c5e3cSpl196000 PCI_MEM_PUT32(softs, device, (uint32_t)(slotp->fib_phyaddr >> 32)); 1235942c5e3cSpl196000 device += 4; 1236942c5e3cSpl196000 PCI_MEM_PUT32(softs, device, slotp->acp->fib_size); 1237942c5e3cSpl196000 PCI_MEM_PUT32(softs, AAC_IQUE, index); 1238942c5e3cSpl196000 return (AACOK); 1239942c5e3cSpl196000 } 1240942c5e3cSpl196000 1241942c5e3cSpl196000 static void 1242942c5e3cSpl196000 aac_end_io(struct aac_softstate *softs, struct aac_cmd *acp) 1243942c5e3cSpl196000 { 124458bc78c7SXin Chen struct aac_device *dvp = acp->dvp; 1245942c5e3cSpl196000 int q = AAC_CMDQ(acp); 1246942c5e3cSpl196000 1247942c5e3cSpl196000 if (acp->slotp) { /* outstanding cmd */ 1248f42c2f53Szhongyan gu - Sun Microsystems - Beijing China if (!(acp->flags & AAC_CMD_IN_SYNC_SLOT)) { 1249942c5e3cSpl196000 aac_release_slot(softs, acp->slotp); 1250942c5e3cSpl196000 acp->slotp = NULL; 1251f42c2f53Szhongyan gu - Sun Microsystems - Beijing China } 1252942c5e3cSpl196000 if (dvp) { 1253942c5e3cSpl196000 dvp->ncmds[q]--; 1254942c5e3cSpl196000 if (dvp->throttle[q] == AAC_THROTTLE_DRAIN && 1255942c5e3cSpl196000 dvp->ncmds[q] == 0 && q == AAC_CMDQ_ASYNC) 1256942c5e3cSpl196000 aac_set_throttle(softs, dvp, q, 1257942c5e3cSpl196000 softs->total_slots); 1258f42c2f53Szhongyan gu - Sun Microsystems - Beijing China /* 1259f42c2f53Szhongyan gu - Sun Microsystems - Beijing China * Setup auto sense data for UNIT ATTENTION 1260f42c2f53Szhongyan gu - Sun Microsystems - Beijing China * Each lun should generate a unit attention 1261f42c2f53Szhongyan gu - Sun Microsystems - Beijing China * condition when reset. 1262f42c2f53Szhongyan gu - Sun Microsystems - Beijing China * Phys. drives are treated as logical ones 1263f42c2f53Szhongyan gu - Sun Microsystems - Beijing China * during error recovery. 1264f42c2f53Szhongyan gu - Sun Microsystems - Beijing China */ 1265f42c2f53Szhongyan gu - Sun Microsystems - Beijing China if (dvp->type == AAC_DEV_LD) { 1266f42c2f53Szhongyan gu - Sun Microsystems - Beijing China struct aac_container *ctp = 1267f42c2f53Szhongyan gu - Sun Microsystems - Beijing China (struct aac_container *)dvp; 1268f42c2f53Szhongyan gu - Sun Microsystems - Beijing China if (ctp->reset == 0) 1269f42c2f53Szhongyan gu - Sun Microsystems - Beijing China goto noreset; 1270f42c2f53Szhongyan gu - Sun Microsystems - Beijing China 1271f42c2f53Szhongyan gu - Sun Microsystems - Beijing China AACDB_PRINT(softs, CE_NOTE, 1272f42c2f53Szhongyan gu - Sun Microsystems - Beijing China "Unit attention: reset"); 1273f42c2f53Szhongyan gu - Sun Microsystems - Beijing China ctp->reset = 0; 1274f42c2f53Szhongyan gu - Sun Microsystems - Beijing China aac_set_arq_data(acp->pkt, KEY_UNIT_ATTENTION, 1275f42c2f53Szhongyan gu - Sun Microsystems - Beijing China 0x29, 0x02, 0); 1276942c5e3cSpl196000 } 1277f42c2f53Szhongyan gu - Sun Microsystems - Beijing China } 1278f42c2f53Szhongyan gu - Sun Microsystems - Beijing China noreset: 1279942c5e3cSpl196000 softs->bus_ncmds[q]--; 1280f42c2f53Szhongyan gu - Sun Microsystems - Beijing China aac_cmd_delete(&softs->q_busy, acp); 1281942c5e3cSpl196000 } else { /* cmd in waiting queue */ 1282942c5e3cSpl196000 aac_cmd_delete(&softs->q_wait[q], acp); 1283942c5e3cSpl196000 } 1284942c5e3cSpl196000 1285942c5e3cSpl196000 if (!(acp->flags & (AAC_CMD_NO_CB | AAC_CMD_NO_INTR))) { /* async IO */ 1286942c5e3cSpl196000 mutex_enter(&softs->q_comp_mutex); 1287942c5e3cSpl196000 aac_cmd_enqueue(&softs->q_comp, acp); 1288942c5e3cSpl196000 mutex_exit(&softs->q_comp_mutex); 1289942c5e3cSpl196000 } else if (acp->flags & AAC_CMD_NO_CB) { /* sync IO */ 1290942c5e3cSpl196000 cv_broadcast(&softs->event); 1291942c5e3cSpl196000 } 1292942c5e3cSpl196000 } 1293942c5e3cSpl196000 1294942c5e3cSpl196000 static void 1295942c5e3cSpl196000 aac_handle_io(struct aac_softstate *softs, int index) 1296942c5e3cSpl196000 { 1297942c5e3cSpl196000 struct aac_slot *slotp; 1298942c5e3cSpl196000 struct aac_cmd *acp; 1299942c5e3cSpl196000 uint32_t fast; 1300942c5e3cSpl196000 1301942c5e3cSpl196000 fast = index & AAC_SENDERADDR_MASK_FAST_RESPONSE; 1302942c5e3cSpl196000 index >>= 2; 1303942c5e3cSpl196000 1304942c5e3cSpl196000 /* Make sure firmware reported index is valid */ 1305942c5e3cSpl196000 ASSERT(index >= 0 && index < softs->total_slots); 1306942c5e3cSpl196000 slotp = &softs->io_slot[index]; 1307942c5e3cSpl196000 ASSERT(slotp->index == index); 1308942c5e3cSpl196000 acp = slotp->acp; 130958bc78c7SXin Chen 131058bc78c7SXin Chen if (acp == NULL || acp->slotp != slotp) { 131158bc78c7SXin Chen cmn_err(CE_WARN, 131258bc78c7SXin Chen "Firmware error: invalid slot index received from FW"); 131358bc78c7SXin Chen return; 131458bc78c7SXin Chen } 1315942c5e3cSpl196000 1316942c5e3cSpl196000 acp->flags |= AAC_CMD_CMPLT; 1317942c5e3cSpl196000 (void) ddi_dma_sync(slotp->fib_dma_handle, 0, 0, DDI_DMA_SYNC_FORCPU); 1318942c5e3cSpl196000 1319942c5e3cSpl196000 if (aac_check_dma_handle(slotp->fib_dma_handle) == DDI_SUCCESS) { 1320942c5e3cSpl196000 /* 1321942c5e3cSpl196000 * For fast response IO, the firmware do not return any FIB 1322942c5e3cSpl196000 * data, so we need to fill in the FIB status and state so that 1323942c5e3cSpl196000 * FIB users can handle it correctly. 1324942c5e3cSpl196000 */ 1325942c5e3cSpl196000 if (fast) { 1326942c5e3cSpl196000 uint32_t state; 1327942c5e3cSpl196000 1328942c5e3cSpl196000 state = ddi_get32(slotp->fib_acc_handle, 1329942c5e3cSpl196000 &slotp->fibp->Header.XferState); 1330942c5e3cSpl196000 /* 1331942c5e3cSpl196000 * Update state for CPU not for device, no DMA sync 1332942c5e3cSpl196000 * needed 1333942c5e3cSpl196000 */ 1334942c5e3cSpl196000 ddi_put32(slotp->fib_acc_handle, 1335942c5e3cSpl196000 &slotp->fibp->Header.XferState, 1336942c5e3cSpl196000 state | AAC_FIBSTATE_DONEADAP); 1337942c5e3cSpl196000 ddi_put32(slotp->fib_acc_handle, 1338a74f7440Spl196000 (void *)&slotp->fibp->data[0], ST_OK); 1339942c5e3cSpl196000 } 1340942c5e3cSpl196000 1341942c5e3cSpl196000 /* Handle completed ac */ 1342942c5e3cSpl196000 acp->ac_comp(softs, acp); 1343942c5e3cSpl196000 } else { 1344942c5e3cSpl196000 ddi_fm_service_impact(softs->devinfo_p, DDI_SERVICE_UNAFFECTED); 1345942c5e3cSpl196000 acp->flags |= AAC_CMD_ERR; 1346942c5e3cSpl196000 if (acp->pkt) { 1347942c5e3cSpl196000 acp->pkt->pkt_reason = CMD_TRAN_ERR; 1348942c5e3cSpl196000 acp->pkt->pkt_statistics = 0; 1349942c5e3cSpl196000 } 1350942c5e3cSpl196000 } 1351942c5e3cSpl196000 aac_end_io(softs, acp); 1352942c5e3cSpl196000 } 1353942c5e3cSpl196000 1354942c5e3cSpl196000 /* 1355942c5e3cSpl196000 * Interrupt handler for New Comm. interface 1356942c5e3cSpl196000 * New Comm. interface use a different mechanism for interrupt. No explict 1357942c5e3cSpl196000 * message queues, and driver need only accesses the mapped PCI mem space to 1358942c5e3cSpl196000 * find the completed FIB or AIF. 1359942c5e3cSpl196000 */ 1360942c5e3cSpl196000 static int 1361942c5e3cSpl196000 aac_process_intr_new(struct aac_softstate *softs) 1362942c5e3cSpl196000 { 1363942c5e3cSpl196000 uint32_t index; 1364942c5e3cSpl196000 1365942c5e3cSpl196000 index = AAC_OUTB_GET(softs); 1366942c5e3cSpl196000 if (index == 0xfffffffful) 1367942c5e3cSpl196000 index = AAC_OUTB_GET(softs); 1368942c5e3cSpl196000 if (aac_check_acc_handle(softs->pci_mem_handle) != DDI_SUCCESS) { 1369942c5e3cSpl196000 ddi_fm_service_impact(softs->devinfo_p, DDI_SERVICE_UNAFFECTED); 137058bc78c7SXin Chen return (0); 1371942c5e3cSpl196000 } 1372942c5e3cSpl196000 if (index != 0xfffffffful) { 1373942c5e3cSpl196000 do { 1374942c5e3cSpl196000 if ((index & AAC_SENDERADDR_MASK_AIF) == 0) { 1375942c5e3cSpl196000 aac_handle_io(softs, index); 1376942c5e3cSpl196000 } else if (index != 0xfffffffeul) { 1377942c5e3cSpl196000 struct aac_fib *fibp; /* FIB in AIF queue */ 13780749e8deSXin Chen - Sun Microsystems - Beijing China uint16_t fib_size; 1379942c5e3cSpl196000 1380942c5e3cSpl196000 /* 1381942c5e3cSpl196000 * 0xfffffffe means that the controller wants 1382942c5e3cSpl196000 * more work, ignore it for now. Otherwise, 1383942c5e3cSpl196000 * AIF received. 1384942c5e3cSpl196000 */ 1385942c5e3cSpl196000 index &= ~2; 1386942c5e3cSpl196000 13870749e8deSXin Chen - Sun Microsystems - Beijing China fibp = (struct aac_fib *)(softs-> \ 13880749e8deSXin Chen - Sun Microsystems - Beijing China pci_mem_base_vaddr + index); 13890749e8deSXin Chen - Sun Microsystems - Beijing China fib_size = PCI_MEM_GET16(softs, index + \ 1390942c5e3cSpl196000 offsetof(struct aac_fib, Header.Size)); 1391942c5e3cSpl196000 13920749e8deSXin Chen - Sun Microsystems - Beijing China aac_save_aif(softs, softs->pci_mem_handle, 13930749e8deSXin Chen - Sun Microsystems - Beijing China fibp, fib_size); 1394942c5e3cSpl196000 1395942c5e3cSpl196000 /* 1396942c5e3cSpl196000 * AIF memory is owned by the adapter, so let it 1397942c5e3cSpl196000 * know that we are done with it. 1398942c5e3cSpl196000 */ 1399942c5e3cSpl196000 AAC_OUTB_SET(softs, index); 1400942c5e3cSpl196000 AAC_STATUS_CLR(softs, AAC_DB_RESPONSE_READY); 1401942c5e3cSpl196000 } 1402942c5e3cSpl196000 1403942c5e3cSpl196000 index = AAC_OUTB_GET(softs); 1404942c5e3cSpl196000 } while (index != 0xfffffffful); 1405942c5e3cSpl196000 1406942c5e3cSpl196000 /* 1407942c5e3cSpl196000 * Process waiting cmds before start new ones to 1408942c5e3cSpl196000 * ensure first IOs are serviced first. 1409942c5e3cSpl196000 */ 1410942c5e3cSpl196000 aac_start_waiting_io(softs); 1411942c5e3cSpl196000 return (AAC_DB_COMMAND_READY); 1412942c5e3cSpl196000 } else { 1413942c5e3cSpl196000 return (0); 1414942c5e3cSpl196000 } 1415942c5e3cSpl196000 } 1416942c5e3cSpl196000 1417942c5e3cSpl196000 static uint_t 1418942c5e3cSpl196000 aac_intr_new(caddr_t arg) 1419942c5e3cSpl196000 { 1420a74f7440Spl196000 struct aac_softstate *softs = (void *)arg; 1421942c5e3cSpl196000 uint_t rval; 1422942c5e3cSpl196000 1423942c5e3cSpl196000 mutex_enter(&softs->io_lock); 1424942c5e3cSpl196000 if (aac_process_intr_new(softs)) 1425942c5e3cSpl196000 rval = DDI_INTR_CLAIMED; 1426942c5e3cSpl196000 else 1427942c5e3cSpl196000 rval = DDI_INTR_UNCLAIMED; 1428942c5e3cSpl196000 mutex_exit(&softs->io_lock); 1429942c5e3cSpl196000 1430942c5e3cSpl196000 aac_drain_comp_q(softs); 1431942c5e3cSpl196000 return (rval); 1432942c5e3cSpl196000 } 1433942c5e3cSpl196000 1434942c5e3cSpl196000 /* 1435942c5e3cSpl196000 * Interrupt handler for old interface 1436942c5e3cSpl196000 * Explicit message queues are used to send FIB to and get completed FIB from 1437942c5e3cSpl196000 * the adapter. Driver and adapter maitain the queues in the producer/consumer 1438942c5e3cSpl196000 * manner. The driver has to query the queues to find the completed FIB. 1439942c5e3cSpl196000 */ 1440942c5e3cSpl196000 static int 1441942c5e3cSpl196000 aac_process_intr_old(struct aac_softstate *softs) 1442942c5e3cSpl196000 { 1443942c5e3cSpl196000 uint16_t status; 1444942c5e3cSpl196000 1445942c5e3cSpl196000 status = AAC_STATUS_GET(softs); 1446942c5e3cSpl196000 if (aac_check_acc_handle(softs->pci_mem_handle) != DDI_SUCCESS) { 1447942c5e3cSpl196000 ddi_fm_service_impact(softs->devinfo_p, DDI_SERVICE_UNAFFECTED); 1448942c5e3cSpl196000 return (DDI_INTR_UNCLAIMED); 1449942c5e3cSpl196000 } 1450942c5e3cSpl196000 if (status & AAC_DB_RESPONSE_READY) { 1451942c5e3cSpl196000 int slot_idx; 1452942c5e3cSpl196000 1453942c5e3cSpl196000 /* ACK the intr */ 1454942c5e3cSpl196000 AAC_STATUS_CLR(softs, AAC_DB_RESPONSE_READY); 1455942c5e3cSpl196000 (void) AAC_STATUS_GET(softs); 1456942c5e3cSpl196000 while (aac_fib_dequeue(softs, AAC_HOST_NORM_RESP_Q, 1457942c5e3cSpl196000 &slot_idx) == AACOK) 1458942c5e3cSpl196000 aac_handle_io(softs, slot_idx); 1459942c5e3cSpl196000 1460942c5e3cSpl196000 /* 1461942c5e3cSpl196000 * Process waiting cmds before start new ones to 1462942c5e3cSpl196000 * ensure first IOs are serviced first. 1463942c5e3cSpl196000 */ 1464942c5e3cSpl196000 aac_start_waiting_io(softs); 1465942c5e3cSpl196000 return (AAC_DB_RESPONSE_READY); 1466942c5e3cSpl196000 } else if (status & AAC_DB_COMMAND_READY) { 1467942c5e3cSpl196000 int aif_idx; 1468942c5e3cSpl196000 1469942c5e3cSpl196000 AAC_STATUS_CLR(softs, AAC_DB_COMMAND_READY); 1470942c5e3cSpl196000 (void) AAC_STATUS_GET(softs); 1471942c5e3cSpl196000 if (aac_fib_dequeue(softs, AAC_HOST_NORM_CMD_Q, &aif_idx) == 1472942c5e3cSpl196000 AACOK) { 1473942c5e3cSpl196000 ddi_acc_handle_t acc = softs->comm_space_acc_handle; 14740749e8deSXin Chen - Sun Microsystems - Beijing China struct aac_fib *fibp; /* FIB in communication space */ 14750749e8deSXin Chen - Sun Microsystems - Beijing China uint16_t fib_size; 1476942c5e3cSpl196000 uint32_t fib_xfer_state; 1477942c5e3cSpl196000 uint32_t addr, size; 1478942c5e3cSpl196000 1479942c5e3cSpl196000 ASSERT((aif_idx >= 0) && (aif_idx < AAC_ADAPTER_FIBS)); 1480942c5e3cSpl196000 1481942c5e3cSpl196000 #define AAC_SYNC_AIF(softs, aif_idx, type) \ 1482942c5e3cSpl196000 { (void) ddi_dma_sync((softs)->comm_space_dma_handle, \ 1483942c5e3cSpl196000 offsetof(struct aac_comm_space, \ 1484942c5e3cSpl196000 adapter_fibs[(aif_idx)]), AAC_FIB_SIZE, \ 1485942c5e3cSpl196000 (type)); } 1486942c5e3cSpl196000 1487942c5e3cSpl196000 /* Copy AIF from adapter to the empty AIF slot */ 1488942c5e3cSpl196000 AAC_SYNC_AIF(softs, aif_idx, DDI_DMA_SYNC_FORCPU); 14890749e8deSXin Chen - Sun Microsystems - Beijing China fibp = &softs->comm_space->adapter_fibs[aif_idx]; 14900749e8deSXin Chen - Sun Microsystems - Beijing China fib_size = ddi_get16(acc, &fibp->Header.Size); 1491942c5e3cSpl196000 14920749e8deSXin Chen - Sun Microsystems - Beijing China aac_save_aif(softs, acc, fibp, fib_size); 1493942c5e3cSpl196000 1494942c5e3cSpl196000 /* Complete AIF back to adapter with good status */ 1495942c5e3cSpl196000 fib_xfer_state = LE_32(fibp->Header.XferState); 1496942c5e3cSpl196000 if (fib_xfer_state & AAC_FIBSTATE_FROMADAP) { 14970749e8deSXin Chen - Sun Microsystems - Beijing China ddi_put32(acc, &fibp->Header.XferState, 1498942c5e3cSpl196000 fib_xfer_state | AAC_FIBSTATE_DONEHOST); 14990749e8deSXin Chen - Sun Microsystems - Beijing China ddi_put32(acc, (void *)&fibp->data[0], ST_OK); 15000749e8deSXin Chen - Sun Microsystems - Beijing China if (fib_size > AAC_FIB_SIZE) 15010749e8deSXin Chen - Sun Microsystems - Beijing China ddi_put16(acc, &fibp->Header.Size, 1502942c5e3cSpl196000 AAC_FIB_SIZE); 1503942c5e3cSpl196000 AAC_SYNC_AIF(softs, aif_idx, 1504942c5e3cSpl196000 DDI_DMA_SYNC_FORDEV); 1505942c5e3cSpl196000 } 1506942c5e3cSpl196000 1507942c5e3cSpl196000 /* Put the AIF response on the response queue */ 1508942c5e3cSpl196000 addr = ddi_get32(acc, 1509942c5e3cSpl196000 &softs->comm_space->adapter_fibs[aif_idx]. \ 1510942c5e3cSpl196000 Header.SenderFibAddress); 1511942c5e3cSpl196000 size = (uint32_t)ddi_get16(acc, 1512942c5e3cSpl196000 &softs->comm_space->adapter_fibs[aif_idx]. \ 1513942c5e3cSpl196000 Header.Size); 1514942c5e3cSpl196000 ddi_put32(acc, 1515942c5e3cSpl196000 &softs->comm_space->adapter_fibs[aif_idx]. \ 1516942c5e3cSpl196000 Header.ReceiverFibAddress, addr); 1517942c5e3cSpl196000 if (aac_fib_enqueue(softs, AAC_ADAP_NORM_RESP_Q, 1518942c5e3cSpl196000 addr, size) == AACERR) 1519942c5e3cSpl196000 cmn_err(CE_NOTE, "!AIF ack failed"); 1520942c5e3cSpl196000 } 1521942c5e3cSpl196000 return (AAC_DB_COMMAND_READY); 1522942c5e3cSpl196000 } else if (status & AAC_DB_PRINTF_READY) { 1523942c5e3cSpl196000 /* ACK the intr */ 1524942c5e3cSpl196000 AAC_STATUS_CLR(softs, AAC_DB_PRINTF_READY); 1525942c5e3cSpl196000 (void) AAC_STATUS_GET(softs); 1526942c5e3cSpl196000 (void) ddi_dma_sync(softs->comm_space_dma_handle, 1527942c5e3cSpl196000 offsetof(struct aac_comm_space, adapter_print_buf), 1528942c5e3cSpl196000 AAC_ADAPTER_PRINT_BUFSIZE, DDI_DMA_SYNC_FORCPU); 1529942c5e3cSpl196000 if (aac_check_dma_handle(softs->comm_space_dma_handle) == 1530942c5e3cSpl196000 DDI_SUCCESS) 1531942c5e3cSpl196000 cmn_err(CE_NOTE, "MSG From Adapter: %s", 1532942c5e3cSpl196000 softs->comm_space->adapter_print_buf); 1533942c5e3cSpl196000 else 1534942c5e3cSpl196000 ddi_fm_service_impact(softs->devinfo_p, 1535942c5e3cSpl196000 DDI_SERVICE_UNAFFECTED); 1536942c5e3cSpl196000 AAC_NOTIFY(softs, AAC_DB_PRINTF_READY); 1537942c5e3cSpl196000 return (AAC_DB_PRINTF_READY); 1538942c5e3cSpl196000 } else if (status & AAC_DB_COMMAND_NOT_FULL) { 1539942c5e3cSpl196000 /* 1540942c5e3cSpl196000 * Without these two condition statements, the OS could hang 1541942c5e3cSpl196000 * after a while, especially if there are a lot of AIF's to 1542942c5e3cSpl196000 * handle, for instance if a drive is pulled from an array 1543942c5e3cSpl196000 * under heavy load. 1544942c5e3cSpl196000 */ 1545942c5e3cSpl196000 AAC_STATUS_CLR(softs, AAC_DB_COMMAND_NOT_FULL); 1546942c5e3cSpl196000 return (AAC_DB_COMMAND_NOT_FULL); 1547942c5e3cSpl196000 } else if (status & AAC_DB_RESPONSE_NOT_FULL) { 1548942c5e3cSpl196000 AAC_STATUS_CLR(softs, AAC_DB_COMMAND_NOT_FULL); 1549942c5e3cSpl196000 AAC_STATUS_CLR(softs, AAC_DB_RESPONSE_NOT_FULL); 1550942c5e3cSpl196000 return (AAC_DB_RESPONSE_NOT_FULL); 1551942c5e3cSpl196000 } else { 1552942c5e3cSpl196000 return (0); 1553942c5e3cSpl196000 } 1554942c5e3cSpl196000 } 1555942c5e3cSpl196000 1556942c5e3cSpl196000 static uint_t 1557942c5e3cSpl196000 aac_intr_old(caddr_t arg) 1558942c5e3cSpl196000 { 1559a74f7440Spl196000 struct aac_softstate *softs = (void *)arg; 1560942c5e3cSpl196000 int rval; 1561942c5e3cSpl196000 1562942c5e3cSpl196000 mutex_enter(&softs->io_lock); 1563942c5e3cSpl196000 if (aac_process_intr_old(softs)) 1564942c5e3cSpl196000 rval = DDI_INTR_CLAIMED; 1565942c5e3cSpl196000 else 1566942c5e3cSpl196000 rval = DDI_INTR_UNCLAIMED; 1567942c5e3cSpl196000 mutex_exit(&softs->io_lock); 1568942c5e3cSpl196000 1569942c5e3cSpl196000 aac_drain_comp_q(softs); 1570942c5e3cSpl196000 return (rval); 1571942c5e3cSpl196000 } 1572942c5e3cSpl196000 1573942c5e3cSpl196000 /* 1574b6094a86Sjd218194 * Query FIXED or MSI interrupts 1575b6094a86Sjd218194 */ 1576b6094a86Sjd218194 static int 1577b6094a86Sjd218194 aac_query_intrs(struct aac_softstate *softs, int intr_type) 1578b6094a86Sjd218194 { 1579b6094a86Sjd218194 dev_info_t *dip = softs->devinfo_p; 1580f42c2f53Szhongyan gu - Sun Microsystems - Beijing China int avail, actual, count; 1581b6094a86Sjd218194 int i, flag, ret; 1582b6094a86Sjd218194 1583b6094a86Sjd218194 AACDB_PRINT(softs, CE_NOTE, 1584b6094a86Sjd218194 "aac_query_intrs:interrupt type 0x%x", intr_type); 1585b6094a86Sjd218194 1586b6094a86Sjd218194 /* Get number of interrupts */ 1587b6094a86Sjd218194 ret = ddi_intr_get_nintrs(dip, intr_type, &count); 1588b6094a86Sjd218194 if ((ret != DDI_SUCCESS) || (count == 0)) { 1589b6094a86Sjd218194 AACDB_PRINT(softs, CE_WARN, 1590b6094a86Sjd218194 "ddi_intr_get_nintrs() failed, ret %d count %d", 1591b6094a86Sjd218194 ret, count); 1592b6094a86Sjd218194 return (DDI_FAILURE); 1593b6094a86Sjd218194 } 1594b6094a86Sjd218194 1595b6094a86Sjd218194 /* Get number of available interrupts */ 1596b6094a86Sjd218194 ret = ddi_intr_get_navail(dip, intr_type, &avail); 1597b6094a86Sjd218194 if ((ret != DDI_SUCCESS) || (avail == 0)) { 1598b6094a86Sjd218194 AACDB_PRINT(softs, CE_WARN, 1599b6094a86Sjd218194 "ddi_intr_get_navail() failed, ret %d avail %d", 1600b6094a86Sjd218194 ret, avail); 1601b6094a86Sjd218194 return (DDI_FAILURE); 1602b6094a86Sjd218194 } 1603b6094a86Sjd218194 1604b6094a86Sjd218194 AACDB_PRINT(softs, CE_NOTE, 1605b6094a86Sjd218194 "ddi_intr_get_nvail returned %d, navail() returned %d", 1606b6094a86Sjd218194 count, avail); 1607b6094a86Sjd218194 1608b6094a86Sjd218194 /* Allocate an array of interrupt handles */ 1609f42c2f53Szhongyan gu - Sun Microsystems - Beijing China softs->intr_size = count * sizeof (ddi_intr_handle_t); 1610f42c2f53Szhongyan gu - Sun Microsystems - Beijing China softs->htable = kmem_alloc(softs->intr_size, KM_SLEEP); 1611b6094a86Sjd218194 1612b6094a86Sjd218194 if (intr_type == DDI_INTR_TYPE_MSI) { 1613b6094a86Sjd218194 count = 1; /* only one vector needed by now */ 1614b6094a86Sjd218194 flag = DDI_INTR_ALLOC_STRICT; 1615b6094a86Sjd218194 } else { /* must be DDI_INTR_TYPE_FIXED */ 1616b6094a86Sjd218194 flag = DDI_INTR_ALLOC_NORMAL; 1617b6094a86Sjd218194 } 1618b6094a86Sjd218194 1619b6094a86Sjd218194 /* Call ddi_intr_alloc() */ 1620b6094a86Sjd218194 ret = ddi_intr_alloc(dip, softs->htable, intr_type, 0, 1621b6094a86Sjd218194 count, &actual, flag); 1622b6094a86Sjd218194 1623b6094a86Sjd218194 if ((ret != DDI_SUCCESS) || (actual == 0)) { 1624b6094a86Sjd218194 AACDB_PRINT(softs, CE_WARN, 1625b6094a86Sjd218194 "ddi_intr_alloc() failed, ret = %d", ret); 1626b6094a86Sjd218194 actual = 0; 1627b6094a86Sjd218194 goto error; 1628b6094a86Sjd218194 } 1629b6094a86Sjd218194 1630b6094a86Sjd218194 if (actual < count) { 1631b6094a86Sjd218194 AACDB_PRINT(softs, CE_NOTE, 1632b6094a86Sjd218194 "Requested: %d, Received: %d", count, actual); 1633b6094a86Sjd218194 goto error; 1634b6094a86Sjd218194 } 1635b6094a86Sjd218194 1636b6094a86Sjd218194 softs->intr_cnt = actual; 1637b6094a86Sjd218194 1638b6094a86Sjd218194 /* Get priority for first msi, assume remaining are all the same */ 1639b6094a86Sjd218194 if ((ret = ddi_intr_get_pri(softs->htable[0], 1640b6094a86Sjd218194 &softs->intr_pri)) != DDI_SUCCESS) { 1641b6094a86Sjd218194 AACDB_PRINT(softs, CE_WARN, 1642b6094a86Sjd218194 "ddi_intr_get_pri() failed, ret = %d", ret); 1643b6094a86Sjd218194 goto error; 1644b6094a86Sjd218194 } 1645b6094a86Sjd218194 1646b6094a86Sjd218194 /* Test for high level mutex */ 1647b6094a86Sjd218194 if (softs->intr_pri >= ddi_intr_get_hilevel_pri()) { 1648b6094a86Sjd218194 AACDB_PRINT(softs, CE_WARN, 1649b6094a86Sjd218194 "aac_query_intrs: Hi level interrupt not supported"); 1650b6094a86Sjd218194 goto error; 1651b6094a86Sjd218194 } 1652b6094a86Sjd218194 1653b6094a86Sjd218194 return (DDI_SUCCESS); 1654b6094a86Sjd218194 1655b6094a86Sjd218194 error: 1656b6094a86Sjd218194 /* Free already allocated intr */ 1657b6094a86Sjd218194 for (i = 0; i < actual; i++) 1658b6094a86Sjd218194 (void) ddi_intr_free(softs->htable[i]); 1659b6094a86Sjd218194 1660f42c2f53Szhongyan gu - Sun Microsystems - Beijing China kmem_free(softs->htable, softs->intr_size); 1661b6094a86Sjd218194 return (DDI_FAILURE); 1662b6094a86Sjd218194 } 1663b6094a86Sjd218194 1664349b53ddSStuart Maybee 1665b6094a86Sjd218194 /* 1666b6094a86Sjd218194 * Register FIXED or MSI interrupts, and enable them 1667b6094a86Sjd218194 */ 1668b6094a86Sjd218194 static int 1669b6094a86Sjd218194 aac_add_intrs(struct aac_softstate *softs) 1670b6094a86Sjd218194 { 1671b6094a86Sjd218194 int i, ret; 1672f42c2f53Szhongyan gu - Sun Microsystems - Beijing China int actual; 1673b6094a86Sjd218194 ddi_intr_handler_t *aac_intr; 1674b6094a86Sjd218194 1675b6094a86Sjd218194 actual = softs->intr_cnt; 1676b6094a86Sjd218194 aac_intr = (ddi_intr_handler_t *)((softs->flags & AAC_FLAGS_NEW_COMM) ? 1677b6094a86Sjd218194 aac_intr_new : aac_intr_old); 1678b6094a86Sjd218194 1679b6094a86Sjd218194 /* Call ddi_intr_add_handler() */ 1680b6094a86Sjd218194 for (i = 0; i < actual; i++) { 1681b6094a86Sjd218194 if ((ret = ddi_intr_add_handler(softs->htable[i], 1682b6094a86Sjd218194 aac_intr, (caddr_t)softs, NULL)) != DDI_SUCCESS) { 1683b6094a86Sjd218194 cmn_err(CE_WARN, 1684b6094a86Sjd218194 "ddi_intr_add_handler() failed ret = %d", ret); 1685b6094a86Sjd218194 1686b6094a86Sjd218194 /* Free already allocated intr */ 1687b6094a86Sjd218194 for (i = 0; i < actual; i++) 1688b6094a86Sjd218194 (void) ddi_intr_free(softs->htable[i]); 1689b6094a86Sjd218194 1690f42c2f53Szhongyan gu - Sun Microsystems - Beijing China kmem_free(softs->htable, softs->intr_size); 1691b6094a86Sjd218194 return (DDI_FAILURE); 1692b6094a86Sjd218194 } 1693b6094a86Sjd218194 } 1694b6094a86Sjd218194 1695b6094a86Sjd218194 if ((ret = ddi_intr_get_cap(softs->htable[0], &softs->intr_cap)) 1696b6094a86Sjd218194 != DDI_SUCCESS) { 1697b6094a86Sjd218194 cmn_err(CE_WARN, "ddi_intr_get_cap() failed, ret = %d", ret); 1698b6094a86Sjd218194 1699b6094a86Sjd218194 /* Free already allocated intr */ 1700b6094a86Sjd218194 for (i = 0; i < actual; i++) 1701b6094a86Sjd218194 (void) ddi_intr_free(softs->htable[i]); 1702b6094a86Sjd218194 1703f42c2f53Szhongyan gu - Sun Microsystems - Beijing China kmem_free(softs->htable, softs->intr_size); 1704b6094a86Sjd218194 return (DDI_FAILURE); 1705b6094a86Sjd218194 } 1706b6094a86Sjd218194 1707b6094a86Sjd218194 return (DDI_SUCCESS); 1708b6094a86Sjd218194 } 1709b6094a86Sjd218194 1710b6094a86Sjd218194 /* 1711b6094a86Sjd218194 * Unregister FIXED or MSI interrupts 1712b6094a86Sjd218194 */ 1713b6094a86Sjd218194 static void 1714b6094a86Sjd218194 aac_remove_intrs(struct aac_softstate *softs) 1715b6094a86Sjd218194 { 1716b6094a86Sjd218194 int i; 1717b6094a86Sjd218194 1718b6094a86Sjd218194 /* Disable all interrupts */ 1719f42c2f53Szhongyan gu - Sun Microsystems - Beijing China (void) aac_disable_intrs(softs); 1720b6094a86Sjd218194 /* Call ddi_intr_remove_handler() */ 1721b6094a86Sjd218194 for (i = 0; i < softs->intr_cnt; i++) { 1722b6094a86Sjd218194 (void) ddi_intr_remove_handler(softs->htable[i]); 1723b6094a86Sjd218194 (void) ddi_intr_free(softs->htable[i]); 1724b6094a86Sjd218194 } 1725b6094a86Sjd218194 1726f42c2f53Szhongyan gu - Sun Microsystems - Beijing China kmem_free(softs->htable, softs->intr_size); 1727f42c2f53Szhongyan gu - Sun Microsystems - Beijing China } 1728f42c2f53Szhongyan gu - Sun Microsystems - Beijing China 1729f42c2f53Szhongyan gu - Sun Microsystems - Beijing China static int 1730f42c2f53Szhongyan gu - Sun Microsystems - Beijing China aac_enable_intrs(struct aac_softstate *softs) 1731f42c2f53Szhongyan gu - Sun Microsystems - Beijing China { 1732f42c2f53Szhongyan gu - Sun Microsystems - Beijing China int rval = AACOK; 1733f42c2f53Szhongyan gu - Sun Microsystems - Beijing China 1734f42c2f53Szhongyan gu - Sun Microsystems - Beijing China if (softs->intr_cap & DDI_INTR_FLAG_BLOCK) { 1735f42c2f53Szhongyan gu - Sun Microsystems - Beijing China /* for MSI block enable */ 1736f42c2f53Szhongyan gu - Sun Microsystems - Beijing China if (ddi_intr_block_enable(softs->htable, softs->intr_cnt) != 1737f42c2f53Szhongyan gu - Sun Microsystems - Beijing China DDI_SUCCESS) 1738f42c2f53Szhongyan gu - Sun Microsystems - Beijing China rval = AACERR; 1739f42c2f53Szhongyan gu - Sun Microsystems - Beijing China } else { 1740f42c2f53Szhongyan gu - Sun Microsystems - Beijing China int i; 1741f42c2f53Szhongyan gu - Sun Microsystems - Beijing China 1742f42c2f53Szhongyan gu - Sun Microsystems - Beijing China /* Call ddi_intr_enable() for legacy/MSI non block enable */ 1743f42c2f53Szhongyan gu - Sun Microsystems - Beijing China for (i = 0; i < softs->intr_cnt; i++) { 1744f42c2f53Szhongyan gu - Sun Microsystems - Beijing China if (ddi_intr_enable(softs->htable[i]) != DDI_SUCCESS) 1745f42c2f53Szhongyan gu - Sun Microsystems - Beijing China rval = AACERR; 1746f42c2f53Szhongyan gu - Sun Microsystems - Beijing China } 1747f42c2f53Szhongyan gu - Sun Microsystems - Beijing China } 1748f42c2f53Szhongyan gu - Sun Microsystems - Beijing China return (rval); 1749f42c2f53Szhongyan gu - Sun Microsystems - Beijing China } 1750f42c2f53Szhongyan gu - Sun Microsystems - Beijing China 1751f42c2f53Szhongyan gu - Sun Microsystems - Beijing China static int 1752f42c2f53Szhongyan gu - Sun Microsystems - Beijing China aac_disable_intrs(struct aac_softstate *softs) 1753f42c2f53Szhongyan gu - Sun Microsystems - Beijing China { 1754f42c2f53Szhongyan gu - Sun Microsystems - Beijing China int rval = AACOK; 1755f42c2f53Szhongyan gu - Sun Microsystems - Beijing China 1756f42c2f53Szhongyan gu - Sun Microsystems - Beijing China if (softs->intr_cap & DDI_INTR_FLAG_BLOCK) { 1757f42c2f53Szhongyan gu - Sun Microsystems - Beijing China /* Call ddi_intr_block_disable() */ 1758f42c2f53Szhongyan gu - Sun Microsystems - Beijing China if (ddi_intr_block_disable(softs->htable, softs->intr_cnt) != 1759f42c2f53Szhongyan gu - Sun Microsystems - Beijing China DDI_SUCCESS) 1760f42c2f53Szhongyan gu - Sun Microsystems - Beijing China rval = AACERR; 1761f42c2f53Szhongyan gu - Sun Microsystems - Beijing China } else { 1762f42c2f53Szhongyan gu - Sun Microsystems - Beijing China int i; 1763f42c2f53Szhongyan gu - Sun Microsystems - Beijing China 1764f42c2f53Szhongyan gu - Sun Microsystems - Beijing China for (i = 0; i < softs->intr_cnt; i++) { 1765f42c2f53Szhongyan gu - Sun Microsystems - Beijing China if (ddi_intr_disable(softs->htable[i]) != DDI_SUCCESS) 1766f42c2f53Szhongyan gu - Sun Microsystems - Beijing China rval = AACERR; 1767f42c2f53Szhongyan gu - Sun Microsystems - Beijing China } 1768f42c2f53Szhongyan gu - Sun Microsystems - Beijing China } 1769f42c2f53Szhongyan gu - Sun Microsystems - Beijing China return (rval); 1770b6094a86Sjd218194 } 1771b6094a86Sjd218194 1772b6094a86Sjd218194 /* 1773942c5e3cSpl196000 * Set pkt_reason and OR in pkt_statistics flag 1774942c5e3cSpl196000 */ 1775942c5e3cSpl196000 static void 1776942c5e3cSpl196000 aac_set_pkt_reason(struct aac_softstate *softs, struct aac_cmd *acp, 1777942c5e3cSpl196000 uchar_t reason, uint_t stat) 1778942c5e3cSpl196000 { 1779942c5e3cSpl196000 #ifndef __lock_lint 1780942c5e3cSpl196000 _NOTE(ARGUNUSED(softs)) 1781942c5e3cSpl196000 #endif 1782942c5e3cSpl196000 if (acp->pkt->pkt_reason == CMD_CMPLT) 1783942c5e3cSpl196000 acp->pkt->pkt_reason = reason; 1784942c5e3cSpl196000 acp->pkt->pkt_statistics |= stat; 1785942c5e3cSpl196000 } 1786942c5e3cSpl196000 1787942c5e3cSpl196000 /* 1788942c5e3cSpl196000 * Handle a finished pkt of soft SCMD 1789942c5e3cSpl196000 */ 1790942c5e3cSpl196000 static void 1791942c5e3cSpl196000 aac_soft_callback(struct aac_softstate *softs, struct aac_cmd *acp) 1792942c5e3cSpl196000 { 1793942c5e3cSpl196000 ASSERT(acp->pkt); 1794942c5e3cSpl196000 1795942c5e3cSpl196000 acp->flags |= AAC_CMD_CMPLT; 1796942c5e3cSpl196000 1797942c5e3cSpl196000 acp->pkt->pkt_state |= STATE_GOT_BUS | STATE_GOT_TARGET | \ 179858bc78c7SXin Chen STATE_SENT_CMD | STATE_GOT_STATUS; 1799942c5e3cSpl196000 if (acp->pkt->pkt_state & STATE_XFERRED_DATA) 1800942c5e3cSpl196000 acp->pkt->pkt_resid = 0; 1801942c5e3cSpl196000 1802942c5e3cSpl196000 /* AAC_CMD_NO_INTR means no complete callback */ 1803942c5e3cSpl196000 if (!(acp->flags & AAC_CMD_NO_INTR)) { 1804942c5e3cSpl196000 mutex_enter(&softs->q_comp_mutex); 1805942c5e3cSpl196000 aac_cmd_enqueue(&softs->q_comp, acp); 1806942c5e3cSpl196000 mutex_exit(&softs->q_comp_mutex); 1807942c5e3cSpl196000 ddi_trigger_softintr(softs->softint_id); 1808942c5e3cSpl196000 } 1809942c5e3cSpl196000 } 1810942c5e3cSpl196000 1811942c5e3cSpl196000 /* 1812942c5e3cSpl196000 * Handlers for completed IOs, common to aac_intr_new() and aac_intr_old() 1813942c5e3cSpl196000 */ 1814942c5e3cSpl196000 1815942c5e3cSpl196000 /* 1816942c5e3cSpl196000 * Handle completed logical device IO command 1817942c5e3cSpl196000 */ 1818942c5e3cSpl196000 /*ARGSUSED*/ 1819942c5e3cSpl196000 static void 1820942c5e3cSpl196000 aac_ld_complete(struct aac_softstate *softs, struct aac_cmd *acp) 1821942c5e3cSpl196000 { 1822942c5e3cSpl196000 struct aac_slot *slotp = acp->slotp; 1823942c5e3cSpl196000 struct aac_blockread_response *resp; 1824942c5e3cSpl196000 uint32_t status; 1825942c5e3cSpl196000 1826942c5e3cSpl196000 ASSERT(!(acp->flags & AAC_CMD_SYNC)); 1827942c5e3cSpl196000 ASSERT(!(acp->flags & AAC_CMD_NO_CB)); 1828942c5e3cSpl196000 182958bc78c7SXin Chen acp->pkt->pkt_state |= STATE_GOT_STATUS; 183058bc78c7SXin Chen 1831942c5e3cSpl196000 /* 1832942c5e3cSpl196000 * block_read/write has a similar response header, use blockread 1833942c5e3cSpl196000 * response for both. 1834942c5e3cSpl196000 */ 1835942c5e3cSpl196000 resp = (struct aac_blockread_response *)&slotp->fibp->data[0]; 1836942c5e3cSpl196000 status = ddi_get32(slotp->fib_acc_handle, &resp->Status); 1837942c5e3cSpl196000 if (status == ST_OK) { 1838942c5e3cSpl196000 acp->pkt->pkt_resid = 0; 1839942c5e3cSpl196000 acp->pkt->pkt_state |= STATE_XFERRED_DATA; 1840942c5e3cSpl196000 } else { 1841942c5e3cSpl196000 aac_set_arq_data_hwerr(acp); 1842942c5e3cSpl196000 } 1843942c5e3cSpl196000 } 1844942c5e3cSpl196000 1845942c5e3cSpl196000 /* 184658bc78c7SXin Chen * Handle completed phys. device IO command 184758bc78c7SXin Chen */ 184858bc78c7SXin Chen static void 184958bc78c7SXin Chen aac_pd_complete(struct aac_softstate *softs, struct aac_cmd *acp) 185058bc78c7SXin Chen { 185158bc78c7SXin Chen ddi_acc_handle_t acc = acp->slotp->fib_acc_handle; 185258bc78c7SXin Chen struct aac_fib *fibp = acp->slotp->fibp; 185358bc78c7SXin Chen struct scsi_pkt *pkt = acp->pkt; 185458bc78c7SXin Chen struct aac_srb_reply *resp; 185558bc78c7SXin Chen uint32_t resp_status; 185658bc78c7SXin Chen 185758bc78c7SXin Chen ASSERT(!(acp->flags & AAC_CMD_SYNC)); 185858bc78c7SXin Chen ASSERT(!(acp->flags & AAC_CMD_NO_CB)); 185958bc78c7SXin Chen 186058bc78c7SXin Chen resp = (struct aac_srb_reply *)&fibp->data[0]; 186158bc78c7SXin Chen resp_status = ddi_get32(acc, &resp->status); 186258bc78c7SXin Chen 186358bc78c7SXin Chen /* First check FIB status */ 186458bc78c7SXin Chen if (resp_status == ST_OK) { 186558bc78c7SXin Chen uint32_t scsi_status; 186658bc78c7SXin Chen uint32_t srb_status; 186758bc78c7SXin Chen uint32_t data_xfer_length; 186858bc78c7SXin Chen 186958bc78c7SXin Chen scsi_status = ddi_get32(acc, &resp->scsi_status); 187058bc78c7SXin Chen srb_status = ddi_get32(acc, &resp->srb_status); 187158bc78c7SXin Chen data_xfer_length = ddi_get32(acc, &resp->data_xfer_length); 187258bc78c7SXin Chen 187358bc78c7SXin Chen *pkt->pkt_scbp = (uint8_t)scsi_status; 187458bc78c7SXin Chen pkt->pkt_state |= STATE_GOT_STATUS; 187558bc78c7SXin Chen if (scsi_status == STATUS_GOOD) { 187658bc78c7SXin Chen uchar_t cmd = ((union scsi_cdb *)(void *) 187758bc78c7SXin Chen (pkt->pkt_cdbp))->scc_cmd; 187858bc78c7SXin Chen 187958bc78c7SXin Chen /* Next check SRB status */ 188058bc78c7SXin Chen switch (srb_status & 0x3f) { 188158bc78c7SXin Chen case SRB_STATUS_DATA_OVERRUN: 188258bc78c7SXin Chen AACDB_PRINT(softs, CE_NOTE, "DATA_OVERRUN: " \ 188358bc78c7SXin Chen "scmd=%d, xfer=%d, buflen=%d", 188458bc78c7SXin Chen (uint32_t)cmd, data_xfer_length, 188558bc78c7SXin Chen acp->bcount); 188658bc78c7SXin Chen 188758bc78c7SXin Chen switch (cmd) { 188858bc78c7SXin Chen case SCMD_READ: 188958bc78c7SXin Chen case SCMD_WRITE: 189058bc78c7SXin Chen case SCMD_READ_G1: 189158bc78c7SXin Chen case SCMD_WRITE_G1: 189258bc78c7SXin Chen case SCMD_READ_G4: 189358bc78c7SXin Chen case SCMD_WRITE_G4: 189458bc78c7SXin Chen case SCMD_READ_G5: 189558bc78c7SXin Chen case SCMD_WRITE_G5: 189658bc78c7SXin Chen aac_set_pkt_reason(softs, acp, 189758bc78c7SXin Chen CMD_DATA_OVR, 0); 189858bc78c7SXin Chen break; 189958bc78c7SXin Chen } 190058bc78c7SXin Chen /*FALLTHRU*/ 190158bc78c7SXin Chen case SRB_STATUS_ERROR_RECOVERY: 190258bc78c7SXin Chen case SRB_STATUS_PENDING: 190358bc78c7SXin Chen case SRB_STATUS_SUCCESS: 190458bc78c7SXin Chen /* 190558bc78c7SXin Chen * pkt_resid should only be calculated if the 190658bc78c7SXin Chen * status is ERROR_RECOVERY/PENDING/SUCCESS/ 190758bc78c7SXin Chen * OVERRUN/UNDERRUN 190858bc78c7SXin Chen */ 190958bc78c7SXin Chen if (data_xfer_length) { 191058bc78c7SXin Chen pkt->pkt_state |= STATE_XFERRED_DATA; 191158bc78c7SXin Chen pkt->pkt_resid = acp->bcount - \ 191258bc78c7SXin Chen data_xfer_length; 191358bc78c7SXin Chen ASSERT(pkt->pkt_resid >= 0); 191458bc78c7SXin Chen } 191558bc78c7SXin Chen break; 191658bc78c7SXin Chen case SRB_STATUS_ABORTED: 191758bc78c7SXin Chen AACDB_PRINT(softs, CE_NOTE, 191858bc78c7SXin Chen "SRB_STATUS_ABORTED, xfer=%d, resid=%d", 191958bc78c7SXin Chen data_xfer_length, pkt->pkt_resid); 192058bc78c7SXin Chen aac_set_pkt_reason(softs, acp, CMD_ABORTED, 192158bc78c7SXin Chen STAT_ABORTED); 192258bc78c7SXin Chen break; 192358bc78c7SXin Chen case SRB_STATUS_ABORT_FAILED: 192458bc78c7SXin Chen AACDB_PRINT(softs, CE_NOTE, 192558bc78c7SXin Chen "SRB_STATUS_ABORT_FAILED, xfer=%d, " \ 192658bc78c7SXin Chen "resid=%d", data_xfer_length, 192758bc78c7SXin Chen pkt->pkt_resid); 192858bc78c7SXin Chen aac_set_pkt_reason(softs, acp, CMD_ABORT_FAIL, 192958bc78c7SXin Chen 0); 193058bc78c7SXin Chen break; 193158bc78c7SXin Chen case SRB_STATUS_PARITY_ERROR: 193258bc78c7SXin Chen AACDB_PRINT(softs, CE_NOTE, 193358bc78c7SXin Chen "SRB_STATUS_PARITY_ERROR, xfer=%d, " \ 193458bc78c7SXin Chen "resid=%d", data_xfer_length, 193558bc78c7SXin Chen pkt->pkt_resid); 193658bc78c7SXin Chen aac_set_pkt_reason(softs, acp, CMD_PER_FAIL, 0); 193758bc78c7SXin Chen break; 193858bc78c7SXin Chen case SRB_STATUS_NO_DEVICE: 193958bc78c7SXin Chen case SRB_STATUS_INVALID_PATH_ID: 194058bc78c7SXin Chen case SRB_STATUS_INVALID_TARGET_ID: 194158bc78c7SXin Chen case SRB_STATUS_INVALID_LUN: 194258bc78c7SXin Chen case SRB_STATUS_SELECTION_TIMEOUT: 194358bc78c7SXin Chen #ifdef DEBUG 194458bc78c7SXin Chen if (AAC_DEV_IS_VALID(acp->dvp)) { 194558bc78c7SXin Chen AACDB_PRINT(softs, CE_NOTE, 194658bc78c7SXin Chen "SRB_STATUS_NO_DEVICE(%d), " \ 194758bc78c7SXin Chen "xfer=%d, resid=%d ", 194858bc78c7SXin Chen srb_status & 0x3f, 194958bc78c7SXin Chen data_xfer_length, pkt->pkt_resid); 195058bc78c7SXin Chen } 195158bc78c7SXin Chen #endif 195258bc78c7SXin Chen aac_set_pkt_reason(softs, acp, CMD_DEV_GONE, 0); 195358bc78c7SXin Chen break; 195458bc78c7SXin Chen case SRB_STATUS_COMMAND_TIMEOUT: 195558bc78c7SXin Chen case SRB_STATUS_TIMEOUT: 195658bc78c7SXin Chen AACDB_PRINT(softs, CE_NOTE, 195758bc78c7SXin Chen "SRB_STATUS_COMMAND_TIMEOUT, xfer=%d, " \ 195858bc78c7SXin Chen "resid=%d", data_xfer_length, 195958bc78c7SXin Chen pkt->pkt_resid); 196058bc78c7SXin Chen aac_set_pkt_reason(softs, acp, CMD_TIMEOUT, 196158bc78c7SXin Chen STAT_TIMEOUT); 196258bc78c7SXin Chen break; 196358bc78c7SXin Chen case SRB_STATUS_BUS_RESET: 196458bc78c7SXin Chen AACDB_PRINT(softs, CE_NOTE, 196558bc78c7SXin Chen "SRB_STATUS_BUS_RESET, xfer=%d, " \ 196658bc78c7SXin Chen "resid=%d", data_xfer_length, 196758bc78c7SXin Chen pkt->pkt_resid); 196858bc78c7SXin Chen aac_set_pkt_reason(softs, acp, CMD_RESET, 196958bc78c7SXin Chen STAT_BUS_RESET); 197058bc78c7SXin Chen break; 197158bc78c7SXin Chen default: 197258bc78c7SXin Chen AACDB_PRINT(softs, CE_NOTE, "srb_status=%d, " \ 197358bc78c7SXin Chen "xfer=%d, resid=%d", srb_status & 0x3f, 197458bc78c7SXin Chen data_xfer_length, pkt->pkt_resid); 197558bc78c7SXin Chen aac_set_pkt_reason(softs, acp, CMD_TRAN_ERR, 0); 197658bc78c7SXin Chen break; 197758bc78c7SXin Chen } 197858bc78c7SXin Chen } else if (scsi_status == STATUS_CHECK) { 197958bc78c7SXin Chen /* CHECK CONDITION */ 198058bc78c7SXin Chen struct scsi_arq_status *arqstat = 198158bc78c7SXin Chen (void *)(pkt->pkt_scbp); 198258bc78c7SXin Chen uint32_t sense_data_size; 198358bc78c7SXin Chen 198458bc78c7SXin Chen pkt->pkt_state |= STATE_ARQ_DONE; 198558bc78c7SXin Chen 198658bc78c7SXin Chen *(uint8_t *)&arqstat->sts_rqpkt_status = STATUS_GOOD; 198758bc78c7SXin Chen arqstat->sts_rqpkt_reason = CMD_CMPLT; 198858bc78c7SXin Chen arqstat->sts_rqpkt_resid = 0; 198958bc78c7SXin Chen arqstat->sts_rqpkt_state = 199058bc78c7SXin Chen STATE_GOT_BUS | 199158bc78c7SXin Chen STATE_GOT_TARGET | 199258bc78c7SXin Chen STATE_SENT_CMD | 199358bc78c7SXin Chen STATE_XFERRED_DATA; 199458bc78c7SXin Chen arqstat->sts_rqpkt_statistics = 0; 199558bc78c7SXin Chen 199658bc78c7SXin Chen sense_data_size = ddi_get32(acc, 199758bc78c7SXin Chen &resp->sense_data_size); 199858bc78c7SXin Chen ASSERT(sense_data_size <= AAC_SENSE_BUFFERSIZE); 199958bc78c7SXin Chen AACDB_PRINT(softs, CE_NOTE, 200058bc78c7SXin Chen "CHECK CONDITION: sense len=%d, xfer len=%d", 200158bc78c7SXin Chen sense_data_size, data_xfer_length); 200258bc78c7SXin Chen 200358bc78c7SXin Chen if (sense_data_size > SENSE_LENGTH) 200458bc78c7SXin Chen sense_data_size = SENSE_LENGTH; 200558bc78c7SXin Chen ddi_rep_get8(acc, (uint8_t *)&arqstat->sts_sensedata, 200658bc78c7SXin Chen (uint8_t *)resp->sense_data, sense_data_size, 200758bc78c7SXin Chen DDI_DEV_AUTOINCR); 200858bc78c7SXin Chen } else { 200958bc78c7SXin Chen AACDB_PRINT(softs, CE_WARN, "invaild scsi status: " \ 201058bc78c7SXin Chen "scsi_status=%d, srb_status=%d", 201158bc78c7SXin Chen scsi_status, srb_status); 201258bc78c7SXin Chen aac_set_pkt_reason(softs, acp, CMD_TRAN_ERR, 0); 201358bc78c7SXin Chen } 201458bc78c7SXin Chen } else { 201558bc78c7SXin Chen AACDB_PRINT(softs, CE_NOTE, "SRB failed: fib status %d", 201658bc78c7SXin Chen resp_status); 201758bc78c7SXin Chen aac_set_pkt_reason(softs, acp, CMD_TRAN_ERR, 0); 201858bc78c7SXin Chen } 201958bc78c7SXin Chen } 202058bc78c7SXin Chen 202158bc78c7SXin Chen /* 2022942c5e3cSpl196000 * Handle completed IOCTL command 2023942c5e3cSpl196000 */ 2024942c5e3cSpl196000 /*ARGSUSED*/ 2025942c5e3cSpl196000 void 2026942c5e3cSpl196000 aac_ioctl_complete(struct aac_softstate *softs, struct aac_cmd *acp) 2027942c5e3cSpl196000 { 2028942c5e3cSpl196000 struct aac_slot *slotp = acp->slotp; 2029942c5e3cSpl196000 2030942c5e3cSpl196000 /* 2031942c5e3cSpl196000 * NOTE: Both aac_ioctl_send_fib() and aac_send_raw_srb() 2032942c5e3cSpl196000 * may wait on softs->event, so use cv_broadcast() instead 2033942c5e3cSpl196000 * of cv_signal(). 2034942c5e3cSpl196000 */ 2035942c5e3cSpl196000 ASSERT(acp->flags & AAC_CMD_SYNC); 2036942c5e3cSpl196000 ASSERT(acp->flags & AAC_CMD_NO_CB); 2037942c5e3cSpl196000 2038942c5e3cSpl196000 /* Get the size of the response FIB from its FIB.Header.Size field */ 2039942c5e3cSpl196000 acp->fib_size = ddi_get16(slotp->fib_acc_handle, 2040942c5e3cSpl196000 &slotp->fibp->Header.Size); 2041942c5e3cSpl196000 2042942c5e3cSpl196000 ASSERT(acp->fib_size <= softs->aac_max_fib_size); 2043942c5e3cSpl196000 ddi_rep_get8(slotp->fib_acc_handle, (uint8_t *)acp->fibp, 2044942c5e3cSpl196000 (uint8_t *)slotp->fibp, acp->fib_size, DDI_DEV_AUTOINCR); 2045942c5e3cSpl196000 } 2046942c5e3cSpl196000 2047942c5e3cSpl196000 /* 2048f42c2f53Szhongyan gu - Sun Microsystems - Beijing China * Handle completed sync fib command 2049f42c2f53Szhongyan gu - Sun Microsystems - Beijing China */ 2050f42c2f53Szhongyan gu - Sun Microsystems - Beijing China /*ARGSUSED*/ 2051f42c2f53Szhongyan gu - Sun Microsystems - Beijing China void 2052f42c2f53Szhongyan gu - Sun Microsystems - Beijing China aac_sync_complete(struct aac_softstate *softs, struct aac_cmd *acp) 2053f42c2f53Szhongyan gu - Sun Microsystems - Beijing China { 2054f42c2f53Szhongyan gu - Sun Microsystems - Beijing China } 2055f42c2f53Szhongyan gu - Sun Microsystems - Beijing China 2056f42c2f53Szhongyan gu - Sun Microsystems - Beijing China /* 2057942c5e3cSpl196000 * Handle completed Flush command 2058942c5e3cSpl196000 */ 2059942c5e3cSpl196000 /*ARGSUSED*/ 2060942c5e3cSpl196000 static void 2061942c5e3cSpl196000 aac_synccache_complete(struct aac_softstate *softs, struct aac_cmd *acp) 2062942c5e3cSpl196000 { 2063942c5e3cSpl196000 struct aac_slot *slotp = acp->slotp; 2064942c5e3cSpl196000 ddi_acc_handle_t acc = slotp->fib_acc_handle; 2065942c5e3cSpl196000 struct aac_synchronize_reply *resp; 2066942c5e3cSpl196000 uint32_t status; 2067942c5e3cSpl196000 2068942c5e3cSpl196000 ASSERT(!(acp->flags & AAC_CMD_SYNC)); 2069942c5e3cSpl196000 207058bc78c7SXin Chen acp->pkt->pkt_state |= STATE_GOT_STATUS; 207158bc78c7SXin Chen 2072942c5e3cSpl196000 resp = (struct aac_synchronize_reply *)&slotp->fibp->data[0]; 2073942c5e3cSpl196000 status = ddi_get32(acc, &resp->Status); 2074942c5e3cSpl196000 if (status != CT_OK) 2075942c5e3cSpl196000 aac_set_arq_data_hwerr(acp); 2076942c5e3cSpl196000 } 2077942c5e3cSpl196000 20781ee13a44SXinChen /*ARGSUSED*/ 2079b40e8a89Szhongyan gu - Sun Microsystems - Beijing China static void 2080b40e8a89Szhongyan gu - Sun Microsystems - Beijing China aac_startstop_complete(struct aac_softstate *softs, struct aac_cmd *acp) 2081b40e8a89Szhongyan gu - Sun Microsystems - Beijing China { 2082b40e8a89Szhongyan gu - Sun Microsystems - Beijing China struct aac_slot *slotp = acp->slotp; 2083b40e8a89Szhongyan gu - Sun Microsystems - Beijing China ddi_acc_handle_t acc = slotp->fib_acc_handle; 2084b40e8a89Szhongyan gu - Sun Microsystems - Beijing China struct aac_Container_resp *resp; 2085b40e8a89Szhongyan gu - Sun Microsystems - Beijing China uint32_t status; 2086b40e8a89Szhongyan gu - Sun Microsystems - Beijing China 2087b40e8a89Szhongyan gu - Sun Microsystems - Beijing China ASSERT(!(acp->flags & AAC_CMD_SYNC)); 2088b40e8a89Szhongyan gu - Sun Microsystems - Beijing China 2089b40e8a89Szhongyan gu - Sun Microsystems - Beijing China acp->pkt->pkt_state |= STATE_GOT_STATUS; 2090b40e8a89Szhongyan gu - Sun Microsystems - Beijing China 2091b40e8a89Szhongyan gu - Sun Microsystems - Beijing China resp = (struct aac_Container_resp *)&slotp->fibp->data[0]; 2092b40e8a89Szhongyan gu - Sun Microsystems - Beijing China status = ddi_get32(acc, &resp->Status); 2093b40e8a89Szhongyan gu - Sun Microsystems - Beijing China if (status != 0) { 2094b40e8a89Szhongyan gu - Sun Microsystems - Beijing China AACDB_PRINT(softs, CE_WARN, "Cannot start/stop a unit"); 2095b40e8a89Szhongyan gu - Sun Microsystems - Beijing China aac_set_arq_data_hwerr(acp); 2096b40e8a89Szhongyan gu - Sun Microsystems - Beijing China } 2097b40e8a89Szhongyan gu - Sun Microsystems - Beijing China } 2098b40e8a89Szhongyan gu - Sun Microsystems - Beijing China 2099942c5e3cSpl196000 /* 2100942c5e3cSpl196000 * Access PCI space to see if the driver can support the card 2101942c5e3cSpl196000 */ 2102942c5e3cSpl196000 static int 2103942c5e3cSpl196000 aac_check_card_type(struct aac_softstate *softs) 2104942c5e3cSpl196000 { 2105942c5e3cSpl196000 ddi_acc_handle_t pci_config_handle; 2106942c5e3cSpl196000 int card_index; 2107942c5e3cSpl196000 uint32_t pci_cmd; 2108942c5e3cSpl196000 2109942c5e3cSpl196000 /* Map pci configuration space */ 2110942c5e3cSpl196000 if ((pci_config_setup(softs->devinfo_p, &pci_config_handle)) != 2111942c5e3cSpl196000 DDI_SUCCESS) { 2112942c5e3cSpl196000 AACDB_PRINT(softs, CE_WARN, "Cannot setup pci config space"); 2113942c5e3cSpl196000 return (AACERR); 2114942c5e3cSpl196000 } 2115942c5e3cSpl196000 2116942c5e3cSpl196000 softs->vendid = pci_config_get16(pci_config_handle, PCI_CONF_VENID); 2117942c5e3cSpl196000 softs->devid = pci_config_get16(pci_config_handle, PCI_CONF_DEVID); 2118942c5e3cSpl196000 softs->subvendid = pci_config_get16(pci_config_handle, 2119942c5e3cSpl196000 PCI_CONF_SUBVENID); 2120942c5e3cSpl196000 softs->subsysid = pci_config_get16(pci_config_handle, 2121942c5e3cSpl196000 PCI_CONF_SUBSYSID); 2122942c5e3cSpl196000 2123942c5e3cSpl196000 card_index = 0; 2124942c5e3cSpl196000 while (!CARD_IS_UNKNOWN(card_index)) { 2125942c5e3cSpl196000 if ((aac_cards[card_index].vendor == softs->vendid) && 2126942c5e3cSpl196000 (aac_cards[card_index].device == softs->devid) && 2127942c5e3cSpl196000 (aac_cards[card_index].subvendor == softs->subvendid) && 2128942c5e3cSpl196000 (aac_cards[card_index].subsys == softs->subsysid)) { 2129942c5e3cSpl196000 break; 2130942c5e3cSpl196000 } 2131942c5e3cSpl196000 card_index++; 2132942c5e3cSpl196000 } 2133942c5e3cSpl196000 2134942c5e3cSpl196000 softs->card = card_index; 2135942c5e3cSpl196000 softs->hwif = aac_cards[card_index].hwif; 2136942c5e3cSpl196000 2137942c5e3cSpl196000 /* 2138942c5e3cSpl196000 * Unknown aac card 2139942c5e3cSpl196000 * do a generic match based on the VendorID and DeviceID to 2140942c5e3cSpl196000 * support the new cards in the aac family 2141942c5e3cSpl196000 */ 2142942c5e3cSpl196000 if (CARD_IS_UNKNOWN(card_index)) { 2143942c5e3cSpl196000 if (softs->vendid != 0x9005) { 2144942c5e3cSpl196000 AACDB_PRINT(softs, CE_WARN, 2145942c5e3cSpl196000 "Unknown vendor 0x%x", softs->vendid); 2146942c5e3cSpl196000 goto error; 2147942c5e3cSpl196000 } 2148942c5e3cSpl196000 switch (softs->devid) { 2149942c5e3cSpl196000 case 0x285: 2150942c5e3cSpl196000 softs->hwif = AAC_HWIF_I960RX; 2151942c5e3cSpl196000 break; 2152942c5e3cSpl196000 case 0x286: 2153942c5e3cSpl196000 softs->hwif = AAC_HWIF_RKT; 2154942c5e3cSpl196000 break; 2155942c5e3cSpl196000 default: 2156942c5e3cSpl196000 AACDB_PRINT(softs, CE_WARN, 2157942c5e3cSpl196000 "Unknown device \"pci9005,%x\"", softs->devid); 2158942c5e3cSpl196000 goto error; 2159942c5e3cSpl196000 } 2160942c5e3cSpl196000 } 2161942c5e3cSpl196000 2162942c5e3cSpl196000 /* Set hardware dependent interface */ 2163942c5e3cSpl196000 switch (softs->hwif) { 2164942c5e3cSpl196000 case AAC_HWIF_I960RX: 2165942c5e3cSpl196000 softs->aac_if = aac_rx_interface; 2166942c5e3cSpl196000 softs->map_size_min = AAC_MAP_SIZE_MIN_RX; 2167942c5e3cSpl196000 break; 2168942c5e3cSpl196000 case AAC_HWIF_RKT: 2169942c5e3cSpl196000 softs->aac_if = aac_rkt_interface; 2170942c5e3cSpl196000 softs->map_size_min = AAC_MAP_SIZE_MIN_RKT; 2171942c5e3cSpl196000 break; 2172942c5e3cSpl196000 default: 2173942c5e3cSpl196000 AACDB_PRINT(softs, CE_WARN, 2174942c5e3cSpl196000 "Unknown hardware interface %d", softs->hwif); 2175942c5e3cSpl196000 goto error; 2176942c5e3cSpl196000 } 2177942c5e3cSpl196000 2178942c5e3cSpl196000 /* Set card names */ 2179942c5e3cSpl196000 (void *)strncpy(softs->vendor_name, aac_cards[card_index].vid, 2180942c5e3cSpl196000 AAC_VENDOR_LEN); 2181942c5e3cSpl196000 (void *)strncpy(softs->product_name, aac_cards[card_index].desc, 2182942c5e3cSpl196000 AAC_PRODUCT_LEN); 2183942c5e3cSpl196000 2184942c5e3cSpl196000 /* Set up quirks */ 2185942c5e3cSpl196000 softs->flags = aac_cards[card_index].quirks; 2186942c5e3cSpl196000 2187942c5e3cSpl196000 /* Force the busmaster enable bit on */ 2188942c5e3cSpl196000 pci_cmd = pci_config_get16(pci_config_handle, PCI_CONF_COMM); 2189942c5e3cSpl196000 if ((pci_cmd & PCI_COMM_ME) == 0) { 2190942c5e3cSpl196000 pci_cmd |= PCI_COMM_ME; 2191942c5e3cSpl196000 pci_config_put16(pci_config_handle, PCI_CONF_COMM, pci_cmd); 2192942c5e3cSpl196000 pci_cmd = pci_config_get16(pci_config_handle, PCI_CONF_COMM); 2193942c5e3cSpl196000 if ((pci_cmd & PCI_COMM_ME) == 0) { 2194942c5e3cSpl196000 cmn_err(CE_CONT, "?Cannot enable busmaster bit"); 2195942c5e3cSpl196000 goto error; 2196942c5e3cSpl196000 } 2197942c5e3cSpl196000 } 2198942c5e3cSpl196000 2199942c5e3cSpl196000 /* Set memory base to map */ 2200942c5e3cSpl196000 softs->pci_mem_base_paddr = 0xfffffff0UL & \ 2201942c5e3cSpl196000 pci_config_get32(pci_config_handle, PCI_CONF_BASE0); 2202942c5e3cSpl196000 2203942c5e3cSpl196000 pci_config_teardown(&pci_config_handle); 2204942c5e3cSpl196000 2205942c5e3cSpl196000 return (AACOK); /* card type detected */ 2206942c5e3cSpl196000 error: 2207942c5e3cSpl196000 pci_config_teardown(&pci_config_handle); 2208942c5e3cSpl196000 return (AACERR); /* no matched card found */ 2209942c5e3cSpl196000 } 2210942c5e3cSpl196000 2211942c5e3cSpl196000 /* 2212f42c2f53Szhongyan gu - Sun Microsystems - Beijing China * Do the usual interrupt handler setup stuff. 2213f42c2f53Szhongyan gu - Sun Microsystems - Beijing China */ 2214f42c2f53Szhongyan gu - Sun Microsystems - Beijing China static int 2215f42c2f53Szhongyan gu - Sun Microsystems - Beijing China aac_register_intrs(struct aac_softstate *softs) 2216f42c2f53Szhongyan gu - Sun Microsystems - Beijing China { 2217f42c2f53Szhongyan gu - Sun Microsystems - Beijing China dev_info_t *dip; 2218f42c2f53Szhongyan gu - Sun Microsystems - Beijing China int intr_types; 2219f42c2f53Szhongyan gu - Sun Microsystems - Beijing China 2220f42c2f53Szhongyan gu - Sun Microsystems - Beijing China ASSERT(softs->devinfo_p); 2221f42c2f53Szhongyan gu - Sun Microsystems - Beijing China dip = softs->devinfo_p; 2222f42c2f53Szhongyan gu - Sun Microsystems - Beijing China 2223f42c2f53Szhongyan gu - Sun Microsystems - Beijing China /* Get the type of device intrrupts */ 2224f42c2f53Szhongyan gu - Sun Microsystems - Beijing China if (ddi_intr_get_supported_types(dip, &intr_types) != DDI_SUCCESS) { 2225f42c2f53Szhongyan gu - Sun Microsystems - Beijing China AACDB_PRINT(softs, CE_WARN, 2226f42c2f53Szhongyan gu - Sun Microsystems - Beijing China "ddi_intr_get_supported_types() failed"); 2227f42c2f53Szhongyan gu - Sun Microsystems - Beijing China return (AACERR); 2228f42c2f53Szhongyan gu - Sun Microsystems - Beijing China } 2229f42c2f53Szhongyan gu - Sun Microsystems - Beijing China AACDB_PRINT(softs, CE_NOTE, 2230f42c2f53Szhongyan gu - Sun Microsystems - Beijing China "ddi_intr_get_supported_types() ret: 0x%x", intr_types); 2231f42c2f53Szhongyan gu - Sun Microsystems - Beijing China 2232f42c2f53Szhongyan gu - Sun Microsystems - Beijing China /* Query interrupt, and alloc/init all needed struct */ 2233f42c2f53Szhongyan gu - Sun Microsystems - Beijing China if (intr_types & DDI_INTR_TYPE_MSI) { 2234f42c2f53Szhongyan gu - Sun Microsystems - Beijing China if (aac_query_intrs(softs, DDI_INTR_TYPE_MSI) 2235f42c2f53Szhongyan gu - Sun Microsystems - Beijing China != DDI_SUCCESS) { 2236f42c2f53Szhongyan gu - Sun Microsystems - Beijing China AACDB_PRINT(softs, CE_WARN, 2237f42c2f53Szhongyan gu - Sun Microsystems - Beijing China "MSI interrupt query failed"); 2238f42c2f53Szhongyan gu - Sun Microsystems - Beijing China return (AACERR); 2239f42c2f53Szhongyan gu - Sun Microsystems - Beijing China } 2240f42c2f53Szhongyan gu - Sun Microsystems - Beijing China softs->intr_type = DDI_INTR_TYPE_MSI; 2241f42c2f53Szhongyan gu - Sun Microsystems - Beijing China } else if (intr_types & DDI_INTR_TYPE_FIXED) { 2242f42c2f53Szhongyan gu - Sun Microsystems - Beijing China if (aac_query_intrs(softs, DDI_INTR_TYPE_FIXED) 2243f42c2f53Szhongyan gu - Sun Microsystems - Beijing China != DDI_SUCCESS) { 2244f42c2f53Szhongyan gu - Sun Microsystems - Beijing China AACDB_PRINT(softs, CE_WARN, 2245f42c2f53Szhongyan gu - Sun Microsystems - Beijing China "FIXED interrupt query failed"); 2246f42c2f53Szhongyan gu - Sun Microsystems - Beijing China return (AACERR); 2247f42c2f53Szhongyan gu - Sun Microsystems - Beijing China } 2248f42c2f53Szhongyan gu - Sun Microsystems - Beijing China softs->intr_type = DDI_INTR_TYPE_FIXED; 2249f42c2f53Szhongyan gu - Sun Microsystems - Beijing China } else { 2250f42c2f53Szhongyan gu - Sun Microsystems - Beijing China AACDB_PRINT(softs, CE_WARN, 2251f42c2f53Szhongyan gu - Sun Microsystems - Beijing China "Device cannot suppport both FIXED and MSI interrupts"); 2252f42c2f53Szhongyan gu - Sun Microsystems - Beijing China return (AACERR); 2253f42c2f53Szhongyan gu - Sun Microsystems - Beijing China } 2254f42c2f53Szhongyan gu - Sun Microsystems - Beijing China 2255f42c2f53Szhongyan gu - Sun Microsystems - Beijing China /* Connect interrupt handlers */ 2256f42c2f53Szhongyan gu - Sun Microsystems - Beijing China if (aac_add_intrs(softs) != DDI_SUCCESS) { 2257f42c2f53Szhongyan gu - Sun Microsystems - Beijing China AACDB_PRINT(softs, CE_WARN, 2258f42c2f53Szhongyan gu - Sun Microsystems - Beijing China "Interrupt registration failed, intr type: %s", 2259f42c2f53Szhongyan gu - Sun Microsystems - Beijing China softs->intr_type == DDI_INTR_TYPE_MSI ? "MSI" : "FIXED"); 2260f42c2f53Szhongyan gu - Sun Microsystems - Beijing China return (AACERR); 2261f42c2f53Szhongyan gu - Sun Microsystems - Beijing China } 2262f42c2f53Szhongyan gu - Sun Microsystems - Beijing China (void) aac_enable_intrs(softs); 2263f42c2f53Szhongyan gu - Sun Microsystems - Beijing China 2264f42c2f53Szhongyan gu - Sun Microsystems - Beijing China if (ddi_add_softintr(dip, DDI_SOFTINT_LOW, &softs->softint_id, 2265f42c2f53Szhongyan gu - Sun Microsystems - Beijing China NULL, NULL, aac_softintr, (caddr_t)softs) != DDI_SUCCESS) { 2266f42c2f53Szhongyan gu - Sun Microsystems - Beijing China AACDB_PRINT(softs, CE_WARN, 2267f42c2f53Szhongyan gu - Sun Microsystems - Beijing China "Can not setup soft interrupt handler!"); 2268f42c2f53Szhongyan gu - Sun Microsystems - Beijing China aac_remove_intrs(softs); 2269f42c2f53Szhongyan gu - Sun Microsystems - Beijing China return (AACERR); 2270f42c2f53Szhongyan gu - Sun Microsystems - Beijing China } 2271f42c2f53Szhongyan gu - Sun Microsystems - Beijing China 2272f42c2f53Szhongyan gu - Sun Microsystems - Beijing China return (AACOK); 2273f42c2f53Szhongyan gu - Sun Microsystems - Beijing China } 2274f42c2f53Szhongyan gu - Sun Microsystems - Beijing China 2275f42c2f53Szhongyan gu - Sun Microsystems - Beijing China static void 2276f42c2f53Szhongyan gu - Sun Microsystems - Beijing China aac_unregister_intrs(struct aac_softstate *softs) 2277f42c2f53Szhongyan gu - Sun Microsystems - Beijing China { 2278f42c2f53Szhongyan gu - Sun Microsystems - Beijing China aac_remove_intrs(softs); 2279f42c2f53Szhongyan gu - Sun Microsystems - Beijing China ddi_remove_softintr(softs->softint_id); 2280f42c2f53Szhongyan gu - Sun Microsystems - Beijing China } 2281f42c2f53Szhongyan gu - Sun Microsystems - Beijing China 2282f42c2f53Szhongyan gu - Sun Microsystems - Beijing China /* 2283942c5e3cSpl196000 * Check the firmware to determine the features to support and the FIB 2284942c5e3cSpl196000 * parameters to use. 2285942c5e3cSpl196000 */ 2286942c5e3cSpl196000 static int 2287942c5e3cSpl196000 aac_check_firmware(struct aac_softstate *softs) 2288942c5e3cSpl196000 { 2289942c5e3cSpl196000 uint32_t options; 2290942c5e3cSpl196000 uint32_t atu_size; 2291942c5e3cSpl196000 ddi_acc_handle_t pci_handle; 229258bc78c7SXin Chen uint8_t *data; 2293942c5e3cSpl196000 uint32_t max_fibs; 2294942c5e3cSpl196000 uint32_t max_fib_size; 2295942c5e3cSpl196000 uint32_t sg_tablesize; 2296942c5e3cSpl196000 uint32_t max_sectors; 2297942c5e3cSpl196000 uint32_t status; 2298942c5e3cSpl196000 2299942c5e3cSpl196000 /* Get supported options */ 2300942c5e3cSpl196000 if ((aac_sync_mbcommand(softs, AAC_MONKER_GETINFO, 0, 0, 0, 0, 2301942c5e3cSpl196000 &status)) != AACOK) { 2302942c5e3cSpl196000 if (status != SRB_STATUS_INVALID_REQUEST) { 2303942c5e3cSpl196000 cmn_err(CE_CONT, 2304942c5e3cSpl196000 "?Fatal error: request adapter info error"); 2305942c5e3cSpl196000 return (AACERR); 2306942c5e3cSpl196000 } 2307942c5e3cSpl196000 options = 0; 2308942c5e3cSpl196000 atu_size = 0; 2309942c5e3cSpl196000 } else { 2310942c5e3cSpl196000 options = AAC_MAILBOX_GET(softs, 1); 2311942c5e3cSpl196000 atu_size = AAC_MAILBOX_GET(softs, 2); 2312942c5e3cSpl196000 } 2313942c5e3cSpl196000 2314942c5e3cSpl196000 if (softs->state & AAC_STATE_RESET) { 2315942c5e3cSpl196000 if ((softs->support_opt == options) && 2316942c5e3cSpl196000 (softs->atu_size == atu_size)) 2317942c5e3cSpl196000 return (AACOK); 2318942c5e3cSpl196000 2319942c5e3cSpl196000 cmn_err(CE_WARN, 2320942c5e3cSpl196000 "?Fatal error: firmware changed, system needs reboot"); 2321942c5e3cSpl196000 return (AACERR); 2322942c5e3cSpl196000 } 2323942c5e3cSpl196000 2324942c5e3cSpl196000 /* 2325942c5e3cSpl196000 * The following critical settings are initialized only once during 2326942c5e3cSpl196000 * driver attachment. 2327942c5e3cSpl196000 */ 2328942c5e3cSpl196000 softs->support_opt = options; 2329942c5e3cSpl196000 softs->atu_size = atu_size; 2330942c5e3cSpl196000 2331942c5e3cSpl196000 /* Process supported options */ 2332942c5e3cSpl196000 if ((options & AAC_SUPPORTED_4GB_WINDOW) != 0 && 2333942c5e3cSpl196000 (softs->flags & AAC_FLAGS_NO4GB) == 0) { 2334942c5e3cSpl196000 AACDB_PRINT(softs, CE_NOTE, "!Enable FIB map 4GB window"); 2335942c5e3cSpl196000 softs->flags |= AAC_FLAGS_4GB_WINDOW; 2336942c5e3cSpl196000 } else { 2337942c5e3cSpl196000 /* 2338942c5e3cSpl196000 * Quirk AAC_FLAGS_NO4GB is for FIB address and thus comm space 2339942c5e3cSpl196000 * only. IO is handled by the DMA engine which does not suffer 2340942c5e3cSpl196000 * from the ATU window programming workarounds necessary for 2341942c5e3cSpl196000 * CPU copy operations. 2342942c5e3cSpl196000 */ 2343942c5e3cSpl196000 softs->addr_dma_attr.dma_attr_addr_lo = 0x2000ull; 2344942c5e3cSpl196000 softs->addr_dma_attr.dma_attr_addr_hi = 0x7fffffffull; 2345942c5e3cSpl196000 } 2346942c5e3cSpl196000 2347942c5e3cSpl196000 if ((options & AAC_SUPPORTED_SGMAP_HOST64) != 0) { 2348942c5e3cSpl196000 AACDB_PRINT(softs, CE_NOTE, "!Enable SG map 64-bit address"); 2349942c5e3cSpl196000 softs->buf_dma_attr.dma_attr_addr_hi = 0xffffffffffffffffull; 2350942c5e3cSpl196000 softs->buf_dma_attr.dma_attr_seg = 0xffffffffffffffffull; 2351942c5e3cSpl196000 softs->flags |= AAC_FLAGS_SG_64BIT; 2352942c5e3cSpl196000 } 2353942c5e3cSpl196000 2354942c5e3cSpl196000 if (options & AAC_SUPPORTED_64BIT_ARRAYSIZE) { 2355942c5e3cSpl196000 softs->flags |= AAC_FLAGS_ARRAY_64BIT; 2356942c5e3cSpl196000 AACDB_PRINT(softs, CE_NOTE, "!Enable 64-bit array size"); 2357942c5e3cSpl196000 } 2358942c5e3cSpl196000 235958bc78c7SXin Chen if (options & AAC_SUPPORTED_NONDASD) { 236058bc78c7SXin Chen if ((ddi_prop_lookup_string(DDI_DEV_T_ANY, softs->devinfo_p, 0, 236158bc78c7SXin Chen "nondasd-enable", (char **)&data) == DDI_SUCCESS)) { 236258bc78c7SXin Chen if (strcmp((char *)data, "yes") == 0) { 236358bc78c7SXin Chen AACDB_PRINT(softs, CE_NOTE, 236458bc78c7SXin Chen "!Enable Non-DASD access"); 236558bc78c7SXin Chen softs->flags |= AAC_FLAGS_NONDASD; 236658bc78c7SXin Chen } 236758bc78c7SXin Chen ddi_prop_free(data); 236858bc78c7SXin Chen } 236958bc78c7SXin Chen } 237058bc78c7SXin Chen 2371942c5e3cSpl196000 /* Read preferred settings */ 2372942c5e3cSpl196000 max_fib_size = 0; 2373942c5e3cSpl196000 if ((aac_sync_mbcommand(softs, AAC_MONKER_GETCOMMPREF, 2374942c5e3cSpl196000 0, 0, 0, 0, NULL)) == AACOK) { 2375942c5e3cSpl196000 options = AAC_MAILBOX_GET(softs, 1); 2376942c5e3cSpl196000 max_fib_size = (options & 0xffff); 2377942c5e3cSpl196000 max_sectors = (options >> 16) << 1; 2378942c5e3cSpl196000 options = AAC_MAILBOX_GET(softs, 2); 2379942c5e3cSpl196000 sg_tablesize = (options >> 16); 2380942c5e3cSpl196000 options = AAC_MAILBOX_GET(softs, 3); 2381942c5e3cSpl196000 max_fibs = (options & 0xffff); 2382942c5e3cSpl196000 } 2383942c5e3cSpl196000 2384942c5e3cSpl196000 /* Enable new comm. and rawio at the same time */ 2385942c5e3cSpl196000 if ((softs->support_opt & AAC_SUPPORTED_NEW_COMM) && 2386942c5e3cSpl196000 (max_fib_size != 0)) { 238758bc78c7SXin Chen /* read out and save PCI MBR */ 2388942c5e3cSpl196000 if ((atu_size > softs->map_size) && 2389942c5e3cSpl196000 (ddi_regs_map_setup(softs->devinfo_p, 1, 2390837c1ac4SStephen Hanson (caddr_t *)&data, 0, atu_size, &softs->reg_attr, 2391942c5e3cSpl196000 &pci_handle) == DDI_SUCCESS)) { 2392942c5e3cSpl196000 ddi_regs_map_free(&softs->pci_mem_handle); 2393942c5e3cSpl196000 softs->pci_mem_handle = pci_handle; 239458bc78c7SXin Chen softs->pci_mem_base_vaddr = data; 2395942c5e3cSpl196000 softs->map_size = atu_size; 2396942c5e3cSpl196000 } 2397942c5e3cSpl196000 if (atu_size == softs->map_size) { 2398942c5e3cSpl196000 softs->flags |= AAC_FLAGS_NEW_COMM; 2399942c5e3cSpl196000 AACDB_PRINT(softs, CE_NOTE, 2400942c5e3cSpl196000 "!Enable New Comm. interface"); 2401942c5e3cSpl196000 } 2402942c5e3cSpl196000 } 2403942c5e3cSpl196000 2404942c5e3cSpl196000 /* Set FIB parameters */ 2405942c5e3cSpl196000 if (softs->flags & AAC_FLAGS_NEW_COMM) { 2406942c5e3cSpl196000 softs->aac_max_fibs = max_fibs; 2407942c5e3cSpl196000 softs->aac_max_fib_size = max_fib_size; 2408942c5e3cSpl196000 softs->aac_max_sectors = max_sectors; 2409942c5e3cSpl196000 softs->aac_sg_tablesize = sg_tablesize; 2410942c5e3cSpl196000 2411942c5e3cSpl196000 softs->flags |= AAC_FLAGS_RAW_IO; 2412942c5e3cSpl196000 AACDB_PRINT(softs, CE_NOTE, "!Enable RawIO"); 2413942c5e3cSpl196000 } else { 2414942c5e3cSpl196000 softs->aac_max_fibs = 2415942c5e3cSpl196000 (softs->flags & AAC_FLAGS_256FIBS) ? 256 : 512; 2416942c5e3cSpl196000 softs->aac_max_fib_size = AAC_FIB_SIZE; 2417942c5e3cSpl196000 softs->aac_max_sectors = 128; /* 64K */ 2418942c5e3cSpl196000 if (softs->flags & AAC_FLAGS_17SG) 2419942c5e3cSpl196000 softs->aac_sg_tablesize = 17; 2420942c5e3cSpl196000 else if (softs->flags & AAC_FLAGS_34SG) 2421942c5e3cSpl196000 softs->aac_sg_tablesize = 34; 2422942c5e3cSpl196000 else if (softs->flags & AAC_FLAGS_SG_64BIT) 2423942c5e3cSpl196000 softs->aac_sg_tablesize = (AAC_FIB_DATASIZE - 2424942c5e3cSpl196000 sizeof (struct aac_blockwrite64) + 2425942c5e3cSpl196000 sizeof (struct aac_sg_entry64)) / 2426942c5e3cSpl196000 sizeof (struct aac_sg_entry64); 2427942c5e3cSpl196000 else 2428942c5e3cSpl196000 softs->aac_sg_tablesize = (AAC_FIB_DATASIZE - 2429942c5e3cSpl196000 sizeof (struct aac_blockwrite) + 2430942c5e3cSpl196000 sizeof (struct aac_sg_entry)) / 2431942c5e3cSpl196000 sizeof (struct aac_sg_entry); 2432942c5e3cSpl196000 } 2433942c5e3cSpl196000 2434942c5e3cSpl196000 if ((softs->flags & AAC_FLAGS_RAW_IO) && 2435942c5e3cSpl196000 (softs->flags & AAC_FLAGS_ARRAY_64BIT)) { 2436942c5e3cSpl196000 softs->flags |= AAC_FLAGS_LBA_64BIT; 2437942c5e3cSpl196000 AACDB_PRINT(softs, CE_NOTE, "!Enable 64-bit array"); 2438942c5e3cSpl196000 } 2439942c5e3cSpl196000 softs->buf_dma_attr.dma_attr_sgllen = softs->aac_sg_tablesize; 2440942c5e3cSpl196000 softs->buf_dma_attr.dma_attr_maxxfer = softs->aac_max_sectors << 9; 2441942c5e3cSpl196000 /* 2442942c5e3cSpl196000 * 64K maximum segment size in scatter gather list is controlled by 2443942c5e3cSpl196000 * the NEW_COMM bit in the adapter information. If not set, the card 2444942c5e3cSpl196000 * can only accept a maximum of 64K. It is not recommended to permit 2445942c5e3cSpl196000 * more than 128KB of total transfer size to the adapters because 2446942c5e3cSpl196000 * performance is negatively impacted. 2447942c5e3cSpl196000 * 2448942c5e3cSpl196000 * For new comm, segment size equals max xfer size. For old comm, 2449942c5e3cSpl196000 * we use 64K for both. 2450942c5e3cSpl196000 */ 2451942c5e3cSpl196000 softs->buf_dma_attr.dma_attr_count_max = 2452942c5e3cSpl196000 softs->buf_dma_attr.dma_attr_maxxfer - 1; 2453942c5e3cSpl196000 245458bc78c7SXin Chen /* Setup FIB operations */ 2455942c5e3cSpl196000 if (softs->flags & AAC_FLAGS_RAW_IO) 2456942c5e3cSpl196000 softs->aac_cmd_fib = aac_cmd_fib_rawio; 2457942c5e3cSpl196000 else if (softs->flags & AAC_FLAGS_SG_64BIT) 2458942c5e3cSpl196000 softs->aac_cmd_fib = aac_cmd_fib_brw64; 2459942c5e3cSpl196000 else 2460942c5e3cSpl196000 softs->aac_cmd_fib = aac_cmd_fib_brw; 2461942c5e3cSpl196000 softs->aac_cmd_fib_scsi = (softs->flags & AAC_FLAGS_SG_64BIT) ? \ 2462942c5e3cSpl196000 aac_cmd_fib_scsi64 : aac_cmd_fib_scsi32; 2463942c5e3cSpl196000 2464942c5e3cSpl196000 /* 64-bit LBA needs descriptor format sense data */ 2465942c5e3cSpl196000 softs->slen = sizeof (struct scsi_arq_status); 2466942c5e3cSpl196000 if ((softs->flags & AAC_FLAGS_LBA_64BIT) && 2467942c5e3cSpl196000 softs->slen < AAC_ARQ64_LENGTH) 2468942c5e3cSpl196000 softs->slen = AAC_ARQ64_LENGTH; 2469942c5e3cSpl196000 2470942c5e3cSpl196000 AACDB_PRINT(softs, CE_NOTE, 2471942c5e3cSpl196000 "!max_fibs %d max_fibsize 0x%x max_sectors %d max_sg %d", 2472942c5e3cSpl196000 softs->aac_max_fibs, softs->aac_max_fib_size, 2473942c5e3cSpl196000 softs->aac_max_sectors, softs->aac_sg_tablesize); 2474942c5e3cSpl196000 2475942c5e3cSpl196000 return (AACOK); 2476942c5e3cSpl196000 } 2477942c5e3cSpl196000 2478942c5e3cSpl196000 static void 2479942c5e3cSpl196000 aac_fsa_rev(struct aac_softstate *softs, struct FsaRev *fsarev0, 2480942c5e3cSpl196000 struct FsaRev *fsarev1) 2481942c5e3cSpl196000 { 2482f42c2f53Szhongyan gu - Sun Microsystems - Beijing China ddi_acc_handle_t acc = softs->sync_ac.slotp->fib_acc_handle; 2483942c5e3cSpl196000 2484942c5e3cSpl196000 AAC_GET_FIELD8(acc, fsarev1, fsarev0, external.comp.dash); 2485942c5e3cSpl196000 AAC_GET_FIELD8(acc, fsarev1, fsarev0, external.comp.type); 2486942c5e3cSpl196000 AAC_GET_FIELD8(acc, fsarev1, fsarev0, external.comp.minor); 2487942c5e3cSpl196000 AAC_GET_FIELD8(acc, fsarev1, fsarev0, external.comp.major); 2488942c5e3cSpl196000 AAC_GET_FIELD32(acc, fsarev1, fsarev0, buildNumber); 2489942c5e3cSpl196000 } 2490942c5e3cSpl196000 2491942c5e3cSpl196000 /* 2492942c5e3cSpl196000 * The following function comes from Adaptec: 2493942c5e3cSpl196000 * 2494942c5e3cSpl196000 * Query adapter information and supplement adapter information 2495942c5e3cSpl196000 */ 2496942c5e3cSpl196000 static int 2497942c5e3cSpl196000 aac_get_adapter_info(struct aac_softstate *softs, 2498942c5e3cSpl196000 struct aac_adapter_info *ainfr, struct aac_supplement_adapter_info *sinfr) 2499942c5e3cSpl196000 { 2500f42c2f53Szhongyan gu - Sun Microsystems - Beijing China struct aac_cmd *acp = &softs->sync_ac; 2501f42c2f53Szhongyan gu - Sun Microsystems - Beijing China ddi_acc_handle_t acc; 2502f42c2f53Szhongyan gu - Sun Microsystems - Beijing China struct aac_fib *fibp; 2503942c5e3cSpl196000 struct aac_adapter_info *ainfp; 2504942c5e3cSpl196000 struct aac_supplement_adapter_info *sinfp; 2505f42c2f53Szhongyan gu - Sun Microsystems - Beijing China int rval; 2506f42c2f53Szhongyan gu - Sun Microsystems - Beijing China 2507f42c2f53Szhongyan gu - Sun Microsystems - Beijing China (void) aac_sync_fib_slot_bind(softs, acp); 2508f42c2f53Szhongyan gu - Sun Microsystems - Beijing China acc = acp->slotp->fib_acc_handle; 2509f42c2f53Szhongyan gu - Sun Microsystems - Beijing China fibp = acp->slotp->fibp; 2510942c5e3cSpl196000 2511942c5e3cSpl196000 ddi_put8(acc, &fibp->data[0], 0); 2512942c5e3cSpl196000 if (aac_sync_fib(softs, RequestAdapterInfo, 25133fced439Szhongyan gu - Sun Microsystems - Beijing China AAC_FIB_SIZEOF(struct aac_adapter_info)) != AACOK) { 2514942c5e3cSpl196000 AACDB_PRINT(softs, CE_WARN, "RequestAdapterInfo failed"); 2515f42c2f53Szhongyan gu - Sun Microsystems - Beijing China rval = AACERR; 2516f42c2f53Szhongyan gu - Sun Microsystems - Beijing China goto finish; 2517942c5e3cSpl196000 } 2518942c5e3cSpl196000 ainfp = (struct aac_adapter_info *)fibp->data; 2519942c5e3cSpl196000 if (ainfr) { 2520942c5e3cSpl196000 AAC_GET_FIELD32(acc, ainfr, ainfp, SupportedOptions); 2521942c5e3cSpl196000 AAC_GET_FIELD32(acc, ainfr, ainfp, PlatformBase); 2522942c5e3cSpl196000 AAC_GET_FIELD32(acc, ainfr, ainfp, CpuArchitecture); 2523942c5e3cSpl196000 AAC_GET_FIELD32(acc, ainfr, ainfp, CpuVariant); 2524942c5e3cSpl196000 AAC_GET_FIELD32(acc, ainfr, ainfp, ClockSpeed); 2525942c5e3cSpl196000 AAC_GET_FIELD32(acc, ainfr, ainfp, ExecutionMem); 2526942c5e3cSpl196000 AAC_GET_FIELD32(acc, ainfr, ainfp, BufferMem); 2527942c5e3cSpl196000 AAC_GET_FIELD32(acc, ainfr, ainfp, TotalMem); 2528942c5e3cSpl196000 aac_fsa_rev(softs, &ainfp->KernelRevision, 2529942c5e3cSpl196000 &ainfr->KernelRevision); 2530942c5e3cSpl196000 aac_fsa_rev(softs, &ainfp->MonitorRevision, 2531942c5e3cSpl196000 &ainfr->MonitorRevision); 2532942c5e3cSpl196000 aac_fsa_rev(softs, &ainfp->HardwareRevision, 2533942c5e3cSpl196000 &ainfr->HardwareRevision); 2534942c5e3cSpl196000 aac_fsa_rev(softs, &ainfp->BIOSRevision, 2535942c5e3cSpl196000 &ainfr->BIOSRevision); 2536942c5e3cSpl196000 AAC_GET_FIELD32(acc, ainfr, ainfp, ClusteringEnabled); 2537942c5e3cSpl196000 AAC_GET_FIELD32(acc, ainfr, ainfp, ClusterChannelMask); 2538942c5e3cSpl196000 AAC_GET_FIELD64(acc, ainfr, ainfp, SerialNumber); 2539942c5e3cSpl196000 AAC_GET_FIELD32(acc, ainfr, ainfp, batteryPlatform); 2540942c5e3cSpl196000 AAC_GET_FIELD32(acc, ainfr, ainfp, SupportedOptions); 2541942c5e3cSpl196000 AAC_GET_FIELD32(acc, ainfr, ainfp, OemVariant); 2542942c5e3cSpl196000 } 2543942c5e3cSpl196000 if (sinfr) { 2544942c5e3cSpl196000 if (!(softs->support_opt & 2545942c5e3cSpl196000 AAC_SUPPORTED_SUPPLEMENT_ADAPTER_INFO)) { 2546942c5e3cSpl196000 AACDB_PRINT(softs, CE_WARN, 2547942c5e3cSpl196000 "SupplementAdapterInfo not supported"); 2548f42c2f53Szhongyan gu - Sun Microsystems - Beijing China rval = AACERR; 2549f42c2f53Szhongyan gu - Sun Microsystems - Beijing China goto finish; 2550942c5e3cSpl196000 } 2551942c5e3cSpl196000 ddi_put8(acc, &fibp->data[0], 0); 2552942c5e3cSpl196000 if (aac_sync_fib(softs, RequestSupplementAdapterInfo, 25533fced439Szhongyan gu - Sun Microsystems - Beijing China AAC_FIB_SIZEOF(struct aac_supplement_adapter_info)) 25543fced439Szhongyan gu - Sun Microsystems - Beijing China != AACOK) { 2555942c5e3cSpl196000 AACDB_PRINT(softs, CE_WARN, 2556942c5e3cSpl196000 "RequestSupplementAdapterInfo failed"); 2557f42c2f53Szhongyan gu - Sun Microsystems - Beijing China rval = AACERR; 2558f42c2f53Szhongyan gu - Sun Microsystems - Beijing China goto finish; 2559942c5e3cSpl196000 } 2560942c5e3cSpl196000 sinfp = (struct aac_supplement_adapter_info *)fibp->data; 2561942c5e3cSpl196000 AAC_REP_GET_FIELD8(acc, sinfr, sinfp, AdapterTypeText[0], 17+1); 2562942c5e3cSpl196000 AAC_REP_GET_FIELD8(acc, sinfr, sinfp, Pad[0], 2); 2563942c5e3cSpl196000 AAC_GET_FIELD32(acc, sinfr, sinfp, FlashMemoryByteSize); 2564942c5e3cSpl196000 AAC_GET_FIELD32(acc, sinfr, sinfp, FlashImageId); 2565942c5e3cSpl196000 AAC_GET_FIELD32(acc, sinfr, sinfp, MaxNumberPorts); 2566942c5e3cSpl196000 AAC_GET_FIELD32(acc, sinfr, sinfp, Version); 2567942c5e3cSpl196000 AAC_GET_FIELD32(acc, sinfr, sinfp, FeatureBits); 2568942c5e3cSpl196000 AAC_GET_FIELD8(acc, sinfr, sinfp, SlotNumber); 2569942c5e3cSpl196000 AAC_REP_GET_FIELD8(acc, sinfr, sinfp, ReservedPad0[0], 3); 2570942c5e3cSpl196000 AAC_REP_GET_FIELD8(acc, sinfr, sinfp, BuildDate[0], 12); 2571942c5e3cSpl196000 AAC_GET_FIELD32(acc, sinfr, sinfp, CurrentNumberPorts); 2572942c5e3cSpl196000 AAC_REP_GET_FIELD8(acc, sinfr, sinfp, VpdInfo, 2573942c5e3cSpl196000 sizeof (struct vpd_info)); 2574942c5e3cSpl196000 aac_fsa_rev(softs, &sinfp->FlashFirmwareRevision, 2575942c5e3cSpl196000 &sinfr->FlashFirmwareRevision); 2576942c5e3cSpl196000 AAC_GET_FIELD32(acc, sinfr, sinfp, RaidTypeMorphOptions); 2577942c5e3cSpl196000 aac_fsa_rev(softs, &sinfp->FlashFirmwareBootRevision, 2578942c5e3cSpl196000 &sinfr->FlashFirmwareBootRevision); 2579942c5e3cSpl196000 AAC_REP_GET_FIELD8(acc, sinfr, sinfp, MfgPcbaSerialNo, 2580942c5e3cSpl196000 MFG_PCBA_SERIAL_NUMBER_WIDTH); 2581942c5e3cSpl196000 AAC_REP_GET_FIELD8(acc, sinfr, sinfp, MfgWWNName[0], 2582942c5e3cSpl196000 MFG_WWN_WIDTH); 2583b40e8a89Szhongyan gu - Sun Microsystems - Beijing China AAC_GET_FIELD32(acc, sinfr, sinfp, SupportedOptions2); 2584b40e8a89Szhongyan gu - Sun Microsystems - Beijing China AAC_GET_FIELD32(acc, sinfr, sinfp, ExpansionFlag); 2585b40e8a89Szhongyan gu - Sun Microsystems - Beijing China if (sinfr->ExpansionFlag == 1) { 2586b40e8a89Szhongyan gu - Sun Microsystems - Beijing China AAC_GET_FIELD32(acc, sinfr, sinfp, FeatureBits3); 2587b40e8a89Szhongyan gu - Sun Microsystems - Beijing China AAC_GET_FIELD32(acc, sinfr, sinfp, 2588b40e8a89Szhongyan gu - Sun Microsystems - Beijing China SupportedPerformanceMode); 2589b40e8a89Szhongyan gu - Sun Microsystems - Beijing China AAC_REP_GET_FIELD32(acc, sinfr, sinfp, 2590b40e8a89Szhongyan gu - Sun Microsystems - Beijing China ReservedGrowth[0], 80); 2591b40e8a89Szhongyan gu - Sun Microsystems - Beijing China } 2592942c5e3cSpl196000 } 2593f42c2f53Szhongyan gu - Sun Microsystems - Beijing China rval = AACOK; 2594f42c2f53Szhongyan gu - Sun Microsystems - Beijing China finish: 2595f42c2f53Szhongyan gu - Sun Microsystems - Beijing China aac_sync_fib_slot_release(softs, acp); 2596f42c2f53Szhongyan gu - Sun Microsystems - Beijing China return (rval); 2597942c5e3cSpl196000 } 2598942c5e3cSpl196000 259958bc78c7SXin Chen static int 260058bc78c7SXin Chen aac_get_bus_info(struct aac_softstate *softs, uint32_t *bus_max, 260158bc78c7SXin Chen uint32_t *tgt_max) 260258bc78c7SXin Chen { 2603f42c2f53Szhongyan gu - Sun Microsystems - Beijing China struct aac_cmd *acp = &softs->sync_ac; 2604f42c2f53Szhongyan gu - Sun Microsystems - Beijing China ddi_acc_handle_t acc; 2605f42c2f53Szhongyan gu - Sun Microsystems - Beijing China struct aac_fib *fibp; 260658bc78c7SXin Chen struct aac_ctcfg *c_cmd; 260758bc78c7SXin Chen struct aac_ctcfg_resp *c_resp; 260858bc78c7SXin Chen uint32_t scsi_method_id; 260958bc78c7SXin Chen struct aac_bus_info *cmd; 261058bc78c7SXin Chen struct aac_bus_info_response *resp; 261158bc78c7SXin Chen int rval; 261258bc78c7SXin Chen 2613f42c2f53Szhongyan gu - Sun Microsystems - Beijing China (void) aac_sync_fib_slot_bind(softs, acp); 2614f42c2f53Szhongyan gu - Sun Microsystems - Beijing China acc = acp->slotp->fib_acc_handle; 2615f42c2f53Szhongyan gu - Sun Microsystems - Beijing China fibp = acp->slotp->fibp; 2616f42c2f53Szhongyan gu - Sun Microsystems - Beijing China 261758bc78c7SXin Chen /* Detect MethodId */ 261858bc78c7SXin Chen c_cmd = (struct aac_ctcfg *)&fibp->data[0]; 261958bc78c7SXin Chen ddi_put32(acc, &c_cmd->Command, VM_ContainerConfig); 262058bc78c7SXin Chen ddi_put32(acc, &c_cmd->cmd, CT_GET_SCSI_METHOD); 262158bc78c7SXin Chen ddi_put32(acc, &c_cmd->param, 0); 262258bc78c7SXin Chen rval = aac_sync_fib(softs, ContainerCommand, 262358bc78c7SXin Chen AAC_FIB_SIZEOF(struct aac_ctcfg)); 262458bc78c7SXin Chen c_resp = (struct aac_ctcfg_resp *)&fibp->data[0]; 262558bc78c7SXin Chen if (rval != AACOK || ddi_get32(acc, &c_resp->Status) != 0) { 262658bc78c7SXin Chen AACDB_PRINT(softs, CE_WARN, 262758bc78c7SXin Chen "VM_ContainerConfig command fail"); 2628f42c2f53Szhongyan gu - Sun Microsystems - Beijing China rval = AACERR; 2629f42c2f53Szhongyan gu - Sun Microsystems - Beijing China goto finish; 263058bc78c7SXin Chen } 263158bc78c7SXin Chen scsi_method_id = ddi_get32(acc, &c_resp->param); 263258bc78c7SXin Chen 263358bc78c7SXin Chen /* Detect phys. bus count and max. target id first */ 263458bc78c7SXin Chen cmd = (struct aac_bus_info *)&fibp->data[0]; 263558bc78c7SXin Chen ddi_put32(acc, &cmd->Command, VM_Ioctl); 263658bc78c7SXin Chen ddi_put32(acc, &cmd->ObjType, FT_DRIVE); /* physical drive */ 263758bc78c7SXin Chen ddi_put32(acc, &cmd->MethodId, scsi_method_id); 263858bc78c7SXin Chen ddi_put32(acc, &cmd->ObjectId, 0); 263958bc78c7SXin Chen ddi_put32(acc, &cmd->CtlCmd, GetBusInfo); 264058bc78c7SXin Chen /* 264158bc78c7SXin Chen * For VM_Ioctl, the firmware uses the Header.Size filled from the 264258bc78c7SXin Chen * driver as the size to be returned. Therefore the driver has to use 264358bc78c7SXin Chen * sizeof (struct aac_bus_info_response) because it is greater than 264458bc78c7SXin Chen * sizeof (struct aac_bus_info). 264558bc78c7SXin Chen */ 264658bc78c7SXin Chen rval = aac_sync_fib(softs, ContainerCommand, 264758bc78c7SXin Chen AAC_FIB_SIZEOF(struct aac_bus_info_response)); 264858bc78c7SXin Chen resp = (struct aac_bus_info_response *)cmd; 264958bc78c7SXin Chen 265058bc78c7SXin Chen /* Scan all coordinates with INQUIRY */ 265158bc78c7SXin Chen if ((rval != AACOK) || (ddi_get32(acc, &resp->Status) != 0)) { 265258bc78c7SXin Chen AACDB_PRINT(softs, CE_WARN, "GetBusInfo command fail"); 2653f42c2f53Szhongyan gu - Sun Microsystems - Beijing China rval = AACERR; 2654f42c2f53Szhongyan gu - Sun Microsystems - Beijing China goto finish; 265558bc78c7SXin Chen } 265658bc78c7SXin Chen *bus_max = ddi_get32(acc, &resp->BusCount); 265758bc78c7SXin Chen *tgt_max = ddi_get32(acc, &resp->TargetsPerBus); 2658f42c2f53Szhongyan gu - Sun Microsystems - Beijing China 2659f42c2f53Szhongyan gu - Sun Microsystems - Beijing China finish: 2660f42c2f53Szhongyan gu - Sun Microsystems - Beijing China aac_sync_fib_slot_release(softs, acp); 266158bc78c7SXin Chen return (AACOK); 266258bc78c7SXin Chen } 266358bc78c7SXin Chen 2664942c5e3cSpl196000 /* 2665942c5e3cSpl196000 * The following function comes from Adaptec: 2666942c5e3cSpl196000 * 2667942c5e3cSpl196000 * Routine to be called during initialization of communications with 2668942c5e3cSpl196000 * the adapter to handle possible adapter configuration issues. When 2669942c5e3cSpl196000 * the adapter first boots up, it examines attached drives, etc, and 2670942c5e3cSpl196000 * potentially comes up with a new or revised configuration (relative to 2671942c5e3cSpl196000 * what's stored in it's NVRAM). Additionally it may discover problems 2672942c5e3cSpl196000 * that make the current physical configuration unworkable (currently 2673942c5e3cSpl196000 * applicable only to cluster configuration issues). 2674942c5e3cSpl196000 * 2675942c5e3cSpl196000 * If there are no configuration issues or the issues are considered 2676942c5e3cSpl196000 * trival by the adapter, it will set it's configuration status to 2677942c5e3cSpl196000 * "FSACT_CONTINUE" and execute the "commit confiuguration" action 2678942c5e3cSpl196000 * automatically on it's own. 2679942c5e3cSpl196000 * 2680942c5e3cSpl196000 * However, if there are non-trivial issues, the adapter will set it's 2681942c5e3cSpl196000 * internal configuration status to "FSACT_PAUSE" or "FASCT_ABORT" 2682942c5e3cSpl196000 * and wait for some agent on the host to issue the "\ContainerCommand 2683942c5e3cSpl196000 * \VM_ContainerConfig\CT_COMMIT_CONFIG" FIB command to cause the 2684942c5e3cSpl196000 * adapter to commit the new/updated configuration and enable 2685942c5e3cSpl196000 * un-inhibited operation. The host agent should first issue the 2686942c5e3cSpl196000 * "\ContainerCommand\VM_ContainerConfig\CT_GET_CONFIG_STATUS" FIB 2687942c5e3cSpl196000 * command to obtain information about config issues detected by 2688942c5e3cSpl196000 * the adapter. 2689942c5e3cSpl196000 * 2690942c5e3cSpl196000 * Normally the adapter's PC BIOS will execute on the host following 2691942c5e3cSpl196000 * adapter poweron and reset and will be responsible for querring the 2692942c5e3cSpl196000 * adapter with CT_GET_CONFIG_STATUS and issuing the CT_COMMIT_CONFIG 2693942c5e3cSpl196000 * command if appropriate. 2694942c5e3cSpl196000 * 2695942c5e3cSpl196000 * However, with the introduction of IOP reset support, the adapter may 2696942c5e3cSpl196000 * boot up without the benefit of the adapter's PC BIOS host agent. 2697942c5e3cSpl196000 * This routine is intended to take care of these issues in situations 2698942c5e3cSpl196000 * where BIOS doesn't execute following adapter poweron or reset. The 2699942c5e3cSpl196000 * CT_COMMIT_CONFIG command is a no-op if it's already been issued, so 2700942c5e3cSpl196000 * there is no harm in doing this when it's already been done. 2701942c5e3cSpl196000 */ 2702942c5e3cSpl196000 static int 2703942c5e3cSpl196000 aac_handle_adapter_config_issues(struct aac_softstate *softs) 2704942c5e3cSpl196000 { 2705f42c2f53Szhongyan gu - Sun Microsystems - Beijing China struct aac_cmd *acp = &softs->sync_ac; 2706f42c2f53Szhongyan gu - Sun Microsystems - Beijing China ddi_acc_handle_t acc; 2707f42c2f53Szhongyan gu - Sun Microsystems - Beijing China struct aac_fib *fibp; 2708942c5e3cSpl196000 struct aac_Container *cmd; 2709942c5e3cSpl196000 struct aac_Container_resp *resp; 2710942c5e3cSpl196000 struct aac_cf_status_header *cfg_sts_hdr; 2711942c5e3cSpl196000 uint32_t resp_status; 2712942c5e3cSpl196000 uint32_t ct_status; 2713942c5e3cSpl196000 uint32_t cfg_stat_action; 2714942c5e3cSpl196000 int rval; 2715942c5e3cSpl196000 2716f42c2f53Szhongyan gu - Sun Microsystems - Beijing China (void) aac_sync_fib_slot_bind(softs, acp); 2717f42c2f53Szhongyan gu - Sun Microsystems - Beijing China acc = acp->slotp->fib_acc_handle; 2718f42c2f53Szhongyan gu - Sun Microsystems - Beijing China fibp = acp->slotp->fibp; 2719f42c2f53Szhongyan gu - Sun Microsystems - Beijing China 2720942c5e3cSpl196000 /* Get adapter config status */ 2721942c5e3cSpl196000 cmd = (struct aac_Container *)&fibp->data[0]; 2722942c5e3cSpl196000 2723942c5e3cSpl196000 bzero(cmd, sizeof (*cmd) - CT_PACKET_SIZE); 2724942c5e3cSpl196000 ddi_put32(acc, &cmd->Command, VM_ContainerConfig); 2725942c5e3cSpl196000 ddi_put32(acc, &cmd->CTCommand.command, CT_GET_CONFIG_STATUS); 2726942c5e3cSpl196000 ddi_put32(acc, &cmd->CTCommand.param[CNT_SIZE], 2727942c5e3cSpl196000 sizeof (struct aac_cf_status_header)); 2728942c5e3cSpl196000 rval = aac_sync_fib(softs, ContainerCommand, 2729942c5e3cSpl196000 AAC_FIB_SIZEOF(struct aac_Container)); 2730942c5e3cSpl196000 resp = (struct aac_Container_resp *)cmd; 2731942c5e3cSpl196000 cfg_sts_hdr = (struct aac_cf_status_header *)resp->CTResponse.data; 2732942c5e3cSpl196000 2733942c5e3cSpl196000 resp_status = ddi_get32(acc, &resp->Status); 2734942c5e3cSpl196000 ct_status = ddi_get32(acc, &resp->CTResponse.param[0]); 2735942c5e3cSpl196000 if ((rval == AACOK) && (resp_status == 0) && (ct_status == CT_OK)) { 2736942c5e3cSpl196000 cfg_stat_action = ddi_get32(acc, &cfg_sts_hdr->action); 2737942c5e3cSpl196000 2738942c5e3cSpl196000 /* Commit configuration if it's reasonable to do so. */ 2739942c5e3cSpl196000 if (cfg_stat_action <= CFACT_PAUSE) { 2740942c5e3cSpl196000 bzero(cmd, sizeof (*cmd) - CT_PACKET_SIZE); 2741942c5e3cSpl196000 ddi_put32(acc, &cmd->Command, VM_ContainerConfig); 2742942c5e3cSpl196000 ddi_put32(acc, &cmd->CTCommand.command, 2743942c5e3cSpl196000 CT_COMMIT_CONFIG); 2744942c5e3cSpl196000 rval = aac_sync_fib(softs, ContainerCommand, 2745942c5e3cSpl196000 AAC_FIB_SIZEOF(struct aac_Container)); 2746942c5e3cSpl196000 2747942c5e3cSpl196000 resp_status = ddi_get32(acc, &resp->Status); 2748942c5e3cSpl196000 ct_status = ddi_get32(acc, &resp->CTResponse.param[0]); 2749942c5e3cSpl196000 if ((rval == AACOK) && (resp_status == 0) && 2750942c5e3cSpl196000 (ct_status == CT_OK)) 2751942c5e3cSpl196000 /* Successful completion */ 2752942c5e3cSpl196000 rval = AACMPE_OK; 2753942c5e3cSpl196000 else 2754942c5e3cSpl196000 /* Auto-commit aborted due to error(s). */ 2755942c5e3cSpl196000 rval = AACMPE_COMMIT_CONFIG; 2756942c5e3cSpl196000 } else { 2757942c5e3cSpl196000 /* 2758942c5e3cSpl196000 * Auto-commit aborted due to adapter indicating 2759942c5e3cSpl196000 * configuration issue(s) too dangerous to auto-commit. 2760942c5e3cSpl196000 */ 2761942c5e3cSpl196000 rval = AACMPE_CONFIG_STATUS; 2762942c5e3cSpl196000 } 2763942c5e3cSpl196000 } else { 2764942c5e3cSpl196000 cmn_err(CE_WARN, "!Configuration issue, auto-commit aborted"); 2765942c5e3cSpl196000 rval = AACMPE_CONFIG_STATUS; 2766942c5e3cSpl196000 } 2767f42c2f53Szhongyan gu - Sun Microsystems - Beijing China 2768f42c2f53Szhongyan gu - Sun Microsystems - Beijing China aac_sync_fib_slot_release(softs, acp); 2769942c5e3cSpl196000 return (rval); 2770942c5e3cSpl196000 } 2771942c5e3cSpl196000 2772942c5e3cSpl196000 /* 2773942c5e3cSpl196000 * Hardware initialization and resource allocation 2774942c5e3cSpl196000 */ 2775942c5e3cSpl196000 static int 2776942c5e3cSpl196000 aac_common_attach(struct aac_softstate *softs) 2777942c5e3cSpl196000 { 2778942c5e3cSpl196000 uint32_t status; 2779942c5e3cSpl196000 int i; 27800749e8deSXin Chen - Sun Microsystems - Beijing China struct aac_supplement_adapter_info sinf; 2781942c5e3cSpl196000 2782942c5e3cSpl196000 DBCALLED(softs, 1); 2783942c5e3cSpl196000 2784942c5e3cSpl196000 /* 2785942c5e3cSpl196000 * Do a little check here to make sure there aren't any outstanding 2786942c5e3cSpl196000 * FIBs in the message queue. At this point there should not be and 2787942c5e3cSpl196000 * if there are they are probably left over from another instance of 2788942c5e3cSpl196000 * the driver like when the system crashes and the crash dump driver 2789942c5e3cSpl196000 * gets loaded. 2790942c5e3cSpl196000 */ 2791942c5e3cSpl196000 while (AAC_OUTB_GET(softs) != 0xfffffffful) 2792942c5e3cSpl196000 ; 2793942c5e3cSpl196000 2794942c5e3cSpl196000 /* 2795942c5e3cSpl196000 * Wait the card to complete booting up before do anything that 2796942c5e3cSpl196000 * attempts to communicate with it. 2797942c5e3cSpl196000 */ 2798942c5e3cSpl196000 status = AAC_FWSTATUS_GET(softs); 2799942c5e3cSpl196000 if (status == AAC_SELF_TEST_FAILED || status == AAC_KERNEL_PANIC) 2800942c5e3cSpl196000 goto error; 2801942c5e3cSpl196000 i = AAC_FWUP_TIMEOUT * 1000; /* set timeout */ 2802942c5e3cSpl196000 AAC_BUSYWAIT(AAC_FWSTATUS_GET(softs) & AAC_KERNEL_UP_AND_RUNNING, i); 2803942c5e3cSpl196000 if (i == 0) { 2804942c5e3cSpl196000 cmn_err(CE_CONT, "?Fatal error: controller not ready"); 2805942c5e3cSpl196000 aac_fm_ereport(softs, DDI_FM_DEVICE_NO_RESPONSE); 2806942c5e3cSpl196000 ddi_fm_service_impact(softs->devinfo_p, DDI_SERVICE_LOST); 2807942c5e3cSpl196000 goto error; 2808942c5e3cSpl196000 } 2809942c5e3cSpl196000 2810942c5e3cSpl196000 /* Read and set card supported options and settings */ 2811942c5e3cSpl196000 if (aac_check_firmware(softs) == AACERR) { 2812942c5e3cSpl196000 aac_fm_ereport(softs, DDI_FM_DEVICE_NO_RESPONSE); 2813942c5e3cSpl196000 ddi_fm_service_impact(softs->devinfo_p, DDI_SERVICE_LOST); 2814942c5e3cSpl196000 goto error; 2815942c5e3cSpl196000 } 2816942c5e3cSpl196000 2817f42c2f53Szhongyan gu - Sun Microsystems - Beijing China /* Add interrupt handlers */ 2818f42c2f53Szhongyan gu - Sun Microsystems - Beijing China if (aac_register_intrs(softs) == AACERR) { 2819f42c2f53Szhongyan gu - Sun Microsystems - Beijing China cmn_err(CE_CONT, 2820f42c2f53Szhongyan gu - Sun Microsystems - Beijing China "?Fatal error: interrupts register failed"); 2821f42c2f53Szhongyan gu - Sun Microsystems - Beijing China goto error; 2822f42c2f53Szhongyan gu - Sun Microsystems - Beijing China } 2823942c5e3cSpl196000 2824942c5e3cSpl196000 /* Setup communication space with the card */ 2825942c5e3cSpl196000 if (softs->comm_space_dma_handle == NULL) { 2826942c5e3cSpl196000 if (aac_alloc_comm_space(softs) != AACOK) 2827942c5e3cSpl196000 goto error; 2828942c5e3cSpl196000 } 2829942c5e3cSpl196000 if (aac_setup_comm_space(softs) != AACOK) { 2830942c5e3cSpl196000 cmn_err(CE_CONT, "?Setup communication space failed"); 2831942c5e3cSpl196000 aac_fm_ereport(softs, DDI_FM_DEVICE_NO_RESPONSE); 2832942c5e3cSpl196000 ddi_fm_service_impact(softs->devinfo_p, DDI_SERVICE_LOST); 2833942c5e3cSpl196000 goto error; 2834942c5e3cSpl196000 } 2835942c5e3cSpl196000 2836942c5e3cSpl196000 #ifdef DEBUG 2837942c5e3cSpl196000 if (aac_get_fw_debug_buffer(softs) != AACOK) 2838942c5e3cSpl196000 cmn_err(CE_CONT, "?firmware UART trace not supported"); 2839942c5e3cSpl196000 #endif 2840942c5e3cSpl196000 2841942c5e3cSpl196000 /* Allocate slots */ 2842942c5e3cSpl196000 if ((softs->total_slots == 0) && (aac_create_slots(softs) != AACOK)) { 2843942c5e3cSpl196000 cmn_err(CE_CONT, "?Fatal error: slots allocate failed"); 2844942c5e3cSpl196000 goto error; 2845942c5e3cSpl196000 } 2846942c5e3cSpl196000 AACDB_PRINT(softs, CE_NOTE, "%d slots allocated", softs->total_slots); 2847942c5e3cSpl196000 2848942c5e3cSpl196000 /* Allocate FIBs */ 2849942c5e3cSpl196000 if (softs->total_fibs < softs->total_slots) { 2850942c5e3cSpl196000 aac_alloc_fibs(softs); 2851942c5e3cSpl196000 if (softs->total_fibs == 0) 2852942c5e3cSpl196000 goto error; 2853942c5e3cSpl196000 AACDB_PRINT(softs, CE_NOTE, "%d fibs allocated", 2854942c5e3cSpl196000 softs->total_fibs); 2855942c5e3cSpl196000 } 2856942c5e3cSpl196000 2857f42c2f53Szhongyan gu - Sun Microsystems - Beijing China AAC_STATUS_CLR(softs, ~0); /* Clear out all interrupts */ 2858f42c2f53Szhongyan gu - Sun Microsystems - Beijing China AAC_ENABLE_INTR(softs); /* Enable the interrupts we can handle */ 2859f42c2f53Szhongyan gu - Sun Microsystems - Beijing China 28600749e8deSXin Chen - Sun Microsystems - Beijing China if (aac_get_adapter_info(softs, NULL, &sinf) == AACOK) { 2861b40e8a89Szhongyan gu - Sun Microsystems - Beijing China softs->feature_bits = sinf.FeatureBits; 2862b40e8a89Szhongyan gu - Sun Microsystems - Beijing China softs->support_opt2 = sinf.SupportedOptions2; 2863b40e8a89Szhongyan gu - Sun Microsystems - Beijing China 28643fced439Szhongyan gu - Sun Microsystems - Beijing China /* Get adapter names */ 28653fced439Szhongyan gu - Sun Microsystems - Beijing China if (CARD_IS_UNKNOWN(softs->card)) { 2866942c5e3cSpl196000 char *p, *p0, *p1; 2867942c5e3cSpl196000 2868942c5e3cSpl196000 /* 2869942c5e3cSpl196000 * Now find the controller name in supp_adapter_info-> 2870942c5e3cSpl196000 * AdapterTypeText. Use the first word as the vendor 2871942c5e3cSpl196000 * and the other words as the product name. 2872942c5e3cSpl196000 */ 2873942c5e3cSpl196000 AACDB_PRINT(softs, CE_NOTE, "sinf.AdapterTypeText = " 2874942c5e3cSpl196000 "\"%s\"", sinf.AdapterTypeText); 2875942c5e3cSpl196000 p = sinf.AdapterTypeText; 2876942c5e3cSpl196000 p0 = p1 = NULL; 2877942c5e3cSpl196000 /* Skip heading spaces */ 2878942c5e3cSpl196000 while (*p && (*p == ' ' || *p == '\t')) 2879942c5e3cSpl196000 p++; 2880942c5e3cSpl196000 p0 = p; 2881942c5e3cSpl196000 while (*p && (*p != ' ' && *p != '\t')) 2882942c5e3cSpl196000 p++; 2883942c5e3cSpl196000 /* Remove middle spaces */ 2884942c5e3cSpl196000 while (*p && (*p == ' ' || *p == '\t')) 2885942c5e3cSpl196000 *p++ = 0; 2886942c5e3cSpl196000 p1 = p; 2887942c5e3cSpl196000 /* Remove trailing spaces */ 2888942c5e3cSpl196000 p = p1 + strlen(p1) - 1; 2889942c5e3cSpl196000 while (p > p1 && (*p == ' ' || *p == '\t')) 2890942c5e3cSpl196000 *p-- = 0; 2891942c5e3cSpl196000 if (*p0 && *p1) { 2892942c5e3cSpl196000 (void *)strncpy(softs->vendor_name, p0, 2893942c5e3cSpl196000 AAC_VENDOR_LEN); 2894942c5e3cSpl196000 (void *)strncpy(softs->product_name, p1, 2895942c5e3cSpl196000 AAC_PRODUCT_LEN); 2896942c5e3cSpl196000 } else { 2897942c5e3cSpl196000 cmn_err(CE_WARN, 2898942c5e3cSpl196000 "?adapter name mis-formatted\n"); 2899942c5e3cSpl196000 if (*p0) 2900942c5e3cSpl196000 (void *)strncpy(softs->product_name, 2901942c5e3cSpl196000 p0, AAC_PRODUCT_LEN); 2902942c5e3cSpl196000 } 2903942c5e3cSpl196000 } 29040749e8deSXin Chen - Sun Microsystems - Beijing China } else { 29050749e8deSXin Chen - Sun Microsystems - Beijing China cmn_err(CE_CONT, "?Query adapter information failed"); 2906942c5e3cSpl196000 } 2907942c5e3cSpl196000 29080749e8deSXin Chen - Sun Microsystems - Beijing China 2909942c5e3cSpl196000 cmn_err(CE_NOTE, 2910942c5e3cSpl196000 "!aac driver %d.%02d.%02d-%d, found card: " \ 2911942c5e3cSpl196000 "%s %s(pci0x%x.%x.%x.%x) at 0x%x", 2912942c5e3cSpl196000 AAC_DRIVER_MAJOR_VERSION, 2913942c5e3cSpl196000 AAC_DRIVER_MINOR_VERSION, 2914942c5e3cSpl196000 AAC_DRIVER_BUGFIX_LEVEL, 2915942c5e3cSpl196000 AAC_DRIVER_BUILD, 2916942c5e3cSpl196000 softs->vendor_name, softs->product_name, 2917942c5e3cSpl196000 softs->vendid, softs->devid, softs->subvendid, softs->subsysid, 2918942c5e3cSpl196000 softs->pci_mem_base_paddr); 2919942c5e3cSpl196000 2920942c5e3cSpl196000 /* Perform acceptance of adapter-detected config changes if possible */ 2921942c5e3cSpl196000 if (aac_handle_adapter_config_issues(softs) != AACMPE_OK) { 2922942c5e3cSpl196000 cmn_err(CE_CONT, "?Handle adapter config issues failed"); 2923942c5e3cSpl196000 aac_fm_ereport(softs, DDI_FM_DEVICE_NO_RESPONSE); 2924942c5e3cSpl196000 ddi_fm_service_impact(softs->devinfo_p, DDI_SERVICE_LOST); 2925942c5e3cSpl196000 goto error; 2926942c5e3cSpl196000 } 2927942c5e3cSpl196000 292858bc78c7SXin Chen /* Setup containers (logical devices) */ 2929942c5e3cSpl196000 if (aac_probe_containers(softs) != AACOK) { 2930942c5e3cSpl196000 cmn_err(CE_CONT, "?Fatal error: get container info error"); 2931942c5e3cSpl196000 goto error; 2932942c5e3cSpl196000 } 2933942c5e3cSpl196000 29343fced439Szhongyan gu - Sun Microsystems - Beijing China /* Check for JBOD support. Default disable */ 29353fced439Szhongyan gu - Sun Microsystems - Beijing China char *data; 29363fced439Szhongyan gu - Sun Microsystems - Beijing China if (softs->feature_bits & AAC_FEATURE_SUPPORTED_JBOD) { 29373fced439Szhongyan gu - Sun Microsystems - Beijing China if ((ddi_prop_lookup_string(DDI_DEV_T_ANY, softs->devinfo_p, 29383fced439Szhongyan gu - Sun Microsystems - Beijing China 0, "jbod-enable", &data) == DDI_SUCCESS)) { 29393fced439Szhongyan gu - Sun Microsystems - Beijing China if (strcmp(data, "yes") == 0) { 29403fced439Szhongyan gu - Sun Microsystems - Beijing China AACDB_PRINT(softs, CE_NOTE, 29413fced439Szhongyan gu - Sun Microsystems - Beijing China "Enable JBOD access"); 29423fced439Szhongyan gu - Sun Microsystems - Beijing China softs->flags |= AAC_FLAGS_JBOD; 29433fced439Szhongyan gu - Sun Microsystems - Beijing China } 29443fced439Szhongyan gu - Sun Microsystems - Beijing China ddi_prop_free(data); 29453fced439Szhongyan gu - Sun Microsystems - Beijing China } 29463fced439Szhongyan gu - Sun Microsystems - Beijing China } 29473fced439Szhongyan gu - Sun Microsystems - Beijing China 294858bc78c7SXin Chen /* Setup phys. devices */ 29493fced439Szhongyan gu - Sun Microsystems - Beijing China if (softs->flags & (AAC_FLAGS_NONDASD | AAC_FLAGS_JBOD)) { 295058bc78c7SXin Chen uint32_t bus_max, tgt_max; 295158bc78c7SXin Chen uint32_t bus, tgt; 295258bc78c7SXin Chen int index; 295358bc78c7SXin Chen 295458bc78c7SXin Chen if (aac_get_bus_info(softs, &bus_max, &tgt_max) != AACOK) { 295558bc78c7SXin Chen cmn_err(CE_CONT, "?Fatal error: get bus info error"); 295658bc78c7SXin Chen goto error; 295758bc78c7SXin Chen } 295858bc78c7SXin Chen AACDB_PRINT(softs, CE_NOTE, "bus_max=%d, tgt_max=%d", 295958bc78c7SXin Chen bus_max, tgt_max); 296058bc78c7SXin Chen if (bus_max != softs->bus_max || tgt_max != softs->tgt_max) { 296158bc78c7SXin Chen if (softs->state & AAC_STATE_RESET) { 296258bc78c7SXin Chen cmn_err(CE_WARN, 296358bc78c7SXin Chen "?Fatal error: bus map changed"); 296458bc78c7SXin Chen goto error; 296558bc78c7SXin Chen } 296658bc78c7SXin Chen softs->bus_max = bus_max; 296758bc78c7SXin Chen softs->tgt_max = tgt_max; 296858bc78c7SXin Chen if (softs->nondasds) { 296958bc78c7SXin Chen kmem_free(softs->nondasds, AAC_MAX_PD(softs) * \ 297058bc78c7SXin Chen sizeof (struct aac_nondasd)); 297158bc78c7SXin Chen } 297258bc78c7SXin Chen softs->nondasds = kmem_zalloc(AAC_MAX_PD(softs) * \ 297358bc78c7SXin Chen sizeof (struct aac_nondasd), KM_SLEEP); 297458bc78c7SXin Chen 297558bc78c7SXin Chen index = 0; 297658bc78c7SXin Chen for (bus = 0; bus < softs->bus_max; bus++) { 297758bc78c7SXin Chen for (tgt = 0; tgt < softs->tgt_max; tgt++) { 297858bc78c7SXin Chen struct aac_nondasd *dvp = 297958bc78c7SXin Chen &softs->nondasds[index++]; 298058bc78c7SXin Chen dvp->dev.type = AAC_DEV_PD; 298158bc78c7SXin Chen dvp->bus = bus; 298258bc78c7SXin Chen dvp->tid = tgt; 298358bc78c7SXin Chen } 298458bc78c7SXin Chen } 298558bc78c7SXin Chen } 298658bc78c7SXin Chen } 298758bc78c7SXin Chen 2988942c5e3cSpl196000 /* Check dma & acc handles allocated in attach */ 2989942c5e3cSpl196000 if (aac_check_dma_handle(softs->comm_space_dma_handle) != DDI_SUCCESS) { 2990942c5e3cSpl196000 ddi_fm_service_impact(softs->devinfo_p, DDI_SERVICE_LOST); 2991942c5e3cSpl196000 goto error; 2992942c5e3cSpl196000 } 2993942c5e3cSpl196000 2994942c5e3cSpl196000 if (aac_check_acc_handle(softs->pci_mem_handle) != DDI_SUCCESS) { 2995942c5e3cSpl196000 ddi_fm_service_impact(softs->devinfo_p, DDI_SERVICE_LOST); 2996942c5e3cSpl196000 goto error; 2997942c5e3cSpl196000 } 2998942c5e3cSpl196000 2999942c5e3cSpl196000 for (i = 0; i < softs->total_slots; i++) { 3000942c5e3cSpl196000 if (aac_check_dma_handle(softs->io_slot[i].fib_dma_handle) != 3001942c5e3cSpl196000 DDI_SUCCESS) { 3002942c5e3cSpl196000 ddi_fm_service_impact(softs->devinfo_p, 3003942c5e3cSpl196000 DDI_SERVICE_LOST); 3004942c5e3cSpl196000 goto error; 3005942c5e3cSpl196000 } 3006942c5e3cSpl196000 } 3007942c5e3cSpl196000 3008942c5e3cSpl196000 return (AACOK); 3009942c5e3cSpl196000 error: 3010942c5e3cSpl196000 if (softs->state & AAC_STATE_RESET) 3011942c5e3cSpl196000 return (AACERR); 301258bc78c7SXin Chen if (softs->nondasds) { 301358bc78c7SXin Chen kmem_free(softs->nondasds, AAC_MAX_PD(softs) * \ 301458bc78c7SXin Chen sizeof (struct aac_nondasd)); 301558bc78c7SXin Chen softs->nondasds = NULL; 301658bc78c7SXin Chen } 3017942c5e3cSpl196000 if (softs->total_fibs > 0) 3018942c5e3cSpl196000 aac_destroy_fibs(softs); 3019942c5e3cSpl196000 if (softs->total_slots > 0) 3020942c5e3cSpl196000 aac_destroy_slots(softs); 3021942c5e3cSpl196000 if (softs->comm_space_dma_handle) 3022942c5e3cSpl196000 aac_free_comm_space(softs); 3023942c5e3cSpl196000 return (AACERR); 3024942c5e3cSpl196000 } 3025942c5e3cSpl196000 3026942c5e3cSpl196000 /* 3027942c5e3cSpl196000 * Hardware shutdown and resource release 3028942c5e3cSpl196000 */ 3029942c5e3cSpl196000 static void 3030942c5e3cSpl196000 aac_common_detach(struct aac_softstate *softs) 3031942c5e3cSpl196000 { 3032942c5e3cSpl196000 DBCALLED(softs, 1); 3033942c5e3cSpl196000 3034f42c2f53Szhongyan gu - Sun Microsystems - Beijing China aac_unregister_intrs(softs); 3035f42c2f53Szhongyan gu - Sun Microsystems - Beijing China 3036f42c2f53Szhongyan gu - Sun Microsystems - Beijing China mutex_enter(&softs->io_lock); 3037942c5e3cSpl196000 (void) aac_shutdown(softs); 3038942c5e3cSpl196000 303958bc78c7SXin Chen if (softs->nondasds) { 304058bc78c7SXin Chen kmem_free(softs->nondasds, AAC_MAX_PD(softs) * \ 304158bc78c7SXin Chen sizeof (struct aac_nondasd)); 304258bc78c7SXin Chen softs->nondasds = NULL; 304358bc78c7SXin Chen } 3044942c5e3cSpl196000 aac_destroy_fibs(softs); 3045942c5e3cSpl196000 aac_destroy_slots(softs); 3046942c5e3cSpl196000 aac_free_comm_space(softs); 3047f42c2f53Szhongyan gu - Sun Microsystems - Beijing China mutex_exit(&softs->io_lock); 3048942c5e3cSpl196000 } 3049942c5e3cSpl196000 3050942c5e3cSpl196000 /* 3051942c5e3cSpl196000 * Send a synchronous command to the controller and wait for a result. 3052942c5e3cSpl196000 * Indicate if the controller completed the command with an error status. 3053942c5e3cSpl196000 */ 3054942c5e3cSpl196000 int 3055942c5e3cSpl196000 aac_sync_mbcommand(struct aac_softstate *softs, uint32_t cmd, 3056942c5e3cSpl196000 uint32_t arg0, uint32_t arg1, uint32_t arg2, uint32_t arg3, 3057942c5e3cSpl196000 uint32_t *statusp) 3058942c5e3cSpl196000 { 3059942c5e3cSpl196000 int timeout; 3060942c5e3cSpl196000 uint32_t status; 3061942c5e3cSpl196000 3062942c5e3cSpl196000 if (statusp != NULL) 3063942c5e3cSpl196000 *statusp = SRB_STATUS_SUCCESS; 3064942c5e3cSpl196000 3065942c5e3cSpl196000 /* Fill in mailbox */ 3066942c5e3cSpl196000 AAC_MAILBOX_SET(softs, cmd, arg0, arg1, arg2, arg3); 3067942c5e3cSpl196000 3068942c5e3cSpl196000 /* Ensure the sync command doorbell flag is cleared */ 3069942c5e3cSpl196000 AAC_STATUS_CLR(softs, AAC_DB_SYNC_COMMAND); 3070942c5e3cSpl196000 3071942c5e3cSpl196000 /* Then set it to signal the adapter */ 3072942c5e3cSpl196000 AAC_NOTIFY(softs, AAC_DB_SYNC_COMMAND); 3073942c5e3cSpl196000 3074942c5e3cSpl196000 /* Spin waiting for the command to complete */ 3075942c5e3cSpl196000 timeout = AAC_IMMEDIATE_TIMEOUT * 1000; 3076942c5e3cSpl196000 AAC_BUSYWAIT(AAC_STATUS_GET(softs) & AAC_DB_SYNC_COMMAND, timeout); 3077942c5e3cSpl196000 if (!timeout) { 3078942c5e3cSpl196000 AACDB_PRINT(softs, CE_WARN, 3079942c5e3cSpl196000 "Sync command timed out after %d seconds (0x%x)!", 3080942c5e3cSpl196000 AAC_IMMEDIATE_TIMEOUT, AAC_FWSTATUS_GET(softs)); 3081942c5e3cSpl196000 return (AACERR); 3082942c5e3cSpl196000 } 3083942c5e3cSpl196000 3084942c5e3cSpl196000 /* Clear the completion flag */ 3085942c5e3cSpl196000 AAC_STATUS_CLR(softs, AAC_DB_SYNC_COMMAND); 3086942c5e3cSpl196000 3087942c5e3cSpl196000 /* Get the command status */ 3088942c5e3cSpl196000 status = AAC_MAILBOX_GET(softs, 0); 3089942c5e3cSpl196000 if (statusp != NULL) 3090942c5e3cSpl196000 *statusp = status; 3091942c5e3cSpl196000 if (status != SRB_STATUS_SUCCESS) { 3092942c5e3cSpl196000 AACDB_PRINT(softs, CE_WARN, 3093942c5e3cSpl196000 "Sync command fail: status = 0x%x", status); 3094942c5e3cSpl196000 return (AACERR); 3095942c5e3cSpl196000 } 3096942c5e3cSpl196000 3097942c5e3cSpl196000 return (AACOK); 3098942c5e3cSpl196000 } 3099942c5e3cSpl196000 3100942c5e3cSpl196000 /* 3101942c5e3cSpl196000 * Send a synchronous FIB to the adapter and wait for its completion 3102942c5e3cSpl196000 */ 3103942c5e3cSpl196000 static int 3104942c5e3cSpl196000 aac_sync_fib(struct aac_softstate *softs, uint16_t cmd, uint16_t fibsize) 3105942c5e3cSpl196000 { 3106f42c2f53Szhongyan gu - Sun Microsystems - Beijing China struct aac_cmd *acp = &softs->sync_ac; 3107942c5e3cSpl196000 31081ee13a44SXinChen acp->flags = AAC_CMD_SYNC | AAC_CMD_IN_SYNC_SLOT; 31091ee13a44SXinChen if (softs->state & AAC_STATE_INTR) 31101ee13a44SXinChen acp->flags |= AAC_CMD_NO_CB; 31111ee13a44SXinChen else 31121ee13a44SXinChen acp->flags |= AAC_CMD_NO_INTR; 31131ee13a44SXinChen 3114f42c2f53Szhongyan gu - Sun Microsystems - Beijing China acp->ac_comp = aac_sync_complete; 3115f42c2f53Szhongyan gu - Sun Microsystems - Beijing China acp->timeout = AAC_SYNC_TIMEOUT; 3116f42c2f53Szhongyan gu - Sun Microsystems - Beijing China acp->fib_size = fibsize; 31171ee13a44SXinChen 3118942c5e3cSpl196000 /* 3119f42c2f53Szhongyan gu - Sun Microsystems - Beijing China * Only need to setup sync fib header, caller should have init 3120f42c2f53Szhongyan gu - Sun Microsystems - Beijing China * fib data 3121942c5e3cSpl196000 */ 3122f42c2f53Szhongyan gu - Sun Microsystems - Beijing China aac_cmd_fib_header(softs, acp, cmd); 3123942c5e3cSpl196000 31241ee13a44SXinChen (void) ddi_dma_sync(acp->slotp->fib_dma_handle, 0, fibsize, 31251ee13a44SXinChen DDI_DMA_SYNC_FORDEV); 31261ee13a44SXinChen 3127f42c2f53Szhongyan gu - Sun Microsystems - Beijing China aac_start_io(softs, acp); 312858bc78c7SXin Chen 31291ee13a44SXinChen if (softs->state & AAC_STATE_INTR) 31301ee13a44SXinChen return (aac_do_sync_io(softs, acp)); 31311ee13a44SXinChen else 31321ee13a44SXinChen return (aac_do_poll_io(softs, acp)); 3133942c5e3cSpl196000 } 3134942c5e3cSpl196000 3135942c5e3cSpl196000 static void 3136942c5e3cSpl196000 aac_cmd_initq(struct aac_cmd_queue *q) 3137942c5e3cSpl196000 { 3138942c5e3cSpl196000 q->q_head = NULL; 3139942c5e3cSpl196000 q->q_tail = (struct aac_cmd *)&q->q_head; 3140942c5e3cSpl196000 } 3141942c5e3cSpl196000 3142942c5e3cSpl196000 /* 3143942c5e3cSpl196000 * Remove a cmd from the head of q 3144942c5e3cSpl196000 */ 3145942c5e3cSpl196000 static struct aac_cmd * 3146942c5e3cSpl196000 aac_cmd_dequeue(struct aac_cmd_queue *q) 3147942c5e3cSpl196000 { 3148942c5e3cSpl196000 struct aac_cmd *acp; 3149942c5e3cSpl196000 3150942c5e3cSpl196000 _NOTE(ASSUMING_PROTECTED(*q)) 3151942c5e3cSpl196000 3152942c5e3cSpl196000 if ((acp = q->q_head) != NULL) { 3153942c5e3cSpl196000 if ((q->q_head = acp->next) != NULL) 3154942c5e3cSpl196000 acp->next = NULL; 3155942c5e3cSpl196000 else 3156942c5e3cSpl196000 q->q_tail = (struct aac_cmd *)&q->q_head; 3157942c5e3cSpl196000 acp->prev = NULL; 3158942c5e3cSpl196000 } 3159942c5e3cSpl196000 return (acp); 3160942c5e3cSpl196000 } 3161942c5e3cSpl196000 3162942c5e3cSpl196000 /* 3163942c5e3cSpl196000 * Add a cmd to the tail of q 3164942c5e3cSpl196000 */ 3165942c5e3cSpl196000 static void 3166942c5e3cSpl196000 aac_cmd_enqueue(struct aac_cmd_queue *q, struct aac_cmd *acp) 3167942c5e3cSpl196000 { 3168942c5e3cSpl196000 ASSERT(acp->next == NULL); 3169942c5e3cSpl196000 acp->prev = q->q_tail; 3170942c5e3cSpl196000 q->q_tail->next = acp; 3171942c5e3cSpl196000 q->q_tail = acp; 3172942c5e3cSpl196000 } 3173942c5e3cSpl196000 3174942c5e3cSpl196000 /* 3175942c5e3cSpl196000 * Remove the cmd ac from q 3176942c5e3cSpl196000 */ 3177942c5e3cSpl196000 static void 3178942c5e3cSpl196000 aac_cmd_delete(struct aac_cmd_queue *q, struct aac_cmd *acp) 3179942c5e3cSpl196000 { 3180942c5e3cSpl196000 if (acp->prev) { 3181942c5e3cSpl196000 if ((acp->prev->next = acp->next) != NULL) { 3182942c5e3cSpl196000 acp->next->prev = acp->prev; 3183942c5e3cSpl196000 acp->next = NULL; 3184942c5e3cSpl196000 } else { 3185942c5e3cSpl196000 q->q_tail = acp->prev; 3186942c5e3cSpl196000 } 3187942c5e3cSpl196000 acp->prev = NULL; 3188942c5e3cSpl196000 } 3189942c5e3cSpl196000 /* ac is not in the queue */ 3190942c5e3cSpl196000 } 3191942c5e3cSpl196000 3192942c5e3cSpl196000 /* 3193942c5e3cSpl196000 * Atomically insert an entry into the nominated queue, returns 0 on success or 3194942c5e3cSpl196000 * AACERR if the queue is full. 3195942c5e3cSpl196000 * 3196942c5e3cSpl196000 * Note: it would be more efficient to defer notifying the controller in 3197942c5e3cSpl196000 * the case where we may be inserting several entries in rapid succession, 3198942c5e3cSpl196000 * but implementing this usefully may be difficult (it would involve a 3199942c5e3cSpl196000 * separate queue/notify interface). 3200942c5e3cSpl196000 */ 3201942c5e3cSpl196000 static int 3202942c5e3cSpl196000 aac_fib_enqueue(struct aac_softstate *softs, int queue, uint32_t fib_addr, 3203942c5e3cSpl196000 uint32_t fib_size) 3204942c5e3cSpl196000 { 3205942c5e3cSpl196000 ddi_dma_handle_t dma = softs->comm_space_dma_handle; 3206942c5e3cSpl196000 ddi_acc_handle_t acc = softs->comm_space_acc_handle; 3207942c5e3cSpl196000 uint32_t pi, ci; 3208942c5e3cSpl196000 3209942c5e3cSpl196000 DBCALLED(softs, 2); 3210942c5e3cSpl196000 3211942c5e3cSpl196000 ASSERT(queue == AAC_ADAP_NORM_CMD_Q || queue == AAC_ADAP_NORM_RESP_Q); 3212942c5e3cSpl196000 3213942c5e3cSpl196000 /* Get the producer/consumer indices */ 3214a74f7440Spl196000 (void) ddi_dma_sync(dma, (uintptr_t)softs->qtablep->qt_qindex[queue] - \ 3215a74f7440Spl196000 (uintptr_t)softs->comm_space, sizeof (uint32_t) * 2, 3216942c5e3cSpl196000 DDI_DMA_SYNC_FORCPU); 3217942c5e3cSpl196000 if (aac_check_dma_handle(dma) != DDI_SUCCESS) { 3218942c5e3cSpl196000 ddi_fm_service_impact(softs->devinfo_p, DDI_SERVICE_UNAFFECTED); 3219942c5e3cSpl196000 return (AACERR); 3220942c5e3cSpl196000 } 3221942c5e3cSpl196000 3222942c5e3cSpl196000 pi = ddi_get32(acc, 3223942c5e3cSpl196000 &softs->qtablep->qt_qindex[queue][AAC_PRODUCER_INDEX]); 3224942c5e3cSpl196000 ci = ddi_get32(acc, 3225942c5e3cSpl196000 &softs->qtablep->qt_qindex[queue][AAC_CONSUMER_INDEX]); 3226942c5e3cSpl196000 3227942c5e3cSpl196000 /* 3228942c5e3cSpl196000 * Wrap the queue first before we check the queue to see 3229942c5e3cSpl196000 * if it is full 3230942c5e3cSpl196000 */ 3231942c5e3cSpl196000 if (pi >= aac_qinfo[queue].size) 3232942c5e3cSpl196000 pi = 0; 3233942c5e3cSpl196000 3234942c5e3cSpl196000 /* XXX queue full */ 3235942c5e3cSpl196000 if ((pi + 1) == ci) 3236942c5e3cSpl196000 return (AACERR); 3237942c5e3cSpl196000 3238942c5e3cSpl196000 /* Fill in queue entry */ 3239942c5e3cSpl196000 ddi_put32(acc, &((softs->qentries[queue] + pi)->aq_fib_size), fib_size); 3240942c5e3cSpl196000 ddi_put32(acc, &((softs->qentries[queue] + pi)->aq_fib_addr), fib_addr); 3241a74f7440Spl196000 (void) ddi_dma_sync(dma, (uintptr_t)(softs->qentries[queue] + pi) - \ 3242a74f7440Spl196000 (uintptr_t)softs->comm_space, sizeof (struct aac_queue_entry), 3243942c5e3cSpl196000 DDI_DMA_SYNC_FORDEV); 3244942c5e3cSpl196000 3245942c5e3cSpl196000 /* Update producer index */ 3246942c5e3cSpl196000 ddi_put32(acc, &softs->qtablep->qt_qindex[queue][AAC_PRODUCER_INDEX], 3247942c5e3cSpl196000 pi + 1); 3248942c5e3cSpl196000 (void) ddi_dma_sync(dma, 3249a74f7440Spl196000 (uintptr_t)&softs->qtablep->qt_qindex[queue][AAC_PRODUCER_INDEX] - \ 3250a74f7440Spl196000 (uintptr_t)softs->comm_space, sizeof (uint32_t), 3251942c5e3cSpl196000 DDI_DMA_SYNC_FORDEV); 3252942c5e3cSpl196000 3253942c5e3cSpl196000 if (aac_qinfo[queue].notify != 0) 3254942c5e3cSpl196000 AAC_NOTIFY(softs, aac_qinfo[queue].notify); 3255942c5e3cSpl196000 return (AACOK); 3256942c5e3cSpl196000 } 3257942c5e3cSpl196000 3258942c5e3cSpl196000 /* 3259942c5e3cSpl196000 * Atomically remove one entry from the nominated queue, returns 0 on 3260942c5e3cSpl196000 * success or AACERR if the queue is empty. 3261942c5e3cSpl196000 */ 3262942c5e3cSpl196000 static int 3263942c5e3cSpl196000 aac_fib_dequeue(struct aac_softstate *softs, int queue, int *idxp) 3264942c5e3cSpl196000 { 3265942c5e3cSpl196000 ddi_acc_handle_t acc = softs->comm_space_acc_handle; 3266942c5e3cSpl196000 ddi_dma_handle_t dma = softs->comm_space_dma_handle; 3267942c5e3cSpl196000 uint32_t pi, ci; 3268942c5e3cSpl196000 int unfull = 0; 3269942c5e3cSpl196000 3270942c5e3cSpl196000 DBCALLED(softs, 2); 3271942c5e3cSpl196000 3272942c5e3cSpl196000 ASSERT(idxp); 3273942c5e3cSpl196000 3274942c5e3cSpl196000 /* Get the producer/consumer indices */ 3275a74f7440Spl196000 (void) ddi_dma_sync(dma, (uintptr_t)softs->qtablep->qt_qindex[queue] - \ 3276a74f7440Spl196000 (uintptr_t)softs->comm_space, sizeof (uint32_t) * 2, 3277942c5e3cSpl196000 DDI_DMA_SYNC_FORCPU); 3278942c5e3cSpl196000 pi = ddi_get32(acc, 3279942c5e3cSpl196000 &softs->qtablep->qt_qindex[queue][AAC_PRODUCER_INDEX]); 3280942c5e3cSpl196000 ci = ddi_get32(acc, 3281942c5e3cSpl196000 &softs->qtablep->qt_qindex[queue][AAC_CONSUMER_INDEX]); 3282942c5e3cSpl196000 3283942c5e3cSpl196000 /* Check for queue empty */ 3284942c5e3cSpl196000 if (ci == pi) 3285942c5e3cSpl196000 return (AACERR); 3286942c5e3cSpl196000 3287942c5e3cSpl196000 if (pi >= aac_qinfo[queue].size) 3288942c5e3cSpl196000 pi = 0; 3289942c5e3cSpl196000 3290942c5e3cSpl196000 /* Check for queue full */ 3291942c5e3cSpl196000 if (ci == pi + 1) 3292942c5e3cSpl196000 unfull = 1; 3293942c5e3cSpl196000 3294942c5e3cSpl196000 /* 3295942c5e3cSpl196000 * The controller does not wrap the queue, 3296942c5e3cSpl196000 * so we have to do it by ourselves 3297942c5e3cSpl196000 */ 3298942c5e3cSpl196000 if (ci >= aac_qinfo[queue].size) 3299942c5e3cSpl196000 ci = 0; 3300942c5e3cSpl196000 3301942c5e3cSpl196000 /* Fetch the entry */ 3302a74f7440Spl196000 (void) ddi_dma_sync(dma, (uintptr_t)(softs->qentries[queue] + pi) - \ 3303a74f7440Spl196000 (uintptr_t)softs->comm_space, sizeof (struct aac_queue_entry), 3304942c5e3cSpl196000 DDI_DMA_SYNC_FORCPU); 3305942c5e3cSpl196000 if (aac_check_dma_handle(dma) != DDI_SUCCESS) { 3306942c5e3cSpl196000 ddi_fm_service_impact(softs->devinfo_p, DDI_SERVICE_UNAFFECTED); 3307942c5e3cSpl196000 return (AACERR); 3308942c5e3cSpl196000 } 3309942c5e3cSpl196000 3310942c5e3cSpl196000 switch (queue) { 3311942c5e3cSpl196000 case AAC_HOST_NORM_RESP_Q: 3312942c5e3cSpl196000 case AAC_HOST_HIGH_RESP_Q: 3313942c5e3cSpl196000 *idxp = ddi_get32(acc, 3314942c5e3cSpl196000 &(softs->qentries[queue] + ci)->aq_fib_addr); 3315942c5e3cSpl196000 break; 3316942c5e3cSpl196000 3317942c5e3cSpl196000 case AAC_HOST_NORM_CMD_Q: 3318942c5e3cSpl196000 case AAC_HOST_HIGH_CMD_Q: 3319942c5e3cSpl196000 *idxp = ddi_get32(acc, 3320942c5e3cSpl196000 &(softs->qentries[queue] + ci)->aq_fib_addr) / AAC_FIB_SIZE; 3321942c5e3cSpl196000 break; 3322942c5e3cSpl196000 3323942c5e3cSpl196000 default: 3324942c5e3cSpl196000 cmn_err(CE_NOTE, "!Invalid queue in aac_fib_dequeue()"); 3325942c5e3cSpl196000 return (AACERR); 3326942c5e3cSpl196000 } 3327942c5e3cSpl196000 3328942c5e3cSpl196000 /* Update consumer index */ 3329942c5e3cSpl196000 ddi_put32(acc, &softs->qtablep->qt_qindex[queue][AAC_CONSUMER_INDEX], 3330942c5e3cSpl196000 ci + 1); 3331942c5e3cSpl196000 (void) ddi_dma_sync(dma, 3332a74f7440Spl196000 (uintptr_t)&softs->qtablep->qt_qindex[queue][AAC_CONSUMER_INDEX] - \ 3333a74f7440Spl196000 (uintptr_t)softs->comm_space, sizeof (uint32_t), 3334942c5e3cSpl196000 DDI_DMA_SYNC_FORDEV); 3335942c5e3cSpl196000 3336942c5e3cSpl196000 if (unfull && aac_qinfo[queue].notify != 0) 3337942c5e3cSpl196000 AAC_NOTIFY(softs, aac_qinfo[queue].notify); 3338942c5e3cSpl196000 return (AACOK); 3339942c5e3cSpl196000 } 3340942c5e3cSpl196000 3341942c5e3cSpl196000 static struct aac_mntinforesp * 3342f42c2f53Szhongyan gu - Sun Microsystems - Beijing China aac_get_mntinfo(struct aac_softstate *softs, int cid) 3343942c5e3cSpl196000 { 3344f42c2f53Szhongyan gu - Sun Microsystems - Beijing China ddi_acc_handle_t acc = softs->sync_ac.slotp->fib_acc_handle; 3345f42c2f53Szhongyan gu - Sun Microsystems - Beijing China struct aac_fib *fibp = softs->sync_ac.slotp->fibp; 3346942c5e3cSpl196000 struct aac_mntinfo *mi = (struct aac_mntinfo *)&fibp->data[0]; 3347942c5e3cSpl196000 struct aac_mntinforesp *mir; 3348942c5e3cSpl196000 3349942c5e3cSpl196000 ddi_put32(acc, &mi->Command, /* Use 64-bit LBA if enabled */ 3350942c5e3cSpl196000 (softs->flags & AAC_FLAGS_LBA_64BIT) ? 3351942c5e3cSpl196000 VM_NameServe64 : VM_NameServe); 3352942c5e3cSpl196000 ddi_put32(acc, &mi->MntType, FT_FILESYS); 3353942c5e3cSpl196000 ddi_put32(acc, &mi->MntCount, cid); 3354942c5e3cSpl196000 3355942c5e3cSpl196000 if (aac_sync_fib(softs, ContainerCommand, 3356942c5e3cSpl196000 AAC_FIB_SIZEOF(struct aac_mntinfo)) == AACERR) { 3357942c5e3cSpl196000 AACDB_PRINT(softs, CE_WARN, "Error probe container %d", cid); 3358942c5e3cSpl196000 return (NULL); 3359942c5e3cSpl196000 } 3360942c5e3cSpl196000 3361942c5e3cSpl196000 mir = (struct aac_mntinforesp *)&fibp->data[0]; 3362942c5e3cSpl196000 if (ddi_get32(acc, &mir->Status) == ST_OK) 3363942c5e3cSpl196000 return (mir); 3364942c5e3cSpl196000 return (NULL); 3365942c5e3cSpl196000 } 3366942c5e3cSpl196000 3367942c5e3cSpl196000 static int 3368942c5e3cSpl196000 aac_get_container_count(struct aac_softstate *softs, int *count) 3369942c5e3cSpl196000 { 3370f42c2f53Szhongyan gu - Sun Microsystems - Beijing China ddi_acc_handle_t acc; 3371942c5e3cSpl196000 struct aac_mntinforesp *mir; 3372f42c2f53Szhongyan gu - Sun Microsystems - Beijing China int rval; 3373942c5e3cSpl196000 3374f42c2f53Szhongyan gu - Sun Microsystems - Beijing China (void) aac_sync_fib_slot_bind(softs, &softs->sync_ac); 3375f42c2f53Szhongyan gu - Sun Microsystems - Beijing China acc = softs->sync_ac.slotp->fib_acc_handle; 3376f42c2f53Szhongyan gu - Sun Microsystems - Beijing China 3377f42c2f53Szhongyan gu - Sun Microsystems - Beijing China if ((mir = aac_get_mntinfo(softs, 0)) == NULL) { 3378f42c2f53Szhongyan gu - Sun Microsystems - Beijing China rval = AACERR; 3379f42c2f53Szhongyan gu - Sun Microsystems - Beijing China goto finish; 3380f42c2f53Szhongyan gu - Sun Microsystems - Beijing China } 3381942c5e3cSpl196000 *count = ddi_get32(acc, &mir->MntRespCount); 3382942c5e3cSpl196000 if (*count > AAC_MAX_LD) { 3383942c5e3cSpl196000 AACDB_PRINT(softs, CE_CONT, 3384942c5e3cSpl196000 "container count(%d) > AAC_MAX_LD", *count); 3385f42c2f53Szhongyan gu - Sun Microsystems - Beijing China rval = AACERR; 3386f42c2f53Szhongyan gu - Sun Microsystems - Beijing China goto finish; 3387942c5e3cSpl196000 } 3388f42c2f53Szhongyan gu - Sun Microsystems - Beijing China rval = AACOK; 3389f42c2f53Szhongyan gu - Sun Microsystems - Beijing China 3390f42c2f53Szhongyan gu - Sun Microsystems - Beijing China finish: 3391f42c2f53Szhongyan gu - Sun Microsystems - Beijing China aac_sync_fib_slot_release(softs, &softs->sync_ac); 3392f42c2f53Szhongyan gu - Sun Microsystems - Beijing China return (rval); 3393942c5e3cSpl196000 } 3394942c5e3cSpl196000 3395942c5e3cSpl196000 static int 3396942c5e3cSpl196000 aac_get_container_uid(struct aac_softstate *softs, uint32_t cid, uint32_t *uid) 3397942c5e3cSpl196000 { 3398f42c2f53Szhongyan gu - Sun Microsystems - Beijing China ddi_acc_handle_t acc = softs->sync_ac.slotp->fib_acc_handle; 3399942c5e3cSpl196000 struct aac_Container *ct = (struct aac_Container *) \ 3400f42c2f53Szhongyan gu - Sun Microsystems - Beijing China &softs->sync_ac.slotp->fibp->data[0]; 3401942c5e3cSpl196000 3402942c5e3cSpl196000 bzero(ct, sizeof (*ct) - CT_PACKET_SIZE); 3403942c5e3cSpl196000 ddi_put32(acc, &ct->Command, VM_ContainerConfig); 3404942c5e3cSpl196000 ddi_put32(acc, &ct->CTCommand.command, CT_CID_TO_32BITS_UID); 3405942c5e3cSpl196000 ddi_put32(acc, &ct->CTCommand.param[0], cid); 3406942c5e3cSpl196000 3407942c5e3cSpl196000 if (aac_sync_fib(softs, ContainerCommand, 3408942c5e3cSpl196000 AAC_FIB_SIZEOF(struct aac_Container)) == AACERR) 3409942c5e3cSpl196000 return (AACERR); 3410942c5e3cSpl196000 if (ddi_get32(acc, &ct->CTCommand.param[0]) != CT_OK) 3411942c5e3cSpl196000 return (AACERR); 3412942c5e3cSpl196000 3413942c5e3cSpl196000 *uid = ddi_get32(acc, &ct->CTCommand.param[1]); 3414942c5e3cSpl196000 return (AACOK); 3415942c5e3cSpl196000 } 3416942c5e3cSpl196000 3417f42c2f53Szhongyan gu - Sun Microsystems - Beijing China /* 3418f42c2f53Szhongyan gu - Sun Microsystems - Beijing China * Request information of the container cid 3419f42c2f53Szhongyan gu - Sun Microsystems - Beijing China */ 3420f42c2f53Szhongyan gu - Sun Microsystems - Beijing China static struct aac_mntinforesp * 3421f42c2f53Szhongyan gu - Sun Microsystems - Beijing China aac_get_container_info(struct aac_softstate *softs, int cid) 3422f42c2f53Szhongyan gu - Sun Microsystems - Beijing China { 3423f42c2f53Szhongyan gu - Sun Microsystems - Beijing China ddi_acc_handle_t acc = softs->sync_ac.slotp->fib_acc_handle; 3424f42c2f53Szhongyan gu - Sun Microsystems - Beijing China struct aac_mntinforesp *mir; 3425f42c2f53Szhongyan gu - Sun Microsystems - Beijing China int rval_uid; 3426f42c2f53Szhongyan gu - Sun Microsystems - Beijing China uint32_t uid; 3427f42c2f53Szhongyan gu - Sun Microsystems - Beijing China 3428f42c2f53Szhongyan gu - Sun Microsystems - Beijing China /* Get container UID first so that it will not overwrite mntinfo */ 3429f42c2f53Szhongyan gu - Sun Microsystems - Beijing China rval_uid = aac_get_container_uid(softs, cid, &uid); 3430f42c2f53Szhongyan gu - Sun Microsystems - Beijing China 3431f42c2f53Szhongyan gu - Sun Microsystems - Beijing China /* Get container basic info */ 3432f42c2f53Szhongyan gu - Sun Microsystems - Beijing China if ((mir = aac_get_mntinfo(softs, cid)) == NULL) { 3433f42c2f53Szhongyan gu - Sun Microsystems - Beijing China AACDB_PRINT(softs, CE_CONT, 3434f42c2f53Szhongyan gu - Sun Microsystems - Beijing China "query container %d info failed", cid); 3435f42c2f53Szhongyan gu - Sun Microsystems - Beijing China return (NULL); 3436f42c2f53Szhongyan gu - Sun Microsystems - Beijing China } 3437f42c2f53Szhongyan gu - Sun Microsystems - Beijing China if (ddi_get32(acc, &mir->MntObj.VolType) == CT_NONE) 3438f42c2f53Szhongyan gu - Sun Microsystems - Beijing China return (mir); 3439f42c2f53Szhongyan gu - Sun Microsystems - Beijing China if (rval_uid != AACOK) { 3440f42c2f53Szhongyan gu - Sun Microsystems - Beijing China AACDB_PRINT(softs, CE_CONT, 3441f42c2f53Szhongyan gu - Sun Microsystems - Beijing China "query container %d uid failed", cid); 3442f42c2f53Szhongyan gu - Sun Microsystems - Beijing China return (NULL); 3443f42c2f53Szhongyan gu - Sun Microsystems - Beijing China } 3444f42c2f53Szhongyan gu - Sun Microsystems - Beijing China 3445f42c2f53Szhongyan gu - Sun Microsystems - Beijing China ddi_put32(acc, &mir->Status, uid); 3446f42c2f53Szhongyan gu - Sun Microsystems - Beijing China return (mir); 3447f42c2f53Szhongyan gu - Sun Microsystems - Beijing China } 3448f42c2f53Szhongyan gu - Sun Microsystems - Beijing China 34490749e8deSXin Chen - Sun Microsystems - Beijing China static enum aac_cfg_event 3450942c5e3cSpl196000 aac_probe_container(struct aac_softstate *softs, uint32_t cid) 3451942c5e3cSpl196000 { 34520749e8deSXin Chen - Sun Microsystems - Beijing China enum aac_cfg_event event = AAC_CFG_NULL_NOEXIST; 3453942c5e3cSpl196000 struct aac_container *dvp = &softs->containers[cid]; 3454942c5e3cSpl196000 struct aac_mntinforesp *mir; 34550749e8deSXin Chen - Sun Microsystems - Beijing China ddi_acc_handle_t acc; 3456f42c2f53Szhongyan gu - Sun Microsystems - Beijing China 3457f42c2f53Szhongyan gu - Sun Microsystems - Beijing China (void) aac_sync_fib_slot_bind(softs, &softs->sync_ac); 3458f42c2f53Szhongyan gu - Sun Microsystems - Beijing China acc = softs->sync_ac.slotp->fib_acc_handle; 3459942c5e3cSpl196000 3460942c5e3cSpl196000 /* Get container basic info */ 3461f42c2f53Szhongyan gu - Sun Microsystems - Beijing China if ((mir = aac_get_container_info(softs, cid)) == NULL) { 34620749e8deSXin Chen - Sun Microsystems - Beijing China /* AAC_CFG_NULL_NOEXIST */ 3463f42c2f53Szhongyan gu - Sun Microsystems - Beijing China goto finish; 3464f42c2f53Szhongyan gu - Sun Microsystems - Beijing China } 3465942c5e3cSpl196000 3466942c5e3cSpl196000 if (ddi_get32(acc, &mir->MntObj.VolType) == CT_NONE) { 346758bc78c7SXin Chen if (AAC_DEV_IS_VALID(&dvp->dev)) { 3468942c5e3cSpl196000 AACDB_PRINT(softs, CE_NOTE, 3469942c5e3cSpl196000 ">>> Container %d deleted", cid); 347058bc78c7SXin Chen dvp->dev.flags &= ~AAC_DFLAG_VALID; 34710749e8deSXin Chen - Sun Microsystems - Beijing China event = AAC_CFG_DELETE; 3472942c5e3cSpl196000 } 34730749e8deSXin Chen - Sun Microsystems - Beijing China /* AAC_CFG_NULL_NOEXIST */ 3474942c5e3cSpl196000 } else { 34750749e8deSXin Chen - Sun Microsystems - Beijing China uint64_t size; 34760749e8deSXin Chen - Sun Microsystems - Beijing China uint32_t uid; 34770749e8deSXin Chen - Sun Microsystems - Beijing China 34780749e8deSXin Chen - Sun Microsystems - Beijing China event = AAC_CFG_NULL_EXIST; 34790749e8deSXin Chen - Sun Microsystems - Beijing China 3480942c5e3cSpl196000 size = AAC_MIR_SIZE(softs, acc, mir); 3481f42c2f53Szhongyan gu - Sun Microsystems - Beijing China uid = ddi_get32(acc, &mir->Status); 348258bc78c7SXin Chen if (AAC_DEV_IS_VALID(&dvp->dev)) { 3483942c5e3cSpl196000 if (dvp->uid != uid) { 3484942c5e3cSpl196000 AACDB_PRINT(softs, CE_WARN, 3485942c5e3cSpl196000 ">>> Container %u uid changed to %d", 3486942c5e3cSpl196000 cid, uid); 3487942c5e3cSpl196000 dvp->uid = uid; 34880749e8deSXin Chen - Sun Microsystems - Beijing China event = AAC_CFG_CHANGE; 3489942c5e3cSpl196000 } 3490942c5e3cSpl196000 if (dvp->size != size) { 3491942c5e3cSpl196000 AACDB_PRINT(softs, CE_NOTE, 3492942c5e3cSpl196000 ">>> Container %u size changed to %"PRIu64, 3493942c5e3cSpl196000 cid, size); 3494942c5e3cSpl196000 dvp->size = size; 34950749e8deSXin Chen - Sun Microsystems - Beijing China event = AAC_CFG_CHANGE; 3496942c5e3cSpl196000 } 3497942c5e3cSpl196000 } else { /* Init new container */ 3498942c5e3cSpl196000 AACDB_PRINT(softs, CE_NOTE, 349958bc78c7SXin Chen ">>> Container %d added: " \ 350058bc78c7SXin Chen "size=0x%x.%08x, type=%d, name=%s", 350158bc78c7SXin Chen cid, 350258bc78c7SXin Chen ddi_get32(acc, &mir->MntObj.CapacityHigh), 350358bc78c7SXin Chen ddi_get32(acc, &mir->MntObj.Capacity), 350458bc78c7SXin Chen ddi_get32(acc, &mir->MntObj.VolType), 350558bc78c7SXin Chen mir->MntObj.FileSystemName); 350658bc78c7SXin Chen dvp->dev.flags |= AAC_DFLAG_VALID; 350758bc78c7SXin Chen dvp->dev.type = AAC_DEV_LD; 3508942c5e3cSpl196000 3509942c5e3cSpl196000 dvp->cid = cid; 3510942c5e3cSpl196000 dvp->uid = uid; 3511942c5e3cSpl196000 dvp->size = size; 3512942c5e3cSpl196000 dvp->locked = 0; 3513942c5e3cSpl196000 dvp->deleted = 0; 35140749e8deSXin Chen - Sun Microsystems - Beijing China 35150749e8deSXin Chen - Sun Microsystems - Beijing China event = AAC_CFG_ADD; 3516942c5e3cSpl196000 } 3517942c5e3cSpl196000 } 3518f42c2f53Szhongyan gu - Sun Microsystems - Beijing China 3519f42c2f53Szhongyan gu - Sun Microsystems - Beijing China finish: 3520f42c2f53Szhongyan gu - Sun Microsystems - Beijing China aac_sync_fib_slot_release(softs, &softs->sync_ac); 35210749e8deSXin Chen - Sun Microsystems - Beijing China return (event); 3522942c5e3cSpl196000 } 3523942c5e3cSpl196000 3524942c5e3cSpl196000 /* 3525942c5e3cSpl196000 * Do a rescan of all the possible containers and update the container list 352658bc78c7SXin Chen * with newly online/offline containers, and prepare for autoconfiguration. 3527942c5e3cSpl196000 */ 3528942c5e3cSpl196000 static int 3529942c5e3cSpl196000 aac_probe_containers(struct aac_softstate *softs) 3530942c5e3cSpl196000 { 3531942c5e3cSpl196000 int i, count, total; 3532942c5e3cSpl196000 3533942c5e3cSpl196000 /* Loop over possible containers */ 3534942c5e3cSpl196000 count = softs->container_count; 3535942c5e3cSpl196000 if (aac_get_container_count(softs, &count) == AACERR) 3536942c5e3cSpl196000 return (AACERR); 35370749e8deSXin Chen - Sun Microsystems - Beijing China 3538942c5e3cSpl196000 for (i = total = 0; i < count; i++) { 35390749e8deSXin Chen - Sun Microsystems - Beijing China enum aac_cfg_event event = aac_probe_container(softs, i); 35400749e8deSXin Chen - Sun Microsystems - Beijing China if ((event != AAC_CFG_NULL_NOEXIST) && 35410749e8deSXin Chen - Sun Microsystems - Beijing China (event != AAC_CFG_NULL_EXIST)) { 35420749e8deSXin Chen - Sun Microsystems - Beijing China (void) aac_handle_dr(softs, i, -1, event); 3543942c5e3cSpl196000 total++; 3544942c5e3cSpl196000 } 35450749e8deSXin Chen - Sun Microsystems - Beijing China } 35460749e8deSXin Chen - Sun Microsystems - Beijing China 3547942c5e3cSpl196000 if (count < softs->container_count) { 3548942c5e3cSpl196000 struct aac_container *dvp; 3549942c5e3cSpl196000 3550942c5e3cSpl196000 for (dvp = &softs->containers[count]; 3551942c5e3cSpl196000 dvp < &softs->containers[softs->container_count]; dvp++) { 355258bc78c7SXin Chen if (!AAC_DEV_IS_VALID(&dvp->dev)) 3553942c5e3cSpl196000 continue; 3554942c5e3cSpl196000 AACDB_PRINT(softs, CE_NOTE, ">>> Container %d deleted", 3555942c5e3cSpl196000 dvp->cid); 355658bc78c7SXin Chen dvp->dev.flags &= ~AAC_DFLAG_VALID; 35570749e8deSXin Chen - Sun Microsystems - Beijing China (void) aac_handle_dr(softs, dvp->cid, -1, 35580749e8deSXin Chen - Sun Microsystems - Beijing China AAC_CFG_DELETE); 3559942c5e3cSpl196000 } 3560942c5e3cSpl196000 } 35610749e8deSXin Chen - Sun Microsystems - Beijing China 3562942c5e3cSpl196000 softs->container_count = count; 3563942c5e3cSpl196000 AACDB_PRINT(softs, CE_CONT, "?Total %d container(s) found", total); 3564942c5e3cSpl196000 return (AACOK); 3565942c5e3cSpl196000 } 3566942c5e3cSpl196000 3567942c5e3cSpl196000 static int 35683fced439Szhongyan gu - Sun Microsystems - Beijing China aac_probe_jbod(struct aac_softstate *softs, int tgt, int event) 35693fced439Szhongyan gu - Sun Microsystems - Beijing China { 3570*3ce33fb0SHengqing Hu ASSERT(AAC_MAX_LD <= tgt); 3571*3ce33fb0SHengqing Hu ASSERT(tgt < AAC_MAX_DEV(softs)); 35723fced439Szhongyan gu - Sun Microsystems - Beijing China struct aac_device *dvp; 35733fced439Szhongyan gu - Sun Microsystems - Beijing China dvp = AAC_DEV(softs, tgt); 35743fced439Szhongyan gu - Sun Microsystems - Beijing China 35753fced439Szhongyan gu - Sun Microsystems - Beijing China switch (event) { 35763fced439Szhongyan gu - Sun Microsystems - Beijing China case AAC_CFG_ADD: 35773fced439Szhongyan gu - Sun Microsystems - Beijing China AACDB_PRINT(softs, CE_NOTE, 35783fced439Szhongyan gu - Sun Microsystems - Beijing China ">>> Jbod %d added", tgt - AAC_MAX_LD); 35793fced439Szhongyan gu - Sun Microsystems - Beijing China dvp->flags |= AAC_DFLAG_VALID; 35803fced439Szhongyan gu - Sun Microsystems - Beijing China dvp->type = AAC_DEV_PD; 35813fced439Szhongyan gu - Sun Microsystems - Beijing China break; 35823fced439Szhongyan gu - Sun Microsystems - Beijing China case AAC_CFG_DELETE: 35833fced439Szhongyan gu - Sun Microsystems - Beijing China AACDB_PRINT(softs, CE_NOTE, 35843fced439Szhongyan gu - Sun Microsystems - Beijing China ">>> Jbod %d deleted", tgt - AAC_MAX_LD); 35853fced439Szhongyan gu - Sun Microsystems - Beijing China dvp->flags &= ~AAC_DFLAG_VALID; 35863fced439Szhongyan gu - Sun Microsystems - Beijing China break; 35873fced439Szhongyan gu - Sun Microsystems - Beijing China default: 35883fced439Szhongyan gu - Sun Microsystems - Beijing China return (AACERR); 35893fced439Szhongyan gu - Sun Microsystems - Beijing China } 35903fced439Szhongyan gu - Sun Microsystems - Beijing China (void) aac_handle_dr(softs, tgt, 0, event); 35913fced439Szhongyan gu - Sun Microsystems - Beijing China return (AACOK); 35923fced439Szhongyan gu - Sun Microsystems - Beijing China } 35933fced439Szhongyan gu - Sun Microsystems - Beijing China 35943fced439Szhongyan gu - Sun Microsystems - Beijing China static int 3595942c5e3cSpl196000 aac_alloc_comm_space(struct aac_softstate *softs) 3596942c5e3cSpl196000 { 3597942c5e3cSpl196000 size_t rlen; 3598942c5e3cSpl196000 ddi_dma_cookie_t cookie; 3599942c5e3cSpl196000 uint_t cookien; 3600942c5e3cSpl196000 3601942c5e3cSpl196000 /* Allocate DMA for comm. space */ 3602942c5e3cSpl196000 if (ddi_dma_alloc_handle( 3603942c5e3cSpl196000 softs->devinfo_p, 3604942c5e3cSpl196000 &softs->addr_dma_attr, 3605942c5e3cSpl196000 DDI_DMA_SLEEP, 3606942c5e3cSpl196000 NULL, 3607942c5e3cSpl196000 &softs->comm_space_dma_handle) != DDI_SUCCESS) { 3608942c5e3cSpl196000 AACDB_PRINT(softs, CE_WARN, 3609942c5e3cSpl196000 "Cannot alloc dma handle for communication area"); 3610942c5e3cSpl196000 goto error; 3611942c5e3cSpl196000 } 3612942c5e3cSpl196000 if (ddi_dma_mem_alloc( 3613942c5e3cSpl196000 softs->comm_space_dma_handle, 3614942c5e3cSpl196000 sizeof (struct aac_comm_space), 361558bc78c7SXin Chen &softs->acc_attr, 3616942c5e3cSpl196000 DDI_DMA_RDWR | DDI_DMA_CONSISTENT, 3617942c5e3cSpl196000 DDI_DMA_SLEEP, 3618942c5e3cSpl196000 NULL, 3619942c5e3cSpl196000 (caddr_t *)&softs->comm_space, 3620942c5e3cSpl196000 &rlen, 3621942c5e3cSpl196000 &softs->comm_space_acc_handle) != DDI_SUCCESS) { 3622942c5e3cSpl196000 AACDB_PRINT(softs, CE_WARN, 3623942c5e3cSpl196000 "Cannot alloc mem for communication area"); 3624942c5e3cSpl196000 goto error; 3625942c5e3cSpl196000 } 3626942c5e3cSpl196000 if (ddi_dma_addr_bind_handle( 3627942c5e3cSpl196000 softs->comm_space_dma_handle, 3628942c5e3cSpl196000 NULL, 3629942c5e3cSpl196000 (caddr_t)softs->comm_space, 3630942c5e3cSpl196000 sizeof (struct aac_comm_space), 3631942c5e3cSpl196000 DDI_DMA_RDWR | DDI_DMA_CONSISTENT, 3632942c5e3cSpl196000 DDI_DMA_SLEEP, 3633942c5e3cSpl196000 NULL, 3634942c5e3cSpl196000 &cookie, 3635942c5e3cSpl196000 &cookien) != DDI_DMA_MAPPED) { 3636942c5e3cSpl196000 AACDB_PRINT(softs, CE_WARN, 3637942c5e3cSpl196000 "DMA bind failed for communication area"); 3638942c5e3cSpl196000 goto error; 3639942c5e3cSpl196000 } 3640942c5e3cSpl196000 softs->comm_space_phyaddr = cookie.dmac_address; 3641942c5e3cSpl196000 3642942c5e3cSpl196000 return (AACOK); 3643942c5e3cSpl196000 error: 3644942c5e3cSpl196000 if (softs->comm_space_acc_handle) { 3645942c5e3cSpl196000 ddi_dma_mem_free(&softs->comm_space_acc_handle); 3646942c5e3cSpl196000 softs->comm_space_acc_handle = NULL; 3647942c5e3cSpl196000 } 3648942c5e3cSpl196000 if (softs->comm_space_dma_handle) { 3649942c5e3cSpl196000 ddi_dma_free_handle(&softs->comm_space_dma_handle); 3650942c5e3cSpl196000 softs->comm_space_dma_handle = NULL; 3651942c5e3cSpl196000 } 3652942c5e3cSpl196000 return (AACERR); 3653942c5e3cSpl196000 } 3654942c5e3cSpl196000 3655942c5e3cSpl196000 static void 3656942c5e3cSpl196000 aac_free_comm_space(struct aac_softstate *softs) 3657942c5e3cSpl196000 { 3658942c5e3cSpl196000 3659942c5e3cSpl196000 (void) ddi_dma_unbind_handle(softs->comm_space_dma_handle); 3660942c5e3cSpl196000 ddi_dma_mem_free(&softs->comm_space_acc_handle); 3661942c5e3cSpl196000 softs->comm_space_acc_handle = NULL; 3662942c5e3cSpl196000 ddi_dma_free_handle(&softs->comm_space_dma_handle); 3663942c5e3cSpl196000 softs->comm_space_dma_handle = NULL; 3664942c5e3cSpl196000 softs->comm_space_phyaddr = NULL; 3665942c5e3cSpl196000 } 3666942c5e3cSpl196000 3667942c5e3cSpl196000 /* 3668942c5e3cSpl196000 * Initialize the data structures that are required for the communication 3669942c5e3cSpl196000 * interface to operate 3670942c5e3cSpl196000 */ 3671942c5e3cSpl196000 static int 3672942c5e3cSpl196000 aac_setup_comm_space(struct aac_softstate *softs) 3673942c5e3cSpl196000 { 3674942c5e3cSpl196000 ddi_dma_handle_t dma = softs->comm_space_dma_handle; 3675942c5e3cSpl196000 ddi_acc_handle_t acc = softs->comm_space_acc_handle; 3676942c5e3cSpl196000 uint32_t comm_space_phyaddr; 3677942c5e3cSpl196000 struct aac_adapter_init *initp; 3678942c5e3cSpl196000 int qoffset; 3679942c5e3cSpl196000 3680942c5e3cSpl196000 comm_space_phyaddr = softs->comm_space_phyaddr; 3681942c5e3cSpl196000 3682942c5e3cSpl196000 /* Setup adapter init struct */ 3683942c5e3cSpl196000 initp = &softs->comm_space->init_data; 3684942c5e3cSpl196000 bzero(initp, sizeof (struct aac_adapter_init)); 3685942c5e3cSpl196000 3686942c5e3cSpl196000 ddi_put32(acc, &initp->InitStructRevision, AAC_INIT_STRUCT_REVISION); 3687942c5e3cSpl196000 ddi_put32(acc, &initp->HostElapsedSeconds, ddi_get_time()); 3688942c5e3cSpl196000 3689942c5e3cSpl196000 /* Setup new/old comm. specific data */ 3690942c5e3cSpl196000 if (softs->flags & AAC_FLAGS_RAW_IO) { 3691b40e8a89Szhongyan gu - Sun Microsystems - Beijing China uint32_t init_flags = 0; 3692b40e8a89Szhongyan gu - Sun Microsystems - Beijing China 3693b40e8a89Szhongyan gu - Sun Microsystems - Beijing China if (softs->flags & AAC_FLAGS_NEW_COMM) 3694b40e8a89Szhongyan gu - Sun Microsystems - Beijing China init_flags |= AAC_INIT_FLAGS_NEW_COMM_SUPPORTED; 3695b40e8a89Szhongyan gu - Sun Microsystems - Beijing China /* AAC_SUPPORTED_POWER_MANAGEMENT */ 3696b40e8a89Szhongyan gu - Sun Microsystems - Beijing China init_flags |= AAC_INIT_FLAGS_DRIVER_SUPPORTS_PM; 3697b40e8a89Szhongyan gu - Sun Microsystems - Beijing China init_flags |= AAC_INIT_FLAGS_DRIVER_USES_UTC_TIME; 3698b40e8a89Szhongyan gu - Sun Microsystems - Beijing China 3699942c5e3cSpl196000 ddi_put32(acc, &initp->InitStructRevision, 3700942c5e3cSpl196000 AAC_INIT_STRUCT_REVISION_4); 3701b40e8a89Szhongyan gu - Sun Microsystems - Beijing China ddi_put32(acc, &initp->InitFlags, init_flags); 3702942c5e3cSpl196000 /* Setup the preferred settings */ 3703942c5e3cSpl196000 ddi_put32(acc, &initp->MaxIoCommands, softs->aac_max_fibs); 3704942c5e3cSpl196000 ddi_put32(acc, &initp->MaxIoSize, 3705942c5e3cSpl196000 (softs->aac_max_sectors << 9)); 3706942c5e3cSpl196000 ddi_put32(acc, &initp->MaxFibSize, softs->aac_max_fib_size); 3707942c5e3cSpl196000 } else { 3708942c5e3cSpl196000 /* 3709942c5e3cSpl196000 * Tells the adapter about the physical location of various 3710942c5e3cSpl196000 * important shared data structures 3711942c5e3cSpl196000 */ 3712942c5e3cSpl196000 ddi_put32(acc, &initp->AdapterFibsPhysicalAddress, 3713942c5e3cSpl196000 comm_space_phyaddr + \ 3714942c5e3cSpl196000 offsetof(struct aac_comm_space, adapter_fibs)); 3715942c5e3cSpl196000 ddi_put32(acc, &initp->AdapterFibsVirtualAddress, 0); 3716942c5e3cSpl196000 ddi_put32(acc, &initp->AdapterFibAlign, AAC_FIB_SIZE); 3717942c5e3cSpl196000 ddi_put32(acc, &initp->AdapterFibsSize, 3718942c5e3cSpl196000 AAC_ADAPTER_FIBS * AAC_FIB_SIZE); 3719942c5e3cSpl196000 ddi_put32(acc, &initp->PrintfBufferAddress, 3720942c5e3cSpl196000 comm_space_phyaddr + \ 3721942c5e3cSpl196000 offsetof(struct aac_comm_space, adapter_print_buf)); 3722942c5e3cSpl196000 ddi_put32(acc, &initp->PrintfBufferSize, 3723942c5e3cSpl196000 AAC_ADAPTER_PRINT_BUFSIZE); 3724942c5e3cSpl196000 ddi_put32(acc, &initp->MiniPortRevision, 3725942c5e3cSpl196000 AAC_INIT_STRUCT_MINIPORT_REVISION); 3726942c5e3cSpl196000 ddi_put32(acc, &initp->HostPhysMemPages, AAC_MAX_PFN); 3727942c5e3cSpl196000 3728942c5e3cSpl196000 qoffset = (comm_space_phyaddr + \ 3729942c5e3cSpl196000 offsetof(struct aac_comm_space, qtable)) % \ 3730942c5e3cSpl196000 AAC_QUEUE_ALIGN; 3731942c5e3cSpl196000 if (qoffset) 3732942c5e3cSpl196000 qoffset = AAC_QUEUE_ALIGN - qoffset; 3733942c5e3cSpl196000 softs->qtablep = (struct aac_queue_table *) \ 3734942c5e3cSpl196000 ((char *)&softs->comm_space->qtable + qoffset); 3735942c5e3cSpl196000 ddi_put32(acc, &initp->CommHeaderAddress, comm_space_phyaddr + \ 3736942c5e3cSpl196000 offsetof(struct aac_comm_space, qtable) + qoffset); 3737942c5e3cSpl196000 3738942c5e3cSpl196000 /* Init queue table */ 3739942c5e3cSpl196000 ddi_put32(acc, &softs->qtablep-> \ 3740942c5e3cSpl196000 qt_qindex[AAC_HOST_NORM_CMD_Q][AAC_PRODUCER_INDEX], 3741942c5e3cSpl196000 AAC_HOST_NORM_CMD_ENTRIES); 3742942c5e3cSpl196000 ddi_put32(acc, &softs->qtablep-> \ 3743942c5e3cSpl196000 qt_qindex[AAC_HOST_NORM_CMD_Q][AAC_CONSUMER_INDEX], 3744942c5e3cSpl196000 AAC_HOST_NORM_CMD_ENTRIES); 3745942c5e3cSpl196000 ddi_put32(acc, &softs->qtablep-> \ 3746942c5e3cSpl196000 qt_qindex[AAC_HOST_HIGH_CMD_Q][AAC_PRODUCER_INDEX], 3747942c5e3cSpl196000 AAC_HOST_HIGH_CMD_ENTRIES); 3748942c5e3cSpl196000 ddi_put32(acc, &softs->qtablep-> \ 3749942c5e3cSpl196000 qt_qindex[AAC_HOST_HIGH_CMD_Q][AAC_CONSUMER_INDEX], 3750942c5e3cSpl196000 AAC_HOST_HIGH_CMD_ENTRIES); 3751942c5e3cSpl196000 ddi_put32(acc, &softs->qtablep-> \ 3752942c5e3cSpl196000 qt_qindex[AAC_ADAP_NORM_CMD_Q][AAC_PRODUCER_INDEX], 3753942c5e3cSpl196000 AAC_ADAP_NORM_CMD_ENTRIES); 3754942c5e3cSpl196000 ddi_put32(acc, &softs->qtablep-> \ 3755942c5e3cSpl196000 qt_qindex[AAC_ADAP_NORM_CMD_Q][AAC_CONSUMER_INDEX], 3756942c5e3cSpl196000 AAC_ADAP_NORM_CMD_ENTRIES); 3757942c5e3cSpl196000 ddi_put32(acc, &softs->qtablep-> \ 3758942c5e3cSpl196000 qt_qindex[AAC_ADAP_HIGH_CMD_Q][AAC_PRODUCER_INDEX], 3759942c5e3cSpl196000 AAC_ADAP_HIGH_CMD_ENTRIES); 3760942c5e3cSpl196000 ddi_put32(acc, &softs->qtablep-> \ 3761942c5e3cSpl196000 qt_qindex[AAC_ADAP_HIGH_CMD_Q][AAC_CONSUMER_INDEX], 3762942c5e3cSpl196000 AAC_ADAP_HIGH_CMD_ENTRIES); 3763942c5e3cSpl196000 ddi_put32(acc, &softs->qtablep-> \ 3764942c5e3cSpl196000 qt_qindex[AAC_HOST_NORM_RESP_Q][AAC_PRODUCER_INDEX], 3765942c5e3cSpl196000 AAC_HOST_NORM_RESP_ENTRIES); 3766942c5e3cSpl196000 ddi_put32(acc, &softs->qtablep-> \ 3767942c5e3cSpl196000 qt_qindex[AAC_HOST_NORM_RESP_Q][AAC_CONSUMER_INDEX], 3768942c5e3cSpl196000 AAC_HOST_NORM_RESP_ENTRIES); 3769942c5e3cSpl196000 ddi_put32(acc, &softs->qtablep-> \ 3770942c5e3cSpl196000 qt_qindex[AAC_HOST_HIGH_RESP_Q][AAC_PRODUCER_INDEX], 3771942c5e3cSpl196000 AAC_HOST_HIGH_RESP_ENTRIES); 3772942c5e3cSpl196000 ddi_put32(acc, &softs->qtablep-> \ 3773942c5e3cSpl196000 qt_qindex[AAC_HOST_HIGH_RESP_Q][AAC_CONSUMER_INDEX], 3774942c5e3cSpl196000 AAC_HOST_HIGH_RESP_ENTRIES); 3775942c5e3cSpl196000 ddi_put32(acc, &softs->qtablep-> \ 3776942c5e3cSpl196000 qt_qindex[AAC_ADAP_NORM_RESP_Q][AAC_PRODUCER_INDEX], 3777942c5e3cSpl196000 AAC_ADAP_NORM_RESP_ENTRIES); 3778942c5e3cSpl196000 ddi_put32(acc, &softs->qtablep-> \ 3779942c5e3cSpl196000 qt_qindex[AAC_ADAP_NORM_RESP_Q][AAC_CONSUMER_INDEX], 3780942c5e3cSpl196000 AAC_ADAP_NORM_RESP_ENTRIES); 3781942c5e3cSpl196000 ddi_put32(acc, &softs->qtablep-> \ 3782942c5e3cSpl196000 qt_qindex[AAC_ADAP_HIGH_RESP_Q][AAC_PRODUCER_INDEX], 3783942c5e3cSpl196000 AAC_ADAP_HIGH_RESP_ENTRIES); 3784942c5e3cSpl196000 ddi_put32(acc, &softs->qtablep-> \ 3785942c5e3cSpl196000 qt_qindex[AAC_ADAP_HIGH_RESP_Q][AAC_CONSUMER_INDEX], 3786942c5e3cSpl196000 AAC_ADAP_HIGH_RESP_ENTRIES); 3787942c5e3cSpl196000 3788942c5e3cSpl196000 /* Init queue entries */ 3789942c5e3cSpl196000 softs->qentries[AAC_HOST_NORM_CMD_Q] = 3790942c5e3cSpl196000 &softs->qtablep->qt_HostNormCmdQueue[0]; 3791942c5e3cSpl196000 softs->qentries[AAC_HOST_HIGH_CMD_Q] = 3792942c5e3cSpl196000 &softs->qtablep->qt_HostHighCmdQueue[0]; 3793942c5e3cSpl196000 softs->qentries[AAC_ADAP_NORM_CMD_Q] = 3794942c5e3cSpl196000 &softs->qtablep->qt_AdapNormCmdQueue[0]; 3795942c5e3cSpl196000 softs->qentries[AAC_ADAP_HIGH_CMD_Q] = 3796942c5e3cSpl196000 &softs->qtablep->qt_AdapHighCmdQueue[0]; 3797942c5e3cSpl196000 softs->qentries[AAC_HOST_NORM_RESP_Q] = 3798942c5e3cSpl196000 &softs->qtablep->qt_HostNormRespQueue[0]; 3799942c5e3cSpl196000 softs->qentries[AAC_HOST_HIGH_RESP_Q] = 3800942c5e3cSpl196000 &softs->qtablep->qt_HostHighRespQueue[0]; 3801942c5e3cSpl196000 softs->qentries[AAC_ADAP_NORM_RESP_Q] = 3802942c5e3cSpl196000 &softs->qtablep->qt_AdapNormRespQueue[0]; 3803942c5e3cSpl196000 softs->qentries[AAC_ADAP_HIGH_RESP_Q] = 3804942c5e3cSpl196000 &softs->qtablep->qt_AdapHighRespQueue[0]; 3805942c5e3cSpl196000 } 3806942c5e3cSpl196000 (void) ddi_dma_sync(dma, 0, 0, DDI_DMA_SYNC_FORDEV); 3807942c5e3cSpl196000 3808942c5e3cSpl196000 /* Send init structure to the card */ 3809942c5e3cSpl196000 if (aac_sync_mbcommand(softs, AAC_MONKER_INITSTRUCT, 3810942c5e3cSpl196000 comm_space_phyaddr + \ 3811942c5e3cSpl196000 offsetof(struct aac_comm_space, init_data), 3812942c5e3cSpl196000 0, 0, 0, NULL) == AACERR) { 3813942c5e3cSpl196000 AACDB_PRINT(softs, CE_WARN, 3814942c5e3cSpl196000 "Cannot send init structure to adapter"); 3815942c5e3cSpl196000 return (AACERR); 3816942c5e3cSpl196000 } 3817942c5e3cSpl196000 3818942c5e3cSpl196000 return (AACOK); 3819942c5e3cSpl196000 } 3820942c5e3cSpl196000 3821942c5e3cSpl196000 static uchar_t * 3822942c5e3cSpl196000 aac_vendor_id(struct aac_softstate *softs, uchar_t *buf) 3823942c5e3cSpl196000 { 3824942c5e3cSpl196000 (void) memset(buf, ' ', AAC_VENDOR_LEN); 3825942c5e3cSpl196000 bcopy(softs->vendor_name, buf, strlen(softs->vendor_name)); 3826942c5e3cSpl196000 return (buf + AAC_VENDOR_LEN); 3827942c5e3cSpl196000 } 3828942c5e3cSpl196000 3829942c5e3cSpl196000 static uchar_t * 3830942c5e3cSpl196000 aac_product_id(struct aac_softstate *softs, uchar_t *buf) 3831942c5e3cSpl196000 { 3832942c5e3cSpl196000 (void) memset(buf, ' ', AAC_PRODUCT_LEN); 3833942c5e3cSpl196000 bcopy(softs->product_name, buf, strlen(softs->product_name)); 3834942c5e3cSpl196000 return (buf + AAC_PRODUCT_LEN); 3835942c5e3cSpl196000 } 3836942c5e3cSpl196000 3837942c5e3cSpl196000 /* 3838942c5e3cSpl196000 * Construct unit serial number from container uid 3839942c5e3cSpl196000 */ 3840942c5e3cSpl196000 static uchar_t * 3841942c5e3cSpl196000 aac_lun_serialno(struct aac_softstate *softs, int tgt, uchar_t *buf) 3842942c5e3cSpl196000 { 3843942c5e3cSpl196000 int i, d; 384458bc78c7SXin Chen uint32_t uid; 3845942c5e3cSpl196000 384658bc78c7SXin Chen ASSERT(tgt >= 0 && tgt < AAC_MAX_LD); 384758bc78c7SXin Chen 384858bc78c7SXin Chen uid = softs->containers[tgt].uid; 3849942c5e3cSpl196000 for (i = 7; i >= 0; i--) { 3850942c5e3cSpl196000 d = uid & 0xf; 3851942c5e3cSpl196000 buf[i] = d > 9 ? 'A' + (d - 0xa) : '0' + d; 3852942c5e3cSpl196000 uid >>= 4; 3853942c5e3cSpl196000 } 3854942c5e3cSpl196000 return (buf + 8); 3855942c5e3cSpl196000 } 3856942c5e3cSpl196000 3857942c5e3cSpl196000 /* 3858942c5e3cSpl196000 * SPC-3 7.5 INQUIRY command implementation 3859942c5e3cSpl196000 */ 3860942c5e3cSpl196000 static void 3861942c5e3cSpl196000 aac_inquiry(struct aac_softstate *softs, struct scsi_pkt *pkt, 3862942c5e3cSpl196000 union scsi_cdb *cdbp, struct buf *bp) 3863942c5e3cSpl196000 { 3864942c5e3cSpl196000 int tgt = pkt->pkt_address.a_target; 3865942c5e3cSpl196000 char *b_addr = NULL; 3866942c5e3cSpl196000 uchar_t page = cdbp->cdb_opaque[2]; 3867942c5e3cSpl196000 3868942c5e3cSpl196000 if (cdbp->cdb_opaque[1] & AAC_CDB_INQUIRY_CMDDT) { 3869942c5e3cSpl196000 /* Command Support Data is not supported */ 3870942c5e3cSpl196000 aac_set_arq_data(pkt, KEY_ILLEGAL_REQUEST, 0x24, 0x00, 0); 3871942c5e3cSpl196000 return; 3872942c5e3cSpl196000 } 3873942c5e3cSpl196000 3874942c5e3cSpl196000 if (bp && bp->b_un.b_addr && bp->b_bcount) { 3875942c5e3cSpl196000 if (bp->b_flags & (B_PHYS | B_PAGEIO)) 3876942c5e3cSpl196000 bp_mapin(bp); 3877942c5e3cSpl196000 b_addr = bp->b_un.b_addr; 3878942c5e3cSpl196000 } 3879942c5e3cSpl196000 3880942c5e3cSpl196000 if (cdbp->cdb_opaque[1] & AAC_CDB_INQUIRY_EVPD) { 3881942c5e3cSpl196000 uchar_t *vpdp = (uchar_t *)b_addr; 3882942c5e3cSpl196000 uchar_t *idp, *sp; 3883942c5e3cSpl196000 3884942c5e3cSpl196000 /* SPC-3 8.4 Vital product data parameters */ 3885942c5e3cSpl196000 switch (page) { 3886942c5e3cSpl196000 case 0x00: 3887942c5e3cSpl196000 /* Supported VPD pages */ 388851ccf66eSjd218194 if (vpdp == NULL || 388951ccf66eSjd218194 bp->b_bcount < (AAC_VPD_PAGE_DATA + 3)) 3890942c5e3cSpl196000 return; 3891942c5e3cSpl196000 bzero(vpdp, AAC_VPD_PAGE_LENGTH); 3892942c5e3cSpl196000 vpdp[AAC_VPD_PAGE_CODE] = 0x00; 3893942c5e3cSpl196000 vpdp[AAC_VPD_PAGE_LENGTH] = 3; 3894942c5e3cSpl196000 3895942c5e3cSpl196000 vpdp[AAC_VPD_PAGE_DATA] = 0x00; 3896942c5e3cSpl196000 vpdp[AAC_VPD_PAGE_DATA + 1] = 0x80; 3897942c5e3cSpl196000 vpdp[AAC_VPD_PAGE_DATA + 2] = 0x83; 3898942c5e3cSpl196000 3899942c5e3cSpl196000 pkt->pkt_state |= STATE_XFERRED_DATA; 3900942c5e3cSpl196000 break; 3901942c5e3cSpl196000 3902942c5e3cSpl196000 case 0x80: 3903942c5e3cSpl196000 /* Unit serial number page */ 390451ccf66eSjd218194 if (vpdp == NULL || 390551ccf66eSjd218194 bp->b_bcount < (AAC_VPD_PAGE_DATA + 8)) 3906942c5e3cSpl196000 return; 3907942c5e3cSpl196000 bzero(vpdp, AAC_VPD_PAGE_LENGTH); 3908942c5e3cSpl196000 vpdp[AAC_VPD_PAGE_CODE] = 0x80; 3909942c5e3cSpl196000 vpdp[AAC_VPD_PAGE_LENGTH] = 8; 3910942c5e3cSpl196000 3911942c5e3cSpl196000 sp = &vpdp[AAC_VPD_PAGE_DATA]; 3912942c5e3cSpl196000 (void) aac_lun_serialno(softs, tgt, sp); 3913942c5e3cSpl196000 3914942c5e3cSpl196000 pkt->pkt_state |= STATE_XFERRED_DATA; 3915942c5e3cSpl196000 break; 3916942c5e3cSpl196000 3917942c5e3cSpl196000 case 0x83: 3918942c5e3cSpl196000 /* Device identification page */ 391951ccf66eSjd218194 if (vpdp == NULL || 392051ccf66eSjd218194 bp->b_bcount < (AAC_VPD_PAGE_DATA + 32)) 3921942c5e3cSpl196000 return; 3922942c5e3cSpl196000 bzero(vpdp, AAC_VPD_PAGE_LENGTH); 3923942c5e3cSpl196000 vpdp[AAC_VPD_PAGE_CODE] = 0x83; 3924942c5e3cSpl196000 3925942c5e3cSpl196000 idp = &vpdp[AAC_VPD_PAGE_DATA]; 3926942c5e3cSpl196000 bzero(idp, AAC_VPD_ID_LENGTH); 3927942c5e3cSpl196000 idp[AAC_VPD_ID_CODESET] = 0x02; 3928942c5e3cSpl196000 idp[AAC_VPD_ID_TYPE] = 0x01; 3929942c5e3cSpl196000 3930942c5e3cSpl196000 /* 3931942c5e3cSpl196000 * SPC-3 Table 111 - Identifier type 3932942c5e3cSpl196000 * One recommanded method of constructing the remainder 3933942c5e3cSpl196000 * of identifier field is to concatenate the product 3934942c5e3cSpl196000 * identification field from the standard INQUIRY data 3935942c5e3cSpl196000 * field and the product serial number field from the 3936942c5e3cSpl196000 * unit serial number page. 3937942c5e3cSpl196000 */ 3938942c5e3cSpl196000 sp = &idp[AAC_VPD_ID_DATA]; 3939942c5e3cSpl196000 sp = aac_vendor_id(softs, sp); 3940942c5e3cSpl196000 sp = aac_product_id(softs, sp); 3941942c5e3cSpl196000 sp = aac_lun_serialno(softs, tgt, sp); 3942a74f7440Spl196000 idp[AAC_VPD_ID_LENGTH] = (uintptr_t)sp - \ 3943a74f7440Spl196000 (uintptr_t)&idp[AAC_VPD_ID_DATA]; 3944942c5e3cSpl196000 3945a74f7440Spl196000 vpdp[AAC_VPD_PAGE_LENGTH] = (uintptr_t)sp - \ 3946a74f7440Spl196000 (uintptr_t)&vpdp[AAC_VPD_PAGE_DATA]; 3947942c5e3cSpl196000 pkt->pkt_state |= STATE_XFERRED_DATA; 3948942c5e3cSpl196000 break; 3949942c5e3cSpl196000 3950942c5e3cSpl196000 default: 3951942c5e3cSpl196000 aac_set_arq_data(pkt, KEY_ILLEGAL_REQUEST, 3952942c5e3cSpl196000 0x24, 0x00, 0); 3953942c5e3cSpl196000 break; 3954942c5e3cSpl196000 } 3955942c5e3cSpl196000 } else { 3956942c5e3cSpl196000 struct scsi_inquiry *inqp = (struct scsi_inquiry *)b_addr; 3957942c5e3cSpl196000 size_t len = sizeof (struct scsi_inquiry); 3958942c5e3cSpl196000 3959942c5e3cSpl196000 if (page != 0) { 3960942c5e3cSpl196000 aac_set_arq_data(pkt, KEY_ILLEGAL_REQUEST, 3961942c5e3cSpl196000 0x24, 0x00, 0); 3962942c5e3cSpl196000 return; 3963942c5e3cSpl196000 } 396451ccf66eSjd218194 if (inqp == NULL || bp->b_bcount < len) 3965942c5e3cSpl196000 return; 3966942c5e3cSpl196000 3967942c5e3cSpl196000 bzero(inqp, len); 3968942c5e3cSpl196000 inqp->inq_len = AAC_ADDITIONAL_LEN; 3969942c5e3cSpl196000 inqp->inq_ansi = AAC_ANSI_VER; 3970942c5e3cSpl196000 inqp->inq_rdf = AAC_RESP_DATA_FORMAT; 3971942c5e3cSpl196000 (void) aac_vendor_id(softs, (uchar_t *)inqp->inq_vid); 3972942c5e3cSpl196000 (void) aac_product_id(softs, (uchar_t *)inqp->inq_pid); 3973942c5e3cSpl196000 bcopy("V1.0", inqp->inq_revision, 4); 3974942c5e3cSpl196000 inqp->inq_cmdque = 1; /* enable tagged-queuing */ 3975942c5e3cSpl196000 /* 3976942c5e3cSpl196000 * For "sd-max-xfer-size" property which may impact performance 3977942c5e3cSpl196000 * when IO threads increase. 3978942c5e3cSpl196000 */ 3979942c5e3cSpl196000 inqp->inq_wbus32 = 1; 3980942c5e3cSpl196000 3981942c5e3cSpl196000 pkt->pkt_state |= STATE_XFERRED_DATA; 3982942c5e3cSpl196000 } 3983942c5e3cSpl196000 } 3984942c5e3cSpl196000 3985942c5e3cSpl196000 /* 3986942c5e3cSpl196000 * SPC-3 7.10 MODE SENSE command implementation 3987942c5e3cSpl196000 */ 3988942c5e3cSpl196000 static void 3989942c5e3cSpl196000 aac_mode_sense(struct aac_softstate *softs, struct scsi_pkt *pkt, 3990942c5e3cSpl196000 union scsi_cdb *cdbp, struct buf *bp, int capacity) 3991942c5e3cSpl196000 { 3992942c5e3cSpl196000 uchar_t pagecode; 3993942c5e3cSpl196000 struct mode_header *headerp; 399451ccf66eSjd218194 struct mode_header_g1 *g1_headerp; 3995942c5e3cSpl196000 unsigned int ncyl; 399651ccf66eSjd218194 caddr_t sense_data; 399751ccf66eSjd218194 caddr_t next_page; 399851ccf66eSjd218194 size_t sdata_size; 399951ccf66eSjd218194 size_t pages_size; 400051ccf66eSjd218194 int unsupport_page = 0; 400151ccf66eSjd218194 400251ccf66eSjd218194 ASSERT(cdbp->scc_cmd == SCMD_MODE_SENSE || 400351ccf66eSjd218194 cdbp->scc_cmd == SCMD_MODE_SENSE_G1); 4004942c5e3cSpl196000 4005942c5e3cSpl196000 if (!(bp && bp->b_un.b_addr && bp->b_bcount)) 4006942c5e3cSpl196000 return; 4007942c5e3cSpl196000 4008942c5e3cSpl196000 if (bp->b_flags & (B_PHYS | B_PAGEIO)) 4009942c5e3cSpl196000 bp_mapin(bp); 4010942c5e3cSpl196000 pkt->pkt_state |= STATE_XFERRED_DATA; 401151ccf66eSjd218194 pagecode = cdbp->cdb_un.sg.scsi[0] & 0x3F; 4012942c5e3cSpl196000 401351ccf66eSjd218194 /* calculate the size of needed buffer */ 401451ccf66eSjd218194 if (cdbp->scc_cmd == SCMD_MODE_SENSE) 401551ccf66eSjd218194 sdata_size = MODE_HEADER_LENGTH; 401651ccf66eSjd218194 else /* must be SCMD_MODE_SENSE_G1 */ 401751ccf66eSjd218194 sdata_size = MODE_HEADER_LENGTH_G1; 401851ccf66eSjd218194 401951ccf66eSjd218194 pages_size = 0; 4020942c5e3cSpl196000 switch (pagecode) { 4021942c5e3cSpl196000 case SD_MODE_SENSE_PAGE3_CODE: 402251ccf66eSjd218194 pages_size += sizeof (struct mode_format); 402351ccf66eSjd218194 break; 402451ccf66eSjd218194 402551ccf66eSjd218194 case SD_MODE_SENSE_PAGE4_CODE: 402651ccf66eSjd218194 pages_size += sizeof (struct mode_geometry); 402751ccf66eSjd218194 break; 402851ccf66eSjd218194 402951ccf66eSjd218194 case MODEPAGE_CTRL_MODE: 403051ccf66eSjd218194 if (softs->flags & AAC_FLAGS_LBA_64BIT) { 403151ccf66eSjd218194 pages_size += sizeof (struct mode_control_scsi3); 403251ccf66eSjd218194 } else { 403351ccf66eSjd218194 unsupport_page = 1; 403451ccf66eSjd218194 } 403551ccf66eSjd218194 break; 403651ccf66eSjd218194 403751ccf66eSjd218194 case MODEPAGE_ALLPAGES: 403851ccf66eSjd218194 if (softs->flags & AAC_FLAGS_LBA_64BIT) { 403951ccf66eSjd218194 pages_size += sizeof (struct mode_format) + 404051ccf66eSjd218194 sizeof (struct mode_geometry) + 404151ccf66eSjd218194 sizeof (struct mode_control_scsi3); 404251ccf66eSjd218194 } else { 404351ccf66eSjd218194 pages_size += sizeof (struct mode_format) + 404451ccf66eSjd218194 sizeof (struct mode_geometry); 404551ccf66eSjd218194 } 404651ccf66eSjd218194 break; 404751ccf66eSjd218194 404851ccf66eSjd218194 default: 404951ccf66eSjd218194 /* unsupported pages */ 405051ccf66eSjd218194 unsupport_page = 1; 405151ccf66eSjd218194 } 405251ccf66eSjd218194 405351ccf66eSjd218194 /* allocate buffer to fill the send data */ 405451ccf66eSjd218194 sdata_size += pages_size; 405551ccf66eSjd218194 sense_data = kmem_zalloc(sdata_size, KM_SLEEP); 405651ccf66eSjd218194 405751ccf66eSjd218194 if (cdbp->scc_cmd == SCMD_MODE_SENSE) { 405851ccf66eSjd218194 headerp = (struct mode_header *)sense_data; 405951ccf66eSjd218194 headerp->length = MODE_HEADER_LENGTH + pages_size - 406051ccf66eSjd218194 sizeof (headerp->length); 406151ccf66eSjd218194 headerp->bdesc_length = 0; 406251ccf66eSjd218194 next_page = sense_data + sizeof (struct mode_header); 406351ccf66eSjd218194 } else { 4064a74f7440Spl196000 g1_headerp = (void *)sense_data; 4065b6094a86Sjd218194 g1_headerp->length = BE_16(MODE_HEADER_LENGTH_G1 + pages_size - 4066b6094a86Sjd218194 sizeof (g1_headerp->length)); 406751ccf66eSjd218194 g1_headerp->bdesc_length = 0; 406851ccf66eSjd218194 next_page = sense_data + sizeof (struct mode_header_g1); 406951ccf66eSjd218194 } 407051ccf66eSjd218194 407151ccf66eSjd218194 if (unsupport_page) 407251ccf66eSjd218194 goto finish; 407351ccf66eSjd218194 407451ccf66eSjd218194 if (pagecode == SD_MODE_SENSE_PAGE3_CODE || 407551ccf66eSjd218194 pagecode == MODEPAGE_ALLPAGES) { 407651ccf66eSjd218194 /* SBC-3 7.1.3.3 Format device page */ 407751ccf66eSjd218194 struct mode_format *page3p; 407851ccf66eSjd218194 4079a74f7440Spl196000 page3p = (void *)next_page; 4080942c5e3cSpl196000 page3p->mode_page.code = SD_MODE_SENSE_PAGE3_CODE; 4081942c5e3cSpl196000 page3p->mode_page.length = sizeof (struct mode_format); 4082942c5e3cSpl196000 page3p->data_bytes_sect = BE_16(AAC_SECTOR_SIZE); 4083942c5e3cSpl196000 page3p->sect_track = BE_16(AAC_SECTORS_PER_TRACK); 4084942c5e3cSpl196000 408551ccf66eSjd218194 next_page += sizeof (struct mode_format); 408651ccf66eSjd218194 } 408751ccf66eSjd218194 408851ccf66eSjd218194 if (pagecode == SD_MODE_SENSE_PAGE4_CODE || 408951ccf66eSjd218194 pagecode == MODEPAGE_ALLPAGES) { 4090942c5e3cSpl196000 /* SBC-3 7.1.3.8 Rigid disk device geometry page */ 409151ccf66eSjd218194 struct mode_geometry *page4p; 409251ccf66eSjd218194 4093a74f7440Spl196000 page4p = (void *)next_page; 4094942c5e3cSpl196000 page4p->mode_page.code = SD_MODE_SENSE_PAGE4_CODE; 4095942c5e3cSpl196000 page4p->mode_page.length = sizeof (struct mode_geometry); 4096942c5e3cSpl196000 page4p->heads = AAC_NUMBER_OF_HEADS; 4097942c5e3cSpl196000 page4p->rpm = BE_16(AAC_ROTATION_SPEED); 4098942c5e3cSpl196000 ncyl = capacity / (AAC_NUMBER_OF_HEADS * AAC_SECTORS_PER_TRACK); 4099942c5e3cSpl196000 page4p->cyl_lb = ncyl & 0xff; 4100942c5e3cSpl196000 page4p->cyl_mb = (ncyl >> 8) & 0xff; 4101942c5e3cSpl196000 page4p->cyl_ub = (ncyl >> 16) & 0xff; 4102942c5e3cSpl196000 410351ccf66eSjd218194 next_page += sizeof (struct mode_geometry); 410451ccf66eSjd218194 } 410551ccf66eSjd218194 410651ccf66eSjd218194 if ((pagecode == MODEPAGE_CTRL_MODE || pagecode == MODEPAGE_ALLPAGES) && 410751ccf66eSjd218194 softs->flags & AAC_FLAGS_LBA_64BIT) { 410851ccf66eSjd218194 /* 64-bit LBA need large sense data */ 4109942c5e3cSpl196000 struct mode_control_scsi3 *mctl; 4110942c5e3cSpl196000 4111a74f7440Spl196000 mctl = (void *)next_page; 4112942c5e3cSpl196000 mctl->mode_page.code = MODEPAGE_CTRL_MODE; 4113942c5e3cSpl196000 mctl->mode_page.length = 4114942c5e3cSpl196000 sizeof (struct mode_control_scsi3) - 4115942c5e3cSpl196000 sizeof (struct mode_page); 4116942c5e3cSpl196000 mctl->d_sense = 1; 4117942c5e3cSpl196000 } 4118942c5e3cSpl196000 411951ccf66eSjd218194 finish: 412051ccf66eSjd218194 /* copyout the valid data. */ 412151ccf66eSjd218194 bcopy(sense_data, bp->b_un.b_addr, min(sdata_size, bp->b_bcount)); 412251ccf66eSjd218194 kmem_free(sense_data, sdata_size); 4123942c5e3cSpl196000 } 4124942c5e3cSpl196000 412558bc78c7SXin Chen static int 412658bc78c7SXin Chen aac_name_node(dev_info_t *dip, char *name, int len) 412758bc78c7SXin Chen { 412858bc78c7SXin Chen int tgt, lun; 412958bc78c7SXin Chen 413058bc78c7SXin Chen tgt = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 413158bc78c7SXin Chen DDI_PROP_DONTPASS, "target", -1); 413258bc78c7SXin Chen if (tgt == -1) 413358bc78c7SXin Chen return (DDI_FAILURE); 413458bc78c7SXin Chen lun = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 413558bc78c7SXin Chen DDI_PROP_DONTPASS, "lun", -1); 413658bc78c7SXin Chen if (lun == -1) 413758bc78c7SXin Chen return (DDI_FAILURE); 413858bc78c7SXin Chen 413958bc78c7SXin Chen (void) snprintf(name, len, "%x,%x", tgt, lun); 414058bc78c7SXin Chen return (DDI_SUCCESS); 414158bc78c7SXin Chen } 414258bc78c7SXin Chen 4143942c5e3cSpl196000 /*ARGSUSED*/ 4144942c5e3cSpl196000 static int 4145942c5e3cSpl196000 aac_tran_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip, 4146942c5e3cSpl196000 scsi_hba_tran_t *tran, struct scsi_device *sd) 4147942c5e3cSpl196000 { 4148942c5e3cSpl196000 struct aac_softstate *softs = AAC_TRAN2SOFTS(tran); 4149942c5e3cSpl196000 #if defined(DEBUG) || defined(__lock_lint) 4150942c5e3cSpl196000 int ctl = ddi_get_instance(softs->devinfo_p); 4151942c5e3cSpl196000 #endif 415258bc78c7SXin Chen uint16_t tgt = sd->sd_address.a_target; 415358bc78c7SXin Chen uint8_t lun = sd->sd_address.a_lun; 415458bc78c7SXin Chen struct aac_device *dvp; 4155942c5e3cSpl196000 4156942c5e3cSpl196000 DBCALLED(softs, 2); 4157942c5e3cSpl196000 415858bc78c7SXin Chen if (ndi_dev_is_persistent_node(tgt_dip) == 0) { 415958bc78c7SXin Chen /* 416058bc78c7SXin Chen * If no persistent node exist, we don't allow .conf node 416158bc78c7SXin Chen * to be created. 416258bc78c7SXin Chen */ 416358bc78c7SXin Chen if (aac_find_child(softs, tgt, lun) != NULL) { 416458bc78c7SXin Chen if (ndi_merge_node(tgt_dip, aac_name_node) != 416558bc78c7SXin Chen DDI_SUCCESS) 416658bc78c7SXin Chen /* Create this .conf node */ 416758bc78c7SXin Chen return (DDI_SUCCESS); 416858bc78c7SXin Chen } 4169942c5e3cSpl196000 return (DDI_FAILURE); 4170942c5e3cSpl196000 } 4171942c5e3cSpl196000 4172942c5e3cSpl196000 /* 417358bc78c7SXin Chen * Only support container/phys. device that has been 417458bc78c7SXin Chen * detected and valid 4175942c5e3cSpl196000 */ 4176942c5e3cSpl196000 mutex_enter(&softs->io_lock); 417758bc78c7SXin Chen if (tgt >= AAC_MAX_DEV(softs)) { 417858bc78c7SXin Chen AACDB_PRINT_TRAN(softs, 417958bc78c7SXin Chen "aac_tran_tgt_init: c%dt%dL%d out", ctl, tgt, lun); 4180942c5e3cSpl196000 mutex_exit(&softs->io_lock); 418158bc78c7SXin Chen return (DDI_FAILURE); 418258bc78c7SXin Chen } 418358bc78c7SXin Chen 418458bc78c7SXin Chen if (tgt < AAC_MAX_LD) { 418558bc78c7SXin Chen dvp = (struct aac_device *)&softs->containers[tgt]; 418658bc78c7SXin Chen if (lun != 0 || !AAC_DEV_IS_VALID(dvp)) { 418758bc78c7SXin Chen AACDB_PRINT_TRAN(softs, "aac_tran_tgt_init: c%dt%dL%d", 4188942c5e3cSpl196000 ctl, tgt, lun); 4189942c5e3cSpl196000 mutex_exit(&softs->io_lock); 4190942c5e3cSpl196000 return (DDI_FAILURE); 4191942c5e3cSpl196000 } 419258bc78c7SXin Chen /* 419358bc78c7SXin Chen * Save the tgt_dip for the given target if one doesn't exist 419458bc78c7SXin Chen * already. Dip's for non-existance tgt's will be cleared in 419558bc78c7SXin Chen * tgt_free. 419658bc78c7SXin Chen */ 419758bc78c7SXin Chen if (softs->containers[tgt].dev.dip == NULL && 419858bc78c7SXin Chen strcmp(ddi_driver_name(sd->sd_dev), "sd") == 0) 419958bc78c7SXin Chen softs->containers[tgt].dev.dip = tgt_dip; 420058bc78c7SXin Chen } else { 420158bc78c7SXin Chen dvp = (struct aac_device *)&softs->nondasds[AAC_PD(tgt)]; 42023fced439Szhongyan gu - Sun Microsystems - Beijing China /* 42033fced439Szhongyan gu - Sun Microsystems - Beijing China * Save the tgt_dip for the given target if one doesn't exist 42043fced439Szhongyan gu - Sun Microsystems - Beijing China * already. Dip's for non-existance tgt's will be cleared in 42053fced439Szhongyan gu - Sun Microsystems - Beijing China * tgt_free. 42063fced439Szhongyan gu - Sun Microsystems - Beijing China */ 42073fced439Szhongyan gu - Sun Microsystems - Beijing China 42083fced439Szhongyan gu - Sun Microsystems - Beijing China if (softs->nondasds[AAC_PD(tgt)].dev.dip == NULL && 42093fced439Szhongyan gu - Sun Microsystems - Beijing China strcmp(ddi_driver_name(sd->sd_dev), "sd") == 0) 42103fced439Szhongyan gu - Sun Microsystems - Beijing China softs->nondasds[AAC_PD(tgt)].dev.dip = tgt_dip; 421158bc78c7SXin Chen } 421258bc78c7SXin Chen 421372888e72Speng liu - Sun Microsystems - Beijing China if (softs->flags & AAC_FLAGS_BRKUP) { 421472888e72Speng liu - Sun Microsystems - Beijing China if (ndi_prop_update_int(DDI_DEV_T_NONE, tgt_dip, 421572888e72Speng liu - Sun Microsystems - Beijing China "buf_break", 1) != DDI_PROP_SUCCESS) { 421672888e72Speng liu - Sun Microsystems - Beijing China cmn_err(CE_CONT, "unable to create " 421772888e72Speng liu - Sun Microsystems - Beijing China "property for t%dL%d (buf_break)", tgt, lun); 421872888e72Speng liu - Sun Microsystems - Beijing China } 421972888e72Speng liu - Sun Microsystems - Beijing China } 422072888e72Speng liu - Sun Microsystems - Beijing China 422158bc78c7SXin Chen AACDB_PRINT(softs, CE_NOTE, 422258bc78c7SXin Chen "aac_tran_tgt_init: c%dt%dL%d ok (%s)", ctl, tgt, lun, 422358bc78c7SXin Chen (dvp->type == AAC_DEV_PD) ? "pd" : "ld"); 422458bc78c7SXin Chen mutex_exit(&softs->io_lock); 422558bc78c7SXin Chen return (DDI_SUCCESS); 422658bc78c7SXin Chen } 422758bc78c7SXin Chen 422858bc78c7SXin Chen static void 422958bc78c7SXin Chen aac_tran_tgt_free(dev_info_t *hba_dip, dev_info_t *tgt_dip, 423058bc78c7SXin Chen scsi_hba_tran_t *hba_tran, struct scsi_device *sd) 423158bc78c7SXin Chen { 423258bc78c7SXin Chen #ifndef __lock_lint 423358bc78c7SXin Chen _NOTE(ARGUNUSED(hba_dip, tgt_dip, hba_tran)) 423458bc78c7SXin Chen #endif 423558bc78c7SXin Chen 423658bc78c7SXin Chen struct aac_softstate *softs = SD2AAC(sd); 423758bc78c7SXin Chen int tgt = sd->sd_address.a_target; 423858bc78c7SXin Chen 423958bc78c7SXin Chen mutex_enter(&softs->io_lock); 424058bc78c7SXin Chen if (tgt < AAC_MAX_LD) { 424158bc78c7SXin Chen if (softs->containers[tgt].dev.dip == tgt_dip) 424258bc78c7SXin Chen softs->containers[tgt].dev.dip = NULL; 424358bc78c7SXin Chen } else { 42443fced439Szhongyan gu - Sun Microsystems - Beijing China if (softs->nondasds[AAC_PD(tgt)].dev.dip == tgt_dip) 42453fced439Szhongyan gu - Sun Microsystems - Beijing China softs->nondasds[AAC_PD(tgt)].dev.dip = NULL; 424658bc78c7SXin Chen softs->nondasds[AAC_PD(tgt)].dev.flags &= ~AAC_DFLAG_VALID; 424758bc78c7SXin Chen } 424858bc78c7SXin Chen mutex_exit(&softs->io_lock); 4249942c5e3cSpl196000 } 4250942c5e3cSpl196000 4251942c5e3cSpl196000 /* 4252942c5e3cSpl196000 * Check if the firmware is Up And Running. If it is in the Kernel Panic 4253942c5e3cSpl196000 * state, (BlinkLED code + 1) is returned. 4254942c5e3cSpl196000 * 0 -- firmware up and running 4255942c5e3cSpl196000 * -1 -- firmware dead 4256942c5e3cSpl196000 * >0 -- firmware kernel panic 4257942c5e3cSpl196000 */ 4258942c5e3cSpl196000 static int 4259942c5e3cSpl196000 aac_check_adapter_health(struct aac_softstate *softs) 4260942c5e3cSpl196000 { 4261942c5e3cSpl196000 int rval; 4262942c5e3cSpl196000 4263942c5e3cSpl196000 rval = PCI_MEM_GET32(softs, AAC_OMR0); 4264942c5e3cSpl196000 4265942c5e3cSpl196000 if (rval & AAC_KERNEL_UP_AND_RUNNING) { 4266942c5e3cSpl196000 rval = 0; 4267942c5e3cSpl196000 } else if (rval & AAC_KERNEL_PANIC) { 4268942c5e3cSpl196000 cmn_err(CE_WARN, "firmware panic"); 4269942c5e3cSpl196000 rval = ((rval >> 16) & 0xff) + 1; /* avoid 0 as return value */ 4270942c5e3cSpl196000 } else { 4271942c5e3cSpl196000 cmn_err(CE_WARN, "firmware dead"); 4272942c5e3cSpl196000 rval = -1; 4273942c5e3cSpl196000 } 4274942c5e3cSpl196000 return (rval); 4275942c5e3cSpl196000 } 4276942c5e3cSpl196000 4277942c5e3cSpl196000 static void 4278942c5e3cSpl196000 aac_abort_iocmd(struct aac_softstate *softs, struct aac_cmd *acp, 4279942c5e3cSpl196000 uchar_t reason) 4280942c5e3cSpl196000 { 4281942c5e3cSpl196000 acp->flags |= AAC_CMD_ABORT; 4282942c5e3cSpl196000 4283942c5e3cSpl196000 if (acp->pkt) { 428458bc78c7SXin Chen if (acp->slotp) { /* outstanding cmd */ 428558bc78c7SXin Chen acp->pkt->pkt_state |= STATE_GOT_STATUS; 428658bc78c7SXin Chen } 4287942c5e3cSpl196000 4288942c5e3cSpl196000 switch (reason) { 4289942c5e3cSpl196000 case CMD_TIMEOUT: 429058bc78c7SXin Chen AACDB_PRINT(softs, CE_NOTE, "CMD_TIMEOUT: acp=0x%p", 429158bc78c7SXin Chen acp); 4292942c5e3cSpl196000 aac_set_pkt_reason(softs, acp, CMD_TIMEOUT, 4293942c5e3cSpl196000 STAT_TIMEOUT | STAT_BUS_RESET); 4294942c5e3cSpl196000 break; 4295942c5e3cSpl196000 case CMD_RESET: 4296942c5e3cSpl196000 /* aac support only RESET_ALL */ 429758bc78c7SXin Chen AACDB_PRINT(softs, CE_NOTE, "CMD_RESET: acp=0x%p", acp); 4298942c5e3cSpl196000 aac_set_pkt_reason(softs, acp, CMD_RESET, 4299942c5e3cSpl196000 STAT_BUS_RESET); 4300942c5e3cSpl196000 break; 4301942c5e3cSpl196000 case CMD_ABORTED: 430258bc78c7SXin Chen AACDB_PRINT(softs, CE_NOTE, "CMD_ABORTED: acp=0x%p", 430358bc78c7SXin Chen acp); 4304942c5e3cSpl196000 aac_set_pkt_reason(softs, acp, CMD_ABORTED, 4305942c5e3cSpl196000 STAT_ABORTED); 4306942c5e3cSpl196000 break; 4307942c5e3cSpl196000 } 4308942c5e3cSpl196000 } 4309942c5e3cSpl196000 aac_end_io(softs, acp); 4310942c5e3cSpl196000 } 4311942c5e3cSpl196000 4312942c5e3cSpl196000 /* 4313942c5e3cSpl196000 * Abort all the pending commands of type iocmd or just the command pkt 4314942c5e3cSpl196000 * corresponding to pkt 4315942c5e3cSpl196000 */ 4316942c5e3cSpl196000 static void 4317942c5e3cSpl196000 aac_abort_iocmds(struct aac_softstate *softs, int iocmd, struct scsi_pkt *pkt, 4318942c5e3cSpl196000 int reason) 4319942c5e3cSpl196000 { 4320942c5e3cSpl196000 struct aac_cmd *ac_arg, *acp; 4321942c5e3cSpl196000 int i; 4322942c5e3cSpl196000 4323942c5e3cSpl196000 if (pkt == NULL) { 4324942c5e3cSpl196000 ac_arg = NULL; 4325942c5e3cSpl196000 } else { 4326942c5e3cSpl196000 ac_arg = PKT2AC(pkt); 4327942c5e3cSpl196000 iocmd = (ac_arg->flags & AAC_CMD_SYNC) ? 4328942c5e3cSpl196000 AAC_IOCMD_SYNC : AAC_IOCMD_ASYNC; 4329942c5e3cSpl196000 } 4330942c5e3cSpl196000 4331942c5e3cSpl196000 /* 4332942c5e3cSpl196000 * a) outstanding commands on the controller 4333942c5e3cSpl196000 * Note: should abort outstanding commands only after one 4334942c5e3cSpl196000 * IOP reset has been done. 4335942c5e3cSpl196000 */ 4336942c5e3cSpl196000 if (iocmd & AAC_IOCMD_OUTSTANDING) { 4337942c5e3cSpl196000 struct aac_cmd *acp; 4338942c5e3cSpl196000 4339942c5e3cSpl196000 for (i = 0; i < AAC_MAX_LD; i++) { 434058bc78c7SXin Chen if (AAC_DEV_IS_VALID(&softs->containers[i].dev)) 4341942c5e3cSpl196000 softs->containers[i].reset = 1; 4342942c5e3cSpl196000 } 4343942c5e3cSpl196000 while ((acp = softs->q_busy.q_head) != NULL) 4344942c5e3cSpl196000 aac_abort_iocmd(softs, acp, reason); 4345942c5e3cSpl196000 } 4346942c5e3cSpl196000 4347942c5e3cSpl196000 /* b) commands in the waiting queues */ 4348942c5e3cSpl196000 for (i = 0; i < AAC_CMDQ_NUM; i++) { 4349942c5e3cSpl196000 if (iocmd & (1 << i)) { 4350942c5e3cSpl196000 if (ac_arg) { 4351942c5e3cSpl196000 aac_abort_iocmd(softs, ac_arg, reason); 4352942c5e3cSpl196000 } else { 4353942c5e3cSpl196000 while ((acp = softs->q_wait[i].q_head) != NULL) 4354942c5e3cSpl196000 aac_abort_iocmd(softs, acp, reason); 4355942c5e3cSpl196000 } 4356942c5e3cSpl196000 } 4357942c5e3cSpl196000 } 4358942c5e3cSpl196000 } 4359942c5e3cSpl196000 4360942c5e3cSpl196000 /* 4361942c5e3cSpl196000 * The draining thread is shared among quiesce threads. It terminates 4362942c5e3cSpl196000 * when the adapter is quiesced or stopped by aac_stop_drain(). 4363942c5e3cSpl196000 */ 4364942c5e3cSpl196000 static void 4365942c5e3cSpl196000 aac_check_drain(void *arg) 4366942c5e3cSpl196000 { 4367942c5e3cSpl196000 struct aac_softstate *softs = arg; 4368942c5e3cSpl196000 4369942c5e3cSpl196000 mutex_enter(&softs->io_lock); 4370942c5e3cSpl196000 if (softs->ndrains) { 437158bc78c7SXin Chen softs->drain_timeid = 0; 4372942c5e3cSpl196000 /* 4373942c5e3cSpl196000 * If both ASYNC and SYNC bus throttle are held, 4374942c5e3cSpl196000 * wake up threads only when both are drained out. 4375942c5e3cSpl196000 */ 4376942c5e3cSpl196000 if ((softs->bus_throttle[AAC_CMDQ_ASYNC] > 0 || 4377942c5e3cSpl196000 softs->bus_ncmds[AAC_CMDQ_ASYNC] == 0) && 4378942c5e3cSpl196000 (softs->bus_throttle[AAC_CMDQ_SYNC] > 0 || 4379942c5e3cSpl196000 softs->bus_ncmds[AAC_CMDQ_SYNC] == 0)) 4380942c5e3cSpl196000 cv_broadcast(&softs->drain_cv); 4381942c5e3cSpl196000 else 4382942c5e3cSpl196000 softs->drain_timeid = timeout(aac_check_drain, softs, 4383942c5e3cSpl196000 AAC_QUIESCE_TICK * drv_usectohz(1000000)); 4384942c5e3cSpl196000 } 4385942c5e3cSpl196000 mutex_exit(&softs->io_lock); 4386942c5e3cSpl196000 } 4387942c5e3cSpl196000 4388942c5e3cSpl196000 /* 4389942c5e3cSpl196000 * If not draining the outstanding cmds, drain them. Otherwise, 4390942c5e3cSpl196000 * only update ndrains. 4391942c5e3cSpl196000 */ 4392942c5e3cSpl196000 static void 4393942c5e3cSpl196000 aac_start_drain(struct aac_softstate *softs) 4394942c5e3cSpl196000 { 4395942c5e3cSpl196000 if (softs->ndrains == 0) { 439658bc78c7SXin Chen ASSERT(softs->drain_timeid == 0); 4397942c5e3cSpl196000 softs->drain_timeid = timeout(aac_check_drain, softs, 4398942c5e3cSpl196000 AAC_QUIESCE_TICK * drv_usectohz(1000000)); 4399942c5e3cSpl196000 } 4400942c5e3cSpl196000 softs->ndrains++; 4401942c5e3cSpl196000 } 4402942c5e3cSpl196000 4403942c5e3cSpl196000 /* 4404942c5e3cSpl196000 * Stop the draining thread when no other threads use it any longer. 4405942c5e3cSpl196000 * Side effect: io_lock may be released in the middle. 4406942c5e3cSpl196000 */ 4407942c5e3cSpl196000 static void 4408942c5e3cSpl196000 aac_stop_drain(struct aac_softstate *softs) 4409942c5e3cSpl196000 { 4410942c5e3cSpl196000 softs->ndrains--; 4411942c5e3cSpl196000 if (softs->ndrains == 0) { 4412942c5e3cSpl196000 if (softs->drain_timeid != 0) { 4413942c5e3cSpl196000 timeout_id_t tid = softs->drain_timeid; 4414942c5e3cSpl196000 4415942c5e3cSpl196000 softs->drain_timeid = 0; 4416942c5e3cSpl196000 mutex_exit(&softs->io_lock); 4417942c5e3cSpl196000 (void) untimeout(tid); 4418942c5e3cSpl196000 mutex_enter(&softs->io_lock); 4419942c5e3cSpl196000 } 4420942c5e3cSpl196000 } 4421942c5e3cSpl196000 } 4422942c5e3cSpl196000 4423942c5e3cSpl196000 /* 4424942c5e3cSpl196000 * The following function comes from Adaptec: 4425942c5e3cSpl196000 * 4426942c5e3cSpl196000 * Once do an IOP reset, basically the driver have to re-initialize the card 4427942c5e3cSpl196000 * as if up from a cold boot, and the driver is responsible for any IO that 4428942c5e3cSpl196000 * is outstanding to the adapter at the time of the IOP RESET. And prepare 4429942c5e3cSpl196000 * for IOP RESET by making the init code modular with the ability to call it 4430942c5e3cSpl196000 * from multiple places. 4431942c5e3cSpl196000 */ 4432942c5e3cSpl196000 static int 4433942c5e3cSpl196000 aac_reset_adapter(struct aac_softstate *softs) 4434942c5e3cSpl196000 { 4435942c5e3cSpl196000 int health; 4436942c5e3cSpl196000 uint32_t status; 443758bc78c7SXin Chen int rval = AAC_IOP_RESET_FAILED; 4438942c5e3cSpl196000 4439942c5e3cSpl196000 DBCALLED(softs, 1); 4440942c5e3cSpl196000 4441942c5e3cSpl196000 ASSERT(softs->state & AAC_STATE_RESET); 4442942c5e3cSpl196000 4443942c5e3cSpl196000 ddi_fm_acc_err_clear(softs->pci_mem_handle, DDI_FME_VER0); 4444942c5e3cSpl196000 /* Disable interrupt */ 4445942c5e3cSpl196000 AAC_DISABLE_INTR(softs); 4446942c5e3cSpl196000 4447942c5e3cSpl196000 health = aac_check_adapter_health(softs); 4448942c5e3cSpl196000 if (health == -1) { 4449942c5e3cSpl196000 ddi_fm_service_impact(softs->devinfo_p, DDI_SERVICE_LOST); 4450942c5e3cSpl196000 goto finish; 4451942c5e3cSpl196000 } 4452942c5e3cSpl196000 if (health == 0) /* flush drives if possible */ 4453942c5e3cSpl196000 (void) aac_shutdown(softs); 4454942c5e3cSpl196000 4455942c5e3cSpl196000 /* Execute IOP reset */ 4456942c5e3cSpl196000 if ((aac_sync_mbcommand(softs, AAC_IOP_RESET, 0, 0, 0, 0, 4457942c5e3cSpl196000 &status)) != AACOK) { 4458f42c2f53Szhongyan gu - Sun Microsystems - Beijing China ddi_acc_handle_t acc; 4459942c5e3cSpl196000 struct aac_fib *fibp; 4460942c5e3cSpl196000 struct aac_pause_command *pc; 4461942c5e3cSpl196000 4462942c5e3cSpl196000 if ((status & 0xf) == 0xf) { 4463942c5e3cSpl196000 uint32_t wait_count; 4464942c5e3cSpl196000 4465942c5e3cSpl196000 /* 4466942c5e3cSpl196000 * Sunrise Lake has dual cores and we must drag the 4467942c5e3cSpl196000 * other core with us to reset simultaneously. There 4468942c5e3cSpl196000 * are 2 bits in the Inbound Reset Control and Status 4469942c5e3cSpl196000 * Register (offset 0x38) of the Sunrise Lake to reset 4470942c5e3cSpl196000 * the chip without clearing out the PCI configuration 4471942c5e3cSpl196000 * info (COMMAND & BARS). 4472942c5e3cSpl196000 */ 4473942c5e3cSpl196000 PCI_MEM_PUT32(softs, AAC_IRCSR, AAC_IRCSR_CORES_RST); 4474942c5e3cSpl196000 4475942c5e3cSpl196000 /* 4476942c5e3cSpl196000 * We need to wait for 5 seconds before accessing the MU 4477942c5e3cSpl196000 * again 10000 * 100us = 1000,000us = 1000ms = 1s 4478942c5e3cSpl196000 */ 4479942c5e3cSpl196000 wait_count = 5 * 10000; 4480942c5e3cSpl196000 while (wait_count) { 4481942c5e3cSpl196000 drv_usecwait(100); /* delay 100 microseconds */ 4482942c5e3cSpl196000 wait_count--; 4483942c5e3cSpl196000 } 4484942c5e3cSpl196000 } else { 4485942c5e3cSpl196000 if (status == SRB_STATUS_INVALID_REQUEST) 4486942c5e3cSpl196000 cmn_err(CE_WARN, "!IOP_RESET not supported"); 4487942c5e3cSpl196000 else /* probably timeout */ 4488942c5e3cSpl196000 cmn_err(CE_WARN, "!IOP_RESET failed"); 4489942c5e3cSpl196000 4490942c5e3cSpl196000 /* Unwind aac_shutdown() */ 4491f42c2f53Szhongyan gu - Sun Microsystems - Beijing China (void) aac_sync_fib_slot_bind(softs, &softs->sync_ac); 4492f42c2f53Szhongyan gu - Sun Microsystems - Beijing China acc = softs->sync_ac.slotp->fib_acc_handle; 4493f42c2f53Szhongyan gu - Sun Microsystems - Beijing China 4494f42c2f53Szhongyan gu - Sun Microsystems - Beijing China fibp = softs->sync_ac.slotp->fibp; 4495942c5e3cSpl196000 pc = (struct aac_pause_command *)&fibp->data[0]; 4496942c5e3cSpl196000 4497942c5e3cSpl196000 bzero(pc, sizeof (*pc)); 4498942c5e3cSpl196000 ddi_put32(acc, &pc->Command, VM_ContainerConfig); 4499942c5e3cSpl196000 ddi_put32(acc, &pc->Type, CT_PAUSE_IO); 4500942c5e3cSpl196000 ddi_put32(acc, &pc->Timeout, 1); 4501942c5e3cSpl196000 ddi_put32(acc, &pc->Min, 1); 4502942c5e3cSpl196000 ddi_put32(acc, &pc->NoRescan, 1); 4503942c5e3cSpl196000 4504942c5e3cSpl196000 (void) aac_sync_fib(softs, ContainerCommand, 4505942c5e3cSpl196000 AAC_FIB_SIZEOF(struct aac_pause_command)); 4506f42c2f53Szhongyan gu - Sun Microsystems - Beijing China aac_sync_fib_slot_release(softs, &softs->sync_ac); 4507942c5e3cSpl196000 450858bc78c7SXin Chen if (aac_check_adapter_health(softs) != 0) 4509942c5e3cSpl196000 ddi_fm_service_impact(softs->devinfo_p, 4510942c5e3cSpl196000 DDI_SERVICE_LOST); 451158bc78c7SXin Chen else 451258bc78c7SXin Chen /* 451358bc78c7SXin Chen * IOP reset not supported or IOP not reseted 451458bc78c7SXin Chen */ 451558bc78c7SXin Chen rval = AAC_IOP_RESET_ABNORMAL; 4516942c5e3cSpl196000 goto finish; 4517942c5e3cSpl196000 } 4518942c5e3cSpl196000 } 4519942c5e3cSpl196000 4520942c5e3cSpl196000 /* 4521942c5e3cSpl196000 * Re-read and renegotiate the FIB parameters, as one of the actions 4522942c5e3cSpl196000 * that can result from an IOP reset is the running of a new firmware 4523942c5e3cSpl196000 * image. 4524942c5e3cSpl196000 */ 4525942c5e3cSpl196000 if (aac_common_attach(softs) != AACOK) 4526942c5e3cSpl196000 goto finish; 4527942c5e3cSpl196000 452858bc78c7SXin Chen rval = AAC_IOP_RESET_SUCCEED; 4529942c5e3cSpl196000 4530942c5e3cSpl196000 finish: 4531942c5e3cSpl196000 AAC_ENABLE_INTR(softs); 4532942c5e3cSpl196000 return (rval); 4533942c5e3cSpl196000 } 4534942c5e3cSpl196000 4535942c5e3cSpl196000 static void 453658bc78c7SXin Chen aac_set_throttle(struct aac_softstate *softs, struct aac_device *dvp, int q, 4537942c5e3cSpl196000 int throttle) 4538942c5e3cSpl196000 { 4539942c5e3cSpl196000 /* 4540942c5e3cSpl196000 * If the bus is draining/quiesced, no changes to the throttles 4541942c5e3cSpl196000 * are allowed. All throttles should have been set to 0. 4542942c5e3cSpl196000 */ 4543942c5e3cSpl196000 if ((softs->state & AAC_STATE_QUIESCED) || softs->ndrains) 4544942c5e3cSpl196000 return; 4545942c5e3cSpl196000 dvp->throttle[q] = throttle; 4546942c5e3cSpl196000 } 4547942c5e3cSpl196000 4548942c5e3cSpl196000 static void 4549942c5e3cSpl196000 aac_hold_bus(struct aac_softstate *softs, int iocmds) 4550942c5e3cSpl196000 { 4551942c5e3cSpl196000 int i, q; 4552942c5e3cSpl196000 4553942c5e3cSpl196000 /* Hold bus by holding every device on the bus */ 4554942c5e3cSpl196000 for (q = 0; q < AAC_CMDQ_NUM; q++) { 4555942c5e3cSpl196000 if (iocmds & (1 << q)) { 4556942c5e3cSpl196000 softs->bus_throttle[q] = 0; 4557942c5e3cSpl196000 for (i = 0; i < AAC_MAX_LD; i++) 455858bc78c7SXin Chen aac_set_throttle(softs, 455958bc78c7SXin Chen &softs->containers[i].dev, q, 0); 456058bc78c7SXin Chen for (i = 0; i < AAC_MAX_PD(softs); i++) 456158bc78c7SXin Chen aac_set_throttle(softs, 456258bc78c7SXin Chen &softs->nondasds[i].dev, q, 0); 4563942c5e3cSpl196000 } 4564942c5e3cSpl196000 } 4565942c5e3cSpl196000 } 4566942c5e3cSpl196000 4567942c5e3cSpl196000 static void 4568942c5e3cSpl196000 aac_unhold_bus(struct aac_softstate *softs, int iocmds) 4569942c5e3cSpl196000 { 4570f42c2f53Szhongyan gu - Sun Microsystems - Beijing China int i, q, max_throttle; 4571942c5e3cSpl196000 4572942c5e3cSpl196000 for (q = 0; q < AAC_CMDQ_NUM; q++) { 4573942c5e3cSpl196000 if (iocmds & (1 << q)) { 4574942c5e3cSpl196000 /* 4575942c5e3cSpl196000 * Should not unhold AAC_IOCMD_ASYNC bus, if it has been 4576942c5e3cSpl196000 * quiesced or being drained by possibly some quiesce 4577942c5e3cSpl196000 * threads. 4578942c5e3cSpl196000 */ 4579942c5e3cSpl196000 if (q == AAC_CMDQ_ASYNC && ((softs->state & 4580942c5e3cSpl196000 AAC_STATE_QUIESCED) || softs->ndrains)) 4581942c5e3cSpl196000 continue; 4582f42c2f53Szhongyan gu - Sun Microsystems - Beijing China if (q == AAC_CMDQ_ASYNC) 4583f42c2f53Szhongyan gu - Sun Microsystems - Beijing China max_throttle = softs->total_slots - 4584f42c2f53Szhongyan gu - Sun Microsystems - Beijing China AAC_MGT_SLOT_NUM; 4585f42c2f53Szhongyan gu - Sun Microsystems - Beijing China else 4586f42c2f53Szhongyan gu - Sun Microsystems - Beijing China max_throttle = softs->total_slots - 1; 4587f42c2f53Szhongyan gu - Sun Microsystems - Beijing China softs->bus_throttle[q] = max_throttle; 4588942c5e3cSpl196000 for (i = 0; i < AAC_MAX_LD; i++) 458958bc78c7SXin Chen aac_set_throttle(softs, 459058bc78c7SXin Chen &softs->containers[i].dev, 4591f42c2f53Szhongyan gu - Sun Microsystems - Beijing China q, max_throttle); 459258bc78c7SXin Chen for (i = 0; i < AAC_MAX_PD(softs); i++) 459358bc78c7SXin Chen aac_set_throttle(softs, &softs->nondasds[i].dev, 4594f42c2f53Szhongyan gu - Sun Microsystems - Beijing China q, max_throttle); 4595942c5e3cSpl196000 } 4596942c5e3cSpl196000 } 4597942c5e3cSpl196000 } 4598942c5e3cSpl196000 4599942c5e3cSpl196000 static int 4600942c5e3cSpl196000 aac_do_reset(struct aac_softstate *softs) 4601942c5e3cSpl196000 { 4602942c5e3cSpl196000 int health; 4603942c5e3cSpl196000 int rval; 4604942c5e3cSpl196000 4605942c5e3cSpl196000 softs->state |= AAC_STATE_RESET; 4606942c5e3cSpl196000 health = aac_check_adapter_health(softs); 4607942c5e3cSpl196000 4608942c5e3cSpl196000 /* 4609942c5e3cSpl196000 * Hold off new io commands and wait all outstanding io 4610942c5e3cSpl196000 * commands to complete. 4611942c5e3cSpl196000 */ 461258bc78c7SXin Chen if (health == 0) { 461358bc78c7SXin Chen int sync_cmds = softs->bus_ncmds[AAC_CMDQ_SYNC]; 461458bc78c7SXin Chen int async_cmds = softs->bus_ncmds[AAC_CMDQ_ASYNC]; 461558bc78c7SXin Chen 461658bc78c7SXin Chen if (sync_cmds == 0 && async_cmds == 0) { 461758bc78c7SXin Chen rval = AAC_IOP_RESET_SUCCEED; 461858bc78c7SXin Chen goto finish; 461958bc78c7SXin Chen } 4620942c5e3cSpl196000 /* 4621942c5e3cSpl196000 * Give the adapter up to AAC_QUIESCE_TIMEOUT more seconds 4622942c5e3cSpl196000 * to complete the outstanding io commands 4623942c5e3cSpl196000 */ 4624942c5e3cSpl196000 int timeout = AAC_QUIESCE_TIMEOUT * 1000 * 10; 4625942c5e3cSpl196000 int (*intr_handler)(struct aac_softstate *); 4626942c5e3cSpl196000 4627942c5e3cSpl196000 aac_hold_bus(softs, AAC_IOCMD_SYNC | AAC_IOCMD_ASYNC); 4628942c5e3cSpl196000 /* 4629942c5e3cSpl196000 * Poll the adapter by ourselves in case interrupt is disabled 4630942c5e3cSpl196000 * and to avoid releasing the io_lock. 4631942c5e3cSpl196000 */ 4632942c5e3cSpl196000 intr_handler = (softs->flags & AAC_FLAGS_NEW_COMM) ? 4633942c5e3cSpl196000 aac_process_intr_new : aac_process_intr_old; 4634942c5e3cSpl196000 while ((softs->bus_ncmds[AAC_CMDQ_SYNC] || 4635942c5e3cSpl196000 softs->bus_ncmds[AAC_CMDQ_ASYNC]) && timeout) { 4636942c5e3cSpl196000 drv_usecwait(100); 4637942c5e3cSpl196000 (void) intr_handler(softs); 4638942c5e3cSpl196000 timeout--; 4639942c5e3cSpl196000 } 4640942c5e3cSpl196000 aac_unhold_bus(softs, AAC_IOCMD_SYNC | AAC_IOCMD_ASYNC); 464158bc78c7SXin Chen 464258bc78c7SXin Chen if (softs->bus_ncmds[AAC_CMDQ_SYNC] == 0 && 464358bc78c7SXin Chen softs->bus_ncmds[AAC_CMDQ_ASYNC] == 0) { 464458bc78c7SXin Chen /* Cmds drained out */ 464558bc78c7SXin Chen rval = AAC_IOP_RESET_SUCCEED; 464658bc78c7SXin Chen goto finish; 464758bc78c7SXin Chen } else if (softs->bus_ncmds[AAC_CMDQ_SYNC] < sync_cmds || 464858bc78c7SXin Chen softs->bus_ncmds[AAC_CMDQ_ASYNC] < async_cmds) { 464958bc78c7SXin Chen /* Cmds not drained out, adapter overloaded */ 465058bc78c7SXin Chen rval = AAC_IOP_RESET_ABNORMAL; 465158bc78c7SXin Chen goto finish; 465258bc78c7SXin Chen } 4653942c5e3cSpl196000 } 4654942c5e3cSpl196000 4655942c5e3cSpl196000 /* 465658bc78c7SXin Chen * If a longer waiting time still can't drain any outstanding io 4657942c5e3cSpl196000 * commands, do IOP reset. 4658942c5e3cSpl196000 */ 465958bc78c7SXin Chen if ((rval = aac_reset_adapter(softs)) == AAC_IOP_RESET_FAILED) 4660942c5e3cSpl196000 softs->state |= AAC_STATE_DEAD; 4661942c5e3cSpl196000 466258bc78c7SXin Chen finish: 4663942c5e3cSpl196000 softs->state &= ~AAC_STATE_RESET; 4664942c5e3cSpl196000 return (rval); 4665942c5e3cSpl196000 } 4666942c5e3cSpl196000 4667942c5e3cSpl196000 static int 4668942c5e3cSpl196000 aac_tran_reset(struct scsi_address *ap, int level) 4669942c5e3cSpl196000 { 4670942c5e3cSpl196000 struct aac_softstate *softs = AAC_TRAN2SOFTS(ap->a_hba_tran); 4671942c5e3cSpl196000 int rval; 4672942c5e3cSpl196000 4673942c5e3cSpl196000 DBCALLED(softs, 1); 4674942c5e3cSpl196000 4675942c5e3cSpl196000 if (level != RESET_ALL) { 4676942c5e3cSpl196000 cmn_err(CE_NOTE, "!reset target/lun not supported"); 4677942c5e3cSpl196000 return (0); 4678942c5e3cSpl196000 } 4679942c5e3cSpl196000 4680942c5e3cSpl196000 mutex_enter(&softs->io_lock); 468158bc78c7SXin Chen switch (rval = aac_do_reset(softs)) { 468258bc78c7SXin Chen case AAC_IOP_RESET_SUCCEED: 4683942c5e3cSpl196000 aac_abort_iocmds(softs, AAC_IOCMD_OUTSTANDING | AAC_IOCMD_ASYNC, 4684942c5e3cSpl196000 NULL, CMD_RESET); 4685942c5e3cSpl196000 aac_start_waiting_io(softs); 468658bc78c7SXin Chen break; 468758bc78c7SXin Chen case AAC_IOP_RESET_FAILED: 468858bc78c7SXin Chen /* Abort IOCTL cmds when adapter is dead */ 4689942c5e3cSpl196000 aac_abort_iocmds(softs, AAC_IOCMD_ALL, NULL, CMD_RESET); 469058bc78c7SXin Chen break; 469158bc78c7SXin Chen case AAC_IOP_RESET_ABNORMAL: 469258bc78c7SXin Chen aac_start_waiting_io(softs); 4693942c5e3cSpl196000 } 4694942c5e3cSpl196000 mutex_exit(&softs->io_lock); 4695942c5e3cSpl196000 4696942c5e3cSpl196000 aac_drain_comp_q(softs); 469758bc78c7SXin Chen return (rval == 0); 4698942c5e3cSpl196000 } 4699942c5e3cSpl196000 4700942c5e3cSpl196000 static int 4701942c5e3cSpl196000 aac_tran_abort(struct scsi_address *ap, struct scsi_pkt *pkt) 4702942c5e3cSpl196000 { 4703942c5e3cSpl196000 struct aac_softstate *softs = AAC_TRAN2SOFTS(ap->a_hba_tran); 4704942c5e3cSpl196000 4705942c5e3cSpl196000 DBCALLED(softs, 1); 4706942c5e3cSpl196000 4707942c5e3cSpl196000 mutex_enter(&softs->io_lock); 4708942c5e3cSpl196000 aac_abort_iocmds(softs, 0, pkt, CMD_ABORTED); 4709942c5e3cSpl196000 mutex_exit(&softs->io_lock); 4710942c5e3cSpl196000 4711942c5e3cSpl196000 aac_drain_comp_q(softs); 4712942c5e3cSpl196000 return (1); 4713942c5e3cSpl196000 } 4714942c5e3cSpl196000 4715942c5e3cSpl196000 void 4716942c5e3cSpl196000 aac_free_dmamap(struct aac_cmd *acp) 4717942c5e3cSpl196000 { 4718942c5e3cSpl196000 /* Free dma mapping */ 4719942c5e3cSpl196000 if (acp->flags & AAC_CMD_DMA_VALID) { 4720942c5e3cSpl196000 ASSERT(acp->buf_dma_handle); 4721942c5e3cSpl196000 (void) ddi_dma_unbind_handle(acp->buf_dma_handle); 4722942c5e3cSpl196000 acp->flags &= ~AAC_CMD_DMA_VALID; 4723942c5e3cSpl196000 } 4724942c5e3cSpl196000 4725942c5e3cSpl196000 if (acp->abp != NULL) { /* free non-aligned buf DMA */ 4726942c5e3cSpl196000 ASSERT(acp->buf_dma_handle); 4727942c5e3cSpl196000 if ((acp->flags & AAC_CMD_BUF_WRITE) == 0 && acp->bp) 4728942c5e3cSpl196000 ddi_rep_get8(acp->abh, (uint8_t *)acp->bp->b_un.b_addr, 4729942c5e3cSpl196000 (uint8_t *)acp->abp, acp->bp->b_bcount, 4730942c5e3cSpl196000 DDI_DEV_AUTOINCR); 4731942c5e3cSpl196000 ddi_dma_mem_free(&acp->abh); 4732942c5e3cSpl196000 acp->abp = NULL; 4733942c5e3cSpl196000 } 4734942c5e3cSpl196000 4735942c5e3cSpl196000 if (acp->buf_dma_handle) { 4736942c5e3cSpl196000 ddi_dma_free_handle(&acp->buf_dma_handle); 4737942c5e3cSpl196000 acp->buf_dma_handle = NULL; 4738942c5e3cSpl196000 } 4739942c5e3cSpl196000 } 4740942c5e3cSpl196000 4741942c5e3cSpl196000 static void 4742942c5e3cSpl196000 aac_unknown_scmd(struct aac_softstate *softs, struct aac_cmd *acp) 4743942c5e3cSpl196000 { 4744942c5e3cSpl196000 AACDB_PRINT(softs, CE_CONT, "SCMD 0x%x not supported", 4745a74f7440Spl196000 ((union scsi_cdb *)(void *)acp->pkt->pkt_cdbp)->scc_cmd); 4746942c5e3cSpl196000 aac_free_dmamap(acp); 4747942c5e3cSpl196000 aac_set_arq_data(acp->pkt, KEY_ILLEGAL_REQUEST, 0x20, 0x00, 0); 4748942c5e3cSpl196000 aac_soft_callback(softs, acp); 4749942c5e3cSpl196000 } 4750942c5e3cSpl196000 4751942c5e3cSpl196000 /* 4752942c5e3cSpl196000 * Handle command to logical device 4753942c5e3cSpl196000 */ 4754942c5e3cSpl196000 static int 4755942c5e3cSpl196000 aac_tran_start_ld(struct aac_softstate *softs, struct aac_cmd *acp) 4756942c5e3cSpl196000 { 4757942c5e3cSpl196000 struct aac_container *dvp; 4758942c5e3cSpl196000 struct scsi_pkt *pkt; 4759942c5e3cSpl196000 union scsi_cdb *cdbp; 4760942c5e3cSpl196000 struct buf *bp; 4761942c5e3cSpl196000 int rval; 4762942c5e3cSpl196000 476358bc78c7SXin Chen dvp = (struct aac_container *)acp->dvp; 4764942c5e3cSpl196000 pkt = acp->pkt; 4765a74f7440Spl196000 cdbp = (void *)pkt->pkt_cdbp; 4766942c5e3cSpl196000 bp = acp->bp; 4767942c5e3cSpl196000 4768942c5e3cSpl196000 switch (cdbp->scc_cmd) { 4769942c5e3cSpl196000 case SCMD_INQUIRY: /* inquiry */ 4770942c5e3cSpl196000 aac_free_dmamap(acp); 4771942c5e3cSpl196000 aac_inquiry(softs, pkt, cdbp, bp); 4772942c5e3cSpl196000 aac_soft_callback(softs, acp); 4773942c5e3cSpl196000 rval = TRAN_ACCEPT; 4774942c5e3cSpl196000 break; 4775942c5e3cSpl196000 4776942c5e3cSpl196000 case SCMD_READ_CAPACITY: /* read capacity */ 4777942c5e3cSpl196000 if (bp && bp->b_un.b_addr && bp->b_bcount) { 4778942c5e3cSpl196000 struct scsi_capacity cap; 4779942c5e3cSpl196000 uint64_t last_lba; 4780942c5e3cSpl196000 4781942c5e3cSpl196000 /* check 64-bit LBA */ 4782942c5e3cSpl196000 last_lba = dvp->size - 1; 4783942c5e3cSpl196000 if (last_lba > 0xffffffffull) { 4784942c5e3cSpl196000 cap.capacity = 0xfffffffful; 4785942c5e3cSpl196000 } else { 4786942c5e3cSpl196000 cap.capacity = BE_32(last_lba); 4787942c5e3cSpl196000 } 4788942c5e3cSpl196000 cap.lbasize = BE_32(AAC_SECTOR_SIZE); 4789942c5e3cSpl196000 4790942c5e3cSpl196000 aac_free_dmamap(acp); 4791942c5e3cSpl196000 if (bp->b_flags & (B_PHYS|B_PAGEIO)) 4792942c5e3cSpl196000 bp_mapin(bp); 479351ccf66eSjd218194 bcopy(&cap, bp->b_un.b_addr, min(bp->b_bcount, 8)); 4794942c5e3cSpl196000 pkt->pkt_state |= STATE_XFERRED_DATA; 4795942c5e3cSpl196000 } 4796942c5e3cSpl196000 aac_soft_callback(softs, acp); 4797942c5e3cSpl196000 rval = TRAN_ACCEPT; 4798942c5e3cSpl196000 break; 4799942c5e3cSpl196000 4800942c5e3cSpl196000 case SCMD_SVC_ACTION_IN_G4: /* read capacity 16 */ 4801942c5e3cSpl196000 /* Check if containers need 64-bit LBA support */ 4802942c5e3cSpl196000 if (cdbp->cdb_opaque[1] == SSVC_ACTION_READ_CAPACITY_G4) { 4803942c5e3cSpl196000 if (bp && bp->b_un.b_addr && bp->b_bcount) { 4804942c5e3cSpl196000 struct scsi_capacity_16 cap16; 4805942c5e3cSpl196000 int cap_len = sizeof (struct scsi_capacity_16); 4806942c5e3cSpl196000 4807942c5e3cSpl196000 bzero(&cap16, cap_len); 4808b6094a86Sjd218194 cap16.sc_capacity = BE_64(dvp->size - 1); 4809942c5e3cSpl196000 cap16.sc_lbasize = BE_32(AAC_SECTOR_SIZE); 4810942c5e3cSpl196000 4811942c5e3cSpl196000 aac_free_dmamap(acp); 4812942c5e3cSpl196000 if (bp->b_flags & (B_PHYS | B_PAGEIO)) 4813942c5e3cSpl196000 bp_mapin(bp); 481451ccf66eSjd218194 bcopy(&cap16, bp->b_un.b_addr, 481551ccf66eSjd218194 min(bp->b_bcount, cap_len)); 4816942c5e3cSpl196000 pkt->pkt_state |= STATE_XFERRED_DATA; 4817942c5e3cSpl196000 } 4818942c5e3cSpl196000 aac_soft_callback(softs, acp); 4819942c5e3cSpl196000 } else { 4820942c5e3cSpl196000 aac_unknown_scmd(softs, acp); 4821942c5e3cSpl196000 } 4822942c5e3cSpl196000 rval = TRAN_ACCEPT; 4823942c5e3cSpl196000 break; 4824942c5e3cSpl196000 4825942c5e3cSpl196000 case SCMD_READ_G4: /* read_16 */ 4826942c5e3cSpl196000 case SCMD_WRITE_G4: /* write_16 */ 4827942c5e3cSpl196000 if (softs->flags & AAC_FLAGS_RAW_IO) { 4828942c5e3cSpl196000 /* NOTE: GETG4ADDRTL(cdbp) is int32_t */ 4829942c5e3cSpl196000 acp->blkno = ((uint64_t) \ 4830942c5e3cSpl196000 GETG4ADDR(cdbp) << 32) | \ 4831942c5e3cSpl196000 (uint32_t)GETG4ADDRTL(cdbp); 4832942c5e3cSpl196000 goto do_io; 4833942c5e3cSpl196000 } 4834942c5e3cSpl196000 AACDB_PRINT(softs, CE_WARN, "64-bit LBA not supported"); 4835942c5e3cSpl196000 aac_unknown_scmd(softs, acp); 4836942c5e3cSpl196000 rval = TRAN_ACCEPT; 4837942c5e3cSpl196000 break; 4838942c5e3cSpl196000 4839942c5e3cSpl196000 case SCMD_READ: /* read_6 */ 4840942c5e3cSpl196000 case SCMD_WRITE: /* write_6 */ 4841942c5e3cSpl196000 acp->blkno = GETG0ADDR(cdbp); 4842942c5e3cSpl196000 goto do_io; 4843942c5e3cSpl196000 484458bc78c7SXin Chen case SCMD_READ_G5: /* read_12 */ 484558bc78c7SXin Chen case SCMD_WRITE_G5: /* write_12 */ 484658bc78c7SXin Chen acp->blkno = GETG5ADDR(cdbp); 484758bc78c7SXin Chen goto do_io; 484858bc78c7SXin Chen 4849942c5e3cSpl196000 case SCMD_READ_G1: /* read_10 */ 4850942c5e3cSpl196000 case SCMD_WRITE_G1: /* write_10 */ 4851942c5e3cSpl196000 acp->blkno = (uint32_t)GETG1ADDR(cdbp); 4852942c5e3cSpl196000 do_io: 4853942c5e3cSpl196000 if (acp->flags & AAC_CMD_DMA_VALID) { 4854942c5e3cSpl196000 uint64_t cnt_size = dvp->size; 4855942c5e3cSpl196000 4856942c5e3cSpl196000 /* 4857942c5e3cSpl196000 * If LBA > array size AND rawio, the 4858942c5e3cSpl196000 * adapter may hang. So check it before 4859942c5e3cSpl196000 * sending. 4860942c5e3cSpl196000 * NOTE: (blkno + blkcnt) may overflow 4861942c5e3cSpl196000 */ 4862942c5e3cSpl196000 if ((acp->blkno < cnt_size) && 4863942c5e3cSpl196000 ((acp->blkno + acp->bcount / 4864942c5e3cSpl196000 AAC_BLK_SIZE) <= cnt_size)) { 4865942c5e3cSpl196000 rval = aac_do_io(softs, acp); 4866942c5e3cSpl196000 } else { 4867942c5e3cSpl196000 /* 4868942c5e3cSpl196000 * Request exceeds the capacity of disk, 4869942c5e3cSpl196000 * set error block number to last LBA 4870942c5e3cSpl196000 * + 1. 4871942c5e3cSpl196000 */ 4872942c5e3cSpl196000 aac_set_arq_data(pkt, 4873942c5e3cSpl196000 KEY_ILLEGAL_REQUEST, 0x21, 4874942c5e3cSpl196000 0x00, cnt_size); 4875942c5e3cSpl196000 aac_soft_callback(softs, acp); 4876942c5e3cSpl196000 rval = TRAN_ACCEPT; 4877942c5e3cSpl196000 } 4878942c5e3cSpl196000 } else if (acp->bcount == 0) { 4879942c5e3cSpl196000 /* For 0 length IO, just return ok */ 4880942c5e3cSpl196000 aac_soft_callback(softs, acp); 4881942c5e3cSpl196000 rval = TRAN_ACCEPT; 4882942c5e3cSpl196000 } else { 4883942c5e3cSpl196000 rval = TRAN_BADPKT; 4884942c5e3cSpl196000 } 4885942c5e3cSpl196000 break; 4886942c5e3cSpl196000 4887942c5e3cSpl196000 case SCMD_MODE_SENSE: /* mode_sense_6 */ 4888942c5e3cSpl196000 case SCMD_MODE_SENSE_G1: { /* mode_sense_10 */ 4889942c5e3cSpl196000 int capacity; 4890942c5e3cSpl196000 4891942c5e3cSpl196000 aac_free_dmamap(acp); 4892942c5e3cSpl196000 if (dvp->size > 0xffffffffull) 4893942c5e3cSpl196000 capacity = 0xfffffffful; /* 64-bit LBA */ 4894942c5e3cSpl196000 else 4895942c5e3cSpl196000 capacity = dvp->size; 4896942c5e3cSpl196000 aac_mode_sense(softs, pkt, cdbp, bp, capacity); 4897942c5e3cSpl196000 aac_soft_callback(softs, acp); 4898942c5e3cSpl196000 rval = TRAN_ACCEPT; 4899942c5e3cSpl196000 break; 4900942c5e3cSpl196000 } 4901942c5e3cSpl196000 4902b40e8a89Szhongyan gu - Sun Microsystems - Beijing China case SCMD_START_STOP: 4903b40e8a89Szhongyan gu - Sun Microsystems - Beijing China if (softs->support_opt2 & AAC_SUPPORTED_POWER_MANAGEMENT) { 4904b40e8a89Szhongyan gu - Sun Microsystems - Beijing China acp->aac_cmd_fib = aac_cmd_fib_startstop; 4905b40e8a89Szhongyan gu - Sun Microsystems - Beijing China acp->ac_comp = aac_startstop_complete; 4906b40e8a89Szhongyan gu - Sun Microsystems - Beijing China rval = aac_do_io(softs, acp); 4907b40e8a89Szhongyan gu - Sun Microsystems - Beijing China break; 4908b40e8a89Szhongyan gu - Sun Microsystems - Beijing China } 4909b40e8a89Szhongyan gu - Sun Microsystems - Beijing China /* FALLTHRU */ 4910942c5e3cSpl196000 case SCMD_TEST_UNIT_READY: 4911942c5e3cSpl196000 case SCMD_REQUEST_SENSE: 4912942c5e3cSpl196000 case SCMD_FORMAT: 4913942c5e3cSpl196000 aac_free_dmamap(acp); 4914942c5e3cSpl196000 if (bp && bp->b_un.b_addr && bp->b_bcount) { 4915942c5e3cSpl196000 if (acp->flags & AAC_CMD_BUF_READ) { 4916942c5e3cSpl196000 if (bp->b_flags & (B_PHYS|B_PAGEIO)) 4917942c5e3cSpl196000 bp_mapin(bp); 4918942c5e3cSpl196000 bzero(bp->b_un.b_addr, bp->b_bcount); 4919942c5e3cSpl196000 } 4920942c5e3cSpl196000 pkt->pkt_state |= STATE_XFERRED_DATA; 4921942c5e3cSpl196000 } 4922942c5e3cSpl196000 aac_soft_callback(softs, acp); 4923942c5e3cSpl196000 rval = TRAN_ACCEPT; 4924942c5e3cSpl196000 break; 4925942c5e3cSpl196000 4926942c5e3cSpl196000 case SCMD_SYNCHRONIZE_CACHE: 4927942c5e3cSpl196000 acp->flags |= AAC_CMD_NTAG; 4928942c5e3cSpl196000 acp->aac_cmd_fib = aac_cmd_fib_sync; 4929942c5e3cSpl196000 acp->ac_comp = aac_synccache_complete; 4930942c5e3cSpl196000 rval = aac_do_io(softs, acp); 4931942c5e3cSpl196000 break; 4932942c5e3cSpl196000 4933942c5e3cSpl196000 case SCMD_DOORLOCK: 4934942c5e3cSpl196000 aac_free_dmamap(acp); 4935942c5e3cSpl196000 dvp->locked = (pkt->pkt_cdbp[4] & 0x01) ? 1 : 0; 4936942c5e3cSpl196000 aac_soft_callback(softs, acp); 4937942c5e3cSpl196000 rval = TRAN_ACCEPT; 4938942c5e3cSpl196000 break; 4939942c5e3cSpl196000 4940942c5e3cSpl196000 default: /* unknown command */ 4941942c5e3cSpl196000 aac_unknown_scmd(softs, acp); 4942942c5e3cSpl196000 rval = TRAN_ACCEPT; 4943942c5e3cSpl196000 break; 4944942c5e3cSpl196000 } 4945942c5e3cSpl196000 4946942c5e3cSpl196000 return (rval); 4947942c5e3cSpl196000 } 4948942c5e3cSpl196000 4949942c5e3cSpl196000 static int 4950942c5e3cSpl196000 aac_tran_start(struct scsi_address *ap, struct scsi_pkt *pkt) 4951942c5e3cSpl196000 { 4952942c5e3cSpl196000 struct aac_softstate *softs = AAC_TRAN2SOFTS(ap->a_hba_tran); 4953942c5e3cSpl196000 struct aac_cmd *acp = PKT2AC(pkt); 495458bc78c7SXin Chen struct aac_device *dvp = acp->dvp; 4955942c5e3cSpl196000 int rval; 4956942c5e3cSpl196000 4957942c5e3cSpl196000 DBCALLED(softs, 2); 4958942c5e3cSpl196000 4959942c5e3cSpl196000 /* 4960942c5e3cSpl196000 * Reinitialize some fields of ac and pkt; the packet may 4961942c5e3cSpl196000 * have been resubmitted 4962942c5e3cSpl196000 */ 4963942c5e3cSpl196000 acp->flags &= AAC_CMD_CONSISTENT | AAC_CMD_DMA_PARTIAL | \ 4964942c5e3cSpl196000 AAC_CMD_BUF_READ | AAC_CMD_BUF_WRITE | AAC_CMD_DMA_VALID; 4965942c5e3cSpl196000 acp->timeout = acp->pkt->pkt_time; 4966942c5e3cSpl196000 if (pkt->pkt_flags & FLAG_NOINTR) 4967942c5e3cSpl196000 acp->flags |= AAC_CMD_NO_INTR; 496858bc78c7SXin Chen #ifdef DEBUG 496958bc78c7SXin Chen acp->fib_flags = AACDB_FLAGS_FIB_SCMD; 497058bc78c7SXin Chen #endif 4971942c5e3cSpl196000 pkt->pkt_reason = CMD_CMPLT; 4972942c5e3cSpl196000 pkt->pkt_state = 0; 4973942c5e3cSpl196000 pkt->pkt_statistics = 0; 497458bc78c7SXin Chen *pkt->pkt_scbp = STATUS_GOOD; /* clear arq scsi_status */ 4975942c5e3cSpl196000 4976942c5e3cSpl196000 if (acp->flags & AAC_CMD_DMA_VALID) { 4977942c5e3cSpl196000 pkt->pkt_resid = acp->bcount; 4978942c5e3cSpl196000 /* Consistent packets need to be sync'ed first */ 4979942c5e3cSpl196000 if ((acp->flags & AAC_CMD_CONSISTENT) && 4980942c5e3cSpl196000 (acp->flags & AAC_CMD_BUF_WRITE)) 4981942c5e3cSpl196000 if (aac_dma_sync_ac(acp) != AACOK) { 4982942c5e3cSpl196000 ddi_fm_service_impact(softs->devinfo_p, 4983942c5e3cSpl196000 DDI_SERVICE_UNAFFECTED); 4984942c5e3cSpl196000 return (TRAN_BADPKT); 4985942c5e3cSpl196000 } 4986942c5e3cSpl196000 } else { 4987942c5e3cSpl196000 pkt->pkt_resid = 0; 4988942c5e3cSpl196000 } 4989942c5e3cSpl196000 4990942c5e3cSpl196000 mutex_enter(&softs->io_lock); 4991942c5e3cSpl196000 AACDB_PRINT_SCMD(softs, acp); 499258bc78c7SXin Chen if ((dvp->flags & (AAC_DFLAG_VALID | AAC_DFLAG_CONFIGURING)) && 499358bc78c7SXin Chen !(softs->state & AAC_STATE_DEAD)) { 499458bc78c7SXin Chen if (dvp->type == AAC_DEV_LD) { 499558bc78c7SXin Chen if (ap->a_lun == 0) 4996942c5e3cSpl196000 rval = aac_tran_start_ld(softs, acp); 499758bc78c7SXin Chen else 499858bc78c7SXin Chen goto error; 499958bc78c7SXin Chen } else { 500058bc78c7SXin Chen rval = aac_do_io(softs, acp); 500158bc78c7SXin Chen } 500258bc78c7SXin Chen } else { 500358bc78c7SXin Chen error: 500458bc78c7SXin Chen #ifdef DEBUG 500558bc78c7SXin Chen if (!(softs->state & AAC_STATE_DEAD)) { 500658bc78c7SXin Chen AACDB_PRINT_TRAN(softs, 500758bc78c7SXin Chen "Cannot send cmd to target t%dL%d: %s", 500858bc78c7SXin Chen ap->a_target, ap->a_lun, 500958bc78c7SXin Chen "target invalid"); 5010942c5e3cSpl196000 } else { 5011942c5e3cSpl196000 AACDB_PRINT(softs, CE_WARN, 5012942c5e3cSpl196000 "Cannot send cmd to target t%dL%d: %s", 5013942c5e3cSpl196000 ap->a_target, ap->a_lun, 501458bc78c7SXin Chen "adapter dead"); 501558bc78c7SXin Chen } 501658bc78c7SXin Chen #endif 5017942c5e3cSpl196000 rval = TRAN_FATAL_ERROR; 5018942c5e3cSpl196000 } 5019942c5e3cSpl196000 mutex_exit(&softs->io_lock); 5020942c5e3cSpl196000 return (rval); 5021942c5e3cSpl196000 } 5022942c5e3cSpl196000 5023942c5e3cSpl196000 static int 5024942c5e3cSpl196000 aac_tran_getcap(struct scsi_address *ap, char *cap, int whom) 5025942c5e3cSpl196000 { 5026942c5e3cSpl196000 struct aac_softstate *softs = AAC_TRAN2SOFTS(ap->a_hba_tran); 502758bc78c7SXin Chen struct aac_device *dvp; 5028942c5e3cSpl196000 int rval; 5029942c5e3cSpl196000 5030942c5e3cSpl196000 DBCALLED(softs, 2); 5031942c5e3cSpl196000 5032942c5e3cSpl196000 /* We don't allow inquiring about capabilities for other targets */ 5033942c5e3cSpl196000 if (cap == NULL || whom == 0) { 5034942c5e3cSpl196000 AACDB_PRINT(softs, CE_WARN, 5035942c5e3cSpl196000 "GetCap> %s not supported: whom=%d", cap, whom); 5036942c5e3cSpl196000 return (-1); 5037942c5e3cSpl196000 } 5038942c5e3cSpl196000 5039942c5e3cSpl196000 mutex_enter(&softs->io_lock); 504058bc78c7SXin Chen dvp = AAC_DEV(softs, ap->a_target); 504158bc78c7SXin Chen if (dvp == NULL || !AAC_DEV_IS_VALID(dvp)) { 5042942c5e3cSpl196000 mutex_exit(&softs->io_lock); 504358bc78c7SXin Chen AACDB_PRINT_TRAN(softs, "Bad target t%dL%d to getcap", 5044942c5e3cSpl196000 ap->a_target, ap->a_lun); 5045942c5e3cSpl196000 return (-1); 5046942c5e3cSpl196000 } 5047942c5e3cSpl196000 5048942c5e3cSpl196000 switch (scsi_hba_lookup_capstr(cap)) { 5049942c5e3cSpl196000 case SCSI_CAP_ARQ: /* auto request sense */ 5050942c5e3cSpl196000 rval = 1; 5051942c5e3cSpl196000 break; 5052942c5e3cSpl196000 case SCSI_CAP_UNTAGGED_QING: 5053942c5e3cSpl196000 case SCSI_CAP_TAGGED_QING: 5054942c5e3cSpl196000 rval = 1; 5055942c5e3cSpl196000 break; 5056942c5e3cSpl196000 case SCSI_CAP_DMA_MAX: 505772888e72Speng liu - Sun Microsystems - Beijing China rval = softs->dma_max; 5058942c5e3cSpl196000 break; 5059942c5e3cSpl196000 default: 5060942c5e3cSpl196000 rval = -1; 5061942c5e3cSpl196000 break; 5062942c5e3cSpl196000 } 5063942c5e3cSpl196000 mutex_exit(&softs->io_lock); 5064942c5e3cSpl196000 5065942c5e3cSpl196000 AACDB_PRINT_TRAN(softs, "GetCap> %s t%dL%d: rval=%d", 5066942c5e3cSpl196000 cap, ap->a_target, ap->a_lun, rval); 5067942c5e3cSpl196000 return (rval); 5068942c5e3cSpl196000 } 5069942c5e3cSpl196000 5070942c5e3cSpl196000 /*ARGSUSED*/ 5071942c5e3cSpl196000 static int 5072942c5e3cSpl196000 aac_tran_setcap(struct scsi_address *ap, char *cap, int value, int whom) 5073942c5e3cSpl196000 { 5074942c5e3cSpl196000 struct aac_softstate *softs = AAC_TRAN2SOFTS(ap->a_hba_tran); 507558bc78c7SXin Chen struct aac_device *dvp; 5076942c5e3cSpl196000 int rval; 5077942c5e3cSpl196000 5078942c5e3cSpl196000 DBCALLED(softs, 2); 5079942c5e3cSpl196000 5080942c5e3cSpl196000 /* We don't allow inquiring about capabilities for other targets */ 5081942c5e3cSpl196000 if (cap == NULL || whom == 0) { 5082942c5e3cSpl196000 AACDB_PRINT(softs, CE_WARN, 5083942c5e3cSpl196000 "SetCap> %s not supported: whom=%d", cap, whom); 5084942c5e3cSpl196000 return (-1); 5085942c5e3cSpl196000 } 5086942c5e3cSpl196000 5087942c5e3cSpl196000 mutex_enter(&softs->io_lock); 508858bc78c7SXin Chen dvp = AAC_DEV(softs, ap->a_target); 508958bc78c7SXin Chen if (dvp == NULL || !AAC_DEV_IS_VALID(dvp)) { 5090942c5e3cSpl196000 mutex_exit(&softs->io_lock); 509158bc78c7SXin Chen AACDB_PRINT_TRAN(softs, "Bad target t%dL%d to setcap", 5092942c5e3cSpl196000 ap->a_target, ap->a_lun); 5093942c5e3cSpl196000 return (-1); 5094942c5e3cSpl196000 } 5095942c5e3cSpl196000 5096942c5e3cSpl196000 switch (scsi_hba_lookup_capstr(cap)) { 5097942c5e3cSpl196000 case SCSI_CAP_ARQ: 5098942c5e3cSpl196000 /* Force auto request sense */ 5099942c5e3cSpl196000 rval = (value == 1) ? 1 : 0; 5100942c5e3cSpl196000 break; 5101942c5e3cSpl196000 case SCSI_CAP_UNTAGGED_QING: 5102942c5e3cSpl196000 case SCSI_CAP_TAGGED_QING: 5103942c5e3cSpl196000 rval = (value == 1) ? 1 : 0; 5104942c5e3cSpl196000 break; 5105942c5e3cSpl196000 default: 5106942c5e3cSpl196000 rval = -1; 5107942c5e3cSpl196000 break; 5108942c5e3cSpl196000 } 5109942c5e3cSpl196000 mutex_exit(&softs->io_lock); 5110942c5e3cSpl196000 5111942c5e3cSpl196000 AACDB_PRINT_TRAN(softs, "SetCap> %s t%dL%d val=%d: rval=%d", 5112942c5e3cSpl196000 cap, ap->a_target, ap->a_lun, value, rval); 5113942c5e3cSpl196000 return (rval); 5114942c5e3cSpl196000 } 5115942c5e3cSpl196000 5116942c5e3cSpl196000 static void 5117942c5e3cSpl196000 aac_tran_destroy_pkt(struct scsi_address *ap, struct scsi_pkt *pkt) 5118942c5e3cSpl196000 { 5119942c5e3cSpl196000 struct aac_cmd *acp = PKT2AC(pkt); 5120942c5e3cSpl196000 5121942c5e3cSpl196000 DBCALLED(NULL, 2); 5122942c5e3cSpl196000 5123942c5e3cSpl196000 if (acp->sgt) { 5124942c5e3cSpl196000 kmem_free(acp->sgt, sizeof (struct aac_sge) * \ 5125942c5e3cSpl196000 acp->left_cookien); 5126942c5e3cSpl196000 } 5127942c5e3cSpl196000 aac_free_dmamap(acp); 5128942c5e3cSpl196000 ASSERT(acp->slotp == NULL); 5129942c5e3cSpl196000 scsi_hba_pkt_free(ap, pkt); 5130942c5e3cSpl196000 } 5131942c5e3cSpl196000 5132942c5e3cSpl196000 int 5133942c5e3cSpl196000 aac_cmd_dma_alloc(struct aac_softstate *softs, struct aac_cmd *acp, 5134942c5e3cSpl196000 struct buf *bp, int flags, int (*cb)(), caddr_t arg) 5135942c5e3cSpl196000 { 5136942c5e3cSpl196000 int kf = (cb == SLEEP_FUNC) ? KM_SLEEP : KM_NOSLEEP; 5137942c5e3cSpl196000 uint_t oldcookiec; 5138942c5e3cSpl196000 int bioerr; 5139942c5e3cSpl196000 int rval; 5140942c5e3cSpl196000 5141942c5e3cSpl196000 oldcookiec = acp->left_cookien; 5142942c5e3cSpl196000 5143942c5e3cSpl196000 /* Move window to build s/g map */ 5144942c5e3cSpl196000 if (acp->total_nwin > 0) { 5145942c5e3cSpl196000 if (++acp->cur_win < acp->total_nwin) { 5146942c5e3cSpl196000 off_t off; 5147942c5e3cSpl196000 size_t len; 5148942c5e3cSpl196000 5149942c5e3cSpl196000 rval = ddi_dma_getwin(acp->buf_dma_handle, acp->cur_win, 5150942c5e3cSpl196000 &off, &len, &acp->cookie, &acp->left_cookien); 5151942c5e3cSpl196000 if (rval == DDI_SUCCESS) 5152942c5e3cSpl196000 goto get_dma_cookies; 5153942c5e3cSpl196000 AACDB_PRINT(softs, CE_WARN, 5154942c5e3cSpl196000 "ddi_dma_getwin() fail %d", rval); 515558bc78c7SXin Chen return (AACERR); 5156942c5e3cSpl196000 } 5157942c5e3cSpl196000 AACDB_PRINT(softs, CE_WARN, "Nothing to transfer"); 515858bc78c7SXin Chen return (AACERR); 5159942c5e3cSpl196000 } 5160942c5e3cSpl196000 5161942c5e3cSpl196000 /* We need to transfer data, so we alloc DMA resources for this pkt */ 5162942c5e3cSpl196000 if (bp && bp->b_bcount != 0 && !(acp->flags & AAC_CMD_DMA_VALID)) { 5163942c5e3cSpl196000 uint_t dma_flags = 0; 5164942c5e3cSpl196000 struct aac_sge *sge; 5165942c5e3cSpl196000 5166942c5e3cSpl196000 /* 5167942c5e3cSpl196000 * We will still use this point to fake some 5168942c5e3cSpl196000 * infomation in tran_start 5169942c5e3cSpl196000 */ 5170942c5e3cSpl196000 acp->bp = bp; 5171942c5e3cSpl196000 5172942c5e3cSpl196000 /* Set dma flags */ 5173942c5e3cSpl196000 if (BUF_IS_READ(bp)) { 5174942c5e3cSpl196000 dma_flags |= DDI_DMA_READ; 5175942c5e3cSpl196000 acp->flags |= AAC_CMD_BUF_READ; 5176942c5e3cSpl196000 } else { 5177942c5e3cSpl196000 dma_flags |= DDI_DMA_WRITE; 5178942c5e3cSpl196000 acp->flags |= AAC_CMD_BUF_WRITE; 5179942c5e3cSpl196000 } 5180942c5e3cSpl196000 if (flags & PKT_CONSISTENT) 5181942c5e3cSpl196000 dma_flags |= DDI_DMA_CONSISTENT; 5182942c5e3cSpl196000 if (flags & PKT_DMA_PARTIAL) 5183942c5e3cSpl196000 dma_flags |= DDI_DMA_PARTIAL; 5184942c5e3cSpl196000 5185942c5e3cSpl196000 /* Alloc buf dma handle */ 5186942c5e3cSpl196000 if (!acp->buf_dma_handle) { 5187942c5e3cSpl196000 rval = ddi_dma_alloc_handle(softs->devinfo_p, 5188942c5e3cSpl196000 &softs->buf_dma_attr, cb, arg, 5189942c5e3cSpl196000 &acp->buf_dma_handle); 5190942c5e3cSpl196000 if (rval != DDI_SUCCESS) { 5191942c5e3cSpl196000 AACDB_PRINT(softs, CE_WARN, 5192942c5e3cSpl196000 "Can't allocate DMA handle, errno=%d", 5193942c5e3cSpl196000 rval); 5194942c5e3cSpl196000 goto error_out; 5195942c5e3cSpl196000 } 5196942c5e3cSpl196000 } 5197942c5e3cSpl196000 5198942c5e3cSpl196000 /* Bind buf */ 5199942c5e3cSpl196000 if (((uintptr_t)bp->b_un.b_addr & AAC_DMA_ALIGN_MASK) == 0) { 5200942c5e3cSpl196000 rval = ddi_dma_buf_bind_handle(acp->buf_dma_handle, 5201942c5e3cSpl196000 bp, dma_flags, cb, arg, &acp->cookie, 5202942c5e3cSpl196000 &acp->left_cookien); 5203942c5e3cSpl196000 } else { 5204942c5e3cSpl196000 size_t bufsz; 5205942c5e3cSpl196000 5206942c5e3cSpl196000 AACDB_PRINT_TRAN(softs, 5207942c5e3cSpl196000 "non-aligned buffer: addr=0x%p, cnt=%lu", 5208942c5e3cSpl196000 (void *)bp->b_un.b_addr, bp->b_bcount); 5209942c5e3cSpl196000 if (bp->b_flags & (B_PAGEIO|B_PHYS)) 5210942c5e3cSpl196000 bp_mapin(bp); 5211942c5e3cSpl196000 5212942c5e3cSpl196000 rval = ddi_dma_mem_alloc(acp->buf_dma_handle, 5213942c5e3cSpl196000 AAC_ROUNDUP(bp->b_bcount, AAC_DMA_ALIGN), 521458bc78c7SXin Chen &softs->acc_attr, DDI_DMA_STREAMING, 5215942c5e3cSpl196000 cb, arg, &acp->abp, &bufsz, &acp->abh); 5216942c5e3cSpl196000 5217942c5e3cSpl196000 if (rval != DDI_SUCCESS) { 5218942c5e3cSpl196000 AACDB_PRINT(softs, CE_NOTE, 5219942c5e3cSpl196000 "Cannot alloc DMA to non-aligned buf"); 5220942c5e3cSpl196000 bioerr = 0; 5221942c5e3cSpl196000 goto error_out; 5222942c5e3cSpl196000 } 5223942c5e3cSpl196000 5224942c5e3cSpl196000 if (acp->flags & AAC_CMD_BUF_WRITE) 5225942c5e3cSpl196000 ddi_rep_put8(acp->abh, 5226942c5e3cSpl196000 (uint8_t *)bp->b_un.b_addr, 5227942c5e3cSpl196000 (uint8_t *)acp->abp, bp->b_bcount, 5228942c5e3cSpl196000 DDI_DEV_AUTOINCR); 5229942c5e3cSpl196000 5230942c5e3cSpl196000 rval = ddi_dma_addr_bind_handle(acp->buf_dma_handle, 5231942c5e3cSpl196000 NULL, acp->abp, bufsz, dma_flags, cb, arg, 5232942c5e3cSpl196000 &acp->cookie, &acp->left_cookien); 5233942c5e3cSpl196000 } 5234942c5e3cSpl196000 5235942c5e3cSpl196000 switch (rval) { 5236942c5e3cSpl196000 case DDI_DMA_PARTIAL_MAP: 5237942c5e3cSpl196000 if (ddi_dma_numwin(acp->buf_dma_handle, 5238942c5e3cSpl196000 &acp->total_nwin) == DDI_FAILURE) { 5239942c5e3cSpl196000 AACDB_PRINT(softs, CE_WARN, 5240942c5e3cSpl196000 "Cannot get number of DMA windows"); 5241942c5e3cSpl196000 bioerr = 0; 5242942c5e3cSpl196000 goto error_out; 5243942c5e3cSpl196000 } 5244942c5e3cSpl196000 AACDB_PRINT_TRAN(softs, "buf bind, %d seg(s)", 5245942c5e3cSpl196000 acp->left_cookien); 5246942c5e3cSpl196000 acp->cur_win = 0; 5247942c5e3cSpl196000 break; 5248942c5e3cSpl196000 5249942c5e3cSpl196000 case DDI_DMA_MAPPED: 5250942c5e3cSpl196000 AACDB_PRINT_TRAN(softs, "buf bind, %d seg(s)", 5251942c5e3cSpl196000 acp->left_cookien); 5252942c5e3cSpl196000 acp->cur_win = 0; 5253942c5e3cSpl196000 acp->total_nwin = 1; 5254942c5e3cSpl196000 break; 5255942c5e3cSpl196000 5256942c5e3cSpl196000 case DDI_DMA_NORESOURCES: 5257942c5e3cSpl196000 bioerr = 0; 5258942c5e3cSpl196000 AACDB_PRINT(softs, CE_WARN, 5259942c5e3cSpl196000 "Cannot bind buf for DMA: DDI_DMA_NORESOURCES"); 5260942c5e3cSpl196000 goto error_out; 5261942c5e3cSpl196000 case DDI_DMA_BADATTR: 5262942c5e3cSpl196000 case DDI_DMA_NOMAPPING: 5263942c5e3cSpl196000 bioerr = EFAULT; 5264942c5e3cSpl196000 AACDB_PRINT(softs, CE_WARN, 5265942c5e3cSpl196000 "Cannot bind buf for DMA: DDI_DMA_NOMAPPING"); 5266942c5e3cSpl196000 goto error_out; 5267942c5e3cSpl196000 case DDI_DMA_TOOBIG: 5268942c5e3cSpl196000 bioerr = EINVAL; 5269942c5e3cSpl196000 AACDB_PRINT(softs, CE_WARN, 5270942c5e3cSpl196000 "Cannot bind buf for DMA: DDI_DMA_TOOBIG(%d)", 5271942c5e3cSpl196000 bp->b_bcount); 5272942c5e3cSpl196000 goto error_out; 5273942c5e3cSpl196000 default: 5274942c5e3cSpl196000 bioerr = EINVAL; 5275942c5e3cSpl196000 AACDB_PRINT(softs, CE_WARN, 5276942c5e3cSpl196000 "Cannot bind buf for DMA: %d", rval); 5277942c5e3cSpl196000 goto error_out; 5278942c5e3cSpl196000 } 5279942c5e3cSpl196000 acp->flags |= AAC_CMD_DMA_VALID; 5280942c5e3cSpl196000 5281942c5e3cSpl196000 get_dma_cookies: 5282942c5e3cSpl196000 ASSERT(acp->left_cookien > 0); 5283942c5e3cSpl196000 if (acp->left_cookien > softs->aac_sg_tablesize) { 5284942c5e3cSpl196000 AACDB_PRINT(softs, CE_NOTE, "large cookiec received %d", 5285942c5e3cSpl196000 acp->left_cookien); 5286942c5e3cSpl196000 bioerr = EINVAL; 5287942c5e3cSpl196000 goto error_out; 5288942c5e3cSpl196000 } 5289942c5e3cSpl196000 if (oldcookiec != acp->left_cookien && acp->sgt != NULL) { 5290942c5e3cSpl196000 kmem_free(acp->sgt, sizeof (struct aac_sge) * \ 5291942c5e3cSpl196000 oldcookiec); 5292942c5e3cSpl196000 acp->sgt = NULL; 5293942c5e3cSpl196000 } 5294942c5e3cSpl196000 if (acp->sgt == NULL) { 5295942c5e3cSpl196000 acp->sgt = kmem_alloc(sizeof (struct aac_sge) * \ 5296942c5e3cSpl196000 acp->left_cookien, kf); 5297942c5e3cSpl196000 if (acp->sgt == NULL) { 5298942c5e3cSpl196000 AACDB_PRINT(softs, CE_WARN, 5299942c5e3cSpl196000 "sgt kmem_alloc fail"); 5300942c5e3cSpl196000 bioerr = ENOMEM; 5301942c5e3cSpl196000 goto error_out; 5302942c5e3cSpl196000 } 5303942c5e3cSpl196000 } 5304942c5e3cSpl196000 5305942c5e3cSpl196000 sge = &acp->sgt[0]; 5306942c5e3cSpl196000 sge->bcount = acp->cookie.dmac_size; 5307942c5e3cSpl196000 sge->addr.ad64.lo = AAC_LS32(acp->cookie.dmac_laddress); 5308942c5e3cSpl196000 sge->addr.ad64.hi = AAC_MS32(acp->cookie.dmac_laddress); 5309942c5e3cSpl196000 acp->bcount = acp->cookie.dmac_size; 5310942c5e3cSpl196000 for (sge++; sge < &acp->sgt[acp->left_cookien]; sge++) { 5311942c5e3cSpl196000 ddi_dma_nextcookie(acp->buf_dma_handle, &acp->cookie); 5312942c5e3cSpl196000 sge->bcount = acp->cookie.dmac_size; 5313942c5e3cSpl196000 sge->addr.ad64.lo = AAC_LS32(acp->cookie.dmac_laddress); 5314942c5e3cSpl196000 sge->addr.ad64.hi = AAC_MS32(acp->cookie.dmac_laddress); 5315942c5e3cSpl196000 acp->bcount += acp->cookie.dmac_size; 5316942c5e3cSpl196000 } 5317942c5e3cSpl196000 5318942c5e3cSpl196000 /* 5319942c5e3cSpl196000 * Note: The old DMA engine do not correctly handle 5320942c5e3cSpl196000 * dma_attr_maxxfer attribute. So we have to ensure 5321942c5e3cSpl196000 * it by ourself. 5322942c5e3cSpl196000 */ 5323942c5e3cSpl196000 if (acp->bcount > softs->buf_dma_attr.dma_attr_maxxfer) { 5324942c5e3cSpl196000 AACDB_PRINT(softs, CE_NOTE, 5325942c5e3cSpl196000 "large xfer size received %d\n", acp->bcount); 5326942c5e3cSpl196000 bioerr = EINVAL; 5327942c5e3cSpl196000 goto error_out; 5328942c5e3cSpl196000 } 5329942c5e3cSpl196000 5330942c5e3cSpl196000 acp->total_xfer += acp->bcount; 5331942c5e3cSpl196000 5332942c5e3cSpl196000 if (acp->pkt) { 5333942c5e3cSpl196000 /* Return remaining byte count */ 533458bc78c7SXin Chen if (acp->total_xfer <= bp->b_bcount) { 533558bc78c7SXin Chen acp->pkt->pkt_resid = bp->b_bcount - \ 533658bc78c7SXin Chen acp->total_xfer; 533758bc78c7SXin Chen } else { 533858bc78c7SXin Chen /* 533958bc78c7SXin Chen * Allocated DMA size is greater than the buf 534058bc78c7SXin Chen * size of bp. This is caused by devices like 534158bc78c7SXin Chen * tape. we have extra bytes allocated, but 534258bc78c7SXin Chen * the packet residual has to stay correct. 534358bc78c7SXin Chen */ 534458bc78c7SXin Chen acp->pkt->pkt_resid = 0; 534558bc78c7SXin Chen } 5346942c5e3cSpl196000 AACDB_PRINT_TRAN(softs, 5347942c5e3cSpl196000 "bp=0x%p, xfered=%d/%d, resid=%d", 5348942c5e3cSpl196000 (void *)bp->b_un.b_addr, (int)acp->total_xfer, 5349942c5e3cSpl196000 (int)bp->b_bcount, (int)acp->pkt->pkt_resid); 5350942c5e3cSpl196000 } 5351942c5e3cSpl196000 } 5352942c5e3cSpl196000 return (AACOK); 5353942c5e3cSpl196000 5354942c5e3cSpl196000 error_out: 5355942c5e3cSpl196000 bioerror(bp, bioerr); 5356942c5e3cSpl196000 return (AACERR); 5357942c5e3cSpl196000 } 5358942c5e3cSpl196000 5359942c5e3cSpl196000 static struct scsi_pkt * 5360942c5e3cSpl196000 aac_tran_init_pkt(struct scsi_address *ap, struct scsi_pkt *pkt, 5361942c5e3cSpl196000 struct buf *bp, int cmdlen, int statuslen, int tgtlen, int flags, 5362942c5e3cSpl196000 int (*callback)(), caddr_t arg) 5363942c5e3cSpl196000 { 5364942c5e3cSpl196000 struct aac_softstate *softs = AAC_TRAN2SOFTS(ap->a_hba_tran); 5365942c5e3cSpl196000 struct aac_cmd *acp, *new_acp; 5366942c5e3cSpl196000 5367942c5e3cSpl196000 DBCALLED(softs, 2); 5368942c5e3cSpl196000 5369942c5e3cSpl196000 /* Allocate pkt */ 5370942c5e3cSpl196000 if (pkt == NULL) { 5371942c5e3cSpl196000 int slen; 5372942c5e3cSpl196000 5373942c5e3cSpl196000 /* Force auto request sense */ 5374942c5e3cSpl196000 slen = (statuslen > softs->slen) ? statuslen : softs->slen; 5375942c5e3cSpl196000 pkt = scsi_hba_pkt_alloc(softs->devinfo_p, ap, cmdlen, 5376942c5e3cSpl196000 slen, tgtlen, sizeof (struct aac_cmd), callback, arg); 5377942c5e3cSpl196000 if (pkt == NULL) { 5378942c5e3cSpl196000 AACDB_PRINT(softs, CE_WARN, "Alloc scsi pkt failed"); 5379942c5e3cSpl196000 return (NULL); 5380942c5e3cSpl196000 } 5381942c5e3cSpl196000 acp = new_acp = PKT2AC(pkt); 5382942c5e3cSpl196000 acp->pkt = pkt; 5383942c5e3cSpl196000 acp->cmdlen = cmdlen; 5384942c5e3cSpl196000 538558bc78c7SXin Chen if (ap->a_target < AAC_MAX_LD) { 538658bc78c7SXin Chen acp->dvp = &softs->containers[ap->a_target].dev; 5387942c5e3cSpl196000 acp->aac_cmd_fib = softs->aac_cmd_fib; 5388942c5e3cSpl196000 acp->ac_comp = aac_ld_complete; 5389942c5e3cSpl196000 } else { 539058bc78c7SXin Chen _NOTE(ASSUMING_PROTECTED(softs->nondasds)) 539158bc78c7SXin Chen 539258bc78c7SXin Chen acp->dvp = &softs->nondasds[AAC_PD(ap->a_target)].dev; 539358bc78c7SXin Chen acp->aac_cmd_fib = softs->aac_cmd_fib_scsi; 539458bc78c7SXin Chen acp->ac_comp = aac_pd_complete; 539558bc78c7SXin Chen } 539658bc78c7SXin Chen } else { 5397942c5e3cSpl196000 acp = PKT2AC(pkt); 5398942c5e3cSpl196000 new_acp = NULL; 5399942c5e3cSpl196000 } 5400942c5e3cSpl196000 5401942c5e3cSpl196000 if (aac_cmd_dma_alloc(softs, acp, bp, flags, callback, arg) == AACOK) 5402942c5e3cSpl196000 return (pkt); 5403942c5e3cSpl196000 5404942c5e3cSpl196000 if (new_acp) 5405942c5e3cSpl196000 aac_tran_destroy_pkt(ap, pkt); 5406942c5e3cSpl196000 return (NULL); 5407942c5e3cSpl196000 } 5408942c5e3cSpl196000 5409942c5e3cSpl196000 /* 5410942c5e3cSpl196000 * tran_sync_pkt(9E) - explicit DMA synchronization 5411942c5e3cSpl196000 */ 5412942c5e3cSpl196000 /*ARGSUSED*/ 5413942c5e3cSpl196000 static void 5414942c5e3cSpl196000 aac_tran_sync_pkt(struct scsi_address *ap, struct scsi_pkt *pkt) 5415942c5e3cSpl196000 { 5416942c5e3cSpl196000 struct aac_cmd *acp = PKT2AC(pkt); 5417942c5e3cSpl196000 5418942c5e3cSpl196000 DBCALLED(NULL, 2); 5419942c5e3cSpl196000 5420942c5e3cSpl196000 if (aac_dma_sync_ac(acp) != AACOK) 5421942c5e3cSpl196000 ddi_fm_service_impact( 5422942c5e3cSpl196000 (AAC_TRAN2SOFTS(ap->a_hba_tran))->devinfo_p, 5423942c5e3cSpl196000 DDI_SERVICE_UNAFFECTED); 5424942c5e3cSpl196000 } 5425942c5e3cSpl196000 5426942c5e3cSpl196000 /* 5427942c5e3cSpl196000 * tran_dmafree(9E) - deallocate DMA resources allocated for command 5428942c5e3cSpl196000 */ 5429942c5e3cSpl196000 /*ARGSUSED*/ 5430942c5e3cSpl196000 static void 5431942c5e3cSpl196000 aac_tran_dmafree(struct scsi_address *ap, struct scsi_pkt *pkt) 5432942c5e3cSpl196000 { 5433942c5e3cSpl196000 struct aac_cmd *acp = PKT2AC(pkt); 5434942c5e3cSpl196000 5435942c5e3cSpl196000 DBCALLED(NULL, 2); 5436942c5e3cSpl196000 5437942c5e3cSpl196000 aac_free_dmamap(acp); 5438942c5e3cSpl196000 } 5439942c5e3cSpl196000 5440942c5e3cSpl196000 static int 5441942c5e3cSpl196000 aac_do_quiesce(struct aac_softstate *softs) 5442942c5e3cSpl196000 { 5443942c5e3cSpl196000 aac_hold_bus(softs, AAC_IOCMD_ASYNC); 5444942c5e3cSpl196000 if (softs->bus_ncmds[AAC_CMDQ_ASYNC]) { 5445942c5e3cSpl196000 aac_start_drain(softs); 5446942c5e3cSpl196000 do { 5447942c5e3cSpl196000 if (cv_wait_sig(&softs->drain_cv, 5448942c5e3cSpl196000 &softs->io_lock) == 0) { 5449942c5e3cSpl196000 /* Quiesce has been interrupted */ 5450942c5e3cSpl196000 aac_stop_drain(softs); 5451942c5e3cSpl196000 aac_unhold_bus(softs, AAC_IOCMD_ASYNC); 5452942c5e3cSpl196000 aac_start_waiting_io(softs); 5453942c5e3cSpl196000 return (AACERR); 5454942c5e3cSpl196000 } 5455942c5e3cSpl196000 } while (softs->bus_ncmds[AAC_CMDQ_ASYNC]); 5456942c5e3cSpl196000 aac_stop_drain(softs); 5457942c5e3cSpl196000 } 5458942c5e3cSpl196000 5459942c5e3cSpl196000 softs->state |= AAC_STATE_QUIESCED; 5460942c5e3cSpl196000 return (AACOK); 5461942c5e3cSpl196000 } 5462942c5e3cSpl196000 5463942c5e3cSpl196000 static int 5464942c5e3cSpl196000 aac_tran_quiesce(dev_info_t *dip) 5465942c5e3cSpl196000 { 5466942c5e3cSpl196000 struct aac_softstate *softs = AAC_DIP2SOFTS(dip); 5467942c5e3cSpl196000 int rval; 5468942c5e3cSpl196000 5469942c5e3cSpl196000 DBCALLED(softs, 1); 5470942c5e3cSpl196000 5471942c5e3cSpl196000 mutex_enter(&softs->io_lock); 5472942c5e3cSpl196000 if (aac_do_quiesce(softs) == AACOK) 5473942c5e3cSpl196000 rval = 0; 5474942c5e3cSpl196000 else 5475942c5e3cSpl196000 rval = 1; 5476942c5e3cSpl196000 mutex_exit(&softs->io_lock); 5477942c5e3cSpl196000 return (rval); 5478942c5e3cSpl196000 } 5479942c5e3cSpl196000 5480942c5e3cSpl196000 static int 5481942c5e3cSpl196000 aac_do_unquiesce(struct aac_softstate *softs) 5482942c5e3cSpl196000 { 5483942c5e3cSpl196000 softs->state &= ~AAC_STATE_QUIESCED; 5484942c5e3cSpl196000 aac_unhold_bus(softs, AAC_IOCMD_ASYNC); 5485942c5e3cSpl196000 5486942c5e3cSpl196000 aac_start_waiting_io(softs); 5487942c5e3cSpl196000 return (AACOK); 5488942c5e3cSpl196000 } 5489942c5e3cSpl196000 5490942c5e3cSpl196000 static int 5491942c5e3cSpl196000 aac_tran_unquiesce(dev_info_t *dip) 5492942c5e3cSpl196000 { 5493942c5e3cSpl196000 struct aac_softstate *softs = AAC_DIP2SOFTS(dip); 5494942c5e3cSpl196000 int rval; 5495942c5e3cSpl196000 5496942c5e3cSpl196000 DBCALLED(softs, 1); 5497942c5e3cSpl196000 5498942c5e3cSpl196000 mutex_enter(&softs->io_lock); 5499942c5e3cSpl196000 if (aac_do_unquiesce(softs) == AACOK) 5500942c5e3cSpl196000 rval = 0; 5501942c5e3cSpl196000 else 5502942c5e3cSpl196000 rval = 1; 5503942c5e3cSpl196000 mutex_exit(&softs->io_lock); 5504942c5e3cSpl196000 return (rval); 5505942c5e3cSpl196000 } 5506942c5e3cSpl196000 5507942c5e3cSpl196000 static int 5508942c5e3cSpl196000 aac_hba_setup(struct aac_softstate *softs) 5509942c5e3cSpl196000 { 5510942c5e3cSpl196000 scsi_hba_tran_t *hba_tran; 5511942c5e3cSpl196000 int rval; 5512942c5e3cSpl196000 5513942c5e3cSpl196000 hba_tran = scsi_hba_tran_alloc(softs->devinfo_p, SCSI_HBA_CANSLEEP); 5514942c5e3cSpl196000 if (hba_tran == NULL) 5515942c5e3cSpl196000 return (AACERR); 5516942c5e3cSpl196000 hba_tran->tran_hba_private = softs; 5517942c5e3cSpl196000 hba_tran->tran_tgt_init = aac_tran_tgt_init; 551858bc78c7SXin Chen hba_tran->tran_tgt_free = aac_tran_tgt_free; 5519942c5e3cSpl196000 hba_tran->tran_tgt_probe = scsi_hba_probe; 5520942c5e3cSpl196000 hba_tran->tran_start = aac_tran_start; 5521942c5e3cSpl196000 hba_tran->tran_getcap = aac_tran_getcap; 5522942c5e3cSpl196000 hba_tran->tran_setcap = aac_tran_setcap; 5523942c5e3cSpl196000 hba_tran->tran_init_pkt = aac_tran_init_pkt; 5524942c5e3cSpl196000 hba_tran->tran_destroy_pkt = aac_tran_destroy_pkt; 5525942c5e3cSpl196000 hba_tran->tran_reset = aac_tran_reset; 5526942c5e3cSpl196000 hba_tran->tran_abort = aac_tran_abort; 5527942c5e3cSpl196000 hba_tran->tran_sync_pkt = aac_tran_sync_pkt; 5528942c5e3cSpl196000 hba_tran->tran_dmafree = aac_tran_dmafree; 5529942c5e3cSpl196000 hba_tran->tran_quiesce = aac_tran_quiesce; 5530942c5e3cSpl196000 hba_tran->tran_unquiesce = aac_tran_unquiesce; 553158bc78c7SXin Chen hba_tran->tran_bus_config = aac_tran_bus_config; 5532942c5e3cSpl196000 rval = scsi_hba_attach_setup(softs->devinfo_p, &softs->buf_dma_attr, 5533942c5e3cSpl196000 hba_tran, 0); 5534942c5e3cSpl196000 if (rval != DDI_SUCCESS) { 5535942c5e3cSpl196000 scsi_hba_tran_free(hba_tran); 5536942c5e3cSpl196000 AACDB_PRINT(softs, CE_WARN, "aac_hba_setup failed"); 5537942c5e3cSpl196000 return (AACERR); 5538942c5e3cSpl196000 } 5539942c5e3cSpl196000 554058bc78c7SXin Chen softs->hba_tran = hba_tran; 5541942c5e3cSpl196000 return (AACOK); 5542942c5e3cSpl196000 } 5543942c5e3cSpl196000 5544942c5e3cSpl196000 /* 5545942c5e3cSpl196000 * FIB setup operations 5546942c5e3cSpl196000 */ 5547942c5e3cSpl196000 5548942c5e3cSpl196000 /* 5549942c5e3cSpl196000 * Init FIB header 5550942c5e3cSpl196000 */ 5551942c5e3cSpl196000 static void 5552f42c2f53Szhongyan gu - Sun Microsystems - Beijing China aac_cmd_fib_header(struct aac_softstate *softs, struct aac_cmd *acp, 5553f42c2f53Szhongyan gu - Sun Microsystems - Beijing China uint16_t cmd) 5554942c5e3cSpl196000 { 5555f42c2f53Szhongyan gu - Sun Microsystems - Beijing China struct aac_slot *slotp = acp->slotp; 5556942c5e3cSpl196000 ddi_acc_handle_t acc = slotp->fib_acc_handle; 5557942c5e3cSpl196000 struct aac_fib *fibp = slotp->fibp; 5558942c5e3cSpl196000 uint32_t xfer_state; 5559942c5e3cSpl196000 5560942c5e3cSpl196000 xfer_state = 5561942c5e3cSpl196000 AAC_FIBSTATE_HOSTOWNED | 5562942c5e3cSpl196000 AAC_FIBSTATE_INITIALISED | 5563942c5e3cSpl196000 AAC_FIBSTATE_EMPTY | 55640749e8deSXin Chen - Sun Microsystems - Beijing China AAC_FIBSTATE_FAST_RESPONSE | /* enable fast io */ 5565942c5e3cSpl196000 AAC_FIBSTATE_FROMHOST | 5566942c5e3cSpl196000 AAC_FIBSTATE_REXPECTED | 5567942c5e3cSpl196000 AAC_FIBSTATE_NORM; 5568f42c2f53Szhongyan gu - Sun Microsystems - Beijing China 55690749e8deSXin Chen - Sun Microsystems - Beijing China if (!(acp->flags & AAC_CMD_SYNC)) 55700749e8deSXin Chen - Sun Microsystems - Beijing China xfer_state |= AAC_FIBSTATE_ASYNC; 5571942c5e3cSpl196000 5572942c5e3cSpl196000 ddi_put32(acc, &fibp->Header.XferState, xfer_state); 5573942c5e3cSpl196000 ddi_put16(acc, &fibp->Header.Command, cmd); 5574942c5e3cSpl196000 ddi_put8(acc, &fibp->Header.StructType, AAC_FIBTYPE_TFIB); 5575942c5e3cSpl196000 ddi_put8(acc, &fibp->Header.Flags, 0); /* don't care */ 5576f42c2f53Szhongyan gu - Sun Microsystems - Beijing China ddi_put16(acc, &fibp->Header.Size, acp->fib_size); 5577f42c2f53Szhongyan gu - Sun Microsystems - Beijing China ddi_put16(acc, &fibp->Header.SenderSize, softs->aac_max_fib_size); 5578942c5e3cSpl196000 ddi_put32(acc, &fibp->Header.SenderFibAddress, (slotp->index << 2)); 5579942c5e3cSpl196000 ddi_put32(acc, &fibp->Header.ReceiverFibAddress, slotp->fib_phyaddr); 5580942c5e3cSpl196000 ddi_put32(acc, &fibp->Header.SenderData, 0); /* don't care */ 5581942c5e3cSpl196000 } 5582942c5e3cSpl196000 5583942c5e3cSpl196000 /* 5584942c5e3cSpl196000 * Init FIB for raw IO command 5585942c5e3cSpl196000 */ 5586942c5e3cSpl196000 static void 5587942c5e3cSpl196000 aac_cmd_fib_rawio(struct aac_softstate *softs, struct aac_cmd *acp) 5588942c5e3cSpl196000 { 5589942c5e3cSpl196000 ddi_acc_handle_t acc = acp->slotp->fib_acc_handle; 5590942c5e3cSpl196000 struct aac_raw_io *io = (struct aac_raw_io *)&acp->slotp->fibp->data[0]; 5591942c5e3cSpl196000 struct aac_sg_entryraw *sgp; 5592942c5e3cSpl196000 struct aac_sge *sge; 5593942c5e3cSpl196000 5594942c5e3cSpl196000 /* Calculate FIB size */ 5595942c5e3cSpl196000 acp->fib_size = sizeof (struct aac_fib_header) + \ 5596942c5e3cSpl196000 sizeof (struct aac_raw_io) + (acp->left_cookien - 1) * \ 5597942c5e3cSpl196000 sizeof (struct aac_sg_entryraw); 5598942c5e3cSpl196000 5599f42c2f53Szhongyan gu - Sun Microsystems - Beijing China aac_cmd_fib_header(softs, acp, RawIo); 5600942c5e3cSpl196000 5601942c5e3cSpl196000 ddi_put16(acc, &io->Flags, (acp->flags & AAC_CMD_BUF_READ) ? 1 : 0); 5602942c5e3cSpl196000 ddi_put16(acc, &io->BpTotal, 0); 5603942c5e3cSpl196000 ddi_put16(acc, &io->BpComplete, 0); 5604942c5e3cSpl196000 5605942c5e3cSpl196000 ddi_put32(acc, AAC_LO32(&io->BlockNumber), AAC_LS32(acp->blkno)); 5606942c5e3cSpl196000 ddi_put32(acc, AAC_HI32(&io->BlockNumber), AAC_MS32(acp->blkno)); 5607942c5e3cSpl196000 ddi_put16(acc, &io->ContainerId, 5608942c5e3cSpl196000 ((struct aac_container *)acp->dvp)->cid); 5609942c5e3cSpl196000 5610942c5e3cSpl196000 /* Fill SG table */ 5611942c5e3cSpl196000 ddi_put32(acc, &io->SgMapRaw.SgCount, acp->left_cookien); 5612942c5e3cSpl196000 ddi_put32(acc, &io->ByteCount, acp->bcount); 5613942c5e3cSpl196000 5614942c5e3cSpl196000 for (sge = &acp->sgt[0], sgp = &io->SgMapRaw.SgEntryRaw[0]; 5615942c5e3cSpl196000 sge < &acp->sgt[acp->left_cookien]; sge++, sgp++) { 5616942c5e3cSpl196000 ddi_put32(acc, AAC_LO32(&sgp->SgAddress), sge->addr.ad64.lo); 5617942c5e3cSpl196000 ddi_put32(acc, AAC_HI32(&sgp->SgAddress), sge->addr.ad64.hi); 5618942c5e3cSpl196000 ddi_put32(acc, &sgp->SgByteCount, sge->bcount); 5619942c5e3cSpl196000 sgp->Next = 0; 5620942c5e3cSpl196000 sgp->Prev = 0; 5621942c5e3cSpl196000 sgp->Flags = 0; 5622942c5e3cSpl196000 } 5623942c5e3cSpl196000 } 5624942c5e3cSpl196000 5625942c5e3cSpl196000 /* Init FIB for 64-bit block IO command */ 5626942c5e3cSpl196000 static void 5627942c5e3cSpl196000 aac_cmd_fib_brw64(struct aac_softstate *softs, struct aac_cmd *acp) 5628942c5e3cSpl196000 { 5629942c5e3cSpl196000 ddi_acc_handle_t acc = acp->slotp->fib_acc_handle; 5630942c5e3cSpl196000 struct aac_blockread64 *br = (struct aac_blockread64 *) \ 5631942c5e3cSpl196000 &acp->slotp->fibp->data[0]; 5632942c5e3cSpl196000 struct aac_sg_entry64 *sgp; 5633942c5e3cSpl196000 struct aac_sge *sge; 5634942c5e3cSpl196000 5635942c5e3cSpl196000 acp->fib_size = sizeof (struct aac_fib_header) + \ 5636942c5e3cSpl196000 sizeof (struct aac_blockread64) + (acp->left_cookien - 1) * \ 5637942c5e3cSpl196000 sizeof (struct aac_sg_entry64); 5638942c5e3cSpl196000 5639f42c2f53Szhongyan gu - Sun Microsystems - Beijing China aac_cmd_fib_header(softs, acp, ContainerCommand64); 5640942c5e3cSpl196000 5641942c5e3cSpl196000 /* 5642942c5e3cSpl196000 * The definitions for aac_blockread64 and aac_blockwrite64 5643942c5e3cSpl196000 * are the same. 5644942c5e3cSpl196000 */ 5645942c5e3cSpl196000 ddi_put32(acc, &br->BlockNumber, (uint32_t)acp->blkno); 5646942c5e3cSpl196000 ddi_put16(acc, &br->ContainerId, 5647942c5e3cSpl196000 ((struct aac_container *)acp->dvp)->cid); 5648942c5e3cSpl196000 ddi_put32(acc, &br->Command, (acp->flags & AAC_CMD_BUF_READ) ? 5649942c5e3cSpl196000 VM_CtHostRead64 : VM_CtHostWrite64); 5650942c5e3cSpl196000 ddi_put16(acc, &br->Pad, 0); 5651942c5e3cSpl196000 ddi_put16(acc, &br->Flags, 0); 5652942c5e3cSpl196000 5653942c5e3cSpl196000 /* Fill SG table */ 5654942c5e3cSpl196000 ddi_put32(acc, &br->SgMap64.SgCount, acp->left_cookien); 5655942c5e3cSpl196000 ddi_put16(acc, &br->SectorCount, acp->bcount / AAC_BLK_SIZE); 5656942c5e3cSpl196000 5657942c5e3cSpl196000 for (sge = &acp->sgt[0], sgp = &br->SgMap64.SgEntry64[0]; 5658942c5e3cSpl196000 sge < &acp->sgt[acp->left_cookien]; sge++, sgp++) { 5659942c5e3cSpl196000 ddi_put32(acc, AAC_LO32(&sgp->SgAddress), sge->addr.ad64.lo); 5660942c5e3cSpl196000 ddi_put32(acc, AAC_HI32(&sgp->SgAddress), sge->addr.ad64.hi); 5661942c5e3cSpl196000 ddi_put32(acc, &sgp->SgByteCount, sge->bcount); 5662942c5e3cSpl196000 } 5663942c5e3cSpl196000 } 5664942c5e3cSpl196000 5665942c5e3cSpl196000 /* Init FIB for block IO command */ 5666942c5e3cSpl196000 static void 5667942c5e3cSpl196000 aac_cmd_fib_brw(struct aac_softstate *softs, struct aac_cmd *acp) 5668942c5e3cSpl196000 { 5669942c5e3cSpl196000 ddi_acc_handle_t acc = acp->slotp->fib_acc_handle; 5670942c5e3cSpl196000 struct aac_blockread *br = (struct aac_blockread *) \ 5671942c5e3cSpl196000 &acp->slotp->fibp->data[0]; 5672942c5e3cSpl196000 struct aac_sg_entry *sgp; 5673942c5e3cSpl196000 struct aac_sge *sge = &acp->sgt[0]; 5674942c5e3cSpl196000 5675942c5e3cSpl196000 if (acp->flags & AAC_CMD_BUF_READ) { 5676942c5e3cSpl196000 acp->fib_size = sizeof (struct aac_fib_header) + \ 5677942c5e3cSpl196000 sizeof (struct aac_blockread) + (acp->left_cookien - 1) * \ 5678942c5e3cSpl196000 sizeof (struct aac_sg_entry); 5679942c5e3cSpl196000 5680942c5e3cSpl196000 ddi_put32(acc, &br->Command, VM_CtBlockRead); 5681942c5e3cSpl196000 ddi_put32(acc, &br->SgMap.SgCount, acp->left_cookien); 5682942c5e3cSpl196000 sgp = &br->SgMap.SgEntry[0]; 5683942c5e3cSpl196000 } else { 5684942c5e3cSpl196000 struct aac_blockwrite *bw = (struct aac_blockwrite *)br; 5685942c5e3cSpl196000 5686942c5e3cSpl196000 acp->fib_size = sizeof (struct aac_fib_header) + \ 5687942c5e3cSpl196000 sizeof (struct aac_blockwrite) + (acp->left_cookien - 1) * \ 5688942c5e3cSpl196000 sizeof (struct aac_sg_entry); 5689942c5e3cSpl196000 5690942c5e3cSpl196000 ddi_put32(acc, &bw->Command, VM_CtBlockWrite); 5691942c5e3cSpl196000 ddi_put32(acc, &bw->Stable, CUNSTABLE); 5692942c5e3cSpl196000 ddi_put32(acc, &bw->SgMap.SgCount, acp->left_cookien); 5693942c5e3cSpl196000 sgp = &bw->SgMap.SgEntry[0]; 5694942c5e3cSpl196000 } 5695f42c2f53Szhongyan gu - Sun Microsystems - Beijing China aac_cmd_fib_header(softs, acp, ContainerCommand); 5696942c5e3cSpl196000 5697942c5e3cSpl196000 /* 5698942c5e3cSpl196000 * aac_blockread and aac_blockwrite have the similar 5699942c5e3cSpl196000 * structure head, so use br for bw here 5700942c5e3cSpl196000 */ 5701942c5e3cSpl196000 ddi_put32(acc, &br->BlockNumber, (uint32_t)acp->blkno); 5702942c5e3cSpl196000 ddi_put32(acc, &br->ContainerId, 5703942c5e3cSpl196000 ((struct aac_container *)acp->dvp)->cid); 5704942c5e3cSpl196000 ddi_put32(acc, &br->ByteCount, acp->bcount); 5705942c5e3cSpl196000 5706942c5e3cSpl196000 /* Fill SG table */ 5707942c5e3cSpl196000 for (sge = &acp->sgt[0]; 5708942c5e3cSpl196000 sge < &acp->sgt[acp->left_cookien]; sge++, sgp++) { 5709942c5e3cSpl196000 ddi_put32(acc, &sgp->SgAddress, sge->addr.ad32); 5710942c5e3cSpl196000 ddi_put32(acc, &sgp->SgByteCount, sge->bcount); 5711942c5e3cSpl196000 } 5712942c5e3cSpl196000 } 5713942c5e3cSpl196000 5714942c5e3cSpl196000 /*ARGSUSED*/ 5715942c5e3cSpl196000 void 5716942c5e3cSpl196000 aac_cmd_fib_copy(struct aac_softstate *softs, struct aac_cmd *acp) 5717942c5e3cSpl196000 { 5718942c5e3cSpl196000 struct aac_slot *slotp = acp->slotp; 5719942c5e3cSpl196000 struct aac_fib *fibp = slotp->fibp; 5720942c5e3cSpl196000 ddi_acc_handle_t acc = slotp->fib_acc_handle; 5721942c5e3cSpl196000 5722942c5e3cSpl196000 ddi_rep_put8(acc, (uint8_t *)acp->fibp, (uint8_t *)fibp, 5723942c5e3cSpl196000 acp->fib_size, /* only copy data of needed length */ 5724942c5e3cSpl196000 DDI_DEV_AUTOINCR); 5725942c5e3cSpl196000 ddi_put32(acc, &fibp->Header.ReceiverFibAddress, slotp->fib_phyaddr); 5726942c5e3cSpl196000 ddi_put32(acc, &fibp->Header.SenderFibAddress, slotp->index << 2); 5727942c5e3cSpl196000 } 5728942c5e3cSpl196000 5729942c5e3cSpl196000 static void 5730942c5e3cSpl196000 aac_cmd_fib_sync(struct aac_softstate *softs, struct aac_cmd *acp) 5731942c5e3cSpl196000 { 5732f42c2f53Szhongyan gu - Sun Microsystems - Beijing China ddi_acc_handle_t acc = acp->slotp->fib_acc_handle; 5733942c5e3cSpl196000 struct aac_synchronize_command *sync = 5734f42c2f53Szhongyan gu - Sun Microsystems - Beijing China (struct aac_synchronize_command *)&acp->slotp->fibp->data[0]; 5735942c5e3cSpl196000 5736f42c2f53Szhongyan gu - Sun Microsystems - Beijing China acp->fib_size = AAC_FIB_SIZEOF(struct aac_synchronize_command); 5737942c5e3cSpl196000 5738f42c2f53Szhongyan gu - Sun Microsystems - Beijing China aac_cmd_fib_header(softs, acp, ContainerCommand); 5739942c5e3cSpl196000 ddi_put32(acc, &sync->Command, VM_ContainerConfig); 5740942c5e3cSpl196000 ddi_put32(acc, &sync->Type, (uint32_t)CT_FLUSH_CACHE); 5741942c5e3cSpl196000 ddi_put32(acc, &sync->Cid, ((struct aac_container *)acp->dvp)->cid); 5742942c5e3cSpl196000 ddi_put32(acc, &sync->Count, 5743942c5e3cSpl196000 sizeof (((struct aac_synchronize_reply *)0)->Data)); 5744942c5e3cSpl196000 } 5745942c5e3cSpl196000 5746942c5e3cSpl196000 /* 5747b40e8a89Szhongyan gu - Sun Microsystems - Beijing China * Start/Stop unit (Power Management) 5748b40e8a89Szhongyan gu - Sun Microsystems - Beijing China */ 5749b40e8a89Szhongyan gu - Sun Microsystems - Beijing China static void 5750b40e8a89Szhongyan gu - Sun Microsystems - Beijing China aac_cmd_fib_startstop(struct aac_softstate *softs, struct aac_cmd *acp) 5751b40e8a89Szhongyan gu - Sun Microsystems - Beijing China { 5752f42c2f53Szhongyan gu - Sun Microsystems - Beijing China ddi_acc_handle_t acc = acp->slotp->fib_acc_handle; 5753b40e8a89Szhongyan gu - Sun Microsystems - Beijing China struct aac_Container *cmd = 5754f42c2f53Szhongyan gu - Sun Microsystems - Beijing China (struct aac_Container *)&acp->slotp->fibp->data[0]; 5755b40e8a89Szhongyan gu - Sun Microsystems - Beijing China union scsi_cdb *cdbp = (void *)acp->pkt->pkt_cdbp; 5756b40e8a89Szhongyan gu - Sun Microsystems - Beijing China 5757b40e8a89Szhongyan gu - Sun Microsystems - Beijing China acp->fib_size = AAC_FIB_SIZEOF(struct aac_Container); 5758b40e8a89Szhongyan gu - Sun Microsystems - Beijing China 5759f42c2f53Szhongyan gu - Sun Microsystems - Beijing China aac_cmd_fib_header(softs, acp, ContainerCommand); 5760b40e8a89Szhongyan gu - Sun Microsystems - Beijing China bzero(cmd, sizeof (*cmd) - CT_PACKET_SIZE); 5761b40e8a89Szhongyan gu - Sun Microsystems - Beijing China ddi_put32(acc, &cmd->Command, VM_ContainerConfig); 5762b40e8a89Szhongyan gu - Sun Microsystems - Beijing China ddi_put32(acc, &cmd->CTCommand.command, CT_PM_DRIVER_SUPPORT); 5763b40e8a89Szhongyan gu - Sun Microsystems - Beijing China ddi_put32(acc, &cmd->CTCommand.param[0], cdbp->cdb_opaque[4] & 1 ? \ 5764b40e8a89Szhongyan gu - Sun Microsystems - Beijing China AAC_PM_DRIVERSUP_START_UNIT : AAC_PM_DRIVERSUP_STOP_UNIT); 5765b40e8a89Szhongyan gu - Sun Microsystems - Beijing China ddi_put32(acc, &cmd->CTCommand.param[1], 5766b40e8a89Szhongyan gu - Sun Microsystems - Beijing China ((struct aac_container *)acp->dvp)->cid); 5767b40e8a89Szhongyan gu - Sun Microsystems - Beijing China ddi_put32(acc, &cmd->CTCommand.param[2], cdbp->cdb_opaque[1] & 1); 5768b40e8a89Szhongyan gu - Sun Microsystems - Beijing China } 5769b40e8a89Szhongyan gu - Sun Microsystems - Beijing China 5770b40e8a89Szhongyan gu - Sun Microsystems - Beijing China /* 5771942c5e3cSpl196000 * Init FIB for pass-through SCMD 5772942c5e3cSpl196000 */ 5773942c5e3cSpl196000 static void 5774942c5e3cSpl196000 aac_cmd_fib_srb(struct aac_cmd *acp) 5775942c5e3cSpl196000 { 5776f42c2f53Szhongyan gu - Sun Microsystems - Beijing China ddi_acc_handle_t acc = acp->slotp->fib_acc_handle; 5777f42c2f53Szhongyan gu - Sun Microsystems - Beijing China struct aac_srb *srb = (struct aac_srb *)&acp->slotp->fibp->data[0]; 577858bc78c7SXin Chen uint8_t *cdb; 5779942c5e3cSpl196000 5780942c5e3cSpl196000 ddi_put32(acc, &srb->function, SRBF_ExecuteScsi); 5781942c5e3cSpl196000 ddi_put32(acc, &srb->retry_limit, 0); 5782942c5e3cSpl196000 ddi_put32(acc, &srb->cdb_size, acp->cmdlen); 5783942c5e3cSpl196000 ddi_put32(acc, &srb->timeout, 0); /* use driver timeout */ 578458bc78c7SXin Chen if (acp->fibp == NULL) { 578558bc78c7SXin Chen if (acp->flags & AAC_CMD_BUF_READ) 578658bc78c7SXin Chen ddi_put32(acc, &srb->flags, SRB_DataIn); 578758bc78c7SXin Chen else if (acp->flags & AAC_CMD_BUF_WRITE) 578858bc78c7SXin Chen ddi_put32(acc, &srb->flags, SRB_DataOut); 578958bc78c7SXin Chen ddi_put32(acc, &srb->channel, 579058bc78c7SXin Chen ((struct aac_nondasd *)acp->dvp)->bus); 579158bc78c7SXin Chen ddi_put32(acc, &srb->id, ((struct aac_nondasd *)acp->dvp)->tid); 579258bc78c7SXin Chen ddi_put32(acc, &srb->lun, 0); 579358bc78c7SXin Chen cdb = acp->pkt->pkt_cdbp; 579458bc78c7SXin Chen } else { 579558bc78c7SXin Chen struct aac_srb *srb0 = (struct aac_srb *)&acp->fibp->data[0]; 5796942c5e3cSpl196000 5797942c5e3cSpl196000 ddi_put32(acc, &srb->flags, srb0->flags); 5798942c5e3cSpl196000 ddi_put32(acc, &srb->channel, srb0->channel); 5799942c5e3cSpl196000 ddi_put32(acc, &srb->id, srb0->id); 5800942c5e3cSpl196000 ddi_put32(acc, &srb->lun, srb0->lun); 580158bc78c7SXin Chen cdb = srb0->cdb; 580258bc78c7SXin Chen } 580358bc78c7SXin Chen ddi_rep_put8(acc, cdb, srb->cdb, acp->cmdlen, DDI_DEV_AUTOINCR); 5804942c5e3cSpl196000 } 5805942c5e3cSpl196000 5806942c5e3cSpl196000 static void 5807942c5e3cSpl196000 aac_cmd_fib_scsi32(struct aac_softstate *softs, struct aac_cmd *acp) 5808942c5e3cSpl196000 { 5809942c5e3cSpl196000 ddi_acc_handle_t acc = acp->slotp->fib_acc_handle; 5810942c5e3cSpl196000 struct aac_srb *srb = (struct aac_srb *)&acp->slotp->fibp->data[0]; 5811942c5e3cSpl196000 struct aac_sg_entry *sgp; 5812942c5e3cSpl196000 struct aac_sge *sge; 5813942c5e3cSpl196000 5814942c5e3cSpl196000 acp->fib_size = sizeof (struct aac_fib_header) + \ 5815942c5e3cSpl196000 sizeof (struct aac_srb) - sizeof (struct aac_sg_entry) + \ 5816942c5e3cSpl196000 acp->left_cookien * sizeof (struct aac_sg_entry); 5817942c5e3cSpl196000 5818942c5e3cSpl196000 /* Fill FIB and SRB headers, and copy cdb */ 5819f42c2f53Szhongyan gu - Sun Microsystems - Beijing China aac_cmd_fib_header(softs, acp, ScsiPortCommand); 5820942c5e3cSpl196000 aac_cmd_fib_srb(acp); 5821942c5e3cSpl196000 5822942c5e3cSpl196000 /* Fill SG table */ 5823942c5e3cSpl196000 ddi_put32(acc, &srb->sg.SgCount, acp->left_cookien); 5824942c5e3cSpl196000 ddi_put32(acc, &srb->count, acp->bcount); 5825942c5e3cSpl196000 5826942c5e3cSpl196000 for (sge = &acp->sgt[0], sgp = &srb->sg.SgEntry[0]; 5827942c5e3cSpl196000 sge < &acp->sgt[acp->left_cookien]; sge++, sgp++) { 5828942c5e3cSpl196000 ddi_put32(acc, &sgp->SgAddress, sge->addr.ad32); 5829942c5e3cSpl196000 ddi_put32(acc, &sgp->SgByteCount, sge->bcount); 5830942c5e3cSpl196000 } 5831942c5e3cSpl196000 } 5832942c5e3cSpl196000 5833942c5e3cSpl196000 static void 5834942c5e3cSpl196000 aac_cmd_fib_scsi64(struct aac_softstate *softs, struct aac_cmd *acp) 5835942c5e3cSpl196000 { 5836942c5e3cSpl196000 ddi_acc_handle_t acc = acp->slotp->fib_acc_handle; 5837942c5e3cSpl196000 struct aac_srb *srb = (struct aac_srb *)&acp->slotp->fibp->data[0]; 5838942c5e3cSpl196000 struct aac_sg_entry64 *sgp; 5839942c5e3cSpl196000 struct aac_sge *sge; 5840942c5e3cSpl196000 5841942c5e3cSpl196000 acp->fib_size = sizeof (struct aac_fib_header) + \ 5842942c5e3cSpl196000 sizeof (struct aac_srb) - sizeof (struct aac_sg_entry) + \ 5843942c5e3cSpl196000 acp->left_cookien * sizeof (struct aac_sg_entry64); 5844942c5e3cSpl196000 5845942c5e3cSpl196000 /* Fill FIB and SRB headers, and copy cdb */ 5846f42c2f53Szhongyan gu - Sun Microsystems - Beijing China aac_cmd_fib_header(softs, acp, ScsiPortCommandU64); 5847942c5e3cSpl196000 aac_cmd_fib_srb(acp); 5848942c5e3cSpl196000 5849942c5e3cSpl196000 /* Fill SG table */ 5850942c5e3cSpl196000 ddi_put32(acc, &srb->sg.SgCount, acp->left_cookien); 5851942c5e3cSpl196000 ddi_put32(acc, &srb->count, acp->bcount); 5852942c5e3cSpl196000 5853942c5e3cSpl196000 for (sge = &acp->sgt[0], 5854942c5e3cSpl196000 sgp = &((struct aac_sg_table64 *)&srb->sg)->SgEntry64[0]; 5855942c5e3cSpl196000 sge < &acp->sgt[acp->left_cookien]; sge++, sgp++) { 5856942c5e3cSpl196000 ddi_put32(acc, AAC_LO32(&sgp->SgAddress), sge->addr.ad64.lo); 5857942c5e3cSpl196000 ddi_put32(acc, AAC_HI32(&sgp->SgAddress), sge->addr.ad64.hi); 5858942c5e3cSpl196000 ddi_put32(acc, &sgp->SgByteCount, sge->bcount); 5859942c5e3cSpl196000 } 5860942c5e3cSpl196000 } 5861942c5e3cSpl196000 5862942c5e3cSpl196000 static int 5863942c5e3cSpl196000 aac_cmd_slot_bind(struct aac_softstate *softs, struct aac_cmd *acp) 5864942c5e3cSpl196000 { 5865942c5e3cSpl196000 struct aac_slot *slotp; 5866942c5e3cSpl196000 5867942c5e3cSpl196000 if (slotp = aac_get_slot(softs)) { 5868942c5e3cSpl196000 acp->slotp = slotp; 5869942c5e3cSpl196000 slotp->acp = acp; 5870942c5e3cSpl196000 acp->aac_cmd_fib(softs, acp); 5871942c5e3cSpl196000 (void) ddi_dma_sync(slotp->fib_dma_handle, 0, 0, 5872942c5e3cSpl196000 DDI_DMA_SYNC_FORDEV); 5873942c5e3cSpl196000 return (AACOK); 5874942c5e3cSpl196000 } 5875942c5e3cSpl196000 return (AACERR); 5876942c5e3cSpl196000 } 5877942c5e3cSpl196000 5878942c5e3cSpl196000 static int 5879942c5e3cSpl196000 aac_bind_io(struct aac_softstate *softs, struct aac_cmd *acp) 5880942c5e3cSpl196000 { 588158bc78c7SXin Chen struct aac_device *dvp = acp->dvp; 5882942c5e3cSpl196000 int q = AAC_CMDQ(acp); 5883942c5e3cSpl196000 58841ee13a44SXinChen if (softs->bus_ncmds[q] < softs->bus_throttle[q]) { 5885942c5e3cSpl196000 if (dvp) { 5886942c5e3cSpl196000 if (dvp->ncmds[q] < dvp->throttle[q]) { 5887942c5e3cSpl196000 if (!(acp->flags & AAC_CMD_NTAG) || 5888942c5e3cSpl196000 dvp->ncmds[q] == 0) { 5889942c5e3cSpl196000 return (aac_cmd_slot_bind(softs, acp)); 5890942c5e3cSpl196000 } 5891942c5e3cSpl196000 ASSERT(q == AAC_CMDQ_ASYNC); 5892942c5e3cSpl196000 aac_set_throttle(softs, dvp, AAC_CMDQ_ASYNC, 5893942c5e3cSpl196000 AAC_THROTTLE_DRAIN); 5894942c5e3cSpl196000 } 5895942c5e3cSpl196000 } else { 58961ee13a44SXinChen return (aac_cmd_slot_bind(softs, acp)); 58971ee13a44SXinChen } 5898942c5e3cSpl196000 } 5899942c5e3cSpl196000 return (AACERR); 5900942c5e3cSpl196000 } 5901942c5e3cSpl196000 5902f42c2f53Szhongyan gu - Sun Microsystems - Beijing China static int 5903f42c2f53Szhongyan gu - Sun Microsystems - Beijing China aac_sync_fib_slot_bind(struct aac_softstate *softs, struct aac_cmd *acp) 5904f42c2f53Szhongyan gu - Sun Microsystems - Beijing China { 5905f42c2f53Szhongyan gu - Sun Microsystems - Beijing China struct aac_slot *slotp; 5906f42c2f53Szhongyan gu - Sun Microsystems - Beijing China 59071ee13a44SXinChen while (softs->sync_ac.slotp) 59081ee13a44SXinChen cv_wait(&softs->sync_fib_cv, &softs->io_lock); 59091ee13a44SXinChen 5910f42c2f53Szhongyan gu - Sun Microsystems - Beijing China if (slotp = aac_get_slot(softs)) { 5911f42c2f53Szhongyan gu - Sun Microsystems - Beijing China ASSERT(acp->slotp == NULL); 5912f42c2f53Szhongyan gu - Sun Microsystems - Beijing China 5913f42c2f53Szhongyan gu - Sun Microsystems - Beijing China acp->slotp = slotp; 5914f42c2f53Szhongyan gu - Sun Microsystems - Beijing China slotp->acp = acp; 5915f42c2f53Szhongyan gu - Sun Microsystems - Beijing China return (AACOK); 5916f42c2f53Szhongyan gu - Sun Microsystems - Beijing China } 5917f42c2f53Szhongyan gu - Sun Microsystems - Beijing China return (AACERR); 5918f42c2f53Szhongyan gu - Sun Microsystems - Beijing China } 5919f42c2f53Szhongyan gu - Sun Microsystems - Beijing China 5920f42c2f53Szhongyan gu - Sun Microsystems - Beijing China static void 5921f42c2f53Szhongyan gu - Sun Microsystems - Beijing China aac_sync_fib_slot_release(struct aac_softstate *softs, struct aac_cmd *acp) 5922f42c2f53Szhongyan gu - Sun Microsystems - Beijing China { 5923f42c2f53Szhongyan gu - Sun Microsystems - Beijing China ASSERT(acp->slotp); 5924f42c2f53Szhongyan gu - Sun Microsystems - Beijing China 5925f42c2f53Szhongyan gu - Sun Microsystems - Beijing China aac_release_slot(softs, acp->slotp); 5926f42c2f53Szhongyan gu - Sun Microsystems - Beijing China acp->slotp->acp = NULL; 5927f42c2f53Szhongyan gu - Sun Microsystems - Beijing China acp->slotp = NULL; 59281ee13a44SXinChen 59291ee13a44SXinChen cv_signal(&softs->sync_fib_cv); 5930f42c2f53Szhongyan gu - Sun Microsystems - Beijing China } 5931f42c2f53Szhongyan gu - Sun Microsystems - Beijing China 5932942c5e3cSpl196000 static void 5933942c5e3cSpl196000 aac_start_io(struct aac_softstate *softs, struct aac_cmd *acp) 5934942c5e3cSpl196000 { 5935942c5e3cSpl196000 struct aac_slot *slotp = acp->slotp; 5936942c5e3cSpl196000 int q = AAC_CMDQ(acp); 5937942c5e3cSpl196000 int rval; 5938942c5e3cSpl196000 5939942c5e3cSpl196000 /* Set ac and pkt */ 5940942c5e3cSpl196000 if (acp->pkt) { /* ac from ioctl has no pkt */ 5941942c5e3cSpl196000 acp->pkt->pkt_state |= 5942942c5e3cSpl196000 STATE_GOT_BUS | STATE_GOT_TARGET | STATE_SENT_CMD; 5943942c5e3cSpl196000 } 5944942c5e3cSpl196000 if (acp->timeout) /* 0 indicates no timeout */ 5945942c5e3cSpl196000 acp->timeout += aac_timebase + aac_tick; 5946942c5e3cSpl196000 5947942c5e3cSpl196000 if (acp->dvp) 5948942c5e3cSpl196000 acp->dvp->ncmds[q]++; 5949942c5e3cSpl196000 softs->bus_ncmds[q]++; 5950942c5e3cSpl196000 aac_cmd_enqueue(&softs->q_busy, acp); 5951942c5e3cSpl196000 595258bc78c7SXin Chen AACDB_PRINT_FIB(softs, slotp); 595358bc78c7SXin Chen 5954942c5e3cSpl196000 if (softs->flags & AAC_FLAGS_NEW_COMM) { 5955942c5e3cSpl196000 rval = aac_send_command(softs, slotp); 5956942c5e3cSpl196000 } else { 5957942c5e3cSpl196000 /* 5958942c5e3cSpl196000 * If fib can not be enqueued, the adapter is in an abnormal 5959942c5e3cSpl196000 * state, there will be no interrupt to us. 5960942c5e3cSpl196000 */ 5961942c5e3cSpl196000 rval = aac_fib_enqueue(softs, AAC_ADAP_NORM_CMD_Q, 5962942c5e3cSpl196000 slotp->fib_phyaddr, acp->fib_size); 5963942c5e3cSpl196000 } 5964942c5e3cSpl196000 5965942c5e3cSpl196000 if (aac_check_dma_handle(slotp->fib_dma_handle) != DDI_SUCCESS) 5966942c5e3cSpl196000 ddi_fm_service_impact(softs->devinfo_p, DDI_SERVICE_UNAFFECTED); 5967942c5e3cSpl196000 5968942c5e3cSpl196000 /* 5969942c5e3cSpl196000 * NOTE: We send command only when slots availabe, so should never 5970942c5e3cSpl196000 * reach here. 5971942c5e3cSpl196000 */ 5972942c5e3cSpl196000 if (rval != AACOK) { 5973942c5e3cSpl196000 AACDB_PRINT(softs, CE_NOTE, "SCMD send failed"); 5974942c5e3cSpl196000 if (acp->pkt) { 5975942c5e3cSpl196000 acp->pkt->pkt_state &= ~STATE_SENT_CMD; 5976942c5e3cSpl196000 aac_set_pkt_reason(softs, acp, CMD_INCOMPLETE, 0); 5977942c5e3cSpl196000 } 5978942c5e3cSpl196000 aac_end_io(softs, acp); 5979942c5e3cSpl196000 if (!(acp->flags & (AAC_CMD_NO_INTR | AAC_CMD_NO_CB))) 5980942c5e3cSpl196000 ddi_trigger_softintr(softs->softint_id); 5981942c5e3cSpl196000 } 5982942c5e3cSpl196000 } 5983942c5e3cSpl196000 5984942c5e3cSpl196000 static void 5985942c5e3cSpl196000 aac_start_waitq(struct aac_softstate *softs, struct aac_cmd_queue *q) 5986942c5e3cSpl196000 { 5987942c5e3cSpl196000 struct aac_cmd *acp, *next_acp; 5988942c5e3cSpl196000 5989942c5e3cSpl196000 /* Serve as many waiting io's as possible */ 5990942c5e3cSpl196000 for (acp = q->q_head; acp; acp = next_acp) { 5991942c5e3cSpl196000 next_acp = acp->next; 5992942c5e3cSpl196000 if (aac_bind_io(softs, acp) == AACOK) { 5993942c5e3cSpl196000 aac_cmd_delete(q, acp); 5994942c5e3cSpl196000 aac_start_io(softs, acp); 5995942c5e3cSpl196000 } 5996942c5e3cSpl196000 if (softs->free_io_slot_head == NULL) 5997942c5e3cSpl196000 break; 5998942c5e3cSpl196000 } 5999942c5e3cSpl196000 } 6000942c5e3cSpl196000 6001942c5e3cSpl196000 static void 6002942c5e3cSpl196000 aac_start_waiting_io(struct aac_softstate *softs) 6003942c5e3cSpl196000 { 6004942c5e3cSpl196000 /* 6005942c5e3cSpl196000 * Sync FIB io is served before async FIB io so that io requests 6006942c5e3cSpl196000 * sent by interactive userland commands get responded asap. 6007942c5e3cSpl196000 */ 6008942c5e3cSpl196000 if (softs->q_wait[AAC_CMDQ_SYNC].q_head) 6009942c5e3cSpl196000 aac_start_waitq(softs, &softs->q_wait[AAC_CMDQ_SYNC]); 6010942c5e3cSpl196000 if (softs->q_wait[AAC_CMDQ_ASYNC].q_head) 6011942c5e3cSpl196000 aac_start_waitq(softs, &softs->q_wait[AAC_CMDQ_ASYNC]); 6012942c5e3cSpl196000 } 6013942c5e3cSpl196000 6014942c5e3cSpl196000 static void 6015942c5e3cSpl196000 aac_drain_comp_q(struct aac_softstate *softs) 6016942c5e3cSpl196000 { 6017942c5e3cSpl196000 struct aac_cmd *acp; 6018942c5e3cSpl196000 struct scsi_pkt *pkt; 6019942c5e3cSpl196000 6020942c5e3cSpl196000 /*CONSTCOND*/ 6021942c5e3cSpl196000 while (1) { 6022942c5e3cSpl196000 mutex_enter(&softs->q_comp_mutex); 6023942c5e3cSpl196000 acp = aac_cmd_dequeue(&softs->q_comp); 6024942c5e3cSpl196000 mutex_exit(&softs->q_comp_mutex); 6025942c5e3cSpl196000 if (acp != NULL) { 6026942c5e3cSpl196000 ASSERT(acp->pkt != NULL); 6027942c5e3cSpl196000 pkt = acp->pkt; 6028942c5e3cSpl196000 6029942c5e3cSpl196000 if (pkt->pkt_reason == CMD_CMPLT) { 6030942c5e3cSpl196000 /* 6031942c5e3cSpl196000 * Consistent packets need to be sync'ed first 6032942c5e3cSpl196000 */ 6033942c5e3cSpl196000 if ((acp->flags & AAC_CMD_CONSISTENT) && 6034942c5e3cSpl196000 (acp->flags & AAC_CMD_BUF_READ)) { 6035942c5e3cSpl196000 if (aac_dma_sync_ac(acp) != AACOK) { 6036942c5e3cSpl196000 ddi_fm_service_impact( 6037942c5e3cSpl196000 softs->devinfo_p, 6038942c5e3cSpl196000 DDI_SERVICE_UNAFFECTED); 6039942c5e3cSpl196000 pkt->pkt_reason = CMD_TRAN_ERR; 6040942c5e3cSpl196000 pkt->pkt_statistics = 0; 6041942c5e3cSpl196000 } 6042942c5e3cSpl196000 } 6043942c5e3cSpl196000 if ((aac_check_acc_handle(softs-> \ 6044942c5e3cSpl196000 comm_space_acc_handle) != DDI_SUCCESS) || 6045942c5e3cSpl196000 (aac_check_acc_handle(softs-> \ 6046942c5e3cSpl196000 pci_mem_handle) != DDI_SUCCESS)) { 6047942c5e3cSpl196000 ddi_fm_service_impact(softs->devinfo_p, 6048942c5e3cSpl196000 DDI_SERVICE_UNAFFECTED); 6049942c5e3cSpl196000 ddi_fm_acc_err_clear(softs-> \ 6050942c5e3cSpl196000 pci_mem_handle, DDI_FME_VER0); 6051942c5e3cSpl196000 pkt->pkt_reason = CMD_TRAN_ERR; 6052942c5e3cSpl196000 pkt->pkt_statistics = 0; 6053942c5e3cSpl196000 } 6054942c5e3cSpl196000 if (aac_check_dma_handle(softs-> \ 6055942c5e3cSpl196000 comm_space_dma_handle) != DDI_SUCCESS) { 6056942c5e3cSpl196000 ddi_fm_service_impact(softs->devinfo_p, 6057942c5e3cSpl196000 DDI_SERVICE_UNAFFECTED); 6058942c5e3cSpl196000 pkt->pkt_reason = CMD_TRAN_ERR; 6059942c5e3cSpl196000 pkt->pkt_statistics = 0; 6060942c5e3cSpl196000 } 6061942c5e3cSpl196000 } 60629c57abc8Ssrivijitha dugganapalli scsi_hba_pkt_comp(pkt); 6063942c5e3cSpl196000 } else { 6064942c5e3cSpl196000 break; 6065942c5e3cSpl196000 } 6066942c5e3cSpl196000 } 6067942c5e3cSpl196000 } 6068942c5e3cSpl196000 6069942c5e3cSpl196000 static int 6070942c5e3cSpl196000 aac_alloc_fib(struct aac_softstate *softs, struct aac_slot *slotp) 6071942c5e3cSpl196000 { 6072942c5e3cSpl196000 size_t rlen; 6073942c5e3cSpl196000 ddi_dma_cookie_t cookie; 6074942c5e3cSpl196000 uint_t cookien; 6075942c5e3cSpl196000 6076942c5e3cSpl196000 /* Allocate FIB dma resource */ 6077942c5e3cSpl196000 if (ddi_dma_alloc_handle( 6078942c5e3cSpl196000 softs->devinfo_p, 6079942c5e3cSpl196000 &softs->addr_dma_attr, 6080942c5e3cSpl196000 DDI_DMA_SLEEP, 6081942c5e3cSpl196000 NULL, 6082942c5e3cSpl196000 &slotp->fib_dma_handle) != DDI_SUCCESS) { 6083942c5e3cSpl196000 AACDB_PRINT(softs, CE_WARN, 6084942c5e3cSpl196000 "Cannot alloc dma handle for slot fib area"); 6085942c5e3cSpl196000 goto error; 6086942c5e3cSpl196000 } 6087942c5e3cSpl196000 if (ddi_dma_mem_alloc( 6088942c5e3cSpl196000 slotp->fib_dma_handle, 6089942c5e3cSpl196000 softs->aac_max_fib_size, 609058bc78c7SXin Chen &softs->acc_attr, 6091942c5e3cSpl196000 DDI_DMA_RDWR | DDI_DMA_CONSISTENT, 6092942c5e3cSpl196000 DDI_DMA_SLEEP, 6093942c5e3cSpl196000 NULL, 6094942c5e3cSpl196000 (caddr_t *)&slotp->fibp, 6095942c5e3cSpl196000 &rlen, 6096942c5e3cSpl196000 &slotp->fib_acc_handle) != DDI_SUCCESS) { 6097942c5e3cSpl196000 AACDB_PRINT(softs, CE_WARN, 6098942c5e3cSpl196000 "Cannot alloc mem for slot fib area"); 6099942c5e3cSpl196000 goto error; 6100942c5e3cSpl196000 } 6101942c5e3cSpl196000 if (ddi_dma_addr_bind_handle( 6102942c5e3cSpl196000 slotp->fib_dma_handle, 6103942c5e3cSpl196000 NULL, 6104942c5e3cSpl196000 (caddr_t)slotp->fibp, 6105942c5e3cSpl196000 softs->aac_max_fib_size, 6106942c5e3cSpl196000 DDI_DMA_RDWR | DDI_DMA_CONSISTENT, 6107942c5e3cSpl196000 DDI_DMA_SLEEP, 6108942c5e3cSpl196000 NULL, 6109942c5e3cSpl196000 &cookie, 6110942c5e3cSpl196000 &cookien) != DDI_DMA_MAPPED) { 6111942c5e3cSpl196000 AACDB_PRINT(softs, CE_WARN, 6112942c5e3cSpl196000 "dma bind failed for slot fib area"); 6113942c5e3cSpl196000 goto error; 6114942c5e3cSpl196000 } 6115942c5e3cSpl196000 6116942c5e3cSpl196000 /* Check dma handles allocated in fib attach */ 6117942c5e3cSpl196000 if (aac_check_dma_handle(slotp->fib_dma_handle) != DDI_SUCCESS) { 6118942c5e3cSpl196000 ddi_fm_service_impact(softs->devinfo_p, DDI_SERVICE_LOST); 6119942c5e3cSpl196000 goto error; 6120942c5e3cSpl196000 } 6121942c5e3cSpl196000 6122942c5e3cSpl196000 /* Check acc handles allocated in fib attach */ 6123942c5e3cSpl196000 if (aac_check_acc_handle(slotp->fib_acc_handle) != DDI_SUCCESS) { 6124942c5e3cSpl196000 ddi_fm_service_impact(softs->devinfo_p, DDI_SERVICE_LOST); 6125942c5e3cSpl196000 goto error; 6126942c5e3cSpl196000 } 6127942c5e3cSpl196000 6128942c5e3cSpl196000 slotp->fib_phyaddr = cookie.dmac_laddress; 6129942c5e3cSpl196000 return (AACOK); 6130942c5e3cSpl196000 6131942c5e3cSpl196000 error: 6132942c5e3cSpl196000 if (slotp->fib_acc_handle) { 6133942c5e3cSpl196000 ddi_dma_mem_free(&slotp->fib_acc_handle); 6134942c5e3cSpl196000 slotp->fib_acc_handle = NULL; 6135942c5e3cSpl196000 } 6136942c5e3cSpl196000 if (slotp->fib_dma_handle) { 6137942c5e3cSpl196000 ddi_dma_free_handle(&slotp->fib_dma_handle); 6138942c5e3cSpl196000 slotp->fib_dma_handle = NULL; 6139942c5e3cSpl196000 } 6140942c5e3cSpl196000 return (AACERR); 6141942c5e3cSpl196000 } 6142942c5e3cSpl196000 6143942c5e3cSpl196000 static void 6144942c5e3cSpl196000 aac_free_fib(struct aac_slot *slotp) 6145942c5e3cSpl196000 { 6146942c5e3cSpl196000 (void) ddi_dma_unbind_handle(slotp->fib_dma_handle); 6147942c5e3cSpl196000 ddi_dma_mem_free(&slotp->fib_acc_handle); 6148942c5e3cSpl196000 slotp->fib_acc_handle = NULL; 6149942c5e3cSpl196000 ddi_dma_free_handle(&slotp->fib_dma_handle); 6150942c5e3cSpl196000 slotp->fib_dma_handle = NULL; 6151942c5e3cSpl196000 slotp->fib_phyaddr = 0; 6152942c5e3cSpl196000 } 6153942c5e3cSpl196000 6154942c5e3cSpl196000 static void 6155942c5e3cSpl196000 aac_alloc_fibs(struct aac_softstate *softs) 6156942c5e3cSpl196000 { 6157942c5e3cSpl196000 int i; 6158942c5e3cSpl196000 struct aac_slot *slotp; 6159942c5e3cSpl196000 6160942c5e3cSpl196000 for (i = 0; i < softs->total_slots && 6161942c5e3cSpl196000 softs->total_fibs < softs->total_slots; i++) { 6162942c5e3cSpl196000 slotp = &(softs->io_slot[i]); 6163942c5e3cSpl196000 if (slotp->fib_phyaddr) 6164942c5e3cSpl196000 continue; 6165942c5e3cSpl196000 if (aac_alloc_fib(softs, slotp) != AACOK) 6166942c5e3cSpl196000 break; 6167942c5e3cSpl196000 6168942c5e3cSpl196000 /* Insert the slot to the free slot list */ 6169942c5e3cSpl196000 aac_release_slot(softs, slotp); 6170942c5e3cSpl196000 softs->total_fibs++; 6171942c5e3cSpl196000 } 6172942c5e3cSpl196000 } 6173942c5e3cSpl196000 6174942c5e3cSpl196000 static void 6175942c5e3cSpl196000 aac_destroy_fibs(struct aac_softstate *softs) 6176942c5e3cSpl196000 { 6177942c5e3cSpl196000 struct aac_slot *slotp; 6178942c5e3cSpl196000 6179942c5e3cSpl196000 while ((slotp = softs->free_io_slot_head) != NULL) { 6180942c5e3cSpl196000 ASSERT(slotp->fib_phyaddr); 6181942c5e3cSpl196000 softs->free_io_slot_head = slotp->next; 6182942c5e3cSpl196000 aac_free_fib(slotp); 6183942c5e3cSpl196000 ASSERT(slotp->index == (slotp - softs->io_slot)); 6184942c5e3cSpl196000 softs->total_fibs--; 6185942c5e3cSpl196000 } 6186942c5e3cSpl196000 ASSERT(softs->total_fibs == 0); 6187942c5e3cSpl196000 } 6188942c5e3cSpl196000 6189942c5e3cSpl196000 static int 6190942c5e3cSpl196000 aac_create_slots(struct aac_softstate *softs) 6191942c5e3cSpl196000 { 6192942c5e3cSpl196000 int i; 6193942c5e3cSpl196000 6194942c5e3cSpl196000 softs->total_slots = softs->aac_max_fibs; 6195942c5e3cSpl196000 softs->io_slot = kmem_zalloc(sizeof (struct aac_slot) * \ 6196942c5e3cSpl196000 softs->total_slots, KM_SLEEP); 6197942c5e3cSpl196000 if (softs->io_slot == NULL) { 6198942c5e3cSpl196000 AACDB_PRINT(softs, CE_WARN, "Cannot allocate slot"); 6199942c5e3cSpl196000 return (AACERR); 6200942c5e3cSpl196000 } 6201942c5e3cSpl196000 for (i = 0; i < softs->total_slots; i++) 6202942c5e3cSpl196000 softs->io_slot[i].index = i; 6203942c5e3cSpl196000 softs->free_io_slot_head = NULL; 6204942c5e3cSpl196000 softs->total_fibs = 0; 6205942c5e3cSpl196000 return (AACOK); 6206942c5e3cSpl196000 } 6207942c5e3cSpl196000 6208942c5e3cSpl196000 static void 6209942c5e3cSpl196000 aac_destroy_slots(struct aac_softstate *softs) 6210942c5e3cSpl196000 { 6211942c5e3cSpl196000 ASSERT(softs->free_io_slot_head == NULL); 6212942c5e3cSpl196000 6213942c5e3cSpl196000 kmem_free(softs->io_slot, sizeof (struct aac_slot) * \ 6214942c5e3cSpl196000 softs->total_slots); 6215942c5e3cSpl196000 softs->io_slot = NULL; 6216942c5e3cSpl196000 softs->total_slots = 0; 6217942c5e3cSpl196000 } 6218942c5e3cSpl196000 6219942c5e3cSpl196000 struct aac_slot * 6220942c5e3cSpl196000 aac_get_slot(struct aac_softstate *softs) 6221942c5e3cSpl196000 { 6222942c5e3cSpl196000 struct aac_slot *slotp; 6223942c5e3cSpl196000 6224942c5e3cSpl196000 if ((slotp = softs->free_io_slot_head) != NULL) { 6225942c5e3cSpl196000 softs->free_io_slot_head = slotp->next; 6226942c5e3cSpl196000 slotp->next = NULL; 6227942c5e3cSpl196000 } 6228942c5e3cSpl196000 return (slotp); 6229942c5e3cSpl196000 } 6230942c5e3cSpl196000 6231942c5e3cSpl196000 static void 6232942c5e3cSpl196000 aac_release_slot(struct aac_softstate *softs, struct aac_slot *slotp) 6233942c5e3cSpl196000 { 6234942c5e3cSpl196000 ASSERT((slotp->index >= 0) && (slotp->index < softs->total_slots)); 6235942c5e3cSpl196000 ASSERT(slotp == &softs->io_slot[slotp->index]); 6236942c5e3cSpl196000 6237942c5e3cSpl196000 slotp->acp = NULL; 6238942c5e3cSpl196000 slotp->next = softs->free_io_slot_head; 6239942c5e3cSpl196000 softs->free_io_slot_head = slotp; 6240942c5e3cSpl196000 } 6241942c5e3cSpl196000 6242942c5e3cSpl196000 int 6243942c5e3cSpl196000 aac_do_io(struct aac_softstate *softs, struct aac_cmd *acp) 6244942c5e3cSpl196000 { 6245942c5e3cSpl196000 if (aac_bind_io(softs, acp) == AACOK) 6246942c5e3cSpl196000 aac_start_io(softs, acp); 6247942c5e3cSpl196000 else 6248942c5e3cSpl196000 aac_cmd_enqueue(&softs->q_wait[AAC_CMDQ(acp)], acp); 6249942c5e3cSpl196000 6250942c5e3cSpl196000 if (!(acp->flags & (AAC_CMD_NO_CB | AAC_CMD_NO_INTR))) 6251942c5e3cSpl196000 return (TRAN_ACCEPT); 6252942c5e3cSpl196000 /* 6253942c5e3cSpl196000 * Because sync FIB is always 512 bytes and used for critical 6254942c5e3cSpl196000 * functions, async FIB is used for poll IO. 6255942c5e3cSpl196000 */ 6256942c5e3cSpl196000 if (acp->flags & AAC_CMD_NO_INTR) { 6257942c5e3cSpl196000 if (aac_do_poll_io(softs, acp) == AACOK) 6258942c5e3cSpl196000 return (TRAN_ACCEPT); 6259942c5e3cSpl196000 } else { 6260942c5e3cSpl196000 if (aac_do_sync_io(softs, acp) == AACOK) 6261942c5e3cSpl196000 return (TRAN_ACCEPT); 6262942c5e3cSpl196000 } 6263942c5e3cSpl196000 return (TRAN_BADPKT); 6264942c5e3cSpl196000 } 6265942c5e3cSpl196000 6266942c5e3cSpl196000 static int 6267942c5e3cSpl196000 aac_do_poll_io(struct aac_softstate *softs, struct aac_cmd *acp) 6268942c5e3cSpl196000 { 6269942c5e3cSpl196000 int (*intr_handler)(struct aac_softstate *); 6270942c5e3cSpl196000 6271942c5e3cSpl196000 /* 6272942c5e3cSpl196000 * Interrupt is disabled, we have to poll the adapter by ourselves. 6273942c5e3cSpl196000 */ 6274942c5e3cSpl196000 intr_handler = (softs->flags & AAC_FLAGS_NEW_COMM) ? 6275942c5e3cSpl196000 aac_process_intr_new : aac_process_intr_old; 6276942c5e3cSpl196000 while (!(acp->flags & (AAC_CMD_CMPLT | AAC_CMD_ABORT))) { 6277942c5e3cSpl196000 int i = AAC_POLL_TIME * 1000; 6278942c5e3cSpl196000 6279942c5e3cSpl196000 AAC_BUSYWAIT((intr_handler(softs) != AAC_DB_RESPONSE_READY), i); 6280942c5e3cSpl196000 if (i == 0) 628158bc78c7SXin Chen aac_cmd_timeout(softs, acp); 6282942c5e3cSpl196000 } 6283942c5e3cSpl196000 6284942c5e3cSpl196000 ddi_trigger_softintr(softs->softint_id); 6285942c5e3cSpl196000 6286942c5e3cSpl196000 if ((acp->flags & AAC_CMD_CMPLT) && !(acp->flags & AAC_CMD_ERR)) 6287942c5e3cSpl196000 return (AACOK); 6288942c5e3cSpl196000 return (AACERR); 6289942c5e3cSpl196000 } 6290942c5e3cSpl196000 6291942c5e3cSpl196000 static int 6292942c5e3cSpl196000 aac_do_sync_io(struct aac_softstate *softs, struct aac_cmd *acp) 6293942c5e3cSpl196000 { 6294942c5e3cSpl196000 ASSERT(softs && acp); 6295942c5e3cSpl196000 6296942c5e3cSpl196000 while (!(acp->flags & (AAC_CMD_CMPLT | AAC_CMD_ABORT))) 6297942c5e3cSpl196000 cv_wait(&softs->event, &softs->io_lock); 6298942c5e3cSpl196000 6299942c5e3cSpl196000 if (acp->flags & AAC_CMD_CMPLT) 6300942c5e3cSpl196000 return (AACOK); 6301942c5e3cSpl196000 return (AACERR); 6302942c5e3cSpl196000 } 6303942c5e3cSpl196000 6304942c5e3cSpl196000 static int 6305942c5e3cSpl196000 aac_dma_sync_ac(struct aac_cmd *acp) 6306942c5e3cSpl196000 { 6307942c5e3cSpl196000 if (acp->buf_dma_handle) { 6308942c5e3cSpl196000 if (acp->flags & AAC_CMD_BUF_WRITE) { 6309942c5e3cSpl196000 if (acp->abp != NULL) 6310942c5e3cSpl196000 ddi_rep_put8(acp->abh, 6311942c5e3cSpl196000 (uint8_t *)acp->bp->b_un.b_addr, 6312942c5e3cSpl196000 (uint8_t *)acp->abp, acp->bp->b_bcount, 6313942c5e3cSpl196000 DDI_DEV_AUTOINCR); 6314942c5e3cSpl196000 (void) ddi_dma_sync(acp->buf_dma_handle, 0, 0, 6315942c5e3cSpl196000 DDI_DMA_SYNC_FORDEV); 6316942c5e3cSpl196000 } else { 6317942c5e3cSpl196000 (void) ddi_dma_sync(acp->buf_dma_handle, 0, 0, 6318942c5e3cSpl196000 DDI_DMA_SYNC_FORCPU); 6319942c5e3cSpl196000 if (aac_check_dma_handle(acp->buf_dma_handle) != 6320942c5e3cSpl196000 DDI_SUCCESS) 6321942c5e3cSpl196000 return (AACERR); 6322942c5e3cSpl196000 if (acp->abp != NULL) 6323942c5e3cSpl196000 ddi_rep_get8(acp->abh, 6324942c5e3cSpl196000 (uint8_t *)acp->bp->b_un.b_addr, 6325942c5e3cSpl196000 (uint8_t *)acp->abp, acp->bp->b_bcount, 6326942c5e3cSpl196000 DDI_DEV_AUTOINCR); 6327942c5e3cSpl196000 } 6328942c5e3cSpl196000 } 6329942c5e3cSpl196000 return (AACOK); 6330942c5e3cSpl196000 } 6331942c5e3cSpl196000 6332942c5e3cSpl196000 /* 63330749e8deSXin Chen - Sun Microsystems - Beijing China * Copy AIF from adapter to the empty AIF slot and inform AIF threads 63340749e8deSXin Chen - Sun Microsystems - Beijing China */ 63350749e8deSXin Chen - Sun Microsystems - Beijing China static void 63360749e8deSXin Chen - Sun Microsystems - Beijing China aac_save_aif(struct aac_softstate *softs, ddi_acc_handle_t acc, 63370749e8deSXin Chen - Sun Microsystems - Beijing China struct aac_fib *fibp0, int fib_size0) 63380749e8deSXin Chen - Sun Microsystems - Beijing China { 63390749e8deSXin Chen - Sun Microsystems - Beijing China struct aac_fib *fibp; /* FIB in AIF queue */ 63400749e8deSXin Chen - Sun Microsystems - Beijing China int fib_size; 63410749e8deSXin Chen - Sun Microsystems - Beijing China uint16_t fib_command; 63420749e8deSXin Chen - Sun Microsystems - Beijing China int current, next; 63430749e8deSXin Chen - Sun Microsystems - Beijing China 63440749e8deSXin Chen - Sun Microsystems - Beijing China /* Ignore non AIF messages */ 63450749e8deSXin Chen - Sun Microsystems - Beijing China fib_command = ddi_get16(acc, &fibp0->Header.Command); 63460749e8deSXin Chen - Sun Microsystems - Beijing China if (fib_command != AifRequest) { 63470749e8deSXin Chen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "!Unknown command from controller"); 63480749e8deSXin Chen - Sun Microsystems - Beijing China return; 63490749e8deSXin Chen - Sun Microsystems - Beijing China } 63500749e8deSXin Chen - Sun Microsystems - Beijing China 63510749e8deSXin Chen - Sun Microsystems - Beijing China mutex_enter(&softs->aifq_mutex); 63520749e8deSXin Chen - Sun Microsystems - Beijing China 63530749e8deSXin Chen - Sun Microsystems - Beijing China /* Save AIF */ 63540749e8deSXin Chen - Sun Microsystems - Beijing China fibp = &softs->aifq[softs->aifq_idx].d; 63550749e8deSXin Chen - Sun Microsystems - Beijing China fib_size = (fib_size0 > AAC_FIB_SIZE) ? AAC_FIB_SIZE : fib_size0; 63560749e8deSXin Chen - Sun Microsystems - Beijing China ddi_rep_get8(acc, (uint8_t *)fibp, (uint8_t *)fibp0, fib_size, 63570749e8deSXin Chen - Sun Microsystems - Beijing China DDI_DEV_AUTOINCR); 63580749e8deSXin Chen - Sun Microsystems - Beijing China 63590749e8deSXin Chen - Sun Microsystems - Beijing China if (aac_check_acc_handle(softs->pci_mem_handle) != DDI_SUCCESS) { 63600749e8deSXin Chen - Sun Microsystems - Beijing China ddi_fm_service_impact(softs->devinfo_p, 63610749e8deSXin Chen - Sun Microsystems - Beijing China DDI_SERVICE_UNAFFECTED); 63620749e8deSXin Chen - Sun Microsystems - Beijing China mutex_exit(&softs->aifq_mutex); 63630749e8deSXin Chen - Sun Microsystems - Beijing China return; 63640749e8deSXin Chen - Sun Microsystems - Beijing China } 63650749e8deSXin Chen - Sun Microsystems - Beijing China 63660749e8deSXin Chen - Sun Microsystems - Beijing China AACDB_PRINT_AIF(softs, (struct aac_aif_command *)&fibp->data[0]); 63670749e8deSXin Chen - Sun Microsystems - Beijing China 63680749e8deSXin Chen - Sun Microsystems - Beijing China /* Modify AIF contexts */ 63690749e8deSXin Chen - Sun Microsystems - Beijing China current = softs->aifq_idx; 63700749e8deSXin Chen - Sun Microsystems - Beijing China next = (current + 1) % AAC_AIFQ_LENGTH; 63710749e8deSXin Chen - Sun Microsystems - Beijing China if (next == 0) { 63720749e8deSXin Chen - Sun Microsystems - Beijing China struct aac_fib_context *ctx_p; 63730749e8deSXin Chen - Sun Microsystems - Beijing China 63740749e8deSXin Chen - Sun Microsystems - Beijing China softs->aifq_wrap = 1; 63750749e8deSXin Chen - Sun Microsystems - Beijing China for (ctx_p = softs->fibctx_p; ctx_p; ctx_p = ctx_p->next) { 63760749e8deSXin Chen - Sun Microsystems - Beijing China if (next == ctx_p->ctx_idx) { 63770749e8deSXin Chen - Sun Microsystems - Beijing China ctx_p->ctx_flags |= AAC_CTXFLAG_FILLED; 63780749e8deSXin Chen - Sun Microsystems - Beijing China } else if (current == ctx_p->ctx_idx && 63790749e8deSXin Chen - Sun Microsystems - Beijing China (ctx_p->ctx_flags & AAC_CTXFLAG_FILLED)) { 63800749e8deSXin Chen - Sun Microsystems - Beijing China ctx_p->ctx_idx = next; 63810749e8deSXin Chen - Sun Microsystems - Beijing China ctx_p->ctx_overrun++; 63820749e8deSXin Chen - Sun Microsystems - Beijing China } 63830749e8deSXin Chen - Sun Microsystems - Beijing China } 63840749e8deSXin Chen - Sun Microsystems - Beijing China } 63850749e8deSXin Chen - Sun Microsystems - Beijing China softs->aifq_idx = next; 63860749e8deSXin Chen - Sun Microsystems - Beijing China 63870749e8deSXin Chen - Sun Microsystems - Beijing China /* Wakeup AIF threads */ 63880749e8deSXin Chen - Sun Microsystems - Beijing China cv_broadcast(&softs->aifq_cv); 63890749e8deSXin Chen - Sun Microsystems - Beijing China mutex_exit(&softs->aifq_mutex); 63900749e8deSXin Chen - Sun Microsystems - Beijing China 63910749e8deSXin Chen - Sun Microsystems - Beijing China /* Wakeup event thread to handle aif */ 63920749e8deSXin Chen - Sun Microsystems - Beijing China aac_event_disp(softs, AAC_EVENT_AIF); 63930749e8deSXin Chen - Sun Microsystems - Beijing China } 63940749e8deSXin Chen - Sun Microsystems - Beijing China 63950749e8deSXin Chen - Sun Microsystems - Beijing China static int 63960749e8deSXin Chen - Sun Microsystems - Beijing China aac_return_aif_common(struct aac_softstate *softs, struct aac_fib_context *ctx, 63970749e8deSXin Chen - Sun Microsystems - Beijing China struct aac_fib **fibpp) 63980749e8deSXin Chen - Sun Microsystems - Beijing China { 63990749e8deSXin Chen - Sun Microsystems - Beijing China int current; 64000749e8deSXin Chen - Sun Microsystems - Beijing China 64010749e8deSXin Chen - Sun Microsystems - Beijing China current = ctx->ctx_idx; 64020749e8deSXin Chen - Sun Microsystems - Beijing China if (current == softs->aifq_idx && 64030749e8deSXin Chen - Sun Microsystems - Beijing China !(ctx->ctx_flags & AAC_CTXFLAG_FILLED)) 64040749e8deSXin Chen - Sun Microsystems - Beijing China return (EAGAIN); /* Empty */ 64050749e8deSXin Chen - Sun Microsystems - Beijing China 64060749e8deSXin Chen - Sun Microsystems - Beijing China *fibpp = &softs->aifq[current].d; 64070749e8deSXin Chen - Sun Microsystems - Beijing China 64080749e8deSXin Chen - Sun Microsystems - Beijing China ctx->ctx_flags &= ~AAC_CTXFLAG_FILLED; 64090749e8deSXin Chen - Sun Microsystems - Beijing China ctx->ctx_idx = (current + 1) % AAC_AIFQ_LENGTH; 64100749e8deSXin Chen - Sun Microsystems - Beijing China return (0); 64110749e8deSXin Chen - Sun Microsystems - Beijing China } 64120749e8deSXin Chen - Sun Microsystems - Beijing China 64130749e8deSXin Chen - Sun Microsystems - Beijing China int 64140749e8deSXin Chen - Sun Microsystems - Beijing China aac_return_aif(struct aac_softstate *softs, struct aac_fib_context *ctx, 64150749e8deSXin Chen - Sun Microsystems - Beijing China struct aac_fib **fibpp) 64160749e8deSXin Chen - Sun Microsystems - Beijing China { 64170749e8deSXin Chen - Sun Microsystems - Beijing China int rval; 64180749e8deSXin Chen - Sun Microsystems - Beijing China 64190749e8deSXin Chen - Sun Microsystems - Beijing China mutex_enter(&softs->aifq_mutex); 64200749e8deSXin Chen - Sun Microsystems - Beijing China rval = aac_return_aif_common(softs, ctx, fibpp); 64210749e8deSXin Chen - Sun Microsystems - Beijing China mutex_exit(&softs->aifq_mutex); 64220749e8deSXin Chen - Sun Microsystems - Beijing China return (rval); 64230749e8deSXin Chen - Sun Microsystems - Beijing China } 64240749e8deSXin Chen - Sun Microsystems - Beijing China 64250749e8deSXin Chen - Sun Microsystems - Beijing China int 64260749e8deSXin Chen - Sun Microsystems - Beijing China aac_return_aif_wait(struct aac_softstate *softs, struct aac_fib_context *ctx, 64270749e8deSXin Chen - Sun Microsystems - Beijing China struct aac_fib **fibpp) 64280749e8deSXin Chen - Sun Microsystems - Beijing China { 64290749e8deSXin Chen - Sun Microsystems - Beijing China int rval; 64300749e8deSXin Chen - Sun Microsystems - Beijing China 64310749e8deSXin Chen - Sun Microsystems - Beijing China mutex_enter(&softs->aifq_mutex); 64320749e8deSXin Chen - Sun Microsystems - Beijing China rval = aac_return_aif_common(softs, ctx, fibpp); 64330749e8deSXin Chen - Sun Microsystems - Beijing China if (rval == EAGAIN) { 64340749e8deSXin Chen - Sun Microsystems - Beijing China AACDB_PRINT(softs, CE_NOTE, "Waiting for AIF"); 64350749e8deSXin Chen - Sun Microsystems - Beijing China rval = cv_wait_sig(&softs->aifq_cv, &softs->aifq_mutex); 64360749e8deSXin Chen - Sun Microsystems - Beijing China } 64370749e8deSXin Chen - Sun Microsystems - Beijing China mutex_exit(&softs->aifq_mutex); 64380749e8deSXin Chen - Sun Microsystems - Beijing China return ((rval > 0) ? 0 : EINTR); 64390749e8deSXin Chen - Sun Microsystems - Beijing China } 64400749e8deSXin Chen - Sun Microsystems - Beijing China 64410749e8deSXin Chen - Sun Microsystems - Beijing China /* 6442942c5e3cSpl196000 * The following function comes from Adaptec: 6443942c5e3cSpl196000 * 6444942c5e3cSpl196000 * When driver sees a particular event that means containers are changed, it 6445942c5e3cSpl196000 * will rescan containers. However a change may not be complete until some 6446942c5e3cSpl196000 * other event is received. For example, creating or deleting an array will 6447942c5e3cSpl196000 * incur as many as six AifEnConfigChange events which would generate six 6448942c5e3cSpl196000 * container rescans. To diminish rescans, driver set a flag to wait for 6449942c5e3cSpl196000 * another particular event. When sees that events come in, it will do rescan. 6450942c5e3cSpl196000 */ 6451942c5e3cSpl196000 static int 64520749e8deSXin Chen - Sun Microsystems - Beijing China aac_handle_aif(struct aac_softstate *softs, struct aac_aif_command *aif) 6453942c5e3cSpl196000 { 6454942c5e3cSpl196000 ddi_acc_handle_t acc = softs->comm_space_acc_handle; 6455942c5e3cSpl196000 int en_type; 6456942c5e3cSpl196000 int devcfg_needed; 64573fced439Szhongyan gu - Sun Microsystems - Beijing China int cid; 64583fced439Szhongyan gu - Sun Microsystems - Beijing China uint32_t bus_id, tgt_id; 64593fced439Szhongyan gu - Sun Microsystems - Beijing China enum aac_cfg_event event = AAC_CFG_NULL_EXIST; 6460942c5e3cSpl196000 6461942c5e3cSpl196000 devcfg_needed = 0; 6462942c5e3cSpl196000 en_type = LE_32((uint32_t)aif->data.EN.type); 6463942c5e3cSpl196000 6464942c5e3cSpl196000 switch (LE_32((uint32_t)aif->command)) { 6465942c5e3cSpl196000 case AifCmdDriverNotify: { 64663fced439Szhongyan gu - Sun Microsystems - Beijing China cid = LE_32(aif->data.EN.data.ECC.container[0]); 6467942c5e3cSpl196000 6468942c5e3cSpl196000 switch (en_type) { 6469942c5e3cSpl196000 case AifDenMorphComplete: 6470942c5e3cSpl196000 case AifDenVolumeExtendComplete: 647158bc78c7SXin Chen if (AAC_DEV_IS_VALID(&softs->containers[cid].dev)) 6472942c5e3cSpl196000 softs->devcfg_wait_on = AifEnConfigChange; 6473942c5e3cSpl196000 break; 6474942c5e3cSpl196000 } 6475942c5e3cSpl196000 if (softs->devcfg_wait_on == en_type) 6476942c5e3cSpl196000 devcfg_needed = 1; 6477942c5e3cSpl196000 break; 6478942c5e3cSpl196000 } 6479942c5e3cSpl196000 6480942c5e3cSpl196000 case AifCmdEventNotify: 64813fced439Szhongyan gu - Sun Microsystems - Beijing China cid = LE_32(aif->data.EN.data.ECC.container[0]); 6482942c5e3cSpl196000 switch (en_type) { 6483942c5e3cSpl196000 case AifEnAddContainer: 6484942c5e3cSpl196000 case AifEnDeleteContainer: 6485942c5e3cSpl196000 softs->devcfg_wait_on = AifEnConfigChange; 6486942c5e3cSpl196000 break; 6487942c5e3cSpl196000 case AifEnContainerChange: 6488942c5e3cSpl196000 if (!softs->devcfg_wait_on) 6489942c5e3cSpl196000 softs->devcfg_wait_on = AifEnConfigChange; 6490942c5e3cSpl196000 break; 6491942c5e3cSpl196000 case AifEnContainerEvent: 6492942c5e3cSpl196000 if (ddi_get32(acc, &aif-> \ 6493942c5e3cSpl196000 data.EN.data.ECE.eventType) == CT_PUP_MISSING_DRIVE) 6494942c5e3cSpl196000 devcfg_needed = 1; 6495942c5e3cSpl196000 break; 64963fced439Szhongyan gu - Sun Microsystems - Beijing China case AifEnAddJBOD: 64973fced439Szhongyan gu - Sun Microsystems - Beijing China if (!(softs->flags & AAC_FLAGS_JBOD)) 64983fced439Szhongyan gu - Sun Microsystems - Beijing China return (AACERR); 64993fced439Szhongyan gu - Sun Microsystems - Beijing China event = AAC_CFG_ADD; 65003fced439Szhongyan gu - Sun Microsystems - Beijing China bus_id = (cid >> 24) & 0xf; 65013fced439Szhongyan gu - Sun Microsystems - Beijing China tgt_id = cid & 0xffff; 65023fced439Szhongyan gu - Sun Microsystems - Beijing China break; 65033fced439Szhongyan gu - Sun Microsystems - Beijing China case AifEnDeleteJBOD: 65043fced439Szhongyan gu - Sun Microsystems - Beijing China if (!(softs->flags & AAC_FLAGS_JBOD)) 65053fced439Szhongyan gu - Sun Microsystems - Beijing China return (AACERR); 65063fced439Szhongyan gu - Sun Microsystems - Beijing China event = AAC_CFG_DELETE; 65073fced439Szhongyan gu - Sun Microsystems - Beijing China bus_id = (cid >> 24) & 0xf; 65083fced439Szhongyan gu - Sun Microsystems - Beijing China tgt_id = cid & 0xffff; 65093fced439Szhongyan gu - Sun Microsystems - Beijing China break; 6510942c5e3cSpl196000 } 6511942c5e3cSpl196000 if (softs->devcfg_wait_on == en_type) 6512942c5e3cSpl196000 devcfg_needed = 1; 6513942c5e3cSpl196000 break; 6514942c5e3cSpl196000 6515942c5e3cSpl196000 case AifCmdJobProgress: 6516942c5e3cSpl196000 if (LE_32((uint32_t)aif->data.PR[0].jd.type) == AifJobCtrZero) { 6517942c5e3cSpl196000 int pr_status; 6518942c5e3cSpl196000 uint32_t pr_ftick, pr_ctick; 6519942c5e3cSpl196000 6520942c5e3cSpl196000 pr_status = LE_32((uint32_t)aif->data.PR[0].status); 6521942c5e3cSpl196000 pr_ctick = LE_32(aif->data.PR[0].currentTick); 6522942c5e3cSpl196000 pr_ftick = LE_32(aif->data.PR[0].finalTick); 6523942c5e3cSpl196000 6524942c5e3cSpl196000 if ((pr_ctick == pr_ftick) || 6525942c5e3cSpl196000 (pr_status == AifJobStsSuccess)) 6526942c5e3cSpl196000 softs->devcfg_wait_on = AifEnContainerChange; 6527942c5e3cSpl196000 else if ((pr_ctick == 0) && 6528942c5e3cSpl196000 (pr_status == AifJobStsRunning)) 6529942c5e3cSpl196000 softs->devcfg_wait_on = AifEnContainerChange; 6530942c5e3cSpl196000 } 6531942c5e3cSpl196000 break; 6532942c5e3cSpl196000 } 6533942c5e3cSpl196000 653458bc78c7SXin Chen if (devcfg_needed) { 653558bc78c7SXin Chen softs->devcfg_wait_on = 0; 6536942c5e3cSpl196000 (void) aac_probe_containers(softs); 653758bc78c7SXin Chen } 6538942c5e3cSpl196000 65393fced439Szhongyan gu - Sun Microsystems - Beijing China if (event != AAC_CFG_NULL_EXIST) { 65403fced439Szhongyan gu - Sun Microsystems - Beijing China ASSERT(en_type == AifEnAddJBOD || en_type == AifEnDeleteJBOD); 65413fced439Szhongyan gu - Sun Microsystems - Beijing China (void) aac_probe_jbod(softs, 65423fced439Szhongyan gu - Sun Microsystems - Beijing China AAC_P2VTGT(softs, bus_id, tgt_id), event); 65433fced439Szhongyan gu - Sun Microsystems - Beijing China } 6544942c5e3cSpl196000 return (AACOK); 6545942c5e3cSpl196000 } 6546942c5e3cSpl196000 65470749e8deSXin Chen - Sun Microsystems - Beijing China 65480749e8deSXin Chen - Sun Microsystems - Beijing China /* 65490749e8deSXin Chen - Sun Microsystems - Beijing China * Check and handle AIF events 65500749e8deSXin Chen - Sun Microsystems - Beijing China */ 65510749e8deSXin Chen - Sun Microsystems - Beijing China static void 65520749e8deSXin Chen - Sun Microsystems - Beijing China aac_aif_event(struct aac_softstate *softs) 65530749e8deSXin Chen - Sun Microsystems - Beijing China { 65540749e8deSXin Chen - Sun Microsystems - Beijing China struct aac_fib *fibp; 65550749e8deSXin Chen - Sun Microsystems - Beijing China 65560749e8deSXin Chen - Sun Microsystems - Beijing China /*CONSTCOND*/ 65570749e8deSXin Chen - Sun Microsystems - Beijing China while (1) { 65580749e8deSXin Chen - Sun Microsystems - Beijing China if (aac_return_aif(softs, &softs->aifctx, &fibp) != 0) 65590749e8deSXin Chen - Sun Microsystems - Beijing China break; /* No more AIFs to handle, end loop */ 65600749e8deSXin Chen - Sun Microsystems - Beijing China 65610749e8deSXin Chen - Sun Microsystems - Beijing China /* AIF overrun, array create/delete may missed. */ 65620749e8deSXin Chen - Sun Microsystems - Beijing China if (softs->aifctx.ctx_overrun) { 65630749e8deSXin Chen - Sun Microsystems - Beijing China softs->aifctx.ctx_overrun = 0; 65640749e8deSXin Chen - Sun Microsystems - Beijing China } 65650749e8deSXin Chen - Sun Microsystems - Beijing China 65660749e8deSXin Chen - Sun Microsystems - Beijing China /* AIF received, handle it */ 65670749e8deSXin Chen - Sun Microsystems - Beijing China struct aac_aif_command *aifp = 65680749e8deSXin Chen - Sun Microsystems - Beijing China (struct aac_aif_command *)&fibp->data[0]; 65690749e8deSXin Chen - Sun Microsystems - Beijing China uint32_t aif_command = LE_32((uint32_t)aifp->command); 65700749e8deSXin Chen - Sun Microsystems - Beijing China 65710749e8deSXin Chen - Sun Microsystems - Beijing China if (aif_command == AifCmdDriverNotify || 65720749e8deSXin Chen - Sun Microsystems - Beijing China aif_command == AifCmdEventNotify || 65730749e8deSXin Chen - Sun Microsystems - Beijing China aif_command == AifCmdJobProgress) 65740749e8deSXin Chen - Sun Microsystems - Beijing China (void) aac_handle_aif(softs, aifp); 65750749e8deSXin Chen - Sun Microsystems - Beijing China } 65760749e8deSXin Chen - Sun Microsystems - Beijing China } 65770749e8deSXin Chen - Sun Microsystems - Beijing China 6578942c5e3cSpl196000 /* 6579942c5e3cSpl196000 * Timeout recovery 6580942c5e3cSpl196000 */ 658158bc78c7SXin Chen /*ARGSUSED*/ 6582942c5e3cSpl196000 static void 658358bc78c7SXin Chen aac_cmd_timeout(struct aac_softstate *softs, struct aac_cmd *acp) 6584942c5e3cSpl196000 { 658558bc78c7SXin Chen #ifdef DEBUG 658658bc78c7SXin Chen acp->fib_flags |= AACDB_FLAGS_FIB_TIMEOUT; 658758bc78c7SXin Chen AACDB_PRINT(softs, CE_WARN, "acp %p timed out", acp); 658858bc78c7SXin Chen AACDB_PRINT_FIB(softs, acp->slotp); 658958bc78c7SXin Chen #endif 659058bc78c7SXin Chen 6591942c5e3cSpl196000 /* 6592942c5e3cSpl196000 * Besides the firmware in unhealthy state, an overloaded 6593942c5e3cSpl196000 * adapter may also incur pkt timeout. 6594942c5e3cSpl196000 * There is a chance for an adapter with a slower IOP to take 6595942c5e3cSpl196000 * longer than 60 seconds to process the commands, such as when 6596942c5e3cSpl196000 * to perform IOs. So the adapter is doing a build on a RAID-5 6597942c5e3cSpl196000 * while being required longer completion times should be 6598942c5e3cSpl196000 * tolerated. 6599942c5e3cSpl196000 */ 660058bc78c7SXin Chen switch (aac_do_reset(softs)) { 660158bc78c7SXin Chen case AAC_IOP_RESET_SUCCEED: 660258bc78c7SXin Chen aac_abort_iocmds(softs, AAC_IOCMD_OUTSTANDING, NULL, CMD_RESET); 6603942c5e3cSpl196000 aac_start_waiting_io(softs); 660458bc78c7SXin Chen break; 660558bc78c7SXin Chen case AAC_IOP_RESET_FAILED: 6606942c5e3cSpl196000 /* Abort all waiting cmds when adapter is dead */ 660758bc78c7SXin Chen aac_abort_iocmds(softs, AAC_IOCMD_ALL, NULL, CMD_TIMEOUT); 660858bc78c7SXin Chen break; 660958bc78c7SXin Chen case AAC_IOP_RESET_ABNORMAL: 661058bc78c7SXin Chen aac_start_waiting_io(softs); 6611942c5e3cSpl196000 } 6612942c5e3cSpl196000 } 6613942c5e3cSpl196000 6614942c5e3cSpl196000 /* 6615942c5e3cSpl196000 * The following function comes from Adaptec: 6616942c5e3cSpl196000 * 6617942c5e3cSpl196000 * Time sync. command added to synchronize time with firmware every 30 6618942c5e3cSpl196000 * minutes (required for correct AIF timestamps etc.) 6619942c5e3cSpl196000 */ 66200749e8deSXin Chen - Sun Microsystems - Beijing China static void 6621942c5e3cSpl196000 aac_sync_tick(struct aac_softstate *softs) 6622942c5e3cSpl196000 { 6623f42c2f53Szhongyan gu - Sun Microsystems - Beijing China ddi_acc_handle_t acc; 6624f42c2f53Szhongyan gu - Sun Microsystems - Beijing China int rval; 6625942c5e3cSpl196000 66260749e8deSXin Chen - Sun Microsystems - Beijing China mutex_enter(&softs->time_mutex); 66270749e8deSXin Chen - Sun Microsystems - Beijing China ASSERT(softs->time_sync <= softs->timebase); 66280749e8deSXin Chen - Sun Microsystems - Beijing China softs->time_sync = 0; 66290749e8deSXin Chen - Sun Microsystems - Beijing China mutex_exit(&softs->time_mutex); 66300749e8deSXin Chen - Sun Microsystems - Beijing China 6631f42c2f53Szhongyan gu - Sun Microsystems - Beijing China /* Time sync. with firmware every AAC_SYNC_TICK */ 6632f42c2f53Szhongyan gu - Sun Microsystems - Beijing China (void) aac_sync_fib_slot_bind(softs, &softs->sync_ac); 6633f42c2f53Szhongyan gu - Sun Microsystems - Beijing China acc = softs->sync_ac.slotp->fib_acc_handle; 6634f42c2f53Szhongyan gu - Sun Microsystems - Beijing China 6635f42c2f53Szhongyan gu - Sun Microsystems - Beijing China ddi_put32(acc, (void *)&softs->sync_ac.slotp->fibp->data[0], 6636f42c2f53Szhongyan gu - Sun Microsystems - Beijing China ddi_get_time()); 6637f42c2f53Szhongyan gu - Sun Microsystems - Beijing China rval = aac_sync_fib(softs, SendHostTime, AAC_FIB_SIZEOF(uint32_t)); 6638f42c2f53Szhongyan gu - Sun Microsystems - Beijing China aac_sync_fib_slot_release(softs, &softs->sync_ac); 66390749e8deSXin Chen - Sun Microsystems - Beijing China 66400749e8deSXin Chen - Sun Microsystems - Beijing China mutex_enter(&softs->time_mutex); 66410749e8deSXin Chen - Sun Microsystems - Beijing China softs->time_sync = softs->timebase; 66420749e8deSXin Chen - Sun Microsystems - Beijing China if (rval != AACOK) 66430749e8deSXin Chen - Sun Microsystems - Beijing China /* retry shortly */ 66440749e8deSXin Chen - Sun Microsystems - Beijing China softs->time_sync += aac_tick << 1; 66450749e8deSXin Chen - Sun Microsystems - Beijing China else 66460749e8deSXin Chen - Sun Microsystems - Beijing China softs->time_sync += AAC_SYNC_TICK; 66470749e8deSXin Chen - Sun Microsystems - Beijing China mutex_exit(&softs->time_mutex); 6648942c5e3cSpl196000 } 6649942c5e3cSpl196000 66500749e8deSXin Chen - Sun Microsystems - Beijing China /* 66510749e8deSXin Chen - Sun Microsystems - Beijing China * Timeout checking and handling 66520749e8deSXin Chen - Sun Microsystems - Beijing China */ 6653942c5e3cSpl196000 static void 66540749e8deSXin Chen - Sun Microsystems - Beijing China aac_daemon(struct aac_softstate *softs) 6655942c5e3cSpl196000 { 66560749e8deSXin Chen - Sun Microsystems - Beijing China int time_out; /* set if timeout happened */ 66570749e8deSXin Chen - Sun Microsystems - Beijing China int time_adjust; 66580749e8deSXin Chen - Sun Microsystems - Beijing China uint32_t softs_timebase; 66590749e8deSXin Chen - Sun Microsystems - Beijing China 66600749e8deSXin Chen - Sun Microsystems - Beijing China mutex_enter(&softs->time_mutex); 66610749e8deSXin Chen - Sun Microsystems - Beijing China ASSERT(softs->time_out <= softs->timebase); 66620749e8deSXin Chen - Sun Microsystems - Beijing China softs->time_out = 0; 66630749e8deSXin Chen - Sun Microsystems - Beijing China softs_timebase = softs->timebase; 66640749e8deSXin Chen - Sun Microsystems - Beijing China mutex_exit(&softs->time_mutex); 66650749e8deSXin Chen - Sun Microsystems - Beijing China 66660749e8deSXin Chen - Sun Microsystems - Beijing China /* Check slots for timeout pkts */ 66670749e8deSXin Chen - Sun Microsystems - Beijing China time_adjust = 0; 66680749e8deSXin Chen - Sun Microsystems - Beijing China do { 6669942c5e3cSpl196000 struct aac_cmd *acp; 6670942c5e3cSpl196000 66710749e8deSXin Chen - Sun Microsystems - Beijing China time_out = 0; 66720749e8deSXin Chen - Sun Microsystems - Beijing China for (acp = softs->q_busy.q_head; acp; acp = acp->next) { 66730749e8deSXin Chen - Sun Microsystems - Beijing China if (acp->timeout == 0) 66740749e8deSXin Chen - Sun Microsystems - Beijing China continue; 66750749e8deSXin Chen - Sun Microsystems - Beijing China 66760749e8deSXin Chen - Sun Microsystems - Beijing China /* 66770749e8deSXin Chen - Sun Microsystems - Beijing China * If timeout happened, update outstanding cmds 66780749e8deSXin Chen - Sun Microsystems - Beijing China * to be checked later again. 66790749e8deSXin Chen - Sun Microsystems - Beijing China */ 66800749e8deSXin Chen - Sun Microsystems - Beijing China if (time_adjust) { 66810749e8deSXin Chen - Sun Microsystems - Beijing China acp->timeout += time_adjust; 66820749e8deSXin Chen - Sun Microsystems - Beijing China continue; 66830749e8deSXin Chen - Sun Microsystems - Beijing China } 66840749e8deSXin Chen - Sun Microsystems - Beijing China 66850749e8deSXin Chen - Sun Microsystems - Beijing China if (acp->timeout <= softs_timebase) { 66860749e8deSXin Chen - Sun Microsystems - Beijing China aac_cmd_timeout(softs, acp); 66870749e8deSXin Chen - Sun Microsystems - Beijing China time_out = 1; 66880749e8deSXin Chen - Sun Microsystems - Beijing China time_adjust = aac_tick * drv_usectohz(1000000); 66890749e8deSXin Chen - Sun Microsystems - Beijing China break; /* timeout happened */ 66900749e8deSXin Chen - Sun Microsystems - Beijing China } else { 66910749e8deSXin Chen - Sun Microsystems - Beijing China break; /* no timeout */ 66920749e8deSXin Chen - Sun Microsystems - Beijing China } 66930749e8deSXin Chen - Sun Microsystems - Beijing China } 66940749e8deSXin Chen - Sun Microsystems - Beijing China } while (time_out); 66950749e8deSXin Chen - Sun Microsystems - Beijing China 66960749e8deSXin Chen - Sun Microsystems - Beijing China mutex_enter(&softs->time_mutex); 66970749e8deSXin Chen - Sun Microsystems - Beijing China softs->time_out = softs->timebase + aac_tick; 66980749e8deSXin Chen - Sun Microsystems - Beijing China mutex_exit(&softs->time_mutex); 66990749e8deSXin Chen - Sun Microsystems - Beijing China } 67000749e8deSXin Chen - Sun Microsystems - Beijing China 67010749e8deSXin Chen - Sun Microsystems - Beijing China /* 67020749e8deSXin Chen - Sun Microsystems - Beijing China * The event thread handles various tasks serially for the other parts of 67030749e8deSXin Chen - Sun Microsystems - Beijing China * the driver, so that they can run fast. 67040749e8deSXin Chen - Sun Microsystems - Beijing China */ 67050749e8deSXin Chen - Sun Microsystems - Beijing China static void 67060749e8deSXin Chen - Sun Microsystems - Beijing China aac_event_thread(struct aac_softstate *softs) 67070749e8deSXin Chen - Sun Microsystems - Beijing China { 67080749e8deSXin Chen - Sun Microsystems - Beijing China int run = 1; 67090749e8deSXin Chen - Sun Microsystems - Beijing China 67100749e8deSXin Chen - Sun Microsystems - Beijing China DBCALLED(softs, 1); 67110749e8deSXin Chen - Sun Microsystems - Beijing China 67120749e8deSXin Chen - Sun Microsystems - Beijing China mutex_enter(&softs->ev_lock); 67130749e8deSXin Chen - Sun Microsystems - Beijing China while (run) { 67140749e8deSXin Chen - Sun Microsystems - Beijing China int events; 67150749e8deSXin Chen - Sun Microsystems - Beijing China 67160749e8deSXin Chen - Sun Microsystems - Beijing China if ((events = softs->events) == 0) { 67170749e8deSXin Chen - Sun Microsystems - Beijing China cv_wait(&softs->event_disp_cv, &softs->ev_lock); 67180749e8deSXin Chen - Sun Microsystems - Beijing China events = softs->events; 67190749e8deSXin Chen - Sun Microsystems - Beijing China } 67200749e8deSXin Chen - Sun Microsystems - Beijing China softs->events = 0; 67210749e8deSXin Chen - Sun Microsystems - Beijing China mutex_exit(&softs->ev_lock); 6722942c5e3cSpl196000 6723942c5e3cSpl196000 mutex_enter(&softs->io_lock); 67240749e8deSXin Chen - Sun Microsystems - Beijing China if ((softs->state & AAC_STATE_RUN) && 67250749e8deSXin Chen - Sun Microsystems - Beijing China (softs->state & AAC_STATE_DEAD) == 0) { 67260749e8deSXin Chen - Sun Microsystems - Beijing China if (events & AAC_EVENT_TIMEOUT) 67270749e8deSXin Chen - Sun Microsystems - Beijing China aac_daemon(softs); 67280749e8deSXin Chen - Sun Microsystems - Beijing China if (events & AAC_EVENT_SYNCTICK) 67290749e8deSXin Chen - Sun Microsystems - Beijing China aac_sync_tick(softs); 67300749e8deSXin Chen - Sun Microsystems - Beijing China if (events & AAC_EVENT_AIF) 67310749e8deSXin Chen - Sun Microsystems - Beijing China aac_aif_event(softs); 67320749e8deSXin Chen - Sun Microsystems - Beijing China } else { 67330749e8deSXin Chen - Sun Microsystems - Beijing China run = 0; 6734942c5e3cSpl196000 } 6735942c5e3cSpl196000 mutex_exit(&softs->io_lock); 67360749e8deSXin Chen - Sun Microsystems - Beijing China 67370749e8deSXin Chen - Sun Microsystems - Beijing China mutex_enter(&softs->ev_lock); 67380749e8deSXin Chen - Sun Microsystems - Beijing China } 67390749e8deSXin Chen - Sun Microsystems - Beijing China 67400749e8deSXin Chen - Sun Microsystems - Beijing China cv_signal(&softs->event_wait_cv); 67410749e8deSXin Chen - Sun Microsystems - Beijing China mutex_exit(&softs->ev_lock); 67420749e8deSXin Chen - Sun Microsystems - Beijing China } 67430749e8deSXin Chen - Sun Microsystems - Beijing China 67440749e8deSXin Chen - Sun Microsystems - Beijing China /* 67450749e8deSXin Chen - Sun Microsystems - Beijing China * Internal timer. It is only responsbile for time counting and report time 67460749e8deSXin Chen - Sun Microsystems - Beijing China * related events. Events handling is done by aac_event_thread(), so that 67470749e8deSXin Chen - Sun Microsystems - Beijing China * the timer itself could be as precise as possible. 67480749e8deSXin Chen - Sun Microsystems - Beijing China */ 67490749e8deSXin Chen - Sun Microsystems - Beijing China static void 67500749e8deSXin Chen - Sun Microsystems - Beijing China aac_timer(void *arg) 67510749e8deSXin Chen - Sun Microsystems - Beijing China { 67520749e8deSXin Chen - Sun Microsystems - Beijing China struct aac_softstate *softs = arg; 67530749e8deSXin Chen - Sun Microsystems - Beijing China int events = 0; 67540749e8deSXin Chen - Sun Microsystems - Beijing China 67550749e8deSXin Chen - Sun Microsystems - Beijing China mutex_enter(&softs->time_mutex); 67560749e8deSXin Chen - Sun Microsystems - Beijing China 67570749e8deSXin Chen - Sun Microsystems - Beijing China /* If timer is being stopped, exit */ 67580749e8deSXin Chen - Sun Microsystems - Beijing China if (softs->timeout_id) { 67590749e8deSXin Chen - Sun Microsystems - Beijing China softs->timeout_id = timeout(aac_timer, (void *)softs, 67600749e8deSXin Chen - Sun Microsystems - Beijing China (aac_tick * drv_usectohz(1000000))); 67610749e8deSXin Chen - Sun Microsystems - Beijing China } else { 67620749e8deSXin Chen - Sun Microsystems - Beijing China mutex_exit(&softs->time_mutex); 67630749e8deSXin Chen - Sun Microsystems - Beijing China return; 67640749e8deSXin Chen - Sun Microsystems - Beijing China } 67650749e8deSXin Chen - Sun Microsystems - Beijing China 67660749e8deSXin Chen - Sun Microsystems - Beijing China /* Time counting */ 67670749e8deSXin Chen - Sun Microsystems - Beijing China softs->timebase += aac_tick; 67680749e8deSXin Chen - Sun Microsystems - Beijing China 67690749e8deSXin Chen - Sun Microsystems - Beijing China /* Check time related events */ 67700749e8deSXin Chen - Sun Microsystems - Beijing China if (softs->time_out && softs->time_out <= softs->timebase) 67710749e8deSXin Chen - Sun Microsystems - Beijing China events |= AAC_EVENT_TIMEOUT; 67720749e8deSXin Chen - Sun Microsystems - Beijing China if (softs->time_sync && softs->time_sync <= softs->timebase) 67730749e8deSXin Chen - Sun Microsystems - Beijing China events |= AAC_EVENT_SYNCTICK; 67740749e8deSXin Chen - Sun Microsystems - Beijing China 67750749e8deSXin Chen - Sun Microsystems - Beijing China mutex_exit(&softs->time_mutex); 67760749e8deSXin Chen - Sun Microsystems - Beijing China 67770749e8deSXin Chen - Sun Microsystems - Beijing China if (events) 67780749e8deSXin Chen - Sun Microsystems - Beijing China aac_event_disp(softs, events); 67790749e8deSXin Chen - Sun Microsystems - Beijing China } 67800749e8deSXin Chen - Sun Microsystems - Beijing China 67810749e8deSXin Chen - Sun Microsystems - Beijing China /* 67820749e8deSXin Chen - Sun Microsystems - Beijing China * Dispatch events to daemon thread for handling 67830749e8deSXin Chen - Sun Microsystems - Beijing China */ 67840749e8deSXin Chen - Sun Microsystems - Beijing China static void 67850749e8deSXin Chen - Sun Microsystems - Beijing China aac_event_disp(struct aac_softstate *softs, int events) 67860749e8deSXin Chen - Sun Microsystems - Beijing China { 67870749e8deSXin Chen - Sun Microsystems - Beijing China mutex_enter(&softs->ev_lock); 67880749e8deSXin Chen - Sun Microsystems - Beijing China softs->events |= events; 67890749e8deSXin Chen - Sun Microsystems - Beijing China cv_broadcast(&softs->event_disp_cv); 67900749e8deSXin Chen - Sun Microsystems - Beijing China mutex_exit(&softs->ev_lock); 6791942c5e3cSpl196000 } 6792942c5e3cSpl196000 6793942c5e3cSpl196000 /* 6794942c5e3cSpl196000 * Architecture dependent functions 6795942c5e3cSpl196000 */ 6796942c5e3cSpl196000 static int 6797942c5e3cSpl196000 aac_rx_get_fwstatus(struct aac_softstate *softs) 6798942c5e3cSpl196000 { 6799942c5e3cSpl196000 return (PCI_MEM_GET32(softs, AAC_OMR0)); 6800942c5e3cSpl196000 } 6801942c5e3cSpl196000 6802942c5e3cSpl196000 static int 6803942c5e3cSpl196000 aac_rx_get_mailbox(struct aac_softstate *softs, int mb) 6804942c5e3cSpl196000 { 6805942c5e3cSpl196000 return (PCI_MEM_GET32(softs, AAC_RX_MAILBOX + mb * 4)); 6806942c5e3cSpl196000 } 6807942c5e3cSpl196000 6808942c5e3cSpl196000 static void 6809942c5e3cSpl196000 aac_rx_set_mailbox(struct aac_softstate *softs, uint32_t cmd, 6810942c5e3cSpl196000 uint32_t arg0, uint32_t arg1, uint32_t arg2, uint32_t arg3) 6811942c5e3cSpl196000 { 6812942c5e3cSpl196000 PCI_MEM_PUT32(softs, AAC_RX_MAILBOX, cmd); 6813942c5e3cSpl196000 PCI_MEM_PUT32(softs, AAC_RX_MAILBOX + 4, arg0); 6814942c5e3cSpl196000 PCI_MEM_PUT32(softs, AAC_RX_MAILBOX + 8, arg1); 6815942c5e3cSpl196000 PCI_MEM_PUT32(softs, AAC_RX_MAILBOX + 12, arg2); 6816942c5e3cSpl196000 PCI_MEM_PUT32(softs, AAC_RX_MAILBOX + 16, arg3); 6817942c5e3cSpl196000 } 6818942c5e3cSpl196000 6819942c5e3cSpl196000 static int 6820942c5e3cSpl196000 aac_rkt_get_fwstatus(struct aac_softstate *softs) 6821942c5e3cSpl196000 { 6822942c5e3cSpl196000 return (PCI_MEM_GET32(softs, AAC_OMR0)); 6823942c5e3cSpl196000 } 6824942c5e3cSpl196000 6825942c5e3cSpl196000 static int 6826942c5e3cSpl196000 aac_rkt_get_mailbox(struct aac_softstate *softs, int mb) 6827942c5e3cSpl196000 { 6828942c5e3cSpl196000 return (PCI_MEM_GET32(softs, AAC_RKT_MAILBOX + mb *4)); 6829942c5e3cSpl196000 } 6830942c5e3cSpl196000 6831942c5e3cSpl196000 static void 6832942c5e3cSpl196000 aac_rkt_set_mailbox(struct aac_softstate *softs, uint32_t cmd, 6833942c5e3cSpl196000 uint32_t arg0, uint32_t arg1, uint32_t arg2, uint32_t arg3) 6834942c5e3cSpl196000 { 6835942c5e3cSpl196000 PCI_MEM_PUT32(softs, AAC_RKT_MAILBOX, cmd); 6836942c5e3cSpl196000 PCI_MEM_PUT32(softs, AAC_RKT_MAILBOX + 4, arg0); 6837942c5e3cSpl196000 PCI_MEM_PUT32(softs, AAC_RKT_MAILBOX + 8, arg1); 6838942c5e3cSpl196000 PCI_MEM_PUT32(softs, AAC_RKT_MAILBOX + 12, arg2); 6839942c5e3cSpl196000 PCI_MEM_PUT32(softs, AAC_RKT_MAILBOX + 16, arg3); 6840942c5e3cSpl196000 } 6841942c5e3cSpl196000 6842942c5e3cSpl196000 /* 6843942c5e3cSpl196000 * cb_ops functions 6844942c5e3cSpl196000 */ 6845942c5e3cSpl196000 static int 6846942c5e3cSpl196000 aac_open(dev_t *devp, int flag, int otyp, cred_t *cred) 6847942c5e3cSpl196000 { 6848942c5e3cSpl196000 struct aac_softstate *softs; 6849942c5e3cSpl196000 int minor0, minor; 6850942c5e3cSpl196000 int instance; 6851942c5e3cSpl196000 6852942c5e3cSpl196000 DBCALLED(NULL, 2); 6853942c5e3cSpl196000 6854942c5e3cSpl196000 if (otyp != OTYP_BLK && otyp != OTYP_CHR) 6855942c5e3cSpl196000 return (EINVAL); 6856942c5e3cSpl196000 6857942c5e3cSpl196000 minor0 = getminor(*devp); 6858942c5e3cSpl196000 minor = AAC_SCSA_MINOR(minor0); 6859942c5e3cSpl196000 6860942c5e3cSpl196000 if (AAC_IS_SCSA_NODE(minor)) 6861942c5e3cSpl196000 return (scsi_hba_open(devp, flag, otyp, cred)); 6862942c5e3cSpl196000 6863942c5e3cSpl196000 instance = MINOR2INST(minor0); 6864942c5e3cSpl196000 if (instance >= AAC_MAX_ADAPTERS) 6865942c5e3cSpl196000 return (ENXIO); 6866942c5e3cSpl196000 6867942c5e3cSpl196000 softs = ddi_get_soft_state(aac_softstatep, instance); 6868942c5e3cSpl196000 if (softs == NULL) 6869942c5e3cSpl196000 return (ENXIO); 6870942c5e3cSpl196000 6871942c5e3cSpl196000 return (0); 6872942c5e3cSpl196000 } 6873942c5e3cSpl196000 6874942c5e3cSpl196000 /*ARGSUSED*/ 6875942c5e3cSpl196000 static int 6876942c5e3cSpl196000 aac_close(dev_t dev, int flag, int otyp, cred_t *cred) 6877942c5e3cSpl196000 { 6878942c5e3cSpl196000 int minor0, minor; 6879942c5e3cSpl196000 int instance; 6880942c5e3cSpl196000 6881942c5e3cSpl196000 DBCALLED(NULL, 2); 6882942c5e3cSpl196000 6883942c5e3cSpl196000 if (otyp != OTYP_BLK && otyp != OTYP_CHR) 6884942c5e3cSpl196000 return (EINVAL); 6885942c5e3cSpl196000 6886942c5e3cSpl196000 minor0 = getminor(dev); 6887942c5e3cSpl196000 minor = AAC_SCSA_MINOR(minor0); 6888942c5e3cSpl196000 6889942c5e3cSpl196000 if (AAC_IS_SCSA_NODE(minor)) 6890942c5e3cSpl196000 return (scsi_hba_close(dev, flag, otyp, cred)); 6891942c5e3cSpl196000 6892942c5e3cSpl196000 instance = MINOR2INST(minor0); 6893942c5e3cSpl196000 if (instance >= AAC_MAX_ADAPTERS) 6894942c5e3cSpl196000 return (ENXIO); 6895942c5e3cSpl196000 6896942c5e3cSpl196000 return (0); 6897942c5e3cSpl196000 } 6898942c5e3cSpl196000 6899942c5e3cSpl196000 static int 6900942c5e3cSpl196000 aac_ioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *cred_p, 6901942c5e3cSpl196000 int *rval_p) 6902942c5e3cSpl196000 { 6903942c5e3cSpl196000 struct aac_softstate *softs; 6904942c5e3cSpl196000 int minor0, minor; 6905942c5e3cSpl196000 int instance; 6906942c5e3cSpl196000 6907942c5e3cSpl196000 DBCALLED(NULL, 2); 6908942c5e3cSpl196000 6909942c5e3cSpl196000 if (drv_priv(cred_p) != 0) 6910942c5e3cSpl196000 return (EPERM); 6911942c5e3cSpl196000 6912942c5e3cSpl196000 minor0 = getminor(dev); 6913942c5e3cSpl196000 minor = AAC_SCSA_MINOR(minor0); 6914942c5e3cSpl196000 6915942c5e3cSpl196000 if (AAC_IS_SCSA_NODE(minor)) 6916942c5e3cSpl196000 return (scsi_hba_ioctl(dev, cmd, arg, flag, cred_p, rval_p)); 6917942c5e3cSpl196000 6918942c5e3cSpl196000 instance = MINOR2INST(minor0); 6919942c5e3cSpl196000 if (instance < AAC_MAX_ADAPTERS) { 6920942c5e3cSpl196000 softs = ddi_get_soft_state(aac_softstatep, instance); 6921942c5e3cSpl196000 return (aac_do_ioctl(softs, dev, cmd, arg, flag)); 6922942c5e3cSpl196000 } 6923942c5e3cSpl196000 return (ENXIO); 6924942c5e3cSpl196000 } 6925942c5e3cSpl196000 6926942c5e3cSpl196000 /* 6927942c5e3cSpl196000 * The IO fault service error handling callback function 6928942c5e3cSpl196000 */ 6929942c5e3cSpl196000 /*ARGSUSED*/ 6930942c5e3cSpl196000 static int 6931942c5e3cSpl196000 aac_fm_error_cb(dev_info_t *dip, ddi_fm_error_t *err, const void *impl_data) 6932942c5e3cSpl196000 { 6933942c5e3cSpl196000 /* 6934942c5e3cSpl196000 * as the driver can always deal with an error in any dma or 6935942c5e3cSpl196000 * access handle, we can just return the fme_status value. 6936942c5e3cSpl196000 */ 6937942c5e3cSpl196000 pci_ereport_post(dip, err, NULL); 6938942c5e3cSpl196000 return (err->fme_status); 6939942c5e3cSpl196000 } 6940942c5e3cSpl196000 6941942c5e3cSpl196000 /* 6942942c5e3cSpl196000 * aac_fm_init - initialize fma capabilities and register with IO 6943942c5e3cSpl196000 * fault services. 6944942c5e3cSpl196000 */ 6945942c5e3cSpl196000 static void 6946942c5e3cSpl196000 aac_fm_init(struct aac_softstate *softs) 6947942c5e3cSpl196000 { 6948942c5e3cSpl196000 /* 6949942c5e3cSpl196000 * Need to change iblock to priority for new MSI intr 6950942c5e3cSpl196000 */ 6951942c5e3cSpl196000 ddi_iblock_cookie_t fm_ibc; 6952942c5e3cSpl196000 695358bc78c7SXin Chen softs->fm_capabilities = ddi_getprop(DDI_DEV_T_ANY, softs->devinfo_p, 695458bc78c7SXin Chen DDI_PROP_CANSLEEP | DDI_PROP_DONTPASS, "fm-capable", 695558bc78c7SXin Chen DDI_FM_EREPORT_CAPABLE | DDI_FM_ACCCHK_CAPABLE | 695658bc78c7SXin Chen DDI_FM_DMACHK_CAPABLE | DDI_FM_ERRCB_CAPABLE); 695758bc78c7SXin Chen 6958942c5e3cSpl196000 /* Only register with IO Fault Services if we have some capability */ 6959942c5e3cSpl196000 if (softs->fm_capabilities) { 6960942c5e3cSpl196000 /* Adjust access and dma attributes for FMA */ 6961837c1ac4SStephen Hanson softs->reg_attr.devacc_attr_access = DDI_FLAGERR_ACC; 696258bc78c7SXin Chen softs->addr_dma_attr.dma_attr_flags |= DDI_DMA_FLAGERR; 696358bc78c7SXin Chen softs->buf_dma_attr.dma_attr_flags |= DDI_DMA_FLAGERR; 6964942c5e3cSpl196000 6965942c5e3cSpl196000 /* 6966942c5e3cSpl196000 * Register capabilities with IO Fault Services. 6967942c5e3cSpl196000 * fm_capabilities will be updated to indicate 6968942c5e3cSpl196000 * capabilities actually supported (not requested.) 6969942c5e3cSpl196000 */ 6970942c5e3cSpl196000 ddi_fm_init(softs->devinfo_p, &softs->fm_capabilities, &fm_ibc); 6971942c5e3cSpl196000 6972942c5e3cSpl196000 /* 6973942c5e3cSpl196000 * Initialize pci ereport capabilities if ereport 6974942c5e3cSpl196000 * capable (should always be.) 6975942c5e3cSpl196000 */ 6976942c5e3cSpl196000 if (DDI_FM_EREPORT_CAP(softs->fm_capabilities) || 6977942c5e3cSpl196000 DDI_FM_ERRCB_CAP(softs->fm_capabilities)) { 6978942c5e3cSpl196000 pci_ereport_setup(softs->devinfo_p); 6979942c5e3cSpl196000 } 6980942c5e3cSpl196000 6981942c5e3cSpl196000 /* 6982942c5e3cSpl196000 * Register error callback if error callback capable. 6983942c5e3cSpl196000 */ 6984942c5e3cSpl196000 if (DDI_FM_ERRCB_CAP(softs->fm_capabilities)) { 6985942c5e3cSpl196000 ddi_fm_handler_register(softs->devinfo_p, 6986942c5e3cSpl196000 aac_fm_error_cb, (void *) softs); 6987942c5e3cSpl196000 } 6988942c5e3cSpl196000 } 6989942c5e3cSpl196000 } 6990942c5e3cSpl196000 6991942c5e3cSpl196000 /* 6992942c5e3cSpl196000 * aac_fm_fini - Releases fma capabilities and un-registers with IO 6993942c5e3cSpl196000 * fault services. 6994942c5e3cSpl196000 */ 6995942c5e3cSpl196000 static void 6996942c5e3cSpl196000 aac_fm_fini(struct aac_softstate *softs) 6997942c5e3cSpl196000 { 6998942c5e3cSpl196000 /* Only unregister FMA capabilities if registered */ 6999942c5e3cSpl196000 if (softs->fm_capabilities) { 7000942c5e3cSpl196000 /* 7001942c5e3cSpl196000 * Un-register error callback if error callback capable. 7002942c5e3cSpl196000 */ 7003942c5e3cSpl196000 if (DDI_FM_ERRCB_CAP(softs->fm_capabilities)) { 7004942c5e3cSpl196000 ddi_fm_handler_unregister(softs->devinfo_p); 7005942c5e3cSpl196000 } 7006942c5e3cSpl196000 7007942c5e3cSpl196000 /* 7008942c5e3cSpl196000 * Release any resources allocated by pci_ereport_setup() 7009942c5e3cSpl196000 */ 7010942c5e3cSpl196000 if (DDI_FM_EREPORT_CAP(softs->fm_capabilities) || 7011942c5e3cSpl196000 DDI_FM_ERRCB_CAP(softs->fm_capabilities)) { 7012942c5e3cSpl196000 pci_ereport_teardown(softs->devinfo_p); 7013942c5e3cSpl196000 } 7014942c5e3cSpl196000 7015942c5e3cSpl196000 /* Unregister from IO Fault Services */ 7016942c5e3cSpl196000 ddi_fm_fini(softs->devinfo_p); 701758bc78c7SXin Chen 701858bc78c7SXin Chen /* Adjust access and dma attributes for FMA */ 7019837c1ac4SStephen Hanson softs->reg_attr.devacc_attr_access = DDI_DEFAULT_ACC; 702058bc78c7SXin Chen softs->addr_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR; 702158bc78c7SXin Chen softs->buf_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR; 7022942c5e3cSpl196000 } 7023942c5e3cSpl196000 } 7024942c5e3cSpl196000 7025942c5e3cSpl196000 int 7026942c5e3cSpl196000 aac_check_acc_handle(ddi_acc_handle_t handle) 7027942c5e3cSpl196000 { 7028942c5e3cSpl196000 ddi_fm_error_t de; 7029942c5e3cSpl196000 7030942c5e3cSpl196000 ddi_fm_acc_err_get(handle, &de, DDI_FME_VERSION); 7031942c5e3cSpl196000 return (de.fme_status); 7032942c5e3cSpl196000 } 7033942c5e3cSpl196000 7034942c5e3cSpl196000 int 7035942c5e3cSpl196000 aac_check_dma_handle(ddi_dma_handle_t handle) 7036942c5e3cSpl196000 { 7037942c5e3cSpl196000 ddi_fm_error_t de; 7038942c5e3cSpl196000 7039942c5e3cSpl196000 ddi_fm_dma_err_get(handle, &de, DDI_FME_VERSION); 7040942c5e3cSpl196000 return (de.fme_status); 7041942c5e3cSpl196000 } 7042942c5e3cSpl196000 7043942c5e3cSpl196000 void 7044942c5e3cSpl196000 aac_fm_ereport(struct aac_softstate *softs, char *detail) 7045942c5e3cSpl196000 { 7046942c5e3cSpl196000 uint64_t ena; 7047942c5e3cSpl196000 char buf[FM_MAX_CLASS]; 7048942c5e3cSpl196000 7049942c5e3cSpl196000 (void) snprintf(buf, FM_MAX_CLASS, "%s.%s", DDI_FM_DEVICE, detail); 7050942c5e3cSpl196000 ena = fm_ena_generate(0, FM_ENA_FMT1); 7051942c5e3cSpl196000 if (DDI_FM_EREPORT_CAP(softs->fm_capabilities)) { 7052942c5e3cSpl196000 ddi_fm_ereport_post(softs->devinfo_p, buf, ena, DDI_NOSLEEP, 7053942c5e3cSpl196000 FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERSION, NULL); 7054942c5e3cSpl196000 } 7055942c5e3cSpl196000 } 7056942c5e3cSpl196000 705758bc78c7SXin Chen /* 705858bc78c7SXin Chen * Autoconfiguration support 705958bc78c7SXin Chen */ 706058bc78c7SXin Chen static int 706158bc78c7SXin Chen aac_parse_devname(char *devnm, int *tgt, int *lun) 706258bc78c7SXin Chen { 706358bc78c7SXin Chen char devbuf[SCSI_MAXNAMELEN]; 706458bc78c7SXin Chen char *addr; 706558bc78c7SXin Chen char *p, *tp, *lp; 706658bc78c7SXin Chen long num; 706758bc78c7SXin Chen 706858bc78c7SXin Chen /* Parse dev name and address */ 706958bc78c7SXin Chen (void) strcpy(devbuf, devnm); 707058bc78c7SXin Chen addr = ""; 707158bc78c7SXin Chen for (p = devbuf; *p != '\0'; p++) { 707258bc78c7SXin Chen if (*p == '@') { 707358bc78c7SXin Chen addr = p + 1; 707458bc78c7SXin Chen *p = '\0'; 707558bc78c7SXin Chen } else if (*p == ':') { 707658bc78c7SXin Chen *p = '\0'; 707758bc78c7SXin Chen break; 707858bc78c7SXin Chen } 707958bc78c7SXin Chen } 708058bc78c7SXin Chen 708158bc78c7SXin Chen /* Parse taget and lun */ 708258bc78c7SXin Chen for (p = tp = addr, lp = NULL; *p != '\0'; p++) { 708358bc78c7SXin Chen if (*p == ',') { 708458bc78c7SXin Chen lp = p + 1; 708558bc78c7SXin Chen *p = '\0'; 708658bc78c7SXin Chen break; 708758bc78c7SXin Chen } 708858bc78c7SXin Chen } 708958bc78c7SXin Chen if (tgt && tp) { 709058bc78c7SXin Chen if (ddi_strtol(tp, NULL, 0x10, &num)) 709158bc78c7SXin Chen return (AACERR); 709258bc78c7SXin Chen *tgt = (int)num; 709358bc78c7SXin Chen } 709458bc78c7SXin Chen if (lun && lp) { 709558bc78c7SXin Chen if (ddi_strtol(lp, NULL, 0x10, &num)) 709658bc78c7SXin Chen return (AACERR); 709758bc78c7SXin Chen *lun = (int)num; 709858bc78c7SXin Chen } 709958bc78c7SXin Chen return (AACOK); 710058bc78c7SXin Chen } 710158bc78c7SXin Chen 710258bc78c7SXin Chen static dev_info_t * 710358bc78c7SXin Chen aac_find_child(struct aac_softstate *softs, uint16_t tgt, uint8_t lun) 710458bc78c7SXin Chen { 710558bc78c7SXin Chen dev_info_t *child = NULL; 710658bc78c7SXin Chen char addr[SCSI_MAXNAMELEN]; 710758bc78c7SXin Chen char tmp[MAXNAMELEN]; 710858bc78c7SXin Chen 710958bc78c7SXin Chen if (tgt < AAC_MAX_LD) { 711058bc78c7SXin Chen if (lun == 0) { 711158bc78c7SXin Chen struct aac_device *dvp = &softs->containers[tgt].dev; 711258bc78c7SXin Chen 711358bc78c7SXin Chen child = dvp->dip; 711458bc78c7SXin Chen } 711558bc78c7SXin Chen } else { 711658bc78c7SXin Chen (void) sprintf(addr, "%x,%x", tgt, lun); 711758bc78c7SXin Chen for (child = ddi_get_child(softs->devinfo_p); 711858bc78c7SXin Chen child; child = ddi_get_next_sibling(child)) { 711958bc78c7SXin Chen /* We don't care about non-persistent node */ 712058bc78c7SXin Chen if (ndi_dev_is_persistent_node(child) == 0) 712158bc78c7SXin Chen continue; 712258bc78c7SXin Chen 712358bc78c7SXin Chen if (aac_name_node(child, tmp, MAXNAMELEN) != 712458bc78c7SXin Chen DDI_SUCCESS) 712558bc78c7SXin Chen continue; 712658bc78c7SXin Chen if (strcmp(addr, tmp) == 0) 712758bc78c7SXin Chen break; 712858bc78c7SXin Chen } 712958bc78c7SXin Chen } 713058bc78c7SXin Chen return (child); 713158bc78c7SXin Chen } 713258bc78c7SXin Chen 713358bc78c7SXin Chen static int 713458bc78c7SXin Chen aac_config_child(struct aac_softstate *softs, struct scsi_device *sd, 713558bc78c7SXin Chen dev_info_t **dipp) 713658bc78c7SXin Chen { 713758bc78c7SXin Chen char *nodename = NULL; 713858bc78c7SXin Chen char **compatible = NULL; 713958bc78c7SXin Chen int ncompatible = 0; 714058bc78c7SXin Chen char *childname; 714158bc78c7SXin Chen dev_info_t *ldip = NULL; 714258bc78c7SXin Chen int tgt = sd->sd_address.a_target; 714358bc78c7SXin Chen int lun = sd->sd_address.a_lun; 714458bc78c7SXin Chen int dtype = sd->sd_inq->inq_dtype & DTYPE_MASK; 714558bc78c7SXin Chen int rval; 714658bc78c7SXin Chen 714758bc78c7SXin Chen DBCALLED(softs, 2); 714858bc78c7SXin Chen 714958bc78c7SXin Chen scsi_hba_nodename_compatible_get(sd->sd_inq, NULL, dtype, 715058bc78c7SXin Chen NULL, &nodename, &compatible, &ncompatible); 715158bc78c7SXin Chen if (nodename == NULL) { 715258bc78c7SXin Chen AACDB_PRINT(softs, CE_WARN, 715358bc78c7SXin Chen "found no comptible driver for t%dL%d", tgt, lun); 715458bc78c7SXin Chen rval = NDI_FAILURE; 715558bc78c7SXin Chen goto finish; 715658bc78c7SXin Chen } 715758bc78c7SXin Chen childname = (softs->legacy && dtype == DTYPE_DIRECT) ? "sd" : nodename; 715858bc78c7SXin Chen 715958bc78c7SXin Chen /* Create dev node */ 716058bc78c7SXin Chen rval = ndi_devi_alloc(softs->devinfo_p, childname, DEVI_SID_NODEID, 716158bc78c7SXin Chen &ldip); 716258bc78c7SXin Chen if (rval == NDI_SUCCESS) { 716358bc78c7SXin Chen if (ndi_prop_update_int(DDI_DEV_T_NONE, ldip, "target", tgt) 716458bc78c7SXin Chen != DDI_PROP_SUCCESS) { 716558bc78c7SXin Chen AACDB_PRINT(softs, CE_WARN, "unable to create " 716658bc78c7SXin Chen "property for t%dL%d (target)", tgt, lun); 716758bc78c7SXin Chen rval = NDI_FAILURE; 716858bc78c7SXin Chen goto finish; 716958bc78c7SXin Chen } 717058bc78c7SXin Chen if (ndi_prop_update_int(DDI_DEV_T_NONE, ldip, "lun", lun) 717158bc78c7SXin Chen != DDI_PROP_SUCCESS) { 717258bc78c7SXin Chen AACDB_PRINT(softs, CE_WARN, "unable to create " 717358bc78c7SXin Chen "property for t%dL%d (lun)", tgt, lun); 717458bc78c7SXin Chen rval = NDI_FAILURE; 717558bc78c7SXin Chen goto finish; 717658bc78c7SXin Chen } 717758bc78c7SXin Chen if (ndi_prop_update_string_array(DDI_DEV_T_NONE, ldip, 717858bc78c7SXin Chen "compatible", compatible, ncompatible) 717958bc78c7SXin Chen != DDI_PROP_SUCCESS) { 718058bc78c7SXin Chen AACDB_PRINT(softs, CE_WARN, "unable to create " 718158bc78c7SXin Chen "property for t%dL%d (compatible)", tgt, lun); 718258bc78c7SXin Chen rval = NDI_FAILURE; 718358bc78c7SXin Chen goto finish; 718458bc78c7SXin Chen } 718558bc78c7SXin Chen 718658bc78c7SXin Chen rval = ndi_devi_online(ldip, NDI_ONLINE_ATTACH); 718758bc78c7SXin Chen if (rval != NDI_SUCCESS) { 718858bc78c7SXin Chen AACDB_PRINT(softs, CE_WARN, "unable to online t%dL%d", 718958bc78c7SXin Chen tgt, lun); 719058bc78c7SXin Chen ndi_prop_remove_all(ldip); 719158bc78c7SXin Chen (void) ndi_devi_free(ldip); 719258bc78c7SXin Chen } 719358bc78c7SXin Chen } 719458bc78c7SXin Chen finish: 719558bc78c7SXin Chen if (dipp) 719658bc78c7SXin Chen *dipp = ldip; 719758bc78c7SXin Chen 719858bc78c7SXin Chen scsi_hba_nodename_compatible_free(nodename, compatible); 719958bc78c7SXin Chen return (rval); 720058bc78c7SXin Chen } 720158bc78c7SXin Chen 720258bc78c7SXin Chen /*ARGSUSED*/ 720358bc78c7SXin Chen static int 720458bc78c7SXin Chen aac_probe_lun(struct aac_softstate *softs, struct scsi_device *sd) 720558bc78c7SXin Chen { 720658bc78c7SXin Chen int tgt = sd->sd_address.a_target; 720758bc78c7SXin Chen int lun = sd->sd_address.a_lun; 720858bc78c7SXin Chen 720958bc78c7SXin Chen DBCALLED(softs, 2); 721058bc78c7SXin Chen 721158bc78c7SXin Chen if (tgt < AAC_MAX_LD) { 72120749e8deSXin Chen - Sun Microsystems - Beijing China enum aac_cfg_event event; 721358bc78c7SXin Chen 721458bc78c7SXin Chen if (lun == 0) { 721558bc78c7SXin Chen mutex_enter(&softs->io_lock); 72160749e8deSXin Chen - Sun Microsystems - Beijing China event = aac_probe_container(softs, tgt); 721758bc78c7SXin Chen mutex_exit(&softs->io_lock); 72180749e8deSXin Chen - Sun Microsystems - Beijing China if ((event != AAC_CFG_NULL_NOEXIST) && 72190749e8deSXin Chen - Sun Microsystems - Beijing China (event != AAC_CFG_DELETE)) { 722058bc78c7SXin Chen if (scsi_hba_probe(sd, NULL) == 722158bc78c7SXin Chen SCSIPROBE_EXISTS) 722258bc78c7SXin Chen return (NDI_SUCCESS); 722358bc78c7SXin Chen } 722458bc78c7SXin Chen } 722558bc78c7SXin Chen return (NDI_FAILURE); 722658bc78c7SXin Chen } else { 722758bc78c7SXin Chen int dtype; 72283fced439Szhongyan gu - Sun Microsystems - Beijing China int qual; /* device qualifier */ 722958bc78c7SXin Chen 723058bc78c7SXin Chen if (scsi_hba_probe(sd, NULL) != SCSIPROBE_EXISTS) 723158bc78c7SXin Chen return (NDI_FAILURE); 723258bc78c7SXin Chen 723358bc78c7SXin Chen dtype = sd->sd_inq->inq_dtype & DTYPE_MASK; 72343fced439Szhongyan gu - Sun Microsystems - Beijing China qual = dtype >> 5; 723558bc78c7SXin Chen 723658bc78c7SXin Chen AACDB_PRINT(softs, CE_NOTE, 723758bc78c7SXin Chen "Phys. device found: tgt %d dtype %d: %s", 723858bc78c7SXin Chen tgt, dtype, sd->sd_inq->inq_vid); 723958bc78c7SXin Chen 72403fced439Szhongyan gu - Sun Microsystems - Beijing China /* Only non-DASD and JBOD mode DASD are allowed exposed */ 72413fced439Szhongyan gu - Sun Microsystems - Beijing China if (dtype == DTYPE_RODIRECT /* CDROM */ || 72423fced439Szhongyan gu - Sun Microsystems - Beijing China dtype == DTYPE_SEQUENTIAL /* TAPE */ || 72433fced439Szhongyan gu - Sun Microsystems - Beijing China dtype == DTYPE_ESI /* SES */) { 72443fced439Szhongyan gu - Sun Microsystems - Beijing China if (!(softs->flags & AAC_FLAGS_NONDASD)) 724558bc78c7SXin Chen return (NDI_FAILURE); 724658bc78c7SXin Chen AACDB_PRINT(softs, CE_NOTE, "non-DASD %d found", tgt); 72473fced439Szhongyan gu - Sun Microsystems - Beijing China 72483fced439Szhongyan gu - Sun Microsystems - Beijing China } else if (dtype == DTYPE_DIRECT) { 72493fced439Szhongyan gu - Sun Microsystems - Beijing China if (!(softs->flags & AAC_FLAGS_JBOD) || qual != 0) 72503fced439Szhongyan gu - Sun Microsystems - Beijing China return (NDI_FAILURE); 72513fced439Szhongyan gu - Sun Microsystems - Beijing China AACDB_PRINT(softs, CE_NOTE, "JBOD DASD %d found", tgt); 72523fced439Szhongyan gu - Sun Microsystems - Beijing China } 72533fced439Szhongyan gu - Sun Microsystems - Beijing China 725458bc78c7SXin Chen mutex_enter(&softs->io_lock); 725558bc78c7SXin Chen softs->nondasds[AAC_PD(tgt)].dev.flags |= AAC_DFLAG_VALID; 725658bc78c7SXin Chen mutex_exit(&softs->io_lock); 725758bc78c7SXin Chen return (NDI_SUCCESS); 725858bc78c7SXin Chen } 725958bc78c7SXin Chen } 726058bc78c7SXin Chen 726158bc78c7SXin Chen static int 726258bc78c7SXin Chen aac_config_lun(struct aac_softstate *softs, uint16_t tgt, uint8_t lun, 726358bc78c7SXin Chen dev_info_t **ldip) 726458bc78c7SXin Chen { 726558bc78c7SXin Chen struct scsi_device sd; 726658bc78c7SXin Chen dev_info_t *child; 726758bc78c7SXin Chen int rval; 726858bc78c7SXin Chen 726958bc78c7SXin Chen DBCALLED(softs, 2); 727058bc78c7SXin Chen 727158bc78c7SXin Chen if ((child = aac_find_child(softs, tgt, lun)) != NULL) { 727258bc78c7SXin Chen if (ldip) 727358bc78c7SXin Chen *ldip = child; 727458bc78c7SXin Chen return (NDI_SUCCESS); 727558bc78c7SXin Chen } 727658bc78c7SXin Chen 727758bc78c7SXin Chen bzero(&sd, sizeof (struct scsi_device)); 727858bc78c7SXin Chen sd.sd_address.a_hba_tran = softs->hba_tran; 727958bc78c7SXin Chen sd.sd_address.a_target = (uint16_t)tgt; 728058bc78c7SXin Chen sd.sd_address.a_lun = (uint8_t)lun; 728158bc78c7SXin Chen if ((rval = aac_probe_lun(softs, &sd)) == NDI_SUCCESS) 728258bc78c7SXin Chen rval = aac_config_child(softs, &sd, ldip); 7283f42c2f53Szhongyan gu - Sun Microsystems - Beijing China /* scsi_unprobe is blank now. Free buffer manually */ 7284f42c2f53Szhongyan gu - Sun Microsystems - Beijing China if (sd.sd_inq) { 7285f42c2f53Szhongyan gu - Sun Microsystems - Beijing China kmem_free(sd.sd_inq, SUN_INQSIZE); 7286f42c2f53Szhongyan gu - Sun Microsystems - Beijing China sd.sd_inq = (struct scsi_inquiry *)NULL; 7287f42c2f53Szhongyan gu - Sun Microsystems - Beijing China } 728858bc78c7SXin Chen return (rval); 728958bc78c7SXin Chen } 729058bc78c7SXin Chen 729158bc78c7SXin Chen static int 729258bc78c7SXin Chen aac_config_tgt(struct aac_softstate *softs, int tgt) 729358bc78c7SXin Chen { 729458bc78c7SXin Chen struct scsi_address ap; 729558bc78c7SXin Chen struct buf *bp = NULL; 729658bc78c7SXin Chen int buf_len = AAC_SCSI_RPTLUNS_HEAD_SIZE + AAC_SCSI_RPTLUNS_ADDR_SIZE; 729758bc78c7SXin Chen int list_len = 0; 729858bc78c7SXin Chen int lun_total = 0; 729958bc78c7SXin Chen dev_info_t *ldip; 730058bc78c7SXin Chen int i; 730158bc78c7SXin Chen 730258bc78c7SXin Chen ap.a_hba_tran = softs->hba_tran; 730358bc78c7SXin Chen ap.a_target = (uint16_t)tgt; 730458bc78c7SXin Chen ap.a_lun = 0; 730558bc78c7SXin Chen 730658bc78c7SXin Chen for (i = 0; i < 2; i++) { 730758bc78c7SXin Chen struct scsi_pkt *pkt; 730858bc78c7SXin Chen uchar_t *cdb; 730958bc78c7SXin Chen uchar_t *p; 731058bc78c7SXin Chen uint32_t data; 731158bc78c7SXin Chen 731258bc78c7SXin Chen if (bp == NULL) { 731358bc78c7SXin Chen if ((bp = scsi_alloc_consistent_buf(&ap, NULL, 731458bc78c7SXin Chen buf_len, B_READ, NULL_FUNC, NULL)) == NULL) 731558bc78c7SXin Chen return (AACERR); 731658bc78c7SXin Chen } 731758bc78c7SXin Chen if ((pkt = scsi_init_pkt(&ap, NULL, bp, CDB_GROUP5, 731858bc78c7SXin Chen sizeof (struct scsi_arq_status), 0, PKT_CONSISTENT, 731958bc78c7SXin Chen NULL, NULL)) == NULL) { 732058bc78c7SXin Chen scsi_free_consistent_buf(bp); 732158bc78c7SXin Chen return (AACERR); 732258bc78c7SXin Chen } 732358bc78c7SXin Chen cdb = pkt->pkt_cdbp; 732458bc78c7SXin Chen bzero(cdb, CDB_GROUP5); 732558bc78c7SXin Chen cdb[0] = SCMD_REPORT_LUNS; 732658bc78c7SXin Chen 732758bc78c7SXin Chen /* Convert buffer len from local to LE_32 */ 732858bc78c7SXin Chen data = buf_len; 732958bc78c7SXin Chen for (p = &cdb[9]; p > &cdb[5]; p--) { 733058bc78c7SXin Chen *p = data & 0xff; 733158bc78c7SXin Chen data >>= 8; 733258bc78c7SXin Chen } 733358bc78c7SXin Chen 733458bc78c7SXin Chen if (scsi_poll(pkt) < 0 || 733558bc78c7SXin Chen ((struct scsi_status *)pkt->pkt_scbp)->sts_chk) { 733658bc78c7SXin Chen scsi_destroy_pkt(pkt); 733758bc78c7SXin Chen break; 733858bc78c7SXin Chen } 733958bc78c7SXin Chen 734058bc78c7SXin Chen /* Convert list_len from LE_32 to local */ 734158bc78c7SXin Chen for (p = (uchar_t *)bp->b_un.b_addr; 734258bc78c7SXin Chen p < (uchar_t *)bp->b_un.b_addr + 4; p++) { 734358bc78c7SXin Chen data <<= 8; 734458bc78c7SXin Chen data |= *p; 734558bc78c7SXin Chen } 734658bc78c7SXin Chen list_len = data; 734758bc78c7SXin Chen if (buf_len < list_len + AAC_SCSI_RPTLUNS_HEAD_SIZE) { 734858bc78c7SXin Chen scsi_free_consistent_buf(bp); 734958bc78c7SXin Chen bp = NULL; 735058bc78c7SXin Chen buf_len = list_len + AAC_SCSI_RPTLUNS_HEAD_SIZE; 735158bc78c7SXin Chen } 735258bc78c7SXin Chen scsi_destroy_pkt(pkt); 735358bc78c7SXin Chen } 735458bc78c7SXin Chen if (i >= 2) { 735558bc78c7SXin Chen uint8_t *buf = (uint8_t *)(bp->b_un.b_addr + 735658bc78c7SXin Chen AAC_SCSI_RPTLUNS_HEAD_SIZE); 735758bc78c7SXin Chen 735858bc78c7SXin Chen for (i = 0; i < (list_len / AAC_SCSI_RPTLUNS_ADDR_SIZE); i++) { 735958bc78c7SXin Chen uint16_t lun; 736058bc78c7SXin Chen 736158bc78c7SXin Chen /* Determine report luns addressing type */ 736258bc78c7SXin Chen switch (buf[0] & AAC_SCSI_RPTLUNS_ADDR_MASK) { 736358bc78c7SXin Chen /* 736458bc78c7SXin Chen * Vendors in the field have been found to be 736558bc78c7SXin Chen * concatenating bus/target/lun to equal the 736658bc78c7SXin Chen * complete lun value instead of switching to 736758bc78c7SXin Chen * flat space addressing 736858bc78c7SXin Chen */ 736958bc78c7SXin Chen case AAC_SCSI_RPTLUNS_ADDR_PERIPHERAL: 737058bc78c7SXin Chen case AAC_SCSI_RPTLUNS_ADDR_LOGICAL_UNIT: 737158bc78c7SXin Chen case AAC_SCSI_RPTLUNS_ADDR_FLAT_SPACE: 737258bc78c7SXin Chen lun = ((buf[0] & 0x3f) << 8) | buf[1]; 737358bc78c7SXin Chen if (lun > UINT8_MAX) { 737458bc78c7SXin Chen AACDB_PRINT(softs, CE_WARN, 737558bc78c7SXin Chen "abnormal lun number: %d", lun); 737658bc78c7SXin Chen break; 737758bc78c7SXin Chen } 737858bc78c7SXin Chen if (aac_config_lun(softs, tgt, lun, &ldip) == 737958bc78c7SXin Chen NDI_SUCCESS) 738058bc78c7SXin Chen lun_total++; 738158bc78c7SXin Chen break; 738258bc78c7SXin Chen } 738358bc78c7SXin Chen 738458bc78c7SXin Chen buf += AAC_SCSI_RPTLUNS_ADDR_SIZE; 738558bc78c7SXin Chen } 738658bc78c7SXin Chen } else { 738758bc78c7SXin Chen /* The target may do not support SCMD_REPORT_LUNS. */ 738858bc78c7SXin Chen if (aac_config_lun(softs, tgt, 0, &ldip) == NDI_SUCCESS) 738958bc78c7SXin Chen lun_total++; 739058bc78c7SXin Chen } 739158bc78c7SXin Chen scsi_free_consistent_buf(bp); 739258bc78c7SXin Chen return (lun_total); 739358bc78c7SXin Chen } 739458bc78c7SXin Chen 739558bc78c7SXin Chen static void 739658bc78c7SXin Chen aac_devcfg(struct aac_softstate *softs, int tgt, int en) 739758bc78c7SXin Chen { 739858bc78c7SXin Chen struct aac_device *dvp; 739958bc78c7SXin Chen 740058bc78c7SXin Chen mutex_enter(&softs->io_lock); 740158bc78c7SXin Chen dvp = AAC_DEV(softs, tgt); 740258bc78c7SXin Chen if (en) 740358bc78c7SXin Chen dvp->flags |= AAC_DFLAG_CONFIGURING; 740458bc78c7SXin Chen else 740558bc78c7SXin Chen dvp->flags &= ~AAC_DFLAG_CONFIGURING; 740658bc78c7SXin Chen mutex_exit(&softs->io_lock); 740758bc78c7SXin Chen } 740858bc78c7SXin Chen 740958bc78c7SXin Chen static int 741058bc78c7SXin Chen aac_tran_bus_config(dev_info_t *parent, uint_t flags, ddi_bus_config_op_t op, 741158bc78c7SXin Chen void *arg, dev_info_t **childp) 741258bc78c7SXin Chen { 741358bc78c7SXin Chen struct aac_softstate *softs; 741458bc78c7SXin Chen int circ = 0; 741558bc78c7SXin Chen int rval; 741658bc78c7SXin Chen 741758bc78c7SXin Chen if ((softs = ddi_get_soft_state(aac_softstatep, 741858bc78c7SXin Chen ddi_get_instance(parent))) == NULL) 741958bc78c7SXin Chen return (NDI_FAILURE); 742058bc78c7SXin Chen 742158bc78c7SXin Chen /* Commands for bus config should be blocked as the bus is quiesced */ 742258bc78c7SXin Chen mutex_enter(&softs->io_lock); 742358bc78c7SXin Chen if (softs->state & AAC_STATE_QUIESCED) { 742458bc78c7SXin Chen AACDB_PRINT(softs, CE_NOTE, 742558bc78c7SXin Chen "bus_config abroted because bus is quiesced"); 742658bc78c7SXin Chen mutex_exit(&softs->io_lock); 742758bc78c7SXin Chen return (NDI_FAILURE); 742858bc78c7SXin Chen } 742958bc78c7SXin Chen mutex_exit(&softs->io_lock); 743058bc78c7SXin Chen 743158bc78c7SXin Chen DBCALLED(softs, 1); 743258bc78c7SXin Chen 743358bc78c7SXin Chen /* Hold the nexus across the bus_config */ 743458bc78c7SXin Chen ndi_devi_enter(parent, &circ); 743558bc78c7SXin Chen switch (op) { 743658bc78c7SXin Chen case BUS_CONFIG_ONE: { 743758bc78c7SXin Chen int tgt, lun; 743858bc78c7SXin Chen 743958bc78c7SXin Chen if (aac_parse_devname(arg, &tgt, &lun) != AACOK) { 744058bc78c7SXin Chen rval = NDI_FAILURE; 744158bc78c7SXin Chen break; 744258bc78c7SXin Chen } 74433fced439Szhongyan gu - Sun Microsystems - Beijing China if (tgt >= AAC_MAX_LD) { 74443fced439Szhongyan gu - Sun Microsystems - Beijing China if (tgt >= AAC_MAX_DEV(softs)) { 74453fced439Szhongyan gu - Sun Microsystems - Beijing China rval = NDI_FAILURE; 74463fced439Szhongyan gu - Sun Microsystems - Beijing China break; 74473fced439Szhongyan gu - Sun Microsystems - Beijing China } 74483fced439Szhongyan gu - Sun Microsystems - Beijing China } 744958bc78c7SXin Chen 745058bc78c7SXin Chen AAC_DEVCFG_BEGIN(softs, tgt); 745158bc78c7SXin Chen rval = aac_config_lun(softs, tgt, lun, childp); 745258bc78c7SXin Chen AAC_DEVCFG_END(softs, tgt); 745358bc78c7SXin Chen break; 745458bc78c7SXin Chen } 745558bc78c7SXin Chen 745658bc78c7SXin Chen case BUS_CONFIG_DRIVER: 745758bc78c7SXin Chen case BUS_CONFIG_ALL: { 745858bc78c7SXin Chen uint32_t bus, tgt; 745958bc78c7SXin Chen int index, total; 746058bc78c7SXin Chen 746158bc78c7SXin Chen for (tgt = 0; tgt < AAC_MAX_LD; tgt++) { 746258bc78c7SXin Chen AAC_DEVCFG_BEGIN(softs, tgt); 746358bc78c7SXin Chen (void) aac_config_lun(softs, tgt, 0, NULL); 746458bc78c7SXin Chen AAC_DEVCFG_END(softs, tgt); 746558bc78c7SXin Chen } 746658bc78c7SXin Chen 746758bc78c7SXin Chen /* Config the non-DASD devices connected to the card */ 746858bc78c7SXin Chen total = 0; 746958bc78c7SXin Chen index = AAC_MAX_LD; 747058bc78c7SXin Chen for (bus = 0; bus < softs->bus_max; bus++) { 747158bc78c7SXin Chen AACDB_PRINT(softs, CE_NOTE, "bus %d:", bus); 747258bc78c7SXin Chen for (tgt = 0; tgt < softs->tgt_max; tgt++, index++) { 747358bc78c7SXin Chen AAC_DEVCFG_BEGIN(softs, index); 747458bc78c7SXin Chen if (aac_config_tgt(softs, index)) 747558bc78c7SXin Chen total++; 747658bc78c7SXin Chen AAC_DEVCFG_END(softs, index); 747758bc78c7SXin Chen } 747858bc78c7SXin Chen } 747958bc78c7SXin Chen AACDB_PRINT(softs, CE_CONT, 748058bc78c7SXin Chen "?Total %d phys. device(s) found", total); 748158bc78c7SXin Chen rval = NDI_SUCCESS; 748258bc78c7SXin Chen break; 748358bc78c7SXin Chen } 748458bc78c7SXin Chen } 748558bc78c7SXin Chen 748658bc78c7SXin Chen if (rval == NDI_SUCCESS) 748758bc78c7SXin Chen rval = ndi_busop_bus_config(parent, flags, op, arg, childp, 0); 748858bc78c7SXin Chen ndi_devi_exit(parent, circ); 748958bc78c7SXin Chen return (rval); 749058bc78c7SXin Chen } 749158bc78c7SXin Chen 74920749e8deSXin Chen - Sun Microsystems - Beijing China /*ARGSUSED*/ 74930749e8deSXin Chen - Sun Microsystems - Beijing China static int 74940749e8deSXin Chen - Sun Microsystems - Beijing China aac_handle_dr(struct aac_softstate *softs, int tgt, int lun, int event) 749558bc78c7SXin Chen { 749658bc78c7SXin Chen struct aac_device *dvp; 749758bc78c7SXin Chen dev_info_t *dip; 749858bc78c7SXin Chen int valid; 749958bc78c7SXin Chen int circ1 = 0; 750058bc78c7SXin Chen 750158bc78c7SXin Chen DBCALLED(softs, 1); 750258bc78c7SXin Chen 750358bc78c7SXin Chen /* Hold the nexus across the bus_config */ 75040749e8deSXin Chen - Sun Microsystems - Beijing China dvp = AAC_DEV(softs, tgt); 750558bc78c7SXin Chen valid = AAC_DEV_IS_VALID(dvp); 750658bc78c7SXin Chen dip = dvp->dip; 75070749e8deSXin Chen - Sun Microsystems - Beijing China if (!(softs->state & AAC_STATE_RUN)) 75080749e8deSXin Chen - Sun Microsystems - Beijing China return (AACERR); 750958bc78c7SXin Chen mutex_exit(&softs->io_lock); 751058bc78c7SXin Chen 75110749e8deSXin Chen - Sun Microsystems - Beijing China switch (event) { 75120749e8deSXin Chen - Sun Microsystems - Beijing China case AAC_CFG_ADD: 75130749e8deSXin Chen - Sun Microsystems - Beijing China case AAC_CFG_DELETE: 751458bc78c7SXin Chen /* Device onlined */ 751558bc78c7SXin Chen if (dip == NULL && valid) { 751658bc78c7SXin Chen ndi_devi_enter(softs->devinfo_p, &circ1); 75170749e8deSXin Chen - Sun Microsystems - Beijing China (void) aac_config_lun(softs, tgt, 0, NULL); 751858bc78c7SXin Chen AACDB_PRINT(softs, CE_NOTE, "c%dt%dL%d onlined", 75190749e8deSXin Chen - Sun Microsystems - Beijing China softs->instance, tgt, lun); 752058bc78c7SXin Chen ndi_devi_exit(softs->devinfo_p, circ1); 752158bc78c7SXin Chen } 752258bc78c7SXin Chen /* Device offlined */ 752358bc78c7SXin Chen if (dip && !valid) { 752458bc78c7SXin Chen mutex_enter(&softs->io_lock); 752558bc78c7SXin Chen (void) aac_do_reset(softs); 752658bc78c7SXin Chen mutex_exit(&softs->io_lock); 752758bc78c7SXin Chen 752858bc78c7SXin Chen (void) ndi_devi_offline(dip, NDI_DEVI_REMOVE); 752958bc78c7SXin Chen AACDB_PRINT(softs, CE_NOTE, "c%dt%dL%d offlined", 75300749e8deSXin Chen - Sun Microsystems - Beijing China softs->instance, tgt, lun); 753158bc78c7SXin Chen } 753258bc78c7SXin Chen break; 753358bc78c7SXin Chen } 753458bc78c7SXin Chen 75350749e8deSXin Chen - Sun Microsystems - Beijing China mutex_enter(&softs->io_lock); 753658bc78c7SXin Chen return (AACOK); 753758bc78c7SXin Chen } 753858bc78c7SXin Chen 7539942c5e3cSpl196000 #ifdef DEBUG 7540942c5e3cSpl196000 7541942c5e3cSpl196000 /* -------------------------debug aid functions-------------------------- */ 7542942c5e3cSpl196000 7543942c5e3cSpl196000 #define AAC_FIB_CMD_KEY_STRINGS \ 7544942c5e3cSpl196000 TestCommandResponse, "TestCommandResponse", \ 7545942c5e3cSpl196000 TestAdapterCommand, "TestAdapterCommand", \ 7546942c5e3cSpl196000 LastTestCommand, "LastTestCommand", \ 7547942c5e3cSpl196000 ReinitHostNormCommandQueue, "ReinitHostNormCommandQueue", \ 7548942c5e3cSpl196000 ReinitHostHighCommandQueue, "ReinitHostHighCommandQueue", \ 7549942c5e3cSpl196000 ReinitHostHighRespQueue, "ReinitHostHighRespQueue", \ 7550942c5e3cSpl196000 ReinitHostNormRespQueue, "ReinitHostNormRespQueue", \ 7551942c5e3cSpl196000 ReinitAdapNormCommandQueue, "ReinitAdapNormCommandQueue", \ 7552942c5e3cSpl196000 ReinitAdapHighCommandQueue, "ReinitAdapHighCommandQueue", \ 7553942c5e3cSpl196000 ReinitAdapHighRespQueue, "ReinitAdapHighRespQueue", \ 7554942c5e3cSpl196000 ReinitAdapNormRespQueue, "ReinitAdapNormRespQueue", \ 7555942c5e3cSpl196000 InterfaceShutdown, "InterfaceShutdown", \ 7556942c5e3cSpl196000 DmaCommandFib, "DmaCommandFib", \ 7557942c5e3cSpl196000 StartProfile, "StartProfile", \ 7558942c5e3cSpl196000 TermProfile, "TermProfile", \ 7559942c5e3cSpl196000 SpeedTest, "SpeedTest", \ 7560942c5e3cSpl196000 TakeABreakPt, "TakeABreakPt", \ 7561942c5e3cSpl196000 RequestPerfData, "RequestPerfData", \ 7562942c5e3cSpl196000 SetInterruptDefTimer, "SetInterruptDefTimer", \ 7563942c5e3cSpl196000 SetInterruptDefCount, "SetInterruptDefCount", \ 7564942c5e3cSpl196000 GetInterruptDefStatus, "GetInterruptDefStatus", \ 7565942c5e3cSpl196000 LastCommCommand, "LastCommCommand", \ 7566942c5e3cSpl196000 NuFileSystem, "NuFileSystem", \ 7567942c5e3cSpl196000 UFS, "UFS", \ 7568942c5e3cSpl196000 HostFileSystem, "HostFileSystem", \ 7569942c5e3cSpl196000 LastFileSystemCommand, "LastFileSystemCommand", \ 7570942c5e3cSpl196000 ContainerCommand, "ContainerCommand", \ 7571942c5e3cSpl196000 ContainerCommand64, "ContainerCommand64", \ 7572942c5e3cSpl196000 ClusterCommand, "ClusterCommand", \ 7573942c5e3cSpl196000 ScsiPortCommand, "ScsiPortCommand", \ 7574942c5e3cSpl196000 ScsiPortCommandU64, "ScsiPortCommandU64", \ 7575942c5e3cSpl196000 AifRequest, "AifRequest", \ 7576942c5e3cSpl196000 CheckRevision, "CheckRevision", \ 7577942c5e3cSpl196000 FsaHostShutdown, "FsaHostShutdown", \ 7578942c5e3cSpl196000 RequestAdapterInfo, "RequestAdapterInfo", \ 7579942c5e3cSpl196000 IsAdapterPaused, "IsAdapterPaused", \ 7580942c5e3cSpl196000 SendHostTime, "SendHostTime", \ 7581942c5e3cSpl196000 LastMiscCommand, "LastMiscCommand" 7582942c5e3cSpl196000 7583942c5e3cSpl196000 #define AAC_CTVM_SUBCMD_KEY_STRINGS \ 7584942c5e3cSpl196000 VM_Null, "VM_Null", \ 7585942c5e3cSpl196000 VM_NameServe, "VM_NameServe", \ 7586942c5e3cSpl196000 VM_ContainerConfig, "VM_ContainerConfig", \ 7587942c5e3cSpl196000 VM_Ioctl, "VM_Ioctl", \ 7588942c5e3cSpl196000 VM_FilesystemIoctl, "VM_FilesystemIoctl", \ 7589942c5e3cSpl196000 VM_CloseAll, "VM_CloseAll", \ 7590942c5e3cSpl196000 VM_CtBlockRead, "VM_CtBlockRead", \ 7591942c5e3cSpl196000 VM_CtBlockWrite, "VM_CtBlockWrite", \ 7592942c5e3cSpl196000 VM_SliceBlockRead, "VM_SliceBlockRead", \ 7593942c5e3cSpl196000 VM_SliceBlockWrite, "VM_SliceBlockWrite", \ 7594942c5e3cSpl196000 VM_DriveBlockRead, "VM_DriveBlockRead", \ 7595942c5e3cSpl196000 VM_DriveBlockWrite, "VM_DriveBlockWrite", \ 7596942c5e3cSpl196000 VM_EnclosureMgt, "VM_EnclosureMgt", \ 7597942c5e3cSpl196000 VM_Unused, "VM_Unused", \ 7598942c5e3cSpl196000 VM_CtBlockVerify, "VM_CtBlockVerify", \ 7599942c5e3cSpl196000 VM_CtPerf, "VM_CtPerf", \ 7600942c5e3cSpl196000 VM_CtBlockRead64, "VM_CtBlockRead64", \ 7601942c5e3cSpl196000 VM_CtBlockWrite64, "VM_CtBlockWrite64", \ 7602942c5e3cSpl196000 VM_CtBlockVerify64, "VM_CtBlockVerify64", \ 7603942c5e3cSpl196000 VM_CtHostRead64, "VM_CtHostRead64", \ 7604942c5e3cSpl196000 VM_CtHostWrite64, "VM_CtHostWrite64", \ 7605942c5e3cSpl196000 VM_NameServe64, "VM_NameServe64" 7606942c5e3cSpl196000 7607942c5e3cSpl196000 #define AAC_CT_SUBCMD_KEY_STRINGS \ 7608942c5e3cSpl196000 CT_Null, "CT_Null", \ 7609942c5e3cSpl196000 CT_GET_SLICE_COUNT, "CT_GET_SLICE_COUNT", \ 7610942c5e3cSpl196000 CT_GET_PARTITION_COUNT, "CT_GET_PARTITION_COUNT", \ 7611942c5e3cSpl196000 CT_GET_PARTITION_INFO, "CT_GET_PARTITION_INFO", \ 7612942c5e3cSpl196000 CT_GET_CONTAINER_COUNT, "CT_GET_CONTAINER_COUNT", \ 7613942c5e3cSpl196000 CT_GET_CONTAINER_INFO_OLD, "CT_GET_CONTAINER_INFO_OLD", \ 7614942c5e3cSpl196000 CT_WRITE_MBR, "CT_WRITE_MBR", \ 7615942c5e3cSpl196000 CT_WRITE_PARTITION, "CT_WRITE_PARTITION", \ 7616942c5e3cSpl196000 CT_UPDATE_PARTITION, "CT_UPDATE_PARTITION", \ 7617942c5e3cSpl196000 CT_UNLOAD_CONTAINER, "CT_UNLOAD_CONTAINER", \ 7618942c5e3cSpl196000 CT_CONFIG_SINGLE_PRIMARY, "CT_CONFIG_SINGLE_PRIMARY", \ 7619942c5e3cSpl196000 CT_READ_CONFIG_AGE, "CT_READ_CONFIG_AGE", \ 7620942c5e3cSpl196000 CT_WRITE_CONFIG_AGE, "CT_WRITE_CONFIG_AGE", \ 7621942c5e3cSpl196000 CT_READ_SERIAL_NUMBER, "CT_READ_SERIAL_NUMBER", \ 7622942c5e3cSpl196000 CT_ZERO_PAR_ENTRY, "CT_ZERO_PAR_ENTRY", \ 7623942c5e3cSpl196000 CT_READ_MBR, "CT_READ_MBR", \ 7624942c5e3cSpl196000 CT_READ_PARTITION, "CT_READ_PARTITION", \ 7625942c5e3cSpl196000 CT_DESTROY_CONTAINER, "CT_DESTROY_CONTAINER", \ 7626942c5e3cSpl196000 CT_DESTROY2_CONTAINER, "CT_DESTROY2_CONTAINER", \ 7627942c5e3cSpl196000 CT_SLICE_SIZE, "CT_SLICE_SIZE", \ 7628942c5e3cSpl196000 CT_CHECK_CONFLICTS, "CT_CHECK_CONFLICTS", \ 7629942c5e3cSpl196000 CT_MOVE_CONTAINER, "CT_MOVE_CONTAINER", \ 7630942c5e3cSpl196000 CT_READ_LAST_DRIVE, "CT_READ_LAST_DRIVE", \ 7631942c5e3cSpl196000 CT_WRITE_LAST_DRIVE, "CT_WRITE_LAST_DRIVE", \ 7632942c5e3cSpl196000 CT_UNMIRROR, "CT_UNMIRROR", \ 7633942c5e3cSpl196000 CT_MIRROR_DELAY, "CT_MIRROR_DELAY", \ 7634942c5e3cSpl196000 CT_GEN_MIRROR, "CT_GEN_MIRROR", \ 7635942c5e3cSpl196000 CT_GEN_MIRROR2, "CT_GEN_MIRROR2", \ 7636942c5e3cSpl196000 CT_TEST_CONTAINER, "CT_TEST_CONTAINER", \ 7637942c5e3cSpl196000 CT_MOVE2, "CT_MOVE2", \ 7638942c5e3cSpl196000 CT_SPLIT, "CT_SPLIT", \ 7639942c5e3cSpl196000 CT_SPLIT2, "CT_SPLIT2", \ 7640942c5e3cSpl196000 CT_SPLIT_BROKEN, "CT_SPLIT_BROKEN", \ 7641942c5e3cSpl196000 CT_SPLIT_BROKEN2, "CT_SPLIT_BROKEN2", \ 7642942c5e3cSpl196000 CT_RECONFIG, "CT_RECONFIG", \ 7643942c5e3cSpl196000 CT_BREAK2, "CT_BREAK2", \ 7644942c5e3cSpl196000 CT_BREAK, "CT_BREAK", \ 7645942c5e3cSpl196000 CT_MERGE2, "CT_MERGE2", \ 7646942c5e3cSpl196000 CT_MERGE, "CT_MERGE", \ 7647942c5e3cSpl196000 CT_FORCE_ERROR, "CT_FORCE_ERROR", \ 7648942c5e3cSpl196000 CT_CLEAR_ERROR, "CT_CLEAR_ERROR", \ 7649942c5e3cSpl196000 CT_ASSIGN_FAILOVER, "CT_ASSIGN_FAILOVER", \ 7650942c5e3cSpl196000 CT_CLEAR_FAILOVER, "CT_CLEAR_FAILOVER", \ 7651942c5e3cSpl196000 CT_GET_FAILOVER_DATA, "CT_GET_FAILOVER_DATA", \ 7652942c5e3cSpl196000 CT_VOLUME_ADD, "CT_VOLUME_ADD", \ 7653942c5e3cSpl196000 CT_VOLUME_ADD2, "CT_VOLUME_ADD2", \ 7654942c5e3cSpl196000 CT_MIRROR_STATUS, "CT_MIRROR_STATUS", \ 7655942c5e3cSpl196000 CT_COPY_STATUS, "CT_COPY_STATUS", \ 7656942c5e3cSpl196000 CT_COPY, "CT_COPY", \ 7657942c5e3cSpl196000 CT_UNLOCK_CONTAINER, "CT_UNLOCK_CONTAINER", \ 7658942c5e3cSpl196000 CT_LOCK_CONTAINER, "CT_LOCK_CONTAINER", \ 7659942c5e3cSpl196000 CT_MAKE_READ_ONLY, "CT_MAKE_READ_ONLY", \ 7660942c5e3cSpl196000 CT_MAKE_READ_WRITE, "CT_MAKE_READ_WRITE", \ 7661942c5e3cSpl196000 CT_CLEAN_DEAD, "CT_CLEAN_DEAD", \ 7662942c5e3cSpl196000 CT_ABORT_MIRROR_COMMAND, "CT_ABORT_MIRROR_COMMAND", \ 7663942c5e3cSpl196000 CT_SET, "CT_SET", \ 7664942c5e3cSpl196000 CT_GET, "CT_GET", \ 7665942c5e3cSpl196000 CT_GET_NVLOG_ENTRY, "CT_GET_NVLOG_ENTRY", \ 7666942c5e3cSpl196000 CT_GET_DELAY, "CT_GET_DELAY", \ 7667942c5e3cSpl196000 CT_ZERO_CONTAINER_SPACE, "CT_ZERO_CONTAINER_SPACE", \ 7668942c5e3cSpl196000 CT_GET_ZERO_STATUS, "CT_GET_ZERO_STATUS", \ 7669942c5e3cSpl196000 CT_SCRUB, "CT_SCRUB", \ 7670942c5e3cSpl196000 CT_GET_SCRUB_STATUS, "CT_GET_SCRUB_STATUS", \ 7671942c5e3cSpl196000 CT_GET_SLICE_INFO, "CT_GET_SLICE_INFO", \ 7672942c5e3cSpl196000 CT_GET_SCSI_METHOD, "CT_GET_SCSI_METHOD", \ 7673942c5e3cSpl196000 CT_PAUSE_IO, "CT_PAUSE_IO", \ 7674942c5e3cSpl196000 CT_RELEASE_IO, "CT_RELEASE_IO", \ 7675942c5e3cSpl196000 CT_SCRUB2, "CT_SCRUB2", \ 7676942c5e3cSpl196000 CT_MCHECK, "CT_MCHECK", \ 7677942c5e3cSpl196000 CT_CORRUPT, "CT_CORRUPT", \ 7678942c5e3cSpl196000 CT_GET_TASK_COUNT, "CT_GET_TASK_COUNT", \ 7679942c5e3cSpl196000 CT_PROMOTE, "CT_PROMOTE", \ 7680942c5e3cSpl196000 CT_SET_DEAD, "CT_SET_DEAD", \ 7681942c5e3cSpl196000 CT_CONTAINER_OPTIONS, "CT_CONTAINER_OPTIONS", \ 7682942c5e3cSpl196000 CT_GET_NV_PARAM, "CT_GET_NV_PARAM", \ 7683942c5e3cSpl196000 CT_GET_PARAM, "CT_GET_PARAM", \ 7684942c5e3cSpl196000 CT_NV_PARAM_SIZE, "CT_NV_PARAM_SIZE", \ 7685942c5e3cSpl196000 CT_COMMON_PARAM_SIZE, "CT_COMMON_PARAM_SIZE", \ 7686942c5e3cSpl196000 CT_PLATFORM_PARAM_SIZE, "CT_PLATFORM_PARAM_SIZE", \ 7687942c5e3cSpl196000 CT_SET_NV_PARAM, "CT_SET_NV_PARAM", \ 7688942c5e3cSpl196000 CT_ABORT_SCRUB, "CT_ABORT_SCRUB", \ 7689942c5e3cSpl196000 CT_GET_SCRUB_ERROR, "CT_GET_SCRUB_ERROR", \ 7690942c5e3cSpl196000 CT_LABEL_CONTAINER, "CT_LABEL_CONTAINER", \ 7691942c5e3cSpl196000 CT_CONTINUE_DATA, "CT_CONTINUE_DATA", \ 7692942c5e3cSpl196000 CT_STOP_DATA, "CT_STOP_DATA", \ 7693942c5e3cSpl196000 CT_GET_PARTITION_TABLE, "CT_GET_PARTITION_TABLE", \ 7694942c5e3cSpl196000 CT_GET_DISK_PARTITIONS, "CT_GET_DISK_PARTITIONS", \ 7695942c5e3cSpl196000 CT_GET_MISC_STATUS, "CT_GET_MISC_STATUS", \ 7696942c5e3cSpl196000 CT_GET_CONTAINER_PERF_INFO, "CT_GET_CONTAINER_PERF_INFO", \ 7697942c5e3cSpl196000 CT_GET_TIME, "CT_GET_TIME", \ 7698942c5e3cSpl196000 CT_READ_DATA, "CT_READ_DATA", \ 7699942c5e3cSpl196000 CT_CTR, "CT_CTR", \ 7700942c5e3cSpl196000 CT_CTL, "CT_CTL", \ 7701942c5e3cSpl196000 CT_DRAINIO, "CT_DRAINIO", \ 7702942c5e3cSpl196000 CT_RELEASEIO, "CT_RELEASEIO", \ 7703942c5e3cSpl196000 CT_GET_NVRAM, "CT_GET_NVRAM", \ 7704942c5e3cSpl196000 CT_GET_MEMORY, "CT_GET_MEMORY", \ 7705942c5e3cSpl196000 CT_PRINT_CT_LOG, "CT_PRINT_CT_LOG", \ 7706942c5e3cSpl196000 CT_ADD_LEVEL, "CT_ADD_LEVEL", \ 7707942c5e3cSpl196000 CT_NV_ZERO, "CT_NV_ZERO", \ 7708942c5e3cSpl196000 CT_READ_SIGNATURE, "CT_READ_SIGNATURE", \ 7709942c5e3cSpl196000 CT_THROTTLE_ON, "CT_THROTTLE_ON", \ 7710942c5e3cSpl196000 CT_THROTTLE_OFF, "CT_THROTTLE_OFF", \ 7711942c5e3cSpl196000 CT_GET_THROTTLE_STATS, "CT_GET_THROTTLE_STATS", \ 7712942c5e3cSpl196000 CT_MAKE_SNAPSHOT, "CT_MAKE_SNAPSHOT", \ 7713942c5e3cSpl196000 CT_REMOVE_SNAPSHOT, "CT_REMOVE_SNAPSHOT", \ 7714942c5e3cSpl196000 CT_WRITE_USER_FLAGS, "CT_WRITE_USER_FLAGS", \ 7715942c5e3cSpl196000 CT_READ_USER_FLAGS, "CT_READ_USER_FLAGS", \ 7716942c5e3cSpl196000 CT_MONITOR, "CT_MONITOR", \ 7717942c5e3cSpl196000 CT_GEN_MORPH, "CT_GEN_MORPH", \ 7718942c5e3cSpl196000 CT_GET_SNAPSHOT_INFO, "CT_GET_SNAPSHOT_INFO", \ 7719942c5e3cSpl196000 CT_CACHE_SET, "CT_CACHE_SET", \ 7720942c5e3cSpl196000 CT_CACHE_STAT, "CT_CACHE_STAT", \ 7721942c5e3cSpl196000 CT_TRACE_START, "CT_TRACE_START", \ 7722942c5e3cSpl196000 CT_TRACE_STOP, "CT_TRACE_STOP", \ 7723942c5e3cSpl196000 CT_TRACE_ENABLE, "CT_TRACE_ENABLE", \ 7724942c5e3cSpl196000 CT_TRACE_DISABLE, "CT_TRACE_DISABLE", \ 7725942c5e3cSpl196000 CT_FORCE_CORE_DUMP, "CT_FORCE_CORE_DUMP", \ 7726942c5e3cSpl196000 CT_SET_SERIAL_NUMBER, "CT_SET_SERIAL_NUMBER", \ 7727942c5e3cSpl196000 CT_RESET_SERIAL_NUMBER, "CT_RESET_SERIAL_NUMBER", \ 7728942c5e3cSpl196000 CT_ENABLE_RAID5, "CT_ENABLE_RAID5", \ 7729942c5e3cSpl196000 CT_CLEAR_VALID_DUMP_FLAG, "CT_CLEAR_VALID_DUMP_FLAG", \ 7730942c5e3cSpl196000 CT_GET_MEM_STATS, "CT_GET_MEM_STATS", \ 7731942c5e3cSpl196000 CT_GET_CORE_SIZE, "CT_GET_CORE_SIZE", \ 7732942c5e3cSpl196000 CT_CREATE_CONTAINER_OLD, "CT_CREATE_CONTAINER_OLD", \ 7733942c5e3cSpl196000 CT_STOP_DUMPS, "CT_STOP_DUMPS", \ 7734942c5e3cSpl196000 CT_PANIC_ON_TAKE_A_BREAK, "CT_PANIC_ON_TAKE_A_BREAK", \ 7735942c5e3cSpl196000 CT_GET_CACHE_STATS, "CT_GET_CACHE_STATS", \ 7736942c5e3cSpl196000 CT_MOVE_PARTITION, "CT_MOVE_PARTITION", \ 7737942c5e3cSpl196000 CT_FLUSH_CACHE, "CT_FLUSH_CACHE", \ 7738942c5e3cSpl196000 CT_READ_NAME, "CT_READ_NAME", \ 7739942c5e3cSpl196000 CT_WRITE_NAME, "CT_WRITE_NAME", \ 7740942c5e3cSpl196000 CT_TOSS_CACHE, "CT_TOSS_CACHE", \ 7741942c5e3cSpl196000 CT_LOCK_DRAINIO, "CT_LOCK_DRAINIO", \ 7742942c5e3cSpl196000 CT_CONTAINER_OFFLINE, "CT_CONTAINER_OFFLINE", \ 7743942c5e3cSpl196000 CT_SET_CACHE_SIZE, "CT_SET_CACHE_SIZE", \ 7744942c5e3cSpl196000 CT_CLEAN_SHUTDOWN_STATUS, "CT_CLEAN_SHUTDOWN_STATUS", \ 7745942c5e3cSpl196000 CT_CLEAR_DISKLOG_ON_DISK, "CT_CLEAR_DISKLOG_ON_DISK", \ 7746942c5e3cSpl196000 CT_CLEAR_ALL_DISKLOG, "CT_CLEAR_ALL_DISKLOG", \ 7747942c5e3cSpl196000 CT_CACHE_FAVOR, "CT_CACHE_FAVOR", \ 7748942c5e3cSpl196000 CT_READ_PASSTHRU_MBR, "CT_READ_PASSTHRU_MBR", \ 7749942c5e3cSpl196000 CT_SCRUB_NOFIX, "CT_SCRUB_NOFIX", \ 7750942c5e3cSpl196000 CT_SCRUB2_NOFIX, "CT_SCRUB2_NOFIX", \ 7751942c5e3cSpl196000 CT_FLUSH, "CT_FLUSH", \ 7752942c5e3cSpl196000 CT_REBUILD, "CT_REBUILD", \ 7753942c5e3cSpl196000 CT_FLUSH_CONTAINER, "CT_FLUSH_CONTAINER", \ 7754942c5e3cSpl196000 CT_RESTART, "CT_RESTART", \ 7755942c5e3cSpl196000 CT_GET_CONFIG_STATUS, "CT_GET_CONFIG_STATUS", \ 7756942c5e3cSpl196000 CT_TRACE_FLAG, "CT_TRACE_FLAG", \ 7757942c5e3cSpl196000 CT_RESTART_MORPH, "CT_RESTART_MORPH", \ 7758942c5e3cSpl196000 CT_GET_TRACE_INFO, "CT_GET_TRACE_INFO", \ 7759942c5e3cSpl196000 CT_GET_TRACE_ITEM, "CT_GET_TRACE_ITEM", \ 7760942c5e3cSpl196000 CT_COMMIT_CONFIG, "CT_COMMIT_CONFIG", \ 7761942c5e3cSpl196000 CT_CONTAINER_EXISTS, "CT_CONTAINER_EXISTS", \ 7762942c5e3cSpl196000 CT_GET_SLICE_FROM_DEVT, "CT_GET_SLICE_FROM_DEVT", \ 7763942c5e3cSpl196000 CT_OPEN_READ_WRITE, "CT_OPEN_READ_WRITE", \ 7764942c5e3cSpl196000 CT_WRITE_MEMORY_BLOCK, "CT_WRITE_MEMORY_BLOCK", \ 7765942c5e3cSpl196000 CT_GET_CACHE_PARAMS, "CT_GET_CACHE_PARAMS", \ 7766942c5e3cSpl196000 CT_CRAZY_CACHE, "CT_CRAZY_CACHE", \ 7767942c5e3cSpl196000 CT_GET_PROFILE_STRUCT, "CT_GET_PROFILE_STRUCT", \ 7768942c5e3cSpl196000 CT_SET_IO_TRACE_FLAG, "CT_SET_IO_TRACE_FLAG", \ 7769942c5e3cSpl196000 CT_GET_IO_TRACE_STRUCT, "CT_GET_IO_TRACE_STRUCT", \ 7770942c5e3cSpl196000 CT_CID_TO_64BITS_UID, "CT_CID_TO_64BITS_UID", \ 7771942c5e3cSpl196000 CT_64BITS_UID_TO_CID, "CT_64BITS_UID_TO_CID", \ 7772942c5e3cSpl196000 CT_PAR_TO_64BITS_UID, "CT_PAR_TO_64BITS_UID", \ 7773942c5e3cSpl196000 CT_CID_TO_32BITS_UID, "CT_CID_TO_32BITS_UID", \ 7774942c5e3cSpl196000 CT_32BITS_UID_TO_CID, "CT_32BITS_UID_TO_CID", \ 7775942c5e3cSpl196000 CT_PAR_TO_32BITS_UID, "CT_PAR_TO_32BITS_UID", \ 7776942c5e3cSpl196000 CT_SET_FAILOVER_OPTION, "CT_SET_FAILOVER_OPTION", \ 7777942c5e3cSpl196000 CT_GET_FAILOVER_OPTION, "CT_GET_FAILOVER_OPTION", \ 7778942c5e3cSpl196000 CT_STRIPE_ADD2, "CT_STRIPE_ADD2", \ 7779942c5e3cSpl196000 CT_CREATE_VOLUME_SET, "CT_CREATE_VOLUME_SET", \ 7780942c5e3cSpl196000 CT_CREATE_STRIPE_SET, "CT_CREATE_STRIPE_SET", \ 7781942c5e3cSpl196000 CT_VERIFY_CONTAINER, "CT_VERIFY_CONTAINER", \ 7782942c5e3cSpl196000 CT_IS_CONTAINER_DEAD, "CT_IS_CONTAINER_DEAD", \ 7783942c5e3cSpl196000 CT_GET_CONTAINER_OPTION, "CT_GET_CONTAINER_OPTION", \ 7784942c5e3cSpl196000 CT_GET_SNAPSHOT_UNUSED_STRUCT, "CT_GET_SNAPSHOT_UNUSED_STRUCT", \ 7785942c5e3cSpl196000 CT_CLEAR_SNAPSHOT_UNUSED_STRUCT, "CT_CLEAR_SNAPSHOT_UNUSED_STRUCT", \ 7786942c5e3cSpl196000 CT_GET_CONTAINER_INFO, "CT_GET_CONTAINER_INFO", \ 7787942c5e3cSpl196000 CT_CREATE_CONTAINER, "CT_CREATE_CONTAINER", \ 7788942c5e3cSpl196000 CT_CHANGE_CREATIONINFO, "CT_CHANGE_CREATIONINFO", \ 7789942c5e3cSpl196000 CT_CHECK_CONFLICT_UID, "CT_CHECK_CONFLICT_UID", \ 7790942c5e3cSpl196000 CT_CONTAINER_UID_CHECK, "CT_CONTAINER_UID_CHECK", \ 7791942c5e3cSpl196000 CT_IS_CONTAINER_MEATADATA_STANDARD, \ 7792942c5e3cSpl196000 "CT_IS_CONTAINER_MEATADATA_STANDARD", \ 7793942c5e3cSpl196000 CT_IS_SLICE_METADATA_STANDARD, "CT_IS_SLICE_METADATA_STANDARD", \ 7794942c5e3cSpl196000 CT_GET_IMPORT_COUNT, "CT_GET_IMPORT_COUNT", \ 7795942c5e3cSpl196000 CT_CANCEL_ALL_IMPORTS, "CT_CANCEL_ALL_IMPORTS", \ 7796942c5e3cSpl196000 CT_GET_IMPORT_INFO, "CT_GET_IMPORT_INFO", \ 7797942c5e3cSpl196000 CT_IMPORT_ARRAY, "CT_IMPORT_ARRAY", \ 7798942c5e3cSpl196000 CT_GET_LOG_SIZE, "CT_GET_LOG_SIZE", \ 7799942c5e3cSpl196000 CT_ALARM_GET_STATE, "CT_ALARM_GET_STATE", \ 7800942c5e3cSpl196000 CT_ALARM_SET_STATE, "CT_ALARM_SET_STATE", \ 7801942c5e3cSpl196000 CT_ALARM_ON_OFF, "CT_ALARM_ON_OFF", \ 7802942c5e3cSpl196000 CT_GET_EE_OEM_ID, "CT_GET_EE_OEM_ID", \ 7803942c5e3cSpl196000 CT_GET_PPI_HEADERS, "CT_GET_PPI_HEADERS", \ 7804942c5e3cSpl196000 CT_GET_PPI_DATA, "CT_GET_PPI_DATA", \ 7805942c5e3cSpl196000 CT_GET_PPI_ENTRIES, "CT_GET_PPI_ENTRIES", \ 7806942c5e3cSpl196000 CT_DELETE_PPI_BUNDLE, "CT_DELETE_PPI_BUNDLE", \ 7807942c5e3cSpl196000 CT_GET_PARTITION_TABLE_2, "CT_GET_PARTITION_TABLE_2", \ 7808942c5e3cSpl196000 CT_GET_PARTITION_INFO_2, "CT_GET_PARTITION_INFO_2", \ 7809942c5e3cSpl196000 CT_GET_DISK_PARTITIONS_2, "CT_GET_DISK_PARTITIONS_2", \ 7810942c5e3cSpl196000 CT_QUIESCE_ADAPTER, "CT_QUIESCE_ADAPTER", \ 7811942c5e3cSpl196000 CT_CLEAR_PPI_TABLE, "CT_CLEAR_PPI_TABLE" 7812942c5e3cSpl196000 7813942c5e3cSpl196000 #define AAC_CL_SUBCMD_KEY_STRINGS \ 7814942c5e3cSpl196000 CL_NULL, "CL_NULL", \ 7815942c5e3cSpl196000 DS_INIT, "DS_INIT", \ 7816942c5e3cSpl196000 DS_RESCAN, "DS_RESCAN", \ 7817942c5e3cSpl196000 DS_CREATE, "DS_CREATE", \ 7818942c5e3cSpl196000 DS_DELETE, "DS_DELETE", \ 7819942c5e3cSpl196000 DS_ADD_DISK, "DS_ADD_DISK", \ 7820942c5e3cSpl196000 DS_REMOVE_DISK, "DS_REMOVE_DISK", \ 7821942c5e3cSpl196000 DS_MOVE_DISK, "DS_MOVE_DISK", \ 7822942c5e3cSpl196000 DS_TAKE_OWNERSHIP, "DS_TAKE_OWNERSHIP", \ 7823942c5e3cSpl196000 DS_RELEASE_OWNERSHIP, "DS_RELEASE_OWNERSHIP", \ 7824942c5e3cSpl196000 DS_FORCE_OWNERSHIP, "DS_FORCE_OWNERSHIP", \ 7825942c5e3cSpl196000 DS_GET_DISK_SET_PARAM, "DS_GET_DISK_SET_PARAM", \ 7826942c5e3cSpl196000 DS_GET_DRIVE_PARAM, "DS_GET_DRIVE_PARAM", \ 7827942c5e3cSpl196000 DS_GET_SLICE_PARAM, "DS_GET_SLICE_PARAM", \ 7828942c5e3cSpl196000 DS_GET_DISK_SETS, "DS_GET_DISK_SETS", \ 7829942c5e3cSpl196000 DS_GET_DRIVES, "DS_GET_DRIVES", \ 7830942c5e3cSpl196000 DS_SET_DISK_SET_PARAM, "DS_SET_DISK_SET_PARAM", \ 7831942c5e3cSpl196000 DS_ONLINE, "DS_ONLINE", \ 7832942c5e3cSpl196000 DS_OFFLINE, "DS_OFFLINE", \ 7833942c5e3cSpl196000 DS_ONLINE_CONTAINERS, "DS_ONLINE_CONTAINERS", \ 7834942c5e3cSpl196000 DS_FSAPRINT, "DS_FSAPRINT", \ 7835942c5e3cSpl196000 CL_CFG_SET_HOST_IDS, "CL_CFG_SET_HOST_IDS", \ 7836942c5e3cSpl196000 CL_CFG_SET_PARTNER_HOST_IDS, "CL_CFG_SET_PARTNER_HOST_IDS", \ 7837942c5e3cSpl196000 CL_CFG_GET_CLUSTER_CONFIG, "CL_CFG_GET_CLUSTER_CONFIG", \ 7838942c5e3cSpl196000 CC_CLI_CLEAR_MESSAGE_BUFFER, "CC_CLI_CLEAR_MESSAGE_BUFFER", \ 7839942c5e3cSpl196000 CC_SRV_CLEAR_MESSAGE_BUFFER, "CC_SRV_CLEAR_MESSAGE_BUFFER", \ 7840942c5e3cSpl196000 CC_CLI_SHOW_MESSAGE_BUFFER, "CC_CLI_SHOW_MESSAGE_BUFFER", \ 7841942c5e3cSpl196000 CC_SRV_SHOW_MESSAGE_BUFFER, "CC_SRV_SHOW_MESSAGE_BUFFER", \ 7842942c5e3cSpl196000 CC_CLI_SEND_MESSAGE, "CC_CLI_SEND_MESSAGE", \ 7843942c5e3cSpl196000 CC_SRV_SEND_MESSAGE, "CC_SRV_SEND_MESSAGE", \ 7844942c5e3cSpl196000 CC_CLI_GET_MESSAGE, "CC_CLI_GET_MESSAGE", \ 7845942c5e3cSpl196000 CC_SRV_GET_MESSAGE, "CC_SRV_GET_MESSAGE", \ 7846942c5e3cSpl196000 CC_SEND_TEST_MESSAGE, "CC_SEND_TEST_MESSAGE", \ 7847942c5e3cSpl196000 CC_GET_BUSINFO, "CC_GET_BUSINFO", \ 7848942c5e3cSpl196000 CC_GET_PORTINFO, "CC_GET_PORTINFO", \ 7849942c5e3cSpl196000 CC_GET_NAMEINFO, "CC_GET_NAMEINFO", \ 7850942c5e3cSpl196000 CC_GET_CONFIGINFO, "CC_GET_CONFIGINFO", \ 7851942c5e3cSpl196000 CQ_QUORUM_OP, "CQ_QUORUM_OP" 7852942c5e3cSpl196000 7853942c5e3cSpl196000 #define AAC_AIF_SUBCMD_KEY_STRINGS \ 7854942c5e3cSpl196000 AifCmdEventNotify, "AifCmdEventNotify", \ 7855942c5e3cSpl196000 AifCmdJobProgress, "AifCmdJobProgress", \ 7856942c5e3cSpl196000 AifCmdAPIReport, "AifCmdAPIReport", \ 7857942c5e3cSpl196000 AifCmdDriverNotify, "AifCmdDriverNotify", \ 7858942c5e3cSpl196000 AifReqJobList, "AifReqJobList", \ 7859942c5e3cSpl196000 AifReqJobsForCtr, "AifReqJobsForCtr", \ 7860942c5e3cSpl196000 AifReqJobsForScsi, "AifReqJobsForScsi", \ 7861942c5e3cSpl196000 AifReqJobReport, "AifReqJobReport", \ 7862942c5e3cSpl196000 AifReqTerminateJob, "AifReqTerminateJob", \ 7863942c5e3cSpl196000 AifReqSuspendJob, "AifReqSuspendJob", \ 7864942c5e3cSpl196000 AifReqResumeJob, "AifReqResumeJob", \ 7865942c5e3cSpl196000 AifReqSendAPIReport, "AifReqSendAPIReport", \ 7866942c5e3cSpl196000 AifReqAPIJobStart, "AifReqAPIJobStart", \ 7867942c5e3cSpl196000 AifReqAPIJobUpdate, "AifReqAPIJobUpdate", \ 7868942c5e3cSpl196000 AifReqAPIJobFinish, "AifReqAPIJobFinish" 7869942c5e3cSpl196000 7870942c5e3cSpl196000 #define AAC_IOCTL_SUBCMD_KEY_STRINGS \ 7871942c5e3cSpl196000 Reserved_IOCTL, "Reserved_IOCTL", \ 7872942c5e3cSpl196000 GetDeviceHandle, "GetDeviceHandle", \ 7873942c5e3cSpl196000 BusTargetLun_to_DeviceHandle, "BusTargetLun_to_DeviceHandle", \ 7874942c5e3cSpl196000 DeviceHandle_to_BusTargetLun, "DeviceHandle_to_BusTargetLun", \ 7875942c5e3cSpl196000 RescanBus, "RescanBus", \ 7876942c5e3cSpl196000 GetDeviceProbeInfo, "GetDeviceProbeInfo", \ 7877942c5e3cSpl196000 GetDeviceCapacity, "GetDeviceCapacity", \ 7878942c5e3cSpl196000 GetContainerProbeInfo, "GetContainerProbeInfo", \ 7879942c5e3cSpl196000 GetRequestedMemorySize, "GetRequestedMemorySize", \ 7880942c5e3cSpl196000 GetBusInfo, "GetBusInfo", \ 7881942c5e3cSpl196000 GetVendorSpecific, "GetVendorSpecific", \ 7882942c5e3cSpl196000 EnhancedGetDeviceProbeInfo, "EnhancedGetDeviceProbeInfo", \ 7883942c5e3cSpl196000 EnhancedGetBusInfo, "EnhancedGetBusInfo", \ 7884942c5e3cSpl196000 SetupExtendedCounters, "SetupExtendedCounters", \ 7885942c5e3cSpl196000 GetPerformanceCounters, "GetPerformanceCounters", \ 7886942c5e3cSpl196000 ResetPerformanceCounters, "ResetPerformanceCounters", \ 7887942c5e3cSpl196000 ReadModePage, "ReadModePage", \ 7888942c5e3cSpl196000 WriteModePage, "WriteModePage", \ 7889942c5e3cSpl196000 ReadDriveParameter, "ReadDriveParameter", \ 7890942c5e3cSpl196000 WriteDriveParameter, "WriteDriveParameter", \ 7891942c5e3cSpl196000 ResetAdapter, "ResetAdapter", \ 7892942c5e3cSpl196000 ResetBus, "ResetBus", \ 7893942c5e3cSpl196000 ResetBusDevice, "ResetBusDevice", \ 7894942c5e3cSpl196000 ExecuteSrb, "ExecuteSrb", \ 7895942c5e3cSpl196000 Create_IO_Task, "Create_IO_Task", \ 7896942c5e3cSpl196000 Delete_IO_Task, "Delete_IO_Task", \ 7897942c5e3cSpl196000 Get_IO_Task_Info, "Get_IO_Task_Info", \ 7898942c5e3cSpl196000 Check_Task_Progress, "Check_Task_Progress", \ 7899942c5e3cSpl196000 InjectError, "InjectError", \ 7900942c5e3cSpl196000 GetDeviceDefectCounts, "GetDeviceDefectCounts", \ 7901942c5e3cSpl196000 GetDeviceDefectInfo, "GetDeviceDefectInfo", \ 7902942c5e3cSpl196000 GetDeviceStatus, "GetDeviceStatus", \ 7903942c5e3cSpl196000 ClearDeviceStatus, "ClearDeviceStatus", \ 7904942c5e3cSpl196000 DiskSpinControl, "DiskSpinControl", \ 7905942c5e3cSpl196000 DiskSmartControl, "DiskSmartControl", \ 7906942c5e3cSpl196000 WriteSame, "WriteSame", \ 7907942c5e3cSpl196000 ReadWriteLong, "ReadWriteLong", \ 7908942c5e3cSpl196000 FormatUnit, "FormatUnit", \ 7909942c5e3cSpl196000 TargetDeviceControl, "TargetDeviceControl", \ 7910942c5e3cSpl196000 TargetChannelControl, "TargetChannelControl", \ 7911942c5e3cSpl196000 FlashNewCode, "FlashNewCode", \ 7912942c5e3cSpl196000 DiskCheck, "DiskCheck", \ 7913942c5e3cSpl196000 RequestSense, "RequestSense", \ 7914942c5e3cSpl196000 DiskPERControl, "DiskPERControl", \ 7915942c5e3cSpl196000 Read10, "Read10", \ 7916942c5e3cSpl196000 Write10, "Write10" 7917942c5e3cSpl196000 7918942c5e3cSpl196000 #define AAC_AIFEN_KEY_STRINGS \ 7919942c5e3cSpl196000 AifEnGeneric, "Generic", \ 7920942c5e3cSpl196000 AifEnTaskComplete, "TaskComplete", \ 7921942c5e3cSpl196000 AifEnConfigChange, "Config change", \ 7922942c5e3cSpl196000 AifEnContainerChange, "Container change", \ 7923942c5e3cSpl196000 AifEnDeviceFailure, "device failed", \ 7924942c5e3cSpl196000 AifEnMirrorFailover, "Mirror failover", \ 7925942c5e3cSpl196000 AifEnContainerEvent, "container event", \ 7926942c5e3cSpl196000 AifEnFileSystemChange, "File system changed", \ 7927942c5e3cSpl196000 AifEnConfigPause, "Container pause event", \ 7928942c5e3cSpl196000 AifEnConfigResume, "Container resume event", \ 7929942c5e3cSpl196000 AifEnFailoverChange, "Failover space assignment changed", \ 7930942c5e3cSpl196000 AifEnRAID5RebuildDone, "RAID5 rebuild finished", \ 7931942c5e3cSpl196000 AifEnEnclosureManagement, "Enclosure management event", \ 7932942c5e3cSpl196000 AifEnBatteryEvent, "battery event", \ 7933942c5e3cSpl196000 AifEnAddContainer, "Add container", \ 7934942c5e3cSpl196000 AifEnDeleteContainer, "Delete container", \ 7935942c5e3cSpl196000 AifEnSMARTEvent, "SMART Event", \ 7936942c5e3cSpl196000 AifEnBatteryNeedsRecond, "battery needs reconditioning", \ 7937942c5e3cSpl196000 AifEnClusterEvent, "cluster event", \ 7938942c5e3cSpl196000 AifEnDiskSetEvent, "disk set event occured", \ 7939942c5e3cSpl196000 AifDenMorphComplete, "morph operation completed", \ 7940942c5e3cSpl196000 AifDenVolumeExtendComplete, "VolumeExtendComplete" 7941942c5e3cSpl196000 7942942c5e3cSpl196000 struct aac_key_strings { 7943942c5e3cSpl196000 int key; 7944942c5e3cSpl196000 char *message; 7945942c5e3cSpl196000 }; 7946942c5e3cSpl196000 7947942c5e3cSpl196000 extern struct scsi_key_strings scsi_cmds[]; 7948942c5e3cSpl196000 7949942c5e3cSpl196000 static struct aac_key_strings aac_fib_cmds[] = { 7950942c5e3cSpl196000 AAC_FIB_CMD_KEY_STRINGS, 7951942c5e3cSpl196000 -1, NULL 7952942c5e3cSpl196000 }; 7953942c5e3cSpl196000 7954942c5e3cSpl196000 static struct aac_key_strings aac_ctvm_subcmds[] = { 7955942c5e3cSpl196000 AAC_CTVM_SUBCMD_KEY_STRINGS, 7956942c5e3cSpl196000 -1, NULL 7957942c5e3cSpl196000 }; 7958942c5e3cSpl196000 7959942c5e3cSpl196000 static struct aac_key_strings aac_ct_subcmds[] = { 7960942c5e3cSpl196000 AAC_CT_SUBCMD_KEY_STRINGS, 7961942c5e3cSpl196000 -1, NULL 7962942c5e3cSpl196000 }; 7963942c5e3cSpl196000 7964942c5e3cSpl196000 static struct aac_key_strings aac_cl_subcmds[] = { 7965942c5e3cSpl196000 AAC_CL_SUBCMD_KEY_STRINGS, 7966942c5e3cSpl196000 -1, NULL 7967942c5e3cSpl196000 }; 7968942c5e3cSpl196000 7969942c5e3cSpl196000 static struct aac_key_strings aac_aif_subcmds[] = { 7970942c5e3cSpl196000 AAC_AIF_SUBCMD_KEY_STRINGS, 7971942c5e3cSpl196000 -1, NULL 7972942c5e3cSpl196000 }; 7973942c5e3cSpl196000 7974942c5e3cSpl196000 static struct aac_key_strings aac_ioctl_subcmds[] = { 7975942c5e3cSpl196000 AAC_IOCTL_SUBCMD_KEY_STRINGS, 7976942c5e3cSpl196000 -1, NULL 7977942c5e3cSpl196000 }; 7978942c5e3cSpl196000 7979942c5e3cSpl196000 static struct aac_key_strings aac_aifens[] = { 7980942c5e3cSpl196000 AAC_AIFEN_KEY_STRINGS, 7981942c5e3cSpl196000 -1, NULL 7982942c5e3cSpl196000 }; 7983942c5e3cSpl196000 7984942c5e3cSpl196000 /* 7985942c5e3cSpl196000 * The following function comes from Adaptec: 7986942c5e3cSpl196000 * 7987942c5e3cSpl196000 * Get the firmware print buffer parameters from the firmware, 7988942c5e3cSpl196000 * if the command was successful map in the address. 7989942c5e3cSpl196000 */ 7990942c5e3cSpl196000 static int 7991942c5e3cSpl196000 aac_get_fw_debug_buffer(struct aac_softstate *softs) 7992942c5e3cSpl196000 { 7993942c5e3cSpl196000 if (aac_sync_mbcommand(softs, AAC_MONKER_GETDRVPROP, 7994942c5e3cSpl196000 0, 0, 0, 0, NULL) == AACOK) { 7995942c5e3cSpl196000 uint32_t mondrv_buf_paddrl = AAC_MAILBOX_GET(softs, 1); 7996942c5e3cSpl196000 uint32_t mondrv_buf_paddrh = AAC_MAILBOX_GET(softs, 2); 7997942c5e3cSpl196000 uint32_t mondrv_buf_size = AAC_MAILBOX_GET(softs, 3); 7998942c5e3cSpl196000 uint32_t mondrv_hdr_size = AAC_MAILBOX_GET(softs, 4); 7999942c5e3cSpl196000 8000942c5e3cSpl196000 if (mondrv_buf_size) { 8001942c5e3cSpl196000 uint32_t offset = mondrv_buf_paddrl - \ 8002942c5e3cSpl196000 softs->pci_mem_base_paddr; 8003942c5e3cSpl196000 8004942c5e3cSpl196000 /* 8005942c5e3cSpl196000 * See if the address is already mapped in, and 8006942c5e3cSpl196000 * if so set it up from the base address 8007942c5e3cSpl196000 */ 8008942c5e3cSpl196000 if ((mondrv_buf_paddrh == 0) && 8009942c5e3cSpl196000 (offset + mondrv_buf_size < softs->map_size)) { 8010942c5e3cSpl196000 mutex_enter(&aac_prt_mutex); 8011942c5e3cSpl196000 softs->debug_buf_offset = offset; 8012942c5e3cSpl196000 softs->debug_header_size = mondrv_hdr_size; 8013942c5e3cSpl196000 softs->debug_buf_size = mondrv_buf_size; 8014942c5e3cSpl196000 softs->debug_fw_flags = 0; 8015942c5e3cSpl196000 softs->debug_flags &= ~AACDB_FLAGS_FW_PRINT; 8016942c5e3cSpl196000 mutex_exit(&aac_prt_mutex); 8017942c5e3cSpl196000 8018942c5e3cSpl196000 return (AACOK); 8019942c5e3cSpl196000 } 8020942c5e3cSpl196000 } 8021942c5e3cSpl196000 } 8022942c5e3cSpl196000 return (AACERR); 8023942c5e3cSpl196000 } 8024942c5e3cSpl196000 8025942c5e3cSpl196000 int 8026942c5e3cSpl196000 aac_dbflag_on(struct aac_softstate *softs, int flag) 8027942c5e3cSpl196000 { 8028942c5e3cSpl196000 int debug_flags = softs ? softs->debug_flags : aac_debug_flags; 8029942c5e3cSpl196000 8030942c5e3cSpl196000 return ((debug_flags & (AACDB_FLAGS_FW_PRINT | \ 8031942c5e3cSpl196000 AACDB_FLAGS_KERNEL_PRINT)) && (debug_flags & flag)); 8032942c5e3cSpl196000 } 8033942c5e3cSpl196000 8034942c5e3cSpl196000 static void 8035942c5e3cSpl196000 aac_cmn_err(struct aac_softstate *softs, uint_t lev, char sl, int noheader) 8036942c5e3cSpl196000 { 8037942c5e3cSpl196000 if (noheader) { 8038942c5e3cSpl196000 if (sl) { 8039942c5e3cSpl196000 aac_fmt[0] = sl; 8040942c5e3cSpl196000 cmn_err(lev, aac_fmt, aac_prt_buf); 8041942c5e3cSpl196000 } else { 8042942c5e3cSpl196000 cmn_err(lev, &aac_fmt[1], aac_prt_buf); 8043942c5e3cSpl196000 } 8044942c5e3cSpl196000 } else { 8045942c5e3cSpl196000 if (sl) { 8046942c5e3cSpl196000 aac_fmt_header[0] = sl; 8047942c5e3cSpl196000 cmn_err(lev, aac_fmt_header, 8048942c5e3cSpl196000 softs->vendor_name, softs->instance, 8049942c5e3cSpl196000 aac_prt_buf); 8050942c5e3cSpl196000 } else { 8051942c5e3cSpl196000 cmn_err(lev, &aac_fmt_header[1], 8052942c5e3cSpl196000 softs->vendor_name, softs->instance, 8053942c5e3cSpl196000 aac_prt_buf); 8054942c5e3cSpl196000 } 8055942c5e3cSpl196000 } 8056942c5e3cSpl196000 } 8057942c5e3cSpl196000 8058942c5e3cSpl196000 /* 8059942c5e3cSpl196000 * The following function comes from Adaptec: 8060942c5e3cSpl196000 * 8061942c5e3cSpl196000 * Format and print out the data passed in to UART or console 8062942c5e3cSpl196000 * as specified by debug flags. 8063942c5e3cSpl196000 */ 8064942c5e3cSpl196000 void 8065942c5e3cSpl196000 aac_printf(struct aac_softstate *softs, uint_t lev, const char *fmt, ...) 8066942c5e3cSpl196000 { 8067942c5e3cSpl196000 va_list args; 8068942c5e3cSpl196000 char sl; /* system log character */ 8069942c5e3cSpl196000 8070942c5e3cSpl196000 mutex_enter(&aac_prt_mutex); 8071942c5e3cSpl196000 /* Set up parameters and call sprintf function to format the data */ 8072942c5e3cSpl196000 if (strchr("^!?", fmt[0]) == NULL) { 8073942c5e3cSpl196000 sl = 0; 8074942c5e3cSpl196000 } else { 8075942c5e3cSpl196000 sl = fmt[0]; 8076942c5e3cSpl196000 fmt++; 8077942c5e3cSpl196000 } 8078942c5e3cSpl196000 va_start(args, fmt); 8079942c5e3cSpl196000 (void) vsprintf(aac_prt_buf, fmt, args); 8080942c5e3cSpl196000 va_end(args); 8081942c5e3cSpl196000 8082942c5e3cSpl196000 /* Make sure the softs structure has been passed in for this section */ 8083942c5e3cSpl196000 if (softs) { 8084942c5e3cSpl196000 if ((softs->debug_flags & AACDB_FLAGS_FW_PRINT) && 8085942c5e3cSpl196000 /* If we are set up for a Firmware print */ 8086942c5e3cSpl196000 (softs->debug_buf_size)) { 8087942c5e3cSpl196000 uint32_t count, i; 8088942c5e3cSpl196000 8089942c5e3cSpl196000 /* Make sure the string size is within boundaries */ 8090942c5e3cSpl196000 count = strlen(aac_prt_buf); 8091942c5e3cSpl196000 if (count > softs->debug_buf_size) 8092942c5e3cSpl196000 count = (uint16_t)softs->debug_buf_size; 8093942c5e3cSpl196000 8094942c5e3cSpl196000 /* 8095942c5e3cSpl196000 * Wait for no more than AAC_PRINT_TIMEOUT for the 8096942c5e3cSpl196000 * previous message length to clear (the handshake). 8097942c5e3cSpl196000 */ 8098942c5e3cSpl196000 for (i = 0; i < AAC_PRINT_TIMEOUT; i++) { 8099942c5e3cSpl196000 if (!PCI_MEM_GET32(softs, 8100942c5e3cSpl196000 softs->debug_buf_offset + \ 8101942c5e3cSpl196000 AAC_FW_DBG_STRLEN_OFFSET)) 8102942c5e3cSpl196000 break; 8103942c5e3cSpl196000 8104942c5e3cSpl196000 drv_usecwait(1000); 8105942c5e3cSpl196000 } 8106942c5e3cSpl196000 8107942c5e3cSpl196000 /* 8108942c5e3cSpl196000 * If the length is clear, copy over the message, the 8109942c5e3cSpl196000 * flags, and the length. Make sure the length is the 8110942c5e3cSpl196000 * last because that is the signal for the Firmware to 8111942c5e3cSpl196000 * pick it up. 8112942c5e3cSpl196000 */ 8113942c5e3cSpl196000 if (!PCI_MEM_GET32(softs, softs->debug_buf_offset + \ 8114942c5e3cSpl196000 AAC_FW_DBG_STRLEN_OFFSET)) { 8115942c5e3cSpl196000 PCI_MEM_REP_PUT8(softs, 8116942c5e3cSpl196000 softs->debug_buf_offset + \ 8117942c5e3cSpl196000 softs->debug_header_size, 8118942c5e3cSpl196000 aac_prt_buf, count); 8119942c5e3cSpl196000 PCI_MEM_PUT32(softs, 8120942c5e3cSpl196000 softs->debug_buf_offset + \ 8121942c5e3cSpl196000 AAC_FW_DBG_FLAGS_OFFSET, 8122942c5e3cSpl196000 softs->debug_fw_flags); 8123942c5e3cSpl196000 PCI_MEM_PUT32(softs, 8124942c5e3cSpl196000 softs->debug_buf_offset + \ 8125942c5e3cSpl196000 AAC_FW_DBG_STRLEN_OFFSET, count); 8126942c5e3cSpl196000 } else { 8127942c5e3cSpl196000 cmn_err(CE_WARN, "UART output fail"); 8128942c5e3cSpl196000 softs->debug_flags &= ~AACDB_FLAGS_FW_PRINT; 8129942c5e3cSpl196000 } 8130942c5e3cSpl196000 } 8131942c5e3cSpl196000 8132942c5e3cSpl196000 /* 8133942c5e3cSpl196000 * If the Kernel Debug Print flag is set, send it off 8134942c5e3cSpl196000 * to the Kernel Debugger 8135942c5e3cSpl196000 */ 8136942c5e3cSpl196000 if (softs->debug_flags & AACDB_FLAGS_KERNEL_PRINT) 8137942c5e3cSpl196000 aac_cmn_err(softs, lev, sl, 8138942c5e3cSpl196000 (softs->debug_flags & AACDB_FLAGS_NO_HEADERS)); 8139942c5e3cSpl196000 } else { 8140942c5e3cSpl196000 /* Driver not initialized yet, no firmware or header output */ 8141942c5e3cSpl196000 if (aac_debug_flags & AACDB_FLAGS_KERNEL_PRINT) 8142942c5e3cSpl196000 aac_cmn_err(softs, lev, sl, 1); 8143942c5e3cSpl196000 } 8144942c5e3cSpl196000 mutex_exit(&aac_prt_mutex); 8145942c5e3cSpl196000 } 8146942c5e3cSpl196000 8147942c5e3cSpl196000 /* 8148942c5e3cSpl196000 * Translate command number to description string 8149942c5e3cSpl196000 */ 8150942c5e3cSpl196000 static char * 8151942c5e3cSpl196000 aac_cmd_name(int cmd, struct aac_key_strings *cmdlist) 8152942c5e3cSpl196000 { 8153942c5e3cSpl196000 int i; 8154942c5e3cSpl196000 8155942c5e3cSpl196000 for (i = 0; cmdlist[i].key != -1; i++) { 8156942c5e3cSpl196000 if (cmd == cmdlist[i].key) 8157942c5e3cSpl196000 return (cmdlist[i].message); 8158942c5e3cSpl196000 } 8159942c5e3cSpl196000 return (NULL); 8160942c5e3cSpl196000 } 8161942c5e3cSpl196000 8162942c5e3cSpl196000 static void 8163942c5e3cSpl196000 aac_print_scmd(struct aac_softstate *softs, struct aac_cmd *acp) 8164942c5e3cSpl196000 { 8165942c5e3cSpl196000 struct scsi_pkt *pkt = acp->pkt; 8166942c5e3cSpl196000 struct scsi_address *ap = &pkt->pkt_address; 816758bc78c7SXin Chen int is_pd = 0; 8168942c5e3cSpl196000 int ctl = ddi_get_instance(softs->devinfo_p); 8169942c5e3cSpl196000 int tgt = ap->a_target; 8170942c5e3cSpl196000 int lun = ap->a_lun; 8171a74f7440Spl196000 union scsi_cdb *cdbp = (void *)pkt->pkt_cdbp; 8172942c5e3cSpl196000 uchar_t cmd = cdbp->scc_cmd; 8173942c5e3cSpl196000 char *desc; 8174942c5e3cSpl196000 817558bc78c7SXin Chen if (tgt >= AAC_MAX_LD) { 817658bc78c7SXin Chen is_pd = 1; 817758bc78c7SXin Chen ctl = ((struct aac_nondasd *)acp->dvp)->bus; 817858bc78c7SXin Chen tgt = ((struct aac_nondasd *)acp->dvp)->tid; 817958bc78c7SXin Chen lun = 0; 818058bc78c7SXin Chen } 818158bc78c7SXin Chen 8182942c5e3cSpl196000 if ((desc = aac_cmd_name(cmd, 8183942c5e3cSpl196000 (struct aac_key_strings *)scsi_cmds)) == NULL) { 8184942c5e3cSpl196000 aac_printf(softs, CE_NOTE, 818558bc78c7SXin Chen "SCMD> Unknown(0x%2x) --> c%dt%dL%d %s", 818658bc78c7SXin Chen cmd, ctl, tgt, lun, is_pd ? "(pd)" : ""); 8187942c5e3cSpl196000 return; 8188942c5e3cSpl196000 } 8189942c5e3cSpl196000 8190942c5e3cSpl196000 switch (cmd) { 8191942c5e3cSpl196000 case SCMD_READ: 8192942c5e3cSpl196000 case SCMD_WRITE: 8193942c5e3cSpl196000 aac_printf(softs, CE_NOTE, 819458bc78c7SXin Chen "SCMD> %s 0x%x[%d] %s --> c%dt%dL%d %s", 8195942c5e3cSpl196000 desc, GETG0ADDR(cdbp), GETG0COUNT(cdbp), 8196942c5e3cSpl196000 (acp->flags & AAC_CMD_NO_INTR) ? "poll" : "intr", 819758bc78c7SXin Chen ctl, tgt, lun, is_pd ? "(pd)" : ""); 8198942c5e3cSpl196000 break; 8199942c5e3cSpl196000 case SCMD_READ_G1: 8200942c5e3cSpl196000 case SCMD_WRITE_G1: 8201942c5e3cSpl196000 aac_printf(softs, CE_NOTE, 820258bc78c7SXin Chen "SCMD> %s 0x%x[%d] %s --> c%dt%dL%d %s", 8203942c5e3cSpl196000 desc, GETG1ADDR(cdbp), GETG1COUNT(cdbp), 8204942c5e3cSpl196000 (acp->flags & AAC_CMD_NO_INTR) ? "poll" : "intr", 820558bc78c7SXin Chen ctl, tgt, lun, is_pd ? "(pd)" : ""); 8206942c5e3cSpl196000 break; 8207942c5e3cSpl196000 case SCMD_READ_G4: 8208942c5e3cSpl196000 case SCMD_WRITE_G4: 8209942c5e3cSpl196000 aac_printf(softs, CE_NOTE, 821058bc78c7SXin Chen "SCMD> %s 0x%x.%08x[%d] %s --> c%dt%dL%d %s", 8211942c5e3cSpl196000 desc, GETG4ADDR(cdbp), GETG4ADDRTL(cdbp), 8212942c5e3cSpl196000 GETG4COUNT(cdbp), 8213942c5e3cSpl196000 (acp->flags & AAC_CMD_NO_INTR) ? "poll" : "intr", 821458bc78c7SXin Chen ctl, tgt, lun, is_pd ? "(pd)" : ""); 821558bc78c7SXin Chen break; 821658bc78c7SXin Chen case SCMD_READ_G5: 821758bc78c7SXin Chen case SCMD_WRITE_G5: 821858bc78c7SXin Chen aac_printf(softs, CE_NOTE, 821958bc78c7SXin Chen "SCMD> %s 0x%x[%d] %s --> c%dt%dL%d %s", 822058bc78c7SXin Chen desc, GETG5ADDR(cdbp), GETG5COUNT(cdbp), 822158bc78c7SXin Chen (acp->flags & AAC_CMD_NO_INTR) ? "poll" : "intr", 822258bc78c7SXin Chen ctl, tgt, lun, is_pd ? "(pd)" : ""); 8223942c5e3cSpl196000 break; 8224942c5e3cSpl196000 default: 822558bc78c7SXin Chen aac_printf(softs, CE_NOTE, "SCMD> %s --> c%dt%dL%d %s", 822658bc78c7SXin Chen desc, ctl, tgt, lun, is_pd ? "(pd)" : ""); 8227942c5e3cSpl196000 } 8228942c5e3cSpl196000 } 8229942c5e3cSpl196000 8230942c5e3cSpl196000 void 823158bc78c7SXin Chen aac_print_fib(struct aac_softstate *softs, struct aac_slot *slotp) 8232942c5e3cSpl196000 { 823358bc78c7SXin Chen struct aac_cmd *acp = slotp->acp; 823458bc78c7SXin Chen struct aac_fib *fibp = slotp->fibp; 823558bc78c7SXin Chen ddi_acc_handle_t acc = slotp->fib_acc_handle; 8236942c5e3cSpl196000 uint16_t fib_size; 823758bc78c7SXin Chen uint32_t fib_cmd, sub_cmd; 8238942c5e3cSpl196000 char *cmdstr, *subcmdstr; 823958bc78c7SXin Chen char *caller; 824058bc78c7SXin Chen int i; 8241942c5e3cSpl196000 824258bc78c7SXin Chen if (acp) { 824358bc78c7SXin Chen if (!(softs->debug_fib_flags & acp->fib_flags)) 824458bc78c7SXin Chen return; 824558bc78c7SXin Chen if (acp->fib_flags & AACDB_FLAGS_FIB_SCMD) 824658bc78c7SXin Chen caller = "SCMD"; 824758bc78c7SXin Chen else if (acp->fib_flags & AACDB_FLAGS_FIB_IOCTL) 824858bc78c7SXin Chen caller = "IOCTL"; 824958bc78c7SXin Chen else if (acp->fib_flags & AACDB_FLAGS_FIB_SRB) 825058bc78c7SXin Chen caller = "SRB"; 825158bc78c7SXin Chen else 825258bc78c7SXin Chen return; 825358bc78c7SXin Chen } else { 825458bc78c7SXin Chen if (!(softs->debug_fib_flags & AACDB_FLAGS_FIB_SYNC)) 825558bc78c7SXin Chen return; 825658bc78c7SXin Chen caller = "SYNC"; 825758bc78c7SXin Chen } 825858bc78c7SXin Chen 825958bc78c7SXin Chen fib_cmd = ddi_get16(acc, &fibp->Header.Command); 8260942c5e3cSpl196000 cmdstr = aac_cmd_name(fib_cmd, aac_fib_cmds); 826158bc78c7SXin Chen sub_cmd = (uint32_t)-1; 8262942c5e3cSpl196000 subcmdstr = NULL; 8263942c5e3cSpl196000 826458bc78c7SXin Chen /* Print FIB header */ 826558bc78c7SXin Chen if (softs->debug_fib_flags & AACDB_FLAGS_FIB_HEADER) { 826658bc78c7SXin Chen aac_printf(softs, CE_NOTE, "FIB> from %s", caller); 826758bc78c7SXin Chen aac_printf(softs, CE_NOTE, " XferState %d", 826858bc78c7SXin Chen ddi_get32(acc, &fibp->Header.XferState)); 826958bc78c7SXin Chen aac_printf(softs, CE_NOTE, " Command %d", 827058bc78c7SXin Chen ddi_get16(acc, &fibp->Header.Command)); 827158bc78c7SXin Chen aac_printf(softs, CE_NOTE, " StructType %d", 827258bc78c7SXin Chen ddi_get8(acc, &fibp->Header.StructType)); 827358bc78c7SXin Chen aac_printf(softs, CE_NOTE, " Flags 0x%x", 827458bc78c7SXin Chen ddi_get8(acc, &fibp->Header.Flags)); 827558bc78c7SXin Chen aac_printf(softs, CE_NOTE, " Size %d", 827658bc78c7SXin Chen ddi_get16(acc, &fibp->Header.Size)); 827758bc78c7SXin Chen aac_printf(softs, CE_NOTE, " SenderSize %d", 827858bc78c7SXin Chen ddi_get16(acc, &fibp->Header.SenderSize)); 827958bc78c7SXin Chen aac_printf(softs, CE_NOTE, " SenderAddr 0x%x", 828058bc78c7SXin Chen ddi_get32(acc, &fibp->Header.SenderFibAddress)); 828158bc78c7SXin Chen aac_printf(softs, CE_NOTE, " RcvrAddr 0x%x", 828258bc78c7SXin Chen ddi_get32(acc, &fibp->Header.ReceiverFibAddress)); 828358bc78c7SXin Chen aac_printf(softs, CE_NOTE, " SenderData 0x%x", 828458bc78c7SXin Chen ddi_get32(acc, &fibp->Header.SenderData)); 828558bc78c7SXin Chen } 828658bc78c7SXin Chen 828758bc78c7SXin Chen /* Print FIB data */ 8288942c5e3cSpl196000 switch (fib_cmd) { 8289942c5e3cSpl196000 case ContainerCommand: 829058bc78c7SXin Chen sub_cmd = ddi_get32(acc, 829158bc78c7SXin Chen (void *)&(((uint32_t *)(void *)&fibp->data[0])[0])); 8292942c5e3cSpl196000 subcmdstr = aac_cmd_name(sub_cmd, aac_ctvm_subcmds); 8293942c5e3cSpl196000 if (subcmdstr == NULL) 8294942c5e3cSpl196000 break; 829558bc78c7SXin Chen 829658bc78c7SXin Chen switch (sub_cmd) { 829758bc78c7SXin Chen case VM_ContainerConfig: { 829858bc78c7SXin Chen struct aac_Container *pContainer = 829958bc78c7SXin Chen (struct aac_Container *)fibp->data; 830058bc78c7SXin Chen 8301942c5e3cSpl196000 fib_cmd = sub_cmd; 8302942c5e3cSpl196000 cmdstr = subcmdstr; 830358bc78c7SXin Chen sub_cmd = (uint32_t)-1; 8304942c5e3cSpl196000 subcmdstr = NULL; 8305942c5e3cSpl196000 830658bc78c7SXin Chen sub_cmd = ddi_get32(acc, 830758bc78c7SXin Chen &pContainer->CTCommand.command); 8308942c5e3cSpl196000 subcmdstr = aac_cmd_name(sub_cmd, aac_ct_subcmds); 8309942c5e3cSpl196000 if (subcmdstr == NULL) 8310942c5e3cSpl196000 break; 8311942c5e3cSpl196000 aac_printf(softs, CE_NOTE, "FIB> %s (0x%x, 0x%x, 0x%x)", 8312942c5e3cSpl196000 subcmdstr, 831358bc78c7SXin Chen ddi_get32(acc, &pContainer->CTCommand.param[0]), 831458bc78c7SXin Chen ddi_get32(acc, &pContainer->CTCommand.param[1]), 831558bc78c7SXin Chen ddi_get32(acc, &pContainer->CTCommand.param[2])); 8316942c5e3cSpl196000 return; 831758bc78c7SXin Chen } 831858bc78c7SXin Chen 8319942c5e3cSpl196000 case VM_Ioctl: 832058bc78c7SXin Chen fib_cmd = sub_cmd; 832158bc78c7SXin Chen cmdstr = subcmdstr; 832258bc78c7SXin Chen sub_cmd = (uint32_t)-1; 832358bc78c7SXin Chen subcmdstr = NULL; 832458bc78c7SXin Chen 832558bc78c7SXin Chen sub_cmd = ddi_get32(acc, 832658bc78c7SXin Chen (void *)&(((uint32_t *)(void *)&fibp->data[0])[4])); 8327942c5e3cSpl196000 subcmdstr = aac_cmd_name(sub_cmd, aac_ioctl_subcmds); 8328942c5e3cSpl196000 break; 832958bc78c7SXin Chen 833058bc78c7SXin Chen case VM_CtBlockRead: 833158bc78c7SXin Chen case VM_CtBlockWrite: { 833258bc78c7SXin Chen struct aac_blockread *br = 833358bc78c7SXin Chen (struct aac_blockread *)fibp->data; 833458bc78c7SXin Chen struct aac_sg_table *sg = &br->SgMap; 833558bc78c7SXin Chen uint32_t sgcount = ddi_get32(acc, &sg->SgCount); 833658bc78c7SXin Chen 833758bc78c7SXin Chen aac_printf(softs, CE_NOTE, 833858bc78c7SXin Chen "FIB> %s Container %d 0x%x/%d", subcmdstr, 833958bc78c7SXin Chen ddi_get32(acc, &br->ContainerId), 834058bc78c7SXin Chen ddi_get32(acc, &br->BlockNumber), 834158bc78c7SXin Chen ddi_get32(acc, &br->ByteCount)); 834258bc78c7SXin Chen for (i = 0; i < sgcount; i++) 834358bc78c7SXin Chen aac_printf(softs, CE_NOTE, 834458bc78c7SXin Chen " %d: 0x%08x/%d", i, 834558bc78c7SXin Chen ddi_get32(acc, &sg->SgEntry[i].SgAddress), 834658bc78c7SXin Chen ddi_get32(acc, &sg->SgEntry[i]. \ 834758bc78c7SXin Chen SgByteCount)); 834858bc78c7SXin Chen return; 834958bc78c7SXin Chen } 8350942c5e3cSpl196000 } 8351942c5e3cSpl196000 break; 8352942c5e3cSpl196000 835358bc78c7SXin Chen case ContainerCommand64: { 835458bc78c7SXin Chen struct aac_blockread64 *br = 835558bc78c7SXin Chen (struct aac_blockread64 *)fibp->data; 835658bc78c7SXin Chen struct aac_sg_table64 *sg = &br->SgMap64; 835758bc78c7SXin Chen uint32_t sgcount = ddi_get32(acc, &sg->SgCount); 835858bc78c7SXin Chen uint64_t sgaddr; 835958bc78c7SXin Chen 836058bc78c7SXin Chen sub_cmd = br->Command; 836158bc78c7SXin Chen subcmdstr = NULL; 836258bc78c7SXin Chen if (sub_cmd == VM_CtHostRead64) 836358bc78c7SXin Chen subcmdstr = "VM_CtHostRead64"; 836458bc78c7SXin Chen else if (sub_cmd == VM_CtHostWrite64) 836558bc78c7SXin Chen subcmdstr = "VM_CtHostWrite64"; 836658bc78c7SXin Chen else 836758bc78c7SXin Chen break; 836858bc78c7SXin Chen 836958bc78c7SXin Chen aac_printf(softs, CE_NOTE, 837058bc78c7SXin Chen "FIB> %s Container %d 0x%x/%d", subcmdstr, 837158bc78c7SXin Chen ddi_get16(acc, &br->ContainerId), 837258bc78c7SXin Chen ddi_get32(acc, &br->BlockNumber), 837358bc78c7SXin Chen ddi_get16(acc, &br->SectorCount)); 837458bc78c7SXin Chen for (i = 0; i < sgcount; i++) { 837558bc78c7SXin Chen sgaddr = ddi_get64(acc, 837658bc78c7SXin Chen &sg->SgEntry64[i].SgAddress); 837758bc78c7SXin Chen aac_printf(softs, CE_NOTE, 837858bc78c7SXin Chen " %d: 0x%08x.%08x/%d", i, 837958bc78c7SXin Chen AAC_MS32(sgaddr), AAC_LS32(sgaddr), 838058bc78c7SXin Chen ddi_get32(acc, &sg->SgEntry64[i]. \ 838158bc78c7SXin Chen SgByteCount)); 838258bc78c7SXin Chen } 838358bc78c7SXin Chen return; 838458bc78c7SXin Chen } 838558bc78c7SXin Chen 838658bc78c7SXin Chen case RawIo: { 838758bc78c7SXin Chen struct aac_raw_io *io = (struct aac_raw_io *)fibp->data; 838858bc78c7SXin Chen struct aac_sg_tableraw *sg = &io->SgMapRaw; 838958bc78c7SXin Chen uint32_t sgcount = ddi_get32(acc, &sg->SgCount); 839058bc78c7SXin Chen uint64_t sgaddr; 839158bc78c7SXin Chen 839258bc78c7SXin Chen aac_printf(softs, CE_NOTE, 839358bc78c7SXin Chen "FIB> RawIo Container %d 0x%llx/%d 0x%x", 839458bc78c7SXin Chen ddi_get16(acc, &io->ContainerId), 839558bc78c7SXin Chen ddi_get64(acc, &io->BlockNumber), 839658bc78c7SXin Chen ddi_get32(acc, &io->ByteCount), 839758bc78c7SXin Chen ddi_get16(acc, &io->Flags)); 839858bc78c7SXin Chen for (i = 0; i < sgcount; i++) { 839958bc78c7SXin Chen sgaddr = ddi_get64(acc, &sg->SgEntryRaw[i].SgAddress); 840058bc78c7SXin Chen aac_printf(softs, CE_NOTE, " %d: 0x%08x.%08x/%d", i, 840158bc78c7SXin Chen AAC_MS32(sgaddr), AAC_LS32(sgaddr), 840258bc78c7SXin Chen ddi_get32(acc, &sg->SgEntryRaw[i].SgByteCount)); 840358bc78c7SXin Chen } 840458bc78c7SXin Chen return; 840558bc78c7SXin Chen } 840658bc78c7SXin Chen 8407942c5e3cSpl196000 case ClusterCommand: 840858bc78c7SXin Chen sub_cmd = ddi_get32(acc, 840958bc78c7SXin Chen (void *)&(((uint32_t *)(void *)fibp->data)[0])); 8410942c5e3cSpl196000 subcmdstr = aac_cmd_name(sub_cmd, aac_cl_subcmds); 8411942c5e3cSpl196000 break; 8412942c5e3cSpl196000 8413942c5e3cSpl196000 case AifRequest: 841458bc78c7SXin Chen sub_cmd = ddi_get32(acc, 841558bc78c7SXin Chen (void *)&(((uint32_t *)(void *)fibp->data)[0])); 8416942c5e3cSpl196000 subcmdstr = aac_cmd_name(sub_cmd, aac_aif_subcmds); 8417942c5e3cSpl196000 break; 8418942c5e3cSpl196000 8419942c5e3cSpl196000 default: 8420942c5e3cSpl196000 break; 8421942c5e3cSpl196000 } 8422942c5e3cSpl196000 842358bc78c7SXin Chen fib_size = ddi_get16(acc, &(fibp->Header.Size)); 8424942c5e3cSpl196000 if (subcmdstr) 8425942c5e3cSpl196000 aac_printf(softs, CE_NOTE, "FIB> %s, sz=%d", 8426942c5e3cSpl196000 subcmdstr, fib_size); 842758bc78c7SXin Chen else if (cmdstr && sub_cmd == (uint32_t)-1) 8428942c5e3cSpl196000 aac_printf(softs, CE_NOTE, "FIB> %s, sz=%d", 8429942c5e3cSpl196000 cmdstr, fib_size); 8430942c5e3cSpl196000 else if (cmdstr) 8431942c5e3cSpl196000 aac_printf(softs, CE_NOTE, "FIB> %s: Unknown(0x%x), sz=%d", 8432942c5e3cSpl196000 cmdstr, sub_cmd, fib_size); 8433942c5e3cSpl196000 else 8434942c5e3cSpl196000 aac_printf(softs, CE_NOTE, "FIB> Unknown(0x%x), sz=%d", 8435942c5e3cSpl196000 fib_cmd, fib_size); 8436942c5e3cSpl196000 } 8437942c5e3cSpl196000 8438942c5e3cSpl196000 static void 8439942c5e3cSpl196000 aac_print_aif(struct aac_softstate *softs, struct aac_aif_command *aif) 8440942c5e3cSpl196000 { 8441942c5e3cSpl196000 int aif_command; 8442942c5e3cSpl196000 uint32_t aif_seqnumber; 8443942c5e3cSpl196000 int aif_en_type; 8444942c5e3cSpl196000 char *str; 8445942c5e3cSpl196000 8446942c5e3cSpl196000 aif_command = LE_32(aif->command); 8447942c5e3cSpl196000 aif_seqnumber = LE_32(aif->seqNumber); 8448942c5e3cSpl196000 aif_en_type = LE_32(aif->data.EN.type); 8449942c5e3cSpl196000 8450942c5e3cSpl196000 switch (aif_command) { 8451942c5e3cSpl196000 case AifCmdEventNotify: 8452942c5e3cSpl196000 str = aac_cmd_name(aif_en_type, aac_aifens); 8453942c5e3cSpl196000 if (str) 8454942c5e3cSpl196000 aac_printf(softs, CE_NOTE, "AIF! %s", str); 8455942c5e3cSpl196000 else 8456942c5e3cSpl196000 aac_printf(softs, CE_NOTE, "AIF! Unknown(0x%x)", 8457942c5e3cSpl196000 aif_en_type); 8458942c5e3cSpl196000 break; 8459942c5e3cSpl196000 8460942c5e3cSpl196000 case AifCmdJobProgress: 8461942c5e3cSpl196000 switch (LE_32(aif->data.PR[0].status)) { 8462942c5e3cSpl196000 case AifJobStsSuccess: 8463942c5e3cSpl196000 str = "success"; break; 8464942c5e3cSpl196000 case AifJobStsFinished: 8465942c5e3cSpl196000 str = "finished"; break; 8466942c5e3cSpl196000 case AifJobStsAborted: 8467942c5e3cSpl196000 str = "aborted"; break; 8468942c5e3cSpl196000 case AifJobStsFailed: 8469942c5e3cSpl196000 str = "failed"; break; 8470942c5e3cSpl196000 case AifJobStsSuspended: 8471942c5e3cSpl196000 str = "suspended"; break; 8472942c5e3cSpl196000 case AifJobStsRunning: 8473942c5e3cSpl196000 str = "running"; break; 8474942c5e3cSpl196000 default: 8475942c5e3cSpl196000 str = "unknown"; break; 8476942c5e3cSpl196000 } 8477942c5e3cSpl196000 aac_printf(softs, CE_NOTE, 8478942c5e3cSpl196000 "AIF! JobProgress (%d) - %s (%d, %d)", 8479942c5e3cSpl196000 aif_seqnumber, str, 8480942c5e3cSpl196000 LE_32(aif->data.PR[0].currentTick), 8481942c5e3cSpl196000 LE_32(aif->data.PR[0].finalTick)); 8482942c5e3cSpl196000 break; 8483942c5e3cSpl196000 8484942c5e3cSpl196000 case AifCmdAPIReport: 8485942c5e3cSpl196000 aac_printf(softs, CE_NOTE, "AIF! APIReport (%d)", 8486942c5e3cSpl196000 aif_seqnumber); 8487942c5e3cSpl196000 break; 8488942c5e3cSpl196000 8489942c5e3cSpl196000 case AifCmdDriverNotify: 8490942c5e3cSpl196000 aac_printf(softs, CE_NOTE, "AIF! DriverNotify (%d)", 8491942c5e3cSpl196000 aif_seqnumber); 8492942c5e3cSpl196000 break; 8493942c5e3cSpl196000 8494942c5e3cSpl196000 default: 8495942c5e3cSpl196000 aac_printf(softs, CE_NOTE, "AIF! AIF %d (%d)", 8496942c5e3cSpl196000 aif_command, aif_seqnumber); 8497942c5e3cSpl196000 break; 8498942c5e3cSpl196000 } 8499942c5e3cSpl196000 } 8500942c5e3cSpl196000 8501942c5e3cSpl196000 #endif /* DEBUG */ 8502