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