156813Sralph /*- 256813Sralph * Copyright (c) 1992 The Regents of the University of California. 356813Sralph * 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*57234Sralph * @(#)dtop.c 7.2 (Berkeley) 12/20/92 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 */ 44*57234Sralph /************************************************************ 45*57234Sralph Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts, 46*57234Sralph and the Massachusetts Institute of Technology, Cambridge, Massachusetts. 4756813Sralph 48*57234Sralph All Rights Reserved 49*57234Sralph 50*57234Sralph Permission to use, copy, modify, and distribute this software and its 51*57234Sralph documentation for any purpose and without fee is hereby granted, 52*57234Sralph provided that the above copyright notice appear in all copies and that 53*57234Sralph both that copyright notice and this permission notice appear in 54*57234Sralph supporting documentation, and that the names of Digital or MIT not be 55*57234Sralph used in advertising or publicity pertaining to distribution of the 56*57234Sralph software without specific, written prior permission. 57*57234Sralph 58*57234Sralph DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 59*57234Sralph ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 60*57234Sralph DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 61*57234Sralph ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 62*57234Sralph WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 63*57234Sralph ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 64*57234Sralph SOFTWARE. 65*57234Sralph 66*57234Sralph ********************************************************/ 67*57234Sralph 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 *)); 9856813Sralph void dtop_keyboard_autorepeat __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)); 106*57234Sralph static void dtop_keyboard_repeat __P((dtop_device_t)); 10756813Sralph 10856813Sralph struct tty dtop_tty[NDTOP]; 10956813Sralph void (*dtopDivertXInput)(); /* X windows keyboard input routine */ 11056813Sralph void (*dtopMouseEvent)(); /* X windows mouse motion event routine */ 11156813Sralph void (*dtopMouseButtons)(); /* X windows mouse buttons event routine */ 11256813Sralph 11356813Sralph #define DTOP_MAX_POLL 0x7fff /* about half a sec */ 11456813Sralph 11556813Sralph typedef volatile unsigned int *data_reg_t; /* uC */ 11656813Sralph #define DTOP_GET_BYTE(data) (((*(data)) >> 8) & 0xff) 11756813Sralph #define DTOP_PUT_BYTE(data,c) { *(data) = (c) << 8; } 11856813Sralph 11956813Sralph typedef volatile unsigned int *poll_reg_t; /* SIR */ 12056813Sralph #define DTOP_RX_AVAIL(poll) (*(poll) & 1) 12156813Sralph #define DTOP_TX_AVAIL(poll) (*(poll) & 2) 12256813Sralph 12356813Sralph #define GET_SHORT(b0,b1) (((b0)<<8)|(b1)) 12456813Sralph 12556813Sralph /* 12656813Sralph * Driver status 12756813Sralph */ 12856813Sralph struct dtop_softc { 12956813Sralph data_reg_t data; 13056813Sralph poll_reg_t poll; 13156813Sralph char polling_mode; 13256813Sralph char probed_once; 13356813Sralph short bad_pkts; 13456813Sralph 13556813Sralph struct dtop_ds { 13656813Sralph int (*handler)(); 13756813Sralph dtop_device status; 13856813Sralph } device[(DTOP_ADDR_DEFAULT - DTOP_ADDR_FIRST) >> 1]; 13956813Sralph 14056813Sralph # define DTOP_DEVICE_NO(address) (((address)-DTOP_ADDR_FIRST)>>1) 14156813Sralph 14256813Sralph } dtop_softc[NDTOP]; 14356813Sralph 14456813Sralph typedef struct dtop_softc *dtop_softc_t; 14556813Sralph struct tty dtop_tty[NDTOP]; 14656813Sralph 14756813Sralph /* 148*57234Sralph * lk201 keyboard divisions and up/down mode key bitmap. 149*57234Sralph */ 150*57234Sralph #define NUMDIVS 14 151*57234Sralph static u_char divbeg[NUMDIVS] = {0xbf, 0x91, 0xbc, 0xbd, 0xb0, 0xad, 0xa6, 152*57234Sralph 0xa9, 0x88, 0x56, 0x63, 0x6f, 0x7b, 0x7e}; 153*57234Sralph static u_char divend[NUMDIVS] = {0xff, 0xa5, 0xbc, 0xbe, 0xb2, 0xaf, 0xa8, 154*57234Sralph 0xac, 0x90, 0x62, 0x6e, 0x7a, 0x7d, 0x87}; 155*57234Sralph /* 156*57234Sralph * Initial defaults, groups 5 and 6 are up/down 157*57234Sralph */ 158*57234Sralph static u_long keymodes[8] = {0, 0, 0, 0, 0, 0x0003e000, 0, 0}; 159*57234Sralph 160*57234Sralph /* 16156813Sralph * Definition of the driver for the auto-configuration program. 16256813Sralph */ 16356813Sralph int dtopprobe(); 16456813Sralph void dtopintr(); 16556813Sralph struct driver dtopdriver = { 16656813Sralph "dtop", dtopprobe, 0, 0, dtopintr, 16756813Sralph }; 16856813Sralph 16956813Sralph dtopprobe(cp) 17056813Sralph struct pmax_ctlr *cp; 17156813Sralph { 17256813Sralph register struct tty *tp; 17356813Sralph register int cntr; 17456813Sralph int dtopunit = cp->pmax_unit, i, s; 17556813Sralph dtop_softc_t dtop; 17656813Sralph 17756813Sralph if (dtopunit >= NDTOP) 17856813Sralph return (0); 17956813Sralph if (badaddr(cp->pmax_addr, 2)) 18056813Sralph return (0); 18156813Sralph dtop = &dtop_softc[dtopunit]; 18256813Sralph 18356813Sralph dtop->poll = (poll_reg_t)MACH_PHYS_TO_UNCACHED(XINE_REG_INTR); 18456813Sralph dtop->data = (data_reg_t)cp->pmax_addr; 18556813Sralph 18656813Sralph for (i = 0; i < DTOP_MAX_DEVICES; i++) 18756813Sralph dtop->device[i].handler = dtop_null_device_handler; 18856813Sralph 18956813Sralph /* a lot more needed here, fornow: */ 19056813Sralph dtop->device[DTOP_DEVICE_NO(0x6a)].handler = dtop_locator_handler; 19156813Sralph dtop->device[DTOP_DEVICE_NO(0x6c)].handler = dtop_keyboard_handler; 19256813Sralph dtop->device[DTOP_DEVICE_NO(0x6c)].status.keyboard.poll_frequency = 19356813Sralph (hz * 5) / 100; /* x0.01 secs */ 19456813Sralph dtop->device[DTOP_DEVICE_NO(0x6c)].status.keyboard.k_ar_state = 19556813Sralph K_AR_IDLE; 19656813Sralph 19756813Sralph /* 19856813Sralph * Sometimes a first interrupt gets lost, so just in case 19956813Sralph * poke it now. 20056813Sralph */ 20156813Sralph dtopintr(dtopunit); 202*57234Sralph dtop->probed_once = 1; 203*57234Sralph printf("dtop%d at nexus0 csr 0x%x priority %d\n", 204*57234Sralph cp->pmax_unit, cp->pmax_addr, cp->pmax_pri); 20556813Sralph return (1); 20656813Sralph } 20756813Sralph 20856813Sralph dtopopen(dev, flag, mode, p) 20956813Sralph dev_t dev; 21056813Sralph int flag, mode; 21156813Sralph struct proc *p; 21256813Sralph { 21356813Sralph register struct tty *tp; 21456813Sralph register int unit; 21556813Sralph int s, error = 0; 21656813Sralph 21756813Sralph unit = minor(dev); 21856813Sralph if (unit >= NDTOP) 21956813Sralph return (ENXIO); 22056813Sralph tp = &dtop_tty[unit]; 22156813Sralph tp->t_oproc = dtopstart; 22256813Sralph tp->t_param = dtopparam; 22356813Sralph tp->t_dev = dev; 22456813Sralph if ((tp->t_state & TS_ISOPEN) == 0) { 22556813Sralph tp->t_state |= TS_WOPEN; 22656813Sralph ttychars(tp); 22756813Sralph if (tp->t_ispeed == 0) { 22856813Sralph tp->t_iflag = TTYDEF_IFLAG; 22956813Sralph tp->t_oflag = TTYDEF_OFLAG; 23056813Sralph tp->t_cflag = TTYDEF_CFLAG; 23156813Sralph tp->t_lflag = TTYDEF_LFLAG; 23256813Sralph tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; 23356813Sralph } 23456813Sralph (void) dtopparam(tp, &tp->t_termios); 23556813Sralph ttsetwater(tp); 23656813Sralph } else if ((tp->t_state & TS_XCLUDE) && curproc->p_ucred->cr_uid != 0) 23756813Sralph return (EBUSY); 23856813Sralph s = spltty(); 23956813Sralph while (!(flag & O_NONBLOCK) && !(tp->t_cflag & CLOCAL) && 24056813Sralph !(tp->t_state & TS_CARR_ON)) { 24156813Sralph tp->t_state |= TS_WOPEN; 24256813Sralph if (error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH, 24356813Sralph ttopen, 0)) 24456813Sralph break; 24556813Sralph } 24656813Sralph splx(s); 24756813Sralph if (error) 24856813Sralph return (error); 24956813Sralph error = (*linesw[tp->t_line].l_open)(dev, tp); 25056813Sralph return (error); 25156813Sralph } 25256813Sralph 25356813Sralph /*ARGSUSED*/ 25456813Sralph dtopclose(dev, flag, mode, p) 25556813Sralph dev_t dev; 25656813Sralph int flag, mode; 25756813Sralph struct proc *p; 25856813Sralph { 25956813Sralph register struct tty *tp; 26056813Sralph register int unit; 26156813Sralph 26256813Sralph unit = minor(dev); 26356813Sralph tp = &dtop_tty[unit]; 26456813Sralph (*linesw[tp->t_line].l_close)(tp, flag); 26556813Sralph return (ttyclose(tp)); 26656813Sralph } 26756813Sralph 26856813Sralph dtopread(dev, uio, flag) 26956813Sralph dev_t dev; 27056813Sralph struct uio *uio; 27156813Sralph { 27256813Sralph register struct tty *tp; 27356813Sralph 27456813Sralph tp = &dtop_tty[minor(dev)]; 27556813Sralph return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); 27656813Sralph } 27756813Sralph 27856813Sralph dtopwrite(dev, uio, flag) 27956813Sralph dev_t dev; 28056813Sralph struct uio *uio; 28156813Sralph { 28256813Sralph register struct tty *tp; 28356813Sralph 28456813Sralph tp = &dtop_tty[minor(dev)]; 28556813Sralph return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); 28656813Sralph } 28756813Sralph 28856813Sralph /*ARGSUSED*/ 28956813Sralph dtopioctl(dev, cmd, data, flag, p) 29056813Sralph dev_t dev; 29156813Sralph int cmd; 29256813Sralph caddr_t data; 29356813Sralph int flag; 29456813Sralph struct proc *p; 29556813Sralph { 29656813Sralph register struct tty *tp; 29756813Sralph register int unit = minor(dev); 29856813Sralph int error; 29956813Sralph 30056813Sralph tp = &dtop_tty[unit]; 30156813Sralph error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); 30256813Sralph if (error >= 0) 30356813Sralph return (error); 30456813Sralph error = ttioctl(tp, cmd, data, flag); 30556813Sralph if (error >= 0) 30656813Sralph return (error); 30756813Sralph 30856813Sralph switch (cmd) { 30956813Sralph 31056813Sralph case TIOCSBRK: 31156813Sralph ttyoutput(0, tp); 31256813Sralph break; 31356813Sralph 31456813Sralph case TIOCCBRK: 31556813Sralph ttyoutput(0, tp); 31656813Sralph break; 31756813Sralph 31856813Sralph case TIOCMGET: 31956813Sralph *(int *)data = DML_DTR | DML_DSR | DML_CAR; 32056813Sralph break; 32156813Sralph 32256813Sralph default: 32356813Sralph return (ENOTTY); 32456813Sralph } 32556813Sralph return (0); 32656813Sralph } 32756813Sralph 32856813Sralph /* 32956813Sralph * Interrupt routine 33056813Sralph */ 33156813Sralph void 33256813Sralph dtopintr(unit) 33356813Sralph int unit; 33456813Sralph { 33556813Sralph dtop_message msg; 33656813Sralph int devno; 33756813Sralph dtop_softc_t dtop; 33856813Sralph 33956813Sralph dtop = &dtop_softc[unit]; 34056813Sralph if (dtop_get_packet(dtop, &msg) < 0) { 341*57234Sralph if (dtop->probed_once) 34256813Sralph printf("%s", "dtop: overrun (or stray)\n"); 34356813Sralph return; 34456813Sralph } 34556813Sralph 34656813Sralph devno = DTOP_DEVICE_NO(msg.src_address); 34756813Sralph if (devno < 0 || devno > 15) 34856813Sralph return; 34956813Sralph 35056813Sralph (void) (*dtop->device[devno].handler) 35156813Sralph (&dtop->device[devno].status, &msg, 35256813Sralph DTOP_EVENT_RECEIVE_PACKET, 0); 35356813Sralph } 35456813Sralph 35556813Sralph void 35656813Sralph dtopstart(tp) 35756813Sralph register struct tty *tp; 35856813Sralph { 35956813Sralph register int cc; 36056813Sralph int s; 36156813Sralph 36256813Sralph s = spltty(); 36356813Sralph if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) 36456813Sralph goto out; 36556813Sralph if (tp->t_outq.c_cc <= tp->t_lowat) { 36656813Sralph if (tp->t_state & TS_ASLEEP) { 36756813Sralph tp->t_state &= ~TS_ASLEEP; 36856813Sralph wakeup((caddr_t)&tp->t_outq); 36956813Sralph } 37056813Sralph selwakeup(&tp->t_wsel); 37156813Sralph } 37256813Sralph if (tp->t_outq.c_cc == 0) 37356813Sralph goto out; 37456813Sralph /* handle console specially */ 37556813Sralph if (tp == dtop_tty) { 37656813Sralph while (tp->t_outq.c_cc > 0) { 37756813Sralph cc = getc(&tp->t_outq) & 0x7f; 37856813Sralph cnputc(cc); 37956813Sralph } 38056813Sralph /* 38156813Sralph * After we flush the output queue we may need to wake 38256813Sralph * up the process that made the output. 38356813Sralph */ 38456813Sralph if (tp->t_outq.c_cc <= tp->t_lowat) { 38556813Sralph if (tp->t_state & TS_ASLEEP) { 38656813Sralph tp->t_state &= ~TS_ASLEEP; 38756813Sralph wakeup((caddr_t)&tp->t_outq); 38856813Sralph } 38956813Sralph selwakeup(&tp->t_wsel); 39056813Sralph } 39156813Sralph } 39256813Sralph out: 39356813Sralph splx(s); 39456813Sralph } 39556813Sralph 39656813Sralph void 39756813Sralph dtopKBDPutc(dev, c) 39856813Sralph dev_t dev; 39956813Sralph int c; 40056813Sralph { 401*57234Sralph register int i; 402*57234Sralph static int param = 0, cmd, mod, typ; 403*57234Sralph static u_char parms[2]; 40456813Sralph 40556813Sralph /* 406*57234Sralph * Emulate the lk201 command codes. 40756813Sralph */ 408*57234Sralph if (param == 0) { 409*57234Sralph typ = (c & 0x1); 410*57234Sralph cmd = ((c >> 3) & 0xf); 411*57234Sralph mod = ((c >> 1) & 0x3); 412*57234Sralph } else 413*57234Sralph parms[param - 1] = (c & 0x7f); 414*57234Sralph if (c & 0x80) { 415*57234Sralph if (typ) { 416*57234Sralph /* 417*57234Sralph * A peripheral command code. Someday this driver 418*57234Sralph * should know how to send commands to the lk501, 419*57234Sralph * but until then this is all essentially a no-op. 420*57234Sralph */ 421*57234Sralph ; 422*57234Sralph } else { 423*57234Sralph /* 424*57234Sralph * Set modes. These have to be emulated in software. 425*57234Sralph */ 426*57234Sralph if (cmd > 0 && cmd < 15) { 427*57234Sralph cmd--; 428*57234Sralph if (mod & 0x2) 429*57234Sralph for (i = divbeg[cmd]; i <= divend[cmd]; i++) 430*57234Sralph keymodes[i >> 5] |= 431*57234Sralph (1 << (i & 0x1f)); 432*57234Sralph else 433*57234Sralph for (i = divbeg[cmd]; i <= divend[cmd]; i++) 434*57234Sralph keymodes[i >> 5] &= 435*57234Sralph ~(1 << (i & 0x1f)); 436*57234Sralph } 437*57234Sralph } 438*57234Sralph param = 0; 439*57234Sralph } else if (++param > 2) 440*57234Sralph param = 2; 44156813Sralph } 44256813Sralph 44356813Sralph /* 44456813Sralph * Take a packet off dtop interface 44556813Sralph * A packet MUST be there, this is not checked for. 44656813Sralph */ 44756813Sralph #define DTOP_ESC_CHAR 0xf8 44856813Sralph dtop_escape(c) 44956813Sralph { 45056813Sralph /* I donno much about this stuff.. */ 45156813Sralph switch (c) { 45256813Sralph case 0xe8: return (0xf8); 45356813Sralph case 0xe9: return (0xf9); 45456813Sralph case 0xea: return (0xfa); 45556813Sralph case 0xeb: return (0xfb); 45656813Sralph default: /* printf("{esc %x}", c); */ 45756813Sralph return (c); 45856813Sralph } 45956813Sralph } 46056813Sralph 46156813Sralph dtop_get_packet(dtop, pkt) 46256813Sralph dtop_softc_t dtop; 46356813Sralph dtop_message_t pkt; 46456813Sralph { 46556813Sralph register poll_reg_t poll; 46656813Sralph register data_reg_t data; 46756813Sralph register int max, i, len; 46856813Sralph register unsigned char c; 46956813Sralph 47056813Sralph poll = dtop->poll; 47156813Sralph data = dtop->data; 47256813Sralph 47356813Sralph /* 47456813Sralph * The interface does not handle us the first byte, 47556813Sralph * which is our address and cannot ever be anything 47656813Sralph * else but 0x50. This is a good thing, it makes 47756813Sralph * the average packet exactly one word long, too. 47856813Sralph */ 47956813Sralph for (max = 0; (max < DTOP_MAX_POLL) && !DTOP_RX_AVAIL(poll); max++) 480*57234Sralph DELAY(1); 48156813Sralph if (max == DTOP_MAX_POLL) 48256813Sralph goto bad; 48356813Sralph pkt->src_address = DTOP_GET_BYTE(data); 48456813Sralph 48556813Sralph for (max = 0; (max < DTOP_MAX_POLL) && !DTOP_RX_AVAIL(poll); max++) 486*57234Sralph DELAY(1); 48756813Sralph if (max == DTOP_MAX_POLL) 48856813Sralph goto bad; 48956813Sralph pkt->code.bits = DTOP_GET_BYTE(data); 49056813Sralph 49156813Sralph /* 49256813Sralph * Now get data and checksum 49356813Sralph */ 49456813Sralph len = pkt->code.val.len + 1; 49556813Sralph c = 0; 49656813Sralph for (i = 0; i < len; i++) { 49756813Sralph again: 49856813Sralph for (max = 0; (max < DTOP_MAX_POLL) && !DTOP_RX_AVAIL(poll); max++) 499*57234Sralph DELAY(1); 50056813Sralph if (max == DTOP_MAX_POLL) 50156813Sralph goto bad; 50256813Sralph if (c == DTOP_ESC_CHAR) { 50356813Sralph c = dtop_escape(DTOP_GET_BYTE(data) & 0xff); 50456813Sralph } else { 50556813Sralph c = DTOP_GET_BYTE(data); 50656813Sralph if (c == DTOP_ESC_CHAR) 50756813Sralph goto again; 50856813Sralph } 50956813Sralph pkt->body[i] = c; 51056813Sralph } 51156813Sralph return (len); 51256813Sralph bad: 51356813Sralph dtop->bad_pkts++; 51456813Sralph return (-1); 51556813Sralph } 51656813Sralph 51756813Sralph /* 51856813Sralph * Get a keyboard char for the console 51956813Sralph */ 52056813Sralph dtopKBDGetc() 52156813Sralph { 52256813Sralph register int c; 52356813Sralph dtop_softc_t dtop; 52456813Sralph 52556813Sralph dtop = &dtop_softc[0]; 52656813Sralph again: 52756813Sralph c = -1; 52856813Sralph 52956813Sralph /* 53056813Sralph * Now check keyboard 53156813Sralph */ 53256813Sralph if (DTOP_RX_AVAIL(dtop->poll)) { 53356813Sralph 53456813Sralph dtop_message msg; 53556813Sralph struct dtop_ds *ds; 53656813Sralph 53756813Sralph if (dtop_get_packet(dtop, &msg) >= 0) { 53856813Sralph 53956813Sralph ds = &dtop->device[DTOP_DEVICE_NO(msg.src_address)]; 54056813Sralph if (ds->handler == dtop_keyboard_handler) { 54156813Sralph 54256813Sralph c = dtop_keyboard_handler( 54356813Sralph &ds->status, &msg, 54456813Sralph DTOP_EVENT_RECEIVE_PACKET, -1); 54556813Sralph 54656813Sralph if (c > 0) return c; 54756813Sralph 54856813Sralph c = -1; 54956813Sralph } 55056813Sralph } 55156813Sralph } 55256813Sralph 55356813Sralph if (c == -1) { 55456813Sralph DELAY(100); 55556813Sralph goto again; 55656813Sralph } 55756813Sralph 55856813Sralph return c; 55956813Sralph } 56056813Sralph 56156813Sralph int 56256813Sralph dtopparam(tp, t) 56356813Sralph struct tty *tp; 56456813Sralph struct termios *t; 56556813Sralph { 56656813Sralph if (tp->t_ispeed == 0) 56756813Sralph ttymodem(tp, 0); 56856813Sralph else 56956813Sralph /* called too early to invoke ttymodem, sigh */ 57056813Sralph tp->t_state |= TS_CARR_ON; 57156813Sralph return (0); 57256813Sralph } 57356813Sralph 57456813Sralph /* 57556813Sralph * Stop output on a line. 57656813Sralph */ 57756813Sralph /*ARGSUSED*/ 57856813Sralph dtopstop(tp, flag) 57956813Sralph register struct tty *tp; 58056813Sralph int flag; 58156813Sralph { 58256813Sralph int s; 58356813Sralph 58456813Sralph s = spltty(); 58556813Sralph if (tp->t_state & TS_BUSY) { 58656813Sralph if (!(tp->t_state & TS_TTSTOP)) 58756813Sralph tp->t_state |= TS_FLUSH; 58856813Sralph } 58956813Sralph splx(s); 59056813Sralph } 59156813Sralph 59256813Sralph /* 59356813Sralph * Default handler function 59456813Sralph */ 59556813Sralph int 59656813Sralph dtop_null_device_handler(dev, msg, event, outc) 59756813Sralph dtop_device_t dev; 59856813Sralph dtop_message_t msg; 59956813Sralph int event; 60056813Sralph int outc; 60156813Sralph { 60256813Sralph /* See if the message was to the default address (powerup) */ 60356813Sralph 60456813Sralph /* Uhmm, donno how to handle this. Drop it */ 60556813Sralph if (event == DTOP_EVENT_RECEIVE_PACKET) 60656813Sralph dev->unknown_report = *msg; 60756813Sralph return 0; 60856813Sralph } 60956813Sralph 61056813Sralph /* 61156813Sralph * Handler for locator devices (mice) 61256813Sralph */ 61356813Sralph int 61456813Sralph dtop_locator_handler(dev, msg, event, outc) 61556813Sralph dtop_device_t dev; 61656813Sralph dtop_message_t msg; 61756813Sralph int event; 61856813Sralph int outc; 61956813Sralph { 62056813Sralph register unsigned short buttons; 62156813Sralph register short coord; 62256813Sralph register int moved = 0; 62356813Sralph static MouseReport currentRep; 62456813Sralph register MouseReport *mrp = ¤tRep; 62556813Sralph 62656813Sralph if (dtopMouseButtons) { 627*57234Sralph mrp->state = 0; 62856813Sralph /* 62956813Sralph * Do the position first 63056813Sralph */ 63156813Sralph coord = GET_SHORT(msg->body[2], msg->body[3]); 632*57234Sralph if (coord < 0) { 633*57234Sralph coord = -coord; 63456813Sralph moved = 1; 635*57234Sralph } else if (coord > 0) { 636*57234Sralph mrp->state |= MOUSE_X_SIGN; 637*57234Sralph moved = 1; 638*57234Sralph } 639*57234Sralph mrp->dx = (coord & 0x1f); 64056813Sralph coord = GET_SHORT(msg->body[4], msg->body[5]); 641*57234Sralph if (coord < 0) { 642*57234Sralph coord = -coord; 64356813Sralph moved = 1; 644*57234Sralph } else if (coord > 0) { 645*57234Sralph mrp->state |= MOUSE_Y_SIGN; 646*57234Sralph moved = 1; 647*57234Sralph } 648*57234Sralph mrp->dy = (coord & 0x1f); 64956813Sralph 65056813Sralph /* 65156813Sralph * Time for the buttons now 65256813Sralph */ 65356813Sralph buttons = GET_SHORT(msg->body[0], msg->body[1]); 654*57234Sralph mrp->state |= (buttons & 0x7); 65556813Sralph if (moved) 65656813Sralph (*dtopMouseEvent)(mrp); 65756813Sralph (*dtopMouseButtons)(mrp); 65856813Sralph } 65956813Sralph return (0); 66056813Sralph } 66156813Sralph 66256813Sralph /* 66356813Sralph * Handler for keyboard devices 66456813Sralph * Special case: outc set for recv packet means 66556813Sralph * we are inside the kernel debugger 66656813Sralph */ 66756813Sralph int 66856813Sralph dtop_keyboard_handler(dev, msg, event, outc) 66956813Sralph dtop_device_t dev; 67056813Sralph dtop_message_t msg; 67156813Sralph int event; 67256813Sralph int outc; 67356813Sralph { 67456813Sralph register u_char *ls, *le, *ns, *ne; 67556813Sralph u_char save[11], retc; 67656813Sralph int msg_len, c; 67756813Sralph struct tty *tp = &dtop_tty[0]; 67856813Sralph 67956813Sralph /* 68056813Sralph * Fiddle about emulating an lk201 keyboard. The lk501 68156813Sralph * designers carefully ensured that keyboard handlers could be 68256813Sralph * stateless, then we turn around and use lots of state to 68356813Sralph * emulate the stateful lk201, since the X11R5 X servers 68456813Sralph * only know about the lk201... (oh well) 68556813Sralph */ 68656813Sralph msg_len = msg->code.val.len; 68756813Sralph 68856813Sralph /* Check for errors */ 68956813Sralph c = msg->body[0]; 69056813Sralph if ((c < DTOP_KBD_KEY_MIN) && (c != DTOP_KBD_EMPTY)) { 69156813Sralph printf("Keyboard error: %x %x %x..\n", msg_len, c, msg->body[1]); 69256813Sralph if (c != DTOP_KBD_OUT_ERR) return -1; 69356813Sralph /* spec sez if scan list overflow still there is data */ 69456813Sralph msg->body[0] = 0; 69556813Sralph } 69656813Sralph 69756813Sralph dev->keyboard.last_msec = TO_MS(time); 69856813Sralph 69956813Sralph switch (dev->keyboard.k_ar_state) { 70056813Sralph case K_AR_IDLE: 70156813Sralph if (outc != 0xff) /* from debugger, might be too early */ 70256813Sralph dtop_keyboard_autorepeat(dev); 70356813Sralph /* fall through */ 70456813Sralph case K_AR_TRIGGER: 70556813Sralph dev->keyboard.k_ar_state = K_AR_ACTIVE; 70656813Sralph break; 70756813Sralph case K_AR_ACTIVE: 70856813Sralph break; 70956813Sralph case K_AR_OFF: 71056813Sralph printf("dtop keyb off?\n"); 71156813Sralph dev->keyboard.k_ar_state = K_AR_IDLE; 71256813Sralph } 71356813Sralph 71456813Sralph /* 71556813Sralph * To make things readable, do a first pass cancelling out 71656813Sralph * all keys that are still pressed, and a second one generating 71756813Sralph * events. While generating events, do the upstrokes first 71856813Sralph * from oldest to youngest, then the downstrokes from oldest 71956813Sralph * to youngest. This copes with lost packets and provides 72056813Sralph * a reasonable model even if scans are too slow. 72156813Sralph */ 72256813Sralph 72356813Sralph /* make a copy of new state first */ 72456813Sralph if (msg_len == 1) 72556813Sralph save[0] = msg->body[0]; 72656813Sralph else if (msg_len > 0) 72756813Sralph bcopy(msg->body, save, msg_len); 72856813Sralph 72956813Sralph /* 73056813Sralph * Cancel out any keys in both the last and current message as 73156813Sralph * they are unchanged. 73256813Sralph */ 73356813Sralph if (msg_len > 0 && dev->keyboard.last_codes_count > 0) { 73456813Sralph ls = dev->keyboard.last_codes; 73556813Sralph le = &dev->keyboard.last_codes[dev->keyboard.last_codes_count]; 73656813Sralph ne = &msg->body[msg_len]; 73756813Sralph for (; ls < le; ls++) { 73856813Sralph for (ns = msg->body; ns < ne; ns++) 73956813Sralph if (*ls == *ns) { 74056813Sralph *ls = *ns = 0; 74156813Sralph break; 74256813Sralph } 74356813Sralph } 74456813Sralph } 74556813Sralph 74656813Sralph /* 74756813Sralph * Now generate all upstrokes 74856813Sralph */ 74956813Sralph le = dev->keyboard.last_codes; 75056813Sralph ls = &dev->keyboard.last_codes[dev->keyboard.last_codes_count - 1]; 75156813Sralph for ( ; ls >= le; ls--) 75256813Sralph if (c = *ls) { 75356813Sralph (void) kbdMapChar(c); 75456813Sralph 755*57234Sralph if (outc == 0 && dtopDivertXInput && 756*57234Sralph (keymodes[(c >> 5) & 0x7] & (1 << (c & 0x1f)))) 75756813Sralph (*dtopDivertXInput)(c); 75856813Sralph } 75956813Sralph /* 76056813Sralph * And finally the downstrokes 76156813Sralph */ 76256813Sralph ne = (char*)msg->body; 76356813Sralph ns = (char*)&msg->body[msg_len - 1]; 76456813Sralph retc = 0; 76556813Sralph for ( ; ns >= ne; ns--) 76656813Sralph if (*ns) { 76756813Sralph c = kbdMapChar(*ns); 76856813Sralph if (outc == 0) { 76956813Sralph if (dtopDivertXInput) { 77056813Sralph (*dtopDivertXInput)(*ns); 77156813Sralph c = -1; /* consumed by X */ 77256813Sralph } else if (c >= 0) 77356813Sralph (*linesw[tp->t_line].l_rint)(c, tp); 77456813Sralph } 77556813Sralph /* return the related keycode anyways */ 77656813Sralph if ((c >= 0) && (retc == 0)) 77756813Sralph retc = c; 77856813Sralph } 77956813Sralph outc = retc; 78056813Sralph /* install new scan state */ 78156813Sralph if (msg_len == 1) 78256813Sralph dev->keyboard.last_codes[0] = save[0]; 78356813Sralph else if (msg_len > 0) 78456813Sralph bcopy(save, dev->keyboard.last_codes, msg_len); 78556813Sralph dev->keyboard.last_codes_count = msg_len; 78656813Sralph return (outc); 78756813Sralph } 78856813Sralph 78956813Sralph /* 790*57234Sralph * Timeout routine to do autorepeat. 79156813Sralph */ 79256813Sralph void 79356813Sralph dtop_keyboard_autorepeat(arg) 79456813Sralph void *arg; 79556813Sralph { 79656813Sralph dtop_device_t dev = (dtop_device_t)arg; 79756813Sralph int s; 79856813Sralph 79956813Sralph s = spltty(); 80056813Sralph if (dev->keyboard.k_ar_state != K_AR_IDLE) 801*57234Sralph dtop_keyboard_repeat(dev); 80256813Sralph 80356813Sralph if (dev->keyboard.k_ar_state == K_AR_OFF) 80456813Sralph dev->keyboard.k_ar_state = K_AR_IDLE; 80556813Sralph else 80656813Sralph timeout(dtop_keyboard_autorepeat, dev, dev->keyboard.poll_frequency); 80756813Sralph 80856813Sralph splx(s); 80956813Sralph } 810*57234Sralph 811*57234Sralph /* 812*57234Sralph * See if an autorepeat is required. 813*57234Sralph */ 814*57234Sralph static void 815*57234Sralph dtop_keyboard_repeat(dev) 816*57234Sralph dtop_device_t dev; 817*57234Sralph { 818*57234Sralph register int i, c; 819*57234Sralph register u_int t, t0; 820*57234Sralph struct tty *tp = dtop_tty; 821*57234Sralph 822*57234Sralph for (i = 0; i < dev->keyboard.last_codes_count; i++) { 823*57234Sralph c = (int)dev->keyboard.last_codes[i]; 824*57234Sralph if (c != DTOP_KBD_EMPTY && 825*57234Sralph (keymodes[(c >> 5) & 0x7] & (1 << (c & 0x1f))) == 0) { 826*57234Sralph /* 827*57234Sralph * Got a char. See if enough time from stroke, 828*57234Sralph * or from last repeat. 829*57234Sralph */ 830*57234Sralph t0 = (dev->keyboard.k_ar_state == K_AR_TRIGGER) ? 30 : 500; 831*57234Sralph t = TO_MS(time); 832*57234Sralph if ((t - dev->keyboard.last_msec) < t0) 833*57234Sralph return; 834*57234Sralph 835*57234Sralph dev->keyboard.k_ar_state = K_AR_TRIGGER; 836*57234Sralph 837*57234Sralph if (dtopDivertXInput) { 838*57234Sralph (*dtopDivertXInput)(KEY_REPEAT); 839*57234Sralph return; 840*57234Sralph } 841*57234Sralph 842*57234Sralph if ((c = kbdMapChar(KEY_REPEAT)) >= 0) 843*57234Sralph (*linesw[tp->t_line].l_rint)(c, tp); 844*57234Sralph return; 845*57234Sralph } 846*57234Sralph } 847*57234Sralph dev->keyboard.k_ar_state = K_AR_OFF; 848*57234Sralph } 84956813Sralph #endif 850