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