Annotation of sys/arch/sparc/dev/bpp.c, Revision 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