V9/sys/dev.old/vc.c
#include "vc.h"
#if NVC > 0
/*
* Versatec model 122 matrix printer/plotter
* dma interface driver
*
*/
#include "../h/param.h"
#include "../h/dir.h"
#include "../h/user.h"
#include "../h/buf.h"
#include "../h/systm.h"
#include "../h/map.h"
#include "../h/pte.h"
#include "../h/ubavar.h"
#include "../h/ubareg.h"
#include "../h/vc_cmd.h"
unsigned minvcph();
#define VCPRI (PZERO-1)
struct vcdevice {
short int csr;
short int buf;
};
#define VC_ERROR 0100000
#define VC_UNUSED1 0040000
#define VC_SPP 0020000
#define VC_BTCNT 0010000
#define VC_ADDR 0004000
#define VC_PP 0002000
#define VC_SWPBT 0001000
#define VC_UNUSED2 0000400
#define VC_READY 0000200
#define VC_IENABLE 0000100
#define VC_AD17 0000040
#define VC_AD16 0000020
#define VC_REMOTE 0000016
#define VC_REMOTE2 0000010
#define VC_REMOTE1 0000004
#define VC_REMOTE0 0000002
#define VC_DMAGO 0000001
#define VC_MASK (VC_SPP | VC_PP | VC_SWPBT | VC_REMOTE)
struct vc_softc {
int sc_open;
int sc_count;
int sc_bufp;
struct buf *sc_bp;
int sc_ubinfo;
} vc_softc[NVC];
/* remote functions */
#define VC_RLTER (01 << 1)
#define VC_CLEAR (02 << 1)
#define VC_RESET (03 << 1)
#define VC_RFFED (04 << 1)
#define VC_REOTR (05 << 1)
#define VC_RESET_ALL (06 << 1)
/* high order 2 address bits */
#define VC_XMEM(x) ((x) << 4)
struct uba_device *vcdinfo[NVC];
#define VCUNIT(dev) (minor(dev))
struct buf rvcbuf[NVC];
int vcprobe(), vcattach();
struct uba_device *vcdinfo[NVC];
u_short vcstd[] = { 0777514, 0 };
struct uba_driver vcdriver =
{ vcprobe, 0, vcattach, 0, vcstd, "vc", vcdinfo };
vcprobe(reg)
caddr_t reg;
{
register int br, cvec; /* value-result */
register struct vcdevice *vcaddr = (struct vcdevice *) reg;
vcaddr->csr = VC_IENABLE;
DELAY(10000);
vcaddr->csr = 0;
}
/*ARGSUSED*/
vcattach(ui)
struct uba_device *ui;
{
}
vcopen(dev)
dev_t dev;
{
register struct vc_softc *sc;
register struct vcdevice *vcaddr;
register struct uba_device *ui;
if (VCUNIT(dev) >= NVC ||
((sc = &vc_softc[minor(dev)])->sc_open) ||
(ui = vcdinfo[VCUNIT(dev)]) == 0 ||
(ui->ui_alive == 0)) {
u.u_error = ENXIO;
return;
}
vcaddr = (struct vcdevice *)ui->ui_addr;
sc->sc_open = -1;
sc->sc_count = 0;
vcaddr->csr = VC_RESET_ALL;
while (vcwait(dev));
vcaddr->csr |= VC_IENABLE;
vctimo(dev);
if (u.u_error)
vcclose(dev);
}
vcstrategy(bp)
register struct buf *bp;
{
register int e, oldpri;
register struct vc_softc *sc = &vc_softc[VCUNIT(bp->b_dev)];
register struct uba_device *ui = vcdinfo[VCUNIT(bp->b_dev)];
register struct vcdevice *vcaddr = (struct vcdevice *)ui->ui_addr;
oldpri = spl4();
e = vcwait(bp->b_dev);
sc->sc_bp = bp;
sc->sc_ubinfo = ubasetup(ui->ui_ubanum, bp, UBA_NEEDBDP);
if (e = vcwait(bp->b_dev))
goto brkout;
sc->sc_count = -(bp->b_bcount);
vcstart(bp->b_dev);
e = vcwait(bp->b_dev);
sc->sc_count = 0;
brkout:
(void) splx(oldpri);
ubarelse(ui->ui_ubanum, &sc->sc_ubinfo);
sc->sc_bp = 0;
iodone(bp);
if (e)
u.u_error = EIO;
wakeup((caddr_t)sc);
}
int vcblock = 16384;
unsigned
minvcph(bp)
struct buf *bp;
{
if (bp->b_bcount > vcblock)
bp->b_bcount = vcblock;
}
/*ARGSUSED*/
vcwrite(dev)
dev_t dev;
{
physio(vcstrategy, &rvcbuf[VCUNIT(dev)], dev, B_WRITE, minvcph);
}
vcwait(dev)
dev_t dev;
{
register int e;
register struct vcdevice *vcaddr =
(struct vcdevice *)vcdinfo[VCUNIT(dev)]->ui_addr;
register struct vc_softc *sc = &vc_softc[VCUNIT(dev)];
for (;;) {
if (vcaddr->csr & (VC_READY | VC_ERROR))
break;
sleep((caddr_t)sc, VCPRI);
}
if (!(vcaddr -> csr & VC_ERROR)) return(0);
/* Check for NXM - VC_ERROR remains 1 if NOT NXM) */
vcaddr -> csr &= ~VC_ERROR;
if ((e = (vcaddr -> csr & VC_ERROR)) == 0)
printf("vc%d: NXM\n", VCUNIT(dev));
return (e);
}
vcstart(dev)
dev_t;
{
register struct vc_softc *sc = &vc_softc[VCUNIT(dev)];
register struct vcdevice *vcaddr =
(struct vcdevice *)vcdinfo[VCUNIT(dev)]->ui_addr;
if (sc->sc_count == 0) return;
vcaddr->csr |= VC_IENABLE | VC_ADDR;
vcaddr->csr &= ~VC_BTCNT;
vcaddr->buf = sc->sc_ubinfo;
vcaddr->csr |= VC_BTCNT;
vcaddr->buf = sc->sc_count; /* count complemented in strategy */
vcaddr->csr |= VC_DMAGO | VC_XMEM((sc -> sc_ubinfo >> 16) & 3);
}
/*ARGSUSED*/
vcioctl(dev, cmd, addr, flag)
dev_t dev;
int cmd;
register caddr_t addr;
int flag;
{
register int m;
register struct vc_softc *sc = &vc_softc[VCUNIT(dev)];
register struct vcdevice *vcaddr =
(struct vcdevice *)vcdinfo[VCUNIT(dev)]->ui_addr;
switch (cmd) {
case VGETSTATE:
(void) suword(addr, vcaddr -> csr);
return;
case VSETSTATE:
m = fuword(addr);
if (m == -1) {
u.u_error = EFAULT;
return;
}
vccmd(dev, m);
break;
default:
u.u_error = ENOTTY;
return;
}
}
vccmd(dev, vcmd)
dev_t dev;
int vcmd;
{
register int e, oldpri;
register struct vc_softc *sc = &vc_softc[VCUNIT(dev)];
register struct vcdevice *vcaddr =
(struct vcdevice *)vcdinfo[VCUNIT(dev)]->ui_addr;
oldpri = spl4();
e = (vcaddr -> csr & ~VC_MASK) | (vcmd & VC_MASK);
vcaddr -> csr = e;
if (e = vcwait(dev))
u.u_error = EIO;
(void) splx(oldpri);
}
vctimo(dev)
dev_t dev;
{
register struct vc_softc *sc = &vc_softc[VCUNIT(dev)];
if (sc->sc_open)
timeout(vctimo, (caddr_t)dev, hz/10);
vcintr(dev);
}
/*ARGSUSED*/
vcintr(dev)
dev_t dev;
{
register struct vc_softc *sc = &vc_softc[VCUNIT(dev)];
wakeup((caddr_t)sc);
}
vcclose(dev)
dev_t dev;
{
register struct vc_softc *sc = &vc_softc[VCUNIT(dev)];
register struct vcdevice *vcaddr =
(struct vcdevice *)vcdinfo[VCUNIT(dev)]->ui_addr;
sc->sc_open = 0;
sc->sc_count = 0;
sc->sc_ubinfo = 0;
vcaddr->csr = 0;
}
vcreset(uban)
int uban;
{
register int vc11;
register struct uba_device *ui;
register struct vc_softc *sc = vc_softc;
register struct vcdevice *vcaddr;
for (vc11 = 0; vc11 < NVC; vc11++, sc++) {
if ((ui = vcdinfo[vc11]) == 0 ||
ui->ui_alive == 0 ||
ui->ui_ubanum != uban ||
((sc->sc_open) == 0))
continue;
printf(" vc%d", vc11);
vcaddr = (struct vcdevice *)ui->ui_addr;
vcaddr->csr = VC_IENABLE;
if (!(vcaddr -> csr & VC_READY))
continue;
if (sc->sc_ubinfo) {
printf("<%d>", (sc->sc_ubinfo>>28) & 0xf);
ubarelse(ui->ui_ubanum, &sc->sc_ubinfo);
}
sc->sc_count = -(sc->sc_bp->b_bcount);
sc->sc_ubinfo = ubasetup(ui->ui_ubanum, sc->sc_bp, UBA_NEEDBDP);
vcstart(sc->sc_bp->b_dev);
}
}
#endif