1 /* $NetBSD: aac.c,v 1.1 2002/04/26 02:05:11 ad 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.1 2002/04/26 02:05:11 ad 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 ((*cf->cf_attach->ca_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 le32toh(info->batteryPlatform), 362 info->KernelRevision.external.comp.major, 363 info->KernelRevision.external.comp.minor, 364 info->KernelRevision.external.comp.dash); 365 366 /* Save the kernel revision structure for later use. */ 367 sc->sc_revision = info->KernelRevision; 368 } 369 370 /* 371 * Retrieve the firmware version numbers. Dell PERC2/QC cards with firmware 372 * version 1.x are not compatible with this driver. 373 */ 374 int 375 aac_check_firmware(struct aac_softc *sc) 376 { 377 u_int32_t major, minor; 378 379 if ((sc->sc_quirks & AAC_QUIRK_PERC2QC) != 0) { 380 if (aac_sync_command(sc, AAC_MONKER_GETKERNVER, 0, 0, 0, 0, 381 NULL)) { 382 printf("%s: error reading firmware version\n", 383 sc->sc_dv.dv_xname); 384 return (1); 385 } 386 387 /* These numbers are stored as ASCII! */ 388 major = (AAC_GETREG4(sc, AAC_SA_MAILBOX + 4) & 0xff) - 0x30; 389 minor = (AAC_GETREG4(sc, AAC_SA_MAILBOX + 8) & 0xff) - 0x30; 390 if (major == 1) { 391 printf("%s: firmware version %d.%d not supported.\n", 392 sc->sc_dv.dv_xname, major, minor); 393 return (1); 394 } 395 } 396 397 return (0); 398 } 399 400 int 401 aac_init(struct aac_softc *sc) 402 { 403 int nsegs, i, rv, state, norm, high; 404 struct aac_adapter_init *ip; 405 u_int32_t code; 406 u_int8_t *qaddr; 407 408 state = 0; 409 410 /* 411 * First wait for the adapter to come ready. 412 */ 413 for (i = 0; i < AAC_BOOT_TIMEOUT * 1000; i++) { 414 code = AAC_GET_FWSTATUS(sc); 415 if ((code & AAC_SELF_TEST_FAILED) != 0) { 416 printf("%s: FATAL: selftest failed\n", 417 sc->sc_dv.dv_xname); 418 return (ENXIO); 419 } 420 if ((code & AAC_KERNEL_PANIC) != 0) { 421 printf("%s: FATAL: controller kernel panic\n", 422 sc->sc_dv.dv_xname); 423 return (ENXIO); 424 } 425 if ((code & AAC_UP_AND_RUNNING) != 0) 426 break; 427 DELAY(1000); 428 } 429 if (i == AAC_BOOT_TIMEOUT * 1000) { 430 printf("%s: FATAL: controller not coming ready, status %x\n", 431 sc->sc_dv.dv_xname, code); 432 return (ENXIO); 433 } 434 435 if ((rv = bus_dmamap_create(sc->sc_dmat, sizeof(*sc->sc_common), 1, 436 sizeof(*sc->sc_common), 0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, 437 &sc->sc_common_dmamap)) != 0) { 438 printf("%s: cannot create common dmamap\n", 439 sc->sc_dv.dv_xname); 440 return (rv); 441 } 442 if ((rv = bus_dmamem_alloc(sc->sc_dmat, sizeof(*sc->sc_common), 443 PAGE_SIZE, 0, &sc->sc_common_seg, 1, &nsegs, 444 BUS_DMA_NOWAIT)) != 0) { 445 printf("%s: can't allocate common structure\n", 446 sc->sc_dv.dv_xname); 447 goto bail_out; 448 } 449 state++; 450 if ((rv = bus_dmamem_map(sc->sc_dmat, &sc->sc_common_seg, nsegs, 451 sizeof(*sc->sc_common), (caddr_t *)&sc->sc_common, 0)) != 0) { 452 printf("%s: can't map common structure\n", 453 sc->sc_dv.dv_xname); 454 goto bail_out; 455 } 456 state++; 457 if ((rv = bus_dmamap_load(sc->sc_dmat, sc->sc_common_dmamap, 458 sc->sc_common, sizeof(*sc->sc_common), NULL, 459 BUS_DMA_NOWAIT)) != 0) { 460 printf("%s: cannot load common dmamap\n", sc->sc_dv.dv_xname); 461 goto bail_out; 462 } 463 state++; 464 465 memset(sc->sc_common, 0, sizeof(*sc->sc_common)); 466 467 /* 468 * Fill in the init structure. This tells the adapter about the 469 * physical location of various important shared data structures. 470 */ 471 ip = &sc->sc_common->ac_init; 472 ip->InitStructRevision = htole32(AAC_INIT_STRUCT_REVISION); 473 474 ip->AdapterFibsPhysicalAddress = htole32(sc->sc_common_seg.ds_addr + 475 offsetof(struct aac_common, ac_fibs)); 476 ip->AdapterFibsVirtualAddress = htole32(&sc->sc_common->ac_fibs[0]); 477 ip->AdapterFibsSize = 478 htole32(AAC_ADAPTER_FIBS * sizeof(struct aac_fib)); 479 ip->AdapterFibAlign = htole32(sizeof(struct aac_fib)); 480 481 ip->PrintfBufferAddress = htole32(sc->sc_common_seg.ds_addr + 482 offsetof(struct aac_common, ac_printf)); 483 ip->PrintfBufferSize = htole32(AAC_PRINTF_BUFSIZE); 484 485 ip->HostPhysMemPages = 0; /* not used? */ 486 ip->HostElapsedSeconds = 0; /* reset later if invalid */ 487 488 /* 489 * Initialise FIB queues. Note that it appears that the layout of 490 * the indexes and the segmentation of the entries is mandated by 491 * the adapter, which is only told about the base of the queue index 492 * fields. 493 * 494 * The initial values of the indices are assumed to inform the 495 * adapter of the sizes of the respective queues. 496 * 497 * The Linux driver uses a much more complex scheme whereby several 498 * header records are kept for each queue. We use a couple of 499 * generic list manipulation functions which 'know' the size of each 500 * list by virtue of a table. 501 */ 502 qaddr = &sc->sc_common->ac_qbuf[0] + AAC_QUEUE_ALIGN; 503 qaddr -= (u_int32_t)qaddr % AAC_QUEUE_ALIGN; /* XXX not portable */ 504 sc->sc_queues = (struct aac_queue_table *)qaddr; 505 ip->CommHeaderAddress = htole32(sc->sc_common_seg.ds_addr + 506 ((caddr_t)sc->sc_queues - (caddr_t)sc->sc_common)); 507 memset(sc->sc_queues, 0, sizeof(struct aac_queue_table)); 508 509 norm = htole32(AAC_HOST_NORM_CMD_ENTRIES); 510 high = htole32(AAC_HOST_HIGH_CMD_ENTRIES); 511 512 sc->sc_queues->qt_qindex[AAC_HOST_NORM_CMD_QUEUE][AAC_PRODUCER_INDEX] = 513 norm; 514 sc->sc_queues->qt_qindex[AAC_HOST_NORM_CMD_QUEUE][AAC_CONSUMER_INDEX] = 515 norm; 516 sc->sc_queues->qt_qindex[AAC_HOST_HIGH_CMD_QUEUE][AAC_PRODUCER_INDEX] = 517 high; 518 sc->sc_queues->qt_qindex[AAC_HOST_HIGH_CMD_QUEUE][AAC_CONSUMER_INDEX] = 519 high; 520 521 norm = htole32(AAC_ADAP_NORM_CMD_ENTRIES); 522 high = htole32(AAC_ADAP_HIGH_CMD_ENTRIES); 523 524 sc->sc_queues->qt_qindex[AAC_ADAP_NORM_CMD_QUEUE][AAC_PRODUCER_INDEX] = 525 norm; 526 sc->sc_queues->qt_qindex[AAC_ADAP_NORM_CMD_QUEUE][AAC_CONSUMER_INDEX] = 527 norm; 528 sc->sc_queues->qt_qindex[AAC_ADAP_HIGH_CMD_QUEUE][AAC_PRODUCER_INDEX] = 529 high; 530 sc->sc_queues->qt_qindex[AAC_ADAP_HIGH_CMD_QUEUE][AAC_CONSUMER_INDEX] = 531 high; 532 533 norm = htole32(AAC_HOST_NORM_RESP_ENTRIES); 534 high = htole32(AAC_HOST_HIGH_RESP_ENTRIES); 535 536 sc->sc_queues-> 537 qt_qindex[AAC_HOST_NORM_RESP_QUEUE][AAC_PRODUCER_INDEX] = norm; 538 sc->sc_queues-> 539 qt_qindex[AAC_HOST_NORM_RESP_QUEUE][AAC_CONSUMER_INDEX] = norm; 540 sc->sc_queues-> 541 qt_qindex[AAC_HOST_HIGH_RESP_QUEUE][AAC_PRODUCER_INDEX] = high; 542 sc->sc_queues-> 543 qt_qindex[AAC_HOST_HIGH_RESP_QUEUE][AAC_CONSUMER_INDEX] = high; 544 545 norm = htole32(AAC_ADAP_NORM_RESP_ENTRIES); 546 high = htole32(AAC_ADAP_HIGH_RESP_ENTRIES); 547 548 sc->sc_queues-> 549 qt_qindex[AAC_ADAP_NORM_RESP_QUEUE][AAC_PRODUCER_INDEX] = norm; 550 sc->sc_queues-> 551 qt_qindex[AAC_ADAP_NORM_RESP_QUEUE][AAC_CONSUMER_INDEX] = norm; 552 sc->sc_queues-> 553 qt_qindex[AAC_ADAP_HIGH_RESP_QUEUE][AAC_PRODUCER_INDEX] = high; 554 sc->sc_queues-> 555 qt_qindex[AAC_ADAP_HIGH_RESP_QUEUE][AAC_CONSUMER_INDEX] = high; 556 557 sc->sc_qentries[AAC_HOST_NORM_CMD_QUEUE] = 558 &sc->sc_queues->qt_HostNormCmdQueue[0]; 559 sc->sc_qentries[AAC_HOST_HIGH_CMD_QUEUE] = 560 &sc->sc_queues->qt_HostHighCmdQueue[0]; 561 sc->sc_qentries[AAC_ADAP_NORM_CMD_QUEUE] = 562 &sc->sc_queues->qt_AdapNormCmdQueue[0]; 563 sc->sc_qentries[AAC_ADAP_HIGH_CMD_QUEUE] = 564 &sc->sc_queues->qt_AdapHighCmdQueue[0]; 565 sc->sc_qentries[AAC_HOST_NORM_RESP_QUEUE] = 566 &sc->sc_queues->qt_HostNormRespQueue[0]; 567 sc->sc_qentries[AAC_HOST_HIGH_RESP_QUEUE] = 568 &sc->sc_queues->qt_HostHighRespQueue[0]; 569 sc->sc_qentries[AAC_ADAP_NORM_RESP_QUEUE] = 570 &sc->sc_queues->qt_AdapNormRespQueue[0]; 571 sc->sc_qentries[AAC_ADAP_HIGH_RESP_QUEUE] = 572 &sc->sc_queues->qt_AdapHighRespQueue[0]; 573 574 /* 575 * Do controller-type-specific initialisation 576 */ 577 switch (sc->sc_hwif) { 578 case AAC_HWIF_I960RX: 579 AAC_SETREG4(sc, AAC_RX_ODBR, ~0); 580 break; 581 } 582 583 bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap, 0, 584 sizeof(*sc->sc_common), 585 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 586 587 /* 588 * Give the init structure to the controller. 589 */ 590 if (aac_sync_command(sc, AAC_MONKER_INITSTRUCT, 591 sc->sc_common_seg.ds_addr + offsetof(struct aac_common, ac_init), 592 0, 0, 0, NULL)) { 593 printf("%s: error establishing init structure\n", 594 sc->sc_dv.dv_xname); 595 rv = EIO; 596 goto bail_out; 597 } 598 599 return (0); 600 601 bail_out: 602 if (state > 2) 603 bus_dmamap_unload(sc->sc_dmat, sc->sc_common_dmamap); 604 if (state > 1) 605 bus_dmamem_unmap(sc->sc_dmat, (caddr_t)sc->sc_common, 606 sizeof(*sc->sc_common)); 607 if (state > 0) 608 bus_dmamem_free(sc->sc_dmat, &sc->sc_common_seg, 1); 609 bus_dmamap_destroy(sc->sc_dmat, sc->sc_common_dmamap); 610 611 return (rv); 612 } 613 614 /* 615 * Probe for containers, create disks. 616 */ 617 void 618 aac_startup(struct aac_softc *sc) 619 { 620 struct aac_mntinfo mi; 621 struct aac_mntinforesponse mir; 622 struct aac_drive *hd; 623 u_int16_t rsize; 624 int i; 625 626 /* 627 * Loop over possible containers. 628 */ 629 mi.Command = htole32(VM_NameServe); 630 mi.MntType = htole32(FT_FILESYS); 631 hd = sc->sc_hdr; 632 633 for (i = 0; i < AAC_MAX_CONTAINERS; i++, hd++) { 634 /* 635 * Request information on this container. 636 */ 637 mi.MntCount = htole32(i); 638 if (aac_sync_fib(sc, ContainerCommand, 0, &mi, sizeof(mi), &mir, 639 &rsize)) { 640 printf("%s: error probing container %d\n", 641 sc->sc_dv.dv_xname, i); 642 continue; 643 } 644 if (rsize != sizeof(mir)) { 645 printf("%s: container info response wrong size " 646 "(%d should be %d)\n", 647 sc->sc_dv.dv_xname, rsize, sizeof(mir)); 648 continue; 649 } 650 651 /* 652 * Check container volume type for validity. Note that many 653 * of the possible types may never show up. 654 */ 655 if (le32toh(mir.Status) != ST_OK || 656 le32toh(mir.MntTable[0].VolType) == CT_NONE) 657 continue; 658 659 hd->hd_present = 1; 660 hd->hd_size = le32toh(mir.MntTable[0].Capacity); 661 hd->hd_devtype = le32toh(mir.MntTable[0].VolType); 662 hd->hd_size &= ~0x1f; 663 sc->sc_nunits++; 664 } 665 } 666 667 void 668 aac_shutdown(void *cookie) 669 { 670 struct aac_softc *sc; 671 struct aac_close_command cc; 672 u_int32_t i; 673 674 for (i = 0; i < aac_cd.cd_ndevs; i++) { 675 if ((sc = device_lookup(&aac_cd, i)) == NULL) 676 continue; 677 if ((sc->sc_flags & AAC_ONLINE) == 0) 678 continue; 679 680 AAC_MASK_INTERRUPTS(sc); 681 682 /* 683 * Send a Container shutdown followed by a HostShutdown FIB 684 * to the controller to convince it that we don't want to 685 * talk to it anymore. We've been closed and all I/O 686 * completed already 687 */ 688 cc.Command = htole32(VM_CloseAll); 689 cc.ContainerId = 0xffffffff; 690 if (aac_sync_fib(sc, ContainerCommand, 0, &cc, sizeof(cc), 691 NULL, NULL)) { 692 printf("%s: unable to halt controller\n", 693 sc->sc_dv.dv_xname); 694 continue; 695 } 696 697 /* 698 * Note that issuing this command to the controller makes it 699 * shut down but also keeps it from coming back up without a 700 * reset of the PCI bus. 701 */ 702 if (aac_sync_fib(sc, FsaHostShutdown, AAC_FIBSTATE_SHUTDOWN, 703 &i, sizeof(i), NULL, NULL)) 704 printf("%s: unable to halt controller\n", 705 sc->sc_dv.dv_xname); 706 } 707 } 708 709 /* 710 * Take an interrupt. 711 */ 712 int 713 aac_intr(void *cookie) 714 { 715 struct aac_softc *sc; 716 u_int16_t reason; 717 int claimed; 718 719 sc = cookie; 720 claimed = 0; 721 722 AAC_DPRINTF(AAC_D_INTR, ("aac_intr(%p) ", sc)); 723 724 reason = AAC_GET_ISTATUS(sc); 725 AAC_DPRINTF(AAC_D_INTR, ("istatus 0x%04x ", reason)); 726 727 /* 728 * Controller wants to talk to the log. XXX Should we defer this? 729 */ 730 if ((reason & AAC_DB_PRINTF) != 0) { 731 if (sc->sc_common->ac_printf[0] != '\0') { 732 printf("%s: WARNING: adapter logged message:\n", 733 sc->sc_dv.dv_xname); 734 printf("%s: %.*s", sc->sc_dv.dv_xname, 735 AAC_PRINTF_BUFSIZE, sc->sc_common->ac_printf); 736 sc->sc_common->ac_printf[0] = '\0'; 737 } 738 AAC_CLEAR_ISTATUS(sc, AAC_DB_PRINTF); 739 AAC_QNOTIFY(sc, AAC_DB_PRINTF); 740 claimed = 1; 741 } 742 743 /* 744 * Controller has a message for us? 745 */ 746 if ((reason & AAC_DB_COMMAND_READY) != 0) { 747 aac_host_command(sc); 748 AAC_CLEAR_ISTATUS(sc, AAC_DB_COMMAND_READY); 749 claimed = 1; 750 } 751 752 /* 753 * Controller has a response for us? 754 */ 755 if ((reason & AAC_DB_RESPONSE_READY) != 0) { 756 aac_host_response(sc); 757 AAC_CLEAR_ISTATUS(sc, AAC_DB_RESPONSE_READY); 758 claimed = 1; 759 } 760 761 /* 762 * Spurious interrupts that we don't use - reset the mask and clear 763 * the interrupts. 764 */ 765 if ((reason & (AAC_DB_SYNC_COMMAND | AAC_DB_COMMAND_NOT_FULL | 766 AAC_DB_RESPONSE_NOT_FULL)) != 0) { 767 AAC_UNMASK_INTERRUPTS(sc); 768 AAC_CLEAR_ISTATUS(sc, AAC_DB_SYNC_COMMAND | 769 AAC_DB_COMMAND_NOT_FULL | AAC_DB_RESPONSE_NOT_FULL); 770 claimed = 1; 771 } 772 773 return (claimed); 774 } 775 776 /* 777 * Handle notification of one or more FIBs coming from the controller. 778 */ 779 void 780 aac_host_command(struct aac_softc *sc) 781 { 782 struct aac_fib *fib; 783 u_int32_t fib_size; 784 785 for (;;) { 786 if (aac_dequeue_fib(sc, AAC_HOST_NORM_CMD_QUEUE, &fib_size, 787 &fib)) 788 break; /* nothing to do */ 789 790 bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap, 791 (caddr_t)fib - (caddr_t)sc->sc_common, sizeof(*fib), 792 BUS_DMASYNC_POSTREAD); 793 794 switch (le16toh(fib->Header.Command)) { 795 case AifRequest: 796 #ifdef notyet 797 aac_handle_aif(sc, 798 (struct aac_aif_command *)&fib->data[0]); 799 #endif 800 break; 801 default: 802 printf("%s: unknown command from controller\n", 803 sc->sc_dv.dv_xname); 804 AAC_PRINT_FIB(sc, fib); 805 break; 806 } 807 808 bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap, 809 (caddr_t)fib - (caddr_t)sc->sc_common, sizeof(*fib), 810 BUS_DMASYNC_PREREAD); 811 812 /* XXX reply to FIBs requesting responses ?? */ 813 /* XXX how do we return these FIBs to the controller? */ 814 } 815 } 816 817 /* 818 * Handle notification of one or more FIBs completed by the controller 819 */ 820 void 821 aac_host_response(struct aac_softc *sc) 822 { 823 struct aac_ccb *ac; 824 struct aac_fib *fib; 825 u_int32_t fib_size; 826 827 /* 828 * Look for completed FIBs on our queue. 829 */ 830 for (;;) { 831 if (aac_dequeue_fib(sc, AAC_HOST_NORM_RESP_QUEUE, &fib_size, 832 &fib)) 833 break; /* nothing to do */ 834 835 bus_dmamap_sync(sc->sc_dmat, sc->sc_fibs_dmamap, 836 (caddr_t)fib - (caddr_t)sc->sc_fibs, sizeof(*fib), 837 BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD); 838 839 if ((fib->Header.SenderData & 0x80000000) == 0) { 840 /* Not valid; not sent by us. */ 841 AAC_PRINT_FIB(sc, fib); 842 } else { 843 ac = (struct aac_ccb *)((caddr_t)sc->sc_ccbs + 844 (fib->Header.SenderData & 0x7fffffff)); 845 fib->Header.SenderData = 0; 846 SIMPLEQ_INSERT_TAIL(&sc->sc_ccb_complete, ac, ac_chain); 847 } 848 } 849 850 /* 851 * Deal with any completed commands. 852 */ 853 while ((ac = SIMPLEQ_FIRST(&sc->sc_ccb_complete)) != NULL) { 854 SIMPLEQ_REMOVE_HEAD(&sc->sc_ccb_complete, ac, ac_chain); 855 ac->ac_flags |= AAC_CCB_COMPLETED; 856 857 if (ac->ac_intr != NULL) 858 (*ac->ac_intr)(ac); 859 } 860 861 /* 862 * Try to submit more commands. 863 */ 864 if (SIMPLEQ_FIRST(&sc->sc_ccb_queue) != NULL) 865 aac_ccb_enqueue(sc, NULL); 866 } 867 868 /* 869 * Send a synchronous command to the controller and wait for a result. 870 */ 871 int 872 aac_sync_command(struct aac_softc *sc, u_int32_t command, u_int32_t arg0, 873 u_int32_t arg1, u_int32_t arg2, u_int32_t arg3, u_int32_t *sp) 874 { 875 int i; 876 u_int32_t status; 877 int s; 878 879 s = splbio(); 880 881 /* Populate the mailbox. */ 882 AAC_SET_MAILBOX(sc, command, arg0, arg1, arg2, arg3); 883 884 /* Ensure the sync command doorbell flag is cleared. */ 885 AAC_CLEAR_ISTATUS(sc, AAC_DB_SYNC_COMMAND); 886 887 /* ... then set it to signal the adapter. */ 888 AAC_QNOTIFY(sc, AAC_DB_SYNC_COMMAND); 889 DELAY(AAC_SYNC_DELAY); 890 891 /* Spin waiting for the command to complete. */ 892 for (i = 0; i < AAC_IMMEDIATE_TIMEOUT * 1000; i++) { 893 if (AAC_GET_ISTATUS(sc) & AAC_DB_SYNC_COMMAND); 894 break; 895 DELAY(1000); 896 } 897 if (i == AAC_IMMEDIATE_TIMEOUT * 1000) { 898 splx(s); 899 return (EIO); 900 } 901 902 /* Clear the completion flag. */ 903 AAC_CLEAR_ISTATUS(sc, AAC_DB_SYNC_COMMAND); 904 905 /* Get the command status. */ 906 status = AAC_GET_MAILBOXSTATUS(sc); 907 splx(s); 908 if (sp != NULL) 909 *sp = status; 910 911 return (0); /* XXX Check command return status? */ 912 } 913 914 /* 915 * Send a synchronous FIB to the controller and wait for a result. 916 */ 917 int 918 aac_sync_fib(struct aac_softc *sc, u_int32_t command, u_int32_t xferstate, 919 void *data, u_int16_t datasize, void *result, 920 u_int16_t *resultsize) 921 { 922 struct aac_fib *fib; 923 u_int32_t fibpa, status; 924 925 fib = &sc->sc_common->ac_sync_fib; 926 fibpa = sc->sc_common_seg.ds_addr + 927 offsetof(struct aac_common, ac_sync_fib); 928 929 if (datasize > AAC_FIB_DATASIZE) 930 return (EINVAL); 931 932 /* 933 * Set up the sync FIB. 934 */ 935 fib->Header.XferState = htole32(AAC_FIBSTATE_HOSTOWNED | 936 AAC_FIBSTATE_INITIALISED | AAC_FIBSTATE_EMPTY | xferstate); 937 fib->Header.Command = htole16(command); 938 fib->Header.StructType = AAC_FIBTYPE_TFIB; 939 fib->Header.Size = htole16(sizeof(*fib) + datasize); 940 fib->Header.SenderSize = htole16(sizeof(*fib)); 941 fib->Header.SenderFibAddress = htole32((u_int32_t)fib); /* XXX */ 942 fib->Header.ReceiverFibAddress = htole32(fibpa); 943 944 /* 945 * Copy in data. 946 */ 947 if (data != NULL) { 948 memcpy(fib->data, data, datasize); 949 fib->Header.XferState |= 950 htole32(AAC_FIBSTATE_FROMHOST | AAC_FIBSTATE_NORM); 951 } 952 953 bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap, 954 (caddr_t)fib - (caddr_t)sc->sc_common, sizeof(*fib), 955 BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); 956 957 /* 958 * Give the FIB to the controller, wait for a response. 959 */ 960 if (aac_sync_command(sc, AAC_MONKER_SYNCFIB, fibpa, 0, 0, 0, &status)) 961 return (EIO); 962 963 bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap, 964 (caddr_t)fib - (caddr_t)sc->sc_common, sizeof(*fib), 965 BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD); 966 967 /* 968 * Copy out the result 969 */ 970 if (result != NULL) { 971 *resultsize = le16toh(fib->Header.Size) - sizeof(fib->Header); 972 memcpy(result, fib->data, *resultsize); 973 } 974 975 return (0); 976 } 977 978 struct aac_ccb * 979 aac_ccb_alloc(struct aac_softc *sc, int flags) 980 { 981 struct aac_ccb *ac; 982 int s; 983 984 AAC_DPRINTF(AAC_D_QUEUE, ("aac_ccb_alloc(%p, 0x%x) ", sc, flags)); 985 986 s = splbio(); 987 ac = SIMPLEQ_FIRST(&sc->sc_ccb_free); 988 #ifdef DIAGNOSTIC 989 if (ac == NULL) 990 panic("aac_ccb_get: no free CCBS"); 991 #endif 992 SIMPLEQ_REMOVE_HEAD(&sc->sc_ccb_free, ac, ac_chain); 993 splx(s); 994 995 ac->ac_flags = flags; 996 return (ac); 997 } 998 999 void 1000 aac_ccb_free(struct aac_softc *sc, struct aac_ccb *ac) 1001 { 1002 int s; 1003 1004 AAC_DPRINTF(AAC_D_QUEUE, ("aac_ccb_free(%p, %p) ", sc, ac)); 1005 1006 ac->ac_flags = 0; 1007 ac->ac_intr = NULL; 1008 ac->ac_fib->Header.XferState = htole32(AAC_FIBSTATE_EMPTY); 1009 ac->ac_fib->Header.StructType = AAC_FIBTYPE_TFIB; 1010 ac->ac_fib->Header.Flags = 0; 1011 ac->ac_fib->Header.SenderSize = htole16(sizeof(*ac->ac_fib)); 1012 1013 #ifdef AAC_DEBUG 1014 /* 1015 * These are duplicated in aac_ccb_submit() to cover the case where 1016 * an intermediate stage may have destroyed them. They're left 1017 * initialised here for debugging purposes only. 1018 */ 1019 ac->ac_fib->Header.SenderFibAddress = htole32((u_int32_t)ac->ac_fib); 1020 ac->ac_fib->Header.ReceiverFibAddress = htole32(ac->ac_fibphys); 1021 #endif 1022 1023 s = splbio(); 1024 SIMPLEQ_INSERT_HEAD(&sc->sc_ccb_free, ac, ac_chain); 1025 splx(s); 1026 } 1027 1028 int 1029 aac_ccb_map(struct aac_softc *sc, struct aac_ccb *ac) 1030 { 1031 int error; 1032 1033 AAC_DPRINTF(AAC_D_QUEUE, ("aac_ccb_map(%p, %p) ", sc, ac)); 1034 1035 #ifdef DIAGNOSTIC 1036 if ((ac->ac_flags & AAC_CCB_MAPPED) != 0) 1037 panic("aac_ccb_map: already mapped"); 1038 #endif 1039 1040 error = bus_dmamap_load(sc->sc_dmat, ac->ac_dmamap_xfer, ac->ac_data, 1041 ac->ac_datalen, NULL, BUS_DMA_NOWAIT | BUS_DMA_STREAMING | 1042 ((ac->ac_flags & AAC_CCB_DATA_IN) ? BUS_DMA_READ : BUS_DMA_WRITE)); 1043 if (error) { 1044 printf("%s: aac_ccb_map: ", sc->sc_dv.dv_xname); 1045 if (error == EFBIG) 1046 printf("more than %d dma segs\n", AAC_MAX_SGENTRIES); 1047 else 1048 printf("error %d loading dma map\n", error); 1049 return (error); 1050 } 1051 1052 bus_dmamap_sync(sc->sc_dmat, ac->ac_dmamap_xfer, 0, ac->ac_datalen, 1053 (ac->ac_flags & AAC_CCB_DATA_IN) ? BUS_DMASYNC_PREREAD : 1054 BUS_DMASYNC_PREWRITE); 1055 1056 #ifdef DIAGNOSTIC 1057 ac->ac_flags |= AAC_CCB_MAPPED; 1058 #endif 1059 return (0); 1060 } 1061 1062 void 1063 aac_ccb_unmap(struct aac_softc *sc, struct aac_ccb *ac) 1064 { 1065 1066 AAC_DPRINTF(AAC_D_QUEUE, ("aac_ccb_unmap(%p, %p) ", sc, ac)); 1067 1068 #ifdef DIAGNOSTIC 1069 if ((ac->ac_flags & AAC_CCB_MAPPED) == 0) 1070 panic("aac_ccb_unmap: not mapped"); 1071 #endif 1072 1073 bus_dmamap_sync(sc->sc_dmat, ac->ac_dmamap_xfer, 0, ac->ac_datalen, 1074 (ac->ac_flags & AAC_CCB_DATA_IN) ? BUS_DMASYNC_POSTREAD : 1075 BUS_DMASYNC_POSTWRITE); 1076 bus_dmamap_unload(sc->sc_dmat, ac->ac_dmamap_xfer); 1077 1078 #ifdef DIAGNOSTIC 1079 ac->ac_flags &= ~AAC_CCB_MAPPED; 1080 #endif 1081 } 1082 1083 void 1084 aac_ccb_enqueue(struct aac_softc *sc, struct aac_ccb *ac) 1085 { 1086 int s; 1087 1088 AAC_DPRINTF(AAC_D_QUEUE, ("aac_ccb_enqueue(%p, %p) ", sc, ac)); 1089 1090 s = splbio(); 1091 1092 if (ac != NULL) 1093 SIMPLEQ_INSERT_TAIL(&sc->sc_ccb_queue, ac, ac_chain); 1094 1095 while ((ac = SIMPLEQ_FIRST(&sc->sc_ccb_queue)) != NULL) { 1096 if (aac_ccb_submit(sc, ac)) 1097 break; 1098 SIMPLEQ_REMOVE_HEAD(&sc->sc_ccb_queue, ac, ac_chain); 1099 } 1100 1101 splx(s); 1102 } 1103 1104 int 1105 aac_ccb_submit(struct aac_softc *sc, struct aac_ccb *ac) 1106 { 1107 1108 AAC_DPRINTF(AAC_D_QUEUE, ("aac_ccb_submit(%p, %p) ", sc, ac)); 1109 1110 /* Fix up the address values. */ 1111 ac->ac_fib->Header.SenderFibAddress = htole32((u_int32_t)ac->ac_fib); 1112 ac->ac_fib->Header.ReceiverFibAddress = htole32(ac->ac_fibphys); 1113 1114 /* Save a pointer to the command for speedy reverse-lookup. */ 1115 ac->ac_fib->Header.SenderData = 1116 (u_int32_t)((caddr_t)ac - (caddr_t)sc->sc_ccbs) | 0x80000000; 1117 1118 bus_dmamap_sync(sc->sc_dmat, sc->sc_fibs_dmamap, 1119 (caddr_t)ac->ac_fib - (caddr_t)sc->sc_fibs, sizeof(*ac->ac_fib), 1120 BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); 1121 1122 /* Put the FIB on the outbound queue. */ 1123 return (aac_enqueue_fib(sc, AAC_ADAP_NORM_CMD_QUEUE, ac->ac_fib)); 1124 } 1125 1126 int 1127 aac_ccb_poll(struct aac_softc *sc, struct aac_ccb *ac, int timo) 1128 { 1129 int rv, s; 1130 1131 AAC_DPRINTF(AAC_D_QUEUE, ("aac_ccb_poll(%p, %p, %d) ", sc, ac, timo)); 1132 1133 s = splbio(); 1134 1135 if ((rv = aac_ccb_submit(sc, ac)) != 0) { 1136 splx(s); 1137 return (rv); 1138 } 1139 1140 for (timo *= 1000; timo != 0; timo--) { 1141 aac_intr(sc); 1142 if ((ac->ac_flags & AAC_CCB_COMPLETED) != 0) 1143 break; 1144 DELAY(100); 1145 } 1146 1147 splx(s); 1148 return (timo == 0); 1149 } 1150 1151 /* 1152 * Atomically insert an entry into the nominated queue, returns 0 on success 1153 * or EBUSY if the queue is full. 1154 * 1155 * XXX Note that it would be more efficient to defer notifying the 1156 * controller in the case where we may be inserting several entries in rapid 1157 * succession, but implementing this usefully is difficult. 1158 */ 1159 int 1160 aac_enqueue_fib(struct aac_softc *sc, int queue, struct aac_fib *fib) 1161 { 1162 u_int32_t fib_size, fib_addr, pi, ci; 1163 1164 fib_size = le16toh(fib->Header.Size); 1165 fib_addr = le32toh(fib->Header.ReceiverFibAddress); 1166 1167 bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap, 1168 (caddr_t)sc->sc_common->ac_qbuf - (caddr_t)sc->sc_common, 1169 sizeof(sc->sc_common->ac_qbuf), 1170 BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD); 1171 1172 /* Get the producer/consumer indices. */ 1173 pi = le32toh(sc->sc_queues->qt_qindex[queue][AAC_PRODUCER_INDEX]); 1174 ci = le32toh(sc->sc_queues->qt_qindex[queue][AAC_CONSUMER_INDEX]); 1175 1176 /* Wrap the queue? */ 1177 if (pi >= aac_qinfo[queue].size) 1178 pi = 0; 1179 1180 /* Check for queue full. */ 1181 if ((pi + 1) == ci) 1182 return (EAGAIN); 1183 1184 /* Populate queue entry. */ 1185 (sc->sc_qentries[queue] + pi)->aq_fib_size = htole32(fib_size); 1186 (sc->sc_qentries[queue] + pi)->aq_fib_addr = htole32(fib_addr); 1187 1188 /* Update producer index. */ 1189 sc->sc_queues->qt_qindex[queue][AAC_PRODUCER_INDEX] = htole32(pi + 1); 1190 1191 bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap, 1192 (caddr_t)sc->sc_common->ac_qbuf - (caddr_t)sc->sc_common, 1193 sizeof(sc->sc_common->ac_qbuf), 1194 BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); 1195 1196 /* Notify the adapter if we know how. */ 1197 if (aac_qinfo[queue].notify != 0) 1198 AAC_QNOTIFY(sc, aac_qinfo[queue].notify); 1199 1200 return (0); 1201 } 1202 1203 /* 1204 * Atomically remove one entry from the nominated queue, returns 0 on success 1205 * or ENOENT if the queue is empty. 1206 */ 1207 int 1208 aac_dequeue_fib(struct aac_softc *sc, int queue, u_int32_t *fib_size, 1209 struct aac_fib **fib_addr) 1210 { 1211 u_int32_t pi, ci; 1212 int notify; 1213 1214 bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap, 1215 (caddr_t)sc->sc_common->ac_qbuf - (caddr_t)sc->sc_common, 1216 sizeof(sc->sc_common->ac_qbuf), 1217 BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD); 1218 1219 /* Get the producer/consumer indices. */ 1220 pi = le32toh(sc->sc_queues->qt_qindex[queue][AAC_PRODUCER_INDEX]); 1221 ci = le32toh(sc->sc_queues->qt_qindex[queue][AAC_CONSUMER_INDEX]); 1222 1223 /* Check for queue empty. */ 1224 if (ci == pi) 1225 return (ENOENT); 1226 1227 notify = 0; 1228 if (ci == pi + 1) 1229 notify = 1; 1230 1231 /* Wrap the queue? */ 1232 if (ci >= aac_qinfo[queue].size) 1233 ci = 0; 1234 1235 /* Fetch the entry. */ 1236 *fib_size = le32toh((sc->sc_qentries[queue] + ci)->aq_fib_size); 1237 *fib_addr = le32toh((struct aac_fib *) 1238 (sc->sc_qentries[queue] + ci)->aq_fib_addr); 1239 1240 /* Update consumer index. */ 1241 sc->sc_queues->qt_qindex[queue][AAC_CONSUMER_INDEX] = ci + 1; 1242 1243 bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap, 1244 (caddr_t)sc->sc_common->ac_qbuf - (caddr_t)sc->sc_common, 1245 sizeof(sc->sc_common->ac_qbuf), 1246 BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); 1247 1248 /* If we have made the queue un-full, notify the adapter. */ 1249 if (notify && (aac_qinfo[queue].notify != 0)) 1250 AAC_QNOTIFY(sc, aac_qinfo[queue].notify); 1251 1252 return (0); 1253 } 1254 1255 #ifdef AAC_DEBUG 1256 /* 1257 * Print a FIB 1258 */ 1259 void 1260 aac_print_fib(struct aac_softc *sc, struct aac_fib *fib, char *caller) 1261 { 1262 struct aac_blockread *br; 1263 struct aac_blockwrite *bw; 1264 struct aac_sg_table *sg; 1265 char buf[512]; 1266 int i; 1267 1268 printf("%s: FIB @ %p\n", caller, fib); 1269 bitmask_snprintf(le32toh(fib->Header.XferState), 1270 "\20" 1271 "\1HOSTOWNED" 1272 "\2ADAPTEROWNED" 1273 "\3INITIALISED" 1274 "\4EMPTY" 1275 "\5FROMPOOL" 1276 "\6FROMHOST" 1277 "\7FROMADAP" 1278 "\10REXPECTED" 1279 "\11RNOTEXPECTED" 1280 "\12DONEADAP" 1281 "\13DONEHOST" 1282 "\14HIGH" 1283 "\15NORM" 1284 "\16ASYNC" 1285 "\17PAGEFILEIO" 1286 "\20SHUTDOWN" 1287 "\21LAZYWRITE" 1288 "\22ADAPMICROFIB" 1289 "\23BIOSFIB" 1290 "\24FAST_RESPONSE" 1291 "\25APIFIB\n", 1292 buf, 1293 sizeof(buf)); 1294 1295 printf(" XferState %s\n", buf); 1296 printf(" Command %d\n", le16toh(fib->Header.Command)); 1297 printf(" StructType %d\n", fib->Header.StructType); 1298 printf(" Flags 0x%x\n", fib->Header.Flags); 1299 printf(" Size %d\n", le16toh(fib->Header.Size)); 1300 printf(" SenderSize %d\n", le16toh(fib->Header.SenderSize)); 1301 printf(" SenderAddress 0x%x\n", 1302 le32toh(fib->Header.SenderFibAddress)); 1303 printf(" ReceiverAddress 0x%x\n", 1304 le32toh(fib->Header.ReceiverFibAddress)); 1305 printf(" SenderData 0x%x\n", fib->Header.SenderData); 1306 1307 switch (fib->Header.Command) { 1308 case ContainerCommand: { 1309 br = (struct aac_blockread *)fib->data; 1310 bw = (struct aac_blockwrite *)fib->data; 1311 sg = NULL; 1312 1313 if (le32toh(br->Command) == VM_CtBlockRead) { 1314 printf(" BlockRead: container %d 0x%x/%d\n", 1315 le32toh(br->ContainerId), le32toh(br->BlockNumber), 1316 le32toh(br->ByteCount)); 1317 sg = &br->SgMap; 1318 } 1319 if (le32toh(bw->Command) == VM_CtBlockWrite) { 1320 printf(" BlockWrite: container %d 0x%x/%d (%s)\n", 1321 le32toh(bw->ContainerId), le32toh(bw->BlockNumber), 1322 le32toh(bw->ByteCount), 1323 le32toh(bw->Stable) == CSTABLE ? 1324 "stable" : "unstable"); 1325 sg = &bw->SgMap; 1326 } 1327 if (sg != NULL) { 1328 printf(" %d s/g entries\n", le32toh(sg->SgCount)); 1329 for (i = 0; i < le32toh(sg->SgCount); i++) 1330 printf(" 0x%08x/%d\n", 1331 le32toh(sg->SgEntry[i].SgAddress), 1332 le32toh(sg->SgEntry[i].SgByteCount)); 1333 } 1334 break; 1335 } 1336 default: 1337 printf(" %16D\n", fib->data, " "); 1338 printf(" %16D\n", fib->data + 16, " "); 1339 break; 1340 } 1341 } 1342 #endif 1343