syscons.c revision 32457
117683Spst/*- 239291Sfenner * Copyright (c) 1992-1997 S�ren Schmidt 317683Spst * All rights reserved. 417683Spst * 517683Spst * Redistribution and use in source and binary forms, with or without 617683Spst * modification, are permitted provided that the following conditions 717683Spst * are met: 817683Spst * 1. Redistributions of source code must retain the above copyright 917683Spst * notice, this list of conditions and the following disclaimer 1017683Spst * in this position and unchanged. 1117683Spst * 2. Redistributions in binary form must reproduce the above copyright 1217683Spst * notice, this list of conditions and the following disclaimer in the 1317683Spst * documentation and/or other materials provided with the distribution. 1417683Spst * 3. The name of the author may not be used to endorse or promote products 1517683Spst * derived from this software withough specific prior written permission 1617683Spst * 1717683Spst * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1817683Spst * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1917683Spst * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 2017683Spst * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 2117683Spst * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2217683Spst * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2317683Spst * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2417683Spst * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2517683Spst * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2617683Spst * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2717683Spst * 2817683Spst * $Id: syscons.c,v 1.244 1998/01/09 09:06:55 yokota Exp $ 2917683Spst */ 3017683Spst 3117683Spst#include "sc.h" 3217683Spst#include "apm.h" 3317683Spst#include "opt_ddb.h" 3417683Spst#include "opt_syscons.h" 3526175Sfenner 3698530Sfenner#if NSC > 0 3717683Spst#include <sys/param.h> 3817683Spst#include <sys/systm.h> 3975107Sfenner#include <sys/conf.h> 4075107Sfenner#include <sys/proc.h> 4175107Sfenner#include <sys/signalvar.h> 4275107Sfenner#include <sys/tty.h> 4317683Spst#include <sys/kernel.h> 4417683Spst#include <sys/malloc.h> 4517683Spst#ifdef DEVFS 4617683Spst#include <sys/devfsext.h> 4717683Spst#endif 4817683Spst 4998530Sfenner#include <machine/clock.h> 5098530Sfenner#include <machine/cons.h> 5117683Spst#include <machine/console.h> 5217683Spst#include <machine/mouse.h> 5317683Spst#include <machine/md_var.h> 5417683Spst#include <machine/psl.h> 5517683Spst#include <machine/frame.h> 5617683Spst#include <machine/pc/display.h> 5717683Spst#include <machine/apm_bios.h> 5817683Spst#include <machine/random.h> 5917683Spst 6017683Spst#include <vm/vm.h> 6117683Spst#include <vm/vm_param.h> 6217683Spst#include <vm/pmap.h> 6317683Spst 6439291Sfenner#include <i386/isa/isa.h> 6517683Spst#include <i386/isa/isa_device.h> 6617683Spst#include <i386/isa/timerreg.h> 6717683Spst#include <i386/isa/kbdtables.h> 6817683Spst#include <i386/isa/kbdio.h> 6917683Spst#include <i386/isa/syscons.h> 7039291Sfenner 7139291Sfenner#if !defined(MAXCONS) 7217683Spst#define MAXCONS 16 7339291Sfenner#endif 7439291Sfenner 7539291Sfenner#if !defined(SC_MAX_HISTORY_SIZE) 7639291Sfenner#define SC_MAX_HISTORY_SIZE (1000 * MAXCONS) 7739291Sfenner#endif 7839291Sfenner 7939291Sfenner#if !defined(SC_HISTORY_SIZE) 8039291Sfenner#define SC_HISTORY_SIZE (ROW * 4) 8139291Sfenner#endif 8239291Sfenner 8339291Sfenner#if (SC_HISTORY_SIZE * MAXCONS) > SC_MAX_HISTORY_SIZE 8417683Spst#undef SC_MAX_HISTORY_SIZE 8517683Spst#define SC_MAX_HISTORY_SIZE (SC_HISTORY_SIZE * MAXCONS) 8617683Spst#endif 8717683Spst 8817683Spst#define COLD 0 8917683Spst#define WARM 1 9017683Spst 9117683Spst#define MODE_MAP_SIZE (M_VGA_CG320 + 1) 9217683Spst#define MODE_PARAM_SIZE 64 9317683Spst 9417683Spst/* XXX use sc_bcopy where video memory is concerned */ 9517683Spst#define sc_bcopy generic_bcopy 9617683Spstextern void generic_bcopy(const void *, void *, size_t); 9717683Spst 9817683Spststatic default_attr user_default = { 9917683Spst (FG_LIGHTGREY | BG_BLACK) << 8, 10017683Spst (FG_BLACK | BG_LIGHTGREY) << 8 10117683Spst}; 10217683Spst 10317683Spststatic default_attr kernel_default = { 10417683Spst (FG_WHITE | BG_BLACK) << 8, 10517683Spst (FG_BLACK | BG_LIGHTGREY) << 8 10617683Spst}; 10717683Spst 10817683Spststatic scr_stat main_console; 10917683Spststatic scr_stat *console[MAXCONS]; 11017683Spst#ifdef DEVFS 11117683Spststatic void *sc_devfs_token[MAXCONS]; 11217683Spststatic void *sc_mouse_devfs_token; 11317683Spststatic void *sc_console_devfs_token; 11417683Spst#endif 11517683Spst scr_stat *cur_console; 11617683Spststatic scr_stat *new_scp, *old_scp; 11717683Spststatic term_stat kernel_console; 11817683Spststatic default_attr *current_default; 11917683Spststatic int flags = 0; 12017683Spststatic int sc_port = IO_KBD; 12117683Spststatic KBDC sc_kbdc = NULL; 12217683Spststatic char init_done = COLD; 12317683Spststatic u_short sc_buffer[ROW*COL]; 12417683Spststatic char switch_in_progress = FALSE; 12517683Spststatic char write_in_progress = FALSE; 12617683Spststatic char blink_in_progress = FALSE; 12717683Spststatic int blinkrate = 0; 12817683Spst u_int crtc_addr = MONO_BASE; 12917683Spst char crtc_type = KD_MONO; 13017683Spst char crtc_vga = FALSE; 13117683Spststatic u_char shfts = 0, ctls = 0, alts = 0, agrs = 0, metas = 0; 13217683Spststatic u_char accents = 0; 13317683Spststatic u_char nlkcnt = 0, clkcnt = 0, slkcnt = 0, alkcnt = 0; 13417683Spststatic const u_int n_fkey_tab = sizeof(fkey_tab) / sizeof(*fkey_tab); 13517683Spststatic int delayed_next_scr = FALSE; 13617683Spststatic long scrn_blank_time = 0; /* screen saver timeout value */ 13717683Spst int scrn_blanked = 0; /* screen saver active flag */ 13817683Spststatic long scrn_time_stamp; 13917683Spst u_char scr_map[256]; 14017683Spst u_char scr_rmap[256]; 14117683Spst char *video_mode_ptr = NULL; 14217683Spst int fonts_loaded = 0 14317683Spst#ifdef STD8X16FONT 14417683Spst | FONT_16 14517683Spst#endif 14617683Spst ; 14717683Spst 14817683Spst char font_8[256*8]; 14917683Spst char font_14[256*14]; 15017683Spst#ifdef STD8X16FONT 15117683Spstextern 15217683Spst#endif 15317683Spst unsigned char font_16[256*16]; 15417683Spst char palette[256*3]; 15517683Spststatic char *mode_map[MODE_MAP_SIZE]; 15617683Spststatic char vgaregs[MODE_PARAM_SIZE]; 15717683Spststatic char vgaregs2[MODE_PARAM_SIZE]; 15817683Spststatic int rows_offset = 1; 15917683Spststatic char *cut_buffer; 16017683Spststatic int mouse_level = 0; /* sysmouse protocol level */ 16117683Spststatic mousestatus_t mouse_status = { 0, 0, 0, 0, 0, 0 }; 16217683Spststatic u_short mouse_and_mask[16] = { 16317683Spst 0xc000, 0xe000, 0xf000, 0xf800, 16417683Spst 0xfc00, 0xfe00, 0xff00, 0xff80, 16517683Spst 0xfe00, 0x1e00, 0x1f00, 0x0f00, 16617683Spst 0x0f00, 0x0000, 0x0000, 0x0000 16717683Spst }; 16817683Spststatic u_short mouse_or_mask[16] = { 16917683Spst 0x0000, 0x4000, 0x6000, 0x7000, 17017683Spst 0x7800, 0x7c00, 0x7e00, 0x6800, 17117683Spst 0x0c00, 0x0c00, 0x0600, 0x0600, 17217683Spst 0x0000, 0x0000, 0x0000, 0x0000 17317683Spst }; 17498530Sfenner 17598530Sfennerstatic int extra_history_size = 17698530Sfenner SC_MAX_HISTORY_SIZE - SC_HISTORY_SIZE * MAXCONS; 17798530Sfenner 17898530Sfennerstatic void none_saver(int blank) { } 17998530Sfennerstatic void (*current_saver)(int blank) = none_saver; 18098530Sfennerint (*sc_user_ioctl)(dev_t dev, int cmd, caddr_t data, 18198530Sfenner int flag, struct proc *p) = NULL; 18298530Sfenner 18398530Sfenner/* OS specific stuff */ 18498530Sfenner#ifdef not_yet_done 18598530Sfenner#define VIRTUAL_TTY(x) (sccons[x] = ttymalloc(sccons[x])) 18698530Sfennerstruct CONSOLE_TTY (sccons[MAXCONS] = ttymalloc(sccons[MAXCONS])) 18798530Sfennerstruct MOUSE_TTY (sccons[MAXCONS+1] = ttymalloc(sccons[MAXCONS+1])) 18898530Sfennerstruct tty *sccons[MAXCONS+2]; 18998530Sfenner#else 19098530Sfenner#define VIRTUAL_TTY(x) &sccons[x] 19198530Sfenner#define CONSOLE_TTY &sccons[MAXCONS] 19298530Sfenner#define MOUSE_TTY &sccons[MAXCONS+1] 19398530Sfennerstatic struct tty sccons[MAXCONS+2]; 19498530Sfenner#endif 19598530Sfenner#define SC_MOUSE 128 19698530Sfenner#define SC_CONSOLE 255 19798530Sfenner#define MONO_BUF pa_to_va(0xB0000) 19898530Sfenner#define CGA_BUF pa_to_va(0xB8000) 19998530Sfenneru_short *Crtat; 20098530Sfennerstatic const int nsccons = MAXCONS+2; 20198530Sfenner 20298530Sfenner#define WRAPHIST(scp, pointer, offset)\ 20398530Sfenner ((scp->history) + ((((pointer) - (scp->history)) + (scp->history_size)\ 20498530Sfenner + (offset)) % (scp->history_size))) 20598530Sfenner#define ISSIGVALID(sig) ((sig) > 0 && (sig) < NSIG) 20698530Sfenner 20798530Sfenner/* this should really be in `rtc.h' */ 20898530Sfenner#define RTC_EQUIPMENT 0x14 20998530Sfenner 21098530Sfenner/* prototypes */ 21198530Sfennerstatic int scattach(struct isa_device *dev); 21298530Sfennerstatic int scparam(struct tty *tp, struct termios *t); 21398530Sfennerstatic int scprobe(struct isa_device *dev); 21498530Sfennerstatic int scvidprobe(int unit, int flags); 21598530Sfennerstatic int sckbdprobe(int unit, int flags); 21698530Sfennerstatic void scstart(struct tty *tp); 21798530Sfennerstatic void scmousestart(struct tty *tp); 21898530Sfennerstatic void scinit(void); 21998530Sfennerstatic void map_mode_table(char *map[], char *table, int max); 22098530Sfennerstatic u_char map_mode_num(u_char mode); 22198530Sfennerstatic char *get_mode_param(scr_stat *scp, u_char mode); 22298530Sfennerstatic u_int scgetc(u_int flags); 22398530Sfenner#define SCGETC_CN 1 22498530Sfenner#define SCGETC_NONBLOCK 2 22598530Sfennerstatic scr_stat *get_scr_stat(dev_t dev); 22698530Sfennerstatic scr_stat *alloc_scp(void); 22798530Sfennerstatic void init_scp(scr_stat *scp); 22898530Sfennerstatic int get_scr_num(void); 22998530Sfennerstatic timeout_t scrn_timer; 23098530Sfennerstatic void stop_scrn_saver(void (*saver)(int)); 23198530Sfennerstatic void clear_screen(scr_stat *scp); 23298530Sfennerstatic int switch_scr(scr_stat *scp, u_int next_scr); 23317683Spststatic void exchange_scr(void); 23417683Spststatic inline void move_crsr(scr_stat *scp, int x, int y); 23517683Spststatic void scan_esc(scr_stat *scp, u_char c); 23617683Spststatic void draw_cursor_image(scr_stat *scp); 23717683Spststatic void remove_cursor_image(scr_stat *scp); 23817683Spststatic void ansi_put(scr_stat *scp, u_char *buf, int len); 23917683Spststatic u_char *get_fstr(u_int c, u_int *len); 24017683Spststatic void history_to_screen(scr_stat *scp); 24117683Spststatic int history_up_line(scr_stat *scp); 24217683Spststatic int history_down_line(scr_stat *scp); 24317683Spststatic int mask2attr(struct term_stat *term); 24417683Spststatic void set_keyboard(int command, int data); 24517683Spststatic void update_leds(int which); 24617683Spststatic void set_vgaregs(char *modetable); 24775107Sfennerstatic void read_vgaregs(char *buf); 24817683Spst#define COMP_IDENTICAL 0 24917683Spst#define COMP_SIMILAR 1 25017683Spst#define COMP_DIFFERENT 2 25117683Spststatic int comp_vgaregs(u_char *buf1, u_char *buf2); 25275107Sfennerstatic void dump_vgaregs(u_char *buf); 25375107Sfenner#define PARAM_BUFSIZE 6 25475107Sfennerstatic void set_font_mode(u_char *buf); 25575107Sfennerstatic void set_normal_mode(u_char *buf); 25675107Sfennerstatic void set_destructive_cursor(scr_stat *scp); 25775107Sfennerstatic void set_mouse_pos(scr_stat *scp); 25875107Sfennerstatic int skip_spc_right(scr_stat *scp, u_short *p); 25975107Sfennerstatic int skip_spc_left(scr_stat *scp, u_short *p); 26075107Sfennerstatic void mouse_cut(scr_stat *scp); 26175107Sfennerstatic void mouse_cut_start(scr_stat *scp); 26275107Sfennerstatic void mouse_cut_end(scr_stat *scp); 26375107Sfennerstatic void mouse_cut_word(scr_stat *scp); 26475107Sfennerstatic void mouse_cut_line(scr_stat *scp); 26575107Sfennerstatic void mouse_cut_extend(scr_stat *scp); 26675107Sfennerstatic void mouse_paste(scr_stat *scp); 26717683Spststatic void draw_mouse_image(scr_stat *scp); 26817683Spststatic void remove_mouse_image(scr_stat *scp); 26917683Spststatic void draw_cutmarking(scr_stat *scp); 27017683Spststatic void remove_cutmarking(scr_stat *scp); 27175107Sfennerstatic void save_palette(void); 27275107Sfennerstatic void do_bell(scr_stat *scp, int pitch, int duration); 27375107Sfennerstatic timeout_t blink_screen; 27475107Sfenner#ifdef SC_SPLASH_SCREEN 27517683Spststatic void toggle_splash_screen(scr_stat *scp); 27675107Sfenner#endif 27717683Spst 27875107Sfennerstruct isa_driver scdriver = { 27975107Sfenner scprobe, scattach, "sc", 1 28017683Spst}; 28117683Spst 28217683Spststatic d_open_t scopen; 28317683Spststatic d_close_t scclose; 28417683Spststatic d_read_t scread; 28575107Sfennerstatic d_write_t scwrite; 28617683Spststatic d_ioctl_t scioctl; 28717683Spststatic d_devtotty_t scdevtotty; 288static d_mmap_t scmmap; 289 290#define CDEV_MAJOR 12 291static struct cdevsw scdevsw = { 292 scopen, scclose, scread, scwrite, 293 scioctl, nullstop, noreset, scdevtotty, 294 ttpoll, scmmap, nostrategy, "sc", NULL, -1 }; 295 296/* 297 * These functions need to be before calls to them so they can be inlined. 298 */ 299static inline void 300draw_cursor_image(scr_stat *scp) 301{ 302 u_short cursor_image, *ptr = Crtat + (scp->cursor_pos - scp->scr_buf); 303 u_short prev_image; 304 305 /* do we have a destructive cursor ? */ 306 if (flags & CHAR_CURSOR) { 307 prev_image = scp->cursor_saveunder; 308 cursor_image = *ptr & 0x00ff; 309 if (cursor_image == DEAD_CHAR) 310 cursor_image = prev_image & 0x00ff; 311 cursor_image |= *(scp->cursor_pos) & 0xff00; 312 scp->cursor_saveunder = cursor_image; 313 /* update the cursor bitmap if the char under the cursor has changed */ 314 if (prev_image != cursor_image) 315 set_destructive_cursor(scp); 316 /* modify cursor_image */ 317 if (!(flags & BLINK_CURSOR)||((flags & BLINK_CURSOR)&&(blinkrate & 4))){ 318 /* 319 * When the mouse pointer is at the same position as the cursor, 320 * the cursor bitmap needs to be updated even if the char under 321 * the cursor hasn't changed, because the mouse pionter may 322 * have moved by a few dots within the cursor cel. 323 */ 324 if ((prev_image == cursor_image) 325 && (cursor_image != *(scp->cursor_pos))) 326 set_destructive_cursor(scp); 327 cursor_image &= 0xff00; 328 cursor_image |= DEAD_CHAR; 329 } 330 } 331 else { 332 cursor_image = (*(ptr) & 0x00ff) | *(scp->cursor_pos) & 0xff00; 333 scp->cursor_saveunder = cursor_image; 334 if (!(flags & BLINK_CURSOR)||((flags & BLINK_CURSOR)&&(blinkrate & 4))){ 335 if ((cursor_image & 0x7000) == 0x7000) { 336 cursor_image &= 0x8fff; 337 if(!(cursor_image & 0x0700)) 338 cursor_image |= 0x0700; 339 } else { 340 cursor_image |= 0x7000; 341 if ((cursor_image & 0x0700) == 0x0700) 342 cursor_image &= 0xf0ff; 343 } 344 } 345 } 346 *ptr = cursor_image; 347} 348 349static inline void 350remove_cursor_image(scr_stat *scp) 351{ 352 *(Crtat + (scp->cursor_oldpos - scp->scr_buf)) = scp->cursor_saveunder; 353} 354 355static inline void 356move_crsr(scr_stat *scp, int x, int y) 357{ 358 if (x < 0) 359 x = 0; 360 if (y < 0) 361 y = 0; 362 if (x >= scp->xsize) 363 x = scp->xsize-1; 364 if (y >= scp->ysize) 365 y = scp->ysize-1; 366 scp->xpos = x; 367 scp->ypos = y; 368 scp->cursor_pos = scp->scr_buf + scp->ypos * scp->xsize + scp->xpos; 369} 370 371static int 372scprobe(struct isa_device *dev) 373{ 374 if (!scvidprobe(dev->id_unit, dev->id_flags)) { 375 if (bootverbose) 376 printf("sc%d: no video adapter is found.\n", dev->id_unit); 377 return (0); 378 } 379 380 sc_port = dev->id_iobase; 381 if (sckbdprobe(dev->id_unit, dev->id_flags)) 382 return (IO_KBDSIZE); 383 else 384 return ((dev->id_flags & DETECT_KBD) ? 0 : IO_KBDSIZE); 385} 386 387/* probe video adapters, return TRUE if found */ 388static int 389scvidprobe(int unit, int flags) 390{ 391 /* 392 * XXX don't try to `printf' anything here, the console may not have 393 * been configured yet. 394 */ 395 u_short volatile *cp; 396 u_short was; 397 u_long pa; 398 u_long segoff; 399 400 /* do this test only once */ 401 if (init_done != COLD) 402 return (Crtat != 0); 403 404 /* 405 * Finish defaulting crtc variables for a mono screen. Crtat is a 406 * bogus common variable so that it can be shared with pcvt, so it 407 * can't be statically initialized. XXX. 408 */ 409 Crtat = (u_short *)MONO_BUF; 410 crtc_type = KD_MONO; 411 /* If CGA memory seems to work, switch to color. */ 412 cp = (u_short *)CGA_BUF; 413 was = *cp; 414 *cp = (u_short) 0xA55A; 415 if (*cp == 0xA55A) { 416 Crtat = (u_short *)CGA_BUF; 417 crtc_addr = COLOR_BASE; 418 crtc_type = KD_CGA; 419 } else { 420 cp = Crtat; 421 was = *cp; 422 *cp = (u_short) 0xA55A; 423 if (*cp != 0xA55A) { 424 /* no screen at all, bail out */ 425 Crtat = 0; 426 return FALSE; 427 } 428 } 429 *cp = was; 430 431 /* 432 * Check rtc and BIOS date area. 433 * XXX: don't use BIOSDATA_EQUIPMENT, it is not a dead copy 434 * of RTC_EQUIPMENT. The bit 4 and 5 of the ETC_EQUIPMENT are 435 * zeros for EGA and VGA. However, the EGA/VGA BIOS will set 436 * these bits in BIOSDATA_EQUIPMENT according to the monitor 437 * type detected. 438 */ 439 switch ((rtcin(RTC_EQUIPMENT) >> 4) & 3) { /* bit 4 and 5 */ 440 case 0: /* EGA/VGA, or nothing */ 441 crtc_type = KD_EGA; 442 /* the color adapter may be in the 40x25 mode... XXX */ 443 break; 444 case 1: /* CGA 40x25 */ 445 /* switch to the 80x25 mode? XXX */ 446 /* FALL THROUGH */ 447 case 2: /* CGA 80x25 */ 448 /* `crtc_type' has already been set... */ 449 /* crtc_type = KD_CGA; */ 450 break; 451 case 3: /* MDA */ 452 /* `crtc_type' has already been set... */ 453 /* crtc_type = KD_MONO; */ 454 break; 455 } 456 457 /* is this a VGA or higher ? */ 458 outb(crtc_addr, 7); 459 if (inb(crtc_addr) == 7) { 460 461 crtc_type = KD_VGA; 462 crtc_vga = TRUE; 463 read_vgaregs(vgaregs); 464 465 /* Get the BIOS video mode pointer */ 466 segoff = *(u_long *)pa_to_va(0x4a8); 467 pa = (((segoff & 0xffff0000) >> 12) + (segoff & 0xffff)); 468 if (ISMAPPED(pa, sizeof(u_long))) { 469 segoff = *(u_long *)pa_to_va(pa); 470 pa = (((segoff & 0xffff0000) >> 12) + (segoff & 0xffff)); 471 if (ISMAPPED(pa, MODE_PARAM_SIZE)) 472 video_mode_ptr = (char *)pa_to_va(pa); 473 } 474 } 475 476 return TRUE; 477} 478 479/* probe the keyboard, return TRUE if found */ 480static int 481sckbdprobe(int unit, int flags) 482{ 483 int codeset; 484 int c = -1; 485 int m; 486 487 sc_kbdc = kbdc_open(sc_port); 488 489 if (!kbdc_lock(sc_kbdc, TRUE)) { 490 /* driver error? */ 491 printf("sc%d: unable to lock the controller.\n", unit); 492 return ((flags & DETECT_KBD) ? FALSE : TRUE); 493 } 494 495 /* discard anything left after UserConfig */ 496 empty_both_buffers(sc_kbdc, 10); 497 498 /* save the current keyboard controller command byte */ 499 m = kbdc_get_device_mask(sc_kbdc) & ~KBD_KBD_CONTROL_BITS; 500 c = get_controller_command_byte(sc_kbdc); 501 if (c == -1) { 502 /* CONTROLLER ERROR */ 503 printf("sc%d: unable to get the current command byte value.\n", unit); 504 goto fail; 505 } 506 if (bootverbose) 507 printf("sc%d: the current keyboard controller command byte %04x\n", 508 unit, c); 509#if 0 510 /* override the keyboard lock switch */ 511 c |= KBD_OVERRIDE_KBD_LOCK; 512#endif 513 514 /* 515 * The keyboard may have been screwed up by the boot block. 516 * We may just be able to recover from error by testing the controller 517 * and the keyboard port. The controller command byte needs to be saved 518 * before this recovery operation, as some controllers seem to set 519 * the command byte to particular values. 520 */ 521 test_controller(sc_kbdc); 522 test_kbd_port(sc_kbdc); 523 524 /* enable the keyboard port, but disable the keyboard intr. */ 525 if (!set_controller_command_byte(sc_kbdc, 526 KBD_KBD_CONTROL_BITS, 527 KBD_ENABLE_KBD_PORT | KBD_DISABLE_KBD_INT)) { 528 /* CONTROLLER ERROR 529 * there is very little we can do... 530 */ 531 printf("sc%d: unable to set the command byte.\n", unit); 532 goto fail; 533 } 534 535 /* 536 * Check if we have an XT keyboard before we attempt to reset it. 537 * The procedure assumes that the keyboard and the controller have 538 * been set up properly by BIOS and have not been messed up 539 * during the boot process. 540 */ 541 codeset = -1; 542 if (flags & XT_KEYBD) 543 /* the user says there is a XT keyboard */ 544 codeset = 1; 545#ifdef DETECT_XT_KEYBOARD 546 else if ((c & KBD_TRANSLATION) == 0) { 547 /* SET_SCANCODE_SET is not always supported; ignore error */ 548 if (send_kbd_command_and_data(sc_kbdc, KBDC_SET_SCANCODE_SET, 0) 549 == KBD_ACK) 550 codeset = read_kbd_data(sc_kbdc); 551 } 552 if (bootverbose) 553 printf("sc%d: keyboard scancode set %d\n", unit, codeset); 554#endif /* DETECT_XT_KEYBOARD */ 555 556 if (flags & KBD_NORESET) { 557 write_kbd_command(sc_kbdc, KBDC_ECHO); 558 if (read_kbd_data(sc_kbdc) != KBD_ECHO) { 559 empty_both_buffers(sc_kbdc, 10); 560 test_controller(sc_kbdc); 561 test_kbd_port(sc_kbdc); 562 if (bootverbose) 563 printf("sc%d: failed to get response from the keyboard.\n", 564 unit); 565 goto fail; 566 } 567 } else { 568 /* reset keyboard hardware */ 569 if (!reset_kbd(sc_kbdc)) { 570 /* KEYBOARD ERROR 571 * Keyboard reset may fail either because the keyboard doen't 572 * exist, or because the keyboard doesn't pass the self-test, 573 * or the keyboard controller on the motherboard and the keyboard 574 * somehow fail to shake hands. It is just possible, particularly 575 * in the last case, that the keyoard controller may be left 576 * in a hung state. test_controller() and test_kbd_port() appear 577 * to bring the keyboard controller back (I don't know why and 578 * how, though.) 579 */ 580 empty_both_buffers(sc_kbdc, 10); 581 test_controller(sc_kbdc); 582 test_kbd_port(sc_kbdc); 583 /* We could disable the keyboard port and interrupt... but, 584 * the keyboard may still exist (see above). 585 */ 586 if (bootverbose) 587 printf("sc%d: failed to reset the keyboard.\n", unit); 588 goto fail; 589 } 590 } 591 592 /* 593 * Allow us to set the XT_KEYBD flag in UserConfig so that keyboards 594 * such as those on the IBM ThinkPad laptop computers can be used 595 * with the standard console driver. 596 */ 597 if (codeset == 1) { 598 if (send_kbd_command_and_data( 599 sc_kbdc, KBDC_SET_SCANCODE_SET, codeset) == KBD_ACK) { 600 /* XT kbd doesn't need scan code translation */ 601 c &= ~KBD_TRANSLATION; 602 } else { 603 /* KEYBOARD ERROR 604 * The XT kbd isn't usable unless the proper scan code set 605 * is selected. 606 */ 607 printf("sc%d: unable to set the XT keyboard mode.\n", unit); 608 goto fail; 609 } 610 } 611 /* enable the keyboard port and intr. */ 612 if (!set_controller_command_byte(sc_kbdc, 613 KBD_KBD_CONTROL_BITS | KBD_TRANSLATION | KBD_OVERRIDE_KBD_LOCK, 614 (c & (KBD_TRANSLATION | KBD_OVERRIDE_KBD_LOCK)) 615 | KBD_ENABLE_KBD_PORT | KBD_ENABLE_KBD_INT)) { 616 /* CONTROLLER ERROR 617 * This is serious; we are left with the disabled keyboard intr. 618 */ 619 printf("sc%d: unable to enable the keyboard port and intr.\n", unit); 620 goto fail; 621 } 622 623 kbdc_set_device_mask(sc_kbdc, m | KBD_KBD_CONTROL_BITS), 624 kbdc_lock(sc_kbdc, FALSE); 625 return TRUE; 626 627fail: 628 if (c != -1) 629 /* try to restore the command byte as before, if possible */ 630 set_controller_command_byte(sc_kbdc, 0xff, c); 631 kbdc_set_device_mask(sc_kbdc, 632 (flags & DETECT_KBD) ? m : m | KBD_KBD_CONTROL_BITS); 633 kbdc_lock(sc_kbdc, FALSE); 634 return FALSE; 635} 636 637#if NAPM > 0 638static int 639scresume(void *dummy) 640{ 641 shfts = ctls = alts = agrs = metas = accents = 0; 642 return 0; 643} 644#endif 645 646static int 647scattach(struct isa_device *dev) 648{ 649 scr_stat *scp; 650 dev_t cdev = makedev(CDEV_MAJOR, 0); 651 char *p; 652#ifdef DEVFS 653 int vc; 654#endif 655 656 scinit(); 657 flags = dev->id_flags; 658 if (!crtc_vga) 659 flags &= ~CHAR_CURSOR; 660 661 scp = console[0]; 662 663 if (crtc_vga) { 664 cut_buffer = (char *)malloc(scp->xsize*scp->ysize, M_DEVBUF, M_NOWAIT); 665 } 666 667 scp->scr_buf = (u_short *)malloc(scp->xsize*scp->ysize*sizeof(u_short), 668 M_DEVBUF, M_NOWAIT); 669 670 /* copy temporary buffer to final buffer */ 671 bcopy(sc_buffer, scp->scr_buf, scp->xsize * scp->ysize * sizeof(u_short)); 672 673 scp->cursor_pos = scp->cursor_oldpos = 674 scp->scr_buf + scp->xpos + scp->ypos * scp->xsize; 675 scp->mouse_pos = scp->mouse_oldpos = 676 scp->scr_buf + ((scp->mouse_ypos/scp->font_size)*scp->xsize + 677 scp->mouse_xpos/8); 678 679 /* initialize history buffer & pointers */ 680 scp->history_head = scp->history_pos = 681 (u_short *)malloc(scp->history_size*sizeof(u_short), 682 M_DEVBUF, M_NOWAIT); 683 if (scp->history_head != NULL) 684 bzero(scp->history_head, scp->history_size*sizeof(u_short)); 685 scp->history = scp->history_head; 686 687 /* initialize cursor stuff */ 688 if (!(scp->status & UNKNOWN_MODE)) 689 draw_cursor_image(scp); 690 691 /* get screen update going */ 692 scrn_timer(NULL); 693 694 update_leds(scp->status); 695 696 if ((crtc_type == KD_VGA) && bootverbose) { 697 printf("sc%d: BIOS video mode:%d\n", 698 dev->id_unit, *(u_char *)pa_to_va(0x449)); 699 printf("sc%d: VGA registers upon power-up\n", dev->id_unit); 700 dump_vgaregs(vgaregs); 701 printf("sc%d: video mode:%d\n", dev->id_unit, scp->mode); 702 printf("sc%d: VGA registers in BIOS for mode:%d\n", 703 dev->id_unit, scp->mode); 704 dump_vgaregs(vgaregs2); 705 p = get_mode_param(scp, scp->mode); 706 if (p != NULL) { 707 printf("sc%d: VGA registers to be used for mode:%d\n", 708 dev->id_unit, scp->mode); 709 dump_vgaregs(p); 710 } 711 printf("sc%d: rows_offset:%d\n", dev->id_unit, rows_offset); 712 } 713 if ((crtc_type == KD_VGA) && (video_mode_ptr == NULL)) 714 printf("sc%d: WARNING: video mode switching is only partially supported\n", 715 dev->id_unit); 716 717 printf("sc%d: ", dev->id_unit); 718 switch(crtc_type) { 719 case KD_VGA: 720 if (crtc_addr == MONO_BASE) 721 printf("VGA mono"); 722 else 723 printf("VGA color"); 724 break; 725 case KD_EGA: 726 if (crtc_addr == MONO_BASE) 727 printf("EGA mono"); 728 else 729 printf("EGA color"); 730 break; 731 case KD_CGA: 732 printf("CGA"); 733 break; 734 case KD_MONO: 735 case KD_HERCULES: 736 default: 737 printf("MDA/hercules"); 738 break; 739 } 740 printf(" <%d virtual consoles, flags=0x%x>\n", MAXCONS, flags); 741 742#if NAPM > 0 743 scp->r_hook.ah_fun = scresume; 744 scp->r_hook.ah_arg = NULL; 745 scp->r_hook.ah_name = "system keyboard"; 746 scp->r_hook.ah_order = APM_MID_ORDER; 747 apm_hook_establish(APM_HOOK_RESUME , &scp->r_hook); 748#endif 749 750 cdevsw_add(&cdev, &scdevsw, NULL); 751 752#ifdef DEVFS 753 for (vc = 0; vc < MAXCONS; vc++) 754 sc_devfs_token[vc] = devfs_add_devswf(&scdevsw, vc, DV_CHR, 755 UID_ROOT, GID_WHEEL, 0600, "ttyv%n", vc); 756 sc_mouse_devfs_token = devfs_add_devswf(&scdevsw, SC_MOUSE, DV_CHR, 757 UID_ROOT, GID_WHEEL, 0600, "sysmouse"); 758 sc_console_devfs_token = devfs_add_devswf(&scdevsw, SC_CONSOLE, DV_CHR, 759 UID_ROOT, GID_WHEEL, 0600, "consolectl"); 760#endif 761 return 0; 762} 763 764struct tty 765*scdevtotty(dev_t dev) 766{ 767 int unit = minor(dev); 768 769 if (init_done == COLD) 770 return(NULL); 771 if (unit == SC_CONSOLE) 772 return CONSOLE_TTY; 773 if (unit == SC_MOUSE) 774 return MOUSE_TTY; 775 if (unit >= MAXCONS || unit < 0) 776 return(NULL); 777 return VIRTUAL_TTY(unit); 778} 779 780int 781scopen(dev_t dev, int flag, int mode, struct proc *p) 782{ 783 struct tty *tp = scdevtotty(dev); 784 785 if (!tp) 786 return(ENXIO); 787 788 tp->t_oproc = (minor(dev) == SC_MOUSE) ? scmousestart : scstart; 789 tp->t_param = scparam; 790 tp->t_dev = dev; 791 if (!(tp->t_state & TS_ISOPEN)) { 792 ttychars(tp); 793 /* Use the current setting of the <-- key as default VERASE. */ 794 /* If the Delete key is preferable, an stty is necessary */ 795 tp->t_cc[VERASE] = key_map.key[0x0e].map[0]; 796 tp->t_iflag = TTYDEF_IFLAG; 797 tp->t_oflag = TTYDEF_OFLAG; 798 tp->t_cflag = TTYDEF_CFLAG; 799 tp->t_lflag = TTYDEF_LFLAG; 800 tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; 801 scparam(tp, &tp->t_termios); 802 ttsetwater(tp); 803 (*linesw[tp->t_line].l_modem)(tp, 1); 804 if (minor(dev) == SC_MOUSE) 805 mouse_level = 0; /* XXX */ 806 } 807 else 808 if (tp->t_state & TS_XCLUDE && p->p_ucred->cr_uid != 0) 809 return(EBUSY); 810 if (minor(dev) < MAXCONS && !console[minor(dev)]) { 811 console[minor(dev)] = alloc_scp(); 812 } 813 if (minor(dev)<MAXCONS && !tp->t_winsize.ws_col && !tp->t_winsize.ws_row) { 814 tp->t_winsize.ws_col = console[minor(dev)]->xsize; 815 tp->t_winsize.ws_row = console[minor(dev)]->ysize; 816 } 817 return ((*linesw[tp->t_line].l_open)(dev, tp)); 818} 819 820int 821scclose(dev_t dev, int flag, int mode, struct proc *p) 822{ 823 struct tty *tp = scdevtotty(dev); 824 struct scr_stat *scp; 825 826 if (!tp) 827 return(ENXIO); 828 if (minor(dev) < MAXCONS) { 829 scp = get_scr_stat(tp->t_dev); 830 if (scp->status & SWITCH_WAIT_ACQ) 831 wakeup((caddr_t)&scp->smode); 832#if not_yet_done 833 if (scp == &main_console) { 834 scp->pid = 0; 835 scp->proc = NULL; 836 scp->smode.mode = VT_AUTO; 837 } 838 else { 839 free(scp->scr_buf, M_DEVBUF); 840 if (scp->history != NULL) { 841 free(scp->history, M_DEVBUF); 842 if (scp->history_size / scp->xsize 843 > imax(SC_HISTORY_SIZE, scp->ysize)) 844 extra_history_size += scp->history_size / scp->xsize 845 - imax(SC_HISTORY_SIZE, scp->ysize); 846 } 847 free(scp, M_DEVBUF); 848 console[minor(dev)] = NULL; 849 } 850#else 851 scp->pid = 0; 852 scp->proc = NULL; 853 scp->smode.mode = VT_AUTO; 854#endif 855 } 856 spltty(); 857 (*linesw[tp->t_line].l_close)(tp, flag); 858 ttyclose(tp); 859 spl0(); 860 return(0); 861} 862 863int 864scread(dev_t dev, struct uio *uio, int flag) 865{ 866 struct tty *tp = scdevtotty(dev); 867 868 if (!tp) 869 return(ENXIO); 870 return((*linesw[tp->t_line].l_read)(tp, uio, flag)); 871} 872 873int 874scwrite(dev_t dev, struct uio *uio, int flag) 875{ 876 struct tty *tp = scdevtotty(dev); 877 878 if (!tp) 879 return(ENXIO); 880 return((*linesw[tp->t_line].l_write)(tp, uio, flag)); 881} 882 883void 884scintr(int unit) 885{ 886 static struct tty *cur_tty; 887 int c, len; 888 u_char *cp; 889 890 /* make screensaver happy */ 891 scrn_time_stamp = mono_time.tv_sec; 892 893 /* 894 * Loop while there is still input to get from the keyboard. 895 * I don't think this is nessesary, and it doesn't fix 896 * the Xaccel-2.1 keyboard hang, but it can't hurt. XXX 897 */ 898 while ((c = scgetc(SCGETC_NONBLOCK)) != NOKEY) { 899 900 cur_tty = VIRTUAL_TTY(get_scr_num()); 901 if (!(cur_tty->t_state & TS_ISOPEN)) 902 if (!((cur_tty = CONSOLE_TTY)->t_state & TS_ISOPEN)) 903 continue; 904 905 switch (c & 0xff00) { 906 case 0x0000: /* normal key */ 907 (*linesw[cur_tty->t_line].l_rint)(c & 0xFF, cur_tty); 908 break; 909 case FKEY: /* function key, return string */ 910 if (cp = get_fstr((u_int)c, (u_int *)&len)) { 911 while (len-- > 0) 912 (*linesw[cur_tty->t_line].l_rint)(*cp++ & 0xFF, cur_tty); 913 } 914 break; 915 case MKEY: /* meta is active, prepend ESC */ 916 (*linesw[cur_tty->t_line].l_rint)(0x1b, cur_tty); 917 (*linesw[cur_tty->t_line].l_rint)(c & 0xFF, cur_tty); 918 break; 919 case BKEY: /* backtab fixed sequence (esc [ Z) */ 920 (*linesw[cur_tty->t_line].l_rint)(0x1b, cur_tty); 921 (*linesw[cur_tty->t_line].l_rint)('[', cur_tty); 922 (*linesw[cur_tty->t_line].l_rint)('Z', cur_tty); 923 break; 924 } 925 } 926 927 if (cur_console->status & MOUSE_ENABLED) { 928 cur_console->status &= ~MOUSE_VISIBLE; 929 remove_mouse_image(cur_console); 930 } 931} 932 933static int 934scparam(struct tty *tp, struct termios *t) 935{ 936 tp->t_ispeed = t->c_ispeed; 937 tp->t_ospeed = t->c_ospeed; 938 tp->t_cflag = t->c_cflag; 939 return 0; 940} 941 942int 943scioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p) 944{ 945 int error; 946 u_int i; 947 struct tty *tp; 948 scr_stat *scp; 949 u_short *usp; 950 char *mp; 951 int s; 952 953 tp = scdevtotty(dev); 954 if (!tp) 955 return ENXIO; 956 scp = get_scr_stat(tp->t_dev); 957 958 /* If there is a user_ioctl function call that first */ 959 if (sc_user_ioctl) { 960 if (error = (*sc_user_ioctl)(dev, cmd, data, flag, p)) 961 return error; 962 } 963 964 switch (cmd) { /* process console hardware related ioctl's */ 965 966 case GIO_ATTR: /* get current attributes */ 967 *(int*)data = (scp->term.cur_attr >> 8) & 0xFF; 968 return 0; 969 970 case GIO_COLOR: /* is this a color console ? */ 971 if (crtc_addr == COLOR_BASE) 972 *(int*)data = 1; 973 else 974 *(int*)data = 0; 975 return 0; 976 977 case CONS_CURRENT: /* get current adapter type */ 978 *(int *)data = crtc_type; 979 return 0; 980 981 case CONS_GET: /* get current video mode */ 982 *(int*)data = scp->mode; 983 return 0; 984 985 case CONS_BLANKTIME: /* set screen saver timeout (0 = no saver) */ 986 if (*(int *)data < 0) 987 return EINVAL; 988 scrn_blank_time = *(int *)data; 989 if (scrn_blank_time == 0) 990 scrn_time_stamp = mono_time.tv_sec; 991 return 0; 992 993 case CONS_CURSORTYPE: /* set cursor type blink/noblink */ 994 if ((*(int*)data) & 0x01) 995 flags |= BLINK_CURSOR; 996 else 997 flags &= ~BLINK_CURSOR; 998 if ((*(int*)data) & 0x02) { 999 if (!crtc_vga) 1000 return ENXIO; 1001 flags |= CHAR_CURSOR; 1002 } else 1003 flags &= ~CHAR_CURSOR; 1004 /* 1005 * The cursor shape is global property; all virtual consoles 1006 * are affected. Update the cursor in the current console... 1007 */ 1008 if (!(cur_console->status & UNKNOWN_MODE)) { 1009 remove_cursor_image(cur_console); 1010 if (flags & CHAR_CURSOR) 1011 set_destructive_cursor(cur_console); 1012 draw_cursor_image(cur_console); 1013 } 1014 return 0; 1015 1016 case CONS_BELLTYPE: /* set bell type sound/visual */ 1017 if (*data) 1018 flags |= VISUAL_BELL; 1019 else 1020 flags &= ~VISUAL_BELL; 1021 return 0; 1022 1023 case CONS_HISTORY: /* set history size */ 1024 if (*(int *)data > 0) { 1025 int lines; /* buffer size to allocate */ 1026 int lines0; /* current buffer size */ 1027 1028 lines = imax(*(int *)data, scp->ysize); 1029 lines0 = (scp->history != NULL) ? 1030 scp->history_size / scp->xsize : scp->ysize; 1031 /* 1032 * syscons unconditionally allocates buffers upto SC_HISTORY_SIZE 1033 * lines or scp->ysize lines, whichever is larger. A value 1034 * greater than that is allowed, subject to extra_history_size. 1035 */ 1036 if (lines > imax(lines0, SC_HISTORY_SIZE) + extra_history_size) 1037 return EINVAL; 1038 if (cur_console->status & BUFFER_SAVED) 1039 return EBUSY; 1040 usp = scp->history; 1041 scp->history = NULL; 1042 if (usp != NULL) 1043 free(usp, M_DEVBUF); 1044 scp->history_size = lines * scp->xsize; 1045 /* 1046 * extra_history_size += 1047 * (lines0 > imax(SC_HISTORY_SIZE, scp->ysize)) ? 1048 * lines0 - imax(SC_HISTORY_SIZE, scp->ysize)) : 0; 1049 * extra_history_size -= 1050 * (lines > imax(SC_HISTORY_SIZE, scp->ysize)) ? 1051 * lines - imax(SC_HISTORY_SIZE, scp->ysize)) : 0; 1052 * lines0 >= ysize && lines >= ysize... Hey, the above can be 1053 * reduced to the following... 1054 */ 1055 extra_history_size += 1056 imax(lines0, SC_HISTORY_SIZE) - imax(lines, SC_HISTORY_SIZE); 1057 usp = (u_short *)malloc(scp->history_size * sizeof(u_short), 1058 M_DEVBUF, M_WAITOK); 1059 bzero(usp, scp->history_size * sizeof(u_short)); 1060 scp->history_head = scp->history_pos = usp; 1061 scp->history = usp; 1062 return 0; 1063 } 1064 else 1065 return EINVAL; 1066 1067 case CONS_MOUSECTL: /* control mouse arrow */ 1068 { 1069 /* MOUSE_BUTTON?DOWN -> MOUSE_MSC_BUTTON?UP */ 1070 static butmap[8] = { 1071 MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON2UP 1072 | MOUSE_MSC_BUTTON3UP, 1073 MOUSE_MSC_BUTTON2UP | MOUSE_MSC_BUTTON3UP, 1074 MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON3UP, 1075 MOUSE_MSC_BUTTON3UP, 1076 MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON2UP, 1077 MOUSE_MSC_BUTTON2UP, 1078 MOUSE_MSC_BUTTON1UP, 1079 0, 1080 }; 1081 mouse_info_t *mouse = (mouse_info_t*)data; 1082 1083 if (!crtc_vga) 1084 return ENODEV; 1085 1086 switch (mouse->operation) { 1087 case MOUSE_MODE: 1088 if (ISSIGVALID(mouse->u.mode.signal)) { 1089 scp->mouse_signal = mouse->u.mode.signal; 1090 scp->mouse_proc = p; 1091 scp->mouse_pid = p->p_pid; 1092 } 1093 else { 1094 scp->mouse_signal = 0; 1095 scp->mouse_proc = NULL; 1096 scp->mouse_pid = 0; 1097 } 1098 break; 1099 1100 case MOUSE_SHOW: 1101 if (!(scp->status & MOUSE_ENABLED)) { 1102 scp->status |= (MOUSE_ENABLED | MOUSE_VISIBLE); 1103 scp->mouse_oldpos = scp->mouse_pos; 1104 mark_all(scp); 1105 } 1106 else 1107 return EINVAL; 1108 break; 1109 1110 case MOUSE_HIDE: 1111 if (scp->status & MOUSE_ENABLED) { 1112 scp->status &= ~(MOUSE_ENABLED | MOUSE_VISIBLE); 1113 mark_all(scp); 1114 } 1115 else 1116 return EINVAL; 1117 break; 1118 1119 case MOUSE_MOVEABS: 1120 scp->mouse_xpos = mouse->u.data.x; 1121 scp->mouse_ypos = mouse->u.data.y; 1122 set_mouse_pos(scp); 1123 break; 1124 1125 case MOUSE_MOVEREL: 1126 scp->mouse_xpos += mouse->u.data.x; 1127 scp->mouse_ypos += mouse->u.data.y; 1128 set_mouse_pos(scp); 1129 break; 1130 1131 case MOUSE_GETINFO: 1132 mouse->u.data.x = scp->mouse_xpos; 1133 mouse->u.data.y = scp->mouse_ypos; 1134 mouse->u.data.z = 0; 1135 mouse->u.data.buttons = scp->mouse_buttons; 1136 break; 1137 1138 case MOUSE_ACTION: 1139 case MOUSE_MOTION_EVENT: 1140 /* this should maybe only be settable from /dev/consolectl SOS */ 1141 /* send out mouse event on /dev/sysmouse */ 1142 1143 mouse_status.dx += mouse->u.data.x; 1144 mouse_status.dy += mouse->u.data.y; 1145 mouse_status.dz += mouse->u.data.z; 1146 if (mouse->operation == MOUSE_ACTION) 1147 mouse_status.button = mouse->u.data.buttons; 1148 mouse_status.flags |= 1149 ((mouse->u.data.x || mouse->u.data.y || mouse->u.data.z) ? 1150 MOUSE_POSCHANGED : 0) 1151 | (mouse_status.obutton ^ mouse_status.button); 1152 1153 if (cur_console->status & MOUSE_ENABLED) 1154 cur_console->status |= MOUSE_VISIBLE; 1155 1156 if ((MOUSE_TTY)->t_state & TS_ISOPEN) { 1157 u_char buf[MOUSE_SYS_PACKETSIZE]; 1158 int j; 1159 1160 /* the first five bytes are compatible with MouseSystems' */ 1161 buf[0] = MOUSE_MSC_SYNC 1162 | butmap[mouse_status.button & MOUSE_STDBUTTONS]; 1163 j = imax(imin(mouse->u.data.x, 255), -256); 1164 buf[1] = j >> 1; 1165 buf[3] = j - buf[1]; 1166 j = -imax(imin(mouse->u.data.y, 255), -256); 1167 buf[2] = j >> 1; 1168 buf[4] = j - buf[2]; 1169 for (j = 0; j < MOUSE_MSC_PACKETSIZE; j++) 1170 (*linesw[(MOUSE_TTY)->t_line].l_rint)(buf[j],MOUSE_TTY); 1171 if (mouse_level >= 1) { /* extended part */ 1172 j = imax(imin(mouse->u.data.z, 127), -128); 1173 buf[5] = (j >> 1) & 0x7f; 1174 buf[6] = (j - (j >> 1)) & 0x7f; 1175 /* buttons 4-10 */ 1176 buf[7] = (~mouse_status.button >> 3) & 0x7f; 1177 for (j = MOUSE_MSC_PACKETSIZE; 1178 j < MOUSE_SYS_PACKETSIZE; j++) 1179 (*linesw[(MOUSE_TTY)->t_line].l_rint)(buf[j],MOUSE_TTY); 1180 } 1181 } 1182 1183 if (cur_console->mouse_signal) { 1184 cur_console->mouse_buttons = mouse->u.data.buttons; 1185 /* has controlling process died? */ 1186 if (cur_console->mouse_proc && 1187 (cur_console->mouse_proc != pfind(cur_console->mouse_pid))){ 1188 cur_console->mouse_signal = 0; 1189 cur_console->mouse_proc = NULL; 1190 cur_console->mouse_pid = 0; 1191 } 1192 else 1193 psignal(cur_console->mouse_proc, cur_console->mouse_signal); 1194 } 1195 else if (mouse->operation == MOUSE_ACTION) { 1196 /* process button presses */ 1197 if ((cur_console->mouse_buttons ^ mouse->u.data.buttons) && 1198 !(cur_console->status & UNKNOWN_MODE)) { 1199 cur_console->mouse_buttons = mouse->u.data.buttons; 1200 if (cur_console->mouse_buttons & MOUSE_BUTTON1DOWN) 1201 mouse_cut_start(cur_console); 1202 else 1203 mouse_cut_end(cur_console); 1204 if (cur_console->mouse_buttons & MOUSE_BUTTON2DOWN || 1205 cur_console->mouse_buttons & MOUSE_BUTTON3DOWN) 1206 mouse_paste(cur_console); 1207 } 1208 } 1209 1210 if (mouse->u.data.x != 0 || mouse->u.data.y != 0) { 1211 cur_console->mouse_xpos += mouse->u.data.x; 1212 cur_console->mouse_ypos += mouse->u.data.y; 1213 set_mouse_pos(cur_console); 1214 } 1215 1216 break; 1217 1218 case MOUSE_BUTTON_EVENT: 1219 if ((mouse->u.event.id & MOUSE_BUTTONS) == 0) 1220 return EINVAL; 1221 if (mouse->u.event.value < 0) 1222 return EINVAL; 1223 1224 if (mouse->u.event.value > 0) { 1225 cur_console->mouse_buttons |= mouse->u.event.id; 1226 mouse_status.button |= mouse->u.event.id; 1227 } else { 1228 cur_console->mouse_buttons &= ~mouse->u.event.id; 1229 mouse_status.button &= ~mouse->u.event.id; 1230 } 1231 mouse_status.flags |= 1232 ((mouse->u.data.x || mouse->u.data.y || mouse->u.data.z) ? 1233 MOUSE_POSCHANGED : 0) 1234 | (mouse_status.obutton ^ mouse_status.button); 1235 1236 if (cur_console->status & MOUSE_ENABLED) 1237 cur_console->status |= MOUSE_VISIBLE; 1238 1239 if ((MOUSE_TTY)->t_state & TS_ISOPEN) { 1240 u_char buf[8]; 1241 int i; 1242 1243 buf[0] = MOUSE_MSC_SYNC 1244 | butmap[mouse_status.button & MOUSE_STDBUTTONS]; 1245 buf[7] = (~mouse_status.button >> 3) & 0x7f; 1246 buf[1] = buf[2] = buf[3] = buf[4] = buf[5] = buf[6] = 0; 1247 for (i = 0; 1248 i < ((mouse_level >= 1) ? MOUSE_SYS_PACKETSIZE 1249 : MOUSE_MSC_PACKETSIZE); i++) 1250 (*linesw[(MOUSE_TTY)->t_line].l_rint)(buf[i],MOUSE_TTY); 1251 } 1252 1253 if (cur_console->mouse_signal) { 1254 if (cur_console->mouse_proc && 1255 (cur_console->mouse_proc != pfind(cur_console->mouse_pid))){ 1256 cur_console->mouse_signal = 0; 1257 cur_console->mouse_proc = NULL; 1258 cur_console->mouse_pid = 0; 1259 } 1260 else 1261 psignal(cur_console->mouse_proc, cur_console->mouse_signal); 1262 break; 1263 } 1264 1265 if (cur_console->status & UNKNOWN_MODE) 1266 break; 1267 1268 switch (mouse->u.event.id) { 1269 case MOUSE_BUTTON1DOWN: 1270 switch (mouse->u.event.value % 4) { 1271 case 0: /* up */ 1272 mouse_cut_end(cur_console); 1273 break; 1274 case 1: 1275 mouse_cut_start(cur_console); 1276 break; 1277 case 2: 1278 mouse_cut_word(cur_console); 1279 break; 1280 case 3: 1281 mouse_cut_line(cur_console); 1282 break; 1283 } 1284 break; 1285 case MOUSE_BUTTON2DOWN: 1286 switch (mouse->u.event.value) { 1287 case 0: /* up */ 1288 break; 1289 default: 1290 mouse_paste(cur_console); 1291 break; 1292 } 1293 break; 1294 case MOUSE_BUTTON3DOWN: 1295 switch (mouse->u.event.value) { 1296 case 0: /* up */ 1297 if (!(cur_console->mouse_buttons & MOUSE_BUTTON1DOWN)) 1298 mouse_cut_end(cur_console); 1299 break; 1300 default: 1301 mouse_cut_extend(cur_console); 1302 break; 1303 } 1304 break; 1305 } 1306 break; 1307 1308 default: 1309 return EINVAL; 1310 } 1311 /* make screensaver happy */ 1312 scrn_time_stamp = mono_time.tv_sec; 1313 return 0; 1314 } 1315 1316 /* MOUSE_XXX: /dev/sysmouse ioctls */ 1317 case MOUSE_GETHWINFO: /* get device information */ 1318 { 1319 mousehw_t *hw = (mousehw_t *)data; 1320 1321 if (tp != MOUSE_TTY) 1322 return ENOTTY; 1323 hw->buttons = 10; /* XXX unknown */ 1324 hw->iftype = MOUSE_IF_SYSMOUSE; 1325 hw->type = MOUSE_MOUSE; 1326 hw->model = MOUSE_MODEL_GENERIC; 1327 hw->hwid = 0; 1328 return 0; 1329 } 1330 1331 case MOUSE_GETMODE: /* get protocol/mode */ 1332 { 1333 mousemode_t *mode = (mousemode_t *)data; 1334 1335 if (tp != MOUSE_TTY) 1336 return ENOTTY; 1337 mode->level = mouse_level; 1338 switch (mode->level) { 1339 case 0: 1340 /* at this level, sysmouse emulates MouseSystems protocol */ 1341 mode->protocol = MOUSE_PROTO_MSC; 1342 mode->rate = -1; /* unknown */ 1343 mode->resolution = -1; /* unknown */ 1344 mode->accelfactor = 0; /* disabled */ 1345 mode->packetsize = MOUSE_MSC_PACKETSIZE; 1346 mode->syncmask[0] = MOUSE_MSC_SYNCMASK; 1347 mode->syncmask[1] = MOUSE_MSC_SYNC; 1348 break; 1349 1350 case 1: 1351 /* at this level, sysmouse uses its own protocol */ 1352 mode->protocol = MOUSE_PROTO_SYSMOUSE; 1353 mode->rate = -1; 1354 mode->resolution = -1; 1355 mode->accelfactor = 0; 1356 mode->packetsize = MOUSE_SYS_PACKETSIZE; 1357 mode->syncmask[0] = MOUSE_SYS_SYNCMASK; 1358 mode->syncmask[1] = MOUSE_SYS_SYNC; 1359 break; 1360 } 1361 return 0; 1362 } 1363 1364 case MOUSE_SETMODE: /* set protocol/mode */ 1365 { 1366 mousemode_t *mode = (mousemode_t *)data; 1367 1368 if (tp != MOUSE_TTY) 1369 return ENOTTY; 1370 if ((mode->level < 0) || (mode->level > 1)) 1371 return EINVAL; 1372 mouse_level = mode->level; 1373 return 0; 1374 } 1375 1376 case MOUSE_GETLEVEL: /* get operation level */ 1377 if (tp != MOUSE_TTY) 1378 return ENOTTY; 1379 *(int *)data = mouse_level; 1380 return 0; 1381 1382 case MOUSE_SETLEVEL: /* set operation level */ 1383 if (tp != MOUSE_TTY) 1384 return ENOTTY; 1385 if ((*(int *)data < 0) || (*(int *)data > 1)) 1386 return EINVAL; 1387 mouse_level = *(int *)data; 1388 return 0; 1389 1390 case MOUSE_GETSTATUS: /* get accumulated mouse events */ 1391 if (tp != MOUSE_TTY) 1392 return ENOTTY; 1393 s = spltty(); 1394 *(mousestatus_t *)data = mouse_status; 1395 mouse_status.flags = 0; 1396 mouse_status.obutton = mouse_status.button; 1397 mouse_status.dx = 0; 1398 mouse_status.dy = 0; 1399 mouse_status.dz = 0; 1400 splx(s); 1401 return 0; 1402 1403#if notyet 1404 case MOUSE_GETVARS: /* get internal mouse variables */ 1405 case MOUSE_SETVARS: /* set internal mouse variables */ 1406 if (tp != MOUSE_TTY) 1407 return ENOTTY; 1408 return ENODEV; 1409#endif 1410 1411 case MOUSE_READSTATE: /* read status from the device */ 1412 case MOUSE_READDATA: /* read data from the device */ 1413 if (tp != MOUSE_TTY) 1414 return ENOTTY; 1415 return ENODEV; 1416 1417 case CONS_GETINFO: /* get current (virtual) console info */ 1418 { 1419 vid_info_t *ptr = (vid_info_t*)data; 1420 if (ptr->size == sizeof(struct vid_info)) { 1421 ptr->m_num = get_scr_num(); 1422 ptr->mv_col = scp->xpos; 1423 ptr->mv_row = scp->ypos; 1424 ptr->mv_csz = scp->xsize; 1425 ptr->mv_rsz = scp->ysize; 1426 ptr->mv_norm.fore = (scp->term.std_color & 0x0f00)>>8; 1427 ptr->mv_norm.back = (scp->term.std_color & 0xf000)>>12; 1428 ptr->mv_rev.fore = (scp->term.rev_color & 0x0f00)>>8; 1429 ptr->mv_rev.back = (scp->term.rev_color & 0xf000)>>12; 1430 ptr->mv_grfc.fore = 0; /* not supported */ 1431 ptr->mv_grfc.back = 0; /* not supported */ 1432 ptr->mv_ovscan = scp->border; 1433 ptr->mk_keylock = scp->status & LOCK_KEY_MASK; 1434 return 0; 1435 } 1436 return EINVAL; 1437 } 1438 1439 case CONS_GETVERS: /* get version number */ 1440 *(int*)data = 0x200; /* version 2.0 */ 1441 return 0; 1442 1443 /* VGA TEXT MODES */ 1444 case SW_VGA_C40x25: 1445 case SW_VGA_C80x25: case SW_VGA_M80x25: 1446 case SW_VGA_C80x30: case SW_VGA_M80x30: 1447 case SW_VGA_C80x50: case SW_VGA_M80x50: 1448 case SW_VGA_C80x60: case SW_VGA_M80x60: 1449 case SW_B40x25: case SW_C40x25: 1450 case SW_B80x25: case SW_C80x25: 1451 case SW_ENH_B40x25: case SW_ENH_C40x25: 1452 case SW_ENH_B80x25: case SW_ENH_C80x25: 1453 case SW_ENH_B80x43: case SW_ENH_C80x43: 1454 case SW_EGAMONO80x25: 1455 1456 if (!crtc_vga) 1457 return ENODEV; 1458 mp = get_mode_param(scp, cmd & 0xff); 1459 if (mp == NULL) 1460 return ENODEV; 1461 1462 if (scp->history != NULL) 1463 i = imax(scp->history_size / scp->xsize 1464 - imax(SC_HISTORY_SIZE, scp->ysize), 0); 1465 else 1466 i = 0; 1467 switch (cmd & 0xff) { 1468 case M_VGA_C80x60: case M_VGA_M80x60: 1469 if (!(fonts_loaded & FONT_8)) 1470 return EINVAL; 1471 scp->xsize = 80; 1472 scp->ysize = 60; 1473 break; 1474 case M_VGA_C80x50: case M_VGA_M80x50: 1475 if (!(fonts_loaded & FONT_8)) 1476 return EINVAL; 1477 scp->xsize = 80; 1478 scp->ysize = 50; 1479 break; 1480 case M_ENH_B80x43: case M_ENH_C80x43: 1481 if (!(fonts_loaded & FONT_8)) 1482 return EINVAL; 1483 scp->xsize = 80; 1484 scp->ysize = 43; 1485 break; 1486 case M_VGA_C80x30: case M_VGA_M80x30: 1487 scp->xsize = 80; 1488 scp->ysize = 30; 1489 break; 1490 case M_ENH_C40x25: case M_ENH_B40x25: 1491 case M_ENH_C80x25: case M_ENH_B80x25: 1492 case M_EGAMONO80x25: 1493 if (!(fonts_loaded & FONT_14)) 1494 return EINVAL; 1495 /* FALL THROUGH */ 1496 default: 1497 if ((cmd & 0xff) > M_VGA_CG320) 1498 return EINVAL; 1499 scp->xsize = mp[0]; 1500 scp->ysize = mp[1] + rows_offset; 1501 break; 1502 } 1503 scp->mode = cmd & 0xff; 1504 free(scp->scr_buf, M_DEVBUF); 1505 scp->scr_buf = (u_short *) 1506 malloc(scp->xsize*scp->ysize*sizeof(u_short), M_DEVBUF, M_WAITOK); 1507 scp->cursor_pos = scp->cursor_oldpos = 1508 scp->scr_buf + scp->xpos + scp->ypos * scp->xsize; 1509 scp->mouse_pos = scp->mouse_oldpos = 1510 scp->scr_buf + ((scp->mouse_ypos/scp->font_size)*scp->xsize + 1511 scp->mouse_xpos/8); 1512 free(cut_buffer, M_DEVBUF); 1513 cut_buffer = (char *)malloc(scp->xsize*scp->ysize, M_DEVBUF, M_NOWAIT); 1514 cut_buffer[0] = 0x00; 1515 usp = scp->history; 1516 scp->history = NULL; 1517 if (usp != NULL) { 1518 free(usp, M_DEVBUF); 1519 extra_history_size += i; 1520 } 1521 scp->history_size = imax(SC_HISTORY_SIZE, scp->ysize) * scp->xsize; 1522 usp = (u_short *)malloc(scp->history_size * sizeof(u_short), 1523 M_DEVBUF, M_NOWAIT); 1524 if (usp != NULL) 1525 bzero(usp, scp->history_size * sizeof(u_short)); 1526 scp->history_head = scp->history_pos = usp; 1527 scp->history = usp; 1528 if (scp == cur_console) 1529 set_mode(scp); 1530 scp->status &= ~UNKNOWN_MODE; 1531 clear_screen(scp); 1532 1533 if (tp->t_winsize.ws_col != scp->xsize 1534 || tp->t_winsize.ws_row != scp->ysize) { 1535 tp->t_winsize.ws_col = scp->xsize; 1536 tp->t_winsize.ws_row = scp->ysize; 1537 pgsignal(tp->t_pgrp, SIGWINCH, 1); 1538 } 1539 return 0; 1540 1541 /* GRAPHICS MODES */ 1542 case SW_BG320: case SW_BG640: 1543 case SW_CG320: case SW_CG320_D: case SW_CG640_E: 1544 case SW_CG640x350: case SW_ENH_CG640: 1545 case SW_BG640x480: case SW_CG640x480: case SW_VGA_CG320: 1546 1547 if (!crtc_vga) 1548 return ENODEV; 1549 mp = get_mode_param(scp, cmd & 0xff); 1550 if (mp == NULL) 1551 return ENODEV; 1552 1553 scp->mode = cmd & 0xFF; 1554 scp->xpixel = mp[0] * 8; 1555 scp->ypixel = (mp[1] + rows_offset) * mp[2]; 1556 if (scp == cur_console) 1557 set_mode(scp); 1558 scp->status |= UNKNOWN_MODE; /* graphics mode */ 1559 /* clear_graphics();*/ 1560 1561 if (tp->t_winsize.ws_xpixel != scp->xpixel 1562 || tp->t_winsize.ws_ypixel != scp->ypixel) { 1563 tp->t_winsize.ws_xpixel = scp->xpixel; 1564 tp->t_winsize.ws_ypixel = scp->ypixel; 1565 pgsignal(tp->t_pgrp, SIGWINCH, 1); 1566 } 1567 return 0; 1568 1569 case SW_VGA_MODEX: 1570 if (!crtc_vga) 1571 return ENODEV; 1572 mp = get_mode_param(scp, cmd & 0xff); 1573 if (mp == NULL) 1574 return ENODEV; 1575 1576 scp->mode = cmd & 0xFF; 1577 if (scp == cur_console) 1578 set_mode(scp); 1579 scp->status |= UNKNOWN_MODE; /* graphics mode */ 1580 /* clear_graphics();*/ 1581 scp->xpixel = 320; 1582 scp->ypixel = 240; 1583 if (tp->t_winsize.ws_xpixel != scp->xpixel 1584 || tp->t_winsize.ws_ypixel != scp->ypixel) { 1585 tp->t_winsize.ws_xpixel = scp->xpixel; 1586 tp->t_winsize.ws_ypixel = scp->ypixel; 1587 pgsignal(tp->t_pgrp, SIGWINCH, 1); 1588 } 1589 return 0; 1590 1591 case VT_SETMODE: /* set screen switcher mode */ 1592 { 1593 struct vt_mode *mode; 1594 1595 mode = (struct vt_mode *)data; 1596 if (ISSIGVALID(mode->relsig) && ISSIGVALID(mode->acqsig) && 1597 ISSIGVALID(mode->frsig)) { 1598 bcopy(data, &scp->smode, sizeof(struct vt_mode)); 1599 if (scp->smode.mode == VT_PROCESS) { 1600 scp->proc = p; 1601 scp->pid = scp->proc->p_pid; 1602 } 1603 return 0; 1604 } else 1605 return EINVAL; 1606 } 1607 1608 case VT_GETMODE: /* get screen switcher mode */ 1609 bcopy(&scp->smode, data, sizeof(struct vt_mode)); 1610 return 0; 1611 1612 case VT_RELDISP: /* screen switcher ioctl */ 1613 switch(*data) { 1614 case VT_FALSE: /* user refuses to release screen, abort */ 1615 if (scp == old_scp && (scp->status & SWITCH_WAIT_REL)) { 1616 old_scp->status &= ~SWITCH_WAIT_REL; 1617 switch_in_progress = FALSE; 1618 return 0; 1619 } 1620 return EINVAL; 1621 1622 case VT_TRUE: /* user has released screen, go on */ 1623 if (scp == old_scp && (scp->status & SWITCH_WAIT_REL)) { 1624 scp->status &= ~SWITCH_WAIT_REL; 1625 exchange_scr(); 1626 if (new_scp->smode.mode == VT_PROCESS) { 1627 new_scp->status |= SWITCH_WAIT_ACQ; 1628 psignal(new_scp->proc, new_scp->smode.acqsig); 1629 } 1630 else 1631 switch_in_progress = FALSE; 1632 return 0; 1633 } 1634 return EINVAL; 1635 1636 case VT_ACKACQ: /* acquire acknowledged, switch completed */ 1637 if (scp == new_scp && (scp->status & SWITCH_WAIT_ACQ)) { 1638 scp->status &= ~SWITCH_WAIT_ACQ; 1639 switch_in_progress = FALSE; 1640 return 0; 1641 } 1642 return EINVAL; 1643 1644 default: 1645 return EINVAL; 1646 } 1647 /* NOT REACHED */ 1648 1649 case VT_OPENQRY: /* return free virtual console */ 1650 for (i = 0; i < MAXCONS; i++) { 1651 tp = VIRTUAL_TTY(i); 1652 if (!(tp->t_state & TS_ISOPEN)) { 1653 *data = i + 1; 1654 return 0; 1655 } 1656 } 1657 return EINVAL; 1658 1659 case VT_ACTIVATE: /* switch to screen *data */ 1660 return switch_scr(scp, (*data) - 1); 1661 1662 case VT_WAITACTIVE: /* wait for switch to occur */ 1663 if (*data > MAXCONS || *data < 0) 1664 return EINVAL; 1665 if (minor(dev) == (*data) - 1) 1666 return 0; 1667 if (*data == 0) { 1668 if (scp == cur_console) 1669 return 0; 1670 } 1671 else 1672 scp = console[(*data) - 1]; 1673 while ((error=tsleep((caddr_t)&scp->smode, PZERO|PCATCH, 1674 "waitvt", 0)) == ERESTART) ; 1675 return error; 1676 1677 case VT_GETACTIVE: 1678 *data = get_scr_num()+1; 1679 return 0; 1680 1681 case KDENABIO: /* allow io operations */ 1682 error = suser(p->p_ucred, &p->p_acflag); 1683 if (error != 0) 1684 return error; 1685 if (securelevel > 0) 1686 return EPERM; 1687 p->p_md.md_regs->tf_eflags |= PSL_IOPL; 1688 return 0; 1689 1690 case KDDISABIO: /* disallow io operations (default) */ 1691 p->p_md.md_regs->tf_eflags &= ~PSL_IOPL; 1692 return 0; 1693 1694 case KDSETMODE: /* set current mode of this (virtual) console */ 1695 switch (*data) { 1696 case KD_TEXT: /* switch to TEXT (known) mode */ 1697 /* restore fonts & palette ! */ 1698 if (crtc_vga) { 1699 if (fonts_loaded & FONT_8) 1700 copy_font(LOAD, FONT_8, font_8); 1701 if (fonts_loaded & FONT_14) 1702 copy_font(LOAD, FONT_14, font_14); 1703 if (fonts_loaded & FONT_16) 1704 copy_font(LOAD, FONT_16, font_16); 1705 load_palette(palette); 1706 } 1707 1708 /* move hardware cursor out of the way */ 1709 outb(crtc_addr, 14); 1710 outb(crtc_addr + 1, 0xff); 1711 outb(crtc_addr, 15); 1712 outb(crtc_addr + 1, 0xff); 1713 1714 /* FALL THROUGH */ 1715 1716 case KD_TEXT1: /* switch to TEXT (known) mode */ 1717 /* no restore fonts & palette */ 1718 if (crtc_vga) 1719 set_mode(scp); 1720 scp->status &= ~UNKNOWN_MODE; 1721 clear_screen(scp); 1722 return 0; 1723 1724 case KD_GRAPHICS: /* switch to GRAPHICS (unknown) mode */ 1725 scp->status |= UNKNOWN_MODE; 1726 return 0; 1727 default: 1728 return EINVAL; 1729 } 1730 /* NOT REACHED */ 1731 1732 case KDGETMODE: /* get current mode of this (virtual) console */ 1733 *data = (scp->status & UNKNOWN_MODE) ? KD_GRAPHICS : KD_TEXT; 1734 return 0; 1735 1736 case KDSBORDER: /* set border color of this (virtual) console */ 1737 scp->border = *data; 1738 if (scp == cur_console) 1739 set_border(scp->border); 1740 return 0; 1741 1742 case KDSKBSTATE: /* set keyboard state (locks) */ 1743 if (*data >= 0 && *data <= LOCK_KEY_MASK) { 1744 scp->status &= ~LOCK_KEY_MASK; 1745 scp->status |= *data; 1746 if (scp == cur_console) 1747 update_leds(scp->status); 1748 return 0; 1749 } 1750 return EINVAL; 1751 1752 case KDGKBSTATE: /* get keyboard state (locks) */ 1753 *data = scp->status & LOCK_KEY_MASK; 1754 return 0; 1755 1756 case KDSETRAD: /* set keyboard repeat & delay rates */ 1757 if (*data & 0x80) 1758 return EINVAL; 1759 if (sc_kbdc != NULL) 1760 set_keyboard(KBDC_SET_TYPEMATIC, *data); 1761 return 0; 1762 1763 case KDSKBMODE: /* set keyboard mode */ 1764 switch (*data) { 1765 case K_RAW: /* switch to RAW scancode mode */ 1766 scp->status &= ~KBD_CODE_MODE; 1767 scp->status |= KBD_RAW_MODE; 1768 return 0; 1769 1770 case K_CODE: /* switch to CODE mode */ 1771 scp->status &= ~KBD_RAW_MODE; 1772 scp->status |= KBD_CODE_MODE; 1773 return 0; 1774 1775 case K_XLATE: /* switch to XLT ascii mode */ 1776 if (scp == cur_console && scp->status & KBD_RAW_MODE) 1777 shfts = ctls = alts = agrs = metas = accents = 0; 1778 scp->status &= ~(KBD_RAW_MODE | KBD_CODE_MODE); 1779 return 0; 1780 default: 1781 return EINVAL; 1782 } 1783 /* NOT REACHED */ 1784 1785 case KDGKBMODE: /* get keyboard mode */ 1786 *data = (scp->status & KBD_RAW_MODE) ? K_RAW : 1787 ((scp->status & KBD_CODE_MODE) ? K_CODE : K_XLATE); 1788 return 0; 1789 1790 case KDMKTONE: /* sound the bell */ 1791 if (*(int*)data) 1792 do_bell(scp, (*(int*)data)&0xffff, 1793 (((*(int*)data)>>16)&0xffff)*hz/1000); 1794 else 1795 do_bell(scp, scp->bell_pitch, scp->bell_duration); 1796 return 0; 1797 1798 case KIOCSOUND: /* make tone (*data) hz */ 1799 if (scp == cur_console) { 1800 if (*(int*)data) { 1801 int pitch = timer_freq / *(int*)data; 1802 1803 /* set command for counter 2, 2 byte write */ 1804 if (acquire_timer2(TIMER_16BIT|TIMER_SQWAVE)) 1805 return EBUSY; 1806 1807 /* set pitch */ 1808 outb(TIMER_CNTR2, pitch); 1809 outb(TIMER_CNTR2, (pitch>>8)); 1810 1811 /* enable counter 2 output to speaker */ 1812 outb(IO_PPI, inb(IO_PPI) | 3); 1813 } 1814 else { 1815 /* disable counter 2 output to speaker */ 1816 outb(IO_PPI, inb(IO_PPI) & 0xFC); 1817 release_timer2(); 1818 } 1819 } 1820 return 0; 1821 1822 case KDGKBTYPE: /* get keyboard type */ 1823 *data = 0; /* type not known (yet) */ 1824 return 0; 1825 1826 case KDSETLED: /* set keyboard LED status */ 1827 if (*data >= 0 && *data <= LED_MASK) { 1828 scp->status &= ~LED_MASK; 1829 scp->status |= *data; 1830 if (scp == cur_console) 1831 update_leds(scp->status); 1832 return 0; 1833 } 1834 return EINVAL; 1835 1836 case KDGETLED: /* get keyboard LED status */ 1837 *data = scp->status & LED_MASK; 1838 return 0; 1839 1840 case GETFKEY: /* get functionkey string */ 1841 if (*(u_short*)data < n_fkey_tab) { 1842 fkeyarg_t *ptr = (fkeyarg_t*)data; 1843 bcopy(&fkey_tab[ptr->keynum].str, ptr->keydef, 1844 fkey_tab[ptr->keynum].len); 1845 ptr->flen = fkey_tab[ptr->keynum].len; 1846 return 0; 1847 } 1848 else 1849 return EINVAL; 1850 1851 case SETFKEY: /* set functionkey string */ 1852 if (*(u_short*)data < n_fkey_tab) { 1853 fkeyarg_t *ptr = (fkeyarg_t*)data; 1854 bcopy(ptr->keydef, &fkey_tab[ptr->keynum].str, 1855 min(ptr->flen, MAXFK)); 1856 fkey_tab[ptr->keynum].len = min(ptr->flen, MAXFK); 1857 return 0; 1858 } 1859 else 1860 return EINVAL; 1861 1862 case GIO_SCRNMAP: /* get output translation table */ 1863 bcopy(&scr_map, data, sizeof(scr_map)); 1864 return 0; 1865 1866 case PIO_SCRNMAP: /* set output translation table */ 1867 bcopy(data, &scr_map, sizeof(scr_map)); 1868 for (i=0; i<sizeof(scr_map); i++) 1869 scr_rmap[scr_map[i]] = i; 1870 return 0; 1871 1872 case GIO_KEYMAP: /* get keyboard translation table */ 1873 bcopy(&key_map, data, sizeof(key_map)); 1874 return 0; 1875 1876 case PIO_KEYMAP: /* set keyboard translation table */ 1877 accents = 0; 1878 bzero(&accent_map, sizeof(accent_map)); 1879 bcopy(data, &key_map, sizeof(key_map)); 1880 return 0; 1881 1882 case GIO_DEADKEYMAP: /* get accent key translation table */ 1883 bcopy(&accent_map, data, sizeof(accent_map)); 1884 return 0; 1885 1886 case PIO_DEADKEYMAP: /* set accent key translation table */ 1887 accents = 0; 1888 bcopy(data, &accent_map, sizeof(accent_map)); 1889 return 0; 1890 1891 case PIO_FONT8x8: /* set 8x8 dot font */ 1892 if (!crtc_vga) 1893 return ENXIO; 1894 bcopy(data, font_8, 8*256); 1895 fonts_loaded |= FONT_8; 1896 if (!(cur_console->status & UNKNOWN_MODE)) { 1897 copy_font(LOAD, FONT_8, font_8); 1898 if (flags & CHAR_CURSOR) 1899 set_destructive_cursor(cur_console); 1900 } 1901 return 0; 1902 1903 case GIO_FONT8x8: /* get 8x8 dot font */ 1904 if (!crtc_vga) 1905 return ENXIO; 1906 if (fonts_loaded & FONT_8) { 1907 bcopy(font_8, data, 8*256); 1908 return 0; 1909 } 1910 else 1911 return ENXIO; 1912 1913 case PIO_FONT8x14: /* set 8x14 dot font */ 1914 if (!crtc_vga) 1915 return ENXIO; 1916 bcopy(data, font_14, 14*256); 1917 fonts_loaded |= FONT_14; 1918 if (!(cur_console->status & UNKNOWN_MODE)) { 1919 copy_font(LOAD, FONT_14, font_14); 1920 if (flags & CHAR_CURSOR) 1921 set_destructive_cursor(cur_console); 1922 } 1923 return 0; 1924 1925 case GIO_FONT8x14: /* get 8x14 dot font */ 1926 if (!crtc_vga) 1927 return ENXIO; 1928 if (fonts_loaded & FONT_14) { 1929 bcopy(font_14, data, 14*256); 1930 return 0; 1931 } 1932 else 1933 return ENXIO; 1934 1935 case PIO_FONT8x16: /* set 8x16 dot font */ 1936 if (!crtc_vga) 1937 return ENXIO; 1938 bcopy(data, font_16, 16*256); 1939 fonts_loaded |= FONT_16; 1940 if (!(cur_console->status & UNKNOWN_MODE)) { 1941 copy_font(LOAD, FONT_16, font_16); 1942 if (flags & CHAR_CURSOR) 1943 set_destructive_cursor(cur_console); 1944 } 1945 return 0; 1946 1947 case GIO_FONT8x16: /* get 8x16 dot font */ 1948 if (!crtc_vga) 1949 return ENXIO; 1950 if (fonts_loaded & FONT_16) { 1951 bcopy(font_16, data, 16*256); 1952 return 0; 1953 } 1954 else 1955 return ENXIO; 1956 default: 1957 break; 1958 } 1959 1960 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); 1961 if (error != ENOIOCTL) 1962 return(error); 1963 error = ttioctl(tp, cmd, data, flag); 1964 if (error != ENOIOCTL) 1965 return(error); 1966 return(ENOTTY); 1967} 1968 1969static void 1970scstart(struct tty *tp) 1971{ 1972 struct clist *rbp; 1973 int s, len; 1974 u_char buf[PCBURST]; 1975 scr_stat *scp = get_scr_stat(tp->t_dev); 1976 1977 if (scp->status & SLKED || blink_in_progress) 1978 return; /* XXX who repeats the call when the above flags are cleared? */ 1979 s = spltty(); 1980 if (!(tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP))) { 1981 tp->t_state |= TS_BUSY; 1982 rbp = &tp->t_outq; 1983 while (rbp->c_cc) { 1984 len = q_to_b(rbp, buf, PCBURST); 1985 splx(s); 1986 ansi_put(scp, buf, len); 1987 s = spltty(); 1988 } 1989 tp->t_state &= ~TS_BUSY; 1990 ttwwakeup(tp); 1991 } 1992 splx(s); 1993} 1994 1995static void 1996scmousestart(struct tty *tp) 1997{ 1998 struct clist *rbp; 1999 int s; 2000 u_char buf[PCBURST]; 2001 2002 s = spltty(); 2003 if (!(tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP))) { 2004 tp->t_state |= TS_BUSY; 2005 rbp = &tp->t_outq; 2006 while (rbp->c_cc) { 2007 q_to_b(rbp, buf, PCBURST); 2008 } 2009 tp->t_state &= ~TS_BUSY; 2010 ttwwakeup(tp); 2011 } 2012 splx(s); 2013} 2014 2015void 2016sccnprobe(struct consdev *cp) 2017{ 2018 struct isa_device *dvp; 2019 2020 /* 2021 * Take control if we are the highest priority enabled display device. 2022 */ 2023 dvp = find_display(); 2024 if (dvp == NULL || dvp->id_driver != &scdriver) { 2025 cp->cn_pri = CN_DEAD; 2026 return; 2027 } 2028 2029 if (!scvidprobe(dvp->id_unit, dvp->id_flags)) { 2030 cp->cn_pri = CN_DEAD; 2031 return; 2032 } 2033 2034 /* initialize required fields */ 2035 cp->cn_dev = makedev(CDEV_MAJOR, SC_CONSOLE); 2036 cp->cn_pri = CN_INTERNAL; 2037 2038 sc_kbdc = kbdc_open(sc_port); 2039} 2040 2041void 2042sccninit(struct consdev *cp) 2043{ 2044 scinit(); 2045} 2046 2047void 2048sccnputc(dev_t dev, int c) 2049{ 2050 u_char buf[1]; 2051 int s; 2052 scr_stat *scp = console[0]; 2053 term_stat save = scp->term; 2054 2055 scp->term = kernel_console; 2056 current_default = &kernel_default; 2057 if (scp == cur_console && !(scp->status & UNKNOWN_MODE)) 2058 remove_cursor_image(scp); 2059 buf[0] = c; 2060 ansi_put(scp, buf, 1); 2061 kernel_console = scp->term; 2062 current_default = &user_default; 2063 scp->term = save; 2064 s = splclock(); 2065 if (scp == cur_console && !(scp->status & UNKNOWN_MODE)) { 2066 if (/* timer not running && */ (scp->start <= scp->end)) { 2067 sc_bcopy(scp->scr_buf + scp->start, Crtat + scp->start, 2068 (1 + scp->end - scp->start) * sizeof(u_short)); 2069 scp->start = scp->xsize * scp->ysize; 2070 scp->end = 0; 2071 } 2072 scp->cursor_oldpos = scp->cursor_pos; 2073 draw_cursor_image(scp); 2074 } 2075 splx(s); 2076} 2077 2078int 2079sccngetc(dev_t dev) 2080{ 2081 int s = spltty(); /* block scintr and scrn_timer while we poll */ 2082 int c; 2083 2084 /* 2085 * Stop the screen saver if necessary. 2086 * What if we have been running in the screen saver code... XXX 2087 */ 2088 if (scrn_blanked > 0) 2089 stop_scrn_saver(current_saver); 2090 2091 c = scgetc(SCGETC_CN); 2092 2093 /* make sure the screen saver won't be activated soon */ 2094 scrn_time_stamp = mono_time.tv_sec; 2095 splx(s); 2096 return(c); 2097} 2098 2099int 2100sccncheckc(dev_t dev) 2101{ 2102 int c, s; 2103 2104 s = spltty(); 2105 if (scrn_blanked > 0) 2106 stop_scrn_saver(current_saver); 2107 c = scgetc(SCGETC_CN | SCGETC_NONBLOCK); 2108 if (c != NOKEY) 2109 scrn_time_stamp = mono_time.tv_sec; 2110 splx(s); 2111 return(c == NOKEY ? -1 : c); /* c == -1 can't happen */ 2112} 2113 2114static scr_stat 2115*get_scr_stat(dev_t dev) 2116{ 2117 int unit = minor(dev); 2118 2119 if (unit == SC_CONSOLE) 2120 return console[0]; 2121 if (unit >= MAXCONS || unit < 0) 2122 return(NULL); 2123 return console[unit]; 2124} 2125 2126static int 2127get_scr_num() 2128{ 2129 int i = 0; 2130 2131 while ((i < MAXCONS) && (cur_console != console[i])) 2132 i++; 2133 return i < MAXCONS ? i : 0; 2134} 2135 2136static void 2137scrn_timer(void *arg) 2138{ 2139 scr_stat *scp = cur_console; 2140 int s = spltty(); 2141 2142 /* 2143 * With release 2.1 of the Xaccel server, the keyboard is left 2144 * hanging pretty often. Apparently an interrupt from the 2145 * keyboard is lost, and I don't know why (yet). 2146 * This ugly hack calls scintr if input is ready for the keyboard 2147 * and conveniently hides the problem. XXX 2148 */ 2149 /* Try removing anything stuck in the keyboard controller; whether 2150 * it's a keyboard scan code or mouse data. `scintr()' doesn't 2151 * read the mouse data directly, but `kbdio' routines will, as a 2152 * side effect. 2153 */ 2154 if (kbdc_lock(sc_kbdc, TRUE)) { 2155 /* 2156 * We have seen the lock flag is not set. Let's reset the flag early; 2157 * otherwise `update_led()' failes which may want the lock 2158 * during `scintr()'. 2159 */ 2160 kbdc_lock(sc_kbdc, FALSE); 2161 if (kbdc_data_ready(sc_kbdc)) 2162 scintr(0); 2163 } 2164 2165 /* should we just return ? */ 2166 if ((scp->status&UNKNOWN_MODE) || blink_in_progress || switch_in_progress) { 2167 timeout(scrn_timer, NULL, hz / 10); 2168 splx(s); 2169 return; 2170 } 2171 2172 /* should we stop the screen saver? */ 2173 if (mono_time.tv_sec <= scrn_time_stamp + scrn_blank_time) 2174 if (scrn_blanked > 0) 2175 stop_scrn_saver(current_saver); 2176 2177 if (scrn_blanked <= 0) { 2178 /* update screen image */ 2179 if (scp->start <= scp->end) { 2180 sc_bcopy(scp->scr_buf + scp->start, Crtat + scp->start, 2181 (1 + scp->end - scp->start) * sizeof(u_short)); 2182 } 2183 2184 /* update "pseudo" mouse pointer image */ 2185 if ((scp->status & MOUSE_VISIBLE) && crtc_vga) { 2186 /* did mouse move since last time ? */ 2187 if (scp->status & MOUSE_MOVED) { 2188 /* do we need to remove old mouse pointer image ? */ 2189 if (scp->mouse_cut_start != NULL || 2190 (scp->mouse_pos-scp->scr_buf) <= scp->start || 2191 (scp->mouse_pos+scp->xsize+1-scp->scr_buf) >= scp->end) { 2192 remove_mouse_image(scp); 2193 } 2194 scp->status &= ~MOUSE_MOVED; 2195 draw_mouse_image(scp); 2196 } 2197 else { 2198 /* mouse didn't move, has it been overwritten ? */ 2199 if ((scp->mouse_pos+scp->xsize+1-scp->scr_buf) >= scp->start && 2200 (scp->mouse_pos - scp->scr_buf) <= scp->end) { 2201 draw_mouse_image(scp); 2202 } 2203 } 2204 } 2205 2206 /* update cursor image */ 2207 if (scp->status & CURSOR_ENABLED) { 2208 /* did cursor move since last time ? */ 2209 if (scp->cursor_pos != scp->cursor_oldpos) { 2210 /* do we need to remove old cursor image ? */ 2211 if ((scp->cursor_oldpos - scp->scr_buf) < scp->start || 2212 ((scp->cursor_oldpos - scp->scr_buf) > scp->end)) { 2213 remove_cursor_image(scp); 2214 } 2215 scp->cursor_oldpos = scp->cursor_pos; 2216 draw_cursor_image(scp); 2217 } 2218 else { 2219 /* cursor didn't move, has it been overwritten ? */ 2220 if (scp->cursor_pos - scp->scr_buf >= scp->start && 2221 scp->cursor_pos - scp->scr_buf <= scp->end) { 2222 draw_cursor_image(scp); 2223 } else { 2224 /* if its a blinking cursor, we may have to update it */ 2225 if (flags & BLINK_CURSOR) 2226 draw_cursor_image(scp); 2227 } 2228 } 2229 blinkrate++; 2230 } 2231 2232 if (scp->mouse_cut_start != NULL) 2233 draw_cutmarking(scp); 2234 2235 scp->end = 0; 2236 scp->start = scp->xsize*scp->ysize; 2237 } 2238 2239 /* should we activate the screen saver? */ 2240 if ((scrn_blank_time != 0) 2241 && (mono_time.tv_sec > scrn_time_stamp + scrn_blank_time)) 2242 (*current_saver)(TRUE); 2243 2244 timeout(scrn_timer, NULL, hz / 25); 2245 splx(s); 2246} 2247 2248int 2249add_scrn_saver(void (*this_saver)(int)) 2250{ 2251 if (current_saver != none_saver) 2252 return EBUSY; 2253 current_saver = this_saver; 2254 return 0; 2255} 2256 2257int 2258remove_scrn_saver(void (*this_saver)(int)) 2259{ 2260 if (current_saver != this_saver) 2261 return EINVAL; 2262 2263 /* 2264 * In order to prevent `current_saver' from being called by 2265 * the timeout routine `scrn_timer()' while we manipulate 2266 * the saver list, we shall set `current_saver' to `none_saver' 2267 * before stopping the current saver, rather than blocking by `splXX()'. 2268 */ 2269 current_saver = none_saver; 2270 if (scrn_blanked > 0) 2271 stop_scrn_saver(this_saver); 2272 2273 return 0; 2274} 2275 2276static void 2277stop_scrn_saver(void (*saver)(int)) 2278{ 2279 (*saver)(FALSE); 2280 scrn_time_stamp = mono_time.tv_sec; 2281 mark_all(cur_console); 2282} 2283 2284static void 2285clear_screen(scr_stat *scp) 2286{ 2287 move_crsr(scp, 0, 0); 2288 scp->cursor_oldpos = scp->cursor_pos; 2289 fillw(scp->term.cur_color | scr_map[0x20], scp->scr_buf, 2290 scp->xsize * scp->ysize); 2291 mark_all(scp); 2292 remove_cutmarking(scp); 2293} 2294 2295static int 2296switch_scr(scr_stat *scp, u_int next_scr) 2297{ 2298 if (switch_in_progress && (cur_console->proc != pfind(cur_console->pid))) 2299 switch_in_progress = FALSE; 2300 2301 if (next_scr >= MAXCONS || switch_in_progress || 2302 (cur_console->smode.mode == VT_AUTO 2303 && cur_console->status & UNKNOWN_MODE)) { 2304 do_bell(scp, BELL_PITCH, BELL_DURATION); 2305 return EINVAL; 2306 } 2307 2308 /* is the wanted virtual console open ? */ 2309 if (next_scr) { 2310 struct tty *tp = VIRTUAL_TTY(next_scr); 2311 if (!(tp->t_state & TS_ISOPEN)) { 2312 do_bell(scp, BELL_PITCH, BELL_DURATION); 2313 return EINVAL; 2314 } 2315 } 2316 /* delay switch if actively updating screen */ 2317 if (write_in_progress || blink_in_progress) { 2318 delayed_next_scr = next_scr+1; 2319 return 0; 2320 } 2321 switch_in_progress = TRUE; 2322 old_scp = cur_console; 2323 new_scp = console[next_scr]; 2324 wakeup((caddr_t)&new_scp->smode); 2325 if (new_scp == old_scp) { 2326 switch_in_progress = FALSE; 2327 delayed_next_scr = FALSE; 2328 return 0; 2329 } 2330 2331 /* has controlling process died? */ 2332 if (old_scp->proc && (old_scp->proc != pfind(old_scp->pid))) 2333 old_scp->smode.mode = VT_AUTO; 2334 if (new_scp->proc && (new_scp->proc != pfind(new_scp->pid))) 2335 new_scp->smode.mode = VT_AUTO; 2336 2337 /* check the modes and switch appropriately */ 2338 if (old_scp->smode.mode == VT_PROCESS) { 2339 old_scp->status |= SWITCH_WAIT_REL; 2340 psignal(old_scp->proc, old_scp->smode.relsig); 2341 } 2342 else { 2343 exchange_scr(); 2344 if (new_scp->smode.mode == VT_PROCESS) { 2345 new_scp->status |= SWITCH_WAIT_ACQ; 2346 psignal(new_scp->proc, new_scp->smode.acqsig); 2347 } 2348 else 2349 switch_in_progress = FALSE; 2350 } 2351 return 0; 2352} 2353 2354static void 2355exchange_scr(void) 2356{ 2357 move_crsr(old_scp, old_scp->xpos, old_scp->ypos); 2358 cur_console = new_scp; 2359 if (old_scp->mode != new_scp->mode || (old_scp->status & UNKNOWN_MODE)){ 2360 if (crtc_vga) 2361 set_mode(new_scp); 2362 } 2363 move_crsr(new_scp, new_scp->xpos, new_scp->ypos); 2364 if (!(new_scp->status & UNKNOWN_MODE) && (flags & CHAR_CURSOR)) 2365 set_destructive_cursor(new_scp); 2366 if ((old_scp->status & UNKNOWN_MODE) && crtc_vga) 2367 load_palette(palette); 2368 if (old_scp->status & KBD_RAW_MODE || new_scp->status & KBD_RAW_MODE || 2369 old_scp->status & KBD_CODE_MODE || new_scp->status & KBD_CODE_MODE) 2370 shfts = ctls = alts = agrs = metas = accents = 0; 2371 set_border(new_scp->border); 2372 update_leds(new_scp->status); 2373 delayed_next_scr = FALSE; 2374 mark_all(new_scp); 2375} 2376 2377static void 2378scan_esc(scr_stat *scp, u_char c) 2379{ 2380 static u_char ansi_col[16] = 2381 {0, 4, 2, 6, 1, 5, 3, 7, 8, 12, 10, 14, 9, 13, 11, 15}; 2382 int i, n; 2383 u_short *src, *dst, count; 2384 2385 if (scp->term.esc == 1) { /* seen ESC */ 2386 switch (c) { 2387 2388 case '7': /* Save cursor position */ 2389 scp->saved_xpos = scp->xpos; 2390 scp->saved_ypos = scp->ypos; 2391 break; 2392 2393 case '8': /* Restore saved cursor position */ 2394 if (scp->saved_xpos >= 0 && scp->saved_ypos >= 0) 2395 move_crsr(scp, scp->saved_xpos, scp->saved_ypos); 2396 break; 2397 2398 case '[': /* Start ESC [ sequence */ 2399 scp->term.esc = 2; 2400 scp->term.last_param = -1; 2401 for (i = scp->term.num_param; i < MAX_ESC_PAR; i++) 2402 scp->term.param[i] = 1; 2403 scp->term.num_param = 0; 2404 return; 2405 2406 case 'M': /* Move cursor up 1 line, scroll if at top */ 2407 if (scp->ypos > 0) 2408 move_crsr(scp, scp->xpos, scp->ypos - 1); 2409 else { 2410 bcopy(scp->scr_buf, scp->scr_buf + scp->xsize, 2411 (scp->ysize - 1) * scp->xsize * sizeof(u_short)); 2412 fillw(scp->term.cur_color | scr_map[0x20], 2413 scp->scr_buf, scp->xsize); 2414 mark_all(scp); 2415 } 2416 break; 2417#if notyet 2418 case 'Q': 2419 scp->term.esc = 4; 2420 return; 2421#endif 2422 case 'c': /* Clear screen & home */ 2423 clear_screen(scp); 2424 break; 2425 2426 case '(': /* iso-2022: designate 94 character set to G0 */ 2427 scp->term.esc = 5; 2428 return; 2429 } 2430 } 2431 else if (scp->term.esc == 2) { /* seen ESC [ */ 2432 if (c >= '0' && c <= '9') { 2433 if (scp->term.num_param < MAX_ESC_PAR) { 2434 if (scp->term.last_param != scp->term.num_param) { 2435 scp->term.last_param = scp->term.num_param; 2436 scp->term.param[scp->term.num_param] = 0; 2437 } 2438 else 2439 scp->term.param[scp->term.num_param] *= 10; 2440 scp->term.param[scp->term.num_param] += c - '0'; 2441 return; 2442 } 2443 } 2444 scp->term.num_param = scp->term.last_param + 1; 2445 switch (c) { 2446 2447 case ';': 2448 if (scp->term.num_param < MAX_ESC_PAR) 2449 return; 2450 break; 2451 2452 case '=': 2453 scp->term.esc = 3; 2454 scp->term.last_param = -1; 2455 for (i = scp->term.num_param; i < MAX_ESC_PAR; i++) 2456 scp->term.param[i] = 1; 2457 scp->term.num_param = 0; 2458 return; 2459 2460 case 'A': /* up n rows */ 2461 n = scp->term.param[0]; if (n < 1) n = 1; 2462 move_crsr(scp, scp->xpos, scp->ypos - n); 2463 break; 2464 2465 case 'B': /* down n rows */ 2466 n = scp->term.param[0]; if (n < 1) n = 1; 2467 move_crsr(scp, scp->xpos, scp->ypos + n); 2468 break; 2469 2470 case 'C': /* right n columns */ 2471 n = scp->term.param[0]; if (n < 1) n = 1; 2472 move_crsr(scp, scp->xpos + n, scp->ypos); 2473 break; 2474 2475 case 'D': /* left n columns */ 2476 n = scp->term.param[0]; if (n < 1) n = 1; 2477 move_crsr(scp, scp->xpos - n, scp->ypos); 2478 break; 2479 2480 case 'E': /* cursor to start of line n lines down */ 2481 n = scp->term.param[0]; if (n < 1) n = 1; 2482 move_crsr(scp, 0, scp->ypos + n); 2483 break; 2484 2485 case 'F': /* cursor to start of line n lines up */ 2486 n = scp->term.param[0]; if (n < 1) n = 1; 2487 move_crsr(scp, 0, scp->ypos - n); 2488 break; 2489 2490 case 'f': /* Cursor move */ 2491 case 'H': 2492 if (scp->term.num_param == 0) 2493 move_crsr(scp, 0, 0); 2494 else if (scp->term.num_param == 2) 2495 move_crsr(scp, scp->term.param[1] - 1, scp->term.param[0] - 1); 2496 break; 2497 2498 case 'J': /* Clear all or part of display */ 2499 if (scp->term.num_param == 0) 2500 n = 0; 2501 else 2502 n = scp->term.param[0]; 2503 switch (n) { 2504 case 0: /* clear form cursor to end of display */ 2505 fillw(scp->term.cur_color | scr_map[0x20], 2506 scp->cursor_pos, 2507 scp->scr_buf + scp->xsize * scp->ysize - scp->cursor_pos); 2508 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2509 mark_for_update(scp, scp->xsize * scp->ysize); 2510 remove_cutmarking(scp); 2511 break; 2512 case 1: /* clear from beginning of display to cursor */ 2513 fillw(scp->term.cur_color | scr_map[0x20], 2514 scp->scr_buf, 2515 scp->cursor_pos - scp->scr_buf); 2516 mark_for_update(scp, 0); 2517 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2518 remove_cutmarking(scp); 2519 break; 2520 case 2: /* clear entire display */ 2521 fillw(scp->term.cur_color | scr_map[0x20], scp->scr_buf, 2522 scp->xsize * scp->ysize); 2523 mark_all(scp); 2524 remove_cutmarking(scp); 2525 break; 2526 } 2527 break; 2528 2529 case 'K': /* Clear all or part of line */ 2530 if (scp->term.num_param == 0) 2531 n = 0; 2532 else 2533 n = scp->term.param[0]; 2534 switch (n) { 2535 case 0: /* clear form cursor to end of line */ 2536 fillw(scp->term.cur_color | scr_map[0x20], 2537 scp->cursor_pos, 2538 scp->xsize - scp->xpos); 2539 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2540 mark_for_update(scp, scp->cursor_pos - scp->scr_buf + 2541 scp->xsize - scp->xpos); 2542 break; 2543 case 1: /* clear from beginning of line to cursor */ 2544 fillw(scp->term.cur_color | scr_map[0x20], 2545 scp->cursor_pos - scp->xpos, 2546 scp->xpos + 1); 2547 mark_for_update(scp, scp->ypos * scp->xsize); 2548 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2549 break; 2550 case 2: /* clear entire line */ 2551 fillw(scp->term.cur_color | scr_map[0x20], 2552 scp->cursor_pos - scp->xpos, 2553 scp->xsize); 2554 mark_for_update(scp, scp->ypos * scp->xsize); 2555 mark_for_update(scp, (scp->ypos + 1) * scp->xsize); 2556 break; 2557 } 2558 break; 2559 2560 case 'L': /* Insert n lines */ 2561 n = scp->term.param[0]; if (n < 1) n = 1; 2562 if (n > scp->ysize - scp->ypos) 2563 n = scp->ysize - scp->ypos; 2564 src = scp->scr_buf + scp->ypos * scp->xsize; 2565 dst = src + n * scp->xsize; 2566 count = scp->ysize - (scp->ypos + n); 2567 bcopy(src, dst, count * scp->xsize * sizeof(u_short)); 2568 fillw(scp->term.cur_color | scr_map[0x20], src, 2569 n * scp->xsize); 2570 mark_for_update(scp, scp->ypos * scp->xsize); 2571 mark_for_update(scp, scp->xsize * scp->ysize); 2572 break; 2573 2574 case 'M': /* Delete n lines */ 2575 n = scp->term.param[0]; if (n < 1) n = 1; 2576 if (n > scp->ysize - scp->ypos) 2577 n = scp->ysize - scp->ypos; 2578 dst = scp->scr_buf + scp->ypos * scp->xsize; 2579 src = dst + n * scp->xsize; 2580 count = scp->ysize - (scp->ypos + n); 2581 bcopy(src, dst, count * scp->xsize * sizeof(u_short)); 2582 src = dst + count * scp->xsize; 2583 fillw(scp->term.cur_color | scr_map[0x20], src, 2584 n * scp->xsize); 2585 mark_for_update(scp, scp->ypos * scp->xsize); 2586 mark_for_update(scp, scp->xsize * scp->ysize); 2587 break; 2588 2589 case 'P': /* Delete n chars */ 2590 n = scp->term.param[0]; if (n < 1) n = 1; 2591 if (n > scp->xsize - scp->xpos) 2592 n = scp->xsize - scp->xpos; 2593 dst = scp->cursor_pos; 2594 src = dst + n; 2595 count = scp->xsize - (scp->xpos + n); 2596 bcopy(src, dst, count * sizeof(u_short)); 2597 src = dst + count; 2598 fillw(scp->term.cur_color | scr_map[0x20], src, n); 2599 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2600 mark_for_update(scp, scp->cursor_pos - scp->scr_buf + n + count); 2601 break; 2602 2603 case '@': /* Insert n chars */ 2604 n = scp->term.param[0]; if (n < 1) n = 1; 2605 if (n > scp->xsize - scp->xpos) 2606 n = scp->xsize - scp->xpos; 2607 src = scp->cursor_pos; 2608 dst = src + n; 2609 count = scp->xsize - (scp->xpos + n); 2610 bcopy(src, dst, count * sizeof(u_short)); 2611 fillw(scp->term.cur_color | scr_map[0x20], src, n); 2612 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2613 mark_for_update(scp, scp->cursor_pos - scp->scr_buf + n + count); 2614 break; 2615 2616 case 'S': /* scroll up n lines */ 2617 n = scp->term.param[0]; if (n < 1) n = 1; 2618 if (n > scp->ysize) 2619 n = scp->ysize; 2620 bcopy(scp->scr_buf + (scp->xsize * n), 2621 scp->scr_buf, 2622 scp->xsize * (scp->ysize - n) * sizeof(u_short)); 2623 fillw(scp->term.cur_color | scr_map[0x20], 2624 scp->scr_buf + scp->xsize * (scp->ysize - n), 2625 scp->xsize * n); 2626 mark_all(scp); 2627 break; 2628 2629 case 'T': /* scroll down n lines */ 2630 n = scp->term.param[0]; if (n < 1) n = 1; 2631 if (n > scp->ysize) 2632 n = scp->ysize; 2633 bcopy(scp->scr_buf, 2634 scp->scr_buf + (scp->xsize * n), 2635 scp->xsize * (scp->ysize - n) * 2636 sizeof(u_short)); 2637 fillw(scp->term.cur_color | scr_map[0x20], 2638 scp->scr_buf, scp->xsize * n); 2639 mark_all(scp); 2640 break; 2641 2642 case 'X': /* erase n characters in line */ 2643 n = scp->term.param[0]; if (n < 1) n = 1; 2644 if (n > scp->xsize - scp->xpos) 2645 n = scp->xsize - scp->xpos; 2646 fillw(scp->term.cur_color | scr_map[0x20], 2647 scp->cursor_pos, n); 2648 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2649 mark_for_update(scp, scp->cursor_pos - scp->scr_buf + n); 2650 break; 2651 2652 case 'Z': /* move n tabs backwards */ 2653 n = scp->term.param[0]; if (n < 1) n = 1; 2654 if ((i = scp->xpos & 0xf8) == scp->xpos) 2655 i -= 8*n; 2656 else 2657 i -= 8*(n-1); 2658 if (i < 0) 2659 i = 0; 2660 move_crsr(scp, i, scp->ypos); 2661 break; 2662 2663 case '`': /* move cursor to column n */ 2664 n = scp->term.param[0]; if (n < 1) n = 1; 2665 move_crsr(scp, n - 1, scp->ypos); 2666 break; 2667 2668 case 'a': /* move cursor n columns to the right */ 2669 n = scp->term.param[0]; if (n < 1) n = 1; 2670 move_crsr(scp, scp->xpos + n, scp->ypos); 2671 break; 2672 2673 case 'd': /* move cursor to row n */ 2674 n = scp->term.param[0]; if (n < 1) n = 1; 2675 move_crsr(scp, scp->xpos, n - 1); 2676 break; 2677 2678 case 'e': /* move cursor n rows down */ 2679 n = scp->term.param[0]; if (n < 1) n = 1; 2680 move_crsr(scp, scp->xpos, scp->ypos + n); 2681 break; 2682 2683 case 'm': /* change attribute */ 2684 if (scp->term.num_param == 0) { 2685 scp->term.attr_mask = NORMAL_ATTR; 2686 scp->term.cur_attr = 2687 scp->term.cur_color = scp->term.std_color; 2688 break; 2689 } 2690 for (i = 0; i < scp->term.num_param; i++) { 2691 switch (n = scp->term.param[i]) { 2692 case 0: /* back to normal */ 2693 scp->term.attr_mask = NORMAL_ATTR; 2694 scp->term.cur_attr = 2695 scp->term.cur_color = scp->term.std_color; 2696 break; 2697 case 1: /* bold */ 2698 scp->term.attr_mask |= BOLD_ATTR; 2699 scp->term.cur_attr = mask2attr(&scp->term); 2700 break; 2701 case 4: /* underline */ 2702 scp->term.attr_mask |= UNDERLINE_ATTR; 2703 scp->term.cur_attr = mask2attr(&scp->term); 2704 break; 2705 case 5: /* blink */ 2706 scp->term.attr_mask |= BLINK_ATTR; 2707 scp->term.cur_attr = mask2attr(&scp->term); 2708 break; 2709 case 7: /* reverse video */ 2710 scp->term.attr_mask |= REVERSE_ATTR; 2711 scp->term.cur_attr = mask2attr(&scp->term); 2712 break; 2713 case 30: case 31: /* set fg color */ 2714 case 32: case 33: case 34: 2715 case 35: case 36: case 37: 2716 scp->term.attr_mask |= FOREGROUND_CHANGED; 2717 scp->term.cur_color = 2718 (scp->term.cur_color&0xF000) | (ansi_col[(n-30)&7]<<8); 2719 scp->term.cur_attr = mask2attr(&scp->term); 2720 break; 2721 case 40: case 41: /* set bg color */ 2722 case 42: case 43: case 44: 2723 case 45: case 46: case 47: 2724 scp->term.attr_mask |= BACKGROUND_CHANGED; 2725 scp->term.cur_color = 2726 (scp->term.cur_color&0x0F00) | (ansi_col[(n-40)&7]<<12); 2727 scp->term.cur_attr = mask2attr(&scp->term); 2728 break; 2729 } 2730 } 2731 break; 2732 2733 case 's': /* Save cursor position */ 2734 scp->saved_xpos = scp->xpos; 2735 scp->saved_ypos = scp->ypos; 2736 break; 2737 2738 case 'u': /* Restore saved cursor position */ 2739 if (scp->saved_xpos >= 0 && scp->saved_ypos >= 0) 2740 move_crsr(scp, scp->saved_xpos, scp->saved_ypos); 2741 break; 2742 2743 case 'x': 2744 if (scp->term.num_param == 0) 2745 n = 0; 2746 else 2747 n = scp->term.param[0]; 2748 switch (n) { 2749 case 0: /* reset attributes */ 2750 scp->term.attr_mask = NORMAL_ATTR; 2751 scp->term.cur_attr = 2752 scp->term.cur_color = scp->term.std_color = 2753 current_default->std_color; 2754 scp->term.rev_color = current_default->rev_color; 2755 break; 2756 case 1: /* set ansi background */ 2757 scp->term.attr_mask &= ~BACKGROUND_CHANGED; 2758 scp->term.cur_color = scp->term.std_color = 2759 (scp->term.std_color & 0x0F00) | 2760 (ansi_col[(scp->term.param[1])&0x0F]<<12); 2761 scp->term.cur_attr = mask2attr(&scp->term); 2762 break; 2763 case 2: /* set ansi foreground */ 2764 scp->term.attr_mask &= ~FOREGROUND_CHANGED; 2765 scp->term.cur_color = scp->term.std_color = 2766 (scp->term.std_color & 0xF000) | 2767 (ansi_col[(scp->term.param[1])&0x0F]<<8); 2768 scp->term.cur_attr = mask2attr(&scp->term); 2769 break; 2770 case 3: /* set ansi attribute directly */ 2771 scp->term.attr_mask &= ~(FOREGROUND_CHANGED|BACKGROUND_CHANGED); 2772 scp->term.cur_color = scp->term.std_color = 2773 (scp->term.param[1]&0xFF)<<8; 2774 scp->term.cur_attr = mask2attr(&scp->term); 2775 break; 2776 case 5: /* set ansi reverse video background */ 2777 scp->term.rev_color = 2778 (scp->term.rev_color & 0x0F00) | 2779 (ansi_col[(scp->term.param[1])&0x0F]<<12); 2780 scp->term.cur_attr = mask2attr(&scp->term); 2781 break; 2782 case 6: /* set ansi reverse video foreground */ 2783 scp->term.rev_color = 2784 (scp->term.rev_color & 0xF000) | 2785 (ansi_col[(scp->term.param[1])&0x0F]<<8); 2786 scp->term.cur_attr = mask2attr(&scp->term); 2787 break; 2788 case 7: /* set ansi reverse video directly */ 2789 scp->term.rev_color = 2790 (scp->term.param[1]&0xFF)<<8; 2791 scp->term.cur_attr = mask2attr(&scp->term); 2792 break; 2793 } 2794 break; 2795 2796 case 'z': /* switch to (virtual) console n */ 2797 if (scp->term.num_param == 1) 2798 switch_scr(scp, scp->term.param[0]); 2799 break; 2800 } 2801 } 2802 else if (scp->term.esc == 3) { /* seen ESC [0-9]+ = */ 2803 if (c >= '0' && c <= '9') { 2804 if (scp->term.num_param < MAX_ESC_PAR) { 2805 if (scp->term.last_param != scp->term.num_param) { 2806 scp->term.last_param = scp->term.num_param; 2807 scp->term.param[scp->term.num_param] = 0; 2808 } 2809 else 2810 scp->term.param[scp->term.num_param] *= 10; 2811 scp->term.param[scp->term.num_param] += c - '0'; 2812 return; 2813 } 2814 } 2815 scp->term.num_param = scp->term.last_param + 1; 2816 switch (c) { 2817 2818 case ';': 2819 if (scp->term.num_param < MAX_ESC_PAR) 2820 return; 2821 break; 2822 2823 case 'A': /* set display border color */ 2824 if (scp->term.num_param == 1) { 2825 scp->border=scp->term.param[0] & 0xff; 2826 if (scp == cur_console) 2827 set_border(scp->border); 2828 } 2829 break; 2830 2831 case 'B': /* set bell pitch and duration */ 2832 if (scp->term.num_param == 2) { 2833 scp->bell_pitch = scp->term.param[0]; 2834 scp->bell_duration = scp->term.param[1]*10; 2835 } 2836 break; 2837 2838 case 'C': /* set cursor type & shape */ 2839 if (scp->term.num_param == 1) { 2840 if (scp->term.param[0] & 0x01) 2841 flags |= BLINK_CURSOR; 2842 else 2843 flags &= ~BLINK_CURSOR; 2844 if ((scp->term.param[0] & 0x02) && crtc_vga) 2845 flags |= CHAR_CURSOR; 2846 else 2847 flags &= ~CHAR_CURSOR; 2848 } 2849 else if (scp->term.num_param == 2) { 2850 scp->cursor_start = scp->term.param[0] & 0x1F; 2851 scp->cursor_end = scp->term.param[1] & 0x1F; 2852 } 2853 /* 2854 * The cursor shape is global property; all virtual consoles 2855 * are affected. Update the cursor in the current console... 2856 */ 2857 if (!(cur_console->status & UNKNOWN_MODE)) { 2858 remove_cursor_image(cur_console); 2859 if (crtc_vga && (flags & CHAR_CURSOR)) 2860 set_destructive_cursor(cur_console); 2861 draw_cursor_image(cur_console); 2862 } 2863 break; 2864 2865 case 'F': /* set ansi foreground */ 2866 if (scp->term.num_param == 1) { 2867 scp->term.attr_mask &= ~FOREGROUND_CHANGED; 2868 scp->term.cur_color = scp->term.std_color = 2869 (scp->term.std_color & 0xF000) 2870 | ((scp->term.param[0] & 0x0F) << 8); 2871 scp->term.cur_attr = mask2attr(&scp->term); 2872 } 2873 break; 2874 2875 case 'G': /* set ansi background */ 2876 if (scp->term.num_param == 1) { 2877 scp->term.attr_mask &= ~BACKGROUND_CHANGED; 2878 scp->term.cur_color = scp->term.std_color = 2879 (scp->term.std_color & 0x0F00) 2880 | ((scp->term.param[0] & 0x0F) << 12); 2881 scp->term.cur_attr = mask2attr(&scp->term); 2882 } 2883 break; 2884 2885 case 'H': /* set ansi reverse video foreground */ 2886 if (scp->term.num_param == 1) { 2887 scp->term.rev_color = 2888 (scp->term.rev_color & 0xF000) 2889 | ((scp->term.param[0] & 0x0F) << 8); 2890 scp->term.cur_attr = mask2attr(&scp->term); 2891 } 2892 break; 2893 2894 case 'I': /* set ansi reverse video background */ 2895 if (scp->term.num_param == 1) { 2896 scp->term.rev_color = 2897 (scp->term.rev_color & 0x0F00) 2898 | ((scp->term.param[0] & 0x0F) << 12); 2899 scp->term.cur_attr = mask2attr(&scp->term); 2900 } 2901 break; 2902 } 2903 } 2904#if notyet 2905 else if (scp->term.esc == 4) { /* seen ESC Q */ 2906 /* to be filled */ 2907 } 2908#endif 2909 else if (scp->term.esc == 5) { /* seen ESC ( */ 2910 switch (c) { 2911 case 'B': /* iso-2022: desginate ASCII into G0 */ 2912 break; 2913 /* other items to be filled */ 2914 default: 2915 break; 2916 } 2917 } 2918 scp->term.esc = 0; 2919} 2920 2921static void 2922ansi_put(scr_stat *scp, u_char *buf, int len) 2923{ 2924 u_char *ptr = buf; 2925 2926 /* make screensaver happy */ 2927 if (scp == cur_console) 2928 scrn_time_stamp = mono_time.tv_sec; 2929 2930 write_in_progress++; 2931outloop: 2932 if (scp->term.esc) { 2933 scan_esc(scp, *ptr++); 2934 len--; 2935 } 2936 else if (PRINTABLE(*ptr)) { /* Print only printables */ 2937 int cnt = len <= (scp->xsize-scp->xpos) ? len : (scp->xsize-scp->xpos); 2938 u_short cur_attr = scp->term.cur_attr; 2939 u_short *cursor_pos = scp->cursor_pos; 2940 do { 2941 /* 2942 * gcc-2.6.3 generates poor (un)sign extension code. Casting the 2943 * pointers in the following to volatile should have no effect, 2944 * but in fact speeds up this inner loop from 26 to 18 cycles 2945 * (+ cache misses) on i486's. 2946 */ 2947#define UCVP(ucp) ((u_char volatile *)(ucp)) 2948 *cursor_pos++ = UCVP(scr_map)[*UCVP(ptr)] | cur_attr; 2949 ptr++; 2950 cnt--; 2951 } while (cnt && PRINTABLE(*ptr)); 2952 len -= (cursor_pos - scp->cursor_pos); 2953 scp->xpos += (cursor_pos - scp->cursor_pos); 2954 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2955 mark_for_update(scp, cursor_pos - scp->scr_buf); 2956 scp->cursor_pos = cursor_pos; 2957 if (scp->xpos >= scp->xsize) { 2958 scp->xpos = 0; 2959 scp->ypos++; 2960 } 2961 } 2962 else { 2963 switch(*ptr) { 2964 case 0x07: 2965 do_bell(scp, scp->bell_pitch, scp->bell_duration); 2966 break; 2967 2968 case 0x08: /* non-destructive backspace */ 2969 if (scp->cursor_pos > scp->scr_buf) { 2970 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2971 scp->cursor_pos--; 2972 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2973 if (scp->xpos > 0) 2974 scp->xpos--; 2975 else { 2976 scp->xpos += scp->xsize - 1; 2977 scp->ypos--; 2978 } 2979 } 2980 break; 2981 2982 case 0x09: /* non-destructive tab */ 2983 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2984 scp->cursor_pos += (8 - scp->xpos % 8u); 2985 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2986 if ((scp->xpos += (8 - scp->xpos % 8u)) >= scp->xsize) { 2987 scp->xpos = 0; 2988 scp->ypos++; 2989 } 2990 break; 2991 2992 case 0x0a: /* newline, same pos */ 2993 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2994 scp->cursor_pos += scp->xsize; 2995 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2996 scp->ypos++; 2997 break; 2998 2999 case 0x0c: /* form feed, clears screen */ 3000 clear_screen(scp); 3001 break; 3002 3003 case 0x0d: /* return, return to pos 0 */ 3004 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 3005 scp->cursor_pos -= scp->xpos; 3006 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 3007 scp->xpos = 0; 3008 break; 3009 3010 case 0x1b: /* start escape sequence */ 3011 scp->term.esc = 1; 3012 scp->term.num_param = 0; 3013 break; 3014 } 3015 ptr++; len--; 3016 } 3017 /* do we have to scroll ?? */ 3018 if (scp->cursor_pos >= scp->scr_buf + scp->ysize * scp->xsize) { 3019 remove_cutmarking(scp); 3020 if (scp->history) { 3021 bcopy(scp->scr_buf, scp->history_head, 3022 scp->xsize * sizeof(u_short)); 3023 scp->history_head += scp->xsize; 3024 if (scp->history_head + scp->xsize > 3025 scp->history + scp->history_size) 3026 scp->history_head = scp->history; 3027 } 3028 bcopy(scp->scr_buf + scp->xsize, scp->scr_buf, 3029 scp->xsize * (scp->ysize - 1) * sizeof(u_short)); 3030 fillw(scp->term.cur_color | scr_map[0x20], 3031 scp->scr_buf + scp->xsize * (scp->ysize - 1), 3032 scp->xsize); 3033 scp->cursor_pos -= scp->xsize; 3034 scp->ypos--; 3035 mark_all(scp); 3036 } 3037 if (len) 3038 goto outloop; 3039 write_in_progress--; 3040 if (delayed_next_scr) 3041 switch_scr(scp, delayed_next_scr - 1); 3042} 3043 3044static void 3045scinit(void) 3046{ 3047 u_int hw_cursor; 3048 u_int i; 3049 3050 if (init_done != COLD) 3051 return; 3052 init_done = WARM; 3053 3054 /* 3055 * Ensure a zero start address. This is mainly to recover after 3056 * switching from pcvt using userconfig(). The registers are w/o 3057 * for old hardware so it's too hard to relocate the active screen 3058 * memory. 3059 */ 3060 outb(crtc_addr, 12); 3061 outb(crtc_addr + 1, 0); 3062 outb(crtc_addr, 13); 3063 outb(crtc_addr + 1, 0); 3064 3065 /* extract cursor location */ 3066 outb(crtc_addr, 14); 3067 hw_cursor = inb(crtc_addr + 1) << 8; 3068 outb(crtc_addr, 15); 3069 hw_cursor |= inb(crtc_addr + 1); 3070 3071 /* 3072 * Validate cursor location. It may be off the screen. Then we must 3073 * not use it for the initial buffer offset. 3074 */ 3075 if (hw_cursor >= ROW * COL) 3076 hw_cursor = (ROW - 1) * COL; 3077 3078 /* move hardware cursor out of the way */ 3079 outb(crtc_addr, 14); 3080 outb(crtc_addr + 1, 0xff); 3081 outb(crtc_addr, 15); 3082 outb(crtc_addr + 1, 0xff); 3083 3084 /* set up the first console */ 3085 current_default = &user_default; 3086 console[0] = &main_console; 3087 init_scp(console[0]); 3088 cur_console = console[0]; 3089 3090 /* discard the video mode table if we are not familiar with it... */ 3091 if (video_mode_ptr) { 3092 bzero(mode_map, sizeof(mode_map)); 3093 bcopy(video_mode_ptr + MODE_PARAM_SIZE*console[0]->mode, 3094 vgaregs2, sizeof(vgaregs2)); 3095 switch (comp_vgaregs(vgaregs, video_mode_ptr 3096 + MODE_PARAM_SIZE*console[0]->mode)) { 3097 case COMP_IDENTICAL: 3098 map_mode_table(mode_map, video_mode_ptr, M_VGA_CG320 + 1); 3099 /* 3100 * This is a kludge for Toshiba DynaBook SS433 whose BIOS video 3101 * mode table entry has the actual # of rows at the offset 1; 3102 * BIOSes from other manufacturers store the # of rows - 1 there. 3103 * XXX 3104 */ 3105 rows_offset = vgaregs[1] + 1 3106 - video_mode_ptr[MODE_PARAM_SIZE*console[0]->mode + 1]; 3107 break; 3108 case COMP_SIMILAR: 3109 map_mode_table(mode_map, video_mode_ptr, M_VGA_CG320 + 1); 3110 mode_map[console[0]->mode] = vgaregs; 3111 rows_offset = vgaregs[1] + 1 3112 - video_mode_ptr[MODE_PARAM_SIZE*console[0]->mode + 1]; 3113 vgaregs[1] -= rows_offset - 1; 3114 break; 3115 case COMP_DIFFERENT: 3116 default: 3117 video_mode_ptr = NULL; 3118 mode_map[console[0]->mode] = vgaregs; 3119 rows_offset = 1; 3120 break; 3121 } 3122 } 3123 3124 /* copy screen to temporary buffer */ 3125 sc_bcopy(Crtat, sc_buffer, 3126 console[0]->xsize * console[0]->ysize * sizeof(u_short)); 3127 3128 console[0]->scr_buf = console[0]->mouse_pos = sc_buffer; 3129 console[0]->cursor_pos = console[0]->cursor_oldpos = sc_buffer + hw_cursor; 3130 console[0]->cursor_saveunder = *console[0]->cursor_pos; 3131 console[0]->xpos = hw_cursor % COL; 3132 console[0]->ypos = hw_cursor / COL; 3133 for (i=1; i<MAXCONS; i++) 3134 console[i] = NULL; 3135 kernel_console.esc = 0; 3136 kernel_console.attr_mask = NORMAL_ATTR; 3137 kernel_console.cur_attr = 3138 kernel_console.cur_color = kernel_console.std_color = 3139 kernel_default.std_color; 3140 kernel_console.rev_color = kernel_default.rev_color; 3141 3142 /* initialize mapscrn arrays to a one to one map */ 3143 for (i=0; i<sizeof(scr_map); i++) { 3144 scr_map[i] = scr_rmap[i] = i; 3145 } 3146 3147 /* Save font and palette if VGA */ 3148 if (crtc_vga) { 3149 if (fonts_loaded & FONT_16) { 3150 copy_font(LOAD, FONT_16, font_16); 3151 } else { 3152 copy_font(SAVE, FONT_16, font_16); 3153 fonts_loaded = FONT_16; 3154 } 3155 save_palette(); 3156 set_destructive_cursor(console[0]); 3157 } 3158 3159#ifdef SC_SPLASH_SCREEN 3160 /* 3161 * Now put up a graphics image, and maybe cycle a 3162 * couble of palette entries for simple animation. 3163 */ 3164 toggle_splash_screen(cur_console); 3165#endif 3166} 3167 3168static void 3169map_mode_table(char *map[], char *table, int max) 3170{ 3171 int i; 3172 3173 for(i = 0; i < max; ++i) 3174 map[i] = table + i*MODE_PARAM_SIZE; 3175 for(; i < MODE_MAP_SIZE; ++i) 3176 map[i] = NULL; 3177} 3178 3179static u_char 3180map_mode_num(u_char mode) 3181{ 3182 static struct { 3183 u_char from; 3184 u_char to; 3185 } mode_map[] = { 3186 { M_ENH_B80x43, M_ENH_B80x25 }, 3187 { M_ENH_C80x43, M_ENH_C80x25 }, 3188 { M_VGA_M80x30, M_VGA_M80x25 }, 3189 { M_VGA_C80x30, M_VGA_C80x25 }, 3190 { M_VGA_M80x50, M_VGA_M80x25 }, 3191 { M_VGA_C80x50, M_VGA_C80x25 }, 3192 { M_VGA_M80x60, M_VGA_M80x25 }, 3193 { M_VGA_C80x60, M_VGA_C80x25 }, 3194 { M_VGA_MODEX, M_VGA_CG320 }, 3195 }; 3196 int i; 3197 3198 for (i = 0; i < sizeof(mode_map)/sizeof(mode_map[0]); ++i) { 3199 if (mode_map[i].from == mode) 3200 return mode_map[i].to; 3201 } 3202 return mode; 3203} 3204 3205static char 3206*get_mode_param(scr_stat *scp, u_char mode) 3207{ 3208 if (mode >= MODE_MAP_SIZE) 3209 mode = map_mode_num(mode); 3210 if (mode < MODE_MAP_SIZE) 3211 return mode_map[mode]; 3212 else 3213 return NULL; 3214} 3215 3216static scr_stat 3217*alloc_scp() 3218{ 3219 scr_stat *scp; 3220 3221 scp = (scr_stat *)malloc(sizeof(scr_stat), M_DEVBUF, M_WAITOK); 3222 init_scp(scp); 3223 scp->scr_buf = scp->cursor_pos = scp->cursor_oldpos = 3224 (u_short *)malloc(scp->xsize*scp->ysize*sizeof(u_short), 3225 M_DEVBUF, M_WAITOK); 3226 scp->mouse_pos = scp->mouse_oldpos = 3227 scp->scr_buf + ((scp->mouse_ypos/scp->font_size)*scp->xsize + 3228 scp->mouse_xpos/8); 3229 scp->history_head = scp->history_pos = 3230 (u_short *)malloc(scp->history_size*sizeof(u_short), 3231 M_DEVBUF, M_WAITOK); 3232 bzero(scp->history_head, scp->history_size*sizeof(u_short)); 3233 scp->history = scp->history_head; 3234/* SOS 3235 if (crtc_vga && video_mode_ptr) 3236 set_mode(scp); 3237*/ 3238 clear_screen(scp); 3239 scp->cursor_saveunder = *scp->cursor_pos; 3240 return scp; 3241} 3242 3243static void 3244init_scp(scr_stat *scp) 3245{ 3246 if (crtc_vga) 3247 if (crtc_addr == MONO_BASE) 3248 scp->mode = M_VGA_M80x25; 3249 else 3250 scp->mode = M_VGA_C80x25; 3251 else 3252 if (crtc_addr == MONO_BASE) 3253 scp->mode = M_B80x25; 3254 else 3255 scp->mode = M_C80x25; 3256 scp->initial_mode = scp->mode; 3257 3258 scp->font_size = 16; 3259 scp->xsize = COL; 3260 scp->ysize = ROW; 3261 scp->xpos = scp->ypos = 0; 3262 scp->saved_xpos = scp->saved_ypos = -1; 3263 scp->start = scp->xsize * scp->ysize; 3264 scp->end = 0; 3265 scp->term.esc = 0; 3266 scp->term.attr_mask = NORMAL_ATTR; 3267 scp->term.cur_attr = 3268 scp->term.cur_color = scp->term.std_color = 3269 current_default->std_color; 3270 scp->term.rev_color = current_default->rev_color; 3271 scp->border = BG_BLACK; 3272 scp->cursor_start = *(char *)pa_to_va(0x461); 3273 scp->cursor_end = *(char *)pa_to_va(0x460); 3274 scp->mouse_xpos = scp->xsize*8/2; 3275 scp->mouse_ypos = scp->ysize*scp->font_size/2; 3276 scp->mouse_cut_start = scp->mouse_cut_end = NULL; 3277 scp->mouse_signal = 0; 3278 scp->mouse_pid = 0; 3279 scp->mouse_proc = NULL; 3280 scp->bell_pitch = BELL_PITCH; 3281 scp->bell_duration = BELL_DURATION; 3282 scp->status = (*(char *)pa_to_va(0x417) & 0x20) ? NLKED : 0; 3283 scp->status |= CURSOR_ENABLED; 3284 scp->pid = 0; 3285 scp->proc = NULL; 3286 scp->smode.mode = VT_AUTO; 3287 scp->history_head = scp->history_pos = scp->history = NULL; 3288 scp->history_size = imax(SC_HISTORY_SIZE, scp->ysize) * scp->xsize; 3289} 3290 3291static u_char 3292*get_fstr(u_int c, u_int *len) 3293{ 3294 u_int i; 3295 3296 if (!(c & FKEY)) 3297 return(NULL); 3298 i = (c & 0xFF) - F_FN; 3299 if (i > n_fkey_tab) 3300 return(NULL); 3301 *len = fkey_tab[i].len; 3302 return(fkey_tab[i].str); 3303} 3304 3305static void 3306history_to_screen(scr_stat *scp) 3307{ 3308 int i; 3309 3310 for (i=0; i<scp->ysize; i++) 3311 bcopy(scp->history + (((scp->history_pos - scp->history) + 3312 scp->history_size-((i+1)*scp->xsize))%scp->history_size), 3313 scp->scr_buf + (scp->xsize * (scp->ysize-1 - i)), 3314 scp->xsize * sizeof(u_short)); 3315 mark_all(scp); 3316} 3317 3318static int 3319history_up_line(scr_stat *scp) 3320{ 3321 if (WRAPHIST(scp, scp->history_pos, -(scp->xsize*scp->ysize)) != 3322 scp->history_head) { 3323 scp->history_pos = WRAPHIST(scp, scp->history_pos, -scp->xsize); 3324 history_to_screen(scp); 3325 return 0; 3326 } 3327 else 3328 return -1; 3329} 3330 3331static int 3332history_down_line(scr_stat *scp) 3333{ 3334 if (scp->history_pos != scp->history_head) { 3335 scp->history_pos = WRAPHIST(scp, scp->history_pos, scp->xsize); 3336 history_to_screen(scp); 3337 return 0; 3338 } 3339 else 3340 return -1; 3341} 3342 3343/* 3344 * scgetc(flags) - get character from keyboard. 3345 * If flags & SCGETC_CN, then avoid harmful side effects. 3346 * If flags & SCGETC_NONBLOCK, then wait until a key is pressed, else 3347 * return NOKEY if there is nothing there. 3348 */ 3349static u_int 3350scgetc(u_int flags) 3351{ 3352 struct key_t *key; 3353 u_char scancode, keycode; 3354 u_int state, action; 3355 int c; 3356 static u_char esc_flag = 0, compose = 0; 3357 static u_int chr = 0; 3358 3359next_code: 3360 /* first see if there is something in the keyboard port */ 3361 if (flags & SCGETC_NONBLOCK) { 3362 c = read_kbd_data_no_wait(sc_kbdc); 3363 if (c == -1) 3364 return(NOKEY); 3365 } else { 3366 do { 3367 c = read_kbd_data(sc_kbdc); 3368 } while(c == -1); 3369 } 3370 scancode = (u_char)c; 3371 3372 /* do the /dev/random device a favour */ 3373 if (!(flags & SCGETC_CN)) 3374 add_keyboard_randomness(scancode); 3375 3376 if (cur_console->status & KBD_RAW_MODE) 3377 return scancode; 3378 3379 keycode = scancode & 0x7F; 3380 switch (esc_flag) { 3381 case 0x00: /* normal scancode */ 3382 switch(scancode) { 3383 case 0xB8: /* left alt (compose key) */ 3384 if (compose) { 3385 compose = 0; 3386 if (chr > 255) { 3387 do_bell(cur_console, 3388 BELL_PITCH, BELL_DURATION); 3389 chr = 0; 3390 } 3391 } 3392 break; 3393 case 0x38: 3394 if (!compose) { 3395 compose = 1; 3396 chr = 0; 3397 } 3398 break; 3399 case 0xE0: 3400 case 0xE1: 3401 esc_flag = scancode; 3402 goto next_code; 3403 } 3404 break; 3405 case 0xE0: /* 0xE0 prefix */ 3406 esc_flag = 0; 3407 switch (keycode) { 3408 case 0x1C: /* right enter key */ 3409 keycode = 0x59; 3410 break; 3411 case 0x1D: /* right ctrl key */ 3412 keycode = 0x5A; 3413 break; 3414 case 0x35: /* keypad divide key */ 3415 keycode = 0x5B; 3416 break; 3417 case 0x37: /* print scrn key */ 3418 keycode = 0x5C; 3419 break; 3420 case 0x38: /* right alt key (alt gr) */ 3421 keycode = 0x5D; 3422 break; 3423 case 0x47: /* grey home key */ 3424 keycode = 0x5E; 3425 break; 3426 case 0x48: /* grey up arrow key */ 3427 keycode = 0x5F; 3428 break; 3429 case 0x49: /* grey page up key */ 3430 keycode = 0x60; 3431 break; 3432 case 0x4B: /* grey left arrow key */ 3433 keycode = 0x61; 3434 break; 3435 case 0x4D: /* grey right arrow key */ 3436 keycode = 0x62; 3437 break; 3438 case 0x4F: /* grey end key */ 3439 keycode = 0x63; 3440 break; 3441 case 0x50: /* grey down arrow key */ 3442 keycode = 0x64; 3443 break; 3444 case 0x51: /* grey page down key */ 3445 keycode = 0x65; 3446 break; 3447 case 0x52: /* grey insert key */ 3448 keycode = 0x66; 3449 break; 3450 case 0x53: /* grey delete key */ 3451 keycode = 0x67; 3452 break; 3453 3454 /* the following 3 are only used on the MS "Natural" keyboard */ 3455 case 0x5b: /* left Window key */ 3456 keycode = 0x69; 3457 break; 3458 case 0x5c: /* right Window key */ 3459 keycode = 0x6a; 3460 break; 3461 case 0x5d: /* menu key */ 3462 keycode = 0x6b; 3463 break; 3464 default: /* ignore everything else */ 3465 goto next_code; 3466 } 3467 break; 3468 case 0xE1: /* 0xE1 prefix */ 3469 esc_flag = 0; 3470 if (keycode == 0x1D) 3471 esc_flag = 0x1D; 3472 goto next_code; 3473 /* NOT REACHED */ 3474 case 0x1D: /* pause / break */ 3475 esc_flag = 0; 3476 if (keycode != 0x45) 3477 goto next_code; 3478 keycode = 0x68; 3479 break; 3480 } 3481 3482 if (cur_console->status & KBD_CODE_MODE) 3483 return (keycode | (scancode & 0x80)); 3484 3485 /* if scroll-lock pressed allow history browsing */ 3486 if (cur_console->history && cur_console->status & SLKED) { 3487 int i; 3488 3489 cur_console->status &= ~CURSOR_ENABLED; 3490 if (!(cur_console->status & BUFFER_SAVED)) { 3491 cur_console->status |= BUFFER_SAVED; 3492 cur_console->history_save = cur_console->history_head; 3493 3494 /* copy screen into top of history buffer */ 3495 for (i=0; i<cur_console->ysize; i++) { 3496 bcopy(cur_console->scr_buf + (cur_console->xsize * i), 3497 cur_console->history_head, 3498 cur_console->xsize * sizeof(u_short)); 3499 cur_console->history_head += cur_console->xsize; 3500 if (cur_console->history_head + cur_console->xsize > 3501 cur_console->history + cur_console->history_size) 3502 cur_console->history_head=cur_console->history; 3503 } 3504 cur_console->history_pos = cur_console->history_head; 3505 history_to_screen(cur_console); 3506 } 3507 switch (scancode) { 3508 case 0x47: /* home key */ 3509 cur_console->history_pos = cur_console->history_head; 3510 history_to_screen(cur_console); 3511 goto next_code; 3512 3513 case 0x4F: /* end key */ 3514 cur_console->history_pos = 3515 WRAPHIST(cur_console, cur_console->history_head, 3516 cur_console->xsize*cur_console->ysize); 3517 history_to_screen(cur_console); 3518 goto next_code; 3519 3520 case 0x48: /* up arrow key */ 3521 if (history_up_line(cur_console)) 3522 do_bell(cur_console, BELL_PITCH, BELL_DURATION); 3523 goto next_code; 3524 3525 case 0x50: /* down arrow key */ 3526 if (history_down_line(cur_console)) 3527 do_bell(cur_console, BELL_PITCH, BELL_DURATION); 3528 goto next_code; 3529 3530 case 0x49: /* page up key */ 3531 for (i=0; i<cur_console->ysize; i++) 3532 if (history_up_line(cur_console)) { 3533 do_bell(cur_console, BELL_PITCH, BELL_DURATION); 3534 break; 3535 } 3536 goto next_code; 3537 3538 case 0x51: /* page down key */ 3539 for (i=0; i<cur_console->ysize; i++) 3540 if (history_down_line(cur_console)) { 3541 do_bell(cur_console, BELL_PITCH, BELL_DURATION); 3542 break; 3543 } 3544 goto next_code; 3545 } 3546 } 3547 3548 if (compose) { 3549 switch (scancode) { 3550 /* key pressed process it */ 3551 case 0x47: case 0x48: case 0x49: /* keypad 7,8,9 */ 3552 chr = (scancode - 0x40) + chr*10; 3553 goto next_code; 3554 case 0x4B: case 0x4C: case 0x4D: /* keypad 4,5,6 */ 3555 chr = (scancode - 0x47) + chr*10; 3556 goto next_code; 3557 case 0x4F: case 0x50: case 0x51: /* keypad 1,2,3 */ 3558 chr = (scancode - 0x4E) + chr*10; 3559 goto next_code; 3560 case 0x52: /* keypad 0 */ 3561 chr *= 10; 3562 goto next_code; 3563 3564 /* key release, no interest here */ 3565 case 0xC7: case 0xC8: case 0xC9: /* keypad 7,8,9 */ 3566 case 0xCB: case 0xCC: case 0xCD: /* keypad 4,5,6 */ 3567 case 0xCF: case 0xD0: case 0xD1: /* keypad 1,2,3 */ 3568 case 0xD2: /* keypad 0 */ 3569 goto next_code; 3570 3571 case 0x38: /* left alt key */ 3572 break; 3573 default: 3574 if (chr) { 3575 compose = chr = 0; 3576 do_bell(cur_console, BELL_PITCH, BELL_DURATION); 3577 goto next_code; 3578 } 3579 break; 3580 } 3581 } 3582 3583 state = (shfts ? 1 : 0 ) | (2 * (ctls ? 1 : 0)) | (4 * (alts ? 1 : 0)); 3584 if ((!agrs && (cur_console->status & ALKED)) 3585 || (agrs && !(cur_console->status & ALKED))) 3586 keycode += ALTGR_OFFSET; 3587 key = &key_map.key[keycode]; 3588 if ( ((key->flgs & FLAG_LOCK_C) && (cur_console->status & CLKED)) 3589 || ((key->flgs & FLAG_LOCK_N) && (cur_console->status & NLKED)) ) 3590 state ^= 1; 3591 3592 /* Check for make/break */ 3593 action = key->map[state]; 3594 if (scancode & 0x80) { /* key released */ 3595 if (key->spcl & (0x80>>state)) { 3596 switch (action) { 3597 case LSH: 3598 shfts &= ~1; 3599 break; 3600 case RSH: 3601 shfts &= ~2; 3602 break; 3603 case LCTR: 3604 ctls &= ~1; 3605 break; 3606 case RCTR: 3607 ctls &= ~2; 3608 break; 3609 case LALT: 3610 alts &= ~1; 3611 break; 3612 case RALT: 3613 alts &= ~2; 3614 break; 3615 case NLK: 3616 nlkcnt = 0; 3617 break; 3618 case CLK: 3619 clkcnt = 0; 3620 break; 3621 case SLK: 3622 slkcnt = 0; 3623 break; 3624 case ASH: 3625 agrs = 0; 3626 break; 3627 case ALK: 3628 alkcnt = 0; 3629 break; 3630 case META: 3631 metas = 0; 3632 break; 3633 } 3634 } 3635 if (chr && !compose) { 3636 action = chr; 3637 chr = 0; 3638 return(action); 3639 } 3640 } else { 3641 /* key pressed */ 3642 if (key->spcl & (0x80>>state)) { 3643 switch (action) { 3644 /* LOCKING KEYS */ 3645 case NLK: 3646#ifdef SC_SPLASH_SCREEN 3647 toggle_splash_screen(cur_console); /* SOS XXX */ 3648#endif 3649 if (!nlkcnt) { 3650 nlkcnt++; 3651 if (cur_console->status & NLKED) 3652 cur_console->status &= ~NLKED; 3653 else 3654 cur_console->status |= NLKED; 3655 update_leds(cur_console->status); 3656 } 3657 break; 3658 case CLK: 3659 if (!clkcnt) { 3660 clkcnt++; 3661 if (cur_console->status & CLKED) 3662 cur_console->status &= ~CLKED; 3663 else 3664 cur_console->status |= CLKED; 3665 update_leds(cur_console->status); 3666 } 3667 break; 3668 case SLK: 3669 if (!slkcnt) { 3670 slkcnt++; 3671 if (cur_console->status & SLKED) { 3672 cur_console->status &= ~SLKED; 3673 if (cur_console->status & BUFFER_SAVED){ 3674 int i; 3675 u_short *ptr = cur_console->history_save; 3676 3677 for (i=0; i<cur_console->ysize; i++) { 3678 bcopy(ptr, 3679 cur_console->scr_buf + 3680 (cur_console->xsize*i), 3681 cur_console->xsize * sizeof(u_short)); 3682 ptr += cur_console->xsize; 3683 if (ptr + cur_console->xsize > 3684 cur_console->history + 3685 cur_console->history_size) 3686 ptr = cur_console->history; 3687 } 3688 cur_console->status &= ~BUFFER_SAVED; 3689 cur_console->history_head=cur_console->history_save; 3690 cur_console->status |= CURSOR_ENABLED; 3691 mark_all(cur_console); 3692 } 3693 scstart(VIRTUAL_TTY(get_scr_num())); 3694 } 3695 else 3696 cur_console->status |= SLKED; 3697 update_leds(cur_console->status); 3698 } 3699 break; 3700 case ALK: 3701 if (!alkcnt) { 3702 alkcnt++; 3703 if (cur_console->status & ALKED) 3704 cur_console->status &= ~ALKED; 3705 else 3706 cur_console->status |= ALKED; 3707 update_leds(cur_console->status); 3708 } 3709 break; 3710 3711 /* NON-LOCKING KEYS */ 3712 case NOP: 3713 break; 3714 case SPSC: 3715#ifdef SC_SPLASH_SCREEN 3716 accents = 0; 3717 toggle_splash_screen(cur_console); 3718#endif 3719 break; 3720 case RBT: 3721 accents = 0; 3722 shutdown_nice(); 3723 break; 3724 case SUSP: 3725#if NAPM > 0 3726 accents = 0; 3727 apm_suspend(); 3728#endif 3729 break; 3730 3731 case DBG: 3732#ifdef DDB /* try to switch to console 0 */ 3733 accents = 0; 3734 if (cur_console->smode.mode == VT_AUTO && 3735 console[0]->smode.mode == VT_AUTO) 3736 switch_scr(cur_console, 0); 3737 Debugger("manual escape to debugger"); 3738#else 3739 printf("No debugger in kernel\n"); 3740#endif 3741 break; 3742 case LSH: 3743 shfts |= 1; 3744 break; 3745 case RSH: 3746 shfts |= 2; 3747 break; 3748 case LCTR: 3749 ctls |= 1; 3750 break; 3751 case RCTR: 3752 ctls |= 2; 3753 break; 3754 case LALT: 3755 alts |= 1; 3756 break; 3757 case RALT: 3758 alts |= 2; 3759 break; 3760 case ASH: 3761 agrs = 1; 3762 break; 3763 case META: 3764 metas = 1; 3765 break; 3766 case NEXT: 3767 { 3768 int next, this = get_scr_num(); 3769 accents = 0; 3770 for (next = this+1; next != this; next = (next+1)%MAXCONS) { 3771 struct tty *tp = VIRTUAL_TTY(next); 3772 if (tp->t_state & TS_ISOPEN) { 3773 switch_scr(cur_console, next); 3774 break; 3775 } 3776 } 3777 } 3778 break; 3779 case BTAB: 3780 accents = 0; 3781 return(BKEY); 3782 default: 3783 if (action >= F_ACC && action <= L_ACC) { 3784 /* turn it into an index */ 3785 action -= F_ACC - 1; 3786 if ((action > accent_map.n_accs) 3787 || (accent_map.acc[action - 1].accchar == 0)) { 3788 /* 3789 * The index is out of range or pointing to an 3790 * empty entry. 3791 */ 3792 accents = 0; 3793 do_bell(cur_console, BELL_PITCH, BELL_DURATION); 3794 } 3795 /* 3796 * If the same accent key has been hit twice, 3797 * produce the accent char itself. 3798 */ 3799 if (action == accents) { 3800 action = accent_map.acc[accents - 1].accchar; 3801 accents = 0; 3802 if (metas) 3803 action |= MKEY; 3804 return (action); 3805 } 3806 /* remember the index and wait for the next key stroke */ 3807 accents = action; 3808 break; 3809 } 3810 if (accents > 0) { 3811 accents = 0; 3812 do_bell(cur_console, BELL_PITCH, BELL_DURATION); 3813 } 3814 if (action >= F_SCR && action <= L_SCR) { 3815 switch_scr(cur_console, action - F_SCR); 3816 break; 3817 } 3818 if (action >= F_FN && action <= L_FN) 3819 action |= FKEY; 3820 return(action); 3821 } 3822 } 3823 else { 3824 if (accents) { 3825 struct acc_t *acc; 3826 int i; 3827 3828 acc = &accent_map.acc[accents - 1]; 3829 accents = 0; 3830 /* 3831 * If the accent key is followed by the space key, 3832 * produce the accent char itself. 3833 */ 3834 if (action == ' ') { 3835 action = acc->accchar; 3836 if (metas) 3837 action |= MKEY; 3838 return (action); 3839 } 3840 for (i = 0; i < NUM_ACCENTCHARS; ++i) { 3841 if (acc->map[i][0] == 0) /* end of the map entry */ 3842 break; 3843 if (acc->map[i][0] == action) { 3844 action = acc->map[i][1]; 3845 if (metas) 3846 action |= MKEY; 3847 return (action); 3848 } 3849 } 3850 do_bell(cur_console, BELL_PITCH, BELL_DURATION); 3851 goto next_code; 3852 } 3853 if (metas) 3854 action |= MKEY; 3855 return(action); 3856 } 3857 } 3858 goto next_code; 3859} 3860 3861int 3862scmmap(dev_t dev, int offset, int nprot) 3863{ 3864 if (offset > 0x20000 - PAGE_SIZE) 3865 return -1; 3866 return i386_btop((VIDEOMEM + offset)); 3867} 3868 3869/* 3870 * Calculate hardware attributes word using logical attributes mask and 3871 * hardware colors 3872 */ 3873 3874static int 3875mask2attr(struct term_stat *term) 3876{ 3877 int attr, mask = term->attr_mask; 3878 3879 if (mask & REVERSE_ATTR) { 3880 attr = ((mask & FOREGROUND_CHANGED) ? 3881 ((term->cur_color & 0xF000) >> 4) : 3882 (term->rev_color & 0x0F00)) | 3883 ((mask & BACKGROUND_CHANGED) ? 3884 ((term->cur_color & 0x0F00) << 4) : 3885 (term->rev_color & 0xF000)); 3886 } else 3887 attr = term->cur_color; 3888 3889 /* XXX: underline mapping for Hercules adapter can be better */ 3890 if (mask & (BOLD_ATTR | UNDERLINE_ATTR)) 3891 attr ^= 0x0800; 3892 if (mask & BLINK_ATTR) 3893 attr ^= 0x8000; 3894 3895 return attr; 3896} 3897 3898static void 3899set_keyboard(int command, int data) 3900{ 3901 int s; 3902 3903 if (sc_kbdc == NULL) 3904 return; 3905 3906 /* prevent the timeout routine from polling the keyboard */ 3907 if (!kbdc_lock(sc_kbdc, TRUE)) 3908 return; 3909 3910 /* disable the keyboard and mouse interrupt */ 3911 s = spltty(); 3912#if 0 3913 c = get_controller_command_byte(sc_kbdc); 3914 if ((c == -1) 3915 || !set_controller_command_byte(sc_kbdc, 3916 kbdc_get_device_mask(sc_kbdc), 3917 KBD_DISABLE_KBD_PORT | KBD_DISABLE_KBD_INT 3918 | KBD_DISABLE_AUX_PORT | KBD_DISABLE_AUX_INT)) { 3919 /* CONTROLLER ERROR */ 3920 kbdc_lock(sc_kbdc, FALSE); 3921 splx(s); 3922 return; 3923 } 3924 /* 3925 * Now that the keyboard controller is told not to generate 3926 * the keyboard and mouse interrupts, call `splx()' to allow 3927 * the other tty interrupts. The clock interrupt may also occur, 3928 * but the timeout routine (`scrn_timer()') will be blocked 3929 * by the lock flag set via `kbdc_lock()' 3930 */ 3931 splx(s); 3932#endif 3933 3934 if (send_kbd_command_and_data(sc_kbdc, command, data) != KBD_ACK) 3935 send_kbd_command(sc_kbdc, KBDC_ENABLE_KBD); 3936 3937#if 0 3938 /* restore the interrupts */ 3939 if (!set_controller_command_byte(sc_kbdc, 3940 kbdc_get_device_mask(sc_kbdc), 3941 c & (KBD_KBD_CONTROL_BITS | KBD_AUX_CONTROL_BITS))) { 3942 /* CONTROLLER ERROR */ 3943 } 3944#else 3945 splx(s); 3946#endif 3947 kbdc_lock(sc_kbdc, FALSE); 3948} 3949 3950static void 3951update_leds(int which) 3952{ 3953 static u_char xlate_leds[8] = { 0, 4, 2, 6, 1, 5, 3, 7 }; 3954 3955 /* replace CAPS led with ALTGR led for ALTGR keyboards */ 3956 if (key_map.n_keys > ALTGR_OFFSET) { 3957 if (which & ALKED) 3958 which |= CLKED; 3959 else 3960 which &= ~CLKED; 3961 } 3962 3963 set_keyboard(KBDC_SET_LEDS, xlate_leds[which & LED_MASK]); 3964} 3965 3966void 3967set_mode(scr_stat *scp) 3968{ 3969 char special_modetable[MODE_PARAM_SIZE]; 3970 char *mp; 3971 3972 if (scp != cur_console) 3973 return; 3974 3975 /* 3976 * even if mode switching is disabled, we can change back 3977 * to the initial mode or the custom mode based on the initial 3978 * mode if we have saved register values upon start-up. 3979 */ 3980 mp = get_mode_param(scp, scp->mode); 3981 if (mp == NULL) 3982 return; 3983 bcopy(mp, &special_modetable, sizeof(special_modetable)); 3984 3985 /* setup video hardware for the given mode */ 3986 switch (scp->mode) { 3987 case M_VGA_C80x60: case M_VGA_M80x60: 3988 special_modetable[2] = 0x08; 3989 special_modetable[19] = 0x47; 3990 goto special_480l; 3991 3992 case M_VGA_C80x30: case M_VGA_M80x30: 3993 special_modetable[19] = 0x4f; 3994special_480l: 3995 special_modetable[9] |= 0xc0; 3996 special_modetable[16] = 0x08; 3997 special_modetable[17] = 0x3e; 3998 special_modetable[26] = 0xea; 3999 special_modetable[28] = 0xdf; 4000 special_modetable[31] = 0xe7; 4001 special_modetable[32] = 0x04; 4002 goto setup_mode; 4003 4004 case M_ENH_C80x43: case M_ENH_B80x43: 4005 special_modetable[28] = 87; 4006 goto special_80x50; 4007 4008 case M_VGA_C80x50: case M_VGA_M80x50: 4009special_80x50: 4010 special_modetable[2] = 8; 4011 special_modetable[19] = 7; 4012 goto setup_mode; 4013 4014 case M_VGA_C40x25: case M_VGA_C80x25: 4015 case M_VGA_M80x25: 4016 case M_B40x25: case M_C40x25: 4017 case M_B80x25: case M_C80x25: 4018 case M_ENH_B40x25: case M_ENH_C40x25: 4019 case M_ENH_B80x25: case M_ENH_C80x25: 4020 case M_EGAMONO80x25: 4021 4022setup_mode: 4023 set_vgaregs(special_modetable); 4024 scp->font_size = special_modetable[2]; 4025 4026 /* set font type (size) */ 4027 if (scp->font_size < 14) { 4028 if (fonts_loaded & FONT_8) 4029 copy_font(LOAD, FONT_8, font_8); 4030 outb(TSIDX, 0x03); outb(TSREG, 0x0A); /* font 2 */ 4031 } else if (scp->font_size >= 16) { 4032 if (fonts_loaded & FONT_16) 4033 copy_font(LOAD, FONT_16, font_16); 4034 outb(TSIDX, 0x03); outb(TSREG, 0x00); /* font 0 */ 4035 } else { 4036 if (fonts_loaded & FONT_14) 4037 copy_font(LOAD, FONT_14, font_14); 4038 outb(TSIDX, 0x03); outb(TSREG, 0x05); /* font 1 */ 4039 } 4040 if (flags & CHAR_CURSOR) 4041 set_destructive_cursor(scp); 4042 mark_all(scp); 4043 break; 4044 4045 case M_VGA_MODEX: 4046 /* "unchain" the VGA mode */ 4047 special_modetable[5-1+0x04] &= 0xf7; 4048 special_modetable[5-1+0x04] |= 0x04; 4049 /* turn off doubleword mode */ 4050 special_modetable[10+0x14] &= 0xbf; 4051 /* turn off word adressing */ 4052 special_modetable[10+0x17] |= 0x40; 4053 /* set logical screen width */ 4054 special_modetable[10+0x13] = 80; 4055 /* set 240 lines */ 4056 special_modetable[10+0x11] = 0x2c; 4057 special_modetable[10+0x06] = 0x0d; 4058 special_modetable[10+0x07] = 0x3e; 4059 special_modetable[10+0x10] = 0xea; 4060 special_modetable[10+0x11] = 0xac; 4061 special_modetable[10+0x12] = 0xdf; 4062 special_modetable[10+0x15] = 0xe7; 4063 special_modetable[10+0x16] = 0x06; 4064 /* set vertical sync polarity to reflect aspect ratio */ 4065 special_modetable[9] = 0xe3; 4066 goto setup_grmode; 4067 4068 case M_BG320: case M_CG320: case M_BG640: 4069 case M_CG320_D: case M_CG640_E: 4070 case M_CG640x350: case M_ENH_CG640: 4071 case M_BG640x480: case M_CG640x480: case M_VGA_CG320: 4072 4073setup_grmode: 4074 set_vgaregs(special_modetable); 4075 scp->font_size = FONT_NONE; 4076 break; 4077 4078 default: 4079 /* call user defined function XXX */ 4080 break; 4081 } 4082 4083 /* set border color for this (virtual) console */ 4084 set_border(scp->border); 4085 return; 4086} 4087 4088void 4089set_border(u_char color) 4090{ 4091 switch (crtc_type) { 4092 case KD_EGA: 4093 case KD_VGA: 4094 inb(crtc_addr + 6); /* reset flip-flop */ 4095 outb(ATC, 0x31); outb(ATC, color); 4096 break; 4097 case KD_CGA: 4098 outb(crtc_addr + 5, color & 0x0f); /* color select register */ 4099 break; 4100 case KD_MONO: 4101 case KD_HERCULES: 4102 default: 4103 break; 4104 } 4105} 4106 4107static void 4108set_vgaregs(char *modetable) 4109{ 4110 int i, s = splhigh(); 4111 4112 outb(TSIDX, 0x00); outb(TSREG, 0x01); /* stop sequencer */ 4113 outb(TSIDX, 0x07); outb(TSREG, 0x00); /* unlock registers */ 4114 for (i=0; i<4; i++) { /* program sequencer */ 4115 outb(TSIDX, i+1); 4116 outb(TSREG, modetable[i+5]); 4117 } 4118 outb(MISC, modetable[9]); /* set dot-clock */ 4119 outb(TSIDX, 0x00); outb(TSREG, 0x03); /* start sequencer */ 4120 outb(crtc_addr, 0x11); 4121 outb(crtc_addr+1, inb(crtc_addr+1) & 0x7F); 4122 for (i=0; i<25; i++) { /* program crtc */ 4123 outb(crtc_addr, i); 4124 if (i == 14 || i == 15) /* no hardware cursor */ 4125 outb(crtc_addr+1, 0xff); 4126 else 4127 outb(crtc_addr+1, modetable[i+10]); 4128 } 4129 inb(crtc_addr+6); /* reset flip-flop */ 4130 for (i=0; i<20; i++) { /* program attribute ctrl */ 4131 outb(ATC, i); 4132 outb(ATC, modetable[i+35]); 4133 } 4134 for (i=0; i<9; i++) { /* program graph data ctrl */ 4135 outb(GDCIDX, i); 4136 outb(GDCREG, modetable[i+55]); 4137 } 4138 inb(crtc_addr+6); /* reset flip-flop */ 4139 outb(ATC, 0x20); /* enable palette */ 4140 splx(s); 4141} 4142 4143static void 4144read_vgaregs(char *buf) 4145{ 4146 int i, j; 4147 int s; 4148 4149 bzero(buf, MODE_PARAM_SIZE); 4150 4151 s = splhigh(); 4152 4153 outb(TSIDX, 0x00); outb(TSREG, 0x01); /* stop sequencer */ 4154 outb(TSIDX, 0x07); outb(TSREG, 0x00); /* unlock registers */ 4155 for (i=0, j=5; i<4; i++) { 4156 outb(TSIDX, i+1); 4157 buf[j++] = inb(TSREG); 4158 } 4159 buf[9] = inb(MISC + 10); /* dot-clock */ 4160 outb(TSIDX, 0x00); outb(TSREG, 0x03); /* start sequencer */ 4161 4162 for (i=0, j=10; i<25; i++) { /* crtc */ 4163 outb(crtc_addr, i); 4164 buf[j++] = inb(crtc_addr+1); 4165 } 4166 for (i=0, j=35; i<20; i++) { /* attribute ctrl */ 4167 inb(crtc_addr+6); /* reset flip-flop */ 4168 outb(ATC, i); 4169 buf[j++] = inb(ATC + 1); 4170 } 4171 for (i=0, j=55; i<9; i++) { /* graph data ctrl */ 4172 outb(GDCIDX, i); 4173 buf[j++] = inb(GDCREG); 4174 } 4175 inb(crtc_addr+6); /* reset flip-flop */ 4176 outb(ATC, 0x20); /* enable palette */ 4177 4178 buf[0] = *(char *)pa_to_va(0x44a); /* COLS */ 4179 buf[1] = *(char *)pa_to_va(0x484); /* ROWS */ 4180 buf[2] = *(char *)pa_to_va(0x485); /* POINTS */ 4181 buf[3] = *(char *)pa_to_va(0x44c); 4182 buf[4] = *(char *)pa_to_va(0x44d); 4183 4184 splx(s); 4185} 4186 4187static int 4188comp_vgaregs(u_char *buf1, u_char *buf2) 4189{ 4190 static struct { 4191 u_char mask; 4192 } params[MODE_PARAM_SIZE] = { 4193 0xff, 0x00, 0xff, /* COLS, ROWS, POINTS */ 4194 0xff, 0xff, /* page length */ 4195 0xfe, 0xff, 0xff, 0xff, /* sequencer registers */ 4196 0xf3, /* misc register */ 4197 0xff, 0xff, 0xff, 0x7f, 0xff, /* CRTC */ 4198 0xff, 0xff, 0xff, 0x7f, 0xff, 4199 0x00, 0x00, 0x00, 0x00, 0x00, 4200 0x00, 0xff, 0x7f, 0xff, 0xff, 4201 0x7f, 0xff, 0xff, 0xef, 0xff, 4202 0xff, 0xff, 0xff, 0xff, 0xff, /* attribute controller registers */ 4203 0xff, 0xff, 0xff, 0xff, 0xff, 4204 0xff, 0xff, 0xff, 0xff, 0xff, 4205 0xff, 0xff, 0xff, 0xff, 0xf0, 4206 0xff, 0xff, 0xff, 0xff, 0xff, /* GDC register */ 4207 0xff, 0xff, 0xff, 0xff, 4208 }; 4209 int identical = TRUE; 4210 int i; 4211 4212 for (i = 0; i < sizeof(params)/sizeof(params[0]); ++i) { 4213 if (params[i].mask == 0) /* don't care */ 4214 continue; 4215 if ((buf1[i] & params[i].mask) != (buf2[i] & params[i].mask)) 4216 return COMP_DIFFERENT; 4217 if (buf1[i] != buf2[i]) 4218 identical = FALSE; 4219 } 4220 return (identical) ? COMP_IDENTICAL : COMP_SIMILAR; 4221 4222#if 0 4223 for(i = 0; i < 20; ++i) { 4224 if (*buf1++ != *buf2++) 4225 return COMP_DIFFERENT; 4226 } 4227 buf1 += 2; /* skip the cursor shape */ 4228 buf2 += 2; 4229 for(i = 22; i < 24; ++i) { 4230 if (*buf1++ != *buf2++) 4231 return COMP_DIFFERENT; 4232 } 4233 buf1 += 2; /* skip the cursor position */ 4234 buf2 += 2; 4235 for(i = 26; i < MODE_PARAM_SIZE; ++i) { 4236 if (*buf1++ != *buf2++) 4237 return COMP_DIFFERENT; 4238 } 4239 return COMP_IDENTICAL; 4240#endif 4241} 4242 4243static void 4244dump_vgaregs(u_char *buf) 4245{ 4246 int i; 4247 4248 for(i = 0; i < MODE_PARAM_SIZE;) { 4249 printf("%02x ", buf[i]); 4250 if ((++i % 16) == 0) 4251 printf("\n"); 4252 } 4253} 4254 4255static void 4256set_font_mode(u_char *buf) 4257{ 4258 int s = splhigh(); 4259 4260 /* save register values */ 4261 outb(TSIDX, 0x02); buf[0] = inb(TSREG); 4262 outb(TSIDX, 0x04); buf[1] = inb(TSREG); 4263 outb(GDCIDX, 0x04); buf[2] = inb(GDCREG); 4264 outb(GDCIDX, 0x05); buf[3] = inb(GDCREG); 4265 outb(GDCIDX, 0x06); buf[4] = inb(GDCREG); 4266 inb(crtc_addr + 6); 4267 outb(ATC, 0x10); buf[5] = inb(ATC + 1); 4268 4269 /* setup vga for loading fonts (graphics plane mode) */ 4270 inb(crtc_addr+6); /* reset flip-flop */ 4271 outb(ATC, 0x10); outb(ATC, 0x01); 4272 inb(crtc_addr+6); /* reset flip-flop */ 4273 outb(ATC, 0x20); /* enable palette */ 4274 4275#if SLOW_VGA 4276 outb(TSIDX, 0x02); outb(TSREG, 0x04); 4277 outb(TSIDX, 0x04); outb(TSREG, 0x06); 4278 outb(GDCIDX, 0x04); outb(GDCREG, 0x02); 4279 outb(GDCIDX, 0x05); outb(GDCREG, 0x00); 4280 outb(GDCIDX, 0x06); outb(GDCREG, 0x05); 4281#else 4282 outw(TSIDX, 0x0402); 4283 outw(TSIDX, 0x0604); 4284 outw(GDCIDX, 0x0204); 4285 outw(GDCIDX, 0x0005); 4286 outw(GDCIDX, 0x0506); /* addr = a0000, 64kb */ 4287#endif 4288 splx(s); 4289} 4290 4291static void 4292set_normal_mode(u_char *buf) 4293{ 4294 char *modetable; 4295 int s = splhigh(); 4296 4297 /* setup vga for normal operation mode again */ 4298 inb(crtc_addr+6); /* reset flip-flop */ 4299 outb(ATC, 0x10); outb(ATC, buf[5]); 4300 inb(crtc_addr+6); /* reset flip-flop */ 4301 outb(ATC, 0x20); /* enable palette */ 4302 4303#if SLOW_VGA 4304 outb(TSIDX, 0x02); outb(TSREG, buf[0]); 4305 outb(TSIDX, 0x04); outb(TSREG, buf[1]); 4306 outb(GDCIDX, 0x04); outb(GDCREG, buf[2]); 4307 outb(GDCIDX, 0x05); outb(GDCREG, buf[3]); 4308 if (crtc_addr == MONO_BASE) { 4309 outb(GDCIDX, 0x06); outb(GDCREG,(buf[4] & 0x03) | 0x08); 4310 } else { 4311 outb(GDCIDX, 0x06); outb(GDCREG,(buf[4] & 0x03) | 0x0c); 4312 } 4313#else 4314 outw(TSIDX, 0x0002 | (buf[0] << 8)); 4315 outw(TSIDX, 0x0004 | (buf[1] << 8)); 4316 outw(GDCIDX, 0x0004 | (buf[2] << 8)); 4317 outw(GDCIDX, 0x0005 | (buf[3] << 8)); 4318 if (crtc_addr == MONO_BASE) 4319 outw(GDCIDX, 0x0006 | (((buf[4] & 0x03) | 0x08)<<8)); 4320 else 4321 outw(GDCIDX, 0x0006 | (((buf[4] & 0x03) | 0x0c)<<8)); 4322#endif 4323 splx(s); 4324} 4325 4326void 4327copy_font(int operation, int font_type, char* font_image) 4328{ 4329 int ch, line, segment, fontsize; 4330 u_char buf[PARAM_BUFSIZE]; 4331 u_char val; 4332 4333 switch (font_type) { 4334 default: 4335 case FONT_8: 4336 segment = 0x8000; 4337 fontsize = 8; 4338 break; 4339 case FONT_14: 4340 segment = 0x4000; 4341 fontsize = 14; 4342 break; 4343 case FONT_16: 4344 segment = 0x0000; 4345 fontsize = 16; 4346 break; 4347 } 4348 outb(TSIDX, 0x01); val = inb(TSREG); /* disable screen */ 4349 outb(TSIDX, 0x01); outb(TSREG, val | 0x20); 4350 set_font_mode(buf); 4351 for (ch=0; ch < 256; ch++) 4352 for (line=0; line < fontsize; line++) 4353 if (operation) 4354 *(char *)pa_to_va(VIDEOMEM+(segment)+(ch*32)+line) = 4355 font_image[(ch*fontsize)+line]; 4356 else 4357 font_image[(ch*fontsize)+line] = 4358 *(char *)pa_to_va(VIDEOMEM+(segment)+(ch*32)+line); 4359 set_normal_mode(buf); 4360 outb(TSIDX, 0x01); outb(TSREG, val & 0xDF); /* enable screen */ 4361} 4362 4363static void 4364set_destructive_cursor(scr_stat *scp) 4365{ 4366 u_char buf[PARAM_BUFSIZE]; 4367 u_char cursor[32]; 4368 caddr_t address; 4369 int i; 4370 char *font_buffer; 4371 4372 if (scp->font_size < 14) { 4373 font_buffer = font_8; 4374 address = (caddr_t)VIDEOMEM + 0x8000; 4375 } 4376 else if (scp->font_size >= 16) { 4377 font_buffer = font_16; 4378 address = (caddr_t)VIDEOMEM; 4379 } 4380 else { 4381 font_buffer = font_14; 4382 address = (caddr_t)VIDEOMEM + 0x4000; 4383 } 4384 4385 if (scp->status & MOUSE_VISIBLE) { 4386 if ((scp->cursor_saveunder & 0xff) == 0xd0) 4387 bcopy(&scp->mouse_cursor[0], cursor, scp->font_size); 4388 else if ((scp->cursor_saveunder & 0xff) == 0xd1) 4389 bcopy(&scp->mouse_cursor[32], cursor, scp->font_size); 4390 else if ((scp->cursor_saveunder & 0xff) == 0xd2) 4391 bcopy(&scp->mouse_cursor[64], cursor, scp->font_size); 4392 else if ((scp->cursor_saveunder & 0xff) == 0xd3) 4393 bcopy(&scp->mouse_cursor[96], cursor, scp->font_size); 4394 else 4395 bcopy(font_buffer+((scp->cursor_saveunder & 0xff)*scp->font_size), 4396 cursor, scp->font_size); 4397 } 4398 else 4399 bcopy(font_buffer + ((scp->cursor_saveunder & 0xff) * scp->font_size), 4400 cursor, scp->font_size); 4401 for (i=0; i<32; i++) 4402 if ((i >= scp->cursor_start && i <= scp->cursor_end) || 4403 (scp->cursor_start >= scp->font_size && i == scp->font_size - 1)) 4404 cursor[i] |= 0xff; 4405#if 1 4406 while (!(inb(crtc_addr+6) & 0x08)) /* wait for vertical retrace */ ; 4407#endif 4408 set_font_mode(buf); 4409 sc_bcopy(cursor, (char *)pa_to_va(address) + DEAD_CHAR * 32, 32); 4410 set_normal_mode(buf); 4411} 4412 4413static void 4414set_mouse_pos(scr_stat *scp) 4415{ 4416 static int last_xpos = -1, last_ypos = -1; 4417 4418 if (scp->mouse_xpos < 0) 4419 scp->mouse_xpos = 0; 4420 if (scp->mouse_ypos < 0) 4421 scp->mouse_ypos = 0; 4422 if (scp->status & UNKNOWN_MODE) { 4423 if (scp->mouse_xpos > scp->xpixel-1) 4424 scp->mouse_xpos = scp->xpixel-1; 4425 if (scp->mouse_ypos > scp->ypixel-1) 4426 scp->mouse_ypos = scp->ypixel-1; 4427 return; 4428 } 4429 if (scp->mouse_xpos > (scp->xsize*8)-1) 4430 scp->mouse_xpos = (scp->xsize*8)-1; 4431 if (scp->mouse_ypos > (scp->ysize*scp->font_size)-1) 4432 scp->mouse_ypos = (scp->ysize*scp->font_size)-1; 4433 4434 if (scp->mouse_xpos != last_xpos || scp->mouse_ypos != last_ypos) { 4435 scp->status |= MOUSE_MOVED; 4436 4437 scp->mouse_pos = scp->scr_buf + 4438 ((scp->mouse_ypos/scp->font_size)*scp->xsize + scp->mouse_xpos/8); 4439 4440 if ((scp->status & MOUSE_VISIBLE) && (scp->status & MOUSE_CUTTING)) 4441 mouse_cut(scp); 4442 } 4443} 4444 4445#define isspace(c) (((c) & 0xff) == ' ') 4446 4447static int 4448skip_spc_right(scr_stat *scp, u_short *p) 4449{ 4450 int i; 4451 4452 for (i = (p - scp->scr_buf) % scp->xsize; i < scp->xsize; ++i) { 4453 if (!isspace(*p)) 4454 break; 4455 ++p; 4456 } 4457 return i; 4458} 4459 4460static int 4461skip_spc_left(scr_stat *scp, u_short *p) 4462{ 4463 int i; 4464 4465 for (i = (p-- - scp->scr_buf) % scp->xsize - 1; i >= 0; --i) { 4466 if (!isspace(*p)) 4467 break; 4468 --p; 4469 } 4470 return i; 4471} 4472 4473static void 4474mouse_cut(scr_stat *scp) 4475{ 4476 u_short *end; 4477 u_short *p; 4478 int i = 0; 4479 int j = 0; 4480 4481 scp->mouse_cut_end = (scp->mouse_pos >= scp->mouse_cut_start) ? 4482 scp->mouse_pos + 1 : scp->mouse_pos; 4483 end = (scp->mouse_cut_start > scp->mouse_cut_end) ? 4484 scp->mouse_cut_start : scp->mouse_cut_end; 4485 for (p = (scp->mouse_cut_start > scp->mouse_cut_end) ? 4486 scp->mouse_cut_end : scp->mouse_cut_start; p < end; ++p) { 4487 cut_buffer[i] = *p & 0xff; 4488 /* remember the position of the last non-space char */ 4489 if (!isspace(cut_buffer[i++])) 4490 j = i; 4491 /* trim trailing blank when crossing lines */ 4492 if (((p - scp->scr_buf) % scp->xsize) == (scp->xsize - 1)) { 4493 cut_buffer[j++] = '\n'; 4494 i = j; 4495 } 4496 } 4497 cut_buffer[i] = '\0'; 4498 4499 /* scan towards the end of the last line */ 4500 --p; 4501 for (i = (p - scp->scr_buf) % scp->xsize; i < scp->xsize; ++i) { 4502 if (!isspace(*p)) 4503 break; 4504 ++p; 4505 } 4506 /* if there is nothing but blank chars, trim them, but mark towards eol */ 4507 if (i >= scp->xsize) { 4508 if (scp->mouse_cut_start > scp->mouse_cut_end) 4509 scp->mouse_cut_start = p; 4510 else 4511 scp->mouse_cut_end = p; 4512 cut_buffer[j++] = '\n'; 4513 cut_buffer[j] = '\0'; 4514 } 4515 4516 mark_for_update(scp, scp->mouse_cut_start - scp->scr_buf); 4517 mark_for_update(scp, scp->mouse_cut_end - scp->scr_buf); 4518} 4519 4520static void 4521mouse_cut_start(scr_stat *scp) 4522{ 4523 int i; 4524 4525 if (scp->status & MOUSE_VISIBLE) { 4526 if (scp->mouse_pos == scp->mouse_cut_start && 4527 scp->mouse_cut_start == scp->mouse_cut_end - 1) { 4528 cut_buffer[0] = '\0'; 4529 remove_cutmarking(scp); 4530 } else if (skip_spc_right(scp, scp->mouse_pos) >= scp->xsize) { 4531 /* if the pointer is on trailing blank chars, mark towards eol */ 4532 i = skip_spc_left(scp, scp->mouse_pos) + 1; 4533 scp->mouse_cut_start = scp->scr_buf + 4534 ((scp->mouse_pos - scp->scr_buf) / scp->xsize) * scp->xsize + i; 4535 scp->mouse_cut_end = scp->scr_buf + 4536 ((scp->mouse_pos - scp->scr_buf) / scp->xsize + 1) * scp->xsize; 4537 cut_buffer[0] = '\n'; 4538 cut_buffer[1] = '\0'; 4539 scp->status |= MOUSE_CUTTING; 4540 } else { 4541 scp->mouse_cut_start = scp->mouse_pos; 4542 scp->mouse_cut_end = scp->mouse_cut_start + 1; 4543 cut_buffer[0] = *scp->mouse_cut_start & 0xff; 4544 cut_buffer[1] = '\0'; 4545 scp->status |= MOUSE_CUTTING; 4546 } 4547 mark_all(scp); 4548 /* delete all other screens cut markings */ 4549 for (i=0; i<MAXCONS; i++) { 4550 if (console[i] == NULL || console[i] == scp) 4551 continue; 4552 remove_cutmarking(console[i]); 4553 } 4554 } 4555} 4556 4557static void 4558mouse_cut_end(scr_stat *scp) 4559{ 4560 if (scp->status & MOUSE_VISIBLE) { 4561 scp->status &= ~MOUSE_CUTTING; 4562 } 4563} 4564 4565static void 4566mouse_cut_word(scr_stat *scp) 4567{ 4568 u_short *p; 4569 u_short *sol; 4570 u_short *eol; 4571 int i; 4572 4573 /* 4574 * Because we don't have locale information in the kernel, 4575 * we only distinguish space char and non-space chars. Punctuation 4576 * chars, symbols and other regular chars are all treated alike. 4577 */ 4578 if (scp->status & MOUSE_VISIBLE) { 4579 sol = scp->scr_buf 4580 + ((scp->mouse_pos - scp->scr_buf) / scp->xsize) * scp->xsize; 4581 eol = sol + scp->xsize; 4582 if (isspace(*scp->mouse_pos)) { 4583 for (p = scp->mouse_pos; p >= sol; --p) 4584 if (!isspace(*p)) 4585 break; 4586 scp->mouse_cut_start = ++p; 4587 for (p = scp->mouse_pos; p < eol; ++p) 4588 if (!isspace(*p)) 4589 break; 4590 scp->mouse_cut_end = p; 4591 } else { 4592 for (p = scp->mouse_pos; p >= sol; --p) 4593 if (isspace(*p)) 4594 break; 4595 scp->mouse_cut_start = ++p; 4596 for (p = scp->mouse_pos; p < eol; ++p) 4597 if (isspace(*p)) 4598 break; 4599 scp->mouse_cut_end = p; 4600 } 4601 for (i = 0, p = scp->mouse_cut_start; p < scp->mouse_cut_end; ++p) 4602 cut_buffer[i++] = *p & 0xff; 4603 cut_buffer[i] = '\0'; 4604 scp->status |= MOUSE_CUTTING; 4605 } 4606} 4607 4608static void 4609mouse_cut_line(scr_stat *scp) 4610{ 4611 u_short *p; 4612 int i; 4613 4614 if (scp->status & MOUSE_VISIBLE) { 4615 scp->mouse_cut_start = scp->scr_buf 4616 + ((scp->mouse_pos - scp->scr_buf) / scp->xsize) * scp->xsize; 4617 scp->mouse_cut_end = scp->mouse_cut_start + scp->xsize; 4618 for (i = 0, p = scp->mouse_cut_start; p < scp->mouse_cut_end; ++p) 4619 cut_buffer[i++] = *p & 0xff; 4620 cut_buffer[i++] = '\n'; 4621 cut_buffer[i] = '\0'; 4622 scp->status |= MOUSE_CUTTING; 4623 } 4624} 4625 4626static void 4627mouse_cut_extend(scr_stat *scp) 4628{ 4629 if ((scp->status & MOUSE_VISIBLE) && !(scp->status & MOUSE_CUTTING) 4630 && (scp->mouse_cut_start != NULL)) { 4631 mouse_cut(scp); 4632 scp->status |= MOUSE_CUTTING; 4633 } 4634} 4635 4636static void 4637mouse_paste(scr_stat *scp) 4638{ 4639 if (scp->status & MOUSE_VISIBLE) { 4640 struct tty *tp; 4641 u_char *ptr = cut_buffer; 4642 4643 tp = VIRTUAL_TTY(get_scr_num()); 4644 while (*ptr) 4645 (*linesw[tp->t_line].l_rint)(scr_rmap[*ptr++], tp); 4646 } 4647} 4648 4649static void 4650draw_mouse_image(scr_stat *scp) 4651{ 4652 caddr_t address; 4653 int i; 4654 char *font_buffer; 4655 u_char buf[PARAM_BUFSIZE]; 4656 u_short buffer[32]; 4657 u_short xoffset, yoffset; 4658 u_short *crt_pos = Crtat + (scp->mouse_pos - scp->scr_buf); 4659 int font_size = scp->font_size; 4660 4661 if (font_size < 14) { 4662 font_buffer = font_8; 4663 address = (caddr_t)VIDEOMEM + 0x8000; 4664 } 4665 else if (font_size >= 16) { 4666 font_buffer = font_16; 4667 address = (caddr_t)VIDEOMEM; 4668 } 4669 else { 4670 font_buffer = font_14; 4671 address = (caddr_t)VIDEOMEM + 0x4000; 4672 } 4673 xoffset = scp->mouse_xpos % 8; 4674 yoffset = scp->mouse_ypos % font_size; 4675 4676 /* prepare mousepointer char's bitmaps */ 4677 bcopy(font_buffer + ((*(scp->mouse_pos) & 0xff) * font_size), 4678 &scp->mouse_cursor[0], font_size); 4679 bcopy(font_buffer + ((*(scp->mouse_pos+1) & 0xff) * font_size), 4680 &scp->mouse_cursor[32], font_size); 4681 bcopy(font_buffer + ((*(scp->mouse_pos+scp->xsize) & 0xff) * font_size), 4682 &scp->mouse_cursor[64], font_size); 4683 bcopy(font_buffer + ((*(scp->mouse_pos+scp->xsize+1) & 0xff) * font_size), 4684 &scp->mouse_cursor[96], font_size); 4685 for (i=0; i<font_size; i++) { 4686 buffer[i] = scp->mouse_cursor[i]<<8 | scp->mouse_cursor[i+32]; 4687 buffer[i+font_size]=scp->mouse_cursor[i+64]<<8|scp->mouse_cursor[i+96]; 4688 } 4689 4690 /* now and-or in the mousepointer image */ 4691 for (i=0; i<16; i++) { 4692 buffer[i+yoffset] = 4693 ( buffer[i+yoffset] & ~(mouse_and_mask[i] >> xoffset)) 4694 | (mouse_or_mask[i] >> xoffset); 4695 } 4696 for (i=0; i<font_size; i++) { 4697 scp->mouse_cursor[i] = (buffer[i] & 0xff00) >> 8; 4698 scp->mouse_cursor[i+32] = buffer[i] & 0xff; 4699 scp->mouse_cursor[i+64] = (buffer[i+font_size] & 0xff00) >> 8; 4700 scp->mouse_cursor[i+96] = buffer[i+font_size] & 0xff; 4701 } 4702 4703 scp->mouse_oldpos = scp->mouse_pos; 4704 4705#if 1 4706 /* wait for vertical retrace to avoid jitter on some videocards */ 4707 while (!(inb(crtc_addr+6) & 0x08)) /* idle */ ; 4708#endif 4709 set_font_mode(buf); 4710 sc_bcopy(scp->mouse_cursor, (char *)pa_to_va(address) + 0xd0 * 32, 128); 4711 set_normal_mode(buf); 4712 *(crt_pos) = (*(scp->mouse_pos)&0xff00)|0xd0; 4713 *(crt_pos+scp->xsize) = (*(scp->mouse_pos+scp->xsize)&0xff00)|0xd2; 4714 if (scp->mouse_xpos < (scp->xsize-1)*8) { 4715 *(crt_pos+1) = (*(scp->mouse_pos+1)&0xff00)|0xd1; 4716 *(crt_pos+scp->xsize+1) = (*(scp->mouse_pos+scp->xsize+1)&0xff00)|0xd3; 4717 } 4718 mark_for_update(scp, scp->mouse_pos - scp->scr_buf); 4719 mark_for_update(scp, scp->mouse_pos + scp->xsize + 1 - scp->scr_buf); 4720} 4721 4722static void 4723remove_mouse_image(scr_stat *scp) 4724{ 4725 u_short *crt_pos = Crtat + (scp->mouse_oldpos - scp->scr_buf); 4726 4727 *(crt_pos) = *(scp->mouse_oldpos); 4728 *(crt_pos+1) = *(scp->mouse_oldpos+1); 4729 *(crt_pos+scp->xsize) = *(scp->mouse_oldpos+scp->xsize); 4730 *(crt_pos+scp->xsize+1) = *(scp->mouse_oldpos+scp->xsize+1); 4731 mark_for_update(scp, scp->mouse_oldpos - scp->scr_buf); 4732 mark_for_update(scp, scp->mouse_oldpos + scp->xsize + 1 - scp->scr_buf); 4733} 4734 4735static void 4736draw_cutmarking(scr_stat *scp) 4737{ 4738 u_short *ptr; 4739 u_short och, nch; 4740 4741 for (ptr=scp->scr_buf; ptr<=(scp->scr_buf+(scp->xsize*scp->ysize)); ptr++) { 4742 nch = och = *(Crtat + (ptr - scp->scr_buf)); 4743 /* are we outside the selected area ? */ 4744 if ( ptr < (scp->mouse_cut_start > scp->mouse_cut_end ? 4745 scp->mouse_cut_end : scp->mouse_cut_start) || 4746 ptr >= (scp->mouse_cut_start > scp->mouse_cut_end ? 4747 scp->mouse_cut_start : scp->mouse_cut_end)) { 4748 if (ptr != scp->cursor_pos) 4749 nch = (och & 0xff) | (*ptr & 0xff00); 4750 } 4751 else { 4752 /* are we clear of the cursor image ? */ 4753 if (ptr != scp->cursor_pos) 4754 nch = (och & 0x88ff) | (*ptr & 0x7000)>>4 | (*ptr & 0x0700)<<4; 4755 else { 4756 if (flags & CHAR_CURSOR) 4757 nch = (och & 0x88ff)|(*ptr & 0x7000)>>4|(*ptr & 0x0700)<<4; 4758 else 4759 if (!(flags & BLINK_CURSOR)) 4760 nch = (och & 0xff) | (*ptr & 0xff00); 4761 } 4762 } 4763 if (nch != och) 4764 *(Crtat + (ptr - scp->scr_buf)) = nch; 4765 } 4766} 4767 4768static void 4769remove_cutmarking(scr_stat *scp) 4770{ 4771 scp->mouse_cut_start = scp->mouse_cut_end = NULL; 4772 scp->status &= ~MOUSE_CUTTING; 4773 mark_all(scp); 4774} 4775 4776static void 4777save_palette(void) 4778{ 4779 int i; 4780 4781 outb(PALRADR, 0x00); 4782 for (i=0x00; i<0x300; i++) 4783 palette[i] = inb(PALDATA); 4784 inb(crtc_addr+6); /* reset flip/flop */ 4785} 4786 4787void 4788load_palette(char *palette) 4789{ 4790 int i; 4791 4792 outb(PIXMASK, 0xFF); /* no pixelmask */ 4793 outb(PALWADR, 0x00); 4794 for (i=0x00; i<0x300; i++) 4795 outb(PALDATA, palette[i]); 4796 inb(crtc_addr+6); /* reset flip/flop */ 4797 outb(ATC, 0x20); /* enable palette */ 4798} 4799 4800static void 4801do_bell(scr_stat *scp, int pitch, int duration) 4802{ 4803 if (flags & VISUAL_BELL) { 4804 if (blink_in_progress) 4805 return; 4806 blink_in_progress = 4; 4807 if (scp != cur_console) 4808 blink_in_progress += 2; 4809 blink_screen(cur_console); 4810 } else { 4811 if (scp != cur_console) 4812 pitch *= 2; 4813 sysbeep(pitch, duration); 4814 } 4815} 4816 4817static void 4818blink_screen(void *arg) 4819{ 4820 scr_stat *scp = arg; 4821 4822 if ((scp->status & UNKNOWN_MODE) || (blink_in_progress <= 1)) { 4823 blink_in_progress = FALSE; 4824 mark_all(scp); 4825 if (delayed_next_scr) 4826 switch_scr(scp, delayed_next_scr - 1); 4827 } 4828 else { 4829 if (blink_in_progress & 1) 4830 fillw(kernel_default.std_color | scr_map[0x20], 4831 Crtat, scp->xsize * scp->ysize); 4832 else 4833 fillw(kernel_default.rev_color | scr_map[0x20], 4834 Crtat, scp->xsize * scp->ysize); 4835 blink_in_progress--; 4836 timeout(blink_screen, scp, hz / 10); 4837 } 4838} 4839 4840#ifdef SC_SPLASH_SCREEN 4841static void 4842toggle_splash_screen(scr_stat *scp) 4843{ 4844 static int toggle = 0; 4845 static u_char save_mode; 4846 int s; 4847 4848 if (video_mode_ptr == NULL) 4849 return; 4850 4851 s = splhigh(); 4852 if (toggle) { 4853 scp->mode = save_mode; 4854 scp->status &= ~UNKNOWN_MODE; 4855 set_mode(scp); 4856 load_palette(palette); 4857 toggle = 0; 4858 } 4859 else { 4860 save_mode = scp->mode; 4861 scp->mode = M_VGA_CG320; 4862 scp->status |= UNKNOWN_MODE; 4863 set_mode(scp); 4864 /* load image */ 4865 toggle = 1; 4866 } 4867 splx(s); 4868} 4869#endif 4870#endif /* NSC */ 4871