141480Smckusick /* 241480Smckusick * Copyright (c) 1988 University of Utah. 363148Sbostic * Copyright (c) 1990, 1993 463148Sbostic * The Regents of the University of California. 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 * 1257311Shibler * from: Utah $Hdr: ite.c 1.28 92/12/20$ 1341480Smckusick * 14*65645Sbostic * @(#)ite.c 8.2 (Berkeley) 01/12/94 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 /* 4757311Shibler * No need to raise SPL above the HIL (the only thing that can 4857311Shibler * affect our state. 4957311Shibler */ 5057311Shibler #include <hp/dev/hilreg.h> 5157311Shibler #define splite() splhil() 5257311Shibler 5357311Shibler /* 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 6657311Shibler 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 7657311Shibler #define ite_erasecursor(ip, sp) { \ 7757311Shibler if ((ip)->flags & ITE_CURSORON) \ 7857311Shibler (*(sp)->ite_cursor)((ip), ERASE_CURSOR); \ 7957311Shibler } 8057311Shibler #define ite_drawcursor(ip, sp) { \ 8157311Shibler if ((ip)->flags & ITE_CURSORON) \ 8257311Shibler (*(sp)->ite_cursor)((ip), DRAW_CURSOR); \ 8357311Shibler } 8457311Shibler #define ite_movecursor(ip, sp) { \ 8557311Shibler if ((ip)->flags & ITE_CURSORON) \ 8657311Shibler (*(sp)->ite_cursor)((ip), MOVE_CURSOR); \ 8757311Shibler } 8857311Shibler 8941480Smckusick /* 9041480Smckusick * Perform functions necessary to setup device as a terminal emulator. 9141480Smckusick */ 9241480Smckusick iteon(dev, flag) 9341480Smckusick dev_t dev; 94*65645Sbostic int flag; 9541480Smckusick { 9641480Smckusick int unit = UNIT(dev); 9741480Smckusick struct tty *tp = &ite_tty[unit]; 9841480Smckusick struct ite_softc *ip = &ite_softc[unit]; 9941480Smckusick 10041480Smckusick if (unit < 0 || unit >= NITE || (ip->flags&ITE_ALIVE) == 0) 10141480Smckusick return(ENXIO); 10241480Smckusick /* force ite active, overriding graphics mode */ 10341480Smckusick if (flag & 1) { 10441480Smckusick ip->flags |= ITE_ACTIVE; 10541480Smckusick ip->flags &= ~(ITE_INGRF|ITE_INITED); 10641480Smckusick } 10741480Smckusick /* leave graphics mode */ 10841480Smckusick if (flag & 2) { 10941480Smckusick ip->flags &= ~ITE_INGRF; 11041480Smckusick if ((ip->flags & ITE_ACTIVE) == 0) 11141480Smckusick return(0); 11241480Smckusick } 11341480Smckusick ip->flags |= ITE_ACTIVE; 11441480Smckusick if (ip->flags & ITE_INGRF) 11541480Smckusick return(0); 11641480Smckusick if (kbd_tty == NULL || kbd_tty == tp) { 11741480Smckusick kbd_tty = tp; 11853923Shibler kbdenable(unit); 11941480Smckusick } 12041480Smckusick iteinit(dev); 12141480Smckusick return(0); 12241480Smckusick } 12341480Smckusick 12441480Smckusick iteinit(dev) 12541480Smckusick dev_t dev; 12641480Smckusick { 12741480Smckusick int unit = UNIT(dev); 12841480Smckusick struct ite_softc *ip = &ite_softc[unit]; 12941480Smckusick 13041480Smckusick if (ip->flags & ITE_INITED) 13141480Smckusick return; 13241480Smckusick 13341480Smckusick ip->curx = 0; 13441480Smckusick ip->cury = 0; 13541480Smckusick ip->cursorx = 0; 13641480Smckusick ip->cursory = 0; 13741480Smckusick 13853923Shibler (*ip->isw->ite_init)(ip); 13957311Shibler ip->flags |= ITE_CURSORON; 14057311Shibler ite_drawcursor(ip, ip->isw); 14141480Smckusick 14241480Smckusick ip->attribute = 0; 14341480Smckusick if (ip->attrbuf == NULL) 14441480Smckusick ip->attrbuf = (u_char *) 14541480Smckusick malloc(ip->rows * ip->cols, M_DEVBUF, M_WAITOK); 14641480Smckusick bzero(ip->attrbuf, (ip->rows * ip->cols)); 14741480Smckusick 14841480Smckusick ip->imode = 0; 14941480Smckusick ip->flags |= ITE_INITED; 15041480Smckusick } 15141480Smckusick 15241480Smckusick /* 15341480Smckusick * "Shut down" device as terminal emulator. 15441480Smckusick * Note that we do not deinit the console device unless forced. 15541480Smckusick * Deinit'ing the console every time leads to a very active 15641480Smckusick * screen when processing /etc/rc. 15741480Smckusick */ 15841480Smckusick iteoff(dev, flag) 15941480Smckusick dev_t dev; 160*65645Sbostic int flag; 16141480Smckusick { 16241480Smckusick register struct ite_softc *ip = &ite_softc[UNIT(dev)]; 16341480Smckusick 16458052Shibler if (flag & 2) { 16541480Smckusick ip->flags |= ITE_INGRF; 16658052Shibler ip->flags &= ~ITE_CURSORON; 16758052Shibler } 16841480Smckusick if ((ip->flags & ITE_ACTIVE) == 0) 16941480Smckusick return; 17041480Smckusick if ((flag & 1) || 17158052Shibler (ip->flags & (ITE_INGRF|ITE_ISCONS|ITE_INITED)) == ITE_INITED) 17253923Shibler (*ip->isw->ite_deinit)(ip); 17341480Smckusick if ((flag & 2) == 0) 17441480Smckusick ip->flags &= ~ITE_ACTIVE; 17541480Smckusick } 17641480Smckusick 17749132Skarels /* ARGSUSED */ 17849132Skarels #ifdef __STDC__ 17949132Skarels iteopen(dev_t dev, int mode, int devtype, struct proc *p) 18049132Skarels #else 18149132Skarels iteopen(dev, mode, devtype, p) 18241480Smckusick dev_t dev; 18349132Skarels int mode, devtype; 18449132Skarels struct proc *p; 18549132Skarels #endif 18641480Smckusick { 18741480Smckusick int unit = UNIT(dev); 18841480Smckusick register struct tty *tp = &ite_tty[unit]; 18941480Smckusick register struct ite_softc *ip = &ite_softc[unit]; 19041480Smckusick register int error; 19141480Smckusick int first = 0; 19241480Smckusick 19343409Shibler if ((tp->t_state&(TS_ISOPEN|TS_XCLUDE)) == (TS_ISOPEN|TS_XCLUDE) 19449132Skarels && p->p_ucred->cr_uid != 0) 19541480Smckusick return (EBUSY); 19641480Smckusick if ((ip->flags & ITE_ACTIVE) == 0) { 19741480Smckusick error = iteon(dev, 0); 19841480Smckusick if (error) 19941480Smckusick return (error); 20041480Smckusick first = 1; 20141480Smckusick } 20241480Smckusick tp->t_oproc = itestart; 20341480Smckusick tp->t_param = NULL; 20441480Smckusick tp->t_dev = dev; 20541480Smckusick if ((tp->t_state&TS_ISOPEN) == 0) { 20641480Smckusick ttychars(tp); 20741480Smckusick tp->t_iflag = TTYDEF_IFLAG; 20841480Smckusick tp->t_oflag = TTYDEF_OFLAG; 20941480Smckusick tp->t_cflag = CS8|CREAD; 21041480Smckusick tp->t_lflag = TTYDEF_LFLAG; 21141480Smckusick tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; 21241480Smckusick tp->t_state = TS_ISOPEN|TS_CARR_ON; 21341480Smckusick ttsetwater(tp); 21441480Smckusick } 21541480Smckusick error = (*linesw[tp->t_line].l_open)(dev, tp); 21641480Smckusick if (error == 0) { 21741480Smckusick tp->t_winsize.ws_row = ip->rows; 21841480Smckusick tp->t_winsize.ws_col = ip->cols; 21941480Smckusick } else if (first) 22041480Smckusick iteoff(dev, 0); 22141480Smckusick return (error); 22241480Smckusick } 22341480Smckusick 22441480Smckusick /*ARGSUSED*/ 22549750Smarc iteclose(dev, flag, mode, p) 22641480Smckusick dev_t dev; 22749750Smarc int flag, mode; 22849750Smarc struct proc *p; 22941480Smckusick { 23041480Smckusick register struct tty *tp = &ite_tty[UNIT(dev)]; 23141480Smckusick 23249750Smarc (*linesw[tp->t_line].l_close)(tp, flag); 23341480Smckusick ttyclose(tp); 23441480Smckusick iteoff(dev, 0); 23541480Smckusick return(0); 23641480Smckusick } 23741480Smckusick 23841480Smckusick iteread(dev, uio, flag) 23941480Smckusick dev_t dev; 24041480Smckusick struct uio *uio; 241*65645Sbostic int flag; 24241480Smckusick { 24341480Smckusick register struct tty *tp = &ite_tty[UNIT(dev)]; 24441480Smckusick 24541480Smckusick return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); 24641480Smckusick } 24741480Smckusick 24841480Smckusick itewrite(dev, uio, flag) 24941480Smckusick dev_t dev; 25041480Smckusick struct uio *uio; 251*65645Sbostic int flag; 25241480Smckusick { 25341480Smckusick int unit = UNIT(dev); 25441480Smckusick register struct tty *tp = &ite_tty[unit]; 25541480Smckusick 25641480Smckusick if ((ite_softc[unit].flags & ITE_ISCONS) && constty && 25741480Smckusick (constty->t_state&(TS_CARR_ON|TS_ISOPEN))==(TS_CARR_ON|TS_ISOPEN)) 25841480Smckusick tp = constty; 25941480Smckusick return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); 26041480Smckusick } 26141480Smckusick 26252417Smckusick iteioctl(dev, cmd, addr, flag, p) 26341480Smckusick dev_t dev; 26452417Smckusick int cmd; 26541480Smckusick caddr_t addr; 26652417Smckusick int flag; 26752417Smckusick struct proc *p; 26841480Smckusick { 26941480Smckusick register struct tty *tp = &ite_tty[UNIT(dev)]; 27041480Smckusick int error; 27141480Smckusick 27252417Smckusick error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, addr, flag, p); 27341480Smckusick if (error >= 0) 27441480Smckusick return (error); 27541480Smckusick error = ttioctl(tp, cmd, addr, flag); 27641480Smckusick if (error >= 0) 27741480Smckusick return (error); 27841480Smckusick return (ENOTTY); 27941480Smckusick } 28041480Smckusick 28152390Smckusick void 28257311Shibler iterestart(tp) 28357311Shibler register struct tty *tp; 28457311Shibler { 28557311Shibler register int s = splite(); 28657311Shibler 28757311Shibler tp->t_state &= ~TS_TIMEOUT; 28857311Shibler itestart(tp); 28957311Shibler splx(s); 29057311Shibler } 29157311Shibler 29257311Shibler void 29341480Smckusick itestart(tp) 29441480Smckusick register struct tty *tp; 29541480Smckusick { 29641480Smckusick register int cc, s; 29758052Shibler int hiwat = 0, hadcursor = 0; 29857311Shibler struct ite_softc *ip; 29941480Smckusick 30057311Shibler /* 30157311Shibler * (Potentially) lower priority. We only need to protect ourselves 30257311Shibler * from keyboard interrupts since that is all that can affect the 30357311Shibler * state of our tty (kernel printf doesn't go through this routine). 30457311Shibler */ 30557311Shibler s = splite(); 30641480Smckusick if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) { 30741480Smckusick splx(s); 30841480Smckusick return; 30941480Smckusick } 31041480Smckusick tp->t_state |= TS_BUSY; 31141480Smckusick cc = tp->t_outq.c_cc; 31241480Smckusick if (cc <= tp->t_lowat) { 31341480Smckusick if (tp->t_state & TS_ASLEEP) { 31441480Smckusick tp->t_state &= ~TS_ASLEEP; 31552390Smckusick wakeup((caddr_t)&tp->t_outq); 31641480Smckusick } 31752530Storek selwakeup(&tp->t_wsel); 31841480Smckusick } 31941480Smckusick /* 32057311Shibler * Handle common (?) case 32141480Smckusick */ 32257311Shibler if (cc == 1) { 32357311Shibler iteputchar(getc(&tp->t_outq), tp->t_dev); 32457311Shibler } else if (cc) { 32541480Smckusick /* 32657311Shibler * Limit the amount of output we do in one burst 32757311Shibler * to prevent hogging the CPU. 32841480Smckusick */ 32957311Shibler if (cc > iteburst) { 33057311Shibler hiwat++; 33157311Shibler cc = iteburst; 33257311Shibler } 33357311Shibler /* 33457311Shibler * Turn off cursor while we output multiple characters. 33557311Shibler * Saves a lot of expensive window move operations. 33657311Shibler */ 33757311Shibler ip = &ite_softc[UNIT(tp->t_dev)]; 33858052Shibler if (ip->flags & ITE_CURSORON) { 33958052Shibler ite_erasecursor(ip, ip->isw); 34058052Shibler ip->flags &= ~ITE_CURSORON; 34158052Shibler hadcursor = 1; 34258052Shibler } 34357311Shibler while (--cc >= 0) 34457311Shibler iteputchar(getc(&tp->t_outq), tp->t_dev); 34558052Shibler if (hadcursor) { 34658052Shibler ip->flags |= ITE_CURSORON; 34758052Shibler ite_drawcursor(ip, ip->isw); 34858052Shibler } 34957311Shibler if (hiwat) { 35057311Shibler tp->t_state |= TS_TIMEOUT; 35157311Shibler timeout(iterestart, tp, 1); 35257311Shibler } 35341480Smckusick } 35441480Smckusick tp->t_state &= ~TS_BUSY; 35541480Smckusick splx(s); 35641480Smckusick } 35741480Smckusick 35841480Smckusick itefilter(stat, c) 359*65645Sbostic register char stat, c; 36041480Smckusick { 36141480Smckusick static int capsmode = 0; 36241480Smckusick static int metamode = 0; 36341480Smckusick register char code, *str; 36441480Smckusick 36541480Smckusick if (kbd_tty == NULL) 36641480Smckusick return; 36741480Smckusick 36841480Smckusick switch (c & 0xFF) { 36941480Smckusick case KBD_CAPSLOCK: 37041480Smckusick capsmode = !capsmode; 37141480Smckusick return; 37241480Smckusick 37341480Smckusick case KBD_EXT_LEFT_DOWN: 37441480Smckusick case KBD_EXT_RIGHT_DOWN: 37541480Smckusick metamode = 1; 37641480Smckusick return; 37741480Smckusick 37841480Smckusick case KBD_EXT_LEFT_UP: 37941480Smckusick case KBD_EXT_RIGHT_UP: 38041480Smckusick metamode = 0; 38141480Smckusick return; 38241480Smckusick } 38341480Smckusick 38441480Smckusick c &= KBD_CHARMASK; 38541480Smckusick switch ((stat>>KBD_SSHIFT) & KBD_SMASK) { 38641480Smckusick 38741480Smckusick case KBD_KEY: 38841480Smckusick if (!capsmode) { 38941480Smckusick code = kbd_keymap[c]; 39041480Smckusick break; 39141480Smckusick } 392*65645Sbostic /* FALLTHROUGH */ 39341480Smckusick 39441480Smckusick case KBD_SHIFT: 39541480Smckusick code = kbd_shiftmap[c]; 39641480Smckusick break; 39741480Smckusick 39841480Smckusick case KBD_CTRL: 39941480Smckusick code = kbd_ctrlmap[c]; 40041480Smckusick break; 40141480Smckusick 40241480Smckusick case KBD_CTRLSHIFT: 40341480Smckusick code = kbd_ctrlshiftmap[c]; 40441480Smckusick break; 40541480Smckusick } 40641480Smckusick 40741480Smckusick if (code == NULL && (str = kbd_stringmap[c]) != NULL) { 40841480Smckusick while (*str) 40941480Smckusick (*linesw[kbd_tty->t_line].l_rint)(*str++, kbd_tty); 41041480Smckusick } else { 41141480Smckusick if (metamode) 41241480Smckusick code |= 0x80; 41341480Smckusick (*linesw[kbd_tty->t_line].l_rint)(code, kbd_tty); 41441480Smckusick } 41541480Smckusick } 41641480Smckusick 41741480Smckusick iteputchar(c, dev) 41841480Smckusick register int c; 41941480Smckusick dev_t dev; 42041480Smckusick { 42141480Smckusick int unit = UNIT(dev); 42241480Smckusick register struct ite_softc *ip = &ite_softc[unit]; 42353923Shibler register struct itesw *sp = ip->isw; 42441480Smckusick register int n; 42541480Smckusick 42641480Smckusick if ((ip->flags & (ITE_ACTIVE|ITE_INGRF)) != ITE_ACTIVE) 42741480Smckusick return; 42841480Smckusick 42941480Smckusick if (ip->escape) { 43041480Smckusick doesc: 43141480Smckusick switch (ip->escape) { 43241480Smckusick 43341480Smckusick case '&': /* Next can be a,d, or s */ 43441480Smckusick if (ip->fpd++) { 43541480Smckusick ip->escape = c; 43641480Smckusick ip->fpd = 0; 43741480Smckusick } 43841480Smckusick return; 43941480Smckusick 44041480Smckusick case 'a': /* cursor change */ 44141480Smckusick switch (c) { 44241480Smckusick 44341480Smckusick case 'Y': /* Only y coord. */ 44455069Spendry ip->cury = min(ip->pos, ip->rows-1); 44541480Smckusick ip->pos = 0; 44641480Smckusick ip->escape = 0; 44757311Shibler ite_movecursor(ip, sp); 44841480Smckusick clr_attr(ip, ATTR_INV); 44941480Smckusick break; 45041480Smckusick 45141480Smckusick case 'y': /* y coord first */ 45255069Spendry ip->cury = min(ip->pos, ip->rows-1); 45341480Smckusick ip->pos = 0; 45441480Smckusick ip->fpd = 0; 45541480Smckusick break; 45641480Smckusick 45741480Smckusick case 'C': /* x coord */ 45855069Spendry ip->curx = min(ip->pos, ip->cols-1); 45941480Smckusick ip->pos = 0; 46041480Smckusick ip->escape = 0; 46157311Shibler ite_movecursor(ip, sp); 46241480Smckusick clr_attr(ip, ATTR_INV); 46341480Smckusick break; 46441480Smckusick 46541480Smckusick default: /* Possibly a 3 digit number. */ 46641480Smckusick if (c >= '0' && c <= '9' && ip->fpd < 3) { 46741480Smckusick ip->pos = ip->pos * 10 + (c - '0'); 46841480Smckusick ip->fpd++; 46941480Smckusick } else { 47041480Smckusick ip->pos = 0; 47141480Smckusick ip->escape = 0; 47241480Smckusick } 47341480Smckusick break; 47441480Smckusick } 47541480Smckusick return; 47641480Smckusick 47741480Smckusick case 'd': /* attribute change */ 47841480Smckusick switch (c) { 47941480Smckusick 48041480Smckusick case 'B': 48141480Smckusick set_attr(ip, ATTR_INV); 48241480Smckusick break; 48341480Smckusick case 'D': 48441480Smckusick /* XXX: we don't do anything for underline */ 48541480Smckusick set_attr(ip, ATTR_UL); 48641480Smckusick break; 48741480Smckusick case '@': 48841480Smckusick clr_attr(ip, ATTR_ALL); 48941480Smckusick break; 49041480Smckusick } 49141480Smckusick ip->escape = 0; 49241480Smckusick return; 49341480Smckusick 49441480Smckusick case 's': /* keypad control */ 49541480Smckusick switch (ip->fpd) { 49641480Smckusick 49741480Smckusick case 0: 49841480Smckusick ip->hold = c; 49941480Smckusick ip->fpd++; 50041480Smckusick return; 50141480Smckusick 50241480Smckusick case 1: 50341480Smckusick if (c == 'A') { 50441480Smckusick switch (ip->hold) { 50541480Smckusick 50641480Smckusick case '0': 50741480Smckusick clr_attr(ip, ATTR_KPAD); 50841480Smckusick break; 50941480Smckusick case '1': 51041480Smckusick set_attr(ip, ATTR_KPAD); 51141480Smckusick break; 51241480Smckusick } 51341480Smckusick } 51441480Smckusick ip->hold = 0; 51541480Smckusick } 51641480Smckusick ip->escape = 0; 51741480Smckusick return; 51841480Smckusick 51941480Smckusick case 'i': /* back tab */ 52041480Smckusick if (ip->curx > TABSIZE) { 52141480Smckusick n = ip->curx - (ip->curx & (TABSIZE - 1)); 52241480Smckusick ip->curx -= n; 52341480Smckusick } else 52441480Smckusick ip->curx = 0; 52557311Shibler ite_movecursor(ip, sp); 52641480Smckusick ip->escape = 0; 52741480Smckusick return; 52841480Smckusick 52941480Smckusick case '3': /* clear all tabs */ 53041480Smckusick goto ignore; 53141480Smckusick 53241480Smckusick case 'K': /* clear_eol */ 53341480Smckusick ite_clrtoeol(ip, sp, ip->cury, ip->curx); 53441480Smckusick ip->escape = 0; 53541480Smckusick return; 53641480Smckusick 53741480Smckusick case 'J': /* clear_eos */ 53841480Smckusick ite_clrtoeos(ip, sp); 53941480Smckusick ip->escape = 0; 54041480Smckusick return; 54141480Smckusick 54241480Smckusick case 'B': /* cursor down 1 line */ 54341480Smckusick if (++ip->cury == ip->rows) { 54441480Smckusick --ip->cury; 54557311Shibler ite_erasecursor(ip, sp); 54641480Smckusick (*sp->ite_scroll)(ip, 1, 0, 1, SCROLL_UP); 54741480Smckusick ite_clrtoeol(ip, sp, ip->cury, 0); 54841480Smckusick } 54941480Smckusick else 55057311Shibler ite_movecursor(ip, sp); 55141480Smckusick clr_attr(ip, ATTR_INV); 55241480Smckusick ip->escape = 0; 55341480Smckusick return; 55441480Smckusick 55541480Smckusick case 'C': /* cursor forward 1 char */ 55641480Smckusick ip->escape = 0; 55741480Smckusick itecheckwrap(ip, sp); 55841480Smckusick return; 55941480Smckusick 56041480Smckusick case 'A': /* cursor up 1 line */ 56141480Smckusick if (ip->cury > 0) { 56241480Smckusick ip->cury--; 56357311Shibler ite_movecursor(ip, sp); 56441480Smckusick } 56541480Smckusick ip->escape = 0; 56641480Smckusick clr_attr(ip, ATTR_INV); 56741480Smckusick return; 56841480Smckusick 56941480Smckusick case 'P': /* delete character */ 57041480Smckusick ite_dchar(ip, sp); 57141480Smckusick ip->escape = 0; 57241480Smckusick return; 57341480Smckusick 57441480Smckusick case 'M': /* delete line */ 57541480Smckusick ite_dline(ip, sp); 57641480Smckusick ip->escape = 0; 57741480Smckusick return; 57841480Smckusick 57941480Smckusick case 'Q': /* enter insert mode */ 58041480Smckusick ip->imode = 1; 58141480Smckusick ip->escape = 0; 58241480Smckusick return; 58341480Smckusick 58441480Smckusick case 'R': /* exit insert mode */ 58541480Smckusick ip->imode = 0; 58641480Smckusick ip->escape = 0; 58741480Smckusick return; 58841480Smckusick 58941480Smckusick case 'L': /* insert blank line */ 59041480Smckusick ite_iline(ip, sp); 59141480Smckusick ip->escape = 0; 59241480Smckusick return; 59341480Smckusick 59441480Smckusick case 'h': /* home key */ 59541480Smckusick ip->cury = ip->curx = 0; 59657311Shibler ite_movecursor(ip, sp); 59741480Smckusick ip->escape = 0; 59841480Smckusick return; 59941480Smckusick 60041480Smckusick case 'D': /* left arrow key */ 60141480Smckusick if (ip->curx > 0) { 60241480Smckusick ip->curx--; 60357311Shibler ite_movecursor(ip, sp); 60441480Smckusick } 60541480Smckusick ip->escape = 0; 60641480Smckusick return; 60741480Smckusick 60841480Smckusick case '1': /* set tab in all rows */ 60941480Smckusick goto ignore; 61041480Smckusick 61141480Smckusick case ESC: 61241480Smckusick if ((ip->escape = c) == ESC) 61341480Smckusick break; 61441480Smckusick ip->fpd = 0; 61541480Smckusick goto doesc; 61641480Smckusick 61741480Smckusick default: 61841480Smckusick ignore: 61941480Smckusick ip->escape = 0; 62041480Smckusick return; 62141480Smckusick 62241480Smckusick } 62341480Smckusick } 62441480Smckusick 62541480Smckusick switch (c &= 0x7F) { 62641480Smckusick 62741480Smckusick case '\n': 62841480Smckusick 62941480Smckusick if (++ip->cury == ip->rows) { 63041480Smckusick --ip->cury; 63157311Shibler ite_erasecursor(ip, sp); 63241480Smckusick (*sp->ite_scroll)(ip, 1, 0, 1, SCROLL_UP); 63341480Smckusick ite_clrtoeol(ip, sp, ip->cury, 0); 63457311Shibler } else 63557311Shibler ite_movecursor(ip, sp); 63641480Smckusick clr_attr(ip, ATTR_INV); 63741480Smckusick break; 63841480Smckusick 63941480Smckusick case '\r': 64041480Smckusick if (ip->curx) { 64141480Smckusick ip->curx = 0; 64257311Shibler ite_movecursor(ip, sp); 64341480Smckusick } 64441480Smckusick break; 64541480Smckusick 64641480Smckusick case '\b': 64741480Smckusick if (--ip->curx < 0) 64841480Smckusick ip->curx = 0; 64941480Smckusick else 65057311Shibler ite_movecursor(ip, sp); 65141480Smckusick break; 65241480Smckusick 65341480Smckusick case '\t': 65441480Smckusick if (ip->curx < TABEND(unit)) { 65541480Smckusick n = TABSIZE - (ip->curx & (TABSIZE - 1)); 65641480Smckusick ip->curx += n; 65757311Shibler ite_movecursor(ip, sp); 65841480Smckusick } else 65941480Smckusick itecheckwrap(ip, sp); 66041480Smckusick break; 66141480Smckusick 66241480Smckusick case CTRL('G'): 66341480Smckusick if (&ite_tty[unit] == kbd_tty) 66453923Shibler kbdbell(unit); 66541480Smckusick break; 66641480Smckusick 66741480Smckusick case ESC: 66841480Smckusick ip->escape = ESC; 66941480Smckusick break; 67041480Smckusick 67141480Smckusick default: 67241480Smckusick if (c < ' ' || c == DEL) 67341480Smckusick break; 67441480Smckusick if (ip->imode) 67541480Smckusick ite_ichar(ip, sp); 67641480Smckusick if ((ip->attribute & ATTR_INV) || attrtest(ip, ATTR_INV)) { 67741480Smckusick attrset(ip, ATTR_INV); 67841480Smckusick (*sp->ite_putc)(ip, c, ip->cury, ip->curx, ATTR_INV); 67957311Shibler } else 68041480Smckusick (*sp->ite_putc)(ip, c, ip->cury, ip->curx, ATTR_NOR); 68157311Shibler ite_drawcursor(ip, sp); 68241480Smckusick itecheckwrap(ip, sp); 68341480Smckusick break; 68441480Smckusick } 68541480Smckusick } 68641480Smckusick 68741480Smckusick itecheckwrap(ip, sp) 68841480Smckusick register struct ite_softc *ip; 68941480Smckusick register struct itesw *sp; 69041480Smckusick { 69141480Smckusick if (++ip->curx == ip->cols) { 69241480Smckusick ip->curx = 0; 69341480Smckusick clr_attr(ip, ATTR_INV); 69441480Smckusick if (++ip->cury == ip->rows) { 69541480Smckusick --ip->cury; 69657311Shibler ite_erasecursor(ip, sp); 69741480Smckusick (*sp->ite_scroll)(ip, 1, 0, 1, SCROLL_UP); 69841480Smckusick ite_clrtoeol(ip, sp, ip->cury, 0); 69941480Smckusick return; 70041480Smckusick } 70141480Smckusick } 70257311Shibler ite_movecursor(ip, sp); 70341480Smckusick } 70441480Smckusick 70541480Smckusick ite_dchar(ip, sp) 70641480Smckusick register struct ite_softc *ip; 70741480Smckusick register struct itesw *sp; 70841480Smckusick { 70957311Shibler if (ip->curx < ip->cols - 1) { 71057311Shibler ite_erasecursor(ip, sp); 71157311Shibler (*sp->ite_scroll)(ip, ip->cury, ip->curx + 1, 1, SCROLL_LEFT); 71257311Shibler attrmov(ip, ip->cury, ip->curx + 1, ip->cury, ip->curx, 71357311Shibler 1, ip->cols - ip->curx - 1); 71457311Shibler } 71541480Smckusick attrclr(ip, ip->cury, ip->cols - 1, 1, 1); 71641480Smckusick (*sp->ite_putc)(ip, ' ', ip->cury, ip->cols - 1, ATTR_NOR); 71757311Shibler ite_drawcursor(ip, sp); 71841480Smckusick } 71941480Smckusick 72041480Smckusick ite_ichar(ip, sp) 72141480Smckusick register struct ite_softc *ip; 72241480Smckusick register struct itesw *sp; 72341480Smckusick { 72457311Shibler if (ip->curx < ip->cols - 1) { 72557311Shibler ite_erasecursor(ip, sp); 72657311Shibler (*sp->ite_scroll)(ip, ip->cury, ip->curx, 1, SCROLL_RIGHT); 72757311Shibler attrmov(ip, ip->cury, ip->curx, ip->cury, ip->curx + 1, 72857311Shibler 1, ip->cols - ip->curx - 1); 72957311Shibler } 73041480Smckusick attrclr(ip, ip->cury, ip->curx, 1, 1); 73141480Smckusick (*sp->ite_putc)(ip, ' ', ip->cury, ip->curx, ATTR_NOR); 73257311Shibler ite_drawcursor(ip, sp); 73341480Smckusick } 73441480Smckusick 73541480Smckusick ite_dline(ip, sp) 73641480Smckusick register struct ite_softc *ip; 73741480Smckusick register struct itesw *sp; 73841480Smckusick { 73957311Shibler if (ip->cury < ip->rows - 1) { 74057311Shibler ite_erasecursor(ip, sp); 74157311Shibler (*sp->ite_scroll)(ip, ip->cury + 1, 0, 1, SCROLL_UP); 74257311Shibler attrmov(ip, ip->cury + 1, 0, ip->cury, 0, 74357311Shibler ip->rows - ip->cury - 1, ip->cols); 74457311Shibler } 74541480Smckusick ite_clrtoeol(ip, sp, ip->rows - 1, 0); 74641480Smckusick } 74741480Smckusick 74841480Smckusick ite_iline(ip, sp) 74941480Smckusick register struct ite_softc *ip; 75041480Smckusick register struct itesw *sp; 75141480Smckusick { 75257311Shibler if (ip->cury < ip->rows - 1) { 75357311Shibler ite_erasecursor(ip, sp); 75457311Shibler (*sp->ite_scroll)(ip, ip->cury, 0, 1, SCROLL_DOWN); 75557311Shibler attrmov(ip, ip->cury, 0, ip->cury + 1, 0, 75657311Shibler ip->rows - ip->cury - 1, ip->cols); 75757311Shibler } 75841480Smckusick ite_clrtoeol(ip, sp, ip->cury, 0); 75941480Smckusick } 76041480Smckusick 76141480Smckusick ite_clrtoeol(ip, sp, y, x) 76241480Smckusick register struct ite_softc *ip; 76341480Smckusick register struct itesw *sp; 76441480Smckusick register int y, x; 76541480Smckusick { 76641480Smckusick (*sp->ite_clear)(ip, y, x, 1, ip->cols - x); 76741480Smckusick attrclr(ip, y, x, 1, ip->cols - x); 76857311Shibler ite_drawcursor(ip, sp); 76941480Smckusick } 77041480Smckusick 77141480Smckusick ite_clrtoeos(ip, sp) 77241480Smckusick register struct ite_softc *ip; 77341480Smckusick register struct itesw *sp; 77441480Smckusick { 77541480Smckusick (*sp->ite_clear)(ip, ip->cury, 0, ip->rows - ip->cury, ip->cols); 77641480Smckusick attrclr(ip, ip->cury, 0, ip->rows - ip->cury, ip->cols); 77757311Shibler ite_drawcursor(ip, sp); 77841480Smckusick } 77941480Smckusick 78041480Smckusick /* 78141480Smckusick * Console functions 78241480Smckusick */ 78356504Sbostic #include <hp/dev/cons.h> 78453923Shibler #ifdef hp300 78556504Sbostic #include <hp/dev/grfreg.h> 78653923Shibler #endif 78741480Smckusick 78841480Smckusick #ifdef DEBUG 78941480Smckusick /* 79041480Smckusick * Minimum ITE number at which to start looking for a console. 79141480Smckusick * Setting to 0 will do normal search, 1 will skip first ITE device, 79241480Smckusick * NITE will skip ITEs and use serial port. 79341480Smckusick */ 79441480Smckusick int whichconsole = 0; 79541480Smckusick #endif 79641480Smckusick 79741480Smckusick itecnprobe(cp) 79841480Smckusick struct consdev *cp; 79941480Smckusick { 80041480Smckusick register struct ite_softc *ip; 80153923Shibler int i, sw, maj, unit, pri; 80241480Smckusick 80341480Smckusick /* locate the major number */ 80441480Smckusick for (maj = 0; maj < nchrdev; maj++) 80541480Smckusick if (cdevsw[maj].d_open == iteopen) 80641480Smckusick break; 80741480Smckusick 80841480Smckusick /* urk! */ 80941480Smckusick grfconfig(); 81041480Smckusick 81141480Smckusick /* check all the individual displays and find the best */ 81241480Smckusick unit = -1; 81341480Smckusick pri = CN_DEAD; 81441480Smckusick for (i = 0; i < NITE; i++) { 81541480Smckusick struct grf_softc *gp = &grf_softc[i]; 81641480Smckusick 81741480Smckusick ip = &ite_softc[i]; 81841480Smckusick if ((gp->g_flags & GF_ALIVE) == 0) 81941480Smckusick continue; 82041480Smckusick ip->flags = (ITE_ALIVE|ITE_CONSOLE); 82141480Smckusick 82253923Shibler /* locate the proper switch table. */ 82353923Shibler for (sw = 0; sw < nitesw; sw++) 82453923Shibler if (itesw[sw].ite_hwid == gp->g_sw->gd_hwid) 82553923Shibler break; 82641480Smckusick 82753923Shibler if (sw == nitesw) 82853923Shibler continue; 82941480Smckusick #ifdef DEBUG 83041480Smckusick if (i < whichconsole) 83141480Smckusick continue; 83241480Smckusick #endif 83353923Shibler ip->isw = &itesw[sw]; 83453923Shibler ip->grf = gp; 83553923Shibler #ifdef hp300 83641480Smckusick if ((int)gp->g_display.gd_regaddr == GRFIADDR) { 83741480Smckusick pri = CN_INTERNAL; 83841480Smckusick unit = i; 83941480Smckusick } else if (unit < 0) { 84041480Smckusick pri = CN_NORMAL; 84141480Smckusick unit = i; 84241480Smckusick } 84353923Shibler #endif 84453923Shibler #ifdef hp800 84553923Shibler /* XXX use the first one for now */ 84653923Shibler if (unit < 0) { 84753923Shibler pri = CN_INTERNAL; 84853923Shibler unit = i; 84953923Shibler } 85053923Shibler #endif 85141480Smckusick } 85241480Smckusick 85341480Smckusick /* initialize required fields */ 85441480Smckusick cp->cn_dev = makedev(maj, unit); 85541480Smckusick cp->cn_tp = &ite_tty[unit]; 85641480Smckusick cp->cn_pri = pri; 85741480Smckusick } 85841480Smckusick 85941480Smckusick itecninit(cp) 86041480Smckusick struct consdev *cp; 86141480Smckusick { 86241480Smckusick int unit = UNIT(cp->cn_dev); 86341480Smckusick struct ite_softc *ip = &ite_softc[unit]; 86441480Smckusick 86541480Smckusick ip->attrbuf = console_attributes; 86641480Smckusick iteinit(cp->cn_dev); 86741480Smckusick ip->flags |= (ITE_ACTIVE|ITE_ISCONS); 86841480Smckusick kbd_tty = &ite_tty[unit]; 86941480Smckusick } 87041480Smckusick 87141480Smckusick /*ARGSUSED*/ 87241480Smckusick itecngetc(dev) 87341480Smckusick dev_t dev; 87441480Smckusick { 87541480Smckusick register int c; 87641480Smckusick int stat; 87741480Smckusick 87853923Shibler c = kbdgetc(0, &stat); /* XXX always read from keyboard 0 for now */ 87941480Smckusick switch ((stat >> KBD_SSHIFT) & KBD_SMASK) { 88041480Smckusick case KBD_SHIFT: 88141480Smckusick c = kbd_shiftmap[c & KBD_CHARMASK]; 88241480Smckusick break; 88341480Smckusick case KBD_CTRL: 88441480Smckusick c = kbd_ctrlmap[c & KBD_CHARMASK]; 88541480Smckusick break; 88641480Smckusick case KBD_KEY: 88741480Smckusick c = kbd_keymap[c & KBD_CHARMASK]; 88841480Smckusick break; 88941480Smckusick default: 89041480Smckusick c = 0; 89141480Smckusick break; 89241480Smckusick } 89341480Smckusick return(c); 89441480Smckusick } 89541480Smckusick 89641480Smckusick itecnputc(dev, c) 89741480Smckusick dev_t dev; 89841480Smckusick int c; 89941480Smckusick { 90041480Smckusick static int paniced = 0; 90141480Smckusick struct ite_softc *ip = &ite_softc[UNIT(dev)]; 90241480Smckusick 90341480Smckusick if (panicstr && !paniced && 90441480Smckusick (ip->flags & (ITE_ACTIVE|ITE_INGRF)) != ITE_ACTIVE) { 90541480Smckusick (void) iteon(dev, 3); 90641480Smckusick paniced = 1; 90741480Smckusick } 90841480Smckusick iteputchar(c, dev); 90941480Smckusick } 91041480Smckusick #endif 911