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

Cache object: 0a8d216fe8b3b4b5588b53e10914937a


[ 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.