1 /* 2 * Copyright (c) 1992 Regents of the University of California. 3 * All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Ralph Campbell. 7 * @(#)dz.c 7.9 (Berkeley) 6/28/90 8 */ 9 10 /* 11 * devDC7085.c -- 12 * 13 * %sccs.include.redist.c% 14 * 15 * @(#)dc.c 7.7 (Berkeley) 07/27/92 16 * 17 * devDC7085.c -- 18 * 19 * This file contains machine-dependent routines that handle the 20 * output queue for the serial lines. 21 * 22 * Copyright (C) 1989 Digital Equipment Corporation. 23 * Permission to use, copy, modify, and distribute this software and 24 * its documentation for any purpose and without fee is hereby granted, 25 * provided that the above copyright notice appears in all copies. 26 * Digital Equipment Corporation makes no representations about the 27 * suitability of this software for any purpose. It is provided "as is" 28 * without express or implied warranty. 29 * 30 * from: $Header: /sprite/src/kernel/dev/ds3100.md/RCS/devDC7085.c, 31 * v 1.4 89/08/29 11:55:30 nelson Exp $ SPRITE (DECWRL)"; 32 */ 33 34 #include "dc.h" 35 #if NDC > 0 36 /* 37 * DC7085 (DZ-11 look alike) Driver 38 */ 39 #include "param.h" 40 #include "systm.h" 41 #include "ioctl.h" 42 #include "tty.h" 43 #include "proc.h" 44 #include "map.h" 45 #include "buf.h" 46 #include "conf.h" 47 #include "file.h" 48 #include "uio.h" 49 #include "kernel.h" 50 #include "syslog.h" 51 52 #include "machine/dc7085cons.h" 53 54 #include "device.h" 55 #include "pdma.h" 56 57 /* 58 * Driver information for auto-configuration stuff. 59 */ 60 int dcprobe(); 61 void dcintr(); 62 struct driver dcdriver = { 63 "dc", dcprobe, 0, 0, dcintr, 64 }; 65 66 #define NDCLINE (NDC*4) 67 68 extern void dcstart __P((struct tty *)); 69 extern void dcxint __P((struct tty *)); 70 extern void ttrstrt __P((struct tty *)); 71 72 struct tty dc_tty[NDCLINE]; 73 int dc_cnt = NDCLINE; 74 void (*dcDivertXInput)(); /* X windows keyboard input routine */ 75 void (*dcMouseEvent)(); /* X windows mouse motion event routine */ 76 void (*dcMouseButtons)(); /* X windows mouse buttons event routine */ 77 #ifdef DEBUG 78 int debugChar; 79 #endif 80 81 static void dcscan __P((void *)); 82 static int dcMapChar __P((int)); 83 static void dcKBDReset __P((void)); 84 static void MouseInit __P((void)); 85 86 /* 87 * Software copy of brk register since it isn't readable 88 */ 89 int dc_brk[NDC]; 90 char dcsoftCAR[NDC]; /* mask of dc's with carrier on (DSR) */ 91 92 /* 93 * The DC7085 doesn't interrupt on carrier transitions, so 94 * we have to use a timer to watch it. 95 */ 96 int dc_timer; /* true if timer started */ 97 98 /* 99 * Pdma structures for fast output code 100 */ 101 struct pdma dcpdma[NDCLINE]; 102 103 struct speedtab dcspeedtab[] = { 104 0, 0, 105 50, LPR_B50, 106 75, LPR_B75, 107 110, LPR_B110, 108 134, LPR_B134, 109 150, LPR_B150, 110 300, LPR_B300, 111 600, LPR_B600, 112 1200, LPR_B1200, 113 1800, LPR_B1800, 114 2400, LPR_B2400, 115 4800, LPR_B4800, 116 9600, LPR_B9600, 117 #ifdef DS5000 118 19200, LPR_B19200, 119 #endif 120 -1, -1 121 }; 122 123 #ifndef PORTSELECTOR 124 #define ISPEED TTYDEF_SPEED 125 #define LFLAG TTYDEF_LFLAG 126 #else 127 #define ISPEED B4800 128 #define LFLAG (TTYDEF_LFLAG & ~ECHO) 129 #endif 130 131 /* 132 * Ascii values of command keys. 133 */ 134 #define KBD_TAB '\t' 135 #define KBD_DEL 127 136 #define KBD_RET '\r' 137 138 /* 139 * Define "hardware-independent" codes for the control, shift, meta and 140 * function keys. Codes start after the last 7-bit ASCII code (127) 141 * and are assigned in an arbitrary order. 142 */ 143 #define KBD_NOKEY 128 144 145 #define KBD_F1 201 146 #define KBD_F2 202 147 #define KBD_F3 203 148 #define KBD_F4 204 149 #define KBD_F5 205 150 #define KBD_F6 206 151 #define KBD_F7 207 152 #define KBD_F8 208 153 #define KBD_F9 209 154 #define KBD_F10 210 155 #define KBD_F11 211 156 #define KBD_F12 212 157 #define KBD_F13 213 158 #define KBD_F14 214 159 #define KBD_HELP 215 160 #define KBD_DO 216 161 #define KBD_F17 217 162 #define KBD_F18 218 163 #define KBD_F19 219 164 #define KBD_F20 220 165 166 #define KBD_FIND 221 167 #define KBD_INSERT 222 168 #define KBD_REMOVE 223 169 #define KBD_SELECT 224 170 #define KBD_PREVIOUS 225 171 #define KBD_NEXT 226 172 173 #define KBD_KP_ENTER 227 174 #define KBD_KP_F1 228 175 #define KBD_KP_F2 229 176 #define KBD_KP_F3 230 177 #define KBD_KP_F4 231 178 #define KBD_LEFT 232 179 #define KBD_RIGHT 233 180 #define KBD_DOWN 234 181 #define KBD_UP 235 182 183 #define KBD_CONTROL 236 184 #define KBD_SHIFT 237 185 #define KBD_CAPSLOCK 238 186 #define KBD_ALTERNATE 239 187 188 /* 189 * Keyboard to Ascii, unshifted. 190 */ 191 static unsigned char unshiftedAscii[] = { 192 /* 0 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 193 /* 4 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 194 /* 8 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 195 /* c */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 196 /* 10 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 197 /* 14 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 198 /* 18 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 199 /* 1c */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 200 /* 20 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 201 /* 24 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 202 /* 28 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 203 /* 2c */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 204 /* 30 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 205 /* 34 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 206 /* 38 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 207 /* 3c */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 208 /* 40 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 209 /* 44 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 210 /* 48 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 211 /* 4c */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 212 /* 50 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 213 /* 54 */ KBD_NOKEY, KBD_NOKEY, KBD_F1, KBD_F2, 214 /* 58 */ KBD_F3, KBD_F4, KBD_F5, KBD_NOKEY, 215 /* 5c */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 216 /* 60 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 217 /* 64 */ KBD_F6, KBD_F7, KBD_F8, KBD_F9, 218 /* 68 */ KBD_F10, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 219 /* 6c */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 220 /* 70 */ KBD_NOKEY, '\033', KBD_F12, KBD_F13, 221 /* 74 */ KBD_F14, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 222 /* 78 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 223 /* 7c */ KBD_HELP, KBD_DO, KBD_NOKEY, KBD_NOKEY, 224 /* 80 */ KBD_F17, KBD_F18, KBD_F19, KBD_F20, 225 /* 84 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 226 /* 88 */ KBD_NOKEY, KBD_NOKEY, KBD_FIND, KBD_INSERT, 227 /* 8c */ KBD_REMOVE, KBD_SELECT, KBD_PREVIOUS, KBD_NEXT, 228 /* 90 */ KBD_NOKEY, KBD_NOKEY, '0', KBD_NOKEY, 229 /* 94 */ '.', KBD_KP_ENTER, '1', '2', 230 /* 98 */ '3', '4', '5', '6', 231 /* 9c */ ',', '7', '8', '9', 232 /* a0 */ '-', KBD_KP_F1, KBD_KP_F2, KBD_KP_F3, 233 /* a4 */ KBD_KP_F4, KBD_NOKEY, KBD_NOKEY, KBD_LEFT, 234 /* a8 */ KBD_RIGHT, KBD_DOWN, KBD_UP, KBD_NOKEY, 235 /* ac */ KBD_NOKEY, KBD_NOKEY, KBD_SHIFT, KBD_CONTROL, 236 /* b0 */ KBD_CAPSLOCK, KBD_ALTERNATE, KBD_NOKEY, KBD_NOKEY, 237 /* b4 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 238 /* b8 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 239 /* bc */ KBD_DEL, KBD_RET, KBD_TAB, '`', 240 /* c0 */ '1', 'q', 'a', 'z', 241 /* c4 */ KBD_NOKEY, '2', 'w', 's', 242 /* c8 */ 'x', '<', KBD_NOKEY, '3', 243 /* cc */ 'e', 'd', 'c', KBD_NOKEY, 244 /* d0 */ '4', 'r', 'f', 'v', 245 /* d4 */ ' ', KBD_NOKEY, '5', 't', 246 /* d8 */ 'g', 'b', KBD_NOKEY, '6', 247 /* dc */ 'y', 'h', 'n', KBD_NOKEY, 248 /* e0 */ '7', 'u', 'j', 'm', 249 /* e4 */ KBD_NOKEY, '8', 'i', 'k', 250 /* e8 */ ',', KBD_NOKEY, '9', 'o', 251 /* ec */ 'l', '.', KBD_NOKEY, '0', 252 /* f0 */ 'p', KBD_NOKEY, ';', '/', 253 /* f4 */ KBD_NOKEY, '=', ']', '\\', 254 /* f8 */ KBD_NOKEY, '-', '[', '\'', 255 /* fc */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 256 }; 257 258 /* 259 * Keyboard to Ascii, shifted. 260 */ 261 static unsigned char shiftedAscii[] = { 262 /* 0 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 263 /* 4 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 264 /* 8 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 265 /* c */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 266 /* 10 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 267 /* 14 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 268 /* 18 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 269 /* 1c */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 270 /* 20 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 271 /* 24 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 272 /* 28 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 273 /* 2c */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 274 /* 30 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 275 /* 34 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 276 /* 38 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 277 /* 3c */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 278 /* 40 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 279 /* 44 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 280 /* 48 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 281 /* 4c */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 282 /* 50 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 283 /* 54 */ KBD_NOKEY, KBD_NOKEY, KBD_F1, KBD_F2, 284 /* 58 */ KBD_F3, KBD_F4, KBD_F5, KBD_NOKEY, 285 /* 5c */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 286 /* 60 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 287 /* 64 */ KBD_F6, KBD_F7, KBD_F8, KBD_F9, 288 /* 68 */ KBD_F10, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 289 /* 6c */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 290 /* 70 */ KBD_NOKEY, KBD_F11, KBD_F12, KBD_F13, 291 /* 74 */ KBD_F14, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 292 /* 78 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 293 /* 7c */ KBD_HELP, KBD_DO, KBD_NOKEY, KBD_NOKEY, 294 /* 80 */ KBD_F17, KBD_F18, KBD_F19, KBD_F20, 295 /* 84 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 296 /* 88 */ KBD_NOKEY, KBD_NOKEY, KBD_FIND, KBD_INSERT, 297 /* 8c */ KBD_REMOVE, KBD_SELECT, KBD_PREVIOUS, KBD_NEXT, 298 /* 90 */ KBD_NOKEY, KBD_NOKEY, '0', KBD_NOKEY, 299 /* 94 */ '.', KBD_KP_ENTER, '1', '2', 300 /* 98 */ '3', '4', '5', '6', 301 /* 9c */ ',', '7', '8', '9', 302 /* a0 */ '-', KBD_KP_F1, KBD_KP_F2, KBD_KP_F3, 303 /* a4 */ KBD_KP_F4, KBD_NOKEY, KBD_NOKEY, KBD_LEFT, 304 /* a8 */ KBD_RIGHT, KBD_DOWN, KBD_UP, KBD_NOKEY, 305 /* ac */ KBD_NOKEY, KBD_NOKEY, KBD_SHIFT, KBD_CONTROL, 306 /* b0 */ KBD_CAPSLOCK, KBD_ALTERNATE, KBD_NOKEY, KBD_NOKEY, 307 /* b4 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 308 /* b8 */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 309 /* bc */ KBD_DEL, KBD_RET, KBD_TAB, '~', 310 /* c0 */ '!', 'q', 'a', 'z', 311 /* c4 */ KBD_NOKEY, '@', 'w', 's', 312 /* c8 */ 'x', '>', KBD_NOKEY, '#', 313 /* cc */ 'e', 'd', 'c', KBD_NOKEY, 314 /* d0 */ '$', 'r', 'f', 'v', 315 /* d4 */ ' ', KBD_NOKEY, '%', 't', 316 /* d8 */ 'g', 'b', KBD_NOKEY, '^', 317 /* dc */ 'y', 'h', 'n', KBD_NOKEY, 318 /* e0 */ '&', 'u', 'j', 'm', 319 /* e4 */ KBD_NOKEY, '*', 'i', 'k', 320 /* e8 */ '<', KBD_NOKEY, '(', 'o', 321 /* ec */ 'l', '>', KBD_NOKEY, ')', 322 /* f0 */ 'p', KBD_NOKEY, ':', '?', 323 /* f4 */ KBD_NOKEY, '+', '}', '|', 324 /* f8 */ KBD_NOKEY, '_', '{', '"', 325 /* fc */ KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, KBD_NOKEY, 326 }; 327 328 /* 329 * Keyboard initialization string. 330 */ 331 static u_char kbdInitString[] = { 332 LK_LED_ENABLE, LED_ALL, /* show we are resetting keyboard */ 333 LK_DEFAULTS, 334 LK_CMD_MODE(LK_AUTODOWN, 1), 335 LK_CMD_MODE(LK_AUTODOWN, 2), 336 LK_CMD_MODE(LK_AUTODOWN, 3), 337 LK_CMD_MODE(LK_DOWN, 4), /* could also be LK_AUTODOWN */ 338 LK_CMD_MODE(LK_UPDOWN, 5), 339 LK_CMD_MODE(LK_UPDOWN, 6), 340 LK_CMD_MODE(LK_AUTODOWN, 7), 341 LK_CMD_MODE(LK_AUTODOWN, 8), 342 LK_CMD_MODE(LK_AUTODOWN, 9), 343 LK_CMD_MODE(LK_AUTODOWN, 10), 344 LK_CMD_MODE(LK_AUTODOWN, 11), 345 LK_CMD_MODE(LK_AUTODOWN, 12), 346 LK_CMD_MODE(LK_DOWN, 13), 347 LK_CMD_MODE(LK_AUTODOWN, 14), 348 LK_AR_ENABLE, /* we want autorepeat by default */ 349 LK_CL_ENABLE, 0x83, /* keyclick, volume */ 350 LK_KBD_ENABLE, /* the keyboard itself */ 351 LK_BELL_ENABLE, 0x83, /* keyboard bell, volume */ 352 LK_LED_DISABLE, LED_ALL, /* clear keyboard leds */ 353 }; 354 355 /* 356 * Test to see if device is present. 357 * Return true if found and initialized ok. 358 */ 359 dcprobe(cp) 360 register struct pmax_ctlr *cp; 361 { 362 register dcregs *dcaddr; 363 register struct pdma *pdp; 364 register struct tty *tp; 365 register int cntr; 366 367 if (cp->pmax_unit >= NDC) 368 return (0); 369 if (badaddr(cp->pmax_addr, 2)) 370 return (0); 371 372 /* reset chip */ 373 dcaddr = (dcregs *)cp->pmax_addr; 374 dcaddr->dc_csr = CSR_CLR; 375 MachEmptyWriteBuffer(); 376 while (dcaddr->dc_csr & CSR_CLR) 377 ; 378 dcaddr->dc_csr = CSR_MSE | CSR_TIE | CSR_RIE; 379 380 /* init pseudo DMA structures */ 381 pdp = &dcpdma[cp->pmax_unit * 4]; 382 tp = &dc_tty[cp->pmax_unit * 4]; 383 for (cntr = 0; cntr < 4; cntr++) { 384 pdp->p_addr = dcaddr; 385 pdp->p_arg = (int)tp; 386 pdp->p_fcn = dcxint; 387 tp->t_addr = (caddr_t)pdp; 388 pdp++, tp++; 389 } 390 dcsoftCAR[cp->pmax_unit] = cp->pmax_flags | 0xB; 391 392 if (dc_timer == 0) { 393 dc_timer = 1; 394 timeout(dcscan, (void *)0, hz); 395 } 396 printf("dc%d at nexus0 csr 0x%x priority %d\n", 397 cp->pmax_unit, cp->pmax_addr, cp->pmax_pri); 398 if (cp->pmax_unit == 0) { 399 int s; 400 401 s = spltty(); 402 dcaddr->dc_lpr = LPR_RXENAB | LPR_B4800 | LPR_8_BIT_CHAR | 403 KBD_PORT; 404 dcaddr->dc_lpr = LPR_RXENAB | LPR_B4800 | LPR_OPAR | 405 LPR_PARENB | LPR_8_BIT_CHAR | MOUSE_PORT; 406 MachEmptyWriteBuffer(); 407 dcKBDReset(); 408 MouseInit(); 409 splx(s); 410 } 411 return (1); 412 } 413 414 dcopen(dev, flag, mode, p) 415 dev_t dev; 416 int flag, mode; 417 struct proc *p; 418 { 419 register struct tty *tp; 420 register int unit; 421 int s, error = 0; 422 extern int dcparam(); 423 424 unit = minor(dev); 425 if (unit >= dc_cnt || dcpdma[unit].p_addr == 0) 426 return (ENXIO); 427 tp = &dc_tty[unit]; 428 tp->t_addr = (caddr_t)&dcpdma[unit]; 429 tp->t_oproc = dcstart; 430 tp->t_param = dcparam; 431 tp->t_dev = dev; 432 if ((tp->t_state & TS_ISOPEN) == 0) { 433 tp->t_state |= TS_WOPEN; 434 ttychars(tp); 435 #ifndef PORTSELECTOR 436 if (tp->t_ispeed == 0) { 437 #endif 438 tp->t_iflag = TTYDEF_IFLAG; 439 tp->t_oflag = TTYDEF_OFLAG; 440 tp->t_cflag = TTYDEF_CFLAG; 441 tp->t_lflag = LFLAG; 442 tp->t_ispeed = tp->t_ospeed = ISPEED; 443 #ifdef PORTSELECTOR 444 tp->t_cflag |= HUPCL; 445 #else 446 } 447 #endif 448 (void) dcparam(tp, &tp->t_termios); 449 ttsetwater(tp); 450 } else if ((tp->t_state & TS_XCLUDE) && curproc->p_ucred->cr_uid != 0) 451 return (EBUSY); 452 (void) dcmctl(dev, DML_DTR, DMSET); 453 s = spltty(); 454 while (!(flag & O_NONBLOCK) && !(tp->t_cflag & CLOCAL) && 455 !(tp->t_state & TS_CARR_ON)) { 456 tp->t_state |= TS_WOPEN; 457 if (error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH, 458 ttopen, 0)) 459 break; 460 } 461 splx(s); 462 if (error) 463 return (error); 464 return ((*linesw[tp->t_line].l_open)(dev, tp)); 465 } 466 467 /*ARGSUSED*/ 468 dcclose(dev, flag, mode, p) 469 dev_t dev; 470 int flag, mode; 471 struct proc *p; 472 { 473 register struct tty *tp; 474 register int unit, bit; 475 476 unit = minor(dev); 477 tp = &dc_tty[unit]; 478 bit = 1 << ((unit & 03) + 8); 479 if (dc_brk[unit >> 2] & bit) { 480 dc_brk[unit >> 2] &= ~bit; 481 ttyoutput(0, tp); 482 } 483 (*linesw[tp->t_line].l_close)(tp, flag); 484 if ((tp->t_cflag & HUPCL) || (tp->t_state & TS_WOPEN) || 485 !(tp->t_state & TS_ISOPEN)) 486 (void) dcmctl(dev, 0, DMSET); 487 return (ttyclose(tp)); 488 } 489 490 dcread(dev, uio, flag) 491 dev_t dev; 492 struct uio *uio; 493 { 494 register struct tty *tp; 495 496 tp = &dc_tty[minor(dev)]; 497 return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); 498 } 499 500 dcwrite(dev, uio, flag) 501 dev_t dev; 502 struct uio *uio; 503 { 504 register struct tty *tp; 505 506 tp = &dc_tty[minor(dev)]; 507 return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); 508 } 509 510 /*ARGSUSED*/ 511 dcioctl(dev, cmd, data, flag, p) 512 dev_t dev; 513 caddr_t data; 514 int flag; 515 struct proc *p; 516 { 517 register struct tty *tp; 518 register int unit = minor(dev); 519 register int dc = unit >> 2; 520 int error; 521 522 tp = &dc_tty[unit]; 523 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); 524 if (error >= 0) 525 return (error); 526 error = ttioctl(tp, cmd, data, flag); 527 if (error >= 0) 528 return (error); 529 530 switch (cmd) { 531 532 case TIOCSBRK: 533 dc_brk[dc] |= 1 << ((unit & 03) + 8); 534 ttyoutput(0, tp); 535 break; 536 537 case TIOCCBRK: 538 dc_brk[dc] &= ~(1 << ((unit & 03) + 8)); 539 ttyoutput(0, tp); 540 break; 541 542 case TIOCSDTR: 543 (void) dcmctl(dev, DML_DTR|DML_RTS, DMBIS); 544 break; 545 546 case TIOCCDTR: 547 (void) dcmctl(dev, DML_DTR|DML_RTS, DMBIC); 548 break; 549 550 case TIOCMSET: 551 (void) dcmctl(dev, *(int *)data, DMSET); 552 break; 553 554 case TIOCMBIS: 555 (void) dcmctl(dev, *(int *)data, DMBIS); 556 break; 557 558 case TIOCMBIC: 559 (void) dcmctl(dev, *(int *)data, DMBIC); 560 break; 561 562 case TIOCMGET: 563 *(int *)data = dcmctl(dev, 0, DMGET); 564 break; 565 566 default: 567 return (ENOTTY); 568 } 569 return (0); 570 } 571 572 dcparam(tp, t) 573 register struct tty *tp; 574 register struct termios *t; 575 { 576 register dcregs *dcaddr; 577 register int lpr; 578 register int cflag = t->c_cflag; 579 int unit = minor(tp->t_dev); 580 int ospeed = ttspeedtab(t->c_ospeed, dcspeedtab); 581 582 /* check requested parameters */ 583 if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed) || 584 (cflag & CSIZE) == CS5 || (cflag & CSIZE) == CS6) 585 return (EINVAL); 586 /* and copy to tty */ 587 tp->t_ispeed = t->c_ispeed; 588 tp->t_ospeed = t->c_ospeed; 589 tp->t_cflag = cflag; 590 591 dcaddr = dcpdma[unit].p_addr; 592 if (tp == dc_tty + KBD_PORT) { 593 /* handle the keyboard specially */ 594 dcaddr->dc_lpr = LPR_RXENAB | LPR_B4800 | LPR_8_BIT_CHAR | 595 KBD_PORT; 596 MachEmptyWriteBuffer(); 597 return (0); 598 } 599 if (tp == dc_tty + MOUSE_PORT) { 600 /* handle the mouse specially */ 601 dcaddr->dc_lpr = LPR_RXENAB | LPR_B4800 | LPR_OPAR | 602 LPR_PARENB | LPR_8_BIT_CHAR | MOUSE_PORT; 603 MachEmptyWriteBuffer(); 604 return (0); 605 } 606 if (ospeed == 0) { 607 (void) dcmctl(unit, 0, DMSET); /* hang up line */ 608 return (0); 609 } 610 lpr = LPR_RXENAB | ospeed | (unit & 03); 611 if ((cflag & CSIZE) == CS7) 612 lpr |= LPR_7_BIT_CHAR; 613 else 614 lpr |= LPR_8_BIT_CHAR; 615 if (cflag & PARENB) 616 lpr |= LPR_PARENB; 617 if (cflag & PARODD) 618 lpr |= LPR_OPAR; 619 if (cflag & CSTOPB) 620 lpr |= LPR_2_STOP; 621 dcaddr->dc_lpr = lpr; 622 MachEmptyWriteBuffer(); 623 return (0); 624 } 625 626 /* 627 * Check for interrupts from all devices. 628 */ 629 void 630 dcintr(unit) 631 register int unit; 632 { 633 register dcregs *dcaddr; 634 register unsigned csr; 635 636 unit <<= 2; 637 dcaddr = dcpdma[unit].p_addr; 638 while ((csr = dcaddr->dc_csr) & (CSR_RDONE | CSR_TRDY)) { 639 if (csr & CSR_RDONE) 640 dcrint(unit); 641 if (csr & CSR_TRDY) 642 dcxint(&dc_tty[unit + ((csr >> 8) & 03)]); 643 } 644 } 645 646 dcrint(unit) 647 register int unit; 648 { 649 register dcregs *dcaddr; 650 register struct tty *tp; 651 register int c, cc; 652 register struct tty *tp0; 653 int overrun = 0; 654 655 dcaddr = dcpdma[unit].p_addr; 656 tp0 = &dc_tty[unit]; 657 while ((c = dcaddr->dc_rbuf) < 0) { /* char present */ 658 cc = c & 0xff; 659 tp = tp0 + ((c >> 8) & 03); 660 if ((c & RBUF_OERR) && overrun == 0) { 661 log(LOG_WARNING, "dc%d,%d: silo overflow\n", unit >> 2, 662 (c >> 8) & 03); 663 overrun = 1; 664 } 665 /* the keyboard requires special translation */ 666 if (tp == &dc_tty[KBD_PORT]) { 667 #ifdef KADB 668 if (cc == LK_DO) { 669 spl0(); 670 kdbpanic(); 671 return; 672 } 673 #endif 674 #ifdef DEBUG 675 debugChar = cc; 676 #endif 677 if (dcDivertXInput) { 678 (*dcDivertXInput)(cc); 679 return; 680 } 681 if ((cc = dcMapChar(cc)) < 0) 682 return; 683 } else if (tp == &dc_tty[MOUSE_PORT] && dcMouseButtons) { 684 register MouseReport *mrp; 685 static MouseReport currentRep; 686 687 mrp = ¤tRep; 688 mrp->byteCount++; 689 if (cc & MOUSE_START_FRAME) { 690 /* 691 * The first mouse report byte (button state). 692 */ 693 mrp->state = cc; 694 if (mrp->byteCount > 1) 695 mrp->byteCount = 1; 696 } else if (mrp->byteCount == 2) { 697 /* 698 * The second mouse report byte (delta x). 699 */ 700 mrp->dx = cc; 701 } else if (mrp->byteCount == 3) { 702 /* 703 * The final mouse report byte (delta y). 704 */ 705 mrp->dy = cc; 706 mrp->byteCount = 0; 707 if (mrp->dx != 0 || mrp->dy != 0) { 708 /* 709 * If the mouse moved, 710 * post a motion event. 711 */ 712 (*dcMouseEvent)(mrp); 713 } 714 (*dcMouseButtons)(mrp); 715 } 716 return; 717 } 718 if (!(tp->t_state & TS_ISOPEN)) { 719 wakeup((caddr_t)&tp->t_rawq); 720 #ifdef PORTSELECTOR 721 if (!(tp->t_state & TS_WOPEN)) 722 #endif 723 return; 724 } 725 if (c & RBUF_FERR) 726 cc |= TTY_FE; 727 if (c & RBUF_PERR) 728 cc |= TTY_PE; 729 (*linesw[tp->t_line].l_rint)(cc, tp); 730 } 731 DELAY(10); 732 } 733 734 void 735 dcxint(tp) 736 register struct tty *tp; 737 { 738 register struct pdma *dp; 739 register dcregs *dcaddr; 740 741 dp = (struct pdma *)tp->t_addr; 742 if (dp->p_mem < dp->p_end) { 743 dcaddr = dp->p_addr; 744 dcaddr->dc_tdr = dc_brk[(tp - dc_tty) >> 2] | *dp->p_mem++; 745 MachEmptyWriteBuffer(); 746 DELAY(10); 747 return; 748 } 749 tp->t_state &= ~TS_BUSY; 750 if (tp->t_state & TS_FLUSH) 751 tp->t_state &= ~TS_FLUSH; 752 else { 753 ndflush(&tp->t_outq, dp->p_mem-tp->t_outq.c_cf); 754 dp->p_end = dp->p_mem = tp->t_outq.c_cf; 755 } 756 if (tp->t_line) 757 (*linesw[tp->t_line].l_start)(tp); 758 else 759 dcstart(tp); 760 if (tp->t_outq.c_cc == 0 || !(tp->t_state & TS_BUSY)) { 761 dp->p_addr->dc_tcr &= ~(1 << (minor(tp->t_dev) & 03)); 762 MachEmptyWriteBuffer(); 763 DELAY(10); 764 } 765 } 766 767 void 768 dcstart(tp) 769 register struct tty *tp; 770 { 771 register struct pdma *dp; 772 register dcregs *dcaddr; 773 register int cc; 774 int s; 775 776 dp = (struct pdma *)tp->t_addr; 777 dcaddr = dp->p_addr; 778 s = spltty(); 779 if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) 780 goto out; 781 if (tp->t_outq.c_cc <= tp->t_lowat) { 782 if (tp->t_state & TS_ASLEEP) { 783 tp->t_state &= ~TS_ASLEEP; 784 wakeup((caddr_t)&tp->t_outq); 785 } 786 selwakeup(&tp->t_wsel); 787 } 788 if (tp->t_outq.c_cc == 0) 789 goto out; 790 /* handle console specially */ 791 if (tp == dc_tty) { 792 while (tp->t_outq.c_cc > 0) { 793 cc = getc(&tp->t_outq) & 0x7f; 794 cnputc(cc); 795 } 796 /* 797 * After we flush the output queue we may need to wake 798 * up the process that made the output. 799 */ 800 if (tp->t_outq.c_cc <= tp->t_lowat) { 801 if (tp->t_state & TS_ASLEEP) { 802 tp->t_state &= ~TS_ASLEEP; 803 wakeup((caddr_t)&tp->t_outq); 804 } 805 selwakeup(&tp->t_wsel); 806 } 807 goto out; 808 } 809 if (tp->t_flags & (RAW|LITOUT)) 810 cc = ndqb(&tp->t_outq, 0); 811 else { 812 cc = ndqb(&tp->t_outq, 0200); 813 if (cc == 0) { 814 cc = getc(&tp->t_outq); 815 timeout(ttrstrt, (void *)tp, (cc & 0x7f) + 6); 816 tp->t_state |= TS_TIMEOUT; 817 goto out; 818 } 819 } 820 tp->t_state |= TS_BUSY; 821 dp->p_end = dp->p_mem = tp->t_outq.c_cf; 822 dp->p_end += cc; 823 dcaddr->dc_tcr |= 1 << (minor(tp->t_dev) & 03); 824 MachEmptyWriteBuffer(); 825 out: 826 splx(s); 827 } 828 829 /* 830 * Stop output on a line. 831 */ 832 /*ARGSUSED*/ 833 dcstop(tp, flag) 834 register struct tty *tp; 835 { 836 register struct pdma *dp; 837 register int s; 838 839 dp = (struct pdma *)tp->t_addr; 840 s = spltty(); 841 if (tp->t_state & TS_BUSY) { 842 dp->p_end = dp->p_mem; 843 if (!(tp->t_state & TS_TTSTOP)) 844 tp->t_state |= TS_FLUSH; 845 } 846 splx(s); 847 } 848 849 dcmctl(dev, bits, how) 850 dev_t dev; 851 int bits, how; 852 { 853 register dcregs *dcaddr; 854 register int unit, mbits; 855 int b, s; 856 #ifdef DS5000 857 register int msr; 858 #endif 859 860 unit = minor(dev); 861 b = 1 << (unit & 03); 862 dcaddr = dcpdma[unit].p_addr; 863 s = spltty(); 864 /* only channel 2 has modem control (what about line 3?) */ 865 switch (unit & 03) { 866 case 2: 867 mbits = 0; 868 if (dcaddr->dc_tcr & TCR_DTR2) 869 mbits |= DML_DTR; 870 #ifdef DS3100 871 if (dcaddr->dc_msr & MSR_DSR2) 872 mbits |= DML_DSR | DML_CAR; 873 #endif 874 #ifdef DS5000 875 msr = dcaddr->dc_msr; 876 if (msr & MSR_CD2) 877 mbits |= DML_CAR; 878 if (msr & MSR_DSR2) 879 mbits |= DML_DSR; 880 #endif 881 break; 882 883 #ifdef DS5000 884 case 3: 885 mbits = 0; 886 if (dcaddr->dc_tcr & TCR_DTR3) 887 mbits |= DML_DTR; 888 msr = dcaddr->dc_msr; 889 if (msr & MSR_CD3) 890 mbits |= DML_CAR; 891 if (msr & MSR_DSR3) 892 mbits |= DML_DSR; 893 break; 894 #endif 895 896 default: 897 mbits = DML_DTR | DML_DSR | DML_CAR; 898 } 899 switch (how) { 900 case DMSET: 901 mbits = bits; 902 break; 903 904 case DMBIS: 905 mbits |= bits; 906 break; 907 908 case DMBIC: 909 mbits &= ~bits; 910 break; 911 912 case DMGET: 913 (void) splx(s); 914 return (mbits); 915 } 916 switch (unit & 03) { 917 case 2: 918 if (mbits & DML_DTR) 919 dcaddr->dc_tcr |= TCR_DTR2; 920 else 921 dcaddr->dc_tcr &= ~TCR_DTR2; 922 break; 923 924 #ifdef DS5000 925 case 3: 926 if (mbits & DML_DTR) 927 dcaddr->dc_tcr |= TCR_DTR3; 928 else 929 dcaddr->dc_tcr &= ~TCR_DTR3; 930 #endif 931 } 932 if ((mbits & DML_DTR) && (dcsoftCAR[unit >> 2] & b)) 933 dc_tty[unit].t_state |= TS_CARR_ON; 934 (void) splx(s); 935 return (mbits); 936 } 937 938 /* 939 * This is called by timeout() periodically. 940 * Check to see if modem status bits have changed. 941 */ 942 /* ARGSUSED */ 943 static void 944 dcscan(arg) 945 void *arg; 946 { 947 register dcregs *dcaddr; 948 register struct tty *tp; 949 register int i, bit, car; 950 int s; 951 952 s = spltty(); 953 /* only channel 2 has modem control (what about line 3?) */ 954 dcaddr = dcpdma[i = 2].p_addr; 955 tp = &dc_tty[i]; 956 bit = TCR_DTR2; 957 if (dcsoftCAR[i >> 2] & bit) 958 car = 1; 959 else 960 car = dcaddr->dc_msr & MSR_DSR2; 961 if (car) { 962 /* carrier present */ 963 if (!(tp->t_state & TS_CARR_ON)) 964 (void)(*linesw[tp->t_line].l_modem)(tp, 1); 965 } else if ((tp->t_state & TS_CARR_ON) && 966 (*linesw[tp->t_line].l_modem)(tp, 0) == 0) 967 dcaddr->dc_tcr &= ~bit; 968 splx(s); 969 timeout(dcscan, (void *)0, hz); 970 } 971 972 /* 973 * ---------------------------------------------------------------------------- 974 * 975 * dcKBDPutc -- 976 * 977 * Put a character out to the keyboard. 978 * 979 * Results: 980 * None. 981 * 982 * Side effects: 983 * A character is written to the keyboard. 984 * 985 * ---------------------------------------------------------------------------- 986 */ 987 void 988 dcKBDPutc(c) 989 register int c; 990 { 991 register dcregs *dcaddr; 992 register u_short tcr; 993 register int timeout; 994 int s, line; 995 996 s = spltty(); 997 998 dcaddr = dcpdma[KBD_PORT].p_addr; 999 tcr = dcaddr->dc_tcr; 1000 dcaddr->dc_tcr = tcr | (1 << KBD_PORT); 1001 MachEmptyWriteBuffer(); 1002 DELAY(10); 1003 while (1) { 1004 /* 1005 * Wait for transmitter to be not busy. 1006 */ 1007 timeout = 1000000; 1008 while (!(dcaddr->dc_csr & CSR_TRDY) && timeout > 0) 1009 timeout--; 1010 if (timeout == 0) { 1011 printf("dcKBDPutc: timeout waiting for CSR_TRDY\n"); 1012 break; 1013 } 1014 line = (dcaddr->dc_csr >> 8) & 3; 1015 /* 1016 * Check to be sure its the right port. 1017 */ 1018 if (line != KBD_PORT) { 1019 tcr |= 1 << line; 1020 dcaddr->dc_tcr &= ~(1 << line); 1021 MachEmptyWriteBuffer(); 1022 DELAY(10); 1023 continue; 1024 } 1025 /* 1026 * Start sending the character. 1027 */ 1028 dcaddr->dc_tdr = dc_brk[0] | (c & 0xff); 1029 MachEmptyWriteBuffer(); 1030 DELAY(10); 1031 /* 1032 * Wait for character to be sent. 1033 */ 1034 while (1) { 1035 /* 1036 * cc -O bug: this code produces and infinite loop! 1037 * while (!(dcaddr->dc_csr & CSR_TRDY)) 1038 * ; 1039 */ 1040 timeout = 1000000; 1041 while (!(dcaddr->dc_csr & CSR_TRDY) && timeout > 0) 1042 timeout--; 1043 line = (dcaddr->dc_csr >> 8) & 3; 1044 if (line != KBD_PORT) { 1045 tcr |= 1 << line; 1046 dcaddr->dc_tcr &= ~(1 << line); 1047 MachEmptyWriteBuffer(); 1048 DELAY(10); 1049 continue; 1050 } 1051 dcaddr->dc_tcr &= ~(1 << KBD_PORT); 1052 MachEmptyWriteBuffer(); 1053 DELAY(10); 1054 break; 1055 } 1056 break; 1057 } 1058 /* 1059 * Enable interrupts for other lines which became ready. 1060 */ 1061 if (tcr & 0xF) { 1062 dcaddr->dc_tcr = tcr; 1063 MachEmptyWriteBuffer(); 1064 DELAY(10); 1065 } 1066 1067 splx(s); 1068 } 1069 1070 #ifdef DEBUG 1071 /* 1072 * ---------------------------------------------------------------------------- 1073 * 1074 * dcDebugGetc -- 1075 * 1076 * Read a character from the keyboard if one is ready (i.e., don't wait). 1077 * 1078 * Results: 1079 * A character read from the mouse, -1 if none were ready. 1080 * 1081 * Side effects: 1082 * None. 1083 * 1084 * ---------------------------------------------------------------------------- 1085 */ 1086 int 1087 dcDebugGetc() 1088 { 1089 register dcregs *dcaddr; 1090 register int c; 1091 int s; 1092 1093 dcaddr = dcpdma[KBD_PORT].p_addr; 1094 if (!dcaddr) 1095 return (0); 1096 1097 s = spltty(); 1098 if (c = debugChar) 1099 debugChar = 0; 1100 else { 1101 while (dcaddr->dc_csr & CSR_RDONE) { 1102 c = dcaddr->dc_rbuf; 1103 DELAY(10); 1104 if (((c >> 8) & 03) == KBD_PORT) 1105 break; 1106 c = 0; 1107 } 1108 } 1109 splx(s); 1110 1111 return (c & 0xff); 1112 } 1113 #endif 1114 1115 /* 1116 * ---------------------------------------------------------------------------- 1117 * 1118 * dcKBDGetc -- 1119 * 1120 * Read a character from the keyboard. 1121 * 1122 * Results: 1123 * A character read from the keyboard. 1124 * 1125 * Side effects: 1126 * None. 1127 * 1128 * ---------------------------------------------------------------------------- 1129 */ 1130 int 1131 dcKBDGetc() 1132 { 1133 register dcregs *dcaddr; 1134 register int c; 1135 int s; 1136 1137 dcaddr = dcpdma[KBD_PORT].p_addr; 1138 if (!dcaddr) 1139 return (-1); 1140 s = spltty(); 1141 for (;;) { 1142 if (!(dcaddr->dc_csr & CSR_RDONE)) 1143 continue; 1144 c = dcaddr->dc_rbuf; 1145 DELAY(10); 1146 if (((c >> 8) & 03) != KBD_PORT) 1147 continue; 1148 if ((c = dcMapChar(c & 0xff)) >= 0) 1149 break; 1150 } 1151 splx(s); 1152 return (c); 1153 } 1154 1155 /* 1156 * ---------------------------------------------------------------------------- 1157 * 1158 * dcMapChar -- 1159 * 1160 * Map characters from the keyboard to ASCII. Return -1 if there is 1161 * no valid mapping. 1162 * 1163 * Results: 1164 * None. 1165 * 1166 * Side effects: 1167 * Remember state of shift and control keys. 1168 * 1169 * ---------------------------------------------------------------------------- 1170 */ 1171 static int 1172 dcMapChar(cc) 1173 int cc; 1174 { 1175 static u_char shiftDown; 1176 static u_char ctrlDown; 1177 static u_char lastChar; 1178 1179 switch (cc) { 1180 case KEY_REPEAT: 1181 cc = lastChar; 1182 goto done; 1183 1184 case KEY_UP: 1185 shiftDown = 0; 1186 ctrlDown = 0; 1187 return (-1); 1188 1189 case KEY_SHIFT: 1190 if (ctrlDown) 1191 shiftDown = 0; 1192 else 1193 shiftDown = 1; 1194 return (-1); 1195 1196 case KEY_CONTROL: 1197 if (shiftDown) 1198 ctrlDown = 0; 1199 else 1200 ctrlDown = 1; 1201 return (-1); 1202 1203 case LK_POWER_ERROR: 1204 case LK_KDOWN_ERROR: 1205 case LK_INPUT_ERROR: 1206 case LK_OUTPUT_ERROR: 1207 log(LOG_WARNING, 1208 "dc0,0: keyboard error, code=%x\n", cc); 1209 return (-1); 1210 } 1211 if (shiftDown) 1212 cc = shiftedAscii[cc]; 1213 else 1214 cc = unshiftedAscii[cc]; 1215 if (cc >= KBD_NOKEY) { 1216 /* 1217 * A function key was typed - ignore it. 1218 */ 1219 return (-1); 1220 } 1221 if (cc >= 'a' && cc <= 'z') { 1222 if (ctrlDown) 1223 cc = cc - 'a' + '\1'; /* ^A */ 1224 else if (shiftDown) 1225 cc = cc - 'a' + 'A'; 1226 } else if (ctrlDown) { 1227 if (cc >= '[' && cc <= '_') 1228 cc = cc - '@'; 1229 else if (cc == ' ' || cc == '@') 1230 cc = '\0'; 1231 } 1232 lastChar = cc; 1233 done: 1234 return (cc); 1235 } 1236 1237 /* 1238 * ---------------------------------------------------------------------------- 1239 * 1240 * dcKBDReset -- 1241 * 1242 * Reset the keyboard to default characteristics. 1243 * 1244 * Results: 1245 * None. 1246 * 1247 * Side effects: 1248 * None. 1249 * 1250 * ---------------------------------------------------------------------------- 1251 */ 1252 void 1253 dcKBDReset() 1254 { 1255 register int i; 1256 static int inKBDReset; 1257 1258 if (inKBDReset) 1259 return; 1260 inKBDReset = 1; 1261 for (i = 0; i < sizeof(kbdInitString); i++) 1262 dcKBDPutc((int)kbdInitString[i]); 1263 inKBDReset = 0; 1264 } 1265 1266 /* 1267 * ---------------------------------------------------------------------------- 1268 * 1269 * MousePutc -- 1270 * 1271 * Write a character to the mouse. 1272 * This is only called at initialization time. 1273 * 1274 * Results: 1275 * None. 1276 * 1277 * Side effects: 1278 * A character is written to the mouse. 1279 * 1280 * ---------------------------------------------------------------------------- 1281 */ 1282 static void 1283 MousePutc(c) 1284 int c; 1285 { 1286 register dcregs *dcaddr; 1287 register u_short tcr; 1288 register int timeout; 1289 int line; 1290 1291 dcaddr = dcpdma[MOUSE_PORT].p_addr; 1292 tcr = dcaddr->dc_tcr; 1293 dcaddr->dc_tcr = tcr | (1 << MOUSE_PORT); 1294 MachEmptyWriteBuffer(); 1295 DELAY(10); 1296 while (1) { 1297 /* 1298 * Wait for transmitter to be not busy. 1299 */ 1300 timeout = 1000000; 1301 while (!(dcaddr->dc_csr & CSR_TRDY) && timeout > 0) 1302 timeout--; 1303 if (timeout == 0) { 1304 printf("MousePutc: timeout waiting for CSR_TRDY\n"); 1305 break; 1306 } 1307 line = (dcaddr->dc_csr >> 8) & 3; 1308 /* 1309 * Check to be sure its the right port. 1310 */ 1311 if (line != MOUSE_PORT) { 1312 tcr |= 1 << line; 1313 dcaddr->dc_tcr &= ~(1 << line); 1314 MachEmptyWriteBuffer(); 1315 DELAY(10); 1316 continue; 1317 } 1318 /* 1319 * Start sending the character. 1320 */ 1321 dcaddr->dc_tdr = dc_brk[0] | (c & 0xff); 1322 MachEmptyWriteBuffer(); 1323 DELAY(10); 1324 /* 1325 * Wait for character to be sent. 1326 */ 1327 while (1) { 1328 /* 1329 * cc -O bug: this code produces and infinite loop! 1330 * while (!(dcaddr->dc_csr & CSR_TRDY)) 1331 * ; 1332 */ 1333 timeout = 1000000; 1334 while (!(dcaddr->dc_csr & CSR_TRDY) && timeout > 0) 1335 timeout--; 1336 line = (dcaddr->dc_csr >> 8) & 3; 1337 if (line != MOUSE_PORT) { 1338 tcr |= 1 << line; 1339 dcaddr->dc_tcr &= ~(1 << line); 1340 MachEmptyWriteBuffer(); 1341 DELAY(10); 1342 continue; 1343 } 1344 dcaddr->dc_tcr &= ~(1 << MOUSE_PORT); 1345 MachEmptyWriteBuffer(); 1346 DELAY(10); 1347 break; 1348 } 1349 break; 1350 } 1351 /* 1352 * Enable interrupts for other lines which became ready. 1353 */ 1354 if (tcr & 0xF) { 1355 dcaddr->dc_tcr = tcr; 1356 MachEmptyWriteBuffer(); 1357 DELAY(10); 1358 } 1359 } 1360 1361 /* 1362 * ---------------------------------------------------------------------------- 1363 * 1364 * MouseGetc -- 1365 * 1366 * Read a character from the mouse. 1367 * This is only called at initialization time. 1368 * 1369 * Results: 1370 * A character read from the mouse, -1 if we timed out waiting. 1371 * 1372 * Side effects: 1373 * None. 1374 * 1375 * ---------------------------------------------------------------------------- 1376 */ 1377 static int 1378 MouseGetc() 1379 { 1380 register dcregs *dcaddr; 1381 register int timeout; 1382 register int c; 1383 1384 dcaddr = dcpdma[MOUSE_PORT].p_addr; 1385 for (timeout = 1000000; timeout > 0; timeout--) { 1386 if (!(dcaddr->dc_csr & CSR_RDONE)) 1387 continue; 1388 c = dcaddr->dc_rbuf; 1389 DELAY(10); 1390 if (((c >> 8) & 03) != MOUSE_PORT) 1391 continue; 1392 return (c & 0xff); 1393 } 1394 1395 return (-1); 1396 } 1397 1398 /* 1399 * ---------------------------------------------------------------------------- 1400 * 1401 * MouseInit -- 1402 * 1403 * Initialize the mouse. 1404 * 1405 * Results: 1406 * None. 1407 * 1408 * Side effects: 1409 * None. 1410 * 1411 * ---------------------------------------------------------------------------- 1412 */ 1413 static void 1414 MouseInit() 1415 { 1416 int id_byte1, id_byte2, id_byte3, id_byte4; 1417 1418 /* 1419 * Initialize the mouse. 1420 */ 1421 MousePutc(MOUSE_SELF_TEST); 1422 id_byte1 = MouseGetc(); 1423 if (id_byte1 < 0) { 1424 printf("MouseInit: Timeout on 1st byte of self-test report\n"); 1425 return; 1426 } 1427 id_byte2 = MouseGetc(); 1428 if (id_byte2 < 0) { 1429 printf("MouseInit: Timeout on 2nd byte of self-test report\n"); 1430 return; 1431 } 1432 id_byte3 = MouseGetc(); 1433 if (id_byte3 < 0) { 1434 printf("MouseInit: Timeout on 3rd byte of self-test report\n"); 1435 return; 1436 } 1437 id_byte4 = MouseGetc(); 1438 if (id_byte4 < 0) { 1439 printf("MouseInit: Timeout on 4th byte of self-test report\n"); 1440 return; 1441 } 1442 if ((id_byte2 & 0x0f) != 0x2) 1443 printf("MouseInit: We don't have a mouse!!!\n"); 1444 /* 1445 * For some reason, the mouse doesn't see this command if it comes 1446 * too soon after a self test. 1447 */ 1448 DELAY(100); 1449 MousePutc(MOUSE_INCREMENTAL); 1450 } 1451 #endif /* NDC */ 1452