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