|
|
1.1 root 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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.