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