ast@cs.vu.nl (Andy Tanenbaum) (09/28/88)
: 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<BLOCK_SIZE/SECTOR_SIZE; i++) { X receive(HARDWARE, &w_mess); X! old_state = lock(); X dma_read((unsigned)(usr_buf >> 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<BLOCK_SIZE/SECTOR_SIZE; i++) { X receive(HARDWARE, &w_mess); X! /* old_state = lock(); */ X dma_read((unsigned)(usr_buf >> 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<BLOCK_SIZE/SECTOR_SIZE; i++) { X! old_state = lock(); X dma_write((unsigned)(usr_buf >> 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<BLOCK_SIZE/SECTOR_SIZE; i++) { X! /* old_state = lock(); */ X dma_write((unsigned)(usr_buf >> 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