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