|
|
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;
1.1.1.3 root 1062:
1.1 root 1063: if (tp->t_state & TS_TTSTOP)
1064: return;
1065: for ( ; ; ) {
1.1.1.3 root 1066: tp->t_state &= ~TS_BUSY;
1.1 root 1067: if (tp->t_state & TS_TTSTOP)
1068: break;
1069: if ((tp->t_outq.c_cc <= 0) || (ch = getc(&tp->t_outq)) == -1)
1070: break;
1071: /*
1072: * Drop priority for long screen updates. ttstart() calls us at
1073: * spltty.
1074: */
1075: o_pri = splsoftclock(); /* block timeout */
1.1.1.6 ! root 1076: kd_putc_esc(ch);
1.1 root 1077: splx(o_pri);
1078: }
1079: if (tp->t_outq.c_cc <= TTLOWAT(tp)) {
1080: tt_write_wakeup(tp);
1081: }
1082: }
1083:
1084: /*ARGSUSED*/
1.1.1.4 root 1085: void
1.1.1.5 root 1086: kdstop(
1087: struct tty *tp,
1088: int flags)
1.1 root 1089: {
1090: /*
1091: * do nothing - all characters are output by one call to
1092: * kdstart.
1093: */
1094: }
1095:
1096: /*
1097: * kdinit:
1098: *
1099: * This code initializes the structures and sets up the port registers
1.1.1.3 root 1100: * for the console driver.
1.1 root 1101: *
1102: * Each bitmap-based graphics card is likely to require a unique
1103: * way to determine the card's presence. The driver runs through
1104: * each "special" card that it knows about and uses the first one
1105: * that it finds. If it doesn't find any, it assumes that an
1106: * EGA-like card is installed.
1107: *
1108: * input : None. Interrupts are assumed to be disabled
1109: * output : Driver is initialized
1110: *
1111: */
1.1.1.4 root 1112: void
1.1.1.5 root 1113: kdinit(void)
1.1 root 1114: {
1115: unsigned char k_comm; /* keyboard command byte */
1116:
1117: if (kd_initialized)
1118: return;
1119:
1120: esc_spt = esc_seq;
1121: kd_attr = KA_NORMAL;
1122:
1.1.1.3 root 1123: kd_attrflags = 0;
1124: kd_color = KA_NORMAL;
1.1 root 1125: /*
1126: * board specific initialization: set up globals and kd_dxxx
1127: * pointers, and synch displayed cursor with logical cursor.
1128: */
1.1.1.4 root 1129: kd_xga_init();
1.1 root 1130:
1131: /* get rid of any garbage in output buffer */
1132: if (inb(K_STATUS) & K_OBUF_FUL)
1133: (void)inb(K_RDWR);
1134:
1135: kd_sendcmd(KC_CMD_READ); /* ask for the ctlr command byte */
1136: k_comm = kd_getdata();
1137: k_comm &= ~K_CB_DISBLE; /* clear keyboard disable bit */
1138: k_comm |= K_CB_ENBLIRQ; /* enable interrupt */
1139: kd_sendcmd(KC_CMD_WRITE); /* write new ctlr command byte */
1140: kd_senddata(k_comm);
1141: kd_initialized = TRUE;
1142:
1.1.1.6 ! root 1143: #if ENABLE_IMMEDIATE_CONSOLE
1.1 root 1144: /* Now that we're set up, we no longer need or want the
1145: immediate console. */
1146: {
1.1.1.5 root 1147: extern boolean_t immediate_console_enable;
1148: immediate_console_enable = FALSE;
1.1 root 1149: }
1150:
1151: /* The immediate console printed stuff at the bottom of the
1152: screen rather than at the cursor position, so that's where
1153: we should start. */
1154: kd_setpos(ONE_PAGE - ONE_LINE); printf("\n");
1.1.1.5 root 1155: #endif /* ENABLE_IMMEDIATE_CONSOLE */
1.1 root 1156:
1157: cnsetleds(kd_state = KS_NORMAL);
1158: /* clear the LEDs AFTER we
1159: enable the keyboard controller.
1160: This keeps NUM-LOCK from being
1161: set on the NEC Versa. */
1.1.1.4 root 1162:
1163: /* Allocate the input buffer. */
1164: ttychars(&kd_tty);
1.1 root 1165: }
1166:
1167: /*
1168: * kd_belloff:
1169: *
1170: * This routine shuts the bell off, by sending the appropriate code
1171: * to the speaker port.
1172: *
1173: * input : None
1174: * output : bell is turned off
1175: *
1176: */
1.1.1.5 root 1177: static boolean_t kd_bellstate = FALSE;
1.1.1.4 root 1178:
1179: void
1180: kd_belloff(void * param)
1.1 root 1181: {
1182: unsigned char status;
1183:
1184: status = (inb(K_PORTB) & ~(K_SPKRDATA | K_ENABLETMR2));
1185: outb(K_PORTB, status);
1.1.1.5 root 1186: kd_bellstate = FALSE;
1.1 root 1187: return;
1188: }
1189:
1190:
1191: /*
1192: * kd_bellon:
1193: *
1194: * This routine turns the bell on.
1195: *
1196: * input : None
1197: * output : bell is turned on
1198: *
1199: */
1.1.1.4 root 1200: void
1.1.1.5 root 1201: kd_bellon(void)
1.1 root 1202: {
1203: unsigned char status;
1204:
1205: /* program timer 2 */
1206: outb(K_TMRCTL, K_SELTMR2 | K_RDLDTWORD | K_TSQRWAVE | K_TBINARY);
1207: outb(K_TMR2, 1500 & 0xff); /* LSB */
1208: outb(K_TMR2, (int)1500 >> 8); /* MSB */
1209:
1210: /* start speaker - why must we turn on K_SPKRDATA? */
1211: status = (inb(K_PORTB)| K_ENABLETMR2 | K_SPKRDATA);
1212: outb(K_PORTB, status);
1213: return;
1214: }
1215:
1216: /*
1217: *
1.1.1.6 ! root 1218: * Function kd_putc_esc():
! 1219: *
! 1220: * This function puts a character on the screen, handling escape
! 1221: * sequences.
! 1222: *
! 1223: * input : character to be displayed (or part of an escape code)
! 1224: * output : character is displayed, or some action is taken
! 1225: *
! 1226: */
! 1227: void
! 1228: kd_putc_esc(u_char c)
! 1229: {
! 1230: if (c == (K_ESC)) {
! 1231: if (esc_spt == esc_seq) {
! 1232: *(esc_spt++)=(K_ESC);
! 1233: *(esc_spt) = '\0';
! 1234: } else {
! 1235: kd_putc((K_ESC));
! 1236: esc_spt = esc_seq;
! 1237: }
! 1238: } else {
! 1239: if (esc_spt - esc_seq) {
! 1240: if (esc_spt - esc_seq > K_MAXESC - 1)
! 1241: esc_spt = esc_seq;
! 1242: else {
! 1243: *(esc_spt++) = c;
! 1244: *(esc_spt) = '\0';
! 1245: kd_parseesc();
! 1246: }
! 1247: } else {
! 1248: kd_putc(c);
! 1249: }
! 1250: }
! 1251: }
! 1252:
! 1253: /*
! 1254: *
1.1 root 1255: * Function kd_putc():
1256: *
1257: * This function simply puts a character on the screen. It does some
1258: * special processing for linefeed, carriage return, backspace and
1259: * the bell.
1260: *
1261: * input : character to be displayed
1262: * output : character is displayed, or some action is taken
1263: *
1264: */
1265: int sit_for_0 = 1;
1266:
1.1.1.4 root 1267: void
1.1.1.5 root 1268: kd_putc(u_char ch)
1.1 root 1269: {
1270: if ((!ch) && sit_for_0)
1271: return;
1272:
1.1.1.3 root 1273: switch (ch) {
1.1 root 1274: case ((K_LF)):
1275: kd_down();
1276: break;
1.1.1.3 root 1277: case ((K_CR)):
1.1 root 1278: kd_cr();
1279: break;
1280: case ((K_BS)):
1281: kd_left();
1282: break;
1283: case ((K_HT)):
1284: kd_tab();
1285: break;
1286: case ((K_BEL)):
1287: /*
1288: * Similar problem to K_BS here (behavior might depend
1289: * on tty setting). Also check LF and CR.
1290: */
1291: if (!kd_bellstate)
1292: {
1293: kd_bellon();
1294: timeout(kd_belloff, 0, hz/8 );
1.1.1.5 root 1295: kd_bellstate = TRUE;
1.1 root 1296: }
1297: break;
1298: default:
1299: (*kd_dput)(kd_curpos, ch, kd_attr);
1300: kd_right();
1301: break;
1302: }
1303: return;
1304: }
1305:
1306:
1307: /*
1308: * kd_setpos:
1309: *
1310: * This function sets the software and hardware cursor position
1311: * on the screen, using device-specific code to actually move and
1312: * display the cursor.
1313: *
1314: * input : position on (or off) screen to move the cursor to
1315: * output : cursor position is updated, screen has been scrolled
1316: * if necessary to bring cursor position back onto
1317: * screen.
1318: *
1319: */
1.1.1.4 root 1320: void
1.1.1.5 root 1321: kd_setpos(csrpos_t newpos)
1.1 root 1322: {
1323: if (newpos > ONE_PAGE) {
1324: kd_scrollup();
1325: newpos = BOTTOM_LINE;
1326: }
1327: if (newpos < 0) {
1328: kd_scrolldn();
1329: newpos = 0;
1330: }
1331:
1332: (*kd_dsetcursor)(newpos);
1333: }
1334:
1335:
1336: /*
1337: * kd_scrollup:
1338: *
1339: * This function scrolls the screen up one line using a DMA memory
1340: * copy.
1341: *
1342: * input : None
1343: * output : lines on screen appear to be shifted up one line
1344: *
1345: */
1.1.1.4 root 1346: void
1.1.1.5 root 1347: kd_scrollup(void)
1.1 root 1348: {
1349: csrpos_t to;
1350: csrpos_t from;
1351: int count;
1352:
1353: /* scroll up */
1354: to = 0;
1355: from = ONE_LINE;
1356: count = (ONE_PAGE - ONE_LINE)/ONE_SPACE;
1357: (*kd_dmvup)(from, to, count);
1358:
1359: /* clear bottom line */
1360: to = BOTTOM_LINE;
1361: count = ONE_LINE/ONE_SPACE;
1362: (*kd_dclear)(to, count, kd_attr);
1363: return;
1364: }
1365:
1366:
1367: /*
1368: * kd_scrolldn:
1369: *
1370: * Scrolls the characters on the screen down one line.
1371: *
1372: * input : None
1373: * output : Lines on screen appear to be moved down one line
1374: *
1375: */
1.1.1.4 root 1376: void
1.1.1.5 root 1377: kd_scrolldn(void)
1.1 root 1378: {
1379: csrpos_t to;
1380: csrpos_t from;
1381: int count;
1382:
1383: /* move down */
1384: to = ONE_PAGE - ONE_SPACE;
1385: from = ONE_PAGE - ONE_LINE - ONE_SPACE;
1386: count = (ONE_PAGE - ONE_LINE) / ONE_SPACE;
1387: (*kd_dmvdown)(from, to, count);
1388:
1389: /* clear top line */
1390: to = 0;
1391: count = ONE_LINE/ONE_SPACE;
1392: (*kd_dclear)(to, count, kd_attr);
1393: return;
1.1.1.3 root 1394:
1.1 root 1395: }
1396:
1397:
1398: /*
1399: * kd_parseesc:
1400: *
1401: * This routine begins the parsing of an escape sequence. It uses the
1.1.1.3 root 1402: * escape sequence array and the escape spot pointer to handle
1.1 root 1403: * asynchronous parsing of escape sequences.
1404: *
1405: * input : String of characters prepended by an escape
1406: * output : Appropriate actions are taken depending on the string as
1407: * defined by the ansi terminal specification
1408: *
1409: */
1.1.1.4 root 1410: void
1.1.1.5 root 1411: kd_parseesc(void)
1.1 root 1412: {
1413: u_char *escp;
1414:
1415: escp = esc_seq + 1; /* point to char following ESC */
1416: switch(*(escp)) {
1417: case 'c':
1418: kd_cls();
1419: kd_home();
1420: esc_spt = esc_seq; /* reset spot in ESC sequence */
1421: break;
1422: case '[':
1423: escp++;
1424: kd_parserest(escp);
1425: break;
1426: case '\0':
1427: break; /* not enough info yet */
1428: default:
1429: kd_putc(*escp);
1430: esc_spt = esc_seq; /* inv sequence char, reset */
1431: break;
1432: }
1433: return;
1434:
1435: }
1436:
1437:
1.1.1.3 root 1438: /* kd_update_kd_attr:
1439: *
1440: * Updates kd_attr according to kd_attrflags and kd_color.
1441: * This code has its origin from console.c and selection.h in
1442: * linux 2.2 drivers/char/.
1443: * Modified for GNU Mach by Marcus Brinkmann.
1444: */
1445:
1446: #define reverse_video_char(a) (((a) & 0x88) | ((((a) >> 4) | ((a) << 4)) & 0x77))
1447: void
1448: kd_update_kd_attr(void)
1449: {
1450: kd_attr = kd_color;
1451: if (kd_attrflags & KAX_UNDERLINE)
1452: kd_attr = (kd_attr & 0xf0) | KAX_COL_UNDERLINE;
1453: else if (kd_attrflags & KAX_DIM)
1454: kd_attr = (kd_attr & 0xf0) | KAX_COL_DIM;
1455: if (kd_attrflags & KAX_REVERSE)
1456: kd_attr = reverse_video_char(kd_attr);
1457: if (kd_attrflags & KAX_BLINK)
1458: kd_attr ^= 0x80;
1459: if (kd_attrflags & KAX_BOLD)
1460: kd_attr ^= 0x08;
1461: }
1462:
1463: /* color_table added by Julio Merino to take proper color order.
1464: * I get this code from Linux 2.2 source code in file:
1465: * linux/drivers/char/console.c
1466: */
1467: unsigned char color_table[] = { 0, 4, 2, 6, 1, 5, 3, 7,
1468: 8,12,10,14, 9,13,11,15 };
1.1 root 1469: /*
1470: * kd_parserest:
1471: *
1472: * This function will complete the parsing of an escape sequence and
1473: * call the appropriate support routine if it matches a character. This
1474: * function could be greatly improved by using a function jump table, and
1475: * removing this bulky switch statement.
1476: *
1477: * input : An string
1478: * output : Appropriate action based on whether the string matches a
1479: * sequence acceptable to the ansi terminal specification
1480: *
1481: */
1.1.1.4 root 1482: void
1.1.1.5 root 1483: kd_parserest(u_char *cp)
1.1 root 1484: {
1.1.1.3 root 1485: int number[16], npar = 0, i;
1.1 root 1486: csrpos_t newpos;
1487:
1.1.1.3 root 1488: for(i=0;i<=15;i++)
1.1.1.4 root 1489: number[i] = MACH_ATOI_DEFAULT;
1.1.1.3 root 1490:
1491: do {
1.1.1.4 root 1492: cp += mach_atoi(cp, &number[npar]);
1.1.1.3 root 1493: } while (*cp == ';' && ++npar <= 15 && cp++);
1494:
1.1 root 1495: switch(*cp) {
1496: case 'm':
1.1.1.3 root 1497: for (i=0;i<=npar;i++)
1498: switch(number[i]) {
1.1.1.4 root 1499: case MACH_ATOI_DEFAULT:
1.1.1.3 root 1500: case 0:
1501: kd_attrflags = 0;
1502: kd_color = KA_NORMAL;
1503: break;
1504: case 1:
1505: kd_attrflags |= KAX_BOLD;
1506: kd_attrflags &= ~KAX_DIM;
1507: break;
1508: case 2:
1509: kd_attrflags |= KAX_DIM;
1510: kd_attrflags &= ~KAX_BOLD;
1511: break;
1512: case 4:
1513: kd_attrflags |= KAX_UNDERLINE;
1514: break;
1515: case 5:
1516: kd_attrflags |= KAX_BLINK;
1517: break;
1518: case 7:
1519: kd_attrflags |= KAX_REVERSE;
1520: break;
1521: case 8:
1522: kd_attrflags |= KAX_INVISIBLE;
1523: break;
1524: case 21:
1525: case 22:
1526: kd_attrflags &= ~(KAX_BOLD | KAX_DIM);
1527: break;
1528: case 24:
1529: kd_attrflags &= ~KAX_UNDERLINE;
1530: break;
1531: case 25:
1532: kd_attrflags &= ~KAX_BLINK;
1533: break;
1534: case 27:
1535: kd_attrflags &= ~KAX_REVERSE;
1536: break;
1537: case 38:
1538: kd_attrflags |= KAX_UNDERLINE;
1539: kd_color = (kd_color & 0xf0) | (KA_NORMAL & 0x0f);
1540: break;
1541: case 39:
1542: kd_attrflags &= ~KAX_UNDERLINE;
1543: kd_color = (kd_color & 0xf0) | (KA_NORMAL & 0x0f);
1544: break;
1545: default:
1546: if (number[i] >= 30 && number[i] <= 37) {
1547: /* foreground color */
1548: kd_color = (kd_color & 0xf0) | color_table[(number[i] - 30)];
1549: } else if (number[i] >= 40 && number[i] <= 47) {
1550: /* background color */
1551: kd_color = (kd_color & 0x0f) | (color_table[(number[i] - 40)] << 4);
1552: }
1553: break;
1554: }
1555: kd_update_kd_attr();
1.1 root 1556: esc_spt = esc_seq;
1557: break;
1558: case '@':
1.1.1.4 root 1559: if (number[0] == MACH_ATOI_DEFAULT)
1.1 root 1560: kd_insch(1);
1561: else
1.1.1.3 root 1562: kd_insch(number[0]);
1.1 root 1563: esc_spt = esc_seq;
1564: break;
1565: case 'A':
1.1.1.4 root 1566: if (number[0] == MACH_ATOI_DEFAULT)
1.1 root 1567: kd_up();
1568: else
1.1.1.3 root 1569: while (number[0]--)
1.1 root 1570: kd_up();
1571: esc_spt = esc_seq;
1572: break;
1573: case 'B':
1.1.1.4 root 1574: if (number[0] == MACH_ATOI_DEFAULT)
1.1 root 1575: kd_down();
1576: else
1.1.1.3 root 1577: while (number[0]--)
1.1 root 1578: kd_down();
1579: esc_spt = esc_seq;
1580: break;
1581: case 'C':
1.1.1.4 root 1582: if (number[0] == MACH_ATOI_DEFAULT)
1.1 root 1583: kd_right();
1584: else
1.1.1.3 root 1585: while (number[0]--)
1.1 root 1586: kd_right();
1587: esc_spt = esc_seq;
1588: break;
1589: case 'D':
1.1.1.4 root 1590: if (number[0] == MACH_ATOI_DEFAULT)
1.1 root 1591: kd_left();
1592: else
1.1.1.3 root 1593: while (number[0]--)
1.1 root 1594: kd_left();
1595: esc_spt = esc_seq;
1596: break;
1597: case 'E':
1598: kd_cr();
1.1.1.4 root 1599: if (number[0] == MACH_ATOI_DEFAULT)
1.1 root 1600: kd_down();
1601: else
1.1.1.3 root 1602: while (number[0]--)
1.1 root 1603: kd_down();
1604: esc_spt = esc_seq;
1605: break;
1606: case 'F':
1607: kd_cr();
1.1.1.4 root 1608: if (number[0] == MACH_ATOI_DEFAULT)
1.1 root 1609: kd_up();
1610: else
1.1.1.3 root 1611: while (number[0]--)
1.1 root 1612: kd_up();
1613: esc_spt = esc_seq;
1614: break;
1615: case 'G':
1.1.1.4 root 1616: if (number[0] == MACH_ATOI_DEFAULT)
1.1.1.3 root 1617: number[0] = 0;
1.1 root 1618: else
1.1.1.3 root 1619: if (number[0] > 0)
1620: --number[0]; /* because number[0] is from 1 */
1621: kd_setpos(BEG_OF_LINE(kd_curpos) + number[0] * ONE_SPACE);
1.1 root 1622: esc_spt = esc_seq;
1623: break;
1.1.1.3 root 1624: case 'f':
1625: case 'H':
1.1.1.4 root 1626: if (number[0] == MACH_ATOI_DEFAULT && number[1] == MACH_ATOI_DEFAULT)
1.1.1.3 root 1627: {
1628: kd_home();
1629: esc_spt = esc_seq;
1630: break;
1631: }
1.1.1.4 root 1632: if (number[0] == MACH_ATOI_DEFAULT)
1.1.1.3 root 1633: number[0] = 0;
1634: else if (number[0] > 0)
1635: --number[0]; /* numbered from 1 */
1636: newpos = (number[0] * ONE_LINE); /* setup row */
1.1.1.4 root 1637: if (number[1] == MACH_ATOI_DEFAULT)
1.1.1.3 root 1638: number[1] = 0;
1639: else if (number[1] > 0)
1640: number[1]--;
1641: newpos += (number[1] * ONE_SPACE); /* setup column */
1.1 root 1642: if (newpos < 0)
1643: newpos = 0; /* upper left */
1644: if (newpos > ONE_PAGE)
1.1.1.3 root 1645: newpos = (ONE_PAGE - ONE_SPACE); /* lower right */
1646: kd_setpos(newpos);
1647: esc_spt = esc_seq;
1.1 root 1648: break; /* done or not ready */
1649: case 'J':
1.1.1.3 root 1650: switch(number[0]) {
1.1.1.4 root 1651: case MACH_ATOI_DEFAULT:
1.1 root 1652: case 0:
1653: kd_cltobcur(); /* clears from current
1654: pos to bottom.
1.1.1.3 root 1655: */
1.1 root 1656: break;
1657: case 1:
1658: kd_cltopcur(); /* clears from top to
1659: current pos.
1.1.1.3 root 1660: */
1.1 root 1661: break;
1662: case 2:
1663: kd_cls();
1664: break;
1665: default:
1666: break;
1667: }
1668: esc_spt = esc_seq; /* reset it */
1669: break;
1670: case 'K':
1.1.1.3 root 1671: switch(number[0]) {
1.1.1.4 root 1672: case MACH_ATOI_DEFAULT:
1.1 root 1673: case 0:
1674: kd_cltoecur(); /* clears from current
1675: pos to eoln.
1.1.1.3 root 1676: */
1.1 root 1677: break;
1678: case 1:
1679: kd_clfrbcur(); /* clears from begin
1680: of line to current
1681: pos.
1682: */
1683: break;
1684: case 2:
1685: kd_eraseln(); /* clear entire line */
1686: break;
1687: default:
1688: break;
1689: }
1690: esc_spt = esc_seq;
1691: break;
1692: case 'L':
1.1.1.4 root 1693: if (number[0] == MACH_ATOI_DEFAULT)
1.1 root 1694: kd_insln(1);
1695: else
1.1.1.3 root 1696: kd_insln(number[0]);
1.1 root 1697: esc_spt = esc_seq;
1698: break;
1699: case 'M':
1.1.1.4 root 1700: if (number[0] == MACH_ATOI_DEFAULT)
1.1 root 1701: kd_delln(1);
1702: else
1.1.1.3 root 1703: kd_delln(number[0]);
1.1 root 1704: esc_spt = esc_seq;
1705: break;
1706: case 'P':
1.1.1.4 root 1707: if (number[0] == MACH_ATOI_DEFAULT)
1.1 root 1708: kd_delch(1);
1709: else
1.1.1.3 root 1710: kd_delch(number[0]);
1.1 root 1711: esc_spt = esc_seq;
1712: break;
1713: case 'S':
1.1.1.4 root 1714: if (number[0] == MACH_ATOI_DEFAULT)
1.1 root 1715: kd_scrollup();
1716: else
1.1.1.3 root 1717: while (number[0]--)
1.1 root 1718: kd_scrollup();
1719: esc_spt = esc_seq;
1720: break;
1721: case 'T':
1.1.1.4 root 1722: if (number[0] == MACH_ATOI_DEFAULT)
1.1 root 1723: kd_scrolldn();
1724: else
1.1.1.3 root 1725: while (number[0]--)
1.1 root 1726: kd_scrolldn();
1727: esc_spt = esc_seq;
1728: break;
1729: case 'X':
1.1.1.4 root 1730: if (number[0] == MACH_ATOI_DEFAULT)
1.1 root 1731: kd_erase(1);
1732: else
1.1.1.3 root 1733: kd_erase(number[0]);
1.1 root 1734: esc_spt = esc_seq;
1.1.1.3 root 1735: break;
1.1 root 1736: case '\0':
1737: break; /* not enough yet */
1738: default:
1739: kd_putc(*cp); /* show inv character */
1740: esc_spt = esc_seq; /* inv entry, reset */
1741: break;
1742: }
1743: return;
1744: }
1745:
1.1.1.4 root 1746: void
1.1.1.5 root 1747: kd_tab(void)
1.1 root 1748: {
1749: int i;
1750:
1751: for (i = 8 - (CURRENT_COLUMN(kd_curpos) % 8); i > 0; i--) {
1752: kd_putc(' ');
1753: }
1754:
1755: }
1756:
1757:
1758: /*
1759: * kd_cls:
1760: *
1761: * This function clears the screen with spaces and the current attribute.
1762: *
1763: * input : None
1764: * output : Screen is cleared
1765: *
1766: */
1.1.1.4 root 1767: void
1.1.1.5 root 1768: kd_cls(void)
1.1 root 1769: {
1770: (*kd_dclear)(0, ONE_PAGE/ONE_SPACE, kd_attr);
1771: return;
1772: }
1773:
1774:
1775: /*
1776: * kd_home:
1777: *
1778: * This function will move the cursor to the home position on the screen,
1779: * as well as set the internal cursor position (kd_curpos) to home.
1780: *
1781: * input : None
1782: * output : Cursor position is moved
1783: *
1784: */
1.1.1.4 root 1785: void
1.1.1.5 root 1786: kd_home(void)
1.1 root 1787: {
1788: kd_setpos(0);
1789: return;
1790: }
1791:
1792:
1793: /*
1794: * kd_up:
1795: *
1796: * This function moves the cursor up one line position.
1797: *
1798: * input : None
1799: * output : Cursor moves up one line, or screen is scrolled
1800: *
1801: */
1.1.1.4 root 1802: void
1.1.1.5 root 1803: kd_up(void)
1.1 root 1804: {
1805: if (kd_curpos < ONE_LINE)
1806: kd_scrolldn();
1807: else
1808: kd_setpos(kd_curpos - ONE_LINE);
1809: return;
1810: }
1811:
1812:
1813: /*
1814: * kd_down:
1815: *
1816: * This function moves the cursor down one line position.
1817: *
1818: * input : None
1819: * output : Cursor moves down one line or the screen is scrolled
1820: *
1821: */
1.1.1.4 root 1822: void
1.1.1.5 root 1823: kd_down(void)
1.1 root 1824: {
1825: if (kd_curpos >= (ONE_PAGE - ONE_LINE))
1826: kd_scrollup();
1827: else
1828: kd_setpos(kd_curpos + ONE_LINE);
1829: return;
1830: }
1831:
1832:
1833: /*
1834: * kd_right:
1835: *
1836: * This function moves the cursor one position to the right.
1837: *
1838: * input : None
1839: * output : Cursor moves one position to the right
1840: *
1841: */
1.1.1.4 root 1842: void
1.1.1.5 root 1843: kd_right(void)
1.1 root 1844: {
1845: if (kd_curpos < (ONE_PAGE - ONE_SPACE))
1846: kd_setpos(kd_curpos + ONE_SPACE);
1847: else {
1848: kd_scrollup();
1849: kd_setpos(BEG_OF_LINE(kd_curpos));
1850: }
1851: return;
1852: }
1853:
1854:
1855: /*
1856: * kd_left:
1857: *
1858: * This function moves the cursor one position to the left.
1859: *
1860: * input : None
1861: * output : Cursor moves one position to the left
1862: *
1863: */
1.1.1.4 root 1864: void
1.1.1.5 root 1865: kd_left(void)
1.1 root 1866: {
1867: if (0 < kd_curpos)
1868: kd_setpos(kd_curpos - ONE_SPACE);
1869: return;
1870: }
1871:
1872:
1873: /*
1874: * kd_cr:
1875: *
1876: * This function moves the cursor to the beginning of the current
1877: * line.
1878: *
1879: * input : None
1880: * output : Cursor moves to the beginning of the current line
1881: *
1882: */
1.1.1.4 root 1883: void
1.1.1.5 root 1884: kd_cr(void)
1.1 root 1885: {
1886: kd_setpos(BEG_OF_LINE(kd_curpos));
1887: return;
1888: }
1889:
1890:
1891: /*
1892: * kd_cltobcur:
1893: *
1894: * This function clears from the current cursor position to the bottom
1895: * of the screen.
1896: *
1897: * input : None
1.1.1.5 root 1898: * output : Screen is cleared from current cursor position to bottom
1.1 root 1899: *
1900: */
1.1.1.4 root 1901: void
1.1.1.5 root 1902: kd_cltobcur(void)
1.1 root 1903: {
1904: csrpos_t start;
1905: int count;
1906:
1907: start = kd_curpos;
1908: count = (ONE_PAGE - kd_curpos)/ONE_SPACE;
1909: (*kd_dclear)(start, count, kd_attr);
1910: return;
1911: }
1912:
1913:
1914: /*
1915: * kd_cltopcur:
1916: *
1917: * This function clears from the current cursor position to the top
1918: * of the screen.
1919: *
1920: * input : None
1.1.1.5 root 1921: * output : Screen is cleared from current cursor position to top
1.1 root 1922: *
1923: */
1.1.1.4 root 1924: void
1.1.1.5 root 1925: kd_cltopcur(void)
1.1 root 1926: {
1927: int count;
1928:
1929: count = (kd_curpos + ONE_SPACE) / ONE_SPACE;
1930: (*kd_dclear)(0, count, kd_attr);
1931: return;
1932: }
1933:
1934:
1935: /*
1936: * kd_cltoecur:
1937: *
1.1.1.3 root 1938: * This function clears from the current cursor position to eoln.
1.1 root 1939: *
1940: * input : None
1941: * output : Line is cleared from current cursor position to eoln
1942: *
1943: */
1.1.1.4 root 1944: void
1.1.1.5 root 1945: kd_cltoecur(void)
1.1 root 1946: {
1947: csrpos_t i;
1948: csrpos_t hold;
1949:
1950: hold = BEG_OF_LINE(kd_curpos) + ONE_LINE;
1951: for (i = kd_curpos; i < hold; i += ONE_SPACE) {
1952: (*kd_dput)(i, K_SPACE, kd_attr);
1953: }
1954: }
1955:
1956:
1957: /*
1958: * kd_clfrbcur:
1959: *
1960: * This function clears from the beginning of the line to the current
1961: * cursor position.
1962: *
1963: * input : None
1964: * output : Line is cleared from beginning to current position
1965: *
1966: */
1.1.1.4 root 1967: void
1.1.1.5 root 1968: kd_clfrbcur(void)
1.1 root 1969: {
1970: csrpos_t i;
1971:
1972: for (i = BEG_OF_LINE(kd_curpos); i <= kd_curpos; i += ONE_SPACE) {
1973: (*kd_dput)(i, K_SPACE, kd_attr);
1974: }
1975: }
1976:
1977:
1978: /*
1979: * kd_delln:
1980: *
1981: * This function deletes 'number' lines on the screen by effectively
1982: * scrolling the lines up and replacing the old lines with spaces.
1983: *
1984: * input : number of lines to delete
1985: * output : lines appear to be deleted
1986: *
1987: */
1.1.1.4 root 1988: void
1.1.1.5 root 1989: kd_delln(int number)
1.1 root 1990: {
1991: csrpos_t to;
1992: csrpos_t from;
1993: int delbytes; /* num of bytes to delete */
1994: int count; /* num of words to move or fill */
1995:
1996: if (number <= 0)
1997: return;
1998:
1999: delbytes = number * ONE_LINE;
2000: to = BEG_OF_LINE(kd_curpos);
2001: if (to + delbytes >= ONE_PAGE)
2002: delbytes = ONE_PAGE - to;
2003: if (to + delbytes < ONE_PAGE) {
2004: from = to + delbytes;
2005: count = (ONE_PAGE - from) / ONE_SPACE;
2006: (*kd_dmvup)(from, to, count);
2007: }
2008:
2009: to = ONE_PAGE - delbytes;
2010: count = delbytes / ONE_SPACE;
2011: (*kd_dclear)(to, count, kd_attr);
2012: return;
2013: }
2014:
2015:
2016: /*
2017: * kd_insln:
2018: *
2019: * This function inserts a line above the current one by
2020: * scrolling the current line and all the lines below it down.
2021: *
2022: * input : number of lines to insert
2023: * output : New lines appear to be inserted
2024: *
2025: */
1.1.1.4 root 2026: void
1.1.1.5 root 2027: kd_insln(int number)
1.1 root 2028: {
2029: csrpos_t to;
2030: csrpos_t from;
2031: int count;
2032: csrpos_t top; /* top of block to be moved */
2033: int insbytes; /* num of bytes inserted */
2034:
2035: if (number <= 0)
2036: return;
2037:
2038: top = BEG_OF_LINE(kd_curpos);
2039: insbytes = number * ONE_LINE;
2040: if (top + insbytes > ONE_PAGE)
2041: insbytes = ONE_PAGE - top;
2042: to = ONE_PAGE - ONE_SPACE;
2043: from = to - insbytes;
2044: if (from > top) {
2045: count = (from - top + ONE_SPACE) / ONE_SPACE;
2046: (*kd_dmvdown)(from, to, count);
2047: }
2048:
2049: count = insbytes / ONE_SPACE;
2050: (*kd_dclear)(top, count, kd_attr);
2051: return;
2052: }
2053:
2054:
2055: /*
2056: * kd_delch:
2057: *
1.1.1.3 root 2058: * This function deletes a number of characters from the current
1.1 root 2059: * position in the line.
2060: *
2061: * input : number of characters to delete
2062: * output : characters appear to be deleted
2063: *
2064: */
1.1.1.4 root 2065: void
1.1.1.5 root 2066: kd_delch(int number)
1.1 root 2067: {
1.1.1.5 root 2068: int count; /* num words moved/filled */
2069: int delbytes; /* bytes to delete */
2070: csrpos_t to;
1.1 root 2071: csrpos_t from;
2072: csrpos_t nextline; /* start of next line */
2073:
2074: if (number <= 0)
2075: return;
2076:
2077: nextline = BEG_OF_LINE(kd_curpos) + ONE_LINE;
2078: delbytes = number * ONE_SPACE;
2079: if (kd_curpos + delbytes > nextline)
2080: delbytes = nextline - kd_curpos;
2081: if (kd_curpos + delbytes < nextline) {
2082: from = kd_curpos + delbytes;
2083: to = kd_curpos;
2084: count = (nextline - from) / ONE_SPACE;
2085: (*kd_dmvup)(from, to, count);
2086: }
2087:
2088: to = nextline - delbytes;
2089: count = delbytes / ONE_SPACE;
2090: (*kd_dclear)(to, count, kd_attr);
2091: return;
2092:
2093: }
2094:
2095:
2096: /*
2097: * kd_erase:
2098: *
2099: * This function overwrites characters with a space starting with the
2100: * current cursor position and ending in number spaces away.
2101: *
2102: * input : number of characters to erase
2103: * output : characters appear to be blanked or erased
2104: *
2105: */
1.1.1.4 root 2106: void
1.1.1.5 root 2107: kd_erase(int number)
1.1 root 2108: {
2109: csrpos_t i;
2110: csrpos_t stop;
2111:
1.1.1.3 root 2112: stop = kd_curpos + (ONE_SPACE * number);
1.1 root 2113: if (stop > BEG_OF_LINE(kd_curpos) + ONE_LINE)
2114: stop = BEG_OF_LINE(kd_curpos) + ONE_LINE;
2115: for (i = kd_curpos; i < stop; i += ONE_SPACE) {
2116: (*kd_dput)(i, K_SPACE, kd_attr);
2117: }
2118: return;
2119: }
2120:
2121:
2122: /*
2123: * kd_eraseln:
2124: *
2125: * This function erases the current line with spaces.
2126: *
2127: * input : None
2128: * output : Current line is erased
2129: *
2130: */
1.1.1.4 root 2131: void
1.1.1.5 root 2132: kd_eraseln(void)
1.1 root 2133: {
2134: csrpos_t i;
2135: csrpos_t stop;
2136:
2137: stop = BEG_OF_LINE(kd_curpos) + ONE_LINE;
1.1.1.3 root 2138: for (i = BEG_OF_LINE(kd_curpos); i < stop; i += ONE_SPACE) {
1.1 root 2139: (*kd_dput)(i, K_SPACE, kd_attr);
2140: }
2141: return;
2142: }
2143:
2144:
2145: /*
2146: * kd_insch:
2147: *
2148: * This function inserts a blank at the current cursor position
2149: * and moves all other characters on the line over.
2150: *
2151: * input : number of blanks to insert
2152: * output : Blanks are inserted at cursor position
2153: *
2154: */
1.1.1.4 root 2155: void
1.1.1.5 root 2156: kd_insch(int number)
1.1 root 2157: {
2158: csrpos_t to;
2159: csrpos_t from;
2160: int count;
2161: csrpos_t nextline; /* start of next line */
2162: int insbytes; /* num of bytes inserted */
2163:
2164: if (number <= 0)
2165: return;
2166:
2167: nextline = BEG_OF_LINE(kd_curpos) + ONE_LINE;
2168: insbytes = number * ONE_SPACE;
2169: if (kd_curpos + insbytes > nextline)
2170: insbytes = nextline - kd_curpos;
2171:
2172: to = nextline - ONE_SPACE;
2173: from = to - insbytes;
2174: if (from >= kd_curpos) {
2175: count = (from - kd_curpos + ONE_SPACE) / ONE_SPACE;
2176: (*kd_dmvdown)(from, to, count);
2177: }
2178:
2179: count = insbytes / ONE_SPACE;
2180: (*kd_dclear)(kd_curpos, count, kd_attr);
2181: return;
2182: }
2183:
2184:
2185: /*
2186: * kd_isupper, kd_islower:
2187: *
2188: * Didn't want to include ctype.h because it brings in stdio.h, and
2189: * only want to see if the darn character is uppercase or lowercase.
2190: *
2191: * input : Character 'c'
2192: * output : isuuper gives TRUE if character is uppercase, islower
2193: * returns TRUE if character is lowercase
2194: *
2195: */
1.1.1.4 root 2196: boolean_t
1.1.1.5 root 2197: kd_isupper(u_char c)
1.1 root 2198: {
2199: if (('A' <= c) && (c <= 'Z'))
2200: return(TRUE);
2201: return(FALSE);
2202: }
2203:
1.1.1.4 root 2204: boolean_t
1.1.1.5 root 2205: kd_islower(u_char c)
1.1 root 2206: {
2207: if (('a' <= c) && (c <= 'z'))
2208: return(TRUE);
2209: return(FALSE);
2210: }
2211:
2212: /*
2213: * kd_senddata:
2214: *
2215: * This function sends a byte to the keyboard RDWR port, but
2216: * first waits until the input/output data buffer is clear before
2217: * sending the data. Note that this byte can be either data or a
2218: * keyboard command.
2219: *
2220: */
1.1.1.4 root 2221: void
1.1.1.5 root 2222: kd_senddata(unsigned char ch)
1.1 root 2223: {
1.1.1.5 root 2224: while (inb(K_STATUS) & K_IBUF_FUL)
2225: ;
1.1 root 2226: outb(K_RDWR, ch);
2227: last_sent = ch;
2228: return;
2229: }
2230:
2231: /*
2232: * kd_sendcmd:
2233: *
2234: * This function sends a command byte to the keyboard command
2235: * port, but first waits until the input/output data buffer is
2236: * clear before sending the data.
2237: *
2238: */
1.1.1.4 root 2239: void
1.1.1.5 root 2240: kd_sendcmd(unsigned char ch)
1.1 root 2241: {
1.1.1.5 root 2242: while (inb(K_STATUS) & K_IBUF_FUL)
2243: ;
1.1 root 2244: outb(K_CMD, ch);
2245: return;
2246: }
2247:
2248:
1.1.1.3 root 2249: /*
1.1 root 2250: * kd_getdata:
1.1.1.3 root 2251: *
2252: * This function returns a data byte from the keyboard RDWR port,
2253: * after waiting until the port is flagged as having something to
2254: * read.
1.1 root 2255: */
2256: unsigned char
1.1.1.5 root 2257: kd_getdata(void)
1.1 root 2258: {
1.1.1.5 root 2259: while ((inb(K_STATUS) & K_OBUF_FUL) == 0)
2260: ;
1.1 root 2261: return(inb(K_RDWR));
2262: }
2263:
1.1.1.4 root 2264: unsigned char
1.1.1.5 root 2265: kd_cmdreg_read(void)
1.1 root 2266: {
2267: int ch=KC_CMD_READ;
2268:
1.1.1.5 root 2269: while (inb(K_STATUS) & K_IBUF_FUL)
2270: ;
1.1 root 2271: outb(K_CMD, ch);
2272:
1.1.1.5 root 2273: while ((inb(K_STATUS) & K_OBUF_FUL) == 0)
2274: ;
1.1 root 2275: return(inb(K_RDWR));
2276: }
2277:
1.1.1.4 root 2278: void
1.1.1.5 root 2279: kd_cmdreg_write(int val)
1.1 root 2280: {
2281: int ch=KC_CMD_WRITE;
2282:
1.1.1.5 root 2283: while (inb(K_STATUS) & K_IBUF_FUL)
2284: ;
1.1 root 2285: outb(K_CMD, ch);
2286:
1.1.1.5 root 2287: while (inb(K_STATUS) & K_IBUF_FUL)
2288: ;
1.1 root 2289: outb(K_RDWR, val);
2290: }
2291:
1.1.1.4 root 2292: void
1.1.1.5 root 2293: kd_mouse_drain(void)
1.1 root 2294: {
2295: int i;
1.1.1.5 root 2296: while(inb(K_STATUS) & K_IBUF_FUL)
2297: ;
1.1 root 2298: while((i = inb(K_STATUS)) & K_OBUF_FUL)
2299: printf("kbd: S = %x D = %x\n", i, inb(K_RDWR));
2300: }
2301:
1.1.1.3 root 2302: /*
1.1 root 2303: * set_kd_state:
1.1.1.3 root 2304: *
1.1 root 2305: * Set kd_state and update the keyboard status LEDs.
2306: */
1.1.1.4 root 2307: void
1.1.1.5 root 2308: set_kd_state(int newstate)
1.1 root 2309: {
2310: kd_state = newstate;
2311: kd_setleds1(state2leds(newstate));
2312: }
2313:
1.1.1.3 root 2314: /*
1.1 root 2315: * state2leds:
1.1.1.3 root 2316: *
2317: * Return a byte containing LED settings for the keyboard, given
1.1 root 2318: * a state vector.
2319: */
2320: u_char
1.1.1.5 root 2321: state2leds(int state)
1.1 root 2322: {
2323: u_char result = 0;
2324:
2325: if (state & KS_NLKED)
2326: result |= K_LED_NUMLK;
2327: if (state & KS_CLKED)
2328: result |= K_LED_CAPSLK;
2329: return(result);
2330: }
2331:
1.1.1.3 root 2332: /*
1.1 root 2333: * kd_setleds[12]:
1.1.1.3 root 2334: *
2335: * Set the keyboard LEDs according to the given byte.
1.1 root 2336: */
1.1.1.4 root 2337: void
1.1.1.5 root 2338: kd_setleds1(u_char val)
1.1 root 2339: {
2340: if (kd_ack != NOT_WAITING) {
1.1.1.4 root 2341: #ifdef MACH_KBD
1.1 root 2342: printf("kd_setleds1: unexpected state (%d)\n", kd_ack);
1.1.1.4 root 2343: #endif
1.1 root 2344: return;
2345: }
2346:
2347: kd_ack = SET_LEDS;
2348: kd_nextled = val;
2349: kd_senddata(K_CMD_LEDS);
2350: }
2351:
1.1.1.4 root 2352: void
1.1.1.5 root 2353: kd_setleds2(void)
1.1 root 2354: {
2355: kd_senddata(kd_nextled);
2356: }
2357:
2358:
1.1.1.3 root 2359: /*
1.1 root 2360: * cnsetleds:
1.1.1.3 root 2361: *
1.1 root 2362: * like kd_setleds[12], but not interrupt-based.
1.1.1.3 root 2363: * Currently disabled because cngetc ignores caps lock and num
1.1 root 2364: * lock anyway.
2365: */
1.1.1.4 root 2366: void
1.1.1.5 root 2367: cnsetleds(u_char val)
1.1 root 2368: {
2369: kd_senddata(K_CMD_LEDS);
2370: (void)kd_getdata(); /* XXX - assume is ACK */
2371: kd_senddata(val);
2372: (void)kd_getdata(); /* XXX - assume is ACK */
2373: }
2374:
1.1.1.4 root 2375: void
1.1.1.5 root 2376: kdreboot(void)
1.1 root 2377: {
2378: (*kd_dreset)();
2379:
2380: #ifndef BROKEN_KEYBOARD_RESET
2381: kd_sendcmd(0xFE); /* XXX - magic # */
2382: delay(1000000); /* wait to see if anything happens */
2383: #endif
1.1.1.3 root 2384: /*
1.1 root 2385: * If that didn't work, then we'll just have to try and
1.1.1.3 root 2386: * do it the hard way.
1.1 root 2387: */
2388: cpu_shutdown();
2389: }
2390:
2391: static int which_button[] = {0, MOUSE_LEFT, MOUSE_MIDDLE, MOUSE_RIGHT};
2392: static struct mouse_motion moved;
2393:
1.1.1.4 root 2394: int
1.1.1.5 root 2395: kd_kbd_magic(int scancode)
1.1 root 2396: {
2397: int new_button = 0;
2398:
2399: if (kd_kbd_mouse == 2)
2400: printf("sc = %x\n", scancode);
2401:
2402: switch (scancode) {
2403: /* f1 f2 f3 */
2404: case 0x3d:
2405: new_button++;
2406: case 0x3c:
2407: new_button++;
2408: case 0x3b:
2409: new_button++;
2410: if (kd_kbd_magic_button && (new_button != kd_kbd_magic_button)) {
2411: /* down w/o up */
2412: mouse_button(which_button[kd_kbd_magic_button], 1);
2413: }
2414: /* normal */
2415: if (kd_kbd_magic_button == new_button) {
2416: mouse_button(which_button[new_button], 1);
2417: kd_kbd_magic_button = 0;
2418: } else {
2419: mouse_button(which_button[new_button], 0);
2420: kd_kbd_magic_button = new_button;
2421: }
2422: break;
2423:
2424: /* right left up down */
2425: case 0x4d:
2426: moved.mm_deltaX = kd_kbd_magic_scale;
2427: moved.mm_deltaY = 0;
2428: mouse_moved(moved);
2429: break;
2430: case 0x4b:
2431: moved.mm_deltaX = -kd_kbd_magic_scale;
2432: moved.mm_deltaY = 0;
2433: mouse_moved(moved);
2434: break;
2435: case 0x48:
2436: moved.mm_deltaX = 0;
2437: moved.mm_deltaY = kd_kbd_magic_scale;
2438: mouse_moved(moved);
2439: break;
2440: case 0x50:
2441: moved.mm_deltaX = 0;
2442: moved.mm_deltaY = -kd_kbd_magic_scale;
2443: mouse_moved(moved);
2444: break;
2445: /* home pageup end pagedown */
2446: case 0x47:
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: case 0x49:
2452: moved.mm_deltaX = 2*kd_kbd_magic_scale;
2453: moved.mm_deltaY = 2*kd_kbd_magic_scale;
2454: mouse_moved(moved);
2455: break;
2456: case 0x4f:
2457: moved.mm_deltaX = -2*kd_kbd_magic_scale;
2458: moved.mm_deltaY = -2*kd_kbd_magic_scale;
2459: mouse_moved(moved);
2460: break;
2461: case 0x51:
2462: moved.mm_deltaX = 2*kd_kbd_magic_scale;
2463: moved.mm_deltaY = -2*kd_kbd_magic_scale;
2464: mouse_moved(moved);
2465: break;
2466:
2467: default:
2468: return 0;
2469: }
2470: return 1;
2471: }
2472:
2473:
2474:
2475: /*
2476: * Code specific to EGA/CGA/VGA boards. This code relies on the fact
2477: * that the "slam" functions take a word count and ONE_SPACE takes up
2478: * 1 word.
2479: */
2480: #define SLAMBPW 2 /* bytes per word for "slam" fcns */
2481:
2482:
2483: /*
2484: * kd_xga_init:
2485: *
2486: * Initialization specific to character-based graphics adapters.
2487: */
2488: void
1.1.1.5 root 2489: kd_xga_init(void)
1.1 root 2490: {
2491: csrpos_t xga_getpos();
2492: unsigned char screen;
1.1.1.5 root 2493: unsigned char start, stop;
1.1 root 2494:
2495: outb(CMOS_ADDR, CMOS_EB);
2496: screen = inb(CMOS_DATA) & CM_SCRMSK;
2497: switch(screen) {
1.1.1.5 root 2498: default:
2499: printf("kd: unknown screen type, defaulting to EGA\n");
2500: /* FALLTHROUGH */
1.1 root 2501: case CM_EGA_VGA:
2502: /*
2503: * Here we'll want to query to bios on the card
2504: * itself, because then we can figure out what
2505: * type we have exactly. At this point we only
2506: * know that the card is NOT CGA or MONO. For
2507: * now, however, we assume backwards compatibility
2508: * with 0xb8000 as the starting screen offset
2509: * memory location for these cards.
2510: *
2511: */
1.1.1.3 root 2512:
1.1 root 2513: vid_start = (u_char *)phystokv(EGA_START);
2514: kd_index_reg = EGA_IDX_REG;
2515: kd_io_reg = EGA_IO_REG;
2516: kd_lines = 25;
2517: kd_cols = 80;
2518: kd_bitmap_start = 0xa0000; /* XXX - magic numbers */
2519: { /* XXX - is there a cleaner way to do this? */
2520: char *addr = (char *)phystokv(kd_bitmap_start);
2521: int i;
2522: for (i = 0; i < 200; i++)
2523: addr[i] = 0x00;
2524: }
2525: break;
1.1.1.5 root 2526: #if 0
2527: /* XXX: some buggy BIOSes report these... */
1.1 root 2528: case CM_CGA_40:
2529: vid_start = (u_char *)phystokv(CGA_START);
2530: kd_index_reg = CGA_IDX_REG;
2531: kd_io_reg = CGA_IO_REG;
2532: kd_lines = 25;
2533: kd_cols = 40;
2534: break;
2535: case CM_CGA_80:
2536: vid_start = (u_char *)phystokv(CGA_START);
2537: kd_index_reg = CGA_IDX_REG;
2538: kd_io_reg = CGA_IO_REG;
2539: kd_lines = 25;
2540: kd_cols = 80;
2541: break;
2542: case CM_MONO_80:
2543: vid_start = (u_char *)phystokv(MONO_START);
2544: kd_index_reg = MONO_IDX_REG;
2545: kd_io_reg = MONO_IO_REG;
2546: kd_lines = 25;
2547: kd_cols = 80;
2548: break;
1.1.1.5 root 2549: #endif
2550: }
2551:
2552: outb(kd_index_reg, C_START);
2553: start = inb(kd_io_reg);
2554: /* Make sure cursor is enabled */
2555: start &= ~0x20;
2556: outb(kd_io_reg, start);
2557: outb(kd_index_reg, C_STOP);
2558: stop = inb(kd_io_reg);
2559:
2560: if (!start && !stop)
2561: {
2562: /* Some firmware seem not to be initializing the cursor size
2563: * any more... Try using standard values. */
2564: outb(kd_index_reg, C_START);
2565: outb(kd_io_reg, 14);
2566: outb(kd_index_reg, C_STOP);
2567: outb(kd_io_reg, 15);
1.1 root 2568: }
2569:
2570: kd_setpos(xga_getpos());
2571: }
2572:
2573:
2574: /*
2575: * xga_getpos:
2576: *
2577: * This function returns the current hardware cursor position on the
2578: * screen, scaled for compatibility with kd_curpos.
2579: *
2580: * input : None
2581: * output : returns the value of cursor position on screen
2582: *
2583: */
2584: csrpos_t
1.1.1.5 root 2585: xga_getpos(void)
1.1 root 2586:
2587: {
2588: unsigned char low;
2589: unsigned char high;
2590: short pos;
2591:
2592: outb(kd_index_reg, C_HIGH);
2593: high = inb(kd_io_reg);
2594: outb(kd_index_reg, C_LOW);
2595: low = inb(kd_io_reg);
2596: pos = (0xff&low) + ((unsigned short)high<<8);
2597:
2598: return(ONE_SPACE * (csrpos_t)pos);
2599: }
2600:
2601:
2602: /*
2603: * charput:
2604: *
2605: * Put attributed character for EGA/CGA/etc.
2606: */
2607: static void
2608: charput(pos, ch, chattr)
2609: csrpos_t pos; /* where to put it */
2610: char ch; /* the character */
2611: char chattr; /* its attribute */
2612: {
2613: *(vid_start + pos) = ch;
2614: *(vid_start + pos + 1) = chattr;
2615: }
2616:
2617:
2618: /*
2619: * charsetcursor:
2620: *
2621: * Set hardware cursor position for EGA/CGA/etc.
2622: */
2623: static void
2624: charsetcursor(newpos)
2625: csrpos_t newpos;
2626: {
2627: short curpos; /* position, not scaled for attribute byte */
2628:
2629: curpos = newpos / ONE_SPACE;
2630: outb(kd_index_reg, C_HIGH);
2631: outb(kd_io_reg, (u_char)(curpos>>8));
2632: outb(kd_index_reg, C_LOW);
2633: outb(kd_io_reg, (u_char)(curpos&0xff));
2634:
2635: kd_curpos = newpos;
2636: }
2637:
2638:
2639: /*
2640: * charmvup:
2641: *
2642: * Block move up for EGA/CGA/etc.
2643: */
2644: static void
2645: charmvup(from, to, count)
2646: csrpos_t from, to;
2647: int count;
2648: {
2649: kd_slmscu(vid_start+from, vid_start+to, count);
2650: }
2651:
2652:
2653: /*
2654: * charmvdown:
2655: *
2656: * Block move down for EGA/CGA/etc.
2657: */
2658: static void
2659: charmvdown(from, to, count)
2660: csrpos_t from, to;
2661: int count;
2662: {
2663: kd_slmscd(vid_start+from, vid_start+to, count);
2664: }
2665:
2666:
2667: /*
2668: * charclear:
2669: *
2670: * Fast clear for CGA/EGA/etc.
2671: */
2672: static void
2673: charclear(to, count, chattr)
2674: csrpos_t to;
2675: int count;
2676: char chattr;
2677: {
2678: kd_slmwd(vid_start+to, count, ((unsigned short)chattr<<8)+K_SPACE);
2679: }
2680:
2681:
1.1.1.3 root 2682: /*
1.1 root 2683: * kd_noopreset:
1.1.1.3 root 2684: *
1.1 root 2685: * No-op reset routine for kd_dreset.
2686: */
2687: static void
1.1.1.5 root 2688: kd_noopreset(void)
1.1 root 2689: {
2690: }
2691:
2692:
2693: /*
2694: * bmpput: Copy a character from the font to the frame buffer.
2695: */
2696:
2697: void
1.1.1.5 root 2698: bmpput(
2699: csrpos_t pos,
2700: char ch,
2701: char chattr)
1.1 root 2702: {
2703: short xbit, ybit; /* u/l corner of char pos */
1.1.1.5 root 2704: u_char *to, *from;
2705: short i, j;
1.1 root 2706: u_char mask = (chattr == KA_REVERSE ? 0xff : 0);
2707:
2708: if ((u_char)ch >= chars_in_font)
2709: ch = K_QUES;
2710:
2711: bmpch2bit(pos, &xbit, &ybit);
2712: to = bit2fbptr(xbit, ybit);
2713: from = font_start + ch * char_byte_width;
2714: for (i = 0; i < char_height; ++i) {
2715: for (j = 0; j < char_byte_width; ++j)
2716: *(to+j) = *(from+j) ^ mask;
2717: to += fb_byte_width;
2718: from += font_byte_width;
2719: }
2720: }
2721:
2722: /*
2723: * bmpcp1char: copy 1 char from one place in the frame buffer to
2724: * another.
2725: */
2726: void
1.1.1.5 root 2727: bmpcp1char(
2728: csrpos_t from,
2729: csrpos_t to)
1.1 root 2730: {
2731: short from_xbit, from_ybit;
2732: short to_xbit, to_ybit;
1.1.1.5 root 2733: u_char *tp, *fp;
2734: short i, j;
1.1 root 2735:
2736: bmpch2bit(from, &from_xbit, &from_ybit);
2737: bmpch2bit(to, &to_xbit, &to_ybit);
2738:
2739: tp = bit2fbptr(to_xbit, to_ybit);
2740: fp = bit2fbptr(from_xbit, from_ybit);
2741:
2742: for (i = 0; i < char_height; ++i) {
2743: for (j = 0; j < char_byte_width; ++j)
2744: *(tp+j) = *(fp+j);
2745: tp += fb_byte_width;
2746: fp += fb_byte_width;
2747: }
2748: }
2749:
2750: /*
2751: * bmpvmup: Copy a block of character positions upwards.
2752: */
2753: void
1.1.1.5 root 2754: bmpmvup(
2755: csrpos_t from,
2756: csrpos_t to,
2757: int count)
1.1 root 2758: {
2759: short from_xbit, from_ybit;
2760: short to_xbit, to_ybit;
2761: short i;
2762:
2763: bmpch2bit(from, &from_xbit, &from_ybit);
2764: bmpch2bit(to, &to_xbit, &to_ybit);
2765:
2766: if (from_xbit == xstart && to_xbit == xstart && count%kd_cols == 0) {
2767: /* fast case - entire lines */
2768: from_xbit = to_xbit = 0;
2769: bmppaintcsr(kd_curpos, char_black); /* don't copy cursor */
2770: count /= kd_cols; /* num lines */
2771: count *= fb_byte_width * (char_height+cursor_height);
2772: kd_slmscu(bit2fbptr(from_xbit, from_ybit),
1.1.1.3 root 2773: bit2fbptr(to_xbit, to_ybit),
1.1 root 2774: count/SLAMBPW);
2775: bmppaintcsr(kd_curpos, char_white);
2776: } else {
2777: /* slow case - everything else */
2778: for (i=0; i < count; ++i) {
2779: bmpcp1char(from, to);
2780: from += ONE_SPACE;
2781: to += ONE_SPACE;
2782: }
2783: }
2784: }
2785:
2786: /*
2787: * bmpmvdown: copy a block of characters down.
2788: */
2789: void
1.1.1.5 root 2790: bmpmvdown(
2791: csrpos_t from,
2792: csrpos_t to,
2793: int count)
1.1 root 2794: {
2795: short from_xbit, from_ybit;
2796: short to_xbit, to_ybit;
2797: short i;
2798:
2799: bmpch2bit(from, &from_xbit, &from_ybit);
2800: bmpch2bit(to, &to_xbit, &to_ybit);
2801:
2802: if (from_xbit == xstart + (kd_cols - 1) * char_width
2803: && to_xbit == xstart + (kd_cols - 1) * char_width
2804: && count%kd_cols == 0) {
2805: /* fast case - entire lines*/
2806: from_xbit = to_xbit = 8 * (fb_byte_width - 1);
2807: /* last byte on line */
2808: bmppaintcsr(kd_curpos, char_black); /* don't copy cursor */
2809: count /= kd_cols; /* num lines */
2810: count *= fb_byte_width * (char_height+cursor_height);
2811: kd_slmscd(bit2fbptr(from_xbit, from_ybit),
2812: bit2fbptr(to_xbit, to_ybit),
2813: count/SLAMBPW);
2814: bmppaintcsr(kd_curpos, char_white);
2815: } else {
2816: /* slow case - everything else */
2817: for (i=0; i < count; ++i) {
2818: bmpcp1char(from, to);
2819: from -= ONE_SPACE;
2820: to -= ONE_SPACE;
2821: }
2822: }
2823: }
2824:
2825: /*
2826: * bmpclear: clear one or more character positions.
2827: */
2828: void
1.1.1.5 root 2829: bmpclear(
2830: csrpos_t to, /* 1st char */
2831: int count, /* num chars */
2832: char chattr) /* reverse or normal */
1.1 root 2833: {
1.1.1.5 root 2834: short i;
1.1 root 2835: u_short clearval;
2836: u_short clearbyte = (chattr == KA_REVERSE ? char_white : char_black);
2837:
2838: clearval = (u_short)(clearbyte<<8) + clearbyte;
2839: if (to == 0 && count >= kd_lines * kd_cols) {
2840: /* fast case - entire page */
2841: kd_slmwd(vid_start, (fb_byte_width * fb_height)/SLAMBPW,
2842: clearval);
1.1.1.3 root 2843: } else
1.1 root 2844: /* slow case */
2845: for (i = 0; i < count; ++i) {
2846: bmpput(to, K_SPACE, chattr);
2847: to += ONE_SPACE;
2848: }
2849: }
2850:
2851: /*
2852: * bmpsetcursor: update the display and set the logical cursor.
2853: */
2854: void
1.1.1.5 root 2855: bmpsetcursor(csrpos_t pos)
1.1 root 2856: {
2857: /* erase old cursor & paint new one */
2858: bmppaintcsr(kd_curpos, char_black);
2859: bmppaintcsr(pos, char_white);
2860: kd_curpos = pos;
2861: }
2862:
2863: /*
2864: * bmppaintcsr: paint cursor bits.
2865: */
2866: void
1.1.1.5 root 2867: bmppaintcsr(
2868: csrpos_t pos,
2869: u_char val)
1.1 root 2870: {
2871: short xbit, ybit;
1.1.1.5 root 2872: u_char *cp;
2873: short line, byte;
1.1 root 2874:
2875: bmpch2bit(pos, &xbit, &ybit);
2876: ybit += char_height; /* position at bottom of line */
2877: cp = bit2fbptr(xbit, ybit);
2878: for (line = 0; line < cursor_height; ++line) {
2879: for (byte = 0; byte < char_byte_width; ++byte)
2880: *(cp+byte) = val;
2881: cp += fb_byte_width;
2882: }
2883: }
2884:
2885: /*
2886: * bmpch2bit: convert character position to x and y bit addresses.
2887: * (0, 0) is the upper left corner.
2888: */
2889: void
1.1.1.5 root 2890: bmpch2bit(
2891: csrpos_t pos,
2892: short *xb,
2893: short *yb) /* x, y bit positions, u/l corner */
1.1 root 2894: {
1.1.1.5 root 2895: short xch, ych;
1.1 root 2896:
2897: xch = (pos / ONE_SPACE) % kd_cols;
2898: ych = pos / (ONE_SPACE * kd_cols);
2899: *xb = xstart + xch * char_width;
2900: *yb = ystart + ych * (char_height + cursor_height);
2901: }
2902:
2903: /*
2904: * bit2fbptr: return a pointer into the frame buffer corresponding to
2905: * the bit address (x, y).
2906: * Assumes that xb and yb don't point to the middle of a
2907: * byte.
2908: */
2909: u_char *
1.1.1.5 root 2910: bit2fbptr(
2911: short xb,
2912: short yb)
1.1 root 2913: {
2914: return(vid_start + yb * fb_byte_width + xb/8);
2915: }
2916:
2917:
2918: /*
2919: * console stuff
2920: */
2921:
2922: /*
2923: * XXX we assume that pcs *always* have a console
2924: */
2925: int
2926: kdcnprobe(struct consdev *cp)
2927: {
2928: int maj, unit, pri;
2929:
2930: maj = 0;
2931: unit = 0;
2932: pri = CN_INTERNAL;
1.1.1.3 root 2933:
1.1 root 2934: cp->cn_dev = makedev(maj, unit);
2935: cp->cn_pri = pri;
1.1.1.4 root 2936: return 0;
1.1 root 2937: }
2938:
2939: int
2940: kdcninit(struct consdev *cp)
2941: {
2942: kdinit();
2943: return 0;
2944: }
2945:
2946: int
2947: kdcngetc(dev_t dev, int wait)
2948: {
2949: if (wait) {
2950: int c;
2951: while ((c = kdcnmaygetc()) < 0)
2952: continue;
2953: return c;
2954: }
2955: else
2956: return kdcnmaygetc();
2957: }
2958:
2959: int
2960: kdcnputc(dev_t dev, int c)
2961: {
2962: if (!kd_initialized)
1.1.1.4 root 2963: return -1;
1.1 root 2964:
2965: /* Note that tab is handled in kd_putc */
2966: if (c == '\n')
2967: kd_putc('\r');
1.1.1.6 ! root 2968: kd_putc_esc(c);
1.1.1.4 root 2969:
2970: return 0;
1.1 root 2971: }
2972:
1.1.1.3 root 2973: /*
1.1 root 2974: * kdcnmaygetc:
1.1.1.3 root 2975: *
2976: * Get one character using polling, rather than interrupts. Used
1.1 root 2977: * by the kernel debugger. Note that Caps Lock is ignored.
1.1.1.3 root 2978: * Normally this routine is called with interrupts already
2979: * disabled, but there is code in place so that it will be more
1.1 root 2980: * likely to work even if interrupts are turned on.
2981: */
2982: int
2983: kdcnmaygetc(void)
2984: {
2985: unsigned char c;
2986: unsigned char scancode;
2987: unsigned int char_idx;
2988: #ifdef notdef
2989: spl_t o_pri;
2990: #endif
2991: boolean_t up;
2992:
2993: if (! kd_initialized)
2994: return -1;
2995:
2996: kd_extended = FALSE;
2997: #ifdef notdef
2998: o_pri = splhi();
2999: #endif
3000: for ( ; ; ) {
3001: if (!(inb(K_STATUS) & K_OBUF_FUL))
3002: return -1;
3003:
3004: up = FALSE;
3005: /*
3006: * We'd come here for mouse events in debugger, if
3007: * the mouse were on.
3008: */
3009: if ((inb(K_STATUS) & 0x20) == 0x20) {
3010: printf("M%xP", inb(K_RDWR));
3011: continue;
3012: }
3013: scancode = inb(K_RDWR);
3014: /*
3015: * Handle extend modifier and
3016: * ack/resend, otherwise we may never receive
3017: * a key.
3018: */
3019: if (scancode == K_EXTEND) {
3020: kd_extended = TRUE;
3021: continue;
3022: } else if (scancode == K_RESEND) {
3023: printf("cngetc: resend");
3024: kd_resend();
3025: continue;
3026: } else if (scancode == K_ACKSC) {
3027: printf("cngetc: handle_ack");
3028: kd_handle_ack();
3029: continue;
3030: }
3031: if (scancode & K_UP) {
3032: up = TRUE;
3033: scancode &= ~K_UP;
3034: }
3035: if (kd_kbd_mouse)
3036: kd_kbd_magic(scancode);
3037: if (scancode < NUMKEYS) {
3038: /* Lookup in map, then process. */
3039: char_idx = kdstate2idx(kd_state, kd_extended);
3040: c = key_map[scancode][char_idx];
3041: if (c == K_SCAN) {
3042: c = key_map[scancode][++char_idx];
3043: kd_state = do_modifier(kd_state, c, up);
3044: #ifdef notdef
3045: cnsetleds(state2leds(kd_state));
3046: #endif
1.1.1.5 root 3047: } else if (! up
3048: && c == K_ESC
3049: && key_map[scancode][char_idx+1] == 0x5b) {
3050: /* As a convenience for the nice
3051: people using our debugger, remap
3052: some keys to the readline-like
3053: shortcuts supported by dde.
3054:
3055: XXX This is a workaround for the
3056: limited kernel getchar interface.
3057: It is only used by the debugger. */
3058: c = key_map[scancode][char_idx+2];
3059: switch (c) {
3060: #define _MAP(A,B,C) (C)
3061: #define MAP(T) _MAP(T)
3062: #define CTRL(c) ((c) & 0x1f)
3063: case MAP(K_HOME): c = CTRL('a'); break;
3064: case MAP(K_UA): c = CTRL('p'); break;
3065: case MAP(K_LA): c = CTRL('b'); break;
3066: case MAP(K_RA): c = CTRL('f'); break;
3067: case MAP(K_DA): c = CTRL('n'); break;
3068: case MAP(K_END): c = CTRL('e'); break;
3069: /* delete */
3070: case 0x39: c = CTRL('d'); break;
3071: #undef CTRL
3072: #undef MAP
3073: #undef _MAP
3074: default:
3075: /* Retain the old behavior. */
3076: c = K_ESC;
3077: }
3078:
3079: return(c);
1.1 root 3080: } else if (!up) {
3081: /* regular key-down */
3082: if (c == K_CR)
3083: c = K_LF;
3084: #ifdef notdef
3085: splx(o_pri);
3086: #endif
3087: return(c & 0177);
3088: }
3089: }
3090: }
3091: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.