Annotation of Gnu-Mach/i386/i386at/kd.c, revision 1.1.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.