1 /* $NetBSD: aac.c,v 1.39 2008/04/28 20:23:48 martin Exp $ */ 2 3 /*- 4 * Copyright (c) 2002, 2007 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 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 /*- 33 * Copyright (c) 2001 Scott Long 34 * Copyright (c) 2001 Adaptec, Inc. 35 * Copyright (c) 2000 Michael Smith 36 * Copyright (c) 2000 BSDi 37 * Copyright (c) 2000 Niklas Hallqvist 38 * All rights reserved. 39 * 40 * Redistribution and use in source and binary forms, with or without 41 * modification, are permitted provided that the following conditions 42 * are met: 43 * 1. Redistributions of source code must retain the above copyright 44 * notice, this list of conditions and the following disclaimer. 45 * 2. Redistributions in binary form must reproduce the above copyright 46 * notice, this list of conditions and the following disclaimer in the 47 * documentation and/or other materials provided with the distribution. 48 * 49 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 50 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 51 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 52 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 53 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 54 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 55 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 56 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 57 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 58 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 59 * SUCH DAMAGE. 60 */ 61 62 /* 63 * Driver for the Adaptec 'FSA' family of PCI/SCSI RAID adapters. 64 * 65 * TODO: 66 * 67 * o Management interface. 68 * o Look again at some of the portability issues. 69 * o Handle various AIFs (e.g., notification that a container is going away). 70 */ 71 72 #include <sys/cdefs.h> 73 __KERNEL_RCSID(0, "$NetBSD: aac.c,v 1.39 2008/04/28 20:23:48 martin Exp $"); 74 75 #include <sys/param.h> 76 #include <sys/systm.h> 77 #include <sys/buf.h> 78 #include <sys/device.h> 79 #include <sys/kernel.h> 80 #include <sys/malloc.h> 81 #include <sys/proc.h> 82 83 #include <sys/bus.h> 84 85 #include <uvm/uvm_extern.h> 86 87 #include <dev/ic/aacreg.h> 88 #include <dev/ic/aacvar.h> 89 #include <dev/ic/aac_tables.h> 90 91 #include "locators.h" 92 93 static int aac_new_intr(void *); 94 static int aac_alloc_commands(struct aac_softc *); 95 #ifdef notyet 96 static void aac_free_commands(struct aac_softc *); 97 #endif 98 static int aac_check_firmware(struct aac_softc *); 99 static void aac_describe_controller(struct aac_softc *); 100 static int aac_dequeue_fib(struct aac_softc *, int, u_int32_t *, 101 struct aac_fib **); 102 static int aac_enqueue_fib(struct aac_softc *, int, struct aac_ccb *); 103 static int aac_enqueue_response(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 115 #ifdef AAC_DEBUG 116 static void aac_print_fib(struct aac_softc *, struct aac_fib *, const char *); 117 #endif 118 119 /* 120 * Adapter-space FIB queue manipulation. 121 * 122 * Note that the queue implementation here is a little funky; neither the PI or 123 * CI will ever be zero. This behaviour is a controller feature. 124 */ 125 static struct { 126 int size; 127 int notify; 128 } const aac_qinfo[] = { 129 { AAC_HOST_NORM_CMD_ENTRIES, AAC_DB_COMMAND_NOT_FULL }, 130 { AAC_HOST_HIGH_CMD_ENTRIES, 0 }, 131 { AAC_ADAP_NORM_CMD_ENTRIES, AAC_DB_COMMAND_READY }, 132 { AAC_ADAP_HIGH_CMD_ENTRIES, 0 }, 133 { AAC_HOST_NORM_RESP_ENTRIES, AAC_DB_RESPONSE_NOT_FULL }, 134 { AAC_HOST_HIGH_RESP_ENTRIES, 0 }, 135 { AAC_ADAP_NORM_RESP_ENTRIES, AAC_DB_RESPONSE_READY }, 136 { AAC_ADAP_HIGH_RESP_ENTRIES, 0 } 137 }; 138 139 #ifdef AAC_DEBUG 140 int aac_debug = AAC_DEBUG; 141 #endif 142 143 MALLOC_DEFINE(M_AACBUF, "aacbuf", "Buffers for aac(4)"); 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 i, rv; 154 int locs[AACCF_NLOCS]; 155 156 SIMPLEQ_INIT(&sc->sc_ccb_free); 157 SIMPLEQ_INIT(&sc->sc_ccb_queue); 158 SIMPLEQ_INIT(&sc->sc_ccb_complete); 159 160 /* 161 * Disable interrupts before we do anything. 162 */ 163 AAC_MASK_INTERRUPTS(sc); 164 165 /* 166 * Initialise the adapter. 167 */ 168 if (aac_check_firmware(sc)) 169 return (EINVAL); 170 171 if ((rv = aac_init(sc)) != 0) 172 return (rv); 173 174 if (sc->sc_quirks & AAC_QUIRK_NEW_COMM) { 175 rv = sc->sc_intr_set(sc, aac_new_intr, sc); 176 if (rv) 177 return (rv); 178 } 179 180 aac_startup(sc); 181 182 /* 183 * Print a little information about the controller. 184 */ 185 aac_describe_controller(sc); 186 187 /* 188 * Attach devices. 189 */ 190 for (i = 0; i < AAC_MAX_CONTAINERS; i++) { 191 if (!sc->sc_hdr[i].hd_present) 192 continue; 193 aaca.aaca_unit = i; 194 195 locs[AACCF_UNIT] = i; 196 197 config_found_sm_loc(&sc->sc_dv, "aac", locs, &aaca, 198 aac_print, config_stdsubmatch); 199 } 200 201 /* 202 * Enable interrupts, and register our shutdown hook. 203 */ 204 sc->sc_flags |= AAC_ONLINE; 205 AAC_UNMASK_INTERRUPTS(sc); 206 if (aac_sdh != NULL) 207 shutdownhook_establish(aac_shutdown, NULL); 208 return (0); 209 } 210 211 static int 212 aac_alloc_commands(struct aac_softc *sc) 213 { 214 struct aac_fibmap *fm; 215 struct aac_ccb *ac; 216 bus_addr_t fibpa; 217 int size, nsegs; 218 int i, error; 219 int state; 220 221 if (sc->sc_total_fibs + sc->sc_max_fibs_alloc > sc->sc_max_fibs) 222 return ENOMEM; 223 224 fm = malloc(sizeof(struct aac_fibmap), M_AACBUF, M_NOWAIT|M_ZERO); 225 if (fm == NULL) 226 return ENOMEM; 227 228 size = sc->sc_max_fibs_alloc * sc->sc_max_fib_size; 229 230 state = 0; 231 error = bus_dmamap_create(sc->sc_dmat, size, 1, size, 232 0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &fm->fm_fibmap); 233 if (error != 0) { 234 aprint_error_dev(&sc->sc_dv, "cannot create fibs dmamap (%d)\n", 235 error); 236 goto bail_out; 237 } 238 state++; 239 error = bus_dmamem_alloc(sc->sc_dmat, size, PAGE_SIZE, 0, 240 &fm->fm_fibseg, 1, &nsegs, BUS_DMA_NOWAIT); 241 if (error != 0) { 242 aprint_error_dev(&sc->sc_dv, "can't allocate fibs structure (%d)\n", 243 error); 244 goto bail_out; 245 } 246 state++; 247 error = bus_dmamem_map(sc->sc_dmat, &fm->fm_fibseg, nsegs, size, 248 (void **)&fm->fm_fibs, 0); 249 if (error != 0) { 250 aprint_error_dev(&sc->sc_dv, "can't map fibs structure (%d)\n", 251 error); 252 goto bail_out; 253 } 254 state++; 255 error = bus_dmamap_load(sc->sc_dmat, fm->fm_fibmap, fm->fm_fibs, 256 size, NULL, BUS_DMA_NOWAIT); 257 if (error != 0) { 258 aprint_error_dev(&sc->sc_dv, "cannot load fibs dmamap (%d)\n", 259 error); 260 goto bail_out; 261 } 262 263 fm->fm_ccbs = sc->sc_ccbs + sc->sc_total_fibs; 264 fibpa = fm->fm_fibseg.ds_addr; 265 266 memset(fm->fm_fibs, 0, size); 267 for (i = 0; i < sc->sc_max_fibs_alloc; i++) { 268 ac = fm->fm_ccbs + i; 269 270 error = bus_dmamap_create(sc->sc_dmat, AAC_MAX_XFER(sc), 271 sc->sc_max_sgs, AAC_MAX_XFER(sc), 0, 272 BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &ac->ac_dmamap_xfer); 273 if (error) { 274 while (--i >= 0) { 275 ac = fm->fm_ccbs + i; 276 bus_dmamap_destroy(sc->sc_dmat, 277 ac->ac_dmamap_xfer); 278 sc->sc_total_fibs--; 279 } 280 aprint_error_dev(&sc->sc_dv, "cannot create ccb dmamap (%d)", 281 error); 282 goto bail_out; 283 } 284 285 ac->ac_fibmap = fm; 286 ac->ac_fib = (struct aac_fib *) 287 ((char *) fm->fm_fibs + i * sc->sc_max_fib_size); 288 ac->ac_fibphys = fibpa + i * sc->sc_max_fib_size; 289 aac_ccb_free(sc, ac); 290 sc->sc_total_fibs++; 291 } 292 293 TAILQ_INSERT_TAIL(&sc->sc_fibmap_tqh, fm, fm_link); 294 295 return 0; 296 bail_out: 297 if (state > 3) 298 bus_dmamap_unload(sc->sc_dmat, fm->fm_fibmap); 299 if (state > 2) 300 bus_dmamem_unmap(sc->sc_dmat, (void *) fm->fm_fibs, size); 301 if (state > 1) 302 bus_dmamem_free(sc->sc_dmat, &fm->fm_fibseg, 1); 303 304 bus_dmamap_destroy(sc->sc_dmat, fm->fm_fibmap); 305 306 free(fm, M_AACBUF); 307 308 return error; 309 } 310 311 #ifdef notyet 312 static void 313 aac_free_commands(struct aac_softc *sc) 314 { 315 } 316 #endif 317 318 /* 319 * Print autoconfiguration message for a sub-device. 320 */ 321 static int 322 aac_print(void *aux, const char *pnp) 323 { 324 struct aac_attach_args *aaca; 325 326 aaca = aux; 327 328 if (pnp != NULL) 329 aprint_normal("block device at %s", pnp); 330 aprint_normal(" unit %d", aaca->aaca_unit); 331 return (UNCONF); 332 } 333 334 /* 335 * Look up a text description of a numeric error code and return a pointer to 336 * same. 337 */ 338 const char * 339 aac_describe_code(const struct aac_code_lookup *table, u_int32_t code) 340 { 341 int i; 342 343 for (i = 0; table[i].string != NULL; i++) 344 if (table[i].code == code) 345 return (table[i].string); 346 347 return (table[i + 1].string); 348 } 349 350 /* 351 * bitmask_snprintf(9) format string for the adapter options. 352 */ 353 static const char *optfmt = 354 "\20\1SNAPSHOT\2CLUSTERS\3WCACHE\4DATA64\5HOSTTIME\6RAID50" 355 "\7WINDOW4GB" 356 "\10SCSIUPGD\11SOFTERR\12NORECOND\13SGMAP64\14ALARM\15NONDASD"; 357 358 static void 359 aac_describe_controller(struct aac_softc *sc) 360 { 361 u_int8_t fmtbuf[256]; 362 u_int8_t tbuf[AAC_FIB_DATASIZE]; 363 u_int16_t bufsize; 364 struct aac_adapter_info *info; 365 u_int8_t arg; 366 367 arg = 0; 368 if (aac_sync_fib(sc, RequestAdapterInfo, 0, &arg, sizeof(arg), &tbuf, 369 &bufsize)) { 370 aprint_error_dev(&sc->sc_dv, "RequestAdapterInfo failed\n"); 371 return; 372 } 373 if (bufsize != sizeof(*info)) { 374 aprint_error_dev(&sc->sc_dv, 375 "RequestAdapterInfo returned wrong data size (%d != %zu)\n", 376 bufsize, sizeof(*info)); 377 return; 378 } 379 info = (struct aac_adapter_info *)&tbuf[0]; 380 381 aprint_normal_dev(&sc->sc_dv, "%s at %dMHz, %dMB mem (%dMB cache), %s\n", 382 aac_describe_code(aac_cpu_variant, le32toh(info->CpuVariant)), 383 le32toh(info->ClockSpeed), 384 le32toh(info->TotalMem) / (1024 * 1024), 385 le32toh(info->BufferMem) / (1024 * 1024), 386 aac_describe_code(aac_battery_platform, 387 le32toh(info->batteryPlatform))); 388 389 aprint_verbose_dev(&sc->sc_dv, "Kernel %d.%d-%d [Build %d], ", 390 info->KernelRevision.external.comp.major, 391 info->KernelRevision.external.comp.minor, 392 info->KernelRevision.external.comp.dash, 393 info->KernelRevision.buildNumber); 394 395 aprint_verbose("Monitor %d.%d-%d [Build %d], S/N %6X\n", 396 info->MonitorRevision.external.comp.major, 397 info->MonitorRevision.external.comp.minor, 398 info->MonitorRevision.external.comp.dash, 399 info->MonitorRevision.buildNumber, 400 ((u_int32_t)info->SerialNumber & 0xffffff)); 401 402 aprint_verbose_dev(&sc->sc_dv, "Controller supports: %s\n", 403 bitmask_snprintf(sc->sc_supported_options, optfmt, fmtbuf, 404 sizeof(fmtbuf))); 405 406 /* Save the kernel revision structure for later use. */ 407 sc->sc_revision = info->KernelRevision; 408 } 409 410 /* 411 * Retrieve the firmware version numbers. Dell PERC2/QC cards with firmware 412 * version 1.x are not compatible with this driver. 413 */ 414 static int 415 aac_check_firmware(struct aac_softc *sc) 416 { 417 u_int32_t major, minor, opts, atusize = 0, status = 0; 418 u_int32_t calcsgs; 419 420 if ((sc->sc_quirks & AAC_QUIRK_PERC2QC) != 0) { 421 if (aac_sync_command(sc, AAC_MONKER_GETKERNVER, 0, 0, 0, 0, 422 NULL)) { 423 aprint_error_dev(&sc->sc_dv, "error reading firmware version\n"); 424 return (1); 425 } 426 427 /* These numbers are stored as ASCII! */ 428 major = (AAC_GET_MAILBOX(sc, 1) & 0xff) - 0x30; 429 minor = (AAC_GET_MAILBOX(sc, 2) & 0xff) - 0x30; 430 if (major == 1) { 431 aprint_error_dev(&sc->sc_dv, 432 "firmware version %d.%d not supported.\n", 433 major, minor); 434 return (1); 435 } 436 } 437 438 if (aac_sync_command(sc, AAC_MONKER_GETINFO, 0, 0, 0, 0, &status)) { 439 if (status != AAC_SRB_STS_INVALID_REQUEST) { 440 aprint_error_dev(&sc->sc_dv, "GETINFO failed, status 0x%08x\n", status); 441 return (1); 442 } 443 } else { 444 opts = AAC_GET_MAILBOX(sc, 1); 445 atusize = AAC_GET_MAILBOX(sc, 2); 446 sc->sc_supported_options = opts; 447 448 if (((opts & AAC_SUPPORTED_4GB_WINDOW) != 0) && 449 ((sc->sc_quirks & AAC_QUIRK_NO4GB) == 0) ) 450 sc->sc_quirks |= AAC_QUIRK_4GB_WINDOW; 451 452 if (((opts & AAC_SUPPORTED_SGMAP_HOST64) != 0) && 453 (sizeof(bus_addr_t) > 4)) { 454 aprint_normal_dev(&sc->sc_dv, "Enabling 64-bit address support\n"); 455 sc->sc_quirks |= AAC_QUIRK_SG_64BIT; 456 } 457 if ((opts & AAC_SUPPORTED_NEW_COMM) && 458 (sc->sc_if.aif_send_command != NULL)) { 459 sc->sc_quirks |= AAC_QUIRK_NEW_COMM; 460 } 461 #ifdef notyet 462 if (opts & AAC_SUPPORTED_64BIT_ARRAYSIZE) 463 sc->sc_quirks |= AAC_QUIRK_ARRAY_64BIT; 464 #endif 465 } 466 467 sc->sc_max_fibs = (sc->sc_quirks & AAC_QUIRK_256FIBS) ? 256 : 512; 468 469 if ( (sc->sc_quirks & AAC_QUIRK_NEW_COMM) 470 && (sc->sc_regsize < atusize)) { 471 aprint_error_dev(&sc->sc_dv, "Not enabling new comm i/f -- " 472 "atusize 0x%08x, regsize 0x%08x\n", 473 atusize, 474 (uint32_t) sc->sc_regsize); 475 sc->sc_quirks &= ~AAC_QUIRK_NEW_COMM; 476 } 477 #if 0 478 if (sc->sc_quirks & AAC_QUIRK_NEW_COMM) { 479 aprint_error_dev(&sc->sc_dv, "Not enabling new comm i/f -- " 480 "driver not ready yet\n"); 481 sc->sc_quirks &= ~AAC_QUIRK_NEW_COMM; 482 } 483 #endif 484 485 sc->sc_max_fib_size = sizeof(struct aac_fib); 486 sc->sc_max_sectors = 128; /* 64KB */ 487 if (sc->sc_quirks & AAC_QUIRK_SG_64BIT) 488 sc->sc_max_sgs = (sc->sc_max_fib_size 489 - sizeof(struct aac_blockwrite64) 490 + sizeof(struct aac_sg_table64)) 491 / sizeof(struct aac_sg_table64); 492 else 493 sc->sc_max_sgs = (sc->sc_max_fib_size 494 - sizeof(struct aac_blockwrite) 495 + sizeof(struct aac_sg_table)) 496 / sizeof(struct aac_sg_table); 497 498 if (!aac_sync_command(sc, AAC_MONKER_GETCOMMPREF, 0, 0, 0, 0, NULL)) { 499 u_int32_t opt1, opt2, opt3; 500 u_int32_t tmpval; 501 502 opt1 = AAC_GET_MAILBOX(sc, 1); 503 opt2 = AAC_GET_MAILBOX(sc, 2); 504 opt3 = AAC_GET_MAILBOX(sc, 3); 505 if (!opt1 || !opt2 || !opt3) { 506 aprint_verbose_dev(&sc->sc_dv, "GETCOMMPREF appears untrustworthy." 507 " Ignoring.\n"); 508 } else { 509 sc->sc_max_fib_size = le32toh(opt1) & 0xffff; 510 sc->sc_max_sectors = (le32toh(opt1) >> 16) << 1; 511 tmpval = (le32toh(opt2) >> 16); 512 if (tmpval < sc->sc_max_sgs) { 513 sc->sc_max_sgs = tmpval; 514 } 515 tmpval = (le32toh(opt3) & 0xffff); 516 if (tmpval < sc->sc_max_fibs) { 517 sc->sc_max_fibs = tmpval; 518 } 519 } 520 } 521 if (sc->sc_max_fib_size > PAGE_SIZE) 522 sc->sc_max_fib_size = PAGE_SIZE; 523 524 if (sc->sc_quirks & AAC_QUIRK_SG_64BIT) 525 calcsgs = (sc->sc_max_fib_size 526 - sizeof(struct aac_blockwrite64) 527 + sizeof(struct aac_sg_table64)) 528 / sizeof(struct aac_sg_table64); 529 else 530 calcsgs = (sc->sc_max_fib_size 531 - sizeof(struct aac_blockwrite) 532 + sizeof(struct aac_sg_table)) 533 / sizeof(struct aac_sg_table); 534 535 if (calcsgs < sc->sc_max_sgs) { 536 sc->sc_max_sgs = calcsgs; 537 } 538 539 sc->sc_max_fibs_alloc = PAGE_SIZE / sc->sc_max_fib_size; 540 541 return (0); 542 } 543 544 static int 545 aac_init(struct aac_softc *sc) 546 { 547 int nsegs, i, rv, state, norm, high; 548 struct aac_adapter_init *ip; 549 u_int32_t code, qoff; 550 551 state = 0; 552 553 /* 554 * First wait for the adapter to come ready. 555 */ 556 for (i = 0; i < AAC_BOOT_TIMEOUT * 1000; i++) { 557 code = AAC_GET_FWSTATUS(sc); 558 if ((code & AAC_SELF_TEST_FAILED) != 0) { 559 aprint_error_dev(&sc->sc_dv, "FATAL: selftest failed\n"); 560 return (ENXIO); 561 } 562 if ((code & AAC_KERNEL_PANIC) != 0) { 563 aprint_error_dev(&sc->sc_dv, "FATAL: controller kernel panic\n"); 564 return (ENXIO); 565 } 566 if ((code & AAC_UP_AND_RUNNING) != 0) 567 break; 568 DELAY(1000); 569 } 570 if (i == AAC_BOOT_TIMEOUT * 1000) { 571 aprint_error_dev(&sc->sc_dv, 572 "FATAL: controller not coming ready, status %x\n", 573 code); 574 return (ENXIO); 575 } 576 577 sc->sc_aif_fib = malloc(sizeof(struct aac_fib), M_AACBUF, 578 M_NOWAIT | M_ZERO); 579 if (sc->sc_aif_fib == NULL) { 580 aprint_error_dev(&sc->sc_dv, "cannot alloc fib structure\n"); 581 return (ENOMEM); 582 } 583 if ((rv = bus_dmamap_create(sc->sc_dmat, sizeof(*sc->sc_common), 1, 584 sizeof(*sc->sc_common), 0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, 585 &sc->sc_common_dmamap)) != 0) { 586 aprint_error_dev(&sc->sc_dv, "cannot create common dmamap\n"); 587 goto bail_out; 588 } 589 state++; 590 if ((rv = bus_dmamem_alloc(sc->sc_dmat, sizeof(*sc->sc_common), 591 PAGE_SIZE, 0, &sc->sc_common_seg, 1, &nsegs, 592 BUS_DMA_NOWAIT)) != 0) { 593 aprint_error_dev(&sc->sc_dv, "can't allocate common structure\n"); 594 goto bail_out; 595 } 596 state++; 597 if ((rv = bus_dmamem_map(sc->sc_dmat, &sc->sc_common_seg, nsegs, 598 sizeof(*sc->sc_common), (void **)&sc->sc_common, 0)) != 0) { 599 aprint_error_dev(&sc->sc_dv, "can't map common structure\n"); 600 goto bail_out; 601 } 602 state++; 603 if ((rv = bus_dmamap_load(sc->sc_dmat, sc->sc_common_dmamap, 604 sc->sc_common, sizeof(*sc->sc_common), NULL, 605 BUS_DMA_NOWAIT)) != 0) { 606 aprint_error_dev(&sc->sc_dv, "cannot load common dmamap\n"); 607 goto bail_out; 608 } 609 state++; 610 611 memset(sc->sc_common, 0, sizeof(*sc->sc_common)); 612 613 TAILQ_INIT(&sc->sc_fibmap_tqh); 614 sc->sc_ccbs = malloc(sizeof(struct aac_ccb) * sc->sc_max_fibs, M_AACBUF, 615 M_NOWAIT | M_ZERO); 616 if (sc->sc_ccbs == NULL) { 617 aprint_error_dev(&sc->sc_dv, "memory allocation failure getting ccbs\n"); 618 rv = ENOMEM; 619 goto bail_out; 620 } 621 state++; 622 while (sc->sc_total_fibs < AAC_PREALLOCATE_FIBS(sc)) { 623 if (aac_alloc_commands(sc) != 0) 624 break; 625 } 626 if (sc->sc_total_fibs == 0) 627 goto bail_out; 628 629 /* 630 * Fill in the init structure. This tells the adapter about the 631 * physical location of various important shared data structures. 632 */ 633 ip = &sc->sc_common->ac_init; 634 ip->InitStructRevision = htole32(AAC_INIT_STRUCT_REVISION); 635 if (sc->sc_max_fib_size > sizeof(struct aac_fib)) { 636 ip->InitStructRevision = htole32(AAC_INIT_STRUCT_REVISION_4); 637 sc->sc_quirks |= AAC_QUIRK_RAW_IO; 638 } 639 ip->MiniPortRevision = htole32(AAC_INIT_STRUCT_MINIPORT_REVISION); 640 641 ip->AdapterFibsPhysicalAddress = htole32(sc->sc_common_seg.ds_addr + 642 offsetof(struct aac_common, ac_fibs)); 643 ip->AdapterFibsVirtualAddress = 0; 644 ip->AdapterFibsSize = 645 htole32(AAC_ADAPTER_FIBS * sizeof(struct aac_fib)); 646 ip->AdapterFibAlign = htole32(sizeof(struct aac_fib)); 647 648 ip->PrintfBufferAddress = htole32(sc->sc_common_seg.ds_addr + 649 offsetof(struct aac_common, ac_printf)); 650 ip->PrintfBufferSize = htole32(AAC_PRINTF_BUFSIZE); 651 652 /* 653 * The adapter assumes that pages are 4K in size, except on some 654 * broken firmware versions that do the page->byte conversion twice, 655 * therefore 'assuming' that this value is in 16MB units (2^24). 656 * Round up since the granularity is so high. 657 */ 658 ip->HostPhysMemPages = ctob(physmem) / AAC_PAGE_SIZE; 659 if (sc->sc_quirks & AAC_QUIRK_BROKEN_MMAP) { 660 ip->HostPhysMemPages = 661 (ip->HostPhysMemPages + AAC_PAGE_SIZE) / AAC_PAGE_SIZE; 662 } 663 ip->HostElapsedSeconds = 0; /* reset later if invalid */ 664 665 ip->InitFlags = 0; 666 if (sc->sc_quirks & AAC_QUIRK_NEW_COMM) { 667 ip->InitFlags = htole32(AAC_INITFLAGS_NEW_COMM_SUPPORTED); 668 aprint_normal_dev(&sc->sc_dv, "New comm. interface enabled\n"); 669 } 670 671 ip->MaxIoCommands = htole32(sc->sc_max_fibs); 672 ip->MaxIoSize = htole32(sc->sc_max_sectors << 9); 673 ip->MaxFibSize = htole32(sc->sc_max_fib_size); 674 675 /* 676 * Initialise FIB queues. Note that it appears that the layout of 677 * the indexes and the segmentation of the entries is mandated by 678 * the adapter, which is only told about the base of the queue index 679 * fields. 680 * 681 * The initial values of the indices are assumed to inform the 682 * adapter of the sizes of the respective queues. 683 * 684 * The Linux driver uses a much more complex scheme whereby several 685 * header records are kept for each queue. We use a couple of 686 * generic list manipulation functions which 'know' the size of each 687 * list by virtue of a table. 688 */ 689 qoff = offsetof(struct aac_common, ac_qbuf) + AAC_QUEUE_ALIGN; 690 qoff &= ~(AAC_QUEUE_ALIGN - 1); 691 sc->sc_queues = (struct aac_queue_table *)((uintptr_t)sc->sc_common + qoff); 692 ip->CommHeaderAddress = htole32(sc->sc_common_seg.ds_addr + 693 ((char *)sc->sc_queues - (char *)sc->sc_common)); 694 memset(sc->sc_queues, 0, sizeof(struct aac_queue_table)); 695 696 norm = htole32(AAC_HOST_NORM_CMD_ENTRIES); 697 high = htole32(AAC_HOST_HIGH_CMD_ENTRIES); 698 699 sc->sc_queues->qt_qindex[AAC_HOST_NORM_CMD_QUEUE][AAC_PRODUCER_INDEX] = 700 norm; 701 sc->sc_queues->qt_qindex[AAC_HOST_NORM_CMD_QUEUE][AAC_CONSUMER_INDEX] = 702 norm; 703 sc->sc_queues->qt_qindex[AAC_HOST_HIGH_CMD_QUEUE][AAC_PRODUCER_INDEX] = 704 high; 705 sc->sc_queues->qt_qindex[AAC_HOST_HIGH_CMD_QUEUE][AAC_CONSUMER_INDEX] = 706 high; 707 708 norm = htole32(AAC_ADAP_NORM_CMD_ENTRIES); 709 high = htole32(AAC_ADAP_HIGH_CMD_ENTRIES); 710 711 sc->sc_queues->qt_qindex[AAC_ADAP_NORM_CMD_QUEUE][AAC_PRODUCER_INDEX] = 712 norm; 713 sc->sc_queues->qt_qindex[AAC_ADAP_NORM_CMD_QUEUE][AAC_CONSUMER_INDEX] = 714 norm; 715 sc->sc_queues->qt_qindex[AAC_ADAP_HIGH_CMD_QUEUE][AAC_PRODUCER_INDEX] = 716 high; 717 sc->sc_queues->qt_qindex[AAC_ADAP_HIGH_CMD_QUEUE][AAC_CONSUMER_INDEX] = 718 high; 719 720 norm = htole32(AAC_HOST_NORM_RESP_ENTRIES); 721 high = htole32(AAC_HOST_HIGH_RESP_ENTRIES); 722 723 sc->sc_queues-> 724 qt_qindex[AAC_HOST_NORM_RESP_QUEUE][AAC_PRODUCER_INDEX] = norm; 725 sc->sc_queues-> 726 qt_qindex[AAC_HOST_NORM_RESP_QUEUE][AAC_CONSUMER_INDEX] = norm; 727 sc->sc_queues-> 728 qt_qindex[AAC_HOST_HIGH_RESP_QUEUE][AAC_PRODUCER_INDEX] = high; 729 sc->sc_queues-> 730 qt_qindex[AAC_HOST_HIGH_RESP_QUEUE][AAC_CONSUMER_INDEX] = high; 731 732 norm = htole32(AAC_ADAP_NORM_RESP_ENTRIES); 733 high = htole32(AAC_ADAP_HIGH_RESP_ENTRIES); 734 735 sc->sc_queues-> 736 qt_qindex[AAC_ADAP_NORM_RESP_QUEUE][AAC_PRODUCER_INDEX] = norm; 737 sc->sc_queues-> 738 qt_qindex[AAC_ADAP_NORM_RESP_QUEUE][AAC_CONSUMER_INDEX] = norm; 739 sc->sc_queues-> 740 qt_qindex[AAC_ADAP_HIGH_RESP_QUEUE][AAC_PRODUCER_INDEX] = high; 741 sc->sc_queues-> 742 qt_qindex[AAC_ADAP_HIGH_RESP_QUEUE][AAC_CONSUMER_INDEX] = high; 743 744 sc->sc_qentries[AAC_HOST_NORM_CMD_QUEUE] = 745 &sc->sc_queues->qt_HostNormCmdQueue[0]; 746 sc->sc_qentries[AAC_HOST_HIGH_CMD_QUEUE] = 747 &sc->sc_queues->qt_HostHighCmdQueue[0]; 748 sc->sc_qentries[AAC_ADAP_NORM_CMD_QUEUE] = 749 &sc->sc_queues->qt_AdapNormCmdQueue[0]; 750 sc->sc_qentries[AAC_ADAP_HIGH_CMD_QUEUE] = 751 &sc->sc_queues->qt_AdapHighCmdQueue[0]; 752 sc->sc_qentries[AAC_HOST_NORM_RESP_QUEUE] = 753 &sc->sc_queues->qt_HostNormRespQueue[0]; 754 sc->sc_qentries[AAC_HOST_HIGH_RESP_QUEUE] = 755 &sc->sc_queues->qt_HostHighRespQueue[0]; 756 sc->sc_qentries[AAC_ADAP_NORM_RESP_QUEUE] = 757 &sc->sc_queues->qt_AdapNormRespQueue[0]; 758 sc->sc_qentries[AAC_ADAP_HIGH_RESP_QUEUE] = 759 &sc->sc_queues->qt_AdapHighRespQueue[0]; 760 761 /* 762 * Do controller-type-specific initialisation 763 */ 764 switch (sc->sc_hwif) { 765 case AAC_HWIF_I960RX: 766 AAC_SETREG4(sc, AAC_RX_ODBR, ~0); 767 break; 768 } 769 770 bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap, 0, 771 sizeof(*sc->sc_common), 772 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 773 774 /* 775 * Give the init structure to the controller. 776 */ 777 if (aac_sync_command(sc, AAC_MONKER_INITSTRUCT, 778 sc->sc_common_seg.ds_addr + offsetof(struct aac_common, ac_init), 779 0, 0, 0, NULL)) { 780 aprint_error_dev(&sc->sc_dv, "error establishing init structure\n"); 781 rv = EIO; 782 goto bail_out; 783 } 784 785 return (0); 786 787 bail_out: 788 if (state > 4) 789 free(sc->sc_ccbs, M_AACBUF); 790 if (state > 3) 791 bus_dmamap_unload(sc->sc_dmat, sc->sc_common_dmamap); 792 if (state > 2) 793 bus_dmamem_unmap(sc->sc_dmat, (void *)sc->sc_common, 794 sizeof(*sc->sc_common)); 795 if (state > 1) 796 bus_dmamem_free(sc->sc_dmat, &sc->sc_common_seg, 1); 797 if (state > 0) 798 bus_dmamap_destroy(sc->sc_dmat, sc->sc_common_dmamap); 799 800 free(sc->sc_aif_fib, M_AACBUF); 801 802 return (rv); 803 } 804 805 /* 806 * Probe for containers, create disks. 807 */ 808 static void 809 aac_startup(struct aac_softc *sc) 810 { 811 struct aac_mntinfo mi; 812 struct aac_mntinforesponse mir; 813 struct aac_drive *hd; 814 u_int16_t rsize; 815 int i; 816 817 /* 818 * Loop over possible containers. 819 */ 820 hd = sc->sc_hdr; 821 822 for (i = 0; i < AAC_MAX_CONTAINERS; i++, hd++) { 823 /* 824 * Request information on this container. 825 */ 826 memset(&mi, 0, sizeof(mi)); 827 mi.Command = htole32(VM_NameServe); 828 mi.MntType = htole32(FT_FILESYS); 829 mi.MntCount = htole32(i); 830 if (aac_sync_fib(sc, ContainerCommand, 0, &mi, sizeof(mi), &mir, 831 &rsize)) { 832 aprint_error_dev(&sc->sc_dv, "error probing container %d\n", i); 833 continue; 834 } 835 if (rsize != sizeof(mir)) { 836 aprint_error_dev(&sc->sc_dv, "container info response wrong size " 837 "(%d should be %zu)\n", rsize, sizeof(mir)); 838 continue; 839 } 840 841 /* 842 * Check container volume type for validity. Note that many 843 * of the possible types may never show up. 844 */ 845 if (le32toh(mir.Status) != ST_OK || 846 le32toh(mir.MntTable[0].VolType) == CT_NONE) 847 continue; 848 849 hd->hd_present = 1; 850 hd->hd_size = le32toh(mir.MntTable[0].Capacity); 851 hd->hd_devtype = le32toh(mir.MntTable[0].VolType); 852 hd->hd_size &= ~0x1f; 853 sc->sc_nunits++; 854 } 855 } 856 857 static void 858 aac_shutdown(void *cookie) 859 { 860 struct aac_softc *sc; 861 struct aac_close_command cc; 862 u_int32_t i; 863 864 for (i = 0; i < aac_cd.cd_ndevs; i++) { 865 if ((sc = device_lookup(&aac_cd, i)) == NULL) 866 continue; 867 if ((sc->sc_flags & AAC_ONLINE) == 0) 868 continue; 869 870 AAC_MASK_INTERRUPTS(sc); 871 872 /* 873 * Send a Container shutdown followed by a HostShutdown FIB 874 * to the controller to convince it that we don't want to 875 * talk to it anymore. We've been closed and all I/O 876 * completed already 877 */ 878 memset(&cc, 0, sizeof(cc)); 879 cc.Command = htole32(VM_CloseAll); 880 cc.ContainerId = 0xffffffff; 881 if (aac_sync_fib(sc, ContainerCommand, 0, &cc, sizeof(cc), 882 NULL, NULL)) { 883 aprint_error_dev(&sc->sc_dv, "unable to halt controller\n"); 884 continue; 885 } 886 887 /* 888 * Note that issuing this command to the controller makes it 889 * shut down but also keeps it from coming back up without a 890 * reset of the PCI bus. 891 */ 892 if (aac_sync_fib(sc, FsaHostShutdown, AAC_FIBSTATE_SHUTDOWN, 893 &i, sizeof(i), NULL, NULL)) 894 aprint_error_dev(&sc->sc_dv, "unable to halt controller\n"); 895 896 sc->sc_flags &= ~AAC_ONLINE; 897 } 898 } 899 900 static int 901 aac_new_intr(void *cookie) 902 { 903 struct aac_softc *sc; 904 u_int32_t index, fast; 905 struct aac_ccb *ac; 906 struct aac_fib *fib; 907 struct aac_fibmap *fm; 908 int i; 909 910 sc = (struct aac_softc *) cookie; 911 912 for (;;) { 913 index = AAC_GET_OUTB_QUEUE(sc); 914 if (index == 0xffffffff) 915 index = AAC_GET_OUTB_QUEUE(sc); 916 if (index == 0xffffffff) 917 break; 918 if (index & 2) { 919 if (index == 0xfffffffe) { 920 /* XXX This means that the controller wants 921 * more work. Ignore it for now. 922 */ 923 continue; 924 } 925 /* AIF */ 926 index &= ~2; 927 fib = sc->sc_aif_fib; 928 for (i = 0; i < sizeof(struct aac_fib)/4; i++) { 929 ((u_int32_t*)fib)[i] = 930 AAC_GETREG4(sc, index + i*4); 931 } 932 #ifdef notyet 933 aac_handle_aif(sc, &fib); 934 #endif 935 936 AAC_SET_OUTB_QUEUE(sc, index); 937 AAC_CLEAR_ISTATUS(sc, AAC_DB_RESPONSE_READY); 938 } else { 939 fast = index & 1; 940 ac = sc->sc_ccbs + (index >> 2); 941 fib = ac->ac_fib; 942 fm = ac->ac_fibmap; 943 if (fast) { 944 bus_dmamap_sync(sc->sc_dmat, fm->fm_fibmap, 945 (char *)fib - (char *)fm->fm_fibs, 946 sc->sc_max_fib_size, 947 BUS_DMASYNC_POSTWRITE | 948 BUS_DMASYNC_POSTREAD); 949 fib->Header.XferState |= 950 htole32(AAC_FIBSTATE_DONEADAP); 951 *((u_int32_t *)(fib->data)) = 952 htole32(AAC_ERROR_NORMAL); 953 } 954 ac->ac_flags |= AAC_CCB_COMPLETED; 955 956 if (ac->ac_intr != NULL) 957 (*ac->ac_intr)(ac); 958 else 959 wakeup(ac); 960 } 961 } 962 963 /* 964 * Try to submit more commands. 965 */ 966 if (! SIMPLEQ_EMPTY(&sc->sc_ccb_queue)) 967 aac_ccb_enqueue(sc, NULL); 968 969 return 1; 970 } 971 972 /* 973 * Take an interrupt. 974 */ 975 int 976 aac_intr(void *cookie) 977 { 978 struct aac_softc *sc; 979 u_int16_t reason; 980 int claimed; 981 982 sc = cookie; 983 claimed = 0; 984 985 AAC_DPRINTF(AAC_D_INTR, ("aac_intr(%p) ", sc)); 986 987 reason = AAC_GET_ISTATUS(sc); 988 AAC_CLEAR_ISTATUS(sc, reason); 989 990 AAC_DPRINTF(AAC_D_INTR, ("istatus 0x%04x ", reason)); 991 992 /* 993 * Controller wants to talk to the log. XXX Should we defer this? 994 */ 995 if ((reason & AAC_DB_PRINTF) != 0) { 996 if (sc->sc_common->ac_printf[0] == '\0') 997 sc->sc_common->ac_printf[0] = ' '; 998 printf("%s: WARNING: adapter logged message:\n", 999 device_xname(&sc->sc_dv)); 1000 printf("%s: %.*s", device_xname(&sc->sc_dv), 1001 AAC_PRINTF_BUFSIZE, sc->sc_common->ac_printf); 1002 sc->sc_common->ac_printf[0] = '\0'; 1003 AAC_QNOTIFY(sc, AAC_DB_PRINTF); 1004 claimed = 1; 1005 } 1006 1007 /* 1008 * Controller has a message for us? 1009 */ 1010 if ((reason & AAC_DB_COMMAND_READY) != 0) { 1011 aac_host_command(sc); 1012 claimed = 1; 1013 } 1014 1015 /* 1016 * Controller has a response for us? 1017 */ 1018 if ((reason & AAC_DB_RESPONSE_READY) != 0) { 1019 aac_host_response(sc); 1020 claimed = 1; 1021 } 1022 1023 /* 1024 * Spurious interrupts that we don't use - reset the mask and clear 1025 * the interrupts. 1026 */ 1027 if ((reason & (AAC_DB_SYNC_COMMAND | AAC_DB_COMMAND_NOT_FULL | 1028 AAC_DB_RESPONSE_NOT_FULL)) != 0) { 1029 AAC_UNMASK_INTERRUPTS(sc); 1030 AAC_CLEAR_ISTATUS(sc, AAC_DB_SYNC_COMMAND | 1031 AAC_DB_COMMAND_NOT_FULL | AAC_DB_RESPONSE_NOT_FULL); 1032 claimed = 1; 1033 } 1034 1035 return (claimed); 1036 } 1037 1038 /* 1039 * Handle notification of one or more FIBs coming from the controller. 1040 */ 1041 static void 1042 aac_host_command(struct aac_softc *sc) 1043 { 1044 struct aac_fib *fib; 1045 u_int32_t fib_size; 1046 1047 for (;;) { 1048 if (aac_dequeue_fib(sc, AAC_HOST_NORM_CMD_QUEUE, &fib_size, 1049 &fib)) 1050 break; /* nothing to do */ 1051 1052 bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap, 1053 (char *)fib - (char *)sc->sc_common, sizeof(*fib), 1054 BUS_DMASYNC_POSTREAD); 1055 1056 switch (le16toh(fib->Header.Command)) { 1057 case AifRequest: 1058 #ifdef notyet 1059 aac_handle_aif(sc, 1060 (struct aac_aif_command *)&fib->data[0]); 1061 #endif 1062 AAC_PRINT_FIB(sc, fib); 1063 break; 1064 default: 1065 aprint_error_dev(&sc->sc_dv, "unknown command from controller\n"); 1066 AAC_PRINT_FIB(sc, fib); 1067 break; 1068 } 1069 1070 bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap, 1071 (char *)fib - (char *)sc->sc_common, sizeof(*fib), 1072 BUS_DMASYNC_PREREAD); 1073 1074 if ((fib->Header.XferState == 0) || 1075 (fib->Header.StructType != AAC_FIBTYPE_TFIB)) { 1076 break; // continue; ??? 1077 } 1078 1079 /* XXX reply to FIBs requesting responses ?? */ 1080 1081 /* Return the AIF/FIB to the controller */ 1082 if (le32toh(fib->Header.XferState) & AAC_FIBSTATE_FROMADAP) { 1083 u_int16_t size; 1084 1085 fib->Header.XferState |= 1086 htole32(AAC_FIBSTATE_DONEHOST); 1087 *(u_int32_t*)fib->data = htole32(ST_OK); 1088 1089 /* XXX Compute the Size field? */ 1090 size = le16toh(fib->Header.Size); 1091 if (size > sizeof(struct aac_fib)) { 1092 size = sizeof(struct aac_fib); 1093 fib->Header.Size = htole16(size); 1094 } 1095 1096 /* 1097 * Since we didn't generate this command, it can't 1098 * go through the normal process. 1099 */ 1100 aac_enqueue_response(sc, 1101 AAC_ADAP_NORM_RESP_QUEUE, fib); 1102 } 1103 } 1104 } 1105 1106 /* 1107 * Handle notification of one or more FIBs completed by the controller 1108 */ 1109 static void 1110 aac_host_response(struct aac_softc *sc) 1111 { 1112 struct aac_ccb *ac; 1113 struct aac_fib *fib; 1114 u_int32_t fib_size; 1115 1116 /* 1117 * Look for completed FIBs on our queue. 1118 */ 1119 for (;;) { 1120 if (aac_dequeue_fib(sc, AAC_HOST_NORM_RESP_QUEUE, &fib_size, 1121 &fib)) 1122 break; /* nothing to do */ 1123 1124 if ((fib->Header.SenderData & 0x80000000) == 0) { 1125 /* Not valid; not sent by us. */ 1126 AAC_PRINT_FIB(sc, fib); 1127 } else { 1128 ac = (struct aac_ccb *)(sc->sc_ccbs + 1129 (fib->Header.SenderData & 0x7fffffff)); 1130 fib->Header.SenderData = 0; 1131 SIMPLEQ_INSERT_TAIL(&sc->sc_ccb_complete, ac, ac_chain); 1132 } 1133 } 1134 1135 /* 1136 * Deal with any completed commands. 1137 */ 1138 while ((ac = SIMPLEQ_FIRST(&sc->sc_ccb_complete)) != NULL) { 1139 SIMPLEQ_REMOVE_HEAD(&sc->sc_ccb_complete, ac_chain); 1140 ac->ac_flags |= AAC_CCB_COMPLETED; 1141 1142 if (ac->ac_intr != NULL) 1143 (*ac->ac_intr)(ac); 1144 else 1145 wakeup(ac); 1146 } 1147 1148 /* 1149 * Try to submit more commands. 1150 */ 1151 if (! SIMPLEQ_EMPTY(&sc->sc_ccb_queue)) 1152 aac_ccb_enqueue(sc, NULL); 1153 } 1154 1155 /* 1156 * Send a synchronous command to the controller and wait for a result. 1157 */ 1158 static int 1159 aac_sync_command(struct aac_softc *sc, u_int32_t command, u_int32_t arg0, 1160 u_int32_t arg1, u_int32_t arg2, u_int32_t arg3, u_int32_t *sp) 1161 { 1162 int i; 1163 u_int32_t status; 1164 int s; 1165 1166 s = splbio(); 1167 1168 /* Populate the mailbox. */ 1169 AAC_SET_MAILBOX(sc, command, arg0, arg1, arg2, arg3); 1170 1171 /* Ensure the sync command doorbell flag is cleared. */ 1172 AAC_CLEAR_ISTATUS(sc, AAC_DB_SYNC_COMMAND); 1173 1174 /* ... then set it to signal the adapter. */ 1175 AAC_QNOTIFY(sc, AAC_DB_SYNC_COMMAND); 1176 DELAY(AAC_SYNC_DELAY); 1177 1178 /* Spin waiting for the command to complete. */ 1179 for (i = 0; i < AAC_IMMEDIATE_TIMEOUT * 1000; i++) { 1180 if (AAC_GET_ISTATUS(sc) & AAC_DB_SYNC_COMMAND) 1181 break; 1182 DELAY(1000); 1183 } 1184 if (i == AAC_IMMEDIATE_TIMEOUT * 1000) { 1185 splx(s); 1186 return (EIO); 1187 } 1188 1189 /* Clear the completion flag. */ 1190 AAC_CLEAR_ISTATUS(sc, AAC_DB_SYNC_COMMAND); 1191 1192 /* Get the command status. */ 1193 status = AAC_GET_MAILBOXSTATUS(sc); 1194 splx(s); 1195 if (sp != NULL) 1196 *sp = status; 1197 1198 return (0); /* XXX Check command return status? */ 1199 } 1200 1201 /* 1202 * Send a synchronous FIB to the controller and wait for a result. 1203 */ 1204 static int 1205 aac_sync_fib(struct aac_softc *sc, u_int32_t command, u_int32_t xferstate, 1206 void *data, u_int16_t datasize, void *result, 1207 u_int16_t *resultsize) 1208 { 1209 struct aac_fib *fib; 1210 u_int32_t fibpa, status; 1211 1212 fib = &sc->sc_common->ac_sync_fib; 1213 fibpa = sc->sc_common_seg.ds_addr + 1214 offsetof(struct aac_common, ac_sync_fib); 1215 1216 if (datasize > AAC_FIB_DATASIZE) 1217 return (EINVAL); 1218 1219 /* 1220 * Set up the sync FIB. 1221 */ 1222 fib->Header.XferState = htole32(AAC_FIBSTATE_HOSTOWNED | 1223 AAC_FIBSTATE_INITIALISED | AAC_FIBSTATE_EMPTY | xferstate); 1224 fib->Header.Command = htole16(command); 1225 fib->Header.StructType = AAC_FIBTYPE_TFIB; 1226 fib->Header.Size = htole16(sizeof(*fib) + datasize); 1227 fib->Header.SenderSize = htole16(sizeof(*fib)); 1228 fib->Header.SenderFibAddress = 0; /* not needed */ 1229 fib->Header.ReceiverFibAddress = htole32(fibpa); 1230 1231 /* 1232 * Copy in data. 1233 */ 1234 if (data != NULL) { 1235 memcpy(fib->data, data, datasize); 1236 fib->Header.XferState |= 1237 htole32(AAC_FIBSTATE_FROMHOST | AAC_FIBSTATE_NORM); 1238 } 1239 1240 bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap, 1241 (char *)fib - (char *)sc->sc_common, sizeof(*fib), 1242 BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); 1243 1244 /* 1245 * Give the FIB to the controller, wait for a response. 1246 */ 1247 if (aac_sync_command(sc, AAC_MONKER_SYNCFIB, fibpa, 0, 0, 0, &status)) 1248 return (EIO); 1249 if (status != 1) { 1250 printf("%s: syncfib command %04x status %08x\n", 1251 device_xname(&sc->sc_dv), command, status); 1252 } 1253 1254 bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap, 1255 (char *)fib - (char *)sc->sc_common, sizeof(*fib), 1256 BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD); 1257 1258 /* 1259 * Copy out the result 1260 */ 1261 if (result != NULL) { 1262 *resultsize = le16toh(fib->Header.Size) - sizeof(fib->Header); 1263 memcpy(result, fib->data, *resultsize); 1264 } 1265 1266 return (0); 1267 } 1268 1269 struct aac_ccb * 1270 aac_ccb_alloc(struct aac_softc *sc, int flags) 1271 { 1272 struct aac_ccb *ac; 1273 int s; 1274 1275 AAC_DPRINTF(AAC_D_QUEUE, ("aac_ccb_alloc(%p, 0x%x) ", sc, flags)); 1276 1277 s = splbio(); 1278 ac = SIMPLEQ_FIRST(&sc->sc_ccb_free); 1279 if (ac == NULL) { 1280 if (aac_alloc_commands(sc)) { 1281 splx(s); 1282 return NULL; 1283 } 1284 ac = SIMPLEQ_FIRST(&sc->sc_ccb_free); 1285 } 1286 #ifdef DIAGNOSTIC 1287 if (ac == NULL) 1288 panic("aac_ccb_get: no free CCBS"); 1289 #endif 1290 SIMPLEQ_REMOVE_HEAD(&sc->sc_ccb_free, ac_chain); 1291 splx(s); 1292 1293 ac->ac_flags = flags; 1294 return (ac); 1295 } 1296 1297 void 1298 aac_ccb_free(struct aac_softc *sc, struct aac_ccb *ac) 1299 { 1300 int s; 1301 1302 AAC_DPRINTF(AAC_D_QUEUE, ("aac_ccb_free(%p, %p) ", sc, ac)); 1303 1304 ac->ac_flags = 0; 1305 ac->ac_intr = NULL; 1306 ac->ac_fib->Header.XferState = htole32(AAC_FIBSTATE_EMPTY); 1307 ac->ac_fib->Header.StructType = AAC_FIBTYPE_TFIB; 1308 ac->ac_fib->Header.Flags = 0; 1309 ac->ac_fib->Header.SenderSize = htole16(sc->sc_max_fib_size); 1310 1311 #ifdef AAC_DEBUG 1312 /* 1313 * These are duplicated in aac_ccb_submit() to cover the case where 1314 * an intermediate stage may have destroyed them. They're left 1315 * initialised here for debugging purposes only. 1316 */ 1317 ac->ac_fib->Header.SenderFibAddress = 1318 htole32(((u_int32_t) (ac - sc->sc_ccbs)) << 2); 1319 ac->ac_fib->Header.ReceiverFibAddress = htole32(ac->ac_fibphys); 1320 #endif 1321 1322 s = splbio(); 1323 SIMPLEQ_INSERT_HEAD(&sc->sc_ccb_free, ac, ac_chain); 1324 splx(s); 1325 } 1326 1327 int 1328 aac_ccb_map(struct aac_softc *sc, struct aac_ccb *ac) 1329 { 1330 int error; 1331 1332 AAC_DPRINTF(AAC_D_QUEUE, ("aac_ccb_map(%p, %p) ", sc, ac)); 1333 1334 #ifdef DIAGNOSTIC 1335 if ((ac->ac_flags & AAC_CCB_MAPPED) != 0) 1336 panic("aac_ccb_map: already mapped"); 1337 #endif 1338 1339 error = bus_dmamap_load(sc->sc_dmat, ac->ac_dmamap_xfer, ac->ac_data, 1340 ac->ac_datalen, NULL, BUS_DMA_NOWAIT | BUS_DMA_STREAMING | 1341 ((ac->ac_flags & AAC_CCB_DATA_IN) ? BUS_DMA_READ : BUS_DMA_WRITE)); 1342 if (error) { 1343 printf("%s: aac_ccb_map: ", device_xname(&sc->sc_dv)); 1344 if (error == EFBIG) 1345 printf("more than %d DMA segs\n", sc->sc_max_sgs); 1346 else 1347 printf("error %d loading DMA map\n", error); 1348 return (error); 1349 } 1350 1351 bus_dmamap_sync(sc->sc_dmat, ac->ac_dmamap_xfer, 0, ac->ac_datalen, 1352 (ac->ac_flags & AAC_CCB_DATA_IN) ? BUS_DMASYNC_PREREAD : 1353 BUS_DMASYNC_PREWRITE); 1354 1355 #ifdef DIAGNOSTIC 1356 ac->ac_flags |= AAC_CCB_MAPPED; 1357 #endif 1358 return (0); 1359 } 1360 1361 void 1362 aac_ccb_unmap(struct aac_softc *sc, struct aac_ccb *ac) 1363 { 1364 1365 AAC_DPRINTF(AAC_D_QUEUE, ("aac_ccb_unmap(%p, %p) ", sc, ac)); 1366 1367 #ifdef DIAGNOSTIC 1368 if ((ac->ac_flags & AAC_CCB_MAPPED) == 0) 1369 panic("aac_ccb_unmap: not mapped"); 1370 #endif 1371 1372 bus_dmamap_sync(sc->sc_dmat, ac->ac_dmamap_xfer, 0, ac->ac_datalen, 1373 (ac->ac_flags & AAC_CCB_DATA_IN) ? BUS_DMASYNC_POSTREAD : 1374 BUS_DMASYNC_POSTWRITE); 1375 bus_dmamap_unload(sc->sc_dmat, ac->ac_dmamap_xfer); 1376 1377 #ifdef DIAGNOSTIC 1378 ac->ac_flags &= ~AAC_CCB_MAPPED; 1379 #endif 1380 } 1381 1382 void 1383 aac_ccb_enqueue(struct aac_softc *sc, struct aac_ccb *ac) 1384 { 1385 int s; 1386 1387 AAC_DPRINTF(AAC_D_QUEUE, ("aac_ccb_enqueue(%p, %p) ", sc, ac)); 1388 1389 s = splbio(); 1390 1391 if (ac != NULL) 1392 SIMPLEQ_INSERT_TAIL(&sc->sc_ccb_queue, ac, ac_chain); 1393 1394 while ((ac = SIMPLEQ_FIRST(&sc->sc_ccb_queue)) != NULL) { 1395 if (aac_ccb_submit(sc, ac)) 1396 break; 1397 SIMPLEQ_REMOVE_HEAD(&sc->sc_ccb_queue, ac_chain); 1398 } 1399 1400 splx(s); 1401 } 1402 1403 int 1404 aac_ccb_submit(struct aac_softc *sc, struct aac_ccb *ac) 1405 { 1406 struct aac_fibmap *fm; 1407 u_int32_t acidx; 1408 1409 AAC_DPRINTF(AAC_D_QUEUE, ("aac_ccb_submit(%p, %p) ", sc, ac)); 1410 1411 acidx = (u_int32_t) (ac - sc->sc_ccbs); 1412 /* Fix up the address values. */ 1413 ac->ac_fib->Header.SenderFibAddress = htole32(acidx << 2); 1414 ac->ac_fib->Header.ReceiverFibAddress = htole32(ac->ac_fibphys); 1415 1416 /* Save a pointer to the command for speedy reverse-lookup. */ 1417 ac->ac_fib->Header.SenderData = acidx | 0x80000000; 1418 1419 fm = ac->ac_fibmap; 1420 bus_dmamap_sync(sc->sc_dmat, fm->fm_fibmap, 1421 (char *)ac->ac_fib - (char *)fm->fm_fibs, sc->sc_max_fib_size, 1422 BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); 1423 1424 /* Put the FIB on the outbound queue. */ 1425 if (sc->sc_quirks & AAC_QUIRK_NEW_COMM) { 1426 int count = 10000000L; 1427 while (AAC_SEND_COMMAND(sc, ac) != 0) { 1428 if (--count == 0) { 1429 panic("aac: fixme!"); 1430 return EAGAIN; 1431 } 1432 DELAY(5); 1433 } 1434 return 0; 1435 } else { 1436 return (aac_enqueue_fib(sc, AAC_ADAP_NORM_CMD_QUEUE, ac)); 1437 } 1438 } 1439 1440 int 1441 aac_ccb_poll(struct aac_softc *sc, struct aac_ccb *ac, int timo) 1442 { 1443 int rv, s; 1444 1445 AAC_DPRINTF(AAC_D_QUEUE, ("aac_ccb_poll(%p, %p, %d) ", sc, ac, timo)); 1446 1447 s = splbio(); 1448 1449 if ((rv = aac_ccb_submit(sc, ac)) != 0) { 1450 splx(s); 1451 return (rv); 1452 } 1453 1454 for (timo *= 1000; timo != 0; timo--) { 1455 if (sc->sc_quirks & AAC_QUIRK_NEW_COMM) 1456 aac_new_intr(sc); 1457 else 1458 aac_intr(sc); 1459 if ((ac->ac_flags & AAC_CCB_COMPLETED) != 0) 1460 break; 1461 DELAY(100); 1462 } 1463 1464 splx(s); 1465 return (timo == 0); 1466 } 1467 1468 /* 1469 * Atomically insert an entry into the nominated queue, returns 0 on success 1470 * or EBUSY if the queue is full. 1471 * 1472 * XXX Note that it would be more efficient to defer notifying the 1473 * controller in the case where we may be inserting several entries in rapid 1474 * succession, but implementing this usefully is difficult. 1475 */ 1476 static int 1477 aac_enqueue_fib(struct aac_softc *sc, int queue, struct aac_ccb *ac) 1478 { 1479 u_int32_t fib_size, fib_addr, pi, ci; 1480 1481 fib_size = le16toh(ac->ac_fib->Header.Size); 1482 fib_addr = le32toh(ac->ac_fib->Header.ReceiverFibAddress); 1483 1484 bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap, 1485 (char *)sc->sc_common->ac_qbuf - (char *)sc->sc_common, 1486 sizeof(sc->sc_common->ac_qbuf), 1487 BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD); 1488 1489 /* Get the producer/consumer indices. */ 1490 pi = le32toh(sc->sc_queues->qt_qindex[queue][AAC_PRODUCER_INDEX]); 1491 ci = le32toh(sc->sc_queues->qt_qindex[queue][AAC_CONSUMER_INDEX]); 1492 1493 /* Wrap the queue? */ 1494 if (pi >= aac_qinfo[queue].size) 1495 pi = 0; 1496 1497 /* Check for queue full. */ 1498 if ((pi + 1) == ci) 1499 return (EAGAIN); 1500 1501 /* Populate queue entry. */ 1502 (sc->sc_qentries[queue] + pi)->aq_fib_size = htole32(fib_size); 1503 (sc->sc_qentries[queue] + pi)->aq_fib_addr = htole32(fib_addr); 1504 1505 /* Update producer index. */ 1506 sc->sc_queues->qt_qindex[queue][AAC_PRODUCER_INDEX] = htole32(pi + 1); 1507 1508 bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap, 1509 (char *)sc->sc_common->ac_qbuf - (char *)sc->sc_common, 1510 sizeof(sc->sc_common->ac_qbuf), 1511 BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); 1512 1513 /* Notify the adapter if we know how. */ 1514 if (aac_qinfo[queue].notify != 0) 1515 AAC_QNOTIFY(sc, aac_qinfo[queue].notify); 1516 1517 return (0); 1518 } 1519 1520 /* 1521 * Atomically remove one entry from the nominated queue, returns 0 on success 1522 * or ENOENT if the queue is empty. 1523 */ 1524 static int 1525 aac_dequeue_fib(struct aac_softc *sc, int queue, u_int32_t *fib_size, 1526 struct aac_fib **fib_addr) 1527 { 1528 struct aac_fibmap *fm; 1529 struct aac_ccb *ac; 1530 u_int32_t pi, ci, idx; 1531 int notify; 1532 1533 bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap, 1534 (char *)sc->sc_common->ac_qbuf - (char *)sc->sc_common, 1535 sizeof(sc->sc_common->ac_qbuf), 1536 BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD); 1537 1538 /* Get the producer/consumer indices. */ 1539 pi = le32toh(sc->sc_queues->qt_qindex[queue][AAC_PRODUCER_INDEX]); 1540 ci = le32toh(sc->sc_queues->qt_qindex[queue][AAC_CONSUMER_INDEX]); 1541 1542 /* Check for queue empty. */ 1543 if (ci == pi) 1544 return (ENOENT); 1545 1546 notify = 0; 1547 if (ci == pi + 1) 1548 notify = 1; 1549 1550 /* Wrap the queue? */ 1551 if (ci >= aac_qinfo[queue].size) 1552 ci = 0; 1553 1554 /* Fetch the entry. */ 1555 *fib_size = le32toh((sc->sc_qentries[queue] + ci)->aq_fib_size); 1556 1557 switch (queue) { 1558 case AAC_HOST_NORM_CMD_QUEUE: 1559 case AAC_HOST_HIGH_CMD_QUEUE: 1560 idx = le32toh((sc->sc_qentries[queue] + ci)->aq_fib_addr); 1561 idx /= sizeof(struct aac_fib); 1562 *fib_addr = &sc->sc_common->ac_fibs[idx]; 1563 break; 1564 case AAC_HOST_NORM_RESP_QUEUE: 1565 case AAC_HOST_HIGH_RESP_QUEUE: 1566 idx = le32toh((sc->sc_qentries[queue] + ci)->aq_fib_addr); 1567 ac = sc->sc_ccbs + (idx >> 2); 1568 *fib_addr = ac->ac_fib; 1569 if (idx & 0x01) { 1570 fm = ac->ac_fibmap; 1571 bus_dmamap_sync(sc->sc_dmat, fm->fm_fibmap, 1572 (char *)ac->ac_fib - (char *)fm->fm_fibs, 1573 sc->sc_max_fib_size, 1574 BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD); 1575 ac->ac_fib->Header.XferState |= 1576 htole32(AAC_FIBSTATE_DONEADAP); 1577 *((u_int32_t*)(ac->ac_fib->data)) = 1578 htole32(AAC_ERROR_NORMAL); 1579 } 1580 break; 1581 default: 1582 panic("Invalid queue in aac_dequeue_fib()"); 1583 break; 1584 } 1585 1586 /* Update consumer index. */ 1587 sc->sc_queues->qt_qindex[queue][AAC_CONSUMER_INDEX] = ci + 1; 1588 1589 bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap, 1590 (char *)sc->sc_common->ac_qbuf - (char *)sc->sc_common, 1591 sizeof(sc->sc_common->ac_qbuf), 1592 BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); 1593 1594 /* If we have made the queue un-full, notify the adapter. */ 1595 if (notify && (aac_qinfo[queue].notify != 0)) 1596 AAC_QNOTIFY(sc, aac_qinfo[queue].notify); 1597 1598 return (0); 1599 } 1600 1601 /* 1602 * Put our response to an adapter-initiated fib (AIF) on the response queue. 1603 */ 1604 static int 1605 aac_enqueue_response(struct aac_softc *sc, int queue, struct aac_fib *fib) 1606 { 1607 u_int32_t fib_size, fib_addr, pi, ci; 1608 1609 fib_size = le16toh(fib->Header.Size); 1610 fib_addr = fib->Header.SenderFibAddress; 1611 fib->Header.ReceiverFibAddress = fib_addr; 1612 1613 bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap, 1614 (char *)sc->sc_common->ac_qbuf - (char *)sc->sc_common, 1615 sizeof(sc->sc_common->ac_qbuf), 1616 BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD); 1617 1618 /* Get the producer/consumer indices. */ 1619 pi = le32toh(sc->sc_queues->qt_qindex[queue][AAC_PRODUCER_INDEX]); 1620 ci = le32toh(sc->sc_queues->qt_qindex[queue][AAC_CONSUMER_INDEX]); 1621 1622 /* Wrap the queue? */ 1623 if (pi >= aac_qinfo[queue].size) 1624 pi = 0; 1625 1626 /* Check for queue full. */ 1627 if ((pi + 1) == ci) 1628 return (EAGAIN); 1629 1630 /* Populate queue entry. */ 1631 (sc->sc_qentries[queue] + pi)->aq_fib_size = htole32(fib_size); 1632 (sc->sc_qentries[queue] + pi)->aq_fib_addr = htole32(fib_addr); 1633 1634 /* Update producer index. */ 1635 sc->sc_queues->qt_qindex[queue][AAC_PRODUCER_INDEX] = htole32(pi + 1); 1636 1637 bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap, 1638 (char *)sc->sc_common->ac_qbuf - (char *)sc->sc_common, 1639 sizeof(sc->sc_common->ac_qbuf), 1640 BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); 1641 1642 /* Notify the adapter if we know how. */ 1643 if (aac_qinfo[queue].notify != 0) 1644 AAC_QNOTIFY(sc, aac_qinfo[queue].notify); 1645 1646 return (0); 1647 } 1648 1649 #ifdef AAC_DEBUG 1650 /* 1651 * Print a FIB 1652 */ 1653 static void 1654 aac_print_fib(struct aac_softc *sc, struct aac_fib *fib, 1655 const char *caller) 1656 { 1657 struct aac_blockread *br; 1658 struct aac_blockwrite *bw; 1659 struct aac_sg_table *sg; 1660 char tbuf[512]; 1661 int i; 1662 1663 printf("%s: FIB @ %p\n", caller, fib); 1664 bitmask_snprintf(le32toh(fib->Header.XferState), 1665 "\20" 1666 "\1HOSTOWNED" 1667 "\2ADAPTEROWNED" 1668 "\3INITIALISED" 1669 "\4EMPTY" 1670 "\5FROMPOOL" 1671 "\6FROMHOST" 1672 "\7FROMADAP" 1673 "\10REXPECTED" 1674 "\11RNOTEXPECTED" 1675 "\12DONEADAP" 1676 "\13DONEHOST" 1677 "\14HIGH" 1678 "\15NORM" 1679 "\16ASYNC" 1680 "\17PAGEFILEIO" 1681 "\20SHUTDOWN" 1682 "\21LAZYWRITE" 1683 "\22ADAPMICROFIB" 1684 "\23BIOSFIB" 1685 "\24FAST_RESPONSE" 1686 "\25APIFIB\n", 1687 tbuf, 1688 sizeof(tbuf)); 1689 1690 printf(" XferState %s\n", tbuf); 1691 printf(" Command %d\n", le16toh(fib->Header.Command)); 1692 printf(" StructType %d\n", fib->Header.StructType); 1693 printf(" Flags 0x%x\n", fib->Header.Flags); 1694 printf(" Size %d\n", le16toh(fib->Header.Size)); 1695 printf(" SenderSize %d\n", le16toh(fib->Header.SenderSize)); 1696 printf(" SenderAddress 0x%x\n", 1697 le32toh(fib->Header.SenderFibAddress)); 1698 printf(" ReceiverAddress 0x%x\n", 1699 le32toh(fib->Header.ReceiverFibAddress)); 1700 printf(" SenderData 0x%x\n", fib->Header.SenderData); 1701 1702 switch (fib->Header.Command) { 1703 case ContainerCommand: { 1704 br = (struct aac_blockread *)fib->data; 1705 bw = (struct aac_blockwrite *)fib->data; 1706 sg = NULL; 1707 1708 if (le32toh(br->Command) == VM_CtBlockRead) { 1709 printf(" BlockRead: container %d 0x%x/%d\n", 1710 le32toh(br->ContainerId), le32toh(br->BlockNumber), 1711 le32toh(br->ByteCount)); 1712 sg = &br->SgMap; 1713 } 1714 if (le32toh(bw->Command) == VM_CtBlockWrite) { 1715 printf(" BlockWrite: container %d 0x%x/%d (%s)\n", 1716 le32toh(bw->ContainerId), le32toh(bw->BlockNumber), 1717 le32toh(bw->ByteCount), 1718 le32toh(bw->Stable) == CSTABLE ? 1719 "stable" : "unstable"); 1720 sg = &bw->SgMap; 1721 } 1722 if (sg != NULL) { 1723 printf(" %d s/g entries\n", le32toh(sg->SgCount)); 1724 for (i = 0; i < le32toh(sg->SgCount); i++) 1725 printf(" 0x%08x/%d\n", 1726 le32toh(sg->SgEntry[i].SgAddress), 1727 le32toh(sg->SgEntry[i].SgByteCount)); 1728 } 1729 break; 1730 } 1731 default: 1732 // dump first 32 bytes of fib->data 1733 printf(" Raw data:"); 1734 for (i = 0; i < 32; i++) 1735 printf(" %02x", fib->data[i]); 1736 printf("\n"); 1737 break; 1738 } 1739 } 1740 #endif /* AAC_DEBUG */ 1741