Annotation of sys/arch/sparc/dev/bpp.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: bpp.c,v 1.4 2003/06/03 21:09:02 deraadt Exp $ */
2:
3: /*
4: * Copyright (c) 1997, Jason Downs. All rights reserved.
5: *
6: * Redistribution and use in source and binary forms, with or without
7: * modification, are permitted provided that the following conditions
8: * are met:
9: * 1. Redistributions of source code must retain the above copyright
10: * notice, this list of conditions and the following disclaimer.
11: * 2. Redistributions in binary form must reproduce the above copyright
12: * notice, this list of conditions and the following disclaimer in the
13: * documentation and/or other materials provided with the distribution.
14: *
15: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS
16: * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18: * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT,
19: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21: * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22: * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25: * SUCH DAMAGE.
26: */
27:
28: #include <sys/param.h>
29: #include <sys/buf.h>
30: #include <sys/kernel.h>
31: #include <sys/uio.h>
32: #include <sys/device.h>
33: #include <sys/conf.h>
34: #include <sys/systm.h>
35:
36: #include <machine/autoconf.h>
37: #include <machine/conf.h>
38:
39: #include <sparc/dev/bppreg.h>
40:
41: #define BPP_BSIZE 1024
42:
43: #define LONG_TIMEOUT 30 /* XXX */
44: #define SHORT_TIMEOUT 3 /* XXX */
45:
46: struct bpp_softc {
47: struct device sc_dev;
48:
49: size_t sc_count;
50: struct buf *sc_inbuf;
51: u_int8_t *sc_cp;
52:
53: char sc_open;
54:
55: volatile struct bppregs *sc_regs;
56: };
57:
58: static int bppmatch(struct device *, void *, void *);
59: static void bppattach(struct device *, struct device *, void *);
60:
61: #define BPPUNIT(s) minor(s)
62:
63: struct cfattach bpp_ca = {
64: sizeof(struct bpp_softc), bppmatch, bppattach
65: };
66:
67: struct cfdriver bpp_cd = {
68: NULL, "bpp", DV_DULL
69: };
70:
71: static __inline__ void bpp_outb(struct bpp_softc *, u_int8_t);
72: static __inline__ u_int8_t bpp_inb(struct bpp_softc *);
73: static void bppreset(struct bpp_softc *, int);
74: static void bppresetmode(struct bpp_softc *);
75: static int bpppushbytes(struct bpp_softc *);
76:
77: static int
78: bppmatch(parent, vcf, aux)
79: struct device *parent;
80: void *aux, *vcf;
81: {
82: register struct confargs *ca = aux;
83:
84: if (strcmp(ca->ca_ra.ra_name, "SUNW,bpp"))
85: return (0);
86:
87: return (1);
88: }
89:
90: static void
91: bppattach(parent, self, aux)
92: struct device *parent, *self;
93: void *aux;
94: {
95: struct confargs *ca = aux;
96: struct romaux *ra = &ca->ca_ra;
97: struct bpp_softc *bpp = (void *)self;
98:
99: bpp->sc_regs = mapiodev(ra->ra_reg, 0, ra->ra_len);
100:
101: bppreset(bpp, 0);
102:
103: switch (bpp->sc_regs->bpp_csr & BPP_DEV_ID_MASK) {
104: case BPP_DEV_ID_ZEBRA:
105: printf(": Zebra\n");
106: break;
107: case BPP_DEV_ID_L64854:
108: printf(": DMA2\n");
109: break;
110: default:
111: printf(": Unknown type\n");
112: break;
113: }
114:
115: bppresetmode(bpp);
116: }
117:
118: static void
119: bppreset(bpp, verbose)
120: struct bpp_softc *bpp;
121: int verbose;
122: {
123: volatile u_int32_t bpp_csr;
124:
125: /* Reset hardware. */
126: bpp_csr = bpp->sc_regs->bpp_csr;
127: if ((bpp_csr & BPP_DRAINING) && !(bpp_csr & BPP_ERR_PEND)) {
128: delay(20);
129:
130: bpp_csr = bpp->sc_regs->bpp_csr;
131: if (verbose && (bpp_csr & BPP_DRAINING) &&
132: !(bpp_csr & BPP_ERR_PEND))
133: printf("%s: draining still active (0x%08x)\n",
134: bpp->sc_dev.dv_xname, bpp_csr);
135: }
136: bpp->sc_regs->bpp_csr = (bpp_csr | BPP_RESET) & ~BPP_INT_EN;
137: delay(500);
138: bpp->sc_regs->bpp_csr &= ~BPP_RESET;
139: }
140:
141: static void
142: bppresetmode(bpp)
143: struct bpp_softc *bpp;
144: {
145: bpp->sc_regs->bpp_or = BPP_OR_AFXN|BPP_OR_SLCT_IN;
146: bpp->sc_regs->bpp_tcr = BPP_TCR_DS;
147: }
148:
149: static __inline__ void
150: bpp_outb(bpp, byte)
151: struct bpp_softc *bpp;
152: u_int8_t byte;
153: {
154: bpp->sc_regs->bpp_dr = byte;
155: }
156:
157: static __inline__ u_int8_t
158: bpp_inb(bpp)
159: struct bpp_softc *bpp;
160: {
161: return (bpp->sc_regs->bpp_dr);
162: }
163:
164: int
165: bppopen(dev, flag, mode, p)
166: dev_t dev;
167: int flag, mode;
168: struct proc *p;
169: {
170: int unit = BPPUNIT(dev);
171: struct bpp_softc *bpp;
172:
173: if (unit >= bpp_cd.cd_ndevs)
174: return (ENXIO);
175: bpp = bpp_cd.cd_devs[unit];
176: if (!bpp)
177: return (ENXIO);
178:
179: if (bpp->sc_open)
180: return (EBUSY);
181:
182: bpp->sc_inbuf = geteblk(BPP_BSIZE);
183: bpp->sc_count = 0;
184: bpp->sc_open = 1;
185:
186: /* bppreset(bpp, 1); */
187: bppresetmode(bpp);
188:
189: return (0);
190: }
191:
192: int
193: bppclose(dev, flag, mode, p)
194: dev_t dev;
195: int flag, mode;
196: struct proc *p;
197: {
198: struct bpp_softc *bpp = bpp_cd.cd_devs[BPPUNIT(dev)];
199: int error = 0;
200:
201: if (bpp->sc_count)
202: (void) bpppushbytes(bpp);
203:
204: /* XXX */
205: bppresetmode(bpp);
206: delay(100);
207: bppreset(bpp, 1);
208: delay(100);
209: bppresetmode(bpp);
210:
211: brelse(bpp->sc_inbuf);
212:
213: bpp->sc_open = 0;
214: return (error);
215: }
216:
217: int
218: bpppushbytes(bpp)
219: struct bpp_softc *bpp;
220: {
221: int spin, error;
222:
223: while (bpp->sc_count > 0) {
224: error = 0;
225:
226: /* Wait for BPP_TCR_ACK and BPP_TCR_BUSY to clear. */
227: spin = 0;
228: while ((bpp->sc_regs->bpp_tcr & BPP_TCR_ACK) ||
229: (bpp->sc_regs->bpp_tcr & BPP_TCR_BUSY)) {
230: delay(1000);
231: if (++spin >= LONG_TIMEOUT)
232: break;
233: }
234:
235: if ((bpp->sc_regs->bpp_tcr & BPP_TCR_ACK) ||
236: (bpp->sc_regs->bpp_tcr & BPP_TCR_BUSY))
237: return (EBUSY);
238:
239: bpp_outb(bpp, *bpp->sc_cp++);
240:
241: /* Clear BPP_TCR_DS. */
242: bpp->sc_regs->bpp_tcr &= ~BPP_TCR_DS;
243:
244: /* Short wait for BPP_TCR_BUSY. */
245: spin = 0;
246: while (!(bpp->sc_regs->bpp_tcr & BPP_TCR_BUSY)) {
247: delay(1000);
248: if (++spin >= SHORT_TIMEOUT)
249: break;
250: }
251: if (!(bpp->sc_regs->bpp_tcr & BPP_TCR_BUSY))
252: error = EIO;
253:
254: /* Set BPP_TCR_DS. */
255: bpp->sc_regs->bpp_tcr |= BPP_TCR_DS;
256:
257: if (error)
258: return (error);
259:
260: bpp->sc_count--;
261: }
262: return (error);
263: }
264:
265: int
266: bppwrite(dev, uio, flags)
267: dev_t dev;
268: struct uio *uio;
269: int flags;
270: {
271: struct bpp_softc *bpp = bpp_cd.cd_devs[BPPUNIT(dev)];
272: size_t n;
273: int error = 0;
274:
275: while ((n = min(BPP_BSIZE, uio->uio_resid)) != 0) {
276: uiomove(bpp->sc_cp = bpp->sc_inbuf->b_data, n, uio);
277: bpp->sc_count = n;
278: error = bpppushbytes(bpp);
279: if (error) {
280: /*
281: * Return accurate residual if interrupted or timed
282: * out.
283: */
284: uio->uio_resid += bpp->sc_count;
285: bpp->sc_count = 0;
286: return (error);
287: }
288: }
289: return (0);
290: }
291:
292: int
293: bppioctl(dev, cmd, data, flag, p)
294: dev_t dev;
295: u_long cmd;
296: caddr_t data;
297: int flag;
298: struct proc *p;
299: {
300: return (ENODEV);
301: }
CVSweb