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