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