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