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