xref: /openbsd-src/sys/dev/ic/aac.c (revision 50b7afb2c2c0993b0894d4e34bf857cb13ed9c80)
1 /*	$OpenBSD: aac.c,v 1.64 2014/07/12 18:48:17 tedu Exp $	*/
2 
3 /*-
4  * Copyright (c) 2000 Michael Smith
5  * Copyright (c) 2001 Scott Long
6  * Copyright (c) 2000 BSDi
7  * Copyright (c) 2001 Adaptec, Inc.
8  * Copyright (c) 2000 Niklas Hallqvist
9  * Copyright (c) 2004 Nathan Binkert
10  * All rights reserved.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions and the following disclaimer.
17  * 2. Redistributions in binary form must reproduce the above copyright
18  *    notice, this list of conditions and the following disclaimer in the
19  *    documentation and/or other materials provided with the distribution.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  *
33  *	$FreeBSD: /c/ncvs/src/sys/dev/aac/aac.c,v 1.1 2000/09/13 03:20:34 msmith Exp $
34  */
35 
36 /*
37  * Driver for the Adaptec 'FSA' family of PCI/SCSI RAID adapters.
38  */
39 
40 /*
41  * This driver would not have rewritten for OpenBSD if it was not for the
42  * hardware donation from Nocom.  I want to thank them for their support.
43  * Of course, credit should go to Mike Smith for the original work he did
44  * in the FreeBSD driver where I found lots of reusable code and inspiration.
45  * - Niklas Hallqvist
46  */
47 
48 #include <sys/param.h>
49 #include <sys/systm.h>
50 #include <sys/buf.h>
51 #include <sys/device.h>
52 #include <sys/kernel.h>
53 #include <sys/kthread.h>
54 #include <sys/malloc.h>
55 #include <sys/rwlock.h>
56 #include <sys/time.h>
57 
58 #include <machine/bus.h>
59 
60 #include <scsi/scsi_all.h>
61 #include <scsi/scsi_disk.h>
62 #include <scsi/scsiconf.h>
63 
64 #include <dev/ic/aacreg.h>
65 #include <dev/ic/aacvar.h>
66 #include <dev/ic/aac_tables.h>
67 
68 /* Geometry constants. */
69 #define AAC_MAXCYLS		1024
70 #define AAC_HEADS		64
71 #define AAC_SECS		32	/* mapping 64*32 */
72 #define AAC_MEDHEADS		127
73 #define AAC_MEDSECS		63	/* mapping 127*63 */
74 #define AAC_BIGHEADS		255
75 #define AAC_BIGSECS		63	/* mapping 255*63 */
76 #define AAC_SECS32		0x1f	/* round capacity */
77 
78 struct scsi_xfer;
79 
80 void	aac_copy_internal_data(struct scsi_xfer *, u_int8_t *, size_t);
81 char   *aac_describe_code(struct aac_code_lookup *, u_int32_t);
82 void	aac_describe_controller(struct aac_softc *);
83 int	aac_enqueue_fib(struct aac_softc *, int, struct aac_command *);
84 int	aac_dequeue_fib(struct aac_softc *, int, u_int32_t *,
85 			struct aac_fib **);
86 int	aac_enqueue_response(struct aac_softc *sc, int queue,
87 			     struct aac_fib *fib);
88 
89 void	aac_eval_mapping(u_int32_t, int *, int *, int *);
90 void	aac_print_printf(struct aac_softc *);
91 int	aac_init(struct aac_softc *);
92 int	aac_check_firmware(struct aac_softc *);
93 void	aac_internal_cache_cmd(struct scsi_xfer *);
94 
95 /* Command Processing */
96 void	aac_timeout(struct aac_softc *);
97 void	aac_command_timeout(struct aac_command *);
98 int	aac_map_command(struct aac_command *);
99 void	aac_complete(void *);
100 int	aac_bio_command(struct aac_softc *, struct aac_command **);
101 void	aac_bio_complete(struct aac_command *);
102 int	aac_wait_command(struct aac_command *, int);
103 void	aac_create_thread(void *);
104 void	aac_command_thread(void *);
105 
106 /* Command Buffer Management */
107 void	aac_map_command_sg(void *, bus_dma_segment_t *, int, int);
108 int	aac_alloc_commands(struct aac_softc *);
109 void	aac_free_commands(struct aac_softc *);
110 void	aac_unmap_command(struct aac_command *);
111 int	aac_wait_command(struct aac_command *, int);
112 void *	aac_alloc_command(void *);
113 void	aac_scrub_command(struct aac_command *);
114 void	aac_release_command(void *, void *);
115 int	aac_alloc_sync_fib(struct aac_softc *, struct aac_fib **, int);
116 void	aac_release_sync_fib(struct aac_softc *);
117 int	aac_sync_fib(struct aac_softc *, u_int32_t, u_int32_t,
118 	    struct aac_fib *, u_int16_t);
119 
120 void	aac_scsi_cmd(struct scsi_xfer *);
121 void	aac_startio(struct aac_softc *);
122 void	aac_startup(struct aac_softc *);
123 void	aac_add_container(struct aac_softc *, struct aac_mntinforesp *, int);
124 void	aac_shutdown(void *);
125 int	aac_sync_command(struct aac_softc *, u_int32_t, u_int32_t,
126     u_int32_t, u_int32_t, u_int32_t, u_int32_t *);
127 
128 struct cfdriver aac_cd = {
129 	NULL, "aac", DV_DULL
130 };
131 
132 struct scsi_adapter aac_switch = {
133 	aac_scsi_cmd,
134 	scsi_minphys,
135 	NULL,		/* probe */
136 	NULL,		/* free */
137 	NULL		/* ioctl */
138 };
139 
140 /* Falcon/PPC interface */
141 int	aac_fa_get_fwstatus(struct aac_softc *);
142 void	aac_fa_qnotify(struct aac_softc *, int);
143 int	aac_fa_get_istatus(struct aac_softc *);
144 void	aac_fa_clear_istatus(struct aac_softc *, int);
145 void	aac_fa_set_mailbox(struct aac_softc *, u_int32_t, u_int32_t, u_int32_t,
146 			   u_int32_t, u_int32_t);
147 int	aac_fa_get_mailbox(struct aac_softc *, int);
148 void	aac_fa_set_interrupts(struct aac_softc *, int);
149 
150 struct aac_interface aac_fa_interface = {
151 	aac_fa_get_fwstatus,
152 	aac_fa_qnotify,
153 	aac_fa_get_istatus,
154 	aac_fa_clear_istatus,
155 	aac_fa_set_mailbox,
156 	aac_fa_get_mailbox,
157 	aac_fa_set_interrupts
158 };
159 
160 /* StrongARM interface */
161 int	aac_sa_get_fwstatus(struct aac_softc *);
162 void	aac_sa_qnotify(struct aac_softc *, int);
163 int	aac_sa_get_istatus(struct aac_softc *);
164 void	aac_sa_clear_istatus(struct aac_softc *, int);
165 void	aac_sa_set_mailbox(struct aac_softc *, u_int32_t, u_int32_t,
166     u_int32_t, u_int32_t, u_int32_t);
167 int	aac_sa_get_mailbox(struct aac_softc *, int);
168 void	aac_sa_set_interrupts(struct aac_softc *, int);
169 
170 struct aac_interface aac_sa_interface = {
171 	aac_sa_get_fwstatus,
172 	aac_sa_qnotify,
173 	aac_sa_get_istatus,
174 	aac_sa_clear_istatus,
175 	aac_sa_set_mailbox,
176 	aac_sa_get_mailbox,
177 	aac_sa_set_interrupts
178 };
179 
180 /* i960Rx interface */
181 int	aac_rx_get_fwstatus(struct aac_softc *);
182 void	aac_rx_qnotify(struct aac_softc *, int);
183 int	aac_rx_get_istatus(struct aac_softc *);
184 void	aac_rx_clear_istatus(struct aac_softc *, int);
185 void	aac_rx_set_mailbox(struct aac_softc *, u_int32_t, u_int32_t,
186     u_int32_t, u_int32_t, u_int32_t);
187 int	aac_rx_get_mailbox(struct aac_softc *, int);
188 void	aac_rx_set_interrupts(struct aac_softc *, int);
189 
190 struct aac_interface aac_rx_interface = {
191 	aac_rx_get_fwstatus,
192 	aac_rx_qnotify,
193 	aac_rx_get_istatus,
194 	aac_rx_clear_istatus,
195 	aac_rx_set_mailbox,
196 	aac_rx_get_mailbox,
197 	aac_rx_set_interrupts
198 };
199 
200 /* Rocket/MIPS interface */
201 int	aac_rkt_get_fwstatus(struct aac_softc *);
202 void	aac_rkt_qnotify(struct aac_softc *, int);
203 int	aac_rkt_get_istatus(struct aac_softc *);
204 void	aac_rkt_clear_istatus(struct aac_softc *, int);
205 void	aac_rkt_set_mailbox(struct aac_softc *, u_int32_t,
206 				    u_int32_t, u_int32_t,
207 				    u_int32_t, u_int32_t);
208 int	aac_rkt_get_mailbox(struct aac_softc *, int);
209 void	aac_rkt_set_interrupts(struct aac_softc *, int);
210 
211 struct aac_interface aac_rkt_interface = {
212 	aac_rkt_get_fwstatus,
213 	aac_rkt_qnotify,
214 	aac_rkt_get_istatus,
215 	aac_rkt_clear_istatus,
216 	aac_rkt_set_mailbox,
217 	aac_rkt_get_mailbox,
218 	aac_rkt_set_interrupts
219 };
220 
221 #ifdef AAC_DEBUG
222 int	aac_debug = AAC_DEBUG;
223 #endif
224 
225 int
226 aac_attach(struct aac_softc *sc)
227 {
228 	struct scsibus_attach_args saa;
229 	int error;
230 
231 	/*
232 	 * Initialise per-controller queues.
233 	 */
234 	mtx_init(&sc->aac_free_mtx, IPL_BIO);
235 	aac_initq_free(sc);
236 	aac_initq_ready(sc);
237 	aac_initq_busy(sc);
238 	aac_initq_bio(sc);
239 
240 	/* disable interrupts before we enable anything */
241 	AAC_MASK_INTERRUPTS(sc);
242 
243 	/* mark controller as suspended until we get ourselves organised */
244 	sc->aac_state |= AAC_STATE_SUSPEND;
245 
246 	/*
247 	 * Check that the firmware on the card is supported.
248 	 */
249 	error = aac_check_firmware(sc);
250 	if (error)
251 		return (error);
252 
253 	/*
254 	 * Initialize locks
255 	 */
256 	AAC_LOCK_INIT(&sc->aac_sync_lock, "AAC sync FIB lock");
257 	AAC_LOCK_INIT(&sc->aac_aifq_lock, "AAC AIF lock");
258 	AAC_LOCK_INIT(&sc->aac_io_lock, "AAC I/O lock");
259 	AAC_LOCK_INIT(&sc->aac_container_lock, "AAC container lock");
260 	TAILQ_INIT(&sc->aac_container_tqh);
261 
262 	/* Initialize the local AIF queue pointers */
263 	sc->aac_aifq_head = sc->aac_aifq_tail = AAC_AIFQ_LENGTH;
264 
265 	/*
266 	 * Initialise the adapter.
267 	 */
268 	error = aac_init(sc);
269 	if (error)
270 		return (error);
271 
272 	/* Fill in the prototype scsi_link. */
273 	sc->aac_link.adapter_softc = sc;
274 	sc->aac_link.adapter = &aac_switch;
275 	sc->aac_link.openings = (sc->total_fibs - 8) /
276 	    (sc->aac_container_count ? sc->aac_container_count : 1);
277 	sc->aac_link.adapter_buswidth = AAC_MAX_CONTAINERS;
278 	sc->aac_link.adapter_target = AAC_MAX_CONTAINERS;
279 	sc->aac_link.pool = &sc->aac_iopool;
280 
281 	bzero(&saa, sizeof(saa));
282 	saa.saa_sc_link = &sc->aac_link;
283 
284 	config_found(&sc->aac_dev, &saa, scsiprint);
285 
286 	/* Create the AIF thread */
287 	sc->aifthread = 0;
288 	sc->aifflags = 0;
289 	kthread_create_deferred(aac_create_thread, sc);
290 
291 	return (0);
292 }
293 
294 void
295 aac_create_thread(void *arg)
296 {
297 	struct aac_softc *sc = arg;
298 
299 	if (kthread_create(aac_command_thread, sc, &sc->aifthread,
300 	    sc->aac_dev.dv_xname)) {
301 		/* TODO disable aac */
302 		printf("%s: failed to create kernel thread, disabled",
303 		sc->aac_dev.dv_xname);
304 	}
305 	AAC_DPRINTF(AAC_D_MISC, ("%s: aac_create_thread\n",
306 	    sc->aac_dev.dv_xname));
307 
308 }
309 
310 /*
311  * Probe for containers, create disks.
312  */
313 void
314 aac_startup(struct aac_softc *sc)
315 {
316 	struct aac_fib *fib;
317 	struct aac_mntinfo *mi;
318 	struct aac_mntinforesp *mir = NULL;
319 	int count = 0, i = 0;
320 
321 
322 	aac_alloc_sync_fib(sc, &fib, 0);
323 	mi = (struct aac_mntinfo *)&fib->data[0];
324 
325 	AAC_DPRINTF(AAC_D_MISC, ("%s: aac startup\n", sc->aac_dev.dv_xname));
326 
327 	sc->aac_container_count = 0;
328 	/* loop over possible containers */
329 	do {
330 		/* request information on this container */
331 		bzero(mi, sizeof(struct aac_mntinfo));
332 		mi->Command = VM_NameServe;
333 		mi->MntType = FT_FILESYS;
334 		mi->MntCount = i;
335 		if (aac_sync_fib(sc, ContainerCommand, 0, fib,
336 				 sizeof(struct aac_mntinfo))) {
337 			printf("%s: error probing container %d\n",
338 			       sc->aac_dev.dv_xname, i);
339 			continue;
340 		}
341 
342 		mir = (struct aac_mntinforesp *)&fib->data[0];
343 		/* XXX Need to check if count changed */
344 		count = mir->MntRespCount;
345 
346 #if 0
347 		aac_add_container(sc, mir, 0);
348 #else
349 		/*
350 		 * Check container volume type for validity.  Note
351 		 * that many of the possible types may never show up.
352 		 */
353 		if (mir->Status == ST_OK &&
354 		    mir->MntTable[0].VolType != CT_NONE) {
355 			int drv_cyls, drv_hds, drv_secs;
356 
357 			AAC_DPRINTF(AAC_D_MISC,
358 			    ("%s: %d: id %x  name '%.16s'  size %u  type %d\n",
359 			     sc->aac_dev.dv_xname, i,
360 			     mir->MntTable[0].ObjectId,
361 			     mir->MntTable[0].FileSystemName,
362 			     mir->MntTable[0].Capacity,
363 			     mir->MntTable[0].VolType));
364 
365 			sc->aac_container_count++;
366 			sc->aac_hdr[i].hd_present = 1;
367 			sc->aac_hdr[i].hd_size = mir->MntTable[0].Capacity;
368 
369 			/*
370 			 * Evaluate mapping (sectors per head, heads per cyl)
371 			 */
372 			sc->aac_hdr[i].hd_size &= ~AAC_SECS32;
373 			aac_eval_mapping(sc->aac_hdr[i].hd_size, &drv_cyls,
374 					 &drv_hds, &drv_secs);
375 			sc->aac_hdr[i].hd_heads = drv_hds;
376 			sc->aac_hdr[i].hd_secs = drv_secs;
377 			/* Round the size */
378 			sc->aac_hdr[i].hd_size = drv_cyls * drv_hds * drv_secs;
379 
380 			sc->aac_hdr[i].hd_devtype = mir->MntTable[0].VolType;
381 
382 			/* XXX Save the name too for use in IDENTIFY later */
383 		}
384 #endif
385 
386 		i++;
387 	} while ((i < count) && (i < AAC_MAX_CONTAINERS));
388 
389 	aac_release_sync_fib(sc);
390 
391 #if 0
392 	/* poke the bus to actually attach the child devices */
393 	if (bus_generic_attach(sc->aac_dev))
394 		printf("%s: bus_generic_attach failed\n",
395 		       sc->aac_dev.dv_xname);
396 #endif
397 
398 
399 	/* mark the controller up */
400 	sc->aac_state &= ~AAC_STATE_SUSPEND;
401 
402 	/* enable interrupts now */
403 	AAC_UNMASK_INTERRUPTS(sc);
404 }
405 
406 #if 0
407 /*
408  * Create a device to respresent a new container
409  */
410 void
411 aac_add_container(struct aac_softc *sc, struct aac_mntinforesp *mir, int f)
412 {
413 	struct aac_container *co;
414 	device_t child;
415 
416 	/*
417 	 * Check container volume type for validity.  Note that many of
418 	 * the possible types may never show up.
419 	 */
420 	if ((mir->Status == ST_OK) && (mir->MntTable[0].VolType != CT_NONE)) {
421 		co = (struct aac_container *)malloc(sizeof *co, M_DEVBUF,
422 		       M_NOWAIT);
423 		if (co == NULL)
424 			panic("Out of memory?!");
425 		bzero(co, sizeof *co);
426 		AAC_DPRINTF(AAC_D_MISC,
427 			    ("%s: id %x  name '%.16s'  size %u  type %d\n",
428 			     sc->aac_dev.dv_xname,
429 			     mir->MntTable[0].ObjectId,
430 			     mir->MntTable[0].FileSystemName,
431 			     mir->MntTable[0].Capacity,
432 			     mir->MntTable[0].VolType);
433 
434 		if ((child = device_add_child(sc->aac_dev, "aacd", -1)) == NULL)
435 			printf("%s: device_add_child failed\n",
436 			       sc->aac_dev.dv_xname);
437 		else
438 			device_set_ivars(child, co);
439 		device_set_desc(child, aac_describe_code(aac_container_types,
440 				mir->MntTable[0].VolType));
441 		co->co_disk = child;
442 		co->co_found = f;
443 		bcopy(&mir->MntTable[0], &co->co_mntobj,
444 		      sizeof(struct aac_mntobj));
445 		AAC_LOCK_ACQUIRE(&sc->aac_container_lock);
446 		TAILQ_INSERT_TAIL(&sc->aac_container_tqh, co, co_link);
447 		AAC_LOCK_RELEASE(&sc->aac_container_lock);
448 	}
449 }
450 #endif
451 
452 #if 0
453 /*
454  * Free all of the resources associated with (sc)
455  *
456  * Should not be called if the controller is active.
457  */
458 void
459 aac_free(struct aac_softc *sc)
460 {
461 
462 	debug_called(1);
463 
464 	/* remove the control device */
465 	if (sc->aac_dev_t != NULL)
466 		destroy_dev(sc->aac_dev_t);
467 
468 	/* throw away any FIB buffers, discard the FIB DMA tag */
469 	aac_free_commands(sc);
470 	if (sc->aac_fib_dmat)
471 		bus_dma_tag_destroy(sc->aac_fib_dmat);
472 
473 	free(sc->aac_commands, M_AACBUF, 0);
474 
475 	/* destroy the common area */
476 	if (sc->aac_common) {
477 		bus_dmamap_unload(sc->aac_common_dmat, sc->aac_common_dmamap);
478 		bus_dmamem_free(sc->aac_common_dmat, sc->aac_common,
479 				sc->aac_common_dmamap);
480 	}
481 	if (sc->aac_common_dmat)
482 		bus_dma_tag_destroy(sc->aac_common_dmat);
483 
484 	/* disconnect the interrupt handler */
485 	if (sc->aac_intr)
486 		bus_teardown_intr(sc->aac_dev, sc->aac_irq, sc->aac_intr);
487 	if (sc->aac_irq != NULL)
488 		bus_release_resource(sc->aac_dev, SYS_RES_IRQ, sc->aac_irq_rid,
489 				     sc->aac_irq);
490 
491 	/* destroy data-transfer DMA tag */
492 	if (sc->aac_buffer_dmat)
493 		bus_dma_tag_destroy(sc->aac_buffer_dmat);
494 
495 	/* destroy the parent DMA tag */
496 	if (sc->aac_parent_dmat)
497 		bus_dma_tag_destroy(sc->aac_parent_dmat);
498 
499 	/* release the register window mapping */
500 	if (sc->aac_regs_resource != NULL)
501 		bus_release_resource(sc->aac_dev, SYS_RES_MEMORY,
502 				     sc->aac_regs_rid, sc->aac_regs_resource);
503 }
504 
505 /*
506  * Disconnect from the controller completely, in preparation for unload.
507  */
508 int
509 aac_detach(device_t dev)
510 {
511 	struct aac_softc *sc;
512 	struct aac_container *co;
513 	struct aac_sim	*sim;
514 	int error;
515 
516 	debug_called(1);
517 
518 	sc = device_get_softc(dev);
519 
520 	if (sc->aac_state & AAC_STATE_OPEN)
521 		return(EBUSY);
522 
523 	/* Remove the child containers */
524 	while ((co = TAILQ_FIRST(&sc->aac_container_tqh)) != NULL) {
525 		error = device_delete_child(dev, co->co_disk);
526 		if (error)
527 			return (error);
528 		TAILQ_REMOVE(&sc->aac_container_tqh, co, co_link);
529 		free(co, M_AACBUF, 0);
530 	}
531 
532 	/* Remove the CAM SIMs */
533 	while ((sim = TAILQ_FIRST(&sc->aac_sim_tqh)) != NULL) {
534 		TAILQ_REMOVE(&sc->aac_sim_tqh, sim, sim_link);
535 		error = device_delete_child(dev, sim->sim_dev);
536 		if (error)
537 			return (error);
538 		free(sim, M_AACBUF, 0);
539 	}
540 
541 	if (sc->aifflags & AAC_AIFFLAGS_RUNNING) {
542 		sc->aifflags |= AAC_AIFFLAGS_EXIT;
543 		wakeup(sc->aifthread);
544 		tsleep(sc->aac_dev, PUSER | PCATCH, "aacdch", 30 * hz);
545 	}
546 
547 	if (sc->aifflags & AAC_AIFFLAGS_RUNNING)
548 		panic("Cannot shutdown AIF thread");
549 
550 	if ((error = aac_shutdown(dev)))
551 		return(error);
552 
553 	EVENTHANDLER_DEREGISTER(shutdown_final, sc->eh);
554 
555 	aac_free(sc);
556 
557 	return(0);
558 }
559 
560 /*
561  * Bring the controller down to a dormant state and detach all child devices.
562  *
563  * This function is called before detach or system shutdown.
564  *
565  * Note that we can assume that the bioq on the controller is empty, as we won't
566  * allow shutdown if any device is open.
567  */
568 int
569 aac_shutdown(device_t dev)
570 {
571 	struct aac_softc *sc;
572 	struct aac_fib *fib;
573 	struct aac_close_command *cc;
574 
575 	debug_called(1);
576 
577 	sc = device_get_softc(dev);
578 
579 	sc->aac_state |= AAC_STATE_SUSPEND;
580 
581 	/*
582 	 * Send a Container shutdown followed by a HostShutdown FIB to the
583 	 * controller to convince it that we don't want to talk to it anymore.
584 	 * We've been closed and all I/O completed already
585 	 */
586 	device_printf(sc->aac_dev, "shutting down controller...");
587 
588 	aac_alloc_sync_fib(sc, &fib, AAC_SYNC_LOCK_FORCE);
589 	cc = (struct aac_close_command *)&fib->data[0];
590 
591 	bzero(cc, sizeof(struct aac_close_command));
592 	cc->Command = VM_CloseAll;
593 	cc->ContainerId = 0xffffffff;
594 	if (aac_sync_fib(sc, ContainerCommand, 0, fib,
595 	    sizeof(struct aac_close_command)))
596 		printf("FAILED.\n");
597 	else
598 		printf("done\n");
599 	else {
600 		fib->data[0] = 0;
601 		/*
602 		 * XXX Issuing this command to the controller makes it
603 		 * shut down but also keeps it from coming back up
604 		 * without a reset of the PCI bus.  This is not
605 		 * desirable if you are just unloading the driver
606 		 * module with the intent to reload it later.
607 		 */
608 		if (aac_sync_fib(sc, FsaHostShutdown, AAC_FIBSTATE_SHUTDOWN,
609 		    fib, 1)) {
610 			printf("FAILED.\n");
611 		} else {
612 			printf("done.\n");
613 		}
614 	}
615 
616 	AAC_MASK_INTERRUPTS(sc);
617 
618 	return(0);
619 }
620 
621 /*
622  * Bring the controller to a quiescent state, ready for system suspend.
623  */
624 int
625 aac_suspend(device_t dev)
626 {
627 	struct aac_softc *sc;
628 
629 	debug_called(1);
630 
631 	sc = device_get_softc(dev);
632 
633 	sc->aac_state |= AAC_STATE_SUSPEND;
634 
635 	AAC_MASK_INTERRUPTS(sc);
636 	return(0);
637 }
638 
639 /*
640  * Bring the controller back to a state ready for operation.
641  */
642 int
643 aac_resume(device_t dev)
644 {
645 	struct aac_softc *sc;
646 
647 	debug_called(1);
648 
649 	sc = device_get_softc(dev);
650 
651 	sc->aac_state &= ~AAC_STATE_SUSPEND;
652 	AAC_UNMASK_INTERRUPTS(sc);
653 	return(0);
654 }
655 #endif
656 
657 /*
658  * Take an interrupt.
659  */
660 int
661 aac_intr(void *arg)
662 {
663 	struct aac_softc *sc = arg;
664 	u_int16_t reason;
665 
666 
667 	/*
668 	 * Read the status register directly.  This is faster than taking the
669 	 * driver lock and reading the queues directly.  It also saves having
670 	 * to turn parts of the driver lock into a spin mutex, which would be
671 	 * ugly.
672 	 */
673 	reason = AAC_GET_ISTATUS(sc);
674 	AAC_CLEAR_ISTATUS(sc, reason);
675 	(void)AAC_GET_ISTATUS(sc);
676 
677 	if (reason == 0)
678 		return (0);
679 
680 	AAC_DPRINTF(AAC_D_INTR, ("%s: intr: sc=%p: reason=%#x\n",
681 				 sc->aac_dev.dv_xname, sc, reason));
682 
683 	/* controller wants to talk to us */
684 	if (reason & (AAC_DB_PRINTF | AAC_DB_COMMAND_READY |
685 		      AAC_DB_RESPONSE_READY)) {
686 
687 		if (reason & AAC_DB_RESPONSE_READY) {
688 			/* handle completion processing */
689 			if (sc->aifflags & AAC_AIFFLAGS_RUNNING) {
690 				sc->aifflags |= AAC_AIFFLAGS_COMPLETE;
691 			} else {
692 				AAC_LOCK_ACQUIRE(&sc->aac_io_lock);
693 				aac_complete(sc);
694 				AAC_LOCK_RELEASE(&sc->aac_io_lock);
695 			}
696 		}
697 
698 
699 		/*
700 		 * XXX Make sure that we don't get fooled by strange messages
701 		 * that start with a NULL.
702 		 */
703 		if (reason & AAC_DB_PRINTF)
704 			if (sc->aac_common->ac_printf[0] == 0)
705 				sc->aac_common->ac_printf[0] = 32;
706 
707 		/*
708 		 * This might miss doing the actual wakeup.  However, the
709 		 * msleep that this is waking up has a timeout, so it will
710 		 * wake up eventually.  AIFs and printfs are low enough
711 		 * priority that they can handle hanging out for a few seconds
712 		 * if needed.
713 		 */
714 		if (sc->aifthread)
715 			wakeup(sc->aifthread);
716 
717 	}
718 
719 	return (1);
720 }
721 
722 /*
723  * Command Processing
724  */
725 
726 /*
727  * Start as much queued I/O as possible on the controller
728  */
729 void
730 aac_startio(struct aac_softc *sc)
731 {
732 	struct aac_command *cm;
733 
734 	AAC_DPRINTF(AAC_D_CMD, ("%s: start command", sc->aac_dev.dv_xname));
735 
736 	if (sc->flags & AAC_QUEUE_FRZN) {
737 		AAC_DPRINTF(AAC_D_CMD, (": queue frozen"));
738 		return;
739 	}
740 
741 	AAC_DPRINTF(AAC_D_CMD, ("\n"));
742 
743 	for (;;) {
744 		/*
745 		 * Try to get a command that's been put off for lack of
746 		 * resources
747 		 */
748 		cm = aac_dequeue_ready(sc);
749 
750 		/*
751 		 * Try to build a command off the bio queue (ignore error
752 		 * return)
753 		 */
754 		if (cm == NULL) {
755 			AAC_DPRINTF(AAC_D_CMD, ("\n"));
756 			aac_bio_command(sc, &cm);
757 			AAC_DPRINTF(AAC_D_CMD, ("%s: start done bio",
758 						sc->aac_dev.dv_xname));
759 		}
760 
761 		/* nothing to do? */
762 		if (cm == NULL)
763 			break;
764 
765 		/*
766 		 * Try to give the command to the controller.  Any error is
767 		 * catastrophic since it means that bus_dmamap_load() failed.
768 		 */
769 		if (aac_map_command(cm) != 0)
770 			panic("aac: error mapping command %p", cm);
771 
772 		AAC_DPRINTF(AAC_D_CMD, ("\n%s: another command",
773 					sc->aac_dev.dv_xname));
774 	}
775 
776 	AAC_DPRINTF(AAC_D_CMD, ("\n"));
777 }
778 
779 /*
780  * Deliver a command to the controller; allocate controller resources at the
781  * last moment when possible.
782  */
783 int
784 aac_map_command(struct aac_command *cm)
785 {
786 	struct aac_softc *sc = cm->cm_sc;
787 	int error = 0;
788 
789 	AAC_DPRINTF(AAC_D_CMD, (": map command"));
790 
791 	/* don't map more than once */
792 	if (cm->cm_flags & AAC_CMD_MAPPED)
793 		panic("aac: command %p already mapped", cm);
794 
795 	if (cm->cm_datalen != 0) {
796 		error = bus_dmamap_load(sc->aac_dmat, cm->cm_datamap,
797 					cm->cm_data, cm->cm_datalen, NULL,
798 					BUS_DMA_NOWAIT);
799 		if (error)
800 			return (error);
801 
802 		aac_map_command_sg(cm, cm->cm_datamap->dm_segs,
803 				   cm->cm_datamap->dm_nsegs, 0);
804 	} else {
805 		aac_map_command_sg(cm, NULL, 0, 0);
806 	}
807 
808 	return (error);
809 }
810 
811 /*
812  * Handle notification of one or more FIBs coming from the controller.
813  */
814 void
815 aac_command_thread(void *arg)
816 {
817 	struct aac_softc *sc = arg;
818 	struct aac_fib *fib;
819 	u_int32_t fib_size;
820 	int size, retval;
821 
822 	AAC_DPRINTF(AAC_D_THREAD, ("%s: aac_command_thread: starting\n",
823 	    sc->aac_dev.dv_xname));
824 	AAC_LOCK_ACQUIRE(&sc->aac_io_lock);
825 	sc->aifflags = AAC_AIFFLAGS_RUNNING;
826 
827 	while ((sc->aifflags & AAC_AIFFLAGS_EXIT) == 0) {
828 
829 		AAC_DPRINTF(AAC_D_THREAD,
830 		    ("%s: aac_command_thread: aifflags=%#x\n",
831 		    sc->aac_dev.dv_xname, sc->aifflags));
832 		retval = 0;
833 
834 		if ((sc->aifflags & AAC_AIFFLAGS_PENDING) == 0) {
835 			AAC_DPRINTF(AAC_D_THREAD,
836 				    ("%s: command thread sleeping\n",
837 				     sc->aac_dev.dv_xname));
838 			AAC_LOCK_RELEASE(&sc->aac_io_lock);
839 			retval = tsleep(sc->aifthread, PRIBIO, "aifthd",
840 					AAC_PERIODIC_INTERVAL * hz);
841 			AAC_LOCK_ACQUIRE(&sc->aac_io_lock);
842 		}
843 
844 		if ((sc->aifflags & AAC_AIFFLAGS_COMPLETE) != 0) {
845 			aac_complete(sc);
846 			sc->aifflags &= ~AAC_AIFFLAGS_COMPLETE;
847 		}
848 
849 		/*
850 		 * While we're here, check to see if any commands are stuck.
851 		 * This is pretty low-priority, so it's ok if it doesn't
852 		 * always fire.
853 		 */
854 		if (retval == EWOULDBLOCK)
855 			aac_timeout(sc);
856 
857 		/* Check the hardware printf message buffer */
858 		if (sc->aac_common->ac_printf[0] != 0)
859 			aac_print_printf(sc);
860 
861 		/* Also check to see if the adapter has a command for us. */
862 		while (aac_dequeue_fib(sc, AAC_HOST_NORM_CMD_QUEUE,
863 				       &fib_size, &fib) == 0) {
864 
865 			AAC_PRINT_FIB(sc, fib);
866 
867 			switch (fib->Header.Command) {
868 			case AifRequest:
869 				//aac_handle_aif(sc, fib);
870 				break;
871 			default:
872 				printf("%s: unknown command from controller\n",
873 				       sc->aac_dev.dv_xname);
874 				break;
875 			}
876 
877 			if ((fib->Header.XferState == 0) ||
878 			    (fib->Header.StructType != AAC_FIBTYPE_TFIB))
879 				break;
880 
881 			/* Return the AIF to the controller. */
882 			if (fib->Header.XferState & AAC_FIBSTATE_FROMADAP) {
883 				fib->Header.XferState |= AAC_FIBSTATE_DONEHOST;
884 				*(AAC_FSAStatus*)fib->data = ST_OK;
885 
886 				/* XXX Compute the Size field? */
887 				size = fib->Header.Size;
888 				if (size > sizeof(struct aac_fib)) {
889 					size = sizeof(struct aac_fib);
890 					fib->Header.Size = size;
891 				}
892 
893 				/*
894 				 * Since we did not generate this command, it
895 				 * cannot go through the normal
896 				 * enqueue->startio chain.
897 				 */
898 				aac_enqueue_response(sc,
899 						     AAC_ADAP_NORM_RESP_QUEUE,
900 						     fib);
901 			}
902 		}
903 	}
904 	sc->aifflags &= ~AAC_AIFFLAGS_RUNNING;
905 	AAC_LOCK_RELEASE(&sc->aac_io_lock);
906 
907 #if 0
908 	/*
909 	 * if we ever implement detach, we should have detach tsleep
910 	 * to wait for this thread to finish
911 	 */
912 	wakeup(sc->aac_dev);
913 #endif
914 
915 	AAC_DPRINTF(AAC_D_THREAD, ("%s: aac_command_thread: exiting\n",
916 	    sc->aac_dev.dv_xname));
917 	kthread_exit(0);
918 }
919 
920 /*
921  * Process completed commands.
922  */
923 void
924 aac_complete(void *context)
925 {
926 	struct aac_softc *sc = (struct aac_softc *)context;
927 	struct aac_command *cm;
928 	struct aac_fib *fib;
929 	u_int32_t fib_size;
930 
931 	AAC_DPRINTF(AAC_D_CMD, ("%s: complete", sc->aac_dev.dv_xname));
932 
933 	/* pull completed commands off the queue */
934 	for (;;) {
935 		/* look for completed FIBs on our queue */
936 		if (aac_dequeue_fib(sc, AAC_HOST_NORM_RESP_QUEUE, &fib_size,
937 				    &fib))
938 			break;	/* nothing to do */
939 
940 		/* get the command, unmap and hand off for processing */
941 		cm = sc->aac_commands + fib->Header.SenderData;
942 		if (cm == NULL) {
943 			AAC_PRINT_FIB(sc, fib);
944 			break;
945 		}
946 
947 		aac_remove_busy(cm);
948 		aac_unmap_command(cm);
949 		cm->cm_flags |= AAC_CMD_COMPLETED;
950 
951 		/* is there a completion handler? */
952 		if (cm->cm_complete != NULL) {
953 			cm->cm_complete(cm);
954 		} else {
955 			/* assume that someone is sleeping on this command */
956 			wakeup(cm);
957 		}
958 	}
959 
960 	AAC_DPRINTF(AAC_D_CMD, ("\n"));
961 	/* see if we can start some more I/O */
962 	sc->flags &= ~AAC_QUEUE_FRZN;
963 	aac_startio(sc);
964 }
965 
966 /*
967  * Get a bio and build a command to go with it.
968  */
969 int
970 aac_bio_command(struct aac_softc *sc, struct aac_command **cmp)
971 {
972 	struct aac_command *cm;
973 	struct aac_fib *fib;
974 	struct scsi_xfer *xs;
975 	u_int8_t opcode = 0;
976 
977 	AAC_DPRINTF(AAC_D_CMD, ("%s: bio command", sc->aac_dev.dv_xname));
978 
979 	/* get the resources we will need */
980 	if ((cm = aac_dequeue_bio(sc)) == NULL)
981 		goto fail;
982 	xs = cm->cm_private;
983 
984 	/* build the FIB */
985 	fib = cm->cm_fib;
986 	fib->Header.Size = sizeof(struct aac_fib_header);
987 	fib->Header.XferState =
988 		AAC_FIBSTATE_HOSTOWNED   |
989 		AAC_FIBSTATE_INITIALISED |
990 		AAC_FIBSTATE_EMPTY	 |
991 		AAC_FIBSTATE_FROMHOST	 |
992 		AAC_FIBSTATE_REXPECTED   |
993 		AAC_FIBSTATE_NORM	 |
994 		AAC_FIBSTATE_ASYNC	 |
995 		AAC_FIBSTATE_FAST_RESPONSE;
996 
997 	switch(xs->cmd->opcode) {
998 	case READ_COMMAND:
999 	case READ_BIG:
1000 		opcode = READ_COMMAND;
1001 		break;
1002 	case WRITE_COMMAND:
1003 	case WRITE_BIG:
1004 		opcode = WRITE_COMMAND;
1005 		break;
1006 	default:
1007 		panic("%s: invalid opcode %#x", sc->aac_dev.dv_xname,
1008 		      xs->cmd->opcode);
1009 	}
1010 
1011 	/* build the read/write request */
1012 	if ((sc->flags & AAC_FLAGS_SG_64BIT) == 0) {
1013 		fib->Header.Command = ContainerCommand;
1014 		if (opcode == READ_COMMAND) {
1015 			struct aac_blockread *br;
1016 			br = (struct aac_blockread *)&fib->data[0];
1017 			br->Command = VM_CtBlockRead;
1018 			br->ContainerId = xs->sc_link->target;
1019 			br->BlockNumber = cm->cm_blkno;
1020 			br->ByteCount = cm->cm_bcount * AAC_BLOCK_SIZE;
1021 			fib->Header.Size += sizeof(struct aac_blockread);
1022 			cm->cm_sgtable = &br->SgMap;
1023 			cm->cm_flags |= AAC_CMD_DATAIN;
1024 		} else {
1025 			struct aac_blockwrite *bw;
1026 			bw = (struct aac_blockwrite *)&fib->data[0];
1027 			bw->Command = VM_CtBlockWrite;
1028 			bw->ContainerId = xs->sc_link->target;
1029 			bw->BlockNumber = cm->cm_blkno;
1030 			bw->ByteCount = cm->cm_bcount * AAC_BLOCK_SIZE;
1031 			bw->Stable = CUNSTABLE;
1032 			fib->Header.Size += sizeof(struct aac_blockwrite);
1033 			cm->cm_flags |= AAC_CMD_DATAOUT;
1034 			cm->cm_sgtable = &bw->SgMap;
1035 		}
1036 	} else {
1037 		fib->Header.Command = ContainerCommand64;
1038 		if (opcode == READ_COMMAND) {
1039 			struct aac_blockread64 *br;
1040 			br = (struct aac_blockread64 *)&fib->data[0];
1041 			br->Command = VM_CtHostRead64;
1042 			br->ContainerId = xs->sc_link->target;
1043 			br->BlockNumber = cm->cm_blkno;
1044 			br->SectorCount = cm->cm_bcount;
1045 			br->Pad = 0;
1046 			br->Flags = 0;
1047 			fib->Header.Size += sizeof(struct aac_blockread64);
1048 			cm->cm_flags |= AAC_CMD_DATAOUT;
1049 			cm->cm_sgtable = (struct aac_sg_table *)&br->SgMap64;
1050 		} else {
1051 			struct aac_blockwrite64 *bw;
1052 			bw = (struct aac_blockwrite64 *)&fib->data[0];
1053 			bw->Command = VM_CtHostWrite64;
1054 			bw->ContainerId = xs->sc_link->target;
1055 			bw->BlockNumber = cm->cm_blkno;
1056 			bw->SectorCount = cm->cm_bcount;
1057 			bw->Pad = 0;
1058 			bw->Flags = 0;
1059 			fib->Header.Size += sizeof(struct aac_blockwrite64);
1060 			cm->cm_flags |= AAC_CMD_DATAIN;
1061 			cm->cm_sgtable = (struct aac_sg_table *)&bw->SgMap64;
1062 		}
1063 	}
1064 
1065 	*cmp = cm;
1066 	AAC_DPRINTF(AAC_D_CMD, ("\n"));
1067 	return(0);
1068 
1069 fail:
1070 	AAC_DPRINTF(AAC_D_CMD, ("\n"));
1071 	return(ENOMEM);
1072 }
1073 
1074 /*
1075  * Handle a bio-instigated command that has been completed.
1076  */
1077 void
1078 aac_bio_complete(struct aac_command *cm)
1079 {
1080 	struct aac_blockread_response *brr;
1081 	struct aac_blockwrite_response *bwr;
1082 	struct scsi_xfer *xs = (struct scsi_xfer *)cm->cm_private;
1083 	AAC_FSAStatus status;
1084 	int s;
1085 
1086 	AAC_DPRINTF(AAC_D_CMD,
1087 		    ("%s: bio complete\n", cm->cm_sc->aac_dev.dv_xname));
1088 
1089 	/* fetch relevant status and then release the command */
1090 	if (xs->flags & SCSI_DATA_IN) {
1091 		brr = (struct aac_blockread_response *)&cm->cm_fib->data[0];
1092 		status = brr->Status;
1093 	} else {
1094 		bwr = (struct aac_blockwrite_response *)&cm->cm_fib->data[0];
1095 		status = bwr->Status;
1096 	}
1097 
1098 	xs->error = status == ST_OK? XS_NOERROR : XS_DRIVER_STUFFUP;
1099 	xs->resid = 0;
1100 	s = splbio();
1101 	scsi_done(xs);
1102 	splx(s);
1103 }
1104 
1105 /*
1106  * Submit a command to the controller, return when it completes.
1107  * XXX This is very dangerous!  If the card has gone out to lunch, we could
1108  *     be stuck here forever.  At the same time, signals are not caught
1109  *     because there is a risk that a signal could wakeup the tsleep before
1110  *     the card has a chance to complete the command.  The passed in timeout
1111  *     is ignored for the same reason.  Since there is no way to cancel a
1112  *     command in progress, we should probably create a 'dead' queue where
1113  *     commands go that have been interrupted/timed-out/etc, that keeps them
1114  *     out of the free pool.  That way, if the card is just slow, it won't
1115  *     spam the memory of a command that has been recycled.
1116  */
1117 int
1118 aac_wait_command(struct aac_command *cm, int timeout)
1119 {
1120 	struct aac_softc *sc = cm->cm_sc;
1121 	int error = 0;
1122 
1123 	AAC_DPRINTF(AAC_D_CMD, (": wait for command"));
1124 
1125 	/* Put the command on the ready queue and get things going */
1126 	cm->cm_queue = AAC_ADAP_NORM_CMD_QUEUE;
1127 	aac_enqueue_ready(cm);
1128 	AAC_DPRINTF(AAC_D_CMD, ("\n"));
1129 	aac_startio(sc);
1130 	while (!(cm->cm_flags & AAC_CMD_COMPLETED) && (error != EWOULDBLOCK)) {
1131 		AAC_DPRINTF(AAC_D_MISC, ("%s: sleeping until command done\n",
1132 					 sc->aac_dev.dv_xname));
1133 		AAC_LOCK_RELEASE(&sc->aac_io_lock);
1134 		error = tsleep(cm, PRIBIO, "aacwait", timeout);
1135 		AAC_LOCK_ACQUIRE(&sc->aac_io_lock);
1136 	}
1137 	return (error);
1138 }
1139 
1140 /*
1141  *Command Buffer Management
1142  */
1143 
1144 /*
1145  * Allocate a command.
1146  */
1147 void *
1148 aac_alloc_command(void *xsc)
1149 {
1150 	struct aac_softc *sc = xsc;
1151 	struct aac_command *cm;
1152 
1153 	AAC_DPRINTF(AAC_D_CMD, (": allocate command"));
1154 	mtx_enter(&sc->aac_free_mtx);
1155 	cm = aac_dequeue_free(sc);
1156 	mtx_leave(&sc->aac_free_mtx);
1157 
1158 	return (cm);
1159 }
1160 
1161 void
1162 aac_scrub_command(struct aac_command *cm)
1163 {
1164 	cm->cm_sgtable = NULL;
1165 	cm->cm_flags = 0;
1166 	cm->cm_complete = NULL;
1167 	cm->cm_private = NULL;
1168 	cm->cm_fib->Header.XferState = AAC_FIBSTATE_EMPTY;
1169 	cm->cm_fib->Header.StructType = AAC_FIBTYPE_TFIB;
1170 	cm->cm_fib->Header.Flags = 0;
1171 	cm->cm_fib->Header.SenderSize = sizeof(struct aac_fib);
1172 }
1173 
1174 /*
1175  * Release a command back to the freelist.
1176  */
1177 void
1178 aac_release_command(void *xsc, void *xcm)
1179 {
1180 	struct aac_softc *sc = xsc;
1181 	struct aac_command *cm = xcm;
1182 	AAC_DPRINTF(AAC_D_CMD, (": release command"));
1183 
1184 	mtx_enter(&sc->aac_free_mtx);
1185 	aac_enqueue_free(cm);
1186 	mtx_leave(&sc->aac_free_mtx);
1187 }
1188 
1189 /*
1190  * Allocate and initialise commands/FIBs for this adapter.
1191  */
1192 int
1193 aac_alloc_commands(struct aac_softc *sc)
1194 {
1195 	struct aac_command *cm;
1196 	struct aac_fibmap *fm;
1197 	int i, error = ENOMEM;
1198 
1199 	if (sc->total_fibs + AAC_FIB_COUNT > sc->aac_max_fibs)
1200 		return (ENOMEM);
1201 
1202 	fm = malloc(sizeof(*fm), M_DEVBUF, M_NOWAIT | M_ZERO);
1203 	if (fm == NULL)
1204 		goto exit;
1205 
1206 	/* allocate the FIBs in DMAable memory and load them */
1207 	if (bus_dmamem_alloc(sc->aac_dmat, AAC_FIBMAP_SIZE, PAGE_SIZE, 0,
1208 	    &fm->aac_seg, 1, &fm->aac_nsegs, BUS_DMA_NOWAIT | BUS_DMA_ZERO)) {
1209 		printf("%s: can't alloc FIBs\n", sc->aac_dev.dv_xname);
1210 		error = ENOBUFS;
1211 		goto exit_alloc;
1212 	}
1213 
1214 	if (bus_dmamem_map(sc->aac_dmat, &fm->aac_seg, 1,
1215 	    AAC_FIBMAP_SIZE, (caddr_t *)&fm->aac_fibs, BUS_DMA_NOWAIT)) {
1216 		printf("%s: can't map FIB structure\n", sc->aac_dev.dv_xname);
1217 		error = ENOBUFS;
1218 		goto exit_map;
1219 	}
1220 
1221 	if (bus_dmamap_create(sc->aac_dmat, AAC_FIBMAP_SIZE, 1,
1222 	    AAC_FIBMAP_SIZE, 0, BUS_DMA_NOWAIT, &fm->aac_fibmap)) {
1223 		printf("%s: can't create dma map\n", sc->aac_dev.dv_xname);
1224 		error = ENOBUFS;
1225 		goto exit_create;
1226 	}
1227 
1228 	if (bus_dmamap_load(sc->aac_dmat, fm->aac_fibmap, fm->aac_fibs,
1229 	    AAC_FIBMAP_SIZE, NULL, BUS_DMA_NOWAIT)) {
1230 		printf("%s: can't load dma map\n", sc->aac_dev.dv_xname);
1231 		error = ENOBUFS;
1232 		goto exit_load;
1233 	}
1234 
1235 	/* initialise constant fields in the command structure */
1236 	AAC_LOCK_ACQUIRE(&sc->aac_io_lock);
1237 	for (i = 0; i < AAC_FIB_COUNT; i++) {
1238 		cm = sc->aac_commands + sc->total_fibs;
1239 		fm->aac_commands = cm;
1240 		cm->cm_sc = sc;
1241 		cm->cm_fib = fm->aac_fibs + i;
1242 		cm->cm_fibphys = fm->aac_fibmap->dm_segs[0].ds_addr +
1243 			(i * sizeof(struct aac_fib));
1244 		cm->cm_index = sc->total_fibs;
1245 
1246 		if (bus_dmamap_create(sc->aac_dmat, MAXBSIZE, AAC_MAXSGENTRIES,
1247 		    MAXBSIZE, 0, BUS_DMA_NOWAIT, &cm->cm_datamap)) {
1248 			break;
1249 		}
1250 		aac_release_command(sc, cm);
1251 		sc->total_fibs++;
1252 	}
1253 
1254 	if (i > 0) {
1255 		TAILQ_INSERT_TAIL(&sc->aac_fibmap_tqh, fm, fm_link);
1256 		AAC_DPRINTF(AAC_D_MISC, ("%s: total_fibs= %d\n",
1257 					 sc->aac_dev.dv_xname,
1258 					 sc->total_fibs));
1259 		AAC_LOCK_RELEASE(&sc->aac_io_lock);
1260 		return (0);
1261 	}
1262 
1263  exit_load:
1264 	bus_dmamap_destroy(sc->aac_dmat, fm->aac_fibmap);
1265  exit_create:
1266 	bus_dmamem_unmap(sc->aac_dmat, (caddr_t)fm->aac_fibs, AAC_FIBMAP_SIZE);
1267  exit_map:
1268 	bus_dmamem_free(sc->aac_dmat, &fm->aac_seg, fm->aac_nsegs);
1269  exit_alloc:
1270 	free(fm, M_DEVBUF, 0);
1271  exit:
1272 	AAC_LOCK_RELEASE(&sc->aac_io_lock);
1273 	return (error);
1274 }
1275 
1276 /*
1277  * Free FIBs owned by this adapter.
1278  */
1279 void
1280 aac_free_commands(struct aac_softc *sc)
1281 {
1282 	struct aac_fibmap *fm;
1283 	struct aac_command *cm;
1284 	int i;
1285 
1286 	while ((fm = TAILQ_FIRST(&sc->aac_fibmap_tqh)) != NULL) {
1287 
1288 		TAILQ_REMOVE(&sc->aac_fibmap_tqh, fm, fm_link);
1289 
1290 		/*
1291 		 * We check against total_fibs to handle partially
1292 		 * allocated blocks.
1293 		 */
1294 		for (i = 0; i < AAC_FIB_COUNT && sc->total_fibs--; i++) {
1295 			cm = fm->aac_commands + i;
1296 			bus_dmamap_destroy(sc->aac_dmat, cm->cm_datamap);
1297 		}
1298 
1299 		bus_dmamap_unload(sc->aac_dmat, fm->aac_fibmap);
1300 		bus_dmamap_destroy(sc->aac_dmat, fm->aac_fibmap);
1301 		bus_dmamem_unmap(sc->aac_dmat, (caddr_t)fm->aac_fibs,
1302 				 AAC_FIBMAP_SIZE);
1303 		bus_dmamem_free(sc->aac_dmat, &fm->aac_seg, fm->aac_nsegs);
1304 		free(fm, M_DEVBUF, 0);
1305 	}
1306 }
1307 
1308 
1309 /*
1310  * Command-mapping helper function - populate this command's s/g table.
1311  */
1312 void
1313 aac_map_command_sg(void *arg, bus_dma_segment_t *segs, int nseg, int error)
1314 {
1315 	struct aac_command *cm = arg;
1316 	struct aac_softc *sc = cm->cm_sc;
1317 	struct aac_fib *fib = cm->cm_fib;
1318 	int i;
1319 
1320 	/* copy into the FIB */
1321 	if (cm->cm_sgtable != NULL) {
1322 		if ((cm->cm_sc->flags & AAC_FLAGS_SG_64BIT) == 0) {
1323 			struct aac_sg_table *sg = cm->cm_sgtable;
1324 			sg->SgCount = nseg;
1325 			for (i = 0; i < nseg; i++) {
1326 				sg->SgEntry[i].SgAddress = segs[i].ds_addr;
1327 				sg->SgEntry[i].SgByteCount = segs[i].ds_len;
1328 			}
1329 			/* update the FIB size for the s/g count */
1330 			fib->Header.Size += nseg * sizeof(struct aac_sg_entry);
1331 		} else {
1332 			struct aac_sg_table64 *sg;
1333 			sg = (struct aac_sg_table64 *)cm->cm_sgtable;
1334 			sg->SgCount = nseg;
1335 			for (i = 0; i < nseg; i++) {
1336 				sg->SgEntry64[i].SgAddress = segs[i].ds_addr;
1337 				sg->SgEntry64[i].SgByteCount = segs[i].ds_len;
1338 			}
1339 			/* update the FIB size for the s/g count */
1340 			fib->Header.Size += nseg*sizeof(struct aac_sg_entry64);
1341 		}
1342 	}
1343 
1344 	/* Fix up the address values in the FIB.  Use the command array index
1345 	 * instead of a pointer since these fields are only 32 bits.  Shift
1346 	 * the SenderFibAddress over to make room for the fast response bit.
1347 	 */
1348 	cm->cm_fib->Header.SenderFibAddress = (cm->cm_index << 1);
1349 	cm->cm_fib->Header.ReceiverFibAddress = cm->cm_fibphys;
1350 
1351 	/* save a pointer to the command for speedy reverse-lookup */
1352 	cm->cm_fib->Header.SenderData = cm->cm_index;
1353 
1354 	if (cm->cm_flags & AAC_CMD_DATAIN)
1355 		bus_dmamap_sync(sc->aac_dmat, cm->cm_datamap, 0,
1356 				cm->cm_datamap->dm_mapsize,
1357 				BUS_DMASYNC_PREREAD);
1358 	if (cm->cm_flags & AAC_CMD_DATAOUT)
1359 		bus_dmamap_sync(sc->aac_dmat, cm->cm_datamap, 0,
1360 				cm->cm_datamap->dm_mapsize,
1361 				BUS_DMASYNC_PREWRITE);
1362 	cm->cm_flags |= AAC_CMD_MAPPED;
1363 
1364 	/* put the FIB on the outbound queue */
1365 	if (aac_enqueue_fib(sc, cm->cm_queue, cm) == EBUSY) {
1366 		aac_remove_busy(cm);
1367 		aac_unmap_command(cm);
1368 		aac_requeue_ready(cm);
1369 	}
1370 }
1371 
1372 /*
1373  * Unmap a command from controller-visible space.
1374  */
1375 void
1376 aac_unmap_command(struct aac_command *cm)
1377 {
1378 	struct aac_softc *sc = cm->cm_sc;
1379 
1380 	if (!(cm->cm_flags & AAC_CMD_MAPPED))
1381 		return;
1382 
1383 	if (cm->cm_datalen != 0) {
1384 		if (cm->cm_flags & AAC_CMD_DATAIN)
1385 			bus_dmamap_sync(sc->aac_dmat, cm->cm_datamap, 0,
1386 					cm->cm_datamap->dm_mapsize,
1387 					BUS_DMASYNC_POSTREAD);
1388 		if (cm->cm_flags & AAC_CMD_DATAOUT)
1389 			bus_dmamap_sync(sc->aac_dmat, cm->cm_datamap, 0,
1390 					cm->cm_datamap->dm_mapsize,
1391 					BUS_DMASYNC_POSTWRITE);
1392 
1393 		bus_dmamap_unload(sc->aac_dmat, cm->cm_datamap);
1394 	}
1395 	cm->cm_flags &= ~AAC_CMD_MAPPED;
1396 }
1397 
1398 /*
1399  * Hardware Interface
1400  */
1401 
1402 /*
1403  * Initialise the adapter.
1404  */
1405 int
1406 aac_check_firmware(struct aac_softc *sc)
1407 {
1408 	u_int32_t major, minor, options;
1409 
1410 	/*
1411 	 * Retrieve the firmware version numbers.  Dell PERC2/QC cards with
1412 	 * firmware version 1.x are not compatible with this driver.
1413 	 */
1414 	if (sc->flags & AAC_FLAGS_PERC2QC) {
1415 		if (aac_sync_command(sc, AAC_MONKER_GETKERNVER, 0, 0, 0, 0,
1416 				     NULL)) {
1417 			printf("%s: Error reading firmware version\n",
1418 			       sc->aac_dev.dv_xname);
1419 			return (EIO);
1420 		}
1421 
1422 		/* These numbers are stored as ASCII! */
1423 		major = (AAC_GET_MAILBOX(sc, 1) & 0xff) - 0x30;
1424 		minor = (AAC_GET_MAILBOX(sc, 2) & 0xff) - 0x30;
1425 		if (major == 1) {
1426 			printf("%s: Firmware version %d.%d is not supported\n",
1427 			       sc->aac_dev.dv_xname, major, minor);
1428 			return (EINVAL);
1429 		}
1430 	}
1431 
1432 	/*
1433 	 * Retrieve the capabilities/supported options word so we know what
1434 	 * work-arounds to enable.
1435 	 */
1436 	if (aac_sync_command(sc, AAC_MONKER_GETINFO, 0, 0, 0, 0, NULL)) {
1437 		printf("%s: RequestAdapterInfo failed\n",
1438 		       sc->aac_dev.dv_xname);
1439 		return (EIO);
1440 	}
1441 	options = AAC_GET_MAILBOX(sc, 1);
1442 	sc->supported_options = options;
1443 
1444 	if ((options & AAC_SUPPORTED_4GB_WINDOW) != 0 &&
1445 	    (sc->flags & AAC_FLAGS_NO4GB) == 0)
1446 		sc->flags |= AAC_FLAGS_4GB_WINDOW;
1447 	if (options & AAC_SUPPORTED_NONDASD)
1448 		sc->flags |= AAC_FLAGS_ENABLE_CAM;
1449 	if ((options & AAC_SUPPORTED_SGMAP_HOST64) != 0
1450 	     && (sizeof(bus_addr_t) > 4)) {
1451 		printf("%s: Enabling 64-bit address support\n",
1452 		       sc->aac_dev.dv_xname);
1453 		sc->flags |= AAC_FLAGS_SG_64BIT;
1454 	}
1455 
1456 	/* Check for broken hardware that does a lower number of commands */
1457 	if ((sc->flags & AAC_FLAGS_256FIBS) == 0)
1458 		sc->aac_max_fibs = AAC_MAX_FIBS;
1459 	else
1460 		sc->aac_max_fibs = 256;
1461 
1462 	return (0);
1463 }
1464 
1465 int
1466 aac_init(struct aac_softc *sc)
1467 {
1468 	bus_dma_segment_t seg;
1469 	int nsegs;
1470 	int i, error;
1471 	int state = 0;
1472 	struct aac_adapter_init	*ip;
1473 	time_t then;
1474 	u_int32_t code, qoffset;
1475 
1476 	/*
1477 	 * First wait for the adapter to come ready.
1478 	 */
1479 	then = time_uptime;
1480 	for (i = 0; i < AAC_BOOT_TIMEOUT * 1000; i++) {
1481 		code = AAC_GET_FWSTATUS(sc);
1482 		if (code & AAC_SELF_TEST_FAILED) {
1483 			printf("%s: FATAL: selftest failed\n",
1484 			    sc->aac_dev.dv_xname);
1485 			return (ENXIO);
1486 		}
1487 		if (code & AAC_KERNEL_PANIC) {
1488 			printf("%s: FATAL: controller kernel panic\n",
1489 			    sc->aac_dev.dv_xname);
1490 			return (ENXIO);
1491 		}
1492 		if (code & AAC_UP_AND_RUNNING)
1493 			break;
1494 		DELAY(1000);
1495 	}
1496 	if (i == AAC_BOOT_TIMEOUT * 1000) {
1497 		printf("%s: FATAL: controller not coming ready, status %x\n",
1498 		    sc->aac_dev.dv_xname, code);
1499 		return (ENXIO);
1500 	}
1501 
1502 	/*
1503 	 * Work around a bug in the 2120 and 2200 that cannot DMA commands
1504 	 * below address 8192 in physical memory.
1505 	 * XXX If the padding is not needed, can it be put to use instead
1506 	 * of ignored?
1507 	 */
1508 	if (bus_dmamem_alloc(sc->aac_dmat, AAC_COMMON_ALLOCSIZE, PAGE_SIZE, 0,
1509 			     &seg, 1, &nsegs, BUS_DMA_NOWAIT | BUS_DMA_ZERO)) {
1510 		printf("%s: can't allocate common structure\n",
1511 		    sc->aac_dev.dv_xname);
1512 		return (ENOMEM);
1513 	}
1514 	state++;
1515 
1516 	if (bus_dmamem_map(sc->aac_dmat, &seg, nsegs, AAC_COMMON_ALLOCSIZE,
1517 			   (caddr_t *)&sc->aac_common, BUS_DMA_NOWAIT)) {
1518 		printf("%s: can't map common structure\n",
1519 		    sc->aac_dev.dv_xname);
1520 		error = ENOMEM;
1521 		goto bail_out;
1522 	}
1523 	state++;
1524 
1525 	if (bus_dmamap_create(sc->aac_dmat, AAC_COMMON_ALLOCSIZE, 1,
1526 	    AAC_COMMON_ALLOCSIZE, 0, BUS_DMA_NOWAIT, &sc->aac_common_map)) {
1527 		printf("%s: can't create dma map\n", sc->aac_dev.dv_xname);
1528 		error = ENOBUFS;
1529 		goto bail_out;
1530 	}
1531 	state++;
1532 
1533 	if (bus_dmamap_load(sc->aac_dmat, sc->aac_common_map, sc->aac_common,
1534 	    AAC_COMMON_ALLOCSIZE, NULL, BUS_DMA_NOWAIT)) {
1535 		printf("%s: can't load dma map\n", sc->aac_dev.dv_xname);
1536 		error = ENOBUFS;
1537 		goto bail_out;
1538 	}
1539 	state++;
1540 
1541 	sc->aac_common_busaddr = sc->aac_common_map->dm_segs[0].ds_addr;
1542 
1543 	if (sc->aac_common_busaddr < 8192) {
1544 		sc->aac_common = (struct aac_common *)
1545 		    ((uint8_t *)sc->aac_common + 8192);
1546 		sc->aac_common_busaddr += 8192;
1547 	}
1548 
1549 	/* Allocate some FIBs and associated command structs */
1550 	TAILQ_INIT(&sc->aac_fibmap_tqh);
1551 	sc->aac_commands = malloc(AAC_MAX_FIBS * sizeof(struct aac_command),
1552 	    M_DEVBUF, M_WAITOK | M_ZERO);
1553 	while (sc->total_fibs < AAC_MAX_FIBS) {
1554 		if (aac_alloc_commands(sc) != 0)
1555 			break;
1556 	}
1557 	if (sc->total_fibs == 0)
1558 		goto out;
1559 
1560 	scsi_iopool_init(&sc->aac_iopool, sc,
1561 	    aac_alloc_command, aac_release_command);
1562 
1563 	/*
1564 	 * Fill in the init structure.  This tells the adapter about the
1565 	 * physical location of various important shared data structures.
1566 	 */
1567 	ip = &sc->aac_common->ac_init;
1568 	ip->InitStructRevision = AAC_INIT_STRUCT_REVISION;
1569 	ip->MiniPortRevision = AAC_INIT_STRUCT_MINIPORT_REVISION;
1570 
1571 	ip->AdapterFibsPhysicalAddress = sc->aac_common_busaddr +
1572 					 offsetof(struct aac_common, ac_fibs);
1573 	ip->AdapterFibsVirtualAddress = 0;
1574 	ip->AdapterFibsSize = AAC_ADAPTER_FIBS * sizeof(struct aac_fib);
1575 	ip->AdapterFibAlign = sizeof(struct aac_fib);
1576 
1577 	ip->PrintfBufferAddress = sc->aac_common_busaddr +
1578 				  offsetof(struct aac_common, ac_printf);
1579 	ip->PrintfBufferSize = AAC_PRINTF_BUFSIZE;
1580 
1581 	/*
1582 	 * The adapter assumes that pages are 4K in size, except on some
1583  	 * broken firmware versions that do the page->byte conversion twice,
1584 	 * therefore 'assuming' that this value is in 16MB units (2^24).
1585 	 * Round up since the granularity is so high.
1586 	 */
1587 	ip->HostPhysMemPages = ptoa(physmem) / AAC_PAGE_SIZE;
1588 	if (sc->flags & AAC_FLAGS_BROKEN_MEMMAP) {
1589 		ip->HostPhysMemPages =
1590 		    (ip->HostPhysMemPages + AAC_PAGE_SIZE) / AAC_PAGE_SIZE;
1591 	}
1592 	ip->HostElapsedSeconds = time_uptime; /* reset later if invalid */
1593 
1594 	/*
1595 	 * Initialise FIB queues.  Note that it appears that the layout of the
1596 	 * indexes and the segmentation of the entries may be mandated by the
1597 	 * adapter, which is only told about the base of the queue index fields.
1598 	 *
1599 	 * The initial values of the indices are assumed to inform the adapter
1600 	 * of the sizes of the respective queues, and theoretically it could
1601 	 * work out the entire layout of the queue structures from this.  We
1602 	 * take the easy route and just lay this area out like everyone else
1603 	 * does.
1604 	 *
1605 	 * The Linux driver uses a much more complex scheme whereby several
1606 	 * header records are kept for each queue.  We use a couple of generic
1607 	 * list manipulation functions which 'know' the size of each list by
1608 	 * virtue of a table.
1609 	 */
1610 	qoffset = offsetof(struct aac_common, ac_qbuf) + AAC_QUEUE_ALIGN;
1611 	qoffset &= ~(AAC_QUEUE_ALIGN - 1);
1612 	sc->aac_queues =
1613 	    (struct aac_queue_table *)((caddr_t)sc->aac_common + qoffset);
1614 	ip->CommHeaderAddress = sc->aac_common_busaddr + qoffset;
1615 
1616 	sc->aac_queues->qt_qindex[AAC_HOST_NORM_CMD_QUEUE][AAC_PRODUCER_INDEX] =
1617 		AAC_HOST_NORM_CMD_ENTRIES;
1618 	sc->aac_queues->qt_qindex[AAC_HOST_NORM_CMD_QUEUE][AAC_CONSUMER_INDEX] =
1619 		AAC_HOST_NORM_CMD_ENTRIES;
1620 	sc->aac_queues->qt_qindex[AAC_HOST_HIGH_CMD_QUEUE][AAC_PRODUCER_INDEX] =
1621 		AAC_HOST_HIGH_CMD_ENTRIES;
1622 	sc->aac_queues->qt_qindex[AAC_HOST_HIGH_CMD_QUEUE][AAC_CONSUMER_INDEX] =
1623 		AAC_HOST_HIGH_CMD_ENTRIES;
1624 	sc->aac_queues->qt_qindex[AAC_ADAP_NORM_CMD_QUEUE][AAC_PRODUCER_INDEX] =
1625 		AAC_ADAP_NORM_CMD_ENTRIES;
1626 	sc->aac_queues->qt_qindex[AAC_ADAP_NORM_CMD_QUEUE][AAC_CONSUMER_INDEX] =
1627 		AAC_ADAP_NORM_CMD_ENTRIES;
1628 	sc->aac_queues->qt_qindex[AAC_ADAP_HIGH_CMD_QUEUE][AAC_PRODUCER_INDEX] =
1629 		AAC_ADAP_HIGH_CMD_ENTRIES;
1630 	sc->aac_queues->qt_qindex[AAC_ADAP_HIGH_CMD_QUEUE][AAC_CONSUMER_INDEX] =
1631 		AAC_ADAP_HIGH_CMD_ENTRIES;
1632 	sc->aac_queues->qt_qindex[AAC_HOST_NORM_RESP_QUEUE][AAC_PRODUCER_INDEX]=
1633 		AAC_HOST_NORM_RESP_ENTRIES;
1634 	sc->aac_queues->qt_qindex[AAC_HOST_NORM_RESP_QUEUE][AAC_CONSUMER_INDEX]=
1635 		AAC_HOST_NORM_RESP_ENTRIES;
1636 	sc->aac_queues->qt_qindex[AAC_HOST_HIGH_RESP_QUEUE][AAC_PRODUCER_INDEX]=
1637 		AAC_HOST_HIGH_RESP_ENTRIES;
1638 	sc->aac_queues->qt_qindex[AAC_HOST_HIGH_RESP_QUEUE][AAC_CONSUMER_INDEX]=
1639 		AAC_HOST_HIGH_RESP_ENTRIES;
1640 	sc->aac_queues->qt_qindex[AAC_ADAP_NORM_RESP_QUEUE][AAC_PRODUCER_INDEX]=
1641 		AAC_ADAP_NORM_RESP_ENTRIES;
1642 	sc->aac_queues->qt_qindex[AAC_ADAP_NORM_RESP_QUEUE][AAC_CONSUMER_INDEX]=
1643 		AAC_ADAP_NORM_RESP_ENTRIES;
1644 	sc->aac_queues->qt_qindex[AAC_ADAP_HIGH_RESP_QUEUE][AAC_PRODUCER_INDEX]=
1645 		AAC_ADAP_HIGH_RESP_ENTRIES;
1646 	sc->aac_queues->qt_qindex[AAC_ADAP_HIGH_RESP_QUEUE][AAC_CONSUMER_INDEX]=
1647 		AAC_ADAP_HIGH_RESP_ENTRIES;
1648 	sc->aac_qentries[AAC_HOST_NORM_CMD_QUEUE] =
1649 		&sc->aac_queues->qt_HostNormCmdQueue[0];
1650 	sc->aac_qentries[AAC_HOST_HIGH_CMD_QUEUE] =
1651 		&sc->aac_queues->qt_HostHighCmdQueue[0];
1652 	sc->aac_qentries[AAC_ADAP_NORM_CMD_QUEUE] =
1653 		&sc->aac_queues->qt_AdapNormCmdQueue[0];
1654 	sc->aac_qentries[AAC_ADAP_HIGH_CMD_QUEUE] =
1655 		&sc->aac_queues->qt_AdapHighCmdQueue[0];
1656 	sc->aac_qentries[AAC_HOST_NORM_RESP_QUEUE] =
1657 		&sc->aac_queues->qt_HostNormRespQueue[0];
1658 	sc->aac_qentries[AAC_HOST_HIGH_RESP_QUEUE] =
1659 		&sc->aac_queues->qt_HostHighRespQueue[0];
1660 	sc->aac_qentries[AAC_ADAP_NORM_RESP_QUEUE] =
1661 		&sc->aac_queues->qt_AdapNormRespQueue[0];
1662 	sc->aac_qentries[AAC_ADAP_HIGH_RESP_QUEUE] =
1663 		&sc->aac_queues->qt_AdapHighRespQueue[0];
1664 
1665 	/*
1666 	 * Do controller-type-specific initialisation
1667 	 */
1668 	switch (sc->aac_hwif) {
1669 	case AAC_HWIF_I960RX:
1670 		AAC_SETREG4(sc, AAC_RX_ODBR, ~0);
1671 		break;
1672 	case AAC_HWIF_RKT:
1673 		AAC_SETREG4(sc, AAC_RKT_ODBR, ~0);
1674 		break;
1675 	default:
1676 		break;
1677 	}
1678 
1679 	/*
1680 	 * Give the init structure to the controller.
1681 	 */
1682 	if (aac_sync_command(sc, AAC_MONKER_INITSTRUCT,
1683 			     sc->aac_common_busaddr +
1684 			     offsetof(struct aac_common, ac_init), 0, 0, 0,
1685 			     NULL)) {
1686 		printf("%s: error establishing init structure\n",
1687 		    sc->aac_dev.dv_xname);
1688 		error = EIO;
1689 		goto bail_out;
1690 	}
1691 
1692 	aac_describe_controller(sc);
1693 	aac_startup(sc);
1694 
1695 	return (0);
1696 
1697  bail_out:
1698 	if (state > 3)
1699 		bus_dmamap_unload(sc->aac_dmat, sc->aac_common_map);
1700 	if (state > 2)
1701 		bus_dmamap_destroy(sc->aac_dmat, sc->aac_common_map);
1702 	if (state > 1)
1703 		bus_dmamem_unmap(sc->aac_dmat, (caddr_t)sc->aac_common,
1704 		    sizeof *sc->aac_common);
1705 	if (state > 0)
1706 		bus_dmamem_free(sc->aac_dmat, &seg, 1);
1707 
1708  out:
1709 	return (error);
1710 }
1711 
1712 /*
1713  * Send a synchronous command to the controller and wait for a result.
1714  */
1715 int
1716 aac_sync_command(struct aac_softc *sc, u_int32_t command, u_int32_t arg0,
1717 		 u_int32_t arg1, u_int32_t arg2, u_int32_t arg3, u_int32_t *sp)
1718 {
1719 //	time_t then;
1720 	int i;
1721 	u_int32_t status;
1722 	u_int16_t reason;
1723 
1724 	/* populate the mailbox */
1725 	AAC_SET_MAILBOX(sc, command, arg0, arg1, arg2, arg3);
1726 
1727 	/* ensure the sync command doorbell flag is cleared */
1728 	AAC_CLEAR_ISTATUS(sc, AAC_DB_SYNC_COMMAND);
1729 
1730 	/* then set it to signal the adapter */
1731 	AAC_QNOTIFY(sc, AAC_DB_SYNC_COMMAND);
1732 
1733 #if 0
1734 	/* spin waiting for the command to complete */
1735 	then = time_uptime;
1736 	do {
1737 		if (time_uptime > (then + AAC_IMMEDIATE_TIMEOUT)) {
1738 			AAC_DPRINTF(AAC_D_MISC, ("timed out"));
1739 			return(EIO);
1740 		}
1741 	} while (!(AAC_GET_ISTATUS(sc) & AAC_DB_SYNC_COMMAND));
1742 #else
1743 	DELAY(AAC_SYNC_DELAY);
1744 
1745 	/* spin waiting for the command to complete */
1746 	for (i = 0; i < AAC_IMMEDIATE_TIMEOUT * 1000; i++) {
1747 		reason = AAC_GET_ISTATUS(sc);
1748 		if (reason & AAC_DB_SYNC_COMMAND)
1749 			break;
1750 		reason = AAC_GET_ISTATUS(sc);
1751 		if (reason & AAC_DB_SYNC_COMMAND)
1752 			break;
1753 		reason = AAC_GET_ISTATUS(sc);
1754 		if (reason & AAC_DB_SYNC_COMMAND)
1755 			break;
1756 		DELAY(1000);
1757 	}
1758 	if (i == AAC_IMMEDIATE_TIMEOUT * 1000) {
1759 		printf("aac_sync_command: failed, reason=%#x\n", reason);
1760 		return (EIO);
1761 	}
1762 #endif
1763 
1764 	/* clear the completion flag */
1765 	AAC_CLEAR_ISTATUS(sc, AAC_DB_SYNC_COMMAND);
1766 
1767 	/* get the command status */
1768 	status = AAC_GET_MAILBOX(sc, 0);
1769 
1770 	if (sp != NULL)
1771 		*sp = status;
1772 
1773 	return(0);
1774 }
1775 
1776 /*
1777  * Grab the sync fib area.
1778  */
1779 int
1780 aac_alloc_sync_fib(struct aac_softc *sc, struct aac_fib **fib, int flags)
1781 {
1782 
1783 	/*
1784 	 * If the force flag is set, the system is shutting down, or in
1785 	 * trouble.  Ignore the mutex.
1786 	 */
1787 	if (!(flags & AAC_SYNC_LOCK_FORCE))
1788 		AAC_LOCK_ACQUIRE(&sc->aac_sync_lock);
1789 
1790 	*fib = &sc->aac_common->ac_sync_fib;
1791 
1792 	return (1);
1793 }
1794 
1795 /*
1796  * Release the sync fib area.
1797  */
1798 void
1799 aac_release_sync_fib(struct aac_softc *sc)
1800 {
1801 	AAC_LOCK_RELEASE(&sc->aac_sync_lock);
1802 }
1803 
1804 /*
1805  * Send a synchronous FIB to the controller and wait for a result.
1806  */
1807 int
1808 aac_sync_fib(struct aac_softc *sc, u_int32_t command, u_int32_t xferstate,
1809 	     struct aac_fib *fib, u_int16_t datasize)
1810 {
1811 
1812 	if (datasize > AAC_FIB_DATASIZE) {
1813 		printf("aac_sync_fib 1: datasize=%d AAC_FIB_DATASIZE %lu\n",
1814 		    datasize, AAC_FIB_DATASIZE);
1815 		return(EINVAL);
1816 	}
1817 
1818 	/*
1819 	 * Set up the sync FIB
1820 	 */
1821 	fib->Header.XferState = AAC_FIBSTATE_HOSTOWNED |
1822 				AAC_FIBSTATE_INITIALISED |
1823 				AAC_FIBSTATE_EMPTY;
1824 	fib->Header.XferState |= xferstate;
1825 	fib->Header.Command = command;
1826 	fib->Header.StructType = AAC_FIBTYPE_TFIB;
1827 	fib->Header.Size = sizeof(struct aac_fib) + datasize;
1828 	fib->Header.SenderSize = sizeof(struct aac_fib);
1829 	fib->Header.SenderFibAddress = 0;	/* Not needed */
1830 	fib->Header.ReceiverFibAddress = sc->aac_common_busaddr +
1831 					 offsetof(struct aac_common,
1832 						  ac_sync_fib);
1833 
1834 	/*
1835 	 * Give the FIB to the controller, wait for a response.
1836 	 */
1837 	if (aac_sync_command(sc, AAC_MONKER_SYNCFIB,
1838 			     fib->Header.ReceiverFibAddress, 0, 0, 0, NULL)) {
1839 		AAC_DPRINTF(AAC_D_IO, ("%s: aac_sync_fib: IO error\n",
1840 				       sc->aac_dev.dv_xname));
1841 		printf("aac_sync_fib 2\n");
1842 		return(EIO);
1843 	}
1844 
1845 	return (0);
1846 }
1847 
1848 /*****************************************************************************
1849  * Adapter-space FIB queue manipulation
1850  *
1851  * Note that the queue implementation here is a little funky; neither the PI or
1852  * CI will ever be zero.  This behaviour is a controller feature.
1853  */
1854 static struct {
1855 	int size;
1856 	int notify;
1857 } aac_qinfo[] = {
1858 	{ AAC_HOST_NORM_CMD_ENTRIES, AAC_DB_COMMAND_NOT_FULL },
1859 	{ AAC_HOST_HIGH_CMD_ENTRIES, 0 },
1860 	{ AAC_ADAP_NORM_CMD_ENTRIES, AAC_DB_COMMAND_READY },
1861 	{ AAC_ADAP_HIGH_CMD_ENTRIES, 0 },
1862 	{ AAC_HOST_NORM_RESP_ENTRIES, AAC_DB_RESPONSE_NOT_FULL },
1863 	{ AAC_HOST_HIGH_RESP_ENTRIES, 0 },
1864 	{ AAC_ADAP_NORM_RESP_ENTRIES, AAC_DB_RESPONSE_READY },
1865 	{ AAC_ADAP_HIGH_RESP_ENTRIES, 0 }
1866 };
1867 
1868 /*
1869  * Atomically insert an entry into the nominated queue, returns 0 on success
1870  * or EBUSY if the queue is full.
1871  *
1872  * Note: it would be more efficient to defer notifying the controller in
1873  *	 the case where we may be inserting several entries in rapid
1874  *	 succession, but implementing this usefully may be difficult
1875  *	 (it would involve a separate queue/notify interface).
1876  */
1877 int
1878 aac_enqueue_fib(struct aac_softc *sc, int queue, struct aac_command *cm)
1879 {
1880 	u_int32_t pi, ci;
1881 	int error;
1882 	u_int32_t fib_size;
1883 	u_int32_t fib_addr;
1884 
1885 	fib_size = cm->cm_fib->Header.Size;
1886 	fib_addr = cm->cm_fib->Header.ReceiverFibAddress;
1887 
1888 	/* get the producer/consumer indices */
1889 	pi = sc->aac_queues->qt_qindex[queue][AAC_PRODUCER_INDEX];
1890 	ci = sc->aac_queues->qt_qindex[queue][AAC_CONSUMER_INDEX];
1891 
1892 	/* wrap the queue? */
1893 	if (pi >= aac_qinfo[queue].size)
1894 		pi = 0;
1895 
1896 	/* check for queue full */
1897 	if ((pi + 1) == ci) {
1898 		error = EBUSY;
1899 		goto out;
1900 	}
1901 
1902 	/* populate queue entry */
1903 	(sc->aac_qentries[queue] + pi)->aq_fib_size = fib_size;
1904 	(sc->aac_qentries[queue] + pi)->aq_fib_addr = fib_addr;
1905 
1906 	/* update producer index */
1907 	sc->aac_queues->qt_qindex[queue][AAC_PRODUCER_INDEX] = pi + 1;
1908 
1909 	/*
1910 	 * To avoid a race with its completion interrupt, place this command on
1911 	 * the busy queue prior to advertising it to the controller.
1912 	 */
1913 	aac_enqueue_busy(cm);
1914 
1915 	/* notify the adapter if we know how */
1916 	if (aac_qinfo[queue].notify != 0)
1917 		AAC_QNOTIFY(sc, aac_qinfo[queue].notify);
1918 
1919 	error = 0;
1920 
1921 out:
1922 	return (error);
1923 }
1924 
1925 /*
1926  * Atomically remove one entry from the nominated queue, returns 0 on success
1927  * or ENOENT if the queue is empty.
1928  */
1929 int
1930 aac_dequeue_fib(struct aac_softc *sc, int queue, u_int32_t *fib_size,
1931 		struct aac_fib **fib_addr)
1932 {
1933 	u_int32_t pi, ci;
1934 	u_int32_t fib_index;
1935 	int notify;
1936 	int error;
1937 
1938 	/* get the producer/consumer indices */
1939 	pi = sc->aac_queues->qt_qindex[queue][AAC_PRODUCER_INDEX];
1940 	ci = sc->aac_queues->qt_qindex[queue][AAC_CONSUMER_INDEX];
1941 
1942 	/* check for queue empty */
1943 	if (ci == pi) {
1944 		error = ENOENT;
1945 		goto out;
1946 	}
1947 
1948 	/* wrap the pi so the following test works */
1949 	if (pi >= aac_qinfo[queue].size)
1950 		pi = 0;
1951 
1952 	notify = 0;
1953 	if (ci == pi + 1)
1954 		notify++;
1955 
1956 	/* wrap the queue? */
1957 	if (ci >= aac_qinfo[queue].size)
1958 		ci = 0;
1959 
1960 	/* fetch the entry */
1961 	*fib_size = (sc->aac_qentries[queue] + ci)->aq_fib_size;
1962 
1963 	switch (queue) {
1964 	case AAC_HOST_NORM_CMD_QUEUE:
1965 	case AAC_HOST_HIGH_CMD_QUEUE:
1966 		/*
1967 		 * The aq_fib_addr is only 32 bits wide so it can't be counted
1968 		 * on to hold an address.  For AIF's, the adapter assumes
1969 		 * that it's giving us an address into the array of AIF fibs.
1970 		 * Therefore, we have to convert it to an index.
1971 		 */
1972 		fib_index = (sc->aac_qentries[queue] + ci)->aq_fib_addr /
1973 			sizeof(struct aac_fib);
1974 		*fib_addr = &sc->aac_common->ac_fibs[fib_index];
1975 		break;
1976 
1977 	case AAC_HOST_NORM_RESP_QUEUE:
1978 	case AAC_HOST_HIGH_RESP_QUEUE:
1979 	{
1980 		struct aac_command *cm;
1981 
1982 		/*
1983 		 * As above, an index is used instead of an actual address.
1984 		 * Gotta shift the index to account for the fast response
1985 		 * bit.  No other correction is needed since this value was
1986 		 * originally provided by the driver via the SenderFibAddress
1987 		 * field.
1988 		 */
1989 		fib_index = (sc->aac_qentries[queue] + ci)->aq_fib_addr;
1990 		cm = sc->aac_commands + (fib_index >> 1);
1991 		*fib_addr = cm->cm_fib;
1992 
1993 		/*
1994 		 * Is this a fast response? If it is, update the fib fields in
1995 		 * local memory since the whole fib isn't DMA'd back up.
1996 		 */
1997 		if (fib_index & 0x01) {
1998 			(*fib_addr)->Header.XferState |= AAC_FIBSTATE_DONEADAP;
1999 			*((u_int32_t*)((*fib_addr)->data)) = AAC_ERROR_NORMAL;
2000 		}
2001 		break;
2002 	}
2003 	default:
2004 		panic("Invalid queue in aac_dequeue_fib()");
2005 		break;
2006 	}
2007 
2008 
2009 	/* update consumer index */
2010 	sc->aac_queues->qt_qindex[queue][AAC_CONSUMER_INDEX] = ci + 1;
2011 
2012 	/* if we have made the queue un-full, notify the adapter */
2013 	if (notify && (aac_qinfo[queue].notify != 0))
2014 		AAC_QNOTIFY(sc, aac_qinfo[queue].notify);
2015 	error = 0;
2016 
2017 out:
2018 	return (error);
2019 }
2020 
2021 /*
2022  * Put our response to an Adapter Initialed Fib on the response queue
2023  */
2024 int
2025 aac_enqueue_response(struct aac_softc *sc, int queue, struct aac_fib *fib)
2026 {
2027 	u_int32_t pi, ci;
2028 	int error;
2029 	u_int32_t fib_size;
2030 	u_int32_t fib_addr;
2031 
2032 	/* Tell the adapter where the FIB is */
2033 	fib_size = fib->Header.Size;
2034 	fib_addr = fib->Header.SenderFibAddress;
2035 	fib->Header.ReceiverFibAddress = fib_addr;
2036 
2037 	/* get the producer/consumer indices */
2038 	pi = sc->aac_queues->qt_qindex[queue][AAC_PRODUCER_INDEX];
2039 	ci = sc->aac_queues->qt_qindex[queue][AAC_CONSUMER_INDEX];
2040 
2041 	/* wrap the queue? */
2042 	if (pi >= aac_qinfo[queue].size)
2043 		pi = 0;
2044 
2045 	/* check for queue full */
2046 	if ((pi + 1) == ci) {
2047 		error = EBUSY;
2048 		goto out;
2049 	}
2050 
2051 	/* populate queue entry */
2052 	(sc->aac_qentries[queue] + pi)->aq_fib_size = fib_size;
2053 	(sc->aac_qentries[queue] + pi)->aq_fib_addr = fib_addr;
2054 
2055 	/* update producer index */
2056 	sc->aac_queues->qt_qindex[queue][AAC_PRODUCER_INDEX] = pi + 1;
2057 
2058 	/* notify the adapter if we know how */
2059 	if (aac_qinfo[queue].notify != 0)
2060 		AAC_QNOTIFY(sc, aac_qinfo[queue].notify);
2061 
2062 	error = 0;
2063 
2064 out:
2065 	return(error);
2066 }
2067 
2068 void
2069 aac_command_timeout(struct aac_command *cm)
2070 {
2071 	struct aac_softc *sc = cm->cm_sc;
2072 
2073 	printf("%s: COMMAND %p (flags=%#x) TIMEOUT AFTER %d SECONDS\n",
2074 	       sc->aac_dev.dv_xname, cm, cm->cm_flags,
2075 	       (int)(time_uptime - cm->cm_timestamp));
2076 
2077 	if (cm->cm_flags & AAC_CMD_TIMEDOUT)
2078 		return;
2079 
2080 	cm->cm_flags |= AAC_CMD_TIMEDOUT;
2081 
2082 	AAC_PRINT_FIB(sc, cm->cm_fib);
2083 
2084 	if (cm->cm_flags & AAC_ON_AACQ_BIO) {
2085 		struct scsi_xfer *xs = cm->cm_private;
2086 		int s = splbio();
2087 		xs->error = XS_DRIVER_STUFFUP;
2088 		splx(s);
2089 		scsi_done(xs);
2090 
2091 		aac_remove_bio(cm);
2092 		aac_unmap_command(cm);
2093 	}
2094 }
2095 
2096 void
2097 aac_timeout(struct aac_softc *sc)
2098 {
2099 	struct aac_command *cm;
2100 	time_t deadline;
2101 
2102 	/*
2103 	 * Traverse the busy command list and timeout any commands
2104 	 * that are past their deadline.
2105 	 */
2106 	deadline = time_uptime - AAC_CMD_TIMEOUT;
2107 	TAILQ_FOREACH(cm, &sc->aac_busy, cm_link) {
2108 		if (cm->cm_timestamp  < deadline)
2109 			aac_command_timeout(cm);
2110 	}
2111 }
2112 
2113 /*
2114  * Interface Function Vectors
2115  */
2116 
2117 /*
2118  * Read the current firmware status word.
2119  */
2120 int
2121 aac_sa_get_fwstatus(struct aac_softc *sc)
2122 {
2123 	return (AAC_GETREG4(sc, AAC_SA_FWSTATUS));
2124 }
2125 
2126 int
2127 aac_rx_get_fwstatus(struct aac_softc *sc)
2128 {
2129 	return (AAC_GETREG4(sc, AAC_RX_FWSTATUS));
2130 }
2131 
2132 int
2133 aac_fa_get_fwstatus(struct aac_softc *sc)
2134 {
2135  	return (AAC_GETREG4(sc, AAC_FA_FWSTATUS));
2136 }
2137 
2138 int
2139 aac_rkt_get_fwstatus(struct aac_softc *sc)
2140 {
2141 	return(AAC_GETREG4(sc, AAC_RKT_FWSTATUS));
2142 }
2143 
2144 /*
2145  * Notify the controller of a change in a given queue
2146  */
2147 
2148 void
2149 aac_sa_qnotify(struct aac_softc *sc, int qbit)
2150 {
2151 	AAC_SETREG2(sc, AAC_SA_DOORBELL1_SET, qbit);
2152 }
2153 
2154 void
2155 aac_rx_qnotify(struct aac_softc *sc, int qbit)
2156 {
2157 	AAC_SETREG4(sc, AAC_RX_IDBR, qbit);
2158 }
2159 
2160 void
2161 aac_fa_qnotify(struct aac_softc *sc, int qbit)
2162 {
2163 	AAC_SETREG2(sc, AAC_FA_DOORBELL1, qbit);
2164 	AAC_FA_HACK(sc);
2165 }
2166 
2167 void
2168 aac_rkt_qnotify(struct aac_softc *sc, int qbit)
2169 {
2170 	AAC_SETREG4(sc, AAC_RKT_IDBR, qbit);
2171 }
2172 
2173 /*
2174  * Get the interrupt reason bits
2175  */
2176 int
2177 aac_sa_get_istatus(struct aac_softc *sc)
2178 {
2179 	return (AAC_GETREG2(sc, AAC_SA_DOORBELL0));
2180 }
2181 
2182 int
2183 aac_rx_get_istatus(struct aac_softc *sc)
2184 {
2185 	return (AAC_GETREG4(sc, AAC_RX_ODBR));
2186 }
2187 
2188 int
2189 aac_fa_get_istatus(struct aac_softc *sc)
2190 {
2191 	return (AAC_GETREG2(sc, AAC_FA_DOORBELL0));
2192 }
2193 
2194 int
2195 aac_rkt_get_istatus(struct aac_softc *sc)
2196 {
2197 	return(AAC_GETREG4(sc, AAC_RKT_ODBR));
2198 }
2199 
2200 /*
2201  * Clear some interrupt reason bits
2202  */
2203 void
2204 aac_sa_clear_istatus(struct aac_softc *sc, int mask)
2205 {
2206 	AAC_SETREG2(sc, AAC_SA_DOORBELL0_CLEAR, mask);
2207 }
2208 
2209 void
2210 aac_rx_clear_istatus(struct aac_softc *sc, int mask)
2211 {
2212 	AAC_SETREG4(sc, AAC_RX_ODBR, mask);
2213 }
2214 
2215 void
2216 aac_fa_clear_istatus(struct aac_softc *sc, int mask)
2217 {
2218 	AAC_SETREG2(sc, AAC_FA_DOORBELL0_CLEAR, mask);
2219 	AAC_FA_HACK(sc);
2220 }
2221 
2222 void
2223 aac_rkt_clear_istatus(struct aac_softc *sc, int mask)
2224 {
2225 	AAC_SETREG4(sc, AAC_RKT_ODBR, mask);
2226 }
2227 
2228 /*
2229  * Populate the mailbox and set the command word
2230  */
2231 void
2232 aac_sa_set_mailbox(struct aac_softc *sc, u_int32_t command, u_int32_t arg0,
2233 		   u_int32_t arg1, u_int32_t arg2, u_int32_t arg3)
2234 {
2235 	AAC_SETREG4(sc, AAC_SA_MAILBOX, command);
2236 	AAC_SETREG4(sc, AAC_SA_MAILBOX + 4, arg0);
2237 	AAC_SETREG4(sc, AAC_SA_MAILBOX + 8, arg1);
2238 	AAC_SETREG4(sc, AAC_SA_MAILBOX + 12, arg2);
2239 	AAC_SETREG4(sc, AAC_SA_MAILBOX + 16, arg3);
2240 }
2241 
2242 void
2243 aac_rx_set_mailbox(struct aac_softc *sc, u_int32_t command, u_int32_t arg0,
2244 		   u_int32_t arg1, u_int32_t arg2, u_int32_t arg3)
2245 {
2246 	AAC_SETREG4(sc, AAC_RX_MAILBOX, command);
2247 	AAC_SETREG4(sc, AAC_RX_MAILBOX + 4, arg0);
2248 	AAC_SETREG4(sc, AAC_RX_MAILBOX + 8, arg1);
2249 	AAC_SETREG4(sc, AAC_RX_MAILBOX + 12, arg2);
2250 	AAC_SETREG4(sc, AAC_RX_MAILBOX + 16, arg3);
2251 }
2252 
2253 void
2254 aac_fa_set_mailbox(struct aac_softc *sc, u_int32_t command, u_int32_t arg0,
2255 		   u_int32_t arg1, u_int32_t arg2, u_int32_t arg3)
2256 {
2257 	AAC_SETREG4(sc, AAC_FA_MAILBOX, command);
2258 	AAC_FA_HACK(sc);
2259 	AAC_SETREG4(sc, AAC_FA_MAILBOX + 4, arg0);
2260 	AAC_FA_HACK(sc);
2261 	AAC_SETREG4(sc, AAC_FA_MAILBOX + 8, arg1);
2262 	AAC_FA_HACK(sc);
2263 	AAC_SETREG4(sc, AAC_FA_MAILBOX + 12, arg2);
2264 	AAC_FA_HACK(sc);
2265 	AAC_SETREG4(sc, AAC_FA_MAILBOX + 16, arg3);
2266 	AAC_FA_HACK(sc);
2267 }
2268 
2269 void
2270 aac_rkt_set_mailbox(struct aac_softc *sc, u_int32_t command, u_int32_t arg0,
2271 		    u_int32_t arg1, u_int32_t arg2, u_int32_t arg3)
2272 {
2273 	AAC_SETREG4(sc, AAC_RKT_MAILBOX, command);
2274 	AAC_SETREG4(sc, AAC_RKT_MAILBOX + 4, arg0);
2275 	AAC_SETREG4(sc, AAC_RKT_MAILBOX + 8, arg1);
2276 	AAC_SETREG4(sc, AAC_RKT_MAILBOX + 12, arg2);
2277 	AAC_SETREG4(sc, AAC_RKT_MAILBOX + 16, arg3);
2278 }
2279 
2280 /*
2281  * Fetch the immediate command status word
2282  */
2283 int
2284 aac_sa_get_mailbox(struct aac_softc *sc, int mb)
2285 {
2286 	return (AAC_GETREG4(sc, AAC_SA_MAILBOX + (mb * 4)));
2287 }
2288 
2289 int
2290 aac_rx_get_mailbox(struct aac_softc *sc, int mb)
2291 {
2292 	return (AAC_GETREG4(sc, AAC_RX_MAILBOX + (mb * 4)));
2293 }
2294 
2295 int
2296 aac_fa_get_mailbox(struct aac_softc *sc, int mb)
2297 {
2298 	return (AAC_GETREG4(sc, AAC_FA_MAILBOX + (mb * 4)));
2299 }
2300 
2301 int
2302 aac_rkt_get_mailbox(struct aac_softc *sc, int mb)
2303 {
2304 	return(AAC_GETREG4(sc, AAC_RKT_MAILBOX + (mb * 4)));
2305 }
2306 
2307 /*
2308  * Set/clear interrupt masks
2309  */
2310 void
2311 aac_sa_set_interrupts(struct aac_softc *sc, int enable)
2312 {
2313 	AAC_DPRINTF(AAC_D_INTR, ("%s: %sable interrupts\n",
2314 				 sc->aac_dev.dv_xname, enable ? "en" : "dis"));
2315 
2316 	if (enable)
2317 		AAC_SETREG2((sc), AAC_SA_MASK0_CLEAR, AAC_DB_INTERRUPTS);
2318 	else
2319 		AAC_SETREG2((sc), AAC_SA_MASK0_SET, ~0);
2320 }
2321 
2322 void
2323 aac_rx_set_interrupts(struct aac_softc *sc, int enable)
2324 {
2325 	AAC_DPRINTF(AAC_D_INTR, ("%s: %sable interrupts",
2326 				 sc->aac_dev.dv_xname, enable ? "en" : "dis"));
2327 
2328 	if (enable)
2329 		AAC_SETREG4(sc, AAC_RX_OIMR, ~AAC_DB_INTERRUPTS);
2330 	else
2331 		AAC_SETREG4(sc, AAC_RX_OIMR, ~0);
2332 }
2333 
2334 void
2335 aac_fa_set_interrupts(struct aac_softc *sc, int enable)
2336 {
2337 	AAC_DPRINTF(AAC_D_INTR, ("%s: %sable interrupts",
2338 				 sc->aac_dev.dv_xname, enable ? "en" : "dis"));
2339 
2340 	if (enable) {
2341 		AAC_SETREG2((sc), AAC_FA_MASK0_CLEAR, AAC_DB_INTERRUPTS);
2342 		AAC_FA_HACK(sc);
2343 	} else {
2344 		AAC_SETREG2((sc), AAC_FA_MASK0, ~0);
2345 		AAC_FA_HACK(sc);
2346 	}
2347 }
2348 
2349 void
2350 aac_rkt_set_interrupts(struct aac_softc *sc, int enable)
2351 {
2352 	AAC_DPRINTF(AAC_D_INTR, ("%s: %sable interrupts",
2353 				 sc->aac_dev.dv_xname, enable ? "en" : "dis"));
2354 
2355 	if (enable)
2356 		AAC_SETREG4(sc, AAC_RKT_OIMR, ~AAC_DB_INTERRUPTS);
2357 	else
2358 		AAC_SETREG4(sc, AAC_RKT_OIMR, ~0);
2359 }
2360 
2361 void
2362 aac_eval_mapping(size, cyls, heads, secs)
2363 	u_int32_t size;
2364 	int *cyls, *heads, *secs;
2365 {
2366 	*cyls = size / AAC_HEADS / AAC_SECS;
2367 	if (*cyls < AAC_MAXCYLS) {
2368 		*heads = AAC_HEADS;
2369 		*secs = AAC_SECS;
2370 	} else {
2371 		/* Too high for 64 * 32 */
2372 		*cyls = size / AAC_MEDHEADS / AAC_MEDSECS;
2373 		if (*cyls < AAC_MAXCYLS) {
2374 			*heads = AAC_MEDHEADS;
2375 			*secs = AAC_MEDSECS;
2376 		} else {
2377 			/* Too high for 127 * 63 */
2378 			*cyls = size / AAC_BIGHEADS / AAC_BIGSECS;
2379 			*heads = AAC_BIGHEADS;
2380 			*secs = AAC_BIGSECS;
2381 		}
2382 	}
2383 }
2384 
2385 void
2386 aac_copy_internal_data(struct scsi_xfer *xs, u_int8_t *data, size_t size)
2387 {
2388 	struct aac_softc *sc = xs->sc_link->adapter_softc;
2389 	size_t copy_cnt;
2390 
2391 	AAC_DPRINTF(AAC_D_MISC, ("%s: aac_copy_internal_data\n",
2392 				 sc->aac_dev.dv_xname));
2393 
2394 	if (!xs->datalen)
2395 		printf("%s: uio move not yet supported\n",
2396 		       sc->aac_dev.dv_xname);
2397 	else {
2398 		copy_cnt = MIN(size, xs->datalen);
2399 		bcopy(data, xs->data, copy_cnt);
2400 	}
2401 }
2402 
2403 /* Emulated SCSI operation on cache device */
2404 void
2405 aac_internal_cache_cmd(struct scsi_xfer *xs)
2406 {
2407 	struct scsi_link *link = xs->sc_link;
2408 	struct aac_softc *sc = link->adapter_softc;
2409 	struct scsi_inquiry_data inq;
2410 	struct scsi_sense_data sd;
2411 	struct scsi_read_cap_data rcd;
2412 	u_int8_t target = link->target;
2413 
2414 	AAC_DPRINTF(AAC_D_CMD, ("aac_internal_cache_cmd: ",
2415 				sc->aac_dev.dv_xname));
2416 
2417 	switch (xs->cmd->opcode) {
2418 	case TEST_UNIT_READY:
2419 	case START_STOP:
2420 #if 0
2421 	case VERIFY:
2422 #endif
2423 		AAC_DPRINTF(AAC_D_CMD, ("opc %#x tgt %d ", xs->cmd->opcode,
2424 		    target));
2425 		break;
2426 
2427 	case REQUEST_SENSE:
2428 		AAC_DPRINTF(AAC_D_CMD, ("REQUEST SENSE tgt %d ", target));
2429 		bzero(&sd, sizeof sd);
2430 		sd.error_code = SSD_ERRCODE_CURRENT;
2431 		sd.segment = 0;
2432 		sd.flags = SKEY_NO_SENSE;
2433 		aac_enc32(sd.info, 0);
2434 		sd.extra_len = 0;
2435 		aac_copy_internal_data(xs, (u_int8_t *)&sd, sizeof sd);
2436 		break;
2437 
2438 	case INQUIRY:
2439 		AAC_DPRINTF(AAC_D_CMD, ("INQUIRY tgt %d devtype %x ", target,
2440 		    sc->aac_hdr[target].hd_devtype));
2441 		bzero(&inq, sizeof inq);
2442 		/* XXX How do we detect removable/CD-ROM devices?  */
2443 		inq.device = T_DIRECT;
2444 		inq.dev_qual2 = 0;
2445 		inq.version = 2;
2446 		inq.response_format = 2;
2447 		inq.additional_length = 32;
2448 		inq.flags |= SID_CmdQue;
2449 		strlcpy(inq.vendor, "Adaptec", sizeof inq.vendor);
2450 		snprintf(inq.product, sizeof inq.product, "Container #%02d",
2451 		    target);
2452 		strlcpy(inq.revision, "   ", sizeof inq.revision);
2453 		aac_copy_internal_data(xs, (u_int8_t *)&inq, sizeof inq);
2454 		break;
2455 
2456 	case READ_CAPACITY:
2457 		AAC_DPRINTF(AAC_D_CMD, ("READ CAPACITY tgt %d ", target));
2458 		bzero(&rcd, sizeof rcd);
2459 		_lto4b(sc->aac_hdr[target].hd_size - 1, rcd.addr);
2460 		_lto4b(AAC_BLOCK_SIZE, rcd.length);
2461 		aac_copy_internal_data(xs, (u_int8_t *)&rcd, sizeof rcd);
2462 		break;
2463 
2464 	default:
2465 		AAC_DPRINTF(AAC_D_CMD, ("\n"));
2466 		printf("aac_internal_cache_cmd got bad opcode: %#x\n",
2467 		    xs->cmd->opcode);
2468 		xs->error = XS_DRIVER_STUFFUP;
2469 		return;
2470 	}
2471 
2472 	xs->error = XS_NOERROR;
2473 }
2474 
2475 void
2476 aac_scsi_cmd(struct scsi_xfer *xs)
2477 {
2478 	struct scsi_link *link = xs->sc_link;
2479 	struct aac_softc *sc = link->adapter_softc;
2480 	u_int8_t target = link->target;
2481 	struct aac_command *cm;
2482 	u_int32_t blockno, blockcnt;
2483 	struct scsi_rw *rw;
2484 	struct scsi_rw_big *rwb;
2485 	int s;
2486 
2487 	s = splbio();
2488 
2489 	xs->error = XS_NOERROR;
2490 
2491 	if (target >= AAC_MAX_CONTAINERS || !sc->aac_hdr[target].hd_present ||
2492 	    link->lun != 0) {
2493 		/*
2494 		 * XXX Should be XS_SENSE but that would require setting up a
2495 		 * faked sense too.
2496 		 */
2497 		splx(s);
2498 		xs->error = XS_DRIVER_STUFFUP;
2499 		scsi_done(xs);
2500 		return;
2501 	}
2502 
2503 	AAC_DPRINTF(AAC_D_CMD, ("%s: aac_scsi_cmd: ", sc->aac_dev.dv_xname));
2504 
2505 	xs->error = XS_NOERROR;
2506 	cm = NULL;
2507 	link = xs->sc_link;
2508 	target = link->target;
2509 
2510 	switch (xs->cmd->opcode) {
2511 	case TEST_UNIT_READY:
2512 	case REQUEST_SENSE:
2513 	case INQUIRY:
2514 	case START_STOP:
2515 	case READ_CAPACITY:
2516 #if 0
2517 	case VERIFY:
2518 #endif
2519 		aac_internal_cache_cmd(xs);
2520 		scsi_done(xs);
2521 		goto ready;
2522 
2523 	case PREVENT_ALLOW:
2524 		AAC_DPRINTF(AAC_D_CMD, ("PREVENT/ALLOW "));
2525 		/* XXX Not yet implemented */
2526 		xs->error = XS_NOERROR;
2527 		scsi_done(xs);
2528 		goto ready;
2529 
2530 	case SYNCHRONIZE_CACHE:
2531 		AAC_DPRINTF(AAC_D_CMD, ("SYNCHRONIZE_CACHE "));
2532 		/* XXX Not yet implemented */
2533 		xs->error = XS_NOERROR;
2534 		scsi_done(xs);
2535 		goto ready;
2536 
2537 	default:
2538 		AAC_DPRINTF(AAC_D_CMD, ("unknown opc %#x ", xs->cmd->opcode));
2539 		/* XXX Not yet implemented */
2540 		xs->error = XS_DRIVER_STUFFUP;
2541 		scsi_done(xs);
2542 		goto ready;
2543 
2544 	case READ_COMMAND:
2545 	case READ_BIG:
2546 	case WRITE_COMMAND:
2547 	case WRITE_BIG:
2548 		AAC_DPRINTF(AAC_D_CMD, ("rw opc %#x ", xs->cmd->opcode));
2549 
2550 		/* A read or write operation. */
2551 		if (xs->cmdlen == 6) {
2552 			rw = (struct scsi_rw *)xs->cmd;
2553 			blockno = _3btol(rw->addr) &
2554 				(SRW_TOPADDR << 16 | 0xffff);
2555 			blockcnt = rw->length ? rw->length : 0x100;
2556 		} else {
2557 			rwb = (struct scsi_rw_big *)xs->cmd;
2558 			blockno = _4btol(rwb->addr);
2559 			blockcnt = _2btol(rwb->length);
2560 		}
2561 
2562 		AAC_DPRINTF(AAC_D_CMD, ("blkno=%d bcount=%d ",
2563 					xs->cmd->opcode, blockno, blockcnt));
2564 
2565 		if (blockno >= sc->aac_hdr[target].hd_size ||
2566 		    blockno + blockcnt > sc->aac_hdr[target].hd_size) {
2567 			AAC_DPRINTF(AAC_D_CMD, ("\n"));
2568 			printf("%s: out of bounds %u-%u >= %u\n",
2569 			       sc->aac_dev.dv_xname, blockno,
2570 			       blockcnt, sc->aac_hdr[target].hd_size);
2571 			/*
2572 			 * XXX Should be XS_SENSE but that
2573 			 * would require setting up a faked
2574 			 * sense too.
2575 			 */
2576 			xs->error = XS_DRIVER_STUFFUP;
2577 			scsi_done(xs);
2578 			goto ready;
2579 		}
2580 
2581 		cm = xs->io;
2582 		aac_scrub_command(cm);
2583 
2584 		/* fill out the command */
2585 		cm->cm_data = (void *)xs->data;
2586 		cm->cm_datalen = xs->datalen;
2587 		cm->cm_complete = aac_bio_complete;
2588 		cm->cm_private = xs;
2589 		cm->cm_timestamp = time_uptime;
2590 		cm->cm_queue = AAC_ADAP_NORM_CMD_QUEUE;
2591 		cm->cm_blkno = blockno;
2592 		cm->cm_bcount = blockcnt;
2593 
2594 		AAC_DPRINTF(AAC_D_CMD, ("\n"));
2595 		aac_enqueue_bio(cm);
2596 		aac_startio(sc);
2597 
2598 		/* XXX what if enqueue did not start a transfer? */
2599 		if (xs->flags & SCSI_POLL) {
2600 			if (!aac_wait_command(cm, xs->timeout))
2601 			{
2602 				printf("%s: command timed out\n",
2603 				       sc->aac_dev.dv_xname);
2604 				xs->error = XS_DRIVER_STUFFUP;
2605 				scsi_done(xs);
2606 				splx(s);
2607 				return;
2608 			}
2609 			scsi_done(xs);
2610 		}
2611 	}
2612 
2613  ready:
2614 	splx(s);
2615 	AAC_DPRINTF(AAC_D_CMD, ("%s: scsi_cmd complete\n",
2616 				sc->aac_dev.dv_xname));
2617 }
2618 
2619 /*
2620  * Debugging and Diagnostics
2621  */
2622 
2623 /*
2624  * Print some information about the controller.
2625  */
2626 void
2627 aac_describe_controller(struct aac_softc *sc)
2628 {
2629 	struct aac_fib *fib;
2630 	struct aac_adapter_info	*info;
2631 
2632 	aac_alloc_sync_fib(sc, &fib, 0);
2633 
2634 	fib->data[0] = 0;
2635 	if (aac_sync_fib(sc, RequestAdapterInfo, 0, fib, 1)) {
2636 		printf("%s: RequestAdapterInfo failed 2\n",
2637 		       sc->aac_dev.dv_xname);
2638 		aac_release_sync_fib(sc);
2639 		return;
2640 	}
2641 	info = (struct aac_adapter_info *)&fib->data[0];
2642 
2643 	printf("%s: %s %dMHz, %dMB cache memory, %s\n", sc->aac_dev.dv_xname,
2644 	       aac_describe_code(aac_cpu_variant, info->CpuVariant),
2645 	       info->ClockSpeed, info->BufferMem / (1024 * 1024),
2646 	       aac_describe_code(aac_battery_platform, info->batteryPlatform));
2647 
2648 	/* save the kernel revision structure for later use */
2649 	sc->aac_revision = info->KernelRevision;
2650 	printf("%s: Kernel %d.%d-%d, Build %d, S/N %6X\n",
2651 	       sc->aac_dev.dv_xname,
2652 	       info->KernelRevision.external.comp.major,
2653 	       info->KernelRevision.external.comp.minor,
2654 	       info->KernelRevision.external.comp.dash,
2655 	       info->KernelRevision.buildNumber,
2656 	       (u_int32_t)(info->SerialNumber & 0xffffff));
2657 
2658 	aac_release_sync_fib(sc);
2659 
2660 #if 0
2661 	if (1 || bootverbose) {
2662 		device_printf(sc->aac_dev, "Supported Options=%b\n",
2663 			      sc->supported_options,
2664 			      "\20"
2665 			      "\1SNAPSHOT"
2666 			      "\2CLUSTERS"
2667 			      "\3WCACHE"
2668 			      "\4DATA64"
2669 			      "\5HOSTTIME"
2670 			      "\6RAID50"
2671 			      "\7WINDOW4GB"
2672 			      "\10SCSIUPGD"
2673 			      "\11SOFTERR"
2674 			      "\12NORECOND"
2675 			      "\13SGMAP64"
2676 			      "\14ALARM"
2677 			      "\15NONDASD");
2678 	}
2679 #endif
2680 }
2681 
2682 /*
2683  * Look up a text description of a numeric error code and return a pointer to
2684  * same.
2685  */
2686 char *
2687 aac_describe_code(struct aac_code_lookup *table, u_int32_t code)
2688 {
2689 	int i;
2690 
2691 	for (i = 0; table[i].string != NULL; i++)
2692 		if (table[i].code == code)
2693 			return(table[i].string);
2694 	return(table[i + 1].string);
2695 }
2696 
2697 #ifdef AAC_DEBUG
2698 /*
2699  * Print a FIB
2700  */
2701 void
2702 aac_print_fib(struct aac_softc *sc, struct aac_fib *fib, const char *caller)
2703 {
2704 	printf("%s: FIB @ %p\n", caller, fib);
2705 	printf("  XferState %b\n", fib->Header.XferState, "\20"
2706 	    "\1HOSTOWNED"
2707 	    "\2ADAPTEROWNED"
2708 	    "\3INITIALISED"
2709 	    "\4EMPTY"
2710 	    "\5FROMPOOL"
2711 	    "\6FROMHOST"
2712 	    "\7FROMADAP"
2713 	    "\10REXPECTED"
2714 	    "\11RNOTEXPECTED"
2715 	    "\12DONEADAP"
2716 	    "\13DONEHOST"
2717 	    "\14HIGH"
2718 	    "\15NORM"
2719 	    "\16ASYNC"
2720 	    "\17PAGEFILEIO"
2721 	    "\20SHUTDOWN"
2722 	    "\21LAZYWRITE"
2723 	    "\22ADAPMICROFIB"
2724 	    "\23BIOSFIB"
2725 	    "\24FAST_RESPONSE"
2726 	    "\25APIFIB\n");
2727 	printf("  Command         %d\n", fib->Header.Command);
2728 	printf("  StructType      %d\n", fib->Header.StructType);
2729 	printf("  Flags           0x%x\n", fib->Header.Flags);
2730 	printf("  Size            %d\n", fib->Header.Size);
2731 	printf("  SenderSize      %d\n", fib->Header.SenderSize);
2732 	printf("  SenderAddress   0x%x\n", fib->Header.SenderFibAddress);
2733 	printf("  ReceiverAddress 0x%x\n", fib->Header.ReceiverFibAddress);
2734 	printf("  SenderData      0x%x\n", fib->Header.SenderData);
2735 	switch(fib->Header.Command) {
2736 	case ContainerCommand: {
2737 		struct aac_blockread *br = (struct aac_blockread *)fib->data;
2738 		struct aac_blockwrite *bw = (struct aac_blockwrite *)fib->data;
2739 		struct aac_sg_table *sg = NULL;
2740 		int i;
2741 
2742 		if (br->Command == VM_CtBlockRead) {
2743 			printf("  BlockRead: container %d  0x%x/%d\n",
2744 			    br->ContainerId, br->BlockNumber, br->ByteCount);
2745 			    sg = &br->SgMap;
2746 		}
2747 		if (bw->Command == VM_CtBlockWrite) {
2748 			printf("  BlockWrite: container %d  0x%x/%d (%s)\n",
2749 			    bw->ContainerId, bw->BlockNumber, bw->ByteCount,
2750 			    bw->Stable == CSTABLE ? "stable" : "unstable");
2751 			sg = &bw->SgMap;
2752 		}
2753 		if (sg != NULL) {
2754 			printf("  %d s/g entries\n", sg->SgCount);
2755 			for (i = 0; i < sg->SgCount; i++)
2756 				printf("  0x%08x/%d\n",
2757 				       sg->SgEntry[i].SgAddress,
2758 				       sg->SgEntry[i].SgByteCount);
2759 		}
2760 		break;
2761 	}
2762 	default:
2763 		printf("   %16D\n", fib->data, " ");
2764 		printf("   %16D\n", fib->data + 16, " ");
2765 	break;
2766 	}
2767 }
2768 
2769 /*
2770  * Describe an AIF we have received.
2771  */
2772 void
2773 aac_print_aif(struct aac_softc *sc, struct aac_aif_command *aif)
2774 {
2775 	printf("%s: print_aif: ", sc->aac_dev.dv_xname);
2776 
2777 	switch(aif->command) {
2778 	case AifCmdEventNotify:
2779 		printf("EventNotify(%d)\n", aif->seqNumber);
2780 
2781 		switch(aif->data.EN.type) {
2782 		case AifEnGeneric:
2783 			/* Generic notification */
2784 			printf("\t(Generic) %.*s\n",
2785 			       (int)sizeof(aif->data.EN.data.EG),
2786 			       aif->data.EN.data.EG.text);
2787 			break;
2788 		case AifEnTaskComplete:
2789 			/* Task has completed */
2790 			printf("\t(TaskComplete)\n");
2791 			break;
2792 		case AifEnConfigChange:
2793 			/* Adapter configuration change occurred */
2794 			printf("\t(ConfigChange)\n");
2795 			break;
2796 		case AifEnContainerChange:
2797 			/* Adapter specific container configuration change */
2798 			printf("\t(ContainerChange) container %d,%d\n",
2799 			       aif->data.EN.data.ECC.container[0],
2800 			       aif->data.EN.data.ECC.container[1]);
2801 			break;
2802 		case AifEnDeviceFailure:
2803 			/* SCSI device failed */
2804 			printf("\t(DeviceFailure) handle %d\n",
2805 			       aif->data.EN.data.EDF.deviceHandle);
2806 			break;
2807 		case AifEnMirrorFailover:
2808 			/* Mirror failover started */
2809 			printf("\t(MirrorFailover) container %d failed, "
2810 			       "migrating from slice %d to %d\n",
2811 			       aif->data.EN.data.EMF.container,
2812 			       aif->data.EN.data.EMF.failedSlice,
2813 			       aif->data.EN.data.EMF.creatingSlice);
2814 			break;
2815 		case AifEnContainerEvent:
2816 			/* Significant container event */
2817 			printf("\t(ContainerEvent) container %d event %d\n",
2818 			       aif->data.EN.data.ECE.container,
2819 			       aif->data.EN.data.ECE.eventType);
2820 			break;
2821 		case AifEnFileSystemChange:
2822 			/* File system changed */
2823 			printf("\t(FileSystemChange)\n");
2824 			break;
2825 		case AifEnConfigPause:
2826 			/* Container pause event */
2827 			printf("\t(ConfigPause)\n");
2828 			break;
2829 		case AifEnConfigResume:
2830 			/* Container resume event */
2831 			printf("\t(ConfigResume)\n");
2832 			break;
2833 		case AifEnFailoverChange:
2834 			/* Failover space assignment changed */
2835 			printf("\t(FailoverChange)\n");
2836 			break;
2837 		case AifEnRAID5RebuildDone:
2838 			/* RAID5 rebuild finished */
2839 			printf("\t(RAID5RebuildDone)\n");
2840 			break;
2841 		case AifEnEnclosureManagement:
2842 			/* Enclosure management event */
2843 			printf("\t(EnclosureManagement) EMPID %d unit %d "
2844 			       "event %d\n",
2845 			       aif->data.EN.data.EEE.empID,
2846 			       aif->data.EN.data.EEE.unitID,
2847 			       aif->data.EN.data.EEE.eventType);
2848 			break;
2849 		case AifEnBatteryEvent:
2850 			/* Significant NV battery event */
2851 			printf("\t(BatteryEvent) %d (state was %d, is %d\n",
2852 			       aif->data.EN.data.EBE.transition_type,
2853 			       aif->data.EN.data.EBE.current_state,
2854 			       aif->data.EN.data.EBE.prior_state);
2855 			break;
2856 		case AifEnAddContainer:
2857 			/* A new container was created. */
2858 			printf("\t(AddContainer)\n");
2859 			break;
2860 		case AifEnDeleteContainer:
2861 			/* A container was deleted. */
2862 			printf("\t(DeleteContainer)\n");
2863 			break;
2864 		case AifEnBatteryNeedsRecond:
2865 			/* The battery needs reconditioning */
2866 			printf("\t(BatteryNeedsRecond)\n");
2867 			break;
2868 		case AifEnClusterEvent:
2869 			/* Some cluster event */
2870 			printf("\t(ClusterEvent) event %d\n",
2871 			       aif->data.EN.data.ECLE.eventType);
2872 			break;
2873 		case AifEnDiskSetEvent:
2874 			/* A disk set event occured. */
2875 			printf("(DiskSetEvent) event %d "
2876 			       "diskset %lld creator %lld\n",
2877 			       aif->data.EN.data.EDS.eventType,
2878 			       aif->data.EN.data.EDS.DsNum,
2879 			       aif->data.EN.data.EDS.CreatorId);
2880 			break;
2881 		case AifDenMorphComplete:
2882 			/* A morph operation completed */
2883 			printf("\t(MorphComplete)\n");
2884 			break;
2885 		case AifDenVolumeExtendComplete:
2886 			/* A volume expand operation completed */
2887 			printf("\t(VolumeExtendComplete)\n");
2888 			break;
2889 		default:
2890 			printf("\t(%d)\n", aif->data.EN.type);
2891 			break;
2892 		}
2893 		break;
2894 	case AifCmdJobProgress:
2895 	{
2896 		char	*status;
2897 		switch(aif->data.PR[0].status) {
2898 		case AifJobStsSuccess:
2899 			status = "success"; break;
2900 		case AifJobStsFinished:
2901 			status = "finished"; break;
2902 		case AifJobStsAborted:
2903 			status = "aborted"; break;
2904 		case AifJobStsFailed:
2905 			status = "failed"; break;
2906 		case AifJobStsSuspended:
2907 			status = "suspended"; break;
2908 		case AifJobStsRunning:
2909 			status = "running"; break;
2910 		default:
2911 			status = "unknown status"; break;
2912 		}
2913 
2914 		printf("JobProgress (%d) - %s (%d, %d)\n",
2915 		       aif->seqNumber, status,
2916 		       aif->data.PR[0].currentTick,
2917 		       aif->data.PR[0].finalTick);
2918 
2919 		switch(aif->data.PR[0].jd.type) {
2920 		case AifJobScsiZero:
2921 			/* SCSI dev clear operation */
2922 			printf("\t(ScsiZero) handle %d\n",
2923 				      aif->data.PR[0].jd.client.scsi_dh);
2924 			break;
2925 		case AifJobScsiVerify:
2926 			/* SCSI device Verify operation NO REPAIR */
2927 			printf("\t(ScsiVerify) handle %d\n",
2928 				      aif->data.PR[0].jd.client.scsi_dh);
2929 			break;
2930 		case AifJobScsiExercise:
2931 			/* SCSI device Exercise operation */
2932 			printf("\t(ScsiExercise) handle %d\n",
2933 			       aif->data.PR[0].jd.client.scsi_dh);
2934 			break;
2935 		case AifJobScsiVerifyRepair:
2936 			/* SCSI device Verify operation WITH repair */
2937 			printf("\t(ScsiVerifyRepair) handle %d\n",
2938 			       aif->data.PR[0].jd.client.scsi_dh);
2939 			break;
2940 		case AifJobCtrZero:
2941 			/* Container clear operation */
2942 			printf("\t(ContainerZero) container %d\n",
2943 			       aif->data.PR[0].jd.client.container.src);
2944 			break;
2945 		case AifJobCtrCopy:
2946 			/* Container copy operation */
2947 			printf("\t(ContainerCopy) container %d to %d\n",
2948 			       aif->data.PR[0].jd.client.container.src,
2949 			       aif->data.PR[0].jd.client.container.dst);
2950 			break;
2951 		case AifJobCtrCreateMirror:
2952 			/* Container Create Mirror operation */
2953 			printf("\t(ContainerCreateMirror) container %d\n",
2954 			       aif->data.PR[0].jd.client.container.src);
2955 			/* XXX two containers? */
2956 			break;
2957 		case AifJobCtrMergeMirror:
2958 			/* Container Merge Mirror operation */
2959 			printf("\t(ContainerMergeMirror) container %d\n",
2960 			       aif->data.PR[0].jd.client.container.src);
2961 			/* XXX two containers? */
2962 			break;
2963 		case AifJobCtrScrubMirror:
2964 			/* Container Scrub Mirror operation */
2965 			printf("\t(ContainerScrubMirror) container %d\n",
2966 			       aif->data.PR[0].jd.client.container.src);
2967 			break;
2968 		case AifJobCtrRebuildRaid5:
2969 			/* Container Rebuild Raid5 operation */
2970 			printf("\t(ContainerRebuildRaid5) container %d\n",
2971 			       aif->data.PR[0].jd.client.container.src);
2972 			break;
2973 		case AifJobCtrScrubRaid5:
2974 			/* Container Scrub Raid5 operation */
2975 			printf("\t(ContainerScrubRaid5) container %d\n",
2976 			       aif->data.PR[0].jd.client.container.src);
2977 			break;
2978 		case AifJobCtrMorph:
2979 			/* Container morph operation */
2980 			printf("\t(ContainerMorph) container %d\n",
2981 			       aif->data.PR[0].jd.client.container.src);
2982 			/* XXX two containers? */
2983 			break;
2984 		case AifJobCtrPartCopy:
2985 			/* Container Partition copy operation */
2986 			printf("\t(ContainerPartCopy) container %d to %d\n",
2987 			       aif->data.PR[0].jd.client.container.src,
2988 			       aif->data.PR[0].jd.client.container.dst);
2989 			break;
2990 		case AifJobCtrRebuildMirror:
2991 			/* Container Rebuild Mirror operation */
2992 			printf("\t(ContainerRebuildMirror) container %d\n",
2993 			       aif->data.PR[0].jd.client.container.src);
2994 			break;
2995 		case AifJobCtrCrazyCache:
2996 			/* crazy cache */
2997 			printf("\t(ContainerCrazyCache) container %d\n",
2998 			       aif->data.PR[0].jd.client.container.src);
2999 			/* XXX two containers? */
3000 			break;
3001 		case AifJobFsCreate:
3002 			/* File System Create operation */
3003 			printf("\t(FsCreate)\n");
3004 			break;
3005 		case AifJobFsVerify:
3006 			/* File System Verify operation */
3007 			printf("\t(FsVerivy)\n");
3008 			break;
3009 		case AifJobFsExtend:
3010 			/* File System Extend operation */
3011 			printf("\t(FsExtend)\n");
3012 			break;
3013 		case AifJobApiFormatNTFS:
3014 			/* Format a drive to NTFS */
3015 			printf("\t(FormatNTFS)\n");
3016 			break;
3017 		case AifJobApiFormatFAT:
3018 			/* Format a drive to FAT */
3019 			printf("\t(FormatFAT)\n");
3020 			break;
3021 		case AifJobApiUpdateSnapshot:
3022 			/* update the read/write half of a snapshot */
3023 			printf("\t(UpdateSnapshot)\n");
3024 			break;
3025 		case AifJobApiFormatFAT32:
3026 			/* Format a drive to FAT32 */
3027 			printf("\t(FormatFAT32)\n");
3028 			break;
3029 		case AifJobCtlContinuousCtrVerify:
3030 			/* Adapter operation */
3031 			printf("\t(ContinuousCtrVerify)\n");
3032 			break;
3033 		default:
3034 			printf("\t(%d)\n", aif->data.PR[0].jd.type);
3035 			break;
3036 		}
3037 		break;
3038 	}
3039 	case AifCmdAPIReport:
3040 		printf("APIReport (%d)\n", aif->seqNumber);
3041 		break;
3042 	case AifCmdDriverNotify:
3043 		printf("DriverNotify (%d)\n", aif->seqNumber);
3044 		break;
3045 	default:
3046 		printf("AIF %d (%d)\n", aif->command, aif->seqNumber);
3047 		break;
3048 	}
3049 }
3050 #endif
3051