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