|
|
1.1 ! root 1: /* ! 2: * to do: ! 3: * check overflow of user read (bp->b_count) ! 4: * does the address loaded into the registers ! 5: * have to be on a 2k boundary? ! 6: */ ! 7: #include "sys/param.h" ! 8: #include "sys/conf.h" ! 9: #include "sys/user.h" ! 10: #include "sys/buf.h" ! 11: #include "sys/ubaddr.h" ! 12: #include "sys/pte.h" ! 13: ! 14: #include "sys/rco.h" ! 15: #include "sys/rcocmd.h" ! 16: ! 17: /* ! 18: * hardware ! 19: */ ! 20: struct device { ! 21: u_short csr; /* control/status register */ ! 22: u_short vr; /* virtual register (write only)*/ ! 23: u_short ar; /* address register */ ! 24: u_short xar; /* extended address register */ ! 25: }; ! 26: ! 27: #define GO 01 ! 28: #define ERROR 016 /* 02 = FAULT, 04 = TIMEOUT, 010 = OVERFLO */ ! 29: #define RESL 060 ! 30: #define HALF 0100 ! 31: #define READY 0200 ! 32: #define UBACT 07400 ! 33: #define UBALOW 010000 ! 34: #define TEOP 020000 ! 35: #define IENABLE 040000 ! 36: ! 37: #define NUBMREG 4 ! 38: #define IOCHUNK (NBPG*NUBMREG) ! 39: ! 40: /* ! 41: * config glue ! 42: */ ! 43: int rcoopen(), rcoclose(), rcoread(), rcoioctl(); ! 44: ! 45: extern struct rco rco[]; ! 46: extern struct ubaddr rcoaddr[]; ! 47: extern int rcocnt; ! 48: struct cdevsw rcocdev = cdinit(rcoopen, rcoclose, rcoread, nodev, rcoioctl); ! 49: ! 50: #define OPEN 0x01 ! 51: #define BUSY 0x02 ! 52: ! 53: rcoopen(d, f) ! 54: { ! 55: register int dev; ! 56: register struct rco *rp; ! 57: ! 58: if((dev = minor(d)) >= rcocnt) { ! 59: u.u_error = ENODEV; ! 60: return; ! 61: } ! 62: if((rp = &rco[dev])->flags&OPEN) { ! 63: u.u_error = EBUSY; ! 64: return; ! 65: } ! 66: if((rp->addr = (struct device *)ubaddr(&rcoaddr[dev])) == 0 ! 67: || ubbadaddr(rcoaddr[dev].ubno, (caddr_t)rp->addr, sizeof(u_short))) { ! 68: printf("rco%d absent\n", dev); ! 69: u.u_error = ENODEV; ! 70: return; ! 71: } ! 72: rp->flags = OPEN; ! 73: rp->addr->csr = 0; ! 74: rp->dither = 0; ! 75: rp->resol = 2; ! 76: } ! 77: ! 78: rcoclose(d) ! 79: { ! 80: rco[minor(d)].flags &= ~OPEN; ! 81: } ! 82: ! 83: rcominp(bp) ! 84: struct buf *bp; ! 85: { ! 86: } ! 87: ! 88: rcostrategy(bp) ! 89: register struct buf *bp; ! 90: { ! 91: register struct rco *rp = &rco[minor(bp->b_dev)]; ! 92: register uaddr_t uaddr; ! 93: register int s, ubno; ! 94: u_short csr; ! 95: ! 96: csr = IENABLE | ((rp->dither << 6) & HALF) | ((rp->resol << 4) & RESL); ! 97: ubno = rcoaddr[minor(bp->b_dev)].ubno; ! 98: rp->ubm = ubmalloc(ubno, IOCHUNK+(IOCHUNK-1), UBDP|USLP); ! 99: rp->chunkubm = (rp->ubm + (NUBMREG-1)) & ~(NUBMREG-1); ! 100: rp->pte = btopte(bp); ! 101: uaddr = ubmsetmap(ubno, rp->pte, NUBMREG, rp->chunkubm); ! 102: rp->pte += NUBMREG; ! 103: s = spl5(); ! 104: rp->flags |= BUSY; ! 105: rp->addr->ar = uaddr & 0x7FE; /* bits 10-1 */ ! 106: rp->addr->xar = (uaddr >> 8) & 0x3FF8; /* bits 21-11 */ ! 107: while((rp->addr->csr&READY) == 0) ! 108: ; ! 109: rp->addr->csr = csr; ! 110: for(rp->mreg = NUBMREG; rp->mreg; rp->mreg--) ! 111: rp->addr->vr = 1; ! 112: DELAY(50000); ! 113: rp->addr->csr = csr | GO; ! 114: if(tsleep((caddr_t)bp, PRIBIO+1, 20) != TS_OK) { ! 115: bp->b_flags |= B_ERROR; ! 116: iodone(bp); ! 117: } ! 118: rp->addr->csr = 0; ! 119: rp->flags &= ~BUSY; ! 120: splx(s); ! 121: bp->b_resid = 0; ! 122: ubmfree(ubno, rp->ubm); ! 123: } ! 124: ! 125: rcoread(d) ! 126: { ! 127: if((((int)u.u_base) & (IOALIGN-1))) { ! 128: u.u_error = EFAULT; ! 129: return; ! 130: } ! 131: physio(rcostrategy, &rco[minor(d)].buf, d, B_READ, rcominp); ! 132: } ! 133: ! 134: rcoioctl(dev, cmd, addr, flag) ! 135: caddr_t addr; ! 136: { ! 137: register struct rco *rp = &rco[minor(dev)]; ! 138: int i; ! 139: ! 140: if(copyin(addr, (caddr_t)&i, sizeof(i))) { ! 141: u.u_error = EFAULT; ! 142: return; ! 143: } ! 144: switch(cmd) { ! 145: ! 146: case RCORES: ! 147: rp->resol = i; ! 148: break; ! 149: ! 150: case RCODITHER: ! 151: rp->dither = i; ! 152: break; ! 153: ! 154: default: ! 155: u.u_error = ENXIO; ! 156: } ! 157: } ! 158: ! 159: rco0int(d) ! 160: { ! 161: register struct rco *rp = &rco[d]; ! 162: register struct buf *bp; ! 163: ubm_t ubm; ! 164: u_short csr; ! 165: ! 166: if((rp->flags & (BUSY|OPEN)) != (BUSY|OPEN)) { ! 167: printf("rco%d: not busy interrupt\n", d); ! 168: rp->addr->csr = 0; ! 169: return; ! 170: } ! 171: if((csr = rp->addr->csr) & GO) { ! 172: ubm = rp->chunkubm + rp->mreg++; ! 173: (void) ubmsetmap(rcoaddr[d].ubno, rp->pte++, 1, ubm); ! 174: if(rp->mreg > (NUBMREG-1)) ! 175: rp->mreg = 0; ! 176: rp->addr->vr = 1; ! 177: return; ! 178: } ! 179: bp = &rp->buf; ! 180: if((csr & ERROR) || (csr & TEOP) == 0) { ! 181: printf("rco%d: csr=0%o\n", d, csr); ! 182: bp->b_flags |= B_ERROR; ! 183: } ! 184: rp->addr->csr = 0; ! 185: iodone(bp); ! 186: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.