]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/sparc64/sbus/lsi64854.c
Add libbearssl
[FreeBSD/FreeBSD.git] / sys / sparc64 / sbus / lsi64854.c
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD AND BSD-2-Clause-NetBSD
3  *
4  * Copyright (c) 2004 Scott Long
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  *
28  */
29
30 /*      $NetBSD: lsi64854.c,v 1.33 2008/04/28 20:23:50 martin Exp $ */
31
32 /*-
33  * Copyright (c) 1998 The NetBSD Foundation, Inc.
34  * All rights reserved.
35  *
36  * This code is derived from software contributed to The NetBSD Foundation
37  * by Paul Kranenburg.
38  *
39  * Redistribution and use in source and binary forms, with or without
40  * modification, are permitted provided that the following conditions
41  * are met:
42  * 1. Redistributions of source code must retain the above copyright
43  *    notice, this list of conditions and the following disclaimer.
44  * 2. Redistributions in binary form must reproduce the above copyright
45  *    notice, this list of conditions and the following disclaimer in the
46  *    documentation and/or other materials provided with the distribution.
47  *
48  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
49  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
50  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
51  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
52  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
53  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
54  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
55  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
56  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
57  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
58  * POSSIBILITY OF SUCH DAMAGE.
59  */
60
61 #include <sys/cdefs.h>
62 __FBSDID("$FreeBSD$");
63
64 #include <sys/param.h>
65 #include <sys/systm.h>
66 #include <sys/bus.h>
67 #include <sys/kernel.h>
68 #include <sys/lock.h>
69 #include <sys/mutex.h>
70 #include <sys/rman.h>
71
72 #include <machine/bus.h>
73
74 #include <cam/cam.h>
75 #include <cam/cam_ccb.h>
76 #include <cam/scsi/scsi_all.h>
77
78 #include <sparc64/sbus/lsi64854reg.h>
79 #include <sparc64/sbus/lsi64854var.h>
80
81 #include <dev/esp/ncr53c9xreg.h>
82 #include <dev/esp/ncr53c9xvar.h>
83
84 #ifdef DEBUG
85 #define LDB_SCSI        1
86 #define LDB_ENET        2
87 #define LDB_PP          4
88 #define LDB_ANY         0xff
89 int lsi64854debug = 0;
90 #define DPRINTF(a,x)                                                    \
91         do {                                                            \
92                 if ((lsi64854debug & (a)) != 0)                         \
93                         printf x;                                       \
94         } while (/* CONSTCOND */0)
95 #else
96 #define DPRINTF(a,x)
97 #endif
98
99 /*
100  * The rules say we cannot transfer more than the limit of this DMA chip (64k
101  * for old and 16Mb for new), and we cannot cross a 16Mb boundary.
102  */
103 #define MAX_DMA_SZ      (64 * 1024)
104 #define BOUNDARY        (16 * 1024 * 1024)
105
106 static void     lsi64854_reset(struct lsi64854_softc *);
107 static void     lsi64854_map_scsi(void *, bus_dma_segment_t *, int, int);
108 static int      lsi64854_setup(struct lsi64854_softc *, void **, size_t *,
109                     int, size_t *);
110 static int      lsi64854_scsi_intr(void *);
111 static int      lsi64854_enet_intr(void *);
112 static int      lsi64854_setup_pp(struct lsi64854_softc *, void **,
113                     size_t *, int, size_t *);
114 static int      lsi64854_pp_intr(void *);
115
116 /*
117  * Finish attaching this DMA device.
118  * Front-end must fill in these fields:
119  *      sc_res
120  *      sc_burst
121  *      sc_channel (one of SCSI, ENET, PP)
122  *      sc_client (one of SCSI, ENET, PP `soft_c' pointers)
123  */
124 int
125 lsi64854_attach(struct lsi64854_softc *sc)
126 {
127         bus_dma_lock_t *lockfunc;
128         struct ncr53c9x_softc *nsc;
129         void *lockfuncarg;
130         uint32_t csr;
131         int error;
132
133         lockfunc = NULL;
134         lockfuncarg = NULL;
135         sc->sc_maxdmasize = MAX_DMA_SZ;
136
137         switch (sc->sc_channel) {
138         case L64854_CHANNEL_SCSI:
139                 nsc = sc->sc_client;
140                 if (NCR_LOCK_INITIALIZED(nsc) == 0) {
141                         device_printf(sc->sc_dev, "mutex not initialized\n");
142                         return (ENXIO);
143                 }
144                 lockfunc = busdma_lock_mutex;
145                 lockfuncarg = &nsc->sc_lock;
146                 sc->sc_maxdmasize = nsc->sc_maxxfer;
147                 sc->intr = lsi64854_scsi_intr;
148                 sc->setup = lsi64854_setup;
149                 break;
150         case L64854_CHANNEL_ENET:
151                 sc->intr = lsi64854_enet_intr;
152                 break;
153         case L64854_CHANNEL_PP:
154                 sc->intr = lsi64854_pp_intr;
155                 sc->setup = lsi64854_setup_pp;
156                 break;
157         default:
158                 device_printf(sc->sc_dev, "unknown channel\n");
159         }
160         sc->reset = lsi64854_reset;
161
162         if (sc->setup != NULL) {
163                 error = bus_dma_tag_create(
164                     sc->sc_parent_dmat,         /* parent */
165                     1, BOUNDARY,                /* alignment, boundary */
166                     BUS_SPACE_MAXADDR_32BIT,    /* lowaddr */
167                     BUS_SPACE_MAXADDR,          /* highaddr */
168                     NULL, NULL,                 /* filter, filterarg */
169                     sc->sc_maxdmasize,          /* maxsize */
170                     1,                          /* nsegments */
171                     sc->sc_maxdmasize,          /* maxsegsize */
172                     BUS_DMA_ALLOCNOW,           /* flags */
173                     lockfunc, lockfuncarg,      /* lockfunc, lockfuncarg */
174                     &sc->sc_buffer_dmat);
175                 if (error != 0) {
176                         device_printf(sc->sc_dev,
177                             "cannot allocate buffer DMA tag\n");
178                         return (error);
179                 }
180
181                 error = bus_dmamap_create(sc->sc_buffer_dmat, 0,
182                     &sc->sc_dmamap);
183                 if (error != 0) {
184                         device_printf(sc->sc_dev, "DMA map create failed\n");
185                         bus_dma_tag_destroy(sc->sc_buffer_dmat);
186                         return (error);
187                 }
188         }
189
190         csr = L64854_GCSR(sc);
191         sc->sc_rev = csr & L64854_DEVID;
192         if (sc->sc_rev == DMAREV_HME)
193                 return (0);
194         device_printf(sc->sc_dev, "DMA rev. ");
195         switch (sc->sc_rev) {
196         case DMAREV_0:
197                 printf("0");
198                 break;
199         case DMAREV_ESC:
200                 printf("ESC");
201                 break;
202         case DMAREV_1:
203                 printf("1");
204                 break;
205         case DMAREV_PLUS:
206                 printf("1+");
207                 break;
208         case DMAREV_2:
209                 printf("2");
210                 break;
211         default:
212                 printf("unknown (0x%x)", sc->sc_rev);
213         }
214
215         DPRINTF(LDB_ANY, (", burst 0x%x, csr 0x%x", sc->sc_burst, csr));
216         printf("\n");
217
218         return (0);
219 }
220
221 int
222 lsi64854_detach(struct lsi64854_softc *sc)
223 {
224
225         if (sc->setup != NULL) {
226                 bus_dmamap_sync(sc->sc_buffer_dmat, sc->sc_dmamap,
227                     (L64854_GCSR(sc) & L64854_WRITE) != 0 ?
228                     BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE);
229                 bus_dmamap_unload(sc->sc_buffer_dmat, sc->sc_dmamap);
230                 bus_dmamap_destroy(sc->sc_buffer_dmat, sc->sc_dmamap);
231                 bus_dma_tag_destroy(sc->sc_buffer_dmat);
232         }
233
234         return (0);
235 }
236
237 /*
238  * DMAWAIT waits while condition is true.
239  */
240 #define DMAWAIT(SC, COND, MSG, DONTPANIC) do if (COND) {                \
241         int count = 500000;                                             \
242         while ((COND) && --count > 0) DELAY(1);                         \
243         if (count == 0) {                                               \
244                 printf("%s: line %d: CSR = 0x%lx\n", __FILE__, __LINE__, \
245                         (u_long)L64854_GCSR(SC));                       \
246                 if (DONTPANIC)                                          \
247                         printf(MSG);                                    \
248                 else                                                    \
249                         panic(MSG);                                     \
250         }                                                               \
251 } while (/* CONSTCOND */0)
252
253 #define DMA_DRAIN(sc, dontpanic) do {                                   \
254         uint32_t csr;                                                   \
255         /*                                                              \
256          * DMA rev0 & rev1: we are not allowed to touch the DMA "flush" \
257          *     and "drain" bits while it is still thinking about a      \
258          *     request.                                                 \
259          * other revs: D_ESC_R_PEND bit reads as 0                      \
260          */                                                             \
261         DMAWAIT(sc, L64854_GCSR(sc) & D_ESC_R_PEND, "R_PEND", dontpanic);\
262         if (sc->sc_rev != DMAREV_HME) {                                 \
263                 /*                                                      \
264                  * Select drain bit based on revision                   \
265                  * also clears errors and D_TC flag                     \
266                  */                                                     \
267                 csr = L64854_GCSR(sc);                                  \
268                 if (sc->sc_rev == DMAREV_1 || sc->sc_rev == DMAREV_0)   \
269                         csr |= D_ESC_DRAIN;                             \
270                 else                                                    \
271                         csr |= L64854_INVALIDATE;                       \
272                                                                         \
273                 L64854_SCSR(sc, csr);                                   \
274         }                                                               \
275         /*                                                              \
276          * Wait for draining to finish                                  \
277          * rev0 & rev1 call this PACKCNT                                \
278          */                                                             \
279         DMAWAIT(sc, L64854_GCSR(sc) & L64854_DRAINING, "DRAINING",      \
280             dontpanic);                                                 \
281 } while (/* CONSTCOND */0)
282
283 #define DMA_FLUSH(sc, dontpanic) do {                                   \
284         uint32_t csr;                                                   \
285         /*                                                              \
286          * DMA rev0 & rev1: we are not allowed to touch the DMA "flush" \
287          *     and "drain" bits while it is still thinking about a      \
288          *     request.                                                 \
289          * other revs: D_ESC_R_PEND bit reads as 0                      \
290          */                                                             \
291         DMAWAIT(sc, L64854_GCSR(sc) & D_ESC_R_PEND, "R_PEND", dontpanic);\
292         csr = L64854_GCSR(sc);                                  \
293         csr &= ~(L64854_WRITE|L64854_EN_DMA); /* no-ops on ENET */      \
294         csr |= L64854_INVALIDATE;               /* XXX FAS ? */         \
295         L64854_SCSR(sc, csr);                                           \
296 } while (/* CONSTCOND */0)
297
298 static void
299 lsi64854_reset(struct lsi64854_softc *sc)
300 {
301         bus_dma_tag_t dmat;
302         bus_dmamap_t dmam;
303         uint32_t csr;
304
305         DMA_FLUSH(sc, 1);
306         csr = L64854_GCSR(sc);
307
308         DPRINTF(LDB_ANY, ("%s: csr 0x%x\n", __func__, csr));
309
310         if (sc->sc_dmasize != 0) {
311                 dmat = sc->sc_buffer_dmat;
312                 dmam = sc->sc_dmamap;
313                 bus_dmamap_sync(dmat, dmam, (csr & D_WRITE) != 0 ?
314                     BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE);
315                 bus_dmamap_unload(dmat, dmam);
316         }
317
318         if (sc->sc_rev == DMAREV_HME)
319                 L64854_SCSR(sc, csr | D_HW_RESET_FAS366);
320
321         csr |= L64854_RESET;            /* reset DMA */
322         L64854_SCSR(sc, csr);
323         DELAY(200);                     /* > 10 Sbus clocks(?) */
324
325         /*DMAWAIT1(sc); why was this here? */
326         csr = L64854_GCSR(sc);
327         csr &= ~L64854_RESET;           /* de-assert reset line */
328         L64854_SCSR(sc, csr);
329         DELAY(5);                       /* allow a few ticks to settle */
330
331         csr = L64854_GCSR(sc);
332         csr |= L64854_INT_EN;           /* enable interrupts */
333         if (sc->sc_rev > DMAREV_1 && sc->sc_channel == L64854_CHANNEL_SCSI) {
334                 if (sc->sc_rev == DMAREV_HME)
335                         csr |= D_TWO_CYCLE;
336                 else
337                         csr |= D_FASTER;
338         }
339
340         /* Set burst */
341         switch (sc->sc_rev) {
342         case DMAREV_HME:
343         case DMAREV_2:
344                 csr &= ~L64854_BURST_SIZE;
345                 if (sc->sc_burst == 32)
346                         csr |= L64854_BURST_32;
347                 else if (sc->sc_burst == 16)
348                         csr |= L64854_BURST_16;
349                 else
350                         csr |= L64854_BURST_0;
351                 break;
352         case DMAREV_ESC:
353                 csr |= D_ESC_AUTODRAIN; /* Auto-drain */
354                 if (sc->sc_burst == 32)
355                         csr &= ~D_ESC_BURST;
356                 else
357                         csr |= D_ESC_BURST;
358                 break;
359         default:
360                 break;
361         }
362         L64854_SCSR(sc, csr);
363
364         if (sc->sc_rev == DMAREV_HME) {
365                 bus_write_4(sc->sc_res, L64854_REG_ADDR, 0);
366                 sc->sc_dmactl = csr;
367         }
368         sc->sc_active = 0;
369
370         DPRINTF(LDB_ANY, ("%s: done, csr 0x%x\n", __func__, csr));
371 }
372
373 static void
374 lsi64854_map_scsi(void *arg, bus_dma_segment_t *segs, int nseg, int error)
375 {
376         struct lsi64854_softc *sc;
377
378         sc = (struct lsi64854_softc *)arg;
379
380         if (error != 0)
381                 return;
382         if (nseg != 1)
383                 panic("%s: cannot map %d segments\n", __func__, nseg);
384
385         bus_dmamap_sync(sc->sc_buffer_dmat, sc->sc_dmamap,
386             sc->sc_datain != 0 ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE);
387         bus_write_4(sc->sc_res, L64854_REG_ADDR, segs[0].ds_addr);
388 }
389
390 /*
391  * setup a DMA transfer
392  */
393 static int
394 lsi64854_setup(struct lsi64854_softc *sc, void **addr, size_t *len,
395     int datain, size_t *dmasize)
396 {
397         long bcnt;
398         int error;
399         uint32_t csr;
400
401         DMA_FLUSH(sc, 0);
402
403 #if 0
404         DMACSR(sc) &= ~D_INT_EN;
405 #endif
406         sc->sc_dmaaddr = addr;
407         sc->sc_dmalen = len;
408         sc->sc_datain = datain;
409
410         KASSERT(*dmasize <= sc->sc_maxdmasize,
411             ("%s: transfer size %ld too large", __func__, (long)*dmasize));
412
413         sc->sc_dmasize = *dmasize;
414
415         DPRINTF(LDB_ANY, ("%s: dmasize=%ld\n", __func__, (long)*dmasize));
416
417         /*
418          * XXX what length?
419          */
420         if (sc->sc_rev == DMAREV_HME) {
421                 L64854_SCSR(sc, sc->sc_dmactl | L64854_RESET);
422                 L64854_SCSR(sc, sc->sc_dmactl);
423
424                 bus_write_4(sc->sc_res, L64854_REG_CNT, *dmasize);
425         }
426
427         /*
428          * Load the transfer buffer and program the DMA address.
429          * Note that the NCR53C9x core can't handle EINPROGRESS so we set
430          * BUS_DMA_NOWAIT.
431          */
432         if (*dmasize != 0) {
433                 error = bus_dmamap_load(sc->sc_buffer_dmat, sc->sc_dmamap,
434                     *sc->sc_dmaaddr, *dmasize, lsi64854_map_scsi, sc,
435                     BUS_DMA_NOWAIT);
436                 if (error != 0)
437                         return (error);
438         }
439
440         if (sc->sc_rev == DMAREV_ESC) {
441                 /* DMA ESC chip bug work-around */
442                 bcnt = *dmasize;
443                 if (((bcnt + (long)*sc->sc_dmaaddr) & PAGE_MASK_8K) != 0)
444                         bcnt = roundup(bcnt, PAGE_SIZE_8K);
445                 bus_write_4(sc->sc_res, L64854_REG_CNT, bcnt);
446         }
447
448         /* Setup the DMA control register. */
449         csr = L64854_GCSR(sc);
450
451         if (datain != 0)
452                 csr |= L64854_WRITE;
453         else
454                 csr &= ~L64854_WRITE;
455         csr |= L64854_INT_EN;
456
457         if (sc->sc_rev == DMAREV_HME)
458                 csr |= (D_DSBL_SCSI_DRN | D_EN_DMA);
459
460         L64854_SCSR(sc, csr);
461
462         return (0);
463 }
464
465 /*
466  * Pseudo (chained) interrupt from the esp driver to kick the
467  * current running DMA transfer.  Called from ncr53c9x_intr()
468  * for now.
469  *
470  * return 1 if it was a DMA continue.
471  */
472 static int
473 lsi64854_scsi_intr(void *arg)
474 {
475         struct lsi64854_softc *sc = arg;
476         struct ncr53c9x_softc *nsc = sc->sc_client;
477         bus_dma_tag_t dmat;
478         bus_dmamap_t dmam;
479         size_t dmasize;
480         int lxfer, resid, trans;
481         uint32_t csr;
482
483         csr = L64854_GCSR(sc);
484
485         DPRINTF(LDB_SCSI, ("%s: addr 0x%x, csr %b\n", __func__,
486             bus_read_4(sc->sc_res, L64854_REG_ADDR), csr, DDMACSR_BITS));
487
488         if (csr & (D_ERR_PEND | D_SLAVE_ERR)) {
489                 device_printf(sc->sc_dev, "error: csr=%b\n", csr,
490                     DDMACSR_BITS);
491                 csr &= ~D_EN_DMA;       /* Stop DMA. */
492                 /* Invalidate the queue; SLAVE_ERR bit is write-to-clear */
493                 csr |= D_INVALIDATE | D_SLAVE_ERR;
494                 L64854_SCSR(sc, csr);
495                 return (-1);
496         }
497
498         /* This is an "assertion" :) */
499         if (sc->sc_active == 0)
500                 panic("%s: DMA wasn't active", __func__);
501
502         DMA_DRAIN(sc, 0);
503
504         /* DMA has stopped */
505         csr &= ~D_EN_DMA;
506         L64854_SCSR(sc, csr);
507         sc->sc_active = 0;
508
509         dmasize = sc->sc_dmasize;
510         if (dmasize == 0) {
511                 /* A "Transfer Pad" operation completed. */
512                 DPRINTF(LDB_SCSI, ("%s: discarded %d bytes (tcl=%d, "
513                     "tcm=%d)\n", __func__, NCR_READ_REG(nsc, NCR_TCL) |
514                     (NCR_READ_REG(nsc, NCR_TCM) << 8),
515                     NCR_READ_REG(nsc, NCR_TCL), NCR_READ_REG(nsc, NCR_TCM)));
516                 return (0);
517         }
518
519         resid = 0;
520         /*
521          * If a transfer onto the SCSI bus gets interrupted by the device
522          * (e.g. for a SAVEPOINTER message), the data in the FIFO counts
523          * as residual since the NCR53C9X counter registers get decremented
524          * as bytes are clocked into the FIFO.
525          */
526         if ((csr & D_WRITE) == 0 &&
527             (resid = (NCR_READ_REG(nsc, NCR_FFLAG) & NCRFIFO_FF)) != 0) {
528                 DPRINTF(LDB_SCSI, ("%s: empty esp FIFO of %d ", __func__,
529                     resid));
530                 if (nsc->sc_rev == NCR_VARIANT_FAS366 &&
531                     (NCR_READ_REG(nsc, NCR_CFG3) & NCRFASCFG3_EWIDE))
532                         resid <<= 1;
533         }
534
535         if ((nsc->sc_espstat & NCRSTAT_TC) == 0) {
536                 lxfer = nsc->sc_features & NCR_F_LARGEXFER;
537                 /*
538                  * "Terminal count" is off, so read the residue
539                  * out of the NCR53C9X counter registers.
540                  */
541                 resid += (NCR_READ_REG(nsc, NCR_TCL) |
542                     (NCR_READ_REG(nsc, NCR_TCM) << 8) |
543                     (lxfer != 0 ? (NCR_READ_REG(nsc, NCR_TCH) << 16) : 0));
544
545                 if (resid == 0 && dmasize == 65536 && lxfer == 0)
546                         /* A transfer of 64k is encoded as TCL=TCM=0. */
547                         resid = 65536;
548         }
549
550         trans = dmasize - resid;
551         if (trans < 0) {                        /* transferred < 0? */
552 #if 0
553                 /*
554                  * This situation can happen in perfectly normal operation
555                  * if the ESP is reselected while using DMA to select
556                  * another target.  As such, don't print the warning.
557                  */
558                 device_printf(sc->sc_dev, "xfer (%d) > req (%d)\n", trans,
559                     dmasize);
560 #endif
561                 trans = dmasize;
562         }
563
564         DPRINTF(LDB_SCSI, ("%s: tcl=%d, tcm=%d, tch=%d; trans=%d, resid=%d\n",
565             __func__, NCR_READ_REG(nsc, NCR_TCL), NCR_READ_REG(nsc, NCR_TCM),
566             (nsc->sc_features & NCR_F_LARGEXFER) != 0 ?
567             NCR_READ_REG(nsc, NCR_TCH) : 0, trans, resid));
568
569         if (dmasize != 0) {
570                 dmat = sc->sc_buffer_dmat;
571                 dmam = sc->sc_dmamap;
572                 bus_dmamap_sync(dmat, dmam, (csr & D_WRITE) != 0 ?
573                     BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
574                 bus_dmamap_unload(dmat, dmam);
575         }
576
577         *sc->sc_dmalen -= trans;
578         *sc->sc_dmaaddr = (char *)*sc->sc_dmaaddr + trans;
579
580 #if 0   /* this is not normal operation just yet */
581         if (*sc->sc_dmalen == 0 || nsc->sc_phase != nsc->sc_prevphase)
582                 return (0);
583
584         /* and again */
585         dma_start(sc, sc->sc_dmaaddr, sc->sc_dmalen, DMACSR(sc) & D_WRITE);
586         return (1);
587 #endif
588         return (0);
589 }
590
591 /*
592  * Pseudo (chained) interrupt to le(4) driver to handle DMA errors
593  */
594 static int
595 lsi64854_enet_intr(void *arg)
596 {
597         struct lsi64854_softc *sc = arg;
598         uint32_t csr;
599         int i, rv;
600
601         csr = L64854_GCSR(sc);
602
603         /* If the DMA logic shows an interrupt, claim it */
604         rv = ((csr & E_INT_PEND) != 0) ? 1 : 0;
605
606         if (csr & (E_ERR_PEND | E_SLAVE_ERR)) {
607                 device_printf(sc->sc_dev, "error: csr=%b\n", csr,
608                     EDMACSR_BITS);
609                 csr &= ~L64854_EN_DMA;  /* Stop DMA. */
610                 /* Invalidate the queue; SLAVE_ERR bit is write-to-clear */
611                 csr |= E_INVALIDATE | E_SLAVE_ERR;
612                 L64854_SCSR(sc, csr);
613                 /* Will be drained with the LE_C0_IDON interrupt. */
614                 sc->sc_dodrain = 1;
615                 return (-1);
616         }
617
618         /* XXX - is this necessary with E_DSBL_WR_INVAL on? */
619         if (sc->sc_dodrain) {
620                 i = 10;
621                 csr |= E_DRAIN;
622                 L64854_SCSR(sc, csr);
623                 while (i-- > 0 && (L64854_GCSR(sc) & E_DRAINING))
624                         DELAY(1);
625                 sc->sc_dodrain = 0;
626         }
627
628         return (rv);
629 }
630
631 static void
632 lsi64854_map_pp(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
633 {
634         struct lsi64854_softc *sc;
635
636         sc = (struct lsi64854_softc *)arg;
637
638         if (error != 0)
639                 return;
640         if (nsegs != 1)
641                 panic("%s: cannot map %d segments\n", __func__, nsegs);
642
643         bus_dmamap_sync(sc->sc_buffer_dmat, sc->sc_dmamap,
644             sc->sc_datain != 0 ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE);
645         bus_write_4(sc->sc_res, L64854_REG_ADDR, segs[0].ds_addr);
646
647         bus_write_4(sc->sc_res, L64854_REG_CNT, sc->sc_dmasize);
648 }
649
650 /*
651  * Setup a DMA transfer.
652  */
653 static int
654 lsi64854_setup_pp(struct lsi64854_softc *sc, void **addr, size_t *len,
655     int datain, size_t *dmasize)
656 {
657         int error;
658         uint32_t csr;
659
660         DMA_FLUSH(sc, 0);
661
662         sc->sc_dmaaddr = addr;
663         sc->sc_dmalen = len;
664         sc->sc_datain = datain;
665
666         DPRINTF(LDB_PP, ("%s: pp start %ld@%p,%d\n", __func__,
667             (long)*sc->sc_dmalen, *sc->sc_dmaaddr, datain != 0 ? 1 : 0));
668
669         KASSERT(*dmasize <= sc->sc_maxdmasize,
670             ("%s: transfer size %ld too large", __func__, (long)*dmasize));
671
672         sc->sc_dmasize = *dmasize;
673
674         DPRINTF(LDB_PP, ("%s: dmasize=%ld\n", __func__, (long)*dmasize));
675
676         /* Load the transfer buffer and program the DMA address. */
677         if (*dmasize != 0) {
678                 error = bus_dmamap_load(sc->sc_buffer_dmat, sc->sc_dmamap,
679                     *sc->sc_dmaaddr, *dmasize, lsi64854_map_pp, sc,
680                     BUS_DMA_NOWAIT);
681                 if (error != 0)
682                         return (error);
683         }
684
685         /* Setup the DMA control register. */
686         csr = L64854_GCSR(sc);
687         csr &= ~L64854_BURST_SIZE;
688         if (sc->sc_burst == 32)
689                 csr |= L64854_BURST_32;
690         else if (sc->sc_burst == 16)
691                 csr |= L64854_BURST_16;
692         else
693                 csr |= L64854_BURST_0;
694         csr |= P_EN_DMA | P_INT_EN | P_EN_CNT;
695 #if 0
696         /* This bit is read-only in PP csr register. */
697         if (datain != 0)
698                 csr |= P_WRITE;
699         else
700                 csr &= ~P_WRITE;
701 #endif
702         L64854_SCSR(sc, csr);
703
704         return (0);
705 }
706
707 /*
708  * Parallel port DMA interrupt
709  */
710 static int
711 lsi64854_pp_intr(void *arg)
712 {
713         struct lsi64854_softc *sc = arg;
714         bus_dma_tag_t dmat;
715         bus_dmamap_t dmam;
716         size_t dmasize;
717         int ret, trans, resid = 0;
718         uint32_t csr;
719
720         csr = L64854_GCSR(sc);
721
722         DPRINTF(LDB_PP, ("%s: addr 0x%x, csr %b\n", __func__,
723             bus_read_4(sc->sc_res, L64854_REG_ADDR), csr, PDMACSR_BITS));
724
725         if ((csr & (P_ERR_PEND | P_SLAVE_ERR)) != 0) {
726                 resid = bus_read_4(sc->sc_res, L64854_REG_CNT);
727                 device_printf(sc->sc_dev, "error: resid %d csr=%b\n", resid,
728                     csr, PDMACSR_BITS);
729                 csr &= ~P_EN_DMA;       /* Stop DMA. */
730                 /* Invalidate the queue; SLAVE_ERR bit is write-to-clear */
731                 csr |= P_INVALIDATE | P_SLAVE_ERR;
732                 L64854_SCSR(sc, csr);
733                 return (-1);
734         }
735
736         ret = (csr & P_INT_PEND) != 0;
737
738         if (sc->sc_active != 0) {
739                 DMA_DRAIN(sc, 0);
740                 resid = bus_read_4(sc->sc_res, L64854_REG_CNT);
741         }
742
743         /* DMA has stopped */
744         csr &= ~D_EN_DMA;
745         L64854_SCSR(sc, csr);
746         sc->sc_active = 0;
747
748         dmasize = sc->sc_dmasize;
749         trans = dmasize - resid;
750         if (trans < 0)                          /* transferred < 0? */
751                 trans = dmasize;
752         *sc->sc_dmalen -= trans;
753         *sc->sc_dmaaddr = (char *)*sc->sc_dmaaddr + trans;
754
755         if (dmasize != 0) {
756                 dmat = sc->sc_buffer_dmat;
757                 dmam = sc->sc_dmamap;
758                 bus_dmamap_sync(dmat, dmam, (csr & D_WRITE) != 0 ?
759                     BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
760                 bus_dmamap_unload(dmat, dmam);
761         }
762
763         return (ret != 0);
764 }