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