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