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