USG_PG3/usr/source/io1/dc.c
#
/*
*/
/*
* DC-11 driver
*/
#include "../head/param.h"
#include "../head/conf.h"
#include "../head/user.h"
#include "../head/userx.h"
#include "../head/tty.h"
/*
* Base address of DC-11's. Minor device i is at
* DCADDR + 10*i.
*/
#define DCADDR 0174000 /* Std is 174000 */
#define DCTYPE 02
/*
* Number of DC's for which table space is allocated.
*/
#define NDC11 1
/*
* Control bits in device registers
*/
#define IENABLE 0100 /* interrupt enable */
#define DTR 01 /* data terminal ready */
#define DCRQS 01 /* request to send */
#define DCST 0400 /* secondary transmit */
#define PARITY 040
#define DCOVRN 010000 /* data overrun */
#define MTRANS 040000 /* modem transition */
int ndc11 NDC11;
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.
*/
dcopen(dev, flag)
{
register struct tty *tp;
register *addr;
if (dev.d_minor >= NDC11) {
u.u_error = ENXIO;
return;
}
tp = &dc11[dev.d_minor];
tp->t_addr = addr = DCADDR + dev.d_minor*8;
tp->t_dev = dev;
tp->t_dtype = DCTYPE;
if (flag) {
addr->dcrcsr =| IENABLE;
(*linesw[tp->t_discp].l_open)(dev, tp);
}
}
/*
* Close a dc11
*/
dcclose(dev, flag)
{
register struct tty *tp;
tp = &dc11[dev.d_minor];
(*linesw[tp->t_discp].l_close)(dev, tp);
}
dcparam(dev, atp)
struct tty *atp;
{
register struct tty *tp;
register r;
tp = atp;
if (r = dcrstab[tp->t_speeds.lobyte&017])
tp->t_addr->dcrcsr = r;
if (r = dctstab[tp->t_speeds.hibyte&017])
tp->t_addr->dctcsr = r;
}
/*
* Modem control for DC 11.
*/
dcmctl(dev, action)
{
register struct tty *tp;
register int sps, *addr;
int tcsr, status;
tp = &dc11[dev.d_minor];
addr = tp->t_addr;
status = 0;
sps = PS->integ;
spl5();
switch(action&03) {
case FSTATUS:
tcsr = addr->dctcsr;
status = (addr->dcrcsr&CARRIER)|(tcsr&CTS)|((tcsr>>15)&SR);
break;
case DISABLE:
case HUP:
addr->dcrcsr =& ~DTR;
break;
case TURNON:
/*
* Set data terminal ready. Also set primary and secondary
* carrier status according to bits 2 and 3 of "action"
*/
addr->dcrcsr =| DTR;
if(action&ST)
addr->dcrcsr =| DCST;
else
addr->dcrcsr =& ~DCST;
if(action&RQS)
addr->dctcsr =| DCRQS;
else
addr->dctcsr =& ~DCRQS;
}
PS->integ = sps;
return(status);
}
/*
* Read a DC11
*/
dcread(dev)
{
register struct tty *tp;
tp = &dc11[dev.d_minor];
(*linesw[tp->t_discp].l_read)(tp);
}
/*
* Write a DC11
*/
dcwrite(dev)
{
register struct tty *tp;
tp = &dc11[dev.d_minor];
(*linesw[tp->t_discp].l_write)(tp);
}
/*
* DC11 transmitter interrupt.
*/
dcxint(dev)
{
register struct tty *tp;
ttstart(tp = &dc11[dev.d_minor]);
}
/*
* DC11 receiver interrupt.
*/
dcrint(dev)
{
register struct tty *tp;
register int c, rcsr;
int tcsr;
int status, action;
tp = &dc11[dev.d_minor];
rcsr = tp->t_addr->dcrcsr;
if(rcsr&MTRANS) {
/*
* Only primary carrier transitions cause interrupts
*/
tcsr = tp->t_addr->dctcsr;
status = (rcsr&CARRIER)|(tcsr&CTS)|((tcsr>>15)&SR);
action = (*linesw[tp->t_discp].l_mt)(tp, status);
if (action > 0)
dcmctl(dev, action);
if ((rcsr = tp->t_addr->dcrcsr)&DONE == 0)
return;
}
c = tp->t_addr->dcrbuf;
if(rcsr&DCOVRN)
c =| OVERRUN;
else {
rcsr =& PARITY;
if (tp->t_flags&RAW == 0)
if(rcsr && (tp->t_flags&ODDP)==0 ||
!rcsr && (tp->t_flags&EVENP)==0)
c =| PERROR;
}
(*linesw[tp->t_discp].l_rcvd)(c, tp);
}
/*
* DC11 stty/gtty.
* Perform general functions and set speeds.
*/
dcsgtty(dev, flag)
{
register struct tty *tp;
tp = &dc11[dev.d_minor];
ttioctl(dev, tp, flag);
}