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