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