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