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