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