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