]> git.saurik.com Git - apple/xnu.git/blob - pexpert/i386/kd.c
xnu-123.5.tar.gz
[apple/xnu.git] / pexpert / i386 / kd.c
1 /*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
11 *
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22 /*
23 * @OSF_COPYRIGHT@
24 */
25 /*
26 */
27
28 /*
29 * Olivetti Mach Console driver v0.0
30 * Copyright Ing. C. Olivetti & C. S.p.A. 1988, 1989
31 * All rights reserved.
32 *
33 */
34 /*
35 * Copyright 1988, 1989 by Olivetti Advanced Technology Center, Inc.,
36 * Cupertino, California.
37 *
38 * All Rights Reserved
39 *
40 * Permission to use, copy, modify, and distribute this software and
41 * its documentation for any purpose and without fee is hereby
42 * granted, provided that the above copyright notice appears in all
43 * copies and that both the copyright notice and this permission notice
44 * appear in supporting documentation, and that the name of Olivetti
45 * not be used in advertising or publicity pertaining to distribution
46 * of the software without specific, written prior permission.
47 *
48 * OLIVETTI DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
49 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
50 * IN NO EVENT SHALL OLIVETTI BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
51 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
52 * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
53 * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUR OF OR IN CONNECTION
54 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
55 *
56 *
57 * Copyright 1988, 1989 by Intel Corporation, Santa Clara, California.
58 *
59 * All Rights Reserved
60 *
61 * Permission to use, copy, modify, and distribute this software and
62 * its documentation for any purpose and without fee is hereby
63 * granted, provided that the above copyright notice appears in all
64 * copies and that both the copyright notice and this permission notice
65 * appear in supporting documentation, and that the name of Intel
66 * not be used in advertising or publicity pertaining to distribution
67 * of the software without specific, written prior permission.
68 *
69 * INTEL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
70 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
71 * IN NO EVENT SHALL INTEL BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
72 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
73 * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
74 * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
75 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
76 */
77
78 /* $ Header: $ */
79
80 #include <string.h>
81 #include "kd.h"
82
83 #include <mach/i386/vm_param.h>
84
85 #define at386_io_lock_state()
86 #define at386_io_lock(op) (TRUE)
87 #define at386_io_unlock()
88
89
90 typedef unsigned short i386_ioport_t;
91
92 /* read a byte */
93 extern unsigned char inb(
94 i386_ioport_t port);
95 /* write a longword */
96 extern void outb(
97 i386_ioport_t port,
98 unsigned char datum);
99
100 extern __inline__ unsigned char inb(
101 i386_ioport_t port)
102 {
103 unsigned char datum;
104 __asm__ volatile("inb %1, %0" : "=a" (datum) : "d" (port));
105 return(datum);
106 }
107
108 extern __inline__ void outb(
109 i386_ioport_t port,
110 unsigned char datum)
111 {
112 __asm__ volatile("outb %0, %1" : : "a" (datum), "d" (port));
113 }
114
115 /* Forward */
116
117 extern void kd_sendcmd(unsigned char ch);
118 extern void kdreboot(void);
119 extern int kd_dogetc(int wait);
120 extern void kd_handle_ack(void);
121 extern void kd_resend(void);
122 extern int do_modifier(
123 int state,
124 Scancode c,
125 int up);
126 extern int kdcheckmagic(
127 Scancode sc,
128 int * regs);
129 extern int kdstate2idx(
130 int state,
131 int extended);
132 extern void kdinit(void);
133 extern void kd_belloff(void);
134 extern void kd_bellon(void);
135 extern void kd_senddata(unsigned char c);
136 extern unsigned char kd_getdata(void);
137 extern unsigned char kd_cmdreg_read(void);
138 extern void set_kd_state(
139 int newstate);
140 extern unsigned char state2leds(
141 int state);
142 extern void kd_setleds1(
143 unsigned char val);
144 extern void kd_setleds2(void);
145 extern void cnsetleds(
146 unsigned char val);
147 extern int kd_kbd_magic(
148 int scancode);
149
150 extern int cngetc(void);
151 extern int cnmaygetc(void);
152 extern void kdreboot(void);
153 extern int kd_dogetc(int wait);
154
155 /* reboot on CTL-ALT-DEL ? */
156 extern int rebootflag;
157 /* enter kernel debugger on CTR-ALT-d ? */
158 int kbdkdbflag = 1;
159 /* allow keyboard mouse ? */
160 int kbdmouseflag = 0;
161
162 /*
163 * kd_state shows the state of the modifier keys (ctrl, caps lock,
164 * etc.) It should normally be changed by calling set_kd_state(), so
165 * that the keyboard status LEDs are updated correctly.
166 */
167 int kd_state = KS_NORMAL;
168 int kb_mode = KB_ASCII; /* event/ascii */
169
170 int kd_kbd_mouse = 0;
171 int kd_kbd_magic_scale = 6;
172 int kd_kbd_magic_button = 0;
173
174 /*
175 * Some keyboard commands work by sending a command, waiting for an
176 * ack (handled by kdintr), then sending data, which generates a
177 * second ack. If we are in the middle of such a sequence, kd_ack
178 * shows what the ack is for.
179 *
180 * When a byte is sent to the keyboard, it is kept around in last_sent
181 * in case it needs to be resent.
182 *
183 * The rest of the variables here hold the data required to complete
184 * the sequence.
185 *
186 * XXX - the System V driver keeps a command queue, I guess in case we
187 * want to start a command while another is in progress. Is this
188 * something we should worry about?
189 */
190 enum why_ack {NOT_WAITING, SET_LEDS, DATA_ACK};
191 enum why_ack kd_ack = NOT_WAITING;
192
193 unsigned char last_sent = 0;
194
195 unsigned char kd_nextled = 0;
196
197 /*
198 * We don't provide any mutex protection for this flag because we know
199 * that this module will have been initialized by the time multiple
200 * threads are running.
201 */
202 int kd_initialized = FALSE; /* driver initialized? */
203 int kd_extended = FALSE;
204
205 /*
206 * This array maps scancodes to Ascii characters (or character
207 * sequences).
208 * Each row corresponds to one key. There are NUMOUTPUT bytes per key
209 * state. The states are ordered: Normal, SHIFT, CTRL, ALT,
210 * SHIFT/ALT.
211 */
212 unsigned char key_map[NUMKEYS][WIDTH_KMAP] = {
213 {NC,NC,NC,NC,NC,NC,NC,NC,NC,NC,NC,NC,NC,NC,NC},
214 {K_ESC,NC,NC, K_ESC,NC,NC, K_ESC,NC,NC, K_ESC,NC,NC, K_ESC,NC,NC},
215 {K_ONE,NC,NC, K_BANG,NC,NC, K_ONE,NC,NC, 0x1b,0x4e,0x31, 0x1b,0x4e,0x21},
216 {K_TWO,NC,NC, K_ATSN,NC,NC, K_NUL,NC,NC, 0x1b,0x4e,0x32, 0x1b,0x4e,0x40},
217 {K_THREE,NC,NC, K_POUND,NC,NC, K_THREE,NC,NC, 0x1b,0x4e,0x33, 0x1b,0x4e,0x23},
218 {K_FOUR,NC,NC, K_DOLLAR,NC,NC, K_FOUR,NC,NC, 0x1b,0x4e,0x34, 0x1b,0x4e,0x24},
219 {K_FIVE,NC,NC, K_PERC,NC,NC, K_FIVE,NC,NC, 0x1b,0x4e,0x35, 0x1b,0x4e,0x25},
220 {K_SIX,NC,NC, K_CARET,NC,NC, K_RS,NC,NC, 0x1b,0x4e,0x36, 0x1b,0x4e,0x5e},
221 {K_SEVEN,NC,NC, K_AMPER,NC,NC, K_SEVEN,NC,NC, 0x1b,0x4e,0x37, 0x1b,0x4e,0x26},
222 {K_EIGHT,NC,NC, K_ASTER,NC,NC, K_EIGHT,NC,NC, 0x1b,0x4e,0x38, 0x1b,0x4e,0x2a},
223 {K_NINE,NC,NC, K_LPAREN,NC,NC, K_NINE,NC,NC, 0x1b,0x4e,0x39,0x1b,0x4e,0x28},
224 {K_ZERO,NC,NC, K_RPAREN,NC,NC, K_ZERO,NC,NC, 0x1b,0x4e,0x30,0x1b,0x4e,0x29},
225 {K_MINUS,NC,NC, K_UNDSC,NC,NC, K_US,NC,NC, 0x1b,0x4e,0x2d, 0x1b,0x4e,0x5f},
226 {K_EQL,NC,NC, K_PLUS,NC,NC, K_EQL,NC,NC, 0x1b,0x4e,0x3d, 0x1b,0x4e,0x2b},
227 {K_BS,NC,NC, K_BS,NC,NC, K_BS,NC,NC, K_BS,NC,NC, K_BS,NC,NC},
228 {K_HT,NC,NC, K_GS,NC,NC, K_HT,NC,NC, K_HT,NC,NC, K_GS,NC,NC},
229 {K_q,NC,NC, K_Q,NC,NC, K_DC1,NC,NC, 0x1b,0x4e,0x71, 0x1b,0x4e,0x51},
230 {K_w,NC,NC, K_W,NC,NC, K_ETB,NC,NC, 0x1b,0x4e,0x77, 0x1b,0x4e,0x57},
231 {K_e,NC,NC, K_E,NC,NC, K_ENQ,NC,NC, 0x1b,0x4e,0x65, 0x1b,0x4e,0x45},
232 {K_r,NC,NC, K_R,NC,NC, K_DC2,NC,NC, 0x1b,0x4e,0x72, 0x1b,0x4e,0x52},
233 {K_t,NC,NC, K_T,NC,NC, K_DC4,NC,NC, 0x1b,0x4e,0x74, 0x1b,0x4e,0x54},
234 {K_y,NC,NC, K_Y,NC,NC, K_EM,NC,NC, 0x1b,0x4e,0x79, 0x1b,0x4e,0x59},
235 {K_u,NC,NC, K_U,NC,NC, K_NAK,NC,NC, 0x1b,0x4e,0x75, 0x1b,0x4e,0x55},
236 {K_i,NC,NC, K_I,NC,NC, K_HT,NC,NC, 0x1b,0x4e,0x69, 0x1b,0x4e,0x49},
237 {K_o,NC,NC, K_O,NC,NC, K_SI,NC,NC, 0x1b,0x4e,0x6f, 0x1b,0x4e,0x4f},
238 {K_p,NC,NC, K_P,NC,NC, K_DLE,NC,NC, 0x1b,0x4e,0x70, 0x1b,0x4e,0x50},
239 {K_LBRKT,NC,NC, K_LBRACE,NC,NC, K_ESC,NC,NC, 0x1b,0x4e,0x5b, 0x1b,0x4e,0x7b},
240 {K_RBRKT,NC,NC, K_RBRACE,NC,NC, K_GS,NC,NC, 0x1b,0x4e,0x5d, 0x1b,0x4e,0x7d},
241 {K_CR,NC,NC, K_CR,NC,NC, K_CR,NC,NC, K_CR,NC,NC, K_CR,NC,NC},
242 {K_SCAN,K_CTLSC,NC, K_SCAN,K_CTLSC,NC, K_SCAN,K_CTLSC,NC, K_SCAN,K_CTLSC,NC,
243 K_SCAN,K_CTLSC,NC},
244 {K_a,NC,NC, K_A,NC,NC, K_SOH,NC,NC, 0x1b,0x4e,0x61, 0x1b,0x4e,0x41},
245 {K_s,NC,NC, K_S,NC,NC, K_DC3,NC,NC, 0x1b,0x4e,0x73, 0x1b,0x4e,0x53},
246 {K_d,NC,NC, K_D,NC,NC, K_EOT,NC,NC, 0x1b,0x4e,0x65, 0x1b,0x4e,0x45},
247 {K_f,NC,NC, K_F,NC,NC, K_ACK,NC,NC, 0x1b,0x4e,0x66, 0x1b,0x4e,0x46},
248 {K_g,NC,NC, K_G,NC,NC, K_BEL,NC,NC, 0x1b,0x4e,0x67, 0x1b,0x4e,0x47},
249 {K_h,NC,NC, K_H,NC,NC, K_BS,NC,NC, 0x1b,0x4e,0x68, 0x1b,0x4e,0x48},
250 {K_j,NC,NC, K_J,NC,NC, K_LF,NC,NC, 0x1b,0x4e,0x6a, 0x1b,0x4e,0x4a},
251 {K_k,NC,NC, K_K,NC,NC, K_VT,NC,NC, 0x1b,0x4e,0x6b, 0x1b,0x4e,0x4b},
252 {K_l,NC,NC, K_L,NC,NC, K_FF,NC,NC, 0x1b,0x4e,0x6c, 0x1b,0x4e,0x4c},
253 {K_SEMI,NC,NC, K_COLON,NC,NC, K_SEMI,NC,NC, 0x1b,0x4e,0x3b, 0x1b,0x4e,0x3a},
254 {K_SQUOTE,NC,NC,K_DQUOTE,NC,NC,K_SQUOTE,NC,NC,0x1b,0x4e,0x27,0x1b,0x4e,0x22},
255 {K_GRAV,NC,NC, K_TILDE,NC,NC, K_RS,NC,NC, 0x1b,0x4e,0x60, 0x1b,0x4e,0x7e},
256 {K_SCAN,K_LSHSC,NC, K_SCAN,K_LSHSC,NC, K_SCAN,K_LSHSC,NC, K_SCAN,K_LSHSC,NC,
257 K_SCAN,K_LSHSC,NC},
258 {K_BSLSH,NC,NC, K_PIPE,NC,NC, K_FS,NC,NC, 0x1b,0x4e,0x5c, 0x1b,0x4e,0x7c},
259 {K_z,NC,NC, K_Z,NC,NC, K_SUB,NC,NC, 0x1b,0x4e,0x7a, 0x1b,0x4e,0x5a},
260 {K_x,NC,NC, K_X,NC,NC, K_CAN,NC,NC, 0x1b,0x4e,0x78, 0x1b,0x4e,0x58},
261 {K_c,NC,NC, K_C,NC,NC, K_ETX,NC,NC, 0x1b,0x4e,0x63, 0x1b,0x4e,0x43},
262 {K_v,NC,NC, K_V,NC,NC, K_SYN,NC,NC, 0x1b,0x4e,0x76, 0x1b,0x4e,0x56},
263 {K_b,NC,NC, K_B,NC,NC, K_STX,NC,NC, 0x1b,0x4e,0x62, 0x1b,0x4e,0x42},
264 {K_n,NC,NC, K_N,NC,NC, K_SO,NC,NC, 0x1b,0x4e,0x6e, 0x1b,0x4e,0x4e},
265 {K_m,NC,NC, K_M,NC,NC, K_CR,NC,NC, 0x1b,0x4e,0x6d, 0x1b,0x4e,0x4d},
266 {K_COMMA,NC,NC, K_LTHN,NC,NC, K_COMMA,NC,NC, 0x1b,0x4e,0x2c, 0x1b,0x4e,0x3c},
267 {K_PERIOD,NC,NC, K_GTHN,NC,NC, K_PERIOD,NC,NC,0x1b,0x4e,0x2e,0x1b,0x4e,0x3e},
268 {K_SLASH,NC,NC, K_QUES,NC,NC, K_SLASH,NC,NC, 0x1b,0x4e,0x2f, 0x1b,0x4e,0x3f},
269 {K_SCAN,K_RSHSC,NC, K_SCAN,K_RSHSC,NC, K_SCAN,K_RSHSC,NC, K_SCAN,K_RSHSC,NC,
270 K_SCAN,K_RSHSC,NC},
271 {K_ASTER,NC,NC, K_ASTER,NC,NC, K_ASTER,NC,NC, 0x1b,0x4e,0x2a,0x1b,0x4e,0x2a},
272 {K_SCAN,K_ALTSC,NC, K_SCAN,K_ALTSC,NC, K_SCAN,K_ALTSC,NC, K_SCAN,K_ALTSC,NC,
273 K_SCAN,K_ALTSC,NC},
274 {K_SPACE,NC,NC, K_SPACE,NC,NC, K_NUL,NC,NC, K_SPACE,NC,NC, K_SPACE,NC,NC},
275 {K_SCAN,K_CLCKSC,NC, K_SCAN,K_CLCKSC,NC, K_SCAN,K_CLCKSC,NC,
276 K_SCAN,K_CLCKSC,NC, K_SCAN,K_CLCKSC,NC},
277 {K_F1, K_F1S, K_F1, K_F1, K_F1S},
278 {K_F2, K_F2S, K_F2, K_F2, K_F2S},
279 {K_F3, K_F3S, K_F3, K_F3, K_F3S},
280 {K_F4, K_F4S, K_F4, K_F4, K_F4S},
281 {K_F5, K_F5S, K_F5, K_F5, K_F5S},
282 {K_F6, K_F6S, K_F6, K_F6, K_F6S},
283 {K_F7, K_F7S, K_F7, K_F7, K_F7S},
284 {K_F8, K_F8S, K_F8, K_F8, K_F8S},
285 {K_F9, K_F9S, K_F9, K_F9, K_F9S},
286 {K_F10, K_F10S, K_F10, K_F10, K_F10S},
287 {K_SCAN,K_NLCKSC,NC, K_SCAN,K_NLCKSC,NC, K_SCAN,K_NLCKSC,NC,
288 K_SCAN,K_NLCKSC,NC, K_SCAN,K_NLCKSC,NC},
289 {K_SCRL, K_NUL,NC,NC, K_SCRL, K_SCRL, K_NUL,NC,NC},
290 {K_HOME, K_SEVEN,NC,NC, K_HOME, K_HOME, 0x1b,0x4e,0x37},
291 {K_UA, K_EIGHT,NC,NC, K_UA, K_UA, 0x1b,0x4e,0x38},
292 {K_PUP, K_NINE,NC,NC, K_PUP, K_PUP, 0x1b,0x4e,0x39},
293 {0x1b,0x5b,0x53, K_MINUS,NC,NC, 0x1b,0x5b,0x53,0x1b,0x5b,0x53,0x1b,0x4e,0x2d},
294 {K_LA, K_FOUR,NC,NC, K_LA, K_LA, 0x1b,0x4e,0x34},
295 {0x1b,0x5b,0x47,K_FIVE,NC,NC,0x1b,0x5b,0x47, 0x1b,0x5b,0x47, 0x1b,0x4e,0x35},
296 {K_RA, K_SIX,NC,NC, K_RA, K_RA, 0x1b,0x4e,0x36},
297 {0x1b,0x5b,0x54,K_PLUS,NC,NC, 0x1b,0x5b,0x54, 0x1b,0x5b,0x54, 0x1b,0x4e,0x2b},
298 {K_END, K_ONE,NC,NC, K_END, K_END, 0x1b,0x4e,0x31},
299 {K_DA, K_TWO,NC,NC, K_DA, K_DA, 0x1b,0x4e,0x32},
300 {K_PDN, K_THREE,NC,NC, K_PDN, K_PDN, 0x1b,0x4e,0x33},
301 {K_INS, K_ZERO,NC,NC, K_INS, K_INS, 0x1b,0x4e,0x30},
302 {K_DEL,NC,NC, K_PERIOD,NC,NC, K_DEL,NC,NC, K_DEL,NC,NC, 0x1b,0x4e,0x2e},
303 {NC,NC,NC,NC,NC,NC,NC,NC,NC,NC,NC,NC,NC,NC,NC},
304 {NC,NC,NC,NC,NC,NC,NC,NC,NC,NC,NC,NC,NC,NC,NC},
305 {NC,NC,NC,NC,NC,NC,NC,NC,NC,NC,NC,NC,NC,NC,NC},
306 {K_F11, K_F11S, K_F11, K_F11, K_F11S},
307 {K_F12, K_F12S, K_F12, K_F12, K_F12S}
308 };
309
310 extern void cnputc(unsigned char ch);
311
312 /*
313 * Switch for poll vs. interrupt.
314 */
315 int kd_pollc = 0;
316
317 int (*cgetc)(
318 int wait) = kd_dogetc;
319 /* get a char. from console */
320 void (*cputc)(
321 char ch) = cnputc;
322 /* put a char. to console */
323
324 /*
325 * cngetc:
326 *
327 * Get one character using polling, rather than interrupts. Used
328 * by the kernel debugger. Note that Caps Lock is ignored.
329 * Normally this routine is called with interrupts already
330 * disabled, but there is code in place so that it will be more
331 * likely to work even if interrupts are turned on.
332 */
333
334 int
335 cngetc(void)
336 {
337 int ret;
338
339 ret = (*cgetc)(TRUE);
340
341 return ret;
342 }
343
344 int
345 cnmaygetc(void)
346 {
347 int ret;
348
349 ret = (*cgetc)(FALSE);
350
351 return ret;
352 }
353
354 int
355 kd_dogetc(
356 int wait)
357 {
358 unsigned char c;
359 unsigned char scancode;
360 unsigned int char_idx;
361 int up;
362
363 kdinit();
364 kd_extended = FALSE;
365
366 for ( ; ; ) {
367 while (!(inb(K_STATUS) & K_OBUF_FUL))
368 if (!wait)
369 return (-1);
370 up = FALSE;
371 /*
372 * We'd come here for mouse events in debugger, if
373 * the mouse were on.
374 */
375 if ((inb(K_STATUS) & 0x20) == 0x20) {
376 printf("M%xP", inb(K_RDWR));
377 continue;
378 }
379 scancode = inb(K_RDWR);
380 /*
381 * Handle extend modifier and
382 * ack/resend, otherwise we may never receive
383 * a key.
384 */
385 if (scancode == K_EXTEND) {
386 kd_extended = TRUE;
387 continue;
388 } else if (scancode == K_RESEND) {
389 /* printf("kd_getc: resend"); */
390 kd_resend();
391 continue;
392 } else if (scancode == K_ACKSC) {
393 /* printf("kd_getc: handle_ack"); */
394 kd_handle_ack();
395 continue;
396 }
397 if (scancode & K_UP) {
398 up = TRUE;
399 scancode &= ~K_UP;
400 }
401 if (kd_kbd_mouse)
402 kd_kbd_magic(scancode);
403 if (scancode < NUMKEYS) {
404 /* Lookup in map, then process. */
405 char_idx = kdstate2idx(kd_state, kd_extended);
406 c = key_map[scancode][char_idx];
407 if (c == K_SCAN) {
408 c = key_map[scancode][++char_idx];
409 kd_state = do_modifier(kd_state, c, up);
410 #ifdef notdef
411 cnsetleds(state2leds(kd_state));
412 #endif
413 } else if (!up) {
414 /* regular key-down */
415 if (c == K_CR)
416 c = K_LF;
417 #ifdef notdef
418 splx(o_pri);
419 #endif
420 return(c & 0177);
421 }
422 }
423 }
424 }
425
426
427 int old_kb_mode;
428
429 #if MACH_KDB
430 #define poll_spl() db_splhigh() /* prevent race w/ kdintr() */
431 #define poll_splx(s) db_splx(s)
432 #else /* MACH_KDB */
433 #define poll_spl() SPLKD()
434 #define poll_splx(s) splx(s)
435 #endif /* MACH_KDB */
436
437
438 void
439 cnpollc(
440 int on)
441 {
442 int old_spl; /* spl we're called at... */
443
444 if (cpu_number()) {
445 return;
446 }
447 if (on) {
448 old_spl = poll_spl();
449
450 old_kb_mode = kb_mode;
451 kb_mode = KB_ASCII;
452 poll_splx(old_spl);
453
454 kd_pollc++;
455 } else {
456 --kd_pollc;
457
458 old_spl = poll_spl();
459 kb_mode = old_kb_mode;
460 poll_splx(old_spl);
461
462
463 }
464 }
465
466 /*
467 * kd_handle_ack:
468 *
469 * For pending commands, complete the command. For data bytes,
470 * drop the ack on the floor.
471 */
472
473 void
474 kd_handle_ack(void)
475 {
476 switch (kd_ack) {
477 case SET_LEDS:
478 kd_setleds2();
479 kd_ack = DATA_ACK;
480 break;
481 case DATA_ACK:
482 kd_ack = NOT_WAITING;
483 break;
484 case NOT_WAITING:
485 printf("unexpected ACK from keyboard\n");
486 break;
487 default:
488 panic("bogus kd_ack\n");
489 break;
490 }
491 }
492
493 /*
494 * kd_resend:
495 *
496 * Resend a missed keyboard command or data byte.
497 */
498
499 void
500 kd_resend(void)
501 {
502 if (kd_ack == NOT_WAITING)
503 printf("unexpected RESEND from keyboard\n");
504 else
505 kd_senddata(last_sent);
506 }
507
508
509 /*
510 * do_modifier:
511 *
512 * Change keyboard state according to which modifier key and
513 * whether it went down or up.
514 *
515 * input: the current state, the key, and the key's direction.
516 * The key can be any key, not just a modifier key.
517 *
518 * output: the new state
519 */
520
521 int
522 do_modifier(
523 int state,
524 Scancode c,
525 int up)
526 {
527 switch (c) {
528 case (K_ALTSC):
529 if (up)
530 state &= ~KS_ALTED;
531 else
532 state |= KS_ALTED;
533 kd_extended = FALSE;
534 break;
535 #ifndef ORC
536 case (K_CLCKSC):
537 #endif /* ORC */
538 case (K_CTLSC):
539 if (up)
540 state &= ~KS_CTLED;
541 else
542 state |= KS_CTLED;
543 kd_extended = FALSE;
544 break;
545 #ifdef ORC
546 case (K_CLCKSC):
547 if (!up)
548 state ^= KS_CLKED;
549 break;
550 #endif /* ORC */
551 case (K_NLCKSC):
552 if (!up)
553 state ^= KS_NLKED;
554 break;
555 case (K_LSHSC):
556 case (K_RSHSC):
557 if (up)
558 state &= ~KS_SHIFTED;
559 else
560 state |= KS_SHIFTED;
561 kd_extended = FALSE;
562 break;
563 }
564
565 return(state);
566 }
567
568
569 /*
570 * kdcheckmagic:
571 *
572 * Check for magic keystrokes for invoking the debugger or
573 * rebooting or ...
574 *
575 * input: an unprocessed scancode
576 *
577 * output: TRUE if a magic key combination was recognized and
578 * processed. FALSE otherwise.
579 *
580 * side effects:
581 * various actions possible, depending on which keys are
582 * pressed. If the debugger is called, steps are taken
583 * to ensure that the system doesn't think the magic keys
584 * are still held down.
585 */
586
587 int
588 kdcheckmagic(
589 Scancode scancode,
590 int *regs)
591 {
592 static int magic_state = KS_NORMAL; /* like kd_state */
593 int up = FALSE;
594 extern int rebootflag;
595
596 if (scancode == 0x46 && kbdmouseflag) /* scroll lock */
597 {
598 kd_kbd_mouse = !kd_kbd_mouse;
599 kd_kbd_magic_button = 0;
600 return(TRUE);
601 }
602 if (scancode & K_UP) {
603 up = TRUE;
604 scancode &= ~K_UP;
605 }
606 magic_state = do_modifier(magic_state, scancode, up);
607
608 if ((magic_state&(KS_CTLED|KS_ALTED)) == (KS_CTLED|KS_ALTED)) {
609 switch (scancode) {
610 #if MACH_KDB
611 case K_dSC: /* ctl-alt-d */
612 if (!kbdkdbflag)
613 return(FALSE);
614
615 kdb_kintr(); /* invoke debugger */
616
617 /* Returned from debugger, so reset kbd state. */
618 (void)SPLKD();
619 magic_state = KS_NORMAL;
620 if (kb_mode == KB_ASCII)
621 kd_state = KS_NORMAL;
622 /* setting leds kills kbd */
623
624 return(TRUE);
625 break;
626 #endif /* MACH_KDB */
627 case K_DELSC: /* ctl-alt-del */
628 /* if rebootflag is on, reboot the system */
629 if (rebootflag)
630 kdreboot();
631 break;
632 }
633 }
634 return(FALSE);
635 }
636
637
638 /*
639 * kdstate2idx:
640 *
641 * Return the value for the 2nd index into key_map that
642 * corresponds to the given state.
643 */
644
645 int
646 kdstate2idx(
647 int state, /* bit vector, not a state index */
648 int extended)
649 {
650 int state_idx = NORM_STATE;
651
652 if ((!extended) && state != KS_NORMAL) {
653 if ((state&(KS_SHIFTED|KS_ALTED)) == (KS_SHIFTED|KS_ALTED))
654 state_idx = SHIFT_ALT;
655 else if (state&KS_SHIFTED)
656 state_idx = SHIFT_STATE;
657 else if (state&KS_ALTED)
658 state_idx = ALT_STATE;
659 else if (state&KS_CTLED)
660 state_idx = CTRL_STATE;
661 }
662
663 return (CHARIDX(state_idx));
664 }
665
666 /*
667 * kdinit:
668 *
669 * This code initializes the structures and sets up the port registers
670 * for the console driver.
671 *
672 * Each bitmap-based graphics card is likely to require a unique
673 * way to determine the card's presence. The driver runs through
674 * each "special" card that it knows about and uses the first one
675 * that it finds. If it doesn't find any, it assumes that an
676 * EGA-like card is installed.
677 *
678 * input : None. Interrupts are assumed to be disabled
679 * output : Driver is initialized
680 *
681 */
682
683 void
684 kdinit(void)
685 {
686 unsigned char k_comm; /* keyboard command byte */
687 unsigned char kd_stat;
688
689 if (kd_initialized)
690 return;
691 kd_initialized = TRUE;
692
693 /* get rid of any garbage in output buffer */
694 if (inb(K_STATUS) & K_OBUF_FUL)
695 (void)inb(K_RDWR);
696
697 cnsetleds(kd_state = KS_NORMAL);
698
699 kd_sendcmd(KC_CMD_READ); /* ask for the ctlr command byte */
700 k_comm = kd_getdata();
701 k_comm &= ~K_CB_DISBLE; /* clear keyboard disable bit */
702 k_comm |= K_CB_ENBLIRQ; /* enable interrupt */
703 kd_sendcmd(KC_CMD_WRITE); /* write new ctlr command byte */
704 kd_senddata(k_comm);
705
706 /* set_kd_state(KS_NORMAL); does only HALF of set-leds sequence -
707 leaves kbd dead */
708
709 /* get rid of any garbage in output buffer */
710 (void)inb(K_RDWR);
711 }
712
713 /*
714 * kd_belloff:
715 *
716 * This routine shuts the bell off, by sending the appropriate code
717 * to the speaker port.
718 *
719 * input : None
720 * output : bell is turned off
721 *
722 */
723
724 void
725 kd_belloff(void)
726 {
727 unsigned char status;
728
729 status = (inb(K_PORTB) & ~(K_SPKRDATA | K_ENABLETMR2));
730 outb(K_PORTB, status);
731 }
732
733
734 /*
735 * kd_bellon:
736 *
737 * This routine turns the bell on.
738 *
739 * input : None
740 * output : bell is turned on
741 *
742 */
743
744 void
745 kd_bellon(void)
746 {
747 unsigned char status;
748
749 /* program timer 2 */
750 outb(K_TMRCTL, K_SELTMR2 | K_RDLDTWORD | K_TSQRWAVE | K_TBINARY);
751 outb(K_TMR2, 1500 & 0xff); /* LSB */
752 outb(K_TMR2, (int)1500 >> 8); /* MSB */
753
754 /* start speaker - why must we turn on K_SPKRDATA? */
755 status = (inb(K_PORTB)| K_ENABLETMR2 | K_SPKRDATA);
756 outb(K_PORTB, status);
757 return;
758 }
759
760 /*
761 * kd_senddata:
762 *
763 * This function sends a byte to the keyboard RDWR port, but
764 * first waits until the input/output data buffer is clear before
765 * sending the data. Note that this byte can be either data or a
766 * keyboard command.
767 *
768 */
769
770 void
771 kd_senddata(
772 unsigned char ch)
773 {
774 while (inb(K_STATUS) & K_IBUF_FUL);
775 outb(K_RDWR, ch);
776 last_sent = ch;
777 }
778
779 /*
780 * kd_sendcmd:
781 *
782 * This function sends a command byte to the keyboard command
783 * port, but first waits until the input/output data buffer is
784 * clear before sending the data.
785 *
786 */
787
788 void
789 kd_sendcmd(
790 unsigned char ch)
791 {
792 while (inb(K_STATUS) & K_IBUF_FUL);
793 outb(K_CMD, ch);
794 }
795
796
797 /*
798 * kd_getdata:
799 *
800 * This function returns a data byte from the keyboard RDWR port,
801 * after waiting until the port is flagged as having something to
802 * read.
803 */
804
805 unsigned char
806 kd_getdata(void)
807 {
808 while ((inb(K_STATUS) & K_OBUF_FUL) == 0);
809 return(inb(K_RDWR));
810 }
811
812 unsigned char
813 kd_cmdreg_read(void)
814 {
815 int ch=KC_CMD_READ;
816
817 while (inb(K_STATUS) & (K_IBUF_FUL | K_OBUF_FUL));
818 outb(K_CMD, ch);
819
820 while ((inb(K_STATUS) & K_OBUF_FUL) == 0);
821 return(inb(K_RDWR));
822 }
823
824 void
825 kd_cmdreg_write(
826 unsigned char val)
827 {
828 int ch=KC_CMD_WRITE;
829
830 while (inb(K_STATUS) & K_IBUF_FUL);
831 outb(K_CMD, ch);
832
833 while (inb(K_STATUS) & K_IBUF_FUL);
834 outb(K_RDWR, val);
835 }
836
837 int kd_mouse_write_no_ack = 0;
838
839 int
840 kd_mouse_write(
841 unsigned char val)
842 {
843 int ch=0xd4; /* output byte to aux device (i.e. mouse) */
844 int ret = 0;
845
846 while (inb(K_STATUS) & K_IBUF_FUL);
847 outb(K_CMD, ch);
848
849 while (inb(K_STATUS) & K_IBUF_FUL);
850 outb(K_RDWR, val);
851
852 if (kd_mouse_write_no_ack) goto done;
853
854 while ((inb(K_STATUS) & K_OBUF_FUL) == 0);
855 if ((inb(K_STATUS) & 0x20) == 0x20) {
856 switch (ret = inb(K_RDWR)) {
857 case 0xfa:
858 break;
859 case 0xfe:
860 case 0xfc:
861 default:
862 printf("kd_mouse_write: saw %x for %x\n",
863 ret, val);
864 }
865 } else { /* abort */
866 printf("kd_mouse_write: sync error ??? on %x\n", val);
867 }
868
869 done:
870 return ret;
871 }
872
873 void
874 kd_mouse_read(
875 int no,
876 char *buf)
877 {
878
879 while (no-- > 0) {
880 while ((inb(K_STATUS) & K_OBUF_FUL) == 0);
881 /*
882 * We may have seen a mouse event.
883 */
884 if ((inb(K_STATUS) & 0x20) == 0x20) {
885 *buf++ = (unsigned char)inb(K_RDWR);
886 } else { /* abort */
887 int junk = inb(K_RDWR);
888 printf("kd_mouse_read: sync error, received: 0x%x\n",
889 junk);
890 break;
891 }
892 }
893 }
894
895 void
896 kd_mouse_drain(void)
897 {
898 int i;
899 while(inb(K_STATUS) & K_IBUF_FUL);
900 while((i = inb(K_STATUS)) & K_OBUF_FUL)
901 printf("kbd: S = %x D = %x\n", i, inb(K_RDWR));
902 }
903
904 /*
905 * set_kd_state:
906 *
907 * Set kd_state and update the keyboard status LEDs.
908 */
909
910 void
911 set_kd_state(
912 int newstate)
913 {
914 kd_state = newstate;
915 kd_setleds1(state2leds(newstate));
916 }
917
918 /*
919 * state2leds:
920 *
921 * Return a byte containing LED settings for the keyboard, given
922 * a state vector.
923 */
924
925 unsigned char
926 state2leds(
927 int state)
928 {
929 unsigned char result = 0;
930
931 if (state & KS_NLKED)
932 result |= K_LED_NUMLK;
933 if (state & KS_CLKED)
934 result |= K_LED_CAPSLK;
935 return(result);
936 }
937
938 /*
939 * kd_setleds[12]:
940 *
941 * Set the keyboard LEDs according to the given byte.
942 */
943
944 void
945 kd_setleds1(
946 unsigned char val)
947 {
948 if (kd_ack != NOT_WAITING) {
949 printf("kd_setleds1: unexpected state (%d)\n", kd_ack);
950 return;
951 }
952
953 kd_ack = SET_LEDS;
954 kd_nextled = val;
955 kd_senddata(K_CMD_LEDS);
956 }
957
958 void
959 kd_setleds2(void)
960 {
961 kd_senddata(kd_nextled);
962 }
963
964
965 /*
966 * cnsetleds:
967 *
968 * like kd_setleds[12], but not interrupt-based.
969 * Currently disabled because cngetc ignores caps lock and num
970 * lock anyway.
971 */
972
973 void
974 cnsetleds(
975 unsigned char val)
976 {
977 kd_senddata(K_CMD_LEDS);
978 (void)kd_getdata(); /* XXX - assume is ACK */
979 kd_senddata(val);
980 (void)kd_getdata(); /* XXX - assume is ACK */
981 }
982
983 void
984 kdreboot(void)
985 {
986 kd_sendcmd(0xFE); /* XXX - magic # */
987 /*
988 * DRAT. We're still here. Let's try a "CPU shutdown", which consists
989 * of clearing the IDTR and causing an exception. It's in locore.s
990 */
991 cpu_shutdown();
992 /*NOTREACHED*/
993 }
994
995 int
996 kd_kbd_magic(
997 int scancode)
998 {
999 int new_button = 0;
1000
1001 if (kd_kbd_mouse == 2)
1002 printf("sc = %x\n", scancode);
1003
1004 switch (scancode) {
1005 /* f1 f2 f3 */
1006 case 0x3d:
1007 new_button++;
1008 case 0x3c:
1009 new_button++;
1010 case 0x3b:
1011 new_button++;
1012 if (kd_kbd_magic_button && (new_button != kd_kbd_magic_button)) {
1013 /* down w/o up */
1014 }
1015 /* normal */
1016 if (kd_kbd_magic_button == new_button) {
1017 kd_kbd_magic_button = 0;
1018 } else {
1019 kd_kbd_magic_button = new_button;
1020 }
1021 break;
1022 default:
1023 return 0;
1024 }
1025 return 1;
1026 }