V10/lsys/md/cdisknaut.c

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

/*
 * Nautilus console disks
 */

#include "sys/param.h"
#include "sys/user.h"
#include "sys/buf.h"
#include "sys/conf.h"

/*
 * interface to console driver
 * (on nautilus only)
 * this should really be in a header somewhere
 */

extern int *cniwrite(), *cniread();
extern int cniwait();

int cbsopen(), cbsstrat();
int cbsread(), cbswrite();

struct bdevsw cbsbdev = bdinit(cbsopen, nulldev, cbsstrat, 0);
struct cdevsw cbscdev = cdinit(cbsopen, nulldev, cbsread, cbswrite, nodev);

#define	NDEVS	3

static char cbsid[NDEVS] = {
	1,		/* (0) first floppy */
	4,		/* (1) second floppy */
	2,		/* (2) winchester -- read only */
};

#define	BSCMD	0x9	/* ID to write commands */
#define	BSSTS	0x8	/* ID to read answers */
#define	SECTOR	512
#define	MAXBLK	65535	/* the limit is in the protocol */
#define	RCOM	0
#define	WCOM	1
#define	USHIFT	4
#define	STSTS(s)	((s)&017)	/* status in status */
#define	STOK	0

#define	UNIT(d)	((d)&077)	/* in case of silly 0100 bit */

static char cbsbusy, cbswant;

#define	MAXRAW	(8*SECTOR)
static struct buf cbsbuf;
static char cbsdat[MAXRAW];
struct buf *cbsmkbuf();

cbsopen(dev)
dev_t dev;
{
	if (UNIT(minor(dev)) >= NDEVS)
		u.u_error = ENXIO;
}

cbsread(dev)
dev_t dev;
{
	register struct buf *bp;

	if ((bp = cbsmkbuf(dev, B_READ)) == NULL)
		return;
	cbsstrat(bp);
	iowait(bp);
	if (u.u_error == 0)
		iomove(bp->b_un.b_addr, bp->b_bcount-bp->b_resid, B_READ);
	cbsrelse(bp);
}

cbswrite(dev)
dev_t dev;
{
	register struct buf *bp;

	if ((bp = cbsmkbuf(dev, B_WRITE)) == NULL)
		return;
	iomove(bp->b_un.b_addr, bp->b_bcount, B_WRITE);
	if (u.u_error) {
		cbsrelse(bp);
		return;
	}
	cbsstrat(bp);
	iowait(bp);
	cbsrelse(bp);
}

struct buf *
cbsmkbuf(dev, rw)
dev_t dev;
int rw;
{
	register struct buf *bp;
	register int s;

	if (u.u_count < SECTOR || (Ltol(u.u_offset) % SECTOR) != 0) {
		u.u_error = ENXIO;
		return (NULL);
	}
	bp = &cbsbuf;
	s = spl6();
	while (bp->b_flags & B_BUSY) {
		bp->b_flags |= B_WANTED;
		sleep((caddr_t)bp, PRIBIO);
	}
	bp->b_flags |= B_BUSY | rw;
	bp->b_flags &=~ B_DONE;
	splx(s);
	bp->b_bcount = min(u.u_count, MAXRAW);
	bp->b_un.b_addr = cbsdat;
	bp->b_blkno = Ltol(u.u_offset) / SECTOR;
	bp->b_dev = dev;
	return (bp);
}

cbsrelse(bp)
register struct buf *bp;
{

	if (bp->b_flags & B_WANTED)
		wakeup((caddr_t)bp);
	bp->b_flags &=~ (B_WANTED|B_BUSY);
}

cbsstrat(bp)
struct buf *bp;
{
	int s;

	if (bp->b_blkno >= MAXBLK) {
		bp->b_flags |= B_ERROR;
		iodone(bp);
		return;
	}
	s = spl6();
	while (cbsbusy) {
		cbswant++;
		sleep(&cbsbusy);
	}
	cbsbusy++;
	splx(s);
	if (bp->b_flags & B_READ)
		cbsrd(bp);
	else
		cbswr(bp);
	if (cbswant) {
		cbswant = 0;
		wakeup(&cbsbusy);
	}
	cbsbusy = 0;
}

cbsrd(bp)
register struct buf *bp;
{
	static char cmd[3];
	static char sts;
	register int unit;
	daddr_t blkno;
	register char *buf;
	register int *pst, *pdt;

	unit = UNIT(minor(bp->b_dev));
	blkno = bp->b_blkno;
	bp->b_resid = bp->b_bcount;
	buf = bp->b_un.b_addr;
	while (bp->b_resid >= SECTOR) {
		cmd[0] = RCOM|(unit<<USHIFT);
		cmd[1] = blkno;
		cmd[2] = blkno>>8;
		pst = cniread(BSSTS, &sts, 1);
		pdt = cniread(cbsid[unit], buf, SECTOR);
		cniwrite(BSCMD, cmd, 3);
		if (cniwait(pst, 5) || STSTS(sts) != STOK) {
			*pdt = 0;
			if (bp->b_resid != bp->b_bcount)
				bp->b_flags |= B_ERROR;
			break;
		}
		if (cniwait(pdt, 5)) {
			if (bp->b_resid != bp->b_bcount)
				bp->b_flags |= B_ERROR;
			break;
		}
		blkno++;
		buf += SECTOR;
		bp->b_resid -= SECTOR;
	}
	iodone(bp);
}

cbswr(bp)
register struct buf *bp;
{
	static char cmd[3];
	static char sts;
	register int unit;
	daddr_t blkno;
	register char *buf;
	register int *pst, *pdt;

	unit = UNIT(minor(bp->b_dev));
	blkno = bp->b_blkno;
	bp->b_resid = bp->b_bcount;
	buf = bp->b_un.b_addr;
	while (bp->b_resid >= SECTOR) {
		cmd[0] = WCOM|(unit<<USHIFT);
		cmd[1] = blkno;
		cmd[2] = blkno>>8;
		pst = cniread(BSSTS, &sts, 1);
		cniwrite(BSCMD, cmd, 3);
		pdt = cniwrite(cbsid[unit], buf, SECTOR);
		if (cniwait(pst, 5) || STSTS(sts) != STOK) {
			*pdt = 0;
			if (bp->b_resid != bp->b_bcount)
				bp->b_flags |= B_ERROR;
			break;
		}
		if (cniwait(pdt, 1)) {
			if (bp->b_resid != bp->b_bcount)
				bp->b_flags |= B_ERROR;
			break;
		}
		blkno++;
		buf += SECTOR;
		bp->b_resid -= SECTOR;
	}
	iodone(bp);
}