SysIII/usr/src/uts/vax/io/dz.c
/*
* DZ11 driver
*/
#include "sys/param.h"
#include "sys/dir.h"
#include "sys/user.h"
#include "sys/file.h"
#include "sys/tty.h"
#include "sys/conf.h"
#include "sys/sysinfo.h"
struct device *dz_addr[];
int dz_cnt;
struct tty dz_tty[];
short dz_scan;
char dz_brk[8]; /* break bits - max 64 lines */
char dz_speeds[16] = {
0, 00, 01, 02, 03, 04, 0, 05,
06, 07, 010, 012, 014, 016, 0, 0
};
#define BITS6 010
#define BITS7 020
#define TWOSB 040
#define PENABLE 0100
#define OPAR 0200
#define RCVENB 010000
#define IE 040140
struct device {
short dzcsr, dzrbuf;
char dztcr, dzdtr;
char dztbuf, dzbrk;
};
#define dzlpr dzrbuf
#define dzmsr dzbrk
#define ON 1
#define OFF 0
dzopen(dev, flag)
{
register struct tty *tp;
extern dzproc(), dzscan();
if (dev >= dz_cnt) {
u.u_error = ENXIO;
return;
}
tp = &dz_tty[dev];
if ((tp->t_state&(ISOPEN|WOPEN)) == 0) {
ttinit(tp);
tp->t_proc = dzproc;
dzparam(dev);
}
spl5();
if (tp->t_cflag&CLOCAL || dzmodem(dev, ON))
tp->t_state |= CARR_ON;
else
tp->t_state &= ~CARR_ON;
if (!(flag&FNDELAY))
while ((tp->t_state&CARR_ON)==0) {
tp->t_state |= WOPEN;
sleep((caddr_t)&tp->t_canq, TTIPRI);
}
(*linesw[tp->t_line].l_open)(tp);
spl0();
}
dzclose(dev)
{
register struct tty *tp;
tp = &dz_tty[dev];
(*linesw[tp->t_line].l_close)(tp);
if (tp->t_cflag&HUPCL)
dzmodem(dev, OFF);
}
dzread(dev)
{
register struct tty *tp;
tp = &dz_tty[dev];
(*linesw[tp->t_line].l_read)(tp);
}
dzwrite(dev)
{
register struct tty *tp;
tp = &dz_tty[dev];
(*linesw[tp->t_line].l_write)(tp);
}
dzioctl(dev, cmd, arg, mode)
register dev;
{
switch(cmd) {
default:
if (ttiocom(&dz_tty[dev], cmd, arg, mode))
dzparam(dev);
}
}
dzparam(dev)
{
register struct tty *tp;
register flags, lpr;
register struct device *dzaddr;
tp = &dz_tty[dev];
dzaddr= dz_addr[dev>>3];
dzaddr->dzcsr = IE;
if (dz_scan==0) {
dzscan();
dz_scan++;
}
flags = tp->t_cflag;
if ((flags&CBAUD) == 0) {
/* hang up line */
dzmodem(dev, OFF);
return;
}
lpr = (dz_speeds[flags&CBAUD]<<8)|(dev&07);
if (flags&CREAD)
lpr |= RCVENB;
if (flags&CS6)
lpr |= BITS6;
if (flags&CS7)
lpr |= BITS7;
if (flags&PARENB) {
lpr |= PENABLE;
if (flags&PARODD)
lpr |= OPAR;
}
if (flags&CSTOPB)
lpr |= TWOSB;
dzaddr->dzlpr = lpr;
}
dzrint(dev)
{
register struct tty *tp;
register c;
register line;
register struct device *dzaddr;
sysinfo.rcvint++;
dzaddr = dz_addr[dev];
while ((c = dzaddr->dzrbuf) < 0) { /* char. present */
line = (c>>8)&07;
tp = &dz_tty[line|(dev<<3)];
if (tp >= &dz_tty[dz_cnt])
continue;
if (!(tp->t_state&(ISOPEN|WOPEN)))
continue;
if (tp->t_cflag&CLOCAL || dzaddr->dzmsr&(1<<line)) {
if ((tp->t_state&CARR_ON) == 0) {
wakeup(&tp->t_canq);
tp->t_state |= CARR_ON;
}
} else {
if (tp->t_state&CARR_ON) {
signal(tp->t_pgrp, SIGHUP);
dzaddr->dzdtr &= ~(1<<line);
tp->t_state &= ~CARR_ON;
ttyflush(tp, (FREAD|FWRITE));
}
continue;
}
(*linesw[tp->t_line].l_input)(tp, c, 0);
}
}
dzxint(dev)
{
register struct tty *tp;
register struct device *dzaddr;
register unit;
sysinfo.xmtint++;
dzaddr = dz_addr[dev];
while(dzaddr->dzcsr<0) { /* TX rdy */
unit = (dzaddr->dzcsr >> 8) & 07;
tp = &dz_tty[(dev<<3)|unit];
if (tp->t_state & TTXON) {
dzaddr->dztbuf = CSTART;
tp->t_state &= ~TTXON;
continue;
}
if (tp->t_state & TTXOFF) {
dzaddr->dztbuf = CSTOP;
tp->t_state &= ~TTXOFF;
continue;
}
if (tp->t_state & BUSY) {
dzaddr->dztbuf = (char)tp->t_buf;
tp->t_state &= ~BUSY;
dzproc(tp, T_OUTPUT);
continue;
}
dzaddr->dztcr &= ~(1<<unit);
}
}
dzproc(tp, cmd)
register struct tty *tp;
{
register unit, c;
struct device *dzaddr;
int dev;
extern ttrstrt();
unit = tp - dz_tty;
dev = unit>>3;
dzaddr = dz_addr[dev];
unit = 1<<(unit&07);
switch(cmd) {
case T_TIME:
tp->t_state &= ~TIMEOUT;
dz_brk[dev] &= ~unit;
dzaddr->dzbrk = dz_brk[dev];
goto start;
case T_WFLUSH:
case T_RESUME:
tp->t_state &= ~TTSTOP;
goto start;
case T_OUTPUT:
start:
if (tp->t_state&(TIMEOUT|TTSTOP|BUSY))
break;
if (tp->t_state&TTIOW && tp->t_outq.c_cc==0) {
tp->t_state &= ~TTIOW;
wakeup((caddr_t)&tp->t_oflag);
}
while ((c=getc(&tp->t_outq)) >= 0) {
if (tp->t_oflag&OPOST && c == 0200) {
if ((c = getc(&tp->t_outq)) < 0)
break;
if (c > 0200) {
tp->t_state |= TIMEOUT;
timeout(ttrstrt, tp, (c&0177)+6);
break;
}
}
*((char *)&tp->t_buf) = c;
tp->t_state |= BUSY;
dzaddr->dztcr |= unit;
break;
}
if (tp->t_state&OASLP && tp->t_outq.c_cc<=ttlowat[tp->t_cflag&CBAUD]) {
tp->t_state &= ~OASLP;
wakeup((caddr_t)&tp->t_outq);
}
break;
case T_SUSPEND:
tp->t_state |= TTSTOP;
break;
case T_BLOCK:
tp->t_state &= ~TTXON;
tp->t_state |= TTXOFF|TBLOCK;
dzaddr->dztcr |= unit;
break;
case T_RFLUSH:
if (!(tp->t_state&TBLOCK))
break;
case T_UNBLOCK:
tp->t_state &= ~(TTXOFF|TBLOCK);
tp->t_state |= TTXON;
dzaddr->dztcr |= unit;
break;
case T_BREAK:
dz_brk[dev] |= unit;
dzaddr->dzbrk = dz_brk[dev];
tp->t_state |= TIMEOUT;
timeout(ttrstrt, tp, HZ/4);
break;
}
}
dzmodem(dev, flag)
{
register struct device *dzaddr;
register bit;
dzaddr = dz_addr[dev>>3];
bit = 1<<(dev&07);
if (flag==OFF)
dzaddr->dzdtr &= ~bit;
else
dzaddr->dzdtr |= bit;
return(dzaddr->dzmsr & bit);
}
dzscan()
{
register i;
register struct device *dzaddr;
register struct tty *tp;
char bit;
for (i=0; i<dz_cnt; i++) {
tp = &dz_tty[i];
if (!(tp->t_state&(ISOPEN|WOPEN)))
continue;
dzaddr = dz_addr[i>>3];
bit = 1<<(i&07);
if (tp->t_cflag&CLOCAL || dzaddr->dzmsr&bit) {
if ((tp->t_state&CARR_ON)==0) {
wakeup(&tp->t_canq);
tp->t_state |= CARR_ON;
}
} else {
if (tp->t_state&CARR_ON) {
if (tp->t_state&ISOPEN) {
signal(tp->t_pgrp, SIGHUP);
dzaddr->dzdtr &= ~bit;
ttyflush(tp, (FREAD|FWRITE));
}
tp->t_state &= ~CARR_ON;
}
}
}
timeout(dzscan, 0, 120);
}
dzclr()
{
register dev;
register struct tty *tp;
for (dev = 0; dev < dz_cnt; dev++) {
tp = &dz_tty[dev];
if ((tp->t_state&(ISOPEN|WOPEN)) == 0)
continue;
dzparam(dev);
dzmodem(dev, ON);
tp->t_state &= ~BUSY;
dzproc(tp, T_OUTPUT);
}
}