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