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