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