syscons.c revision 2092
1201052Smarius/*- 2201052Smarius * Copyright (c) 1992-1994 S�ren Schmidt 3201052Smarius * Copyright (c) 1990 The Regents of the University of California. 4201052Smarius * All rights reserved. 5201052Smarius * 6201052Smarius * This code is derived from software contributed to Berkeley by 7201052Smarius * William Jolitz and Don Ahn. 8201052Smarius * 9201052Smarius * Redistribution and use in source and binary forms, with or without 10201052Smarius * modification, are permitted provided that the following conditions 11201052Smarius * are met: 12201052Smarius * 1. Redistributions of source code must retain the above copyright 13201052Smarius * notice, this list of conditions and the following disclaimer. 14201052Smarius * 2. Redistributions in binary form must reproduce the above copyright 15201052Smarius * notice, this list of conditions and the following disclaimer in the 16201052Smarius * documentation and/or other materials provided with the distribution. 17201052Smarius * 3. All advertising materials mentioning features or use of this software 18201052Smarius * must display the following acknowledgement: 19201052Smarius * This product includes software developed by the University of 20201052Smarius * California, Berkeley and its contributors. 21201052Smarius * 4. Neither the name of the University nor the names of its contributors 22201052Smarius * may be used to endorse or promote products derived from this software 23201052Smarius * without specific prior written permission. 24201052Smarius * 25201052Smarius * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 26201052Smarius * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27201052Smarius * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28201052Smarius * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 29201052Smarius * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30201052Smarius * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31201052Smarius * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32201052Smarius * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33201052Smarius * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34201052Smarius * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35201052Smarius * SUCH DAMAGE. 36201052Smarius * 37201052Smarius * $Id: syscons.c,v 1.50 1994/08/17 08:51:59 sos Exp $ 38201052Smarius */ 39201052Smarius 40201052Smarius#include "sc.h" 41201052Smarius 42201052Smarius#if NSC > 0 43201052Smarius 44201052Smarius#include <sys/param.h> 45201052Smarius#include <sys/systm.h> 46201052Smarius#include <sys/conf.h> 47201052Smarius#include <sys/ioctl.h> 48201052Smarius#include <sys/proc.h> 49201052Smarius#include <sys/user.h> 50201052Smarius#include <sys/tty.h> 51201052Smarius#include <sys/uio.h> 52201052Smarius#include <sys/callout.h> 53201052Smarius#include <sys/kernel.h> 54201052Smarius#include <sys/syslog.h> 55201052Smarius#include <sys/errno.h> 56201052Smarius#include <sys/malloc.h> 57201052Smarius#include <machine/console.h> 58201052Smarius#include <machine/psl.h> 59201052Smarius#include <machine/frame.h> 60201052Smarius#include <machine/pc/display.h> 61201052Smarius#include <i386/isa/isa.h> 62201052Smarius#include <i386/isa/isa_device.h> 63201052Smarius#include <i386/isa/timerreg.h> 64201052Smarius#include <i386/isa/kbdtables.h> 65201052Smarius#include <i386/i386/cons.h> 66201052Smarius 67201052Smarius#if !defined(NCONS) 68201052Smarius#define NCONS 12 69201052Smarius#endif 70201052Smarius 71201052Smarius#if !defined(NO_HARDFONTS) 72201052Smarius#include <i386/isa/iso8859.font> 73201052Smarius#endif 74201052Smarius 75201052Smarius/* status flags */ 76201052Smarius#define LOCK_KEY_MASK 0x0000F 77201052Smarius#define LED_MASK 0x00007 78201052Smarius#define UNKNOWN_MODE 0x00010 79201052Smarius#define KBD_RAW_MODE 0x00020 80201052Smarius#define SWITCH_WAIT_REL 0x00040 81201052Smarius#define SWITCH_WAIT_ACQ 0x00080 82201052Smarius 83201052Smarius/* video hardware memory addresses */ 84202003Smarius#define VIDEOMEM 0x000A0000 85202003Smarius 86201052Smarius/* misc defines */ 87201052Smarius#define MAX_ESC_PAR 5 88201052Smarius#define TEXT80x25 1 89201052Smarius#define TEXT80x50 2 90201052Smarius#define LOAD 1 91201052Smarius#define SAVE 0 92201052Smarius#define COL 80 93201052Smarius#define ROW 25 94201052Smarius#define BELL_DURATION 5 95201052Smarius#define BELL_PITCH 800 96202003Smarius#define TIMER_FREQ 1193182 /* should be in isa.h */ 97202003Smarius#define CONSOLE_BUFSIZE 1024 98202003Smarius#define PCBURST 128 99201052Smarius#define FONT_8_LOADED 0x001 100201052Smarius#define FONT_14_LOADED 0x002 101201052Smarius#define FONT_16_LOADED 0x004 102201052Smarius 103201052Smarius/* defines related to hardware addresses */ 104201052Smarius#define MONO_BASE 0x3B4 /* crt controller base mono */ 105201052Smarius#define COLOR_BASE 0x3D4 /* crt controller base color */ 106201052Smarius#define ATC IO_VGA+0x00 /* attribute controller */ 107201052Smarius#define TSIDX IO_VGA+0x04 /* timing sequencer idx */ 108201052Smarius#define TSREG IO_VGA+0x05 /* timing sequencer data */ 109201052Smarius#define PIXMASK IO_VGA+0x06 /* pixel write mask */ 110201052Smarius#define PALRADR IO_VGA+0x07 /* palette read address */ 111201052Smarius#define PALWADR IO_VGA+0x08 /* palette write address */ 112201052Smarius#define PALDATA IO_VGA+0x09 /* palette data register */ 113201052Smarius#define GDCIDX IO_VGA+0x0E /* graph data controller idx */ 114201052Smarius#define GDCREG IO_VGA+0x0F /* graph data controller data */ 115201052Smarius 116201052Smarius/* special characters */ 117201052Smarius#define cntlc 0x03 118201052Smarius#define cntld 0x04 119201052Smarius#define bs 0x08 120201052Smarius#define lf 0x0a 121201052Smarius#define cr 0x0d 122201052Smarius#define del 0x7f 123201052Smarius 124201052Smariustypedef struct term_stat { 125201052Smarius int esc; /* processing escape sequence */ 126201052Smarius int num_param; /* # of parameters to ESC */ 127201052Smarius int last_param; /* last parameter # */ 128201052Smarius int param[MAX_ESC_PAR]; /* contains ESC parameters */ 129201052Smarius int cur_attr; /* current attributes */ 130201052Smarius int std_attr; /* normal attributes */ 131201052Smarius int rev_attr; /* reverse attributes */ 132201052Smarius} term_stat; 133201052Smarius 134201052Smariustypedef struct scr_stat { 135201052Smarius u_short *crt_base; /* address of screen memory */ 136292789Smarius u_short *scr_buf; /* buffer when off screen */ 137201052Smarius u_short *crtat; /* cursor address */ 138201052Smarius int xpos; /* current X position */ 139201052Smarius int ypos; /* current Y position */ 140292789Smarius int xsize; /* X size */ 141225931Smarius int ysize; /* Y size */ 142292789Smarius term_stat term; /* terminal emulation stuff */ 143225931Smarius char cursor_start; /* cursor start line # */ 144292789Smarius char cursor_end; /* cursor end line # */ 145201052Smarius u_char border; /* border color */ 146201052Smarius u_short bell_duration; 147201052Smarius u_short bell_pitch; 148201052Smarius u_short status; /* status (bitfield) */ 149201052Smarius u_short mode; /* mode */ 150201052Smarius pid_t pid; /* pid of controlling proc */ 151201052Smarius struct proc *proc; /* proc* of controlling proc */ 152201052Smarius struct vt_mode smode; /* switch mode */ 153201052Smarius} scr_stat; 154201052Smarius 155201052Smariustypedef struct default_attr { 156201052Smarius int std_attr; /* normal attributes */ 157201052Smarius int rev_attr; /* reverse attributes */ 158292789Smarius} default_attr; 159201052Smarius 160227843Smariusstatic default_attr user_default = { 161201052Smarius (FG_LIGHTGREY | BG_BLACK) << 8, 162201052Smarius (FG_BLACK | BG_LIGHTGREY) << 8 163201052Smarius}; 164201052Smarius 165201052Smariusstatic default_attr kernel_default = { 166201052Smarius (FG_WHITE | BG_BLACK) << 8, 167201052Smarius (FG_BLACK | BG_LIGHTGREY) << 8 168201052Smarius}; 169201052Smarius 170201052Smariusstatic scr_stat console[NCONS]; 171201052Smariusstatic scr_stat *cur_console = &console[0]; 172201052Smariusstatic scr_stat *new_scp, *old_scp; 173201052Smariusstatic term_stat kernel_console; 174201052Smariusstatic default_attr *current_default; 175201052Smariusstatic int console_buffer_count; 176201052Smariusstatic char console_buffer[CONSOLE_BUFSIZE]; 177201052Smariusstatic int switch_in_progress = 0; 178201052Smariusstatic u_short *crtat = 0; 179201052Smariusstatic u_int crtc_addr = MONO_BASE; 180201052Smariusstatic char crtc_vga = 0; 181201052Smariusstatic u_char shfts = 0, ctls = 0, alts = 0, agrs = 0, metas = 0; 182201052Smariusstatic u_char nlkcnt = 0, clkcnt = 0, slkcnt = 0, alkcnt = 0; 183202003Smariusstatic char *font_8 = NULL, *font_14 = NULL, *font_16 = NULL; 184202003Smariusstatic int fonts_loaded = 0; 185202003Smariusstatic char palette[3*256]; 186202003Smariusstatic const u_int n_fkey_tab = sizeof(fkey_tab) / sizeof(*fkey_tab); 187202003Smariusstatic int cur_cursor_pos = -1; 188202003Smariusstatic char in_putc = 0; 189202003Smariusstatic char polling = 0; 190201052Smarius#if ASYNCH 191201052Smariusstatic u_char kbd_reply = 0; 192201052Smarius#endif 193201052Smariusstatic int delayed_next_scr; 194201052Smariusstatic char saved_console = -1; /* saved console number */ 195201052Smariusstatic long scrn_blank_time = 0; /* screen saver timeout value */ 196201052Smariusstatic int scrn_blanked = 0; /* screen saver active flag */ 197201052Smariusstatic int scrn_saver = 0; /* screen saver routine */ 198201052Smariusstatic long scrn_time_stamp; 199201052Smariusstatic u_char scr_map[256]; 200201052Smarius 201201052Smariusextern int hz; 202201052Smariusextern struct timeval time; 203201052Smarius 204201052Smarius/* function prototypes */ 205201052Smariusint pcprobe(struct isa_device *dev); 206201052Smariusint pcattach(struct isa_device *dev); 207201052Smariusint pcopen(dev_t dev, int flag, int mode, struct proc *p); 208201052Smariusint pcclose(dev_t dev, int flag, int mode, struct proc *p); 209201052Smariusint pcread(dev_t dev, struct uio *uio, int flag); 210201052Smariusint pcwrite(dev_t dev, struct uio *uio, int flag); 211201052Smariusint pcparam(struct tty *tp, struct termios *t); 212201052Smariusint pcioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p); 213201052Smariusvoid pcxint(dev_t dev); 214201052Smariusvoid pcstart(struct tty *tp); 215201052Smariusvoid pccnprobe(struct consdev *cp); 216201052Smariusvoid pccninit(struct consdev *cp); 217201052Smariusvoid pccnputc(dev_t dev, char c); 218201052Smariusint pccngetc(dev_t dev); 219201052Smariusvoid scintr(int unit); 220201052Smariusint pcmmap(dev_t dev, int offset, int nprot); 221201052Smariusu_int sgetc(int noblock); 222201052Smariusint getchar(void); 223201052Smariusstatic void scinit(void); 224201052Smariusstatic void scput(u_char c); 225201052Smariusstatic u_int scgetc(int noblock); 226201052Smariusstatic struct tty *get_tty_ptr(dev_t dev); 227201052Smariusstatic scr_stat *get_scr_stat(dev_t dev); 228201052Smariusstatic int get_scr_num(); 229201052Smariusstatic void cursor_shape(int start, int end); 230201052Smariusstatic void get_cursor_shape(int *start, int *end); 231201052Smariusstatic void cursor_pos(int force); 232201052Smariusstatic void clear_screen(scr_stat *scp); 233201052Smariusstatic int switch_scr(u_int next_scr); 234201052Smariusstatic void exchange_scr(void); 235201052Smariusstatic void move_crsr(scr_stat *scp, int x, int y); 236201052Smariusstatic void move_up(u_short *s, u_short *d, u_int len); 237201052Smariusstatic void move_down(u_short *s, u_short *d, u_int len); 238201052Smariusstatic void scan_esc(scr_stat *scp, u_char c); 239201052Smariusstatic void ansi_put(scr_stat *scp, u_char c); 240201052Smariusstatic u_char *get_fstr(u_int c, u_int *len); 241201052Smariusstatic void update_leds(int which); 242201052Smariusstatic void kbd_wait(void); 243201052Smariusstatic void kbd_cmd(u_char command); 244201052Smariusstatic void set_mode(scr_stat *scp); 245242625Sdimstatic void set_border(int color); 246201052Smariusstatic void copy_font(int direction, int segment, int size, char* font); 247201052Smariusstatic void save_palette(void); 248201052Smariusstatic void load_palette(void); 249201052Smariusstatic void change_winsize(struct tty *tp, int x, int y); 250201052Smarius 251201052Smarius/* available screen savers */ 252201052Smariusstatic void none_saver(int test); 253201052Smariusstatic void blank_saver(int test); 254201052Smariusstatic void fade_saver(int test); 255201052Smariusstatic void star_saver(int test); 256201052Smariusstatic void snake_saver(int test); 257201052Smarius 258201052Smariusstatic const struct { 259201052Smarius char *name; 260201052Smarius void (*routine)(); 261201052Smarius} screen_savers[] = { 262201052Smarius { "none", none_saver }, /* 0 */ 263201052Smarius { "blank", blank_saver }, /* 1 */ 264201052Smarius { "fade", fade_saver }, /* 2 */ 265201052Smarius { "star", star_saver }, /* 3 */ 266201052Smarius { "snake", snake_saver }, /* 4 */ 267201052Smarius}; 268201052Smarius#define SCRN_SAVER(arg) (*screen_savers[scrn_saver].routine)(arg) 269201052Smarius#define NUM_SCRN_SAVERS (sizeof(screen_savers) / sizeof(screen_savers[0])) 270201052Smarius 271201052Smarius/* OS specific stuff */ 272201052Smarius#if 0 273201052Smarius#define VIRTUAL_TTY(x) (pccons[x] = ttymalloc(pccons[x])) 274201052Smarius#define CONSOLE_TTY (pccons[NCONS] = ttymalloc(pccons[NCONS])) 275201052Smariusstruct tty *pccons[NCONS+1]; 276201052Smarius#else 277201052Smarius#define VIRTUAL_TTY(x) &pccons[x] 278201052Smarius#define CONSOLE_TTY &pccons[NCONS] 279201052Smariusstruct tty pccons[NCONS+1]; 280201052Smarius#endif 281201052Smarius#define timeout_t timeout_func_t 282201052Smarius#define MONO_BUF (KERNBASE+0xB0000) 283201052Smarius#define CGA_BUF (KERNBASE+0xB8000) 284201052Smarius#include "ddb.h" 285201052Smarius#if NDDB > 0 286201052Smarius#define DDB 1 287201052Smarius#endif 288201052Smariusu_short *Crtat = (u_short *)MONO_BUF; 289201052Smariusvoid consinit(void) {scinit();} 290201052Smarius 291201052Smariusstruct isa_driver scdriver = { 292292789Smarius pcprobe, pcattach, "sc", 293201052Smarius}; 294201052Smarius 295201052Smarius 296201200Smariusint 297201052Smariuspcprobe(struct isa_device *dev) 298201052Smarius{ 299201052Smarius int i, retries = 5; 300201052Smarius unsigned char val; 301201052Smarius 302201052Smarius /* Enable interrupts and keyboard controller */ 303201052Smarius kbd_wait(); 304201052Smarius outb(KB_STAT, KB_WRITE); 305201052Smarius kbd_wait(); 306201052Smarius outb(KB_DATA, KB_MODE); 307201052Smarius 308201052Smarius /* flush any noise in the buffer */ 309201052Smarius while (inb(KB_STAT) & KB_BUF_FULL) { 310201052Smarius DELAY(10); 311201052Smarius (void) inb(KB_DATA); 312201052Smarius } 313201052Smarius 314201052Smarius /* Reset keyboard hardware */ 315201052Smarius while (retries--) { 316201052Smarius kbd_wait(); 317201052Smarius outb(KB_DATA, KB_RESET); 318201052Smarius for (i=0; i<100000; i++) { 319201052Smarius DELAY(10); 320201052Smarius val = inb(KB_DATA); 321201052Smarius if (val == KB_ACK || val == KB_ECHO) 322201052Smarius goto gotres; 323201052Smarius if (val == KB_RESEND) 324201052Smarius break; 325201052Smarius } 326201052Smarius } 327201052Smariusgotres: 328201052Smarius if (!retries) 329201052Smarius printf("scprobe: keyboard won't accept RESET command\n"); 330219785Smarius else { 331201052Smariusgotack: 332201052Smarius DELAY(10); 333201052Smarius while ((inb(KB_STAT) & KB_BUF_FULL) == 0) DELAY(10); 334201052Smarius DELAY(10); 335201052Smarius val = inb(KB_DATA); 336201052Smarius if (val == KB_ACK) 337201052Smarius goto gotack; 338201052Smarius if (val != KB_RESET_DONE) 339201052Smarius printf("scprobe: keyboard RESET failed %02x\n", val); 340201052Smarius } 341201052Smarius return (IO_KBDSIZE); 342201052Smarius} 343201052Smarius 344201052Smarius 345201052Smariusint 346201052Smariuspcattach(struct isa_device *dev) 347201052Smarius{ 348201052Smarius scr_stat *scp; 349201052Smarius int start = -1, end = -1, i; 350201052Smarius 351201052Smarius printf("sc%d: ", dev->id_unit); 352201052Smarius if (crtc_vga) 353201052Smarius if (crtc_addr == MONO_BASE) 354201052Smarius printf("VGA mono"); 355201052Smarius else 356201052Smarius printf("VGA color"); 357201052Smarius else 358201052Smarius if (crtc_addr == MONO_BASE) 359201052Smarius printf("MDA/hercules"); 360201052Smarius else 361201052Smarius printf("CGA/EGA"); 362201052Smarius 363201052Smarius if (NCONS > 1) 364201052Smarius printf(" <%d virtual consoles>\n", NCONS); 365201052Smarius else 366201052Smarius printf("\n"); 367201052Smarius#if defined(FAT_CURSOR) 368201052Smarius start = 0; 369201052Smarius end = 18; 370201052Smarius if (crtc_vga) { 371201052Smarius#else 372201052Smarius if (crtc_vga) { 373201052Smarius get_cursor_shape(&start, &end); 374201052Smarius#endif 375201052Smarius#if !defined(NO_HARDFONTS) 376201052Smarius font_8 = font_8x8; 377201052Smarius font_14 = font_8x14; 378201052Smarius font_16 = font_8x16; 379201052Smarius fonts_loaded = FONT_8_LOADED|FONT_14_LOADED|FONT_16_LOADED; 380201052Smarius copy_font(LOAD, 1, 8, font_8); 381201052Smarius copy_font(LOAD, 2, 14, font_14); 382201052Smarius copy_font(LOAD, 0, 16, font_16); 383201052Smarius#else 384201052Smarius font_8 = (char *)malloc(8*256, M_DEVBUF, M_NOWAIT); 385201052Smarius font_14 = (char *)malloc(14*256, M_DEVBUF, M_NOWAIT); 386201052Smarius font_16 = (char *)malloc(16*256, M_DEVBUF, M_NOWAIT); 387201052Smarius copy_font(SAVE, 0, 16, font_16); 388201052Smarius fonts_loaded = FONT_16_LOADED; 389201052Smarius#endif 390201052Smarius save_palette(); 391201052Smarius } 392201052Smarius current_default = &user_default; 393201052Smarius for (i = 0; i < NCONS; i++) { 394201052Smarius scp = &console[i]; 395201052Smarius scp->scr_buf = (u_short *)malloc(COL * ROW * 2, 396201052Smarius M_DEVBUF, M_NOWAIT); 397201052Smarius scp->mode = TEXT80x25; 398201052Smarius scp->term.esc = 0; 399201052Smarius scp->term.std_attr = current_default->std_attr; 400201052Smarius scp->term.rev_attr = current_default->rev_attr; 401201052Smarius scp->term.cur_attr = scp->term.std_attr; 402201052Smarius scp->border = BG_BLACK; 403201052Smarius scp->cursor_start = start; 404201052Smarius scp->cursor_end = end; 405201052Smarius scp->xsize = COL; 406201052Smarius scp->ysize = ROW; 407201052Smarius scp->bell_pitch = BELL_PITCH; 408201052Smarius scp->bell_duration = BELL_DURATION; 409201052Smarius scp->status = NLKED; 410201052Smarius scp->pid = 0; 411201052Smarius scp->proc = NULL; 412201052Smarius scp->smode.mode = VT_AUTO; 413201052Smarius if (i > 0) { 414201052Smarius scp->crt_base = scp->crtat = scp->scr_buf; 415201052Smarius fillw(scp->term.cur_attr|scr_map[0x20], 416201052Smarius scp->scr_buf, COL*ROW); 417201052Smarius } 418201052Smarius } 419201052Smarius /* get cursor going */ 420201052Smarius#if defined(FAT_CURSOR) 421201052Smarius cursor_shape(console[0].cursor_start, 422201052Smarius console[0].cursor_end); 423201052Smarius#endif 424201052Smarius cursor_pos(1); 425201052Smarius update_leds(console[0].status); 426201052Smarius return 0; 427201052Smarius} 428201052Smarius 429201052Smarius 430201052Smariusstatic struct tty 431201052Smarius*get_tty_ptr(dev_t dev) 432201052Smarius{ 433201052Smarius int unit = minor(dev); 434201052Smarius 435201052Smarius if (unit > NCONS) 436201052Smarius return(NULL); 437201052Smarius if (unit == NCONS) 438233701Smarius return(CONSOLE_TTY); 439233701Smarius return(VIRTUAL_TTY(unit)); 440201052Smarius} 441201052Smarius 442233701Smarius 443201052Smariusstatic scr_stat 444201052Smarius*get_scr_stat(dev_t dev) 445201052Smarius{ 446201052Smarius int unit = minor(dev); 447201052Smarius 448201052Smarius if (unit > NCONS) 449201052Smarius return(NULL); 450201052Smarius if (unit == NCONS) 451201052Smarius return(&console[0]); 452201052Smarius return(&console[unit]); 453201052Smarius} 454201052Smarius 455201052Smarius 456201052Smariusstatic int 457201052Smariusget_scr_num() 458201052Smarius{ 459201052Smarius int i = 0; 460201052Smarius 461201052Smarius while ((i < NCONS) && (cur_console != &console[i])) i++; 462201052Smarius return i < NCONS ? i : 0; 463201052Smarius} 464201052Smarius 465201052Smarius 466201052Smariusint 467201052Smariuspcopen(dev_t dev, int flag, int mode, struct proc *p) 468201052Smarius{ 469201052Smarius struct tty *tp = get_tty_ptr(dev); 470201052Smarius 471201052Smarius if (!tp) 472201052Smarius return(ENXIO); 473201052Smarius 474201052Smarius tp->t_oproc = pcstart; 475201052Smarius tp->t_param = pcparam; 476201052Smarius tp->t_dev = dev; 477201052Smarius if (!(tp->t_state & TS_ISOPEN)) { 478201052Smarius ttychars(tp); 479201052Smarius tp->t_iflag = TTYDEF_IFLAG; 480201052Smarius tp->t_oflag = TTYDEF_OFLAG; 481201052Smarius tp->t_cflag = TTYDEF_CFLAG; 482201052Smarius tp->t_lflag = TTYDEF_LFLAG; 483201052Smarius tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; 484201052Smarius pcparam(tp, &tp->t_termios); 485201052Smarius ttsetwater(tp); 486201052Smarius } else if (tp->t_state&TS_XCLUDE && p->p_ucred->cr_uid != 0) 487201052Smarius return(EBUSY); 488201052Smarius tp->t_state |= TS_CARR_ON; 489201052Smarius tp->t_cflag |= CLOCAL; 490201052Smarius return((*linesw[tp->t_line].l_open)(dev, tp)); 491201052Smarius} 492201052Smarius 493201052Smarius 494201052Smariusint 495201052Smariuspcclose(dev_t dev, int flag, int mode, struct proc *p) 496201052Smarius{ 497201052Smarius struct tty *tp = get_tty_ptr(dev); 498201052Smarius struct scr_stat *scp; 499201052Smarius 500201052Smarius if (!tp) 501201052Smarius return(ENXIO); 502201052Smarius if (minor(dev) < NCONS) { 503201052Smarius scp = get_scr_stat(tp->t_dev); 504201052Smarius if (scp->status & SWITCH_WAIT_ACQ) 505201052Smarius wakeup((caddr_t)&scp->smode); 506201052Smarius scp->pid = 0; 507201052Smarius scp->proc = NULL; 508201052Smarius scp->smode.mode = VT_AUTO; 509201052Smarius } 510201052Smarius (*linesw[tp->t_line].l_close)(tp, flag); 511201052Smarius ttyclose(tp); 512201052Smarius return(0); 513201052Smarius} 514201052Smarius 515201052Smarius 516201052Smariusint 517201052Smariuspcread(dev_t dev, struct uio *uio, int flag) 518201052Smarius{ 519201052Smarius struct tty *tp = get_tty_ptr(dev); 520201052Smarius 521201052Smarius if (!tp) 522201052Smarius return(ENXIO); 523201052Smarius return((*linesw[tp->t_line].l_read)(tp, uio, flag)); 524201052Smarius} 525201052Smarius 526201052Smarius 527201052Smariusint 528201052Smariuspcwrite(dev_t dev, struct uio *uio, int flag) 529201052Smarius{ 530201052Smarius struct tty *tp = get_tty_ptr(dev); 531201052Smarius 532201052Smarius if (!tp) 533201052Smarius return(ENXIO); 534201052Smarius return((*linesw[tp->t_line].l_write)(tp, uio, flag)); 535201052Smarius} 536201052Smarius 537201052Smarius 538201052Smariusvoid 539201052Smariusscintr(int unit) 540201052Smarius{ 541201052Smarius static struct tty *cur_tty; 542201052Smarius int c, len; 543201052Smarius u_char *cp; 544201052Smarius 545201052Smarius /* make screensaver happy */ 546201052Smarius scrn_time_stamp = time.tv_sec; 547201052Smarius if (scrn_blanked) 548201052Smarius SCRN_SAVER(0); 549201052Smarius 550201052Smarius c = scgetc(1); 551201052Smarius 552201052Smarius cur_tty = VIRTUAL_TTY(get_scr_num()); 553201052Smarius if (!(cur_tty->t_state & TS_ISOPEN)) 554201052Smarius cur_tty = CONSOLE_TTY; 555201052Smarius 556201052Smarius if (!(cur_tty->t_state & TS_ISOPEN) || polling) 557201052Smarius return; 558201052Smarius 559201052Smarius switch (c & 0xff00) { 560201052Smarius case 0x0000: /* normal key */ 561201052Smarius (*linesw[cur_tty->t_line].l_rint)(c & 0xFF, cur_tty); 562201052Smarius break; 563201052Smarius case NOKEY: /* nothing there */ 564201052Smarius break; 565201052Smarius case FKEY: /* function key, return string */ 566201052Smarius if (cp = get_fstr((u_int)c, (u_int *)&len)) { 567201052Smarius while (len-- > 0) 568201052Smarius (*linesw[cur_tty->t_line].l_rint) 569201052Smarius (*cp++ & 0xFF, cur_tty); 570201052Smarius } 571201052Smarius break; 572201052Smarius case MKEY: /* meta is active, prepend ESC */ 573201052Smarius (*linesw[cur_tty->t_line].l_rint)(0x1b, cur_tty); 574201052Smarius (*linesw[cur_tty->t_line].l_rint)(c & 0xFF, cur_tty); 575201052Smarius break; 576201052Smarius } 577201052Smarius} 578201052Smarius 579201052Smarius 580201052Smariusint 581201052Smariuspcparam(struct tty *tp, struct termios *t) 582201052Smarius{ 583201052Smarius int cflag = t->c_cflag; 584201052Smarius 585201052Smarius /* and copy to tty */ 586201052Smarius tp->t_ispeed = t->c_ispeed; 587201052Smarius tp->t_ospeed = t->c_ospeed; 588201052Smarius tp->t_cflag = cflag; 589201052Smarius return 0; 590201052Smarius} 591201052Smarius 592201052Smarius 593201052Smariusint 594201052Smariuspcioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p) 595201052Smarius{ 596201052Smarius int i, error; 597201052Smarius struct tty *tp; 598201052Smarius struct trapframe *fp; 599201052Smarius scr_stat *scp; 600201052Smarius 601201052Smarius tp = get_tty_ptr(dev); 602201052Smarius if (!tp) 603201052Smarius return ENXIO; 604201052Smarius scp = get_scr_stat(tp->t_dev); 605201052Smarius 606201052Smarius switch (cmd) { /* process console hardware related ioctl's */ 607201052Smarius 608201052Smarius case CONS_BLANKTIME: /* set screen saver timeout (0 = no saver) */ 609201052Smarius scrn_blank_time = *(int*)data; 610201052Smarius return 0; 611201052Smarius case CONS_SSAVER: /* set screen saver */ 612201052Smarius { 613201052Smarius register ssaver_t *sav = (ssaver_t *)data; 614201052Smarius if (sav->num < 0 || sav->num >= NUM_SCRN_SAVERS) 615201052Smarius return EIO; 616201052Smarius SCRN_SAVER(0); 617201052Smarius scrn_saver = sav->num; 618201052Smarius scrn_blank_time = sav->time; 619201052Smarius return 0; 620201052Smarius } 621201052Smarius case CONS_GSAVER: /* get screen saver info */ 622201052Smarius { 623201052Smarius register ssaver_t *sav = (ssaver_t *)data; 624201052Smarius if (sav->num < 0) 625201052Smarius sav->num = scrn_saver; 626201052Smarius else if (sav->num >= NUM_SCRN_SAVERS) 627201052Smarius return EIO; 628201052Smarius sav->time = scrn_blank_time; 629201052Smarius strcpy(sav->name, screen_savers[sav->num].name); 630201052Smarius return 0; 631201052Smarius } 632201052Smarius case CONS_80x25TEXT: /* set 80x25 text mode */ 633201052Smarius if (!crtc_vga) 634201052Smarius return ENXIO; 635201052Smarius scp->mode = TEXT80x25; 636201052Smarius scp->ysize = 25; 637201052Smarius free(scp->scr_buf, M_DEVBUF); 638201052Smarius scp->scr_buf = (u_short *)malloc(scp->xsize*scp->ysize*2, 639201052Smarius M_DEVBUF, M_NOWAIT); 640201052Smarius if (scp != cur_console) 641201052Smarius scp->crt_base = scp->scr_buf; 642201052Smarius set_mode(scp); 643201052Smarius clear_screen(scp); 644201052Smarius change_winsize(tp, scp->xsize, scp->ysize); 645201052Smarius return 0; 646201052Smarius 647201052Smarius case CONS_80x50TEXT: /* set 80x50 text mode */ 648201052Smarius if (!crtc_vga) 649201052Smarius return ENXIO; 650201052Smarius /* is there a 8x8 font loaded ? */ 651201052Smarius if (fonts_loaded & FONT_8_LOADED) { 652201052Smarius scp->mode = TEXT80x50; 653201052Smarius scp->ysize = 50; 654201052Smarius free(scp->scr_buf, M_DEVBUF); 655201052Smarius scp->scr_buf = 656201052Smarius (u_short *)malloc(scp->xsize * scp->ysize * 2, 657201052Smarius M_DEVBUF, M_NOWAIT); 658223960Smarius if (scp != cur_console) 659201052Smarius scp->crt_base = scp->scr_buf; 660201052Smarius set_mode(scp); 661201052Smarius clear_screen(scp); 662201052Smarius change_winsize(tp, scp->xsize, scp->ysize); 663201052Smarius return 0; 664201052Smarius } 665201052Smarius else 666201052Smarius return EINVAL; 667201052Smarius 668201052Smarius case CONS_GETVERS: /* get version number */ 669201052Smarius *(int*)data = 0x103; /* version 1.3 */ 670201052Smarius return 0; 671201052Smarius 672201052Smarius case CONS_GETINFO: /* get current (virtual) console info */ 673201052Smarius { 674201052Smarius vid_info_t *ptr = (vid_info_t*)data; 675201052Smarius if (ptr->size == sizeof(struct vid_info)) { 676201052Smarius ptr->m_num = get_scr_num(); 677201052Smarius ptr->mv_col = scp->xpos; 678223960Smarius ptr->mv_row = scp->ypos; 679223960Smarius ptr->mv_csz = scp->xsize; 680223960Smarius ptr->mv_rsz = scp->ysize; 681223960Smarius ptr->mv_norm.fore = (scp->term.std_attr & 0x0f00)>>8; 682223960Smarius ptr->mv_norm.back = (scp->term.std_attr & 0xf000)>>12; 683223960Smarius ptr->mv_rev.fore = (scp->term.rev_attr & 0x0f00)>>8; 684223960Smarius ptr->mv_rev.back = (scp->term.rev_attr & 0xf000)>>12; 685223960Smarius ptr->mv_grfc.fore = 0; /* not supported */ 686223960Smarius ptr->mv_grfc.back = 0; /* not supported */ 687201052Smarius ptr->mv_ovscan = scp->border; 688201052Smarius ptr->mk_keylock = scp->status & LOCK_KEY_MASK; 689201052Smarius return 0; 690201052Smarius } 691201052Smarius return EINVAL; 692201052Smarius } 693201052Smarius 694201052Smarius case VT_SETMODE: /* set screen switcher mode */ 695201052Smarius bcopy(data, &scp->smode, sizeof(struct vt_mode)); 696201052Smarius if (scp->smode.mode == VT_PROCESS) { 697201052Smarius scp->proc = p; 698201052Smarius scp->pid = scp->proc->p_pid; 699201052Smarius } 700201052Smarius return 0; 701201052Smarius 702201052Smarius case VT_GETMODE: /* get screen switcher mode */ 703201052Smarius bcopy(&scp->smode, data, sizeof(struct vt_mode)); 704201052Smarius return 0; 705201052Smarius 706201052Smarius case VT_RELDISP: /* screen switcher ioctl */ 707201052Smarius switch(*data) { 708201052Smarius case VT_FALSE: /* user refuses to release screen, abort */ 709201052Smarius if (scp == old_scp && (scp->status & SWITCH_WAIT_REL)) { 710292789Smarius old_scp->status &= ~SWITCH_WAIT_REL; 711201052Smarius switch_in_progress = 0; 712201052Smarius return 0; 713201052Smarius } 714201052Smarius return EINVAL; 715292789Smarius 716233421Smarius case VT_TRUE: /* user has released screen, go on */ 717201052Smarius if (scp == old_scp && (scp->status & SWITCH_WAIT_REL)) { 718292789Smarius scp->status &= ~SWITCH_WAIT_REL; 719225931Smarius exchange_scr(); 720292789Smarius if (new_scp->smode.mode == VT_PROCESS) { 721292789Smarius new_scp->status |= SWITCH_WAIT_ACQ; 722201052Smarius psignal(new_scp->proc, 723292789Smarius new_scp->smode.acqsig); 724292789Smarius } 725201052Smarius else 726201052Smarius switch_in_progress = 0; 727201052Smarius return 0; 728201052Smarius } 729201052Smarius return EINVAL; 730201052Smarius 731201052Smarius case VT_ACKACQ: /* acquire acknowledged, switch completed */ 732201052Smarius if (scp == new_scp && (scp->status & SWITCH_WAIT_ACQ)) { 733201052Smarius scp->status &= ~SWITCH_WAIT_ACQ; 734201052Smarius switch_in_progress = 0; 735201052Smarius return 0; 736201052Smarius } 737201052Smarius return EINVAL; 738201052Smarius 739201052Smarius default: 740201052Smarius return EINVAL; 741201052Smarius } 742201052Smarius /* NOT REACHED */ 743201052Smarius 744201052Smarius case VT_OPENQRY: /* return free virtual console */ 745201052Smarius for (i = 0; i < NCONS; i++) { 746201052Smarius tp = VIRTUAL_TTY(i); 747201052Smarius if (!(tp->t_state & TS_ISOPEN)) { 748201052Smarius *data = i + 1; 749201052Smarius return 0; 750201052Smarius } 751201052Smarius } 752201052Smarius return EINVAL; 753201052Smarius 754201052Smarius case VT_ACTIVATE: /* switch to screen *data */ 755201052Smarius return switch_scr((*data) - 1); 756201052Smarius 757201052Smarius case VT_WAITACTIVE: /* wait for switch to occur */ 758201052Smarius if (*data > NCONS) 759201052Smarius return EINVAL; 760201052Smarius if (minor(dev) == (*data) - 1) 761201052Smarius return 0; 762201052Smarius if (*data == 0) { 763201052Smarius if (scp == cur_console) 764201052Smarius return 0; 765201052Smarius while ((error=tsleep((caddr_t)&scp->smode, 766201052Smarius PZERO|PCATCH, "waitvt", 0)) == ERESTART) ; 767201052Smarius } 768201052Smarius else 769201052Smarius while ((error=tsleep( 770201052Smarius (caddr_t)&console[*(data-1)].smode, 771201052Smarius PZERO|PCATCH, "waitvt", 0)) == ERESTART) ; 772201052Smarius return error; 773216961Smarius 774201052Smarius case VT_GETACTIVE: 775201052Smarius *data = get_scr_num()+1; 776201052Smarius return 0; 777201052Smarius 778201052Smarius case KDENABIO: /* allow io operations */ 779201052Smarius fp = (struct trapframe *)p->p_md.md_regs; 780201052Smarius fp->tf_eflags |= PSL_IOPL; 781201052Smarius return 0; 782201052Smarius 783201052Smarius case KDDISABIO: /* disallow io operations (default) */ 784201052Smarius fp = (struct trapframe *)p->p_md.md_regs; 785201052Smarius fp->tf_eflags &= ~PSL_IOPL; 786201052Smarius return 0; 787201052Smarius 788201052Smarius case KDSETMODE: /* set current mode of this (virtual) console */ 789203094Smarius switch (*data) { 790201052Smarius case KD_TEXT: /* switch to TEXT (known) mode */ 791201052Smarius /* restore fonts & palette ! */ 792201052Smarius if (crtc_vga) { 793201052Smarius copy_font(LOAD, 0, 16, font_16); 794201052Smarius copy_font(LOAD, 1, 8, font_8); 795201052Smarius copy_font(LOAD, 2, 14, font_14); 796201052Smarius load_palette(); 797201052Smarius } 798201052Smarius /* FALL THROUGH */ 799201052Smarius 800201052Smarius case KD_TEXT1: /* switch to TEXT (known) mode */ 801201052Smarius /* no restore fonts & palette */ 802201052Smarius scp->status &= ~UNKNOWN_MODE; 803201052Smarius set_mode(scp); 804201052Smarius clear_screen(scp); 805201052Smarius return 0; 806201052Smarius 807201052Smarius case KD_GRAPHICS:/* switch to GRAPHICS (unknown) mode */ 808201052Smarius scp->status |= UNKNOWN_MODE; 809201052Smarius return 0; 810201052Smarius default: 811201052Smarius return EINVAL; 812201052Smarius } 813201052Smarius /* NOT REACHED */ 814201052Smarius 815201052Smarius case KDGETMODE: /* get current mode of this (virtual) console */ 816201052Smarius *data = (scp->status & UNKNOWN_MODE) ? KD_GRAPHICS : KD_TEXT; 817201052Smarius return 0; 818201052Smarius 819201052Smarius case KDSBORDER: /* set border color of this (virtual) console */ 820201052Smarius if (!crtc_vga) 821201052Smarius return ENXIO; 822201052Smarius scp->border = *data; 823201052Smarius if (scp == cur_console) 824201052Smarius set_border(scp->border); 825201052Smarius return 0; 826201052Smarius 827201052Smarius case KDSKBSTATE: /* set keyboard state (locks) */ 828201052Smarius if (*data >= 0 && *data <= LOCK_KEY_MASK) { 829201052Smarius scp->status &= ~LOCK_KEY_MASK; 830201052Smarius scp->status |= *data; 831201052Smarius if (scp == cur_console) 832201052Smarius update_leds(scp->status); 833201052Smarius return 0; 834201052Smarius } 835201052Smarius return EINVAL; 836201052Smarius 837201052Smarius case KDGKBSTATE: /* get keyboard state (locks) */ 838201052Smarius *data = scp->status & LOCK_KEY_MASK; 839201052Smarius return 0; 840201052Smarius 841201052Smarius case KDSETRAD: /* set keyboard repeat & delay rates */ 842201052Smarius if (*data & 0x80) 843201052Smarius return EINVAL; 844201052Smarius i = spltty(); 845201052Smarius kbd_cmd(KB_SETRAD); 846201052Smarius kbd_cmd(*data); 847201052Smarius splx(i); 848201052Smarius return 0; 849201052Smarius 850201052Smarius case KDSKBMODE: /* set keyboard mode */ 851201052Smarius switch (*data) { 852201052Smarius case K_RAW: /* switch to RAW scancode mode */ 853201052Smarius scp->status |= KBD_RAW_MODE; 854201052Smarius return 0; 855201052Smarius 856201052Smarius case K_XLATE: /* switch to XLT ascii mode */ 857201052Smarius if (scp == cur_console && scp->status == KBD_RAW_MODE) 858201052Smarius shfts = ctls = alts = agrs = metas = 0; 859201052Smarius scp->status &= ~KBD_RAW_MODE; 860201052Smarius return 0; 861201052Smarius default: 862201052Smarius return EINVAL; 863201052Smarius } 864201052Smarius /* NOT REACHED */ 865201052Smarius 866201052Smarius case KDGKBMODE: /* get keyboard mode */ 867201052Smarius *data = (scp->status & KBD_RAW_MODE) ? K_RAW : K_XLATE; 868201052Smarius return 0; 869201052Smarius 870201052Smarius case KDMKTONE: /* sound the bell */ 871201052Smarius if (scp == cur_console) 872201052Smarius sysbeep(scp->bell_pitch, scp->bell_duration); 873201052Smarius return 0; 874201052Smarius 875201052Smarius case KIOCSOUND: /* make tone (*data) hz */ 876201052Smarius if (scp == cur_console) { 877201052Smarius if (*(int*)data) { 878201052Smarius int pitch = TIMER_FREQ/(*(int*)data); 879201052Smarius /* set command for counter 2, 2 byte write */ 880201052Smarius if (acquire_timer2(TIMER_16BIT|TIMER_SQWAVE)) { 881201052Smarius return EBUSY; 882201052Smarius } 883201052Smarius /* set pitch */ 884201052Smarius outb(TIMER_CNTR2, pitch); 885201052Smarius outb(TIMER_CNTR2, (pitch>>8)); 886201052Smarius /* enable counter 2 output to speaker */ 887201052Smarius outb(IO_PPI, inb(IO_PPI) | 3); 888201052Smarius } 889201052Smarius else { 890201052Smarius /* disable counter 2 output to speaker */ 891201052Smarius outb(IO_PPI, inb(IO_PPI) & 0xFC); 892201052Smarius release_timer2(); 893201052Smarius } 894201052Smarius } 895201052Smarius return 0; 896201052Smarius 897201052Smarius case KDGKBTYPE: /* get keyboard type */ 898201052Smarius *data = 0; /* type not known (yet) */ 899201052Smarius return 0; 900201052Smarius 901201052Smarius case KDSETLED: /* set keyboard LED status */ 902201052Smarius if (*data >= 0 && *data <= LED_MASK) { 903201052Smarius scp->status &= ~LED_MASK; 904201052Smarius scp->status |= *data; 905201052Smarius if (scp == cur_console) 906201052Smarius update_leds(scp->status); 907201052Smarius return 0; 908201052Smarius } 909201052Smarius return EINVAL; 910201052Smarius 911201052Smarius case KDGETLED: /* get keyboard LED status */ 912201052Smarius *data = scp->status & LED_MASK; 913201052Smarius return 0; 914201052Smarius 915201052Smarius case GETFKEY: /* get functionkey string */ 916201052Smarius if (*(u_short*)data < n_fkey_tab) { 917201052Smarius fkeyarg_t *ptr = (fkeyarg_t*)data; 918201052Smarius bcopy(&fkey_tab[ptr->keynum].str, 919201052Smarius ptr->keydef, 920201052Smarius fkey_tab[ptr->keynum].len); 921201052Smarius ptr->flen = fkey_tab[ptr->keynum].len; 922201052Smarius return 0; 923201052Smarius } 924201052Smarius else 925201052Smarius return EINVAL; 926201052Smarius 927201052Smarius case SETFKEY: /* set functionkey string */ 928201052Smarius if (*(u_short*)data < n_fkey_tab) { 929201052Smarius fkeyarg_t *ptr = (fkeyarg_t*)data; 930201052Smarius bcopy(ptr->keydef, 931201052Smarius &fkey_tab[ptr->keynum].str, 932201052Smarius min(ptr->flen, MAXFK)); 933201052Smarius fkey_tab[ptr->keynum].len = min(ptr->flen, MAXFK); 934201052Smarius return 0; 935201052Smarius } 936201052Smarius else 937201052Smarius return EINVAL; 938201052Smarius 939201052Smarius case GIO_SCRNMAP: /* get output translation table */ 940201052Smarius bcopy(&scr_map, data, sizeof(scr_map)); 941201052Smarius return 0; 942201052Smarius 943201052Smarius case PIO_SCRNMAP: /* set output translation table */ 944201052Smarius bcopy(data, &scr_map, sizeof(scr_map)); 945201052Smarius return 0; 946201052Smarius 947201052Smarius case GIO_KEYMAP: /* get keyboard translation table */ 948201052Smarius bcopy(&key_map, data, sizeof(key_map)); 949201052Smarius return 0; 950201052Smarius 951201052Smarius case PIO_KEYMAP: /* set keyboard translation table */ 952201052Smarius bcopy(data, &key_map, sizeof(key_map)); 953201052Smarius return 0; 954201052Smarius 955201052Smarius case PIO_FONT8x8: /* set 8x8 dot font */ 956201052Smarius if (!crtc_vga) 957201052Smarius return ENXIO; 958201052Smarius bcopy(data, font_8, 8*256); 959201052Smarius fonts_loaded |= FONT_8_LOADED; 960201052Smarius copy_font(LOAD, 1, 8, font_8); 961201052Smarius return 0; 962201052Smarius 963201052Smarius case GIO_FONT8x8: /* get 8x8 dot font */ 964201052Smarius if (!crtc_vga) 965201052Smarius return ENXIO; 966201052Smarius if (fonts_loaded & FONT_8_LOADED) { 967201052Smarius bcopy(font_8, data, 8*256); 968201052Smarius return 0; 969201052Smarius } 970201052Smarius else 971201052Smarius return ENXIO; 972201052Smarius 973201052Smarius case PIO_FONT8x14: /* set 8x14 dot font */ 974201052Smarius if (!crtc_vga) 975201052Smarius return ENXIO; 976201052Smarius bcopy(data, font_14, 14*256); 977201052Smarius fonts_loaded |= FONT_14_LOADED; 978201052Smarius copy_font(LOAD, 2, 14, font_14); 979201052Smarius return 0; 980201052Smarius 981201052Smarius case GIO_FONT8x14: /* get 8x14 dot font */ 982201052Smarius if (!crtc_vga) 983201052Smarius return ENXIO; 984201052Smarius if (fonts_loaded & FONT_14_LOADED) { 985201052Smarius bcopy(font_14, data, 14*256); 986201052Smarius return 0; 987201052Smarius } 988201052Smarius else 989201052Smarius return ENXIO; 990201052Smarius 991201052Smarius case PIO_FONT8x16: /* set 8x16 dot font */ 992201052Smarius if (!crtc_vga) 993201052Smarius return ENXIO; 994201052Smarius bcopy(data, font_16, 16*256); 995201052Smarius fonts_loaded |= FONT_16_LOADED; 996201052Smarius copy_font(LOAD, 0, 16, font_16); 997201052Smarius return 0; 998201052Smarius 999201052Smarius case GIO_FONT8x16: /* get 8x16 dot font */ 1000201052Smarius if (!crtc_vga) 1001201052Smarius return ENXIO; 1002201052Smarius if (fonts_loaded & FONT_16_LOADED) { 1003201052Smarius bcopy(font_16, data, 16*256); 1004201052Smarius return 0; 1005201052Smarius } 1006201052Smarius else 1007201052Smarius return ENXIO; 1008201052Smarius 1009201052Smarius case CONSOLE_X_MODE_ON: /* just to be compatible */ 1010201052Smarius if (saved_console < 0) { 1011201052Smarius saved_console = get_scr_num(); 1012201052Smarius switch_scr(minor(dev)); 1013201052Smarius fp = (struct trapframe *)p->p_md.md_regs; 1014201052Smarius fp->tf_eflags |= PSL_IOPL; 1015201052Smarius scp->status |= UNKNOWN_MODE; 1016201052Smarius scp->status |= KBD_RAW_MODE; 1017201052Smarius return 0; 1018201052Smarius } 1019201052Smarius return EAGAIN; 1020201052Smarius 1021201052Smarius case CONSOLE_X_MODE_OFF:/* just to be compatible */ 1022201052Smarius fp = (struct trapframe *)p->p_md.md_regs; 1023201052Smarius fp->tf_eflags &= ~PSL_IOPL; 1024201052Smarius if (crtc_vga) { 1025201052Smarius copy_font(LOAD, 0, 16, font_16); 1026201052Smarius copy_font(LOAD, 1, 8, font_8); 1027201052Smarius copy_font(LOAD, 2, 14, font_14); 1028201052Smarius load_palette(); 1029201052Smarius } 1030201052Smarius scp->status &= ~UNKNOWN_MODE; 1031201052Smarius set_mode(scp); 1032201052Smarius clear_screen(scp); 1033201052Smarius scp->status &= ~KBD_RAW_MODE; 1034201052Smarius switch_scr(saved_console); 1035201052Smarius saved_console = -1; 1036201052Smarius return 0; 1037201052Smarius 1038201052Smarius case CONSOLE_X_BELL: /* more compatibility */ 1039201052Smarius /* 1040201052Smarius * if set, data is a pointer to a length 2 array of 1041201052Smarius * integers. data[0] is the pitch in Hz and data[1] 1042201052Smarius * is the duration in msec. 1043201052Smarius */ 1044201052Smarius if (data) 1045201052Smarius sysbeep(TIMER_FREQ/((int*)data)[0], 1046201052Smarius ((int*)data)[1]*hz/1000); 1047201052Smarius else 1048201052Smarius sysbeep(scp->bell_pitch, scp->bell_duration); 1049201052Smarius return 0; 1050201052Smarius 1051201052Smarius default: 1052201052Smarius break; 1053201052Smarius } 1054201052Smarius 1055201052Smarius error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); 1056201052Smarius if (error >= 0) 1057201052Smarius return(error); 1058201052Smarius error = ttioctl(tp, cmd, data, flag); 1059201052Smarius if (error >= 0) 1060201052Smarius return(error); 1061201052Smarius return(ENOTTY); 1062201052Smarius} 1063201052Smarius 1064201052Smarius 1065201052Smariusvoid 1066201052Smariuspcxint(dev_t dev) 1067201052Smarius{ 1068201052Smarius struct tty *tp = get_tty_ptr(dev); 1069201052Smarius 1070201052Smarius if (!tp) 1071201052Smarius return; 1072201052Smarius tp->t_state &= ~TS_BUSY; 1073201052Smarius if (tp->t_line) 1074201052Smarius (*linesw[tp->t_line].l_start)(tp); 1075201052Smarius else 1076201052Smarius pcstart(tp); 1077201052Smarius} 1078201052Smarius 1079201052Smarius 1080201052Smariusvoid 1081201052Smariuspcstart(struct tty *tp) 1082201052Smarius{ 1083201052Smarius struct clist *rbp; 1084201052Smarius int i, s, len; 1085201052Smarius u_char buf[PCBURST]; 1086201052Smarius scr_stat *scp = get_scr_stat(tp->t_dev); 1087201052Smarius 1088201052Smarius if (scp->status & SLKED) 1089201052Smarius return; 1090201052Smarius s = spltty(); 1091201052Smarius if (!(tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))) { 1092201052Smarius tp->t_state |= TS_BUSY; 1093201052Smarius splx(s); 1094201052Smarius rbp = &tp->t_outq; 1095201052Smarius while (rbp->c_cc) { 1096201052Smarius len = q_to_b(rbp, buf, PCBURST); 1097201052Smarius for (i=0; i<len; i++) 1098201052Smarius if (buf[i]) ansi_put(scp, buf[i]); 1099201052Smarius } 1100201052Smarius s = spltty(); 1101201052Smarius tp->t_state &= ~TS_BUSY; 1102201052Smarius#if 0 1103201052Smarius if (rbp->c_cc) { 1104201052Smarius tp->t_state |= TS_TIMEOUT; 1105201052Smarius timeout((timeout_t)ttrstrt, (caddr_t)tp, 1); 1106201052Smarius } 1107201052Smarius#endif 1108201052Smarius if (rbp->c_cc <= tp->t_lowat) { 1109201052Smarius if (tp->t_state & TS_ASLEEP) { 1110201052Smarius tp->t_state &= ~TS_ASLEEP; 1111201052Smarius wakeup((caddr_t)rbp); 1112201052Smarius } 1113201052Smarius selwakeup(&tp->t_wsel); 1114201052Smarius } 1115201052Smarius } 1116201052Smarius splx(s); 1117201052Smarius} 1118201052Smarius 1119201052Smarius 1120201052Smariusvoid 1121201052Smariuspccnprobe(struct consdev *cp) 1122201052Smarius{ 1123201052Smarius int maj; 1124201052Smarius 1125201052Smarius /* locate the major number */ 1126201052Smarius for (maj = 0; maj < nchrdev; maj++) 1127201052Smarius if ((void*)cdevsw[maj].d_open == (void*)pcopen) 1128201052Smarius break; 1129201052Smarius 1130201052Smarius /* initialize required fields */ 1131201052Smarius cp->cn_dev = makedev(maj, NCONS); 1132201052Smarius cp->cn_pri = CN_INTERNAL; 1133201052Smarius} 1134201052Smarius 1135201052Smarius 1136201052Smariusvoid 1137201052Smariuspccninit(struct consdev *cp) 1138201052Smarius{ 1139201052Smarius scinit(); 1140201052Smarius} 1141201052Smarius 1142201052Smarius 1143201052Smariusvoid 1144201052Smariuspccnputc(dev_t dev, char c) 1145201052Smarius{ 1146201052Smarius if (c == '\n') 1147201052Smarius scput('\r'); 1148201052Smarius scput(c); 1149201052Smarius if (cur_console == &console[0]) { 1150201052Smarius int pos = cur_console->crtat - cur_console->crt_base; 1151201052Smarius if (pos != cur_cursor_pos) { 1152201052Smarius cur_cursor_pos = pos; 1153201052Smarius outb(crtc_addr,14); 1154201052Smarius outb(crtc_addr+1,pos >> 8); 1155201052Smarius outb(crtc_addr,15); 1156201052Smarius outb(crtc_addr+1,pos&0xff); 1157201052Smarius } 1158201052Smarius } 1159201052Smarius} 1160201052Smarius 1161201052Smarius 1162201052Smariusint 1163201052Smariuspccngetc(dev_t dev) 1164201052Smarius{ 1165201052Smarius int s = spltty(); /* block scintr while we poll */ 1166201052Smarius int c = scgetc(0); 1167201052Smarius splx(s); 1168201052Smarius if (c == '\r') c = '\n'; 1169201052Smarius return(c); 1170201052Smarius} 1171201052Smarius 1172201052Smarius 1173201052Smariusstatic void 1174201052Smariusnone_saver(int test) 1175201052Smarius{ 1176201052Smarius} 1177201052Smarius 1178201052Smarius 1179201052Smariusstatic void 1180201052Smariusfade_saver(int test) 1181201052Smarius{ 1182201052Smarius static int count = 0; 1183201052Smarius int i; 1184201052Smarius 1185201052Smarius if (test) { 1186201052Smarius scrn_blanked = 1; 1187201052Smarius if (count < 64) { 1188201052Smarius outb(PIXMASK, 0xFF); /* no pixelmask */ 1189201052Smarius outb(PALWADR, 0x00); 1190201052Smarius outb(PALDATA, 0); 1191201052Smarius outb(PALDATA, 0); 1192201052Smarius outb(PALDATA, 0); 1193201052Smarius for (i = 3; i < 768; i++) { 1194201052Smarius if (palette[i] - count > 15) 1195201052Smarius outb(PALDATA, palette[i]-count); 1196201052Smarius else 1197201052Smarius outb(PALDATA, 15); 1198201052Smarius } 1199201052Smarius inb(crtc_addr+6); /* reset flip/flop */ 1200201052Smarius outb(ATC, 0x20); /* enable palette */ 1201201052Smarius count++; 1202201052Smarius } 1203201052Smarius } 1204201052Smarius else { 1205201052Smarius count = scrn_blanked = 0; 1206201052Smarius load_palette(); 1207201052Smarius } 1208201052Smarius} 1209201052Smarius 1210201052Smarius 1211201052Smariusstatic void 1212201052Smariusblank_saver(int test) 1213201052Smarius{ 1214201052Smarius u_char val; 1215201052Smarius if (test) { 1216201052Smarius scrn_blanked = 1; 1217201052Smarius outb(TSIDX, 0x01); val = inb(TSREG); 1218201052Smarius outb(TSIDX, 0x01); outb(TSREG, val | 0x20); 1219201052Smarius } 1220201052Smarius else { 1221201052Smarius scrn_blanked = 0; 1222201052Smarius outb(TSIDX, 0x01); val = inb(TSREG); 1223201052Smarius outb(TSIDX, 0x01); outb(TSREG, val & 0xDF); 1224201052Smarius } 1225201052Smarius} 1226201052Smarius 1227201052Smarius#define NUM_STARS 50 1228201052Smarius 1229201052Smarius/* 1230201052Smarius * Alternate saver that got its inspiration from a well known utility 1231201052Smarius * package for an inferior^H^H^H^H^H^Hfamous OS. 1232201052Smarius */ 1233201052Smariusstatic void 1234201052Smariusstar_saver(int test) 1235201052Smarius{ 1236201052Smarius scr_stat *scp = cur_console; 1237201052Smarius int cell, i; 1238201052Smarius char pattern[] = {"...........++++*** "}; 1239201052Smarius char colors[] = {FG_DARKGREY, FG_LIGHTGREY, 1240201052Smarius FG_WHITE, FG_LIGHTCYAN}; 1241201052Smarius static u_short stars[NUM_STARS][2]; 1242201052Smarius 1243201052Smarius if (test) { 1244201052Smarius if (!scrn_blanked) { 1245201052Smarius bcopy(Crtat, scp->scr_buf, 1246201052Smarius scp->xsize * scp->ysize * 2); 1247201052Smarius fillw((FG_LIGHTGREY|BG_BLACK)<<8 | scr_map[0x20], Crtat, 1248201052Smarius scp->xsize * scp->ysize); 1249201052Smarius set_border(0); 1250201052Smarius i = scp->ysize * scp->xsize + 5; 1251201052Smarius outb(crtc_addr, 14); 1252201052Smarius outb(crtc_addr+1, i >> 8); 1253201052Smarius outb(crtc_addr, 15); 1254201052Smarius outb(crtc_addr+1, i & 0xff); 1255201052Smarius scrn_blanked = 1; 1256201052Smarius for(i=0; i<NUM_STARS; i++) { 1257201052Smarius stars[i][0] = 1258201052Smarius random() % (scp->xsize*scp->ysize); 1259201052Smarius stars[i][1] = 0; 1260201052Smarius } 1261201052Smarius } 1262201052Smarius cell = random() % NUM_STARS; 1263201052Smarius *((u_short*)(Crtat + stars[cell][0])) = 1264201052Smarius scr_map[pattern[stars[cell][1]]] | 1265201052Smarius colors[random()%sizeof(colors)] << 8; 1266201052Smarius if ((stars[cell][1]+=(random()%4)) >= sizeof(pattern)-1) { 1267201052Smarius stars[cell][0] = random() % (scp->xsize*scp->ysize); 1268201052Smarius stars[cell][1] = 0; 1269201052Smarius } 1270201052Smarius } 1271201052Smarius else { 1272201052Smarius if (scrn_blanked) { 1273201052Smarius bcopy(scp->scr_buf, Crtat, scp->xsize*scp->ysize*2); 1274201052Smarius cur_cursor_pos = -1; 1275201052Smarius set_border(scp->border); 1276201052Smarius scrn_blanked = 0; 1277201052Smarius } 1278201052Smarius } 1279201052Smarius} 1280201052Smarius 1281201052Smarius 1282201052Smariusstatic void 1283201052Smariussnake_saver(int test) 1284201052Smarius{ 1285201052Smarius const char saves[] = {"FreeBSD-2.0"}; 1286201052Smarius static u_char *savs[sizeof(saves)-1]; 1287201052Smarius static int dirx, diry; 1288201052Smarius int f; 1289201052Smarius scr_stat *scp = cur_console; 1290201052Smarius 1291201052Smarius if (test) { 1292201052Smarius if (!scrn_blanked) { 1293201052Smarius bcopy(Crtat, scp->scr_buf, 1294201052Smarius scp->xsize * scp->ysize * 2); 1295201052Smarius fillw((FG_LIGHTGREY|BG_BLACK)<<8 | scr_map[0x20], 1296201052Smarius Crtat, scp->xsize * scp->ysize); 1297201052Smarius set_border(0); 1298201052Smarius dirx = (scp->xpos ? 1 : -1); 1299201052Smarius diry = (scp->ypos ? 1300201052Smarius scp->xsize : -scp->xsize); 1301201052Smarius for (f=0; f< sizeof(saves)-1; f++) 1302201052Smarius savs[f] = (u_char *)Crtat + 2 * 1303201052Smarius (scp->xpos+scp->ypos*scp->xsize); 1304201052Smarius *(savs[0]) = scr_map[*saves]; 1305201052Smarius f = scp->ysize * scp->xsize + 5; 1306201052Smarius outb(crtc_addr, 14); 1307201052Smarius outb(crtc_addr+1, f >> 8); 1308201052Smarius outb(crtc_addr, 15); 1309201052Smarius outb(crtc_addr+1, f & 0xff); 1310201052Smarius scrn_blanked = 1; 1311201052Smarius } 1312201052Smarius if (scrn_blanked++ < 4) 1313201052Smarius return; 1314201052Smarius scrn_blanked = 1; 1315201052Smarius *(savs[sizeof(saves)-2]) = scr_map[0x20]; 1316201052Smarius for (f=sizeof(saves)-2; f > 0; f--) 1317201052Smarius savs[f] = savs[f-1]; 1318201052Smarius f = (savs[0] - (u_char *)Crtat) / 2; 1319201052Smarius if ((f % scp->xsize) == 0 || 1320201052Smarius (f % scp->xsize) == scp->xsize - 1 || 1321201052Smarius (random() % 50) == 0) 1322201052Smarius dirx = -dirx; 1323201052Smarius if ((f / scp->xsize) == 0 || 1324201052Smarius (f / scp->xsize) == scp->ysize - 1 || 1325201052Smarius (random() % 20) == 0) 1326201052Smarius diry = -diry; 1327201052Smarius savs[0] += 2*dirx + 2*diry; 1328292789Smarius for (f=sizeof(saves)-2; f>=0; f--) 1329292789Smarius *(savs[f]) = scr_map[saves[f]]; 1330201052Smarius } 1331201052Smarius else { 1332201052Smarius if (scrn_blanked) { 1333201052Smarius bcopy(scp->scr_buf, Crtat, 1334201052Smarius scp->xsize * scp->ysize * 2); 1335201052Smarius cur_cursor_pos = -1; 1336201052Smarius set_border(scp->border); 1337292789Smarius scrn_blanked = 0; 1338292789Smarius } 1339201052Smarius } 1340201052Smarius} 1341201052Smarius 1342201052Smarius 1343201052Smariusstatic void 1344292789Smariuscursor_shape(int start, int end) 1345201052Smarius{ 1346292789Smarius outb(crtc_addr, 10); 1347292789Smarius outb(crtc_addr+1, start & 0xFF); 1348292789Smarius outb(crtc_addr, 11); 1349292789Smarius outb(crtc_addr+1, end & 0xFF); 1350292789Smarius} 1351292789Smarius 1352201052Smarius 1353201052Smarius#if !defined(FAT_CURSOR) 1354201052Smariusstatic void 1355201052Smariusget_cursor_shape(int *start, int *end) 1356201052Smarius{ 1357201052Smarius outb(crtc_addr, 10); 1358201052Smarius *start = inb(crtc_addr+1) & 0x1F; 1359219785Smarius outb(crtc_addr, 11); 1360201052Smarius *end = inb(crtc_addr+1) & 0x1F; 1361201052Smarius} 1362292789Smarius#endif 1363292789Smarius 1364292789Smarius 1365219785Smariusstatic void 1366201052Smariuscursor_pos(int force) 1367201052Smarius{ 1368201052Smarius int pos; 1369201052Smarius 1370201052Smarius if (cur_console->status & UNKNOWN_MODE) 1371201052Smarius return; 1372201052Smarius if (scrn_blank_time && (time.tv_sec > scrn_time_stamp+scrn_blank_time)) 1373201052Smarius SCRN_SAVER(1); 1374201052Smarius pos = cur_console->crtat - cur_console->crt_base; 1375201052Smarius if (force || (!scrn_blanked && pos != cur_cursor_pos)) { 1376201052Smarius cur_cursor_pos = pos; 1377201052Smarius outb(crtc_addr, 14); 1378201052Smarius outb(crtc_addr+1, pos>>8); 1379201052Smarius outb(crtc_addr, 15); 1380201052Smarius outb(crtc_addr+1, pos&0xff); 1381201052Smarius } 1382201052Smarius timeout((timeout_t)cursor_pos, 0, hz/20); 1383201052Smarius} 1384201052Smarius 1385201052Smarius 1386201052Smariusstatic void 1387201052Smariusclear_screen(scr_stat *scp) 1388201052Smarius{ 1389201052Smarius move_crsr(scp, 0, 0); 1390201052Smarius fillw(scp->term.cur_attr | scr_map[0x20], scp->crt_base, 1391201052Smarius scp->xsize * scp->ysize); 1392201052Smarius} 1393201052Smarius 1394201052Smarius 1395201052Smariusstatic int 1396201052Smariusswitch_scr(u_int next_scr) 1397201052Smarius{ 1398201052Smarius if (switch_in_progress && 1399201052Smarius (cur_console->proc != pfind(cur_console->pid))) 1400201052Smarius switch_in_progress = 0; 1401201052Smarius 1402201052Smarius if (next_scr >= NCONS || switch_in_progress) { 1403201052Smarius sysbeep(BELL_PITCH, BELL_DURATION); 1404201052Smarius return EINVAL; 1405201052Smarius } 1406201052Smarius 1407201052Smarius /* is the wanted virtual console open ? */ 1408201052Smarius if (next_scr) { 1409201052Smarius struct tty *tp = VIRTUAL_TTY(next_scr); 1410201052Smarius if (!(tp->t_state & TS_ISOPEN)) { 1411201052Smarius sysbeep(BELL_PITCH, BELL_DURATION); 1412201052Smarius return EINVAL; 1413201052Smarius } 1414201052Smarius } 1415201052Smarius if (in_putc) { /* delay switch if in putc */ 1416201052Smarius delayed_next_scr = next_scr+1; 1417201052Smarius return 0; 1418201052Smarius } 1419201052Smarius switch_in_progress = 1; 1420201052Smarius old_scp = cur_console; 1421201052Smarius new_scp = &console[next_scr]; 1422201052Smarius wakeup((caddr_t)&new_scp->smode); 1423201052Smarius if (new_scp == old_scp) { 1424201052Smarius switch_in_progress = 0; 1425201052Smarius return 0; 1426201052Smarius } 1427201052Smarius 1428201052Smarius /* has controlling process died? */ 1429201052Smarius if (old_scp->proc && (old_scp->proc != pfind(old_scp->pid))) 1430201052Smarius old_scp->smode.mode = VT_AUTO; 1431201052Smarius if (new_scp->proc && (new_scp->proc != pfind(new_scp->pid))) 1432201052Smarius new_scp->smode.mode = VT_AUTO; 1433201052Smarius 1434201052Smarius /* check the modes and switch approbiatly */ 1435201052Smarius if (old_scp->smode.mode == VT_PROCESS) { 1436201052Smarius old_scp->status |= SWITCH_WAIT_REL; 1437201052Smarius psignal(old_scp->proc, old_scp->smode.relsig); 1438201052Smarius } 1439201052Smarius else { 1440201052Smarius exchange_scr(); 1441201052Smarius if (new_scp->smode.mode == VT_PROCESS) { 1442201052Smarius new_scp->status |= SWITCH_WAIT_ACQ; 1443201052Smarius psignal(new_scp->proc, new_scp->smode.acqsig); 1444201052Smarius } 1445201052Smarius else 1446201052Smarius switch_in_progress = 0; 1447201052Smarius } 1448201052Smarius return 0; 1449201052Smarius} 1450201052Smarius 1451201052Smarius 1452201052Smariusstatic void 1453201052Smariusexchange_scr(void) 1454201052Smarius{ 1455201052Smarius struct tty *tp; 1456201052Smarius 1457201052Smarius bcopy(Crtat, old_scp->scr_buf, old_scp->xsize * old_scp->ysize * 2); 1458201052Smarius old_scp->crt_base = old_scp->scr_buf; 1459201052Smarius move_crsr(old_scp, old_scp->xpos, old_scp->ypos); 1460201052Smarius cur_console = new_scp; 1461201052Smarius set_mode(new_scp); 1462201052Smarius new_scp->crt_base = Crtat; 1463201052Smarius move_crsr(new_scp, new_scp->xpos, new_scp->ypos); 1464201052Smarius bcopy(new_scp->scr_buf, Crtat, new_scp->xsize * new_scp->ysize * 2); 1465201052Smarius update_leds(new_scp->status); 1466201052Smarius if ((old_scp->status & UNKNOWN_MODE) && crtc_vga) { 1467202003Smarius copy_font(LOAD, 0, 16, font_16); 1468201052Smarius copy_font(LOAD, 1, 8, font_8); 1469201052Smarius copy_font(LOAD, 2, 14, font_14); 1470201052Smarius load_palette(); 1471201052Smarius } 1472201052Smarius if (old_scp->status & KBD_RAW_MODE || new_scp->status & KBD_RAW_MODE) 1473201052Smarius shfts = ctls = alts = agrs = metas = 0; 1474201052Smarius delayed_next_scr = 0; 1475201052Smarius} 1476201052Smarius 1477201052Smarius 1478201052Smariusstatic void 1479201052Smariusmove_crsr(scr_stat *scp, int x, int y) 1480201052Smarius{ 1481201052Smarius if (x < 0 || y < 0 || x >= scp->xsize || y >= scp->ysize) 1482201052Smarius return; 1483201052Smarius scp->xpos = x; 1484201052Smarius scp->ypos = y; 1485201052Smarius scp->crtat = scp->crt_base + scp->ypos * scp->xsize + scp->xpos; 1486201052Smarius} 1487201052Smarius 1488201052Smarius 1489201052Smariusstatic void 1490201052Smariusmove_up(u_short *s, u_short *d, u_int len) 1491201052Smarius{ 1492201052Smarius s += len; 1493202003Smarius d += len; 1494202003Smarius while (len-- > 0) 1495201052Smarius *--d = *--s; 1496201052Smarius} 1497202003Smarius 1498201052Smarius 1499201052Smariusstatic void 1500201052Smariusmove_down(u_short *s, u_short *d, u_int len) 1501201052Smarius{ 1502201052Smarius while (len-- > 0) 1503201052Smarius *d++ = *s++; 1504201052Smarius} 1505201052Smarius 1506201052Smarius 1507201052Smariusstatic void 1508201052Smariusscan_esc(scr_stat *scp, u_char c) 1509201052Smarius{ 1510201052Smarius static u_char ansi_col[16] = 1511201052Smarius {0, 4, 2, 6, 1, 5, 3, 7, 8, 12, 10, 14, 9, 13, 11, 15}; 1512201052Smarius int i, n; 1513201052Smarius u_short *src, *dst, count; 1514201052Smarius 1515201052Smarius if (scp->term.esc == 1) { 1516201052Smarius switch (c) { 1517201052Smarius 1518201052Smarius case '[': /* Start ESC [ sequence */ 1519201052Smarius scp->term.esc = 2; 1520201052Smarius scp->term.last_param = -1; 1521201052Smarius for (i = scp->term.num_param; i < MAX_ESC_PAR; i++) 1522201052Smarius scp->term.param[i] = 1; 1523201052Smarius scp->term.num_param = 0; 1524201052Smarius return; 1525201052Smarius 1526201052Smarius case 'M': /* Move cursor up 1 line, scroll if at top */ 1527201052Smarius if (scp->ypos > 0) 1528201052Smarius move_crsr(scp, scp->xpos, scp->ypos - 1); 1529201052Smarius else { 1530201052Smarius move_up(scp->crt_base, 1531201052Smarius scp->crt_base + scp->xsize, 1532201052Smarius (scp->ysize - 1) * scp->xsize); 1533262621Sdim fillw(scp->term.cur_attr | scr_map[0x20], 1534201052Smarius scp->crt_base, scp->xsize); 1535201052Smarius } 1536201052Smarius break; 1537201052Smarius#if notyet 1538201052Smarius case 'Q': 1539201052Smarius scp->term.esc = 4; 1540201052Smarius break; 1541201052Smarius#endif 1542201052Smarius case 'c': /* Clear screen & home */ 1543201052Smarius clear_screen(scp); 1544201052Smarius break; 1545201052Smarius } 1546201052Smarius } 1547201052Smarius else if (scp->term.esc == 2) { 1548201052Smarius if (c >= '0' && c <= '9') { 1549201052Smarius if (scp->term.num_param < MAX_ESC_PAR) { 1550201052Smarius if (scp->term.last_param != scp->term.num_param) { 1551201052Smarius scp->term.last_param = scp->term.num_param; 1552201052Smarius scp->term.param[scp->term.num_param] = 0; 1553201052Smarius } 1554201052Smarius else 1555201052Smarius scp->term.param[scp->term.num_param] *= 10; 1556201052Smarius scp->term.param[scp->term.num_param] += c - '0'; 1557201052Smarius return; 1558201052Smarius } 1559201052Smarius } 1560201052Smarius scp->term.num_param = scp->term.last_param + 1; 1561201052Smarius switch (c) { 1562201052Smarius 1563201052Smarius case ';': 1564201052Smarius if (scp->term.num_param < MAX_ESC_PAR) 1565201052Smarius return; 1566201052Smarius break; 1567201052Smarius 1568201052Smarius case '=': 1569201052Smarius scp->term.esc = 3; 1570201052Smarius scp->term.last_param = -1; 1571201052Smarius for (i = scp->term.num_param; i < MAX_ESC_PAR; i++) 1572201052Smarius scp->term.param[i] = 1; 1573201052Smarius scp->term.num_param = 0; 1574201052Smarius return; 1575201052Smarius 1576201052Smarius case 'A': /* up n rows */ 1577201052Smarius n = scp->term.param[0]; if (n < 1) n = 1; 1578201052Smarius move_crsr(scp, scp->xpos, scp->ypos - n); 1579201052Smarius break; 1580201052Smarius 1581201052Smarius case 'B': /* down n rows */ 1582201052Smarius n = scp->term.param[0]; if (n < 1) n = 1; 1583201052Smarius move_crsr(scp, scp->xpos, scp->ypos + n); 1584201052Smarius break; 1585201052Smarius 1586201052Smarius case 'C': /* right n columns */ 1587201052Smarius n = scp->term.param[0]; if (n < 1) n = 1; 1588201052Smarius move_crsr(scp, scp->xpos + n, scp->ypos); 1589201052Smarius break; 1590201052Smarius 1591201052Smarius case 'D': /* left n columns */ 1592201052Smarius n = scp->term.param[0]; if (n < 1) n = 1; 1593201052Smarius move_crsr(scp, scp->xpos - n, scp->ypos); 1594201052Smarius break; 1595201052Smarius 1596201052Smarius case 'E': /* cursor to start of line n lines down */ 1597201052Smarius n = scp->term.param[0]; if (n < 1) n = 1; 1598201052Smarius move_crsr(scp, 0, scp->ypos + n); 1599201052Smarius break; 1600201052Smarius 1601201052Smarius case 'F': /* cursor to start of line n lines up */ 1602201052Smarius n = scp->term.param[0]; if (n < 1) n = 1; 1603201052Smarius move_crsr(scp, 0, scp->ypos - n); 1604201052Smarius break; 1605201052Smarius 1606201052Smarius case 'f': /* System V consoles .. */ 1607201052Smarius case 'H': /* Cursor move */ 1608201052Smarius if (scp->term.num_param == 0) 1609201052Smarius move_crsr(scp, 0, 0); 1610201052Smarius else if (scp->term.num_param == 2) 1611201052Smarius move_crsr(scp, scp->term.param[1] - 1, 1612201052Smarius scp->term.param[0] - 1); 1613201052Smarius break; 1614201052Smarius 1615201052Smarius case 'J': /* Clear all or part of display */ 1616201052Smarius if (scp->term.num_param == 0) 1617201052Smarius n = 0; 1618201052Smarius else 1619201052Smarius n = scp->term.param[0]; 1620201052Smarius switch (n) { 1621202003Smarius case 0: /* clear form cursor to end of display */ 1622202003Smarius fillw(scp->term.cur_attr | scr_map[0x20], 1623202003Smarius scp->crtat, scp->crt_base + 1624201052Smarius scp->xsize * scp->ysize - 1625201052Smarius scp->crtat); 1626202003Smarius break; 1627202003Smarius case 1: /* clear from beginning of display to cursor */ 1628201052Smarius fillw(scp->term.cur_attr | scr_map[0x20], 1629202003Smarius scp->crt_base, 1630202003Smarius scp->crtat - scp->crt_base); 1631202003Smarius break; 1632202003Smarius case 2: /* clear entire display */ 1633201052Smarius clear_screen(scp); 1634201052Smarius break; 1635202003Smarius } 1636202003Smarius break; 1637202003Smarius 1638202003Smarius case 'K': /* Clear all or part of line */ 1639202003Smarius if (scp->term.num_param == 0) 1640202003Smarius n = 0; 1641202003Smarius else 1642202003Smarius n = scp->term.param[0]; 1643202003Smarius switch (n) { 1644202003Smarius case 0: /* clear form cursor to end of line */ 1645202003Smarius fillw(scp->term.cur_attr | scr_map[0x20], 1646202003Smarius scp->crtat, scp->xsize - scp->xpos); 1647202003Smarius break; 1648202003Smarius case 1: /* clear from beginning of line to cursor */ 1649202003Smarius fillw(scp->term.cur_attr|scr_map[0x20], 1650202003Smarius scp->crtat - (scp->xsize - scp->xpos), 1651202003Smarius (scp->xsize - scp->xpos) + 1); 1652202003Smarius break; 1653202003Smarius case 2: /* clear entire line */ 1654202003Smarius fillw(scp->term.cur_attr|scr_map[0x20], 1655202003Smarius scp->crtat - (scp->xsize - scp->xpos), 1656202003Smarius scp->xsize); 1657202003Smarius break; 1658202003Smarius } 1659202003Smarius break; 1660202003Smarius 1661202003Smarius case 'L': /* Insert n lines */ 1662202003Smarius n = scp->term.param[0]; if (n < 1) n = 1; 1663202003Smarius if (n > scp->ysize - scp->ypos) 1664202003Smarius n = scp->ysize - scp->ypos; 1665202003Smarius src = scp->crt_base + scp->ypos * scp->xsize; 1666202003Smarius dst = src + n * scp->xsize; 1667202003Smarius count = scp->ysize - (scp->ypos + n); 1668202003Smarius move_up(src, dst, count * scp->xsize); 1669202003Smarius fillw(scp->term.cur_attr | scr_map[0x20], src, 1670202003Smarius n * scp->xsize); 1671202003Smarius break; 1672202003Smarius 1673202003Smarius case 'M': /* Delete n lines */ 1674202003Smarius n = scp->term.param[0]; if (n < 1) n = 1; 1675202003Smarius if (n > scp->ysize - scp->ypos) 1676202003Smarius n = scp->ysize - scp->ypos; 1677201052Smarius dst = scp->crt_base + scp->ypos * scp->xsize; 1678201052Smarius src = dst + n * scp->xsize; 1679201052Smarius count = scp->ysize - (scp->ypos + n); 1680201052Smarius move_down(src, dst, count * scp->xsize); 1681201052Smarius src = dst + count * scp->xsize; 1682203094Smarius fillw(scp->term.cur_attr | scr_map[0x20], src, 1683203094Smarius n * scp->xsize); 1684201052Smarius break; 1685201052Smarius 1686201052Smarius case 'P': /* Delete n chars */ 1687201052Smarius n = scp->term.param[0]; if (n < 1) n = 1; 1688201052Smarius if (n > scp->xsize - scp->xpos) 1689201052Smarius n = scp->xsize - scp->xpos; 1690201052Smarius dst = scp->crtat; 1691201052Smarius src = dst + n; 1692201052Smarius count = scp->xsize - (scp->xpos + n); 1693201052Smarius move_down(src, dst, count); 1694201052Smarius src = dst + count; 1695201052Smarius fillw(scp->term.cur_attr | scr_map[0x20], src, n); 1696201052Smarius break; 1697201052Smarius 1698201052Smarius case '@': /* Insert n chars */ 1699201052Smarius n = scp->term.param[0]; if (n < 1) n = 1; 1700201052Smarius if (n > scp->xsize - scp->xpos) 1701201052Smarius n = scp->xsize - scp->xpos; 1702201052Smarius src = scp->crtat; 1703201052Smarius dst = src + n; 1704201052Smarius count = scp->xsize - (scp->xpos + n); 1705201052Smarius move_up(src, dst, count); 1706201052Smarius fillw(scp->term.cur_attr | scr_map[0x20], src, n); 1707201052Smarius break; 1708201052Smarius 1709201052Smarius case 'S': /* scroll up n lines */ 1710201052Smarius n = scp->term.param[0]; if (n < 1) n = 1; 1711201052Smarius if (n > scp->ypos) 1712201052Smarius n = scp->ypos; 1713201052Smarius bcopy(scp->crt_base + (scp->xsize * n), 1714201052Smarius scp->crt_base, 1715201052Smarius scp->xsize * (scp->ysize - n) * 1716201052Smarius sizeof(u_short)); 1717201052Smarius fillw(scp->term.cur_attr | scr_map[0x20], 1718201052Smarius scp->crt_base + scp->xsize * 1719201052Smarius (scp->ysize - 1), 1720201052Smarius scp->xsize); 1721201052Smarius break; 1722201052Smarius 1723201052Smarius case 'T': /* scroll down n lines */ 1724201052Smarius n = scp->term.param[0]; if (n < 1) n = 1; 1725201052Smarius if (n > scp->ysize - scp->ypos) 1726202023Smarius n = scp->ysize - scp->ypos; 1727201052Smarius bcopy(scp->crt_base, 1728201052Smarius scp->crt_base + (scp->xsize * n), 1729201052Smarius scp->xsize * (scp->ysize - n) * 1730201052Smarius sizeof(u_short)); 1731201052Smarius fillw(scp->term.cur_attr | scr_map[0x20], 1732201052Smarius scp->crt_base, scp->xsize); 1733201052Smarius break; 1734201052Smarius 1735201052Smarius case 'X': /* delete n characters in line */ 1736201052Smarius n = scp->term.param[0]; if (n < 1) n = 1; 1737201052Smarius if (n > scp->xsize - scp->xpos) 1738201052Smarius n = scp->xsize - scp->xpos; 1739201052Smarius fillw(scp->term.cur_attr | scr_map[0x20], 1740201052Smarius scp->crt_base + scp->xpos + 1741201052Smarius ((scp->xsize*scp->ypos) * sizeof(u_short)), n); 1742201052Smarius break; 1743201052Smarius 1744201052Smarius case 'Z': /* move n tabs backwards */ 1745201052Smarius n = scp->term.param[0]; if (n < 1) n = 1; 1746201052Smarius if ((i = scp->xpos & 0xf8) == scp->xpos) 1747201052Smarius i -= 8*n; 1748201052Smarius else 1749201052Smarius i -= 8*(n-1); 1750201052Smarius if (i < 0) 1751201052Smarius i = 0; 1752201052Smarius move_crsr(scp, i, scp->ypos); 1753201052Smarius break; 1754201052Smarius 1755201052Smarius case '`': /* move cursor to column n */ 1756201052Smarius n = scp->term.param[0]; if (n < 1) n = 1; 1757202003Smarius move_crsr(scp, n, scp->ypos); 1758202003Smarius break; 1759202023Smarius 1760202003Smarius case 'a': /* move cursor n columns to the right */ 1761202003Smarius n = scp->term.param[0]; if (n < 1) n = 1; 1762202003Smarius move_crsr(scp, scp->xpos + n, scp->ypos); 1763202003Smarius break; 1764202003Smarius 1765202003Smarius case 'd': /* move cursor to row n */ 1766202023Smarius n = scp->term.param[0]; if (n < 1) n = 1; 1767202023Smarius move_crsr(scp, scp->xpos, n); 1768202023Smarius break; 1769202023Smarius 1770202023Smarius case 'e': /* move cursor n rows down */ 1771202023Smarius n = scp->term.param[0]; if (n < 1) n = 1; 1772202023Smarius move_crsr(scp, scp->xpos, scp->ypos + n); 1773202003Smarius break; 1774201052Smarius 1775202003Smarius case 'm': /* change attribute */ 1776202023Smarius if (scp->term.num_param == 0) { 1777202003Smarius scp->term.cur_attr = scp->term.std_attr; 1778202003Smarius break; 1779202003Smarius } 1780202003Smarius for (i = 0; i < scp->term.num_param; i++) { 1781202003Smarius switch (n = scp->term.param[i]) { 1782202003Smarius case 0: /* back to normal */ 1783202003Smarius scp->term.cur_attr = scp->term.std_attr; 1784202003Smarius break; 1785202003Smarius case 1: /* highlight (bold) */ 1786202003Smarius scp->term.cur_attr &= 0xFF00; 1787202003Smarius scp->term.cur_attr |= 0x0800; 1788202003Smarius break; 1789202003Smarius case 4: /* highlight (underline) */ 1790201052Smarius scp->term.cur_attr &= 0xFF00; 1791201052Smarius scp->term.cur_attr |= 0x0800; 1792201052Smarius break; 1793201052Smarius case 5: /* blink */ 1794201052Smarius scp->term.cur_attr &= 0xFF00; 1795201052Smarius scp->term.cur_attr |= 0x8000; 1796201052Smarius break; 1797201052Smarius case 7: /* reverse video */ 1798201052Smarius scp->term.cur_attr = scp->term.rev_attr; 1799201052Smarius break; 1800201052Smarius case 30: case 31: /* set fg color */ 1801201052Smarius case 32: case 33: case 34: 1802201052Smarius case 35: case 36: case 37: 1803201052Smarius scp->term.cur_attr = 1804201052Smarius (scp->term.cur_attr & 0xF8FF) 1805201052Smarius | (ansi_col[(n-30) & 7] << 8); 1806201052Smarius break; 1807201052Smarius case 40: case 41: /* set bg color */ 1808201052Smarius case 42: case 43: case 44: 1809201052Smarius case 45: case 46: case 47: 1810201052Smarius scp->term.cur_attr = 1811201052Smarius (scp->term.cur_attr & 0x8FFF) 1812201052Smarius | (ansi_col[(n-40) & 7] << 12); 1813201052Smarius break; 1814201052Smarius } 1815201052Smarius } 1816201052Smarius break; 1817201052Smarius 1818201052Smarius case 'x': 1819201052Smarius if (scp->term.num_param == 0) 1820201052Smarius n = 0; 1821201052Smarius else 1822201052Smarius n = scp->term.param[0]; 1823201052Smarius switch (n) { 1824201052Smarius case 0: /* reset attributes */ 1825201052Smarius scp->term.cur_attr = scp->term.std_attr = 1826201052Smarius current_default->std_attr; 1827201052Smarius scp->term.rev_attr = current_default->rev_attr; 1828201052Smarius break; 1829201052Smarius case 1: /* set ansi background */ 1830201052Smarius scp->term.cur_attr = scp->term.std_attr = 1831201052Smarius (scp->term.std_attr & 0x0F00) | 1832201052Smarius (ansi_col[(scp->term.param[1])&0x0F]<<12); 1833201052Smarius break; 1834201052Smarius case 2: /* set ansi foreground */ 1835201052Smarius scp->term.cur_attr = scp->term.std_attr = 1836201052Smarius (scp->term.std_attr & 0xF000) | 1837201052Smarius (ansi_col[(scp->term.param[1])&0x0F]<<8); 1838202003Smarius break; 1839201052Smarius case 3: /* set ansi attribute directly */ 1840201052Smarius scp->term.cur_attr = scp->term.std_attr = 1841201052Smarius (scp->term.param[1]&0xFF)<<8; 1842201052Smarius break; 1843201052Smarius case 5: /* set ansi reverse video background */ 1844201052Smarius scp->term.rev_attr = 1845202003Smarius (scp->term.rev_attr & 0x0F00) | 1846201052Smarius (ansi_col[(scp->term.param[1])&0x0F]<<12); 1847202003Smarius break; 1848201052Smarius case 6: /* set ansi reverse video foreground */ 1849201052Smarius scp->term.rev_attr = 1850201052Smarius (scp->term.rev_attr & 0xF000) | 1851201052Smarius (ansi_col[(scp->term.param[1])&0x0F]<<8); 1852201052Smarius break; 1853201052Smarius case 7: /* set ansi reverse video directly */ 1854201052Smarius scp->term.rev_attr = (scp->term.param[1]&0xFF)<<8; 1855201052Smarius break; 1856201052Smarius } 1857201052Smarius break; 1858201052Smarius 1859292789Smarius case 'z': /* switch to (virtual) console n */ 1860292789Smarius if (scp->term.num_param == 1) 1861292789Smarius switch_scr(scp->term.param[0]); 1862201052Smarius break; 1863292789Smarius } 1864292789Smarius } 1865201052Smarius else if (scp->term.esc == 3) { 1866201052Smarius if (c >= '0' && c <= '9') { 1867201052Smarius if (scp->term.num_param < MAX_ESC_PAR) { 1868201052Smarius if (scp->term.last_param != scp->term.num_param) { 1869201052Smarius scp->term.last_param = scp->term.num_param; 1870201052Smarius scp->term.param[scp->term.num_param] = 0; 1871201052Smarius } 1872201052Smarius else 1873201052Smarius scp->term.param[scp->term.num_param] *= 10; 1874201052Smarius scp->term.param[scp->term.num_param] += c - '0'; 1875 return; 1876 } 1877 } 1878 scp->term.num_param = scp->term.last_param + 1; 1879 switch (c) { 1880 1881 case ';': 1882 if (scp->term.num_param < MAX_ESC_PAR) 1883 return; 1884 break; 1885 1886 case 'A': /* set display border color */ 1887 if (scp->term.num_param == 1) 1888 scp->border=scp->term.param[0] & 0xff; 1889 if (scp == cur_console) 1890 set_border(scp->border); 1891 break; 1892 1893 case 'B': /* set bell pitch and duration */ 1894 if (scp->term.num_param == 2) { 1895 scp->bell_pitch = scp->term.param[0]; 1896 scp->bell_duration = scp->term.param[1]*10; 1897 } 1898 break; 1899 1900 case 'C': /* set cursor shape (start & end line) */ 1901 if (scp->term.num_param == 2) { 1902 scp->cursor_start = scp->term.param[0] & 0x1F; 1903 scp->cursor_end = scp->term.param[1] & 0x1F; 1904 if (scp == cur_console) 1905 cursor_shape(scp->cursor_start, 1906 scp->cursor_end); 1907 } 1908 break; 1909 1910 case 'F': /* set ansi foreground */ 1911 if (scp->term.num_param == 1) 1912 scp->term.cur_attr = scp->term.std_attr = 1913 (scp->term.std_attr & 0xF000) 1914 | ((scp->term.param[0] & 0x0F) << 8); 1915 break; 1916 1917 case 'G': /* set ansi background */ 1918 if (scp->term.num_param == 1) 1919 scp->term.cur_attr = scp->term.std_attr = 1920 (scp->term.std_attr & 0x0F00) 1921 | ((scp->term.param[0] & 0x0F) << 12); 1922 break; 1923 1924 case 'H': /* set ansi reverse video foreground */ 1925 if (scp->term.num_param == 1) 1926 scp->term.rev_attr = 1927 (scp->term.rev_attr & 0xF000) 1928 | ((scp->term.param[0] & 0x0F) << 8); 1929 break; 1930 1931 case 'I': /* set ansi reverse video background */ 1932 if (scp->term.num_param == 1) 1933 scp->term.rev_attr = 1934 (scp->term.rev_attr & 0x0F00) 1935 | ((scp->term.param[0] & 0x0F) << 12); 1936 break; 1937 } 1938 } 1939 scp->term.esc = 0; 1940} 1941 1942 1943static void 1944ansi_put(scr_stat *scp, u_char c) 1945{ 1946 if (scp->status & UNKNOWN_MODE) 1947 return; 1948 1949 /* make screensaver happy */ 1950 if (scp == cur_console) { 1951 scrn_time_stamp = time.tv_sec; 1952 if (scrn_blanked) 1953 SCRN_SAVER(0); 1954 } 1955 in_putc++; 1956 if (scp->term.esc) 1957 scan_esc(scp, c); 1958 else switch(c) { 1959 case 0x1B: /* start escape sequence */ 1960 scp->term.esc = 1; 1961 scp->term.num_param = 0; 1962 break; 1963 case 0x07: 1964 if (scp == cur_console) 1965 sysbeep(scp->bell_pitch, scp->bell_duration); 1966 break; 1967 case '\t': /* non-destructive tab */ 1968 scp->crtat += (8 - scp->xpos % 8); 1969 scp->xpos += (8 - scp->xpos % 8); 1970 break; 1971 case '\b': /* non-destructive backspace */ 1972 if (scp->crtat > scp->crt_base) { 1973 scp->crtat--; 1974 if (scp->xpos > 0) 1975 scp->xpos--; 1976 else { 1977 scp->xpos += scp->xsize - 1; 1978 scp->ypos--; 1979 } 1980 } 1981 break; 1982 case '\r': /* return to pos 0 */ 1983 move_crsr(scp, 0, scp->ypos); 1984 break; 1985 case '\n': /* newline, same pos */ 1986 scp->crtat += scp->xsize; 1987 scp->ypos++; 1988 break; 1989 case '\f': /* form feed, clears screen */ 1990 clear_screen(scp); 1991 break; 1992 default: 1993 /* Print only printables */ 1994 *scp->crtat = (scp->term.cur_attr | scr_map[c]); 1995 scp->crtat++; 1996 if (++scp->xpos >= scp->xsize) { 1997 scp->xpos = 0; 1998 scp->ypos++; 1999 } 2000 break; 2001 } 2002 if (scp->crtat >= scp->crt_base + scp->ysize * scp->xsize) { 2003 bcopy(scp->crt_base + scp->xsize, scp->crt_base, 2004 scp->xsize * (scp->ysize - 1) * sizeof(u_short)); 2005 fillw(scp->term.cur_attr | scr_map[0x20], 2006 scp->crt_base + scp->xsize * (scp->ysize - 1), 2007 scp->xsize); 2008 scp->crtat -= scp->xsize; 2009 scp->ypos--; 2010 } 2011 in_putc--; 2012 if (delayed_next_scr) 2013 switch_scr(delayed_next_scr - 1); 2014} 2015 2016 2017static void 2018scinit(void) 2019{ 2020 u_short volatile *cp = Crtat + (CGA_BUF-MONO_BUF)/sizeof(u_short), was; 2021 unsigned cursorat; 2022 int i; 2023 2024 /* 2025 * catch that once in a blue moon occurence when scinit is called 2026 * TWICE, adding the CGA_BUF offset again -> poooff 2027 */ 2028 if (crtat != 0) 2029 return; 2030 /* 2031 * Crtat initialized to point to MONO buffer, if not present change 2032 * to CGA_BUF offset. ONLY ADD the difference since locore.s adds 2033 * in the remapped offset at the "right" time 2034 */ 2035 was = *cp; 2036 *cp = (u_short) 0xA55A; 2037 if (*cp != 0xA55A) { 2038 crtc_addr = MONO_BASE; 2039 } else { 2040 *cp = was; 2041 crtc_addr = COLOR_BASE; 2042 Crtat = Crtat + (CGA_BUF-MONO_BUF)/sizeof(u_short); 2043 } 2044 2045 /* Extract cursor location */ 2046 outb(crtc_addr,14); 2047 cursorat = inb(crtc_addr+1)<<8 ; 2048 outb(crtc_addr,15); 2049 cursorat |= inb(crtc_addr+1); 2050 crtat = Crtat + cursorat; 2051 2052 /* is this a VGA or higher ? */ 2053 outb(crtc_addr, 7); 2054 if (inb(crtc_addr) == 7) 2055 crtc_vga = 1; 2056 2057 current_default = &user_default; 2058 console[0].crtat = crtat; 2059 console[0].crt_base = Crtat; 2060 console[0].term.esc = 0; 2061 console[0].term.std_attr = current_default->std_attr; 2062 console[0].term.rev_attr = current_default->rev_attr; 2063 console[0].term.cur_attr = current_default->std_attr; 2064 console[0].xpos = cursorat % COL; 2065 console[0].ypos = cursorat / COL; 2066 console[0].border = BG_BLACK;; 2067 console[0].xsize = COL; 2068 console[0].ysize = ROW; 2069 console[0].status = NLKED; 2070 console[0].pid = 0; 2071 console[0].proc = NULL; 2072 console[0].smode.mode = VT_AUTO; 2073 console[0].bell_pitch = BELL_PITCH; 2074 console[0].bell_duration = BELL_DURATION; 2075 kernel_console.esc = 0; 2076 kernel_console.std_attr = kernel_default.std_attr; 2077 kernel_console.rev_attr = kernel_default.rev_attr; 2078 kernel_console.cur_attr = kernel_default.std_attr; 2079 /* initialize mapscrn array to a one to one map */ 2080 for (i=0; i<sizeof(scr_map); i++) 2081 scr_map[i] = i; 2082 clear_screen(&console[0]); 2083} 2084 2085 2086static void 2087scput(u_char c) 2088{ 2089 scr_stat *scp = &console[0]; 2090 term_stat save; 2091 2092 if (crtat == 0) 2093 scinit(); 2094 if( in_putc == 0) { 2095 ++in_putc; 2096 save = scp->term; 2097 scp->term = kernel_console; 2098 current_default = &kernel_default; 2099 ansi_put(scp, c); 2100 kernel_console = scp->term; 2101 current_default = &user_default; 2102 scp->term = save; 2103 --in_putc; 2104 } else { 2105 if( console_buffer_count < CONSOLE_BUFSIZE) 2106 console_buffer[console_buffer_count++] = c; 2107 } 2108} 2109 2110 2111static u_char 2112*get_fstr(u_int c, u_int *len) 2113{ 2114 u_int i; 2115 2116 if (!(c & FKEY)) 2117 return(NULL); 2118 i = (c & 0xFF) - F_FN; 2119 if (i > n_fkey_tab) 2120 return(NULL); 2121 *len = fkey_tab[i].len; 2122 return(fkey_tab[i].str); 2123} 2124 2125 2126static void 2127update_leds(int which) 2128{ 2129 int s; 2130 static u_char xlate_leds[8] = { 0, 4, 2, 6, 1, 5, 3, 7 }; 2131 2132 /* replace CAPS led with ALTGR led for ALTGR keyboards */ 2133 if (key_map.n_keys > ALTGR_OFFSET) { 2134 if (which & ALKED) 2135 which |= CLKED; 2136 else 2137 which &= ~CLKED; 2138 } 2139 s = spltty(); 2140 kbd_cmd(KB_SETLEDS); 2141 kbd_cmd(xlate_leds[which & LED_MASK]); 2142 splx(s); 2143} 2144 2145 2146/* 2147 * scgetc(noblock) - get character from keyboard. 2148 * If noblock = 0 wait until a key is pressed. 2149 * Else return NOKEY. 2150 */ 2151u_int 2152scgetc(int noblock) 2153{ 2154 u_char scancode, keycode; 2155 u_int state, action; 2156 struct key_t *key; 2157 static u_char esc_flag = 0, compose = 0; 2158 static u_int chr = 0; 2159 2160next_code: 2161 kbd_wait(); 2162 /* First see if there is something in the keyboard port */ 2163 if (inb(KB_STAT) & KB_BUF_FULL) 2164 scancode = inb(KB_DATA); 2165 else if (noblock) 2166 return(NOKEY); 2167 else 2168 goto next_code; 2169 2170 if (cur_console->status & KBD_RAW_MODE) 2171 return scancode; 2172#if ASYNCH 2173 if (scancode == KB_ACK || scancode == KB_RESEND) { 2174 kbd_reply = scancode; 2175 if (noblock) 2176 return(NOKEY); 2177 goto next_code; 2178 } 2179#endif 2180 keycode = scancode & 0x7F; 2181 switch (esc_flag) { 2182 case 0x00: /* normal scancode */ 2183 switch(scancode) { 2184 case 0xB8: /* left alt (compose key) */ 2185 if (compose) { 2186 compose = 0; 2187 if (chr > 255) { 2188 sysbeep(BELL_PITCH, BELL_DURATION); 2189 chr = 0; 2190 } 2191 } 2192 break; 2193 case 0x38: 2194 if (!compose) { 2195 compose = 1; 2196 chr = 0; 2197 } 2198 break; 2199 case 0xE0: 2200 case 0xE1: 2201 esc_flag = scancode; 2202 goto next_code; 2203 } 2204 break; 2205 case 0xE0: /* 0xE0 prefix */ 2206 esc_flag = 0; 2207 switch (keycode) { 2208 case 0x1C: /* right enter key */ 2209 keycode = 0x59; 2210 break; 2211 case 0x1D: /* right ctrl key */ 2212 keycode = 0x5A; 2213 break; 2214 case 0x35: /* keypad divide key */ 2215 keycode = 0x5B; 2216 break; 2217 case 0x37: /* print scrn key */ 2218 keycode = 0x5C; 2219 break; 2220 case 0x38: /* right alt key (alt gr) */ 2221 keycode = 0x5D; 2222 break; 2223 case 0x47: /* grey home key */ 2224 keycode = 0x5E; 2225 break; 2226 case 0x48: /* grey up arrow key */ 2227 keycode = 0x5F; 2228 break; 2229 case 0x49: /* grey page up key */ 2230 keycode = 0x60; 2231 break; 2232 case 0x4B: /* grey left arrow key */ 2233 keycode = 0x61; 2234 break; 2235 case 0x4D: /* grey right arrow key */ 2236 keycode = 0x62; 2237 break; 2238 case 0x4F: /* grey end key */ 2239 keycode = 0x63; 2240 break; 2241 case 0x50: /* grey down arrow key */ 2242 keycode = 0x64; 2243 break; 2244 case 0x51: /* grey page down key */ 2245 keycode = 0x65; 2246 break; 2247 case 0x52: /* grey insert key */ 2248 keycode = 0x66; 2249 break; 2250 case 0x53: /* grey delete key */ 2251 keycode = 0x67; 2252 break; 2253 default: /* ignore everything else */ 2254 goto next_code; 2255 } 2256 break; 2257 case 0xE1: /* 0xE1 prefix */ 2258 esc_flag = 0; 2259 if (keycode == 0x1D) 2260 esc_flag = 0x1D; 2261 goto next_code; 2262 /* NOT REACHED */ 2263 case 0x1D: /* pause / break */ 2264 esc_flag = 0; 2265 if (keycode != 0x45) 2266 goto next_code; 2267 keycode = 0x68; 2268 break; 2269 } 2270 2271 if (compose) { 2272 switch (scancode) { 2273 /* key pressed process it */ 2274 case 0x47: case 0x48: case 0x49: /* keypad 7,8,9 */ 2275 chr = (scancode - 0x40) + chr*10; 2276 goto next_code; 2277 case 0x4B: case 0x4C: case 0x4D: /* keypad 4,5,6 */ 2278 chr = (scancode - 0x47) + chr*10; 2279 goto next_code; 2280 case 0x4F: case 0x50: case 0x51: /* keypad 1,2,3 */ 2281 chr = (scancode - 0x4E) + chr*10; 2282 goto next_code; 2283 case 0x52: /* keypad 0 */ 2284 chr *= 10; 2285 goto next_code; 2286 2287 /* key release, no interest here */ 2288 case 0xC7: case 0xC8: case 0xC9: /* keypad 7,8,9 */ 2289 case 0xCB: case 0xCC: case 0xCD: /* keypad 4,5,6 */ 2290 case 0xCF: case 0xD0: case 0xD1: /* keypad 1,2,3 */ 2291 case 0xD2: /* keypad 0 */ 2292 goto next_code; 2293 2294 case 0x38: /* left alt key */ 2295 break; 2296 default: 2297 if (chr) { 2298 compose = chr = 0; 2299 sysbeep(BELL_PITCH, BELL_DURATION); 2300 goto next_code; 2301 } 2302 break; 2303 } 2304 } 2305 2306 state = (shfts ? 1 : 0 ) | (2 * (ctls ? 1 : 0)) | (4 * (alts ? 1 : 0)); 2307 if ((!agrs && (cur_console->status & ALKED)) 2308 || (agrs && !(cur_console->status & ALKED))) 2309 keycode += ALTGR_OFFSET; 2310 key = &key_map.key[keycode]; 2311 if ( ((key->flgs & FLAG_LOCK_C) && (cur_console->status & CLKED)) 2312 || ((key->flgs & FLAG_LOCK_N) && (cur_console->status & NLKED)) ) 2313 state ^= 1; 2314 2315 /* Check for make/break */ 2316 action = key->map[state]; 2317 if (scancode & 0x80) { /* key released */ 2318 if (key->spcl & 0x80) { 2319 switch (action) { 2320 case LSH: 2321 shfts &= ~1; 2322 break; 2323 case RSH: 2324 shfts &= ~2; 2325 break; 2326 case LCTR: 2327 ctls &= ~1; 2328 break; 2329 case RCTR: 2330 ctls &= ~2; 2331 break; 2332 case LALT: 2333 alts &= ~1; 2334 break; 2335 case RALT: 2336 alts &= ~2; 2337 break; 2338 case NLK: 2339 nlkcnt = 0; 2340 break; 2341 case CLK: 2342 clkcnt = 0; 2343 break; 2344 case SLK: 2345 slkcnt = 0; 2346 break; 2347 case ASH: 2348 agrs = 0; 2349 break; 2350 case ALK: 2351 alkcnt = 0; 2352 break; 2353 case META: 2354 metas = 0; 2355 break; 2356 } 2357 } 2358 if (chr && !compose) { 2359 action = chr; 2360 chr = 0; 2361 return(action); 2362 } 2363 } else { 2364 /* key pressed */ 2365 if (key->spcl & (0x80>>state)) { 2366 switch (action) { 2367 /* LOCKING KEYS */ 2368 case NLK: 2369 if (!nlkcnt) { 2370 nlkcnt++; 2371 if (cur_console->status & NLKED) 2372 cur_console->status &= ~NLKED; 2373 else 2374 cur_console->status |= NLKED; 2375 update_leds(cur_console->status); 2376 } 2377 break; 2378 case CLK: 2379 if (!clkcnt) { 2380 clkcnt++; 2381 if (cur_console->status & CLKED) 2382 cur_console->status &= ~CLKED; 2383 else 2384 cur_console->status |= CLKED; 2385 update_leds(cur_console->status); 2386 } 2387 break; 2388 case SLK: 2389 if (!slkcnt) { 2390 slkcnt++; 2391 if (cur_console->status & SLKED) { 2392 cur_console->status &= ~SLKED; 2393 pcstart(VIRTUAL_TTY(get_scr_num())); 2394 } 2395 else 2396 cur_console->status |= SLKED; 2397 update_leds(cur_console->status); 2398 } 2399 break; 2400 case ALK: 2401 if (!alkcnt) { 2402 alkcnt++; 2403 if (cur_console->status & ALKED) 2404 cur_console->status &= ~ALKED; 2405 else 2406 cur_console->status |= ALKED; 2407 update_leds(cur_console->status); 2408 } 2409 break; 2410 2411 /* NON-LOCKING KEYS */ 2412 case NOP: 2413 break; 2414 case RBT: 2415 shutdown_nice(); 2416 break; 2417 case DBG: 2418#if DDB > 0 /* try to switch to console 0 */ 2419 if (cur_console->smode.mode == VT_AUTO && 2420 console[0].smode.mode == VT_AUTO) 2421 switch_scr(0); 2422 Debugger("manual escape to debugger"); 2423 return(NOKEY); 2424#else 2425 printf("No debugger in kernel\n"); 2426#endif 2427 break; 2428 case LSH: 2429 shfts |= 1; 2430 break; 2431 case RSH: 2432 shfts |= 2; 2433 break; 2434 case LCTR: 2435 ctls |= 1; 2436 break; 2437 case RCTR: 2438 ctls |= 2; 2439 break; 2440 case LALT: 2441 alts |= 1; 2442 break; 2443 case RALT: 2444 alts |= 2; 2445 break; 2446 case ASH: 2447 agrs = 1; 2448 break; 2449 case META: 2450 metas = 1; 2451 break; 2452 case NEXT: 2453 switch_scr((get_scr_num()+1)%NCONS); 2454 break; 2455 default: 2456 if (action >= F_SCR && action <= L_SCR) { 2457 switch_scr(action - F_SCR); 2458 break; 2459 } 2460 if (action >= F_FN && action <= L_FN) 2461 action |= FKEY; 2462 return(action); 2463 } 2464 } 2465 else { 2466 if (metas) 2467 action |= MKEY; 2468 return(action); 2469 } 2470 } 2471 goto next_code; 2472} 2473 2474 2475int 2476getchar(void) 2477{ 2478 u_char thechar; 2479 int s; 2480 2481 polling = 1; 2482 s = splhigh(); 2483 scput('>'); 2484 thechar = (u_char) scgetc(0); 2485 polling = 0; 2486 splx(s); 2487 switch (thechar) { 2488 default: 2489 if (thechar >= scr_map[0x20]) 2490 scput(thechar); 2491 return(thechar); 2492 case cr: 2493 case lf: 2494 scput(cr); scput(lf); 2495 return(lf); 2496 case bs: 2497 case del: 2498 scput(bs); scput(scr_map[0x20]); scput(bs); 2499 return(thechar); 2500 case cntld: 2501 scput('^'); scput('D'); scput('\r'); scput('\n'); 2502 return(0); 2503 } 2504} 2505 2506 2507u_int 2508sgetc(int noblock) 2509{ 2510 return (scgetc(noblock) & 0xff); 2511} 2512 2513 2514int 2515pcmmap(dev_t dev, int offset, int nprot) 2516{ 2517 if (offset > 0x20000) 2518 return EINVAL; 2519 return i386_btop((VIDEOMEM + offset)); 2520} 2521 2522 2523static void 2524kbd_wait(void) 2525{ 2526 int i = 1000; 2527 2528 while (i--) { 2529 if ((inb(KB_STAT) & KB_READY) == 0) 2530 break; 2531 DELAY (10); 2532 } 2533} 2534 2535 2536static void 2537kbd_cmd(u_char command) 2538{ 2539 int retry = 5; 2540 do { 2541 int i = 100000; 2542 2543 kbd_wait(); 2544#if ASYNCH 2545 kbd_reply = 0; 2546 outb(KB_DATA, command); 2547 while (i--) { 2548 if (kbd_reply == KB_ACK) 2549 return; 2550 if (kbd_reply == KB_RESEND) 2551 break; 2552 } 2553#else 2554 outb(KB_DATA, command); 2555 while (i--) { 2556 if (inb(KB_STAT) & KB_BUF_FULL) { 2557 int val; 2558 DELAY(10); 2559 val = inb(KB_DATA); 2560 if (val == KB_ACK) 2561 return; 2562 if (val == KB_RESEND) 2563 break; 2564 } 2565 } 2566#endif 2567 } while (retry--); 2568} 2569 2570 2571static void 2572set_mode(scr_stat *scp) 2573{ 2574 u_char byte; 2575 int s; 2576 2577 if (scp != cur_console) 2578 return; 2579 2580 /* (re)activate cursor */ 2581 untimeout((timeout_t)cursor_pos, 0); 2582 cursor_pos(1); 2583 2584 /* change cursor type if set */ 2585 if (scp->cursor_start != -1 && scp->cursor_end != -1) 2586 cursor_shape(scp->cursor_start, scp->cursor_end); 2587 2588 /* mode change only on VGA's */ 2589 if (!crtc_vga) 2590 return; 2591 2592 /* setup video hardware for the given mode */ 2593 s = splhigh(); 2594 switch(scp->mode) { 2595 case TEXT80x25: 2596 outb(crtc_addr, 9); byte = inb(crtc_addr+1); 2597 outb(crtc_addr, 9); outb(crtc_addr+1, byte | 0x0F); 2598 outb(TSIDX, 0x03); outb(TSREG, 0x00); /* select font 0 */ 2599 break; 2600 case TEXT80x50: 2601 outb(crtc_addr, 9); byte = inb(crtc_addr+1); 2602 outb(crtc_addr, 9); outb(crtc_addr+1, (byte & 0xF0) | 0x07); 2603 outb(TSIDX, 0x03); outb(TSREG, 0x05); /* select font 1 */ 2604 break; 2605 default: 2606 break; 2607 } 2608 splx(s); 2609 2610 /* set border color for this (virtual) console */ 2611 set_border(scp->border); 2612 return; 2613} 2614 2615 2616static void 2617set_border(int color) 2618{ 2619 inb(crtc_addr+6); /* reset flip-flop */ 2620 outb(ATC, 0x11); outb(ATC, color); 2621 inb(crtc_addr+6); /* reset flip-flop */ 2622 outb(ATC, 0x20); /* enable Palette */ 2623} 2624 2625 2626static void 2627copy_font(int direction, int segment, int size, char* font) 2628{ 2629 int ch, line, s; 2630 u_char val; 2631 2632 outb(TSIDX, 0x01); val = inb(TSREG); /* blank screen */ 2633 outb(TSIDX, 0x01); outb(TSREG, val | 0x20); 2634 2635 /* setup vga for loading fonts (graphics plane mode) */ 2636 s = splhigh(); 2637 inb(crtc_addr+6); /* reset flip/flop */ 2638 outb(ATC, 0x30); outb(ATC, 0x01); 2639 outb(TSIDX, 0x02); outb(TSREG, 0x04); 2640 outb(TSIDX, 0x04); outb(TSREG, 0x06); 2641 outb(GDCIDX, 0x04); outb(GDCREG, 0x02); 2642 outb(GDCIDX, 0x05); outb(GDCREG, 0x00); 2643 outb(GDCIDX, 0x06); outb(GDCREG, 0x05); /* addr = a0000, 64kb */ 2644 splx(s); 2645 for (ch=0; ch < 256; ch++) 2646 for (line=0; line < size; line++) 2647 if (direction) 2648 *((char *)atdevbase+(segment*0x4000)+(ch*32)+line) = 2649 font[(ch*size)+line]; 2650 else 2651 font[(ch*size)+line] = 2652 *((char *)atdevbase+(segment*0x4000)+(ch*32)+line); 2653 2654 /* setup vga for text mode again */ 2655 s = splhigh(); 2656 inb(crtc_addr+6); /* reset flip/flop */ 2657 outb(ATC, 0x30); outb(ATC, 0x0C); 2658 outb(TSIDX, 0x02); outb(TSREG, 0x03); 2659 outb(TSIDX, 0x04); outb(TSREG, 0x02); 2660 outb(GDCIDX, 0x04); outb(GDCREG, 0x00); 2661 outb(GDCIDX, 0x05); outb(GDCREG, 0x10); 2662 if (crtc_addr == MONO_BASE) { 2663 outb(GDCIDX, 0x06); outb(GDCREG, 0x0A); /* addr = b0000, 32kb */ 2664 } 2665 else { 2666 outb(GDCIDX, 0x06); outb(GDCREG, 0x0E); /* addr = b8000, 32kb */ 2667 } 2668 splx(s); 2669 outb(TSIDX, 0x01); val = inb(TSREG); /* unblank screen */ 2670 outb(TSIDX, 0x01); outb(TSREG, val & 0xDF); 2671} 2672 2673 2674static void 2675load_palette(void) 2676{ 2677 int i; 2678 2679 outb(PIXMASK, 0xFF); /* no pixelmask */ 2680 outb(PALWADR, 0x00); 2681 for (i=0x00; i<0x300; i++) 2682 outb(PALDATA, palette[i]); 2683 inb(crtc_addr+6); /* reset flip/flop */ 2684 outb(ATC, 0x20); /* enable palette */ 2685} 2686 2687 2688static void 2689save_palette(void) 2690{ 2691 int i; 2692 2693 outb(PALRADR, 0x00); 2694 for (i=0x00; i<0x300; i++) 2695 palette[i] = inb(PALDATA); 2696 inb(crtc_addr+6); /* reset flip/flop */ 2697} 2698 2699 2700static void 2701change_winsize(struct tty *tp, int x, int y) 2702{ 2703 if (tp->t_winsize.ws_col != x || tp->t_winsize.ws_row != y) { 2704 tp->t_winsize.ws_col = x; 2705 tp->t_winsize.ws_row = y; 2706 pgsignal(tp->t_pgrp, SIGWINCH, 1); 2707 } 2708} 2709 2710#endif /* NSC */ 2711