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