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