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