]>
git.saurik.com Git - apple/xnu.git/blob - pexpert/i386/kd.c
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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.
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
20 * @APPLE_LICENSE_HEADER_END@
29 * Olivetti Mach Console driver v0.0
30 * Copyright Ing. C. Olivetti & C. S.p.A. 1988, 1989
31 * All rights reserved.
35 * Copyright 1988, 1989 by Olivetti Advanced Technology Center, Inc.,
36 * Cupertino, California.
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.
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.
57 * Copyright 1988, 1989 by Intel Corporation, Santa Clara, California.
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.
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.
83 #include <mach/i386/vm_param.h>
85 #define at386_io_lock_state()
86 #define at386_io_lock(op) (TRUE)
87 #define at386_io_unlock()
90 typedef unsigned short i386_ioport_t
;
93 extern unsigned char inb(
95 /* write a longword */
100 extern __inline__
unsigned char inb(
104 __asm__
volatile("inb %1, %0" : "=a" (datum
) : "d" (port
));
108 extern __inline__
void outb(
112 __asm__
volatile("outb %0, %1" : : "a" (datum
), "d" (port
));
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(
126 extern int kdcheckmagic(
129 extern int kdstate2idx(
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(
140 extern unsigned char state2leds(
142 extern void kd_setleds1(
144 extern void kd_setleds2(void);
145 extern void cnsetleds(
147 extern int kd_kbd_magic(
150 extern int cngetc(void);
151 extern int cnmaygetc(void);
152 extern void kdreboot(void);
153 extern int kd_dogetc(int wait
);
155 /* reboot on CTL-ALT-DEL ? */
156 extern int rebootflag
;
157 /* enter kernel debugger on CTR-ALT-d ? */
159 /* allow keyboard mouse ? */
160 int kbdmouseflag
= 0;
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.
167 int kd_state
= KS_NORMAL
;
168 int kb_mode
= KB_ASCII
; /* event/ascii */
170 int kd_kbd_mouse
= 0;
171 int kd_kbd_magic_scale
= 6;
172 int kd_kbd_magic_button
= 0;
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.
180 * When a byte is sent to the keyboard, it is kept around in last_sent
181 * in case it needs to be resent.
183 * The rest of the variables here hold the data required to complete
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?
190 enum why_ack
{NOT_WAITING
, SET_LEDS
, DATA_ACK
};
191 enum why_ack kd_ack
= NOT_WAITING
;
193 unsigned char last_sent
= 0;
195 unsigned char kd_nextled
= 0;
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.
202 int kd_initialized
= FALSE
; /* driver initialized? */
203 int kd_extended
= FALSE
;
206 * This array maps scancodes to Ascii characters (or character
208 * Each row corresponds to one key. There are NUMOUTPUT bytes per key
209 * state. The states are ordered: Normal, SHIFT, CTRL, ALT,
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
,
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
,
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
,
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
,
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
}
310 extern void cnputc(unsigned char ch
);
313 * Switch for poll vs. interrupt.
318 int wait
) = kd_dogetc
;
319 /* get a char. from console */
322 /* put a char. to console */
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.
339 ret
= (*cgetc
)(TRUE
);
349 ret
= (*cgetc
)(FALSE
);
359 unsigned char scancode
;
360 unsigned int char_idx
;
367 while (!(inb(K_STATUS
) & K_OBUF_FUL
))
372 * We'd come here for mouse events in debugger, if
375 if ((inb(K_STATUS
) & 0x20) == 0x20) {
376 printf("M%xP", inb(K_RDWR
));
379 scancode
= inb(K_RDWR
);
381 * Handle extend modifier and
382 * ack/resend, otherwise we may never receive
385 if (scancode
== K_EXTEND
) {
388 } else if (scancode
== K_RESEND
) {
389 /* printf("kd_getc: resend"); */
392 } else if (scancode
== K_ACKSC
) {
393 /* printf("kd_getc: handle_ack"); */
397 if (scancode
& K_UP
) {
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
];
408 c
= key_map
[scancode
][++char_idx
];
409 kd_state
= do_modifier(kd_state
, c
, up
);
411 cnsetleds(state2leds(kd_state
));
414 /* regular key-down */
430 #define poll_spl() db_splhigh() /* prevent race w/ kdintr() */
431 #define poll_splx(s) db_splx(s)
433 #define poll_spl() SPLKD()
434 #define poll_splx(s) splx(s)
435 #endif /* MACH_KDB */
442 int old_spl
; /* spl we're called at... */
448 old_spl
= poll_spl();
450 old_kb_mode
= kb_mode
;
458 old_spl
= poll_spl();
459 kb_mode
= old_kb_mode
;
469 * For pending commands, complete the command. For data bytes,
470 * drop the ack on the floor.
482 kd_ack
= NOT_WAITING
;
485 printf("unexpected ACK from keyboard\n");
488 panic("bogus kd_ack\n");
496 * Resend a missed keyboard command or data byte.
502 if (kd_ack
== NOT_WAITING
)
503 printf("unexpected RESEND from keyboard\n");
505 kd_senddata(last_sent
);
512 * Change keyboard state according to which modifier key and
513 * whether it went down or up.
515 * input: the current state, the key, and the key's direction.
516 * The key can be any key, not just a modifier key.
518 * output: the new state
558 state
&= ~KS_SHIFTED
;
572 * Check for magic keystrokes for invoking the debugger or
575 * input: an unprocessed scancode
577 * output: TRUE if a magic key combination was recognized and
578 * processed. FALSE otherwise.
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.
592 static int magic_state
= KS_NORMAL
; /* like kd_state */
594 extern int rebootflag
;
596 if (scancode
== 0x46 && kbdmouseflag
) /* scroll lock */
598 kd_kbd_mouse
= !kd_kbd_mouse
;
599 kd_kbd_magic_button
= 0;
602 if (scancode
& K_UP
) {
606 magic_state
= do_modifier(magic_state
, scancode
, up
);
608 if ((magic_state
&(KS_CTLED
|KS_ALTED
)) == (KS_CTLED
|KS_ALTED
)) {
611 case K_dSC
: /* ctl-alt-d */
615 kdb_kintr(); /* invoke debugger */
617 /* Returned from debugger, so reset kbd state. */
619 magic_state
= KS_NORMAL
;
620 if (kb_mode
== KB_ASCII
)
621 kd_state
= KS_NORMAL
;
622 /* setting leds kills kbd */
626 #endif /* MACH_KDB */
627 case K_DELSC
: /* ctl-alt-del */
628 /* if rebootflag is on, reboot the system */
641 * Return the value for the 2nd index into key_map that
642 * corresponds to the given state.
647 int state
, /* bit vector, not a state index */
650 int state_idx
= NORM_STATE
;
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
;
663 return (CHARIDX(state_idx
));
669 * This code initializes the structures and sets up the port registers
670 * for the console driver.
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.
678 * input : None. Interrupts are assumed to be disabled
679 * output : Driver is initialized
686 unsigned char k_comm
; /* keyboard command byte */
687 unsigned char kd_stat
;
691 kd_initialized
= TRUE
;
693 /* get rid of any garbage in output buffer */
694 if (inb(K_STATUS
) & K_OBUF_FUL
)
697 cnsetleds(kd_state
= KS_NORMAL
);
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 */
706 /* set_kd_state(KS_NORMAL); does only HALF of set-leds sequence -
709 /* get rid of any garbage in output buffer */
716 * This routine shuts the bell off, by sending the appropriate code
717 * to the speaker port.
720 * output : bell is turned off
727 unsigned char status
;
729 status
= (inb(K_PORTB
) & ~(K_SPKRDATA
| K_ENABLETMR2
));
730 outb(K_PORTB
, status
);
737 * This routine turns the bell on.
740 * output : bell is turned on
747 unsigned char status
;
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 */
754 /* start speaker - why must we turn on K_SPKRDATA? */
755 status
= (inb(K_PORTB
)| K_ENABLETMR2
| K_SPKRDATA
);
756 outb(K_PORTB
, status
);
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
774 while (inb(K_STATUS
) & K_IBUF_FUL
);
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.
792 while (inb(K_STATUS
) & K_IBUF_FUL
);
800 * This function returns a data byte from the keyboard RDWR port,
801 * after waiting until the port is flagged as having something to
808 while ((inb(K_STATUS
) & K_OBUF_FUL
) == 0);
817 while (inb(K_STATUS
) & (K_IBUF_FUL
| K_OBUF_FUL
));
820 while ((inb(K_STATUS
) & K_OBUF_FUL
) == 0);
830 while (inb(K_STATUS
) & K_IBUF_FUL
);
833 while (inb(K_STATUS
) & K_IBUF_FUL
);
837 int kd_mouse_write_no_ack
= 0;
843 int ch
=0xd4; /* output byte to aux device (i.e. mouse) */
846 while (inb(K_STATUS
) & K_IBUF_FUL
);
849 while (inb(K_STATUS
) & K_IBUF_FUL
);
852 if (kd_mouse_write_no_ack
) goto done
;
854 while ((inb(K_STATUS
) & K_OBUF_FUL
) == 0);
855 if ((inb(K_STATUS
) & 0x20) == 0x20) {
856 switch (ret
= inb(K_RDWR
)) {
862 printf("kd_mouse_write: saw %x for %x\n",
866 printf("kd_mouse_write: sync error ??? on %x\n", val
);
880 while ((inb(K_STATUS
) & K_OBUF_FUL
) == 0);
882 * We may have seen a mouse event.
884 if ((inb(K_STATUS
) & 0x20) == 0x20) {
885 *buf
++ = (unsigned char)inb(K_RDWR
);
887 int junk
= inb(K_RDWR
);
888 printf("kd_mouse_read: sync error, received: 0x%x\n",
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
));
907 * Set kd_state and update the keyboard status LEDs.
915 kd_setleds1(state2leds(newstate
));
921 * Return a byte containing LED settings for the keyboard, given
929 unsigned char result
= 0;
931 if (state
& KS_NLKED
)
932 result
|= K_LED_NUMLK
;
933 if (state
& KS_CLKED
)
934 result
|= K_LED_CAPSLK
;
941 * Set the keyboard LEDs according to the given byte.
948 if (kd_ack
!= NOT_WAITING
) {
949 printf("kd_setleds1: unexpected state (%d)\n", kd_ack
);
955 kd_senddata(K_CMD_LEDS
);
961 kd_senddata(kd_nextled
);
968 * like kd_setleds[12], but not interrupt-based.
969 * Currently disabled because cngetc ignores caps lock and num
977 kd_senddata(K_CMD_LEDS
);
978 (void)kd_getdata(); /* XXX - assume is ACK */
980 (void)kd_getdata(); /* XXX - assume is ACK */
986 kd_sendcmd(0xFE); /* XXX - magic # */
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
1001 if (kd_kbd_mouse
== 2)
1002 printf("sc = %x\n", scancode
);
1012 if (kd_kbd_magic_button
&& (new_button
!= kd_kbd_magic_button
)) {
1016 if (kd_kbd_magic_button
== new_button
) {
1017 kd_kbd_magic_button
= 0;
1019 kd_kbd_magic_button
= new_button
;