1 /* $OpenBSD: aac.c,v 1.96 2023/09/11 12:10:47 mvs Exp $ */ 2 3 /*- 4 * Copyright (c) 2000 Michael Smith 5 * Copyright (c) 2001 Scott Long 6 * Copyright (c) 2000 BSDi 7 * Copyright (c) 2001 Adaptec, Inc. 8 * Copyright (c) 2000 Niklas Hallqvist 9 * Copyright (c) 2004 Nathan Binkert 10 * All rights reserved. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * $FreeBSD: /c/ncvs/src/sys/dev/aac/aac.c,v 1.1 2000/09/13 03:20:34 msmith Exp $ 34 */ 35 36 /* 37 * Driver for the Adaptec 'FSA' family of PCI/SCSI RAID adapters. 38 */ 39 40 /* 41 * This driver would not have rewritten for OpenBSD if it was not for the 42 * hardware donation from Nocom. I want to thank them for their support. 43 * Of course, credit should go to Mike Smith for the original work he did 44 * in the FreeBSD driver where I found lots of reusable code and inspiration. 45 * - Niklas Hallqvist 46 */ 47 48 #include <sys/param.h> 49 #include <sys/systm.h> 50 #include <sys/buf.h> 51 #include <sys/device.h> 52 #include <sys/kernel.h> 53 #include <sys/kthread.h> 54 #include <sys/malloc.h> 55 #include <sys/rwlock.h> 56 #include <sys/time.h> 57 58 #include <machine/bus.h> 59 60 #include <uvm/uvm_extern.h> 61 62 #include <scsi/scsi_all.h> 63 #include <scsi/scsi_disk.h> 64 #include <scsi/scsiconf.h> 65 66 #include <dev/ic/aacreg.h> 67 #include <dev/ic/aacvar.h> 68 #include <dev/ic/aac_tables.h> 69 70 /* Geometry constants. */ 71 #define AAC_MAXCYLS 1024 72 #define AAC_HEADS 64 73 #define AAC_SECS 32 /* mapping 64*32 */ 74 #define AAC_MEDHEADS 127 75 #define AAC_MEDSECS 63 /* mapping 127*63 */ 76 #define AAC_BIGHEADS 255 77 #define AAC_BIGSECS 63 /* mapping 255*63 */ 78 #define AAC_SECS32 0x1f /* round capacity */ 79 80 struct scsi_xfer; 81 82 char *aac_describe_code(struct aac_code_lookup *, u_int32_t); 83 void aac_describe_controller(struct aac_softc *); 84 int aac_enqueue_fib(struct aac_softc *, int, struct aac_command *); 85 int aac_dequeue_fib(struct aac_softc *, int, u_int32_t *, 86 struct aac_fib **); 87 int aac_enqueue_response(struct aac_softc *sc, int queue, 88 struct aac_fib *fib); 89 90 void aac_eval_mapping(u_int32_t, int *, int *, int *); 91 void aac_print_printf(struct aac_softc *); 92 int aac_init(struct aac_softc *); 93 int aac_check_firmware(struct aac_softc *); 94 void aac_internal_cache_cmd(struct scsi_xfer *); 95 96 /* Command Processing */ 97 void aac_timeout(struct aac_softc *); 98 void aac_command_timeout(struct aac_command *); 99 int aac_map_command(struct aac_command *); 100 void aac_complete(void *); 101 int aac_bio_command(struct aac_softc *, struct aac_command **); 102 void aac_bio_complete(struct aac_command *); 103 int aac_wait_command(struct aac_command *, int); 104 void aac_create_thread(void *); 105 void aac_command_thread(void *); 106 107 /* Command Buffer Management */ 108 void aac_map_command_sg(void *, bus_dma_segment_t *, int, int); 109 int aac_alloc_commands(struct aac_softc *); 110 void aac_free_commands(struct aac_softc *); 111 void aac_unmap_command(struct aac_command *); 112 int aac_wait_command(struct aac_command *, int); 113 void * aac_alloc_command(void *); 114 void aac_scrub_command(struct aac_command *); 115 void aac_release_command(void *, void *); 116 int aac_alloc_sync_fib(struct aac_softc *, struct aac_fib **, int); 117 void aac_release_sync_fib(struct aac_softc *); 118 int aac_sync_fib(struct aac_softc *, u_int32_t, u_int32_t, 119 struct aac_fib *, u_int16_t); 120 121 void aac_scsi_cmd(struct scsi_xfer *); 122 void aac_startio(struct aac_softc *); 123 void aac_startup(struct aac_softc *); 124 int aac_sync_command(struct aac_softc *, u_int32_t, u_int32_t, 125 u_int32_t, u_int32_t, u_int32_t, u_int32_t *); 126 127 struct cfdriver aac_cd = { 128 NULL, "aac", DV_DULL 129 }; 130 131 const struct scsi_adapter aac_switch = { 132 aac_scsi_cmd, NULL, NULL, NULL, NULL 133 }; 134 135 /* Falcon/PPC interface */ 136 int aac_fa_get_fwstatus(struct aac_softc *); 137 void aac_fa_qnotify(struct aac_softc *, int); 138 int aac_fa_get_istatus(struct aac_softc *); 139 void aac_fa_clear_istatus(struct aac_softc *, int); 140 void aac_fa_set_mailbox(struct aac_softc *, u_int32_t, u_int32_t, u_int32_t, 141 u_int32_t, u_int32_t); 142 int aac_fa_get_mailbox(struct aac_softc *, int); 143 void aac_fa_set_interrupts(struct aac_softc *, int); 144 145 struct aac_interface aac_fa_interface = { 146 aac_fa_get_fwstatus, 147 aac_fa_qnotify, 148 aac_fa_get_istatus, 149 aac_fa_clear_istatus, 150 aac_fa_set_mailbox, 151 aac_fa_get_mailbox, 152 aac_fa_set_interrupts 153 }; 154 155 /* StrongARM interface */ 156 int aac_sa_get_fwstatus(struct aac_softc *); 157 void aac_sa_qnotify(struct aac_softc *, int); 158 int aac_sa_get_istatus(struct aac_softc *); 159 void aac_sa_clear_istatus(struct aac_softc *, int); 160 void aac_sa_set_mailbox(struct aac_softc *, u_int32_t, u_int32_t, 161 u_int32_t, u_int32_t, u_int32_t); 162 int aac_sa_get_mailbox(struct aac_softc *, int); 163 void aac_sa_set_interrupts(struct aac_softc *, int); 164 165 struct aac_interface aac_sa_interface = { 166 aac_sa_get_fwstatus, 167 aac_sa_qnotify, 168 aac_sa_get_istatus, 169 aac_sa_clear_istatus, 170 aac_sa_set_mailbox, 171 aac_sa_get_mailbox, 172 aac_sa_set_interrupts 173 }; 174 175 /* i960Rx interface */ 176 int aac_rx_get_fwstatus(struct aac_softc *); 177 void aac_rx_qnotify(struct aac_softc *, int); 178 int aac_rx_get_istatus(struct aac_softc *); 179 void aac_rx_clear_istatus(struct aac_softc *, int); 180 void aac_rx_set_mailbox(struct aac_softc *, u_int32_t, u_int32_t, 181 u_int32_t, u_int32_t, u_int32_t); 182 int aac_rx_get_mailbox(struct aac_softc *, int); 183 void aac_rx_set_interrupts(struct aac_softc *, int); 184 185 struct aac_interface aac_rx_interface = { 186 aac_rx_get_fwstatus, 187 aac_rx_qnotify, 188 aac_rx_get_istatus, 189 aac_rx_clear_istatus, 190 aac_rx_set_mailbox, 191 aac_rx_get_mailbox, 192 aac_rx_set_interrupts 193 }; 194 195 /* Rocket/MIPS interface */ 196 int aac_rkt_get_fwstatus(struct aac_softc *); 197 void aac_rkt_qnotify(struct aac_softc *, int); 198 int aac_rkt_get_istatus(struct aac_softc *); 199 void aac_rkt_clear_istatus(struct aac_softc *, int); 200 void aac_rkt_set_mailbox(struct aac_softc *, u_int32_t, 201 u_int32_t, u_int32_t, 202 u_int32_t, u_int32_t); 203 int aac_rkt_get_mailbox(struct aac_softc *, int); 204 void aac_rkt_set_interrupts(struct aac_softc *, int); 205 206 struct aac_interface aac_rkt_interface = { 207 aac_rkt_get_fwstatus, 208 aac_rkt_qnotify, 209 aac_rkt_get_istatus, 210 aac_rkt_clear_istatus, 211 aac_rkt_set_mailbox, 212 aac_rkt_get_mailbox, 213 aac_rkt_set_interrupts 214 }; 215 216 #ifdef AAC_DEBUG 217 int aac_debug = AAC_DEBUG; 218 #endif 219 220 int 221 aac_attach(struct aac_softc *sc) 222 { 223 struct scsibus_attach_args saa; 224 int error; 225 226 /* 227 * Initialise per-controller queues. 228 */ 229 mtx_init(&sc->aac_free_mtx, IPL_BIO); 230 aac_initq_free(sc); 231 aac_initq_ready(sc); 232 aac_initq_busy(sc); 233 aac_initq_bio(sc); 234 235 /* disable interrupts before we enable anything */ 236 AAC_MASK_INTERRUPTS(sc); 237 238 /* mark controller as suspended until we get ourselves organised */ 239 sc->aac_state |= AAC_STATE_SUSPEND; 240 241 /* 242 * Check that the firmware on the card is supported. 243 */ 244 error = aac_check_firmware(sc); 245 if (error) 246 return (error); 247 248 /* 249 * Initialize locks 250 */ 251 AAC_LOCK_INIT(&sc->aac_sync_lock, "AAC sync FIB lock"); 252 AAC_LOCK_INIT(&sc->aac_aifq_lock, "AAC AIF lock"); 253 AAC_LOCK_INIT(&sc->aac_io_lock, "AAC I/O lock"); 254 AAC_LOCK_INIT(&sc->aac_container_lock, "AAC container lock"); 255 TAILQ_INIT(&sc->aac_container_tqh); 256 257 /* Initialize the local AIF queue pointers */ 258 sc->aac_aifq_head = sc->aac_aifq_tail = AAC_AIFQ_LENGTH; 259 260 /* 261 * Initialise the adapter. 262 */ 263 error = aac_init(sc); 264 if (error) 265 return (error); 266 267 268 saa.saa_adapter_softc = sc; 269 saa.saa_adapter = &aac_switch; 270 saa.saa_adapter_buswidth = AAC_MAX_CONTAINERS; 271 saa.saa_adapter_target = SDEV_NO_ADAPTER_TARGET; 272 saa.saa_luns = 8; 273 saa.saa_openings = (sc->total_fibs - 8) / 274 (sc->aac_container_count ? sc->aac_container_count : 1); 275 saa.saa_pool = &sc->aac_iopool; 276 saa.saa_wwpn = saa.saa_wwnn = 0; 277 saa.saa_quirks = saa.saa_flags = 0; 278 279 config_found(&sc->aac_dev, &saa, scsiprint); 280 281 /* Create the AIF thread */ 282 sc->aifthread = 0; 283 sc->aifflags = 0; 284 kthread_create_deferred(aac_create_thread, sc); 285 286 return (0); 287 } 288 289 void 290 aac_create_thread(void *arg) 291 { 292 struct aac_softc *sc = arg; 293 294 if (kthread_create(aac_command_thread, sc, &sc->aifthread, 295 sc->aac_dev.dv_xname)) { 296 /* TODO disable aac */ 297 printf("%s: failed to create kernel thread, disabled", 298 sc->aac_dev.dv_xname); 299 } 300 AAC_DPRINTF(AAC_D_MISC, ("%s: aac_create_thread\n", 301 sc->aac_dev.dv_xname)); 302 303 } 304 305 /* 306 * Probe for containers, create disks. 307 */ 308 void 309 aac_startup(struct aac_softc *sc) 310 { 311 struct aac_fib *fib; 312 struct aac_mntinfo *mi; 313 struct aac_mntinforesp *mir = NULL; 314 int count = 0, i = 0; 315 316 317 aac_alloc_sync_fib(sc, &fib, 0); 318 mi = (struct aac_mntinfo *)&fib->data[0]; 319 320 AAC_DPRINTF(AAC_D_MISC, ("%s: aac startup\n", sc->aac_dev.dv_xname)); 321 322 sc->aac_container_count = 0; 323 /* loop over possible containers */ 324 do { 325 /* request information on this container */ 326 bzero(mi, sizeof(struct aac_mntinfo)); 327 mi->Command = VM_NameServe; 328 mi->MntType = FT_FILESYS; 329 mi->MntCount = i; 330 if (aac_sync_fib(sc, ContainerCommand, 0, fib, 331 sizeof(struct aac_mntinfo))) { 332 printf("%s: error probing container %d\n", 333 sc->aac_dev.dv_xname, i); 334 continue; 335 } 336 337 mir = (struct aac_mntinforesp *)&fib->data[0]; 338 /* XXX Need to check if count changed */ 339 count = mir->MntRespCount; 340 341 /* 342 * Check container volume type for validity. Note 343 * that many of the possible types may never show up. 344 */ 345 if (mir->Status == ST_OK && 346 mir->MntTable[0].VolType != CT_NONE) { 347 int drv_cyls, drv_hds, drv_secs; 348 349 AAC_DPRINTF(AAC_D_MISC, 350 ("%s: %d: id %x name '%.16s' size %u type %d\n", 351 sc->aac_dev.dv_xname, i, 352 mir->MntTable[0].ObjectId, 353 mir->MntTable[0].FileSystemName, 354 mir->MntTable[0].Capacity, 355 mir->MntTable[0].VolType)); 356 357 sc->aac_container_count++; 358 sc->aac_hdr[i].hd_present = 1; 359 sc->aac_hdr[i].hd_size = mir->MntTable[0].Capacity; 360 361 /* 362 * Evaluate mapping (sectors per head, heads per cyl) 363 */ 364 sc->aac_hdr[i].hd_size &= ~AAC_SECS32; 365 aac_eval_mapping(sc->aac_hdr[i].hd_size, &drv_cyls, 366 &drv_hds, &drv_secs); 367 sc->aac_hdr[i].hd_heads = drv_hds; 368 sc->aac_hdr[i].hd_secs = drv_secs; 369 /* Round the size */ 370 sc->aac_hdr[i].hd_size = drv_cyls * drv_hds * drv_secs; 371 372 sc->aac_hdr[i].hd_devtype = mir->MntTable[0].VolType; 373 374 /* XXX Save the name too for use in IDENTIFY later */ 375 } 376 377 i++; 378 } while ((i < count) && (i < AAC_MAX_CONTAINERS)); 379 380 aac_release_sync_fib(sc); 381 382 /* mark the controller up */ 383 sc->aac_state &= ~AAC_STATE_SUSPEND; 384 385 /* enable interrupts now */ 386 AAC_UNMASK_INTERRUPTS(sc); 387 } 388 389 /* 390 * Take an interrupt. 391 */ 392 int 393 aac_intr(void *arg) 394 { 395 struct aac_softc *sc = arg; 396 u_int16_t reason; 397 398 399 /* 400 * Read the status register directly. This is faster than taking the 401 * driver lock and reading the queues directly. It also saves having 402 * to turn parts of the driver lock into a spin mutex, which would be 403 * ugly. 404 */ 405 reason = AAC_GET_ISTATUS(sc); 406 AAC_CLEAR_ISTATUS(sc, reason); 407 (void)AAC_GET_ISTATUS(sc); 408 409 if (reason == 0) 410 return (0); 411 412 AAC_DPRINTF(AAC_D_INTR, ("%s: intr: sc=%p: reason=%#x\n", 413 sc->aac_dev.dv_xname, sc, reason)); 414 415 /* controller wants to talk to us */ 416 if (reason & (AAC_DB_PRINTF | AAC_DB_COMMAND_READY | 417 AAC_DB_RESPONSE_READY)) { 418 419 if (reason & AAC_DB_RESPONSE_READY) { 420 /* handle completion processing */ 421 if (sc->aifflags & AAC_AIFFLAGS_RUNNING) { 422 sc->aifflags |= AAC_AIFFLAGS_COMPLETE; 423 } else { 424 AAC_LOCK_ACQUIRE(&sc->aac_io_lock); 425 aac_complete(sc); 426 AAC_LOCK_RELEASE(&sc->aac_io_lock); 427 } 428 } 429 430 431 /* 432 * XXX Make sure that we don't get fooled by strange messages 433 * that start with a NULL. 434 */ 435 if (reason & AAC_DB_PRINTF) 436 if (sc->aac_common->ac_printf[0] == 0) 437 sc->aac_common->ac_printf[0] = 32; 438 439 /* 440 * This might miss doing the actual wakeup. However, the 441 * msleep that this is waking up has a timeout, so it will 442 * wake up eventually. AIFs and printfs are low enough 443 * priority that they can handle hanging out for a few seconds 444 * if needed. 445 */ 446 if (sc->aifthread) 447 wakeup(sc->aifthread); 448 449 } 450 451 return (1); 452 } 453 454 /* 455 * Command Processing 456 */ 457 458 /* 459 * Start as much queued I/O as possible on the controller 460 */ 461 void 462 aac_startio(struct aac_softc *sc) 463 { 464 struct aac_command *cm; 465 466 AAC_DPRINTF(AAC_D_CMD, ("%s: start command", sc->aac_dev.dv_xname)); 467 468 if (sc->flags & AAC_QUEUE_FRZN) { 469 AAC_DPRINTF(AAC_D_CMD, (": queue frozen")); 470 return; 471 } 472 473 AAC_DPRINTF(AAC_D_CMD, ("\n")); 474 475 for (;;) { 476 /* 477 * Try to get a command that's been put off for lack of 478 * resources 479 */ 480 cm = aac_dequeue_ready(sc); 481 482 /* 483 * Try to build a command off the bio queue (ignore error 484 * return) 485 */ 486 if (cm == NULL) { 487 AAC_DPRINTF(AAC_D_CMD, ("\n")); 488 aac_bio_command(sc, &cm); 489 AAC_DPRINTF(AAC_D_CMD, ("%s: start done bio", 490 sc->aac_dev.dv_xname)); 491 } 492 493 /* nothing to do? */ 494 if (cm == NULL) 495 break; 496 497 /* 498 * Try to give the command to the controller. Any error is 499 * catastrophic since it means that bus_dmamap_load() failed. 500 */ 501 if (aac_map_command(cm) != 0) 502 panic("aac: error mapping command %p", cm); 503 504 AAC_DPRINTF(AAC_D_CMD, ("\n%s: another command", 505 sc->aac_dev.dv_xname)); 506 } 507 508 AAC_DPRINTF(AAC_D_CMD, ("\n")); 509 } 510 511 /* 512 * Deliver a command to the controller; allocate controller resources at the 513 * last moment when possible. 514 */ 515 int 516 aac_map_command(struct aac_command *cm) 517 { 518 struct aac_softc *sc = cm->cm_sc; 519 int error = 0; 520 521 AAC_DPRINTF(AAC_D_CMD, (": map command")); 522 523 /* don't map more than once */ 524 if (cm->cm_flags & AAC_CMD_MAPPED) 525 panic("aac: command %p already mapped", cm); 526 527 if (cm->cm_datalen != 0) { 528 error = bus_dmamap_load(sc->aac_dmat, cm->cm_datamap, 529 cm->cm_data, cm->cm_datalen, NULL, 530 BUS_DMA_NOWAIT); 531 if (error) 532 return (error); 533 534 aac_map_command_sg(cm, cm->cm_datamap->dm_segs, 535 cm->cm_datamap->dm_nsegs, 0); 536 } else { 537 aac_map_command_sg(cm, NULL, 0, 0); 538 } 539 540 return (error); 541 } 542 543 /* 544 * Handle notification of one or more FIBs coming from the controller. 545 */ 546 void 547 aac_command_thread(void *arg) 548 { 549 struct aac_softc *sc = arg; 550 struct aac_fib *fib; 551 u_int32_t fib_size; 552 int size, retval; 553 554 AAC_DPRINTF(AAC_D_THREAD, ("%s: aac_command_thread: starting\n", 555 sc->aac_dev.dv_xname)); 556 AAC_LOCK_ACQUIRE(&sc->aac_io_lock); 557 sc->aifflags = AAC_AIFFLAGS_RUNNING; 558 559 while ((sc->aifflags & AAC_AIFFLAGS_EXIT) == 0) { 560 561 AAC_DPRINTF(AAC_D_THREAD, 562 ("%s: aac_command_thread: aifflags=%#x\n", 563 sc->aac_dev.dv_xname, sc->aifflags)); 564 retval = 0; 565 566 if ((sc->aifflags & AAC_AIFFLAGS_PENDING) == 0) { 567 AAC_DPRINTF(AAC_D_THREAD, 568 ("%s: command thread sleeping\n", 569 sc->aac_dev.dv_xname)); 570 AAC_LOCK_RELEASE(&sc->aac_io_lock); 571 retval = tsleep_nsec(sc->aifthread, PRIBIO, "aifthd", 572 SEC_TO_NSEC(AAC_PERIODIC_INTERVAL)); 573 AAC_LOCK_ACQUIRE(&sc->aac_io_lock); 574 } 575 576 if ((sc->aifflags & AAC_AIFFLAGS_COMPLETE) != 0) { 577 aac_complete(sc); 578 sc->aifflags &= ~AAC_AIFFLAGS_COMPLETE; 579 } 580 581 /* 582 * While we're here, check to see if any commands are stuck. 583 * This is pretty low-priority, so it's ok if it doesn't 584 * always fire. 585 */ 586 if (retval == EWOULDBLOCK) 587 aac_timeout(sc); 588 589 /* Check the hardware printf message buffer */ 590 if (sc->aac_common->ac_printf[0] != 0) 591 aac_print_printf(sc); 592 593 /* Also check to see if the adapter has a command for us. */ 594 while (aac_dequeue_fib(sc, AAC_HOST_NORM_CMD_QUEUE, 595 &fib_size, &fib) == 0) { 596 597 AAC_PRINT_FIB(sc, fib); 598 599 switch (fib->Header.Command) { 600 case AifRequest: 601 //aac_handle_aif(sc, fib); 602 break; 603 default: 604 printf("%s: unknown command from controller\n", 605 sc->aac_dev.dv_xname); 606 break; 607 } 608 609 if ((fib->Header.XferState == 0) || 610 (fib->Header.StructType != AAC_FIBTYPE_TFIB)) 611 break; 612 613 /* Return the AIF to the controller. */ 614 if (fib->Header.XferState & AAC_FIBSTATE_FROMADAP) { 615 fib->Header.XferState |= AAC_FIBSTATE_DONEHOST; 616 *(AAC_FSAStatus*)fib->data = ST_OK; 617 618 /* XXX Compute the Size field? */ 619 size = fib->Header.Size; 620 if (size > sizeof(struct aac_fib)) { 621 size = sizeof(struct aac_fib); 622 fib->Header.Size = size; 623 } 624 625 /* 626 * Since we did not generate this command, it 627 * cannot go through the normal 628 * enqueue->startio chain. 629 */ 630 aac_enqueue_response(sc, 631 AAC_ADAP_NORM_RESP_QUEUE, 632 fib); 633 } 634 } 635 } 636 sc->aifflags &= ~AAC_AIFFLAGS_RUNNING; 637 AAC_LOCK_RELEASE(&sc->aac_io_lock); 638 639 AAC_DPRINTF(AAC_D_THREAD, ("%s: aac_command_thread: exiting\n", 640 sc->aac_dev.dv_xname)); 641 kthread_exit(0); 642 } 643 644 /* 645 * Process completed commands. 646 */ 647 void 648 aac_complete(void *context) 649 { 650 struct aac_softc *sc = (struct aac_softc *)context; 651 struct aac_command *cm; 652 struct aac_fib *fib; 653 u_int32_t fib_size; 654 655 AAC_DPRINTF(AAC_D_CMD, ("%s: complete", sc->aac_dev.dv_xname)); 656 657 /* pull completed commands off the queue */ 658 for (;;) { 659 /* look for completed FIBs on our queue */ 660 if (aac_dequeue_fib(sc, AAC_HOST_NORM_RESP_QUEUE, &fib_size, 661 &fib)) 662 break; /* nothing to do */ 663 664 /* get the command, unmap and hand off for processing */ 665 cm = sc->aac_commands + fib->Header.SenderData; 666 if (cm == NULL) { 667 AAC_PRINT_FIB(sc, fib); 668 break; 669 } 670 671 aac_remove_busy(cm); 672 aac_unmap_command(cm); 673 cm->cm_flags |= AAC_CMD_COMPLETED; 674 675 /* is there a completion handler? */ 676 if (cm->cm_complete != NULL) { 677 cm->cm_complete(cm); 678 } else { 679 /* assume that someone is sleeping on this command */ 680 wakeup(cm); 681 } 682 } 683 684 AAC_DPRINTF(AAC_D_CMD, ("\n")); 685 /* see if we can start some more I/O */ 686 sc->flags &= ~AAC_QUEUE_FRZN; 687 aac_startio(sc); 688 } 689 690 /* 691 * Get a bio and build a command to go with it. 692 */ 693 int 694 aac_bio_command(struct aac_softc *sc, struct aac_command **cmp) 695 { 696 struct aac_command *cm; 697 struct aac_fib *fib; 698 struct scsi_xfer *xs; 699 u_int8_t opcode = 0; 700 701 AAC_DPRINTF(AAC_D_CMD, ("%s: bio command", sc->aac_dev.dv_xname)); 702 703 /* get the resources we will need */ 704 if ((cm = aac_dequeue_bio(sc)) == NULL) 705 goto fail; 706 xs = cm->cm_private; 707 708 /* build the FIB */ 709 fib = cm->cm_fib; 710 fib->Header.Size = sizeof(struct aac_fib_header); 711 fib->Header.XferState = 712 AAC_FIBSTATE_HOSTOWNED | 713 AAC_FIBSTATE_INITIALISED | 714 AAC_FIBSTATE_EMPTY | 715 AAC_FIBSTATE_FROMHOST | 716 AAC_FIBSTATE_REXPECTED | 717 AAC_FIBSTATE_NORM | 718 AAC_FIBSTATE_ASYNC | 719 AAC_FIBSTATE_FAST_RESPONSE; 720 721 switch(xs->cmd.opcode) { 722 case READ_COMMAND: 723 case READ_10: 724 opcode = READ_COMMAND; 725 break; 726 case WRITE_COMMAND: 727 case WRITE_10: 728 opcode = WRITE_COMMAND; 729 break; 730 default: 731 panic("%s: invalid opcode %#x", sc->aac_dev.dv_xname, 732 xs->cmd.opcode); 733 } 734 735 /* build the read/write request */ 736 if ((sc->flags & AAC_FLAGS_SG_64BIT) == 0) { 737 fib->Header.Command = ContainerCommand; 738 if (opcode == READ_COMMAND) { 739 struct aac_blockread *br; 740 br = (struct aac_blockread *)&fib->data[0]; 741 br->Command = VM_CtBlockRead; 742 br->ContainerId = xs->sc_link->target; 743 br->BlockNumber = cm->cm_blkno; 744 br->ByteCount = cm->cm_bcount * AAC_BLOCK_SIZE; 745 fib->Header.Size += sizeof(struct aac_blockread); 746 cm->cm_sgtable = &br->SgMap; 747 cm->cm_flags |= AAC_CMD_DATAIN; 748 } else { 749 struct aac_blockwrite *bw; 750 bw = (struct aac_blockwrite *)&fib->data[0]; 751 bw->Command = VM_CtBlockWrite; 752 bw->ContainerId = xs->sc_link->target; 753 bw->BlockNumber = cm->cm_blkno; 754 bw->ByteCount = cm->cm_bcount * AAC_BLOCK_SIZE; 755 bw->Stable = CUNSTABLE; 756 fib->Header.Size += sizeof(struct aac_blockwrite); 757 cm->cm_flags |= AAC_CMD_DATAOUT; 758 cm->cm_sgtable = &bw->SgMap; 759 } 760 } else { 761 fib->Header.Command = ContainerCommand64; 762 if (opcode == READ_COMMAND) { 763 struct aac_blockread64 *br; 764 br = (struct aac_blockread64 *)&fib->data[0]; 765 br->Command = VM_CtHostRead64; 766 br->ContainerId = xs->sc_link->target; 767 br->BlockNumber = cm->cm_blkno; 768 br->SectorCount = cm->cm_bcount; 769 br->Pad = 0; 770 br->Flags = 0; 771 fib->Header.Size += sizeof(struct aac_blockread64); 772 cm->cm_flags |= AAC_CMD_DATAOUT; 773 cm->cm_sgtable = (struct aac_sg_table *)&br->SgMap64; 774 } else { 775 struct aac_blockwrite64 *bw; 776 bw = (struct aac_blockwrite64 *)&fib->data[0]; 777 bw->Command = VM_CtHostWrite64; 778 bw->ContainerId = xs->sc_link->target; 779 bw->BlockNumber = cm->cm_blkno; 780 bw->SectorCount = cm->cm_bcount; 781 bw->Pad = 0; 782 bw->Flags = 0; 783 fib->Header.Size += sizeof(struct aac_blockwrite64); 784 cm->cm_flags |= AAC_CMD_DATAIN; 785 cm->cm_sgtable = (struct aac_sg_table *)&bw->SgMap64; 786 } 787 } 788 789 *cmp = cm; 790 AAC_DPRINTF(AAC_D_CMD, ("\n")); 791 return(0); 792 793 fail: 794 AAC_DPRINTF(AAC_D_CMD, ("\n")); 795 return(ENOMEM); 796 } 797 798 /* 799 * Handle a bio-instigated command that has been completed. 800 */ 801 void 802 aac_bio_complete(struct aac_command *cm) 803 { 804 struct aac_blockread_response *brr; 805 struct aac_blockwrite_response *bwr; 806 struct scsi_xfer *xs = (struct scsi_xfer *)cm->cm_private; 807 AAC_FSAStatus status; 808 int s; 809 810 AAC_DPRINTF(AAC_D_CMD, 811 ("%s: bio complete\n", cm->cm_sc->aac_dev.dv_xname)); 812 813 /* fetch relevant status and then release the command */ 814 if (xs->flags & SCSI_DATA_IN) { 815 brr = (struct aac_blockread_response *)&cm->cm_fib->data[0]; 816 status = brr->Status; 817 } else { 818 bwr = (struct aac_blockwrite_response *)&cm->cm_fib->data[0]; 819 status = bwr->Status; 820 } 821 822 xs->error = status == ST_OK? XS_NOERROR : XS_DRIVER_STUFFUP; 823 xs->resid = 0; 824 s = splbio(); 825 scsi_done(xs); 826 splx(s); 827 } 828 829 /* 830 * Submit a command to the controller, return when it completes. 831 * XXX This is very dangerous! If the card has gone out to lunch, we could 832 * be stuck here forever. At the same time, signals are not caught 833 * because there is a risk that a signal could wakeup the tsleep before 834 * the card has a chance to complete the command. The passed in timeout 835 * is ignored for the same reason. Since there is no way to cancel a 836 * command in progress, we should probably create a 'dead' queue where 837 * commands go that have been interrupted/timed-out/etc, that keeps them 838 * out of the free pool. That way, if the card is just slow, it won't 839 * spam the memory of a command that has been recycled. 840 */ 841 int 842 aac_wait_command(struct aac_command *cm, int msecs) 843 { 844 struct aac_softc *sc = cm->cm_sc; 845 int error = 0; 846 847 AAC_DPRINTF(AAC_D_CMD, (": wait for command")); 848 849 /* Put the command on the ready queue and get things going */ 850 cm->cm_queue = AAC_ADAP_NORM_CMD_QUEUE; 851 aac_enqueue_ready(cm); 852 AAC_DPRINTF(AAC_D_CMD, ("\n")); 853 aac_startio(sc); 854 while (!(cm->cm_flags & AAC_CMD_COMPLETED) && (error != EWOULDBLOCK)) { 855 AAC_DPRINTF(AAC_D_MISC, ("%s: sleeping until command done\n", 856 sc->aac_dev.dv_xname)); 857 AAC_LOCK_RELEASE(&sc->aac_io_lock); 858 error = tsleep_nsec(cm, PRIBIO, "aacwait", MSEC_TO_NSEC(msecs)); 859 AAC_LOCK_ACQUIRE(&sc->aac_io_lock); 860 } 861 return (error); 862 } 863 864 /* 865 *Command Buffer Management 866 */ 867 868 /* 869 * Allocate a command. 870 */ 871 void * 872 aac_alloc_command(void *xsc) 873 { 874 struct aac_softc *sc = xsc; 875 struct aac_command *cm; 876 877 AAC_DPRINTF(AAC_D_CMD, (": allocate command")); 878 mtx_enter(&sc->aac_free_mtx); 879 cm = aac_dequeue_free(sc); 880 mtx_leave(&sc->aac_free_mtx); 881 882 return (cm); 883 } 884 885 void 886 aac_scrub_command(struct aac_command *cm) 887 { 888 cm->cm_sgtable = NULL; 889 cm->cm_flags = 0; 890 cm->cm_complete = NULL; 891 cm->cm_private = NULL; 892 cm->cm_fib->Header.XferState = AAC_FIBSTATE_EMPTY; 893 cm->cm_fib->Header.StructType = AAC_FIBTYPE_TFIB; 894 cm->cm_fib->Header.Flags = 0; 895 cm->cm_fib->Header.SenderSize = sizeof(struct aac_fib); 896 } 897 898 /* 899 * Release a command back to the freelist. 900 */ 901 void 902 aac_release_command(void *xsc, void *xcm) 903 { 904 struct aac_softc *sc = xsc; 905 struct aac_command *cm = xcm; 906 AAC_DPRINTF(AAC_D_CMD, (": release command")); 907 908 mtx_enter(&sc->aac_free_mtx); 909 aac_enqueue_free(cm); 910 mtx_leave(&sc->aac_free_mtx); 911 } 912 913 /* 914 * Allocate and initialise commands/FIBs for this adapter. 915 */ 916 int 917 aac_alloc_commands(struct aac_softc *sc) 918 { 919 struct aac_command *cm; 920 struct aac_fibmap *fm; 921 int i, error = ENOMEM; 922 923 if (sc->total_fibs + AAC_FIB_COUNT > sc->aac_max_fibs) 924 return (ENOMEM); 925 926 fm = malloc(sizeof(*fm), M_DEVBUF, M_NOWAIT | M_ZERO); 927 if (fm == NULL) 928 goto exit; 929 930 /* allocate the FIBs in DMAable memory and load them */ 931 if (bus_dmamem_alloc(sc->aac_dmat, AAC_FIBMAP_SIZE, PAGE_SIZE, 0, 932 &fm->aac_seg, 1, &fm->aac_nsegs, BUS_DMA_NOWAIT | BUS_DMA_ZERO)) { 933 printf("%s: can't alloc FIBs\n", sc->aac_dev.dv_xname); 934 error = ENOBUFS; 935 goto exit_alloc; 936 } 937 938 if (bus_dmamem_map(sc->aac_dmat, &fm->aac_seg, 1, 939 AAC_FIBMAP_SIZE, (caddr_t *)&fm->aac_fibs, BUS_DMA_NOWAIT)) { 940 printf("%s: can't map FIB structure\n", sc->aac_dev.dv_xname); 941 error = ENOBUFS; 942 goto exit_map; 943 } 944 945 if (bus_dmamap_create(sc->aac_dmat, AAC_FIBMAP_SIZE, 1, 946 AAC_FIBMAP_SIZE, 0, BUS_DMA_NOWAIT, &fm->aac_fibmap)) { 947 printf("%s: can't create dma map\n", sc->aac_dev.dv_xname); 948 error = ENOBUFS; 949 goto exit_create; 950 } 951 952 if (bus_dmamap_load(sc->aac_dmat, fm->aac_fibmap, fm->aac_fibs, 953 AAC_FIBMAP_SIZE, NULL, BUS_DMA_NOWAIT)) { 954 printf("%s: can't load dma map\n", sc->aac_dev.dv_xname); 955 error = ENOBUFS; 956 goto exit_load; 957 } 958 959 /* initialise constant fields in the command structure */ 960 AAC_LOCK_ACQUIRE(&sc->aac_io_lock); 961 for (i = 0; i < AAC_FIB_COUNT; i++) { 962 cm = sc->aac_commands + sc->total_fibs; 963 fm->aac_commands = cm; 964 cm->cm_sc = sc; 965 cm->cm_fib = fm->aac_fibs + i; 966 cm->cm_fibphys = fm->aac_fibmap->dm_segs[0].ds_addr + 967 (i * sizeof(struct aac_fib)); 968 cm->cm_index = sc->total_fibs; 969 970 if (bus_dmamap_create(sc->aac_dmat, MAXPHYS, AAC_MAXSGENTRIES, 971 MAXPHYS, 0, BUS_DMA_NOWAIT, &cm->cm_datamap)) { 972 break; 973 } 974 aac_release_command(sc, cm); 975 sc->total_fibs++; 976 } 977 978 if (i > 0) { 979 TAILQ_INSERT_TAIL(&sc->aac_fibmap_tqh, fm, fm_link); 980 AAC_DPRINTF(AAC_D_MISC, ("%s: total_fibs= %d\n", 981 sc->aac_dev.dv_xname, 982 sc->total_fibs)); 983 AAC_LOCK_RELEASE(&sc->aac_io_lock); 984 return (0); 985 } 986 987 exit_load: 988 bus_dmamap_destroy(sc->aac_dmat, fm->aac_fibmap); 989 exit_create: 990 bus_dmamem_unmap(sc->aac_dmat, (caddr_t)fm->aac_fibs, AAC_FIBMAP_SIZE); 991 exit_map: 992 bus_dmamem_free(sc->aac_dmat, &fm->aac_seg, fm->aac_nsegs); 993 exit_alloc: 994 free(fm, M_DEVBUF, sizeof *fm); 995 exit: 996 AAC_LOCK_RELEASE(&sc->aac_io_lock); 997 return (error); 998 } 999 1000 /* 1001 * Free FIBs owned by this adapter. 1002 */ 1003 void 1004 aac_free_commands(struct aac_softc *sc) 1005 { 1006 struct aac_fibmap *fm; 1007 struct aac_command *cm; 1008 int i; 1009 1010 while ((fm = TAILQ_FIRST(&sc->aac_fibmap_tqh)) != NULL) { 1011 1012 TAILQ_REMOVE(&sc->aac_fibmap_tqh, fm, fm_link); 1013 1014 /* 1015 * We check against total_fibs to handle partially 1016 * allocated blocks. 1017 */ 1018 for (i = 0; i < AAC_FIB_COUNT && sc->total_fibs--; i++) { 1019 cm = fm->aac_commands + i; 1020 bus_dmamap_destroy(sc->aac_dmat, cm->cm_datamap); 1021 } 1022 1023 bus_dmamap_unload(sc->aac_dmat, fm->aac_fibmap); 1024 bus_dmamap_destroy(sc->aac_dmat, fm->aac_fibmap); 1025 bus_dmamem_unmap(sc->aac_dmat, (caddr_t)fm->aac_fibs, 1026 AAC_FIBMAP_SIZE); 1027 bus_dmamem_free(sc->aac_dmat, &fm->aac_seg, fm->aac_nsegs); 1028 free(fm, M_DEVBUF, sizeof *fm); 1029 } 1030 } 1031 1032 1033 /* 1034 * Command-mapping helper function - populate this command's s/g table. 1035 */ 1036 void 1037 aac_map_command_sg(void *arg, bus_dma_segment_t *segs, int nseg, int error) 1038 { 1039 struct aac_command *cm = arg; 1040 struct aac_softc *sc = cm->cm_sc; 1041 struct aac_fib *fib = cm->cm_fib; 1042 int i; 1043 1044 /* copy into the FIB */ 1045 if (cm->cm_sgtable != NULL) { 1046 if ((cm->cm_sc->flags & AAC_FLAGS_SG_64BIT) == 0) { 1047 struct aac_sg_table *sg = cm->cm_sgtable; 1048 sg->SgCount = nseg; 1049 for (i = 0; i < nseg; i++) { 1050 sg->SgEntry[i].SgAddress = segs[i].ds_addr; 1051 sg->SgEntry[i].SgByteCount = segs[i].ds_len; 1052 } 1053 /* update the FIB size for the s/g count */ 1054 fib->Header.Size += nseg * sizeof(struct aac_sg_entry); 1055 } else { 1056 struct aac_sg_table64 *sg; 1057 sg = (struct aac_sg_table64 *)cm->cm_sgtable; 1058 sg->SgCount = nseg; 1059 for (i = 0; i < nseg; i++) { 1060 sg->SgEntry64[i].SgAddress = segs[i].ds_addr; 1061 sg->SgEntry64[i].SgByteCount = segs[i].ds_len; 1062 } 1063 /* update the FIB size for the s/g count */ 1064 fib->Header.Size += nseg*sizeof(struct aac_sg_entry64); 1065 } 1066 } 1067 1068 /* Fix up the address values in the FIB. Use the command array index 1069 * instead of a pointer since these fields are only 32 bits. Shift 1070 * the SenderFibAddress over to make room for the fast response bit. 1071 */ 1072 cm->cm_fib->Header.SenderFibAddress = (cm->cm_index << 1); 1073 cm->cm_fib->Header.ReceiverFibAddress = cm->cm_fibphys; 1074 1075 /* save a pointer to the command for speedy reverse-lookup */ 1076 cm->cm_fib->Header.SenderData = cm->cm_index; 1077 1078 if (cm->cm_flags & AAC_CMD_DATAIN) 1079 bus_dmamap_sync(sc->aac_dmat, cm->cm_datamap, 0, 1080 cm->cm_datamap->dm_mapsize, 1081 BUS_DMASYNC_PREREAD); 1082 if (cm->cm_flags & AAC_CMD_DATAOUT) 1083 bus_dmamap_sync(sc->aac_dmat, cm->cm_datamap, 0, 1084 cm->cm_datamap->dm_mapsize, 1085 BUS_DMASYNC_PREWRITE); 1086 cm->cm_flags |= AAC_CMD_MAPPED; 1087 1088 /* put the FIB on the outbound queue */ 1089 if (aac_enqueue_fib(sc, cm->cm_queue, cm) == EBUSY) { 1090 aac_remove_busy(cm); 1091 aac_unmap_command(cm); 1092 aac_requeue_ready(cm); 1093 } 1094 } 1095 1096 /* 1097 * Unmap a command from controller-visible space. 1098 */ 1099 void 1100 aac_unmap_command(struct aac_command *cm) 1101 { 1102 struct aac_softc *sc = cm->cm_sc; 1103 1104 if (!(cm->cm_flags & AAC_CMD_MAPPED)) 1105 return; 1106 1107 if (cm->cm_datalen != 0) { 1108 if (cm->cm_flags & AAC_CMD_DATAIN) 1109 bus_dmamap_sync(sc->aac_dmat, cm->cm_datamap, 0, 1110 cm->cm_datamap->dm_mapsize, 1111 BUS_DMASYNC_POSTREAD); 1112 if (cm->cm_flags & AAC_CMD_DATAOUT) 1113 bus_dmamap_sync(sc->aac_dmat, cm->cm_datamap, 0, 1114 cm->cm_datamap->dm_mapsize, 1115 BUS_DMASYNC_POSTWRITE); 1116 1117 bus_dmamap_unload(sc->aac_dmat, cm->cm_datamap); 1118 } 1119 cm->cm_flags &= ~AAC_CMD_MAPPED; 1120 } 1121 1122 /* 1123 * Hardware Interface 1124 */ 1125 1126 /* 1127 * Initialise the adapter. 1128 */ 1129 int 1130 aac_check_firmware(struct aac_softc *sc) 1131 { 1132 u_int32_t major, minor, options; 1133 1134 /* 1135 * Retrieve the firmware version numbers. Dell PERC2/QC cards with 1136 * firmware version 1.x are not compatible with this driver. 1137 */ 1138 if (sc->flags & AAC_FLAGS_PERC2QC) { 1139 if (aac_sync_command(sc, AAC_MONKER_GETKERNVER, 0, 0, 0, 0, 1140 NULL)) { 1141 printf("%s: Error reading firmware version\n", 1142 sc->aac_dev.dv_xname); 1143 return (EIO); 1144 } 1145 1146 /* These numbers are stored as ASCII! */ 1147 major = (AAC_GET_MAILBOX(sc, 1) & 0xff) - 0x30; 1148 minor = (AAC_GET_MAILBOX(sc, 2) & 0xff) - 0x30; 1149 if (major == 1) { 1150 printf("%s: Firmware version %d.%d is not supported\n", 1151 sc->aac_dev.dv_xname, major, minor); 1152 return (EINVAL); 1153 } 1154 } 1155 1156 /* 1157 * Retrieve the capabilities/supported options word so we know what 1158 * work-arounds to enable. 1159 */ 1160 if (aac_sync_command(sc, AAC_MONKER_GETINFO, 0, 0, 0, 0, NULL)) { 1161 printf("%s: RequestAdapterInfo failed\n", 1162 sc->aac_dev.dv_xname); 1163 return (EIO); 1164 } 1165 options = AAC_GET_MAILBOX(sc, 1); 1166 sc->supported_options = options; 1167 1168 if ((options & AAC_SUPPORTED_4GB_WINDOW) != 0 && 1169 (sc->flags & AAC_FLAGS_NO4GB) == 0) 1170 sc->flags |= AAC_FLAGS_4GB_WINDOW; 1171 if (options & AAC_SUPPORTED_NONDASD) 1172 sc->flags |= AAC_FLAGS_ENABLE_CAM; 1173 if ((options & AAC_SUPPORTED_SGMAP_HOST64) != 0 1174 && (sizeof(bus_addr_t) > 4)) { 1175 printf("%s: Enabling 64-bit address support\n", 1176 sc->aac_dev.dv_xname); 1177 sc->flags |= AAC_FLAGS_SG_64BIT; 1178 } 1179 1180 /* Check for broken hardware that does a lower number of commands */ 1181 if ((sc->flags & AAC_FLAGS_256FIBS) == 0) 1182 sc->aac_max_fibs = AAC_MAX_FIBS; 1183 else 1184 sc->aac_max_fibs = 256; 1185 1186 return (0); 1187 } 1188 1189 int 1190 aac_init(struct aac_softc *sc) 1191 { 1192 bus_dma_segment_t seg; 1193 int nsegs; 1194 int i, error; 1195 int state = 0; 1196 struct aac_adapter_init *ip; 1197 time_t then; 1198 u_int32_t code, qoffset; 1199 1200 /* 1201 * First wait for the adapter to come ready. 1202 */ 1203 then = getuptime(); 1204 for (i = 0; i < AAC_BOOT_TIMEOUT * 1000; i++) { 1205 code = AAC_GET_FWSTATUS(sc); 1206 if (code & AAC_SELF_TEST_FAILED) { 1207 printf("%s: FATAL: selftest failed\n", 1208 sc->aac_dev.dv_xname); 1209 return (ENXIO); 1210 } 1211 if (code & AAC_KERNEL_PANIC) { 1212 printf("%s: FATAL: controller kernel panic\n", 1213 sc->aac_dev.dv_xname); 1214 return (ENXIO); 1215 } 1216 if (code & AAC_UP_AND_RUNNING) 1217 break; 1218 DELAY(1000); 1219 } 1220 if (i == AAC_BOOT_TIMEOUT * 1000) { 1221 printf("%s: FATAL: controller not coming ready, status %x\n", 1222 sc->aac_dev.dv_xname, code); 1223 return (ENXIO); 1224 } 1225 1226 /* 1227 * Work around a bug in the 2120 and 2200 that cannot DMA commands 1228 * below address 8192 in physical memory. 1229 * XXX If the padding is not needed, can it be put to use instead 1230 * of ignored? 1231 */ 1232 if (bus_dmamem_alloc(sc->aac_dmat, AAC_COMMON_ALLOCSIZE, PAGE_SIZE, 0, 1233 &seg, 1, &nsegs, BUS_DMA_NOWAIT | BUS_DMA_ZERO)) { 1234 printf("%s: can't allocate common structure\n", 1235 sc->aac_dev.dv_xname); 1236 return (ENOMEM); 1237 } 1238 state++; 1239 1240 if (bus_dmamem_map(sc->aac_dmat, &seg, nsegs, AAC_COMMON_ALLOCSIZE, 1241 (caddr_t *)&sc->aac_common, BUS_DMA_NOWAIT)) { 1242 printf("%s: can't map common structure\n", 1243 sc->aac_dev.dv_xname); 1244 error = ENOMEM; 1245 goto bail_out; 1246 } 1247 state++; 1248 1249 if (bus_dmamap_create(sc->aac_dmat, AAC_COMMON_ALLOCSIZE, 1, 1250 AAC_COMMON_ALLOCSIZE, 0, BUS_DMA_NOWAIT, &sc->aac_common_map)) { 1251 printf("%s: can't create dma map\n", sc->aac_dev.dv_xname); 1252 error = ENOBUFS; 1253 goto bail_out; 1254 } 1255 state++; 1256 1257 if (bus_dmamap_load(sc->aac_dmat, sc->aac_common_map, sc->aac_common, 1258 AAC_COMMON_ALLOCSIZE, NULL, BUS_DMA_NOWAIT)) { 1259 printf("%s: can't load dma map\n", sc->aac_dev.dv_xname); 1260 error = ENOBUFS; 1261 goto bail_out; 1262 } 1263 state++; 1264 1265 sc->aac_common_busaddr = sc->aac_common_map->dm_segs[0].ds_addr; 1266 1267 if (sc->aac_common_busaddr < 8192) { 1268 sc->aac_common = (struct aac_common *) 1269 ((uint8_t *)sc->aac_common + 8192); 1270 sc->aac_common_busaddr += 8192; 1271 } 1272 1273 /* Allocate some FIBs and associated command structs */ 1274 TAILQ_INIT(&sc->aac_fibmap_tqh); 1275 sc->aac_commands = malloc(AAC_MAX_FIBS * sizeof(struct aac_command), 1276 M_DEVBUF, M_WAITOK | M_ZERO); 1277 while (sc->total_fibs < AAC_MAX_FIBS) { 1278 if (aac_alloc_commands(sc) != 0) 1279 break; 1280 } 1281 if (sc->total_fibs == 0) { 1282 error = ENOMEM; 1283 goto bail_out; 1284 } 1285 1286 scsi_iopool_init(&sc->aac_iopool, sc, 1287 aac_alloc_command, aac_release_command); 1288 1289 /* 1290 * Fill in the init structure. This tells the adapter about the 1291 * physical location of various important shared data structures. 1292 */ 1293 ip = &sc->aac_common->ac_init; 1294 ip->InitStructRevision = AAC_INIT_STRUCT_REVISION; 1295 ip->MiniPortRevision = AAC_INIT_STRUCT_MINIPORT_REVISION; 1296 1297 ip->AdapterFibsPhysicalAddress = sc->aac_common_busaddr + 1298 offsetof(struct aac_common, ac_fibs); 1299 ip->AdapterFibsVirtualAddress = 0; 1300 ip->AdapterFibsSize = AAC_ADAPTER_FIBS * sizeof(struct aac_fib); 1301 ip->AdapterFibAlign = sizeof(struct aac_fib); 1302 1303 ip->PrintfBufferAddress = sc->aac_common_busaddr + 1304 offsetof(struct aac_common, ac_printf); 1305 ip->PrintfBufferSize = AAC_PRINTF_BUFSIZE; 1306 1307 /* 1308 * The adapter assumes that pages are 4K in size, except on some 1309 * broken firmware versions that do the page->byte conversion twice, 1310 * therefore 'assuming' that this value is in 16MB units (2^24). 1311 * Round up since the granularity is so high. 1312 */ 1313 ip->HostPhysMemPages = ptoa(physmem) / AAC_PAGE_SIZE; 1314 if (sc->flags & AAC_FLAGS_BROKEN_MEMMAP) { 1315 ip->HostPhysMemPages = 1316 (ip->HostPhysMemPages + AAC_PAGE_SIZE) / AAC_PAGE_SIZE; 1317 } 1318 ip->HostElapsedSeconds = getuptime(); /* reset later if invalid */ 1319 1320 /* 1321 * Initialise FIB queues. Note that it appears that the layout of the 1322 * indexes and the segmentation of the entries may be mandated by the 1323 * adapter, which is only told about the base of the queue index fields. 1324 * 1325 * The initial values of the indices are assumed to inform the adapter 1326 * of the sizes of the respective queues, and theoretically it could 1327 * work out the entire layout of the queue structures from this. We 1328 * take the easy route and just lay this area out like everyone else 1329 * does. 1330 * 1331 * The Linux driver uses a much more complex scheme whereby several 1332 * header records are kept for each queue. We use a couple of generic 1333 * list manipulation functions which 'know' the size of each list by 1334 * virtue of a table. 1335 */ 1336 qoffset = offsetof(struct aac_common, ac_qbuf) + AAC_QUEUE_ALIGN; 1337 qoffset &= ~(AAC_QUEUE_ALIGN - 1); 1338 sc->aac_queues = 1339 (struct aac_queue_table *)((caddr_t)sc->aac_common + qoffset); 1340 ip->CommHeaderAddress = sc->aac_common_busaddr + qoffset; 1341 1342 sc->aac_queues->qt_qindex[AAC_HOST_NORM_CMD_QUEUE][AAC_PRODUCER_INDEX] = 1343 AAC_HOST_NORM_CMD_ENTRIES; 1344 sc->aac_queues->qt_qindex[AAC_HOST_NORM_CMD_QUEUE][AAC_CONSUMER_INDEX] = 1345 AAC_HOST_NORM_CMD_ENTRIES; 1346 sc->aac_queues->qt_qindex[AAC_HOST_HIGH_CMD_QUEUE][AAC_PRODUCER_INDEX] = 1347 AAC_HOST_HIGH_CMD_ENTRIES; 1348 sc->aac_queues->qt_qindex[AAC_HOST_HIGH_CMD_QUEUE][AAC_CONSUMER_INDEX] = 1349 AAC_HOST_HIGH_CMD_ENTRIES; 1350 sc->aac_queues->qt_qindex[AAC_ADAP_NORM_CMD_QUEUE][AAC_PRODUCER_INDEX] = 1351 AAC_ADAP_NORM_CMD_ENTRIES; 1352 sc->aac_queues->qt_qindex[AAC_ADAP_NORM_CMD_QUEUE][AAC_CONSUMER_INDEX] = 1353 AAC_ADAP_NORM_CMD_ENTRIES; 1354 sc->aac_queues->qt_qindex[AAC_ADAP_HIGH_CMD_QUEUE][AAC_PRODUCER_INDEX] = 1355 AAC_ADAP_HIGH_CMD_ENTRIES; 1356 sc->aac_queues->qt_qindex[AAC_ADAP_HIGH_CMD_QUEUE][AAC_CONSUMER_INDEX] = 1357 AAC_ADAP_HIGH_CMD_ENTRIES; 1358 sc->aac_queues->qt_qindex[AAC_HOST_NORM_RESP_QUEUE][AAC_PRODUCER_INDEX]= 1359 AAC_HOST_NORM_RESP_ENTRIES; 1360 sc->aac_queues->qt_qindex[AAC_HOST_NORM_RESP_QUEUE][AAC_CONSUMER_INDEX]= 1361 AAC_HOST_NORM_RESP_ENTRIES; 1362 sc->aac_queues->qt_qindex[AAC_HOST_HIGH_RESP_QUEUE][AAC_PRODUCER_INDEX]= 1363 AAC_HOST_HIGH_RESP_ENTRIES; 1364 sc->aac_queues->qt_qindex[AAC_HOST_HIGH_RESP_QUEUE][AAC_CONSUMER_INDEX]= 1365 AAC_HOST_HIGH_RESP_ENTRIES; 1366 sc->aac_queues->qt_qindex[AAC_ADAP_NORM_RESP_QUEUE][AAC_PRODUCER_INDEX]= 1367 AAC_ADAP_NORM_RESP_ENTRIES; 1368 sc->aac_queues->qt_qindex[AAC_ADAP_NORM_RESP_QUEUE][AAC_CONSUMER_INDEX]= 1369 AAC_ADAP_NORM_RESP_ENTRIES; 1370 sc->aac_queues->qt_qindex[AAC_ADAP_HIGH_RESP_QUEUE][AAC_PRODUCER_INDEX]= 1371 AAC_ADAP_HIGH_RESP_ENTRIES; 1372 sc->aac_queues->qt_qindex[AAC_ADAP_HIGH_RESP_QUEUE][AAC_CONSUMER_INDEX]= 1373 AAC_ADAP_HIGH_RESP_ENTRIES; 1374 sc->aac_qentries[AAC_HOST_NORM_CMD_QUEUE] = 1375 &sc->aac_queues->qt_HostNormCmdQueue[0]; 1376 sc->aac_qentries[AAC_HOST_HIGH_CMD_QUEUE] = 1377 &sc->aac_queues->qt_HostHighCmdQueue[0]; 1378 sc->aac_qentries[AAC_ADAP_NORM_CMD_QUEUE] = 1379 &sc->aac_queues->qt_AdapNormCmdQueue[0]; 1380 sc->aac_qentries[AAC_ADAP_HIGH_CMD_QUEUE] = 1381 &sc->aac_queues->qt_AdapHighCmdQueue[0]; 1382 sc->aac_qentries[AAC_HOST_NORM_RESP_QUEUE] = 1383 &sc->aac_queues->qt_HostNormRespQueue[0]; 1384 sc->aac_qentries[AAC_HOST_HIGH_RESP_QUEUE] = 1385 &sc->aac_queues->qt_HostHighRespQueue[0]; 1386 sc->aac_qentries[AAC_ADAP_NORM_RESP_QUEUE] = 1387 &sc->aac_queues->qt_AdapNormRespQueue[0]; 1388 sc->aac_qentries[AAC_ADAP_HIGH_RESP_QUEUE] = 1389 &sc->aac_queues->qt_AdapHighRespQueue[0]; 1390 1391 /* 1392 * Do controller-type-specific initialisation 1393 */ 1394 switch (sc->aac_hwif) { 1395 case AAC_HWIF_I960RX: 1396 AAC_SETREG4(sc, AAC_RX_ODBR, ~0); 1397 break; 1398 case AAC_HWIF_RKT: 1399 AAC_SETREG4(sc, AAC_RKT_ODBR, ~0); 1400 break; 1401 default: 1402 break; 1403 } 1404 1405 /* 1406 * Give the init structure to the controller. 1407 */ 1408 if (aac_sync_command(sc, AAC_MONKER_INITSTRUCT, 1409 sc->aac_common_busaddr + 1410 offsetof(struct aac_common, ac_init), 0, 0, 0, 1411 NULL)) { 1412 printf("%s: error establishing init structure\n", 1413 sc->aac_dev.dv_xname); 1414 error = EIO; 1415 goto bail_out; 1416 } 1417 1418 aac_describe_controller(sc); 1419 aac_startup(sc); 1420 1421 return (0); 1422 1423 bail_out: 1424 if (state > 3) 1425 bus_dmamap_unload(sc->aac_dmat, sc->aac_common_map); 1426 if (state > 2) 1427 bus_dmamap_destroy(sc->aac_dmat, sc->aac_common_map); 1428 if (state > 1) 1429 bus_dmamem_unmap(sc->aac_dmat, (caddr_t)sc->aac_common, 1430 sizeof *sc->aac_common); 1431 if (state > 0) 1432 bus_dmamem_free(sc->aac_dmat, &seg, 1); 1433 1434 return (error); 1435 } 1436 1437 /* 1438 * Send a synchronous command to the controller and wait for a result. 1439 */ 1440 int 1441 aac_sync_command(struct aac_softc *sc, u_int32_t command, u_int32_t arg0, 1442 u_int32_t arg1, u_int32_t arg2, u_int32_t arg3, u_int32_t *sp) 1443 { 1444 // time_t then; 1445 int i; 1446 u_int32_t status; 1447 u_int16_t reason; 1448 1449 /* populate the mailbox */ 1450 AAC_SET_MAILBOX(sc, command, arg0, arg1, arg2, arg3); 1451 1452 /* ensure the sync command doorbell flag is cleared */ 1453 AAC_CLEAR_ISTATUS(sc, AAC_DB_SYNC_COMMAND); 1454 1455 /* then set it to signal the adapter */ 1456 AAC_QNOTIFY(sc, AAC_DB_SYNC_COMMAND); 1457 1458 DELAY(AAC_SYNC_DELAY); 1459 1460 /* spin waiting for the command to complete */ 1461 for (i = 0; i < AAC_IMMEDIATE_TIMEOUT * 1000; i++) { 1462 reason = AAC_GET_ISTATUS(sc); 1463 if (reason & AAC_DB_SYNC_COMMAND) 1464 break; 1465 reason = AAC_GET_ISTATUS(sc); 1466 if (reason & AAC_DB_SYNC_COMMAND) 1467 break; 1468 reason = AAC_GET_ISTATUS(sc); 1469 if (reason & AAC_DB_SYNC_COMMAND) 1470 break; 1471 DELAY(1000); 1472 } 1473 if (i == AAC_IMMEDIATE_TIMEOUT * 1000) { 1474 printf("aac_sync_command: failed, reason=%#x\n", reason); 1475 return (EIO); 1476 } 1477 1478 /* clear the completion flag */ 1479 AAC_CLEAR_ISTATUS(sc, AAC_DB_SYNC_COMMAND); 1480 1481 /* get the command status */ 1482 status = AAC_GET_MAILBOX(sc, 0); 1483 1484 if (sp != NULL) 1485 *sp = status; 1486 1487 return(0); 1488 } 1489 1490 /* 1491 * Grab the sync fib area. 1492 */ 1493 int 1494 aac_alloc_sync_fib(struct aac_softc *sc, struct aac_fib **fib, int flags) 1495 { 1496 1497 /* 1498 * If the force flag is set, the system is shutting down, or in 1499 * trouble. Ignore the mutex. 1500 */ 1501 if (!(flags & AAC_SYNC_LOCK_FORCE)) 1502 AAC_LOCK_ACQUIRE(&sc->aac_sync_lock); 1503 1504 *fib = &sc->aac_common->ac_sync_fib; 1505 1506 return (1); 1507 } 1508 1509 /* 1510 * Release the sync fib area. 1511 */ 1512 void 1513 aac_release_sync_fib(struct aac_softc *sc) 1514 { 1515 AAC_LOCK_RELEASE(&sc->aac_sync_lock); 1516 } 1517 1518 /* 1519 * Send a synchronous FIB to the controller and wait for a result. 1520 */ 1521 int 1522 aac_sync_fib(struct aac_softc *sc, u_int32_t command, u_int32_t xferstate, 1523 struct aac_fib *fib, u_int16_t datasize) 1524 { 1525 1526 if (datasize > AAC_FIB_DATASIZE) { 1527 printf("aac_sync_fib 1: datasize=%d AAC_FIB_DATASIZE %lu\n", 1528 datasize, AAC_FIB_DATASIZE); 1529 return(EINVAL); 1530 } 1531 1532 /* 1533 * Set up the sync FIB 1534 */ 1535 fib->Header.XferState = AAC_FIBSTATE_HOSTOWNED | 1536 AAC_FIBSTATE_INITIALISED | 1537 AAC_FIBSTATE_EMPTY; 1538 fib->Header.XferState |= xferstate; 1539 fib->Header.Command = command; 1540 fib->Header.StructType = AAC_FIBTYPE_TFIB; 1541 fib->Header.Size = sizeof(struct aac_fib) + datasize; 1542 fib->Header.SenderSize = sizeof(struct aac_fib); 1543 fib->Header.SenderFibAddress = 0; /* Not needed */ 1544 fib->Header.ReceiverFibAddress = sc->aac_common_busaddr + 1545 offsetof(struct aac_common, 1546 ac_sync_fib); 1547 1548 /* 1549 * Give the FIB to the controller, wait for a response. 1550 */ 1551 if (aac_sync_command(sc, AAC_MONKER_SYNCFIB, 1552 fib->Header.ReceiverFibAddress, 0, 0, 0, NULL)) { 1553 AAC_DPRINTF(AAC_D_IO, ("%s: aac_sync_fib: IO error\n", 1554 sc->aac_dev.dv_xname)); 1555 printf("aac_sync_fib 2\n"); 1556 return(EIO); 1557 } 1558 1559 return (0); 1560 } 1561 1562 /***************************************************************************** 1563 * Adapter-space FIB queue manipulation 1564 * 1565 * Note that the queue implementation here is a little funky; neither the PI or 1566 * CI will ever be zero. This behaviour is a controller feature. 1567 */ 1568 static struct { 1569 int size; 1570 int notify; 1571 } aac_qinfo[] = { 1572 { AAC_HOST_NORM_CMD_ENTRIES, AAC_DB_COMMAND_NOT_FULL }, 1573 { AAC_HOST_HIGH_CMD_ENTRIES, 0 }, 1574 { AAC_ADAP_NORM_CMD_ENTRIES, AAC_DB_COMMAND_READY }, 1575 { AAC_ADAP_HIGH_CMD_ENTRIES, 0 }, 1576 { AAC_HOST_NORM_RESP_ENTRIES, AAC_DB_RESPONSE_NOT_FULL }, 1577 { AAC_HOST_HIGH_RESP_ENTRIES, 0 }, 1578 { AAC_ADAP_NORM_RESP_ENTRIES, AAC_DB_RESPONSE_READY }, 1579 { AAC_ADAP_HIGH_RESP_ENTRIES, 0 } 1580 }; 1581 1582 /* 1583 * Atomically insert an entry into the nominated queue, returns 0 on success 1584 * or EBUSY if the queue is full. 1585 * 1586 * Note: it would be more efficient to defer notifying the controller in 1587 * the case where we may be inserting several entries in rapid 1588 * succession, but implementing this usefully may be difficult 1589 * (it would involve a separate queue/notify interface). 1590 */ 1591 int 1592 aac_enqueue_fib(struct aac_softc *sc, int queue, struct aac_command *cm) 1593 { 1594 u_int32_t pi, ci; 1595 int error; 1596 u_int32_t fib_size; 1597 u_int32_t fib_addr; 1598 1599 fib_size = cm->cm_fib->Header.Size; 1600 fib_addr = cm->cm_fib->Header.ReceiverFibAddress; 1601 1602 /* get the producer/consumer indices */ 1603 pi = sc->aac_queues->qt_qindex[queue][AAC_PRODUCER_INDEX]; 1604 ci = sc->aac_queues->qt_qindex[queue][AAC_CONSUMER_INDEX]; 1605 1606 /* wrap the queue? */ 1607 if (pi >= aac_qinfo[queue].size) 1608 pi = 0; 1609 1610 /* check for queue full */ 1611 if ((pi + 1) == ci) { 1612 error = EBUSY; 1613 goto out; 1614 } 1615 1616 /* populate queue entry */ 1617 (sc->aac_qentries[queue] + pi)->aq_fib_size = fib_size; 1618 (sc->aac_qentries[queue] + pi)->aq_fib_addr = fib_addr; 1619 1620 /* update producer index */ 1621 sc->aac_queues->qt_qindex[queue][AAC_PRODUCER_INDEX] = pi + 1; 1622 1623 /* 1624 * To avoid a race with its completion interrupt, place this command on 1625 * the busy queue prior to advertising it to the controller. 1626 */ 1627 aac_enqueue_busy(cm); 1628 1629 /* notify the adapter if we know how */ 1630 if (aac_qinfo[queue].notify != 0) 1631 AAC_QNOTIFY(sc, aac_qinfo[queue].notify); 1632 1633 error = 0; 1634 1635 out: 1636 return (error); 1637 } 1638 1639 /* 1640 * Atomically remove one entry from the nominated queue, returns 0 on success 1641 * or ENOENT if the queue is empty. 1642 */ 1643 int 1644 aac_dequeue_fib(struct aac_softc *sc, int queue, u_int32_t *fib_size, 1645 struct aac_fib **fib_addr) 1646 { 1647 u_int32_t pi, ci; 1648 u_int32_t fib_index; 1649 int notify; 1650 int error; 1651 1652 /* get the producer/consumer indices */ 1653 pi = sc->aac_queues->qt_qindex[queue][AAC_PRODUCER_INDEX]; 1654 ci = sc->aac_queues->qt_qindex[queue][AAC_CONSUMER_INDEX]; 1655 1656 /* check for queue empty */ 1657 if (ci == pi) { 1658 error = ENOENT; 1659 goto out; 1660 } 1661 1662 /* wrap the pi so the following test works */ 1663 if (pi >= aac_qinfo[queue].size) 1664 pi = 0; 1665 1666 notify = 0; 1667 if (ci == pi + 1) 1668 notify++; 1669 1670 /* wrap the queue? */ 1671 if (ci >= aac_qinfo[queue].size) 1672 ci = 0; 1673 1674 /* fetch the entry */ 1675 *fib_size = (sc->aac_qentries[queue] + ci)->aq_fib_size; 1676 1677 switch (queue) { 1678 case AAC_HOST_NORM_CMD_QUEUE: 1679 case AAC_HOST_HIGH_CMD_QUEUE: 1680 /* 1681 * The aq_fib_addr is only 32 bits wide so it can't be counted 1682 * on to hold an address. For AIF's, the adapter assumes 1683 * that it's giving us an address into the array of AIF fibs. 1684 * Therefore, we have to convert it to an index. 1685 */ 1686 fib_index = (sc->aac_qentries[queue] + ci)->aq_fib_addr / 1687 sizeof(struct aac_fib); 1688 *fib_addr = &sc->aac_common->ac_fibs[fib_index]; 1689 break; 1690 1691 case AAC_HOST_NORM_RESP_QUEUE: 1692 case AAC_HOST_HIGH_RESP_QUEUE: 1693 { 1694 struct aac_command *cm; 1695 1696 /* 1697 * As above, an index is used instead of an actual address. 1698 * Gotta shift the index to account for the fast response 1699 * bit. No other correction is needed since this value was 1700 * originally provided by the driver via the SenderFibAddress 1701 * field. 1702 */ 1703 fib_index = (sc->aac_qentries[queue] + ci)->aq_fib_addr; 1704 cm = sc->aac_commands + (fib_index >> 1); 1705 *fib_addr = cm->cm_fib; 1706 1707 /* 1708 * Is this a fast response? If it is, update the fib fields in 1709 * local memory since the whole fib isn't DMA'd back up. 1710 */ 1711 if (fib_index & 0x01) { 1712 (*fib_addr)->Header.XferState |= AAC_FIBSTATE_DONEADAP; 1713 *((u_int32_t*)((*fib_addr)->data)) = AAC_ERROR_NORMAL; 1714 } 1715 break; 1716 } 1717 default: 1718 panic("Invalid queue in aac_dequeue_fib()"); 1719 break; 1720 } 1721 1722 1723 /* update consumer index */ 1724 sc->aac_queues->qt_qindex[queue][AAC_CONSUMER_INDEX] = ci + 1; 1725 1726 /* if we have made the queue un-full, notify the adapter */ 1727 if (notify && (aac_qinfo[queue].notify != 0)) 1728 AAC_QNOTIFY(sc, aac_qinfo[queue].notify); 1729 error = 0; 1730 1731 out: 1732 return (error); 1733 } 1734 1735 /* 1736 * Put our response to an Adapter Initialed Fib on the response queue 1737 */ 1738 int 1739 aac_enqueue_response(struct aac_softc *sc, int queue, struct aac_fib *fib) 1740 { 1741 u_int32_t pi, ci; 1742 int error; 1743 u_int32_t fib_size; 1744 u_int32_t fib_addr; 1745 1746 /* Tell the adapter where the FIB is */ 1747 fib_size = fib->Header.Size; 1748 fib_addr = fib->Header.SenderFibAddress; 1749 fib->Header.ReceiverFibAddress = fib_addr; 1750 1751 /* get the producer/consumer indices */ 1752 pi = sc->aac_queues->qt_qindex[queue][AAC_PRODUCER_INDEX]; 1753 ci = sc->aac_queues->qt_qindex[queue][AAC_CONSUMER_INDEX]; 1754 1755 /* wrap the queue? */ 1756 if (pi >= aac_qinfo[queue].size) 1757 pi = 0; 1758 1759 /* check for queue full */ 1760 if ((pi + 1) == ci) { 1761 error = EBUSY; 1762 goto out; 1763 } 1764 1765 /* populate queue entry */ 1766 (sc->aac_qentries[queue] + pi)->aq_fib_size = fib_size; 1767 (sc->aac_qentries[queue] + pi)->aq_fib_addr = fib_addr; 1768 1769 /* update producer index */ 1770 sc->aac_queues->qt_qindex[queue][AAC_PRODUCER_INDEX] = pi + 1; 1771 1772 /* notify the adapter if we know how */ 1773 if (aac_qinfo[queue].notify != 0) 1774 AAC_QNOTIFY(sc, aac_qinfo[queue].notify); 1775 1776 error = 0; 1777 1778 out: 1779 return(error); 1780 } 1781 1782 void 1783 aac_command_timeout(struct aac_command *cm) 1784 { 1785 struct aac_softc *sc = cm->cm_sc; 1786 1787 printf("%s: COMMAND %p (flags=%#x) TIMEOUT AFTER %d SECONDS\n", 1788 sc->aac_dev.dv_xname, cm, cm->cm_flags, 1789 (int)(getuptime() - cm->cm_timestamp)); 1790 1791 if (cm->cm_flags & AAC_CMD_TIMEDOUT) 1792 return; 1793 1794 cm->cm_flags |= AAC_CMD_TIMEDOUT; 1795 1796 AAC_PRINT_FIB(sc, cm->cm_fib); 1797 1798 if (cm->cm_flags & AAC_ON_AACQ_BIO) { 1799 struct scsi_xfer *xs = cm->cm_private; 1800 int s = splbio(); 1801 xs->error = XS_DRIVER_STUFFUP; 1802 splx(s); 1803 scsi_done(xs); 1804 1805 aac_remove_bio(cm); 1806 aac_unmap_command(cm); 1807 } 1808 } 1809 1810 void 1811 aac_timeout(struct aac_softc *sc) 1812 { 1813 struct aac_command *cm; 1814 time_t deadline; 1815 1816 /* 1817 * Traverse the busy command list and timeout any commands 1818 * that are past their deadline. 1819 */ 1820 deadline = getuptime() - AAC_CMD_TIMEOUT; 1821 TAILQ_FOREACH(cm, &sc->aac_busy, cm_link) { 1822 if (cm->cm_timestamp < deadline) 1823 aac_command_timeout(cm); 1824 } 1825 } 1826 1827 /* 1828 * Interface Function Vectors 1829 */ 1830 1831 /* 1832 * Read the current firmware status word. 1833 */ 1834 int 1835 aac_sa_get_fwstatus(struct aac_softc *sc) 1836 { 1837 return (AAC_GETREG4(sc, AAC_SA_FWSTATUS)); 1838 } 1839 1840 int 1841 aac_rx_get_fwstatus(struct aac_softc *sc) 1842 { 1843 return (AAC_GETREG4(sc, AAC_RX_FWSTATUS)); 1844 } 1845 1846 int 1847 aac_fa_get_fwstatus(struct aac_softc *sc) 1848 { 1849 return (AAC_GETREG4(sc, AAC_FA_FWSTATUS)); 1850 } 1851 1852 int 1853 aac_rkt_get_fwstatus(struct aac_softc *sc) 1854 { 1855 return(AAC_GETREG4(sc, AAC_RKT_FWSTATUS)); 1856 } 1857 1858 /* 1859 * Notify the controller of a change in a given queue 1860 */ 1861 1862 void 1863 aac_sa_qnotify(struct aac_softc *sc, int qbit) 1864 { 1865 AAC_SETREG2(sc, AAC_SA_DOORBELL1_SET, qbit); 1866 } 1867 1868 void 1869 aac_rx_qnotify(struct aac_softc *sc, int qbit) 1870 { 1871 AAC_SETREG4(sc, AAC_RX_IDBR, qbit); 1872 } 1873 1874 void 1875 aac_fa_qnotify(struct aac_softc *sc, int qbit) 1876 { 1877 AAC_SETREG2(sc, AAC_FA_DOORBELL1, qbit); 1878 AAC_FA_HACK(sc); 1879 } 1880 1881 void 1882 aac_rkt_qnotify(struct aac_softc *sc, int qbit) 1883 { 1884 AAC_SETREG4(sc, AAC_RKT_IDBR, qbit); 1885 } 1886 1887 /* 1888 * Get the interrupt reason bits 1889 */ 1890 int 1891 aac_sa_get_istatus(struct aac_softc *sc) 1892 { 1893 return (AAC_GETREG2(sc, AAC_SA_DOORBELL0)); 1894 } 1895 1896 int 1897 aac_rx_get_istatus(struct aac_softc *sc) 1898 { 1899 return (AAC_GETREG4(sc, AAC_RX_ODBR)); 1900 } 1901 1902 int 1903 aac_fa_get_istatus(struct aac_softc *sc) 1904 { 1905 return (AAC_GETREG2(sc, AAC_FA_DOORBELL0)); 1906 } 1907 1908 int 1909 aac_rkt_get_istatus(struct aac_softc *sc) 1910 { 1911 return(AAC_GETREG4(sc, AAC_RKT_ODBR)); 1912 } 1913 1914 /* 1915 * Clear some interrupt reason bits 1916 */ 1917 void 1918 aac_sa_clear_istatus(struct aac_softc *sc, int mask) 1919 { 1920 AAC_SETREG2(sc, AAC_SA_DOORBELL0_CLEAR, mask); 1921 } 1922 1923 void 1924 aac_rx_clear_istatus(struct aac_softc *sc, int mask) 1925 { 1926 AAC_SETREG4(sc, AAC_RX_ODBR, mask); 1927 } 1928 1929 void 1930 aac_fa_clear_istatus(struct aac_softc *sc, int mask) 1931 { 1932 AAC_SETREG2(sc, AAC_FA_DOORBELL0_CLEAR, mask); 1933 AAC_FA_HACK(sc); 1934 } 1935 1936 void 1937 aac_rkt_clear_istatus(struct aac_softc *sc, int mask) 1938 { 1939 AAC_SETREG4(sc, AAC_RKT_ODBR, mask); 1940 } 1941 1942 /* 1943 * Populate the mailbox and set the command word 1944 */ 1945 void 1946 aac_sa_set_mailbox(struct aac_softc *sc, u_int32_t command, u_int32_t arg0, 1947 u_int32_t arg1, u_int32_t arg2, u_int32_t arg3) 1948 { 1949 AAC_SETREG4(sc, AAC_SA_MAILBOX, command); 1950 AAC_SETREG4(sc, AAC_SA_MAILBOX + 4, arg0); 1951 AAC_SETREG4(sc, AAC_SA_MAILBOX + 8, arg1); 1952 AAC_SETREG4(sc, AAC_SA_MAILBOX + 12, arg2); 1953 AAC_SETREG4(sc, AAC_SA_MAILBOX + 16, arg3); 1954 } 1955 1956 void 1957 aac_rx_set_mailbox(struct aac_softc *sc, u_int32_t command, u_int32_t arg0, 1958 u_int32_t arg1, u_int32_t arg2, u_int32_t arg3) 1959 { 1960 AAC_SETREG4(sc, AAC_RX_MAILBOX, command); 1961 AAC_SETREG4(sc, AAC_RX_MAILBOX + 4, arg0); 1962 AAC_SETREG4(sc, AAC_RX_MAILBOX + 8, arg1); 1963 AAC_SETREG4(sc, AAC_RX_MAILBOX + 12, arg2); 1964 AAC_SETREG4(sc, AAC_RX_MAILBOX + 16, arg3); 1965 } 1966 1967 void 1968 aac_fa_set_mailbox(struct aac_softc *sc, u_int32_t command, u_int32_t arg0, 1969 u_int32_t arg1, u_int32_t arg2, u_int32_t arg3) 1970 { 1971 AAC_SETREG4(sc, AAC_FA_MAILBOX, command); 1972 AAC_FA_HACK(sc); 1973 AAC_SETREG4(sc, AAC_FA_MAILBOX + 4, arg0); 1974 AAC_FA_HACK(sc); 1975 AAC_SETREG4(sc, AAC_FA_MAILBOX + 8, arg1); 1976 AAC_FA_HACK(sc); 1977 AAC_SETREG4(sc, AAC_FA_MAILBOX + 12, arg2); 1978 AAC_FA_HACK(sc); 1979 AAC_SETREG4(sc, AAC_FA_MAILBOX + 16, arg3); 1980 AAC_FA_HACK(sc); 1981 } 1982 1983 void 1984 aac_rkt_set_mailbox(struct aac_softc *sc, u_int32_t command, u_int32_t arg0, 1985 u_int32_t arg1, u_int32_t arg2, u_int32_t arg3) 1986 { 1987 AAC_SETREG4(sc, AAC_RKT_MAILBOX, command); 1988 AAC_SETREG4(sc, AAC_RKT_MAILBOX + 4, arg0); 1989 AAC_SETREG4(sc, AAC_RKT_MAILBOX + 8, arg1); 1990 AAC_SETREG4(sc, AAC_RKT_MAILBOX + 12, arg2); 1991 AAC_SETREG4(sc, AAC_RKT_MAILBOX + 16, arg3); 1992 } 1993 1994 /* 1995 * Fetch the immediate command status word 1996 */ 1997 int 1998 aac_sa_get_mailbox(struct aac_softc *sc, int mb) 1999 { 2000 return (AAC_GETREG4(sc, AAC_SA_MAILBOX + (mb * 4))); 2001 } 2002 2003 int 2004 aac_rx_get_mailbox(struct aac_softc *sc, int mb) 2005 { 2006 return (AAC_GETREG4(sc, AAC_RX_MAILBOX + (mb * 4))); 2007 } 2008 2009 int 2010 aac_fa_get_mailbox(struct aac_softc *sc, int mb) 2011 { 2012 return (AAC_GETREG4(sc, AAC_FA_MAILBOX + (mb * 4))); 2013 } 2014 2015 int 2016 aac_rkt_get_mailbox(struct aac_softc *sc, int mb) 2017 { 2018 return(AAC_GETREG4(sc, AAC_RKT_MAILBOX + (mb * 4))); 2019 } 2020 2021 /* 2022 * Set/clear interrupt masks 2023 */ 2024 void 2025 aac_sa_set_interrupts(struct aac_softc *sc, int enable) 2026 { 2027 AAC_DPRINTF(AAC_D_INTR, ("%s: %sable interrupts\n", 2028 sc->aac_dev.dv_xname, enable ? "en" : "dis")); 2029 2030 if (enable) 2031 AAC_SETREG2((sc), AAC_SA_MASK0_CLEAR, AAC_DB_INTERRUPTS); 2032 else 2033 AAC_SETREG2((sc), AAC_SA_MASK0_SET, ~0); 2034 } 2035 2036 void 2037 aac_rx_set_interrupts(struct aac_softc *sc, int enable) 2038 { 2039 AAC_DPRINTF(AAC_D_INTR, ("%s: %sable interrupts", 2040 sc->aac_dev.dv_xname, enable ? "en" : "dis")); 2041 2042 if (enable) 2043 AAC_SETREG4(sc, AAC_RX_OIMR, ~AAC_DB_INTERRUPTS); 2044 else 2045 AAC_SETREG4(sc, AAC_RX_OIMR, ~0); 2046 } 2047 2048 void 2049 aac_fa_set_interrupts(struct aac_softc *sc, int enable) 2050 { 2051 AAC_DPRINTF(AAC_D_INTR, ("%s: %sable interrupts", 2052 sc->aac_dev.dv_xname, enable ? "en" : "dis")); 2053 2054 if (enable) { 2055 AAC_SETREG2((sc), AAC_FA_MASK0_CLEAR, AAC_DB_INTERRUPTS); 2056 AAC_FA_HACK(sc); 2057 } else { 2058 AAC_SETREG2((sc), AAC_FA_MASK0, ~0); 2059 AAC_FA_HACK(sc); 2060 } 2061 } 2062 2063 void 2064 aac_rkt_set_interrupts(struct aac_softc *sc, int enable) 2065 { 2066 AAC_DPRINTF(AAC_D_INTR, ("%s: %sable interrupts", 2067 sc->aac_dev.dv_xname, enable ? "en" : "dis")); 2068 2069 if (enable) 2070 AAC_SETREG4(sc, AAC_RKT_OIMR, ~AAC_DB_INTERRUPTS); 2071 else 2072 AAC_SETREG4(sc, AAC_RKT_OIMR, ~0); 2073 } 2074 2075 void 2076 aac_eval_mapping(u_int32_t size, int *cyls, int *heads, int *secs) 2077 { 2078 *cyls = size / AAC_HEADS / AAC_SECS; 2079 if (*cyls < AAC_MAXCYLS) { 2080 *heads = AAC_HEADS; 2081 *secs = AAC_SECS; 2082 } else { 2083 /* Too high for 64 * 32 */ 2084 *cyls = size / AAC_MEDHEADS / AAC_MEDSECS; 2085 if (*cyls < AAC_MAXCYLS) { 2086 *heads = AAC_MEDHEADS; 2087 *secs = AAC_MEDSECS; 2088 } else { 2089 /* Too high for 127 * 63 */ 2090 *cyls = size / AAC_BIGHEADS / AAC_BIGSECS; 2091 *heads = AAC_BIGHEADS; 2092 *secs = AAC_BIGSECS; 2093 } 2094 } 2095 } 2096 2097 /* Emulated SCSI operation on cache device */ 2098 void 2099 aac_internal_cache_cmd(struct scsi_xfer *xs) 2100 { 2101 struct scsi_link *link = xs->sc_link; 2102 struct aac_softc *sc = link->bus->sb_adapter_softc; 2103 struct scsi_inquiry_data inq; 2104 struct scsi_sense_data sd; 2105 struct scsi_read_cap_data rcd; 2106 u_int8_t target = link->target; 2107 2108 AAC_DPRINTF(AAC_D_CMD, ("%s: aac_internal_cache_cmd: ", 2109 sc->aac_dev.dv_xname)); 2110 2111 switch (xs->cmd.opcode) { 2112 case TEST_UNIT_READY: 2113 case START_STOP: 2114 #if 0 2115 case VERIFY: 2116 #endif 2117 AAC_DPRINTF(AAC_D_CMD, ("opc %#x tgt %d ", xs->cmd.opcode, 2118 target)); 2119 break; 2120 2121 case REQUEST_SENSE: 2122 AAC_DPRINTF(AAC_D_CMD, ("REQUEST SENSE tgt %d ", target)); 2123 bzero(&sd, sizeof sd); 2124 sd.error_code = SSD_ERRCODE_CURRENT; 2125 sd.segment = 0; 2126 sd.flags = SKEY_NO_SENSE; 2127 aac_enc32(sd.info, 0); 2128 sd.extra_len = 0; 2129 scsi_copy_internal_data(xs, &sd, sizeof(sd)); 2130 break; 2131 2132 case INQUIRY: 2133 AAC_DPRINTF(AAC_D_CMD, ("INQUIRY tgt %d devtype %x ", target, 2134 sc->aac_hdr[target].hd_devtype)); 2135 bzero(&inq, sizeof inq); 2136 /* XXX How do we detect removable/CD-ROM devices? */ 2137 inq.device = T_DIRECT; 2138 inq.dev_qual2 = 0; 2139 inq.version = SCSI_REV_2; 2140 inq.response_format = SID_SCSI2_RESPONSE; 2141 inq.additional_length = SID_SCSI2_ALEN; 2142 inq.flags |= SID_CmdQue; 2143 strlcpy(inq.vendor, "Adaptec", sizeof inq.vendor); 2144 snprintf(inq.product, sizeof inq.product, "Container #%02d", 2145 target); 2146 strlcpy(inq.revision, " ", sizeof inq.revision); 2147 scsi_copy_internal_data(xs, &inq, sizeof(inq)); 2148 break; 2149 2150 case READ_CAPACITY: 2151 AAC_DPRINTF(AAC_D_CMD, ("READ CAPACITY tgt %d ", target)); 2152 bzero(&rcd, sizeof rcd); 2153 _lto4b(sc->aac_hdr[target].hd_size - 1, rcd.addr); 2154 _lto4b(AAC_BLOCK_SIZE, rcd.length); 2155 scsi_copy_internal_data(xs, (u_int8_t *)&rcd, sizeof rcd); 2156 break; 2157 2158 default: 2159 AAC_DPRINTF(AAC_D_CMD, ("\n")); 2160 printf("aac_internal_cache_cmd got bad opcode: %#x\n", 2161 xs->cmd.opcode); 2162 xs->error = XS_DRIVER_STUFFUP; 2163 return; 2164 } 2165 2166 xs->error = XS_NOERROR; 2167 } 2168 2169 void 2170 aac_scsi_cmd(struct scsi_xfer *xs) 2171 { 2172 struct scsi_link *link = xs->sc_link; 2173 struct aac_softc *sc = link->bus->sb_adapter_softc; 2174 u_int8_t target = link->target; 2175 struct aac_command *cm; 2176 u_int32_t blockno, blockcnt; 2177 struct scsi_rw *rw; 2178 struct scsi_rw_10 *rw10; 2179 int s; 2180 2181 s = splbio(); 2182 2183 xs->error = XS_NOERROR; 2184 2185 if (target >= AAC_MAX_CONTAINERS || !sc->aac_hdr[target].hd_present || 2186 link->lun != 0) { 2187 /* 2188 * XXX Should be XS_SENSE but that would require setting up a 2189 * faked sense too. 2190 */ 2191 splx(s); 2192 xs->error = XS_DRIVER_STUFFUP; 2193 scsi_done(xs); 2194 return; 2195 } 2196 2197 AAC_DPRINTF(AAC_D_CMD, ("%s: aac_scsi_cmd: ", sc->aac_dev.dv_xname)); 2198 2199 xs->error = XS_NOERROR; 2200 cm = NULL; 2201 link = xs->sc_link; 2202 target = link->target; 2203 2204 switch (xs->cmd.opcode) { 2205 case TEST_UNIT_READY: 2206 case REQUEST_SENSE: 2207 case INQUIRY: 2208 case START_STOP: 2209 case READ_CAPACITY: 2210 #if 0 2211 case VERIFY: 2212 #endif 2213 aac_internal_cache_cmd(xs); 2214 scsi_done(xs); 2215 goto ready; 2216 2217 case PREVENT_ALLOW: 2218 AAC_DPRINTF(AAC_D_CMD, ("PREVENT/ALLOW ")); 2219 /* XXX Not yet implemented */ 2220 xs->error = XS_NOERROR; 2221 scsi_done(xs); 2222 goto ready; 2223 2224 case SYNCHRONIZE_CACHE: 2225 AAC_DPRINTF(AAC_D_CMD, ("SYNCHRONIZE_CACHE ")); 2226 /* XXX Not yet implemented */ 2227 xs->error = XS_NOERROR; 2228 scsi_done(xs); 2229 goto ready; 2230 2231 default: 2232 AAC_DPRINTF(AAC_D_CMD, ("unknown opc %#x ", xs->cmd.opcode)); 2233 /* XXX Not yet implemented */ 2234 xs->error = XS_DRIVER_STUFFUP; 2235 scsi_done(xs); 2236 goto ready; 2237 2238 case READ_COMMAND: 2239 case READ_10: 2240 case WRITE_COMMAND: 2241 case WRITE_10: 2242 AAC_DPRINTF(AAC_D_CMD, ("rw opc %#x ", xs->cmd.opcode)); 2243 2244 /* A read or write operation. */ 2245 if (xs->cmdlen == 6) { 2246 rw = (struct scsi_rw *)&xs->cmd; 2247 blockno = _3btol(rw->addr) & 2248 (SRW_TOPADDR << 16 | 0xffff); 2249 blockcnt = rw->length ? rw->length : 0x100; 2250 } else { 2251 rw10 = (struct scsi_rw_10 *)&xs->cmd; 2252 blockno = _4btol(rw10->addr); 2253 blockcnt = _2btol(rw10->length); 2254 } 2255 2256 AAC_DPRINTF(AAC_D_CMD, ("opcode=%d blkno=%d bcount=%d ", 2257 xs->cmd.opcode, blockno, blockcnt)); 2258 2259 if (blockno >= sc->aac_hdr[target].hd_size || 2260 blockno + blockcnt > sc->aac_hdr[target].hd_size) { 2261 AAC_DPRINTF(AAC_D_CMD, ("\n")); 2262 printf("%s: out of bounds %u-%u >= %u\n", 2263 sc->aac_dev.dv_xname, blockno, 2264 blockcnt, sc->aac_hdr[target].hd_size); 2265 /* 2266 * XXX Should be XS_SENSE but that 2267 * would require setting up a faked 2268 * sense too. 2269 */ 2270 xs->error = XS_DRIVER_STUFFUP; 2271 scsi_done(xs); 2272 goto ready; 2273 } 2274 2275 cm = xs->io; 2276 aac_scrub_command(cm); 2277 2278 /* fill out the command */ 2279 cm->cm_data = (void *)xs->data; 2280 cm->cm_datalen = xs->datalen; 2281 cm->cm_complete = aac_bio_complete; 2282 cm->cm_private = xs; 2283 cm->cm_timestamp = getuptime(); 2284 cm->cm_queue = AAC_ADAP_NORM_CMD_QUEUE; 2285 cm->cm_blkno = blockno; 2286 cm->cm_bcount = blockcnt; 2287 2288 AAC_DPRINTF(AAC_D_CMD, ("\n")); 2289 aac_enqueue_bio(cm); 2290 aac_startio(sc); 2291 2292 /* XXX what if enqueue did not start a transfer? */ 2293 if (xs->flags & SCSI_POLL) { 2294 if (!aac_wait_command(cm, xs->timeout)) 2295 { 2296 printf("%s: command timed out\n", 2297 sc->aac_dev.dv_xname); 2298 xs->error = XS_DRIVER_STUFFUP; 2299 scsi_done(xs); 2300 splx(s); 2301 return; 2302 } 2303 scsi_done(xs); 2304 } 2305 } 2306 2307 ready: 2308 splx(s); 2309 AAC_DPRINTF(AAC_D_CMD, ("%s: scsi_cmd complete\n", 2310 sc->aac_dev.dv_xname)); 2311 } 2312 2313 /* 2314 * Debugging and Diagnostics 2315 */ 2316 2317 /* 2318 * Print some information about the controller. 2319 */ 2320 void 2321 aac_describe_controller(struct aac_softc *sc) 2322 { 2323 struct aac_fib *fib; 2324 struct aac_adapter_info *info; 2325 2326 aac_alloc_sync_fib(sc, &fib, 0); 2327 2328 fib->data[0] = 0; 2329 if (aac_sync_fib(sc, RequestAdapterInfo, 0, fib, 1)) { 2330 printf("%s: RequestAdapterInfo failed 2\n", 2331 sc->aac_dev.dv_xname); 2332 aac_release_sync_fib(sc); 2333 return; 2334 } 2335 info = (struct aac_adapter_info *)&fib->data[0]; 2336 2337 printf("%s: %s %dMHz, %dMB cache memory, %s\n", sc->aac_dev.dv_xname, 2338 aac_describe_code(aac_cpu_variant, info->CpuVariant), 2339 info->ClockSpeed, info->BufferMem / (1024 * 1024), 2340 aac_describe_code(aac_battery_platform, info->batteryPlatform)); 2341 2342 /* save the kernel revision structure for later use */ 2343 sc->aac_revision = info->KernelRevision; 2344 printf("%s: Kernel %d.%d-%d, Build %d, S/N %6X\n", 2345 sc->aac_dev.dv_xname, 2346 info->KernelRevision.external.comp.major, 2347 info->KernelRevision.external.comp.minor, 2348 info->KernelRevision.external.comp.dash, 2349 info->KernelRevision.buildNumber, 2350 (u_int32_t)(info->SerialNumber & 0xffffff)); 2351 2352 aac_release_sync_fib(sc); 2353 } 2354 2355 /* 2356 * Look up a text description of a numeric error code and return a pointer to 2357 * same. 2358 */ 2359 char * 2360 aac_describe_code(struct aac_code_lookup *table, u_int32_t code) 2361 { 2362 int i; 2363 2364 for (i = 0; table[i].string != NULL; i++) 2365 if (table[i].code == code) 2366 return(table[i].string); 2367 return(table[i + 1].string); 2368 } 2369 2370 #ifdef AAC_DEBUG 2371 /* 2372 * Print a FIB 2373 */ 2374 void 2375 aac_print_fib(struct aac_softc *sc, struct aac_fib *fib, const char *caller) 2376 { 2377 printf("%s: FIB @ %p\n", caller, fib); 2378 printf(" XferState %b\n", fib->Header.XferState, "\20" 2379 "\1HOSTOWNED" 2380 "\2ADAPTEROWNED" 2381 "\3INITIALISED" 2382 "\4EMPTY" 2383 "\5FROMPOOL" 2384 "\6FROMHOST" 2385 "\7FROMADAP" 2386 "\10REXPECTED" 2387 "\11RNOTEXPECTED" 2388 "\12DONEADAP" 2389 "\13DONEHOST" 2390 "\14HIGH" 2391 "\15NORM" 2392 "\16ASYNC" 2393 "\17PAGEFILEIO" 2394 "\20SHUTDOWN" 2395 "\21LAZYWRITE" 2396 "\22ADAPMICROFIB" 2397 "\23BIOSFIB" 2398 "\24FAST_RESPONSE" 2399 "\25APIFIB\n"); 2400 printf(" Command %d\n", fib->Header.Command); 2401 printf(" StructType %d\n", fib->Header.StructType); 2402 printf(" Flags 0x%x\n", fib->Header.Flags); 2403 printf(" Size %d\n", fib->Header.Size); 2404 printf(" SenderSize %d\n", fib->Header.SenderSize); 2405 printf(" SenderAddress 0x%x\n", fib->Header.SenderFibAddress); 2406 printf(" ReceiverAddress 0x%x\n", fib->Header.ReceiverFibAddress); 2407 printf(" SenderData 0x%x\n", fib->Header.SenderData); 2408 switch(fib->Header.Command) { 2409 case ContainerCommand: { 2410 struct aac_blockread *br = (struct aac_blockread *)fib->data; 2411 struct aac_blockwrite *bw = (struct aac_blockwrite *)fib->data; 2412 struct aac_sg_table *sg = NULL; 2413 int i; 2414 2415 if (br->Command == VM_CtBlockRead) { 2416 printf(" BlockRead: container %d 0x%x/%d\n", 2417 br->ContainerId, br->BlockNumber, br->ByteCount); 2418 sg = &br->SgMap; 2419 } 2420 if (bw->Command == VM_CtBlockWrite) { 2421 printf(" BlockWrite: container %d 0x%x/%d (%s)\n", 2422 bw->ContainerId, bw->BlockNumber, bw->ByteCount, 2423 bw->Stable == CSTABLE ? "stable" : "unstable"); 2424 sg = &bw->SgMap; 2425 } 2426 if (sg != NULL) { 2427 printf(" %d s/g entries\n", sg->SgCount); 2428 for (i = 0; i < sg->SgCount; i++) 2429 printf(" 0x%08x/%d\n", 2430 sg->SgEntry[i].SgAddress, 2431 sg->SgEntry[i].SgByteCount); 2432 } 2433 break; 2434 } 2435 default: 2436 printf(" %16D\n", fib->data, " "); 2437 printf(" %16D\n", fib->data + 16, " "); 2438 break; 2439 } 2440 } 2441 2442 /* 2443 * Describe an AIF we have received. 2444 */ 2445 void 2446 aac_print_aif(struct aac_softc *sc, struct aac_aif_command *aif) 2447 { 2448 printf("%s: print_aif: ", sc->aac_dev.dv_xname); 2449 2450 switch(aif->command) { 2451 case AifCmdEventNotify: 2452 printf("EventNotify(%d)\n", aif->seqNumber); 2453 2454 switch(aif->data.EN.type) { 2455 case AifEnGeneric: 2456 /* Generic notification */ 2457 printf("\t(Generic) %.*s\n", 2458 (int)sizeof(aif->data.EN.data.EG), 2459 aif->data.EN.data.EG.text); 2460 break; 2461 case AifEnTaskComplete: 2462 /* Task has completed */ 2463 printf("\t(TaskComplete)\n"); 2464 break; 2465 case AifEnConfigChange: 2466 /* Adapter configuration change occurred */ 2467 printf("\t(ConfigChange)\n"); 2468 break; 2469 case AifEnContainerChange: 2470 /* Adapter specific container configuration change */ 2471 printf("\t(ContainerChange) container %d,%d\n", 2472 aif->data.EN.data.ECC.container[0], 2473 aif->data.EN.data.ECC.container[1]); 2474 break; 2475 case AifEnDeviceFailure: 2476 /* SCSI device failed */ 2477 printf("\t(DeviceFailure) handle %d\n", 2478 aif->data.EN.data.EDF.deviceHandle); 2479 break; 2480 case AifEnMirrorFailover: 2481 /* Mirror failover started */ 2482 printf("\t(MirrorFailover) container %d failed, " 2483 "migrating from slice %d to %d\n", 2484 aif->data.EN.data.EMF.container, 2485 aif->data.EN.data.EMF.failedSlice, 2486 aif->data.EN.data.EMF.creatingSlice); 2487 break; 2488 case AifEnContainerEvent: 2489 /* Significant container event */ 2490 printf("\t(ContainerEvent) container %d event %d\n", 2491 aif->data.EN.data.ECE.container, 2492 aif->data.EN.data.ECE.eventType); 2493 break; 2494 case AifEnFileSystemChange: 2495 /* File system changed */ 2496 printf("\t(FileSystemChange)\n"); 2497 break; 2498 case AifEnConfigPause: 2499 /* Container pause event */ 2500 printf("\t(ConfigPause)\n"); 2501 break; 2502 case AifEnConfigResume: 2503 /* Container resume event */ 2504 printf("\t(ConfigResume)\n"); 2505 break; 2506 case AifEnFailoverChange: 2507 /* Failover space assignment changed */ 2508 printf("\t(FailoverChange)\n"); 2509 break; 2510 case AifEnRAID5RebuildDone: 2511 /* RAID5 rebuild finished */ 2512 printf("\t(RAID5RebuildDone)\n"); 2513 break; 2514 case AifEnEnclosureManagement: 2515 /* Enclosure management event */ 2516 printf("\t(EnclosureManagement) EMPID %d unit %d " 2517 "event %d\n", 2518 aif->data.EN.data.EEE.empID, 2519 aif->data.EN.data.EEE.unitID, 2520 aif->data.EN.data.EEE.eventType); 2521 break; 2522 case AifEnBatteryEvent: 2523 /* Significant NV battery event */ 2524 printf("\t(BatteryEvent) %d (state was %d, is %d\n", 2525 aif->data.EN.data.EBE.transition_type, 2526 aif->data.EN.data.EBE.current_state, 2527 aif->data.EN.data.EBE.prior_state); 2528 break; 2529 case AifEnAddContainer: 2530 /* A new container was created. */ 2531 printf("\t(AddContainer)\n"); 2532 break; 2533 case AifEnDeleteContainer: 2534 /* A container was deleted. */ 2535 printf("\t(DeleteContainer)\n"); 2536 break; 2537 case AifEnBatteryNeedsRecond: 2538 /* The battery needs reconditioning */ 2539 printf("\t(BatteryNeedsRecond)\n"); 2540 break; 2541 case AifEnClusterEvent: 2542 /* Some cluster event */ 2543 printf("\t(ClusterEvent) event %d\n", 2544 aif->data.EN.data.ECLE.eventType); 2545 break; 2546 case AifEnDiskSetEvent: 2547 /* A disk set event occurred. */ 2548 printf("(DiskSetEvent) event %d " 2549 "diskset %lld creator %lld\n", 2550 aif->data.EN.data.EDS.eventType, 2551 aif->data.EN.data.EDS.DsNum, 2552 aif->data.EN.data.EDS.CreatorId); 2553 break; 2554 case AifDenMorphComplete: 2555 /* A morph operation completed */ 2556 printf("\t(MorphComplete)\n"); 2557 break; 2558 case AifDenVolumeExtendComplete: 2559 /* A volume expand operation completed */ 2560 printf("\t(VolumeExtendComplete)\n"); 2561 break; 2562 default: 2563 printf("\t(%d)\n", aif->data.EN.type); 2564 break; 2565 } 2566 break; 2567 case AifCmdJobProgress: 2568 { 2569 char *status; 2570 switch(aif->data.PR[0].status) { 2571 case AifJobStsSuccess: 2572 status = "success"; break; 2573 case AifJobStsFinished: 2574 status = "finished"; break; 2575 case AifJobStsAborted: 2576 status = "aborted"; break; 2577 case AifJobStsFailed: 2578 status = "failed"; break; 2579 case AifJobStsSuspended: 2580 status = "suspended"; break; 2581 case AifJobStsRunning: 2582 status = "running"; break; 2583 default: 2584 status = "unknown status"; break; 2585 } 2586 2587 printf("JobProgress (%d) - %s (%d, %d)\n", 2588 aif->seqNumber, status, 2589 aif->data.PR[0].currentTick, 2590 aif->data.PR[0].finalTick); 2591 2592 switch(aif->data.PR[0].jd.type) { 2593 case AifJobScsiZero: 2594 /* SCSI dev clear operation */ 2595 printf("\t(ScsiZero) handle %d\n", 2596 aif->data.PR[0].jd.client.scsi_dh); 2597 break; 2598 case AifJobScsiVerify: 2599 /* SCSI device Verify operation NO REPAIR */ 2600 printf("\t(ScsiVerify) handle %d\n", 2601 aif->data.PR[0].jd.client.scsi_dh); 2602 break; 2603 case AifJobScsiExercise: 2604 /* SCSI device Exercise operation */ 2605 printf("\t(ScsiExercise) handle %d\n", 2606 aif->data.PR[0].jd.client.scsi_dh); 2607 break; 2608 case AifJobScsiVerifyRepair: 2609 /* SCSI device Verify operation WITH repair */ 2610 printf("\t(ScsiVerifyRepair) handle %d\n", 2611 aif->data.PR[0].jd.client.scsi_dh); 2612 break; 2613 case AifJobCtrZero: 2614 /* Container clear operation */ 2615 printf("\t(ContainerZero) container %d\n", 2616 aif->data.PR[0].jd.client.container.src); 2617 break; 2618 case AifJobCtrCopy: 2619 /* Container copy operation */ 2620 printf("\t(ContainerCopy) container %d to %d\n", 2621 aif->data.PR[0].jd.client.container.src, 2622 aif->data.PR[0].jd.client.container.dst); 2623 break; 2624 case AifJobCtrCreateMirror: 2625 /* Container Create Mirror operation */ 2626 printf("\t(ContainerCreateMirror) container %d\n", 2627 aif->data.PR[0].jd.client.container.src); 2628 /* XXX two containers? */ 2629 break; 2630 case AifJobCtrMergeMirror: 2631 /* Container Merge Mirror operation */ 2632 printf("\t(ContainerMergeMirror) container %d\n", 2633 aif->data.PR[0].jd.client.container.src); 2634 /* XXX two containers? */ 2635 break; 2636 case AifJobCtrScrubMirror: 2637 /* Container Scrub Mirror operation */ 2638 printf("\t(ContainerScrubMirror) container %d\n", 2639 aif->data.PR[0].jd.client.container.src); 2640 break; 2641 case AifJobCtrRebuildRaid5: 2642 /* Container Rebuild Raid5 operation */ 2643 printf("\t(ContainerRebuildRaid5) container %d\n", 2644 aif->data.PR[0].jd.client.container.src); 2645 break; 2646 case AifJobCtrScrubRaid5: 2647 /* Container Scrub Raid5 operation */ 2648 printf("\t(ContainerScrubRaid5) container %d\n", 2649 aif->data.PR[0].jd.client.container.src); 2650 break; 2651 case AifJobCtrMorph: 2652 /* Container morph operation */ 2653 printf("\t(ContainerMorph) container %d\n", 2654 aif->data.PR[0].jd.client.container.src); 2655 /* XXX two containers? */ 2656 break; 2657 case AifJobCtrPartCopy: 2658 /* Container Partition copy operation */ 2659 printf("\t(ContainerPartCopy) container %d to %d\n", 2660 aif->data.PR[0].jd.client.container.src, 2661 aif->data.PR[0].jd.client.container.dst); 2662 break; 2663 case AifJobCtrRebuildMirror: 2664 /* Container Rebuild Mirror operation */ 2665 printf("\t(ContainerRebuildMirror) container %d\n", 2666 aif->data.PR[0].jd.client.container.src); 2667 break; 2668 case AifJobCtrCrazyCache: 2669 /* crazy cache */ 2670 printf("\t(ContainerCrazyCache) container %d\n", 2671 aif->data.PR[0].jd.client.container.src); 2672 /* XXX two containers? */ 2673 break; 2674 case AifJobFsCreate: 2675 /* File System Create operation */ 2676 printf("\t(FsCreate)\n"); 2677 break; 2678 case AifJobFsVerify: 2679 /* File System Verify operation */ 2680 printf("\t(FsVerivy)\n"); 2681 break; 2682 case AifJobFsExtend: 2683 /* File System Extend operation */ 2684 printf("\t(FsExtend)\n"); 2685 break; 2686 case AifJobApiFormatNTFS: 2687 /* Format a drive to NTFS */ 2688 printf("\t(FormatNTFS)\n"); 2689 break; 2690 case AifJobApiFormatFAT: 2691 /* Format a drive to FAT */ 2692 printf("\t(FormatFAT)\n"); 2693 break; 2694 case AifJobApiUpdateSnapshot: 2695 /* update the read/write half of a snapshot */ 2696 printf("\t(UpdateSnapshot)\n"); 2697 break; 2698 case AifJobApiFormatFAT32: 2699 /* Format a drive to FAT32 */ 2700 printf("\t(FormatFAT32)\n"); 2701 break; 2702 case AifJobCtlContinuousCtrVerify: 2703 /* Adapter operation */ 2704 printf("\t(ContinuousCtrVerify)\n"); 2705 break; 2706 default: 2707 printf("\t(%d)\n", aif->data.PR[0].jd.type); 2708 break; 2709 } 2710 break; 2711 } 2712 case AifCmdAPIReport: 2713 printf("APIReport (%d)\n", aif->seqNumber); 2714 break; 2715 case AifCmdDriverNotify: 2716 printf("DriverNotify (%d)\n", aif->seqNumber); 2717 break; 2718 default: 2719 printf("AIF %d (%d)\n", aif->command, aif->seqNumber); 2720 break; 2721 } 2722 } 2723 #endif 2724