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