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