V10/sys/md/cdiskstar.c

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

/*
 * Star console floppy
 * -- traces of multiple drives; this was derived from Nautilus.
 * It is probably easier to leave the traces in for future need.
 */

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

/*
 * interface to console driver
 * this should really be in a header somewhere
 */

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

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

struct cdevsw cbscdev = cdinit(cbsopen, nulldev, cbsread, cbswrite, nodev);

#define	NDEVS	1

static char cbsid[NDEVS] = {
	1,		/* (0) floppy */
};

#define	BSCMD	0x9	/* ID to write commands */
#define	BSSTS	0x2	/* ID to read answers */
#define	SECTOR	128
#define	SECTRK	26
#define	MAXBLK	(77*SECTRK)
#define	RCOM	0
#define	WCOM	1
#define	USHIFT	4
#define	STSTS(s)	((s)&0200)	/* status in status */
#define	STOK	0

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

static char cbsbusy, cbswant;

#define	MAXRAW	(4*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;
	cbsdoio(bp, (daddr_t)(Ltol(u.u_offset)/SECTOR));
	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;
	daddr_t sno;

	if ((bp = cbsmkbuf(dev, B_WRITE)) == NULL)
		return;
	sno = Ltol(u.u_offset)/SECTOR;
	iomove(bp->b_un.b_addr, bp->b_bcount, B_WRITE);
	if (u.u_error) {
		cbsrelse(bp);
		return;
	}
	cbsdoio(bp, sno);
	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;
	splx(s);
	bp->b_bcount = min(u.u_count, MAXRAW);
	bp->b_un.b_addr = cbsdat;
	bp->b_dev = dev;
	/* b_blkno unused by any code we'll call */
	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);
}

cbsdoio(bp, sno)
struct buf *bp;
daddr_t sno;
{
	int s;

	if (sno >= 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, sno);
	else
		cbswr(bp, sno);
	if (cbswant) {
		cbswant = 0;
		wakeup(&cbsbusy);
	}
	cbsbusy = 0;
}

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

	unit = UNIT(minor(bp->b_dev));
	bp->b_resid = bp->b_bcount;
	buf = bp->b_un.b_addr;
	while (bp->b_resid >= SECTOR) {
		cmd[0] = RCOM|(unit<<USHIFT);
		pst = cniwrite(BSCMD, cmd, 1);
		if (cniwait(pst, 5)) {
			bp->b_flags |= B_ERROR;
			break;
		}
		cmd[0] = (sno%SECTRK) + 1;
		cmd[1] = sno / SECTRK;
		pst = cniread(BSSTS, &sts, 1);
		pdt = cniread(cbsid[unit], buf, SECTOR);
		cniwrite(cbsid[unit], cmd, 2);
		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;
		}
		sno++;
		buf += SECTOR;
		bp->b_resid -= SECTOR;
	}
	iodone(bp);
}

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

	unit = UNIT(minor(bp->b_dev));
	bp->b_resid = bp->b_bcount;
	buf = bp->b_un.b_addr;
	while (bp->b_resid >= SECTOR) {
		cmd[0] = WCOM|(unit<<USHIFT);
		pst = cniwrite(BSCMD, cmd, 1);
		if (cniwait(pst, 5)) {
			bp->b_flags |= B_ERROR;
			break;
		}
		cmd[0] = (sno%SECTRK) + 1;
		cmd[1] = sno / SECTRK;
		pst = cniread(BSSTS, &sts, 1);
		pdt = cniwrite(cbsid[unit], cmd, 2);
		if (cniwait(pdt, 5)) {
			*pst = 0;
			bp->b_flags |= B_ERROR;
			break;
		}
		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;
		}
		sno++;
		buf += SECTOR;
		bp->b_resid -= SECTOR;
	}
	iodone(bp);
}