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/chips/screen.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) 1993,1992,1991,1990,1989 Carnegie Mellon University
    4  * All Rights Reserved.
    5  * 
    6  * Permission to use, copy, modify and distribute this software and its
    7  * documentation is hereby granted, provided that both the copyright
    8  * notice and this permission notice appear in all copies of the
    9  * software, derivative works or modified versions, and any portions
   10  * thereof, and that both notices appear in supporting documentation.
   11  * 
   12  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
   13  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
   14  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
   15  * 
   16  * Carnegie Mellon requests users of this software to return to
   17  * 
   18  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
   19  *  School of Computer Science
   20  *  Carnegie Mellon University
   21  *  Pittsburgh PA 15213-3890
   22  * 
   23  * any improvements or extensions that they make and grant Carnegie Mellon
   24  * the rights to redistribute these changes.
   25  */
   26 /*
   27  * HISTORY
   28  * $Log:        screen.c,v $
   29  * Revision 2.24  93/11/17  16:13:56  dbg
   30  *      Use clock_read to get time.  Cleaned up lint.
   31  *      [93/06/29            dbg]
   32  * 
   33  * Revision 2.23  93/05/28  14:43:18  rvb
   34  *      Initialize screen_console because used before the bss is.
   35  *      [93/05/21            af]
   36  * 
   37  * Revision 2.22  93/05/15  19:39:14  mrt
   38  *      machparam.h -> machspl.h
   39  * 
   40  * Revision 2.21  93/05/10  20:08:42  rvb
   41  *      No more sys/types.h
   42  *      [93/05/06  09:54:42  af]
   43  * 
   44  * Revision 2.20  93/03/26  17:58:36  mrt
   45  *      No more minor()s.
   46  *      [93/03/18            af]
   47  * 
   48  * Revision 2.19  93/02/05  08:07:08  danner
   49  *      Prototypes. 64bit clean.
   50  *      [93/02/04  01:34:50  af]
   51  * 
   52  *      Added first cut at true kbd layer [jtp@hut.fi]
   53  *      Proper spl typing.  Finessed the above.
   54  *      [92/11/30            af]
   55  * 
   56  *      Fixed screen_set_cursor to keep the cursor from wrapping to
   57  *      the other side of the screen when the mouse is moved outside
   58  *      the screen.
   59  *      Move also the physical cursor when the cursor is moved from
   60  *      above.
   61  *      [92/11/30            jvh]
   62  * 
   63  * Revision 2.18  92/05/22  15:48:18  jfriedl
   64  *      Avoid playing with the cursor when it's not the case.
   65  * 
   66  * Revision 2.17  92/04/01  15:14:33  rpd
   67  *      Fixed scaling and thresholding for negative deltas of
   68  *      the cursor, broken in previous merge.
   69  *      [92/03/11  16:06:27  af]
   70  * 
   71  * Revision 2.16  92/03/05  17:08:29  rpd
   72  *      Moved here code that used to be in mouse.c for scaling
   73  *      and thresholding of motion events.
   74  *      [92/03/05            af]
   75  * 
   76  * Revision 2.15  92/03/05  11:36:55  rpd
   77  *      Restore cursor 1-off-max, not to any predefined constant.
   78  *      [92/03/04            af]
   79  * 
   80  * Revision 2.14  92/02/19  16:46:15  elf
   81  *      Turn on screen if output.
   82  *      [92/02/10  17:06:15  af]
   83  * 
   84  * Revision 2.13  91/08/28  11:09:56  jsb
   85  *      Fixed screen_write to check vm_map_copyout's return code.
   86  *      [91/08/03            rpd]
   87  * 
   88  * Revision 2.12  91/08/24  11:52:59  af
   89  *      Spls for 3min, added SCREEN_HARDWARE_INFO.
   90  *      [91/08/02  02:04:46  af]
   91  * 
   92  * Revision 2.11  91/06/25  20:54:45  rpd
   93  *      Tweaks to make gcc happy.
   94  *      [91/06/25            rpd]
   95  * 
   96  * Revision 2.10  91/06/19  11:54:14  rvb
   97  *      X support
   98  *      [91/06/18  21:36:53  rvb]
   99  * 
  100  *      mips->DECSTATION; vax->VAXSTATION
  101  *      [91/06/12  14:02:09  rvb]
  102  * 
  103  *      File moved here from mips/PMAX since it tries to be generic;
  104  *      it is used on the PMAX and the Vax3100.
  105  *      [91/06/04            rvb]
  106  * 
  107  * Revision 2.9  91/05/18  14:35:23  rpd
  108  *      Picked up mouse-movement bug fix for screen_motion_event from Sandro.
  109  *      Also changed compress_mouse_events to TRUE.
  110  *      [91/04/08            rpd]
  111  * 
  112  * Revision 2.8  91/05/14  17:27:14  mrt
  113  *      Correcting copyright
  114  * 
  115  * Revision 2.7  91/05/13  06:31:49  af
  116  *      Generate escape seqs on mouse clicks if X not running.
  117  * 
  118  * Revision 2.6  91/03/16  14:54:29  rpd
  119  *      Fixed ioctl definitions for ANSI C.
  120  *      [91/02/20            rpd]
  121  * 
  122  * Revision 2.5  91/02/05  17:44:07  mrt
  123  *      Added author notices
  124  *      [91/02/04  11:17:25  mrt]
  125  * 
  126  *      Changed to use new Mach copyright
  127  *      [91/02/02  12:15:59  mrt]
  128  * 
  129  * Revision 2.4  91/01/08  15:48:14  rpd
  130  *      Added compress_mouse_events, by default FALSE.
  131  *      [91/01/08  14:14:03  rpd]
  132  * 
  133  * Revision 2.3  90/12/05  23:34:07  af
  134  *      Debugged cursor positioning.
  135  *      [90/12/03  23:34:53  af]
  136  * 
  137  * Revision 2.1.1.1  90/11/01  03:41:25  af
  138  *      Created, starting from code written at CMU.
  139  *      Main (known) contributions:
  140  *              Bob Baron (overall decomposition)
  141  *              Joe Barrera (terminal emulation)
  142  *              Steve Berman (screen saver)
  143  *      [90/09/03            af]
  144  */
  145 /*
  146  *      File: screen.c
  147  *      Author: Alessandro Forin, Robert V. Baron, Joseph S. Barrera,
  148  *              at Carnegie Mellon University
  149  *      Date:   9/90
  150  *
  151  *      Generic Screen Driver routines.
  152  */
  153 
  154 #include <bm.h>
  155 #if     NBM > 0
  156 #include <dtop.h>
  157 
  158 #include <machine/machspl.h>            /* spl definitions */
  159 #include <chips/screen_defs.h>
  160 #include <chips/serial_defs.h>
  161 
  162 #include <chips/lk201.h>
  163 
  164 #include <mach/std_types.h>
  165 #include <kern/clock.h>
  166 #include <kern/time_out.h>
  167 #include <device/io_req.h>
  168 
  169 #include <vm/vm_map.h>
  170 #include <vm/vm_user.h>
  171 #include <device/ds_routines.h>
  172 #include <machine/machspl.h>
  173 
  174 #define Ctrl(x) ((x)-'@')
  175 
  176 #define SCREEN_BLITC_NORMAL             0
  177 #define SCREEN_BLITC_ROW                1
  178 #define SCREEN_BLITC_COL                2
  179 
  180 #define SCREEN_ASCII_INVALID    '\0'    /* ascii_screen not valid here */
  181 
  182 struct screen_softc screen_softc_data[NBM];
  183 struct screen_softc *screen_softc[NBM];
  184 
  185 short screen_console = 0;
  186 
  187 /* Forward decls */
  188 
  189 void screen_blitc(
  190         int             unit,
  191         unsigned char   c);
  192 
  193 void screen_blitc_at(
  194         screen_softc_t  sc,
  195         unsigned char   c,
  196         short           row,
  197         short           col);
  198 
  199 void screen_advance_position(
  200         screen_softc_t  sc);
  201 
  202 void screen_set_cursor(
  203         screen_softc_t  sc,
  204         int             x,
  205         int             y);
  206 
  207 void screen_on_off(
  208         int             unit,
  209         boolean_t       on);
  210 
  211 void screen_enable_vretrace(
  212         int             unit,
  213         boolean_t       on);
  214 
  215 void screen_event_init(
  216         user_info_t     *screen_data);
  217 
  218 void screen_default_colors(
  219         user_info_t     *screen_data);
  220 
  221 void ascii_screen_initialize(
  222         register screen_softc_t sc);
  223 
  224 int approx_time_in_msec(void);
  225 
  226 /*
  227  8-D    A "Screen" has a bitmapped display, a keyboard and a mouse
  228  *
  229  */
  230 
  231 #if NDTOP > 0
  232 extern int      dtop_kbd_probe(), dtop_set_status();
  233 extern void     dtop_kbd_reset(int unit);
  234 extern void     dtop_ring_bell(int unit);
  235 #endif /* NDTOP */
  236 
  237 extern int      lk201_probe(), lk201_set_status();
  238 extern void     lk201_reset(int unit);
  239 extern void     lk201_ring_bell(int unit);
  240 
  241 struct kbd_probe_vector {
  242         int     (*probe)();
  243         int     (*set_status)();
  244         void    (*reset)(int unit);
  245         void    (*beep)(int unit);
  246 } kbd_vector[] = {
  247 #if NDTOP > 0
  248         {dtop_kbd_probe, dtop_set_status, dtop_kbd_reset, dtop_ring_bell},
  249 #endif
  250         {lk201_probe, lk201_set_status, lk201_reset, lk201_ring_bell},
  251         {0,}
  252 };
  253 
  254 int screen_find_kbd(int unit)
  255 {
  256         struct kbd_probe_vector *p = kbd_vector;
  257 
  258         for (; p->probe; p++) {
  259                 if ((*p->probe) (unit)) {
  260                         screen_softc[unit]->kbd_set_status = p->set_status;
  261                         screen_softc[unit]->kbd_reset = p->reset;
  262                         screen_softc[unit]->kbd_beep = p->beep;
  263                         return 1;
  264                 }
  265         }
  266         return 0;
  267 }
  268 
  269 /*
  270  * The screen probe routine looks for the associated
  271  * keyboard and mouse, at the same unit number.
  272  */
  273 int screen_probe(int unit)
  274 {
  275         if (unit >= NBM)
  276                 return 0;
  277         screen_softc[unit] = &screen_softc_data[unit];  
  278         if (!screen_find())
  279                 return 0;
  280         if (!screen_find_kbd(unit))
  281                 return 0;
  282         mouse_probe(unit);
  283         return 1;
  284 }
  285 
  286 screen_softc_t
  287 screen(int unit)
  288 {
  289         return screen_softc[unit];
  290 }
  291 
  292 /*
  293  * This is an upcall from the specific display
  294  * hardware, to register its descriptor
  295  */
  296 void
  297 screen_attach(
  298         int     unit,
  299         char    **hwp)
  300 {
  301         register screen_softc_t sc = screen_softc[unit];
  302 
  303         sc->hw_state = hwp;
  304         sc->blitc_state = SCREEN_BLITC_NORMAL;
  305 }
  306 
  307 /*
  308  * This is another upcall (for now) to register
  309  * the user-mapped information
  310  */
  311 void
  312 screen_up(
  313         int             unit,
  314         user_info_t     *screen_data)
  315 {
  316         register screen_softc_t sc = screen_softc[unit];
  317 
  318         sc->up = screen_data;
  319         mouse_notify_mapped(unit, unit, screen_data);
  320         screen_event_init(screen_data);
  321         ascii_screen_initialize(sc);
  322 }
  323 
  324 /*
  325  * Screen saver
  326  */
  327 #define SSAVER_MIN_TIME (2*60)  /* Minimum fade interval                */
  328 long ssaver_last = 0;   /* Last tv_sec that the keyboard was touched    */
  329 long ssaver_time = 0;   /* Number of seconds before screen is blanked   */
  330 
  331 void
  332 ssaver_bump(int unit)
  333 {
  334         time_spec_t     cur_time;
  335 
  336         if (sys_clock == 0) {
  337             /*
  338              *  We are called before clocks are initialized
  339              */
  340             screen_on_off(unit, TRUE);
  341             return;
  342         }
  343 
  344         /*
  345          *      Turn on the screen if the screen saver is active
  346          */
  347         clock_read(cur_time, sys_clock);
  348 
  349         if ((cur_time.seconds - ssaver_last) > ssaver_time)
  350                 screen_on_off(unit, TRUE);
  351         ssaver_last = cur_time.seconds;
  352 }
  353 
  354 void
  355 screen_saver(int unit)
  356 {
  357         time_spec_t     cur_time;
  358 
  359         /* wakeup each minute */
  360         timeout(screen_saver, (void *)unit, hz * 60);
  361         clock_read(cur_time, sys_clock);
  362         if ((cur_time.seconds - ssaver_last) >= ssaver_time)
  363                 /* this does nothing if already off */
  364                 screen_on_off(unit, FALSE);
  365 }
  366 
  367 /*
  368  * Screen open routine.  We are also notified
  369  * of console operations if our screen is acting
  370  * as a console display.
  371  */
  372 void
  373 screen_open(
  374         int             unit,
  375         boolean_t       console_only)
  376 {
  377         register screen_softc_t sc = screen_softc[unit];
  378 
  379         /*
  380          * Start screen saver on first (console) open
  381          */
  382         if (!ssaver_time) {
  383                 ssaver_time = 10*60;            /* 10 minutes to fade   */
  384                 ssaver_bump(unit);              /* .. from now          */
  385                 screen_saver(unit);             /* Start timer          */
  386         }
  387         /*
  388          * Really opening the screen or just notifying ?
  389          */
  390         if (!console_only) {
  391 #if 0
  392                 (*sc->sw.init_colormap)(sc);
  393 #endif
  394                 screen_event_init(sc->up);
  395                 ascii_screen_initialize(sc);
  396                 (*sc->sw.graphic_open)(sc->hw_state);
  397                 sc->mapped = TRUE;
  398         }
  399 }
  400 
  401 /*
  402  * Screen close
  403  */
  404 void
  405 screen_close(
  406         int             unit,
  407         boolean_t       console_only)
  408 {
  409         register screen_softc_t sc = screen_softc[unit];
  410 
  411         /*
  412          * Closing of the plain console has no effect
  413          */
  414         if (!console_only) {
  415                 user_info_t     *up = sc->up;
  416 
  417                 screen_default_colors(up);
  418                 /* mapped info, cursor and colormap resetting */
  419                 (*sc->sw.graphic_close)(sc);
  420 
  421                 /* turn screen on, and blank it */
  422                 screen_on_off(unit, TRUE);
  423                 ascii_screen_initialize(sc);
  424                 (*sc->sw.clear_bitmap)(sc);
  425 
  426                 /* position cursor circa page end */
  427                 up->row = up->max_row - 1;
  428                 up->col = 0;
  429 
  430                 /* set keyboard back our way */
  431                 (*sc->kbd_reset)(unit);
  432                 lk201_lights(unit, LED_OFF);
  433 
  434                 sc->mapped = FALSE;
  435         }
  436 }
  437 
  438 void screen_default_colors(
  439         user_info_t     *up)
  440 {
  441         register int    i;
  442 
  443         /* restore bg and fg colors */
  444         for (i = 0; i < 3; i++) {
  445                 up->dev_dep_2.pm.Bg_color[i] = 0x00;
  446                 up->dev_dep_2.pm.Fg_color[i] = 0xff;
  447         }
  448 }
  449 
  450 /*
  451  * Write characters to the screen
  452  */
  453 io_return_t
  454 screen_write(
  455         int                     unit,
  456         register io_req_t       ior)
  457 {
  458         register int            count;
  459         register unsigned char  *data;
  460         vm_offset_t             addr;
  461 
  462         if (unit == 1)  /* no writes to the mouse */
  463                 return D_INVALID_OPERATION;
  464 
  465         data  = (unsigned char*) ior->io_data;
  466         count = ior->io_count;
  467         if (count == 0)
  468                 return D_SUCCESS;
  469 
  470         if (!(ior->io_op & IO_INBAND)) {
  471                 vm_map_copy_t copy = (vm_map_copy_t) data;
  472                 kern_return_t kr;
  473 
  474                 kr = vm_map_copyout(device_io_map, &addr, copy);
  475                 if (kr != KERN_SUCCESS)
  476                         return kr;
  477                 data = (unsigned char *) addr;
  478         }
  479 
  480         /* Spill chars out, might fault data in */
  481         while (count--)
  482                 screen_blitc(unit, *data++);
  483 
  484         if (!(ior->io_op & IO_INBAND))
  485                 (void) vm_deallocate(device_io_map, addr, ior->io_count);
  486 
  487         return D_SUCCESS;
  488 }
  489 
  490 /*
  491  * Read from the screen.  This really means waiting
  492  * for an event, which can be either a keypress on
  493  * the keyboard (or pointer) or a mouse movement.
  494  * If there are no available events we queue the
  495  * request for later.
  496  */
  497 queue_head_t screen_read_queue = { &screen_read_queue, &screen_read_queue };
  498 boolean_t    screen_read_done(io_req_t);
  499 
  500 io_return_t
  501 screen_read(
  502         int                     unit,
  503         register io_req_t       ior)
  504 {
  505         register user_info_t    *up = screen_softc[unit]->up;
  506         register spl_t          s = spltty();
  507 
  508         if (up->evque.q_head != up->evque.q_tail) {
  509                 splx(s);
  510                 return D_SUCCESS;
  511         }
  512         ior->io_dev_ptr = (char *) up;
  513         ior->io_done = screen_read_done;
  514         enqueue_tail(&screen_read_queue, (queue_entry_t) ior);
  515         splx(s);
  516         return D_IO_QUEUED;
  517 }
  518 
  519 boolean_t
  520 screen_read_done(
  521         register io_req_t       ior)
  522 {
  523         register user_info_t *up = (user_info_t *) ior->io_dev_ptr;
  524         register spl_t    s = spltty();
  525 
  526         if (up->evque.q_head != up->evque.q_tail) {
  527                 splx(s);
  528                 (void) ds_read_done(ior);
  529                 return TRUE;
  530         }
  531         enqueue_tail(&screen_read_queue, (queue_entry_t) ior);
  532         splx(s);
  533         return FALSE;
  534 }
  535 
  536 static void
  537 screen_event_posted(
  538         register user_info_t    *up)
  539 {
  540         if (up->evque.q_head != up->evque.q_tail) {
  541                 register io_req_t       ior;
  542                 while ((ior = (io_req_t)dequeue_head(&screen_read_queue)))
  543                         iodone(ior);
  544         }
  545 }
  546 
  547 boolean_t compress_mouse_events = TRUE;
  548 
  549 /*
  550  * Upcall from input pointer devices
  551  */
  552 void screen_motion_event(
  553         int     unit,
  554         int     device,
  555         int     x,
  556         int     y)
  557 {
  558         register screen_softc_t sc = screen_softc[unit];
  559         register user_info_t    *up = sc->up;
  560         register unsigned       next;
  561         unsigned int            ev_time;
  562 
  563         /*
  564          * Take care of scale/threshold issues
  565          */
  566         if (device == DEV_MOUSE) {
  567                 register int    scale;
  568 
  569                 scale = up->mouse_scale;
  570 
  571                 if (scale >= 0) {
  572                         register int            threshold;
  573                         register boolean_t      neg;
  574 
  575                         threshold = up->mouse_threshold;
  576 
  577                         neg = (x < 0);
  578                         if (neg) x = -x;
  579                         if (x >= threshold)
  580                                 x += (x - threshold) * scale;
  581                         if (neg) x = -x;
  582 
  583                         neg = (y < 0);
  584                         if (neg) y = -y;
  585                         if (y >= threshold)
  586                                 y += (y - threshold) * scale;
  587                         if (neg) y = -y;
  588 
  589                 }
  590 
  591                 /* we expect mices in incremental mode */
  592                 x += up->mouse_loc.x;
  593                 y += up->mouse_loc.y;
  594 
  595         } else if (device == DEV_TABLET) {
  596 
  597                 /* we expect tablets in absolute mode */
  598                 x = (x * up->dev_dep_2.pm.tablet_scale_x) / 1000;
  599                 y = ((2200 - y) * up->dev_dep_2.pm.tablet_scale_y) / 1000;
  600         
  601         } /* else who are you */
  602 
  603         /*
  604          * Clip if necessary
  605          */
  606         {
  607                 register int            max;
  608 
  609                 if (x > (max = up->max_cur_x))
  610                         x = max;
  611                 if (y > (max = up->max_cur_y))
  612                         y = max;
  613         }
  614 
  615         /*
  616          * Did it actually move
  617          */
  618         if ((up->mouse_loc.x == x) &&
  619             (up->mouse_loc.y == y))
  620                 return;
  621 
  622         /*
  623          * Update mouse location, and cursor
  624          */
  625         up->mouse_loc.x = x;
  626         up->mouse_loc.y = y;
  627 
  628         screen_set_cursor(sc, x, y);
  629 
  630         /*
  631          * Add point to track.
  632          */
  633         {
  634                 register screen_timed_point_t   *tr;
  635 
  636                 /* simply add and overflow if necessary */
  637                 next = up->evque.t_next;
  638                 if (next >= MAX_TRACK)
  639                         next = MAX_TRACK-1;
  640                 tr              = &up->point_track[next++];
  641                 up->evque.t_next = (next == MAX_TRACK) ? 0 : next;
  642 
  643                 ev_time         = (unsigned int) approx_time_in_msec();
  644                 tr->time        = ev_time;
  645                 tr->x           = x;
  646                 tr->y           = y;
  647         }
  648 
  649         /*
  650          * Don't post event if mouse is within bounding box,
  651          * Note our y-s are upside down
  652          */
  653         if (y <  up->mouse_box.bottom &&
  654             y >= up->mouse_box.top &&
  655             x <  up->mouse_box.right &&
  656             x >= up->mouse_box.left)
  657                 return;
  658         up->mouse_box.bottom = 0;       /* X11 wants it ? */
  659 
  660         /*
  661          * Post motion event now
  662          */
  663 #define round(x)        ((x) & (MAX_EVENTS - 1))
  664         {
  665                 register unsigned int   head = up->evque.q_head;
  666                 register unsigned int   tail = up->evque.q_tail;
  667                 register screen_event_t *ev;
  668 
  669                 if (round(tail + 1) == head)    /* queue full, drop it */
  670                         return;
  671 
  672                 /* see if we can spare too many motion events */
  673                 next = round(tail - 1);
  674                 if (compress_mouse_events &&
  675                     (tail != head) && (next != head)) {
  676                         ev = & up->event_queue[next];
  677                         if (ev->type == EVT_PTR_MOTION) {
  678                                 ev->x           = x;
  679                                 ev->y           = y;
  680                                 ev->time        = ev_time;
  681                                 ev->device      = device;
  682                                 screen_event_posted(up);
  683                                 return;
  684                         }
  685                 }
  686                 ev              = & up->event_queue[tail];
  687                 ev->type        = EVT_PTR_MOTION;
  688                 ev->time        = ev_time;
  689                 ev->x           = x;
  690                 ev->y           = y;
  691                 ev->device      = device;
  692 
  693                 /* added to queue */
  694                 up->evque.q_tail = round(tail + 1);
  695         }
  696 
  697         /*
  698          * Wakeup any sleepers
  699          */
  700         screen_event_posted(up);
  701 }
  702 
  703 /*
  704  * Upcall from keypress input devices
  705  * Returns wether the event was consumed or not.
  706  */
  707 boolean_t
  708 screen_keypress_event(
  709         int     unit,
  710         int     device,
  711         int     key,
  712         int     type)
  713 {
  714         register screen_softc_t sc = screen_softc[unit];
  715         register user_info_t    *up = sc->up;
  716         register unsigned int   head, tail;
  717         register screen_event_t *ev;
  718 
  719         if (!sc->mapped) {
  720                 int col, row;
  721 
  722                 if (device != DEV_MOUSE)
  723                         return FALSE;
  724                 /* generate escapes for mouse position */
  725                 col = up->mouse_loc.x / 8;
  726                 row = up->mouse_loc.y / 15;
  727                 mouse_report_position(unit, col, row, key, type);
  728                 return TRUE;
  729         }
  730 
  731         head = up->evque.q_head;
  732         tail = up->evque.q_tail;
  733 
  734         if (round(tail + 1) == head)    /* queue full */
  735                 return TRUE;
  736 
  737         ev              = & up->event_queue[tail];
  738         ev->key         = key;
  739         ev->type        = type;
  740         ev->device      = device;
  741         ev->time        = approx_time_in_msec();
  742         ev->x           = up->mouse_loc.x;
  743         ev->y           = up->mouse_loc.y;
  744 
  745         up->evque.q_tail = round(tail + 1);
  746 
  747         screen_event_posted(up);
  748 
  749         return TRUE;
  750 }
  751 #undef  round
  752 
  753 /*
  754  * Event queue initialization
  755  */
  756 void screen_event_init(
  757         user_info_t     *up)
  758 {
  759         up->evque.q_size = MAX_EVENTS;
  760         up->evque.q_head = 0;
  761         up->evque.q_tail = 0;
  762 ;       up->evque.t_size = MAX_TRACK;
  763         up->evque.t_next = 0;
  764         up->evque.timestamp = approx_time_in_msec();
  765 
  766 }
  767 
  768 /*
  769  * Set/Get status functions.
  770  * ...
  771  */
  772 io_return_t
  773 screen_set_status(
  774         int             unit,
  775         dev_flavor_t    flavor,
  776         dev_status_t    status,
  777         natural_t       status_count)
  778 {
  779         register screen_softc_t sc = screen_softc[unit];
  780         register user_info_t    *up = sc->up;
  781         io_return_t             ret = D_SUCCESS;
  782 
  783 /* XXX checks before getting here */
  784 
  785         switch (flavor) {
  786 
  787         case SCREEN_INIT:
  788                 ascii_screen_initialize(sc);
  789                 break;
  790 
  791         case SCREEN_ON:
  792                 screen_on_off(unit, TRUE);
  793                 break;
  794 
  795         case SCREEN_OFF:
  796                 screen_on_off(unit, FALSE);
  797                 break;
  798 
  799         case SCREEN_FADE: {
  800                 register int tm = * (int *) status;
  801 
  802                 untimeout(screen_saver, (void *)unit);
  803                                                 /* stop everything and     */
  804                 if (tm == -1)                   /* don't reschedule a fade */
  805                         break; 
  806                 if (tm < SSAVER_MIN_TIME)
  807                         tm = SSAVER_MIN_TIME;
  808                 ssaver_time = tm;
  809                 ssaver_bump(unit);
  810                 screen_saver(unit);
  811                 break;
  812         }
  813 
  814         case SCREEN_SET_CURSOR: {
  815                 screen_point_t          *loc = (screen_point_t*) status;
  816 
  817                 if (status_count < sizeof(screen_point_t)/sizeof(int))
  818                         return D_INVALID_SIZE;
  819 
  820                 sc->flags |= SCREEN_BEING_UPDATED;
  821                 up->mouse_loc = *loc;
  822                 sc->flags &= ~SCREEN_BEING_UPDATED;
  823 
  824                 screen_set_cursor(sc, loc->x, loc->y);
  825 
  826                 break;
  827         }
  828 
  829         /* COMPAT: these codes do nothing, but we understand */
  830         case _IO('q', 8):       /* KERNLOOP */
  831         case _IO('q', 9):       /* KERNUNLOOP */
  832         case _IO('g', 21):      /* KERN_UNLOOP */
  833                 break;
  834 
  835         /*
  836          * Anything else is either device-specific,
  837          * or for the keyboard
  838          */
  839         default:
  840                 ret = (*sc->sw.set_status)(sc, flavor, status, status_count);
  841                 if (ret == D_INVALID_OPERATION)
  842                         ret = (*sc->kbd_set_status)(unit, flavor,
  843                                                     status, status_count);
  844                 break;
  845         }
  846         return ret;
  847 }
  848 
  849 io_return_t
  850 screen_get_status(
  851         int             unit,
  852         dev_flavor_t    flavor,
  853         dev_status_t    status,
  854         natural_t       *count)
  855 {
  856         register screen_softc_t sc = screen_softc[unit];
  857 
  858         if (flavor == SCREEN_STATUS_FLAGS) {
  859                 *(int *)status  = sc->flags;
  860                 *count          = 1;
  861                 return D_SUCCESS;
  862         } else if (flavor == SCREEN_HARDWARE_INFO) {
  863                 screen_hw_info_t        *hinfo;
  864 
  865                 hinfo = (screen_hw_info_t*)status;
  866                 hinfo->frame_width = sc->frame_scanline_width;
  867                 hinfo->frame_height = sc->frame_height;
  868                 hinfo->frame_visible_width = sc->frame_visible_width;
  869                 hinfo->frame_visible_height = sc->frame_visible_height;
  870                 *count = sizeof(screen_hw_info_t)/sizeof(int);
  871                 return D_SUCCESS;
  872         } else
  873 
  874                 return (*sc->sw.get_status)(sc, flavor, status, count);
  875 }
  876 
  877 /*
  878  * Routine to handle display and control characters sent to screen
  879  */
  880 void
  881 screen_blitc(
  882         int     unit,
  883         register unsigned char c)
  884 {
  885         register screen_softc_t sc = screen_softc[unit];
  886         register user_info_t    *up = sc->up;
  887         register unsigned char  *ap;
  888         register int i;
  889 
  890         /*
  891          * Handle cursor positioning sequence
  892          */
  893         switch (sc->blitc_state) {
  894         case SCREEN_BLITC_NORMAL:
  895                 break;
  896 
  897         case SCREEN_BLITC_ROW:
  898                 c -= ' ';
  899                 if (c >= up->max_row) {
  900                         up->row = up->max_row - 1;
  901                 } else {
  902                         up->row = c;
  903                 }
  904                 sc->blitc_state = SCREEN_BLITC_COL;
  905                 return;
  906 
  907         case SCREEN_BLITC_COL:
  908                 c -= ' ';
  909                 if (c >= up->max_col) {
  910                         up->col = up->max_col - 1;
  911                 } else {
  912                         up->col = c;
  913                 }
  914                 sc->blitc_state = SCREEN_BLITC_NORMAL;
  915                 goto move_cursor;
  916         }
  917 
  918         c &= 0xff;
  919 
  920         /* echo on rconsole line */
  921         rcputc(c);
  922 
  923         /* we got something to say, turn on the TV */
  924         ssaver_bump(unit);
  925 
  926         switch (c) {
  927                                                 /* Locate cursor*/
  928         case Ctrl('A'):                         /* ^A -> cm     */
  929                 sc->blitc_state = SCREEN_BLITC_ROW;
  930                 return;
  931 
  932                                                 /* Home cursor  */
  933         case Ctrl('B'):                         /* ^B -> ho     */
  934                 up->row = 0;
  935                 up->col = 0;
  936                 break;
  937 
  938                                                 /* Clear screen */
  939         case Ctrl('C'):                         /* ^C -> cl     */
  940                 up->row = 0;
  941                 up->col = 0;
  942                 (*sc->sw.clear_bitmap)(sc);
  943                 break;
  944 
  945                                                 /* Move forward */
  946         case Ctrl('D'):                         /* ^D -> nd     */
  947                 screen_advance_position(sc);
  948                 break;
  949 
  950                                                 /* Clear to eol */
  951         case Ctrl('E'):                         /* ^E -> ce     */
  952                 ap = &sc->ascii_screen[up->max_col*up->row + up->col];
  953                 for (i = up->col; i < up->max_col; i++, ap++) {
  954                         if (sc->standout || *ap != ' ') {
  955                                 if (sc->standout) {
  956                                         *ap = SCREEN_ASCII_INVALID;
  957                                 } else {
  958                                         *ap = ' ';
  959                                 }
  960                                 screen_blitc_at(sc, ' ', up->row, i);
  961                         }
  962                 }
  963                 return;
  964 
  965                                                 /* Cursor up    */
  966         case Ctrl('F'):                         /* ^F -> up     */
  967                 if (up->row != 0) up->row--;
  968                 break;
  969 
  970         case Ctrl('G'):                         /* ^G -> bell   */
  971                 (*sc->kbd_beep)(unit);
  972                 return;
  973 
  974                                                 /* Backspace    */
  975         case Ctrl('H'):                         /* ^H -> bs     */
  976                 if (--up->col < 0)
  977                         up->col = 0;
  978                 break;
  979 
  980         case Ctrl('I'):                         /* ^I -> tab    */
  981                 up->col += (8 - (up->col & 0x7));
  982                 break;
  983 
  984         case Ctrl('J'):                         /* ^J -> lf     */
  985                 if (up->row+1 >= up->max_row)
  986                         (*sc->sw.remove_line)(sc, 0);
  987                 else
  988                         up->row++;
  989                 break;
  990 
  991                                                 /* Start rev-video */
  992         case Ctrl('K'):                         /* ^K -> so     */
  993                 sc->standout = 1;
  994                 return;
  995 
  996                                                 /* End rev-video */
  997         case Ctrl('L'):                         /* ^L -> se     */
  998                 sc->standout = 0;
  999                 return;
 1000 
 1001         case Ctrl('M'):                         /* ^M -> return */
 1002                 up->col = 0;
 1003                 break;
 1004 
 1005                                                 /* Save cursor position */
 1006         case Ctrl('N'):                         /* ^N -> sc     */
 1007                 sc->save_col = up->col;
 1008                 sc->save_row = up->row;
 1009                 return;
 1010 
 1011                                                 /* Restore cursor position */
 1012         case Ctrl('O'):                         /* ^O -> rc     */
 1013                 up->row = sc->save_row;
 1014                 up->col = sc->save_col;
 1015                 break;
 1016 
 1017                                                 /* Add blank line */
 1018         case Ctrl('P'):                         /* ^P -> al     */
 1019                 (*sc->sw.insert_line)(sc, up->row);
 1020                 return;
 1021 
 1022                                                 /* Delete line  */
 1023         case Ctrl('Q'):                         /* ^Q -> dl     */
 1024                 (*sc->sw.remove_line)(sc, up->row);
 1025                 return;
 1026 
 1027         default:
 1028                 /*
 1029                  * If the desired character is already there, then don't
 1030                  * bother redrawing it. Always redraw standout-ed chars,
 1031                  * so that we can assume that all cached characters are
 1032                  * un-standout-ed. (This could be fixed.)
 1033                  */
 1034                 ap = &sc->ascii_screen[up->max_col*up->row + up->col];
 1035                 if (sc->standout || c != *ap) {
 1036                         if (sc->standout) {
 1037                                 *ap = SCREEN_ASCII_INVALID;
 1038                         } else {
 1039                                 *ap = c;
 1040                         }
 1041                         screen_blitc_at(sc, c, up->row, up->col);
 1042                 }
 1043                 screen_advance_position(sc);
 1044                 break;
 1045         }
 1046 
 1047 move_cursor:
 1048         screen_set_cursor(sc, up->col*8, up->row*15);
 1049 
 1050 }
 1051 
 1052 
 1053 /*
 1054  * Advance current position, wrapping and scrolling when necessary
 1055  */
 1056 void screen_advance_position(
 1057         register screen_softc_t sc)
 1058 {
 1059         register user_info_t    *up = sc->up;
 1060 
 1061         if (++up->col >= up->max_col) {
 1062                 up->col = 0 ;
 1063                 if (up->row+1 >= up->max_row) {
 1064                         (*sc->sw.remove_line)(sc, 0);
 1065                 } else {
 1066                         up->row++;
 1067                 }
 1068         }
 1069 }
 1070 
 1071 
 1072 /*
 1073  * Routine to display a character at a given position
 1074  */
 1075 void
 1076 screen_blitc_at(
 1077         register screen_softc_t sc,
 1078         unsigned char           c,
 1079         short                   row,
 1080         short                   col)
 1081 {
 1082         /*
 1083          * Silently ignore non-printable chars
 1084          */
 1085         if (c < ' ' || c > 0xfd)
 1086                 return;
 1087         (*sc->sw.char_paint)(sc, c, row, col);
 1088 }
 1089 
 1090 /*
 1091  * Update sc->ascii_screen array after deleting ROW
 1092  */
 1093 void ascii_screen_rem_update(
 1094         register screen_softc_t sc,
 1095         int     row)
 1096 {
 1097         register user_info_t    *up = sc->up;
 1098         register unsigned int   col_w, row_w;
 1099         register unsigned char  *c, *end;
 1100 
 1101         /* cache and sanity */
 1102         col_w   = up->max_col;
 1103         if (col_w > MaxCharCols)
 1104                 col_w = MaxCharCols;
 1105         row_w   = up->max_row;
 1106         if (row_w > MaxCharRows)
 1107                 row_w = MaxCharRows;
 1108 
 1109         /* scroll up */
 1110         c       = &sc->ascii_screen[row * col_w];
 1111         end     = &sc->ascii_screen[(row_w-1) * col_w];
 1112         for (; c < end; c++)            /* bcopy ? XXX */
 1113                 *c = *(c + col_w);
 1114 
 1115         /* zero out line that entered at end */
 1116         c       = end;
 1117         end     = &sc->ascii_screen[row_w * col_w];
 1118         for (; c < end; c++)
 1119                 *c = ' ';
 1120 
 1121 }
 1122 
 1123 /*
 1124  * Update sc->ascii_screen array after opening new ROW
 1125  */
 1126 void ascii_screen_ins_update(
 1127         register screen_softc_t sc,
 1128         int     row)
 1129 {
 1130         register user_info_t    *up = sc->up;
 1131         register unsigned int   col_w, row_w;
 1132         register unsigned char  *c, *end;
 1133 
 1134         /* cache and sanity */
 1135         col_w   = up->max_col;
 1136         if (col_w > MaxCharCols)
 1137                 col_w = MaxCharCols;
 1138         row_w   = up->max_row;
 1139         if (row_w > MaxCharRows)
 1140                 row_w = MaxCharRows;
 1141 
 1142         /* scroll down */
 1143         c       = &sc->ascii_screen[row_w * col_w - 1];
 1144         end     = &sc->ascii_screen[(row + 1) * col_w];
 1145         for (; c >= end; c--)
 1146                 *c = *(c - col_w);
 1147 
 1148         /* zero out line that entered at row */
 1149         c       = end - 1;
 1150         end     = &sc->ascii_screen[row * col_w];
 1151         for (; c >= end; c--)
 1152                 *c = ' ';
 1153 }
 1154 
 1155 /*
 1156  * Init charmap
 1157  */
 1158 void ascii_screen_fill(
 1159         register screen_softc_t sc,
 1160         char    c)
 1161 {
 1162         register user_info_t    *up = sc->up;
 1163         register int i, to;
 1164 
 1165         to = up->max_row * up->max_col;
 1166         for (i = 0; i < to; i++) {
 1167                 sc->ascii_screen[i] = c;
 1168         }
 1169 }
 1170 
 1171 void ascii_screen_initialize(
 1172         register screen_softc_t sc)
 1173 {
 1174         ascii_screen_fill(sc, SCREEN_ASCII_INVALID);
 1175 }
 1176 
 1177 /*
 1178  * Cursor positioning
 1179  */
 1180 void screen_set_cursor(
 1181         register screen_softc_t sc,
 1182         register int x,
 1183         register int y)
 1184 {
 1185         register user_info_t    *up = sc->up;
 1186 
 1187         /* If we are called from interrupt level..  */
 1188         if (sc->flags & SCREEN_BEING_UPDATED)
 1189                return;
 1190         sc->flags |= SCREEN_BEING_UPDATED;
 1191         /*
 1192          * Note that that was not atomic, but this is
 1193          * a two-party game on the same processor and
 1194          * not a real parallel program.
 1195          */
 1196 
 1197         /* Sanity checks (ignore noise) */
 1198         if (y < up->min_cur_y || y > up->max_cur_y)
 1199                 y = up->cursor.y;
 1200         if (x < up->min_cur_x || x > up->max_cur_x)
 1201                 x = up->cursor.x;
 1202 
 1203         /*
 1204          * Track cursor position
 1205          */
 1206         up->cursor.x = x;
 1207         up->cursor.y = y;
 1208 
 1209         (*sc->sw.pos_cursor)(*(sc->hw_state), x, y);
 1210 
 1211         sc->flags &= ~SCREEN_BEING_UPDATED;
 1212 }
 1213 
 1214 void screen_on_off(
 1215         int             unit,
 1216         boolean_t       on)
 1217 {
 1218         register screen_softc_t sc = screen_softc[unit];
 1219 
 1220         if (sc->sw.video_on == 0)       /* sanity */
 1221                 return;
 1222 
 1223         if (on)
 1224                 (*sc->sw.video_on)(sc->hw_state, sc->up);
 1225         else
 1226                 (*sc->sw.video_off)(sc->hw_state, sc->up);
 1227 }
 1228 
 1229 void screen_enable_vretrace(
 1230         int             unit,
 1231         boolean_t       on)
 1232 {
 1233         register screen_softc_t sc = screen_softc[unit];
 1234         (*sc->sw.intr_enable)(sc->hw_state, on);
 1235 }
 1236 
 1237 /*
 1238  * For our purposes, time does not need to be
 1239  * precise but just monotonic and approximate
 1240  * to about the millisecond.  Instead of div/
 1241  * mul by 1000 we div/mul by 1024 (shifting).
 1242  *
 1243  * Well, it almost worked. The only problem
 1244  * is that X somehow checks the time against
 1245  * gettimeofday() and .. turns screen off at
 1246  * startup if we use approx time. SO we are
 1247  * back to precise time, sigh.
 1248  */
 1249 int approx_time_in_msec(void)
 1250 {
 1251         time_spec_t     cur_time;
 1252 
 1253         if (sys_clock == 0) {
 1254             /*
 1255              *  We are called before clocks are initialized
 1256              */
 1257             return 0;
 1258         }
 1259 
 1260         clock_read(cur_time, sys_clock);
 1261 #if 0
 1262         return ((cur_time.seconds << 10) + (time.nanoseconds >> 20));
 1263 #else
 1264         return ((cur_time.seconds * 1000) + (cur_time.nanoseconds / 1000000));
 1265 #endif
 1266 }
 1267 
 1268 /*
 1269  * Screen mapping to user space
 1270  * This is called on a per-page basis
 1271  */
 1272 vm_offset_t
 1273 screen_mmap(
 1274         int             dev,
 1275         vm_offset_t     off,
 1276         int             prot)
 1277 {
 1278         /* dev is safe, but it is the mouse's one */
 1279         register screen_softc_t sc = screen_softc[dev-1];
 1280 
 1281         return (*sc->sw.map_page)(sc, off, prot);
 1282 }
 1283 
 1284 #endif  /* NBM > 0 */

Cache object: e4635919b75f811bd0043437fa8ac68e


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