The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/i386ps2/kd.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: 5ab73b6fb7db47d279e453f1a2030972


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.