[comp.os.minix] new tty driver - 1 of 3

marks@elec.uq.oz (Mark Schulz) (09/22/88)

Please reply to hannam.uq.oz . I'm using someone elses account to post
this.

echo x - read_me
sed 's/^X//' >read_me <<'*-*-END-of-read_me-*-*'
XPlease reply to hannam.uq.oz . I'm using someone elses account to post
Xthis.
X
XThis is a brand new tty driver. It is vastly superier to the original V1.3
Xin performance (throughput speed). It takes a significant amount of
Xrecompiling to install the new driver but the results are worthwhile. The
Xrest of the kernel has hardly been touched at all except to improve
Xinterrupt latency by removing non-essential locks.
XThe tty driver is split into 3 files ...
Xtty1.c	- contains all the device independent code. (this is truly device
X		independent and it should be very easy to add a new
X		low level driver for some other strange device you may have
X		connected to your PC). Two examples of low level drivers
X		are given, tty2.c (console) and tty3.c (rs232 using an 8250).
Xtty2.c	- contains the console driver. This supports a very large subset of
X		ANSI (it's missing scrolling regions, printer port etc).
X		Note that insert line and delete line + insert chars, delete
X		chars + insert mode are fully supported etc.
X		The cludgy EGA patches that have been floating around the
X		network are NOT in this version. This version has been
X		written properly from the start to handle such cards as EGA.
X		All scrolling is via hardware scrolling, there is no
X		software scrolling available. For those that have EGA cards
X		and find this excessivly fast there is a function key that
X		enables you to toggle between CGA type video access and the
X		faster EGA access's.
X		The function keys have been given their proper ANSI codes
X		and so the special keys have been moved to <Cntrl> <alt> Fx
X		keys. The <Alt> Fx keys, <Shift> <Alt> Fx , <Cntrl> Fx &
X		<Shift> Fx keys have been given pre-defined key macros.
X		At present they can only be reprogrammed at compile time.
X		The special Fx keys are:
X		<Cntrl> <Alt> F1	- process map
X		<Cntrl> <Alt> F2	- memory map
X		<Cntrl> <Alt> F3	- EGA/ ??? toggle
X		<Cntrl> <Alt> F4	- amoeba init (if defined)
X		<Cntrl> <Alt> F9	- kill -9 -1
X	As a general point, the scancode to ascii translation routine,
X	whilst defined in the tty file, is a general translation routine
X	and could be used on any terminal. The interface has been produced
X	such that it is possible to add any translation routine very simply.
X	This translation routine interface has facilities for generating macros
X	(such as is used for the arrow, Fn, and general macros for the console)
X	. For Example, an EBDIC to ascii converter may be worth while.
X	At some lator date some one may add an ioctl call to allow the
X	translation routine to be changed from amongst a small set provided
X	by the kernel.
Xtty3.c	- The rs232 driver routines for the standard PC. This is significantly
X	superior in performance to the original V1.3 . It also includes both
X	xonxoff handshaking and hardware handshaking.
X
X	Two # variables are used to control the compilation ...
X	#ifdef ...
X	SLOW - default baud = 1200  (normally 4800)
X	NXONXOFF - default handshaking is hardware (normally xonxoff).
X
X	For the TX, hardware handshaking will not work over a 3 wire cable
X	so xonxoff is generally best. (Blame the PC hardware.)
X	For the RX, xonxoff is handled by the high level driver (in COOKED
X	or CBREAK only). Hardware handshaking works irrespective of the
X	cable connected so generally hardware is the best. (xonxoff is
X	still handled by the high level driver in hardware handshaking modes).
X
X	These routines have been used upto 38400 to non IBM-PC machines
X	and upto 57600 between PC's. (I haven't tried at 115200 although
X	it is defined). Note - these are NOT throughput figures just speeds
X	at which it will still operate reliably.
X
XThe total compiled code is approximately 1K larger than the old V1.3 but
Xit includes many many new features in that 1K. For Example, LCASE, CTLECH
XDECCTQ, CRTBS, CRTERA, CRTKIL, PRTERA etc etc are included (as well as the
Xrs232 flow control and the extra console ANSI codes.) The source code is
Xalmost exactly the same size (for the tty files).
X
XThe misfeatures in the V1.3 tty driver that prompted the rewrite are ...
X1/  Only one process is allowed to write to the tty at once
X	(and read but it really doesn't make sence for more than one to read)
X2/  Grossly inefficient and messy code (in my opinion)
X3/  No flow control on the rs232 lines
X4/  If a reader requests more chars than we can hold in our input buffer,
X	and the user doesn't type a nl before the tty buffer overflows
X	then the terminal hangs permanently.
X5/  A similiar problem to the above except on output.
X6/  If a serial line is overrun (starts to lose characters) then every
X	terminal on the system will start to lose characters
X7/  Insufficient range of ioctl calls to implement any decent screen driving
X	package (or even kermit without patching the kernel).
X
XA new ioctl.c has been provided for the libraries ...
X	This means any program that uses ioctl will need to be recompiled.
X	MINED relies on no EOL wrap when compiled without termcap. The
X	new tty driver has EOL wrap so change the init string in mined
X	to include the escape codes to turn off EOL wrap ("ESC [ 7 l" I
X	think from memory - see tty2.c) and possibly change the exit
X	string to turn it back on again. This is simple enough for
X	most people to patch by hand (my mined is not standard any more
X	or I would patch a diff)
X	A new version of STTY has also been provided to show some of the
X	new features.
X	LOGIN has been fixed severly (little to do with the change in tty)
X	and TERM has been fixed for the new TTY.
X	XONXOFF is a short program that enables you to change between
X	hardware and xonxoff handshaking.
X	Full files have been provided for all the above (rather than diffs)
X	as the diff files are almost as long or longer.
Xmpx88.asd is a diff file relative to my assembler (not MINIX). It should
X	be obvious how to patch your own mpx88.???
Xklib88.as is the full listing using my assembler ... to convert to
X	whatever you use (I would appreciate it if someone did this for the
X	standard MINIX assembler and posted it.)
X	Note carefully when interrupts etc are turned off.
X	Some notes on my C - compiler ...
X	it expects cs,ds,ss,sp,bp,si,di to be unaltered upon return,
X	es, ax, bx, cx, dx can be altered without harm.
X	ax is the return register for ints etc and ax,dx for longs.
X
XFILES:
Xread_me		- this file (documentation)
Xsgtty.h		- replacement for h/sgtty.h, <sgtty.h>, <minix/sgtty.h>
Xioctl.c		- replacement for lib/ioctl.c
Xstty.c		- replacement for commands/stty.c
Xlogin.c		- replacement for commands/login.c
Xterm.c		- replacement for commands/term.c
Xxonxoff.c	- new in commands
Xtty.h		- new in kernel
Xbuffer.h	- new in kernel
Xtty1.c		- new in kernel
Xtty2.c		- new in kernel
Xtty3.c		- new in kernel
Xtty.c		- deleted from kernel
Xklib88.as	- replacement for kernel/klib88.as
Xmpx88.asd	- diff file on kernel/mpx88.as
Xtable.cd	- diff file on kernel/table.c
X	/* Thanks to hedrick@athos.rutgers.edu (Charles Hedrick) 
X	 * for these interrupt latency reducing sections
X	 * (and bug fix for printer.c).
X	 */
Xprinter.cd	- diff file on kernel/printer.c
Xat_wini.cd	- diff file on kernel/at_wini.c
Xxt_wini.cd	- diff file on kernel/xt_wini.c
*-*-END-of-read_me-*-*
echo x - buffer.h
sed 's/^X//' >buffer.h <<'*-*-END-of-buffer.h-*-*'
X/* buffer.h - buffer routines
X *
X * Written by:  A.Hannam	(Jul 1987)
X *
X * Modifications:
X */
X
X/*
X *	This header file provides some definitions and macro's for buffer
X *	handling. They compile to very few instructions and should be very
X *	fast. The macro's are not protected from interrupt type access and
X *	should be used inside exclusion locks for this type of work.
X *	No error checking is done to see if there are any valid objects
X *	or if the buffer is full on reads or writes etc.
X */
X
X/****************************************************************************/
X
X/*	Macros to define the types.
X *	Also defines 'bool' type and the 'between' function macro.
X */
X
Xtypedef unsigned char bool;
X#ifndef TRUE
X#	define	TRUE	1		/* Really any non zero is true */
X#endif
X#ifndef FALSE
X#	define FALSE	0
X#endif
X
X#define between(a,b,c)	((b < a) ? a : ((b > c) ? c : b))
X
X	/* Object FIFO - size <= 128 && power of 2 */
X#define GEN_S_BUF_TYPE(obj,size)	\
Xtypedef struct {			\
X	obj	b[size];		\
X	unsigned char in, out, count;	\
X	} obj/**/size;
X
X	/* Object FIFO - size >= 256 && power of 2 */
X#define GEN_L_BUF_TYPE(obj,size)	\
Xtypedef struct {			\
X	obj	b[size];		\
X	unsigned in, out, count;	\
X	} obj/**/size;
X
X/***************************************************************************/
X
X/* Fast Buffers - The macros provide fast access "getting" or "putting"
X *	for objects. (Not Both !!). Use the Macro's defined where the
X *	speed is desired. To access on the slow side, copy to another fbuf
X *	variable, re-initialize the original and then use loops to access
X *	the objects from the copy. These routines are ideal where one side is
X *	an interrupt handler.
X *	Note: the fast "getting" macros assume the objects are stored in
X *		reverse order.
X */
X
X
X	/* Fast Buffer - size <= 128 && power of 2 */
X#define GEN_S_FBUF_TYPE(obj,size)	\
Xtypedef struct {		\
X	obj	b[size];	\
X	unsigned char count;	\
X	} f/**/obj/**/size;
X
X	/* Fast Buffer - size >= 256 && power of 2 */
X#define GEN_L_FBUF_TYPE(obj,size)	\
Xtypedef struct {		\
X	obj	b[size];	\
X	unsigned count;		\
X	} f/**/obj/**/size;
X
X/***************** Routines to act on all the types defined above ************/
X
X#define bufsize(buf)	(sizeof((buf).b)/sizeof((buf).b[0]))/* max obj's in buf */
X#define bufcount(buf)	((buf).count)			/* objects in buf   */
X#define bufempty(buf)	(!((buf).count))		/* buf is empty */
X#define bufnempty(buf)	((buf).count)			/* buf is not empty */
X#define buffull(buf)	((buf).count >= bufsize(buf))	/* buf is full */
X#define bufnfull(buf)	((buf).count < bufsize(buf))	/* buf is not full. */
X
X/*********************** These work on the FIFO buffers **********************/
X
X	/* bufinit - initialize the buffer */
X#define bufinit(buf)	(buf).count= (buf).out= (buf).in= 0	/* initialize buf   */
X
X	/* getobj - Non Destructive Read */
X#define getobj(buf)	(buf).b[(buf).out]
X
X	/* advgetobj - advances the FIFO pointers after getobj */
X#define advgetobj(buf)	(buf).count--;(buf).out++;(buf).out &= (bufsize(buf) -1)
X
X		/* putobj - Write to FIFO */
X#define putobj(buf,obj)	\
X	(buf).b[(buf).in++]= (obj); (buf).count++; (buf).in &= (bufsize(buf) -1)
X
X/*********************** These work on the Fast Buffers **********************/
X
X	/* fbufinit - initialize the fbuf */
X#define fbufinit(fbuf)		(fbuf).count= 0
X
X	/* putfobj - Fast Write to fbuf */
X#define putfobj(fbuf,obj)	(fbuf).b[(fbuf).count++]= (obj)
X
X	/* copyfobj - Transfer the data to safety */
X#define copyfobj(fbuf1,fbuf2)	(fbuf1)=(fbuf2)
X
X	/* getfobj - Fast (Destructive) Read from fbuf */
X#define getfobj(fbuf)		(fbuf).b[--(fbuf).count]
X
X/*****************************************************************************/
*-*-END-of-buffer.h-*-*
echo x - sgtty.h
sed 's/^X//' >sgtty.h <<'*-*-END-of-sgtty.h-*-*'
X/* sgtty.h - ioctl information
X *
X * Written by:  A.Hannam	(Feb 1988)
X *
X * Modifications:
X * 21/8/88  -	Modified for MINIX V1.3 on IBM-PC
X *			support new tty driver
X */
X
X/* Data structures for IOCTL. */
X
Xstruct sgttyb {
X  char sg_ispeed;		/* input speed */
X  char sg_ospeed;		/* output speed */
X  char sg_erase;		/* erase character */
X  char sg_kill;			/* kill character */
X  int  sg_flags;		/* mode flags */
X};
X
Xstruct tchars {
X  char t_intrc;			/* SIGINT char */
X  char t_quitc;			/* SIGQUIT char */
X  char t_startc;		/* start output (initially CTRL-Q) */
X  char t_stopc;			/* stop output	(initially CTRL-S) */
X  char t_eofc;			/* EOF (initially CTRL-D) */
X  char t_brkc;			/* input delimiter (like nl) */
X};
X
X#define IOC_IN		0x0080
X#define IOC_OUT		0x8000
X#define IOC_VOID	0x0000
X#define _IOWR(x,y,t)	(IOC_OUT  | IOC_IN   | ('x'<<8) | y)
X#define _IOR(x,y,t)	(IOC_OUT  | ('x'<<8) | y)
X#define _IOW(x,y,t)	(IOC_IN   | ('x'<<8) | y)
X#define _IO(x,y)	(IOC_VOID | ('x'<<8) | y)
X
X#define TIOCMODG  _IOR(t, 3, int)	/* Get/Set modem control state */
X#define TIOCMODS  _IOW(t, 4, int)
X#define		TIOCM_LE	0001	/* line enable (ignored) */
X#define		TIOCM_DTR	0002	/* data terminal ready */
X#define		TIOCM_RTS	0004	/* request to send */
X#define		TIOCM_ST	0010	/* secondary transmit (ignored) */
X#define		TIOCM_SR	0020	/* secondary recieve (ignored) */
X#define		TIOCM_CTS	0040	/* clear to send */
X#define		TIOCM_CAR	0100	/* carrier detect */
X#define		TIOCM_CD	TIOCM_CAR
X#define		TIOCM_RNG	0200	/* ring indicater */
X#define		TIOCM_RI	TIOCM_RNG
X#define		TIOCM_DSR	0400	/* data set ready */
X#define TIOCGETP  _IOR(t, 8, struct sgttyb)	/* Get/Set parameters */
X#define TIOCSETP  _IOW(t, 9, struct sgttyb)
X#define TIOCSETN  _IOW(t, 10, struct sgttyb)	/* as above but don't flush */
X	/* sg_ispeed/sg_ospeed - Baud Rates */
X#define		NO_BAUDS 19	/* there are 19 different speeds */
X#define		B00	0	/* no such baud rate */
X#define		B45	1	/* really 45.5 */
X#define		B50	2
X#define		B75	3
X#define		B110	4
X#define		B134	5	/* really 134.5 */
X#define		B150	6
X#define		B200	7	/* Not all of these will necessarily be	 */
X#define		B300	8	/* 	implemented.			 */
X#define		B600	9	/* E.g. The console ignores these bauds. */
X#define		B1200	10
X#define		B1800	11
X#define		B2000	12
X#define		B2400	13
X#define		B4800	14
X#define		B9600	15
X#define		B19200	16
X#define		B38400	17
X#define		B57600	18
X#define		B115200	19
X	/* sg_flags - Terminal Mode Flags */
X#define		TOSTOP	0x8000	/* SIGSTOP (SIGBUS in MINIX) on backgnd outpt*/
X#define		DECCTQ	0x4000	/* only ^Q starts after ^S */
X#define		CTLECH	0x2000	/* echo control chars as ^X */
X#define		CRTKIL	0x1000	/* kill line with "\b \b" */
X#define		XTABS	0x0800	/* do tab expansion */
X#define		CRTERA	0x0400	/* "\b \b" to wipe out char */
X#define		PRTERA	0x0200	/* \ .. / to wipe out chars */
X#define		CRTBS	0x0100	/* "\b" to wipe out chars */
X#define		ANYP	0x00C0	/* rec any, send no parity */
X#define		EVENP	0x0080	/* rec/send even parity */
X#define		ODDP	0x0040	/* rec/send odd parity */
X#define		RAW	0x0020	/* enable raw mode */
X#define		CRMOD	0x0010	/* map lf to cr + lf */
X#define		ECHO	0x0008	/* echo input */
X#define		LCASE	0x0004	/* simulate lower case */
X#define		CBREAK	0x0002	/* enable cbreak mode */
X#define		NOHANG	0x0001	/* no SIGHUP on carrier drop */
X#define		COOKED	0x0000	/* neither CBREAK nor RAW */
X#define		NONEP	0x0000	/* neither EVENP or ODDP or ANYP (no parity) */
X#define TIOCSETC  _IOW(t, 17, struct tchars)	/* Get/Set chars */
X#define TIOCGETC  _IOR(t, 18, struct tchars)
X
X/* Locals from 127 down */
X#define TIOCGETM  _IOR(t, 127, int)	/* Get/Set Device Modes */
X#define TIOCSETM  _IOW(t, 126, int)
X	/* Flags for TIOCGETM/TIOCSETM */
X#define	D_CONSOLE		0x0100	/* This is the console terminal    */
X#define		CON_COOK8	0x0001	/* Generate 8 bits in cooked modes */
X#define		CON_LOCK	0x0002	/* Console keyboard is locked */
X#define		CON_WRAP	0x0004	/* Console does EOL wrap & BS wrap */
X#define		CON_INSERT	0x0008	/* Console is in insert mode */
X#define D_SERIAL		0x0200	/* This is a async serial terminal */
X#define		SER_DATABITS	0x0003	/* Mask for the no. of data bits   */
X#define		SER_5DATA	0x0000	/* Generate 5 data bits */
X#define		SER_6DATA	0x0001	/* Generate 6 data bits */
X#define		SER_7DATA	0x0002	/* Generate 7 data bits */
X#define		SER_8DATA	0x0003	/* Generate 8 data bits */
X#define		SER_1STOP	0x0000	/* Generate 1 stop bit  */
X#define		SER_2STOP	0x0004	/* Generate 2 stop bits */
X#define		RX_XONXOFF	0x0008	/* Use xon-xoff RX flow cntrl */
X#define		TX_XONXOFF	0x0010	/* Use only xon-xoff TX flow cntrl */
X
X#define TIOCSBRK  _IO(t, 123)		/* set break bit */
X#define TIOCCBRK  _IO(t, 122)		/* clear break bit */
X#define TIOCSDTR  _IO(t, 121)		/* set data terminal ready */
X#define TIOCCDTR  _IO(t, 120)		/* clear data terminal ready */
X#define TIOCSTI   _IOW(t, 114, char)	/* simulate terminal input */
X#define TIOCSTOP  _IO(t, 111)		/* simulate ^S */
X#define TIOCSTART _IO(t, 110)		/* simulate ^Q */
X#define TIOCSMLB  _IO(t, 104)		/* turn on loopback mode */
X#define TIOCCMLB  _IO(t, 103)		/* turn off loopback mode */
X
X#define FIONREAD  _IOR(f, 102, unsigned)/* # of chars in input queue */
*-*-END-of-sgtty.h-*-*
echo x - tty.h
sed 's/^X//' >tty.h <<'*-*-END-of-tty.h-*-*'
X/* tty.h - include file for tty driver
X *
X * Written by:  A.Hannam	(Feb 1988)
X *
X * Modifications:
X * 21/8/88  -	Modified for MINIX V1.3 on IBM-PC
X *			Added flush-flag etc to allow flushing by clock
X */
X
X#include "buffer.h"
X
X#ifndef SIGSTOP			/* not implemented yet */
X#define SIGSTOP		SIGBUS	/* use SIGBUS for SIGSTOP in MINIX */
X#endif
X
X	/* The types of terminal known about so far */
X#define NR_CONS		1			/* No of console terminals */
X#define NR_8250S	1			/* No of 8250 serial terms */
X#define NR_TTYS		NR_CONS + NR_8250S	/* Total No of terminals   */
X
X/* Description of the above terminals - tty_struct[] Numbers */
X#define CON1		0		/* Console - 1 of NR_CONS  */
X#define COM1		NR_CONS+0	/* Serial  - 1 of NR_8250S */
X#define	COM2		NR_CONS+1	/* Serial  - 2 of NR_8250S */
X#define COM3		NR_CONS+2	/* Serial  - 3 of NR_8250S */
X#define COM4		NR_CONS+3	/* Serial  - 4 of NR_8250S */
X/* Next type of device will be "NR_CONS + NR_8250S + 0" etc */
X
X#ifdef HIGH_LEVEL
X		/* Their initialization routines */
Xextern void init_con(), init_8250();
Xstatic void (*dev_init[NR_TTYS])()= {
X	init_con, init_8250
X	};
X
Xint	flush_flag;	/* Chars are ready for input or needed for output */
X
X#else
X	extern flush_flag;
X#endif
X
X	/* Info that must be stored to enable backspacing in cooked modes */
Xtypedef struct charpos {
X	unsigned char ch,col;
X	} charpos;
X
X	/* These lines set the size of tty_entry */
XGEN_S_BUF_TYPE(charpos,128)
XGEN_S_FBUF_TYPE(char,32)
X#define MAX_WRITERS	3
X
X	/* Provide a name for the fbuf that gives no indication of size */
Xtypedef fchar32 charfbuf;
X#define CHAR_BUF_THRESHOLD	28	/* Flush if more than this many chars*/
X
X	/* The definition of a tty_entry */
Xtypedef struct {
X  /* Input queue.  Typed characters are stored here until read by a program. */
X  charpos128 tty_inbuf;		/* buffer used to store the processed chars */
X  int tty_lfct;			/* # line feeds in tty_inbuf */
X
X  /* Information about incomplete read requests is stored here. */
X  char tty_incaller;		/* process that made the call (usually FS) */
X  char tty_inproc;		/* process that wants to read from tty */
X  int tty_inseg;		/* segment of address where data is to go */
X  int tty_inoffset;		/* offset of address where data is to go */
X  int tty_inleft;		/* how many chars are still needed */
X  int tty_incum;		/* the number of chars transfered so far */
X
X  /* Information about incomplete write requests is stored here. */
X  struct writers {
X	char otcaller;		/* process that made the call (usually FS) */
X	char outproc;		/* process that wants to write to tty */
X	int  seg;		/* seg of address where data comes from */
X	int  offset;		/* offset of address where data comes from */
X	int  outleft;		/* # chars yet to be copied to tty_outqueue */
X	} w[MAX_WRITERS];
X  int tty_writers;		/* no of process's currently trying to write */
X  int tty_cum;			/* # chars sent to output device so far */
X
X  /* Information specific to this terminal */
X  bool (*tty_devraw)();		/* routine to do raw device output (tp,c,p) */
X#define WRITE_OUT	0		/* use the write stream */
X#define ECHO_OUT	1		/* use the echo stream */
X  void (*tty_devclr)();		/* routine to clear raw output buffers (tp) */
X  void (*tty_devflush)();	/* routine to flush raw output buffers (tp) */
X  void (*tty_devempty)();	/* routine to say raw input bufs clear (tp) */
X  void (*tty_devioctl)();	/* routine to do raw device ioctl's (tp,&m) */
X  unsigned (*tty_devtrans)();	/* routine to do character translation (uint)*/
X#define MARKER		0x8000		/* The mark bit for translation */
X  charfbuf *tty_fbuf;		/* the fbuf from which to get raw input */
X
X  /* Terminal parameters and status. */
X  int tty_ddmod;		/* device dependant terminal mode */
X  int tty_mode;			/* terminal mode set by IOCTL flags */
X  int tty_pgrp;			/* the tty process group */
X  char tty_ispeed;		/* terminal input baud rate */
X  char tty_ospeed;		/* terminal output baud rate */
X  int tty_column;		/* current column number (0-origin) */
X
X  unsigned tty_state;
X#define ESCAPED		1	/* 1 when '\' just seen, else 0 */
X#define INHIBITED	2	/* 1 when CTRL-S just seen (stops output) */
X#define TRANSLATE	4	/* 1 when special char translation required */
X#define WAITING		8	/* 1 when output proc wants a reply */
X#define COK8BIT		0x10	/* 1 when 8 bits even in cooked modes */
X#define BS_WRAP		0x20	/* 1 when column is zero and a \b occurs 
X					- this is not reset by the HL driver */
X#define IN_FLUSH	0x40	/* 1 when the device dependant drivers have
X					input ready for processing */
X#define OUT_FLUSH	0x80	/* 1 when the device dependant drivers need
X					to have more chars feed to them to
X					keep them busy on output */
X#define DD_FLAG1	0x100	/* Device dependant state flags */
X#define DD_FLAG2	0x200
X#define DD_FLAG3	0x400
X#define DD_FLAG4	0x800
X#define DD_FLAG5	0x1000
X#define DD_FLAG6	0x2000
X#define DD_FLAG7	0x4000
X#define DD_FLAG8	0x8000
X
X  /* User settable characters: erase, kill, interrupt, quit, x-on; x-off. */
X  char tty_erase;		/* char used to erase 1 char (init ^H)     */
X  char tty_kill;		/* char used to erase a line (init @)      */
X  char tty_intr;		/* char used to send SIGINT  (init DEL)    */
X  char tty_quit;		/* char used for core dump   (init CTRL-\) */
X  char tty_xon;			/* char used to start output (init CTRL-Q) */
X  char tty_xoff;		/* char used to stop output  (init CTRL-S) */
X  char tty_eof;			/* char used to stop output  (init CTRL-D) */
X  char tty_brk;			/* char used as input delimiter (not used) */
X
X} tty_entry;
X
Xextern tty_entry tty_struct[];
*-*-END-of-tty.h-*-*
echo x - at_wini.cd
sed 's/^X//' >at_wini.cd <<'*-*-END-of-at_wini.cd-*-*'
X194c194
X<   register int i, old_state;
X---
X>   register int i/*, old_state*/;
X217,219c217,219
X< 		old_state = lock();
X< 		dma_read((unsigned)(usr_buf >> 4), (unsigned)(usr_buf & 0x0F));
X< 		restore(old_state);
X---
X> 		/*old_state = lock();*/
X> 		dma_read((unsigned)(usr_buf >> 4), (unsigned)(usr_buf & 0x0F));
X> 		/*restore(old_state);*/
X235,237c235,237
X< 		old_state = lock();
X< 		dma_write((unsigned)(usr_buf >> 4), (unsigned)(usr_buf&0x0F));
X< 		restore(old_state);
X---
X> 		/*old_state = lock();*/
X> 		dma_write((unsigned)(usr_buf >> 4), (unsigned)(usr_buf&0x0F));
X> 		/*restore(old_state);*/
*-*-END-of-at_wini.cd-*-*
echo x - printer.cd
sed 's/^X//' >printer.cd <<'*-*-END-of-printer.cd-*-*'
X139,140c139,141
X< 		}
X< 	}
X---
X>   		}
X>   	}
X>   restore(old_state);
*-*-END-of-printer.cd-*-*
echo x - table.cd
sed 's/^X//' >table.cd <<'*-*-END-of-table.cd-*-*'
X48,49c48,50
X< 
X< #define	TTY_STACK	SMALL_STACK
X---
X> #define LARGER_STACK	384
X> 
X> #define	TTY_STACK	LARGER_STACK
*-*-END-of-table.cd-*-*
echo x - xt_wini.cd
sed 's/^X//' >xt_wini.cd <<'*-*-END-of-xt_wini.cd-*-*'
X*** xt_wini.c.ORIG	Thu Jan  1 00:12:15 1970
X--- xt_wini.c	Thu Sep  1 06:02:15 1988
X***************
X*** 615,621 ****
X  	}
X  
X  
X! 	old_state = lock();
X  
X  	for (i=0; i<6; i++) {
X  		if(hd_wait(WST_REQ) != OK)
X--- 615,621 ----
X  	}
X  
X  
X! /*	old_state = lock(); */
X  
X  	for (i=0; i<6; i++) {
X  		if(hd_wait(WST_REQ) != OK)
X***************
X*** 630,636 ****
X  		port_out(WIN_DATA, command[i]);
X  	}
X  
X! 	restore(old_state);
X  
X  	if(i != 6) {
X  		return(ERR);
X--- 630,636 ----
X  		port_out(WIN_DATA, command[i]);
X  	}
X  
X! /*	restore(old_state); */
X  
X  	if(i != 6) {
X  		return(ERR);
*-*-END-of-xt_wini.cd-*-*
echo x - mpx88.asd
sed 's/^X//' >mpx88.asd <<'*-*-END-of-mpx88.asd-*-*'
X46,47c46,47
X< .globl _main, _sys_call, _interrupt, _keyboard, _panic, _unexpected_int, _trap
X< .globl _pr_char, _rs232, _dp8390_int
X---
X> .globl _main, _sys_call, _interrupt, _int_con, _panic, _unexpected_int, _trap
X> .globl _pr_char, _int_8250, _dp8390_int
X104c104
X< 	call _keyboard		; process a keyboard interrupt
X---
X> 	call _int_con		; process a keyboard interrupt
X111,115c111,115
X< _rs232_int:			; Interrupt routine for rs232 I/O.
X< 	call save		; save the machine state
X< 	mov ax,#1		; which unit caused the interrupt
X< 	push ax			; pass it as a parameter
X< 	call _rs232		; process a rs232 interrupt
X---
X> _rs232_int:			; Interrupt routine for rs232 port 1.
X> 	call save		; save the machine state
X> 	mov ax,#0		; which unit caused the interrupt
X> 	push ax			; pass it as a parameter
X> 	call _int_8250		; process a rs232 interrupt
X123,125c123,125
X< 	mov ax,#2		; which unit caused the interrupt
X<   	push ax			; pass it as a parameter
X<   	call _rs232		; process a rs232 interrupt
X---
X> 	mov ax,#1		; which unit caused the interrupt
X>   	push ax			; pass it as a parameter
X>   	call _int_8250		; process a rs232 interrupt
X304,305c304,306
X< 	mov ax,ret_save		; ax = address to return to
X< 	jmp ax			; return to caller; Note: sp points to saved ax
X---
X> 	cld			; all kernel copy loops are forward.
X>   	mov ax,ret_save		; ax = address to return to
X>   	jmp ax			; return to caller; Note: sp points to saved ax
*-*-END-of-mpx88.asd-*-*
echo x - klib88.as
sed 's/^X//' >klib88.as <<'*-*-END-of-klib88.as-*-*'
X; This file is significantly different in code to klib88.s. It does however
X; perform the same functions in the same way as the original klib88.
X; i.e. It is largly a translation with a few optimizations. Throughout the
X; file the word 'INT' in the comment means to comment out the entire line to
X; improve interrupt latency. The 'INT' will be followed by a class letter.
X; E.g. INTV indicates all video routine interrupts.
X
X; This file contains a number of assembly code utility routines needed by the
X; kernel.  They are:
X;
X;   phys_copy:	copies data from anywhere to anywhere in memory
X;   cp_mess:	copies messages from source to destination
X;   port_out:	outputs data on an I/O port
X;   port_in:	inputs data from an I/O port
X;   dma_read:	transfer data between HD controller and memory
X;   dma_write:	transfer data between memory and HD controller
X;   lock:	disable interrupts
X;   restore:	restore interrupts (enable/disabled) as they were before lock()
X;   build_sig:	build 4 word structure pushed onto stack for signals
X;   get_chrome:	returns 0 if display is monochrome, 1 if it is color
X;   scr_up:	scroll screen a line up (in software, by copying)
X;   scr_down:	scroll screen a line down (in software, by copying)
X;   vid_write:	write data to video ram (on color display during retrace only)
X;   vid_fill:	fill a section of video ram with a char (and attribute)
X;   vid_fmove:  move a section of video ram around (using forward copies)
X;   vid_bmove:  move a section of video ram around (using backward copies)
X;   get_byte:	reads a byte from a user program and returns it as value
X;   put_byte:	writes a byte to a user program
X;   reboot:	reboot for CTRL-ALT-DEL
X;   wreboot:	wait for character then reboot 
X;   em_xfer:	read or write AT extended memory using the BIOS
X
X; The following procedures are defined in this file and called from outside it.
X.globl _phys_copy, _cp_mess, _port_out, _port_in, _lock, _restore, _em_xfer
X.globl _build_sig, _get_chrome, _vid_write, _vid_fill, _vid_fmove, _vid_bmove
X.globl _get_byte, _put_byte, _reboot, _wreboot, _dma_read, _dma_write
X
X; The following external procedure is called in this file.
X.globl _panic, _eth_stp
X
X; Variables and data structures
X.globl _cur_proc, _proc_ptr, _vec_table
X.globl _color, _vid_mask, _vid_retrace, _vid_base
X
X.psect _TEXT
X
X;*===========================================================================*
X;*				phys_copy				     *
X;*===========================================================================*
X; This routine copies a block of physical memory.  It is called by:
X;    phys_copy( (long) source, (long) destination, (long) bytecount)
X;	interrupts are unchanged.
X
X_phys_copy:
X	push bp
X	mov bp,sp		; set bp to point to parameters
X	push si			; save si
X	push di			; save di
X	push ds			; save ds
X
X;	pushf			; INTC save flags
X;	cli			; INTC no interrupts
X;	cld			; INTC ensure this is the correct copy dir
X
X  L0:	mov ax,10[bp]		; ax = high-order word of 32-bit destination
X	mov di,8[bp]		; di = low-order word of 32-bit destination
X	mov cx,#4		; start extracting click number from dest
X  L1:	rcr ax,#1		; click number is destination address / 16
X	rcr di,#1		; it is used in segment register for copy
X	loop L1			; 4 bits of high-order word are used
X	mov es,di		; es = destination click
X
X	mov ax,6[bp]		; ax = high-order word of 32-bit source
X	mov si,4[bp]		; si = low-order word of 32-bit source
X	mov cx,#4		; start extracting click number from source
X  L2:	rcr ax,#1		; click number is source address / 16
X	rcr si,#1		; it is used in segment register for copy
X	loop L2			; 4 bits of high-order word are used
X	mov ds,si		; ds = source click
X
X	mov di,8[bp]		; di = low-order word of dest address
X	and di,#000Fh		; di = offset from paragraph # in es
X	mov si,4[bp]		; si = low-order word of source address
X	and si,#000Fh		; si = offset from paragraph # in ds
X
X	mov dx,14[bp]		; dx = high-order word of byte count
X	mov cx,12[bp]		; cx = low-order word of byte count
X
X	test cx,#8000h		; if bytes >= 32768, only do 32768 
X	jnz L3			; per iteration
X	test dx,#0FFFFh		; check high-order 17 bits to see if bytes
X	jz	L4		; if bytes < 32768 then go to L4
X  L3:	mov cx,#8000h		; 0x8000 is unsigned 32768
X  L4:	mov ax,cx		; save actual count used in ax; needed later
X
X	test cx,#1		; should we copy a byte or a word at a time?
X	jz L5			; jump if even
X	rep	movs byte	; copy 1 byte at a time
X	jmp L6			; check for more bytes
X
X  L5:	shr cx,#1		; word copy
X	rep	movs word	; copy 1 word at a time
X
X  L6:	mov dx,14[bp]		; decr count, incr src & dst, iterate if needed
X	mov cx,12[bp]		; dx || cx is 32-bit byte count
X	xor bx,bx		; bx || ax is 32-bit actual count used
X	sub cx,ax		; compute bytes - actual count
X	sbb dx,bx		; dx || cx is # bytes not yet processed
X	or cx,cx		; see if it is 0
X	jnz L7			; if more bytes then go to L7
X	or dx,dx		; keep testing
X	jnz L7			; if loop done, fall through
X
X;	popf			; INTC restore flags
X	pop ds			; restore ds
X	pop di			; restore di
X	pop si			; restore si
X	pop bp			; restore bp
X	ret			; return to caller
X
XL7:	mov 14[bp],dx		; store decremented byte count back in mem
X	mov 12[bp],cx		; as a long
X	add 8[bp],ax		; increment destination
X	adc 10[bp],bx		; carry from low-order word
X	add 4[bp],ax		; increment source
X	adc 6[bp],bx		; carry from low-order word
X	jmp L0			; start next iteration
X
X
X;*===========================================================================*
X;*				cp_mess					     *
X;*===========================================================================*
X; This routine is makes a fast copy of a message from anywhere in the address
X; This routine makes a fast copy of a message from anywhere in the address
X; space to anywhere else.  It also copies the source address provided as a
X; parameter to the call into the first word of the destination message.
X; It is called by:
X;    cp_mess(src, src_clicks, src_offset, dst_clicks, dst_offset)
X; where all 5 parameters are shorts (16-bits).
X;
X; Note that the message size, 'Msize' is in WORDS (not bytes) and must be set
X; correctly.  Changing the definition of message in type file and not changing
X; it here will lead to total disaster.
X
XMsize	equ	12		; size of a message in 16-bit words
X_cp_mess:
X	mov bx,sp		; index off bp because machine can't use sp
X	push ds			; save ds
X	push si			; save si
X	push di			; save di
X
X	mov ax,2[bx]		; ax = process number of sender
X	mov di,10[bx]		; di = offset of destination buffer
X	mov es,8[bx]		; es = clicks of destination
X	mov si,6[bx]		; si = offset of source message
X	mov ds,4[bx]		; ds = clicks of source message
X	mov cx,#Msize-1		; remember, first word doesn't count
X
X;	pushf			; INTM so we know what to restore later
X;	cli			; INTM disable interrupts
X;	cld			; INTM clear direction flag
X
X  	stos word		; copy sender's process number to dest message
X	add si,#2		; don't copy first word
X	rep movs word		; iterate cx times to copy 11 words
X
X;	popf			; INTM restore the interupt condition
X	pop di			; restore di
X	pop si			; restore si
X	pop ds			; restore ds
X	ret			; that's all folks!
X
X
X;*===========================================================================*
X;*				port_out				     *
X;*===========================================================================*
X; port_out(port, value) writes 'value' on the I/O port 'port'.
X
X_port_out:
X	mov bx,sp		; index off bx
X	mov dx,2[bx]		; dx = port
X	mov ax,4[bx]		; ax = value
X	out [dx],al		; output 1 byte
X	ret			; return to caller
X
X
X;*===========================================================================*
X;*				port_in					     *
X;*===========================================================================*
X; port_in(port, &value) reads from port 'port' and puts the result in 'value'.
X_port_in:
X	mov bx,sp		; index off bx
X	mov dx,2[bx]		; dx = port
X	in al,[dx]		; input 1 byte
X	xor ah,ah		; clear ah
X	mov bx,4[bx]		; fetch address where byte is to go
X	mov [bx],ax		; return byte to caller in param
X	ret			; return to caller
X
X
X;*===========================================================================*
X;*				dma_read				     *
X;*===========================================================================*
X_dma_read:
X	mov	bx,sp
X	push	di
X	mov	cx,#256		; transfer 256 words
X	mov	dx,#1F0H	; from/to port 1f0
X	mov	es,2[bx]	; segment in es
X	mov	di,4[bx]	; offset in di
X	.byte	0F3H, 6DH	; opcode for 'rep ins word'
X	pop	di
X	ret
X
X;*===========================================================================*
X;*				dma_write				     *
X;*===========================================================================*
X_dma_write:
X	mov	bx,sp
X	push	si
X	push	ds
X 	mov	cx,#256		; transfer 256 words
X	mov	dx,#1F0H	; from/to port 1f0
X	mov	si,4[bx]	; offset in si
X	mov	ds,2[bx]	; segment in ds
X	.byte	0F3H, 6FH	; opcode for 'rep outs word'
X	pop	ds
X	pop	si
X	ret
X
X;*===========================================================================*
X;*				lock					     *
X;*===========================================================================*
X; Disable CPU interrupts.  Return old psw as function value.
X_lock:  
X	pushf			; save flags on stack
X	cli			; disable interrupts
X	pop ax	 		; return flags for restoration later
X	ret			; return to caller
X
X;*===========================================================================*
X;*				restore					     *
X;*===========================================================================*
X; restore enable/disable bit to the value it had before last lock.
X_restore:
X	mov bx,sp		; set up base for indexing
X	push 2[bx]		; bp is the psw to be restored
X	popf			; restore flags
X	ret			; return to caller
X
X
X;*===========================================================================*
X;*				build_sig				     *
X;*===========================================================================*
X;* Build a structure that is pushed onto the stack for signals.  It contains
X;* pc, psw, etc., and is machine dependent. The format is the same as generated
X;* by hardware interrupts, except that after the "interrupt", the signal number
X;* is also pushed.  The signal processing routine within the user space first
X;* pops the signal number, to see which function to call.  Then it calls the
X;* function.  Finally, when the function returns to the low-level signal
X;* handling routine, control is passed back to where it was prior to the signal
X;* by executing a return-from-interrupt instruction, hence the need for using
X;* the hardware generated interrupt format on the stack.  The call is:
X;*     build_sig(sig_stuff, rp, sig)
X
X; Offsets within proc table
XPC	equ	24
Xcsreg	equ	18
XPSW	equ	28
X
X_build_sig:
X	mov bx,sp		; set bp to sp for accessing params
X	push si			; save si
X	mov ax,6[bx]		; ax = signal number
X	mov si,4[bx]		; si points to proc table entry
X	mov bx,2[bx]		; bx points to sig_stuff
X	mov [bx],ax		; put signal number in sig_stuff
X	mov ax,PC[si]		; ax = signalled process' PC
X	mov 2[bx],ax		; put pc in sig_stuff
X	mov ax,csreg[si]	; ax = signalled process' cs
X	mov 4[bx],ax		; put cs in sig_stuff
X	mov ax,PSW[si]		; ax = signalled process' PSW
X	mov 6[bx],ax		; put psw in sig_stuff
X	pop si			; restore si
X	ret			; return to caller
X
X;*===========================================================================*
X;*				get_chrome				     *
X;*===========================================================================*
X; This routine calls the BIOS to find out if the display is monochrome or 
X; color.  The drivers are different, as are the video ram addresses, so we
X; need to know. An EGA card is a 'color' for printer ports but may display
X; in mono or color. A test on the result returns ...
X;	if (get_chrome()) ...	- true if color or ega card (e.g. for printer
X;					port)
X;	if (get_chrome()&1) ... - true if color mode, false if mono mode
X;	if (get_chrome()&2) ... - true iff ega card
X_get_chrome:
X	mov	tmp,#0,byte	; clear previous (if any) modes
X	mov	bl,#10H		; test if EGA
X	mov	ah,#12H
X	int	#10H
X	cmp	bl,#10H
X	jz	1f		; if EGA then
X	mov	tmp,#2,byte	;	mark as EGA
X1:	int #11h		; test for color/mono
X	and al,#30h		; isolate color/mono field
X	cmp al,#30h
X	mov	al,tmp		; if monochrome then
X	je	2f		;	return
X	or	al,#1		; mark as color
X2:	xor	ah,ah		; return as word
X	ret
X
X
X;*===========================================================================*
X;*			video routines	(PUBLIC)			     *
X;*===========================================================================*
X; This routines handle writes to the screen. For a color display, the writing
X; only takes places during the vertical retrace interval, to avoid displaying
X; garbage on the screen. It will only display a maximum of vid_retrace words
X; in a single refresh cycle for the same reason. The display ram overflow is
X; handled carefully so that EGA cards work properly. These routines rely on
X; the stack segment being equal to the data segment.
X;
X; The calls are:
X;     vid_write(buffer, dest, words)
X;     vid_fill(fillw, dest, words)
X;     vid_fmove(src, dest, words)
X;     vid_bmove(src, dest, words)
X; where
X;     'buffer'	is a pointer to the (character, attribute) pairs
X;     'fillw'	is the word (character, attribute) for filling
X;     'src'	tells where within video ram to copy data from
X;     'dest'	tells where within video ram to copy the data
X;     'words'	tells how many words to copy
X
X_vid_write:		; let vidtransfer handle dest overflow
X	push	bp		; set up stack frame
X	mov	bp,sp
X	push	si		; save the registers
X	push	di
X	mov	es,_vid_base	; screen seg register
X	call	vidtransfer	; do the transfer
X	pop	di		; finished - clear stack frame
X	pop	si
X	pop	bp
X	ret
X
X_vid_fill:		; handle dest overflow explicitly
X	push	bp		; set up stack frame
X	mov	bp,sp
X	push	di		; save the registers
X	mov	es,_vid_base	; screen seg register
X	mov	ax,4[bp]	; get the fill char
X	mov	di,6[bp]	; get the dest
X	call	lvidfill	; do the initial fill
X	call	vidcheck	; check if overflow has occurred
X	jz	1f
X	call	lvidfill	; fix overflow
X1:	pop	di		; finished - clear stack frame
X	pop	bp
X	ret
X
X_vid_fmove:		; handle src overflow explicitly
X			; let vidtransfer handle dest overflow
X	push	bp		; set up stack frame
X	mov	bp,sp
X	push	si		; save the registers
X	push	di
X	push	ds
X	mov	ax,4[bp]	; src &= vid_mask
X	and	ax,_vid_mask
X	mov	4[bp],ax
X	add	ax,8[bp]	; if (src + words*2 > vid_mask)
X	add	ax,8[bp]	;	we have src overflow.
X	cmp	ax,_vid_mask
X	mov	es,_vid_base	; set up segment registers
X	mov	ds,_vid_base
X	jle	2f		; if src overflow then
X	push	8[bp]		; save the words count
X	mov	bx,ss:_vid_mask	; count = MIN(count, ((vid_mask+1)-src)/2)
X	inc	bx
X	sub	bx,4[bp]
X	shr	bx,#1
X	cmp	bx,8[bp]
X	jle	1f
X	mov	bx,8[bp]
X1:	mov	8[bp],bx	; bx and count now has count to do
X	call	vidtransfer	; do this first transfer
X	mov	4[bp],#0,word	; set up for remaining transfer
X	mov	6[bp],di
X	pop	8[bp]		; restore our original count
X	sub	8[bp],bx	; subtract the count done so far
X	jz	3f		; only continue if more to do
X2:	call	vidtransfer	; do the transfer for no src overflow
X3:	pop	ds		; finished - clear stack frame
X	pop	di
X	pop	si
X	pop	bp
X	ret
X
X_vid_bmove:		; handle src overflow explicitly
X			; let rvidtransfer handle dest overflow
X	push	bp		; set up stack frame
X	mov	bp,sp
X	push	si		; save the registers
X	push	di
X	push	ds
X	pushf
X	std			; transfer in reverse direction
X	mov	bx,4[bp]	; src &= vid_mask
X	and	bx,_vid_mask
X	mov	4[bp],bx
X	mov	es,_vid_base	; set up segment registers
X	mov	ds,_vid_base
X	push	8[bp]		; save the total count
X	shr	bx,#1		; count = MIN(count, src/2 + 1)
X	inc	bx
X	cmp	bx,8[bp]
X	jle	1f
X	mov	bx,8[bp]	; also save count in bx
X1:	mov	8[bp],bx
X	call	vidrtransfer	; do the transfer of non overflowing section
X	mov	ax,ss:_vid_mask	; set up to do overflow of src
X	dec	ax		; convert to word address
X	mov	4[bp],ax	; new src addr
X	pop	8[bp]		; calculate count left
X	sub	8[bp],bx
X	jz	2f		; if none to do don't continue
X	call	vidrtransfer	; transfer overflow
X2:	popf			; finished - clear stack frame
X	pop	ds
X	pop	di
X	pop	si
X	pop	bp
X	ret
X
X;*===========================================================================*
X;*			video routines	(private)			     *
X;*===========================================================================*
X; The following video support routines may be changed in thier interrupt
X; handling methods. If a glitch due to an interrupt during screen writes
X; is acceptable then comment out all lines with 'INTV' in thier comment.
X; Doing this improves interrupt latency (e.g. for RS232 throughput). In
X; practice I have never seen any glitches with the interrupts on.
X
Xvidtransfer:		; transfer a block to the screen (forward dir)
X			; handle dest overflow
X			; final results returned in si, di
X	mov	si,4[bp]	; si = pointer to data to be copied
X	mov	di,6[bp]	; di = offset within video ram
X	call	lvidcopy	; write the block to the screen
X	call	vidcheck	; check for video ram (window) overflow
X	jz	1f
X	sub	si,8[bp]	; overflow - find buffer position
X	sub	si,8[bp]
X	call	lvidcopy	; fix up overflow
X1:	ret
X
Xvidrtransfer:		; transfer a block to the screen (reverse dir)
X			; handle dest overflow
X			; final results in stack frame
X	mov	si,4[bp]	; si = pointer to data to be copied
X	mov	di,6[bp]	; di = offset within video ram
X	call	lvidcopy	; write the block to the screen
X	call	vidrcheck	; check for video ram (window) overflow
X	xchg	si,4[bp]	; get orig src & dest , save final src dest
X	xchg	di,6[bp]
X	jz	1f
X	and	di,ss:_vid_mask	; address the overflow block
X	call	lvidcopy	; write the overflow block
X1:	ret
X
Xlvidcopy:		; Transfer a block to the screen in sub-blocks
X			; with a maximum of vid_retrace words per sub-block.
X	mov	cx,ss:_vid_retrace	; cx = MIN(count, vid_retrace)
X	cmp	cx,8[bp]
X	jle	1f
X	mov	cx,8[bp]
X1:	jcxz	2f		; only do transfer if cx != 0
X	sub	8[bp],cx	; count -= cx
X	call	vidcopy
X	jmp	lvidcopy	; get the next sub-block
X2:	ret
X
Xlvidfill:		; Fill a block on the screen in sub-blocks
X			; with a maximum of vid_retrace words per sub-block.
X	mov	cx,ss:_vid_retrace	; cx = MIN(count, vid_retrace)
X	cmp	cx,8[bp]
X	jle	1f
X	mov	cx,8[bp]
X1:	jcxz	2f		; only do transfer if cx != 0
X	sub	8[bp],cx	; count -= cx
X	call	vidfill
X	jmp	lvidfill	; get the next sub-block
X2:	ret
X
Xvidcopy:		; Transfer a sub-block to the screen waiting for
X			; retrace if necessary.
X	call	vidwait		; wait for retrace if necessary
X	rep	movs word	; transfer the block
X;	push	ax		; INTV restore the flags
X;	popf			; INTV
X	ret
X
Xvidfill:		; Fill a sub-block on the screen waiting for
X			; retrace if necessary.
X	push	ax		; save the fill char
X	call	vidwait		; wait for retrace if necessary
X;	mov	dx,ax		; INTV save the flags
X	pop	ax		; restore the fill char
X	rep	stos word	; do the fill
X;	push	dx		; INTV restore the flags
X;	popf			; INTV
X	ret
X
Xvidwait:		; Wait for retrace only if necessary
X	test	ss:_color,#1,byte	; mono's don't need retrace checking
X	jz	2f
X	test	ss:_color,#2,byte	; ega's don't need retrace checking
X	jnz	2f
X	mov	dx,#3DAH	; port for retrace status
X;	pushf			; INTV
X1:
X;	sti			; INTV ensure interrupts can have a go
X;	nop			; INTV
X;	nop			; INTV
X;	cli			; INTV
X	in	al,[dx]		; wait for retrace on
X	test	al,#8
X	jz	1b
X;	pop	ax		; INTV return the flags in ax (ints off)
X2:	ret
X
Xvidcheck:		; Check if the forward transfer just completed
X			; requires overflow fixing on dest. If so set up
X			; di and count.  count = 0 on entry
X	mov	dx,di		; dx = final dest
X	sub	dx,ss:_vid_mask	; see if overflowed
X	sub	dx,#1		;	must do sub as dec doesn't set flag
X	jle	2f		; if so dx = overflow count
X	sub	di,6[bp]	; count = MIN(dx, final dest - init dest)
X	cmp	di,dx
X	jle	1f
X	mov	di,dx
X1:	mov	8[bp],di	; save the new count
X	sub	dx,di		; new dest = overflow count - new count
X	mov	di,dx
X2:	shr	8[bp],#1,word	; turn byte count to word count & test
X	ret			;	if any work done.
X
Xvidrcheck:		; Check if the backward transfer just completed
X			; requires overflow fixing on dest. If so set up
X			; count.  count = 0 on entry
X	mov	dx,6[bp]	; dx = final dest
X	sub	dx,ss:_vid_mask	; see if overflowed
X	sub	dx,#1		;	must do sub as dec doesn't set flag
X	jle	2f		; if so dx = overflow count
X	mov	ax,6[bp]	; count = MIN(dx, final dest - init dest)
X	sub	ax,di
X	cmp	ax,dx
X	jle	1f
X	mov	ax,dx
X1:	mov	8[bp],ax	; save the new count
X2:	shr	8[bp],#1,word	; turn byte count to word count & test
X	ret			;	if any work done.
X
X;*===========================================================================*
X;*				get_byte				     *
X;*===========================================================================*
X; This routine is used to fetch a byte from anywhere in memory.
X; The call is:
X;     c = get_byte(seg, off)
X; where
X;     'seg' is the value to put in es
X;     'off' is the offset from the es value
X_get_byte:
X	mov bx,sp		; we need to access parameters
X	mov es,2[bx]		; load es with segment value
X	mov bx,4[bx]		; load bx with offset from segment
X				; go get the byte
X	mov al,es:[bx]		; al = byte
X	xor ah,ah		; ax = byte
X	ret			; return to caller
X
X
X;*===========================================================================*
X;*				put_byte				     *
X;*===========================================================================*
X; This routine is used to put a byte anywhere in memory.
X; The call is:
X;     retval = put_byte(seg, off, val)
X; where
X;     'seg' is the value to put in es
X;     'off' is the offset from the es value
X;     'val' is value to put in memory
X;     'retval' = val & 0xFF
X_put_byte:
X	mov bx,sp		; we need to access parameters
X	mov al,6[bx]		; load al with value
X	mov es,2[bx]		; load es with segment value
X	mov bx,4[bx]		; load bx with offset from segment
X	mov es:[bx],al		; put the byte
X	xor ah,ah		; ax = byte
X	ret			; return to caller
X
X;*===========================================================================*
X;*				reboot & wreboot			     *
X;*===========================================================================*
X; This code reboots the PC
X
X_reboot:
X	cli			; disable interrupts
X	mov ax,#20h		; re-enable interrupt controller
X	out 20h,al
X 	call _eth_stp		; stop the ethernet chip
X	call resvec		; restore the vectors in low core
X	jmp doboot		; reboot the PC
X
X_wreboot:
X	cli			; disable interrupts
X	mov ax,#20h		; re-enable interrupt controller
X	out 20h,al
X	call _eth_stp		; stop the ethernet chip
X	call resvec		; restore the vectors in low core
X	xor ax,ax		; wait for character before continuing
X	int #16h		; get char
X	jmp doboot		; reboot the PC
X
X; Restore the interrupt vectors in low core.
Xresvec:	cld
X	mov cx,#2*71
X	mov si,#_vec_table
X	xor di,di
X	mov es,di
X	rep	movs	word
X	ret
X
X; Replaces int #19h
Xdoboot:
X	mov	ax,#40h
X	mov	ds,ax
X	mov	ax,#1234h
X	mov	72h,ax
X	mov	ax,#0FFFFh
X	mov	ds,ax
X	mov	ax,3
X	push	ax
X	mov	ax,1
X	push	ax
X	iret
X
X; Some library routines use exit, so this label is needed.
X; Actual calls to exit cannot occur in the kernel.
X.globl _exit
X_exit:	sti
X	jmp _exit
X
X;===========================================================================
X;                		em_xfer
X;===========================================================================
X;
X;  This file contains one routine which transfers words between user memory
X;  and extended memory on an AT or clone.  A BIOS call (INT 15h, Func 87h)
X;  is used to accomplish the transfer.
X;
X;  This particular BIOS routine runs with interrupts off since the 80286
X;  must be placed in protected mode to access the memory above 1 Mbyte.
X;  So there should be no problems using the BIOS call.
X;
X	.psect _TEXT
Xgdt:				; Begin global descriptor table
X					; Dummy descriptor
X	.word 0		; segment length (limit)
X	.word 0		; bits 15-0 of physical address
X	.byte 0		; bits 23-16 of physical address
X	.byte 0		; access rights byte
X	.word 0		; reserved
X					; descriptor for GDT itself
X	.word 0		; segment length (limit)
X	.word 0		; bits 15-0 of physical address
X	.byte 0		; bits 23-16 of physical address
X	.byte 0		; access rights byte
X	.word 0		; reserved
Xsrc:					; source descriptor
Xsrcsz:	.word 0		; segment length (limit)
Xsrcl:	.word 0		; bits 15-0 of physical address
Xsrch:	.byte 0		; bits 23-16 of physical address
X	.byte 93H	; access rights byte
X	.word 0		; reserved
Xtgt:					; target descriptor
Xtgtsz:	.word 0		; segment length (limit)
Xtgtl:	.word 0		; bits 15-0 of physical address
Xtgth:	.byte 0		; bits 23-16 of physical address
X	.byte 93H	; access rights byte
X	.word 0		; reserved
X					; BIOS CS descriptor
X	.word 0		; segment length (limit)
X	.word 0		; bits 15-0 of physical address
X	.byte 0		; bits 23-16 of physical address
X	.byte 0		; access rights byte
X	.word 0		; reserved
X					; stack segment descriptor
X	.word 0		; segment length (limit)
X	.word 0		; bits 15-0 of physical address
X	.byte 0		; bits 23-16 of physical address
X	.byte 0		; access rights byte
X	.word 0		; reserved
X;
X;
X;  Execute a transfer between user memory and extended memory.
X;
X;  status = em_xfer(source, dest, count);
X;
X;    Where:
X;       status => return code (0 => OK)
X;       source => Physical source address (32-bit)
X;       dest   => Physical destination address (32-bit)
X;       count  => Number of words to transfer
X;
X;
X;
X_em_xfer:
X	push	bp		; Save registers
X	mov	bp,sp
X	push	si
X	push	es
X;
X;  Pick up source and destination addresses and update descriptor tables
X;
X	mov ax,4[bp]
X	mov cs:srcl,ax
X	mov ax,6[bp]
X	mov cs:srch,al
X	mov ax,8[bp]
X	mov cs:tgtl,ax
X	mov ax,10[bp]
X	mov cs:tgth,al
X;
X;  Update descriptor table segment limits
X;
X	mov cx,12[bp]
X	mov ax,cx
X	add ax,ax
X	mov cs:tgtsz,ax
X	mov cs:srcsz,ax
X;
X;  Now do actual DOS call
X;
X	push cs
X	pop es
X	mov si,#gdt
X	mov ah,#87H
X				; Hopefully this will work instead of ...
X	int #15H		; Do a far call to BIOS routine
X;
X;  All done, return to caller.
X;
X	pop	es		; restore registers
X	pop	si
X	mov	sp,bp
X	pop	bp
X	ret
X
X	.psect data
Xvidlock:	.word 0		; dummy variable for use with lock prefix
Xtmp:		.word 0		; count of bytes already copied
X_vec_table:	.blkb 284	; storage for interrupt vectors
X
X	.psect _TEXT
*-*-END-of-klib88.as-*-*
exit

pa1293@sdcc15.ucsd.edu (pa1293) (11/10/88)

I have tried to install Andrew Hannam's tty handler routines but I 
am confronted with the problem that the assembly routines are
written in some other unix assembler code and I don't know what the
differences are between MINIX asld and the ??UNIX?? as used by
Andrew Hannam.  Also, I am not sure if the assembly files would 
be portable with the MINIX cc even if I were to do a simple
conversion of the mnemonics.  

Could anybody who has converted the tty driver to MINIX-compileable
code please post the diffs or the files.

Is this tty driver relative to v1.3a v1.3b or v1.3c?

Thanks.

Mail to / flame:
pa1293@iugrad2.ucsd.edu
~!nosc!ucsd!iugrad2!pa1293
or try: ~!nosc!ucsd!sdcc15!pa1293