1 /* $OpenBSD: aac.c,v 1.19 2004/03/20 03:58:09 aaron Exp $ */
2
3 /*-
4 * Copyright (c) 2000 Michael Smith
5 * Copyright (c) 2000 BSDi
6 * Copyright (c) 2000 Niklas Hallqvist
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 *
30 * $FreeBSD: /c/ncvs/src/sys/dev/aac/aac.c,v 1.1 2000/09/13 03:20:34 msmith Exp $
31 */
32
33 /*
34 * Driver for the Adaptec 'FSA' family of PCI/SCSI RAID adapters.
35 */
36
37 /*
38 * This driver would not have rewritten for OpenBSD if it was not for the
39 * hardware donation from Nocom. I want to thank them for their support.
40 * Of course, credit should go to Mike Smith for the original work he did
41 * in the FreeBSD driver where I found lots of reusable code and inspiration.
42 * - Niklas Hallqvist
43 */
44
45 #include <sys/param.h>
46 #include <sys/systm.h>
47 #include <sys/buf.h>
48 #include <sys/device.h>
49 #include <sys/kernel.h>
50 #include <sys/malloc.h>
51
52 #include <machine/bus.h>
53
54 #include <uvm/uvm_extern.h>
55
56 #include <scsi/scsi_all.h>
57 #include <scsi/scsi_disk.h>
58 #include <scsi/scsiconf.h>
59
60 #include <dev/ic/aacreg.h>
61 #include <dev/ic/aacvar.h>
62 #include <dev/ic/aac_tables.h>
63
64 /* Geometry constants. */
65 #define AAC_MAXCYLS 1024
66 #define AAC_HEADS 64
67 #define AAC_SECS 32 /* mapping 64*32 */
68 #define AAC_MEDHEADS 127
69 #define AAC_MEDSECS 63 /* mapping 127*63 */
70 #define AAC_BIGHEADS 255
71 #define AAC_BIGSECS 63 /* mapping 255*63 */
72 #define AAC_SECS32 0x1f /* round capacity */
73
74 void aac_bio_complete(struct aac_ccb *);
75 void aac_complete(void *, int);
76 void aac_copy_internal_data(struct scsi_xfer *, u_int8_t *, size_t);
77 struct scsi_xfer *aac_dequeue(struct aac_softc *);
78 int aac_dequeue_fib(struct aac_softc *, int, u_int32_t *,
79 struct aac_fib **);
80 char *aac_describe_code(struct aac_code_lookup *, u_int32_t);
81 void aac_describe_controller(struct aac_softc *);
82 void aac_enqueue(struct aac_softc *, struct scsi_xfer *, int);
83 void aac_enqueue_ccb(struct aac_softc *, struct aac_ccb *);
84 int aac_enqueue_fib(struct aac_softc *, int, struct aac_ccb *);
85 void aac_eval_mapping(u_int32_t, int *, int *, int *);
86 int aac_exec_ccb(struct aac_ccb *);
87 void aac_free_ccb(struct aac_softc *, struct aac_ccb *);
88 struct aac_ccb *aac_get_ccb(struct aac_softc *, int);
89 #if 0
90 void aac_handle_aif(struct aac_softc *, struct aac_aif_command *);
91 #endif
92 void aac_host_command(struct aac_softc *);
93 void aac_host_response(struct aac_softc *);
94 int aac_init(struct aac_softc *);
95 int aac_internal_cache_cmd(struct scsi_xfer *);
96 int aac_map_command(struct aac_ccb *);
97 #ifdef AAC_DEBUG
98 void aac_print_fib(struct aac_softc *, struct aac_fib *, char *);
99 #endif
100 int aac_raw_scsi_cmd(struct scsi_xfer *);
101 int aac_scsi_cmd(struct scsi_xfer *);
102 int aac_start(struct aac_ccb *);
103 void aac_start_ccbs(struct aac_softc *);
104 void aac_startup(struct aac_softc *);
105 int aac_sync_command(struct aac_softc *, u_int32_t, u_int32_t,
106 u_int32_t, u_int32_t, u_int32_t, u_int32_t *);
107 int aac_sync_fib(struct aac_softc *, u_int32_t, u_int32_t, void *,
108 u_int16_t, void *, u_int16_t *);
109 void aac_timeout(void *);
110 void aac_unmap_command(struct aac_ccb *);
111 void aac_watchdog(void *);
112
113 struct cfdriver aac_cd = {
114 NULL, "aac", DV_DULL
115 };
116
117 struct scsi_adapter aac_switch = {
118 aac_scsi_cmd, aacminphys, 0, 0,
119 };
120
121 struct scsi_adapter aac_raw_switch = {
122 aac_raw_scsi_cmd, aacminphys, 0, 0,
123 };
124
125 struct scsi_device aac_dev = {
126 NULL, NULL, NULL, NULL
127 };
128
129 /* i960Rx interface */
130 int aac_rx_get_fwstatus(struct aac_softc *);
131 void aac_rx_qnotify(struct aac_softc *, int);
132 int aac_rx_get_istatus(struct aac_softc *);
133 void aac_rx_clear_istatus(struct aac_softc *, int);
134 void aac_rx_set_mailbox(struct aac_softc *, u_int32_t, u_int32_t,
135 u_int32_t, u_int32_t, u_int32_t);
136 int aac_rx_get_mailboxstatus(struct aac_softc *);
137 void aac_rx_set_interrupts(struct aac_softc *, int);
138
139 /* StrongARM interface */
140 int aac_sa_get_fwstatus(struct aac_softc *);
141 void aac_sa_qnotify(struct aac_softc *, int);
142 int aac_sa_get_istatus(struct aac_softc *);
143 void aac_sa_clear_istatus(struct aac_softc *, int);
144 void aac_sa_set_mailbox(struct aac_softc *, u_int32_t, u_int32_t,
145 u_int32_t, u_int32_t, u_int32_t);
146 int aac_sa_get_mailboxstatus(struct aac_softc *);
147 void aac_sa_set_interrupts(struct aac_softc *, int);
148
149 struct aac_interface aac_rx_interface = {
150 aac_rx_get_fwstatus,
151 aac_rx_qnotify,
152 aac_rx_get_istatus,
153 aac_rx_clear_istatus,
154 aac_rx_set_mailbox,
155 aac_rx_get_mailboxstatus,
156 aac_rx_set_interrupts
157 };
158
159 struct aac_interface aac_sa_interface = {
160 aac_sa_get_fwstatus,
161 aac_sa_qnotify,
162 aac_sa_get_istatus,
163 aac_sa_clear_istatus,
164 aac_sa_set_mailbox,
165 aac_sa_get_mailboxstatus,
166 aac_sa_set_interrupts
167 };
168
169 #ifdef AAC_DEBUG
170 int aac_debug = AAC_DEBUG;
171 #endif
172
173 int
aac_attach(sc)174 aac_attach(sc)
175 struct aac_softc *sc;
176 {
177 int i, error;
178 bus_dma_segment_t seg;
179 int nsegs;
180 struct aac_ccb *ccb;
181
182 TAILQ_INIT(&sc->sc_free_ccb);
183 TAILQ_INIT(&sc->sc_ccbq);
184 TAILQ_INIT(&sc->sc_completed);
185 LIST_INIT(&sc->sc_queue);
186
187 /* disable interrupts before we enable anything */
188 AAC_MASK_INTERRUPTS(sc);
189
190 /* mark controller as suspended until we get ourselves organised */
191 sc->sc_state |= AAC_STATE_SUSPEND;
192
193 /*
194 * Initialise the adapter.
195 */
196 error = aac_init(sc);
197 if (error)
198 return (error);
199
200 /*
201 * Print a little information about the controller.
202 */
203 aac_describe_controller(sc);
204
205 /* Initialize the ccbs */
206 for (i = 0; i < AAC_ADAP_NORM_CMD_ENTRIES; i++) {
207 ccb = &sc->sc_ccbs[i];
208 error = bus_dmamap_create(sc->sc_dmat,
209 (AAC_MAXSGENTRIES - 1) << PGSHIFT, AAC_MAXSGENTRIES,
210 (AAC_MAXSGENTRIES - 1) << PGSHIFT, 0,
211 BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &ccb->ac_dmamap_xfer);
212 if (error) {
213 printf("%s: cannot create ccb dmamap (%d)",
214 sc->sc_dev.dv_xname, error);
215 /* XXX cleanup */
216 return (1);
217 }
218
219 /* allocate the FIB cluster in DMAable memory and load it */
220 if (bus_dmamem_alloc(sc->sc_dmat, sizeof *ccb->ac_fib, 1, 0,
221 &seg, 1, &nsegs, BUS_DMA_NOWAIT)) {
222 printf("%s: can't allocate FIB structure\n",
223 sc->sc_dev.dv_xname);
224 /* XXX cleanup */
225 return (1);
226 }
227 ccb->ac_fibphys = seg.ds_addr;
228 if (bus_dmamem_map(sc->sc_dmat, &seg, nsegs,
229 sizeof *ccb->ac_fib, (caddr_t *)&ccb->ac_fib, 0)) {
230 printf("%s: can't map FIB structure\n",
231 sc->sc_dev.dv_xname);
232 /* XXX cleanup */
233 return (1);
234 }
235
236 TAILQ_INSERT_TAIL(&sc->sc_free_ccb, &sc->sc_ccbs[i],
237 ac_chain);
238 }
239
240 /* Fill in the prototype scsi_link. */
241 sc->sc_link.adapter_softc = sc;
242 sc->sc_link.adapter = &aac_switch;
243 sc->sc_link.device = &aac_dev;
244 /*
245 * XXX Theoretically this should be AAC_ADAP_NORM_CMD_ENTRIES but
246 * XXX in some configurations this can cause "not queued" errors.
247 * XXX A quarter of that number has been reported to be safe.
248 */
249 sc->sc_link.openings = AAC_ADAP_NORM_CMD_ENTRIES / 4;
250 sc->sc_link.adapter_buswidth = AAC_MAX_CONTAINERS;
251 sc->sc_link.adapter_target = AAC_MAX_CONTAINERS;
252
253 config_found(&sc->sc_dev, &sc->sc_link, scsiprint);
254
255 return (0);
256 }
257
258 /*
259 * Look up a text description of a numeric error code and return a pointer to
260 * same.
261 */
262 char *
aac_describe_code(table,code)263 aac_describe_code(table, code)
264 struct aac_code_lookup *table;
265 u_int32_t code;
266 {
267 int i;
268
269 for (i = 0; table[i].string != NULL; i++)
270 if (table[i].code == code)
271 return (table[i].string);
272 return (table[i + 1].string);
273 }
274
275 void
aac_describe_controller(sc)276 aac_describe_controller(sc)
277 struct aac_softc *sc;
278 {
279 u_int8_t buf[AAC_FIB_DATASIZE]; /* XXX a bit big for the stack */
280 u_int16_t bufsize;
281 struct aac_adapter_info *info;
282 u_int8_t arg;
283
284 arg = 0;
285 if (aac_sync_fib(sc, RequestAdapterInfo, 0, &arg, sizeof arg, &buf,
286 &bufsize)) {
287 printf("%s: RequestAdapterInfo failed\n", sc->sc_dev.dv_xname);
288 return;
289 }
290 if (bufsize != sizeof *info) {
291 printf("%s: "
292 "RequestAdapterInfo returned wrong data size (%d != %d)\n",
293 sc->sc_dev.dv_xname, bufsize, sizeof *info);
294 return;
295 }
296 info = (struct aac_adapter_info *)&buf[0];
297
298 printf("%s: %s %dMHz, %dMB, %s (%d) Kernel %d.%d-%d\n",
299 sc->sc_dev.dv_xname,
300 aac_describe_code(aac_cpu_variant, info->CpuVariant),
301 info->ClockSpeed, info->TotalMem / (1024 * 1024),
302 aac_describe_code(aac_battery_platform, info->batteryPlatform),
303 info->batteryPlatform, info->KernelRevision.external.comp.major,
304 info->KernelRevision.external.comp.minor,
305 info->KernelRevision.external.comp.dash);
306
307 /* save the kernel revision structure for later use */
308 sc->sc_revision = info->KernelRevision;
309 }
310
311 int
aac_init(sc)312 aac_init(sc)
313 struct aac_softc *sc;
314 {
315 bus_dma_segment_t seg;
316 int nsegs;
317 int i, error;
318 int state = 0;
319 struct aac_adapter_init *ip;
320 u_int32_t code;
321 u_int8_t *qaddr;
322
323 /*
324 * First wait for the adapter to come ready.
325 */
326 for (i = 0; i < AAC_BOOT_TIMEOUT * 1000; i++) {
327 code = AAC_GET_FWSTATUS(sc);
328 if (code & AAC_SELF_TEST_FAILED) {
329 printf("%s: FATAL: selftest failed\n",
330 sc->sc_dev.dv_xname);
331 return (ENXIO);
332 }
333 if (code & AAC_KERNEL_PANIC) {
334 printf("%s: FATAL: controller kernel panic\n",
335 sc->sc_dev.dv_xname);
336 return (ENXIO);
337 }
338 if (code & AAC_UP_AND_RUNNING)
339 break;
340 DELAY(1000);
341 }
342 if (i == AAC_BOOT_TIMEOUT * 1000) {
343 printf("%s: FATAL: controller not coming ready, status %x\n",
344 sc->sc_dev.dv_xname, code);
345 return (ENXIO);
346 }
347
348 if (bus_dmamem_alloc(sc->sc_dmat, sizeof *sc->sc_common, 1, 0, &seg, 1,
349 &nsegs, BUS_DMA_NOWAIT)) {
350 printf("%s: can't allocate common structure\n",
351 sc->sc_dev.dv_xname);
352 return (ENOMEM);
353 }
354 state++;
355 sc->sc_common_busaddr = seg.ds_addr;
356 if (bus_dmamem_map(sc->sc_dmat, &seg, nsegs, sizeof *sc->sc_common,
357 (caddr_t *)&sc->sc_common, 0)) {
358 printf("%s: can't map common structure\n",
359 sc->sc_dev.dv_xname);
360 error = ENOMEM;
361 goto bail_out;
362 }
363 state++;
364 bzero(sc->sc_common, sizeof *sc->sc_common);
365
366 /*
367 * Fill in the init structure. This tells the adapter about
368 * the physical location * of various important shared data
369 * structures.
370 */
371 ip = &sc->sc_common->ac_init;
372 ip->InitStructRevision = AAC_INIT_STRUCT_REVISION;
373
374 ip->AdapterFibsPhysicalAddress =
375 sc->sc_common_busaddr + offsetof(struct aac_common, ac_fibs);
376 ip->AdapterFibsVirtualAddress = &sc->sc_common->ac_fibs[0];
377 ip->AdapterFibsSize = AAC_ADAPTER_FIBS * sizeof(struct aac_fib);
378 ip->AdapterFibAlign = sizeof(struct aac_fib);
379
380 ip->PrintfBufferAddress =
381 sc->sc_common_busaddr + offsetof(struct aac_common, ac_printf);
382 ip->PrintfBufferSize = AAC_PRINTF_BUFSIZE;
383
384 ip->HostPhysMemPages = 0; /* not used? */
385 ip->HostElapsedSeconds = 0; /* reset later if invalid */
386
387 /*
388 * Initialise FIB queues. Note that it appears that the
389 * layout of the indexes and the segmentation of the entries
390 * is mandated by the adapter, which is only told about the
391 * base of the queue index fields.
392 *
393 * The initial values of the indices are assumed to inform the
394 * adapter of the sizes of the respective queues.
395 *
396 * The Linux driver uses a much more complex scheme whereby
397 * several header * records are kept for each queue. We use a
398 * couple of generic list manipulation functions which
399 * 'know' the size of each list by virtue of a table.
400 */
401 qaddr = &sc->sc_common->ac_qbuf[0] + AAC_QUEUE_ALIGN;
402 qaddr -= (u_int32_t)qaddr % AAC_QUEUE_ALIGN; /* XXX not portable */
403 sc->sc_queues = (struct aac_queue_table *)qaddr;
404 ip->CommHeaderAddress = sc->sc_common_busaddr +
405 ((char *)sc->sc_queues - (char *)sc->sc_common);
406 bzero(sc->sc_queues, sizeof(struct aac_queue_table));
407
408 sc->sc_queues->qt_qindex[AAC_HOST_NORM_CMD_QUEUE][AAC_PRODUCER_INDEX] =
409 AAC_HOST_NORM_CMD_ENTRIES;
410 sc->sc_queues->qt_qindex[AAC_HOST_NORM_CMD_QUEUE][AAC_CONSUMER_INDEX] =
411 AAC_HOST_NORM_CMD_ENTRIES;
412 sc->sc_queues->qt_qindex[AAC_HOST_HIGH_CMD_QUEUE][AAC_PRODUCER_INDEX] =
413 AAC_HOST_HIGH_CMD_ENTRIES;
414 sc->sc_queues->qt_qindex[AAC_HOST_HIGH_CMD_QUEUE][AAC_CONSUMER_INDEX] =
415 AAC_HOST_HIGH_CMD_ENTRIES;
416 sc->sc_queues->qt_qindex[AAC_ADAP_NORM_CMD_QUEUE][AAC_PRODUCER_INDEX] =
417 AAC_ADAP_NORM_CMD_ENTRIES;
418 sc->sc_queues->qt_qindex[AAC_ADAP_NORM_CMD_QUEUE][AAC_CONSUMER_INDEX] =
419 AAC_ADAP_NORM_CMD_ENTRIES;
420 sc->sc_queues->qt_qindex[AAC_ADAP_HIGH_CMD_QUEUE][AAC_PRODUCER_INDEX] =
421 AAC_ADAP_HIGH_CMD_ENTRIES;
422 sc->sc_queues->qt_qindex[AAC_ADAP_HIGH_CMD_QUEUE][AAC_CONSUMER_INDEX] =
423 AAC_ADAP_HIGH_CMD_ENTRIES;
424 sc->sc_queues->
425 qt_qindex[AAC_HOST_NORM_RESP_QUEUE][AAC_PRODUCER_INDEX] =
426 AAC_HOST_NORM_RESP_ENTRIES;
427 sc->sc_queues->
428 qt_qindex[AAC_HOST_NORM_RESP_QUEUE][AAC_CONSUMER_INDEX] =
429 AAC_HOST_NORM_RESP_ENTRIES;
430 sc->sc_queues->
431 qt_qindex[AAC_HOST_HIGH_RESP_QUEUE][AAC_PRODUCER_INDEX] =
432 AAC_HOST_HIGH_RESP_ENTRIES;
433 sc->sc_queues->
434 qt_qindex[AAC_HOST_HIGH_RESP_QUEUE][AAC_CONSUMER_INDEX] =
435 AAC_HOST_HIGH_RESP_ENTRIES;
436 sc->sc_queues->
437 qt_qindex[AAC_ADAP_NORM_RESP_QUEUE][AAC_PRODUCER_INDEX] =
438 AAC_ADAP_NORM_RESP_ENTRIES;
439 sc->sc_queues->
440 qt_qindex[AAC_ADAP_NORM_RESP_QUEUE][AAC_CONSUMER_INDEX] =
441 AAC_ADAP_NORM_RESP_ENTRIES;
442 sc->sc_queues->
443 qt_qindex[AAC_ADAP_HIGH_RESP_QUEUE][AAC_PRODUCER_INDEX] =
444 AAC_ADAP_HIGH_RESP_ENTRIES;
445 sc->sc_queues->
446 qt_qindex[AAC_ADAP_HIGH_RESP_QUEUE][AAC_CONSUMER_INDEX] =
447 AAC_ADAP_HIGH_RESP_ENTRIES;
448 sc->sc_qentries[AAC_HOST_NORM_CMD_QUEUE] =
449 &sc->sc_queues->qt_HostNormCmdQueue[0];
450 sc->sc_qentries[AAC_HOST_HIGH_CMD_QUEUE] =
451 &sc->sc_queues->qt_HostHighCmdQueue[0];
452 sc->sc_qentries[AAC_ADAP_NORM_CMD_QUEUE] =
453 &sc->sc_queues->qt_AdapNormCmdQueue[0];
454 sc->sc_qentries[AAC_ADAP_HIGH_CMD_QUEUE] =
455 &sc->sc_queues->qt_AdapHighCmdQueue[0];
456 sc->sc_qentries[AAC_HOST_NORM_RESP_QUEUE] =
457 &sc->sc_queues->qt_HostNormRespQueue[0];
458 sc->sc_qentries[AAC_HOST_HIGH_RESP_QUEUE] =
459 &sc->sc_queues->qt_HostHighRespQueue[0];
460 sc->sc_qentries[AAC_ADAP_NORM_RESP_QUEUE] =
461 &sc->sc_queues->qt_AdapNormRespQueue[0];
462 sc->sc_qentries[AAC_ADAP_HIGH_RESP_QUEUE] =
463 &sc->sc_queues->qt_AdapHighRespQueue[0];
464
465 /*
466 * Do controller-type-specific initialisation
467 */
468 switch (sc->sc_hwif) {
469 case AAC_HWIF_I960RX:
470 AAC_SETREG4(sc, AAC_RX_ODBR, ~0);
471 break;
472 }
473
474 /*
475 * Give the init structure to the controller.
476 */
477 if (aac_sync_command(sc, AAC_MONKER_INITSTRUCT,
478 sc->sc_common_busaddr + offsetof(struct aac_common, ac_init), 0, 0,
479 0, NULL)) {
480 printf("%s: error establishing init structure\n",
481 sc->sc_dev.dv_xname);
482 error = EIO;
483 goto bail_out;
484 }
485
486 aac_startup(sc);
487
488 return (0);
489
490 bail_out:
491 if (state > 1)
492 bus_dmamem_unmap(sc->sc_dmat, (caddr_t)sc->sc_common,
493 sizeof *sc->sc_common);
494 if (state > 0)
495 bus_dmamem_free(sc->sc_dmat, &seg, 1);
496 return (error);
497 }
498
499 /*
500 * Probe for containers, create disks.
501 */
502 void
aac_startup(sc)503 aac_startup (sc)
504 struct aac_softc *sc;
505 {
506 struct aac_mntinfo mi;
507 struct aac_mntinforesponse mir;
508 u_int16_t rsize;
509 int i, drv_cyls, drv_hds, drv_secs;
510
511 /* loop over possible containers */
512 mi.Command = VM_NameServe;
513 mi.MntType = FT_FILESYS;
514 for (i = 0; i < AAC_MAX_CONTAINERS; i++) {
515 /* request information on this container */
516 mi.MntCount = i;
517 if (aac_sync_fib(sc, ContainerCommand, 0, &mi, sizeof mi, &mir,
518 &rsize)) {
519 printf("%s: error probing container %d",
520 sc->sc_dev.dv_xname, i);
521 continue;
522 }
523 /* check response size */
524 if (rsize != sizeof mir) {
525 printf("%s: container info response wrong size "
526 "(%d should be %d)",
527 sc->sc_dev.dv_xname, rsize, sizeof mir);
528 continue;
529 }
530
531 /*
532 * Check container volume type for validity. Note
533 * that many of the possible types * may never show
534 * up.
535 */
536 if (mir.Status == ST_OK &&
537 mir.MntTable[0].VolType != CT_NONE) {
538 AAC_DPRINTF(AAC_D_MISC,
539 ("%d: id %x name '%.16s' size %u type %d", i,
540 mir.MntTable[0].ObjectId,
541 mir.MntTable[0].FileSystemName,
542 mir.MntTable[0].Capacity,
543 mir.MntTable[0].VolType));
544
545 sc->sc_hdr[i].hd_present = 1;
546 sc->sc_hdr[i].hd_size = mir.MntTable[0].Capacity;
547
548 /*
549 * Evaluate mapping (sectors per head, heads per cyl)
550 */
551 sc->sc_hdr[i].hd_size &= ~AAC_SECS32;
552 aac_eval_mapping(sc->sc_hdr[i].hd_size, &drv_cyls,
553 &drv_hds, &drv_secs);
554 sc->sc_hdr[i].hd_heads = drv_hds;
555 sc->sc_hdr[i].hd_secs = drv_secs;
556 /* Round the size */
557 sc->sc_hdr[i].hd_size = drv_cyls * drv_hds * drv_secs;
558
559 sc->sc_hdr[i].hd_devtype = mir.MntTable[0].VolType;
560
561 /* XXX Save the name too for use in IDENTIFY later */
562 }
563 }
564
565 /* mark the controller up */
566 sc->sc_state &= ~AAC_STATE_SUSPEND;
567
568 /* enable interrupts now */
569 AAC_UNMASK_INTERRUPTS(sc);
570 }
571
572 void
aac_eval_mapping(size,cyls,heads,secs)573 aac_eval_mapping(size, cyls, heads, secs)
574 u_int32_t size;
575 int *cyls, *heads, *secs;
576 {
577 *cyls = size / AAC_HEADS / AAC_SECS;
578 if (*cyls < AAC_MAXCYLS) {
579 *heads = AAC_HEADS;
580 *secs = AAC_SECS;
581 } else {
582 /* Too high for 64 * 32 */
583 *cyls = size / AAC_MEDHEADS / AAC_MEDSECS;
584 if (*cyls < AAC_MAXCYLS) {
585 *heads = AAC_MEDHEADS;
586 *secs = AAC_MEDSECS;
587 } else {
588 /* Too high for 127 * 63 */
589 *cyls = size / AAC_BIGHEADS / AAC_BIGSECS;
590 *heads = AAC_BIGHEADS;
591 *secs = AAC_BIGSECS;
592 }
593 }
594 }
595
596 int
aac_raw_scsi_cmd(xs)597 aac_raw_scsi_cmd(xs)
598 struct scsi_xfer *xs;
599 {
600 AAC_DPRINTF(AAC_D_CMD, ("aac_raw_scsi_cmd "));
601
602 /* XXX Not yet implemented */
603 xs->error = XS_DRIVER_STUFFUP;
604 return (COMPLETE);
605 }
606
607 int
aac_scsi_cmd(xs)608 aac_scsi_cmd(xs)
609 struct scsi_xfer *xs;
610 {
611 struct scsi_link *link = xs->sc_link;
612 struct aac_softc *sc = link->adapter_softc;
613 u_int8_t target = link->target;
614 struct aac_ccb *ccb;
615 u_int32_t blockno, blockcnt;
616 struct scsi_rw *rw;
617 struct scsi_rw_big *rwb;
618 aac_lock_t lock;
619 int retval = SUCCESSFULLY_QUEUED;
620
621 AAC_DPRINTF(AAC_D_CMD, ("aac_scsi_cmd "));
622
623 xs->error = XS_NOERROR;
624
625 if (target >= AAC_MAX_CONTAINERS || !sc->sc_hdr[target].hd_present ||
626 link->lun != 0) {
627 /*
628 * XXX Should be XS_SENSE but that would require setting up a
629 * faked sense too.
630 */
631 xs->error = XS_DRIVER_STUFFUP;
632 xs->flags |= ITSDONE;
633 scsi_done(xs);
634 return (COMPLETE);
635 }
636
637 lock = AAC_LOCK(sc);
638
639 /* Don't double enqueue if we came from aac_chain. */
640 if (xs != LIST_FIRST(&sc->sc_queue))
641 aac_enqueue(sc, xs, 0);
642
643 while ((xs = aac_dequeue(sc))) {
644 xs->error = XS_NOERROR;
645 ccb = NULL;
646 link = xs->sc_link;
647 target = link->target;
648
649 switch (xs->cmd->opcode) {
650 case TEST_UNIT_READY:
651 case REQUEST_SENSE:
652 case INQUIRY:
653 case MODE_SENSE:
654 case START_STOP:
655 case READ_CAPACITY:
656 #if 0
657 case VERIFY:
658 #endif
659 if (!aac_internal_cache_cmd(xs)) {
660 AAC_UNLOCK(sc, lock);
661 return (TRY_AGAIN_LATER);
662 }
663 xs->flags |= ITSDONE;
664 scsi_done(xs);
665 goto ready;
666
667 case PREVENT_ALLOW:
668 AAC_DPRINTF(AAC_D_CMD, ("PREVENT/ALLOW "));
669 /* XXX Not yet implemented */
670 xs->error = XS_NOERROR;
671 xs->flags |= ITSDONE;
672 scsi_done(xs);
673 goto ready;
674
675 case SYNCHRONIZE_CACHE:
676 AAC_DPRINTF(AAC_D_CMD, ("SYNCHRONIZE_CACHE "));
677 /* XXX Not yet implemented */
678 xs->error = XS_NOERROR;
679 xs->flags |= ITSDONE;
680 scsi_done(xs);
681 goto ready;
682
683 default:
684 AAC_DPRINTF(AAC_D_CMD,
685 ("unknown opc %d ", xs->cmd->opcode));
686 /* XXX Not yet implemented */
687 xs->error = XS_DRIVER_STUFFUP;
688 xs->flags |= ITSDONE;
689 scsi_done(xs);
690 goto ready;
691
692 case READ_COMMAND:
693 case READ_BIG:
694 case WRITE_COMMAND:
695 case WRITE_BIG:
696 AAC_DPRINTF(AAC_D_CMD,
697 ("rw opc %d ", xs->cmd->opcode));
698
699 if (xs->cmd->opcode != SYNCHRONIZE_CACHE) {
700 /* A read or write operation. */
701 if (xs->cmdlen == 6) {
702 rw = (struct scsi_rw *)xs->cmd;
703 blockno = _3btol(rw->addr) &
704 (SRW_TOPADDR << 16 | 0xffff);
705 blockcnt =
706 rw->length ? rw->length : 0x100;
707 } else {
708 rwb = (struct scsi_rw_big *)xs->cmd;
709 blockno = _4btol(rwb->addr);
710 blockcnt = _2btol(rwb->length);
711 }
712 if (blockno >= sc->sc_hdr[target].hd_size ||
713 blockno + blockcnt >
714 sc->sc_hdr[target].hd_size) {
715 printf(
716 "%s: out of bounds %u-%u >= %u\n",
717 sc->sc_dev.dv_xname, blockno,
718 blockcnt,
719 sc->sc_hdr[target].hd_size);
720 /*
721 * XXX Should be XS_SENSE but that
722 * would require setting up a faked
723 * sense too.
724 */
725 xs->error = XS_DRIVER_STUFFUP;
726 xs->flags |= ITSDONE;
727 scsi_done(xs);
728 goto ready;
729 }
730 }
731
732 ccb = aac_get_ccb(sc, xs->flags);
733
734 /*
735 * We are out of commands, try again in a little while.
736 */
737 if (ccb == NULL) {
738 xs->error = XS_DRIVER_STUFFUP;
739 AAC_UNLOCK(sc, lock);
740 return (TRY_AGAIN_LATER);
741 }
742
743 ccb->ac_blockno = blockno;
744 ccb->ac_blockcnt = blockcnt;
745 ccb->ac_xs = xs;
746 ccb->ac_timeout = xs->timeout;
747
748 if (xs->cmd->opcode != SYNCHRONIZE_CACHE &&
749 aac_map_command(ccb)) {
750 aac_free_ccb(sc, ccb);
751 xs->error = XS_DRIVER_STUFFUP;
752 xs->flags |= ITSDONE;
753 scsi_done(xs);
754 goto ready;
755 }
756
757 aac_enqueue_ccb(sc, ccb);
758 /* XXX what if enqueue did not start a transfer? */
759 if (xs->flags & SCSI_POLL) {
760 #if 0
761 if (!aac_wait(sc, ccb, ccb->ac_timeout)) {
762 AAC_UNLOCK(sc, lock);
763 printf("%s: command timed out\n",
764 sc->sc_dev.dv_xname);
765 xs->error = XS_TIMEOUT;
766 return (TRY_AGAIN_LATER);
767 }
768 xs->flags |= ITSDONE;
769 scsi_done(xs);
770 #endif
771 }
772 }
773
774 ready:
775 /*
776 * Don't process the queue if we are polling.
777 */
778 if (xs->flags & SCSI_POLL) {
779 retval = COMPLETE;
780 break;
781 }
782 }
783
784 AAC_UNLOCK(sc, lock);
785 return (retval);
786 }
787
788 void
aac_copy_internal_data(xs,data,size)789 aac_copy_internal_data(xs, data, size)
790 struct scsi_xfer *xs;
791 u_int8_t *data;
792 size_t size;
793 {
794 size_t copy_cnt;
795
796 AAC_DPRINTF(AAC_D_MISC, ("aac_copy_internal_data "));
797
798 if (!xs->datalen)
799 printf("uio move not yet supported\n");
800 else {
801 copy_cnt = MIN(size, xs->datalen);
802 bcopy(data, xs->data, copy_cnt);
803 }
804 }
805
806 /* Emulated SCSI operation on cache device */
807 int
aac_internal_cache_cmd(xs)808 aac_internal_cache_cmd(xs)
809 struct scsi_xfer *xs;
810 {
811 struct scsi_link *link = xs->sc_link;
812 struct aac_softc *sc = link->adapter_softc;
813 struct scsi_inquiry_data inq;
814 struct scsi_sense_data sd;
815 struct {
816 struct scsi_mode_header hd;
817 struct scsi_blk_desc bd;
818 union scsi_disk_pages dp;
819 } mpd;
820 struct scsi_read_cap_data rcd;
821 u_int8_t target = link->target;
822
823 AAC_DPRINTF(AAC_D_CMD, ("aac_internal_cache_cmd "));
824
825 switch (xs->cmd->opcode) {
826 case TEST_UNIT_READY:
827 case START_STOP:
828 #if 0
829 case VERIFY:
830 #endif
831 AAC_DPRINTF(AAC_D_CMD, ("opc %d tgt %d ", xs->cmd->opcode,
832 target));
833 break;
834
835 case REQUEST_SENSE:
836 AAC_DPRINTF(AAC_D_CMD, ("REQUEST SENSE tgt %d ", target));
837 bzero(&sd, sizeof sd);
838 sd.error_code = 0x70;
839 sd.segment = 0;
840 sd.flags = SKEY_NO_SENSE;
841 aac_enc32(sd.info, 0);
842 sd.extra_len = 0;
843 aac_copy_internal_data(xs, (u_int8_t *)&sd, sizeof sd);
844 break;
845
846 case INQUIRY:
847 AAC_DPRINTF(AAC_D_CMD, ("INQUIRY tgt %d devtype %x ", target,
848 sc->sc_hdr[target].hd_devtype));
849 bzero(&inq, sizeof inq);
850 /* XXX How do we detect removable/CD-ROM devices? */
851 inq.device = T_DIRECT;
852 inq.dev_qual2 = 0;
853 inq.version = 2;
854 inq.response_format = 2;
855 inq.additional_length = 32;
856 strlcpy(inq.vendor, "Adaptec", sizeof inq.vendor);
857 snprintf(inq.product, sizeof inq.product, "Container #%02d",
858 target);
859 strlcpy(inq.revision, " ", sizeof inq.revision);
860 aac_copy_internal_data(xs, (u_int8_t *)&inq, sizeof inq);
861 break;
862
863 case MODE_SENSE:
864 AAC_DPRINTF(AAC_D_CMD, ("MODE SENSE tgt %d ", target));
865
866 bzero(&mpd, sizeof mpd);
867 switch (((struct scsi_mode_sense *)xs->cmd)->page) {
868 case 4:
869 /* scsi_disk.h says this should be 0x16 */
870 mpd.dp.rigid_geometry.pg_length = 0x16;
871 mpd.hd.data_length = sizeof mpd.hd + sizeof mpd.bd +
872 mpd.dp.rigid_geometry.pg_length;
873 mpd.hd.blk_desc_len = sizeof mpd.bd;
874
875 /* XXX */
876 mpd.hd.dev_spec = 0;
877 _lto3b(AAC_BLOCK_SIZE, mpd.bd.blklen);
878 mpd.dp.rigid_geometry.pg_code = 4;
879 _lto3b(sc->sc_hdr[target].hd_size /
880 sc->sc_hdr[target].hd_heads /
881 sc->sc_hdr[target].hd_secs,
882 mpd.dp.rigid_geometry.ncyl);
883 mpd.dp.rigid_geometry.nheads =
884 sc->sc_hdr[target].hd_heads;
885 aac_copy_internal_data(xs, (u_int8_t *)&mpd,
886 sizeof mpd);
887 break;
888
889 default:
890 printf("%s: mode sense page %d not simulated\n",
891 sc->sc_dev.dv_xname,
892 ((struct scsi_mode_sense *)xs->cmd)->page);
893 xs->error = XS_DRIVER_STUFFUP;
894 return (0);
895 }
896 break;
897
898 case READ_CAPACITY:
899 AAC_DPRINTF(AAC_D_CMD, ("READ CAPACITY tgt %d ", target));
900 bzero(&rcd, sizeof rcd);
901 _lto4b(sc->sc_hdr[target].hd_size - 1, rcd.addr);
902 _lto4b(AAC_BLOCK_SIZE, rcd.length);
903 aac_copy_internal_data(xs, (u_int8_t *)&rcd, sizeof rcd);
904 break;
905
906 default:
907 printf("aac_internal_cache_cmd got bad opcode: %d\n",
908 xs->cmd->opcode);
909 xs->error = XS_DRIVER_STUFFUP;
910 return (0);
911 }
912
913 xs->error = XS_NOERROR;
914 return (1);
915 }
916
917 /*
918 * Take an interrupt.
919 */
920 int
aac_intr(arg)921 aac_intr(arg)
922 void *arg;
923 {
924 struct aac_softc *sc = arg;
925 u_int16_t reason;
926 int claimed = 0;
927
928 AAC_DPRINTF(AAC_D_INTR, ("aac_intr(%p) ", sc));
929
930 reason = AAC_GET_ISTATUS(sc);
931 AAC_DPRINTF(AAC_D_INTR, ("istatus 0x%04x ", reason));
932
933 /* controller wants to talk to the log? XXX should we defer this? */
934 if (reason & AAC_DB_PRINTF) {
935 if (sc->sc_common->ac_printf[0]) {
936 printf("%s: ** %.*s", sc->sc_dev.dv_xname,
937 AAC_PRINTF_BUFSIZE, sc->sc_common->ac_printf);
938 sc->sc_common->ac_printf[0] = 0;
939 }
940 AAC_CLEAR_ISTATUS(sc, AAC_DB_PRINTF);
941 AAC_QNOTIFY(sc, AAC_DB_PRINTF);
942 claimed = 1;
943 }
944
945 /* Controller has a message for us? */
946 if (reason & AAC_DB_COMMAND_READY) {
947 aac_host_command(sc);
948 AAC_CLEAR_ISTATUS(sc, AAC_DB_COMMAND_READY);
949 claimed = 1;
950 }
951
952 /* Controller has a response for us? */
953 if (reason & AAC_DB_RESPONSE_READY) {
954 aac_host_response(sc);
955 AAC_CLEAR_ISTATUS(sc, AAC_DB_RESPONSE_READY);
956 claimed = 1;
957 }
958
959 /*
960 * Spurious interrupts that we don't use - reset the mask and clear
961 * the interrupts.
962 */
963 if (reason & (AAC_DB_SYNC_COMMAND | AAC_DB_COMMAND_NOT_FULL |
964 AAC_DB_RESPONSE_NOT_FULL)) {
965 AAC_UNMASK_INTERRUPTS(sc);
966 AAC_CLEAR_ISTATUS(sc, AAC_DB_SYNC_COMMAND |
967 AAC_DB_COMMAND_NOT_FULL | AAC_DB_RESPONSE_NOT_FULL);
968 claimed = 1;
969 }
970
971 return (claimed);
972 }
973
974 /*
975 * Handle notification of one or more FIBs coming from the controller.
976 */
977 void
aac_host_command(struct aac_softc * sc)978 aac_host_command(struct aac_softc *sc)
979 {
980 struct aac_fib *fib;
981 u_int32_t fib_size;
982
983 for (;;) {
984 if (aac_dequeue_fib(sc, AAC_HOST_NORM_CMD_QUEUE, &fib_size,
985 &fib))
986 break; /* nothing to do */
987
988 switch(fib->Header.Command) {
989 case AifRequest:
990 #if 0
991 aac_handle_aif(sc,
992 (struct aac_aif_command *)&fib->data[0]);
993 #endif
994
995 break;
996 default:
997 printf("%s: unknown command from controller\n",
998 sc->sc_dev.dv_xname);
999 AAC_PRINT_FIB(sc, fib);
1000 break;
1001 }
1002
1003 /* XXX reply to FIBs requesting responses ?? */
1004 /* XXX how do we return these FIBs to the controller? */
1005 }
1006 }
1007
1008 /*
1009 * Handle notification of one or more FIBs completed by the controller
1010 */
1011 void
aac_host_response(struct aac_softc * sc)1012 aac_host_response(struct aac_softc *sc)
1013 {
1014 struct aac_ccb *ccb;
1015 struct aac_fib *fib;
1016 u_int32_t fib_size;
1017
1018 for (;;) {
1019 /* look for completed FIBs on our queue */
1020 if (aac_dequeue_fib(sc, AAC_HOST_NORM_RESP_QUEUE, &fib_size,
1021 &fib))
1022 break; /* nothing to do */
1023
1024 /* get the command, unmap and queue for later processing */
1025 ccb = (struct aac_ccb *)fib->Header.SenderData;
1026 if (ccb == NULL) {
1027 AAC_PRINT_FIB(sc, fib);
1028 } else {
1029 timeout_del(&ccb->ac_xs->stimeout);
1030 aac_unmap_command(ccb); /* XXX defer? */
1031 aac_enqueue_completed(ccb);
1032 }
1033 }
1034
1035 /* handle completion processing */
1036 aac_complete(sc, 0);
1037 }
1038
1039 /*
1040 * Process completed commands.
1041 */
1042 void
aac_complete(void * context,int pending)1043 aac_complete(void *context, int pending)
1044 {
1045 struct aac_softc *sc = (struct aac_softc *)context;
1046 struct aac_ccb *ccb;
1047
1048 /* pull completed commands off the queue */
1049 for (;;) {
1050 ccb = aac_dequeue_completed(sc);
1051 if (ccb == NULL)
1052 return;
1053 ccb->ac_flags |= AAC_ACF_COMPLETED;
1054
1055 #if 0
1056 /* is there a completion handler? */
1057 if (ccb->ac_complete != NULL) {
1058 ccb->ac_complete(ccb);
1059 } else {
1060 /* assume that someone is sleeping on this command */
1061 wakeup(ccb);
1062 }
1063 #else
1064 aac_bio_complete(ccb);
1065 #endif
1066 }
1067 }
1068
1069 /*
1070 * Handle a bio-instigated command that has been completed.
1071 */
1072 void
aac_bio_complete(struct aac_ccb * ccb)1073 aac_bio_complete(struct aac_ccb *ccb)
1074 {
1075 struct scsi_xfer *xs = ccb->ac_xs;
1076 struct aac_softc *sc = xs->sc_link->adapter_softc;
1077 struct buf *bp = xs->bp;
1078 struct aac_blockread_response *brr;
1079 struct aac_blockwrite_response *bwr;
1080 AAC_FSAStatus status;
1081
1082 /* fetch relevant status and then release the command */
1083 if (bp->b_flags & B_READ) {
1084 brr = (struct aac_blockread_response *)&ccb->ac_fib->data[0];
1085 status = brr->Status;
1086 } else {
1087 bwr = (struct aac_blockwrite_response *)&ccb->ac_fib->data[0];
1088 status = bwr->Status;
1089 }
1090 aac_free_ccb(sc, ccb);
1091
1092 /* fix up the bio based on status */
1093 if (status == ST_OK) {
1094 bp->b_resid = 0;
1095 } else {
1096 bp->b_error = EIO;
1097 bp->b_flags |= B_ERROR;
1098
1099 /* XXX be more verbose? */
1100 printf("%s: I/O error %d (%s)\n", sc->sc_dev.dv_xname,
1101 status, AAC_COMMAND_STATUS(status));
1102 }
1103 scsi_done(xs);
1104 }
1105
1106 /*
1107 * Send a synchronous command to the controller and wait for a result.
1108 */
1109 int
aac_sync_command(sc,command,arg0,arg1,arg2,arg3,sp)1110 aac_sync_command(sc, command, arg0, arg1, arg2, arg3, sp)
1111 struct aac_softc *sc;
1112 u_int32_t command;
1113 u_int32_t arg0;
1114 u_int32_t arg1;
1115 u_int32_t arg2;
1116 u_int32_t arg3;
1117 u_int32_t *sp;
1118 {
1119 int i;
1120 u_int32_t status;
1121 aac_lock_t lock = AAC_LOCK(sc);
1122
1123 /* populate the mailbox */
1124 AAC_SET_MAILBOX(sc, command, arg0, arg1, arg2, arg3);
1125
1126 /* ensure the sync command doorbell flag is cleared */
1127 AAC_CLEAR_ISTATUS(sc, AAC_DB_SYNC_COMMAND);
1128
1129 /* then set it to signal the adapter */
1130 AAC_QNOTIFY(sc, AAC_DB_SYNC_COMMAND);
1131 DELAY(AAC_SYNC_DELAY);
1132
1133 /* spin waiting for the command to complete */
1134 for (i = 0; i < AAC_IMMEDIATE_TIMEOUT * 1000; i++) {
1135 if (AAC_GET_ISTATUS(sc) & AAC_DB_SYNC_COMMAND)
1136 break;
1137 DELAY(1000);
1138 }
1139 if (i == AAC_IMMEDIATE_TIMEOUT * 1000) {
1140 AAC_UNLOCK(sc, lock);
1141 return (EIO);
1142 }
1143
1144 /* clear the completion flag */
1145 AAC_CLEAR_ISTATUS(sc, AAC_DB_SYNC_COMMAND);
1146
1147 /* get the command status */
1148 status = AAC_GET_MAILBOXSTATUS(sc);
1149 AAC_UNLOCK(sc, lock);
1150 if (sp != NULL)
1151 *sp = status;
1152 return (0); /* check command return status? */
1153 }
1154
1155 /*
1156 * Send a synchronous FIB to the controller and wait for a result.
1157 */
1158 int
aac_sync_fib(sc,command,xferstate,data,datasize,result,resultsize)1159 aac_sync_fib(sc, command, xferstate, data, datasize, result, resultsize)
1160 struct aac_softc *sc;
1161 u_int32_t command;
1162 u_int32_t xferstate;
1163 void *data;
1164 u_int16_t datasize;
1165 void *result;
1166 u_int16_t *resultsize;
1167 {
1168 struct aac_fib *fib = &sc->sc_common->ac_sync_fib;
1169
1170 if (datasize > AAC_FIB_DATASIZE)
1171 return (EINVAL);
1172
1173 /*
1174 * Set up the sync FIB
1175 */
1176 fib->Header.XferState = AAC_FIBSTATE_HOSTOWNED |
1177 AAC_FIBSTATE_INITIALISED | AAC_FIBSTATE_EMPTY;
1178 fib->Header.XferState |= xferstate;
1179 fib->Header.Command = command;
1180 fib->Header.StructType = AAC_FIBTYPE_TFIB;
1181 fib->Header.Size = sizeof fib + datasize;
1182 fib->Header.SenderSize = sizeof *fib;
1183 fib->Header.SenderFibAddress = (u_int32_t)fib;
1184 fib->Header.ReceiverFibAddress =
1185 sc->sc_common_busaddr + offsetof(struct aac_common, ac_sync_fib);
1186
1187 /*
1188 * Copy in data.
1189 */
1190 if (data != NULL) {
1191 bcopy(data, fib->data, datasize);
1192 fib->Header.XferState |=
1193 AAC_FIBSTATE_FROMHOST | AAC_FIBSTATE_NORM;
1194 }
1195
1196 /*
1197 * Give the FIB to the controller, wait for a response.
1198 */
1199 if (aac_sync_command(sc, AAC_MONKER_SYNCFIB,
1200 fib->Header.ReceiverFibAddress, 0, 0, 0, NULL)) {
1201 return (EIO);
1202 }
1203
1204 /*
1205 * Copy out the result
1206 */
1207 if (result != NULL) {
1208 *resultsize = fib->Header.Size - sizeof fib->Header;
1209 bcopy(fib->data, result, *resultsize);
1210 }
1211 return (0);
1212 }
1213
1214 void
aacminphys(bp)1215 aacminphys(bp)
1216 struct buf *bp;
1217 {
1218 #if 0
1219 u_int8_t *buf = bp->b_data;
1220 paddr_t pa;
1221 long off;
1222 #endif
1223
1224 AAC_DPRINTF(AAC_D_MISC, ("aacminphys(0x%x) ", bp));
1225
1226 #if 1
1227 #if 0 /* As this is way more than MAXPHYS it's really not necessary. */
1228 if (bp->b_bcount > ((AAC_MAXOFFSETS - 1) * PAGE_SIZE))
1229 bp->b_bcount = ((AAC_MAXOFFSETS - 1) * PAGE_SIZE);
1230 #endif
1231 #else
1232 for (off = PAGE_SIZE, pa = vtophys(buf); off < bp->b_bcount;
1233 off += PAGE_SIZE)
1234 if (pa + off != vtophys(buf + off)) {
1235 bp->b_bcount = off;
1236 break;
1237 }
1238 #endif
1239 minphys(bp);
1240 }
1241
1242 /*
1243 * Read the current firmware status word.
1244 */
1245 int
aac_sa_get_fwstatus(sc)1246 aac_sa_get_fwstatus(sc)
1247 struct aac_softc *sc;
1248 {
1249 return (AAC_GETREG4(sc, AAC_SA_FWSTATUS));
1250 }
1251
1252 int
aac_rx_get_fwstatus(sc)1253 aac_rx_get_fwstatus(sc)
1254 struct aac_softc *sc;
1255 {
1256 return (AAC_GETREG4(sc, AAC_RX_FWSTATUS));
1257 }
1258
1259 /*
1260 * Notify the controller of a change in a given queue
1261 */
1262
1263 void
aac_sa_qnotify(sc,qbit)1264 aac_sa_qnotify(sc, qbit)
1265 struct aac_softc *sc;
1266 int qbit;
1267 {
1268 AAC_SETREG2(sc, AAC_SA_DOORBELL1_SET, qbit);
1269 }
1270
1271 void
aac_rx_qnotify(sc,qbit)1272 aac_rx_qnotify(sc, qbit)
1273 struct aac_softc *sc;
1274 int qbit;
1275 {
1276 AAC_SETREG4(sc, AAC_RX_IDBR, qbit);
1277 }
1278
1279 /*
1280 * Get the interrupt reason bits
1281 */
1282 int
aac_sa_get_istatus(sc)1283 aac_sa_get_istatus(sc)
1284 struct aac_softc *sc;
1285 {
1286 return (AAC_GETREG2(sc, AAC_SA_DOORBELL0));
1287 }
1288
1289 int
aac_rx_get_istatus(sc)1290 aac_rx_get_istatus(sc)
1291 struct aac_softc *sc;
1292 {
1293 return (AAC_GETREG4(sc, AAC_RX_ODBR));
1294 }
1295
1296 /*
1297 * Clear some interrupt reason bits
1298 */
1299 void
aac_sa_clear_istatus(sc,mask)1300 aac_sa_clear_istatus(sc, mask)
1301 struct aac_softc *sc;
1302 int mask;
1303 {
1304 AAC_SETREG2(sc, AAC_SA_DOORBELL0_CLEAR, mask);
1305 }
1306
1307 void
aac_rx_clear_istatus(sc,mask)1308 aac_rx_clear_istatus(sc, mask)
1309 struct aac_softc *sc;
1310 int mask;
1311 {
1312 AAC_SETREG4(sc, AAC_RX_ODBR, mask);
1313 }
1314
1315 /*
1316 * Populate the mailbox and set the command word
1317 */
1318 void
aac_sa_set_mailbox(sc,command,arg0,arg1,arg2,arg3)1319 aac_sa_set_mailbox(sc, command, arg0, arg1, arg2, arg3)
1320 struct aac_softc *sc;
1321 u_int32_t command;
1322 u_int32_t arg0;
1323 u_int32_t arg1;
1324 u_int32_t arg2;
1325 u_int32_t arg3;
1326 {
1327 AAC_SETREG4(sc, AAC_SA_MAILBOX, command);
1328 AAC_SETREG4(sc, AAC_SA_MAILBOX + 4, arg0);
1329 AAC_SETREG4(sc, AAC_SA_MAILBOX + 8, arg1);
1330 AAC_SETREG4(sc, AAC_SA_MAILBOX + 12, arg2);
1331 AAC_SETREG4(sc, AAC_SA_MAILBOX + 16, arg3);
1332 }
1333
1334 void
aac_rx_set_mailbox(sc,command,arg0,arg1,arg2,arg3)1335 aac_rx_set_mailbox(sc, command, arg0, arg1, arg2, arg3)
1336 struct aac_softc *sc;
1337 u_int32_t command;
1338 u_int32_t arg0;
1339 u_int32_t arg1;
1340 u_int32_t arg2;
1341 u_int32_t arg3;
1342 {
1343 AAC_SETREG4(sc, AAC_RX_MAILBOX, command);
1344 AAC_SETREG4(sc, AAC_RX_MAILBOX + 4, arg0);
1345 AAC_SETREG4(sc, AAC_RX_MAILBOX + 8, arg1);
1346 AAC_SETREG4(sc, AAC_RX_MAILBOX + 12, arg2);
1347 AAC_SETREG4(sc, AAC_RX_MAILBOX + 16, arg3);
1348 }
1349
1350 /*
1351 * Fetch the immediate command status word
1352 */
1353 int
aac_sa_get_mailboxstatus(sc)1354 aac_sa_get_mailboxstatus(sc)
1355 struct aac_softc *sc;
1356 {
1357 return (AAC_GETREG4(sc, AAC_SA_MAILBOX));
1358 }
1359
1360 int
aac_rx_get_mailboxstatus(sc)1361 aac_rx_get_mailboxstatus(sc)
1362 struct aac_softc *sc;
1363 {
1364 return (AAC_GETREG4(sc, AAC_RX_MAILBOX));
1365 }
1366
1367 /*
1368 * Set/clear interrupt masks
1369 */
1370 void
aac_sa_set_interrupts(sc,enable)1371 aac_sa_set_interrupts(sc, enable)
1372 struct aac_softc *sc;
1373 int enable;
1374 {
1375 if (enable)
1376 AAC_SETREG2((sc), AAC_SA_MASK0_CLEAR, AAC_DB_INTERRUPTS);
1377 else
1378 AAC_SETREG2((sc), AAC_SA_MASK0_SET, ~0);
1379 }
1380
1381 void
aac_rx_set_interrupts(sc,enable)1382 aac_rx_set_interrupts(sc, enable)
1383 struct aac_softc *sc;
1384 int enable;
1385 {
1386 if (enable)
1387 AAC_SETREG4(sc, AAC_RX_OIMR, ~AAC_DB_INTERRUPTS);
1388 else
1389 AAC_SETREG4(sc, AAC_RX_OIMR, ~0);
1390 }
1391
1392 struct aac_ccb *
aac_get_ccb(sc,flags)1393 aac_get_ccb(sc, flags)
1394 struct aac_softc *sc;
1395 int flags;
1396 {
1397 struct aac_ccb *ccb;
1398 aac_lock_t lock;
1399
1400 AAC_DPRINTF(AAC_D_QUEUE, ("aac_get_ccb(%p, 0x%x) ", sc, flags));
1401
1402 lock = AAC_LOCK(sc);
1403
1404 for (;;) {
1405 ccb = TAILQ_FIRST(&sc->sc_free_ccb);
1406 if (ccb != NULL)
1407 break;
1408 if (flags & SCSI_NOSLEEP)
1409 goto bail_out;
1410 tsleep(&sc->sc_free_ccb, PRIBIO, "aac_ccb", 0);
1411 }
1412
1413 TAILQ_REMOVE(&sc->sc_free_ccb, ccb, ac_chain);
1414
1415 /* initialise the command/FIB */
1416 ccb->ac_sgtable = NULL;
1417 ccb->ac_flags = 0;
1418 ccb->ac_fib->Header.XferState = AAC_FIBSTATE_EMPTY;
1419 ccb->ac_fib->Header.StructType = AAC_FIBTYPE_TFIB;
1420 ccb->ac_fib->Header.Flags = 0;
1421 ccb->ac_fib->Header.SenderSize = sizeof(struct aac_fib);
1422
1423 /*
1424 * These are duplicated in aac_start to cover the case where an
1425 * intermediate stage may have destroyed them. They're left
1426 * initialised here for debugging purposes only.
1427 */
1428 ccb->ac_fib->Header.SenderFibAddress = (u_int32_t)ccb->ac_fib;
1429 ccb->ac_fib->Header.ReceiverFibAddress = ccb->ac_fibphys;
1430
1431 bail_out:
1432 AAC_UNLOCK(sc, lock);
1433 return (ccb);
1434 }
1435
1436 void
aac_free_ccb(sc,ccb)1437 aac_free_ccb(sc, ccb)
1438 struct aac_softc *sc;
1439 struct aac_ccb *ccb;
1440 {
1441 aac_lock_t lock;
1442
1443 AAC_DPRINTF(AAC_D_QUEUE, ("aac_free_ccb(%p, %p) ", sc, ccb));
1444
1445 lock = AAC_LOCK(sc);
1446
1447 TAILQ_INSERT_HEAD(&sc->sc_free_ccb, ccb, ac_chain);
1448
1449 /* If the free list was empty, wake up potential waiters. */
1450 if (TAILQ_NEXT(ccb, ac_chain) == NULL)
1451 wakeup(&sc->sc_free_ccb);
1452
1453 AAC_UNLOCK(sc, lock);
1454 }
1455
1456 void
aac_enqueue_ccb(sc,ccb)1457 aac_enqueue_ccb(sc, ccb)
1458 struct aac_softc *sc;
1459 struct aac_ccb *ccb;
1460 {
1461 AAC_DPRINTF(AAC_D_QUEUE, ("aac_enqueue_ccb(%p, %p) ", sc, ccb));
1462
1463 timeout_set(&ccb->ac_xs->stimeout, aac_timeout, ccb);
1464 TAILQ_INSERT_TAIL(&sc->sc_ccbq, ccb, ac_chain);
1465 aac_start_ccbs(sc);
1466 }
1467
1468 void
aac_start_ccbs(sc)1469 aac_start_ccbs(sc)
1470 struct aac_softc *sc;
1471 {
1472 struct aac_ccb *ccb;
1473 struct scsi_xfer *xs;
1474
1475 AAC_DPRINTF(AAC_D_QUEUE, ("aac_start_ccbs(%p) ", sc));
1476
1477 while ((ccb = TAILQ_FIRST(&sc->sc_ccbq)) != NULL) {
1478
1479 xs = ccb->ac_xs;
1480 if (ccb->ac_flags & AAC_ACF_WATCHDOG)
1481 timeout_del(&xs->stimeout);
1482
1483 if (aac_exec_ccb(ccb) == 0) {
1484 ccb->ac_flags |= AAC_ACF_WATCHDOG;
1485 timeout_set(&ccb->ac_xs->stimeout, aac_watchdog, ccb);
1486 timeout_add(&xs->stimeout,
1487 (AAC_WATCH_TIMEOUT * hz) / 1000);
1488 break;
1489 }
1490 TAILQ_REMOVE(&sc->sc_ccbq, ccb, ac_chain);
1491
1492 if ((xs->flags & SCSI_POLL) == 0) {
1493 timeout_set(&ccb->ac_xs->stimeout, aac_timeout, ccb);
1494 timeout_add(&xs->stimeout,
1495 (ccb->ac_timeout * hz) / 1000);
1496 }
1497 }
1498 }
1499
1500 int
aac_exec_ccb(ccb)1501 aac_exec_ccb(ccb)
1502 struct aac_ccb *ccb;
1503 {
1504 struct scsi_xfer *xs = ccb->ac_xs;
1505 struct scsi_link *link = xs->sc_link;
1506 u_int8_t target = link->target;
1507 int i;
1508 struct aac_fib *fib;
1509 struct aac_blockread *br;
1510 struct aac_blockwrite *bw;
1511 bus_dmamap_t xfer;
1512
1513 AAC_DPRINTF(AAC_D_CMD, ("aac_exec_ccb(%p, %p) ", xs, ccb));
1514
1515 /* build the FIB */
1516 fib = ccb->ac_fib;
1517 fib->Header.XferState = AAC_FIBSTATE_HOSTOWNED |
1518 AAC_FIBSTATE_INITIALISED | AAC_FIBSTATE_FROMHOST |
1519 AAC_FIBSTATE_REXPECTED | AAC_FIBSTATE_NORM;
1520 fib->Header.Command = ContainerCommand;
1521 fib->Header.Size = sizeof(struct aac_fib_header);
1522
1523 switch (xs->cmd->opcode) {
1524 case PREVENT_ALLOW:
1525 case SYNCHRONIZE_CACHE:
1526 if (xs->cmd->opcode == PREVENT_ALLOW) {
1527 /* XXX PREVENT_ALLOW support goes here */
1528 } else {
1529 AAC_DPRINTF(AAC_D_CMD,
1530 ("SYNCHRONIZE CACHE tgt %d ", target));
1531 }
1532 break;
1533
1534 case WRITE_COMMAND:
1535 case WRITE_BIG:
1536 bw = (struct aac_blockwrite *)&fib->data[0];
1537 bw->Command = VM_CtBlockWrite;
1538 bw->ContainerId = target;
1539 bw->BlockNumber = ccb->ac_blockno;
1540 bw->ByteCount = ccb->ac_blockcnt * DEV_BSIZE;
1541 bw->Stable = CUNSTABLE; /* XXX what's appropriate here? */
1542 fib->Header.Size += sizeof(struct aac_blockwrite);
1543 ccb->ac_sgtable = &bw->SgMap;
1544 break;
1545
1546 case READ_COMMAND:
1547 case READ_BIG:
1548 br = (struct aac_blockread *)&fib->data[0];
1549 br->Command = VM_CtBlockRead;
1550 br->ContainerId = target;
1551 br->BlockNumber = ccb->ac_blockno;
1552 br->ByteCount = ccb->ac_blockcnt * DEV_BSIZE;
1553 fib->Header.Size += sizeof(struct aac_blockread);
1554 ccb->ac_sgtable = &br->SgMap;
1555 break;
1556 }
1557
1558 if (xs->cmd->opcode != PREVENT_ALLOW &&
1559 xs->cmd->opcode != SYNCHRONIZE_CACHE) {
1560 xfer = ccb->ac_dmamap_xfer;
1561 ccb->ac_sgtable->SgCount = xfer->dm_nsegs;
1562 for (i = 0; i < xfer->dm_nsegs; i++) {
1563 ccb->ac_sgtable->SgEntry[i].SgAddress =
1564 xfer->dm_segs[i].ds_addr;
1565 ccb->ac_sgtable->SgEntry[i].SgByteCount =
1566 xfer->dm_segs[i].ds_len;
1567 AAC_DPRINTF(AAC_D_IO,
1568 ("#%d va %p pa %p len %x\n", i, buf,
1569 xfer->dm_segs[i].ds_addr,
1570 xfer->dm_segs[i].ds_len));
1571 }
1572
1573 /* update the FIB size for the s/g count */
1574 fib->Header.Size += xfer->dm_nsegs *
1575 sizeof(struct aac_sg_entry);
1576 }
1577
1578 if (aac_start(ccb) == 0) {
1579 xs->error = XS_NOERROR;
1580 xs->resid = 0;
1581 return (1);
1582 }
1583 return (0);
1584 }
1585
1586 /********************************************************************************
1587 * Deliver a command to the controller; allocate controller resources at the
1588 * last moment when possible.
1589 */
1590 int
aac_start(struct aac_ccb * ccb)1591 aac_start(struct aac_ccb *ccb)
1592 {
1593 struct aac_softc *sc = ccb->ac_xs->sc_link->adapter_softc;
1594
1595 #if 0
1596 /* get the command mapped */
1597 aac_map_command(ccb);
1598 #endif
1599
1600 /* fix up the address values */
1601 ccb->ac_fib->Header.SenderFibAddress = (u_int32_t)ccb->ac_fib;
1602 ccb->ac_fib->Header.ReceiverFibAddress = ccb->ac_fibphys;
1603
1604 /* save a pointer to the command for speedy reverse-lookup */
1605 ccb->ac_fib->Header.SenderData = (u_int32_t)ccb; /* XXX ack, sizing */
1606
1607 /* put the FIB on the outbound queue */
1608 if (aac_enqueue_fib(sc, AAC_ADAP_NORM_CMD_QUEUE, ccb))
1609 return (EBUSY);
1610
1611 return (0);
1612 }
1613
1614 /*
1615 * Map a command into controller-visible space.
1616 */
1617 int
aac_map_command(struct aac_ccb * ccb)1618 aac_map_command(struct aac_ccb *ccb)
1619 {
1620 struct scsi_xfer *xs = ccb->ac_xs;
1621 struct aac_softc *sc = xs->sc_link->adapter_softc;
1622 int error;
1623
1624 #if 0
1625 /* don't map more than once */
1626 if (ccb->ac_flags & AAC_CMD_MAPPED)
1627 return;
1628 #endif
1629
1630 if (xs->datalen != 0) {
1631 error = bus_dmamap_load(sc->sc_dmat, ccb->ac_dmamap_xfer,
1632 xs->data, xs->datalen, NULL,
1633 (xs->flags & SCSI_NOSLEEP) ? BUS_DMA_NOWAIT :
1634 BUS_DMA_WAITOK);
1635 if (error) {
1636 printf("%s: aac_scsi_cmd: ", sc->sc_dev.dv_xname);
1637 if (error == EFBIG)
1638 printf("more than %d dma segs\n",
1639 AAC_MAXSGENTRIES);
1640 else
1641 printf("error %d loading dma map\n", error);
1642 return (error);
1643 }
1644
1645 bus_dmamap_sync(sc->sc_dmat, ccb->ac_dmamap_xfer, 0,
1646 ccb->ac_dmamap_xfer->dm_mapsize,
1647 (xs->flags & SCSI_DATA_IN) ? BUS_DMASYNC_PREREAD :
1648 BUS_DMASYNC_PREWRITE);
1649 }
1650
1651 #if 0
1652 ccb->ac_flags |= AAC_CMD_MAPPED;
1653 #endif
1654 return (0);
1655 }
1656
1657 /*
1658 * Unmap a command from controller-visible space.
1659 */
1660 void
aac_unmap_command(struct aac_ccb * ccb)1661 aac_unmap_command(struct aac_ccb *ccb)
1662 {
1663 struct scsi_xfer *xs = ccb->ac_xs;
1664 struct aac_softc *sc = xs->sc_link->adapter_softc;
1665
1666 #if 0
1667 if (!(ccb->ac_flags & AAC_CMD_MAPPED))
1668 return;
1669 #endif
1670
1671 if (xs->datalen != 0) {
1672 bus_dmamap_sync(sc->sc_dmat, ccb->ac_dmamap_xfer, 0,
1673 ccb->ac_dmamap_xfer->dm_mapsize,
1674 (xs->flags & SCSI_DATA_IN) ? BUS_DMASYNC_POSTREAD :
1675 BUS_DMASYNC_POSTWRITE);
1676
1677 bus_dmamap_unload(sc->sc_dmat, ccb->ac_dmamap_xfer);
1678 }
1679 #if 0
1680 ccb->ac_flags &= ~AAC_CMD_MAPPED;
1681 #endif
1682 }
1683
1684 void
aac_timeout(arg)1685 aac_timeout(arg)
1686 void *arg;
1687 {
1688 struct aac_ccb *ccb = arg;
1689 struct scsi_link *link = ccb->ac_xs->sc_link;
1690 struct aac_softc *sc = link->adapter_softc;
1691 aac_lock_t lock;
1692
1693 sc_print_addr(link);
1694 printf("timed out\n");
1695
1696 /* XXX Test for multiple timeouts */
1697
1698 ccb->ac_xs->error = XS_TIMEOUT;
1699 lock = AAC_LOCK(sc);
1700 aac_enqueue_ccb(sc, ccb);
1701 AAC_UNLOCK(sc, lock);
1702 }
1703
1704 void
aac_watchdog(arg)1705 aac_watchdog(arg)
1706 void *arg;
1707 {
1708 struct aac_ccb *ccb = arg;
1709 struct scsi_link *link = ccb->ac_xs->sc_link;
1710 struct aac_softc *sc = link->adapter_softc;
1711 aac_lock_t lock;
1712
1713 lock = AAC_LOCK(sc);
1714 ccb->ac_flags &= ~AAC_ACF_WATCHDOG;
1715 aac_start_ccbs(sc);
1716 AAC_UNLOCK(sc, lock);
1717 }
1718 /*
1719 * Insert a command into the driver queue, either at the front or at the tail.
1720 * It's ok to overload the freelist link as these structures are never on
1721 * the freelist at this time.
1722 */
1723 void
aac_enqueue(sc,xs,infront)1724 aac_enqueue(sc, xs, infront)
1725 struct aac_softc *sc;
1726 struct scsi_xfer *xs;
1727 int infront;
1728 {
1729 if (infront || LIST_FIRST(&sc->sc_queue) == NULL) {
1730 if (LIST_FIRST(&sc->sc_queue) == NULL)
1731 sc->sc_queuelast = xs;
1732 LIST_INSERT_HEAD(&sc->sc_queue, xs, free_list);
1733 return;
1734 }
1735 LIST_INSERT_AFTER(sc->sc_queuelast, xs, free_list);
1736 sc->sc_queuelast = xs;
1737 }
1738
1739 /*
1740 * Pull a command off the front of the driver queue.
1741 */
1742 struct scsi_xfer *
aac_dequeue(sc)1743 aac_dequeue(sc)
1744 struct aac_softc *sc;
1745 {
1746 struct scsi_xfer *xs;
1747
1748 xs = LIST_FIRST(&sc->sc_queue);
1749 if (xs == NULL)
1750 return (NULL);
1751 LIST_REMOVE(xs, free_list);
1752
1753 if (LIST_FIRST(&sc->sc_queue) == NULL)
1754 sc->sc_queuelast = NULL;
1755
1756 return (xs);
1757 }
1758
1759 /********************************************************************************
1760 * Adapter-space FIB queue manipulation
1761 *
1762 * Note that the queue implementation here is a little funky; neither the PI or
1763 * CI will ever be zero. This behaviour is a controller feature.
1764 */
1765 static struct {
1766 int size;
1767 int notify;
1768 } aac_qinfo[] = {
1769 { AAC_HOST_NORM_CMD_ENTRIES, AAC_DB_COMMAND_NOT_FULL },
1770 { AAC_HOST_HIGH_CMD_ENTRIES, 0 },
1771 { AAC_ADAP_NORM_CMD_ENTRIES, AAC_DB_COMMAND_READY },
1772 { AAC_ADAP_HIGH_CMD_ENTRIES, 0 },
1773 { AAC_HOST_NORM_RESP_ENTRIES, AAC_DB_RESPONSE_NOT_FULL },
1774 { AAC_HOST_HIGH_RESP_ENTRIES, 0 },
1775 { AAC_ADAP_NORM_RESP_ENTRIES, AAC_DB_RESPONSE_READY },
1776 { AAC_ADAP_HIGH_RESP_ENTRIES, 0 }
1777 };
1778
1779 /*
1780 * Atomically insert an entry into the nominated queue, returns 0 on success
1781 * or EBUSY if the queue is full.
1782 *
1783 * XXX Note that it would be more efficient to defer notifying the controller
1784 * in the case where we may be inserting several entries in rapid succession,
1785 * but implementing this usefully is difficult.
1786 */
1787 int
aac_enqueue_fib(struct aac_softc * sc,int queue,struct aac_ccb * ccb)1788 aac_enqueue_fib(struct aac_softc *sc, int queue, struct aac_ccb *ccb)
1789 {
1790 u_int32_t pi, ci;
1791 int error;
1792 aac_lock_t lock;
1793 u_int32_t fib_size;
1794 u_int32_t fib_addr;
1795
1796 fib_size = ccb->ac_fib->Header.Size;
1797 fib_addr = ccb->ac_fib->Header.ReceiverFibAddress;
1798
1799 lock = AAC_LOCK(sc);
1800
1801 /* get the producer/consumer indices */
1802 pi = sc->sc_queues->qt_qindex[queue][AAC_PRODUCER_INDEX];
1803 ci = sc->sc_queues->qt_qindex[queue][AAC_CONSUMER_INDEX];
1804
1805 /* wrap the queue? */
1806 if (pi >= aac_qinfo[queue].size)
1807 pi = 0;
1808
1809 /* check for queue full */
1810 if ((pi + 1) == ci) {
1811 error = EBUSY;
1812 goto out;
1813 }
1814
1815 /* populate queue entry */
1816 (sc->sc_qentries[queue] + pi)->aq_fib_size = fib_size;
1817 (sc->sc_qentries[queue] + pi)->aq_fib_addr = fib_addr;
1818
1819 /* update producer index */
1820 sc->sc_queues->qt_qindex[queue][AAC_PRODUCER_INDEX] = pi + 1;
1821
1822 /* notify the adapter if we know how */
1823 if (aac_qinfo[queue].notify != 0)
1824 AAC_QNOTIFY(sc, aac_qinfo[queue].notify);
1825
1826 error = 0;
1827
1828 out:
1829 AAC_UNLOCK(sc, lock);
1830 return (error);
1831 }
1832
1833 /*
1834 * Atomically remove one entry from the nominated queue, returns 0 on success
1835 * or ENOENT if the queue is empty.
1836 */
1837 int
aac_dequeue_fib(struct aac_softc * sc,int queue,u_int32_t * fib_size,struct aac_fib ** fib_addr)1838 aac_dequeue_fib(struct aac_softc *sc, int queue, u_int32_t *fib_size,
1839 struct aac_fib **fib_addr)
1840 {
1841 u_int32_t pi, ci;
1842 int notify;
1843 int error;
1844 aac_lock_t lock;
1845
1846 lock = AAC_LOCK(sc);
1847
1848 /* get the producer/consumer indices */
1849 pi = sc->sc_queues->qt_qindex[queue][AAC_PRODUCER_INDEX];
1850 ci = sc->sc_queues->qt_qindex[queue][AAC_CONSUMER_INDEX];
1851
1852 /* check for queue empty */
1853 if (ci == pi) {
1854 error = ENOENT;
1855 goto out;
1856 }
1857
1858 notify = 0;
1859 if (ci == pi + 1)
1860 notify++;
1861
1862 /* wrap the queue? */
1863 if (ci >= aac_qinfo[queue].size)
1864 ci = 0;
1865
1866 /* fetch the entry */
1867 *fib_size = (sc->sc_qentries[queue] + ci)->aq_fib_size;
1868 *fib_addr =
1869 (struct aac_fib *)(sc->sc_qentries[queue] + ci)->aq_fib_addr;
1870
1871 /* update consumer index */
1872 sc->sc_queues->qt_qindex[queue][AAC_CONSUMER_INDEX] = ci + 1;
1873
1874 /* if we have made the queue un-full, notify the adapter */
1875 if (notify && (aac_qinfo[queue].notify != 0))
1876 AAC_QNOTIFY(sc, aac_qinfo[queue].notify);
1877 error = 0;
1878
1879 out:
1880 AAC_UNLOCK(sc, lock);
1881 return (error);
1882 }
1883
1884 #ifdef AAC_DEBUG
1885 /*
1886 * Print a FIB
1887 */
1888 void
aac_print_fib(struct aac_softc * sc,struct aac_fib * fib,char * caller)1889 aac_print_fib(struct aac_softc *sc, struct aac_fib *fib, char *caller)
1890 {
1891 printf("%s: FIB @ %p\n", caller, fib);
1892 printf(" XferState %b\n", fib->Header.XferState, "\20"
1893 "\1HOSTOWNED"
1894 "\2ADAPTEROWNED"
1895 "\3INITIALISED"
1896 "\4EMPTY"
1897 "\5FROMPOOL"
1898 "\6FROMHOST"
1899 "\7FROMADAP"
1900 "\10REXPECTED"
1901 "\11RNOTEXPECTED"
1902 "\12DONEADAP"
1903 "\13DONEHOST"
1904 "\14HIGH"
1905 "\15NORM"
1906 "\16ASYNC"
1907 "\17PAGEFILEIO"
1908 "\20SHUTDOWN"
1909 "\21LAZYWRITE"
1910 "\22ADAPMICROFIB"
1911 "\23BIOSFIB"
1912 "\24FAST_RESPONSE"
1913 "\25APIFIB\n");
1914 printf(" Command %d\n", fib->Header.Command);
1915 printf(" StructType %d\n", fib->Header.StructType);
1916 printf(" Flags 0x%x\n", fib->Header.Flags);
1917 printf(" Size %d\n", fib->Header.Size);
1918 printf(" SenderSize %d\n", fib->Header.SenderSize);
1919 printf(" SenderAddress 0x%x\n", fib->Header.SenderFibAddress);
1920 printf(" ReceiverAddress 0x%x\n", fib->Header.ReceiverFibAddress);
1921 printf(" SenderData 0x%x\n", fib->Header.SenderData);
1922 switch(fib->Header.Command) {
1923 case ContainerCommand: {
1924 struct aac_blockread *br = (struct aac_blockread *)fib->data;
1925 struct aac_blockwrite *bw = (struct aac_blockwrite *)fib->data;
1926 struct aac_sg_table *sg = NULL;
1927 int i;
1928
1929 if (br->Command == VM_CtBlockRead) {
1930 printf(" BlockRead: container %d 0x%x/%d\n",
1931 br->ContainerId, br->BlockNumber, br->ByteCount);
1932 sg = &br->SgMap;
1933 }
1934 if (bw->Command == VM_CtBlockWrite) {
1935 printf(" BlockWrite: container %d 0x%x/%d (%s)\n",
1936 bw->ContainerId, bw->BlockNumber, bw->ByteCount,
1937 bw->Stable == CSTABLE ? "stable" : "unstable");
1938 sg = &bw->SgMap;
1939 }
1940 if (sg != NULL) {
1941 printf(" %d s/g entries\n", sg->SgCount);
1942 for (i = 0; i < sg->SgCount; i++)
1943 printf(" 0x%08x/%d\n",
1944 sg->SgEntry[i].SgAddress,
1945 sg->SgEntry[i].SgByteCount);
1946 }
1947 break;
1948 }
1949 default:
1950 printf(" %16D\n", fib->data, " ");
1951 printf(" %16D\n", fib->data + 16, " ");
1952 break;
1953 }
1954 }
1955 #endif
1956