152130Smckusick /* 252130Smckusick * Copyright (c) 1992 Regents of the University of California. 352130Smckusick * All rights reserved. 452130Smckusick * 552130Smckusick * This code is derived from software contributed to Berkeley by 652130Smckusick * Ralph Campbell. 752130Smckusick * 852130Smckusick * %sccs.include.redist.c% 952130Smckusick * 10*52674Smckusick * @(#)dc.c 7.2 (Berkeley) 02/26/92 1152130Smckusick * 1252130Smckusick * devDC7085.c -- 1352130Smckusick * 1452130Smckusick * This file contains machine-dependent routines that handle the 1552130Smckusick * output queue for the serial lines. 1652130Smckusick * 1752130Smckusick * Copyright (C) 1989 Digital Equipment Corporation. 1852130Smckusick * Permission to use, copy, modify, and distribute this software and 1952130Smckusick * its documentation for any purpose and without fee is hereby granted, 2052130Smckusick * provided that the above copyright notice appears in all copies. 2152130Smckusick * Digital Equipment Corporation makes no representations about the 2252130Smckusick * suitability of this software for any purpose. It is provided "as is" 2352130Smckusick * without express or implied warranty. 2452130Smckusick * 2552130Smckusick * from: $Header: /sprite/src/kernel/dev/ds3100.md/RCS/devDC7085.c, 2652130Smckusick * v 1.4 89/08/29 11:55:30 nelson Exp $ SPRITE (DECWRL)"; 2752130Smckusick */ 2852130Smckusick 2952130Smckusick #include "dc.h" 3052130Smckusick #if NDC > 0 3152130Smckusick /* 3252130Smckusick * DC7085 (DZ-11 look alike) Driver 3352130Smckusick */ 3452130Smckusick #include "param.h" 3552130Smckusick #include "systm.h" 3652130Smckusick #include "ioctl.h" 3752130Smckusick #include "tty.h" 3852130Smckusick #include "proc.h" 3952130Smckusick #include "map.h" 4052130Smckusick #include "buf.h" 4152130Smckusick #include "conf.h" 4252130Smckusick #include "file.h" 4352130Smckusick #include "uio.h" 4452130Smckusick #include "kernel.h" 4552130Smckusick #include "syslog.h" 4652130Smckusick 4752130Smckusick #include "machine/dc7085cons.h" 4852130Smckusick 4952130Smckusick #include "device.h" 5052130Smckusick #include "pdma.h" 5152130Smckusick 5252130Smckusick /* 5352130Smckusick * Driver information for auto-configuration stuff. 5452130Smckusick */ 5552130Smckusick int dcprobe(); 5652130Smckusick struct driver dcdriver = { 5752130Smckusick "dc", dcprobe, 0, 0, 5852130Smckusick }; 5952130Smckusick 6052130Smckusick #define NDCLINE (NDC*4) 6152130Smckusick 6252130Smckusick extern int dcstart(), dcxint(); 6352130Smckusick extern int ttrstrt(); 6452130Smckusick 6552130Smckusick struct tty dc_tty[NDCLINE]; 6652130Smckusick int dc_cnt = NDCLINE; 6752130Smckusick int dcDivertXInput; /* true if diverting KBD input to X */ 6852130Smckusick #ifdef DEBUG 6952130Smckusick int debugChar; 7052130Smckusick #endif 7152130Smckusick 7252130Smckusick /* 7352130Smckusick * Software copy of brk register since it isn't readable 7452130Smckusick */ 7552130Smckusick int dc_brk[NDC]; 7652130Smckusick char dcsoftCAR[NDC]; /* mask of dc's with carrier on (DSR) */ 7752130Smckusick 7852130Smckusick /* 7952130Smckusick * The DC7085 doesn't interrupt on carrier transitions, so 8052130Smckusick * we have to use a timer to watch it. 8152130Smckusick */ 8252130Smckusick int dc_timer; /* true if timer started */ 8352130Smckusick 8452130Smckusick /* 8552130Smckusick * Pdma structures for fast output code 8652130Smckusick */ 8752130Smckusick struct pdma dcpdma[NDCLINE]; 8852130Smckusick 8952130Smckusick struct speedtab dcspeedtab[] = { 9052130Smckusick 0, 0, 9152130Smckusick 50, LPR_B50, 9252130Smckusick 75, LPR_B75, 9352130Smckusick 110, LPR_B110, 9452130Smckusick 134, LPR_B134, 9552130Smckusick 150, LPR_B150, 9652130Smckusick 300, LPR_B300, 9752130Smckusick 600, LPR_B600, 9852130Smckusick 1200, LPR_B1200, 9952130Smckusick 1800, LPR_B1800, 10052130Smckusick 2400, LPR_B2400, 10152130Smckusick 4800, LPR_B4800, 10252130Smckusick 9600, LPR_B9600, 10352130Smckusick -1, -1 10452130Smckusick }; 10552130Smckusick 10652130Smckusick #ifndef PORTSELECTOR 10752130Smckusick #define ISPEED TTYDEF_SPEED 10852130Smckusick #define LFLAG TTYDEF_LFLAG 10952130Smckusick #else 11052130Smckusick #define ISPEED B4800 11152130Smckusick #define LFLAG (TTYDEF_LFLAG & ~ECHO) 11252130Smckusick #endif 11352130Smckusick 11452130Smckusick /* 11552130Smckusick * Ascii values of command keys. 11652130Smckusick */ 11752130Smckusick #define KBD_TAB '\t' 11852130Smckusick #define KBD_DEL 127 11952130Smckusick #define KBD_RET '\r' 12052130Smckusick 12152130Smckusick /* 12252130Smckusick * Define "hardware-independent" codes for the control, shift, meta and 12352130Smckusick * function keys. Codes start after the last 7-bit ASCII code (127) 12452130Smckusick * and are assigned in an arbitrary order. 12552130Smckusick */ 12652130Smckusick #define KBD_NOKEY 128 12752130Smckusick 12852130Smckusick #define KBD_F1 201 12952130Smckusick #define KBD_F2 202 13052130Smckusick #define KBD_F3 203 13152130Smckusick #define KBD_F4 204 13252130Smckusick #define KBD_F5 205 13352130Smckusick #define KBD_F6 206 13452130Smckusick #define KBD_F7 207 13552130Smckusick #define KBD_F8 208 13652130Smckusick #define KBD_F9 209 13752130Smckusick #define KBD_F10 210 13852130Smckusick #define KBD_F11 211 13952130Smckusick #define KBD_F12 212 14052130Smckusick #define KBD_F13 213 14152130Smckusick #define KBD_F14 214 14252130Smckusick #define KBD_HELP 215 14352130Smckusick #define KBD_DO 216 14452130Smckusick #define KBD_F17 217 14552130Smckusick #define KBD_F18 218 14652130Smckusick #define KBD_F19 219 14752130Smckusick #define KBD_F20 220 14852130Smckusick 14952130Smckusick #define KBD_FIND 221 15052130Smckusick #define KBD_INSERT 222 15152130Smckusick #define KBD_REMOVE 223 15252130Smckusick #define KBD_SELECT 224 15352130Smckusick #define KBD_PREVIOUS 225 15452130Smckusick #define KBD_NEXT 226 15552130Smckusick 15652130Smckusick #define KBD_KP_ENTER 227 15752130Smckusick #define KBD_KP_F1 228 15852130Smckusick #define KBD_KP_F2 229 15952130Smckusick #define KBD_KP_F3 230 16052130Smckusick #define KBD_KP_F4 231 16152130Smckusick #define KBD_LEFT 232 16252130Smckusick #define KBD_RIGHT 233 16352130Smckusick #define KBD_DOWN 234 16452130Smckusick #define KBD_UP 235 16552130Smckusick 16652130Smckusick #define KBD_CONTROL 236 16752130Smckusick #define KBD_SHIFT 237 16852130Smckusick #define KBD_CAPSLOCK 238 16952130Smckusick #define KBD_ALTERNATE 239 17052130Smckusick 17152130Smckusick /* 17252130Smckusick * Keyboard to Ascii, unshifted. 17352130Smckusick */ 17452130Smckusick static unsigned char unshiftedAscii[] = { 17552130Smckusick /* 0 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 17652130Smckusick /* 4 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 17752130Smckusick /* 8 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 17852130Smckusick /* c */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 17952130Smckusick /* 10 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 18052130Smckusick /* 14 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 18152130Smckusick /* 18 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 18252130Smckusick /* 1c */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 18352130Smckusick /* 20 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 18452130Smckusick /* 24 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 18552130Smckusick /* 28 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 18652130Smckusick /* 2c */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 18752130Smckusick /* 30 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 18852130Smckusick /* 34 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 18952130Smckusick /* 38 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 19052130Smckusick /* 3c */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 19152130Smckusick /* 40 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 19252130Smckusick /* 44 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 19352130Smckusick /* 48 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 19452130Smckusick /* 4c */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 19552130Smckusick /* 50 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 19652130Smckusick /* 54 */ KBD_NOKEY, KBD_NOKEY, KBD_F1, KBD_F2, 19752130Smckusick /* 58 */ KBD_F3, KBD_F4, KBD_F5, KBD_NOKEY, 19852130Smckusick /* 5c */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 19952130Smckusick /* 60 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 20052130Smckusick /* 64 */ KBD_F6, KBD_F7, KBD_F8, KBD_F9, 20152130Smckusick /* 68 */ KBD_F10, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 20252130Smckusick /* 6c */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 20352130Smckusick /* 70 */ KBD_NOKEY, '\033', KBD_F12, KBD_F13, 20452130Smckusick /* 74 */ KBD_F14, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 20552130Smckusick /* 78 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 20652130Smckusick /* 7c */ KBD_HELP, KBD_DO, KBD_NOKEY, KBD_NOKEY, 20752130Smckusick /* 80 */ KBD_F17, KBD_F18, KBD_F19, KBD_F20, 20852130Smckusick /* 84 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 20952130Smckusick /* 88 */ KBD_NOKEY, KBD_NOKEY, KBD_FIND, KBD_INSERT, 21052130Smckusick /* 8c */ KBD_REMOVE, KBD_SELECT, KBD_PREVIOUS, KBD_NEXT, 21152130Smckusick /* 90 */ KBD_NOKEY, KBD_NOKEY, '0', KBD_NOKEY, 21252130Smckusick /* 94 */ '.', KBD_KP_ENTER, '1', '2', 21352130Smckusick /* 98 */ '3', '4', '5', '6', 21452130Smckusick /* 9c */ ',', '7', '8', '9', 21552130Smckusick /* a0 */ '-', KBD_KP_F1, KBD_KP_F2, KBD_KP_F3, 21652130Smckusick /* a4 */ KBD_KP_F4, KBD_NOKEY, KBD_NOKEY, KBD_LEFT, 21752130Smckusick /* a8 */ KBD_RIGHT, KBD_DOWN, KBD_UP, KBD_NOKEY, 21852130Smckusick /* ac */ KBD_NOKEY, KBD_NOKEY, KBD_SHIFT, KBD_CONTROL, 21952130Smckusick /* b0 */ KBD_CAPSLOCK, KBD_ALTERNATE, KBD_NOKEY, KBD_NOKEY, 22052130Smckusick /* b4 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 22152130Smckusick /* b8 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 22252130Smckusick /* bc */ KBD_DEL, KBD_RET, KBD_TAB, '`', 22352130Smckusick /* c0 */ '1', 'q', 'a', 'z', 22452130Smckusick /* c4 */ KBD_NOKEY, '2', 'w', 's', 22552130Smckusick /* c8 */ 'x', '<', KBD_NOKEY, '3', 22652130Smckusick /* cc */ 'e', 'd', 'c', KBD_NOKEY, 22752130Smckusick /* d0 */ '4', 'r', 'f', 'v', 22852130Smckusick /* d4 */ ' ', KBD_NOKEY, '5', 't', 22952130Smckusick /* d8 */ 'g', 'b', KBD_NOKEY, '6', 23052130Smckusick /* dc */ 'y', 'h', 'n', KBD_NOKEY, 23152130Smckusick /* e0 */ '7', 'u', 'j', 'm', 23252130Smckusick /* e4 */ KBD_NOKEY, '8', 'i', 'k', 23352130Smckusick /* e8 */ ',', KBD_NOKEY, '9', 'o', 23452130Smckusick /* ec */ 'l', '.', KBD_NOKEY, '0', 23552130Smckusick /* f0 */ 'p', KBD_NOKEY, ';', '/', 23652130Smckusick /* f4 */ KBD_NOKEY, '=', ']', '\\', 23752130Smckusick /* f8 */ KBD_NOKEY, '-', '[', '\'', 23852130Smckusick /* fc */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 23952130Smckusick }; 24052130Smckusick 24152130Smckusick /* 24252130Smckusick * Keyboard to Ascii, shifted. 24352130Smckusick */ 24452130Smckusick static unsigned char shiftedAscii[] = { 24552130Smckusick /* 0 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 24652130Smckusick /* 4 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 24752130Smckusick /* 8 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 24852130Smckusick /* c */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 24952130Smckusick /* 10 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 25052130Smckusick /* 14 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 25152130Smckusick /* 18 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 25252130Smckusick /* 1c */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 25352130Smckusick /* 20 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 25452130Smckusick /* 24 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 25552130Smckusick /* 28 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 25652130Smckusick /* 2c */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 25752130Smckusick /* 30 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 25852130Smckusick /* 34 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 25952130Smckusick /* 38 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 26052130Smckusick /* 3c */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 26152130Smckusick /* 40 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 26252130Smckusick /* 44 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 26352130Smckusick /* 48 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 26452130Smckusick /* 4c */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 26552130Smckusick /* 50 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 26652130Smckusick /* 54 */ KBD_NOKEY, KBD_NOKEY, KBD_F1, KBD_F2, 26752130Smckusick /* 58 */ KBD_F3, KBD_F4, KBD_F5, KBD_NOKEY, 26852130Smckusick /* 5c */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 26952130Smckusick /* 60 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 27052130Smckusick /* 64 */ KBD_F6, KBD_F7, KBD_F8, KBD_F9, 27152130Smckusick /* 68 */ KBD_F10, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 27252130Smckusick /* 6c */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 27352130Smckusick /* 70 */ KBD_NOKEY, KBD_F11, KBD_F12, KBD_F13, 27452130Smckusick /* 74 */ KBD_F14, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 27552130Smckusick /* 78 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 27652130Smckusick /* 7c */ KBD_HELP, KBD_DO, KBD_NOKEY, KBD_NOKEY, 27752130Smckusick /* 80 */ KBD_F17, KBD_F18, KBD_F19, KBD_F20, 27852130Smckusick /* 84 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 27952130Smckusick /* 88 */ KBD_NOKEY, KBD_NOKEY, KBD_FIND, KBD_INSERT, 28052130Smckusick /* 8c */ KBD_REMOVE, KBD_SELECT, KBD_PREVIOUS, KBD_NEXT, 28152130Smckusick /* 90 */ KBD_NOKEY, KBD_NOKEY, '0', KBD_NOKEY, 28252130Smckusick /* 94 */ '.', KBD_KP_ENTER, '1', '2', 28352130Smckusick /* 98 */ '3', '4', '5', '6', 28452130Smckusick /* 9c */ ',', '7', '8', '9', 28552130Smckusick /* a0 */ '-', KBD_KP_F1, KBD_KP_F2, KBD_KP_F3, 28652130Smckusick /* a4 */ KBD_KP_F4, KBD_NOKEY, KBD_NOKEY, KBD_LEFT, 28752130Smckusick /* a8 */ KBD_RIGHT, KBD_DOWN, KBD_UP, KBD_NOKEY, 28852130Smckusick /* ac */ KBD_NOKEY, KBD_NOKEY, KBD_SHIFT, KBD_CONTROL, 28952130Smckusick /* b0 */ KBD_CAPSLOCK, KBD_ALTERNATE, KBD_NOKEY, KBD_NOKEY, 29052130Smckusick /* b4 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 29152130Smckusick /* b8 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 29252130Smckusick /* bc */ KBD_DEL, KBD_RET, KBD_TAB, '~', 29352130Smckusick /* c0 */ '!', 'q', 'a', 'z', 29452130Smckusick /* c4 */ KBD_NOKEY, '@', 'w', 's', 29552130Smckusick /* c8 */ 'x', '>', KBD_NOKEY, '#', 29652130Smckusick /* cc */ 'e', 'd', 'c', KBD_NOKEY, 29752130Smckusick /* d0 */ '$', 'r', 'f', 'v', 29852130Smckusick /* d4 */ ' ', KBD_NOKEY, '%', 't', 29952130Smckusick /* d8 */ 'g', 'b', KBD_NOKEY, '^', 30052130Smckusick /* dc */ 'y', 'h', 'n', KBD_NOKEY, 30152130Smckusick /* e0 */ '&', 'u', 'j', 'm', 30252130Smckusick /* e4 */ KBD_NOKEY, '*', 'i', 'k', 30352130Smckusick /* e8 */ '<', KBD_NOKEY, '(', 'o', 30452130Smckusick /* ec */ 'l', '>', KBD_NOKEY, ')', 30552130Smckusick /* f0 */ 'p', KBD_NOKEY, ':', '?', 30652130Smckusick /* f4 */ KBD_NOKEY, '+', '}', '|', 30752130Smckusick /* f8 */ KBD_NOKEY, '_', '{', '"', 30852130Smckusick /* fc */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 30952130Smckusick }; 31052130Smckusick 31152130Smckusick /* 31252130Smckusick * Keyboard initialization string. 31352130Smckusick */ 31452130Smckusick static u_char kbdInitString[] = { 31552130Smckusick LK_LED_ENABLE, LED_ALL, /* show we are resetting keyboard */ 31652130Smckusick LK_DEFAULTS, 31752130Smckusick LK_CMD_MODE(LK_AUTODOWN, 1), 31852130Smckusick LK_CMD_MODE(LK_AUTODOWN, 2), 31952130Smckusick LK_CMD_MODE(LK_AUTODOWN, 3), 32052130Smckusick LK_CMD_MODE(LK_DOWN, 4), /* could also be LK_AUTODOWN */ 32152130Smckusick LK_CMD_MODE(LK_UPDOWN, 5), 32252130Smckusick LK_CMD_MODE(LK_UPDOWN, 6), 32352130Smckusick LK_CMD_MODE(LK_AUTODOWN, 7), 32452130Smckusick LK_CMD_MODE(LK_AUTODOWN, 8), 32552130Smckusick LK_CMD_MODE(LK_AUTODOWN, 9), 32652130Smckusick LK_CMD_MODE(LK_AUTODOWN, 10), 32752130Smckusick LK_CMD_MODE(LK_AUTODOWN, 11), 32852130Smckusick LK_CMD_MODE(LK_AUTODOWN, 12), 32952130Smckusick LK_CMD_MODE(LK_DOWN, 13), 33052130Smckusick LK_CMD_MODE(LK_AUTODOWN, 14), 33152130Smckusick LK_AR_ENABLE, /* we want autorepeat by default */ 33252130Smckusick LK_CL_ENABLE, 0x83, /* keyclick, volume */ 33352130Smckusick LK_KBD_ENABLE, /* the keyboard itself */ 33452130Smckusick LK_BELL_ENABLE, 0x83, /* keyboard bell, volume */ 33552130Smckusick LK_LED_DISABLE, LED_ALL, /* clear keyboard leds */ 33652130Smckusick }; 33752130Smckusick 33852130Smckusick /* 33952130Smckusick * Test to see if device is present. 34052130Smckusick * Return true if found and initialized ok. 34152130Smckusick */ 34252130Smckusick dcprobe(cp) 34352130Smckusick register struct pmax_ctlr *cp; 34452130Smckusick { 34552130Smckusick register dcregs *dcaddr; 34652130Smckusick register struct pdma *pdp; 34752130Smckusick register struct tty *tp; 34852130Smckusick register int cntr; 34952130Smckusick extern dcscan(); 35052130Smckusick extern void dcKBDReset(); 35152130Smckusick extern void MouseInit(); 35252130Smckusick 35352130Smckusick if (cp->pmax_unit >= NDC) 35452130Smckusick return (0); 35552130Smckusick if (badaddr(cp->pmax_addr, 2)) 35652130Smckusick return (0); 35752130Smckusick 35852130Smckusick /* reset chip */ 35952130Smckusick dcaddr = (dcregs *)cp->pmax_addr; 36052130Smckusick dcaddr->dc_csr = CSR_CLR; 36152130Smckusick MachEmptyWriteBuffer(); 36252130Smckusick while (dcaddr->dc_csr & CSR_CLR) 36352130Smckusick ; 36452130Smckusick dcaddr->dc_csr = CSR_MSE | CSR_TIE | CSR_RIE; 36552130Smckusick 36652130Smckusick /* init pseudo DMA structures */ 36752130Smckusick pdp = &dcpdma[cp->pmax_unit * 4]; 36852130Smckusick tp = &dc_tty[cp->pmax_unit * 4]; 36952130Smckusick for (cntr = 0; cntr < 4; cntr++) { 37052130Smckusick pdp->p_addr = dcaddr; 37152130Smckusick pdp->p_arg = (int)tp; 37252130Smckusick pdp->p_fcn = dcxint; 37352130Smckusick tp->t_addr = (caddr_t)pdp; 37452130Smckusick pdp++, tp++; 37552130Smckusick } 37652130Smckusick dcsoftCAR[cp->pmax_unit] = cp->pmax_flags | 0xB; 37752130Smckusick 37852130Smckusick if (dc_timer == 0) { 37952130Smckusick dc_timer = 1; 38052130Smckusick timeout(dcscan, (caddr_t)0, hz); 38152130Smckusick } 38252130Smckusick printf("dc%d at nexus0 csr 0x%x\n", cp->pmax_unit, cp->pmax_addr); 38352130Smckusick if (cp->pmax_unit == 0) { 38452130Smckusick int s; 38552130Smckusick 38652130Smckusick s = spltty(); 38752130Smckusick dcaddr->dc_lpr = LPR_RXENAB | LPR_B4800 | LPR_8_BIT_CHAR | 38852130Smckusick KBD_PORT; 38952130Smckusick dcaddr->dc_lpr = LPR_RXENAB | LPR_B4800 | LPR_OPAR | 39052130Smckusick LPR_PARENB | LPR_8_BIT_CHAR | MOUSE_PORT; 39152130Smckusick MachEmptyWriteBuffer(); 39252130Smckusick dcKBDReset(); 39352130Smckusick MouseInit(); 39452130Smckusick splx(s); 39552130Smckusick } 39652130Smckusick return (1); 39752130Smckusick } 39852130Smckusick 39952130Smckusick dcopen(dev, flag) 40052130Smckusick dev_t dev; 40152130Smckusick { 40252130Smckusick register struct tty *tp; 40352130Smckusick register int unit; 40452130Smckusick int s, error = 0; 40552130Smckusick extern int dcparam(); 40652130Smckusick 40752130Smckusick unit = minor(dev); 40852130Smckusick if (unit >= dc_cnt || dcpdma[unit].p_addr == 0) 40952130Smckusick return (ENXIO); 41052130Smckusick tp = &dc_tty[unit]; 41152130Smckusick tp->t_addr = (caddr_t)&dcpdma[unit]; 41252130Smckusick tp->t_oproc = dcstart; 41352130Smckusick tp->t_param = dcparam; 41452130Smckusick tp->t_dev = dev; 41552130Smckusick if ((tp->t_state & TS_ISOPEN) == 0) { 41652130Smckusick tp->t_state |= TS_WOPEN; 41752130Smckusick ttychars(tp); 41852130Smckusick #ifndef PORTSELECTOR 41952130Smckusick if (tp->t_ispeed == 0) { 42052130Smckusick #endif 42152130Smckusick tp->t_iflag = TTYDEF_IFLAG; 42252130Smckusick tp->t_oflag = TTYDEF_OFLAG; 42352130Smckusick tp->t_cflag = TTYDEF_CFLAG; 42452130Smckusick tp->t_lflag = LFLAG; 42552130Smckusick tp->t_ispeed = tp->t_ospeed = ISPEED; 42652130Smckusick #ifdef PORTSELECTOR 42752130Smckusick tp->t_cflag |= HUPCL; 42852130Smckusick #else 42952130Smckusick } 43052130Smckusick #endif 43152130Smckusick (void) dcparam(tp, &tp->t_termios); 43252130Smckusick ttsetwater(tp); 43352130Smckusick } else if ((tp->t_state & TS_XCLUDE) && curproc->p_ucred->cr_uid != 0) 43452130Smckusick return (EBUSY); 43552130Smckusick (void) dcmctl(dev, DML_DTR, DMSET); 43652130Smckusick s = spltty(); 43752130Smckusick while (!(flag & O_NONBLOCK) && !(tp->t_cflag & CLOCAL) && 43852130Smckusick !(tp->t_state & TS_CARR_ON)) { 43952130Smckusick tp->t_state |= TS_WOPEN; 44052130Smckusick if (error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH, 44152130Smckusick ttopen, 0)) 44252130Smckusick break; 44352130Smckusick } 44452130Smckusick splx(s); 44552130Smckusick if (error) 44652130Smckusick return (error); 44752130Smckusick return ((*linesw[tp->t_line].l_open)(dev, tp)); 44852130Smckusick } 44952130Smckusick 45052130Smckusick /*ARGSUSED*/ 45152130Smckusick dcclose(dev, flag) 45252130Smckusick dev_t dev; 45352130Smckusick { 45452130Smckusick register struct tty *tp; 45552130Smckusick register int unit, bit; 45652130Smckusick 45752130Smckusick unit = minor(dev); 45852130Smckusick tp = &dc_tty[unit]; 45952130Smckusick bit = 1 << ((unit & 03) + 8); 46052130Smckusick if (dc_brk[unit >> 2] & bit) { 46152130Smckusick dc_brk[unit >> 2] &= ~bit; 46252130Smckusick ttyoutput(0, tp); 46352130Smckusick } 46452130Smckusick (*linesw[tp->t_line].l_close)(tp); 46552130Smckusick if ((tp->t_cflag & HUPCL) || (tp->t_state & TS_WOPEN) || 46652130Smckusick !(tp->t_state & TS_ISOPEN)) 46752130Smckusick (void) dcmctl(dev, 0, DMSET); 46852130Smckusick return (ttyclose(tp)); 46952130Smckusick } 47052130Smckusick 47152130Smckusick dcread(dev, uio, flag) 47252130Smckusick dev_t dev; 47352130Smckusick struct uio *uio; 47452130Smckusick { 47552130Smckusick register struct tty *tp; 47652130Smckusick 47752130Smckusick tp = &dc_tty[minor(dev)]; 47852130Smckusick return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); 47952130Smckusick } 48052130Smckusick 48152130Smckusick dcwrite(dev, uio, flag) 48252130Smckusick dev_t dev; 48352130Smckusick struct uio *uio; 48452130Smckusick { 48552130Smckusick register struct tty *tp; 48652130Smckusick 48752130Smckusick tp = &dc_tty[minor(dev)]; 48852130Smckusick return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); 48952130Smckusick } 49052130Smckusick 49152130Smckusick /* 49252130Smckusick * Check for interrupts from all devices. 49352130Smckusick */ 49452130Smckusick dcintr() 49552130Smckusick { 49652130Smckusick register struct pdma *p; 49752130Smckusick register unsigned csr; 49852130Smckusick register int unit; 49952130Smckusick 50052130Smckusick for (unit = 0, p = dcpdma; p < &dcpdma[NDCLINE]; unit += 4, p += 4) { 50152130Smckusick while ((csr = p->p_addr->dc_csr) & (CSR_RDONE | CSR_TRDY)) { 50252130Smckusick if (csr & CSR_RDONE) 50352130Smckusick dcrint(unit); 50452130Smckusick if (csr & CSR_TRDY) 50552130Smckusick dcxint(&dc_tty[unit + ((csr >> 8) & 03)]); 50652130Smckusick } 50752130Smckusick } 50852130Smckusick } 50952130Smckusick 51052130Smckusick dcrint(unit) 51152130Smckusick register int unit; 51252130Smckusick { 51352130Smckusick register dcregs *dcaddr; 51452130Smckusick register struct tty *tp; 51552130Smckusick register int c, cc; 51652130Smckusick register struct tty *tp0; 51752130Smckusick int overrun = 0; 51852130Smckusick 51952130Smckusick dcaddr = dcpdma[unit].p_addr; 52052130Smckusick tp0 = &dc_tty[unit]; 52152130Smckusick while ((c = dcaddr->dc_rbuf) < 0) { /* char present */ 52252130Smckusick cc = c & 0xff; 52352130Smckusick tp = tp0 + ((c >> 8) & 03); 52452130Smckusick if ((c & RBUF_OERR) && overrun == 0) { 52552130Smckusick log(LOG_WARNING, "dc%d,%d: silo overflow\n", unit >> 2, 52652130Smckusick (c >> 8) & 03); 52752130Smckusick overrun = 1; 52852130Smckusick } 52952130Smckusick /* the keyboard requires special translation */ 53052130Smckusick if (tp == &dc_tty[KBD_PORT]) { 53152130Smckusick static u_char shiftDown; 53252130Smckusick static u_char ctrlDown; 53352130Smckusick static u_char lastChar; 53452130Smckusick 53552130Smckusick #ifdef DEBUG 53652130Smckusick if (cc == LK_DO) 53752130Smckusick panic("dcrint"); 53852130Smckusick debugChar = cc; 53952130Smckusick 54052130Smckusick #endif 54152130Smckusick if (dcDivertXInput) { 54252130Smckusick #ifdef DEBUG 54352130Smckusick if (cc == KEY_F1) { 54452130Smckusick dcDivertXInput = 0; 54552130Smckusick continue; 54652130Smckusick } 54752130Smckusick #endif 54852130Smckusick pmKbdEvent(cc); 54952130Smckusick continue; 55052130Smckusick } 55152130Smckusick 55252130Smckusick switch (cc) { 55352130Smckusick case KEY_REPEAT: 55452130Smckusick cc = lastChar; 55552130Smckusick goto done; 55652130Smckusick 55752130Smckusick case KEY_UP: 55852130Smckusick shiftDown = 0; 55952130Smckusick ctrlDown = 0; 56052130Smckusick continue; 56152130Smckusick 56252130Smckusick case KEY_SHIFT: 56352130Smckusick if (ctrlDown) 56452130Smckusick shiftDown = 0; 56552130Smckusick else 56652130Smckusick shiftDown = 1; 56752130Smckusick continue; 56852130Smckusick 56952130Smckusick case KEY_CONTROL: 57052130Smckusick if (shiftDown) 57152130Smckusick ctrlDown = 0; 57252130Smckusick else 57352130Smckusick ctrlDown = 1; 57452130Smckusick continue; 57552130Smckusick 57652130Smckusick case LK_POWER_ERROR: 57752130Smckusick case LK_KDOWN_ERROR: 57852130Smckusick case LK_INPUT_ERROR: 57952130Smckusick case LK_OUTPUT_ERROR: 58052130Smckusick log(LOG_WARNING, 58152130Smckusick "dc0,0: keyboard error, code=%x\n", cc); 58252130Smckusick continue; 58352130Smckusick } 58452130Smckusick if (shiftDown) 58552130Smckusick cc = shiftedAscii[cc]; 58652130Smckusick else 58752130Smckusick cc = unshiftedAscii[cc]; 58852130Smckusick if (cc >= KBD_NOKEY) { 58952130Smckusick /* 59052130Smckusick * A function key was typed - ignore it. 59152130Smckusick */ 59252130Smckusick continue; 59352130Smckusick } 59452130Smckusick if (cc >= 'a' && cc <= 'z') { 59552130Smckusick if (ctrlDown) 59652130Smckusick cc = cc - 'a' + '\1'; /* ^A */ 59752130Smckusick else if (shiftDown) 59852130Smckusick cc = cc - 'a' + 'A'; 59952130Smckusick } else if (ctrlDown) { 60052130Smckusick if (cc >= '[' && cc <= '_') 60152130Smckusick cc = cc - '@'; 60252130Smckusick else if (cc == ' ' || cc == '@') 60352130Smckusick cc = '\0'; 60452130Smckusick } 60552130Smckusick lastChar = cc; 60652130Smckusick done: 60752130Smckusick ; 60852130Smckusick } else if (tp == &dc_tty[MOUSE_PORT]) { 60952130Smckusick register MouseReport *newRepPtr; 61052130Smckusick static MouseReport currentRep; 61152130Smckusick 61252130Smckusick newRepPtr = ¤tRep; 61352130Smckusick newRepPtr->byteCount++; 61452130Smckusick if (cc & MOUSE_START_FRAME) { 61552130Smckusick /* 61652130Smckusick * The first mouse report byte (button state). 61752130Smckusick */ 61852130Smckusick newRepPtr->state = cc; 61952130Smckusick if (newRepPtr->byteCount > 1) 62052130Smckusick newRepPtr->byteCount = 1; 62152130Smckusick } else if (newRepPtr->byteCount == 2) { 62252130Smckusick /* 62352130Smckusick * The second mouse report byte (delta x). 62452130Smckusick */ 62552130Smckusick newRepPtr->dx = cc; 62652130Smckusick } else if (newRepPtr->byteCount == 3) { 62752130Smckusick /* 62852130Smckusick * The final mouse report byte (delta y). 62952130Smckusick */ 63052130Smckusick newRepPtr->dy = cc; 63152130Smckusick newRepPtr->byteCount = 0; 63252130Smckusick if (newRepPtr->dx != 0 || newRepPtr->dy != 0) { 63352130Smckusick /* 63452130Smckusick * If the mouse moved, 63552130Smckusick * post a motion event. 63652130Smckusick */ 63752130Smckusick pmMouseEvent(newRepPtr); 63852130Smckusick } 63952130Smckusick pmMouseButtons(newRepPtr); 64052130Smckusick } 64152130Smckusick continue; 64252130Smckusick } 64352130Smckusick if (!(tp->t_state & TS_ISOPEN)) { 64452130Smckusick wakeup((caddr_t)&tp->t_rawq); 64552130Smckusick #ifdef PORTSELECTOR 64652130Smckusick if (!(tp->t_state & TS_WOPEN)) 64752130Smckusick #endif 64852130Smckusick continue; 64952130Smckusick } 65052130Smckusick if (c & RBUF_FERR) 65152130Smckusick cc |= TTY_FE; 65252130Smckusick if (c & RBUF_PERR) 65352130Smckusick cc |= TTY_PE; 65452130Smckusick (*linesw[tp->t_line].l_rint)(cc, tp); 65552130Smckusick } 65652130Smckusick DELAY(10); 65752130Smckusick } 65852130Smckusick 65952130Smckusick /*ARGSUSED*/ 66052130Smckusick dcioctl(dev, cmd, data, flag) 66152130Smckusick dev_t dev; 66252130Smckusick caddr_t data; 66352130Smckusick { 66452130Smckusick register struct tty *tp; 66552130Smckusick register int unit = minor(dev); 66652130Smckusick register int dc = unit >> 2; 66752130Smckusick int error; 66852130Smckusick 66952130Smckusick tp = &dc_tty[unit]; 67052130Smckusick error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag); 67152130Smckusick if (error >= 0) 67252130Smckusick return (error); 67352130Smckusick error = ttioctl(tp, cmd, data, flag); 67452130Smckusick if (error >= 0) 67552130Smckusick return (error); 67652130Smckusick 67752130Smckusick switch (cmd) { 67852130Smckusick 67952130Smckusick case TIOCSBRK: 68052130Smckusick dc_brk[dc] |= 1 << ((unit & 03) + 8); 68152130Smckusick ttyoutput(0, tp); 68252130Smckusick break; 68352130Smckusick 68452130Smckusick case TIOCCBRK: 68552130Smckusick dc_brk[dc] &= ~(1 << ((unit & 03) + 8)); 68652130Smckusick ttyoutput(0, tp); 68752130Smckusick break; 68852130Smckusick 68952130Smckusick case TIOCSDTR: 69052130Smckusick (void) dcmctl(dev, DML_DTR|DML_RTS, DMBIS); 69152130Smckusick break; 69252130Smckusick 69352130Smckusick case TIOCCDTR: 69452130Smckusick (void) dcmctl(dev, DML_DTR|DML_RTS, DMBIC); 69552130Smckusick break; 69652130Smckusick 69752130Smckusick case TIOCMSET: 69852130Smckusick (void) dcmctl(dev, *(int *)data, DMSET); 69952130Smckusick break; 70052130Smckusick 70152130Smckusick case TIOCMBIS: 70252130Smckusick (void) dcmctl(dev, *(int *)data, DMBIS); 70352130Smckusick break; 70452130Smckusick 70552130Smckusick case TIOCMBIC: 70652130Smckusick (void) dcmctl(dev, *(int *)data, DMBIC); 70752130Smckusick break; 70852130Smckusick 70952130Smckusick case TIOCMGET: 71052130Smckusick *(int *)data = dcmctl(dev, 0, DMGET); 71152130Smckusick break; 71252130Smckusick 71352130Smckusick default: 71452130Smckusick return (ENOTTY); 71552130Smckusick } 71652130Smckusick return (0); 71752130Smckusick } 71852130Smckusick 71952130Smckusick dcparam(tp, t) 72052130Smckusick register struct tty *tp; 72152130Smckusick register struct termios *t; 72252130Smckusick { 72352130Smckusick register dcregs *dcaddr; 72452130Smckusick register int lpr; 72552130Smckusick register int cflag = t->c_cflag; 72652130Smckusick int unit = minor(tp->t_dev); 72752130Smckusick int ospeed = ttspeedtab(t->c_ospeed, dcspeedtab); 72852130Smckusick 72952130Smckusick /* check requested parameters */ 73052130Smckusick if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed) || 73152130Smckusick (cflag & CSIZE) == CS5 || (cflag & CSIZE) == CS6) 73252130Smckusick return (EINVAL); 73352130Smckusick /* and copy to tty */ 73452130Smckusick tp->t_ispeed = t->c_ispeed; 73552130Smckusick tp->t_ospeed = t->c_ospeed; 73652130Smckusick tp->t_cflag = cflag; 73752130Smckusick 73852130Smckusick dcaddr = dcpdma[unit].p_addr; 73952130Smckusick if (tp == dc_tty + KBD_PORT) { 74052130Smckusick /* handle the keyboard specially */ 74152130Smckusick dcaddr->dc_lpr = LPR_RXENAB | LPR_B4800 | LPR_8_BIT_CHAR | 74252130Smckusick KBD_PORT; 74352130Smckusick MachEmptyWriteBuffer(); 74452130Smckusick return (0); 74552130Smckusick } 74652130Smckusick if (tp == dc_tty + MOUSE_PORT) { 74752130Smckusick /* handle the mouse specially */ 74852130Smckusick dcaddr->dc_lpr = LPR_RXENAB | LPR_B4800 | LPR_OPAR | 74952130Smckusick LPR_PARENB | LPR_8_BIT_CHAR | MOUSE_PORT; 75052130Smckusick MachEmptyWriteBuffer(); 75152130Smckusick return (0); 75252130Smckusick } 75352130Smckusick if (ospeed == 0) { 75452130Smckusick (void) dcmctl(unit, 0, DMSET); /* hang up line */ 75552130Smckusick return (0); 75652130Smckusick } 75752130Smckusick lpr = LPR_RXENAB | ospeed | (unit & 03); 75852130Smckusick if ((cflag & CSIZE) == CS7) 75952130Smckusick lpr |= LPR_7_BIT_CHAR; 76052130Smckusick else 76152130Smckusick lpr |= LPR_8_BIT_CHAR; 76252130Smckusick if (cflag & PARENB) 76352130Smckusick lpr |= LPR_PARENB; 76452130Smckusick if (cflag & PARODD) 76552130Smckusick lpr |= LPR_OPAR; 76652130Smckusick if (cflag & CSTOPB) 76752130Smckusick lpr |= LPR_2_STOP; 76852130Smckusick dcaddr->dc_lpr = lpr; 76952130Smckusick MachEmptyWriteBuffer(); 77052130Smckusick return (0); 77152130Smckusick } 77252130Smckusick 77352130Smckusick dcxint(tp) 77452130Smckusick register struct tty *tp; 77552130Smckusick { 77652130Smckusick register struct pdma *dp; 77752130Smckusick register dcregs *dcaddr; 77852130Smckusick 77952130Smckusick dp = (struct pdma *)tp->t_addr; 78052130Smckusick if (dp->p_mem < dp->p_end) { 78152130Smckusick dcaddr = dp->p_addr; 78252130Smckusick dcaddr->dc_tdr = dc_brk[(tp - dc_tty) >> 2] | *dp->p_mem++; 78352130Smckusick MachEmptyWriteBuffer(); 78452130Smckusick DELAY(10); 78552130Smckusick return; 78652130Smckusick } 78752130Smckusick tp->t_state &= ~TS_BUSY; 78852130Smckusick if (tp->t_state & TS_FLUSH) 78952130Smckusick tp->t_state &= ~TS_FLUSH; 79052130Smckusick else { 79152130Smckusick ndflush(&tp->t_outq, dp->p_mem-tp->t_outq.c_cf); 79252130Smckusick dp->p_end = dp->p_mem = tp->t_outq.c_cf; 79352130Smckusick } 79452130Smckusick if (tp->t_line) 79552130Smckusick (*linesw[tp->t_line].l_start)(tp); 79652130Smckusick else 79752130Smckusick dcstart(tp); 79852130Smckusick if (tp->t_outq.c_cc == 0 || !(tp->t_state & TS_BUSY)) { 79952130Smckusick dp->p_addr->dc_tcr &= ~(1 << (minor(tp->t_dev) & 03)); 80052130Smckusick MachEmptyWriteBuffer(); 80152130Smckusick DELAY(10); 80252130Smckusick } 80352130Smckusick } 80452130Smckusick 80552130Smckusick dcstart(tp) 80652130Smckusick register struct tty *tp; 80752130Smckusick { 80852130Smckusick register struct pdma *dp; 80952130Smckusick register dcregs *dcaddr; 81052130Smckusick register int cc; 81152130Smckusick int s; 81252130Smckusick 81352130Smckusick dp = (struct pdma *)tp->t_addr; 81452130Smckusick dcaddr = dp->p_addr; 81552130Smckusick s = spltty(); 81652130Smckusick if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) 81752130Smckusick goto out; 81852130Smckusick if (tp->t_outq.c_cc <= tp->t_lowat) { 81952130Smckusick if (tp->t_state & TS_ASLEEP) { 82052130Smckusick tp->t_state &= ~TS_ASLEEP; 82152130Smckusick wakeup((caddr_t)&tp->t_outq); 82252130Smckusick } 823*52674Smckusick selwakeup(&tp->t_wsel); 82452130Smckusick } 82552130Smckusick if (tp->t_outq.c_cc == 0) 82652130Smckusick goto out; 82752130Smckusick /* handle console specially */ 82852130Smckusick if (tp == dc_tty) { 82952130Smckusick while (tp->t_outq.c_cc > 0) { 83052130Smckusick cc = getc(&tp->t_outq) & 0x7f; 83152130Smckusick pmPutc(cc); 83252130Smckusick } 83352130Smckusick /* 83452130Smckusick * After we flush the output queue we may need to wake 83552130Smckusick * up the process that made the output. 83652130Smckusick */ 83752130Smckusick if (tp->t_outq.c_cc <= tp->t_lowat) { 83852130Smckusick if (tp->t_state & TS_ASLEEP) { 83952130Smckusick tp->t_state &= ~TS_ASLEEP; 84052130Smckusick wakeup((caddr_t)&tp->t_outq); 84152130Smckusick } 842*52674Smckusick selwakeup(&tp->t_wsel); 84352130Smckusick } 84452130Smckusick goto out; 84552130Smckusick } 84652130Smckusick if (tp->t_flags & (RAW|LITOUT)) 84752130Smckusick cc = ndqb(&tp->t_outq, 0); 84852130Smckusick else { 84952130Smckusick cc = ndqb(&tp->t_outq, 0200); 85052130Smckusick if (cc == 0) { 85152130Smckusick cc = getc(&tp->t_outq); 85252130Smckusick timeout(ttrstrt, (caddr_t)tp, (cc & 0x7f) + 6); 85352130Smckusick tp->t_state |= TS_TIMEOUT; 85452130Smckusick goto out; 85552130Smckusick } 85652130Smckusick } 85752130Smckusick tp->t_state |= TS_BUSY; 85852130Smckusick dp->p_end = dp->p_mem = tp->t_outq.c_cf; 85952130Smckusick dp->p_end += cc; 86052130Smckusick dcaddr->dc_tcr |= 1 << (minor(tp->t_dev) & 03); 86152130Smckusick MachEmptyWriteBuffer(); 86252130Smckusick out: 86352130Smckusick splx(s); 86452130Smckusick } 86552130Smckusick 86652130Smckusick /* 86752130Smckusick * Stop output on a line. 86852130Smckusick */ 86952130Smckusick /*ARGSUSED*/ 87052130Smckusick dcstop(tp, flag) 87152130Smckusick register struct tty *tp; 87252130Smckusick { 87352130Smckusick register struct pdma *dp; 87452130Smckusick register int s; 87552130Smckusick 87652130Smckusick dp = (struct pdma *)tp->t_addr; 87752130Smckusick s = spltty(); 87852130Smckusick if (tp->t_state & TS_BUSY) { 87952130Smckusick dp->p_end = dp->p_mem; 88052130Smckusick if (!(tp->t_state & TS_TTSTOP)) 88152130Smckusick tp->t_state |= TS_FLUSH; 88252130Smckusick } 88352130Smckusick splx(s); 88452130Smckusick } 88552130Smckusick 88652130Smckusick dcmctl(dev, bits, how) 88752130Smckusick dev_t dev; 88852130Smckusick int bits, how; 88952130Smckusick { 89052130Smckusick register dcregs *dcaddr; 89152130Smckusick register int unit, mbits; 89252130Smckusick int b, s; 89352130Smckusick 89452130Smckusick unit = minor(dev); 89552130Smckusick b = 1 << (unit & 03); 89652130Smckusick dcaddr = dcpdma[unit].p_addr; 89752130Smckusick s = spltty(); 89852130Smckusick /* only channel 2 has modem control (what about line 3?) */ 89952130Smckusick if ((unit & 03) == 2) { 90052130Smckusick mbits = 0; 90152130Smckusick if (dcaddr->dc_tcr & TCR_DTR2) 90252130Smckusick mbits |= DML_DTR; 90352130Smckusick if (dcaddr->dc_msr & MSR_DSR2) 90452130Smckusick mbits |= DML_DSR | DML_CAR; 90552130Smckusick } else 90652130Smckusick mbits = DML_DTR | DML_DSR | DML_CAR; 90752130Smckusick switch (how) { 90852130Smckusick case DMSET: 90952130Smckusick mbits = bits; 91052130Smckusick break; 91152130Smckusick 91252130Smckusick case DMBIS: 91352130Smckusick mbits |= bits; 91452130Smckusick break; 91552130Smckusick 91652130Smckusick case DMBIC: 91752130Smckusick mbits &= ~bits; 91852130Smckusick break; 91952130Smckusick 92052130Smckusick case DMGET: 92152130Smckusick (void) splx(s); 92252130Smckusick return (mbits); 92352130Smckusick } 92452130Smckusick if ((unit & 03) == 2) { 92552130Smckusick if (mbits & DML_DTR) 92652130Smckusick dcaddr->dc_tcr |= TCR_DTR2; 92752130Smckusick else 92852130Smckusick dcaddr->dc_tcr &= ~TCR_DTR2; 92952130Smckusick } 93052130Smckusick if ((mbits & DML_DTR) && (dcsoftCAR[unit >> 2] & b)) 93152130Smckusick dc_tty[unit].t_state |= TS_CARR_ON; 93252130Smckusick (void) splx(s); 93352130Smckusick return (mbits); 93452130Smckusick } 93552130Smckusick 93652130Smckusick /* 93752130Smckusick * This is called by timeout() periodically. 93852130Smckusick * Check to see if modem status bits have changed. 93952130Smckusick */ 94052130Smckusick dcscan() 94152130Smckusick { 94252130Smckusick register dcregs *dcaddr; 94352130Smckusick register struct tty *tp; 94452130Smckusick register int i, bit, car; 94552130Smckusick int s; 94652130Smckusick 94752130Smckusick s = spltty(); 94852130Smckusick /* only channel 2 has modem control (what about line 3?) */ 94952130Smckusick dcaddr = dcpdma[i = 2].p_addr; 95052130Smckusick tp = &dc_tty[i]; 95152130Smckusick bit = TCR_DTR2; 95252130Smckusick if (dcsoftCAR[i >> 2] & bit) 95352130Smckusick car = 1; 95452130Smckusick else 95552130Smckusick car = dcaddr->dc_msr & MSR_DSR2; 95652130Smckusick if (car) { 95752130Smckusick /* carrier present */ 95852130Smckusick if (!(tp->t_state & TS_CARR_ON)) 95952130Smckusick (void)(*linesw[tp->t_line].l_modem)(tp, 1); 96052130Smckusick } else if ((tp->t_state & TS_CARR_ON) && 96152130Smckusick (*linesw[tp->t_line].l_modem)(tp, 0) == 0) 96252130Smckusick dcaddr->dc_tcr &= ~bit; 96352130Smckusick splx(s); 96452130Smckusick timeout(dcscan, (caddr_t)0, hz); 96552130Smckusick } 96652130Smckusick 96752130Smckusick /* 96852130Smckusick * ---------------------------------------------------------------------------- 96952130Smckusick * 97052130Smckusick * dcKBDPutc -- 97152130Smckusick * 97252130Smckusick * Put a character out to the keyboard. 97352130Smckusick * 97452130Smckusick * Results: 97552130Smckusick * None. 97652130Smckusick * 97752130Smckusick * Side effects: 97852130Smckusick * A character is written to the keyboard. 97952130Smckusick * 98052130Smckusick * ---------------------------------------------------------------------------- 98152130Smckusick */ 98252130Smckusick void 98352130Smckusick dcKBDPutc(c) 98452130Smckusick register int c; 98552130Smckusick { 98652130Smckusick register dcregs *dcaddr; 98752130Smckusick register u_short tcr; 98852130Smckusick register int timeout; 98952130Smckusick int s, line; 99052130Smckusick 99152130Smckusick s = spltty(); 99252130Smckusick 99352130Smckusick dcaddr = dcpdma[KBD_PORT].p_addr; 99452130Smckusick tcr = dcaddr->dc_tcr; 99552130Smckusick dcaddr->dc_tcr = tcr | (1 << KBD_PORT); 99652130Smckusick MachEmptyWriteBuffer(); 99752130Smckusick DELAY(10); 99852130Smckusick while (1) { 99952130Smckusick /* 100052130Smckusick * Wait for transmitter to be not busy. 100152130Smckusick */ 100252130Smckusick timeout = 1000000; 100352130Smckusick while (!(dcaddr->dc_csr & CSR_TRDY) && timeout > 0) 100452130Smckusick timeout--; 100552130Smckusick if (timeout == 0) { 100652130Smckusick printf("dcKBDPutc: timeout waiting for CSR_TRDY\n"); 100752130Smckusick break; 100852130Smckusick } 100952130Smckusick line = (dcaddr->dc_csr >> 8) & 3; 101052130Smckusick /* 101152130Smckusick * Check to be sure its the right port. 101252130Smckusick */ 101352130Smckusick if (line != KBD_PORT) { 101452130Smckusick tcr |= 1 << line; 101552130Smckusick dcaddr->dc_tcr &= ~(1 << line); 101652130Smckusick MachEmptyWriteBuffer(); 101752130Smckusick DELAY(10); 101852130Smckusick continue; 101952130Smckusick } 102052130Smckusick /* 102152130Smckusick * Start sending the character. 102252130Smckusick */ 102352130Smckusick dcaddr->dc_tdr = dc_brk[0] | (c & 0xff); 102452130Smckusick MachEmptyWriteBuffer(); 102552130Smckusick DELAY(10); 102652130Smckusick /* 102752130Smckusick * Wait for character to be sent. 102852130Smckusick */ 102952130Smckusick while (1) { 103052130Smckusick /* 103152130Smckusick * cc -O bug: this code produces and infinite loop! 103252130Smckusick * while (!(dcaddr->dc_csr & CSR_TRDY)) 103352130Smckusick * ; 103452130Smckusick */ 103552130Smckusick timeout = 1000000; 103652130Smckusick while (!(dcaddr->dc_csr & CSR_TRDY) && timeout > 0) 103752130Smckusick timeout--; 103852130Smckusick line = (dcaddr->dc_csr >> 8) & 3; 103952130Smckusick if (line != KBD_PORT) { 104052130Smckusick tcr |= 1 << line; 104152130Smckusick dcaddr->dc_tcr &= ~(1 << line); 104252130Smckusick MachEmptyWriteBuffer(); 104352130Smckusick DELAY(10); 104452130Smckusick continue; 104552130Smckusick } 104652130Smckusick dcaddr->dc_tcr &= ~(1 << KBD_PORT); 104752130Smckusick MachEmptyWriteBuffer(); 104852130Smckusick DELAY(10); 104952130Smckusick break; 105052130Smckusick } 105152130Smckusick break; 105252130Smckusick } 105352130Smckusick /* 105452130Smckusick * Enable interrupts for other lines which became ready. 105552130Smckusick */ 105652130Smckusick if (tcr & 0xF) { 105752130Smckusick dcaddr->dc_tcr = tcr; 105852130Smckusick MachEmptyWriteBuffer(); 105952130Smckusick DELAY(10); 106052130Smckusick } 106152130Smckusick 106252130Smckusick splx(s); 106352130Smckusick } 106452130Smckusick 106552130Smckusick #ifdef DEBUG 106652130Smckusick /* 106752130Smckusick * ---------------------------------------------------------------------------- 106852130Smckusick * 106952130Smckusick * dcKBDGetc -- 107052130Smckusick * 107152130Smckusick * Read a character from the keyboard. 107252130Smckusick * 107352130Smckusick * Results: 107452130Smckusick * A character read from the mouse, -1 if none were ready. 107552130Smckusick * 107652130Smckusick * Side effects: 107752130Smckusick * None. 107852130Smckusick * 107952130Smckusick * ---------------------------------------------------------------------------- 108052130Smckusick */ 108152130Smckusick int 108252130Smckusick dcKBDGetc() 108352130Smckusick { 108452130Smckusick register dcregs *dcaddr; 108552130Smckusick register int c; 108652130Smckusick 108752130Smckusick dcaddr = dcpdma[KBD_PORT].p_addr; 108852130Smckusick if (!dcaddr) 108952130Smckusick return (0); 109052130Smckusick if (c = debugChar) 109152130Smckusick debugChar = 0; 109252130Smckusick else { 109352130Smckusick while (dcaddr->dc_csr & CSR_RDONE) { 109452130Smckusick c = dcaddr->dc_rbuf; 109552130Smckusick DELAY(10); 109652130Smckusick if (((c >> 8) & 03) == KBD_PORT) 109752130Smckusick break; 109852130Smckusick c = 0; 109952130Smckusick } 110052130Smckusick } 110152130Smckusick return (c & 0xff); 110252130Smckusick } 110352130Smckusick #endif 110452130Smckusick 110552130Smckusick /* 110652130Smckusick * ---------------------------------------------------------------------------- 110752130Smckusick * 110852130Smckusick * dcKBDReset -- 110952130Smckusick * 111052130Smckusick * Reset the keyboard to default characteristics. 111152130Smckusick * 111252130Smckusick * Results: 111352130Smckusick * None. 111452130Smckusick * 111552130Smckusick * Side effects: 111652130Smckusick * None. 111752130Smckusick * 111852130Smckusick * ---------------------------------------------------------------------------- 111952130Smckusick */ 112052130Smckusick void 112152130Smckusick dcKBDReset() 112252130Smckusick { 112352130Smckusick register int i; 112452130Smckusick static int inKBDReset; 112552130Smckusick 112652130Smckusick if (inKBDReset) 112752130Smckusick return; 112852130Smckusick inKBDReset = 1; 112952130Smckusick for (i = 0; i < sizeof(kbdInitString); i++) 113052130Smckusick dcKBDPutc((int)kbdInitString[i]); 113152130Smckusick inKBDReset = 0; 113252130Smckusick } 113352130Smckusick 113452130Smckusick /* 113552130Smckusick * ---------------------------------------------------------------------------- 113652130Smckusick * 113752130Smckusick * MousePutc -- 113852130Smckusick * 113952130Smckusick * Write a character to the mouse. 114052130Smckusick * This is only called at initialization time. 114152130Smckusick * 114252130Smckusick * Results: 114352130Smckusick * None. 114452130Smckusick * 114552130Smckusick * Side effects: 114652130Smckusick * A character is written to the mouse. 114752130Smckusick * 114852130Smckusick * ---------------------------------------------------------------------------- 114952130Smckusick */ 115052130Smckusick static void 115152130Smckusick MousePutc(c) 115252130Smckusick int c; 115352130Smckusick { 115452130Smckusick register dcregs *dcaddr; 115552130Smckusick register u_short tcr; 115652130Smckusick register int timeout; 115752130Smckusick int line; 115852130Smckusick 115952130Smckusick dcaddr = dcpdma[MOUSE_PORT].p_addr; 116052130Smckusick tcr = dcaddr->dc_tcr; 116152130Smckusick dcaddr->dc_tcr = tcr | (1 << MOUSE_PORT); 116252130Smckusick MachEmptyWriteBuffer(); 116352130Smckusick DELAY(10); 116452130Smckusick while (1) { 116552130Smckusick /* 116652130Smckusick * Wait for transmitter to be not busy. 116752130Smckusick */ 116852130Smckusick timeout = 1000000; 116952130Smckusick while (!(dcaddr->dc_csr & CSR_TRDY) && timeout > 0) 117052130Smckusick timeout--; 117152130Smckusick if (timeout == 0) { 117252130Smckusick printf("MousePutc: timeout waiting for CSR_TRDY\n"); 117352130Smckusick break; 117452130Smckusick } 117552130Smckusick line = (dcaddr->dc_csr >> 8) & 3; 117652130Smckusick /* 117752130Smckusick * Check to be sure its the right port. 117852130Smckusick */ 117952130Smckusick if (line != MOUSE_PORT) { 118052130Smckusick tcr |= 1 << line; 118152130Smckusick dcaddr->dc_tcr &= ~(1 << line); 118252130Smckusick MachEmptyWriteBuffer(); 118352130Smckusick DELAY(10); 118452130Smckusick continue; 118552130Smckusick } 118652130Smckusick /* 118752130Smckusick * Start sending the character. 118852130Smckusick */ 118952130Smckusick dcaddr->dc_tdr = dc_brk[0] | (c & 0xff); 119052130Smckusick MachEmptyWriteBuffer(); 119152130Smckusick DELAY(10); 119252130Smckusick /* 119352130Smckusick * Wait for character to be sent. 119452130Smckusick */ 119552130Smckusick while (1) { 119652130Smckusick /* 119752130Smckusick * cc -O bug: this code produces and infinite loop! 119852130Smckusick * while (!(dcaddr->dc_csr & CSR_TRDY)) 119952130Smckusick * ; 120052130Smckusick */ 120152130Smckusick timeout = 1000000; 120252130Smckusick while (!(dcaddr->dc_csr & CSR_TRDY) && timeout > 0) 120352130Smckusick timeout--; 120452130Smckusick line = (dcaddr->dc_csr >> 8) & 3; 120552130Smckusick if (line != MOUSE_PORT) { 120652130Smckusick tcr |= 1 << line; 120752130Smckusick dcaddr->dc_tcr &= ~(1 << line); 120852130Smckusick MachEmptyWriteBuffer(); 120952130Smckusick DELAY(10); 121052130Smckusick continue; 121152130Smckusick } 121252130Smckusick dcaddr->dc_tcr &= ~(1 << MOUSE_PORT); 121352130Smckusick MachEmptyWriteBuffer(); 121452130Smckusick DELAY(10); 121552130Smckusick break; 121652130Smckusick } 121752130Smckusick break; 121852130Smckusick } 121952130Smckusick /* 122052130Smckusick * Enable interrupts for other lines which became ready. 122152130Smckusick */ 122252130Smckusick if (tcr & 0xF) { 122352130Smckusick dcaddr->dc_tcr = tcr; 122452130Smckusick MachEmptyWriteBuffer(); 122552130Smckusick DELAY(10); 122652130Smckusick } 122752130Smckusick } 122852130Smckusick 122952130Smckusick /* 123052130Smckusick * ---------------------------------------------------------------------------- 123152130Smckusick * 123252130Smckusick * MouseGetc -- 123352130Smckusick * 123452130Smckusick * Read a character from the mouse. 123552130Smckusick * This is only called at initialization time. 123652130Smckusick * 123752130Smckusick * Results: 123852130Smckusick * A character read from the mouse, -1 if we timed out waiting. 123952130Smckusick * 124052130Smckusick * Side effects: 124152130Smckusick * None. 124252130Smckusick * 124352130Smckusick * ---------------------------------------------------------------------------- 124452130Smckusick */ 124552130Smckusick static int 124652130Smckusick MouseGetc() 124752130Smckusick { 124852130Smckusick register dcregs *dcaddr; 124952130Smckusick register int timeout; 125052130Smckusick register int c; 125152130Smckusick 125252130Smckusick dcaddr = dcpdma[MOUSE_PORT].p_addr; 125352130Smckusick for (timeout = 1000000; timeout > 0; timeout--) { 125452130Smckusick if (!(dcaddr->dc_csr & CSR_RDONE)) 125552130Smckusick continue; 125652130Smckusick c = dcaddr->dc_rbuf; 125752130Smckusick DELAY(10); 125852130Smckusick if (((c >> 8) & 03) != MOUSE_PORT) 125952130Smckusick continue; 126052130Smckusick return (c & 0xff); 126152130Smckusick } 126252130Smckusick 126352130Smckusick return (-1); 126452130Smckusick } 126552130Smckusick 126652130Smckusick /* 126752130Smckusick * ---------------------------------------------------------------------------- 126852130Smckusick * 126952130Smckusick * MouseInit -- 127052130Smckusick * 127152130Smckusick * Initialize the mouse. 127252130Smckusick * 127352130Smckusick * Results: 127452130Smckusick * None. 127552130Smckusick * 127652130Smckusick * Side effects: 127752130Smckusick * None. 127852130Smckusick * 127952130Smckusick * ---------------------------------------------------------------------------- 128052130Smckusick */ 128152130Smckusick static void 128252130Smckusick MouseInit() 128352130Smckusick { 128452130Smckusick int id_byte1, id_byte2, id_byte3, id_byte4; 128552130Smckusick 128652130Smckusick /* 128752130Smckusick * Initialize the mouse. 128852130Smckusick */ 128952130Smckusick MousePutc(MOUSE_SELF_TEST); 129052130Smckusick id_byte1 = MouseGetc(); 129152130Smckusick if (id_byte1 < 0) { 129252130Smckusick printf("MouseInit: Timeout on 1st byte of self-test report\n"); 129352130Smckusick return; 129452130Smckusick } 129552130Smckusick id_byte2 = MouseGetc(); 129652130Smckusick if (id_byte2 < 0) { 129752130Smckusick printf("MouseInit: Timeout on 2nd byte of self-test report\n"); 129852130Smckusick return; 129952130Smckusick } 130052130Smckusick id_byte3 = MouseGetc(); 130152130Smckusick if (id_byte3 < 0) { 130252130Smckusick printf("MouseInit: Timeout on 3rd byte of self-test report\n"); 130352130Smckusick return; 130452130Smckusick } 130552130Smckusick id_byte4 = MouseGetc(); 130652130Smckusick if (id_byte4 < 0) { 130752130Smckusick printf("MouseInit: Timeout on 4th byte of self-test report\n"); 130852130Smckusick return; 130952130Smckusick } 131052130Smckusick if ((id_byte2 & 0x0f) != 0x2) 131152130Smckusick printf("MouseInit: We don't have a mouse!!!\n"); 131252130Smckusick /* 131352130Smckusick * For some reason, the mouse doesn't see this command if it comes 131452130Smckusick * too soon after a self test. 131552130Smckusick */ 131652130Smckusick DELAY(100); 131752130Smckusick MousePutc(MOUSE_INCREMENTAL); 131852130Smckusick } 131952130Smckusick #endif /* NDC */ 1320