Deleted Added
full compact
1/*-
2 * Copyright (c) 1992-1994 S�ren Schmidt
3 * Copyright (c) 1990 The Regents of the University of California.
4 * All rights reserved.
5 *
6 * This code is derived from software contributed to Berkeley by
7 * William Jolitz and Don Ahn.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed by the University of
20 * California, Berkeley and its contributors.
21 * 4. Neither the name of the University nor the names of its contributors
22 * may be used to endorse or promote products derived from this software
23 * without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * SUCH DAMAGE.
36 *
37 * from:@(#)syscons.c 1.3 940129
38 * $Id: syscons.c,v 1.33 1994/02/02 23:10:55 ache Exp $
39 *
40 */
41
42#if !defined(__FreeBSD__)
43#define FAT_CURSOR
44#endif
45
46#include "param.h"
47#include "conf.h"
48#include "ioctl.h"
49#include "proc.h"
50#include "user.h"
51#include "tty.h"
52#include "uio.h"
53#include "callout.h"
54#include "systm.h"
55#include "kernel.h"
56#include "syslog.h"
57#include "errno.h"
58#include "malloc.h"
59#include "i386/isa/isa.h"
60#include "i386/isa/isa_device.h"
61#include "i386/isa/timerreg.h"
62#include "i386/i386/cons.h"
63#include "machine/console.h"
64#include "machine/psl.h"
65#include "machine/frame.h"
66#include "machine/pc/display.h"
67#include "iso8859.font"
68#include "kbdtables.h"
69#include "sc.h"
70
71#if NSC > 0
72
73#if !defined(NCONS)
74#define NCONS 12
75#endif
76
77/* status flags */
78#define LOCK_KEY_MASK 0x0000F
79#define LED_MASK 0x00007
80#define UNKNOWN_MODE 0x00010
81#define KBD_RAW_MODE 0x00020
82#define SWITCH_WAIT_REL 0x00040
83#define SWITCH_WAIT_ACQ 0x00080
84
85/* video hardware memory addresses */
86#define VIDEOMEM 0x000A0000
87
88/* misc defines */
89#define MAX_ESC_PAR 3
90#define TEXT80x25 1
91#define TEXT80x50 2
92#define COL 80
93#define ROW 25
94#define BELL_DURATION 5
95#define BELL_PITCH 800
96#define TIMER_FREQ 1193182 /* should be in isa.h */
97#define PCBURST 128
98
99/* defines related to hardware addresses */
100#define MONO_BASE 0x3B4 /* crt controller base mono */
101#define COLOR_BASE 0x3D4 /* crt controller base color */
102#define ATC IO_VGA+0x00 /* attribute controller */
103#define TSIDX IO_VGA+0x04 /* timing sequencer idx */
104#define TSREG IO_VGA+0x05 /* timing sequencer data */
105#define PIXMASK IO_VGA+0x06 /* pixel write mask */
106#define PALRADR IO_VGA+0x07 /* palette read address */
107#define PALWADR IO_VGA+0x08 /* palette write address */
108#define PALDATA IO_VGA+0x09 /* palette data register */
109#define GDCIDX IO_VGA+0x0E /* graph data controller idx */
110#define GDCREG IO_VGA+0x0F /* graph data controller data */
111
112/* special characters */
113#define cntlc 0x03
114#define cntld 0x04
115#define bs 0x08
116#define lf 0x0a
117#define cr 0x0d
118#define del 0x7f
119
120typedef struct term_stat {
121 int esc; /* processing escape sequence */
122 int num_param; /* # of parameters to ESC */
123 int last_param; /* last parameter # */
124 int param[MAX_ESC_PAR]; /* contains ESC parameters */
125 int cur_attr; /* current attributes */
126 int std_attr; /* normal attributes */
127 int rev_attr; /* reverse attributes */
128} term_stat;
129
130typedef struct scr_stat {
131 u_short *crt_base; /* address of screen memory */
132 u_short *scr_buf; /* buffer when off screen */
133 u_short *crtat; /* cursor address */
134 int xpos; /* current X position */
135 int ypos; /* current Y position */
136 int xsize; /* X size */
137 int ysize; /* Y size */
138 term_stat term; /* terminal emulation stuff */
139 char cursor_start; /* cursor start line # */
140 char cursor_end; /* cursor end line # */
141 u_char border; /* border color */
142 u_short bell_duration;
143 u_short bell_pitch;
144 u_short status; /* status (bitfield) */
145 u_short mode; /* mode */
146 pid_t pid; /* pid of controlling proc */
147 struct proc *proc; /* proc* of controlling proc */
148 struct vt_mode smode; /* switch mode */
149} scr_stat;
150
151typedef struct default_attr {
152 int std_attr; /* normal attributes */
153 int rev_attr; /* reverse attributes */
154} default_attr;
155
156static default_attr user_default = {
157 (FG_LIGHTGREY | BG_BLACK) << 8,
158 (FG_BLACK | BG_LIGHTGREY) << 8
159};
160
161static default_attr kernel_default = {
162 (FG_WHITE | BG_BLACK) << 8,
163 (FG_BLACK | BG_LIGHTGREY) << 8
164};
165
166static scr_stat console[NCONS];
167static scr_stat *cur_console = &console[0];
168static scr_stat *new_scp, *old_scp;
169static term_stat kernel_console;
170static default_attr *current_default;
171static int switch_in_progress = 0;
172static u_short *crtat = 0;
173static u_int crtc_addr = MONO_BASE;
174static char crtc_vga = 0;
175static u_char shfts = 0, ctls = 0, alts = 0, agrs = 0, metas = 0;
176static u_char nlkcnt = 0, clkcnt = 0, slkcnt = 0, alkcnt = 0;
177static char palette[3*256];
178static const u_int n_fkey_tab = sizeof(fkey_tab) / sizeof(*fkey_tab);
179static int cur_cursor_pos = -1;
180static char in_putc = 0;
181static char polling = 0;
182static int delayed_next_scr;
183static char saved_console = -1; /* saved console number */
184static long scrn_blank_time = 0; /* screen saver timout value */
185static int scrn_blanked = 0; /* screen saver active flag */
186static int scrn_saver = 0; /* screen saver routine */
187static long scrn_time_stamp;
188static u_char scr_map[256];
189extern int hz;
190extern struct timeval time;
191
192/* function prototypes */
193int pcprobe(struct isa_device *dev);
194int pcattach(struct isa_device *dev);
195int pcopen(dev_t dev, int flag, int mode, struct proc *p);
196int pcclose(dev_t dev, int flag, int mode, struct proc *p);
197int pcread(dev_t dev, struct uio *uio, int flag);
198int pcwrite(dev_t dev, struct uio *uio, int flag);
199int pcparam(struct tty *tp, struct termios *t);
200int pcioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p);
201void pcxint(dev_t dev);
202void pcstart(struct tty *tp);
203void pccnprobe(struct consdev *cp);
204void pccninit(struct consdev *cp);
205void pccnputc(dev_t dev, char c);
206int pccngetc(dev_t dev);
207void scintr(int unit);
208int pcmmap(dev_t dev, int offset, int nprot);
209u_int sgetc(int noblock);
210int getchar(void);
211static void scinit(void);
212static void scput(u_char c);
213static u_int scgetc(int noblock);
214static struct tty *get_tty_ptr(dev_t dev);
215static scr_stat *get_scr_stat(dev_t dev);
216static int get_scr_num();
217static void cursor_shape(int start, int end);
218static void get_cursor_shape(int *start, int *end);
219static void cursor_pos(int force);
220static void clear_screen(scr_stat *scp);
221static int switch_scr(u_int next_scr);
222static void exchange_scr(void);
223static void move_crsr(scr_stat *scp, int x, int y);
224static void move_up(u_short *s, u_short *d, u_int len);
225static void move_down(u_short *s, u_short *d, u_int len);
226static void scan_esc(scr_stat *scp, u_char c);
227static void ansi_put(scr_stat *scp, u_char c);
228static u_char *get_fstr(u_int c, u_int *len);
229static void update_leds(int which);
230static void kbd_wait(void);
231static void kbd_cmd(u_char command);
232static void kbd_cmd2(u_char command, u_char arg);
233static int kbd_reply(void);
234static void set_mode(scr_stat *scp);
235static void set_border(int color);
236static void load_font(int segment, int size, char* font);
237static void save_palette(void);
238static void load_palette(void);
239static void change_winsize(struct tty *tp, int x, int y);
240
241
242/* available screen savers */
243
244static void none_saver(int test);
245static void blank_saver(int test);
246static void fade_saver(int test);
247static void star_saver(int test);
248static void snake_saver(int test);
249
250static const struct {
251 char *name;
252 void (*routine)();
253} screen_savers[] = {
254 { "none", none_saver }, /* 0 */
255 { "blank", blank_saver }, /* 1 */
256 { "fade", fade_saver }, /* 2 */
257 { "star", star_saver }, /* 3 */
258 { "snake", snake_saver }, /* 4 */
259};
260#define SCRN_SAVER(arg) (*screen_savers[scrn_saver].routine)(arg)
261#define NUM_SCRN_SAVERS (sizeof(screen_savers) / sizeof(screen_savers[0]))
262
263/* OS specific stuff */
264
265#if defined(NetBSD)
266#define VIRTUAL_TTY(x) pc_tty[x] ? (pc_tty[x]) : (pc_tty[x] = ttymalloc())
267#define CONSOLE_TTY pc_tty[NCONS] ? (pc_tty[NCONS]) : (pc_tty[NCONS] = ttymalloc())
268#define frametype struct trapframe
269#define eflags tf_eflags
270extern u_short *Crtat;
271struct tty *pc_tty[NCONS+1];
272int ttrstrt();
273#endif
274
275#if defined(__FreeBSD__)
276#define frametype struct trapframe
277#define eflags tf_eflags
278#define timeout_t timeout_func_t
279#define MONO_BUF (KERNBASE+0xB0000)
280#define CGA_BUF (KERNBASE+0xB8000)
281#endif
282
283#if defined(__386BSD__) && !defined(__FreeBSD__)
284#define frametype struct syscframe
285#define eflags sf_eflags
286#define timeout_t caddr_t
287#define MONO_BUF (0xFE0B0000)
288#define CGA_BUF (0xFE0B8000)
289#endif
290
291#if defined(__386BSD__) || defined(__FreeBSD__)
292#define VIRTUAL_TTY(x) &pccons[x]
293#define CONSOLE_TTY &pccons[NCONS]
294u_short *Crtat = (u_short *)MONO_BUF;
295struct tty pccons[NCONS+1];
296void consinit(void) {scinit();}
297#include "ddb.h"
298#if NDDB > 0
299#define DDB 1
300#endif
301#endif
302
303
304struct isa_driver scdriver = {
305 pcprobe, pcattach, "sc",
306};
307
308
309int pcprobe(struct isa_device *dev)
310{
311 /* Enable interrupts and keyboard controller */
312 kbd_wait();
313 outb(KB_STAT, KB_WRITE);
314 kbd_cmd(0x4D);
315
316 /* Start keyboard stuff RESET */
317 for (;;) {
318 kbd_cmd(KB_RESET);
319 if (kbd_reply() == KB_ACK && /* command accepted */
320 kbd_reply() == 0xaa) /* self test passed */
321 break;
322 printf("Keyboard reset failed\n");
323 }
324 return (IO_KBDSIZE);
325}
326
327
328int pcattach(struct isa_device *dev)
329{
330 scr_stat *scp;
331 int start = -1, end = -1, i;
332
333 printf("sc%d: ", dev->id_unit);
334 if (crtc_vga)
335 if (crtc_addr == MONO_BASE)
336 printf("VGA mono");
337 else
338 printf("VGA color");
339 else
340 if (crtc_addr == MONO_BASE)
341 printf("MDA/hercules");
342 else
343 printf("CGA/EGA");
344
345 if (NCONS > 1)
346 printf(" <%d virtual consoles>\n", NCONS);
347 else
348 printf("\n");
349#if defined(FAT_CURSOR)
350 start = 0;
351 end = 18;
352 if (crtc_vga) {
353#else
354 if (crtc_vga) {
355 get_cursor_shape(&start, &end);
356#endif
357 save_palette();
358 load_font(0, 16, font_8x16);
359 load_font(1, 8, font_8x8);
360 load_font(2, 14, font_8x14);
361 }
362 current_default = &user_default;
363 for (i = 0; i < NCONS; i++) {
364 scp = &console[i];
365 scp->scr_buf = (u_short *)malloc(COL * ROW * 2, M_DEVBUF, M_NOWAIT);
366 scp->mode = TEXT80x25;
367 scp->term.esc = 0;
368 scp->term.std_attr = current_default->std_attr;
369 scp->term.rev_attr = current_default->rev_attr;
370 scp->term.cur_attr = scp->term.std_attr;
371 scp->border = BG_BLACK;
372 scp->cursor_start = start;
373 scp->cursor_end = end;
374 scp->xsize = COL;
375 scp->ysize = ROW;
376 scp->bell_pitch = BELL_PITCH;
377 scp->bell_duration = BELL_DURATION;
378 scp->status = 0;
379 scp->pid = 0;
380 scp->proc = NULL;
381 scp->smode.mode = VT_AUTO;
382 if (i > 0) {
383 scp->crt_base = scp->crtat = scp->scr_buf;
384 fillw(scp->term.cur_attr|scr_map[0x20], scp->scr_buf, COL*ROW);
385 }
386 }
387 /* get cursor going */
388#if defined(FAT_CURSOR)
389 cursor_shape(console[0].cursor_start,
390 console[0].cursor_end);
391#endif
392 cursor_pos(1);
393 return 0;
394}
395
396
397static struct tty *get_tty_ptr(dev_t dev)
398{
399 int unit = minor(dev);
400
401 if (unit > NCONS)
402 return(NULL);
403 if (unit == NCONS)
404 return(CONSOLE_TTY);
405 return(VIRTUAL_TTY(unit));
406}
407
408
409static scr_stat *get_scr_stat(dev_t dev)
410{
411 int unit = minor(dev);
412
413 if (unit > NCONS)
414 return(NULL);
415 if (unit == NCONS)
416 return(&console[0]);
417 return(&console[unit]);
418}
419
420
421static int get_scr_num()
422{
423 int i = 0;
424
425 while ((i < NCONS) && (cur_console != &console[i])) i++;
426 return i < NCONS ? i : 0;
427}
428
429int pcopen(dev_t dev, int flag, int mode, struct proc *p)
430{
431 struct tty *tp = get_tty_ptr(dev);
432
433 if (!tp)
434 return(ENXIO);
435
436 tp->t_oproc = pcstart;
437 tp->t_param = pcparam;
438 tp->t_dev = dev;
439 if (!(tp->t_state & TS_ISOPEN)) {
440 tp->t_state |= TS_WOPEN;
441 ttychars(tp);
442 tp->t_iflag = TTYDEF_IFLAG;
443 tp->t_oflag = TTYDEF_OFLAG;
444 tp->t_cflag = TTYDEF_CFLAG;
445 tp->t_lflag = TTYDEF_LFLAG;
446 tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
447 pcparam(tp, &tp->t_termios);
448 ttsetwater(tp);
449 } else if (tp->t_state&TS_XCLUDE && p->p_ucred->cr_uid != 0)
450 return(EBUSY);
451 tp->t_state |= TS_CARR_ON;
452 tp->t_cflag |= CLOCAL;
453#if defined(__FreeBSD__)
454 return((*linesw[tp->t_line].l_open)(dev, tp, 0));
455#else
456 return((*linesw[tp->t_line].l_open)(dev, tp));
457#endif
458}
459
460
461int pcclose(dev_t dev, int flag, int mode, struct proc *p)
462{
463 struct tty *tp = get_tty_ptr(dev);
464 struct scr_stat *scp;
465
466 if (!tp)
467 return(ENXIO);
468 if (minor(dev) < NCONS) {
469 scp = get_scr_stat(tp->t_dev);
470 if (scp->status & SWITCH_WAIT_ACQ)
471 wakeup((caddr_t)&scp->smode);
472 scp->pid = 0;
473 scp->proc = NULL;
474 scp->smode.mode = VT_AUTO;
475 }
476 (*linesw[tp->t_line].l_close)(tp, flag);
477 ttyclose(tp);
478 return(0);
479}
480
481
482int pcread(dev_t dev, struct uio *uio, int flag)
483{
484 struct tty *tp = get_tty_ptr(dev);
485
486 if (!tp)
487 return(ENXIO);
488 return((*linesw[tp->t_line].l_read)(tp, uio, flag));
489}
490
491
492int pcwrite(dev_t dev, struct uio *uio, int flag)
493{
494 struct tty *tp = get_tty_ptr(dev);
495
496 if (!tp)
497 return(ENXIO);
498 return((*linesw[tp->t_line].l_write)(tp, uio, flag));
499}
500
501
502/*
503 * Got a console interrupt, keyboard action !
504 * Catch the character, and see who it goes to.
505 */
506void scintr(int unit)
507{
508 static struct tty *cur_tty;
509 int c, len;
510 u_char *cp;
511
512 /* make screensaver happy */
513 scrn_time_stamp = time.tv_sec;
514 if (scrn_blanked)
515 SCRN_SAVER(0);
516
517 c = scgetc(1);
518
519 cur_tty = VIRTUAL_TTY(get_scr_num());
520 if (!(cur_tty->t_state & TS_ISOPEN))
521 cur_tty = CONSOLE_TTY;
522
523 if (!(cur_tty->t_state & TS_ISOPEN) || polling)
524 return;
525
526 switch (c & 0xff00) {
527 case 0x0000: /* normal key */
528 (*linesw[cur_tty->t_line].l_rint)(c & 0xFF, cur_tty);
529 break;
530 case NOKEY: /* nothing there */
531 break;
532 case FKEY: /* function key, return string */
533 if (cp = get_fstr((u_int)c, (u_int *)&len)) {
534 while (len-- > 0)
535 (*linesw[cur_tty->t_line].l_rint)
536 (*cp++ & 0xFF, cur_tty);
537 }
538 break;
539 case MKEY: /* meta is active, prepend ESC */
540 (*linesw[cur_tty->t_line].l_rint)(0x1b, cur_tty);
541 (*linesw[cur_tty->t_line].l_rint)(c & 0xFF, cur_tty);
542 break;
543 }
544}
545
546
547/*
548 * Set line parameters
549 */
550int pcparam(struct tty *tp, struct termios *t)
551{
552 int cflag = t->c_cflag;
553
554 /* and copy to tty */
555 tp->t_ispeed = t->c_ispeed;
556 tp->t_ospeed = t->c_ospeed;
557 tp->t_cflag = cflag;
558 return 0;
559}
560
561
562int pcioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p)
563{
564 int i, error;
565 struct tty *tp;
566 frametype *fp;
567 scr_stat *scp;
568
569 tp = get_tty_ptr(dev);
570 if (!tp)
571 return ENXIO;
572 scp = get_scr_stat(tp->t_dev);
573
574 switch (cmd) { /* process console hardware related ioctl's */
575
576 case CONS_BLANKTIME: /* set screen saver timeout (0 = no saver) */
577 scrn_blank_time = *(int*)data;
578 return 0;
579 case CONS_SSAVER: /* set screen saver */
580 {
581 register ssaver_t *sav = (ssaver_t *)data;
582 if (sav->num < 0 || sav->num >= NUM_SCRN_SAVERS)
583 return EIO;
584 SCRN_SAVER(0);
585 scrn_saver = sav->num;
586 scrn_blank_time = sav->time;
587 return 0;
588 }
589 case CONS_GSAVER: /* get screen saver info */
590 {
591 register ssaver_t *sav = (ssaver_t *)data;
592 if (sav->num < 0)
593 sav->num = scrn_saver;
594 else if (sav->num >= NUM_SCRN_SAVERS)
595 return EIO;
596 sav->time = scrn_blank_time;
597 strcpy(sav->name, screen_savers[sav->num].name);
598 return 0;
599 }
600 case CONS_80x25TEXT: /* set 80x25 text mode */
601 if (!crtc_vga)
602 return ENXIO;
603 scp->mode = TEXT80x25;
604 scp->ysize = 25;
605 free(scp->scr_buf, M_DEVBUF);
606 scp->scr_buf = (u_short *)malloc(scp->xsize*scp->ysize*2,
607 M_DEVBUF, M_NOWAIT);
608 if (scp != cur_console)
609 scp->crt_base = scp->scr_buf;
610 set_mode(scp);
611 clear_screen(scp);
612 change_winsize(tp, scp->xsize, scp->ysize);
613 return 0;
614
615 case CONS_80x50TEXT: /* set 80x50 text mode */
616 if (!crtc_vga)
617 return ENXIO;
618 scp->mode = TEXT80x50;
619 scp->ysize = 50;
620 free(scp->scr_buf, M_DEVBUF);
621 scp->scr_buf = (u_short *)malloc(scp->xsize*scp->ysize*2,
622 M_DEVBUF, M_NOWAIT);
623 if (scp != cur_console)
624 scp->crt_base = scp->scr_buf;
625 set_mode(scp);
626 clear_screen(scp);
627 change_winsize(tp, scp->xsize, scp->ysize);
628 return 0;
629
630 case CONS_GETVERS: /* get version number */
631 *(int*)data = 0x103; /* version 1.3 */
632 return 0;
633
634 case CONS_GETINFO: /* get current (virtual) console info */
635 if (*data == sizeof(struct vid_info)) {
636 vid_info_t *ptr = (vid_info_t*)data;
637 ptr->m_num = get_scr_num();
638 ptr->mv_col = scp->xpos;
639 ptr->mv_row = scp->ypos;
640 ptr->mv_csz = scp->xsize;
641 ptr->mv_rsz = scp->ysize;
642 ptr->mv_norm.fore = (scp->term.std_attr & 0x0f00)>>8;
643 ptr->mv_norm.back = (scp->term.std_attr & 0xf000)>>12;
644 ptr->mv_rev.fore = (scp->term.rev_attr & 0x0f00)>>8;
645 ptr->mv_rev.back = (scp->term.rev_attr & 0xf000)>>12;
646 ptr->mv_grfc.fore = 0; /* not supported */
647 ptr->mv_grfc.back = 0; /* not supported */
648 ptr->mv_ovscan = scp->border;
649 ptr->mk_keylock = scp->status & LOCK_KEY_MASK;
650 return 0;
651 }
652 return EINVAL;
653
654 case VT_SETMODE: /* set screen switcher mode */
655 bcopy(data, &scp->smode, sizeof(struct vt_mode));
656 if (scp->smode.mode == VT_PROCESS) {
657 scp->proc = p;
658 scp->pid = scp->proc->p_pid;
659 }
660 return 0;
661
662 case VT_GETMODE: /* get screen switcher mode */
663 bcopy(&scp->smode, data, sizeof(struct vt_mode));
664 return 0;
665
666 case VT_RELDISP: /* screen switcher ioctl */
667 switch(*data) {
668 case VT_FALSE: /* user refuses to release screen, abort */
669 if (scp == old_scp && (scp->status & SWITCH_WAIT_REL)) {
670 old_scp->status &= ~SWITCH_WAIT_REL;
671 switch_in_progress = 0;
672 return 0;
673 }
674 return EINVAL;
675
676 case VT_TRUE: /* user has released screen, go on */
677 if (scp == old_scp && (scp->status & SWITCH_WAIT_REL)) {
678 scp->status &= ~SWITCH_WAIT_REL;
679 exchange_scr();
680 if (new_scp->smode.mode == VT_PROCESS) {
681 new_scp->status |= SWITCH_WAIT_ACQ;
682 psignal(new_scp->proc,
683 new_scp->smode.acqsig);
684 }
685 else
686 switch_in_progress = 0;
687 return 0;
688 }
689 return EINVAL;
690
691 case VT_ACKACQ: /* acquire acknowledged, switch completed */
692 if (scp == new_scp && (scp->status & SWITCH_WAIT_ACQ)) {
693 scp->status &= ~SWITCH_WAIT_ACQ;
694 switch_in_progress = 0;
695 return 0;
696 }
697 return EINVAL;
698
699 default:
700 return EINVAL;
701 }
702 /* NOT REACHED */
703
704 case VT_OPENQRY: /* return free virtual console */
705 for (i = 0; i < NCONS; i++) {
706 tp = VIRTUAL_TTY(i);
707 if (!(tp->t_state & TS_ISOPEN)) {
708 *data = i + 1;
709 return 0;
710 }
711 }
712 return EINVAL;
713
714 case VT_ACTIVATE: /* switch to screen *data */
715 return switch_scr((*data) - 1);
716
717 case VT_WAITACTIVE: /* wait for switch to occur */
718 if (*data > NCONS)
719 return EINVAL;
720 if (minor(dev) == (*data) - 1)
721 return 0;
722 if (*data == 0) {
723 if (scp == cur_console)
724 return 0;
725 while ((error=tsleep((caddr_t)&scp->smode,
726 PZERO|PCATCH, "waitvt", 0)) == ERESTART) ;
727 }
728 else
729 while ((error=tsleep(
730 (caddr_t)&console[*(data-1)].smode,
731 PZERO|PCATCH, "waitvt", 0)) == ERESTART) ;
732 return error;
733
734 case VT_GETACTIVE:
735 *data = get_scr_num()+1;
736 return 0;
737
738 case KDENABIO: /* allow io operations */
739 fp = (frametype *)p->p_regs;
740 fp->eflags |= PSL_IOPL;
741 return 0;
742
743 case KDDISABIO: /* disallow io operations (default) */
744 fp = (frametype *)p->p_regs;
745 fp->eflags &= ~PSL_IOPL;
746 return 0;
747
748 case KDSETMODE: /* set current mode of this (virtual) console */
749 switch (*data) {
750 case KD_TEXT: /* switch to TEXT (known) mode */
751 /* restore fonts & palette ! */
752 if (crtc_vga) {
753 load_font(0, 16, font_8x16);
754 load_font(1, 8, font_8x8);
755 load_font(2, 14, font_8x14);
756 load_palette();
757 }
758 /* FALL THROUGH */
759
760 case KD_TEXT1: /* switch to TEXT (known) mode */
761 /* no restore fonts & palette */
762 scp->status &= ~UNKNOWN_MODE;
763 set_mode(scp);
764 clear_screen(scp);
765 return 0;
766
767 case KD_GRAPHICS:/* switch to GRAPHICS (unknown) mode */
768 scp->status |= UNKNOWN_MODE;
769 return 0;
770 default:
771 return EINVAL;
772 }
773 /* NOT REACHED */
774
775 case KDGETMODE: /* get current mode of this (virtual) console */
776 *data = (scp->status & UNKNOWN_MODE) ? KD_GRAPHICS : KD_TEXT;
777 return 0;
778
779 case KDSBORDER: /* set border color of this (virtual) console */
780 if (!crtc_vga)
781 return ENXIO;
782 scp->border = *data;
783 if (scp == cur_console)
784 set_border(scp->border);
785 return 0;
786
787 case KDSKBSTATE: /* set keyboard state (locks) */
788 if (*data >= 0 && *data <= LOCK_KEY_MASK) {
789 scp->status &= ~LOCK_KEY_MASK;
790 scp->status |= *data;
791 if (scp == cur_console)
792 update_leds(scp->status & LED_MASK);
793 return 0;
794 }
795 return EINVAL;
796
797 case KDGKBSTATE: /* get keyboard state (locks) */
798 *data = scp->status & LOCK_KEY_MASK;
799 return 0;
800
801 case KDSETRAD: /* set keyboard repeat & delay rates */
802 if (*data & 0x80)
803 return EINVAL;
804 kbd_cmd2(KB_SETRAD, *data);
805 return 0;
806
807 case KDSKBMODE: /* set keyboard mode */
808 switch (*data) {
809 case K_RAW: /* switch to RAW scancode mode */
810 scp->status |= KBD_RAW_MODE;
811 return 0;
812
813 case K_XLATE: /* switch to XLT ascii mode */
814 if (scp == cur_console && scp->status == KBD_RAW_MODE)
815 shfts = ctls = alts = agrs = metas = 0;
816 scp->status &= ~KBD_RAW_MODE;
817 return 0;
818 default:
819 return EINVAL;
820 }
821 /* NOT REACHED */
822
823 case KDGKBMODE: /* get keyboard mode */
824 *data = (scp->status & KBD_RAW_MODE) ? K_RAW : K_XLATE;
825 return 0;
826
827 case KDMKTONE: /* sound the bell */
828 if (scp == cur_console)
829 sysbeep(scp->bell_pitch, scp->bell_duration);
830 return 0;
831
832 case KIOCSOUND: /* make tone (*data) hz */
833 if (scp == cur_console) {
834 if (*(int*)data) {
835 int pitch = TIMER_FREQ/(*(int*)data);
836 /* enable counter 2 */
837 outb(0x61, inb(0x61) | 3);
838 /* set command for counter 2, 2 byte write */
839 outb(TIMER_MODE,
840 TIMER_SEL2|TIMER_16BIT|TIMER_SQWAVE);
841 /* set pitch */
842 outb(TIMER_CNTR2, pitch);
843 outb(TIMER_CNTR2, (pitch>>8));
844 }
845 else {
846 /* disable counter 2 */
847 outb(0x61, inb(0x61) & 0xFC);
848 }
849 }
850 return 0;
851
852 case KDGKBTYPE: /* get keyboard type */
853 *data = 0; /* type not known (yet) */
854 return 0;
855
856 case KDSETLED: /* set keyboard LED status */
857 if (*data >= 0 && *data <= LED_MASK) {
858 scp->status &= ~LED_MASK;
859 scp->status |= *data;
860 if (scp == cur_console)
861 update_leds(scp->status & LED_MASK);
862 return 0;
863 }
864 return EINVAL;
865
866 case KDGETLED: /* get keyboard LED status */
867 *data = scp->status & LED_MASK;
868 return 0;
869
870 case GETFKEY: /* get functionkey string */
871 if (*(u_short*)data < n_fkey_tab) {
872 fkeyarg_t *ptr = (fkeyarg_t*)data;
873 bcopy(&fkey_tab[ptr->keynum].str,
874 ptr->keydef,
875 fkey_tab[ptr->keynum].len);
876 ptr->flen = fkey_tab[ptr->keynum].len;
877 return 0;
878 }
879 else
880 return EINVAL;
881
882 case SETFKEY: /* set functionkey string */
883 if (*(u_short*)data < n_fkey_tab) {
884 fkeyarg_t *ptr = (fkeyarg_t*)data;
885 bcopy(ptr->keydef,
886 &fkey_tab[ptr->keynum].str,
887 min(ptr->flen, MAXFK));
888 fkey_tab[ptr->keynum].len = min(ptr->flen, MAXFK);
889 return 0;
890 }
891 else
892 return EINVAL;
893
894 case GIO_SCRNMAP: /* get output translation table */
895 bcopy(&scr_map, data, sizeof(scr_map));
896 return 0;
897
898 case PIO_SCRNMAP: /* set output translation table */
899 bcopy(data, &scr_map, sizeof(scr_map));
900 return 0;
901
902 case GIO_KEYMAP: /* get keyboard translation table */
903 bcopy(&key_map, data, sizeof(key_map));
904 return 0;
905
906 case PIO_KEYMAP: /* set keyboard translation table */
907 bcopy(data, &key_map, sizeof(key_map));
908 return 0;
909
910 case PIO_FONT8x8: /* set 8x8 dot font */
911 if (!crtc_vga)
912 return ENXIO;
913 bcopy(data, &font_8x8, sizeof(font_8x8));
914 load_font(1, 8, font_8x8);
915 return 0;
916
917 case GIO_FONT8x8: /* get 8x8 dot font */
918 if (!crtc_vga)
919 return ENXIO;
920 bcopy(&font_8x8, data, sizeof(font_8x8));
921 return 0;
922
923 case PIO_FONT8x14: /* set 8x14 dot font */
924 if (!crtc_vga)
925 return ENXIO;
926 bcopy(data, &font_8x14, sizeof(font_8x14));
927 load_font(2, 14, font_8x14);
928 return 0;
929
930 case GIO_FONT8x14: /* get 8x14 dot font */
931 if (!crtc_vga)
932 return ENXIO;
933 bcopy(&font_8x14, data, sizeof(font_8x14));
934 return 0;
935
936 case PIO_FONT8x16: /* set 8x16 dot font */
937 if (!crtc_vga)
938 return ENXIO;
939 bcopy(data, &font_8x16, sizeof(font_8x16));
940 load_font(0, 16, font_8x16);
941 return 0;
942
943 case GIO_FONT8x16: /* get 8x16 dot font */
944 if (!crtc_vga)
945 return ENXIO;
946 bcopy(&font_8x16, data, sizeof(font_8x16));
947 return 0;
948
949 case CONSOLE_X_MODE_ON: /* just to be compatible */
950 if (saved_console < 0) {
951 saved_console = get_scr_num();
952 switch_scr(minor(dev));
953 fp = (frametype *)p->p_regs;
954 fp->eflags |= PSL_IOPL;
955 scp->status |= UNKNOWN_MODE;
956 scp->status |= KBD_RAW_MODE;
957 return 0;
958 }
959 return EAGAIN;
960
961 case CONSOLE_X_MODE_OFF:/* just to be compatible */
962 fp = (frametype *)p->p_regs;
963 fp->eflags &= ~PSL_IOPL;
964 if (crtc_vga) {
965 load_font(0, 16, font_8x16);
966 load_font(1, 8, font_8x8);
967 load_font(2, 14, font_8x14);
968 load_palette();
969 }
970 scp->status &= ~UNKNOWN_MODE;
971 set_mode(scp);
972 clear_screen(scp);
973 scp->status &= ~KBD_RAW_MODE;
974 switch_scr(saved_console);
975 saved_console = -1;
976 return 0;
977
978 case CONSOLE_X_BELL: /* more compatibility */
979 /*
980 * if set, data is a pointer to a length 2 array of
981 * integers. data[0] is the pitch in Hz and data[1]
982 * is the duration in msec.
983 */
984 if (data)
985 sysbeep(TIMER_FREQ/((int*)data)[0],
986 ((int*)data)[1]*hz/3000);
987 else
988 sysbeep(scp->bell_pitch, scp->bell_duration);
989 return 0;
990
991 default:
992 break;
993 }
994
995 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag);
996 if (error >= 0)
997 return(error);
998 error = ttioctl(tp, cmd, data, flag);
999 if (error >= 0)
1000 return(error);
1001 return(ENOTTY);
1002}
1003
1004
1005void pcxint(dev_t dev)
1006{
1007 struct tty *tp = get_tty_ptr(dev);
1008
1009 if (!tp)
1010 return;
1011 tp->t_state &= ~TS_BUSY;
1012 if (tp->t_line)
1013 (*linesw[tp->t_line].l_start)(tp);
1014 else
1015 pcstart(tp);
1016}
1017
1018
1019void pcstart(struct tty *tp)
1020{
1021#if defined(NetBSD)
1022 struct clist *rbp;
1023 int i, s, len;
1024 u_char buf[PCBURST];
1025 scr_stat *scp = get_scr_stat(tp->t_dev);
1026
1027 if (scp->status & SLKED)
1028 return;
1029 s = spltty();
1030 if (!(tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))) {
1031 tp->t_state |= TS_BUSY;
1032 splx(s);
1033 rbp = &tp->t_outq;
1034 len = q_to_b(rbp, buf, PCBURST);
1035 for (i=0; i<len; i++)
1036 if (buf[i]) ansi_put(scp, buf[i]);
1037 s = spltty();
1038 tp->t_state &= ~TS_BUSY;
1039 if (rbp->c_cc) {
1040 tp->t_state |= TS_TIMEOUT;
1041 timeout((timeout_t)ttrstrt, (caddr_t)tp, 1);
1042 }
1043 if (rbp->c_cc <= tp->t_lowat) {
1044 if (tp->t_state & TS_ASLEEP) {
1045 tp->t_state &= ~TS_ASLEEP;
1046 wakeup((caddr_t)rbp);
1047 }
1048 selwakeup(&tp->t_wsel);
1049 }
1050 }
1051 splx(s);
1052
1053#else /* __FreeBSD__ & __386BSD__ */
1054
1055 int c, s;
1056 scr_stat *scp = get_scr_stat(tp->t_dev);
1057
1058 if (scp->status & SLKED)
1059 return;
1060 s = spltty();
1061 if (!(tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP)))
1062 for (;;) {
1063 if (RB_LEN(&tp->t_out) <= tp->t_lowat) {
1064 if (tp->t_state & TS_ASLEEP) {
1065 tp->t_state &= ~TS_ASLEEP;
1066 wakeup((caddr_t)&tp->t_out);
1067 }
1068 if (tp->t_wsel) {
1069 selwakeup(tp->t_wsel,
1070 tp->t_state & TS_WCOLL);
1071 tp->t_wsel = 0;
1072 tp->t_state &= ~TS_WCOLL;
1073 }
1074 }
1075 if (RB_LEN(&tp->t_out) == 0)
1076 break;
1077 if (scp->status & SLKED)
1078 break;
1079 c = getc(&tp->t_out);
1080 tp->t_state |= TS_BUSY;
1081 splx(s);
1082 ansi_put(scp, c);
1083 s = spltty();
1084 tp->t_state &= ~TS_BUSY;
1085 }
1086 splx(s);
1087#endif
1088}
1089
1090
1091void pccnprobe(struct consdev *cp)
1092{
1093 int maj;
1094
1095 /* locate the major number */
1096 for (maj = 0; maj < nchrdev; maj++)
1097 if ((void*)cdevsw[maj].d_open == (void*)pcopen)
1098 break;
1099
1100 /* initialize required fields */
1101 cp->cn_dev = makedev(maj, NCONS);
1102 cp->cn_pri = CN_INTERNAL;
1103#if defined(__FreeBSD__) || defined(__386BSD__)
1104 cp->cn_tp = CONSOLE_TTY;
1105#endif
1106}
1107
1108
1109void pccninit(struct consdev *cp)
1110{
1111 scinit();
1112}
1113
1114
1115void pccnputc(dev_t dev, char c)
1116{
1117 if (c == '\n')
1118 scput('\r');
1119 scput(c);
1120 if (cur_console == &console[0]) {
1121 int pos = cur_console->crtat - cur_console->crt_base;
1122 if (pos != cur_cursor_pos) {
1123 cur_cursor_pos = pos;
1124 outb(crtc_addr,14);
1125 outb(crtc_addr+1,pos >> 8);
1126 outb(crtc_addr,15);
1127 outb(crtc_addr+1,pos&0xff);
1128 }
1129 }
1130}
1131
1132
1133int pccngetc(dev_t dev)
1134{
1135 int s = spltty(); /* block scintr while we poll */
1136 int c = scgetc(0);
1137 splx(s);
1138 if (c == '\r') c = '\n';
1139 return(c);
1140}
1141
1142static void none_saver(int test)
1143{
1144}
1145
1146static void fade_saver(int test)
1147{
1148 static int count = 0;
1149 int i;
1150
1151 if (test) {
1152 scrn_blanked = 1;
1153 if (count < 64) {
1154 outb(PIXMASK, 0xFF); /* no pixelmask */
1155 outb(PALWADR, 0x00);
1156 outb(PALDATA, 0);
1157 outb(PALDATA, 0);
1158 outb(PALDATA, 0);
1159 for (i = 3; i < 768; i++) {
1160 if (palette[i] - count > 15)
1161 outb(PALDATA, palette[i]-count);
1162 else
1163 outb(PALDATA, 15);
1164 }
1165 inb(crtc_addr+6); /* reset flip/flop */
1166 outb(ATC, 0x20); /* enable palette */
1167 count++;
1168 }
1169 }
1170 else {
1171 count = scrn_blanked = 0;
1172 load_palette();
1173 }
1174}
1175
1176static void blank_saver(int test)
1177{
1178 u_char val;
1179 if (test) {
1180 scrn_blanked = 1;
1181 outb(TSIDX, 0x01); val = inb(TSREG);
1182 outb(TSIDX, 0x01); outb(TSREG, val | 0x20);
1183 }
1184 else {
1185 scrn_blanked = 0;
1186 outb(TSIDX, 0x01); val = inb(TSREG);
1187 outb(TSIDX, 0x01); outb(TSREG, val & 0xDF);
1188 }
1189}
1190
1191static u_long rand_next = 1;
1192
1193static int rand()
1194{
1195 return ((rand_next = rand_next * 1103515245 + 12345) & 0x7FFFFFFF);
1196}
1197
1198/*
1199 * Alternate saver that got its inspiration from a well known utility
1200 * package for an unfamous OS.
1201 */
1202
1203#define NUM_STARS 50
1204
1205static void star_saver(int test)
1206{
1207 scr_stat *scp = cur_console;
1208 int cell, i;
1209 char pattern[] = {"...........++++*** "};
1210 char colors[] = {FG_DARKGREY, FG_LIGHTGREY,
1211 FG_WHITE, FG_LIGHTCYAN};
1212 static u_short stars[NUM_STARS][2];
1213
1214 if (test) {
1215 if (!scrn_blanked) {
1216 bcopy(Crtat, scp->scr_buf,
1217 scp->xsize * scp->ysize * 2);
1218 fillw((FG_LIGHTGREY|BG_BLACK)<<8 | scr_map[0x20], Crtat,
1219 scp->xsize * scp->ysize);
1220 set_border(0);
1221 i = scp->ysize * scp->xsize + 5;
1222 outb(crtc_addr, 14);
1223 outb(crtc_addr+1, i >> 8);
1224 outb(crtc_addr, 15);
1225 outb(crtc_addr+1, i & 0xff);
1226 scrn_blanked = 1;
1227 for(i=0; i<NUM_STARS; i++) {
1228 stars[i][0] =
1229 rand() % (scp->xsize*scp->ysize);
1230 stars[i][1] = 0;
1231 }
1232 }
1233 cell = rand() % NUM_STARS;
1234 *((u_short*)(Crtat + stars[cell][0])) =
1235 scr_map[pattern[stars[cell][1]]] |
1236 colors[rand()%sizeof(colors)] << 8;
1237 if ((stars[cell][1]+=(rand()%4)) >= sizeof(pattern)-1) {
1238 stars[cell][0] = rand() % (scp->xsize*scp->ysize);
1239 stars[cell][1] = 0;
1240 }
1241 }
1242 else {
1243 if (scrn_blanked) {
1244 bcopy(scp->scr_buf, Crtat, scp->xsize*scp->ysize*2);
1245 cur_cursor_pos = -1;
1246 set_border(scp->border);
1247 scrn_blanked = 0;
1248 }
1249 }
1250}
1251
1252
1253static void snake_saver(int test)
1254{
1255 const char saves[] = {"FreeBSD"};
1256 static u_char *savs[sizeof(saves)-1];
1257 static int dirx, diry;
1258 int f;
1259 scr_stat *scp = cur_console;
1260
1261 if (test) {
1262 if (!scrn_blanked) {
1263 bcopy(Crtat, scp->scr_buf,
1264 scp->xsize * scp->ysize * 2);
1265 fillw((FG_LIGHTGREY|BG_BLACK)<<8 | scr_map[0x20],
1266 Crtat, scp->xsize * scp->ysize);
1267 set_border(0);
1268 dirx = (scp->xpos ? 1 : -1);
1269 diry = (scp->ypos ?
1270 scp->xsize : -scp->xsize);
1271 for (f=0; f< sizeof(saves)-1; f++)
1272 savs[f] = (u_char *)Crtat + 2 *
1273 (scp->xpos+scp->ypos*scp->xsize);
1274 *(savs[0]) = scr_map[*saves];
1275 f = scp->ysize * scp->xsize + 5;
1276 outb(crtc_addr, 14);
1277 outb(crtc_addr+1, f >> 8);
1278 outb(crtc_addr, 15);
1279 outb(crtc_addr+1, f & 0xff);
1280 scrn_blanked = 1;
1281 }
1282 if (scrn_blanked++ < 4)
1283 return;
1284 scrn_blanked = 1;
1285 *(savs[sizeof(saves)-2]) = scr_map[0x20];
1286 for (f=sizeof(saves)-2; f > 0; f--)
1287 savs[f] = savs[f-1];
1288 f = (savs[0] - (u_char *)Crtat) / 2;
1289 if ((f % scp->xsize) == 0 ||
1290 (f % scp->xsize) == scp->xsize - 1 ||
1291 (rand() % 50) == 0)
1292 dirx = -dirx;
1293 if ((f / scp->xsize) == 0 ||
1294 (f / scp->xsize) == scp->ysize - 1 ||
1295 (rand() % 20) == 0)
1296 diry = -diry;
1297 savs[0] += 2*dirx + 2*diry;
1298 for (f=sizeof(saves)-2; f>=0; f--)
1299 *(savs[f]) = scr_map[saves[f]];
1300 }
1301 else {
1302 if (scrn_blanked) {
1303 bcopy(scp->scr_buf, Crtat,
1304 scp->xsize * scp->ysize * 2);
1305 cur_cursor_pos = -1;
1306 set_border(scp->border);
1307 scrn_blanked = 0;
1308 }
1309 }
1310}
1311
1312static void cursor_shape(int start, int end)
1313{
1314 outb(crtc_addr, 10);
1315 outb(crtc_addr+1, start & 0xFF);
1316 outb(crtc_addr, 11);
1317 outb(crtc_addr+1, end & 0xFF);
1318}
1319
1320
1321#if !defined(FAT_CURSOR)
1322static void get_cursor_shape(int *start, int *end)
1323{
1324 outb(crtc_addr, 10);
1325 *start = inb(crtc_addr+1) & 0x1F;
1326 outb(crtc_addr, 11);
1327 *end = inb(crtc_addr+1) & 0x1F;
1328}
1329#endif
1330
1331
1332static void cursor_pos(int force)
1333{
1334 int pos;
1335
1336 if (cur_console->status & UNKNOWN_MODE)
1337 return;
1338 if (scrn_blank_time && (time.tv_sec > scrn_time_stamp+scrn_blank_time))
1339 SCRN_SAVER(1);
1340 pos = cur_console->crtat - cur_console->crt_base;
1341 if (force || (!scrn_blanked && pos != cur_cursor_pos)) {
1342 cur_cursor_pos = pos;
1343 outb(crtc_addr, 14);
1344 outb(crtc_addr+1, pos>>8);
1345 outb(crtc_addr, 15);
1346 outb(crtc_addr+1, pos&0xff);
1347 }
1348 timeout((timeout_t)cursor_pos, 0, hz/20);
1349}
1350
1351
1352static void clear_screen(scr_stat *scp)
1353{
1354 move_crsr(scp, 0, 0);
1355 fillw(scp->term.cur_attr | scr_map[0x20], scp->crt_base,
1356 scp->xsize * scp->ysize);
1357}
1358
1359
1360static int switch_scr(u_int next_scr)
1361{
1362 if (in_putc) { /* delay switch if in putc */
1363 delayed_next_scr = next_scr+1;
1364 return 0;
1365 }
1366 if (switch_in_progress &&
1367 (cur_console->proc != pfind(cur_console->pid)))
1368 switch_in_progress = 0;
1369
1370 if (next_scr >= NCONS || switch_in_progress) {
1371 sysbeep(BELL_PITCH, BELL_DURATION);
1372 return EINVAL;
1373 }
1374
1375 /* is the wanted virtual console open ? */
1376 if (next_scr) {
1377 struct tty *tp = VIRTUAL_TTY(next_scr);
1378 if (!(tp->t_state & TS_ISOPEN)) {
1379 sysbeep(BELL_PITCH, BELL_DURATION);
1380 return EINVAL;
1381 }
1382 }
1383
1384 switch_in_progress = 1;
1385 old_scp = cur_console;
1386 new_scp = &console[next_scr];
1387 wakeup((caddr_t)&new_scp->smode);
1388 if (new_scp == old_scp) {
1389 switch_in_progress = 0;
1390 return 0;
1391 }
1392
1393 /* has controlling process died? */
1394 if (old_scp->proc && (old_scp->proc != pfind(old_scp->pid)))
1395 old_scp->smode.mode = VT_AUTO;
1396 if (new_scp->proc && (new_scp->proc != pfind(new_scp->pid)))
1397 new_scp->smode.mode = VT_AUTO;
1398
1399 /* check the modes and switch approbiatly */
1400 if (old_scp->smode.mode == VT_PROCESS) {
1401 old_scp->status |= SWITCH_WAIT_REL;
1402 psignal(old_scp->proc, old_scp->smode.relsig);
1403 }
1404 else {
1405 exchange_scr();
1406 if (new_scp->smode.mode == VT_PROCESS) {
1407 new_scp->status |= SWITCH_WAIT_ACQ;
1408 psignal(new_scp->proc, new_scp->smode.acqsig);
1409 }
1410 else
1411 switch_in_progress = 0;
1412 }
1413 return 0;
1414}
1415
1416
1417static void exchange_scr(void)
1418{
1419 struct tty *tp;
1420
1421 bcopy(Crtat, old_scp->scr_buf, old_scp->xsize * old_scp->ysize * 2);
1422 old_scp->crt_base = old_scp->scr_buf;
1423 move_crsr(old_scp, old_scp->xpos, old_scp->ypos);
1424 cur_console = new_scp;
1425 set_mode(new_scp);
1426 new_scp->crt_base = Crtat;
1427 move_crsr(new_scp, new_scp->xpos, new_scp->ypos);
1428 bcopy(new_scp->scr_buf, Crtat, new_scp->xsize * new_scp->ysize * 2);
1429 update_leds(new_scp->status & LED_MASK);
1430 if (old_scp->status & KBD_RAW_MODE || new_scp->status & KBD_RAW_MODE)
1431 shfts = ctls = alts = agrs = metas = 0;
1432 delayed_next_scr = 0;
1433}
1434
1435
1436static void move_crsr(scr_stat *scp, int x, int y)
1437{
1438 if (x < 0 || y < 0 || x >= scp->xsize || y >= scp->ysize)
1439 return;
1440 scp->xpos = x;
1441 scp->ypos = y;
1442 scp->crtat = scp->crt_base + scp->ypos * scp->xsize + scp->xpos;
1443}
1444
1445
1446static void move_up(u_short *s, u_short *d, u_int len)
1447{
1448 s += len;
1449 d += len;
1450 while (len-- > 0)
1451 *--d = *--s;
1452}
1453
1454
1455static void move_down(u_short *s, u_short *d, u_int len)
1456{
1457 while (len-- > 0)
1458 *d++ = *s++;
1459}
1460
1461
1462static void scan_esc(scr_stat *scp, u_char c)
1463{
1464 static u_char ansi_col[16] =
1465 {0, 4, 2, 6, 1, 5, 3, 7, 8, 12, 10, 14, 9, 13, 11, 15};
1466 int i, n;
1467 u_short *src, *dst, count;
1468
1469 if (scp->term.esc == 1) {
1470 switch (c) {
1471
1472 case '[': /* Start ESC [ sequence */
1473 scp->term.esc = 2;
1474 scp->term.last_param = -1;
1475 for (i = scp->term.num_param; i < MAX_ESC_PAR; i++)
1476 scp->term.param[i] = 1;
1477 scp->term.num_param = 0;
1478 return;
1479
1480 case 'M': /* Move cursor up 1 line, scroll if at top */
1481 if (scp->ypos > 0)
1482 move_crsr(scp, scp->xpos, scp->ypos - 1);
1483 else {
1484 move_up(scp->crt_base,
1485 scp->crt_base + scp->xsize,
1486 (scp->ysize - 1) * scp->xsize);
1487 fillw(scp->term.cur_attr | scr_map[0x20],
1488 scp->crt_base, scp->xsize);
1489 }
1490 break;
1491#if notyet
1492 case 'Q':
1493 scp->term.esc = 4;
1494 break;
1495#endif
1496 case 'c': /* Clear screen & home */
1497 clear_screen(scp);
1498 break;
1499 }
1500 }
1501 else if (scp->term.esc == 2) {
1502 if (c >= '0' && c <= '9') {
1503 if (scp->term.num_param < MAX_ESC_PAR) {
1504 if (scp->term.last_param != scp->term.num_param) {
1505 scp->term.last_param = scp->term.num_param;
1506 scp->term.param[scp->term.num_param] = 0;
1507 }
1508 else
1509 scp->term.param[scp->term.num_param] *= 10;
1510 scp->term.param[scp->term.num_param] += c - '0';
1511 return;
1512 }
1513 }
1514 scp->term.num_param = scp->term.last_param + 1;
1515 switch (c) {
1516
1517 case ';':
1518 if (scp->term.num_param < MAX_ESC_PAR)
1519 return;
1520 break;
1521
1522 case '=':
1523 scp->term.esc = 3;
1524 scp->term.last_param = -1;
1525 for (i = scp->term.num_param; i < MAX_ESC_PAR; i++)
1526 scp->term.param[i] = 1;
1527 scp->term.num_param = 0;
1528 return;
1529
1530 case 'A': /* up n rows */
1531 n = scp->term.param[0]; if (n < 1) n = 1;
1532 move_crsr(scp, scp->xpos, scp->ypos - n);
1533 break;
1534
1535 case 'B': /* down n rows */
1536 n = scp->term.param[0]; if (n < 1) n = 1;
1537 move_crsr(scp, scp->xpos, scp->ypos + n);
1538 break;
1539
1540 case 'C': /* right n columns */
1541 n = scp->term.param[0]; if (n < 1) n = 1;
1542 move_crsr(scp, scp->xpos + n, scp->ypos);
1543 break;
1544
1545 case 'D': /* left n columns */
1546 n = scp->term.param[0]; if (n < 1) n = 1;
1547 move_crsr(scp, scp->xpos - n, scp->ypos);
1548 break;
1549
1550 case 'E': /* cursor to start of line n lines down */
1551 n = scp->term.param[0]; if (n < 1) n = 1;
1552 move_crsr(scp, 0, scp->ypos + n);
1553 break;
1554
1555 case 'F': /* cursor to start of line n lines up */
1556 n = scp->term.param[0]; if (n < 1) n = 1;
1557 move_crsr(scp, 0, scp->ypos - n);
1558 break;
1559
1560 case 'f': /* System V consoles .. */
1561 case 'H': /* Cursor move */
1562 if (scp->term.num_param == 0)
1563 move_crsr(scp, 0, 0);
1564 else if (scp->term.num_param == 2)
1565 move_crsr(scp, scp->term.param[1] - 1,
1566 scp->term.param[0] - 1);
1567 break;
1568
1569 case 'J': /* Clear all or part of display */
1570 if (scp->term.num_param == 0)
1571 n = 0;
1572 else
1573 n = scp->term.param[0];
1574 switch (n) {
1575 case 0: /* clear form cursor to end of display */
1576 fillw(scp->term.cur_attr | scr_map[0x20],
1577 scp->crtat, scp->crt_base +
1578 scp->xsize * scp->ysize -
1579 scp->crtat);
1580 break;
1581 case 1: /* clear from beginning of display to cursor */
1582 fillw(scp->term.cur_attr | scr_map[0x20],
1583 scp->crt_base,
1584 scp->crtat - scp->crt_base);
1585 break;
1586 case 2: /* clear entire display */
1587 clear_screen(scp);
1588 break;
1589 }
1590 break;
1591
1592 case 'K': /* Clear all or part of line */
1593 if (scp->term.num_param == 0)
1594 n = 0;
1595 else
1596 n = scp->term.param[0];
1597 switch (n) {
1598 case 0: /* clear form cursor to end of line */
1599 fillw(scp->term.cur_attr | scr_map[0x20],
1600 scp->crtat, scp->xsize - scp->xpos);
1601 break;
1602 case 1: /* clear from beginning of line to cursor */
1603 fillw(scp->term.cur_attr|scr_map[0x20],
1604 scp->crtat - (scp->xsize - scp->xpos),
1605 (scp->xsize - scp->xpos) + 1);
1606 break;
1607 case 2: /* clear entire line */
1608 fillw(scp->term.cur_attr|scr_map[0x20],
1609 scp->crtat - (scp->xsize - scp->xpos),
1610 scp->xsize);
1611 break;
1612 }
1613 break;
1614
1615 case 'L': /* Insert n lines */
1616 n = scp->term.param[0]; if (n < 1) n = 1;
1617 if (n > scp->ysize - scp->ypos)
1618 n = scp->ysize - scp->ypos;
1619 src = scp->crt_base + scp->ypos * scp->xsize;
1620 dst = src + n * scp->xsize;
1621 count = scp->ysize - (scp->ypos + n);
1622 move_up(src, dst, count * scp->xsize);
1623 fillw(scp->term.cur_attr | scr_map[0x20], src,
1624 n * scp->xsize);
1625 break;
1626
1627 case 'M': /* Delete n lines */
1628 n = scp->term.param[0]; if (n < 1) n = 1;
1629 if (n > scp->ysize - scp->ypos)
1630 n = scp->ysize - scp->ypos;
1631 dst = scp->crt_base + scp->ypos * scp->xsize;
1632 src = dst + n * scp->xsize;
1633 count = scp->ysize - (scp->ypos + n);
1634 move_down(src, dst, count * scp->xsize);
1635 src = dst + count * scp->xsize;
1636 fillw(scp->term.cur_attr | scr_map[0x20], src,
1637 n * scp->xsize);
1638 break;
1639
1640 case 'P': /* Delete n chars */
1641 n = scp->term.param[0]; if (n < 1) n = 1;
1642 if (n > scp->xsize - scp->xpos)
1643 n = scp->xsize - scp->xpos;
1644 dst = scp->crtat;
1645 src = dst + n;
1646 count = scp->xsize - (scp->xpos + n);
1647 move_down(src, dst, count);
1648 src = dst + count;
1649 fillw(scp->term.cur_attr | scr_map[0x20], src, n);
1650 break;
1651
1652 case '@': /* Insert n chars */
1653 n = scp->term.param[0]; if (n < 1) n = 1;
1654 if (n > scp->xsize - scp->xpos)
1655 n = scp->xsize - scp->xpos;
1656 src = scp->crtat;
1657 dst = src + n;
1658 count = scp->xsize - (scp->xpos + n);
1659 move_up(src, dst, count);
1660 fillw(scp->term.cur_attr | scr_map[0x20], src, n);
1661 break;
1662
1663 case 'S': /* scroll up n lines */
1664 n = scp->term.param[0]; if (n < 1) n = 1;
1665 bcopy(scp->crt_base + (scp->xsize * n),
1666 scp->crt_base,
1667 scp->xsize * (scp->ysize - n) *
1668 sizeof(u_short));
1669 fillw(scp->term.cur_attr | scr_map[0x20],
1670 scp->crt_base + scp->xsize *
1671 (scp->ysize - 1),
1672 scp->xsize);
1673 break;
1674
1675 case 'T': /* scroll down n lines */
1676 n = scp->term.param[0]; if (n < 1) n = 1;
1677 bcopy(scp->crt_base,
1678 scp->crt_base + (scp->xsize * n),
1679 scp->xsize * (scp->ysize - n) *
1680 sizeof(u_short));
1681 fillw(scp->term.cur_attr | scr_map[0x20], scp->crt_base,
1682 scp->xsize);
1683 break;
1684
1685 case 'X': /* delete n characters in line */
1686 n = scp->term.param[0]; if (n < 1) n = 1;
1687 fillw(scp->term.cur_attr | scr_map[0x20],
1688 scp->crt_base + scp->xpos +
1689 ((scp->xsize*scp->ypos) * sizeof(u_short)), n);
1690 break;
1691
1692 case 'Z': /* move n tabs backwards */
1693 n = scp->term.param[0]; if (n < 1) n = 1;
1694 if ((i = scp->xpos & 0xf8) == scp->xpos)
1695 i -= 8*n;
1696 else
1697 i -= 8*(n-1);
1698 if (i < 0)
1699 i = 0;
1700 move_crsr(scp, i, scp->ypos);
1701 break;
1702
1703 case '`': /* move cursor to column n */
1704 n = scp->term.param[0]; if (n < 1) n = 1;
1705 move_crsr(scp, n, scp->ypos);
1706 break;
1707
1708 case 'a': /* move cursor n columns to the right */
1709 n = scp->term.param[0]; if (n < 1) n = 1;
1710 move_crsr(scp, scp->xpos + n, scp->ypos);
1711 break;
1712
1713 case 'd': /* move cursor to row n */
1714 n = scp->term.param[0]; if (n < 1) n = 1;
1715 move_crsr(scp, scp->xpos, n);
1716 break;
1717
1718 case 'e': /* move cursor n rows down */
1719 n = scp->term.param[0]; if (n < 1) n = 1;
1720 move_crsr(scp, scp->xpos, scp->ypos + n);
1721 break;
1722
1723 case 'm': /* change attribute */
1724 if (scp->term.num_param == 0)
1725 n = 0;
1726 else
1727 n = scp->term.param[0];
1728 switch (n) {
1729 case 0: /* back to normal */
1730 scp->term.cur_attr = scp->term.std_attr;
1731 break;
1732 case 1: /* highlight (bold) */
1733 scp->term.cur_attr &= 0xFF00;
1734 scp->term.cur_attr |= 0x0800;
1735 break;
1736 case 4: /* highlight (underline) */
1737 scp->term.cur_attr &= 0x0F00;
1738 scp->term.cur_attr |= 0x0800;
1739 break;
1740 case 5: /* blink */
1741 scp->term.cur_attr &= 0xFF00;
1742 scp->term.cur_attr |= 0x8000;
1743 break;
1744 case 7: /* reverse video */
1745 scp->term.cur_attr = scp->term.rev_attr;
1746 break;
1747 case 30: case 31: case 32: case 33: /* set fg color */
1748 case 34: case 35: case 36: case 37:
1749 scp->term.cur_attr = (scp->term.cur_attr & 0xF0FF)
1750 | (ansi_col[(n - 30) & 7] << 8);
1751 break;
1752 case 40: case 41: case 42: case 43: /* set bg color */
1753 case 44: case 45: case 46: case 47:
1754 scp->term.cur_attr = (scp->term.cur_attr & 0x0FFF)
1755 | (ansi_col[(n - 40) & 7] << 12);
1756 break;
1757 }
1758 break;
1759
1760 case 'x':
1761 if (scp->term.num_param == 0)
1762 n = 0;
1763 else
1764 n = scp->term.param[0];
1765 switch (n) {
1766 case 0: /* reset attributes */
1767 scp->term.cur_attr = scp->term.std_attr =
1768 current_default->std_attr;
1769 scp->term.rev_attr = current_default->rev_attr;
1770 break;
1771 case 1: /* set ansi background */
1772 scp->term.cur_attr = scp->term.std_attr =
1773 (scp->term.std_attr & 0x0F00) |
1774 (ansi_col[(scp->term.param[1])&0x0F]<<12);
1775 break;
1776 case 2: /* set ansi foreground */
1777 scp->term.cur_attr = scp->term.std_attr =
1778 (scp->term.std_attr & 0xF000) |
1779 (ansi_col[(scp->term.param[1])&0x0F]<<8);
1780 break;
1781 case 3: /* set ansi attribute directly */
1782 scp->term.cur_attr = scp->term.std_attr =
1783 (scp->term.param[1]&0xFF)<<8;
1784 break;
1785 case 5: /* set ansi reverse video background */
1786 scp->term.rev_attr =
1787 (scp->term.rev_attr & 0x0F00) |
1788 (ansi_col[(scp->term.param[1])&0x0F]<<12);
1789 break;
1790 case 6: /* set ansi reverse video foreground */
1791 scp->term.rev_attr =
1792 (scp->term.rev_attr & 0xF000) |
1793 (ansi_col[(scp->term.param[1])&0x0F]<<8);
1794 break;
1795 case 7: /* set ansi reverse video directly */
1796 scp->term.rev_attr = (scp->term.param[1]&0xFF)<<8;
1797 break;
1798 }
1799 break;
1800
1801 case 'z': /* switch to (virtual) console n */
1802 if (scp->term.num_param == 1)
1803 switch_scr(scp->term.param[0]);
1804 break;
1805 }
1806 }
1807 else if (scp->term.esc == 3) {
1808 if (c >= '0' && c <= '9') {
1809 if (scp->term.num_param < MAX_ESC_PAR) {
1810 if (scp->term.last_param != scp->term.num_param) {
1811 scp->term.last_param = scp->term.num_param;
1812 scp->term.param[scp->term.num_param] = 0;
1813 }
1814 else
1815 scp->term.param[scp->term.num_param] *= 10;
1816 scp->term.param[scp->term.num_param] += c - '0';
1817 return;
1818 }
1819 }
1820 scp->term.num_param = scp->term.last_param + 1;
1821 switch (c) {
1822
1823 case ';':
1824 if (scp->term.num_param < MAX_ESC_PAR)
1825 return;
1826 break;
1827
1828 case 'A': /* set display border color */
1829 if (scp->term.num_param == 1)
1830 scp->border=scp->term.param[0] & 0xff;
1831 if (scp == cur_console)
1832 set_border(scp->border);
1833 break;
1834
1835 case 'B': /* set bell pitch and duration */
1836 if (scp->term.num_param == 2) {
1837 scp->bell_pitch = scp->term.param[0];
1838 scp->bell_duration = scp->term.param[1]*10;
1839 }
1840 break;
1841
1842 case 'C': /* set cursor shape (start & end line) */
1843 if (scp->term.num_param == 2) {
1844 scp->cursor_start = scp->term.param[0] & 0x1F;
1845 scp->cursor_end = scp->term.param[1] & 0x1F;
1846 if (scp == cur_console)
1847 cursor_shape(scp->cursor_start,
1848 scp->cursor_end);
1849 }
1850 break;
1851
1852 case 'F': /* set ansi foreground */
1853 if (scp->term.num_param == 1)
1854 scp->term.cur_attr = scp->term.std_attr =
1855 (scp->term.std_attr & 0xF000)
1856 | ((scp->term.param[0] & 0x0F) << 8);
1857 break;
1858
1859 case 'G': /* set ansi background */
1860 if (scp->term.num_param == 1)
1861 scp->term.cur_attr = scp->term.std_attr =
1862 (scp->term.std_attr & 0x0F00)
1863 | ((scp->term.param[0] & 0x0F) << 12);
1864 break;
1865
1866 case 'H': /* set ansi reverse video foreground */
1867 if (scp->term.num_param == 1)
1868 scp->term.rev_attr =
1869 (scp->term.rev_attr & 0xF000)
1870 | ((scp->term.param[0] & 0x0F) << 8);
1871 break;
1872
1873 case 'I': /* set ansi reverse video background */
1874 if (scp->term.num_param == 1)
1875 scp->term.rev_attr =
1876 (scp->term.rev_attr & 0x0F00)
1877 | ((scp->term.param[0] & 0x0F) << 12);
1878 break;
1879 }
1880 }
1881 scp->term.esc = 0;
1882}
1883
1884
1885static void ansi_put(scr_stat *scp, u_char c)
1886{
1887 if (scp->status & UNKNOWN_MODE)
1888 return;
1889
1890 /* make screensaver happy */
1891 if (scp == cur_console) {
1892 scrn_time_stamp = time.tv_sec;
1893 if (scrn_blanked)
1894 SCRN_SAVER(0);
1895 }
1896 in_putc++;
1897 if (scp->term.esc)
1898 scan_esc(scp, c);
1899 else switch(c) {
1900 case 0x1B: /* start escape sequence */
1901 scp->term.esc = 1;
1902 scp->term.num_param = 0;
1903 break;
1904 case 0x07:
1905 if (scp == cur_console)
1906 sysbeep(scp->bell_pitch, scp->bell_duration);
1907 break;
1908 case '\t': /* non-destructive tab */
1909 scp->crtat += (8 - scp->xpos % 8);
1910 scp->xpos += (8 - scp->xpos % 8);
1911 break;
1912 case '\b': /* non-destructive backspace */
1913 if (scp->crtat > scp->crt_base) {
1914 scp->crtat--;
1915 if (scp->xpos > 0)
1916 scp->xpos--;
1917 else {
1918 scp->xpos += scp->xsize - 1;
1919 scp->ypos--;
1920 }
1921 }
1922 break;
1923 case '\r': /* return to pos 0 */
1924 move_crsr(scp, 0, scp->ypos);
1925 break;
1926 case '\n': /* newline, same pos */
1927 scp->crtat += scp->xsize;
1928 scp->ypos++;
1929 break;
1930 case '\f': /* form feed, clears screen */
1931 clear_screen(scp);
1932 break;
1933 default:
1934 /* Print only printables */
1935 *scp->crtat = (scp->term.cur_attr | scr_map[c]);
1936 scp->crtat++;
1937 if (++scp->xpos >= scp->xsize) {
1938 scp->xpos = 0;
1939 scp->ypos++;
1940 }
1941 break;
1942 }
1943 if (scp->crtat >= scp->crt_base + scp->ysize * scp->xsize) {
1944 bcopy(scp->crt_base + scp->xsize, scp->crt_base,
1945 scp->xsize * (scp->ysize - 1) * sizeof(u_short));
1946 fillw(scp->term.cur_attr | scr_map[0x20],
1947 scp->crt_base + scp->xsize * (scp->ysize - 1),
1948 scp->xsize);
1949 scp->crtat -= scp->xsize;
1950 scp->ypos--;
1951 }
1952 in_putc--;
1953 if (delayed_next_scr)
1954 switch_scr(delayed_next_scr - 1);
1955}
1956
1957static void scinit(void)
1958{
1959 u_short volatile *cp = Crtat + (CGA_BUF-MONO_BUF)/sizeof(u_short), was;
1960 unsigned cursorat;
1961 int i;
1962
1963 /*
1964 * catch that once in a blue moon occurence when scinit is called
1965 * TWICE, adding the CGA_BUF offset again -> poooff
1966 */
1967 if (crtat != 0)
1968 return;
1969 /*
1970 * Crtat initialized to point to MONO buffer, if not present change
1971 * to CGA_BUF offset. ONLY ADD the difference since locore.s adds
1972 * in the remapped offset at the "right" time
1973 */
1974 was = *cp;
1975 *cp = (u_short) 0xA55A;
1976 if (*cp != 0xA55A) {
1977 crtc_addr = MONO_BASE;
1978 } else {
1979 *cp = was;
1980 crtc_addr = COLOR_BASE;
1981 Crtat = Crtat + (CGA_BUF-MONO_BUF)/sizeof(u_short);
1982 }
1983
1984 /* Extract cursor location */
1985 outb(crtc_addr,14);
1986 cursorat = inb(crtc_addr+1)<<8 ;
1987 outb(crtc_addr,15);
1988 cursorat |= inb(crtc_addr+1);
1989 crtat = Crtat + cursorat;
1990
1991 /* is this a VGA or higher ? */
1992 outb(crtc_addr, 7);
1993 if (inb(crtc_addr) == 7)
1994 crtc_vga = 1;
1995
1996 current_default = &user_default;
1997 console[0].crtat = crtat;
1998 console[0].crt_base = Crtat;
1999 console[0].term.esc = 0;
2000 console[0].term.std_attr = current_default->std_attr;
2001 console[0].term.rev_attr = current_default->rev_attr;
2002 console[0].term.cur_attr = current_default->std_attr;
2003 console[0].xpos = cursorat % COL;
2004 console[0].ypos = cursorat / COL;
2005 console[0].border = BG_BLACK;;
2006 console[0].xsize = COL;
2007 console[0].ysize = ROW;
2008 console[0].status = 0;
2009 console[0].pid = 0;
2010 console[0].proc = NULL;
2011 console[0].smode.mode = VT_AUTO;
2012 console[0].bell_pitch = BELL_PITCH;
2013 console[0].bell_duration = BELL_DURATION;
2014 kernel_console.esc = 0;
2015 kernel_console.std_attr = kernel_default.std_attr;
2016 kernel_console.rev_attr = kernel_default.rev_attr;
2017 kernel_console.cur_attr = kernel_default.std_attr;
2018 /* initialize mapscrn array to a one to one map */
2019 for (i=0; i<sizeof(scr_map); i++)
2020 scr_map[i] = i;
2021 clear_screen(&console[0]);
2022}
2023
2024
2025static void scput(u_char c)
2026{
2027 scr_stat *scp = &console[0];
2028 term_stat save;
2029
2030 if (crtat == 0)
2031 scinit();
2032 save = scp->term;
2033 scp->term = kernel_console;
2034 current_default = &kernel_default;
2035 ansi_put(scp, c);
2036 kernel_console = scp->term;
2037 current_default = &user_default;
2038 scp->term = save;
2039}
2040
2041
2042static u_char *get_fstr(u_int c, u_int *len)
2043{
2044 u_int i;
2045
2046 if (!(c & FKEY))
2047 return(NULL);
2048 i = (c & 0xFF) - F_FN;
2049 if (i > n_fkey_tab)
2050 return(NULL);
2051 *len = fkey_tab[i].len;
2052 return(fkey_tab[i].str);
2053}
2054
2055
2056static void update_leds(int which)
2057{
2058 static u_char xlate_leds[8] = { 0, 4, 2, 6, 1, 5, 3, 7 };
2059
2060 kbd_cmd2(KB_SETLEDS, xlate_leds[which & LED_MASK]);
2061}
2062
2063
2064/*
2065 * scgetc(noblock) : get a character from the keyboard.
2066 * If noblock = 0 wait until a key is gotten. Otherwise return NOKEY.
2067 */
2068u_int scgetc(int noblock)
2069{
2070 u_char val, code, release;
2071 u_int state, action;
2072 struct key_t *key;
2073 static u_char esc_flag = 0, compose = 0;
2074 static u_int chr = 0;
2075
2076next_code:
2077 kbd_wait();
2078 /* First see if there is something in the keyboard port */
2079 if (inb(KB_STAT) & KB_BUF_FULL)
2080 val = inb(KB_DATA);
2081 else if (noblock)
2082 return(NOKEY);
2083 else
2084 goto next_code;
2085
2086 if (cur_console->status & KBD_RAW_MODE)
2087 return val;
2088
2089 code = val & 0x7F;
2090 release = val & 0x80;
2091
2092 switch (esc_flag) {
2093 case 0x00: /* normal scancode */
2094 switch(code) {
2095 case 0x38: /* left alt (compose key) */
2096 if (release && compose) {
2097 compose = 0;
2098 if (chr > 255) {
2099 sysbeep(BELL_PITCH, BELL_DURATION);
2100 chr = 0;
2101 }
2102 }
2103 else {
2104 if (!compose) {
2105 compose = 1;
2106 chr = 0;
2107 }
2108 }
2109 break;
2110 case 0x60:
2111 case 0x61:
2112 esc_flag = code;
2113 goto next_code;
2114 }
2115 break;
2116 case 0x60: /* 0xE0 prefix */
2117 esc_flag = 0;
2118 switch (code) {
2119 case 0x1c: /* right enter key */
2120 code = 0x59;
2121 break;
2122 case 0x1d: /* right ctrl key */
2123 code = 0x5a;
2124 break;
2125 case 0x35: /* keypad divide key */
2126 code = 0x5b;
2127 break;
2128 case 0x37: /* print scrn key */
2129 code = 0x5c;
2130 break;
2131 case 0x38: /* right alt key (alt gr) */
2132 code = 0x5d;
2133 break;
2134 case 0x47: /* grey home key */
2135 code = 0x5e;
2136 break;
2137 case 0x48: /* grey up arrow key */
2138 code = 0x5f;
2139 break;
2140 case 0x49: /* grey page up key */
2141 code = 0x60;
2142 break;
2143 case 0x4b: /* grey left arrow key */
2144 code = 0x61;
2145 break;
2146 case 0x4d: /* grey right arrow key */
2147 code = 0x62;
2148 break;
2149 case 0x4f: /* grey end key */
2150 code = 0x63;
2151 break;
2152 case 0x50: /* grey down arrow key */
2153 code = 0x64;
2154 break;
2155 case 0x51: /* grey page down key */
2156 code = 0x65;
2157 break;
2158 case 0x52: /* grey insert key */
2159 code = 0x66;
2160 break;
2161 case 0x53: /* grey delete key */
2162 code = 0x67;
2163 break;
2164 default: /* ignore everything else */
2165 goto next_code;
2166 }
2167 break;
2168 case 0x61: /* 0xE1 prefix */
2169 esc_flag = 0;
2170 if (code == 0x1D)
2171 esc_flag = 0x1D;
2172 goto next_code;
2173 /* NOT REACHED */
2174 case 0x1D: /* pause / break */
2175 esc_flag = 0;
2176 if (code != 0x45)
2177 goto next_code;
2178 code = 0x68;
2179 break;
2180 }
2181
2182 if (compose) {
2183 switch (code) {
2184 case 0x47:
2185 case 0x48: /* keypad 7,8,9 */
2186 case 0x49:
2187 if (!release)
2188 chr = (code - 0x40) + chr*10;
2189 goto next_code;
2190 case 0x4b:
2191 case 0x4c: /* keypad 4,5,6 */
2192 case 0x4d:
2193 if (!release)
2194 chr = (code - 0x47) + chr*10;
2195 goto next_code;
2196 case 0x4f:
2197 case 0x50: /* keypad 1,2,3 */
2198 case 0x51:
2199 if (!release)
2200 chr = (code - 0x4e) + chr*10;
2201 goto next_code;
2202 case 0x52: /* keypad 0 */
2203 if (!release)
2204 chr *= 10;
2205 goto next_code;
2206 case 0x38: /* left alt key */
2207 break;
2208 default:
2209 if (chr) {
2210 compose = chr = 0;
2211 sysbeep(BELL_PITCH, BELL_DURATION);
2212 goto next_code;
2213 }
2214 break;
2215 }
2216 }
2217
2218 state = (shfts ? 1 : 0 ) | (2 * (ctls ? 1 : 0)) | (4 * (alts ? 1 : 0));
2219 if ((!agrs && (cur_console->status & ALKED))
2220 || (agrs && !(cur_console->status & ALKED)))
2221 code += ALTGR_OFFSET;
2222 key = &key_map.key[code];
2223 if ( ((key->flgs & FLAG_LOCK_C) && (cur_console->status & CLKED))
2224 || ((key->flgs & FLAG_LOCK_N) && (cur_console->status & NLKED)) )
2225 state ^= 1;
2226
2227 /* Check for make/break */
2228 action = key->map[state];
2229 if (release) { /* key released */
2230 if (key->spcl & 0x80) {
2231 switch (action) {
2232 case LSH:
2233 shfts &= ~1;
2234 break;
2235 case RSH:
2236 shfts &= ~2;
2237 break;
2238 case LCTR:
2239 ctls &= ~1;
2240 break;
2241 case RCTR:
2242 ctls &= ~2;
2243 break;
2244 case LALT:
2245 alts &= ~1;
2246 break;
2247 case RALT:
2248 alts &= ~2;
2249 break;
2250 case NLK:
2251 nlkcnt = 0;
2252 break;
2253 case CLK:
2254 clkcnt = 0;
2255 break;
2256 case SLK:
2257 slkcnt = 0;
2258 break;
2259 case ASH:
2260 agrs = 0;
2261 break;
2262 case ALK:
2263 alkcnt = 0;
2264 break;
2265 case META:
2266 metas = 0;
2267 break;
2268 }
2269 }
2270 if (chr && !compose) {
2271 action = chr;
2272 chr = 0;
2273 return(action);
2274 }
2275 } else {
2276 /* key pressed */
2277 if (key->spcl & (0x80>>state)) {
2278 switch (action) {
2279 /* LOCKING KEYS */
2280 case NLK:
2281 if (!nlkcnt) {
2282 nlkcnt++;
2283 if (cur_console->status & NLKED)
2284 cur_console->status &= ~NLKED;
2285 else
2286 cur_console->status |= NLKED;
2287 update_leds(cur_console->status & LED_MASK);
2288 }
2289 break;
2290 case CLK:
2291 if (!clkcnt) {
2292 clkcnt++;
2293 if (cur_console->status & CLKED)
2294 cur_console->status &= ~CLKED;
2295 else
2296 cur_console->status |= CLKED;
2297 update_leds(cur_console->status & LED_MASK);
2298 }
2299 break;
2300 case SLK:
2301 if (!slkcnt) {
2302 slkcnt++;
2303 if (cur_console->status & SLKED) {
2304 cur_console->status &= ~SLKED;
2305 pcstart(VIRTUAL_TTY(get_scr_num()));
2306 }
2307 else
2308 cur_console->status |= SLKED;
2309 update_leds(cur_console->status & LED_MASK);
2310 }
2311 break;
2312 case ALK:
2313 if (!alkcnt) {
2314 alkcnt++;
2315 if (cur_console->status & ALKED)
2316 cur_console->status &= ~ALKED;
2317 else
2318 cur_console->status |= ALKED;
2319 }
2320 break;
2321
2322 /* NON-LOCKING KEYS */
2323 case NOP:
2324 break;
2325 case RBT:
2326#if defined(__FreeBSD__)
2327 shutdown_nice();
2328#else
2329 cpu_reset();
2330#endif
2331 break;
2332 case DBG:
2333#if DDB > 0 /* try to switch to console 0 */
2334 if (cur_console->smode.mode == VT_AUTO &&
2335 console[0].smode.mode == VT_AUTO)
2336 switch_scr(0);
2337 Debugger("manual escape to debugger");
2338 return(NOKEY);
2339#else
2340 printf("No debugger in kernel\n");
2341#endif
2342 break;
2343 case LSH:
2344 shfts |= 1;
2345 break;
2346 case RSH:
2347 shfts |= 2;
2348 break;
2349 case LCTR:
2350 ctls |= 1;
2351 break;
2352 case RCTR:
2353 ctls |= 2;
2354 break;
2355 case LALT:
2356 alts |= 1;
2357 break;
2358 case RALT:
2359 alts |= 2;
2360 break;
2361 case ASH:
2362 agrs = 1;
2363 break;
2364 case META:
2365 metas = 1;
2366 break;
2367 case NEXT:
2368 switch_scr((get_scr_num()+1)%NCONS);
2369 break;
2370 default:
2371 if (action >= F_SCR && action <= L_SCR) {
2372 switch_scr(action - F_SCR);
2373 break;
2374 }
2375 if (action >= F_FN && action <= L_FN)
2376 action |= FKEY;
2377 return(action);
2378 }
2379 }
2380 else {
2381 if (metas)
2382 action |= MKEY;
2383 return(action);
2384 }
2385 }
2386 goto next_code;
2387}
2388
2389
2390int getchar(void)
2391{
2392 u_char thechar;
2393 int s;
2394
2395 polling = 1;
2396 s = splhigh();
2397 scput('>');
2398 thechar = (u_char) scgetc(0);
2399 polling = 0;
2400 splx(s);
2401 switch (thechar) {
2402 default:
2403 if (thechar >= scr_map[0x20])
2404 scput(thechar);
2405 return(thechar);
2406 case cr:
2407 case lf:
2408 scput(cr); scput(lf);
2409 return(lf);
2410 case bs:
2411 case del:
2412 scput(bs); scput(scr_map[0x20]); scput(bs);
2413 return(thechar);
2414 case cntld:
2415 scput('^'); scput('D'); scput('\r'); scput('\n');
2416 return(0);
2417 }
2418}
2419
2420
2421u_int sgetc(int noblock)
2422{
2423 return (scgetc(noblock) & 0xff);
2424}
2425
2426int pcmmap(dev_t dev, int offset, int nprot)
2427{
2428 if (offset > 0x20000)
2429 return EINVAL;
2430 return i386_btop((VIDEOMEM + offset));
2431}
2432
2433
2434static void kbd_wait(void)
2435{
2436 int i;
2437
2438 for (i=0; i<1000; i++) { /* up to 10 msec */
2439 if ((inb(KB_STAT) & KB_READY) == 0)
2440 break;
2441 DELAY (10);
2442 }
2443}
2444
2445
2446static void kbd_cmd(u_char command)
2447{
2448 kbd_wait();
2449 outb(KB_DATA, command);
2450}
2451
2452
2453static void kbd_cmd2(u_char command, u_char arg)
2454{
2455 int r, s = spltty();
2456 do {
2457 kbd_cmd(command);
2458 r = kbd_reply();
2459 if (r == KB_ACK) {
2460 kbd_cmd(arg & 0x7f);
2461 r = kbd_reply();
2462 }
2463 } while (r != KB_ACK);
2464 splx(s);
2465}
2466
2467
2468static int kbd_reply()
2469{
2470 int i;
2471
2472 kbd_wait();
2473 for (i=0; i<50000; i++) { /* at least 300 msec, 500 msec enough */
2474 if (inb(KB_STAT) & KB_BUF_FULL)
2475 return ((u_char) inb(KB_DATA));
2476 DELAY (10);
2477 }
2478 return(-1);
2479}
2480
2481
2482static void set_mode(scr_stat *scp)
2483{
2484 u_char byte;
2485 int s;
2486
2487 if (scp != cur_console)
2488 return;
2489
2490 /* (re)activate cursor */
2491 untimeout((timeout_t)cursor_pos, 0);
2492 cursor_pos(1);
2493
2494 /* change cursor type if set */
2495 if (scp->cursor_start != -1 && scp->cursor_end != -1)
2496 cursor_shape(scp->cursor_start, scp->cursor_end);
2497
2498 /* mode change only on VGA's */
2499 if (!crtc_vga)
2500 return;
2501
2502 /* setup video hardware for the given mode */
2503 s = splhigh();
2504 switch(scp->mode) {
2505 case TEXT80x25:
2506 outb(crtc_addr, 9); byte = inb(crtc_addr+1);
2507 outb(crtc_addr, 9); outb(crtc_addr+1, byte | 0x0F);
2508 outb(TSIDX, 0x03); outb(TSREG, 0x00); /* select font 0 */
2509 break;
2510 case TEXT80x50:
2511 outb(crtc_addr, 9); byte = inb(crtc_addr+1);
2512 outb(crtc_addr, 9); outb(crtc_addr+1, (byte & 0xF0) | 0x07);
2513 outb(TSIDX, 0x03); outb(TSREG, 0x05); /* select font 1 */
2514 break;
2515 default:
2516 break;
2517 }
2518 splx(s);
2519
2520 /* set border color for this (virtual) console */
2521 set_border(scp->border);
2522 return;
2523}
2524
2525
2526static void set_border(int color)
2527{
2528 inb(crtc_addr+6); /* reset flip-flop */
2529 outb(ATC, 0x11); outb(ATC, color);
2530 inb(crtc_addr+6); /* reset flip-flop */
2531 outb(ATC, 0x20); /* enable Palette */
2532}
2533
2534static void load_font(int segment, int size, char* font)
2535{
2536 int ch, line, s;
2537 u_char val;
2538
2539 outb(TSIDX, 0x01); val = inb(TSREG); /* blank screen */
2540 outb(TSIDX, 0x01); outb(TSREG, val | 0x20);
2541
2542 /* setup vga for loading fonts (graphics plane mode) */
2543 s = splhigh();
2544 inb(crtc_addr+6); /* reset flip/flop */
2545 outb(ATC, 0x30); outb(ATC, 0x01);
2546 outb(TSIDX, 0x02); outb(TSREG, 0x04);
2547 outb(TSIDX, 0x04); outb(TSREG, 0x06);
2548 outb(GDCIDX, 0x04); outb(GDCREG, 0x02);
2549 outb(GDCIDX, 0x05); outb(GDCREG, 0x00);
2550 outb(GDCIDX, 0x06); outb(GDCREG, 0x05); /* addr = a0000, 64kb */
2551 splx(s);
2552 for (ch=0; ch < 256; ch++)
2553 for (line=0; line < size; line++)
2554 *((char *)atdevbase+(segment*0x4000)+(ch*32)+line) =
2555 font[(ch*size)+line];
2556 /* setup vga for text mode again */
2557 s = splhigh();
2558 inb(crtc_addr+6); /* reset flip/flop */
2559 outb(ATC, 0x30); outb(ATC, 0x0C);
2560 outb(TSIDX, 0x02); outb(TSREG, 0x03);
2561 outb(TSIDX, 0x04); outb(TSREG, 0x02);
2562 outb(GDCIDX, 0x04); outb(GDCREG, 0x00);
2563 outb(GDCIDX, 0x05); outb(GDCREG, 0x10);
2564 if (crtc_addr == MONO_BASE) {
2565 outb(GDCIDX, 0x06); outb(GDCREG, 0x0A); /* addr = b0000, 32kb */
2566 }
2567 else {
2568 outb(GDCIDX, 0x06); outb(GDCREG, 0x0E); /* addr = b8000, 32kb */
2569 }
2570 splx(s);
2571 outb(TSIDX, 0x01); val = inb(TSREG); /* unblank screen */
2572 outb(TSIDX, 0x01); outb(TSREG, val & 0xDF);
2573}
2574
2575
2576static void load_palette(void)
2577{
2578 int i;
2579
2580 outb(PIXMASK, 0xFF); /* no pixelmask */
2581 outb(PALWADR, 0x00);
2582 for (i=0x00; i<0x300; i++)
2583 outb(PALDATA, palette[i]);
2584 inb(crtc_addr+6); /* reset flip/flop */
2585 outb(ATC, 0x20); /* enable palette */
2586}
2587
2588static void save_palette(void)
2589{
2590 int i;
2591
2592 outb(PALRADR, 0x00);
2593 for (i=0x00; i<0x300; i++)
2594 palette[i] = inb(PALDATA);
2595 inb(crtc_addr+6); /* reset flip/flop */
2596}
2597
2598
2599static void change_winsize(struct tty *tp, int x, int y)
2600{
2601 if (tp->t_winsize.ws_col != x || tp->t_winsize.ws_row != y) {
2602 tp->t_winsize.ws_col = x;
2603 tp->t_winsize.ws_row = y;
2604 pgsignal(tp->t_pgrp, SIGWINCH, 1);
2605 }
2606}
2607
2608#endif /* NSC */