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