Commit | Line | Data |
---|---|---|
12d43ee5 KM |
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. | |
84722262 RC |
7 | * @(#)dz.c 7.9 (Berkeley) 6/28/90 |
8 | */ | |
9 | ||
10 | /* | |
11 | * devDC7085.c -- | |
12d43ee5 KM |
12 | * |
13 | * %sccs.include.redist.c% | |
14 | * | |
38a01dbe | 15 | * @(#)dc.c 7.9 (Berkeley) %G% |
12d43ee5 KM |
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 | */ | |
38a01dbe KB |
39 | #include <sys/param.h> |
40 | #include <sys/systm.h> | |
41 | #include <sys/ioctl.h> | |
42 | #include <sys/tty.h> | |
43 | #include <sys/proc.h> | |
44 | #include <sys/map.h> | |
45 | #include <sys/buf.h> | |
46 | #include <sys/conf.h> | |
47 | #include <sys/file.h> | |
48 | #include <sys/uio.h> | |
49 | #include <sys/kernel.h> | |
50 | #include <sys/syslog.h> | |
12d43ee5 | 51 | |
38a01dbe | 52 | #include <machine/dc7085cons.h> |
12d43ee5 | 53 | |
38a01dbe KB |
54 | #include <mips/dev/device.h> |
55 | #include <mips/dev/pdma.h> | |
12d43ee5 KM |
56 | |
57 | /* | |
58 | * Driver information for auto-configuration stuff. | |
59 | */ | |
60 | int dcprobe(); | |
84722262 | 61 | void dcintr(); |
12d43ee5 | 62 | struct driver dcdriver = { |
84722262 | 63 | "dc", dcprobe, 0, 0, dcintr, |
12d43ee5 KM |
64 | }; |
65 | ||
66 | #define NDCLINE (NDC*4) | |
67 | ||
c74d1258 RC |
68 | extern void dcstart __P((struct tty *)); |
69 | extern void dcxint __P((struct tty *)); | |
2c940704 | 70 | extern void ttrstrt __P((void *)); |
12d43ee5 KM |
71 | |
72 | struct tty dc_tty[NDCLINE]; | |
73 | int dc_cnt = NDCLINE; | |
60160479 RC |
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 */ | |
12d43ee5 KM |
77 | #ifdef DEBUG |
78 | int debugChar; | |
79 | #endif | |
80 | ||
57373dbf | 81 | static void dcscan __P((void *)); |
c74d1258 RC |
82 | static int dcMapChar __P((int)); |
83 | static void dcKBDReset __P((void)); | |
84 | static void MouseInit __P((void)); | |
85 | ||
12d43ee5 KM |
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, | |
84722262 RC |
117 | #ifdef DS5000 |
118 | 19200, LPR_B19200, | |
119 | #endif | |
12d43ee5 KM |
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; | |
12d43ee5 KM |
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; | |
57373dbf | 394 | timeout(dcscan, (void *)0, hz); |
12d43ee5 | 395 | } |
84722262 RC |
396 | printf("dc%d at nexus0 csr 0x%x priority %d\n", |
397 | cp->pmax_unit, cp->pmax_addr, cp->pmax_pri); | |
12d43ee5 KM |
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 | ||
c74d1258 | 414 | dcopen(dev, flag, mode, p) |
12d43ee5 | 415 | dev_t dev; |
c74d1258 RC |
416 | int flag, mode; |
417 | struct proc *p; | |
12d43ee5 KM |
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*/ | |
c74d1258 | 468 | dcclose(dev, flag, mode, p) |
12d43ee5 | 469 | dev_t dev; |
c74d1258 RC |
470 | int flag, mode; |
471 | struct proc *p; | |
12d43ee5 KM |
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 | } | |
c74d1258 | 483 | (*linesw[tp->t_line].l_close)(tp, flag); |
12d43ee5 KM |
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 | ||
12d43ee5 | 510 | /*ARGSUSED*/ |
c74d1258 | 511 | dcioctl(dev, cmd, data, flag, p) |
12d43ee5 KM |
512 | dev_t dev; |
513 | caddr_t data; | |
c74d1258 RC |
514 | int flag; |
515 | struct proc *p; | |
12d43ee5 KM |
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]; | |
c74d1258 | 523 | error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); |
12d43ee5 KM |
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 | ||
84722262 RC |
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) { | |
60160479 | 678 | (*dcDivertXInput)(cc); |
84722262 RC |
679 | return; |
680 | } | |
681 | if ((cc = dcMapChar(cc)) < 0) | |
682 | return; | |
60160479 RC |
683 | } else if (tp == &dc_tty[MOUSE_PORT] && dcMouseButtons) { |
684 | register MouseReport *mrp; | |
84722262 RC |
685 | static MouseReport currentRep; |
686 | ||
60160479 RC |
687 | mrp = ¤tRep; |
688 | mrp->byteCount++; | |
84722262 RC |
689 | if (cc & MOUSE_START_FRAME) { |
690 | /* | |
691 | * The first mouse report byte (button state). | |
692 | */ | |
60160479 RC |
693 | mrp->state = cc; |
694 | if (mrp->byteCount > 1) | |
695 | mrp->byteCount = 1; | |
696 | } else if (mrp->byteCount == 2) { | |
84722262 RC |
697 | /* |
698 | * The second mouse report byte (delta x). | |
699 | */ | |
60160479 RC |
700 | mrp->dx = cc; |
701 | } else if (mrp->byteCount == 3) { | |
84722262 RC |
702 | /* |
703 | * The final mouse report byte (delta y). | |
704 | */ | |
60160479 RC |
705 | mrp->dy = cc; |
706 | mrp->byteCount = 0; | |
707 | if (mrp->dx != 0 || mrp->dy != 0) { | |
84722262 RC |
708 | /* |
709 | * If the mouse moved, | |
710 | * post a motion event. | |
711 | */ | |
60160479 | 712 | (*dcMouseEvent)(mrp); |
84722262 | 713 | } |
60160479 | 714 | (*dcMouseButtons)(mrp); |
84722262 RC |
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 | ||
024ed1ef | 734 | void |
12d43ee5 KM |
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 | ||
024ed1ef | 767 | void |
12d43ee5 KM |
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 | } | |
86e31fc2 | 786 | selwakeup(&tp->t_wsel); |
12d43ee5 KM |
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; | |
60160479 | 794 | cnputc(cc); |
12d43ee5 KM |
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 | } | |
86e31fc2 | 805 | selwakeup(&tp->t_wsel); |
12d43ee5 KM |
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); | |
57373dbf | 815 | timeout(ttrstrt, (void *)tp, (cc & 0x7f) + 6); |
12d43ee5 KM |
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; | |
84722262 RC |
856 | #ifdef DS5000 |
857 | register int msr; | |
858 | #endif | |
12d43ee5 KM |
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?) */ | |
84722262 RC |
865 | switch (unit & 03) { |
866 | case 2: | |
12d43ee5 KM |
867 | mbits = 0; |
868 | if (dcaddr->dc_tcr & TCR_DTR2) | |
869 | mbits |= DML_DTR; | |
84722262 | 870 | #ifdef DS3100 |
12d43ee5 KM |
871 | if (dcaddr->dc_msr & MSR_DSR2) |
872 | mbits |= DML_DSR | DML_CAR; | |
84722262 RC |
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: | |
12d43ee5 | 897 | mbits = DML_DTR | DML_DSR | DML_CAR; |
84722262 | 898 | } |
12d43ee5 KM |
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 | } | |
84722262 RC |
916 | switch (unit & 03) { |
917 | case 2: | |
12d43ee5 KM |
918 | if (mbits & DML_DTR) |
919 | dcaddr->dc_tcr |= TCR_DTR2; | |
920 | else | |
921 | dcaddr->dc_tcr &= ~TCR_DTR2; | |
84722262 RC |
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 | |
12d43ee5 KM |
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 | */ | |
57373dbf | 942 | /* ARGSUSED */ |
c74d1258 | 943 | static void |
57373dbf RC |
944 | dcscan(arg) |
945 | void *arg; | |
12d43ee5 KM |
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); | |
57373dbf | 969 | timeout(dcscan, (void *)0, hz); |
12d43ee5 KM |
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 | * | |
84722262 | 1074 | * dcDebugGetc -- |
12d43ee5 | 1075 | * |
84722262 | 1076 | * Read a character from the keyboard if one is ready (i.e., don't wait). |
12d43ee5 KM |
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 | |
84722262 | 1087 | dcDebugGetc() |
12d43ee5 KM |
1088 | { |
1089 | register dcregs *dcaddr; | |
1090 | register int c; | |
c74d1258 | 1091 | int s; |
12d43ee5 KM |
1092 | |
1093 | dcaddr = dcpdma[KBD_PORT].p_addr; | |
1094 | if (!dcaddr) | |
1095 | return (0); | |
c74d1258 RC |
1096 | |
1097 | s = spltty(); | |
12d43ee5 KM |
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 | } | |
c74d1258 RC |
1109 | splx(s); |
1110 | ||
12d43ee5 KM |
1111 | return (c & 0xff); |
1112 | } | |
1113 | #endif | |
1114 | ||
84722262 RC |
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 | ||
12d43ee5 KM |
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 */ |