V7/usr/sys/dev/dc.c
#include "../h/param.h"
#include "../h/conf.h"
#include "../h/dir.h"
#include "../h/user.h"
#include "../h/tty.h"
#include "../h/systm.h"
/*
* Base address of DC-11's. Minor device i is at
* DCADDR + 10*i.
*/
#define DCADDR (struct device *)0174000
/*
* Number of DC's for which table space is allocated.
*/
#define NDC11 4
/*
* 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 device {
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)
dev_t dev;
{
register struct tty *tp;
register struct device *addr;
extern int klstart();
int s;
if (minor(dev) >= NDC11) {
u.u_error = ENXIO;
return;
}
tp = &dc11[minor(dev)];
addr = DCADDR + minor(dev);
tp->t_addr = (caddr_t)addr;
tp->t_state |= WOPEN;
s = spl5();
addr->dcrcsr |= IENABLE|CDLEAD;
if ((tp->t_state&ISOPEN) == 0) {
tp->t_erase = CERASE;
tp->t_kill = CKILL;
addr->dcrcsr = IENABLE|CDLEAD|SPEED1;
addr->dctcsr = IENABLE|SPEED1|STOP1|RQSEND;
tp->t_state = ISOPEN | WOPEN;
tp->t_flags = ODDP|EVENP|ECHO;
tp->t_oproc = klstart;
}
if (addr->dcrcsr & CARRIER)
tp->t_state |= CARR_ON;
splx(s);
while ((tp->t_state & CARR_ON) == 0)
sleep((caddr_t)&tp->t_rawq, TTIPRI);
ttyopen(dev, tp);
}
/*
* Close a dc11
*/
dcclose(dev)
dev_t dev;
{
register struct tty *tp;
tp = &dc11[minor(dev)];
if (tp->t_state&HUPCLS)
((struct device *)(tp->t_addr))->dcrcsr &= ~CDLEAD;
ttyclose(tp);
}
/*
* Read a DC11
*/
dcread(dev)
dev_t dev;
{
ttread(&dc11[minor(dev)]);
}
/*
* Write a DC11
*/
dcwrite(dev)
dev_t dev;
{
ttwrite(&dc11[minor(dev)]);
}
/*
* DC11 transmitter interrupt.
*/
dcxint(dev)
dev_t dev;
{
register struct tty *tp;
tp = &dc11[minor(dev)];
ttstart(tp);
if (tp->t_outq.c_cc == 0 || tp->t_outq.c_cc == TTLOWAT)
wakeup((caddr_t)&tp->t_outq);
}
/*
* DC11 receiver interrupt.
*/
dcrint(dev)
dev_t dev;
{
register struct tty *tp;
register int c, csr;
tp = &dc11[minor(dev)];
c = ((struct device *)(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 = ((struct device *)(tp->t_addr))->dcrcsr) & CARRIER) == 0) {
if ((tp->t_state&WOPEN) == 0) {
((struct device *)(tp->t_addr))->dcrcsr &= ~CDLEAD;
if (tp->t_state & CARR_ON)
signal(tp->t_pgrp, 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((caddr_t)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.
*/
dcioctl(dev, cmd, addr, flag)
dev_t dev;
caddr_t addr;
{
register struct tty *tp;
register r;
tp = &dc11[minor(dev)];
if (ttioccom(cmd, &dc11[minor(dev)], addr, dev) == 0) {
u.u_error = ENOTTY;
return;
}
if (cmd == TIOCSETP) {
r = dcrstab[tp->t_ispeed];
if (r)
((struct device *)(tp->t_addr))->dcrcsr = r;
else
((struct device *)(tp->t_addr))->dcrcsr &= ~CDLEAD;
r = dctstab[tp->t_ospeed];
((struct device *)(tp->t_addr))->dctcsr = r;
}
}