Annotation of sys/arch/sparc/dev/esp.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: esp.c,v 1.24 2006/06/02 20:00:54 miod Exp $ */
2: /* $NetBSD: esp.c,v 1.69 1997/08/27 11:24:18 bouyer Exp $ */
3:
4: /*
5: * Copyright (c) 1997 Jason R. Thorpe.
6: * All rights reserved.
7: *
8: * Redistribution and use in source and binary forms, with or without
9: * modification, are permitted provided that the following conditions
10: * are met:
11: * 1. Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: * 2. Redistributions in binary form must reproduce the above copyright
14: * notice, this list of conditions and the following disclaimer in the
15: * documentation and/or other materials provided with the distribution.
16: * 3. All advertising materials mentioning features or use of this software
17: * must display the following acknowledgement:
18: * This product includes software developed for the NetBSD Project
19: * by Jason R. Thorpe.
20: * 4. The name of the author may not be used to endorse or promote products
21: * derived from this software without specific prior written permission.
22: *
23: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
27: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
28: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
32: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33: */
34:
35: /*
36: * Copyright (c) 1996 Charles M. Hannum. All rights reserved.
37: *
38: * Redistribution and use in source and binary forms, with or without
39: * modification, are permitted provided that the following conditions
40: * are met:
41: * 1. Redistributions of source code must retain the above copyright
42: * notice, this list of conditions and the following disclaimer.
43: * 2. Redistributions in binary form must reproduce the above copyright
44: * notice, this list of conditions and the following disclaimer in the
45: * documentation and/or other materials provided with the distribution.
46: * 3. All advertising materials mentioning features or use of this software
47: * must display the following acknowledgement:
48: * This product includes software developed by Charles M. Hannum.
49: * 4. The name of the author may not be used to endorse or promote products
50: * derived from this software without specific prior written permission.
51: *
52: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
53: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
54: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
55: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
56: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
57: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
58: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
59: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
60: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
61: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
62: */
63:
64: /*
65: * Copyright (c) 1994 Peter Galbavy
66: * Copyright (c) 1995 Paul Kranenburg
67: * All rights reserved.
68: *
69: * Redistribution and use in source and binary forms, with or without
70: * modification, are permitted provided that the following conditions
71: * are met:
72: * 1. Redistributions of source code must retain the above copyright
73: * notice, this list of conditions and the following disclaimer.
74: * 2. Redistributions in binary form must reproduce the above copyright
75: * notice, this list of conditions and the following disclaimer in the
76: * documentation and/or other materials provided with the distribution.
77: *
78: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
79: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
80: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
81: * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
82: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
83: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
84: * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
85: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
86: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
87: * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
88: * POSSIBILITY OF SUCH DAMAGE.
89: */
90:
91: /*
92: * Based on aic6360 by Jarle Greipsland
93: *
94: * Acknowledgements: Many of the algorithms used in this driver are
95: * inspired by the work of Julian Elischer (julian@tfs.com) and
96: * Charles Hannum (mycroft@duality.gnu.ai.mit.edu). Thanks a million!
97: */
98:
99: #include <sys/types.h>
100: #include <sys/param.h>
101: #include <sys/systm.h>
102: #include <sys/kernel.h>
103: #include <sys/errno.h>
104: #include <sys/ioctl.h>
105: #include <sys/device.h>
106: #include <sys/buf.h>
107: #include <sys/proc.h>
108: #include <sys/user.h>
109: #include <sys/queue.h>
110: #include <sys/malloc.h>
111:
112: #include <scsi/scsi_all.h>
113: #include <scsi/scsiconf.h>
114: #include <scsi/scsi_message.h>
115:
116: #include <machine/cpu.h>
117: #include <machine/autoconf.h>
118:
119: #include <dev/ic/ncr53c9xreg.h>
120: #include <dev/ic/ncr53c9xvar.h>
121:
122: #include <sparc/dev/sbusvar.h>
123: #include <sparc/dev/dmareg.h>
124: #include <sparc/dev/dmavar.h>
125: #include <sparc/dev/espvar.h>
126:
127: void espattach(struct device *, struct device *, void *);
128: int espmatch(struct device *, void *, void *);
129:
130: /* Linkup to the rest of the kernel */
131: struct cfattach esp_ca = {
132: sizeof(struct esp_softc), espmatch, espattach
133: };
134:
135: struct scsi_adapter esp_switch = {
136: ncr53c9x_scsi_cmd,
137: minphys, /* no max at this level; handled by DMA code */
138: NULL,
139: NULL,
140: };
141:
142: struct scsi_device esp_dev = {
143: NULL, /* Use default error handler */
144: NULL, /* have a queue, served by this */
145: NULL, /* have no async handler */
146: NULL, /* Use default 'done' routine */
147: };
148:
149: /*
150: * Functions and the switch for the MI code.
151: */
152: u_char esp_read_reg(struct ncr53c9x_softc *, int);
153: void esp_write_reg(struct ncr53c9x_softc *, int, u_char);
154: u_char esp_rdreg1(struct ncr53c9x_softc *, int);
155: void esp_wrreg1(struct ncr53c9x_softc *, int, u_char);
156: int esp_dma_isintr(struct ncr53c9x_softc *);
157: void esp_dma_reset(struct ncr53c9x_softc *);
158: int esp_dma_intr(struct ncr53c9x_softc *);
159: int esp_dma_setup(struct ncr53c9x_softc *, caddr_t *,
160: size_t *, int, size_t *);
161: void esp_dma_go(struct ncr53c9x_softc *);
162: void esp_dma_stop(struct ncr53c9x_softc *);
163: int esp_dma_isactive(struct ncr53c9x_softc *);
164:
165: struct ncr53c9x_glue esp_glue = {
166: esp_read_reg,
167: esp_write_reg,
168: esp_dma_isintr,
169: esp_dma_reset,
170: esp_dma_intr,
171: esp_dma_setup,
172: esp_dma_go,
173: esp_dma_stop,
174: esp_dma_isactive,
175: NULL, /* gl_clear_latched_intr */
176: };
177:
178: #if defined(SUN4C) || defined(SUN4M)
179: struct ncr53c9x_glue esp_glue1 = {
180: esp_rdreg1,
181: esp_wrreg1,
182: esp_dma_isintr,
183: esp_dma_reset,
184: esp_dma_intr,
185: esp_dma_setup,
186: esp_dma_go,
187: esp_dma_stop,
188: esp_dma_isactive,
189: NULL, /* gl_clear_latched_intr */
190: };
191: #endif
192:
193: int
194: espmatch(parent, vcf, aux)
195: struct device *parent;
196: void *vcf, *aux;
197: {
198: register struct cfdata *cf = vcf;
199: register struct confargs *ca = aux;
200: register struct romaux *ra = &ca->ca_ra;
201:
202: #if defined(SUN4C) || defined(SUN4M)
203: if (ca->ca_bustype == BUS_SBUS) {
204: if (strcmp("SUNW,fas", ra->ra_name) == 0 ||
205: strcmp("ptscII", ra->ra_name) == 0)
206: return (1);
207: }
208: #endif
209:
210: if (strcmp(cf->cf_driver->cd_name, ra->ra_name))
211: return (0);
212: #if defined(SUN4C) || defined(SUN4M)
213: if (ca->ca_bustype == BUS_SBUS) {
214: if (!sbus_testdma((struct sbus_softc *)parent, ca))
215: return (0);
216: return (1);
217: }
218: #endif
219: ra->ra_len = NBPG;
220: return (probeget(ra->ra_vaddr, 1) != -1);
221: }
222:
223: /*
224: * Attach this instance, and then all the sub-devices
225: */
226: void
227: espattach(parent, self, aux)
228: struct device *parent, *self;
229: void *aux;
230: {
231: register struct confargs *ca = aux;
232: struct esp_softc *esc = (void *)self;
233: struct ncr53c9x_softc *sc = &esc->sc_ncr53c9x;
234: struct bootpath *bp;
235: int dmachild;
236: unsigned int uid = 0;
237:
238: /*
239: * If no interrupts properties, bail out: this might happen
240: * on the Sparc X terminal.
241: */
242: if (ca->ca_ra.ra_nintr != 1) {
243: printf(": expected 1 interrupt, got %d\n", ca->ca_ra.ra_nintr);
244: return;
245: }
246:
247: esc->sc_pri = ca->ca_ra.ra_intr[0].int_pri;
248: printf(" pri %d", esc->sc_pri);
249:
250: /* Other settings */
251: esc->sc_node = ca->ca_ra.ra_node;
252: if (ca->ca_bustype == BUS_SBUS) {
253: sc->sc_id = getpropint(esc->sc_node, "initiator-id", 7);
254: sc->sc_freq = getpropint(esc->sc_node, "clock-frequency", -1);
255: } else {
256: sc->sc_id = 7;
257: sc->sc_freq = 24000000;
258: }
259: if (sc->sc_freq < 0)
260: sc->sc_freq = ((struct sbus_softc *)
261: sc->sc_dev.dv_parent)->sc_clockfreq;
262:
263: /* gimme MHz */
264: sc->sc_freq /= 1000000;
265:
266: #if defined(SUN4C) || defined(SUN4M)
267: if (ca->ca_bustype == BUS_SBUS &&
268: strcmp("SUNW,fas", ca->ca_ra.ra_name) == 0) {
269: struct dma_softc *dsc;
270:
271: /*
272: * fas has 2 register spaces: DMA (lsi64854) and SCSI core
273: * (ncr53c9x).
274: */
275: if (ca->ca_ra.ra_nreg != 2) {
276: printf(": expected 2 register spaces, found %d\n",
277: ca->ca_ra.ra_nreg);
278: return;
279: }
280:
281: /*
282: * Allocate a softc for the DMA companion, which will not
283: * get a regular attachment.
284: */
285: dsc = malloc(sizeof(struct dma_softc), M_DEVBUF, M_NOWAIT);
286: if (dsc == NULL) {
287: printf(": could not allocate dma softc\n");
288: return;
289: }
290: bzero(dsc, sizeof(struct dma_softc));
291: strlcpy(dsc->sc_dev.dv_xname, sc->sc_dev.dv_xname,
292: sizeof(dsc->sc_dev.dv_xname));
293: esc->sc_dma = dsc;
294:
295: /*
296: * Map DMA registers
297: */
298: dsc->sc_regs = (struct dma_regs *)mapiodev(&ca->ca_ra.ra_reg[0],
299: 0, ca->ca_ra.ra_reg[0].rr_len);
300: if (dsc->sc_regs == NULL) {
301: printf(": could not map DMA registers\n");
302: return;
303: }
304: dsc->sc_rev = dsc->sc_regs->csr & D_DEV_ID;
305: dsc->sc_esp = esc;
306:
307: #ifdef SUN4M
308: /*
309: * Get transfer burst size from PROM and plug it into the
310: * controller registers. This is needed on the Sun4m; do
311: * others need it too?
312: */
313: if (CPU_ISSUN4M) {
314: int sbusburst;
315:
316: sbusburst = ((struct sbus_softc *)parent)->sc_burst;
317: if (sbusburst == 0)
318: sbusburst = SBUS_BURST_32 - 1; /* 1 -> 16 */
319:
320: dsc->sc_burst =
321: getpropint(ca->ca_ra.ra_node, "burst-sizes", -1);
322: if (dsc->sc_burst == -1)
323: /* take SBus burst sizes */
324: dsc->sc_burst = sbusburst;
325:
326: /* Clamp at parent's burst sizes */
327: dsc->sc_burst &= sbusburst;
328: }
329: #endif /* SUN4M */
330:
331: /* indirect functions */
332: dma_setuphandlers(dsc);
333:
334: /*
335: * Map SCSI core registers
336: */
337: esc->sc_reg = (volatile u_char *)mapiodev(&ca->ca_ra.ra_reg[1],
338: 0, ca->ca_ra.ra_reg[1].rr_len);
339: if (esc->sc_reg == NULL) {
340: printf(": could not map SCSI core registers\n");
341: return;
342: }
343:
344: dmachild = 0;
345: } else
346: #endif
347: {
348: /*
349: * Map my registers in, if they aren't already in virtual
350: * address space.
351: */
352: if (ca->ca_ra.ra_vaddr)
353: esc->sc_reg = (volatile u_char *) ca->ca_ra.ra_vaddr;
354: else {
355: esc->sc_reg = (volatile u_char *)
356: mapiodev(ca->ca_ra.ra_reg, 0, ca->ca_ra.ra_len);
357: }
358:
359: dmachild = strncmp(parent->dv_xname, "dma", 3) == 0;
360: if (dmachild) {
361: esc->sc_dma = (struct dma_softc *)parent;
362: esc->sc_dma->sc_esp = esc;
363: } else {
364: /*
365: * Find the DMA by poking around the DMA device
366: * structures.
367: *
368: * What happens here is that if the DMA driver has
369: * not been configured, then this returns a NULL
370: * pointer. Then when the DMA actually gets configured,
371: * it does the opposite test, and if the sc->sc_esp
372: * field in its softc is NULL, then tries to find the
373: * matching esp driver.
374: */
375: esc->sc_dma = (struct dma_softc *)
376: getdevunit("dma", sc->sc_dev.dv_unit);
377:
378: /*
379: * ...and a back pointer to us, for DMA.
380: */
381: if (esc->sc_dma)
382: esc->sc_dma->sc_esp = esc;
383: else {
384: printf("\n");
385: panic("espattach: no dma found");
386: }
387: }
388: }
389:
390: /*
391: * Set up glue for MI code.
392: */
393: #if defined(SUN4C) || defined(SUN4M)
394: if (ca->ca_bustype == BUS_SBUS &&
395: strcmp("ptscII", ca->ca_ra.ra_name) == 0) {
396: sc->sc_glue = &esp_glue1;
397: } else
398: #endif
399: sc->sc_glue = &esp_glue;
400:
401: /*
402: * XXX More of this should be in ncr53c9x_attach(), but
403: * XXX should we really poke around the chip that much in
404: * XXX the MI code? Think about this more...
405: */
406:
407: /*
408: * It is necessary to try to load the 2nd config register here,
409: * to find out what rev the esp chip is, else the ncr53c9x_reset
410: * will not set up the defaults correctly.
411: */
412: sc->sc_cfg1 = sc->sc_id | NCRCFG1_PARENB;
413: sc->sc_cfg2 = NCRCFG2_SCSI2 | NCRCFG2_RPE;
414: sc->sc_cfg3 = NCRCFG3_CDB;
415: NCR_WRITE_REG(sc, NCR_CFG2, sc->sc_cfg2);
416:
417: if ((NCR_READ_REG(sc, NCR_CFG2) & ~NCRCFG2_RSVD) !=
418: (NCRCFG2_SCSI2 | NCRCFG2_RPE)) {
419: sc->sc_rev = NCR_VARIANT_ESP100;
420: } else {
421: sc->sc_cfg2 = NCRCFG2_SCSI2;
422: NCR_WRITE_REG(sc, NCR_CFG2, sc->sc_cfg2);
423: sc->sc_cfg3 = 0;
424: NCR_WRITE_REG(sc, NCR_CFG3, sc->sc_cfg3);
425: sc->sc_cfg3 = (NCRCFG3_CDB | NCRCFG3_FCLK);
426: NCR_WRITE_REG(sc, NCR_CFG3, sc->sc_cfg3);
427: if (NCR_READ_REG(sc, NCR_CFG3) !=
428: (NCRCFG3_CDB | NCRCFG3_FCLK)) {
429: sc->sc_rev = NCR_VARIANT_ESP100A;
430: } else {
431: /* NCRCFG2_FE enables > 64K transfers */
432: sc->sc_cfg2 |= NCRCFG2_FE;
433: sc->sc_cfg3 = 0;
434: NCR_WRITE_REG(sc, NCR_CFG3, sc->sc_cfg3);
435: sc->sc_rev = NCR_VARIANT_ESP200;
436:
437: /* XXX spec says it's valid after power up or chip reset */
438: uid = NCR_READ_REG(sc, NCR_UID);
439: if (((uid & 0xf8) >> 3) == 0x0a) /* XXX */
440: sc->sc_rev = NCR_VARIANT_FAS366;
441: }
442: }
443:
444: /*
445: * XXX minsync and maxxfer _should_ be set up in MI code,
446: * XXX but it appears to have some dependency on what sort
447: * XXX of DMA we're hooked up to, etc.
448: */
449:
450: /*
451: * This is the value used to start sync negotiations
452: * Note that the NCR register "SYNCTP" is programmed
453: * in "clocks per byte", and has a minimum value of 4.
454: * The SCSI period used in negotiation is one-fourth
455: * of the time (in nanoseconds) needed to transfer one byte.
456: * Since the chip's clock is given in MHz, we have the following
457: * formula: 4 * period = (1000 / freq) * 4
458: */
459: sc->sc_minsync = 1000 / sc->sc_freq;
460:
461: /*
462: * Alas, we must now modify the value a bit, because it's
463: * only valid when can switch on FASTCLK and FASTSCSI bits
464: * in config register 3...
465: */
466: switch (sc->sc_rev) {
467: case NCR_VARIANT_ESP100:
468: sc->sc_maxxfer = 64 * 1024;
469: sc->sc_minsync = 0; /* No synch on old chip? */
470: break;
471:
472: case NCR_VARIANT_ESP100A:
473: sc->sc_maxxfer = 64 * 1024;
474: /* Min clocks/byte is 5 */
475: sc->sc_minsync = ncr53c9x_cpb2stp(sc, 5);
476: break;
477:
478: case NCR_VARIANT_ESP200:
479: case NCR_VARIANT_FAS366:
480: sc->sc_maxxfer = 16 * 1024 * 1024;
481: /* XXX - do actually set FAST* bits */
482: break;
483: }
484:
485: /* and the interrupts */
486: esc->sc_ih.ih_fun = (void *) ncr53c9x_intr;
487: esc->sc_ih.ih_arg = sc;
488: intr_establish(esc->sc_pri, &esc->sc_ih, IPL_BIO, self->dv_xname);
489:
490: /*
491: * If the boot path is "esp" at the moment and it's me, then
492: * walk our pointer to the sub-device, ready for the config
493: * below.
494: */
495: bp = ca->ca_ra.ra_bp;
496: switch (ca->ca_bustype) {
497: case BUS_SBUS:
498: if (bp != NULL && strcmp(bp->name, "esp") == 0 &&
499: SAME_ESP(sc, bp, ca))
500: bootpath_store(1, bp + 1);
501: break;
502: default:
503: if (bp != NULL && strcmp(bp->name, "esp") == 0 &&
504: bp->val[0] == -1 && bp->val[1] == sc->sc_dev.dv_unit)
505: bootpath_store(1, bp + 1);
506: break;
507: }
508:
509: /* Turn on target selection using the `dma' method */
510: if (sc->sc_rev != NCR_VARIANT_FAS366)
511: sc->sc_features |= NCR_F_DMASELECT;
512:
513: /* Do the common parts of attachment. */
514: ncr53c9x_attach(sc, &esp_switch, &esp_dev);
515:
516: bootpath_store(1, NULL);
517: }
518:
519: /*
520: * Glue functions.
521: */
522:
523: u_char
524: esp_read_reg(sc, reg)
525: struct ncr53c9x_softc *sc;
526: int reg;
527: {
528: struct esp_softc *esc = (struct esp_softc *)sc;
529:
530: return (esc->sc_reg[reg * 4]);
531: }
532:
533: void
534: esp_write_reg(sc, reg, val)
535: struct ncr53c9x_softc *sc;
536: int reg;
537: u_char val;
538: {
539: struct esp_softc *esc = (struct esp_softc *)sc;
540: u_char v = val;
541:
542: esc->sc_reg[reg * 4] = v;
543: }
544:
545: #if defined(SUN4C) || defined(SUN4M)
546: u_char
547: esp_rdreg1(sc, reg)
548: struct ncr53c9x_softc *sc;
549: int reg;
550: {
551: struct esp_softc *esc = (struct esp_softc *)sc;
552:
553: return (esc->sc_reg[reg]);
554: }
555:
556: void
557: esp_wrreg1(sc, reg, val)
558: struct ncr53c9x_softc *sc;
559: int reg;
560: u_char val;
561: {
562: struct esp_softc *esc = (struct esp_softc *)sc;
563: u_char v = val;
564:
565: esc->sc_reg[reg] = v;
566: }
567: #endif
568:
569: int
570: esp_dma_isintr(sc)
571: struct ncr53c9x_softc *sc;
572: {
573: struct esp_softc *esc = (struct esp_softc *)sc;
574:
575: return (DMA_ISINTR(esc->sc_dma));
576: }
577:
578: void
579: esp_dma_reset(sc)
580: struct ncr53c9x_softc *sc;
581: {
582: struct esp_softc *esc = (struct esp_softc *)sc;
583:
584: DMA_RESET(esc->sc_dma);
585: }
586:
587: int
588: esp_dma_intr(sc)
589: struct ncr53c9x_softc *sc;
590: {
591: struct esp_softc *esc = (struct esp_softc *)sc;
592:
593: return (DMA_INTR(esc->sc_dma));
594: }
595:
596: int
597: esp_dma_setup(sc, addr, len, datain, dmasize)
598: struct ncr53c9x_softc *sc;
599: caddr_t *addr;
600: size_t *len;
601: int datain;
602: size_t *dmasize;
603: {
604: struct esp_softc *esc = (struct esp_softc *)sc;
605:
606: return (DMA_SETUP(esc->sc_dma, addr, len, datain, dmasize));
607: }
608:
609: void
610: esp_dma_go(sc)
611: struct ncr53c9x_softc *sc;
612: {
613: struct esp_softc *esc = (struct esp_softc *)sc;
614:
615: DMA_GO(esc->sc_dma);
616: }
617:
618: void
619: esp_dma_stop(sc)
620: struct ncr53c9x_softc *sc;
621: {
622: struct esp_softc *esc = (struct esp_softc *)sc;
623:
624: DMACSR(esc->sc_dma) &= ~D_EN_DMA;
625: }
626:
627: int
628: esp_dma_isactive(sc)
629: struct ncr53c9x_softc *sc;
630: {
631: struct esp_softc *esc = (struct esp_softc *)sc;
632:
633: return (DMA_ISACTIVE(esc->sc_dma));
634: }
CVSweb