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