aac.c revision 1.31 1 /* $NetBSD: aac.c,v 1.31 2007/05/24 15:07:47 briggs Exp $ */
2
3 /*-
4 * Copyright (c) 2002, 2007 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.31 2007/05/24 15:07:47 briggs Exp $");
81
82 #include <sys/param.h>
83 #include <sys/systm.h>
84 #include <sys/buf.h>
85 #include <sys/device.h>
86 #include <sys/kernel.h>
87 #include <sys/malloc.h>
88
89 #include <machine/bus.h>
90
91 #include <uvm/uvm_extern.h>
92
93 #include <dev/ic/aacreg.h>
94 #include <dev/ic/aacvar.h>
95 #include <dev/ic/aac_tables.h>
96
97 #include "locators.h"
98
99 static int aac_check_firmware(struct aac_softc *);
100 static void aac_describe_controller(struct aac_softc *);
101 static int aac_dequeue_fib(struct aac_softc *, int, u_int32_t *,
102 struct aac_fib **);
103 static int aac_enqueue_fib(struct aac_softc *, int, struct aac_fib *);
104 static int aac_enqueue_response(struct aac_softc *, int, struct aac_fib *);
105 static void aac_host_command(struct aac_softc *);
106 static void aac_host_response(struct aac_softc *);
107 static int aac_init(struct aac_softc *);
108 static int aac_print(void *, const char *);
109 static void aac_shutdown(void *);
110 static void aac_startup(struct aac_softc *);
111 static int aac_sync_command(struct aac_softc *, u_int32_t, u_int32_t,
112 u_int32_t, u_int32_t, u_int32_t, u_int32_t *);
113 static int aac_sync_fib(struct aac_softc *, u_int32_t, u_int32_t, void *,
114 u_int16_t, void *, u_int16_t *);
115
116 #ifdef AAC_DEBUG
117 static void aac_print_fib(struct aac_softc *, struct aac_fib *, const char *);
118 #endif
119
120 /*
121 * Adapter-space FIB queue manipulation.
122 *
123 * Note that the queue implementation here is a little funky; neither the PI or
124 * CI will ever be zero. This behaviour is a controller feature.
125 */
126 static struct {
127 int size;
128 int notify;
129 } const aac_qinfo[] = {
130 { AAC_HOST_NORM_CMD_ENTRIES, AAC_DB_COMMAND_NOT_FULL },
131 { AAC_HOST_HIGH_CMD_ENTRIES, 0 },
132 { AAC_ADAP_NORM_CMD_ENTRIES, AAC_DB_COMMAND_READY },
133 { AAC_ADAP_HIGH_CMD_ENTRIES, 0 },
134 { AAC_HOST_NORM_RESP_ENTRIES, AAC_DB_RESPONSE_NOT_FULL },
135 { AAC_HOST_HIGH_RESP_ENTRIES, 0 },
136 { AAC_ADAP_NORM_RESP_ENTRIES, AAC_DB_RESPONSE_READY },
137 { AAC_ADAP_HIGH_RESP_ENTRIES, 0 }
138 };
139
140 #ifdef AAC_DEBUG
141 int aac_debug = AAC_DEBUG;
142 #endif
143
144 static void *aac_sdh;
145
146 extern struct cfdriver aac_cd;
147
148 int
149 aac_attach(struct aac_softc *sc)
150 {
151 struct aac_attach_args aaca;
152 int nsegs, i, rv, state, size;
153 struct aac_ccb *ac;
154 struct aac_fib *fib;
155 bus_addr_t fibpa;
156 int locs[AACCF_NLOCS];
157
158 SIMPLEQ_INIT(&sc->sc_ccb_free);
159 SIMPLEQ_INIT(&sc->sc_ccb_queue);
160 SIMPLEQ_INIT(&sc->sc_ccb_complete);
161
162 /*
163 * Disable interrupts before we do anything.
164 */
165 AAC_MASK_INTERRUPTS(sc);
166
167 /*
168 * Initialise the adapter.
169 */
170 if (aac_check_firmware(sc))
171 return (EINVAL);
172
173 if ((rv = aac_init(sc)) != 0)
174 return (rv);
175 aac_startup(sc);
176
177 /*
178 * Print a little information about the controller.
179 */
180 aac_describe_controller(sc);
181
182 /*
183 * Initialize the ccbs.
184 */
185 sc->sc_ccbs = malloc(sizeof(*ac) * AAC_NCCBS, M_DEVBUF,
186 M_NOWAIT | M_ZERO);
187 if (sc->sc_ccbs == NULL) {
188 aprint_error("%s: memory allocation failure\n",
189 sc->sc_dv.dv_xname);
190 return (ENOMEM);
191 }
192 state = 0;
193 size = sizeof(*fib) * AAC_NCCBS;
194
195 if ((rv = bus_dmamap_create(sc->sc_dmat, size, 1, size,
196 0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &sc->sc_fibs_dmamap)) != 0) {
197 aprint_error("%s: cannot create fibs dmamap\n",
198 sc->sc_dv.dv_xname);
199 goto bail_out;
200 }
201 state++;
202 if ((rv = bus_dmamem_alloc(sc->sc_dmat, size, PAGE_SIZE, 0,
203 &sc->sc_fibs_seg, 1, &nsegs, BUS_DMA_NOWAIT)) != 0) {
204 aprint_error("%s: can't allocate fibs structure\n",
205 sc->sc_dv.dv_xname);
206 goto bail_out;
207 }
208 state++;
209 if ((rv = bus_dmamem_map(sc->sc_dmat, &sc->sc_fibs_seg, nsegs, size,
210 (void **)&sc->sc_fibs, 0)) != 0) {
211 aprint_error("%s: can't map fibs structure\n",
212 sc->sc_dv.dv_xname);
213 goto bail_out;
214 }
215 state++;
216 if ((rv = bus_dmamap_load(sc->sc_dmat, sc->sc_fibs_dmamap, sc->sc_fibs,
217 size, NULL, BUS_DMA_NOWAIT)) != 0) {
218 aprint_error("%s: cannot load fibs dmamap\n",
219 sc->sc_dv.dv_xname);
220 goto bail_out;
221 }
222 state++;
223
224 memset(sc->sc_fibs, 0, size);
225 fibpa = sc->sc_fibs_seg.ds_addr;
226 fib = sc->sc_fibs;
227
228 for (i = 0, ac = sc->sc_ccbs; i < AAC_NCCBS; i++, ac++) {
229 rv = bus_dmamap_create(sc->sc_dmat, AAC_MAX_XFER,
230 AAC_MAX_SGENTRIES, AAC_MAX_XFER, 0,
231 BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &ac->ac_dmamap_xfer);
232 if (rv) {
233 while (--ac >= sc->sc_ccbs)
234 bus_dmamap_destroy(sc->sc_dmat,
235 ac->ac_dmamap_xfer);
236 aprint_error("%s: cannot create ccb dmamap (%d)",
237 sc->sc_dv.dv_xname, rv);
238 goto bail_out;
239 }
240
241 ac->ac_fib = fib++;
242 ac->ac_fibphys = fibpa;
243 fibpa += sizeof(*fib);
244 aac_ccb_free(sc, ac);
245 }
246
247 /*
248 * Attach devices.
249 */
250 for (i = 0; i < AAC_MAX_CONTAINERS; i++) {
251 if (!sc->sc_hdr[i].hd_present)
252 continue;
253 aaca.aaca_unit = i;
254
255 locs[AACCF_UNIT] = i;
256
257 config_found_sm_loc(&sc->sc_dv, "aac", locs, &aaca,
258 aac_print, config_stdsubmatch);
259 }
260
261 /*
262 * Enable interrupts, and register our shutdown hook.
263 */
264 sc->sc_flags |= AAC_ONLINE;
265 AAC_UNMASK_INTERRUPTS(sc);
266 if (aac_sdh != NULL)
267 shutdownhook_establish(aac_shutdown, NULL);
268 return (0);
269
270 bail_out:
271 bus_dmamap_unload(sc->sc_dmat, sc->sc_common_dmamap);
272 bus_dmamem_unmap(sc->sc_dmat, (void *)sc->sc_common,
273 sizeof(*sc->sc_common));
274 bus_dmamem_free(sc->sc_dmat, &sc->sc_common_seg, 1);
275 bus_dmamap_destroy(sc->sc_dmat, sc->sc_common_dmamap);
276
277 if (state > 3)
278 bus_dmamap_unload(sc->sc_dmat, sc->sc_fibs_dmamap);
279 if (state > 2)
280 bus_dmamem_unmap(sc->sc_dmat, (void *)sc->sc_fibs, size);
281 if (state > 1)
282 bus_dmamem_free(sc->sc_dmat, &sc->sc_fibs_seg, 1);
283 if (state > 0)
284 bus_dmamap_destroy(sc->sc_dmat, sc->sc_fibs_dmamap);
285
286 free(sc->sc_ccbs, M_DEVBUF);
287 return (rv);
288 }
289
290 /*
291 * Print autoconfiguration message for a sub-device.
292 */
293 static int
294 aac_print(void *aux, const char *pnp)
295 {
296 struct aac_attach_args *aaca;
297
298 aaca = aux;
299
300 if (pnp != NULL)
301 aprint_normal("block device at %s", pnp);
302 aprint_normal(" unit %d", aaca->aaca_unit);
303 return (UNCONF);
304 }
305
306 /*
307 * Look up a text description of a numeric error code and return a pointer to
308 * same.
309 */
310 const char *
311 aac_describe_code(const struct aac_code_lookup *table, u_int32_t code)
312 {
313 int i;
314
315 for (i = 0; table[i].string != NULL; i++)
316 if (table[i].code == code)
317 return (table[i].string);
318
319 return (table[i + 1].string);
320 }
321
322 /*
323 * bitmask_snprintf(9) format string for the adapter options.
324 */
325 static const char *optfmt =
326 "\20\1SNAPSHOT\2CLUSTERS\3WCACHE\4DATA64\5HOSTTIME\6RAID50"
327 "\7WINDOW4GB"
328 "\10SCSIUPGD\11SOFTERR\12NORECOND\13SGMAP64\14ALARM\15NONDASD";
329
330 static void
331 aac_describe_controller(struct aac_softc *sc)
332 {
333 u_int8_t fmtbuf[256];
334 u_int8_t tbuf[AAC_FIB_DATASIZE];
335 u_int16_t bufsize;
336 struct aac_adapter_info *info;
337 u_int8_t arg;
338
339 arg = 0;
340 if (aac_sync_fib(sc, RequestAdapterInfo, 0, &arg, sizeof(arg), &tbuf,
341 &bufsize)) {
342 aprint_error("%s: RequestAdapterInfo failed\n",
343 sc->sc_dv.dv_xname);
344 return;
345 }
346 if (bufsize != sizeof(*info)) {
347 aprint_error("%s: "
348 "RequestAdapterInfo returned wrong data size (%d != %zu)\n",
349 sc->sc_dv.dv_xname, bufsize, sizeof(*info));
350 return;
351 }
352 info = (struct aac_adapter_info *)&tbuf[0];
353
354 aprint_normal("%s: %s at %dMHz, %dMB mem (%dMB cache), %s\n",
355 sc->sc_dv.dv_xname,
356 aac_describe_code(aac_cpu_variant, le32toh(info->CpuVariant)),
357 le32toh(info->ClockSpeed),
358 le32toh(info->TotalMem) / (1024 * 1024),
359 le32toh(info->BufferMem) / (1024 * 1024),
360 aac_describe_code(aac_battery_platform,
361 le32toh(info->batteryPlatform)));
362
363 aprint_verbose("%s: Kernel %d.%d-%d [Build %d], ",
364 sc->sc_dv.dv_xname,
365 info->KernelRevision.external.comp.major,
366 info->KernelRevision.external.comp.minor,
367 info->KernelRevision.external.comp.dash,
368 info->KernelRevision.buildNumber);
369
370 aprint_verbose("Monitor %d.%d-%d [Build %d], S/N %6X\n",
371 info->MonitorRevision.external.comp.major,
372 info->MonitorRevision.external.comp.minor,
373 info->MonitorRevision.external.comp.dash,
374 info->MonitorRevision.buildNumber,
375 ((u_int32_t)info->SerialNumber & 0xffffff));
376
377 aprint_verbose("%s: Controller supports: %s\n",
378 sc->sc_dv.dv_xname,
379 bitmask_snprintf(sc->sc_supported_options, optfmt, fmtbuf,
380 sizeof(fmtbuf)));
381
382 /* Save the kernel revision structure for later use. */
383 sc->sc_revision = info->KernelRevision;
384 }
385
386 /*
387 * Retrieve the firmware version numbers. Dell PERC2/QC cards with firmware
388 * version 1.x are not compatible with this driver.
389 */
390 static int
391 aac_check_firmware(struct aac_softc *sc)
392 {
393 u_int32_t major, minor, opts;
394
395 if ((sc->sc_quirks & AAC_QUIRK_PERC2QC) != 0) {
396 if (aac_sync_command(sc, AAC_MONKER_GETKERNVER, 0, 0, 0, 0,
397 NULL)) {
398 aprint_error("%s: error reading firmware version\n",
399 sc->sc_dv.dv_xname);
400 return (1);
401 }
402
403 /* These numbers are stored as ASCII! */
404 major = (AAC_GET_MAILBOX(sc, 1) & 0xff) - 0x30;
405 minor = (AAC_GET_MAILBOX(sc, 2) & 0xff) - 0x30;
406 if (major == 1) {
407 aprint_error(
408 "%s: firmware version %d.%d not supported.\n",
409 sc->sc_dv.dv_xname, major, minor);
410 return (1);
411 }
412 }
413
414 if (aac_sync_command(sc, AAC_MONKER_GETINFO, 0, 0, 0, 0, NULL)) {
415 aprint_error("%s: GETINFO failed\n", sc->sc_dv.dv_xname);
416 return (1);
417 }
418 opts = AAC_GET_MAILBOX(sc, 1);
419 sc->sc_supported_options = opts;
420
421 /* XXX -- Enable 64-bit sglists if we can */
422
423 return (0);
424 }
425
426 static int
427 aac_init(struct aac_softc *sc)
428 {
429 int nsegs, i, rv, state, norm, high;
430 struct aac_adapter_init *ip;
431 u_int32_t code, qoff;
432
433 state = 0;
434
435 /*
436 * First wait for the adapter to come ready.
437 */
438 for (i = 0; i < AAC_BOOT_TIMEOUT * 1000; i++) {
439 code = AAC_GET_FWSTATUS(sc);
440 if ((code & AAC_SELF_TEST_FAILED) != 0) {
441 aprint_error("%s: FATAL: selftest failed\n",
442 sc->sc_dv.dv_xname);
443 return (ENXIO);
444 }
445 if ((code & AAC_KERNEL_PANIC) != 0) {
446 aprint_error("%s: FATAL: controller kernel panic\n",
447 sc->sc_dv.dv_xname);
448 return (ENXIO);
449 }
450 if ((code & AAC_UP_AND_RUNNING) != 0)
451 break;
452 DELAY(1000);
453 }
454 if (i == AAC_BOOT_TIMEOUT * 1000) {
455 aprint_error(
456 "%s: FATAL: controller not coming ready, status %x\n",
457 sc->sc_dv.dv_xname, code);
458 return (ENXIO);
459 }
460
461 if ((rv = bus_dmamap_create(sc->sc_dmat, sizeof(*sc->sc_common), 1,
462 sizeof(*sc->sc_common), 0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW,
463 &sc->sc_common_dmamap)) != 0) {
464 aprint_error("%s: cannot create common dmamap\n",
465 sc->sc_dv.dv_xname);
466 return (rv);
467 }
468 if ((rv = bus_dmamem_alloc(sc->sc_dmat, sizeof(*sc->sc_common),
469 PAGE_SIZE, 0, &sc->sc_common_seg, 1, &nsegs,
470 BUS_DMA_NOWAIT)) != 0) {
471 aprint_error("%s: can't allocate common structure\n",
472 sc->sc_dv.dv_xname);
473 goto bail_out;
474 }
475 state++;
476 if ((rv = bus_dmamem_map(sc->sc_dmat, &sc->sc_common_seg, nsegs,
477 sizeof(*sc->sc_common), (void **)&sc->sc_common, 0)) != 0) {
478 aprint_error("%s: can't map common structure\n",
479 sc->sc_dv.dv_xname);
480 goto bail_out;
481 }
482 state++;
483 if ((rv = bus_dmamap_load(sc->sc_dmat, sc->sc_common_dmamap,
484 sc->sc_common, sizeof(*sc->sc_common), NULL,
485 BUS_DMA_NOWAIT)) != 0) {
486 aprint_error("%s: cannot load common dmamap\n",
487 sc->sc_dv.dv_xname);
488 goto bail_out;
489 }
490 state++;
491
492 memset(sc->sc_common, 0, sizeof(*sc->sc_common));
493
494 /*
495 * Fill in the init structure. This tells the adapter about the
496 * physical location of various important shared data structures.
497 */
498 ip = &sc->sc_common->ac_init;
499 ip->InitStructRevision = htole32(AAC_INIT_STRUCT_REVISION);
500
501 ip->AdapterFibsPhysicalAddress = htole32(sc->sc_common_seg.ds_addr +
502 offsetof(struct aac_common, ac_fibs));
503 ip->AdapterFibsVirtualAddress = 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 ((char *)sc->sc_queues - (char *)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, (void *)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 sc->sc_common->ac_printf[0] = ' ';
764 printf("%s: WARNING: adapter logged message:\n",
765 sc->sc_dv.dv_xname);
766 printf("%s: %.*s", sc->sc_dv.dv_xname,
767 AAC_PRINTF_BUFSIZE, sc->sc_common->ac_printf);
768 sc->sc_common->ac_printf[0] = '\0';
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 (char *)fib - (char *)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 AAC_PRINT_FIB(sc, fib);
832 break;
833 default:
834 printf("%s: unknown command from controller\n",
835 sc->sc_dv.dv_xname);
836 AAC_PRINT_FIB(sc, fib);
837 break;
838 }
839
840 bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap,
841 (char *)fib - (char *)sc->sc_common, sizeof(*fib),
842 BUS_DMASYNC_PREREAD);
843
844 if ((fib->Header.XferState == 0) ||
845 (fib->Header.StructType != AAC_FIBTYPE_TFIB)) {
846 break; // continue; ???
847 }
848
849 /* XXX reply to FIBs requesting responses ?? */
850
851 /* Return the AIF/FIB to the controller */
852 if (le32toh(fib->Header.XferState) & AAC_FIBSTATE_FROMADAP) {
853 u_int16_t size;
854
855 fib->Header.XferState |=
856 htole32(AAC_FIBSTATE_DONEHOST);
857 *(u_int32_t*)fib->data = htole32(ST_OK);
858
859 /* XXX Compute the Size field? */
860 size = le16toh(fib->Header.Size);
861 if (size > sizeof(struct aac_fib)) {
862 size = sizeof(struct aac_fib);
863 fib->Header.Size = htole16(size);
864 }
865
866 /*
867 * Since we didn't generate this command, it can't
868 * go through the normal process.
869 */
870 aac_enqueue_response(sc,
871 AAC_ADAP_NORM_RESP_QUEUE, fib);
872 }
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 (char *)fib - (char *)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 *)((char *)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; /* not needed */
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 (char *)fib - (char *)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 (char *)fib - (char *)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)(intptr_t/*XXX LP64*/)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 u_int32_t acidx;
1171
1172 AAC_DPRINTF(AAC_D_QUEUE, ("aac_ccb_submit(%p, %p) ", sc, ac));
1173
1174 acidx = (u_int32_t) ((char *)ac - (char *)sc->sc_ccbs);
1175 /* Fix up the address values. */
1176 ac->ac_fib->Header.SenderFibAddress = htole32(acidx << 2);
1177 ac->ac_fib->Header.ReceiverFibAddress = htole32(ac->ac_fibphys);
1178
1179 /* Save a pointer to the command for speedy reverse-lookup. */
1180 ac->ac_fib->Header.SenderData = acidx | 0x80000000;
1181
1182 bus_dmamap_sync(sc->sc_dmat, sc->sc_fibs_dmamap,
1183 (char *)ac->ac_fib - (char *)sc->sc_fibs, sizeof(*ac->ac_fib),
1184 BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
1185
1186 /* Put the FIB on the outbound queue. */
1187 return (aac_enqueue_fib(sc, AAC_ADAP_NORM_CMD_QUEUE, ac->ac_fib));
1188 }
1189
1190 int
1191 aac_ccb_poll(struct aac_softc *sc, struct aac_ccb *ac, int timo)
1192 {
1193 int rv, s;
1194
1195 AAC_DPRINTF(AAC_D_QUEUE, ("aac_ccb_poll(%p, %p, %d) ", sc, ac, timo));
1196
1197 s = splbio();
1198
1199 if ((rv = aac_ccb_submit(sc, ac)) != 0) {
1200 splx(s);
1201 return (rv);
1202 }
1203
1204 for (timo *= 1000; timo != 0; timo--) {
1205 aac_intr(sc);
1206 if ((ac->ac_flags & AAC_CCB_COMPLETED) != 0)
1207 break;
1208 DELAY(100);
1209 }
1210
1211 splx(s);
1212 return (timo == 0);
1213 }
1214
1215 /*
1216 * Atomically insert an entry into the nominated queue, returns 0 on success
1217 * or EBUSY if the queue is full.
1218 *
1219 * XXX Note that it would be more efficient to defer notifying the
1220 * controller in the case where we may be inserting several entries in rapid
1221 * succession, but implementing this usefully is difficult.
1222 */
1223 static int
1224 aac_enqueue_fib(struct aac_softc *sc, int queue, struct aac_fib *fib)
1225 {
1226 u_int32_t fib_size, fib_addr, pi, ci;
1227
1228 fib_size = le16toh(fib->Header.Size);
1229 fib_addr = le32toh(fib->Header.ReceiverFibAddress);
1230
1231 bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap,
1232 (char *)sc->sc_common->ac_qbuf - (char *)sc->sc_common,
1233 sizeof(sc->sc_common->ac_qbuf),
1234 BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
1235
1236 /* Get the producer/consumer indices. */
1237 pi = le32toh(sc->sc_queues->qt_qindex[queue][AAC_PRODUCER_INDEX]);
1238 ci = le32toh(sc->sc_queues->qt_qindex[queue][AAC_CONSUMER_INDEX]);
1239
1240 /* Wrap the queue? */
1241 if (pi >= aac_qinfo[queue].size)
1242 pi = 0;
1243
1244 /* Check for queue full. */
1245 if ((pi + 1) == ci)
1246 return (EAGAIN);
1247
1248 /* Populate queue entry. */
1249 (sc->sc_qentries[queue] + pi)->aq_fib_size = htole32(fib_size);
1250 (sc->sc_qentries[queue] + pi)->aq_fib_addr = htole32(fib_addr);
1251
1252 /* Update producer index. */
1253 sc->sc_queues->qt_qindex[queue][AAC_PRODUCER_INDEX] = htole32(pi + 1);
1254
1255 bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap,
1256 (char *)sc->sc_common->ac_qbuf - (char *)sc->sc_common,
1257 sizeof(sc->sc_common->ac_qbuf),
1258 BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
1259
1260 /* Notify the adapter if we know how. */
1261 if (aac_qinfo[queue].notify != 0)
1262 AAC_QNOTIFY(sc, aac_qinfo[queue].notify);
1263
1264 return (0);
1265 }
1266
1267 /*
1268 * Atomically remove one entry from the nominated queue, returns 0 on success
1269 * or ENOENT if the queue is empty.
1270 */
1271 static int
1272 aac_dequeue_fib(struct aac_softc *sc, int queue, u_int32_t *fib_size,
1273 struct aac_fib **fib_addr)
1274 {
1275 struct aac_ccb *ac;
1276 u_int32_t pi, ci, idx;
1277 int notify;
1278
1279 bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap,
1280 (char *)sc->sc_common->ac_qbuf - (char *)sc->sc_common,
1281 sizeof(sc->sc_common->ac_qbuf),
1282 BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
1283
1284 /* Get the producer/consumer indices. */
1285 pi = le32toh(sc->sc_queues->qt_qindex[queue][AAC_PRODUCER_INDEX]);
1286 ci = le32toh(sc->sc_queues->qt_qindex[queue][AAC_CONSUMER_INDEX]);
1287
1288 /* Check for queue empty. */
1289 if (ci == pi)
1290 return (ENOENT);
1291
1292 notify = 0;
1293 if (ci == pi + 1)
1294 notify = 1;
1295
1296 /* Wrap the queue? */
1297 if (ci >= aac_qinfo[queue].size)
1298 ci = 0;
1299
1300 /* Fetch the entry. */
1301 *fib_size = le32toh((sc->sc_qentries[queue] + ci)->aq_fib_size);
1302
1303 switch (queue) {
1304 case AAC_HOST_NORM_CMD_QUEUE:
1305 case AAC_HOST_HIGH_CMD_QUEUE:
1306 idx = le32toh((sc->sc_qentries[queue] + ci)->aq_fib_addr);
1307 idx /= sizeof(struct aac_fib);
1308 *fib_addr = &sc->sc_common->ac_fibs[idx];
1309 break;
1310 case AAC_HOST_NORM_RESP_QUEUE:
1311 case AAC_HOST_HIGH_RESP_QUEUE:
1312 idx = le32toh((sc->sc_qentries[queue] + ci)->aq_fib_addr);
1313 ac = (struct aac_ccb *) ((char *) sc->sc_ccbs + (idx >> 2));
1314 *fib_addr = ac->ac_fib;
1315 break;
1316 default:
1317 panic("Invalid queue in aac_dequeue_fib()");
1318 break;
1319 }
1320
1321 /* Update consumer index. */
1322 sc->sc_queues->qt_qindex[queue][AAC_CONSUMER_INDEX] = ci + 1;
1323
1324 bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap,
1325 (char *)sc->sc_common->ac_qbuf - (char *)sc->sc_common,
1326 sizeof(sc->sc_common->ac_qbuf),
1327 BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
1328
1329 /* If we have made the queue un-full, notify the adapter. */
1330 if (notify && (aac_qinfo[queue].notify != 0))
1331 AAC_QNOTIFY(sc, aac_qinfo[queue].notify);
1332
1333 return (0);
1334 }
1335
1336 /*
1337 * Put our response to an adapter-initiated fib (AIF) on the response queue.
1338 */
1339 static int
1340 aac_enqueue_response(struct aac_softc *sc, int queue, struct aac_fib *fib)
1341 {
1342 u_int32_t fib_size, fib_addr, pi, ci;
1343
1344 fib_size = le16toh(fib->Header.Size);
1345 fib_addr = fib->Header.SenderFibAddress;
1346 fib->Header.ReceiverFibAddress = fib_addr;
1347
1348 bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap,
1349 (char *)sc->sc_common->ac_qbuf - (char *)sc->sc_common,
1350 sizeof(sc->sc_common->ac_qbuf),
1351 BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
1352
1353 /* Get the producer/consumer indices. */
1354 pi = le32toh(sc->sc_queues->qt_qindex[queue][AAC_PRODUCER_INDEX]);
1355 ci = le32toh(sc->sc_queues->qt_qindex[queue][AAC_CONSUMER_INDEX]);
1356
1357 /* Wrap the queue? */
1358 if (pi >= aac_qinfo[queue].size)
1359 pi = 0;
1360
1361 /* Check for queue full. */
1362 if ((pi + 1) == ci)
1363 return (EAGAIN);
1364
1365 /* Populate queue entry. */
1366 (sc->sc_qentries[queue] + pi)->aq_fib_size = htole32(fib_size);
1367 (sc->sc_qentries[queue] + pi)->aq_fib_addr = htole32(fib_addr);
1368
1369 /* Update producer index. */
1370 sc->sc_queues->qt_qindex[queue][AAC_PRODUCER_INDEX] = htole32(pi + 1);
1371
1372 bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap,
1373 (char *)sc->sc_common->ac_qbuf - (char *)sc->sc_common,
1374 sizeof(sc->sc_common->ac_qbuf),
1375 BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
1376
1377 /* Notify the adapter if we know how. */
1378 if (aac_qinfo[queue].notify != 0)
1379 AAC_QNOTIFY(sc, aac_qinfo[queue].notify);
1380
1381 return (0);
1382 }
1383
1384 #ifdef AAC_DEBUG
1385 /*
1386 * Print a FIB
1387 */
1388 static void
1389 aac_print_fib(struct aac_softc *sc, struct aac_fib *fib,
1390 const char *caller)
1391 {
1392 struct aac_blockread *br;
1393 struct aac_blockwrite *bw;
1394 struct aac_sg_table *sg;
1395 char tbuf[512];
1396 int i;
1397
1398 printf("%s: FIB @ %p\n", caller, fib);
1399 bitmask_snprintf(le32toh(fib->Header.XferState),
1400 "\20"
1401 "\1HOSTOWNED"
1402 "\2ADAPTEROWNED"
1403 "\3INITIALISED"
1404 "\4EMPTY"
1405 "\5FROMPOOL"
1406 "\6FROMHOST"
1407 "\7FROMADAP"
1408 "\10REXPECTED"
1409 "\11RNOTEXPECTED"
1410 "\12DONEADAP"
1411 "\13DONEHOST"
1412 "\14HIGH"
1413 "\15NORM"
1414 "\16ASYNC"
1415 "\17PAGEFILEIO"
1416 "\20SHUTDOWN"
1417 "\21LAZYWRITE"
1418 "\22ADAPMICROFIB"
1419 "\23BIOSFIB"
1420 "\24FAST_RESPONSE"
1421 "\25APIFIB\n",
1422 tbuf,
1423 sizeof(tbuf));
1424
1425 printf(" XferState %s\n", tbuf);
1426 printf(" Command %d\n", le16toh(fib->Header.Command));
1427 printf(" StructType %d\n", fib->Header.StructType);
1428 printf(" Flags 0x%x\n", fib->Header.Flags);
1429 printf(" Size %d\n", le16toh(fib->Header.Size));
1430 printf(" SenderSize %d\n", le16toh(fib->Header.SenderSize));
1431 printf(" SenderAddress 0x%x\n",
1432 le32toh(fib->Header.SenderFibAddress));
1433 printf(" ReceiverAddress 0x%x\n",
1434 le32toh(fib->Header.ReceiverFibAddress));
1435 printf(" SenderData 0x%x\n", fib->Header.SenderData);
1436
1437 switch (fib->Header.Command) {
1438 case ContainerCommand: {
1439 br = (struct aac_blockread *)fib->data;
1440 bw = (struct aac_blockwrite *)fib->data;
1441 sg = NULL;
1442
1443 if (le32toh(br->Command) == VM_CtBlockRead) {
1444 printf(" BlockRead: container %d 0x%x/%d\n",
1445 le32toh(br->ContainerId), le32toh(br->BlockNumber),
1446 le32toh(br->ByteCount));
1447 sg = &br->SgMap;
1448 }
1449 if (le32toh(bw->Command) == VM_CtBlockWrite) {
1450 printf(" BlockWrite: container %d 0x%x/%d (%s)\n",
1451 le32toh(bw->ContainerId), le32toh(bw->BlockNumber),
1452 le32toh(bw->ByteCount),
1453 le32toh(bw->Stable) == CSTABLE ?
1454 "stable" : "unstable");
1455 sg = &bw->SgMap;
1456 }
1457 if (sg != NULL) {
1458 printf(" %d s/g entries\n", le32toh(sg->SgCount));
1459 for (i = 0; i < le32toh(sg->SgCount); i++)
1460 printf(" 0x%08x/%d\n",
1461 le32toh(sg->SgEntry[i].SgAddress),
1462 le32toh(sg->SgEntry[i].SgByteCount));
1463 }
1464 break;
1465 }
1466 default:
1467 // dump first 32 bytes of fib->data
1468 printf(" Raw data:");
1469 for (i = 0; i < 32; i++)
1470 printf(" %02x", fib->data[i]);
1471 printf("\n");
1472 break;
1473 }
1474 }
1475 #endif /* AAC_DEBUG */
1476