#include "cv.h" /* * Raster Technologies Color Video Interface -- Rob Pike * Model One 20 with Option Card, on DR-11/W */ #include "../h/param.h" #include "../h/dir.h" #include "../h/user.h" #include "../h/buf.h" #include "../h/systm.h" #include "../h/pte.h" #include "../h/map.h" #include "../h/ubareg.h" #include "../h/ubavar.h" struct cvdevice { short wcr; /* Unibus word count reg */ u_short bar; /* Unibus address register */ u_short csr; /* Unibus status/command reg */ u_short idr; /* Input Data Register */ }; #define eir csr /* Error and Information Register */ #define odr idr /* Output Data Register */ /* * Unibus status/command register bits */ #define GO 0000001 #define IENABLE 0000100 #define READY 0000200 #define MAINT 0010000 #define ERROR 0100000 /* * Function codes */ #define WR_IMAGE (1<<1) #define WR_CMD (4<<1) #define WR_RLE (5<<1) #define RD_CMD (7<<1) #define RD_IMAGE (3<<1) #define FUNCMASK (7<<1) #define TOGGLE (8<<1) /* toggle between X and WR_CMD, WR_CMD first */ /* * IOCTL */ #define CVSETDMA (('c'<<8)|1) #define BUSY 01 #define DMAPRI (PZERO-1) #define WAITPRI (PZERO+1) int cvprobe(), cvattach(), cvintr(); struct uba_device *cvdinfo[NCV]; u_short cvstd[] = { 0772410, 0000000, 0 }; struct uba_driver cvdriver = { cvprobe, 0, cvattach, 0, cvstd, "cv", cvdinfo, 0, 0 }; struct cvsoftc { char open; short uid; short state; int ubinfo; int count; struct buf *bp; int bufp; int icnt; short dmamode; short func; } cvsoftc[NCV]; int cvstrategy(); u_int cvminphys(); struct buf rcvbuf[NCV]; #define UNIT(dev) (minor(dev)) cvprobe(reg) caddr_t reg; { register int br, cvec; /* value-result */ register struct cvdevice *cvaddr = (struct cvdevice *) reg; #ifdef lint br = 0; cvec = br; br = cvec; cvintr(0); #endif cvaddr->csr = IENABLE; cvaddr->odr = 0x0707; /* clear screen, force interrupt */ DELAY(10000); cvaddr->csr = 0; /* KLUDGE */ br=0x15; cvec=0124; return (sizeof (struct cvdevice)); } /*ARGSUSED*/ cvattach(ui) struct uba_device *ui; { } cvopen(dev) dev_t dev; { register struct cvsoftc *cvp; register struct uba_device *ui; if (UNIT(dev) >= NCV || (cvp = &cvsoftc[minor(dev)])->open || (ui = cvdinfo[UNIT(dev)]) == 0 || ui->ui_alive == 0) u.u_error = EBUSY; else { cvp->open = 1; cvp->icnt = 0; cvp->state = 0; cvp->uid = u.u_uid; cvp->dmamode = -1; } } cvclose(dev) dev_t dev; { cvsoftc[minor(dev)].open = 0; cvsoftc[minor(dev)].state = 0; } cvread(dev, uio) dev_t dev; struct uio *uio; { register int unit = UNIT(dev); if (unit >= NCV) return (ENXIO); return (physio(cvstrategy, &rcvbuf[unit], dev, B_READ, cvminphys, uio)); } cvwrite(dev, uio) dev_t dev; struct uio *uio; { register int unit = UNIT(dev); if (unit >= NCV) return (ENXIO); return (physio(cvstrategy, &rcvbuf[unit], dev, B_WRITE, cvminphys, uio)); } u_int cvminphys(bp) register struct buf *bp; { if (bp->b_bcount > 65536) /* may be able to do twice as much */ bp->b_bcount = 65536; } cvstrategy(bp) register struct buf *bp; { register struct cvsoftc *cvp = &cvsoftc[UNIT(bp->b_dev)]; register struct uba_device *ui; if (UNIT(bp->b_dev) >= NCV || (ui = cvdinfo[UNIT(bp->b_dev)]) == 0 || ui->ui_alive == 0) goto bad; (void) spl5(); while (cvp->state & BUSY) sleep((caddr_t)cvp, DMAPRI+1); cvp->state |= BUSY; cvp->bp = bp; if(bp->b_bcount<=0 || (bp->b_bcount&1) || ((int)bp->b_un.b_addr&1) || cvp->dmamode<0){ u.u_error = EINVAL; goto bad; } cvp->ubinfo = ubasetup(ui->ui_ubanum, bp, UBA_NEEDBDP); cvp->bufp = cvp->ubinfo & 0x3ffff; cvp->count = -(bp->b_bcount>>1); /* it's a word count */ cvstart(ui); if(tsleep((caddr_t)cvp, DMAPRI+1, 15) != TS_OK){ register struct cvdevice *cvaddr = (struct cvdevice *) ui->ui_addr; bp->b_flags |= B_ERROR; /* stop the dma */ cvslam(cvaddr); cvaddr->wcr=0xFFFF; /* gently; -1 first... */ cvaddr->wcr=0x0000; /* then zero */ /* reset device */ cvslam(cvaddr); /* fake an interrupt to clear software status */ cvintr(UNIT(bp->b_dev)); } cvp->count = 0; cvp->bufp = 0; (void) spl0(); ubarelse(ui->ui_ubanum, &cvp->ubinfo); cvp->bp = 0; iodone(bp); wakeup((caddr_t)cvp); return; bad: cvp->state &= ~BUSY; bp->b_flags |= B_ERROR; iodone(bp); return; } cvslam(cvaddr) register struct cvdevice *cvaddr; { register i; cvaddr->csr=MAINT; for(i=0; i<10; i++) ; cvaddr->csr=0; for(i=0; i<10; i++) ; } cvstart(ui) register struct uba_device *ui; { register int csr; register struct cvdevice *cvaddr = (struct cvdevice *) ui->ui_addr; register struct cvsoftc *cvp = &cvsoftc[UNIT(ui->ui_unit)]; if((cvp->dmamode&TOGGLE) && cvp->func!=WR_CMD) cvp->func = WR_CMD; else cvp->func = cvp->dmamode&~TOGGLE; csr = IENABLE|((cvp->bufp>>12)&060) | cvp->func; cvaddr->wcr = cvp->count; cvaddr->bar = cvp->bufp; cvaddr->csr = csr; /* No GO bit; let function codes settle */ cvaddr->csr = csr|GO; } /*ARGSUSED*/ cvioctl(dev, cmd, data) dev_t dev; int cmd; register caddr_t data; { register struct uba_device *ui = cvdinfo[UNIT(dev)]; register struct cvsoftc *cvp = &cvsoftc[UNIT(dev)]; int fmt; switch (cmd) { case CVSETDMA: /* set DMA mode */ if (copyin(data, (caddr_t)&fmt, sizeof(fmt))) { u.u_error = EFAULT; goto out; } switch (fmt&~TOGGLE) { case WR_IMAGE: case WR_CMD: case WR_RLE: case RD_CMD: case RD_IMAGE: cvp->dmamode = cvp->func = fmt; cvp->func &= ~TOGGLE; break; default: u.u_error = EINVAL; } goto out; default: return (ENOTTY); } out: return u.u_error; } /*ARGSUSED*/ cvintr(dev) dev_t dev; { register struct cvdevice *cvaddr = (struct cvdevice *) cvdinfo[UNIT(dev)]->ui_addr; register struct cvsoftc *cvp = &cvsoftc[UNIT(dev)]; register csr; cvp->icnt++; if (cvp->state&BUSY) { csr = cvaddr->csr; if(csr & ERROR){ cvaddr->eir |= ERROR; printf("cv: CSR %x EIR %x\n", csr, cvaddr->eir); } cvaddr->csr = csr&~FUNCMASK; cvp->state &= ~BUSY; wakeup((caddr_t)cvp); } } cvreset(uban) int uban; { register int i; register struct uba_device *ui; register struct cvsoftc *cvp = cvsoftc; #ifdef untried for (i = 0; i < NCV; i++, cvp++) { if ((ui = cvdinfo[i]) == 0 || ui->ui_alive == 0 || ui->ui_ubanum != uban || cvp->open == 0) continue; printf(" cv%d", i); if ((cvp->state&CVBUSY) == 0) continue; cvp->ubinfo = ubasetup(ui->ui_ubanum, cvp->bp, UBA_NEEDBDP); cvp->count = -(cvp->bp->b_bcount/2); cvstart(ui); } #endif }