aac.c revision 68877
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 68877 2000-11-18 15:21:22Z dwmalone $
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,
924	M_NOWAIT | M_ZERO);
925    if (cmc != NULL) {
926	/* allocate the FIB cluster in DMAable memory and load it */
927	if (bus_dmamem_alloc(sc->aac_fib_dmat, (void **)&cmc->cmc_fibs, BUS_DMA_NOWAIT, &cmc->cmc_fibmap)) {
928	    free(cmc, M_DEVBUF);
929	    return;
930	}
931	bus_dmamap_load(sc->aac_fib_dmat, cmc->cmc_fibmap, cmc->cmc_fibs,
932			AAC_CLUSTER_COUNT * sizeof(struct aac_fib), aac_map_command_cluster, cmc, 0);
933
934	aac_enqueue_cluster(sc, cmc);
935	for (i = 0; i < AAC_CLUSTER_COUNT; i++) {
936	    cm = &cmc->cmc_command[i];
937	    cm->cm_sc = sc;
938	    cm->cm_fib = cmc->cmc_fibs + i;
939	    cm->cm_fibphys = cmc->cmc_fibphys + (i * sizeof(struct aac_fib));
940
941	    if (!bus_dmamap_create(sc->aac_buffer_dmat, 0, &cm->cm_datamap))
942		aac_release_command(cm);
943	}
944    } else {
945	debug(2, "can't allocate memeory for command cluster");
946    }
947}
948
949/********************************************************************************
950 * Free a command cluster.
951 */
952static void
953aac_free_command_cluster(struct aac_command_cluster *cmc)
954{
955    struct aac_softc	*sc = cmc->cmc_command[0].cm_sc;
956    int			i;
957
958    debug_called(1);
959
960    for (i = 0; i < AAC_CLUSTER_COUNT; i++)
961	bus_dmamap_destroy(sc->aac_buffer_dmat, cmc->cmc_command[i].cm_datamap);
962    bus_dmamap_unload(sc->aac_fib_dmat, cmc->cmc_fibmap);
963    bus_dmamem_free(sc->aac_fib_dmat, cmc->cmc_fibs, cmc->cmc_fibmap);
964
965    free(cmc, M_DEVBUF);
966}
967
968/********************************************************************************
969 * Command-mapping helper function - populate this command's s/g table.
970 */
971static void
972aac_map_command_sg(void *arg, bus_dma_segment_t *segs, int nseg, int error)
973{
974    struct aac_command		*cm = (struct aac_command *)arg;
975    struct aac_fib		*fib = cm->cm_fib;
976    struct aac_sg_table		*sg;
977    int				i;
978
979    debug_called(3);
980
981    /* find the s/g table */
982    sg = cm->cm_sgtable;
983
984    /* copy into the FIB */
985    if (sg != NULL) {
986	sg->SgCount = nseg;
987	for (i = 0; i < nseg; i++) {
988	    sg->SgEntry[i].SgAddress = segs[i].ds_addr;
989	    sg->SgEntry[i].SgByteCount = segs[i].ds_len;
990	}
991	/* update the FIB size for the s/g count */
992	fib->Header.Size += nseg * sizeof(struct aac_sg_entry);
993    }
994
995}
996
997/********************************************************************************
998 * Map a command into controller-visible space.
999 */
1000static void
1001aac_map_command(struct aac_command *cm)
1002{
1003    struct aac_softc	*sc = cm->cm_sc;
1004
1005    debug_called(2);
1006
1007    /* don't map more than once */
1008    if (cm->cm_flags & AAC_CMD_MAPPED)
1009	return;
1010
1011    if (cm->cm_datalen != 0) {
1012	bus_dmamap_load(sc->aac_buffer_dmat, cm->cm_datamap, cm->cm_data,
1013			cm->cm_datalen, aac_map_command_sg, cm, 0);
1014
1015	if (cm->cm_flags & AAC_CMD_DATAIN)
1016	    bus_dmamap_sync(sc->aac_buffer_dmat, cm->cm_datamap, BUS_DMASYNC_PREREAD);
1017	if (cm->cm_flags & AAC_CMD_DATAOUT)
1018	    bus_dmamap_sync(sc->aac_buffer_dmat, cm->cm_datamap, BUS_DMASYNC_PREWRITE);
1019    }
1020    cm->cm_flags |= AAC_CMD_MAPPED;
1021}
1022
1023/********************************************************************************
1024 * Unmap a command from controller-visible space.
1025 */
1026static void
1027aac_unmap_command(struct aac_command *cm)
1028{
1029    struct aac_softc	*sc = cm->cm_sc;
1030
1031    debug_called(2);
1032
1033    if (!(cm->cm_flags & AAC_CMD_MAPPED))
1034	return;
1035
1036    if (cm->cm_datalen != 0) {
1037	if (cm->cm_flags & AAC_CMD_DATAIN)
1038	    bus_dmamap_sync(sc->aac_buffer_dmat, cm->cm_datamap, BUS_DMASYNC_POSTREAD);
1039	if (cm->cm_flags & AAC_CMD_DATAOUT)
1040	    bus_dmamap_sync(sc->aac_buffer_dmat, cm->cm_datamap, BUS_DMASYNC_POSTWRITE);
1041
1042	bus_dmamap_unload(sc->aac_buffer_dmat, cm->cm_datamap);
1043    }
1044    cm->cm_flags &= ~AAC_CMD_MAPPED;
1045}
1046
1047/********************************************************************************
1048 ********************************************************************************
1049                                                               Hardware Interface
1050 ********************************************************************************
1051 ********************************************************************************/
1052
1053/********************************************************************************
1054 * Initialise the adapter.
1055 */
1056static void
1057aac_common_map(void *arg, bus_dma_segment_t *segs, int nseg, int error)
1058{
1059    struct aac_softc	*sc = (struct aac_softc *)arg;
1060
1061    debug_called(1);
1062
1063    sc->aac_common_busaddr = segs[0].ds_addr;
1064}
1065
1066static int
1067aac_init(struct aac_softc *sc)
1068{
1069    struct aac_adapter_init	*ip;
1070    time_t			then;
1071    u_int32_t			code;
1072    u_int8_t			*qaddr;
1073
1074    debug_called(1);
1075
1076    /*
1077     * First wait for the adapter to come ready.
1078     */
1079    then = time_second;
1080    do {
1081	code = AAC_GET_FWSTATUS(sc);
1082	if (code & AAC_SELF_TEST_FAILED) {
1083	    device_printf(sc->aac_dev, "FATAL: selftest failed\n");
1084	    return(ENXIO);
1085	}
1086	if (code & AAC_KERNEL_PANIC) {
1087	    device_printf(sc->aac_dev, "FATAL: controller kernel panic\n");
1088	    return(ENXIO);
1089	}
1090	if (time_second > (then + AAC_BOOT_TIMEOUT)) {
1091	    device_printf(sc->aac_dev, "FATAL: controller not coming ready, status %x\n", code);
1092	    return(ENXIO);
1093	}
1094    } while (!(code & AAC_UP_AND_RUNNING));
1095
1096    /*
1097     * Create DMA tag for the common structure and allocate it.
1098     */
1099    if (bus_dma_tag_create(sc->aac_parent_dmat, 	/* parent */
1100			   1, 0, 			/* alignment, boundary */
1101			   BUS_SPACE_MAXADDR,		/* lowaddr */
1102			   BUS_SPACE_MAXADDR, 		/* highaddr */
1103			   NULL, NULL, 			/* filter, filterarg */
1104			   sizeof(struct aac_common), 1,/* maxsize, nsegments */
1105			   BUS_SPACE_MAXSIZE_32BIT,	/* maxsegsize */
1106			   0,				/* flags */
1107			   &sc->aac_common_dmat)) {
1108	device_printf(sc->aac_dev, "can't allocate common structure DMA tag\n");
1109	return(ENOMEM);
1110    }
1111    if (bus_dmamem_alloc(sc->aac_common_dmat, (void **)&sc->aac_common, BUS_DMA_NOWAIT, &sc->aac_common_dmamap)) {
1112	device_printf(sc->aac_dev, "can't allocate common structure\n");
1113	return(ENOMEM);
1114    }
1115    bus_dmamap_load(sc->aac_common_dmat, sc->aac_common_dmamap, sc->aac_common, sizeof(*sc->aac_common),
1116		    aac_common_map, sc, 0);
1117    bzero(sc->aac_common, sizeof(*sc->aac_common));
1118
1119    /*
1120     * Fill in the init structure.  This tells the adapter about the physical location
1121     * of various important shared data structures.
1122     */
1123    ip = &sc->aac_common->ac_init;
1124    ip->InitStructRevision = AAC_INIT_STRUCT_REVISION;
1125
1126    ip->AdapterFibsPhysicalAddress = sc->aac_common_busaddr + offsetof(struct aac_common, ac_fibs);
1127    ip->AdapterFibsVirtualAddress = &sc->aac_common->ac_fibs[0];
1128    ip->AdapterFibsSize = AAC_ADAPTER_FIBS * sizeof(struct aac_fib);
1129    ip->AdapterFibAlign = sizeof(struct aac_fib);
1130
1131    ip->PrintfBufferAddress = sc->aac_common_busaddr + offsetof(struct aac_common, ac_printf);
1132    ip->PrintfBufferSize = AAC_PRINTF_BUFSIZE;
1133
1134    ip->HostPhysMemPages = 0;			/* not used? */
1135    ip->HostElapsedSeconds = time_second;	/* reset later if invalid */
1136
1137    /*
1138     * Initialise FIB queues.  Note that it appears that the layout of the indexes
1139     * and the segmentation of the entries is mandated by the adapter, which is
1140     * only told about the base of the queue index fields.
1141     *
1142     * The initial values of the indices are assumed to inform the adapter
1143     * of the sizes of the respective queues.
1144     *
1145     * The Linux driver uses a much more complex scheme whereby several header
1146     * records are kept for each queue.  We use a couple of generic list manipulation
1147     * functions which 'know' the size of each list by virtue of a table.
1148     */
1149    qaddr = &sc->aac_common->ac_qbuf[0] + AAC_QUEUE_ALIGN;
1150    qaddr -= (u_int32_t)qaddr % AAC_QUEUE_ALIGN;
1151    sc->aac_queues = (struct aac_queue_table *)qaddr;
1152    ip->CommHeaderAddress = sc->aac_common_busaddr + ((u_int32_t)sc->aac_queues - (u_int32_t)sc->aac_common);
1153    bzero(sc->aac_queues, sizeof(struct aac_queue_table));
1154
1155    sc->aac_queues->qt_qindex[AAC_HOST_NORM_CMD_QUEUE][AAC_PRODUCER_INDEX]  = AAC_HOST_NORM_CMD_ENTRIES;
1156    sc->aac_queues->qt_qindex[AAC_HOST_NORM_CMD_QUEUE][AAC_CONSUMER_INDEX]  = AAC_HOST_NORM_CMD_ENTRIES;
1157    sc->aac_queues->qt_qindex[AAC_HOST_HIGH_CMD_QUEUE][AAC_PRODUCER_INDEX]  = AAC_HOST_HIGH_CMD_ENTRIES;
1158    sc->aac_queues->qt_qindex[AAC_HOST_HIGH_CMD_QUEUE][AAC_CONSUMER_INDEX]  = AAC_HOST_HIGH_CMD_ENTRIES;
1159    sc->aac_queues->qt_qindex[AAC_ADAP_NORM_CMD_QUEUE][AAC_PRODUCER_INDEX]  = AAC_ADAP_NORM_CMD_ENTRIES;
1160    sc->aac_queues->qt_qindex[AAC_ADAP_NORM_CMD_QUEUE][AAC_CONSUMER_INDEX]  = AAC_ADAP_NORM_CMD_ENTRIES;
1161    sc->aac_queues->qt_qindex[AAC_ADAP_HIGH_CMD_QUEUE][AAC_PRODUCER_INDEX]  = AAC_ADAP_HIGH_CMD_ENTRIES;
1162    sc->aac_queues->qt_qindex[AAC_ADAP_HIGH_CMD_QUEUE][AAC_CONSUMER_INDEX]  = AAC_ADAP_HIGH_CMD_ENTRIES;
1163    sc->aac_queues->qt_qindex[AAC_HOST_NORM_RESP_QUEUE][AAC_PRODUCER_INDEX] = AAC_HOST_NORM_RESP_ENTRIES;
1164    sc->aac_queues->qt_qindex[AAC_HOST_NORM_RESP_QUEUE][AAC_CONSUMER_INDEX] = AAC_HOST_NORM_RESP_ENTRIES;
1165    sc->aac_queues->qt_qindex[AAC_HOST_HIGH_RESP_QUEUE][AAC_PRODUCER_INDEX] = AAC_HOST_HIGH_RESP_ENTRIES;
1166    sc->aac_queues->qt_qindex[AAC_HOST_HIGH_RESP_QUEUE][AAC_CONSUMER_INDEX] = AAC_HOST_HIGH_RESP_ENTRIES;
1167    sc->aac_queues->qt_qindex[AAC_ADAP_NORM_RESP_QUEUE][AAC_PRODUCER_INDEX] = AAC_ADAP_NORM_RESP_ENTRIES;
1168    sc->aac_queues->qt_qindex[AAC_ADAP_NORM_RESP_QUEUE][AAC_CONSUMER_INDEX] = AAC_ADAP_NORM_RESP_ENTRIES;
1169    sc->aac_queues->qt_qindex[AAC_ADAP_HIGH_RESP_QUEUE][AAC_PRODUCER_INDEX] = AAC_ADAP_HIGH_RESP_ENTRIES;
1170    sc->aac_queues->qt_qindex[AAC_ADAP_HIGH_RESP_QUEUE][AAC_CONSUMER_INDEX] = AAC_ADAP_HIGH_RESP_ENTRIES;
1171    sc->aac_qentries[AAC_HOST_NORM_CMD_QUEUE] = &sc->aac_queues->qt_HostNormCmdQueue[0];
1172    sc->aac_qentries[AAC_HOST_HIGH_CMD_QUEUE] = &sc->aac_queues->qt_HostHighCmdQueue[0];
1173    sc->aac_qentries[AAC_ADAP_NORM_CMD_QUEUE] = &sc->aac_queues->qt_AdapNormCmdQueue[0];
1174    sc->aac_qentries[AAC_ADAP_HIGH_CMD_QUEUE] = &sc->aac_queues->qt_AdapHighCmdQueue[0];
1175    sc->aac_qentries[AAC_HOST_NORM_RESP_QUEUE] = &sc->aac_queues->qt_HostNormRespQueue[0];
1176    sc->aac_qentries[AAC_HOST_HIGH_RESP_QUEUE] = &sc->aac_queues->qt_HostHighRespQueue[0];
1177    sc->aac_qentries[AAC_ADAP_NORM_RESP_QUEUE] = &sc->aac_queues->qt_AdapNormRespQueue[0];
1178    sc->aac_qentries[AAC_ADAP_HIGH_RESP_QUEUE] = &sc->aac_queues->qt_AdapHighRespQueue[0];
1179
1180    /*
1181     * Do controller-type-specific initialisation
1182     */
1183    switch (sc->aac_hwif) {
1184    case AAC_HWIF_I960RX:
1185	AAC_SETREG4(sc, AAC_RX_ODBR, ~0);
1186	break;
1187    }
1188
1189    /*
1190     * Give the init structure to the controller.
1191     */
1192    if (aac_sync_command(sc, AAC_MONKER_INITSTRUCT,
1193			  sc->aac_common_busaddr + offsetof(struct aac_common, ac_init),
1194			  0, 0, 0, NULL)) {
1195	device_printf(sc->aac_dev, "error establishing init structure\n");
1196	return(EIO);
1197    }
1198
1199    return(0);
1200}
1201
1202/********************************************************************************
1203 * Send a synchronous command to the controller and wait for a result.
1204 */
1205static int
1206aac_sync_command(struct aac_softc *sc, u_int32_t command,
1207		       u_int32_t arg0, u_int32_t arg1, u_int32_t arg2, u_int32_t arg3,
1208		       u_int32_t *sp)
1209{
1210    time_t	then;
1211    u_int32_t	status;
1212
1213    debug_called(3);
1214
1215    /* populate the mailbox */
1216    AAC_SET_MAILBOX(sc, command, arg0, arg1, arg2, arg3);
1217
1218    /* ensure the sync command doorbell flag is cleared */
1219    AAC_CLEAR_ISTATUS(sc, AAC_DB_SYNC_COMMAND);
1220
1221    /* then set it to signal the adapter */
1222    AAC_QNOTIFY(sc, AAC_DB_SYNC_COMMAND);
1223
1224    /* spin waiting for the command to complete */
1225    then = time_second;
1226    do {
1227	if (time_second > (then + AAC_IMMEDIATE_TIMEOUT)) {
1228	    debug(2, "timed out");
1229	    return(EIO);
1230	}
1231    } while (!(AAC_GET_ISTATUS(sc) & AAC_DB_SYNC_COMMAND));
1232
1233    /* clear the completion flag */
1234    AAC_CLEAR_ISTATUS(sc, AAC_DB_SYNC_COMMAND);
1235
1236    /* get the command status */
1237    status = AAC_GET_MAILBOXSTATUS(sc);
1238    if (sp != NULL)
1239	*sp = status;
1240    return(0);	/* check command return status? */
1241}
1242
1243/********************************************************************************
1244 * Send a synchronous FIB to the controller and wait for a result.
1245 */
1246static int
1247aac_sync_fib(struct aac_softc *sc, u_int32_t command, u_int32_t xferstate,
1248	     void *data, u_int16_t datasize,
1249	     void *result, u_int16_t *resultsize)
1250{
1251    struct aac_fib	*fib = &sc->aac_common->ac_sync_fib;
1252
1253    debug_called(3);
1254
1255    if (datasize > AAC_FIB_DATASIZE)
1256	return(EINVAL);
1257
1258    /*
1259     * Set up the sync FIB
1260     */
1261    fib->Header.XferState = AAC_FIBSTATE_HOSTOWNED | AAC_FIBSTATE_INITIALISED | AAC_FIBSTATE_EMPTY;
1262    fib->Header.XferState |= xferstate;
1263    fib->Header.Command = command;
1264    fib->Header.StructType = AAC_FIBTYPE_TFIB;
1265    fib->Header.Size = sizeof(struct aac_fib) + datasize;
1266    fib->Header.SenderSize = sizeof(struct aac_fib);
1267    fib->Header.SenderFibAddress = (u_int32_t)fib;
1268    fib->Header.ReceiverFibAddress = sc->aac_common_busaddr + offsetof(struct aac_common, ac_sync_fib);
1269
1270    /*
1271     * Copy in data.
1272     */
1273    if (data != NULL) {
1274	bcopy(data, fib->data, datasize);
1275	fib->Header.XferState |= AAC_FIBSTATE_FROMHOST | AAC_FIBSTATE_NORM;
1276    }
1277
1278    /*
1279     * Give the FIB to the controller, wait for a response.
1280     */
1281    if (aac_sync_command(sc, AAC_MONKER_SYNCFIB, fib->Header.ReceiverFibAddress,
1282			  0, 0, 0, NULL)) {
1283	debug(2, "IO error");
1284	return(EIO);
1285    }
1286
1287    /*
1288     * Copy out the result
1289     */
1290    if (result != NULL) {
1291	*resultsize = fib->Header.Size - sizeof(struct aac_fib_header);
1292	bcopy(fib->data, result, *resultsize);
1293    }
1294    return(0);
1295}
1296
1297/********************************************************************************
1298 * Adapter-space FIB queue manipulation
1299 *
1300 * Note that the queue implementation here is a little funky; neither the PI or
1301 * CI will ever be zero.  This behaviour is a controller feature.
1302 */
1303static struct {
1304    int		size;
1305    int		notify;
1306} aac_qinfo[] = {
1307    {AAC_HOST_NORM_CMD_ENTRIES, AAC_DB_COMMAND_NOT_FULL},
1308    {AAC_HOST_HIGH_CMD_ENTRIES, 0},
1309    {AAC_ADAP_NORM_CMD_ENTRIES, AAC_DB_COMMAND_READY},
1310    {AAC_ADAP_HIGH_CMD_ENTRIES, 0},
1311    {AAC_HOST_NORM_RESP_ENTRIES, AAC_DB_RESPONSE_NOT_FULL},
1312    {AAC_HOST_HIGH_RESP_ENTRIES, 0},
1313    {AAC_ADAP_NORM_RESP_ENTRIES, AAC_DB_RESPONSE_READY},
1314    {AAC_ADAP_HIGH_RESP_ENTRIES, 0}
1315};
1316
1317/*
1318 * Atomically insert an entry into the nominated queue, returns 0 on success or EBUSY
1319 * if the queue is full.
1320 *
1321 * XXX note that it would be more efficient to defer notifying the controller in
1322 * the case where we may be inserting several entries in rapid succession, but
1323 * implementing this usefully is difficult.
1324 */
1325static int
1326aac_enqueue_fib(struct aac_softc *sc, int queue, u_int32_t fib_size, u_int32_t fib_addr)
1327{
1328    u_int32_t	pi, ci;
1329    int		s, error;
1330
1331    debug_called(3);
1332
1333    s = splbio();
1334
1335    /* get the producer/consumer indices */
1336    pi = sc->aac_queues->qt_qindex[queue][AAC_PRODUCER_INDEX];
1337    ci = sc->aac_queues->qt_qindex[queue][AAC_CONSUMER_INDEX];
1338
1339    /* wrap the queue? */
1340    if (pi >= aac_qinfo[queue].size)
1341	pi = 0;
1342
1343    /* check for queue full */
1344    if ((pi + 1) == ci) {
1345	error = EBUSY;
1346	goto out;
1347    }
1348
1349    /* populate queue entry */
1350    (sc->aac_qentries[queue] + pi)->aq_fib_size = fib_size;
1351    (sc->aac_qentries[queue] + pi)->aq_fib_addr = fib_addr;
1352
1353    /* update producer index */
1354    sc->aac_queues->qt_qindex[queue][AAC_PRODUCER_INDEX] = pi + 1;
1355
1356    /* notify the adapter if we know how */
1357    if (aac_qinfo[queue].notify != 0)
1358	AAC_QNOTIFY(sc, aac_qinfo[queue].notify);
1359
1360    error = 0;
1361
1362out:
1363    splx(s);
1364    return(error);
1365}
1366
1367/*
1368 * Atomically remove one entry from the nominated queue, returns 0 on success or ENOENT
1369 * if the queue is empty.
1370 */
1371static int
1372aac_dequeue_fib(struct aac_softc *sc, int queue, u_int32_t *fib_size, struct aac_fib **fib_addr)
1373{
1374    u_int32_t	pi, ci;
1375    int		s, error;
1376
1377    debug_called(3);
1378
1379    s = splbio();
1380
1381    /* get the producer/consumer indices */
1382    pi = sc->aac_queues->qt_qindex[queue][AAC_PRODUCER_INDEX];
1383    ci = sc->aac_queues->qt_qindex[queue][AAC_CONSUMER_INDEX];
1384
1385    /* check for queue empty */
1386    if (ci == pi) {
1387	error = ENOENT;
1388	goto out;
1389    }
1390
1391    /* wrap the queue? */
1392    if (ci >= aac_qinfo[queue].size)
1393	ci = 0;
1394
1395    /* fetch the entry */
1396    *fib_size = (sc->aac_qentries[queue] + ci)->aq_fib_size;
1397    *fib_addr = (struct aac_fib *)(sc->aac_qentries[queue] + ci)->aq_fib_addr;
1398
1399    /* update consumer index */
1400    sc->aac_queues->qt_qindex[queue][AAC_CONSUMER_INDEX] = ci + 1;
1401
1402    /* if we have made the queue un-full, notify the adapter */
1403    if (((pi + 1) == ci) && (aac_qinfo[queue].notify != 0))
1404	AAC_QNOTIFY(sc, aac_qinfo[queue].notify);
1405    error = 0;
1406
1407out:
1408    splx(s);
1409    return(error);
1410}
1411
1412/********************************************************************************
1413 ********************************************************************************
1414                                                       Interface Function Vectors
1415 ********************************************************************************
1416 ********************************************************************************/
1417
1418/********************************************************************************
1419 * Read the current firmware status word.
1420 */
1421static int
1422aac_sa_get_fwstatus(struct aac_softc *sc)
1423{
1424    debug_called(3);
1425
1426    return(AAC_GETREG4(sc, AAC_SA_FWSTATUS));
1427}
1428
1429static int
1430aac_rx_get_fwstatus(struct aac_softc *sc)
1431{
1432    debug_called(3);
1433
1434    return(AAC_GETREG4(sc, AAC_RX_FWSTATUS));
1435}
1436
1437/********************************************************************************
1438 * Notify the controller of a change in a given queue
1439 */
1440
1441static void
1442aac_sa_qnotify(struct aac_softc *sc, int qbit)
1443{
1444    debug_called(3);
1445
1446    AAC_SETREG2(sc, AAC_SA_DOORBELL1_SET, qbit);
1447}
1448
1449static void
1450aac_rx_qnotify(struct aac_softc *sc, int qbit)
1451{
1452    debug_called(3);
1453
1454    AAC_SETREG4(sc, AAC_RX_IDBR, qbit);
1455}
1456
1457/********************************************************************************
1458 * Get the interrupt reason bits
1459 */
1460static int
1461aac_sa_get_istatus(struct aac_softc *sc)
1462{
1463    debug_called(3);
1464
1465    return(AAC_GETREG2(sc, AAC_SA_DOORBELL0));
1466}
1467
1468static int
1469aac_rx_get_istatus(struct aac_softc *sc)
1470{
1471    debug_called(3);
1472
1473    return(AAC_GETREG4(sc, AAC_RX_ODBR));
1474}
1475
1476/********************************************************************************
1477 * Clear some interrupt reason bits
1478 */
1479static void
1480aac_sa_clear_istatus(struct aac_softc *sc, int mask)
1481{
1482    debug_called(3);
1483
1484    AAC_SETREG2(sc, AAC_SA_DOORBELL0_CLEAR, mask);
1485}
1486
1487static void
1488aac_rx_clear_istatus(struct aac_softc *sc, int mask)
1489{
1490    debug_called(3);
1491
1492    AAC_SETREG4(sc, AAC_RX_ODBR, mask);
1493}
1494
1495/********************************************************************************
1496 * Populate the mailbox and set the command word
1497 */
1498static void
1499aac_sa_set_mailbox(struct aac_softc *sc, u_int32_t command,
1500		u_int32_t arg0, u_int32_t arg1, u_int32_t arg2, u_int32_t arg3)
1501{
1502    debug_called(4);
1503
1504    AAC_SETREG4(sc, AAC_SA_MAILBOX, command);
1505    AAC_SETREG4(sc, AAC_SA_MAILBOX + 4, arg0);
1506    AAC_SETREG4(sc, AAC_SA_MAILBOX + 8, arg1);
1507    AAC_SETREG4(sc, AAC_SA_MAILBOX + 12, arg2);
1508    AAC_SETREG4(sc, AAC_SA_MAILBOX + 16, arg3);
1509}
1510
1511static void
1512aac_rx_set_mailbox(struct aac_softc *sc, u_int32_t command,
1513		u_int32_t arg0, u_int32_t arg1, u_int32_t arg2, u_int32_t arg3)
1514{
1515    debug_called(4);
1516
1517    AAC_SETREG4(sc, AAC_RX_MAILBOX, command);
1518    AAC_SETREG4(sc, AAC_RX_MAILBOX + 4, arg0);
1519    AAC_SETREG4(sc, AAC_RX_MAILBOX + 8, arg1);
1520    AAC_SETREG4(sc, AAC_RX_MAILBOX + 12, arg2);
1521    AAC_SETREG4(sc, AAC_RX_MAILBOX + 16, arg3);
1522}
1523
1524/********************************************************************************
1525 * Fetch the immediate command status word
1526 */
1527static int
1528aac_sa_get_mailboxstatus(struct aac_softc *sc)
1529{
1530    debug_called(4);
1531
1532    return(AAC_GETREG4(sc, AAC_SA_MAILBOX));
1533}
1534
1535static int
1536aac_rx_get_mailboxstatus(struct aac_softc *sc)
1537{
1538    debug_called(4);
1539
1540    return(AAC_GETREG4(sc, AAC_RX_MAILBOX));
1541}
1542
1543/********************************************************************************
1544 * Set/clear interrupt masks
1545 */
1546static void
1547aac_sa_set_interrupts(struct aac_softc *sc, int enable)
1548{
1549    debug(2, "%sable interrupts", enable ? "en" : "dis");
1550
1551    if (enable) {
1552	AAC_SETREG2((sc), AAC_SA_MASK0_CLEAR, AAC_DB_INTERRUPTS);
1553    } else {
1554	AAC_SETREG2((sc), AAC_SA_MASK0_SET, ~0);
1555    }
1556}
1557
1558static void
1559aac_rx_set_interrupts(struct aac_softc *sc, int enable)
1560{
1561    debug(2, "%sable interrupts", enable ? "en" : "dis");
1562
1563    if (enable) {
1564	AAC_SETREG4(sc, AAC_RX_OIMR, ~AAC_DB_INTERRUPTS);
1565    } else {
1566	AAC_SETREG4(sc, AAC_RX_OIMR, ~0);
1567    }
1568}
1569
1570/********************************************************************************
1571 ********************************************************************************
1572                                                        Debugging and Diagnostics
1573 ********************************************************************************
1574 ********************************************************************************/
1575
1576/********************************************************************************
1577 * Print some information about the controller.
1578 */
1579static void
1580aac_describe_controller(struct aac_softc *sc)
1581{
1582    u_int8_t			buf[AAC_FIB_DATASIZE];	/* XXX really a bit big for the stack */
1583    u_int16_t			bufsize;
1584    struct aac_adapter_info	*info;
1585    u_int8_t			arg;
1586
1587    debug_called(2);
1588
1589    arg = 0;
1590    if (aac_sync_fib(sc, RequestAdapterInfo, 0, &arg, sizeof(arg), &buf, &bufsize)) {
1591	device_printf(sc->aac_dev, "RequestAdapterInfo failed\n");
1592	return;
1593    }
1594    if (bufsize != sizeof(*info)) {
1595	device_printf(sc->aac_dev, "RequestAdapterInfo returned wrong data size (%d != %d)\n",
1596		      bufsize, sizeof(*info));
1597	return;
1598    }
1599    info = (struct aac_adapter_info *)&buf[0];
1600
1601    device_printf(sc->aac_dev, "%s %dMHz, %dMB total memory, %s (%d)\n",
1602		  aac_describe_code(aac_cpu_variant, info->CpuVariant), info->ClockSpeed,
1603		  info->TotalMem / (1024 * 1024),
1604		  aac_describe_code(aac_battery_platform, info->batteryPlatform), info->batteryPlatform);
1605
1606    /* save the kernel revision structure for later use */
1607    sc->aac_revision = info->KernelRevision;
1608    device_printf(sc->aac_dev, "Kernel %d.%d-%d, S/N %llx\n",
1609		  info->KernelRevision.external.comp.major,
1610		  info->KernelRevision.external.comp.minor,
1611		  info->KernelRevision.external.comp.dash,
1612		  info->SerialNumber);	/* XXX how is this meant to be formatted? */
1613}
1614
1615/********************************************************************************
1616 * Look up a text description of a numeric error code and return a pointer to
1617 * same.
1618 */
1619static char *
1620aac_describe_code(struct aac_code_lookup *table, u_int32_t code)
1621{
1622    int		i;
1623
1624    for (i = 0; table[i].string != NULL; i++)
1625	if (table[i].code == code)
1626	    return(table[i].string);
1627    return(table[i+1].string);
1628}
1629
1630/*****************************************************************************
1631 *****************************************************************************
1632                                                    Management Interface
1633 *****************************************************************************
1634 *****************************************************************************/
1635
1636static int
1637aac_open(dev_t dev, int flags, int fmt, struct proc *p)
1638{
1639    struct aac_softc	*sc = dev->si_drv1;
1640
1641    debug_called(2);
1642
1643    /* Check to make sure the device isn't already open */
1644    if (sc->aac_state & AAC_STATE_OPEN) {
1645        return EBUSY;
1646    }
1647    sc->aac_state |= AAC_STATE_OPEN;
1648
1649    return 0;
1650}
1651
1652static int
1653aac_close(dev_t dev, int flags, int fmt, struct proc *p)
1654{
1655    struct aac_softc	*sc = dev->si_drv1;
1656
1657    debug_called(2);
1658
1659    /* Mark this unit as no longer open  */
1660    sc->aac_state &= ~AAC_STATE_OPEN;
1661
1662    return 0;
1663}
1664
1665static int
1666aac_ioctl(dev_t dev, u_long cmd, caddr_t arg, int flag, struct proc *p)
1667{
1668    struct aac_softc	*sc = dev->si_drv1;
1669    int			error = 0, i;
1670
1671    debug_called(2);
1672
1673    switch (cmd) {
1674#ifdef AAC_COMPAT_LINUX
1675    case FSACTL_SENDFIB:
1676	debug(0, "FSACTL_SENDFIB");
1677	error = aac_ioctl_sendfib(sc, arg);
1678	break;
1679    case FSACTL_AIF_THREAD:
1680	debug(0, "FSACTL_AIF_THREAD");
1681	error = EINVAL;
1682	break;
1683    case FSACTL_OPEN_GET_ADAPTER_FIB:
1684	debug(0, "FSACTL_OPEN_GET_ADAPTER_FIB");
1685	/*
1686	 * Pass the caller out an AdapterFibContext.
1687	 *
1688	 * Note that because we only support one opener, we
1689	 * basically ignore this.  Set the caller's context to a magic
1690	 * number just in case.
1691	 */
1692	i = AAC_AIF_SILLYMAGIC;
1693	error = copyout(&i, arg, sizeof(i));
1694	break;
1695    case FSACTL_GET_NEXT_ADAPTER_FIB:
1696	debug(0, "FSACTL_GET_NEXT_ADAPTER_FIB");
1697	error = aac_linux_getnext_aif(sc, arg);
1698	break;
1699    case FSACTL_CLOSE_GET_ADAPTER_FIB:
1700	debug(0, "FSACTL_CLOSE_GET_ADAPTER_FIB");
1701	/* don't do anything here */
1702	break;
1703    case FSACTL_MINIPORT_REV_CHECK:
1704	debug(0, "FSACTL_MINIPORT_REV_CHECK");
1705	error = aac_linux_rev_check(sc, arg);
1706	break;
1707#endif
1708    default:
1709	device_printf(sc->aac_dev, "unsupported cmd 0x%lx\n", cmd);
1710	error = EINVAL;
1711	break;
1712    }
1713    return(error);
1714}
1715
1716/********************************************************************************
1717 * Send a FIB supplied from userspace
1718 */
1719static int
1720aac_ioctl_sendfib(struct aac_softc *sc, caddr_t ufib)
1721{
1722    struct aac_command 	*cm;
1723    int			size, error;
1724
1725    debug_called(2);
1726
1727    cm = NULL;
1728
1729    /*
1730     * Get a command
1731     */
1732    if (aac_alloc_command(sc, &cm)) {
1733	error = EBUSY;
1734	goto out;
1735    }
1736
1737    /*
1738     * Fetch the FIB header, then re-copy to get data as well.
1739     */
1740    if ((error = copyin(ufib, cm->cm_fib, sizeof(struct aac_fib_header))) != 0)
1741	goto out;
1742    size = cm->cm_fib->Header.Size + sizeof(struct aac_fib_header);
1743    if (size > sizeof(struct aac_fib)) {
1744	device_printf(sc->aac_dev, "incoming FIB oversized (%d > %d)\n", size, sizeof(struct aac_fib));
1745	size = sizeof(struct aac_fib);
1746    }
1747    if ((error = copyin(ufib, cm->cm_fib, size)) != 0)
1748	goto out;
1749    cm->cm_fib->Header.Size = size;
1750
1751    /*
1752     * Pass the FIB to the controller, wait for it to complete.
1753     */
1754    if ((error = aac_wait_command(cm, 30)) != 0)	/* XXX user timeout? */
1755	goto out;
1756
1757    /*
1758     * Copy the FIB and data back out to the caller.
1759     */
1760    size = cm->cm_fib->Header.Size;
1761    if (size > sizeof(struct aac_fib)) {
1762	device_printf(sc->aac_dev, "outbound FIB oversized (%d > %d)\n", size, sizeof(struct aac_fib));
1763	size = sizeof(struct aac_fib);
1764    }
1765    error = copyout(cm->cm_fib, ufib, size);
1766
1767out:
1768    if (cm != NULL)
1769	aac_release_command(cm);
1770    return(error);
1771}
1772
1773/********************************************************************************
1774 * Handle an AIF sent to us by the controller; queue it for later reference.
1775 *
1776 * XXX what's the right thing to do here when the queue is full?  Drop the older
1777 * or newer entries?
1778 */
1779static void
1780aac_handle_aif(struct aac_softc *sc, struct aac_aif_command *aif)
1781{
1782    int		next, s;
1783
1784    debug_called(2);
1785
1786    s = splbio();
1787    next = (sc->aac_aifq_head + 1) % AAC_AIFQ_LENGTH;
1788    if (next != sc->aac_aifq_tail) {
1789	bcopy(aif, &sc->aac_aifq[next], sizeof(struct aac_aif_command));
1790	sc->aac_aifq_head = next;
1791	if (sc->aac_state & AAC_STATE_AIF_SLEEPER)
1792	    wakeup(sc->aac_aifq);
1793    }
1794    splx(s);
1795    aac_print_aif(sc, aif);
1796}
1797
1798/********************************************************************************
1799 * Hand the next AIF off the top of the queue out to userspace.
1800 */
1801static int
1802aac_return_aif(struct aac_softc *sc, caddr_t uptr)
1803{
1804    int		error, s;
1805
1806    debug_called(2);
1807
1808    s = splbio();
1809    if (sc->aac_aifq_tail == sc->aac_aifq_head) {
1810	error = EAGAIN;
1811    } else {
1812	error = copyout(&sc->aac_aifq[sc->aac_aifq_tail], uptr, sizeof(struct aac_aif_command));
1813	if (!error)
1814	    sc->aac_aifq_tail = (sc->aac_aifq_tail + 1) % AAC_AIFQ_LENGTH;
1815    }
1816    splx(s);
1817    return(error);
1818}
1819
1820/********************************************************************************
1821 ********************************************************************************
1822                                                       Linux Management Interface
1823 ********************************************************************************
1824 ********************************************************************************/
1825
1826#ifdef AAC_COMPAT_LINUX
1827
1828#include <sys/proc.h>
1829#include <machine/../linux/linux.h>
1830#include <machine/../linux/linux_proto.h>
1831#include <compat/linux/linux_ioctl.h>
1832
1833#define AAC_LINUX_IOCTL_MIN  0x2000
1834#define AAC_LINUX_IOCTL_MAX  0x21ff
1835
1836static linux_ioctl_function_t aac_linux_ioctl;
1837static struct linux_ioctl_handler aac_handler = {aac_linux_ioctl, AAC_LINUX_IOCTL_MIN, AAC_LINUX_IOCTL_MAX};
1838
1839SYSINIT  (aac_register,   SI_SUB_KLD, SI_ORDER_MIDDLE, linux_ioctl_register_handler, &aac_handler);
1840SYSUNINIT(aac_unregister, SI_SUB_KLD, SI_ORDER_MIDDLE, linux_ioctl_unregister_handler, &aac_handler);
1841
1842MODULE_DEPEND(aac, linux, 1, 1, 1);
1843
1844static int
1845aac_linux_ioctl(struct proc *p, struct linux_ioctl_args *args)
1846{
1847    struct file		*fp = p->p_fd->fd_ofiles[args->fd];
1848    u_long		cmd = args->cmd;
1849
1850    /*
1851     * Pass the ioctl off to our standard handler.
1852     */
1853    return(fo_ioctl(fp, cmd, (caddr_t)args->arg, p));
1854}
1855
1856/********************************************************************************
1857 * Return the Revision of the driver to the userspace and check to see if the
1858 * userspace app is possibly compatible.  This is extremely bogus right now
1859 * because I have no idea how to handle the versioning of this driver.  It is
1860 * needed, though, to get aaccli working.
1861 */
1862static int
1863aac_linux_rev_check(struct aac_softc *sc, caddr_t udata)
1864{
1865    struct aac_rev_check	rev_check;
1866    struct aac_rev_check_resp	rev_check_resp;
1867    int				error = 0;
1868
1869    debug_called(2);
1870
1871    /*
1872     * Copyin the revision struct from userspace
1873     */
1874    if ((error = copyin(udata, (caddr_t)&rev_check, sizeof(struct aac_rev_check))) != 0) {
1875	return error;
1876    }
1877
1878    debug(2, "Userland revision= %d\n", rev_check.callingRevision.buildNumber);
1879
1880    /*
1881     * Doctor up the response struct.
1882     */
1883    rev_check_resp.possiblyCompatible = 1;
1884    rev_check_resp.adapterSWRevision.external.ul = sc->aac_revision.external.ul;
1885    rev_check_resp.adapterSWRevision.buildNumber = sc->aac_revision.buildNumber;
1886
1887    return(copyout((caddr_t)&rev_check_resp, udata, sizeof(struct aac_rev_check_resp)));
1888}
1889
1890/********************************************************************************
1891 * Pass the caller the next AIF in their queue
1892 */
1893static int
1894aac_linux_getnext_aif(struct aac_softc *sc, caddr_t arg)
1895{
1896    struct get_adapter_fib_ioctl	agf;
1897    int					error, s;
1898
1899    debug_called(2);
1900
1901    if ((error = copyin(arg, &agf, sizeof(agf))) == 0) {
1902
1903	/*
1904	 * Check the magic number that we gave the caller.
1905	 */
1906	if (agf.AdapterFibContext != AAC_AIF_SILLYMAGIC) {
1907	    error = EFAULT;
1908	} else {
1909
1910	    s = splbio();
1911	    error = aac_return_aif(sc, agf.AifFib);
1912
1913	    if ((error == EAGAIN) && (agf.Wait)) {
1914		sc->aac_state |= AAC_STATE_AIF_SLEEPER;
1915		while (error == EAGAIN) {
1916		    error = tsleep(sc->aac_aifq, PRIBIO | PCATCH, "aacaif", 0);
1917		    if (error == 0)
1918			error = aac_return_aif(sc, agf.AifFib);
1919		}
1920		sc->aac_state &= ~AAC_STATE_AIF_SLEEPER;
1921	    }
1922	    splx(s);
1923	}
1924    }
1925    return(error);
1926}
1927
1928#endif /* AAC_COMPAT_LINUX */
1929