Add original unix v6

This commit is contained in:
memnoth
2018-01-27 22:35:41 +09:00
commit 2c7099ee50
664 changed files with 106254 additions and 0 deletions
+636
View File
@@ -0,0 +1,636 @@
#
/*
*/
#include "../param.h"
#include "../user.h"
#include "../buf.h"
#include "../conf.h"
#include "../systm.h"
#include "../proc.h"
#include "../seg.h"
/*
* This is the set of buffers proper, whose heads
* were declared in buf.h. There can exist buffer
* headers not pointing here that are used purely
* as arguments to the I/O routines to describe
* I/O to be done-- e.g. swbuf, just below, for
* swapping.
*/
char buffers[NBUF][514];
struct buf swbuf;
/*
* Declarations of the tables for the magtape devices;
* see bdwrite.
*/
int tmtab;
int httab;
/*
* The following several routines allocate and free
* buffers with various side effects. In general the
* arguments to an allocate routine are a device and
* a block number, and the value is a pointer to
* to the buffer header; the buffer is marked "busy"
* so that no on else can touch it. If the block was
* already in core, no I/O need be done; if it is
* already busy, the process waits until it becomes free.
* The following routines allocate a buffer:
* getblk
* bread
* breada
* Eventually the buffer must be released, possibly with the
* side effect of writing it out, by using one of
* bwrite
* bdwrite
* bawrite
* brelse
*/
/*
* Read in (if necessary) the block and return a buffer pointer.
*/
bread(dev, blkno)
{
register struct buf *rbp;
rbp = getblk(dev, blkno);
if (rbp->b_flags&B_DONE)
return(rbp);
rbp->b_flags =| B_READ;
rbp->b_wcount = -256;
(*bdevsw[dev.d_major].d_strategy)(rbp);
iowait(rbp);
return(rbp);
}
/*
* Read in the block, like bread, but also start I/O on the
* read-ahead block (which is not allocated to the caller)
*/
breada(adev, blkno, rablkno)
{
register struct buf *rbp, *rabp;
register int dev;
dev = adev;
rbp = 0;
if (!incore(dev, blkno)) {
rbp = getblk(dev, blkno);
if ((rbp->b_flags&B_DONE) == 0) {
rbp->b_flags =| B_READ;
rbp->b_wcount = -256;
(*bdevsw[adev.d_major].d_strategy)(rbp);
}
}
if (rablkno && !incore(dev, rablkno)) {
rabp = getblk(dev, rablkno);
if (rabp->b_flags & B_DONE)
brelse(rabp);
else {
rabp->b_flags =| B_READ|B_ASYNC;
rabp->b_wcount = -256;
(*bdevsw[adev.d_major].d_strategy)(rabp);
}
}
if (rbp==0)
return(bread(dev, blkno));
iowait(rbp);
return(rbp);
}
/*
* Write the buffer, waiting for completion.
* Then release the buffer.
*/
bwrite(bp)
struct buf *bp;
{
register struct buf *rbp;
register flag;
rbp = bp;
flag = rbp->b_flags;
rbp->b_flags =& ~(B_READ | B_DONE | B_ERROR | B_DELWRI);
rbp->b_wcount = -256;
(*bdevsw[rbp->b_dev.d_major].d_strategy)(rbp);
if ((flag&B_ASYNC) == 0) {
iowait(rbp);
brelse(rbp);
} else if ((flag&B_DELWRI)==0)
geterror(rbp);
}
/*
* Release the buffer, marking it so that if it is grabbed
* for another purpose it will be written out before being
* given up (e.g. when writing a partial block where it is
* assumed that another write for the same block will soon follow).
* This can't be done for magtape, since writes must be done
* in the same order as requested.
*/
bdwrite(bp)
struct buf *bp;
{
register struct buf *rbp;
register struct devtab *dp;
rbp = bp;
dp = bdevsw[rbp->b_dev.d_major].d_tab;
if (dp == &tmtab || dp == &httab)
bawrite(rbp);
else {
rbp->b_flags =| B_DELWRI | B_DONE;
brelse(rbp);
}
}
/*
* Release the buffer, start I/O on it, but don't wait for completion.
*/
bawrite(bp)
struct buf *bp;
{
register struct buf *rbp;
rbp = bp;
rbp->b_flags =| B_ASYNC;
bwrite(rbp);
}
/*
* release the buffer, with no I/O implied.
*/
brelse(bp)
struct buf *bp;
{
register struct buf *rbp, **backp;
register int sps;
rbp = bp;
if (rbp->b_flags&B_WANTED)
wakeup(rbp);
if (bfreelist.b_flags&B_WANTED) {
bfreelist.b_flags =& ~B_WANTED;
wakeup(&bfreelist);
}
if (rbp->b_flags&B_ERROR)
rbp->b_dev.d_minor = -1; /* no assoc. on error */
backp = &bfreelist.av_back;
sps = PS->integ;
spl6();
rbp->b_flags =& ~(B_WANTED|B_BUSY|B_ASYNC);
(*backp)->av_forw = rbp;
rbp->av_back = *backp;
*backp = rbp;
rbp->av_forw = &bfreelist;
PS->integ = sps;
}
/*
* See if the block is associated with some buffer
* (mainly to avoid getting hung up on a wait in breada)
*/
incore(adev, blkno)
{
register int dev;
register struct buf *bp;
register struct devtab *dp;
dev = adev;
dp = bdevsw[adev.d_major].d_tab;
for (bp=dp->b_forw; bp != dp; bp = bp->b_forw)
if (bp->b_blkno==blkno && bp->b_dev==dev)
return(bp);
return(0);
}
/*
* Assign a buffer for the given block. If the appropriate
* block is already associated, return it; otherwise search
* for the oldest non-busy buffer and reassign it.
* When a 512-byte area is wanted for some random reason
* (e.g. during exec, for the user arglist) getblk can be called
* with device NODEV to avoid unwanted associativity.
*/
getblk(dev, blkno)
{
register struct buf *bp;
register struct devtab *dp;
extern lbolt;
if(dev.d_major >= nblkdev)
panic("blkdev");
loop:
if (dev < 0)
dp = &bfreelist;
else {
dp = bdevsw[dev.d_major].d_tab;
if(dp == NULL)
panic("devtab");
for (bp=dp->b_forw; bp != dp; bp = bp->b_forw) {
if (bp->b_blkno!=blkno || bp->b_dev!=dev)
continue;
spl6();
if (bp->b_flags&B_BUSY) {
bp->b_flags =| B_WANTED;
sleep(bp, PRIBIO);
spl0();
goto loop;
}
spl0();
notavail(bp);
return(bp);
}
}
spl6();
if (bfreelist.av_forw == &bfreelist) {
bfreelist.b_flags =| B_WANTED;
sleep(&bfreelist, PRIBIO);
spl0();
goto loop;
}
spl0();
notavail(bp = bfreelist.av_forw);
if (bp->b_flags & B_DELWRI) {
bp->b_flags =| B_ASYNC;
bwrite(bp);
goto loop;
}
bp->b_flags = B_BUSY | B_RELOC;
bp->b_back->b_forw = bp->b_forw;
bp->b_forw->b_back = bp->b_back;
bp->b_forw = dp->b_forw;
bp->b_back = dp;
dp->b_forw->b_back = bp;
dp->b_forw = bp;
bp->b_dev = dev;
bp->b_blkno = blkno;
return(bp);
}
/*
* Wait for I/O completion on the buffer; return errors
* to the user.
*/
iowait(bp)
struct buf *bp;
{
register struct buf *rbp;
rbp = bp;
spl6();
while ((rbp->b_flags&B_DONE)==0)
sleep(rbp, PRIBIO);
spl0();
geterror(rbp);
}
/*
* Unlink a buffer from the available list and mark it busy.
* (internal interface)
*/
notavail(bp)
struct buf *bp;
{
register struct buf *rbp;
register int sps;
rbp = bp;
sps = PS->integ;
spl6();
rbp->av_back->av_forw = rbp->av_forw;
rbp->av_forw->av_back = rbp->av_back;
rbp->b_flags =| B_BUSY;
PS->integ = sps;
}
/*
* Mark I/O complete on a buffer, release it if I/O is asynchronous,
* and wake up anyone waiting for it.
*/
iodone(bp)
struct buf *bp;
{
register struct buf *rbp;
rbp = bp;
if(rbp->b_flags&B_MAP)
mapfree(rbp);
rbp->b_flags =| B_DONE;
if (rbp->b_flags&B_ASYNC)
brelse(rbp);
else {
rbp->b_flags =& ~B_WANTED;
wakeup(rbp);
}
}
/*
* Zero the core associated with a buffer.
*/
clrbuf(bp)
int *bp;
{
register *p;
register c;
p = bp->b_addr;
c = 256;
do
*p++ = 0;
while (--c);
}
/*
* Initialize the buffer I/O system by freeing
* all buffers and setting all device buffer lists to empty.
*/
binit()
{
register struct buf *bp;
register struct devtab *dp;
register int i;
struct bdevsw *bdp;
bfreelist.b_forw = bfreelist.b_back =
bfreelist.av_forw = bfreelist.av_back = &bfreelist;
for (i=0; i<NBUF; i++) {
bp = &buf[i];
bp->b_dev = -1;
bp->b_addr = buffers[i];
bp->b_back = &bfreelist;
bp->b_forw = bfreelist.b_forw;
bfreelist.b_forw->b_back = bp;
bfreelist.b_forw = bp;
bp->b_flags = B_BUSY;
brelse(bp);
}
i = 0;
for (bdp = bdevsw; bdp->d_open; bdp++) {
dp = bdp->d_tab;
if(dp) {
dp->b_forw = dp;
dp->b_back = dp;
}
i++;
}
nblkdev = i;
}
/*
* Device start routine for disks
* and other devices that have the register
* layout of the older DEC controllers (RF, RK, RP, TM)
*/
#define IENABLE 0100
#define WCOM 02
#define RCOM 04
#define GO 01
devstart(bp, devloc, devblk, hbcom)
struct buf *bp;
int *devloc;
{
register int *dp;
register struct buf *rbp;
register int com;
dp = devloc;
rbp = bp;
*dp = devblk; /* block address */
*--dp = rbp->b_addr; /* buffer address */
*--dp = rbp->b_wcount; /* word count */
com = (hbcom<<8) | IENABLE | GO |
((rbp->b_xmem & 03) << 4);
if (rbp->b_flags&B_READ) /* command + x-mem */
com =| RCOM;
else
com =| WCOM;
*--dp = com;
}
/*
* startup routine for RH controllers.
*/
#define RHWCOM 060
#define RHRCOM 070
rhstart(bp, devloc, devblk, abae)
struct buf *bp;
int *devloc, *abae;
{
register int *dp;
register struct buf *rbp;
register int com;
dp = devloc;
rbp = bp;
if(cputype == 70)
*abae = rbp->b_xmem;
*dp = devblk; /* block address */
*--dp = rbp->b_addr; /* buffer address */
*--dp = rbp->b_wcount; /* word count */
com = IENABLE | GO |
((rbp->b_xmem & 03) << 8);
if (rbp->b_flags&B_READ) /* command + x-mem */
com =| RHRCOM; else
com =| RHWCOM;
*--dp = com;
}
/*
* 11/70 routine to allocate the
* UNIBUS map and initialize for
* a unibus device.
* The code here and in
* rhstart assumes that an rh on an 11/70
* is an rh70 and contains 22 bit addressing.
*/
int maplock;
mapalloc(abp)
struct buf *abp;
{
register i, a;
register struct buf *bp;
if(cputype != 70)
return;
spl6();
while(maplock&B_BUSY) {
maplock =| B_WANTED;
sleep(&maplock, PSWP);
}
maplock =| B_BUSY;
spl0();
bp = abp;
bp->b_flags =| B_MAP;
a = bp->b_xmem;
for(i=16; i<32; i=+2)
UBMAP->r[i+1] = a;
for(a++; i<48; i=+2)
UBMAP->r[i+1] = a;
bp->b_xmem = 1;
}
mapfree(bp)
struct buf *bp;
{
bp->b_flags =& ~B_MAP;
if(maplock&B_WANTED)
wakeup(&maplock);
maplock = 0;
}
/*
* swap I/O
*/
swap(blkno, coreaddr, count, rdflg)
{
register int *fp;
fp = &swbuf.b_flags;
spl6();
while (*fp&B_BUSY) {
*fp =| B_WANTED;
sleep(fp, PSWP);
}
*fp = B_BUSY | B_PHYS | rdflg;
swbuf.b_dev = swapdev;
swbuf.b_wcount = - (count<<5); /* 32 w/block */
swbuf.b_blkno = blkno;
swbuf.b_addr = coreaddr<<6; /* 64 b/block */
swbuf.b_xmem = (coreaddr>>10) & 077;
(*bdevsw[swapdev>>8].d_strategy)(&swbuf);
spl6();
while((*fp&B_DONE)==0)
sleep(fp, PSWP);
if (*fp&B_WANTED)
wakeup(fp);
spl0();
*fp =& ~(B_BUSY|B_WANTED);
return(*fp&B_ERROR);
}
/*
* make sure all write-behind blocks
* on dev (or NODEV for all)
* are flushed out.
* (from umount and update)
*/
bflush(dev)
{
register struct buf *bp;
loop:
spl6();
for (bp = bfreelist.av_forw; bp != &bfreelist; bp = bp->av_forw) {
if (bp->b_flags&B_DELWRI && (dev == NODEV||dev==bp->b_dev)) {
bp->b_flags =| B_ASYNC;
notavail(bp);
bwrite(bp);
goto loop;
}
}
spl0();
}
/*
* Raw I/O. The arguments are
* The strategy routine for the device
* A buffer, which will always be a special buffer
* header owned exclusively by the device for this purpose
* The device number
* Read/write flag
* Essentially all the work is computing physical addresses and
* validating them.
*/
physio(strat, abp, dev, rw)
struct buf *abp;
int (*strat)();
{
register struct buf *bp;
register char *base;
register int nb;
int ts;
bp = abp;
base = u.u_base;
/*
* Check odd base, odd count, and address wraparound
*/
if (base&01 || u.u_count&01 || base>=base+u.u_count)
goto bad;
ts = (u.u_tsize+127) & ~0177;
if (u.u_sep)
ts = 0;
nb = (base>>6) & 01777;
/*
* Check overlap with text. (ts and nb now
* in 64-byte clicks)
*/
if (nb < ts)
goto bad;
/*
* Check that transfer is either entirely in the
* data or in the stack: that is, either
* the end is in the data or the start is in the stack
* (remember wraparound was already checked).
*/
if ((((base+u.u_count)>>6)&01777) >= ts+u.u_dsize
&& nb < 1024-u.u_ssize)
goto bad;
spl6();
while (bp->b_flags&B_BUSY) {
bp->b_flags =| B_WANTED;
sleep(bp, PRIBIO);
}
bp->b_flags = B_BUSY | B_PHYS | rw;
bp->b_dev = dev;
/*
* Compute physical address by simulating
* the segmentation hardware.
*/
bp->b_addr = base&077;
base = (u.u_sep? UDSA: UISA)->r[nb>>7] + (nb&0177);
bp->b_addr =+ base<<6;
bp->b_xmem = (base>>10) & 077;
bp->b_blkno = lshift(u.u_offset, -9);
bp->b_wcount = -((u.u_count>>1) & 077777);
bp->b_error = 0;
u.u_procp->p_flag =| SLOCK;
(*strat)(bp);
spl6();
while ((bp->b_flags&B_DONE) == 0)
sleep(bp, PRIBIO);
u.u_procp->p_flag =& ~SLOCK;
if (bp->b_flags&B_WANTED)
wakeup(bp);
spl0();
bp->b_flags =& ~(B_BUSY|B_WANTED);
u.u_count = (-bp->b_resid)<<1;
geterror(bp);
return;
bad:
u.u_error = EFAULT;
}
/*
* Pick up the device's error number and pass it to the user;
* if there is an error but the number is 0 set a generalized
* code. Actually the latter is always true because devices
* don't yet return specific errors.
*/
geterror(abp)
struct buf *abp;
{
register struct buf *bp;
bp = abp;
if (bp->b_flags&B_ERROR)
if ((u.u_error = bp->b_error)==0)
u.u_error = EIO;
}
+70
View File
@@ -0,0 +1,70 @@
#
/*
*/
/*
* GP DR11C driver used for C/A/T
*/
#include "../param.h"
#include "../user.h"
#include "../tty.h"
#define CATADDR 0167750
#define PCAT 9
#define CATHIWAT 60
#define CATLOWAT 15
struct {
int catlock;
struct clist oq;
} cat;
struct {
int catcsr;
int catbuf;
};
ctopen(dev)
{
if (cat.catlock==0) {
cat.catlock++;
CATADDR->catcsr =| IENABLE;
} else
u.u_error = ENXIO;
}
ctclose()
{
cat.catlock = 0;
}
ctwrite(dev)
{
register c;
extern lbolt;
while ((c=cpass()) >= 0) {
spl5();
while (cat.oq.c_cc > CATHIWAT)
sleep(&cat.oq, PCAT);
while (putc(c, &cat.oq) < 0)
sleep(&lbolt, PCAT);
catintr();
spl0();
}
}
catintr()
{
register int c;
if (CATADDR->catcsr&DONE && (c=getc(&cat.oq))>=0) {
CATADDR->catbuf = c;
if (cat.oq.c_cc==0 || cat.oq.c_cc==CATLOWAT)
wakeup(&cat.oq);
} else {
if (cat.catlock==0)
CATADDR->catcsr = 0;
}
}
+231
View File
@@ -0,0 +1,231 @@
#
/*
*/
/*
* DC-11 driver
*/
#include "../param.h"
#include "../conf.h"
#include "../user.h"
#include "../tty.h"
#include "../proc.h"
/*
* Base address of DC-11's. Minor device i is at
* DCADDR + 10*i.
*/
#define DCADDR 0174000
/*
* Number of DC's for which table space is allocated.
*/
#define NDC11 14
/*
* Control bits in device registers
*/
#define CDLEAD 01
#define CARRIER 04
#define SPEED1 010
#define STOP1 0400
#define RQSEND 01
#define PARITY 040
#define ERROR 0100000
#define CTRANS 040000
#define RINGIND 020000
struct tty dc11[NDC11];
struct dcregs {
int dcrcsr;
int dcrbuf;
int dctcsr;
int dctbuf;
};
/*
* Input-side speed and control bit table.
* Each DC11 has 4 speeds which correspond to the 4 non-zero entries.
* The table index is the same as the speed-selector
* number for the DH11.
* Attempts to set the speed to a zero entry are ignored.
*/
int dcrstab[] {
0, /* 0 baud */
0, /* 50 baud */
0, /* 75 baud */
0, /* 110 baud */
01101, /* 134.5 baud: 7b/ch, speed 0 */
0111, /* 150 baud: 8b/ch, speed 1 */
0, /* 200 baud */
0121, /* 300 baud: 8b/ch, speed 2 */
0, /* 600 baud */
0131, /* 1200 baud */
0, /* 1800 baud */
0, /* 2400 baud */
0, /* 4800 baud */
0, /* 9600 baud */
0, /* X0 */
0, /* X1 */
};
/*
* Transmitter speed table
*/
int dctstab[] {
0, /* 0 baud */
0, /* 50 baud */
0, /* 75 baud */
0, /* 110 baud */
0501, /* 134.5 baud: stop 1 */
0511, /* 150 baud */
0, /* 200 baud */
0521, /* 300 baud */
0, /* 600 baud */
0531, /* 1200 baud */
0, /* 1800 baud */
0, /* 2400 baud */
0, /* 4800 baud */
0, /* 9600 baud */
0, /* X0 */
0, /* X1 */
};
/*
* Open a DC11, waiting until carrier is established.
* Default initial conditions are set up on the first open.
* t_state's CARR_ON bit is a pure copy of the hardware
* CARRIER bit, and is only used to regularize
* carrier tests in general tty routines.
*/
dcopen(dev, flag)
{
register struct tty *rtp;
register *addr;
if (dev.d_minor >= NDC11) {
u.u_error = ENXIO;
return;
}
rtp = &dc11[dev.d_minor];
rtp->t_addr = addr = DCADDR + dev.d_minor*8;
rtp->t_state =| WOPEN;
addr->dcrcsr =| IENABLE|CDLEAD;
if ((rtp->t_state&ISOPEN) == 0) {
rtp->t_erase = CERASE;
rtp->t_kill = CKILL;
addr->dcrcsr = IENABLE|CDLEAD|SPEED1;
addr->dctcsr = IENABLE|SPEED1|STOP1|RQSEND;
rtp->t_state = ISOPEN | WOPEN;
rtp->t_flags = ODDP|EVENP|ECHO;
}
if (addr->dcrcsr & CARRIER)
rtp->t_state =| CARR_ON;
while ((rtp->t_state & CARR_ON) == 0)
sleep(&rtp->t_rawq, TTIPRI);
rtp->t_state =& ~WOPEN;
if (u.u_procp->p_ttyp == 0) {
u.u_procp->p_ttyp = rtp;
rtp->t_dev = dev;
}
}
/*
* Close a dc11
*/
dcclose(dev)
{
register struct tty *tp;
(tp = &dc11[dev.d_minor])->t_state = 0;
if (tp->t_flags&HUPCL)
tp->t_addr->dcrcsr =& ~CDLEAD;
wflushtty(tp);
}
/*
* Read a DC11
*/
dcread(dev)
{
ttread(&dc11[dev.d_minor]);
}
/*
* Write a DC11
*/
dcwrite(dev)
{
ttwrite(&dc11[dev.d_minor]);
}
/*
* DC11 transmitter interrupt.
*/
dcxint(dev)
{
register struct tty *tp;
ttstart(tp = &dc11[dev.d_minor]);
if (tp->t_outq.c_cc == 0 || tp->t_outq.c_cc == TTLOWAT)
wakeup(&tp->t_outq);
}
/*
* DC11 receiver interrupt.
*/
dcrint(dev)
{
register struct tty *tp;
register int c, csr;
tp = &dc11[dev.d_minor];
c = tp->t_addr->dcrbuf;
/*
* If carrier is off, and an open is not in progress,
* knock down the CD lead to hang up the local dataset
* and signal a hangup.
*/
if (((csr = tp->t_addr->dcrcsr) & CARRIER) == 0) {
if ((tp->t_state&WOPEN) == 0) {
tp->t_addr->dcrcsr =& ~CDLEAD;
if (tp->t_state & CARR_ON)
signal(tp, SIGHUP);
flushtty(tp);
}
tp->t_state =& ~CARR_ON;
return;
}
if (csr&ERROR || (tp->t_state&ISOPEN)==0) {
if (tp->t_state&WOPEN && csr&CARRIER)
tp->t_state =| CARR_ON;
wakeup(tp);
return;
}
csr =& PARITY;
if (csr&&(tp->t_flags&ODDP) || !csr&&(tp->t_flags&EVENP))
ttyinput(c, tp);
}
/*
* DC11 stty/gtty.
* Perform general functions and set speeds.
*/
dcsgtty(dev, av)
int *av;
{
register struct tty *tp;
register r;
tp = &dc11[dev.d_minor];
if (ttystty(tp, av))
return;
if (r = dcrstab[tp->t_speeds.lobyte&017])
tp->t_addr->dcrcsr = r;
else
tp->t_addr->dcrcsr =& ~CDLEAD;
if (r = dctstab[tp->t_speeds.hibyte&017])
tp->t_addr->dctcsr = r;
}
+300
View File
@@ -0,0 +1,300 @@
#
/*
*/
/*
* DH-11 driver
* This driver calls on the DHDM driver.
* If the DH has no DM11-BB, then the latter will
* be fake. To insure loading of the correct DM code,
* lib2 should have dhdm.o, dh.o and dhfdm.o in that order.
*/
#include "../param.h"
#include "../conf.h"
#include "../user.h"
#include "../tty.h"
#include "../proc.h"
#define DHADDR 0160020
#define NDH11 16 /* number of lines */
#define DHNCH 8 /* max number of DMA chars */
struct tty dh11[NDH11];
/*
* Place from which to do DMA on output
*/
char dh_clist[NDH11][DHNCH];
/*
* Used to communicate the number of lines to the DM
*/
int ndh11 NDH11;
/*
* Hardware control bits
*/
#define BITS6 01
#define BITS7 02
#define BITS8 03
#define TWOSB 04
#define PENABLE 020
/* DEC manuals incorrectly say this bit causes generation of even parity. */
#define OPAR 040
#define HDUPLX 040000
#define IENABLE 030100
#define PERROR 010000
#define FRERROR 020000
#define XINT 0100000
#define SSPEED 7 /* standard speed: 300 baud */
/*
* Software copy of last dhbar
*/
int dhsar;
struct dhregs {
int dhcsr;
int dhnxch;
int dhlpr;
int dhcar;
int dhbcr;
int dhbar;
int dhbreak;
int dhsilo;
};
/*
* Open a DH11 line.
*/
dhopen(dev, flag)
{
register struct tty *tp;
extern dhstart();
if (dev.d_minor >= NDH11) {
u.u_error = ENXIO;
return;
}
tp = &dh11[dev.d_minor];
tp->t_addr = dhstart;
tp->t_dev = dev;
DHADDR->dhcsr =| IENABLE;
tp->t_state =| WOPEN|SSTART;
if ((tp->t_state&ISOPEN) == 0) {
tp->t_erase = CERASE;
tp->t_kill = CKILL;
tp->t_speeds = SSPEED | (SSPEED<<8);
tp->t_flags = ODDP|EVENP|ECHO;
dhparam(tp);
}
dmopen(dev);
tp->t_state =& ~WOPEN;
tp->t_state =| ISOPEN;
if (u.u_procp->p_ttyp == 0)
u.u_procp->p_ttyp = tp;
}
/*
* Close a DH11 line.
*/
dhclose(dev)
{
register struct tty *tp;
tp = &dh11[dev.d_minor];
dmclose(dev);
tp->t_state =& (CARR_ON|SSTART);
wflushtty(tp);
}
/*
* Read from a DH11 line.
*/
dhread(dev)
{
ttread(&dh11[dev.d_minor]);
}
/*
* write on a DH11 line
*/
dhwrite(dev)
{
ttwrite(&dh11[dev.d_minor]);
}
/*
* DH11 receiver interrupt.
*/
dhrint()
{
register struct tty *tp;
register int c;
while ((c = DHADDR->dhnxch) < 0) { /* char. present */
tp = &dh11[(c>>8)&017];
if (tp >= &dh11[NDH11])
continue;
if((tp->t_state&ISOPEN)==0 || (c&PERROR)) {
wakeup(tp);
continue;
}
if (c&FRERROR) /* break */
if (tp->t_flags&RAW)
c = 0; /* null (for getty) */
else
c = 0177; /* DEL (intr) */
ttyinput(c, tp);
}
}
/*
* stty/gtty for DH11
*/
dhsgtty(dev, av)
int *av;
{
register struct tty *tp;
register r;
tp = &dh11[dev.d_minor];
if (ttystty(tp, av))
return;
dhparam(tp);
}
/*
* Set parameters from open or stty into the DH hardware
* registers.
*/
dhparam(atp)
struct tty *atp;
{
register struct tty *tp;
register int lpr;
tp = atp;
spl5();
DHADDR->dhcsr.lobyte = tp->t_dev.d_minor | IENABLE;
/*
* Hang up line?
*/
if (tp->t_speeds.lobyte==0) {
tp->t_flags =| HUPCL;
dmclose(tp->t_dev);
return;
}
lpr = (tp->t_speeds.hibyte<<10) | (tp->t_speeds.lobyte<<6);
if (tp->t_speeds.lobyte == 4) /* 134.5 baud */
lpr =| BITS6|PENABLE|HDUPLX; else
if (tp->t_flags&EVENP)
if (tp->t_flags&ODDP)
lpr =| BITS8; else
lpr =| BITS7|PENABLE; else
lpr =| BITS7|OPAR|PENABLE;
if (tp->t_speeds.lobyte == 3) /* 110 baud */
lpr =| TWOSB;
DHADDR->dhlpr = lpr;
spl0();
}
/*
* DH11 transmitter interrupt.
* Restart each line which used to be active but has
* terminated transmission since the last interrupt.
*/
dhxint()
{
register struct tty *tp;
register ttybit, bar;
bar = dhsar & ~DHADDR->dhbar;
DHADDR->dhcsr =& ~XINT;
ttybit = 1;
for (tp = dh11; bar; tp++) {
if(bar&ttybit) {
dhsar =& ~ttybit;
bar =& ~ttybit;
tp->t_state =& ~BUSY;
dhstart(tp);
}
ttybit =<< 1;
}
}
/*
* Start (restart) transmission on the given DH11 line.
*/
dhstart(atp)
struct tty *atp;
{
extern ttrstrt();
register c, nch;
register struct tty *tp;
int sps;
char *cp;
sps = PS->integ;
spl5();
tp = atp;
/*
* If it's currently active, or delaying,
* no need to do anything.
*/
if (tp->t_state&(TIMEOUT|BUSY))
goto out;
/*
* t_char is a delay indicator which may have been
* left over from the last start.
* Arrange for the delay.
*/
if (c = tp->t_char) {
tp->t_char = 0;
timeout(ttrstrt, tp, (c&0177)+6);
tp->t_state =| TIMEOUT;
goto out;
}
cp = dh_clist[tp->t_dev.d_minor];
nch = 0;
/*
* Copy DHNCH characters, or up to a delay indicator,
* to the DMA area.
*/
while (nch > -DHNCH && (c = getc(&tp->t_outq))>=0) {
if (c >= 0200) {
tp->t_char = c;
break;
}
*cp++ = c;
nch--;
}
/*
* If the writer was sleeping on output overflow,
* wake him when low tide is reached.
*/
if (tp->t_outq.c_cc<=TTLOWAT && tp->t_state&ASLEEP) {
tp->t_state =& ~ASLEEP;
wakeup(&tp->t_outq);
}
/*
* If any characters were set up, start transmission;
* otherwise, check for possible delay.
*/
if (nch) {
DHADDR->dhcsr.lobyte = tp->t_dev.d_minor | IENABLE;
DHADDR->dhcar = cp+nch;
DHADDR->dhbcr = nch;
c = 1<<tp->t_dev.d_minor;
DHADDR->dhbar =| c;
dhsar =| c;
tp->t_state =| BUSY;
} else if (c = tp->t_char) {
tp->t_char = 0;
timeout(ttrstrt, tp, (c&0177)+6);
tp->t_state =| TIMEOUT;
}
out:
PS->integ = sps;
}
+88
View File
@@ -0,0 +1,88 @@
#
/*
*/
/*
* DM-BB driver
*/
#include "../param.h"
#include "../tty.h"
#include "../conf.h"
#define DMADDR 0170500
struct tty dh11[];
int ndh11; /* Set by dh.c to number of lines */
#define DONE 0200
#define SCENABL 040
#define CLSCAN 01000
#define TURNON 07 /* RQ send, CD lead, line enable */
#define TURNOFF 1 /* line enable only */
#define CARRIER 0100
struct dmregs {
int dmcsr;
int dmlstat;
};
/*
* Turn on the line associated with the (DH) device dev.
*/
dmopen(dev)
{
register struct tty *tp;
tp = &dh11[dev.d_minor];
DMADDR->dmcsr = dev.d_minor;
DMADDR->dmlstat = TURNON;
if (DMADDR->dmlstat&CARRIER)
tp->t_state =| CARR_ON;
DMADDR->dmcsr = IENABLE|SCENABL;
spl5();
while ((tp->t_state&CARR_ON)==0)
sleep(&tp->t_rawq, TTIPRI);
spl0();
}
/*
* If a DH line has the HUPCL mode,
* turn off carrier when it is closed.
*/
dmclose(dev)
{
register struct tty *tp;
tp = &dh11[dev.d_minor];
if (tp->t_flags&HUPCL) {
DMADDR->dmcsr = dev.d_minor;
DMADDR->dmlstat = TURNOFF;
DMADDR->dmcsr = IENABLE|SCENABL;
}
}
/*
* DM11 interrupt.
* Mainly, deal with carrier transitions.
*/
dmint()
{
register struct tty *tp;
if (DMADDR->dmcsr&DONE) {
tp = &dh11[DMADDR->dmcsr&017];
if (tp < &dh11[ndh11]) {
wakeup(tp);
if ((DMADDR->dmlstat&CARRIER)==0) {
if ((tp->t_state&WOPEN)==0) {
signal(tp, SIGHUP);
DMADDR->dmlstat = 0;
flushtty(tp);
}
tp->t_state =& ~CARR_ON;
} else
tp->t_state =| CARR_ON;
}
DMADDR->dmcsr = IENABLE|SCENABL;
}
}
+23
View File
@@ -0,0 +1,23 @@
#
/*
*/
/*
* DM-BB fake driver
*/
#include "../tty.h"
#include "../conf.h"
struct tty dh11[];
dmopen(dev)
{
register struct tty *tp;
tp = &dh11[dev.d_minor];
tp->t_state =| CARR_ON;
}
dmclose(dev)
{
}
+89
View File
@@ -0,0 +1,89 @@
#
/*
*/
/*
* DN-11 ACU interface
*/
#include "../param.h"
#include "../conf.h"
#include "../user.h"
struct dn {
struct {
char dn_stat;
char dn_reg;
} dn11[3];
}
#define DNADDR 0175200
#define PWI 00200
#define ACR 00100
#define DLO 0020
#define DONE 0200
#define IENABLE 0100
#define DSS 040
#define PND 020
#define MENABLE 04
#define DPR 02
#define CRQ 01
#define DNPRI 5
dnopen(dev, flag)
{
register struct dn *dp;
register int rdev;
rdev = dev.d_minor;
dp = &DNADDR->dn11[rdev];
if (dp->dn_reg&(PWI|DLO))
u.u_error = ENXIO;
else {
DNADDR->dn11[0].dn_stat =| MENABLE;
dp->dn_stat = IENABLE|MENABLE|CRQ;
}
}
dnclose(dev)
{
DNADDR->dn11[dev.d_minor].dn_stat =& MENABLE;
}
dnwrite(dev)
{
register struct dn *dp;
register c;
extern lbolt;
dp = &DNADDR->dn11[dev.d_minor];
for(;;) {
while ((dp->dn_stat&DONE)==0)
sleep(DNADDR, DNPRI);
dp->dn_stat =& ~DONE;
contin:
if (dp->dn_reg&(PWI|ACR)) {
u.u_error = EIO;
return;
}
if (dp->dn_stat&DSS)
return;
c = 0;
if (u.u_count==0 || (dp->dn_stat&PND)==0 || (c=cpass())<0)
continue;
if (c=='-') {
sleep(&lbolt, DNPRI);
sleep(&lbolt, DNPRI);
goto contin;
}
dp->dn_reg = c-'0';
dp->dn_stat =| DPR;
}
}
dnint(dev)
{
wakeup(DNADDR);
}
+255
View File
@@ -0,0 +1,255 @@
#
/*
*/
/*
* DP-11 Synchronous interface driver
* This driver is rather insensitive to the remote
* device it talks to, which is to say most of the protocol
* must be supplied by the calling program.
* Exceptions: parity is even; 7 data bits per character;
* max. of 512 characters per record; 10 second timeout
* on waiting to receive; half-duplex transmission.
*/
#include "../param.h"
#include "../conf.h"
#include "../user.h"
#include "../buf.h"
/* control info */
struct {
char *dp_buf;
char *dp_bufp;
int dp_nxmit;
char dp_state;
char dp_timer;
int dp_proc;
} dp11;
/* device registers */
struct {
int dprcsr;
char dprbuf;
char dpsyn0;
int dptcsr;
char dptbuf;
char dpsyn1;
};
/* bits */
#define ODDPAR 010000
#define IENABLE 0100
#define HDUPLX 02
#define CTRANS 0100000
#define RORUN 040000
#define RING 020000
#define DSRDY 010000
#define CARRIER 04000
#define DONE 0200
#define IENABLE 0100
#define SIENABL 040
#define WRITE 1
#define READ 0
#define DTRDY 01
#define RCVACT 04000
#define DPADDR 0174770
#define DPPRI 5
#define SYN 026 /* (receive) sync character */
/*
* The open fails unless the device is not open or
* the opening process is the one that has it open already.
*/
dpopen(dev, flag)
{
int dptimeout();
if (dp11.dp_proc!=0 && dp11.dp_proc!=u.u_procp) {
u.u_error = ENXIO;
return;
}
dp11.dp_proc = u.u_procp;
dp11.dp_state = READ;
if (dp11.dp_buf==0) {
dp11.dp_buf = getblk(NODEV);
dp11.dp_bufp = dp11.dp_buf->b_addr;
dp11.dp_timer = HZ;
timeout(dptimeout, 0, HZ);
}
DPADDR->dpsyn0 = SYN;
DPADDR->dprcsr = HDUPLX|IENABLE;
DPADDR->dptcsr = IENABLE|SIENABL|DTRDY;
}
dpclose()
{
DPADDR->dprcsr = 0;
DPADDR->dptcsr = 0;
dp11.dp_timer = 0;
dp11.dp_proc = 0;
if (dp11.dp_buf != 0) {
brelse(dp11.dp_buf);
dp11.dp_buf = 0;
}
}
/*
* Read waits until:
* there is loss of "data set ready", or
* a timeout occurs, or
* a full record has been received.
* The former two result in an error.
*/
dpread()
{
register char *bp, **epp;
bp = dp11.dp_buf->b_addr;
epp = &dp11.dp_bufp;
for(;;) {
if(dpwait())
return;
if (*epp > bp)
break;
spl6();
if (dp11.dp_timer <= 1) {
spl0();
return;
}
sleep(&dp11, DPPRI);
spl0();
}
iomove(dp11.dp_buf, 0, min(u.u_count, *epp-bp), B_READ);
}
/*
* write checks to make sure that the data set is not reading,
* and that it is ready. Then the record is copied
* and transmission started.
*/
dpwrite()
{
register char *bp;
if (u.u_count==0 || dpwait())
return;
dp11.dp_state = WRITE;
bp = dp11.dp_buf->b_addr;
dp11.dp_bufp = bp;
if (u.u_count>512)
u.u_count = 512;
dp11.dp_nxmit = u.u_count;
iomove(dp11.dp_buf, 0, u.u_count, B_WRITE);
dpstart();
}
/*
* If "data set ready" is down return an error; otherwise
* wait until the dataset is in read state with no carrier,
* which means a record has just been received.
*/
dpwait()
{
for(;;) {
if ((DPADDR->dptcsr&DSRDY)==0 || dp11.dp_buf==0) {
u.u_error = EIO;
return(1);
}
spl6();
if (dp11.dp_state==READ && (DPADDR->dptcsr&CARRIER)==0) {
spl0();
return(0);
}
sleep(&dp11, DPPRI);
spl0();
}
}
/*
* Start off the next character to be transmitted;
* when the record is done, drop back into read state.
*/
dpstart()
{
register int c;
extern char partab[];
dp11.dp_timer = 10;
if (--dp11.dp_nxmit >= 0) {
c = (*dp11.dp_bufp++) & 0177;
DPADDR->dptbuf = c | ~partab[c]&0200;
} else {
dp11.dp_bufp = dp11.dp_buf->b_addr;
dp11.dp_state = READ;
}
}
/*
* Count down the DP timer (once per second)
* If it runs out, it presumably means the other station
* won't speak.
*/
dptimeout()
{
if (dp11.dp_timer==0)
return;
if (--dp11.dp_timer==0) {
dpturnaround();
dp11.dp_timer = 1;
}
timeout(dptimeout, 0, HZ);
}
/*
* Receiver interrupt: if reading, stash character
* unless there is an overrun.
*/
dprint()
{
register int c;
c = DPADDR->dprbuf & 0177;
if (dp11.dp_state==READ) {
if ((DPADDR->dprcsr&ODDPAR) == 0)
c =| 0200;
if (dp11.dp_bufp < dp11.dp_buf->b_addr+512)
*dp11.dp_bufp++ = c;
}
}
/*
* Transmitter interrupt:
* Knock down hardware bits.
* If carrier has dropped, the record is done, so turn the line around;
* otherwise start another character.
*/
dpxint()
{
register int dpstat;
dpstat = DPADDR->dptcsr;
DPADDR->dptcsr =& ~(CTRANS|RORUN|RING|DONE);
if (dpstat & (CTRANS|RORUN))
dpturnaround();
else if (dpstat&DONE && dp11.dp_state==WRITE)
dpstart();
}
/*
* Change the state from writing to reading at the end of a record.
*/
dpturnaround()
{
DPADDR->dprcsr =& ~RCVACT;
if (dp11.dp_state==WRITE) {
dp11.dp_timer = 10;
dp11.dp_state = READ;
dp11.dp_bufp = dp11.dp_buf->b_addr;
}
wakeup(&dp11);
}
+218
View File
@@ -0,0 +1,218 @@
#
/*
*/
/*
* RP04 disk driver
*
* This driver has been tested on a working RP04 for a few hours.
* It does not attempt ECC error correction and is probably
* deficient in general in the case of errors and when packs
* are dismounted.
*/
#include "../param.h"
#include "../buf.h"
#include "../conf.h"
#include "../user.h"
struct {
int hpcs1; /* Control and Status register 1 */
int hpwc; /* Word count register */
int hpba; /* UNIBUS address register */
int hpda; /* Desired address register */
int hpcs2; /* Control and Status register 2*/
int hpds; /* Drive Status */
int hper1; /* Error register 1 */
int hpas; /* Attention Summary */
int hpla; /* Look ahead */
int hpdb; /* Data buffer */
int hpmr; /* Maintenance register */
int hpdt; /* Drive type */
int hpsn; /* Serial number */
int hpof; /* Offset register */
int hpca; /* Desired Cylinder address register*/
int hpcc; /* Current Cylinder */
int hper2; /* Error register 2 */
int hper3; /* Error register 3 */
int hppos; /* Burst error bit position */
int hppat; /* Burst error bit pattern */
int hpbae; /* 11/70 bus extension */
};
#define HPADDR 0176700
#define NHP 8
struct {
char *nblocks;
int cyloff;
} hp_sizes[] {
9614, 0, /* cyl 0 thru 23 */
/* cyl 24 thru 43 available */
-1, 44, /* cyl 44 thru 200 */
-1, 201, /* cyl 201 thru 357 */
20900, 358, /* cyl 358 thru 407 */
/* cyl 408 thru 410 blank */
40600, 0,
40600, 100,
40600, 200,
40600, 300,
};
struct devtab hptab;
struct buf hpbuf;
char hp_openf;
/* Drive Commands */
#define GO 01
#define PRESET 020
#define RECAL 06
#define RCLR 010
#define OFFSET 014
#define READY 0200 /* hpds - drive ready */
#define PIP 020000 /* hpds - Positioning Operation in Progress */
#define ERR 040000 /* hpcs1 - composite error */
#define DU 040000 /* hper1 - Drive Unsafe */
#define DTE 010000 /* hper1 - Drive Timing Error */
#define OPI 020000 /* hper1 - Operation Incomplete */
/* Error Correction Code errors */
#define DCK 0100000 /* hper1 - Data Check error */
#define ECH 0100 /* hper1 - ECC hard error */
#define CLR 040 /* hpcs2 - Controller Clear */
#define FMT22 010000 /* hpof - 16 bit /word format */
/*
* Use av_back to save track+sector,
* b_resid for cylinder.
*/
#define trksec av_back
#define cylin b_resid
hpopen()
{
if(!hp_openf){
hp_openf++;
HPADDR->hpcs2 = CLR;
HPADDR->hpcs1 = RCLR|GO;
HPADDR->hpcs1 = PRESET|GO;
HPADDR->hpof = FMT22;
}
}
hpstrategy(abp)
struct buf *abp;
{
register struct buf *bp;
register char *p1, *p2;
bp = abp;
p1 = &hp_sizes[bp->b_dev.d_minor&07];
if (bp->b_dev.d_minor >= (NHP<<3) ||
bp->b_blkno >= p1->nblocks) {
bp->b_flags =| B_ERROR;
iodone(bp);
return;
}
bp->av_forw = 0;
bp->cylin = p1->cyloff;
p1 = bp->b_blkno;
p2 = lrem(p1, 22);
p1 = ldiv(p1, 22);
bp->trksec = (p1%19)<<8 | p2;
bp->cylin =+ p1/19;
spl5();
if ((p1 = hptab.d_actf)==0)
hptab.d_actf = bp;
else {
for (; p2 = p1->av_forw; p1 = p2) {
if (p1->cylin <= bp->cylin
&& bp->cylin < p2->cylin
|| p1->cylin >= bp->cylin
&& bp->cylin > p2->cylin)
break;
}
bp->av_forw = p2;
p1->av_forw = bp;
}
if (hptab.d_active==0)
hpstart();
spl0();
}
hpstart()
{
register struct buf *bp;
if ((bp = hptab.d_actf) == 0)
return;
hptab.d_active++;
HPADDR->hpcs2 = bp->b_dev.d_minor >> 3;
HPADDR->hpca = bp->cylin;
rhstart(bp, &HPADDR->hpda, bp->trksec, &HPADDR->hpbae);
}
hpintr()
{
register struct buf *bp;
register int ctr;
if (hptab.d_active == 0)
return;
bp = hptab.d_actf;
hptab.d_active = 0;
if (HPADDR->hpcs1 & ERR) { /* error bit */
deverror(bp, HPADDR->hpcs2, 0);
if(HPADDR->hper1 & (DU|DTE|OPI)) {
HPADDR->hpcs2 = CLR;
HPADDR->hpcs1 = RECAL|GO;
ctr = 0;
while ((HPADDR->hpds&PIP) && --ctr);
}
HPADDR->hpcs1 = RCLR|GO;
if (++hptab.d_errcnt <= 10) {
hpstart();
return;
}
bp->b_flags =| B_ERROR;
}
hptab.d_errcnt = 0;
hptab.d_actf = bp->av_forw;
bp->b_resid = HPADDR->hpwc;
iodone(bp);
hpstart();
}
hpread(dev)
{
if(hpphys(dev))
physio(hpstrategy, &hpbuf, dev, B_READ);
}
hpwrite(dev)
{
if(hpphys(dev))
physio(hpstrategy, &hpbuf, dev, B_WRITE);
}
hpphys(dev)
{
register c;
c = lshift(u.u_offset, -9);
c =+ ldiv(u.u_count+511, 512);
if(c > hp_sizes[dev.d_minor & 07].nblocks) {
u.u_error = ENXIO;
return(0);
}
return(1);
}
+116
View File
@@ -0,0 +1,116 @@
#
/*
*/
/*
* RS03/04 disk driver
*/
#include "../param.h"
#include "../buf.h"
#include "../conf.h"
#include "../user.h"
struct {
int hscs1; /* Control and Status register 1 */
int hswc; /* Word count register */
int hsba; /* UNIBUS address register */
int hsda; /* Desired address register */
int hscs2; /* Control and Status register 2 */
int hsds; /* Drive Status */
int hser; /* Error register */
int hsas; /* not used */
int hsla; /* not used */
int hsdb; /* not used */
int hsmr; /* not used */
int hsdt; /* not used */
int hsbae; /* 11/70 bus extension */
};
struct devtab hstab;
struct buf rhsbuf;
#define HSADDR 0172040
#define ERR 040000 /* hscs1 - composite error */
#define GO 01
#define RCLR 010
#define DRY 0200 /* hsds - Drive Ready */
hsstrategy(abp)
struct buf *abp;
{
register struct buf *bp;
register mblks;
bp = abp;
mblks = 1024; /* RJS03 */
if(bp->b_dev.d_minor >= 8)
mblks = 2048; /* RJS04 */
if(bp->b_blkno >= mblks) {
bp->b_flags =| B_ERROR;
iodone(bp);
return;
}
bp->av_forw = 0;
spl5();
if (hstab.d_actf==0)
hstab.d_actf = bp; else
hstab.d_actl->av_forw = bp;
hstab.d_actl = bp;
if (hstab.d_active==0)
hsstart();
spl0();
}
hsstart()
{
register struct buf *bp;
register addr;
if ((bp = hstab.d_actf) == 0)
return;
hstab.d_active++;
addr = bp->b_blkno;
if(bp->b_dev.d_minor < 8)
addr =<< 1; /* RJS03 */
HSADDR->hscs2 = bp->b_dev.d_minor & 07;
rhstart(bp, &HSADDR->hsda, addr<<1, &HSADDR->hsbae);
}
hsintr()
{
register struct buf *bp;
if (hstab.d_active == 0)
return;
bp = hstab.d_actf;
hstab.d_active = 0;
if(HSADDR->hscs1 & ERR){ /* error bit */
deverror(bp, HSADDR->hscs2, 0);
HSADDR->hscs1 = RCLR|GO;
if (++hstab.d_errcnt <= 10) {
hsstart();
return;
}
bp->b_flags =| B_ERROR;
}
hstab.d_errcnt = 0;
hstab.d_actf = bp->av_forw;
iodone(bp);
hsstart();
}
hsread(dev)
{
physio(hsstrategy, &rhsbuf, dev, B_READ);
}
hswrite(dev)
{
physio(hsstrategy, &rhsbuf, dev, B_WRITE);
}
+248
View File
@@ -0,0 +1,248 @@
#
/*
*/
/*
* TJU16 tape driver
*/
#include "../param.h"
#include "../buf.h"
#include "../conf.h"
#include "../user.h"
struct {
int htcs1;
int htwc;
int htba;
int htfc;
int htcs2;
int htds;
int hter;
int htas;
int htck;
int htdb;
int htmr;
int htdt;
int htsn;
int httc;
int htbae; /* 11/70 bus extension */
};
struct devtab httab;
struct buf rhtbuf;
#define NUNIT 8
char h_openf[NUNIT];
char *h_blkno[NUNIT];
char *h_nxrec[NUNIT];
#define HTADDR 0172440
#define GO 01
#define NOP 0
#define WEOF 026
#define SFORW 030
#define SREV 032
#define ERASE 024
#define REW 06
#define CLR 010
#define P800 01300 /* 800 + pdp11 mode */
#define P1600 02300 /* 1600 + pdp11 mode */
#define IENABLE 0100
#define CRDY 0200
#define EOF 04
#define DRY 0200
#define MOL 010000
#define PIP 020000
#define ERR 040000
#define SSEEK 1
#define SIO 2
htopen(dev, flag)
{
register unit;
unit = dev.d_minor&077;
if (unit >= NUNIT || h_openf[unit])
u.u_error = ENXIO;
else {
h_openf[unit]++;
h_blkno[unit] = 0;
h_nxrec[unit] = 65535;
hcommand(dev, NOP);
}
}
htclose(dev, flag)
{
register int unit;
unit = dev.d_minor&077;
h_openf[unit] = 0;
if (flag) {
hcommand(dev, WEOF);
hcommand(dev, WEOF);
}
hcommand(dev, REW);
}
hcommand(dev, com)
{
register unit;
extern lbolt;
unit = dev.d_minor;
while (httab.d_active || (HTADDR->htcs1 & CRDY)==0)
sleep(&lbolt, 1);
HTADDR->htcs2 = (unit>>3)&07;
while((HTADDR->htds&DRY) == 0)
sleep(&lbolt, 1);
if(unit >= 64)
HTADDR->httc = P800 | (unit&07); else
HTADDR->httc = P1600 | (unit&07);
while((HTADDR->htds&(MOL|PIP)) != MOL)
sleep(&lbolt, 1);
HTADDR->htcs1 = com | GO;
}
htstrategy(abp)
struct buf *abp;
{
register struct buf *bp;
register char **p;
bp = abp;
p = &h_nxrec[bp->b_dev.d_minor&077];
if (*p <= bp->b_blkno) {
if (*p < bp->b_blkno) {
bp->b_flags =| B_ERROR;
iodone(bp);
return;
}
if (bp->b_flags&B_READ) {
clrbuf(bp);
iodone(bp);
return;
}
}
if ((bp->b_flags&B_READ)==0)
*p = bp->b_blkno + 1;
bp->av_forw = 0;
spl5();
if (httab.d_actf==0)
httab.d_actf = bp;
else
httab.d_actl->av_forw = bp;
httab.d_actl = bp;
if (httab.d_active==0)
htstart();
spl0();
}
htstart()
{
register struct buf *bp;
register int unit;
register char *blkno;
loop:
if ((bp = httab.d_actf) == 0)
return;
unit = bp->b_dev.d_minor;
HTADDR->htcs2 = (unit>>3)&07;
if(unit >= 64)
HTADDR->httc = P800 | (unit&07); else
HTADDR->httc = P1600 | (unit&07);
unit =& 077;
blkno = h_blkno[unit];
if (h_openf[unit] < 0 || (HTADDR->htcs1 & CRDY)==0) {
bp->b_flags =| B_ERROR;
httab.d_actf = bp->av_forw;
iodone(bp);
goto loop;
}
if (blkno != bp->b_blkno) {
httab.d_active = SSEEK;
if (blkno < bp->b_blkno) {
HTADDR->htfc = blkno - bp->b_blkno;
HTADDR->htcs1 = SFORW|IENABLE|GO;
} else {
if (bp->b_blkno == 0)
HTADDR->htcs1 = REW|IENABLE|GO;
else {
HTADDR->htfc = bp->b_blkno - blkno;
HTADDR->htcs1 = SREV|IENABLE|GO;
}
}
return;
}
httab.d_active = SIO;
rhstart(bp, &HTADDR->htfc, bp->b_wcount<<1, &HTADDR->htbae);
}
htintr()
{
register struct buf *bp;
register int unit;
if ((bp = httab.d_actf)==0)
return;
unit = bp->b_dev.d_minor&077;
if (HTADDR->htcs1 & ERR) {
/*
deverror(bp, HTADDR->hter, 0);
*/
if(HTADDR->htds&EOF) {
if(bp != &rhtbuf && h_openf[unit])
h_openf[unit] = -1;
}
HTADDR->htcs1 = ERR|CLR|GO;
if ((HTADDR->htds&DRY)!=0 && httab.d_active==SIO) {
if (++httab.d_errcnt < 10) {
h_blkno[unit]++;
httab.d_active = 0;
htstart();
return;
}
}
bp->b_flags =| B_ERROR;
httab.d_active = SIO;
}
if (httab.d_active == SIO) {
httab.d_errcnt = 0;
h_blkno[unit]++;
httab.d_actf = bp->av_forw;
httab.d_active = 0;
iodone(bp);
bp->b_resid = HTADDR->htfc;
} else
h_blkno[unit] = bp->b_blkno;
htstart();
}
htread(dev)
{
htphys(dev);
physio(htstrategy, &rhtbuf, dev, B_READ);
u.u_count = -rhtbuf.b_resid;
}
htwrite(dev)
{
htphys(dev);
physio(htstrategy, &rhtbuf, dev, B_WRITE);
u.u_count = 0;
}
htphys(dev)
{
register unit, a;
unit = dev.d_minor;
a = lshift(u.u_offset, -9);
h_blkno[unit] = a;
h_nxrec[unit] = ++a;
}
+117
View File
@@ -0,0 +1,117 @@
#
/*
*/
/*
* KL/DL-11 driver
*/
#include "../param.h"
#include "../conf.h"
#include "../user.h"
#include "../tty.h"
#include "../proc.h"
/* base address */
#define KLADDR 0177560 /* console */
#define KLBASE 0176500 /* kl and dl11-a */
#define DLBASE 0175610 /* dl-e */
#define NKL11 1
#define NDL11 0
#define DSRDY 02
#define RDRENB 01
struct tty kl11[NKL11+NDL11];
struct klregs {
int klrcsr;
int klrbuf;
int kltcsr;
int kltbuf;
}
klopen(dev, flag)
{
register char *addr;
register struct tty *tp;
if(dev.d_minor >= NKL11+NDL11) {
u.u_error = ENXIO;
return;
}
tp = &kl11[dev.d_minor];
if (u.u_procp->p_ttyp == 0) {
u.u_procp->p_ttyp = tp;
tp->t_dev = dev;
}
/*
* set up minor 0 to address KLADDR
* set up minor 1 thru NKL11-1 to address from KLBASE
* set up minor NKL11 on to address from DLBASE
*/
addr = KLADDR + 8*dev.d_minor;
if(dev.d_minor)
addr =+ KLBASE-KLADDR-8;
if(dev.d_minor >= NKL11)
addr =+ DLBASE-KLBASE-8*NKL11+8;
tp->t_addr = addr;
if ((tp->t_state&ISOPEN) == 0) {
tp->t_state = ISOPEN|CARR_ON;
tp->t_flags = XTABS|LCASE|ECHO|CRMOD;
tp->t_erase = CERASE;
tp->t_kill = CKILL;
}
addr->klrcsr =| IENABLE|DSRDY|RDRENB;
addr->kltcsr =| IENABLE;
}
klclose(dev)
{
register struct tty *tp;
tp = &kl11[dev.d_minor];
wflushtty(tp);
tp->t_state = 0;
}
klread(dev)
{
ttread(&kl11[dev.d_minor]);
}
klwrite(dev)
{
ttwrite(&kl11[dev.d_minor]);
}
klxint(dev)
{
register struct tty *tp;
tp = &kl11[dev.d_minor];
ttstart(tp);
if (tp->t_outq.c_cc == 0 || tp->t_outq.c_cc == TTLOWAT)
wakeup(&tp->t_outq);
}
klrint(dev)
{
register int c, *addr;
register struct tty *tp;
tp = &kl11[dev.d_minor];
addr = tp->t_addr;
c = addr->klrbuf;
addr->klrcsr =| RDRENB;
if ((c&0177)==0)
addr->kltbuf = c; /* hardware botch */
ttyinput(c, tp);
}
klsgtty(dev, v)
int *v;
{
register struct tty *tp;
tp = &kl11[dev.d_minor];
ttystty(tp, v);
}
+184
View File
@@ -0,0 +1,184 @@
#
/*
*/
/*
* LP-11 Line printer driver
*/
#include "../param.h"
#include "../conf.h"
#include "../user.h"
#define LPADDR 0177514
#define IENABLE 0100
#define DONE 0200
#define LPPRI 10
#define LPLWAT 50
#define LPHWAT 100
#define EJLINE 60
#define MAXCOL 80
struct {
int lpsr;
int lpbuf;
};
struct {
int cc;
int cf;
int cl;
int flag;
int mcc;
int ccc;
int mlc;
} lp11;
#define CAP 01 /* Set to 0 for 96-char printer, else to 01 */
#define EJECT 02
#define OPEN 04
#define IND 010 /* Set to 0 for no indent, else to 010 */
#define FORM 014
lpopen(dev, flag)
{
if(lp11.flag & OPEN || LPADDR->lpsr < 0) {
u.u_error = EIO;
return;
}
lp11.flag =| (IND|EJECT|OPEN);
LPADDR->lpsr =| IENABLE;
lpcanon(FORM);
}
lpclose(dev, flag)
{
lpcanon(FORM);
lp11.flag = 0;
}
lpwrite()
{
register int c;
while ((c=cpass())>=0)
lpcanon(c);
}
lpcanon(c)
{
register c1, c2;
c1 = c;
if(lp11.flag&CAP) {
if(c1>='a' && c1<='z')
c1 =+ 'A'-'a'; else
switch(c1) {
case '{':
c2 = '(';
goto esc;
case '}':
c2 = ')';
goto esc;
case '`':
c2 = '\'';
goto esc;
case '|':
c2 = '!';
goto esc;
case '~':
c2 = '^';
esc:
lpcanon(c2);
lp11.ccc--;
c1 = '-';
}
}
switch(c1) {
case '\t':
lp11.ccc = (lp11.ccc+8) & ~7;
return;
case FORM:
case '\n':
if((lp11.flag&EJECT) == 0 ||
lp11.mcc!=0 || lp11.mlc!=0) {
lp11.mcc = 0;
lp11.mlc++;
if(lp11.mlc >= EJLINE && lp11.flag&EJECT)
c1 = FORM;
lpoutput(c1);
if(c1 == FORM)
lp11.mlc = 0;
}
case '\r':
lp11.ccc = 0;
if(lp11.flag&IND)
lp11.ccc = 8;
return;
case 010:
if(lp11.ccc > 0)
lp11.ccc--;
return;
case ' ':
lp11.ccc++;
return;
default:
if(lp11.ccc < lp11.mcc) {
lpoutput('\r');
lp11.mcc = 0;
}
if(lp11.ccc < MAXCOL) {
while(lp11.ccc > lp11.mcc) {
lpoutput(' ');
lp11.mcc++;
}
lpoutput(c1);
lp11.mcc++;
}
lp11.ccc++;
}
}
lpstart()
{
register int c;
while (LPADDR->lpsr&DONE && (c = getc(&lp11)) >= 0)
LPADDR->lpbuf = c;
}
lpint()
{
register int c;
lpstart();
if (lp11.cc == LPLWAT || lp11.cc == 0)
wakeup(&lp11);
}
lpoutput(c)
{
if (lp11.cc >= LPHWAT)
sleep(&lp11, LPPRI);
putc(c, &lp11);
spl4();
lpstart();
spl0();
}
+70
View File
@@ -0,0 +1,70 @@
#
/*
*/
/*
* Memory special file
* minor device 0 is physical memory
* minor device 1 is kernel memory
* minor device 2 is EOF/RATHOLE
*/
#include "../param.h"
#include "../user.h"
#include "../conf.h"
#include "../seg.h"
mmread(dev)
{
register c, bn, on;
int a, d;
if(dev.d_minor == 2)
return;
do {
bn = lshift(u.u_offset, -6);
on = u.u_offset[1] & 077;
a = UISA->r[0];
d = UISD->r[0];
spl7();
UISA->r[0] = bn;
UISD->r[0] = 077406;
if(dev.d_minor == 1)
UISA->r[0] = (ka6-6)->r[(bn>>7)&07] + (bn & 0177);
c = fuibyte(on);
UISA->r[0] = a;
UISD->r[0] = d;
spl0();
} while(u.u_error==0 && passc(c)>=0);
}
mmwrite(dev)
{
register c, bn, on;
int a, d;
if(dev.d_minor == 2) {
c = u.u_count;
u.u_count = 0;
u.u_base =+ c;
dpadd(u.u_offset, c);
return;
}
for(;;) {
bn = lshift(u.u_offset, -6);
on = u.u_offset[1] & 077;
if ((c=cpass())<0 || u.u_error!=0)
break;
a = UISA->r[0];
d = UISD->r[0];
spl7();
UISA->r[0] = bn;
UISD->r[0] = 077406;
if(dev.d_minor == 1)
UISA->r[0] = (ka6-6)->r[(bn>>7)&07] + (bn & 0177);
suibyte(on, c);
UISA->r[0] = a;
UISD->r[0] = d;
spl0();
}
}
+21
View File
@@ -0,0 +1,21 @@
/*
*/
char partab[] {
0001,0201,0201,0001,0201,0001,0001,0201,
0202,0004,0003,0205,0005,0206,0201,0001,
0201,0001,0001,0201,0001,0201,0201,0001,
0001,0201,0201,0001,0201,0001,0001,0201,
0200,0000,0000,0200,0000,0200,0200,0000,
0000,0200,0200,0000,0200,0000,0000,0200,
0000,0200,0200,0000,0200,0000,0000,0200,
0200,0000,0000,0200,0000,0200,0200,0000,
0200,0000,0000,0200,0000,0200,0200,0000,
0000,0200,0200,0000,0200,0000,0000,0200,
0000,0200,0200,0000,0200,0000,0000,0200,
0200,0000,0000,0200,0000,0200,0200,0000,
0000,0200,0200,0000,0200,0000,0000,0200,
0200,0000,0000,0200,0000,0200,0200,0000,
0200,0000,0000,0200,0000,0200,0200,0000,
0000,0200,0200,0000,0200,0000,0000,0201
};
+166
View File
@@ -0,0 +1,166 @@
#
/*
*/
/*
* PC-11 Paper tape reader/punch driver
*/
#include "../param.h"
#include "../conf.h"
#include "../user.h"
#define PCADDR 0177550
#define CLOSED 0
#define WAITING 1
#define READING 2
#define EOF 3
#define RDRENB 01
#define IENABLE 0100
#define DONE 0200
#define BUSY 04000
#define ERROR 0100000
#define PCIPRI 30
#define PCOPRI 40
#define PCOLWAT 50
#define PCOHWAT 100
#define PCIHWAT 250
struct {
int pcrcsr;
int pcrbuf;
int pcpcsr;
int pcpbuf;
};
struct clist {
int cc;
int cf;
int cl;
};
struct pc11 {
int pcstate;
struct clist pcin;
struct clist pcout;
} pc11;
pcopen(dev, flag)
{
extern lbolt;
if (flag==0) {
if (pc11.pcstate!=CLOSED) {
u.u_error = ENXIO;
return;
}
pc11.pcstate = WAITING;
while(pc11.pcstate==WAITING) {
PCADDR->pcrcsr = IENABLE|RDRENB;
sleep(&lbolt, PCIPRI);
}
} else {
PCADDR->pcpcsr =| IENABLE;
pcleader();
}
}
pcclose(dev, flag)
{
if (flag==0) {
spl4();
while (getc(&pc11.pcin) >= 0);
PCADDR->pcrcsr = 0;
pc11.pcstate = CLOSED;
spl0();
} else
pcleader();
}
pcread()
{
register int c;
spl4();
do {
while ((c = getc(&pc11.pcin)) < 0) {
if (pc11.pcstate==EOF)
goto out;
if ((PCADDR->pcrcsr&(ERROR|BUSY|DONE))==0)
PCADDR->pcrcsr =| IENABLE|RDRENB;
sleep(&pc11.pcin, PCIPRI);
}
} while (passc(c)>=0);
out:
spl0();
}
pcwrite()
{
register int c;
while ((c=cpass())>=0)
pcoutput(c);
}
pcstart()
{
register int c;
if (PCADDR->pcpcsr&DONE && (c = getc(&pc11.pcout)) >= 0)
PCADDR->pcpbuf = c;
}
pcrint()
{
if (pc11.pcstate==WAITING) {
if (PCADDR->pcrcsr&ERROR)
return;
pc11.pcstate = READING;
}
if (pc11.pcstate==READING) {
if (PCADDR->pcrcsr&ERROR)
pc11.pcstate = EOF;
else {
putc(PCADDR->pcrbuf, &pc11.pcin);
if (pc11.pcin.cc < PCIHWAT)
PCADDR->pcrcsr =| IENABLE|RDRENB;
}
wakeup(&pc11.pcin);
}
}
pcpint()
{
pcstart();
if (pc11.pcout.cc <= PCOLWAT)
wakeup(&pc11.pcout);
}
pcoutput(c)
{
if (PCADDR->pcpcsr&ERROR) {
u.u_error = EIO;
return;
}
if (pc11.pcout.cc >= PCOHWAT)
sleep(&pc11.pcout, PCOPRI);
putc(c, &pc11.pcout);
spl4();
pcstart();
spl0();
}
pcleader()
{
register int i;
i = 100;
do
pcoutput(0);
while (--i);
}
+103
View File
@@ -0,0 +1,103 @@
#
/*
*/
/*
* RF disk driver
*/
#include "../param.h"
#include "../buf.h"
#include "../conf.h"
#include "../user.h"
struct {
int rfcs;
int rfwc;
int rfba;
int rfda;
int rfdae;
};
struct devtab rftab;
struct buf rrfbuf;
#define NRFBLK 1024
#define RFADDR 0177460
#define GO 01
#define RCOM 02
#define WCOM 04
#define CTLCLR 0400
#define IENABLE 0100
rfstrategy(abp)
struct buf *abp;
{
register struct buf *bp;
bp = abp;
if(bp->b_flags&B_PHYS)
mapalloc(bp);
if (bp->b_blkno >= NRFBLK*(bp->b_dev.d_minor+1)) {
bp->b_flags =| B_ERROR;
iodone(bp);
return;
}
bp->av_forw = 0;
spl5();
if (rftab.d_actf==0)
rftab.d_actf = bp;
else
rftab.d_actl->av_forw = bp;
rftab.d_actl = bp;
if (rftab.d_active==0)
rfstart();
spl0();
}
rfstart()
{
register struct buf *bp;
if ((bp = rftab.d_actf) == 0)
return;
rftab.d_active++;
RFADDR->rfdae = bp->b_blkno.hibyte;
devstart(bp, &RFADDR->rfda, bp->b_blkno<<8, 0);
}
rfintr()
{
register struct buf *bp;
if (rftab.d_active == 0)
return;
bp = rftab.d_actf;
rftab.d_active = 0;
if (RFADDR->rfcs < 0) { /* error bit */
deverror(bp, RFADDR->rfcs, RFADDR->rfdae);
RFADDR->rfcs = CTLCLR;
if (++rftab.d_errcnt <= 10) {
rfstart();
return;
}
bp->b_flags =| B_ERROR;
}
rftab.d_errcnt = 0;
rftab.d_actf = bp->av_forw;
iodone(bp);
rfstart();
}
rfread(dev)
{
physio(rfstrategy, &rrfbuf, dev, B_READ);
}
rfwrite(dev)
{
physio(rfstrategy, &rrfbuf, dev, B_WRITE);
}
+132
View File
@@ -0,0 +1,132 @@
#
/*
*/
/*
* RK disk driver
*/
#include "../param.h"
#include "../buf.h"
#include "../conf.h"
#include "../user.h"
#define RKADDR 0177400
#define NRK 4
#define NRKBLK 4872
#define RESET 0
#define GO 01
#define DRESET 014
#define IENABLE 0100
#define DRY 0200
#define ARDY 0100
#define WLO 020000
#define CTLRDY 0200
struct {
int rkds;
int rker;
int rkcs;
int rkwc;
int rkba;
int rkda;
};
struct devtab rktab;
struct buf rrkbuf;
rkstrategy(abp)
struct buf *abp;
{
register struct buf *bp;
register *qc, *ql;
int d;
bp = abp;
if(bp->b_flags&B_PHYS)
mapalloc(bp);
d = bp->b_dev.d_minor-7;
if(d <= 0)
d = 1;
if (bp->b_blkno >= NRKBLK*d) {
bp->b_flags =| B_ERROR;
iodone(bp);
return;
}
bp->av_forw = 0;
spl5();
if (rktab.d_actf==0)
rktab.d_actf = bp;
else
rktab.d_actl->av_forw = bp;
rktab.d_actl = bp;
if (rktab.d_active==0)
rkstart();
spl0();
}
rkaddr(bp)
struct buf *bp;
{
register struct buf *p;
register int b;
int d, m;
p = bp;
b = p->b_blkno;
m = p->b_dev.d_minor - 7;
if(m <= 0)
d = p->b_dev.d_minor;
else {
d = lrem(b, m);
b = ldiv(b, m);
}
return(d<<13 | (b/12)<<4 | b%12);
}
rkstart()
{
register struct buf *bp;
if ((bp = rktab.d_actf) == 0)
return;
rktab.d_active++;
devstart(bp, &RKADDR->rkda, rkaddr(bp), 0);
}
rkintr()
{
register struct buf *bp;
if (rktab.d_active == 0)
return;
bp = rktab.d_actf;
rktab.d_active = 0;
if (RKADDR->rkcs < 0) { /* error bit */
deverror(bp, RKADDR->rker, RKADDR->rkds);
RKADDR->rkcs = RESET|GO;
while((RKADDR->rkcs&CTLRDY) == 0) ;
if (++rktab.d_errcnt <= 10) {
rkstart();
return;
}
bp->b_flags =| B_ERROR;
}
rktab.d_errcnt = 0;
rktab.d_actf = bp->av_forw;
iodone(bp);
rkstart();
}
rkread(dev)
{
physio(rkstrategy, &rrkbuf, dev, B_READ);
}
rkwrite(dev)
{
physio(rkstrategy, &rrkbuf, dev, B_WRITE);
}
+174
View File
@@ -0,0 +1,174 @@
#
/*
*/
/*
* RP disk driver
*/
#include "../param.h"
#include "../buf.h"
#include "../conf.h"
#include "../user.h"
struct {
int rpds;
int rper;
int rpcs;
int rpwc;
int rpba;
int rpca;
int rpda;
};
#define RPADDR 0176710
#define NRP 8
struct {
char *nblocks;
int cyloff;
} rp_sizes[] {
40600, 0, /* cyl 0 thru 202 */
40600, 203, /* cyl 203 thru 405 */
9200, 0, /* cyl 0 thru 45 */
9200, 360, /* cyl 360 thru 405 */
-1, 0, /* cyl 0 thru 327 */
-1, 78, /* cyl 78 thru 405 */
15600, 0, /* cyl 0 thru 77 */
15600, 328, /* cyl 328 thru 405 */
};
struct devtab rptab;
struct buf rrpbuf;
#define GO 01
#define RESET 0
#define HSEEK 014
#define IENABLE 0100
#define READY 0200
#define SUFU 01000
#define SUSU 02000
#define SUSI 04000
#define HNF 010000
/*
* Use av_back to save track+sector,
* b_resid for cylinder.
*/
#define trksec av_back
#define cylin b_resid
rpstrategy(abp)
struct buf *abp;
{
register struct buf *bp;
register char *p1, *p2;
bp = abp;
if(bp->b_flags&B_PHYS)
mapalloc(bp);
p1 = &rp_sizes[bp->b_dev.d_minor&07];
if (bp->b_dev.d_minor >= (NRP<<3) ||
bp->b_blkno >= p1->nblocks) {
bp->b_flags =| B_ERROR;
iodone(bp);
return;
}
bp->av_forw = 0;
bp->cylin = p1->cyloff;
p1 = bp->b_blkno;
p2 = lrem(p1, 10);
p1 = ldiv(p1, 10);
bp->trksec = (p1%20)<<8 | p2;
bp->cylin =+ p1/20;
spl5();
if ((p1 = rptab.d_actf)==0)
rptab.d_actf = bp;
else {
for (; p2 = p1->av_forw; p1 = p2) {
if (p1->cylin <= bp->cylin
&& bp->cylin < p2->cylin
|| p1->cylin >= bp->cylin
&& bp->cylin > p2->cylin)
break;
}
bp->av_forw = p2;
p1->av_forw = bp;
}
if (rptab.d_active==0)
rpstart();
spl0();
}
rpstart()
{
register struct buf *bp;
if ((bp = rptab.d_actf) == 0)
return;
rptab.d_active++;
RPADDR->rpda = bp->trksec;
devstart(bp, &RPADDR->rpca, bp->cylin, bp->b_dev.d_minor>>3);
}
rpintr()
{
register struct buf *bp;
register int ctr;
if (rptab.d_active == 0)
return;
bp = rptab.d_actf;
rptab.d_active = 0;
if (RPADDR->rpcs < 0) { /* error bit */
deverror(bp, RPADDR->rper, RPADDR->rpds);
if(RPADDR->rpds & (SUFU|SUSI|HNF)) {
RPADDR->rpcs.lobyte = HSEEK|GO;
ctr = 0;
while ((RPADDR->rpds&SUSU) && --ctr);
}
RPADDR->rpcs = RESET|GO;
ctr = 0;
while ((RPADDR->rpcs&READY) == 0 && --ctr);
if (++rptab.d_errcnt <= 10) {
rpstart();
return;
}
bp->b_flags =| B_ERROR;
}
rptab.d_errcnt = 0;
rptab.d_actf = bp->av_forw;
bp->b_resid = RPADDR->rpwc;
iodone(bp);
rpstart();
}
rpread(dev)
{
if(rpphys(dev))
physio(rpstrategy, &rrpbuf, dev, B_READ);
}
rpwrite(dev)
{
if(rpphys(dev))
physio(rpstrategy, &rrpbuf, dev, B_WRITE);
}
rpphys(dev)
{
register c;
c = lshift(u.u_offset, -9);
c =+ ldiv(u.u_count+511, 512);
if(c > rp_sizes[dev.d_minor & 07].nblocks) {
u.u_error = ENXIO;
return(0);
}
return(1);
}
+54
View File
@@ -0,0 +1,54 @@
#
/*
*/
/*
* indirect driver for controlling tty.
*/
#include "../param.h"
#include "../conf.h"
#include "../user.h"
#include "../tty.h"
#include "../proc.h"
syopen(dev, flag)
{
register *tp;
if(tp = syttyp())
(*cdevsw[tp->t_dev.d_major].d_open)(tp->t_dev, flag);
}
syread(dev)
{
register *tp;
if(tp = syttyp())
(*cdevsw[tp->t_dev.d_major].d_read)(tp->t_dev);
}
sywrite(dev)
{
register *tp;
if(tp = syttyp())
(*cdevsw[tp->t_dev.d_major].d_write)(tp->t_dev);
}
sysgtty(dev, flag)
{
register *tp;
if(tp = syttyp())
(*cdevsw[tp->t_dev.d_major].d_sgtty)(tp->t_dev, flag);
}
syttyp()
{
register tp;
tp = u.u_procp->p_ttyp;
if(tp == NULL)
u.u_error = ENXIO;
return(tp);
}
+171
View File
@@ -0,0 +1,171 @@
#
/*
*/
/*
* TC-11 DECtape driver
*/
#include "../param.h"
#include "../conf.h"
#include "../buf.h"
#include "../user.h"
struct {
int tccsr;
int tccm;
int tcwc;
int tcba;
int tcdt;
};
struct devtab tctab;
char tcper[8];
#define TCADDR 0177340
#define NTCBLK 578
#define TAPERR 0100000
#define TREV 04000
#define READY 0200
#define IENABLE 0100
#define UPS 0200
#define ENDZ 0100000
#define BLKM 02000
#define ILGOP 010000
#define SELERR 04000
#define SAT 0
#define RNUM 02
#define RDATA 04
#define SST 010
#define WDATA 014
#define GO 01
#define SFORW 1
#define SREV 2
#define SIO 3
tcclose(dev)
{
bflush(dev);
tcper[dev&07] = 0;
}
tcstrategy(abp)
struct buf *abp;
{
register struct buf *bp;
bp = abp;
if(bp->b_flags&B_PHYS)
mapalloc(bp);
if(bp->b_blkno >= NTCBLK || tcper[bp->b_dev&07]) {
bp->b_flags =| B_ERROR;
iodone(bp);
return;
}
bp->av_forw = 0;
spl6();
if (tctab.d_actf==0)
tctab.d_actf = bp;
else
tctab.d_actl->av_forw = bp;
tctab.d_actl = bp;
if (tctab.d_active==0)
tcstart();
spl0();
}
tcstart()
{
register struct buf *bp;
register int *tccmp, com;
loop:
tccmp = &TCADDR->tccm;
if ((bp = tctab.d_actf) == 0)
return;
if(tcper[bp->b_dev&07]) {
if((tctab.d_actf = bp->av_forw) == 0)
(*tccmp).lobyte = SAT|GO;
bp->b_flags =| B_ERROR;
iodone(bp);
goto loop;
}
if (((*tccmp).hibyte&07) != bp->b_dev.d_minor)
(*tccmp).lobyte = SAT|GO;
tctab.d_errcnt = 20;
tctab.d_active = SFORW;
com = (bp->b_dev.d_minor<<8) | IENABLE|RNUM|GO;
if ((TCADDR->tccsr & UPS) == 0) {
com =| TREV;
tctab.d_active = SREV;
}
*tccmp = com;
}
tcintr()
{
register struct buf *bp;
register int *tccmp;
register int *tcdtp;
tccmp = &TCADDR->tccm;
tcdtp = &TCADDR->tccsr;
bp = tctab.d_actf;
if (*tccmp&TAPERR) {
if((*tcdtp&(ENDZ|BLKM)) == 0)
deverror(bp, *tcdtp, 0);
if(*tcdtp & (ILGOP|SELERR)) {
tcper[bp->b_dev&07]++;
tctab.d_errcnt = 0;
}
*tccmp =& ~TAPERR;
if (--tctab.d_errcnt <= 0) {
bp->b_flags =| B_ERROR;
goto done;
}
if (*tccmp&TREV) {
setforw:
tctab.d_active = SFORW;
*tccmp =& ~TREV;
} else {
setback:
tctab.d_active = SREV;
*tccmp =| TREV;
}
(*tccmp).lobyte = IENABLE|RNUM|GO;
return;
}
tcdtp = &TCADDR->tcdt;
switch (tctab.d_active) {
case SIO:
done:
tctab.d_active = 0;
if (tctab.d_actf = bp->av_forw)
tcstart();
else
TCADDR->tccm.lobyte = SAT|GO;
iodone(bp);
return;
case SFORW:
if (*tcdtp > bp->b_blkno)
goto setback;
if (*tcdtp < bp->b_blkno)
goto setforw;
*--tcdtp = bp->b_addr; /* core address */
*--tcdtp = bp->b_wcount;
tccmp->lobyte = ((bp->b_xmem & 03) << 4) | IENABLE|GO
| (bp->b_flags&B_READ?RDATA:WDATA);
tctab.d_active = SIO;
return;
case SREV:
if (*tcdtp+3 > bp->b_blkno)
goto setback;
goto setforw;
}
}
+221
View File
@@ -0,0 +1,221 @@
#
/*
*/
/*
* TM tape driver
*/
#include "../param.h"
#include "../buf.h"
#include "../conf.h"
#include "../user.h"
struct {
int tmer;
int tmcs;
int tmbc;
int tmba;
int tmdb;
int tmrd;
};
struct devtab tmtab;
struct buf rtmbuf;
char t_openf[8];
char *t_blkno[8];
char *t_nxrec[8];
#define TMADDR 0172520
#define GO 01
#define RCOM 02
#define WCOM 04
#define WEOF 06
#define SFORW 010
#define SREV 012
#define WIRG 014
#define REW 016
#define DENS 060000 /* 9-channel */
#define IENABLE 0100
#define CRDY 0200
#define GAPSD 010000
#define TUR 1
#define HARD 0102200 /* ILC, EOT, NXM */
#define EOF 0040000
#define SSEEK 1
#define SIO 2
tmopen(dev, flag)
{
register dminor;
dminor = dev.d_minor;
if (t_openf[dminor])
u.u_error = ENXIO;
else {
t_openf[dminor]++;
t_blkno[dminor] = 0;
t_nxrec[dminor] = 65535;
}
}
tmclose(dev, flag)
{
register int dminor;
dminor = dev.d_minor;
t_openf[dminor] = 0;
if (flag)
tcommand(dminor, WEOF);
tcommand(dminor, REW);
}
tcommand(unit, com)
{
extern lbolt;
while (tmtab.d_active || (TMADDR->tmcs & CRDY)==0)
sleep(&lbolt, 1);
TMADDR->tmcs = DENS|com|GO | (unit<<8);
}
tmstrategy(abp)
struct buf *abp;
{
register struct buf *bp;
register char **p;
bp = abp;
p = &t_nxrec[bp->b_dev.d_minor];
if (*p <= bp->b_blkno) {
if (*p < bp->b_blkno) {
bp->b_flags =| B_ERROR;
iodone(bp);
return;
}
if (bp->b_flags&B_READ) {
clrbuf(bp);
iodone(bp);
return;
}
}
if ((bp->b_flags&B_READ)==0)
*p = bp->b_blkno + 1;
bp->av_forw = 0;
spl5();
if (tmtab.d_actf==0)
tmtab.d_actf = bp;
else
tmtab.d_actl->av_forw = bp;
tmtab.d_actl = bp;
if (tmtab.d_active==0)
tmstart();
spl0();
}
tmstart()
{
register struct buf *bp;
register int com;
int unit;
register char *blkno;
loop:
if ((bp = tmtab.d_actf) == 0)
return;
unit = bp->b_dev.d_minor;
blkno = t_blkno[unit];
if (t_openf[unit] < 0 || (TMADDR->tmcs & CRDY)==0) {
bp->b_flags =| B_ERROR;
tmtab.d_actf = bp->av_forw;
iodone(bp);
goto loop;
}
com = (unit<<8) | ((bp->b_xmem & 03) << 4) | IENABLE|DENS;
if (blkno != bp->b_blkno) {
tmtab.d_active = SSEEK;
if (blkno < bp->b_blkno) {
com =| SFORW|GO;
TMADDR->tmbc = blkno - bp->b_blkno;
} else {
if (bp->b_blkno == 0)
com =| REW|GO;
else {
com =| SREV|GO;
TMADDR->tmbc = bp->b_blkno - blkno;
}
}
TMADDR->tmcs = com;
return;
}
tmtab.d_active = SIO;
TMADDR->tmbc = bp->b_wcount << 1;
TMADDR->tmba = bp->b_addr; /* core address */
TMADDR->tmcs = com | ((bp->b_flags&B_READ)? RCOM|GO:
((tmtab.d_errcnt)? WIRG|GO: WCOM|GO));
}
tmintr()
{
register struct buf *bp;
register int unit;
if ((bp = tmtab.d_actf)==0)
return;
unit = bp->b_dev.d_minor;
if (TMADDR->tmcs < 0) { /* error bit */
/*
deverror(bp, TMADDR->tmer);
*/
while(TMADDR->tmrd & GAPSD) ; /* wait for gap shutdown */
if ((TMADDR->tmer&(HARD|EOF))==0 && tmtab.d_active==SIO) {
if (++tmtab.d_errcnt < 10) {
t_blkno[unit]++;
tmtab.d_active = 0;
tmstart();
return;
}
} else
if(bp != &rtmbuf && (TMADDR->tmer&EOF)==0)
t_openf[unit] = -1;
bp->b_flags =| B_ERROR;
tmtab.d_active = SIO;
}
if (tmtab.d_active == SIO) {
tmtab.d_errcnt = 0;
t_blkno[unit]++;
tmtab.d_actf = bp->av_forw;
tmtab.d_active = 0;
iodone(bp);
bp->b_resid = TMADDR->tmbc;
} else
t_blkno[unit] = bp->b_blkno;
tmstart();
}
tmread(dev)
{
tmphys(dev);
physio(tmstrategy, &rtmbuf, dev, B_READ);
u.u_count = -rtmbuf.b_resid;
}
tmwrite(dev)
{
tmphys(dev);
physio(tmstrategy, &rtmbuf, dev, B_WRITE);
u.u_count = 0;
}
tmphys(dev)
{
register unit, a;
unit = dev.d_minor;
a = lshift(u.u_offset, -9);
t_blkno[unit] = a;
t_nxrec[unit] = ++a;
}
+537
View File
@@ -0,0 +1,537 @@
#
/*
*/
/*
* general TTY subroutines
*/
#include "../param.h"
#include "../systm.h"
#include "../user.h"
#include "../tty.h"
#include "../proc.h"
#include "../inode.h"
#include "../file.h"
#include "../reg.h"
#include "../conf.h"
/*
* Input mapping table-- if an entry is non-zero, when the
* corresponding character is typed preceded by "\" the escape
* sequence is replaced by the table value. Mostly used for
* upper-case only terminals.
*/
char maptab[]
{
000,000,000,000,004,000,000,000,
000,000,000,000,000,000,000,000,
000,000,000,000,000,000,000,000,
000,000,000,000,000,000,000,000,
000,'|',000,'#',000,000,000,'`',
'{','}',000,000,000,000,000,000,
000,000,000,000,000,000,000,000,
000,000,000,000,000,000,000,000,
'@',000,000,000,000,000,000,000,
000,000,000,000,000,000,000,000,
000,000,000,000,000,000,000,000,
000,000,000,000,000,000,'~',000,
000,'A','B','C','D','E','F','G',
'H','I','J','K','L','M','N','O',
'P','Q','R','S','T','U','V','W',
'X','Y','Z',000,000,000,000,000,
};
/*
* The actual structure of a clist block manipulated by
* getc and putc (mch.s)
*/
struct cblock {
struct cblock *c_next;
char info[6];
};
/* The character lists-- space for 6*NCLIST characters */
struct cblock cfree[NCLIST];
/* List head for unused character blocks. */
struct cblock *cfreelist;
/*
* structure of device registers for KL, DL, and DC
* interfaces-- more particularly, those for which the
* SSTART bit is off and can be treated by general routines
* (that is, not DH).
*/
struct {
int ttrcsr;
int ttrbuf;
int tttcsr;
int tttbuf;
};
/*
* The routine implementing the gtty system call.
* Just call lower level routine and pass back values.
*/
gtty()
{
int v[3];
register *up, *vp;
vp = v;
sgtty(vp);
if (u.u_error)
return;
up = u.u_arg[0];
suword(up, *vp++);
suword(++up, *vp++);
suword(++up, *vp++);
}
/*
* The routine implementing the stty system call.
* Read in values and call lower level.
*/
stty()
{
register int *up;
up = u.u_arg[0];
u.u_arg[0] = fuword(up);
u.u_arg[1] = fuword(++up);
u.u_arg[2] = fuword(++up);
sgtty(0);
}
/*
* Stuff common to stty and gtty.
* Check legality and switch out to individual
* device routine.
* v is 0 for stty; the parameters are taken from u.u_arg[].
* c is non-zero for gtty and is the place in which the device
* routines place their information.
*/
sgtty(v)
int *v;
{
register struct file *fp;
register struct inode *ip;
if ((fp = getf(u.u_ar0[R0])) == NULL)
return;
ip = fp->f_inode;
if ((ip->i_mode&IFMT) != IFCHR) {
u.u_error = ENOTTY;
return;
}
(*cdevsw[ip->i_addr[0].d_major].d_sgtty)(ip->i_addr[0], v);
}
/*
* Wait for output to drain, then flush input waiting.
*/
wflushtty(atp)
struct tty *atp;
{
register struct tty *tp;
tp = atp;
spl5();
while (tp->t_outq.c_cc) {
tp->t_state =| ASLEEP;
sleep(&tp->t_outq, TTOPRI);
}
flushtty(tp);
spl0();
}
/*
* Initialize clist by freeing all character blocks, then count
* number of character devices. (Once-only routine)
*/
cinit()
{
register int ccp;
register struct cblock *cp;
register struct cdevsw *cdp;
ccp = cfree;
for (cp=(ccp+07)&~07; cp <= &cfree[NCLIST-1]; cp++) {
cp->c_next = cfreelist;
cfreelist = cp;
}
ccp = 0;
for(cdp = cdevsw; cdp->d_open; cdp++)
ccp++;
nchrdev = ccp;
}
/*
* flush all TTY queues
*/
flushtty(atp)
struct tty *atp;
{
register struct tty *tp;
register int sps;
tp = atp;
while (getc(&tp->t_canq) >= 0);
while (getc(&tp->t_outq) >= 0);
wakeup(&tp->t_rawq);
wakeup(&tp->t_outq);
sps = PS->integ;
spl5();
while (getc(&tp->t_rawq) >= 0);
tp->t_delct = 0;
PS->integ = sps;
}
/*
* transfer raw input list to canonical list,
* doing erase-kill processing and handling escapes.
* It waits until a full line has been typed in cooked mode,
* or until any character has been typed in raw mode.
*/
canon(atp)
struct tty *atp;
{
register char *bp;
char *bp1;
register struct tty *tp;
register int c;
tp = atp;
spl5();
while (tp->t_delct==0) {
if ((tp->t_state&CARR_ON)==0)
return(0);
sleep(&tp->t_rawq, TTIPRI);
}
spl0();
loop:
bp = &canonb[2];
while ((c=getc(&tp->t_rawq)) >= 0) {
if (c==0377) {
tp->t_delct--;
break;
}
if ((tp->t_flags&RAW)==0) {
if (bp[-1]!='\\') {
if (c==tp->t_erase) {
if (bp > &canonb[2])
bp--;
continue;
}
if (c==tp->t_kill)
goto loop;
if (c==CEOT)
continue;
} else
if (maptab[c] && (maptab[c]==c || (tp->t_flags&LCASE))) {
if (bp[-2] != '\\')
c = maptab[c];
bp--;
}
}
*bp++ = c;
if (bp>=canonb+CANBSIZ)
break;
}
bp1 = bp;
bp = &canonb[2];
c = &tp->t_canq;
while (bp<bp1)
putc(*bp++, c);
return(1);
}
/*
* Place a character on raw TTY input queue, putting in delimiters
* and waking up top half as needed.
* Also echo if required.
* The arguments are the character and the appropriate
* tty structure.
*/
ttyinput(ac, atp)
struct tty *atp;
{
register int t_flags, c;
register struct tty *tp;
tp = atp;
c = ac;
t_flags = tp->t_flags;
if ((c =& 0177) == '\r' && t_flags&CRMOD)
c = '\n';
if ((t_flags&RAW)==0 && (c==CQUIT || c==CINTR)) {
signal(tp, c==CINTR? SIGINT:SIGQIT);
flushtty(tp);
return;
}
if (tp->t_rawq.c_cc>=TTYHOG) {
flushtty(tp);
return;
}
if (t_flags&LCASE && c>='A' && c<='Z')
c =+ 'a'-'A';
putc(c, &tp->t_rawq);
if (t_flags&RAW || c=='\n' || c==004) {
wakeup(&tp->t_rawq);
if (putc(0377, &tp->t_rawq)==0)
tp->t_delct++;
}
if (t_flags&ECHO) {
ttyoutput(c, tp);
ttstart(tp);
}
}
/*
* put character on TTY output queue, adding delays,
* expanding tabs, and handling the CR/NL bit.
* It is called both from the top half for output, and from
* interrupt level for echoing.
* The arguments are the character and the tty structure.
*/
ttyoutput(ac, tp)
struct tty *tp;
{
register int c;
register struct tty *rtp;
register char *colp;
int ctype;
rtp = tp;
c = ac&0177;
/*
* Ignore EOT in normal mode to avoid hanging up
* certain terminals.
*/
if (c==004 && (rtp->t_flags&RAW)==0)
return;
/*
* Turn tabs to spaces as required
*/
if (c=='\t' && rtp->t_flags&XTABS) {
do
ttyoutput(' ', rtp);
while (rtp->t_col&07);
return;
}
/*
* for upper-case-only terminals,
* generate escapes.
*/
if (rtp->t_flags&LCASE) {
colp = "({)}!|^~'`";
while(*colp++)
if(c == *colp++) {
ttyoutput('\\', rtp);
c = colp[-2];
break;
}
if ('a'<=c && c<='z')
c =+ 'A' - 'a';
}
/*
* turn <nl> to <cr><lf> if desired.
*/
if (c=='\n' && rtp->t_flags&CRMOD)
ttyoutput('\r', rtp);
if (putc(c, &rtp->t_outq))
return;
/*
* Calculate delays.
* The numbers here represent clock ticks
* and are not necessarily optimal for all terminals.
* The delays are indicated by characters above 0200,
* thus (unfortunately) restricting the transmission
* path to 7 bits.
*/
colp = &rtp->t_col;
ctype = partab[c];
c = 0;
switch (ctype&077) {
/* ordinary */
case 0:
(*colp)++;
/* non-printing */
case 1:
break;
/* backspace */
case 2:
if (*colp)
(*colp)--;
break;
/* newline */
case 3:
ctype = (rtp->t_flags >> 8) & 03;
if(ctype == 1) { /* tty 37 */
if (*colp)
c = max((*colp>>4) + 3, 6);
} else
if(ctype == 2) { /* vt05 */
c = 6;
}
*colp = 0;
break;
/* tab */
case 4:
ctype = (rtp->t_flags >> 10) & 03;
if(ctype == 1) { /* tty 37 */
c = 1 - (*colp | ~07);
if(c < 5)
c = 0;
}
*colp =| 07;
(*colp)++;
break;
/* vertical motion */
case 5:
if(rtp->t_flags & VTDELAY) /* tty 37 */
c = 0177;
break;
/* carriage return */
case 6:
ctype = (rtp->t_flags >> 12) & 03;
if(ctype == 1) { /* tn 300 */
c = 5;
} else
if(ctype == 2) { /* ti 700 */
c = 10;
}
*colp = 0;
}
if(c)
putc(c|0200, &rtp->t_outq);
}
/*
* Restart typewriter output following a delay
* timeout.
* The name of the routine is passed to the timeout
* subroutine and it is called during a clock interrupt.
*/
ttrstrt(atp)
{
register struct tty *tp;
tp = atp;
tp->t_state =& ~TIMEOUT;
ttstart(tp);
}
/*
* Start output on the typewriter. It is used from the top half
* after some characters have been put on the output queue,
* from the interrupt routine to transmit the next
* character, and after a timeout has finished.
* If the SSTART bit is off for the tty the work is done here,
* using the protocol of the single-line interfaces (KL, DL, DC);
* otherwise the address word of the tty structure is
* taken to be the name of the device-dependent startup routine.
*/
ttstart(atp)
struct tty *atp;
{
register int *addr, c;
register struct tty *tp;
struct { int (*func)(); };
tp = atp;
addr = tp->t_addr;
if (tp->t_state&SSTART) {
(*addr.func)(tp);
return;
}
if ((addr->tttcsr&DONE)==0 || tp->t_state&TIMEOUT)
return;
if ((c=getc(&tp->t_outq)) >= 0) {
if (c<=0177)
addr->tttbuf = c | (partab[c]&0200);
else {
timeout(ttrstrt, tp, c&0177);
tp->t_state =| TIMEOUT;
}
}
}
/*
* Called from device's read routine after it has
* calculated the tty-structure given as argument.
* The pc is backed up for the duration of this call.
* In case of a caught interrupt, an RTI will re-execute.
*/
ttread(atp)
struct tty *atp;
{
register struct tty *tp;
tp = atp;
if ((tp->t_state&CARR_ON)==0)
return;
if (tp->t_canq.c_cc || canon(tp))
while (tp->t_canq.c_cc && passc(getc(&tp->t_canq))>=0);
}
/*
* Called from the device's write routine after it has
* calculated the tty-structure given as argument.
*/
ttwrite(atp)
struct tty *atp;
{
register struct tty *tp;
register int c;
tp = atp;
if ((tp->t_state&CARR_ON)==0)
return;
while ((c=cpass())>=0) {
spl5();
while (tp->t_outq.c_cc > TTHIWAT) {
ttstart(tp);
tp->t_state =| ASLEEP;
sleep(&tp->t_outq, TTOPRI);
}
spl0();
ttyoutput(c, tp);
}
ttstart(tp);
}
/*
* Common code for gtty and stty functions on typewriters.
* If v is non-zero then gtty is being done and information is
* passed back therein;
* if it is zero stty is being done and the input information is in the
* u_arg array.
*/
ttystty(atp, av)
int *atp, *av;
{
register *tp, *v;
tp = atp;
if(v = av) {
*v++ = tp->t_speeds;
v->lobyte = tp->t_erase;
v->hibyte = tp->t_kill;
v[1] = tp->t_flags;
return(1);
}
wflushtty(tp);
v = u.u_arg;
tp->t_speeds = *v++;
tp->t_erase = v->lobyte;
tp->t_kill = v->hibyte;
tp->t_flags = v[1];
return(0);
}
+122
View File
@@ -0,0 +1,122 @@
#
/*
*/
/*
* Screw Works interface via DC-11
*/
#include "../tty.h"
#define VSADDR 0174150
#define CDLEAD 01
#define B1200 030
#define STOP1 0400
#define CLSEND 02
#define RQSEND 01
#define MAGIC_MAP 0377
struct {
int vsrcsr;
int vsrbuf;
int vsxcsr;
int vsxbuf;
};
struct {
struct clist iq;
struct clist oq;
} vs;
vsopen(dev)
{
VSADDR->vsrcsr = IENABLE|B1200|CDLEAD;
VSADDR->vsxcsr = STOP1|IENABLE|B1200;
vschar(0);
}
vsclose(dev)
{
vschar(0);
VSADDR->vsrcsr =& ~IENABLE;
while (getc(&vs.iq) >= 0);
}
vswrite(dev)
{
register int count, c;
count = 0;
while ((c=cpass()) >= 0) {
if (--count <= 0) {
count = 60;
vschar(0);
}
vschar(c);
}
vschar(0);
}
vschar(c)
{
c =^ MAGIC_MAP;
spl5();
while (vs.oq.c_cc > 60) {
vsxintr();
sleep(&vs.oq, TTIPRI);
}
putc(c, &vs.oq);
vsxintr();
spl0();
}
vsxintr()
{
static lchar;
register c;
register int *xcsr;
xcsr = &VSADDR->vsxcsr;
if (*xcsr&DONE) {
if (lchar==MAGIC_MAP) {
*xcsr =& ~RQSEND;
lchar = 0;
if (vs.oq.c_cc==0)
goto wake;
}
if ((*xcsr&CLSEND) == 0) {
*xcsr =& ~RQSEND;
*xcsr =| RQSEND;
if ((*xcsr&CLSEND) == 0)
goto wake;
}
if ((c = getc(&vs.oq)) >= 0)
VSADDR->vsxbuf = lchar = c;
if (vs.oq.c_cc <= 15)
wake:
wakeup(&vs.oq);
}
}
vsread(dev)
{
register int c;
spl5();
while ((c = getc(&vs.iq)) < 0)
sleep(&vs.iq, TTIPRI);
spl0();
passc("?0*#?546?213?879?"[c&017]);
}
vsrintr()
{
register int c;
c = VSADDR->vsrbuf;
if (vs.iq.c_cc<=10)
putc(c, &vs.iq);
wakeup(&vs.iq);
}
+70
View File
@@ -0,0 +1,70 @@
#
/*
*/
/*
* VT01 driver via DR11C to 11/20
*/
#include "../param.h"
#include "../user.h"
int vtflag;
struct vtreg {
int csr;
int buf;
};
#define VTADDR 0167770
#define RQINT 01
#define BIENABL 040
#define SEOF 0100000
#define VTPRI 8
vtopen(dev, flag)
{
if (!flag)
u.u_error = ENXIO;
else
VTADDR->csr = BIENABL;
}
vtclose()
{
VTADDR->buf = SEOF;
VTADDR->csr =| RQINT;
}
vtwrite()
{
register int c;
int register count;
while ((c=cpass()) >= 0) {
retry:
for (count=0; count<10; count++)
if ((VTADDR->csr&RQINT)==0) {
VTADDR->buf = c&0377;
VTADDR->csr =| RQINT;
goto contin;
}
spl5();
if (VTADDR->csr&RQINT) {
vtflag++;
sleep(VTADDR, VTPRI);
}
spl0();
goto retry;
contin:;
}
}
vtintr()
{
VTADDR->csr =& ~RQINT;
if (vtflag) {
vtflag = 0;
wakeup(VTADDR);
}
}