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