/* * (C) 1984 UniSoft Corp. of Berkeley CA * * UniPlus Source Code. This program is proprietary * with Unisoft Corporation and is not to be reproduced * or used in any manner except as authorized in * writing by Unisoft. * * co.c - "console" (ie, bitmap screen and keyboard) driver for the lisa. */ #include "sys/param.h" #include "sys/config.h" #include "sys/types.h" #include "sys/systm.h" #include "sys/dir.h" #include "sys/signal.h" #include "sys/user.h" #include "sys/errno.h" #include "sys/file.h" #include "sys/tty.h" #include "sys/termio.h" #include "sys/conf.h" #include "sys/sysinfo.h" #include "sys/var.h" #include "sys/reg.h" #include "setjmp.h" #include "sys/ioctl.h" #include "sys/kb.h" #include "sys/al_ioctl.h" #ifdef SUNIX #include "sys/reboot.h" #endif SUNIX #include "sys/mmu.h" #include "sys/cops.h" #include "sys/l2.h" int coproc(); extern int co_cnt; extern struct tty co_tty[]; extern struct ttyptr co_ttptr[]; extern char bmbck, bmnormal; extern char *bmscrn; /* pointer to screen -- initialized in bminit */ /* calls to the putc routine are made indirectly through * the te_putc pointer which is used to * keep track of the current state for escape character * processing, ie, although initialized to point to * the normal putc, an escape character causes other * functions to process the next character(s) */ extern int vt_putc(); int (*te_putc)()=vt_putc; /*#ifdef SUNIX extern caddr_t start; #endif SUNIX */ struct device { char csr; /* Command status register */ char idum[2]; /* fillers */ char dbuf; /* data buffer */ }; /* ARGSUSED */ coopen(dev, flag) register dev; { register struct tty *tp; if (dev >= co_cnt) { u.u_error = ENXIO; return; } tp = co_ttptr[dev].tt_tty; tp->t_index = dev; SPL6(); if ((tp->t_state&(ISOPEN|WOPEN)) == 0) { tp->t_proc = coproc; ttinit(tp); tp->t_state = WOPEN | CARR_ON; if (dev == CONSOLE) { tp->t_iflag = ICRNL | ISTRIP; tp->t_oflag = OPOST | ONLCR | TAB3; tp->t_lflag = ISIG | ICANON | ECHO | ECHOK; tp->t_cflag = sspeed | CS8 | CREAD | HUPCL; } } SPL0(); (*linesw[tp->t_line].l_open)(tp); } /* ARGSUSED */ coclose(dev, flag) { register struct tty *tp; tp = co_ttptr[dev].tt_tty; (*linesw[tp->t_line].l_close)(tp); } coread(dev) { struct tty *tp; tp = co_ttptr[dev].tt_tty; (*linesw[tp->t_line].l_read)(tp); } cowrite(dev) { struct tty *tp; tp = co_ttptr[dev].tt_tty; (*linesw[tp->t_line].l_write)(tp); } /* ARGSUSED */ coioctl(dev, cmd, arg, mode) { int i; switch (cmd) { case AL_SBVOL: l2_bvol = arg & 7; break; case AL_SBPITCH: l2_bpitch = arg & 0x1FFF; break; case AL_SBTIME: if (arg <= 0) arg = 1; if (arg > 10 * v.v_hz) /* limit to 10 seconds */ arg = 10 * v.v_hz; l2_btime = arg; break; case AL_SDIMTIME: l2_dtime = arg; l2_dtrap = lbolt + l2_dtime; break; case AL_SDIMCONT: l2_dimcont = (~arg) & 0xFF; break; case AL_SDIMRATE: l2_crate = arg; break; case AL_SCONTRAST: l2_defcont = (~arg) & 0xFF; l2_desired = l2_defcont; l2ramp(0); break; case AL_SREPWAIT: kb_repwait = arg; break; case AL_SREPDELAY: kb_repdlay = arg; break; case AL_GBVOL: i = l2_bvol; if (copyout((caddr_t)&i, (caddr_t)arg, 4)) u.u_error = EFAULT; break; case AL_GBPITCH: if (copyout((caddr_t)&l2_bpitch, (caddr_t)arg, 4)) u.u_error = EFAULT; break; case AL_GBTIME: if (copyout((caddr_t)&l2_btime, (caddr_t)arg, 4)) u.u_error = EFAULT; break; case AL_GDIMTIME: if (copyout((caddr_t)&l2_dtime, (caddr_t)arg, 4)) u.u_error = EFAULT; break; case AL_GDIMCONT: i = (~l2_dimcont) & 0xFF; if (copyout((caddr_t)&i, (caddr_t)arg, 4)) u.u_error = EFAULT; break; case AL_GDIMRATE: if (copyout((caddr_t)&l2_crate, (caddr_t)arg, 4)) u.u_error = EFAULT; break; case AL_GCONTRAST: i = (~l2_defcont) & 0xFF; if (copyout((caddr_t)&i, (caddr_t)arg, 4)) u.u_error = EFAULT; break; case AL_GREPWAIT: i = kb_repwait & 0xFFFF; if (copyout((caddr_t)&i, (caddr_t)arg, 4)) u.u_error = EFAULT; break; case AL_GREPDELAY: i = kb_repdlay & 0xFFFF; if (copyout((caddr_t)&i, (caddr_t)arg, 4)) u.u_error = EFAULT; break; case AL_GBMADDR: if (copyout((caddr_t)&bmscrn, (caddr_t)arg, 4)) u.u_error = EFAULT; break; case AL_REVVIDEO: if (arg > 0) i = 0; else if (arg == 0) i = -1; else i = (bmbck)? 0 : -1; if (bmbck != i) { bmswitch(); bmsinv(); } bmbck = i; bmnormal = bmbck; break; #ifdef SUNIX case RESTART: /* jump to the start of unix */ reinit(); ((int (*)())0xC000)(); break; #endif SUNIX default: (void) ttiocom(co_ttptr[0].tt_tty, cmd, arg, mode); break; } } coproc(tp, cmd) register struct tty *tp; { register struct ccblock *tbuf; extern ttrstrt(); switch (cmd) { case T_TIME: tp->t_state &= ~TIMEOUT; goto start; case T_WFLUSH: tbuf = &tp->t_tbuf; tbuf->c_size -= tbuf->c_count; tbuf->c_count = 0; /* fall through */ case T_RESUME: tp->t_state &= ~TTSTOP; goto start; case T_OUTPUT: start: if (tp->t_state & (TTSTOP|TIMEOUT|BUSY)) break; tbuf = &tp->t_tbuf; if ((tbuf->c_ptr == 0) || (tbuf->c_count == 0)) { if (tbuf->c_ptr) tbuf->c_ptr -= tbuf->c_size; if (!(CPRES & (*linesw[tp->t_line].l_output)(tp))) break; } (*te_putc)((*tbuf->c_ptr++)&0x7f); tbuf->c_count--; sysinfo.xmtint++; /* this is the xmit interrupt */ splx(spl1()); goto start; case T_SUSPEND: tp->t_state |= TTSTOP; break; case T_BLOCK: break; case T_RFLUSH: if (!(tp->t_state&TBLOCK)) break; /* fall through */ case T_UNBLOCK: break; case T_BREAK: break; } } cointr(dev) { register struct ccblock *cbp; register int c, lcnt, flg; struct tty *tp; register char ctmp; char lbuf[3]; sysinfo.rcvint++; c = kb_chrbuf; tp = co_ttptr[dev].tt_tty; if (tp->t_rbuf.c_ptr == NULL) return; #undef NULLDEBUG #ifdef NULLDEBUG if( c == 0x00 ) { sccdebug(); return; } #endif if (tp->t_iflag & IXON) { ctmp = c & 0177; if (tp->t_state & TTSTOP) { if (ctmp == CSTART || tp->t_iflag & IXANY) (*tp->t_proc)(tp, T_RESUME); } else { if (ctmp == CSTOP) (*tp->t_proc)(tp, T_SUSPEND); } if (ctmp == CSTART || ctmp == CSTOP) return; } /* * Check for errors */ lcnt = 1; flg = tp->t_iflag; if (flg&ISTRIP) c &= 0177; else { if (c == 0377 && flg&PARMRK) { lbuf[1] = 0377; lcnt = 2; } } /* * Stash character in r_buf */ cbp = &tp->t_rbuf; if (lcnt != 1) { lbuf[0] = c; while (lcnt) { *cbp->c_ptr++ = lbuf[--lcnt]; if (--cbp->c_count == 0) { cbp->c_ptr -= cbp->c_size; (*linesw[tp->t_line].l_input)(tp); } } if (cbp->c_size != cbp->c_count) { cbp->c_ptr -= cbp->c_size - cbp->c_count; (*linesw[tp->t_line].l_input)(tp); } } else { *cbp->c_ptr = c; cbp->c_count--; (*linesw[tp->t_line].l_input)(tp); } } /* * This version of putchar writes directly to the bitmap display * for those last-ditch situations when you just have to get stuff to the CRT. */ coputchar(c) register c; { (*te_putc)(c & 0x7F); if (c == '\n') (*te_putc)('\r'); }