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