Path: utzoo!utgpu!attcan!uunet!mcvax!hp4nl!botter!star.cs.vu.nl!ast@cs.vu.nl
From: ast@cs.vu.nl (Andy Tanenbaum)
Newsgroups: comp.os.minix
Subject: V1.3c posting #11 kernel (1 of 3)
Message-ID: <1440@ast.cs.vu.nl>
Date: 27 Sep 88 20:58:20 GMT
Sender: ast@cs.vu.nl
Reply-To: ast@cs.vu.nl (Andy Tanenbaum)
Organization: VU Informatica, Amsterdam
Lines: 1568
: This is a shar archive. Extract with sh, not csh.
: This archive ends with exit, so do not worry about trailing junk.
: --------------------------- cut here --------------------------
PATH=/bin:/usr/bin:/usr/ucb
echo Extracting 'at_makefile'
sed 's/^X//' > 'at_makefile' << '+ END-OF-FILE ''at_makefile'
X# The kernel dir contains xt_wini.c and at_wini.c. Before running make
X# you must copy one of these to wini.c, depending on which controller you
X# have. If you do not have a hard disk, you MUST choose one of them at random.
X# On a PC, cpp and cem are in /lib and will be removed to make space while
X# linking the kernel. On an AT, they are in /usr/lib are are not removed.
X# This is because they have to be in /lib on a PC; the diskette is too small
X# for them to be in /usr/lib. You can change this by editing commands/cc.c.
X#
X# The CFLAGS values are:
X# -Di8088 - required on an 8088/80286/80386 CPU; forbidden on a 68000
X# -F - run cpp and cem sequentially (used when memory is tight)
X# -T. - put temporaries in working directory (when RAM disk is small)
X#
XCFLAGS= -Di8088 -F -T.
Xh=../h
Xl=/usr/lib
X
Xobj = mpx88.s main.s tty.s floppy.s wini.s system.s proc.s clock.s memory.s \
X console.s rs232.s printer.s table.s klib88.s dmp.s
X
Xcobjs = main.s tty.s floppy.s wini.s system.s proc.s clock.s memory.s \
X console.s rs232.s printer.s table.s dmp.s
X
Xkernel: makefile $(obj) $l/libc.a
X @echo "Start linking Kernel."
X @asld -o kernel -T. $(obj) $l/libc.a $l/end.s
X @echo "Kernel done. "
X
Xclean:
X rm -f $(cobjs)
X
Xclock.s: const.h type.h $h/const.h $h/type.h
Xclock.s: $h/callnr.h
Xclock.s: $h/com.h
Xclock.s: $h/error.h
Xclock.s: $h/signal.h
Xclock.s: glo.h
Xclock.s: proc.h
X
Xconsole.s: const.h type.h $h/const.h $h/type.h
Xconsole.s: $h/callnr.h
Xconsole.s: $h/com.h
Xconsole.s: $h/error.h
Xconsole.s: $h/sgtty.h
Xconsole.s: $h/signal.h
Xconsole.s: glo.h
Xconsole.s: proc.h
Xconsole.s: tty.h
Xconsole.s: ttymaps.h
X
Xfloppy.s: const.h type.h $h/const.h $h/type.h
Xfloppy.s: $h/callnr.h
Xfloppy.s: $h/com.h
Xfloppy.s: $h/error.h
Xfloppy.s: glo.h
Xfloppy.s: proc.h
X
X
Xdmp.s: const.h type.h $h/const.h $h/type.h
Xdmp.s: $h/callnr.h
Xdmp.s: $h/com.h
Xdmp.s: $h/error.h
Xdmp.s: glo.h
Xdmp.s: proc.h
X
Xmain.s: const.h type.h $h/const.h $h/type.h
Xmain.s: $h/callnr.h
Xmain.s: $h/com.h
Xmain.s: $h/error.h
Xmain.s: glo.h
Xmain.s: proc.h
X
Xmemory.s: const.h type.h $h/const.h $h/type.h
Xmemory.s: $h/callnr.h
Xmemory.s: $h/com.h
Xmemory.s: $h/error.h
Xmemory.s: proc.h
X
Xprinter.s: const.h type.h $h/const.h $h/type.h
Xprinter.s: $h/callnr.h
Xprinter.s: $h/com.h
Xprinter.s: $h/error.h
Xprinter.s: proc.h
Xprinter.s: glo.h
X
Xproc.s: const.h type.h $h/const.h $h/type.h
Xproc.s: $h/callnr.h
Xproc.s: $h/com.h
Xproc.s: $h/error.h
Xproc.s: glo.h
Xproc.s: proc.h
X
Xsystem.s: const.h type.h $h/const.h $h/type.h
Xsystem.s: $h/callnr.h
Xsystem.s: $h/com.h
Xsystem.s: $h/error.h
Xsystem.s: $h/signal.h
Xsystem.s: glo.h
Xsystem.s: proc.h
X
Xtable.s: const.h type.h $h/const.h $h/type.h $h/com.h
Xtable.s: glo.h
Xtable.s: proc.h
Xtable.s: tty.h
X
Xtty.s: const.h type.h $h/const.h $h/type.h
Xtty.s: $h/callnr.h
Xtty.s: $h/com.h
Xtty.s: $h/error.h
Xtty.s: $h/sgtty.h
Xtty.s: $h/signal.h
Xtty.s: glo.h
Xtty.s: proc.h
Xtty.s: tty.h
Xtty.s: ttymaps.h
Xtty.s: tty.h
Xtty.s: ttymaps.h
X
Xwini.s: const.h type.h $h/const.h $h/type.h
Xwini.s: $h/callnr.h
Xwini.s: $h/com.h
Xwini.s: $h/error.h
Xwini.s: proc.h
+ END-OF-FILE at_makefile
chmod 'u=rw,g=r,o=r' 'at_makefile'
set `wc -c 'at_makefile'`
count=$1
case $count in
3026) :;;
*) echo 'Bad character count in ''at_makefile' >&2
echo 'Count should be 3026' >&2
esac
echo Extracting 'at_wini.c.cdif'
sed 's/^X//' > 'at_wini.c.cdif' << '+ END-OF-FILE ''at_wini.c.cdif'
X*** /local/ast/minix/tape3b/kernel/at_wini.c Wed Jul 13 16:59:17 1988
X--- at_wini.c Mon Sep 26 23:34:01 1988
X***************
X*** 188,199 ****
X register struct wini *wn; /* pointer to the drive struct */
X {
X extern phys_bytes umap();
X! phys_bytes usr_buf = umap(proc_addr(wn->wn_procnr), D, wn->wn_address, BLOCK_SIZE);
X register int i, old_state;
X int r = 0;
X
X /* The command is issued by outputing 7 bytes to the controller chip. */
X
X if (usr_buf == (phys_bytes)0)
X return(ERR);
X command[0] = wn->wn_ctlbyte;
X--- 188,200 ----
X register struct wini *wn; /* pointer to the drive struct */
X {
X extern phys_bytes umap();
X! phys_bytes usr_buf;
X register int i, old_state;
X int r = 0;
X
X /* The command is issued by outputing 7 bytes to the controller chip. */
X
X+ usr_buf = umap(proc_addr(wn->wn_procnr), D, wn->wn_address, BLOCK_SIZE);
X if (usr_buf == (phys_bytes)0)
X return(ERR);
X command[0] = wn->wn_ctlbyte;
X***************
X*** 212,220 ****
X if (wn->wn_opcode == DISK_READ) {
X for (i=0; i> 4), (unsigned)(usr_buf & 0x0F));
X! restore(old_state);
X usr_buf += 0x200;
X if (win_results() != OK) {
X w_need_reset = TRUE;
X--- 213,221 ----
X if (wn->wn_opcode == DISK_READ) {
X for (i=0; i> 4), (unsigned)(usr_buf & 0x0F));
X! /* restore(old_state); */
X usr_buf += 0x200;
X if (win_results() != OK) {
X w_need_reset = TRUE;
X***************
X*** 230,238 ****
X return(ERR);
X }
X for (i=0; i> 4), (unsigned)(usr_buf&0x0F));
X! restore(old_state);
X usr_buf += 0x200;
X receive(HARDWARE, &w_mess);
X if (win_results() != OK) {
X--- 231,239 ----
X return(ERR);
X }
X for (i=0; i> 4), (unsigned)(usr_buf&0x0F));
X! /* restore(old_state); */
X usr_buf += 0x200;
X receive(HARDWARE, &w_mess);
X if (win_results() != OK) {
+ END-OF-FILE at_wini.c.cdif
chmod 'u=rw,g=r,o=r' 'at_wini.c.cdif'
set `wc -c 'at_wini.c.cdif'`
count=$1
case $count in
2242) :;;
*) echo 'Bad character count in ''at_wini.c.cdif' >&2
echo 'Count should be 2242' >&2
esac
echo Extracting 'clock.c.cdif'
sed 's/^X//' > 'clock.c.cdif' << '+ END-OF-FILE ''clock.c.cdif'
X*** /local/ast/minix/tape3b/kernel/clock.c Sat Jul 16 23:59:22 1988
X--- clock.c Mon Sep 26 23:34:02 1988
X***************
X*** 39,44 ****
X--- 39,45 ----
X /* Constant definitions. */
X #define MILLISEC 100 /* how often to call the scheduler (msec) */
X #define SCHED_RATE (MILLISEC*HZ/1000) /* number of ticks per schedule */
X+ #define FLUSH_MASK 07 /* bit mask used for flushing RS232 input */
X
X /* Clock parameters. */
X #define TIMER0 0x40 /* port address for timer channel 0 */
X***************
X*** 54,59 ****
X--- 55,61 ----
X PRIVATE message mc; /* message buffer for both input and output */
X PRIVATE int (*watch_dog[NR_TASKS+1])(); /* watch_dog functions to call */
X extern int flush_flag; /* tells clock when to flush the tty buf */
X+ extern int need_ega_int; /* tells clock to do ega adjust */
X
X /*===========================================================================*
X * clock_task *
X***************
X*** 191,204 ****
X
X accounting(); /* keep track of who is using the cpu */
X
X /* If a user process has been running too long, pick another one. */
X if (--sched_ticks == 0) {
X if (bill_ptr == prev_ptr) sched(); /* process has run too long */
X sched_ticks = SCHED_RATE; /* reset quantum */
X prev_ptr = bill_ptr; /* new previous process */
X
X! /* If characters are accumulating, call the TTY task. */
X! if (flush_flag) rs_flush(); /* flush accumulated tty input */
X
X /* Check if printer is hung up, and if so, restart it. */
X if (pr_busy && pcount > 0 && cum_count == prev_ct) pr_char();
X--- 193,212 ----
X
X accounting(); /* keep track of who is using the cpu */
X
X+ /* If input characters are accumulating on an RS232 line, process them. */
X+ if (flush_flag) {
X+ t = (int) realtime; /* only low-order bits matter */
X+ if ( (t & FLUSH_MASK) == 0) rs_flush(); /* flush tty input */
X+ }
X+
X /* If a user process has been running too long, pick another one. */
X if (--sched_ticks == 0) {
X if (bill_ptr == prev_ptr) sched(); /* process has run too long */
X sched_ticks = SCHED_RATE; /* reset quantum */
X prev_ptr = bill_ptr; /* new previous process */
X
X! /* Does ega need adjustment? */
X! if (need_ega_int) ega_int();
X
X /* Check if printer is hung up, and if so, restart it. */
X if (pr_busy && pcount > 0 && cum_count == prev_ct) pr_char();
+ END-OF-FILE clock.c.cdif
chmod 'u=rw,g=r,o=r' 'clock.c.cdif'
set `wc -c 'clock.c.cdif'`
count=$1
case $count in
2370) :;;
*) echo 'Bad character count in ''clock.c.cdif' >&2
echo 'Count should be 2370' >&2
esac
echo Extracting 'console.c.new'
sed 's/^X//' > 'console.c.new' << '+ END-OF-FILE ''console.c.new'
X
X/* Code and data for the IBM console driver. */
X
X#include "../h/const.h"
X#include "../h/type.h"
X#include "../h/callnr.h"
X#include "../h/com.h"
X#include "../h/error.h"
X#include "../h/sgtty.h"
X#include "../h/signal.h"
X#include "const.h"
X#include "type.h"
X#include "glo.h"
X#include "proc.h"
X#include "tty.h"
X
Xextern char alt_c[], unsh[], sh[], unm24[], m24[];
Xextern char dutch_unsh[], dutch_sh[], dutch_alt[];
Xextern char unsh_usx[], sh_usx[], scode_map[];
X
X/* Definitions used by the console driver. */
X#define COLOR_BASE 0xB800 /* video ram paragraph for color display */
X#define MONO_BASE 0xB000 /* video ram address for mono display */
X#define C_VID_MASK 0x3FFF /* mask for 16K video RAM */
X#define M_VID_MASK 0x0FFF /* mask for 4K video RAM */
X#define C_RETRACE 0x0300 /* how many characters to display at once */
X#define M_RETRACE 0x7000 /* how many characters to display at once */
X#define BEEP_FREQ 0x0533 /* value to put into timer to set beep freq */
X#define B_TIME 3 /* length of CTRL-G beep is ticks */
X#define BLANK 0x0700 /* determines cursor color on blank screen */
X#define LINE_WIDTH 80 /* # characters on a line */
X#define SCR_LINES 25 /* # lines on the screen */
X#define SCR_BYTES 8000 /* size video RAM. multiple of 2*LINE_WIDTH */
X#define CTRL_S 31 /* scan code for letter S (for CRTL-S) */
X#define MONOCHROME 1 /* value for tty_ioport tells color vs. mono */
X#define CONSOLE 0 /* line number for console */
X#define GO_FORWARD 0 /* scroll forward */
X#define GO_BACKWARD 1 /* scroll backward */
X#define TIMER2 0x42 /* I/O port for timer channel 2 */
X#define TIMER3 0x43 /* I/O port for timer channel 3 */
X#define KEYBD 0x60 /* I/O port for keyboard data */
X#define PORT_B 0x61 /* I/O port for 8255 port B */
X#define KBIT 0x80 /* bit used to ack characters to keyboard */
X#define LED_CODE 0xED /* command to keyboard to set LEDs */
X#define LED_DELAY 0x80 /* device dependent delay needed */
X
X/* Constants relating to the video RAM and 6845. */
X#define M_6845 0x3B0 /* port for 6845 mono */
X#define C_6845 0x3D0 /* port for 6845 color */
X#define EGA 0x3C0 /* port for EGA card */
X#define INDEX 4 /* 6845's index register */
X#define DATA 5 /* 6845's data register */
X#define OVRFL_REG 7 /* EGA overflow register */
X#define CUR_SIZE 10 /* 6845's cursor size register */
X#define VID_ORG 12 /* 6845's origin register */
X#define CURSOR 14 /* 6845's cursor register */
X#define LINE_CMP 0x18 /* EGA line compare register */
X
X/* Definitions used for determining if the keyboard is IBM or Olivetti type. */
X#define KB_STATUS 0x64 /* Olivetti keyboard status port */
X#define BYTE_AVAIL 0x01 /* there is something in KEYBD port */
X#define KB_BUSY 0x02 /* KEYBD port ready to accept a command */
X#define DELUXE 0x01 /* this bit is set up iff deluxe keyboard */
X#define GET_TYPE 5 /* command to get keyboard type */
X#define STANDARD_SCAN 13
X#define OLIVETTI_SCAN 12 /* the '=' key is 12 on olivetti, 13 on IBM */
X#define DUTCH_EXT_SCAN 32 /* scan code of 'd' */
X#define US_EXT_SCAN 22 /* scan code of 'u' */
X#define SPACE_SCAN 57 /* a space */
X#define PS_LED_DELAY 1200 /* delay for PS/2 */
X#define PS_KEYBD 0x68 /* I/O port for data on ps/2 */
X
X/* Scan codes to ASCII for IBM DUTCH extended keyboard */
X#define MINUS_DU 0x0035 /* scan code of '-' on Dutch extended keybd */
X#define NUM_SLASH_DU 0x0057 /* scan code of numeric keypad slash */
X
X#define ESCAPE_CODE 0x00E0 /* escape scan code */
X
X/* Global variables used by the console driver. */
XPUBLIC message keybd_mess; /* message used for console input chars */
XPUBLIC int vid_mask; /* 037777 for color (16K) or 07777 for mono */
XPUBLIC int vid_port; /* I/O port for accessing 6845 */
XPUBLIC int blank_color = 0x0700; /* display code for blank */
XPRIVATE vid_retrace; /* how many characters to display per burst */
XPRIVATE unsigned vid_base; /* base of video ram (0xB000 or 0xB800) */
XPRIVATE int esc; /* escape scan code detected? */
X
X/* Map from ANSI colors to the attributes used by the PC */
XPRIVATE int ansi_colors[8] = {0, 4, 2, 6, 1, 5, 3, 7};
X
X/*===========================================================================*
X * keyboard *
X *===========================================================================*/
XPUBLIC keyboard()
X{
X/* A keyboard interrupt has occurred. Process it. */
X
X int val, code, k, raw_bit;
X char stopc;
X
X /* Fetch the character from the keyboard hardware and acknowledge it. */
X if (ps) {
X port_in(PS_KEYBD, &code); /* get the scan code for key struck */
X ack_char(); /* acknowledge the character */
X } else {
X port_in(KEYBD, &code); /* get the scan code for the key struck */
X port_in(PORT_B, &val); /* strobe the keyboard to ack the char */
X port_out(PORT_B, val | KBIT); /* strobe the bit high */
X port_out(PORT_B, val); /* now strobe it low */
X }
X
X /* The IBM keyboard interrupts twice per key, once when depressed, once when
X * released. Filter out the latter, ignoring all but the shift-type keys.
X * The shift-type keys 29, 42, 54, 56, 58, and 69 must be processed normally.
X */
X
X if (keyb_type == DUTCH_EXT)
X if (esc) {
X /* Numeric slash gives scan codes 0xE0 0x35. */
X if (code == minus_code) code = num_slash;
X esc = FALSE;
X } else
X esc = (code == ESCAPE_CODE);
X
X k = code - 0200; /* codes > 0200 mean key release */
X if (k > 0) {
X /* A key has been released. */
X if (k != 29 && k != 42 && k != 54 && k != 56 && k != 58 && k != 69) {
X port_out(INT_CTL, ENABLE); /* re-enable interrupts */
X return; /* don't call tty_task() */
X }
X } else {
X /* Check to see if character is CTRL-S, to stop output. Setting xoff
X * to anything other than CTRL-S will not be detected here, but will
X * be detected later, in the driver. A general routine to detect any
X * xoff character here would be complicated since we only have the
X * scan code here, not the ASCII character.
X */
X raw_bit = tty_struct[CONSOLE].tty_mode & RAW;
X stopc = tty_struct[CONSOLE].tty_xoff;
X if (raw_bit == 0 && control && code == CTRL_S && stopc == XOFF_CHAR) {
X tty_struct[CONSOLE].tty_inhibited = STOPPED;
X port_out(INT_CTL, ENABLE);
X return;
X }
X }
X
X /* Check for CTRL-ALT-DEL, and if found, reboot the computer. */
X if (control && alt && code == DEL_CODE) reboot(); /* CTRL-ALT-DEL */
X
X /* Store the character in memory so the task can get at it later.
X * tty_driver_buf[0] is the current count, and tty_driver_buf[1] is the
X * maximum allowed to be stored.
X */
X if ( (k = tty_driver_buf[0]) < tty_driver_buf[1]) {
X /* There is room to store this character; do it. */
X k = k + k; /* each entry contains two bytes */
X tty_driver_buf[k+2] = code; /* store the scan code */
X tty_driver_buf[k+3] = CONSOLE; /* tell which line it came from */
X tty_driver_buf[0]++; /* increment counter */
X
X /* Build and send the interrupt message. */
X keybd_mess.m_type = TTY_CHAR_INT;
X keybd_mess.ADDRESS = tty_driver_buf;
X interrupt(TTY, &keybd_mess); /* send a message to the tty task */
X } else {
X /* Too many characters have been buffered. Discard excess. */
X port_out(INT_CTL, ENABLE); /* re-enable 8259A controller */
X }
X}
X
X
X/*===========================================================================*
X * console *
X *===========================================================================*/
XPRIVATE console(tp)
Xregister struct tty_struct *tp; /* tells which terminal is to be used */
X{
X/* Copy as much data as possible to the output queue, then start I/O. On
X * memory-mapped terminals, such as the IBM console, the I/O will also be
X * finished, and the counts updated. Keep repeating until all I/O done.
X */
X
X extern char get_byte();
X int count;
X char c;
X unsigned segment, offset, offset1;
X
X /* Loop over the user bytes one at a time, outputting each one. */
X segment = (tp->tty_phys >> 4) & WORD_MASK;
X offset = tp->tty_phys & OFF_MASK;
X offset1 = offset;
X count = 0;
X
X while (tp->tty_outleft > 0 && tp->tty_inhibited == RUNNING) {
X c = get_byte(segment, offset); /* fetch 1 byte from user space */
X out_char(tp, c); /* write 1 byte to terminal */
X offset++; /* advance one character in user buffer */
X tp->tty_outleft--; /* decrement count */
X }
X flush(tp); /* clear out the pending characters */
X
X /* Update terminal data structure. */
X count = offset - offset1; /* # characters printed *
X tp->tty_phys += count; /* advance physical data pointer */
X tp->tty_cum += count; /* number of characters printed */
X
X /* If all data has been copied to the terminal, send the reply. */
X if (tp->tty_outleft == 0) finish(tp, tp->tty_cum);
X}
X
X
X/*===========================================================================*
X * out_char *
X *===========================================================================*/
XPRIVATE out_char(tp, c)
Xregister struct tty_struct *tp; /* pointer to tty struct */
Xchar c; /* character to be output */
X{
X/* Output a character on the console. Check for escape sequences first. */
X
X if (tp->tty_esc_state > 0) {
X parse_escape(tp, c);
X return;
X }
X
X switch(c) {
X case 000: /* null is typically used for padding */
X return; /* better not do anything */
X case 007: /* ring the bell */
X flush(tp); /* print any chars queued for output */
X beep(BEEP_FREQ);/* BEEP_FREQ gives bell tone */
X return;
X
X case 013: /* CTRL-K */
X move_to(tp, tp->tty_column, tp->tty_row - 1);
X return;
X
X case 014: /* CTRL-L */
X move_to(tp, tp->tty_column + 1, tp->tty_row);
X return;
X
X case 016: /* CTRL-N */
X move_to(tp, tp->tty_column + 1, tp->tty_row);
X return;
X
X case '\b': /* backspace */
X move_to(tp, tp->tty_column - 1, tp->tty_row);
X return;
X
X case '\n': /* line feed */
X if (tp->tty_mode & CRMOD) out_char(tp, '\r');
X if (tp->tty_row == SCR_LINES-1)
X scroll_screen(tp, GO_FORWARD);
X else
X tp->tty_row++;
X
X move_to(tp, tp->tty_column, tp->tty_row);
X return;
X
X case '\r': /* carriage return */
X move_to(tp, 0, tp->tty_row);
X return;
X
X case '\t': /* tab */
X if ( (tp->tty_mode & XTABS) == XTABS) {
X do {
X out_char(tp, ' ');
X } while (tp->tty_column & TAB_MASK);
X return;
X }
X /* Ignore tab if XTABS is off--video RAM has no hardware tab */
X return;
X
X case 033: /* ESC - start of an escape sequence */
X flush(tp); /* print any chars queued for output */
X tp->tty_esc_state = 1; /* mark ESC as seen */
X return;
X
X default: /* printable chars are stored in ramqueue */
X#ifndef LINEWRAP
X if (tp->tty_column >= LINE_WIDTH) return; /* long line */
X#endif
X if (tp->tty_rwords == TTY_RAM_WORDS) flush(tp);
X tp->tty_ramqueue[tp->tty_rwords++]=tp->tty_attribute|(c&BYTE);
X tp->tty_column++; /* next column */
X#ifdef LINEWRAP
X if (tp->tty_column >= LINE_WIDTH) {
X flush(tp);
X if (tp->tty_row == SCR_LINES-1)
X scroll_screen(tp, GO_FORWARD);
X else
X tp->tty_row++;
X move_to(tp, 0, tp->tty_row);
X }
X#endif /* LINEWRAP */
X return;
X }
X}
X
X/*===========================================================================*
X * scroll_screen *
X *===========================================================================*/
XPRIVATE scroll_screen(tp, dir)
Xregister struct tty_struct *tp; /* pointer to tty struct */
Xint dir; /* GO_FORWARD or GO_BACKWARD */
X{
X int amount, offset, bytes, old_state;
X
X flush(tp);
X bytes = 2 * (SCR_LINES - 1) * LINE_WIDTH; /* 2 * 24 * 80 bytes */
X
X /* Scrolling the screen is a real nuisance due to the various incompatible
X * video cards. This driver supports hardware scrolling (mono and CGA cards)
X * and software scrolling (EGA cards).
X */
X if (softscroll) {
X /* Software scrolling for non-IBM compatible EGA cards. */
X if (dir == GO_FORWARD) {
X scr_up(vid_base, LINE_WIDTH * 2, 0,
X (SCR_LINES - 1) * LINE_WIDTH);
X vid_copy(NIL_PTR, vid_base, tp->tty_org+bytes, LINE_WIDTH);
X } else {
X scr_down(vid_base,
X (SCR_LINES - 1) * LINE_WIDTH * 2 - 2,
X SCR_LINES * LINE_WIDTH * 2 - 2,
X (SCR_LINES - 1) * LINE_WIDTH);
X vid_copy(NIL_PTR, vid_base, tp->tty_org, LINE_WIDTH);
X }
X } else if (ega) {
X int lines;
X /*
X * EGA scrolling. CGA and MDA scrolling is based on the fact
X * fact that the older adapters wrap around at 4K or whatever.
X * not all EGA's do. So instead we use the line compare
X * register. This is a scan line. Everything after this
X * line is displayed starting at the beginning of the display
X * RAM, ignoring the display start. So the top of the screen
X * starts whereover tty_org says it should in RAM. We compute
X * the scan line where the first page of RAM ends, and force
X * wraparound to the top using line compare. Since this uses
X * nothing beyond the first page of display RAM, and line
X * compare is a documented feature, it should work on all EGA
X * emulators. To keep arithmetic easier, we use a "page size"
X * of SCR_BYTES, which is exactly one screen full.
X */
X
X amount = (dir == GO_FORWARD ? 2 * LINE_WIDTH : -2 * LINE_WIDTH);
X tp->tty_org = (tp->tty_org + amount); /* top of screen in buffer */
X if (tp->tty_org >= SCR_BYTES) /* see if we wrapped around */
X tp->tty_org -= SCR_BYTES;
X else if (tp->tty_org < 0) /* wrap around the other way */
X tp->tty_org += SCR_BYTES;
X if (dir == GO_FORWARD) { /* compute line to clear */
X offset = tp->tty_org + bytes;
X if (offset >= SCR_BYTES)
X offset -= SCR_BYTES;
X }
X else
X offset = tp->tty_org;
X
X /* Blank the new line at top or bottom. */
X vid_copy(NIL_PTR, vid_base, offset, LINE_WIDTH);
X
X /* Figure out where to wrap around to top of display mem */
X lines = SCR_BYTES - tp->tty_org;
X lines = char_height * (lines / (LINE_WIDTH * 2)) - 1;
X if (lines >= (char_height * SCR_LINES))
X lines = 0x7fff; /* disable line compare */
X /* Now for the fun. Set the wraparound line. This is one of
X * the wierd registers where the high-order bit is in the
X * overflow register. Note that we're hardcoding the other bits
X * in it. This is another potential problem if a new model needs
X * extra bits. Unfortunately I couldn't figure out any way to
X * read this register. */
X
X ega_line = lines;
X ega_origin = tp->tty_org;
X
X /*
X * We now have the settings for the EGA registers. However
X * we don't want to do them now. The problem is that in
X * order to avoid flicker we have to wait for vertical
X * retrace. We don't want to do that for every line, because
X * it slows things like "more" down to the point where they
X * are about as slow as with software scrolling. So we
X * do the actual register update in ega_int, which is called
X * from the clock when need_ega_int is non-zero. If you
X * just increment need_ega_int in the next line, but don't
X * call ega_int, when you're cating to the terminal, you'll
X * get a whole screen at once. We choose to do it every
X * 8 lines in order to give some visual impression of
X * scrolling. So this is a compromise between a pure
X * clock driven approach, which is too fast, and updating
X * for each line, which is too slow.
X */
X
X if (need_ega_int++ > 8) ega_int();
X } else {
X /* Normal scrolling using the 6845 registers. */
X amount = (dir == GO_FORWARD ? 2 * LINE_WIDTH : -2 * LINE_WIDTH);
X tp->tty_org = (tp->tty_org + amount) & vid_mask;
X if (dir == GO_FORWARD)
X offset = (tp->tty_org + bytes) & vid_mask;
X else
X offset = tp->tty_org;
X
X /* Blank the new line at top or bottom. */
X vid_copy(NIL_PTR, vid_base, offset, LINE_WIDTH);
X set_6845(VID_ORG, tp->tty_org >> 1); /* 6845 thinks in words */
X }
X}
X
X/*===========================================================================*
X * ega_int *
X *===========================================================================*/
XPUBLIC ega_int()
X{
X/*
X * Need to change ega registers for scrolling. Called from clock
X * when need_ega_int is set. Done this way because we only want to
X * do this every so often, because we have to wait for a vert
X * retrace interval.
X */
X
X int old_state;
X
X /*
X * VID_ORG takes effect at the next retrace. LINE_CMP presumably
X * takes effect immediately, but won't show until we get to that
X * line. So to be completely clean, we first wait for non-retrace
X * status (which of course will usually be the case), set the
X * video origin to take effect on the next retrace, then wait
X * for that retrace, and then set the overflow reg. Perhaps this
X * is paranoid, but various people have reported screen glitch.
X */
X old_state = wait_no_retrace();
X set_6845(VID_ORG, ega_origin >> 1); /* 6845 thinks in words */
X wait_retrace();
X if (ega_line > 255)
X setb6845(OVRFL_REG, 0x1f); /* high order bit is in overflow reg */
X else
X setb6845(OVRFL_REG, 0x0f); /* high order bit 0 */
X setb6845(LINE_CMP, ega_line & 0xff); /* now set line compare reg */
X need_ega_int = 0;
X restore(old_state);
X}
X
X/*===========================================================================*
X * flush *
X *===========================================================================*/
XPRIVATE flush(tp)
Xregister struct tty_struct *tp; /* pointer to tty struct */
X{
X/* Have the characters in 'ramqueue' transferred to the screen. */
X
X if (tp->tty_rwords == 0) return;
X vid_copy((char *)tp->tty_ramqueue, vid_base, tp->tty_vid, tp->tty_rwords);
X
X /* Update the video parameters and cursor. */
X tp->tty_vid = (tp->tty_vid + 2 * tp->tty_rwords);
X if ((! softscroll) && ega && (tp->tty_vid >= SCR_BYTES))
X tp->tty_vid -= SCR_BYTES;
X set_6845(CURSOR, tp->tty_vid >> 1); /* cursor counts in words */
X tp->tty_rwords = 0;
X}
X
X
X/*===========================================================================*
X * move_to *
X *===========================================================================*/
XPRIVATE move_to(tp, x, y)
Xstruct tty_struct *tp; /* pointer to tty struct */
Xint x; /* column (0 <= x <= 79) */
Xint y; /* row (0 <= y <= 24, 0 at top) */
X{
X/* Move the cursor to (x, y). */
X
X flush(tp); /* flush any pending characters */
X if (x < 0 || x >= LINE_WIDTH || y < 0 || y >= SCR_LINES) return;
X tp->tty_column = x; /* set x co-ordinate */
X tp->tty_row = y; /* set y co-ordinate */
X tp->tty_vid = (tp->tty_org + 2*y*LINE_WIDTH + 2*x);
X if ((! softscroll) && ega && (tp->tty_vid >= SCR_BYTES))
X tp->tty_vid -= SCR_BYTES;
X
X set_6845(CURSOR, tp->tty_vid >> 1); /* cursor counts in words */
X}
X
X
X/*===========================================================================*
X * parse_escape *
X *===========================================================================*/
XPRIVATE parse_escape(tp, c)
Xregister struct tty_struct *tp; /* pointer to tty struct */
Xchar c; /* next character in escape sequence */
X{
X/* The following ANSI escape sequences are currently supported.
X * If n and/or m are omitted, they default to 1.
X * ESC [nA moves up n lines
X * ESC [nB moves down n lines
X * ESC [nC moves right n spaces
X * ESC [nD moves left n spaces
X * ESC [m;nH" moves cursor to (m,n)
X * ESC [J clears screen from cursor
X * ESC [K clears line from cursor
X * ESC [nL inserts n lines ar cursor
X * ESC [nM deletes n lines at cursor
X * ESC [nP deletes n chars at cursor
X * ESC [n@ inserts n chars at cursor
X * ESC [nm enables rendition n (0=normal, 4=bold, 5=blinking, 7=reverse)
X * ESC M scrolls the screen backwards if the cursor is on the top line
X */
X
X switch (tp->tty_esc_state) {
X case 1: /* ESC seen */
X tp->tty_esc_intro = '\0';
X tp->tty_esc_parmp = tp->tty_esc_parmv;
X tp->tty_esc_parmv[0] = tp->tty_esc_parmv[1] = 0;
X switch (c) {
X case '[': /* Control Sequence Introducer */
X tp->tty_esc_intro = c;
X tp->tty_esc_state = 2;
X break;
X case 'M': /* Reverse Index */
X do_escape(tp, c);
X break;
X default:
X tp->tty_esc_state = 0;
X break;
X }
X break;
X
X case 2: /* ESC [ seen */
X if (c >= '0' && c <= '9') {
X if (tp->tty_esc_parmp
X < tp->tty_esc_parmv + MAX_ESC_PARMS)
X *tp->tty_esc_parmp =
X *tp->tty_esc_parmp * 10 + (c - '0');
X break;
X }
X else if (c == ';') {
X if (++tp->tty_esc_parmp
X < tp->tty_esc_parmv + MAX_ESC_PARMS)
X *tp->tty_esc_parmp = 0;
X break;
X }
X else {
X do_escape(tp, c);
X }
X break;
X default: /* illegal state */
X tp->tty_esc_state = 0;
X break;
X }
X}
X
X/*===========================================================================*
X * do_escape *
X *===========================================================================*/
XPRIVATE do_escape(tp, c)
Xregister struct tty_struct *tp; /* pointer to tty struct */
Xchar c; /* next character in escape sequence */
X{
X int n, ct, vx, value, attr, src, dst, count, limit, m;
X
X /* Some of these things hack on screen RAM, so it had better be up to date */
X flush(tp);
X
X /* Handle a sequence beginning with just ESC */
X if (tp->tty_esc_intro == '\0') {
X switch (c) {
X case 'M': /* Reverse Index */
X if (tp->tty_row == 0)
X scroll_screen(tp, GO_BACKWARD);
X else
X tp->tty_row--;
X move_to(tp, tp->tty_column, tp->tty_row);
X break;
X
X default: break;
X }
X } else {
X /* Handle a sequence beginning with ESC [ and parameters */
X if (tp->tty_esc_intro == '[') {
X value = tp->tty_esc_parmv[0];
X attr = tp->tty_attribute;
X switch (c) {
X case 'A': /* ESC [nA moves up n lines */
X n = (value == 0 ? 1 : value);
X move_to(tp, tp->tty_column, tp->tty_row - n);
X break;
X
X case 'B': /* ESC [nB moves down n lines */
X n = (value == 0 ? 1 : value);
X move_to(tp, tp->tty_column, tp->tty_row + n);
X break;
X
X case 'C': /* ESC [nC moves right n spaces */
X n = (value == 0 ? 1 : value);
X move_to(tp, tp->tty_column + n, tp->tty_row);
X break;
X
X case 'D': /* ESC [nD moves left n spaces */
X n = (value == 0 ? 1 : value);
X move_to(tp, tp->tty_column - n, tp->tty_row);
X break;
X
X case 'H': /* ESC [m;nH" moves cursor to (m,n) */
X move_to(tp, MAX(1, MIN(LINE_WIDTH,
X tp->tty_esc_parmv[1])) - 1,
X MAX(1, MIN(SCR_LINES, tp->tty_esc_parmv[0])) - 1 );
X break;
X
X case 'J': /* ESC [J clears screen from cursor */
X if (value == 0) {
X n=2*((SCR_LINES-(tp->tty_row+1))*LINE_WIDTH
X + LINE_WIDTH - (tp->tty_column));
X vx = tp->tty_vid;
X if (ega) {
X ct = MIN(n, SCR_BYTES - vx);
X vid_copy(NIL_PTR, vid_base, vx, ct/2);
X n -= ct;
X if (n > 0)
X vid_copy(NIL_PTR,vid_base,0,n/2);
X } else
X long_vid_copy(NIL_PTR,vid_base,vx,n/2);
X }
X break;
X
X case 'K': /* ESC [K clears line from cursor */
X if (value == 0) {
X n = 2 * (LINE_WIDTH - (tp->tty_column));
X vid_copy(NIL_PTR, vid_base, tp->tty_vid, n/2);
X }
X break;
X
X case 'L': /* ESC [nL inserts n lines ar cursor */
X n = value;
X if (n < 1) n = 1;
X if (n > (SCR_LINES - tp->tty_row))
X n = SCR_LINES - tp->tty_row;
X
X /* These are all relative to start of screen, ignoring
X * difficulties such as wraparound. They are actually
X * appropiate args to scr_down for soft_scroll case.
X */
X src = (SCR_LINES - n) * LINE_WIDTH * 2 - 2;
X dst = SCR_LINES * LINE_WIDTH * 2 - 2;
X count = (SCR_LINES - n - tp->tty_row) * LINE_WIDTH;
X if (softscroll)
X limit = 0x7fff; /* no wraparound possible */
X else if (ega)
X limit = SCR_BYTES;
X else
X limit = vid_mask + 1;
X
X /*
X * The copy will have three phases: src and dest
X * wrapped around, dest wrapped around and src not,
X * and neither wrapped around
X */
X src += tp->tty_org;
X dst += tp->tty_org;
X if (src >= limit && dst >= limit) {
X m = MIN (count, (src - limit) / 2 + 1);
X l_scr_down(vid_base, src-limit, dst-limit, m);
X count -= m;
X src -= m * 2;
X dst -= m * 2;
X }
X if (dst >= limit && count > 0) {
X m = MIN (count, (dst - limit) / 2 + 1);
X l_scr_down(vid_base, src, dst - limit, m);
X count -= m;
X src -= m * 2;
X dst -= m * 2;
X }
X if (count > 0) l_scr_down(vid_base, src, dst, count);
X
X /* OK, now let's clear the lines we inserted */
X dst = tp->tty_row * LINE_WIDTH * 2;
X count = n * LINE_WIDTH;
X dst += tp->tty_org;
X if (dst < limit) {
X m = MIN (count, (limit - dst) / 2);
X long_vid_copy(NIL_PTR, vid_base, dst, m);
X count -= m;
X dst += m * 2;
X }
X if (count > 0)
X long_vid_copy(NIL_PTR,vid_base,dst-limit,count);
X break;
X
X case 'M': /* ESC [nM deletes n lines at cursor */
X n = value;
X if (n < 1) n = 1;
X if (n > (SCR_LINES - tp->tty_row))
X n = SCR_LINES - tp->tty_row;
X
X /* These are all relative to start of screen, ignoring
X * difficulties such as wraparound. They are actually
X * appropiate args to scr_down for soft_scroll case.
X */
X src = (tp->tty_row + n) * LINE_WIDTH * 2;
X dst = (tp->tty_row) * LINE_WIDTH * 2;
X count = (SCR_LINES - n - tp->tty_row) * LINE_WIDTH;
X if (softscroll)
X limit = 0x7fff; /* no wraparound possible */
X else if (ega)
X limit = SCR_BYTES;
X else
X limit = vid_mask + 1;
X /*
X * The copy will have three phases: src and dest
X * not wrapped, src wrapped dest not, both wrapped
X */
X src += tp->tty_org;
X dst += tp->tty_org;
X if (src < limit && dst < limit) {
X m = MIN (count, (limit - src) / 2);
X l_scr_up(vid_base, src, dst, m);
X count -= m;
X src += m * 2;
X dst += m * 2;
X }
X if (dst < limit && count > 0) {
X m = MIN (count, (limit - dst) / 2);
X l_scr_up(vid_base, src - limit, dst, m);
X count -= m;
X src += m * 2;
X dst += m * 2;
X }
X if (count > 0)
X l_scr_up(vid_base, src-limit, dst-limit,count);
X
X /* OK, now let's clear the lines at the bottom */
X dst = (SCR_LINES - n) * LINE_WIDTH * 2;
X count = n * LINE_WIDTH;
X dst += tp->tty_org;
X if (dst < limit) {
X m = MIN (count, (limit - dst) / 2);
X long_vid_copy(NIL_PTR, vid_base, dst, m);
X count -= m;
X dst += m * 2;
X }
X if (count > 0)
X long_vid_copy(NIL_PTR,vid_base,dst-limit,count);
X break;
X
X case 'P': /* ESC [nP deletes n chars at cursor */
X n = value;
X if (n < 1) n = 1;
X if (n > (LINE_WIDTH - tp->tty_column))
X n = LINE_WIDTH - tp->tty_column;
X src = (tp->tty_row * LINE_WIDTH + tp->tty_column+n) *2;
X dst = (tp->tty_row * LINE_WIDTH + tp->tty_column) * 2;
X count = LINE_WIDTH - tp->tty_column - n;
X src += tp->tty_org;
X dst += tp->tty_org;
X if ((! softscroll) && ega) {
X if (src > SCR_BYTES) src -= SCR_BYTES;
X if (dst > SCR_BYTES) dst -= SCR_BYTES;
X }
X scr_up(vid_base, src, dst, count);
X vid_copy(NIL_PTR, vid_base, dst + count * 2, n);
X break;
X
X case '@': /* ESC [n@ inserts n chars at cursor */
X n = value;
X if (n < 1) n = 1;
X if (n > (LINE_WIDTH - tp->tty_column))
X n = LINE_WIDTH - tp->tty_column;
X src = (tp->tty_row * LINE_WIDTH + LINE_WIDTH- n-1) * 2;
X dst = (tp->tty_row * LINE_WIDTH + LINE_WIDTH - 1) * 2;
X count = LINE_WIDTH - tp->tty_column - n;
X src += tp->tty_org;
X dst += tp->tty_org;
X if ((! softscroll) && ega) {
X if (src > SCR_BYTES)
X src -= SCR_BYTES;
X if (dst > SCR_BYTES)
X dst -= SCR_BYTES;
X }
X scr_down(vid_base, src, dst, count);
X dst = (tp->tty_row * LINE_WIDTH + tp->tty_column) * 2;
X dst += tp->tty_org;
X if ((! softscroll) && ega) {
X if (dst > SCR_BYTES) dst -= SCR_BYTES;
X }
X vid_copy(NIL_PTR, vid_base, dst, n);
X break;
X
X case 'm': /* ESC [nm enables rendition n */
X switch (value) {
X case 1: /* BOLD */
X if (color)
X tp->tty_attribute = /* red fg */
X (attr & 0xf0ff) | 0x0400;
X else
X tp->tty_attribute |= 0x0800; /* inten*/
X break;
X
X case 4: /* UNDERLINE */
X if (color)
X tp->tty_attribute = /* blue fg */
X (attr & 0xf0ff) | 0x0100;
X else
X tp->tty_attribute = /* ul */
X (attr & 0x8900);
X break;
X
X case 5: /* BLINKING */
X if (color) /* can't blink color */
X tp->tty_attribute = /* magenta fg */
X (attr & 0xf0ff) | 0x0500;
X else
X tp->tty_attribute |= /* blink */
X 0x8000;
X break;
X
X case 7: /* REVERSE (black on light grey) */
X if (color)
X tp->tty_attribute =
X ((attr & 0xf000) >> 4) |
X ((attr & 0x0f00) << 4);
X else if ((attr & 0x7000) == 0)
X tp->tty_attribute =
X (attr & 0x8800) | 0x7000;
X else
X tp->tty_attribute =
X (attr & 0x8800) | 0x0700;
X break;
X
X default: if (value >= 30 && value <= 37) {
X tp->tty_attribute =
X (attr & 0xf0ff) |
X (ansi_colors[(value - 30)] << 8);
X blank_color =
X (blank_color & 0xf0ff) |
X (ansi_colors[(value - 30)] << 8);
X } else if (value >= 40 && value <= 47) {
X tp->tty_attribute =
X (attr & 0x0fff) |
X (ansi_colors[(value - 40)] << 12);
X blank_color =
X (blank_color & 0x0fff) |
X (ansi_colors[(value - 40)] << 12);
X } else
X tp->tty_attribute = blank_color;
X break;
X }
X break;
X
X default:
X break;
X } /* closes switch(c) */
X } /* closes if (tp->tty_esc_intro == '[') */
X }
X tp->tty_esc_state = 0;
X}
X
X/*===========================================================================*
X * long_vid_copy *
X *===========================================================================*/
XPRIVATE long_vid_copy(src, base, offset, count)
Xchar *src;
Xunsigned int base, offset, count;
X{
X int ct;
X/*
X * break up a call to vid_copy for machines that can only write
X * during vertical retrace. Vid_copy itself does the wait.
X */
X
X while (count > 0) {
X ct = MIN (count, vid_retrace >> 1);
X vid_copy(src, base, offset, ct);
X if (src != NIL_PTR) src += ct * 2;
X offset += ct * 2;
X count -= ct;
X }
X}
X
X/*===========================================================================*
X * long_src_up *
X *===========================================================================*/
XPRIVATE l_scr_up(base, src, dst, count)
Xunsigned int base, src, dst, count;
X{
X int ct, old_state, wait;
X
X /*
X * Break up a call to scr_up for machines that can only write
X * during vertical retrace. scr_up doesn't do the wait, so we do.
X * Note however that we keep interrupts on during the scr_up. This
X * could lead to snow if an interrupt happens while we are doing
X * the display. Sorry, but I don't see any good alternative.
X * Turning off interrupts makes us loses RS232 input chars.
X */
X
X wait = color && ! ega;
X while (count > 0) {
X if (wait) {
X old_state = wait_retrace();
X restore(old_state);
X }
X ct = MIN (count, vid_retrace >> 1);
X scr_up(base, src, dst, ct);
X src += ct * 2;
X dst += ct * 2;
X count -= ct;
X }
X}
X
X/*===========================================================================*
X * long_scr_down *
X *===========================================================================*/
XPRIVATE l_scr_down(base, src, dst, count)
Xunsigned int base, src, dst, count;
X{
X int ct, old_state, wait;
X
X /* Break up a call to scr_down for machines that can only write
X * during vertical retrace. scr_down doesn't do the wait, so we do.
X * Note however that we keep interrupts on during the scr_down. This
X * could lead to snow if an interrupt happens while we are doing
X * the display. Sorry, but I don't see any good alternative.
X * Turning off interrupts makes us loses RS232 input chars.
X */
X
X wait = color && ! ega;
X while (count > 0) {
X if (wait) {
X old_state = wait_retrace();
X restore(old_state);
X }
X ct = MIN (count, vid_retrace >> 1);
X scr_down(base, src, dst, ct);
X src -= ct * 2;
X dst -= ct * 2;
X count -= ct;
X }
X}
X
X/*===========================================================================*
X * set_6845 *
X *===========================================================================*/
XPRIVATE set_6845(reg, val)
Xint reg; /* which register pair to set */
Xint val; /* 16-bit value to set it to */
X{
X/* Set a register pair inside the 6845.
X * Registers 10-11 control the format of the cursor (how high it is, etc).
X * Registers 12-13 tell the 6845 where in video ram to start (in WORDS)
X * Registers 14-15 tell the 6845 where to put the cursor (in WORDS)
X *
X * Note that registers 12-15 work in words, i.e. 0x0000 is the top left
X * character, but 0x0001 (not 0x0002) is the next character. This addressing
X * is different from the way the 8088 addresses the video ram, where 0x0002
X * is the address of the next character.
X */
X port_out(vid_port + INDEX, reg); /* set the index register */
X port_out(vid_port + DATA, (val>>8) & BYTE); /* output high byte */
X port_out(vid_port + INDEX, reg + 1); /* again */
X port_out(vid_port + DATA, val&BYTE); /* output low byte */
X}
X
X/* Similar, but used for registers where we only want to set one byte */
X
XPRIVATE setb6845(reg, val)
Xint reg; /* which register pair to set */
Xint val; /* 16-bit value to set it to */
X{
X port_out(vid_port + INDEX, reg); /* set the index register */
X port_out(vid_port + DATA, val); /* output high byte */
X}
X
X/*===========================================================================*
X * beep *
X *===========================================================================*/
XPRIVATE int beeping = 0;
XPRIVATE int stopbeep();
X
XPRIVATE beep(f)
Xint f; /* this value determines beep frequency */
X{
X/* Making a beeping sound on the speaker (output for CRTL-G). The beep is
X * kept short, because interrupts must be disabled during beeping, and it
X * is undesirable to keep them off too long. This routine works by turning
X * on the bits in port B of the 8255 chip that drive the speaker.
X */
X
X int k, s, x;
X message mess;
X
X if (beeping) return;
X s = lock(); /* disable interrupts */
X port_out(TIMER3,0xB6); /* set up timer channel 2 mode */
X port_out(TIMER2, f&BYTE); /* load low-order bits of frequency in timer */
X port_out(TIMER2,(f>>8)&BYTE); /* now high-order bits of frequency in timer */
X port_in(PORT_B,&x); /* acquire status of port B */
X port_out(PORT_B, x|3); /* turn bits 0 and 1 on to beep */
X beeping = 1;
X restore(s); /* re-enable interrupts to previous state */
X
X mess.m_type = SET_ALARM;
X mess.CLOCK_PROC_NR = TTY;
X mess.DELTA_TICKS = B_TIME;
X mess.FUNC_TO_CALL = stopbeep;
X sendrec(CLOCK, &mess);
X}
X
Xstopbeep() {
X int s, x;
X
X s = lock(); /* disable interrupts */
X port_in(PORT_B,&x); /* acquire status of port B */
X port_out(PORT_B, x & 0xfffc); /* turn bits 0 and 1 on to beep */
X beeping = 0;
X restore(s); /* re-enable interrupts to previous state */
X}
X
X/*===========================================================================*
X * set_leds *
X *===========================================================================*/
XPRIVATE set_leds()
X{
X/* Set the LEDs on the caps lock and num lock keys */
X
X int count, leds, dummy, i, port;
X
X if (pc_at == 0 && !ps) return; /* PC/XT doesn't have LEDs */
X leds = (numlock<<1) | (capslock<<2); /* encode LED bits */
X
X if (ps) {
X port = PS_KEYBD;
X count = PS_LED_DELAY;
X } else {
X count = LED_DELAY;
X port = KEYBD;
X }
X
X port_out(port, LED_CODE); /* prepare keyboard to accept LED values */
X port_in(port, &dummy); /* keyboard sends ack; accept it */
X for (i = 0; i < count; i++) ; /* delay needed */
X port_out(port, leds); /* give keyboard LED values */
X port_in(port, &dummy); /* keyboard sends ack; accept it */
X}
X
X/*===========================================================================*
X * tty_init *
X *===========================================================================*/
XPRIVATE tty_init()
X{
X/* Initialize the tty tables. */
X
X register struct tty_struct *tp;
X
X /* Set initial values. */
X caps_off = 1;
X num_off = 1;
X
X /* Tell the EGA card, if any, to simulate a 16K CGA card. */
X port_out(EGA + INDEX, 4); /* register select */
X port_out(EGA + DATA, 1); /* no extended memory to be used */
X
X for (tp = &tty_struct[0]; tp < &tty_struct[NR_CONS]; tp++) {
X tp->tty_inhead = tp->tty_inqueue;
X tp->tty_intail = tp->tty_inqueue;
X tp->tty_mode = CRMOD | XTABS | ECHO;
X tp->tty_devstart = console;
X tp->tty_makebreak = TWO_INTS;
X tp->tty_attribute = BLANK;
X tp->tty_erase = ERASE_CHAR;
X tp->tty_kill = KILL_CHAR;
X tp->tty_intr = INTR_CHAR;
X tp->tty_quit = QUIT_CHAR;
X tp->tty_xon = XON_CHAR;
X tp->tty_xoff = XOFF_CHAR;
X tp->tty_eof = EOT_CHAR;
X }
X
X if (color) {
X vid_base = COLOR_BASE;
X vid_mask = C_VID_MASK;
X vid_port = C_6845;
X vid_retrace = C_RETRACE;
X } else {
X vid_base = MONO_BASE;
X vid_mask = M_VID_MASK;
X vid_port = M_6845;
X vid_retrace = M_RETRACE;
X }
X
X if (ega) {
X vid_mask = C_VID_MASK;
X vid_retrace = SCR_BYTES;
X /* normally char height is 14 for EGA and 16 for VGA. If your BIOS
X * doesn't put the char height here, then just use a constant. This
X * should only be used by EGA code, as this value may not be set for
X * others.
X */
X char_height = get_byte(0x40, 0x85);
X }
X tty_driver_buf[1] = MAX_OVERRUN; /* set up limit on keyboard buffering*/
X set_6845(CUR_SIZE, 31); /* set cursor shape */
X set_6845(VID_ORG, 0); /* use page 0 of video ram */
X move_to(&tty_struct[0], 0, SCR_LINES-1); /* move cursor to lower left */
X
X if (ps) {
X set_leds(); /* turn off numlock led */
X softscroll = TRUE;
X }
X
X /* Determine which keyboard type is attached. The bootstrap program asks
X * the user to type an '='. The scan codes for '=' differ depending on the
X * keyboard in use.
X */
X switch(scan_code) {
X case STANDARD_SCAN: keyb_type = IBM_PC; break;
X case OLIVETTI_SCAN: keyb_type = OLIVETTI; load_olivetti(); break;
X case DUTCH_EXT_SCAN: keyb_type = DUTCH_EXT;
X load_dutch_table(); break;
X case US_EXT_SCAN: keyb_type = US_EXT;
X load_us_ext(); break;
X }
X}
X
X/*===========================================================================*
X * load_dutch_table *
X *===========================================================================*/
XPRIVATE load_dutch_table()
X{
X/* Load the scan code to ASCII table for extended dutch keyboard. */
X
X register int i;
X
X for (i = 0; i < NR_SCAN_CODES; i++) {
X sh[i] = dutch_sh[i];
X unsh[i] = dutch_unsh[i];
X alt_c[i] = dutch_alt[i];
X }
X
X minus_code = MINUS_DU;
X num_slash = NUM_SLASH_DU;
X}
X
X/*===========================================================================*
X * load_olivetti *
X *===========================================================================*/
XPRIVATE load_olivetti()
X{
X/* Load the scan code to ASCII table for olivetti type keyboard. */
X
X register int i;
X
X for (i = 0; i < NR_SCAN_CODES; i++) {
X sh[i] = m24[i];
X unsh[i] = unm24[i];
X }
X}
X
X/*===========================================================================*
X * load_us_ext *
X *===========================================================================*/
XPRIVATE load_us_ext()
X{
X/* Load the scan code to ASCII table for US extended keyboard. */
X
X register int i;
X
X for (i = 0; i < NR_SCAN_CODES; i++) {
X sh[i] = sh_usx[i];
X unsh[i] = unsh_usx[i];
X }
X}
X
X/*===========================================================================*
X * putc *
X *===========================================================================*/
XPUBLIC putc(c)
Xchar c; /* character to print */
X{
X/* This procedure is used by the version of printf() that is linked with
X * the kernel itself. The one in the library sends a message to FS, which is
X * not what is needed for printing within the kernel. This version just queues
X * the character and starts the output.
X */
X
X out_char(&tty_struct[0], c);
X}
X
X
X/*===========================================================================*
X * func_key *
X *===========================================================================*/
XPRIVATE func_key(ch)
Xchar ch; /* scan code for a function key */
X{
X/* This procedure traps function keys for debugging purposes. When MINIX is
X * fully debugged, it should be removed.
X */
X
X if (ch == F1) p_dmp(); /* print process table */
X if (ch == F2) map_dmp(); /* print memory map */
X if (ch == F3) { /* hardware vs. software scrolling */
X softscroll = 1 - softscroll; /* toggle scroll mode */
X tty_struct[0].tty_org = 0;
X move_to(&tty_struct[0], 0, SCR_LINES-1); /* cursor to lower left */
X set_6845(VID_ORG, 0);
X if (ega) {
X /* If EGA, reint line compare reg used for scrolling.
X * see comments in scroll code.
X */
X setb6845(OVRFL_REG, 0x1f);
X setb6845(LINE_CMP, 0xff);
X }
X
X if (softscroll)
X printf("\033[H\033[JSoftware scrolling enabled.\n");
X else
X printf("\033[H\033[JHardware scrolling enabled.\n");
X }
X
X#ifdef AM_KERNEL
X#ifndef NONET
X if (ch == F4) net_init(); /* re-initialise the ethernet card */
X#endif NONET
X#endif AM_KERNEL
X if (ch == F9 && control) sigchar(&tty_struct[0], SIGKILL); /* SIGKILL */
X}
+ END-OF-FILE console.c.new
chmod 'u=rw,g=r,o=r' 'console.c.new'
set `wc -c 'console.c.new'`
count=$1
case $count in
40525) :;;
*) echo 'Bad character count in ''console.c.new' >&2
echo 'Count should be 40525' >&2
esac
echo Extracting 'const.h.cdif'
sed 's/^X//' > 'const.h.cdif' << '+ END-OF-FILE ''const.h.cdif'
X*** /local/ast/minix/tape3b/kernel/const.h Fri Jul 15 20:31:25 1988
X--- const.h Mon Sep 26 23:34:07 1988
X***************
X*** 30,35 ****
X--- 30,36 ----
X #define PRINTER_VECTOR 15 /* line printer interrupt vector */
X #define SYS_VECTOR 32 /* system calls are made with int SYSVEC */
X #define AT_WINI_VECTOR 118 /* at winchester interrupt vector */
X+ #define PS_KEYB_VECTOR 0x71 /* keyboard interrupt vector for PS/2 */
X
X /* The 8259A interrupt controller has to be re-enabled after each interrupt. */
X #define INT_CTL 0x20 /* I/O port for interrupt controller */
X***************
X*** 37,42 ****
X--- 38,44 ----
X #define INT2_CTL 0xA0 /* I/O port for second interrupt controller */
X #define INT2_MASK 0xA1 /* setting bits in this port disables ints */
X #define ENABLE 0x20 /* code used to re-enable after an interrupt */
X+ #define PCR 0x65 /* Planar Control Register */
X #endif
X
X #define K_STACK_BYTES 512 /* how many bytes for the kernel stack */
+ END-OF-FILE const.h.cdif
chmod 'u=rw,g=r,o=r' 'const.h.cdif'
set `wc -c 'const.h.cdif'`
count=$1
case $count in
989) :;;
*) echo 'Bad character count in ''const.h.cdif' >&2
echo 'Count should be 989' >&2
esac
exit 0