156813Sralph /*- 2*63205Sbostic * Copyright (c) 1992, 1993 3*63205Sbostic * The Regents of the University of California. All rights reserved. 456813Sralph * 556813Sralph * This code is derived from software contributed to Berkeley by 656813Sralph * Ralph Campbell and Rick Macklem. 756813Sralph * 856813Sralph * %sccs.include.redist.c% 956813Sralph * 10*63205Sbostic * @(#)dtop.c 8.1 (Berkeley) 06/10/93 1156813Sralph */ 1256813Sralph 1356813Sralph /* 1456813Sralph * Mach Operating System 1556813Sralph * Copyright (c) 1991,1990,1989 Carnegie Mellon University 1656813Sralph * All Rights Reserved. 1756813Sralph * 1856813Sralph * Permission to use, copy, modify and distribute this software and its 1956813Sralph * documentation is hereby granted, provided that both the copyright 2056813Sralph * notice and this permission notice appear in all copies of the 2156813Sralph * software, derivative works or modified versions, and any portions 2256813Sralph * thereof, and that both notices appear in supporting documentation. 2356813Sralph * 2456813Sralph * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS 2556813Sralph * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR 2656813Sralph * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 2756813Sralph * 2856813Sralph * Carnegie Mellon requests users of this software to return to 2956813Sralph * 3056813Sralph * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 3156813Sralph * School of Computer Science 3256813Sralph * Carnegie Mellon University 3356813Sralph * Pittsburgh PA 15213-3890 3456813Sralph * 3556813Sralph * any improvements or extensions that they make and grant Carnegie the 3656813Sralph * rights to redistribute these changes. 3756813Sralph */ 3856813Sralph /* 3956813Sralph * Author: Alessandro Forin, Carnegie Mellon University 4056813Sralph * 4156813Sralph * Hardware-level operations for the Desktop serial line 4256813Sralph * bus (i2c aka ACCESS). 4356813Sralph */ 4457234Sralph /************************************************************ 4557234Sralph Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts, 4657234Sralph and the Massachusetts Institute of Technology, Cambridge, Massachusetts. 4756813Sralph 4857234Sralph All Rights Reserved 4957234Sralph 5057234Sralph Permission to use, copy, modify, and distribute this software and its 5157234Sralph documentation for any purpose and without fee is hereby granted, 5257234Sralph provided that the above copyright notice appear in all copies and that 5357234Sralph both that copyright notice and this permission notice appear in 5457234Sralph supporting documentation, and that the names of Digital or MIT not be 5557234Sralph used in advertising or publicity pertaining to distribution of the 5657234Sralph software without specific, written prior permission. 5757234Sralph 5857234Sralph DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 5957234Sralph ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 6057234Sralph DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 6157234Sralph ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 6257234Sralph WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 6357234Sralph ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 6457234Sralph SOFTWARE. 6557234Sralph 6657234Sralph ********************************************************/ 6757234Sralph 6856813Sralph #include <dtop.h> 6956813Sralph #if NDTOP > 0 7056813Sralph #include <sys/param.h> 7156813Sralph #include <sys/systm.h> 7256813Sralph #include <sys/ioctl.h> 7356813Sralph #include <sys/tty.h> 7456813Sralph #include <sys/proc.h> 7556813Sralph #include <sys/map.h> 7656813Sralph #include <sys/buf.h> 7756813Sralph #include <sys/conf.h> 7856813Sralph #include <sys/file.h> 7956813Sralph #include <sys/uio.h> 8056813Sralph #include <sys/kernel.h> 8156813Sralph #include <sys/syslog.h> 8256813Sralph 8356813Sralph #include <machine/pmioctl.h> 8456813Sralph #include <machine/machConst.h> 8556813Sralph #include <machine/dc7085cons.h> 8656813Sralph 8756813Sralph #include <pmax/pmax/pmaxtype.h> 8856813Sralph #include <pmax/pmax/maxine.h> 8956813Sralph #include <pmax/pmax/asic.h> 9056813Sralph 9156813Sralph #include <pmax/dev/device.h> 9256813Sralph #include <pmax/dev/dtopreg.h> 9356813Sralph #include <pmax/dev/fbreg.h> 9456813Sralph 9556813Sralph extern int pmax_boardtype; 9656813Sralph 9756813Sralph extern int ttrstrt __P((void *)); 9858793Sralph void dtop_keyboard_repeat __P((void *)); 9956813Sralph int dtop_null_device_handler __P((dtop_device_t, dtop_message_t, int, int)); 10056813Sralph int dtop_locator_handler __P((dtop_device_t, dtop_message_t, int, int)); 10156813Sralph int dtop_keyboard_handler __P((dtop_device_t, dtop_message_t, int, int)); 10256813Sralph int dtopparam __P((struct tty *, struct termios *)); 10356813Sralph int dtopstop __P((struct tty *, int)); 10456813Sralph void dtopstart __P((struct tty *)); 10556813Sralph void dtopKBDPutc __P((dev_t, int)); 10656813Sralph 10756813Sralph struct tty dtop_tty[NDTOP]; 10856813Sralph void (*dtopDivertXInput)(); /* X windows keyboard input routine */ 10956813Sralph void (*dtopMouseEvent)(); /* X windows mouse motion event routine */ 11056813Sralph void (*dtopMouseButtons)(); /* X windows mouse buttons event routine */ 11156813Sralph 11256813Sralph #define DTOP_MAX_POLL 0x7fff /* about half a sec */ 11356813Sralph 11456813Sralph typedef volatile unsigned int *data_reg_t; /* uC */ 11556813Sralph #define DTOP_GET_BYTE(data) (((*(data)) >> 8) & 0xff) 11656813Sralph #define DTOP_PUT_BYTE(data,c) { *(data) = (c) << 8; } 11756813Sralph 11856813Sralph typedef volatile unsigned int *poll_reg_t; /* SIR */ 11956813Sralph #define DTOP_RX_AVAIL(poll) (*(poll) & 1) 12056813Sralph #define DTOP_TX_AVAIL(poll) (*(poll) & 2) 12156813Sralph 12256813Sralph #define GET_SHORT(b0,b1) (((b0)<<8)|(b1)) 12356813Sralph 12456813Sralph /* 12556813Sralph * Driver status 12656813Sralph */ 12756813Sralph struct dtop_softc { 12856813Sralph data_reg_t data; 12956813Sralph poll_reg_t poll; 13056813Sralph char polling_mode; 13156813Sralph char probed_once; 13256813Sralph short bad_pkts; 13356813Sralph 13456813Sralph struct dtop_ds { 13556813Sralph int (*handler)(); 13656813Sralph dtop_device status; 13756813Sralph } device[(DTOP_ADDR_DEFAULT - DTOP_ADDR_FIRST) >> 1]; 13856813Sralph 13956813Sralph # define DTOP_DEVICE_NO(address) (((address)-DTOP_ADDR_FIRST)>>1) 14056813Sralph 14156813Sralph } dtop_softc[NDTOP]; 14256813Sralph 14356813Sralph typedef struct dtop_softc *dtop_softc_t; 14456813Sralph struct tty dtop_tty[NDTOP]; 14556813Sralph 14656813Sralph /* 14757234Sralph * lk201 keyboard divisions and up/down mode key bitmap. 14857234Sralph */ 14957234Sralph #define NUMDIVS 14 15057234Sralph static u_char divbeg[NUMDIVS] = {0xbf, 0x91, 0xbc, 0xbd, 0xb0, 0xad, 0xa6, 15157234Sralph 0xa9, 0x88, 0x56, 0x63, 0x6f, 0x7b, 0x7e}; 15257234Sralph static u_char divend[NUMDIVS] = {0xff, 0xa5, 0xbc, 0xbe, 0xb2, 0xaf, 0xa8, 15357234Sralph 0xac, 0x90, 0x62, 0x6e, 0x7a, 0x7d, 0x87}; 15457234Sralph /* 15557234Sralph * Initial defaults, groups 5 and 6 are up/down 15657234Sralph */ 15757234Sralph static u_long keymodes[8] = {0, 0, 0, 0, 0, 0x0003e000, 0, 0}; 15857234Sralph 15957234Sralph /* 16056813Sralph * Definition of the driver for the auto-configuration program. 16156813Sralph */ 16256813Sralph int dtopprobe(); 16356813Sralph void dtopintr(); 16456813Sralph struct driver dtopdriver = { 16556813Sralph "dtop", dtopprobe, 0, 0, dtopintr, 16656813Sralph }; 16756813Sralph 16856813Sralph dtopprobe(cp) 16956813Sralph struct pmax_ctlr *cp; 17056813Sralph { 17156813Sralph register struct tty *tp; 17256813Sralph register int cntr; 17356813Sralph int dtopunit = cp->pmax_unit, i, s; 17456813Sralph dtop_softc_t dtop; 17556813Sralph 17656813Sralph if (dtopunit >= NDTOP) 17756813Sralph return (0); 17856813Sralph if (badaddr(cp->pmax_addr, 2)) 17956813Sralph return (0); 18056813Sralph dtop = &dtop_softc[dtopunit]; 18156813Sralph 18256813Sralph dtop->poll = (poll_reg_t)MACH_PHYS_TO_UNCACHED(XINE_REG_INTR); 18356813Sralph dtop->data = (data_reg_t)cp->pmax_addr; 18456813Sralph 18556813Sralph for (i = 0; i < DTOP_MAX_DEVICES; i++) 18656813Sralph dtop->device[i].handler = dtop_null_device_handler; 18756813Sralph 18856813Sralph /* a lot more needed here, fornow: */ 18956813Sralph dtop->device[DTOP_DEVICE_NO(0x6a)].handler = dtop_locator_handler; 19056813Sralph dtop->device[DTOP_DEVICE_NO(0x6c)].handler = dtop_keyboard_handler; 19156813Sralph dtop->device[DTOP_DEVICE_NO(0x6c)].status.keyboard.k_ar_state = 19256813Sralph K_AR_IDLE; 19356813Sralph 19457234Sralph dtop->probed_once = 1; 19557234Sralph printf("dtop%d at nexus0 csr 0x%x priority %d\n", 19657234Sralph cp->pmax_unit, cp->pmax_addr, cp->pmax_pri); 19756813Sralph return (1); 19856813Sralph } 19956813Sralph 20056813Sralph dtopopen(dev, flag, mode, p) 20156813Sralph dev_t dev; 20256813Sralph int flag, mode; 20356813Sralph struct proc *p; 20456813Sralph { 20556813Sralph register struct tty *tp; 20656813Sralph register int unit; 20756813Sralph int s, error = 0; 20856813Sralph 20956813Sralph unit = minor(dev); 21056813Sralph if (unit >= NDTOP) 21156813Sralph return (ENXIO); 21256813Sralph tp = &dtop_tty[unit]; 21356813Sralph tp->t_oproc = dtopstart; 21456813Sralph tp->t_param = dtopparam; 21556813Sralph tp->t_dev = dev; 21656813Sralph if ((tp->t_state & TS_ISOPEN) == 0) { 21756813Sralph tp->t_state |= TS_WOPEN; 21856813Sralph ttychars(tp); 21956813Sralph if (tp->t_ispeed == 0) { 22056813Sralph tp->t_iflag = TTYDEF_IFLAG; 22156813Sralph tp->t_oflag = TTYDEF_OFLAG; 22256813Sralph tp->t_cflag = TTYDEF_CFLAG; 22356813Sralph tp->t_lflag = TTYDEF_LFLAG; 22456813Sralph tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; 22556813Sralph } 22656813Sralph (void) dtopparam(tp, &tp->t_termios); 22756813Sralph ttsetwater(tp); 22856813Sralph } else if ((tp->t_state & TS_XCLUDE) && curproc->p_ucred->cr_uid != 0) 22956813Sralph return (EBUSY); 23056813Sralph s = spltty(); 23156813Sralph while (!(flag & O_NONBLOCK) && !(tp->t_cflag & CLOCAL) && 23256813Sralph !(tp->t_state & TS_CARR_ON)) { 23356813Sralph tp->t_state |= TS_WOPEN; 23456813Sralph if (error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH, 23556813Sralph ttopen, 0)) 23656813Sralph break; 23756813Sralph } 23856813Sralph splx(s); 23956813Sralph if (error) 24056813Sralph return (error); 24156813Sralph error = (*linesw[tp->t_line].l_open)(dev, tp); 24256813Sralph return (error); 24356813Sralph } 24456813Sralph 24556813Sralph /*ARGSUSED*/ 24656813Sralph dtopclose(dev, flag, mode, p) 24756813Sralph dev_t dev; 24856813Sralph int flag, mode; 24956813Sralph struct proc *p; 25056813Sralph { 25156813Sralph register struct tty *tp; 25256813Sralph register int unit; 25356813Sralph 25456813Sralph unit = minor(dev); 25556813Sralph tp = &dtop_tty[unit]; 25656813Sralph (*linesw[tp->t_line].l_close)(tp, flag); 25756813Sralph return (ttyclose(tp)); 25856813Sralph } 25956813Sralph 26056813Sralph dtopread(dev, uio, flag) 26156813Sralph dev_t dev; 26256813Sralph struct uio *uio; 26356813Sralph { 26456813Sralph register struct tty *tp; 26556813Sralph 26656813Sralph tp = &dtop_tty[minor(dev)]; 26756813Sralph return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); 26856813Sralph } 26956813Sralph 27056813Sralph dtopwrite(dev, uio, flag) 27156813Sralph dev_t dev; 27256813Sralph struct uio *uio; 27356813Sralph { 27456813Sralph register struct tty *tp; 27556813Sralph 27656813Sralph tp = &dtop_tty[minor(dev)]; 27756813Sralph return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); 27856813Sralph } 27956813Sralph 28056813Sralph /*ARGSUSED*/ 28156813Sralph dtopioctl(dev, cmd, data, flag, p) 28256813Sralph dev_t dev; 28356813Sralph int cmd; 28456813Sralph caddr_t data; 28556813Sralph int flag; 28656813Sralph struct proc *p; 28756813Sralph { 28856813Sralph register struct tty *tp; 28956813Sralph register int unit = minor(dev); 29056813Sralph int error; 29156813Sralph 29256813Sralph tp = &dtop_tty[unit]; 29356813Sralph error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); 29456813Sralph if (error >= 0) 29556813Sralph return (error); 29656813Sralph error = ttioctl(tp, cmd, data, flag); 29756813Sralph if (error >= 0) 29856813Sralph return (error); 29956813Sralph 30056813Sralph switch (cmd) { 30156813Sralph 30256813Sralph case TIOCSBRK: 30356813Sralph ttyoutput(0, tp); 30456813Sralph break; 30556813Sralph 30656813Sralph case TIOCCBRK: 30756813Sralph ttyoutput(0, tp); 30856813Sralph break; 30956813Sralph 31056813Sralph case TIOCMGET: 31156813Sralph *(int *)data = DML_DTR | DML_DSR | DML_CAR; 31256813Sralph break; 31356813Sralph 31456813Sralph default: 31556813Sralph return (ENOTTY); 31656813Sralph } 31756813Sralph return (0); 31856813Sralph } 31956813Sralph 32056813Sralph /* 32156813Sralph * Interrupt routine 32256813Sralph */ 32356813Sralph void 32456813Sralph dtopintr(unit) 32556813Sralph int unit; 32656813Sralph { 32756813Sralph dtop_message msg; 32856813Sralph int devno; 32956813Sralph dtop_softc_t dtop; 33056813Sralph 33156813Sralph dtop = &dtop_softc[unit]; 33256813Sralph if (dtop_get_packet(dtop, &msg) < 0) { 33358793Sralph #ifdef DIAGNOSTIC 33458793Sralph printf("dtop: overrun (or stray)\n"); 33558793Sralph #endif 33658793Sralph /* 33758793Sralph * Ugh! The most common occurrence of a data overrun is upon a 33858793Sralph * key press and the result is a software generated "stuck key". 33958793Sralph * All I can think to do is fake an "all keys up" whenever a 34058793Sralph * data overrun occurs. 34158793Sralph */ 34258793Sralph msg.src_address = 0x6c; 34358793Sralph msg.code.val.len = 1; 34458793Sralph msg.body[0] = DTOP_KBD_EMPTY; 34556813Sralph } 34656813Sralph 34758793Sralph /* 34858793Sralph * If not probed yet, just throw the data away. 34958793Sralph */ 35058793Sralph if (!dtop->probed_once) 35158793Sralph return; 35258793Sralph 35356813Sralph devno = DTOP_DEVICE_NO(msg.src_address); 35456813Sralph if (devno < 0 || devno > 15) 35556813Sralph return; 35656813Sralph (void) (*dtop->device[devno].handler) 35756813Sralph (&dtop->device[devno].status, &msg, 35856813Sralph DTOP_EVENT_RECEIVE_PACKET, 0); 35956813Sralph } 36056813Sralph 36156813Sralph void 36256813Sralph dtopstart(tp) 36356813Sralph register struct tty *tp; 36456813Sralph { 36556813Sralph register int cc; 36656813Sralph int s; 36756813Sralph 36856813Sralph s = spltty(); 36956813Sralph if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) 37056813Sralph goto out; 37156813Sralph if (tp->t_outq.c_cc <= tp->t_lowat) { 37256813Sralph if (tp->t_state & TS_ASLEEP) { 37356813Sralph tp->t_state &= ~TS_ASLEEP; 37456813Sralph wakeup((caddr_t)&tp->t_outq); 37556813Sralph } 37656813Sralph selwakeup(&tp->t_wsel); 37756813Sralph } 37856813Sralph if (tp->t_outq.c_cc == 0) 37956813Sralph goto out; 38056813Sralph /* handle console specially */ 38156813Sralph if (tp == dtop_tty) { 38256813Sralph while (tp->t_outq.c_cc > 0) { 38356813Sralph cc = getc(&tp->t_outq) & 0x7f; 38456813Sralph cnputc(cc); 38556813Sralph } 38656813Sralph /* 38756813Sralph * After we flush the output queue we may need to wake 38856813Sralph * up the process that made the output. 38956813Sralph */ 39056813Sralph if (tp->t_outq.c_cc <= tp->t_lowat) { 39156813Sralph if (tp->t_state & TS_ASLEEP) { 39256813Sralph tp->t_state &= ~TS_ASLEEP; 39356813Sralph wakeup((caddr_t)&tp->t_outq); 39456813Sralph } 39556813Sralph selwakeup(&tp->t_wsel); 39656813Sralph } 39756813Sralph } 39856813Sralph out: 39956813Sralph splx(s); 40056813Sralph } 40156813Sralph 40256813Sralph void 40356813Sralph dtopKBDPutc(dev, c) 40456813Sralph dev_t dev; 40556813Sralph int c; 40656813Sralph { 40757234Sralph register int i; 40857234Sralph static int param = 0, cmd, mod, typ; 40957234Sralph static u_char parms[2]; 41056813Sralph 41156813Sralph /* 41257234Sralph * Emulate the lk201 command codes. 41356813Sralph */ 41457234Sralph if (param == 0) { 41557234Sralph typ = (c & 0x1); 41657234Sralph cmd = ((c >> 3) & 0xf); 41757234Sralph mod = ((c >> 1) & 0x3); 41857234Sralph } else 41957234Sralph parms[param - 1] = (c & 0x7f); 42057234Sralph if (c & 0x80) { 42157234Sralph if (typ) { 42257234Sralph /* 42357234Sralph * A peripheral command code. Someday this driver 42457234Sralph * should know how to send commands to the lk501, 42557234Sralph * but until then this is all essentially a no-op. 42657234Sralph */ 42757234Sralph ; 42857234Sralph } else { 42957234Sralph /* 43057234Sralph * Set modes. These have to be emulated in software. 43157234Sralph */ 43257234Sralph if (cmd > 0 && cmd < 15) { 43357234Sralph cmd--; 43457234Sralph if (mod & 0x2) 43557234Sralph for (i = divbeg[cmd]; i <= divend[cmd]; i++) 43657234Sralph keymodes[i >> 5] |= 43757234Sralph (1 << (i & 0x1f)); 43857234Sralph else 43957234Sralph for (i = divbeg[cmd]; i <= divend[cmd]; i++) 44057234Sralph keymodes[i >> 5] &= 44157234Sralph ~(1 << (i & 0x1f)); 44257234Sralph } 44357234Sralph } 44457234Sralph param = 0; 44557234Sralph } else if (++param > 2) 44657234Sralph param = 2; 44756813Sralph } 44856813Sralph 44956813Sralph /* 45056813Sralph * Take a packet off dtop interface 45156813Sralph * A packet MUST be there, this is not checked for. 45256813Sralph */ 45356813Sralph #define DTOP_ESC_CHAR 0xf8 45456813Sralph dtop_escape(c) 45556813Sralph { 45656813Sralph /* I donno much about this stuff.. */ 45756813Sralph switch (c) { 45856813Sralph case 0xe8: return (0xf8); 45956813Sralph case 0xe9: return (0xf9); 46056813Sralph case 0xea: return (0xfa); 46156813Sralph case 0xeb: return (0xfb); 46256813Sralph default: /* printf("{esc %x}", c); */ 46356813Sralph return (c); 46456813Sralph } 46556813Sralph } 46656813Sralph 46756813Sralph dtop_get_packet(dtop, pkt) 46856813Sralph dtop_softc_t dtop; 46956813Sralph dtop_message_t pkt; 47056813Sralph { 47156813Sralph register poll_reg_t poll; 47256813Sralph register data_reg_t data; 47356813Sralph register int max, i, len; 47456813Sralph register unsigned char c; 47556813Sralph 47656813Sralph poll = dtop->poll; 47756813Sralph data = dtop->data; 47856813Sralph 47956813Sralph /* 48056813Sralph * The interface does not handle us the first byte, 48156813Sralph * which is our address and cannot ever be anything 48256813Sralph * else but 0x50. This is a good thing, it makes 48356813Sralph * the average packet exactly one word long, too. 48456813Sralph */ 48556813Sralph for (max = 0; (max < DTOP_MAX_POLL) && !DTOP_RX_AVAIL(poll); max++) 48657234Sralph DELAY(1); 48756813Sralph if (max == DTOP_MAX_POLL) 48856813Sralph goto bad; 48956813Sralph pkt->src_address = DTOP_GET_BYTE(data); 49056813Sralph 49156813Sralph for (max = 0; (max < DTOP_MAX_POLL) && !DTOP_RX_AVAIL(poll); max++) 49257234Sralph DELAY(1); 49356813Sralph if (max == DTOP_MAX_POLL) 49456813Sralph goto bad; 49556813Sralph pkt->code.bits = DTOP_GET_BYTE(data); 49656813Sralph 49756813Sralph /* 49856813Sralph * Now get data and checksum 49956813Sralph */ 50056813Sralph len = pkt->code.val.len + 1; 50156813Sralph c = 0; 50256813Sralph for (i = 0; i < len; i++) { 50356813Sralph again: 50456813Sralph for (max = 0; (max < DTOP_MAX_POLL) && !DTOP_RX_AVAIL(poll); max++) 50557234Sralph DELAY(1); 50656813Sralph if (max == DTOP_MAX_POLL) 50756813Sralph goto bad; 50856813Sralph if (c == DTOP_ESC_CHAR) { 50956813Sralph c = dtop_escape(DTOP_GET_BYTE(data) & 0xff); 51056813Sralph } else { 51156813Sralph c = DTOP_GET_BYTE(data); 51256813Sralph if (c == DTOP_ESC_CHAR) 51356813Sralph goto again; 51456813Sralph } 51556813Sralph pkt->body[i] = c; 51656813Sralph } 51756813Sralph return (len); 51856813Sralph bad: 51956813Sralph dtop->bad_pkts++; 52056813Sralph return (-1); 52156813Sralph } 52256813Sralph 52356813Sralph /* 52456813Sralph * Get a keyboard char for the console 52556813Sralph */ 52656813Sralph dtopKBDGetc() 52756813Sralph { 52856813Sralph register int c; 52956813Sralph dtop_softc_t dtop; 53056813Sralph 53156813Sralph dtop = &dtop_softc[0]; 53256813Sralph again: 53356813Sralph c = -1; 53456813Sralph 53556813Sralph /* 53656813Sralph * Now check keyboard 53756813Sralph */ 53856813Sralph if (DTOP_RX_AVAIL(dtop->poll)) { 53956813Sralph 54056813Sralph dtop_message msg; 54156813Sralph struct dtop_ds *ds; 54256813Sralph 54356813Sralph if (dtop_get_packet(dtop, &msg) >= 0) { 54456813Sralph 54556813Sralph ds = &dtop->device[DTOP_DEVICE_NO(msg.src_address)]; 54656813Sralph if (ds->handler == dtop_keyboard_handler) { 54756813Sralph 54856813Sralph c = dtop_keyboard_handler( 54956813Sralph &ds->status, &msg, 55056813Sralph DTOP_EVENT_RECEIVE_PACKET, -1); 55156813Sralph 55256813Sralph if (c > 0) return c; 55356813Sralph 55456813Sralph c = -1; 55556813Sralph } 55656813Sralph } 55756813Sralph } 55856813Sralph 55956813Sralph if (c == -1) { 56056813Sralph DELAY(100); 56156813Sralph goto again; 56256813Sralph } 56356813Sralph 56456813Sralph return c; 56556813Sralph } 56656813Sralph 56756813Sralph int 56856813Sralph dtopparam(tp, t) 56956813Sralph struct tty *tp; 57056813Sralph struct termios *t; 57156813Sralph { 57256813Sralph if (tp->t_ispeed == 0) 57356813Sralph ttymodem(tp, 0); 57456813Sralph else 57556813Sralph /* called too early to invoke ttymodem, sigh */ 57656813Sralph tp->t_state |= TS_CARR_ON; 57756813Sralph return (0); 57856813Sralph } 57956813Sralph 58056813Sralph /* 58156813Sralph * Stop output on a line. 58256813Sralph */ 58356813Sralph /*ARGSUSED*/ 58456813Sralph dtopstop(tp, flag) 58556813Sralph register struct tty *tp; 58656813Sralph int flag; 58756813Sralph { 58856813Sralph int s; 58956813Sralph 59056813Sralph s = spltty(); 59156813Sralph if (tp->t_state & TS_BUSY) { 59256813Sralph if (!(tp->t_state & TS_TTSTOP)) 59356813Sralph tp->t_state |= TS_FLUSH; 59456813Sralph } 59556813Sralph splx(s); 59656813Sralph } 59756813Sralph 59856813Sralph /* 59956813Sralph * Default handler function 60056813Sralph */ 60156813Sralph int 60256813Sralph dtop_null_device_handler(dev, msg, event, outc) 60356813Sralph dtop_device_t dev; 60456813Sralph dtop_message_t msg; 60556813Sralph int event; 60656813Sralph int outc; 60756813Sralph { 60856813Sralph /* See if the message was to the default address (powerup) */ 60956813Sralph 61056813Sralph /* Uhmm, donno how to handle this. Drop it */ 61156813Sralph if (event == DTOP_EVENT_RECEIVE_PACKET) 61256813Sralph dev->unknown_report = *msg; 61356813Sralph return 0; 61456813Sralph } 61556813Sralph 61656813Sralph /* 61756813Sralph * Handler for locator devices (mice) 61856813Sralph */ 61956813Sralph int 62056813Sralph dtop_locator_handler(dev, msg, event, outc) 62156813Sralph dtop_device_t dev; 62256813Sralph dtop_message_t msg; 62356813Sralph int event; 62456813Sralph int outc; 62556813Sralph { 62656813Sralph register unsigned short buttons; 62756813Sralph register short coord; 62856813Sralph register int moved = 0; 62956813Sralph static MouseReport currentRep; 63056813Sralph register MouseReport *mrp = ¤tRep; 63156813Sralph 63256813Sralph if (dtopMouseButtons) { 63357234Sralph mrp->state = 0; 63456813Sralph /* 63556813Sralph * Do the position first 63656813Sralph */ 63756813Sralph coord = GET_SHORT(msg->body[2], msg->body[3]); 63857234Sralph if (coord < 0) { 63957234Sralph coord = -coord; 64056813Sralph moved = 1; 64157234Sralph } else if (coord > 0) { 64257234Sralph mrp->state |= MOUSE_X_SIGN; 64357234Sralph moved = 1; 64457234Sralph } 64557234Sralph mrp->dx = (coord & 0x1f); 64656813Sralph coord = GET_SHORT(msg->body[4], msg->body[5]); 64757234Sralph if (coord < 0) { 64857234Sralph coord = -coord; 64956813Sralph moved = 1; 65057234Sralph } else if (coord > 0) { 65157234Sralph mrp->state |= MOUSE_Y_SIGN; 65257234Sralph moved = 1; 65357234Sralph } 65457234Sralph mrp->dy = (coord & 0x1f); 65556813Sralph 65656813Sralph /* 65756813Sralph * Time for the buttons now 65858793Sralph * Shuffle button bits around to serial mouse order. 65956813Sralph */ 66056813Sralph buttons = GET_SHORT(msg->body[0], msg->body[1]); 66158793Sralph mrp->state |= (((buttons >> 1) & 0x3) | ((buttons << 2) & 0x4)); 66256813Sralph if (moved) 66356813Sralph (*dtopMouseEvent)(mrp); 66456813Sralph (*dtopMouseButtons)(mrp); 66556813Sralph } 66656813Sralph return (0); 66756813Sralph } 66856813Sralph 66956813Sralph /* 67056813Sralph * Handler for keyboard devices 67156813Sralph * Special case: outc set for recv packet means 67256813Sralph * we are inside the kernel debugger 67356813Sralph */ 67456813Sralph int 67556813Sralph dtop_keyboard_handler(dev, msg, event, outc) 67656813Sralph dtop_device_t dev; 67756813Sralph dtop_message_t msg; 67856813Sralph int event; 67956813Sralph int outc; 68056813Sralph { 68156813Sralph register u_char *ls, *le, *ns, *ne; 68256813Sralph u_char save[11], retc; 68358793Sralph int msg_len, c, s; 68456813Sralph struct tty *tp = &dtop_tty[0]; 68556813Sralph 68656813Sralph /* 68756813Sralph * Fiddle about emulating an lk201 keyboard. The lk501 68856813Sralph * designers carefully ensured that keyboard handlers could be 68956813Sralph * stateless, then we turn around and use lots of state to 69056813Sralph * emulate the stateful lk201, since the X11R5 X servers 69156813Sralph * only know about the lk201... (oh well) 69256813Sralph */ 69358793Sralph /* 69458793Sralph * Turn off any autorepeat timeout. 69558793Sralph */ 69658793Sralph s = splhigh(); 69758793Sralph if (dev->keyboard.k_ar_state != K_AR_IDLE) { 69858793Sralph dev->keyboard.k_ar_state = K_AR_IDLE; 69958793Sralph untimeout(dtop_keyboard_repeat, (void *)dev); 70058793Sralph } 70158793Sralph splx(s); 70256813Sralph msg_len = msg->code.val.len; 70356813Sralph 70456813Sralph /* Check for errors */ 70556813Sralph c = msg->body[0]; 70656813Sralph if ((c < DTOP_KBD_KEY_MIN) && (c != DTOP_KBD_EMPTY)) { 70756813Sralph printf("Keyboard error: %x %x %x..\n", msg_len, c, msg->body[1]); 70858793Sralph #ifdef notdef 70956813Sralph if (c != DTOP_KBD_OUT_ERR) return -1; 71058793Sralph #endif 71158793Sralph /* 71258793Sralph * Fake an "all ups" to avoid the stuck key syndrome. 71358793Sralph */ 71458793Sralph c = msg->body[0] = DTOP_KBD_EMPTY; 71558793Sralph msg_len = 1; 71656813Sralph } 71756813Sralph 71856813Sralph dev->keyboard.last_msec = TO_MS(time); 71956813Sralph /* 72056813Sralph * To make things readable, do a first pass cancelling out 72156813Sralph * all keys that are still pressed, and a second one generating 72256813Sralph * events. While generating events, do the upstrokes first 72356813Sralph * from oldest to youngest, then the downstrokes from oldest 72456813Sralph * to youngest. This copes with lost packets and provides 72556813Sralph * a reasonable model even if scans are too slow. 72656813Sralph */ 72756813Sralph 72856813Sralph /* make a copy of new state first */ 72956813Sralph if (msg_len == 1) 73056813Sralph save[0] = msg->body[0]; 73156813Sralph else if (msg_len > 0) 73256813Sralph bcopy(msg->body, save, msg_len); 73356813Sralph 73456813Sralph /* 73556813Sralph * Cancel out any keys in both the last and current message as 73656813Sralph * they are unchanged. 73756813Sralph */ 73856813Sralph if (msg_len > 0 && dev->keyboard.last_codes_count > 0) { 73956813Sralph ls = dev->keyboard.last_codes; 74056813Sralph le = &dev->keyboard.last_codes[dev->keyboard.last_codes_count]; 74156813Sralph ne = &msg->body[msg_len]; 74256813Sralph for (; ls < le; ls++) { 74356813Sralph for (ns = msg->body; ns < ne; ns++) 74456813Sralph if (*ls == *ns) { 74556813Sralph *ls = *ns = 0; 74656813Sralph break; 74756813Sralph } 74856813Sralph } 74956813Sralph } 75056813Sralph 75156813Sralph /* 75256813Sralph * Now generate all upstrokes 75356813Sralph */ 75456813Sralph le = dev->keyboard.last_codes; 75556813Sralph ls = &dev->keyboard.last_codes[dev->keyboard.last_codes_count - 1]; 75656813Sralph for ( ; ls >= le; ls--) 75756813Sralph if (c = *ls) { 75856813Sralph (void) kbdMapChar(c); 75956813Sralph 76057234Sralph if (outc == 0 && dtopDivertXInput && 76157234Sralph (keymodes[(c >> 5) & 0x7] & (1 << (c & 0x1f)))) 76256813Sralph (*dtopDivertXInput)(c); 76356813Sralph } 76456813Sralph /* 76556813Sralph * And finally the downstrokes 76656813Sralph */ 76756813Sralph ne = (char*)msg->body; 76856813Sralph ns = (char*)&msg->body[msg_len - 1]; 76956813Sralph retc = 0; 77056813Sralph for ( ; ns >= ne; ns--) 77156813Sralph if (*ns) { 77256813Sralph c = kbdMapChar(*ns); 77356813Sralph if (outc == 0) { 77456813Sralph if (dtopDivertXInput) { 77556813Sralph (*dtopDivertXInput)(*ns); 77656813Sralph c = -1; /* consumed by X */ 77756813Sralph } else if (c >= 0) 77856813Sralph (*linesw[tp->t_line].l_rint)(c, tp); 77958793Sralph dev->keyboard.k_ar_state = K_AR_ACTIVE; 78056813Sralph } 78156813Sralph /* return the related keycode anyways */ 78256813Sralph if ((c >= 0) && (retc == 0)) 78356813Sralph retc = c; 78456813Sralph } 78556813Sralph outc = retc; 78656813Sralph /* install new scan state */ 78756813Sralph if (msg_len == 1) 78856813Sralph dev->keyboard.last_codes[0] = save[0]; 78956813Sralph else if (msg_len > 0) 79056813Sralph bcopy(save, dev->keyboard.last_codes, msg_len); 79156813Sralph dev->keyboard.last_codes_count = msg_len; 79258793Sralph if (dev->keyboard.k_ar_state == K_AR_ACTIVE) 79358793Sralph timeout(dtop_keyboard_repeat, (void *)dev, hz / 2); 79456813Sralph return (outc); 79556813Sralph } 79656813Sralph 79756813Sralph /* 79858793Sralph * Do an autorepeat as required. 79956813Sralph */ 80056813Sralph void 80158793Sralph dtop_keyboard_repeat(arg) 80256813Sralph void *arg; 80356813Sralph { 80456813Sralph dtop_device_t dev = (dtop_device_t)arg; 80557234Sralph register int i, c; 80657234Sralph struct tty *tp = dtop_tty; 80758793Sralph int s = spltty(), gotone = 0; 80857234Sralph 80957234Sralph for (i = 0; i < dev->keyboard.last_codes_count; i++) { 81057234Sralph c = (int)dev->keyboard.last_codes[i]; 81157234Sralph if (c != DTOP_KBD_EMPTY && 81257234Sralph (keymodes[(c >> 5) & 0x7] & (1 << (c & 0x1f))) == 0) { 81357234Sralph dev->keyboard.k_ar_state = K_AR_TRIGGER; 81457234Sralph if (dtopDivertXInput) { 81557234Sralph (*dtopDivertXInput)(KEY_REPEAT); 81658793Sralph gotone = 1; 81758793Sralph continue; 81857234Sralph } 81957234Sralph 82058793Sralph if ((c = kbdMapChar(KEY_REPEAT)) >= 0) { 82157234Sralph (*linesw[tp->t_line].l_rint)(c, tp); 82258793Sralph gotone = 1; 82358793Sralph } 82457234Sralph } 82557234Sralph } 82658793Sralph if (gotone) 82758793Sralph timeout(dtop_keyboard_repeat, arg, hz / 20); 82858793Sralph else 82958793Sralph dev->keyboard.k_ar_state = K_AR_IDLE; 83058793Sralph splx(s); 83157234Sralph } 83256813Sralph #endif 833