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