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