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