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