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