2.11BSD/sys/OTHERS/de11/de.c
#include "de.h"
#if NDE > 0
#include "param.h"
#include <sys/conf.h>
#include <sys/dir.h>
#include <sys/user.h>
#include <sys/tty.h>
#include <sys/systm.h>
#include <sys/dereg.h>
#define FREAD 01
#define FWRITE 02
struct tty de11[NDE];
extern struct dedevice *DEADDR;
extern char partab[];
int destart();
int ttrstrt();
/*
* DLV11E speed and control bit table.
* 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.
*/
short derstab[] = {
0, /* 0 baud */
0x0000 | DE_PBREN, /* 50 baud */
0x1000 | DE_PBREN, /* 75 baud */
0x2000 | DE_PBREN, /* 110 baud */
0x3000 | DE_PBREN, /* 134.5 baud */
0x4000 | DE_PBREN, /* 150 baud */
0x0000, /* 200 baud-Not Available */
0x5000 | DE_PBREN, /* 300 baud */
0x6000 | DE_PBREN, /* 600 baud */
0x7000 | DE_PBREN, /* 1200 baud */
0x8000 | DE_PBREN, /* 1800 baud */
0xA000 | DE_PBREN, /* 2400 baud */
0xC000 | DE_PBREN, /* 4800 baud */
0xE000 | DE_PBREN, /* 9600 baud */
0xF000 | DE_PBREN, /* 19200 baud */
0 /* X1 */
};
/*
* Open a DLV11E, waiting until carrier is established.
* Default initial conditions are set up on the first open.
* T_state's CARR_ON bit is a copy of the hardware
* DE_CAR bit, and is only used to regularize
* carrier tests in general tty routines.
*/
/*ARGSUSED*/
deopen(dev, flag)
register dev_t dev;
{
register struct tty *tp;
register struct dedevice *deaddr;
extern klstart();
int s;
if (minor(dev) >= NDE) {
u.u_error = ENXIO;
return;
}
tp = &de11[minor(dev)];
deaddr = DEADDR + minor(dev);
if (tp->t_state & XCLUDE && u.u_uid != 0) {
u.u_error = EBUSY;
return;
}
tp->t_addr = (caddr_t)deaddr; /* Needed for klstart */
if ((tp->t_state & (ISOPEN | WOPEN)) == 0) {
/* Is dev already or being open(ed) ? */
tp->t_iproc = NULL;
tp->t_oproc = destart;
ttychars(tp); /* Sets default cntrl chars */
tp->t_ispeed = B1200;
tp->t_ospeed = B1200;
tp->t_flags = ODDP | EVENP | ECHO;
tp->t_line = DFLT_LDISC;
deaddr->detcsr = derstab[B1200];
}
#ifdef NODEMODEM
if(dev & NODEMODEM) tp->t_state |= CARR_ON;
else
#endif NODEMODEM
{
s = spl5();
tp->t_state |= WOPEN;
deaddr->dercsr |= DE_DSIE | DE_DTR; /* Enable int. for carrier det. */
if (deaddr->dercsr & DE_CAR) /* Copy the sofware state */
tp->t_state |= CARR_ON; /* if carr. det already on */
splx(s);
}
while ((tp->t_state & CARR_ON) == 0) {
/*
If not on, wait for carrier-interrupt
*/
sleep((caddr_t)&tp->t_rawq, TTIPRI);
}
deaddr->dercsr |= DE_RIE;
deaddr->detcsr |= DE_TIE;
ttyopen(dev, tp);
}
/*
* Close a DE11
*/
declose(dev)
dev_t dev;
{
register struct tty *tp;
int s;
tp = &de11[minor(dev)];
/*
We can shut it down completely if
was exclusive open
*/
if(tp->t_state & XCLUDE && u.u_uid != 0) {
s = spl5();
((struct dedevice *) (tp->t_addr))->dercsr = DE_DTR;
((struct dedevice *) (tp->t_addr))->detcsr = 0;
splx(s);
}
if (tp->t_state & HUPCLS) {
((struct dedevice *) (tp->t_addr))->dercsr &= ~DE_DTR;
}
ttyclose(tp);
}
/*
* Read a DE11
*/
deread(dev)
dev_t dev;
{
register struct tty *tp;
tp = &de11[minor(dev)];
(*linesw[tp->t_line].l_read)(tp);
}
/*
* Write a DE11
*/
dewrite(dev)
dev_t dev;
{
register struct tty *tp;
tp = &de11[minor(dev)];
(*linesw[tp->t_line].l_write)(tp);
}
/*
* DE11 transmitter interrupt.
*/
dexint(dev)
dev_t dev;
{
register struct tty *tp;
register struct clist *cp;
tp = &de11[minor(dev)];
ttstart(tp);
if (tp->t_state & ASLEEP && tp->t_outq.c_cc <= TTLOWAT(tp)) {
tp->t_state &= ~ASLEEP;
#ifdef MPX_FILS
/* to be added later */
HELP
#endif MPX_FILS
wakeup((caddr_t) &tp->t_outq);
}
}
/*
* DE11 receiver interrupt.
*/
derint(dev)
dev_t dev;
{
register struct tty *tp;
register int c, csr;
tp = &de11[minor(dev)];
c = ((struct dedevice *) (tp->t_addr))->derbuf;
/*
* 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 dedevice *)(tp->t_addr))->dercsr) & DE_CAR) == 0)
#ifdef NODEMODEM
&& ( (tp->t_dev & NODEMODEM) == 0) /* Skip it if NODEMODEM here */
#endif NODEMODEM
)
{
if ((tp->t_state & WOPEN) == 0) {
((struct dedevice *) (tp->t_addr))->dercsr &= ~DE_DTR;
if (tp->t_state & CARR_ON)
gsignal(tp->t_pgrp, SIGHUP);
flushtty(tp, FREAD|FWRITE);
}
tp->t_state &= ~CARR_ON;
return;
}
if ((tp->t_state & ISOPEN) == 0) {
if ((tp->t_state & WOPEN) && (csr & DE_CAR))
tp->t_state |= CARR_ON;
wakeup((caddr_t) tp); /* Turn on software carr. if */
/* back in deopen wait loop */
return;
}
/* Parity check to be fixed
* csr &= ((struct dedevice *)(tp->t_addr))->derbuf & 0400;
* if ((csr && ((tp->t_flags & (EVENP | ODDP)) == ODDP)) ||
* (!csr && ((tp->t_flags & (EVENP | ODDP)) == EVENP)))
*/
(*linesw[tp->t_line].l_input)(c, tp);
}
/*
* DE11 stty/gtty.
* Perform general functions and set speeds.
*/
deioctl(dev, cmd, addr, flag)
dev_t dev;
caddr_t addr;
int cmd, flag;
{
register struct tty *tp;
register r;
tp = &de11[minor(dev)];
switch (ttioctl(tp, cmd, addr, flag)) {
case TIOCSETP:
case TIOCSETN:
r = derstab[tp->t_ispeed];
if(tp->t_ispeed){ /* Hang up line */
((struct dedevice *) (tp->t_addr))->detcsr = r;
((struct dedevice *) (tp->t_addr))->dercsr |= DE_RIE;
((struct dedevice *) (tp->t_addr))->detcsr |= DE_TIE;
}
else
((struct dedevice *) (tp->t_addr))->dercsr &= ~DE_DTR;
break;
#ifdef DE_IOCTL
case TIOCSBRK:
((struct dedevice *) (tp->t_addr))->detcsr |= DE_BRK;
break;
case TIOCCBRK:
((struct dedevice *) (tp->t_addr))->detcsr &= ~DE_BRK;
break;
case TIOCSDTR:
((struct dedevice *) (tp->t_addr))->dercsr &= DE_DTR;
break;
case TIOCCDTR:
((struct dedevice *) (tp->t_addr))->dercsr &= ~DE_DTR;
break;
#endif DE_IOCTL
default:
u.u_error = ENOTTY;
case 0:
break;
}
}
destart(tp)
register struct tty *tp;
{
register c;
register struct dedevice *addr;
addr = (struct dedevice *) tp->t_addr;
if ((addr->detcsr & DETCSR_RDY) == 0)
return;
if ((c=getc(&tp->t_outq)) >= 0) {
if (tp->t_flags & RAW)
addr->detbuf = c;
else if (c<=0177)
addr->detbuf = c
/* dlf terminal parity mod */
#ifdef OUT_PAR
| (partab[c] & 0200)
#endif
;
/* end of dlf termnal parity mod */
else {
timeout(ttrstrt, (caddr_t)tp, (c & 0177) + DEDELAY);
tp->t_state |= TIMEOUT;
}
}
}
#endif NDE