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