/* This file is in the public domain. */ /* driver for the console slu at 1777746x, vectors 60 (rx) and 64 (tx) */ #include #include #include #include #include #include #include "driver.h" #include "cons__.h" #define TICKS_PER_WRITE 20 #define CONS_ODT_CHAR 0x10 /* ^P - breaks back to ODT */ static char cons_in_char; static char cons_out_char; static word cons_in_stat; static word cons_out_stat; #define CONS_IE 0x40 #define CONS_READY 0x80 #define CONS_MUTABLE (CONS_IE) static int state; #define DIDINT_IN 0x00000001 #define DIDINT_OUT 0x00000002 #define PRINTING 0x00000004 static int printtime; static int sigio; static struct termios old_tty; static struct termios new_tty; extern DRIVER cons_driver; #define WANTINT(statword) (((statword) & (CONS_IE|CONS_READY)) == (CONS_IE|CONS_READY)) static void chkint(void) { if (WANTINT(cons_in_stat) && !(state & DIDINT_IN)) { interrupt(&cons_driver,060,BR4); state |= DIDINT_IN; } if (WANTINT(cons_out_stat) && !(state & DIDINT_OUT)) { interrupt(&cons_driver,064,BR4); state |= DIDINT_OUT; } } static void cons_tick(DRIVER *); /* forward */ static void getticks(void) { cons_driver.tick = cons_tick; } static void startprinting(void) { write(1,&cons_out_char,1); state |= PRINTING; printtime = TICKS_PER_WRITE; getticks(); cons_out_stat |= CONS_READY; chkint(); } static void cons_tick(UNUSED(DRIVER *d)) { int mask; cons_driver.tick = 0; if (printtime > 0) { if (halted) printtime = 0; else printtime --; if (printtime <= 0) { if (! (cons_out_stat & CONS_READY)) { startprinting(); } else { state &= ~PRINTING; } } else { getticks(); } } if (sigio) { char ch; mask = sigblock(sigmask(SIGIO)); if (read(0,&ch,1) == 1) { do { if (ch == CONS_ODT_CHAR) halted = 1; } while (read(0,&ch,1) == 1); cons_in_char = ch; cons_in_stat |= CONS_READY; chkint(); } sigio = 0; sigsetmask(mask); } } static void cons__sigio(UNUSED(int sig)) { sigio ++; getticks(); } static void cons__sigint(UNUSED(int sig)) { halted = 1; } static void cons_init(UNUSED(DRIVER *d), char *iomask) { int on; struct termios tio; iomask[IOMASK(0777560)] = 1; /* keyboard status */ iomask[IOMASK(0777562)] = 1; /* keyboard data */ iomask[IOMASK(0777564)] = 1; /* printer status */ iomask[IOMASK(0777566)] = 1; /* printer data */ cons_in_stat = 0; cons_out_stat = CONS_READY; state = 0; signal(SIGINT,cons__sigint); signal(SIGIO,cons__sigio); tcgetattr(0,&tio); old_tty = tio; cfmakeraw(&tio); tio.c_cc[VMIN] = 1; tio.c_cc[VTIME] = 0; new_tty = tio; tcsetattr(0,TCSADRAIN,&tio); on = 1; ioctl(0,FIONBIO,&on); ioctl(0,FIOASYNC,&on); fcntl(0,F_SETOWN,getpid()); } static void cons_printchar(char c) { state &= ~DIDINT_OUT; cons_out_char = c; cons_out_stat &= ~CONS_READY; if (! (state & PRINTING)) startprinting(); } static int cons_io(UNUSED(DRIVER *d), int loc, int op, int data, UNUSED(void (*fxn)(void *))) { int rv; rv = 0; switch (loc) { case IOMASK(0777560): /* keyboard status */ rv = reg_access(loc,&cons_in_stat,op,~CONS_MUTABLE,data); chkint(); break; case IOMASK(0777562): /* keyboard data */ if ((op & IO_OP) == IO_R) { cons_in_stat &= ~CONS_READY; state &= ~DIDINT_IN; rv = cons_in_char; } break; case IOMASK(0777564): /* printer status */ rv = reg_access(loc,&cons_out_stat,op,~CONS_MUTABLE,data); chkint(); break; case IOMASK(0777566): /* printer data */ switch (op & IO_OP) { case IO_W: cons_printchar(data); break; } break; } return(rv); } static void cons_busreset(UNUSED(DRIVER *d)) { cons_in_stat = 0; cons_out_stat = CONS_READY; state = 0; } static void cons_reset(UNUSED(DRIVER *d)) { } static int cons_intchk(INTRQ *irq) { return((irq->vec == 060) ? WANTINT(cons_in_stat) : WANTINT(cons_out_stat)); } DRIVER cons_driver = { DVR_NORMW, "console", cons_init, cons_tick, cons_io, cons_busreset, cons_reset, cons_intchk, 0 }; void cons__reset(void) /* called by odt when pausing or exiting */ { int off; tcsetattr(0,TCSANOW,&old_tty); off = 0; ioctl(0,FIONBIO,&off); ioctl(0,FIOASYNC,&off); } void cons__resume(void) /* called by odt when resuming */ { int on; tcsetattr(0,TCSANOW,&new_tty); on = 1; ioctl(0,FIONBIO,&on); ioctl(0,FIOASYNC,&on); } void cons__flush(void) /* called by odt to flush buffered character(s) */ { cons_tick(&cons_driver); cons_tick(&cons_driver); }