V9/sys/dev.old/me.c

Compare this file to the similar file:
Show the results in this format:

#include "me.h"
/*
 * various metheus models on dr11-w, hacked from rob's raster tech driver
 * td 86.09.13
 * Bugs:
 *	should support the cursor
 */
#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 meregs{
	short	wcr;		/* Unibus word count reg */
	u_short	bar;		/* Unibus address register */
	u_short	csr;		/* Unibus status/command reg */
	u_short	dr;		/* Data Register */
};
#define	eir	csr		/* Error and Information Register */
/*
 * Unibus status/command register bits
 */
#define GO		0000001
#define	FUNC1		0000002	/* if set, a dma reads rather than writes */
#define	FUNC2		0000004
#define	FUNC3		0000010
#define IENABLE		0000100
#define READY		0000200
#define	MAINT		0010000
#define	ATTN		0020000
#define	ERROR		0100000
/*
 * setting FUNC1 causes metheus to assert attention,
 * abort any dma in progress, cause an error and
 * interrupt (if enabled)
 */
#define	ABORT	FUNC3

#define DMAPRI (PZERO-1)
#define WAITPRI (PZERO+1)

int	meprobe(), meattach(), meintr();
struct	uba_device *medinfo[NME];
u_short	mestd[] = { 0772410, 0772430, 0, 0 };
struct	uba_driver medriver = {
	meprobe, 0, meattach, 0, mestd, "me", medinfo, 0, 0
};

struct mesoftc {
	char	open;		/* flag for device open */
	char	busy;		/* flag for io in progress */
	int	ubinfo;		/* ubasetup/ubarelse datum */
	int	count;		/* io byte count */
	struct	buf *bp;	/* io buffer header */
	int	bufp;		/* io memory address, in UNIBUS coordinates */
	int	icnt;		/* interrupt count */
} mesoftc[NME];
int	mestrategy();
u_int	meminphys();
struct	buf rmebuf[NME];
#define UNIT(dev) (minor(dev))
meprobe(reg)
	caddr_t reg;
{
	register int br, cvec;		/* value-result */
	register struct meregs *meaddr = (struct meregs *)reg;

#ifdef lint
	br = 0; cvec = br; br = cvec;
#endif
	meaddr->csr=ATTN|ABORT|IENABLE;
	DELAY(10000);
	meaddr->csr=IENABLE;
	/* grumble */
	br = 0x15;
	switch ((int)meaddr&077){
	case 010: cvec=0124; break;
	case 030: cvec=0134; break;
	}
	return sizeof(struct meregs);
}
/*ARGSUSED*/
meattach(ui)
struct uba_device *ui;
{
}
meopen(dev)
dev_t dev;
{
	register struct mesoftc *mep;
	register struct uba_device *ui;
	if(UNIT(dev)>=NME
	|| (mep=&mesoftc[minor(dev)])->open
	|| (ui=medinfo[UNIT(dev)])==0
	|| ui->ui_alive==0)
		u.u_error=EBUSY;
	else{
		mep->open=1;
		mep->icnt=0;
		mep->busy=0;
	}
}
meclose(dev)
dev_t dev;
{
	mesoftc[minor(dev)].open=0;
	mesoftc[minor(dev)].busy=0;
}
meread(dev)
dev_t dev;
{
	return merdwr(dev, B_READ);
}
mewrite(dev)
dev_t dev;
{
	return merdwr(dev, B_WRITE);
}
merdwr(dev, flag)
dev_t dev;
{
	register int unit=UNIT(dev);
	if (unit>=NME)
		return ENXIO;
	return physio(mestrategy, &rmebuf[unit], dev, flag, meminphys);
}
u_int meminphys(bp)
register struct buf *bp;
{
	if(bp->b_bcount>32768)	/* what's the actual upper bound? */
		bp->b_bcount=32768;
}
mestrategy(bp)
register struct buf *bp;
{
	register struct mesoftc *mep = &mesoftc[UNIT(bp->b_dev)];
	register struct uba_device *ui;
	if(UNIT(bp->b_dev)>=NME
	|| (ui=medinfo[UNIT(bp->b_dev)])==0
	|| ui->ui_alive==0)
		goto Bad;
	spl5();
	while(mep->busy)
		sleep((caddr_t)mep, DMAPRI+1);
	mep->busy++;
	mep->bp=bp;
	if(bp->b_bcount<=0
	|| bp->b_bcount&1
	|| (int)bp->b_un.b_addr&1){
		u.u_error=EINVAL;
		goto Bad;
	}
	mep->ubinfo=ubasetup(ui->ui_ubanum, bp, UBA_NEEDBDP);
	mep->bufp=mep->ubinfo&0x3ffff;
	mep->count=-(bp->b_bcount>>1);	/* it's a word count */
	mestart(ui);
	if(tsleep((caddr_t)mep, DMAPRI+1, 15)!=TS_OK){
		register struct meregs *meaddr=(struct meregs *)ui->ui_addr;
		bp->b_flags|=B_ERROR;
		/* stop the dma */
		meabort(meaddr);
#ifdef deleted
		meaddr->wcr=0xFFFF;	/* gently; -1 first... */
		meaddr->wcr=0x0000;	/* then zero */
		/* reset device */
		meabort(meaddr);
#endif
		/* fake an interrupt to clear software status */
		meintr(UNIT(bp->b_dev));
	}
	mep->count=0;
	mep->bufp=0;
	(void) spl0();
	ubarelse(ui->ui_ubanum, &mep->ubinfo);
	mep->bp=0;
	iodone(bp);
	wakeup((caddr_t)mep);
	return;
Bad:
	mep->busy=0;
	bp->b_flags|=B_ERROR;
	iodone(bp);
}
meabort(meaddr)
register struct meregs *meaddr;
{
	meaddr->csr=ATTN|ABORT|IENABLE;
	DELAY(100);
	meaddr->csr=IENABLE;
	DELAY(100);
}
mestart(ui)
register struct uba_device *ui;
{
	register int csr;
	register struct meregs *meaddr = (struct meregs *) ui->ui_addr;
	register struct mesoftc *mep = &mesoftc[UNIT(ui->ui_unit)];
	csr=IENABLE|((mep->bufp>>12)&060);
	if(mep->bp->b_flags&B_WRITE)
		csr|=FUNC1;
	meaddr->wcr=mep->count;
	meaddr->bar=mep->bufp;
	meaddr->csr=csr;	/* No GO bit; let function codes settle */
	meaddr->csr=csr|GO;
}
/*ARGSUSED*/
meioctl(dev, cmd, data)
dev_t dev;
int cmd;
register caddr_t data;
{
	return ENOTTY;
}
/*ARGSUSED*/
meintr(dev)
dev_t dev;
{
	register struct meregs *meaddr=
			(struct meregs *)medinfo[UNIT(dev)]->ui_addr;
	register struct mesoftc *mep=&mesoftc[UNIT(dev)];
	register csr;
	mep->icnt++;
	if(mep->busy){
		csr=meaddr->csr;
		if(csr&ERROR){
			meaddr->eir|=ERROR;
			printf("me: csr %x eir %x\n", csr, meaddr->eir);
		}
		meaddr->csr=csr&~(FUNC1|FUNC2|FUNC3);
		mep->busy=0;
		wakeup((caddr_t)mep);
	}
}