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