1*56813Sralph /*- 2*56813Sralph * Copyright (c) 1992 The Regents of the University of California. 3*56813Sralph * All rights reserved. 4*56813Sralph * 5*56813Sralph * This code is derived from software contributed to Berkeley by 6*56813Sralph * Ralph Campbell and Rick Macklem. 7*56813Sralph * 8*56813Sralph * %sccs.include.redist.c% 9*56813Sralph * 10*56813Sralph * @(#)dtop.c 7.1 (Berkeley) 11/15/92 11*56813Sralph */ 12*56813Sralph 13*56813Sralph /* 14*56813Sralph * Mach Operating System 15*56813Sralph * Copyright (c) 1991,1990,1989 Carnegie Mellon University 16*56813Sralph * All Rights Reserved. 17*56813Sralph * 18*56813Sralph * Permission to use, copy, modify and distribute this software and its 19*56813Sralph * documentation is hereby granted, provided that both the copyright 20*56813Sralph * notice and this permission notice appear in all copies of the 21*56813Sralph * software, derivative works or modified versions, and any portions 22*56813Sralph * thereof, and that both notices appear in supporting documentation. 23*56813Sralph * 24*56813Sralph * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS 25*56813Sralph * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR 26*56813Sralph * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 27*56813Sralph * 28*56813Sralph * Carnegie Mellon requests users of this software to return to 29*56813Sralph * 30*56813Sralph * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 31*56813Sralph * School of Computer Science 32*56813Sralph * Carnegie Mellon University 33*56813Sralph * Pittsburgh PA 15213-3890 34*56813Sralph * 35*56813Sralph * any improvements or extensions that they make and grant Carnegie the 36*56813Sralph * rights to redistribute these changes. 37*56813Sralph */ 38*56813Sralph /* 39*56813Sralph * Author: Alessandro Forin, Carnegie Mellon University 40*56813Sralph * 41*56813Sralph * Hardware-level operations for the Desktop serial line 42*56813Sralph * bus (i2c aka ACCESS). 43*56813Sralph */ 44*56813Sralph 45*56813Sralph #include <dtop.h> 46*56813Sralph #if NDTOP > 0 47*56813Sralph #include <sys/param.h> 48*56813Sralph #include <sys/systm.h> 49*56813Sralph #include <sys/ioctl.h> 50*56813Sralph #include <sys/tty.h> 51*56813Sralph #include <sys/proc.h> 52*56813Sralph #include <sys/map.h> 53*56813Sralph #include <sys/buf.h> 54*56813Sralph #include <sys/conf.h> 55*56813Sralph #include <sys/file.h> 56*56813Sralph #include <sys/uio.h> 57*56813Sralph #include <sys/kernel.h> 58*56813Sralph #include <sys/syslog.h> 59*56813Sralph 60*56813Sralph #include <machine/pmioctl.h> 61*56813Sralph #include <machine/machConst.h> 62*56813Sralph #include <machine/dc7085cons.h> 63*56813Sralph 64*56813Sralph #include <pmax/pmax/pmaxtype.h> 65*56813Sralph #include <pmax/pmax/maxine.h> 66*56813Sralph #include <pmax/pmax/asic.h> 67*56813Sralph 68*56813Sralph #include <pmax/dev/device.h> 69*56813Sralph #include <pmax/dev/dtopreg.h> 70*56813Sralph #include <pmax/dev/fbreg.h> 71*56813Sralph 72*56813Sralph extern int pmax_boardtype; 73*56813Sralph 74*56813Sralph extern int ttrstrt __P((void *)); 75*56813Sralph void dtop_keyboard_autorepeat __P((void *)); 76*56813Sralph int dtop_null_device_handler __P((dtop_device_t, dtop_message_t, int, int)); 77*56813Sralph int dtop_locator_handler __P((dtop_device_t, dtop_message_t, int, int)); 78*56813Sralph int dtop_keyboard_handler __P((dtop_device_t, dtop_message_t, int, int)); 79*56813Sralph int dtopparam __P((struct tty *, struct termios *)); 80*56813Sralph int dtopstop __P((struct tty *, int)); 81*56813Sralph void dtopstart __P((struct tty *)); 82*56813Sralph void dtopKBDPutc __P((dev_t, int)); 83*56813Sralph 84*56813Sralph struct tty dtop_tty[NDTOP]; 85*56813Sralph void (*dtopDivertXInput)(); /* X windows keyboard input routine */ 86*56813Sralph void (*dtopMouseEvent)(); /* X windows mouse motion event routine */ 87*56813Sralph void (*dtopMouseButtons)(); /* X windows mouse buttons event routine */ 88*56813Sralph 89*56813Sralph #define DTOP_MAX_POLL 0x7fff /* about half a sec */ 90*56813Sralph 91*56813Sralph typedef volatile unsigned int *data_reg_t; /* uC */ 92*56813Sralph #define DTOP_GET_BYTE(data) (((*(data)) >> 8) & 0xff) 93*56813Sralph #define DTOP_PUT_BYTE(data,c) { *(data) = (c) << 8; } 94*56813Sralph 95*56813Sralph typedef volatile unsigned int *poll_reg_t; /* SIR */ 96*56813Sralph #define DTOP_RX_AVAIL(poll) (*(poll) & 1) 97*56813Sralph #define DTOP_TX_AVAIL(poll) (*(poll) & 2) 98*56813Sralph 99*56813Sralph #define GET_SHORT(b0,b1) (((b0)<<8)|(b1)) 100*56813Sralph 101*56813Sralph /* 102*56813Sralph * Driver status 103*56813Sralph */ 104*56813Sralph struct dtop_softc { 105*56813Sralph data_reg_t data; 106*56813Sralph poll_reg_t poll; 107*56813Sralph char polling_mode; 108*56813Sralph char probed_once; 109*56813Sralph short bad_pkts; 110*56813Sralph 111*56813Sralph struct dtop_ds { 112*56813Sralph int (*handler)(); 113*56813Sralph dtop_device status; 114*56813Sralph } device[(DTOP_ADDR_DEFAULT - DTOP_ADDR_FIRST) >> 1]; 115*56813Sralph 116*56813Sralph # define DTOP_DEVICE_NO(address) (((address)-DTOP_ADDR_FIRST)>>1) 117*56813Sralph 118*56813Sralph } dtop_softc[NDTOP]; 119*56813Sralph 120*56813Sralph typedef struct dtop_softc *dtop_softc_t; 121*56813Sralph struct tty dtop_tty[NDTOP]; 122*56813Sralph static int dtopenabled = 0; 123*56813Sralph 124*56813Sralph /* 125*56813Sralph * Definition of the driver for the auto-configuration program. 126*56813Sralph */ 127*56813Sralph int dtopprobe(); 128*56813Sralph void dtopintr(); 129*56813Sralph struct driver dtopdriver = { 130*56813Sralph "dtop", dtopprobe, 0, 0, dtopintr, 131*56813Sralph }; 132*56813Sralph 133*56813Sralph dtopprobe(cp) 134*56813Sralph struct pmax_ctlr *cp; 135*56813Sralph { 136*56813Sralph register struct tty *tp; 137*56813Sralph register int cntr; 138*56813Sralph int dtopunit = cp->pmax_unit, i, s; 139*56813Sralph dtop_softc_t dtop; 140*56813Sralph 141*56813Sralph if (dtopunit >= NDTOP) 142*56813Sralph return (0); 143*56813Sralph if (badaddr(cp->pmax_addr, 2)) 144*56813Sralph return (0); 145*56813Sralph dtop = &dtop_softc[dtopunit]; 146*56813Sralph 147*56813Sralph dtop->poll = (poll_reg_t)MACH_PHYS_TO_UNCACHED(XINE_REG_INTR); 148*56813Sralph dtop->data = (data_reg_t)cp->pmax_addr; 149*56813Sralph 150*56813Sralph for (i = 0; i < DTOP_MAX_DEVICES; i++) 151*56813Sralph dtop->device[i].handler = dtop_null_device_handler; 152*56813Sralph 153*56813Sralph /* a lot more needed here, fornow: */ 154*56813Sralph dtop->device[DTOP_DEVICE_NO(0x6a)].handler = dtop_locator_handler; 155*56813Sralph dtop->device[DTOP_DEVICE_NO(0x6c)].handler = dtop_keyboard_handler; 156*56813Sralph dtop->device[DTOP_DEVICE_NO(0x6c)].status.keyboard.poll_frequency = 157*56813Sralph (hz * 5) / 100; /* x0.01 secs */ 158*56813Sralph dtop->device[DTOP_DEVICE_NO(0x6c)].status.keyboard.k_ar_state = 159*56813Sralph K_AR_IDLE; 160*56813Sralph 161*56813Sralph /* 162*56813Sralph * Sometimes a first interrupt gets lost, so just in case 163*56813Sralph * poke it now. 164*56813Sralph */ 165*56813Sralph dtopintr(dtopunit); 166*56813Sralph dtopenabled = 1; 167*56813Sralph return (1); 168*56813Sralph } 169*56813Sralph 170*56813Sralph dtopopen(dev, flag, mode, p) 171*56813Sralph dev_t dev; 172*56813Sralph int flag, mode; 173*56813Sralph struct proc *p; 174*56813Sralph { 175*56813Sralph register struct tty *tp; 176*56813Sralph register int unit; 177*56813Sralph int s, error = 0; 178*56813Sralph 179*56813Sralph unit = minor(dev); 180*56813Sralph if (unit >= NDTOP) 181*56813Sralph return (ENXIO); 182*56813Sralph tp = &dtop_tty[unit]; 183*56813Sralph tp->t_oproc = dtopstart; 184*56813Sralph tp->t_param = dtopparam; 185*56813Sralph tp->t_dev = dev; 186*56813Sralph if ((tp->t_state & TS_ISOPEN) == 0) { 187*56813Sralph tp->t_state |= TS_WOPEN; 188*56813Sralph ttychars(tp); 189*56813Sralph if (tp->t_ispeed == 0) { 190*56813Sralph tp->t_iflag = TTYDEF_IFLAG; 191*56813Sralph tp->t_oflag = TTYDEF_OFLAG; 192*56813Sralph tp->t_cflag = TTYDEF_CFLAG; 193*56813Sralph tp->t_lflag = TTYDEF_LFLAG; 194*56813Sralph tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; 195*56813Sralph } 196*56813Sralph (void) dtopparam(tp, &tp->t_termios); 197*56813Sralph ttsetwater(tp); 198*56813Sralph } else if ((tp->t_state & TS_XCLUDE) && curproc->p_ucred->cr_uid != 0) 199*56813Sralph return (EBUSY); 200*56813Sralph s = spltty(); 201*56813Sralph while (!(flag & O_NONBLOCK) && !(tp->t_cflag & CLOCAL) && 202*56813Sralph !(tp->t_state & TS_CARR_ON)) { 203*56813Sralph tp->t_state |= TS_WOPEN; 204*56813Sralph if (error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH, 205*56813Sralph ttopen, 0)) 206*56813Sralph break; 207*56813Sralph } 208*56813Sralph splx(s); 209*56813Sralph if (error) 210*56813Sralph return (error); 211*56813Sralph error = (*linesw[tp->t_line].l_open)(dev, tp); 212*56813Sralph return (error); 213*56813Sralph } 214*56813Sralph 215*56813Sralph /*ARGSUSED*/ 216*56813Sralph dtopclose(dev, flag, mode, p) 217*56813Sralph dev_t dev; 218*56813Sralph int flag, mode; 219*56813Sralph struct proc *p; 220*56813Sralph { 221*56813Sralph register struct tty *tp; 222*56813Sralph register int unit; 223*56813Sralph 224*56813Sralph unit = minor(dev); 225*56813Sralph tp = &dtop_tty[unit]; 226*56813Sralph (*linesw[tp->t_line].l_close)(tp, flag); 227*56813Sralph return (ttyclose(tp)); 228*56813Sralph } 229*56813Sralph 230*56813Sralph dtopread(dev, uio, flag) 231*56813Sralph dev_t dev; 232*56813Sralph struct uio *uio; 233*56813Sralph { 234*56813Sralph register struct tty *tp; 235*56813Sralph 236*56813Sralph tp = &dtop_tty[minor(dev)]; 237*56813Sralph return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); 238*56813Sralph } 239*56813Sralph 240*56813Sralph dtopwrite(dev, uio, flag) 241*56813Sralph dev_t dev; 242*56813Sralph struct uio *uio; 243*56813Sralph { 244*56813Sralph register struct tty *tp; 245*56813Sralph 246*56813Sralph tp = &dtop_tty[minor(dev)]; 247*56813Sralph return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); 248*56813Sralph } 249*56813Sralph 250*56813Sralph /*ARGSUSED*/ 251*56813Sralph dtopioctl(dev, cmd, data, flag, p) 252*56813Sralph dev_t dev; 253*56813Sralph int cmd; 254*56813Sralph caddr_t data; 255*56813Sralph int flag; 256*56813Sralph struct proc *p; 257*56813Sralph { 258*56813Sralph register struct tty *tp; 259*56813Sralph register int unit = minor(dev); 260*56813Sralph int error; 261*56813Sralph 262*56813Sralph tp = &dtop_tty[unit]; 263*56813Sralph error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); 264*56813Sralph if (error >= 0) 265*56813Sralph return (error); 266*56813Sralph error = ttioctl(tp, cmd, data, flag); 267*56813Sralph if (error >= 0) 268*56813Sralph return (error); 269*56813Sralph 270*56813Sralph switch (cmd) { 271*56813Sralph 272*56813Sralph case TIOCSBRK: 273*56813Sralph ttyoutput(0, tp); 274*56813Sralph break; 275*56813Sralph 276*56813Sralph case TIOCCBRK: 277*56813Sralph ttyoutput(0, tp); 278*56813Sralph break; 279*56813Sralph 280*56813Sralph case TIOCMGET: 281*56813Sralph *(int *)data = DML_DTR | DML_DSR | DML_CAR; 282*56813Sralph break; 283*56813Sralph 284*56813Sralph default: 285*56813Sralph return (ENOTTY); 286*56813Sralph } 287*56813Sralph return (0); 288*56813Sralph } 289*56813Sralph 290*56813Sralph /* 291*56813Sralph * Interrupt routine 292*56813Sralph */ 293*56813Sralph void 294*56813Sralph dtopintr(unit) 295*56813Sralph int unit; 296*56813Sralph { 297*56813Sralph dtop_message msg; 298*56813Sralph int devno; 299*56813Sralph dtop_softc_t dtop; 300*56813Sralph 301*56813Sralph dtop = &dtop_softc[unit]; 302*56813Sralph if (dtop_get_packet(dtop, &msg) < 0) { 303*56813Sralph if (dtopenabled) 304*56813Sralph printf("%s", "dtop: overrun (or stray)\n"); 305*56813Sralph return; 306*56813Sralph } 307*56813Sralph 308*56813Sralph devno = DTOP_DEVICE_NO(msg.src_address); 309*56813Sralph if (devno < 0 || devno > 15) 310*56813Sralph return; 311*56813Sralph 312*56813Sralph (void) (*dtop->device[devno].handler) 313*56813Sralph (&dtop->device[devno].status, &msg, 314*56813Sralph DTOP_EVENT_RECEIVE_PACKET, 0); 315*56813Sralph } 316*56813Sralph 317*56813Sralph void 318*56813Sralph dtopstart(tp) 319*56813Sralph register struct tty *tp; 320*56813Sralph { 321*56813Sralph register int cc; 322*56813Sralph int s; 323*56813Sralph 324*56813Sralph s = spltty(); 325*56813Sralph if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) 326*56813Sralph goto out; 327*56813Sralph if (tp->t_outq.c_cc <= tp->t_lowat) { 328*56813Sralph if (tp->t_state & TS_ASLEEP) { 329*56813Sralph tp->t_state &= ~TS_ASLEEP; 330*56813Sralph wakeup((caddr_t)&tp->t_outq); 331*56813Sralph } 332*56813Sralph selwakeup(&tp->t_wsel); 333*56813Sralph } 334*56813Sralph if (tp->t_outq.c_cc == 0) 335*56813Sralph goto out; 336*56813Sralph /* handle console specially */ 337*56813Sralph if (tp == dtop_tty) { 338*56813Sralph while (tp->t_outq.c_cc > 0) { 339*56813Sralph cc = getc(&tp->t_outq) & 0x7f; 340*56813Sralph cnputc(cc); 341*56813Sralph } 342*56813Sralph /* 343*56813Sralph * After we flush the output queue we may need to wake 344*56813Sralph * up the process that made the output. 345*56813Sralph */ 346*56813Sralph if (tp->t_outq.c_cc <= tp->t_lowat) { 347*56813Sralph if (tp->t_state & TS_ASLEEP) { 348*56813Sralph tp->t_state &= ~TS_ASLEEP; 349*56813Sralph wakeup((caddr_t)&tp->t_outq); 350*56813Sralph } 351*56813Sralph selwakeup(&tp->t_wsel); 352*56813Sralph } 353*56813Sralph } 354*56813Sralph out: 355*56813Sralph splx(s); 356*56813Sralph } 357*56813Sralph 358*56813Sralph void 359*56813Sralph dtopKBDPutc(dev, c) 360*56813Sralph dev_t dev; 361*56813Sralph int c; 362*56813Sralph { 363*56813Sralph 364*56813Sralph /* 365*56813Sralph * Not yet, someday we will know how to send commands to the 366*56813Sralph * LK501 over the Access bus. 367*56813Sralph */ 368*56813Sralph } 369*56813Sralph 370*56813Sralph /* 371*56813Sralph * Take a packet off dtop interface 372*56813Sralph * A packet MUST be there, this is not checked for. 373*56813Sralph */ 374*56813Sralph #define DTOP_ESC_CHAR 0xf8 375*56813Sralph dtop_escape(c) 376*56813Sralph { 377*56813Sralph /* I donno much about this stuff.. */ 378*56813Sralph switch (c) { 379*56813Sralph case 0xe8: return (0xf8); 380*56813Sralph case 0xe9: return (0xf9); 381*56813Sralph case 0xea: return (0xfa); 382*56813Sralph case 0xeb: return (0xfb); 383*56813Sralph default: /* printf("{esc %x}", c); */ 384*56813Sralph return (c); 385*56813Sralph } 386*56813Sralph } 387*56813Sralph 388*56813Sralph dtop_get_packet(dtop, pkt) 389*56813Sralph dtop_softc_t dtop; 390*56813Sralph dtop_message_t pkt; 391*56813Sralph { 392*56813Sralph register poll_reg_t poll; 393*56813Sralph register data_reg_t data; 394*56813Sralph register int max, i, len; 395*56813Sralph register unsigned char c; 396*56813Sralph 397*56813Sralph poll = dtop->poll; 398*56813Sralph data = dtop->data; 399*56813Sralph 400*56813Sralph /* 401*56813Sralph * The interface does not handle us the first byte, 402*56813Sralph * which is our address and cannot ever be anything 403*56813Sralph * else but 0x50. This is a good thing, it makes 404*56813Sralph * the average packet exactly one word long, too. 405*56813Sralph */ 406*56813Sralph for (max = 0; (max < DTOP_MAX_POLL) && !DTOP_RX_AVAIL(poll); max++) 407*56813Sralph DELAY(16); 408*56813Sralph if (max == DTOP_MAX_POLL) 409*56813Sralph goto bad; 410*56813Sralph pkt->src_address = DTOP_GET_BYTE(data); 411*56813Sralph 412*56813Sralph for (max = 0; (max < DTOP_MAX_POLL) && !DTOP_RX_AVAIL(poll); max++) 413*56813Sralph DELAY(16); 414*56813Sralph if (max == DTOP_MAX_POLL) 415*56813Sralph goto bad; 416*56813Sralph pkt->code.bits = DTOP_GET_BYTE(data); 417*56813Sralph 418*56813Sralph /* 419*56813Sralph * Now get data and checksum 420*56813Sralph */ 421*56813Sralph len = pkt->code.val.len + 1; 422*56813Sralph c = 0; 423*56813Sralph for (i = 0; i < len; i++) { 424*56813Sralph again: 425*56813Sralph for (max = 0; (max < DTOP_MAX_POLL) && !DTOP_RX_AVAIL(poll); max++) 426*56813Sralph DELAY(16); 427*56813Sralph if (max == DTOP_MAX_POLL) 428*56813Sralph goto bad; 429*56813Sralph if (c == DTOP_ESC_CHAR) { 430*56813Sralph c = dtop_escape(DTOP_GET_BYTE(data) & 0xff); 431*56813Sralph } else { 432*56813Sralph c = DTOP_GET_BYTE(data); 433*56813Sralph if (c == DTOP_ESC_CHAR) 434*56813Sralph goto again; 435*56813Sralph } 436*56813Sralph pkt->body[i] = c; 437*56813Sralph } 438*56813Sralph return (len); 439*56813Sralph bad: 440*56813Sralph dtop->bad_pkts++; 441*56813Sralph return (-1); 442*56813Sralph } 443*56813Sralph 444*56813Sralph /* 445*56813Sralph * Get a keyboard char for the console 446*56813Sralph */ 447*56813Sralph dtopKBDGetc() 448*56813Sralph { 449*56813Sralph register int c; 450*56813Sralph dtop_softc_t dtop; 451*56813Sralph 452*56813Sralph dtop = &dtop_softc[0]; 453*56813Sralph again: 454*56813Sralph c = -1; 455*56813Sralph 456*56813Sralph /* 457*56813Sralph * Now check keyboard 458*56813Sralph */ 459*56813Sralph if (DTOP_RX_AVAIL(dtop->poll)) { 460*56813Sralph 461*56813Sralph dtop_message msg; 462*56813Sralph struct dtop_ds *ds; 463*56813Sralph 464*56813Sralph if (dtop_get_packet(dtop, &msg) >= 0) { 465*56813Sralph 466*56813Sralph ds = &dtop->device[DTOP_DEVICE_NO(msg.src_address)]; 467*56813Sralph if (ds->handler == dtop_keyboard_handler) { 468*56813Sralph 469*56813Sralph c = dtop_keyboard_handler( 470*56813Sralph &ds->status, &msg, 471*56813Sralph DTOP_EVENT_RECEIVE_PACKET, -1); 472*56813Sralph 473*56813Sralph if (c > 0) return c; 474*56813Sralph 475*56813Sralph c = -1; 476*56813Sralph } 477*56813Sralph } 478*56813Sralph } 479*56813Sralph 480*56813Sralph if (c == -1) { 481*56813Sralph DELAY(100); 482*56813Sralph goto again; 483*56813Sralph } 484*56813Sralph 485*56813Sralph return c; 486*56813Sralph } 487*56813Sralph 488*56813Sralph int 489*56813Sralph dtopparam(tp, t) 490*56813Sralph struct tty *tp; 491*56813Sralph struct termios *t; 492*56813Sralph { 493*56813Sralph if (tp->t_ispeed == 0) 494*56813Sralph ttymodem(tp, 0); 495*56813Sralph else 496*56813Sralph /* called too early to invoke ttymodem, sigh */ 497*56813Sralph tp->t_state |= TS_CARR_ON; 498*56813Sralph return (0); 499*56813Sralph } 500*56813Sralph 501*56813Sralph /* 502*56813Sralph * Stop output on a line. 503*56813Sralph */ 504*56813Sralph /*ARGSUSED*/ 505*56813Sralph dtopstop(tp, flag) 506*56813Sralph register struct tty *tp; 507*56813Sralph int flag; 508*56813Sralph { 509*56813Sralph int s; 510*56813Sralph 511*56813Sralph s = spltty(); 512*56813Sralph if (tp->t_state & TS_BUSY) { 513*56813Sralph if (!(tp->t_state & TS_TTSTOP)) 514*56813Sralph tp->t_state |= TS_FLUSH; 515*56813Sralph } 516*56813Sralph splx(s); 517*56813Sralph } 518*56813Sralph 519*56813Sralph /* 520*56813Sralph * Default handler function 521*56813Sralph */ 522*56813Sralph int 523*56813Sralph dtop_null_device_handler(dev, msg, event, outc) 524*56813Sralph dtop_device_t dev; 525*56813Sralph dtop_message_t msg; 526*56813Sralph int event; 527*56813Sralph int outc; 528*56813Sralph { 529*56813Sralph /* See if the message was to the default address (powerup) */ 530*56813Sralph 531*56813Sralph /* Uhmm, donno how to handle this. Drop it */ 532*56813Sralph if (event == DTOP_EVENT_RECEIVE_PACKET) 533*56813Sralph dev->unknown_report = *msg; 534*56813Sralph return 0; 535*56813Sralph } 536*56813Sralph 537*56813Sralph /* 538*56813Sralph * Handler for locator devices (mice) 539*56813Sralph */ 540*56813Sralph int 541*56813Sralph dtop_locator_handler(dev, msg, event, outc) 542*56813Sralph dtop_device_t dev; 543*56813Sralph dtop_message_t msg; 544*56813Sralph int event; 545*56813Sralph int outc; 546*56813Sralph { 547*56813Sralph register unsigned short buttons; 548*56813Sralph register short coord; 549*56813Sralph register int moved = 0; 550*56813Sralph static MouseReport currentRep; 551*56813Sralph register MouseReport *mrp = ¤tRep; 552*56813Sralph 553*56813Sralph if (dtopMouseButtons) { 554*56813Sralph /* 555*56813Sralph * Do the position first 556*56813Sralph */ 557*56813Sralph coord = GET_SHORT(msg->body[2], msg->body[3]); 558*56813Sralph mrp->dx = coord; 559*56813Sralph if (coord != 0) 560*56813Sralph moved = 1; 561*56813Sralph coord = GET_SHORT(msg->body[4], msg->body[5]); 562*56813Sralph coord = - coord; 563*56813Sralph mrp->dy = coord; 564*56813Sralph if (coord != 0) 565*56813Sralph moved = 1; 566*56813Sralph 567*56813Sralph /* 568*56813Sralph * Time for the buttons now 569*56813Sralph */ 570*56813Sralph buttons = GET_SHORT(msg->body[0], msg->body[1]); 571*56813Sralph mrp->state = MOUSE_Y_SIGN | MOUSE_X_SIGN | (buttons & 0x7); 572*56813Sralph if (moved) 573*56813Sralph (*dtopMouseEvent)(mrp); 574*56813Sralph (*dtopMouseButtons)(mrp); 575*56813Sralph } 576*56813Sralph return (0); 577*56813Sralph } 578*56813Sralph 579*56813Sralph /* 580*56813Sralph * Handler for keyboard devices 581*56813Sralph * Special case: outc set for recv packet means 582*56813Sralph * we are inside the kernel debugger 583*56813Sralph */ 584*56813Sralph int 585*56813Sralph dtop_keyboard_handler(dev, msg, event, outc) 586*56813Sralph dtop_device_t dev; 587*56813Sralph dtop_message_t msg; 588*56813Sralph int event; 589*56813Sralph int outc; 590*56813Sralph { 591*56813Sralph register u_char *ls, *le, *ns, *ne; 592*56813Sralph u_char save[11], retc; 593*56813Sralph int msg_len, c; 594*56813Sralph struct tty *tp = &dtop_tty[0]; 595*56813Sralph 596*56813Sralph /* 597*56813Sralph * Fiddle about emulating an lk201 keyboard. The lk501 598*56813Sralph * designers carefully ensured that keyboard handlers could be 599*56813Sralph * stateless, then we turn around and use lots of state to 600*56813Sralph * emulate the stateful lk201, since the X11R5 X servers 601*56813Sralph * only know about the lk201... (oh well) 602*56813Sralph */ 603*56813Sralph if (event != DTOP_EVENT_RECEIVE_PACKET) { 604*56813Sralph switch (event) { 605*56813Sralph case DTOP_EVENT_POLL: 606*56813Sralph { 607*56813Sralph register unsigned int t, t0; 608*56813Sralph 609*56813Sralph /* 610*56813Sralph * Note we will always have at least the 611*56813Sralph * end-of-list marker present (a zero) 612*56813Sralph * Here stop and trigger of autorepeat. 613*56813Sralph * Do not repeat shift keys, either. 614*56813Sralph */ 615*56813Sralph { 616*56813Sralph register unsigned char uc, i = 0; 617*56813Sralph 618*56813Sralph rpt_char: 619*56813Sralph uc = dev->keyboard.last_codes[i]; 620*56813Sralph 621*56813Sralph if (uc == DTOP_KBD_EMPTY) { 622*56813Sralph dev->keyboard.k_ar_state = K_AR_OFF; 623*56813Sralph return 0; 624*56813Sralph } 625*56813Sralph if ((uc >= KEY_R_SHIFT) && (uc <= KEY_R_ALT)) { 626*56813Sralph /* sometimes swapped. Grrr. */ 627*56813Sralph if (++i < dev->keyboard.last_codes_count) 628*56813Sralph goto rpt_char; 629*56813Sralph dev->keyboard.k_ar_state = K_AR_OFF; 630*56813Sralph return 0; 631*56813Sralph } 632*56813Sralph c = uc; 633*56813Sralph } 634*56813Sralph 635*56813Sralph /* 636*56813Sralph * Got a char. See if enough time from stroke, 637*56813Sralph * or from last repeat. 638*56813Sralph */ 639*56813Sralph t0 = (dev->keyboard.k_ar_state == K_AR_TRIGGER) ? 30 : 500; 640*56813Sralph t = TO_MS(time); 641*56813Sralph if ((t - dev->keyboard.last_msec) < t0) 642*56813Sralph return 0; 643*56813Sralph 644*56813Sralph dev->keyboard.k_ar_state = K_AR_TRIGGER; 645*56813Sralph 646*56813Sralph if (dtopDivertXInput) { 647*56813Sralph (*dtopDivertXInput)(KEY_REPEAT); 648*56813Sralph return (0); 649*56813Sralph } 650*56813Sralph if ((outc = kbdMapChar(KEY_REPEAT)) >= 0) 651*56813Sralph (*linesw[tp->t_line].l_rint)(outc, tp); 652*56813Sralph return 0; 653*56813Sralph } 654*56813Sralph default: 655*56813Sralph printf("Unknown dtop keyb\n"); 656*56813Sralph } 657*56813Sralph return -1; 658*56813Sralph } 659*56813Sralph 660*56813Sralph msg_len = msg->code.val.len; 661*56813Sralph 662*56813Sralph /* Check for errors */ 663*56813Sralph c = msg->body[0]; 664*56813Sralph if ((c < DTOP_KBD_KEY_MIN) && (c != DTOP_KBD_EMPTY)) { 665*56813Sralph printf("Keyboard error: %x %x %x..\n", msg_len, c, msg->body[1]); 666*56813Sralph if (c != DTOP_KBD_OUT_ERR) return -1; 667*56813Sralph /* spec sez if scan list overflow still there is data */ 668*56813Sralph msg->body[0] = 0; 669*56813Sralph } 670*56813Sralph 671*56813Sralph dev->keyboard.last_msec = TO_MS(time); 672*56813Sralph 673*56813Sralph switch (dev->keyboard.k_ar_state) { 674*56813Sralph case K_AR_IDLE: 675*56813Sralph if (outc != 0xff) /* from debugger, might be too early */ 676*56813Sralph dtop_keyboard_autorepeat(dev); 677*56813Sralph /* fall through */ 678*56813Sralph case K_AR_TRIGGER: 679*56813Sralph dev->keyboard.k_ar_state = K_AR_ACTIVE; 680*56813Sralph break; 681*56813Sralph case K_AR_ACTIVE: 682*56813Sralph break; 683*56813Sralph case K_AR_OFF: 684*56813Sralph printf("dtop keyb off?\n"); 685*56813Sralph dev->keyboard.k_ar_state = K_AR_IDLE; 686*56813Sralph } 687*56813Sralph 688*56813Sralph /* 689*56813Sralph * To make things readable, do a first pass cancelling out 690*56813Sralph * all keys that are still pressed, and a second one generating 691*56813Sralph * events. While generating events, do the upstrokes first 692*56813Sralph * from oldest to youngest, then the downstrokes from oldest 693*56813Sralph * to youngest. This copes with lost packets and provides 694*56813Sralph * a reasonable model even if scans are too slow. 695*56813Sralph */ 696*56813Sralph 697*56813Sralph /* make a copy of new state first */ 698*56813Sralph if (msg_len == 1) 699*56813Sralph save[0] = msg->body[0]; 700*56813Sralph else if (msg_len > 0) 701*56813Sralph bcopy(msg->body, save, msg_len); 702*56813Sralph 703*56813Sralph /* 704*56813Sralph * Cancel out any keys in both the last and current message as 705*56813Sralph * they are unchanged. 706*56813Sralph */ 707*56813Sralph if (msg_len > 0 && dev->keyboard.last_codes_count > 0) { 708*56813Sralph ls = dev->keyboard.last_codes; 709*56813Sralph le = &dev->keyboard.last_codes[dev->keyboard.last_codes_count]; 710*56813Sralph ne = &msg->body[msg_len]; 711*56813Sralph for (; ls < le; ls++) { 712*56813Sralph for (ns = msg->body; ns < ne; ns++) 713*56813Sralph if (*ls == *ns) { 714*56813Sralph *ls = *ns = 0; 715*56813Sralph break; 716*56813Sralph } 717*56813Sralph } 718*56813Sralph } 719*56813Sralph 720*56813Sralph /* 721*56813Sralph * Now generate all upstrokes 722*56813Sralph */ 723*56813Sralph le = dev->keyboard.last_codes; 724*56813Sralph ls = &dev->keyboard.last_codes[dev->keyboard.last_codes_count - 1]; 725*56813Sralph for ( ; ls >= le; ls--) 726*56813Sralph if (c = *ls) { 727*56813Sralph /* 728*56813Sralph * If there are no other down/up keys currently down, we 729*56813Sralph * should actually generate a KEY_UP, but that would require 730*56813Sralph * a lot more state. 731*56813Sralph */ 732*56813Sralph (void) kbdMapChar(c); 733*56813Sralph 734*56813Sralph if (outc == 0 && dtopDivertXInput) 735*56813Sralph (*dtopDivertXInput)(c); 736*56813Sralph } 737*56813Sralph /* 738*56813Sralph * And finally the downstrokes 739*56813Sralph */ 740*56813Sralph ne = (char*)msg->body; 741*56813Sralph ns = (char*)&msg->body[msg_len - 1]; 742*56813Sralph retc = 0; 743*56813Sralph for ( ; ns >= ne; ns--) 744*56813Sralph if (*ns) { 745*56813Sralph c = kbdMapChar(*ns); 746*56813Sralph if (outc == 0) { 747*56813Sralph if (dtopDivertXInput) { 748*56813Sralph (*dtopDivertXInput)(*ns); 749*56813Sralph c = -1; /* consumed by X */ 750*56813Sralph } else if (c >= 0) 751*56813Sralph (*linesw[tp->t_line].l_rint)(c, tp); 752*56813Sralph } 753*56813Sralph /* return the related keycode anyways */ 754*56813Sralph if ((c >= 0) && (retc == 0)) 755*56813Sralph retc = c; 756*56813Sralph } 757*56813Sralph outc = retc; 758*56813Sralph /* install new scan state */ 759*56813Sralph if (msg_len == 1) 760*56813Sralph dev->keyboard.last_codes[0] = save[0]; 761*56813Sralph else if (msg_len > 0) 762*56813Sralph bcopy(save, dev->keyboard.last_codes, msg_len); 763*56813Sralph dev->keyboard.last_codes_count = msg_len; 764*56813Sralph return (outc); 765*56813Sralph } 766*56813Sralph 767*56813Sralph /* 768*56813Sralph * Polled operations: we must do autorepeat by hand. Sigh. 769*56813Sralph */ 770*56813Sralph void 771*56813Sralph dtop_keyboard_autorepeat(arg) 772*56813Sralph void *arg; 773*56813Sralph { 774*56813Sralph dtop_device_t dev = (dtop_device_t)arg; 775*56813Sralph int s; 776*56813Sralph 777*56813Sralph s = spltty(); 778*56813Sralph if (dev->keyboard.k_ar_state != K_AR_IDLE) 779*56813Sralph (void)dtop_keyboard_handler(dev, 0, DTOP_EVENT_POLL, 0); 780*56813Sralph 781*56813Sralph if (dev->keyboard.k_ar_state == K_AR_OFF) 782*56813Sralph dev->keyboard.k_ar_state = K_AR_IDLE; 783*56813Sralph else 784*56813Sralph timeout(dtop_keyboard_autorepeat, dev, dev->keyboard.poll_frequency); 785*56813Sralph 786*56813Sralph splx(s); 787*56813Sralph } 788*56813Sralph #endif 789