Annotation of Gnu-Mach/i386/i386at/kd.c, revision 1.1

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, &regs)) {
        !           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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.