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