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