aac.c revision 1.40 1 /* $NetBSD: aac.c,v 1.40 2008/06/08 12:43:51 tsutsui 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.40 2008/06/08 12:43:51 tsutsui 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_private(&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