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