SysIII/usr/src/uts/vax/io/cons.c
/*
* Console/LSI interface
*/
#include "sys/param.h"
#include "sys/dir.h"
#include "sys/user.h"
#include "sys/tty.h"
#include "sys/buf.h"
#include "sys/systm.h"
#include "sys/cons.h"
#include "sys/conf.h"
#include "sys/sysinfo.h"
#include "sys/mtpr.h"
struct tty con_tty;
struct floppy {
struct buf * f_buf;
unsigned char * f_ptr;
short f_cnt;
short f_sec;
short f_trk;
char f_state;
char f_errcnt;
} con_flp;
int conproc();
int ttrstrt();
char partab[];
#define CONSOLE 0
#define FLOPPY 1
#define FSIDLE 1
#define FSRWC 3
#define FSSEC 4
#define FSTRK 5
#define FSRDATA 6
#define FSXDATA 7
#define FSDONE 8
#define FSABORT 10
conopen(dev, flag)
dev_t dev;
{
if (dev == CONSOLE) {
register struct tty *tp;
tp = &con_tty;
tp->t_proc = conproc;
if ((tp->t_state&ISOPEN) == 0) {
ttinit(tp);
tp->t_state = ISOPEN|CARR_ON;
tp->t_iflag |= ICRNL;
tp->t_oflag |= OPOST|ONLCR|TAB3;
tp->t_lflag |= ISIG|ICANON|ECHO|ECHOK;
mtpr(RXCS, C_IE);
mtpr(TXCS, C_IE);
}
(*linesw[tp->t_line].l_open)(tp);
} else if (dev == FLOPPY) {
register struct floppy *fp;
fp = &con_flp;
if (fp->f_state)
u.u_error = ENXIO;
else {
fp->f_state = FSIDLE;
fp->f_buf = geteblk();
fp->f_buf->b_flags = 0;
}
} else
u.u_error = ENXIO;
}
conclose(dev)
dev_t dev;
{
if (dev == CONSOLE) {
register struct tty *tp;
tp = &con_tty;
(*linesw[tp->t_line].l_close)(tp);
tp->t_state = 0;
} else if (dev == FLOPPY) {
brelse(con_flp.f_buf);
con_flp.f_state = 0;
}
}
conread(dev)
dev_t dev;
{
if (dev == CONSOLE) {
ttread(&con_tty);
} else if (dev == FLOPPY) {
confpio(B_READ);
}
}
conwrite(dev)
dev_t dev;
{
if (dev == CONSOLE) {
ttwrite(&con_tty);
} else if (dev == FLOPPY) {
confpio(B_WRITE);
}
}
conxint(dev)
{
register struct tty *tp;
sysinfo.xmtint++;
tp = &con_tty;
if (mfpr(TXCS) & C_DONE) {
tp->t_state &= ~BUSY;
conproc(tp, T_OUTPUT);
}
}
conrint(dev)
{
register struct tty *tp;
register c;
sysinfo.rcvint++;
tp = &con_tty;
while (mfpr(RXCS) & C_DONE) {
c = mfpr(RXDB);
if ((c & C_CID) == 0)
(*linesw[tp->t_line].l_input)(tp, c, 0);
else
confrcv(c);
}
}
conioctl(dev, cmd, arg, mode)
{
if (dev == CONSOLE)
ttiocom(&con_tty, cmd, arg, mode);
}
conproc(tp, cmd)
register struct tty *tp;
{
register c;
switch (cmd) {
case T_TIME:
tp->t_state &= ~TIMEOUT;
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, (caddr_t)tp, (c&0177));
break;
}
}
tp->t_state |= BUSY;
/* parity ? */
mtpr(TXDB, c & C_DATA);
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);
}
if ((tp->t_state&BUSY) == 0 && con_flp.f_state > FSIDLE)
confxmt();
break;
case T_SUSPEND:
tp->t_state |= TTSTOP;
break;
case T_BLOCK:
tp->t_state |= TBLOCK;
break;
case T_RFLUSH:
case T_UNBLOCK:
tp->t_state &= ~TBLOCK;
break;
}
}
putchar(c)
register c;
{
register s;
while((mfpr(TXCS) & C_DONE) == 0)
;
if(c == 0)
return;
s = mfpr(TXCS);
mtpr(TXCS,0);
mtpr(TXDB, c & C_DATA);
if(c == '\n') {
putchar('\r');
}
putchar(0);
mtpr(TXCS, s);
}
confpio(rw)
{
register struct floppy *fp = &con_flp;
register struct buf *bp;
register cnt;
bp = fp->f_buf;
spl4();
while (bp->b_flags&B_BUSY)
sleep((caddr_t)&con_flp, PRIBIO);
bp->b_flags = B_BUSY;
spl0();
while (u.u_count) {
bp->b_blkno = u.u_offset/FSIZE;
if (bp->b_blkno >= (FTRK-1)*FSEC || u.u_offset%FSIZE) {
u.u_error = ENXIO;
break;
}
cnt = min(FSIZE, u.u_count);
if (rw == B_WRITE) {
iomove(bp->b_un.b_addr, cnt, B_WRITE);
if (u.u_error)
break;
}
fp->f_errcnt = 0;
bp->b_flags |= rw;
bp->b_flags &= ~B_DONE;
{
register sec,trk;
trk = bp->b_blkno/FSEC;
sec = bp->b_blkno%FSEC;
sec = (sec*2 + (sec>=13) + trk*6)%26;
fp->f_trk = F_DATA | (trk + 1);
fp->f_sec = F_DATA | (sec + 1);
}
spl4();
fp->f_state = FSRWC;
conproc(&con_tty, T_OUTPUT);
while ((bp->b_flags&B_DONE) == 0)
sleep((caddr_t)bp, PRIBIO);
spl0();
if (bp->b_flags&B_ERROR) {
u.u_error = EIO;
break;
}
if (rw == B_READ) {
iomove(bp->b_un.b_addr, cnt, B_READ);
if (u.u_error)
break;
}
}
bp->b_flags = 0;
wakeup((caddr_t)&con_flp);
}
confxmt()
{
register struct floppy *fp = &con_flp;
register struct buf *bp;
bp = fp->f_buf;
switch(fp->f_state) {
case FSRWC:
fp->f_cnt = FSIZE;
fp->f_ptr = (unsigned char *)bp->b_un.b_addr;
mtpr(TXDB, bp->b_flags&B_READ?F_READ:F_WRITE);
fp->f_state = FSSEC;
break;
case FSSEC:
mtpr(TXDB, fp->f_sec);
fp->f_state = FSTRK;
break;
case FSTRK:
mtpr(TXDB, fp->f_trk);
fp->f_state = bp->b_flags&B_READ?FSDONE:FSXDATA;
break;
case FSXDATA:
mtpr(TXDB, F_DATA|(int)*fp->f_ptr++);
if (--fp->f_cnt == 0)
fp->f_state = FSDONE;
break;
case FSABORT:
mtpr(TXDB, F_CAN);
if (++fp->f_errcnt <= 8) {
fp->f_state = FSRWC;
} else {
bp->b_flags |= B_ERROR|B_DONE;
fp->f_state = FSIDLE;
wakeup(bp);
}
break;
default:
return;
}
con_tty.t_state |= BUSY;
}
confrcv(c)
register c;
{
register struct floppy *fp = &con_flp;
register struct buf *bp;
bp = fp->f_buf;
switch (c & C_CID) {
case F_DATA:
if (fp->f_state != FSRDATA) {
fp->f_state = FSABORT;
break;
}
*fp->f_ptr++ = c & C_DATA;
if (--fp->f_cnt == 0) {
fp->f_state = FSIDLE;
bp->b_flags |= B_DONE;
wakeup(bp);
}
break;
case F_FFC:
if (fp->f_state != FSDONE || (c & C_DATA)) {
fp->f_state = FSABORT;
break;
}
if (bp->b_flags&B_READ) {
fp->f_state = FSRDATA;
} else {
fp->f_state = FSIDLE;
bp->b_flags |= B_DONE;
wakeup(bp);
}
break;
case F_FLP:
fp->f_state = FSABORT;
break;
}
if (fp->f_state == FSABORT)
conproc(&con_tty, T_OUTPUT);
}
conclr()
{
register struct tty *tp;
tp = &con_tty;
if((tp->t_state&ISOPEN) == 0)
return;
mtpr(RXCS, C_IE);
mtpr(TXCS, C_IE);
tp->t_state &= ~BUSY;
conproc(tp, T_OUTPUT);
}