141480Smckusick /* 241480Smckusick * Copyright (c) 1988 University of Utah. 341480Smckusick * Copyright (c) 1990 The Regents of the University of California. 441480Smckusick * All rights reserved. 541480Smckusick * 641480Smckusick * This code is derived from software contributed to Berkeley by 741480Smckusick * the Systems Programming Group of the University of Utah Computer 841480Smckusick * Science Department. 941480Smckusick * 1041480Smckusick * %sccs.include.redist.c% 1141480Smckusick * 12*57311Shibler * from: Utah $Hdr: ite.c 1.28 92/12/20$ 1341480Smckusick * 14*57311Shibler * @(#)ite.c 7.15 (Berkeley) 12/27/92 1541480Smckusick */ 1641480Smckusick 1741480Smckusick /* 1841480Smckusick * Bit-mapped display terminal emulator machine independent code. 1941480Smckusick * This is a very rudimentary. Much more can be abstracted out of 2041480Smckusick * the hardware dependent routines. 2141480Smckusick */ 2241480Smckusick #include "ite.h" 2341480Smckusick #if NITE > 0 2441480Smckusick 2541480Smckusick #include "grf.h" 2641480Smckusick 2741480Smckusick #undef NITE 2841480Smckusick #define NITE NGRF 2941480Smckusick 3056504Sbostic #include <sys/param.h> 3156504Sbostic #include <sys/conf.h> 3256504Sbostic #include <sys/proc.h> 3356504Sbostic #include <sys/ioctl.h> 3456504Sbostic #include <sys/tty.h> 3556504Sbostic #include <sys/systm.h> 3656504Sbostic #include <sys/malloc.h> 3741480Smckusick 3856504Sbostic #include <hp/dev/grfioctl.h> 3956504Sbostic #include <hp/dev/grfvar.h> 4056504Sbostic #include <hp/dev/itevar.h> 4156504Sbostic #include <hp/dev/kbdmap.h> 4241480Smckusick 4341480Smckusick #define set_attr(ip, attr) ((ip)->attribute |= (attr)) 4441480Smckusick #define clr_attr(ip, attr) ((ip)->attribute &= ~(attr)) 4541480Smckusick 4641480Smckusick /* 47*57311Shibler * No need to raise SPL above the HIL (the only thing that can 48*57311Shibler * affect our state. 49*57311Shibler */ 50*57311Shibler #include <hp/dev/hilreg.h> 51*57311Shibler #define splite() splhil() 52*57311Shibler 53*57311Shibler /* 5441480Smckusick * # of chars are output in a single itestart() call. 5541480Smckusick * If this is too big, user processes will be blocked out for 5641480Smckusick * long periods of time while we are emptying the queue in itestart(). 5741480Smckusick * If it is too small, console output will be very ragged. 5841480Smckusick */ 5941480Smckusick int iteburst = 64; 6041480Smckusick 6141480Smckusick int nite = NITE; 6241480Smckusick struct tty *kbd_tty = NULL; 6341480Smckusick struct tty ite_tty[NITE]; 6441480Smckusick struct ite_softc ite_softc[NITE]; 6541480Smckusick 66*57311Shibler void itestart(), iterestart(); 6741480Smckusick extern struct tty *constty; 6841480Smckusick 6941480Smckusick /* 7041480Smckusick * Primary attribute buffer to be used by the first bitmapped console 7141480Smckusick * found. Secondary displays alloc the attribute buffer as needed. 7241480Smckusick * Size is based on a 68x128 display, which is currently our largest. 7341480Smckusick */ 7441480Smckusick u_char console_attributes[0x2200]; 7541480Smckusick 76*57311Shibler #define ite_erasecursor(ip, sp) { \ 77*57311Shibler if ((ip)->flags & ITE_CURSORON) \ 78*57311Shibler (*(sp)->ite_cursor)((ip), ERASE_CURSOR); \ 79*57311Shibler } 80*57311Shibler #define ite_drawcursor(ip, sp) { \ 81*57311Shibler if ((ip)->flags & ITE_CURSORON) \ 82*57311Shibler (*(sp)->ite_cursor)((ip), DRAW_CURSOR); \ 83*57311Shibler } 84*57311Shibler #define ite_movecursor(ip, sp) { \ 85*57311Shibler if ((ip)->flags & ITE_CURSORON) \ 86*57311Shibler (*(sp)->ite_cursor)((ip), MOVE_CURSOR); \ 87*57311Shibler } 88*57311Shibler 8941480Smckusick /* 9041480Smckusick * Perform functions necessary to setup device as a terminal emulator. 9141480Smckusick */ 9241480Smckusick iteon(dev, flag) 9341480Smckusick dev_t dev; 9441480Smckusick { 9541480Smckusick int unit = UNIT(dev); 9641480Smckusick struct tty *tp = &ite_tty[unit]; 9741480Smckusick struct ite_softc *ip = &ite_softc[unit]; 9841480Smckusick 9941480Smckusick if (unit < 0 || unit >= NITE || (ip->flags&ITE_ALIVE) == 0) 10041480Smckusick return(ENXIO); 10141480Smckusick /* force ite active, overriding graphics mode */ 10241480Smckusick if (flag & 1) { 10341480Smckusick ip->flags |= ITE_ACTIVE; 10441480Smckusick ip->flags &= ~(ITE_INGRF|ITE_INITED); 10541480Smckusick } 10641480Smckusick /* leave graphics mode */ 10741480Smckusick if (flag & 2) { 10841480Smckusick ip->flags &= ~ITE_INGRF; 10941480Smckusick if ((ip->flags & ITE_ACTIVE) == 0) 11041480Smckusick return(0); 11141480Smckusick } 11241480Smckusick ip->flags |= ITE_ACTIVE; 11341480Smckusick if (ip->flags & ITE_INGRF) 11441480Smckusick return(0); 11541480Smckusick if (kbd_tty == NULL || kbd_tty == tp) { 11641480Smckusick kbd_tty = tp; 11753923Shibler kbdenable(unit); 11841480Smckusick } 11941480Smckusick iteinit(dev); 12041480Smckusick return(0); 12141480Smckusick } 12241480Smckusick 12341480Smckusick iteinit(dev) 12441480Smckusick dev_t dev; 12541480Smckusick { 12641480Smckusick int unit = UNIT(dev); 12741480Smckusick struct ite_softc *ip = &ite_softc[unit]; 12841480Smckusick 12941480Smckusick if (ip->flags & ITE_INITED) 13041480Smckusick return; 13141480Smckusick 13241480Smckusick ip->curx = 0; 13341480Smckusick ip->cury = 0; 13441480Smckusick ip->cursorx = 0; 13541480Smckusick ip->cursory = 0; 13641480Smckusick 13753923Shibler (*ip->isw->ite_init)(ip); 138*57311Shibler ip->flags |= ITE_CURSORON; 139*57311Shibler ite_drawcursor(ip, ip->isw); 14041480Smckusick 14141480Smckusick ip->attribute = 0; 14241480Smckusick if (ip->attrbuf == NULL) 14341480Smckusick ip->attrbuf = (u_char *) 14441480Smckusick malloc(ip->rows * ip->cols, M_DEVBUF, M_WAITOK); 14541480Smckusick bzero(ip->attrbuf, (ip->rows * ip->cols)); 14641480Smckusick 14741480Smckusick ip->imode = 0; 14841480Smckusick ip->flags |= ITE_INITED; 14941480Smckusick } 15041480Smckusick 15141480Smckusick /* 15241480Smckusick * "Shut down" device as terminal emulator. 15341480Smckusick * Note that we do not deinit the console device unless forced. 15441480Smckusick * Deinit'ing the console every time leads to a very active 15541480Smckusick * screen when processing /etc/rc. 15641480Smckusick */ 15741480Smckusick iteoff(dev, flag) 15841480Smckusick dev_t dev; 15941480Smckusick { 16041480Smckusick register struct ite_softc *ip = &ite_softc[UNIT(dev)]; 16141480Smckusick 16241480Smckusick if (flag & 2) 16341480Smckusick ip->flags |= ITE_INGRF; 16441480Smckusick if ((ip->flags & ITE_ACTIVE) == 0) 16541480Smckusick return; 16641480Smckusick if ((flag & 1) || 167*57311Shibler (ip->flags & (ITE_INGRF|ITE_ISCONS|ITE_INITED)) == ITE_INITED) { 16853923Shibler (*ip->isw->ite_deinit)(ip); 169*57311Shibler ip->flags &= ~ITE_CURSORON; 170*57311Shibler } 17141480Smckusick if ((flag & 2) == 0) 17241480Smckusick ip->flags &= ~ITE_ACTIVE; 17341480Smckusick } 17441480Smckusick 17549132Skarels /* ARGSUSED */ 17649132Skarels #ifdef __STDC__ 17749132Skarels iteopen(dev_t dev, int mode, int devtype, struct proc *p) 17849132Skarels #else 17949132Skarels iteopen(dev, mode, devtype, p) 18041480Smckusick dev_t dev; 18149132Skarels int mode, devtype; 18249132Skarels struct proc *p; 18349132Skarels #endif 18441480Smckusick { 18541480Smckusick int unit = UNIT(dev); 18641480Smckusick register struct tty *tp = &ite_tty[unit]; 18741480Smckusick register struct ite_softc *ip = &ite_softc[unit]; 18841480Smckusick register int error; 18941480Smckusick int first = 0; 19041480Smckusick 19143409Shibler if ((tp->t_state&(TS_ISOPEN|TS_XCLUDE)) == (TS_ISOPEN|TS_XCLUDE) 19249132Skarels && p->p_ucred->cr_uid != 0) 19341480Smckusick return (EBUSY); 19441480Smckusick if ((ip->flags & ITE_ACTIVE) == 0) { 19541480Smckusick error = iteon(dev, 0); 19641480Smckusick if (error) 19741480Smckusick return (error); 19841480Smckusick first = 1; 19941480Smckusick } 20041480Smckusick tp->t_oproc = itestart; 20141480Smckusick tp->t_param = NULL; 20241480Smckusick tp->t_dev = dev; 20341480Smckusick if ((tp->t_state&TS_ISOPEN) == 0) { 20441480Smckusick ttychars(tp); 20541480Smckusick tp->t_iflag = TTYDEF_IFLAG; 20641480Smckusick tp->t_oflag = TTYDEF_OFLAG; 20741480Smckusick tp->t_cflag = CS8|CREAD; 20841480Smckusick tp->t_lflag = TTYDEF_LFLAG; 20941480Smckusick tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; 21041480Smckusick tp->t_state = TS_ISOPEN|TS_CARR_ON; 21141480Smckusick ttsetwater(tp); 21241480Smckusick } 21341480Smckusick error = (*linesw[tp->t_line].l_open)(dev, tp); 21441480Smckusick if (error == 0) { 21541480Smckusick tp->t_winsize.ws_row = ip->rows; 21641480Smckusick tp->t_winsize.ws_col = ip->cols; 21741480Smckusick } else if (first) 21841480Smckusick iteoff(dev, 0); 21941480Smckusick return (error); 22041480Smckusick } 22141480Smckusick 22241480Smckusick /*ARGSUSED*/ 22349750Smarc iteclose(dev, flag, mode, p) 22441480Smckusick dev_t dev; 22549750Smarc int flag, mode; 22649750Smarc struct proc *p; 22741480Smckusick { 22841480Smckusick register struct tty *tp = &ite_tty[UNIT(dev)]; 22941480Smckusick 23049750Smarc (*linesw[tp->t_line].l_close)(tp, flag); 23141480Smckusick ttyclose(tp); 23241480Smckusick iteoff(dev, 0); 23341480Smckusick return(0); 23441480Smckusick } 23541480Smckusick 23641480Smckusick iteread(dev, uio, flag) 23741480Smckusick dev_t dev; 23841480Smckusick struct uio *uio; 23941480Smckusick { 24041480Smckusick register struct tty *tp = &ite_tty[UNIT(dev)]; 24141480Smckusick 24241480Smckusick return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); 24341480Smckusick } 24441480Smckusick 24541480Smckusick itewrite(dev, uio, flag) 24641480Smckusick dev_t dev; 24741480Smckusick struct uio *uio; 24841480Smckusick { 24941480Smckusick int unit = UNIT(dev); 25041480Smckusick register struct tty *tp = &ite_tty[unit]; 25141480Smckusick 25241480Smckusick if ((ite_softc[unit].flags & ITE_ISCONS) && constty && 25341480Smckusick (constty->t_state&(TS_CARR_ON|TS_ISOPEN))==(TS_CARR_ON|TS_ISOPEN)) 25441480Smckusick tp = constty; 25541480Smckusick return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); 25641480Smckusick } 25741480Smckusick 25852417Smckusick iteioctl(dev, cmd, addr, flag, p) 25941480Smckusick dev_t dev; 26052417Smckusick int cmd; 26141480Smckusick caddr_t addr; 26252417Smckusick int flag; 26352417Smckusick struct proc *p; 26441480Smckusick { 26541480Smckusick register struct tty *tp = &ite_tty[UNIT(dev)]; 26641480Smckusick int error; 26741480Smckusick 26852417Smckusick error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, addr, flag, p); 26941480Smckusick if (error >= 0) 27041480Smckusick return (error); 27141480Smckusick error = ttioctl(tp, cmd, addr, flag); 27241480Smckusick if (error >= 0) 27341480Smckusick return (error); 27441480Smckusick return (ENOTTY); 27541480Smckusick } 27641480Smckusick 27752390Smckusick void 278*57311Shibler iterestart(tp) 279*57311Shibler register struct tty *tp; 280*57311Shibler { 281*57311Shibler register int s = splite(); 282*57311Shibler 283*57311Shibler tp->t_state &= ~TS_TIMEOUT; 284*57311Shibler itestart(tp); 285*57311Shibler splx(s); 286*57311Shibler } 287*57311Shibler 288*57311Shibler void 28941480Smckusick itestart(tp) 29041480Smckusick register struct tty *tp; 29141480Smckusick { 29241480Smckusick register int cc, s; 29341480Smckusick int hiwat = 0; 294*57311Shibler struct ite_softc *ip; 29541480Smckusick 296*57311Shibler /* 297*57311Shibler * (Potentially) lower priority. We only need to protect ourselves 298*57311Shibler * from keyboard interrupts since that is all that can affect the 299*57311Shibler * state of our tty (kernel printf doesn't go through this routine). 300*57311Shibler */ 301*57311Shibler s = splite(); 30241480Smckusick if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) { 30341480Smckusick splx(s); 30441480Smckusick return; 30541480Smckusick } 30641480Smckusick tp->t_state |= TS_BUSY; 30741480Smckusick cc = tp->t_outq.c_cc; 30841480Smckusick if (cc <= tp->t_lowat) { 30941480Smckusick if (tp->t_state & TS_ASLEEP) { 31041480Smckusick tp->t_state &= ~TS_ASLEEP; 31152390Smckusick wakeup((caddr_t)&tp->t_outq); 31241480Smckusick } 31352530Storek selwakeup(&tp->t_wsel); 31441480Smckusick } 31541480Smckusick /* 316*57311Shibler * Handle common (?) case 31741480Smckusick */ 318*57311Shibler if (cc == 1) { 319*57311Shibler iteputchar(getc(&tp->t_outq), tp->t_dev); 320*57311Shibler } else if (cc) { 32141480Smckusick /* 322*57311Shibler * Limit the amount of output we do in one burst 323*57311Shibler * to prevent hogging the CPU. 32441480Smckusick */ 325*57311Shibler if (cc > iteburst) { 326*57311Shibler hiwat++; 327*57311Shibler cc = iteburst; 328*57311Shibler } 329*57311Shibler /* 330*57311Shibler * Turn off cursor while we output multiple characters. 331*57311Shibler * Saves a lot of expensive window move operations. 332*57311Shibler */ 333*57311Shibler ip = &ite_softc[UNIT(tp->t_dev)]; 334*57311Shibler ite_erasecursor(ip, ip->isw); 335*57311Shibler ip->flags &= ~ITE_CURSORON; 336*57311Shibler while (--cc >= 0) 337*57311Shibler iteputchar(getc(&tp->t_outq), tp->t_dev); 338*57311Shibler ip->flags |= ITE_CURSORON; 339*57311Shibler ite_drawcursor(ip, ip->isw); 340*57311Shibler if (hiwat) { 341*57311Shibler tp->t_state |= TS_TIMEOUT; 342*57311Shibler timeout(iterestart, tp, 1); 343*57311Shibler } 34441480Smckusick } 34541480Smckusick tp->t_state &= ~TS_BUSY; 34641480Smckusick splx(s); 34741480Smckusick } 34841480Smckusick 34941480Smckusick itefilter(stat, c) 35041480Smckusick register char stat, c; 35141480Smckusick { 35241480Smckusick static int capsmode = 0; 35341480Smckusick static int metamode = 0; 35441480Smckusick register char code, *str; 35541480Smckusick 35641480Smckusick if (kbd_tty == NULL) 35741480Smckusick return; 35841480Smckusick 35941480Smckusick switch (c & 0xFF) { 36041480Smckusick case KBD_CAPSLOCK: 36141480Smckusick capsmode = !capsmode; 36241480Smckusick return; 36341480Smckusick 36441480Smckusick case KBD_EXT_LEFT_DOWN: 36541480Smckusick case KBD_EXT_RIGHT_DOWN: 36641480Smckusick metamode = 1; 36741480Smckusick return; 36841480Smckusick 36941480Smckusick case KBD_EXT_LEFT_UP: 37041480Smckusick case KBD_EXT_RIGHT_UP: 37141480Smckusick metamode = 0; 37241480Smckusick return; 37341480Smckusick } 37441480Smckusick 37541480Smckusick c &= KBD_CHARMASK; 37641480Smckusick switch ((stat>>KBD_SSHIFT) & KBD_SMASK) { 37741480Smckusick 37841480Smckusick case KBD_KEY: 37941480Smckusick if (!capsmode) { 38041480Smckusick code = kbd_keymap[c]; 38141480Smckusick break; 38241480Smckusick } 38341480Smckusick /* fall into... */ 38441480Smckusick 38541480Smckusick case KBD_SHIFT: 38641480Smckusick code = kbd_shiftmap[c]; 38741480Smckusick break; 38841480Smckusick 38941480Smckusick case KBD_CTRL: 39041480Smckusick code = kbd_ctrlmap[c]; 39141480Smckusick break; 39241480Smckusick 39341480Smckusick case KBD_CTRLSHIFT: 39441480Smckusick code = kbd_ctrlshiftmap[c]; 39541480Smckusick break; 39641480Smckusick } 39741480Smckusick 39841480Smckusick if (code == NULL && (str = kbd_stringmap[c]) != NULL) { 39941480Smckusick while (*str) 40041480Smckusick (*linesw[kbd_tty->t_line].l_rint)(*str++, kbd_tty); 40141480Smckusick } else { 40241480Smckusick if (metamode) 40341480Smckusick code |= 0x80; 40441480Smckusick (*linesw[kbd_tty->t_line].l_rint)(code, kbd_tty); 40541480Smckusick } 40641480Smckusick } 40741480Smckusick 40841480Smckusick iteputchar(c, dev) 40941480Smckusick register int c; 41041480Smckusick dev_t dev; 41141480Smckusick { 41241480Smckusick int unit = UNIT(dev); 41341480Smckusick register struct ite_softc *ip = &ite_softc[unit]; 41453923Shibler register struct itesw *sp = ip->isw; 41541480Smckusick register int n; 41641480Smckusick 41741480Smckusick if ((ip->flags & (ITE_ACTIVE|ITE_INGRF)) != ITE_ACTIVE) 41841480Smckusick return; 41941480Smckusick 42041480Smckusick if (ip->escape) { 42141480Smckusick doesc: 42241480Smckusick switch (ip->escape) { 42341480Smckusick 42441480Smckusick case '&': /* Next can be a,d, or s */ 42541480Smckusick if (ip->fpd++) { 42641480Smckusick ip->escape = c; 42741480Smckusick ip->fpd = 0; 42841480Smckusick } 42941480Smckusick return; 43041480Smckusick 43141480Smckusick case 'a': /* cursor change */ 43241480Smckusick switch (c) { 43341480Smckusick 43441480Smckusick case 'Y': /* Only y coord. */ 43555069Spendry ip->cury = min(ip->pos, ip->rows-1); 43641480Smckusick ip->pos = 0; 43741480Smckusick ip->escape = 0; 438*57311Shibler ite_movecursor(ip, sp); 43941480Smckusick clr_attr(ip, ATTR_INV); 44041480Smckusick break; 44141480Smckusick 44241480Smckusick case 'y': /* y coord first */ 44355069Spendry ip->cury = min(ip->pos, ip->rows-1); 44441480Smckusick ip->pos = 0; 44541480Smckusick ip->fpd = 0; 44641480Smckusick break; 44741480Smckusick 44841480Smckusick case 'C': /* x coord */ 44955069Spendry ip->curx = min(ip->pos, ip->cols-1); 45041480Smckusick ip->pos = 0; 45141480Smckusick ip->escape = 0; 452*57311Shibler ite_movecursor(ip, sp); 45341480Smckusick clr_attr(ip, ATTR_INV); 45441480Smckusick break; 45541480Smckusick 45641480Smckusick default: /* Possibly a 3 digit number. */ 45741480Smckusick if (c >= '0' && c <= '9' && ip->fpd < 3) { 45841480Smckusick ip->pos = ip->pos * 10 + (c - '0'); 45941480Smckusick ip->fpd++; 46041480Smckusick } else { 46141480Smckusick ip->pos = 0; 46241480Smckusick ip->escape = 0; 46341480Smckusick } 46441480Smckusick break; 46541480Smckusick } 46641480Smckusick return; 46741480Smckusick 46841480Smckusick case 'd': /* attribute change */ 46941480Smckusick switch (c) { 47041480Smckusick 47141480Smckusick case 'B': 47241480Smckusick set_attr(ip, ATTR_INV); 47341480Smckusick break; 47441480Smckusick case 'D': 47541480Smckusick /* XXX: we don't do anything for underline */ 47641480Smckusick set_attr(ip, ATTR_UL); 47741480Smckusick break; 47841480Smckusick case '@': 47941480Smckusick clr_attr(ip, ATTR_ALL); 48041480Smckusick break; 48141480Smckusick } 48241480Smckusick ip->escape = 0; 48341480Smckusick return; 48441480Smckusick 48541480Smckusick case 's': /* keypad control */ 48641480Smckusick switch (ip->fpd) { 48741480Smckusick 48841480Smckusick case 0: 48941480Smckusick ip->hold = c; 49041480Smckusick ip->fpd++; 49141480Smckusick return; 49241480Smckusick 49341480Smckusick case 1: 49441480Smckusick if (c == 'A') { 49541480Smckusick switch (ip->hold) { 49641480Smckusick 49741480Smckusick case '0': 49841480Smckusick clr_attr(ip, ATTR_KPAD); 49941480Smckusick break; 50041480Smckusick case '1': 50141480Smckusick set_attr(ip, ATTR_KPAD); 50241480Smckusick break; 50341480Smckusick } 50441480Smckusick } 50541480Smckusick ip->hold = 0; 50641480Smckusick } 50741480Smckusick ip->escape = 0; 50841480Smckusick return; 50941480Smckusick 51041480Smckusick case 'i': /* back tab */ 51141480Smckusick if (ip->curx > TABSIZE) { 51241480Smckusick n = ip->curx - (ip->curx & (TABSIZE - 1)); 51341480Smckusick ip->curx -= n; 51441480Smckusick } else 51541480Smckusick ip->curx = 0; 516*57311Shibler ite_movecursor(ip, sp); 51741480Smckusick ip->escape = 0; 51841480Smckusick return; 51941480Smckusick 52041480Smckusick case '3': /* clear all tabs */ 52141480Smckusick goto ignore; 52241480Smckusick 52341480Smckusick case 'K': /* clear_eol */ 52441480Smckusick ite_clrtoeol(ip, sp, ip->cury, ip->curx); 52541480Smckusick ip->escape = 0; 52641480Smckusick return; 52741480Smckusick 52841480Smckusick case 'J': /* clear_eos */ 52941480Smckusick ite_clrtoeos(ip, sp); 53041480Smckusick ip->escape = 0; 53141480Smckusick return; 53241480Smckusick 53341480Smckusick case 'B': /* cursor down 1 line */ 53441480Smckusick if (++ip->cury == ip->rows) { 53541480Smckusick --ip->cury; 536*57311Shibler ite_erasecursor(ip, sp); 53741480Smckusick (*sp->ite_scroll)(ip, 1, 0, 1, SCROLL_UP); 53841480Smckusick ite_clrtoeol(ip, sp, ip->cury, 0); 53941480Smckusick } 54041480Smckusick else 541*57311Shibler ite_movecursor(ip, sp); 54241480Smckusick clr_attr(ip, ATTR_INV); 54341480Smckusick ip->escape = 0; 54441480Smckusick return; 54541480Smckusick 54641480Smckusick case 'C': /* cursor forward 1 char */ 54741480Smckusick ip->escape = 0; 54841480Smckusick itecheckwrap(ip, sp); 54941480Smckusick return; 55041480Smckusick 55141480Smckusick case 'A': /* cursor up 1 line */ 55241480Smckusick if (ip->cury > 0) { 55341480Smckusick ip->cury--; 554*57311Shibler ite_movecursor(ip, sp); 55541480Smckusick } 55641480Smckusick ip->escape = 0; 55741480Smckusick clr_attr(ip, ATTR_INV); 55841480Smckusick return; 55941480Smckusick 56041480Smckusick case 'P': /* delete character */ 56141480Smckusick ite_dchar(ip, sp); 56241480Smckusick ip->escape = 0; 56341480Smckusick return; 56441480Smckusick 56541480Smckusick case 'M': /* delete line */ 56641480Smckusick ite_dline(ip, sp); 56741480Smckusick ip->escape = 0; 56841480Smckusick return; 56941480Smckusick 57041480Smckusick case 'Q': /* enter insert mode */ 57141480Smckusick ip->imode = 1; 57241480Smckusick ip->escape = 0; 57341480Smckusick return; 57441480Smckusick 57541480Smckusick case 'R': /* exit insert mode */ 57641480Smckusick ip->imode = 0; 57741480Smckusick ip->escape = 0; 57841480Smckusick return; 57941480Smckusick 58041480Smckusick case 'L': /* insert blank line */ 58141480Smckusick ite_iline(ip, sp); 58241480Smckusick ip->escape = 0; 58341480Smckusick return; 58441480Smckusick 58541480Smckusick case 'h': /* home key */ 58641480Smckusick ip->cury = ip->curx = 0; 587*57311Shibler ite_movecursor(ip, sp); 58841480Smckusick ip->escape = 0; 58941480Smckusick return; 59041480Smckusick 59141480Smckusick case 'D': /* left arrow key */ 59241480Smckusick if (ip->curx > 0) { 59341480Smckusick ip->curx--; 594*57311Shibler ite_movecursor(ip, sp); 59541480Smckusick } 59641480Smckusick ip->escape = 0; 59741480Smckusick return; 59841480Smckusick 59941480Smckusick case '1': /* set tab in all rows */ 60041480Smckusick goto ignore; 60141480Smckusick 60241480Smckusick case ESC: 60341480Smckusick if ((ip->escape = c) == ESC) 60441480Smckusick break; 60541480Smckusick ip->fpd = 0; 60641480Smckusick goto doesc; 60741480Smckusick 60841480Smckusick default: 60941480Smckusick ignore: 61041480Smckusick ip->escape = 0; 61141480Smckusick return; 61241480Smckusick 61341480Smckusick } 61441480Smckusick } 61541480Smckusick 61641480Smckusick switch (c &= 0x7F) { 61741480Smckusick 61841480Smckusick case '\n': 61941480Smckusick 62041480Smckusick if (++ip->cury == ip->rows) { 62141480Smckusick --ip->cury; 622*57311Shibler ite_erasecursor(ip, sp); 62341480Smckusick (*sp->ite_scroll)(ip, 1, 0, 1, SCROLL_UP); 62441480Smckusick ite_clrtoeol(ip, sp, ip->cury, 0); 625*57311Shibler } else 626*57311Shibler ite_movecursor(ip, sp); 62741480Smckusick clr_attr(ip, ATTR_INV); 62841480Smckusick break; 62941480Smckusick 63041480Smckusick case '\r': 63141480Smckusick if (ip->curx) { 63241480Smckusick ip->curx = 0; 633*57311Shibler ite_movecursor(ip, sp); 63441480Smckusick } 63541480Smckusick break; 63641480Smckusick 63741480Smckusick case '\b': 63841480Smckusick if (--ip->curx < 0) 63941480Smckusick ip->curx = 0; 64041480Smckusick else 641*57311Shibler ite_movecursor(ip, sp); 64241480Smckusick break; 64341480Smckusick 64441480Smckusick case '\t': 64541480Smckusick if (ip->curx < TABEND(unit)) { 64641480Smckusick n = TABSIZE - (ip->curx & (TABSIZE - 1)); 64741480Smckusick ip->curx += n; 648*57311Shibler ite_movecursor(ip, sp); 64941480Smckusick } else 65041480Smckusick itecheckwrap(ip, sp); 65141480Smckusick break; 65241480Smckusick 65341480Smckusick case CTRL('G'): 65441480Smckusick if (&ite_tty[unit] == kbd_tty) 65553923Shibler kbdbell(unit); 65641480Smckusick break; 65741480Smckusick 65841480Smckusick case ESC: 65941480Smckusick ip->escape = ESC; 66041480Smckusick break; 66141480Smckusick 66241480Smckusick default: 66341480Smckusick if (c < ' ' || c == DEL) 66441480Smckusick break; 66541480Smckusick if (ip->imode) 66641480Smckusick ite_ichar(ip, sp); 66741480Smckusick if ((ip->attribute & ATTR_INV) || attrtest(ip, ATTR_INV)) { 66841480Smckusick attrset(ip, ATTR_INV); 66941480Smckusick (*sp->ite_putc)(ip, c, ip->cury, ip->curx, ATTR_INV); 670*57311Shibler } else 67141480Smckusick (*sp->ite_putc)(ip, c, ip->cury, ip->curx, ATTR_NOR); 672*57311Shibler ite_drawcursor(ip, sp); 67341480Smckusick itecheckwrap(ip, sp); 67441480Smckusick break; 67541480Smckusick } 67641480Smckusick } 67741480Smckusick 67841480Smckusick itecheckwrap(ip, sp) 67941480Smckusick register struct ite_softc *ip; 68041480Smckusick register struct itesw *sp; 68141480Smckusick { 68241480Smckusick if (++ip->curx == ip->cols) { 68341480Smckusick ip->curx = 0; 68441480Smckusick clr_attr(ip, ATTR_INV); 68541480Smckusick if (++ip->cury == ip->rows) { 68641480Smckusick --ip->cury; 687*57311Shibler ite_erasecursor(ip, sp); 68841480Smckusick (*sp->ite_scroll)(ip, 1, 0, 1, SCROLL_UP); 68941480Smckusick ite_clrtoeol(ip, sp, ip->cury, 0); 69041480Smckusick return; 69141480Smckusick } 69241480Smckusick } 693*57311Shibler ite_movecursor(ip, sp); 69441480Smckusick } 69541480Smckusick 69641480Smckusick ite_dchar(ip, sp) 69741480Smckusick register struct ite_softc *ip; 69841480Smckusick register struct itesw *sp; 69941480Smckusick { 700*57311Shibler if (ip->curx < ip->cols - 1) { 701*57311Shibler ite_erasecursor(ip, sp); 702*57311Shibler (*sp->ite_scroll)(ip, ip->cury, ip->curx + 1, 1, SCROLL_LEFT); 703*57311Shibler attrmov(ip, ip->cury, ip->curx + 1, ip->cury, ip->curx, 704*57311Shibler 1, ip->cols - ip->curx - 1); 705*57311Shibler } 70641480Smckusick attrclr(ip, ip->cury, ip->cols - 1, 1, 1); 70741480Smckusick (*sp->ite_putc)(ip, ' ', ip->cury, ip->cols - 1, ATTR_NOR); 708*57311Shibler ite_drawcursor(ip, sp); 70941480Smckusick } 71041480Smckusick 71141480Smckusick ite_ichar(ip, sp) 71241480Smckusick register struct ite_softc *ip; 71341480Smckusick register struct itesw *sp; 71441480Smckusick { 715*57311Shibler if (ip->curx < ip->cols - 1) { 716*57311Shibler ite_erasecursor(ip, sp); 717*57311Shibler (*sp->ite_scroll)(ip, ip->cury, ip->curx, 1, SCROLL_RIGHT); 718*57311Shibler attrmov(ip, ip->cury, ip->curx, ip->cury, ip->curx + 1, 719*57311Shibler 1, ip->cols - ip->curx - 1); 720*57311Shibler } 72141480Smckusick attrclr(ip, ip->cury, ip->curx, 1, 1); 72241480Smckusick (*sp->ite_putc)(ip, ' ', ip->cury, ip->curx, ATTR_NOR); 723*57311Shibler ite_drawcursor(ip, sp); 72441480Smckusick } 72541480Smckusick 72641480Smckusick ite_dline(ip, sp) 72741480Smckusick register struct ite_softc *ip; 72841480Smckusick register struct itesw *sp; 72941480Smckusick { 730*57311Shibler if (ip->cury < ip->rows - 1) { 731*57311Shibler ite_erasecursor(ip, sp); 732*57311Shibler (*sp->ite_scroll)(ip, ip->cury + 1, 0, 1, SCROLL_UP); 733*57311Shibler attrmov(ip, ip->cury + 1, 0, ip->cury, 0, 734*57311Shibler ip->rows - ip->cury - 1, ip->cols); 735*57311Shibler } 73641480Smckusick ite_clrtoeol(ip, sp, ip->rows - 1, 0); 73741480Smckusick } 73841480Smckusick 73941480Smckusick ite_iline(ip, sp) 74041480Smckusick register struct ite_softc *ip; 74141480Smckusick register struct itesw *sp; 74241480Smckusick { 743*57311Shibler if (ip->cury < ip->rows - 1) { 744*57311Shibler ite_erasecursor(ip, sp); 745*57311Shibler (*sp->ite_scroll)(ip, ip->cury, 0, 1, SCROLL_DOWN); 746*57311Shibler attrmov(ip, ip->cury, 0, ip->cury + 1, 0, 747*57311Shibler ip->rows - ip->cury - 1, ip->cols); 748*57311Shibler } 74941480Smckusick ite_clrtoeol(ip, sp, ip->cury, 0); 75041480Smckusick } 75141480Smckusick 75241480Smckusick ite_clrtoeol(ip, sp, y, x) 75341480Smckusick register struct ite_softc *ip; 75441480Smckusick register struct itesw *sp; 75541480Smckusick register int y, x; 75641480Smckusick { 75741480Smckusick (*sp->ite_clear)(ip, y, x, 1, ip->cols - x); 75841480Smckusick attrclr(ip, y, x, 1, ip->cols - x); 759*57311Shibler ite_drawcursor(ip, sp); 76041480Smckusick } 76141480Smckusick 76241480Smckusick ite_clrtoeos(ip, sp) 76341480Smckusick register struct ite_softc *ip; 76441480Smckusick register struct itesw *sp; 76541480Smckusick { 76641480Smckusick (*sp->ite_clear)(ip, ip->cury, 0, ip->rows - ip->cury, ip->cols); 76741480Smckusick attrclr(ip, ip->cury, 0, ip->rows - ip->cury, ip->cols); 768*57311Shibler ite_drawcursor(ip, sp); 76941480Smckusick } 77041480Smckusick 77141480Smckusick /* 77241480Smckusick * Console functions 77341480Smckusick */ 77456504Sbostic #include <hp/dev/cons.h> 77553923Shibler #ifdef hp300 77656504Sbostic #include <hp/dev/grfreg.h> 77753923Shibler #endif 77841480Smckusick 77941480Smckusick #ifdef DEBUG 78041480Smckusick /* 78141480Smckusick * Minimum ITE number at which to start looking for a console. 78241480Smckusick * Setting to 0 will do normal search, 1 will skip first ITE device, 78341480Smckusick * NITE will skip ITEs and use serial port. 78441480Smckusick */ 78541480Smckusick int whichconsole = 0; 78641480Smckusick #endif 78741480Smckusick 78841480Smckusick itecnprobe(cp) 78941480Smckusick struct consdev *cp; 79041480Smckusick { 79141480Smckusick register struct ite_softc *ip; 79253923Shibler int i, sw, maj, unit, pri; 79341480Smckusick 79441480Smckusick /* locate the major number */ 79541480Smckusick for (maj = 0; maj < nchrdev; maj++) 79641480Smckusick if (cdevsw[maj].d_open == iteopen) 79741480Smckusick break; 79841480Smckusick 79941480Smckusick /* urk! */ 80041480Smckusick grfconfig(); 80141480Smckusick 80241480Smckusick /* check all the individual displays and find the best */ 80341480Smckusick unit = -1; 80441480Smckusick pri = CN_DEAD; 80541480Smckusick for (i = 0; i < NITE; i++) { 80641480Smckusick struct grf_softc *gp = &grf_softc[i]; 80741480Smckusick 80841480Smckusick ip = &ite_softc[i]; 80941480Smckusick if ((gp->g_flags & GF_ALIVE) == 0) 81041480Smckusick continue; 81141480Smckusick ip->flags = (ITE_ALIVE|ITE_CONSOLE); 81241480Smckusick 81353923Shibler /* locate the proper switch table. */ 81453923Shibler for (sw = 0; sw < nitesw; sw++) 81553923Shibler if (itesw[sw].ite_hwid == gp->g_sw->gd_hwid) 81653923Shibler break; 81741480Smckusick 81853923Shibler if (sw == nitesw) 81953923Shibler continue; 82041480Smckusick #ifdef DEBUG 82141480Smckusick if (i < whichconsole) 82241480Smckusick continue; 82341480Smckusick #endif 82453923Shibler ip->isw = &itesw[sw]; 82553923Shibler ip->grf = gp; 82653923Shibler #ifdef hp300 82741480Smckusick if ((int)gp->g_display.gd_regaddr == GRFIADDR) { 82841480Smckusick pri = CN_INTERNAL; 82941480Smckusick unit = i; 83041480Smckusick } else if (unit < 0) { 83141480Smckusick pri = CN_NORMAL; 83241480Smckusick unit = i; 83341480Smckusick } 83453923Shibler #endif 83553923Shibler #ifdef hp800 83653923Shibler /* XXX use the first one for now */ 83753923Shibler if (unit < 0) { 83853923Shibler pri = CN_INTERNAL; 83953923Shibler unit = i; 84053923Shibler } 84153923Shibler #endif 84241480Smckusick } 84341480Smckusick 84441480Smckusick /* initialize required fields */ 84541480Smckusick cp->cn_dev = makedev(maj, unit); 84641480Smckusick cp->cn_tp = &ite_tty[unit]; 84741480Smckusick cp->cn_pri = pri; 84841480Smckusick } 84941480Smckusick 85041480Smckusick itecninit(cp) 85141480Smckusick struct consdev *cp; 85241480Smckusick { 85341480Smckusick int unit = UNIT(cp->cn_dev); 85441480Smckusick struct ite_softc *ip = &ite_softc[unit]; 85541480Smckusick 85641480Smckusick ip->attrbuf = console_attributes; 85741480Smckusick iteinit(cp->cn_dev); 85841480Smckusick ip->flags |= (ITE_ACTIVE|ITE_ISCONS); 85941480Smckusick kbd_tty = &ite_tty[unit]; 86041480Smckusick } 86141480Smckusick 86241480Smckusick /*ARGSUSED*/ 86341480Smckusick itecngetc(dev) 86441480Smckusick dev_t dev; 86541480Smckusick { 86641480Smckusick register int c; 86741480Smckusick int stat; 86841480Smckusick 86953923Shibler c = kbdgetc(0, &stat); /* XXX always read from keyboard 0 for now */ 87041480Smckusick switch ((stat >> KBD_SSHIFT) & KBD_SMASK) { 87141480Smckusick case KBD_SHIFT: 87241480Smckusick c = kbd_shiftmap[c & KBD_CHARMASK]; 87341480Smckusick break; 87441480Smckusick case KBD_CTRL: 87541480Smckusick c = kbd_ctrlmap[c & KBD_CHARMASK]; 87641480Smckusick break; 87741480Smckusick case KBD_KEY: 87841480Smckusick c = kbd_keymap[c & KBD_CHARMASK]; 87941480Smckusick break; 88041480Smckusick default: 88141480Smckusick c = 0; 88241480Smckusick break; 88341480Smckusick } 88441480Smckusick return(c); 88541480Smckusick } 88641480Smckusick 88741480Smckusick itecnputc(dev, c) 88841480Smckusick dev_t dev; 88941480Smckusick int c; 89041480Smckusick { 89141480Smckusick static int paniced = 0; 89241480Smckusick struct ite_softc *ip = &ite_softc[UNIT(dev)]; 89341480Smckusick 89441480Smckusick if (panicstr && !paniced && 89541480Smckusick (ip->flags & (ITE_ACTIVE|ITE_INGRF)) != ITE_ACTIVE) { 89641480Smckusick (void) iteon(dev, 3); 89741480Smckusick paniced = 1; 89841480Smckusick } 89941480Smckusick iteputchar(c, dev); 90041480Smckusick } 90141480Smckusick #endif 902