|
|
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
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.