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