|
|
researchv10 Norman
/*
* 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);
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.