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