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