1 /* $NetBSD: aac.c,v 1.6 2002/11/25 20:29:14 fvdl Exp $ */ 2 3 /*- 4 * Copyright (c) 2002 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Andrew Doran. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39 /*- 40 * Copyright (c) 2001 Scott Long 41 * Copyright (c) 2001 Adaptec, Inc. 42 * Copyright (c) 2000 Michael Smith 43 * Copyright (c) 2000 BSDi 44 * Copyright (c) 2000 Niklas Hallqvist 45 * All rights reserved. 46 * 47 * Redistribution and use in source and binary forms, with or without 48 * modification, are permitted provided that the following conditions 49 * are met: 50 * 1. Redistributions of source code must retain the above copyright 51 * notice, this list of conditions and the following disclaimer. 52 * 2. Redistributions in binary form must reproduce the above copyright 53 * notice, this list of conditions and the following disclaimer in the 54 * documentation and/or other materials provided with the distribution. 55 * 56 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 57 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 58 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 59 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 60 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 61 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 62 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 63 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 64 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 65 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 66 * SUCH DAMAGE. 67 */ 68 69 /* 70 * Driver for the Adaptec 'FSA' family of PCI/SCSI RAID adapters. 71 * 72 * TODO: 73 * 74 * o Management interface. 75 * o Look again at some of the portability issues. 76 * o Handle various AIFs (e.g., notification that a container is going away). 77 */ 78 79 #include <sys/cdefs.h> 80 __KERNEL_RCSID(0, "$NetBSD: aac.c,v 1.6 2002/11/25 20:29:14 fvdl Exp $"); 81 82 #include "locators.h" 83 84 #include <sys/param.h> 85 #include <sys/systm.h> 86 #include <sys/buf.h> 87 #include <sys/device.h> 88 #include <sys/kernel.h> 89 #include <sys/malloc.h> 90 91 #include <machine/bus.h> 92 93 #include <uvm/uvm_extern.h> 94 95 #include <dev/ic/aacreg.h> 96 #include <dev/ic/aacvar.h> 97 #include <dev/ic/aac_tables.h> 98 99 int aac_check_firmware(struct aac_softc *); 100 void aac_describe_controller(struct aac_softc *); 101 int aac_dequeue_fib(struct aac_softc *, int, u_int32_t *, 102 struct aac_fib **); 103 int aac_enqueue_fib(struct aac_softc *, int, struct aac_fib *); 104 void aac_host_command(struct aac_softc *); 105 void aac_host_response(struct aac_softc *); 106 int aac_init(struct aac_softc *); 107 int aac_print(void *, const char *); 108 void aac_shutdown(void *); 109 void aac_startup(struct aac_softc *); 110 int aac_sync_command(struct aac_softc *, u_int32_t, u_int32_t, 111 u_int32_t, u_int32_t, u_int32_t, u_int32_t *); 112 int aac_sync_fib(struct aac_softc *, u_int32_t, u_int32_t, void *, 113 u_int16_t, void *, u_int16_t *); 114 int aac_submatch(struct device *, struct cfdata *, void *); 115 116 #ifdef AAC_DEBUG 117 void aac_print_fib(struct aac_softc *, struct aac_fib *, char *); 118 #endif 119 120 /* 121 * Adapter-space FIB queue manipulation. 122 * 123 * Note that the queue implementation here is a little funky; neither the PI or 124 * CI will ever be zero. This behaviour is a controller feature. 125 */ 126 static struct { 127 int size; 128 int notify; 129 } const aac_qinfo[] = { 130 { AAC_HOST_NORM_CMD_ENTRIES, AAC_DB_COMMAND_NOT_FULL }, 131 { AAC_HOST_HIGH_CMD_ENTRIES, 0 }, 132 { AAC_ADAP_NORM_CMD_ENTRIES, AAC_DB_COMMAND_READY }, 133 { AAC_ADAP_HIGH_CMD_ENTRIES, 0 }, 134 { AAC_HOST_NORM_RESP_ENTRIES, AAC_DB_RESPONSE_NOT_FULL }, 135 { AAC_HOST_HIGH_RESP_ENTRIES, 0 }, 136 { AAC_ADAP_NORM_RESP_ENTRIES, AAC_DB_RESPONSE_READY }, 137 { AAC_ADAP_HIGH_RESP_ENTRIES, 0 } 138 }; 139 140 #ifdef AAC_DEBUG 141 int aac_debug = AAC_DEBUG; 142 #endif 143 144 void *aac_sdh; 145 146 extern struct cfdriver aac_cd; 147 148 int 149 aac_attach(struct aac_softc *sc) 150 { 151 struct aac_attach_args aaca; 152 int nsegs, i, rv, state, size; 153 struct aac_ccb *ac; 154 struct aac_fib *fib; 155 bus_addr_t fibpa; 156 157 SIMPLEQ_INIT(&sc->sc_ccb_free); 158 SIMPLEQ_INIT(&sc->sc_ccb_queue); 159 SIMPLEQ_INIT(&sc->sc_ccb_complete); 160 161 /* 162 * Disable interrupts before we do anything. 163 */ 164 AAC_MASK_INTERRUPTS(sc); 165 166 /* 167 * Initialise the adapter. 168 */ 169 if (aac_check_firmware(sc)) 170 return (EINVAL); 171 172 if ((rv = aac_init(sc)) != 0) 173 return (rv); 174 aac_startup(sc); 175 176 /* 177 * Print a little information about the controller. 178 */ 179 aac_describe_controller(sc); 180 181 /* 182 * Initialize the ccbs. 183 */ 184 sc->sc_ccbs = malloc(sizeof(*ac) * AAC_NCCBS, M_DEVBUF, 185 M_NOWAIT | M_ZERO); 186 if (sc->sc_ccbs == NULL) { 187 printf("%s: memory allocation failure\n", sc->sc_dv.dv_xname); 188 return (ENOMEM); 189 } 190 state = 0; 191 size = sizeof(*fib) * AAC_NCCBS; 192 193 if ((rv = bus_dmamap_create(sc->sc_dmat, size, 1, size, 194 0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &sc->sc_fibs_dmamap)) != 0) { 195 printf("%s: cannot create fibs dmamap\n", 196 sc->sc_dv.dv_xname); 197 goto bail_out; 198 } 199 state++; 200 if ((rv = bus_dmamem_alloc(sc->sc_dmat, size, PAGE_SIZE, 0, 201 &sc->sc_fibs_seg, 1, &nsegs, BUS_DMA_NOWAIT)) != 0) { 202 printf("%s: can't allocate fibs structure\n", 203 sc->sc_dv.dv_xname); 204 goto bail_out; 205 } 206 state++; 207 if ((rv = bus_dmamem_map(sc->sc_dmat, &sc->sc_fibs_seg, nsegs, size, 208 (caddr_t *)&sc->sc_fibs, 0)) != 0) { 209 printf("%s: can't map fibs structure\n", 210 sc->sc_dv.dv_xname); 211 goto bail_out; 212 } 213 state++; 214 if ((rv = bus_dmamap_load(sc->sc_dmat, sc->sc_fibs_dmamap, sc->sc_fibs, 215 size, NULL, BUS_DMA_NOWAIT)) != 0) { 216 printf("%s: cannot load fibs dmamap\n", sc->sc_dv.dv_xname); 217 goto bail_out; 218 } 219 state++; 220 221 memset(sc->sc_fibs, 0, size); 222 fibpa = sc->sc_fibs_seg.ds_addr; 223 fib = sc->sc_fibs; 224 225 for (i = 0, ac = sc->sc_ccbs; i < AAC_NCCBS; i++, ac++) { 226 rv = bus_dmamap_create(sc->sc_dmat, AAC_MAX_XFER, 227 AAC_MAX_SGENTRIES, AAC_MAX_XFER, 0, 228 BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &ac->ac_dmamap_xfer); 229 if (rv) { 230 while (--ac >= sc->sc_ccbs) 231 bus_dmamap_destroy(sc->sc_dmat, 232 ac->ac_dmamap_xfer); 233 printf("%s: cannot create ccb dmamap (%d)", 234 sc->sc_dv.dv_xname, rv); 235 goto bail_out; 236 } 237 238 ac->ac_fib = fib++; 239 ac->ac_fibphys = fibpa; 240 fibpa += sizeof(*fib); 241 aac_ccb_free(sc, ac); 242 } 243 244 /* 245 * Attach devices. 246 */ 247 for (i = 0; i < AAC_MAX_CONTAINERS; i++) { 248 if (!sc->sc_hdr[i].hd_present) 249 continue; 250 aaca.aaca_unit = i; 251 config_found_sm(&sc->sc_dv, &aaca, aac_print, aac_submatch); 252 } 253 254 /* 255 * Enable interrupts, and register our shutdown hook. 256 */ 257 sc->sc_flags |= AAC_ONLINE; 258 AAC_UNMASK_INTERRUPTS(sc); 259 if (aac_sdh != NULL) 260 shutdownhook_establish(aac_shutdown, NULL); 261 return (0); 262 263 bail_out: 264 bus_dmamap_unload(sc->sc_dmat, sc->sc_common_dmamap); 265 bus_dmamem_unmap(sc->sc_dmat, (caddr_t)sc->sc_common, 266 sizeof(*sc->sc_common)); 267 bus_dmamem_free(sc->sc_dmat, &sc->sc_common_seg, 1); 268 bus_dmamap_destroy(sc->sc_dmat, sc->sc_common_dmamap); 269 270 if (state > 3) 271 bus_dmamap_unload(sc->sc_dmat, sc->sc_fibs_dmamap); 272 if (state > 2) 273 bus_dmamem_unmap(sc->sc_dmat, (caddr_t)sc->sc_fibs, size); 274 if (state > 1) 275 bus_dmamem_free(sc->sc_dmat, &sc->sc_fibs_seg, 1); 276 if (state > 0) 277 bus_dmamap_destroy(sc->sc_dmat, sc->sc_fibs_dmamap); 278 279 free(sc->sc_ccbs, M_DEVBUF); 280 return (rv); 281 } 282 283 /* 284 * Print autoconfiguration message for a sub-device. 285 */ 286 int 287 aac_print(void *aux, const char *pnp) 288 { 289 struct aac_attach_args *aaca; 290 291 aaca = aux; 292 293 if (pnp != NULL) 294 printf("block device at %s", pnp); 295 printf(" unit %d", aaca->aaca_unit); 296 return (UNCONF); 297 } 298 299 /* 300 * Match a sub-device. 301 */ 302 int 303 aac_submatch(struct device *parent, struct cfdata *cf, void *aux) 304 { 305 struct aac_attach_args *aaca; 306 307 aaca = aux; 308 309 if (cf->aaccf_unit != AACCF_UNIT_DEFAULT && 310 cf->aaccf_unit != aaca->aaca_unit) 311 return (0); 312 313 return (config_match(parent, cf, aux)); 314 } 315 316 /* 317 * Look up a text description of a numeric error code and return a pointer to 318 * same. 319 */ 320 const char * 321 aac_describe_code(const struct aac_code_lookup *table, u_int32_t code) 322 { 323 int i; 324 325 for (i = 0; table[i].string != NULL; i++) 326 if (table[i].code == code) 327 return (table[i].string); 328 329 return (table[i + 1].string); 330 } 331 332 void 333 aac_describe_controller(struct aac_softc *sc) 334 { 335 u_int8_t buf[AAC_FIB_DATASIZE]; 336 u_int16_t bufsize; 337 struct aac_adapter_info *info; 338 u_int8_t arg; 339 340 arg = 0; 341 if (aac_sync_fib(sc, RequestAdapterInfo, 0, &arg, sizeof(arg), &buf, 342 &bufsize)) { 343 printf("%s: RequestAdapterInfo failed\n", sc->sc_dv.dv_xname); 344 return; 345 } 346 if (bufsize != sizeof(*info)) { 347 printf("%s: " 348 "RequestAdapterInfo returned wrong data size (%d != %d)\n", 349 sc->sc_dv.dv_xname, bufsize, sizeof(*info)); 350 return; 351 } 352 info = (struct aac_adapter_info *)&buf[0]; 353 354 printf("%s: %s at %dMHz, %dMB cache, %s, kernel %d.%d-%d\n", 355 sc->sc_dv.dv_xname, 356 aac_describe_code(aac_cpu_variant, le32toh(info->CpuVariant)), 357 le32toh(info->ClockSpeed), 358 le32toh(info->BufferMem) / (1024 * 1024), 359 aac_describe_code(aac_battery_platform, 360 le32toh(info->batteryPlatform)), 361 info->KernelRevision.external.comp.major, 362 info->KernelRevision.external.comp.minor, 363 info->KernelRevision.external.comp.dash); 364 365 /* Save the kernel revision structure for later use. */ 366 sc->sc_revision = info->KernelRevision; 367 } 368 369 /* 370 * Retrieve the firmware version numbers. Dell PERC2/QC cards with firmware 371 * version 1.x are not compatible with this driver. 372 */ 373 int 374 aac_check_firmware(struct aac_softc *sc) 375 { 376 u_int32_t major, minor; 377 378 if ((sc->sc_quirks & AAC_QUIRK_PERC2QC) != 0) { 379 if (aac_sync_command(sc, AAC_MONKER_GETKERNVER, 0, 0, 0, 0, 380 NULL)) { 381 printf("%s: error reading firmware version\n", 382 sc->sc_dv.dv_xname); 383 return (1); 384 } 385 386 /* These numbers are stored as ASCII! */ 387 major = (AAC_GETREG4(sc, AAC_SA_MAILBOX + 4) & 0xff) - 0x30; 388 minor = (AAC_GETREG4(sc, AAC_SA_MAILBOX + 8) & 0xff) - 0x30; 389 if (major == 1) { 390 printf("%s: firmware version %d.%d not supported.\n", 391 sc->sc_dv.dv_xname, major, minor); 392 return (1); 393 } 394 } 395 396 return (0); 397 } 398 399 int 400 aac_init(struct aac_softc *sc) 401 { 402 int nsegs, i, rv, state, norm, high; 403 struct aac_adapter_init *ip; 404 u_int32_t code; 405 u_int8_t *qaddr; 406 407 state = 0; 408 409 /* 410 * First wait for the adapter to come ready. 411 */ 412 for (i = 0; i < AAC_BOOT_TIMEOUT * 1000; i++) { 413 code = AAC_GET_FWSTATUS(sc); 414 if ((code & AAC_SELF_TEST_FAILED) != 0) { 415 printf("%s: FATAL: selftest failed\n", 416 sc->sc_dv.dv_xname); 417 return (ENXIO); 418 } 419 if ((code & AAC_KERNEL_PANIC) != 0) { 420 printf("%s: FATAL: controller kernel panic\n", 421 sc->sc_dv.dv_xname); 422 return (ENXIO); 423 } 424 if ((code & AAC_UP_AND_RUNNING) != 0) 425 break; 426 DELAY(1000); 427 } 428 if (i == AAC_BOOT_TIMEOUT * 1000) { 429 printf("%s: FATAL: controller not coming ready, status %x\n", 430 sc->sc_dv.dv_xname, code); 431 return (ENXIO); 432 } 433 434 if ((rv = bus_dmamap_create(sc->sc_dmat, sizeof(*sc->sc_common), 1, 435 sizeof(*sc->sc_common), 0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, 436 &sc->sc_common_dmamap)) != 0) { 437 printf("%s: cannot create common dmamap\n", 438 sc->sc_dv.dv_xname); 439 return (rv); 440 } 441 if ((rv = bus_dmamem_alloc(sc->sc_dmat, sizeof(*sc->sc_common), 442 PAGE_SIZE, 0, &sc->sc_common_seg, 1, &nsegs, 443 BUS_DMA_NOWAIT)) != 0) { 444 printf("%s: can't allocate common structure\n", 445 sc->sc_dv.dv_xname); 446 goto bail_out; 447 } 448 state++; 449 if ((rv = bus_dmamem_map(sc->sc_dmat, &sc->sc_common_seg, nsegs, 450 sizeof(*sc->sc_common), (caddr_t *)&sc->sc_common, 0)) != 0) { 451 printf("%s: can't map common structure\n", 452 sc->sc_dv.dv_xname); 453 goto bail_out; 454 } 455 state++; 456 if ((rv = bus_dmamap_load(sc->sc_dmat, sc->sc_common_dmamap, 457 sc->sc_common, sizeof(*sc->sc_common), NULL, 458 BUS_DMA_NOWAIT)) != 0) { 459 printf("%s: cannot load common dmamap\n", sc->sc_dv.dv_xname); 460 goto bail_out; 461 } 462 state++; 463 464 memset(sc->sc_common, 0, sizeof(*sc->sc_common)); 465 466 /* 467 * Fill in the init structure. This tells the adapter about the 468 * physical location of various important shared data structures. 469 */ 470 ip = &sc->sc_common->ac_init; 471 ip->InitStructRevision = htole32(AAC_INIT_STRUCT_REVISION); 472 473 ip->AdapterFibsPhysicalAddress = htole32(sc->sc_common_seg.ds_addr + 474 offsetof(struct aac_common, ac_fibs)); 475 ip->AdapterFibsVirtualAddress = htole32(&sc->sc_common->ac_fibs[0]); 476 ip->AdapterFibsSize = 477 htole32(AAC_ADAPTER_FIBS * sizeof(struct aac_fib)); 478 ip->AdapterFibAlign = htole32(sizeof(struct aac_fib)); 479 480 ip->PrintfBufferAddress = htole32(sc->sc_common_seg.ds_addr + 481 offsetof(struct aac_common, ac_printf)); 482 ip->PrintfBufferSize = htole32(AAC_PRINTF_BUFSIZE); 483 484 ip->HostPhysMemPages = 0; /* not used? */ 485 ip->HostElapsedSeconds = 0; /* reset later if invalid */ 486 487 /* 488 * Initialise FIB queues. Note that it appears that the layout of 489 * the indexes and the segmentation of the entries is mandated by 490 * the adapter, which is only told about the base of the queue index 491 * fields. 492 * 493 * The initial values of the indices are assumed to inform the 494 * adapter of the sizes of the respective queues. 495 * 496 * The Linux driver uses a much more complex scheme whereby several 497 * header records are kept for each queue. We use a couple of 498 * generic list manipulation functions which 'know' the size of each 499 * list by virtue of a table. 500 */ 501 qaddr = &sc->sc_common->ac_qbuf[0] + AAC_QUEUE_ALIGN; 502 qaddr -= (u_int32_t)qaddr % AAC_QUEUE_ALIGN; /* XXX not portable */ 503 sc->sc_queues = (struct aac_queue_table *)qaddr; 504 ip->CommHeaderAddress = htole32(sc->sc_common_seg.ds_addr + 505 ((caddr_t)sc->sc_queues - (caddr_t)sc->sc_common)); 506 memset(sc->sc_queues, 0, sizeof(struct aac_queue_table)); 507 508 norm = htole32(AAC_HOST_NORM_CMD_ENTRIES); 509 high = htole32(AAC_HOST_HIGH_CMD_ENTRIES); 510 511 sc->sc_queues->qt_qindex[AAC_HOST_NORM_CMD_QUEUE][AAC_PRODUCER_INDEX] = 512 norm; 513 sc->sc_queues->qt_qindex[AAC_HOST_NORM_CMD_QUEUE][AAC_CONSUMER_INDEX] = 514 norm; 515 sc->sc_queues->qt_qindex[AAC_HOST_HIGH_CMD_QUEUE][AAC_PRODUCER_INDEX] = 516 high; 517 sc->sc_queues->qt_qindex[AAC_HOST_HIGH_CMD_QUEUE][AAC_CONSUMER_INDEX] = 518 high; 519 520 norm = htole32(AAC_ADAP_NORM_CMD_ENTRIES); 521 high = htole32(AAC_ADAP_HIGH_CMD_ENTRIES); 522 523 sc->sc_queues->qt_qindex[AAC_ADAP_NORM_CMD_QUEUE][AAC_PRODUCER_INDEX] = 524 norm; 525 sc->sc_queues->qt_qindex[AAC_ADAP_NORM_CMD_QUEUE][AAC_CONSUMER_INDEX] = 526 norm; 527 sc->sc_queues->qt_qindex[AAC_ADAP_HIGH_CMD_QUEUE][AAC_PRODUCER_INDEX] = 528 high; 529 sc->sc_queues->qt_qindex[AAC_ADAP_HIGH_CMD_QUEUE][AAC_CONSUMER_INDEX] = 530 high; 531 532 norm = htole32(AAC_HOST_NORM_RESP_ENTRIES); 533 high = htole32(AAC_HOST_HIGH_RESP_ENTRIES); 534 535 sc->sc_queues-> 536 qt_qindex[AAC_HOST_NORM_RESP_QUEUE][AAC_PRODUCER_INDEX] = norm; 537 sc->sc_queues-> 538 qt_qindex[AAC_HOST_NORM_RESP_QUEUE][AAC_CONSUMER_INDEX] = norm; 539 sc->sc_queues-> 540 qt_qindex[AAC_HOST_HIGH_RESP_QUEUE][AAC_PRODUCER_INDEX] = high; 541 sc->sc_queues-> 542 qt_qindex[AAC_HOST_HIGH_RESP_QUEUE][AAC_CONSUMER_INDEX] = high; 543 544 norm = htole32(AAC_ADAP_NORM_RESP_ENTRIES); 545 high = htole32(AAC_ADAP_HIGH_RESP_ENTRIES); 546 547 sc->sc_queues-> 548 qt_qindex[AAC_ADAP_NORM_RESP_QUEUE][AAC_PRODUCER_INDEX] = norm; 549 sc->sc_queues-> 550 qt_qindex[AAC_ADAP_NORM_RESP_QUEUE][AAC_CONSUMER_INDEX] = norm; 551 sc->sc_queues-> 552 qt_qindex[AAC_ADAP_HIGH_RESP_QUEUE][AAC_PRODUCER_INDEX] = high; 553 sc->sc_queues-> 554 qt_qindex[AAC_ADAP_HIGH_RESP_QUEUE][AAC_CONSUMER_INDEX] = high; 555 556 sc->sc_qentries[AAC_HOST_NORM_CMD_QUEUE] = 557 &sc->sc_queues->qt_HostNormCmdQueue[0]; 558 sc->sc_qentries[AAC_HOST_HIGH_CMD_QUEUE] = 559 &sc->sc_queues->qt_HostHighCmdQueue[0]; 560 sc->sc_qentries[AAC_ADAP_NORM_CMD_QUEUE] = 561 &sc->sc_queues->qt_AdapNormCmdQueue[0]; 562 sc->sc_qentries[AAC_ADAP_HIGH_CMD_QUEUE] = 563 &sc->sc_queues->qt_AdapHighCmdQueue[0]; 564 sc->sc_qentries[AAC_HOST_NORM_RESP_QUEUE] = 565 &sc->sc_queues->qt_HostNormRespQueue[0]; 566 sc->sc_qentries[AAC_HOST_HIGH_RESP_QUEUE] = 567 &sc->sc_queues->qt_HostHighRespQueue[0]; 568 sc->sc_qentries[AAC_ADAP_NORM_RESP_QUEUE] = 569 &sc->sc_queues->qt_AdapNormRespQueue[0]; 570 sc->sc_qentries[AAC_ADAP_HIGH_RESP_QUEUE] = 571 &sc->sc_queues->qt_AdapHighRespQueue[0]; 572 573 /* 574 * Do controller-type-specific initialisation 575 */ 576 switch (sc->sc_hwif) { 577 case AAC_HWIF_I960RX: 578 AAC_SETREG4(sc, AAC_RX_ODBR, ~0); 579 break; 580 } 581 582 bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap, 0, 583 sizeof(*sc->sc_common), 584 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 585 586 /* 587 * Give the init structure to the controller. 588 */ 589 if (aac_sync_command(sc, AAC_MONKER_INITSTRUCT, 590 sc->sc_common_seg.ds_addr + offsetof(struct aac_common, ac_init), 591 0, 0, 0, NULL)) { 592 printf("%s: error establishing init structure\n", 593 sc->sc_dv.dv_xname); 594 rv = EIO; 595 goto bail_out; 596 } 597 598 return (0); 599 600 bail_out: 601 if (state > 2) 602 bus_dmamap_unload(sc->sc_dmat, sc->sc_common_dmamap); 603 if (state > 1) 604 bus_dmamem_unmap(sc->sc_dmat, (caddr_t)sc->sc_common, 605 sizeof(*sc->sc_common)); 606 if (state > 0) 607 bus_dmamem_free(sc->sc_dmat, &sc->sc_common_seg, 1); 608 bus_dmamap_destroy(sc->sc_dmat, sc->sc_common_dmamap); 609 610 return (rv); 611 } 612 613 /* 614 * Probe for containers, create disks. 615 */ 616 void 617 aac_startup(struct aac_softc *sc) 618 { 619 struct aac_mntinfo mi; 620 struct aac_mntinforesponse mir; 621 struct aac_drive *hd; 622 u_int16_t rsize; 623 int i; 624 625 /* 626 * Loop over possible containers. 627 */ 628 mi.Command = htole32(VM_NameServe); 629 mi.MntType = htole32(FT_FILESYS); 630 hd = sc->sc_hdr; 631 632 for (i = 0; i < AAC_MAX_CONTAINERS; i++, hd++) { 633 /* 634 * Request information on this container. 635 */ 636 mi.MntCount = htole32(i); 637 if (aac_sync_fib(sc, ContainerCommand, 0, &mi, sizeof(mi), &mir, 638 &rsize)) { 639 printf("%s: error probing container %d\n", 640 sc->sc_dv.dv_xname, i); 641 continue; 642 } 643 if (rsize != sizeof(mir)) { 644 printf("%s: container info response wrong size " 645 "(%d should be %d)\n", 646 sc->sc_dv.dv_xname, rsize, sizeof(mir)); 647 continue; 648 } 649 650 /* 651 * Check container volume type for validity. Note that many 652 * of the possible types may never show up. 653 */ 654 if (le32toh(mir.Status) != ST_OK || 655 le32toh(mir.MntTable[0].VolType) == CT_NONE) 656 continue; 657 658 hd->hd_present = 1; 659 hd->hd_size = le32toh(mir.MntTable[0].Capacity); 660 hd->hd_devtype = le32toh(mir.MntTable[0].VolType); 661 hd->hd_size &= ~0x1f; 662 sc->sc_nunits++; 663 } 664 } 665 666 void 667 aac_shutdown(void *cookie) 668 { 669 struct aac_softc *sc; 670 struct aac_close_command cc; 671 u_int32_t i; 672 673 for (i = 0; i < aac_cd.cd_ndevs; i++) { 674 if ((sc = device_lookup(&aac_cd, i)) == NULL) 675 continue; 676 if ((sc->sc_flags & AAC_ONLINE) == 0) 677 continue; 678 679 AAC_MASK_INTERRUPTS(sc); 680 681 /* 682 * Send a Container shutdown followed by a HostShutdown FIB 683 * to the controller to convince it that we don't want to 684 * talk to it anymore. We've been closed and all I/O 685 * completed already 686 */ 687 cc.Command = htole32(VM_CloseAll); 688 cc.ContainerId = 0xffffffff; 689 if (aac_sync_fib(sc, ContainerCommand, 0, &cc, sizeof(cc), 690 NULL, NULL)) { 691 printf("%s: unable to halt controller\n", 692 sc->sc_dv.dv_xname); 693 continue; 694 } 695 696 /* 697 * Note that issuing this command to the controller makes it 698 * shut down but also keeps it from coming back up without a 699 * reset of the PCI bus. 700 */ 701 if (aac_sync_fib(sc, FsaHostShutdown, AAC_FIBSTATE_SHUTDOWN, 702 &i, sizeof(i), NULL, NULL)) 703 printf("%s: unable to halt controller\n", 704 sc->sc_dv.dv_xname); 705 } 706 } 707 708 /* 709 * Take an interrupt. 710 */ 711 int 712 aac_intr(void *cookie) 713 { 714 struct aac_softc *sc; 715 u_int16_t reason; 716 int claimed; 717 718 sc = cookie; 719 claimed = 0; 720 721 AAC_DPRINTF(AAC_D_INTR, ("aac_intr(%p) ", sc)); 722 723 reason = AAC_GET_ISTATUS(sc); 724 AAC_DPRINTF(AAC_D_INTR, ("istatus 0x%04x ", reason)); 725 726 /* 727 * Controller wants to talk to the log. XXX Should we defer this? 728 */ 729 if ((reason & AAC_DB_PRINTF) != 0) { 730 if (sc->sc_common->ac_printf[0] != '\0') { 731 printf("%s: WARNING: adapter logged message:\n", 732 sc->sc_dv.dv_xname); 733 printf("%s: %.*s", sc->sc_dv.dv_xname, 734 AAC_PRINTF_BUFSIZE, sc->sc_common->ac_printf); 735 sc->sc_common->ac_printf[0] = '\0'; 736 } 737 AAC_CLEAR_ISTATUS(sc, AAC_DB_PRINTF); 738 AAC_QNOTIFY(sc, AAC_DB_PRINTF); 739 claimed = 1; 740 } 741 742 /* 743 * Controller has a message for us? 744 */ 745 if ((reason & AAC_DB_COMMAND_READY) != 0) { 746 aac_host_command(sc); 747 AAC_CLEAR_ISTATUS(sc, AAC_DB_COMMAND_READY); 748 claimed = 1; 749 } 750 751 /* 752 * Controller has a response for us? 753 */ 754 if ((reason & AAC_DB_RESPONSE_READY) != 0) { 755 aac_host_response(sc); 756 AAC_CLEAR_ISTATUS(sc, AAC_DB_RESPONSE_READY); 757 claimed = 1; 758 } 759 760 /* 761 * Spurious interrupts that we don't use - reset the mask and clear 762 * the interrupts. 763 */ 764 if ((reason & (AAC_DB_SYNC_COMMAND | AAC_DB_COMMAND_NOT_FULL | 765 AAC_DB_RESPONSE_NOT_FULL)) != 0) { 766 AAC_UNMASK_INTERRUPTS(sc); 767 AAC_CLEAR_ISTATUS(sc, AAC_DB_SYNC_COMMAND | 768 AAC_DB_COMMAND_NOT_FULL | AAC_DB_RESPONSE_NOT_FULL); 769 claimed = 1; 770 } 771 772 return (claimed); 773 } 774 775 /* 776 * Handle notification of one or more FIBs coming from the controller. 777 */ 778 void 779 aac_host_command(struct aac_softc *sc) 780 { 781 struct aac_fib *fib; 782 u_int32_t fib_size; 783 784 for (;;) { 785 if (aac_dequeue_fib(sc, AAC_HOST_NORM_CMD_QUEUE, &fib_size, 786 &fib)) 787 break; /* nothing to do */ 788 789 bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap, 790 (caddr_t)fib - (caddr_t)sc->sc_common, sizeof(*fib), 791 BUS_DMASYNC_POSTREAD); 792 793 switch (le16toh(fib->Header.Command)) { 794 case AifRequest: 795 #ifdef notyet 796 aac_handle_aif(sc, 797 (struct aac_aif_command *)&fib->data[0]); 798 #endif 799 break; 800 default: 801 printf("%s: unknown command from controller\n", 802 sc->sc_dv.dv_xname); 803 AAC_PRINT_FIB(sc, fib); 804 break; 805 } 806 807 bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap, 808 (caddr_t)fib - (caddr_t)sc->sc_common, sizeof(*fib), 809 BUS_DMASYNC_PREREAD); 810 811 /* XXX reply to FIBs requesting responses ?? */ 812 /* XXX how do we return these FIBs to the controller? */ 813 } 814 } 815 816 /* 817 * Handle notification of one or more FIBs completed by the controller 818 */ 819 void 820 aac_host_response(struct aac_softc *sc) 821 { 822 struct aac_ccb *ac; 823 struct aac_fib *fib; 824 u_int32_t fib_size; 825 826 /* 827 * Look for completed FIBs on our queue. 828 */ 829 for (;;) { 830 if (aac_dequeue_fib(sc, AAC_HOST_NORM_RESP_QUEUE, &fib_size, 831 &fib)) 832 break; /* nothing to do */ 833 834 bus_dmamap_sync(sc->sc_dmat, sc->sc_fibs_dmamap, 835 (caddr_t)fib - (caddr_t)sc->sc_fibs, sizeof(*fib), 836 BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD); 837 838 if ((fib->Header.SenderData & 0x80000000) == 0) { 839 /* Not valid; not sent by us. */ 840 AAC_PRINT_FIB(sc, fib); 841 } else { 842 ac = (struct aac_ccb *)((caddr_t)sc->sc_ccbs + 843 (fib->Header.SenderData & 0x7fffffff)); 844 fib->Header.SenderData = 0; 845 SIMPLEQ_INSERT_TAIL(&sc->sc_ccb_complete, ac, ac_chain); 846 } 847 } 848 849 /* 850 * Deal with any completed commands. 851 */ 852 while ((ac = SIMPLEQ_FIRST(&sc->sc_ccb_complete)) != NULL) { 853 SIMPLEQ_REMOVE_HEAD(&sc->sc_ccb_complete, ac_chain); 854 ac->ac_flags |= AAC_CCB_COMPLETED; 855 856 if (ac->ac_intr != NULL) 857 (*ac->ac_intr)(ac); 858 } 859 860 /* 861 * Try to submit more commands. 862 */ 863 if (! SIMPLEQ_EMPTY(&sc->sc_ccb_queue)) 864 aac_ccb_enqueue(sc, NULL); 865 } 866 867 /* 868 * Send a synchronous command to the controller and wait for a result. 869 */ 870 int 871 aac_sync_command(struct aac_softc *sc, u_int32_t command, u_int32_t arg0, 872 u_int32_t arg1, u_int32_t arg2, u_int32_t arg3, u_int32_t *sp) 873 { 874 int i; 875 u_int32_t status; 876 int s; 877 878 s = splbio(); 879 880 /* Populate the mailbox. */ 881 AAC_SET_MAILBOX(sc, command, arg0, arg1, arg2, arg3); 882 883 /* Ensure the sync command doorbell flag is cleared. */ 884 AAC_CLEAR_ISTATUS(sc, AAC_DB_SYNC_COMMAND); 885 886 /* ... then set it to signal the adapter. */ 887 AAC_QNOTIFY(sc, AAC_DB_SYNC_COMMAND); 888 DELAY(AAC_SYNC_DELAY); 889 890 /* Spin waiting for the command to complete. */ 891 for (i = 0; i < AAC_IMMEDIATE_TIMEOUT * 1000; i++) { 892 if (AAC_GET_ISTATUS(sc) & AAC_DB_SYNC_COMMAND); 893 break; 894 DELAY(1000); 895 } 896 if (i == AAC_IMMEDIATE_TIMEOUT * 1000) { 897 splx(s); 898 return (EIO); 899 } 900 901 /* Clear the completion flag. */ 902 AAC_CLEAR_ISTATUS(sc, AAC_DB_SYNC_COMMAND); 903 904 /* Get the command status. */ 905 status = AAC_GET_MAILBOXSTATUS(sc); 906 splx(s); 907 if (sp != NULL) 908 *sp = status; 909 910 return (0); /* XXX Check command return status? */ 911 } 912 913 /* 914 * Send a synchronous FIB to the controller and wait for a result. 915 */ 916 int 917 aac_sync_fib(struct aac_softc *sc, u_int32_t command, u_int32_t xferstate, 918 void *data, u_int16_t datasize, void *result, 919 u_int16_t *resultsize) 920 { 921 struct aac_fib *fib; 922 u_int32_t fibpa, status; 923 924 fib = &sc->sc_common->ac_sync_fib; 925 fibpa = sc->sc_common_seg.ds_addr + 926 offsetof(struct aac_common, ac_sync_fib); 927 928 if (datasize > AAC_FIB_DATASIZE) 929 return (EINVAL); 930 931 /* 932 * Set up the sync FIB. 933 */ 934 fib->Header.XferState = htole32(AAC_FIBSTATE_HOSTOWNED | 935 AAC_FIBSTATE_INITIALISED | AAC_FIBSTATE_EMPTY | xferstate); 936 fib->Header.Command = htole16(command); 937 fib->Header.StructType = AAC_FIBTYPE_TFIB; 938 fib->Header.Size = htole16(sizeof(*fib) + datasize); 939 fib->Header.SenderSize = htole16(sizeof(*fib)); 940 fib->Header.SenderFibAddress = htole32((u_int32_t)fib); /* XXX */ 941 fib->Header.ReceiverFibAddress = htole32(fibpa); 942 943 /* 944 * Copy in data. 945 */ 946 if (data != NULL) { 947 memcpy(fib->data, data, datasize); 948 fib->Header.XferState |= 949 htole32(AAC_FIBSTATE_FROMHOST | AAC_FIBSTATE_NORM); 950 } 951 952 bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap, 953 (caddr_t)fib - (caddr_t)sc->sc_common, sizeof(*fib), 954 BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); 955 956 /* 957 * Give the FIB to the controller, wait for a response. 958 */ 959 if (aac_sync_command(sc, AAC_MONKER_SYNCFIB, fibpa, 0, 0, 0, &status)) 960 return (EIO); 961 962 bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap, 963 (caddr_t)fib - (caddr_t)sc->sc_common, sizeof(*fib), 964 BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD); 965 966 /* 967 * Copy out the result 968 */ 969 if (result != NULL) { 970 *resultsize = le16toh(fib->Header.Size) - sizeof(fib->Header); 971 memcpy(result, fib->data, *resultsize); 972 } 973 974 return (0); 975 } 976 977 struct aac_ccb * 978 aac_ccb_alloc(struct aac_softc *sc, int flags) 979 { 980 struct aac_ccb *ac; 981 int s; 982 983 AAC_DPRINTF(AAC_D_QUEUE, ("aac_ccb_alloc(%p, 0x%x) ", sc, flags)); 984 985 s = splbio(); 986 ac = SIMPLEQ_FIRST(&sc->sc_ccb_free); 987 #ifdef DIAGNOSTIC 988 if (ac == NULL) 989 panic("aac_ccb_get: no free CCBS"); 990 #endif 991 SIMPLEQ_REMOVE_HEAD(&sc->sc_ccb_free, ac_chain); 992 splx(s); 993 994 ac->ac_flags = flags; 995 return (ac); 996 } 997 998 void 999 aac_ccb_free(struct aac_softc *sc, struct aac_ccb *ac) 1000 { 1001 int s; 1002 1003 AAC_DPRINTF(AAC_D_QUEUE, ("aac_ccb_free(%p, %p) ", sc, ac)); 1004 1005 ac->ac_flags = 0; 1006 ac->ac_intr = NULL; 1007 ac->ac_fib->Header.XferState = htole32(AAC_FIBSTATE_EMPTY); 1008 ac->ac_fib->Header.StructType = AAC_FIBTYPE_TFIB; 1009 ac->ac_fib->Header.Flags = 0; 1010 ac->ac_fib->Header.SenderSize = htole16(sizeof(*ac->ac_fib)); 1011 1012 #ifdef AAC_DEBUG 1013 /* 1014 * These are duplicated in aac_ccb_submit() to cover the case where 1015 * an intermediate stage may have destroyed them. They're left 1016 * initialised here for debugging purposes only. 1017 */ 1018 ac->ac_fib->Header.SenderFibAddress = htole32((u_int32_t)ac->ac_fib); 1019 ac->ac_fib->Header.ReceiverFibAddress = htole32(ac->ac_fibphys); 1020 #endif 1021 1022 s = splbio(); 1023 SIMPLEQ_INSERT_HEAD(&sc->sc_ccb_free, ac, ac_chain); 1024 splx(s); 1025 } 1026 1027 int 1028 aac_ccb_map(struct aac_softc *sc, struct aac_ccb *ac) 1029 { 1030 int error; 1031 1032 AAC_DPRINTF(AAC_D_QUEUE, ("aac_ccb_map(%p, %p) ", sc, ac)); 1033 1034 #ifdef DIAGNOSTIC 1035 if ((ac->ac_flags & AAC_CCB_MAPPED) != 0) 1036 panic("aac_ccb_map: already mapped"); 1037 #endif 1038 1039 error = bus_dmamap_load(sc->sc_dmat, ac->ac_dmamap_xfer, ac->ac_data, 1040 ac->ac_datalen, NULL, BUS_DMA_NOWAIT | BUS_DMA_STREAMING | 1041 ((ac->ac_flags & AAC_CCB_DATA_IN) ? BUS_DMA_READ : BUS_DMA_WRITE)); 1042 if (error) { 1043 printf("%s: aac_ccb_map: ", sc->sc_dv.dv_xname); 1044 if (error == EFBIG) 1045 printf("more than %d dma segs\n", AAC_MAX_SGENTRIES); 1046 else 1047 printf("error %d loading dma map\n", error); 1048 return (error); 1049 } 1050 1051 bus_dmamap_sync(sc->sc_dmat, ac->ac_dmamap_xfer, 0, ac->ac_datalen, 1052 (ac->ac_flags & AAC_CCB_DATA_IN) ? BUS_DMASYNC_PREREAD : 1053 BUS_DMASYNC_PREWRITE); 1054 1055 #ifdef DIAGNOSTIC 1056 ac->ac_flags |= AAC_CCB_MAPPED; 1057 #endif 1058 return (0); 1059 } 1060 1061 void 1062 aac_ccb_unmap(struct aac_softc *sc, struct aac_ccb *ac) 1063 { 1064 1065 AAC_DPRINTF(AAC_D_QUEUE, ("aac_ccb_unmap(%p, %p) ", sc, ac)); 1066 1067 #ifdef DIAGNOSTIC 1068 if ((ac->ac_flags & AAC_CCB_MAPPED) == 0) 1069 panic("aac_ccb_unmap: not mapped"); 1070 #endif 1071 1072 bus_dmamap_sync(sc->sc_dmat, ac->ac_dmamap_xfer, 0, ac->ac_datalen, 1073 (ac->ac_flags & AAC_CCB_DATA_IN) ? BUS_DMASYNC_POSTREAD : 1074 BUS_DMASYNC_POSTWRITE); 1075 bus_dmamap_unload(sc->sc_dmat, ac->ac_dmamap_xfer); 1076 1077 #ifdef DIAGNOSTIC 1078 ac->ac_flags &= ~AAC_CCB_MAPPED; 1079 #endif 1080 } 1081 1082 void 1083 aac_ccb_enqueue(struct aac_softc *sc, struct aac_ccb *ac) 1084 { 1085 int s; 1086 1087 AAC_DPRINTF(AAC_D_QUEUE, ("aac_ccb_enqueue(%p, %p) ", sc, ac)); 1088 1089 s = splbio(); 1090 1091 if (ac != NULL) 1092 SIMPLEQ_INSERT_TAIL(&sc->sc_ccb_queue, ac, ac_chain); 1093 1094 while ((ac = SIMPLEQ_FIRST(&sc->sc_ccb_queue)) != NULL) { 1095 if (aac_ccb_submit(sc, ac)) 1096 break; 1097 SIMPLEQ_REMOVE_HEAD(&sc->sc_ccb_queue, ac_chain); 1098 } 1099 1100 splx(s); 1101 } 1102 1103 int 1104 aac_ccb_submit(struct aac_softc *sc, struct aac_ccb *ac) 1105 { 1106 1107 AAC_DPRINTF(AAC_D_QUEUE, ("aac_ccb_submit(%p, %p) ", sc, ac)); 1108 1109 /* Fix up the address values. */ 1110 ac->ac_fib->Header.SenderFibAddress = htole32((u_int32_t)ac->ac_fib); 1111 ac->ac_fib->Header.ReceiverFibAddress = htole32(ac->ac_fibphys); 1112 1113 /* Save a pointer to the command for speedy reverse-lookup. */ 1114 ac->ac_fib->Header.SenderData = 1115 (u_int32_t)((caddr_t)ac - (caddr_t)sc->sc_ccbs) | 0x80000000; 1116 1117 bus_dmamap_sync(sc->sc_dmat, sc->sc_fibs_dmamap, 1118 (caddr_t)ac->ac_fib - (caddr_t)sc->sc_fibs, sizeof(*ac->ac_fib), 1119 BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); 1120 1121 /* Put the FIB on the outbound queue. */ 1122 return (aac_enqueue_fib(sc, AAC_ADAP_NORM_CMD_QUEUE, ac->ac_fib)); 1123 } 1124 1125 int 1126 aac_ccb_poll(struct aac_softc *sc, struct aac_ccb *ac, int timo) 1127 { 1128 int rv, s; 1129 1130 AAC_DPRINTF(AAC_D_QUEUE, ("aac_ccb_poll(%p, %p, %d) ", sc, ac, timo)); 1131 1132 s = splbio(); 1133 1134 if ((rv = aac_ccb_submit(sc, ac)) != 0) { 1135 splx(s); 1136 return (rv); 1137 } 1138 1139 for (timo *= 1000; timo != 0; timo--) { 1140 aac_intr(sc); 1141 if ((ac->ac_flags & AAC_CCB_COMPLETED) != 0) 1142 break; 1143 DELAY(100); 1144 } 1145 1146 splx(s); 1147 return (timo == 0); 1148 } 1149 1150 /* 1151 * Atomically insert an entry into the nominated queue, returns 0 on success 1152 * or EBUSY if the queue is full. 1153 * 1154 * XXX Note that it would be more efficient to defer notifying the 1155 * controller in the case where we may be inserting several entries in rapid 1156 * succession, but implementing this usefully is difficult. 1157 */ 1158 int 1159 aac_enqueue_fib(struct aac_softc *sc, int queue, struct aac_fib *fib) 1160 { 1161 u_int32_t fib_size, fib_addr, pi, ci; 1162 1163 fib_size = le16toh(fib->Header.Size); 1164 fib_addr = le32toh(fib->Header.ReceiverFibAddress); 1165 1166 bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap, 1167 (caddr_t)sc->sc_common->ac_qbuf - (caddr_t)sc->sc_common, 1168 sizeof(sc->sc_common->ac_qbuf), 1169 BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD); 1170 1171 /* Get the producer/consumer indices. */ 1172 pi = le32toh(sc->sc_queues->qt_qindex[queue][AAC_PRODUCER_INDEX]); 1173 ci = le32toh(sc->sc_queues->qt_qindex[queue][AAC_CONSUMER_INDEX]); 1174 1175 /* Wrap the queue? */ 1176 if (pi >= aac_qinfo[queue].size) 1177 pi = 0; 1178 1179 /* Check for queue full. */ 1180 if ((pi + 1) == ci) 1181 return (EAGAIN); 1182 1183 /* Populate queue entry. */ 1184 (sc->sc_qentries[queue] + pi)->aq_fib_size = htole32(fib_size); 1185 (sc->sc_qentries[queue] + pi)->aq_fib_addr = htole32(fib_addr); 1186 1187 /* Update producer index. */ 1188 sc->sc_queues->qt_qindex[queue][AAC_PRODUCER_INDEX] = htole32(pi + 1); 1189 1190 bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap, 1191 (caddr_t)sc->sc_common->ac_qbuf - (caddr_t)sc->sc_common, 1192 sizeof(sc->sc_common->ac_qbuf), 1193 BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); 1194 1195 /* Notify the adapter if we know how. */ 1196 if (aac_qinfo[queue].notify != 0) 1197 AAC_QNOTIFY(sc, aac_qinfo[queue].notify); 1198 1199 return (0); 1200 } 1201 1202 /* 1203 * Atomically remove one entry from the nominated queue, returns 0 on success 1204 * or ENOENT if the queue is empty. 1205 */ 1206 int 1207 aac_dequeue_fib(struct aac_softc *sc, int queue, u_int32_t *fib_size, 1208 struct aac_fib **fib_addr) 1209 { 1210 u_int32_t pi, ci; 1211 int notify; 1212 1213 bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap, 1214 (caddr_t)sc->sc_common->ac_qbuf - (caddr_t)sc->sc_common, 1215 sizeof(sc->sc_common->ac_qbuf), 1216 BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD); 1217 1218 /* Get the producer/consumer indices. */ 1219 pi = le32toh(sc->sc_queues->qt_qindex[queue][AAC_PRODUCER_INDEX]); 1220 ci = le32toh(sc->sc_queues->qt_qindex[queue][AAC_CONSUMER_INDEX]); 1221 1222 /* Check for queue empty. */ 1223 if (ci == pi) 1224 return (ENOENT); 1225 1226 notify = 0; 1227 if (ci == pi + 1) 1228 notify = 1; 1229 1230 /* Wrap the queue? */ 1231 if (ci >= aac_qinfo[queue].size) 1232 ci = 0; 1233 1234 /* Fetch the entry. */ 1235 *fib_size = le32toh((sc->sc_qentries[queue] + ci)->aq_fib_size); 1236 *fib_addr = le32toh((struct aac_fib *) 1237 (sc->sc_qentries[queue] + ci)->aq_fib_addr); 1238 1239 /* Update consumer index. */ 1240 sc->sc_queues->qt_qindex[queue][AAC_CONSUMER_INDEX] = ci + 1; 1241 1242 bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap, 1243 (caddr_t)sc->sc_common->ac_qbuf - (caddr_t)sc->sc_common, 1244 sizeof(sc->sc_common->ac_qbuf), 1245 BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); 1246 1247 /* If we have made the queue un-full, notify the adapter. */ 1248 if (notify && (aac_qinfo[queue].notify != 0)) 1249 AAC_QNOTIFY(sc, aac_qinfo[queue].notify); 1250 1251 return (0); 1252 } 1253 1254 #ifdef AAC_DEBUG 1255 /* 1256 * Print a FIB 1257 */ 1258 void 1259 aac_print_fib(struct aac_softc *sc, struct aac_fib *fib, char *caller) 1260 { 1261 struct aac_blockread *br; 1262 struct aac_blockwrite *bw; 1263 struct aac_sg_table *sg; 1264 char buf[512]; 1265 int i; 1266 1267 printf("%s: FIB @ %p\n", caller, fib); 1268 bitmask_snprintf(le32toh(fib->Header.XferState), 1269 "\20" 1270 "\1HOSTOWNED" 1271 "\2ADAPTEROWNED" 1272 "\3INITIALISED" 1273 "\4EMPTY" 1274 "\5FROMPOOL" 1275 "\6FROMHOST" 1276 "\7FROMADAP" 1277 "\10REXPECTED" 1278 "\11RNOTEXPECTED" 1279 "\12DONEADAP" 1280 "\13DONEHOST" 1281 "\14HIGH" 1282 "\15NORM" 1283 "\16ASYNC" 1284 "\17PAGEFILEIO" 1285 "\20SHUTDOWN" 1286 "\21LAZYWRITE" 1287 "\22ADAPMICROFIB" 1288 "\23BIOSFIB" 1289 "\24FAST_RESPONSE" 1290 "\25APIFIB\n", 1291 buf, 1292 sizeof(buf)); 1293 1294 printf(" XferState %s\n", buf); 1295 printf(" Command %d\n", le16toh(fib->Header.Command)); 1296 printf(" StructType %d\n", fib->Header.StructType); 1297 printf(" Flags 0x%x\n", fib->Header.Flags); 1298 printf(" Size %d\n", le16toh(fib->Header.Size)); 1299 printf(" SenderSize %d\n", le16toh(fib->Header.SenderSize)); 1300 printf(" SenderAddress 0x%x\n", 1301 le32toh(fib->Header.SenderFibAddress)); 1302 printf(" ReceiverAddress 0x%x\n", 1303 le32toh(fib->Header.ReceiverFibAddress)); 1304 printf(" SenderData 0x%x\n", fib->Header.SenderData); 1305 1306 switch (fib->Header.Command) { 1307 case ContainerCommand: { 1308 br = (struct aac_blockread *)fib->data; 1309 bw = (struct aac_blockwrite *)fib->data; 1310 sg = NULL; 1311 1312 if (le32toh(br->Command) == VM_CtBlockRead) { 1313 printf(" BlockRead: container %d 0x%x/%d\n", 1314 le32toh(br->ContainerId), le32toh(br->BlockNumber), 1315 le32toh(br->ByteCount)); 1316 sg = &br->SgMap; 1317 } 1318 if (le32toh(bw->Command) == VM_CtBlockWrite) { 1319 printf(" BlockWrite: container %d 0x%x/%d (%s)\n", 1320 le32toh(bw->ContainerId), le32toh(bw->BlockNumber), 1321 le32toh(bw->ByteCount), 1322 le32toh(bw->Stable) == CSTABLE ? 1323 "stable" : "unstable"); 1324 sg = &bw->SgMap; 1325 } 1326 if (sg != NULL) { 1327 printf(" %d s/g entries\n", le32toh(sg->SgCount)); 1328 for (i = 0; i < le32toh(sg->SgCount); i++) 1329 printf(" 0x%08x/%d\n", 1330 le32toh(sg->SgEntry[i].SgAddress), 1331 le32toh(sg->SgEntry[i].SgByteCount)); 1332 } 1333 break; 1334 } 1335 default: 1336 printf(" %16D\n", fib->data, " "); 1337 printf(" %16D\n", fib->data + 16, " "); 1338 break; 1339 } 1340 } 1341 #endif 1342