Annotation of Gnu-Mach/chips/screen.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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