aac.c revision 1.17 1 /* $NetBSD: aac.c,v 1.17 2005/03/01 03:31:45 briggs Exp $ */
2
3 /*-
4 * Copyright (c) 2002 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.17 2005/03/01 03:31:45 briggs 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_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_fib *);
104 static void aac_host_command(struct aac_softc *);
105 static void aac_host_response(struct aac_softc *);
106 static int aac_init(struct aac_softc *);
107 static int aac_print(void *, const char *);
108 static void aac_shutdown(void *);
109 static void aac_startup(struct aac_softc *);
110 static int aac_sync_command(struct aac_softc *, u_int32_t, u_int32_t,
111 u_int32_t, u_int32_t, u_int32_t, u_int32_t *);
112 static int aac_sync_fib(struct aac_softc *, u_int32_t, u_int32_t, void *,
113 u_int16_t, void *, u_int16_t *);
114 static int aac_submatch(struct device *, struct cfdata *,
115 const locdesc_t *, void *);
116
117 #ifdef AAC_DEBUG
118 static void aac_print_fib(struct aac_softc *, struct aac_fib *, char *);
119 #endif
120
121 /*
122 * Adapter-space FIB queue manipulation.
123 *
124 * Note that the queue implementation here is a little funky; neither the PI or
125 * CI will ever be zero. This behaviour is a controller feature.
126 */
127 static struct {
128 int size;
129 int notify;
130 } const aac_qinfo[] = {
131 { AAC_HOST_NORM_CMD_ENTRIES, AAC_DB_COMMAND_NOT_FULL },
132 { AAC_HOST_HIGH_CMD_ENTRIES, 0 },
133 { AAC_ADAP_NORM_CMD_ENTRIES, AAC_DB_COMMAND_READY },
134 { AAC_ADAP_HIGH_CMD_ENTRIES, 0 },
135 { AAC_HOST_NORM_RESP_ENTRIES, AAC_DB_RESPONSE_NOT_FULL },
136 { AAC_HOST_HIGH_RESP_ENTRIES, 0 },
137 { AAC_ADAP_NORM_RESP_ENTRIES, AAC_DB_RESPONSE_READY },
138 { AAC_ADAP_HIGH_RESP_ENTRIES, 0 }
139 };
140
141 #ifdef AAC_DEBUG
142 int aac_debug = AAC_DEBUG;
143 #endif
144
145 static void *aac_sdh;
146
147 extern struct cfdriver aac_cd;
148
149 int
150 aac_attach(struct aac_softc *sc)
151 {
152 struct aac_attach_args aaca;
153 int nsegs, i, rv, state, size;
154 struct aac_ccb *ac;
155 struct aac_fib *fib;
156 bus_addr_t fibpa;
157 int help[2];
158 locdesc_t *ldesc = (void *)help; /* XXX */
159
160 SIMPLEQ_INIT(&sc->sc_ccb_free);
161 SIMPLEQ_INIT(&sc->sc_ccb_queue);
162 SIMPLEQ_INIT(&sc->sc_ccb_complete);
163
164 /*
165 * Disable interrupts before we do anything.
166 */
167 AAC_MASK_INTERRUPTS(sc);
168
169 /*
170 * Initialise the adapter.
171 */
172 if (aac_check_firmware(sc))
173 return (EINVAL);
174
175 if ((rv = aac_init(sc)) != 0)
176 return (rv);
177 aac_startup(sc);
178
179 /*
180 * Print a little information about the controller.
181 */
182 aac_describe_controller(sc);
183
184 /*
185 * Initialize the ccbs.
186 */
187 sc->sc_ccbs = malloc(sizeof(*ac) * AAC_NCCBS, M_DEVBUF,
188 M_NOWAIT | M_ZERO);
189 if (sc->sc_ccbs == NULL) {
190 aprint_error("%s: memory allocation failure\n",
191 sc->sc_dv.dv_xname);
192 return (ENOMEM);
193 }
194 state = 0;
195 size = sizeof(*fib) * AAC_NCCBS;
196
197 if ((rv = bus_dmamap_create(sc->sc_dmat, size, 1, size,
198 0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &sc->sc_fibs_dmamap)) != 0) {
199 aprint_error("%s: cannot create fibs dmamap\n",
200 sc->sc_dv.dv_xname);
201 goto bail_out;
202 }
203 state++;
204 if ((rv = bus_dmamem_alloc(sc->sc_dmat, size, PAGE_SIZE, 0,
205 &sc->sc_fibs_seg, 1, &nsegs, BUS_DMA_NOWAIT)) != 0) {
206 aprint_error("%s: can't allocate fibs structure\n",
207 sc->sc_dv.dv_xname);
208 goto bail_out;
209 }
210 state++;
211 if ((rv = bus_dmamem_map(sc->sc_dmat, &sc->sc_fibs_seg, nsegs, size,
212 (caddr_t *)&sc->sc_fibs, 0)) != 0) {
213 aprint_error("%s: can't map fibs structure\n",
214 sc->sc_dv.dv_xname);
215 goto bail_out;
216 }
217 state++;
218 if ((rv = bus_dmamap_load(sc->sc_dmat, sc->sc_fibs_dmamap, sc->sc_fibs,
219 size, NULL, BUS_DMA_NOWAIT)) != 0) {
220 aprint_error("%s: cannot load fibs dmamap\n",
221 sc->sc_dv.dv_xname);
222 goto bail_out;
223 }
224 state++;
225
226 memset(sc->sc_fibs, 0, size);
227 fibpa = sc->sc_fibs_seg.ds_addr;
228 fib = sc->sc_fibs;
229
230 for (i = 0, ac = sc->sc_ccbs; i < AAC_NCCBS; i++, ac++) {
231 rv = bus_dmamap_create(sc->sc_dmat, AAC_MAX_XFER,
232 AAC_MAX_SGENTRIES, AAC_MAX_XFER, 0,
233 BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &ac->ac_dmamap_xfer);
234 if (rv) {
235 while (--ac >= sc->sc_ccbs)
236 bus_dmamap_destroy(sc->sc_dmat,
237 ac->ac_dmamap_xfer);
238 aprint_error("%s: cannot create ccb dmamap (%d)",
239 sc->sc_dv.dv_xname, rv);
240 goto bail_out;
241 }
242
243 ac->ac_fib = fib++;
244 ac->ac_fibphys = fibpa;
245 fibpa += sizeof(*fib);
246 aac_ccb_free(sc, ac);
247 }
248
249 /*
250 * Attach devices.
251 */
252 for (i = 0; i < AAC_MAX_CONTAINERS; i++) {
253 if (!sc->sc_hdr[i].hd_present)
254 continue;
255 aaca.aaca_unit = i;
256
257 ldesc->len = 1;
258 ldesc->locs[AACCF_UNIT] = i;
259
260 config_found_sm_loc(&sc->sc_dv, "aac", ldesc, &aaca,
261 aac_print, aac_submatch);
262 }
263
264 /*
265 * Enable interrupts, and register our shutdown hook.
266 */
267 sc->sc_flags |= AAC_ONLINE;
268 AAC_UNMASK_INTERRUPTS(sc);
269 if (aac_sdh != NULL)
270 shutdownhook_establish(aac_shutdown, NULL);
271 return (0);
272
273 bail_out:
274 bus_dmamap_unload(sc->sc_dmat, sc->sc_common_dmamap);
275 bus_dmamem_unmap(sc->sc_dmat, (caddr_t)sc->sc_common,
276 sizeof(*sc->sc_common));
277 bus_dmamem_free(sc->sc_dmat, &sc->sc_common_seg, 1);
278 bus_dmamap_destroy(sc->sc_dmat, sc->sc_common_dmamap);
279
280 if (state > 3)
281 bus_dmamap_unload(sc->sc_dmat, sc->sc_fibs_dmamap);
282 if (state > 2)
283 bus_dmamem_unmap(sc->sc_dmat, (caddr_t)sc->sc_fibs, size);
284 if (state > 1)
285 bus_dmamem_free(sc->sc_dmat, &sc->sc_fibs_seg, 1);
286 if (state > 0)
287 bus_dmamap_destroy(sc->sc_dmat, sc->sc_fibs_dmamap);
288
289 free(sc->sc_ccbs, M_DEVBUF);
290 return (rv);
291 }
292
293 /*
294 * Print autoconfiguration message for a sub-device.
295 */
296 static int
297 aac_print(void *aux, const char *pnp)
298 {
299 struct aac_attach_args *aaca;
300
301 aaca = aux;
302
303 if (pnp != NULL)
304 aprint_normal("block device at %s", pnp);
305 aprint_normal(" unit %d", aaca->aaca_unit);
306 return (UNCONF);
307 }
308
309 /*
310 * Match a sub-device.
311 */
312 static int
313 aac_submatch(struct device *parent, struct cfdata *cf,
314 const locdesc_t *ldesc, void *aux)
315 {
316 struct aac_attach_args *aaca;
317
318 aaca = aux;
319
320 if (cf->cf_loc[AACCF_UNIT] != AACCF_UNIT_DEFAULT &&
321 cf->cf_loc[AACCF_UNIT] != ldesc->locs[AACCF_UNIT])
322 return (0);
323
324 return (config_match(parent, cf, aux));
325 }
326
327 /*
328 * Look up a text description of a numeric error code and return a pointer to
329 * same.
330 */
331 const char *
332 aac_describe_code(const struct aac_code_lookup *table, u_int32_t code)
333 {
334 int i;
335
336 for (i = 0; table[i].string != NULL; i++)
337 if (table[i].code == code)
338 return (table[i].string);
339
340 return (table[i + 1].string);
341 }
342
343 /*
344 * bitmask_snprintf(9) format string for the adapter options.
345 */
346 static char *optfmt =
347 "\20\1SNAPSHOT\2CLUSTERS\3WCACHE\4DATA64\5HOSTTIME\6RAID50"
348 "\7WINDOW4GB"
349 "\10SCSIUPGD\11SOFTERR\12NORECOND\13SGMAP64\14ALARM\15NONDASD";
350
351 static void
352 aac_describe_controller(struct aac_softc *sc)
353 {
354 u_int8_t fmtbuf[256];
355 u_int8_t buf[AAC_FIB_DATASIZE];
356 u_int16_t bufsize;
357 struct aac_adapter_info *info;
358 u_int8_t arg;
359
360 arg = 0;
361 if (aac_sync_fib(sc, RequestAdapterInfo, 0, &arg, sizeof(arg), &buf,
362 &bufsize)) {
363 aprint_error("%s: RequestAdapterInfo failed\n",
364 sc->sc_dv.dv_xname);
365 return;
366 }
367 if (bufsize != sizeof(*info)) {
368 aprint_error("%s: "
369 "RequestAdapterInfo returned wrong data size (%d != %d)\n",
370 sc->sc_dv.dv_xname, bufsize, sizeof(*info));
371 return;
372 }
373 info = (struct aac_adapter_info *)&buf[0];
374
375 aprint_normal("%s: %s at %dMHz, %dMB mem (%dMB cache), %s\n",
376 sc->sc_dv.dv_xname,
377 aac_describe_code(aac_cpu_variant, le32toh(info->CpuVariant)),
378 le32toh(info->ClockSpeed),
379 le32toh(info->TotalMem) / (1024 * 1024),
380 le32toh(info->BufferMem) / (1024 * 1024),
381 aac_describe_code(aac_battery_platform,
382 le32toh(info->batteryPlatform)));
383
384 aprint_verbose("%s: Kernel %d.%d-%d [Build %d], ",
385 sc->sc_dv.dv_xname,
386 info->KernelRevision.external.comp.major,
387 info->KernelRevision.external.comp.minor,
388 info->KernelRevision.external.comp.dash,
389 info->KernelRevision.buildNumber);
390
391 aprint_verbose("Monitor %d.%d-%d [Build %d], S/N %6X\n",
392 info->MonitorRevision.external.comp.major,
393 info->MonitorRevision.external.comp.minor,
394 info->MonitorRevision.external.comp.dash,
395 info->MonitorRevision.buildNumber,
396 ((u_int32_t)info->SerialNumber & 0xffffff));
397
398 aprint_verbose("%s: Controller supports: %s\n",
399 sc->sc_dv.dv_xname,
400 bitmask_snprintf(sc->sc_supported_options, optfmt, fmtbuf,
401 sizeof(fmtbuf)));
402
403 /* Save the kernel revision structure for later use. */
404 sc->sc_revision = info->KernelRevision;
405 }
406
407 /*
408 * Retrieve the firmware version numbers. Dell PERC2/QC cards with firmware
409 * version 1.x are not compatible with this driver.
410 */
411 static int
412 aac_check_firmware(struct aac_softc *sc)
413 {
414 u_int32_t major, minor, opts;
415
416 if ((sc->sc_quirks & AAC_QUIRK_PERC2QC) != 0) {
417 if (aac_sync_command(sc, AAC_MONKER_GETKERNVER, 0, 0, 0, 0,
418 NULL)) {
419 aprint_error("%s: error reading firmware version\n",
420 sc->sc_dv.dv_xname);
421 return (1);
422 }
423
424 /* These numbers are stored as ASCII! */
425 major = (AAC_GET_MAILBOX(sc, 1) & 0xff) - 0x30;
426 minor = (AAC_GET_MAILBOX(sc, 2) & 0xff) - 0x30;
427 if (major == 1) {
428 aprint_error(
429 "%s: firmware version %d.%d not supported.\n",
430 sc->sc_dv.dv_xname, major, minor);
431 return (1);
432 }
433 }
434
435 if (aac_sync_command(sc, AAC_MONKER_GETINFO, 0, 0, 0, 0, NULL)) {
436 aprint_error("%s: GETINFO failed\n", sc->sc_dv.dv_xname);
437 return (1);
438 }
439 opts = AAC_GET_MAILBOX(sc, 1);
440 sc->sc_supported_options = opts;
441
442 /* XXX -- Enable 64-bit sglists if we can */
443
444 return (0);
445 }
446
447 static int
448 aac_init(struct aac_softc *sc)
449 {
450 int nsegs, i, rv, state, norm, high;
451 struct aac_adapter_init *ip;
452 u_int32_t code;
453 u_int8_t *qaddr;
454
455 state = 0;
456
457 /*
458 * First wait for the adapter to come ready.
459 */
460 for (i = 0; i < AAC_BOOT_TIMEOUT * 1000; i++) {
461 code = AAC_GET_FWSTATUS(sc);
462 if ((code & AAC_SELF_TEST_FAILED) != 0) {
463 aprint_error("%s: FATAL: selftest failed\n",
464 sc->sc_dv.dv_xname);
465 return (ENXIO);
466 }
467 if ((code & AAC_KERNEL_PANIC) != 0) {
468 aprint_error("%s: FATAL: controller kernel panic\n",
469 sc->sc_dv.dv_xname);
470 return (ENXIO);
471 }
472 if ((code & AAC_UP_AND_RUNNING) != 0)
473 break;
474 DELAY(1000);
475 }
476 if (i == AAC_BOOT_TIMEOUT * 1000) {
477 aprint_error(
478 "%s: FATAL: controller not coming ready, status %x\n",
479 sc->sc_dv.dv_xname, code);
480 return (ENXIO);
481 }
482
483 if ((rv = bus_dmamap_create(sc->sc_dmat, sizeof(*sc->sc_common), 1,
484 sizeof(*sc->sc_common), 0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW,
485 &sc->sc_common_dmamap)) != 0) {
486 aprint_error("%s: cannot create common dmamap\n",
487 sc->sc_dv.dv_xname);
488 return (rv);
489 }
490 if ((rv = bus_dmamem_alloc(sc->sc_dmat, sizeof(*sc->sc_common),
491 PAGE_SIZE, 0, &sc->sc_common_seg, 1, &nsegs,
492 BUS_DMA_NOWAIT)) != 0) {
493 aprint_error("%s: can't allocate common structure\n",
494 sc->sc_dv.dv_xname);
495 goto bail_out;
496 }
497 state++;
498 if ((rv = bus_dmamem_map(sc->sc_dmat, &sc->sc_common_seg, nsegs,
499 sizeof(*sc->sc_common), (caddr_t *)&sc->sc_common, 0)) != 0) {
500 aprint_error("%s: can't map common structure\n",
501 sc->sc_dv.dv_xname);
502 goto bail_out;
503 }
504 state++;
505 if ((rv = bus_dmamap_load(sc->sc_dmat, sc->sc_common_dmamap,
506 sc->sc_common, sizeof(*sc->sc_common), NULL,
507 BUS_DMA_NOWAIT)) != 0) {
508 aprint_error("%s: cannot load common dmamap\n",
509 sc->sc_dv.dv_xname);
510 goto bail_out;
511 }
512 state++;
513
514 memset(sc->sc_common, 0, sizeof(*sc->sc_common));
515
516 /*
517 * Fill in the init structure. This tells the adapter about the
518 * physical location of various important shared data structures.
519 */
520 ip = &sc->sc_common->ac_init;
521 ip->InitStructRevision = htole32(AAC_INIT_STRUCT_REVISION);
522
523 ip->AdapterFibsPhysicalAddress = htole32(sc->sc_common_seg.ds_addr +
524 offsetof(struct aac_common, ac_fibs));
525 ip->AdapterFibsVirtualAddress =
526 (void *)(intptr_t) htole32(&sc->sc_common->ac_fibs[0]);
527 ip->AdapterFibsSize =
528 htole32(AAC_ADAPTER_FIBS * sizeof(struct aac_fib));
529 ip->AdapterFibAlign = htole32(sizeof(struct aac_fib));
530
531 ip->PrintfBufferAddress = htole32(sc->sc_common_seg.ds_addr +
532 offsetof(struct aac_common, ac_printf));
533 ip->PrintfBufferSize = htole32(AAC_PRINTF_BUFSIZE);
534
535 ip->HostPhysMemPages = 0; /* not used? */
536 ip->HostElapsedSeconds = 0; /* reset later if invalid */
537
538 /*
539 * Initialise FIB queues. Note that it appears that the layout of
540 * the indexes and the segmentation of the entries is mandated by
541 * the adapter, which is only told about the base of the queue index
542 * fields.
543 *
544 * The initial values of the indices are assumed to inform the
545 * adapter of the sizes of the respective queues.
546 *
547 * The Linux driver uses a much more complex scheme whereby several
548 * header records are kept for each queue. We use a couple of
549 * generic list manipulation functions which 'know' the size of each
550 * list by virtue of a table.
551 */
552 qaddr = &sc->sc_common->ac_qbuf[0] + AAC_QUEUE_ALIGN;
553 qaddr -= (u_int32_t)qaddr % AAC_QUEUE_ALIGN; /* XXX not portable */
554 sc->sc_queues = (struct aac_queue_table *)qaddr;
555 ip->CommHeaderAddress = htole32(sc->sc_common_seg.ds_addr +
556 ((caddr_t)sc->sc_queues - (caddr_t)sc->sc_common));
557 memset(sc->sc_queues, 0, sizeof(struct aac_queue_table));
558
559 norm = htole32(AAC_HOST_NORM_CMD_ENTRIES);
560 high = htole32(AAC_HOST_HIGH_CMD_ENTRIES);
561
562 sc->sc_queues->qt_qindex[AAC_HOST_NORM_CMD_QUEUE][AAC_PRODUCER_INDEX] =
563 norm;
564 sc->sc_queues->qt_qindex[AAC_HOST_NORM_CMD_QUEUE][AAC_CONSUMER_INDEX] =
565 norm;
566 sc->sc_queues->qt_qindex[AAC_HOST_HIGH_CMD_QUEUE][AAC_PRODUCER_INDEX] =
567 high;
568 sc->sc_queues->qt_qindex[AAC_HOST_HIGH_CMD_QUEUE][AAC_CONSUMER_INDEX] =
569 high;
570
571 norm = htole32(AAC_ADAP_NORM_CMD_ENTRIES);
572 high = htole32(AAC_ADAP_HIGH_CMD_ENTRIES);
573
574 sc->sc_queues->qt_qindex[AAC_ADAP_NORM_CMD_QUEUE][AAC_PRODUCER_INDEX] =
575 norm;
576 sc->sc_queues->qt_qindex[AAC_ADAP_NORM_CMD_QUEUE][AAC_CONSUMER_INDEX] =
577 norm;
578 sc->sc_queues->qt_qindex[AAC_ADAP_HIGH_CMD_QUEUE][AAC_PRODUCER_INDEX] =
579 high;
580 sc->sc_queues->qt_qindex[AAC_ADAP_HIGH_CMD_QUEUE][AAC_CONSUMER_INDEX] =
581 high;
582
583 norm = htole32(AAC_HOST_NORM_RESP_ENTRIES);
584 high = htole32(AAC_HOST_HIGH_RESP_ENTRIES);
585
586 sc->sc_queues->
587 qt_qindex[AAC_HOST_NORM_RESP_QUEUE][AAC_PRODUCER_INDEX] = norm;
588 sc->sc_queues->
589 qt_qindex[AAC_HOST_NORM_RESP_QUEUE][AAC_CONSUMER_INDEX] = norm;
590 sc->sc_queues->
591 qt_qindex[AAC_HOST_HIGH_RESP_QUEUE][AAC_PRODUCER_INDEX] = high;
592 sc->sc_queues->
593 qt_qindex[AAC_HOST_HIGH_RESP_QUEUE][AAC_CONSUMER_INDEX] = high;
594
595 norm = htole32(AAC_ADAP_NORM_RESP_ENTRIES);
596 high = htole32(AAC_ADAP_HIGH_RESP_ENTRIES);
597
598 sc->sc_queues->
599 qt_qindex[AAC_ADAP_NORM_RESP_QUEUE][AAC_PRODUCER_INDEX] = norm;
600 sc->sc_queues->
601 qt_qindex[AAC_ADAP_NORM_RESP_QUEUE][AAC_CONSUMER_INDEX] = norm;
602 sc->sc_queues->
603 qt_qindex[AAC_ADAP_HIGH_RESP_QUEUE][AAC_PRODUCER_INDEX] = high;
604 sc->sc_queues->
605 qt_qindex[AAC_ADAP_HIGH_RESP_QUEUE][AAC_CONSUMER_INDEX] = high;
606
607 sc->sc_qentries[AAC_HOST_NORM_CMD_QUEUE] =
608 &sc->sc_queues->qt_HostNormCmdQueue[0];
609 sc->sc_qentries[AAC_HOST_HIGH_CMD_QUEUE] =
610 &sc->sc_queues->qt_HostHighCmdQueue[0];
611 sc->sc_qentries[AAC_ADAP_NORM_CMD_QUEUE] =
612 &sc->sc_queues->qt_AdapNormCmdQueue[0];
613 sc->sc_qentries[AAC_ADAP_HIGH_CMD_QUEUE] =
614 &sc->sc_queues->qt_AdapHighCmdQueue[0];
615 sc->sc_qentries[AAC_HOST_NORM_RESP_QUEUE] =
616 &sc->sc_queues->qt_HostNormRespQueue[0];
617 sc->sc_qentries[AAC_HOST_HIGH_RESP_QUEUE] =
618 &sc->sc_queues->qt_HostHighRespQueue[0];
619 sc->sc_qentries[AAC_ADAP_NORM_RESP_QUEUE] =
620 &sc->sc_queues->qt_AdapNormRespQueue[0];
621 sc->sc_qentries[AAC_ADAP_HIGH_RESP_QUEUE] =
622 &sc->sc_queues->qt_AdapHighRespQueue[0];
623
624 /*
625 * Do controller-type-specific initialisation
626 */
627 switch (sc->sc_hwif) {
628 case AAC_HWIF_I960RX:
629 AAC_SETREG4(sc, AAC_RX_ODBR, ~0);
630 break;
631 }
632
633 bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap, 0,
634 sizeof(*sc->sc_common),
635 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
636
637 /*
638 * Give the init structure to the controller.
639 */
640 if (aac_sync_command(sc, AAC_MONKER_INITSTRUCT,
641 sc->sc_common_seg.ds_addr + offsetof(struct aac_common, ac_init),
642 0, 0, 0, NULL)) {
643 aprint_error("%s: error establishing init structure\n",
644 sc->sc_dv.dv_xname);
645 rv = EIO;
646 goto bail_out;
647 }
648
649 return (0);
650
651 bail_out:
652 if (state > 2)
653 bus_dmamap_unload(sc->sc_dmat, sc->sc_common_dmamap);
654 if (state > 1)
655 bus_dmamem_unmap(sc->sc_dmat, (caddr_t)sc->sc_common,
656 sizeof(*sc->sc_common));
657 if (state > 0)
658 bus_dmamem_free(sc->sc_dmat, &sc->sc_common_seg, 1);
659 bus_dmamap_destroy(sc->sc_dmat, sc->sc_common_dmamap);
660
661 return (rv);
662 }
663
664 /*
665 * Probe for containers, create disks.
666 */
667 static void
668 aac_startup(struct aac_softc *sc)
669 {
670 struct aac_mntinfo mi;
671 struct aac_mntinforesponse mir;
672 struct aac_drive *hd;
673 u_int16_t rsize;
674 int i;
675
676 /*
677 * Loop over possible containers.
678 */
679 hd = sc->sc_hdr;
680
681 for (i = 0; i < AAC_MAX_CONTAINERS; i++, hd++) {
682 /*
683 * Request information on this container.
684 */
685 memset(&mi, 0, sizeof(mi));
686 mi.Command = htole32(VM_NameServe);
687 mi.MntType = htole32(FT_FILESYS);
688 mi.MntCount = htole32(i);
689 if (aac_sync_fib(sc, ContainerCommand, 0, &mi, sizeof(mi), &mir,
690 &rsize)) {
691 aprint_error("%s: error probing container %d\n",
692 sc->sc_dv.dv_xname, i);
693 continue;
694 }
695 if (rsize != sizeof(mir)) {
696 aprint_error("%s: container info response wrong size "
697 "(%d should be %d)\n",
698 sc->sc_dv.dv_xname, rsize, sizeof(mir));
699 continue;
700 }
701
702 /*
703 * Check container volume type for validity. Note that many
704 * of the possible types may never show up.
705 */
706 if (le32toh(mir.Status) != ST_OK ||
707 le32toh(mir.MntTable[0].VolType) == CT_NONE)
708 continue;
709
710 hd->hd_present = 1;
711 hd->hd_size = le32toh(mir.MntTable[0].Capacity);
712 hd->hd_devtype = le32toh(mir.MntTable[0].VolType);
713 hd->hd_size &= ~0x1f;
714 sc->sc_nunits++;
715 }
716 }
717
718 static void
719 aac_shutdown(void *cookie)
720 {
721 struct aac_softc *sc;
722 struct aac_close_command cc;
723 u_int32_t i;
724
725 for (i = 0; i < aac_cd.cd_ndevs; i++) {
726 if ((sc = device_lookup(&aac_cd, i)) == NULL)
727 continue;
728 if ((sc->sc_flags & AAC_ONLINE) == 0)
729 continue;
730
731 AAC_MASK_INTERRUPTS(sc);
732
733 /*
734 * Send a Container shutdown followed by a HostShutdown FIB
735 * to the controller to convince it that we don't want to
736 * talk to it anymore. We've been closed and all I/O
737 * completed already
738 */
739 memset(&cc, 0, sizeof(cc));
740 cc.Command = htole32(VM_CloseAll);
741 cc.ContainerId = 0xffffffff;
742 if (aac_sync_fib(sc, ContainerCommand, 0, &cc, sizeof(cc),
743 NULL, NULL)) {
744 printf("%s: unable to halt controller\n",
745 sc->sc_dv.dv_xname);
746 continue;
747 }
748
749 /*
750 * Note that issuing this command to the controller makes it
751 * shut down but also keeps it from coming back up without a
752 * reset of the PCI bus.
753 */
754 if (aac_sync_fib(sc, FsaHostShutdown, AAC_FIBSTATE_SHUTDOWN,
755 &i, sizeof(i), NULL, NULL))
756 printf("%s: unable to halt controller\n",
757 sc->sc_dv.dv_xname);
758
759 sc->sc_flags &= ~AAC_ONLINE;
760 }
761 }
762
763 /*
764 * Take an interrupt.
765 */
766 int
767 aac_intr(void *cookie)
768 {
769 struct aac_softc *sc;
770 u_int16_t reason;
771 int claimed;
772
773 sc = cookie;
774 claimed = 0;
775
776 AAC_DPRINTF(AAC_D_INTR, ("aac_intr(%p) ", sc));
777
778 reason = AAC_GET_ISTATUS(sc);
779 AAC_DPRINTF(AAC_D_INTR, ("istatus 0x%04x ", reason));
780
781 /*
782 * Controller wants to talk to the log. XXX Should we defer this?
783 */
784 if ((reason & AAC_DB_PRINTF) != 0) {
785 if (sc->sc_common->ac_printf[0] != '\0') {
786 printf("%s: WARNING: adapter logged message:\n",
787 sc->sc_dv.dv_xname);
788 printf("%s: %.*s", sc->sc_dv.dv_xname,
789 AAC_PRINTF_BUFSIZE, sc->sc_common->ac_printf);
790 sc->sc_common->ac_printf[0] = '\0';
791 }
792 AAC_CLEAR_ISTATUS(sc, AAC_DB_PRINTF);
793 AAC_QNOTIFY(sc, AAC_DB_PRINTF);
794 claimed = 1;
795 }
796
797 /*
798 * Controller has a message for us?
799 */
800 if ((reason & AAC_DB_COMMAND_READY) != 0) {
801 aac_host_command(sc);
802 AAC_CLEAR_ISTATUS(sc, AAC_DB_COMMAND_READY);
803 claimed = 1;
804 }
805
806 /*
807 * Controller has a response for us?
808 */
809 if ((reason & AAC_DB_RESPONSE_READY) != 0) {
810 aac_host_response(sc);
811 AAC_CLEAR_ISTATUS(sc, AAC_DB_RESPONSE_READY);
812 claimed = 1;
813 }
814
815 /*
816 * Spurious interrupts that we don't use - reset the mask and clear
817 * the interrupts.
818 */
819 if ((reason & (AAC_DB_SYNC_COMMAND | AAC_DB_COMMAND_NOT_FULL |
820 AAC_DB_RESPONSE_NOT_FULL)) != 0) {
821 AAC_UNMASK_INTERRUPTS(sc);
822 AAC_CLEAR_ISTATUS(sc, AAC_DB_SYNC_COMMAND |
823 AAC_DB_COMMAND_NOT_FULL | AAC_DB_RESPONSE_NOT_FULL);
824 claimed = 1;
825 }
826
827 return (claimed);
828 }
829
830 /*
831 * Handle notification of one or more FIBs coming from the controller.
832 */
833 static void
834 aac_host_command(struct aac_softc *sc)
835 {
836 struct aac_fib *fib;
837 u_int32_t fib_size;
838
839 for (;;) {
840 if (aac_dequeue_fib(sc, AAC_HOST_NORM_CMD_QUEUE, &fib_size,
841 &fib))
842 break; /* nothing to do */
843
844 bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap,
845 (caddr_t)fib - (caddr_t)sc->sc_common, sizeof(*fib),
846 BUS_DMASYNC_POSTREAD);
847
848 switch (le16toh(fib->Header.Command)) {
849 case AifRequest:
850 #ifdef notyet
851 aac_handle_aif(sc,
852 (struct aac_aif_command *)&fib->data[0]);
853 #endif
854 break;
855 default:
856 printf("%s: unknown command from controller\n",
857 sc->sc_dv.dv_xname);
858 AAC_PRINT_FIB(sc, fib);
859 break;
860 }
861
862 bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap,
863 (caddr_t)fib - (caddr_t)sc->sc_common, sizeof(*fib),
864 BUS_DMASYNC_PREREAD);
865
866 /* XXX reply to FIBs requesting responses ?? */
867 /* XXX how do we return these FIBs to the controller? */
868 }
869 }
870
871 /*
872 * Handle notification of one or more FIBs completed by the controller
873 */
874 static void
875 aac_host_response(struct aac_softc *sc)
876 {
877 struct aac_ccb *ac;
878 struct aac_fib *fib;
879 u_int32_t fib_size;
880
881 /*
882 * Look for completed FIBs on our queue.
883 */
884 for (;;) {
885 if (aac_dequeue_fib(sc, AAC_HOST_NORM_RESP_QUEUE, &fib_size,
886 &fib))
887 break; /* nothing to do */
888
889 bus_dmamap_sync(sc->sc_dmat, sc->sc_fibs_dmamap,
890 (caddr_t)fib - (caddr_t)sc->sc_fibs, sizeof(*fib),
891 BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
892
893 if ((fib->Header.SenderData & 0x80000000) == 0) {
894 /* Not valid; not sent by us. */
895 AAC_PRINT_FIB(sc, fib);
896 } else {
897 ac = (struct aac_ccb *)((caddr_t)sc->sc_ccbs +
898 (fib->Header.SenderData & 0x7fffffff));
899 fib->Header.SenderData = 0;
900 SIMPLEQ_INSERT_TAIL(&sc->sc_ccb_complete, ac, ac_chain);
901 }
902 }
903
904 /*
905 * Deal with any completed commands.
906 */
907 while ((ac = SIMPLEQ_FIRST(&sc->sc_ccb_complete)) != NULL) {
908 SIMPLEQ_REMOVE_HEAD(&sc->sc_ccb_complete, ac_chain);
909 ac->ac_flags |= AAC_CCB_COMPLETED;
910
911 if (ac->ac_intr != NULL)
912 (*ac->ac_intr)(ac);
913 }
914
915 /*
916 * Try to submit more commands.
917 */
918 if (! SIMPLEQ_EMPTY(&sc->sc_ccb_queue))
919 aac_ccb_enqueue(sc, NULL);
920 }
921
922 /*
923 * Send a synchronous command to the controller and wait for a result.
924 */
925 static int
926 aac_sync_command(struct aac_softc *sc, u_int32_t command, u_int32_t arg0,
927 u_int32_t arg1, u_int32_t arg2, u_int32_t arg3, u_int32_t *sp)
928 {
929 int i;
930 u_int32_t status;
931 int s;
932
933 s = splbio();
934
935 /* Populate the mailbox. */
936 AAC_SET_MAILBOX(sc, command, arg0, arg1, arg2, arg3);
937
938 /* Ensure the sync command doorbell flag is cleared. */
939 AAC_CLEAR_ISTATUS(sc, AAC_DB_SYNC_COMMAND);
940
941 /* ... then set it to signal the adapter. */
942 AAC_QNOTIFY(sc, AAC_DB_SYNC_COMMAND);
943 DELAY(AAC_SYNC_DELAY);
944
945 /* Spin waiting for the command to complete. */
946 for (i = 0; i < AAC_IMMEDIATE_TIMEOUT * 1000; i++) {
947 if (AAC_GET_ISTATUS(sc) & AAC_DB_SYNC_COMMAND)
948 break;
949 DELAY(1000);
950 }
951 if (i == AAC_IMMEDIATE_TIMEOUT * 1000) {
952 splx(s);
953 return (EIO);
954 }
955
956 /* Clear the completion flag. */
957 AAC_CLEAR_ISTATUS(sc, AAC_DB_SYNC_COMMAND);
958
959 /* Get the command status. */
960 status = AAC_GET_MAILBOXSTATUS(sc);
961 splx(s);
962 if (sp != NULL)
963 *sp = status;
964
965 return (0); /* XXX Check command return status? */
966 }
967
968 /*
969 * Send a synchronous FIB to the controller and wait for a result.
970 */
971 static int
972 aac_sync_fib(struct aac_softc *sc, u_int32_t command, u_int32_t xferstate,
973 void *data, u_int16_t datasize, void *result,
974 u_int16_t *resultsize)
975 {
976 struct aac_fib *fib;
977 u_int32_t fibpa, status;
978
979 fib = &sc->sc_common->ac_sync_fib;
980 fibpa = sc->sc_common_seg.ds_addr +
981 offsetof(struct aac_common, ac_sync_fib);
982
983 if (datasize > AAC_FIB_DATASIZE)
984 return (EINVAL);
985
986 /*
987 * Set up the sync FIB.
988 */
989 fib->Header.XferState = htole32(AAC_FIBSTATE_HOSTOWNED |
990 AAC_FIBSTATE_INITIALISED | AAC_FIBSTATE_EMPTY | xferstate);
991 fib->Header.Command = htole16(command);
992 fib->Header.StructType = AAC_FIBTYPE_TFIB;
993 fib->Header.Size = htole16(sizeof(*fib) + datasize);
994 fib->Header.SenderSize = htole16(sizeof(*fib));
995 fib->Header.SenderFibAddress = 0; /* htole32((u_int32_t)fib); * XXX */
996 fib->Header.ReceiverFibAddress = htole32(fibpa);
997
998 /*
999 * Copy in data.
1000 */
1001 if (data != NULL) {
1002 memcpy(fib->data, data, datasize);
1003 fib->Header.XferState |=
1004 htole32(AAC_FIBSTATE_FROMHOST | AAC_FIBSTATE_NORM);
1005 }
1006
1007 bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap,
1008 (caddr_t)fib - (caddr_t)sc->sc_common, sizeof(*fib),
1009 BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
1010
1011 /*
1012 * Give the FIB to the controller, wait for a response.
1013 */
1014 if (aac_sync_command(sc, AAC_MONKER_SYNCFIB, fibpa, 0, 0, 0, &status))
1015 return (EIO);
1016 if (status != 1) {
1017 printf("%s: syncfib command %04x status %08x\n",
1018 sc->sc_dv.dv_xname, command, status);
1019 }
1020
1021 bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap,
1022 (caddr_t)fib - (caddr_t)sc->sc_common, sizeof(*fib),
1023 BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
1024
1025 /*
1026 * Copy out the result
1027 */
1028 if (result != NULL) {
1029 *resultsize = le16toh(fib->Header.Size) - sizeof(fib->Header);
1030 memcpy(result, fib->data, *resultsize);
1031 }
1032
1033 return (0);
1034 }
1035
1036 struct aac_ccb *
1037 aac_ccb_alloc(struct aac_softc *sc, int flags)
1038 {
1039 struct aac_ccb *ac;
1040 int s;
1041
1042 AAC_DPRINTF(AAC_D_QUEUE, ("aac_ccb_alloc(%p, 0x%x) ", sc, flags));
1043
1044 s = splbio();
1045 ac = SIMPLEQ_FIRST(&sc->sc_ccb_free);
1046 #ifdef DIAGNOSTIC
1047 if (ac == NULL)
1048 panic("aac_ccb_get: no free CCBS");
1049 #endif
1050 SIMPLEQ_REMOVE_HEAD(&sc->sc_ccb_free, ac_chain);
1051 splx(s);
1052
1053 ac->ac_flags = flags;
1054 return (ac);
1055 }
1056
1057 void
1058 aac_ccb_free(struct aac_softc *sc, struct aac_ccb *ac)
1059 {
1060 int s;
1061
1062 AAC_DPRINTF(AAC_D_QUEUE, ("aac_ccb_free(%p, %p) ", sc, ac));
1063
1064 ac->ac_flags = 0;
1065 ac->ac_intr = NULL;
1066 ac->ac_fib->Header.XferState = htole32(AAC_FIBSTATE_EMPTY);
1067 ac->ac_fib->Header.StructType = AAC_FIBTYPE_TFIB;
1068 ac->ac_fib->Header.Flags = 0;
1069 ac->ac_fib->Header.SenderSize = htole16(sizeof(*ac->ac_fib));
1070
1071 #ifdef AAC_DEBUG
1072 /*
1073 * These are duplicated in aac_ccb_submit() to cover the case where
1074 * an intermediate stage may have destroyed them. They're left
1075 * initialised here for debugging purposes only.
1076 */
1077 ac->ac_fib->Header.SenderFibAddress = htole32((u_int32_t)ac->ac_fib);
1078 ac->ac_fib->Header.ReceiverFibAddress = htole32(ac->ac_fibphys);
1079 #endif
1080
1081 s = splbio();
1082 SIMPLEQ_INSERT_HEAD(&sc->sc_ccb_free, ac, ac_chain);
1083 splx(s);
1084 }
1085
1086 int
1087 aac_ccb_map(struct aac_softc *sc, struct aac_ccb *ac)
1088 {
1089 int error;
1090
1091 AAC_DPRINTF(AAC_D_QUEUE, ("aac_ccb_map(%p, %p) ", sc, ac));
1092
1093 #ifdef DIAGNOSTIC
1094 if ((ac->ac_flags & AAC_CCB_MAPPED) != 0)
1095 panic("aac_ccb_map: already mapped");
1096 #endif
1097
1098 error = bus_dmamap_load(sc->sc_dmat, ac->ac_dmamap_xfer, ac->ac_data,
1099 ac->ac_datalen, NULL, BUS_DMA_NOWAIT | BUS_DMA_STREAMING |
1100 ((ac->ac_flags & AAC_CCB_DATA_IN) ? BUS_DMA_READ : BUS_DMA_WRITE));
1101 if (error) {
1102 printf("%s: aac_ccb_map: ", sc->sc_dv.dv_xname);
1103 if (error == EFBIG)
1104 printf("more than %d DMA segs\n", AAC_MAX_SGENTRIES);
1105 else
1106 printf("error %d loading DMA map\n", error);
1107 return (error);
1108 }
1109
1110 bus_dmamap_sync(sc->sc_dmat, ac->ac_dmamap_xfer, 0, ac->ac_datalen,
1111 (ac->ac_flags & AAC_CCB_DATA_IN) ? BUS_DMASYNC_PREREAD :
1112 BUS_DMASYNC_PREWRITE);
1113
1114 #ifdef DIAGNOSTIC
1115 ac->ac_flags |= AAC_CCB_MAPPED;
1116 #endif
1117 return (0);
1118 }
1119
1120 void
1121 aac_ccb_unmap(struct aac_softc *sc, struct aac_ccb *ac)
1122 {
1123
1124 AAC_DPRINTF(AAC_D_QUEUE, ("aac_ccb_unmap(%p, %p) ", sc, ac));
1125
1126 #ifdef DIAGNOSTIC
1127 if ((ac->ac_flags & AAC_CCB_MAPPED) == 0)
1128 panic("aac_ccb_unmap: not mapped");
1129 #endif
1130
1131 bus_dmamap_sync(sc->sc_dmat, ac->ac_dmamap_xfer, 0, ac->ac_datalen,
1132 (ac->ac_flags & AAC_CCB_DATA_IN) ? BUS_DMASYNC_POSTREAD :
1133 BUS_DMASYNC_POSTWRITE);
1134 bus_dmamap_unload(sc->sc_dmat, ac->ac_dmamap_xfer);
1135
1136 #ifdef DIAGNOSTIC
1137 ac->ac_flags &= ~AAC_CCB_MAPPED;
1138 #endif
1139 }
1140
1141 void
1142 aac_ccb_enqueue(struct aac_softc *sc, struct aac_ccb *ac)
1143 {
1144 int s;
1145
1146 AAC_DPRINTF(AAC_D_QUEUE, ("aac_ccb_enqueue(%p, %p) ", sc, ac));
1147
1148 s = splbio();
1149
1150 if (ac != NULL)
1151 SIMPLEQ_INSERT_TAIL(&sc->sc_ccb_queue, ac, ac_chain);
1152
1153 while ((ac = SIMPLEQ_FIRST(&sc->sc_ccb_queue)) != NULL) {
1154 if (aac_ccb_submit(sc, ac))
1155 break;
1156 SIMPLEQ_REMOVE_HEAD(&sc->sc_ccb_queue, ac_chain);
1157 }
1158
1159 splx(s);
1160 }
1161
1162 int
1163 aac_ccb_submit(struct aac_softc *sc, struct aac_ccb *ac)
1164 {
1165
1166 AAC_DPRINTF(AAC_D_QUEUE, ("aac_ccb_submit(%p, %p) ", sc, ac));
1167
1168 /* Fix up the address values. */
1169 ac->ac_fib->Header.SenderFibAddress = htole32((u_int32_t)ac->ac_fib);
1170 ac->ac_fib->Header.ReceiverFibAddress = htole32(ac->ac_fibphys);
1171
1172 /* Save a pointer to the command for speedy reverse-lookup. */
1173 ac->ac_fib->Header.SenderData =
1174 (u_int32_t)((caddr_t)ac - (caddr_t)sc->sc_ccbs) | 0x80000000;
1175
1176 bus_dmamap_sync(sc->sc_dmat, sc->sc_fibs_dmamap,
1177 (caddr_t)ac->ac_fib - (caddr_t)sc->sc_fibs, sizeof(*ac->ac_fib),
1178 BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
1179
1180 /* Put the FIB on the outbound queue. */
1181 return (aac_enqueue_fib(sc, AAC_ADAP_NORM_CMD_QUEUE, ac->ac_fib));
1182 }
1183
1184 int
1185 aac_ccb_poll(struct aac_softc *sc, struct aac_ccb *ac, int timo)
1186 {
1187 int rv, s;
1188
1189 AAC_DPRINTF(AAC_D_QUEUE, ("aac_ccb_poll(%p, %p, %d) ", sc, ac, timo));
1190
1191 s = splbio();
1192
1193 if ((rv = aac_ccb_submit(sc, ac)) != 0) {
1194 splx(s);
1195 return (rv);
1196 }
1197
1198 for (timo *= 1000; timo != 0; timo--) {
1199 aac_intr(sc);
1200 if ((ac->ac_flags & AAC_CCB_COMPLETED) != 0)
1201 break;
1202 DELAY(100);
1203 }
1204
1205 splx(s);
1206 return (timo == 0);
1207 }
1208
1209 /*
1210 * Atomically insert an entry into the nominated queue, returns 0 on success
1211 * or EBUSY if the queue is full.
1212 *
1213 * XXX Note that it would be more efficient to defer notifying the
1214 * controller in the case where we may be inserting several entries in rapid
1215 * succession, but implementing this usefully is difficult.
1216 */
1217 static int
1218 aac_enqueue_fib(struct aac_softc *sc, int queue, struct aac_fib *fib)
1219 {
1220 u_int32_t fib_size, fib_addr, pi, ci;
1221
1222 fib_size = le16toh(fib->Header.Size);
1223 fib_addr = le32toh(fib->Header.ReceiverFibAddress);
1224
1225 bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap,
1226 (caddr_t)sc->sc_common->ac_qbuf - (caddr_t)sc->sc_common,
1227 sizeof(sc->sc_common->ac_qbuf),
1228 BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
1229
1230 /* Get the producer/consumer indices. */
1231 pi = le32toh(sc->sc_queues->qt_qindex[queue][AAC_PRODUCER_INDEX]);
1232 ci = le32toh(sc->sc_queues->qt_qindex[queue][AAC_CONSUMER_INDEX]);
1233
1234 /* Wrap the queue? */
1235 if (pi >= aac_qinfo[queue].size)
1236 pi = 0;
1237
1238 /* Check for queue full. */
1239 if ((pi + 1) == ci)
1240 return (EAGAIN);
1241
1242 /* Populate queue entry. */
1243 (sc->sc_qentries[queue] + pi)->aq_fib_size = htole32(fib_size);
1244 (sc->sc_qentries[queue] + pi)->aq_fib_addr = htole32(fib_addr);
1245
1246 /* Update producer index. */
1247 sc->sc_queues->qt_qindex[queue][AAC_PRODUCER_INDEX] = htole32(pi + 1);
1248
1249 bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap,
1250 (caddr_t)sc->sc_common->ac_qbuf - (caddr_t)sc->sc_common,
1251 sizeof(sc->sc_common->ac_qbuf),
1252 BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
1253
1254 /* Notify the adapter if we know how. */
1255 if (aac_qinfo[queue].notify != 0)
1256 AAC_QNOTIFY(sc, aac_qinfo[queue].notify);
1257
1258 return (0);
1259 }
1260
1261 /*
1262 * Atomically remove one entry from the nominated queue, returns 0 on success
1263 * or ENOENT if the queue is empty.
1264 */
1265 static int
1266 aac_dequeue_fib(struct aac_softc *sc, int queue, u_int32_t *fib_size,
1267 struct aac_fib **fib_addr)
1268 {
1269 u_int32_t pi, ci;
1270 int notify;
1271
1272 bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap,
1273 (caddr_t)sc->sc_common->ac_qbuf - (caddr_t)sc->sc_common,
1274 sizeof(sc->sc_common->ac_qbuf),
1275 BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
1276
1277 /* Get the producer/consumer indices. */
1278 pi = le32toh(sc->sc_queues->qt_qindex[queue][AAC_PRODUCER_INDEX]);
1279 ci = le32toh(sc->sc_queues->qt_qindex[queue][AAC_CONSUMER_INDEX]);
1280
1281 /* Check for queue empty. */
1282 if (ci == pi)
1283 return (ENOENT);
1284
1285 notify = 0;
1286 if (ci == pi + 1)
1287 notify = 1;
1288
1289 /* Wrap the queue? */
1290 if (ci >= aac_qinfo[queue].size)
1291 ci = 0;
1292
1293 /* Fetch the entry. */
1294 *fib_size = le32toh((sc->sc_qentries[queue] + ci)->aq_fib_size);
1295 *fib_addr = (void *)(intptr_t) le32toh((struct aac_fib *)
1296 (sc->sc_qentries[queue] + ci)->aq_fib_addr);
1297
1298 /* Update consumer index. */
1299 sc->sc_queues->qt_qindex[queue][AAC_CONSUMER_INDEX] = ci + 1;
1300
1301 bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap,
1302 (caddr_t)sc->sc_common->ac_qbuf - (caddr_t)sc->sc_common,
1303 sizeof(sc->sc_common->ac_qbuf),
1304 BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
1305
1306 /* If we have made the queue un-full, notify the adapter. */
1307 if (notify && (aac_qinfo[queue].notify != 0))
1308 AAC_QNOTIFY(sc, aac_qinfo[queue].notify);
1309
1310 return (0);
1311 }
1312
1313 #ifdef AAC_DEBUG
1314 /*
1315 * Print a FIB
1316 */
1317 static void
1318 aac_print_fib(struct aac_softc *sc, struct aac_fib *fib, char *caller)
1319 {
1320 struct aac_blockread *br;
1321 struct aac_blockwrite *bw;
1322 struct aac_sg_table *sg;
1323 char buf[512];
1324 int i;
1325
1326 printf("%s: FIB @ %p\n", caller, fib);
1327 bitmask_snprintf(le32toh(fib->Header.XferState),
1328 "\20"
1329 "\1HOSTOWNED"
1330 "\2ADAPTEROWNED"
1331 "\3INITIALISED"
1332 "\4EMPTY"
1333 "\5FROMPOOL"
1334 "\6FROMHOST"
1335 "\7FROMADAP"
1336 "\10REXPECTED"
1337 "\11RNOTEXPECTED"
1338 "\12DONEADAP"
1339 "\13DONEHOST"
1340 "\14HIGH"
1341 "\15NORM"
1342 "\16ASYNC"
1343 "\17PAGEFILEIO"
1344 "\20SHUTDOWN"
1345 "\21LAZYWRITE"
1346 "\22ADAPMICROFIB"
1347 "\23BIOSFIB"
1348 "\24FAST_RESPONSE"
1349 "\25APIFIB\n",
1350 buf,
1351 sizeof(buf));
1352
1353 printf(" XferState %s\n", buf);
1354 printf(" Command %d\n", le16toh(fib->Header.Command));
1355 printf(" StructType %d\n", fib->Header.StructType);
1356 printf(" Flags 0x%x\n", fib->Header.Flags);
1357 printf(" Size %d\n", le16toh(fib->Header.Size));
1358 printf(" SenderSize %d\n", le16toh(fib->Header.SenderSize));
1359 printf(" SenderAddress 0x%x\n",
1360 le32toh(fib->Header.SenderFibAddress));
1361 printf(" ReceiverAddress 0x%x\n",
1362 le32toh(fib->Header.ReceiverFibAddress));
1363 printf(" SenderData 0x%x\n", fib->Header.SenderData);
1364
1365 switch (fib->Header.Command) {
1366 case ContainerCommand: {
1367 br = (struct aac_blockread *)fib->data;
1368 bw = (struct aac_blockwrite *)fib->data;
1369 sg = NULL;
1370
1371 if (le32toh(br->Command) == VM_CtBlockRead) {
1372 printf(" BlockRead: container %d 0x%x/%d\n",
1373 le32toh(br->ContainerId), le32toh(br->BlockNumber),
1374 le32toh(br->ByteCount));
1375 sg = &br->SgMap;
1376 }
1377 if (le32toh(bw->Command) == VM_CtBlockWrite) {
1378 printf(" BlockWrite: container %d 0x%x/%d (%s)\n",
1379 le32toh(bw->ContainerId), le32toh(bw->BlockNumber),
1380 le32toh(bw->ByteCount),
1381 le32toh(bw->Stable) == CSTABLE ?
1382 "stable" : "unstable");
1383 sg = &bw->SgMap;
1384 }
1385 if (sg != NULL) {
1386 printf(" %d s/g entries\n", le32toh(sg->SgCount));
1387 for (i = 0; i < le32toh(sg->SgCount); i++)
1388 printf(" 0x%08x/%d\n",
1389 le32toh(sg->SgEntry[i].SgAddress),
1390 le32toh(sg->SgEntry[i].SgByteCount));
1391 }
1392 break;
1393 }
1394 default:
1395 printf(" %16D\n", fib->data, " ");
1396 printf(" %16D\n", fib->data + 16, " ");
1397 break;
1398 }
1399 }
1400 #endif /* AAC_DEBUG */
1401