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