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