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