|
|
GNU Mach 1.0
/*
* Mach Operating System
* Copyright (c) 1991,1990,1989 Carnegie Mellon University
* All Rights Reserved.
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
* ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
* Carnegie Mellon requests users of this software to return to
*
* Software Distribution Coordinator or [email protected]
* School of Computer Science
* Carnegie Mellon University
* Pittsburgh PA 15213-3890
*
* any improvements or extensions that they make and grant Carnegie Mellon
* the rights to redistribute these changes.
*/
/*
* File: screen.c
* Author: Alessandro Forin, Robert V. Baron, Joseph S. Barrera,
* at Carnegie Mellon University
* Date: 9/90
*
* Generic Screen Driver routines.
*/
#include <bm.h>
#if NBM > 0
#include <dtop.h>
#include <machine/machspl.h> /* spl definitions */
#include <chips/screen_defs.h>
#include <chips/lk201.h>
#include <mach/std_types.h>
#include <sys/time.h>
#include <kern/time_out.h>
#include <device/io_req.h>
#include <vm/vm_map.h>
#include <device/ds_routines.h>
#include <machine/machspl.h>
#define Ctrl(x) ((x)-'@')
#define SCREEN_BLITC_NORMAL 0
#define SCREEN_BLITC_ROW 1
#define SCREEN_BLITC_COL 2
#define SCREEN_ASCII_INVALID '\0' /* ascii_screen not valid here */
struct screen_softc screen_softc_data[NBM];
struct screen_softc *screen_softc[NBM];
short screen_console = 0;
/* Forward decls */
void screen_blitc(
int unit,
register unsigned char c);
void screen_blitc_at(
register screen_softc_t sc,
unsigned char c,
short row,
short col);
/*
8-D A "Screen" has a bitmapped display, a keyboard and a mouse
*
*/
#if NDTOP > 0
extern int dtop_kbd_probe(), dtop_set_status(), dtop_kbd_reset(),
dtop_ring_bell();
#endif /* NDTOP */
extern int lk201_probe(), lk201_set_status(), lk201_reset(),
lk201_ring_bell();
struct kbd_probe_vector {
int (*probe)();
int (*set_status)();
int (*reset)();
int (*beep)();
} kbd_vector[] = {
#if NDTOP > 0
{dtop_kbd_probe, dtop_set_status, dtop_kbd_reset, dtop_ring_bell},
#endif
{lk201_probe, lk201_set_status, lk201_reset, lk201_ring_bell},
{0,}
};
screen_find_kbd(int unit)
{
struct kbd_probe_vector *p = kbd_vector;
for (; p->probe; p++) {
if ((*p->probe) (unit)) {
screen_softc[unit]->kbd_set_status = p->set_status;
screen_softc[unit]->kbd_reset = p->reset;
screen_softc[unit]->kbd_beep = p->beep;
return 1;
}
}
return 0;
}
/*
* The screen probe routine looks for the associated
* keyboard and mouse, at the same unit number.
*/
screen_probe(int unit)
{
if (unit >= NBM)
return 0;
screen_softc[unit] = &screen_softc_data[unit];
if (!screen_find())
return 0;
if (!screen_find_kbd(unit))
return 0;
mouse_probe(unit);
return 1;
}
screen_softc_t
screen(int unit)
{
return screen_softc[unit];
}
/*
* This is an upcall from the specific display
* hardware, to register its descriptor
*/
screen_attach(
int unit,
char **hwp)
{
register screen_softc_t sc = screen_softc[unit];
sc->hw_state = hwp;
sc->blitc_state = SCREEN_BLITC_NORMAL;
}
/*
* This is another upcall (for now) to register
* the user-mapped information
*/
void
screen_up(
int unit,
user_info_t *screen_data)
{
register screen_softc_t sc = screen_softc[unit];
sc->up = screen_data;
mouse_notify_mapped(unit, unit, screen_data);
screen_event_init(screen_data);
ascii_screen_initialize(sc);
}
/*
* Screen saver
*/
#define SSAVER_MIN_TIME (2*60) /* Minimum fade interval */
long ssaver_last = 0; /* Last tv_sec that the keyboard was touched */
long ssaver_time = 0; /* Number of seconds before screen is blanked */
void
ssaver_bump(int unit)
{
register long tnow = time.tv_sec;
if ((tnow - ssaver_last) > ssaver_time)
screen_on_off(unit, TRUE);
ssaver_last = tnow;
}
void
screen_saver(int unit)
{
register screen_softc_t sc = screen_softc[unit];
/* wakeup each minute */
timeout(screen_saver, unit, hz * 60);
if ((time.tv_sec - ssaver_last) >= ssaver_time)
/* this does nothing if already off */
screen_on_off(unit, FALSE);
}
/*
* Screen open routine. We are also notified
* of console operations if our screen is acting
* as a console display.
*/
screen_open(
int unit,
boolean_t console_only)
{
register screen_softc_t sc = screen_softc[unit];
/*
* Start screen saver on first (console) open
*/
if (!ssaver_time) {
ssaver_time = 10*60; /* 10 minutes to fade */
ssaver_bump(unit); /* .. from now */
screen_saver(unit); /* Start timer */
}
/*
* Really opening the screen or just notifying ?
*/
if (!console_only) {
#if 0
(*sc->sw.init_colormap)(sc);
#endif
screen_event_init(sc->up);
ascii_screen_initialize(sc);
(*sc->sw.graphic_open)(sc->hw_state);
sc->mapped = TRUE;
}
}
/*
* Screen close
*/
screen_close(
int unit,
boolean_t console_only)
{
register screen_softc_t sc = screen_softc[unit];
/*
* Closing of the plain console has no effect
*/
if (!console_only) {
user_info_t *up = sc->up;
screen_default_colors(up);
/* mapped info, cursor and colormap resetting */
(*sc->sw.graphic_close)(sc);
/* turn screen on, and blank it */
screen_on_off(unit, TRUE);
ascii_screen_initialize(sc);
(*sc->sw.clear_bitmap)(sc);
/* position cursor circa page end */
up->row = up->max_row - 1;
up->col = 0;
/* set keyboard back our way */
(*sc->kbd_reset)(unit);
lk201_lights(unit, LED_OFF);
sc->mapped = FALSE;
}
}
screen_default_colors(
user_info_t *up)
{
register int i;
/* restore bg and fg colors */
for (i = 0; i < 3; i++) {
up->dev_dep_2.pm.Bg_color[i] = 0x00;
up->dev_dep_2.pm.Fg_color[i] = 0xff;
}
}
/*
* Write characters to the screen
*/
screen_write(
int unit,
register io_req_t ior)
{
register int count;
register unsigned char *data;
vm_offset_t addr;
if (unit == 1) /* no writes to the mouse */
return D_INVALID_OPERATION;
data = (unsigned char*) ior->io_data;
count = ior->io_count;
if (count == 0)
return (D_SUCCESS);
if (!(ior->io_op & IO_INBAND)) {
vm_map_copy_t copy = (vm_map_copy_t) data;
kern_return_t kr;
kr = vm_map_copyout(device_io_map, &addr, copy);
if (kr != KERN_SUCCESS)
return (kr);
data = (unsigned char *) addr;
}
/* Spill chars out, might fault data in */
while (count--)
screen_blitc(unit, *data++);
if (!(ior->io_op & IO_INBAND))
(void) vm_deallocate(device_io_map, addr, ior->io_count);
return (D_SUCCESS);
}
/*
* Read from the screen. This really means waiting
* for an event, which can be either a keypress on
* the keyboard (or pointer) or a mouse movement.
* If there are no available events we queue the
* request for later.
*/
queue_head_t screen_read_queue = { &screen_read_queue, &screen_read_queue };
boolean_t screen_read_done();
screen_read(
int unit,
register io_req_t ior)
{
register user_info_t *up = screen_softc[unit]->up;
register spl_t s = spltty();
if (up->evque.q_head != up->evque.q_tail) {
splx(s);
return (D_SUCCESS);
}
ior->io_dev_ptr = (char *) up;
ior->io_done = screen_read_done;
enqueue_tail(&screen_read_queue, (queue_entry_t) ior);
splx(s);
return (D_IO_QUEUED);
}
boolean_t
screen_read_done(
register io_req_t ior)
{
register user_info_t *up = (user_info_t *) ior->io_dev_ptr;
register spl_t s = spltty();
if (up->evque.q_head != up->evque.q_tail) {
splx(s);
(void) ds_read_done(ior);
return (TRUE);
}
enqueue_tail(&screen_read_queue, (queue_entry_t) ior);
splx(s);
return (FALSE);
}
static
screen_event_posted(
register user_info_t *up)
{
if (up->evque.q_head != up->evque.q_tail) {
register io_req_t ior;
while ((ior = (io_req_t)dequeue_head(&screen_read_queue)))
iodone(ior);
}
}
boolean_t compress_mouse_events = TRUE;
/*
* Upcall from input pointer devices
*/
screen_motion_event(
int unit,
int device,
int x,
int y)
{
register screen_softc_t sc = screen_softc[unit];
register user_info_t *up = sc->up;
register unsigned next;
unsigned int ev_time;
/*
* Take care of scale/threshold issues
*/
if (device == DEV_MOUSE) {
register int scale;
scale = up->mouse_scale;
if (scale >= 0) {
register int threshold;
register boolean_t neg;
threshold = up->mouse_threshold;
neg = (x < 0);
if (neg) x = -x;
if (x >= threshold)
x += (x - threshold) * scale;
if (neg) x = -x;
neg = (y < 0);
if (neg) y = -y;
if (y >= threshold)
y += (y - threshold) * scale;
if (neg) y = -y;
}
/* we expect mices in incremental mode */
x += up->mouse_loc.x;
y += up->mouse_loc.y;
} else if (device == DEV_TABLET) {
/* we expect tablets in absolute mode */
x = (x * up->dev_dep_2.pm.tablet_scale_x) / 1000;
y = ((2200 - y) * up->dev_dep_2.pm.tablet_scale_y) / 1000;
} /* else who are you */
/*
* Clip if necessary
*/
{
register int max;
if (x > (max = up->max_cur_x))
x = max;
if (y > (max = up->max_cur_y))
y = max;
}
/*
* Did it actually move
*/
if ((up->mouse_loc.x == x) &&
(up->mouse_loc.y == y))
return;
/*
* Update mouse location, and cursor
*/
up->mouse_loc.x = x;
up->mouse_loc.y = y;
screen_set_cursor(sc, x, y);
/*
* Add point to track.
*/
{
register screen_timed_point_t *tr;
/* simply add and overflow if necessary */
next = up->evque.t_next;
if (next >= MAX_TRACK)
next = MAX_TRACK-1;
tr = &up->point_track[next++];
up->evque.t_next = (next == MAX_TRACK) ? 0 : next;
ev_time = (unsigned) approx_time_in_msec();
tr->time = ev_time;
tr->x = x;
tr->y = y;
}
/*
* Don't post event if mouse is within bounding box,
* Note our y-s are upside down
*/
if (y < up->mouse_box.bottom &&
y >= up->mouse_box.top &&
x < up->mouse_box.right &&
x >= up->mouse_box.left)
return;
up->mouse_box.bottom = 0; /* X11 wants it ? */
/*
* Post motion event now
*/
#define round(x) ((x) & (MAX_EVENTS - 1))
{
register unsigned int head = up->evque.q_head;
register unsigned int tail = up->evque.q_tail;
register screen_event_t *ev;
if (round(tail + 1) == head) /* queue full, drop it */
return;
/* see if we can spare too many motion events */
next = round(tail - 1);
if (compress_mouse_events &&
(tail != head) && (next != head)) {
ev = & up->event_queue[next];
if (ev->type == EVT_PTR_MOTION) {
ev->x = x;
ev->y = y;
ev->time = ev_time;
ev->device = device;
screen_event_posted(up);
return;
}
}
ev = & up->event_queue[tail];
ev->type = EVT_PTR_MOTION;
ev->time = ev_time;
ev->x = x;
ev->y = y;
ev->device = device;
/* added to queue */
up->evque.q_tail = round(tail + 1);
}
/*
* Wakeup any sleepers
*/
screen_event_posted(up);
}
/*
* Upcall from keypress input devices
* Returns wether the event was consumed or not.
*/
boolean_t
screen_keypress_event(
int unit,
int device,
int key,
int type)
{
register screen_softc_t sc = screen_softc[unit];
register user_info_t *up = sc->up;
register unsigned int head, tail;
register screen_event_t *ev;
if (!sc->mapped) {
int col, row;
if (device != DEV_MOUSE)
return FALSE;
/* generate escapes for mouse position */
col = up->mouse_loc.x / 8;
row = up->mouse_loc.y / 15;
mouse_report_position(unit, col, row, key, type);
return TRUE;
}
head = up->evque.q_head;
tail = up->evque.q_tail;
if (round(tail + 1) == head) /* queue full */
return TRUE;
ev = & up->event_queue[tail];
ev->key = key;
ev->type = type;
ev->device = device;
ev->time = approx_time_in_msec();
ev->x = up->mouse_loc.x;
ev->y = up->mouse_loc.y;
up->evque.q_tail = round(tail + 1);
screen_event_posted(up);
return TRUE;
}
#undef round
/*
* Event queue initialization
*/
screen_event_init(
user_info_t *up)
{
up->evque.q_size = MAX_EVENTS;
up->evque.q_head = 0;
up->evque.q_tail = 0;
; up->evque.t_size = MAX_TRACK;
up->evque.t_next = 0;
up->evque.timestamp = approx_time_in_msec();
}
/*
* Set/Get status functions.
* ...
*/
io_return_t
screen_set_status(
int unit,
dev_flavor_t flavor,
dev_status_t status,
natural_t status_count)
{
register screen_softc_t sc = screen_softc[unit];
register user_info_t *up = sc->up;
io_return_t ret = D_SUCCESS;
/* XXX checks before getting here */
switch (flavor) {
case SCREEN_INIT:
ascii_screen_initialize(sc);
break;
case SCREEN_ON:
screen_on_off(unit, TRUE);
break;
case SCREEN_OFF:
screen_on_off(unit, FALSE);
break;
case SCREEN_FADE: {
register int tm = * (int *) status;
untimeout(screen_saver, unit); /* stop everything and */
if (tm == -1) /* don't reschedule a fade */
break;
if (tm < SSAVER_MIN_TIME)
tm = SSAVER_MIN_TIME;
ssaver_time = tm;
ssaver_bump(unit);
screen_saver(unit);
break;
}
case SCREEN_SET_CURSOR: {
screen_point_t *loc = (screen_point_t*) status;
if (status_count < sizeof(screen_point_t)/sizeof(int))
return D_INVALID_SIZE;
sc->flags |= SCREEN_BEING_UPDATED;
up->mouse_loc = *loc;
sc->flags &= ~SCREEN_BEING_UPDATED;
screen_set_cursor(sc, loc->x, loc->y);
break;
}
/* COMPAT: these codes do nothing, but we understand */
case _IO('q', 8): /* KERNLOOP */
case _IO('q', 9): /* KERNUNLOOP */
case _IO('g', 21): /* KERN_UNLOOP */
break;
/*
* Anything else is either device-specific,
* or for the keyboard
*/
default:
ret = (*sc->sw.set_status)(sc, flavor, status, status_count);
if (ret == D_INVALID_OPERATION)
ret = (*sc->kbd_set_status)(unit, flavor,
status, status_count);
break;
}
return ret;
}
io_return_t
screen_get_status(
int unit,
dev_flavor_t flavor,
dev_status_t status,
natural_t *count)
{
register screen_softc_t sc = screen_softc[unit];
if (flavor == SCREEN_STATUS_FLAGS) {
*(int *)status = sc->flags;
*count = 1;
return D_SUCCESS;
} else if (flavor == SCREEN_HARDWARE_INFO) {
screen_hw_info_t *hinfo;
hinfo = (screen_hw_info_t*)status;
hinfo->frame_width = sc->frame_scanline_width;
hinfo->frame_height = sc->frame_height;
hinfo->frame_visible_width = sc->frame_visible_width;
hinfo->frame_visible_height = sc->frame_visible_height;
*count = sizeof(screen_hw_info_t)/sizeof(int);
return D_SUCCESS;
} else
return (*sc->sw.get_status)(sc, flavor, status, count);
}
/*
* Routine to handle display and control characters sent to screen
*/
void
screen_blitc(
int unit,
register unsigned char c)
{
register screen_softc_t sc = screen_softc[unit];
register user_info_t *up = sc->up;
register unsigned char *ap;
register int i;
/*
* Handle cursor positioning sequence
*/
switch (sc->blitc_state) {
case SCREEN_BLITC_NORMAL:
break;
case SCREEN_BLITC_ROW:
c -= ' ';
if (c >= up->max_row) {
up->row = up->max_row - 1;
} else {
up->row = c;
}
sc->blitc_state = SCREEN_BLITC_COL;
return;
case SCREEN_BLITC_COL:
c -= ' ';
if (c >= up->max_col) {
up->col = up->max_col - 1;
} else {
up->col = c;
}
sc->blitc_state = SCREEN_BLITC_NORMAL;
goto move_cursor;
}
c &= 0xff;
/* echo on rconsole line */
rcputc(c);
/* we got something to say, turn on the TV */
ssaver_bump(unit);
switch (c) {
/* Locate cursor*/
case Ctrl('A'): /* ^A -> cm */
sc->blitc_state = SCREEN_BLITC_ROW;
return;
/* Home cursor */
case Ctrl('B'): /* ^B -> ho */
up->row = 0;
up->col = 0;
break;
/* Clear screen */
case Ctrl('C'): /* ^C -> cl */
up->row = 0;
up->col = 0;
(*sc->sw.clear_bitmap)(sc);
break;
/* Move forward */
case Ctrl('D'): /* ^D -> nd */
screen_advance_position(sc);
break;
/* Clear to eol */
case Ctrl('E'): /* ^E -> ce */
ap = &sc->ascii_screen[up->max_col*up->row + up->col];
for (i = up->col; i < up->max_col; i++, ap++) {
if (sc->standout || *ap != ' ') {
if (sc->standout) {
*ap = SCREEN_ASCII_INVALID;
} else {
*ap = ' ';
}
screen_blitc_at(sc, ' ', up->row, i);
}
}
return;
/* Cursor up */
case Ctrl('F'): /* ^F -> up */
if (up->row != 0) up->row--;
break;
case Ctrl('G'): /* ^G -> bell */
(*sc->kbd_beep)(unit);
return;
/* Backspace */
case Ctrl('H'): /* ^H -> bs */
if (--up->col < 0)
up->col = 0;
break;
case Ctrl('I'): /* ^I -> tab */
up->col += (8 - (up->col & 0x7));
break;
case Ctrl('J'): /* ^J -> lf */
if (up->row+1 >= up->max_row)
(*sc->sw.remove_line)(sc, 0);
else
up->row++;
break;
/* Start rev-video */
case Ctrl('K'): /* ^K -> so */
sc->standout = 1;
return;
/* End rev-video */
case Ctrl('L'): /* ^L -> se */
sc->standout = 0;
return;
case Ctrl('M'): /* ^M -> return */
up->col = 0;
break;
/* Save cursor position */
case Ctrl('N'): /* ^N -> sc */
sc->save_col = up->col;
sc->save_row = up->row;
return;
/* Restore cursor position */
case Ctrl('O'): /* ^O -> rc */
up->row = sc->save_row;
up->col = sc->save_col;
break;
/* Add blank line */
case Ctrl('P'): /* ^P -> al */
(*sc->sw.insert_line)(sc, up->row);
return;
/* Delete line */
case Ctrl('Q'): /* ^Q -> dl */
(*sc->sw.remove_line)(sc, up->row);
return;
default:
/*
* If the desired character is already there, then don't
* bother redrawing it. Always redraw standout-ed chars,
* so that we can assume that all cached characters are
* un-standout-ed. (This could be fixed.)
*/
ap = &sc->ascii_screen[up->max_col*up->row + up->col];
if (sc->standout || c != *ap) {
if (sc->standout) {
*ap = SCREEN_ASCII_INVALID;
} else {
*ap = c;
}
screen_blitc_at(sc, c, up->row, up->col);
}
screen_advance_position(sc);
break;
}
move_cursor:
screen_set_cursor(sc, up->col*8, up->row*15);
}
/*
* Advance current position, wrapping and scrolling when necessary
*/
screen_advance_position(
register screen_softc_t sc)
{
register user_info_t *up = sc->up;
if (++up->col >= up->max_col) {
up->col = 0 ;
if (up->row+1 >= up->max_row) {
(*sc->sw.remove_line)(sc, 0);
} else {
up->row++;
}
}
}
/*
* Routine to display a character at a given position
*/
void
screen_blitc_at(
register screen_softc_t sc,
unsigned char c,
short row,
short col)
{
/*
* Silently ignore non-printable chars
*/
if (c < ' ' || c > 0xfd)
return;
(*sc->sw.char_paint)(sc, c, row, col);
}
/*
* Update sc->ascii_screen array after deleting ROW
*/
ascii_screen_rem_update(
register screen_softc_t sc,
int row)
{
register user_info_t *up = sc->up;
register unsigned int col_w, row_w;
register unsigned char *c, *end;
/* cache and sanity */
col_w = up->max_col;
if (col_w > MaxCharCols)
col_w = MaxCharCols;
row_w = up->max_row;
if (row_w > MaxCharRows)
row_w = MaxCharRows;
/* scroll up */
c = &sc->ascii_screen[row * col_w];
end = &sc->ascii_screen[(row_w-1) * col_w];
for (; c < end; c++) /* bcopy ? XXX */
*c = *(c + col_w);
/* zero out line that entered at end */
c = end;
end = &sc->ascii_screen[row_w * col_w];
for (; c < end; c++)
*c = ' ';
}
/*
* Update sc->ascii_screen array after opening new ROW
*/
ascii_screen_ins_update(
register screen_softc_t sc,
int row)
{
register user_info_t *up = sc->up;
register unsigned int col_w, row_w;
register unsigned char *c, *end;
/* cache and sanity */
col_w = up->max_col;
if (col_w > MaxCharCols)
col_w = MaxCharCols;
row_w = up->max_row;
if (row_w > MaxCharRows)
row_w = MaxCharRows;
/* scroll down */
c = &sc->ascii_screen[row_w * col_w - 1];
end = &sc->ascii_screen[(row + 1) * col_w];
for (; c >= end; c--)
*c = *(c - col_w);
/* zero out line that entered at row */
c = end - 1;
end = &sc->ascii_screen[row * col_w];
for (; c >= end; c--)
*c = ' ';
}
/*
* Init charmap
*/
ascii_screen_fill(
register screen_softc_t sc,
char c)
{
register user_info_t *up = sc->up;
register int i, to;
to = up->max_row * up->max_col;
for (i = 0; i < to; i++) {
sc->ascii_screen[i] = c;
}
}
ascii_screen_initialize(
register screen_softc_t sc)
{
ascii_screen_fill(sc, SCREEN_ASCII_INVALID);
}
/*
* Cursor positioning
*/
screen_set_cursor(
register screen_softc_t sc,
register int x,
register int y)
{
register user_info_t *up = sc->up;
/* If we are called from interrupt level.. */
if (sc->flags & SCREEN_BEING_UPDATED)
return;
sc->flags |= SCREEN_BEING_UPDATED;
/*
* Note that that was not atomic, but this is
* a two-party game on the same processor and
* not a real parallel program.
*/
/* Sanity checks (ignore noise) */
if (y < up->min_cur_y || y > up->max_cur_y)
y = up->cursor.y;
if (x < up->min_cur_x || x > up->max_cur_x)
x = up->cursor.x;
/*
* Track cursor position
*/
up->cursor.x = x;
up->cursor.y = y;
(*sc->sw.pos_cursor)(*(sc->hw_state), x, y);
sc->flags &= ~SCREEN_BEING_UPDATED;
}
screen_on_off(
int unit,
boolean_t on)
{
register screen_softc_t sc = screen_softc[unit];
if (sc->sw.video_on == 0) /* sanity */
return;
if (on)
(*sc->sw.video_on)(sc->hw_state, sc->up);
else
(*sc->sw.video_off)(sc->hw_state, sc->up);
}
screen_enable_vretrace(
int unit,
boolean_t on)
{
register screen_softc_t sc = screen_softc[unit];
(*sc->sw.intr_enable)(sc->hw_state, on);
}
/*
* For our purposes, time does not need to be
* precise but just monotonic and approximate
* to about the millisecond. Instead of div/
* mul by 1000 we div/mul by 1024 (shifting).
*
* Well, it almost worked. The only problem
* is that X somehow checks the time against
* gettimeofday() and .. turns screen off at
* startup if we use approx time. SO we are
* back to precise time, sigh.
*/
approx_time_in_msec()
{
#if 0
return ((time.seconds << 10) + (time.microseconds >> 10));
#else
return ((time.seconds * 1000) + (time.microseconds / 1000));
#endif
}
/*
* Screen mapping to user space
* This is called on a per-page basis
*/
screen_mmap(
int dev,
vm_offset_t off,
int prot)
{
/* dev is safe, but it is the mouse's one */
register screen_softc_t sc = screen_softc[dev-1];
(*sc->sw.map_page)(sc, off, prot);
}
#endif NBM > 0
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.