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