Home | History | Annotate | Line # | Download | only in ebus
icap_ebus.c revision 1.1.2.2
      1  1.1.2.2  bouyer /*	$NetBSD: icap_ebus.c,v 1.1.2.2 2011/02/08 18:05:06 bouyer Exp $	*/
      2  1.1.2.2  bouyer 
      3  1.1.2.2  bouyer /*-
      4  1.1.2.2  bouyer  * Copyright (c) 2010 The NetBSD Foundation, Inc.
      5  1.1.2.2  bouyer  * All rights reserved.
      6  1.1.2.2  bouyer  *
      7  1.1.2.2  bouyer  * This code was written by Alessandro Forin and Neil Pittman
      8  1.1.2.2  bouyer  * at Microsoft Research and contributed to The NetBSD Foundation
      9  1.1.2.2  bouyer  * by Microsoft Corporation.
     10  1.1.2.2  bouyer  *
     11  1.1.2.2  bouyer  * Redistribution and use in source and binary forms, with or without
     12  1.1.2.2  bouyer  * modification, are permitted provided that the following conditions
     13  1.1.2.2  bouyer  * are met:
     14  1.1.2.2  bouyer  * 1. Redistributions of source code must retain the above copyright
     15  1.1.2.2  bouyer  *    notice, this list of conditions and the following disclaimer.
     16  1.1.2.2  bouyer  * 2. Redistributions in binary form must reproduce the above copyright
     17  1.1.2.2  bouyer  *    notice, this list of conditions and the following disclaimer in the
     18  1.1.2.2  bouyer  *    documentation and/or other materials provided with the distribution.
     19  1.1.2.2  bouyer  *
     20  1.1.2.2  bouyer  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     21  1.1.2.2  bouyer  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     22  1.1.2.2  bouyer  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     23  1.1.2.2  bouyer  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     24  1.1.2.2  bouyer  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     25  1.1.2.2  bouyer  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     26  1.1.2.2  bouyer  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     27  1.1.2.2  bouyer  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     28  1.1.2.2  bouyer  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     29  1.1.2.2  bouyer  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     30  1.1.2.2  bouyer  * POSSIBILITY OF SUCH DAMAGE.
     31  1.1.2.2  bouyer  */
     32  1.1.2.2  bouyer 
     33  1.1.2.2  bouyer #include <sys/cdefs.h>			/* RCS ID & Copyright macro defns */
     34  1.1.2.2  bouyer __KERNEL_RCSID(0, "$NetBSD: icap_ebus.c,v 1.1.2.2 2011/02/08 18:05:06 bouyer Exp $");
     35  1.1.2.2  bouyer 
     36  1.1.2.2  bouyer #include <sys/param.h>
     37  1.1.2.2  bouyer #include <sys/systm.h>
     38  1.1.2.2  bouyer #include <sys/buf.h>
     39  1.1.2.2  bouyer #include <sys/bufq.h>
     40  1.1.2.2  bouyer #include <sys/proc.h>
     41  1.1.2.2  bouyer #include <sys/errno.h>
     42  1.1.2.2  bouyer #include <sys/ioctl.h>
     43  1.1.2.2  bouyer #include <sys/device.h>
     44  1.1.2.2  bouyer #include <sys/conf.h>
     45  1.1.2.2  bouyer #include <uvm/uvm_param.h>
     46  1.1.2.2  bouyer 
     47  1.1.2.2  bouyer #include <emips/ebus/ebusvar.h>
     48  1.1.2.2  bouyer #include <emips/emips/machdep.h>
     49  1.1.2.2  bouyer #include <machine/emipsreg.h>
     50  1.1.2.2  bouyer 
     51  1.1.2.2  bouyer #define DEBUG_INTR   0x01
     52  1.1.2.2  bouyer #define DEBUG_XFERS  0x02
     53  1.1.2.2  bouyer #define DEBUG_STATUS 0x04
     54  1.1.2.2  bouyer #define DEBUG_FUNCS  0x08
     55  1.1.2.2  bouyer #define DEBUG_PROBE  0x10
     56  1.1.2.2  bouyer #define DEBUG_WRITES 0x20
     57  1.1.2.2  bouyer #define DEBUG_READS  0x40
     58  1.1.2.2  bouyer #define DEBUG_ERRORS 0x80
     59  1.1.2.2  bouyer #ifdef DEBUG
     60  1.1.2.2  bouyer int icap_debug = DEBUG_ERRORS;
     61  1.1.2.2  bouyer #define ICAP_DEBUG(x) (icap_debug & (x))
     62  1.1.2.2  bouyer #define DBGME(_lev_,_x_) if ((_lev_) & icap_debug) _x_
     63  1.1.2.2  bouyer #else
     64  1.1.2.2  bouyer #define ICAP_DEBUG(x) (0)
     65  1.1.2.2  bouyer #define DBGME(_lev_,_x_)
     66  1.1.2.2  bouyer #endif
     67  1.1.2.2  bouyer #define DEBUG_PRINT(_args_,_lev_) DBGME(_lev_,printf _args_)
     68  1.1.2.2  bouyer 
     69  1.1.2.2  bouyer /*
     70  1.1.2.2  bouyer  * Device softc
     71  1.1.2.2  bouyer  */
     72  1.1.2.2  bouyer struct icap_softc {
     73  1.1.2.2  bouyer 	device_t sc_dev;
     74  1.1.2.2  bouyer 	struct _Icap *sc_dp;
     75  1.1.2.2  bouyer 	struct bufq_state *sc_buflist;
     76  1.1.2.2  bouyer 	struct buf *sc_bp;
     77  1.1.2.2  bouyer 	char *sc_data;
     78  1.1.2.2  bouyer 	int sc_count;
     79  1.1.2.2  bouyer };
     80  1.1.2.2  bouyer 
     81  1.1.2.2  bouyer /* Required funcs
     82  1.1.2.2  bouyer  */
     83  1.1.2.2  bouyer static int	icap_ebus_match (struct device *, struct cfdata *, void *);
     84  1.1.2.2  bouyer static void	icap_ebus_attach (struct device *, struct device *, void *);
     85  1.1.2.2  bouyer 
     86  1.1.2.2  bouyer static dev_type_open(icapopen);
     87  1.1.2.2  bouyer static dev_type_close(icapclose);
     88  1.1.2.2  bouyer static dev_type_read(icapread);
     89  1.1.2.2  bouyer static dev_type_write(icapwrite);
     90  1.1.2.2  bouyer static dev_type_ioctl(icapioctl);
     91  1.1.2.2  bouyer static dev_type_strategy(icapstrategy);
     92  1.1.2.2  bouyer 
     93  1.1.2.2  bouyer /* Other functions
     94  1.1.2.2  bouyer  */
     95  1.1.2.2  bouyer extern paddr_t kvtophys(vaddr_t);
     96  1.1.2.2  bouyer static void icapstart(struct icap_softc *sc);
     97  1.1.2.2  bouyer static int  icap_ebus_intr(void *cookie, void *f);
     98  1.1.2.2  bouyer static void icap_reset(struct icap_softc *sc);
     99  1.1.2.2  bouyer 
    100  1.1.2.2  bouyer /* Config stuff
    101  1.1.2.2  bouyer  */
    102  1.1.2.2  bouyer extern struct cfdriver icap_cd;
    103  1.1.2.2  bouyer 
    104  1.1.2.2  bouyer CFATTACH_DECL_NEW(icap_ebus, sizeof (struct icap_softc),
    105  1.1.2.2  bouyer     icap_ebus_match, icap_ebus_attach, NULL, NULL);
    106  1.1.2.2  bouyer 
    107  1.1.2.2  bouyer static int
    108  1.1.2.2  bouyer icap_ebus_match(struct device *parent, struct cfdata *match, void *aux)
    109  1.1.2.2  bouyer {
    110  1.1.2.2  bouyer 	struct ebus_attach_args *ia = aux;
    111  1.1.2.2  bouyer     struct _Icap *f = (struct _Icap *)ia->ia_vaddr;
    112  1.1.2.2  bouyer 
    113  1.1.2.2  bouyer 	DEBUG_PRINT(("icap_match %x\n", (f) ? f->Tag : 0), DEBUG_PROBE);
    114  1.1.2.2  bouyer 	if (strcmp("icap", ia->ia_name) != 0)
    115  1.1.2.2  bouyer 		return (0);
    116  1.1.2.2  bouyer     if ((f == NULL) ||
    117  1.1.2.2  bouyer         (! (f->Tag == PMTTAG_ICAP)))
    118  1.1.2.2  bouyer 		return (0);
    119  1.1.2.2  bouyer 
    120  1.1.2.2  bouyer 	return (1);
    121  1.1.2.2  bouyer }
    122  1.1.2.2  bouyer 
    123  1.1.2.2  bouyer static void
    124  1.1.2.2  bouyer icap_ebus_attach(struct device *parent, struct device *self, void *aux)
    125  1.1.2.2  bouyer {
    126  1.1.2.2  bouyer 	struct icap_softc *sc = device_private(self);
    127  1.1.2.2  bouyer 	struct ebus_attach_args *ia =aux;
    128  1.1.2.2  bouyer 
    129  1.1.2.2  bouyer 	DEBUG_PRINT(("icap_attach %p\n", sc), DEBUG_PROBE);
    130  1.1.2.2  bouyer 
    131  1.1.2.2  bouyer 	sc->sc_dev = self;
    132  1.1.2.2  bouyer 	sc->sc_dp = (struct _Icap*)ia->ia_vaddr;
    133  1.1.2.2  bouyer 	bufq_alloc(&sc->sc_buflist, "fcfs", 0);
    134  1.1.2.2  bouyer 	sc->sc_bp = NULL;
    135  1.1.2.2  bouyer 	sc->sc_data = NULL;
    136  1.1.2.2  bouyer 	sc->sc_count = 0;
    137  1.1.2.2  bouyer 
    138  1.1.2.2  bouyer #if DEBUG
    139  1.1.2.2  bouyer     printf(" virt=%p", (void*)sc->sc_dp);
    140  1.1.2.2  bouyer #endif
    141  1.1.2.2  bouyer 	printf(": %s\n", "Internal Configuration Access Port");
    142  1.1.2.2  bouyer 
    143  1.1.2.2  bouyer 	ebus_intr_establish(parent, (void*)ia->ia_cookie, IPL_BIO,
    144  1.1.2.2  bouyer 	    icap_ebus_intr, sc);
    145  1.1.2.2  bouyer 
    146  1.1.2.2  bouyer 	icap_reset(sc);
    147  1.1.2.2  bouyer }
    148  1.1.2.2  bouyer 
    149  1.1.2.2  bouyer /* The character device handlers
    150  1.1.2.2  bouyer  */
    151  1.1.2.2  bouyer const struct cdevsw icap_cdevsw = {
    152  1.1.2.2  bouyer 	icapopen,
    153  1.1.2.2  bouyer 	icapclose,
    154  1.1.2.2  bouyer 	icapread,
    155  1.1.2.2  bouyer 	icapwrite,
    156  1.1.2.2  bouyer 	icapioctl,
    157  1.1.2.2  bouyer 	nostop,
    158  1.1.2.2  bouyer 	notty,
    159  1.1.2.2  bouyer 	nopoll,
    160  1.1.2.2  bouyer 	nommap,
    161  1.1.2.2  bouyer 	nokqfilter,
    162  1.1.2.2  bouyer };
    163  1.1.2.2  bouyer 
    164  1.1.2.2  bouyer /*
    165  1.1.2.2  bouyer  * Handle an open request on the device.
    166  1.1.2.2  bouyer  */
    167  1.1.2.2  bouyer static int
    168  1.1.2.2  bouyer icapopen(dev_t device, int flags, int fmt, struct lwp *process)
    169  1.1.2.2  bouyer {
    170  1.1.2.2  bouyer 	struct icap_softc *sc;
    171  1.1.2.2  bouyer 
    172  1.1.2.2  bouyer 	DEBUG_PRINT(("icapopen\n"), DEBUG_FUNCS);
    173  1.1.2.2  bouyer 	sc = device_lookup_private(&icap_cd, minor(device));
    174  1.1.2.2  bouyer 	if (sc == NULL)
    175  1.1.2.2  bouyer 		return (ENXIO);
    176  1.1.2.2  bouyer 
    177  1.1.2.2  bouyer 	return 0;
    178  1.1.2.2  bouyer }
    179  1.1.2.2  bouyer 
    180  1.1.2.2  bouyer /*
    181  1.1.2.2  bouyer  * Handle the close request for the device.
    182  1.1.2.2  bouyer  */
    183  1.1.2.2  bouyer static int
    184  1.1.2.2  bouyer icapclose(dev_t device, int flags, int fmt, struct lwp *process)
    185  1.1.2.2  bouyer {
    186  1.1.2.2  bouyer 	DEBUG_PRINT(("icapclose\n"), DEBUG_FUNCS);
    187  1.1.2.2  bouyer 	return 0; /* this always succeeds */
    188  1.1.2.2  bouyer }
    189  1.1.2.2  bouyer 
    190  1.1.2.2  bouyer /*
    191  1.1.2.2  bouyer  * Handle the read request for the device.
    192  1.1.2.2  bouyer  */
    193  1.1.2.2  bouyer static int
    194  1.1.2.2  bouyer icapread(dev_t dev, struct uio *uio, int flags)
    195  1.1.2.2  bouyer {
    196  1.1.2.2  bouyer 	DEBUG_PRINT(("icapread\n"), DEBUG_READS);
    197  1.1.2.2  bouyer 	return (physio(icapstrategy, NULL, dev, B_READ, minphys, uio));
    198  1.1.2.2  bouyer }
    199  1.1.2.2  bouyer 
    200  1.1.2.2  bouyer /*
    201  1.1.2.2  bouyer  * Handle the write request for the device.
    202  1.1.2.2  bouyer  */
    203  1.1.2.2  bouyer static int
    204  1.1.2.2  bouyer icapwrite(dev_t dev, struct uio *uio, int flags)
    205  1.1.2.2  bouyer {
    206  1.1.2.2  bouyer 	DEBUG_PRINT(("icapwrite\n"), DEBUG_WRITES);
    207  1.1.2.2  bouyer 	return (physio(icapstrategy, NULL, dev, B_WRITE, minphys, uio));
    208  1.1.2.2  bouyer }
    209  1.1.2.2  bouyer 
    210  1.1.2.2  bouyer /*
    211  1.1.2.2  bouyer  * Handle the ioctl request for the device.
    212  1.1.2.2  bouyer  */
    213  1.1.2.2  bouyer static int
    214  1.1.2.2  bouyer icapioctl(dev_t dev, u_long xfer, void *addr, int flag, struct lwp *l)
    215  1.1.2.2  bouyer {
    216  1.1.2.2  bouyer 
    217  1.1.2.2  bouyer 	return ENOTTY;
    218  1.1.2.2  bouyer }
    219  1.1.2.2  bouyer 
    220  1.1.2.2  bouyer /*
    221  1.1.2.2  bouyer  * Strategy function for the device.
    222  1.1.2.2  bouyer  */
    223  1.1.2.2  bouyer static void
    224  1.1.2.2  bouyer icapstrategy(struct buf *bp)
    225  1.1.2.2  bouyer {
    226  1.1.2.2  bouyer 	struct icap_softc *sc;
    227  1.1.2.2  bouyer 	int s;
    228  1.1.2.2  bouyer 
    229  1.1.2.2  bouyer 	DEBUG_PRINT(("icapstrategy\n"), DEBUG_FUNCS);
    230  1.1.2.2  bouyer 
    231  1.1.2.2  bouyer 	/* We did nothing lest we did */
    232  1.1.2.2  bouyer 	bp->b_resid = bp->b_bcount;
    233  1.1.2.2  bouyer 
    234  1.1.2.2  bouyer 	/* Do we know you.  */
    235  1.1.2.2  bouyer 	sc = device_lookup_private(&icap_cd, minor(bp->b_dev));
    236  1.1.2.2  bouyer 	if (sc == NULL) {
    237  1.1.2.2  bouyer 		DEBUG_PRINT(("icapstrategy: nodev %x\n",bp->b_dev),
    238  1.1.2.2  bouyer 		    DEBUG_ERRORS);
    239  1.1.2.2  bouyer 		bp->b_error = ENXIO;
    240  1.1.2.2  bouyer 		biodone(bp);
    241  1.1.2.2  bouyer 		return;
    242  1.1.2.2  bouyer 	    }
    243  1.1.2.2  bouyer 
    244  1.1.2.2  bouyer 	/* Add to Q. If Q was empty get it started */
    245  1.1.2.2  bouyer 	s = splbio();
    246  1.1.2.2  bouyer 	bufq_put(sc->sc_buflist, bp);
    247  1.1.2.2  bouyer 	if (bufq_peek(sc->sc_buflist) == bp) {
    248  1.1.2.2  bouyer 		icapstart(sc);
    249  1.1.2.2  bouyer 	}
    250  1.1.2.2  bouyer 	splx(s);
    251  1.1.2.2  bouyer }
    252  1.1.2.2  bouyer 
    253  1.1.2.2  bouyer /*
    254  1.1.2.2  bouyer  * Get the next I/O request started
    255  1.1.2.2  bouyer  */
    256  1.1.2.2  bouyer static void
    257  1.1.2.2  bouyer icapstart(struct icap_softc *sc)
    258  1.1.2.2  bouyer {
    259  1.1.2.2  bouyer 	paddr_t phys, phys2;
    260  1.1.2.2  bouyer 	vaddr_t virt;
    261  1.1.2.2  bouyer 	size_t count;
    262  1.1.2.2  bouyer 	uint32_t fl;
    263  1.1.2.2  bouyer 	struct buf *bp = sc->sc_bp;
    264  1.1.2.2  bouyer 
    265  1.1.2.2  bouyer 	DEBUG_PRINT(("icapstart %p %p\n",sc,bp), DEBUG_FUNCS);
    266  1.1.2.2  bouyer 
    267  1.1.2.2  bouyer     /* Were we idle?
    268  1.1.2.2  bouyer      */
    269  1.1.2.2  bouyer  recheck:
    270  1.1.2.2  bouyer     if (bp == NULL) {
    271  1.1.2.2  bouyer 
    272  1.1.2.2  bouyer         /* Yes, get the next request if any
    273  1.1.2.2  bouyer          */
    274  1.1.2.2  bouyer         bp = bufq_get(sc->sc_buflist);
    275  1.1.2.2  bouyer         DEBUG_PRINT(("icapnext: %p\n",bp), DEBUG_XFERS);
    276  1.1.2.2  bouyer         if (bp == NULL)
    277  1.1.2.2  bouyer             return;
    278  1.1.2.2  bouyer     }
    279  1.1.2.2  bouyer 
    280  1.1.2.2  bouyer     /* Done with this request?
    281  1.1.2.2  bouyer      */
    282  1.1.2.2  bouyer     if ((bp->b_resid == 0) || bp->b_error) {
    283  1.1.2.2  bouyer 
    284  1.1.2.2  bouyer         /* Yes, complete and move to next, if any
    285  1.1.2.2  bouyer          */
    286  1.1.2.2  bouyer         sc->sc_bp = NULL;
    287  1.1.2.2  bouyer         biodone(bp);
    288  1.1.2.2  bouyer         DEBUG_PRINT(("icapdone %p\n",bp), DEBUG_XFERS);
    289  1.1.2.2  bouyer         bp = NULL;
    290  1.1.2.2  bouyer         goto recheck;
    291  1.1.2.2  bouyer     }
    292  1.1.2.2  bouyer 
    293  1.1.2.2  bouyer     /* If new request init the xfer info
    294  1.1.2.2  bouyer      */
    295  1.1.2.2  bouyer     if (sc->sc_bp == NULL) {
    296  1.1.2.2  bouyer         sc->sc_bp = bp;
    297  1.1.2.2  bouyer         sc->sc_data = bp->b_data;
    298  1.1.2.2  bouyer         sc->sc_count = bp->b_resid;
    299  1.1.2.2  bouyer     }
    300  1.1.2.2  bouyer 
    301  1.1.2.2  bouyer     /* Loop filling as many buffers as will fit in the FIFO
    302  1.1.2.2  bouyer      */
    303  1.1.2.2  bouyer     fl = (bp->b_flags & B_READ) ? ICAPS_F_RECV : ICAPS_F_XMIT;
    304  1.1.2.2  bouyer     for (;;) {
    305  1.1.2.2  bouyer 
    306  1.1.2.2  bouyer         /* Make sure there's still room in the FIFO, no errors.
    307  1.1.2.2  bouyer          */
    308  1.1.2.2  bouyer         if (sc->sc_dp->Control & (ICAPC_IF_FULL|ICAPC_ERROR))
    309  1.1.2.2  bouyer             break;
    310  1.1.2.2  bouyer 
    311  1.1.2.2  bouyer         /* How much data do we xfer and where
    312  1.1.2.2  bouyer          */
    313  1.1.2.2  bouyer         virt = (vaddr_t)sc->sc_data;
    314  1.1.2.2  bouyer         phys = kvtophys(virt);
    315  1.1.2.2  bouyer         count = round_page(virt) - virt;
    316  1.1.2.2  bouyer         if (count == 0) count = PAGE_SIZE;/* could(will) be aligned */
    317  1.1.2.2  bouyer 
    318  1.1.2.2  bouyer         /* How much of it is contiguous
    319  1.1.2.2  bouyer          */
    320  1.1.2.2  bouyer         while (count < sc->sc_count) {
    321  1.1.2.2  bouyer             phys2 = kvtophys(virt + count);
    322  1.1.2.2  bouyer             if (phys2 != (phys + count)) {
    323  1.1.2.2  bouyer 
    324  1.1.2.2  bouyer                 /* No longer contig, ship it
    325  1.1.2.2  bouyer                  */
    326  1.1.2.2  bouyer                 break;
    327  1.1.2.2  bouyer             }
    328  1.1.2.2  bouyer             count += PAGE_SIZE;
    329  1.1.2.2  bouyer         }
    330  1.1.2.2  bouyer 
    331  1.1.2.2  bouyer         /* Trim if we went too far
    332  1.1.2.2  bouyer          */
    333  1.1.2.2  bouyer         if (count > sc->sc_count)
    334  1.1.2.2  bouyer             count = sc->sc_count;
    335  1.1.2.2  bouyer 
    336  1.1.2.2  bouyer         /* Ship it
    337  1.1.2.2  bouyer          */
    338  1.1.2.2  bouyer         DEBUG_PRINT(("icapship %lx %d\n",phys,count), DEBUG_XFERS);
    339  1.1.2.2  bouyer         sc->sc_dp->SizeAndFlags = fl | count;
    340  1.1.2.2  bouyer         sc->sc_dp->BufferAddressHi32 = 0; /* BUGBUG 64bit */
    341  1.1.2.2  bouyer         sc->sc_dp->BufferAddressLo32 = phys; /* this pushes the fifo */
    342  1.1.2.2  bouyer 
    343  1.1.2.2  bouyer         /* Adjust pointers and continue
    344  1.1.2.2  bouyer          */
    345  1.1.2.2  bouyer         sc->sc_data  += count;
    346  1.1.2.2  bouyer         sc->sc_count -= count;
    347  1.1.2.2  bouyer 
    348  1.1.2.2  bouyer         if (sc->sc_count <= 0)
    349  1.1.2.2  bouyer             break;
    350  1.1.2.2  bouyer     }
    351  1.1.2.2  bouyer }
    352  1.1.2.2  bouyer 
    353  1.1.2.2  bouyer /*
    354  1.1.2.2  bouyer  * Interrupt handler
    355  1.1.2.2  bouyer  */
    356  1.1.2.2  bouyer static int
    357  1.1.2.2  bouyer icap_ebus_intr(void *cookie, void *f)
    358  1.1.2.2  bouyer {
    359  1.1.2.2  bouyer 	struct icap_softc *sc = cookie;
    360  1.1.2.2  bouyer     struct buf *bp = sc->sc_bp;
    361  1.1.2.2  bouyer 	u_int32_t isr, saf = 0, hi, lo;
    362  1.1.2.2  bouyer 
    363  1.1.2.2  bouyer 	isr = sc->sc_dp->Control;
    364  1.1.2.2  bouyer 
    365  1.1.2.2  bouyer 	DEBUG_PRINT(("i %x\n",isr), DEBUG_INTR);
    366  1.1.2.2  bouyer 
    367  1.1.2.2  bouyer     /* Make sure there is an interrupt and that we should take it
    368  1.1.2.2  bouyer      */
    369  1.1.2.2  bouyer 	if ((isr & (ICAPC_INTEN|ICAPC_DONE)) != (ICAPC_INTEN|ICAPC_DONE))
    370  1.1.2.2  bouyer 		return (0);
    371  1.1.2.2  bouyer 
    372  1.1.2.2  bouyer     /* Pull out all completed buffers
    373  1.1.2.2  bouyer      */
    374  1.1.2.2  bouyer     while ((isr & ICAPC_OF_EMPTY) == 0) {
    375  1.1.2.2  bouyer 
    376  1.1.2.2  bouyer         if (isr & ICAPC_ERROR) {
    377  1.1.2.2  bouyer             printf("%s: internal error (%x)\n", device_xname(sc->sc_dev),isr);
    378  1.1.2.2  bouyer             icap_reset(sc);
    379  1.1.2.2  bouyer             if (bp) {
    380  1.1.2.2  bouyer                 bp->b_error = EIO;
    381  1.1.2.2  bouyer                 icapstart(sc);
    382  1.1.2.2  bouyer             }
    383  1.1.2.2  bouyer             return (1);
    384  1.1.2.2  bouyer         }
    385  1.1.2.2  bouyer 
    386  1.1.2.2  bouyer         /* Beware, order matters */
    387  1.1.2.2  bouyer         saf = sc->sc_dp->SizeAndFlags;
    388  1.1.2.2  bouyer         hi  = sc->sc_dp->BufferAddressHi32; /* BUGBUG 64bit */
    389  1.1.2.2  bouyer         lo  = sc->sc_dp->BufferAddressLo32; /* this pops the fifo */
    390  1.1.2.2  bouyer 
    391  1.1.2.2  bouyer         /* Say its done that much (and sanity)
    392  1.1.2.2  bouyer          */
    393  1.1.2.2  bouyer         if (bp) {
    394  1.1.2.2  bouyer             size_t count = saf & ICAPS_S_MASK;
    395  1.1.2.2  bouyer             /* more sanity */
    396  1.1.2.2  bouyer             if (count > bp->b_resid)
    397  1.1.2.2  bouyer                 count = bp->b_resid;
    398  1.1.2.2  bouyer             bp->b_resid -= count;
    399  1.1.2.2  bouyer         }
    400  1.1.2.2  bouyer 
    401  1.1.2.2  bouyer         /* More? */
    402  1.1.2.2  bouyer         isr = sc->sc_dp->Control;
    403  1.1.2.2  bouyer     }
    404  1.1.2.2  bouyer 
    405  1.1.2.2  bouyer     /* Did we pop at least one */
    406  1.1.2.2  bouyer     if (saf)
    407  1.1.2.2  bouyer         icapstart(sc);
    408  1.1.2.2  bouyer 
    409  1.1.2.2  bouyer 	return (1);
    410  1.1.2.2  bouyer }
    411  1.1.2.2  bouyer 
    412  1.1.2.2  bouyer /*
    413  1.1.2.2  bouyer  * HW (re)Initialization
    414  1.1.2.2  bouyer  */
    415  1.1.2.2  bouyer static void
    416  1.1.2.2  bouyer icap_reset(struct icap_softc *sc)
    417  1.1.2.2  bouyer {
    418  1.1.2.2  bouyer 	DEBUG_PRINT(("icap_reset %x\n",sc->sc_dp->Control), DEBUG_STATUS);
    419  1.1.2.2  bouyer     sc->sc_dp->Control = ICAPC_RESET;
    420  1.1.2.2  bouyer     DELAY(2);
    421  1.1.2.2  bouyer     sc->sc_dp->Control = ICAPC_INTEN;
    422  1.1.2.2  bouyer }
    423