# #include "param.h" #include "conf.h" #include "tty.h" #include "user.h" #include "proc.h" /* * Vdu driver -- local terminal on PALS * */ #define NVDU 16 /* number of local terminals */ int vdubase 0x10; /* lowest PALS address */ extern char conscmd2; /* PALS command 2 for 'console' */ struct tty vdu[NVDU]; int vdustart(), vdurint(), vduxint(), ttrstrt(); /* * PALS commands & status bits */ /* command 1 */ #define DIS 0200 #define EN 0100 #define DTR 0040 #define WRT 0002 #define CMD1 0001 /* command 2 */ #define CLKA 0000 #define CLKB 0100 #define CLKC 0200 #define CLKD 0300 #define CMD2 0070 /* Status */ #define CARR_OFF 0002 #define BSY 0010 /* * open routine: * called each time a process opens a terminal as a character file * * - if the terminal was previously inactive, set up the initial status * and arm interrupts */ vduopen(dev) { register struct tty *tp; if (dev.d_minor >= NVDU) { u.u_error = ENXIO; return; } tp = &vdu[dev.d_minor]; tp->t_dev = dev; if ((tp->t_state& ISOPEN) == 0) { tp->t_state = ISOPEN | SSTART; if (tp->t_flags == 0) tp->t_flags = XTABS | LCASE | CRMOD | ECHO; tp->t_erase = CERASE; tp->t_kill = CKILL; tp->t_addr = vdustart; vduenab(tp); } spl(4); while (!(tp->t_state&CARR_ON)) sleep(&tp->t_rawq, TTIPRI); spl(0); if (u.u_procp->p_ttyp == 0) u.u_procp->p_ttyp = tp; } /* * close routine: * - called only when last process using terminal releases it */ vduclose(dev) { register struct tty *tp; tp = &vdu[dev.d_minor]; wflushtty(tp); tp->t_state = 0; vdudisab(dev); } /* * read, write, stty, gtty routines: * - call standard tty routines */ vduread(dev) { ttread(&vdu[dev.d_minor]); } vduwrite(dev) { ttwrite(&vdu[dev.d_minor]); } vdusgtty(dev, v) { register struct tty *tp; tp = &vdu[dev.d_minor]; ttystty(tp, v); /* Stty - reissue CMD 2 to change baud rate */ if (v == 0) vduenab(tp); } /* * vdustart routine - called when there might be something to send * to the terminal */ vdustart(atp) struct tty *atp; { register struct tty *tp; register c, waddr; tp = atp; waddr = 2*tp->t_dev + vdubase + 1; trace(040, "vdustart", waddr); if ((tp->t_state&(TIMEOUT|BUSY|SUSPEND|CARR_ON)) != CARR_ON || (c = getc(&tp->t_outq)) < 0) return; if (c > 0177) { tp->t_state =| TIMEOUT; timeout(ttrstrt, tp, c&0177); } else { tp->t_state =| BUSY; c =| partab[c]&0200; wd(waddr, c); trace(0100, "wrt", ss(waddr)); } } vdurint(raddr, stat) { register struct tty *tp; register char c; tp = &vdu[(raddr-vdubase)>>1]; if (!(tp->t_state & ISOPEN)) return; trace(0100, "rint", raddr); trace(0100, "stat", stat); c = rd(raddr)&0177; trace(0100, "char", c); if (stat & CARR_OFF) { if (tp->t_state & CARR_ON) { signal(tp, SIGHUP); flushtty(tp); } tp->t_state =& ~CARR_ON; return; } if (!(tp->t_state & CARR_ON)) { tp->t_state =| CARR_ON; wakeup(&tp->t_rawq); return; } /* * Carousel DC4 / DC2 (suspend / resume) signals */ if (c == '\024' && !(tp->t_flags&RAW)) tp->t_state =| SUSPEND; else if (c == '\022' && !(tp->t_flags&RAW)) { if (tp->t_state&SUSPEND) { tp->t_state =& ~SUSPEND; wakeup(&tp->t_outq); ttstart(tp); } } else ttyinput(c, tp); } vduxint(waddr, stat) { register struct tty *tp; register c; tp = &vdu[(waddr-vdubase)>>1]; if (!(tp->t_state & ISOPEN)) return; trace(0100, "wint", waddr); trace(0100, "stat", stat); tp->t_state =& ~BUSY; ttstart(tp); if (tp->t_outq.c_cc <= TTLOWAT && (tp->t_state&ASLEEP)) { tp->t_state =& ~ASLEEP; wakeup(&tp->t_outq); } } /* * Arm interrupts from PALS and set baud rate */ vduenab(atp) struct tp *atp; { register struct tp *tp; register radd, wadd; register cmd2, stat; switch ((tp = atp)->t_speeds&0377) { case B300: cmd2 = CLKA | CMD2; break; case B1200: cmd2 = CLKB | CMD2; break; case B2400: cmd2 = CLKC | CMD2; break; case B4800: cmd2 = CLKD | CMD2; break; default: /* Use low-core 'console' definition */ cmd2 = conscmd2; } radd = vdubase + tp->t_dev.d_minor*2; wadd = radd + 1; oc(radd, cmd2); oc(radd, EN | DTR | CMD1); oc(wadd, EN | DTR | WRT | CMD1); stat = ss(radd); if ((stat&CARR_OFF) == 0) tp->t_state =| CARR_ON; trace(0100, "vduenab", stat); rd(radd); } /* * Disarm interrupts from PALS */ vdudisab(dev) { register radd, wadd; radd = vdubase + dev.d_minor*2; wadd = radd + 1; oc(radd, DIS | CMD1); oc(wadd, DIS | WRT | CMD1); trace(0100, "vdudisab", ss(radd)); }