xref: /openbsd-src/sys/dev/ic/aac.c (revision b2ea75c1b17e1a9a339660e7ed45cd24946b230e)
1 /*	$OpenBSD: aac.c,v 1.7 2001/08/12 20:12:11 mickey 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 <vm/vm.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 __P((struct aac_ccb *));
75 void	aac_complete __P((void *, int));
76 void	aac_copy_internal_data __P((struct scsi_xfer *, u_int8_t *, size_t));
77 struct scsi_xfer *aac_dequeue __P((struct aac_softc *));
78 int	aac_dequeue_fib __P((struct aac_softc *, int, u_int32_t *,
79     struct aac_fib **));
80 char   *aac_describe_code __P((struct aac_code_lookup *, u_int32_t));
81 void	aac_describe_controller __P((struct aac_softc *));
82 void	aac_enqueue __P((struct aac_softc *, struct scsi_xfer *, int));
83 void	aac_enqueue_ccb __P((struct aac_softc *, struct aac_ccb *));
84 int	aac_enqueue_fib __P((struct aac_softc *, int, u_int32_t, u_int32_t));
85 void	aac_eval_mapping __P((u_int32_t, int *, int *, int *));
86 int	aac_exec_ccb __P((struct aac_ccb *));
87 void	aac_free_ccb __P((struct aac_softc *, struct aac_ccb *));
88 struct aac_ccb *aac_get_ccb __P((struct aac_softc *, int));
89 #if 0
90 void	aac_handle_aif __P((struct aac_softc *, struct aac_aif_command *));
91 #endif
92 void	aac_host_command __P((struct aac_softc *));
93 void	aac_host_response __P((struct aac_softc *));
94 int	aac_init __P((struct aac_softc *));
95 int	aac_internal_cache_cmd __P((struct scsi_xfer *));
96 int	aac_map_command __P((struct aac_ccb *));
97 #ifdef AAC_DEBUG
98 void	aac_print_fib __P((struct aac_softc *, struct aac_fib *, char *));
99 #endif
100 int	aac_raw_scsi_cmd __P((struct scsi_xfer *));
101 int	aac_scsi_cmd __P((struct scsi_xfer *));
102 int	aac_start __P((struct aac_ccb *));
103 void	aac_start_ccbs __P((struct aac_softc *));
104 void	aac_startup __P((struct aac_softc *));
105 int	aac_sync_command __P((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 __P((struct aac_softc *, u_int32_t, u_int32_t, void *,
108     u_int16_t, void *, u_int16_t *));
109 void	aac_timeout __P((void *));
110 void	aac_unmap_command __P((struct aac_ccb *));
111 void	aac_watchdog __P((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 __P((struct aac_softc *));
131 void	aac_rx_qnotify __P((struct aac_softc *, int));
132 int	aac_rx_get_istatus __P((struct aac_softc *));
133 void	aac_rx_clear_istatus __P((struct aac_softc *, int));
134 void	aac_rx_set_mailbox __P((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 __P((struct aac_softc *));
137 void	aac_rx_set_interrupts __P((struct aac_softc *, int));
138 
139 /* StrongARM interface */
140 int	aac_sa_get_fwstatus __P((struct aac_softc *));
141 void	aac_sa_qnotify __P((struct aac_softc *, int));
142 int	aac_sa_get_istatus __P((struct aac_softc *));
143 void	aac_sa_clear_istatus __P((struct aac_softc *, int));
144 void	aac_sa_set_mailbox __P((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 __P((struct aac_softc *));
147 void	aac_sa_set_interrupts __P((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 			 * Are we out of commands, something is wrong.
731 			 *
732 			 */
733 			if (ccb == NULL) {
734 				printf("%s: no ccb in aac_scsi_cmd",
735 				    sc->sc_dev.dv_xname);
736 				xs->error = XS_DRIVER_STUFFUP;
737 				xs->flags |= ITSDONE;
738 				scsi_done(xs);
739 				goto ready;
740 			}
741 
742 			ccb->ac_blockno = blockno;
743 			ccb->ac_blockcnt = blockcnt;
744 			ccb->ac_xs = xs;
745 			ccb->ac_timeout = xs->timeout;
746 
747 			if (xs->cmd->opcode != SYNCHRONIZE_CACHE &&
748 			    aac_map_command(ccb)) {
749 				aac_free_ccb(sc, ccb);
750 				xs->error = XS_DRIVER_STUFFUP;
751 				xs->flags |= ITSDONE;
752 				scsi_done(xs);
753 				goto ready;
754 			}
755 
756 			aac_enqueue_ccb(sc, ccb);
757 			/* XXX what if enqueue did not start a transfer? */
758 			if (xs->flags & SCSI_POLL) {
759 #if 0
760 				if (!aac_wait(sc, ccb, ccb->ac_timeout)) {
761 					AAC_UNLOCK(sc, lock);
762 					printf("%s: command timed out\n",
763 					    sc->sc_dev.dv_xname);
764 					xs->error = XS_TIMEOUT;
765 					return (TRY_AGAIN_LATER);
766 				}
767 				xs->flags |= ITSDONE;
768 				scsi_done(xs);
769 #endif
770 			}
771 		}
772 
773 	ready:
774 		/*
775 		 * Don't process the queue if we are polling.
776 		 */
777 		if (xs->flags & SCSI_POLL) {
778 			retval = COMPLETE;
779 			break;
780 		}
781 	}
782 
783 	AAC_UNLOCK(sc, lock);
784 	return (retval);
785 }
786 
787 void
788 aac_copy_internal_data(xs, data, size)
789 	struct scsi_xfer *xs;
790 	u_int8_t *data;
791 	size_t size;
792 {
793 	size_t copy_cnt;
794 
795 	AAC_DPRINTF(AAC_D_MISC, ("aac_copy_internal_data "));
796 
797 	if (!xs->datalen)
798 		printf("uio move not yet supported\n");
799 	else {
800 		copy_cnt = MIN(size, xs->datalen);
801 		bcopy(data, xs->data, copy_cnt);
802 	}
803 }
804 
805 /* Emulated SCSI operation on cache device */
806 int
807 aac_internal_cache_cmd(xs)
808 	struct scsi_xfer *xs;
809 {
810 	struct scsi_link *link = xs->sc_link;
811 	struct aac_softc *sc = link->adapter_softc;
812 	struct scsi_inquiry_data inq;
813 	struct scsi_sense_data sd;
814 	struct {
815 		struct scsi_mode_header hd;
816 		struct scsi_blk_desc bd;
817 		union scsi_disk_pages dp;
818 	} mpd;
819 	struct scsi_read_cap_data rcd;
820 	u_int8_t target = link->target;
821 
822 	AAC_DPRINTF(AAC_D_CMD, ("aac_internal_cache_cmd "));
823 
824 	switch (xs->cmd->opcode) {
825 	case TEST_UNIT_READY:
826 	case START_STOP:
827 #if 0
828 	case VERIFY:
829 #endif
830 		AAC_DPRINTF(AAC_D_CMD, ("opc %d tgt %d ", xs->cmd->opcode,
831 		    target));
832 		break;
833 
834 	case REQUEST_SENSE:
835 		AAC_DPRINTF(AAC_D_CMD, ("REQUEST SENSE tgt %d ", target));
836 		bzero(&sd, sizeof sd);
837 		sd.error_code = 0x70;
838 		sd.segment = 0;
839 		sd.flags = SKEY_NO_SENSE;
840 		aac_enc32(sd.info, 0);
841 		sd.extra_len = 0;
842 		aac_copy_internal_data(xs, (u_int8_t *)&sd, sizeof sd);
843 		break;
844 
845 	case INQUIRY:
846 		AAC_DPRINTF(AAC_D_CMD, ("INQUIRY tgt %d devtype %x ", target,
847 		    sc->sc_hdr[target].hd_devtype));
848 		bzero(&inq, sizeof inq);
849 		/* XXX How do we detect removable/CD-ROM devices?  */
850 		inq.device = T_DIRECT;
851 		inq.dev_qual2 = 0;
852 		inq.version = 2;
853 		inq.response_format = 2;
854 		inq.additional_length = 32;
855 		strcpy(inq.vendor, "Adaptec");
856 		sprintf(inq.product, "Container #%02d", target);
857 		strcpy(inq.revision, "   ");
858 		aac_copy_internal_data(xs, (u_int8_t *)&inq, sizeof inq);
859 		break;
860 
861 	case MODE_SENSE:
862 		AAC_DPRINTF(AAC_D_CMD, ("MODE SENSE tgt %d ", target));
863 
864 		bzero(&mpd, sizeof mpd);
865 		switch (((struct scsi_mode_sense *)xs->cmd)->page) {
866 		case 4:
867 			/* scsi_disk.h says this should be 0x16 */
868 			mpd.dp.rigid_geometry.pg_length = 0x16;
869 			mpd.hd.data_length = sizeof mpd.hd + sizeof mpd.bd +
870 			    mpd.dp.rigid_geometry.pg_length;
871 			mpd.hd.blk_desc_len = sizeof mpd.bd;
872 
873 			/* XXX */
874 			mpd.hd.dev_spec = 0;
875 			_lto3b(AAC_BLOCK_SIZE, mpd.bd.blklen);
876 			mpd.dp.rigid_geometry.pg_code = 4;
877 			_lto3b(sc->sc_hdr[target].hd_size /
878 			    sc->sc_hdr[target].hd_heads /
879 			    sc->sc_hdr[target].hd_secs,
880 			    mpd.dp.rigid_geometry.ncyl);
881 			mpd.dp.rigid_geometry.nheads =
882 			    sc->sc_hdr[target].hd_heads;
883 			aac_copy_internal_data(xs, (u_int8_t *)&mpd,
884 			    sizeof mpd);
885 			break;
886 
887 		default:
888 			printf("%s: mode sense page %d not simulated\n",
889 			    sc->sc_dev.dv_xname,
890 			    ((struct scsi_mode_sense *)xs->cmd)->page);
891 			xs->error = XS_DRIVER_STUFFUP;
892 			return (0);
893 		}
894 		break;
895 
896 	case READ_CAPACITY:
897 		AAC_DPRINTF(AAC_D_CMD, ("READ CAPACITY tgt %d ", target));
898 		bzero(&rcd, sizeof rcd);
899 		_lto4b(sc->sc_hdr[target].hd_size - 1, rcd.addr);
900 		_lto4b(AAC_BLOCK_SIZE, rcd.length);
901 		aac_copy_internal_data(xs, (u_int8_t *)&rcd, sizeof rcd);
902 		break;
903 
904 	default:
905 		printf("aac_internal_cache_cmd got bad opcode: %d\n",
906 		    xs->cmd->opcode);
907 		xs->error = XS_DRIVER_STUFFUP;
908 		return (0);
909 	}
910 
911 	xs->error = XS_NOERROR;
912 	return (1);
913 }
914 
915 /*
916  * Take an interrupt.
917  */
918 int
919 aac_intr(arg)
920 	void *arg;
921 {
922 	struct aac_softc *sc = arg;
923 	u_int16_t reason;
924 	int claimed = 0;
925 
926 	AAC_DPRINTF(AAC_D_INTR, ("aac_intr(%p) ", sc));
927 
928 	reason = AAC_GET_ISTATUS(sc);
929 	AAC_DPRINTF(AAC_D_INTR, ("istatus 0x%04x ", reason));
930 
931 	/* controller wants to talk to the log?  XXX should we defer this? */
932 	if (reason & AAC_DB_PRINTF) {
933 		if (sc->sc_common->ac_printf[0]) {
934 			printf("%s: ** %.*s", sc->sc_dev.dv_xname,
935 			    AAC_PRINTF_BUFSIZE, sc->sc_common->ac_printf);
936 			sc->sc_common->ac_printf[0] = 0;
937 		}
938 		AAC_CLEAR_ISTATUS(sc, AAC_DB_PRINTF);
939 		AAC_QNOTIFY(sc, AAC_DB_PRINTF);
940 		claimed = 1;
941 	}
942 
943 	/* Controller has a message for us? */
944 	if (reason & AAC_DB_COMMAND_READY) {
945 		aac_host_command(sc);
946 		AAC_CLEAR_ISTATUS(sc, AAC_DB_COMMAND_READY);
947 		claimed = 1;
948 	}
949 
950 	/* Controller has a response for us? */
951 	if (reason & AAC_DB_RESPONSE_READY) {
952 		aac_host_response(sc);
953 		AAC_CLEAR_ISTATUS(sc, AAC_DB_RESPONSE_READY);
954 		claimed = 1;
955 	}
956 
957 	/*
958 	 * Spurious interrupts that we don't use - reset the mask and clear
959 	 * the interrupts.
960 	 */
961 	if (reason & (AAC_DB_SYNC_COMMAND | AAC_DB_COMMAND_NOT_FULL |
962             AAC_DB_RESPONSE_NOT_FULL)) {
963 		AAC_UNMASK_INTERRUPTS(sc);
964 		AAC_CLEAR_ISTATUS(sc, AAC_DB_SYNC_COMMAND |
965 		    AAC_DB_COMMAND_NOT_FULL | AAC_DB_RESPONSE_NOT_FULL);
966 		claimed = 1;
967 	}
968 
969 	return (claimed);
970 }
971 
972 /*
973  * Handle notification of one or more FIBs coming from the controller.
974  */
975 void
976 aac_host_command(struct aac_softc *sc)
977 {
978 	struct aac_fib *fib;
979 	u_int32_t fib_size;
980 
981 	for (;;) {
982 		if (aac_dequeue_fib(sc, AAC_HOST_NORM_CMD_QUEUE, &fib_size,
983 		    &fib))
984 			break;	/* nothing to do */
985 
986 		switch(fib->Header.Command) {
987 		case AifRequest:
988 #if 0
989 			aac_handle_aif(sc,
990 			    (struct aac_aif_command *)&fib->data[0]);
991 #endif
992 
993 			break;
994 		default:
995 			printf("%s: unknown command from controller\n",
996 			    sc->sc_dev.dv_xname);
997 			AAC_PRINT_FIB(sc, fib);
998 			break;
999 		}
1000 
1001 		/* XXX reply to FIBs requesting responses ?? */
1002 		/* XXX how do we return these FIBs to the controller? */
1003 	}
1004 }
1005 
1006 /*
1007  * Handle notification of one or more FIBs completed by the controller
1008  */
1009 void
1010 aac_host_response(struct aac_softc *sc)
1011 {
1012 	struct aac_ccb *ccb;
1013 	struct aac_fib *fib;
1014 	u_int32_t fib_size;
1015 
1016 	for (;;) {
1017 		/* look for completed FIBs on our queue */
1018 		if (aac_dequeue_fib(sc, AAC_HOST_NORM_RESP_QUEUE, &fib_size,
1019 		    &fib))
1020 			break;	/* nothing to do */
1021 
1022 		/* get the command, unmap and queue for later processing */
1023 		ccb = (struct aac_ccb *)fib->Header.SenderData;
1024 		if (ccb == NULL) {
1025 			AAC_PRINT_FIB(sc, fib);
1026 		} else {
1027 			timeout_del(&ccb->ac_xs->stimeout);
1028 			aac_unmap_command(ccb);		/* XXX defer? */
1029 			aac_enqueue_completed(ccb);
1030 		}
1031 	}
1032 
1033 	/* handle completion processing */
1034 	aac_complete(sc, 0);
1035 }
1036 
1037 /*
1038  * Process completed commands.
1039  */
1040 void
1041 aac_complete(void *context, int pending)
1042 {
1043 	struct aac_softc *sc = (struct aac_softc *)context;
1044 	struct aac_ccb *ccb;
1045 
1046 	/* pull completed commands off the queue */
1047 	for (;;) {
1048 		ccb = aac_dequeue_completed(sc);
1049 		if (ccb == NULL)
1050 			return;
1051 		ccb->ac_flags |= AAC_ACF_COMPLETED;
1052 
1053 #if 0
1054 		/* is there a completion handler? */
1055 		if (ccb->ac_complete != NULL) {
1056 			ccb->ac_complete(ccb);
1057 		} else {
1058 			/* assume that someone is sleeping on this command */
1059 			wakeup(ccb);
1060 		}
1061 #else
1062 		aac_bio_complete(ccb);
1063 #endif
1064 	}
1065 }
1066 
1067 /*
1068  * Handle a bio-instigated command that has been completed.
1069  */
1070 void
1071 aac_bio_complete(struct aac_ccb *ccb)
1072 {
1073 	struct scsi_xfer *xs = ccb->ac_xs;
1074 	struct aac_softc *sc = xs->sc_link->adapter_softc;
1075 	struct buf *bp = xs->bp;
1076 	struct aac_blockread_response *brr;
1077 	struct aac_blockwrite_response *bwr;
1078 	AAC_FSAStatus status;
1079 
1080 	/* fetch relevant status and then release the command */
1081 	if (bp->b_flags & B_READ) {
1082 		brr = (struct aac_blockread_response *)&ccb->ac_fib->data[0];
1083 		status = brr->Status;
1084 	} else {
1085 		bwr = (struct aac_blockwrite_response *)&ccb->ac_fib->data[0];
1086 		status = bwr->Status;
1087 	}
1088 	aac_free_ccb(sc, ccb);
1089 
1090 	/* fix up the bio based on status */
1091 	if (status == ST_OK) {
1092 		bp->b_resid = 0;
1093 	} else {
1094 		bp->b_error = EIO;
1095 		bp->b_flags |= B_ERROR;
1096 
1097 		/* XXX be more verbose? */
1098 		printf("%s: I/O error %d (%s)\n", status,
1099 		    AAC_COMMAND_STATUS(status));
1100 	}
1101 	scsi_done(xs);
1102 }
1103 
1104 /*
1105  * Send a synchronous command to the controller and wait for a result.
1106  */
1107 int
1108 aac_sync_command(sc, command, arg0, arg1, arg2, arg3, sp)
1109 	struct aac_softc *sc;
1110 	u_int32_t command;
1111 	u_int32_t arg0;
1112 	u_int32_t arg1;
1113 	u_int32_t arg2;
1114 	u_int32_t arg3;
1115 	u_int32_t *sp;
1116 {
1117 	int i;
1118 	u_int32_t status;
1119 	aac_lock_t lock = AAC_LOCK(sc);
1120 
1121 	/* populate the mailbox */
1122 	AAC_SET_MAILBOX(sc, command, arg0, arg1, arg2, arg3);
1123 
1124 	/* ensure the sync command doorbell flag is cleared */
1125 	AAC_CLEAR_ISTATUS(sc, AAC_DB_SYNC_COMMAND);
1126 
1127 	/* then set it to signal the adapter */
1128 	AAC_QNOTIFY(sc, AAC_DB_SYNC_COMMAND);
1129 	DELAY(AAC_SYNC_DELAY);
1130 
1131 	/* spin waiting for the command to complete */
1132 	for (i = 0; i < AAC_IMMEDIATE_TIMEOUT * 1000; i++) {
1133 		if (AAC_GET_ISTATUS(sc) & AAC_DB_SYNC_COMMAND);
1134 			break;
1135 		DELAY(1000);
1136 	}
1137 	if (i == AAC_IMMEDIATE_TIMEOUT * 1000) {
1138 		AAC_UNLOCK(sc, lock);
1139 		return (EIO);
1140 	}
1141 
1142 	/* clear the completion flag */
1143 	AAC_CLEAR_ISTATUS(sc, AAC_DB_SYNC_COMMAND);
1144 
1145 	/* get the command status */
1146 	status = AAC_GET_MAILBOXSTATUS(sc);
1147 	AAC_UNLOCK(sc, lock);
1148 	if (sp != NULL)
1149 		*sp = status;
1150 	return (0);	/* check command return status? */
1151 }
1152 
1153 /*
1154  * Send a synchronous FIB to the controller and wait for a result.
1155  */
1156 int
1157 aac_sync_fib(sc, command, xferstate, data, datasize, result, resultsize)
1158 	struct aac_softc *sc;
1159 	u_int32_t command;
1160 	u_int32_t xferstate;
1161 	void *data;
1162 	u_int16_t datasize;
1163 	void *result;
1164 	u_int16_t *resultsize;
1165 {
1166 	struct aac_fib *fib = &sc->sc_common->ac_sync_fib;
1167 
1168 	if (datasize > AAC_FIB_DATASIZE)
1169 		return (EINVAL);
1170 
1171 	/*
1172 	 * Set up the sync FIB
1173 	 */
1174 	fib->Header.XferState = AAC_FIBSTATE_HOSTOWNED |
1175 	    AAC_FIBSTATE_INITIALISED | AAC_FIBSTATE_EMPTY;
1176 	fib->Header.XferState |= xferstate;
1177 	fib->Header.Command = command;
1178 	fib->Header.StructType = AAC_FIBTYPE_TFIB;
1179 	fib->Header.Size = sizeof fib + datasize;
1180 	fib->Header.SenderSize = sizeof *fib;
1181 	fib->Header.SenderFibAddress = (u_int32_t)fib;
1182 	fib->Header.ReceiverFibAddress =
1183 	    sc->sc_common_busaddr + offsetof(struct aac_common, ac_sync_fib);
1184 
1185 	/*
1186 	 * Copy in data.
1187 	 */
1188 	if (data != NULL) {
1189 		bcopy(data, fib->data, datasize);
1190 		fib->Header.XferState |=
1191 		    AAC_FIBSTATE_FROMHOST | AAC_FIBSTATE_NORM;
1192 	}
1193 
1194 	/*
1195 	 * Give the FIB to the controller, wait for a response.
1196 	 */
1197 	if (aac_sync_command(sc, AAC_MONKER_SYNCFIB,
1198 	    fib->Header.ReceiverFibAddress, 0, 0, 0, NULL)) {
1199 		return (EIO);
1200 	}
1201 
1202 	/*
1203 	 * Copy out the result
1204 	 */
1205 	if (result != NULL) {
1206 		*resultsize = fib->Header.Size - sizeof fib->Header;
1207 		bcopy(fib->data, result, *resultsize);
1208 	}
1209 	return (0);
1210 }
1211 
1212 void
1213 aacminphys(bp)
1214 	struct buf *bp;
1215 {
1216 #if 0
1217 	u_int8_t *buf = bp->b_data;
1218 	paddr_t pa;
1219 	long off;
1220 #endif
1221 
1222 	AAC_DPRINTF(AAC_D_MISC, ("aacminphys(0x%x) ", bp));
1223 
1224 #if 1
1225 #if 0	/* As this is way more than MAXPHYS it's really not necessary. */
1226 	if (bp->b_bcount > ((AAC_MAXOFFSETS - 1) * PAGE_SIZE))
1227 		bp->b_bcount = ((AAC_MAXOFFSETS - 1) * PAGE_SIZE);
1228 #endif
1229 #else
1230 	for (off = PAGE_SIZE, pa = vtophys(buf); off < bp->b_bcount;
1231 	    off += PAGE_SIZE)
1232 		if (pa + off != vtophys(buf + off)) {
1233 			bp->b_bcount = off;
1234 			break;
1235 		}
1236 #endif
1237 	minphys(bp);
1238 }
1239 
1240 /*
1241  * Read the current firmware status word.
1242  */
1243 int
1244 aac_sa_get_fwstatus(sc)
1245 	struct aac_softc *sc;
1246 {
1247 	return (AAC_GETREG4(sc, AAC_SA_FWSTATUS));
1248 }
1249 
1250 int
1251 aac_rx_get_fwstatus(sc)
1252 	struct aac_softc *sc;
1253 {
1254 	return (AAC_GETREG4(sc, AAC_RX_FWSTATUS));
1255 }
1256 
1257 /*
1258  * Notify the controller of a change in a given queue
1259  */
1260 
1261 void
1262 aac_sa_qnotify(sc, qbit)
1263 	struct aac_softc *sc;
1264 	int qbit;
1265 {
1266 	AAC_SETREG2(sc, AAC_SA_DOORBELL1_SET, qbit);
1267 }
1268 
1269 void
1270 aac_rx_qnotify(sc, qbit)
1271 	struct aac_softc *sc;
1272 	int qbit;
1273 {
1274 	AAC_SETREG4(sc, AAC_RX_IDBR, qbit);
1275 }
1276 
1277 /*
1278  * Get the interrupt reason bits
1279  */
1280 int
1281 aac_sa_get_istatus(sc)
1282 	struct aac_softc *sc;
1283 {
1284 	return (AAC_GETREG2(sc, AAC_SA_DOORBELL0));
1285 }
1286 
1287 int
1288 aac_rx_get_istatus(sc)
1289 	struct aac_softc *sc;
1290 {
1291 	return (AAC_GETREG4(sc, AAC_RX_ODBR));
1292 }
1293 
1294 /*
1295  * Clear some interrupt reason bits
1296  */
1297 void
1298 aac_sa_clear_istatus(sc, mask)
1299 	struct aac_softc *sc;
1300 	int mask;
1301 {
1302 	AAC_SETREG2(sc, AAC_SA_DOORBELL0_CLEAR, mask);
1303 }
1304 
1305 void
1306 aac_rx_clear_istatus(sc, mask)
1307 	struct aac_softc *sc;
1308 	int mask;
1309 {
1310 	AAC_SETREG4(sc, AAC_RX_ODBR, mask);
1311 }
1312 
1313 /*
1314  * Populate the mailbox and set the command word
1315  */
1316 void
1317 aac_sa_set_mailbox(sc, command, arg0, arg1, arg2, arg3)
1318 	struct aac_softc *sc;
1319 	u_int32_t command;
1320 	u_int32_t arg0;
1321 	u_int32_t arg1;
1322 	u_int32_t arg2;
1323 	u_int32_t arg3;
1324 {
1325 	AAC_SETREG4(sc, AAC_SA_MAILBOX, command);
1326 	AAC_SETREG4(sc, AAC_SA_MAILBOX + 4, arg0);
1327 	AAC_SETREG4(sc, AAC_SA_MAILBOX + 8, arg1);
1328 	AAC_SETREG4(sc, AAC_SA_MAILBOX + 12, arg2);
1329 	AAC_SETREG4(sc, AAC_SA_MAILBOX + 16, arg3);
1330 }
1331 
1332 void
1333 aac_rx_set_mailbox(sc, command, arg0, arg1, arg2, arg3)
1334 	struct aac_softc *sc;
1335 	u_int32_t command;
1336 	u_int32_t arg0;
1337 	u_int32_t arg1;
1338 	u_int32_t arg2;
1339 	u_int32_t arg3;
1340 {
1341 	AAC_SETREG4(sc, AAC_RX_MAILBOX, command);
1342 	AAC_SETREG4(sc, AAC_RX_MAILBOX + 4, arg0);
1343 	AAC_SETREG4(sc, AAC_RX_MAILBOX + 8, arg1);
1344 	AAC_SETREG4(sc, AAC_RX_MAILBOX + 12, arg2);
1345 	AAC_SETREG4(sc, AAC_RX_MAILBOX + 16, arg3);
1346 }
1347 
1348 /*
1349  * Fetch the immediate command status word
1350  */
1351 int
1352 aac_sa_get_mailboxstatus(sc)
1353 	struct aac_softc *sc;
1354 {
1355 	return (AAC_GETREG4(sc, AAC_SA_MAILBOX));
1356 }
1357 
1358 int
1359 aac_rx_get_mailboxstatus(sc)
1360 	struct aac_softc *sc;
1361 {
1362 	return (AAC_GETREG4(sc, AAC_RX_MAILBOX));
1363 }
1364 
1365 /*
1366  * Set/clear interrupt masks
1367  */
1368 void
1369 aac_sa_set_interrupts(sc, enable)
1370 	struct aac_softc *sc;
1371 	int enable;
1372 {
1373 	if (enable)
1374 		AAC_SETREG2((sc), AAC_SA_MASK0_CLEAR, AAC_DB_INTERRUPTS);
1375 	else
1376 		AAC_SETREG2((sc), AAC_SA_MASK0_SET, ~0);
1377 }
1378 
1379 void
1380 aac_rx_set_interrupts(sc, enable)
1381 	struct aac_softc *sc;
1382 	int enable;
1383 {
1384 	if (enable)
1385 		AAC_SETREG4(sc, AAC_RX_OIMR, ~AAC_DB_INTERRUPTS);
1386 	else
1387 		AAC_SETREG4(sc, AAC_RX_OIMR, ~0);
1388 }
1389 
1390 struct aac_ccb *
1391 aac_get_ccb(sc, flags)
1392 	struct aac_softc *sc;
1393 	int flags;
1394 {
1395 	struct aac_ccb *ccb;
1396 	aac_lock_t lock;
1397 
1398 	AAC_DPRINTF(AAC_D_QUEUE, ("aac_get_ccb(%p, 0x%x) ", sc, flags));
1399 
1400 	lock = AAC_LOCK(sc);
1401 
1402 	for (;;) {
1403 		ccb = TAILQ_FIRST(&sc->sc_free_ccb);
1404 		if (ccb != NULL)
1405 			break;
1406 		if (flags & SCSI_NOSLEEP)
1407 			goto bail_out;
1408 		tsleep(&sc->sc_free_ccb, PRIBIO, "aac_ccb", 0);
1409 	}
1410 
1411 	TAILQ_REMOVE(&sc->sc_free_ccb, ccb, ac_chain);
1412 
1413 	/* initialise the command/FIB */
1414 	ccb->ac_sgtable = NULL;
1415 	ccb->ac_flags = 0;
1416 	ccb->ac_fib->Header.XferState = AAC_FIBSTATE_EMPTY;
1417 	ccb->ac_fib->Header.StructType = AAC_FIBTYPE_TFIB;
1418 	ccb->ac_fib->Header.Flags = 0;
1419 	ccb->ac_fib->Header.SenderSize = sizeof(struct aac_fib);
1420 
1421 	/*
1422 	 * These are duplicated in aac_start to cover the case where an
1423 	 * intermediate stage may have destroyed them.  They're left
1424 	 * initialised here for debugging purposes only.
1425 	 */
1426 	ccb->ac_fib->Header.SenderFibAddress = (u_int32_t)ccb->ac_fib;
1427 	ccb->ac_fib->Header.ReceiverFibAddress = ccb->ac_fibphys;
1428 
1429  bail_out:
1430 	AAC_UNLOCK(sc, lock);
1431 	return (ccb);
1432 }
1433 
1434 void
1435 aac_free_ccb(sc, ccb)
1436 	struct aac_softc *sc;
1437 	struct aac_ccb *ccb;
1438 {
1439 	aac_lock_t lock;
1440 
1441 	AAC_DPRINTF(AAC_D_QUEUE, ("aac_free_ccb(%p, %p) ", sc, ccb));
1442 
1443 	lock = AAC_LOCK(sc);
1444 
1445 	TAILQ_INSERT_HEAD(&sc->sc_free_ccb, ccb, ac_chain);
1446 
1447 	/* If the free list was empty, wake up potential waiters. */
1448 	if (TAILQ_NEXT(ccb, ac_chain) == NULL)
1449 		wakeup(&sc->sc_free_ccb);
1450 
1451 	AAC_UNLOCK(sc, lock);
1452 }
1453 
1454 void
1455 aac_enqueue_ccb(sc, ccb)
1456 	struct aac_softc *sc;
1457 	struct aac_ccb *ccb;
1458 {
1459 	AAC_DPRINTF(AAC_D_QUEUE, ("aac_enqueue_ccb(%p, %p) ", sc, ccb));
1460 
1461 	timeout_set(&ccb->ac_xs->stimeout, aac_timeout, ccb);
1462 	TAILQ_INSERT_TAIL(&sc->sc_ccbq, ccb, ac_chain);
1463 	aac_start_ccbs(sc);
1464 }
1465 
1466 void
1467 aac_start_ccbs(sc)
1468 	struct aac_softc *sc;
1469 {
1470 	struct aac_ccb *ccb;
1471 	struct scsi_xfer *xs;
1472 
1473 	AAC_DPRINTF(AAC_D_QUEUE, ("aac_start_ccbs(%p) ", sc));
1474 
1475 	while ((ccb = TAILQ_FIRST(&sc->sc_ccbq)) != NULL) {
1476 
1477 		xs = ccb->ac_xs;
1478 		if (ccb->ac_flags & AAC_ACF_WATCHDOG)
1479 			timeout_del(&xs->stimeout);
1480 
1481 		if (aac_exec_ccb(ccb) == 0) {
1482 			ccb->ac_flags |= AAC_ACF_WATCHDOG;
1483 			timeout_set(&ccb->ac_xs->stimeout, aac_watchdog, ccb);
1484 			timeout_add(&xs->stimeout,
1485 			    (AAC_WATCH_TIMEOUT * hz) / 1000);
1486 			break;
1487 		}
1488 		TAILQ_REMOVE(&sc->sc_ccbq, ccb, ac_chain);
1489 
1490 		if ((xs->flags & SCSI_POLL) == 0) {
1491 			timeout_set(&ccb->ac_xs->stimeout, aac_timeout, ccb);
1492 			timeout_add(&xs->stimeout,
1493 			    (ccb->ac_timeout * hz) / 1000);
1494 		}
1495 	}
1496 }
1497 
1498 int
1499 aac_exec_ccb(ccb)
1500 	struct aac_ccb *ccb;
1501 {
1502 	struct scsi_xfer *xs = ccb->ac_xs;
1503 	struct scsi_link *link = xs->sc_link;
1504 	u_int8_t target = link->target;
1505 	int i;
1506 	struct aac_fib *fib;
1507 	struct aac_blockread *br;
1508 	struct aac_blockwrite *bw;
1509 	bus_dmamap_t xfer;
1510 
1511 	AAC_DPRINTF(AAC_D_CMD, ("aac_exec_ccb(%p, %p) ", xs, ccb));
1512 
1513 	/* build the FIB */
1514 	fib = ccb->ac_fib;
1515 	fib->Header.XferState = AAC_FIBSTATE_HOSTOWNED |
1516 	    AAC_FIBSTATE_INITIALISED | AAC_FIBSTATE_FROMHOST |
1517 	    AAC_FIBSTATE_REXPECTED | AAC_FIBSTATE_NORM;
1518 	fib->Header.Command = ContainerCommand;
1519 	fib->Header.Size = sizeof(struct aac_fib_header);
1520 
1521 	switch (xs->cmd->opcode) {
1522 	case PREVENT_ALLOW:
1523 	case SYNCHRONIZE_CACHE:
1524 		if (xs->cmd->opcode == PREVENT_ALLOW) {
1525 			/* XXX PREVENT_ALLOW support goes here */
1526 		} else {
1527 			AAC_DPRINTF(AAC_D_CMD,
1528 			    ("SYNCHRONIZE CACHE tgt %d ", target));
1529 		}
1530 		break;
1531 
1532 	case WRITE_COMMAND:
1533 	case WRITE_BIG:
1534 		bw = (struct aac_blockwrite *)&fib->data[0];
1535 		bw->Command = VM_CtBlockWrite;
1536 		bw->ContainerId = target;
1537 		bw->BlockNumber = ccb->ac_blockno;
1538 		bw->ByteCount = ccb->ac_blockcnt * DEV_BSIZE;
1539 		bw->Stable = CUNSTABLE;	/* XXX what's appropriate here? */
1540 		fib->Header.Size += sizeof(struct aac_blockwrite);
1541 		ccb->ac_sgtable = &bw->SgMap;
1542 		break;
1543 
1544 	case READ_COMMAND:
1545 	case READ_BIG:
1546 		br = (struct aac_blockread *)&fib->data[0];
1547 		br->Command = VM_CtBlockRead;
1548 		br->ContainerId = target;
1549 		br->BlockNumber = ccb->ac_blockno;
1550 		br->ByteCount = ccb->ac_blockcnt * DEV_BSIZE;
1551 		fib->Header.Size += sizeof(struct aac_blockread);
1552 		ccb->ac_sgtable = &br->SgMap;
1553 		break;
1554 	}
1555 
1556 	if (xs->cmd->opcode != PREVENT_ALLOW &&
1557 	    xs->cmd->opcode != SYNCHRONIZE_CACHE) {
1558 		xfer = ccb->ac_dmamap_xfer;
1559 		ccb->ac_sgtable->SgCount = xfer->dm_nsegs;
1560 		for (i = 0; i < xfer->dm_nsegs; i++) {
1561 			ccb->ac_sgtable->SgEntry[i].SgAddress =
1562 			    xfer->dm_segs[i].ds_addr;
1563 			ccb->ac_sgtable->SgEntry[i].SgByteCount =
1564 			    xfer->dm_segs[i].ds_len;
1565 			AAC_DPRINTF(AAC_D_IO,
1566 			    ("#%d va %p pa %p len %x\n", i, buf,
1567 			    xfer->dm_segs[i].ds_addr,
1568 			    xfer->dm_segs[i].ds_len));
1569 		}
1570 
1571 		/* update the FIB size for the s/g count */
1572 		fib->Header.Size += xfer->dm_nsegs *
1573 		    sizeof(struct aac_sg_entry);
1574 	}
1575 
1576 	aac_start(ccb);
1577 
1578 	xs->error = XS_NOERROR;
1579 	xs->resid = 0;
1580 	return (1);
1581 }
1582 
1583 /********************************************************************************
1584  * Deliver a command to the controller; allocate controller resources at the
1585  * last moment when possible.
1586  */
1587 int
1588 aac_start(struct aac_ccb *ccb)
1589 {
1590 	struct aac_softc *sc = ccb->ac_xs->sc_link->adapter_softc;
1591 
1592 #if 0
1593 	/* get the command mapped */
1594 	aac_map_command(ccb);
1595 #endif
1596 
1597 	/* fix up the address values */
1598 	ccb->ac_fib->Header.SenderFibAddress = (u_int32_t)ccb->ac_fib;
1599 	ccb->ac_fib->Header.ReceiverFibAddress = ccb->ac_fibphys;
1600 
1601 	/* save a pointer to the command for speedy reverse-lookup */
1602 	ccb->ac_fib->Header.SenderData = (u_int32_t)ccb; /* XXX ack, sizing */
1603 
1604 	/* put the FIB on the outbound queue */
1605 	if (aac_enqueue_fib(sc, AAC_ADAP_NORM_CMD_QUEUE,
1606 	    ccb->ac_fib->Header.Size, ccb->ac_fib->Header.ReceiverFibAddress))
1607 		return (EBUSY);
1608 
1609 	return (0);
1610 }
1611 
1612 /*
1613  * Map a command into controller-visible space.
1614  */
1615 int
1616 aac_map_command(struct aac_ccb *ccb)
1617 {
1618 	struct scsi_xfer *xs = ccb->ac_xs;
1619 	struct aac_softc *sc = xs->sc_link->adapter_softc;
1620 	int error;
1621 
1622 #if 0
1623 	/* don't map more than once */
1624 	if (ccb->ac_flags & AAC_CMD_MAPPED)
1625 		return;
1626 #endif
1627 
1628 	if (xs->datalen != 0) {
1629 		error = bus_dmamap_load(sc->sc_dmat, ccb->ac_dmamap_xfer,
1630 		    xs->data, xs->datalen, NULL,
1631 		    (xs->flags & SCSI_NOSLEEP) ? BUS_DMA_NOWAIT :
1632 		    BUS_DMA_WAITOK);
1633 		if (error) {
1634 			printf("%s: aac_scsi_cmd: ", sc->sc_dev.dv_xname);
1635 			if (error == EFBIG)
1636 				printf("more than %d dma segs\n",
1637 				    AAC_MAXSGENTRIES);
1638 			else
1639 				printf("error %d loading dma map\n", error);
1640 			return (error);
1641 		}
1642 
1643 		bus_dmamap_sync(sc->sc_dmat, ccb->ac_dmamap_xfer,
1644 		    (xs->flags & SCSI_DATA_IN) ? BUS_DMASYNC_PREREAD :
1645 		    BUS_DMASYNC_PREWRITE);
1646 	}
1647 
1648 #if 0
1649 	ccb->ac_flags |= AAC_CMD_MAPPED;
1650 #endif
1651 	return (0);
1652 }
1653 
1654 /*
1655  * Unmap a command from controller-visible space.
1656  */
1657 void
1658 aac_unmap_command(struct aac_ccb *ccb)
1659 {
1660 	struct scsi_xfer *xs = ccb->ac_xs;
1661 	struct aac_softc *sc = xs->sc_link->adapter_softc;
1662 
1663 #if 0
1664 	if (!(ccb->ac_flags & AAC_CMD_MAPPED))
1665 		return;
1666 #endif
1667 
1668 	if (xs->datalen != 0) {
1669 		bus_dmamap_sync(sc->sc_dmat, ccb->ac_dmamap_xfer,
1670 		    (xs->flags & SCSI_DATA_IN) ? BUS_DMASYNC_POSTREAD :
1671 		    BUS_DMASYNC_POSTWRITE);
1672 
1673 		bus_dmamap_unload(sc->sc_dmat, ccb->ac_dmamap_xfer);
1674 	}
1675 #if 0
1676 	ccb->ac_flags &= ~AAC_CMD_MAPPED;
1677 #endif
1678 }
1679 
1680 void
1681 aac_timeout(arg)
1682 	void *arg;
1683 {
1684 	struct aac_ccb *ccb = arg;
1685 	struct scsi_link *link = ccb->ac_xs->sc_link;
1686 	struct aac_softc *sc = link->adapter_softc;
1687 	aac_lock_t lock;
1688 
1689 	sc_print_addr(link);
1690 	printf("timed out\n");
1691 
1692 	/* XXX Test for multiple timeouts */
1693 
1694 	ccb->ac_xs->error = XS_TIMEOUT;
1695 	lock = AAC_LOCK(sc);
1696 	aac_enqueue_ccb(sc, ccb);
1697 	AAC_UNLOCK(sc, lock);
1698 }
1699 
1700 void
1701 aac_watchdog(arg)
1702 	void *arg;
1703 {
1704 	struct aac_ccb *ccb = arg;
1705 	struct scsi_link *link = ccb->ac_xs->sc_link;
1706 	struct aac_softc *sc = link->adapter_softc;
1707 	aac_lock_t lock;
1708 
1709 	lock = AAC_LOCK(sc);
1710 	ccb->ac_flags &= ~AAC_ACF_WATCHDOG;
1711 	aac_start_ccbs(sc);
1712 	AAC_UNLOCK(sc, lock);
1713 }
1714 /*
1715  * Insert a command into the driver queue, either at the front or at the tail.
1716  * It's ok to overload the freelist link as these structures are never on
1717  * the freelist at this time.
1718  */
1719 void
1720 aac_enqueue(sc, xs, infront)
1721 	struct aac_softc *sc;
1722 	struct scsi_xfer *xs;
1723 	int infront;
1724 {
1725 	if (infront || LIST_FIRST(&sc->sc_queue) == NULL) {
1726 		if (LIST_FIRST(&sc->sc_queue) == NULL)
1727 			sc->sc_queuelast = xs;
1728 		LIST_INSERT_HEAD(&sc->sc_queue, xs, free_list);
1729 		return;
1730 	}
1731 	LIST_INSERT_AFTER(sc->sc_queuelast, xs, free_list);
1732 	sc->sc_queuelast = xs;
1733 }
1734 
1735 /*
1736  * Pull a command off the front of the driver queue.
1737  */
1738 struct scsi_xfer *
1739 aac_dequeue(sc)
1740 	struct aac_softc *sc;
1741 {
1742 	struct scsi_xfer *xs;
1743 
1744 	xs = LIST_FIRST(&sc->sc_queue);
1745 	if (xs == NULL)
1746 		return (NULL);
1747 	LIST_REMOVE(xs, free_list);
1748 
1749 	if (LIST_FIRST(&sc->sc_queue) == NULL)
1750 		sc->sc_queuelast = NULL;
1751 
1752 	return (xs);
1753 }
1754 
1755 /********************************************************************************
1756  * Adapter-space FIB queue manipulation
1757  *
1758  * Note that the queue implementation here is a little funky; neither the PI or
1759  * CI will ever be zero.  This behaviour is a controller feature.
1760  */
1761 static struct {
1762 	int size;
1763 	int notify;
1764 } aac_qinfo[] = {
1765 	{ AAC_HOST_NORM_CMD_ENTRIES, AAC_DB_COMMAND_NOT_FULL },
1766 	{ AAC_HOST_HIGH_CMD_ENTRIES, 0 },
1767 	{ AAC_ADAP_NORM_CMD_ENTRIES, AAC_DB_COMMAND_READY },
1768 	{ AAC_ADAP_HIGH_CMD_ENTRIES, 0 },
1769 	{ AAC_HOST_NORM_RESP_ENTRIES, AAC_DB_RESPONSE_NOT_FULL },
1770 	{ AAC_HOST_HIGH_RESP_ENTRIES, 0 },
1771 	{ AAC_ADAP_NORM_RESP_ENTRIES, AAC_DB_RESPONSE_READY },
1772 	{ AAC_ADAP_HIGH_RESP_ENTRIES, 0 }
1773 };
1774 
1775 /*
1776  * Atomically insert an entry into the nominated queue, returns 0 on success
1777  * or EBUSY if the queue is full.
1778  *
1779  * XXX Note that it would be more efficient to defer notifying the controller
1780  * in the case where we may be inserting several entries in rapid succession,
1781  * but implementing this usefully is difficult.
1782  */
1783 int
1784 aac_enqueue_fib(struct aac_softc *sc, int queue, u_int32_t fib_size,
1785     u_int32_t fib_addr)
1786 {
1787 	u_int32_t pi, ci;
1788 	int error;
1789 	aac_lock_t lock;
1790 
1791 	lock = AAC_LOCK(sc);
1792 
1793 	/* get the producer/consumer indices */
1794 	pi = sc->sc_queues->qt_qindex[queue][AAC_PRODUCER_INDEX];
1795 	ci = sc->sc_queues->qt_qindex[queue][AAC_CONSUMER_INDEX];
1796 
1797 	/* wrap the queue? */
1798 	if (pi >= aac_qinfo[queue].size)
1799 		pi = 0;
1800 
1801 	/* check for queue full */
1802 	if ((pi + 1) == ci) {
1803 		error = EBUSY;
1804 		goto out;
1805 	}
1806 
1807 	/* populate queue entry */
1808 	(sc->sc_qentries[queue] + pi)->aq_fib_size = fib_size;
1809 	(sc->sc_qentries[queue] + pi)->aq_fib_addr = fib_addr;
1810 
1811 	/* update producer index */
1812 	sc->sc_queues->qt_qindex[queue][AAC_PRODUCER_INDEX] = pi + 1;
1813 
1814 	/* notify the adapter if we know how */
1815 	if (aac_qinfo[queue].notify != 0)
1816 		AAC_QNOTIFY(sc, aac_qinfo[queue].notify);
1817 
1818 	error = 0;
1819 
1820 out:
1821 	AAC_UNLOCK(sc, lock);
1822 	return (error);
1823 }
1824 
1825 /*
1826  * Atomically remove one entry from the nominated queue, returns 0 on success
1827  * or ENOENT if the queue is empty.
1828  */
1829 int
1830 aac_dequeue_fib(struct aac_softc *sc, int queue, u_int32_t *fib_size,
1831     struct aac_fib **fib_addr)
1832 {
1833 	u_int32_t pi, ci;
1834 	int error;
1835 	aac_lock_t lock;
1836 
1837 	lock = AAC_LOCK(sc);
1838 
1839 	/* get the producer/consumer indices */
1840 	pi = sc->sc_queues->qt_qindex[queue][AAC_PRODUCER_INDEX];
1841 	ci = sc->sc_queues->qt_qindex[queue][AAC_CONSUMER_INDEX];
1842 
1843 	/* check for queue empty */
1844 	if (ci == pi) {
1845 		error = ENOENT;
1846 		goto out;
1847 	}
1848 
1849 	/* wrap the queue? */
1850 	if (ci >= aac_qinfo[queue].size)
1851 		ci = 0;
1852 
1853 	/* fetch the entry */
1854 	*fib_size = (sc->sc_qentries[queue] + ci)->aq_fib_size;
1855 	*fib_addr =
1856 	    (struct aac_fib *)(sc->sc_qentries[queue] + ci)->aq_fib_addr;
1857 
1858 	/* update consumer index */
1859 	sc->sc_queues->qt_qindex[queue][AAC_CONSUMER_INDEX] = ci + 1;
1860 
1861 	/* if we have made the queue un-full, notify the adapter */
1862 	if (((pi + 1) == ci) && (aac_qinfo[queue].notify != 0))
1863 		AAC_QNOTIFY(sc, aac_qinfo[queue].notify);
1864 	error = 0;
1865 
1866 out:
1867 	AAC_UNLOCK(sc, lock);
1868 	return (error);
1869 }
1870 
1871 #ifdef AAC_DEBUG
1872 /*
1873  * Print a FIB
1874  */
1875 void
1876 aac_print_fib(struct aac_softc *sc, struct aac_fib *fib, char *caller)
1877 {
1878 	printf("%s: FIB @ %p\n", caller, fib);
1879 	printf("  XferState %b\n", fib->Header.XferState, "\20"
1880 	    "\1HOSTOWNED"
1881 	    "\2ADAPTEROWNED"
1882 	    "\3INITIALISED"
1883 	    "\4EMPTY"
1884 	    "\5FROMPOOL"
1885 	    "\6FROMHOST"
1886 	    "\7FROMADAP"
1887 	    "\10REXPECTED"
1888 	    "\11RNOTEXPECTED"
1889 	    "\12DONEADAP"
1890 	    "\13DONEHOST"
1891 	    "\14HIGH"
1892 	    "\15NORM"
1893 	    "\16ASYNC"
1894 	    "\17PAGEFILEIO"
1895 	    "\20SHUTDOWN"
1896 	    "\21LAZYWRITE"
1897 	    "\22ADAPMICROFIB"
1898 	    "\23BIOSFIB"
1899 	    "\24FAST_RESPONSE"
1900 	    "\25APIFIB\n");
1901 	printf("  Command         %d\n", fib->Header.Command);
1902 	printf("  StructType      %d\n", fib->Header.StructType);
1903 	printf("  Flags           0x%x\n", fib->Header.Flags);
1904 	printf("  Size            %d\n", fib->Header.Size);
1905 	printf("  SenderSize      %d\n", fib->Header.SenderSize);
1906 	printf("  SenderAddress   0x%x\n", fib->Header.SenderFibAddress);
1907 	printf("  ReceiverAddress 0x%x\n", fib->Header.ReceiverFibAddress);
1908 	printf("  SenderData      0x%x\n", fib->Header.SenderData);
1909 	switch(fib->Header.Command) {
1910 	case ContainerCommand: {
1911 		struct aac_blockread *br = (struct aac_blockread *)fib->data;
1912 		struct aac_blockwrite *bw = (struct aac_blockwrite *)fib->data;
1913 		struct aac_sg_table *sg = NULL;
1914 		int i;
1915 
1916 		if (br->Command == VM_CtBlockRead) {
1917 			printf("  BlockRead: container %d  0x%x/%d\n",
1918 			    br->ContainerId, br->BlockNumber, br->ByteCount);
1919 			    sg = &br->SgMap;
1920 		}
1921 		if (bw->Command == VM_CtBlockWrite) {
1922 			printf("  BlockWrite: container %d  0x%x/%d (%s)\n",
1923 			    bw->ContainerId, bw->BlockNumber, bw->ByteCount,
1924 			    bw->Stable == CSTABLE ? "stable" : "unstable");
1925 			sg = &bw->SgMap;
1926 		}
1927 		if (sg != NULL) {
1928 			printf("  %d s/g entries\n", sg->SgCount);
1929 			for (i = 0; i < sg->SgCount; i++)
1930 				printf("  0x%08x/%d\n",
1931 				       sg->SgEntry[i].SgAddress,
1932 				       sg->SgEntry[i].SgByteCount);
1933 		}
1934 		break;
1935 	}
1936 	default:
1937 		printf("   %16D\n", fib->data, " ");
1938 		printf("   %16D\n", fib->data + 16, " ");
1939 	break;
1940 	}
1941 }
1942 #endif
1943