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