aac.c revision 67428
1/*-
2 * Copyright (c) 2000 Michael Smith
3 * Copyright (c) 2000 BSDi
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 *	$FreeBSD: head/sys/dev/aac/aac.c 67428 2000-10-22 09:21:19Z scottl $
28 */
29
30/*
31 * Driver for the Adaptec 'FSA' family of PCI/SCSI RAID adapters.
32 */
33
34#include <sys/param.h>
35#include <sys/systm.h>
36#include <sys/malloc.h>
37#include <sys/kernel.h>
38
39#include <dev/aac/aac_compat.h>
40
41#include <sys/bus.h>
42#include <sys/conf.h>
43#include <sys/devicestat.h>
44#include <sys/disk.h>
45#include <sys/file.h>
46#include <sys/signalvar.h>
47
48#include <machine/bus_memio.h>
49#include <machine/bus.h>
50#include <machine/resource.h>
51
52#include <dev/aac/aacreg.h>
53#include <dev/aac/aacvar.h>
54#include <dev/aac/aac_tables.h>
55#include <dev/aac/aac_ioctl.h>
56
57devclass_t	aac_devclass;
58
59static void	aac_startup(void *arg);
60
61/* Command Processing */
62static void	aac_startio(struct aac_softc *sc);
63static void	aac_timeout(struct aac_command *cm);
64static int	aac_start(struct aac_command *cm);
65static void	aac_complete(void *context, int pending);
66static int	aac_bio_command(struct aac_softc *sc, struct aac_command **cmp);
67static void	aac_bio_complete(struct aac_command *cm);
68static int	aac_wait_command(struct aac_command *cm, int timeout);
69static void	aac_host_command(struct aac_softc *sc);
70static void	aac_host_response(struct aac_softc *sc);
71
72/* Command Buffer Management */
73static int	aac_alloc_command(struct aac_softc *sc, struct aac_command **cmp);
74static void	aac_release_command(struct aac_command *cm);
75static void	aac_map_command_cluster(void *arg, bus_dma_segment_t *segs, int nseg, int error);
76static void	aac_alloc_command_cluster(struct aac_softc *sc);
77static void	aac_free_command_cluster(struct aac_command_cluster *cmc);
78static void	aac_map_command(struct aac_command *cm);
79static void	aac_unmap_command(struct aac_command *cm);
80
81/* Hardware Interface */
82static void	aac_common_map(void *arg, bus_dma_segment_t *segs, int nseg, int error);
83static int	aac_init(struct aac_softc *sc);
84static int	aac_sync_command(struct aac_softc *sc, u_int32_t command,
85				 u_int32_t arg0, u_int32_t arg1, u_int32_t arg2, u_int32_t arg3,
86				 u_int32_t *sp);
87static int	aac_sync_fib(struct aac_softc *sc, u_int32_t command, u_int32_t xferstate,
88			     void *data, u_int16_t datasize,
89			     void *result, u_int16_t *resultsize);
90static int	aac_enqueue_fib(struct aac_softc *sc, int queue, u_int32_t fib_size, u_int32_t fib_addr);
91static int	aac_dequeue_fib(struct aac_softc *sc, int queue, u_int32_t *fib_size, struct aac_fib **fib_addr);
92
93/* StrongARM interface */
94static int	aac_sa_get_fwstatus(struct aac_softc *sc);
95static void	aac_sa_qnotify(struct aac_softc *sc, int qbit);
96static int	aac_sa_get_istatus(struct aac_softc *sc);
97static void	aac_sa_clear_istatus(struct aac_softc *sc, int mask);
98static void	aac_sa_set_mailbox(struct aac_softc *sc, u_int32_t command,
99				   u_int32_t arg0, u_int32_t arg1, u_int32_t arg2, u_int32_t arg3);
100static int	aac_sa_get_mailboxstatus(struct aac_softc *sc);
101static void	aac_sa_set_interrupts(struct aac_softc *sc, int enable);
102
103struct aac_interface aac_sa_interface = {
104    aac_sa_get_fwstatus,
105    aac_sa_qnotify,
106    aac_sa_get_istatus,
107    aac_sa_clear_istatus,
108    aac_sa_set_mailbox,
109    aac_sa_get_mailboxstatus,
110    aac_sa_set_interrupts
111};
112
113/* i960Rx interface */
114static int	aac_rx_get_fwstatus(struct aac_softc *sc);
115static void	aac_rx_qnotify(struct aac_softc *sc, int qbit);
116static int	aac_rx_get_istatus(struct aac_softc *sc);
117static void	aac_rx_clear_istatus(struct aac_softc *sc, int mask);
118static void	aac_rx_set_mailbox(struct aac_softc *sc, u_int32_t command,
119				   u_int32_t arg0, u_int32_t arg1, u_int32_t arg2, u_int32_t arg3);
120static int	aac_rx_get_mailboxstatus(struct aac_softc *sc);
121static void	aac_rx_set_interrupts(struct aac_softc *sc, int enable);
122
123struct aac_interface aac_rx_interface = {
124    aac_rx_get_fwstatus,
125    aac_rx_qnotify,
126    aac_rx_get_istatus,
127    aac_rx_clear_istatus,
128    aac_rx_set_mailbox,
129    aac_rx_get_mailboxstatus,
130    aac_rx_set_interrupts
131};
132
133/* Debugging and Diagnostics */
134static void	aac_describe_controller(struct aac_softc *sc);
135static char	*aac_describe_code(struct aac_code_lookup *table, u_int32_t code);
136
137/* Management Interface */
138static d_open_t		aac_open;
139static d_close_t	aac_close;
140static d_ioctl_t	aac_ioctl;
141static int		aac_ioctl_sendfib(struct aac_softc *sc, caddr_t ufib);
142static void		aac_handle_aif(struct aac_softc *sc, struct aac_aif_command *aif);
143static int		aac_return_aif(struct aac_softc *sc, caddr_t uptr);
144#ifdef AAC_COMPAT_LINUX
145static int		aac_linux_rev_check(struct aac_softc *sc, caddr_t udata);
146static int		aac_linux_getnext_aif(struct aac_softc *sc, caddr_t arg);
147#endif
148
149#define AAC_CDEV_MAJOR	150
150
151static struct cdevsw aac_cdevsw = {
152    aac_open,		/* open */
153    aac_close,		/* close */
154    noread,		/* read */
155    nowrite,		/* write */
156    aac_ioctl,		/* ioctl */
157    nopoll,		/* poll */
158    nommap,		/* mmap */
159    nostrategy,		/* strategy */
160    "aac",		/* name */
161    AAC_CDEV_MAJOR,	/* major */
162    nodump,		/* dump */
163    nopsize,		/* psize */
164    0,			/* flags */
165    -1,			/* bmaj */
166};
167
168/* Timeout for giving up on a command sent to the controller */
169#ifndef AAC_CMD_TIMEOUT
170#define AAC_CMD_TIMEOUT 15
171#endif
172
173/********************************************************************************
174 ********************************************************************************
175                                                                 Device Interface
176 ********************************************************************************
177 ********************************************************************************/
178
179/********************************************************************************
180 * Initialise the controller and softc
181 */
182int
183aac_attach(struct aac_softc *sc)
184{
185    int		error, unit;
186
187    debug_called(1);
188
189    /*
190     * Initialise per-controller queues.
191     */
192    TAILQ_INIT(&sc->aac_freecmds);
193    TAILQ_INIT(&sc->aac_ready);
194    TAILQ_INIT(&sc->aac_completed);
195    TAILQ_INIT(&sc->aac_clusters);
196    bioq_init(&sc->aac_bioq);
197
198#if __FreeBSD_version >= 500005
199    /*
200     * Initialise command-completion task.
201     */
202    TASK_INIT(&sc->aac_task_complete, 0, aac_complete, sc);
203#endif
204
205    /* disable interrupts before we enable anything */
206    AAC_MASK_INTERRUPTS(sc);
207
208    /* mark controller as suspended until we get ourselves organised */
209    sc->aac_state |= AAC_STATE_SUSPEND;
210
211    /*
212     * Initialise the adapter.
213     */
214    if ((error = aac_init(sc)))
215	return(error);
216
217    /*
218     * Print a little information about the controller.
219     */
220    aac_describe_controller(sc);
221
222    /*
223     * Register to probe our containers later.
224     */
225    bzero(&sc->aac_ich, sizeof(struct intr_config_hook));
226    sc->aac_ich.ich_func = aac_startup;
227    sc->aac_ich.ich_arg = sc;
228    if (config_intrhook_establish(&sc->aac_ich) != 0) {
229        device_printf(sc->aac_dev, "can't establish configuration hook\n");
230        return(ENXIO);
231    }
232
233    /*
234     * Make the control device.
235     */
236    unit = device_get_unit(sc->aac_dev);
237    sc->aac_dev_t = make_dev(&aac_cdevsw, unit, UID_ROOT, GID_WHEEL, 0644, "aac%d", unit);
238    sc->aac_dev_t->si_drv1 = sc;
239
240    return(0);
241}
242
243/********************************************************************************
244 * Probe for containers, create disks.
245 */
246static void
247aac_startup(void *arg)
248{
249    struct aac_softc		*sc = (struct aac_softc *)arg;
250    struct aac_mntinfo		mi;
251    struct aac_mntinforesponse	mir;
252    device_t			child;
253    u_int16_t			rsize;
254    int				i;
255
256    debug_called(1);
257
258    /* disconnect ourselves from the intrhook chain */
259    config_intrhook_disestablish(&sc->aac_ich);
260
261    /* loop over possible containers */
262    mi.Command = VM_NameServe;
263    mi.MntType = FT_FILESYS;
264    for (i = 0; i < AAC_MAX_CONTAINERS; i++) {
265	/* request information on this container */
266	mi.MntCount = i;
267	if (aac_sync_fib(sc, ContainerCommand, 0, &mi, sizeof(struct aac_mntinfo), &mir, &rsize)) {
268	    debug(2, "error probing container %d", i);
269	    continue;
270	}
271	/* check response size */
272	if (rsize != sizeof(mir)) {
273	    debug(2, "container info response wrong size (%d should be %d)", rsize, sizeof(mir));
274	    continue;
275	}
276	/*
277	 * Check container volume type for validity.  Note that many of the possible types
278	 * may never show up.
279	 */
280	if ((mir.Status == ST_OK) && (mir.MntTable[0].VolType != CT_NONE)) {
281	    debug(1, "%d: id %x  name '%.16s'  size %u  type %d",
282		  i, mir.MntTable[0].ObjectId,
283		  mir.MntTable[0].FileSystemName, mir.MntTable[0].Capacity,
284		  mir.MntTable[0].VolType);
285
286	    if ((child = device_add_child(sc->aac_dev, NULL, -1)) == NULL) {
287		device_printf(sc->aac_dev, "device_add_child failed\n");
288	    } else {
289		device_set_ivars(child, &sc->aac_container[i]);
290	    }
291	    device_set_desc(child, aac_describe_code(aac_container_types, mir.MntTable[0].VolType));
292	    sc->aac_container[i].co_disk = child;
293	    sc->aac_container[i].co_mntobj = mir.MntTable[0];
294	}
295    }
296
297    /* poke the bus to actually attach the child devices */
298    if (bus_generic_attach(sc->aac_dev))
299	device_printf(sc->aac_dev, "bus_generic_attach failed\n");
300
301    /* mark the controller up */
302    sc->aac_state &= ~AAC_STATE_SUSPEND;
303
304    /* enable interrupts now */
305    AAC_UNMASK_INTERRUPTS(sc);
306}
307
308/********************************************************************************
309 * Free all of the resources associated with (sc)
310 *
311 * Should not be called if the controller is active.
312 *
313 * XXX verify that we are freeing all our resources here...
314 */
315void
316aac_free(struct aac_softc *sc)
317{
318    struct aac_command_cluster	*cmc;
319
320    debug_called(1);
321
322    /* remove the control device */
323    if (sc->aac_dev_t != NULL)
324	destroy_dev(sc->aac_dev_t);
325
326    /* throw away any command buffers */
327    while ((cmc = aac_dequeue_cluster(sc)) != NULL)
328	aac_free_command_cluster(cmc);
329
330    /* destroy the common area */
331    if (sc->aac_common) {
332	bus_dmamap_unload(sc->aac_common_dmat, sc->aac_common_dmamap);
333	bus_dmamem_free(sc->aac_common_dmat, sc->aac_common, sc->aac_common_dmamap);
334	bus_dma_tag_destroy(sc->aac_common_dmat);
335    }
336
337    /* disconnect the interrupt handler */
338    if (sc->aac_intr)
339	bus_teardown_intr(sc->aac_dev, sc->aac_irq, sc->aac_intr);
340    if (sc->aac_irq != NULL)
341	bus_release_resource(sc->aac_dev, SYS_RES_IRQ, sc->aac_irq_rid, sc->aac_irq);
342
343    /* destroy data-transfer DMA tag */
344    if (sc->aac_buffer_dmat)
345	bus_dma_tag_destroy(sc->aac_buffer_dmat);
346
347    /* destroy FIB DMA tag */
348    if (sc->aac_buffer_dmat)
349	bus_dma_tag_destroy(sc->aac_fib_dmat);
350
351    /* destroy the parent DMA tag */
352    if (sc->aac_parent_dmat)
353	bus_dma_tag_destroy(sc->aac_parent_dmat);
354
355    /* release the register window mapping */
356    if (sc->aac_regs_resource != NULL)
357	bus_release_resource(sc->aac_dev, SYS_RES_MEMORY, sc->aac_regs_rid, sc->aac_regs_resource);
358}
359
360/********************************************************************************
361 * Disconnect from the controller completely, in preparation for unload.
362 */
363int
364aac_detach(device_t dev)
365{
366    struct aac_softc	*sc = device_get_softc(dev);
367    int			error;
368
369    debug_called(1);
370
371    if (sc->aac_state & AAC_STATE_OPEN)
372	return(EBUSY);
373
374    if ((error = aac_shutdown(dev)))
375	return(error);
376
377    aac_free(sc);
378
379    return(0);
380}
381
382/********************************************************************************
383 * Bring the controller down to a dormant state and detach all child devices.
384 *
385 * This function is called before detach or system shutdown.
386 *
387 * Note that we can assume that the camq on the controller is empty, as we won't
388 * allow shutdown if any device is open.
389 */
390int
391aac_shutdown(device_t dev)
392{
393    struct aac_softc		*sc = device_get_softc(dev);
394    struct aac_close_command	cc;
395    int				s, i;
396
397    debug_called(1);
398
399    s = splbio();
400
401    sc->aac_state |= AAC_STATE_SUSPEND;
402
403    /*
404     * Send a Container shutdown followed by a HostShutdown FIB to the
405     * controller to convince it that we don't want to talk to it anymore.
406     * We've been closed and all I/O completed already
407     */
408    device_printf(sc->aac_dev, "shutting down controller...");
409
410    cc.Command = VM_CloseAll;
411    cc.ContainerId = 0xffffffff;
412    if (aac_sync_fib(sc, ContainerCommand, 0, &cc, sizeof(cc), NULL, NULL)) {
413	printf("FAILED.\n");
414    } else {
415	i = 0;
416	if (aac_sync_fib(sc, FsaHostShutdown, AAC_FIBSTATE_SHUTDOWN, &i, sizeof(i), NULL, NULL)) {
417	    printf("FAILED.\n");
418	} else {
419	    printf("done.\n");
420	}
421    }
422
423    AAC_MASK_INTERRUPTS(sc);
424
425    splx(s);
426    return(0);
427}
428
429/********************************************************************************
430 * Bring the controller to a quiescent state, ready for system suspend.
431 */
432int
433aac_suspend(device_t dev)
434{
435    struct aac_softc	*sc = device_get_softc(dev);
436    int			s;
437
438    debug_called(1);
439    s = splbio();
440
441    sc->aac_state |= AAC_STATE_SUSPEND;
442
443    AAC_MASK_INTERRUPTS(sc);
444    splx(s);
445    return(0);
446}
447
448/********************************************************************************
449 * Bring the controller back to a state ready for operation.
450 */
451int
452aac_resume(device_t dev)
453{
454    struct aac_softc	*sc = device_get_softc(dev);
455
456    debug_called(1);
457    sc->aac_state &= ~AAC_STATE_SUSPEND;
458    AAC_UNMASK_INTERRUPTS(sc);
459    return(0);
460}
461
462/*******************************************************************************
463 * Take an interrupt.
464 */
465void
466aac_intr(void *arg)
467{
468    struct aac_softc	*sc = (struct aac_softc *)arg;
469    u_int16_t		reason;
470
471    debug_called(2);
472
473    reason = AAC_GET_ISTATUS(sc);
474
475    /* controller wants to talk to the log?  XXX should we defer this? */
476    if (reason & AAC_DB_PRINTF) {
477	if (sc->aac_common->ac_printf[0]) {
478	    device_printf(sc->aac_dev, "** %.*s", AAC_PRINTF_BUFSIZE, sc->aac_common->ac_printf);
479	    sc->aac_common->ac_printf[0] = 0;
480	}
481	AAC_CLEAR_ISTATUS(sc, AAC_DB_PRINTF);
482	AAC_QNOTIFY(sc, AAC_DB_PRINTF);
483    }
484
485    /* controller has a message for us? */
486    if (reason & AAC_DB_COMMAND_READY) {
487	aac_host_command(sc);
488	AAC_CLEAR_ISTATUS(sc, AAC_DB_COMMAND_READY);
489    }
490
491    /* controller has a response for us? */
492    if (reason & AAC_DB_RESPONSE_READY) {
493	aac_host_response(sc);
494	AAC_CLEAR_ISTATUS(sc, AAC_DB_RESPONSE_READY);
495    }
496
497    /* spurious interrupts that we don't use - reset the mask and clear the interrupts */
498    if (reason & (AAC_DB_COMMAND_NOT_FULL | AAC_DB_RESPONSE_NOT_FULL)) {
499	AAC_UNMASK_INTERRUPTS(sc);
500	AAC_CLEAR_ISTATUS(sc, AAC_DB_COMMAND_NOT_FULL | AAC_DB_RESPONSE_NOT_FULL);
501    }
502};
503
504/********************************************************************************
505 ********************************************************************************
506                                                               Command Processing
507 ********************************************************************************
508 ********************************************************************************/
509
510/********************************************************************************
511 * Start as much queued I/O as possible on the controller
512 */
513static void
514aac_startio(struct aac_softc *sc)
515{
516    struct aac_command	*cm;
517
518    debug_called(2);
519
520    for(;;) {
521	/* try to get a command that's been put off for lack of resources */
522	cm = aac_dequeue_ready(sc);
523
524	/* try to build a command off the bio queue (ignore error return) */
525	aac_bio_command(sc, &cm);
526
527	/* nothing to do? */
528	if (cm == NULL)
529	    break;
530
531	/* Set a timeout for this command to be completed by the controller */
532	cm->timeout_handle = timeout((timeout_t*)aac_timeout, cm, AAC_CMD_TIMEOUT * hz);
533
534	/* try to give the command to the controller */
535	if (aac_start(cm) == EBUSY) {
536	    /* put it on the ready queue for later */
537	    aac_requeue_ready(cm);
538	    break;
539	}
540    }
541}
542
543static void
544aac_timeout(struct aac_command *cm)
545{
546	struct aac_softc *sc;
547	struct bio *bp;
548	struct aac_disk  *ad;
549
550	sc = cm->cm_sc;
551	bp = (struct bio*)cm->cm_private;
552	ad = (struct aac_disk *)bp->bio_dev->si_drv1;
553
554	device_printf(sc->aac_dev, "Timeout waiting for controller to respond to command\n");
555
556	/* Should try to requeue the command... is it possible?  Bail for now */
557	bp->bio_error = EIO;
558	bp->bio_flags |= BIO_ERROR;
559	devstat_end_transaction_bio(&ad->ad_stats, bp);
560	biodone(bp);
561	aac_release_command(cm);
562}
563
564/********************************************************************************
565 * Deliver a command to the controller; allocate controller resources at the
566 * last moment when possible.
567 */
568static int
569aac_start(struct aac_command *cm)
570{
571    struct aac_softc	*sc = cm->cm_sc;
572
573    debug_called(2);
574
575    /* get the command mapped */
576    aac_map_command(cm);
577
578    /* fix up the address values */
579    cm->cm_fib->Header.SenderFibAddress = (u_int32_t)cm->cm_fib;
580    cm->cm_fib->Header.ReceiverFibAddress = cm->cm_fibphys;
581
582    /* save a pointer to the command for speedy reverse-lookup */
583    cm->cm_fib->Header.SenderData = (u_int32_t)cm;		/* XXX ack, sizing */
584
585    /* put the FIB on the outbound queue */
586    if (aac_enqueue_fib(sc, AAC_ADAP_NORM_CMD_QUEUE, cm->cm_fib->Header.Size,
587			cm->cm_fib->Header.ReceiverFibAddress))
588	return(EBUSY);
589
590    return(0);
591}
592
593/********************************************************************************
594 * Handle notification of one or more FIBs coming from the controller.
595 */
596static void
597aac_host_command(struct aac_softc *sc)
598{
599    struct aac_fib	*fib;
600    u_int32_t		fib_size;
601
602    debug_called(1);
603
604    for (;;) {
605	if (aac_dequeue_fib(sc, AAC_HOST_NORM_CMD_QUEUE, &fib_size, &fib))
606	    break;	/* nothing to do */
607
608	switch(fib->Header.Command) {
609	case AifRequest:
610	    aac_handle_aif(sc, (struct aac_aif_command *)&fib->data[0]);
611	    break;
612	default:
613	    device_printf(sc->aac_dev, "unknown command from controller\n");
614	    AAC_PRINT_FIB(sc, fib);
615	    break;
616	}
617
618	/* XXX reply to FIBs requesting responses ?? */
619	/* XXX how do we return these FIBs to the controller? */
620    }
621}
622
623/********************************************************************************
624 * Handle notification of one or more FIBs completed by the controller
625 */
626static void
627aac_host_response(struct aac_softc *sc)
628{
629    struct aac_command	*cm;
630    struct aac_fib	*fib;
631    u_int32_t		fib_size;
632
633    debug_called(2);
634
635    for (;;) {
636	/* look for completed FIBs on our queue */
637	if (aac_dequeue_fib(sc, AAC_HOST_NORM_RESP_QUEUE, &fib_size, &fib))
638	    break;	/* nothing to do */
639
640	/* get the command, unmap and queue for later processing */
641	cm = (struct aac_command *)fib->Header.SenderData;
642	if (cm == NULL) {
643	    AAC_PRINT_FIB(sc, fib);
644	} else {
645	    aac_unmap_command(cm);		/* XXX defer? */
646	    aac_enqueue_completed(cm);
647	}
648    }
649
650    /* handle completion processing */
651#if __FreeBSD_version >= 500005
652    taskqueue_enqueue(taskqueue_swi, &sc->aac_task_complete);
653#else
654    aac_complete(sc, 0);
655#endif
656}
657
658/********************************************************************************
659 * Process completed commands.
660 */
661static void
662aac_complete(void *context, int pending)
663{
664    struct aac_softc	*sc = (struct aac_softc *)context;
665    struct aac_command	*cm;
666
667    debug_called(2);
668
669    /* pull completed commands off the queue */
670    for (;;) {
671	cm = aac_dequeue_completed(sc);
672	if (cm == NULL)
673	    return;
674	cm->cm_flags |= AAC_CMD_COMPLETED;
675
676	/* is there a completion handler? */
677	if (cm->cm_complete != NULL) {
678	    cm->cm_complete(cm);
679	} else {
680	    /* assume that someone is sleeping on this command */
681	    wakeup(cm);
682	}
683    }
684}
685
686/********************************************************************************
687 * Handle a bio submitted from a disk device.
688 */
689void
690aac_submit_bio(struct bio *bp)
691{
692    struct aac_disk	*ad = (struct aac_disk *)bp->bio_dev->si_drv1;
693    struct aac_softc	*sc = ad->ad_controller;
694
695    debug_called(2);
696
697    /* queue the BIO and try to get some work done */
698    bioq_insert_tail(&sc->aac_bioq, bp);
699    aac_startio(sc);
700}
701
702/********************************************************************************
703 * Get a bio and build a command to go with it.
704 */
705static int
706aac_bio_command(struct aac_softc *sc, struct aac_command **cmp)
707{
708    struct aac_command		*cm;
709    struct aac_fib		*fib;
710    struct aac_blockread	*br;
711    struct aac_blockwrite	*bw;
712    struct aac_disk		*ad;
713    struct bio			*bp;
714    int				s;
715
716    debug_called(2);
717
718    /* get the resources we will need */
719    cm = NULL;
720    s = splbio();
721    if ((bp = bioq_first(&sc->aac_bioq)))
722	bioq_remove(&sc->aac_bioq, bp);
723    splx(s);
724    if (bp == NULL)			/* no work? */
725	goto fail;
726    if (aac_alloc_command(sc, &cm))	/* get a command */
727	goto fail;
728
729    /* fill out the command */
730    cm->cm_private = bp;
731
732    /* build the FIB */
733    fib = cm->cm_fib;
734    fib->Header.XferState =
735	AAC_FIBSTATE_HOSTOWNED   |
736	AAC_FIBSTATE_INITIALISED |
737	AAC_FIBSTATE_FROMHOST    |
738	AAC_FIBSTATE_REXPECTED   |
739	AAC_FIBSTATE_NORM;
740    fib->Header.Command = ContainerCommand;
741    fib->Header.Size = sizeof(struct aac_fib_header);
742
743    /* build the read/write request */
744    ad = (struct aac_disk *)bp->bio_dev->si_drv1;
745    cm->cm_data = (void *)bp->bio_data;
746    cm->cm_datalen = bp->bio_bcount;
747    cm->cm_complete = aac_bio_complete;
748    if (BIO_IS_READ(bp)) {
749	br = (struct aac_blockread *)&fib->data[0];
750	br->Command = VM_CtBlockRead;
751	br->ContainerId = ad->ad_container->co_mntobj.ObjectId;
752	br->BlockNumber = bp->bio_pblkno;
753	br->ByteCount = bp->bio_bcount;
754	fib->Header.Size += sizeof(struct aac_blockread);
755	cm->cm_sgtable = &br->SgMap;
756	cm->cm_flags |= AAC_CMD_DATAIN;
757    } else {
758	bw = (struct aac_blockwrite *)&fib->data[0];
759	bw->Command = VM_CtBlockWrite;
760	bw->ContainerId = ad->ad_container->co_mntobj.ObjectId;
761	bw->BlockNumber = bp->bio_pblkno;
762	bw->ByteCount = bp->bio_bcount;
763	bw->Stable = CUNSTABLE;		/* XXX what's appropriate here? */
764	fib->Header.Size += sizeof(struct aac_blockwrite);
765	cm->cm_flags |= AAC_CMD_DATAOUT;
766	cm->cm_sgtable = &bw->SgMap;
767    }
768
769    *cmp = cm;
770    return(0);
771
772fail:
773    if (bp != NULL)
774	bioq_insert_tail(&sc->aac_bioq, bp);
775    if (cm != NULL)
776	aac_release_command(cm);
777    return(ENOMEM);
778}
779
780/********************************************************************************
781 * Handle a bio-instigated command that has been completed.
782 */
783static void
784aac_bio_complete(struct aac_command *cm)
785{
786    struct aac_softc			*sc = cm->cm_sc;
787    struct aac_blockread_response	*brr;
788    struct aac_blockwrite_response	*bwr;
789    struct bio				*bp;
790    AAC_FSAStatus			status;
791
792    /* kill the timeout timer */
793    untimeout((timeout_t *)aac_timeout, cm, cm->timeout_handle);
794
795    /* fetch relevant status and then release the command */
796    bp = (struct bio *)cm->cm_private;
797    if (BIO_IS_READ(bp)) {
798	brr = (struct aac_blockread_response *)&cm->cm_fib->data[0];
799	status = brr->Status;
800    } else {
801	bwr = (struct aac_blockwrite_response *)&cm->cm_fib->data[0];
802	status = bwr->Status;
803    }
804    aac_release_command(cm);
805
806    /* fix up the bio based on status */
807    if (status == ST_OK) {
808	bp->bio_resid = 0;
809    } else {
810	bp->bio_error = EIO;
811	bp->bio_flags |= BIO_ERROR;
812
813	/* XXX be more verbose? */
814	device_printf(sc->aac_dev, "I/O error %d (%s)\n", status, AAC_COMMAND_STATUS(status));
815    }
816    aac_complete_bio(bp);	/* XXX rename one of these functions! */
817}
818
819/********************************************************************************
820 * Submit a command to the controller, return when it completes.
821 */
822static int
823aac_wait_command(struct aac_command *cm, int timeout)
824{
825    int s, error = 0;
826
827    debug_called(2);
828
829    /* Put the command on the ready queue and get things going */
830    aac_enqueue_ready(cm);
831    aac_startio(cm->cm_sc);
832    s = splbio();
833    while(!(cm->cm_flags & AAC_CMD_COMPLETED) && (error != EWOULDBLOCK)) {
834        error = tsleep(cm, PRIBIO, "aacwait", timeout * hz);
835    }
836    splx(s);
837    return(error);
838}
839
840/********************************************************************************
841 ********************************************************************************
842                                                        Command Buffer Management
843 ********************************************************************************
844 ********************************************************************************/
845
846/********************************************************************************
847 * Allocate a command.
848 */
849static int
850aac_alloc_command(struct aac_softc *sc, struct aac_command **cmp)
851{
852    struct aac_command	*cm;
853
854    debug_called(3);
855
856    cm = aac_dequeue_free(sc);
857    if (cm == NULL) {
858	aac_alloc_command_cluster(sc);
859	cm = aac_dequeue_free(sc);
860    }
861    if (cm == NULL)
862	return(ENOMEM);
863
864    /* initialise the command/FIB */
865    cm->cm_sgtable = NULL;
866    cm->cm_flags = 0;
867    cm->cm_complete = NULL;
868    cm->cm_private = NULL;
869    cm->cm_fib->Header.XferState = AAC_FIBSTATE_EMPTY;
870    cm->cm_fib->Header.StructType = AAC_FIBTYPE_TFIB;
871    cm->cm_fib->Header.Flags = 0;
872    cm->cm_fib->Header.SenderSize = sizeof(struct aac_fib);
873
874    /*
875     * These are duplicated in aac_start to cover the case where an
876     * intermediate stage may have destroyed them.  They're left
877     * initialised here for debugging purposes only.
878     */
879    cm->cm_fib->Header.SenderFibAddress = (u_int32_t)cm->cm_fib;
880    cm->cm_fib->Header.ReceiverFibAddress = cm->cm_fibphys;
881
882    *cmp = cm;
883    return(0);
884}
885
886/********************************************************************************
887 * Release a command back to the freelist.
888 */
889static void
890aac_release_command(struct aac_command *cm)
891{
892    debug_called(3);
893
894    aac_enqueue_free(cm);
895}
896
897/********************************************************************************
898 * Map helper for command cluster allocation. Tell each of the FIBs what its
899 * address in the adapter's space is, fill in a few other fields.
900 */
901static void
902aac_map_command_cluster(void *arg, bus_dma_segment_t *segs, int nseg, int error)
903{
904    struct aac_command_cluster	*cmc = (struct aac_command_cluster *)arg;
905
906    debug_called(3);
907
908    cmc->cmc_fibphys = segs[0].ds_addr;
909}
910
911/********************************************************************************
912 * Allocate and initialise a cluster of commands.
913 */
914static void
915aac_alloc_command_cluster(struct aac_softc *sc)
916{
917    struct aac_command_cluster	*cmc;
918    struct aac_command		*cm;
919    int				i;
920
921    debug_called(1);
922
923    cmc = malloc(sizeof(struct aac_command_cluster), M_DEVBUF, M_NOWAIT);
924    if (cmc != NULL) {
925	bzero(cmc, sizeof(*cmc));
926
927	/* allocate the FIB cluster in DMAable memory and load it */
928	if (bus_dmamem_alloc(sc->aac_fib_dmat, (void **)&cmc->cmc_fibs, BUS_DMA_NOWAIT, &cmc->cmc_fibmap)) {
929	    free(cmc, M_DEVBUF);
930	    return;
931	}
932	bus_dmamap_load(sc->aac_fib_dmat, cmc->cmc_fibmap, cmc->cmc_fibs,
933			AAC_CLUSTER_COUNT * sizeof(struct aac_fib), aac_map_command_cluster, cmc, 0);
934
935	aac_enqueue_cluster(sc, cmc);
936	for (i = 0; i < AAC_CLUSTER_COUNT; i++) {
937	    cm = &cmc->cmc_command[i];
938	    cm->cm_sc = sc;
939	    cm->cm_fib = cmc->cmc_fibs + i;
940	    cm->cm_fibphys = cmc->cmc_fibphys + (i * sizeof(struct aac_fib));
941
942	    if (!bus_dmamap_create(sc->aac_buffer_dmat, 0, &cm->cm_datamap))
943		aac_release_command(cm);
944	}
945    } else {
946	debug(2, "can't allocate memeory for command cluster");
947    }
948}
949
950/********************************************************************************
951 * Free a command cluster.
952 */
953static void
954aac_free_command_cluster(struct aac_command_cluster *cmc)
955{
956    struct aac_softc	*sc = cmc->cmc_command[0].cm_sc;
957    int			i;
958
959    debug_called(1);
960
961    for (i = 0; i < AAC_CLUSTER_COUNT; i++)
962	bus_dmamap_destroy(sc->aac_buffer_dmat, cmc->cmc_command[i].cm_datamap);
963    bus_dmamap_unload(sc->aac_fib_dmat, cmc->cmc_fibmap);
964    bus_dmamem_free(sc->aac_fib_dmat, cmc->cmc_fibs, cmc->cmc_fibmap);
965
966    free(cmc, M_DEVBUF);
967}
968
969/********************************************************************************
970 * Command-mapping helper function - populate this command's s/g table.
971 */
972static void
973aac_map_command_sg(void *arg, bus_dma_segment_t *segs, int nseg, int error)
974{
975    struct aac_command		*cm = (struct aac_command *)arg;
976    struct aac_fib		*fib = cm->cm_fib;
977    struct aac_sg_table		*sg;
978    int				i;
979
980    debug_called(3);
981
982    /* find the s/g table */
983    sg = cm->cm_sgtable;
984
985    /* copy into the FIB */
986    if (sg != NULL) {
987	sg->SgCount = nseg;
988	for (i = 0; i < nseg; i++) {
989	    sg->SgEntry[i].SgAddress = segs[i].ds_addr;
990	    sg->SgEntry[i].SgByteCount = segs[i].ds_len;
991	}
992	/* update the FIB size for the s/g count */
993	fib->Header.Size += nseg * sizeof(struct aac_sg_entry);
994    }
995
996}
997
998/********************************************************************************
999 * Map a command into controller-visible space.
1000 */
1001static void
1002aac_map_command(struct aac_command *cm)
1003{
1004    struct aac_softc	*sc = cm->cm_sc;
1005
1006    debug_called(2);
1007
1008    /* don't map more than once */
1009    if (cm->cm_flags & AAC_CMD_MAPPED)
1010	return;
1011
1012    if (cm->cm_datalen != 0) {
1013	bus_dmamap_load(sc->aac_buffer_dmat, cm->cm_datamap, cm->cm_data,
1014			cm->cm_datalen, aac_map_command_sg, cm, 0);
1015
1016	if (cm->cm_flags & AAC_CMD_DATAIN)
1017	    bus_dmamap_sync(sc->aac_buffer_dmat, cm->cm_datamap, BUS_DMASYNC_PREREAD);
1018	if (cm->cm_flags & AAC_CMD_DATAOUT)
1019	    bus_dmamap_sync(sc->aac_buffer_dmat, cm->cm_datamap, BUS_DMASYNC_PREWRITE);
1020    }
1021    cm->cm_flags |= AAC_CMD_MAPPED;
1022}
1023
1024/********************************************************************************
1025 * Unmap a command from controller-visible space.
1026 */
1027static void
1028aac_unmap_command(struct aac_command *cm)
1029{
1030    struct aac_softc	*sc = cm->cm_sc;
1031
1032    debug_called(2);
1033
1034    if (!(cm->cm_flags & AAC_CMD_MAPPED))
1035	return;
1036
1037    if (cm->cm_datalen != 0) {
1038	if (cm->cm_flags & AAC_CMD_DATAIN)
1039	    bus_dmamap_sync(sc->aac_buffer_dmat, cm->cm_datamap, BUS_DMASYNC_POSTREAD);
1040	if (cm->cm_flags & AAC_CMD_DATAOUT)
1041	    bus_dmamap_sync(sc->aac_buffer_dmat, cm->cm_datamap, BUS_DMASYNC_POSTWRITE);
1042
1043	bus_dmamap_unload(sc->aac_buffer_dmat, cm->cm_datamap);
1044    }
1045    cm->cm_flags &= ~AAC_CMD_MAPPED;
1046}
1047
1048/********************************************************************************
1049 ********************************************************************************
1050                                                               Hardware Interface
1051 ********************************************************************************
1052 ********************************************************************************/
1053
1054/********************************************************************************
1055 * Initialise the adapter.
1056 */
1057static void
1058aac_common_map(void *arg, bus_dma_segment_t *segs, int nseg, int error)
1059{
1060    struct aac_softc	*sc = (struct aac_softc *)arg;
1061
1062    debug_called(1);
1063
1064    sc->aac_common_busaddr = segs[0].ds_addr;
1065}
1066
1067static int
1068aac_init(struct aac_softc *sc)
1069{
1070    struct aac_adapter_init	*ip;
1071    time_t			then;
1072    u_int32_t			code;
1073    u_int8_t			*qaddr;
1074
1075    debug_called(1);
1076
1077    /*
1078     * First wait for the adapter to come ready.
1079     */
1080    then = time_second;
1081    do {
1082	code = AAC_GET_FWSTATUS(sc);
1083	if (code & AAC_SELF_TEST_FAILED) {
1084	    device_printf(sc->aac_dev, "FATAL: selftest failed\n");
1085	    return(ENXIO);
1086	}
1087	if (code & AAC_KERNEL_PANIC) {
1088	    device_printf(sc->aac_dev, "FATAL: controller kernel panic\n");
1089	    return(ENXIO);
1090	}
1091	if (time_second > (then + AAC_BOOT_TIMEOUT)) {
1092	    device_printf(sc->aac_dev, "FATAL: controller not coming ready, status %x\n", code);
1093	    return(ENXIO);
1094	}
1095    } while (!(code & AAC_UP_AND_RUNNING));
1096
1097    /*
1098     * Create DMA tag for the common structure and allocate it.
1099     */
1100    if (bus_dma_tag_create(sc->aac_parent_dmat, 	/* parent */
1101			   1, 0, 			/* alignment, boundary */
1102			   BUS_SPACE_MAXADDR,		/* lowaddr */
1103			   BUS_SPACE_MAXADDR, 		/* highaddr */
1104			   NULL, NULL, 			/* filter, filterarg */
1105			   sizeof(struct aac_common), 1,/* maxsize, nsegments */
1106			   BUS_SPACE_MAXSIZE_32BIT,	/* maxsegsize */
1107			   0,				/* flags */
1108			   &sc->aac_common_dmat)) {
1109	device_printf(sc->aac_dev, "can't allocate common structure DMA tag\n");
1110	return(ENOMEM);
1111    }
1112    if (bus_dmamem_alloc(sc->aac_common_dmat, (void **)&sc->aac_common, BUS_DMA_NOWAIT, &sc->aac_common_dmamap)) {
1113	device_printf(sc->aac_dev, "can't allocate common structure\n");
1114	return(ENOMEM);
1115    }
1116    bus_dmamap_load(sc->aac_common_dmat, sc->aac_common_dmamap, sc->aac_common, sizeof(*sc->aac_common),
1117		    aac_common_map, sc, 0);
1118    bzero(sc->aac_common, sizeof(*sc->aac_common));
1119
1120    /*
1121     * Fill in the init structure.  This tells the adapter about the physical location
1122     * of various important shared data structures.
1123     */
1124    ip = &sc->aac_common->ac_init;
1125    ip->InitStructRevision = AAC_INIT_STRUCT_REVISION;
1126
1127    ip->AdapterFibsPhysicalAddress = sc->aac_common_busaddr + fldoff(aac_common, ac_fibs);
1128    ip->AdapterFibsVirtualAddress = &sc->aac_common->ac_fibs[0];
1129    ip->AdapterFibsSize = AAC_ADAPTER_FIBS * sizeof(struct aac_fib);
1130    ip->AdapterFibAlign = sizeof(struct aac_fib);
1131
1132    ip->PrintfBufferAddress = sc->aac_common_busaddr + fldoff(aac_common, ac_printf);
1133    ip->PrintfBufferSize = AAC_PRINTF_BUFSIZE;
1134
1135    ip->HostPhysMemPages = 0;			/* not used? */
1136    ip->HostElapsedSeconds = time_second;	/* reset later if invalid */
1137
1138    /*
1139     * Initialise FIB queues.  Note that it appears that the layout of the indexes
1140     * and the segmentation of the entries is mandated by the adapter, which is
1141     * only told about the base of the queue index fields.
1142     *
1143     * The initial values of the indices are assumed to inform the adapter
1144     * of the sizes of the respective queues.
1145     *
1146     * The Linux driver uses a much more complex scheme whereby several header
1147     * records are kept for each queue.  We use a couple of generic list manipulation
1148     * functions which 'know' the size of each list by virtue of a table.
1149     */
1150    qaddr = &sc->aac_common->ac_qbuf[0] + AAC_QUEUE_ALIGN;
1151    qaddr -= (u_int32_t)qaddr % AAC_QUEUE_ALIGN;
1152    sc->aac_queues = (struct aac_queue_table *)qaddr;
1153    ip->CommHeaderAddress = sc->aac_common_busaddr + ((u_int32_t)sc->aac_queues - (u_int32_t)sc->aac_common);
1154    bzero(sc->aac_queues, sizeof(struct aac_queue_table));
1155
1156    sc->aac_queues->qt_qindex[AAC_HOST_NORM_CMD_QUEUE][AAC_PRODUCER_INDEX]  = AAC_HOST_NORM_CMD_ENTRIES;
1157    sc->aac_queues->qt_qindex[AAC_HOST_NORM_CMD_QUEUE][AAC_CONSUMER_INDEX]  = AAC_HOST_NORM_CMD_ENTRIES;
1158    sc->aac_queues->qt_qindex[AAC_HOST_HIGH_CMD_QUEUE][AAC_PRODUCER_INDEX]  = AAC_HOST_HIGH_CMD_ENTRIES;
1159    sc->aac_queues->qt_qindex[AAC_HOST_HIGH_CMD_QUEUE][AAC_CONSUMER_INDEX]  = AAC_HOST_HIGH_CMD_ENTRIES;
1160    sc->aac_queues->qt_qindex[AAC_ADAP_NORM_CMD_QUEUE][AAC_PRODUCER_INDEX]  = AAC_ADAP_NORM_CMD_ENTRIES;
1161    sc->aac_queues->qt_qindex[AAC_ADAP_NORM_CMD_QUEUE][AAC_CONSUMER_INDEX]  = AAC_ADAP_NORM_CMD_ENTRIES;
1162    sc->aac_queues->qt_qindex[AAC_ADAP_HIGH_CMD_QUEUE][AAC_PRODUCER_INDEX]  = AAC_ADAP_HIGH_CMD_ENTRIES;
1163    sc->aac_queues->qt_qindex[AAC_ADAP_HIGH_CMD_QUEUE][AAC_CONSUMER_INDEX]  = AAC_ADAP_HIGH_CMD_ENTRIES;
1164    sc->aac_queues->qt_qindex[AAC_HOST_NORM_RESP_QUEUE][AAC_PRODUCER_INDEX] = AAC_HOST_NORM_RESP_ENTRIES;
1165    sc->aac_queues->qt_qindex[AAC_HOST_NORM_RESP_QUEUE][AAC_CONSUMER_INDEX] = AAC_HOST_NORM_RESP_ENTRIES;
1166    sc->aac_queues->qt_qindex[AAC_HOST_HIGH_RESP_QUEUE][AAC_PRODUCER_INDEX] = AAC_HOST_HIGH_RESP_ENTRIES;
1167    sc->aac_queues->qt_qindex[AAC_HOST_HIGH_RESP_QUEUE][AAC_CONSUMER_INDEX] = AAC_HOST_HIGH_RESP_ENTRIES;
1168    sc->aac_queues->qt_qindex[AAC_ADAP_NORM_RESP_QUEUE][AAC_PRODUCER_INDEX] = AAC_ADAP_NORM_RESP_ENTRIES;
1169    sc->aac_queues->qt_qindex[AAC_ADAP_NORM_RESP_QUEUE][AAC_CONSUMER_INDEX] = AAC_ADAP_NORM_RESP_ENTRIES;
1170    sc->aac_queues->qt_qindex[AAC_ADAP_HIGH_RESP_QUEUE][AAC_PRODUCER_INDEX] = AAC_ADAP_HIGH_RESP_ENTRIES;
1171    sc->aac_queues->qt_qindex[AAC_ADAP_HIGH_RESP_QUEUE][AAC_CONSUMER_INDEX] = AAC_ADAP_HIGH_RESP_ENTRIES;
1172    sc->aac_qentries[AAC_HOST_NORM_CMD_QUEUE] = &sc->aac_queues->qt_HostNormCmdQueue[0];
1173    sc->aac_qentries[AAC_HOST_HIGH_CMD_QUEUE] = &sc->aac_queues->qt_HostHighCmdQueue[0];
1174    sc->aac_qentries[AAC_ADAP_NORM_CMD_QUEUE] = &sc->aac_queues->qt_AdapNormCmdQueue[0];
1175    sc->aac_qentries[AAC_ADAP_HIGH_CMD_QUEUE] = &sc->aac_queues->qt_AdapHighCmdQueue[0];
1176    sc->aac_qentries[AAC_HOST_NORM_RESP_QUEUE] = &sc->aac_queues->qt_HostNormRespQueue[0];
1177    sc->aac_qentries[AAC_HOST_HIGH_RESP_QUEUE] = &sc->aac_queues->qt_HostHighRespQueue[0];
1178    sc->aac_qentries[AAC_ADAP_NORM_RESP_QUEUE] = &sc->aac_queues->qt_AdapNormRespQueue[0];
1179    sc->aac_qentries[AAC_ADAP_HIGH_RESP_QUEUE] = &sc->aac_queues->qt_AdapHighRespQueue[0];
1180
1181    /*
1182     * Do controller-type-specific initialisation
1183     */
1184    switch (sc->aac_hwif) {
1185    case AAC_HWIF_I960RX:
1186	AAC_SETREG4(sc, AAC_RX_ODBR, ~0);
1187	break;
1188    }
1189
1190    /*
1191     * Give the init structure to the controller.
1192     */
1193    if (aac_sync_command(sc, AAC_MONKER_INITSTRUCT,
1194			  sc->aac_common_busaddr + fldoff(aac_common, ac_init),
1195			  0, 0, 0, NULL)) {
1196	device_printf(sc->aac_dev, "error establishing init structure\n");
1197	return(EIO);
1198    }
1199
1200    return(0);
1201}
1202
1203/********************************************************************************
1204 * Send a synchronous command to the controller and wait for a result.
1205 */
1206static int
1207aac_sync_command(struct aac_softc *sc, u_int32_t command,
1208		       u_int32_t arg0, u_int32_t arg1, u_int32_t arg2, u_int32_t arg3,
1209		       u_int32_t *sp)
1210{
1211    time_t	then;
1212    u_int32_t	status;
1213
1214    debug_called(3);
1215
1216    /* populate the mailbox */
1217    AAC_SET_MAILBOX(sc, command, arg0, arg1, arg2, arg3);
1218
1219    /* ensure the sync command doorbell flag is cleared */
1220    AAC_CLEAR_ISTATUS(sc, AAC_DB_SYNC_COMMAND);
1221
1222    /* then set it to signal the adapter */
1223    AAC_QNOTIFY(sc, AAC_DB_SYNC_COMMAND);
1224
1225    /* spin waiting for the command to complete */
1226    then = time_second;
1227    do {
1228	if (time_second > (then + AAC_IMMEDIATE_TIMEOUT)) {
1229	    debug(2, "timed out");
1230	    return(EIO);
1231	}
1232    } while (!(AAC_GET_ISTATUS(sc) & AAC_DB_SYNC_COMMAND));
1233
1234    /* clear the completion flag */
1235    AAC_CLEAR_ISTATUS(sc, AAC_DB_SYNC_COMMAND);
1236
1237    /* get the command status */
1238    status = AAC_GET_MAILBOXSTATUS(sc);
1239    if (sp != NULL)
1240	*sp = status;
1241    return(0);	/* check command return status? */
1242}
1243
1244/********************************************************************************
1245 * Send a synchronous FIB to the controller and wait for a result.
1246 */
1247static int
1248aac_sync_fib(struct aac_softc *sc, u_int32_t command, u_int32_t xferstate,
1249	     void *data, u_int16_t datasize,
1250	     void *result, u_int16_t *resultsize)
1251{
1252    struct aac_fib	*fib = &sc->aac_common->ac_sync_fib;
1253
1254    debug_called(3);
1255
1256    if (datasize > AAC_FIB_DATASIZE)
1257	return(EINVAL);
1258
1259    /*
1260     * Set up the sync FIB
1261     */
1262    fib->Header.XferState = AAC_FIBSTATE_HOSTOWNED | AAC_FIBSTATE_INITIALISED | AAC_FIBSTATE_EMPTY;
1263    fib->Header.XferState |= xferstate;
1264    fib->Header.Command = command;
1265    fib->Header.StructType = AAC_FIBTYPE_TFIB;
1266    fib->Header.Size = sizeof(struct aac_fib) + datasize;
1267    fib->Header.SenderSize = sizeof(struct aac_fib);
1268    fib->Header.SenderFibAddress = (u_int32_t)fib;
1269    fib->Header.ReceiverFibAddress = sc->aac_common_busaddr + fldoff(aac_common, ac_sync_fib);
1270
1271    /*
1272     * Copy in data.
1273     */
1274    if (data != NULL) {
1275	bcopy(data, fib->data, datasize);
1276	fib->Header.XferState |= AAC_FIBSTATE_FROMHOST | AAC_FIBSTATE_NORM;
1277    }
1278
1279    /*
1280     * Give the FIB to the controller, wait for a response.
1281     */
1282    if (aac_sync_command(sc, AAC_MONKER_SYNCFIB, fib->Header.ReceiverFibAddress,
1283			  0, 0, 0, NULL)) {
1284	debug(2, "IO error");
1285	return(EIO);
1286    }
1287
1288    /*
1289     * Copy out the result
1290     */
1291    if (result != NULL) {
1292	*resultsize = fib->Header.Size - sizeof(struct aac_fib_header);
1293	bcopy(fib->data, result, *resultsize);
1294    }
1295    return(0);
1296}
1297
1298/********************************************************************************
1299 * Adapter-space FIB queue manipulation
1300 *
1301 * Note that the queue implementation here is a little funky; neither the PI or
1302 * CI will ever be zero.  This behaviour is a controller feature.
1303 */
1304static struct {
1305    int		size;
1306    int		notify;
1307} aac_qinfo[] = {
1308    {AAC_HOST_NORM_CMD_ENTRIES, AAC_DB_COMMAND_NOT_FULL},
1309    {AAC_HOST_HIGH_CMD_ENTRIES, 0},
1310    {AAC_ADAP_NORM_CMD_ENTRIES, AAC_DB_COMMAND_READY},
1311    {AAC_ADAP_HIGH_CMD_ENTRIES, 0},
1312    {AAC_HOST_NORM_RESP_ENTRIES, AAC_DB_RESPONSE_NOT_FULL},
1313    {AAC_HOST_HIGH_RESP_ENTRIES, 0},
1314    {AAC_ADAP_NORM_RESP_ENTRIES, AAC_DB_RESPONSE_READY},
1315    {AAC_ADAP_HIGH_RESP_ENTRIES, 0}
1316};
1317
1318/*
1319 * Atomically insert an entry into the nominated queue, returns 0 on success or EBUSY
1320 * if the queue is full.
1321 *
1322 * XXX note that it would be more efficient to defer notifying the controller in
1323 * the case where we may be inserting several entries in rapid succession, but
1324 * implementing this usefully is difficult.
1325 */
1326static int
1327aac_enqueue_fib(struct aac_softc *sc, int queue, u_int32_t fib_size, u_int32_t fib_addr)
1328{
1329    u_int32_t	pi, ci;
1330    int		s, error;
1331
1332    debug_called(3);
1333
1334    s = splbio();
1335
1336    /* get the producer/consumer indices */
1337    pi = sc->aac_queues->qt_qindex[queue][AAC_PRODUCER_INDEX];
1338    ci = sc->aac_queues->qt_qindex[queue][AAC_CONSUMER_INDEX];
1339
1340    /* wrap the queue? */
1341    if (pi >= aac_qinfo[queue].size)
1342	pi = 0;
1343
1344    /* check for queue full */
1345    if ((pi + 1) == ci) {
1346	error = EBUSY;
1347	goto out;
1348    }
1349
1350    /* populate queue entry */
1351    (sc->aac_qentries[queue] + pi)->aq_fib_size = fib_size;
1352    (sc->aac_qentries[queue] + pi)->aq_fib_addr = fib_addr;
1353
1354    /* update producer index */
1355    sc->aac_queues->qt_qindex[queue][AAC_PRODUCER_INDEX] = pi + 1;
1356
1357    /* notify the adapter if we know how */
1358    if (aac_qinfo[queue].notify != 0)
1359	AAC_QNOTIFY(sc, aac_qinfo[queue].notify);
1360
1361    error = 0;
1362
1363out:
1364    splx(s);
1365    return(error);
1366}
1367
1368/*
1369 * Atomically remove one entry from the nominated queue, returns 0 on success or ENOENT
1370 * if the queue is empty.
1371 */
1372static int
1373aac_dequeue_fib(struct aac_softc *sc, int queue, u_int32_t *fib_size, struct aac_fib **fib_addr)
1374{
1375    u_int32_t	pi, ci;
1376    int		s, error;
1377
1378    debug_called(3);
1379
1380    s = splbio();
1381
1382    /* get the producer/consumer indices */
1383    pi = sc->aac_queues->qt_qindex[queue][AAC_PRODUCER_INDEX];
1384    ci = sc->aac_queues->qt_qindex[queue][AAC_CONSUMER_INDEX];
1385
1386    /* check for queue empty */
1387    if (ci == pi) {
1388	error = ENOENT;
1389	goto out;
1390    }
1391
1392    /* wrap the queue? */
1393    if (ci >= aac_qinfo[queue].size)
1394	ci = 0;
1395
1396    /* fetch the entry */
1397    *fib_size = (sc->aac_qentries[queue] + ci)->aq_fib_size;
1398    *fib_addr = (struct aac_fib *)(sc->aac_qentries[queue] + ci)->aq_fib_addr;
1399
1400    /* update consumer index */
1401    sc->aac_queues->qt_qindex[queue][AAC_CONSUMER_INDEX] = ci + 1;
1402
1403    /* if we have made the queue un-full, notify the adapter */
1404    if (((pi + 1) == ci) && (aac_qinfo[queue].notify != 0))
1405	AAC_QNOTIFY(sc, aac_qinfo[queue].notify);
1406    error = 0;
1407
1408out:
1409    splx(s);
1410    return(error);
1411}
1412
1413/********************************************************************************
1414 ********************************************************************************
1415                                                       Interface Function Vectors
1416 ********************************************************************************
1417 ********************************************************************************/
1418
1419/********************************************************************************
1420 * Read the current firmware status word.
1421 */
1422static int
1423aac_sa_get_fwstatus(struct aac_softc *sc)
1424{
1425    debug_called(3);
1426
1427    return(AAC_GETREG4(sc, AAC_SA_FWSTATUS));
1428}
1429
1430static int
1431aac_rx_get_fwstatus(struct aac_softc *sc)
1432{
1433    debug_called(3);
1434
1435    return(AAC_GETREG4(sc, AAC_RX_FWSTATUS));
1436}
1437
1438/********************************************************************************
1439 * Notify the controller of a change in a given queue
1440 */
1441
1442static void
1443aac_sa_qnotify(struct aac_softc *sc, int qbit)
1444{
1445    debug_called(3);
1446
1447    AAC_SETREG2(sc, AAC_SA_DOORBELL1_SET, qbit);
1448}
1449
1450static void
1451aac_rx_qnotify(struct aac_softc *sc, int qbit)
1452{
1453    debug_called(3);
1454
1455    AAC_SETREG4(sc, AAC_RX_IDBR, qbit);
1456}
1457
1458/********************************************************************************
1459 * Get the interrupt reason bits
1460 */
1461static int
1462aac_sa_get_istatus(struct aac_softc *sc)
1463{
1464    debug_called(3);
1465
1466    return(AAC_GETREG2(sc, AAC_SA_DOORBELL0));
1467}
1468
1469static int
1470aac_rx_get_istatus(struct aac_softc *sc)
1471{
1472    debug_called(3);
1473
1474    return(AAC_GETREG4(sc, AAC_RX_ODBR));
1475}
1476
1477/********************************************************************************
1478 * Clear some interrupt reason bits
1479 */
1480static void
1481aac_sa_clear_istatus(struct aac_softc *sc, int mask)
1482{
1483    debug_called(3);
1484
1485    AAC_SETREG2(sc, AAC_SA_DOORBELL0_CLEAR, mask);
1486}
1487
1488static void
1489aac_rx_clear_istatus(struct aac_softc *sc, int mask)
1490{
1491    debug_called(3);
1492
1493    AAC_SETREG4(sc, AAC_RX_ODBR, mask);
1494}
1495
1496/********************************************************************************
1497 * Populate the mailbox and set the command word
1498 */
1499static void
1500aac_sa_set_mailbox(struct aac_softc *sc, u_int32_t command,
1501		u_int32_t arg0, u_int32_t arg1, u_int32_t arg2, u_int32_t arg3)
1502{
1503    debug_called(4);
1504
1505    AAC_SETREG4(sc, AAC_SA_MAILBOX, command);
1506    AAC_SETREG4(sc, AAC_SA_MAILBOX + 4, arg0);
1507    AAC_SETREG4(sc, AAC_SA_MAILBOX + 8, arg1);
1508    AAC_SETREG4(sc, AAC_SA_MAILBOX + 12, arg2);
1509    AAC_SETREG4(sc, AAC_SA_MAILBOX + 16, arg3);
1510}
1511
1512static void
1513aac_rx_set_mailbox(struct aac_softc *sc, u_int32_t command,
1514		u_int32_t arg0, u_int32_t arg1, u_int32_t arg2, u_int32_t arg3)
1515{
1516    debug_called(4);
1517
1518    AAC_SETREG4(sc, AAC_RX_MAILBOX, command);
1519    AAC_SETREG4(sc, AAC_RX_MAILBOX + 4, arg0);
1520    AAC_SETREG4(sc, AAC_RX_MAILBOX + 8, arg1);
1521    AAC_SETREG4(sc, AAC_RX_MAILBOX + 12, arg2);
1522    AAC_SETREG4(sc, AAC_RX_MAILBOX + 16, arg3);
1523}
1524
1525/********************************************************************************
1526 * Fetch the immediate command status word
1527 */
1528static int
1529aac_sa_get_mailboxstatus(struct aac_softc *sc)
1530{
1531    debug_called(4);
1532
1533    return(AAC_GETREG4(sc, AAC_SA_MAILBOX));
1534}
1535
1536static int
1537aac_rx_get_mailboxstatus(struct aac_softc *sc)
1538{
1539    debug_called(4);
1540
1541    return(AAC_GETREG4(sc, AAC_RX_MAILBOX));
1542}
1543
1544/********************************************************************************
1545 * Set/clear interrupt masks
1546 */
1547static void
1548aac_sa_set_interrupts(struct aac_softc *sc, int enable)
1549{
1550    debug(2, "%sable interrupts", enable ? "en" : "dis");
1551
1552    if (enable) {
1553	AAC_SETREG2((sc), AAC_SA_MASK0_CLEAR, AAC_DB_INTERRUPTS);
1554    } else {
1555	AAC_SETREG2((sc), AAC_SA_MASK0_SET, ~0);
1556    }
1557}
1558
1559static void
1560aac_rx_set_interrupts(struct aac_softc *sc, int enable)
1561{
1562    debug(2, "%sable interrupts", enable ? "en" : "dis");
1563
1564    if (enable) {
1565	AAC_SETREG4(sc, AAC_RX_OIMR, ~AAC_DB_INTERRUPTS);
1566    } else {
1567	AAC_SETREG4(sc, AAC_RX_OIMR, ~0);
1568    }
1569}
1570
1571/********************************************************************************
1572 ********************************************************************************
1573                                                        Debugging and Diagnostics
1574 ********************************************************************************
1575 ********************************************************************************/
1576
1577/********************************************************************************
1578 * Print some information about the controller.
1579 */
1580static void
1581aac_describe_controller(struct aac_softc *sc)
1582{
1583    u_int8_t			buf[AAC_FIB_DATASIZE];	/* XXX really a bit big for the stack */
1584    u_int16_t			bufsize;
1585    struct aac_adapter_info	*info;
1586    u_int8_t			arg;
1587
1588    debug_called(2);
1589
1590    arg = 0;
1591    if (aac_sync_fib(sc, RequestAdapterInfo, 0, &arg, sizeof(arg), &buf, &bufsize)) {
1592	device_printf(sc->aac_dev, "RequestAdapterInfo failed\n");
1593	return;
1594    }
1595    if (bufsize != sizeof(*info)) {
1596	device_printf(sc->aac_dev, "RequestAdapterInfo returned wrong data size (%d != %d)\n",
1597		      bufsize, sizeof(*info));
1598	return;
1599    }
1600    info = (struct aac_adapter_info *)&buf[0];
1601
1602    device_printf(sc->aac_dev, "%s %dMHz, %dMB total memory, %s (%d)\n",
1603		  aac_describe_code(aac_cpu_variant, info->CpuVariant), info->ClockSpeed,
1604		  info->TotalMem / (1024 * 1024),
1605		  aac_describe_code(aac_battery_platform, info->batteryPlatform), info->batteryPlatform);
1606
1607    /* save the kernel revision structure for later use */
1608    sc->aac_revision = info->KernelRevision;
1609    device_printf(sc->aac_dev, "Kernel %d.%d-%d, S/N %llx\n",
1610		  info->KernelRevision.external.comp.major,
1611		  info->KernelRevision.external.comp.minor,
1612		  info->KernelRevision.external.comp.dash,
1613		  info->SerialNumber);	/* XXX how is this meant to be formatted? */
1614}
1615
1616/********************************************************************************
1617 * Look up a text description of a numeric error code and return a pointer to
1618 * same.
1619 */
1620static char *
1621aac_describe_code(struct aac_code_lookup *table, u_int32_t code)
1622{
1623    int		i;
1624
1625    for (i = 0; table[i].string != NULL; i++)
1626	if (table[i].code == code)
1627	    return(table[i].string);
1628    return(table[i+1].string);
1629}
1630
1631/*****************************************************************************
1632 *****************************************************************************
1633                                                    Management Interface
1634 *****************************************************************************
1635 *****************************************************************************/
1636
1637static int
1638aac_open(dev_t dev, int flags, int fmt, struct proc *p)
1639{
1640    struct aac_softc	*sc = dev->si_drv1;
1641
1642    debug_called(2);
1643
1644    /* Check to make sure the device isn't already open */
1645    if (sc->aac_state & AAC_STATE_OPEN) {
1646        return EBUSY;
1647    }
1648    sc->aac_state |= AAC_STATE_OPEN;
1649
1650    return 0;
1651}
1652
1653static int
1654aac_close(dev_t dev, int flags, int fmt, struct proc *p)
1655{
1656    struct aac_softc	*sc = dev->si_drv1;
1657
1658    debug_called(2);
1659
1660    /* Mark this unit as no longer open  */
1661    sc->aac_state &= ~AAC_STATE_OPEN;
1662
1663    return 0;
1664}
1665
1666static int
1667aac_ioctl(dev_t dev, u_long cmd, caddr_t arg, int flag, struct proc *p)
1668{
1669    struct aac_softc	*sc = dev->si_drv1;
1670    int			error = 0, i;
1671
1672    debug_called(2);
1673
1674    switch (cmd) {
1675#ifdef AAC_COMPAT_LINUX
1676    case FSACTL_SENDFIB:
1677	debug(0, "FSACTL_SENDFIB");
1678	error = aac_ioctl_sendfib(sc, arg);
1679	break;
1680    case FSACTL_AIF_THREAD:
1681	debug(0, "FSACTL_AIF_THREAD");
1682	error = EINVAL;
1683	break;
1684    case FSACTL_OPEN_GET_ADAPTER_FIB:
1685	debug(0, "FSACTL_OPEN_GET_ADAPTER_FIB");
1686	/*
1687	 * Pass the caller out an AdapterFibContext.
1688	 *
1689	 * Note that because we only support one opener, we
1690	 * basically ignore this.  Set the caller's context to a magic
1691	 * number just in case.
1692	 */
1693	i = AAC_AIF_SILLYMAGIC;
1694	error = copyout(&i, arg, sizeof(i));
1695	break;
1696    case FSACTL_GET_NEXT_ADAPTER_FIB:
1697	debug(0, "FSACTL_GET_NEXT_ADAPTER_FIB");
1698	error = aac_linux_getnext_aif(sc, arg);
1699	break;
1700    case FSACTL_CLOSE_GET_ADAPTER_FIB:
1701	debug(0, "FSACTL_CLOSE_GET_ADAPTER_FIB");
1702	/* don't do anything here */
1703	break;
1704    case FSACTL_MINIPORT_REV_CHECK:
1705	debug(0, "FSACTL_MINIPORT_REV_CHECK");
1706	error = aac_linux_rev_check(sc, arg);
1707	break;
1708#endif
1709    default:
1710	device_printf(sc->aac_dev, "unsupported cmd 0x%lx\n", cmd);
1711	error = EINVAL;
1712	break;
1713    }
1714    return(error);
1715}
1716
1717/********************************************************************************
1718 * Send a FIB supplied from userspace
1719 */
1720static int
1721aac_ioctl_sendfib(struct aac_softc *sc, caddr_t ufib)
1722{
1723    struct aac_command 	*cm;
1724    int			size, error;
1725
1726    debug_called(2);
1727
1728    cm = NULL;
1729
1730    /*
1731     * Get a command
1732     */
1733    if (aac_alloc_command(sc, &cm)) {
1734	error = EBUSY;
1735	goto out;
1736    }
1737
1738    /*
1739     * Fetch the FIB header, then re-copy to get data as well.
1740     */
1741    if ((error = copyin(ufib, cm->cm_fib, sizeof(struct aac_fib_header))) != 0)
1742	goto out;
1743    size = cm->cm_fib->Header.Size + sizeof(struct aac_fib_header);
1744    if (size > sizeof(struct aac_fib)) {
1745	device_printf(sc->aac_dev, "incoming FIB oversized (%d > %d)\n", size, sizeof(struct aac_fib));
1746	size = sizeof(struct aac_fib);
1747    }
1748    if ((error = copyin(ufib, cm->cm_fib, size)) != 0)
1749	goto out;
1750    cm->cm_fib->Header.Size = size;
1751
1752    /*
1753     * Pass the FIB to the controller, wait for it to complete.
1754     */
1755    if ((error = aac_wait_command(cm, 30)) != 0)	/* XXX user timeout? */
1756	goto out;
1757
1758    /*
1759     * Copy the FIB and data back out to the caller.
1760     */
1761    size = cm->cm_fib->Header.Size;
1762    if (size > sizeof(struct aac_fib)) {
1763	device_printf(sc->aac_dev, "outbound FIB oversized (%d > %d)\n", size, sizeof(struct aac_fib));
1764	size = sizeof(struct aac_fib);
1765    }
1766    error = copyout(cm->cm_fib, ufib, size);
1767
1768out:
1769    if (cm != NULL)
1770	aac_release_command(cm);
1771    return(error);
1772}
1773
1774/********************************************************************************
1775 * Handle an AIF sent to us by the controller; queue it for later reference.
1776 *
1777 * XXX what's the right thing to do here when the queue is full?  Drop the older
1778 * or newer entries?
1779 */
1780static void
1781aac_handle_aif(struct aac_softc *sc, struct aac_aif_command *aif)
1782{
1783    int		next, s;
1784
1785    debug_called(2);
1786
1787    s = splbio();
1788    next = (sc->aac_aifq_head + 1) % AAC_AIFQ_LENGTH;
1789    if (next != sc->aac_aifq_tail) {
1790	bcopy(aif, &sc->aac_aifq[next], sizeof(struct aac_aif_command));
1791	sc->aac_aifq_head = next;
1792	if (sc->aac_state & AAC_STATE_AIF_SLEEPER)
1793	    wakeup(sc->aac_aifq);
1794    }
1795    splx(s);
1796    aac_print_aif(sc, aif);
1797}
1798
1799/********************************************************************************
1800 * Hand the next AIF off the top of the queue out to userspace.
1801 */
1802static int
1803aac_return_aif(struct aac_softc *sc, caddr_t uptr)
1804{
1805    int		error, s;
1806
1807    debug_called(2);
1808
1809    s = splbio();
1810    if (sc->aac_aifq_tail == sc->aac_aifq_head) {
1811	error = EAGAIN;
1812    } else {
1813	error = copyout(&sc->aac_aifq[sc->aac_aifq_tail], uptr, sizeof(struct aac_aif_command));
1814	if (!error)
1815	    sc->aac_aifq_tail = (sc->aac_aifq_tail + 1) % AAC_AIFQ_LENGTH;
1816    }
1817    splx(s);
1818    return(error);
1819}
1820
1821/********************************************************************************
1822 ********************************************************************************
1823                                                       Linux Management Interface
1824 ********************************************************************************
1825 ********************************************************************************/
1826
1827#ifdef AAC_COMPAT_LINUX
1828
1829#include <sys/proc.h>
1830#include <machine/../linux/linux.h>
1831#include <machine/../linux/linux_proto.h>
1832#include <compat/linux/linux_ioctl.h>
1833
1834#define AAC_LINUX_IOCTL_MIN  0x2000
1835#define AAC_LINUX_IOCTL_MAX  0x21ff
1836
1837static linux_ioctl_function_t aac_linux_ioctl;
1838static struct linux_ioctl_handler aac_handler = {aac_linux_ioctl, AAC_LINUX_IOCTL_MIN, AAC_LINUX_IOCTL_MAX};
1839
1840SYSINIT  (aac_register,   SI_SUB_KLD, SI_ORDER_MIDDLE, linux_ioctl_register_handler, &aac_handler);
1841SYSUNINIT(aac_unregister, SI_SUB_KLD, SI_ORDER_MIDDLE, linux_ioctl_unregister_handler, &aac_handler);
1842
1843MODULE_DEPEND(aac, linux, 1, 1, 1);
1844
1845static int
1846aac_linux_ioctl(struct proc *p, struct linux_ioctl_args *args)
1847{
1848    struct file		*fp = p->p_fd->fd_ofiles[args->fd];
1849    u_long		cmd = args->cmd;
1850
1851    /*
1852     * Pass the ioctl off to our standard handler.
1853     */
1854    return(fo_ioctl(fp, cmd, (caddr_t)args->arg, p));
1855}
1856
1857/********************************************************************************
1858 * Return the Revision of the driver to the userspace and check to see if the
1859 * userspace app is possibly compatible.  This is extremely bogus right now
1860 * because I have no idea how to handle the versioning of this driver.  It is
1861 * needed, though, to get aaccli working.
1862 */
1863static int
1864aac_linux_rev_check(struct aac_softc *sc, caddr_t udata)
1865{
1866    struct aac_rev_check	rev_check;
1867    struct aac_rev_check_resp	rev_check_resp;
1868    int				error = 0;
1869
1870    debug_called(2);
1871
1872    /*
1873     * Copyin the revision struct from userspace
1874     */
1875    if ((error = copyin(udata, (caddr_t)&rev_check, sizeof(struct aac_rev_check))) != 0) {
1876	return error;
1877    }
1878
1879    debug(2, "Userland revision= %d\n", rev_check.callingRevision.buildNumber);
1880
1881    /*
1882     * Doctor up the response struct.
1883     */
1884    rev_check_resp.possiblyCompatible = 1;
1885    rev_check_resp.adapterSWRevision.external.ul = sc->aac_revision.external.ul;
1886    rev_check_resp.adapterSWRevision.buildNumber = sc->aac_revision.buildNumber;
1887
1888    return(copyout((caddr_t)&rev_check_resp, udata, sizeof(struct aac_rev_check_resp)));
1889}
1890
1891/********************************************************************************
1892 * Pass the caller the next AIF in their queue
1893 */
1894static int
1895aac_linux_getnext_aif(struct aac_softc *sc, caddr_t arg)
1896{
1897    struct get_adapter_fib_ioctl	agf;
1898    int					error, s;
1899
1900    debug_called(2);
1901
1902    if ((error = copyin(arg, &agf, sizeof(agf))) == 0) {
1903
1904	/*
1905	 * Check the magic number that we gave the caller.
1906	 */
1907	if (agf.AdapterFibContext != AAC_AIF_SILLYMAGIC) {
1908	    error = EFAULT;
1909	} else {
1910
1911	    s = splbio();
1912	    error = aac_return_aif(sc, agf.AifFib);
1913
1914	    if ((error == EAGAIN) && (agf.Wait)) {
1915		sc->aac_state |= AAC_STATE_AIF_SLEEPER;
1916		while (error == EAGAIN) {
1917		    error = tsleep(sc->aac_aifq, PRIBIO | PCATCH, "aacaif", 0);
1918		    if (error == 0)
1919			error = aac_return_aif(sc, agf.AifFib);
1920		}
1921		sc->aac_state &= ~AAC_STATE_AIF_SLEEPER;
1922	    }
1923	    splx(s);
1924	}
1925    }
1926    return(error);
1927}
1928
1929#endif /* AAC_COMPAT_LINUX */
1930