syscons.c revision 32633
162587Sitojun/*- 267455Sitojun * Copyright (c) 1992-1997 S�ren Schmidt 362587Sitojun * All rights reserved. 456723Sshin * 556723Sshin * Redistribution and use in source and binary forms, with or without 656723Sshin * modification, are permitted provided that the following conditions 756723Sshin * are met: 856723Sshin * 1. Redistributions of source code must retain the above copyright 956723Sshin * notice, this list of conditions and the following disclaimer 1056723Sshin * in this position and unchanged. 1156723Sshin * 2. Redistributions in binary form must reproduce the above copyright 1256723Sshin * notice, this list of conditions and the following disclaimer in the 1356723Sshin * documentation and/or other materials provided with the distribution. 1456723Sshin * 3. The name of the author may not be used to endorse or promote products 1556723Sshin * derived from this software withough specific prior written permission 1656723Sshin * 1756723Sshin * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1856723Sshin * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1956723Sshin * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 2056723Sshin * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 2156723Sshin * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2256723Sshin * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2356723Sshin * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2456723Sshin * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2556723Sshin * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2656723Sshin * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2756723Sshin * 2856723Sshin * $Id: syscons.c,v 1.245 1998/01/12 03:28:36 julian Exp $ 2956723Sshin */ 3056723Sshin 3156723Sshin#include "sc.h" 3256723Sshin#include "apm.h" 3356723Sshin#include "opt_ddb.h" 3456723Sshin#include "opt_syscons.h" 3556723Sshin 3656723Sshin#if NSC > 0 3756723Sshin#include <sys/param.h> 3856723Sshin#include <sys/systm.h> 3956723Sshin#include <sys/conf.h> 4056723Sshin#include <sys/proc.h> 4156723Sshin#include <sys/signalvar.h> 4256723Sshin#include <sys/tty.h> 4356723Sshin#include <sys/kernel.h> 4456723Sshin#include <sys/malloc.h> 4556723Sshin#ifdef DEVFS 4656723Sshin#include <sys/devfsext.h> 4756723Sshin#endif 4856723Sshin 4962587Sitojun#include <machine/clock.h> 5056723Sshin#include <machine/cons.h> 5156723Sshin#include <machine/console.h> 5256723Sshin#include <machine/mouse.h> 5356723Sshin#include <machine/md_var.h> 5456723Sshin#include <machine/psl.h> 5556723Sshin#include <machine/frame.h> 5656723Sshin#include <machine/pc/display.h> 5756723Sshin#include <machine/apm_bios.h> 5856723Sshin#include <machine/random.h> 5956723Sshin 6056723Sshin#include <vm/vm.h> 6156723Sshin#include <vm/vm_param.h> 6256723Sshin#include <vm/pmap.h> 6356723Sshin 6456723Sshin#include <i386/isa/isa.h> 6556723Sshin#include <i386/isa/isa_device.h> 6656723Sshin#include <i386/isa/timerreg.h> 6756723Sshin#include <i386/isa/kbdtables.h> 6856723Sshin#include <i386/isa/kbdio.h> 6956723Sshin#include <i386/isa/syscons.h> 7056723Sshin 7162587Sitojun#if !defined(MAXCONS) 7256723Sshin#define MAXCONS 16 7356723Sshin#endif 7456723Sshin 7556723Sshin#if !defined(SC_MAX_HISTORY_SIZE) 7656723Sshin#define SC_MAX_HISTORY_SIZE (1000 * MAXCONS) 7767455Sitojun#endif 7867455Sitojun 7956723Sshin#if !defined(SC_HISTORY_SIZE) 8056723Sshin#define SC_HISTORY_SIZE (ROW * 4) 8162587Sitojun#endif 8256723Sshin 8362587Sitojun#if (SC_HISTORY_SIZE * MAXCONS) > SC_MAX_HISTORY_SIZE 8462587Sitojun#undef SC_MAX_HISTORY_SIZE 8556723Sshin#define SC_MAX_HISTORY_SIZE (SC_HISTORY_SIZE * MAXCONS) 8662587Sitojun#endif 8762587Sitojun 8862587Sitojun#define COLD 0 8962587Sitojun#define WARM 1 9062587Sitojun 9156723Sshin#define MODE_MAP_SIZE (M_VGA_CG320 + 1) 9256723Sshin#define MODE_PARAM_SIZE 64 9356723Sshin 9456723Sshin/* for backward compatibility */ 9556723Sshin#define OLD_CONS_MOUSECTL _IOWR('c', 10, old_mouse_info_t) 9662587Sitojun 9762587Sitojuntypedef struct old_mouse_data { 9862587Sitojun int x; 9962587Sitojun int y; 10056723Sshin int buttons; 10162587Sitojun} old_mouse_data_t; 10262587Sitojun 10356723Sshintypedef struct old_mouse_info { 10462587Sitojun int operation; 10562587Sitojun union { 10662587Sitojun struct old_mouse_data data; 10756723Sshin struct mouse_mode mode; 10856723Sshin } u; 10962587Sitojun} old_mouse_info_t; 11062587Sitojun 11162587Sitojun/* XXX use sc_bcopy where video memory is concerned */ 11262587Sitojun#define sc_bcopy generic_bcopy 11362587Sitojunextern void generic_bcopy(const void *, void *, size_t); 11462587Sitojun 11556723Sshinstatic default_attr user_default = { 11656723Sshin (FG_LIGHTGREY | BG_BLACK) << 8, 11756723Sshin (FG_BLACK | BG_LIGHTGREY) << 8 11862587Sitojun}; 11962587Sitojun 12056723Sshinstatic default_attr kernel_default = { 12156723Sshin (FG_WHITE | BG_BLACK) << 8, 12256723Sshin (FG_BLACK | BG_LIGHTGREY) << 8 12356723Sshin}; 12456723Sshin 12556723Sshinstatic scr_stat main_console; 12656723Sshinstatic scr_stat *console[MAXCONS]; 12756723Sshin#ifdef DEVFS 12856723Sshinstatic void *sc_devfs_token[MAXCONS]; 12956723Sshinstatic void *sc_mouse_devfs_token; 13056723Sshinstatic void *sc_console_devfs_token; 13156723Sshin#endif 13256723Sshin scr_stat *cur_console; 13356723Sshinstatic scr_stat *new_scp, *old_scp; 13456723Sshinstatic term_stat kernel_console; 13556723Sshinstatic default_attr *current_default; 13656723Sshinstatic int flags = 0; 13762587Sitojunstatic int sc_port = IO_KBD; 13856723Sshinstatic KBDC sc_kbdc = NULL; 13956723Sshinstatic char init_done = COLD; 14056723Sshinstatic u_short sc_buffer[ROW*COL]; 14156723Sshinstatic char switch_in_progress = FALSE; 14256723Sshinstatic char write_in_progress = FALSE; 14356723Sshinstatic char blink_in_progress = FALSE; 14456723Sshinstatic int blinkrate = 0; 14556723Sshin u_int crtc_addr = MONO_BASE; 14656723Sshin char crtc_type = KD_MONO; 14756723Sshin char crtc_vga = FALSE; 14856723Sshinstatic u_char shfts = 0, ctls = 0, alts = 0, agrs = 0, metas = 0; 14956723Sshinstatic u_char accents = 0; 15056723Sshinstatic u_char nlkcnt = 0, clkcnt = 0, slkcnt = 0, alkcnt = 0; 15156723Sshinstatic const u_int n_fkey_tab = sizeof(fkey_tab) / sizeof(*fkey_tab); 15256723Sshinstatic int delayed_next_scr = FALSE; 15356723Sshinstatic long scrn_blank_time = 0; /* screen saver timeout value */ 15456723Sshin int scrn_blanked = 0; /* screen saver active flag */ 15556723Sshinstatic long scrn_time_stamp; 15656723Sshin u_char scr_map[256]; 15762587Sitojun u_char scr_rmap[256]; 15856723Sshin char *video_mode_ptr = NULL; 15956723Sshin int fonts_loaded = 0 16056723Sshin#ifdef STD8X16FONT 16156723Sshin | FONT_16 16256723Sshin#endif 16356723Sshin ; 16456723Sshin 16556723Sshin char font_8[256*8]; 16656723Sshin char font_14[256*14]; 16762587Sitojun#ifdef STD8X16FONT 16856723Sshinextern 16956723Sshin#endif 17056723Sshin unsigned char font_16[256*16]; 17156723Sshin char palette[256*3]; 17256723Sshinstatic char *mode_map[MODE_MAP_SIZE]; 17356723Sshinstatic char vgaregs[MODE_PARAM_SIZE]; 17456723Sshinstatic char vgaregs2[MODE_PARAM_SIZE]; 17556723Sshinstatic int rows_offset = 1; 17656723Sshinstatic char *cut_buffer; 17756723Sshinstatic int mouse_level = 0; /* sysmouse protocol level */ 17856723Sshinstatic mousestatus_t mouse_status = { 0, 0, 0, 0, 0, 0 }; 17956723Sshinstatic u_short mouse_and_mask[16] = { 18056723Sshin 0xc000, 0xe000, 0xf000, 0xf800, 18156723Sshin 0xfc00, 0xfe00, 0xff00, 0xff80, 18256723Sshin 0xfe00, 0x1e00, 0x1f00, 0x0f00, 18362587Sitojun 0x0f00, 0x0000, 0x0000, 0x0000 18456723Sshin }; 18556723Sshinstatic u_short mouse_or_mask[16] = { 18656723Sshin 0x0000, 0x4000, 0x6000, 0x7000, 18756723Sshin 0x7800, 0x7c00, 0x7e00, 0x6800, 18856723Sshin 0x0c00, 0x0c00, 0x0600, 0x0600, 18962587Sitojun 0x0000, 0x0000, 0x0000, 0x0000 19056723Sshin }; 19156723Sshin 19256723Sshinstatic int extra_history_size = 19356723Sshin SC_MAX_HISTORY_SIZE - SC_HISTORY_SIZE * MAXCONS; 19456723Sshin 19556723Sshinstatic void none_saver(int blank) { } 19656723Sshinstatic void (*current_saver)(int blank) = none_saver; 19756723Sshinint (*sc_user_ioctl)(dev_t dev, int cmd, caddr_t data, 19856723Sshin int flag, struct proc *p) = NULL; 19956723Sshin 20056723Sshin/* OS specific stuff */ 20156723Sshin#ifdef not_yet_done 20256723Sshin#define VIRTUAL_TTY(x) (sccons[x] = ttymalloc(sccons[x])) 20356723Sshinstruct CONSOLE_TTY (sccons[MAXCONS] = ttymalloc(sccons[MAXCONS])) 20456723Sshinstruct MOUSE_TTY (sccons[MAXCONS+1] = ttymalloc(sccons[MAXCONS+1])) 20562587Sitojunstruct tty *sccons[MAXCONS+2]; 20656723Sshin#else 20762587Sitojun#define VIRTUAL_TTY(x) &sccons[x] 20856723Sshin#define CONSOLE_TTY &sccons[MAXCONS] 20956723Sshin#define MOUSE_TTY &sccons[MAXCONS+1] 21056723Sshinstatic struct tty sccons[MAXCONS+2]; 21162587Sitojun#endif 21256723Sshin#define SC_MOUSE 128 21356723Sshin#define SC_CONSOLE 255 21456723Sshin#define MONO_BUF pa_to_va(0xB0000) 21556723Sshin#define CGA_BUF pa_to_va(0xB8000) 21656723Sshinu_short *Crtat; 21756723Sshinstatic const int nsccons = MAXCONS+2; 21862587Sitojun 21956723Sshin#define WRAPHIST(scp, pointer, offset)\ 22056723Sshin ((scp->history) + ((((pointer) - (scp->history)) + (scp->history_size)\ 22156723Sshin + (offset)) % (scp->history_size))) 22256723Sshin#define ISSIGVALID(sig) ((sig) > 0 && (sig) < NSIG) 22356723Sshin 22456723Sshin/* this should really be in `rtc.h' */ 22556723Sshin#define RTC_EQUIPMENT 0x14 22656723Sshin 22756723Sshin/* prototypes */ 22856723Sshinstatic int scattach(struct isa_device *dev); 22956723Sshinstatic int scparam(struct tty *tp, struct termios *t); 23056723Sshinstatic int scprobe(struct isa_device *dev); 23156723Sshinstatic int scvidprobe(int unit, int flags); 23256723Sshinstatic int sckbdprobe(int unit, int flags); 23356723Sshinstatic void scstart(struct tty *tp); 23456723Sshinstatic void scmousestart(struct tty *tp); 23556723Sshinstatic void scinit(void); 23656723Sshinstatic void map_mode_table(char *map[], char *table, int max); 23756723Sshinstatic u_char map_mode_num(u_char mode); 23856723Sshinstatic char *get_mode_param(scr_stat *scp, u_char mode); 23956723Sshinstatic u_int scgetc(u_int flags); 24056723Sshin#define SCGETC_CN 1 24156723Sshin#define SCGETC_NONBLOCK 2 24256723Sshinstatic scr_stat *get_scr_stat(dev_t dev); 24356723Sshinstatic scr_stat *alloc_scp(void); 24456723Sshinstatic void init_scp(scr_stat *scp); 24562587Sitojunstatic int get_scr_num(void); 24662587Sitojunstatic timeout_t scrn_timer; 24762587Sitojunstatic void stop_scrn_saver(void (*saver)(int)); 24862587Sitojunstatic void clear_screen(scr_stat *scp); 24956723Sshinstatic int switch_scr(scr_stat *scp, u_int next_scr); 25056723Sshinstatic void exchange_scr(void); 25156723Sshinstatic inline void move_crsr(scr_stat *scp, int x, int y); 25256723Sshinstatic void scan_esc(scr_stat *scp, u_char c); 25356723Sshinstatic void draw_cursor_image(scr_stat *scp); 25456723Sshinstatic void remove_cursor_image(scr_stat *scp); 25556723Sshinstatic void ansi_put(scr_stat *scp, u_char *buf, int len); 25656723Sshinstatic u_char *get_fstr(u_int c, u_int *len); 25756723Sshinstatic void history_to_screen(scr_stat *scp); 25856723Sshinstatic int history_up_line(scr_stat *scp); 25956723Sshinstatic int history_down_line(scr_stat *scp); 26056723Sshinstatic int mask2attr(struct term_stat *term); 26156723Sshinstatic void set_keyboard(int command, int data); 26256723Sshinstatic void update_leds(int which); 26356723Sshinstatic void set_vgaregs(char *modetable); 26456723Sshinstatic void read_vgaregs(char *buf); 26556723Sshin#define COMP_IDENTICAL 0 26656723Sshin#define COMP_SIMILAR 1 26756723Sshin#define COMP_DIFFERENT 2 26856723Sshinstatic int comp_vgaregs(u_char *buf1, u_char *buf2); 26956723Sshinstatic void dump_vgaregs(u_char *buf); 27056723Sshin#define PARAM_BUFSIZE 6 27156723Sshinstatic void set_font_mode(u_char *buf); 27256723Sshinstatic void set_normal_mode(u_char *buf); 27356723Sshinstatic void set_destructive_cursor(scr_stat *scp); 27456723Sshinstatic void set_mouse_pos(scr_stat *scp); 27556723Sshinstatic int skip_spc_right(scr_stat *scp, u_short *p); 27656723Sshinstatic int skip_spc_left(scr_stat *scp, u_short *p); 27756723Sshinstatic void mouse_cut(scr_stat *scp); 27856723Sshinstatic void mouse_cut_start(scr_stat *scp); 27956723Sshinstatic void mouse_cut_end(scr_stat *scp); 28056723Sshinstatic void mouse_cut_word(scr_stat *scp); 28156723Sshinstatic void mouse_cut_line(scr_stat *scp); 28256723Sshinstatic void mouse_cut_extend(scr_stat *scp); 28356723Sshinstatic void mouse_paste(scr_stat *scp); 28456723Sshinstatic void draw_mouse_image(scr_stat *scp); 28556723Sshinstatic void remove_mouse_image(scr_stat *scp); 28656723Sshinstatic void draw_cutmarking(scr_stat *scp); 28756723Sshinstatic void remove_cutmarking(scr_stat *scp); 28856723Sshinstatic void save_palette(void); 28956723Sshinstatic void do_bell(scr_stat *scp, int pitch, int duration); 29056723Sshinstatic timeout_t blink_screen; 29156723Sshin#ifdef SC_SPLASH_SCREEN 29256723Sshinstatic void toggle_splash_screen(scr_stat *scp); 29356723Sshin#endif 29456723Sshin 29556723Sshinstruct isa_driver scdriver = { 29656723Sshin scprobe, scattach, "sc", 1 29756723Sshin}; 29856723Sshin 29956723Sshinstatic d_open_t scopen; 30056723Sshinstatic d_close_t scclose; 30156723Sshinstatic d_read_t scread; 30256723Sshinstatic d_write_t scwrite; 30356723Sshinstatic d_ioctl_t scioctl; 30456723Sshinstatic d_devtotty_t scdevtotty; 30556723Sshinstatic d_mmap_t scmmap; 30656723Sshin 30756723Sshin#define CDEV_MAJOR 12 30856723Sshinstatic struct cdevsw scdevsw = { 30956723Sshin scopen, scclose, scread, scwrite, 31056723Sshin scioctl, nullstop, noreset, scdevtotty, 31156723Sshin ttpoll, scmmap, nostrategy, "sc", NULL, -1 }; 31256723Sshin 31356723Sshin/* 31456723Sshin * These functions need to be before calls to them so they can be inlined. 31556723Sshin */ 31656723Sshinstatic inline void 31756723Sshindraw_cursor_image(scr_stat *scp) 31856723Sshin{ 31956723Sshin u_short cursor_image, *ptr = Crtat + (scp->cursor_pos - scp->scr_buf); 32056723Sshin u_short prev_image; 32156723Sshin 32256723Sshin /* do we have a destructive cursor ? */ 32356723Sshin if (flags & CHAR_CURSOR) { 32456723Sshin prev_image = scp->cursor_saveunder; 32556723Sshin cursor_image = *ptr & 0x00ff; 32656723Sshin if (cursor_image == DEAD_CHAR) 32756723Sshin cursor_image = prev_image & 0x00ff; 32856723Sshin cursor_image |= *(scp->cursor_pos) & 0xff00; 32956723Sshin scp->cursor_saveunder = cursor_image; 33056723Sshin /* update the cursor bitmap if the char under the cursor has changed */ 33156723Sshin if (prev_image != cursor_image) 33256723Sshin set_destructive_cursor(scp); 33356723Sshin /* modify cursor_image */ 33456723Sshin if (!(flags & BLINK_CURSOR)||((flags & BLINK_CURSOR)&&(blinkrate & 4))){ 33556723Sshin /* 33656723Sshin * When the mouse pointer is at the same position as the cursor, 33756723Sshin * the cursor bitmap needs to be updated even if the char under 33856723Sshin * the cursor hasn't changed, because the mouse pionter may 33956723Sshin * have moved by a few dots within the cursor cel. 34062587Sitojun */ 34162587Sitojun if ((prev_image == cursor_image) 34262587Sitojun && (cursor_image != *(scp->cursor_pos))) 34356723Sshin set_destructive_cursor(scp); 34456723Sshin cursor_image &= 0xff00; 34556723Sshin cursor_image |= DEAD_CHAR; 34656723Sshin } 34756723Sshin } 34856723Sshin else { 34956723Sshin cursor_image = (*(ptr) & 0x00ff) | *(scp->cursor_pos) & 0xff00; 35056723Sshin scp->cursor_saveunder = cursor_image; 35156723Sshin if (!(flags & BLINK_CURSOR)||((flags & BLINK_CURSOR)&&(blinkrate & 4))){ 35256723Sshin if ((cursor_image & 0x7000) == 0x7000) { 35356723Sshin cursor_image &= 0x8fff; 35456723Sshin if(!(cursor_image & 0x0700)) 35556723Sshin cursor_image |= 0x0700; 35656723Sshin } else { 35756723Sshin cursor_image |= 0x7000; 35856723Sshin if ((cursor_image & 0x0700) == 0x0700) 35956723Sshin cursor_image &= 0xf0ff; 36056723Sshin } 36156723Sshin } 36256723Sshin } 36356723Sshin *ptr = cursor_image; 36456723Sshin} 36556723Sshin 36656723Sshinstatic inline void 36756723Sshinremove_cursor_image(scr_stat *scp) 36856723Sshin{ 36956723Sshin *(Crtat + (scp->cursor_oldpos - scp->scr_buf)) = scp->cursor_saveunder; 37056723Sshin} 37156723Sshin 37256723Sshinstatic inline void 37356723Sshinmove_crsr(scr_stat *scp, int x, int y) 37456723Sshin{ 37556723Sshin if (x < 0) 37656723Sshin x = 0; 37756723Sshin if (y < 0) 37856723Sshin y = 0; 37956723Sshin if (x >= scp->xsize) 38056723Sshin x = scp->xsize-1; 38156723Sshin if (y >= scp->ysize) 38256723Sshin y = scp->ysize-1; 38362587Sitojun scp->xpos = x; 38456723Sshin scp->ypos = y; 38556723Sshin scp->cursor_pos = scp->scr_buf + scp->ypos * scp->xsize + scp->xpos; 38662587Sitojun} 38756723Sshin 38856723Sshinstatic int 38956723Sshinscprobe(struct isa_device *dev) 39056723Sshin{ 39156723Sshin if (!scvidprobe(dev->id_unit, dev->id_flags)) { 39256723Sshin if (bootverbose) 39356723Sshin printf("sc%d: no video adapter is found.\n", dev->id_unit); 39456723Sshin return (0); 39556723Sshin } 39656723Sshin 39756723Sshin sc_port = dev->id_iobase; 39856723Sshin if (sckbdprobe(dev->id_unit, dev->id_flags)) 39956723Sshin return (IO_KBDSIZE); 40056723Sshin else 40156723Sshin return ((dev->id_flags & DETECT_KBD) ? 0 : IO_KBDSIZE); 40256723Sshin} 40356723Sshin 40456723Sshin/* probe video adapters, return TRUE if found */ 40556723Sshinstatic int 40656723Sshinscvidprobe(int unit, int flags) 40756723Sshin{ 40856723Sshin /* 40956723Sshin * XXX don't try to `printf' anything here, the console may not have 41056723Sshin * been configured yet. 41162587Sitojun */ 41256723Sshin u_short volatile *cp; 41356723Sshin u_short was; 41456723Sshin u_long pa; 41556723Sshin u_long segoff; 41656723Sshin 41756723Sshin /* do this test only once */ 41856723Sshin if (init_done != COLD) 41956723Sshin return (Crtat != 0); 42056723Sshin 42156723Sshin /* 42256723Sshin * Finish defaulting crtc variables for a mono screen. Crtat is a 42356723Sshin * bogus common variable so that it can be shared with pcvt, so it 42456723Sshin * can't be statically initialized. XXX. 42556723Sshin */ 42656723Sshin Crtat = (u_short *)MONO_BUF; 42756723Sshin crtc_type = KD_MONO; 42856723Sshin /* If CGA memory seems to work, switch to color. */ 42956723Sshin cp = (u_short *)CGA_BUF; 43056723Sshin was = *cp; 43156723Sshin *cp = (u_short) 0xA55A; 43256723Sshin if (*cp == 0xA55A) { 43356723Sshin Crtat = (u_short *)CGA_BUF; 43456723Sshin crtc_addr = COLOR_BASE; 43556723Sshin crtc_type = KD_CGA; 43656723Sshin } else { 43756723Sshin cp = Crtat; 43856723Sshin was = *cp; 43956723Sshin *cp = (u_short) 0xA55A; 44056723Sshin if (*cp != 0xA55A) { 44156723Sshin /* no screen at all, bail out */ 44256723Sshin Crtat = 0; 44356723Sshin return FALSE; 44456723Sshin } 44556723Sshin } 44656723Sshin *cp = was; 44756723Sshin 44856723Sshin /* 44956723Sshin * Check rtc and BIOS date area. 45056723Sshin * XXX: don't use BIOSDATA_EQUIPMENT, it is not a dead copy 45156723Sshin * of RTC_EQUIPMENT. The bit 4 and 5 of the ETC_EQUIPMENT are 45256723Sshin * zeros for EGA and VGA. However, the EGA/VGA BIOS will set 45356723Sshin * these bits in BIOSDATA_EQUIPMENT according to the monitor 45456723Sshin * type detected. 45556723Sshin */ 45656723Sshin switch ((rtcin(RTC_EQUIPMENT) >> 4) & 3) { /* bit 4 and 5 */ 45756723Sshin case 0: /* EGA/VGA, or nothing */ 45856723Sshin crtc_type = KD_EGA; 45956723Sshin /* the color adapter may be in the 40x25 mode... XXX */ 46056723Sshin break; 46156723Sshin case 1: /* CGA 40x25 */ 46256723Sshin /* switch to the 80x25 mode? XXX */ 46356723Sshin /* FALL THROUGH */ 46456723Sshin case 2: /* CGA 80x25 */ 46556723Sshin /* `crtc_type' has already been set... */ 46656723Sshin /* crtc_type = KD_CGA; */ 46756723Sshin break; 46856723Sshin case 3: /* MDA */ 46956723Sshin /* `crtc_type' has already been set... */ 47056723Sshin /* crtc_type = KD_MONO; */ 47156723Sshin break; 47262587Sitojun } 47362587Sitojun 47462587Sitojun /* is this a VGA or higher ? */ 47562587Sitojun outb(crtc_addr, 7); 47656723Sshin if (inb(crtc_addr) == 7) { 47756723Sshin 47856723Sshin crtc_type = KD_VGA; 47956723Sshin crtc_vga = TRUE; 48056723Sshin read_vgaregs(vgaregs); 48156723Sshin 48256723Sshin /* Get the BIOS video mode pointer */ 48356723Sshin segoff = *(u_long *)pa_to_va(0x4a8); 48456723Sshin pa = (((segoff & 0xffff0000) >> 12) + (segoff & 0xffff)); 48556723Sshin if (ISMAPPED(pa, sizeof(u_long))) { 48656723Sshin segoff = *(u_long *)pa_to_va(pa); 48756723Sshin pa = (((segoff & 0xffff0000) >> 12) + (segoff & 0xffff)); 48856723Sshin if (ISMAPPED(pa, MODE_PARAM_SIZE)) 48956723Sshin video_mode_ptr = (char *)pa_to_va(pa); 49056723Sshin } 49156723Sshin } 49256723Sshin 49356723Sshin return TRUE; 49456723Sshin} 49556723Sshin 49656723Sshin/* probe the keyboard, return TRUE if found */ 49756723Sshinstatic int 49856723Sshinsckbdprobe(int unit, int flags) 49956723Sshin{ 50056723Sshin int codeset; 50156723Sshin int c = -1; 50256723Sshin int m; 50356723Sshin 50456723Sshin sc_kbdc = kbdc_open(sc_port); 50556723Sshin 50656723Sshin if (!kbdc_lock(sc_kbdc, TRUE)) { 50756723Sshin /* driver error? */ 50856723Sshin printf("sc%d: unable to lock the controller.\n", unit); 50956723Sshin return ((flags & DETECT_KBD) ? FALSE : TRUE); 51056723Sshin } 51156723Sshin 51262587Sitojun /* discard anything left after UserConfig */ 51356723Sshin empty_both_buffers(sc_kbdc, 10); 51456723Sshin 51556723Sshin /* save the current keyboard controller command byte */ 51656723Sshin m = kbdc_get_device_mask(sc_kbdc) & ~KBD_KBD_CONTROL_BITS; 51756723Sshin c = get_controller_command_byte(sc_kbdc); 51856723Sshin if (c == -1) { 51956723Sshin /* CONTROLLER ERROR */ 52056723Sshin printf("sc%d: unable to get the current command byte value.\n", unit); 52156723Sshin goto fail; 52256723Sshin } 52356723Sshin if (bootverbose) 52456723Sshin printf("sc%d: the current keyboard controller command byte %04x\n", 52556723Sshin unit, c); 52656723Sshin#if 0 52756723Sshin /* override the keyboard lock switch */ 52856723Sshin c |= KBD_OVERRIDE_KBD_LOCK; 52956723Sshin#endif 53056723Sshin 53156723Sshin /* 53256723Sshin * The keyboard may have been screwed up by the boot block. 53356723Sshin * We may just be able to recover from error by testing the controller 53456723Sshin * and the keyboard port. The controller command byte needs to be saved 53556723Sshin * before this recovery operation, as some controllers seem to set 53662587Sitojun * the command byte to particular values. 53762587Sitojun */ 53862587Sitojun test_controller(sc_kbdc); 53956723Sshin test_kbd_port(sc_kbdc); 54056723Sshin 54156723Sshin /* enable the keyboard port, but disable the keyboard intr. */ 54256723Sshin if (!set_controller_command_byte(sc_kbdc, 54356723Sshin KBD_KBD_CONTROL_BITS, 54456723Sshin KBD_ENABLE_KBD_PORT | KBD_DISABLE_KBD_INT)) { 54556723Sshin /* CONTROLLER ERROR 54656723Sshin * there is very little we can do... 54756723Sshin */ 54856723Sshin printf("sc%d: unable to set the command byte.\n", unit); 54956723Sshin goto fail; 55056723Sshin } 55156723Sshin 55256723Sshin /* 55356723Sshin * Check if we have an XT keyboard before we attempt to reset it. 55456723Sshin * The procedure assumes that the keyboard and the controller have 55556723Sshin * been set up properly by BIOS and have not been messed up 55656723Sshin * during the boot process. 55756723Sshin */ 55856723Sshin codeset = -1; 55956723Sshin if (flags & XT_KEYBD) 56056723Sshin /* the user says there is a XT keyboard */ 56156723Sshin codeset = 1; 56256723Sshin#ifdef DETECT_XT_KEYBOARD 56356723Sshin else if ((c & KBD_TRANSLATION) == 0) { 56456723Sshin /* SET_SCANCODE_SET is not always supported; ignore error */ 56556723Sshin if (send_kbd_command_and_data(sc_kbdc, KBDC_SET_SCANCODE_SET, 0) 56656723Sshin == KBD_ACK) 56756723Sshin codeset = read_kbd_data(sc_kbdc); 56856723Sshin } 56956723Sshin if (bootverbose) 57056723Sshin printf("sc%d: keyboard scancode set %d\n", unit, codeset); 57156723Sshin#endif /* DETECT_XT_KEYBOARD */ 57256723Sshin 57356723Sshin if (flags & KBD_NORESET) { 57456723Sshin write_kbd_command(sc_kbdc, KBDC_ECHO); 57562587Sitojun if (read_kbd_data(sc_kbdc) != KBD_ECHO) { 57662587Sitojun empty_both_buffers(sc_kbdc, 10); 57762587Sitojun test_controller(sc_kbdc); 57862587Sitojun test_kbd_port(sc_kbdc); 57956723Sshin if (bootverbose) 58056723Sshin printf("sc%d: failed to get response from the keyboard.\n", 58156723Sshin unit); 58256723Sshin goto fail; 58356723Sshin } 58456723Sshin } else { 58556723Sshin /* reset keyboard hardware */ 58656723Sshin if (!reset_kbd(sc_kbdc)) { 58756723Sshin /* KEYBOARD ERROR 58856723Sshin * Keyboard reset may fail either because the keyboard doen't 58956723Sshin * exist, or because the keyboard doesn't pass the self-test, 59056723Sshin * or the keyboard controller on the motherboard and the keyboard 59156723Sshin * somehow fail to shake hands. It is just possible, particularly 59256723Sshin * in the last case, that the keyoard controller may be left 59356723Sshin * in a hung state. test_controller() and test_kbd_port() appear 59456723Sshin * to bring the keyboard controller back (I don't know why and 59556723Sshin * how, though.) 59656723Sshin */ 59756723Sshin empty_both_buffers(sc_kbdc, 10); 59856723Sshin test_controller(sc_kbdc); 59956723Sshin test_kbd_port(sc_kbdc); 60056723Sshin /* We could disable the keyboard port and interrupt... but, 60156723Sshin * the keyboard may still exist (see above). 60256723Sshin */ 60356723Sshin if (bootverbose) 60456723Sshin printf("sc%d: failed to reset the keyboard.\n", unit); 60556723Sshin goto fail; 60656723Sshin } 60756723Sshin } 60856723Sshin 60956723Sshin /* 61056723Sshin * Allow us to set the XT_KEYBD flag in UserConfig so that keyboards 61156723Sshin * such as those on the IBM ThinkPad laptop computers can be used 61256723Sshin * with the standard console driver. 61356723Sshin */ 61456723Sshin if (codeset == 1) { 61556723Sshin if (send_kbd_command_and_data( 61656723Sshin sc_kbdc, KBDC_SET_SCANCODE_SET, codeset) == KBD_ACK) { 61756723Sshin /* XT kbd doesn't need scan code translation */ 61856723Sshin c &= ~KBD_TRANSLATION; 61956723Sshin } else { 62056723Sshin /* KEYBOARD ERROR 62156723Sshin * The XT kbd isn't usable unless the proper scan code set 62256723Sshin * is selected. 62356723Sshin */ 62456723Sshin printf("sc%d: unable to set the XT keyboard mode.\n", unit); 62556723Sshin goto fail; 62656723Sshin } 62756723Sshin } 62856723Sshin /* enable the keyboard port and intr. */ 62956723Sshin if (!set_controller_command_byte(sc_kbdc, 63062587Sitojun KBD_KBD_CONTROL_BITS | KBD_TRANSLATION | KBD_OVERRIDE_KBD_LOCK, 63162587Sitojun (c & (KBD_TRANSLATION | KBD_OVERRIDE_KBD_LOCK)) 63262587Sitojun | KBD_ENABLE_KBD_PORT | KBD_ENABLE_KBD_INT)) { 63362587Sitojun /* CONTROLLER ERROR 63456723Sshin * This is serious; we are left with the disabled keyboard intr. 63556723Sshin */ 63656723Sshin printf("sc%d: unable to enable the keyboard port and intr.\n", unit); 63756723Sshin goto fail; 63856723Sshin } 63956723Sshin 64056723Sshin kbdc_set_device_mask(sc_kbdc, m | KBD_KBD_CONTROL_BITS), 64156723Sshin kbdc_lock(sc_kbdc, FALSE); 64256723Sshin return TRUE; 64356723Sshin 64456723Sshinfail: 64556723Sshin if (c != -1) 64656723Sshin /* try to restore the command byte as before, if possible */ 64756723Sshin set_controller_command_byte(sc_kbdc, 0xff, c); 64856723Sshin kbdc_set_device_mask(sc_kbdc, 64956723Sshin (flags & DETECT_KBD) ? m : m | KBD_KBD_CONTROL_BITS); 65056723Sshin kbdc_lock(sc_kbdc, FALSE); 65156723Sshin return FALSE; 65256723Sshin} 65356723Sshin 65456723Sshin#if NAPM > 0 65556723Sshinstatic int 65656723Sshinscresume(void *dummy) 65756723Sshin{ 65856723Sshin shfts = ctls = alts = agrs = metas = accents = 0; 65956723Sshin return 0; 66056723Sshin} 66156723Sshin#endif 66256723Sshin 66356723Sshinstatic int 66456723Sshinscattach(struct isa_device *dev) 66556723Sshin{ 66656723Sshin scr_stat *scp; 66756723Sshin dev_t cdev = makedev(CDEV_MAJOR, 0); 66856723Sshin char *p; 66956723Sshin#ifdef DEVFS 67056723Sshin int vc; 67156723Sshin#endif 67256723Sshin 67356723Sshin scinit(); 67456723Sshin flags = dev->id_flags; 67556723Sshin if (!crtc_vga) 67656723Sshin flags &= ~CHAR_CURSOR; 67756723Sshin 67856723Sshin scp = console[0]; 67956723Sshin 68056723Sshin if (crtc_vga) { 68156723Sshin cut_buffer = (char *)malloc(scp->xsize*scp->ysize, M_DEVBUF, M_NOWAIT); 68256723Sshin } 68356723Sshin 68456723Sshin scp->scr_buf = (u_short *)malloc(scp->xsize*scp->ysize*sizeof(u_short), 68556723Sshin M_DEVBUF, M_NOWAIT); 68656723Sshin 68756723Sshin /* copy temporary buffer to final buffer */ 68856723Sshin bcopy(sc_buffer, scp->scr_buf, scp->xsize * scp->ysize * sizeof(u_short)); 68956723Sshin 69056723Sshin scp->cursor_pos = scp->cursor_oldpos = 69156723Sshin scp->scr_buf + scp->xpos + scp->ypos * scp->xsize; 69256723Sshin scp->mouse_pos = scp->mouse_oldpos = 69356723Sshin scp->scr_buf + ((scp->mouse_ypos/scp->font_size)*scp->xsize + 69456723Sshin scp->mouse_xpos/8); 69556723Sshin 69656723Sshin /* initialize history buffer & pointers */ 69756723Sshin scp->history_head = scp->history_pos = 69856723Sshin (u_short *)malloc(scp->history_size*sizeof(u_short), 69956723Sshin M_DEVBUF, M_NOWAIT); 70056723Sshin if (scp->history_head != NULL) 70156723Sshin bzero(scp->history_head, scp->history_size*sizeof(u_short)); 70256723Sshin scp->history = scp->history_head; 70356723Sshin 70456723Sshin /* initialize cursor stuff */ 70556723Sshin if (!(scp->status & UNKNOWN_MODE)) 70656723Sshin draw_cursor_image(scp); 70756723Sshin 70856723Sshin /* get screen update going */ 70956723Sshin scrn_timer(NULL); 71056723Sshin 71156723Sshin update_leds(scp->status); 71256723Sshin 71356723Sshin if ((crtc_type == KD_VGA) && bootverbose) { 71456723Sshin printf("sc%d: BIOS video mode:%d\n", 71556723Sshin dev->id_unit, *(u_char *)pa_to_va(0x449)); 71656723Sshin printf("sc%d: VGA registers upon power-up\n", dev->id_unit); 71756723Sshin dump_vgaregs(vgaregs); 71856723Sshin printf("sc%d: video mode:%d\n", dev->id_unit, scp->mode); 71956723Sshin printf("sc%d: VGA registers in BIOS for mode:%d\n", 72056723Sshin dev->id_unit, scp->mode); 72156723Sshin dump_vgaregs(vgaregs2); 72256723Sshin p = get_mode_param(scp, scp->mode); 72356723Sshin if (p != NULL) { 72456723Sshin printf("sc%d: VGA registers to be used for mode:%d\n", 72556723Sshin dev->id_unit, scp->mode); 72656723Sshin dump_vgaregs(p); 72756723Sshin } 72856723Sshin printf("sc%d: rows_offset:%d\n", dev->id_unit, rows_offset); 72956723Sshin } 73056723Sshin if ((crtc_type == KD_VGA) && (video_mode_ptr == NULL)) 73156723Sshin printf("sc%d: WARNING: video mode switching is only partially supported\n", 73256723Sshin dev->id_unit); 73356723Sshin 73456723Sshin printf("sc%d: ", dev->id_unit); 73556723Sshin switch(crtc_type) { 73656723Sshin case KD_VGA: 73756723Sshin if (crtc_addr == MONO_BASE) 73856723Sshin printf("VGA mono"); 73956723Sshin else 74056723Sshin printf("VGA color"); 74156723Sshin break; 74256723Sshin case KD_EGA: 74356723Sshin if (crtc_addr == MONO_BASE) 74456723Sshin printf("EGA mono"); 74556723Sshin else 74656723Sshin printf("EGA color"); 74756723Sshin break; 74856723Sshin case KD_CGA: 74956723Sshin printf("CGA"); 75056723Sshin break; 75156723Sshin case KD_MONO: 75256723Sshin case KD_HERCULES: 75356723Sshin default: 75456723Sshin printf("MDA/hercules"); 75556723Sshin break; 75662587Sitojun } 75756723Sshin printf(" <%d virtual consoles, flags=0x%x>\n", MAXCONS, flags); 75856723Sshin 75956723Sshin#if NAPM > 0 76056723Sshin scp->r_hook.ah_fun = scresume; 76156723Sshin scp->r_hook.ah_arg = NULL; 76256723Sshin scp->r_hook.ah_name = "system keyboard"; 76356723Sshin scp->r_hook.ah_order = APM_MID_ORDER; 76456723Sshin apm_hook_establish(APM_HOOK_RESUME , &scp->r_hook); 76567455Sitojun#endif 76656723Sshin 76756723Sshin cdevsw_add(&cdev, &scdevsw, NULL); 76856723Sshin 76956723Sshin#ifdef DEVFS 77056723Sshin for (vc = 0; vc < MAXCONS; vc++) 77156723Sshin sc_devfs_token[vc] = devfs_add_devswf(&scdevsw, vc, DV_CHR, 77256723Sshin UID_ROOT, GID_WHEEL, 0600, "ttyv%n", vc); 77356723Sshin sc_mouse_devfs_token = devfs_add_devswf(&scdevsw, SC_MOUSE, DV_CHR, 77456723Sshin UID_ROOT, GID_WHEEL, 0600, "sysmouse"); 77556723Sshin sc_console_devfs_token = devfs_add_devswf(&scdevsw, SC_CONSOLE, DV_CHR, 77656723Sshin UID_ROOT, GID_WHEEL, 0600, "consolectl"); 77756723Sshin#endif 77856723Sshin return 0; 77956723Sshin} 78056723Sshin 78156723Sshinstruct tty 78256723Sshin*scdevtotty(dev_t dev) 78356723Sshin{ 78462587Sitojun int unit = minor(dev); 78556723Sshin 78656723Sshin if (init_done == COLD) 78756723Sshin return(NULL); 78856723Sshin if (unit == SC_CONSOLE) 78967455Sitojun return CONSOLE_TTY; 79056723Sshin if (unit == SC_MOUSE) 79156723Sshin return MOUSE_TTY; 79256723Sshin if (unit >= MAXCONS || unit < 0) 79356723Sshin return(NULL); 79456723Sshin return VIRTUAL_TTY(unit); 79556723Sshin} 79662587Sitojun 79756723Sshinint 79856723Sshinscopen(dev_t dev, int flag, int mode, struct proc *p) 79956723Sshin{ 80056723Sshin struct tty *tp = scdevtotty(dev); 80156723Sshin 80256723Sshin if (!tp) 80356723Sshin return(ENXIO); 80456723Sshin 80556723Sshin tp->t_oproc = (minor(dev) == SC_MOUSE) ? scmousestart : scstart; 80656723Sshin tp->t_param = scparam; 80756723Sshin tp->t_dev = dev; 80856723Sshin if (!(tp->t_state & TS_ISOPEN)) { 80956723Sshin ttychars(tp); 81056723Sshin /* Use the current setting of the <-- key as default VERASE. */ 81156723Sshin /* If the Delete key is preferable, an stty is necessary */ 81256723Sshin tp->t_cc[VERASE] = key_map.key[0x0e].map[0]; 81356723Sshin tp->t_iflag = TTYDEF_IFLAG; 81456723Sshin tp->t_oflag = TTYDEF_OFLAG; 81556723Sshin tp->t_cflag = TTYDEF_CFLAG; 81656723Sshin tp->t_lflag = TTYDEF_LFLAG; 81756723Sshin tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; 81856723Sshin scparam(tp, &tp->t_termios); 81956723Sshin ttsetwater(tp); 82056723Sshin (*linesw[tp->t_line].l_modem)(tp, 1); 82156723Sshin if (minor(dev) == SC_MOUSE) 82256723Sshin mouse_level = 0; /* XXX */ 82362587Sitojun } 82456723Sshin else 82556723Sshin if (tp->t_state & TS_XCLUDE && p->p_ucred->cr_uid != 0) 82656723Sshin return(EBUSY); 82762587Sitojun if (minor(dev) < MAXCONS && !console[minor(dev)]) { 82856723Sshin console[minor(dev)] = alloc_scp(); 82956723Sshin } 83056723Sshin if (minor(dev)<MAXCONS && !tp->t_winsize.ws_col && !tp->t_winsize.ws_row) { 83156723Sshin tp->t_winsize.ws_col = console[minor(dev)]->xsize; 83256723Sshin tp->t_winsize.ws_row = console[minor(dev)]->ysize; 83356723Sshin } 83456723Sshin return ((*linesw[tp->t_line].l_open)(dev, tp)); 83556723Sshin} 83656723Sshin 83756723Sshinint 83856723Sshinscclose(dev_t dev, int flag, int mode, struct proc *p) 83956723Sshin{ 84056723Sshin struct tty *tp = scdevtotty(dev); 84156723Sshin struct scr_stat *scp; 84256723Sshin 84356723Sshin if (!tp) 84456723Sshin return(ENXIO); 84556723Sshin if (minor(dev) < MAXCONS) { 84656723Sshin scp = get_scr_stat(tp->t_dev); 84756723Sshin if (scp->status & SWITCH_WAIT_ACQ) 84856723Sshin wakeup((caddr_t)&scp->smode); 84956723Sshin#if not_yet_done 85056723Sshin if (scp == &main_console) { 85156723Sshin scp->pid = 0; 85256723Sshin scp->proc = NULL; 85356723Sshin scp->smode.mode = VT_AUTO; 85456723Sshin } 85556723Sshin else { 85656723Sshin free(scp->scr_buf, M_DEVBUF); 85756723Sshin if (scp->history != NULL) { 85856723Sshin free(scp->history, M_DEVBUF); 85956723Sshin if (scp->history_size / scp->xsize 86056723Sshin > imax(SC_HISTORY_SIZE, scp->ysize)) 86156723Sshin extra_history_size += scp->history_size / scp->xsize 86256723Sshin - imax(SC_HISTORY_SIZE, scp->ysize); 86356723Sshin } 86456723Sshin free(scp, M_DEVBUF); 86556723Sshin console[minor(dev)] = NULL; 86656723Sshin } 86756723Sshin#else 86856723Sshin scp->pid = 0; 86956723Sshin scp->proc = NULL; 87056723Sshin scp->smode.mode = VT_AUTO; 87156723Sshin#endif 87256723Sshin } 87356723Sshin spltty(); 87456723Sshin (*linesw[tp->t_line].l_close)(tp, flag); 87556723Sshin ttyclose(tp); 87656723Sshin spl0(); 87756723Sshin return(0); 87856723Sshin} 87956723Sshin 88056723Sshinint 88156723Sshinscread(dev_t dev, struct uio *uio, int flag) 88256723Sshin{ 88356723Sshin struct tty *tp = scdevtotty(dev); 88456723Sshin 88556723Sshin if (!tp) 88656723Sshin return(ENXIO); 88756723Sshin return((*linesw[tp->t_line].l_read)(tp, uio, flag)); 88856723Sshin} 88956723Sshin 89056723Sshinint 89156723Sshinscwrite(dev_t dev, struct uio *uio, int flag) 89256723Sshin{ 89356723Sshin struct tty *tp = scdevtotty(dev); 89456723Sshin 89556723Sshin if (!tp) 89656723Sshin return(ENXIO); 89756723Sshin return((*linesw[tp->t_line].l_write)(tp, uio, flag)); 89856723Sshin} 89956723Sshin 90056723Sshinvoid 90156723Sshinscintr(int unit) 90256723Sshin{ 90356723Sshin static struct tty *cur_tty; 90456723Sshin int c, len; 90556723Sshin u_char *cp; 90656723Sshin 90756723Sshin /* make screensaver happy */ 90856723Sshin scrn_time_stamp = mono_time.tv_sec; 90956723Sshin 91056723Sshin /* 91156723Sshin * Loop while there is still input to get from the keyboard. 91256723Sshin * I don't think this is nessesary, and it doesn't fix 91356723Sshin * the Xaccel-2.1 keyboard hang, but it can't hurt. XXX 91456723Sshin */ 91556723Sshin while ((c = scgetc(SCGETC_NONBLOCK)) != NOKEY) { 91656723Sshin 91756723Sshin cur_tty = VIRTUAL_TTY(get_scr_num()); 91856723Sshin if (!(cur_tty->t_state & TS_ISOPEN)) 91956723Sshin if (!((cur_tty = CONSOLE_TTY)->t_state & TS_ISOPEN)) 92056723Sshin continue; 92156723Sshin 92256723Sshin switch (c & 0xff00) { 92356723Sshin case 0x0000: /* normal key */ 92456723Sshin (*linesw[cur_tty->t_line].l_rint)(c & 0xFF, cur_tty); 92556723Sshin break; 92656723Sshin case FKEY: /* function key, return string */ 92756723Sshin if (cp = get_fstr((u_int)c, (u_int *)&len)) { 92856723Sshin while (len-- > 0) 92956723Sshin (*linesw[cur_tty->t_line].l_rint)(*cp++ & 0xFF, cur_tty); 93056723Sshin } 93156723Sshin break; 93256723Sshin case MKEY: /* meta is active, prepend ESC */ 93356723Sshin (*linesw[cur_tty->t_line].l_rint)(0x1b, cur_tty); 93456723Sshin (*linesw[cur_tty->t_line].l_rint)(c & 0xFF, cur_tty); 93556723Sshin break; 93656723Sshin case BKEY: /* backtab fixed sequence (esc [ Z) */ 93756723Sshin (*linesw[cur_tty->t_line].l_rint)(0x1b, cur_tty); 93856723Sshin (*linesw[cur_tty->t_line].l_rint)('[', cur_tty); 93956723Sshin (*linesw[cur_tty->t_line].l_rint)('Z', cur_tty); 94056723Sshin break; 94156723Sshin } 94267455Sitojun } 94367455Sitojun 94467455Sitojun if (cur_console->status & MOUSE_ENABLED) { 94567455Sitojun cur_console->status &= ~MOUSE_VISIBLE; 94667455Sitojun remove_mouse_image(cur_console); 94767455Sitojun } 94867455Sitojun} 94967455Sitojun 95067455Sitojunstatic int 95167455Sitojunscparam(struct tty *tp, struct termios *t) 95267455Sitojun{ 95367455Sitojun tp->t_ispeed = t->c_ispeed; 95467455Sitojun tp->t_ospeed = t->c_ospeed; 95567455Sitojun tp->t_cflag = t->c_cflag; 95667455Sitojun return 0; 95767455Sitojun} 95867455Sitojun 95967455Sitojunint 96067455Sitojunscioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p) 96167455Sitojun{ 96267455Sitojun int error; 96367455Sitojun u_int i; 96456723Sshin struct tty *tp; 96556723Sshin scr_stat *scp; 96656723Sshin u_short *usp; 96756723Sshin char *mp; 96856723Sshin int s; 96956723Sshin 97056723Sshin tp = scdevtotty(dev); 97156723Sshin if (!tp) 97256723Sshin return ENXIO; 97356723Sshin scp = get_scr_stat(tp->t_dev); 97456723Sshin 97556723Sshin /* If there is a user_ioctl function call that first */ 97656723Sshin if (sc_user_ioctl) { 97756723Sshin if (error = (*sc_user_ioctl)(dev, cmd, data, flag, p)) 97856723Sshin return error; 97956723Sshin } 98056723Sshin 98156723Sshin switch (cmd) { /* process console hardware related ioctl's */ 98256723Sshin 98356723Sshin case GIO_ATTR: /* get current attributes */ 98456723Sshin *(int*)data = (scp->term.cur_attr >> 8) & 0xFF; 98556723Sshin return 0; 98656723Sshin 98756723Sshin case GIO_COLOR: /* is this a color console ? */ 98856723Sshin if (crtc_addr == COLOR_BASE) 98956723Sshin *(int*)data = 1; 99056723Sshin else 99156723Sshin *(int*)data = 0; 99256723Sshin return 0; 99356723Sshin 99456723Sshin case CONS_CURRENT: /* get current adapter type */ 99556723Sshin *(int *)data = crtc_type; 99656723Sshin return 0; 99756723Sshin 99856723Sshin case CONS_GET: /* get current video mode */ 99956723Sshin *(int*)data = scp->mode; 100056723Sshin return 0; 100156723Sshin 100256723Sshin case CONS_BLANKTIME: /* set screen saver timeout (0 = no saver) */ 100356723Sshin if (*(int *)data < 0) 100456723Sshin return EINVAL; 100556723Sshin scrn_blank_time = *(int *)data; 100656723Sshin if (scrn_blank_time == 0) 100756723Sshin scrn_time_stamp = mono_time.tv_sec; 100856723Sshin return 0; 100956723Sshin 101056723Sshin case CONS_CURSORTYPE: /* set cursor type blink/noblink */ 101156723Sshin if ((*(int*)data) & 0x01) 101256723Sshin flags |= BLINK_CURSOR; 101356723Sshin else 101456723Sshin flags &= ~BLINK_CURSOR; 101556723Sshin if ((*(int*)data) & 0x02) { 101656723Sshin if (!crtc_vga) 101756723Sshin return ENXIO; 101856723Sshin flags |= CHAR_CURSOR; 101956723Sshin } else 102056723Sshin flags &= ~CHAR_CURSOR; 102162587Sitojun /* 102256723Sshin * The cursor shape is global property; all virtual consoles 102356723Sshin * are affected. Update the cursor in the current console... 102456723Sshin */ 102556723Sshin if (!(cur_console->status & UNKNOWN_MODE)) { 102656723Sshin remove_cursor_image(cur_console); 102756723Sshin if (flags & CHAR_CURSOR) 102856723Sshin set_destructive_cursor(cur_console); 102956723Sshin draw_cursor_image(cur_console); 103056723Sshin } 103156723Sshin return 0; 103256723Sshin 103356723Sshin case CONS_BELLTYPE: /* set bell type sound/visual */ 103456723Sshin if (*data) 103562587Sitojun flags |= VISUAL_BELL; 103662587Sitojun else 103762587Sitojun flags &= ~VISUAL_BELL; 103856723Sshin return 0; 103956723Sshin 104056723Sshin case CONS_HISTORY: /* set history size */ 104156723Sshin if (*(int *)data > 0) { 104256723Sshin int lines; /* buffer size to allocate */ 104356723Sshin int lines0; /* current buffer size */ 104456723Sshin 104556723Sshin lines = imax(*(int *)data, scp->ysize); 104656723Sshin lines0 = (scp->history != NULL) ? 104756723Sshin scp->history_size / scp->xsize : scp->ysize; 104856723Sshin /* 104956723Sshin * syscons unconditionally allocates buffers upto SC_HISTORY_SIZE 105056723Sshin * lines or scp->ysize lines, whichever is larger. A value 105156723Sshin * greater than that is allowed, subject to extra_history_size. 105256723Sshin */ 105356723Sshin if (lines > imax(lines0, SC_HISTORY_SIZE) + extra_history_size) 105456723Sshin return EINVAL; 105556723Sshin if (cur_console->status & BUFFER_SAVED) 105656723Sshin return EBUSY; 105756723Sshin usp = scp->history; 105856723Sshin scp->history = NULL; 105956723Sshin if (usp != NULL) 106056723Sshin free(usp, M_DEVBUF); 106156723Sshin scp->history_size = lines * scp->xsize; 106256723Sshin /* 106356723Sshin * extra_history_size += 106456723Sshin * (lines0 > imax(SC_HISTORY_SIZE, scp->ysize)) ? 106556723Sshin * lines0 - imax(SC_HISTORY_SIZE, scp->ysize)) : 0; 106662587Sitojun * extra_history_size -= 106762587Sitojun * (lines > imax(SC_HISTORY_SIZE, scp->ysize)) ? 106862587Sitojun * lines - imax(SC_HISTORY_SIZE, scp->ysize)) : 0; 106962587Sitojun * lines0 >= ysize && lines >= ysize... Hey, the above can be 107062587Sitojun * reduced to the following... 107162587Sitojun */ 107262587Sitojun extra_history_size += 107362587Sitojun imax(lines0, SC_HISTORY_SIZE) - imax(lines, SC_HISTORY_SIZE); 107462587Sitojun usp = (u_short *)malloc(scp->history_size * sizeof(u_short), 107562587Sitojun M_DEVBUF, M_WAITOK); 107662587Sitojun bzero(usp, scp->history_size * sizeof(u_short)); 107762587Sitojun scp->history_head = scp->history_pos = usp; 107862587Sitojun scp->history = usp; 107962587Sitojun return 0; 108062587Sitojun } 108162587Sitojun else 108262587Sitojun return EINVAL; 108362587Sitojun 108462587Sitojun case CONS_MOUSECTL: /* control mouse arrow */ 108562587Sitojun case OLD_CONS_MOUSECTL: 108662587Sitojun { 108762587Sitojun /* MOUSE_BUTTON?DOWN -> MOUSE_MSC_BUTTON?UP */ 108862587Sitojun static butmap[8] = { 108962587Sitojun MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON2UP 109062587Sitojun | MOUSE_MSC_BUTTON3UP, 109156723Sshin MOUSE_MSC_BUTTON2UP | MOUSE_MSC_BUTTON3UP, 109256723Sshin MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON3UP, 109356723Sshin MOUSE_MSC_BUTTON3UP, 109456723Sshin MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON2UP, 109556723Sshin MOUSE_MSC_BUTTON2UP, 109656723Sshin MOUSE_MSC_BUTTON1UP, 109756723Sshin 0, 109856723Sshin }; 109956723Sshin mouse_info_t *mouse = (mouse_info_t*)data; 110056723Sshin mouse_info_t buf; 110156723Sshin 110256723Sshin if (!crtc_vga) 110362587Sitojun return ENODEV; 110462587Sitojun 110562587Sitojun if (cmd == OLD_CONS_MOUSECTL) { 110662587Sitojun static unsigned char swapb[] = { 0, 4, 2, 6, 1, 5, 3, 7 }; 110762587Sitojun old_mouse_info_t *old_mouse = (old_mouse_info_t *)data; 110862587Sitojun 110962587Sitojun mouse = &buf; 111062587Sitojun mouse->operation = old_mouse->operation; 111162587Sitojun switch (mouse->operation) { 111262587Sitojun case MOUSE_MODE: 111356723Sshin mouse->u.mode = old_mouse->u.mode; 111456723Sshin break; 111556723Sshin case MOUSE_SHOW: 111656723Sshin case MOUSE_HIDE: 111756723Sshin break; 111856723Sshin case MOUSE_MOVEABS: 111956723Sshin case MOUSE_MOVEREL: 112056723Sshin case MOUSE_ACTION: 112156723Sshin mouse->u.data.x = old_mouse->u.data.x; 112256723Sshin mouse->u.data.y = old_mouse->u.data.y; 112356723Sshin mouse->u.data.z = 0; 112456723Sshin mouse->u.data.buttons = swapb[old_mouse->u.data.buttons & 0x7]; 112556723Sshin break; 112656723Sshin case MOUSE_GETINFO: 112756723Sshin old_mouse->u.data.x = scp->mouse_xpos; 112856723Sshin old_mouse->u.data.y = scp->mouse_ypos; 112956723Sshin old_mouse->u.data.buttons = swapb[scp->mouse_buttons & 0x7]; 113056723Sshin break; 113156723Sshin default: 113256723Sshin return EINVAL; 113356723Sshin } 113456723Sshin } 113556723Sshin 113656723Sshin switch (mouse->operation) { 113756723Sshin case MOUSE_MODE: 113856723Sshin if (ISSIGVALID(mouse->u.mode.signal)) { 113956723Sshin scp->mouse_signal = mouse->u.mode.signal; 114056723Sshin scp->mouse_proc = p; 114156723Sshin scp->mouse_pid = p->p_pid; 114256723Sshin } 114356723Sshin else { 114456723Sshin scp->mouse_signal = 0; 114556723Sshin scp->mouse_proc = NULL; 114656723Sshin scp->mouse_pid = 0; 114756723Sshin } 114856723Sshin break; 114956723Sshin 115056723Sshin case MOUSE_SHOW: 115156723Sshin if (!(scp->status & MOUSE_ENABLED)) { 115256723Sshin scp->status |= (MOUSE_ENABLED | MOUSE_VISIBLE); 115356723Sshin scp->mouse_oldpos = scp->mouse_pos; 115456723Sshin mark_all(scp); 115556723Sshin } 115656723Sshin else 115756723Sshin return EINVAL; 115856723Sshin break; 115956723Sshin 116056723Sshin case MOUSE_HIDE: 116156723Sshin if (scp->status & MOUSE_ENABLED) { 116256723Sshin scp->status &= ~(MOUSE_ENABLED | MOUSE_VISIBLE); 116356723Sshin mark_all(scp); 116456723Sshin } 116556723Sshin else 116656723Sshin return EINVAL; 116756723Sshin break; 116856723Sshin 116956723Sshin case MOUSE_MOVEABS: 117056723Sshin scp->mouse_xpos = mouse->u.data.x; 117156723Sshin scp->mouse_ypos = mouse->u.data.y; 117256723Sshin set_mouse_pos(scp); 117356723Sshin break; 117456723Sshin 117556723Sshin case MOUSE_MOVEREL: 117656723Sshin scp->mouse_xpos += mouse->u.data.x; 117756723Sshin scp->mouse_ypos += mouse->u.data.y; 117856723Sshin set_mouse_pos(scp); 117956723Sshin break; 118056723Sshin 118156723Sshin case MOUSE_GETINFO: 118256723Sshin mouse->u.data.x = scp->mouse_xpos; 118356723Sshin mouse->u.data.y = scp->mouse_ypos; 118456723Sshin mouse->u.data.z = 0; 118556723Sshin mouse->u.data.buttons = scp->mouse_buttons; 118656723Sshin break; 118756723Sshin 118856723Sshin case MOUSE_ACTION: 118956723Sshin case MOUSE_MOTION_EVENT: 119056723Sshin /* this should maybe only be settable from /dev/consolectl SOS */ 119156723Sshin /* send out mouse event on /dev/sysmouse */ 119256723Sshin 119356723Sshin mouse_status.dx += mouse->u.data.x; 119456723Sshin mouse_status.dy += mouse->u.data.y; 119556723Sshin mouse_status.dz += mouse->u.data.z; 119656723Sshin if (mouse->operation == MOUSE_ACTION) 119756723Sshin mouse_status.button = mouse->u.data.buttons; 119856723Sshin mouse_status.flags |= 119956723Sshin ((mouse->u.data.x || mouse->u.data.y || mouse->u.data.z) ? 120056723Sshin MOUSE_POSCHANGED : 0) 120156723Sshin | (mouse_status.obutton ^ mouse_status.button); 120256723Sshin 120356723Sshin if (cur_console->status & MOUSE_ENABLED) 120456723Sshin cur_console->status |= MOUSE_VISIBLE; 120556723Sshin 120656723Sshin if ((MOUSE_TTY)->t_state & TS_ISOPEN) { 120756723Sshin u_char buf[MOUSE_SYS_PACKETSIZE]; 120856723Sshin int j; 120956723Sshin 121056723Sshin /* the first five bytes are compatible with MouseSystems' */ 121156723Sshin buf[0] = MOUSE_MSC_SYNC 121256723Sshin | butmap[mouse_status.button & MOUSE_STDBUTTONS]; 121356723Sshin j = imax(imin(mouse->u.data.x, 255), -256); 121456723Sshin buf[1] = j >> 1; 121556723Sshin buf[3] = j - buf[1]; 121656723Sshin j = -imax(imin(mouse->u.data.y, 255), -256); 121756723Sshin buf[2] = j >> 1; 121856723Sshin buf[4] = j - buf[2]; 121956723Sshin for (j = 0; j < MOUSE_MSC_PACKETSIZE; j++) 122056723Sshin (*linesw[(MOUSE_TTY)->t_line].l_rint)(buf[j],MOUSE_TTY); 122156723Sshin if (mouse_level >= 1) { /* extended part */ 122256723Sshin j = imax(imin(mouse->u.data.z, 127), -128); 122356723Sshin buf[5] = (j >> 1) & 0x7f; 122456723Sshin buf[6] = (j - (j >> 1)) & 0x7f; 122556723Sshin /* buttons 4-10 */ 122656723Sshin buf[7] = (~mouse_status.button >> 3) & 0x7f; 122756723Sshin for (j = MOUSE_MSC_PACKETSIZE; 122856723Sshin j < MOUSE_SYS_PACKETSIZE; j++) 122956723Sshin (*linesw[(MOUSE_TTY)->t_line].l_rint)(buf[j],MOUSE_TTY); 123056723Sshin } 123162587Sitojun } 123256723Sshin 123356723Sshin if (cur_console->mouse_signal) { 123456723Sshin cur_console->mouse_buttons = mouse->u.data.buttons; 123556723Sshin /* has controlling process died? */ 123656723Sshin if (cur_console->mouse_proc && 123756723Sshin (cur_console->mouse_proc != pfind(cur_console->mouse_pid))){ 123856723Sshin cur_console->mouse_signal = 0; 123956723Sshin cur_console->mouse_proc = NULL; 124056723Sshin cur_console->mouse_pid = 0; 124156723Sshin } 124256723Sshin else 124356723Sshin psignal(cur_console->mouse_proc, cur_console->mouse_signal); 124456723Sshin } 124556723Sshin else if (mouse->operation == MOUSE_ACTION) { 124656723Sshin /* process button presses */ 124756723Sshin if ((cur_console->mouse_buttons ^ mouse->u.data.buttons) && 124856723Sshin !(cur_console->status & UNKNOWN_MODE)) { 124956723Sshin cur_console->mouse_buttons = mouse->u.data.buttons; 125056723Sshin if (cur_console->mouse_buttons & MOUSE_BUTTON1DOWN) 125156723Sshin mouse_cut_start(cur_console); 125256723Sshin else 125356723Sshin mouse_cut_end(cur_console); 125462587Sitojun if (cur_console->mouse_buttons & MOUSE_BUTTON2DOWN || 125562587Sitojun cur_console->mouse_buttons & MOUSE_BUTTON3DOWN) 125662587Sitojun mouse_paste(cur_console); 125762587Sitojun } 125862587Sitojun } 125962587Sitojun 126056723Sshin if (mouse->u.data.x != 0 || mouse->u.data.y != 0) { 126156723Sshin cur_console->mouse_xpos += mouse->u.data.x; 126256723Sshin cur_console->mouse_ypos += mouse->u.data.y; 126356723Sshin set_mouse_pos(cur_console); 126456723Sshin } 126556723Sshin 126656723Sshin break; 126756723Sshin 126856723Sshin case MOUSE_BUTTON_EVENT: 126956723Sshin if ((mouse->u.event.id & MOUSE_BUTTONS) == 0) 127056723Sshin return EINVAL; 127156723Sshin if (mouse->u.event.value < 0) 127256723Sshin return EINVAL; 127356723Sshin 127456723Sshin if (mouse->u.event.value > 0) { 127556723Sshin cur_console->mouse_buttons |= mouse->u.event.id; 127656723Sshin mouse_status.button |= mouse->u.event.id; 127756723Sshin } else { 127856723Sshin cur_console->mouse_buttons &= ~mouse->u.event.id; 127956723Sshin mouse_status.button &= ~mouse->u.event.id; 128056723Sshin } 128156723Sshin mouse_status.flags |= 128262587Sitojun ((mouse->u.data.x || mouse->u.data.y || mouse->u.data.z) ? 128362587Sitojun MOUSE_POSCHANGED : 0) 128462587Sitojun | (mouse_status.obutton ^ mouse_status.button); 128562587Sitojun 128662587Sitojun if (cur_console->status & MOUSE_ENABLED) 128762587Sitojun cur_console->status |= MOUSE_VISIBLE; 128862587Sitojun 128962587Sitojun if ((MOUSE_TTY)->t_state & TS_ISOPEN) { 129062587Sitojun u_char buf[8]; 129162587Sitojun int i; 129256723Sshin 129362587Sitojun buf[0] = MOUSE_MSC_SYNC 129462587Sitojun | butmap[mouse_status.button & MOUSE_STDBUTTONS]; 129562587Sitojun buf[7] = (~mouse_status.button >> 3) & 0x7f; 129662587Sitojun buf[1] = buf[2] = buf[3] = buf[4] = buf[5] = buf[6] = 0; 129762587Sitojun for (i = 0; 129856723Sshin i < ((mouse_level >= 1) ? MOUSE_SYS_PACKETSIZE 129962587Sitojun : MOUSE_MSC_PACKETSIZE); i++) 130062587Sitojun (*linesw[(MOUSE_TTY)->t_line].l_rint)(buf[i],MOUSE_TTY); 130162587Sitojun } 130262587Sitojun 130362587Sitojun if (cur_console->mouse_signal) { 130462587Sitojun if (cur_console->mouse_proc && 130562587Sitojun (cur_console->mouse_proc != pfind(cur_console->mouse_pid))){ 130662587Sitojun cur_console->mouse_signal = 0; 130762587Sitojun cur_console->mouse_proc = NULL; 130862587Sitojun cur_console->mouse_pid = 0; 130962587Sitojun } 131062587Sitojun else 131162587Sitojun psignal(cur_console->mouse_proc, cur_console->mouse_signal); 131262587Sitojun break; 131362587Sitojun } 131462587Sitojun 131562587Sitojun if (cur_console->status & UNKNOWN_MODE) 131662587Sitojun break; 131762587Sitojun 131862587Sitojun switch (mouse->u.event.id) { 131962587Sitojun case MOUSE_BUTTON1DOWN: 132056723Sshin switch (mouse->u.event.value % 4) { 132162587Sitojun case 0: /* up */ 132262587Sitojun mouse_cut_end(cur_console); 132362587Sitojun break; 132462587Sitojun case 1: 132562587Sitojun mouse_cut_start(cur_console); 132662587Sitojun break; 132756723Sshin case 2: 132862587Sitojun mouse_cut_word(cur_console); 132962587Sitojun break; 133062587Sitojun case 3: 133162587Sitojun mouse_cut_line(cur_console); 133262587Sitojun break; 133356723Sshin } 133462587Sitojun break; 133562587Sitojun case MOUSE_BUTTON2DOWN: 133662587Sitojun switch (mouse->u.event.value) { 133762587Sitojun case 0: /* up */ 133862587Sitojun break; 133962587Sitojun default: 134062587Sitojun mouse_paste(cur_console); 134162587Sitojun break; 134262587Sitojun } 134356723Sshin break; 134462587Sitojun case MOUSE_BUTTON3DOWN: 134562587Sitojun switch (mouse->u.event.value) { 134656723Sshin case 0: /* up */ 134762587Sitojun if (!(cur_console->mouse_buttons & MOUSE_BUTTON1DOWN)) 134856723Sshin mouse_cut_end(cur_console); 134962587Sitojun break; 135056723Sshin default: 135162587Sitojun mouse_cut_extend(cur_console); 135262587Sitojun break; 135356723Sshin } 135462587Sitojun break; 135562587Sitojun } 135662587Sitojun break; 135762587Sitojun 135856723Sshin default: 135956723Sshin return EINVAL; 136056723Sshin } 136156723Sshin /* make screensaver happy */ 136256723Sshin scrn_time_stamp = mono_time.tv_sec; 136356723Sshin return 0; 136456723Sshin } 136556723Sshin 136656723Sshin /* MOUSE_XXX: /dev/sysmouse ioctls */ 136756723Sshin case MOUSE_GETHWINFO: /* get device information */ 136856723Sshin { 136956723Sshin mousehw_t *hw = (mousehw_t *)data; 137056723Sshin 137156723Sshin if (tp != MOUSE_TTY) 137256723Sshin return ENOTTY; 137356723Sshin hw->buttons = 10; /* XXX unknown */ 137456723Sshin hw->iftype = MOUSE_IF_SYSMOUSE; 137556723Sshin hw->type = MOUSE_MOUSE; 137656723Sshin hw->model = MOUSE_MODEL_GENERIC; 137756723Sshin hw->hwid = 0; 137856723Sshin return 0; 137962587Sitojun } 138062587Sitojun 138162587Sitojun case MOUSE_GETMODE: /* get protocol/mode */ 138262587Sitojun { 138362587Sitojun mousemode_t *mode = (mousemode_t *)data; 138462587Sitojun 138562587Sitojun if (tp != MOUSE_TTY) 138662587Sitojun return ENOTTY; 138762587Sitojun mode->level = mouse_level; 138862587Sitojun switch (mode->level) { 138962587Sitojun case 0: 139062587Sitojun /* at this level, sysmouse emulates MouseSystems protocol */ 139162587Sitojun mode->protocol = MOUSE_PROTO_MSC; 139262587Sitojun mode->rate = -1; /* unknown */ 139362587Sitojun mode->resolution = -1; /* unknown */ 139462587Sitojun mode->accelfactor = 0; /* disabled */ 139562587Sitojun mode->packetsize = MOUSE_MSC_PACKETSIZE; 139662587Sitojun mode->syncmask[0] = MOUSE_MSC_SYNCMASK; 139762587Sitojun mode->syncmask[1] = MOUSE_MSC_SYNC; 139856723Sshin break; 139956723Sshin 140056723Sshin case 1: 140156723Sshin /* at this level, sysmouse uses its own protocol */ 140256723Sshin mode->protocol = MOUSE_PROTO_SYSMOUSE; 140356723Sshin mode->rate = -1; 140456723Sshin mode->resolution = -1; 140556723Sshin mode->accelfactor = 0; 140656723Sshin mode->packetsize = MOUSE_SYS_PACKETSIZE; 140756723Sshin mode->syncmask[0] = MOUSE_SYS_SYNCMASK; 140856723Sshin mode->syncmask[1] = MOUSE_SYS_SYNC; 140956723Sshin break; 141056723Sshin } 141156723Sshin return 0; 141256723Sshin } 141356723Sshin 141456723Sshin case MOUSE_SETMODE: /* set protocol/mode */ 141556723Sshin { 141656723Sshin mousemode_t *mode = (mousemode_t *)data; 141756723Sshin 141856723Sshin if (tp != MOUSE_TTY) 141956723Sshin return ENOTTY; 142056723Sshin if ((mode->level < 0) || (mode->level > 1)) 142156723Sshin return EINVAL; 142256723Sshin mouse_level = mode->level; 142356723Sshin return 0; 142456723Sshin } 142556723Sshin 142656723Sshin case MOUSE_GETLEVEL: /* get operation level */ 142756723Sshin if (tp != MOUSE_TTY) 142856723Sshin return ENOTTY; 142956723Sshin *(int *)data = mouse_level; 143056723Sshin return 0; 143156723Sshin 143256723Sshin case MOUSE_SETLEVEL: /* set operation level */ 143356723Sshin if (tp != MOUSE_TTY) 143456723Sshin return ENOTTY; 143556723Sshin if ((*(int *)data < 0) || (*(int *)data > 1)) 143656723Sshin return EINVAL; 143756723Sshin mouse_level = *(int *)data; 143856723Sshin return 0; 143956723Sshin 144056723Sshin case MOUSE_GETSTATUS: /* get accumulated mouse events */ 144156723Sshin if (tp != MOUSE_TTY) 144256723Sshin return ENOTTY; 144356723Sshin s = spltty(); 144456723Sshin *(mousestatus_t *)data = mouse_status; 144556723Sshin mouse_status.flags = 0; 144656723Sshin mouse_status.obutton = mouse_status.button; 144756723Sshin mouse_status.dx = 0; 144856723Sshin mouse_status.dy = 0; 144956723Sshin mouse_status.dz = 0; 145056723Sshin splx(s); 145156723Sshin return 0; 145256723Sshin 145356723Sshin#if notyet 145456723Sshin case MOUSE_GETVARS: /* get internal mouse variables */ 145556723Sshin case MOUSE_SETVARS: /* set internal mouse variables */ 145656723Sshin if (tp != MOUSE_TTY) 145756723Sshin return ENOTTY; 145856723Sshin return ENODEV; 145956723Sshin#endif 146056723Sshin 146156723Sshin case MOUSE_READSTATE: /* read status from the device */ 146256723Sshin case MOUSE_READDATA: /* read data from the device */ 146356723Sshin if (tp != MOUSE_TTY) 146456723Sshin return ENOTTY; 146556723Sshin return ENODEV; 146656723Sshin 146756723Sshin case CONS_GETINFO: /* get current (virtual) console info */ 146856723Sshin { 146956723Sshin vid_info_t *ptr = (vid_info_t*)data; 147056723Sshin if (ptr->size == sizeof(struct vid_info)) { 147156723Sshin ptr->m_num = get_scr_num(); 147256723Sshin ptr->mv_col = scp->xpos; 147356723Sshin ptr->mv_row = scp->ypos; 147456723Sshin ptr->mv_csz = scp->xsize; 147556723Sshin ptr->mv_rsz = scp->ysize; 147656723Sshin ptr->mv_norm.fore = (scp->term.std_color & 0x0f00)>>8; 147756723Sshin ptr->mv_norm.back = (scp->term.std_color & 0xf000)>>12; 147856723Sshin ptr->mv_rev.fore = (scp->term.rev_color & 0x0f00)>>8; 147956723Sshin ptr->mv_rev.back = (scp->term.rev_color & 0xf000)>>12; 148056723Sshin ptr->mv_grfc.fore = 0; /* not supported */ 148156723Sshin ptr->mv_grfc.back = 0; /* not supported */ 148256723Sshin ptr->mv_ovscan = scp->border; 148356723Sshin ptr->mk_keylock = scp->status & LOCK_KEY_MASK; 148456723Sshin return 0; 148556723Sshin } 148656723Sshin return EINVAL; 148756723Sshin } 148856723Sshin 148956723Sshin case CONS_GETVERS: /* get version number */ 149056723Sshin *(int*)data = 0x200; /* version 2.0 */ 149156723Sshin return 0; 149256723Sshin 149356723Sshin /* VGA TEXT MODES */ 149456723Sshin case SW_VGA_C40x25: 149556723Sshin case SW_VGA_C80x25: case SW_VGA_M80x25: 149656723Sshin case SW_VGA_C80x30: case SW_VGA_M80x30: 149756723Sshin case SW_VGA_C80x50: case SW_VGA_M80x50: 149856723Sshin case SW_VGA_C80x60: case SW_VGA_M80x60: 149956723Sshin case SW_B40x25: case SW_C40x25: 150056723Sshin case SW_B80x25: case SW_C80x25: 150156723Sshin case SW_ENH_B40x25: case SW_ENH_C40x25: 150256723Sshin case SW_ENH_B80x25: case SW_ENH_C80x25: 150356723Sshin case SW_ENH_B80x43: case SW_ENH_C80x43: 150456723Sshin case SW_EGAMONO80x25: 150556723Sshin 150656723Sshin if (!crtc_vga) 150756723Sshin return ENODEV; 150856723Sshin mp = get_mode_param(scp, cmd & 0xff); 150956723Sshin if (mp == NULL) 151056723Sshin return ENODEV; 151156723Sshin 151256723Sshin if (scp->history != NULL) 151356723Sshin i = imax(scp->history_size / scp->xsize 151456723Sshin - imax(SC_HISTORY_SIZE, scp->ysize), 0); 151556723Sshin else 151656723Sshin i = 0; 151756723Sshin switch (cmd & 0xff) { 151856723Sshin case M_VGA_C80x60: case M_VGA_M80x60: 151956723Sshin if (!(fonts_loaded & FONT_8)) 152056723Sshin return EINVAL; 152156723Sshin scp->xsize = 80; 152256723Sshin scp->ysize = 60; 152356723Sshin break; 152456723Sshin case M_VGA_C80x50: case M_VGA_M80x50: 152556723Sshin if (!(fonts_loaded & FONT_8)) 152656723Sshin return EINVAL; 152756723Sshin scp->xsize = 80; 152856723Sshin scp->ysize = 50; 152956723Sshin break; 153056723Sshin case M_ENH_B80x43: case M_ENH_C80x43: 153156723Sshin if (!(fonts_loaded & FONT_8)) 153256723Sshin return EINVAL; 153356723Sshin scp->xsize = 80; 153456723Sshin scp->ysize = 43; 153556723Sshin break; 153656723Sshin case M_VGA_C80x30: case M_VGA_M80x30: 153756723Sshin scp->xsize = 80; 153856723Sshin scp->ysize = 30; 153956723Sshin break; 154056723Sshin case M_ENH_C40x25: case M_ENH_B40x25: 154156723Sshin case M_ENH_C80x25: case M_ENH_B80x25: 154256723Sshin case M_EGAMONO80x25: 154356723Sshin if (!(fonts_loaded & FONT_14)) 154456723Sshin return EINVAL; 154556723Sshin /* FALL THROUGH */ 154656723Sshin default: 154756723Sshin if ((cmd & 0xff) > M_VGA_CG320) 154856723Sshin return EINVAL; 154956723Sshin scp->xsize = mp[0]; 155056723Sshin scp->ysize = mp[1] + rows_offset; 155156723Sshin break; 155256723Sshin } 155356723Sshin scp->mode = cmd & 0xff; 155456723Sshin free(scp->scr_buf, M_DEVBUF); 155556723Sshin scp->scr_buf = (u_short *) 155656723Sshin malloc(scp->xsize*scp->ysize*sizeof(u_short), M_DEVBUF, M_WAITOK); 155756723Sshin scp->cursor_pos = scp->cursor_oldpos = 155856723Sshin scp->scr_buf + scp->xpos + scp->ypos * scp->xsize; 155956723Sshin scp->mouse_pos = scp->mouse_oldpos = 156056723Sshin scp->scr_buf + ((scp->mouse_ypos/scp->font_size)*scp->xsize + 156156723Sshin scp->mouse_xpos/8); 156256723Sshin free(cut_buffer, M_DEVBUF); 156356723Sshin cut_buffer = (char *)malloc(scp->xsize*scp->ysize, M_DEVBUF, M_NOWAIT); 156456723Sshin cut_buffer[0] = 0x00; 156556723Sshin usp = scp->history; 156656723Sshin scp->history = NULL; 156756723Sshin if (usp != NULL) { 156856723Sshin free(usp, M_DEVBUF); 156956723Sshin extra_history_size += i; 157056723Sshin } 157156723Sshin scp->history_size = imax(SC_HISTORY_SIZE, scp->ysize) * scp->xsize; 157256723Sshin usp = (u_short *)malloc(scp->history_size * sizeof(u_short), 157356723Sshin M_DEVBUF, M_NOWAIT); 157456723Sshin if (usp != NULL) 157556723Sshin bzero(usp, scp->history_size * sizeof(u_short)); 157656723Sshin scp->history_head = scp->history_pos = usp; 157756723Sshin scp->history = usp; 157856723Sshin if (scp == cur_console) 157956723Sshin set_mode(scp); 158056723Sshin scp->status &= ~UNKNOWN_MODE; 158156723Sshin clear_screen(scp); 158256723Sshin 158356723Sshin if (tp->t_winsize.ws_col != scp->xsize 158456723Sshin || tp->t_winsize.ws_row != scp->ysize) { 158556723Sshin tp->t_winsize.ws_col = scp->xsize; 158656723Sshin tp->t_winsize.ws_row = scp->ysize; 158756723Sshin pgsignal(tp->t_pgrp, SIGWINCH, 1); 158856723Sshin } 158956723Sshin return 0; 159056723Sshin 159156723Sshin /* GRAPHICS MODES */ 159256723Sshin case SW_BG320: case SW_BG640: 159356723Sshin case SW_CG320: case SW_CG320_D: case SW_CG640_E: 159456723Sshin case SW_CG640x350: case SW_ENH_CG640: 159556723Sshin case SW_BG640x480: case SW_CG640x480: case SW_VGA_CG320: 159656723Sshin 159756723Sshin if (!crtc_vga) 159856723Sshin return ENODEV; 159956723Sshin mp = get_mode_param(scp, cmd & 0xff); 160056723Sshin if (mp == NULL) 160156723Sshin return ENODEV; 160256723Sshin 160356723Sshin scp->mode = cmd & 0xFF; 160456723Sshin scp->xpixel = mp[0] * 8; 160556723Sshin scp->ypixel = (mp[1] + rows_offset) * mp[2]; 160656723Sshin if (scp == cur_console) 160756723Sshin set_mode(scp); 160856723Sshin scp->status |= UNKNOWN_MODE; /* graphics mode */ 160956723Sshin /* clear_graphics();*/ 161056723Sshin 161156723Sshin if (tp->t_winsize.ws_xpixel != scp->xpixel 161256723Sshin || tp->t_winsize.ws_ypixel != scp->ypixel) { 161356723Sshin tp->t_winsize.ws_xpixel = scp->xpixel; 161456723Sshin tp->t_winsize.ws_ypixel = scp->ypixel; 161556723Sshin pgsignal(tp->t_pgrp, SIGWINCH, 1); 161656723Sshin } 161756723Sshin return 0; 161856723Sshin 161956723Sshin case SW_VGA_MODEX: 162056723Sshin if (!crtc_vga) 162156723Sshin return ENODEV; 162256723Sshin mp = get_mode_param(scp, cmd & 0xff); 162356723Sshin if (mp == NULL) 162456723Sshin return ENODEV; 162556723Sshin 162656723Sshin scp->mode = cmd & 0xFF; 162756723Sshin if (scp == cur_console) 162862587Sitojun set_mode(scp); 162956723Sshin scp->status |= UNKNOWN_MODE; /* graphics mode */ 163056723Sshin /* clear_graphics();*/ 163156723Sshin scp->xpixel = 320; 163256723Sshin scp->ypixel = 240; 163356723Sshin if (tp->t_winsize.ws_xpixel != scp->xpixel 163456723Sshin || tp->t_winsize.ws_ypixel != scp->ypixel) { 163562587Sitojun tp->t_winsize.ws_xpixel = scp->xpixel; 163662587Sitojun tp->t_winsize.ws_ypixel = scp->ypixel; 163762587Sitojun pgsignal(tp->t_pgrp, SIGWINCH, 1); 163862587Sitojun } 163962587Sitojun return 0; 164062587Sitojun 164162587Sitojun case VT_SETMODE: /* set screen switcher mode */ 164256723Sshin { 164362587Sitojun struct vt_mode *mode; 164456723Sshin 164556723Sshin mode = (struct vt_mode *)data; 164656723Sshin if (ISSIGVALID(mode->relsig) && ISSIGVALID(mode->acqsig) && 164756723Sshin ISSIGVALID(mode->frsig)) { 164856723Sshin bcopy(data, &scp->smode, sizeof(struct vt_mode)); 164956723Sshin if (scp->smode.mode == VT_PROCESS) { 165056723Sshin scp->proc = p; 165156723Sshin scp->pid = scp->proc->p_pid; 165256723Sshin } 165356723Sshin return 0; 165456723Sshin } else 165556723Sshin return EINVAL; 165656723Sshin } 165756723Sshin 165856723Sshin case VT_GETMODE: /* get screen switcher mode */ 165956723Sshin bcopy(&scp->smode, data, sizeof(struct vt_mode)); 166056723Sshin return 0; 166156723Sshin 166256723Sshin case VT_RELDISP: /* screen switcher ioctl */ 166356723Sshin switch(*data) { 166456723Sshin case VT_FALSE: /* user refuses to release screen, abort */ 166556723Sshin if (scp == old_scp && (scp->status & SWITCH_WAIT_REL)) { 166656723Sshin old_scp->status &= ~SWITCH_WAIT_REL; 166756723Sshin switch_in_progress = FALSE; 166856723Sshin return 0; 166956723Sshin } 167056723Sshin return EINVAL; 167156723Sshin 167256723Sshin case VT_TRUE: /* user has released screen, go on */ 167356723Sshin if (scp == old_scp && (scp->status & SWITCH_WAIT_REL)) { 167456723Sshin scp->status &= ~SWITCH_WAIT_REL; 167556723Sshin exchange_scr(); 167656723Sshin if (new_scp->smode.mode == VT_PROCESS) { 167756723Sshin new_scp->status |= SWITCH_WAIT_ACQ; 167856723Sshin psignal(new_scp->proc, new_scp->smode.acqsig); 167956723Sshin } 168056723Sshin else 168156723Sshin switch_in_progress = FALSE; 168256723Sshin return 0; 168356723Sshin } 168456723Sshin return EINVAL; 168556723Sshin 168656723Sshin case VT_ACKACQ: /* acquire acknowledged, switch completed */ 168756723Sshin if (scp == new_scp && (scp->status & SWITCH_WAIT_ACQ)) { 168856723Sshin scp->status &= ~SWITCH_WAIT_ACQ; 168956723Sshin switch_in_progress = FALSE; 169056723Sshin return 0; 169156723Sshin } 169256723Sshin return EINVAL; 169356723Sshin 169462587Sitojun default: 169556723Sshin return EINVAL; 169656723Sshin } 169756723Sshin /* NOT REACHED */ 169856723Sshin 169956723Sshin case VT_OPENQRY: /* return free virtual console */ 170056723Sshin for (i = 0; i < MAXCONS; i++) { 170156723Sshin tp = VIRTUAL_TTY(i); 170256723Sshin if (!(tp->t_state & TS_ISOPEN)) { 170356723Sshin *data = i + 1; 170456723Sshin return 0; 170556723Sshin } 170656723Sshin } 170762587Sitojun return EINVAL; 170856723Sshin 170962587Sitojun case VT_ACTIVATE: /* switch to screen *data */ 171056723Sshin return switch_scr(scp, (*data) - 1); 171156723Sshin 171256723Sshin case VT_WAITACTIVE: /* wait for switch to occur */ 171356723Sshin if (*data > MAXCONS || *data < 0) 171456723Sshin return EINVAL; 171556723Sshin if (minor(dev) == (*data) - 1) 171656723Sshin return 0; 171756723Sshin if (*data == 0) { 171856723Sshin if (scp == cur_console) 171956723Sshin return 0; 172056723Sshin } 172156723Sshin else 172256723Sshin scp = console[(*data) - 1]; 172356723Sshin while ((error=tsleep((caddr_t)&scp->smode, PZERO|PCATCH, 172456723Sshin "waitvt", 0)) == ERESTART) ; 172556723Sshin return error; 172656723Sshin 172756723Sshin case VT_GETACTIVE: 172862587Sitojun *data = get_scr_num()+1; 172956723Sshin return 0; 173062587Sitojun 173156723Sshin case KDENABIO: /* allow io operations */ 173256723Sshin error = suser(p->p_ucred, &p->p_acflag); 173356723Sshin if (error != 0) 173456723Sshin return error; 173556723Sshin if (securelevel > 0) 173656723Sshin return EPERM; 173756723Sshin p->p_md.md_regs->tf_eflags |= PSL_IOPL; 173856723Sshin return 0; 173962587Sitojun 174056723Sshin case KDDISABIO: /* disallow io operations (default) */ 174156723Sshin p->p_md.md_regs->tf_eflags &= ~PSL_IOPL; 174256723Sshin return 0; 174356723Sshin 174456723Sshin case KDSETMODE: /* set current mode of this (virtual) console */ 174556723Sshin switch (*data) { 174656723Sshin case KD_TEXT: /* switch to TEXT (known) mode */ 174756723Sshin /* restore fonts & palette ! */ 174856723Sshin if (crtc_vga) { 174956723Sshin if (fonts_loaded & FONT_8) 175056723Sshin copy_font(LOAD, FONT_8, font_8); 175156723Sshin if (fonts_loaded & FONT_14) 175256723Sshin copy_font(LOAD, FONT_14, font_14); 175362587Sitojun if (fonts_loaded & FONT_16) 175456723Sshin copy_font(LOAD, FONT_16, font_16); 175556723Sshin load_palette(palette); 175656723Sshin } 175756723Sshin 175856723Sshin /* move hardware cursor out of the way */ 175956723Sshin outb(crtc_addr, 14); 176056723Sshin outb(crtc_addr + 1, 0xff); 176156723Sshin outb(crtc_addr, 15); 176256723Sshin outb(crtc_addr + 1, 0xff); 176356723Sshin 176456723Sshin /* FALL THROUGH */ 176556723Sshin 176656723Sshin case KD_TEXT1: /* switch to TEXT (known) mode */ 176762587Sitojun /* no restore fonts & palette */ 176856723Sshin if (crtc_vga) 176956723Sshin set_mode(scp); 177056723Sshin scp->status &= ~UNKNOWN_MODE; 177156723Sshin clear_screen(scp); 177256723Sshin return 0; 177356723Sshin 177456723Sshin case KD_GRAPHICS: /* switch to GRAPHICS (unknown) mode */ 177556723Sshin scp->status |= UNKNOWN_MODE; 177656723Sshin return 0; 177756723Sshin default: 177856723Sshin return EINVAL; 177956723Sshin } 178056723Sshin /* NOT REACHED */ 178156723Sshin 178256723Sshin case KDGETMODE: /* get current mode of this (virtual) console */ 178356723Sshin *data = (scp->status & UNKNOWN_MODE) ? KD_GRAPHICS : KD_TEXT; 178462587Sitojun return 0; 178562587Sitojun 178656723Sshin case KDSBORDER: /* set border color of this (virtual) console */ 178756723Sshin scp->border = *data; 178856723Sshin if (scp == cur_console) 178956723Sshin set_border(scp->border); 179056723Sshin return 0; 179156723Sshin 179256723Sshin case KDSKBSTATE: /* set keyboard state (locks) */ 179356723Sshin if (*data >= 0 && *data <= LOCK_KEY_MASK) { 179456723Sshin scp->status &= ~LOCK_KEY_MASK; 179556723Sshin scp->status |= *data; 179656723Sshin if (scp == cur_console) 179756723Sshin update_leds(scp->status); 179856723Sshin return 0; 179956723Sshin } 1800 return EINVAL; 1801 1802 case KDGKBSTATE: /* get keyboard state (locks) */ 1803 *data = scp->status & LOCK_KEY_MASK; 1804 return 0; 1805 1806 case KDSETRAD: /* set keyboard repeat & delay rates */ 1807 if (*data & 0x80) 1808 return EINVAL; 1809 if (sc_kbdc != NULL) 1810 set_keyboard(KBDC_SET_TYPEMATIC, *data); 1811 return 0; 1812 1813 case KDSKBMODE: /* set keyboard mode */ 1814 switch (*data) { 1815 case K_RAW: /* switch to RAW scancode mode */ 1816 scp->status &= ~KBD_CODE_MODE; 1817 scp->status |= KBD_RAW_MODE; 1818 return 0; 1819 1820 case K_CODE: /* switch to CODE mode */ 1821 scp->status &= ~KBD_RAW_MODE; 1822 scp->status |= KBD_CODE_MODE; 1823 return 0; 1824 1825 case K_XLATE: /* switch to XLT ascii mode */ 1826 if (scp == cur_console && scp->status & KBD_RAW_MODE) 1827 shfts = ctls = alts = agrs = metas = accents = 0; 1828 scp->status &= ~(KBD_RAW_MODE | KBD_CODE_MODE); 1829 return 0; 1830 default: 1831 return EINVAL; 1832 } 1833 /* NOT REACHED */ 1834 1835 case KDGKBMODE: /* get keyboard mode */ 1836 *data = (scp->status & KBD_RAW_MODE) ? K_RAW : 1837 ((scp->status & KBD_CODE_MODE) ? K_CODE : K_XLATE); 1838 return 0; 1839 1840 case KDMKTONE: /* sound the bell */ 1841 if (*(int*)data) 1842 do_bell(scp, (*(int*)data)&0xffff, 1843 (((*(int*)data)>>16)&0xffff)*hz/1000); 1844 else 1845 do_bell(scp, scp->bell_pitch, scp->bell_duration); 1846 return 0; 1847 1848 case KIOCSOUND: /* make tone (*data) hz */ 1849 if (scp == cur_console) { 1850 if (*(int*)data) { 1851 int pitch = timer_freq / *(int*)data; 1852 1853 /* set command for counter 2, 2 byte write */ 1854 if (acquire_timer2(TIMER_16BIT|TIMER_SQWAVE)) 1855 return EBUSY; 1856 1857 /* set pitch */ 1858 outb(TIMER_CNTR2, pitch); 1859 outb(TIMER_CNTR2, (pitch>>8)); 1860 1861 /* enable counter 2 output to speaker */ 1862 outb(IO_PPI, inb(IO_PPI) | 3); 1863 } 1864 else { 1865 /* disable counter 2 output to speaker */ 1866 outb(IO_PPI, inb(IO_PPI) & 0xFC); 1867 release_timer2(); 1868 } 1869 } 1870 return 0; 1871 1872 case KDGKBTYPE: /* get keyboard type */ 1873 *data = 0; /* type not known (yet) */ 1874 return 0; 1875 1876 case KDSETLED: /* set keyboard LED status */ 1877 if (*data >= 0 && *data <= LED_MASK) { 1878 scp->status &= ~LED_MASK; 1879 scp->status |= *data; 1880 if (scp == cur_console) 1881 update_leds(scp->status); 1882 return 0; 1883 } 1884 return EINVAL; 1885 1886 case KDGETLED: /* get keyboard LED status */ 1887 *data = scp->status & LED_MASK; 1888 return 0; 1889 1890 case GETFKEY: /* get functionkey string */ 1891 if (*(u_short*)data < n_fkey_tab) { 1892 fkeyarg_t *ptr = (fkeyarg_t*)data; 1893 bcopy(&fkey_tab[ptr->keynum].str, ptr->keydef, 1894 fkey_tab[ptr->keynum].len); 1895 ptr->flen = fkey_tab[ptr->keynum].len; 1896 return 0; 1897 } 1898 else 1899 return EINVAL; 1900 1901 case SETFKEY: /* set functionkey string */ 1902 if (*(u_short*)data < n_fkey_tab) { 1903 fkeyarg_t *ptr = (fkeyarg_t*)data; 1904 bcopy(ptr->keydef, &fkey_tab[ptr->keynum].str, 1905 min(ptr->flen, MAXFK)); 1906 fkey_tab[ptr->keynum].len = min(ptr->flen, MAXFK); 1907 return 0; 1908 } 1909 else 1910 return EINVAL; 1911 1912 case GIO_SCRNMAP: /* get output translation table */ 1913 bcopy(&scr_map, data, sizeof(scr_map)); 1914 return 0; 1915 1916 case PIO_SCRNMAP: /* set output translation table */ 1917 bcopy(data, &scr_map, sizeof(scr_map)); 1918 for (i=0; i<sizeof(scr_map); i++) 1919 scr_rmap[scr_map[i]] = i; 1920 return 0; 1921 1922 case GIO_KEYMAP: /* get keyboard translation table */ 1923 bcopy(&key_map, data, sizeof(key_map)); 1924 return 0; 1925 1926 case PIO_KEYMAP: /* set keyboard translation table */ 1927 accents = 0; 1928 bzero(&accent_map, sizeof(accent_map)); 1929 bcopy(data, &key_map, sizeof(key_map)); 1930 return 0; 1931 1932 case GIO_DEADKEYMAP: /* get accent key translation table */ 1933 bcopy(&accent_map, data, sizeof(accent_map)); 1934 return 0; 1935 1936 case PIO_DEADKEYMAP: /* set accent key translation table */ 1937 accents = 0; 1938 bcopy(data, &accent_map, sizeof(accent_map)); 1939 return 0; 1940 1941 case PIO_FONT8x8: /* set 8x8 dot font */ 1942 if (!crtc_vga) 1943 return ENXIO; 1944 bcopy(data, font_8, 8*256); 1945 fonts_loaded |= FONT_8; 1946 if (!(cur_console->status & UNKNOWN_MODE)) { 1947 copy_font(LOAD, FONT_8, font_8); 1948 if (flags & CHAR_CURSOR) 1949 set_destructive_cursor(cur_console); 1950 } 1951 return 0; 1952 1953 case GIO_FONT8x8: /* get 8x8 dot font */ 1954 if (!crtc_vga) 1955 return ENXIO; 1956 if (fonts_loaded & FONT_8) { 1957 bcopy(font_8, data, 8*256); 1958 return 0; 1959 } 1960 else 1961 return ENXIO; 1962 1963 case PIO_FONT8x14: /* set 8x14 dot font */ 1964 if (!crtc_vga) 1965 return ENXIO; 1966 bcopy(data, font_14, 14*256); 1967 fonts_loaded |= FONT_14; 1968 if (!(cur_console->status & UNKNOWN_MODE)) { 1969 copy_font(LOAD, FONT_14, font_14); 1970 if (flags & CHAR_CURSOR) 1971 set_destructive_cursor(cur_console); 1972 } 1973 return 0; 1974 1975 case GIO_FONT8x14: /* get 8x14 dot font */ 1976 if (!crtc_vga) 1977 return ENXIO; 1978 if (fonts_loaded & FONT_14) { 1979 bcopy(font_14, data, 14*256); 1980 return 0; 1981 } 1982 else 1983 return ENXIO; 1984 1985 case PIO_FONT8x16: /* set 8x16 dot font */ 1986 if (!crtc_vga) 1987 return ENXIO; 1988 bcopy(data, font_16, 16*256); 1989 fonts_loaded |= FONT_16; 1990 if (!(cur_console->status & UNKNOWN_MODE)) { 1991 copy_font(LOAD, FONT_16, font_16); 1992 if (flags & CHAR_CURSOR) 1993 set_destructive_cursor(cur_console); 1994 } 1995 return 0; 1996 1997 case GIO_FONT8x16: /* get 8x16 dot font */ 1998 if (!crtc_vga) 1999 return ENXIO; 2000 if (fonts_loaded & FONT_16) { 2001 bcopy(font_16, data, 16*256); 2002 return 0; 2003 } 2004 else 2005 return ENXIO; 2006 default: 2007 break; 2008 } 2009 2010 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); 2011 if (error != ENOIOCTL) 2012 return(error); 2013 error = ttioctl(tp, cmd, data, flag); 2014 if (error != ENOIOCTL) 2015 return(error); 2016 return(ENOTTY); 2017} 2018 2019static void 2020scstart(struct tty *tp) 2021{ 2022 struct clist *rbp; 2023 int s, len; 2024 u_char buf[PCBURST]; 2025 scr_stat *scp = get_scr_stat(tp->t_dev); 2026 2027 if (scp->status & SLKED || blink_in_progress) 2028 return; /* XXX who repeats the call when the above flags are cleared? */ 2029 s = spltty(); 2030 if (!(tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP))) { 2031 tp->t_state |= TS_BUSY; 2032 rbp = &tp->t_outq; 2033 while (rbp->c_cc) { 2034 len = q_to_b(rbp, buf, PCBURST); 2035 splx(s); 2036 ansi_put(scp, buf, len); 2037 s = spltty(); 2038 } 2039 tp->t_state &= ~TS_BUSY; 2040 ttwwakeup(tp); 2041 } 2042 splx(s); 2043} 2044 2045static void 2046scmousestart(struct tty *tp) 2047{ 2048 struct clist *rbp; 2049 int s; 2050 u_char buf[PCBURST]; 2051 2052 s = spltty(); 2053 if (!(tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP))) { 2054 tp->t_state |= TS_BUSY; 2055 rbp = &tp->t_outq; 2056 while (rbp->c_cc) { 2057 q_to_b(rbp, buf, PCBURST); 2058 } 2059 tp->t_state &= ~TS_BUSY; 2060 ttwwakeup(tp); 2061 } 2062 splx(s); 2063} 2064 2065void 2066sccnprobe(struct consdev *cp) 2067{ 2068 struct isa_device *dvp; 2069 2070 /* 2071 * Take control if we are the highest priority enabled display device. 2072 */ 2073 dvp = find_display(); 2074 if (dvp == NULL || dvp->id_driver != &scdriver) { 2075 cp->cn_pri = CN_DEAD; 2076 return; 2077 } 2078 2079 if (!scvidprobe(dvp->id_unit, dvp->id_flags)) { 2080 cp->cn_pri = CN_DEAD; 2081 return; 2082 } 2083 2084 /* initialize required fields */ 2085 cp->cn_dev = makedev(CDEV_MAJOR, SC_CONSOLE); 2086 cp->cn_pri = CN_INTERNAL; 2087 2088 sc_kbdc = kbdc_open(sc_port); 2089} 2090 2091void 2092sccninit(struct consdev *cp) 2093{ 2094 scinit(); 2095} 2096 2097void 2098sccnputc(dev_t dev, int c) 2099{ 2100 u_char buf[1]; 2101 int s; 2102 scr_stat *scp = console[0]; 2103 term_stat save = scp->term; 2104 2105 scp->term = kernel_console; 2106 current_default = &kernel_default; 2107 if (scp == cur_console && !(scp->status & UNKNOWN_MODE)) 2108 remove_cursor_image(scp); 2109 buf[0] = c; 2110 ansi_put(scp, buf, 1); 2111 kernel_console = scp->term; 2112 current_default = &user_default; 2113 scp->term = save; 2114 s = splclock(); 2115 if (scp == cur_console && !(scp->status & UNKNOWN_MODE)) { 2116 if (/* timer not running && */ (scp->start <= scp->end)) { 2117 sc_bcopy(scp->scr_buf + scp->start, Crtat + scp->start, 2118 (1 + scp->end - scp->start) * sizeof(u_short)); 2119 scp->start = scp->xsize * scp->ysize; 2120 scp->end = 0; 2121 } 2122 scp->cursor_oldpos = scp->cursor_pos; 2123 draw_cursor_image(scp); 2124 } 2125 splx(s); 2126} 2127 2128int 2129sccngetc(dev_t dev) 2130{ 2131 int s = spltty(); /* block scintr and scrn_timer while we poll */ 2132 int c; 2133 2134 /* 2135 * Stop the screen saver if necessary. 2136 * What if we have been running in the screen saver code... XXX 2137 */ 2138 if (scrn_blanked > 0) 2139 stop_scrn_saver(current_saver); 2140 2141 c = scgetc(SCGETC_CN); 2142 2143 /* make sure the screen saver won't be activated soon */ 2144 scrn_time_stamp = mono_time.tv_sec; 2145 splx(s); 2146 return(c); 2147} 2148 2149int 2150sccncheckc(dev_t dev) 2151{ 2152 int c, s; 2153 2154 s = spltty(); 2155 if (scrn_blanked > 0) 2156 stop_scrn_saver(current_saver); 2157 c = scgetc(SCGETC_CN | SCGETC_NONBLOCK); 2158 if (c != NOKEY) 2159 scrn_time_stamp = mono_time.tv_sec; 2160 splx(s); 2161 return(c == NOKEY ? -1 : c); /* c == -1 can't happen */ 2162} 2163 2164static scr_stat 2165*get_scr_stat(dev_t dev) 2166{ 2167 int unit = minor(dev); 2168 2169 if (unit == SC_CONSOLE) 2170 return console[0]; 2171 if (unit >= MAXCONS || unit < 0) 2172 return(NULL); 2173 return console[unit]; 2174} 2175 2176static int 2177get_scr_num() 2178{ 2179 int i = 0; 2180 2181 while ((i < MAXCONS) && (cur_console != console[i])) 2182 i++; 2183 return i < MAXCONS ? i : 0; 2184} 2185 2186static void 2187scrn_timer(void *arg) 2188{ 2189 scr_stat *scp = cur_console; 2190 int s = spltty(); 2191 2192 /* 2193 * With release 2.1 of the Xaccel server, the keyboard is left 2194 * hanging pretty often. Apparently an interrupt from the 2195 * keyboard is lost, and I don't know why (yet). 2196 * This ugly hack calls scintr if input is ready for the keyboard 2197 * and conveniently hides the problem. XXX 2198 */ 2199 /* Try removing anything stuck in the keyboard controller; whether 2200 * it's a keyboard scan code or mouse data. `scintr()' doesn't 2201 * read the mouse data directly, but `kbdio' routines will, as a 2202 * side effect. 2203 */ 2204 if (kbdc_lock(sc_kbdc, TRUE)) { 2205 /* 2206 * We have seen the lock flag is not set. Let's reset the flag early; 2207 * otherwise `update_led()' failes which may want the lock 2208 * during `scintr()'. 2209 */ 2210 kbdc_lock(sc_kbdc, FALSE); 2211 if (kbdc_data_ready(sc_kbdc)) 2212 scintr(0); 2213 } 2214 2215 /* should we just return ? */ 2216 if ((scp->status&UNKNOWN_MODE) || blink_in_progress || switch_in_progress) { 2217 timeout(scrn_timer, NULL, hz / 10); 2218 splx(s); 2219 return; 2220 } 2221 2222 /* should we stop the screen saver? */ 2223 if (mono_time.tv_sec <= scrn_time_stamp + scrn_blank_time) 2224 if (scrn_blanked > 0) 2225 stop_scrn_saver(current_saver); 2226 2227 if (scrn_blanked <= 0) { 2228 /* update screen image */ 2229 if (scp->start <= scp->end) { 2230 sc_bcopy(scp->scr_buf + scp->start, Crtat + scp->start, 2231 (1 + scp->end - scp->start) * sizeof(u_short)); 2232 } 2233 2234 /* update "pseudo" mouse pointer image */ 2235 if ((scp->status & MOUSE_VISIBLE) && crtc_vga) { 2236 /* did mouse move since last time ? */ 2237 if (scp->status & MOUSE_MOVED) { 2238 /* do we need to remove old mouse pointer image ? */ 2239 if (scp->mouse_cut_start != NULL || 2240 (scp->mouse_pos-scp->scr_buf) <= scp->start || 2241 (scp->mouse_pos+scp->xsize+1-scp->scr_buf) >= scp->end) { 2242 remove_mouse_image(scp); 2243 } 2244 scp->status &= ~MOUSE_MOVED; 2245 draw_mouse_image(scp); 2246 } 2247 else { 2248 /* mouse didn't move, has it been overwritten ? */ 2249 if ((scp->mouse_pos+scp->xsize+1-scp->scr_buf) >= scp->start && 2250 (scp->mouse_pos - scp->scr_buf) <= scp->end) { 2251 draw_mouse_image(scp); 2252 } 2253 } 2254 } 2255 2256 /* update cursor image */ 2257 if (scp->status & CURSOR_ENABLED) { 2258 /* did cursor move since last time ? */ 2259 if (scp->cursor_pos != scp->cursor_oldpos) { 2260 /* do we need to remove old cursor image ? */ 2261 if ((scp->cursor_oldpos - scp->scr_buf) < scp->start || 2262 ((scp->cursor_oldpos - scp->scr_buf) > scp->end)) { 2263 remove_cursor_image(scp); 2264 } 2265 scp->cursor_oldpos = scp->cursor_pos; 2266 draw_cursor_image(scp); 2267 } 2268 else { 2269 /* cursor didn't move, has it been overwritten ? */ 2270 if (scp->cursor_pos - scp->scr_buf >= scp->start && 2271 scp->cursor_pos - scp->scr_buf <= scp->end) { 2272 draw_cursor_image(scp); 2273 } else { 2274 /* if its a blinking cursor, we may have to update it */ 2275 if (flags & BLINK_CURSOR) 2276 draw_cursor_image(scp); 2277 } 2278 } 2279 blinkrate++; 2280 } 2281 2282 if (scp->mouse_cut_start != NULL) 2283 draw_cutmarking(scp); 2284 2285 scp->end = 0; 2286 scp->start = scp->xsize*scp->ysize; 2287 } 2288 2289 /* should we activate the screen saver? */ 2290 if ((scrn_blank_time != 0) 2291 && (mono_time.tv_sec > scrn_time_stamp + scrn_blank_time)) 2292 (*current_saver)(TRUE); 2293 2294 timeout(scrn_timer, NULL, hz / 25); 2295 splx(s); 2296} 2297 2298int 2299add_scrn_saver(void (*this_saver)(int)) 2300{ 2301 if (current_saver != none_saver) 2302 return EBUSY; 2303 current_saver = this_saver; 2304 return 0; 2305} 2306 2307int 2308remove_scrn_saver(void (*this_saver)(int)) 2309{ 2310 if (current_saver != this_saver) 2311 return EINVAL; 2312 2313 /* 2314 * In order to prevent `current_saver' from being called by 2315 * the timeout routine `scrn_timer()' while we manipulate 2316 * the saver list, we shall set `current_saver' to `none_saver' 2317 * before stopping the current saver, rather than blocking by `splXX()'. 2318 */ 2319 current_saver = none_saver; 2320 if (scrn_blanked > 0) 2321 stop_scrn_saver(this_saver); 2322 2323 return 0; 2324} 2325 2326static void 2327stop_scrn_saver(void (*saver)(int)) 2328{ 2329 (*saver)(FALSE); 2330 scrn_time_stamp = mono_time.tv_sec; 2331 mark_all(cur_console); 2332} 2333 2334static void 2335clear_screen(scr_stat *scp) 2336{ 2337 move_crsr(scp, 0, 0); 2338 scp->cursor_oldpos = scp->cursor_pos; 2339 fillw(scp->term.cur_color | scr_map[0x20], scp->scr_buf, 2340 scp->xsize * scp->ysize); 2341 mark_all(scp); 2342 remove_cutmarking(scp); 2343} 2344 2345static int 2346switch_scr(scr_stat *scp, u_int next_scr) 2347{ 2348 if (switch_in_progress && (cur_console->proc != pfind(cur_console->pid))) 2349 switch_in_progress = FALSE; 2350 2351 if (next_scr >= MAXCONS || switch_in_progress || 2352 (cur_console->smode.mode == VT_AUTO 2353 && cur_console->status & UNKNOWN_MODE)) { 2354 do_bell(scp, BELL_PITCH, BELL_DURATION); 2355 return EINVAL; 2356 } 2357 2358 /* is the wanted virtual console open ? */ 2359 if (next_scr) { 2360 struct tty *tp = VIRTUAL_TTY(next_scr); 2361 if (!(tp->t_state & TS_ISOPEN)) { 2362 do_bell(scp, BELL_PITCH, BELL_DURATION); 2363 return EINVAL; 2364 } 2365 } 2366 /* delay switch if actively updating screen */ 2367 if (write_in_progress || blink_in_progress) { 2368 delayed_next_scr = next_scr+1; 2369 return 0; 2370 } 2371 switch_in_progress = TRUE; 2372 old_scp = cur_console; 2373 new_scp = console[next_scr]; 2374 wakeup((caddr_t)&new_scp->smode); 2375 if (new_scp == old_scp) { 2376 switch_in_progress = FALSE; 2377 delayed_next_scr = FALSE; 2378 return 0; 2379 } 2380 2381 /* has controlling process died? */ 2382 if (old_scp->proc && (old_scp->proc != pfind(old_scp->pid))) 2383 old_scp->smode.mode = VT_AUTO; 2384 if (new_scp->proc && (new_scp->proc != pfind(new_scp->pid))) 2385 new_scp->smode.mode = VT_AUTO; 2386 2387 /* check the modes and switch appropriately */ 2388 if (old_scp->smode.mode == VT_PROCESS) { 2389 old_scp->status |= SWITCH_WAIT_REL; 2390 psignal(old_scp->proc, old_scp->smode.relsig); 2391 } 2392 else { 2393 exchange_scr(); 2394 if (new_scp->smode.mode == VT_PROCESS) { 2395 new_scp->status |= SWITCH_WAIT_ACQ; 2396 psignal(new_scp->proc, new_scp->smode.acqsig); 2397 } 2398 else 2399 switch_in_progress = FALSE; 2400 } 2401 return 0; 2402} 2403 2404static void 2405exchange_scr(void) 2406{ 2407 move_crsr(old_scp, old_scp->xpos, old_scp->ypos); 2408 cur_console = new_scp; 2409 if (old_scp->mode != new_scp->mode || (old_scp->status & UNKNOWN_MODE)){ 2410 if (crtc_vga) 2411 set_mode(new_scp); 2412 } 2413 move_crsr(new_scp, new_scp->xpos, new_scp->ypos); 2414 if (!(new_scp->status & UNKNOWN_MODE) && (flags & CHAR_CURSOR)) 2415 set_destructive_cursor(new_scp); 2416 if ((old_scp->status & UNKNOWN_MODE) && crtc_vga) 2417 load_palette(palette); 2418 if (old_scp->status & KBD_RAW_MODE || new_scp->status & KBD_RAW_MODE || 2419 old_scp->status & KBD_CODE_MODE || new_scp->status & KBD_CODE_MODE) 2420 shfts = ctls = alts = agrs = metas = accents = 0; 2421 set_border(new_scp->border); 2422 update_leds(new_scp->status); 2423 delayed_next_scr = FALSE; 2424 mark_all(new_scp); 2425} 2426 2427static void 2428scan_esc(scr_stat *scp, u_char c) 2429{ 2430 static u_char ansi_col[16] = 2431 {0, 4, 2, 6, 1, 5, 3, 7, 8, 12, 10, 14, 9, 13, 11, 15}; 2432 int i, n; 2433 u_short *src, *dst, count; 2434 2435 if (scp->term.esc == 1) { /* seen ESC */ 2436 switch (c) { 2437 2438 case '7': /* Save cursor position */ 2439 scp->saved_xpos = scp->xpos; 2440 scp->saved_ypos = scp->ypos; 2441 break; 2442 2443 case '8': /* Restore saved cursor position */ 2444 if (scp->saved_xpos >= 0 && scp->saved_ypos >= 0) 2445 move_crsr(scp, scp->saved_xpos, scp->saved_ypos); 2446 break; 2447 2448 case '[': /* Start ESC [ sequence */ 2449 scp->term.esc = 2; 2450 scp->term.last_param = -1; 2451 for (i = scp->term.num_param; i < MAX_ESC_PAR; i++) 2452 scp->term.param[i] = 1; 2453 scp->term.num_param = 0; 2454 return; 2455 2456 case 'M': /* Move cursor up 1 line, scroll if at top */ 2457 if (scp->ypos > 0) 2458 move_crsr(scp, scp->xpos, scp->ypos - 1); 2459 else { 2460 bcopy(scp->scr_buf, scp->scr_buf + scp->xsize, 2461 (scp->ysize - 1) * scp->xsize * sizeof(u_short)); 2462 fillw(scp->term.cur_color | scr_map[0x20], 2463 scp->scr_buf, scp->xsize); 2464 mark_all(scp); 2465 } 2466 break; 2467#if notyet 2468 case 'Q': 2469 scp->term.esc = 4; 2470 return; 2471#endif 2472 case 'c': /* Clear screen & home */ 2473 clear_screen(scp); 2474 break; 2475 2476 case '(': /* iso-2022: designate 94 character set to G0 */ 2477 scp->term.esc = 5; 2478 return; 2479 } 2480 } 2481 else if (scp->term.esc == 2) { /* seen ESC [ */ 2482 if (c >= '0' && c <= '9') { 2483 if (scp->term.num_param < MAX_ESC_PAR) { 2484 if (scp->term.last_param != scp->term.num_param) { 2485 scp->term.last_param = scp->term.num_param; 2486 scp->term.param[scp->term.num_param] = 0; 2487 } 2488 else 2489 scp->term.param[scp->term.num_param] *= 10; 2490 scp->term.param[scp->term.num_param] += c - '0'; 2491 return; 2492 } 2493 } 2494 scp->term.num_param = scp->term.last_param + 1; 2495 switch (c) { 2496 2497 case ';': 2498 if (scp->term.num_param < MAX_ESC_PAR) 2499 return; 2500 break; 2501 2502 case '=': 2503 scp->term.esc = 3; 2504 scp->term.last_param = -1; 2505 for (i = scp->term.num_param; i < MAX_ESC_PAR; i++) 2506 scp->term.param[i] = 1; 2507 scp->term.num_param = 0; 2508 return; 2509 2510 case 'A': /* up n rows */ 2511 n = scp->term.param[0]; if (n < 1) n = 1; 2512 move_crsr(scp, scp->xpos, scp->ypos - n); 2513 break; 2514 2515 case 'B': /* down n rows */ 2516 n = scp->term.param[0]; if (n < 1) n = 1; 2517 move_crsr(scp, scp->xpos, scp->ypos + n); 2518 break; 2519 2520 case 'C': /* right n columns */ 2521 n = scp->term.param[0]; if (n < 1) n = 1; 2522 move_crsr(scp, scp->xpos + n, scp->ypos); 2523 break; 2524 2525 case 'D': /* left n columns */ 2526 n = scp->term.param[0]; if (n < 1) n = 1; 2527 move_crsr(scp, scp->xpos - n, scp->ypos); 2528 break; 2529 2530 case 'E': /* cursor to start of line n lines down */ 2531 n = scp->term.param[0]; if (n < 1) n = 1; 2532 move_crsr(scp, 0, scp->ypos + n); 2533 break; 2534 2535 case 'F': /* cursor to start of line n lines up */ 2536 n = scp->term.param[0]; if (n < 1) n = 1; 2537 move_crsr(scp, 0, scp->ypos - n); 2538 break; 2539 2540 case 'f': /* Cursor move */ 2541 case 'H': 2542 if (scp->term.num_param == 0) 2543 move_crsr(scp, 0, 0); 2544 else if (scp->term.num_param == 2) 2545 move_crsr(scp, scp->term.param[1] - 1, scp->term.param[0] - 1); 2546 break; 2547 2548 case 'J': /* Clear all or part of display */ 2549 if (scp->term.num_param == 0) 2550 n = 0; 2551 else 2552 n = scp->term.param[0]; 2553 switch (n) { 2554 case 0: /* clear form cursor to end of display */ 2555 fillw(scp->term.cur_color | scr_map[0x20], 2556 scp->cursor_pos, 2557 scp->scr_buf + scp->xsize * scp->ysize - scp->cursor_pos); 2558 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2559 mark_for_update(scp, scp->xsize * scp->ysize); 2560 remove_cutmarking(scp); 2561 break; 2562 case 1: /* clear from beginning of display to cursor */ 2563 fillw(scp->term.cur_color | scr_map[0x20], 2564 scp->scr_buf, 2565 scp->cursor_pos - scp->scr_buf); 2566 mark_for_update(scp, 0); 2567 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2568 remove_cutmarking(scp); 2569 break; 2570 case 2: /* clear entire display */ 2571 fillw(scp->term.cur_color | scr_map[0x20], scp->scr_buf, 2572 scp->xsize * scp->ysize); 2573 mark_all(scp); 2574 remove_cutmarking(scp); 2575 break; 2576 } 2577 break; 2578 2579 case 'K': /* Clear all or part of line */ 2580 if (scp->term.num_param == 0) 2581 n = 0; 2582 else 2583 n = scp->term.param[0]; 2584 switch (n) { 2585 case 0: /* clear form cursor to end of line */ 2586 fillw(scp->term.cur_color | scr_map[0x20], 2587 scp->cursor_pos, 2588 scp->xsize - scp->xpos); 2589 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2590 mark_for_update(scp, scp->cursor_pos - scp->scr_buf + 2591 scp->xsize - scp->xpos); 2592 break; 2593 case 1: /* clear from beginning of line to cursor */ 2594 fillw(scp->term.cur_color | scr_map[0x20], 2595 scp->cursor_pos - scp->xpos, 2596 scp->xpos + 1); 2597 mark_for_update(scp, scp->ypos * scp->xsize); 2598 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2599 break; 2600 case 2: /* clear entire line */ 2601 fillw(scp->term.cur_color | scr_map[0x20], 2602 scp->cursor_pos - scp->xpos, 2603 scp->xsize); 2604 mark_for_update(scp, scp->ypos * scp->xsize); 2605 mark_for_update(scp, (scp->ypos + 1) * scp->xsize); 2606 break; 2607 } 2608 break; 2609 2610 case 'L': /* Insert n lines */ 2611 n = scp->term.param[0]; if (n < 1) n = 1; 2612 if (n > scp->ysize - scp->ypos) 2613 n = scp->ysize - scp->ypos; 2614 src = scp->scr_buf + scp->ypos * scp->xsize; 2615 dst = src + n * scp->xsize; 2616 count = scp->ysize - (scp->ypos + n); 2617 bcopy(src, dst, count * scp->xsize * sizeof(u_short)); 2618 fillw(scp->term.cur_color | scr_map[0x20], src, 2619 n * scp->xsize); 2620 mark_for_update(scp, scp->ypos * scp->xsize); 2621 mark_for_update(scp, scp->xsize * scp->ysize); 2622 break; 2623 2624 case 'M': /* Delete n lines */ 2625 n = scp->term.param[0]; if (n < 1) n = 1; 2626 if (n > scp->ysize - scp->ypos) 2627 n = scp->ysize - scp->ypos; 2628 dst = scp->scr_buf + scp->ypos * scp->xsize; 2629 src = dst + n * scp->xsize; 2630 count = scp->ysize - (scp->ypos + n); 2631 bcopy(src, dst, count * scp->xsize * sizeof(u_short)); 2632 src = dst + count * scp->xsize; 2633 fillw(scp->term.cur_color | scr_map[0x20], src, 2634 n * scp->xsize); 2635 mark_for_update(scp, scp->ypos * scp->xsize); 2636 mark_for_update(scp, scp->xsize * scp->ysize); 2637 break; 2638 2639 case 'P': /* Delete n chars */ 2640 n = scp->term.param[0]; if (n < 1) n = 1; 2641 if (n > scp->xsize - scp->xpos) 2642 n = scp->xsize - scp->xpos; 2643 dst = scp->cursor_pos; 2644 src = dst + n; 2645 count = scp->xsize - (scp->xpos + n); 2646 bcopy(src, dst, count * sizeof(u_short)); 2647 src = dst + count; 2648 fillw(scp->term.cur_color | scr_map[0x20], src, n); 2649 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2650 mark_for_update(scp, scp->cursor_pos - scp->scr_buf + n + count); 2651 break; 2652 2653 case '@': /* Insert n chars */ 2654 n = scp->term.param[0]; if (n < 1) n = 1; 2655 if (n > scp->xsize - scp->xpos) 2656 n = scp->xsize - scp->xpos; 2657 src = scp->cursor_pos; 2658 dst = src + n; 2659 count = scp->xsize - (scp->xpos + n); 2660 bcopy(src, dst, count * sizeof(u_short)); 2661 fillw(scp->term.cur_color | scr_map[0x20], src, n); 2662 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2663 mark_for_update(scp, scp->cursor_pos - scp->scr_buf + n + count); 2664 break; 2665 2666 case 'S': /* scroll up n lines */ 2667 n = scp->term.param[0]; if (n < 1) n = 1; 2668 if (n > scp->ysize) 2669 n = scp->ysize; 2670 bcopy(scp->scr_buf + (scp->xsize * n), 2671 scp->scr_buf, 2672 scp->xsize * (scp->ysize - n) * sizeof(u_short)); 2673 fillw(scp->term.cur_color | scr_map[0x20], 2674 scp->scr_buf + scp->xsize * (scp->ysize - n), 2675 scp->xsize * n); 2676 mark_all(scp); 2677 break; 2678 2679 case 'T': /* scroll down n lines */ 2680 n = scp->term.param[0]; if (n < 1) n = 1; 2681 if (n > scp->ysize) 2682 n = scp->ysize; 2683 bcopy(scp->scr_buf, 2684 scp->scr_buf + (scp->xsize * n), 2685 scp->xsize * (scp->ysize - n) * 2686 sizeof(u_short)); 2687 fillw(scp->term.cur_color | scr_map[0x20], 2688 scp->scr_buf, scp->xsize * n); 2689 mark_all(scp); 2690 break; 2691 2692 case 'X': /* erase n characters in line */ 2693 n = scp->term.param[0]; if (n < 1) n = 1; 2694 if (n > scp->xsize - scp->xpos) 2695 n = scp->xsize - scp->xpos; 2696 fillw(scp->term.cur_color | scr_map[0x20], 2697 scp->cursor_pos, n); 2698 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2699 mark_for_update(scp, scp->cursor_pos - scp->scr_buf + n); 2700 break; 2701 2702 case 'Z': /* move n tabs backwards */ 2703 n = scp->term.param[0]; if (n < 1) n = 1; 2704 if ((i = scp->xpos & 0xf8) == scp->xpos) 2705 i -= 8*n; 2706 else 2707 i -= 8*(n-1); 2708 if (i < 0) 2709 i = 0; 2710 move_crsr(scp, i, scp->ypos); 2711 break; 2712 2713 case '`': /* move cursor to column n */ 2714 n = scp->term.param[0]; if (n < 1) n = 1; 2715 move_crsr(scp, n - 1, scp->ypos); 2716 break; 2717 2718 case 'a': /* move cursor n columns to the right */ 2719 n = scp->term.param[0]; if (n < 1) n = 1; 2720 move_crsr(scp, scp->xpos + n, scp->ypos); 2721 break; 2722 2723 case 'd': /* move cursor to row n */ 2724 n = scp->term.param[0]; if (n < 1) n = 1; 2725 move_crsr(scp, scp->xpos, n - 1); 2726 break; 2727 2728 case 'e': /* move cursor n rows down */ 2729 n = scp->term.param[0]; if (n < 1) n = 1; 2730 move_crsr(scp, scp->xpos, scp->ypos + n); 2731 break; 2732 2733 case 'm': /* change attribute */ 2734 if (scp->term.num_param == 0) { 2735 scp->term.attr_mask = NORMAL_ATTR; 2736 scp->term.cur_attr = 2737 scp->term.cur_color = scp->term.std_color; 2738 break; 2739 } 2740 for (i = 0; i < scp->term.num_param; i++) { 2741 switch (n = scp->term.param[i]) { 2742 case 0: /* back to normal */ 2743 scp->term.attr_mask = NORMAL_ATTR; 2744 scp->term.cur_attr = 2745 scp->term.cur_color = scp->term.std_color; 2746 break; 2747 case 1: /* bold */ 2748 scp->term.attr_mask |= BOLD_ATTR; 2749 scp->term.cur_attr = mask2attr(&scp->term); 2750 break; 2751 case 4: /* underline */ 2752 scp->term.attr_mask |= UNDERLINE_ATTR; 2753 scp->term.cur_attr = mask2attr(&scp->term); 2754 break; 2755 case 5: /* blink */ 2756 scp->term.attr_mask |= BLINK_ATTR; 2757 scp->term.cur_attr = mask2attr(&scp->term); 2758 break; 2759 case 7: /* reverse video */ 2760 scp->term.attr_mask |= REVERSE_ATTR; 2761 scp->term.cur_attr = mask2attr(&scp->term); 2762 break; 2763 case 30: case 31: /* set fg color */ 2764 case 32: case 33: case 34: 2765 case 35: case 36: case 37: 2766 scp->term.attr_mask |= FOREGROUND_CHANGED; 2767 scp->term.cur_color = 2768 (scp->term.cur_color&0xF000) | (ansi_col[(n-30)&7]<<8); 2769 scp->term.cur_attr = mask2attr(&scp->term); 2770 break; 2771 case 40: case 41: /* set bg color */ 2772 case 42: case 43: case 44: 2773 case 45: case 46: case 47: 2774 scp->term.attr_mask |= BACKGROUND_CHANGED; 2775 scp->term.cur_color = 2776 (scp->term.cur_color&0x0F00) | (ansi_col[(n-40)&7]<<12); 2777 scp->term.cur_attr = mask2attr(&scp->term); 2778 break; 2779 } 2780 } 2781 break; 2782 2783 case 's': /* Save cursor position */ 2784 scp->saved_xpos = scp->xpos; 2785 scp->saved_ypos = scp->ypos; 2786 break; 2787 2788 case 'u': /* Restore saved cursor position */ 2789 if (scp->saved_xpos >= 0 && scp->saved_ypos >= 0) 2790 move_crsr(scp, scp->saved_xpos, scp->saved_ypos); 2791 break; 2792 2793 case 'x': 2794 if (scp->term.num_param == 0) 2795 n = 0; 2796 else 2797 n = scp->term.param[0]; 2798 switch (n) { 2799 case 0: /* reset attributes */ 2800 scp->term.attr_mask = NORMAL_ATTR; 2801 scp->term.cur_attr = 2802 scp->term.cur_color = scp->term.std_color = 2803 current_default->std_color; 2804 scp->term.rev_color = current_default->rev_color; 2805 break; 2806 case 1: /* set ansi background */ 2807 scp->term.attr_mask &= ~BACKGROUND_CHANGED; 2808 scp->term.cur_color = scp->term.std_color = 2809 (scp->term.std_color & 0x0F00) | 2810 (ansi_col[(scp->term.param[1])&0x0F]<<12); 2811 scp->term.cur_attr = mask2attr(&scp->term); 2812 break; 2813 case 2: /* set ansi foreground */ 2814 scp->term.attr_mask &= ~FOREGROUND_CHANGED; 2815 scp->term.cur_color = scp->term.std_color = 2816 (scp->term.std_color & 0xF000) | 2817 (ansi_col[(scp->term.param[1])&0x0F]<<8); 2818 scp->term.cur_attr = mask2attr(&scp->term); 2819 break; 2820 case 3: /* set ansi attribute directly */ 2821 scp->term.attr_mask &= ~(FOREGROUND_CHANGED|BACKGROUND_CHANGED); 2822 scp->term.cur_color = scp->term.std_color = 2823 (scp->term.param[1]&0xFF)<<8; 2824 scp->term.cur_attr = mask2attr(&scp->term); 2825 break; 2826 case 5: /* set ansi reverse video background */ 2827 scp->term.rev_color = 2828 (scp->term.rev_color & 0x0F00) | 2829 (ansi_col[(scp->term.param[1])&0x0F]<<12); 2830 scp->term.cur_attr = mask2attr(&scp->term); 2831 break; 2832 case 6: /* set ansi reverse video foreground */ 2833 scp->term.rev_color = 2834 (scp->term.rev_color & 0xF000) | 2835 (ansi_col[(scp->term.param[1])&0x0F]<<8); 2836 scp->term.cur_attr = mask2attr(&scp->term); 2837 break; 2838 case 7: /* set ansi reverse video directly */ 2839 scp->term.rev_color = 2840 (scp->term.param[1]&0xFF)<<8; 2841 scp->term.cur_attr = mask2attr(&scp->term); 2842 break; 2843 } 2844 break; 2845 2846 case 'z': /* switch to (virtual) console n */ 2847 if (scp->term.num_param == 1) 2848 switch_scr(scp, scp->term.param[0]); 2849 break; 2850 } 2851 } 2852 else if (scp->term.esc == 3) { /* seen ESC [0-9]+ = */ 2853 if (c >= '0' && c <= '9') { 2854 if (scp->term.num_param < MAX_ESC_PAR) { 2855 if (scp->term.last_param != scp->term.num_param) { 2856 scp->term.last_param = scp->term.num_param; 2857 scp->term.param[scp->term.num_param] = 0; 2858 } 2859 else 2860 scp->term.param[scp->term.num_param] *= 10; 2861 scp->term.param[scp->term.num_param] += c - '0'; 2862 return; 2863 } 2864 } 2865 scp->term.num_param = scp->term.last_param + 1; 2866 switch (c) { 2867 2868 case ';': 2869 if (scp->term.num_param < MAX_ESC_PAR) 2870 return; 2871 break; 2872 2873 case 'A': /* set display border color */ 2874 if (scp->term.num_param == 1) { 2875 scp->border=scp->term.param[0] & 0xff; 2876 if (scp == cur_console) 2877 set_border(scp->border); 2878 } 2879 break; 2880 2881 case 'B': /* set bell pitch and duration */ 2882 if (scp->term.num_param == 2) { 2883 scp->bell_pitch = scp->term.param[0]; 2884 scp->bell_duration = scp->term.param[1]*10; 2885 } 2886 break; 2887 2888 case 'C': /* set cursor type & shape */ 2889 if (scp->term.num_param == 1) { 2890 if (scp->term.param[0] & 0x01) 2891 flags |= BLINK_CURSOR; 2892 else 2893 flags &= ~BLINK_CURSOR; 2894 if ((scp->term.param[0] & 0x02) && crtc_vga) 2895 flags |= CHAR_CURSOR; 2896 else 2897 flags &= ~CHAR_CURSOR; 2898 } 2899 else if (scp->term.num_param == 2) { 2900 scp->cursor_start = scp->term.param[0] & 0x1F; 2901 scp->cursor_end = scp->term.param[1] & 0x1F; 2902 } 2903 /* 2904 * The cursor shape is global property; all virtual consoles 2905 * are affected. Update the cursor in the current console... 2906 */ 2907 if (!(cur_console->status & UNKNOWN_MODE)) { 2908 remove_cursor_image(cur_console); 2909 if (crtc_vga && (flags & CHAR_CURSOR)) 2910 set_destructive_cursor(cur_console); 2911 draw_cursor_image(cur_console); 2912 } 2913 break; 2914 2915 case 'F': /* set ansi foreground */ 2916 if (scp->term.num_param == 1) { 2917 scp->term.attr_mask &= ~FOREGROUND_CHANGED; 2918 scp->term.cur_color = scp->term.std_color = 2919 (scp->term.std_color & 0xF000) 2920 | ((scp->term.param[0] & 0x0F) << 8); 2921 scp->term.cur_attr = mask2attr(&scp->term); 2922 } 2923 break; 2924 2925 case 'G': /* set ansi background */ 2926 if (scp->term.num_param == 1) { 2927 scp->term.attr_mask &= ~BACKGROUND_CHANGED; 2928 scp->term.cur_color = scp->term.std_color = 2929 (scp->term.std_color & 0x0F00) 2930 | ((scp->term.param[0] & 0x0F) << 12); 2931 scp->term.cur_attr = mask2attr(&scp->term); 2932 } 2933 break; 2934 2935 case 'H': /* set ansi reverse video foreground */ 2936 if (scp->term.num_param == 1) { 2937 scp->term.rev_color = 2938 (scp->term.rev_color & 0xF000) 2939 | ((scp->term.param[0] & 0x0F) << 8); 2940 scp->term.cur_attr = mask2attr(&scp->term); 2941 } 2942 break; 2943 2944 case 'I': /* set ansi reverse video background */ 2945 if (scp->term.num_param == 1) { 2946 scp->term.rev_color = 2947 (scp->term.rev_color & 0x0F00) 2948 | ((scp->term.param[0] & 0x0F) << 12); 2949 scp->term.cur_attr = mask2attr(&scp->term); 2950 } 2951 break; 2952 } 2953 } 2954#if notyet 2955 else if (scp->term.esc == 4) { /* seen ESC Q */ 2956 /* to be filled */ 2957 } 2958#endif 2959 else if (scp->term.esc == 5) { /* seen ESC ( */ 2960 switch (c) { 2961 case 'B': /* iso-2022: desginate ASCII into G0 */ 2962 break; 2963 /* other items to be filled */ 2964 default: 2965 break; 2966 } 2967 } 2968 scp->term.esc = 0; 2969} 2970 2971static void 2972ansi_put(scr_stat *scp, u_char *buf, int len) 2973{ 2974 u_char *ptr = buf; 2975 2976 /* make screensaver happy */ 2977 if (scp == cur_console) 2978 scrn_time_stamp = mono_time.tv_sec; 2979 2980 write_in_progress++; 2981outloop: 2982 if (scp->term.esc) { 2983 scan_esc(scp, *ptr++); 2984 len--; 2985 } 2986 else if (PRINTABLE(*ptr)) { /* Print only printables */ 2987 int cnt = len <= (scp->xsize-scp->xpos) ? len : (scp->xsize-scp->xpos); 2988 u_short cur_attr = scp->term.cur_attr; 2989 u_short *cursor_pos = scp->cursor_pos; 2990 do { 2991 /* 2992 * gcc-2.6.3 generates poor (un)sign extension code. Casting the 2993 * pointers in the following to volatile should have no effect, 2994 * but in fact speeds up this inner loop from 26 to 18 cycles 2995 * (+ cache misses) on i486's. 2996 */ 2997#define UCVP(ucp) ((u_char volatile *)(ucp)) 2998 *cursor_pos++ = UCVP(scr_map)[*UCVP(ptr)] | cur_attr; 2999 ptr++; 3000 cnt--; 3001 } while (cnt && PRINTABLE(*ptr)); 3002 len -= (cursor_pos - scp->cursor_pos); 3003 scp->xpos += (cursor_pos - scp->cursor_pos); 3004 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 3005 mark_for_update(scp, cursor_pos - scp->scr_buf); 3006 scp->cursor_pos = cursor_pos; 3007 if (scp->xpos >= scp->xsize) { 3008 scp->xpos = 0; 3009 scp->ypos++; 3010 } 3011 } 3012 else { 3013 switch(*ptr) { 3014 case 0x07: 3015 do_bell(scp, scp->bell_pitch, scp->bell_duration); 3016 break; 3017 3018 case 0x08: /* non-destructive backspace */ 3019 if (scp->cursor_pos > scp->scr_buf) { 3020 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 3021 scp->cursor_pos--; 3022 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 3023 if (scp->xpos > 0) 3024 scp->xpos--; 3025 else { 3026 scp->xpos += scp->xsize - 1; 3027 scp->ypos--; 3028 } 3029 } 3030 break; 3031 3032 case 0x09: /* non-destructive tab */ 3033 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 3034 scp->cursor_pos += (8 - scp->xpos % 8u); 3035 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 3036 if ((scp->xpos += (8 - scp->xpos % 8u)) >= scp->xsize) { 3037 scp->xpos = 0; 3038 scp->ypos++; 3039 } 3040 break; 3041 3042 case 0x0a: /* newline, same pos */ 3043 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 3044 scp->cursor_pos += scp->xsize; 3045 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 3046 scp->ypos++; 3047 break; 3048 3049 case 0x0c: /* form feed, clears screen */ 3050 clear_screen(scp); 3051 break; 3052 3053 case 0x0d: /* return, return to pos 0 */ 3054 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 3055 scp->cursor_pos -= scp->xpos; 3056 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 3057 scp->xpos = 0; 3058 break; 3059 3060 case 0x1b: /* start escape sequence */ 3061 scp->term.esc = 1; 3062 scp->term.num_param = 0; 3063 break; 3064 } 3065 ptr++; len--; 3066 } 3067 /* do we have to scroll ?? */ 3068 if (scp->cursor_pos >= scp->scr_buf + scp->ysize * scp->xsize) { 3069 remove_cutmarking(scp); 3070 if (scp->history) { 3071 bcopy(scp->scr_buf, scp->history_head, 3072 scp->xsize * sizeof(u_short)); 3073 scp->history_head += scp->xsize; 3074 if (scp->history_head + scp->xsize > 3075 scp->history + scp->history_size) 3076 scp->history_head = scp->history; 3077 } 3078 bcopy(scp->scr_buf + scp->xsize, scp->scr_buf, 3079 scp->xsize * (scp->ysize - 1) * sizeof(u_short)); 3080 fillw(scp->term.cur_color | scr_map[0x20], 3081 scp->scr_buf + scp->xsize * (scp->ysize - 1), 3082 scp->xsize); 3083 scp->cursor_pos -= scp->xsize; 3084 scp->ypos--; 3085 mark_all(scp); 3086 } 3087 if (len) 3088 goto outloop; 3089 write_in_progress--; 3090 if (delayed_next_scr) 3091 switch_scr(scp, delayed_next_scr - 1); 3092} 3093 3094static void 3095scinit(void) 3096{ 3097 u_int hw_cursor; 3098 u_int i; 3099 3100 if (init_done != COLD) 3101 return; 3102 init_done = WARM; 3103 3104 /* 3105 * Ensure a zero start address. This is mainly to recover after 3106 * switching from pcvt using userconfig(). The registers are w/o 3107 * for old hardware so it's too hard to relocate the active screen 3108 * memory. 3109 */ 3110 outb(crtc_addr, 12); 3111 outb(crtc_addr + 1, 0); 3112 outb(crtc_addr, 13); 3113 outb(crtc_addr + 1, 0); 3114 3115 /* extract cursor location */ 3116 outb(crtc_addr, 14); 3117 hw_cursor = inb(crtc_addr + 1) << 8; 3118 outb(crtc_addr, 15); 3119 hw_cursor |= inb(crtc_addr + 1); 3120 3121 /* 3122 * Validate cursor location. It may be off the screen. Then we must 3123 * not use it for the initial buffer offset. 3124 */ 3125 if (hw_cursor >= ROW * COL) 3126 hw_cursor = (ROW - 1) * COL; 3127 3128 /* move hardware cursor out of the way */ 3129 outb(crtc_addr, 14); 3130 outb(crtc_addr + 1, 0xff); 3131 outb(crtc_addr, 15); 3132 outb(crtc_addr + 1, 0xff); 3133 3134 /* set up the first console */ 3135 current_default = &user_default; 3136 console[0] = &main_console; 3137 init_scp(console[0]); 3138 cur_console = console[0]; 3139 3140 /* discard the video mode table if we are not familiar with it... */ 3141 if (video_mode_ptr) { 3142 bzero(mode_map, sizeof(mode_map)); 3143 bcopy(video_mode_ptr + MODE_PARAM_SIZE*console[0]->mode, 3144 vgaregs2, sizeof(vgaregs2)); 3145 switch (comp_vgaregs(vgaregs, video_mode_ptr 3146 + MODE_PARAM_SIZE*console[0]->mode)) { 3147 case COMP_IDENTICAL: 3148 map_mode_table(mode_map, video_mode_ptr, M_VGA_CG320 + 1); 3149 /* 3150 * This is a kludge for Toshiba DynaBook SS433 whose BIOS video 3151 * mode table entry has the actual # of rows at the offset 1; 3152 * BIOSes from other manufacturers store the # of rows - 1 there. 3153 * XXX 3154 */ 3155 rows_offset = vgaregs[1] + 1 3156 - video_mode_ptr[MODE_PARAM_SIZE*console[0]->mode + 1]; 3157 break; 3158 case COMP_SIMILAR: 3159 map_mode_table(mode_map, video_mode_ptr, M_VGA_CG320 + 1); 3160 mode_map[console[0]->mode] = vgaregs; 3161 rows_offset = vgaregs[1] + 1 3162 - video_mode_ptr[MODE_PARAM_SIZE*console[0]->mode + 1]; 3163 vgaregs[1] -= rows_offset - 1; 3164 break; 3165 case COMP_DIFFERENT: 3166 default: 3167 video_mode_ptr = NULL; 3168 mode_map[console[0]->mode] = vgaregs; 3169 rows_offset = 1; 3170 break; 3171 } 3172 } 3173 3174 /* copy screen to temporary buffer */ 3175 sc_bcopy(Crtat, sc_buffer, 3176 console[0]->xsize * console[0]->ysize * sizeof(u_short)); 3177 3178 console[0]->scr_buf = console[0]->mouse_pos = sc_buffer; 3179 console[0]->cursor_pos = console[0]->cursor_oldpos = sc_buffer + hw_cursor; 3180 console[0]->cursor_saveunder = *console[0]->cursor_pos; 3181 console[0]->xpos = hw_cursor % COL; 3182 console[0]->ypos = hw_cursor / COL; 3183 for (i=1; i<MAXCONS; i++) 3184 console[i] = NULL; 3185 kernel_console.esc = 0; 3186 kernel_console.attr_mask = NORMAL_ATTR; 3187 kernel_console.cur_attr = 3188 kernel_console.cur_color = kernel_console.std_color = 3189 kernel_default.std_color; 3190 kernel_console.rev_color = kernel_default.rev_color; 3191 3192 /* initialize mapscrn arrays to a one to one map */ 3193 for (i=0; i<sizeof(scr_map); i++) { 3194 scr_map[i] = scr_rmap[i] = i; 3195 } 3196 3197 /* Save font and palette if VGA */ 3198 if (crtc_vga) { 3199 if (fonts_loaded & FONT_16) { 3200 copy_font(LOAD, FONT_16, font_16); 3201 } else { 3202 copy_font(SAVE, FONT_16, font_16); 3203 fonts_loaded = FONT_16; 3204 } 3205 save_palette(); 3206 set_destructive_cursor(console[0]); 3207 } 3208 3209#ifdef SC_SPLASH_SCREEN 3210 /* 3211 * Now put up a graphics image, and maybe cycle a 3212 * couble of palette entries for simple animation. 3213 */ 3214 toggle_splash_screen(cur_console); 3215#endif 3216} 3217 3218static void 3219map_mode_table(char *map[], char *table, int max) 3220{ 3221 int i; 3222 3223 for(i = 0; i < max; ++i) 3224 map[i] = table + i*MODE_PARAM_SIZE; 3225 for(; i < MODE_MAP_SIZE; ++i) 3226 map[i] = NULL; 3227} 3228 3229static u_char 3230map_mode_num(u_char mode) 3231{ 3232 static struct { 3233 u_char from; 3234 u_char to; 3235 } mode_map[] = { 3236 { M_ENH_B80x43, M_ENH_B80x25 }, 3237 { M_ENH_C80x43, M_ENH_C80x25 }, 3238 { M_VGA_M80x30, M_VGA_M80x25 }, 3239 { M_VGA_C80x30, M_VGA_C80x25 }, 3240 { M_VGA_M80x50, M_VGA_M80x25 }, 3241 { M_VGA_C80x50, M_VGA_C80x25 }, 3242 { M_VGA_M80x60, M_VGA_M80x25 }, 3243 { M_VGA_C80x60, M_VGA_C80x25 }, 3244 { M_VGA_MODEX, M_VGA_CG320 }, 3245 }; 3246 int i; 3247 3248 for (i = 0; i < sizeof(mode_map)/sizeof(mode_map[0]); ++i) { 3249 if (mode_map[i].from == mode) 3250 return mode_map[i].to; 3251 } 3252 return mode; 3253} 3254 3255static char 3256*get_mode_param(scr_stat *scp, u_char mode) 3257{ 3258 if (mode >= MODE_MAP_SIZE) 3259 mode = map_mode_num(mode); 3260 if (mode < MODE_MAP_SIZE) 3261 return mode_map[mode]; 3262 else 3263 return NULL; 3264} 3265 3266static scr_stat 3267*alloc_scp() 3268{ 3269 scr_stat *scp; 3270 3271 scp = (scr_stat *)malloc(sizeof(scr_stat), M_DEVBUF, M_WAITOK); 3272 init_scp(scp); 3273 scp->scr_buf = scp->cursor_pos = scp->cursor_oldpos = 3274 (u_short *)malloc(scp->xsize*scp->ysize*sizeof(u_short), 3275 M_DEVBUF, M_WAITOK); 3276 scp->mouse_pos = scp->mouse_oldpos = 3277 scp->scr_buf + ((scp->mouse_ypos/scp->font_size)*scp->xsize + 3278 scp->mouse_xpos/8); 3279 scp->history_head = scp->history_pos = 3280 (u_short *)malloc(scp->history_size*sizeof(u_short), 3281 M_DEVBUF, M_WAITOK); 3282 bzero(scp->history_head, scp->history_size*sizeof(u_short)); 3283 scp->history = scp->history_head; 3284/* SOS 3285 if (crtc_vga && video_mode_ptr) 3286 set_mode(scp); 3287*/ 3288 clear_screen(scp); 3289 scp->cursor_saveunder = *scp->cursor_pos; 3290 return scp; 3291} 3292 3293static void 3294init_scp(scr_stat *scp) 3295{ 3296 if (crtc_vga) 3297 if (crtc_addr == MONO_BASE) 3298 scp->mode = M_VGA_M80x25; 3299 else 3300 scp->mode = M_VGA_C80x25; 3301 else 3302 if (crtc_addr == MONO_BASE) 3303 scp->mode = M_B80x25; 3304 else 3305 scp->mode = M_C80x25; 3306 scp->initial_mode = scp->mode; 3307 3308 scp->font_size = 16; 3309 scp->xsize = COL; 3310 scp->ysize = ROW; 3311 scp->xpos = scp->ypos = 0; 3312 scp->saved_xpos = scp->saved_ypos = -1; 3313 scp->start = scp->xsize * scp->ysize; 3314 scp->end = 0; 3315 scp->term.esc = 0; 3316 scp->term.attr_mask = NORMAL_ATTR; 3317 scp->term.cur_attr = 3318 scp->term.cur_color = scp->term.std_color = 3319 current_default->std_color; 3320 scp->term.rev_color = current_default->rev_color; 3321 scp->border = BG_BLACK; 3322 scp->cursor_start = *(char *)pa_to_va(0x461); 3323 scp->cursor_end = *(char *)pa_to_va(0x460); 3324 scp->mouse_xpos = scp->xsize*8/2; 3325 scp->mouse_ypos = scp->ysize*scp->font_size/2; 3326 scp->mouse_cut_start = scp->mouse_cut_end = NULL; 3327 scp->mouse_signal = 0; 3328 scp->mouse_pid = 0; 3329 scp->mouse_proc = NULL; 3330 scp->bell_pitch = BELL_PITCH; 3331 scp->bell_duration = BELL_DURATION; 3332 scp->status = (*(char *)pa_to_va(0x417) & 0x20) ? NLKED : 0; 3333 scp->status |= CURSOR_ENABLED; 3334 scp->pid = 0; 3335 scp->proc = NULL; 3336 scp->smode.mode = VT_AUTO; 3337 scp->history_head = scp->history_pos = scp->history = NULL; 3338 scp->history_size = imax(SC_HISTORY_SIZE, scp->ysize) * scp->xsize; 3339} 3340 3341static u_char 3342*get_fstr(u_int c, u_int *len) 3343{ 3344 u_int i; 3345 3346 if (!(c & FKEY)) 3347 return(NULL); 3348 i = (c & 0xFF) - F_FN; 3349 if (i > n_fkey_tab) 3350 return(NULL); 3351 *len = fkey_tab[i].len; 3352 return(fkey_tab[i].str); 3353} 3354 3355static void 3356history_to_screen(scr_stat *scp) 3357{ 3358 int i; 3359 3360 for (i=0; i<scp->ysize; i++) 3361 bcopy(scp->history + (((scp->history_pos - scp->history) + 3362 scp->history_size-((i+1)*scp->xsize))%scp->history_size), 3363 scp->scr_buf + (scp->xsize * (scp->ysize-1 - i)), 3364 scp->xsize * sizeof(u_short)); 3365 mark_all(scp); 3366} 3367 3368static int 3369history_up_line(scr_stat *scp) 3370{ 3371 if (WRAPHIST(scp, scp->history_pos, -(scp->xsize*scp->ysize)) != 3372 scp->history_head) { 3373 scp->history_pos = WRAPHIST(scp, scp->history_pos, -scp->xsize); 3374 history_to_screen(scp); 3375 return 0; 3376 } 3377 else 3378 return -1; 3379} 3380 3381static int 3382history_down_line(scr_stat *scp) 3383{ 3384 if (scp->history_pos != scp->history_head) { 3385 scp->history_pos = WRAPHIST(scp, scp->history_pos, scp->xsize); 3386 history_to_screen(scp); 3387 return 0; 3388 } 3389 else 3390 return -1; 3391} 3392 3393/* 3394 * scgetc(flags) - get character from keyboard. 3395 * If flags & SCGETC_CN, then avoid harmful side effects. 3396 * If flags & SCGETC_NONBLOCK, then wait until a key is pressed, else 3397 * return NOKEY if there is nothing there. 3398 */ 3399static u_int 3400scgetc(u_int flags) 3401{ 3402 struct key_t *key; 3403 u_char scancode, keycode; 3404 u_int state, action; 3405 int c; 3406 static u_char esc_flag = 0, compose = 0; 3407 static u_int chr = 0; 3408 3409next_code: 3410 /* first see if there is something in the keyboard port */ 3411 if (flags & SCGETC_NONBLOCK) { 3412 c = read_kbd_data_no_wait(sc_kbdc); 3413 if (c == -1) 3414 return(NOKEY); 3415 } else { 3416 do { 3417 c = read_kbd_data(sc_kbdc); 3418 } while(c == -1); 3419 } 3420 scancode = (u_char)c; 3421 3422 /* do the /dev/random device a favour */ 3423 if (!(flags & SCGETC_CN)) 3424 add_keyboard_randomness(scancode); 3425 3426 if (cur_console->status & KBD_RAW_MODE) 3427 return scancode; 3428 3429 keycode = scancode & 0x7F; 3430 switch (esc_flag) { 3431 case 0x00: /* normal scancode */ 3432 switch(scancode) { 3433 case 0xB8: /* left alt (compose key) */ 3434 if (compose) { 3435 compose = 0; 3436 if (chr > 255) { 3437 do_bell(cur_console, 3438 BELL_PITCH, BELL_DURATION); 3439 chr = 0; 3440 } 3441 } 3442 break; 3443 case 0x38: 3444 if (!compose) { 3445 compose = 1; 3446 chr = 0; 3447 } 3448 break; 3449 case 0xE0: 3450 case 0xE1: 3451 esc_flag = scancode; 3452 goto next_code; 3453 } 3454 break; 3455 case 0xE0: /* 0xE0 prefix */ 3456 esc_flag = 0; 3457 switch (keycode) { 3458 case 0x1C: /* right enter key */ 3459 keycode = 0x59; 3460 break; 3461 case 0x1D: /* right ctrl key */ 3462 keycode = 0x5A; 3463 break; 3464 case 0x35: /* keypad divide key */ 3465 keycode = 0x5B; 3466 break; 3467 case 0x37: /* print scrn key */ 3468 keycode = 0x5C; 3469 break; 3470 case 0x38: /* right alt key (alt gr) */ 3471 keycode = 0x5D; 3472 break; 3473 case 0x47: /* grey home key */ 3474 keycode = 0x5E; 3475 break; 3476 case 0x48: /* grey up arrow key */ 3477 keycode = 0x5F; 3478 break; 3479 case 0x49: /* grey page up key */ 3480 keycode = 0x60; 3481 break; 3482 case 0x4B: /* grey left arrow key */ 3483 keycode = 0x61; 3484 break; 3485 case 0x4D: /* grey right arrow key */ 3486 keycode = 0x62; 3487 break; 3488 case 0x4F: /* grey end key */ 3489 keycode = 0x63; 3490 break; 3491 case 0x50: /* grey down arrow key */ 3492 keycode = 0x64; 3493 break; 3494 case 0x51: /* grey page down key */ 3495 keycode = 0x65; 3496 break; 3497 case 0x52: /* grey insert key */ 3498 keycode = 0x66; 3499 break; 3500 case 0x53: /* grey delete key */ 3501 keycode = 0x67; 3502 break; 3503 3504 /* the following 3 are only used on the MS "Natural" keyboard */ 3505 case 0x5b: /* left Window key */ 3506 keycode = 0x69; 3507 break; 3508 case 0x5c: /* right Window key */ 3509 keycode = 0x6a; 3510 break; 3511 case 0x5d: /* menu key */ 3512 keycode = 0x6b; 3513 break; 3514 default: /* ignore everything else */ 3515 goto next_code; 3516 } 3517 break; 3518 case 0xE1: /* 0xE1 prefix */ 3519 esc_flag = 0; 3520 if (keycode == 0x1D) 3521 esc_flag = 0x1D; 3522 goto next_code; 3523 /* NOT REACHED */ 3524 case 0x1D: /* pause / break */ 3525 esc_flag = 0; 3526 if (keycode != 0x45) 3527 goto next_code; 3528 keycode = 0x68; 3529 break; 3530 } 3531 3532 if (cur_console->status & KBD_CODE_MODE) 3533 return (keycode | (scancode & 0x80)); 3534 3535 /* if scroll-lock pressed allow history browsing */ 3536 if (cur_console->history && cur_console->status & SLKED) { 3537 int i; 3538 3539 cur_console->status &= ~CURSOR_ENABLED; 3540 if (!(cur_console->status & BUFFER_SAVED)) { 3541 cur_console->status |= BUFFER_SAVED; 3542 cur_console->history_save = cur_console->history_head; 3543 3544 /* copy screen into top of history buffer */ 3545 for (i=0; i<cur_console->ysize; i++) { 3546 bcopy(cur_console->scr_buf + (cur_console->xsize * i), 3547 cur_console->history_head, 3548 cur_console->xsize * sizeof(u_short)); 3549 cur_console->history_head += cur_console->xsize; 3550 if (cur_console->history_head + cur_console->xsize > 3551 cur_console->history + cur_console->history_size) 3552 cur_console->history_head=cur_console->history; 3553 } 3554 cur_console->history_pos = cur_console->history_head; 3555 history_to_screen(cur_console); 3556 } 3557 switch (scancode) { 3558 case 0x47: /* home key */ 3559 cur_console->history_pos = cur_console->history_head; 3560 history_to_screen(cur_console); 3561 goto next_code; 3562 3563 case 0x4F: /* end key */ 3564 cur_console->history_pos = 3565 WRAPHIST(cur_console, cur_console->history_head, 3566 cur_console->xsize*cur_console->ysize); 3567 history_to_screen(cur_console); 3568 goto next_code; 3569 3570 case 0x48: /* up arrow key */ 3571 if (history_up_line(cur_console)) 3572 do_bell(cur_console, BELL_PITCH, BELL_DURATION); 3573 goto next_code; 3574 3575 case 0x50: /* down arrow key */ 3576 if (history_down_line(cur_console)) 3577 do_bell(cur_console, BELL_PITCH, BELL_DURATION); 3578 goto next_code; 3579 3580 case 0x49: /* page up key */ 3581 for (i=0; i<cur_console->ysize; i++) 3582 if (history_up_line(cur_console)) { 3583 do_bell(cur_console, BELL_PITCH, BELL_DURATION); 3584 break; 3585 } 3586 goto next_code; 3587 3588 case 0x51: /* page down key */ 3589 for (i=0; i<cur_console->ysize; i++) 3590 if (history_down_line(cur_console)) { 3591 do_bell(cur_console, BELL_PITCH, BELL_DURATION); 3592 break; 3593 } 3594 goto next_code; 3595 } 3596 } 3597 3598 if (compose) { 3599 switch (scancode) { 3600 /* key pressed process it */ 3601 case 0x47: case 0x48: case 0x49: /* keypad 7,8,9 */ 3602 chr = (scancode - 0x40) + chr*10; 3603 goto next_code; 3604 case 0x4B: case 0x4C: case 0x4D: /* keypad 4,5,6 */ 3605 chr = (scancode - 0x47) + chr*10; 3606 goto next_code; 3607 case 0x4F: case 0x50: case 0x51: /* keypad 1,2,3 */ 3608 chr = (scancode - 0x4E) + chr*10; 3609 goto next_code; 3610 case 0x52: /* keypad 0 */ 3611 chr *= 10; 3612 goto next_code; 3613 3614 /* key release, no interest here */ 3615 case 0xC7: case 0xC8: case 0xC9: /* keypad 7,8,9 */ 3616 case 0xCB: case 0xCC: case 0xCD: /* keypad 4,5,6 */ 3617 case 0xCF: case 0xD0: case 0xD1: /* keypad 1,2,3 */ 3618 case 0xD2: /* keypad 0 */ 3619 goto next_code; 3620 3621 case 0x38: /* left alt key */ 3622 break; 3623 default: 3624 if (chr) { 3625 compose = chr = 0; 3626 do_bell(cur_console, BELL_PITCH, BELL_DURATION); 3627 goto next_code; 3628 } 3629 break; 3630 } 3631 } 3632 3633 state = (shfts ? 1 : 0 ) | (2 * (ctls ? 1 : 0)) | (4 * (alts ? 1 : 0)); 3634 if ((!agrs && (cur_console->status & ALKED)) 3635 || (agrs && !(cur_console->status & ALKED))) 3636 keycode += ALTGR_OFFSET; 3637 key = &key_map.key[keycode]; 3638 if ( ((key->flgs & FLAG_LOCK_C) && (cur_console->status & CLKED)) 3639 || ((key->flgs & FLAG_LOCK_N) && (cur_console->status & NLKED)) ) 3640 state ^= 1; 3641 3642 /* Check for make/break */ 3643 action = key->map[state]; 3644 if (scancode & 0x80) { /* key released */ 3645 if (key->spcl & (0x80>>state)) { 3646 switch (action) { 3647 case LSH: 3648 shfts &= ~1; 3649 break; 3650 case RSH: 3651 shfts &= ~2; 3652 break; 3653 case LCTR: 3654 ctls &= ~1; 3655 break; 3656 case RCTR: 3657 ctls &= ~2; 3658 break; 3659 case LALT: 3660 alts &= ~1; 3661 break; 3662 case RALT: 3663 alts &= ~2; 3664 break; 3665 case NLK: 3666 nlkcnt = 0; 3667 break; 3668 case CLK: 3669 clkcnt = 0; 3670 break; 3671 case SLK: 3672 slkcnt = 0; 3673 break; 3674 case ASH: 3675 agrs = 0; 3676 break; 3677 case ALK: 3678 alkcnt = 0; 3679 break; 3680 case META: 3681 metas = 0; 3682 break; 3683 } 3684 } 3685 if (chr && !compose) { 3686 action = chr; 3687 chr = 0; 3688 return(action); 3689 } 3690 } else { 3691 /* key pressed */ 3692 if (key->spcl & (0x80>>state)) { 3693 switch (action) { 3694 /* LOCKING KEYS */ 3695 case NLK: 3696#ifdef SC_SPLASH_SCREEN 3697 toggle_splash_screen(cur_console); /* SOS XXX */ 3698#endif 3699 if (!nlkcnt) { 3700 nlkcnt++; 3701 if (cur_console->status & NLKED) 3702 cur_console->status &= ~NLKED; 3703 else 3704 cur_console->status |= NLKED; 3705 update_leds(cur_console->status); 3706 } 3707 break; 3708 case CLK: 3709 if (!clkcnt) { 3710 clkcnt++; 3711 if (cur_console->status & CLKED) 3712 cur_console->status &= ~CLKED; 3713 else 3714 cur_console->status |= CLKED; 3715 update_leds(cur_console->status); 3716 } 3717 break; 3718 case SLK: 3719 if (!slkcnt) { 3720 slkcnt++; 3721 if (cur_console->status & SLKED) { 3722 cur_console->status &= ~SLKED; 3723 if (cur_console->status & BUFFER_SAVED){ 3724 int i; 3725 u_short *ptr = cur_console->history_save; 3726 3727 for (i=0; i<cur_console->ysize; i++) { 3728 bcopy(ptr, 3729 cur_console->scr_buf + 3730 (cur_console->xsize*i), 3731 cur_console->xsize * sizeof(u_short)); 3732 ptr += cur_console->xsize; 3733 if (ptr + cur_console->xsize > 3734 cur_console->history + 3735 cur_console->history_size) 3736 ptr = cur_console->history; 3737 } 3738 cur_console->status &= ~BUFFER_SAVED; 3739 cur_console->history_head=cur_console->history_save; 3740 cur_console->status |= CURSOR_ENABLED; 3741 mark_all(cur_console); 3742 } 3743 scstart(VIRTUAL_TTY(get_scr_num())); 3744 } 3745 else 3746 cur_console->status |= SLKED; 3747 update_leds(cur_console->status); 3748 } 3749 break; 3750 case ALK: 3751 if (!alkcnt) { 3752 alkcnt++; 3753 if (cur_console->status & ALKED) 3754 cur_console->status &= ~ALKED; 3755 else 3756 cur_console->status |= ALKED; 3757 update_leds(cur_console->status); 3758 } 3759 break; 3760 3761 /* NON-LOCKING KEYS */ 3762 case NOP: 3763 break; 3764 case SPSC: 3765#ifdef SC_SPLASH_SCREEN 3766 accents = 0; 3767 toggle_splash_screen(cur_console); 3768#endif 3769 break; 3770 case RBT: 3771 accents = 0; 3772 shutdown_nice(); 3773 break; 3774 case SUSP: 3775#if NAPM > 0 3776 accents = 0; 3777 apm_suspend(); 3778#endif 3779 break; 3780 3781 case DBG: 3782#ifdef DDB /* try to switch to console 0 */ 3783 accents = 0; 3784 if (cur_console->smode.mode == VT_AUTO && 3785 console[0]->smode.mode == VT_AUTO) 3786 switch_scr(cur_console, 0); 3787 Debugger("manual escape to debugger"); 3788#else 3789 printf("No debugger in kernel\n"); 3790#endif 3791 break; 3792 case LSH: 3793 shfts |= 1; 3794 break; 3795 case RSH: 3796 shfts |= 2; 3797 break; 3798 case LCTR: 3799 ctls |= 1; 3800 break; 3801 case RCTR: 3802 ctls |= 2; 3803 break; 3804 case LALT: 3805 alts |= 1; 3806 break; 3807 case RALT: 3808 alts |= 2; 3809 break; 3810 case ASH: 3811 agrs = 1; 3812 break; 3813 case META: 3814 metas = 1; 3815 break; 3816 case NEXT: 3817 { 3818 int next, this = get_scr_num(); 3819 accents = 0; 3820 for (next = this+1; next != this; next = (next+1)%MAXCONS) { 3821 struct tty *tp = VIRTUAL_TTY(next); 3822 if (tp->t_state & TS_ISOPEN) { 3823 switch_scr(cur_console, next); 3824 break; 3825 } 3826 } 3827 } 3828 break; 3829 case BTAB: 3830 accents = 0; 3831 return(BKEY); 3832 default: 3833 if (action >= F_ACC && action <= L_ACC) { 3834 /* turn it into an index */ 3835 action -= F_ACC - 1; 3836 if ((action > accent_map.n_accs) 3837 || (accent_map.acc[action - 1].accchar == 0)) { 3838 /* 3839 * The index is out of range or pointing to an 3840 * empty entry. 3841 */ 3842 accents = 0; 3843 do_bell(cur_console, BELL_PITCH, BELL_DURATION); 3844 } 3845 /* 3846 * If the same accent key has been hit twice, 3847 * produce the accent char itself. 3848 */ 3849 if (action == accents) { 3850 action = accent_map.acc[accents - 1].accchar; 3851 accents = 0; 3852 if (metas) 3853 action |= MKEY; 3854 return (action); 3855 } 3856 /* remember the index and wait for the next key stroke */ 3857 accents = action; 3858 break; 3859 } 3860 if (accents > 0) { 3861 accents = 0; 3862 do_bell(cur_console, BELL_PITCH, BELL_DURATION); 3863 } 3864 if (action >= F_SCR && action <= L_SCR) { 3865 switch_scr(cur_console, action - F_SCR); 3866 break; 3867 } 3868 if (action >= F_FN && action <= L_FN) 3869 action |= FKEY; 3870 return(action); 3871 } 3872 } 3873 else { 3874 if (accents) { 3875 struct acc_t *acc; 3876 int i; 3877 3878 acc = &accent_map.acc[accents - 1]; 3879 accents = 0; 3880 /* 3881 * If the accent key is followed by the space key, 3882 * produce the accent char itself. 3883 */ 3884 if (action == ' ') { 3885 action = acc->accchar; 3886 if (metas) 3887 action |= MKEY; 3888 return (action); 3889 } 3890 for (i = 0; i < NUM_ACCENTCHARS; ++i) { 3891 if (acc->map[i][0] == 0) /* end of the map entry */ 3892 break; 3893 if (acc->map[i][0] == action) { 3894 action = acc->map[i][1]; 3895 if (metas) 3896 action |= MKEY; 3897 return (action); 3898 } 3899 } 3900 do_bell(cur_console, BELL_PITCH, BELL_DURATION); 3901 goto next_code; 3902 } 3903 if (metas) 3904 action |= MKEY; 3905 return(action); 3906 } 3907 } 3908 goto next_code; 3909} 3910 3911int 3912scmmap(dev_t dev, int offset, int nprot) 3913{ 3914 if (offset > 0x20000 - PAGE_SIZE) 3915 return -1; 3916 return i386_btop((VIDEOMEM + offset)); 3917} 3918 3919/* 3920 * Calculate hardware attributes word using logical attributes mask and 3921 * hardware colors 3922 */ 3923 3924static int 3925mask2attr(struct term_stat *term) 3926{ 3927 int attr, mask = term->attr_mask; 3928 3929 if (mask & REVERSE_ATTR) { 3930 attr = ((mask & FOREGROUND_CHANGED) ? 3931 ((term->cur_color & 0xF000) >> 4) : 3932 (term->rev_color & 0x0F00)) | 3933 ((mask & BACKGROUND_CHANGED) ? 3934 ((term->cur_color & 0x0F00) << 4) : 3935 (term->rev_color & 0xF000)); 3936 } else 3937 attr = term->cur_color; 3938 3939 /* XXX: underline mapping for Hercules adapter can be better */ 3940 if (mask & (BOLD_ATTR | UNDERLINE_ATTR)) 3941 attr ^= 0x0800; 3942 if (mask & BLINK_ATTR) 3943 attr ^= 0x8000; 3944 3945 return attr; 3946} 3947 3948static void 3949set_keyboard(int command, int data) 3950{ 3951 int s; 3952 3953 if (sc_kbdc == NULL) 3954 return; 3955 3956 /* prevent the timeout routine from polling the keyboard */ 3957 if (!kbdc_lock(sc_kbdc, TRUE)) 3958 return; 3959 3960 /* disable the keyboard and mouse interrupt */ 3961 s = spltty(); 3962#if 0 3963 c = get_controller_command_byte(sc_kbdc); 3964 if ((c == -1) 3965 || !set_controller_command_byte(sc_kbdc, 3966 kbdc_get_device_mask(sc_kbdc), 3967 KBD_DISABLE_KBD_PORT | KBD_DISABLE_KBD_INT 3968 | KBD_DISABLE_AUX_PORT | KBD_DISABLE_AUX_INT)) { 3969 /* CONTROLLER ERROR */ 3970 kbdc_lock(sc_kbdc, FALSE); 3971 splx(s); 3972 return; 3973 } 3974 /* 3975 * Now that the keyboard controller is told not to generate 3976 * the keyboard and mouse interrupts, call `splx()' to allow 3977 * the other tty interrupts. The clock interrupt may also occur, 3978 * but the timeout routine (`scrn_timer()') will be blocked 3979 * by the lock flag set via `kbdc_lock()' 3980 */ 3981 splx(s); 3982#endif 3983 3984 if (send_kbd_command_and_data(sc_kbdc, command, data) != KBD_ACK) 3985 send_kbd_command(sc_kbdc, KBDC_ENABLE_KBD); 3986 3987#if 0 3988 /* restore the interrupts */ 3989 if (!set_controller_command_byte(sc_kbdc, 3990 kbdc_get_device_mask(sc_kbdc), 3991 c & (KBD_KBD_CONTROL_BITS | KBD_AUX_CONTROL_BITS))) { 3992 /* CONTROLLER ERROR */ 3993 } 3994#else 3995 splx(s); 3996#endif 3997 kbdc_lock(sc_kbdc, FALSE); 3998} 3999 4000static void 4001update_leds(int which) 4002{ 4003 static u_char xlate_leds[8] = { 0, 4, 2, 6, 1, 5, 3, 7 }; 4004 4005 /* replace CAPS led with ALTGR led for ALTGR keyboards */ 4006 if (key_map.n_keys > ALTGR_OFFSET) { 4007 if (which & ALKED) 4008 which |= CLKED; 4009 else 4010 which &= ~CLKED; 4011 } 4012 4013 set_keyboard(KBDC_SET_LEDS, xlate_leds[which & LED_MASK]); 4014} 4015 4016void 4017set_mode(scr_stat *scp) 4018{ 4019 char special_modetable[MODE_PARAM_SIZE]; 4020 char *mp; 4021 4022 if (scp != cur_console) 4023 return; 4024 4025 /* 4026 * even if mode switching is disabled, we can change back 4027 * to the initial mode or the custom mode based on the initial 4028 * mode if we have saved register values upon start-up. 4029 */ 4030 mp = get_mode_param(scp, scp->mode); 4031 if (mp == NULL) 4032 return; 4033 bcopy(mp, &special_modetable, sizeof(special_modetable)); 4034 4035 /* setup video hardware for the given mode */ 4036 switch (scp->mode) { 4037 case M_VGA_C80x60: case M_VGA_M80x60: 4038 special_modetable[2] = 0x08; 4039 special_modetable[19] = 0x47; 4040 goto special_480l; 4041 4042 case M_VGA_C80x30: case M_VGA_M80x30: 4043 special_modetable[19] = 0x4f; 4044special_480l: 4045 special_modetable[9] |= 0xc0; 4046 special_modetable[16] = 0x08; 4047 special_modetable[17] = 0x3e; 4048 special_modetable[26] = 0xea; 4049 special_modetable[28] = 0xdf; 4050 special_modetable[31] = 0xe7; 4051 special_modetable[32] = 0x04; 4052 goto setup_mode; 4053 4054 case M_ENH_C80x43: case M_ENH_B80x43: 4055 special_modetable[28] = 87; 4056 goto special_80x50; 4057 4058 case M_VGA_C80x50: case M_VGA_M80x50: 4059special_80x50: 4060 special_modetable[2] = 8; 4061 special_modetable[19] = 7; 4062 goto setup_mode; 4063 4064 case M_VGA_C40x25: case M_VGA_C80x25: 4065 case M_VGA_M80x25: 4066 case M_B40x25: case M_C40x25: 4067 case M_B80x25: case M_C80x25: 4068 case M_ENH_B40x25: case M_ENH_C40x25: 4069 case M_ENH_B80x25: case M_ENH_C80x25: 4070 case M_EGAMONO80x25: 4071 4072setup_mode: 4073 set_vgaregs(special_modetable); 4074 scp->font_size = special_modetable[2]; 4075 4076 /* set font type (size) */ 4077 if (scp->font_size < 14) { 4078 if (fonts_loaded & FONT_8) 4079 copy_font(LOAD, FONT_8, font_8); 4080 outb(TSIDX, 0x03); outb(TSREG, 0x0A); /* font 2 */ 4081 } else if (scp->font_size >= 16) { 4082 if (fonts_loaded & FONT_16) 4083 copy_font(LOAD, FONT_16, font_16); 4084 outb(TSIDX, 0x03); outb(TSREG, 0x00); /* font 0 */ 4085 } else { 4086 if (fonts_loaded & FONT_14) 4087 copy_font(LOAD, FONT_14, font_14); 4088 outb(TSIDX, 0x03); outb(TSREG, 0x05); /* font 1 */ 4089 } 4090 if (flags & CHAR_CURSOR) 4091 set_destructive_cursor(scp); 4092 mark_all(scp); 4093 break; 4094 4095 case M_VGA_MODEX: 4096 /* "unchain" the VGA mode */ 4097 special_modetable[5-1+0x04] &= 0xf7; 4098 special_modetable[5-1+0x04] |= 0x04; 4099 /* turn off doubleword mode */ 4100 special_modetable[10+0x14] &= 0xbf; 4101 /* turn off word adressing */ 4102 special_modetable[10+0x17] |= 0x40; 4103 /* set logical screen width */ 4104 special_modetable[10+0x13] = 80; 4105 /* set 240 lines */ 4106 special_modetable[10+0x11] = 0x2c; 4107 special_modetable[10+0x06] = 0x0d; 4108 special_modetable[10+0x07] = 0x3e; 4109 special_modetable[10+0x10] = 0xea; 4110 special_modetable[10+0x11] = 0xac; 4111 special_modetable[10+0x12] = 0xdf; 4112 special_modetable[10+0x15] = 0xe7; 4113 special_modetable[10+0x16] = 0x06; 4114 /* set vertical sync polarity to reflect aspect ratio */ 4115 special_modetable[9] = 0xe3; 4116 goto setup_grmode; 4117 4118 case M_BG320: case M_CG320: case M_BG640: 4119 case M_CG320_D: case M_CG640_E: 4120 case M_CG640x350: case M_ENH_CG640: 4121 case M_BG640x480: case M_CG640x480: case M_VGA_CG320: 4122 4123setup_grmode: 4124 set_vgaregs(special_modetable); 4125 scp->font_size = FONT_NONE; 4126 break; 4127 4128 default: 4129 /* call user defined function XXX */ 4130 break; 4131 } 4132 4133 /* set border color for this (virtual) console */ 4134 set_border(scp->border); 4135 return; 4136} 4137 4138void 4139set_border(u_char color) 4140{ 4141 switch (crtc_type) { 4142 case KD_EGA: 4143 case KD_VGA: 4144 inb(crtc_addr + 6); /* reset flip-flop */ 4145 outb(ATC, 0x31); outb(ATC, color); 4146 break; 4147 case KD_CGA: 4148 outb(crtc_addr + 5, color & 0x0f); /* color select register */ 4149 break; 4150 case KD_MONO: 4151 case KD_HERCULES: 4152 default: 4153 break; 4154 } 4155} 4156 4157static void 4158set_vgaregs(char *modetable) 4159{ 4160 int i, s = splhigh(); 4161 4162 outb(TSIDX, 0x00); outb(TSREG, 0x01); /* stop sequencer */ 4163 outb(TSIDX, 0x07); outb(TSREG, 0x00); /* unlock registers */ 4164 for (i=0; i<4; i++) { /* program sequencer */ 4165 outb(TSIDX, i+1); 4166 outb(TSREG, modetable[i+5]); 4167 } 4168 outb(MISC, modetable[9]); /* set dot-clock */ 4169 outb(TSIDX, 0x00); outb(TSREG, 0x03); /* start sequencer */ 4170 outb(crtc_addr, 0x11); 4171 outb(crtc_addr+1, inb(crtc_addr+1) & 0x7F); 4172 for (i=0; i<25; i++) { /* program crtc */ 4173 outb(crtc_addr, i); 4174 if (i == 14 || i == 15) /* no hardware cursor */ 4175 outb(crtc_addr+1, 0xff); 4176 else 4177 outb(crtc_addr+1, modetable[i+10]); 4178 } 4179 inb(crtc_addr+6); /* reset flip-flop */ 4180 for (i=0; i<20; i++) { /* program attribute ctrl */ 4181 outb(ATC, i); 4182 outb(ATC, modetable[i+35]); 4183 } 4184 for (i=0; i<9; i++) { /* program graph data ctrl */ 4185 outb(GDCIDX, i); 4186 outb(GDCREG, modetable[i+55]); 4187 } 4188 inb(crtc_addr+6); /* reset flip-flop */ 4189 outb(ATC, 0x20); /* enable palette */ 4190 splx(s); 4191} 4192 4193static void 4194read_vgaregs(char *buf) 4195{ 4196 int i, j; 4197 int s; 4198 4199 bzero(buf, MODE_PARAM_SIZE); 4200 4201 s = splhigh(); 4202 4203 outb(TSIDX, 0x00); outb(TSREG, 0x01); /* stop sequencer */ 4204 outb(TSIDX, 0x07); outb(TSREG, 0x00); /* unlock registers */ 4205 for (i=0, j=5; i<4; i++) { 4206 outb(TSIDX, i+1); 4207 buf[j++] = inb(TSREG); 4208 } 4209 buf[9] = inb(MISC + 10); /* dot-clock */ 4210 outb(TSIDX, 0x00); outb(TSREG, 0x03); /* start sequencer */ 4211 4212 for (i=0, j=10; i<25; i++) { /* crtc */ 4213 outb(crtc_addr, i); 4214 buf[j++] = inb(crtc_addr+1); 4215 } 4216 for (i=0, j=35; i<20; i++) { /* attribute ctrl */ 4217 inb(crtc_addr+6); /* reset flip-flop */ 4218 outb(ATC, i); 4219 buf[j++] = inb(ATC + 1); 4220 } 4221 for (i=0, j=55; i<9; i++) { /* graph data ctrl */ 4222 outb(GDCIDX, i); 4223 buf[j++] = inb(GDCREG); 4224 } 4225 inb(crtc_addr+6); /* reset flip-flop */ 4226 outb(ATC, 0x20); /* enable palette */ 4227 4228 buf[0] = *(char *)pa_to_va(0x44a); /* COLS */ 4229 buf[1] = *(char *)pa_to_va(0x484); /* ROWS */ 4230 buf[2] = *(char *)pa_to_va(0x485); /* POINTS */ 4231 buf[3] = *(char *)pa_to_va(0x44c); 4232 buf[4] = *(char *)pa_to_va(0x44d); 4233 4234 splx(s); 4235} 4236 4237static int 4238comp_vgaregs(u_char *buf1, u_char *buf2) 4239{ 4240 static struct { 4241 u_char mask; 4242 } params[MODE_PARAM_SIZE] = { 4243 0xff, 0x00, 0xff, /* COLS, ROWS, POINTS */ 4244 0xff, 0xff, /* page length */ 4245 0xfe, 0xff, 0xff, 0xff, /* sequencer registers */ 4246 0xf3, /* misc register */ 4247 0xff, 0xff, 0xff, 0x7f, 0xff, /* CRTC */ 4248 0xff, 0xff, 0xff, 0x7f, 0xff, 4249 0x00, 0x00, 0x00, 0x00, 0x00, 4250 0x00, 0xff, 0x7f, 0xff, 0xff, 4251 0x7f, 0xff, 0xff, 0xef, 0xff, 4252 0xff, 0xff, 0xff, 0xff, 0xff, /* attribute controller registers */ 4253 0xff, 0xff, 0xff, 0xff, 0xff, 4254 0xff, 0xff, 0xff, 0xff, 0xff, 4255 0xff, 0xff, 0xff, 0xff, 0xf0, 4256 0xff, 0xff, 0xff, 0xff, 0xff, /* GDC register */ 4257 0xff, 0xff, 0xff, 0xff, 4258 }; 4259 int identical = TRUE; 4260 int i; 4261 4262 for (i = 0; i < sizeof(params)/sizeof(params[0]); ++i) { 4263 if (params[i].mask == 0) /* don't care */ 4264 continue; 4265 if ((buf1[i] & params[i].mask) != (buf2[i] & params[i].mask)) 4266 return COMP_DIFFERENT; 4267 if (buf1[i] != buf2[i]) 4268 identical = FALSE; 4269 } 4270 return (identical) ? COMP_IDENTICAL : COMP_SIMILAR; 4271 4272#if 0 4273 for(i = 0; i < 20; ++i) { 4274 if (*buf1++ != *buf2++) 4275 return COMP_DIFFERENT; 4276 } 4277 buf1 += 2; /* skip the cursor shape */ 4278 buf2 += 2; 4279 for(i = 22; i < 24; ++i) { 4280 if (*buf1++ != *buf2++) 4281 return COMP_DIFFERENT; 4282 } 4283 buf1 += 2; /* skip the cursor position */ 4284 buf2 += 2; 4285 for(i = 26; i < MODE_PARAM_SIZE; ++i) { 4286 if (*buf1++ != *buf2++) 4287 return COMP_DIFFERENT; 4288 } 4289 return COMP_IDENTICAL; 4290#endif 4291} 4292 4293static void 4294dump_vgaregs(u_char *buf) 4295{ 4296 int i; 4297 4298 for(i = 0; i < MODE_PARAM_SIZE;) { 4299 printf("%02x ", buf[i]); 4300 if ((++i % 16) == 0) 4301 printf("\n"); 4302 } 4303} 4304 4305static void 4306set_font_mode(u_char *buf) 4307{ 4308 int s = splhigh(); 4309 4310 /* save register values */ 4311 outb(TSIDX, 0x02); buf[0] = inb(TSREG); 4312 outb(TSIDX, 0x04); buf[1] = inb(TSREG); 4313 outb(GDCIDX, 0x04); buf[2] = inb(GDCREG); 4314 outb(GDCIDX, 0x05); buf[3] = inb(GDCREG); 4315 outb(GDCIDX, 0x06); buf[4] = inb(GDCREG); 4316 inb(crtc_addr + 6); 4317 outb(ATC, 0x10); buf[5] = inb(ATC + 1); 4318 4319 /* setup vga for loading fonts (graphics plane mode) */ 4320 inb(crtc_addr+6); /* reset flip-flop */ 4321 outb(ATC, 0x10); outb(ATC, 0x01); 4322 inb(crtc_addr+6); /* reset flip-flop */ 4323 outb(ATC, 0x20); /* enable palette */ 4324 4325#if SLOW_VGA 4326 outb(TSIDX, 0x02); outb(TSREG, 0x04); 4327 outb(TSIDX, 0x04); outb(TSREG, 0x06); 4328 outb(GDCIDX, 0x04); outb(GDCREG, 0x02); 4329 outb(GDCIDX, 0x05); outb(GDCREG, 0x00); 4330 outb(GDCIDX, 0x06); outb(GDCREG, 0x05); 4331#else 4332 outw(TSIDX, 0x0402); 4333 outw(TSIDX, 0x0604); 4334 outw(GDCIDX, 0x0204); 4335 outw(GDCIDX, 0x0005); 4336 outw(GDCIDX, 0x0506); /* addr = a0000, 64kb */ 4337#endif 4338 splx(s); 4339} 4340 4341static void 4342set_normal_mode(u_char *buf) 4343{ 4344 char *modetable; 4345 int s = splhigh(); 4346 4347 /* setup vga for normal operation mode again */ 4348 inb(crtc_addr+6); /* reset flip-flop */ 4349 outb(ATC, 0x10); outb(ATC, buf[5]); 4350 inb(crtc_addr+6); /* reset flip-flop */ 4351 outb(ATC, 0x20); /* enable palette */ 4352 4353#if SLOW_VGA 4354 outb(TSIDX, 0x02); outb(TSREG, buf[0]); 4355 outb(TSIDX, 0x04); outb(TSREG, buf[1]); 4356 outb(GDCIDX, 0x04); outb(GDCREG, buf[2]); 4357 outb(GDCIDX, 0x05); outb(GDCREG, buf[3]); 4358 if (crtc_addr == MONO_BASE) { 4359 outb(GDCIDX, 0x06); outb(GDCREG,(buf[4] & 0x03) | 0x08); 4360 } else { 4361 outb(GDCIDX, 0x06); outb(GDCREG,(buf[4] & 0x03) | 0x0c); 4362 } 4363#else 4364 outw(TSIDX, 0x0002 | (buf[0] << 8)); 4365 outw(TSIDX, 0x0004 | (buf[1] << 8)); 4366 outw(GDCIDX, 0x0004 | (buf[2] << 8)); 4367 outw(GDCIDX, 0x0005 | (buf[3] << 8)); 4368 if (crtc_addr == MONO_BASE) 4369 outw(GDCIDX, 0x0006 | (((buf[4] & 0x03) | 0x08)<<8)); 4370 else 4371 outw(GDCIDX, 0x0006 | (((buf[4] & 0x03) | 0x0c)<<8)); 4372#endif 4373 splx(s); 4374} 4375 4376void 4377copy_font(int operation, int font_type, char* font_image) 4378{ 4379 int ch, line, segment, fontsize; 4380 u_char buf[PARAM_BUFSIZE]; 4381 u_char val; 4382 4383 switch (font_type) { 4384 default: 4385 case FONT_8: 4386 segment = 0x8000; 4387 fontsize = 8; 4388 break; 4389 case FONT_14: 4390 segment = 0x4000; 4391 fontsize = 14; 4392 break; 4393 case FONT_16: 4394 segment = 0x0000; 4395 fontsize = 16; 4396 break; 4397 } 4398 outb(TSIDX, 0x01); val = inb(TSREG); /* disable screen */ 4399 outb(TSIDX, 0x01); outb(TSREG, val | 0x20); 4400 set_font_mode(buf); 4401 for (ch=0; ch < 256; ch++) 4402 for (line=0; line < fontsize; line++) 4403 if (operation) 4404 *(char *)pa_to_va(VIDEOMEM+(segment)+(ch*32)+line) = 4405 font_image[(ch*fontsize)+line]; 4406 else 4407 font_image[(ch*fontsize)+line] = 4408 *(char *)pa_to_va(VIDEOMEM+(segment)+(ch*32)+line); 4409 set_normal_mode(buf); 4410 outb(TSIDX, 0x01); outb(TSREG, val & 0xDF); /* enable screen */ 4411} 4412 4413static void 4414set_destructive_cursor(scr_stat *scp) 4415{ 4416 u_char buf[PARAM_BUFSIZE]; 4417 u_char cursor[32]; 4418 caddr_t address; 4419 int i; 4420 char *font_buffer; 4421 4422 if (scp->font_size < 14) { 4423 font_buffer = font_8; 4424 address = (caddr_t)VIDEOMEM + 0x8000; 4425 } 4426 else if (scp->font_size >= 16) { 4427 font_buffer = font_16; 4428 address = (caddr_t)VIDEOMEM; 4429 } 4430 else { 4431 font_buffer = font_14; 4432 address = (caddr_t)VIDEOMEM + 0x4000; 4433 } 4434 4435 if (scp->status & MOUSE_VISIBLE) { 4436 if ((scp->cursor_saveunder & 0xff) == 0xd0) 4437 bcopy(&scp->mouse_cursor[0], cursor, scp->font_size); 4438 else if ((scp->cursor_saveunder & 0xff) == 0xd1) 4439 bcopy(&scp->mouse_cursor[32], cursor, scp->font_size); 4440 else if ((scp->cursor_saveunder & 0xff) == 0xd2) 4441 bcopy(&scp->mouse_cursor[64], cursor, scp->font_size); 4442 else if ((scp->cursor_saveunder & 0xff) == 0xd3) 4443 bcopy(&scp->mouse_cursor[96], cursor, scp->font_size); 4444 else 4445 bcopy(font_buffer+((scp->cursor_saveunder & 0xff)*scp->font_size), 4446 cursor, scp->font_size); 4447 } 4448 else 4449 bcopy(font_buffer + ((scp->cursor_saveunder & 0xff) * scp->font_size), 4450 cursor, scp->font_size); 4451 for (i=0; i<32; i++) 4452 if ((i >= scp->cursor_start && i <= scp->cursor_end) || 4453 (scp->cursor_start >= scp->font_size && i == scp->font_size - 1)) 4454 cursor[i] |= 0xff; 4455#if 1 4456 while (!(inb(crtc_addr+6) & 0x08)) /* wait for vertical retrace */ ; 4457#endif 4458 set_font_mode(buf); 4459 sc_bcopy(cursor, (char *)pa_to_va(address) + DEAD_CHAR * 32, 32); 4460 set_normal_mode(buf); 4461} 4462 4463static void 4464set_mouse_pos(scr_stat *scp) 4465{ 4466 static int last_xpos = -1, last_ypos = -1; 4467 4468 if (scp->mouse_xpos < 0) 4469 scp->mouse_xpos = 0; 4470 if (scp->mouse_ypos < 0) 4471 scp->mouse_ypos = 0; 4472 if (scp->status & UNKNOWN_MODE) { 4473 if (scp->mouse_xpos > scp->xpixel-1) 4474 scp->mouse_xpos = scp->xpixel-1; 4475 if (scp->mouse_ypos > scp->ypixel-1) 4476 scp->mouse_ypos = scp->ypixel-1; 4477 return; 4478 } 4479 if (scp->mouse_xpos > (scp->xsize*8)-1) 4480 scp->mouse_xpos = (scp->xsize*8)-1; 4481 if (scp->mouse_ypos > (scp->ysize*scp->font_size)-1) 4482 scp->mouse_ypos = (scp->ysize*scp->font_size)-1; 4483 4484 if (scp->mouse_xpos != last_xpos || scp->mouse_ypos != last_ypos) { 4485 scp->status |= MOUSE_MOVED; 4486 4487 scp->mouse_pos = scp->scr_buf + 4488 ((scp->mouse_ypos/scp->font_size)*scp->xsize + scp->mouse_xpos/8); 4489 4490 if ((scp->status & MOUSE_VISIBLE) && (scp->status & MOUSE_CUTTING)) 4491 mouse_cut(scp); 4492 } 4493} 4494 4495#define isspace(c) (((c) & 0xff) == ' ') 4496 4497static int 4498skip_spc_right(scr_stat *scp, u_short *p) 4499{ 4500 int i; 4501 4502 for (i = (p - scp->scr_buf) % scp->xsize; i < scp->xsize; ++i) { 4503 if (!isspace(*p)) 4504 break; 4505 ++p; 4506 } 4507 return i; 4508} 4509 4510static int 4511skip_spc_left(scr_stat *scp, u_short *p) 4512{ 4513 int i; 4514 4515 for (i = (p-- - scp->scr_buf) % scp->xsize - 1; i >= 0; --i) { 4516 if (!isspace(*p)) 4517 break; 4518 --p; 4519 } 4520 return i; 4521} 4522 4523static void 4524mouse_cut(scr_stat *scp) 4525{ 4526 u_short *end; 4527 u_short *p; 4528 int i = 0; 4529 int j = 0; 4530 4531 scp->mouse_cut_end = (scp->mouse_pos >= scp->mouse_cut_start) ? 4532 scp->mouse_pos + 1 : scp->mouse_pos; 4533 end = (scp->mouse_cut_start > scp->mouse_cut_end) ? 4534 scp->mouse_cut_start : scp->mouse_cut_end; 4535 for (p = (scp->mouse_cut_start > scp->mouse_cut_end) ? 4536 scp->mouse_cut_end : scp->mouse_cut_start; p < end; ++p) { 4537 cut_buffer[i] = *p & 0xff; 4538 /* remember the position of the last non-space char */ 4539 if (!isspace(cut_buffer[i++])) 4540 j = i; 4541 /* trim trailing blank when crossing lines */ 4542 if (((p - scp->scr_buf) % scp->xsize) == (scp->xsize - 1)) { 4543 cut_buffer[j++] = '\n'; 4544 i = j; 4545 } 4546 } 4547 cut_buffer[i] = '\0'; 4548 4549 /* scan towards the end of the last line */ 4550 --p; 4551 for (i = (p - scp->scr_buf) % scp->xsize; i < scp->xsize; ++i) { 4552 if (!isspace(*p)) 4553 break; 4554 ++p; 4555 } 4556 /* if there is nothing but blank chars, trim them, but mark towards eol */ 4557 if (i >= scp->xsize) { 4558 if (scp->mouse_cut_start > scp->mouse_cut_end) 4559 scp->mouse_cut_start = p; 4560 else 4561 scp->mouse_cut_end = p; 4562 cut_buffer[j++] = '\n'; 4563 cut_buffer[j] = '\0'; 4564 } 4565 4566 mark_for_update(scp, scp->mouse_cut_start - scp->scr_buf); 4567 mark_for_update(scp, scp->mouse_cut_end - scp->scr_buf); 4568} 4569 4570static void 4571mouse_cut_start(scr_stat *scp) 4572{ 4573 int i; 4574 4575 if (scp->status & MOUSE_VISIBLE) { 4576 if (scp->mouse_pos == scp->mouse_cut_start && 4577 scp->mouse_cut_start == scp->mouse_cut_end - 1) { 4578 cut_buffer[0] = '\0'; 4579 remove_cutmarking(scp); 4580 } else if (skip_spc_right(scp, scp->mouse_pos) >= scp->xsize) { 4581 /* if the pointer is on trailing blank chars, mark towards eol */ 4582 i = skip_spc_left(scp, scp->mouse_pos) + 1; 4583 scp->mouse_cut_start = scp->scr_buf + 4584 ((scp->mouse_pos - scp->scr_buf) / scp->xsize) * scp->xsize + i; 4585 scp->mouse_cut_end = scp->scr_buf + 4586 ((scp->mouse_pos - scp->scr_buf) / scp->xsize + 1) * scp->xsize; 4587 cut_buffer[0] = '\n'; 4588 cut_buffer[1] = '\0'; 4589 scp->status |= MOUSE_CUTTING; 4590 } else { 4591 scp->mouse_cut_start = scp->mouse_pos; 4592 scp->mouse_cut_end = scp->mouse_cut_start + 1; 4593 cut_buffer[0] = *scp->mouse_cut_start & 0xff; 4594 cut_buffer[1] = '\0'; 4595 scp->status |= MOUSE_CUTTING; 4596 } 4597 mark_all(scp); 4598 /* delete all other screens cut markings */ 4599 for (i=0; i<MAXCONS; i++) { 4600 if (console[i] == NULL || console[i] == scp) 4601 continue; 4602 remove_cutmarking(console[i]); 4603 } 4604 } 4605} 4606 4607static void 4608mouse_cut_end(scr_stat *scp) 4609{ 4610 if (scp->status & MOUSE_VISIBLE) { 4611 scp->status &= ~MOUSE_CUTTING; 4612 } 4613} 4614 4615static void 4616mouse_cut_word(scr_stat *scp) 4617{ 4618 u_short *p; 4619 u_short *sol; 4620 u_short *eol; 4621 int i; 4622 4623 /* 4624 * Because we don't have locale information in the kernel, 4625 * we only distinguish space char and non-space chars. Punctuation 4626 * chars, symbols and other regular chars are all treated alike. 4627 */ 4628 if (scp->status & MOUSE_VISIBLE) { 4629 sol = scp->scr_buf 4630 + ((scp->mouse_pos - scp->scr_buf) / scp->xsize) * scp->xsize; 4631 eol = sol + scp->xsize; 4632 if (isspace(*scp->mouse_pos)) { 4633 for (p = scp->mouse_pos; p >= sol; --p) 4634 if (!isspace(*p)) 4635 break; 4636 scp->mouse_cut_start = ++p; 4637 for (p = scp->mouse_pos; p < eol; ++p) 4638 if (!isspace(*p)) 4639 break; 4640 scp->mouse_cut_end = p; 4641 } else { 4642 for (p = scp->mouse_pos; p >= sol; --p) 4643 if (isspace(*p)) 4644 break; 4645 scp->mouse_cut_start = ++p; 4646 for (p = scp->mouse_pos; p < eol; ++p) 4647 if (isspace(*p)) 4648 break; 4649 scp->mouse_cut_end = p; 4650 } 4651 for (i = 0, p = scp->mouse_cut_start; p < scp->mouse_cut_end; ++p) 4652 cut_buffer[i++] = *p & 0xff; 4653 cut_buffer[i] = '\0'; 4654 scp->status |= MOUSE_CUTTING; 4655 } 4656} 4657 4658static void 4659mouse_cut_line(scr_stat *scp) 4660{ 4661 u_short *p; 4662 int i; 4663 4664 if (scp->status & MOUSE_VISIBLE) { 4665 scp->mouse_cut_start = scp->scr_buf 4666 + ((scp->mouse_pos - scp->scr_buf) / scp->xsize) * scp->xsize; 4667 scp->mouse_cut_end = scp->mouse_cut_start + scp->xsize; 4668 for (i = 0, p = scp->mouse_cut_start; p < scp->mouse_cut_end; ++p) 4669 cut_buffer[i++] = *p & 0xff; 4670 cut_buffer[i++] = '\n'; 4671 cut_buffer[i] = '\0'; 4672 scp->status |= MOUSE_CUTTING; 4673 } 4674} 4675 4676static void 4677mouse_cut_extend(scr_stat *scp) 4678{ 4679 if ((scp->status & MOUSE_VISIBLE) && !(scp->status & MOUSE_CUTTING) 4680 && (scp->mouse_cut_start != NULL)) { 4681 mouse_cut(scp); 4682 scp->status |= MOUSE_CUTTING; 4683 } 4684} 4685 4686static void 4687mouse_paste(scr_stat *scp) 4688{ 4689 if (scp->status & MOUSE_VISIBLE) { 4690 struct tty *tp; 4691 u_char *ptr = cut_buffer; 4692 4693 tp = VIRTUAL_TTY(get_scr_num()); 4694 while (*ptr) 4695 (*linesw[tp->t_line].l_rint)(scr_rmap[*ptr++], tp); 4696 } 4697} 4698 4699static void 4700draw_mouse_image(scr_stat *scp) 4701{ 4702 caddr_t address; 4703 int i; 4704 char *font_buffer; 4705 u_char buf[PARAM_BUFSIZE]; 4706 u_short buffer[32]; 4707 u_short xoffset, yoffset; 4708 u_short *crt_pos = Crtat + (scp->mouse_pos - scp->scr_buf); 4709 int font_size = scp->font_size; 4710 4711 if (font_size < 14) { 4712 font_buffer = font_8; 4713 address = (caddr_t)VIDEOMEM + 0x8000; 4714 } 4715 else if (font_size >= 16) { 4716 font_buffer = font_16; 4717 address = (caddr_t)VIDEOMEM; 4718 } 4719 else { 4720 font_buffer = font_14; 4721 address = (caddr_t)VIDEOMEM + 0x4000; 4722 } 4723 xoffset = scp->mouse_xpos % 8; 4724 yoffset = scp->mouse_ypos % font_size; 4725 4726 /* prepare mousepointer char's bitmaps */ 4727 bcopy(font_buffer + ((*(scp->mouse_pos) & 0xff) * font_size), 4728 &scp->mouse_cursor[0], font_size); 4729 bcopy(font_buffer + ((*(scp->mouse_pos+1) & 0xff) * font_size), 4730 &scp->mouse_cursor[32], font_size); 4731 bcopy(font_buffer + ((*(scp->mouse_pos+scp->xsize) & 0xff) * font_size), 4732 &scp->mouse_cursor[64], font_size); 4733 bcopy(font_buffer + ((*(scp->mouse_pos+scp->xsize+1) & 0xff) * font_size), 4734 &scp->mouse_cursor[96], font_size); 4735 for (i=0; i<font_size; i++) { 4736 buffer[i] = scp->mouse_cursor[i]<<8 | scp->mouse_cursor[i+32]; 4737 buffer[i+font_size]=scp->mouse_cursor[i+64]<<8|scp->mouse_cursor[i+96]; 4738 } 4739 4740 /* now and-or in the mousepointer image */ 4741 for (i=0; i<16; i++) { 4742 buffer[i+yoffset] = 4743 ( buffer[i+yoffset] & ~(mouse_and_mask[i] >> xoffset)) 4744 | (mouse_or_mask[i] >> xoffset); 4745 } 4746 for (i=0; i<font_size; i++) { 4747 scp->mouse_cursor[i] = (buffer[i] & 0xff00) >> 8; 4748 scp->mouse_cursor[i+32] = buffer[i] & 0xff; 4749 scp->mouse_cursor[i+64] = (buffer[i+font_size] & 0xff00) >> 8; 4750 scp->mouse_cursor[i+96] = buffer[i+font_size] & 0xff; 4751 } 4752 4753 scp->mouse_oldpos = scp->mouse_pos; 4754 4755#if 1 4756 /* wait for vertical retrace to avoid jitter on some videocards */ 4757 while (!(inb(crtc_addr+6) & 0x08)) /* idle */ ; 4758#endif 4759 set_font_mode(buf); 4760 sc_bcopy(scp->mouse_cursor, (char *)pa_to_va(address) + 0xd0 * 32, 128); 4761 set_normal_mode(buf); 4762 *(crt_pos) = (*(scp->mouse_pos)&0xff00)|0xd0; 4763 *(crt_pos+scp->xsize) = (*(scp->mouse_pos+scp->xsize)&0xff00)|0xd2; 4764 if (scp->mouse_xpos < (scp->xsize-1)*8) { 4765 *(crt_pos+1) = (*(scp->mouse_pos+1)&0xff00)|0xd1; 4766 *(crt_pos+scp->xsize+1) = (*(scp->mouse_pos+scp->xsize+1)&0xff00)|0xd3; 4767 } 4768 mark_for_update(scp, scp->mouse_pos - scp->scr_buf); 4769 mark_for_update(scp, scp->mouse_pos + scp->xsize + 1 - scp->scr_buf); 4770} 4771 4772static void 4773remove_mouse_image(scr_stat *scp) 4774{ 4775 u_short *crt_pos = Crtat + (scp->mouse_oldpos - scp->scr_buf); 4776 4777 *(crt_pos) = *(scp->mouse_oldpos); 4778 *(crt_pos+1) = *(scp->mouse_oldpos+1); 4779 *(crt_pos+scp->xsize) = *(scp->mouse_oldpos+scp->xsize); 4780 *(crt_pos+scp->xsize+1) = *(scp->mouse_oldpos+scp->xsize+1); 4781 mark_for_update(scp, scp->mouse_oldpos - scp->scr_buf); 4782 mark_for_update(scp, scp->mouse_oldpos + scp->xsize + 1 - scp->scr_buf); 4783} 4784 4785static void 4786draw_cutmarking(scr_stat *scp) 4787{ 4788 u_short *ptr; 4789 u_short och, nch; 4790 4791 for (ptr=scp->scr_buf; ptr<=(scp->scr_buf+(scp->xsize*scp->ysize)); ptr++) { 4792 nch = och = *(Crtat + (ptr - scp->scr_buf)); 4793 /* are we outside the selected area ? */ 4794 if ( ptr < (scp->mouse_cut_start > scp->mouse_cut_end ? 4795 scp->mouse_cut_end : scp->mouse_cut_start) || 4796 ptr >= (scp->mouse_cut_start > scp->mouse_cut_end ? 4797 scp->mouse_cut_start : scp->mouse_cut_end)) { 4798 if (ptr != scp->cursor_pos) 4799 nch = (och & 0xff) | (*ptr & 0xff00); 4800 } 4801 else { 4802 /* are we clear of the cursor image ? */ 4803 if (ptr != scp->cursor_pos) 4804 nch = (och & 0x88ff) | (*ptr & 0x7000)>>4 | (*ptr & 0x0700)<<4; 4805 else { 4806 if (flags & CHAR_CURSOR) 4807 nch = (och & 0x88ff)|(*ptr & 0x7000)>>4|(*ptr & 0x0700)<<4; 4808 else 4809 if (!(flags & BLINK_CURSOR)) 4810 nch = (och & 0xff) | (*ptr & 0xff00); 4811 } 4812 } 4813 if (nch != och) 4814 *(Crtat + (ptr - scp->scr_buf)) = nch; 4815 } 4816} 4817 4818static void 4819remove_cutmarking(scr_stat *scp) 4820{ 4821 scp->mouse_cut_start = scp->mouse_cut_end = NULL; 4822 scp->status &= ~MOUSE_CUTTING; 4823 mark_all(scp); 4824} 4825 4826static void 4827save_palette(void) 4828{ 4829 int i; 4830 4831 outb(PALRADR, 0x00); 4832 for (i=0x00; i<0x300; i++) 4833 palette[i] = inb(PALDATA); 4834 inb(crtc_addr+6); /* reset flip/flop */ 4835} 4836 4837void 4838load_palette(char *palette) 4839{ 4840 int i; 4841 4842 outb(PIXMASK, 0xFF); /* no pixelmask */ 4843 outb(PALWADR, 0x00); 4844 for (i=0x00; i<0x300; i++) 4845 outb(PALDATA, palette[i]); 4846 inb(crtc_addr+6); /* reset flip/flop */ 4847 outb(ATC, 0x20); /* enable palette */ 4848} 4849 4850static void 4851do_bell(scr_stat *scp, int pitch, int duration) 4852{ 4853 if (flags & VISUAL_BELL) { 4854 if (blink_in_progress) 4855 return; 4856 blink_in_progress = 4; 4857 if (scp != cur_console) 4858 blink_in_progress += 2; 4859 blink_screen(cur_console); 4860 } else { 4861 if (scp != cur_console) 4862 pitch *= 2; 4863 sysbeep(pitch, duration); 4864 } 4865} 4866 4867static void 4868blink_screen(void *arg) 4869{ 4870 scr_stat *scp = arg; 4871 4872 if ((scp->status & UNKNOWN_MODE) || (blink_in_progress <= 1)) { 4873 blink_in_progress = FALSE; 4874 mark_all(scp); 4875 if (delayed_next_scr) 4876 switch_scr(scp, delayed_next_scr - 1); 4877 } 4878 else { 4879 if (blink_in_progress & 1) 4880 fillw(kernel_default.std_color | scr_map[0x20], 4881 Crtat, scp->xsize * scp->ysize); 4882 else 4883 fillw(kernel_default.rev_color | scr_map[0x20], 4884 Crtat, scp->xsize * scp->ysize); 4885 blink_in_progress--; 4886 timeout(blink_screen, scp, hz / 10); 4887 } 4888} 4889 4890#ifdef SC_SPLASH_SCREEN 4891static void 4892toggle_splash_screen(scr_stat *scp) 4893{ 4894 static int toggle = 0; 4895 static u_char save_mode; 4896 int s; 4897 4898 if (video_mode_ptr == NULL) 4899 return; 4900 4901 s = splhigh(); 4902 if (toggle) { 4903 scp->mode = save_mode; 4904 scp->status &= ~UNKNOWN_MODE; 4905 set_mode(scp); 4906 load_palette(palette); 4907 toggle = 0; 4908 } 4909 else { 4910 save_mode = scp->mode; 4911 scp->mode = M_VGA_CG320; 4912 scp->status |= UNKNOWN_MODE; 4913 set_mode(scp); 4914 /* load image */ 4915 toggle = 1; 4916 } 4917 splx(s); 4918} 4919#endif 4920#endif /* NSC */ 4921