|
|
1.1 root 1: /*
2: * Mach Operating System
3: * Copyright (c) 1991,1990,1989 Carnegie Mellon University
4: * All Rights Reserved.
5: *
6: * Permission to use, copy, modify and distribute this software and its
7: * documentation is hereby granted, provided that both the copyright
8: * notice and this permission notice appear in all copies of the
9: * software, derivative works or modified versions, and any portions
10: * thereof, and that both notices appear in supporting documentation.
11: *
12: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
13: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
14: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
15: *
16: * Carnegie Mellon requests users of this software to return to
17: *
18: * Software Distribution Coordinator or [email protected]
19: * School of Computer Science
20: * Carnegie Mellon University
21: * Pittsburgh PA 15213-3890
22: *
23: * any improvements or extensions that they make and grant Carnegie Mellon
24: * the rights to redistribute these changes.
25: */
26: /*
27: * Olivetti Mach Console driver v0.0
28: * Copyright Ing. C. Olivetti & C. S.p.A. 1988, 1989
29: * All rights reserved.
30: *
31: */
32: /*
33: Copyright 1988, 1989 by Olivetti Advanced Technology Center, Inc.,
34: Cupertino, California.
35:
36: All Rights Reserved
37:
38: Permission to use, copy, modify, and distribute this software and
39: its documentation for any purpose and without fee is hereby
40: granted, provided that the above copyright notice appears in all
41: copies and that both the copyright notice and this permission notice
42: appear in supporting documentation, and that the name of Olivetti
43: not be used in advertising or publicity pertaining to distribution
44: of the software without specific, written prior permission.
45:
46: OLIVETTI DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
47: INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
48: IN NO EVENT SHALL OLIVETTI BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
49: CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
50: LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
51: NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUR OF OR IN CONNECTION
52: WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
53: */
54:
55: /*
56: Copyright 1988, 1989 by Intel Corporation, Santa Clara, California.
57:
58: All Rights Reserved
59:
60: Permission to use, copy, modify, and distribute this software and
61: its documentation for any purpose and without fee is hereby
62: granted, provided that the above copyright notice appears in all
63: copies and that both the copyright notice and this permission notice
64: appear in supporting documentation, and that the name of Intel
65: not be used in advertising or publicity pertaining to distribution
66: of the software without specific, written prior permission.
67:
68: INTEL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
69: INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
70: IN NO EVENT SHALL INTEL BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
71: CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
72: LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
73: NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
74: WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
75: */
76:
77: /* $ Header: $ */
78:
79: #include <mach_kdb.h>
80:
81: #include <sys/types.h>
82: #include <kern/time_out.h>
83: #include <device/conf.h>
84: #include <device/tty.h>
85: #include <device/io_req.h>
86: #include <device/buf.h> /* for struct uio (!) */
87: #include <i386/io_port.h>
88: #include <vm/vm_kern.h>
89: #include "vm_param.h"
90: #include <i386/machspl.h>
91: #include <i386at/cram.h>
92: #include <i386at/kd.h>
93: #include <i386at/kdsoft.h>
94: #include <cons.h>
95:
96: #include <blit.h>
97: #if NBLIT > 0
98: #include <i386at/blitvar.h>
99: #else
100: #define blit_present() FALSE
101: #define blit_init() /* nothing */
102: #endif
103:
104: #include <evc.h>
105: #if NEVC > 0
106: int evc1init();
107: #else
108: #define evc1init() FALSE
109: #endif
110:
111: #define DEBUG 1 /* export feep() */
112:
113: #define DEFAULT -1 /* see kd_atoi */
114:
115: void kd_enqsc(); /* enqueues a scancode */
116:
117: void timeout();
118:
119: #if 0
120: #define BROKEN_KEYBOARD_RESET
121: #endif
122:
123: struct tty kd_tty;
124: extern int rebootflag;
125:
126: static void charput(), charmvup(), charmvdown(), charclear(), charsetcursor();
127: static void kd_noopreset();
128: boolean_t kdcheckmagic();
129:
130: int kdcnprobe(struct consdev *cp);
131: int kdcninit(struct consdev *cp);
132: int kdcngetc(dev_t dev, int wait);
133: int kdcnputc(dev_t dev, int c);
134:
135: /*
136: * These routines define the interface to the device-specific layer.
137: * See kdsoft.h for a more complete description of what each routine does.
138: */
139: void (*kd_dput)() = charput; /* put attributed char */
140: void (*kd_dmvup)() = charmvup; /* block move up */
141: void (*kd_dmvdown)() = charmvdown; /* block move down */
142: void (*kd_dclear)() = charclear; /* block clear */
143: void (*kd_dsetcursor)() = charsetcursor;
144: /* set cursor position on displayed page */
145: void (*kd_dreset)() = kd_noopreset; /* prepare for reboot */
146:
147: /* forward declarations */
148: unsigned char kd_getdata(), state2leds();
149:
150:
151: /*
152: * Globals used for both character-based controllers and bitmap-based
153: * controllers. Default is EGA.
154: */
155:
156: vm_offset_t kd_bitmap_start = (vm_offset_t)0xa0000; /* XXX - put in kd.h */
157: u_char *vid_start = (u_char *)EGA_START;
158: /* VM start of video RAM or frame buffer */
159: csrpos_t kd_curpos = 0; /* set indirectly by kd_setpos--see kdsoft.h */
160: short kd_lines = 25;
161: short kd_cols = 80;
162: char kd_attr = KA_NORMAL; /* current attribute */
163:
164: /*
165: * kd_state shows the state of the modifier keys (ctrl, caps lock,
166: * etc.) It should normally be changed by calling set_kd_state(), so
167: * that the keyboard status LEDs are updated correctly.
168: */
169: int kd_state = KS_NORMAL;
170: int kb_mode = KB_ASCII; /* event/ascii */
171:
172: /*
173: * State for the keyboard "mouse".
174: */
175: int kd_kbd_mouse = 0;
176: int kd_kbd_magic_scale = 6;
177: int kd_kbd_magic_button = 0;
178:
179: /*
180: * Some keyboard commands work by sending a command, waiting for an
181: * ack (handled by kdintr), then sending data, which generates a
182: * second ack. If we are in the middle of such a sequence, kd_ack
183: * shows what the ack is for.
184: *
185: * When a byte is sent to the keyboard, it is kept around in last_sent
186: * in case it needs to be resent.
187: *
188: * The rest of the variables here hold the data required to complete
189: * the sequence.
190: *
191: * XXX - the System V driver keeps a command queue, I guess in case we
192: * want to start a command while another is in progress. Is this
193: * something we should worry about?
194: */
195: enum why_ack {NOT_WAITING, SET_LEDS, DATA_ACK};
196: enum why_ack kd_ack = NOT_WAITING;
197:
198: u_char last_sent = 0;
199:
200: u_char kd_nextled = 0;
201:
202: /*
203: * We don't provide any mutex protection for this flag because we know
204: * that this module will have been initialized by the time multiple
205: * threads are running.
206: */
207: boolean_t kd_initialized = FALSE; /* driver initialized? */
208: boolean_t kd_extended = FALSE;
209:
210: /* Array for processing escape sequences. */
211: #define K_MAXESC 16
212: u_char esc_seq[K_MAXESC];
213: u_char *esc_spt = (u_char *)0;
214:
215: /*
216: * This array maps scancodes to Ascii characters (or character
217: * sequences).
218: * Each row corresponds to one key. There are NUMOUTPUT bytes per key
219: * state. The states are ordered: Normal, SHIFT, CTRL, ALT,
220: * SHIFT/ALT.
221: */
222: unsigned char key_map[NUMKEYS][WIDTH_KMAP] = {
223: {NC,NC,NC,NC,NC,NC,NC,NC,NC,NC,NC,NC,NC,NC,NC},
224: {K_ESC,NC,NC, K_ESC,NC,NC, K_ESC,NC,NC, K_ESC,NC,NC, K_ESC,NC,NC},
225: {K_ONE,NC,NC, K_BANG,NC,NC, K_ONE,NC,NC, 0x1b,0x4e,0x31, 0x1b,0x4e,0x21},
226: {K_TWO,NC,NC, K_ATSN,NC,NC, K_NUL,NC,NC, 0x1b,0x4e,0x32, 0x1b,0x4e,0x40},
227: {K_THREE,NC,NC, K_POUND,NC,NC, K_THREE,NC,NC, 0x1b,0x4e,0x33, 0x1b,0x4e,0x23},
228: {K_FOUR,NC,NC, K_DOLLAR,NC,NC, K_FOUR,NC,NC, 0x1b,0x4e,0x34, 0x1b,0x4e,0x24},
229: {K_FIVE,NC,NC, K_PERC,NC,NC, K_FIVE,NC,NC, 0x1b,0x4e,0x35, 0x1b,0x4e,0x25},
230: {K_SIX,NC,NC, K_CARET,NC,NC, K_RS,NC,NC, 0x1b,0x4e,0x36, 0x1b,0x4e,0x5e},
231: {K_SEVEN,NC,NC, K_AMPER,NC,NC, K_SEVEN,NC,NC, 0x1b,0x4e,0x37, 0x1b,0x4e,0x26},
232: {K_EIGHT,NC,NC, K_ASTER,NC,NC, K_EIGHT,NC,NC, 0x1b,0x4e,0x38, 0x1b,0x4e,0x2a},
233: {K_NINE,NC,NC, K_LPAREN,NC,NC, K_NINE,NC,NC, 0x1b,0x4e,0x39,0x1b,0x4e,0x28},
234: {K_ZERO,NC,NC, K_RPAREN,NC,NC, K_ZERO,NC,NC, 0x1b,0x4e,0x30,0x1b,0x4e,0x29},
235: {K_MINUS,NC,NC, K_UNDSC,NC,NC, K_US,NC,NC, 0x1b,0x4e,0x2d, 0x1b,0x4e,0x5f},
236: {K_EQL,NC,NC, K_PLUS,NC,NC, K_EQL,NC,NC, 0x1b,0x4e,0x3d, 0x1b,0x4e,0x2b},
237: {K_BS,NC,NC, K_BS,NC,NC, K_BS,NC,NC, K_BS,NC,NC, K_BS,NC,NC},
238: {K_HT,NC,NC, K_GS,NC,NC, K_HT,NC,NC, K_HT,NC,NC, K_GS,NC,NC},
239: {K_q,NC,NC, K_Q,NC,NC, K_DC1,NC,NC, 0x1b,0x4e,0x71, 0x1b,0x4e,0x51},
240: {K_w,NC,NC, K_W,NC,NC, K_ETB,NC,NC, 0x1b,0x4e,0x77, 0x1b,0x4e,0x57},
241: {K_e,NC,NC, K_E,NC,NC, K_ENQ,NC,NC, 0x1b,0x4e,0x65, 0x1b,0x4e,0x45},
242: {K_r,NC,NC, K_R,NC,NC, K_DC2,NC,NC, 0x1b,0x4e,0x72, 0x1b,0x4e,0x52},
243: {K_t,NC,NC, K_T,NC,NC, K_DC4,NC,NC, 0x1b,0x4e,0x74, 0x1b,0x4e,0x54},
244: {K_y,NC,NC, K_Y,NC,NC, K_EM,NC,NC, 0x1b,0x4e,0x79, 0x1b,0x4e,0x59},
245: {K_u,NC,NC, K_U,NC,NC, K_NAK,NC,NC, 0x1b,0x4e,0x75, 0x1b,0x4e,0x55},
246: {K_i,NC,NC, K_I,NC,NC, K_HT,NC,NC, 0x1b,0x4e,0x69, 0x1b,0x4e,0x49},
247: {K_o,NC,NC, K_O,NC,NC, K_SI,NC,NC, 0x1b,0x4e,0x6f, 0x1b,0x4e,0x4f},
248: {K_p,NC,NC, K_P,NC,NC, K_DLE,NC,NC, 0x1b,0x4e,0x70, 0x1b,0x4e,0x50},
249: {K_LBRKT,NC,NC, K_LBRACE,NC,NC, K_ESC,NC,NC, 0x1b,0x4e,0x5b, 0x1b,0x4e,0x7b},
250: {K_RBRKT,NC,NC, K_RBRACE,NC,NC, K_GS,NC,NC, 0x1b,0x4e,0x5d, 0x1b,0x4e,0x7d},
251: {K_CR,NC,NC, K_CR,NC,NC, K_CR,NC,NC, K_CR,NC,NC, K_CR,NC,NC},
252: {K_SCAN,K_CTLSC,NC, K_SCAN,K_CTLSC,NC, K_SCAN,K_CTLSC,NC, K_SCAN,K_CTLSC,NC,
253: K_SCAN,K_CTLSC,NC},
254: {K_a,NC,NC, K_A,NC,NC, K_SOH,NC,NC, 0x1b,0x4e,0x61, 0x1b,0x4e,0x41},
255: {K_s,NC,NC, K_S,NC,NC, K_DC3,NC,NC, 0x1b,0x4e,0x73, 0x1b,0x4e,0x53},
256: {K_d,NC,NC, K_D,NC,NC, K_EOT,NC,NC, 0x1b,0x4e,0x65, 0x1b,0x4e,0x45},
257: {K_f,NC,NC, K_F,NC,NC, K_ACK,NC,NC, 0x1b,0x4e,0x66, 0x1b,0x4e,0x46},
258: {K_g,NC,NC, K_G,NC,NC, K_BEL,NC,NC, 0x1b,0x4e,0x67, 0x1b,0x4e,0x47},
259: {K_h,NC,NC, K_H,NC,NC, K_BS,NC,NC, 0x1b,0x4e,0x68, 0x1b,0x4e,0x48},
260: {K_j,NC,NC, K_J,NC,NC, K_LF,NC,NC, 0x1b,0x4e,0x6a, 0x1b,0x4e,0x4a},
261: {K_k,NC,NC, K_K,NC,NC, K_VT,NC,NC, 0x1b,0x4e,0x6b, 0x1b,0x4e,0x4b},
262: {K_l,NC,NC, K_L,NC,NC, K_FF,NC,NC, 0x1b,0x4e,0x6c, 0x1b,0x4e,0x4c},
263: {K_SEMI,NC,NC, K_COLON,NC,NC, K_SEMI,NC,NC, 0x1b,0x4e,0x3b, 0x1b,0x4e,0x3a},
264: {K_SQUOTE,NC,NC,K_DQUOTE,NC,NC,K_SQUOTE,NC,NC,0x1b,0x4e,0x27,0x1b,0x4e,0x22},
265: {K_GRAV,NC,NC, K_TILDE,NC,NC, K_RS,NC,NC, 0x1b,0x4e,0x60, 0x1b,0x4e,0x7e},
266: {K_SCAN,K_LSHSC,NC, K_SCAN,K_LSHSC,NC, K_SCAN,K_LSHSC,NC, K_SCAN,K_LSHSC,NC,
267: K_SCAN,K_LSHSC,NC},
268: {K_BSLSH,NC,NC, K_PIPE,NC,NC, K_FS,NC,NC, 0x1b,0x4e,0x5c, 0x1b,0x4e,0x7c},
269: {K_z,NC,NC, K_Z,NC,NC, K_SUB,NC,NC, 0x1b,0x4e,0x7a, 0x1b,0x4e,0x5a},
270: {K_x,NC,NC, K_X,NC,NC, K_CAN,NC,NC, 0x1b,0x4e,0x78, 0x1b,0x4e,0x58},
271: {K_c,NC,NC, K_C,NC,NC, K_ETX,NC,NC, 0x1b,0x4e,0x63, 0x1b,0x4e,0x43},
272: {K_v,NC,NC, K_V,NC,NC, K_SYN,NC,NC, 0x1b,0x4e,0x76, 0x1b,0x4e,0x56},
273: {K_b,NC,NC, K_B,NC,NC, K_STX,NC,NC, 0x1b,0x4e,0x62, 0x1b,0x4e,0x42},
274: {K_n,NC,NC, K_N,NC,NC, K_SO,NC,NC, 0x1b,0x4e,0x6e, 0x1b,0x4e,0x4e},
275: {K_m,NC,NC, K_M,NC,NC, K_CR,NC,NC, 0x1b,0x4e,0x6d, 0x1b,0x4e,0x4d},
276: {K_COMMA,NC,NC, K_LTHN,NC,NC, K_COMMA,NC,NC, 0x1b,0x4e,0x2c, 0x1b,0x4e,0x3c},
277: {K_PERIOD,NC,NC, K_GTHN,NC,NC, K_PERIOD,NC,NC,0x1b,0x4e,0x2e,0x1b,0x4e,0x3e},
278: {K_SLASH,NC,NC, K_QUES,NC,NC, K_SLASH,NC,NC, 0x1b,0x4e,0x2f, 0x1b,0x4e,0x3f},
279: {K_SCAN,K_RSHSC,NC, K_SCAN,K_RSHSC,NC, K_SCAN,K_RSHSC,NC, K_SCAN,K_RSHSC,NC,
280: K_SCAN,K_RSHSC,NC},
281: {K_ASTER,NC,NC, K_ASTER,NC,NC, K_ASTER,NC,NC, 0x1b,0x4e,0x2a,0x1b,0x4e,0x2a},
282: {K_SCAN,K_ALTSC,NC, K_SCAN,K_ALTSC,NC, K_SCAN,K_ALTSC,NC, K_SCAN,K_ALTSC,NC,
283: K_SCAN,K_ALTSC,NC},
284: {K_SPACE,NC,NC, K_SPACE,NC,NC, K_NUL,NC,NC, K_SPACE,NC,NC, K_SPACE,NC,NC},
285: {K_SCAN,K_CLCKSC,NC, K_SCAN,K_CLCKSC,NC, K_SCAN,K_CLCKSC,NC,
286: K_SCAN,K_CLCKSC,NC, K_SCAN,K_CLCKSC,NC},
287: {K_F1, K_F1S, K_F1, K_F1, K_F1S},
288: {K_F2, K_F2S, K_F2, K_F2, K_F2S},
289: {K_F3, K_F3S, K_F3, K_F3, K_F3S},
290: {K_F4, K_F4S, K_F4, K_F4, K_F4S},
291: {K_F5, K_F5S, K_F5, K_F5, K_F5S},
292: {K_F6, K_F6S, K_F6, K_F6, K_F6S},
293: {K_F7, K_F7S, K_F7, K_F7, K_F7S},
294: {K_F8, K_F8S, K_F8, K_F8, K_F8S},
295: {K_F9, K_F9S, K_F9, K_F9, K_F9S},
296: {K_F10, K_F10S, K_F10, K_F10, K_F10S},
297: {K_SCAN,K_NLCKSC,NC, K_SCAN,K_NLCKSC,NC, K_SCAN,K_NLCKSC,NC,
298: K_SCAN,K_NLCKSC,NC, K_SCAN,K_NLCKSC,NC},
299: {K_SCRL, K_NUL,NC,NC, K_SCRL, K_SCRL, K_NUL,NC,NC},
300: {K_HOME, K_SEVEN,NC,NC, K_HOME, K_HOME, 0x1b,0x4e,0x37},
301: {K_UA, K_EIGHT,NC,NC, K_UA, K_UA, 0x1b,0x4e,0x38},
302: {K_PUP, K_NINE,NC,NC, K_PUP, K_PUP, 0x1b,0x4e,0x39},
303: {0x1b,0x5b,0x53, K_MINUS,NC,NC, 0x1b,0x5b,0x53,0x1b,0x5b,0x53,0x1b,0x4e,0x2d},
304: {K_LA, K_FOUR,NC,NC, K_LA, K_LA, 0x1b,0x4e,0x34},
305: {0x1b,0x5b,0x47,K_FIVE,NC,NC,0x1b,0x5b,0x47, 0x1b,0x5b,0x47, 0x1b,0x4e,0x35},
306: {K_RA, K_SIX,NC,NC, K_RA, K_RA, 0x1b,0x4e,0x36},
307: {0x1b,0x5b,0x54,K_PLUS,NC,NC, 0x1b,0x5b,0x54, 0x1b,0x5b,0x54, 0x1b,0x4e,0x2b},
308: {K_END, K_ONE,NC,NC, K_END, K_END, 0x1b,0x4e,0x31},
309: {K_DA, K_TWO,NC,NC, K_DA, K_DA, 0x1b,0x4e,0x32},
310: {K_PDN, K_THREE,NC,NC, K_PDN, K_PDN, 0x1b,0x4e,0x33},
311: {K_INS, K_ZERO,NC,NC, K_INS, K_INS, 0x1b,0x4e,0x30},
312: {K_DEL,NC,NC, K_PERIOD,NC,NC, K_DEL,NC,NC, K_DEL,NC,NC, 0x1b,0x4e,0x2e},
313: {NC,NC,NC,NC,NC,NC,NC,NC,NC,NC,NC,NC,NC,NC,NC},
314: {NC,NC,NC,NC,NC,NC,NC,NC,NC,NC,NC,NC,NC,NC,NC},
315: {NC,NC,NC,NC,NC,NC,NC,NC,NC,NC,NC,NC,NC,NC,NC},
316: {K_F11, K_F11S, K_F11, K_F11, K_F11S},
317: {K_F12, K_F12S, K_F12, K_F12, K_F12S}
318: };
319:
320:
321: /*
322: * Globals used only for character-based controllers.
323: */
324:
325: short kd_index_reg = EGA_IDX_REG;
326: short kd_io_reg = EGA_IO_REG;
327:
328: /*
329: * IO port sets for different controllers.
330: */
331: io_reg_t vga_port_list[] = {
332: 0x3b4, 0x3b5, 0x3b8, 0x3b9, 0x3ba, /* MDA/EGA */
333: 0x3d4, 0x3d5, 0x3d8, 0x3d9, 0x3da, /* CGA/EGA */
334: 0x3c0, 0x3c1, 0x3c2, 0x3c3, 0x3c4, 0x3c5, 0x3c6, 0x3c7,
335: 0x3c8, 0x3c9, 0x3ca, 0x3cb, 0x3cc, 0x3cd, 0x3ce, 0x3cf,
336: IO_REG_NULL
337: };
338:
339: mach_device_t kd_io_device = 0;
340:
341: kd_io_map_open(device)
342: mach_device_t device;
343: {
344: kd_io_device = device;
345: io_port_create(device, vga_port_list);
346: }
347:
348: kd_io_map_close()
349: {
350: io_port_destroy(kd_io_device);
351: kd_io_device = 0;
352: }
353:
354: /*
355: * Globals used only for bitmap-based controllers. See kdsoft.h for
356: * an explanation of what some of these variables are used for.
357: */
358:
359: u_char *font_start = 0; /* starting addr of font */
360:
361: short fb_width = 0; /* bits in frame buffer scan line */
362: short fb_height = 0; /* scan lines in frame buffer*/
363: short char_width = 0; /* bit width of 1 char */
364: short char_height = 0; /* bit height of 1 char */
365: short chars_in_font = 0;
366: short cursor_height = 0; /* bit height of cursor */
367:
368: /* These initial values are simply guesses. */
369: u_char char_black = 0;
370: u_char char_white = 0xff;
371:
372: short xstart = 0;
373: short ystart = 0;
374:
375: short char_byte_width = 0; /* char_width/NBBY */
376: short fb_byte_width = 0; /* fb_width/NBBY */
377: short font_byte_width = 0; /* num bytes in 1 scan line of font */
378:
379: /*
380: * Switch for poll vs. interrupt.
381: */
382: int kd_pollc = 0;
383:
384: #ifdef DEBUG
385: /*
386: * feep:
387: *
388: * Ring the bell for a short time.
389: * Warning: uses outb(). You may prefer to use kd_debug_put.
390: */
391: feep()
392: {
393: int i;
394:
395: kd_bellon();
396: for (i = 0; i < 50000; ++i)
397: ;
398: kd_belloff();
399: }
400:
401: pause()
402: {
403: int i;
404:
405: for (i = 0; i < 50000; ++i)
406: ;
407: }
408:
409: /*
410: * Put a debugging character on the screen.
411: * LOC=0 means put it in the bottom right corner, LOC=1 means put it
412: * one column to the left, etc.
413: */
414: kd_debug_put(loc, c)
415: int loc;
416: char c;
417: {
418: csrpos_t pos = ONE_PAGE - (loc+1) * ONE_SPACE;
419:
420: (*kd_dput)(pos, c, KA_NORMAL);
421: }
422: #endif /* DEBUG */
423:
424:
425: extern int mouse_in_use;
426: int old_kb_mode;
427:
428: cnpollc(on)
429: boolean_t on;
430: {
431: if (mouse_in_use) {
432: if (on) {
433: /* switch into X */
434: old_kb_mode = kb_mode;
435: kb_mode = KB_ASCII;
436: X_kdb_enter();
437:
438: kd_pollc++;
439: } else {
440: --kd_pollc;
441:
442: /* switch out of X */
443: X_kdb_exit();
444: kb_mode = old_kb_mode;
445: }
446: } else {
447: if (on) {
448: kd_pollc++;
449: } else {
450: --kd_pollc;
451: }
452: }
453: }
454:
455:
456:
457: /*
458: * kdopen:
459: *
460: * This opens the console driver and sets up the tty and other
461: * rudimentary stuff including calling the line discipline for
462: * setting up the device independent stuff for a tty driver.
463: *
464: * input: device number 'dev', and flag
465: *
466: * output: device is opened and setup
467: *
468: */
469: kdopen(dev, flag, ior)
470: dev_t dev;
471: int flag;
472: io_req_t ior;
473: {
474: struct tty *tp;
475: int kdstart();
476: spl_t o_pri;
477: int kdstop();
478:
479: tp = &kd_tty;
480: o_pri = spltty();
481: simple_lock(&tp->t_lock);
482: if (!(tp->t_state & (TS_ISOPEN|TS_WOPEN))) {
483: /* XXX ttychars allocates memory */
484: simple_unlock(&tp->t_lock);
485: ttychars(tp);
486: simple_lock(&tp->t_lock);
487: /*
488: * Special support for boot-time rc scripts, which don't
489: * stty the console.
490: */
491: tp->t_oproc = kdstart;
492: tp->t_stop = kdstop;
493: tp->t_ospeed = tp->t_ispeed = B9600;
494: tp->t_flags = ODDP|EVENP|ECHO|CRMOD|XTABS;
495: kdinit();
496:
497: /* XXX kd_io_map_open allocates memory */
498: simple_unlock(&tp->t_lock);
499: kd_io_map_open(ior->io_device);
500: simple_lock(&tp->t_lock);
501: }
502: tp->t_state |= TS_CARR_ON;
503: simple_unlock(&tp->t_lock);
504: splx(o_pri);
505: return (char_open(dev, tp, flag, ior));
506: }
507:
508:
509: /*
510: * kdclose:
511: *
512: * This function merely executes the device independent code for
513: * closing the line discipline.
514: *
515: * input: device number 'dev', and flag
516: *
517: * output: device is closed
518: *
519: */
520: /*ARGSUSED*/
521: kdclose(dev, flag)
522: int dev;
523: int flag;
524: {
525: struct tty *tp;
526:
527: tp = &kd_tty;
528: {
529: spl_t s = spltty();
530: simple_lock(&tp->t_lock);
531: ttyclose(tp);
532: simple_unlock(&tp->t_lock);
533: splx(s);
534: }
535:
536: kd_io_map_close();
537:
538: return;
539:
540: }
541:
542:
543: /*
544: * kdread:
545: *
546: * This function executes the device independent code to read from
547: * the tty.
548: *
549: * input: device number 'dev'
550: *
551: * output: characters are read from tty clists
552: *
553: */
554: /*ARGSUSED*/
555: kdread(dev, uio)
556: int dev;
557: struct uio *uio;
558: {
559: struct tty *tp;
560:
561: tp = &kd_tty;
562: tp->t_state |= TS_CARR_ON;
563: return((*linesw[kd_tty.t_line].l_read)(tp, uio));
564: }
565:
566:
567: /*
568: * kdwrite:
569: *
570: * This function does the device independent write action for this
571: * console (tty) driver.
572: *
573: * input: device number 'dev'
574: *
575: * output: characters are written to tty clists
576: *
577: */
578: /*ARGSUSED*/
579: kdwrite(dev, uio)
580: int dev;
581: struct uio *uio;
582: {
583: return((*linesw[kd_tty.t_line].l_write)(&kd_tty, uio));
584: }
585:
586: /*
587: * Mmap.
588: */
589:
590: /*ARGSUSED*/
591: int
592: kdmmap(dev, off, prot)
593: dev_t dev;
594: off_t off;
595: int prot;
596: {
597: if ((u_int) off >= (128*1024))
598: return(-1);
599:
600: /* Get page frame number for the page to be mapped. */
601: return(i386_btop(kd_bitmap_start+off));
602: }
603:
604: kdportdeath(dev, port)
605: dev_t dev;
606: mach_port_t port;
607: {
608: return (tty_portdeath(&kd_tty, port));
609: }
610:
611: /*ARGSUSED*/
612: io_return_t kdgetstat(dev, flavor, data, count)
613: dev_t dev;
614: int flavor;
615: int * data; /* pointer to OUT array */
616: unsigned int *count; /* OUT */
617: {
618: io_return_t result;
619:
620: switch (flavor) {
621: case KDGSTATE:
622: if (*count < 1)
623: return (D_INVALID_OPERATION);
624: *data = kd_state;
625: *count = 1;
626: result = D_SUCCESS;
627: break;
628:
629: case KDGKBENT:
630: result = kdgetkbent((struct kbentry *)data);
631: *count = sizeof(struct kbentry)/sizeof(int);
632: break;
633:
634: default:
635: result = tty_get_status(&kd_tty, flavor, data, count);
636: break;
637: }
638: return (result);
639: }
640:
641: /*ARGSUSED*/
642: io_return_t kdsetstat(dev, flavor, data, count)
643: dev_t dev;
644: int flavor;
645: int * data;
646: unsigned int count;
647: {
648: io_return_t result;
649:
650: switch (flavor) {
651: case KDSKBENT:
652: if (count < sizeof(struct kbentry)/sizeof(int)) {
653: return (D_INVALID_OPERATION);
654: }
655: result = kdsetkbent((struct kbentry *)data, 0);
656: break;
657:
658: case KDSETBELL:
659: if (count < 1)
660: return (D_INVALID_OPERATION);
661: result = kdsetbell(*data, 0);
662: break;
663:
664: default:
665: result = tty_set_status(&kd_tty, flavor, data, count);
666: }
667: return (result);
668: }
669:
670:
671:
672: /*
673: * kdsetbell:
674: *
675: * Turn the bell on or off. Returns error code, if given bogus
676: * on/off value.
677: */
678: kdsetbell(val, flags)
679: int val; /* on or off */
680: int flags; /* flags set for console */
681: {
682: int err = 0;
683:
684:
685: if (val == KD_BELLON)
686: kd_bellon();
687: else if (val == KD_BELLOFF)
688: kd_belloff();
689: else
690: err = D_INVALID_OPERATION;
691:
692: return(err);
693: }
694:
695:
696: /*
697: * kdgetkbent:
698: *
699: * Get entry from key mapping table. Returns error code, if any.
700: */
701: kdgetkbent(kbent)
702: struct kbentry * kbent;
703: {
704: u_char *cp;
705: spl_t o_pri = SPLKD(); /* probably superfluous */
706:
707: cp = &key_map[kbent->kb_index][CHARIDX(kbent->kb_state)];
708: kbent->kb_value[0] = *cp++;
709: kbent->kb_value[1] = *cp++;
710: kbent->kb_value[2] = *cp;
711: (void)splx(o_pri);
712: return(0);
713: }
714:
715:
716: /*
717: * kdsetkbent:
718: *
719: * Set entry in key mapping table. Return error code, if any.
720: */
721: int
722: kdsetkbent(kbent, flags)
723: struct kbentry * kbent;
724: int flags; /* flags set for console */
725: {
726: u_char *cp;
727: spl_t o_pri;
728:
729: o_pri = SPLKD();
730: cp = &key_map[kbent->kb_index][CHARIDX(kbent->kb_state)];
731: *cp++ = kbent->kb_value[0];
732: *cp++ = kbent->kb_value[1];
733: *cp = kbent->kb_value[2];
734: (void)splx(o_pri);
735: return(0);
736: }
737:
738: /*
739: * kdintr:
740: *
741: * This function is the interrupt code for the driver. Since this is
742: * a special tty (console), interrupts are only for input, so we read in
743: * the character. If in ascii mode, we then do the mapping translation
744: * from the keyboard switch table and place the characters on the tty's
745: * input switch table. If in event mode, we create and queue a kd_event.
746: *
747: * input: interrupt vector 'vec'
748: *
749: * output: character or sequence is placed on appropriate queue
750: *
751: */
752: /*ARGSUSED*/
753: kdintr(vec, regs)
754: int vec;
755: int regs;
756: {
757: struct tty *tp;
758: unsigned char c;
759: unsigned char scancode;
760: int o_pri;
761: int char_idx;
762: boolean_t up = FALSE; /* key-up event */
763: extern int mouse_in_use;
764: if (kd_pollc)
765: return; /* kdb polling kbd */
766:
767: tp = &kd_tty;
768: #ifdef old
769: while ((inb(K_STATUS) & K_OBUF_FUL) == 0); /* this should never loop */
770: #else old
771: {
772: /*
773: * Allow for keyboards that raise interrupt before
774: * the character gets to the buffer. But don't wait
775: * forever if grabbing the character by polling leaves
776: * the interrupt on but buffer empty.
777: */
778: /*
779: * Micronics VLB motherboard with 486DX2 can report keyboard
780: * interrupt before K_STATUS register indicates that the
781: * output buffer is full. Moreover, the bus won't settle w
782: * while we poll K_STATUS at speed. Temporary fix is to break
783: * out after safety runs out and pick up keyboard event. This
784: * should be fixed eventually by putting a 1us timout between
785: * inb's to K_STATUS and fix the pic initialization order to
786: * avoid bootup keyboard wedging (ie make kd a real device)
787: */
788: int safety = 1000;
789: while ((inb(K_STATUS) & K_OBUF_FUL) == 0)
790: if (!safety--) break; /* XXX */
791: }
792: #endif old
793: /*
794: * We may have seen a mouse event.
795: */
796: if ((inb(K_STATUS) & 0x20) == 0x20) {
797: if (mouse_in_use) {
798: mouse_handle_byte((u_char)inb(K_RDWR));
799: return;
800: } else {
801: printf("M%xI", inb(K_RDWR));
802: return;
803: }
804: }
805:
806: scancode = inb(K_RDWR);
807: if (scancode == K_EXTEND) {
808: if (kb_mode != KB_EVENT)
809: kd_extended = TRUE;
810: goto done;
811: } else if (scancode == K_RESEND) {
812: kd_resend();
813: goto done;
814: } else if (scancode == K_ACKSC) {
815: kd_handle_ack();
816: goto done;
817: } else if (kd_kbd_mouse && kd_kbd_magic(scancode)) {
818: goto done;
819: } else if (kdcheckmagic(scancode, ®s)) {
820: goto done;
821: } else if (kb_mode == KB_EVENT) {
822: kd_enqsc(scancode);
823: goto done;
824: } /* else... */
825:
826: if (scancode & K_UP) {
827: up = TRUE;
828: scancode &= ~K_UP;
829: }
830: if (scancode < NUMKEYS) {
831: /* Lookup in map, then process. */
832: char_idx = kdstate2idx(kd_state, kd_extended);
833: c = key_map[scancode][char_idx];
834: if (c == K_SCAN) {
835: c = key_map[scancode][++char_idx];
836: set_kd_state(do_modifier(kd_state, c, up));
837: } else if (!up) {
838: /* regular key-down */
839: int max; /* max index for char sequence */
840:
841: max = char_idx + NUMOUTPUT;
842: char_idx++;
843: if (!kd_extended) {
844: if (kd_state&KS_CLKED) {
845: if (kd_isupper(c)) {
846: c += ('a' - 'A');
847: max = char_idx;
848: }
849: else if (kd_islower(c)) {
850: c -= ('a' - 'A');
851: max = char_idx;
852: }
853: }
854: /*
855: * Notice that even if the keypad is remapped,
856: * NumLock only effects the keys that are
857: * physically part of the keypad. Is this
858: * The Right Thing?
859: */
860: if ((kd_state&KS_NLKED) &&
861: (((K_HOMESC) <= scancode) &&
862: (scancode <= (K_DELSC)))) {
863: char_idx = CHARIDX(SHIFT_STATE);
864: c = key_map[scancode][char_idx];
865: max = char_idx + NUMOUTPUT;
866: char_idx++;
867: }
868: }
869:
870: /*
871: * here's where we actually put the char (or
872: * char sequence, for function keys) onto the
873: * input queue.
874: */
875: for ( ; (c != K_DONE) && (char_idx <= max);
876: c = key_map[scancode][char_idx++]) {
877: (*linesw[tp->t_line].l_rint)(c, tp);
878: }
879: kd_extended = FALSE;
880: }
881: }
882:
883: done:
884: return;
885: }
886:
887: /*
888: * kd_handle_ack:
889: *
890: * For pending commands, complete the command. For data bytes,
891: * drop the ack on the floor.
892: */
893: kd_handle_ack()
894: {
895: switch (kd_ack) {
896: case SET_LEDS:
897: kd_setleds2();
898: kd_ack = DATA_ACK;
899: break;
900: case DATA_ACK:
901: kd_ack = NOT_WAITING;
902: break;
903: case NOT_WAITING:
904: printf("unexpected ACK from keyboard\n");
905: break;
906: default:
907: panic("bogus kd_ack\n");
908: break;
909: }
910: }
911:
912: /*
913: * kd_resend:
914: *
915: * Resend a missed keyboard command or data byte.
916: */
917: kd_resend()
918: {
919: if (kd_ack == NOT_WAITING)
920: printf("unexpected RESEND from keyboard\n");
921: else
922: kd_senddata(last_sent);
923: }
924:
925:
926: /*
927: * do_modifier:
928: *
929: * Change keyboard state according to which modifier key and
930: * whether it went down or up.
931: *
932: * input: the current state, the key, and the key's direction.
933: * The key can be any key, not just a modifier key.
934: *
935: * output: the new state
936: */
937: do_modifier(state, c, up)
938: int state;
939: Scancode c;
940: boolean_t up;
941: {
942: switch (c) {
943: case (K_ALTSC):
944: if (up)
945: state &= ~KS_ALTED;
946: else
947: state |= KS_ALTED;
948: kd_extended = FALSE;
949: break;
950: #ifndef ORC
951: case (K_CLCKSC):
952: #endif ORC
953: case (K_CTLSC):
954: if (up)
955: state &= ~KS_CTLED;
956: else
957: state |= KS_CTLED;
958: kd_extended = FALSE;
959: break;
960: #ifdef ORC
961: case (K_CLCKSC):
962: if (!up)
963: state ^= KS_CLKED;
964: break;
965: #endif ORC
966: case (K_NLCKSC):
967: if (!up)
968: state ^= KS_NLKED;
969: break;
970: case (K_LSHSC):
971: case (K_RSHSC):
972: if (up)
973: state &= ~KS_SHIFTED;
974: else
975: state |= KS_SHIFTED;
976: kd_extended = FALSE;
977: break;
978: }
979:
980: return(state);
981: }
982:
983:
984: /*
985: * kdcheckmagic:
986: *
987: * Check for magic keystrokes for invoking the debugger or
988: * rebooting or ...
989: *
990: * input: an unprocessed scancode
991: *
992: * output: TRUE if a magic key combination was recognized and
993: * processed. FALSE otherwise.
994: *
995: * side effects:
996: * various actions possible, depending on which keys are
997: * pressed. If the debugger is called, steps are taken
998: * to ensure that the system doesn't think the magic keys
999: * are still held down.
1000: */
1001: boolean_t
1002: kdcheckmagic(scancode, regs)
1003: Scancode scancode;
1004: int *regs;
1005: {
1006: static int magic_state = KS_NORMAL; /* like kd_state */
1007: boolean_t up = FALSE;
1008: extern int rebootflag;
1009:
1010: if (scancode == 0x46) /* scroll lock */
1011: /* if (scancode == 0x52) ** insert key */
1012: {
1013: kd_kbd_mouse = !kd_kbd_mouse;
1014: kd_kbd_magic_button = 0;
1015: return(TRUE);
1016: }
1017: if (scancode & K_UP) {
1018: up = TRUE;
1019: scancode &= ~K_UP;
1020: }
1021: magic_state = do_modifier(magic_state, scancode, up);
1022:
1023: if ((magic_state&(KS_CTLED|KS_ALTED)) == (KS_CTLED|KS_ALTED)) {
1024: switch (scancode) {
1025: #if MACH_KDB
1026: case K_dSC: /* ctl-alt-d */
1027: kdb_kintr(); /* invoke debugger */
1028: /* Returned from debugger, so reset kbd state. */
1029: (void)SPLKD();
1030: magic_state = KS_NORMAL;
1031: if (kb_mode == KB_ASCII)
1032: kd_state = KS_NORMAL;
1033: /* setting leds kills kbd */
1034: else {
1035: kd_enqsc(K_ALTSC | K_UP);
1036: kd_enqsc(K_CTLSC | K_UP);
1037: kd_enqsc(K_dSC | K_UP);
1038: }
1039: return(TRUE);
1040: break;
1041: #endif MACH_KDB
1042: case K_DELSC: /* ctl-alt-del */
1043: /* if rebootflag is on, reboot the system */
1044: if (rebootflag)
1045: kdreboot();
1046: break;
1047: }
1048: }
1049: return(FALSE);
1050: }
1051:
1052:
1053: /*
1054: * kdstate2idx:
1055: *
1056: * Return the value for the 2nd index into key_map that
1057: * corresponds to the given state.
1058: */
1059: kdstate2idx(state, extended)
1060: int state; /* bit vector, not a state index */
1061: boolean_t extended;
1062: {
1063: int state_idx = NORM_STATE;
1064:
1065: if ((!extended) && state != KS_NORMAL) {
1066: if ((state&(KS_SHIFTED|KS_ALTED)) == (KS_SHIFTED|KS_ALTED))
1067: state_idx = SHIFT_ALT;
1068: else if (state&KS_SHIFTED)
1069: state_idx = SHIFT_STATE;
1070: else if (state&KS_ALTED)
1071: state_idx = ALT_STATE;
1072: else if (state&KS_CTLED)
1073: state_idx = CTRL_STATE;
1074: }
1075:
1076: return (CHARIDX(state_idx));
1077: }
1078:
1079: /*
1080: * kdstart:
1081: *
1082: * This function does the general processing of characters and other
1083: * operations for the device driver. The device independent portion of
1084: * the tty driver calls this routine (it's setup in kdinit) with a
1085: * given command. That command is then processed, and control is passed
1086: * back to the kernel.
1087: *
1088: * input: tty pointer 'tp', and command to execute 'cmd'
1089: *
1090: * output: command is executed
1091: *
1092: * Entered and left at spltty. Drops priority to spl0 to display character.
1093: * ASSUMES that it is never called from interrupt-driven code.
1094: */
1095: kdstart(tp)
1096: struct tty *tp;
1097: {
1098: spl_t o_pri;
1099: int ch;
1100: unsigned char c;
1101:
1102: if (tp->t_state & TS_TTSTOP)
1103: return;
1104: for ( ; ; ) {
1105: tp->t_state &= ~TS_BUSY;
1106: if (tp->t_state & TS_TTSTOP)
1107: break;
1108: if ((tp->t_outq.c_cc <= 0) || (ch = getc(&tp->t_outq)) == -1)
1109: break;
1110: c = ch;
1111: /*
1112: * Drop priority for long screen updates. ttstart() calls us at
1113: * spltty.
1114: */
1115: o_pri = splsoftclock(); /* block timeout */
1116: if (c == (K_ESC)) {
1117: if (esc_spt == esc_seq) {
1118: *(esc_spt++)=(K_ESC);
1119: *(esc_spt) = '\0';
1120: } else {
1121: kd_putc((K_ESC));
1122: esc_spt = esc_seq;
1123: }
1124: } else {
1125: if (esc_spt - esc_seq) {
1126: if (esc_spt - esc_seq > K_MAXESC - 1)
1127: esc_spt = esc_seq;
1128: else {
1129: *(esc_spt++) = c;
1130: *(esc_spt) = '\0';
1131: kd_parseesc();
1132: }
1133: } else {
1134: kd_putc(c);
1135: }
1136: }
1137: splx(o_pri);
1138: }
1139: if (tp->t_outq.c_cc <= TTLOWAT(tp)) {
1140: tt_write_wakeup(tp);
1141: }
1142: }
1143:
1144: /*ARGSUSED*/
1145: kdstop(tp, flags)
1146: register struct tty *tp;
1147: int flags;
1148: {
1149: /*
1150: * do nothing - all characters are output by one call to
1151: * kdstart.
1152: */
1153: }
1154:
1155: /*
1156: * kdinit:
1157: *
1158: * This code initializes the structures and sets up the port registers
1159: * for the console driver.
1160: *
1161: * Each bitmap-based graphics card is likely to require a unique
1162: * way to determine the card's presence. The driver runs through
1163: * each "special" card that it knows about and uses the first one
1164: * that it finds. If it doesn't find any, it assumes that an
1165: * EGA-like card is installed.
1166: *
1167: * input : None. Interrupts are assumed to be disabled
1168: * output : Driver is initialized
1169: *
1170: */
1171: kdinit()
1172: {
1173: void kd_xga_init();
1174: unsigned char k_comm; /* keyboard command byte */
1175:
1176: if (kd_initialized)
1177: return;
1178:
1179: esc_spt = esc_seq;
1180: kd_attr = KA_NORMAL;
1181:
1182: /*
1183: * board specific initialization: set up globals and kd_dxxx
1184: * pointers, and synch displayed cursor with logical cursor.
1185: */
1186: if (!evc1init())
1187: if (blit_present())
1188: blit_init();
1189: else
1190: kd_xga_init();
1191:
1192: /* get rid of any garbage in output buffer */
1193: if (inb(K_STATUS) & K_OBUF_FUL)
1194: (void)inb(K_RDWR);
1195:
1196: kd_sendcmd(KC_CMD_READ); /* ask for the ctlr command byte */
1197: k_comm = kd_getdata();
1198: k_comm &= ~K_CB_DISBLE; /* clear keyboard disable bit */
1199: k_comm |= K_CB_ENBLIRQ; /* enable interrupt */
1200: kd_sendcmd(KC_CMD_WRITE); /* write new ctlr command byte */
1201: kd_senddata(k_comm);
1202: kd_initialized = TRUE;
1203:
1204: #ifdef ENABLE_IMMEDIATE_CONSOLE
1205: /* Now that we're set up, we no longer need or want the
1206: immediate console. */
1207: {
1208: extern int immediate_console_enable;
1209: immediate_console_enable = 0;
1210: }
1211:
1212: /* The immediate console printed stuff at the bottom of the
1213: screen rather than at the cursor position, so that's where
1214: we should start. */
1215: kd_setpos(ONE_PAGE - ONE_LINE); printf("\n");
1216: #endif
1217:
1218: cnsetleds(kd_state = KS_NORMAL);
1219: /* clear the LEDs AFTER we
1220: enable the keyboard controller.
1221: This keeps NUM-LOCK from being
1222: set on the NEC Versa. */
1223: }
1224:
1225: /*
1226: * kd_belloff:
1227: *
1228: * This routine shuts the bell off, by sending the appropriate code
1229: * to the speaker port.
1230: *
1231: * input : None
1232: * output : bell is turned off
1233: *
1234: */
1235: static unsigned int kd_bellstate = 0;
1236: kd_belloff()
1237: {
1238: unsigned char status;
1239:
1240: status = (inb(K_PORTB) & ~(K_SPKRDATA | K_ENABLETMR2));
1241: outb(K_PORTB, status);
1242: kd_bellstate = 0;
1243: return;
1244: }
1245:
1246:
1247: /*
1248: * kd_bellon:
1249: *
1250: * This routine turns the bell on.
1251: *
1252: * input : None
1253: * output : bell is turned on
1254: *
1255: */
1256: kd_bellon()
1257: {
1258: unsigned char status;
1259:
1260: /* program timer 2 */
1261: outb(K_TMRCTL, K_SELTMR2 | K_RDLDTWORD | K_TSQRWAVE | K_TBINARY);
1262: outb(K_TMR2, 1500 & 0xff); /* LSB */
1263: outb(K_TMR2, (int)1500 >> 8); /* MSB */
1264:
1265: /* start speaker - why must we turn on K_SPKRDATA? */
1266: status = (inb(K_PORTB)| K_ENABLETMR2 | K_SPKRDATA);
1267: outb(K_PORTB, status);
1268: return;
1269: }
1270:
1271: /*
1272: *
1273: * Function kd_putc():
1274: *
1275: * This function simply puts a character on the screen. It does some
1276: * special processing for linefeed, carriage return, backspace and
1277: * the bell.
1278: *
1279: * input : character to be displayed
1280: * output : character is displayed, or some action is taken
1281: *
1282: */
1283: int sit_for_0 = 1;
1284:
1285: kd_putc(ch)
1286: u_char ch;
1287: {
1288: if ((!ch) && sit_for_0)
1289: return;
1290:
1291: switch (ch) {
1292: case ((K_LF)):
1293: kd_down();
1294: break;
1295: case ((K_CR)):
1296: kd_cr();
1297: break;
1298: case ((K_BS)):
1299: kd_left();
1300: break;
1301: case ((K_HT)):
1302: kd_tab();
1303: break;
1304: case ((K_BEL)):
1305: /*
1306: * Similar problem to K_BS here (behavior might depend
1307: * on tty setting). Also check LF and CR.
1308: */
1309: if (!kd_bellstate)
1310: {
1311: kd_bellon();
1312: timeout(kd_belloff, 0, hz/8 );
1313: kd_bellstate = 1;
1314: }
1315: break;
1316: default:
1317: (*kd_dput)(kd_curpos, ch, kd_attr);
1318: kd_right();
1319: break;
1320: }
1321: return;
1322: }
1323:
1324:
1325: /*
1326: * kd_setpos:
1327: *
1328: * This function sets the software and hardware cursor position
1329: * on the screen, using device-specific code to actually move and
1330: * display the cursor.
1331: *
1332: * input : position on (or off) screen to move the cursor to
1333: * output : cursor position is updated, screen has been scrolled
1334: * if necessary to bring cursor position back onto
1335: * screen.
1336: *
1337: */
1338: kd_setpos(newpos)
1339: csrpos_t newpos;
1340: {
1341: if (newpos > ONE_PAGE) {
1342: kd_scrollup();
1343: newpos = BOTTOM_LINE;
1344: }
1345: if (newpos < 0) {
1346: kd_scrolldn();
1347: newpos = 0;
1348: }
1349:
1350: (*kd_dsetcursor)(newpos);
1351: }
1352:
1353:
1354: /*
1355: * kd_scrollup:
1356: *
1357: * This function scrolls the screen up one line using a DMA memory
1358: * copy.
1359: *
1360: * input : None
1361: * output : lines on screen appear to be shifted up one line
1362: *
1363: */
1364: kd_scrollup()
1365: {
1366: csrpos_t to;
1367: csrpos_t from;
1368: int count;
1369:
1370: /* scroll up */
1371: to = 0;
1372: from = ONE_LINE;
1373: count = (ONE_PAGE - ONE_LINE)/ONE_SPACE;
1374: (*kd_dmvup)(from, to, count);
1375:
1376: /* clear bottom line */
1377: to = BOTTOM_LINE;
1378: count = ONE_LINE/ONE_SPACE;
1379: (*kd_dclear)(to, count, kd_attr);
1380: return;
1381: }
1382:
1383:
1384: /*
1385: * kd_scrolldn:
1386: *
1387: * Scrolls the characters on the screen down one line.
1388: *
1389: * input : None
1390: * output : Lines on screen appear to be moved down one line
1391: *
1392: */
1393: kd_scrolldn()
1394: {
1395: csrpos_t to;
1396: csrpos_t from;
1397: int count;
1398:
1399: /* move down */
1400: to = ONE_PAGE - ONE_SPACE;
1401: from = ONE_PAGE - ONE_LINE - ONE_SPACE;
1402: count = (ONE_PAGE - ONE_LINE) / ONE_SPACE;
1403: (*kd_dmvdown)(from, to, count);
1404:
1405: /* clear top line */
1406: to = 0;
1407: count = ONE_LINE/ONE_SPACE;
1408: (*kd_dclear)(to, count, kd_attr);
1409: return;
1410:
1411: }
1412:
1413:
1414: /*
1415: * kd_parseesc:
1416: *
1417: * This routine begins the parsing of an escape sequence. It uses the
1418: * escape sequence array and the escape spot pointer to handle
1419: * asynchronous parsing of escape sequences.
1420: *
1421: * input : String of characters prepended by an escape
1422: * output : Appropriate actions are taken depending on the string as
1423: * defined by the ansi terminal specification
1424: *
1425: */
1426: kd_parseesc()
1427: {
1428: u_char *escp;
1429:
1430: escp = esc_seq + 1; /* point to char following ESC */
1431: switch(*(escp)) {
1432: case 'c':
1433: kd_cls();
1434: kd_home();
1435: esc_spt = esc_seq; /* reset spot in ESC sequence */
1436: break;
1437: case '[':
1438: escp++;
1439: kd_parserest(escp);
1440: break;
1441: case '\0':
1442: break; /* not enough info yet */
1443: default:
1444: kd_putc(*escp);
1445: esc_spt = esc_seq; /* inv sequence char, reset */
1446: break;
1447: }
1448: return;
1449:
1450: }
1451:
1452:
1453: /*
1454: * kd_parserest:
1455: *
1456: * This function will complete the parsing of an escape sequence and
1457: * call the appropriate support routine if it matches a character. This
1458: * function could be greatly improved by using a function jump table, and
1459: * removing this bulky switch statement.
1460: *
1461: * input : An string
1462: * output : Appropriate action based on whether the string matches a
1463: * sequence acceptable to the ansi terminal specification
1464: *
1465: */
1466: kd_parserest(cp)
1467: u_char *cp;
1468: {
1469: int number;
1470: csrpos_t newpos;
1471:
1472: cp += kd_atoi(cp, &number);
1473: switch(*cp) {
1474: case 'm':
1475: switch(number) {
1476: case DEFAULT:
1477: case 0:
1478: kd_attr = KA_NORMAL;
1479: break;
1480: case 7:
1481: kd_attr = KA_REVERSE;
1482: break;
1483: default:
1484: kd_attr = KA_NORMAL;
1485: break;
1486: }
1487: esc_spt = esc_seq;
1488: break;
1489: case '@':
1490: if (number == DEFAULT)
1491: kd_insch(1);
1492: else
1493: kd_insch(number);
1494: esc_spt = esc_seq;
1495: break;
1496: case 'H':
1497: kd_home();
1498: esc_spt = esc_seq;
1499: break;
1500: case 'A':
1501: if (number == DEFAULT)
1502: kd_up();
1503: else
1504: while (number--)
1505: kd_up();
1506: esc_spt = esc_seq;
1507: break;
1508: case 'B':
1509: if (number == DEFAULT)
1510: kd_down();
1511: else
1512: while (number--)
1513: kd_down();
1514: esc_spt = esc_seq;
1515: break;
1516: case 'C':
1517: if (number == DEFAULT)
1518: kd_right();
1519: else
1520: while (number--)
1521: kd_right();
1522: esc_spt = esc_seq;
1523: break;
1524: case 'D':
1525: if (number == DEFAULT)
1526: kd_left();
1527: else
1528: while (number--)
1529: kd_left();
1530: esc_spt = esc_seq;
1531: break;
1532: case 'E':
1533: kd_cr();
1534: if (number == DEFAULT)
1535: kd_down();
1536: else
1537: while (number--)
1538: kd_down();
1539: esc_spt = esc_seq;
1540: break;
1541: case 'F':
1542: kd_cr();
1543: if (number == DEFAULT)
1544: kd_up();
1545: else
1546: while (number--)
1547: kd_up();
1548: esc_spt = esc_seq;
1549: break;
1550: case 'G':
1551: if (number == DEFAULT)
1552: number = 0;
1553: else
1554: if (number > 0)
1555: --number; /* because number is from 1 */
1556: kd_setpos(BEG_OF_LINE(kd_curpos) + number * ONE_SPACE);
1557: esc_spt = esc_seq;
1558: break;
1559: case ';':
1560: ++cp;
1561: if (*cp == '\0')
1562: break; /* not ready yet */
1563: if (number == DEFAULT)
1564: number = 0;
1565: else
1566: if (number > 0)
1567: --number; /* numbered from 1 */
1568: newpos = (number * ONE_LINE); /* setup row */
1569: cp += kd_atoi(cp, &number);
1570: if (*cp == '\0')
1571: break; /* not ready yet */
1572: if (number == DEFAULT)
1573: number = 0;
1574: else if (number > 0)
1575: number--;
1576: newpos += (number * ONE_SPACE); /* setup column */
1577: if (newpos < 0)
1578: newpos = 0; /* upper left */
1579: if (newpos > ONE_PAGE)
1580: newpos = (ONE_PAGE - ONE_SPACE);
1581: /* lower right */
1582: if (*cp == '\0')
1583: break; /* not ready yet */
1584: if (*cp == 'H') {
1585: kd_setpos(newpos);
1586: esc_spt = esc_seq; /* done, reset */
1587: }
1588: else
1589: esc_spt = esc_seq;
1590: break; /* done or not ready */
1591: case 'J':
1592: switch(number) {
1593: case DEFAULT:
1594: case 0:
1595: kd_cltobcur(); /* clears from current
1596: pos to bottom.
1597: */
1598: break;
1599: case 1:
1600: kd_cltopcur(); /* clears from top to
1601: current pos.
1602: */
1603: break;
1604: case 2:
1605: kd_cls();
1606: break;
1607: default:
1608: break;
1609: }
1610: esc_spt = esc_seq; /* reset it */
1611: break;
1612: case 'K':
1613: switch(number) {
1614: case DEFAULT:
1615: case 0:
1616: kd_cltoecur(); /* clears from current
1617: pos to eoln.
1618: */
1619: break;
1620: case 1:
1621: kd_clfrbcur(); /* clears from begin
1622: of line to current
1623: pos.
1624: */
1625: break;
1626: case 2:
1627: kd_eraseln(); /* clear entire line */
1628: break;
1629: default:
1630: break;
1631: }
1632: esc_spt = esc_seq;
1633: break;
1634: case 'L':
1635: if (number == DEFAULT)
1636: kd_insln(1);
1637: else
1638: kd_insln(number);
1639: esc_spt = esc_seq;
1640: break;
1641: case 'M':
1642: if (number == DEFAULT)
1643: kd_delln(1);
1644: else
1645: kd_delln(number);
1646: esc_spt = esc_seq;
1647: break;
1648: case 'P':
1649: if (number == DEFAULT)
1650: kd_delch(1);
1651: else
1652: kd_delch(number);
1653: esc_spt = esc_seq;
1654: break;
1655: case 'S':
1656: if (number == DEFAULT)
1657: kd_scrollup();
1658: else
1659: while (number--)
1660: kd_scrollup();
1661: esc_spt = esc_seq;
1662: break;
1663: case 'T':
1664: if (number == DEFAULT)
1665: kd_scrolldn();
1666: else
1667: while (number--)
1668: kd_scrolldn();
1669: esc_spt = esc_seq;
1670: break;
1671: case 'X':
1672: if (number == DEFAULT)
1673: kd_erase(1);
1674: else
1675: kd_erase(number);
1676: esc_spt = esc_seq;
1677: break;
1678: case '\0':
1679: break; /* not enough yet */
1680: default:
1681: kd_putc(*cp); /* show inv character */
1682: esc_spt = esc_seq; /* inv entry, reset */
1683: break;
1684: }
1685: return;
1686: }
1687:
1688: /*
1689: * kd_atoi:
1690: *
1691: * This function converts an ascii string into an integer, and
1692: * returns DEFAULT if no integer was found. Note that this is why
1693: * we don't use the regular atio(), because ZERO is ZERO and not
1694: * the DEFAULT in all cases.
1695: *
1696: * input : string
1697: * output : a number or possibly DEFAULT, and the count of characters
1698: * consumed by the conversion
1699: *
1700: */
1701: int
1702: kd_atoi(cp, nump)
1703: u_char *cp;
1704: int *nump;
1705: {
1706: int number;
1707: u_char *original;
1708:
1709: original = cp;
1710: for (number = 0; ('0' <= *cp) && (*cp <= '9'); cp++)
1711: number = (number * 10) + (*cp - '0');
1712: if (original == cp)
1713: *nump = DEFAULT;
1714: else
1715: *nump = number;
1716: return(cp - original);
1717: }
1718:
1719: kd_tab()
1720: {
1721: int i;
1722:
1723: for (i = 8 - (CURRENT_COLUMN(kd_curpos) % 8); i > 0; i--) {
1724: kd_putc(' ');
1725: }
1726:
1727: }
1728:
1729:
1730: /*
1731: * kd_cls:
1732: *
1733: * This function clears the screen with spaces and the current attribute.
1734: *
1735: * input : None
1736: * output : Screen is cleared
1737: *
1738: */
1739: kd_cls()
1740: {
1741: (*kd_dclear)(0, ONE_PAGE/ONE_SPACE, kd_attr);
1742: return;
1743: }
1744:
1745:
1746: /*
1747: * kd_home:
1748: *
1749: * This function will move the cursor to the home position on the screen,
1750: * as well as set the internal cursor position (kd_curpos) to home.
1751: *
1752: * input : None
1753: * output : Cursor position is moved
1754: *
1755: */
1756: kd_home()
1757: {
1758: kd_setpos(0);
1759: return;
1760: }
1761:
1762:
1763: /*
1764: * kd_up:
1765: *
1766: * This function moves the cursor up one line position.
1767: *
1768: * input : None
1769: * output : Cursor moves up one line, or screen is scrolled
1770: *
1771: */
1772: kd_up()
1773: {
1774: if (kd_curpos < ONE_LINE)
1775: kd_scrolldn();
1776: else
1777: kd_setpos(kd_curpos - ONE_LINE);
1778: return;
1779: }
1780:
1781:
1782: /*
1783: * kd_down:
1784: *
1785: * This function moves the cursor down one line position.
1786: *
1787: * input : None
1788: * output : Cursor moves down one line or the screen is scrolled
1789: *
1790: */
1791: kd_down()
1792: {
1793: if (kd_curpos >= (ONE_PAGE - ONE_LINE))
1794: kd_scrollup();
1795: else
1796: kd_setpos(kd_curpos + ONE_LINE);
1797: return;
1798: }
1799:
1800:
1801: /*
1802: * kd_right:
1803: *
1804: * This function moves the cursor one position to the right.
1805: *
1806: * input : None
1807: * output : Cursor moves one position to the right
1808: *
1809: */
1810: kd_right()
1811: {
1812: if (kd_curpos < (ONE_PAGE - ONE_SPACE))
1813: kd_setpos(kd_curpos + ONE_SPACE);
1814: else {
1815: kd_scrollup();
1816: kd_setpos(BEG_OF_LINE(kd_curpos));
1817: }
1818: return;
1819: }
1820:
1821:
1822: /*
1823: * kd_left:
1824: *
1825: * This function moves the cursor one position to the left.
1826: *
1827: * input : None
1828: * output : Cursor moves one position to the left
1829: *
1830: */
1831: kd_left()
1832: {
1833: if (0 < kd_curpos)
1834: kd_setpos(kd_curpos - ONE_SPACE);
1835: return;
1836: }
1837:
1838:
1839: /*
1840: * kd_cr:
1841: *
1842: * This function moves the cursor to the beginning of the current
1843: * line.
1844: *
1845: * input : None
1846: * output : Cursor moves to the beginning of the current line
1847: *
1848: */
1849: kd_cr()
1850: {
1851: kd_setpos(BEG_OF_LINE(kd_curpos));
1852: return;
1853: }
1854:
1855:
1856: /*
1857: * kd_cltobcur:
1858: *
1859: * This function clears from the current cursor position to the bottom
1860: * of the screen.
1861: *
1862: * input : None
1863: * output : Screen is cleared from current cursor postion to bottom
1864: *
1865: */
1866: kd_cltobcur()
1867: {
1868: csrpos_t start;
1869: int count;
1870:
1871: start = kd_curpos;
1872: count = (ONE_PAGE - kd_curpos)/ONE_SPACE;
1873: (*kd_dclear)(start, count, kd_attr);
1874: return;
1875: }
1876:
1877:
1878: /*
1879: * kd_cltopcur:
1880: *
1881: * This function clears from the current cursor position to the top
1882: * of the screen.
1883: *
1884: * input : None
1885: * output : Screen is cleared from current cursor postion to top
1886: *
1887: */
1888: kd_cltopcur()
1889: {
1890: int count;
1891:
1892: count = (kd_curpos + ONE_SPACE) / ONE_SPACE;
1893: (*kd_dclear)(0, count, kd_attr);
1894: return;
1895: }
1896:
1897:
1898: /*
1899: * kd_cltoecur:
1900: *
1901: * This function clears from the current cursor position to eoln.
1902: *
1903: * input : None
1904: * output : Line is cleared from current cursor position to eoln
1905: *
1906: */
1907: kd_cltoecur()
1908: {
1909: csrpos_t i;
1910: csrpos_t hold;
1911:
1912: hold = BEG_OF_LINE(kd_curpos) + ONE_LINE;
1913: for (i = kd_curpos; i < hold; i += ONE_SPACE) {
1914: (*kd_dput)(i, K_SPACE, kd_attr);
1915: }
1916: }
1917:
1918:
1919: /*
1920: * kd_clfrbcur:
1921: *
1922: * This function clears from the beginning of the line to the current
1923: * cursor position.
1924: *
1925: * input : None
1926: * output : Line is cleared from beginning to current position
1927: *
1928: */
1929: kd_clfrbcur()
1930: {
1931: csrpos_t i;
1932:
1933: for (i = BEG_OF_LINE(kd_curpos); i <= kd_curpos; i += ONE_SPACE) {
1934: (*kd_dput)(i, K_SPACE, kd_attr);
1935: }
1936: }
1937:
1938:
1939: /*
1940: * kd_delln:
1941: *
1942: * This function deletes 'number' lines on the screen by effectively
1943: * scrolling the lines up and replacing the old lines with spaces.
1944: *
1945: * input : number of lines to delete
1946: * output : lines appear to be deleted
1947: *
1948: */
1949: kd_delln(number)
1950: int number;
1951: {
1952: csrpos_t to;
1953: csrpos_t from;
1954: int delbytes; /* num of bytes to delete */
1955: int count; /* num of words to move or fill */
1956:
1957: if (number <= 0)
1958: return;
1959:
1960: delbytes = number * ONE_LINE;
1961: to = BEG_OF_LINE(kd_curpos);
1962: if (to + delbytes >= ONE_PAGE)
1963: delbytes = ONE_PAGE - to;
1964: if (to + delbytes < ONE_PAGE) {
1965: from = to + delbytes;
1966: count = (ONE_PAGE - from) / ONE_SPACE;
1967: (*kd_dmvup)(from, to, count);
1968: }
1969:
1970: to = ONE_PAGE - delbytes;
1971: count = delbytes / ONE_SPACE;
1972: (*kd_dclear)(to, count, kd_attr);
1973: return;
1974: }
1975:
1976:
1977: /*
1978: * kd_insln:
1979: *
1980: * This function inserts a line above the current one by
1981: * scrolling the current line and all the lines below it down.
1982: *
1983: * input : number of lines to insert
1984: * output : New lines appear to be inserted
1985: *
1986: */
1987: kd_insln(number)
1988: int number;
1989: {
1990: csrpos_t to;
1991: csrpos_t from;
1992: int count;
1993: csrpos_t top; /* top of block to be moved */
1994: int insbytes; /* num of bytes inserted */
1995:
1996: if (number <= 0)
1997: return;
1998:
1999: top = BEG_OF_LINE(kd_curpos);
2000: insbytes = number * ONE_LINE;
2001: if (top + insbytes > ONE_PAGE)
2002: insbytes = ONE_PAGE - top;
2003: to = ONE_PAGE - ONE_SPACE;
2004: from = to - insbytes;
2005: if (from > top) {
2006: count = (from - top + ONE_SPACE) / ONE_SPACE;
2007: (*kd_dmvdown)(from, to, count);
2008: }
2009:
2010: count = insbytes / ONE_SPACE;
2011: (*kd_dclear)(top, count, kd_attr);
2012: return;
2013: }
2014:
2015:
2016: /*
2017: * kd_delch:
2018: *
2019: * This function deletes a number of characters from the current
2020: * position in the line.
2021: *
2022: * input : number of characters to delete
2023: * output : characters appear to be deleted
2024: *
2025: */
2026: kd_delch(number)
2027: int number;
2028: {
2029: int count; /* num words moved/filled */
2030: int delbytes; /* bytes to delete */
2031: register csrpos_t to;
2032: csrpos_t from;
2033: csrpos_t nextline; /* start of next line */
2034:
2035: if (number <= 0)
2036: return;
2037:
2038: nextline = BEG_OF_LINE(kd_curpos) + ONE_LINE;
2039: delbytes = number * ONE_SPACE;
2040: if (kd_curpos + delbytes > nextline)
2041: delbytes = nextline - kd_curpos;
2042: if (kd_curpos + delbytes < nextline) {
2043: from = kd_curpos + delbytes;
2044: to = kd_curpos;
2045: count = (nextline - from) / ONE_SPACE;
2046: (*kd_dmvup)(from, to, count);
2047: }
2048:
2049: to = nextline - delbytes;
2050: count = delbytes / ONE_SPACE;
2051: (*kd_dclear)(to, count, kd_attr);
2052: return;
2053:
2054: }
2055:
2056:
2057: /*
2058: * kd_erase:
2059: *
2060: * This function overwrites characters with a space starting with the
2061: * current cursor position and ending in number spaces away.
2062: *
2063: * input : number of characters to erase
2064: * output : characters appear to be blanked or erased
2065: *
2066: */
2067: kd_erase(number)
2068: int number;
2069: {
2070: csrpos_t i;
2071: csrpos_t stop;
2072:
2073: stop = kd_curpos + (ONE_SPACE * number);
2074: if (stop > BEG_OF_LINE(kd_curpos) + ONE_LINE)
2075: stop = BEG_OF_LINE(kd_curpos) + ONE_LINE;
2076: for (i = kd_curpos; i < stop; i += ONE_SPACE) {
2077: (*kd_dput)(i, K_SPACE, kd_attr);
2078: }
2079: return;
2080: }
2081:
2082:
2083: /*
2084: * kd_eraseln:
2085: *
2086: * This function erases the current line with spaces.
2087: *
2088: * input : None
2089: * output : Current line is erased
2090: *
2091: */
2092: kd_eraseln()
2093: {
2094: csrpos_t i;
2095: csrpos_t stop;
2096:
2097: stop = BEG_OF_LINE(kd_curpos) + ONE_LINE;
2098: for (i = BEG_OF_LINE(kd_curpos); i < stop; i += ONE_SPACE) {
2099: (*kd_dput)(i, K_SPACE, kd_attr);
2100: }
2101: return;
2102: }
2103:
2104:
2105: /*
2106: * kd_insch:
2107: *
2108: * This function inserts a blank at the current cursor position
2109: * and moves all other characters on the line over.
2110: *
2111: * input : number of blanks to insert
2112: * output : Blanks are inserted at cursor position
2113: *
2114: */
2115: kd_insch(number)
2116: int number;
2117: {
2118: csrpos_t to;
2119: csrpos_t from;
2120: int count;
2121: csrpos_t nextline; /* start of next line */
2122: int insbytes; /* num of bytes inserted */
2123:
2124: if (number <= 0)
2125: return;
2126:
2127: nextline = BEG_OF_LINE(kd_curpos) + ONE_LINE;
2128: insbytes = number * ONE_SPACE;
2129: if (kd_curpos + insbytes > nextline)
2130: insbytes = nextline - kd_curpos;
2131:
2132: to = nextline - ONE_SPACE;
2133: from = to - insbytes;
2134: if (from >= kd_curpos) {
2135: count = (from - kd_curpos + ONE_SPACE) / ONE_SPACE;
2136: (*kd_dmvdown)(from, to, count);
2137: }
2138:
2139: count = insbytes / ONE_SPACE;
2140: (*kd_dclear)(kd_curpos, count, kd_attr);
2141: return;
2142: }
2143:
2144:
2145: /*
2146: * kd_isupper, kd_islower:
2147: *
2148: * Didn't want to include ctype.h because it brings in stdio.h, and
2149: * only want to see if the darn character is uppercase or lowercase.
2150: *
2151: * input : Character 'c'
2152: * output : isuuper gives TRUE if character is uppercase, islower
2153: * returns TRUE if character is lowercase
2154: *
2155: */
2156: kd_isupper(c)
2157: u_char c;
2158: {
2159: if (('A' <= c) && (c <= 'Z'))
2160: return(TRUE);
2161: return(FALSE);
2162: }
2163:
2164: kd_islower(c)
2165: u_char c;
2166: {
2167: if (('a' <= c) && (c <= 'z'))
2168: return(TRUE);
2169: return(FALSE);
2170: }
2171:
2172: /*
2173: * kd_senddata:
2174: *
2175: * This function sends a byte to the keyboard RDWR port, but
2176: * first waits until the input/output data buffer is clear before
2177: * sending the data. Note that this byte can be either data or a
2178: * keyboard command.
2179: *
2180: */
2181: kd_senddata(ch)
2182: unsigned char ch;
2183: {
2184: while (inb(K_STATUS) & K_IBUF_FUL);
2185: outb(K_RDWR, ch);
2186: last_sent = ch;
2187: return;
2188: }
2189:
2190: /*
2191: * kd_sendcmd:
2192: *
2193: * This function sends a command byte to the keyboard command
2194: * port, but first waits until the input/output data buffer is
2195: * clear before sending the data.
2196: *
2197: */
2198: kd_sendcmd(ch)
2199: unsigned char ch;
2200: {
2201: while (inb(K_STATUS) & K_IBUF_FUL);
2202: outb(K_CMD, ch);
2203: return;
2204: }
2205:
2206:
2207: /*
2208: * kd_getdata:
2209: *
2210: * This function returns a data byte from the keyboard RDWR port,
2211: * after waiting until the port is flagged as having something to
2212: * read.
2213: */
2214: unsigned char
2215: kd_getdata()
2216: {
2217: while ((inb(K_STATUS) & K_OBUF_FUL) == 0);
2218: return(inb(K_RDWR));
2219: }
2220:
2221: kd_cmdreg_read()
2222: {
2223: int ch=KC_CMD_READ;
2224:
2225: while (inb(K_STATUS) & K_IBUF_FUL);
2226: outb(K_CMD, ch);
2227:
2228: while ((inb(K_STATUS) & K_OBUF_FUL) == 0);
2229: return(inb(K_RDWR));
2230: }
2231:
2232: kd_cmdreg_write(val)
2233: {
2234: int ch=KC_CMD_WRITE;
2235:
2236: while (inb(K_STATUS) & K_IBUF_FUL);
2237: outb(K_CMD, ch);
2238:
2239: while (inb(K_STATUS) & K_IBUF_FUL);
2240: outb(K_RDWR, val);
2241: }
2242:
2243: kd_mouse_drain()
2244: {
2245: int i;
2246: while(inb(K_STATUS) & K_IBUF_FUL);
2247: while((i = inb(K_STATUS)) & K_OBUF_FUL)
2248: printf("kbd: S = %x D = %x\n", i, inb(K_RDWR));
2249: }
2250:
2251: /*
2252: * set_kd_state:
2253: *
2254: * Set kd_state and update the keyboard status LEDs.
2255: */
2256:
2257: set_kd_state(newstate)
2258: int newstate;
2259: {
2260: kd_state = newstate;
2261: kd_setleds1(state2leds(newstate));
2262: }
2263:
2264: /*
2265: * state2leds:
2266: *
2267: * Return a byte containing LED settings for the keyboard, given
2268: * a state vector.
2269: */
2270: u_char
2271: state2leds(state)
2272: int state;
2273: {
2274: u_char result = 0;
2275:
2276: if (state & KS_NLKED)
2277: result |= K_LED_NUMLK;
2278: if (state & KS_CLKED)
2279: result |= K_LED_CAPSLK;
2280: return(result);
2281: }
2282:
2283: /*
2284: * kd_setleds[12]:
2285: *
2286: * Set the keyboard LEDs according to the given byte.
2287: */
2288: kd_setleds1(val)
2289: u_char val;
2290: {
2291: if (kd_ack != NOT_WAITING) {
2292: printf("kd_setleds1: unexpected state (%d)\n", kd_ack);
2293: return;
2294: }
2295:
2296: kd_ack = SET_LEDS;
2297: kd_nextled = val;
2298: kd_senddata(K_CMD_LEDS);
2299: }
2300:
2301: kd_setleds2()
2302: {
2303: kd_senddata(kd_nextled);
2304: }
2305:
2306:
2307: /*
2308: * cnsetleds:
2309: *
2310: * like kd_setleds[12], but not interrupt-based.
2311: * Currently disabled because cngetc ignores caps lock and num
2312: * lock anyway.
2313: */
2314: cnsetleds(val)
2315: u_char val;
2316: {
2317: kd_senddata(K_CMD_LEDS);
2318: (void)kd_getdata(); /* XXX - assume is ACK */
2319: kd_senddata(val);
2320: (void)kd_getdata(); /* XXX - assume is ACK */
2321: }
2322:
2323: kdreboot()
2324: {
2325: (*kd_dreset)();
2326:
2327: #ifndef BROKEN_KEYBOARD_RESET
2328: kd_sendcmd(0xFE); /* XXX - magic # */
2329: delay(1000000); /* wait to see if anything happens */
2330: #endif
2331: /*
2332: * If that didn't work, then we'll just have to try and
2333: * do it the hard way.
2334: */
2335: cpu_shutdown();
2336: }
2337:
2338: static int which_button[] = {0, MOUSE_LEFT, MOUSE_MIDDLE, MOUSE_RIGHT};
2339: static struct mouse_motion moved;
2340:
2341: kd_kbd_magic(scancode)
2342: {
2343: int new_button = 0;
2344:
2345: if (kd_kbd_mouse == 2)
2346: printf("sc = %x\n", scancode);
2347:
2348: switch (scancode) {
2349: /* f1 f2 f3 */
2350: case 0x3d:
2351: new_button++;
2352: case 0x3c:
2353: new_button++;
2354: case 0x3b:
2355: new_button++;
2356: if (kd_kbd_magic_button && (new_button != kd_kbd_magic_button)) {
2357: /* down w/o up */
2358: mouse_button(which_button[kd_kbd_magic_button], 1);
2359: }
2360: /* normal */
2361: if (kd_kbd_magic_button == new_button) {
2362: mouse_button(which_button[new_button], 1);
2363: kd_kbd_magic_button = 0;
2364: } else {
2365: mouse_button(which_button[new_button], 0);
2366: kd_kbd_magic_button = new_button;
2367: }
2368: break;
2369:
2370: /* right left up down */
2371: case 0x4d:
2372: moved.mm_deltaX = kd_kbd_magic_scale;
2373: moved.mm_deltaY = 0;
2374: mouse_moved(moved);
2375: break;
2376: case 0x4b:
2377: moved.mm_deltaX = -kd_kbd_magic_scale;
2378: moved.mm_deltaY = 0;
2379: mouse_moved(moved);
2380: break;
2381: case 0x48:
2382: moved.mm_deltaX = 0;
2383: moved.mm_deltaY = kd_kbd_magic_scale;
2384: mouse_moved(moved);
2385: break;
2386: case 0x50:
2387: moved.mm_deltaX = 0;
2388: moved.mm_deltaY = -kd_kbd_magic_scale;
2389: mouse_moved(moved);
2390: break;
2391: /* home pageup end pagedown */
2392: case 0x47:
2393: moved.mm_deltaX = -2*kd_kbd_magic_scale;
2394: moved.mm_deltaY = 2*kd_kbd_magic_scale;
2395: mouse_moved(moved);
2396: break;
2397: case 0x49:
2398: moved.mm_deltaX = 2*kd_kbd_magic_scale;
2399: moved.mm_deltaY = 2*kd_kbd_magic_scale;
2400: mouse_moved(moved);
2401: break;
2402: case 0x4f:
2403: moved.mm_deltaX = -2*kd_kbd_magic_scale;
2404: moved.mm_deltaY = -2*kd_kbd_magic_scale;
2405: mouse_moved(moved);
2406: break;
2407: case 0x51:
2408: moved.mm_deltaX = 2*kd_kbd_magic_scale;
2409: moved.mm_deltaY = -2*kd_kbd_magic_scale;
2410: mouse_moved(moved);
2411: break;
2412:
2413: default:
2414: return 0;
2415: }
2416: return 1;
2417: }
2418:
2419:
2420:
2421: /*
2422: * Code specific to EGA/CGA/VGA boards. This code relies on the fact
2423: * that the "slam" functions take a word count and ONE_SPACE takes up
2424: * 1 word.
2425: */
2426: #define SLAMBPW 2 /* bytes per word for "slam" fcns */
2427:
2428:
2429: /*
2430: * kd_xga_init:
2431: *
2432: * Initialization specific to character-based graphics adapters.
2433: */
2434: void
2435: kd_xga_init()
2436: {
2437: csrpos_t xga_getpos();
2438: unsigned char screen;
2439:
2440: outb(CMOS_ADDR, CMOS_EB);
2441: screen = inb(CMOS_DATA) & CM_SCRMSK;
2442: switch(screen) {
2443: case CM_EGA_VGA:
2444: /*
2445: * Here we'll want to query to bios on the card
2446: * itself, because then we can figure out what
2447: * type we have exactly. At this point we only
2448: * know that the card is NOT CGA or MONO. For
2449: * now, however, we assume backwards compatibility
2450: * with 0xb8000 as the starting screen offset
2451: * memory location for these cards.
2452: *
2453: */
2454:
2455: vid_start = (u_char *)phystokv(EGA_START);
2456: kd_index_reg = EGA_IDX_REG;
2457: kd_io_reg = EGA_IO_REG;
2458: kd_lines = 25;
2459: kd_cols = 80;
2460: kd_bitmap_start = 0xa0000; /* XXX - magic numbers */
2461: { /* XXX - is there a cleaner way to do this? */
2462: char *addr = (char *)phystokv(kd_bitmap_start);
2463: int i;
2464: for (i = 0; i < 200; i++)
2465: addr[i] = 0x00;
2466: }
2467: break;
2468: case CM_CGA_40:
2469: vid_start = (u_char *)phystokv(CGA_START);
2470: kd_index_reg = CGA_IDX_REG;
2471: kd_io_reg = CGA_IO_REG;
2472: kd_lines = 25;
2473: kd_cols = 40;
2474: break;
2475: case CM_CGA_80:
2476: vid_start = (u_char *)phystokv(CGA_START);
2477: kd_index_reg = CGA_IDX_REG;
2478: kd_io_reg = CGA_IO_REG;
2479: kd_lines = 25;
2480: kd_cols = 80;
2481: break;
2482: case CM_MONO_80:
2483: vid_start = (u_char *)phystokv(MONO_START);
2484: kd_index_reg = MONO_IDX_REG;
2485: kd_io_reg = MONO_IO_REG;
2486: kd_lines = 25;
2487: kd_cols = 80;
2488: break;
2489: default:
2490: printf("kd: unknown screen type, defaulting to EGA\n");
2491: }
2492:
2493: kd_setpos(xga_getpos());
2494: }
2495:
2496:
2497: /*
2498: * xga_getpos:
2499: *
2500: * This function returns the current hardware cursor position on the
2501: * screen, scaled for compatibility with kd_curpos.
2502: *
2503: * input : None
2504: * output : returns the value of cursor position on screen
2505: *
2506: */
2507: csrpos_t
2508: xga_getpos()
2509:
2510: {
2511: unsigned char low;
2512: unsigned char high;
2513: short pos;
2514:
2515: outb(kd_index_reg, C_HIGH);
2516: high = inb(kd_io_reg);
2517: outb(kd_index_reg, C_LOW);
2518: low = inb(kd_io_reg);
2519: pos = (0xff&low) + ((unsigned short)high<<8);
2520:
2521: return(ONE_SPACE * (csrpos_t)pos);
2522: }
2523:
2524:
2525: /*
2526: * charput:
2527: *
2528: * Put attributed character for EGA/CGA/etc.
2529: */
2530: static void
2531: charput(pos, ch, chattr)
2532: csrpos_t pos; /* where to put it */
2533: char ch; /* the character */
2534: char chattr; /* its attribute */
2535: {
2536: *(vid_start + pos) = ch;
2537: *(vid_start + pos + 1) = chattr;
2538: }
2539:
2540:
2541: /*
2542: * charsetcursor:
2543: *
2544: * Set hardware cursor position for EGA/CGA/etc.
2545: */
2546: static void
2547: charsetcursor(newpos)
2548: csrpos_t newpos;
2549: {
2550: short curpos; /* position, not scaled for attribute byte */
2551:
2552: curpos = newpos / ONE_SPACE;
2553: outb(kd_index_reg, C_HIGH);
2554: outb(kd_io_reg, (u_char)(curpos>>8));
2555: outb(kd_index_reg, C_LOW);
2556: outb(kd_io_reg, (u_char)(curpos&0xff));
2557:
2558: kd_curpos = newpos;
2559: }
2560:
2561:
2562: /*
2563: * charmvup:
2564: *
2565: * Block move up for EGA/CGA/etc.
2566: */
2567: static void
2568: charmvup(from, to, count)
2569: csrpos_t from, to;
2570: int count;
2571: {
2572: kd_slmscu(vid_start+from, vid_start+to, count);
2573: }
2574:
2575:
2576: /*
2577: * charmvdown:
2578: *
2579: * Block move down for EGA/CGA/etc.
2580: */
2581: static void
2582: charmvdown(from, to, count)
2583: csrpos_t from, to;
2584: int count;
2585: {
2586: kd_slmscd(vid_start+from, vid_start+to, count);
2587: }
2588:
2589:
2590: /*
2591: * charclear:
2592: *
2593: * Fast clear for CGA/EGA/etc.
2594: */
2595: static void
2596: charclear(to, count, chattr)
2597: csrpos_t to;
2598: int count;
2599: char chattr;
2600: {
2601: kd_slmwd(vid_start+to, count, ((unsigned short)chattr<<8)+K_SPACE);
2602: }
2603:
2604:
2605: /*
2606: * kd_noopreset:
2607: *
2608: * No-op reset routine for kd_dreset.
2609: */
2610: static void
2611: kd_noopreset()
2612: {
2613: }
2614:
2615:
2616:
2617: /*
2618: * Generic routines for bitmap devices (i.e., assume no hardware
2619: * assist). Assumes a simple byte ordering (i.e., a byte at a lower
2620: * address is to the left of the byte at the next higher address).
2621: * For the 82786, this works anyway if the characters are 2 bytes
2622: * wide. (more bubble gum and paper clips.)
2623: *
2624: * See the comments above about SLAMBPW.
2625: */
2626:
2627: void bmpch2bit(), bmppaintcsr();
2628: u_char *bit2fbptr();
2629:
2630:
2631: /*
2632: * bmpput: Copy a character from the font to the frame buffer.
2633: */
2634:
2635: void
2636: bmpput(pos, ch, chattr)
2637: csrpos_t pos;
2638: char ch, chattr;
2639: {
2640: short xbit, ybit; /* u/l corner of char pos */
2641: register u_char *to, *from;
2642: register short i, j;
2643: u_char mask = (chattr == KA_REVERSE ? 0xff : 0);
2644:
2645: if ((u_char)ch >= chars_in_font)
2646: ch = K_QUES;
2647:
2648: bmpch2bit(pos, &xbit, &ybit);
2649: to = bit2fbptr(xbit, ybit);
2650: from = font_start + ch * char_byte_width;
2651: for (i = 0; i < char_height; ++i) {
2652: for (j = 0; j < char_byte_width; ++j)
2653: *(to+j) = *(from+j) ^ mask;
2654: to += fb_byte_width;
2655: from += font_byte_width;
2656: }
2657: }
2658:
2659: /*
2660: * bmpcp1char: copy 1 char from one place in the frame buffer to
2661: * another.
2662: */
2663: void
2664: bmpcp1char(from, to)
2665: csrpos_t from, to;
2666: {
2667: short from_xbit, from_ybit;
2668: short to_xbit, to_ybit;
2669: register u_char *tp, *fp;
2670: register short i, j;
2671:
2672: bmpch2bit(from, &from_xbit, &from_ybit);
2673: bmpch2bit(to, &to_xbit, &to_ybit);
2674:
2675: tp = bit2fbptr(to_xbit, to_ybit);
2676: fp = bit2fbptr(from_xbit, from_ybit);
2677:
2678: for (i = 0; i < char_height; ++i) {
2679: for (j = 0; j < char_byte_width; ++j)
2680: *(tp+j) = *(fp+j);
2681: tp += fb_byte_width;
2682: fp += fb_byte_width;
2683: }
2684: }
2685:
2686: /*
2687: * bmpvmup: Copy a block of character positions upwards.
2688: */
2689: void
2690: bmpmvup(from, to, count)
2691: csrpos_t from, to;
2692: int count;
2693: {
2694: short from_xbit, from_ybit;
2695: short to_xbit, to_ybit;
2696: short i;
2697:
2698: bmpch2bit(from, &from_xbit, &from_ybit);
2699: bmpch2bit(to, &to_xbit, &to_ybit);
2700:
2701: if (from_xbit == xstart && to_xbit == xstart && count%kd_cols == 0) {
2702: /* fast case - entire lines */
2703: from_xbit = to_xbit = 0;
2704: bmppaintcsr(kd_curpos, char_black); /* don't copy cursor */
2705: count /= kd_cols; /* num lines */
2706: count *= fb_byte_width * (char_height+cursor_height);
2707: kd_slmscu(bit2fbptr(from_xbit, from_ybit),
2708: bit2fbptr(to_xbit, to_ybit),
2709: count/SLAMBPW);
2710: bmppaintcsr(kd_curpos, char_white);
2711: } else {
2712: /* slow case - everything else */
2713: for (i=0; i < count; ++i) {
2714: bmpcp1char(from, to);
2715: from += ONE_SPACE;
2716: to += ONE_SPACE;
2717: }
2718: }
2719: }
2720:
2721: /*
2722: * bmpmvdown: copy a block of characters down.
2723: */
2724: void
2725: bmpmvdown(from, to, count)
2726: csrpos_t from, to;
2727: int count;
2728: {
2729: short from_xbit, from_ybit;
2730: short to_xbit, to_ybit;
2731: short i;
2732:
2733: bmpch2bit(from, &from_xbit, &from_ybit);
2734: bmpch2bit(to, &to_xbit, &to_ybit);
2735:
2736: if (from_xbit == xstart + (kd_cols - 1) * char_width
2737: && to_xbit == xstart + (kd_cols - 1) * char_width
2738: && count%kd_cols == 0) {
2739: /* fast case - entire lines*/
2740: from_xbit = to_xbit = 8 * (fb_byte_width - 1);
2741: /* last byte on line */
2742: bmppaintcsr(kd_curpos, char_black); /* don't copy cursor */
2743: count /= kd_cols; /* num lines */
2744: count *= fb_byte_width * (char_height+cursor_height);
2745: kd_slmscd(bit2fbptr(from_xbit, from_ybit),
2746: bit2fbptr(to_xbit, to_ybit),
2747: count/SLAMBPW);
2748: bmppaintcsr(kd_curpos, char_white);
2749: } else {
2750: /* slow case - everything else */
2751: for (i=0; i < count; ++i) {
2752: bmpcp1char(from, to);
2753: from -= ONE_SPACE;
2754: to -= ONE_SPACE;
2755: }
2756: }
2757: }
2758:
2759: /*
2760: * bmpclear: clear one or more character positions.
2761: */
2762: void
2763: bmpclear(to, count, chattr)
2764: csrpos_t to; /* 1st char */
2765: int count; /* num chars */
2766: char chattr; /* reverse or normal */
2767: {
2768: register short i;
2769: u_short clearval;
2770: u_short clearbyte = (chattr == KA_REVERSE ? char_white : char_black);
2771:
2772: clearval = (u_short)(clearbyte<<8) + clearbyte;
2773: if (to == 0 && count >= kd_lines * kd_cols) {
2774: /* fast case - entire page */
2775: kd_slmwd(vid_start, (fb_byte_width * fb_height)/SLAMBPW,
2776: clearval);
2777: } else
2778: /* slow case */
2779: for (i = 0; i < count; ++i) {
2780: bmpput(to, K_SPACE, chattr);
2781: to += ONE_SPACE;
2782: }
2783: }
2784:
2785: /*
2786: * bmpsetcursor: update the display and set the logical cursor.
2787: */
2788: void
2789: bmpsetcursor(pos)
2790: csrpos_t pos;
2791: {
2792: /* erase old cursor & paint new one */
2793: bmppaintcsr(kd_curpos, char_black);
2794: bmppaintcsr(pos, char_white);
2795: kd_curpos = pos;
2796: }
2797:
2798: /*
2799: * bmppaintcsr: paint cursor bits.
2800: */
2801: void
2802: bmppaintcsr(pos, val)
2803: csrpos_t pos;
2804: u_char val;
2805: {
2806: short xbit, ybit;
2807: register u_char *cp;
2808: register short line, byte;
2809:
2810: bmpch2bit(pos, &xbit, &ybit);
2811: ybit += char_height; /* position at bottom of line */
2812: cp = bit2fbptr(xbit, ybit);
2813: for (line = 0; line < cursor_height; ++line) {
2814: for (byte = 0; byte < char_byte_width; ++byte)
2815: *(cp+byte) = val;
2816: cp += fb_byte_width;
2817: }
2818: }
2819:
2820: /*
2821: * bmpch2bit: convert character position to x and y bit addresses.
2822: * (0, 0) is the upper left corner.
2823: */
2824: void
2825: bmpch2bit(pos, xb, yb)
2826: csrpos_t pos;
2827: short *xb, *yb; /* x, y bit positions, u/l corner */
2828: {
2829: register short xch, ych;
2830:
2831: xch = (pos / ONE_SPACE) % kd_cols;
2832: ych = pos / (ONE_SPACE * kd_cols);
2833: *xb = xstart + xch * char_width;
2834: *yb = ystart + ych * (char_height + cursor_height);
2835: }
2836:
2837: /*
2838: * bit2fbptr: return a pointer into the frame buffer corresponding to
2839: * the bit address (x, y).
2840: * Assumes that xb and yb don't point to the middle of a
2841: * byte.
2842: */
2843: u_char *
2844: bit2fbptr(xb, yb)
2845: short xb, yb;
2846: {
2847: return(vid_start + yb * fb_byte_width + xb/8);
2848: }
2849:
2850:
2851: /*
2852: * console stuff
2853: */
2854:
2855: /*
2856: * XXX we assume that pcs *always* have a console
2857: */
2858: int
2859: kdcnprobe(struct consdev *cp)
2860: {
2861: int maj, unit, pri;
2862:
2863: maj = 0;
2864: unit = 0;
2865: pri = CN_INTERNAL;
2866:
2867: cp->cn_dev = makedev(maj, unit);
2868: cp->cn_pri = pri;
2869: }
2870:
2871: int
2872: kdcninit(struct consdev *cp)
2873: {
2874: kdinit();
2875: return 0;
2876: }
2877:
2878: int
2879: kdcngetc(dev_t dev, int wait)
2880: {
2881: if (wait) {
2882: int c;
2883: while ((c = kdcnmaygetc()) < 0)
2884: continue;
2885: return c;
2886: }
2887: else
2888: return kdcnmaygetc();
2889: }
2890:
2891: int
2892: kdcnputc(dev_t dev, int c)
2893: {
2894: int i;
2895:
2896: if (!kd_initialized)
2897: return;
2898:
2899: /* Note that tab is handled in kd_putc */
2900: if (c == '\n')
2901: kd_putc('\r');
2902: kd_putc(c);
2903: }
2904:
2905: /*
2906: * kdcnmaygetc:
2907: *
2908: * Get one character using polling, rather than interrupts. Used
2909: * by the kernel debugger. Note that Caps Lock is ignored.
2910: * Normally this routine is called with interrupts already
2911: * disabled, but there is code in place so that it will be more
2912: * likely to work even if interrupts are turned on.
2913: */
2914: int
2915: kdcnmaygetc(void)
2916: {
2917: unsigned char c;
2918: unsigned char scancode;
2919: unsigned int char_idx;
2920: #ifdef notdef
2921: spl_t o_pri;
2922: #endif
2923: boolean_t up;
2924:
2925: if (! kd_initialized)
2926: return -1;
2927:
2928: kd_extended = FALSE;
2929: #ifdef notdef
2930: o_pri = splhi();
2931: #endif
2932: for ( ; ; ) {
2933: if (!(inb(K_STATUS) & K_OBUF_FUL))
2934: return -1;
2935:
2936: up = FALSE;
2937: /*
2938: * We'd come here for mouse events in debugger, if
2939: * the mouse were on.
2940: */
2941: if ((inb(K_STATUS) & 0x20) == 0x20) {
2942: printf("M%xP", inb(K_RDWR));
2943: continue;
2944: }
2945: scancode = inb(K_RDWR);
2946: /*
2947: * Handle extend modifier and
2948: * ack/resend, otherwise we may never receive
2949: * a key.
2950: */
2951: if (scancode == K_EXTEND) {
2952: kd_extended = TRUE;
2953: continue;
2954: } else if (scancode == K_RESEND) {
2955: printf("cngetc: resend");
2956: kd_resend();
2957: continue;
2958: } else if (scancode == K_ACKSC) {
2959: printf("cngetc: handle_ack");
2960: kd_handle_ack();
2961: continue;
2962: }
2963: if (scancode & K_UP) {
2964: up = TRUE;
2965: scancode &= ~K_UP;
2966: }
2967: if (kd_kbd_mouse)
2968: kd_kbd_magic(scancode);
2969: if (scancode < NUMKEYS) {
2970: /* Lookup in map, then process. */
2971: char_idx = kdstate2idx(kd_state, kd_extended);
2972: c = key_map[scancode][char_idx];
2973: if (c == K_SCAN) {
2974: c = key_map[scancode][++char_idx];
2975: kd_state = do_modifier(kd_state, c, up);
2976: #ifdef notdef
2977: cnsetleds(state2leds(kd_state));
2978: #endif
2979: } else if (!up) {
2980: /* regular key-down */
2981: if (c == K_CR)
2982: c = K_LF;
2983: #ifdef notdef
2984: splx(o_pri);
2985: #endif
2986: return(c & 0177);
2987: }
2988: }
2989: }
2990: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.