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