1 /* $OpenBSD: aac.c,v 1.7 2001/08/12 20:12:11 mickey Exp $ */ 2 3 /*- 4 * Copyright (c) 2000 Michael Smith 5 * Copyright (c) 2000 BSDi 6 * Copyright (c) 2000 Niklas Hallqvist 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 * 30 * $FreeBSD: /c/ncvs/src/sys/dev/aac/aac.c,v 1.1 2000/09/13 03:20:34 msmith Exp $ 31 */ 32 33 /* 34 * Driver for the Adaptec 'FSA' family of PCI/SCSI RAID adapters. 35 */ 36 37 /* 38 * This driver would not have rewritten for OpenBSD if it was not for the 39 * hardware donation from Nocom. I want to thank them for their support. 40 * Of course, credit should go to Mike Smith for the original work he did 41 * in the FreeBSD driver where I found lots of reusable code and inspiration. 42 * - Niklas Hallqvist 43 */ 44 45 #include <sys/param.h> 46 #include <sys/systm.h> 47 #include <sys/buf.h> 48 #include <sys/device.h> 49 #include <sys/kernel.h> 50 #include <sys/malloc.h> 51 52 #include <machine/bus.h> 53 54 #include <vm/vm.h> 55 56 #include <scsi/scsi_all.h> 57 #include <scsi/scsi_disk.h> 58 #include <scsi/scsiconf.h> 59 60 #include <dev/ic/aacreg.h> 61 #include <dev/ic/aacvar.h> 62 #include <dev/ic/aac_tables.h> 63 64 /* Geometry constants. */ 65 #define AAC_MAXCYLS 1024 66 #define AAC_HEADS 64 67 #define AAC_SECS 32 /* mapping 64*32 */ 68 #define AAC_MEDHEADS 127 69 #define AAC_MEDSECS 63 /* mapping 127*63 */ 70 #define AAC_BIGHEADS 255 71 #define AAC_BIGSECS 63 /* mapping 255*63 */ 72 #define AAC_SECS32 0x1f /* round capacity */ 73 74 void aac_bio_complete __P((struct aac_ccb *)); 75 void aac_complete __P((void *, int)); 76 void aac_copy_internal_data __P((struct scsi_xfer *, u_int8_t *, size_t)); 77 struct scsi_xfer *aac_dequeue __P((struct aac_softc *)); 78 int aac_dequeue_fib __P((struct aac_softc *, int, u_int32_t *, 79 struct aac_fib **)); 80 char *aac_describe_code __P((struct aac_code_lookup *, u_int32_t)); 81 void aac_describe_controller __P((struct aac_softc *)); 82 void aac_enqueue __P((struct aac_softc *, struct scsi_xfer *, int)); 83 void aac_enqueue_ccb __P((struct aac_softc *, struct aac_ccb *)); 84 int aac_enqueue_fib __P((struct aac_softc *, int, u_int32_t, u_int32_t)); 85 void aac_eval_mapping __P((u_int32_t, int *, int *, int *)); 86 int aac_exec_ccb __P((struct aac_ccb *)); 87 void aac_free_ccb __P((struct aac_softc *, struct aac_ccb *)); 88 struct aac_ccb *aac_get_ccb __P((struct aac_softc *, int)); 89 #if 0 90 void aac_handle_aif __P((struct aac_softc *, struct aac_aif_command *)); 91 #endif 92 void aac_host_command __P((struct aac_softc *)); 93 void aac_host_response __P((struct aac_softc *)); 94 int aac_init __P((struct aac_softc *)); 95 int aac_internal_cache_cmd __P((struct scsi_xfer *)); 96 int aac_map_command __P((struct aac_ccb *)); 97 #ifdef AAC_DEBUG 98 void aac_print_fib __P((struct aac_softc *, struct aac_fib *, char *)); 99 #endif 100 int aac_raw_scsi_cmd __P((struct scsi_xfer *)); 101 int aac_scsi_cmd __P((struct scsi_xfer *)); 102 int aac_start __P((struct aac_ccb *)); 103 void aac_start_ccbs __P((struct aac_softc *)); 104 void aac_startup __P((struct aac_softc *)); 105 int aac_sync_command __P((struct aac_softc *, u_int32_t, u_int32_t, 106 u_int32_t, u_int32_t, u_int32_t, u_int32_t *)); 107 int aac_sync_fib __P((struct aac_softc *, u_int32_t, u_int32_t, void *, 108 u_int16_t, void *, u_int16_t *)); 109 void aac_timeout __P((void *)); 110 void aac_unmap_command __P((struct aac_ccb *)); 111 void aac_watchdog __P((void *)); 112 113 struct cfdriver aac_cd = { 114 NULL, "aac", DV_DULL 115 }; 116 117 struct scsi_adapter aac_switch = { 118 aac_scsi_cmd, aacminphys, 0, 0, 119 }; 120 121 struct scsi_adapter aac_raw_switch = { 122 aac_raw_scsi_cmd, aacminphys, 0, 0, 123 }; 124 125 struct scsi_device aac_dev = { 126 NULL, NULL, NULL, NULL 127 }; 128 129 /* i960Rx interface */ 130 int aac_rx_get_fwstatus __P((struct aac_softc *)); 131 void aac_rx_qnotify __P((struct aac_softc *, int)); 132 int aac_rx_get_istatus __P((struct aac_softc *)); 133 void aac_rx_clear_istatus __P((struct aac_softc *, int)); 134 void aac_rx_set_mailbox __P((struct aac_softc *, u_int32_t, u_int32_t, 135 u_int32_t, u_int32_t, u_int32_t)); 136 int aac_rx_get_mailboxstatus __P((struct aac_softc *)); 137 void aac_rx_set_interrupts __P((struct aac_softc *, int)); 138 139 /* StrongARM interface */ 140 int aac_sa_get_fwstatus __P((struct aac_softc *)); 141 void aac_sa_qnotify __P((struct aac_softc *, int)); 142 int aac_sa_get_istatus __P((struct aac_softc *)); 143 void aac_sa_clear_istatus __P((struct aac_softc *, int)); 144 void aac_sa_set_mailbox __P((struct aac_softc *, u_int32_t, u_int32_t, 145 u_int32_t, u_int32_t, u_int32_t)); 146 int aac_sa_get_mailboxstatus __P((struct aac_softc *)); 147 void aac_sa_set_interrupts __P((struct aac_softc *, int)); 148 149 struct aac_interface aac_rx_interface = { 150 aac_rx_get_fwstatus, 151 aac_rx_qnotify, 152 aac_rx_get_istatus, 153 aac_rx_clear_istatus, 154 aac_rx_set_mailbox, 155 aac_rx_get_mailboxstatus, 156 aac_rx_set_interrupts 157 }; 158 159 struct aac_interface aac_sa_interface = { 160 aac_sa_get_fwstatus, 161 aac_sa_qnotify, 162 aac_sa_get_istatus, 163 aac_sa_clear_istatus, 164 aac_sa_set_mailbox, 165 aac_sa_get_mailboxstatus, 166 aac_sa_set_interrupts 167 }; 168 169 #ifdef AAC_DEBUG 170 int aac_debug = AAC_DEBUG; 171 #endif 172 173 int 174 aac_attach(sc) 175 struct aac_softc *sc; 176 { 177 int i, error; 178 bus_dma_segment_t seg; 179 int nsegs; 180 struct aac_ccb *ccb; 181 182 TAILQ_INIT(&sc->sc_free_ccb); 183 TAILQ_INIT(&sc->sc_ccbq); 184 TAILQ_INIT(&sc->sc_completed); 185 LIST_INIT(&sc->sc_queue); 186 187 /* disable interrupts before we enable anything */ 188 AAC_MASK_INTERRUPTS(sc); 189 190 /* mark controller as suspended until we get ourselves organised */ 191 sc->sc_state |= AAC_STATE_SUSPEND; 192 193 /* 194 * Initialise the adapter. 195 */ 196 error = aac_init(sc); 197 if (error) 198 return (error); 199 200 /* 201 * Print a little information about the controller. 202 */ 203 aac_describe_controller(sc); 204 205 /* Initialize the ccbs */ 206 for (i = 0; i < AAC_ADAP_NORM_CMD_ENTRIES; i++) { 207 ccb = &sc->sc_ccbs[i]; 208 error = bus_dmamap_create(sc->sc_dmat, 209 (AAC_MAXSGENTRIES - 1) << PGSHIFT, AAC_MAXSGENTRIES, 210 (AAC_MAXSGENTRIES - 1) << PGSHIFT, 0, 211 BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &ccb->ac_dmamap_xfer); 212 if (error) { 213 printf("%s: cannot create ccb dmamap (%d)", 214 sc->sc_dev.dv_xname, error); 215 /* XXX cleanup */ 216 return (1); 217 } 218 219 /* allocate the FIB cluster in DMAable memory and load it */ 220 if (bus_dmamem_alloc(sc->sc_dmat, sizeof *ccb->ac_fib, 1, 0, 221 &seg, 1, &nsegs, BUS_DMA_NOWAIT)) { 222 printf("%s: can't allocate FIB structure\n", 223 sc->sc_dev.dv_xname); 224 /* XXX cleanup */ 225 return (1); 226 } 227 ccb->ac_fibphys = seg.ds_addr; 228 if (bus_dmamem_map(sc->sc_dmat, &seg, nsegs, 229 sizeof *ccb->ac_fib, (caddr_t *)&ccb->ac_fib, 0)) { 230 printf("%s: can't map FIB structure\n", 231 sc->sc_dev.dv_xname); 232 /* XXX cleanup */ 233 return (1); 234 } 235 236 TAILQ_INSERT_TAIL(&sc->sc_free_ccb, &sc->sc_ccbs[i], 237 ac_chain); 238 } 239 240 /* Fill in the prototype scsi_link. */ 241 sc->sc_link.adapter_softc = sc; 242 sc->sc_link.adapter = &aac_switch; 243 sc->sc_link.device = &aac_dev; 244 sc->sc_link.openings = AAC_ADAP_NORM_CMD_ENTRIES; /* XXX optimal? */ 245 sc->sc_link.adapter_buswidth = AAC_MAX_CONTAINERS; 246 sc->sc_link.adapter_target = AAC_MAX_CONTAINERS; 247 248 config_found(&sc->sc_dev, &sc->sc_link, scsiprint); 249 250 return (0); 251 } 252 253 /* 254 * Look up a text description of a numeric error code and return a pointer to 255 * same. 256 */ 257 char * 258 aac_describe_code(table, code) 259 struct aac_code_lookup *table; 260 u_int32_t code; 261 { 262 int i; 263 264 for (i = 0; table[i].string != NULL; i++) 265 if (table[i].code == code) 266 return (table[i].string); 267 return (table[i + 1].string); 268 } 269 270 void 271 aac_describe_controller(sc) 272 struct aac_softc *sc; 273 { 274 u_int8_t buf[AAC_FIB_DATASIZE]; /* XXX a bit big for the stack */ 275 u_int16_t bufsize; 276 struct aac_adapter_info *info; 277 u_int8_t arg; 278 279 arg = 0; 280 if (aac_sync_fib(sc, RequestAdapterInfo, 0, &arg, sizeof arg, &buf, 281 &bufsize)) { 282 printf("%s: RequestAdapterInfo failed\n", sc->sc_dev.dv_xname); 283 return; 284 } 285 if (bufsize != sizeof *info) { 286 printf("%s: " 287 "RequestAdapterInfo returned wrong data size (%d != %d)\n", 288 sc->sc_dev.dv_xname, bufsize, sizeof *info); 289 return; 290 } 291 info = (struct aac_adapter_info *)&buf[0]; 292 293 printf("%s: %s %dMHz, %dMB, %s (%d) Kernel %d.%d-%d\n", 294 sc->sc_dev.dv_xname, 295 aac_describe_code(aac_cpu_variant, info->CpuVariant), 296 info->ClockSpeed, info->TotalMem / (1024 * 1024), 297 aac_describe_code(aac_battery_platform, info->batteryPlatform), 298 info->batteryPlatform, info->KernelRevision.external.comp.major, 299 info->KernelRevision.external.comp.minor, 300 info->KernelRevision.external.comp.dash); 301 302 /* save the kernel revision structure for later use */ 303 sc->sc_revision = info->KernelRevision; 304 } 305 306 int 307 aac_init(sc) 308 struct aac_softc *sc; 309 { 310 bus_dma_segment_t seg; 311 int nsegs; 312 int i, error; 313 int state = 0; 314 struct aac_adapter_init *ip; 315 u_int32_t code; 316 u_int8_t *qaddr; 317 318 /* 319 * First wait for the adapter to come ready. 320 */ 321 for (i = 0; i < AAC_BOOT_TIMEOUT * 1000; i++) { 322 code = AAC_GET_FWSTATUS(sc); 323 if (code & AAC_SELF_TEST_FAILED) { 324 printf("%s: FATAL: selftest failed\n", 325 sc->sc_dev.dv_xname); 326 return (ENXIO); 327 } 328 if (code & AAC_KERNEL_PANIC) { 329 printf("%s: FATAL: controller kernel panic\n", 330 sc->sc_dev.dv_xname); 331 return (ENXIO); 332 } 333 if (code & AAC_UP_AND_RUNNING) 334 break; 335 DELAY(1000); 336 } 337 if (i == AAC_BOOT_TIMEOUT * 1000) { 338 printf("%s: FATAL: controller not coming ready, status %x\n", 339 sc->sc_dev.dv_xname, code); 340 return (ENXIO); 341 } 342 343 if (bus_dmamem_alloc(sc->sc_dmat, sizeof *sc->sc_common, 1, 0, &seg, 1, 344 &nsegs, BUS_DMA_NOWAIT)) { 345 printf("%s: can't allocate common structure\n", 346 sc->sc_dev.dv_xname); 347 return (ENOMEM); 348 } 349 state++; 350 sc->sc_common_busaddr = seg.ds_addr; 351 if (bus_dmamem_map(sc->sc_dmat, &seg, nsegs, sizeof *sc->sc_common, 352 (caddr_t *)&sc->sc_common, 0)) { 353 printf("%s: can't map common structure\n", 354 sc->sc_dev.dv_xname); 355 error = ENOMEM; 356 goto bail_out; 357 } 358 state++; 359 bzero(sc->sc_common, sizeof *sc->sc_common); 360 361 /* 362 * Fill in the init structure. This tells the adapter about 363 * the physical location * of various important shared data 364 * structures. 365 */ 366 ip = &sc->sc_common->ac_init; 367 ip->InitStructRevision = AAC_INIT_STRUCT_REVISION; 368 369 ip->AdapterFibsPhysicalAddress = 370 sc->sc_common_busaddr + offsetof(struct aac_common, ac_fibs); 371 ip->AdapterFibsVirtualAddress = &sc->sc_common->ac_fibs[0]; 372 ip->AdapterFibsSize = AAC_ADAPTER_FIBS * sizeof(struct aac_fib); 373 ip->AdapterFibAlign = sizeof(struct aac_fib); 374 375 ip->PrintfBufferAddress = 376 sc->sc_common_busaddr + offsetof(struct aac_common, ac_printf); 377 ip->PrintfBufferSize = AAC_PRINTF_BUFSIZE; 378 379 ip->HostPhysMemPages = 0; /* not used? */ 380 ip->HostElapsedSeconds = 0; /* reset later if invalid */ 381 382 /* 383 * Initialise FIB queues. Note that it appears that the 384 * layout of the indexes and the segmentation of the entries 385 * is mandated by the adapter, which is only told about the 386 * base of the queue index fields. 387 * 388 * The initial values of the indices are assumed to inform the 389 * adapter of the sizes of the respective queues. 390 * 391 * The Linux driver uses a much more complex scheme whereby 392 * several header * records are kept for each queue. We use a 393 * couple of generic list manipulation functions which 394 * 'know' the size of each list by virtue of a table. 395 */ 396 qaddr = &sc->sc_common->ac_qbuf[0] + AAC_QUEUE_ALIGN; 397 qaddr -= (u_int32_t)qaddr % AAC_QUEUE_ALIGN; /* XXX not portable */ 398 sc->sc_queues = (struct aac_queue_table *)qaddr; 399 ip->CommHeaderAddress = sc->sc_common_busaddr + 400 ((char *)sc->sc_queues - (char *)sc->sc_common); 401 bzero(sc->sc_queues, sizeof(struct aac_queue_table)); 402 403 sc->sc_queues->qt_qindex[AAC_HOST_NORM_CMD_QUEUE][AAC_PRODUCER_INDEX] = 404 AAC_HOST_NORM_CMD_ENTRIES; 405 sc->sc_queues->qt_qindex[AAC_HOST_NORM_CMD_QUEUE][AAC_CONSUMER_INDEX] = 406 AAC_HOST_NORM_CMD_ENTRIES; 407 sc->sc_queues->qt_qindex[AAC_HOST_HIGH_CMD_QUEUE][AAC_PRODUCER_INDEX] = 408 AAC_HOST_HIGH_CMD_ENTRIES; 409 sc->sc_queues->qt_qindex[AAC_HOST_HIGH_CMD_QUEUE][AAC_CONSUMER_INDEX] = 410 AAC_HOST_HIGH_CMD_ENTRIES; 411 sc->sc_queues->qt_qindex[AAC_ADAP_NORM_CMD_QUEUE][AAC_PRODUCER_INDEX] = 412 AAC_ADAP_NORM_CMD_ENTRIES; 413 sc->sc_queues->qt_qindex[AAC_ADAP_NORM_CMD_QUEUE][AAC_CONSUMER_INDEX] = 414 AAC_ADAP_NORM_CMD_ENTRIES; 415 sc->sc_queues->qt_qindex[AAC_ADAP_HIGH_CMD_QUEUE][AAC_PRODUCER_INDEX] = 416 AAC_ADAP_HIGH_CMD_ENTRIES; 417 sc->sc_queues->qt_qindex[AAC_ADAP_HIGH_CMD_QUEUE][AAC_CONSUMER_INDEX] = 418 AAC_ADAP_HIGH_CMD_ENTRIES; 419 sc->sc_queues-> 420 qt_qindex[AAC_HOST_NORM_RESP_QUEUE][AAC_PRODUCER_INDEX] = 421 AAC_HOST_NORM_RESP_ENTRIES; 422 sc->sc_queues-> 423 qt_qindex[AAC_HOST_NORM_RESP_QUEUE][AAC_CONSUMER_INDEX] = 424 AAC_HOST_NORM_RESP_ENTRIES; 425 sc->sc_queues-> 426 qt_qindex[AAC_HOST_HIGH_RESP_QUEUE][AAC_PRODUCER_INDEX] = 427 AAC_HOST_HIGH_RESP_ENTRIES; 428 sc->sc_queues-> 429 qt_qindex[AAC_HOST_HIGH_RESP_QUEUE][AAC_CONSUMER_INDEX] = 430 AAC_HOST_HIGH_RESP_ENTRIES; 431 sc->sc_queues-> 432 qt_qindex[AAC_ADAP_NORM_RESP_QUEUE][AAC_PRODUCER_INDEX] = 433 AAC_ADAP_NORM_RESP_ENTRIES; 434 sc->sc_queues-> 435 qt_qindex[AAC_ADAP_NORM_RESP_QUEUE][AAC_CONSUMER_INDEX] = 436 AAC_ADAP_NORM_RESP_ENTRIES; 437 sc->sc_queues-> 438 qt_qindex[AAC_ADAP_HIGH_RESP_QUEUE][AAC_PRODUCER_INDEX] = 439 AAC_ADAP_HIGH_RESP_ENTRIES; 440 sc->sc_queues-> 441 qt_qindex[AAC_ADAP_HIGH_RESP_QUEUE][AAC_CONSUMER_INDEX] = 442 AAC_ADAP_HIGH_RESP_ENTRIES; 443 sc->sc_qentries[AAC_HOST_NORM_CMD_QUEUE] = 444 &sc->sc_queues->qt_HostNormCmdQueue[0]; 445 sc->sc_qentries[AAC_HOST_HIGH_CMD_QUEUE] = 446 &sc->sc_queues->qt_HostHighCmdQueue[0]; 447 sc->sc_qentries[AAC_ADAP_NORM_CMD_QUEUE] = 448 &sc->sc_queues->qt_AdapNormCmdQueue[0]; 449 sc->sc_qentries[AAC_ADAP_HIGH_CMD_QUEUE] = 450 &sc->sc_queues->qt_AdapHighCmdQueue[0]; 451 sc->sc_qentries[AAC_HOST_NORM_RESP_QUEUE] = 452 &sc->sc_queues->qt_HostNormRespQueue[0]; 453 sc->sc_qentries[AAC_HOST_HIGH_RESP_QUEUE] = 454 &sc->sc_queues->qt_HostHighRespQueue[0]; 455 sc->sc_qentries[AAC_ADAP_NORM_RESP_QUEUE] = 456 &sc->sc_queues->qt_AdapNormRespQueue[0]; 457 sc->sc_qentries[AAC_ADAP_HIGH_RESP_QUEUE] = 458 &sc->sc_queues->qt_AdapHighRespQueue[0]; 459 460 /* 461 * Do controller-type-specific initialisation 462 */ 463 switch (sc->sc_hwif) { 464 case AAC_HWIF_I960RX: 465 AAC_SETREG4(sc, AAC_RX_ODBR, ~0); 466 break; 467 } 468 469 /* 470 * Give the init structure to the controller. 471 */ 472 if (aac_sync_command(sc, AAC_MONKER_INITSTRUCT, 473 sc->sc_common_busaddr + offsetof(struct aac_common, ac_init), 0, 0, 474 0, NULL)) { 475 printf("%s: error establishing init structure\n", 476 sc->sc_dev.dv_xname); 477 error = EIO; 478 goto bail_out; 479 } 480 481 aac_startup(sc); 482 483 return (0); 484 485 bail_out: 486 if (state > 1) 487 bus_dmamem_unmap(sc->sc_dmat, (caddr_t)sc->sc_common, 488 sizeof *sc->sc_common); 489 if (state > 0) 490 bus_dmamem_free(sc->sc_dmat, &seg, 1); 491 return (error); 492 } 493 494 /* 495 * Probe for containers, create disks. 496 */ 497 void 498 aac_startup (sc) 499 struct aac_softc *sc; 500 { 501 struct aac_mntinfo mi; 502 struct aac_mntinforesponse mir; 503 u_int16_t rsize; 504 int i, drv_cyls, drv_hds, drv_secs; 505 506 /* loop over possible containers */ 507 mi.Command = VM_NameServe; 508 mi.MntType = FT_FILESYS; 509 for (i = 0; i < AAC_MAX_CONTAINERS; i++) { 510 /* request information on this container */ 511 mi.MntCount = i; 512 if (aac_sync_fib(sc, ContainerCommand, 0, &mi, sizeof mi, &mir, 513 &rsize)) { 514 printf("%s: error probing container %d", 515 sc->sc_dev.dv_xname, i); 516 continue; 517 } 518 /* check response size */ 519 if (rsize != sizeof mir) { 520 printf("%s: container info response wrong size " 521 "(%d should be %d)", 522 sc->sc_dev.dv_xname, rsize, sizeof mir); 523 continue; 524 } 525 526 /* 527 * Check container volume type for validity. Note 528 * that many of the possible types * may never show 529 * up. 530 */ 531 if (mir.Status == ST_OK && 532 mir.MntTable[0].VolType != CT_NONE) { 533 AAC_DPRINTF(AAC_D_MISC, 534 ("%d: id %x name '%.16s' size %u type %d", i, 535 mir.MntTable[0].ObjectId, 536 mir.MntTable[0].FileSystemName, 537 mir.MntTable[0].Capacity, 538 mir.MntTable[0].VolType)); 539 540 sc->sc_hdr[i].hd_present = 1; 541 sc->sc_hdr[i].hd_size = mir.MntTable[0].Capacity; 542 543 /* 544 * Evaluate mapping (sectors per head, heads per cyl) 545 */ 546 sc->sc_hdr[i].hd_size &= ~AAC_SECS32; 547 aac_eval_mapping(sc->sc_hdr[i].hd_size, &drv_cyls, 548 &drv_hds, &drv_secs); 549 sc->sc_hdr[i].hd_heads = drv_hds; 550 sc->sc_hdr[i].hd_secs = drv_secs; 551 /* Round the size */ 552 sc->sc_hdr[i].hd_size = drv_cyls * drv_hds * drv_secs; 553 554 sc->sc_hdr[i].hd_devtype = mir.MntTable[0].VolType; 555 556 /* XXX Save the name too for use in IDENTIFY later */ 557 } 558 } 559 560 /* mark the controller up */ 561 sc->sc_state &= ~AAC_STATE_SUSPEND; 562 563 /* enable interrupts now */ 564 AAC_UNMASK_INTERRUPTS(sc); 565 } 566 567 void 568 aac_eval_mapping(size, cyls, heads, secs) 569 u_int32_t size; 570 int *cyls, *heads, *secs; 571 { 572 *cyls = size / AAC_HEADS / AAC_SECS; 573 if (*cyls < AAC_MAXCYLS) { 574 *heads = AAC_HEADS; 575 *secs = AAC_SECS; 576 } else { 577 /* Too high for 64 * 32 */ 578 *cyls = size / AAC_MEDHEADS / AAC_MEDSECS; 579 if (*cyls < AAC_MAXCYLS) { 580 *heads = AAC_MEDHEADS; 581 *secs = AAC_MEDSECS; 582 } else { 583 /* Too high for 127 * 63 */ 584 *cyls = size / AAC_BIGHEADS / AAC_BIGSECS; 585 *heads = AAC_BIGHEADS; 586 *secs = AAC_BIGSECS; 587 } 588 } 589 } 590 591 int 592 aac_raw_scsi_cmd(xs) 593 struct scsi_xfer *xs; 594 { 595 AAC_DPRINTF(AAC_D_CMD, ("aac_raw_scsi_cmd ")); 596 597 /* XXX Not yet implemented */ 598 xs->error = XS_DRIVER_STUFFUP; 599 return (COMPLETE); 600 } 601 602 int 603 aac_scsi_cmd(xs) 604 struct scsi_xfer *xs; 605 { 606 struct scsi_link *link = xs->sc_link; 607 struct aac_softc *sc = link->adapter_softc; 608 u_int8_t target = link->target; 609 struct aac_ccb *ccb; 610 u_int32_t blockno, blockcnt; 611 struct scsi_rw *rw; 612 struct scsi_rw_big *rwb; 613 aac_lock_t lock; 614 int retval = SUCCESSFULLY_QUEUED; 615 616 AAC_DPRINTF(AAC_D_CMD, ("aac_scsi_cmd ")); 617 618 xs->error = XS_NOERROR; 619 620 if (target >= AAC_MAX_CONTAINERS || !sc->sc_hdr[target].hd_present || 621 link->lun != 0) { 622 /* 623 * XXX Should be XS_SENSE but that would require setting up a 624 * faked sense too. 625 */ 626 xs->error = XS_DRIVER_STUFFUP; 627 xs->flags |= ITSDONE; 628 scsi_done(xs); 629 return (COMPLETE); 630 } 631 632 lock = AAC_LOCK(sc); 633 634 /* Don't double enqueue if we came from aac_chain. */ 635 if (xs != LIST_FIRST(&sc->sc_queue)) 636 aac_enqueue(sc, xs, 0); 637 638 while ((xs = aac_dequeue(sc))) { 639 xs->error = XS_NOERROR; 640 ccb = NULL; 641 link = xs->sc_link; 642 target = link->target; 643 644 switch (xs->cmd->opcode) { 645 case TEST_UNIT_READY: 646 case REQUEST_SENSE: 647 case INQUIRY: 648 case MODE_SENSE: 649 case START_STOP: 650 case READ_CAPACITY: 651 #if 0 652 case VERIFY: 653 #endif 654 if (!aac_internal_cache_cmd(xs)) { 655 AAC_UNLOCK(sc, lock); 656 return (TRY_AGAIN_LATER); 657 } 658 xs->flags |= ITSDONE; 659 scsi_done(xs); 660 goto ready; 661 662 case PREVENT_ALLOW: 663 AAC_DPRINTF(AAC_D_CMD, ("PREVENT/ALLOW ")); 664 /* XXX Not yet implemented */ 665 xs->error = XS_NOERROR; 666 xs->flags |= ITSDONE; 667 scsi_done(xs); 668 goto ready; 669 670 case SYNCHRONIZE_CACHE: 671 AAC_DPRINTF(AAC_D_CMD, ("SYNCHRONIZE_CACHE ")); 672 /* XXX Not yet implemented */ 673 xs->error = XS_NOERROR; 674 xs->flags |= ITSDONE; 675 scsi_done(xs); 676 goto ready; 677 678 default: 679 AAC_DPRINTF(AAC_D_CMD, 680 ("unknown opc %d ", xs->cmd->opcode)); 681 /* XXX Not yet implemented */ 682 xs->error = XS_DRIVER_STUFFUP; 683 xs->flags |= ITSDONE; 684 scsi_done(xs); 685 goto ready; 686 687 case READ_COMMAND: 688 case READ_BIG: 689 case WRITE_COMMAND: 690 case WRITE_BIG: 691 AAC_DPRINTF(AAC_D_CMD, 692 ("rw opc %d ", xs->cmd->opcode)); 693 694 if (xs->cmd->opcode != SYNCHRONIZE_CACHE) { 695 /* A read or write operation. */ 696 if (xs->cmdlen == 6) { 697 rw = (struct scsi_rw *)xs->cmd; 698 blockno = _3btol(rw->addr) & 699 (SRW_TOPADDR << 16 | 0xffff); 700 blockcnt = 701 rw->length ? rw->length : 0x100; 702 } else { 703 rwb = (struct scsi_rw_big *)xs->cmd; 704 blockno = _4btol(rwb->addr); 705 blockcnt = _2btol(rwb->length); 706 } 707 if (blockno >= sc->sc_hdr[target].hd_size || 708 blockno + blockcnt > 709 sc->sc_hdr[target].hd_size) { 710 printf( 711 "%s: out of bounds %u-%u >= %u\n", 712 sc->sc_dev.dv_xname, blockno, 713 blockcnt, 714 sc->sc_hdr[target].hd_size); 715 /* 716 * XXX Should be XS_SENSE but that 717 * would require setting up a faked 718 * sense too. 719 */ 720 xs->error = XS_DRIVER_STUFFUP; 721 xs->flags |= ITSDONE; 722 scsi_done(xs); 723 goto ready; 724 } 725 } 726 727 ccb = aac_get_ccb(sc, xs->flags); 728 729 /* 730 * Are we out of commands, something is wrong. 731 * 732 */ 733 if (ccb == NULL) { 734 printf("%s: no ccb in aac_scsi_cmd", 735 sc->sc_dev.dv_xname); 736 xs->error = XS_DRIVER_STUFFUP; 737 xs->flags |= ITSDONE; 738 scsi_done(xs); 739 goto ready; 740 } 741 742 ccb->ac_blockno = blockno; 743 ccb->ac_blockcnt = blockcnt; 744 ccb->ac_xs = xs; 745 ccb->ac_timeout = xs->timeout; 746 747 if (xs->cmd->opcode != SYNCHRONIZE_CACHE && 748 aac_map_command(ccb)) { 749 aac_free_ccb(sc, ccb); 750 xs->error = XS_DRIVER_STUFFUP; 751 xs->flags |= ITSDONE; 752 scsi_done(xs); 753 goto ready; 754 } 755 756 aac_enqueue_ccb(sc, ccb); 757 /* XXX what if enqueue did not start a transfer? */ 758 if (xs->flags & SCSI_POLL) { 759 #if 0 760 if (!aac_wait(sc, ccb, ccb->ac_timeout)) { 761 AAC_UNLOCK(sc, lock); 762 printf("%s: command timed out\n", 763 sc->sc_dev.dv_xname); 764 xs->error = XS_TIMEOUT; 765 return (TRY_AGAIN_LATER); 766 } 767 xs->flags |= ITSDONE; 768 scsi_done(xs); 769 #endif 770 } 771 } 772 773 ready: 774 /* 775 * Don't process the queue if we are polling. 776 */ 777 if (xs->flags & SCSI_POLL) { 778 retval = COMPLETE; 779 break; 780 } 781 } 782 783 AAC_UNLOCK(sc, lock); 784 return (retval); 785 } 786 787 void 788 aac_copy_internal_data(xs, data, size) 789 struct scsi_xfer *xs; 790 u_int8_t *data; 791 size_t size; 792 { 793 size_t copy_cnt; 794 795 AAC_DPRINTF(AAC_D_MISC, ("aac_copy_internal_data ")); 796 797 if (!xs->datalen) 798 printf("uio move not yet supported\n"); 799 else { 800 copy_cnt = MIN(size, xs->datalen); 801 bcopy(data, xs->data, copy_cnt); 802 } 803 } 804 805 /* Emulated SCSI operation on cache device */ 806 int 807 aac_internal_cache_cmd(xs) 808 struct scsi_xfer *xs; 809 { 810 struct scsi_link *link = xs->sc_link; 811 struct aac_softc *sc = link->adapter_softc; 812 struct scsi_inquiry_data inq; 813 struct scsi_sense_data sd; 814 struct { 815 struct scsi_mode_header hd; 816 struct scsi_blk_desc bd; 817 union scsi_disk_pages dp; 818 } mpd; 819 struct scsi_read_cap_data rcd; 820 u_int8_t target = link->target; 821 822 AAC_DPRINTF(AAC_D_CMD, ("aac_internal_cache_cmd ")); 823 824 switch (xs->cmd->opcode) { 825 case TEST_UNIT_READY: 826 case START_STOP: 827 #if 0 828 case VERIFY: 829 #endif 830 AAC_DPRINTF(AAC_D_CMD, ("opc %d tgt %d ", xs->cmd->opcode, 831 target)); 832 break; 833 834 case REQUEST_SENSE: 835 AAC_DPRINTF(AAC_D_CMD, ("REQUEST SENSE tgt %d ", target)); 836 bzero(&sd, sizeof sd); 837 sd.error_code = 0x70; 838 sd.segment = 0; 839 sd.flags = SKEY_NO_SENSE; 840 aac_enc32(sd.info, 0); 841 sd.extra_len = 0; 842 aac_copy_internal_data(xs, (u_int8_t *)&sd, sizeof sd); 843 break; 844 845 case INQUIRY: 846 AAC_DPRINTF(AAC_D_CMD, ("INQUIRY tgt %d devtype %x ", target, 847 sc->sc_hdr[target].hd_devtype)); 848 bzero(&inq, sizeof inq); 849 /* XXX How do we detect removable/CD-ROM devices? */ 850 inq.device = T_DIRECT; 851 inq.dev_qual2 = 0; 852 inq.version = 2; 853 inq.response_format = 2; 854 inq.additional_length = 32; 855 strcpy(inq.vendor, "Adaptec"); 856 sprintf(inq.product, "Container #%02d", target); 857 strcpy(inq.revision, " "); 858 aac_copy_internal_data(xs, (u_int8_t *)&inq, sizeof inq); 859 break; 860 861 case MODE_SENSE: 862 AAC_DPRINTF(AAC_D_CMD, ("MODE SENSE tgt %d ", target)); 863 864 bzero(&mpd, sizeof mpd); 865 switch (((struct scsi_mode_sense *)xs->cmd)->page) { 866 case 4: 867 /* scsi_disk.h says this should be 0x16 */ 868 mpd.dp.rigid_geometry.pg_length = 0x16; 869 mpd.hd.data_length = sizeof mpd.hd + sizeof mpd.bd + 870 mpd.dp.rigid_geometry.pg_length; 871 mpd.hd.blk_desc_len = sizeof mpd.bd; 872 873 /* XXX */ 874 mpd.hd.dev_spec = 0; 875 _lto3b(AAC_BLOCK_SIZE, mpd.bd.blklen); 876 mpd.dp.rigid_geometry.pg_code = 4; 877 _lto3b(sc->sc_hdr[target].hd_size / 878 sc->sc_hdr[target].hd_heads / 879 sc->sc_hdr[target].hd_secs, 880 mpd.dp.rigid_geometry.ncyl); 881 mpd.dp.rigid_geometry.nheads = 882 sc->sc_hdr[target].hd_heads; 883 aac_copy_internal_data(xs, (u_int8_t *)&mpd, 884 sizeof mpd); 885 break; 886 887 default: 888 printf("%s: mode sense page %d not simulated\n", 889 sc->sc_dev.dv_xname, 890 ((struct scsi_mode_sense *)xs->cmd)->page); 891 xs->error = XS_DRIVER_STUFFUP; 892 return (0); 893 } 894 break; 895 896 case READ_CAPACITY: 897 AAC_DPRINTF(AAC_D_CMD, ("READ CAPACITY tgt %d ", target)); 898 bzero(&rcd, sizeof rcd); 899 _lto4b(sc->sc_hdr[target].hd_size - 1, rcd.addr); 900 _lto4b(AAC_BLOCK_SIZE, rcd.length); 901 aac_copy_internal_data(xs, (u_int8_t *)&rcd, sizeof rcd); 902 break; 903 904 default: 905 printf("aac_internal_cache_cmd got bad opcode: %d\n", 906 xs->cmd->opcode); 907 xs->error = XS_DRIVER_STUFFUP; 908 return (0); 909 } 910 911 xs->error = XS_NOERROR; 912 return (1); 913 } 914 915 /* 916 * Take an interrupt. 917 */ 918 int 919 aac_intr(arg) 920 void *arg; 921 { 922 struct aac_softc *sc = arg; 923 u_int16_t reason; 924 int claimed = 0; 925 926 AAC_DPRINTF(AAC_D_INTR, ("aac_intr(%p) ", sc)); 927 928 reason = AAC_GET_ISTATUS(sc); 929 AAC_DPRINTF(AAC_D_INTR, ("istatus 0x%04x ", reason)); 930 931 /* controller wants to talk to the log? XXX should we defer this? */ 932 if (reason & AAC_DB_PRINTF) { 933 if (sc->sc_common->ac_printf[0]) { 934 printf("%s: ** %.*s", sc->sc_dev.dv_xname, 935 AAC_PRINTF_BUFSIZE, sc->sc_common->ac_printf); 936 sc->sc_common->ac_printf[0] = 0; 937 } 938 AAC_CLEAR_ISTATUS(sc, AAC_DB_PRINTF); 939 AAC_QNOTIFY(sc, AAC_DB_PRINTF); 940 claimed = 1; 941 } 942 943 /* Controller has a message for us? */ 944 if (reason & AAC_DB_COMMAND_READY) { 945 aac_host_command(sc); 946 AAC_CLEAR_ISTATUS(sc, AAC_DB_COMMAND_READY); 947 claimed = 1; 948 } 949 950 /* Controller has a response for us? */ 951 if (reason & AAC_DB_RESPONSE_READY) { 952 aac_host_response(sc); 953 AAC_CLEAR_ISTATUS(sc, AAC_DB_RESPONSE_READY); 954 claimed = 1; 955 } 956 957 /* 958 * Spurious interrupts that we don't use - reset the mask and clear 959 * the interrupts. 960 */ 961 if (reason & (AAC_DB_SYNC_COMMAND | AAC_DB_COMMAND_NOT_FULL | 962 AAC_DB_RESPONSE_NOT_FULL)) { 963 AAC_UNMASK_INTERRUPTS(sc); 964 AAC_CLEAR_ISTATUS(sc, AAC_DB_SYNC_COMMAND | 965 AAC_DB_COMMAND_NOT_FULL | AAC_DB_RESPONSE_NOT_FULL); 966 claimed = 1; 967 } 968 969 return (claimed); 970 } 971 972 /* 973 * Handle notification of one or more FIBs coming from the controller. 974 */ 975 void 976 aac_host_command(struct aac_softc *sc) 977 { 978 struct aac_fib *fib; 979 u_int32_t fib_size; 980 981 for (;;) { 982 if (aac_dequeue_fib(sc, AAC_HOST_NORM_CMD_QUEUE, &fib_size, 983 &fib)) 984 break; /* nothing to do */ 985 986 switch(fib->Header.Command) { 987 case AifRequest: 988 #if 0 989 aac_handle_aif(sc, 990 (struct aac_aif_command *)&fib->data[0]); 991 #endif 992 993 break; 994 default: 995 printf("%s: unknown command from controller\n", 996 sc->sc_dev.dv_xname); 997 AAC_PRINT_FIB(sc, fib); 998 break; 999 } 1000 1001 /* XXX reply to FIBs requesting responses ?? */ 1002 /* XXX how do we return these FIBs to the controller? */ 1003 } 1004 } 1005 1006 /* 1007 * Handle notification of one or more FIBs completed by the controller 1008 */ 1009 void 1010 aac_host_response(struct aac_softc *sc) 1011 { 1012 struct aac_ccb *ccb; 1013 struct aac_fib *fib; 1014 u_int32_t fib_size; 1015 1016 for (;;) { 1017 /* look for completed FIBs on our queue */ 1018 if (aac_dequeue_fib(sc, AAC_HOST_NORM_RESP_QUEUE, &fib_size, 1019 &fib)) 1020 break; /* nothing to do */ 1021 1022 /* get the command, unmap and queue for later processing */ 1023 ccb = (struct aac_ccb *)fib->Header.SenderData; 1024 if (ccb == NULL) { 1025 AAC_PRINT_FIB(sc, fib); 1026 } else { 1027 timeout_del(&ccb->ac_xs->stimeout); 1028 aac_unmap_command(ccb); /* XXX defer? */ 1029 aac_enqueue_completed(ccb); 1030 } 1031 } 1032 1033 /* handle completion processing */ 1034 aac_complete(sc, 0); 1035 } 1036 1037 /* 1038 * Process completed commands. 1039 */ 1040 void 1041 aac_complete(void *context, int pending) 1042 { 1043 struct aac_softc *sc = (struct aac_softc *)context; 1044 struct aac_ccb *ccb; 1045 1046 /* pull completed commands off the queue */ 1047 for (;;) { 1048 ccb = aac_dequeue_completed(sc); 1049 if (ccb == NULL) 1050 return; 1051 ccb->ac_flags |= AAC_ACF_COMPLETED; 1052 1053 #if 0 1054 /* is there a completion handler? */ 1055 if (ccb->ac_complete != NULL) { 1056 ccb->ac_complete(ccb); 1057 } else { 1058 /* assume that someone is sleeping on this command */ 1059 wakeup(ccb); 1060 } 1061 #else 1062 aac_bio_complete(ccb); 1063 #endif 1064 } 1065 } 1066 1067 /* 1068 * Handle a bio-instigated command that has been completed. 1069 */ 1070 void 1071 aac_bio_complete(struct aac_ccb *ccb) 1072 { 1073 struct scsi_xfer *xs = ccb->ac_xs; 1074 struct aac_softc *sc = xs->sc_link->adapter_softc; 1075 struct buf *bp = xs->bp; 1076 struct aac_blockread_response *brr; 1077 struct aac_blockwrite_response *bwr; 1078 AAC_FSAStatus status; 1079 1080 /* fetch relevant status and then release the command */ 1081 if (bp->b_flags & B_READ) { 1082 brr = (struct aac_blockread_response *)&ccb->ac_fib->data[0]; 1083 status = brr->Status; 1084 } else { 1085 bwr = (struct aac_blockwrite_response *)&ccb->ac_fib->data[0]; 1086 status = bwr->Status; 1087 } 1088 aac_free_ccb(sc, ccb); 1089 1090 /* fix up the bio based on status */ 1091 if (status == ST_OK) { 1092 bp->b_resid = 0; 1093 } else { 1094 bp->b_error = EIO; 1095 bp->b_flags |= B_ERROR; 1096 1097 /* XXX be more verbose? */ 1098 printf("%s: I/O error %d (%s)\n", status, 1099 AAC_COMMAND_STATUS(status)); 1100 } 1101 scsi_done(xs); 1102 } 1103 1104 /* 1105 * Send a synchronous command to the controller and wait for a result. 1106 */ 1107 int 1108 aac_sync_command(sc, command, arg0, arg1, arg2, arg3, sp) 1109 struct aac_softc *sc; 1110 u_int32_t command; 1111 u_int32_t arg0; 1112 u_int32_t arg1; 1113 u_int32_t arg2; 1114 u_int32_t arg3; 1115 u_int32_t *sp; 1116 { 1117 int i; 1118 u_int32_t status; 1119 aac_lock_t lock = AAC_LOCK(sc); 1120 1121 /* populate the mailbox */ 1122 AAC_SET_MAILBOX(sc, command, arg0, arg1, arg2, arg3); 1123 1124 /* ensure the sync command doorbell flag is cleared */ 1125 AAC_CLEAR_ISTATUS(sc, AAC_DB_SYNC_COMMAND); 1126 1127 /* then set it to signal the adapter */ 1128 AAC_QNOTIFY(sc, AAC_DB_SYNC_COMMAND); 1129 DELAY(AAC_SYNC_DELAY); 1130 1131 /* spin waiting for the command to complete */ 1132 for (i = 0; i < AAC_IMMEDIATE_TIMEOUT * 1000; i++) { 1133 if (AAC_GET_ISTATUS(sc) & AAC_DB_SYNC_COMMAND); 1134 break; 1135 DELAY(1000); 1136 } 1137 if (i == AAC_IMMEDIATE_TIMEOUT * 1000) { 1138 AAC_UNLOCK(sc, lock); 1139 return (EIO); 1140 } 1141 1142 /* clear the completion flag */ 1143 AAC_CLEAR_ISTATUS(sc, AAC_DB_SYNC_COMMAND); 1144 1145 /* get the command status */ 1146 status = AAC_GET_MAILBOXSTATUS(sc); 1147 AAC_UNLOCK(sc, lock); 1148 if (sp != NULL) 1149 *sp = status; 1150 return (0); /* check command return status? */ 1151 } 1152 1153 /* 1154 * Send a synchronous FIB to the controller and wait for a result. 1155 */ 1156 int 1157 aac_sync_fib(sc, command, xferstate, data, datasize, result, resultsize) 1158 struct aac_softc *sc; 1159 u_int32_t command; 1160 u_int32_t xferstate; 1161 void *data; 1162 u_int16_t datasize; 1163 void *result; 1164 u_int16_t *resultsize; 1165 { 1166 struct aac_fib *fib = &sc->sc_common->ac_sync_fib; 1167 1168 if (datasize > AAC_FIB_DATASIZE) 1169 return (EINVAL); 1170 1171 /* 1172 * Set up the sync FIB 1173 */ 1174 fib->Header.XferState = AAC_FIBSTATE_HOSTOWNED | 1175 AAC_FIBSTATE_INITIALISED | AAC_FIBSTATE_EMPTY; 1176 fib->Header.XferState |= xferstate; 1177 fib->Header.Command = command; 1178 fib->Header.StructType = AAC_FIBTYPE_TFIB; 1179 fib->Header.Size = sizeof fib + datasize; 1180 fib->Header.SenderSize = sizeof *fib; 1181 fib->Header.SenderFibAddress = (u_int32_t)fib; 1182 fib->Header.ReceiverFibAddress = 1183 sc->sc_common_busaddr + offsetof(struct aac_common, ac_sync_fib); 1184 1185 /* 1186 * Copy in data. 1187 */ 1188 if (data != NULL) { 1189 bcopy(data, fib->data, datasize); 1190 fib->Header.XferState |= 1191 AAC_FIBSTATE_FROMHOST | AAC_FIBSTATE_NORM; 1192 } 1193 1194 /* 1195 * Give the FIB to the controller, wait for a response. 1196 */ 1197 if (aac_sync_command(sc, AAC_MONKER_SYNCFIB, 1198 fib->Header.ReceiverFibAddress, 0, 0, 0, NULL)) { 1199 return (EIO); 1200 } 1201 1202 /* 1203 * Copy out the result 1204 */ 1205 if (result != NULL) { 1206 *resultsize = fib->Header.Size - sizeof fib->Header; 1207 bcopy(fib->data, result, *resultsize); 1208 } 1209 return (0); 1210 } 1211 1212 void 1213 aacminphys(bp) 1214 struct buf *bp; 1215 { 1216 #if 0 1217 u_int8_t *buf = bp->b_data; 1218 paddr_t pa; 1219 long off; 1220 #endif 1221 1222 AAC_DPRINTF(AAC_D_MISC, ("aacminphys(0x%x) ", bp)); 1223 1224 #if 1 1225 #if 0 /* As this is way more than MAXPHYS it's really not necessary. */ 1226 if (bp->b_bcount > ((AAC_MAXOFFSETS - 1) * PAGE_SIZE)) 1227 bp->b_bcount = ((AAC_MAXOFFSETS - 1) * PAGE_SIZE); 1228 #endif 1229 #else 1230 for (off = PAGE_SIZE, pa = vtophys(buf); off < bp->b_bcount; 1231 off += PAGE_SIZE) 1232 if (pa + off != vtophys(buf + off)) { 1233 bp->b_bcount = off; 1234 break; 1235 } 1236 #endif 1237 minphys(bp); 1238 } 1239 1240 /* 1241 * Read the current firmware status word. 1242 */ 1243 int 1244 aac_sa_get_fwstatus(sc) 1245 struct aac_softc *sc; 1246 { 1247 return (AAC_GETREG4(sc, AAC_SA_FWSTATUS)); 1248 } 1249 1250 int 1251 aac_rx_get_fwstatus(sc) 1252 struct aac_softc *sc; 1253 { 1254 return (AAC_GETREG4(sc, AAC_RX_FWSTATUS)); 1255 } 1256 1257 /* 1258 * Notify the controller of a change in a given queue 1259 */ 1260 1261 void 1262 aac_sa_qnotify(sc, qbit) 1263 struct aac_softc *sc; 1264 int qbit; 1265 { 1266 AAC_SETREG2(sc, AAC_SA_DOORBELL1_SET, qbit); 1267 } 1268 1269 void 1270 aac_rx_qnotify(sc, qbit) 1271 struct aac_softc *sc; 1272 int qbit; 1273 { 1274 AAC_SETREG4(sc, AAC_RX_IDBR, qbit); 1275 } 1276 1277 /* 1278 * Get the interrupt reason bits 1279 */ 1280 int 1281 aac_sa_get_istatus(sc) 1282 struct aac_softc *sc; 1283 { 1284 return (AAC_GETREG2(sc, AAC_SA_DOORBELL0)); 1285 } 1286 1287 int 1288 aac_rx_get_istatus(sc) 1289 struct aac_softc *sc; 1290 { 1291 return (AAC_GETREG4(sc, AAC_RX_ODBR)); 1292 } 1293 1294 /* 1295 * Clear some interrupt reason bits 1296 */ 1297 void 1298 aac_sa_clear_istatus(sc, mask) 1299 struct aac_softc *sc; 1300 int mask; 1301 { 1302 AAC_SETREG2(sc, AAC_SA_DOORBELL0_CLEAR, mask); 1303 } 1304 1305 void 1306 aac_rx_clear_istatus(sc, mask) 1307 struct aac_softc *sc; 1308 int mask; 1309 { 1310 AAC_SETREG4(sc, AAC_RX_ODBR, mask); 1311 } 1312 1313 /* 1314 * Populate the mailbox and set the command word 1315 */ 1316 void 1317 aac_sa_set_mailbox(sc, command, arg0, arg1, arg2, arg3) 1318 struct aac_softc *sc; 1319 u_int32_t command; 1320 u_int32_t arg0; 1321 u_int32_t arg1; 1322 u_int32_t arg2; 1323 u_int32_t arg3; 1324 { 1325 AAC_SETREG4(sc, AAC_SA_MAILBOX, command); 1326 AAC_SETREG4(sc, AAC_SA_MAILBOX + 4, arg0); 1327 AAC_SETREG4(sc, AAC_SA_MAILBOX + 8, arg1); 1328 AAC_SETREG4(sc, AAC_SA_MAILBOX + 12, arg2); 1329 AAC_SETREG4(sc, AAC_SA_MAILBOX + 16, arg3); 1330 } 1331 1332 void 1333 aac_rx_set_mailbox(sc, command, arg0, arg1, arg2, arg3) 1334 struct aac_softc *sc; 1335 u_int32_t command; 1336 u_int32_t arg0; 1337 u_int32_t arg1; 1338 u_int32_t arg2; 1339 u_int32_t arg3; 1340 { 1341 AAC_SETREG4(sc, AAC_RX_MAILBOX, command); 1342 AAC_SETREG4(sc, AAC_RX_MAILBOX + 4, arg0); 1343 AAC_SETREG4(sc, AAC_RX_MAILBOX + 8, arg1); 1344 AAC_SETREG4(sc, AAC_RX_MAILBOX + 12, arg2); 1345 AAC_SETREG4(sc, AAC_RX_MAILBOX + 16, arg3); 1346 } 1347 1348 /* 1349 * Fetch the immediate command status word 1350 */ 1351 int 1352 aac_sa_get_mailboxstatus(sc) 1353 struct aac_softc *sc; 1354 { 1355 return (AAC_GETREG4(sc, AAC_SA_MAILBOX)); 1356 } 1357 1358 int 1359 aac_rx_get_mailboxstatus(sc) 1360 struct aac_softc *sc; 1361 { 1362 return (AAC_GETREG4(sc, AAC_RX_MAILBOX)); 1363 } 1364 1365 /* 1366 * Set/clear interrupt masks 1367 */ 1368 void 1369 aac_sa_set_interrupts(sc, enable) 1370 struct aac_softc *sc; 1371 int enable; 1372 { 1373 if (enable) 1374 AAC_SETREG2((sc), AAC_SA_MASK0_CLEAR, AAC_DB_INTERRUPTS); 1375 else 1376 AAC_SETREG2((sc), AAC_SA_MASK0_SET, ~0); 1377 } 1378 1379 void 1380 aac_rx_set_interrupts(sc, enable) 1381 struct aac_softc *sc; 1382 int enable; 1383 { 1384 if (enable) 1385 AAC_SETREG4(sc, AAC_RX_OIMR, ~AAC_DB_INTERRUPTS); 1386 else 1387 AAC_SETREG4(sc, AAC_RX_OIMR, ~0); 1388 } 1389 1390 struct aac_ccb * 1391 aac_get_ccb(sc, flags) 1392 struct aac_softc *sc; 1393 int flags; 1394 { 1395 struct aac_ccb *ccb; 1396 aac_lock_t lock; 1397 1398 AAC_DPRINTF(AAC_D_QUEUE, ("aac_get_ccb(%p, 0x%x) ", sc, flags)); 1399 1400 lock = AAC_LOCK(sc); 1401 1402 for (;;) { 1403 ccb = TAILQ_FIRST(&sc->sc_free_ccb); 1404 if (ccb != NULL) 1405 break; 1406 if (flags & SCSI_NOSLEEP) 1407 goto bail_out; 1408 tsleep(&sc->sc_free_ccb, PRIBIO, "aac_ccb", 0); 1409 } 1410 1411 TAILQ_REMOVE(&sc->sc_free_ccb, ccb, ac_chain); 1412 1413 /* initialise the command/FIB */ 1414 ccb->ac_sgtable = NULL; 1415 ccb->ac_flags = 0; 1416 ccb->ac_fib->Header.XferState = AAC_FIBSTATE_EMPTY; 1417 ccb->ac_fib->Header.StructType = AAC_FIBTYPE_TFIB; 1418 ccb->ac_fib->Header.Flags = 0; 1419 ccb->ac_fib->Header.SenderSize = sizeof(struct aac_fib); 1420 1421 /* 1422 * These are duplicated in aac_start to cover the case where an 1423 * intermediate stage may have destroyed them. They're left 1424 * initialised here for debugging purposes only. 1425 */ 1426 ccb->ac_fib->Header.SenderFibAddress = (u_int32_t)ccb->ac_fib; 1427 ccb->ac_fib->Header.ReceiverFibAddress = ccb->ac_fibphys; 1428 1429 bail_out: 1430 AAC_UNLOCK(sc, lock); 1431 return (ccb); 1432 } 1433 1434 void 1435 aac_free_ccb(sc, ccb) 1436 struct aac_softc *sc; 1437 struct aac_ccb *ccb; 1438 { 1439 aac_lock_t lock; 1440 1441 AAC_DPRINTF(AAC_D_QUEUE, ("aac_free_ccb(%p, %p) ", sc, ccb)); 1442 1443 lock = AAC_LOCK(sc); 1444 1445 TAILQ_INSERT_HEAD(&sc->sc_free_ccb, ccb, ac_chain); 1446 1447 /* If the free list was empty, wake up potential waiters. */ 1448 if (TAILQ_NEXT(ccb, ac_chain) == NULL) 1449 wakeup(&sc->sc_free_ccb); 1450 1451 AAC_UNLOCK(sc, lock); 1452 } 1453 1454 void 1455 aac_enqueue_ccb(sc, ccb) 1456 struct aac_softc *sc; 1457 struct aac_ccb *ccb; 1458 { 1459 AAC_DPRINTF(AAC_D_QUEUE, ("aac_enqueue_ccb(%p, %p) ", sc, ccb)); 1460 1461 timeout_set(&ccb->ac_xs->stimeout, aac_timeout, ccb); 1462 TAILQ_INSERT_TAIL(&sc->sc_ccbq, ccb, ac_chain); 1463 aac_start_ccbs(sc); 1464 } 1465 1466 void 1467 aac_start_ccbs(sc) 1468 struct aac_softc *sc; 1469 { 1470 struct aac_ccb *ccb; 1471 struct scsi_xfer *xs; 1472 1473 AAC_DPRINTF(AAC_D_QUEUE, ("aac_start_ccbs(%p) ", sc)); 1474 1475 while ((ccb = TAILQ_FIRST(&sc->sc_ccbq)) != NULL) { 1476 1477 xs = ccb->ac_xs; 1478 if (ccb->ac_flags & AAC_ACF_WATCHDOG) 1479 timeout_del(&xs->stimeout); 1480 1481 if (aac_exec_ccb(ccb) == 0) { 1482 ccb->ac_flags |= AAC_ACF_WATCHDOG; 1483 timeout_set(&ccb->ac_xs->stimeout, aac_watchdog, ccb); 1484 timeout_add(&xs->stimeout, 1485 (AAC_WATCH_TIMEOUT * hz) / 1000); 1486 break; 1487 } 1488 TAILQ_REMOVE(&sc->sc_ccbq, ccb, ac_chain); 1489 1490 if ((xs->flags & SCSI_POLL) == 0) { 1491 timeout_set(&ccb->ac_xs->stimeout, aac_timeout, ccb); 1492 timeout_add(&xs->stimeout, 1493 (ccb->ac_timeout * hz) / 1000); 1494 } 1495 } 1496 } 1497 1498 int 1499 aac_exec_ccb(ccb) 1500 struct aac_ccb *ccb; 1501 { 1502 struct scsi_xfer *xs = ccb->ac_xs; 1503 struct scsi_link *link = xs->sc_link; 1504 u_int8_t target = link->target; 1505 int i; 1506 struct aac_fib *fib; 1507 struct aac_blockread *br; 1508 struct aac_blockwrite *bw; 1509 bus_dmamap_t xfer; 1510 1511 AAC_DPRINTF(AAC_D_CMD, ("aac_exec_ccb(%p, %p) ", xs, ccb)); 1512 1513 /* build the FIB */ 1514 fib = ccb->ac_fib; 1515 fib->Header.XferState = AAC_FIBSTATE_HOSTOWNED | 1516 AAC_FIBSTATE_INITIALISED | AAC_FIBSTATE_FROMHOST | 1517 AAC_FIBSTATE_REXPECTED | AAC_FIBSTATE_NORM; 1518 fib->Header.Command = ContainerCommand; 1519 fib->Header.Size = sizeof(struct aac_fib_header); 1520 1521 switch (xs->cmd->opcode) { 1522 case PREVENT_ALLOW: 1523 case SYNCHRONIZE_CACHE: 1524 if (xs->cmd->opcode == PREVENT_ALLOW) { 1525 /* XXX PREVENT_ALLOW support goes here */ 1526 } else { 1527 AAC_DPRINTF(AAC_D_CMD, 1528 ("SYNCHRONIZE CACHE tgt %d ", target)); 1529 } 1530 break; 1531 1532 case WRITE_COMMAND: 1533 case WRITE_BIG: 1534 bw = (struct aac_blockwrite *)&fib->data[0]; 1535 bw->Command = VM_CtBlockWrite; 1536 bw->ContainerId = target; 1537 bw->BlockNumber = ccb->ac_blockno; 1538 bw->ByteCount = ccb->ac_blockcnt * DEV_BSIZE; 1539 bw->Stable = CUNSTABLE; /* XXX what's appropriate here? */ 1540 fib->Header.Size += sizeof(struct aac_blockwrite); 1541 ccb->ac_sgtable = &bw->SgMap; 1542 break; 1543 1544 case READ_COMMAND: 1545 case READ_BIG: 1546 br = (struct aac_blockread *)&fib->data[0]; 1547 br->Command = VM_CtBlockRead; 1548 br->ContainerId = target; 1549 br->BlockNumber = ccb->ac_blockno; 1550 br->ByteCount = ccb->ac_blockcnt * DEV_BSIZE; 1551 fib->Header.Size += sizeof(struct aac_blockread); 1552 ccb->ac_sgtable = &br->SgMap; 1553 break; 1554 } 1555 1556 if (xs->cmd->opcode != PREVENT_ALLOW && 1557 xs->cmd->opcode != SYNCHRONIZE_CACHE) { 1558 xfer = ccb->ac_dmamap_xfer; 1559 ccb->ac_sgtable->SgCount = xfer->dm_nsegs; 1560 for (i = 0; i < xfer->dm_nsegs; i++) { 1561 ccb->ac_sgtable->SgEntry[i].SgAddress = 1562 xfer->dm_segs[i].ds_addr; 1563 ccb->ac_sgtable->SgEntry[i].SgByteCount = 1564 xfer->dm_segs[i].ds_len; 1565 AAC_DPRINTF(AAC_D_IO, 1566 ("#%d va %p pa %p len %x\n", i, buf, 1567 xfer->dm_segs[i].ds_addr, 1568 xfer->dm_segs[i].ds_len)); 1569 } 1570 1571 /* update the FIB size for the s/g count */ 1572 fib->Header.Size += xfer->dm_nsegs * 1573 sizeof(struct aac_sg_entry); 1574 } 1575 1576 aac_start(ccb); 1577 1578 xs->error = XS_NOERROR; 1579 xs->resid = 0; 1580 return (1); 1581 } 1582 1583 /******************************************************************************** 1584 * Deliver a command to the controller; allocate controller resources at the 1585 * last moment when possible. 1586 */ 1587 int 1588 aac_start(struct aac_ccb *ccb) 1589 { 1590 struct aac_softc *sc = ccb->ac_xs->sc_link->adapter_softc; 1591 1592 #if 0 1593 /* get the command mapped */ 1594 aac_map_command(ccb); 1595 #endif 1596 1597 /* fix up the address values */ 1598 ccb->ac_fib->Header.SenderFibAddress = (u_int32_t)ccb->ac_fib; 1599 ccb->ac_fib->Header.ReceiverFibAddress = ccb->ac_fibphys; 1600 1601 /* save a pointer to the command for speedy reverse-lookup */ 1602 ccb->ac_fib->Header.SenderData = (u_int32_t)ccb; /* XXX ack, sizing */ 1603 1604 /* put the FIB on the outbound queue */ 1605 if (aac_enqueue_fib(sc, AAC_ADAP_NORM_CMD_QUEUE, 1606 ccb->ac_fib->Header.Size, ccb->ac_fib->Header.ReceiverFibAddress)) 1607 return (EBUSY); 1608 1609 return (0); 1610 } 1611 1612 /* 1613 * Map a command into controller-visible space. 1614 */ 1615 int 1616 aac_map_command(struct aac_ccb *ccb) 1617 { 1618 struct scsi_xfer *xs = ccb->ac_xs; 1619 struct aac_softc *sc = xs->sc_link->adapter_softc; 1620 int error; 1621 1622 #if 0 1623 /* don't map more than once */ 1624 if (ccb->ac_flags & AAC_CMD_MAPPED) 1625 return; 1626 #endif 1627 1628 if (xs->datalen != 0) { 1629 error = bus_dmamap_load(sc->sc_dmat, ccb->ac_dmamap_xfer, 1630 xs->data, xs->datalen, NULL, 1631 (xs->flags & SCSI_NOSLEEP) ? BUS_DMA_NOWAIT : 1632 BUS_DMA_WAITOK); 1633 if (error) { 1634 printf("%s: aac_scsi_cmd: ", sc->sc_dev.dv_xname); 1635 if (error == EFBIG) 1636 printf("more than %d dma segs\n", 1637 AAC_MAXSGENTRIES); 1638 else 1639 printf("error %d loading dma map\n", error); 1640 return (error); 1641 } 1642 1643 bus_dmamap_sync(sc->sc_dmat, ccb->ac_dmamap_xfer, 1644 (xs->flags & SCSI_DATA_IN) ? BUS_DMASYNC_PREREAD : 1645 BUS_DMASYNC_PREWRITE); 1646 } 1647 1648 #if 0 1649 ccb->ac_flags |= AAC_CMD_MAPPED; 1650 #endif 1651 return (0); 1652 } 1653 1654 /* 1655 * Unmap a command from controller-visible space. 1656 */ 1657 void 1658 aac_unmap_command(struct aac_ccb *ccb) 1659 { 1660 struct scsi_xfer *xs = ccb->ac_xs; 1661 struct aac_softc *sc = xs->sc_link->adapter_softc; 1662 1663 #if 0 1664 if (!(ccb->ac_flags & AAC_CMD_MAPPED)) 1665 return; 1666 #endif 1667 1668 if (xs->datalen != 0) { 1669 bus_dmamap_sync(sc->sc_dmat, ccb->ac_dmamap_xfer, 1670 (xs->flags & SCSI_DATA_IN) ? BUS_DMASYNC_POSTREAD : 1671 BUS_DMASYNC_POSTWRITE); 1672 1673 bus_dmamap_unload(sc->sc_dmat, ccb->ac_dmamap_xfer); 1674 } 1675 #if 0 1676 ccb->ac_flags &= ~AAC_CMD_MAPPED; 1677 #endif 1678 } 1679 1680 void 1681 aac_timeout(arg) 1682 void *arg; 1683 { 1684 struct aac_ccb *ccb = arg; 1685 struct scsi_link *link = ccb->ac_xs->sc_link; 1686 struct aac_softc *sc = link->adapter_softc; 1687 aac_lock_t lock; 1688 1689 sc_print_addr(link); 1690 printf("timed out\n"); 1691 1692 /* XXX Test for multiple timeouts */ 1693 1694 ccb->ac_xs->error = XS_TIMEOUT; 1695 lock = AAC_LOCK(sc); 1696 aac_enqueue_ccb(sc, ccb); 1697 AAC_UNLOCK(sc, lock); 1698 } 1699 1700 void 1701 aac_watchdog(arg) 1702 void *arg; 1703 { 1704 struct aac_ccb *ccb = arg; 1705 struct scsi_link *link = ccb->ac_xs->sc_link; 1706 struct aac_softc *sc = link->adapter_softc; 1707 aac_lock_t lock; 1708 1709 lock = AAC_LOCK(sc); 1710 ccb->ac_flags &= ~AAC_ACF_WATCHDOG; 1711 aac_start_ccbs(sc); 1712 AAC_UNLOCK(sc, lock); 1713 } 1714 /* 1715 * Insert a command into the driver queue, either at the front or at the tail. 1716 * It's ok to overload the freelist link as these structures are never on 1717 * the freelist at this time. 1718 */ 1719 void 1720 aac_enqueue(sc, xs, infront) 1721 struct aac_softc *sc; 1722 struct scsi_xfer *xs; 1723 int infront; 1724 { 1725 if (infront || LIST_FIRST(&sc->sc_queue) == NULL) { 1726 if (LIST_FIRST(&sc->sc_queue) == NULL) 1727 sc->sc_queuelast = xs; 1728 LIST_INSERT_HEAD(&sc->sc_queue, xs, free_list); 1729 return; 1730 } 1731 LIST_INSERT_AFTER(sc->sc_queuelast, xs, free_list); 1732 sc->sc_queuelast = xs; 1733 } 1734 1735 /* 1736 * Pull a command off the front of the driver queue. 1737 */ 1738 struct scsi_xfer * 1739 aac_dequeue(sc) 1740 struct aac_softc *sc; 1741 { 1742 struct scsi_xfer *xs; 1743 1744 xs = LIST_FIRST(&sc->sc_queue); 1745 if (xs == NULL) 1746 return (NULL); 1747 LIST_REMOVE(xs, free_list); 1748 1749 if (LIST_FIRST(&sc->sc_queue) == NULL) 1750 sc->sc_queuelast = NULL; 1751 1752 return (xs); 1753 } 1754 1755 /******************************************************************************** 1756 * Adapter-space FIB queue manipulation 1757 * 1758 * Note that the queue implementation here is a little funky; neither the PI or 1759 * CI will ever be zero. This behaviour is a controller feature. 1760 */ 1761 static struct { 1762 int size; 1763 int notify; 1764 } aac_qinfo[] = { 1765 { AAC_HOST_NORM_CMD_ENTRIES, AAC_DB_COMMAND_NOT_FULL }, 1766 { AAC_HOST_HIGH_CMD_ENTRIES, 0 }, 1767 { AAC_ADAP_NORM_CMD_ENTRIES, AAC_DB_COMMAND_READY }, 1768 { AAC_ADAP_HIGH_CMD_ENTRIES, 0 }, 1769 { AAC_HOST_NORM_RESP_ENTRIES, AAC_DB_RESPONSE_NOT_FULL }, 1770 { AAC_HOST_HIGH_RESP_ENTRIES, 0 }, 1771 { AAC_ADAP_NORM_RESP_ENTRIES, AAC_DB_RESPONSE_READY }, 1772 { AAC_ADAP_HIGH_RESP_ENTRIES, 0 } 1773 }; 1774 1775 /* 1776 * Atomically insert an entry into the nominated queue, returns 0 on success 1777 * or EBUSY if the queue is full. 1778 * 1779 * XXX Note that it would be more efficient to defer notifying the controller 1780 * in the case where we may be inserting several entries in rapid succession, 1781 * but implementing this usefully is difficult. 1782 */ 1783 int 1784 aac_enqueue_fib(struct aac_softc *sc, int queue, u_int32_t fib_size, 1785 u_int32_t fib_addr) 1786 { 1787 u_int32_t pi, ci; 1788 int error; 1789 aac_lock_t lock; 1790 1791 lock = AAC_LOCK(sc); 1792 1793 /* get the producer/consumer indices */ 1794 pi = sc->sc_queues->qt_qindex[queue][AAC_PRODUCER_INDEX]; 1795 ci = sc->sc_queues->qt_qindex[queue][AAC_CONSUMER_INDEX]; 1796 1797 /* wrap the queue? */ 1798 if (pi >= aac_qinfo[queue].size) 1799 pi = 0; 1800 1801 /* check for queue full */ 1802 if ((pi + 1) == ci) { 1803 error = EBUSY; 1804 goto out; 1805 } 1806 1807 /* populate queue entry */ 1808 (sc->sc_qentries[queue] + pi)->aq_fib_size = fib_size; 1809 (sc->sc_qentries[queue] + pi)->aq_fib_addr = fib_addr; 1810 1811 /* update producer index */ 1812 sc->sc_queues->qt_qindex[queue][AAC_PRODUCER_INDEX] = pi + 1; 1813 1814 /* notify the adapter if we know how */ 1815 if (aac_qinfo[queue].notify != 0) 1816 AAC_QNOTIFY(sc, aac_qinfo[queue].notify); 1817 1818 error = 0; 1819 1820 out: 1821 AAC_UNLOCK(sc, lock); 1822 return (error); 1823 } 1824 1825 /* 1826 * Atomically remove one entry from the nominated queue, returns 0 on success 1827 * or ENOENT if the queue is empty. 1828 */ 1829 int 1830 aac_dequeue_fib(struct aac_softc *sc, int queue, u_int32_t *fib_size, 1831 struct aac_fib **fib_addr) 1832 { 1833 u_int32_t pi, ci; 1834 int error; 1835 aac_lock_t lock; 1836 1837 lock = AAC_LOCK(sc); 1838 1839 /* get the producer/consumer indices */ 1840 pi = sc->sc_queues->qt_qindex[queue][AAC_PRODUCER_INDEX]; 1841 ci = sc->sc_queues->qt_qindex[queue][AAC_CONSUMER_INDEX]; 1842 1843 /* check for queue empty */ 1844 if (ci == pi) { 1845 error = ENOENT; 1846 goto out; 1847 } 1848 1849 /* wrap the queue? */ 1850 if (ci >= aac_qinfo[queue].size) 1851 ci = 0; 1852 1853 /* fetch the entry */ 1854 *fib_size = (sc->sc_qentries[queue] + ci)->aq_fib_size; 1855 *fib_addr = 1856 (struct aac_fib *)(sc->sc_qentries[queue] + ci)->aq_fib_addr; 1857 1858 /* update consumer index */ 1859 sc->sc_queues->qt_qindex[queue][AAC_CONSUMER_INDEX] = ci + 1; 1860 1861 /* if we have made the queue un-full, notify the adapter */ 1862 if (((pi + 1) == ci) && (aac_qinfo[queue].notify != 0)) 1863 AAC_QNOTIFY(sc, aac_qinfo[queue].notify); 1864 error = 0; 1865 1866 out: 1867 AAC_UNLOCK(sc, lock); 1868 return (error); 1869 } 1870 1871 #ifdef AAC_DEBUG 1872 /* 1873 * Print a FIB 1874 */ 1875 void 1876 aac_print_fib(struct aac_softc *sc, struct aac_fib *fib, char *caller) 1877 { 1878 printf("%s: FIB @ %p\n", caller, fib); 1879 printf(" XferState %b\n", fib->Header.XferState, "\20" 1880 "\1HOSTOWNED" 1881 "\2ADAPTEROWNED" 1882 "\3INITIALISED" 1883 "\4EMPTY" 1884 "\5FROMPOOL" 1885 "\6FROMHOST" 1886 "\7FROMADAP" 1887 "\10REXPECTED" 1888 "\11RNOTEXPECTED" 1889 "\12DONEADAP" 1890 "\13DONEHOST" 1891 "\14HIGH" 1892 "\15NORM" 1893 "\16ASYNC" 1894 "\17PAGEFILEIO" 1895 "\20SHUTDOWN" 1896 "\21LAZYWRITE" 1897 "\22ADAPMICROFIB" 1898 "\23BIOSFIB" 1899 "\24FAST_RESPONSE" 1900 "\25APIFIB\n"); 1901 printf(" Command %d\n", fib->Header.Command); 1902 printf(" StructType %d\n", fib->Header.StructType); 1903 printf(" Flags 0x%x\n", fib->Header.Flags); 1904 printf(" Size %d\n", fib->Header.Size); 1905 printf(" SenderSize %d\n", fib->Header.SenderSize); 1906 printf(" SenderAddress 0x%x\n", fib->Header.SenderFibAddress); 1907 printf(" ReceiverAddress 0x%x\n", fib->Header.ReceiverFibAddress); 1908 printf(" SenderData 0x%x\n", fib->Header.SenderData); 1909 switch(fib->Header.Command) { 1910 case ContainerCommand: { 1911 struct aac_blockread *br = (struct aac_blockread *)fib->data; 1912 struct aac_blockwrite *bw = (struct aac_blockwrite *)fib->data; 1913 struct aac_sg_table *sg = NULL; 1914 int i; 1915 1916 if (br->Command == VM_CtBlockRead) { 1917 printf(" BlockRead: container %d 0x%x/%d\n", 1918 br->ContainerId, br->BlockNumber, br->ByteCount); 1919 sg = &br->SgMap; 1920 } 1921 if (bw->Command == VM_CtBlockWrite) { 1922 printf(" BlockWrite: container %d 0x%x/%d (%s)\n", 1923 bw->ContainerId, bw->BlockNumber, bw->ByteCount, 1924 bw->Stable == CSTABLE ? "stable" : "unstable"); 1925 sg = &bw->SgMap; 1926 } 1927 if (sg != NULL) { 1928 printf(" %d s/g entries\n", sg->SgCount); 1929 for (i = 0; i < sg->SgCount; i++) 1930 printf(" 0x%08x/%d\n", 1931 sg->SgEntry[i].SgAddress, 1932 sg->SgEntry[i].SgByteCount); 1933 } 1934 break; 1935 } 1936 default: 1937 printf(" %16D\n", fib->data, " "); 1938 printf(" %16D\n", fib->data + 16, " "); 1939 break; 1940 } 1941 } 1942 #endif 1943