echo x - Makefile.ansi
sed '/^X/s///' > Makefile.ansi << '/'
X# Makefile for kernel using standard Minix directory layout and compiler.
X# CPP may need changing to /usr/lib/cpp.
X# The following nonstandard flags are used:
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
X# Set O=o for ANSI compiler, or O=s for K&R compiler.
XO=o
X#O=s
X
X#Set b=/usr for /usr/include or b=<null string> for /include.
X#b=/usr
Xb=
X
X# Directories
Xi=$b/include
Xs=$i/sys
Xh=$i/minix
Xl=$b/lib
X
X# Programs, flags, and libraries
XBIN		=.
XCC		=exec cc
XCPP		=$l/cpp -DASLD
X#CPP		=$l/ncpp -DASLD
XLD		=$l/ld
XEND		=$l/end.A
XCPPFLAGS	=-P -I$i
XCFLAGS		=-m -I$i
XLDFLAGS		=-i
XLIB=$l/libc.A $l/libe.A
XSTART		=mpx.$O
X
Xa		=kernel.h $h/config.h $h/const.h $h/type.h \
X		 $s/types.h $i/limits.h $i/errno.h \
X		 const.h type.h proto.h glo.h
Xh		=$b/include/minix
Xi		=$b/include
Xs		=$b/include/sys
X
XKEROBJS		=start.$O protect.$O klib.$O wini.$O \
X	table.$O main.$O tty.$O floppy.$O system.$O proc.$O \
X	clock.$O memory.$O console.$O rs232.$O rs2.$O printer.$O \
X	dmp.$O exception.$O i8259.$O misc.$O keyboard.$O
XSOBJS		=klib.$O mpx.$O rs2.$O
X
X# Rules.
X.SUFFIXES: .x		# .x files are .$O files which need C-preprocessing
X.x.$O:
X	$(CPP) $(CPPFLAGS) $< >tmp;  as <tmp -o $@
X
X# What to make.
Xdummy: $(BIN)/kernel	# this line fixes a bug in RAL's latest make
X
X$(BIN)/kernel: $(START) $(KEROBJS) $(LIB) $(END)
X	$(LD) $(LDFLAGS) -o $(BIN)/tmp \
X	$(START) $(KEROBJS) \
X	$(LIB) $(END)
X	$l/cv $(BIN)/tmp >kernel
X	@rm -f tmp
X
Xclean:
X	@rm -f *.s *.o *.bak kernel
X
Xklib.$O: $h/config.h $h/const.h const.h protect.h sconst.h klib.x
Xmpx.$O: $h/config.h $h/const.h $h/com.h const.h protect.h sconst.h mpx.x
Xrs2.$O: $h/config.h $h/const.h const.h sconst.h rs2.x
X
Xclock.$O:	$a
Xclock.$O:	$i/signal.h
Xclock.$O:	$h/callnr.h
Xclock.$O:	$h/com.h
Xclock.$O:	proc.h
X
Xconsole.$O:	$a
Xconsole.$O:	$i/sgtty.h
Xconsole.$O:	$h/callnr.h
Xconsole.$O:	$h/com.h
Xconsole.$O:	protect.h
Xconsole.$O:	tty.h
X
Xstart.$O:	$a
Xstart.$O:	$i/string.h
Xstart.$O:	$h/boot.h
Xstart.$O:	protect.h
Xstart.$O:	start.c
X
Xdmp.$O:		$a
Xdmp.$O:		$h/com.h
Xdmp.$O:		proc.h
Xdmp.$O:		tty.h
X
Xexception.$O:	$a
Xexception.$O:	$i/signal.h
Xexception.$O:	proc.h
X
Xfloppy.$O:	$a
Xfloppy.$O:	$h/callnr.h
Xfloppy.$O:	$h/com.h
Xfloppy.$O:	$h/diskparm.h
X
Xi8259.$O:	$a
X
Xkeyboard.$O:	$a
Xkeyboard.$O:	$i/sgtty.h
Xkeyboard.$O:	$i/signal.h
Xkeyboard.$O:	$h/callnr.h
Xkeyboard.$O:	$h/com.h
Xkeyboard.$O:	tty.h
X
Xmain.$O:	$a
Xmain.$O:	$i/signal.h
Xmain.$O:	$h/callnr.h
Xmain.$O:	$h/com.h
Xmain.$O:	proc.h
X
Xmemory.$O:	$a
Xmemory.$O:	$h/callnr.h
Xmemory.$O:	$h/com.h
X
Xmisc.$O:	$a
Xmisc.$O:	$h/com.h
X
Xprinter.$O:	$a
Xprinter.$O:	$h/callnr.h
Xprinter.$O:	$h/com.h
X
Xproc.$O:	$a
Xproc.$O:	$h/callnr.h
Xproc.$O:	$h/com.h
Xproc.$O:	proc.h
X
Xprotect.$O:	$a
Xprotect.$O:	proc.h
Xprotect.$O:	protect.h
X
Xrs232.$O:	$a
Xrs232.$O:	$i/sgtty.h
Xrs232.$O:	tty.h
X
Xsystem.$O:	$a
Xsystem.$O:	$i/signal.h
Xsystem.$O:	$h/boot.h
Xsystem.$O:	$h/callnr.h
Xsystem.$O:	$h/com.h
Xsystem.$O:	proc.h
Xsystem.$O:	protect.h
Xsystem.$O:	$i/sys/sigcontext.h
X
Xtable.$O:	$a
Xtable.$O:	$h/com.h
Xtable.$O:	proc.h
Xtable.$O:	tty.h
X
Xtty.$O:		$a
Xtty.$O:		$i/sgtty.h
Xtty.$O:		$i/signal.h
Xtty.$O:		$h/callnr.h
Xtty.$O:		$h/com.h
Xtty.$O:		proc.h
Xtty.$O:		tty.h
X
Xwini.$O:	$a
Xwini.$O:	$h/callnr.h
Xwini.$O:	$h/com.h
Xwini.$O:	$h/partition.h
/
echo x - Makefile.kr
sed '/^X/s///' > Makefile.kr << '/'
X# Makefile for kernel using standard Minix directory layout and compiler.
X# CPP may need changing to /usr/lib/cpp.
X# The following nonstandard flags are used:
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
X# Set O=o for ANSI compiler, or O=s for K&R compiler.
X#O=o
XO=s
X
XBIN		=.
XCC		=cc
XCFLAGS		=-F -T.
XCPP		=/usr/lib/cpp
XCPPFLAGS	=-DASLD -P
XEND		=/usr/lib/end.$O
XLD		=asld
XLDFLAGS		=-i
XLIBS		=/usr/lib/libc.a
XSTART		=mpx.s
X
Xa		=kernel.h $h/config.h $h/const.h $h/type.h \
X		 $s/types.h $i/limits.h $i/errno.h \
X		 const.h type.h proto.h glo.h
Xh		=/usr/include/minix
Xi		=/usr/include
Xs		=/usr/include/sys
X
XKEROBJS		=start.$O protect.$O klib.$O wini.$O \
X	table.$O main.$O tty.$O floppy.$O system.$O proc.$O \
X	clock.$O memory.$O console.$O rs232.$O rs2.$O printer.$O \
X	dmp.$O exception.$O i8259.$O misc.$O keyboard.$O
XSOBJS		=start.$O klib.$O mpx.$O rs2.$O
X
X# Rules.
X.SUFFIXES: .x		# .x files are .$O files which need C-preprocessing
X.x.$O:
X	$(CPP) $(CPPFLAGS) $< >$@
X
X# What to make.
Xdummy: $(BIN)/kernel	# this line fixes a bug in RAL's latest make
X
X$(BIN)/kernel: $(START) $(KEROBJS) $(LIBS) $(END)
X	$(LD) $(LDFLAGS) -o $(BIN)/kernel \
X	$(START) $(KEROBJS) \
X	$(LIBS) $(END) -s > kernel.$Oym
X	ast -X $(BIN)/kernel kernel.$Oym
X	@rm kernel.$Oym
X
Xclean:
X	@rm -f *.s *.o *.bak kernel
X
Xklib.$O: $h/config.h $h/const.h const.h protect.h sconst.h klib.x
Xmpx.$O: $h/config.h $h/const.h $h/com.h const.h protect.h sconst.h mpx.x
Xrs2.$O: $h/config.h $h/const.h const.h sconst.h rs2.x
Xstart.$O: $h/config.h $h/const.h $h/com.h const.h protect.h sconst.h start.c
X
Xclock.$O:	$a
Xclock.$O:	$i/signal.h
Xclock.$O:	$h/callnr.h
Xclock.$O:	$h/com.h
Xclock.$O:	proc.h
X
Xconsole.$O:	$a
Xconsole.$O:	$i/sgtty.h
Xconsole.$O:	$h/callnr.h
Xconsole.$O:	$h/com.h
Xconsole.$O:	protect.h
Xconsole.$O:	tty.h
X
Xstart.$O:	$a
Xstart.$O:	$i/string.h
Xstart.$O:	$h/boot.h
Xstart.$O:	protect.h
Xstart.$O:	start.c
X
Xdmp.$O:		$a
Xdmp.$O:		$h/com.h
Xdmp.$O:		proc.h
Xdmp.$O:		tty.h
X
Xexception.$O:	$a
Xexception.$O:	$i/signal.h
Xexception.$O:	proc.h
X
Xfloppy.$O:	$a
Xfloppy.$O:	$h/callnr.h
Xfloppy.$O:	$h/com.h
Xfloppy.$O:	$h/diskparm.h
X
Xi8259.$O:	$a
X
Xkeyboard.$O:	$a
Xkeyboard.$O:	$i/sgtty.h
Xkeyboard.$O:	$i/signal.h
Xkeyboard.$O:	$h/callnr.h
Xkeyboard.$O:	$h/com.h
Xkeyboard.$O:	tty.h
X
Xmain.$O:	$a
Xmain.$O:	$i/signal.h
Xmain.$O:	$h/callnr.h
Xmain.$O:	$h/com.h
Xmain.$O:	proc.h
X
Xmemory.$O:	$a
Xmemory.$O:	$h/callnr.h
Xmemory.$O:	$h/com.h
X
Xmisc.$O:	$a
Xmisc.$O:	$h/com.h
X
Xprinter.$O:	$a
Xprinter.$O:	$h/callnr.h
Xprinter.$O:	$h/com.h
X
Xproc.$O:	$a
Xproc.$O:	$h/callnr.h
Xproc.$O:	$h/com.h
Xproc.$O:	proc.h
X
Xprotect.$O:	$a
Xprotect.$O:	proc.h
Xprotect.$O:	protect.h
X
Xrs232.$O:	$a
Xrs232.$O:	$i/sgtty.h
Xrs232.$O:	tty.h
X
Xsystem.$O:	$a
Xsystem.$O:	$i/signal.h
Xsystem.$O:	$h/boot.h
Xsystem.$O:	$h/callnr.h
Xsystem.$O:	$h/com.h
Xsystem.$O:	proc.h
Xsystem.$O:	protect.h
X
Xtable.$O:	$a
Xtable.$O:	$h/com.h
Xtable.$O:	proc.h
Xtable.$O:	tty.h
X
Xtty.$O:		$a
Xtty.$O:		$i/sgtty.h
Xtty.$O:		$i/signal.h
Xtty.$O:		$h/callnr.h
Xtty.$O:		$h/com.h
Xtty.$O:		tty.h
X
Xwini.$O:	$a
Xwini.$O:	$h/callnr.h
Xwini.$O:	$h/com.h
Xwini.$O:	$h/partition.h
X
X
/
echo x - dp8390.h
sed '/^X/s///' > dp8390.h << '/'
X/* National Semiconductor DP8390 Network Interface Controller. */
X
Xtypedef union dp8390reg {
X  struct pg0rd {		/* Page 0, for reading ------------- */
X	u8_t	dp_cr;		/* Read side of Command Register     */
X	u8_t	dp_clda0;	/* Current Local Dma Address 0       */
X	u8_t	dp_clda1;	/* Current Local Dma Address 1       */
X	u8_t	dp_bnry;	/* Boundary Pointer                  */
X	u8_t	dp_tsr;		/* Transmit Status Register          */
X	u8_t	dp_ncr;		/* Number of Collisions Register     */
X	u8_t	dp_fifo;	/* Fifo ??                           */
X	u8_t	dp_isr;		/* Interrupt Status Register         */
X	u8_t	dp_crda0;	/* Current Remote Dma Address 0      */
X	u8_t	dp_crda1;	/* Current Remote Dma Address 1      */
X	u8_t	dp_dum1;	/* unused                            */
X	u8_t	dp_dum2;	/* unused                            */
X	u8_t	dp_rsr;		/* Receive Status Register           */
X	u8_t	dp_cntr0;	/* Tally Counter 0                   */
X	u8_t	dp_cntr1;	/* Tally Counter 1                   */
X	u8_t	dp_cntr2;	/* Tally Counter 2                   */
X  } dp_pg0rd;
X
X  struct pg0wr {		/* Page 0, for writing ------------- */
X	u8_t	dp_cr;		/* Write side of Command Register    */
X	u8_t	dp_pstart;	/* Page Start Register               */
X	u8_t	dp_pstop;	/* Page Stop Register                */
X	u8_t	dp_bnry;	/* Boundary Pointer                  */
X	u8_t	dp_tpsr;	/* Transmit Page Start Register      */
X	u8_t	dp_tbcr0;	/* Transmit Byte Count Register 0    */
X	u8_t	dp_tbcr1;	/* Transmit Byte Count Register 1    */
X	u8_t	dp_isr;		/* Interrupt Status Register         */
X	u8_t	dp_rsar0;	/* Remote Start Address Register 0   */
X	u8_t	dp_rsar1;	/* Remote Start Address Register 1   */
X	u8_t	dp_rbcr0;	/* Remote Byte Count Register 0      */
X	u8_t	dp_rbcr1;	/* Remote Byte Count Register 1      */
X	u8_t	dp_rcr;		/* Receive Configuration Register    */
X	u8_t	dp_tcr;		/* Transmit Configuration Register   */
X	u8_t	dp_dcr;		/* Data Configuration Register       */
X	u8_t	dp_imr;		/* Interrupt Mask Register           */
X  } dp_pg0wr;
X 
X  struct pg1rdwr {		/* Page 1, read/write -------------- */
X	u8_t	dp_cr;		/* Command Register                  */
X	u8_t	dp_par0;	/* Physical Address Register 0       */
X	u8_t	dp_par1;	/* Physical Address Register 1       */
X	u8_t	dp_par2;	/* Physical Address Register 2       */
X	u8_t	dp_par3;	/* Physical Address Register 3       */
X	u8_t	dp_par4;	/* Physical Address Register 4       */
X	u8_t	dp_par5;	/* Physical Address Register 5       */
X	u8_t	dp_curr;	/* Current Page Register             */
X	u8_t	dp_mar0;	/* Multicast Address Register 0      */
X	u8_t	dp_mar1;	/* Multicast Address Register 1      */
X	u8_t	dp_mar2;	/* Multicast Address Register 2      */
X	u8_t	dp_mar3;	/* Multicast Address Register 3      */
X	u8_t	dp_mar4;	/* Multicast Address Register 4      */
X	u8_t	dp_mar5;	/* Multicast Address Register 5      */
X	u8_t	dp_mar6;	/* Multicast Address Register 6      */
X	u8_t	dp_mar7;	/* Multicast Address Register 7      */
X  } dp_pg1rdwr;
X} dp8390;
X
X/* Bits in dp_cr */
X#define CR_STP		0x01	/* Stop: software reset              */
X#define CR_STA		0x02	/* Start: activate NIC               */
X#define CR_TXP		0x04	/* Transmit Packet                   */
X#define CR_DMA		0x38	/* Mask for DMA control              */
X#define CR_DM_NOP	0x00	/* DMA: No Operation                 */
X#define CR_DM_RR	0x08	/* DMA: Remote Read                  */
X#define CR_DM_RW	0x10	/* DMA: Remote Write                 */
X#define CR_DM_SP	0x18	/* DMA: Send Packet                  */
X#define CR_DM_ABORT	0x20	/* DMA: Abort Remote DMA Operation   */
X#define CR_PS		0xC0	/* Mask for Page Select              */
X#define CR_PS_P0	0x00	/* Register Page 0                   */
X#define CR_PS_P1	0x40	/* Register Page 1                   */
X#define CR_PS_T0	0x80	/* Test Mode Register Map ??         */
X#define CR_SP_T1	0xC0	/* Test Mode Register Map ??         */
X
X/* Bits in dp_isr */
X#define ISR_MASK	0x3F
X#define ISR_PRX		0x01	/* Packet Received with no errors    */
X#define ISR_PTX		0x02	/* Packet Transmitted with no errors */
X#define ISR_RXE		0x04	/* Receive Error                     */
X#define ISR_TXE		0x08	/* Transmit Error                    */
X#define ISR_OVW		0x10	/* Overwrite Warning                 */
X#define ISR_CNT		0x20	/* Counter Overflow                  */
X#define ISR_RDC		0x40	/* Remote DMA Complete               */
X#define ISR_RST		0x80	/* Reset Status                      */
X
X/* Bits in dp_imr */
X#define IMR_PRXE	0x01	/* Packet Received iEnable           */
X#define IMR_PTXE	0x02	/* Packet Transmitted iEnable        */
X#define IMR_RXEE	0x04	/* Receive Error iEnable             */
X#define IMR_TXEE	0x08	/* Transmit Error iEnable            */
X#define IMR_OVWE	0x10	/* Overwrite Warning iEnable         */
X#define IMR_CNTE	0x20	/* Counter Overflow iEnable          */
X#define IMR_RDCE	0x40	/* DMA Complete iEnable              */
X
X/* Bits in dp_dcr */
X#define DCR_WTS		0x01	/* Word Transfer Select              */
X#define DCR_BYTEWIDE	0x00	/* WTS: byte wide transfers          */
X#define DCR_WORDWIDE	0x01	/* WTS: word wide transfers          */
X#define DCR_BOS		0x02	/* Byte Order Select                 */
X#define DCR_LTLENDIAN	0x00	/* BOS: Little Endian                */
X#define DCR_BIGENDIAN	0x02	/* BOS: Big Endian                   */
X#define DCR_LAS		0x04	/* Long Address Select               */
X#define DCR_BMS		0x08	/* Burst Mode Select                 */
X#define DCR_AR		0x10	/* Autoinitialize Remote             */
X#define DCR_FTS		0x60	/* Fifo Threshold Select             */
X#define DCR_2BYTES	0x00	/* 2 bytes                           */
X#define DCR_4BYTES	0x40	/* 4 bytes                           */
X#define DCR_8BYTES	0x20	/* 8 bytes                           */
X#define DCR_12BYTES	0x60	/* 12 bytes                          */
X
X/* Bits in dp_tcr */
X#define TCR_CRC		0x01	/* Inhibit CRC                       */
X#define TCR_ELC		0x06	/* Encoded Loopback Control          */
X#define TCR_NORMAL	0x00	/* ELC: Normal Operation             */
X#define TCR_INTERNAL	0x02	/* ELC: Internal Loopback            */
X#define TCR_0EXTERNAL	0x04	/* ELC: External Loopback LPBK=0     */
X#define TCR_1EXTERNAL	0x06	/* ELC: External Loopback LPBK=1     */
X#define TCR_ATD		0x08	/* Auto Transmit                     */
X#define TCR_OFST	0x10	/* Collision Offset Enable (be nice) */
X
X/* Bits in dp_tsr */
X#define TSR_PTX		0x01	/* Packet Transmitted (without error)*/
X#define TSR_DFR		0x02	/* Transmit Deferred                 */
X#define TSR_COL		0x04	/* Transmit Collided                 */
X#define TSR_ABT		0x08	/* Transmit Aborted                  */
X#define TSR_CRS		0x10	/* Carrier Sense Lost                */
X#define TSR_FU		0x20	/* FIFO Underrun                     */
X#define TSR_CDH		0x40	/* CD Heartbeat                      */
X#define TSR_OWC		0x80	/* Out of Window Collision           */
X
X/* Bits in tp_rcr */
X#define RCR_SEP		0x01	/* Save Errored Packets              */
X#define RCR_AR		0x02	/* Accept Runt Packets               */
X#define RCR_AB		0x04	/* Accept Broadcast                  */
X#define RCR_AM		0x08	/* Accept Multicast                  */
X#define RCR_PRO		0x10	/* Physical Promiscuous              */
X#define RCR_MON		0x20	/* Monitor Mode                      */
X
X/* Bits in dp_rsr */
X#define RSR_PRX		0x01	/* Packet Received Intact            */
X#define RSR_CRC		0x02	/* CRC Error                         */
X#define RSR_FAE		0x04	/* Frame Alignment Error             */
X#define RSR_FO		0x08	/* FIFO Overrun                      */
X#define RSR_MPA		0x10	/* Missed Packet                     */
X#define RSR_PHY		0x20	/* Multicast Address Match !!        */
X#define RSR_DIS		0x40	/* Receiver Disabled                 */
X
X
Xtypedef struct rcvdheader {
X  u8_t rp_status;		/* Copy of rsr                       */
X  u8_t rp_next;			/* Pointer to next packet            */
X  u8_t rp_rbcl;			/* Receive Byte Count Low            */
X  u8_t rp_rbch;			/* Receive Byte Count High           */
X} rcvdheader_t;
/
echo x - epl.h
sed '/^X/s///' > epl.h << '/'
X/* Western Digital Ethercard Plus, or WD8003E card. */
X
Xstruct eplusreg {
X  char epl_ctlstatus;		/* Control(write) and status(read) */
X  char epl_res1[7];
X  char epl_ea0;			/* Most significant eaddr byte */
X  char epl_ea1;
X  char epl_ea2;
X  char epl_ea3;
X  char epl_ea4;
X  char epl_ea5;			/* Least significant eaddr byte */
X  char epl_res2;
X  char epl_chksum;		/* sum from epl_ea0 upto here is 0xFF */
X  dp8390 epl_dp8390;		/* NatSemi chip */
X};
X
X/* Bits in epl_ctlstatus */
X#define CTL_RESET	0x80		/* Software Reset */
X#define CTL_MENABLE	0x40		/* Memory Enable */
X#define CTL_MEMADDR	0x3F		/* Bits SA18-SA13, SA19 implicit 1 */
X#define STA_IIJ		0x07		/* Interrupt Indication Jumpers */
/
echo x - esdi_wini.c
sed '/^X/s///' > esdi_wini.c << '/'
X/*
X *     hard disk driver for ibm ps/2 esdi adapter
X *
X *     written by doug burks, based on other minix wini drivers.
X *     some additions by art roberts
X *     last changed:  22 Jan 1991
X *
X *     references:
X *        ibm personal system/2 hardware technical reference  (1988)
X *        ibm 60/120mb fixed disk drive technical reference  (1988)
X *
X *     caveats:
X *       * this driver has been reported to work on ibm ps/2 models 50 and
X *         70 with ibm's 60/120mb hard disks.
X *       * for a true esdi adapter, changes will have to be made, but this
X *         certainly serves as a good start.
X *       * no timeouts are implemented, so this driver could hang under
X *         adverse conditions.
X *       * the error processing has not been tested.  my disk works too well.
X *
X * The driver supports the following operations (using message format m2):
X *
X *    m_type      DEVICE    PROC_NR     COUNT    POSITION  ADRRESS
X * ----------------------------------------------------------------
X * |  DEV_OPEN  |         |         |         |         |         |
X * |------------+---------+---------+---------+---------+---------|
X * |  DEV_CLOSE |         |         |         |         |         |
X * |------------+---------+---------+---------+---------+---------|
X * |  DEV_READ  | device  | proc nr |  bytes  |  offset | buf ptr |
X * |------------+---------+---------+---------+---------+---------|
X * |  DEV_WRITE | device  | proc nr |  bytes  |  offset | buf ptr |
X * ----------------------------------------------------------------
X * |SCATTERED_IO| device  | proc nr | requests|         | iov ptr |
X * ----------------------------------------------------------------
X *
X * The file contains one entry point:
X *
X *   winchester_task:	main entry when system is brought up
X */
X#include "kernel.h"
X#include <minix/callnr.h>
X#include <minix/com.h>
X#include <minix/partition.h>
X
X
X/*****  esdi i/o adapter ports  */
X
X#define  CMD_REG   0x3510          /*  command interface register            */
X#define  STAT_REG  0x3510          /*  status interface register             */
X#define  BCTL_REG  0x3512          /*  basic control register                */
X#define  BST_REG   0x3512          /*  basic status register                 */
X#define  ATT_REG   0x3513          /*  attention register                    */
X#define  INT_REG   0x3513          /*  interrupt status register             */
X
X
X/*****  basic status register bits  */
X
X#define  DMA_ENA   0x80            /*  DMA enabled?                          */
X#define  INT_PND   0x40            /*  interrupt pending?                    */
X#define  CMD_PRG   0x20            /*  command in progress?                  */
X#define  BUSY      0x10            /*  is adapter busy?                      */
X#define  STR_FUL   0x08            /*  status interface register set?        */
X#define  CMD_FUL   0x04            /*  command interface register full?      */
X#define  XFR_REQ   0x02            /*  data transfer operation ready?        */
X#define  INT_SET   0x01            /*  adapter sending interrupt?            */
X
X
X/*****  attention register commands  */
X
X#define  ATT_CMD  0x01             /*  command request                       */
X#define  ATT_EOI  0x02             /*  end of interrupt processing           */
X#define  ATT_ABT  0x03             /*  abort the current command             */
X#define  ATT_RST  0xE4             /*  reset the esdi adapter                */
X
X
X/*****  dma register addresses  */
X
X#define  DMA_EXTCMD  0x18          /*  extended function register            */
X#define  DMA_EXEC    0x1A          /*  extended function execute             */
X
X
X/*****  miscellaneous  */
X
X#define  ERR            -1         /*  general error code                    */
X#define  SECTOR_SIZE    512        /*  hard disk sector size  [bytes]        */
X#define  MAX_ERRORS     4          /*  maximum number of read/write retries  */
X#define  MAX_DRIVES     2          /*  maximum number of physical drives     */
X#define  DEV_PER_DRIVE  (1+NR_PARTITIONS)
X                                   /*  number of logical devices on each     */
X                                   /*    physical hard disk drive            */
X#define  NR_DEVICES     (MAX_DRIVES*DEV_PER_DRIVE)
X                                   /*  maximum number of logical devices     */
X#define  SYS_PORTA      0x92       /*  system control port a                 */
X#define  LIGHT_ON       0xC0       /*  fixed-disk activity light reg. mask   */
X
X
X/*****  variables  */
X
XPRIVATE struct wini {              /*  disk/partition information            */
X   int wn_opcode;                  /*  requested disk operation              */
X                                   /*    DEV_READ/DEV_WRITE                  */
X   int wn_procnr;                  /*  process requesting operation          */
X   int wn_drive;                   /*  physical hard disk drive number       */
X   long wn_offset;                 /*  offset [sectors on full disk] to the  */
X                                   /*    requested disk block                */
X   long wn_low;                    /*  lowest sector for the partition       */
X   long wn_size;                   /*  disk partition size  [sectors]        */
X   int wn_count;                   /*  read/write request size  [bytes]      */
X   vir_bytes wn_address;           /*  buffer address for requested i/o      */
X} wini[NR_DEVICES];                /*  index:  0, 5 -- full disk 1, 2        */
X                                   /*     others:  add partition number      */
XPUBLIC int using_bios = FALSE;     /*  is the bios used for hard disk i/o?   */
XPRIVATE int nr_drives;             /*  actual number of physical disk drive  */
XPRIVATE message w_mess;            /*  minix message structure buffer        */
XPRIVATE int command[4];            /*  controller command buffer             */
XPRIVATE unsigned int status_block[9]; /*  status block output from a command */
XPRIVATE unsigned char buf[BLOCK_SIZE];
X                                   /*  partition table buffer                */
XPRIVATE int dma_channel;           /*  fixed disk dma channel number         */
X
X
X/*****  functions  */
X
XFORWARD void wake ();
XFORWARD void copy_prt ();
XFORWARD void sort ();
XFORWARD int w_command ();
XFORWARD int w_do_rdwt ();
XFORWARD int w_transfer ();
XFORWARD int w_att_write ();
XFORWARD int w_interrupt ();
XFORWARD void w_dma_setup();
X
X
X/*===========================================================================*
X *				winchester_task				     * 
X *===========================================================================*/
XPUBLIC void winchester_task () {
X/*
X *     services requests for hard disk i/o
X *
X *     after initializing the whole mess, wait for a request message, service
X *     it, send the results, wait for a request message, service it, etc.,
X *     etc.
X */
X   int r, caller, proc_nr;
X
X   wake ();
X
X   while (TRUE) {
X
X      receive (ANY, &w_mess);
X      if (w_mess.m_source < 0) {
X         printf ("winchester task got message from %d\n", w_mess.m_source);
X         continue;
X      }
X      caller = w_mess.m_source;
X      proc_nr = w_mess.PROC_NR;
X
X	switch(w_mess.m_type) {
X	    case DEV_OPEN:	r = OK;				  break;
X	    case DEV_CLOSE:	r = OK;				  break;
X
X	    case DEV_READ:
X	    case DEV_WRITE:	r = w_do_rdwt(&w_mess);		  break;
X
X	    case SCATTERED_IO:	r = do_vrdwt(&w_mess, w_do_rdwt); break;
X	    default:		r = EINVAL;			  break;
X	}
X      w_mess.m_type = TASK_REPLY;	
X      w_mess.REP_PROC_NR = proc_nr;
X      w_mess.REP_STATUS = r;       /*  no. of bytes transferred/error code */
X      send (caller, &w_mess);
X   }
X}
X
X
X/*===========================================================================*
X *                              wake                                         *
X *===========================================================================*/
XPRIVATE void wake () {
X/*
X *     initializes everything needed to run the hard disk
X *
X *     the following items are initialized:
X *       -- hard disk attributes stored in bios
X *       -- partition table, read from the disk
X *       -- dma transfer channel, read from system register
X *       -- dma transfer and interrupts [disabled]
X *
X *     the hard disk adapter is initialized when the ibm ps/2 is turned on,
X *     using the programmable option select registers.  thus the only
X *     additional initialization is making sure the dma transfer and interrupts
X *     are disabled.  other initialization problems could be checked for, such
X *     as an operation underway.  the paranoid could add a check for adapter
X *     activity and abort the operations.  the truly paranoid can reset the
X *     adapter.  until such worries are proven, why bother?
X */
X   unsigned int drv;               /*  hard disk drive number                */
X   phys_bytes address;             /*  real bios address                     */
X
X   /*  retrieve the actual number of hard disk drives from bios  */
X   phys_copy (0x475L, umap (proc_ptr, D, (vir_bytes)buf, 1), 1L);
X   nr_drives = (int) *buf;
X   if (nr_drives > MAX_DRIVES) nr_drives = MAX_DRIVES;
X   if (nr_drives <= 0) return;
X
X   for (drv = 0;  drv < nr_drives;  ++drv) {
X      if (w_command (drv, 0x0609, 6) != OK) {
X         panic ("Unable to get hard disk parameters\n", NO_NUM);
X      }
X      wini[5*drv].wn_size = ((unsigned long)status_block[3] << 16) |
X                             (unsigned long)status_block[2];
X   }
X   if (w_command (7, 0x060A, 5) != OK) {
X      panic ("Unable to get hard disk dma channel\n", NO_NUM);
X   }
X   dma_channel = (status_block[2] & 0x3C00) >> 10;
X/*
X *     retrieves the full partition table
X */
X   wini[0].wn_low = wini[5].wn_low = 0L;
X   for (drv = 0;  drv < nr_drives;  ++drv) {
X
X      w_mess.DEVICE = 5 * drv;
X      w_mess.POSITION = 0L;
X      w_mess.COUNT = BLOCK_SIZE;
X      w_mess.ADDRESS = (char *) buf;
X      w_mess.PROC_NR = WINCHESTER;
X      w_mess.m_type = DEV_READ;
X
X      if (w_do_rdwt (&w_mess) != BLOCK_SIZE) {
X         printf ("Can't read partition table on winchester %d\n", drv);
X         milli_delay (20000);
X         continue;
X      }
X      if (buf[510] != 0x55  ||  buf[511] != 0xAA) {
X         printf ("Invalid partition table on winchester %d\n", drv);
X         milli_delay (20000);
X         continue;
X      }
X      copy_prt ((int)5*drv);       /*  flesh out the partitions              */
X   }
X   return;
X}
X
X
X/*============================================================================*
X *                              copy_prt                                      *
X *============================================================================*/
XPRIVATE void copy_prt (base_dev)
Xint base_dev; {                  /* base device for drive */
X/*
X *     fills out the hard disk partition initial block and number of blocks
X *
X *     the old minix partition support was removed, since this driver didn't
X *     exist for old partitions.
X */
X   register struct part_entry *pe;
X   register struct wini *wn;
X
X   for (pe = (struct part_entry *) &buf[PART_TABLE_OFF],
X           wn = &wini[base_dev + 1];
X        pe < ((struct part_entry *) &buf[PART_TABLE_OFF]) + NR_PARTITIONS;
X        ++pe, ++wn) {
X      wn->wn_low = pe->lowsec;
X      wn->wn_size = pe->size;
X   }
X   sort (&wini[base_dev+1]);
X}
X
X
X
X/*==========================================================================*
X *                                sort                                      *
X *==========================================================================*/
XPRIVATE void sort (wn)
Xregister struct wini wn[]; {
X/*
X *     sorts the partition table according to the initial block number
X *
X *     this apparently eliminates missing partitions, though it screws up
X *     partition numbers compared with using fdisk on different operating
X *     systems.
X */
X   register int i,j;
X   struct wini tmp;
X
X   for (i = 0;  i < NR_PARTITIONS;  i++) {
X      for (j = 0;  j < NR_PARTITIONS-1;  j++) {
X         if ((wn[j].wn_low == 0  &&  wn[j+1].wn_low != 0)  ||
X             (wn[j].wn_low > wn[j+1].wn_low  &&  wn[j+1].wn_low != 0)) {
X            tmp = wn[j];
X            wn[j] = wn[j+1];
X            wn[j+1] = tmp;
X         }
X      }
X   }
X   return;
X}
X
X
X
X/*===========================================================================*
X *                          w_command                                        *
X *===========================================================================*/
XPRIVATE int w_command (device, cmd, num_words)
Xint device;                        /*  i device to operate on                */
X                                   /*    1-2   physical disk drive number    */
X                                   /*    7     hard disk controller          */
Xint cmd;                           /*  i command to execute                  */
Xint num_words; {                   /*  i expected size of status block       */
X/*
X *     executes a command for a particular device
X *
X *     the operation is conducted as follows:
X *       -- create the command block
X *       -- initialize for command reading by the controller
X *       -- write the command block to the controller, making sure the
X *          controller has digested the previous command word, before shoving
X *          the next down its throat
X *       -- wait for an interrupt
X *       -- read expected number of words of command status information
X *       -- return the command status block
X *
X *     reading and writing registers is accompanied by enabling and disabling
X *     interrupts to ensure that the status register contents still apply when
X *     the desired register is read/written.
X */
X   register int ki;                /*  -- scratch --                         */
X   int status;                     /*  disk adapter status register value    */
X
X   device <<= 5;                   /*  adjust device for our use             */
X   command[0] = cmd | device;      /*  build command block                   */
X   command[1] = 0;
X
X   w_att_write (device | ATT_CMD);
X
X   for (ki = 0;  ki < 2;  ++ki) {
X      out_word (CMD_REG, command[ki]);
X      unlock ();
X      while (TRUE) {
X         lock ();
X         status = in_byte (BST_REG);
X         if (!(status & CMD_FUL)) break;
X         unlock ();
X      }
X   }
X   unlock ();
X
X   status = w_interrupt (0);
X   if (status != (device | 0x01)) {
X      w_att_write (device | ATT_ABT);
X      w_interrupt (0);
X      return  ERR;
X   }
X   for (ki = 0;  ki < num_words;  ++ki) {
X      while (TRUE) {
X         lock ();
X         status = in_byte (BST_REG);
X         if (status & STR_FUL) break;
X         unlock ();
X      }
X      status_block[ki] = in_word (STAT_REG);
X      unlock ();
X   }
X   w_att_write (device | ATT_EOI);
X
X   return  OK;
X}
X
X
X
X/*===========================================================================*
X *				w_do_rdwt				     * 
X *===========================================================================*/
XPRIVATE int w_do_rdwt(m_ptr)
Xmessage *m_ptr;	{		/* pointer to read or write w_message */
X/*
X *     reads/writes a block from the hard disk
X *
X *     checks the validity of the request as fully as possible and fills the
X *     disk information structure before calling 'w_transfer' to do the dirty
X *     work.  while unsuccessful operations are re-tried, this may be
X *     superfluous, since the controller does the same on its own.  turns on
X *     the fixed disk activity light, while busy.  computers need blinking
X *     lights, right?
X */
X   register struct wini *wn;
X   int r, device, errors;
X
X   device = m_ptr->DEVICE;
X   if (device < 0 || device >= NR_DEVICES) return  EIO;
X   if (m_ptr->COUNT != BLOCK_SIZE) return  EINVAL;
X
X   wn = &wini[device];
X   wn->wn_drive = device/DEV_PER_DRIVE;	/* save drive number */
X   if (wn->wn_drive >= nr_drives) return  EIO;
X
X   wn->wn_opcode = m_ptr->m_type;	/* DEV_READ or DEV_WRITE */
X   if (m_ptr->POSITION % BLOCK_SIZE != 0) return  EINVAL;
X
X   wn->wn_offset = m_ptr->POSITION/SECTOR_SIZE;
X   if (wn->wn_offset+BLOCK_SIZE/SECTOR_SIZE > wn->wn_size) return  0;
X
X   wn->wn_offset += wn->wn_low;
X   wn->wn_count = m_ptr->COUNT;
X   wn->wn_address = (vir_bytes) m_ptr->ADDRESS;
X   wn->wn_procnr = m_ptr->PROC_NR;
X
X   out_byte (SYS_PORTA, in_byte (SYS_PORTA) | LIGHT_ON); 
X                                   /*  turn on the disk activity light     */
X
X   for (errors = 0;  errors < MAX_ERRORS;  ++errors) {
X
X      r = w_transfer(wn);
X      if (r == OK) break;
X   }
X   out_byte (SYS_PORTA, in_byte (SYS_PORTA) & ~LIGHT_ON); 
X                                   /*  turn off the disk activity light    */
X   return  (r == OK?  BLOCK_SIZE : EIO);
X}
X
X
X
X/*===========================================================================*
X *				w_transfer				     * 
X *===========================================================================*/
XPRIVATE int w_transfer(wn)
Xregister struct wini *wn; {    /* pointer to the drive struct */
X/*
X *     reads/writes a single block of data from/to the hard disk
X *
X *     the read/write operation performs the following steps:
X *       -- create the command block
X *       -- initialize the command reading by the controller
X *       -- write the command block to the controller, making sure the
X *            controller has digested the previous command word, before
X *            shoving the next down its throat.
X *       -- wait for an interrupt, which must return a 'data transfer ready'
X *            status.  abort the command if it doesn't.
X *       -- set up and start up the direct memory transfer
X *       -- wait for an interrupt, signalling the end of the transfer
X */
X   int device;                     /*  device mask for the command register  */
X   int ki;                         /*  -- scratch --                         */
X   long offset;                    /*  ... [blocks] to the requested block   */
X   int r;                          /*  function return (success) value       */
X   int status;                     /*  basic status register value           */
X
X   device = wn->wn_drive << 5;
X   if (wn->wn_opcode == DEV_READ) {
X      command[0] = 0x4601 | device;
X   } else {
X      command[0] = 0x4602 | device;
X   }
X   command[1] = BLOCK_SIZE / SECTOR_SIZE;
X   offset = wn->wn_offset;
X   command[2] = (int)(offset & 0xFFFF);
X   command[3] = (int)(offset >> 16);
X
X   w_att_write (device | ATT_CMD);
X
X   for (ki = 0;  ki < 4;  ++ki) {
X      out_word (CMD_REG, command[ki]);
X      unlock ();
X      while (TRUE) {
X         lock ();
X         status = in_byte (BST_REG);
X         if (!(status & CMD_FUL)) break;
X         unlock ();
X      }
X   }
X   unlock ();
X
X   status = w_interrupt (0);
X   if (status != (device | 0x0B)) {
X      w_att_write (device | ATT_ABT);
X      w_interrupt (0);
X      return  ERR;
X   }
X   w_dma_setup (wn);
X
X   status = w_interrupt (1);
X
X   w_att_write (device | ATT_EOI);
X
X   if ((status & 0x0F) > 8) return  ERR;
X   return  OK;
X}
X
X
X
X/*==========================================================================*
X *                            w_att_write                                   *
X *==========================================================================*/
XPRIVATE int w_att_write (value)
Xregister int value; {
X/*
X *     writes a command to the esdi attention register
X *
X *     waits for the controller to finish its business before sending the
X *     command to the controller.  note that the interrupts must be off to read
X *     the basic status register and, if the controller is ready, must not be
X *     turned back on until the attention register command is sent.
X */
X   int status;                     /*  basic status register value           */
X
X   while (TRUE) {
X      lock ();
X      status = in_byte (BST_REG);
X      if (!(status & (INT_PND | BUSY))) break;
X      unlock ();
X   }
X   out_byte (ATT_REG, value);
X   unlock ();
X
X   return  OK;
X}
X
X
X
X/*===========================================================================*
X *                          w_interrupt                                      *
X *===========================================================================*/
XPRIVATE int w_interrupt (dma)
Xint dma; {                         /*  i dma transfer is underway            */
X/*
X *     waits for an interrupt from the hard disk controller
X *
X *     enable interrupts on the hard disk and interrupt controllers (and dma if
X *     necessary).  wait for an interrupt.  when received, return the interrupt
X *     status register value.
X *
X *     an interrupt can be detected either from the basic status register or
X *     through a system interrupt handler.  the handler is used for all
X *     interrupts, due to the expected long times to process reads and writes
X *     and to avoid busy waits.
X */
X   message dummy;                  /*  -- scratch --                         */
X   int status;                     /*  basic status register value           */
X
X   dma = dma << 1;
X   out_byte (BCTL_REG, dma | 1);
X   cim_at_wini ();
X
X   receive (HARDWARE, &dummy);
X
X   out_byte (BCTL_REG, 0);
X   if (dma) out_byte (DMA_EXTCMD, 0x90+dma_channel);
X
X   status = in_byte (INT_REG);
X
X   return  status;
X}
X
X
X
X/*==========================================================================*
X *			w_dma_setup				  	    *
X *==========================================================================*/
XPRIVATE void w_dma_setup(wn)
Xregister struct wini *wn; {
X/*
X *     programs the dma controller to move data to and from the hard disk.
X *
X *     uses the extended mode operation of the ibm ps/2 interrupt controller
X *     chip, rather than the intel 8237 (pc/at) compatible mode.
X */
X   int mode, low_addr, high_addr, top_addr, low_ct, high_ct;
X   vir_bytes vir, ct;
X   phys_bytes user_phys;
X
X   vir = (vir_bytes) wn->wn_address;
X   ct = (vir_bytes) BLOCK_SIZE;
X   user_phys = numap (wn->wn_procnr, vir, BLOCK_SIZE);
X
X   low_addr = (int) user_phys & BYTE;
X   high_addr = (int) (user_phys >> 8) & BYTE;
X   top_addr = (int) (user_phys >> 16) & BYTE;
X   low_ct = (int) (ct - 1) & BYTE;
X   high_ct = (int) ((ct-1) >> 8) & BYTE;
X   if (user_phys == 0)
X      panic ("FS gave winchester disk driver bad addr %d", (int)vir);
X
X   mode = (wn->wn_opcode == DEV_READ?  0x4C : 0x44);
X   lock ();
X   out_byte (DMA_EXTCMD, 0x90+dma_channel);
X                                   /*  disable access to dma channel 5     */
X   out_byte (DMA_EXTCMD, 0x20+dma_channel);
X                                   /*  clear the address byte pointer      */
X   out_byte (DMA_EXEC, low_addr);  /*  set the lower eight address bits    */
X   out_byte (DMA_EXEC, high_addr); /*  set address bits 8-15               */
X   out_byte (DMA_EXEC, top_addr);  /*  set the higher four address bits    */
X   out_byte (DMA_EXTCMD, 0x40+dma_channel);
X                                   /*  clear the count byte pointer        */
X   out_byte (DMA_EXEC, low_ct);    /*  set the lower eight bits of count   */
X   out_byte (DMA_EXEC, high_ct);   /*  set the higher eight bits of count  */
X   out_byte (DMA_EXTCMD, 0x70+dma_channel);
X                                   /*  set the transfer mode               */
X   out_byte (DMA_EXEC, mode);      /*  set the transfer mode               */
X   out_byte (DMA_EXTCMD, 0xA0+dma_channel);
X                                   /*  enable access to dma channel 5      */
X   unlock ();
X
X   return;
X}
/
echo x - ether.c
sed '/^X/s///' > ether.c << '/'
X/* This file contains the hardware dependant netwerk device driver
X *
X * The valid messages and their parameters are:
X *
X *   m_type	  DL_PORT    DL_PROC   DL_COUNT   DL_MODE   DL_ADDR
X * |------------+----------+---------+----------+---------+---------|
X * | HARDINT	|          |         |          |         |         |
X * |------------|----------|---------|----------|---------|---------|
X * | DL_WRITE	| port nr  | proc nr | count    | mode    | address |
X * |------------|----------|---------|----------|---------|---------|
X * | DL_WRITEV	| port nr  | proc nr | count    | mode    | address |
X * |------------|----------|---------|----------|---------|---------|
X * | DL_READ	| port nr  | proc nr | count    |         | address |
X * |------------|----------|---------|----------|---------|---------|
X * | DL_READV	| port nr  | proc nr | count    |         | address |
X * |------------|----------|---------|----------|---------|---------|
X * | DL_INIT	| port nr  | proc nr | mode     |         | address |
X * |------------|----------|---------|----------|---------|---------|
X * | DL_GETSTAT	| port nr  | proc nr |          |         | address |
X * |------------|----------|---------|----------|---------|---------|
X * | DL_STOP	|	   |         |          |         |         |
X * |------------|----------|---------|----------|---------|---------|
X *
X * The messages sent are:
X
X *   m-type	  DL_POR T   DL_PROC   DL_COUNT   DL_STAT   DL_CLCK
X * |------------|----------|---------|----------|---------|---------|
X * | DL_INT-TASK| port nr  | proc nr | rd-count | err|stat| clock   |
X * |------------|----------|---------|----------|---------|---------|
X * |DL_TASK-REPL| port nr  | proc nr | rd-count | 0| stat | clock   |
X * |------------|----------|---------|----------|---------|---------|
X *
X *   m_type	  m3_i1     m3_i2       m3_ca1
X * |------------+---------+-----------+---------------|
X * |DL_INIT-REPL| port nr | last port | ethernet addr |
X * |------------|---------|-----------|---------------|
X * */
X
X
X#include "kernel.h"
X#include <minix/com.h>
X#include <minix/dl_eth.h>
X#include <net/ether.h>
X#include "protect.h"
X#include "assert.h"
X#if 0
X#include "eth_hw.h"
X#endif
X#include "hw_conf.h"
X#include "dp8390.h"
X#include "epl.h"
X
X#define IOVEC_NR	16	/* we like iovec's of 16 buffers or less but
X				 * we support all requests */
X
Xtypedef struct iovec_dat {
X  iovec_t iod_iovec[IOVEC_NR];
X  int iod_iovec_s;
X  int iod_proc_nr;
X  vir_bytes iod_iovec_addr;
X} iovec_dat_t;
X
X
Xtypedef struct ehw_tab {
X  int et_flags;
X  ether_addr_t et_address;
X  eth_stat_t et_stat;
X  iovec_dat_t et_read_iovec;
X  vir_bytes et_read_s;
X  int et_client;
X} ehw_tab_t;
X
X#define ETF_FLAGS	0x3FF;
X#define ETF_EMPTY	0x000
X#define ETF_PACK_SEND	0x001
X#define ETF_PACK_RECV	0x002
X#define ETF_SENDINT_EN	0x004
X#define ETF_SENDING	0x008
X#define ETF_READING	0x010
X#define ETF_PACKAVAIL	0x020
X#define ETF_PROMISC	0x040
X#define ETF_MULTI	0x080
X#define ETF_BROAD	0x100
X#define ETF_ENABLED	0x200
X#define ETF_READ_SU	0x400
X
XPRIVATE phys_bytes ehw_linmem;
XPRIVATE segm_t ehw_memsegm;
XPRIVATE ehw_tab_t ehw_table[EHW_PORT_NR];
XPRIVATE ehw_tab_t *ehw_port;
XPRIVATE message mess, reply_mess;
XPRIVATE iovec_dat_t tmp_iovec, tmp1_iovec;
XPRIVATE int throw_away_packet = FALSE;
X
X#define ehw_cp_loc2user ehw_loc2user
X
XFORWARD _PROTOTYPE( void do_write, (message *mess) );
XFORWARD _PROTOTYPE( void do_vwrite, (message *mess) );
XFORWARD _PROTOTYPE( void do_vread, (message *mess) );
XFORWARD _PROTOTYPE( void do_read, (message *mess) );
XFORWARD _PROTOTYPE( void do_init, (message *mess) );
XFORWARD _PROTOTYPE( void do_getstat, (message *mess) );
XFORWARD _PROTOTYPE( void do_stop, (void) );
XFORWARD _PROTOTYPE( void do_int, (void) );
XFORWARD _PROTOTYPE( void ehw_init, (void) );
XFORWARD _PROTOTYPE( int epl_init, (ether_addr_t *ea) );
XFORWARD _PROTOTYPE( int dp_init, (ether_addr_t *ea) );
XFORWARD _PROTOTYPE( int dp_reinit, (void) );
XFORWARD _PROTOTYPE( void err_reply, (message *m, int err) );
XFORWARD _PROTOTYPE( void mess_reply, (message *req, message *reply) );
XFORWARD _PROTOTYPE( void ehw_getheader, (int page, rcvdheader_t *h) );
XFORWARD _PROTOTYPE( int ehw_data2user, (int page, int length) );
XFORWARD _PROTOTYPE( int ehw_user2hw, (vir_bytes user_adddr, int hw_addr,
X		      vir_bytes count) );
XFORWARD _PROTOTYPE( int ehw_hw2user, (int hw_addr, vir_bytes user_offs,
X		      vir_bytes count) );
XFORWARD _PROTOTYPE( int ehw_cp_user2loc, (int user_proc, vir_bytes user_addr,
X			  char *loc_addr, vir_bytes count) );
XFORWARD _PROTOTYPE( int ehw_cp_loc2user, (char *loc_addr, int user_proc,
X		     vir_bytes user_addr, vir_bytes count) );
XFORWARD _PROTOTYPE( int ehw_iovec_size, (void) );
XFORWARD _PROTOTYPE( int ehw_next_iovec, (void) );
XFORWARD _PROTOTYPE( void ehw_recv, (void) );
XFORWARD _PROTOTYPE( int ehw_inttask, (void) );
X
XPUBLIC void ehw_task()
X{
X  ehw_tab_t *this_port = &ehw_table[0];	/* this task uses port 0 */
X
X  ehw_port = this_port;
X  ehw_init();
X
X  while (TRUE) {
X	if (receive(ANY, &mess) < 0) panic("eth_hw: receive failed", NO_NUM);
X#if DEBUG
X	if (d_eth_hw)
X		printk("eth_hw: received %d message from %d\n", mess.m_type,
X		       mess.m_source);
X#endif
X	ehw_port = this_port;
X
X	switch (mess.m_type) {
X	    case DL_WRITE:	do_write(&mess);	break;
X	    case DL_WRITEV:	do_vwrite(&mess);	break;
X	    case DL_READ:	do_read(&mess);	break;
X	    case DL_READV:	do_vread(&mess);	break;
X	    case DL_INIT:	do_init(&mess);	break;
X	    case DL_GETSTAT:	do_getstat(&mess);	break;
X	    case DL_STOP:	do_stop();	break;
X	    case HARD_INT:	do_int();	break;
X	    default:
X#if DEBUG
X		if (d_eth_hw)
X			printf("eth_hw: warning got unknown message (type %d) from %d\n", mess.m_type,
X			       mess.m_source);
X#endif
X		err_reply(&mess, EINVAL);
X		break;
X	}
X	if (ehw_port->et_flags & ETF_ENABLED)
X		do_int();	/* we like to know about received or
X				 * transmitted packets as soon as
X				 * possible */
X
X  }
X
X  panic("eth_hw: task is not allowed to terminate", NO_NUM);
X}
X
XPUBLIC void ehw_dump()
X{
X  ehw_port = &ehw_table[0];
X
X  printf("dumping eth_hw statistics of port 0\r\n\r\n");
X  printf("ets_recvErr\t: %ld\t", ehw_port->et_stat.ets_recvErr);
X  printf("ets_sendErr\t: %ld\t", ehw_port->et_stat.ets_sendErr);
X  printf("ets_OVW\t: %ld\t", ehw_port->et_stat.ets_OVW);
X  printf("\r\n");
X  printf("ets_CRCerr\t: %ld\t", ehw_port->et_stat.ets_CRCerr);
X  printf("ets_frameAll\t: %ld\t", ehw_port->et_stat.ets_frameAll);
X  printf("ets_missedP\t: %ld\t", ehw_port->et_stat.ets_missedP);
X  printf("\r\n");
X  printf("ets_packetR\t: %ld\t", ehw_port->et_stat.ets_packetR);
X  printf("ets_packetT\t: %ld\t", ehw_port->et_stat.ets_packetT);
X  printf("ets_transDef\t: %ld\t", ehw_port->et_stat.ets_transDef);
X  printf("\r\n");
X  printf("ets_collision\t: %ld\t", ehw_port->et_stat.ets_collision);
X  printf("ets_transAb\t: %ld\t", ehw_port->et_stat.ets_transAb);
X  printf("ets_carrSense\t: %ld\t", ehw_port->et_stat.ets_carrSense);
X  printf("\r\n");
X  printf("ets_fifoUnder\t: %ld\t", ehw_port->et_stat.ets_fifoUnder);
X  printf("ets_fifoOver\t: %ld\t", ehw_port->et_stat.ets_fifoOver);
X  printf("ets_CDheartbeat\t: %ld\t", ehw_port->et_stat.ets_CDheartbeat);
X  printf("\r\n");
X  printf("ets_OWC\t: %ld\t", ehw_port->et_stat.ets_OWC);
X  printf("\r\n");
X  printf("dp_isr=%x, and %x, et_flags= %x\r\n", read_reg0(dp_isr),
X         read_reg0(dp_isr),
X         ehw_port->et_flags);
X  printf("\r\n");
X}
X
XPRIVATE void do_write(mess)
Xmessage *mess;
X{
X  int port = mess->DL_PORT;
X  int count = mess->DL_COUNT;
X  int result;
X
X  if (port < 0 || port >= EHW_PORT_NR || ehw_table + port != ehw_port ||
X      !(ehw_port->et_flags & ETF_ENABLED)) {
X	err_reply(mess, ENXIO);
X	return;
X  }
X  if (ehw_port->et_flags & ETF_SENDING) {
X	ehw_port->et_flags |= ETF_SENDINT_EN;
X#if DEBUG
X	{
X		printW();
X		printf("replying SUSPEND because of Send ip\n");
X	}
X#endif
X	err_reply(mess, SUSPEND);
X	return;
X  }
X  assert(!(ehw_port->et_flags & ETF_PACK_SEND));
X  if (count < ETH_MIN_PACK_SIZE || count > ETH_MAX_PACK_SIZE) {
X	err_reply(mess, EPACKSIZE);
X	return;
X  }
X  tmp_iovec.iod_iovec[0].iov_addr =
X	(vir_bytes) mess->DL_ADDR;
X  tmp_iovec.iod_iovec[0].iov_size = mess->DL_COUNT;
X  tmp_iovec.iod_iovec_s = 1;
X  tmp_iovec.iod_proc_nr = mess->DL_PROC;
X  tmp_iovec.iod_iovec_addr = 0;
X
X  result = ehw_user2hw(0, ehw_sendpage * EHW_PAGESIZE, count);
X  if (result < 0) {
X	err_reply(mess, result);
X	return;
X  }
X  write_reg0(dp_tpsr, ehw_sendpage);
X  write_reg0(dp_tbcr1, count >> 8);
X  write_reg0(dp_tbcr0, count & 0xff);
X  write_reg0(dp_cr, CR_TXP);	/* there is goes.. */
X
X  if (mess->DL_MODE & DL_WRITEINT_REQ) {
X#if DEBUG
X	{
X		printW();
X		printf("replying SUSPEND because of WRITEINT_REQ\n");
X	}
X#endif
X	ehw_port->et_flags |= ETF_SENDINT_EN;
X	result = SUSPEND;
X  } else {
X#if DEBUG && 0
X	{
X		printW();
X		printf("replying OK because of not WRITEINT_REQ\n");
X	}
X#endif
X	ehw_port->et_flags &= ~ETF_SENDINT_EN;
X	result = OK;
X  }
X  ehw_port->et_flags |= ETF_SENDING;
X  assert(!(ehw_port->et_flags & ETF_PACK_SEND));
X
X  err_reply(mess, result);
X#if DEBUG && 0
X  {
X	printW();
X	printf("err_replyed\n");
X  }
X#endif
X}
X
XPRIVATE void do_vwrite(mess)
Xmessage *mess;
X{
X  int port = mess->DL_PORT;
X  int count = mess->DL_COUNT;
X  int result, size;
X
X  if (port < 0 || port >= EHW_PORT_NR || ehw_table + port != ehw_port ||
X      !(ehw_port->et_flags & ETF_ENABLED)) {
X	err_reply(mess, ENXIO);
X	return;
X  }
X  if (ehw_port->et_flags & ETF_SENDING) {
X#if DEBUG
X	{
X		printW();
X		printf("replying SUSPEND because of Send ip\n");
X	}
X#endif
X	ehw_port->et_flags |= ETF_SENDINT_EN;
X	err_reply(mess, SUSPEND);
X	return;
X  }
X  assert(!(ehw_port->et_flags & ETF_PACK_SEND));
X
X  result = ehw_cp_user2loc(mess->DL_PROC, (vir_bytes) mess->DL_ADDR,
X			 (char *) tmp1_iovec.iod_iovec,
X	   (count > IOVEC_NR ? IOVEC_NR : count) * sizeof(iovec_t));
X  if (result < 0) {
X	err_reply(mess, result);
X	return;
X  }
X  tmp1_iovec.iod_iovec_s = count;
X  tmp1_iovec.iod_proc_nr = mess->DL_PROC;
X  tmp1_iovec.iod_iovec_addr = (vir_bytes) mess->DL_ADDR;
X
X  tmp_iovec = tmp1_iovec;
X  size = ehw_iovec_size();
X  if (size < 0) {
X	err_reply(mess, size);
X	return;
X  }
X  if (size < ETH_MIN_PACK_SIZE || size > ETH_MAX_PACK_SIZE) {
X	err_reply(mess, EPACKSIZE);
X	return;
X  }
X  tmp_iovec = tmp1_iovec;
X  result = ehw_user2hw(0, ehw_sendpage * EHW_PAGESIZE, size);
X  if (result < 0) {
X	err_reply(mess, result);
X	return;
X  }
X  write_reg0(dp_tpsr, ehw_sendpage);
X  write_reg0(dp_tbcr1, size >> 8);
X  write_reg0(dp_tbcr0, size & 0xff);
X  write_reg0(dp_cr, CR_TXP);	/* there is goes.. */
X
X  if (mess->DL_MODE & DL_WRITEINT_REQ) {
X#if DEBUG && 0
X	{
X		printW();
X		printf("replying SUSPEND because of WRITEINT_REQ\n");
X	}
X#endif
X	ehw_port->et_flags |= ETF_SENDINT_EN;
X	result = SUSPEND;
X  } else {
X#if DEBUG && 0
X	{
X		printW();
X		printf("replying OK because of not WRITEINT_REQ\n");
X	}
X#endif
X	ehw_port->et_flags &= ~ETF_SENDINT_EN;
X	result = OK;
X  }
X  ehw_port->et_flags |= ETF_SENDING;
X
X  assert(!(ehw_port->et_flags & ETF_PACK_SEND));
X  err_reply(mess, result);
X#if DEBUG && 0
X  {
X	printW();
X	printf("err_replyed\n");
X  }
X#endif
X}
X
XPRIVATE void do_read(mess)
Xmessage *mess;
X{
X  int port = mess->DL_PORT;
X  int count = mess->DL_COUNT;
X
X  if (port < 0 || port >= EHW_PORT_NR || ehw_table + port != ehw_port ||
X      !(ehw_port->et_flags & ETF_ENABLED)) {
X	err_reply(mess, ENXIO);
X	return;
X  }
X  if (count < ETH_MAX_PACK_SIZE) {
X	err_reply(mess, EPACKSIZE);
X	return;
X  }
X  ehw_port->et_read_iovec.iod_iovec[0].iov_addr =
X	(vir_bytes) mess->DL_ADDR;
X  ehw_port->et_read_iovec.iod_iovec[0].iov_size = mess->DL_COUNT;
X  ehw_port->et_read_iovec.iod_iovec_s = 1;
X  ehw_port->et_read_iovec.iod_proc_nr = mess->DL_PROC;
X  ehw_port->et_read_iovec.iod_iovec_addr = 0;
X
X  ehw_port->et_flags |= ETF_READING | ETF_READ_SU;
X
X  do_int();			/* check if any packet ready */
X
X  if (ehw_port->et_flags & ETF_READING) err_reply(mess, SUSPEND);
X  assert(!(ehw_port->et_flags & ETF_READ_SU));
X}
X
XPRIVATE void do_vread(mess)
Xmessage *mess;
X{
X  int port = mess->DL_PORT;
X  int count = mess->DL_COUNT;
X  int result;
X
X  if (port < 0 || port >= EHW_PORT_NR || ehw_table + port != ehw_port ||
X      !(ehw_port->et_flags & ETF_ENABLED)) {
X	err_reply(mess, ENXIO);
X	return;
X  }
X  result = ehw_cp_user2loc(mess->DL_PROC, (vir_bytes) mess->DL_ADDR,
X			 (char *) ehw_port->et_read_iovec.iod_iovec,
X	   (count > IOVEC_NR ? IOVEC_NR : count) * sizeof(iovec_t));
X  if (result < 0) {
X	err_reply(mess, result);
X	return;
X  }
X  ehw_port->et_read_iovec.iod_iovec_s = count;
X  ehw_port->et_read_iovec.iod_proc_nr = mess->DL_PROC;
X  ehw_port->et_read_iovec.iod_iovec_addr = (vir_bytes) mess->DL_ADDR;
X#if DEBUG
X  if (d_eth_hw) {
X	int i;
X	for (i = 0; i < (count < IOVEC_NR ? count : IOVEC_NR); i++)
X		printf("iovec[%d]: iov_addr= %x, iov_size= %x\n", i,
X		       ehw_port->et_read_iovec.iod_iovec[i].iov_addr,
X		     ehw_port->et_read_iovec.iod_iovec[i].iov_size);
X  }
X#endif
X
X  tmp_iovec = ehw_port->et_read_iovec;
X  if (ehw_iovec_size() < ETH_MAX_PACK_SIZE) {
X	err_reply(mess, EPACKSIZE);
X	return;
X  }
X  ehw_port->et_flags |= ETF_READING | ETF_READ_SU;
X
X  do_int();			/* check if any packet ready */
X
X  if (ehw_port->et_flags & ETF_READING) err_reply(mess, SUSPEND);
X
X  assert(!(ehw_port->et_flags & ETF_READ_SU));
X}
X
XPRIVATE void do_init(mess)
Xmessage *mess;
X{
X  int result;
X  int port = mess->DL_PORT;
X
X  if (port < 0 || port >= EHW_PORT_NR || ehw_table + port != ehw_port) {
X#if DEBUG
X	if (d_eth_hw)
X		printf("%s, %d: going to error reply\n", __FILE__, __LINE__);
X#endif
X	err_reply(mess, ENXIO);
X	return;
X  }
X  if (!(ehw_port->et_flags & ETF_ENABLED))
X	ehw_port->et_flags = ETF_EMPTY;
X  else
X	ehw_port->et_flags &= ~(ETF_ENABLED | ETF_PROMISC | ETF_MULTI |
X				ETF_BROAD);
X
X  if (mess->DL_MODE & DL_PROMISC_REQ)
X	ehw_port->et_flags |= ETF_PROMISC | ETF_MULTI |
X		ETF_BROAD;
X  if (mess->DL_MODE & DL_MULTI_REQ) ehw_port->et_flags |= ETF_MULTI;
X  if (mess->DL_MODE & DL_BROAD_REQ) ehw_port->et_flags |= ETF_BROAD;
X
X  ehw_port->et_client = mess->m_source;
X  if (!(ehw_port->et_flags & ETF_ENABLED)) {
X	result = epl_init(&ehw_port->et_address);
X	if (result < 0) {
X#if DEBUG
X		if (d_eth_hw)
X			printf("%s, %d: going to error reply\n", __FILE__, __LINE__);
X#endif
X		err_reply(mess, result);
X		return;
X	}
X	result = dp_init(&ehw_port->et_address);
X	if (result < 0) {
X#if DEBUG
X		if (d_eth_hw)
X			printf("%s, %d: going to error reply\n", __FILE__, __LINE__);
X#endif
X		err_reply(mess, result);
X		return;
X	}
X  } else {
X	result = dp_reinit();
X	if (result < 0) {
X#if DEBUG
X		if (d_eth_hw)
X			printf("%s, %d: going to error reply\n", __FILE__, __LINE__);
X#endif
X		err_reply(mess, result);
X		return;
X	}
X  }
X
X  ehw_port->et_flags |= ETF_ENABLED;
X
X  reply_mess.m_type = DL_INIT_REPLY;
X  reply_mess.m3_i1 = mess->DL_PORT;
X  reply_mess.m3_i2 = EHW_PORT_NR;
X  *(ether_addr_t *) reply_mess.m3_ca1 = ehw_port->et_address;
X
X  mess_reply(mess, &reply_mess);
X
X  return;
X}
X
X
XPRIVATE void do_int()
X{
X  int isr;
X  int i;
X
X  isr = read_reg0(dp_isr);
X
X  if (isr & ISR_PTX) {
X	int tsr = read_reg0(dp_tsr);
X
X	if (!(read_reg0(dp_cr) & CR_TXP)) {
X		ehw_port->et_flags &= ~ETF_SENDING;
X		if (ehw_port->et_flags & ETF_SENDINT_EN)
X			ehw_port->et_flags |= ETF_PACK_SEND;
X	}
X	if (tsr & TSR_PTX) ehw_port->et_stat.ets_packetT++;
X	if (tsr & TSR_DFR) ehw_port->et_stat.ets_transDef++;
X	if (tsr & TSR_COL) ehw_port->et_stat.ets_collision++;
X	if (tsr & TSR_ABT) ehw_port->et_stat.ets_transAb++;
X	if (tsr & TSR_CRS) {
X		ehw_port->et_stat.ets_carrSense++;
X#if DEBUG
X		if (d_eth_hw) printk("eth_hw: carrier sense lost\n");
X#endif
X	}
X	if (tsr & TSR_FU) {
X		ehw_port->et_stat.ets_fifoUnder++;
X		printk("eth_hw: fifo underrun\n");
X	}
X	if (tsr & TSR_CDH) {
X		ehw_port->et_stat.ets_CDheartbeat++;
X		printk("eth_hw: CD heart beat failure\n");
X	}
X	if (tsr & TSR_OWC) {
X		ehw_port->et_stat.ets_OWC++;
X		printk("eth_hw: out of window collision\n");
X	}
X	write_reg0(dp_isr, ISR_PTX);
X  }
X  if (isr & ISR_PRX) {
X	ehw_recv();
X
X	if (!(ehw_port->et_flags & ETF_READING)) write_reg0(dp_isr, ISR_PRX);
X  }
X  if (isr & ISR_RXE) {
X#if DEBUG && 0
X	{
X		printW();
X		printf("got Receive Error\n");
X	}
X#endif
X	ehw_port->et_stat.ets_recvErr++;
X
X	write_reg0(dp_isr, ISR_RXE);
X  }
X  if (isr & ISR_TXE) {
X	printf("eth_hw: got Send Error\n");
X	ehw_port->et_stat.ets_sendErr++;
X	if (ehw_port->et_flags & ETF_SENDINT_EN)
X		ehw_port->et_flags |= ETF_PACK_SEND;
X
X	write_reg0(dp_isr, ISR_TXE);
X  }
X  if (isr & ISR_OVW) {
X#if DEBUG && 0
X	{
X		printW();
X		printf("got Overwrite Warning\n");
X	}
X#endif
X	ehw_port->et_stat.ets_OVW++;
X	for (i = 0; i < 4; i++) {
X		throw_away_packet = TRUE;
X		ehw_recv();
X	}
X
X	write_reg0(dp_isr, ISR_OVW);
X  }
X  if (isr & ISR_CNT) {
X	ehw_port->et_stat.ets_CRCerr += read_reg0(dp_cntr0);
X	ehw_port->et_stat.ets_frameAll += read_reg0(dp_cntr1);
X	ehw_port->et_stat.ets_missedP += read_reg0(dp_cntr2);
X
X	write_reg0(dp_isr, ISR_CNT);
X  }
X  if (isr & ISR_RDC)		/* remote DMA complete, but we don't use
X				 * remote DMA */
X	panic("eth_hw: remote dma complete", NO_NUM);
X
X  if (isr & ISR_RST) {		/* this means we got an interrupt but the
X				 * ethernet chip is shutdown. We don't do
X				 * anything. */
X#if DEBUG && 0
X	{
X		printW();
X		printf("eth_hw: NIC stopped\n");
X	}
X#endif
X#if 0
X	panic("nic stopped", NO_NUM);
X#else
X	write_reg0(dp_cr, CR_STA);
X#endif
X  }
X  if (ehw_port->et_flags & ETF_PACKAVAIL) ehw_recv();
X
X  if (ehw_port->et_flags & ETF_PACK_SEND) ehw_inttask();
X}
X
XPRIVATE void do_getstat(mess)
Xmessage *mess;
X{
X  int port = mess->DL_PORT;
X  int result;
X
X  if (port < 0 || port >= EHW_PORT_NR || ehw_table + port != ehw_port ||
X      !(ehw_port->et_flags & ETF_ENABLED)) {
X	err_reply(mess, ENXIO);
X	return;
X  }
X  ehw_port->et_stat.ets_CRCerr += read_reg0(dp_cntr0);
X  ehw_port->et_stat.ets_frameAll += read_reg0(dp_cntr1);
X  ehw_port->et_stat.ets_missedP += read_reg0(dp_cntr2);
X
X  result = ehw_cp_loc2user((char *) &ehw_port->et_stat, mess->DL_PROC,
X    (vir_bytes) mess->DL_ADDR, (vir_bytes) sizeof(ehw_port->et_stat));
X
X  err_reply(mess, result);
X}
X
XPRIVATE int ehw_data2user(page, length)
Xint page, length;
X{
X  int last, count;
X  int result;
X
X  if (!(ehw_port->et_flags & ETF_READING)) {
X	if (!throw_away_packet) return ERROR;
X#if DEBUG && 0
X	{
X		printW();
X		printf("throwing away a packet\n");
X	}
X#endif
X	throw_away_packet = FALSE;
X	return OK;		/* this means: we throw away one packet */
X  }
X  last = page + (length - 1) / EHW_PAGESIZE;
X  if (last >= ehw_stoppage) {
X	count = (ehw_stoppage - page) * EHW_PAGESIZE -
X		sizeof(rcvdheader_t);
X	tmp_iovec = ehw_port->et_read_iovec;
X	result = ehw_hw2user(page * EHW_PAGESIZE + sizeof(rcvdheader_t),
X			     0, count);
X	if (result >= 0) {
X		tmp_iovec = ehw_port->et_read_iovec;
X		result = ehw_hw2user(ehw_startpage * EHW_PAGESIZE, count,
X				     length - count);
X	}
X  } else {
X	tmp_iovec = ehw_port->et_read_iovec;
X	result = ehw_hw2user(page * EHW_PAGESIZE + sizeof(rcvdheader_t),
X			     0, length);
X  }
X
X
X  ehw_port->et_read_s = result < 0 ? result : length;
X  ehw_port->et_flags |= ETF_PACK_RECV;
X  ehw_port->et_flags &= ~ETF_READING;
X
X  return ehw_inttask();
X}
X
XPRIVATE void ehw_init()
X{
X  static eth_stat_t empty_stat = {0, 0, 0, 0, 0, 0 	/* ,... */ };
X  ehw_linmem = EHW_LINMEM;
X  ehw_memsegm = protected_mode ? EPLUS_SELECTOR :
X	physb_to_hclick(EHW_LINMEM);
X
X  ehw_port->et_flags = ETF_EMPTY;
X  ehw_port->et_stat = empty_stat;
X}
X
XPRIVATE int epl_init(ea)
Xether_addr_t *ea;
X{
X  int sum;
X
X  ea->ea_addr[0] = read_reg_epl(epl_ea0);
X  ea->ea_addr[1] = read_reg_epl(epl_ea1);
X  ea->ea_addr[2] = read_reg_epl(epl_ea2);
X  ea->ea_addr[3] = read_reg_epl(epl_ea3);
X  ea->ea_addr[4] = read_reg_epl(epl_ea4);
X  ea->ea_addr[5] = read_reg_epl(epl_ea5);
X  sum = ea->ea_addr[0] + ea->ea_addr[1] + ea->ea_addr[2] + ea->ea_addr[3] +
X	ea->ea_addr[4] + ea->ea_addr[5] +
X	read_reg_epl(epl_res2) +
X	read_reg_epl(epl_chksum);
X  if ((sum & 0xFF) != 0xFF) {
X	printf("No ethernet+ board\n");
X	return ERROR;
X  }
X  printf("Found an ethernet+ card\n");
X
X  write_reg_epl(epl_ctlstatus, CTL_RESET);
X  write_reg_epl(epl_ctlstatus, CTL_MENABLE |
X	      ((ehw_linmem >> 13) & CTL_MEMADDR));
X  return OK;
X}
X
XPRIVATE int dp_init(ea)
Xether_addr_t *ea;
X{
X  int dp_rcr_reg;
X
X  write_reg0(dp_cr, CR_PS_P0 | CR_DM_ABORT);
X  write_reg0(dp_pstart, ehw_startpage);
X  write_reg0(dp_pstop, ehw_stoppage);
X  write_reg0(dp_bnry, ehw_startpage);
X  write_reg0(dp_rcr, RCR_MON);
X  write_reg0(dp_tcr, TCR_NORMAL);
X  write_reg0(dp_dcr, DCR_BYTEWIDE | DCR_8BYTES);
X  write_reg0(dp_rbcr0, 0);
X  write_reg0(dp_rbcr1, 0);
X  write_reg0(dp_isr, 0xFF);
X  write_reg0(dp_cr, CR_PS_P1 | CR_DM_ABORT);
X
X  write_reg1(dp_par0, ea->ea_addr[0]);
X  write_reg1(dp_par1, ea->ea_addr[1]);
X  write_reg1(dp_par2, ea->ea_addr[2]);
X  write_reg1(dp_par3, ea->ea_addr[3]);
X  write_reg1(dp_par4, ea->ea_addr[4]);
X  write_reg1(dp_par5, ea->ea_addr[5]);
X
X  write_reg1(dp_mar0, 0xff);
X  write_reg1(dp_mar1, 0xff);
X  write_reg1(dp_mar2, 0xff);
X  write_reg1(dp_mar3, 0xff);
X  write_reg1(dp_mar4, 0xff);
X  write_reg1(dp_mar5, 0xff);
X  write_reg1(dp_mar6, 0xff);
X  write_reg1(dp_mar7, 0xff);
X
X  write_reg1(dp_curr, ehw_startpage + 1);
X  write_reg1(dp_cr, CR_PS_P0 | CR_DM_ABORT);
X
X  dp_rcr_reg = 0;
X  if (ehw_port->et_flags & ETF_PROMISC)
X	dp_rcr_reg |= RCR_AB | RCR_PRO | RCR_AM;
X  if (ehw_port->et_flags & ETF_BROAD) dp_rcr_reg |= RCR_AB;
X  if (ehw_port->et_flags & ETF_MULTI) dp_rcr_reg |= RCR_AM;
X  write_reg0(dp_rcr, dp_rcr_reg);
X  read_reg0(dp_cntr0);		/* reset counters by reading */
X  read_reg0(dp_cntr1);
X  read_reg0(dp_cntr2);
X
X  write_reg0(dp_imr, IMR_PTXE | IMR_TXEE | IMR_PRXE | IMR_CNTE |
X	   IMR_OVWE);
X  write_reg0(dp_cr, CR_STA | CR_DM_ABORT);
X
X  return OK;
X}
X
XPRIVATE int dp_reinit()
X{
X  int dp_rcr_reg;
X
X  write_reg0(dp_cr, CR_PS_P0);
X
X  dp_rcr_reg = 0;
X  if (ehw_port->et_flags & ETF_PROMISC)
X	dp_rcr_reg |= RCR_AB | RCR_PRO | RCR_AM;
X  if (ehw_port->et_flags & ETF_BROAD) dp_rcr_reg |= RCR_AB;
X  if (ehw_port->et_flags & ETF_MULTI) dp_rcr_reg |= RCR_AM;
X  write_reg0(dp_rcr, dp_rcr_reg);
X
X  return OK;
X}
X
XPRIVATE void ehw_recv()
X{
X  rcvdheader_t header;
X  unsigned pageno, curr, next;
X  vir_bytes length;
X  int packet_processed = FALSE;
X
X  pageno = read_reg0(dp_bnry) + 1;
X  if (pageno == ehw_stoppage) pageno = ehw_startpage;
X
X  do {
X	write_reg0(dp_cr, CR_PS_P1);
X	curr = read_reg1(dp_curr);
X	write_reg0(dp_cr, CR_PS_P0);
X	/* Warning: this can cause race conditions if some other
X	 * thread also uses this registers */
X	if (pageno == curr) break;
X
X	ehw_getheader(pageno, &header);
X	length = (header.rp_rbcl | (header.rp_rbch << 8)) -
X		sizeof(rcvdheader_t);
X	next = header.rp_next;
X	if (header.rp_status & RSR_FO) {
X		/* This is very serious, so we issue a warnig and
X		 * reset the buffers */
X		printk("eth_hw: fifo overrun, reseting receive buffer\n");
X		ehw_port->et_stat.ets_fifoOver++;
X		next = curr;
X	} else if ((header.rp_status & RSR_PRX) &&
X		   (ehw_port->et_flags & ETF_ENABLED)) {
X		int result = ehw_data2user(pageno, length);
X
X		if (result < 0) return;
X		packet_processed = TRUE;
X		ehw_port->et_stat.ets_packetR++;
X	}
X	if (next == ehw_startpage)
X		write_reg0(dp_bnry, ehw_stoppage - 1);
X	else
X		write_reg0(dp_bnry, next - 1);
X
X	pageno = next;
X	assert(pageno >= ehw_startpage && pageno < ehw_stoppage);
X  }
X  while (!packet_processed);
X  if (pageno == curr) {		/* if receive buffer empty then the receive
X				 * interrupt can be acknowledged */
X	if (read_reg0(dp_isr) & ISR_PRX) write_reg0(dp_isr, ISR_PRX);
X	ehw_port->et_flags &= ~ETF_PACKAVAIL;
X  } else
X	ehw_port->et_flags |= ETF_PACKAVAIL;
X}
X
XPRIVATE void do_stop()
X{
X#if DEBUG && 0
X  {
X	printW();
X	printf("got a stop request\n");
X  }
X#endif
X  write_reg0(dp_cr, CR_STP);
X  ehw_port->et_flags &= ETF_EMPTY;
X}
X
XPRIVATE void mess_reply(req, reply)
Xmessage *req, *reply;
X{
X  ehw_tab_t *save_port_nr = ehw_port;	/* save port because a Send
X					 * may block */
X#if DEBUG && 0
X  {
X	printW();
X	printk("eth_hw: mess_reply to %d\n",
X	       req->m_source);
X  }
X#endif
X#if DEBUG && 0
X  {
X	printW();
X	printf("sending\n");
X  }
X#endif
X  if (send(req->m_source, reply) < 0)
X	panic("eth_hw: unable to mess_reply()", NO_NUM);
X#if DEBUG && 0
X  {
X	printW();
X	printf("Send completed\n");
X  }
X#endif
X
X  ehw_port = save_port_nr;
X}
X
XPRIVATE void err_reply(m, err)
Xmessage *m;
Xint err;
X{
X  ehw_tab_t *save_port_nr = ehw_port;	/* save port because a Send
X					 * may block */
X  message reply;
X  int status;
X
X#if DEBUG
X  if (d_eth_hw) printk("eth_hw: err_reply() %d to %d\n", err, m->m_source);
X#endif
X  status = 0;
X  if (ehw_port->et_flags & ETF_PACK_SEND) {
X	assert(ehw_port->et_flags & ETF_SENDINT_EN);
X	status |= DL_PACK_SEND;
X#if DEBUG
X	{
X		printW();
X		printf("replying pack sent\n");
X	}
X#endif
X  }
X  if (ehw_port->et_flags & ETF_PACK_RECV) {
X	status |= DL_PACK_RECV;
X#if DEBUG && 0
X	{
X		printW();
X		printf("replying pack received\n");
X	}
X#endif
X  }
X  if (!(ehw_port->et_flags & ETF_ENABLED)) status |= DL_DISABLED;
X
X  reply.m_type = DL_TASK_REPLY;
X  reply.DL_PORT = m->DL_PORT;
X  reply.DL_PROC = m->DL_PROC;
X  reply.DL_STAT = status | ((u32_t) err << 16);
X  reply.DL_COUNT = ehw_port->et_read_s;
X  reply.DL_CLCK = get_uptime();
X#if DEBUG && 0
X  {
X	printW();
X	printf("sending DL_TASK_REPLY\n");
X  }
X#endif
X  if (send(m->m_source, &reply) < 0)
X	panic("eth_hw: unable to err_reply()", NO_NUM);
X#if DEBUG && 0
X  {
X	printW();
X	printf("Send completed\n");
X  }
X#endif
X
X  ehw_port = save_port_nr;
X  ehw_port->et_read_s = 0;
X  if (ehw_port->et_flags & ETF_PACK_SEND) {
X	ehw_port->et_flags &= ~(ETF_PACK_SEND | ETF_SENDING |
X				ETF_SENDINT_EN);
X#if DEBUG
X	{
X		printW();
X		printf("clearing SENDINT_EN\n");
X	}
X#endif
X  }
X  ehw_port->et_flags &= ~(ETF_PACK_RECV | ETF_READ_SU);
X}
X
XPRIVATE int ehw_inttask()
X{
X  ehw_tab_t *save_port_nr;	/* save port because a Send may block */
X  message reply;
X  int status, result;
X
X  save_port_nr = ehw_port;
X  reply.m_type = DL_INT_TASK;
X  status = 0;
X
X  if (ehw_port->et_flags & ETF_PACK_SEND) {
X	assert(ehw_port->et_flags & ETF_SENDINT_EN);
X	status |= DL_PACK_SEND;
X#if DEBUG && 0
X	{
X		printW();
X		printf("replying pack sent\n");
X	}
X#endif
X  }
X  if (ehw_port->et_flags & ETF_PACK_RECV) {
X	status |= DL_PACK_RECV;
X	if (ehw_port->et_flags & ETF_READ_SU) {
X		reply.m_type = DL_TASK_REPLY;
X		ehw_port->et_flags &= ~ETF_READ_SU;
X	}
X#if DEBUG && 0
X	{
X		printW();
X		printf("replying pack received\n");
X	}
X#endif
X  }
X  if (!(ehw_port->et_flags & ETF_ENABLED)) status |= DL_DISABLED;
X
X  reply.DL_PORT = ehw_port - ehw_table;
X  reply.DL_PROC = ehw_port->et_client;
X  reply.DL_STAT = status;
X  reply.DL_COUNT = ehw_port->et_read_s;
X  reply.DL_CLCK = get_uptime();
X
X#if DEBUG && 0
X  {
X	printW();
X	printf("sending\n");
X  }
X#endif
X  result = send(ehw_port->et_client, &reply);
X#if DEBUG && 0
X  {
X	printW();
X	printf("Send completed\n");
X  }
X#endif
X
X  ehw_port = save_port_nr;
X  if (result < 0) {
X#if DEBUG
X	{
X		printW();
X		printf("Send had error %d\n", result);
X	}
X#endif
X	return result;
X	/* The only error posible should be a deadlock but we're able
X	 * to regenerate this message so we just don't reset some
X	 * status flags. */
X  }
X  ehw_port->et_read_s = 0;
X  if (ehw_port->et_flags & ETF_PACK_SEND) {
X	ehw_port->et_flags &= ~(ETF_PACK_SEND | ETF_SENDING |
X				ETF_SENDINT_EN);
X#if DEBUG && 0
X	{
X		printW();
X		printf("clearing SENDINT_EN\n");
X	}
X#endif
X  }
X  ehw_port->et_flags &= ~ETF_PACK_RECV;
X  return OK;
X}
X
XPRIVATE void ehw_getheader(page, h)
Xint page;
Xrcvdheader_t *h;
X{
X  u16_t *ha = (u16_t *) h;
X  u16_t offset = page * EHW_PAGESIZE;
X
X#if DEBUG
X  if (d_eth_hw) printk("eth_hw: mem_rdw(0x%x:0x%x)\n", ehw_memsegm, offset);
X#endif
X  *ha = mem_rdw(ehw_memsegm, offset);
X  ha++;
X  offset += sizeof(*ha);
X
X#if DEBUG
X  if (d_eth_hw) printk("eth_hw: mem_rdw(0x%x:0x%x)\n", ehw_memsegm, offset);
X#endif
X  *ha = mem_rdw(ehw_memsegm, offset);
X}
X
XPRIVATE int ehw_cp_user2loc(user_proc, user_addr, loc_addr, count)
Xint user_proc;
Xvir_bytes user_addr;
Xchar *loc_addr;
Xvir_bytes count;
X{
X  phys_bytes src, dest;
X
X  src = numap(user_proc, user_addr, count);
X  if (!src) {
X#if DEBUG
X	if (d_eth_hw) printk("ehw_cp_user2loc: user umap failed\n");
X#endif
X	return EFAULT;
X  }
X#if DEBUG
X  if (d_eth_hw)
X	printk("ehw_cp_user2loc: %d bytes from %x in proc %d to %x in %d\n",
X	       count, user_addr, user_proc, (vir_bytes) loc_addr, proc_number(proc_ptr));
X#endif
X
X  dest = umap(proc_ptr, D, (vir_bytes) loc_addr, count);
X  assert(dest != 0);
X
X  phys_copy(src, dest, (phys_bytes) count);
X
X  return OK;
X}
X
XPRIVATE int ehw_cp_loc2user(loc_addr, user_proc, user_addr, count)
Xchar *loc_addr;
Xint user_proc;
Xvir_bytes user_addr;
Xvir_bytes count;
X{
X  phys_bytes src, dst;
X
X  dst = numap(user_proc, user_addr, count);
X  if (!dst) {
X#if DEBUG
X	if (d_eth_hw) printk("ehw_cp_loc2user: user umap failed\n");
X#endif
X	return EFAULT;
X  }
X#if DEBUG
X  if (d_eth_hw)
X	printk("ehw_cp_loc2user: %d bytes to %x in proc %d from %x in %d\n",
X	       count, user_addr, user_proc, (vir_bytes) loc_addr, proc_number(proc_ptr));
X#endif
X
X  src = umap(proc_ptr, D, (vir_bytes) loc_addr, count);
X  assert(src != 0);
X
X  phys_copy(src, dst, (phys_bytes) count);
X
X  return OK;
X}
X
XPRIVATE int ehw_iovec_size()
X{
X  int size = 0;
X  int i, n, result;
X
X  while (TRUE) {
X	n = tmp_iovec.iod_iovec_s;
X	if (n > IOVEC_NR) n = IOVEC_NR;
X
X	for (i = 0; i < n; i++) size += tmp_iovec.iod_iovec[i].iov_size;
X
X	if (tmp_iovec.iod_iovec_s == n) break;
X
X	result = ehw_next_iovec();
X	if (result < 0) return result;
X  }
X  return size;
X}
X
XPRIVATE int ehw_hw2user(hw_addr, user_offs, count)
Xint hw_addr;
Xvir_bytes user_offs;
Xvir_bytes count;
X{
X  phys_bytes phys_hw, phys_user;
X  int result, bytes, n, i;
X
X#if DEBUG
X  if (d_eth_hw)
X	printf("ehw_hw2user (%x, %x, %x)\n", hw_addr, user_offs, count);
X#endif
X
X  phys_hw = ehw_linmem + hw_addr;
X
X  do {
X	n = tmp_iovec.iod_iovec_s;
X	if (n > IOVEC_NR) n = IOVEC_NR;
X
X	for (i = 0; i < n && user_offs >= tmp_iovec.iod_iovec[i].iov_size;
X	     i++)
X		user_offs -= tmp_iovec.iod_iovec[i].iov_size;
X
X	if (i == n) {
X		result = ehw_next_iovec();
X		if (result < 0) return result;
X	}
X  }
X  while (i == n);
X  if (user_offs) {
X	bytes = tmp_iovec.iod_iovec[i].iov_size - user_offs;
X	if (bytes > count) bytes = count;
X
X	phys_user = numap(tmp_iovec.iod_proc_nr,
X			tmp_iovec.iod_iovec[i].iov_addr + user_offs,
X			  bytes);
X#if DEBUG
X	if (d_eth_hw)
X		printk("ehw_hw2user: 1st numap(%d, %x, %x) failed\n", tmp_iovec.iod_proc_nr,
X		tmp_iovec.iod_iovec[i].iov_addr + user_offs, bytes);
X#endif
X	if (!phys_user) {
X#if DEBUG
X		if (d_eth_hw)
X			printk("ehw_hw2user: 1st numap(%d, %x, %x) failed\n", tmp_iovec.iod_proc_nr,
X			       tmp_iovec.iod_iovec[i].iov_addr + user_offs, bytes);
X#endif
X		return EFAULT;
X	}
X#if DEBUG
X	if (d_eth_hw)
X		printk("ehw_hw2user: phys_copy(%X,%X,%X)\n", phys_user, phys_hw,
X		       (phys_bytes) bytes);
X#endif
X	phys_copy(phys_hw, phys_user, (phys_bytes) bytes);
X	count -= bytes;
X	phys_hw += bytes;
X	i++;
X  }
X  while (count) {
X	if (i == n) {
X		result = ehw_next_iovec();
X		if (result < 0) return result;
X		i = 0;
X	}
X	for (; i < n; i++) {
X		bytes = tmp_iovec.iod_iovec[i].iov_size;
X		if (bytes > count) bytes = count;
X
X		phys_user = numap(tmp_iovec.iod_proc_nr,
X				  tmp_iovec.iod_iovec[i].iov_addr,
X				  bytes);
X#if DEBUG
X		if (d_eth_hw)
X			printk("ehw_hw2user: 2nd numap(%d, %x, %x) failed\n", tmp_iovec.iod_proc_nr,
X			       tmp_iovec.iod_iovec[i].iov_addr + user_offs, bytes);
X#endif
X		if (!phys_user) {
X#if DEBUG
X			if (d_eth_hw)
X				printk("ehw_hw2user: 2nd numap(%d, %x, %x) failed\n", tmp_iovec.iod_proc_nr,
X				       tmp_iovec.iod_iovec[i].iov_addr + user_offs, bytes);
X			printk("ehw_hw2user: umap failed\n");
X#endif
X			return EFAULT;
X		}
X#if DEBUG
X		if (d_eth_hw)
X			printk("ehw_hw2user: phys_copy(%X,%X,%X)\n", phys_user, phys_hw,
X			       (phys_bytes) bytes);
X#endif
X		phys_copy(phys_hw, phys_user, (phys_bytes) bytes);
X		count -= bytes;
X		phys_hw += bytes;
X		if (!count) break;
X	}
X  }
X  return OK;
X}
X
XPRIVATE int ehw_user2hw(user_offs, hw_addr, count)
Xvir_bytes user_offs;
Xint hw_addr;
Xvir_bytes count;
X{
X  phys_bytes phys_hw, phys_user;
X  int result, bytes, n, i;
X
X#if DEBUG
X  if (d1_eth_hw)
X	printk("ehw_user2hw(%x, %x, %x)\n", user_offs, hw_addr, count);
X#endif
X
X  phys_hw = ehw_linmem + hw_addr;
X
X  do {
X	n = tmp_iovec.iod_iovec_s;
X	if (n > IOVEC_NR) n = IOVEC_NR;
X
X	for (i = 0; i < n && user_offs >= tmp_iovec.iod_iovec[i].iov_size;
X	     i++)
X		user_offs -= tmp_iovec.iod_iovec[i].iov_size;
X
X	if (i == n) {
X		result = ehw_next_iovec();
X		if (result < 0) return result;
X	}
X  }
X  while (i == n);
X  if (user_offs) {
X	bytes = tmp_iovec.iod_iovec[i].iov_size - user_offs;
X	if (bytes > count) bytes = count;
X
X	phys_user = numap(tmp_iovec.iod_proc_nr,
X			tmp_iovec.iod_iovec[i].iov_addr + user_offs,
X			  bytes);
X	if (!phys_user) {
X#if DEBUG
X		if (d1_eth_hw)
X			printk("ehw_user2hw: 1st numap(%d, %x, %x) failed\n", tmp_iovec.iod_proc_nr,
X			       tmp_iovec.iod_iovec[i].iov_addr + user_offs, bytes);
X		printk("ehw_user2hw: umap failed\n");
X#endif
X		return EFAULT;
X	}
X#if DEBUG
X	if (d1_eth_hw)
X		printk("ehw_user2hw: phys_copy(%X,%X,%X)\n", phys_user, phys_hw,
X		       (phys_bytes) bytes);
X#endif
X	phys_copy(phys_user, phys_hw, (phys_bytes) bytes);
X	count -= bytes;
X	phys_hw += bytes;
X	i++;
X  }
X  while (count) {
X	if (i == n) {
X		result = ehw_next_iovec();
X		if (result < 0) return result;
X		i = 0;
X	}
X	for (; i < n; i++) {
X		bytes = tmp_iovec.iod_iovec[i].iov_size;
X		if (bytes > count) bytes = count;
X
X		phys_user = numap(tmp_iovec.iod_proc_nr,
X				  tmp_iovec.iod_iovec[i].iov_addr,
X				  bytes);
X		if (!phys_user) {
X#if DEBUG
X			if (d1_eth_hw)
X				printk("ehw_user2hw: 2nd numap(%d, %x, %x) failed\n", tmp_iovec.iod_proc_nr,
X				       tmp_iovec.iod_iovec[i].iov_addr + user_offs, bytes);
X			printk("ehw_user2hw: umap failed\n");
X#endif
X			return EFAULT;
X		}
X#if DEBUG
X		if (d1_eth_hw)
X			printk("ehw_user2hw: phys_copy(%X,%X,%X)\n", phys_user, phys_hw,
X			       (phys_bytes) bytes);
X#endif
X		phys_copy(phys_user, phys_hw, (phys_bytes) bytes);
X		count -= bytes;
X		phys_hw += bytes;
X		if (!count) break;
X	}
X  }
X  return OK;
X}
X
XPRIVATE int ehw_next_iovec()
X{
X  if (tmp_iovec.iod_iovec_s <= IOVEC_NR) {
X	printk("eth_hw: ehw_next_iovec failed\n");
X	return EINVAL;
X  }
X  tmp_iovec.iod_iovec_s -= IOVEC_NR;
X
X  tmp_iovec.iod_iovec_addr += IOVEC_NR * sizeof(iovec_t);
X
X  return ehw_cp_user2loc(tmp_iovec.iod_proc_nr,
X	     tmp_iovec.iod_iovec_addr, (char *) tmp_iovec.iod_iovec,
X		       (tmp_iovec.iod_iovec_s > IOVEC_NR ? IOVEC_NR :
X			tmp_iovec.iod_iovec_s) * sizeof(iovec_t));
X
X}
/
echo x - ether.h
sed '/^X/s///' > ether.h << '/'
X/* Ethernet driver header. */
X
X#ifndef ETHER_H
X#define ETHER_H
X
X#define EIM_FLAGS		/* init mode flags */
X#define EIM_READ	0x01
X#define EIM_WRITE	0x02
X#define EIM_BROADCAST	0x04
X#define EIM_MULTICAST	0x08
X
X#endif  /* ETHER_H */
/
echo x - hw_conf.h
sed '/^X/s///' > hw_conf.h << '/'
X/*
Xhw_conf.h
X*/
X
X#ifndef HW_CONF_H
X#define HW_CONF_H
X
X#define EHW_PORT_NR	1
X
X#define ehw_dp8390port ((union dp8390reg *)0x290)
X#define ehw_eplport ((struct eplusreg *)0x280)
X#define EHW_LINMEM	EPLUS_BASE
X
X#define ehw_sendpage	0
X#define ehw_startpage	6
X#define ehw_stoppage	32
X
X#define EHW_PAGESIZE	256
X
X#define read_reg_epl(reg) in_byte ((port_t)&(ehw_eplport->reg))
X#define write_reg_epl(reg,data) out_byte ((port_t)&(ehw_eplport->reg), data)
X
X#define read_reg0(reg)	in_byte	((port_t)&(ehw_dp8390port->dp_pg0rd.reg))
X#define write_reg0(reg,data) out_byte ((port_t)&(ehw_dp8390port->dp_pg0wr.reg), data)
X
X#define read_reg1(reg)	in_byte ((port_t)&(ehw_dp8390port->dp_pg1rdwr.reg))
X#define write_reg1(reg,data) out_byte ((port_t)&(ehw_dp8390port->dp_pg1rdwr.reg),data)
X
X#endif /* HW_CONF_H */
/
echo x - klib88.x.ansi
sed '/^X/s///' > klib88.x.ansi << '/'
X! This file contains a number of assembly code utility routines needed by the
X! kernel.  They are:
X
X.define	_bios13		! make BIOS 13 call for disk I/O (real mode only)
X.define	_build_sig	! build 4 word structure pushed onto stack for signals
X.define	_check_mem	! check a block of memory, return the valid size
X.define	_cim_at_wini	! clear the AT winchester interrupt mask
X.define	_cim_floppy	! clear the floppy interrupt mask
X.define	_cim_printer	! clear the printer interrupt mask
X.define	_cim_xt_wini	! clear the XT winchester interrupt mask
X.define	_cp_mess	! copies messages from source to destination
X.define	_exit		! dummy for library routines
X.define	.fat		! dummy for library routines
X.define	_get_byte	! read a byte from anywhere and return it
X.define	_in_byte	! read a byte from a port and return it
X.define _in_word	! read a word from a port and return it
X.define	_klib_1hook	! init from real mode for real or protected mode
X.define	_klib_2hook	! init from protected mode for real or protected mode
X.define	_lock		! disable interrupts
X.define	_mem_rdw	! copy one word from [segment:offset]
X.define	_out_byte	! write a byte to a port
X.define	_out_word	! write a word to a port
X.define	_phys_copy	! copy data from anywhere to anywhere in memory
X.define	_port_read	! transfer data from (disk controller) port to memory
X.define	_port_write	! transfer data from memory to (disk controller) port
X.define	_reset		! reset the system (real mode only)
X.define	_scr_down	! scroll screen a line down (in software, by copying)
X.define	_scr_up		! scroll screen a line up (in software, by copying)
X.define	_sim_printer	! set the printer interrupt mask
X.define	_tasim_printer	! test and set the printer interrupt mask
X.define	_test_and_set	! test and set locking primitive on a word in memory
X.define	.trp		! dummy for library routines
X.define	_unlock		! enable interrupts
X.define	_vid_copy	! copy data to video ram (perhaps during retrace only)
X.define	_wait_retrace	! wait for retrace interval
X
X! The routines only guarantee to preserve the registers the 'C' compiler
X! expects to be preserved (si, di, bp, sp, segment registers, and direction
X! bit in the flags), though some of the older ones preserve bx, cx and dx.
X
X#include <minix/config.h>
X#include <minix/const.h>
X#include "const.h"
X#include "sconst.h"
X#include "protect.h"
X
X#if INTEL_32BITS
X#error /* this is not the 32-bit version */
X#endif
X
X#define DS_286_OFFSET	DS_286_INDEX*DESC_SIZE
X#define ES_286_OFFSET	ES_286_INDEX*DESC_SIZE
X#define EM_MASK		0xFFF0	/* extended memory mask for hi word */
X#define EM_XFER_VEC	0x15	/* copy (normal or extended) memory */
X#	define EM_XFER_FUNC	0x87
X#define JMP_OPCODE	0xE9	/* opcode used for patching */
X#define OFF_MASK	0x000F	/* offset mask for phys_b -> hclick:offset */
X
X! imported functions
X
X.extern		p_restart
X.extern		p_save
X.extern		_restart
X.extern		save
X
X! exported variables
X
X	.bss
X.define		splimit
X
X! imported variables
X
X.extern		_Ax, _Bx, _Cx, _Dx, _Es
X.extern		_blank_color
X.extern		_gdt
X.extern		_protected_mode
X.extern		_snow
X.extern		_vec_table
X.extern		_vid_mask
X.extern		_vid_port
X
X	.text
X!*===========================================================================*
X!*				bios13					     *
X!*===========================================================================*
X! PUBLIC void bios13();
X
X_bios13:			! make a BIOS 0x13 call for disk I/O
X	push ax			! save the registers
X	push bx
X	push cx
X	push dx
X	push es
X	mov ax,_Ax		! load parameters
X	mov bx,_Bx
X	mov cx,_Cx
X	mov dx,_Dx
X	mov es,_Es
X	int 0x13		! make the BIOS call
X	mov _Ax,ax		! save results
X	mov _Bx,bx
X	mov _Cx,cx
X	mov _Dx,dx
X	pop es
X	pop dx
X	pop cx
X	pop bx
X	pop ax
X	ret
X
X
X!*===========================================================================*
X!*				build_sig				     *
X!*===========================================================================*
X! PUBLIC void build_sig(char *sig_stuff, struct proc *rp, int sig)
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.
X
X_build_sig:
X	push bp			! save bp
X	mov bp,sp		! set bp to sp for accessing params
X	push bx			! save bx
X	push si			! save si
X	mov bx,4(bp)		! bx points to sig_stuff
X	mov si,6(bp)		! si points to proc table entry
X	mov ax,8(bp)		! ax = signal number
X	mov (bx),ax		! put signal number in sig_stuff
X	mov ax,PCREG(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,PSWREG(si)	! ax = signalled process' PSW
X	mov 6(bx),ax		! put psw in sig_stuff
X	pop si			! restore si
X	pop bx			! restore bx
X	pop bp			! restore bp
X	ret			! return to caller
X
X
X!*===========================================================================*
X!*				check_mem				     *
X!*===========================================================================*
X! PUBLIC phys_bytes check_mem(phys_bytes base, phys_bytes size);
X! Check a block of memory, return the amount valid.
X! Only every 16th byte is checked.
X! The memory and initial size must be <= 1M for non-protected mode.
X! An initial size of 0 means everything.
X! This really should do some alias checks.
X
X_check_mem:
X	push	bp
X	mov	bp,sp
X	push	ds
X	mov	dx,4+2(bp)	! base in dx:ax
X	sub	ax,ax		! prepare for early exit
X	test	dx,#notop(HCHIGH_MASK)
X	jnz	cm_1exit	! can't handle bases above 1M
X	mov	ax,4(bp)	! ax = base segment = base / 16 % 0x10000
X	andb	al,#HCLOW_MASK
X	orb	al,dl
X	movb	cl,#HCLICK_SHIFT
X	ror	ax,cl
X	mov	bx,4+4(bp)	! size in dx:bx
X	mov	dx,4+4+2(bp)
X	test	dx,#notop(HCHIGH_MASK)
X	jz	over_cm_reduce
X	movb	dl,#HCHIGH_MASK
X	mov	bx,#0xFFFF
Xover_cm_reduce:
X	andb	bl,#HCLOW_MASK	! cx = size in hclicks = size / 16 % 0x10000
X	orb	bl,dl
X	ror	bx,cl
X	mov	cx,bx
X	push	cx		! save size in clicks
X	mov	bx,4(bp)	! bx = base offset = base % 16
X	and	bx,#OFF_MASK
Xcm_loop:
X	mov	ds,ax
X	movb	dl,#TEST1PATTERN
X	xchgb	dl,(bx)		! write test pattern, remember original value
X	xchgb	dl,(bx)		! restore original value, read test pattern
X	cmpb	dl,#TEST1PATTERN	! must agree if good real memory
X	jnz	cm_exit		! if different, memory is unusable
X	movb	dl,#TEST2PATTERN
X	xchgb	dl,(bx)
X	xchgb	dl,(bx)
X	cmpb	dl,#TEST2PATTERN
X	jnz	cm_exit
X	inc	ax		! next segment, test for wraparound at 1M
X	loopnz	cm_loop
Xcm_exit:
X	pop	ax
X	sub	ax,cx		! verified size in phys_clicks
Xcm_1exit:
X	movb	dl,ah		! convert to phys_bytes in dx:ax
X	movb	cl,#HCLICK_SHIFT
X	shl	ax,cl
X	shr	dx,cl
X	and	dx,#HCHIGH_MASK
X	pop	ds
X	pop	bp
X	ret
X
X
X!*===========================================================================*
X!*				cim_at_wini				     *
X!*				cim_floppy				     *
X!*				cim_printer				     *
X!*				cim_xt_wini				     *
X!*===========================================================================*
X! All these routines are meant to be called from the task level where
X! interrupts should not be globally disabled, so they return with interrupts
X! enabled.
X
X! PUBLIC void cim_at_wini();
X! Clear the AT winchester interrupt mask.
X
X_cim_at_wini:
X	cli
X	inb	INT2_MASK
X	andb	al,#notop(AT_WINI_MASK)
X	outb	INT2_MASK
X	sti
X	ret
X
X! PUBLIC void cim_floppy();
X! Clear the AT winchester interrupt mask.
X
X_cim_floppy:
X	cli
X	inb	INT_CTLMASK
X	andb	al,#notop(FLOPPY_MASK)
X	outb	INT_CTLMASK
X	sti
X	ret
X
X! PUBLIC void cim_printer();
X! Clear the printer interrupt mask.
X
X_cim_printer:
X	cli
X	inb	INT_CTLMASK
X#if ASLD
X	andb	al,#notop(PRINTER_MASK)
X#else
X	andb	al,#notop(PRINTER_MASK) & 0xFF
X#endif
X	outb	INT_CTLMASK
X	sti
X	ret
X
X! PUBLIC void cim_xt_wini();
X! Clear the xt_wini interrupt mask.
X
X_cim_xt_wini:
X	cli
X	inb	INT_CTLMASK
X	andb	al,#notop(XT_WINI_MASK)
X	outb	INT_CTLMASK
X	sti
X	ret
X
X
X!*===========================================================================*
X!*				cp_mess					     *
X!*===========================================================================*
X! PUBLIC void cp_mess(int src, phys_clicks src_clicks, vir_bytes src_offset,
X!		      phys_clicks dst_clicks, vir_bytes dst_offset);
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!
X! Note that the message size, 'Msize' is in WORDS (not bytes) and must be set
X! correctly.  Changing the definition of message in the type file and not
X! changing it here will lead to total disaster.
X
X_cp_mess:
X	push es			! save es
X	push ds			! save ds
X	mov bx,sp		! index off bx because machine can't use sp
X	push si			! save si
X	push di			! save di
X
X	mov	ax,12(bx)	! destination click
X#if HCLICK_SHIFT > CLICK_SHIFT
X#error /* Small click sizes are not supported (right shift will lose bits). */
X#endif
X#if HCLICK_SHIFT < CLICK_SHIFT
X	movb	cl,#CLICK_SHIFT-HCLICK_SHIFT
X	shl	ax,cl		! destination segment
X#endif
X	mov	es,ax
X	mov	di,14(bx)	! offset of destination message
X
X! Be careful not to destroy ds before we're finished with the bx pointer.
X! We're using bx and not the more natural bp to save pushing bp.
X
X	mov	ax,6(bx)	! process number of sender
X	mov	si,10(bx)	! offset of source message
X	mov	bx,8(bx)	! source click (finished with bx as a pointer)
X#if HCLICK_SHIFT < CLICK_SHIFT
X	shl	bx,cl		! source segment
X#endif
X	mov	ds,bx
X
X	stos			! copy sender's process number to dest message
X	add si,*2		! don't copy first word
X	mov cx,*Msize-1		! remember, first word doesn't count
X	rep			! iterate cx times to copy 11 words
X	movw			! copy the message
X	pop di			! restore di
X	pop si			! restore si
X	pop ds			! restore ds
X	pop es			! restore es	
X	ret			! that's all folks!
X
X
X!*===========================================================================*
X!*				exit					     *
X!*===========================================================================*
X! PUBLIC void exit();
X! Some library routines use exit, so provide a dummy version.
X! Actual calls to exit cannot occur in the kernel.
X! Same for .fat
X! Same for .trp.
X
X_exit:
X.fat:
X.trp:
X	sti
X	jmp _exit
X
X!*===========================================================================*
X!*				get_byte				     *
X!*===========================================================================*
X! PUBLIC u16_t get_byte(u16_t segment, u8_t *offset);
X! Load and return the byte at the far pointer  segment:offset.
X
X_get_byte:
X	mov	cx,ds		! save ds
X	pop	dx		! return adr
X	pop	ds		! segment
X	pop	bx		! offset
X	sub	sp,#2+2		! adjust for parameters popped
X	movb	al,(bx)		! load the byte to return
X	xorb	ah,ah		! extend the u8_t to a u16_t
X	mov	ds,cx		! restore ds
X	jmp	(dx)		! return
X
X
X!*===========================================================================*
X!*				in_byte					     *
X!*===========================================================================*
X! PUBLIC unsigned in_byte(port_t port);
X! Read an (unsigned) byte from the i/o port  port  and return it.
X
X_in_byte:
X	pop	bx
X	pop	dx		! port
X	dec	sp
X	dec	sp
X	inb			! input 1 byte
X	subb	ah,ah		! unsign extend
X	jmp	(bx)
X!*===========================================================================*
X!*				in_word					     *
X!*===========================================================================*
X! PUBLIC unsigned short in_word(port_t port);
X! Read an (unsigned) word from the i/o port and return it.
X
X_in_word:
X	pop	bx
X	pop	dx		! port
X	dec	sp
X	dec	sp		! added to new klib.x 3/21/91 d.e.c.
X	inw			! input 1 word no sign extend needed
X	jmp	(bx)
X
X
X!*===========================================================================*
X!*				klib_1hook				     *
X!*===========================================================================*
X! PUBLIC void klib_1hook();
X! Initialize klib from real mode for real or protected mode,
X! Do nothing for real mode.
X! For protected mode, patch some real mode functions at their starts to jump
X! to their protected mode equivalents, according to the patch table.
X
X_klib_1hook:
X	cmpb	_protected_mode,#0
X	jz	hook1_done
X	mov	si,#patch_table
X	lods			! original function
Xpatch1:
X	mov	bx,ax
X	cseg
X	movb	(bx),#JMP_OPCODE
X	lods			! new function - target of jump
X	sub	ax,bx		! relative jump
X	sub	ax,#3		! adjust by length of jump instruction
X	cseg
X	mov	1(bx),ax
X	lods			! next original function
X	test	ax,ax
X	jnz	patch1
Xhook1_done:
X	ret
X
X
X!*===========================================================================*
X!*				klib_2hook				     *
X!*===========================================================================*
X! PUBLIC void klib_prot_mode_init();
X! Initialize klib protected real mode for real or protected mode,
X! Do nothing for real mode.
X! For protected mode, load idt, task reg and flags.
X
X_klib_2hook:
X	cmpb	_protected_mode,#0
X	jz	hook2_done
X	deflidt	(_gdt+BIOS_IDT_SELECTOR) ! loaded by BIOS, but in wrong mode!
X	mov	ax,#TSS_SELECTOR	! no other TSS is used
X	defltrax
X	sub	ax,ax		! zero
X	push	ax		! set flags to known good state
X	popf			! especially, clear nested task and int enable
Xhook2_done:
X	ret
X
X
X!*===========================================================================*
X!*				lock					     *
X!*===========================================================================*
X! PUBLIC void lock();
X! Disable CPU interrupts.
X_lock:
X	cli			! disable interrupts
X	ret			! return to caller
X
X
X!*===========================================================================*
X!*				phys_copy				     *
X!*===========================================================================*
X! PUBLIC void phys_copy(phys_bytes source, phys_bytes destination,
X!			phys_bytes bytecount);
X! Copy a block of physical memory.
X
XSRCLO	=	4
XSRCHI	=	6
XDESTLO	=	8
XDESTHI	=	10
XCOUNTLO	=	12
XCOUNTHI	=	14
X
X_phys_copy:
X	push	bp		! save only registers required by C
X	mov	bp,sp		! set bp to point to source arg less 4
X
X! check for extended memory
X
X	mov	ax,SRCHI(bp)
X	or	ax,DESTHI(bp)
X	test	ax,#EM_MASK
X	jnz	to_em_xfer
X
X	push	si		! save si
X	push	di		! save di
X	push	ds		! save ds
X	push	es		! save es
X
X	mov	ax,SRCLO(bp)	! dx:ax = source address (dx is NOT segment)
X	mov	dx,SRCHI(bp)
X	mov	si,ax		! si = source offset = address % 16
X	and	si,#OFF_MASK
X!	andb	dl,#HCHIGH_MASK	| ds = source segment = address / 16 % 0x10000
X				! mask is unnecessary because of EM_MASK test
X	andb	al,#HCLOW_MASK
X	orb	al,dl		! now bottom 4 bits of dx are in ax
X	movb	cl,#HCLICK_SHIFT ! rotate them to the top 4
X	ror	ax,cl
X	mov	ds,ax
X
X	mov	ax,DESTLO(bp)	! dx:ax = destination addr (dx is NOT segment)
X	mov	dx,DESTHI(bp)
X	mov	di,ax		! di = dest offset = address % 16
X	and	di,#OFF_MASK
X!	andb	dl,#HCHIGH_MASK	| es = dest segment = address / 16 % 0x10000
X	andb	al,#HCLOW_MASK
X	orb	al,dl
X	ror	ax,cl
X	mov	es,ax
X
X	mov	ax,COUNTLO(bp)	! dx:ax = remaining count
X	mov	dx,COUNTHI(bp)
X
X! copy upwards (can't handle overlapped copy)
X
Xpc_loop:
X	mov	cx,ax		! provisional count for this iteration
X	test	ax,ax		! if count >= 0x8000, only do 0x8000 per iter
X	js	pc_bigcount	! low byte already >= 0x8000
X	test	dx,dx
X	jz	pc_upcount	! less than 0x8000
Xpc_bigcount:
X	mov	cx,#0x8000	! use maximum count per iteration
Xpc_upcount:
X	sub	ax,cx		! update count
X	sbb	dx,#0		! can't underflow, so carry clear now for rcr
X	rcr	cx,#1		! count in words, carry remembers if byte
X	jnb	pc_even		! no odd byte
X	movb			! copy odd byte
Xpc_even:
X	rep			! copy 1 word at a time
X	movw			! word copy
X
X	mov	cx,ax		! test if remaining count is 0
X	or	cx,dx
X	jnz	pc_more		! more to do
X
X	pop	es		! restore es
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
Xpc_more:
X	sub	si,#0x8000	! adjust pointers so the offset doesn't
X	mov	cx,ds		! overflow in the next 0x8000 bytes
X	add	cx,#0x800	! pointers end up same physical location
X	mov	ds,cx		! the current offsets are known >= 0x8000
X	sub	di,#0x8000	! since we just copied that many
X	mov	cx,es
X	add	cx,#0x800
X	mov	es,cx
X	jmp	pc_loop		! start next iteration
X
X! When source or target is above 1M, join em_xfer.
X! Rely on MM and MEMTASK not to provide bad parameters, and omit checking the
X! following:
X!	count must be even
X!	count must be < 64K
X!	machine must be AT-compatible
X! which are not required for phys_copy.
X
Xto_em_xfer:
X	shr	COUNTLO(bp),#1	! convert count to words
X	pop	bp		! stack frame now agrees with em_xfer's
X	jmp	_em_xfer
X
X
X!*===========================================================================*
X!*				em_xfer					     *
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.  The BIOS call is "faked" by pushing
X!  the processor flags on the stack and then doing a far call through the
X!  saved vector table to the actual BIOS location.  An actual INT 15h would
X!  get a MINIX complaint from an unexpected trap.
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, except it may take
X!  too long and cause interrupts to be lost.
X!
X	.text
Xgdt:				! Begin global descriptor table
X					! Dummy descriptor
X	.data2 0		! segment length (limit)
X	.data2 0		! bits 15-0 of physical address
X	.data1 0		! bits 23-16 of physical address
X	.data1 0		! access rights byte
X	.data2 0		! reserved
X					! descriptor for GDT itself
X	.data2 0		! segment length (limit)
X	.data2 0		! bits 15-0 of physical address
X	.data1 0		! bits 23-16 of physical address
X	.data1 0		! access rights byte
X	.data2 0		! reserved
Xsrc:					! source descriptor
Xsrcsz:	.data2 0		! segment length (limit)
Xsrcl:	.data2 0		! bits 15-0 of physical address
Xsrch:	.data1 0		! bits 23-16 of physical address
X	.data1 0x93	! access rights byte
X	.data2 0		! reserved
Xtgt:					! target descriptor
Xtgtsz:	.data2 0		! segment length (limit)
Xtgtl:	.data2 0		! bits 15-0 of physical address
Xtgth:	.data1 0		! bits 23-16 of physical address
X	.data1 0x93	! access rights byte
X	.data2 0		! reserved
X					! BIOS CS descriptor
X	.data2 0		! segment length (limit)
X	.data2 0		! bits 15-0 of physical address
X	.data1 0		! bits 23-16 of physical address
X	.data1 0		! access rights byte
X	.data2 0		! reserved
X					! stack segment descriptor
X	.data2 0		! segment length (limit)
X	.data2 0		! bits 15-0 of physical address
X	.data1 0		! bits 23-16 of physical address
X	.data1 0		! access rights byte
X	.data2 0		! reserved
X
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	push	cx
X!
X!  Pick up source and destination addresses and update descriptor tables
X!
X	mov ax,4(bp)
X	cseg
X	mov srcl,ax
X	mov ax,6(bp)
X	cseg
X	movb srch,al
X	mov ax,8(bp)
X	cseg
X	mov tgtl,ax
X	mov ax,10(bp)
X	cseg
X	movb tgth,al
X!
X!  Update descriptor table segment limits
X!
X	mov cx,12(bp)
X	mov ax,cx
X	add ax,ax
X	cseg
X	mov tgtsz,ax
X	cseg
X	mov srcsz,ax
X
X!
X!  Now do actual DOS call
X!
X	push cs
X	pop es
X	mov si,#gdt
X	movb ah,#EM_XFER_FUNC
X	pushf			! fake interrupt
X	callf	@_vec_table+4*EM_XFER_VEC
X
X!
X!  All done, return to caller.
X!
X
X	pop	cx		! restore registers
X	pop	es
X	pop	si
X	mov	sp,bp
X	pop	bp
X	ret
X
X
X!*===========================================================================*
X!*				mem_rdw					     *
X!*===========================================================================*
X! PUBLIC u16_t mem_rdw(u16_t segment, u16_t *offset);
X! Load and return the word at the far pointer  segment:offset.
X
X_mem_rdw:
X	mov	cx,ds		! save ds
X	pop	dx		! return adr
X	pop	ds		! segment
X	pop	bx		! offset
X	sub	sp,#2+2		! adjust for parameters popped
X	mov	ax,(bx)		! load the word to return
X	mov	ds,cx		! restore ds
X	jmp	(dx)		! return
X
X
X!*===========================================================================*
X!*				out_byte				     *
X!*===========================================================================*
X! PUBLIC void out_byte(port_t port, int value);
X! Write  value  (cast to a byte)  to the I/O port  port.
X
X_out_byte:
X	pop	bx
X	pop	dx		! port
X	pop	ax		! value
X	sub	sp,#2+2
X	outb			! output 1 byte
X	jmp	(bx)
X
X
X!*===========================================================================*
X!*				out_word				     *
X!*===========================================================================*
X! PUBLIC void out_word(port_t port, int value);
X! Write  value  (cast to a word)  to the I/O port  port.
X
X_out_word:
X	pop	bx
X	pop	dx		! port
X	pop	ax		! value
X	sub	sp,#2+2
X	outw			! output 1 word
X	jmp	(bx)
X
X
X!*===========================================================================*
X!*				port_read				     *
X!*===========================================================================*
X! PUBLIC void port_read(port_t port, phys_bytes destination,unsigned bytcount);
X! Transfer data from (hard disk controller) port to memory.
X
X_port_read:
X	push	bp
X	mov	bp,sp
X	push	cx
X	push	dx
X	push	di
X	push	es
X	mov	ax,4+2(bp)	! destination addr in dx:ax
X	mov	dx,4+2+2(bp)
X	mov	di,ax		! di = dest offset = address % 16
X	and	di,#OFF_MASK
X	andb	dl,#HCHIGH_MASK	! es = dest segment = address / 16 % 0x10000
X	andb	al,#HCLOW_MASK
X	orb	al,dl
X	movb	cl,#HCLICK_SHIFT
X	ror	ax,cl
X	mov	es,ax
X
X	mov	cx,4+2+4(bp)	! count in bytes
X	shr	cx,#1		! count in words
X	mov	dx,4(bp)	! port to read from
X	rep
X	insw
X	pop	es
X	pop	di
X	pop	dx
X	pop	cx
X	mov	sp,bp
X	pop	bp
X	ret
X
X
X!*===========================================================================*
X!*				port_write				     *
X!*===========================================================================*
X! PUBLIC void port_write(port_t port, phys_bytes source, unsigned bytcount);
X! Transfer data from memory to (hard disk controller) port.
X
X_port_write:
X	push	bp
X	mov	bp,sp
X	push	cx
X	push	dx
X	push	si
X	push	ds
X	mov	ax,4+2(bp)	! source addr in dx:ax
X	mov	dx,4+2+2(bp)
X	mov	si,ax		! si = source offset = address % 16
X	and	si,#OFF_MASK
X	andb	dl,#HCHIGH_MASK	! ds = source segment = address / 16 % 0x10000
X	andb	al,#HCLOW_MASK
X	orb	al,dl
X	movb	cl,#HCLICK_SHIFT
X	ror	ax,cl
X	mov	ds,ax
X	mov	cx,4+2+4(bp)	! count in bytes
X	shr	cx,#1		! count in words
X	mov	dx,4(bp)	! port to read from
X	rep
X	outsw
X	pop	ds
X	pop	si
X	pop	dx
X	pop	cx
X	mov	sp,bp
X	pop	bp
X	ret
X
X
X!*===========================================================================*
X!*				reset					     *
X!*===========================================================================*
X! PUBLIC void reset();
X! Reset the system.
X! This only works in real mode.
X! For protected mode, it would be necessary to trap to privilege 0, then do
X! something fatal like loading an IDT with offset 0 and interrupting.
X
X_reset:
X	jmpf	0,0xFFFF
X
X
X!*===========================================================================*
X!*				scr_down & scr_up			     *
X!*===========================================================================*
X! PUBLIC void scr_down(unsigned videoseg, int source, int dest, int count);
X! Scroll the screen down one line.
X!
X! PUBLIC void scr_up(unsigned videoseg, int source, int dest, int count);
X! Scroll the screen up one line.
X!
X! These are identical except scr_down() must reverse the direction flag
X! during the copy to avoid problems with overlap.
X
X_scr_down:
X	std
X_scr_up:
X	push	bp
X	mov	bp,sp
X	push	si
X	push	di
X	push	ds
X	push	es
X	mov	ax,4(bp)	! videoseg (selector for video ram)
X	mov	si,6(bp)	! source (offset within video ram)
X	mov	di,8(bp)	! dest (offset within video ram)
X	mov	cx,10(bp)	! count (in words)
X	mov	ds,ax		! set source and dest segs to videoseg
X	mov	es,ax
X	rep			! do the copy
X	movw
X	pop	es
X	pop	ds
X	pop	di
X	pop	si
X	pop	bp
X	cld			! restore (unnecessarily for scr_up)
X	ret
X
X
X!*===========================================================================*
X!*				sim_printer				     *
X!*===========================================================================*
X! PUBLIC void sim_printer();
X! Set the printer interrupt mask.
X! This is meant to be called from the task level, so it returns with
X! interrupts enabled.
X
X_sim_printer:
X	cli
X	inb	INT_CTLMASK
X	orb	al,#PRINTER_MASK
X	outb	INT_CTLMASK
X	sti
X	ret
X
X
X!*===========================================================================*
X!*				tasim_printer				     *
X!*===========================================================================*
X! PUBLIC unsigned tasim_printer();
X! Set the printer interrupt mask, indivisibly with getting its old value.
X! Return old value.
X! This is meant to be called from the task level, so it returns with
X! interrupts enabled.
X! This might not work for multiple processors, unlike test_and_set().
X
X_tasim_printer:
X	cli
X	inb	INT_CTLMASK
X	movb	ah,al
X	orb	al,#PRINTER_MASK
X	outb	INT_CTLMASK
X	sti
X	movb	al,ah
X	and	ax,#PRINTER_MASK
X	ret
X
X
X!*===========================================================================*
X!*				test_and_set				     *
X!*===========================================================================*
X! PUBLIC int test_and_set(int *flag);
X! Set the flag to TRUE, indivisibly with getting its old value.
X! Return old flag.
X
X_test_and_set:
X	pop	dx
X	pop	bx
X	sub	sp,#2
X	mov	ax,#1
X	xchg	ax,(bx)
X	jmp	(dx)
X
X
X!*===========================================================================*
X!*				unlock					     *
X!*===========================================================================*
X! PUBLIC void unlock();
X! Enable CPU interrupts.
X
X_unlock:
X	sti			! enable interrupts
X	ret			! return to caller
X
X
X!*===========================================================================*
X!*				vid_copy				     *
X!*===========================================================================*
X! PUBLIC void vid_copy(char *buffer, unsigned videobase, int offset,
X!		       int words);
X! where
X!     'buffer'    is a pointer to the (character, attribute) pairs
X!     'videobase' is 0xB800 for color and 0xB000 for monochrome displays
X!     'offset'    tells where within video ram to copy the data
X!     'words'     tells how many words to copy
X! if buffer is zero, the fill char (blank_color) is used
X!
X! This routine takes a string of (character, attribute) pairs and writes them
X! onto the screen.  For a snowy display, the writing only takes places during
X! the vertical retrace interval, to avoid displaying garbage on the screen.
X
X_vid_copy:
X	push bp			! we need bp to access the parameters
X	mov bp,sp		! set bp to sp for indexing
X	push si			! save the registers
X	push di			! save di
X	push bx			! save bx
X	push cx			! save cx
X	push dx			! save dx
X	push es			! save es
Xvid.0:	mov si,4(bp)		! si = pointer to data to be copied
X	mov es,6(bp)		! load es NOW: int routines may NOT ruin it
X	mov di,8(bp)		! di = offset within video ram
X	and di,_vid_mask	! only 4K or 16K counts
X	mov cx,10(bp)		! cx = word count for copy loop
X	mov dx,#0x3DA		! prepare to see if color display is retracing
X
X	mov bx,di		! see if copy will run off end of video ram
X	add bx,cx		! compute where copy ends
X	add bx,cx		! bx = last character copied + 1
X	sub bx,_vid_mask	! bx = # characters beyond end of video ram
X	sub bx,#1		! note: dec bx doesn't set flags properly
X				! it DOES for jle!!
X	jle vid.1		! jump if no overrun
X	sar bx,#1		! bx = # words that don't fit in video ram
X	sub cx,bx		! reduce count by overrun
X
Xvid.1:	push cx			! save actual count used for later
X	cmpb _snow,#0		! skip vertical retrace test if no snow
X	jz vid.4
X
X!vid.2:	in			| with a color display, you can only copy to
X!	test al,*010		| the video ram during vertical retrace, so
X!	jnz vid.2		| wait for start of retrace period.  Bit 3 of
Xvid.3:	in			! 0x3DA is set during retrace.  First wait
X	testb al,*010		! until it is off (no retrace), then wait
X	jz vid.3		! until it comes on (start of retrace)
X
Xvid.4:	cmp si,#0		! si = 0 means blank the screen
X	je vid.7		! jump for blanking
X	lock			! this is a trick for the IBM PC simulator only
X	inc vidlock		! 'lock' indicates a video ram access
X	rep			! this is the copy loop
X	movw			! ditto
X
Xvid.5:	pop si			! si = count of words copied
X	cmp bx,#0		! if bx < 0, then no overrun and we are done
X	jle vid.6		! jump if everything fit
X	mov 10(bp),bx		! set up residual count
X	mov 8(bp),#0		! start copying at base of video ram
X	cmp 4(bp),#0		! NIL_PTR means store blanks
X	je vid.0		! go do it
X	add si,si		! si = count of bytes copied
X	add 4(bp),si		! increment buffer pointer
X	jmp vid.0		! go copy some more
X
Xvid.6:	pop es			! restore registers
X	pop dx			! restore dx
X	pop cx			! restore cx
X	pop bx			! restore bx
X	pop di			! restore di
X	pop si			! restore si
X	pop bp			! restore bp
X	ret			! return to caller
X
Xvid.7:	mov ax,_blank_color	! ax = blanking character
X	rep			! copy loop
X	stos			! blank screen
X	jmp vid.5		! done
X
X
X!*===========================================================================*
X!*			      wait_retrace				     *
X!*===========================================================================*
X! PUBLIC void wait_retrace();
X! Wait for the *start* of retrace period.
X! The VERTICAL_RETRACE_MASK of the color vid_port is set during retrace.
X! First wait until it is off (no retrace).
X! Then wait until it comes on (start of retrace).
X! We can't afford to worry about interrupts.
X
X_wait_retrace:
X	mov	dx,_vid_port
X	orb	dl,#COLOR_STATUS_PORT & 0xFF
Xwait_no_retrace:
X	inb
X	testb	al,#VERTICAL_RETRACE_MASK
X	jnz	wait_no_retrace
Xwait_retrace:
X	inb
X	testb	al,#VERTICAL_RETRACE_MASK
X	jz	wait_retrace
X	ret
X
X
X!*===========================================================================*
X!*			variants for protected mode			     *
X!*===========================================================================*
X! Some routines are different in protected mode.
X! The only essential difference is the handling of segment registers.
X! One complication is that the method of building segment descriptors is not
X! reentrant, so the protected mode versions must not be called by interrupt
X! handlers.
X
X!*===========================================================================*
X!*				p_check_mem				     *
X!*===========================================================================*
XPCM_DENSITY	=	256	! resolution of check
X				! the shift logic depends on this being 256
Xp_check_mem:
X	pop	bx
X	pop	_gdt+DS_286_OFFSET+DESC_BASE
X	pop	ax		! pop base into base of source descriptor
X	movb	_gdt+DS_286_OFFSET+DESC_BASE_MIDDLE,al
X	pop	cx		! byte count in dx:cx
X	pop	dx
X	sub	sp,#4+4
X	push	bx
X	push	ds
X
X	sub	ax,ax		! prepare for early exit
X	test	dx,#0xFF00
X	jnz	pcm_1exit	! can't handle bases above 16M
X	movb	cl,ch		! divide size by 256 and discard high byte
X	movb	ch,dl
X	push	cx		! save divided size
X	sub	bx,bx		! test bytes at bases of segments
Xpcm_loop:
X	mov	ax,#DS_286_SELECTOR
X	mov	ds,ax
X	movb	dl,#TEST1PATTERN
X	xchgb	dl,(bx)		! write test pattern, remember original value
X	xchgb	dl,(bx)		! restore original value, read test pattern
X	cmpb	dl,#TEST1PATTERN	! must agree if good real memory
X	jnz	pcm_exit	! if different, memory is unusable
X	movb	dl,#TEST2PATTERN
X	xchgb	dl,(bx)
X	xchgb	dl,(bx)
X	cmpb	dl,#TEST2PATTERN
X	jnz	pcm_exit
X	eseg		! next segement, test for wraparound at 16M
X	add	_gdt+DS_286_OFFSET+DESC_BASE,#PCM_DENSITY
X	eseg		! assuming es == old ds
X	adcb	_gdt+DS_286_OFFSET+DESC_BASE_MIDDLE,#0
X	loopnz	pcm_loop
X
Xpcm_exit:
X	pop	ax
X	sub	ax,cx		! verified size in multiples of PCM_DENSITY
Xpcm_1exit:
X	movb	dl,ah		! convert to phys_bytes in dx:ax
X	subb	dh,dh
X	movb	ah,al
X	movb	al,dh
X	pop	ds
X	ret
X
X
X!*===========================================================================*
X!*				p_cp_mess				     *
X!*===========================================================================*
X! The real mode version attempts to be efficient by passing raw segments but
X! that just gets in the way here.
X
Xp_cp_mess:
X	pop	dx
X	pop	bx		! proc
X	pop	cx		! source clicks
X	pop	ax		! source offset
X#if CLICK_SHIFT != HCLICK_SHIFT + 4
X#error /* the only click size supported is 256, to avoid slow shifts here */
X#endif
X	addb	ah,cl		! calculate source offset
X	adcb	ch,#0 		! and put in base of source descriptor
X	mov	_gdt+DS_286_OFFSET+DESC_BASE,ax
X	movb	_gdt+DS_286_OFFSET+DESC_BASE_MIDDLE,ch
X	pop	cx		! destination clicks
X	pop	ax		! destination offset
X	addb	ah,cl		! calculate destination offset
X	adcb	ch,#0 		! and put in base of destination descriptor
X	mov	_gdt+ES_286_OFFSET+DESC_BASE,ax
X	movb	_gdt+ES_286_OFFSET+DESC_BASE_MIDDLE,ch
X	sub	sp,#2+2+2+2+2
X
X	push	ds
X	push	es
X	mov	ax,#DS_286_SELECTOR
X	mov	ds,ax
X	mov	ax,#ES_286_SELECTOR
X	mov	es,ax
X
X	eseg
X	mov	0,bx		! sender's proc no. from arg, not msg
X	mov	ax,si
X	mov	bx,di
X	mov	si,#2		! src offset is now 2 relative to start of seg
X	mov	di,si		! and destination offset
X	mov	cx,#Msize-1	! word count
X	rep
X	movw
X	mov	di,bx
X	mov	si,ax
X	pop	es
X	pop	ds
X	jmp	(dx)
X
X
X!*===========================================================================*
X!*				p_phys_copy				     *
X!*===========================================================================*
Xp_phys_copy:
X	pop	dx
X	pop	_gdt+DS_286_OFFSET+DESC_BASE
X	pop	ax		! pop source into base of source descriptor
X	movb	_gdt+DS_286_OFFSET+DESC_BASE_MIDDLE,al
X	pop	_gdt+ES_286_OFFSET+DESC_BASE
X	pop	ax		! pop destination into base of dst descriptor
X	movb	_gdt+ES_286_OFFSET+DESC_BASE_MIDDLE,al
X	pop	cx		! byte count in bx:cx
X	pop	bx
X	sub	sp,#4+4+4
X
X	push	di
X	push	si
X	push	es
X	push	ds
X	sub	si,si		! src offset is now 0 relative to start of seg
X	mov	di,si		! and destination offset
X	jmp	ppc_next
X
X! It is too much trouble to align the segment bases, so word alignment is hard.
X! Avoiding the book-keeping for alignment may be good anyway.
X
Xppc_large:
X	push	cx
X	mov	cx,#0x8000	! copy a large chunk of this many words
X	rep
X	movw
X	pop	cx
X	dec	bx
X	pop	ds		! update the descriptors
X	incb	_gdt+DS_286_OFFSET+DESC_BASE_MIDDLE
X	incb	_gdt+ES_286_OFFSET+DESC_BASE_MIDDLE
X	push	ds
Xppc_next:
X	mov	ax,#DS_286_SELECTOR	! (re)load the selectors
X	mov	ds,ax
X	mov	ax,#ES_286_SELECTOR
X	mov	es,ax
X	test	bx,bx
X	jnz	ppc_large
X
X	shr	cx,#1		! word count
X	rep
X	movw			! move any leftover words
X	rcl	cx,#1		! restore old bit 0
X	rep
X	movb			! move any leftover byte
X	pop	ds
X	pop	es
X	pop	si
X	pop	di
X	jmp	(dx)
X
X
X!*===========================================================================*
X!*				p_port_read				     *
X!*===========================================================================*
Xp_port_read:
X	pop	bx
X	pop	dx		! port
X	pop	_gdt+ES_286_OFFSET+DESC_BASE
X	pop	ax		! pop destination into base of dst descriptor
X	movb	_gdt+ES_286_OFFSET+DESC_BASE_MIDDLE,al
X	pop	cx		! byte count
X	sub	sp,#2+4+2
X	push	es
X	mov	ax,#ES_286_SELECTOR
X	mov	es,ax
X	mov	ax,di
X	sub	di,di		! dst offset is now 0 relative to start of seg
X	shr	cx,#1		! word count
X	rep
X	insw			! read everything
X	mov	di,ax
X	pop	es
X	jmp	(bx)
X
X
X!*===========================================================================*
X!*				p_port_write				     *
X!*===========================================================================*
Xp_port_write:
X	pop	bx
X	pop	dx		! port
X	pop	_gdt+DS_286_OFFSET+DESC_BASE
X	pop	ax		! pop offset into base of source descriptor
X	movb	_gdt+DS_286_OFFSET+DESC_BASE_MIDDLE,al
X	pop	cx		! byte count, discard high word
X	sub	sp,#2+4+2
X	push	ds
X	mov	ax,#DS_286_SELECTOR
X	mov	ds,ax
X	mov	ax,si
X	sub	si,si		! src offset is now 0 relative to start of seg
X	shr	cx,#1		! word count
X	rep
X	outsw			! write everything
X	mov	si,ax
X	pop	ds
X	jmp	(bx)
X
X
X!*===========================================================================*
X!*				data					     *
X!*===========================================================================*
X	.data
Xpatch_table:			! pairs (old function, new function)
X	.data2	_check_mem, p_check_mem
X	.data2	_cp_mess, p_cp_mess
X	.data2	_phys_copy, p_phys_copy
X	.data2	_port_read, p_port_read
X	.data2	_port_write, p_port_write
X	.data2	_restart, p_restart	! in mpx file
X	.data2	save, p_save	! in mpx file
X	.data2	0		! end of table
Xsplimit:			! stack limit for current task (kernel only)
X	.data2 0	
Xvidlock:			! dummy variable for use with lock prefix
X	.data2 0
/
echo x - klib88.x.kr
sed '/^X/s///' > klib88.x.kr << '/'
X| This file contains a number of assembly code utility routines needed by the
X| kernel.  They are:
X.define	_bios13		| make BIOS 13 call for disk I/O (real mode only)
X.define	_build_sig	| build 4 word structure pushed onto stack for signals
X.define	_check_mem	| check a block of memory, return the valid size
X.define	_cim_at_wini	| clear the AT winchester interrupt mask
X.define	_cim_floppy	| clear the floppy interrupt mask
X.define	_cim_printer	| clear the printer interrupt mask
X.define	_cim_xt_wini	| clear the XT winchester interrupt mask
X.define	_cp_mess	| copies messages from source to destination
X.define	_exit		| dummy for library routines
X.define	.fat		| dummy for library routines
X.define	_get_byte	| read a byte from anywhere and return it
X.define	_in_byte	| read a byte from a port and return it
X.define _in_word	| read a word from a port and return it
X.define	_klib_1hook	| init from real mode for real or protected mode
X.define	_klib_2hook	| init from protected mode for real or protected mode
X.define	_lock		| disable interrupts
X.define	_mem_rdw	| copy one word from [segment:offset]
X.define	_out_byte	| write a byte to a port
X.define	_out_word	| write a word to a port
X.define	_phys_copy	| copy data from anywhere to anywhere in memory
X.define	_port_read	| transfer data from (disk controller) port to memory
X.define	_port_write	| transfer data from memory to (disk controller) port
X.define	_reset		| reset the system (real mode only)
X.define	_scr_down	| scroll screen a line down (in software, by copying)
X.define	_scr_up		| scroll screen a line up (in software, by copying)
X.define	_sim_printer	| set the printer interrupt mask
X.define	_tasim_printer	| test and set the printer interrupt mask
X.define	_test_and_set	| test and set locking primitive on a word in memory
X.define	.trp		| dummy for library routines
X.define	_unlock		| enable interrupts
X.define	_vid_copy	| copy data to video ram (perhaps during retrace only)
X.define	_wait_retrace	| wait for retrace interval
X| The routines only guarantee to preserve the registers the 'C' compiler
X| expects to be preserved (si, di, bp, sp, segment registers, and direction
X| bit in the flags), though some of the older ones preserve bx, cx and dx.
X#include <minix/config.h>
X#include <minix/const.h>
X#include "const.h"
X#include "sconst.h"
X#include "protect.h"
X#if INTEL_32BITS
X#error /* this is not the 32-bit version */
X#endif
X#define DS_286_OFFSET	DS_286_INDEX*DESC_SIZE
X#define ES_286_OFFSET	ES_286_INDEX*DESC_SIZE
X#define EM_MASK		0xFFF0	/* extended memory mask for hi word */
X#define EM_XFER_VEC	0x15	/* copy (normal or extended) memory */
X#	define EM_XFER_FUNC	0x87
X#define JMP_OPCODE	0xE9	/* opcode used for patching */
X#define OFF_MASK	0x000F	/* offset mask for phys_b -> hclick:offset */
X| imported functions
X.extern		p_restart
X.extern		p_save
X.extern		_restart
X.extern		save
X| exported variables
X.bss
X.define		splimit
X| imported variables
X.extern		_Ax, _Bx, _Cx, _Dx, _Es
X.extern		_blank_color
X.extern		_gdt
X.extern		_protected_mode
X.extern		_snow
X.extern		_vec_table
X.extern		_vid_mask
X.extern		_vid_port
X.text
X|*===========================================================================*
X|*				bios13					     *
X|*===========================================================================*
X| PUBLIC void bios13();
X_bios13: | make a BIOS 0x13 call for disk I/O
Xpush ax			| save the registers
Xpush bx
Xpush cx
Xpush dx
Xpush es
Xmov ax,_Ax		| load parameters
Xmov bx,_Bx
Xmov cx,_Cx
Xmov dx,_Dx
Xmov es,_Es
Xint 0x13		| make the BIOS call
Xmov _Ax,ax		| save results
Xmov _Bx,bx
Xmov _Cx,cx
Xmov _Dx,dx
Xpop es
Xpop dx
Xpop cx
Xpop bx
Xpop ax
Xret
X|*===========================================================================*
X|*				build_sig				     *
X|*===========================================================================*
X| PUBLIC void build_sig(char *sig_stuff, struct proc *rp, int sig)
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.
X_build_sig: 
Xpush bp			| save bp
Xmov bp,sp		| set bp to sp for accessing params
Xpush bx			| save bx
Xpush si			| save si
Xmov bx,4(bp)		| bx points to sig_stuff
Xmov si,6(bp)		| si points to proc table entry
Xmov ax,8(bp)		| ax = signal number
Xmov (bx),ax		| put signal number in sig_stuff
Xmov ax,PCREG(si)	| ax = signalled process' PC
Xmov 2(bx),ax		| put pc in sig_stuff
Xmov ax,CSREG(si)	| ax = signalled process' cs
Xmov 4(bx),ax		| put cs in sig_stuff
Xmov ax,PSWREG(si)	| ax = signalled process' PSW
Xmov 6(bx),ax		| put psw in sig_stuff
Xpop si			| restore si
Xpop bx			| restore bx
Xpop bp			| restore bp
Xret			| return to caller
X|*===========================================================================*
X|*				check_mem				     *
X|*===========================================================================*
X| PUBLIC phys_bytes check_mem(phys_bytes base, phys_bytes size);
X| Check a block of memory, return the amount valid.
X| Only every 16th byte is checked.
X| The memory and initial size must be <= 1M for non-protected mode.
X| An initial size of 0 means everything.
X| This really should do some alias checks.
X_check_mem: 
Xpush	bp
Xmov	bp,sp
Xpush	ds
Xmov	dx,4+2(bp)	| base in dx:ax
Xsub	ax,ax		| prepare for early exit
Xtest	dx,#notop(HCHIGH_MASK)
Xjnz	cm_1exit	| can't handle bases above 1M
Xmov	ax,4(bp)	| ax = base segment = base / 16 % 0x10000
Xandb	al,#HCLOW_MASK
Xorb	al,dl
Xmovb	cl,#HCLICK_SHIFT
Xror	ax,cl
Xmov	bx,4+4(bp)	| size in dx:bx
Xmov	dx,4+4+2(bp)
Xtest	dx,#notop(HCHIGH_MASK)
Xjz	over_cm_reduce
Xmovb	dl,#HCHIGH_MASK
Xmov	bx,#0xFFFF
Xover_cm_reduce: 
Xandb	bl,#HCLOW_MASK	| cx = size in hclicks = size / 16 % 0x10000
Xorb	bl,dl
Xror	bx,cl
Xmov	cx,bx
Xpush	cx		| save size in clicks
Xmov	bx,4(bp)	| bx = base offset = base % 16
Xand	bx,#OFF_MASK
Xcm_loop: 
Xmov	ds,ax
Xmovb	dl,#TEST1PATTERN
Xxchgb	dl,(bx)		| write test pattern, remember original value
Xxchgb	dl,(bx)		| restore original value, read test pattern
Xcmpb	dl,#TEST1PATTERN	| must agree if good real memory
Xjnz	cm_exit		| if different, memory is unusable
Xmovb	dl,#TEST2PATTERN
Xxchgb	dl,(bx)
Xxchgb	dl,(bx)
Xcmpb	dl,#TEST2PATTERN
Xjnz	cm_exit
Xinc	ax		| next segment, test for wraparound at 1M
Xloopnz	cm_loop
Xcm_exit: 
Xpop	ax
Xsub	ax,cx		| verified size in phys_clicks
Xcm_1exit: 
Xmovb	dl,ah		| convert to phys_bytes in dx:ax
Xmovb	cl,#HCLICK_SHIFT
Xshl	ax,cl
Xshr	dx,cl
Xand	dx,#HCHIGH_MASK
Xpop	ds
Xpop	bp
Xret
X|*===========================================================================*
X|*				cim_at_wini				     *
X|*				cim_floppy				     *
X|*				cim_printer				     *
X|*				cim_xt_wini				     *
X|*===========================================================================*
X| All these routines are meant to be called from the task level where
X| interrupts should not be globally disabled, so they return with interrupts
X| enabled.
X| PUBLIC void cim_at_wini();
X| Clear the AT winchester interrupt mask.
X_cim_at_wini: 
Xcli
Xin	INT2_MASK
Xandb	al,#notop(AT_WINI_MASK)
Xout	INT2_MASK
Xsti
Xret
X| PUBLIC void cim_floppy();
X| Clear the AT winchester interrupt mask.
X_cim_floppy: 
Xcli
Xin	INT_CTLMASK
Xandb	al,#notop(FLOPPY_MASK)
Xout	INT_CTLMASK
Xsti
Xret
X| PUBLIC void cim_printer();
X| Clear the printer interrupt mask.
X_cim_printer: 
Xcli
Xin	INT_CTLMASK
X#if ASLD
Xandb	al,#notop(PRINTER_MASK)
X#else
Xandb	al,#notop(PRINTER_MASK) & 0xFF
X#endif
Xout	INT_CTLMASK
Xsti
Xret
X| PUBLIC void cim_xt_wini();
X| Clear the xt_wini interrupt mask.
X_cim_xt_wini: 
Xcli
Xin	INT_CTLMASK
Xandb	al,#notop(XT_WINI_MASK)
Xout	INT_CTLMASK
Xsti
Xret
X|*===========================================================================*
X|*				cp_mess					     *
X|*===========================================================================*
X| PUBLIC void cp_mess(int src, phys_clicks src_clicks, vir_bytes src_offset,
X|		      phys_clicks dst_clicks, vir_bytes dst_offset);
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|
X| Note that the message size, 'Msize' is in WORDS (not bytes) and must be set
X| correctly.  Changing the definition of message in the type file and not
X| changing it here will lead to total disaster.
X_cp_mess: 
Xpush es			| save es
Xpush ds			| save ds
Xmov bx,sp		| index off bx because machine can't use sp
Xpush si			| save si
Xpush di			| save di
Xmov	ax,12(bx)	| destination click
X#if HCLICK_SHIFT > CLICK_SHIFT
X#error /* Small click sizes are not supported (right shift will lose bits). */
X#endif
X#if HCLICK_SHIFT < CLICK_SHIFT
Xmovb	cl,#CLICK_SHIFT-HCLICK_SHIFT
Xshl	ax,cl		| destination segment
X#endif
Xmov	es,ax
Xmov	di,14(bx)	| offset of destination message
X| Be careful not to destroy ds before we're finished with the bx pointer.
X| We're using bx and not the more natural bp to save pushing bp.
Xmov	ax,6(bx)	| process number of sender
Xmov	si,10(bx)	| offset of source message
Xmov	bx,8(bx)	| source click (finished with bx as a pointer)
X#if HCLICK_SHIFT < CLICK_SHIFT
Xshl	bx,cl		| source segment
X#endif
Xmov	ds,bx
Xstow		| copy sender's process number to dest message
Xadd si,*2		| don't copy first word
Xmov cx,*Msize-1		| remember, first word doesn't count
Xrep			| iterate cx times to copy 11 words
Xmovw			| copy the message
Xpop di			| restore di
Xpop si			| restore si
Xpop ds			| restore ds
Xpop es			| restore es
Xret			| that's all folks!
X|*===========================================================================*
X|*				exit					     *
X|*===========================================================================*
X| PUBLIC void exit();
X| Some library routines use exit, so provide a dummy version.
X| Actual calls to exit cannot occur in the kernel.
X| Same for .fat
X| Same for .trp.
X_exit: 
X.fat:
X.trp:
Xsti
Xj _exit
X|*===========================================================================*
X|*				get_byte				     *
X|*===========================================================================*
X| PUBLIC u16_t get_byte(u16_t segment, u8_t *offset);
X| Load and return the byte at the far pointer  segment:offset.
X_get_byte: 
Xmov	cx,ds		| save ds
Xpop	dx		| return adr
Xpop	ds		| segment
Xpop	bx		| offset
Xsub	sp,#2+2		| adjust for parameters popped
Xmovb	al,(bx)		| load the byte to return
Xxorb	ah,ah		| extend the u8_t to a u16_t
Xmov	ds,cx		| restore ds
Xjmp	(dx)		| return
X|*===========================================================================*
X|*				in_byte					     *
X|*===========================================================================*
X| PUBLIC unsigned in_byte(port_t port);
X| Read an (unsigned) byte from the i/o port  port  and return it.
X_in_byte: 
Xpop	bx
Xpop	dx		| port
Xdec	sp
Xdec	sp
Xin			| input 1 byte
Xsubb	ah,ah		| unsign extend
Xjmp	(bx)
X|*===========================================================================*
X|*				in_word					     *
X|*===========================================================================*
X| PUBLIC unsigned short in_word(port_t port);
X| Read an (unsigned) word from the i/o port and return it.
X_in_word: 
Xpop	bx
Xpop	dx		| port
Xdec	sp
Xdec	sp		| added to new klib.x 3/21/91 d.e.c.
Xinw			| input 1 word no sign extend needed
Xjmp	(bx)
X|*===========================================================================*
X|*				klib_1hook				     *
X|*===========================================================================*
X| PUBLIC void klib_1hook();
X| Initialize klib from real mode for real or protected mode,
X| Do nothing for real mode.
X| For protected mode, patch some real mode functions at their starts to jump
X| to their protected mode equivalents, according to the patch table.
X_klib_1hook: 
Xcmpb	_protected_mode,#0
Xjz	hook1_done
Xmov	si,#patch_table
Xlodw		| original function
Xpatch1: 
Xmov	bx,ax
Xseg cs
Xmovb	(bx),#JMP_OPCODE
Xlodw		| new function - target of jump
Xsub	ax,bx		| relative jump
Xsub	ax,#3		| adjust by length of jump instruction
Xseg cs
Xmov	1(bx),ax
Xlodw		| next original function
Xtest	ax,ax
Xjnz	patch1
Xhook1_done: 
Xret
X|*===========================================================================*
X|*				klib_2hook				     *
X|*===========================================================================*
X| PUBLIC void klib_prot_mode_init();
X| Initialize klib protected real mode for real or protected mode,
X| Do nothing for real mode.
X| For protected mode, load idt, task reg and flags.
X_klib_2hook: 
Xcmpb	_protected_mode,#0
Xjz	hook2_done
Xdeflidt	(_gdt+BIOS_IDT_SELECTOR) | loaded by BIOS, but in wrong mode!
Xmov	ax,#TSS_SELECTOR	| no other TSS is used
Xdefltrax
Xsub	ax,ax		| zero
Xpush	ax		| set flags to known good state
Xpopf			| especially, clear nested task and int enable
Xhook2_done: 
Xret
X|*===========================================================================*
X|*				lock					     *
X|*===========================================================================*
X| PUBLIC void lock();
X| Disable CPU interrupts.
X_lock: 
Xcli			| disable interrupts
Xret			| return to caller
X|*===========================================================================*
X|*				phys_copy				     *
X|*===========================================================================*
X| PUBLIC void phys_copy(phys_bytes source, phys_bytes destination,
X|			phys_bytes bytecount);
X| Copy a block of physical memory.
XSRCLO	=	4
XSRCHI	=	6
XDESTLO	=	8
XDESTHI	=	10
XCOUNTLO	=	12
XCOUNTHI	=	14
X_phys_copy: 
Xpush	bp		| save only registers required by C
Xmov	bp,sp		| set bp to point to source arg less 4
X| check for extended memory
Xmov	ax,SRCHI(bp)
Xor	ax,DESTHI(bp)
Xtest	ax,#EM_MASK
Xjnz	to_em_xfer
Xpush	si		| save si
Xpush	di		| save di
Xpush	ds		| save ds
Xpush	es		| save es
Xmov	ax,SRCLO(bp)	| dx:ax = source address (dx is NOT segment)
Xmov	dx,SRCHI(bp)
Xmov	si,ax		| si = source offset = address % 16
Xand	si,#OFF_MASK
X|	andb	dl,#HCHIGH_MASK	| ds = source segment = address / 16 % 0x10000
X| mask is unnecessary because of EM_MASK test
Xandb	al,#HCLOW_MASK
Xorb	al,dl		| now bottom 4 bits of dx are in ax
Xmovb	cl,#HCLICK_SHIFT | rotate them to the top 4
Xror	ax,cl
Xmov	ds,ax
Xmov	ax,DESTLO(bp)	| dx:ax = destination addr (dx is NOT segment)
Xmov	dx,DESTHI(bp)
Xmov	di,ax		| di = dest offset = address % 16
Xand	di,#OFF_MASK
X|	andb	dl,#HCHIGH_MASK	| es = dest segment = address / 16 % 0x10000
Xandb	al,#HCLOW_MASK
Xorb	al,dl
Xror	ax,cl
Xmov	es,ax
Xmov	ax,COUNTLO(bp)	| dx:ax = remaining count
Xmov	dx,COUNTHI(bp)
X| copy upwards (can't handle overlapped copy)
Xpc_loop: 
Xmov	cx,ax		| provisional count for this iteration
Xtest	ax,ax		| if count >= 0x8000, only do 0x8000 per iter
Xjs	pc_bigcount	| low byte already >= 0x8000
Xtest	dx,dx
Xjz	pc_upcount	| less than 0x8000
Xpc_bigcount: 
Xmov	cx,#0x8000	| use maximum count per iteration
Xpc_upcount: 
Xsub	ax,cx		| update count
Xsbb	dx,#0		| can't underflow, so carry clear now for rcr
Xrcr	cx,#1		| count in words, carry remembers if byte
Xjnb	pc_even		| no odd byte
Xmovb			| copy odd byte
Xpc_even: 
Xrep			| copy 1 word at a time
Xmovw			| word copy
Xmov	cx,ax		| test if remaining count is 0
Xor	cx,dx
Xjnz	pc_more		| more to do
Xpop	es		| restore es
Xpop	ds		| restore ds
Xpop	di		| restore di
Xpop	si		| restore si
Xpop	bp		| restore bp
Xret			| return to caller
Xpc_more: 
Xsub	si,#0x8000	| adjust pointers so the offset doesn't
Xmov	cx,ds		| overflow in the next 0x8000 bytes
Xadd	cx,#0x800	| pointers end up same physical location
Xmov	ds,cx		| the current offsets are known >= 0x8000
Xsub	di,#0x8000	| since we just copied that many
Xmov	cx,es
Xadd	cx,#0x800
Xmov	es,cx
Xj pc_loop		| start next iteration
X| When source or target is above 1M, join em_xfer.
X| Rely on MM and MEMTASK not to provide bad parameters, and omit checking the
X| following:
X|	count must be even
X|	count must be < 64K
X|	machine must be AT-compatible
X| which are not required for phys_copy.
Xto_em_xfer: 
Xshr	COUNTLO(bp),#1	| convert count to words
Xpop	bp		| stack frame now agrees with em_xfer's
Xj _em_xfer
X|*===========================================================================*
X|*				em_xfer					     *
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.  The BIOS call is "faked" by pushing
X|  the processor flags on the stack and then doing a far call through the
X|  saved vector table to the actual BIOS location.  An actual INT 15h would
X|  get a MINIX complaint from an unexpected trap.
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, except it may take
X|  too long and cause interrupts to be lost.
X|
X.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  0x93	| 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  0x93	| 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: 
Xpush	bp		| Save registers
Xmov	bp,sp
Xpush	si
Xpush	es
Xpush	cx
X|
X|  Pick up source and destination addresses and update descriptor tables
X|
Xmov ax,4(bp)
Xseg cs
Xmov srcl,ax
Xmov ax,6(bp)
Xseg cs
Xmovb srch,al
Xmov ax,8(bp)
Xseg cs
Xmov tgtl,ax
Xmov ax,10(bp)
Xseg cs
Xmovb tgth,al
X|
X|  Update descriptor table segment limits
X|
Xmov cx,12(bp)
Xmov ax,cx
Xadd ax,ax
Xseg cs
Xmov tgtsz,ax
Xseg cs
Xmov srcsz,ax
X|
X|  Now do actual DOS call
X|
Xpush cs
Xpop es
Xmov si,#gdt
Xmovb ah,#EM_XFER_FUNC
Xpushf			| fake interrupt
Xcalli @_vec_table+4*EM_XFER_VEC
X|
X|  All done, return to caller.
X|
Xpop	cx		| restore registers
Xpop	es
Xpop	si
Xmov	sp,bp
Xpop	bp
Xret
X|*===========================================================================*
X|*				mem_rdw					     *
X|*===========================================================================*
X| PUBLIC u16_t mem_rdw(u16_t segment, u16_t *offset);
X| Load and return the word at the far pointer  segment:offset.
X_mem_rdw: 
Xmov	cx,ds		| save ds
Xpop	dx		| return adr
Xpop	ds		| segment
Xpop	bx		| offset
Xsub	sp,#2+2		| adjust for parameters popped
Xmov	ax,(bx)		| load the word to return
Xmov	ds,cx		| restore ds
Xjmp	(dx)		| return
X|*===========================================================================*
X|*				out_byte				     *
X|*===========================================================================*
X| PUBLIC void out_byte(port_t port, int value);
X| Write  value  (cast to a byte)  to the I/O port  port.
X_out_byte: 
Xpop	bx
Xpop	dx		| port
Xpop	ax		| value
Xsub	sp,#2+2
Xout			| output 1 byte
Xjmp	(bx)
X|*===========================================================================*
X|*				out_word				     *
X|*===========================================================================*
X| PUBLIC void out_word(port_t port, int value);
X| Write  value  (cast to a word)  to the I/O port  port.
X_out_word: 
Xpop	bx
Xpop	dx		| port
Xpop	ax		| value
Xsub	sp,#2+2
Xoutw			| output 1 word
Xjmp	(bx)
X|*===========================================================================*
X|*				port_read				     *
X|*===========================================================================*
X| PUBLIC void port_read(port_t port, phys_bytes destination,unsigned bytcount);
X| Transfer data from (hard disk controller) port to memory.
X_port_read: 
Xpush	bp
Xmov	bp,sp
Xpush	cx
Xpush	dx
Xpush	di
Xpush	es
Xmov	ax,4+2(bp)	| destination addr in dx:ax
Xmov	dx,4+2+2(bp)
Xmov	di,ax		| di = dest offset = address % 16
Xand	di,#OFF_MASK
Xandb	dl,#HCHIGH_MASK	| es = dest segment = address / 16 % 0x10000
Xandb	al,#HCLOW_MASK
Xorb	al,dl
Xmovb	cl,#HCLICK_SHIFT
Xror	ax,cl
Xmov	es,ax
Xmov	cx,4+2+4(bp)	| count in bytes
Xshr	cx,#1		| count in words
Xmov	dx,4(bp)	| port to read from
Xrep
Xinsw
Xpop	es
Xpop	di
Xpop	dx
Xpop	cx
Xmov	sp,bp
Xpop	bp
Xret
X|*===========================================================================*
X|*				port_write				     *
X|*===========================================================================*
X| PUBLIC void port_write(port_t port, phys_bytes source, unsigned bytcount);
X| Transfer data from memory to (hard disk controller) port.
X_port_write: 
Xpush	bp
Xmov	bp,sp
Xpush	cx
Xpush	dx
Xpush	si
Xpush	ds
Xmov	ax,4+2(bp)	| source addr in dx:ax
Xmov	dx,4+2+2(bp)
Xmov	si,ax		| si = source offset = address % 16
Xand	si,#OFF_MASK
Xandb	dl,#HCHIGH_MASK	| ds = source segment = address / 16 % 0x10000
Xandb	al,#HCLOW_MASK
Xorb	al,dl
Xmovb	cl,#HCLICK_SHIFT
Xror	ax,cl
Xmov	ds,ax
Xmov	cx,4+2+4(bp)	| count in bytes
Xshr	cx,#1		| count in words
Xmov	dx,4(bp)	| port to read from
Xrep
Xoutsw
Xpop	ds
Xpop	si
Xpop	dx
Xpop	cx
Xmov	sp,bp
Xpop	bp
Xret
X|*===========================================================================*
X|*				reset					     *
X|*===========================================================================*
X| PUBLIC void reset();
X| Reset the system.
X| This only works in real mode.
X| For protected mode, it would be necessary to trap to privilege 0, then do
X| something fatal like loading an IDT with offset 0 and interrupting.
X_reset: 
Xjmpi 0,0xFFFF
X|*===========================================================================*
X|*				scr_down & scr_up			     *
X|*===========================================================================*
X| PUBLIC void scr_down(unsigned videoseg, int source, int dest, int count);
X| Scroll the screen down one line.
X|
X| PUBLIC void scr_up(unsigned videoseg, int source, int dest, int count);
X| Scroll the screen up one line.
X|
X| These are identical except scr_down() must reverse the direction flag
X| during the copy to avoid problems with overlap.
X_scr_down: 
Xstd
X_scr_up: 
Xpush	bp
Xmov	bp,sp
Xpush	si
Xpush	di
Xpush	ds
Xpush	es
Xmov	ax,4(bp)	| videoseg (selector for video ram)
Xmov	si,6(bp)	| source (offset within video ram)
Xmov	di,8(bp)	| dest (offset within video ram)
Xmov	cx,10(bp)	| count (in words)
Xmov	ds,ax		| set source and dest segs to videoseg
Xmov	es,ax
Xrep			| do the copy
Xmovw
Xpop	es
Xpop	ds
Xpop	di
Xpop	si
Xpop	bp
Xcld			| restore (unnecessarily for scr_up)
Xret
X|*===========================================================================*
X|*				sim_printer				     *
X|*===========================================================================*
X| PUBLIC void sim_printer();
X| Set the printer interrupt mask.
X| This is meant to be called from the task level, so it returns with
X| interrupts enabled.
X_sim_printer: 
Xcli
Xin	INT_CTLMASK
Xorb	al,#PRINTER_MASK
Xout	INT_CTLMASK
Xsti
Xret
X|*===========================================================================*
X|*				tasim_printer				     *
X|*===========================================================================*
X| PUBLIC unsigned tasim_printer();
X| Set the printer interrupt mask, indivisibly with getting its old value.
X| Return old value.
X| This is meant to be called from the task level, so it returns with
X| interrupts enabled.
X| This might not work for multiple processors, unlike test_and_set().
X_tasim_printer: 
Xcli
Xin	INT_CTLMASK
Xmovb	ah,al
Xorb	al,#PRINTER_MASK
Xout	INT_CTLMASK
Xsti
Xmovb	al,ah
Xand	ax,#PRINTER_MASK
Xret
X|*===========================================================================*
X|*				test_and_set				     *
X|*===========================================================================*
X| PUBLIC int test_and_set(int *flag);
X| Set the flag to TRUE, indivisibly with getting its old value.
X| Return old flag.
X_test_and_set: 
Xpop	dx
Xpop	bx
Xsub	sp,#2
Xmov	ax,#1
Xxchg	ax,(bx)
Xjmp	(dx)
X|*===========================================================================*
X|*				unlock					     *
X|*===========================================================================*
X| PUBLIC void unlock();
X| Enable CPU interrupts.
X_unlock: 
Xsti			| enable interrupts
Xret			| return to caller
X|*===========================================================================*
X|*				vid_copy				     *
X|*===========================================================================*
X| PUBLIC void vid_copy(char *buffer, unsigned videobase, int offset,
X|		       int words);
X| where
X|     'buffer'    is a pointer to the (character, attribute) pairs
X|     'videobase' is 0xB800 for color and 0xB000 for monochrome displays
X|     'offset'    tells where within video ram to copy the data
X|     'words'     tells how many words to copy
X| if buffer is zero, the fill char (blank_color) is used
X|
X| This routine takes a string of (character, attribute) pairs and writes them
X| onto the screen.  For a snowy display, the writing only takes places during
X| the vertical retrace interval, to avoid displaying garbage on the screen.
X_vid_copy: 
Xpush bp			| we need bp to access the parameters
Xmov bp,sp		| set bp to sp for indexing
Xpush si			| save the registers
Xpush di			| save di
Xpush bx			| save bx
Xpush cx			| save cx
Xpush dx			| save dx
Xpush es			| save es
Xvid.0:	mov si,4(bp)		| si = pointer to data to be copied
Xmov es,6(bp)		| load es NOW: int routines may NOT ruin it
Xmov di,8(bp)		| di = offset within video ram
Xand di,_vid_mask	| only 4K or 16K counts
Xmov cx,10(bp)		| cx = word count for copy loop
Xmov dx,#0x3DA		| prepare to see if color display is retracing
Xmov bx,di		| see if copy will run off end of video ram
Xadd bx,cx		| compute where copy ends
Xadd bx,cx		| bx = last character copied + 1
Xsub bx,_vid_mask	| bx = # characters beyond end of video ram
Xsub bx,#1		| note: dec bx doesn't set flags properly
X| it DOES for jle!!
Xjle vid.1		| jump if no overrun
Xsar bx,#1		| bx = # words that don't fit in video ram
Xsub cx,bx		| reduce count by overrun
Xvid.1:	push cx			| save actual count used for later
Xcmpb _snow,#0		| skip vertical retrace test if no snow
Xjz vid.4
X|vid.2:	in			| with a color display, you can only copy to
X|	test al,*010		| the video ram during vertical retrace, so
X|	jnz vid.2		| wait for start of retrace period.  Bit 3 of
Xvid.3:	in			| 0x3DA is set during retrace.  First wait
Xtestb al,*010		| until it is off (no retrace), then wait
Xjz vid.3		| until it comes on (start of retrace)
Xvid.4:	cmp si,#0		| si = 0 means blank the screen
Xje vid.7		| jump for blanking
Xlock			| this is a trick for the IBM PC simulator only
Xinc vidlock		| 'lock' indicates a video ram access
Xrep			| this is the copy loop
Xmovw			| ditto
Xvid.5:	pop si			| si = count of words copied
Xcmp bx,#0		| if bx < 0, then no overrun and we are done
Xjle vid.6		| jump if everything fit
Xmov 10(bp),bx		| set up residual count
Xmov 8(bp),#0		| start copying at base of video ram
Xcmp 4(bp),#0		| NIL_PTR means store blanks
Xje vid.0		| go do it
Xadd si,si		| si = count of bytes copied
Xadd 4(bp),si		| increment buffer pointer
Xj vid.0		| go copy some more
Xvid.6:	pop es			| restore registers
Xpop dx			| restore dx
Xpop cx			| restore cx
Xpop bx			| restore bx
Xpop di			| restore di
Xpop si			| restore si
Xpop bp			| restore bp
Xret			| return to caller
Xvid.7:	mov ax,_blank_color	| ax = blanking character
Xrep			| copy loop
Xstow		| blank screen
Xj vid.5		| done
X|*===========================================================================*
X|*			      wait_retrace				     *
X|*===========================================================================*
X| PUBLIC void wait_retrace();
X| Wait for the *start* of retrace period.
X| The VERTICAL_RETRACE_MASK of the color vid_port is set during retrace.
X| First wait until it is off (no retrace).
X| Then wait until it comes on (start of retrace).
X| We can't afford to worry about interrupts.
X_wait_retrace: 
Xmov	dx,_vid_port
Xorb	dl,#COLOR_STATUS_PORT & 0xFF
Xwait_no_retrace: 
Xin
Xtestb	al,#VERTICAL_RETRACE_MASK
Xjnz	wait_no_retrace
Xwait_retrace: 
Xin
Xtestb	al,#VERTICAL_RETRACE_MASK
Xjz	wait_retrace
Xret
X|*===========================================================================*
X|*			variants for protected mode			     *
X|*===========================================================================*
X| Some routines are different in protected mode.
X| The only essential difference is the handling of segment registers.
X| One complication is that the method of building segment descriptors is not
X| reentrant, so the protected mode versions must not be called by interrupt
X| handlers.
X|*===========================================================================*
X|*				p_check_mem				     *
X|*===========================================================================*
XPCM_DENSITY	=	256	| resolution of check
X| the shift logic depends on this being 256
Xp_check_mem: 
Xpop	bx
Xpop	_gdt+DS_286_OFFSET+DESC_BASE
Xpop	ax		| pop base into base of source descriptor
Xmovb	_gdt+DS_286_OFFSET+DESC_BASE_MIDDLE,al
Xpop	cx		| byte count in dx:cx
Xpop	dx
Xsub	sp,#4+4
Xpush	bx
Xpush	ds
Xsub	ax,ax		| prepare for early exit
Xtest	dx,#0xFF00
Xjnz	pcm_1exit	| can't handle bases above 16M
Xmovb	cl,ch		| divide size by 256 and discard high byte
Xmovb	ch,dl
Xpush	cx		| save divided size
Xsub	bx,bx		| test bytes at bases of segments
Xpcm_loop: 
Xmov	ax,#DS_286_SELECTOR
Xmov	ds,ax
Xmovb	dl,#TEST1PATTERN
Xxchgb	dl,(bx)		| write test pattern, remember original value
Xxchgb	dl,(bx)		| restore original value, read test pattern
Xcmpb	dl,#TEST1PATTERN	| must agree if good real memory
Xjnz	pcm_exit	| if different, memory is unusable
Xmovb	dl,#TEST2PATTERN
Xxchgb	dl,(bx)
Xxchgb	dl,(bx)
Xcmpb	dl,#TEST2PATTERN
Xjnz	pcm_exit
Xseg es	| next segement, test for wraparound at 16M
Xadd	_gdt+DS_286_OFFSET+DESC_BASE,#PCM_DENSITY
Xseg es	| assuming es == old ds
Xadcb	_gdt+DS_286_OFFSET+DESC_BASE_MIDDLE,#0
Xloopnz	pcm_loop
Xpcm_exit: 
Xpop	ax
Xsub	ax,cx		| verified size in multiples of PCM_DENSITY
Xpcm_1exit: 
Xmovb	dl,ah		| convert to phys_bytes in dx:ax
Xsubb	dh,dh
Xmovb	ah,al
Xmovb	al,dh
Xpop	ds
Xret
X|*===========================================================================*
X|*				p_cp_mess				     *
X|*===========================================================================*
X| The real mode version attempts to be efficient by passing raw segments but
X| that just gets in the way here.
Xp_cp_mess: 
Xpop	dx
Xpop	bx		| proc
Xpop	cx		| source clicks
Xpop	ax		| source offset
X#if CLICK_SHIFT != HCLICK_SHIFT + 4
X#error /* the only click size supported is 256, to avoid slow shifts here */
X#endif
Xaddb	ah,cl		| calculate source offset
Xadcb	ch,#0 		| and put in base of source descriptor
Xmov	_gdt+DS_286_OFFSET+DESC_BASE,ax
Xmovb	_gdt+DS_286_OFFSET+DESC_BASE_MIDDLE,ch
Xpop	cx		| destination clicks
Xpop	ax		| destination offset
Xaddb	ah,cl		| calculate destination offset
Xadcb	ch,#0 		| and put in base of destination descriptor
Xmov	_gdt+ES_286_OFFSET+DESC_BASE,ax
Xmovb	_gdt+ES_286_OFFSET+DESC_BASE_MIDDLE,ch
Xsub	sp,#2+2+2+2+2
Xpush	ds
Xpush	es
Xmov	ax,#DS_286_SELECTOR
Xmov	ds,ax
Xmov	ax,#ES_286_SELECTOR
Xmov	es,ax
Xseg es
Xmov	0,bx		| sender's proc no. from arg, not msg
Xmov	ax,si
Xmov	bx,di
Xmov	si,#2		| src offset is now 2 relative to start of seg
Xmov	di,si		| and destination offset
Xmov	cx,#Msize-1	| word count
Xrep
Xmovw
Xmov	di,bx
Xmov	si,ax
Xpop	es
Xpop	ds
Xjmp	(dx)
X|*===========================================================================*
X|*				p_phys_copy				     *
X|*===========================================================================*
Xp_phys_copy: 
Xpop	dx
Xpop	_gdt+DS_286_OFFSET+DESC_BASE
Xpop	ax		| pop source into base of source descriptor
Xmovb	_gdt+DS_286_OFFSET+DESC_BASE_MIDDLE,al
Xpop	_gdt+ES_286_OFFSET+DESC_BASE
Xpop	ax		| pop destination into base of dst descriptor
Xmovb	_gdt+ES_286_OFFSET+DESC_BASE_MIDDLE,al
Xpop	cx		| byte count in bx:cx
Xpop	bx
Xsub	sp,#4+4+4
Xpush	di
Xpush	si
Xpush	es
Xpush	ds
Xsub	si,si		| src offset is now 0 relative to start of seg
Xmov	di,si		| and destination offset
Xj ppc_next
X| It is too much trouble to align the segment bases, so word alignment is hard.
X| Avoiding the book-keeping for alignment may be good anyway.
Xppc_large: 
Xpush	cx
Xmov	cx,#0x8000	| copy a large chunk of this many words
Xrep
Xmovw
Xpop	cx
Xdec	bx
Xpop	ds		| update the descriptors
Xincb	_gdt+DS_286_OFFSET+DESC_BASE_MIDDLE
Xincb	_gdt+ES_286_OFFSET+DESC_BASE_MIDDLE
Xpush	ds
Xppc_next: 
Xmov	ax,#DS_286_SELECTOR	| (re)load the selectors
Xmov	ds,ax
Xmov	ax,#ES_286_SELECTOR
Xmov	es,ax
Xtest	bx,bx
Xjnz	ppc_large
Xshr	cx,#1		| word count
Xrep
Xmovw			| move any leftover words
Xrcl	cx,#1		| restore old bit 0
Xrep
Xmovb			| move any leftover byte
Xpop	ds
Xpop	es
Xpop	si
Xpop	di
Xjmp	(dx)
X|*===========================================================================*
X|*				p_port_read				     *
X|*===========================================================================*
Xp_port_read: 
Xpop	bx
Xpop	dx		| port
Xpop	_gdt+ES_286_OFFSET+DESC_BASE
Xpop	ax		| pop destination into base of dst descriptor
Xmovb	_gdt+ES_286_OFFSET+DESC_BASE_MIDDLE,al
Xpop	cx		| byte count
Xsub	sp,#2+4+2
Xpush	es
Xmov	ax,#ES_286_SELECTOR
Xmov	es,ax
Xmov	ax,di
Xsub	di,di		| dst offset is now 0 relative to start of seg
Xshr	cx,#1		| word count
Xrep
Xinsw			| read everything
Xmov	di,ax
Xpop	es
Xjmp	(bx)
X|*===========================================================================*
X|*				p_port_write				     *
X|*===========================================================================*
Xp_port_write: 
Xpop	bx
Xpop	dx		| port
Xpop	_gdt+DS_286_OFFSET+DESC_BASE
Xpop	ax		| pop offset into base of source descriptor
Xmovb	_gdt+DS_286_OFFSET+DESC_BASE_MIDDLE,al
Xpop	cx		| byte count, discard high word
Xsub	sp,#2+4+2
Xpush	ds
Xmov	ax,#DS_286_SELECTOR
Xmov	ds,ax
Xmov	ax,si
Xsub	si,si		| src offset is now 0 relative to start of seg
Xshr	cx,#1		| word count
Xrep
Xoutsw			| write everything
Xmov	si,ax
Xpop	ds
Xjmp	(bx)
X|*===========================================================================*
X|*				data					     *
X|*===========================================================================*
X.data
Xpatch_table: | pairs (old function, new function)
X.word 	_check_mem, p_check_mem
X.word 	_cp_mess, p_cp_mess
X.word 	_phys_copy, p_phys_copy
X.word 	_port_read, p_port_read
X.word 	_port_write, p_port_write
X.word 	_restart, p_restart	| in mpx file
X.word 	save, p_save	| in mpx file
X.word 	0		| end of table
Xsplimit: | stack limit for current task (kernel only)
X.word  0
Xvidlock: | dummy variable for use with lock prefix
X.word  0
/
echo x - mpx88.x.ansi
sed '/^X/s///' > mpx88.x.ansi << '/'
X! This file contains the assembler startup code for Minix.
X! It cooperates with cstart.c to set up a good environment for main().
X
X! This file is part of the lowest layer of the MINIX kernel.  The other part
X! is "proc.c".  The lowest layer does process switching and message handling.
X
X! Every transition to the kernel goes through this file.  Transitions are
X! caused by sending/receiving messages and by most interrupts.  (RS232
X! interrupts may be handled in the file "rs2.x" and then they rarely enter
X! the kernel.)
X
X! Transitions to the kernel may be nested.  The initial entry may be with a
X! system call, exception or hardware interrupt; reentries may only be made
X! by hardware interrupts.  The count of reentries is kept in 'k_reenter'.
X! It is important for deciding whether to switch to the kernel stack and
X! for protecting the message passing code in "proc.c".
X
X! For the message passing trap, most of the machine state is saved in the
X! proc table.  (Some of the registers need not be saved.)  Then the stack is
X! switched to 'k_stack', and interrupts are reenabled.  Finally, the system
X! call handler (in C) is called.  When it returns, interrupts are disabled
X! again and the code falls into the restart routine, to finish off held-up
X! interrupts and run the process or task whose pointer is in 'proc_ptr'.
X
X! Hardware interrupt handlers do the same, except  (1) The entire state must
X! be saved.  (2) There are too many handlers to do this inline, so the save
X! routine is called.  A few cycles are saved by pushing the address of the
X! appropiate restart routine for a return later.  (3) A stack switch is
X! avoided when the stack is already switched.  (4) The (master) 8259 interrupt
X! controller is reenabled centrally in save().  (5) Each interrupt handler
X! masks its interrupt line using the 8259 before enabling (other unmasked)
X! interrupts, and unmasks it after servicing the interrupt.  This limits the
X! nest level to the number of lines and protects the handler from itself.
X
X
X#include <minix/config.h>
X#include <minix/const.h>
X#include <minix/com.h>
X#include "const.h"
X#include "sconst.h"
X
X! The external entry points into this file are:
X
X.define		_db		! trap to external debugger
X.define		_get_word	! returns word at given segment:offset
X.define		_put_word	! writes given word to given segment:offset
X! _get_word and _put_word may only be called in real mode from cstart().
X
X.define	_clock_int	! clock interrupt routine (HZ times per second)
X.define	_disk_int	! disk interrupt routine
X.define	_idle_task	! executed when there is no work
X.define	_int00		! handlers for unused interrupt vectors < 17
X.define	_int01
X.define	_int02
X.define	_int03
X.define	_int04
X.define	_int05
X.define	_int06
X.define	_int07
X.define	_int08
X.define	_int09
X.define	_int10
X.define	_int11
X.define	_int12
X.define	_int13
X.define	_int14
X.define	_int15
X.define	_int16
X.define	_lpr_int	! interrupt routine for each line printer interrupt
X.define	_mpx_1hook	! init from real mode for real or protected mode
X.define	_mpx_2hook	! init from protected mode for real or protected mode
X.define	_restart	! start running a task or process
X.define	save		! save the machine state in the proc table
X.define	_s_call		! process or task wants to send or receive a message
X.define	_trp		! all traps with vector >= 17 are vectored here
X.define	_tty_int	! interrupt routine for each key depression and release
X.define	_wini_int	! winchester interrupt routine
X
X#if INTEL_32BITS
X#error /* this is not the 32-bit version */
X#include "protect.h"
X#endif
X
X! When using the more portable but slower C-code RS232 interrupt handlers,
X! there are a few more entry points:
X
X#if C_RS232_INT_HANDLERS
X.define	_prs232_int	! same as rs232_int, different label for prot mode
X.define	_psecondary_int	! same as secondary_int, different label for prot mode
X.define	_rs232_int 	! interrupt routine for each rs232 interrupt on port 1
X.define	_secondary_int 	! interrupt routine for each rs232 interrupt on port 2
X#endif
X
X! When networking is enabled, the _eth_int entry point is used instead of the
X! various _secondary_int entry points.
X
X#if NETWORKING_ENABLED
X.define	_eth_int	! ethernet interrupt routine
X#endif
X
X! Imported functions.
X
X.extern		_cstart
X.extern		_main
X.extern		_clock_handler
X.extern		_exception
X.extern		_interrupt
X.extern		kernel_ds
X.extern		_keyboard
X.extern		_pr_char
X.extern		_sys_call
X.extern		_unhold
X
X#if C_RS232_INT_HANDLERS
X.extern		_rs232_1handler
X.extern		_rs232_2handler
X#endif
X
X! Exported variables.
X
X.define		kernel_ds
X
X	.bss
X.define		begbss
X.define		begdata
X.define		k_stktop
X.define		_sizes
X
X! Imported variables.
X
X.extern		_gdt
X.extern		_code_base
X.extern		_data_base
X.extern		_break_vector
X.extern		_db_enabled
X.extern		_held_head
X.extern		_k_reenter
X.extern		k_stktop
X.extern		_pc_at
X.extern		_proc_ptr
X.extern		_protected_mode
X.extern		_ps
X.extern		_ps_mca
X.extern		_sstep_vector
X
X/* BIOS software interrupts, subfunctions and return values. */
X#define SET_PROTECT_VEC		0x15	/* set protected mode */
X#	define SET_PROTECT_FUNC 0x89
X
X	.text
X!*===========================================================================*
X!*				MINIX					     *
X!*===========================================================================*
XMINIX:				! this is the entry point for the MINIX kernel
X	jmp	over_kernel_ds	! skip over the next few bytes
X	.data2	CLICK_SHIFT	! for the monitor: memory granularity
Xkernel_ds:
X	.data2	0x0000		! flags for the boot monitor, later kernel DS
Xover_kernel_ds:
X
X! Set up kernel segment registers and stack.
X! The monitor sets cs and ds right.  ss still points to the monitor data,
X! because the boot parameters offset and size are on its stack.
X
X! Locate boot parameters and set segment registers.
X	pop	bx		! boot parameters offset
X	pop	cx		! boot parameters length
X	mov	dx,ss		! monitor data
X	mov	ax,ds		! kernel data
X	mov	es,ax
X	mov	ss,ax
X	mov	sp,#k_stktop	! set sp to point to the top of kernel stack
X
X! Real mode needs to get kernel DS from the code segment.
X
X	cseg
X	mov	kernel_ds,ds
X
X! Call C startup code to prepare for switching modes.
X
X	push	cx
X	push	dx
X	push	bx
X	push	ds
X	push	cs
X	call	_cstart		! cstart(cs, ds, parmoff, parmseg, parmlen)
X	add	sp,#5*2
X
X! Call the BIOS to switch to protected mode.
X! This is just to do any cleanup necessary, typically to disable a hardware
X! kludge which holds the A20 address line low.
X
X! The call requires the gdt as set up by prot_init():
X!	gdt pointer in gdt[1]
X!	idt pointer in gdt[2]
X!	new ds in gdt[3]
X!	new es in gdt[4]
X!	new ss in gdt[5]
X!	new cs in gdt[6]
X!	nothing in gdt[7] (overwritten with BIOS cs)
X!	ICW2 for master 8259 in bh
X!	ICW2 for slave 8259 in bl
X! The BIOS enables interrupts briefly - this is OK since the BIOS vectors
X! are still valid.
X! Most registers are destroyed.
X! The 8259's are reinitialised.
X
X	mov	si,#_gdt
X	mov	bx,#IRQ0_VECTOR * 256 + IRQ8_VECTOR
X	movb	ah,#SET_PROTECT_FUNC
X	int	SET_PROTECT_VEC
X
X! Now the processor is in protected mode.
X! There is a little more protected mode initialization to do, but leave it
X! to main().
X
X	call	_main
X
X
X!*===========================================================================*
X!*				db					     *
X!*===========================================================================*
X
X! PUBLIC void db();
X! Trap to external debugger.
X
X_db:
X	int	3
X	ret
X
X
X!*===========================================================================*
X!*				get_word				     *
X!*===========================================================================*
X
X! PUBLIC u16_t get_word(u16_t segment, u16_t *offset);
X! Load and return the word at the far pointer  segment:offset.
X
X_get_word:
X	mov	cx,ds		! save ds
X	pop	dx		! return adr
X	pop	ds		! segment
X	pop	bx		! offset
X	sub	sp,#2+2		! adjust for parameters popped
X	mov	ax,(bx)		! load the word to return
X	mov	ds,cx		! restore ds
X	jmp	(dx)		! return
X
X
X!*===========================================================================*
X!*				put_word				     *
X!*===========================================================================*
X
X! PUBLIC void put_word(u16_t segment, u16_t *offset, u16_t value);
X! Store the word  value  at the far pointer  segment:offset.
X
X_put_word:
X	mov	cx,ds		! save ds
X	pop	dx		! return adr
X	pop	ds		! segment
X	pop	bx		! offset
X	pop	ax		! value
X	sub	sp,#2+2+2	! adjust for parameters popped
X	mov	(bx),ax		! store the word
X	mov	ds,cx		! restore ds
X	jmp	(dx)		! return
X
X
X!*===========================================================================*
X!*				tty_int					     *
X!*===========================================================================*
X_tty_int:			! Interrupt routine for terminal input.
X	call	save		! save the machine state
X	inb	INT_CTLMASK	! mask out further keyboard interrupts
X	orb	al,#KEYBOARD_MASK
X	outb	INT_CTLMASK
X	sti			! allow unmasked, non-keyboard, interrupts
X	call	_keyboard	! process a keyboard interrupt
X	cli
X	inb	INT_CTLMASK	! unmask keyboard interrupt
X	andb	al,#notop(KEYBOARD_MASK)
X	outb	INT_CTLMASK
X	ret			! return to appropiate restart built by save()
X
X
X#if C_RS232_INT_HANDLERS
X!*===========================================================================*
X!*				rs232_int				     *
X!*===========================================================================*
X_rs232_int:			! Interrupt routine for rs232 I/O.
X_prs232_int:
X	call	save
X	inb	INT_CTLMASK
X	orb	al,#RS232_MASK
X	outb	INT_CTLMASK
X
X! Do not enable interrupts, the handlers are not designed for it.
X! The mask was set as usual so the handler can reenable interrupts as desired.
X
X	call	_rs232_1handler	! process a serial line 1 interrupt
X	inb	INT_CTLMASK
X	andb	al,#notop(RS232_MASK)
X	outb	INT_CTLMASK
X	ret
X
X
X!*===========================================================================*
X!*				secondary_int				     *
X!*===========================================================================*
X_secondary_int:			! Interrupt routine for rs232 port 2
X_psecondary_int:
X	call	save
X	inb	INT_CTLMASK
X	orb	al,#SECONDARY_MASK
X	outb	INT_CTLMASK
X	call	_rs232_2handler	! process a serial line 2 interrupt
X	inb	INT_CTLMASK
X	andb	al,#notop(SECONDARY_MASK)
X	outb	INT_CTLMASK
X	ret
X#endif /* C_RS232_INT_HANDLERS */
X
X
X!*===========================================================================*
X!*				lpr_int					     *
X!*===========================================================================*
X_lpr_int:			! Interrupt routine for printer output.
X	call	save
X	inb	INT_CTLMASK
X	orb	al,#PRINTER_MASK
X	outb	INT_CTLMASK
X	sti
X	call	_pr_char	! process a line printer interrupt
X	cli
X	inb	INT_CTLMASK
X#if ASLD
X	andb	al,#notop(PRINTER_MASK)
X#else
X	andb	al,#notop(PRINTER_MASK) & 0xFF
X#endif
X	outb	INT_CTLMASK
X	ret
X
X
X!*===========================================================================*
X!*				disk_int				     *
X!*===========================================================================*
X_disk_int:			! Interrupt routine for the floppy disk.
X	call	save
X	cmp	_ps,#0		! check for 2nd int controller on ps (?)
X	je	over_ps_disk
X	movb	al,#ENABLE
X	outb	0x3C
Xover_ps_disk:
X
X! The last doesn't make sense as an 8259 command, since the floppy vector
X! seems to be the same on PS's so the usual 8259 must be controlling it.
X! This used to be done at the start of the interrupt handler, in proc.c.
X! Find out where it really goes, and if there are any mask bits in port
X! 0x3D which have to be fiddled (here and in fdc_results()).
X
X	inb	INT_CTLMASK
X	orb	al,#FLOPPY_MASK
X	outb	INT_CTLMASK
X	sti
X	mov	ax,#FLOPPY
X	push	ax
X	call	_interrupt	! interrupt(FLOPPY)
X	add	sp,#2
X	cli
X	ret
X
X
X!*===========================================================================*
X!*				wini_int				     *
X!*===========================================================================*
X_wini_int:			! Interrupt routine for the winchester disk.
X	call	save
X	cmp	_pc_at,#0	! check for 2nd int controller on AT
X	jnz	at_wini_int
X
Xxt_wini_int:
X	inb	INT_CTLMASK
X	orb	al,#XT_WINI_MASK
X	outb	INT_CTLMASK
X	sti
X	mov	ax,#WINCHESTER
X	push	ax
X	call	_interrupt	! interrupt(WINCHESTER)
X	add	sp,#2
X	cli
X	ret
X
Xat_wini_int:
X	inb	INT2_MASK
X	orb	al,#AT_WINI_MASK
X	outb	INT2_MASK
X	sti
X	movb	al,#ENABLE	! reenable slave 8259
X	outb	INT2_CTL	! the master one was done in save() as usual
X	mov	ax,#WINCHESTER
X	push	ax
X	call	_interrupt	! interrupt(WINCHESTER)
X	add	sp,#2
X	cli
X	ret
X
X
X!*===========================================================================*
X!*				clock_int				     *
X!*===========================================================================*
X_clock_int:			! Interrupt routine for the clock.
X	call	save
X	cmp	_ps_mca, #0	! if not a PS/2, don't twiddle bits
X	je	skip_mca_clock
X	inb	CLOCK_ACK_PORT	! PS/2 clock needs to be told to stop 
X	orb	al,#CLOCK_ACK_BIT	! interrupting CPU, or we'll hang
X	outb	CLOCK_ACK_PORT
Xskip_mca_clock:
X	inb	INT_CTLMASK
X	orb	al,#CLOCK_MASK
X	outb	INT_CTLMASK
X	sti
X	call	_clock_handler	! process a clock interrupt
X				! This calls interrupt() only if necessary.
X				! Very rarely.
X	cli
X	inb	INT_CTLMASK
X	andb	al,#notop(CLOCK_MASK)
X	outb	INT_CTLMASK
X	ret
X
X
X!*===========================================================================*
X!*				eth_int					     *
X!*===========================================================================*
X#if 0 /* original version */
X_eth_int:			! Interrupt routine for ethernet input
X	call	save
X	inb	INT_CTLMASK
X	orb	al,#ETHER_MASK
X	outb	INT_CTLMASK
X	sti
X	call	_dp8390_int	! call the handler
X	cli
X	ret
X#endif
X
X#if NETWORKING_ENABLED
X_eth_int:			! Interrupt routine for ethernet input
X	call	save
X	inb	INT_CTLMASK
X	orb	al,#ETHER_MASK
X	outb	INT_CTLMASK
X	sti
X	mov	ax,#DL_ETH	! EHW_TASK accepts all packets, so it can be
X				! interrupted
X	push	ax
X	call	_interrupt	! interrupt(EHW_TASK)
X	add	sp,#2
X	cli
X	inb	INT_CTLMASK
X	andb	al,#notop(ETHER_MASK)
X	outb	INT_CTLMASK
X	ret
X#endif
X
X
X!*===========================================================================*
X!*				int00-16				     *
X!*===========================================================================*
X_int00:				! interrupt through vector 0
X	push	ax
X	movb	al,#0
X	jmp	exception
X
X_int01:				! interrupt through vector 1, etc
X	push	ds
X	cseg
X	mov	ds,kernel_ds
X	cmpb	_db_enabled,#0
X	pop	ds
X	jz	over_sstep
X	cseg
X	jmpf	@cs_sstep_vector
X
Xover_sstep:
X	push	ax
X	movb	al,#1
X	jmp	exception
X
X_int02:
X	push	ax
X	movb	al,#2
X	jmp	exception
X
X_int03:
X	push	ds
X	cseg
X	mov	ds,kernel_ds
X	cmpb	_db_enabled,#0
X	pop	ds
X	jz	over_breakpoint
X	cseg
X	jmpf	@cs_break_vector
X
Xover_breakpoint:
X	push	ax
X	movb	al,#3
X	jmp	exception
X
X_int04:
X	push	ax
X	movb	al,#4
X	jmp	exception
X
X_int05:
X	push	ax
X	movb	al,#5
X	jmp	exception
X
X_int06:
X	push	ax
X	movb	al,#6
X	jmp	exception
X
X_int07:
X	push	ax
X	movb	al,#7
X	jmp	exception
X
X_int08:
X	push	ax
X	movb	al,#8
X	jmp	exception
X
X_int09:
X	push	ax
X	movb	al,#9
X	jmp	exception
X
X_int10:
X	push	ax
X	movb	al,#10
X	jmp	exception
X
X_int11:
X	push	ax
X	movb	al,#11
X	jmp	exception
X
X_int12:
X	push	ax
X	movb	al,#12
X	jmp	exception
X
X_int13:
X	push	ax
X	movb	al,#13
X	jmp	exception
X
X_int14:
X	push	ax
X	movb	al,#14
X	jmp	exception
X
X_int15:
X	push	ax
X	movb	al,#15
X	jmp	exception
X
X_int16:
X	push	ax
X	movb	al,#16
X	jmp	exception
X
X_trp:
X	push	ax
X	movb	al,#17		! any vector above 17 becomes 17
X
Xexception:
X	cseg
X	movb	ex_number,al	! it's cumbersome to get this into dseg
X	pop	ax
X	call	save
X	cseg
X	push	ex_number	! high byte is constant 0
X	call	_exception	! do whatever's necessary (sti only if safe)
X	add	sp,#2
X	cli
X	ret
X
X
X!*===========================================================================*
X!*				save					     *
X!*===========================================================================*
Xsave:				! save the machine state in the proc table.
X	cld			! set direction flag to a known value
X	push	ds
X	push	si
X	cseg
X	mov	ds,kernel_ds
X	incb	_k_reenter	! from -1 if not reentering
X	jnz	push_current_stack	! stack is already kernel's
X
X	mov	si,_proc_ptr
X	mov	AXREG(si),ax
X	mov	BXREG(si),bx
X	mov	CXREG(si),cx
X	mov	DXREG(si),dx
X	pop	SIREG(si)
X	mov	DIREG(si),di
X	mov	BPREG(si),bp
X	mov	ESREG(si),es
X	pop	DSREG(si)
X	pop	bx		! return adr
X	pop	PCREG(si)
X	pop	CSREG(si)
X	pop	PSWREG(si)
X	mov	SPREG(si),sp
X	mov	SSREG(si),ss
X
X	mov	dx,ds
X	mov	ss,dx
X	mov	sp,#k_stktop
X#if SPLIMITS
X	mov	splimit,#k_stack+8
X#endif
X	mov	ax,#_restart	! build return address for interrupt handler
X	push	ax
X
Xstack_switched:
X	mov	es,dx
X	movb	al,#ENABLE	! reenable int controller for everyone (early)
X	outb	INT_CTL
X	jmp	(bx)
X
Xpush_current_stack:
X	push	es
X	push	bp
X	push	di
X	push	dx
X	push	cx
X	push	bx
X	push	ax
X	mov	bp,sp
X	mov	bx,18(bp)	! get the return adr; it becomes junk on stack
X	mov	ax,#restart1
X	push	ax
X	mov	dx,ss
X	mov	ds,dx
X	jmp	stack_switched
X
X
X!*===========================================================================*
X!*				s_call					     *
X!*===========================================================================*
X_s_call:			! System calls are vectored here.
X				! Do save routine inline for speed,
X				! but don't save ax, bx, cx, dx,
X				! since C doesn't require preservation,
X				! and ax returns the result code anyway.
X				! Regs bp, si, di get saved by sys_call as
X				! well, but it is impractical not to preserve
X				! them here, in case context gets switched.
X				! Some special-case code in pick_proc()
X				! could avoid this.
X	cld			! set direction flag to a known value
X	push	ds
X	push	si
X	cseg
X	mov	ds,kernel_ds
X	incb	_k_reenter
X	mov	si,_proc_ptr
X	pop	SIREG(si)
X	mov	DIREG(si),di
X	mov	BPREG(si),bp
X	mov	ESREG(si),es
X	pop	DSREG(si)
X	pop	PCREG(si)
X	pop	CSREG(si)
X	pop	PSWREG(si)
X	mov	SPREG(si),sp
X	mov	SSREG(si),ss
X	mov	dx,ds
X	mov	es,dx
X	mov	ss,dx		! interrupt handlers may not make system calls
X	mov	sp,#k_stktop	! so stack is not already switched
X#if SPLIMITS
X	mov	splimit,#k_stack+8
X#endif
X				! end of inline save
X				! now set up parameters for C routine sys_call
X	push	bx		! pointer to user message
X	push	ax		! src/dest
X	push	cx		! SEND/RECEIVE/BOTH
X	sti			! allow SWITCHER to be interrupted
X	call	_sys_call	! sys_call(function, src_dest, m_ptr)
X				! caller is now explicitly in proc_ptr
X	mov	AXREG(si),ax	! sys_call MUST PRESERVE si
X	cli
X
X! Fall into code to restart proc/task running.
X
X
X!*===========================================================================*
X!*				restart					     *
X!*===========================================================================*
X_restart:
X
X! Flush any held-up interrupts.
X! This reenables interrupts, so the current interrupt handler may reenter.
X! This doesn't matter, because the current handler is about to exit and no
X! other handlers can reenter since flushing is only done when k_reenter == 0.
X
X	cmp	_held_head,#0	! do fast test to usually avoid function call
X	jz	over_call_unhold
X	call	_unhold		! this is rare so overhead is acceptable
Xover_call_unhold:
X
X	mov	si,_proc_ptr
X#if SPLIMITS
X	mov	ax,P_SPLIMIT(si)	! splimit = p_splimit
X	mov	splimit,ax
X#endif
X	decb	_k_reenter
X	mov	ax,AXREG(si)	! start restoring registers from proc table
X				! could make AXREG == 0 to use lodw here
X	mov	bx,BXREG(si)
X	mov	cx,CXREG(si)
X	mov	dx,DXREG(si)
X	mov	di,DIREG(si)
X	mov	bp,BPREG(si)
X	mov	es,ESREG(si)
X	mov	ss,SSREG(si)
X	mov	sp,SPREG(si)
X	push	PSWREG(si)	! fake interrupt stack frame
X	push	CSREG(si)
X	push	PCREG(si)
X				! could put si:ds together to use
X				! lds si,SIREG(si)
X	push	DSREG(si)
X	mov	si,SIREG(si)
X	pop	ds
X	nop			! helps debugger emulate iret - else pop skips
X	iret			! return to user or task
X
Xrestart1:
X	decb	_k_reenter
X	pop	ax
X	pop	bx
X	pop	cx
X	pop	dx
X	pop	di
X	pop	bp
X	pop	es
X	pop	si
X	pop	ds
X	add	sp,#2		! skip return adr
X	iret
X
X
X!*===========================================================================*
X!*				idle					     *
X!*===========================================================================*
X_idle_task:			! executed when there is no work 
X	jmp	_idle_task	! a "hlt" before this fails in protected mode
X
X
X!*===========================================================================*
X!*				mpx_1hook				     *
X!*===========================================================================*
X! PUBLIC void mpx_1hook();
X! Initialize klib from real mode for real or protected mode:
X! Copy real mode debugger vectors to code segment.
X! They are too hard to access at interrupt time.
X
X_mpx_1hook:
X	push	ds
X	mov	ax,#0		! VEC_TABLE_SEG
X	mov	ds,ax
X	mov	ax,4*BREAKPOINT_VECTOR
X	cseg
X	mov	cs_break_vector,ax
X	mov	ax,4*BREAKPOINT_VECTOR+2
X	cseg
X	mov	cs_break_vector+2,ax
X	mov	ax,4*DEBUG_VECTOR
X	cseg
X	mov	cs_sstep_vector,ax
X	mov	ax,4*DEBUG_VECTOR+2
X	cseg
X	mov	cs_sstep_vector+2,ax
X	pop	ds
X	ret
X
X
X!*===========================================================================*
X!*				data					     *
X!*===========================================================================*
X! NB some variables are stored in code segment.
X
Xcs_break_vector:		! copy of real mode breakpoint vector
X	.space	4
Xcs_sstep_vector:		! copy of real mode single-step vector
X	.space	4
Xex_number:			! exception number
X	.space	2
X
X
X!*===========================================================================*
X!*			variants for 286 protected mode			     *
X!*===========================================================================*
X
X! Most routines are different in 286 protected mode.
X! The only essential difference is that an interrupt in protected mode
X! (usually) switches the stack, so there is less to do in software.
X
X! These functions are reached along jumps patched in by klib286_init():
X
X	.define		p_restart	! replaces _restart
X	.define		p_save		! replaces save
X
X! These exception and software-interrupt handlers are enabled by the new
X! interrupt vector table set up in protect.c:
X
X	.define		_divide_error		! _int00
X	.define		_single_step_exception	! _int01
X	.define		_nmi			! _int02
X	.define		_breakpoint_exception	! _int03
X	.define		_overflow		! _int04
X	.define		_bounds_check		! _int05
X	.define		_inval_opcode		! _int06
X	.define		_copr_not_available	! _int07
X	.define		_double_fault		! _int08
X	.define		_copr_seg_overrun	! _int09
X	.define		_inval_tss		! _int10
X	.define		_segment_not_present	! _int11
X	.define		_stack_exception	! _int12
X	.define		_general_protection	! _int13
X	.define		_p_s_call		! _s_call
X
X! The hardware interrupt handlers need not be altered apart from putting
X! them in the new table (save() handles the differences).
X! Some of the intxx handlers (those for exceptions which don't push an
X! error code) need not have been replaced, but the names here are better.
X
X#include "protect.h"
X
X/* Selected 286 tss offsets. */
X#define TSS2_S_SP0	2
X
X! imported variables
X
X	.bss
X
X	.extern		_tss
X
X	.text
X!*===========================================================================*
X!*				exception handlers			     *
X!*===========================================================================*
X_divide_error:
X	pushi8	(DIVIDE_VECTOR)
X	jmp	p_exception
X
X_single_step_exception:
X	sseg
X	cmpb	_db_enabled,#0
X	jz	p_over_sstep
X	sseg
X	jmpf	@_sstep_vector
X
Xp_over_sstep:
X	pushi8	(DEBUG_VECTOR)
X	jmp	p_exception
X
X_nmi:
X	pushi8	(NMI_VECTOR)
X	jmp	p_exception
X
X_breakpoint_exception:
X	sseg
X	cmpb	_db_enabled,#0
X	jz	p_over_breakpoint
X	sseg
X	jmpf	@_break_vector
X
Xp_over_breakpoint:
X	pushi8	(BREAKPOINT_VECTOR)
X	jmp	p_exception
X
X_overflow:
X	pushi8	(OVERFLOW_VECTOR)
X	jmp	p_exception
X
X_bounds_check:
X	pushi8	(BOUNDS_VECTOR)
X	jmp	p_exception
X
X_inval_opcode:
X	pushi8	(INVAL_OP_VECTOR)
X	jmp	p_exception
X
X_copr_not_available:
X	pushi8	(COPROC_NOT_VECTOR)
X	jmp	p_exception
X
X_double_fault:
X	pushi8	(DOUBLE_FAULT_VECTOR)
X	jmp	errexception
X
X_copr_seg_overrun:
X	pushi8	(COPROC_SEG_VECTOR)
X	jmp	p_exception
X
X_inval_tss:
X	pushi8	(INVAL_TSS_VECTOR)
X	jmp	errexception
X
X_segment_not_present:
X	pushi8	(SEG_NOT_VECTOR)
X	jmp	errexception
X
X_stack_exception:
X	pushi8	(STACK_FAULT_VECTOR)
X	jmp	errexception
X
X_general_protection:
X	pushi8	(PROTECTION_VECTOR)
X	jmp	errexception
X
X
X!*===========================================================================*
X!*				p_exception				     *
X!*===========================================================================*
X! This is called for all exceptions which don't push an error code.
X
Xp_exception:
X	sseg
X	pop	ds_ex_number
X	call	p_save
X	jmp	p1_exception
X
X
X!*===========================================================================*
X!*				errexception				     *
X!*===========================================================================*
X! This is called for all exceptions which push an error code.
X
Xerrexception:
X	sseg
X	pop	ds_ex_number
X	sseg
X	pop	trap_errno
X	call	p_save
Xp1_exception:			! Common for all exceptions.
X	push	ds_ex_number
X	call	_exception
X	add	sp,#2
X	cli
X	ret
X
X
X!*===========================================================================*
X!*				p_save					     *
X!*===========================================================================*
X! Save for 286 protected mode.
X! This is much simpler than for 8086 mode, because the stack already points
X! into process table, or has already been switched to the kernel stack.
X
Xp_save:
X	cld			! set direction flag to a known value
X	pusha			! save "general" registers
X	push	ds		! save ds
X	push	es		! save es
X	mov	dx,ss		! ss is kernel data segment
X	mov	ds,dx		! load rest of kernel segments
X	mov	es,dx
X	movb	al,#ENABLE	! reenable int controller
X	outb	INT_CTL
X	mov	bp,sp		! prepare to return
X	incb	_k_reenter	! from -1 if not reentering
X	jnz	set_p1_restart	! stack is already kernel's
X	mov	sp,#k_stktop
X#if SPLIMITS
X	mov	splimit,#k_stack+8
X#endif
X	pushi16	(p_restart)	! build return address for interrupt handler
X	jmp	@RETADR-P_STACKBASE(bp)
X
Xset_p1_restart:
X	pushi16	(p1_restart)
X	jmp	@RETADR-P_STACKBASE(bp)
X
X
X!*===========================================================================*
X!*				p_s_call				     *
X!*===========================================================================*
X_p_s_call:
X	cld			! set direction flag to a known value
X	sub	sp,#6*2		! skip RETADR, ax, cx, dx, bx, st
X	push	bp		! stack already points into process table
X	push	si
X	push	di
X	push	ds
X	push	es
X	mov	dx,ss
X	mov	ds,dx
X	mov	es,dx
X	incb	_k_reenter
X	mov	si,sp		! assumes P_STACKBASE == 0
X	mov	sp,#k_stktop
X#if SPLIMITS
X	mov	splimit,#k_stack+8
X#endif
X				! end of inline save
X	sti			! allow SWITCHER to be interrupted
X				! now set up parameters for C routine sys_call
X	push	bx		! pointer to user message
X	push	ax		! src/dest
X	push	cx		! SEND/RECEIVE/BOTH
X	call	_sys_call	! sys_call(function, src_dest, m_ptr)
X				! caller is now explicitly in proc_ptr
X	mov	AXREG(si),ax	! sys_call MUST PRESERVE si
X	cli
X
X! Fall into code to restart proc/task running.
X
Xp_restart:
X
X! Flush any held-up interrupts.
X! This reenables interrupts, so the current interrupt handler may reenter.
X! This doesn't matter, because the current handler is about to exit and no
X! other handlers can reenter since flushing is only done when k_reenter == 0.
X
X	cmp	_held_head,#0	! do fast test to usually avoid function call
X	jz	p_over_call_unhold
X	call	_unhold		! this is rare so overhead is acceptable
Xp_over_call_unhold:
X	mov	si,_proc_ptr
X#if SPLIMITS
X	mov	ax,P_SPLIMIT(si)	! splimit = p_splimit
X	mov	splimit,ax
X#endif
X	deflldt	(P_LDT_SEL(si))		! enable task's segment descriptors
X	lea	ax,P_STACKTOP(si)	! arrange for next interrupt
X	mov	_tss+TSS2_S_SP0,ax	! to save state in process table
X	mov	sp,si		! assumes P_STACKBASE == 0
Xp1_restart:
X	decb	_k_reenter
X	pop	es
X	pop	ds
X	popa
X	add	sp,#2		! skip RETADR
X	iret			! continue process
X
X
X!*===========================================================================*
X!*				mpx_2hook				     *
X!*===========================================================================*
X! PUBLIC void mpx_2hook();
X! Initialize klib from protected mode for real or protected mode:
X! Nothing to do.
X
X_mpx_2hook:
X	ret
X
X
X!*===========================================================================*
X!*				data					     *
X!*===========================================================================*
X
X	.data
Xbegdata:
X_sizes:				! sizes of kernel, mm, fs filled in by build
X	.data2	0x526F		! this must be the first data entry (magic #)
X	.data2	CLICK_SHIFT	! consistency check for build
X	.zerow	6		! build uses prevous 2 words and this space
X	.space	K_STACK_BYTES	! kernel stack
Xk_stktop:			! top of kernel stack
X
X	.bss
Xbegbss:
Xds_ex_number:
X	.space	2
Xtrap_errno:
X	.space	2
/
echo x - mpx88.x.kr
sed '/^X/s///' > mpx88.x.kr << '/'
X| This file contains the assembler startup code for Minix.
X| It cooperates with cstart.c to set up a good environment for main().
X| This file is part of the lowest layer of the MINIX kernel.  The other part
X| is "proc.c".  The lowest layer does process switching and message handling.
X| Every transition to the kernel goes through this file.  Transitions are
X| caused by sending/receiving messages and by most interrupts.  (RS232
X| interrupts may be handled in the file "rs2.x" and then they rarely enter
X| the kernel.)
X| Transitions to the kernel may be nested.  The initial entry may be with a
X| system call, exception or hardware interrupt; reentries may only be made
X| by hardware interrupts.  The count of reentries is kept in 'k_reenter'.
X| It is important for deciding whether to switch to the kernel stack and
X| for protecting the message passing code in "proc.c".
X| For the message passing trap, most of the machine state is saved in the
X| proc table.  (Some of the registers need not be saved.)  Then the stack is
X| switched to 'k_stack', and interrupts are reenabled.  Finally, the system
X| call handler (in C) is called.  When it returns, interrupts are disabled
X| again and the code falls into the restart routine, to finish off held-up
X| interrupts and run the process or task whose pointer is in 'proc_ptr'.
X| Hardware interrupt handlers do the same, except  (1) The entire state must
X| be saved.  (2) There are too many handlers to do this inline, so the save
X| routine is called.  A few cycles are saved by pushing the address of the
X| appropiate restart routine for a return later.  (3) A stack switch is
X| avoided when the stack is already switched.  (4) The (master) 8259 interrupt
X| controller is reenabled centrally in save().  (5) Each interrupt handler
X| masks its interrupt line using the 8259 before enabling (other unmasked)
X| interrupts, and unmasks it after servicing the interrupt.  This limits the
X| nest level to the number of lines and protects the handler from itself.
X#include <minix/config.h>
X#include <minix/const.h>
X#include <minix/com.h>
X#include "const.h"
X#include "sconst.h"
X| The external entry points into this file are:
X.define		_db		| trap to external debugger
X.define		_get_word	| returns word at given segment:offset
X.define		_put_word	| writes given word to given segment:offset
X| _get_word and _put_word may only be called in real mode from cstart().
X.define	_clock_int	| clock interrupt routine (HZ times per second)
X.define	_disk_int	| disk interrupt routine
X.define	_idle_task	| executed when there is no work
X.define	_int00		| handlers for unused interrupt vectors < 17
X.define	_int01
X.define	_int02
X.define	_int03
X.define	_int04
X.define	_int05
X.define	_int06
X.define	_int07
X.define	_int08
X.define	_int09
X.define	_int10
X.define	_int11
X.define	_int12
X.define	_int13
X.define	_int14
X.define	_int15
X.define	_int16
X.define	_lpr_int	| interrupt routine for each line printer interrupt
X.define	_mpx_1hook	| init from real mode for real or protected mode
X.define	_mpx_2hook	| init from protected mode for real or protected mode
X.define	_restart	| start running a task or process
X.define	save		| save the machine state in the proc table
X.define	_s_call		| process or task wants to send or receive a message
X.define	_trp		| all traps with vector >= 17 are vectored here
X.define	_tty_int	| interrupt routine for each key depression and release
X.define	_wini_int	| winchester interrupt routine
X#if INTEL_32BITS
X#error /* this is not the 32-bit version */
X#include "protect.h"
X#endif
X| When using the more portable but slower C-code RS232 interrupt handlers,
X| there are a few more entry points:
X#if C_RS232_INT_HANDLERS
X.define	_prs232_int	| same as rs232_int, different label for prot mode
X.define	_psecondary_int	| same as secondary_int, different label for prot mode
X.define	_rs232_int 	| interrupt routine for each rs232 interrupt on port 1
X.define	_secondary_int 	| interrupt routine for each rs232 interrupt on port 2
X#endif
X| When networking is enabled, the _eth_int entry point is used instead of the
X| various _secondary_int entry points.
X#if NETWORKING_ENABLED
X.define	_eth_int	| ethernet interrupt routine
X#endif
X| Imported functions.
X.extern		_cstart
X.extern		_main
X.extern		_clock_handler
X.extern		_exception
X.extern		_interrupt
X.extern		kernel_ds
X.extern		_keyboard
X.extern		_pr_char
X.extern		_sys_call
X.extern		_unhold
X#if C_RS232_INT_HANDLERS
X.extern		_rs232_1handler
X.extern		_rs232_2handler
X#endif
X| Exported variables.
X.define		kernel_ds
X.bss
X.define		begbss
X.define		begdata
X.define		k_stktop
X.define		_sizes
X| Imported variables.
X.extern		_gdt
X.extern		_code_base
X.extern		_data_base
X.extern		_break_vector
X.extern		_db_enabled
X.extern		_held_head
X.extern		_k_reenter
X.extern		k_stktop
X.extern		_pc_at
X.extern		_proc_ptr
X.extern		_protected_mode
X.extern		_ps
X.extern		_ps_mca
X.extern		_sstep_vector
X/* BIOS software interrupts, subfunctions and return values. */
X#define SET_PROTECT_VEC		0x15	/* set protected mode */
X#	define SET_PROTECT_FUNC 0x89
X.text
X|*===========================================================================*
X|*				MINIX					     *
X|*===========================================================================*
XMINIX: | this is the entry point for the MINIX kernel
Xj over_kernel_ds	| skip over the next few bytes
X.word 	CLICK_SHIFT	| for the monitor: memory granularity
Xkernel_ds: 
X.word 	0x0000		| flags for the boot monitor, later kernel DS
Xover_kernel_ds: 
X| Set up kernel segment registers and stack.
X| The monitor sets cs and ds right.  ss still points to the monitor data,
X| because the boot parameters offset and size are on its stack.
X| Locate boot parameters and set segment registers.
Xpop	bx		| boot parameters offset
Xpop	cx		| boot parameters length
Xmov	dx,ss		| monitor data
Xmov	ax,ds		| kernel data
Xmov	es,ax
Xmov	ss,ax
Xmov	sp,#k_stktop	| set sp to point to the top of kernel stack
X| Real mode needs to get kernel DS from the code segment.
Xseg cs
Xmov	kernel_ds,ds
X| Call C startup code to prepare for switching modes.
Xpush	cx
Xpush	dx
Xpush	bx
Xpush	ds
Xpush	cs
Xcall	_cstart		| cstart(cs, ds, parmoff, parmseg, parmlen)
Xadd	sp,#5*2
X| Call the BIOS to switch to protected mode.
X| This is just to do any cleanup necessary, typically to disable a hardware
X| kludge which holds the A20 address line low.
X| The call requires the gdt as set up by prot_init():
X|	gdt pointer in gdt[1]
X|	idt pointer in gdt[2]
X|	new ds in gdt[3]
X|	new es in gdt[4]
X|	new ss in gdt[5]
X|	new cs in gdt[6]
X|	nothing in gdt[7] (overwritten with BIOS cs)
X|	ICW2 for master 8259 in bh
X|	ICW2 for slave 8259 in bl
X| The BIOS enables interrupts briefly - this is OK since the BIOS vectors
X| are still valid.
X| Most registers are destroyed.
X| The 8259's are reinitialised.
Xmov	si,#_gdt
Xmov	bx,#IRQ0_VECTOR * 256 + IRQ8_VECTOR
Xmovb	ah,#SET_PROTECT_FUNC
Xint	SET_PROTECT_VEC
X| Now the processor is in protected mode.
X| There is a little more protected mode initialization to do, but leave it
X| to main().
Xcall	_main
X|*===========================================================================*
X|*				db					     *
X|*===========================================================================*
X| PUBLIC void db();
X| Trap to external debugger.
X_db: 
Xint	3
Xret
X|*===========================================================================*
X|*				get_word				     *
X|*===========================================================================*
X| PUBLIC u16_t get_word(u16_t segment, u16_t *offset);
X| Load and return the word at the far pointer  segment:offset.
X_get_word: 
Xmov	cx,ds		| save ds
Xpop	dx		| return adr
Xpop	ds		| segment
Xpop	bx		| offset
Xsub	sp,#2+2		| adjust for parameters popped
Xmov	ax,(bx)		| load the word to return
Xmov	ds,cx		| restore ds
Xjmp	(dx)		| return
X|*===========================================================================*
X|*				put_word				     *
X|*===========================================================================*
X| PUBLIC void put_word(u16_t segment, u16_t *offset, u16_t value);
X| Store the word  value  at the far pointer  segment:offset.
X_put_word: 
Xmov	cx,ds		| save ds
Xpop	dx		| return adr
Xpop	ds		| segment
Xpop	bx		| offset
Xpop	ax		| value
Xsub	sp,#2+2+2	| adjust for parameters popped
Xmov	(bx),ax		| store the word
Xmov	ds,cx		| restore ds
Xjmp	(dx)		| return
X|*===========================================================================*
X|*				tty_int					     *
X|*===========================================================================*
X_tty_int: | Interrupt routine for terminal input.
Xcall	save		| save the machine state
Xin	INT_CTLMASK	| mask out further keyboard interrupts
Xorb	al,#KEYBOARD_MASK
Xout	INT_CTLMASK
Xsti			| allow unmasked, non-keyboard, interrupts
Xcall	_keyboard	| process a keyboard interrupt
Xcli
Xin	INT_CTLMASK	| unmask keyboard interrupt
Xandb	al,#notop(KEYBOARD_MASK)
Xout	INT_CTLMASK
Xret			| return to appropiate restart built by save()
X#if C_RS232_INT_HANDLERS
X|*===========================================================================*
X|*				rs232_int				     *
X|*===========================================================================*
X_rs232_int: | Interrupt routine for rs232 I/O.
X_prs232_int: 
Xcall	save
Xin	INT_CTLMASK
Xorb	al,#RS232_MASK
Xout	INT_CTLMASK
X| Do not enable interrupts, the handlers are not designed for it.
X| The mask was set as usual so the handler can reenable interrupts as desired.
Xcall	_rs232_1handler	| process a serial line 1 interrupt
Xin	INT_CTLMASK
Xandb	al,#notop(RS232_MASK)
Xout	INT_CTLMASK
Xret
X|*===========================================================================*
X|*				secondary_int				     *
X|*===========================================================================*
X_secondary_int: | Interrupt routine for rs232 port 2
X_psecondary_int: 
Xcall	save
Xin	INT_CTLMASK
Xorb	al,#SECONDARY_MASK
Xout	INT_CTLMASK
Xcall	_rs232_2handler	| process a serial line 2 interrupt
Xin	INT_CTLMASK
Xandb	al,#notop(SECONDARY_MASK)
Xout	INT_CTLMASK
Xret
X#endif /* C_RS232_INT_HANDLERS */
X|*===========================================================================*
X|*				lpr_int					     *
X|*===========================================================================*
X_lpr_int: | Interrupt routine for printer output.
Xcall	save
Xin	INT_CTLMASK
Xorb	al,#PRINTER_MASK
Xout	INT_CTLMASK
Xsti
Xcall	_pr_char	| process a line printer interrupt
Xcli
Xin	INT_CTLMASK
X#if ASLD
Xandb	al,#notop(PRINTER_MASK)
X#else
Xandb	al,#notop(PRINTER_MASK) & 0xFF
X#endif
Xout	INT_CTLMASK
Xret
X|*===========================================================================*
X|*				disk_int				     *
X|*===========================================================================*
X_disk_int: | Interrupt routine for the floppy disk.
Xcall	save
Xcmp	_ps,#0		| check for 2nd int controller on ps (?)
Xje	over_ps_disk
Xmovb	al,#ENABLE
Xout	0x3C
Xover_ps_disk: 
X| The last doesn't make sense as an 8259 command, since the floppy vector
X| seems to be the same on PS's so the usual 8259 must be controlling it.
X| This used to be done at the start of the interrupt handler, in proc.c.
X| Find out where it really goes, and if there are any mask bits in port
X| 0x3D which have to be fiddled (here and in fdc_results()).
Xin	INT_CTLMASK
Xorb	al,#FLOPPY_MASK
Xout	INT_CTLMASK
Xsti
Xmov	ax,#FLOPPY
Xpush	ax
Xcall	_interrupt	| interrupt(FLOPPY)
Xadd	sp,#2
Xcli
Xret
X|*===========================================================================*
X|*				wini_int				     *
X|*===========================================================================*
X_wini_int: | Interrupt routine for the winchester disk.
Xcall	save
Xcmp	_pc_at,#0	| check for 2nd int controller on AT
Xjnz	at_wini_int
Xxt_wini_int: 
Xin	INT_CTLMASK
Xorb	al,#XT_WINI_MASK
Xout	INT_CTLMASK
Xsti
Xmov	ax,#WINCHESTER
Xpush	ax
Xcall	_interrupt	| interrupt(WINCHESTER)
Xadd	sp,#2
Xcli
Xret
Xat_wini_int: 
Xin	INT2_MASK
Xorb	al,#AT_WINI_MASK
Xout	INT2_MASK
Xsti
Xmovb	al,#ENABLE	| reenable slave 8259
Xout	INT2_CTL	| the master one was done in save() as usual
Xmov	ax,#WINCHESTER
Xpush	ax
Xcall	_interrupt	| interrupt(WINCHESTER)
Xadd	sp,#2
Xcli
Xret
X|*===========================================================================*
X|*				clock_int				     *
X|*===========================================================================*
X_clock_int: | Interrupt routine for the clock.
Xcall	save
Xcmp	_ps_mca, #0	| if not a PS/2, don't twiddle bits
Xje	skip_mca_clock
Xin	CLOCK_ACK_PORT	| PS/2 clock needs to be told to stop
Xorb	al,#CLOCK_ACK_BIT	| interrupting CPU, or we'll hang
Xout	CLOCK_ACK_PORT
Xskip_mca_clock: 
Xin	INT_CTLMASK
Xorb	al,#CLOCK_MASK
Xout	INT_CTLMASK
Xsti
Xcall	_clock_handler	| process a clock interrupt
X| This calls interrupt() only if necessary.
X| Very rarely.
Xcli
Xin	INT_CTLMASK
Xandb	al,#notop(CLOCK_MASK)
Xout	INT_CTLMASK
Xret
X|*===========================================================================*
X|*				eth_int					     *
X|*===========================================================================*
X#if 0 /* original version */
X_eth_int: | Interrupt routine for ethernet input
Xcall	save
Xin	INT_CTLMASK
Xorb	al,#ETHER_MASK
Xout	INT_CTLMASK
Xsti
Xcall	_dp8390_int	| call the handler
Xcli
Xret
X#endif
X#if NETWORKING_ENABLED
X_eth_int: | Interrupt routine for ethernet input
Xcall	save
Xin	INT_CTLMASK
Xorb	al,#ETHER_MASK
Xout	INT_CTLMASK
Xsti
Xmov	ax,#DL_ETH	| EHW_TASK accepts all packets, so it can be
X| interrupted
Xpush	ax
Xcall	_interrupt	| interrupt(EHW_TASK)
Xadd	sp,#2
Xcli
Xin	INT_CTLMASK
Xandb	al,#notop(ETHER_MASK)
Xout	INT_CTLMASK
Xret
X#endif
X|*===========================================================================*
X|*				int00-16				     *
X|*===========================================================================*
X_int00: | interrupt through vector 0
Xpush	ax
Xmovb	al,#0
Xj exception
X_int01: | interrupt through vector 1, etc
Xpush	ds
Xseg cs
Xmov	ds,kernel_ds
Xcmpb	_db_enabled,#0
Xpop	ds
Xjz	over_sstep
Xseg cs
Xjmpi @cs_sstep_vector
Xover_sstep: 
Xpush	ax
Xmovb	al,#1
Xj exception
X_int02: 
Xpush	ax
Xmovb	al,#2
Xj exception
X_int03: 
Xpush	ds
Xseg cs
Xmov	ds,kernel_ds
Xcmpb	_db_enabled,#0
Xpop	ds
Xjz	over_breakpoint
Xseg cs
Xjmpi @cs_break_vector
Xover_breakpoint: 
Xpush	ax
Xmovb	al,#3
Xj exception
X_int04: 
Xpush	ax
Xmovb	al,#4
Xj exception
X_int05: 
Xpush	ax
Xmovb	al,#5
Xj exception
X_int06: 
Xpush	ax
Xmovb	al,#6
Xj exception
X_int07: 
Xpush	ax
Xmovb	al,#7
Xj exception
X_int08: 
Xpush	ax
Xmovb	al,#8
Xj exception
X_int09: 
Xpush	ax
Xmovb	al,#9
Xj exception
X_int10: 
Xpush	ax
Xmovb	al,#10
Xj exception
X_int11: 
Xpush	ax
Xmovb	al,#11
Xj exception
X_int12: 
Xpush	ax
Xmovb	al,#12
Xj exception
X_int13: 
Xpush	ax
Xmovb	al,#13
Xj exception
X_int14: 
Xpush	ax
Xmovb	al,#14
Xj exception
X_int15: 
Xpush	ax
Xmovb	al,#15
Xj exception
X_int16: 
Xpush	ax
Xmovb	al,#16
Xj exception
X_trp: 
Xpush	ax
Xmovb	al,#17		| any vector above 17 becomes 17
Xexception: 
Xseg cs
Xmovb	ex_number,al	| it's cumbersome to get this into dseg
Xpop	ax
Xcall	save
Xseg cs
Xpush	ex_number	| high byte is constant 0
Xcall	_exception	| do whatever's necessary (sti only if safe)
Xadd	sp,#2
Xcli
Xret
X|*===========================================================================*
X|*				save					     *
X|*===========================================================================*
Xsave: | save the machine state in the proc table.
Xcld			| set direction flag to a known value
Xpush	ds
Xpush	si
Xseg cs
Xmov	ds,kernel_ds
Xincb	_k_reenter	| from -1 if not reentering
Xjnz	push_current_stack	| stack is already kernel's
Xmov	si,_proc_ptr
Xmov	AXREG(si),ax
Xmov	BXREG(si),bx
Xmov	CXREG(si),cx
Xmov	DXREG(si),dx
Xpop	SIREG(si)
Xmov	DIREG(si),di
Xmov	BPREG(si),bp
Xmov	ESREG(si),es
Xpop	DSREG(si)
Xpop	bx		| return adr
Xpop	PCREG(si)
Xpop	CSREG(si)
Xpop	PSWREG(si)
Xmov	SPREG(si),sp
Xmov	SSREG(si),ss
Xmov	dx,ds
Xmov	ss,dx
Xmov	sp,#k_stktop
X#if SPLIMITS
Xmov	splimit,#k_stack+8
X#endif
Xmov	ax,#_restart	| build return address for interrupt handler
Xpush	ax
Xstack_switched: 
Xmov	es,dx
Xmovb	al,#ENABLE	| reenable int controller for everyone (early)
Xout	INT_CTL
Xjmp	(bx)
Xpush_current_stack: 
Xpush	es
Xpush	bp
Xpush	di
Xpush	dx
Xpush	cx
Xpush	bx
Xpush	ax
Xmov	bp,sp
Xmov	bx,18(bp)	| get the return adr; it becomes junk on stack
Xmov	ax,#restart1
Xpush	ax
Xmov	dx,ss
Xmov	ds,dx
Xj stack_switched
X|*===========================================================================*
X|*				s_call					     *
X|*===========================================================================*
X_s_call: | System calls are vectored here.
X| Do save routine inline for speed,
X| but don't save ax, bx, cx, dx,
X| since C doesn't require preservation,
X| and ax returns the result code anyway.
X| Regs bp, si, di get saved by sys_call as
X| well, but it is impractical not to preserve
X| them here, in case context gets switched.
X| Some special-case code in pick_proc()
X| could avoid this.
Xcld			| set direction flag to a known value
Xpush	ds
Xpush	si
Xseg cs
Xmov	ds,kernel_ds
Xincb	_k_reenter
Xmov	si,_proc_ptr
Xpop	SIREG(si)
Xmov	DIREG(si),di
Xmov	BPREG(si),bp
Xmov	ESREG(si),es
Xpop	DSREG(si)
Xpop	PCREG(si)
Xpop	CSREG(si)
Xpop	PSWREG(si)
Xmov	SPREG(si),sp
Xmov	SSREG(si),ss
Xmov	dx,ds
Xmov	es,dx
Xmov	ss,dx		| interrupt handlers may not make system calls
Xmov	sp,#k_stktop	| so stack is not already switched
X#if SPLIMITS
Xmov	splimit,#k_stack+8
X#endif
X| end of inline save
X| now set up parameters for C routine sys_call
Xpush	bx		| pointer to user message
Xpush	ax		| src/dest
Xpush	cx		| SEND/RECEIVE/BOTH
Xsti			| allow SWITCHER to be interrupted
Xcall	_sys_call	| sys_call(function, src_dest, m_ptr)
X| caller is now explicitly in proc_ptr
Xmov	AXREG(si),ax	| sys_call MUST PRESERVE si
Xcli
X| Fall into code to restart proc/task running.
X|*===========================================================================*
X|*				restart					     *
X|*===========================================================================*
X_restart: 
X| Flush any held-up interrupts.
X| This reenables interrupts, so the current interrupt handler may reenter.
X| This doesn't matter, because the current handler is about to exit and no
X| other handlers can reenter since flushing is only done when k_reenter == 0.
Xcmp	_held_head,#0	| do fast test to usually avoid function call
Xjz	over_call_unhold
Xcall	_unhold		| this is rare so overhead is acceptable
Xover_call_unhold: 
Xmov	si,_proc_ptr
X#if SPLIMITS
Xmov	ax,P_SPLIMIT(si)	| splimit = p_splimit
Xmov	splimit,ax
X#endif
Xdecb	_k_reenter
Xmov	ax,AXREG(si)	| start restoring registers from proc table
X| could make AXREG == 0 to use lodw here
Xmov	bx,BXREG(si)
Xmov	cx,CXREG(si)
Xmov	dx,DXREG(si)
Xmov	di,DIREG(si)
Xmov	bp,BPREG(si)
Xmov	es,ESREG(si)
Xmov	ss,SSREG(si)
Xmov	sp,SPREG(si)
Xpush	PSWREG(si)	| fake interrupt stack frame
Xpush	CSREG(si)
Xpush	PCREG(si)
X| could put si:ds together to use
X| lds si,SIREG(si)
Xpush	DSREG(si)
Xmov	si,SIREG(si)
Xpop	ds
Xnop			| helps debugger emulate iret - else pop skips
Xiret			| return to user or task
Xrestart1: 
Xdecb	_k_reenter
Xpop	ax
Xpop	bx
Xpop	cx
Xpop	dx
Xpop	di
Xpop	bp
Xpop	es
Xpop	si
Xpop	ds
Xadd	sp,#2		| skip return adr
Xiret
X|*===========================================================================*
X|*				idle					     *
X|*===========================================================================*
X_idle_task: | executed when there is no work
Xj _idle_task	| a "hlt" before this fails in protected mode
X|*===========================================================================*
X|*				mpx_1hook				     *
X|*===========================================================================*
X| PUBLIC void mpx_1hook();
X| Initialize klib from real mode for real or protected mode:
X| Copy real mode debugger vectors to code segment.
X| They are too hard to access at interrupt time.
X_mpx_1hook: 
Xpush	ds
Xmov	ax,#0		| VEC_TABLE_SEG
Xmov	ds,ax
Xmov	ax,4*BREAKPOINT_VECTOR
Xseg cs
Xmov	cs_break_vector,ax
Xmov	ax,4*BREAKPOINT_VECTOR+2
Xseg cs
Xmov	cs_break_vector+2,ax
Xmov	ax,4*DEBUG_VECTOR
Xseg cs
Xmov	cs_sstep_vector,ax
Xmov	ax,4*DEBUG_VECTOR+2
Xseg cs
Xmov	cs_sstep_vector+2,ax
Xpop	ds
Xret
X|*===========================================================================*
X|*				data					     *
X|*===========================================================================*
X| NB some variables are stored in code segment.
Xcs_break_vector: | copy of real mode breakpoint vector
X.space	4
Xcs_sstep_vector: | copy of real mode single-step vector
X.space	4
Xex_number: | exception number
X.space	2
X|*===========================================================================*
X|*			variants for 286 protected mode			     *
X|*===========================================================================*
X| Most routines are different in 286 protected mode.
X| The only essential difference is that an interrupt in protected mode
X| (usually) switches the stack, so there is less to do in software.
X| These functions are reached along jumps patched in by klib286_init():
X.define		p_restart	| replaces _restart
X.define		p_save		| replaces save
X| These exception and software-interrupt handlers are enabled by the new
X| interrupt vector table set up in protect.c:
X.define		_divide_error		| _int00
X.define		_single_step_exception	| _int01
X.define		_nmi			| _int02
X.define		_breakpoint_exception	| _int03
X.define		_overflow		| _int04
X.define		_bounds_check		| _int05
X.define		_inval_opcode		| _int06
X.define		_copr_not_available	| _int07
X.define		_double_fault		| _int08
X.define		_copr_seg_overrun	| _int09
X.define		_inval_tss		| _int10
X.define		_segment_not_present	| _int11
X.define		_stack_exception	| _int12
X.define		_general_protection	| _int13
X.define		_p_s_call		| _s_call
X| The hardware interrupt handlers need not be altered apart from putting
X| them in the new table (save() handles the differences).
X| Some of the intxx handlers (those for exceptions which don't push an
X| error code) need not have been replaced, but the names here are better.
X#include "protect.h"
X/* Selected 286 tss offsets. */
X#define TSS2_S_SP0	2
X| imported variables
X.bss
X.extern		_tss
X.text
X|*===========================================================================*
X|*				exception handlers			     *
X|*===========================================================================*
X_divide_error: 
Xpushi8	(DIVIDE_VECTOR)
Xj p_exception
X_single_step_exception: 
Xseg ss
Xcmpb	_db_enabled,#0
Xjz	p_over_sstep
Xseg ss
Xjmpi @_sstep_vector
Xp_over_sstep: 
Xpushi8	(DEBUG_VECTOR)
Xj p_exception
X_nmi: 
Xpushi8	(NMI_VECTOR)
Xj p_exception
X_breakpoint_exception: 
Xseg ss
Xcmpb	_db_enabled,#0
Xjz	p_over_breakpoint
Xseg ss
Xjmpi @_break_vector
Xp_over_breakpoint: 
Xpushi8	(BREAKPOINT_VECTOR)
Xj p_exception
X_overflow: 
Xpushi8	(OVERFLOW_VECTOR)
Xj p_exception
X_bounds_check: 
Xpushi8	(BOUNDS_VECTOR)
Xj p_exception
X_inval_opcode: 
Xpushi8	(INVAL_OP_VECTOR)
Xj p_exception
X_copr_not_available: 
Xpushi8	(COPROC_NOT_VECTOR)
Xj p_exception
X_double_fault: 
Xpushi8	(DOUBLE_FAULT_VECTOR)
Xj errexception
X_copr_seg_overrun: 
Xpushi8	(COPROC_SEG_VECTOR)
Xj p_exception
X_inval_tss: 
Xpushi8	(INVAL_TSS_VECTOR)
Xj errexception
X_segment_not_present: 
Xpushi8	(SEG_NOT_VECTOR)
Xj errexception
X_stack_exception: 
Xpushi8	(STACK_FAULT_VECTOR)
Xj errexception
X_general_protection: 
Xpushi8	(PROTECTION_VECTOR)
Xj errexception
X|*===========================================================================*
X|*				p_exception				     *
X|*===========================================================================*
X| This is called for all exceptions which don't push an error code.
Xp_exception: 
Xseg ss
Xpop	ds_ex_number
Xcall	p_save
Xj p1_exception
X|*===========================================================================*
X|*				errexception				     *
X|*===========================================================================*
X| This is called for all exceptions which push an error code.
Xerrexception: 
Xseg ss
Xpop	ds_ex_number
Xseg ss
Xpop	trap_errno
Xcall	p_save
Xp1_exception: | Common for all exceptions.
Xpush	ds_ex_number
Xcall	_exception
Xadd	sp,#2
Xcli
Xret
X|*===========================================================================*
X|*				p_save					     *
X|*===========================================================================*
X| Save for 286 protected mode.
X| This is much simpler than for 8086 mode, because the stack already points
X| into process table, or has already been switched to the kernel stack.
Xp_save: 
Xcld			| set direction flag to a known value
Xpusha			| save "general" registers
Xpush	ds		| save ds
Xpush	es		| save es
Xmov	dx,ss		| ss is kernel data segment
Xmov	ds,dx		| load rest of kernel segments
Xmov	es,dx
Xmovb	al,#ENABLE	| reenable int controller
Xout	INT_CTL
Xmov	bp,sp		| prepare to return
Xincb	_k_reenter	| from -1 if not reentering
Xjnz	set_p1_restart	| stack is already kernel's
Xmov	sp,#k_stktop
X#if SPLIMITS
Xmov	splimit,#k_stack+8
X#endif
Xpushi16	(p_restart)	| build return address for interrupt handler
Xjmp	@RETADR-P_STACKBASE(bp)
Xset_p1_restart: 
Xpushi16	(p1_restart)
Xjmp	@RETADR-P_STACKBASE(bp)
X|*===========================================================================*
X|*				p_s_call				     *
X|*===========================================================================*
X_p_s_call: 
Xcld			| set direction flag to a known value
Xsub	sp,#6*2		| skip RETADR, ax, cx, dx, bx, st
Xpush	bp		| stack already points into process table
Xpush	si
Xpush	di
Xpush	ds
Xpush	es
Xmov	dx,ss
Xmov	ds,dx
Xmov	es,dx
Xincb	_k_reenter
Xmov	si,sp		| assumes P_STACKBASE == 0
Xmov	sp,#k_stktop
X#if SPLIMITS
Xmov	splimit,#k_stack+8
X#endif
X| end of inline save
Xsti			| allow SWITCHER to be interrupted
X| now set up parameters for C routine sys_call
Xpush	bx		| pointer to user message
Xpush	ax		| src/dest
Xpush	cx		| SEND/RECEIVE/BOTH
Xcall	_sys_call	| sys_call(function, src_dest, m_ptr)
X| caller is now explicitly in proc_ptr
Xmov	AXREG(si),ax	| sys_call MUST PRESERVE si
Xcli
X| Fall into code to restart proc/task running.
Xp_restart: 
X| Flush any held-up interrupts.
X| This reenables interrupts, so the current interrupt handler may reenter.
X| This doesn't matter, because the current handler is about to exit and no
X| other handlers can reenter since flushing is only done when k_reenter == 0.
Xcmp	_held_head,#0	| do fast test to usually avoid function call
Xjz	p_over_call_unhold
Xcall	_unhold		| this is rare so overhead is acceptable
Xp_over_call_unhold: 
Xmov	si,_proc_ptr
X#if SPLIMITS
Xmov	ax,P_SPLIMIT(si)	| splimit = p_splimit
Xmov	splimit,ax
X#endif
Xdeflldt	(P_LDT_SEL(si))		| enable task's segment descriptors
Xlea	ax,P_STACKTOP(si)	| arrange for next interrupt
Xmov	_tss+TSS2_S_SP0,ax	| to save state in process table
Xmov	sp,si		| assumes P_STACKBASE == 0
Xp1_restart: 
Xdecb	_k_reenter
Xpop	es
Xpop	ds
Xpopa
Xadd	sp,#2		| skip RETADR
Xiret			| continue process
X|*===========================================================================*
X|*				mpx_2hook				     *
X|*===========================================================================*
X| PUBLIC void mpx_2hook();
X| Initialize klib from protected mode for real or protected mode:
X| Nothing to do.
X_mpx_2hook: 
Xret
X|*===========================================================================*
X|*				data					     *
X|*===========================================================================*
X.data
Xbegdata: 
X_sizes: | sizes of kernel, mm, fs filled in by build
X.word 	0x526F		| this must be the first data entry (magic #)
X.word 	CLICK_SHIFT	| consistency check for build
X.zerow	6		| build uses prevous 2 words and this space
X.space	K_STACK_BYTES	| kernel stack
Xk_stktop: | top of kernel stack
X.bss
Xbegbss: 
Xds_ex_number: 
X.space	2
Xtrap_errno: 
X.space	2
/
echo x - rs2.x.ansi
sed '/^X/s///' > rs2.x.ansi << '/'
X!*===========================================================================*
X!*		rs232 interrupt handlers for real and protected modes	     *
X!*===========================================================================*
X! This is a fairly direct translation of the interrupt handlers in rs232.c.
X! See the comments there.
X! It is about 5 times as efficient, by avoiding save/restart and slow function
X! calls for port i/o as well as the compiler!
X
X#include <minix/config.h>
X
X#if !C_RS232_INT_HANDLERS /* otherwise, don't use anything in this file */
X
X#include <minix/const.h>
X#include "const.h"
X#include "sconst.h"
X
X! exported functions
X
X	.text
X.define		_prs232_int
X.define		_psecondary_int
X.define		_rs232_int		! used only for real mode
X.define		_secondary_int		! used only for real mode
X
X! imported functions
X
X.extern		kernel_ds
X.extern		save
X.extern		_tty_wakeup
X
X! imported variables
X
X	.bss
X.extern		_rs_lines
X.extern		_tty_events
X
X#undef MINOR
X
X#if !INTEL_32BITS
X#define eax ax			/* use 32-bit register names throughout */
X#define ebx bx			/* but modify them for 16-bit mode/CPU */
X#define edx dx
X#define esi si
X#define iretd iret
X#endif
X
X#if ASLD
X#define add1_and_align(n)	[[[n]+SIZEOF_INT] / SIZEOF_INT * SIZEOF_INT]
X#else
X#define add1_and_align(n)	(((n)+SIZEOF_INT) / SIZEOF_INT * SIZEOF_INT)
X#endif
X
X! These constants are defined in tty.h. That has C stuff so can't be included.
XEVENT_THRESHOLD		=	64
XRS_IBUFSIZE		=	256
X
X! These constants are defined in rs232.c.
XIS_LINE_STATUS_CHANGE	=	6
XIS_MODEM_STATUS_CHANGE	=	0
XIS_NO_INTERRUPT		=	1
XIS_RECEIVER_READY	=	4
XIS_TRANSMITTER_READY	=	2
XLS_OVERRUN_ERR		=	2
XLS_PARITY_ERR		=	4
XLS_FRAMING_ERR		=	8
XLS_BREAK_INTERRUPT	=	0x10
XLS_TRANSMITTER_READY	=	0x20
XMC_DTR			=	1
XMC_OUT2			=	8
XMS_CTS			=	0x10
XODEVREADY		=	MS_CTS
XODONE			=	1
XOQUEUED			=	0x20
XORAW			=	2
XOSWREADY		=	0x40
XOWAKEUP			=	4
XRS_IHIGHWATER		=	3*RS_IBUFSIZE/4
X
X! These port offsets are hard-coded in rs232.c.
XXMIT_OFFSET		=	0
XRECV_OFFSET		=	0
XINT_ID_OFFSET		=	2
XMODEM_CTL_OFFSET	=	4
XLINE_STATUS_OFFSET	=	5
XMODEM_STATUS_OFFSET	=	6
X
X! Offsets in struct rs232_s. They must match rs232.c
XMINOR			=	0
XIDEVREADY		=	MINOR+SIZEOF_INT
XITTYREADY		=	IDEVREADY+1
XIBUF			=	add1_and_align(ITTYREADY)
XIBUFEND			=	IBUF+SIZEOF_INT
XIHIGHWATER		=	IBUFEND+SIZEOF_INT
XIPTR			=	IHIGHWATER+SIZEOF_INT
XOSTATE			=	IPTR+SIZEOF_INT
XOXOFF			=	OSTATE+1
XOBUFEND			=	add1_and_align(OXOFF)
XOPTR			=	OBUFEND+SIZEOF_INT
XXMIT_PORT		=	OPTR+SIZEOF_INT
XRECV_PORT		=	XMIT_PORT+SIZEOF_INT
XDIV_LOW_PORT		=	RECV_PORT+SIZEOF_INT
XDIV_HI_PORT		=	DIV_LOW_PORT+SIZEOF_INT
XINT_ENAB_PORT		=	DIV_HI_PORT+SIZEOF_INT
XINT_ID_PORT		=	INT_ENAB_PORT+SIZEOF_INT
XLINE_CTL_PORT		=	INT_ID_PORT+SIZEOF_INT
XMODEMCTL_PORT		=	LINE_CTL_PORT+SIZEOF_INT
XLINESTATUS_PORT		=	MODEMCTL_PORT+SIZEOF_INT
XMODEMSTATUS_PORT	=	LINESTATUS_PORT+SIZEOF_INT
XLSTATUS			=	MODEMSTATUS_PORT+SIZEOF_INT
XFRAMING_ERRORS		=	add1_and_align(LSTATUS)
XOVERRUN_ERRORS		=	FRAMING_ERRORS+SIZEOF_INT
XPARITY_ERRORS		=	OVERRUN_ERRORS+SIZEOF_INT
XBREAK_INTERRUPTS	=	PARITY_ERRORS+SIZEOF_INT
XIBUF1			=	BREAK_INTERRUPTS+SIZEOF_INT
XIBUF2			=	IBUF1+RS_IBUFSIZE+1
XSIZEOF_STRUCT_RS232_S	=	add1_and_align(IBUF2+RS_IBUFSIZE)
X
X	.text
X
X! PUBLIC void interrupt _psecondary_int();
X
X_psecondary_int:
X	push	ds
X	push	esi
X	mov	si,ss
X	mov	ds,si
X	mov	esi,#_rs_lines+SIZEOF_STRUCT_RS232_S
X	jmp	common
X
X! PUBLIC void interrupt _secondary_int();
X
X_secondary_int:
X	push	ds
X	push	esi
X	mov	esi,#_rs_lines+SIZEOF_STRUCT_RS232_S
X	cseg
X	mov	ds,kernel_ds
X	jmp	common
X
X! PUBLIC void interrupt _prs232_int();
X
X_prs232_int:
X	push	ds
X	push	esi
X	mov	si,ss
X	mov	ds,si
X	mov	esi,#_rs_lines
X	jmp	common
X
X! input interrupt
X
Xinint:
X	addb	dl,#RECV_OFFSET-INT_ID_OFFSET
X	inb
X	mov	ebx,IPTR(esi)
X	movb	(ebx),al
X	cmp	ebx,IBUFEND(esi)
X	jge	checkxoff
X	inc	_tty_events
X	inc	ebx
X	mov	IPTR(esi),ebx
X	cmp	ebx,IHIGHWATER(esi)
X	jne	checkxoff
X	addb	dl,#MODEM_CTL_OFFSET-RECV_OFFSET
X	movb	al,#MC_OUT2+MC_DTR
X	outb
X	movb	IDEVREADY(esi),#FALSE
Xcheckxoff:
X	testb	ah,#ORAW
X	jne	rsnext
X	cmpb	al,OXOFF(esi)
X	je	gotxoff
X	testb	ah,#OSWREADY
X	jne	rsnext
X	orb	ah,#OSWREADY
X	mov	edx,LINESTATUS_PORT(esi)
X	inb
X	testb	al,#LS_TRANSMITTER_READY
X	je	rsnext
X	addb	dl,#XMIT_OFFSET-LINE_STATUS_OFFSET
X	jmp	outint1
X
Xgotxoff:
X	andb	ah,#notop(OSWREADY)
X	jmp	rsnext
X
X! PUBLIC void interrupt rs232_int();
X
X_rs232_int:
X	push	ds
X	push	esi
X	mov	esi,#_rs_lines
X	cseg
X	mov	ds,kernel_ds
X
Xcommon:
X	push	eax
X	push	ebx
X	push	edx
X	movb	ah,OSTATE(esi)
X	mov	edx,INT_ID_PORT(esi)
X	inb
Xrsmore:
X	cmpb	al,#IS_RECEIVER_READY
X	je	inint
X	cmpb	al,#IS_TRANSMITTER_READY
X	je	outint
X	cmpb	al,#IS_MODEM_STATUS_CHANGE
X	je	modemint
X	cmpb	al,#IS_LINE_STATUS_CHANGE
X	jne	rsdone		! fishy
X
X! line status change interrupt
X
X	addb	dl,#LINE_STATUS_OFFSET-INT_ID_OFFSET
X	inb
X	testb	al,#LS_FRAMING_ERR
X	je	over_framing_error
X	inc	FRAMING_ERRORS(esi)	
Xover_framing_error:
X	testb	al,#LS_OVERRUN_ERR
X	je	over_overrun_error
X	inc	OVERRUN_ERRORS(esi)	
Xover_overrun_error:
X	testb	al,#LS_PARITY_ERR
X	je	over_parity_error
X	inc	PARITY_ERRORS(esi)
Xover_parity_error:
X	testb	al,#LS_BREAK_INTERRUPT
X	je	over_break_interrupt
X	inc	BREAK_INTERRUPTS(esi)
Xover_break_interrupt:
X
Xrsnext:
X	mov	edx,INT_ID_PORT(esi)
X	inb
X	cmpb	al,#IS_NO_INTERRUPT
X	jne	rsmore
Xrsdone:
X	movb	al,#ENABLE
X	outb	INT_CTL
X	testb	ah,#OWAKEUP
X	jne	owakeup
X	movb	OSTATE(esi),ah
X	pop	edx
X	pop	ebx
X	pop	eax
X	pop	esi
X	pop	ds
X	iretd
X
X! output interrupt
X
Xoutint:
X	addb	dl,#XMIT_OFFSET-INT_ID_OFFSET
Xoutint1:
X	cmpb	ah,#ODEVREADY+OQUEUED+OSWREADY
X	jb	rsnext		! not all are set
X	mov	ebx,OPTR(esi)
X	movb	al,(ebx)
X	outb
X	inc	ebx
X	mov	OPTR(esi),ebx
X	cmp	ebx,OBUFEND(esi)
X	jb	rsnext
X	add	_tty_events,#EVENT_THRESHOLD
X	xorb	ah,#ODONE+OQUEUED+OWAKEUP	! OQUEUED off, others on
X	jmp	rsnext		! direct exit might lose interrupt
X
X! modem status change interrupt
X
Xmodemint:
X	addb	dl,#MODEM_STATUS_OFFSET-INT_ID_OFFSET
X	inb
X#if NO_HANDSHAKE
X	orb	al,#MS_CTS
X#endif
X	testb	al,#MS_CTS
X	jne	m_devready
X	andb	ah,#notop(ODEVREADY)
X	jmp	rsnext
X
Xm_devready:
X	testb	ah,#ODEVREADY
X	jne	rsnext
X	orb	ah,#ODEVREADY
X	addb	dl,#LINE_STATUS_OFFSET-MODEM_STATUS_OFFSET
X	inb
X	testb	al,#LS_TRANSMITTER_READY
X	je	rsnext
X	addb	dl,#XMIT_OFFSET-LINE_STATUS_OFFSET
X	jmp	outint1
X
X! special exit for output just completed
X
Xowakeup:
X	andb	ah,#notop(OWAKEUP)
X	movb	OSTATE(esi),ah
X
X! determine mask bit (it would be better to precalculate it in the struct)
X
X	movb	ah,#SECONDARY_MASK
X	cmp	esi,#_rs_lines
X	jne	got_rs_mask
X	movb	ah,#RS232_MASK
Xgot_rs_mask:
X	mov	rs_mask,eax	! save mask to clear later
X	inb	INT_CTLMASK
X	orb	al,ah
X	outb	INT_CTLMASK
X
X! rearrange context to call tty_wakeup()
X
X	pop	edx
X	pop	ebx
X	pop	eax
X	pop	esi
X	pop	ds
X	call	save
X	push	rs_mask		! save the mask again, reentrantly
X	sti
X	call	_tty_wakeup
X	cli
X	pop	eax
X	notb	ah		! return this
X	inb	INT_CTLMASK
X	andb	al,ah
X	outb	INT_CTLMASK
X	ret
X
X
X	.data
Xrs_mask:
X	.space	2
X	.space	2		! align
X
X#endif /* !C_RS232_INT_HANDLERS */
/
echo x - rs2.x.kr
sed '/^X/s///' > rs2.x.kr << '/'
X|*===========================================================================*
X|*		rs232 interrupt handlers for real and protected modes	     *
X|*===========================================================================*
X| This is a fairly direct translation of the interrupt handlers in rs232.c.
X| See the comments there.
X| It is about 5 times as efficient, by avoiding save/restart and slow function
X| calls for port i/o as well as the compiler!
X#include <minix/config.h>
X#if !C_RS232_INT_HANDLERS /* otherwise, don't use anything in this file */
X#include <minix/const.h>
X#include "const.h"
X#include "sconst.h"
X| exported functions
X.text
X.define		_prs232_int
X.define		_psecondary_int
X.define		_rs232_int		| used only for real mode
X.define		_secondary_int		| used only for real mode
X| imported functions
X.extern		kernel_ds
X.extern		save
X.extern		_tty_wakeup
X| imported variables
X.bss
X.extern		_rs_lines
X.extern		_tty_events
X#undef MINOR
X#if !INTEL_32BITS
X#define eax ax			/* use 32-bit register names throughout */
X#define ebx bx			/* but modify them for 16-bit mode/CPU */
X#define edx dx
X#define esi si
X#define iretd iret
X#endif
X#if ASLD
X#define add1_and_align(n)	[[[n]+SIZEOF_INT] / SIZEOF_INT * SIZEOF_INT]
X#else
X#define add1_and_align(n)	(((n)+SIZEOF_INT) / SIZEOF_INT * SIZEOF_INT)
X#endif
X| These constants are defined in tty.h. That has C stuff so can't be included.
XEVENT_THRESHOLD		=	64
XRS_IBUFSIZE		=	256
X| These constants are defined in rs232.c.
XIS_LINE_STATUS_CHANGE	=	6
XIS_MODEM_STATUS_CHANGE	=	0
XIS_NO_INTERRUPT		=	1
XIS_RECEIVER_READY	=	4
XIS_TRANSMITTER_READY	=	2
XLS_OVERRUN_ERR		=	2
XLS_PARITY_ERR		=	4
XLS_FRAMING_ERR		=	8
XLS_BREAK_INTERRUPT	=	0x10
XLS_TRANSMITTER_READY	=	0x20
XMC_DTR			=	1
XMC_OUT2			=	8
XMS_CTS			=	0x10
XODEVREADY		=	MS_CTS
XODONE			=	1
XOQUEUED			=	0x20
XORAW			=	2
XOSWREADY		=	0x40
XOWAKEUP			=	4
XRS_IHIGHWATER		=	3*RS_IBUFSIZE/4
X| These port offsets are hard-coded in rs232.c.
XXMIT_OFFSET		=	0
XRECV_OFFSET		=	0
XINT_ID_OFFSET		=	2
XMODEM_CTL_OFFSET	=	4
XLINE_STATUS_OFFSET	=	5
XMODEM_STATUS_OFFSET	=	6
X| Offsets in struct rs232_s. They must match rs232.c
XMINOR			=	0
XIDEVREADY		=	MINOR+SIZEOF_INT
XITTYREADY		=	IDEVREADY+1
XIBUF			=	add1_and_align(ITTYREADY)
XIBUFEND			=	IBUF+SIZEOF_INT
XIHIGHWATER		=	IBUFEND+SIZEOF_INT
XIPTR			=	IHIGHWATER+SIZEOF_INT
XOSTATE			=	IPTR+SIZEOF_INT
XOXOFF			=	OSTATE+1
XOBUFEND			=	add1_and_align(OXOFF)
XOPTR			=	OBUFEND+SIZEOF_INT
XXMIT_PORT		=	OPTR+SIZEOF_INT
XRECV_PORT		=	XMIT_PORT+SIZEOF_INT
XDIV_LOW_PORT		=	RECV_PORT+SIZEOF_INT
XDIV_HI_PORT		=	DIV_LOW_PORT+SIZEOF_INT
XINT_ENAB_PORT		=	DIV_HI_PORT+SIZEOF_INT
XINT_ID_PORT		=	INT_ENAB_PORT+SIZEOF_INT
XLINE_CTL_PORT		=	INT_ID_PORT+SIZEOF_INT
XMODEMCTL_PORT		=	LINE_CTL_PORT+SIZEOF_INT
XLINESTATUS_PORT		=	MODEMCTL_PORT+SIZEOF_INT
XMODEMSTATUS_PORT	=	LINESTATUS_PORT+SIZEOF_INT
XLSTATUS			=	MODEMSTATUS_PORT+SIZEOF_INT
XFRAMING_ERRORS		=	add1_and_align(LSTATUS)
XOVERRUN_ERRORS		=	FRAMING_ERRORS+SIZEOF_INT
XPARITY_ERRORS		=	OVERRUN_ERRORS+SIZEOF_INT
XBREAK_INTERRUPTS	=	PARITY_ERRORS+SIZEOF_INT
XIBUF1			=	BREAK_INTERRUPTS+SIZEOF_INT
XIBUF2			=	IBUF1+RS_IBUFSIZE+1
XSIZEOF_STRUCT_RS232_S	=	add1_and_align(IBUF2+RS_IBUFSIZE)
X.text
X| PUBLIC void interrupt _psecondary_int();
X_psecondary_int: 
Xpush	ds
Xpush	esi
Xmov	si,ss
Xmov	ds,si
Xmov	esi,#_rs_lines+SIZEOF_STRUCT_RS232_S
Xj common
X| PUBLIC void interrupt _secondary_int();
X_secondary_int: 
Xpush	ds
Xpush	esi
Xmov	esi,#_rs_lines+SIZEOF_STRUCT_RS232_S
Xseg cs
Xmov	ds,kernel_ds
Xj common
X| PUBLIC void interrupt _prs232_int();
X_prs232_int: 
Xpush	ds
Xpush	esi
Xmov	si,ss
Xmov	ds,si
Xmov	esi,#_rs_lines
Xj common
X| input interrupt
Xinint: 
Xaddb	dl,#RECV_OFFSET-INT_ID_OFFSET
Xin
Xmov	ebx,IPTR(esi)
Xmovb	(ebx),al
Xcmp	ebx,IBUFEND(esi)
Xjge	checkxoff
Xinc	_tty_events
Xinc	ebx
Xmov	IPTR(esi),ebx
Xcmp	ebx,IHIGHWATER(esi)
Xjne	checkxoff
Xaddb	dl,#MODEM_CTL_OFFSET-RECV_OFFSET
Xmovb	al,#MC_OUT2+MC_DTR
Xout
Xmovb	IDEVREADY(esi),#FALSE
Xcheckxoff: 
Xtestb	ah,#ORAW
Xjne	rsnext
Xcmpb	al,OXOFF(esi)
Xje	gotxoff
Xtestb	ah,#OSWREADY
Xjne	rsnext
Xorb	ah,#OSWREADY
Xmov	edx,LINESTATUS_PORT(esi)
Xin
Xtestb	al,#LS_TRANSMITTER_READY
Xje	rsnext
Xaddb	dl,#XMIT_OFFSET-LINE_STATUS_OFFSET
Xj outint1
Xgotxoff: 
Xandb	ah,#notop(OSWREADY)
Xj rsnext
X| PUBLIC void interrupt rs232_int();
X_rs232_int: 
Xpush	ds
Xpush	esi
Xmov	esi,#_rs_lines
Xseg cs
Xmov	ds,kernel_ds
Xcommon: 
Xpush	eax
Xpush	ebx
Xpush	edx
Xmovb	ah,OSTATE(esi)
Xmov	edx,INT_ID_PORT(esi)
Xin
Xrsmore: 
Xcmpb	al,#IS_RECEIVER_READY
Xje	inint
Xcmpb	al,#IS_TRANSMITTER_READY
Xje	outint
Xcmpb	al,#IS_MODEM_STATUS_CHANGE
Xje	modemint
Xcmpb	al,#IS_LINE_STATUS_CHANGE
Xjne	rsdone		| fishy
X| line status change interrupt
Xaddb	dl,#LINE_STATUS_OFFSET-INT_ID_OFFSET
Xin
Xtestb	al,#LS_FRAMING_ERR
Xje	over_framing_error
Xinc	FRAMING_ERRORS(esi)
Xover_framing_error: 
Xtestb	al,#LS_OVERRUN_ERR
Xje	over_overrun_error
Xinc	OVERRUN_ERRORS(esi)
Xover_overrun_error: 
Xtestb	al,#LS_PARITY_ERR
Xje	over_parity_error
Xinc	PARITY_ERRORS(esi)
Xover_parity_error: 
Xtestb	al,#LS_BREAK_INTERRUPT
Xje	over_break_interrupt
Xinc	BREAK_INTERRUPTS(esi)
Xover_break_interrupt: 
Xrsnext: 
Xmov	edx,INT_ID_PORT(esi)
Xin
Xcmpb	al,#IS_NO_INTERRUPT
Xjne	rsmore
Xrsdone: 
Xmovb	al,#ENABLE
Xout	INT_CTL
Xtestb	ah,#OWAKEUP
Xjne	owakeup
Xmovb	OSTATE(esi),ah
Xpop	edx
Xpop	ebx
Xpop	eax
Xpop	esi
Xpop	ds
Xiretd
X| output interrupt
Xoutint: 
Xaddb	dl,#XMIT_OFFSET-INT_ID_OFFSET
Xoutint1: 
Xcmpb	ah,#ODEVREADY+OQUEUED+OSWREADY
Xjb	rsnext		| not all are set
Xmov	ebx,OPTR(esi)
Xmovb	al,(ebx)
Xout
Xinc	ebx
Xmov	OPTR(esi),ebx
Xcmp	ebx,OBUFEND(esi)
Xjb	rsnext
Xadd	_tty_events,#EVENT_THRESHOLD
Xxorb	ah,#ODONE+OQUEUED+OWAKEUP	| OQUEUED off, others on
Xj rsnext		| direct exit might lose interrupt
X| modem status change interrupt
Xmodemint: 
Xaddb	dl,#MODEM_STATUS_OFFSET-INT_ID_OFFSET
Xin
X#if NO_HANDSHAKE
Xorb	al,#MS_CTS
X#endif
Xtestb	al,#MS_CTS
Xjne	m_devready
Xandb	ah,#notop(ODEVREADY)
Xj rsnext
Xm_devready: 
Xtestb	ah,#ODEVREADY
Xjne	rsnext
Xorb	ah,#ODEVREADY
Xaddb	dl,#LINE_STATUS_OFFSET-MODEM_STATUS_OFFSET
Xin
Xtestb	al,#LS_TRANSMITTER_READY
Xje	rsnext
Xaddb	dl,#XMIT_OFFSET-LINE_STATUS_OFFSET
Xj outint1
X| special exit for output just completed
Xowakeup: 
Xandb	ah,#notop(OWAKEUP)
Xmovb	OSTATE(esi),ah
X| determine mask bit (it would be better to precalculate it in the struct)
Xmovb	ah,#SECONDARY_MASK
Xcmp	esi,#_rs_lines
Xjne	got_rs_mask
Xmovb	ah,#RS232_MASK
Xgot_rs_mask: 
Xmov	rs_mask,eax	| save mask to clear later
Xin	INT_CTLMASK
Xorb	al,ah
Xout	INT_CTLMASK
X| rearrange context to call tty_wakeup()
Xpop	edx
Xpop	ebx
Xpop	eax
Xpop	esi
Xpop	ds
Xcall	save
Xpush	rs_mask		| save the mask again, reentrantly
Xsti
Xcall	_tty_wakeup
Xcli
Xpop	eax
Xnotb	ah		| return this
Xin	INT_CTLMASK
Xandb	al,ah
Xout	INT_CTLMASK
Xret
X.data
Xrs_mask: 
X.space	2
X.space	2		| align
X#endif /* !C_RS232_INT_HANDLERS */
/
echo x - sconst.h.ansi
sed '/^X/s///' > sconst.h.ansi << '/'
X/* Miscellaneous constants used in assembler code. */
X#define HCHIGH_MASK	0x0F	/* h/w click mask for low byte of hi word */
X#define HCLOW_MASK	0xF0	/* h/w click mask for low byte of low word */
X#define TEST1PATTERN	0x55	/* memory test pattern 1 */
X#define TEST2PATTERN	0xAA	/* memory test pattern 2 */
X
X/* Magic numbers for color status port. */
X#define COLOR_STATUS_PORT	0x3DA
X#	define VERTICAL_RETRACE_MASK	0x08
X
X/* 8259 mask bits. */
X#define AT_WINI_MASK	0x40	/* (1 << (AT_WINI_IRQ & 0x07)), etc */
X#define CLOCK_MASK	0x01
X#define ETHER_MASK	0x08
X#define FLOPPY_MASK	0x40
X#define KEYBOARD_MASK	0x02
X#define PRINTER_MASK	0x80
X#define RS232_MASK	0x10
X#define SECONDARY_MASK	0x08
X#define XT_WINI_MASK	0x20
X
X/* Device interrupt acknowledge ports and bits. */
X#define CLOCK_ACK_BIT	0x80
X#define CLOCK_ACK_PORT	PORT_B
X
X/* Offsets in struct proc. They MUST match proc.h. */
X#define P_STACKBASE	0
X#define ESREG		0
X#define DSREG		2
X#define DIREG		4
X#define SIREG		6
X#define BPREG		8
X#define STREG		10	/* hole for another SP */
X#define BXREG		12
X#define DXREG		14
X#define CXREG		16
X#define AXREG		18
X#define RETADR		20	/* return address for save() call */
X#define PCREG		22
X#define CSREG		24
X#define PSWREG		26
X#define SPREG		28
X#define SSREG		30
X#define P_STACKTOP	32
X
X#if INTEL_32BITS
X/* The registers are twice as wide. There are 2 extra segment regs, but
X * these are packed in the double-width es and ds slots.
X */
XEAXREG		=	2 * AXREG	/* use "=" to avoid parentheses */
XERETADR		=	2 * RETADR
XEPCREG		=	2 * PCREG
XECSREG		=	2 * CSREG
XEPSWREG		=	2 * PSWREG
XP3_STACKTOP	=	2 * P_STACKTOP
X#define P_LDT_SEL	P3_STACKTOP
X#define Msize		18
X#define SIZEOF_INT	4
X#else
X#define P_LDT_SEL	P_STACKTOP
X#define Msize		12	/* size of a message in 16-bit words */
X#define SIZEOF_INT	2
X#endif
X
XP_LDT		=	P_LDT_SEL + SIZEOF_INT
XP_SPLIMIT	=	P_LDT_SEL + 16	/* 16 is from 2 8-byte descriptors */
X
X/* Macros to handle bitwise complementation cleanly. */
X#if ASLD
X#define notop(n)	[-[n]-1]
X#else
X#define notop(n)	(!(n))
X#endif /* ASLD */
X
X/* Macros to handle some 286 instructions with asld. */
X#if ASLD
X#define ESC2		.data1	0x0F	/* escape for some 286 instructions */
X#define deflgdt(adr)	ESC2;	add	adr,dx	/* may not be general */
X#define deflidt(adr)	ESC2;	add	adr,bx	/* may not be general */
X#define deflldt(adr)	ESC2;	addb	adr,dl	/* may not be general */
X#define defltrax	ESC2;	.data1	0x00,0xD8
X#define defsgdt(adr)	ESC2;	add	adr,ax	/* may not be general */
X#define defsidt(adr)	ESC2;	add	adr,cx	/* may not be general */
X#define defsldt(adr)	ESC2;	addb	adr,al	/* may not be general */
X#define insw		.data1	0x6D
X#define outsw		.data1	0x6F
X#define popa		.data1	0x61
X#define pusha		.data1	0x60
X#define pushi8(n)	.data1	0x6A;	.data1	n
X#define pushi16(n)	.data1	0x68;	.data2	n
X#else
X#define deflgdt(adr)	lgdt	adr
X#define deflidt(adr)	lidt	adr
X#define deflldt(adr)	lldt	adr
X#define defltrax	ltr	ax
X#define defsgdt(adr)	sgdt	adr
X#define defsidt(adr)	sidt	adr
X#define defsldt(adr)	sldt	adr
X#define pushi8(n)	push	#n
X#define pushi16(n)	push	#n
X#endif /* ASLD */
/
echo x - sconst.h.kr
sed '/^X/s///' > sconst.h.kr << '/'
X/* Miscellaneous constants used in assembler code. */
X#define HCHIGH_MASK	0x0F	/* h/w click mask for low byte of hi word */
X#define HCLOW_MASK	0xF0	/* h/w click mask for low byte of low word */
X#define TEST1PATTERN	0x55	/* memory test pattern 1 */
X#define TEST2PATTERN	0xAA	/* memory test pattern 2 */
X
X/* Magic numbers for color status port. */
X#define COLOR_STATUS_PORT	0x3DA
X#	define VERTICAL_RETRACE_MASK	0x08
X
X/* 8259 mask bits. */
X#define AT_WINI_MASK	0x40	/* (1 << (AT_WINI_IRQ & 0x07)), etc */
X#define CLOCK_MASK	0x01
X#define ETHER_MASK	0x08
X#define FLOPPY_MASK	0x40
X#define KEYBOARD_MASK	0x02
X#define PRINTER_MASK	0x80
X#define RS232_MASK	0x10
X#define SECONDARY_MASK	0x08
X#define XT_WINI_MASK	0x20
X
X/* Device interrupt acknowledge ports and bits. */
X#define CLOCK_ACK_BIT	0x80
X#define CLOCK_ACK_PORT	PORT_B
X
X/* Offsets in struct proc. They MUST match proc.h. */
X#define P_STACKBASE	0
X#define ESREG		0
X#define DSREG		2
X#define DIREG		4
X#define SIREG		6
X#define BPREG		8
X#define STREG		10	/* hole for another SP */
X#define BXREG		12
X#define DXREG		14
X#define CXREG		16
X#define AXREG		18
X#define RETADR		20	/* return address for save() call */
X#define PCREG		22
X#define CSREG		24
X#define PSWREG		26
X#define SPREG		28
X#define SSREG		30
X#define P_STACKTOP	32
X
X#if INTEL_32BITS
X/* The registers are twice as wide. There are 2 extra segment regs, but
X * these are packed in the double-width es and ds slots.
X */
XEAXREG		=	2 * AXREG	/* use "=" to avoid parentheses */
XERETADR		=	2 * RETADR
XEPCREG		=	2 * PCREG
XECSREG		=	2 * CSREG
XEPSWREG		=	2 * PSWREG
XP3_STACKTOP	=	2 * P_STACKTOP
X#define P_LDT_SEL	P3_STACKTOP
X#define Msize		18
X#define SIZEOF_INT	4
X#else
X#define P_LDT_SEL	P_STACKTOP
X#define Msize		12	/* size of a message in 16-bit words */
X#define SIZEOF_INT	2
X#endif
X
XP_LDT		=	P_LDT_SEL + SIZEOF_INT
XP_SPLIMIT	=	P_LDT_SEL + 16	/* 16 is from 2 8-byte descriptors */
X
X/* Macros to handle bitwise complementation cleanly. */
X#if ASLD
X#define notop(n)	[-[n]-1]
X#else
X#define notop(n)	(!(n))
X#endif /* ASLD */
X
X/* Macros to handle some 286 instructions with asld. */
X#if ASLD
X#define ESC2		.byte	0x0F	/* escape for some 286 instructions */
X#define deflgdt(adr)	ESC2;	add	adr,dx	/* may not be general */
X#define deflidt(adr)	ESC2;	add	adr,bx	/* may not be general */
X#define deflldt(adr)	ESC2;	addb	adr,dl	/* may not be general */
X#define defltrax	ESC2;	.byte	0x00,0xD8
X#define defsgdt(adr)	ESC2;	add	adr,ax	/* may not be general */
X#define defsidt(adr)	ESC2;	add	adr,cx	/* may not be general */
X#define defsldt(adr)	ESC2;	addb	adr,al	/* may not be general */
X#define insw		.byte	0x6D
X#define outsw		.byte	0x6F
X#define popa		.byte	0x61
X#define pusha		.byte	0x60
X#define pushi8(n)	.byte	0x6A;	.byte	n
X#define pushi16(n)	.byte	0x68;	.word	n
X#else
X#define deflgdt(adr)	lgdt	adr
X#define deflidt(adr)	lidt	adr
X#define deflldt(adr)	lldt	adr
X#define defltrax	ltr	ax
X#define defsgdt(adr)	sgdt	adr
X#define defsidt(adr)	sidt	adr
X#define defsldt(adr)	sldt	adr
X#define pushi8(n)	push	#n
X#define pushi16(n)	push	#n
X#endif /* ASLD */
/
echo x - start.c
sed '/^X/s///' > start.c << '/'
X/* This file contains the C startup code for Minix on Intel processors.
X * It cooperates with mpx.x to set up a good environment for main().
X *
X * This code runs in real mode for a 16 bit kernel and may have to switch
X * to protected mode for a 286.
X *
X * For a 32 bit kernel this already runs in protected mode, but the selectors
X * are still those given by the BIOS with interrupts disabled, so the
X * descriptors need to be reloaded and interrupt descriptors made.
X */
X
X#include "kernel.h"
X#include "protect.h"
X#include "string.h"
X#include <minix/boot.h>
X
X/* Magic BIOS addresses. */
X#if !INTEL_32BITS
X
X/* 16 bit real mode. */
X#define BIOS_CSEG		0xF000	/* segment of BIOS code */
X#define BIOS_DSEG		0x0040	/* segment of BIOS data */
X#	define BIOS_CURSOR	0x0060	/* offset to cursor type word */
X#define VEC_TABLE_SEG		0x0000	/* segment of vector table */
X#define MACHINE_TYPE_SEG	0xFFFF	/* segment of machine type word */
X#	define MACHINE_TYPE_OFF	0x000E	/* offset of machine type word */
X#else
X
X/* 32 bit protected mode, the es selector addresses 4Gb with a zero base. */
X#define BIOS_CSEG		 0xF000	/* segment of BIOS code (real mode) */
X#define BIOS_DSEG	    ES_SELECTOR	/* segment of BIOS data */
X#	define BIOS_CURSOR      0x00460	/* offset to cursor type word */
X#define VEC_TABLE_SEG	    ES_SELECTOR	/* selector of vector table */
X#define MACHINE_TYPE_SEG    ES_SELECTOR	/* selector of machine type word */
X#	define MACHINE_TYPE_OFF	0xFFFFE	/* offset of machine type word */
X#endif
X
X#	define PC_AT	0xFC	/* code in first byte for PC-AT */
X#	define PS	0xFA	/* code in first byte for PS/2 Model 30 */
X#	define PS_386	0xF8	/* code in first byte for PS/2 386 70 & 80 */
X#	define PS_50	0x04	/* code in second byte for PS/2 Model 50 */
X#	define PS_50A	0xBA	/* code in second byte on some Model 50s */
X#	define PS_50Z	0xE9	/* code in second byte for Model 50Z */
X#	define PS_60	0x05	/* code in second byte for PS/2 Model 60 */
X
XPRIVATE char k_environ[256];	/* environment strings passed by loader */
X
XFORWARD _PROTOTYPE( void db_init, (void) );
XFORWARD _PROTOTYPE( int k_atoi, (char *s) );
XFORWARD _PROTOTYPE( char *k_getenv, (char *name) );
XFORWARD _PROTOTYPE( void rel_vec, (unsigned vec4) );
X
X/*==========================================================================*
X *				cstart					    *
X *==========================================================================*/
XPUBLIC void cstart(cs, ds, parmoff, parmseg, parmsize)
Xu16_t cs, ds;			/* Kernel code and data segment. */
Xchar *parmoff;			/* boot parameters offset */
Xu16_t parmseg;			/* boot parameters segment */
Xsize_t parmsize;		/* boot parameters length */
X{
X/* Perform initializations which must be done in real mode. */
X
X  register u16_t *bootp;
X  register char *envp;
X  unsigned machine_magic;
X  unsigned mach_submagic;
X
X  /* Record where the kernel is. */
X#if INTEL_32BITS
X  register struct segdesc_s *gdtp;
X
X  /* Get the code and data base from the gdt set up by the bootstrap. */
X  gdtp = &gdt[cs / sizeof(gdt[0])];
X  code_base = gdtp->base_low | ((u32_t) gdtp->base_middle << 16)
X				| ((u32_t) gdtp->base_high << 24);
X  gdtp = &gdt[ds / sizeof(gdt[0])];
X  data_base = gdtp->base_low | ((u32_t) gdtp->base_middle << 16)
X				| ((u32_t) gdtp->base_high << 24);
X#else
X  /* Get the code and data base from the real mode segment registers. */
X  code_base = hclick_to_physb(cs);
X  data_base = hclick_to_physb(ds);
X#endif
X
X  /* Copy the boot parameters to kernel memory. */
X  if (parmsize > sizeof k_environ - 2) parmsize = sizeof k_environ - 2;
X  parmsize /= 2;	/* word count */
X  for (bootp = (u16_t *) &k_environ[0]; parmsize != 0; parmsize--, parmoff += 2)
X	*bootp++ = get_word(parmseg, (u16_t *) parmoff);
X
X  /* Just convert environment to boot parameters for now. */
X  envp = k_getenv("rootdev");
X  if (envp != NIL_PTR) boot_parameters.bp_rootdev = k_atoi(envp);
X  envp = k_getenv("ramimagedev");
X  if (envp != NIL_PTR) boot_parameters.bp_ramimagedev = k_atoi(envp);
X  envp = k_getenv("ramsize");
X  if (envp != NIL_PTR) boot_parameters.bp_ramsize = k_atoi(envp);
X  envp = k_getenv("scancode");
X  if (envp != NIL_PTR) boot_parameters.bp_scancode = k_atoi(envp);
X  envp = k_getenv("processor");
X  if (envp != NIL_PTR) boot_parameters.bp_processor = k_atoi(envp);
X
X  scan_code = boot_parameters.bp_scancode;
X
X  /* Type of VDU: */
X  envp = k_getenv("chrome");
X  color = envp != NIL_PTR && strcmp(envp, "color") == 0;
X  envp = k_getenv("video");
X  if (envp != NIL_PTR) {
X	if (strcmp(envp, "ega") == 0) ega = TRUE;
X	if (strcmp(envp, "vga") == 0) vga = ega = TRUE;
X  }
X
X  /* Memory sizes: */
X  envp = k_getenv("memsize");
X  low_memsize = envp != NIL_PTR ? k_atoi(envp) : 256;
X  envp = k_getenv("emssize");
X  ext_memsize = envp != NIL_PTR ? k_atoi(envp) : 0;
X
X  /* Determine machine type. */
X  processor = boot_parameters.bp_processor;	/* 86, 186, 286, 386, ... */
X  machine_magic = get_word(MACHINE_TYPE_SEG, (u16_t *) MACHINE_TYPE_OFF);
X  mach_submagic = (machine_magic >> 8) & BYTE;
X  machine_magic &= BYTE;
X  if (machine_magic == PC_AT) {
X	pc_at = TRUE;
X	/* could be a PS/2 Model 50 or 60 -- check submodel byte */
X	if (mach_submagic == PS_50 || mach_submagic == PS_60)   ps_mca = TRUE;
X	if (mach_submagic == PS_50A || mach_submagic == PS_50Z) ps_mca = TRUE;
X  } else if (machine_magic == PS_386)
X	pc_at = ps_mca = TRUE;
X  else if (machine_magic == PS)
X	ps = TRUE;
X
X  /* Decide if mode is protected. */
X#if INTEL_32BITS
X  protected_mode = TRUE;
X#else
X  protected_mode = processor >= 286 && !using_bios;
X#endif
X  boot_parameters.bp_processor = protected_mode;	/* FS needs to know */
X
X  /* Prepare for relocation of the vector table.  It may contain pointers into
X   * itself.  Fix up only the ones used.
X   */
X  rel_vec(WINI_0_PARM_VEC * 4);
X  rel_vec(WINI_1_PARM_VEC * 4);
X
X  /* Initialize debugger (requires 'protected_mode' to be initialized). */
X  db_init();
X
X  /* Call stage 1 assembler hooks to begin machine/mode specific inits. */
X  mpx_1hook();
X  klib_1hook();
X
X  /* Call main() and never return if not protected mode. */
X  if (!protected_mode) main();
X
X  /* Initialize protected mode (requires 'break_vector' and other globals). */
X  prot_init();
X
X  /* Return to assembler code to switch modes or just reload selectors. */
X}
X
X
X/*==========================================================================*
X *				db_init					    *
X *==========================================================================*/
XPRIVATE void db_init()
X{
X/* Initialize vectors for external debugger. */
X
X  break_vector.offset = get_word(VEC_TABLE_SEG,
X  					(u16_t *) (BREAKPOINT_VECTOR * 4));
X  break_vector.selector = get_word(VEC_TABLE_SEG,
X  					(u16_t *) (BREAKPOINT_VECTOR * 4) + 1);
X  sstep_vector.offset = get_word(VEC_TABLE_SEG,
X  					(u16_t *) (DEBUG_VECTOR * 4));
X  sstep_vector.selector = get_word(VEC_TABLE_SEG,
X  					(u16_t *) (DEBUG_VECTOR * 4) + 1);
X
X  /* No debugger if the breakpoint vector points into the BIOS. */
X  if (break_vector.selector >= BIOS_CSEG) return;
X
X  /* Debugger vectors for protected mode are by convention stored as 16-bit
X   * offsets in the debugger code segment, just before the corresponding real
X   * mode entry points.
X   */
X  if (protected_mode) {
X#if !INTEL_32BITS
X	break_vector.offset = get_word(break_vector.selector,
X					(u16_t *) break_vector.offset - 1);
X	sstep_vector.offset = get_word(sstep_vector.selector,
X					(u16_t *) sstep_vector.offset - 1);
X#else
X	/* Can only poke around in 386 memory using the es selector. */
X	break_vector.offset = get_word(ES_SELECTOR, (u16_t *)
X	    (hclick_to_physb(break_vector.selector) + break_vector.offset) - 1);
X	sstep_vector.offset = get_word(ES_SELECTOR, (u16_t *)
X	    (hclick_to_physb(sstep_vector.selector) + sstep_vector.offset) - 1);
X#endif
X
X	/* Different code segments are not supported. */
X	if (break_vector.selector != sstep_vector.selector)
X		return;
X  }
X
X  /* Enable debugger. */
X  db_exists = TRUE;
X  db_enabled = TRUE;
X
X  /* Tell debugger about Minix's normal cursor shape via the BIOS.  It would
X   * be nice to tell it the variable video parameters, but too hard.  At least
X   * the others get refreshed by the console driver.  Blame the 6845's
X   * read-only registers.
X   */
X  put_word(BIOS_DSEG, (u16_t *) BIOS_CURSOR, CURSOR_SHAPE);
X}
X
X
X/*==========================================================================*
X *				k_atoi					    *
X *==========================================================================*/
XPRIVATE int k_atoi(s)
Xregister char *s;
X{
X/* Convert string to integer - kernel version to avoid bloat from isspace().
X */
X
X  register int total = 0;
X  register unsigned digit;
X  register minus = 0;
X
X  while (*s == ' ' || *s == '\t') s++;
X  if (*s == '-') {
X	s++;
X	minus = 1;
X  }
X  while ((digit = *s++ - '0') < 10) {
X	total *= 10;
X	total += digit;
X  }
X  return(minus ? -total : total);
X}
X
X
X/*==========================================================================*
X *				k_getenv				    *
X *==========================================================================*/
XPRIVATE char *k_getenv(name)
Xchar *name;
X{
X/* Get environment value - kernel version of getenv to avoid setting up the
X * usual environment array.
X */
X
X  register char *namep;
X  register char *envp;
X
X  for (envp = k_environ; *envp != 0;) {
X	for (namep = name; *namep != 0 && *namep == *envp; namep++, envp++)
X		;
X	if (*namep == '\0' && *envp == '=') return(envp + 1);
X	while (*envp++ != 0)
X		;
X  }
X  return(NIL_PTR);
X}
X
X
X/*==========================================================================*
X *				rel_vec					    *
X *==========================================================================*/
XPRIVATE void rel_vec(vec4)
Xunsigned vec4;			/* vector to be relocated (times 4) */
X{
X/* If the vector 'vec4' points into the vector table, relocate it to the copy
X * of the vector table.
X */
X
X  phys_bytes address;
X  u16_t off;
X  u16_t seg;
X
X  off = get_word(VEC_TABLE_SEG, (u16_t *) vec4);
X  seg = get_word(VEC_TABLE_SEG, (u16_t *) vec4 + 1);
X  address = hclick_to_physb(seg) + off;
X  if (address != 0 && address < VECTOR_BYTES) {
X	address += data_base + (vir_bytes) vec_table;
X	seg = physb_to_hclick(address);
X	off = address - hclick_to_physb(seg);
X	put_word(VEC_TABLE_SEG, (u16_t *) vec4, off);
X	put_word(VEC_TABLE_SEG, (u16_t *) vec4 + 1, seg);
X  }
X}
/
echo x - kernel.cd
sed '/^X/s///' > kernel.cd << '/'
Xecho x - at_wini.c.d
Xsed '/^X/s///' > at_wini.c.d << '/'
XX*** /home/top/ast/minix/1.5/kernel/at_wini.c  crc=60195  17795	Sat Apr 21 22:26:22 1990
XX--- /home/top/ast/minix/1.6.25/kernel/at_wini.c  crc=37708  18428	Sun Nov 15 23:17:22 1992
XX***************
XX*** 5,14 ****
XX   *
XX   *    m_type      DEVICE    PROC_NR     COUNT    POSITION  ADRRESS
XX   * ----------------------------------------------------------------
XX!  * |  DISK_READ | device  | proc nr |  bytes  |  offset | buf ptr |
XX   * |------------+---------+---------+---------+---------+---------|
XX!  * | DISK_WRITE | device  | proc nr |  bytes  |  offset | buf ptr |
XX!  * ----------------------------------------------------------------
XX   * |SCATTERED_IO| device  | proc nr | requests|         | iov ptr |
XX   * ----------------------------------------------------------------
XX   *
XX--- 5,18 ----
XX   *
XX   *    m_type      DEVICE    PROC_NR     COUNT    POSITION  ADRRESS
XX   * ----------------------------------------------------------------
XX!  * |  DEV_OPEN  |         |         |         |         |         |
XX   * |------------+---------+---------+---------+---------+---------|
XX!  * |  DEV_CLOSE |         |         |         |         |         |
XX!  * |------------+---------+---------+---------+---------+---------|
XX!  * |  DEV_READ  | device  | proc nr |  bytes  |  offset | buf ptr |
XX!  * |------------+---------+---------+---------+---------+---------|
XX!  * |  DEV_WRITE | device  | proc nr |  bytes  |  offset | buf ptr |
XX!  * |------------+---------+---------+---------+---------+---------|
XX   * |SCATTERED_IO| device  | proc nr | requests|         | iov ptr |
XX   * ----------------------------------------------------------------
XX   *
XX***************
XX*** 40,46 ****
XX  #define WIN_RECALIBRATE	0x10	/* command for the drive to recalibrate */
XX  #define WIN_READ        0x20	/* command for the drive to read */
XX  #define WIN_WRITE       0x30	/* command for the drive to write */
XX! #define WIN_SPECIFY     0x91	/* command for the controller to accept params */
XX  
XX  /* Parameters for the disk drive. */
XX  #define SECTOR_SIZE      512	/* physical sector size in bytes */
XX--- 44,50 ----
XX  #define WIN_RECALIBRATE	0x10	/* command for the drive to recalibrate */
XX  #define WIN_READ        0x20	/* command for the drive to read */
XX  #define WIN_WRITE       0x30	/* command for the drive to write */
XX! #define WIN_SPECIFY     0x91	/* command for the controller: accept params */
XX  
XX  /* Parameters for the disk drive. */
XX  #define SECTOR_SIZE      512	/* physical sector size in bytes */
XX***************
XX*** 57,63 ****
XX  
XX  /* Variables. */
XX  PRIVATE struct wini {		/* main drive struct, one entry per drive */
XX!   int wn_opcode;		/* DISK_READ or DISK_WRITE */
XX    int wn_procnr;		/* which proc wanted this operation? */
XX    int wn_drive;			/* drive number addressed */
XX    int wn_cylinder;		/* cylinder number addressed */
XX--- 61,67 ----
XX  
XX  /* Variables. */
XX  PRIVATE struct wini {		/* main drive struct, one entry per drive */
XX!   int wn_opcode;		/* DEV_READ or DEV_WRITE */
XX    int wn_procnr;		/* which proc wanted this operation? */
XX    int wn_drive;			/* drive number addressed */
XX    int wn_cylinder;		/* cylinder number addressed */
XX***************
XX*** 84,101 ****
XX  
XX  PRIVATE unsigned char buf[BLOCK_SIZE]; /* Buffer used by the startup routine */
XX  
XX! FORWARD int com_out();
XX! FORWARD int controller_ready();
XX! FORWARD void copy_params();
XX! FORWARD void copy_prt();
XX! FORWARD int drive_busy();
XX! FORWARD void init_params();
XX! FORWARD void sort();
XX! FORWARD int w_do_rdwt();
XX! FORWARD int w_reset();
XX! FORWARD int w_transfer();
XX! FORWARD int win_init();
XX! FORWARD int win_results();
XX  
XX  /*===========================================================================*
XX   *				winchester_task				     * 
XX--- 88,105 ----
XX  
XX  PRIVATE unsigned char buf[BLOCK_SIZE]; /* Buffer used by the startup routine */
XX  
XX! FORWARD _PROTOTYPE( int com_out, (void) );
XX! FORWARD _PROTOTYPE( int controller_ready, (void) );
XX! FORWARD _PROTOTYPE( void copy_params, (unsigned char *src, struct wini *dest));
XX! FORWARD _PROTOTYPE( void copy_prt, (int base_dev) );
XX! FORWARD _PROTOTYPE( int drive_busy, (void) );
XX! FORWARD _PROTOTYPE( void init_params, (void) );
XX! FORWARD _PROTOTYPE( void sort, (struct wini wn[]) );
XX! FORWARD _PROTOTYPE( int w_do_rdwt, (message *m_ptr) );
XX! FORWARD _PROTOTYPE( int w_reset, (void) );
XX! FORWARD _PROTOTYPE( int w_transfer, (struct wini *wn) );
XX! FORWARD _PROTOTYPE( int win_init, (void) );
XX! FORWARD _PROTOTYPE( int win_results, (void) );
XX  
XX  /*===========================================================================*
XX   *				winchester_task				     * 
XX***************
XX*** 117,123 ****
XX  	/* First wait for a request to read or write a disk block. */
XX  	receive(ANY, &w_mess);	/* get a request to do some work */
XX  	if (w_mess.m_source < 0) {
XX! 		printf("winchester task got message from %d ", w_mess.m_source);
XX  		continue;
XX  	}
XX  	caller = w_mess.m_source;
XX--- 121,127 ----
XX  	/* First wait for a request to read or write a disk block. */
XX  	receive(ANY, &w_mess);	/* get a request to do some work */
XX  	if (w_mess.m_source < 0) {
XX! 		printf("winchester task got message from %d ",w_mess.m_source);
XX  		continue;
XX  	}
XX  	caller = w_mess.m_source;
XX***************
XX*** 125,134 ****
XX  
XX  	/* Now carry out the work. */
XX  	switch(w_mess.m_type) {
XX! 	    case DISK_READ:
XX! 	    case DISK_WRITE:	r = w_do_rdwt(&w_mess);	break;
XX  	    case SCATTERED_IO:	r = do_vrdwt(&w_mess, w_do_rdwt); break;
XX! 	    default:		r = EINVAL;		break;
XX  	}
XX  
XX  	/* Finally, prepare and send the reply message. */
XX--- 129,142 ----
XX  
XX  	/* Now carry out the work. */
XX  	switch(w_mess.m_type) {
XX! 	    case DEV_OPEN:	r = OK;				  break;
XX! 	    case DEV_CLOSE:	r = OK;				  break;
XX! 
XX! 	    case DEV_READ:
XX! 	    case DEV_WRITE:	r = w_do_rdwt(&w_mess);		  break;
XX! 
XX  	    case SCATTERED_IO:	r = do_vrdwt(&w_mess, w_do_rdwt); break;
XX! 	    default:		r = EINVAL;			  break;
XX  	}
XX  
XX  	/* Finally, prepare and send the reply message. */
XX***************
XX*** 142,148 ****
XX  
XX  
XX  /*===========================================================================*
XX!  *				w_do_rdwt					     * 
XX   *===========================================================================*/
XX  PRIVATE int w_do_rdwt(m_ptr)
XX  message *m_ptr;			/* pointer to read or write w_message */
XX--- 150,156 ----
XX  
XX  
XX  /*===========================================================================*
XX!  *				w_do_rdwt				     * 
XX   *===========================================================================*/
XX  PRIVATE int w_do_rdwt(m_ptr)
XX  message *m_ptr;			/* pointer to read or write w_message */
XX***************
XX*** 150,156 ****
XX  /* Carry out a read or write request from the disk. */
XX    register struct wini *wn;
XX    int r, device, errors = 0;
XX!   long sector;
XX  
XX    /* Decode the w_message parameters. */
XX    device = m_ptr->DEVICE;
XX--- 158,164 ----
XX  /* Carry out a read or write request from the disk. */
XX    register struct wini *wn;
XX    int r, device, errors = 0;
XX!   long sector, s;
XX  
XX    /* Decode the w_message parameters. */
XX    device = m_ptr->DEVICE;
XX***************
XX*** 162,174 ****
XX    wn->wn_drive = device/DEV_PER_DRIVE;	/* save drive number */
XX    if (wn->wn_drive >= nr_drives)
XX  	return(EIO);
XX!   wn->wn_opcode = m_ptr->m_type;	/* DISK_READ or DISK_WRITE */
XX    if (m_ptr->POSITION % BLOCK_SIZE != 0)
XX  	return(EINVAL);
XX!   sector = m_ptr->POSITION/SECTOR_SIZE;
XX!   if ((sector+BLOCK_SIZE/SECTOR_SIZE) > wn->wn_size)
XX  	return(0);
XX!   sector += wn->wn_low;
XX    wn->wn_cylinder = sector / (wn->wn_heads * wn->wn_maxsec);
XX    wn->wn_sector =  (sector % wn->wn_maxsec) + 1;
XX    wn->wn_head = (sector % (wn->wn_heads * wn->wn_maxsec) )/wn->wn_maxsec;
XX--- 170,182 ----
XX    wn->wn_drive = device/DEV_PER_DRIVE;	/* save drive number */
XX    if (wn->wn_drive >= nr_drives)
XX  	return(EIO);
XX!   wn->wn_opcode = m_ptr->m_type;	/* DEV_READ or DEV_WRITE */
XX    if (m_ptr->POSITION % BLOCK_SIZE != 0)
XX  	return(EINVAL);
XX!   s = m_ptr->POSITION;
XX!   if (s < 0 || s > wn->wn_size * SECTOR_SIZE - BLOCK_SIZE)
XX  	return(0);
XX!   sector = s/SECTOR_SIZE + wn->wn_low;
XX    wn->wn_cylinder = sector / (wn->wn_heads * wn->wn_maxsec);
XX    wn->wn_sector =  (sector % wn->wn_maxsec) + 1;
XX    wn->wn_head = (sector % (wn->wn_heads * wn->wn_maxsec) )/wn->wn_maxsec;
XX***************
XX*** 216,228 ****
XX    command[4] = wn->wn_cylinder & 0xFF;
XX    command[5] = (wn->wn_cylinder >> 8) & BYTE;
XX    command[6] = (wn->wn_drive << 4) | wn->wn_head | 0xA0;
XX!   command[7] = (wn->wn_opcode == DISK_READ ? WIN_READ : WIN_WRITE);
XX  
XX    if (com_out() != OK)
XX  	return(ERR);
XX  
XX    /* Block, waiting for disk interrupt. */
XX!   if (wn->wn_opcode == DISK_READ) {
XX  	for (i=0; i<BLOCK_SIZE/SECTOR_SIZE; i++) {
XX  		receive(HARDWARE, &w_mess);
XX  		if (win_results() != OK) {
XX--- 224,236 ----
XX    command[4] = wn->wn_cylinder & 0xFF;
XX    command[5] = (wn->wn_cylinder >> 8) & BYTE;
XX    command[6] = (wn->wn_drive << 4) | wn->wn_head | 0xA0;
XX!   command[7] = (wn->wn_opcode == DEV_READ ? WIN_READ : WIN_WRITE);
XX  
XX    if (com_out() != OK)
XX  	return(ERR);
XX  
XX    /* Block, waiting for disk interrupt. */
XX!   if (wn->wn_opcode == DEV_READ) {
XX  	for (i=0; i<BLOCK_SIZE/SECTOR_SIZE; i++) {
XX  		receive(HARDWARE, &w_mess);
XX  		if (win_results() != OK) {
XX***************
XX*** 357,365 ****
XX    return(OK);
XX  }
XX  
XX! /*============================================================================*
XX!  *				win_results				      *
XX!  *============================================================================*/
XX  PRIVATE int win_results()
XX  {
XX  /* Extract results from the controller after an operation, then allow wini
XX--- 365,373 ----
XX    return(OK);
XX  }
XX  
XX! /*===========================================================================*
XX!  *				win_results				     *
XX!  *===========================================================================*/
XX  PRIVATE int win_results()
XX  {
XX  /* Extract results from the controller after an operation, then allow wini
XX***************
XX*** 394,407 ****
XX  
XX    retries = MAX_CONTROLLER_READY_RETRIES + 1;
XX    while (--retries != 0 &&
XX! 	 (in_byte(WIN_STATUS) & (WIN_BUSY | WIN_OUTREADY)) != WIN_OUTREADY)
XX  	;			/* wait until not busy */
XX    return(retries);		/* nonzero if ready */
XX  }
XX  
XX! /*============================================================================*
XX!  *				drive_busy				      *
XX!  *============================================================================*/
XX  PRIVATE int drive_busy()
XX  {
XX  /* Wait until the controller is ready to receive a command or send status */
XX--- 402,415 ----
XX  
XX    retries = MAX_CONTROLLER_READY_RETRIES + 1;
XX    while (--retries != 0 &&
XX! 	 (in_byte(WIN_STATUS) & WIN_BUSY) == WIN_BUSY)
XX  	;			/* wait until not busy */
XX    return(retries);		/* nonzero if ready */
XX  }
XX  
XX! /*===========================================================================*
XX!  *				drive_busy				     *
XX!  *===========================================================================*/
XX  PRIVATE int drive_busy()
XX  {
XX  /* Wait until the controller is ready to receive a command or send status */
XX***************
XX*** 414,422 ****
XX    return(OK);
XX  }
XX  
XX! /*============================================================================*
XX!  *				com_out					      *
XX!  *============================================================================*/
XX  PRIVATE int com_out()
XX  {
XX  /* Output the command block to the winchester controller and return status */
XX--- 422,430 ----
XX    return(OK);
XX  }
XX  
XX! /*===========================================================================*
XX!  *				com_out					     *
XX!  *===========================================================================*/
XX  PRIVATE int com_out()
XX  {
XX  /* Output the command block to the winchester controller and return status */
XX***************
XX*** 435,448 ****
XX    return(OK);
XX  }
XX  
XX! /*============================================================================*
XX!  *				init_params				      *
XX!  *============================================================================*/
XX  PRIVATE void init_params()
XX  {
XX  /* This routine is called at startup to initialize the partition table,
XX   * the number of drives and the controller
XX! */
XX    unsigned int i, segment, offset;
XX    phys_bytes address;
XX  
XX--- 443,456 ----
XX    return(OK);
XX  }
XX  
XX! /*===========================================================================*
XX!  *				init_params				     *
XX!  *===========================================================================*/
XX  PRIVATE void init_params()
XX  {
XX  /* This routine is called at startup to initialize the partition table,
XX   * the number of drives and the controller
XX!  */
XX    unsigned int i, segment, offset;
XX    phys_bytes address;
XX  
XX***************
XX*** 487,493 ****
XX  	w_mess.COUNT = BLOCK_SIZE;
XX  	w_mess.ADDRESS = (char *) buf;
XX  	w_mess.PROC_NR = WINCHESTER;
XX! 	w_mess.m_type = DISK_READ;
XX  	if (w_do_rdwt(&w_mess) != BLOCK_SIZE) {
XX  		printf("Can't read partition table on winchester %d\n",i);
XX  		milli_delay(20000);
XX--- 495,501 ----
XX  	w_mess.COUNT = BLOCK_SIZE;
XX  	w_mess.ADDRESS = (char *) buf;
XX  	w_mess.PROC_NR = WINCHESTER;
XX! 	w_mess.m_type = DEV_READ;
XX  	if (w_do_rdwt(&w_mess) != BLOCK_SIZE) {
XX  		printf("Can't read partition table on winchester %d\n",i);
XX  		milli_delay(20000);
XX***************
XX*** 502,510 ****
XX    }
XX  }
XX  
XX! /*============================================================================*
XX!  *				copy_params				      *
XX!  *============================================================================*/
XX  PRIVATE void copy_params(src, dest)
XX  register unsigned char *src;
XX  register struct wini *dest;
XX--- 510,518 ----
XX    }
XX  }
XX  
XX! /*===========================================================================*
XX!  *				copy_params				     *
XX!  *===========================================================================*/
XX  PRIVATE void copy_params(src, dest)
XX  register unsigned char *src;
XX  register struct wini *dest;
X/
Xecho x - bios_wini.c.d
Xsed '/^X/s///' > bios_wini.c.d << '/'
XX*** /home/top/ast/minix/1.5/kernel/bios_wini.c  crc=56527  12039	Sat Apr 21 22:26:22 1990
XX--- /home/top/ast/minix/1.6.25/kernel/bios_wini.c  crc=46433  12785	Fri Nov  6 00:14:46 1992
XX***************
XX*** 10,19 ****
XX   *
XX   *	m_type	  DEVICE   PROC_NR	COUNT	 POSITION  ADRRESS
XX   * ----------------------------------------------------------------
XX!  * |  DISK_READ | device  | proc nr |  bytes  |	 offset | buf ptr |
XX   * |------------+---------+---------+---------+---------+---------|
XX!  * | DISK_WRITE | device  | proc nr |  bytes  |	 offset | buf ptr |
XX!  * ----------------------------------------------------------------
XX   * |SCATTERED_IO| device  | proc nr | requests|         | iov ptr |
XX   * ----------------------------------------------------------------
XX   *
XX--- 10,23 ----
XX   *
XX   *	m_type	  DEVICE   PROC_NR	COUNT	 POSITION  ADRRESS
XX   * ----------------------------------------------------------------
XX!  * |  DEV_OPEN  |         |         |         |         |         |
XX   * |------------+---------+---------+---------+---------+---------|
XX!  * |  DEV_CLOSE |         |         |         |         |         |
XX!  * |------------+---------+---------+---------+---------+---------|
XX!  * |  DEV_READ  | device  | proc nr |  bytes  |	 offset | buf ptr |
XX!  * |------------+---------+---------+---------+---------+---------|
XX!  * |  DEV_WRITE | device  | proc nr |  bytes  |	 offset | buf ptr |
XX!  * |------------+---------+---------+---------+---------+---------|
XX   * |SCATTERED_IO| device  | proc nr | requests|         | iov ptr |
XX   * ----------------------------------------------------------------
XX   *
XX***************
XX*** 51,57 ****
XX  PRIVATE message w_mess;		/* message buffer for in and out */
XX  
XX  PRIVATE struct wini {		/* main drive struct, one entry per drive */
XX!   int wn_opcode;		/* DISK_READ or DISK_WRITE */
XX    int wn_procnr;		/* which proc wanted this operation? */
XX    int wn_cylinder;		/* cylinder number addressed */
XX    int wn_sector;		/* sector addressed */
XX--- 55,61 ----
XX  PRIVATE message w_mess;		/* message buffer for in and out */
XX  
XX  PRIVATE struct wini {		/* main drive struct, one entry per drive */
XX!   int wn_opcode;		/* DEV_READ or DEV_WRITE */
XX    int wn_procnr;		/* which proc wanted this operation? */
XX    int wn_cylinder;		/* cylinder number addressed */
XX    int wn_sector;		/* sector addressed */
XX***************
XX*** 72,85 ****
XX  	int nr_sectors;		/* Number of sectors per track */
XX  } param0, param1;
XX  
XX! PRIVATE int nr_drives;
XX  
XX! FORWARD void copy_prt();
XX! FORWARD void get_params();
XX! FORWARD void init_params();
XX! FORWARD void replace();
XX! FORWARD void sort();
XX! FORWARD int w_do_rdwt();
XX  
XX  /*=========================================================================*
XX   *			winchester_task					   * 
XX--- 76,90 ----
XX  	int nr_sectors;		/* Number of sectors per track */
XX  } param0, param1;
XX  
XX! PRIVATE int nr_drives;		/* number of hard disk drives */
XX! PRIVATE int no_disk;		/* TRUE if hard disk problems found */
XX  
XX! FORWARD _PROTOTYPE( void copy_prt, (int base_dev) );
XX! FORWARD _PROTOTYPE( void get_params, (int dr, struct param* params) );
XX! FORWARD _PROTOTYPE( void init_params, (void) );
XX! FORWARD _PROTOTYPE( void replace, (int from, int to) );
XX! FORWARD _PROTOTYPE( void sort, (struct wini wn[]) );
XX! FORWARD _PROTOTYPE( int w_do_rdwt, (message *m_ptr) );
XX  
XX  /*=========================================================================*
XX   *			winchester_task					   * 
XX***************
XX*** 93,108 ****
XX    /* First initialize the controller */
XX    init_params();
XX  
XX!   /* Here is the main loop of the disk task.  It waits for a message, carries
XX!    * it out, and sends a reply.
XX!    */
XX! 
XX    while (TRUE) {
XX  	/* First wait for a request to read or write a disk block. */
XX  	receive(ANY, &w_mess);	/* get a request to do some work */
XX  	if (w_mess.m_source < 0) {
XX! 		printf("winchester task got message from %d\n",w_mess.m_source);
XX! 		continue;
XX  	}
XX  
XX  	caller = w_mess.m_source;
XX--- 98,110 ----
XX    /* First initialize the controller */
XX    init_params();
XX  
XX!   /*  Main loop.  Waits for message, carry it out, and send reply. */
XX    while (TRUE) {
XX  	/* First wait for a request to read or write a disk block. */
XX  	receive(ANY, &w_mess);	/* get a request to do some work */
XX  	if (w_mess.m_source < 0) {
XX! 	       printf("winchester task got message from %d\n",w_mess.m_source);
XX! 	       continue;
XX  	}
XX  
XX  	caller = w_mess.m_source;
XX***************
XX*** 110,117 ****
XX  
XX  	/* Now carry out the work. */
XX  	switch(w_mess.m_type) {
XX! 	    case DISK_READ:
XX! 	    case DISK_WRITE:	r = w_do_rdwt(&w_mess);	break;
XX  	    case SCATTERED_IO:	r = do_vrdwt(&w_mess, w_do_rdwt); break;
XX  	    default:		r = EINVAL;		break;
XX  	}
XX--- 112,123 ----
XX  
XX  	/* Now carry out the work. */
XX  	switch(w_mess.m_type) {
XX! 	    case DEV_OPEN:	r = OK;				  break;
XX! 	    case DEV_CLOSE:	r = OK;				  break;
XX! 
XX! 	    case DEV_READ:
XX! 	    case DEV_WRITE:	r = w_do_rdwt(&w_mess);		  break;
XX! 
XX  	    case SCATTERED_IO:	r = do_vrdwt(&w_mess, w_do_rdwt); break;
XX  	    default:		r = EINVAL;		break;
XX  	}
XX***************
XX*** 120,125 ****
XX--- 126,132 ----
XX  	w_mess.m_type = TASK_REPLY;	
XX  	w_mess.REP_PROC_NR = proc_nr;
XX  
XX+ 	if (no_disk) r = EIO;	/* always fail if there is no disk */
XX  	w_mess.REP_STATUS = r;	/* # of bytes transferred or error code */
XX  	send(caller, &w_mess);	/* send reply to caller */
XX    }
XX***************
XX*** 137,159 ****
XX    vir_bytes vir, ct;
XX    unsigned locyl, hicyl, c1, c2, c3;
XX    int r, device;
XX!   long sector;
XX    phys_bytes user_phys;
XX  
XX    /* Decode the w_message parameters. */
XX    device = m_ptr->DEVICE;	/* minor device #.  1-4 are partitions */
XX    if (device < 0 || device >= NR_DEVICES) return(EIO);
XX    if (m_ptr->COUNT != BLOCK_SIZE) return(EINVAL);
XX    wn = &wini[device];		/* 'wn' points to entry for this drive */
XX  
XX    /* Set opcode to BIOS_READ or BIOS_WRITE. Check for bad starting addr. */
XX!   wn->wn_opcode = (m_ptr->m_type == DISK_WRITE ? BIOS_WRITE : BIOS_READ);
XX    if (m_ptr->POSITION % BLOCK_SIZE != 0) return(EINVAL);
XX  
XX    /* Calculate the physical parameters */
XX!   sector = m_ptr->POSITION/SECTOR_SIZE;	/* relative sector within partition */
XX!   if ((sector+BLOCK_SIZE/SECTOR_SIZE) > wn->wn_size) return(0);
XX!   sector += wn->wn_low;		/* absolute sector number */
XX    wn->wn_cylinder = sector / (wn->wn_heads * wn->wn_maxsec);
XX    wn->wn_sector =  (sector % wn->wn_maxsec);
XX    wn->wn_head = (sector % (wn->wn_heads * wn->wn_maxsec) )/wn->wn_maxsec;
XX--- 144,167 ----
XX    vir_bytes vir, ct;
XX    unsigned locyl, hicyl, c1, c2, c3;
XX    int r, device;
XX!   long sector, s;
XX    phys_bytes user_phys;
XX  
XX    /* Decode the w_message parameters. */
XX+   if (no_disk) return(EIO);	/* if there is no disk, do not even try */
XX    device = m_ptr->DEVICE;	/* minor device #.  1-4 are partitions */
XX    if (device < 0 || device >= NR_DEVICES) return(EIO);
XX    if (m_ptr->COUNT != BLOCK_SIZE) return(EINVAL);
XX    wn = &wini[device];		/* 'wn' points to entry for this drive */
XX  
XX    /* Set opcode to BIOS_READ or BIOS_WRITE. Check for bad starting addr. */
XX!   wn->wn_opcode = (m_ptr->m_type == DEV_WRITE ? BIOS_WRITE : BIOS_READ);
XX    if (m_ptr->POSITION % BLOCK_SIZE != 0) return(EINVAL);
XX  
XX    /* Calculate the physical parameters */
XX!   s = m_ptr->POSITION;
XX!   if (s < 0 || s > wn->wn_size * SECTOR_SIZE - BLOCK_SIZE) return(0);
XX!   sector = s/SECTOR_SIZE + wn->wn_low;	/* relative sector within partition */
XX    wn->wn_cylinder = sector / (wn->wn_heads * wn->wn_maxsec);
XX    wn->wn_sector =  (sector % wn->wn_maxsec);
XX    wn->wn_head = (sector % (wn->wn_heads * wn->wn_maxsec) )/wn->wn_maxsec;
XX***************
XX*** 204,210 ****
XX  {
XX  /* This routine is called at startup to initialize the partition table,
XX   * the number of drives and the controller
XX! */
XX    unsigned int i;
XX  
XX    /* Give control to the BIOS interrupt handler. */
XX--- 212,218 ----
XX  {
XX  /* This routine is called at startup to initialize the partition table,
XX   * the number of drives and the controller
XX!  */
XX    unsigned int i;
XX  
XX    /* Give control to the BIOS interrupt handler. */
XX***************
XX*** 225,232 ****
XX    if (nr_drives > MAX_DRIVES) nr_drives = MAX_DRIVES;
XX  
XX    /* Set the parameters in the drive structure */
XX!   for (i = 0; i < DEV_PER_DRIVE; i++)
XX!   {
XX  	wini[i].wn_heads = param0.nr_heads;
XX  	wini[i].wn_maxsec = param0.nr_sectors;
XX  	wini[i].wn_drive = DRIVE;
XX--- 233,239 ----
XX    if (nr_drives > MAX_DRIVES) nr_drives = MAX_DRIVES;
XX  
XX    /* Set the parameters in the drive structure */
XX!   for (i = 0; i < DEV_PER_DRIVE; i++) {
XX  	wini[i].wn_heads = param0.nr_heads;
XX  	wini[i].wn_maxsec = param0.nr_sectors;
XX  	wini[i].wn_drive = DRIVE;
XX***************
XX*** 234,241 ****
XX    wini[0].wn_low = wini[DEV_PER_DRIVE].wn_low = 0L;
XX    wini[0].wn_size = (long)((long)param0.nr_cyl
XX        * (long)param0.nr_heads * (long)param0.nr_sectors);
XX!   for (i = DEV_PER_DRIVE; i < (2*DEV_PER_DRIVE); i++)
XX!   {
XX  	wini[i].wn_heads = param1.nr_heads;
XX  	wini[i].wn_maxsec = param1.nr_sectors;
XX  	wini[i].wn_drive = DRIVE + 1;
XX--- 241,247 ----
XX    wini[0].wn_low = wini[DEV_PER_DRIVE].wn_low = 0L;
XX    wini[0].wn_size = (long)((long)param0.nr_cyl
XX        * (long)param0.nr_heads * (long)param0.nr_sectors);
XX!   for (i = DEV_PER_DRIVE; i < (2*DEV_PER_DRIVE); i++) {
XX  	wini[i].wn_heads = param1.nr_heads;
XX  	wini[i].wn_maxsec = param1.nr_sectors;
XX  	wini[i].wn_drive = DRIVE + 1;
XX***************
XX*** 251,259 ****
XX  	w_mess.COUNT = BLOCK_SIZE;
XX  	w_mess.ADDRESS = (char *) buf;
XX  	w_mess.PROC_NR = WINCHESTER;
XX! 	w_mess.m_type = DISK_READ;
XX! 	if (w_do_rdwt(&w_mess) != BLOCK_SIZE)
XX! 		panic("Can't read partition table of winchester ", i);
XX  	copy_prt(i * DEV_PER_DRIVE);
XX    }
XX  }
XX--- 257,268 ----
XX  	w_mess.COUNT = BLOCK_SIZE;
XX  	w_mess.ADDRESS = (char *) buf;
XX  	w_mess.PROC_NR = WINCHESTER;
XX! 	w_mess.m_type = DEV_READ;
XX! 	if (w_do_rdwt(&w_mess) != BLOCK_SIZE) {
XX! 		printf("Can't read hard disk partition table. Disable disk\n");
XX! 		no_disk = TRUE;
XX! 		return;
XX! 	}
XX  	copy_prt(i * DEV_PER_DRIVE);
XX    }
XX  }
X/
Xecho x - clock.c.d
Xsed '/^X/s///' > clock.c.d << '/'
XX*** /home/top/ast/minix/1.5/kernel/clock.c  crc=42229  14240	Sat Apr 21 22:26:22 1990
XX--- /home/top/ast/minix/1.6.25/kernel/clock.c  crc=54725  18570	Tue Nov  3 21:20:43 1992
XX***************
XX*** 1,22 ****
XX  /* This file contains the code and data for the clock task.  The clock task
XX!  * has a single entry point, clock_task().  It accepts four message types:
XX   *
XX   *   HARD_INT:    a clock interrupt has occurred
XX!  *   GET_TIME:    a process wants the real time
XX!  *   SET_TIME:    a process wants to set the real time
XX   *   SET_ALARM:   a process wants to be alerted after a specified interval
XX   *
XX   * The input message is format m6.  The parameters are as follows:
XX   *
XX   *     m_type    CLOCK_PROC   FUNC    NEW_TIME
XX   * ---------------------------------------------
XX-  * | SET_ALARM  | proc_nr  |f to call|  delta  |
XX-  * |------------+----------+---------+---------|
XX   * | HARD_INT   |          |         |         |
XX   * |------------+----------+---------+---------|
XX   * | GET_TIME   |          |         |         |
XX   * |------------+----------+---------+---------|
XX   * | SET_TIME   |          |         | newtime |
XX   * ---------------------------------------------
XX   *
XX   * When an alarm goes off, if the caller is a user process, a SIGALRM signal
XX--- 1,29 ----
XX  /* This file contains the code and data for the clock task.  The clock task
XX!  * accepts six message types:
XX   *
XX   *   HARD_INT:    a clock interrupt has occurred
XX!  *   GET_TIME:    a process wants the real time in seconds
XX!  *   SET_TIME:    a process wants to set the real time in seconds
XX   *   SET_ALARM:   a process wants to be alerted after a specified interval
XX+  *   GET_UPTIME:  get the time since boot in ticks
XX+  *   SET_SYN_AL:  set the sync alarm
XX+  *   
XX   *
XX   * The input message is format m6.  The parameters are as follows:
XX   *
XX   *     m_type    CLOCK_PROC   FUNC    NEW_TIME
XX   * ---------------------------------------------
XX   * | HARD_INT   |          |         |         |
XX   * |------------+----------+---------+---------|
XX   * | GET_TIME   |          |         |         |
XX   * |------------+----------+---------+---------|
XX   * | SET_TIME   |          |         | newtime |
XX+  * |------------+----------+---------+---------|
XX+  * | SET_ALARM  | proc_nr  |f to call|  delta  |
XX+  * |------------+----------+---------+---------|
XX+  * | GET_UPTIME |          |         |         |
XX+  * |------------+----------+---------+---------|
XX+  * | SET_SYN_AL |          |         |  delta  |
XX   * ---------------------------------------------
XX   *
XX   * When an alarm goes off, if the caller is a user process, a SIGALRM signal
XX***************
XX*** 42,71 ****
XX  #define SQUARE_WAVE     0x36	/* ccaammmb, a = access, m = mode, b = BCD */
XX  				/*   11x11, 11 = LSB then MSB, x11 = sq wave */
XX  #define TIMER_COUNT ((unsigned) (TIMER_FREQ/HZ)) /* initial value for counter*/
XX! #define TIMER_FREQ   1193182L	/* clock frequency for timer in PC and AT */
XX  #endif
XX  
XX  #if (CHIP == M68000)
XX! #define FLUSH_MASK      0x07	/* bit mask used for flushing RS232 input */
XX! #define TIMER_FREQ   2457600L	/* timer 3 input clock frequency */
XX  #endif
XX  
XX  /* Clock task variables. */
XX  PRIVATE time_t boot_time;	/* time in seconds of system boot */
XX! PRIVATE time_t next_alarm;	/* probable time of next alarm */
XX! PRIVATE time_t pending_ticks;	/* ticks seen by low level only */
XX! PRIVATE time_t realtime;	/* real time clock */
XX! PRIVATE int sched_ticks = SCHED_RATE;	/* counter: when 0, call scheduler */
XX  PRIVATE struct proc *prev_ptr;	/* last user process run by clock task */
XX  PRIVATE message mc;		/* message buffer for both input and output */
XX! PRIVATE void (*watch_dog[NR_TASKS+1])();  /* watch_dog functions to call */
XX  
XX! FORWARD void do_clocktick();
XX! FORWARD void do_get_time();
XX! FORWARD void do_set_time();
XX! FORWARD void do_setalarm();
XX! FORWARD void init_clock();
XX  
XX  /*===========================================================================*
XX   *				clock_task				     *
XX   *===========================================================================*/
XX--- 49,87 ----
XX  #define SQUARE_WAVE     0x36	/* ccaammmb, a = access, m = mode, b = BCD */
XX  				/*   11x11, 11 = LSB then MSB, x11 = sq wave */
XX  #define TIMER_COUNT ((unsigned) (TIMER_FREQ/HZ)) /* initial value for counter*/
XX! #define TIMER_FREQ  1193182L	/* clock frequency for timer in PC and AT */
XX  #endif
XX  
XX  #if (CHIP == M68000)
XX! #define TIMER_FREQ  2457600L	/* timer 3 input clock frequency */
XX  #endif
XX  
XX  /* Clock task variables. */
XX  PRIVATE time_t boot_time;	/* time in seconds of system boot */
XX! PRIVATE clock_t next_alarm;	/* probable time of next alarm */
XX! PRIVATE clock_t pending_ticks;	/* ticks seen by low level only */
XX! PRIVATE clock_t realtime;	/* real time clock */
XX  PRIVATE struct proc *prev_ptr;	/* last user process run by clock task */
XX  PRIVATE message mc;		/* message buffer for both input and output */
XX! PRIVATE int sched_ticks = SCHED_RATE;	/* counter: when 0, call scheduler */
XX  
XX! PRIVATE int syn_al_alive= TRUE; /* don't wake syn_alrm_task before inited*/
XX! PRIVATE int watchdog_proc;	/* contains proc_nr at call of *watch_dog[]*/
XX! PRIVATE int syn_table[NR_TASKS+NR_PROCS]; /* which tasks get CLOCK_INT*/
XX  
XX+ PRIVATE watchdog_t watch_dog[NR_TASKS+NR_PROCS];
XX+ 
XX+ FORWARD _PROTOTYPE( void common_setalarm, (int proc_nr,
XX+ 		long delta_ticks, watchdog_t fuction) );
XX+ FORWARD _PROTOTYPE( void do_clocktick, (void) );
XX+ FORWARD _PROTOTYPE( void do_get_time, (void) );
XX+ FORWARD _PROTOTYPE( void do_getuptime, (void) );
XX+ FORWARD _PROTOTYPE( void do_set_time, (message *m_ptr) );
XX+ FORWARD _PROTOTYPE( void do_setalarm, (message *m_ptr) );
XX+ FORWARD _PROTOTYPE( void init_clock, (void) );
XX+ FORWARD _PROTOTYPE( void cause_alarm, (void) );
XX+ FORWARD _PROTOTYPE( void do_setsyn_alrm, (message *m_ptr) );
XX+ 
XX  /*===========================================================================*
XX   *				clock_task				     *
XX   *===========================================================================*/
XX***************
XX*** 86,99 ****
XX  
XX       lock();
XX       realtime += pending_ticks;	/* transfer ticks from low level handler */
XX!      pending_ticks = 0;
XX       unlock();
XX  
XX       switch (opcode) {
XX! 	case SET_ALARM:	 do_setalarm(&mc);	break;
XX  	case GET_TIME:	 do_get_time();		break;
XX  	case SET_TIME:	 do_set_time(&mc);	break;
XX! 	case HARD_INT:   do_clocktick();	break;
XX  	default: panic("clock task got bad message", mc.m_type);
XX       }
XX  
XX--- 102,117 ----
XX  
XX       lock();
XX       realtime += pending_ticks;	/* transfer ticks from low level handler */
XX!      pending_ticks = 0;		/* so we don't have to worry about them */
XX       unlock();
XX  
XX       switch (opcode) {
XX! 	case HARD_INT:   do_clocktick();	break;
XX  	case GET_TIME:	 do_get_time();		break;
XX  	case SET_TIME:	 do_set_time(&mc);	break;
XX! 	case SET_ALARM:	 do_setalarm(&mc);	break;
XX! 	case GET_UPTIME: do_getuptime();	break;
XX! 	case SET_SYNC_AL:do_setsyn_alrm(&mc);	break;
XX  	default: panic("clock task got bad message", mc.m_type);
XX       }
XX  
XX***************
XX*** 105,214 ****
XX  
XX  
XX  /*===========================================================================*
XX   *				do_setalarm				     *
XX   *===========================================================================*/
XX  PRIVATE void do_setalarm(m_ptr)
XX  message *m_ptr;			/* pointer to request message */
XX  {
XX  /* A process wants an alarm signal or a task wants a given watch_dog function
XX!  * called after a specified interval.  Record the request and check to see
XX!  * it is the very next alarm needed.
XX   */
XX  
XX    register struct proc *rp;
XX    int proc_nr;			/* which process wants the alarm */
XX    long delta_ticks;		/* in how many clock ticks does he want it? */
XX!   void (*function)();		/* function to call (tasks only) */
XX  
XX    /* Extract the parameters from the message. */
XX    proc_nr = m_ptr->CLOCK_PROC_NR;	/* process to interrupt later */
XX    delta_ticks = m_ptr->DELTA_TICKS;	/* how many ticks to wait */
XX!   function = m_ptr->FUNC_TO_CALL;	/* function to call (tasks only) */
XX    rp = proc_addr(proc_nr);
XX!   mc.SECONDS_LEFT = (rp->p_alarm == 0L ? 0 : (rp->p_alarm - realtime)/HZ );
XX!   rp->p_alarm = (delta_ticks == 0L ? 0L : realtime + delta_ticks);
XX!   if (istaskp(rp)) watch_dog[-proc_nr] = function;
XX  
XX-   /* Which alarm is next? */
XX-   next_alarm = MAX_P_LONG;
XX-   for (rp = BEG_PROC_ADDR; rp < END_PROC_ADDR; rp++)
XX- 	if(rp->p_alarm != 0 && rp->p_alarm < next_alarm)next_alarm=rp->p_alarm;
XX  
XX  }
XX  
XX  
XX  /*===========================================================================*
XX!  *				do_get_time				     *
XX   *===========================================================================*/
XX! PRIVATE void do_get_time()
XX  {
XX! /* Get and return the current clock time in ticks. */
XX  
XX!   mc.m_type = REAL_TIME;	/* set message type for reply */
XX!   mc.NEW_TIME = boot_time + realtime/HZ;	/* current real time */
XX  }
XX  
XX  
XX  /*===========================================================================*
XX!  *				do_set_time				     *
XX   *===========================================================================*/
XX! PRIVATE void do_set_time(m_ptr)
XX! message *m_ptr;			/* pointer to request message */
XX  {
XX! /* Set the real time clock.  Only the superuser can use this call. */
XX  
XX!   boot_time = m_ptr->NEW_TIME - realtime/HZ;
XX  }
XX  
XX  
XX  /*===========================================================================*
XX!  *				do_clocktick				     *
XX   *===========================================================================*/
XX! PRIVATE void do_clocktick()
XX  {
XX! /* This routine called on clock ticks when a lot of work needs to be done. */
XX  
XX!   register struct proc *rp;
XX!   register int proc_nr;
XX  
XX!   if (next_alarm <= realtime) {
XX! 	/* An alarm may have gone off, but proc may have exited, so check. */
XX! 	next_alarm = MAX_P_LONG;	/* start computing next alarm */
XX! 	for (rp = BEG_PROC_ADDR; rp < END_PROC_ADDR; rp++) {
XX! 		if (rp->p_alarm != (time_t) 0) {
XX! 			/* See if this alarm time has been reached. */
XX! 			if (rp->p_alarm <= realtime) {
XX! 				/* A timer has gone off.  If it is a user proc,
XX! 				 * send it a signal.  If it is a task, call the
XX! 				 * function previously specified by the task.
XX! 				 */
XX! 				if ( (proc_nr = proc_number(rp)) >= 0)
XX! 					cause_sig(proc_nr, SIGALRM);
XX! 				else
XX! 					(*watch_dog[-proc_nr])();
XX! 				rp->p_alarm = 0;
XX! 			}
XX  
XX! 			/* Work on determining which alarm is next. */
XX! 			if (rp->p_alarm != 0 && rp->p_alarm < next_alarm)
XX! 				next_alarm = rp->p_alarm;
XX  		}
XX  	}
XX    }
XX- 
XX-   /* If a user process has been running too long, pick another one. */
XX-   if (--sched_ticks == 0) {
XX- 	if (bill_ptr == prev_ptr) lock_sched();	/* process has run too long */
XX- 	sched_ticks = SCHED_RATE;		/* reset quantum */
XX- 	prev_ptr = bill_ptr;			/* new previous process */
XX-   }
XX- #if (CHIP == M68000)
XX-   if (rdy_head[SHADOW_Q]) unshadow(rdy_head[SHADOW_Q]);
XX- #endif
XX  }
XX  
XX  
XX  #if (CHIP == INTEL)
XX  /*===========================================================================*
XX   *				init_clock				     *
XX   *===========================================================================*/
XX--- 123,356 ----
XX  
XX  
XX  /*===========================================================================*
XX+  *				do_clocktick				     *
XX+  *===========================================================================*/
XX+ PRIVATE void do_clocktick()
XX+ {
XX+ /* This routine called on clock ticks when a lot of work needs to be done. */
XX+ 
XX+   register struct proc *rp;
XX+   register int proc_nr;
XX+ 
XX+   if (next_alarm <= realtime) {
XX+ 	/* An alarm may have gone off, but proc may have exited, so check. */
XX+ 	next_alarm = LONG_MAX;	/* start computing next alarm */
XX+ 	for (rp = BEG_PROC_ADDR; rp < END_PROC_ADDR; rp++) {
XX+ 		if (rp->p_alarm != 0) {
XX+ 			/* See if this alarm time has been reached. */
XX+ 			if (rp->p_alarm <= realtime) {
XX+ 				/* A timer has gone off.  If it is a user proc,
XX+ 				 * send it a signal.  If it is a task, call the
XX+ 				 * function previously specified by the task.
XX+ 				 */
XX+ 				proc_nr = proc_number(rp);
XX+ 				if (watch_dog[proc_nr+NR_TASKS]) {
XX+ 					watchdog_proc= proc_nr;
XX+ 					(*watch_dog[proc_nr+NR_TASKS])();
XX+ 				}
XX+ 				else
XX+ 					cause_sig(proc_nr, SIGALRM);
XX+ 				rp->p_alarm = 0;
XX+ 			}
XX+ 
XX+ 			/* Work on determining which alarm is next. */
XX+ 			if (rp->p_alarm != 0 && rp->p_alarm < next_alarm)
XX+ 				next_alarm = rp->p_alarm;
XX+ 		}
XX+ 	}
XX+   }
XX+ 
XX+   /* If a user process has been running too long, pick another one. */
XX+   if (--sched_ticks == 0) {
XX+ 	if (bill_ptr == prev_ptr) lock_sched();	/* process has run too long */
XX+ 	sched_ticks = SCHED_RATE;		/* reset quantum */
XX+ 	prev_ptr = bill_ptr;			/* new previous process */
XX+   }
XX+ #if (SHADOWING == 1)
XX+   if (rdy_head[SHADOW_Q]) unshadow(rdy_head[SHADOW_Q]);
XX+ #endif
XX+ }
XX+ 
XX+ 
XX+ /*===========================================================================*
XX+  *				do_get_time				     *
XX+  *===========================================================================*/
XX+ PRIVATE void do_get_time()
XX+ {
XX+ /* Get and return the current clock time in seconds. */
XX+ 
XX+   mc.NEW_TIME = boot_time + realtime/HZ;	/* current real time */
XX+ }
XX+ 
XX+ 
XX+ /*===========================================================================*
XX+  *				do_set_time				     *
XX+  *===========================================================================*/
XX+ PRIVATE void do_set_time(m_ptr)
XX+ message *m_ptr;			/* pointer to request message */
XX+ {
XX+ /* Set the real time clock.  Only the superuser can use this call. */
XX+ 
XX+   boot_time = m_ptr->NEW_TIME - realtime/HZ;
XX+ }
XX+ 
XX+ 
XX+ /*===========================================================================*
XX   *				do_setalarm				     *
XX   *===========================================================================*/
XX  PRIVATE void do_setalarm(m_ptr)
XX  message *m_ptr;			/* pointer to request message */
XX  {
XX  /* A process wants an alarm signal or a task wants a given watch_dog function
XX!  * called after a specified interval.
XX   */
XX  
XX    register struct proc *rp;
XX    int proc_nr;			/* which process wants the alarm */
XX    long delta_ticks;		/* in how many clock ticks does he want it? */
XX!   watchdog_t function;		/* function to call (tasks only) */
XX  
XX    /* Extract the parameters from the message. */
XX    proc_nr = m_ptr->CLOCK_PROC_NR;	/* process to interrupt later */
XX    delta_ticks = m_ptr->DELTA_TICKS;	/* how many ticks to wait */
XX!   function = (watchdog_t) m_ptr->FUNC_TO_CALL;
XX!   					/* function to call (tasks only) */
XX    rp = proc_addr(proc_nr);
XX!   mc.SECONDS_LEFT = (rp->p_alarm == 0 ? 0 : (rp->p_alarm - realtime)/HZ );
XX!   if (!istaskp(rp)) function= 0;	/* user processes get signaled */
XX!   common_setalarm(proc_nr, delta_ticks, function);
XX! }
XX  
XX  
XX+ /*===========================================================================*
XX+  *				do_setsyn_alrm				     *
XX+  *===========================================================================*/
XX+ PRIVATE void do_setsyn_alrm(m_ptr)
XX+ message *m_ptr;			/* pointer to request message */
XX+ {
XX+ /* A process wants an synchronous alarm. 
XX+  */
XX+ 
XX+   register struct proc *rp;
XX+   int proc_nr;			/* which process wants the alarm */
XX+   long delta_ticks;		/* in how many clock ticks does he want it? */
XX+ 
XX+   /* Extract the parameters from the message. */
XX+   proc_nr = m_ptr->CLOCK_PROC_NR;	/* process to interrupt later */
XX+   delta_ticks = m_ptr->DELTA_TICKS;	/* how many ticks to wait */
XX+   rp = proc_addr(proc_nr);
XX+   mc.SECONDS_LEFT = (rp->p_alarm == 0 ? 0 : (rp->p_alarm - realtime)/HZ );
XX+   common_setalarm(proc_nr, delta_ticks, cause_alarm);
XX  }
XX  
XX  
XX  /*===========================================================================*
XX!  *				do_getuptime				     *
XX   *===========================================================================*/
XX! PRIVATE void do_getuptime()
XX  {
XX! /* Get and return the current clock uptime in ticks. */
XX  
XX!   mc.NEW_TIME = realtime;	/* current uptime */
XX  }
XX  
XX  
XX  /*===========================================================================*
XX!  *				common_setalarm				     *
XX   *===========================================================================*/
XX! PRIVATE void common_setalarm(proc_nr, delta_ticks, function)
XX! int proc_nr;			/* which process wants the alarm */
XX! long delta_ticks;		/* in how many clock ticks does he want it? */
XX! watchdog_t function;		/* function to call (0 if cause_sig is
XX! 				 * to be called */
XX  {
XX! /* Record an alarm request and check to see it is the next alarm needed.  */
XX  
XX!   register struct proc *rp;
XX! 
XX!   rp = proc_addr(proc_nr);
XX!   rp->p_alarm = (delta_ticks == 0 ? 0 : realtime + delta_ticks);
XX!   watch_dog[proc_nr+NR_TASKS] = function;
XX! 
XX!   /* Which alarm is next? */
XX!   next_alarm = LONG_MAX;
XX!   for (rp = BEG_PROC_ADDR; rp < END_PROC_ADDR; rp++)
XX! 	if(rp->p_alarm != 0 && rp->p_alarm < next_alarm)next_alarm=rp->p_alarm;
XX! 
XX  }
XX  
XX  
XX  /*===========================================================================*
XX!  *				get_uptime				     *
XX   *===========================================================================*/
XX! PUBLIC clock_t get_uptime()
XX  {
XX! /* Get and return the current clock uptime in ticks.  This function is
XX!  * designed to be called from other tasks, so it has to be careful about
XX!  * pending_ticks.
XX!  */
XX  
XX!   clock_t uptime;
XX  
XX!   lock();
XX!   uptime = realtime + pending_ticks;
XX!   unlock();
XX!   return(uptime);
XX! }
XX  
XX! 
XX! /*===========================================================================*
XX!  *				syn_alrm_task				     *
XX!  *===========================================================================*/
XX! PUBLIC void syn_alrm_task()
XX! {
XX! /* Main program of syn_alrm task.  It sends CLOCK_INT messages to process that
XX!  * requested a syn_alrm.
XX!  */
XX!  
XX!   message mess;
XX!   int work_done;	/* ready to sleep ? */
XX!   int *al_ptr;		/* pointer in syn_table */
XX!   int i;
XX! 
XX!   syn_al_alive= TRUE;
XX!   for (i= 0, al_ptr= syn_table; i<NR_TASKS+NR_PROCS; i++, al_ptr++)
XX! 	*al_ptr= FALSE;
XX! 
XX!   while (TRUE) {
XX! 	work_done= TRUE;
XX! 	for (i= 0, al_ptr= syn_table; i<NR_TASKS+NR_PROCS; i++, al_ptr++)
XX! 		if (*al_ptr) {
XX! 			*al_ptr= FALSE;
XX! 			mess.m_type= CLOCK_INT;
XX! 			send (i-NR_TASKS, &mess); 
XX! 			work_done= FALSE;
XX  		}
XX+ 	if (work_done) {
XX+ 		syn_al_alive= FALSE;
XX+ 		receive (CLOCK, &mess);
XX+ 		syn_al_alive= TRUE;
XX  	}
XX    }
XX  }
XX  
XX  
XX+ /*===========================================================================*
XX+  *				cause_alarm				     *
XX+  *===========================================================================*/
XX+ PRIVATE void cause_alarm()
XX+ {
XX+ /* Routine called if a timer goes off and the process requested a synchronous
XX+  * alarm. The process number is in the global variable watchdog_proc (HACK).
XX+  */
XX+   message mess;
XX+ 
XX+   syn_table[watchdog_proc + NR_TASKS]= TRUE;
XX+   if (!syn_al_alive) send (SYN_ALRM_TASK, &mess);
XX+ }
XX  #if (CHIP == INTEL)
XX+ 
XX+ 
XX  /*===========================================================================*
XX   *				init_clock				     *
XX   *===========================================================================*/
XX***************
XX*** 219,225 ****
XX    out_byte(TIMER_MODE, SQUARE_WAVE);	/* set timer to run continuously */
XX    out_byte(TIMER0, TIMER_COUNT);	/* load timer low byte */
XX    out_byte(TIMER0, TIMER_COUNT >> 8);	/* load timer high byte */
XX!   enable_irq(CLOCK_IRQ);	/* ready for clock interrupts */
XX  }
XX  
XX  
XX--- 361,367 ----
XX    out_byte(TIMER_MODE, SQUARE_WAVE);	/* set timer to run continuously */
XX    out_byte(TIMER0, TIMER_COUNT);	/* load timer low byte */
XX    out_byte(TIMER0, TIMER_COUNT >> 8);	/* load timer high byte */
XX!   enable_irq(CLOCK_IRQ);		/* ready for clock interrupts */
XX  }
XX  
XX  
XX***************
XX*** 286,294 ****
XX   * rate is further reduced by software with a factor of 4.
XX   * Note that the expression below works for both HZ=50 and HZ=60.
XX   */
XX!   do
XX  	MFP->mf_tcdr = TIMER_FREQ/(64*4*HZ);
XX!   while ((MFP->mf_tcdr & 0xFF) != TIMER_FREQ/(64*4*HZ));
XX    MFP->mf_tcdcr |= (T_Q064<<4);
XX  }
XX  #endif
XX--- 428,436 ----
XX   * rate is further reduced by software with a factor of 4.
XX   * Note that the expression below works for both HZ=50 and HZ=60.
XX   */
XX!   do {
XX  	MFP->mf_tcdr = TIMER_FREQ/(64*4*HZ);
XX!   } while ((MFP->mf_tcdr & 0xFF) != TIMER_FREQ/(64*4*HZ));
XX    MFP->mf_tcdcr |= (T_Q064<<4);
XX  }
XX  #endif
XX***************
XX*** 326,332 ****
XX   *		not properly protected in dmp.c (the increment here is not
XX   *		atomic) but that hardly matters.
XX   *	pending_ticks:
XX!  *		This is protected by an explicit lock in clock.c.  Don't
XX   *		update realtime directly, since there are too many
XX   *		references to it to guard conveniently.
XX   *	sched_ticks, prev_ptr:
XX--- 468,474 ----
XX   *		not properly protected in dmp.c (the increment here is not
XX   *		atomic) but that hardly matters.
XX   *	pending_ticks:
XX!  *		This is protected by explicit locks in clock.c.  Don't
XX   *		update realtime directly, since there are too many
XX   *		references to it to guard conveniently.
XX   *	sched_ticks, prev_ptr:
XX***************
XX*** 350,381 ****
XX     * Thus the unbillable tasks' user time is the billable users' system time.
XX     */
XX    if (k_reenter != 0)
XX! 	rp = cproc_addr(HARDWARE);
XX    else
XX  	rp = proc_ptr;
XX    ++rp->user_time;
XX!   if (rp != bill_ptr) ++bill_ptr->sys_time;
XX  
XX    ++pending_ticks;
XX- #if (CHIP != M68000)
XX    tty_wakeup();			/* possibly wake up TTY */
XX    pr_restart();			/* possibly restart printer */
XX  #endif
XX  #if (CHIP == M68000)
XX    kb_timer();			/* keyboard repeat */
XX    if (sched_ticks == 1) fd_timer();	/* floppy deselect */
XX- 
XX-   /* If input characters are accumulating on an RS232 line, process them. */
XX-   if (flush_flag) {
XX- 	if ( (((int)(realtime+pending_ticks)) & FLUSH_MASK) == 0) rs_flush();
XX- 		 		/* only low-order bits of realtime mattered */
XX-   }
XX  #endif
XX  
XX    if (next_alarm <= realtime + pending_ticks ||
XX        sched_ticks == 1 &&
XX        bill_ptr == prev_ptr &&
XX! #if (CHIP != M68000)
XX        rdy_head[USER_Q] != NIL_PROC) {
XX  #else
XX        (rdy_head[USER_Q] != NIL_PROC || rdy_head[SHADOW_Q] != NIL_PROC)) {
XX--- 492,517 ----
XX     * Thus the unbillable tasks' user time is the billable users' system time.
XX     */
XX    if (k_reenter != 0)
XX! 	rp = proc_addr(HARDWARE);
XX    else
XX  	rp = proc_ptr;
XX    ++rp->user_time;
XX!   if (rp != bill_ptr && rp != proc_addr(IDLE)) ++bill_ptr->sys_time;
XX  
XX    ++pending_ticks;
XX    tty_wakeup();			/* possibly wake up TTY */
XX+ #if (CHIP != M68000)
XX    pr_restart();			/* possibly restart printer */
XX  #endif
XX  #if (CHIP == M68000)
XX    kb_timer();			/* keyboard repeat */
XX    if (sched_ticks == 1) fd_timer();	/* floppy deselect */
XX  #endif
XX  
XX    if (next_alarm <= realtime + pending_ticks ||
XX        sched_ticks == 1 &&
XX        bill_ptr == prev_ptr &&
XX! #if (SHADOWING == 0)
XX        rdy_head[USER_Q] != NIL_PROC) {
XX  #else
XX        (rdy_head[USER_Q] != NIL_PROC || rdy_head[SHADOW_Q] != NIL_PROC)) {
X/
Xecho x - config.d
Xsed '/^X/s///' > config.d << '/'
XX*** /home/top/ast/minix/1.5/kernel/config  crc=21032   1152	Sat May  5 13:15:11 1990
XX--- /home/top/ast/minix/1.6.25/kernel/config  crc=12598   1243	Tue Nov  3 21:20:43 1992
XX***************
XX*** 1,6 ****
XX--- 1,7 ----
XX  prog=`basename $0`
XX  
XX  case $1 in
XX+ 
XX  	at)	cpu=88
XX  		wini=at_wini
XX  		what_bits=16
XX***************
XX*** 25,41 ****
XX  		what_cpu=80386
XX  		what_wini=AT;;
XX  
XX! 	ps)     cpu=88
XX  		wini=ps_wini.c
XX  		what_bits=16
XX  		what_cpu=8088
XX  		what_wini="PS/2";;
XX  
XX  	clean)	echo "rm -f klib.x mpx.x wini.c"
XX  		rm -f klib.x mpx.x wini.c
XX  		exit 0;;
XX  	*)	
XX! 		echo "$prog: usage: $prog [at, bios, xt, 386, ps2]"
XX  		exit 1;;
XX  esac
XX  
XX--- 26,48 ----
XX  		what_cpu=80386
XX  		what_wini=AT;;
XX  
XX! 	ps2)    cpu=88
XX  		wini=ps_wini.c
XX  		what_bits=16
XX  		what_cpu=8088
XX  		what_wini="PS/2";;
XX  
XX+ 	esdi) cpu=88
XX+ 		wini=esdi_wini.c
XX+ 		what_bits=16
XX+ 		what_cpu=8088
XX+ 		what_wini=ESDI;;
XX+ 
XX  	clean)	echo "rm -f klib.x mpx.x wini.c"
XX  		rm -f klib.x mpx.x wini.c
XX  		exit 0;;
XX  	*)	
XX! 		echo "$prog: usage: $prog [at, bios, xt, 386, ps2, esdi]"
XX  		exit 1;;
XX  esac
XX  
X/
Xecho x - console.c.d
Xsed '/^X/s///' > console.c.d << '/'
XX*** /home/top/ast/minix/1.5/kernel/console.c  crc=32891  25528	Sat Apr 21 22:26:23 1990
XX--- /home/top/ast/minix/1.6.25/kernel/console.c  crc=55159  26040	Sun Nov 15 23:17:23 1992
XX***************
XX*** 47,62 ****
XX  /* Map from ANSI colors to the attributes used by the PC */
XX  PRIVATE int ansi_colors[8] = {0, 4, 2, 6, 1, 5, 3, 7};
XX  
XX! FORWARD void beep();
XX! FORWARD void do_escape();
XX! FORWARD void l_scr_up();
XX! FORWARD void l_scr_down();
XX! FORWARD void long_vid_copy();
XX! FORWARD void move_to();
XX! FORWARD void parse_escape();
XX! FORWARD void scroll_screen();
XX! FORWARD void set_6845();
XX! FORWARD void stop_beep();
XX  
XX  /*===========================================================================*
XX   *				console					     *
XX--- 47,65 ----
XX  /* Map from ANSI colors to the attributes used by the PC */
XX  PRIVATE int ansi_colors[8] = {0, 4, 2, 6, 1, 5, 3, 7};
XX  
XX! FORWARD _PROTOTYPE( void beep, (void) );
XX! FORWARD _PROTOTYPE( void do_escape, (struct tty_struct *tp, int c) );
XX! FORWARD _PROTOTYPE( void l_scr_up, (unsigned int base, int src, int dst,
XX! 								int count) );
XX! FORWARD _PROTOTYPE( void l_scr_down, (unsigned int base, int src, int dst, 
XX! 								int count) );
XX! FORWARD _PROTOTYPE( void long_vid_copy, (char *src, unsigned int base,
XX! 				unsigned int offset, unsigned int count) );
XX! FORWARD _PROTOTYPE( void move_to, (struct tty_struct *tp, int x, int y) );
XX! FORWARD _PROTOTYPE( void parse_escape, (struct tty_struct *tp, int c) );
XX! FORWARD _PROTOTYPE( void scroll_screen, (struct tty_struct *tp, int dir) );
XX! FORWARD _PROTOTYPE( void set_6845, (int reg, int val) );
XX! FORWARD _PROTOTYPE( void stop_beep, (void) );
XX  
XX  /*===========================================================================*
XX   *				console					     *
XX***************
XX*** 202,210 ****
XX  #if !LINEWRAP
XX  		if (tp->tty_column >= LINE_WIDTH) return;	/* long line */
XX  #endif
XX- 		if (tp->tty_rwords == TTY_RAM_WORDS) flush(tp);
XX- 		tp->tty_ramqueue[tp->tty_rwords++]=one_con_attribute|(c&BYTE);
XX- 		tp->tty_column++;	/* next column */
XX  #if LINEWRAP
XX   		if (tp->tty_column >= LINE_WIDTH) {
XX   			flush(tp);
XX--- 205,210 ----
XX***************
XX*** 215,220 ****
XX--- 215,223 ----
XX   			move_to(tp, 0, tp->tty_row);
XX   		}
XX  #endif /* LINEWRAP */
XX+ 		if (tp->tty_rwords == TTY_RAM_WORDS) flush(tp);
XX+ 		tp->tty_ramqueue[tp->tty_rwords++]=one_con_attribute|(c&BYTE);
XX+ 		tp->tty_column++;	/* next column */
XX  		return;
XX    }
XX  }
XX***************
XX*** 493,499 ****
XX  			count = (SCR_LINES - n - tp->tty_row) * LINE_WIDTH;
XX  			l_scr_up(vid_base, src, dst, count);
XX  			dst = tp->tty_org + (SCR_LINES - n) * LINE_WIDTH * 2;
XX! 			  long_vid_copy(NIL_PTR, vid_base, dst, n * LINE_WIDTH);
XX  			break;
XX  
XX  		    case 'P':		/* ESC [nP deletes n chars at cursor */
XX--- 496,502 ----
XX  			count = (SCR_LINES - n - tp->tty_row) * LINE_WIDTH;
XX  			l_scr_up(vid_base, src, dst, count);
XX  			dst = tp->tty_org + (SCR_LINES - n) * LINE_WIDTH * 2;
XX! 			  long_vid_copy(NIL_PTR, vid_base, dst, n*LINE_WIDTH);
XX  			break;
XX  
XX  		    case 'P':		/* ESC [nP deletes n chars at cursor */
XX***************
XX*** 621,627 ****
XX   *				long_src_up				     *
XX   *===========================================================================*/
XX  PRIVATE void l_scr_up(base, src, dst, count)
XX! unsigned int base, src, dst, count;
XX  {
XX  /* Break up a call to scr_up for machines that can only write
XX   * during vertical retrace.  scr_up doesn't do the wait, so we do.
XX--- 624,631 ----
XX   *				long_src_up				     *
XX   *===========================================================================*/
XX  PRIVATE void l_scr_up(base, src, dst, count)
XX! unsigned int base;
XX! int src, dst, count;
XX  {
XX  /* Break up a call to scr_up for machines that can only write
XX   * during vertical retrace.  scr_up doesn't do the wait, so we do.
XX***************
XX*** 648,654 ****
XX   *				long_scr_down				     *
XX   *===========================================================================*/
XX  PRIVATE void l_scr_down(base, src, dst, count)
XX! unsigned int base, src, dst, count;
XX  {
XX  /* Break up a call to scr_down as for scr_up. */
XX  
XX--- 652,659 ----
XX   *				long_scr_down				     *
XX   *===========================================================================*/
XX  PRIVATE void l_scr_down(base, src, dst, count)
XX! unsigned int base;
XX! int src, dst, count;
XX  {
XX  /* Break up a call to scr_down as for scr_up. */
XX  
XX***************
XX*** 717,723 ****
XX    mess.m_type = SET_ALARM;
XX    mess.CLOCK_PROC_NR = TTY;
XX    mess.DELTA_TICKS = B_TIME;
XX!   mess.FUNC_TO_CALL = (void (*)()) stop_beep;
XX    sendrec(CLOCK, &mess);
XX  }
XX  
XX--- 722,728 ----
XX    mess.m_type = SET_ALARM;
XX    mess.CLOCK_PROC_NR = TTY;
XX    mess.DELTA_TICKS = B_TIME;
XX!   mess.FUNC_TO_CALL = (sighandler_t) stop_beep;
XX    sendrec(CLOCK, &mess);
XX  }
XX  
XX***************
XX*** 774,783 ****
XX  }
XX  
XX  /*===========================================================================*
XX!  *				putc					     *
XX   *===========================================================================*/
XX! PUBLIC void putc(c)
XX! char c;				/* character to print */
XX  {
XX  /* This procedure is used by the version of printf() that is linked with
XX   * the kernel itself.  The one in the library sends a message to FS, which is
XX--- 779,788 ----
XX  }
XX  
XX  /*===========================================================================*
XX!  *				putk					     *
XX   *===========================================================================*/
XX! PUBLIC void putk(c)
XX! int c;				/* character to print */
XX  {
XX  /* This procedure is used by the version of printf() that is linked with
XX   * the kernel itself.  The one in the library sends a message to FS, which is
XX***************
XX*** 785,791 ****
XX   * the character and starts the output.
XX   */
XX  
XX!   out_char(&tty_struct[0], c);
XX  }
XX  
XX  
XX--- 790,796 ----
XX   * the character and starts the output.
XX   */
XX  
XX!   if (c != 0) out_char(&tty_struct[0], (int) c);
XX  }
XX  
XX  
X/
Xecho x - const.h.d
Xsed '/^X/s///' > const.h.d << '/'
XX*** /home/top/ast/minix/1.5/kernel/const.h  crc=39398   6614	Sat Apr 21 22:26:23 1990
XX--- /home/top/ast/minix/1.6.25/kernel/const.h  crc=26026   6652	Mon Feb  8 21:52:31 1993
XX***************
XX*** 7,13 ****
XX  #define INIT_PSW      0x0200	/* initial psw */
XX  #define INIT_TASK_PSW 0x1200	/* initial psw for tasks (with IOPL 1) */
XX  #define TRACEBIT       0x100	/* OR this with psw in proc[] for tracing */
XX! #define SETBITS(rp, new)	/* permits only certain bits to be set */ \
XX  	((rp)->p_reg.psw = (rp)->p_reg.psw & ~0xCD5 | (new) & 0xCD5)
XX  
XX  /* Initial sp for mm, fs and init.
XX--- 7,13 ----
XX  #define INIT_PSW      0x0200	/* initial psw */
XX  #define INIT_TASK_PSW 0x1200	/* initial psw for tasks (with IOPL 1) */
XX  #define TRACEBIT       0x100	/* OR this with psw in proc[] for tracing */
XX! #define SETPSW(rp, new)	/* permits only certain bits to be set */ \
XX  	((rp)->p_reg.psw = (rp)->p_reg.psw & ~0xCD5 | (new) & 0xCD5)
XX  
XX  /* Initial sp for mm, fs and init.
XX***************
XX*** 33,39 ****
XX  
XX  #define ALIGNMENT	   4	/* align large items to a multiple of this */
XX  #define VECTOR_BYTES    1024	/* bytes of interrupt vectors to save (all) */
XX- #define VEC_TABLE_SEG      0	/* segment of vector table */
XX  
XX  /* Interrupt vectors defined/reserved by processor. */
XX  #define DIVIDE_VECTOR      0	/* divide error */
XX--- 33,38 ----
XX***************
XX*** 123,140 ****
XX  
XX  #define K_STACK_BYTES   1024	/* how many bytes for the kernel stack */
XX  
XX  /* p_reg contains: d0-d7, a0-a6,   in that order. */
XX  #define NR_REGS           15	/* number of general regs in each proc slot */
XX   
XX  #define TRACEBIT      0x8000	/* or this with psw in proc[] for tracing */
XX! #define SETBITS(rp, new)	/* permits only certain bits to be set */ \
XX  	((rp)->p_reg.psw = (rp)->p_reg.psw & ~0xFF | (new) & 0xFF)
XX   
XX! #define MEM_BYTES  0x1000000	/* memory size for /dev/mem */
XX  #define ALIGNMENT	   4	/* align large items to a multiple of this */
XX  		/* 2 would do for an 68000, but 4 is nicer for 68020/68030 */
XX   
XX! #ifdef ACK
XX  #define FSTRUCOPY
XX  #endif
XX  
XX--- 122,142 ----
XX  
XX  #define K_STACK_BYTES   1024	/* how many bytes for the kernel stack */
XX  
XX+ /* Sizes of memory tables. */
XX+ #define NR_MEMS            2	/* number of chunks of memory */
XX+ 
XX  /* p_reg contains: d0-d7, a0-a6,   in that order. */
XX  #define NR_REGS           15	/* number of general regs in each proc slot */
XX   
XX  #define TRACEBIT      0x8000	/* or this with psw in proc[] for tracing */
XX! #define SETPSW(rp, new)		/* permits only certain bits to be set */ \
XX  	((rp)->p_reg.psw = (rp)->p_reg.psw & ~0xFF | (new) & 0xFF)
XX   
XX! #define MEM_BYTES  0xffffffff	/* memory size for /dev/mem */
XX  #define ALIGNMENT	   4	/* align large items to a multiple of this */
XX  		/* 2 would do for an 68000, but 4 is nicer for 68020/68030 */
XX   
XX! #ifdef __ACK__
XX  #define FSTRUCOPY
XX  #endif
XX  
X/
Xecho x - dmp.c.d
Xsed '/^X/s///' > dmp.c.d << '/'
XX*** /home/top/ast/minix/1.5/kernel/dmp.c  crc=50036   3257	Sat Apr 21 22:26:23 1990
XX--- /home/top/ast/minix/1.6.25/kernel/dmp.c  crc=16418   6792	Wed Mar 17 22:42:44 1993
XX***************
XX*** 1,69 ****
XX  /* This file contains some dumping routines for debugging. */
XX  
XX  #include "kernel.h"
XX- #include <minix/callnr.h>
XX  #include <minix/com.h>
XX  #include "proc.h"
XX  
XX! #define NSIZE 20
XX! phys_bytes aout[NR_PROCS];	/* pointers to the program names */
XX! char nbuff[NSIZE+1];
XX  char *vargv;
XX  
XX! FORWARD void prname();
XX  
XX  /*===========================================================================*
XX!  *				DEBUG routines here			     * 
XX   *===========================================================================*/
XX  PUBLIC void p_dmp()
XX  {
XX  /* Proc table dump */
XX  
XX    register struct proc *rp;
XX-   char *np;
XX    phys_clicks base, size;
XX-   phys_bytes dst;
XX    int index;
XX  
XX    printf(
XX!   "\r\nproc  --pid -pc- -sp flag -user- --sys-- -base- -size-  recv- command\r\n");
XX  
XX!   dst = umap(cproc_addr(SYSTASK), D, (vir_bytes)nbuff, NSIZE);
XX! 
XX!   for (rp = BEG_PROC_ADDR; rp < END_PROC_ADDR; rp++)  {
XX  	if (rp->p_flags & P_SLOT_FREE) continue;
XX  	base = rp->p_map[T].mem_phys;
XX  	size = rp->p_map[S].mem_phys + rp->p_map[S].mem_len - base;
XX  	prname(proc_number(rp));
XX  	printf("%5u %4lx %4lx %2x %7U %7U %5uK %5uK  ",
XX! 		rp->p_pid,
XX! 		(unsigned long) rp->p_reg.pc,
XX! 		(unsigned long) rp->p_reg.sp,
XX! 		rp->p_flags,
XX! 		rp->user_time, rp->sys_time,
XX! 		click_to_round_k(base), click_to_round_k(size));
XX! 		if (rp->p_flags == 0)
XX! 			printf("      ");
XX! 		else
XX! 			prname(rp->p_getfrom);
XX! 
XX! 	/* Fetch the command string from the user process. */
XX  	index = proc_number(rp);
XX! 	if (index > LOW_USER && aout[index] != 0) {
XX! 		phys_copy(aout[index], dst, (long) NSIZE);
XX! 		for (np = &nbuff[0]; np < &nbuff[NSIZE]; np++)
XX! 			if (*np <= ' ' || *np >= 0177) *np = 0;
XX! 		if (index == LOW_USER + 1)
XX! 			printf("/bin/sh");
XX! 		else
XX! 			printf("%s", nbuff);
XX  	}
XX  	printf("\r\n");
XX    }
XX    printf("\r\n");
XX  }
XX  
XX  
XX  
XX  PUBLIC void map_dmp()
XX  {
XX--- 1,56 ----
XX  /* This file contains some dumping routines for debugging. */
XX  
XX  #include "kernel.h"
XX  #include <minix/com.h>
XX  #include "proc.h"
XX+ #include "tty.h"
XX  
XX! #define NSIZE 40
XX! 
XX! char aout[NR_PROCS][NSIZE + 1];	/* pointers to the program names */
XX  char *vargv;
XX  
XX! FORWARD _PROTOTYPE(void prname, (int i));
XX  
XX  /*===========================================================================*
XX!  *				DEBUG routines here			     *
XX   *===========================================================================*/
XX+ #if (CHIP == INTEL)
XX  PUBLIC void p_dmp()
XX  {
XX  /* Proc table dump */
XX  
XX    register struct proc *rp;
XX    phys_clicks base, size;
XX    int index;
XX  
XX    printf(
XX!          "\r\nproc  --pid -pc- -sp flag -user- --sys-- -base- -size-  recv- command\r\n");
XX  
XX!   for (rp = BEG_PROC_ADDR; rp < END_PROC_ADDR; rp++) {
XX  	if (rp->p_flags & P_SLOT_FREE) continue;
XX  	base = rp->p_map[T].mem_phys;
XX  	size = rp->p_map[S].mem_phys + rp->p_map[S].mem_len - base;
XX  	prname(proc_number(rp));
XX  	printf("%5u %4lx %4lx %2x %7U %7U %5uK %5uK  ",
XX! 	       rp->p_pid,
XX! 	       (unsigned long) rp->p_reg.pc,
XX! 	       (unsigned long) rp->p_reg.sp,
XX! 	       rp->p_flags,
XX! 	       rp->user_time, rp->sys_time,
XX! 	       click_to_round_k(base), click_to_round_k(size));
XX  	index = proc_number(rp);
XX! 	if (index > LOW_USER) {
XX! 		printf("%s", aout[index]);
XX  	}
XX  	printf("\r\n");
XX    }
XX    printf("\r\n");
XX  }
XX  
XX+ #endif				/* (CHIP == INTEL) */
XX  
XX+ #if (SHADOWING == 0)
XX  
XX  PUBLIC void map_dmp()
XX  {
XX***************
XX*** 71,103 ****
XX    phys_clicks base, size;
XX  
XX    printf("\r\nPROC   -----TEXT-----  -----DATA-----  ----STACK-----  -BASE- -SIZE-\r\n");
XX!   for (rp = BEG_SERV_ADDR; rp < END_PROC_ADDR; rp++)  {
XX  	if (rp->p_flags & P_SLOT_FREE) continue;
XX  	base = rp->p_map[T].mem_phys;
XX  	size = rp->p_map[S].mem_phys + rp->p_map[S].mem_len - base;
XX  	prname(proc_number(rp));
XX! 	printf(" %4x %4x %4x  %4x %4x %4x  %4x %4x %4x  %5uK %5uK\r\n", 
XX! 	    rp->p_map[T].mem_vir, rp->p_map[T].mem_phys, rp->p_map[T].mem_len,
XX! 	    rp->p_map[D].mem_vir, rp->p_map[D].mem_phys, rp->p_map[D].mem_len,
XX! 	    rp->p_map[S].mem_vir, rp->p_map[S].mem_phys, rp->p_map[S].mem_len,
XX! 	    click_to_round_k(base), click_to_round_k(size));
XX    }
XX  }
XX  
XX  
XX  PRIVATE void prname(i)
XX  int i;
XX  {
XX    if (i == ANY)
XX  	printf("ANY   ");
XX!   else if ( (unsigned) (i + NR_TASKS) <= LOW_USER + NR_TASKS)
XX  	printf("%s", tasktab[i + NR_TASKS].name);
XX    else
XX  	printf("%4d  ", i);
XX  }
XX  
XX! PUBLIC void set_name(proc_nr, ptr)
XX! int proc_nr;
XX  char *ptr;
XX  {
XX  /* When an EXEC call is done, the kernel is told about the stack pointer.
XX--- 58,240 ----
XX    phys_clicks base, size;
XX  
XX    printf("\r\nPROC   -----TEXT-----  -----DATA-----  ----STACK-----  -BASE- -SIZE-\r\n");
XX!   for (rp = BEG_SERV_ADDR; rp < END_PROC_ADDR; rp++) {
XX  	if (rp->p_flags & P_SLOT_FREE) continue;
XX  	base = rp->p_map[T].mem_phys;
XX  	size = rp->p_map[S].mem_phys + rp->p_map[S].mem_len - base;
XX  	prname(proc_number(rp));
XX! 	printf(" %4x %4x %4x  %4x %4x %4x  %4x %4x %4x  %5uK %5uK\r\n",
XX! 	       rp->p_map[T].mem_vir, rp->p_map[T].mem_phys, rp->p_map[T].mem_len,
XX! 	       rp->p_map[D].mem_vir, rp->p_map[D].mem_phys, rp->p_map[D].mem_len,
XX! 	       rp->p_map[S].mem_vir, rp->p_map[S].mem_phys, rp->p_map[S].mem_len,
XX! 	       click_to_round_k(base), click_to_round_k(size));
XX    }
XX  }
XX  
XX+ #else
XX  
XX+ PUBLIC void map_dmp()
XX+ {
XX+   register struct proc *rp;
XX+   vir_clicks base, limit;
XX+ 
XX+   printf("\r\nPROC   --TEXT---  --DATA---  --STACK-- SHADOW FLIP P BASE  SIZE\r\n");
XX+   for (rp = BEG_SERV_ADDR; rp < END_PROC_ADDR; rp++) {
XX+ 	if (rp->p_flags & P_SLOT_FREE) continue;
XX+ 	base = rp->p_map[T].mem_phys;
XX+ 	limit = rp->p_map[S].mem_phys + rp->p_map[S].mem_len;
XX+ 	prname(proc_number(rp));
XX+ 	printf(" %4x %4x  %4x %4x  %4x %4x   %4x %4d %d %4uK %4uK\r\n",
XX+ 	       rp->p_map[T].mem_phys, rp->p_map[T].mem_len,
XX+ 	       rp->p_map[D].mem_phys, rp->p_map[D].mem_len,
XX+ 	       rp->p_map[S].mem_phys, rp->p_map[S].mem_len,
XX+ 	       rp->p_shadow, rp->p_nflips, rp->p_physio,
XX+ 	       click_to_round_k(base), click_to_round_k(limit));
XX+   }
XX+ }
XX+ 
XX+ #endif
XX+ 
XX+ #if (CHIP == M68000)
XX+ PUBLIC void p_dmp()
XX+ {
XX+ /* Proc table dump */
XX+ 
XX+   register struct proc *rp;
XX+   vir_clicks base, limit;
XX+   int index;
XX+ 
XX+   printf(
XX+          "\r\nproc    pid     pc     sp  splow flag  user    sys   recv  command\r\n");
XX+ 
XX+   for (rp = BEG_PROC_ADDR; rp < END_PROC_ADDR; rp++) {
XX+ 	if (rp->p_flags & P_SLOT_FREE) continue;
XX+ 	base = rp->p_map[T].mem_phys;
XX+ 	limit = rp->p_map[S].mem_phys + rp->p_map[S].mem_len;
XX+ 	prname(proc_number(rp));
XX+ 	printf(" %4u %6lx %6lx %6lx %4x %5U %6U   ",
XX+ 	       rp->p_pid,
XX+ 	       (unsigned long) rp->p_reg.pc,
XX+ 	       (unsigned long) rp->p_reg.sp,
XX+ 	       (unsigned long) rp->p_splow,
XX+ 	       rp->p_flags,
XX+ 	       rp->user_time, rp->sys_time);
XX+ 	if (rp->p_flags == 0)
XX+ 		printf("      ");
XX+ 	else {
XX+ 		if (rp->p_flags & RECEIVING) prname(rp->p_getfrom);
XX+ 		if (rp->p_flags & SENDING) {
XX+ 			printf("S: ");
XX+ 			prname(rp->p_sendto);
XX+ 		}
XX+ 	}
XX+ 
XX+ 	index = proc_number(rp);
XX+ 	if (index > LOW_USER) {
XX+ 		printf("%s", aout[index]);
XX+ 	}
XX+ 	printf("\r\n");
XX+   }
XX+   printf("\r\n");
XX+ }
XX+ 
XX+ 
XX+ PUBLIC void reg_dmp(rp)
XX+ struct proc *rp;
XX+ {
XX+   register int i;
XX+   static char *regs[NR_REGS] = {
XX+ 		    "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7",
XX+ 		    "a0", "a1", "a2", "a3", "a4", "a5", "a6"
XX+   };
XX+   reg_t *regptr = (reg_t *) & rp->p_reg;
XX+ 
XX+   printf("reg = %08lx, ", rp);
XX+   printf("ksp = %08lx\r\n", (long) &rp + sizeof(rp));
XX+   printf(" pc = %08lx, ", rp->p_reg.pc);
XX+   printf(" sr =     %04x, ", rp->p_reg.psw);
XX+   printf("trp =       %2x\r\n", rp->p_trap);
XX+   for (i = 0; i < NR_REGS; i++) 
XX+ 	printf("%3s = %08lx%s",regs[i], *regptr++, (i&3) == 3 ? "\r\n" : ", ");
XX+   printf(" a7 = %08lx\r\n", rp->p_reg.sp);
XX+ #if (SHADOWING == 1)
XX+     mem_dmp((char *) (((long) rp->p_reg.pc & ~31L) - 96), 128);
XX+     mem_dmp((char *) (((long) rp->p_reg.sp & ~31L) - 32), 256);
XX+ #else
XX+     mem_dmp((char *) (((long) rp->p_reg.pc & ~31L) - 96 +
XX+ 			((long)rp->p_map[T].mem_phys<<CLICK_SHIFT)), 128);
XX+     mem_dmp((char *) (((long) rp->p_reg.sp & ~31L) - 32 +
XX+ 			((long)rp->p_map[S].mem_phys<<CLICK_SHIFT)), 256);
XX+ #endif
XX+ }
XX+ 
XX+ #endif				/* (CHIP == M68000) */
XX+ 
XX+ 
XX+ PUBLIC void mem_dmp(adr, len)
XX+ char *adr;
XX+ int len;
XX+ {
XX+   register i;
XX+   register long *p;
XX+ 
XX+   for (i = 0, p = (long *) adr; i < len; i += 4) {
XX+ #if (CHIP == M68000)
XX+ 	if ((i & 31) == 0) printf("\r\n%lX:", p);
XX+ 	printf(" %8lX", *p++);
XX+ #else
XX+ 	if ((i & 31) == 0) printf("\r\n%X:", p);
XX+ 	printf(" %8X", *p++);
XX+ #endif /* (CHIP == M68000) */
XX+   }
XX+   printf("\r\n");
XX+ }
XX+ 
XX+ 
XX+ PUBLIC void tty_dmp()
XX+ {
XX+   struct tty_struct *tp;
XX+   int i;
XX+ 
XX+   printf("tty_events = %u\r\n", tty_events);
XX+ 
XX+   for (i = 0; i < NR_CONS + NR_RS_LINES; i++) {
XX+ 	tp = &tty_struct[i];
XX+ 	printf("line %d; incount = %d, inleft = %d, outleft = %d\n",
XX+ 	       i, tp->tty_incount, tp->tty_inleft, tp->tty_outleft);
XX+ 	if (tp->tty_busy)
XX+ 		printf("busy\r\n");
XX+ 	else
XX+ 		printf("not busy\r\n");
XX+ 	if (tp->tty_inhibited)
XX+ 		printf("inhibited\r\n");
XX+ 	else
XX+ 		printf("not inhibited\r\n");
XX+ 	if (tp->tty_waiting)
XX+ 		if (tp->tty_waiting == SUSPENDED)
XX+ 			printf("suspended\r\n");
XX+ 		else
XX+ 			printf("waiting\r\n");
XX+ 	else
XX+ 		printf("not waiting\r\n");
XX+   }
XX+ }
XX+ 
XX+ 
XX  PRIVATE void prname(i)
XX  int i;
XX  {
XX    if (i == ANY)
XX  	printf("ANY   ");
XX!   else if ((unsigned) (i + NR_TASKS) <= LOW_USER + NR_TASKS)
XX  	printf("%s", tasktab[i + NR_TASKS].name);
XX    else
XX  	printf("%4d  ", i);
XX  }
XX  
XX! 
XX! PUBLIC void set_name(source_nr, proc_nr, ptr)
XX! int source_nr, proc_nr;
XX  char *ptr;
XX  {
XX  /* When an EXEC call is done, the kernel is told about the stack pointer.
XX***************
XX*** 106,122 ****
XX   */
XX  
XX    phys_bytes src, dst;
XX  
XX!   if (ptr == (char *) 0) {
XX! 	aout[proc_nr] = (phys_bytes) 0;
XX! 	return;
XX!   }
XX  
XX!   src = umap(proc_addr(proc_nr), D, (vir_bytes)(ptr + sizeof vargv),
XX! 	     sizeof vargv);
XX!   if (src == 0) return;
XX!   dst = umap(cproc_addr(SYSTASK), D, (vir_bytes)&vargv, sizeof vargv);
XX!   phys_copy(src, dst, (phys_bytes) sizeof vargv);
XX  
XX!   aout[proc_nr] = umap(proc_addr(proc_nr), D, (vir_bytes)vargv, NSIZE);
XX  }
XX--- 243,266 ----
XX   */
XX  
XX    phys_bytes src, dst;
XX+   char *np;
XX  
XX!   aout[proc_nr][0] = 0;
XX!   if (!ptr) return;
XX  
XX!   src = numap(source_nr, (vir_bytes) ptr, (vir_bytes) NSIZE);
XX!   if (!src) return;
XX!   dst = umap(proc_addr(SYSTASK), D, (vir_bytes) (aout[proc_nr]), (vir_bytes)NSIZE);
XX!   phys_copy(src, dst, (phys_bytes) NSIZE);
XX  
XX!   aout[proc_nr][NSIZE] = 0;
XX!   for (np = &aout[proc_nr][0]; np < &aout[proc_nr][NSIZE]; np++)
XX! 	if (*np <= ' ' || *np >= 0177) *np = 0;
XX! }
XX! 
XX! 
XX! PUBLIC void fork_name(p1, p2)
XX! int p1, p2;
XX! {
XX!   memcpy(aout[p2], aout[p1], NSIZE + 1);
XX  }
X/
Xecho x - exception.c.d
Xsed '/^X/s///' > exception.c.d << '/'
XX*** /home/top/ast/minix/1.5/kernel/exception.c  crc=05434   2010	Sat Apr 21 22:26:23 1990
XX--- /home/top/ast/minix/1.6.25/kernel/exception.c  crc=13102   2076	Tue Nov  3 21:20:48 1992
XX***************
XX*** 51,56 ****
XX--- 51,57 ----
XX    }
XX  
XX    /* This is not supposed to happen. */
XX+   soon_reboot();		/* so printf doesn't try to use sys services */
XX    if (ep->msg == NIL_PTR || processor < ep->minprocessor)
XX  	printf("\r\nIntel-reserved exception %d\r\n", vec_nr);
XX    else
X/
Xecho x - floppy.c.d
Xsed '/^X/s///' > floppy.c.d << '/'
XX*** /home/top/ast/minix/1.5/kernel/floppy.c  crc=30650  38038	Sat Apr 21 22:26:23 1990
XX--- /home/top/ast/minix/1.6.25/kernel/floppy.c  crc=21686  41580	Wed Feb  3 00:38:32 1993
XX***************
XX*** 5,14 ****
XX   *
XX   *    m_type      DEVICE    PROC_NR     COUNT    POSITION  ADDRESS
XX   * ----------------------------------------------------------------
XX!  * |  DISK_READ | device  | proc nr |  bytes  |  offset | buf ptr |
XX   * |------------+---------+---------+---------+---------+---------|
XX!  * | DISK_WRITE | device  | proc nr |  bytes  |  offset | buf ptr |
XX!  * ----------------------------------------------------------------
XX   * |SCATTERED_IO| device  | proc nr | requests|         | iov ptr |
XX   * ----------------------------------------------------------------
XX   *
XX--- 5,18 ----
XX   *
XX   *    m_type      DEVICE    PROC_NR     COUNT    POSITION  ADDRESS
XX   * ----------------------------------------------------------------
XX!  * |  DEV_OPEN  |         |         |         |         |         |
XX   * |------------+---------+---------+---------+---------+---------|
XX!  * |  DEV_CLOSE |         |         |         |         |         |
XX!  * |------------+---------+---------+---------+---------+---------|
XX!  * |  DEV_READ  | device  | proc nr |  bytes  |  offset | buf ptr |
XX!  * |------------+---------+---------+---------+---------+---------|
XX!  * |  DEV_WRITE | device  | proc nr |  bytes  |  offset | buf ptr |
XX!  * |------------+---------+---------+---------+---------+---------|
XX   * |SCATTERED_IO| device  | proc nr | requests|         | iov ptr |
XX   * ----------------------------------------------------------------
XX   *
XX***************
XX*** 20,27 ****
XX   *	27 Oct. 1986 by Jakob Schripsema: fdc_results fixed for 8 MHz
XX   *	28 Nov. 1986 by Peter Kay: better resetting for 386
XX   *	06 Jan. 1988 by Al Crew: allow 1.44 MB diskettes
XX!  *		1989 by Bruce Evans: i/o vector to keep up with 1-1 interleave
XX!  *		1990 by Bruce Evans: formatting
XX   */
XX  
XX  #include "kernel.h"
XX--- 24,33 ----
XX   *	27 Oct. 1986 by Jakob Schripsema: fdc_results fixed for 8 MHz
XX   *	28 Nov. 1986 by Peter Kay: better resetting for 386
XX   *	06 Jan. 1988 by Al Crew: allow 1.44 MB diskettes
XX!  *	        1989 by Bruce Evans: I/O vector to keep up with 1-1 interleave
XX!  *	13 May  1991 by Don Chapman: renovated the errors loop.
XX!  *	14 Feb  1992 by Andy Tanenbaum: check drive density on opens only
XX!  *	27 Mar  1992 by Kees J. Bot: last details on density checking
XX   */
XX  
XX  #include "kernel.h"
XX***************
XX*** 99,106 ****
XX  #define NR_HEADS        0x02	/* two heads (i.e., two tracks/cylinder) */
XX  #define DTL             0xFF	/* determines data length (sector size) */
XX  #define SPEC2           0x02	/* second parameter to SPECIFY */
XX- 
XX  #define MOTOR_OFF       3*HZ	/* how long to wait before stopping motor */
XX  
XX  /* Error codes */
XX  #define ERR_SEEK          -1	/* bad seek */
XX--- 105,112 ----
XX  #define NR_HEADS        0x02	/* two heads (i.e., two tracks/cylinder) */
XX  #define DTL             0xFF	/* determines data length (sector size) */
XX  #define SPEC2           0x02	/* second parameter to SPECIFY */
XX  #define MOTOR_OFF       3*HZ	/* how long to wait before stopping motor */
XX+ #define TEST_BYTES        32	/* number of bytes to read in density tests */
XX  
XX  /* Error codes */
XX  #define ERR_SEEK          -1	/* bad seek */
XX***************
XX*** 120,134 ****
XX  #define MOTOR_RUNNING   0xFF	/* message type for clock interrupt */
XX  #define MAX_ERRORS         3	/* how often to try rd/wt before quitting */
XX  #define MAX_RESULTS        7	/* max number of bytes controller returns */
XX! #define NR_DRIVES          2	/* maximum number of drives */
XX  #define DIVISOR          128	/* used for sector size encoding */
XX! #define MAX_FDC_RETRY    100	/* max # times to try to output to FDC */
XX  #define NT                 7	/* number of diskette/drive combinations */
XX! #define AUTOMATIC	0x3F	/* bit map allowing both 3.5 and 5.25 disks */
XX! 				/* except for drive type 6, because that is */
XX! 				/* hard to distinguish from drive type 1 */
XX! #define THREE_INCH	0x48	/* bit map allowing only 3.5 inch diskettes */
XX! #define FIVE_INCH	0x37	/* bit map allowing only 5.25 inch diskettes */
XX  
XX  /* Variables. */
XX  PRIVATE struct floppy {		/* main drive struct, one entry per drive */
XX--- 126,139 ----
XX  #define MOTOR_RUNNING   0xFF	/* message type for clock interrupt */
XX  #define MAX_ERRORS         3	/* how often to try rd/wt before quitting */
XX  #define MAX_RESULTS        7	/* max number of bytes controller returns */
XX! #define NR_DRIVES          3	/* maximum number of drives */
XX  #define DIVISOR          128	/* used for sector size encoding */
XX! #define MAX_FDC_RETRY  10000	/* max # times to try to output to FDC */
XX! #define FDC_TIMEOUT      500	/* milliseconds waiting for FDC */
XX  #define NT                 7	/* number of diskette/drive combinations */
XX! #define UNCALIBRATED       0	/* drive needs to be calibrated at next use */
XX! #define CALIBRATED         1	/* no calibration needed */
XX! #define BASE_SECTOR        1	/* sectors are numbered starting at 1 */
XX  
XX  /* Variables. */
XX  PRIVATE struct floppy {		/* main drive struct, one entry per drive */
XX***************
XX*** 143,167 ****
XX    vir_bytes fl_address;		/* user virtual address */
XX    char fl_results[MAX_RESULTS];	/* the controller can give lots of output */
XX    char fl_calibration;		/* CALIBRATED or UNCALIBRATED */
XX!   char fl_density;		/* 0 = 360K/360K; 1 = 360K/1.2M; etc. */
XX!   char fl_auto_type;		/* nonzero to allow search for working type */
XX    struct disk_parameter_s fl_param;	/* parameters for format */
XX  } floppy[NR_DRIVES];
XX  
XX- #define UNCALIBRATED       0	/* drive needs to be calibrated at next use */
XX- #define CALIBRATED         1	/* no calibration needed */
XX- 
XX  PRIVATE int motor_status;	/* current motor status is in 4 high bits */
XX  PRIVATE int motor_goal;		/* desired motor status is in 4 high bits */
XX  PRIVATE int prev_motor;		/* which motor was started last */
XX  PRIVATE int need_reset;		/* set to 1 when controller must be reset */
XX  PRIVATE int d;			/* diskette/drive combination */
XX  PRIVATE int current_spec1;	/* latest spec1 sent to the controller */
XX- 
XX  PRIVATE message mess;		/* message buffer for in and out */
XX  
XX  PRIVATE char len[] = {-1,0,1,-1,2,-1,-1,3,-1,-1,-1,-1,-1,-1,-1,4};
XX- PRIVATE char base_sector = 1;	/* physical sectors form range starting here */
XX  
XX  /* Seven combinations of diskette/drive are supported. 
XX   *
XX--- 148,168 ----
XX    vir_bytes fl_address;		/* user virtual address */
XX    char fl_results[MAX_RESULTS];	/* the controller can give lots of output */
XX    char fl_calibration;		/* CALIBRATED or UNCALIBRATED */
XX!   char fl_density;		/* -1 = ?, 0 = 360K/360K; 1 = 360K/1.2M; etc.*/
XX!   char fl_class;		/* bitmap for possible densities */
XX    struct disk_parameter_s fl_param;	/* parameters for format */
XX  } floppy[NR_DRIVES];
XX  
XX  PRIVATE int motor_status;	/* current motor status is in 4 high bits */
XX  PRIVATE int motor_goal;		/* desired motor status is in 4 high bits */
XX  PRIVATE int prev_motor;		/* which motor was started last */
XX  PRIVATE int need_reset;		/* set to 1 when controller must be reset */
XX  PRIVATE int d;			/* diskette/drive combination */
XX  PRIVATE int current_spec1;	/* latest spec1 sent to the controller */
XX  PRIVATE message mess;		/* message buffer for in and out */
XX  
XX+ /* The len[] field is only used with 512/128 as its index by x86's */
XX  PRIVATE char len[] = {-1,0,1,-1,2,-1,-1,3,-1,-1,-1,-1,-1,-1,-1,4};
XX  
XX  /* Seven combinations of diskette/drive are supported. 
XX   *
XX***************
XX*** 193,233 ****
XX  	{1*HZ/4,3*HZ/4,1*HZ/4,4*HZ/4,3*HZ/4,3*HZ/4,4*HZ/4}; /* in ticks */
XX  PRIVATE char spec1[NT] =
XX  	{0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xAF}; /* step rate, etc. */
XX  
XX! /* This driver hunts around for the proper density by simply trying them all
XX!  * until it finds one that works.  By defining DEFAULT_CLASS, one can reduce 
XX!  * the searching to only 5.25 inch or only 3.5 inch types.  The array
XX!  * drive_class contains a bit map for each drive, telling which of the NT
XX!  * combinations defined above should be tried.
XX   */
XX! PRIVATE char drive_class[NR_DRIVES] = {
XX! #if (DEFAULT_CLASS == 3)
XX! 	THREE_INCH, THREE_INCH	/* drive 0 = 3.5 inch, drive 1 also */
XX! #endif
XX! #if (DEFAULT_CLASS == 5)
XX! 	FIVE_INCH, FIVE_INCH	/* drive 0 = 5.25 inch, drive 1 also */
XX! #endif
XX! #if (DEFAULT_CLASS != 3 && DEFAULT_CLASS != 5)
XX! 	AUTOMATIC, AUTOMATIC	/* both drives can handle both types */
XX! #endif
XX  };
XX  
XX! FORWARD void clock_mess();
XX! FORWARD void dma_setup();
XX! FORWARD int do1_rdwt();
XX! FORWARD int do_rdwt();
XX! FORWARD int f_do_vrdwt();
XX! FORWARD void f_reset();
XX! FORWARD void fdc_out();
XX! FORWARD int fdc_results();
XX! FORWARD int read_id();
XX! FORWARD int recalibrate();
XX! FORWARD int seek();
XX! FORWARD void send_mess();
XX! FORWARD void start_motor();
XX! FORWARD void stop_motor();
XX! FORWARD int transfer();
XX  
XX  /*===========================================================================*
XX   *				floppy_task				     * 
XX   *===========================================================================*/
XX--- 194,245 ----
XX  	{1*HZ/4,3*HZ/4,1*HZ/4,4*HZ/4,3*HZ/4,3*HZ/4,4*HZ/4}; /* in ticks */
XX  PRIVATE char spec1[NT] =
XX  	{0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xAF}; /* step rate, etc. */
XX+ PRIVATE int test_sector[NT] =
XX+ 	{4*9,  14,   2*9,  4*9,  2*9,  4*9,  16};   /* to recognize it */
XX  
XX! #define b(d)	(1 << (d))	/* bit for density d. */
XX! 
XX! /* The following table is used with the test_sector array to recognize a
XX!  * drive/floppy combination.  The sector to test has been determined by
XX!  * looking at the differences in gap size, sectors/track, and double stepping.
XX!  * This means that types 0 and 3 can't be told apart, only the motor start
XX!  * time differs.  When read test succeeds, the drive is limited to the set
XX!  * of densities it can support to avoid unnecessary tests in the future.
XX   */
XX! 
XX! PRIVATE struct test_order {
XX! 	char	t_density;	/* floppy/drive type */
XX! 	char	t_class;	/* limit drive to this class of densities */
XX! } test_order[NT-1] = {
XX! 	{ 6,  b(3) | b(6) },		/* 1.44M  {720K, 1.44M} */
XX! 	{ 1,  b(1) | b(4) | b(5) },	/* 1.2M   {1.2M, 360K, 720K} */
XX! 	{ 3,  b(2) | b(3) | b(6) },	/* 720K   {360K, 720K, 1.44M} */
XX! 	{ 4,  b(1) | b(4) | b(5) },	/* 360K   {1.2M, 360K, 720K} */
XX! 	{ 5,  b(1) | b(4) | b(5) },	/* 720K   {1.2M, 360K, 720K} */
XX! 	{ 2,  b(2) | b(3) },		/* 360K   {360K, 720K} */
XX! 	/* Note that type 0 is missing, type 3 can read/write it too (alas). */
XX  };
XX  
XX! FORWARD _PROTOTYPE( void clock_mess, (int ticks, watchdog_t func) );
XX! FORWARD _PROTOTYPE( void dma_setup, (struct floppy *fp) );
XX! FORWARD _PROTOTYPE( int do1_rdwt, (struct iorequest_s *iop, message *m_ptr) );
XX! FORWARD _PROTOTYPE( int do_rdwt, (message *m_ptr, int dont_retry) );
XX! FORWARD _PROTOTYPE( int f_do_vrdwt, (message *m_ptr) );
XX! FORWARD _PROTOTYPE( void f_reset, (void) );
XX! FORWARD _PROTOTYPE( void fdc_out, (int val) );
XX! FORWARD _PROTOTYPE( int fdc_results, (struct floppy *fp) );
XX! FORWARD _PROTOTYPE( int read_id, (struct floppy *fp) );
XX! FORWARD _PROTOTYPE( int recalibrate, (struct floppy *fp) );
XX! FORWARD _PROTOTYPE( int seek, (struct floppy *fp) );
XX! FORWARD _PROTOTYPE( void send_mess, (void) );
XX! FORWARD _PROTOTYPE( void start_motor, (struct floppy *fp) );
XX! FORWARD _PROTOTYPE( void stop_motor, (void) );
XX! FORWARD _PROTOTYPE( int transfer, (struct floppy *fp) );
XX! FORWARD _PROTOTYPE( void init, (void) );
XX! FORWARD _PROTOTYPE( int do_open, (message *m_ptr) );
XX! FORWARD _PROTOTYPE( int test_read, (struct floppy *fp, int density) );
XX  
XX+ 
XX  /*===========================================================================*
XX   *				floppy_task				     * 
XX   *===========================================================================*/
XX***************
XX*** 238,243 ****
XX--- 250,256 ----
XX    int r, caller, proc_nr;
XX  
XX    cim_floppy();			/* ready for floppy interrupts */
XX+   init();			/* initialize floppy struct */
XX  
XX    /* Here is the main loop of the disk task.  It waits for a message, carries
XX     * it out, and sends a reply.
XX***************
XX*** 256,265 ****
XX  
XX  	/* Now carry out the work. */
XX  	switch(mess.m_type) {
XX! 	    case DISK_READ:
XX! 	    case DISK_WRITE:	r = do_rdwt(&mess, FALSE);	break;
XX! 	    case SCATTERED_IO:	r = f_do_vrdwt(&mess);	break;
XX! 	    default:		r = EINVAL;		break;
XX  	}
XX  
XX  	/* Start watch_dog timer to turn all motors off in a few seconds. */
XX--- 269,282 ----
XX  
XX  	/* Now carry out the work. */
XX  	switch(mess.m_type) {
XX! 	    case DEV_OPEN:	r = do_open(&mess);		break;
XX! 	    case DEV_CLOSE:	r = OK;				break;
XX! 
XX! 	    case DEV_READ:
XX! 	    case DEV_WRITE:	r = do_rdwt(&mess, FALSE);	break;
XX! 
XX! 	    case SCATTERED_IO:	r = f_do_vrdwt(&mess);		break;
XX! 	    default:		r = EINVAL;			break;
XX  	}
XX  
XX  	/* Start watch_dog timer to turn all motors off in a few seconds. */
XX***************
XX*** 287,293 ****
XX    register struct floppy *fp;
XX    int r, sectors, drive, errors;
XX    off_t block;
XX-   unsigned dtype;
XX    phys_bytes param_phys;
XX    phys_bytes user_param_phys;
XX  
XX--- 304,309 ----
XX***************
XX*** 296,302 ****
XX    if (drive < 0 || drive >= NR_DRIVES) return(EIO);
XX    fp = &floppy[drive];		/* 'fp' points to entry for this drive */
XX    fp->fl_drive = drive;		/* save drive number explicitly */
XX!   fp->fl_opcode = (m_ptr->m_type == DISK_READ ? FDC_READ : FDC_WRITE);
XX    if (m_ptr->DEVICE & FORMAT_DEV_BIT) {
XX  	if (fp->fl_opcode == FDC_READ) return(EIO);
XX  	fp->fl_opcode = FDC_FORMAT;
XX--- 312,318 ----
XX    if (drive < 0 || drive >= NR_DRIVES) return(EIO);
XX    fp = &floppy[drive];		/* 'fp' points to entry for this drive */
XX    fp->fl_drive = drive;		/* save drive number explicitly */
XX!   fp->fl_opcode = (m_ptr->m_type == DEV_READ ? FDC_READ : FDC_WRITE);
XX    if (m_ptr->DEVICE & FORMAT_DEV_BIT) {
XX  	if (fp->fl_opcode == FDC_READ) return(EIO);
XX  	fp->fl_opcode = FDC_FORMAT;
XX***************
XX*** 312,394 ****
XX  	 */
XX  	if (fp->fl_param.sectors_per_cylinder == 0) return(EIO);
XX    }
XX-   dtype = m_ptr->DEVICE & DEV_TYPE_BITS;
XX-   if (dtype != 0) {
XX- 	dtype = (dtype >> DEV_TYPE_SHIFT) - 1;
XX- 	if (dtype >= NT) return(EIO);
XX- 	fp->fl_density = dtype;
XX- 	fp->fl_auto_type = FALSE;
XX-   } else
XX- 	fp->fl_auto_type = TRUE;
XX  
XX!   if (m_ptr->POSITION % BLOCK_SIZE != 0) return(EINVAL);
XX    block = m_ptr->POSITION/SECTOR_SIZE;
XX!   if (block >= HC_SIZE) return(0);	/* sector is beyond end of all disks */
XX  
XX-   d = fp->fl_density;		/* diskette/drive combination */
XX-   if (fp->fl_auto_type) {
XX- 	/* Check bit map to skip illegal densities. */
XX- 	while ((drive_class[drive] & (1 << d)) == 0) d = (d + 1) % NT;
XX-   }
XX- 
XX    /* Store the message parameters in the fp->fl array. */
XX-   fp->fl_density=d;
XX-   sectors = (m_ptr->DEVICE & FORMAT_DEV_BIT ?
XX- 	     fp->fl_param.sectors_per_cylinder : nr_sectors[d]);
XX-   fp->fl_cylinder = (int) (block / (NR_HEADS * sectors));
XX-   fp->fl_sector = base_sector + (int) (block % sectors);
XX-   fp->fl_head = (int) (block % (NR_HEADS * sectors)) / sectors;
XX    fp->fl_count = m_ptr->COUNT;
XX    fp->fl_address = (vir_bytes) m_ptr->ADDRESS;
XX    fp->fl_procnr = m_ptr->PROC_NR;
XX!   if (fp->fl_count != BLOCK_SIZE) return(EINVAL);
XX! 
XX    errors = 0;
XX  
XX!   /* This loop allows a failed operation to be repeated.  It is really a
XX!    * nested loop allowing MAX_ERRORS errors for each of NT drive types.
XX!    */
XX!   while (errors <= MAX_ERRORS * NT) {
XX! 	if (++errors % MAX_ERRORS == 0) {
XX  
XX- #if 0 /* this works well except for programs like mkfs which seek to end 1st*/
XX- 		/* A lot of errors probably means that we are trying the
XX- 		 * wrong drive type.  Try another one if the cylinder is <= 1.
XX- 		 * Otherwise, assume the disk is unchanged and give up.
XX- 		 */
XX- 		if (fp->fl_cylinder > 1)
XX- 			return(block >= nr_blocks[d] ? 0 : EIO);
XX- #else
XX- 		/* A lot of errors probably means that we are trying the
XX- 		 * wrong drive type.  Try another one.
XX- 		 */
XX- #endif
XX- 		if (!fp->fl_auto_type) return(EIO);
XX-                 d++;
XX- 
XX- 		/* Check bit map to skip illegal densities. */
XX- 		while ((drive_class[drive] & (1 << d)) == 0) d = (d + 1) % NT;
XX-  		fp->fl_density = d;
XX- 
XX- 		sectors = nr_sectors[d];
XX- 		fp->fl_cylinder = (int) (block / (NR_HEADS * sectors));
XX- 		fp->fl_sector = base_sector + (int) (block % sectors);
XX- 		fp->fl_head = (int)(block%(NR_HEADS*sectors)) / sectors;
XX-  		need_reset = 1;
XX- 	}
XX-   	if (block >= nr_blocks[d]) continue;
XX- 
XX  	/* First check to see if a reset is needed. */
XX  	if (need_reset) f_reset();
XX  
XX  	/* Set the stepping rate */
XX  	if (current_spec1 != spec1[d]) {
XX  		fdc_out(FDC_SPECIFY);
XX! 		fdc_out(current_spec1=spec1[d]);
XX  		fdc_out(SPEC2);
XX  	}
XX  
XX!  	/* Set the data rate */
XX  	if (pc_at) out_byte(FDC_RATE, rate[d]);
XX  
XX  	/* Now set up the DMA chip. */
XX--- 328,367 ----
XX  	 */
XX  	if (fp->fl_param.sectors_per_cylinder == 0) return(EIO);
XX    }
XX  
XX!   if (m_ptr->POSITION % BLOCK_SIZE) return(EINVAL);
XX!   d = fp->fl_density;		/* diskette/drive combination */
XX!   if (d < 0 || d >= NT) return(EIO);	/* impossible situation */
XX    block = m_ptr->POSITION/SECTOR_SIZE;
XX!   if (block < 0) return(EINVAL);
XX!   if (block >= nr_blocks[d]) return(0);	/* sector is beyond end of the disk */
XX  
XX    /* Store the message parameters in the fp->fl array. */
XX    fp->fl_count = m_ptr->COUNT;
XX    fp->fl_address = (vir_bytes) m_ptr->ADDRESS;
XX    fp->fl_procnr = m_ptr->PROC_NR;
XX!   if (fp->fl_count != BLOCK_SIZE && fp->fl_procnr != FLOPPY) return(EINVAL);
XX    errors = 0;
XX  
XX!   /* This loop allows a failed operation to be repeated. */
XX!   while (errors <= MAX_ERRORS) {
XX! 	sectors = nr_sectors[d];
XX! 	fp->fl_cylinder = (int) (block / (NR_HEADS * sectors));
XX! 	fp->fl_sector = BASE_SECTOR + (int) (block % sectors);
XX! 	fp->fl_head = (int)(block%(NR_HEADS*sectors)) / sectors;
XX  
XX  	/* First check to see if a reset is needed. */
XX  	if (need_reset) f_reset();
XX  
XX  	/* Set the stepping rate */
XX  	if (current_spec1 != spec1[d]) {
XX  		fdc_out(FDC_SPECIFY);
XX! 		current_spec1 = spec1[d];
XX! 		fdc_out(current_spec1);
XX  		fdc_out(SPEC2);
XX  	}
XX  
XX! 	/* Set the data rate */
XX  	if (pc_at) out_byte(FDC_RATE, rate[d]);
XX  
XX  	/* Now set up the DMA chip. */
XX***************
XX*** 405,410 ****
XX--- 378,384 ----
XX  	if (r == OK) break;	/* if successful, exit loop */
XX  	if (dont_retry) break;	/* retries not wanted */
XX  	if (r == ERR_WR_PROTECT) break;	/* retries won't help */
XX+ 	errors++;
XX    }
XX    return(r == OK ? fp->fl_count : EIO);
XX  }
XX***************
XX*** 604,609 ****
XX--- 578,584 ----
XX    if (fp->fl_opcode == FDC_FORMAT) return(OK);
XX  
XX    /* Compare actual numbers of sectors transferred with expected number. */
XX+   if (fp->fl_procnr == FLOPPY) return(OK);    /* FLOPPY reads partial sector */
XX    s =  (fp->fl_results[ST_CYL] - fp->fl_cylinder) * NR_HEADS * nr_sectors[d];
XX    s += (fp->fl_results[ST_HEAD] - fp->fl_head) * nr_sectors[d];
XX    s += (fp->fl_results[ST_SEC] - fp->fl_sector);
XX***************
XX*** 630,636 ****
XX     * really an outer loop on result_nr and an inner loop on status.
XX     */
XX    result_nr = 0;
XX!   retries = MAX_FDC_RETRY;
XX    while (TRUE) {
XX  	/* Reading one byte is almost a mirror of fdc_out() - the DIRECTION
XX  	 * bit must be set instead of clear, but the CTL_BUSY bit destroys
XX--- 605,611 ----
XX     * really an outer loop on result_nr and an inner loop on status.
XX     */
XX    result_nr = 0;
XX!   retries = MAX_FDC_RETRY + FDC_TIMEOUT;
XX    while (TRUE) {
XX  	/* Reading one byte is almost a mirror of fdc_out() - the DIRECTION
XX  	 * bit must be set instead of clear, but the CTL_BUSY bit destroys
XX***************
XX*** 640,652 ****
XX  	if (status == (MASTER | DIRECTION | CTL_BUSY)) {
XX  		if (result_nr >= MAX_RESULTS) break;	/* too many results */
XX  		fp->fl_results[result_nr++] = in_byte(FDC_DATA);
XX! 		retries = MAX_FDC_RETRY;
XX  		continue;
XX  	}
XX  	if (status == MASTER) {	/* all read */
XX  		cim_floppy();
XX  		return(OK);	/* only good exit */
XX  	}
XX  	if (--retries == 0) break;	/* time out */
XX    }
XX    need_reset = TRUE;		/* controller chip must be reset */
XX--- 615,628 ----
XX  	if (status == (MASTER | DIRECTION | CTL_BUSY)) {
XX  		if (result_nr >= MAX_RESULTS) break;	/* too many results */
XX  		fp->fl_results[result_nr++] = in_byte(FDC_DATA);
XX! 		retries = MAX_FDC_RETRY + FDC_TIMEOUT;
XX  		continue;
XX  	}
XX  	if (status == MASTER) {	/* all read */
XX  		cim_floppy();
XX  		return(OK);	/* only good exit */
XX  	}
XX+ 	if (retries < FDC_TIMEOUT) milli_delay(1);	/* take it slow now */
XX  	if (--retries == 0) break;	/* time out */
XX    }
XX    need_reset = TRUE;		/* controller chip must be reset */
XX***************
XX*** 671,683 ****
XX    if (need_reset) return;	/* if controller is not listening, return */
XX  
XX    /* It may take several tries to get the FDC to accept a command. */
XX!   retries = MAX_FDC_RETRY;
XX!   while ( (in_byte(FDC_STATUS) & (MASTER | DIRECTION)) != (MASTER | 0) )
XX  	if (--retries == 0) {
XX!   /* Controller is not listening.  Hit it over the head with a hammer. */
XX  		need_reset = TRUE;
XX  		return;
XX  	}
XX    out_byte(FDC_DATA, val);
XX  }
XX  
XX--- 647,661 ----
XX    if (need_reset) return;	/* if controller is not listening, return */
XX  
XX    /* It may take several tries to get the FDC to accept a command. */
XX!   retries = MAX_FDC_RETRY + FDC_TIMEOUT;
XX!   while ( (in_byte(FDC_STATUS) & (MASTER | DIRECTION)) != (MASTER | 0) ) {
XX  	if (--retries == 0) {
XX! 		/* Controller is not listening.  Hit it over the head. */
XX  		need_reset = TRUE;
XX  		return;
XX  	}
XX+ 	if (retries < FDC_TIMEOUT) milli_delay(1);
XX+   }
XX    out_byte(FDC_DATA, val);
XX  }
XX  
XX***************
XX*** 708,714 ****
XX  
XX    /* Determine if the recalibration succeeded. */
XX    fdc_out(FDC_SENSE);		/* issue SENSE command to request results */
XX!   r = fdc_results(fp);		/* get results of the FDC_RECALIBRATE command */
XX    fp->fl_curcyl = -1;		/* force a SEEK next time */
XX    if (r != OK ||		/* controller would not respond */
XX       (fp->fl_results[ST0]&ST0_BITS) != SEEK_ST0 || fp->fl_results[ST_PCN] !=0){
XX--- 686,692 ----
XX  
XX    /* Determine if the recalibration succeeded. */
XX    fdc_out(FDC_SENSE);		/* issue SENSE command to request results */
XX!   r = fdc_results(fp);		/* get results of the FDC_RECALIBRATE command*/
XX    fp->fl_curcyl = -1;		/* force a SEEK next time */
XX    if (r != OK ||		/* controller would not respond */
XX       (fp->fl_results[ST0]&ST0_BITS) != SEEK_ST0 || fp->fl_results[ST_PCN] !=0){
XX***************
XX*** 743,749 ****
XX  
XX  
XX  /*===========================================================================*
XX!  *				reset					     * 
XX   *===========================================================================*/
XX  PRIVATE void f_reset()
XX  {
XX--- 721,727 ----
XX  
XX  
XX  /*===========================================================================*
XX!  *				f_reset					     * 
XX   *===========================================================================*/
XX  PRIVATE void f_reset()
XX  {
XX***************
XX*** 772,782 ****
XX    out_byte(DOR, ENABLE_INT);	/* strobe it high again */
XX    unlock();
XX    receive(HARDWARE, &mess);	/* collect the RESET interrupt */
XX-   fdc_out(FDC_SENSE);		/* probe FDC to make it return status */
XX-   fdc_results(&floppy[0]);	/* flush controller using scratch structure */
XX-   for (i=0; i<NR_DRIVES; i++)	/* Clear each drive. */
XX- 	floppy[i].fl_calibration = UNCALIBRATED;
XX  
XX    /* Tell FDC drive parameters. */
XX    fdc_out(FDC_SPECIFY);		/* specify some timing parameters */
XX    fdc_out(current_spec1=spec1[d]); /* step-rate and head-unload-time */
XX--- 750,762 ----
XX    out_byte(DOR, ENABLE_INT);	/* strobe it high again */
XX    unlock();
XX    receive(HARDWARE, &mess);	/* collect the RESET interrupt */
XX  
XX+   for (i=0; i<NR_DRIVES; i++) {
XX+ 	fdc_out(FDC_SENSE);	 /* probe FDC to make it return status */
XX+ 	fdc_results(&floppy[i]); /* flush controller using each floppy [i]*/
XX+ 	floppy[i].fl_calibration = UNCALIBRATED; /* Clear each drive. */
XX+   }
XX+ 
XX    /* Tell FDC drive parameters. */
XX    fdc_out(FDC_SPECIFY);		/* specify some timing parameters */
XX    fdc_out(current_spec1=spec1[d]); /* step-rate and head-unload-time */
XX***************
XX*** 789,802 ****
XX   *===========================================================================*/
XX  PRIVATE void clock_mess(ticks, func)
XX  int ticks;			/* how many clock ticks to wait */
XX! void (*func)();			/* function to call upon time out */
XX  {
XX  /* Send the clock task a message. */
XX  
XX    mess.m_type = SET_ALARM;
XX    mess.CLOCK_PROC_NR = FLOPPY;
XX    mess.DELTA_TICKS = (long) ticks;
XX!   mess.FUNC_TO_CALL = func;
XX    sendrec(CLOCK, &mess);
XX  }
XX  
XX--- 769,782 ----
XX   *===========================================================================*/
XX  PRIVATE void clock_mess(ticks, func)
XX  int ticks;			/* how many clock ticks to wait */
XX! watchdog_t func;		/* function to call upon time out */
XX  {
XX  /* Send the clock task a message. */
XX  
XX    mess.m_type = SET_ALARM;
XX    mess.CLOCK_PROC_NR = FLOPPY;
XX    mess.DELTA_TICKS = (long) ticks;
XX!   mess.FUNC_TO_CALL = (sighandler_t) func;
XX    sendrec(CLOCK, &mess);
XX  }
XX  
XX***************
XX*** 855,864 ****
XX     * efficiency if these are wrong after a disk change.
XX     */
XX    fp = &floppy[(m_ptr->DEVICE & ~(DEV_TYPE_BITS|FORMAT_DEV_BIT)) % NR_DRIVES];
XX    nsector = nr_sectors[fp->fl_density];
XX    read_id(fp);			/* should reorganize and seek() before this */
XX    fp->fl_sector = fp->fl_results[5];	/* last sector accessed */
XX- 
XX    for (base = 0; base < nr_requests; base = limit) {
XX  
XX  	/* Handle all requests on the same cylinder as the base request. */
XX--- 835,844 ----
XX     * efficiency if these are wrong after a disk change.
XX     */
XX    fp = &floppy[(m_ptr->DEVICE & ~(DEV_TYPE_BITS|FORMAT_DEV_BIT)) % NR_DRIVES];
XX+ 
XX    nsector = nr_sectors[fp->fl_density];
XX    read_id(fp);			/* should reorganize and seek() before this */
XX    fp->fl_sector = fp->fl_results[5];	/* last sector accessed */
XX    for (base = 0; base < nr_requests; base = limit) {
XX  
XX  	/* Handle all requests on the same cylinder as the base request. */
XX***************
XX*** 870,876 ****
XX  	     ++limit) {
XX  		block = iovec[limit].io_position / SECTOR_SIZE;
XX  		if (cylinder != (int) (block / (NR_HEADS * nsector))) break;
XX! 		dist = base_sector + (int) (block % nsector) - fp->fl_sector;
XX  		if (dist < 0) dist += nsector;
XX  		if (dist > 0 && dist < mindist) {
XX  			/* Closer.  Ignore dist == 0 which is furthest! */
XX--- 850,856 ----
XX  	     ++limit) {
XX  		block = iovec[limit].io_position / SECTOR_SIZE;
XX  		if (cylinder != (int) (block / (NR_HEADS * nsector))) break;
XX! 		dist = BASE_SECTOR + (int) (block % nsector) - fp->fl_sector;
XX  		if (dist < 0) dist += nsector;
XX  		if (dist > 0 && dist < mindist) {
XX  			/* Closer.  Ignore dist == 0 which is furthest! */
XX***************
XX*** 898,907 ****
XX  	 * gives enough time.
XX  	 */
XX  	fp->fl_sector += BLOCK_SIZE / SECTOR_SIZE;
XX! 	while (fp->fl_sector >= nsector + base_sector)
XX  		fp->fl_sector -= nsector;
XX! 	if (fp->fl_sector == base_sector)
XX! 		fp->fl_sector = base_sector + nsector - 1;
XX    }
XX  
XX    /* Return most results in caller's i/o vector. */
XX--- 878,887 ----
XX  	 * gives enough time.
XX  	 */
XX  	fp->fl_sector += BLOCK_SIZE / SECTOR_SIZE;
XX! 	while (fp->fl_sector >= nsector + BASE_SECTOR)
XX  		fp->fl_sector -= nsector;
XX! 	if (fp->fl_sector == BASE_SECTOR)
XX! 		fp->fl_sector = BASE_SECTOR + nsector - 1;
XX    }
XX  
XX    /* Return most results in caller's i/o vector. */
XX***************
XX*** 988,991 ****
XX--- 968,1070 ----
XX    if (fp->fl_results[ST1] | fp->fl_results[ST2]) return(ERR_READ_ID);
XX  
XX    return(OK);
XX+ }
XX+ 
XX+ 
XX+ /*==========================================================================*
XX+  *				init					    *
XX+  *==========================================================================*/
XX+ PRIVATE void init()
XX+ {
XX+ /* Initialize the density and class field of the floppy structure. */
XX+ 
XX+   register struct floppy *fp;
XX+ 
XX+   for (fp = &floppy[0]; fp < &floppy[NR_DRIVES]; fp++) {
XX+ 	fp->fl_density = -1;
XX+ 	fp->fl_class= ~0;
XX+   }
XX+ }
XX+ 
XX+ /*==========================================================================*
XX+  *				do_open					    *
XX+  *==========================================================================*/
XX+ PRIVATE int do_open(m_ptr)
XX+ message *m_ptr;			/* pointer to open message */
XX+ {
XX+ /* Handle an open on a floppy.  Determine diskette type if need be. */
XX+ 
XX+   int dtype, drive;
XX+   register struct floppy *fp;
XX+   register struct test_order *tp;
XX+ 
XX+   /* Decode the message parameters. */
XX+   drive = m_ptr->DEVICE & ~(DEV_TYPE_BITS | FORMAT_DEV_BIT);
XX+   if (drive < 0 || drive >= NR_DRIVES) return(EIO);
XX+   fp = &floppy[drive];
XX+   fp->fl_drive = drive;
XX+   fp->fl_curcyl = -1;		/* force a seek to cylinder 0 or 2 later */
XX+ 
XX+   dtype = m_ptr->DEVICE & DEV_TYPE_BITS;	/* get density from minor dev */
XX+   if (dtype != 0) {
XX+ 	/* All types except 0 indicate a specific drive/medium combination.*/
XX+ 	dtype = (dtype >> DEV_TYPE_SHIFT) - 1;
XX+ 	if (dtype >= NT) return(EIO);
XX+ 	fp->fl_density = dtype;
XX+ 	return(OK);
XX+   }
XX+ 
XX+   /* The device opened is /dev/fdx.  Experimentally determine drive/medium.
XX+    * First check fl_density.  If it is > 0, the drive has been used before and
XX+    * the value of fl_density tells what was found last time. Try that first.
XX+    */
XX+   if (fp->fl_density >= 0 && test_read(fp, fp->fl_density) == OK) return(OK);
XX+ 
XX+   /* Either drive type is unknown or a different diskette is now present.
XX+    * Use test_order to try them one by one.
XX+    */
XX+   for (tp = &test_order[0]; tp < &test_order[NT-1]; tp++) {
XX+ 
XX+   	/* Skip densities that have been proven to be impossible */
XX+ 	if (!(fp->fl_class & (1 << tp->t_density))) continue;
XX+ 
XX+ 	if (test_read(fp, tp->t_density) == OK) {
XX+ 		/* The test succeeded, use this knowledge to limit the
XX+ 		 * drive class to match the density just read.
XX+ 		 */
XX+ 		fp->fl_class &= tp->t_class;
XX+ 		return(OK);
XX+ 	}
XX+   }
XX+ 
XX+   return(EIO);			/* nothing worked */
XX+ }
XX+ 
XX+ 
XX+ /*==========================================================================*
XX+  *				test_read				    *
XX+  *==========================================================================*/
XX+ PRIVATE int test_read(fp, density)
XX+ struct floppy *fp;
XX+ int density;
XX+ {
XX+ /* Try to read the highest numbered sector on cylinder 2.  Not all floppy
XX+  * types have as many sectors per track, and trying cylinder 2 finds the
XX+  * ones that need double stepping.
XX+  */
XX+ 
XX+   message m;
XX+   static char tbuf[TEST_BYTES] = { 1 };
XX+   int r;
XX+ 
XX+   if (density < 0) return(EIO);	/* theoretically cannot happen */
XX+   fp->fl_density = density;
XX+   m.m_type = DEV_READ;
XX+   m.DEVICE = ( (density + 1) << DEV_TYPE_SHIFT) + fp->fl_drive;
XX+   m.PROC_NR = FLOPPY;
XX+   m.COUNT = TEST_BYTES;
XX+   m.POSITION = (long) test_sector[density] * SECTOR_SIZE;
XX+   m.ADDRESS = &tbuf[0];
XX+   r = do_rdwt(&m, 0);
XX+   return(r == TEST_BYTES ? OK : r);
XX  }
X/
Xecho x - glo.h.d
Xsed '/^X/s///' > glo.h.d << '/'
XX*** /home/top/ast/minix/1.5/kernel/glo.h  crc=30419   2905	Sat Apr 21 22:26:23 1990
XX--- /home/top/ast/minix/1.6.25/kernel/glo.h  crc=07476   3369	Tue Dec 15 23:59:22 1992
XX***************
XX*** 21,30 ****
XX  /* Signals. */
XX  EXTERN int sig_procs;		/* number of procs with p_pending != 0 */
XX  
XX  /* Miscellaneous. */
XX  extern u16_t sizes[8];		/* table filled in by build */
XX! extern struct tasktab tasktab[];	/* see table.c */
XX! extern char t_stack[];		/* see table.c */
XX  
XX  #if (CHIP == INTEL)
XX  
XX--- 21,36 ----
XX  /* Signals. */
XX  EXTERN int sig_procs;		/* number of procs with p_pending != 0 */
XX  
XX+ /* Memory sizes. */
XX+ EXTERN phys_clicks mem_base[NR_MEMS];	/* bases of chunks of memory */
XX+ EXTERN phys_clicks mem_size[NR_MEMS];	/* sizes of chunks of memory */
XX+ EXTERN unsigned char mem_type[NR_MEMS];	/* types of chunks of memory */
XX+ 
XX  /* Miscellaneous. */
XX+ EXTERN int rebooting;		/* nonzero while rebooting */
XX  extern u16_t sizes[8];		/* table filled in by build */
XX! extern struct tasktab tasktab[];/* initialized in table.c, so extern here */
XX! extern char t_stack[];		/* initialized in table.c, so extern here */
XX  
XX  #if (CHIP == INTEL)
XX  
XX***************
XX*** 32,70 ****
XX  EXTERN int pc_at;		/* PC-AT compatible hardware interface */
XX  EXTERN int ps;			/* PS/2 */
XX  EXTERN int ps_mca;		/* PS/2 with Micro Channel */
XX! EXTERN int port_65;		/* saved contents of Planar Control Register */
XX! EXTERN unsigned processor;	/* 86, 186, 286, 386, ... */
XX  EXTERN int protected_mode;	/* nonzero if running in Intel protected mode*/
XX- extern int using_bios;		/* nonzero to force real mode (for bios_wini)*/
XX  
XX  /* Video cards and keyboard types. */
XX  EXTERN int color;		/* nonzero if console is color, 0 if mono */
XX! EXTERN int ega;			/* nonzero if console is EGA */
XX  EXTERN int scan_code;		/* scan code of key pressed to start minix */
XX  EXTERN int snow;		/* nonzero if screen needs snow removal */
XX  
XX  /* Memory sizes. */
XX  EXTERN unsigned ext_memsize;	/* initialized by assembler startup code */
XX  EXTERN unsigned low_memsize;
XX- EXTERN phys_clicks mem_base[NR_MEMS];	/* bases of chunks of memory */
XX- EXTERN phys_clicks mem_size[NR_MEMS];	/* sizes of chunks of memory */
XX- EXTERN unsigned char mem_type[NR_MEMS];	/* types of chunks of memory */
XX  
XX  /* Miscellaneous. */
XX  EXTERN u16_t Ax, Bx, Cx, Dx, Es;	/* to hold registers for BIOS calls */
XX- EXTERN struct farptr_s break_vector;	/* debugger breakpoint hook */
XX- EXTERN int db_enabled;		/* nonzero if external debugger is enabled */
XX- EXTERN int db_exists;		/* nonzero if external debugger exists */
XX- extern struct segdesc_s gdt[];	/* global descriptor table for protected mode*/
XX- EXTERN struct farptr_s sstep_vector;	/* debugger single-step hook */
XX  EXTERN u16_t vec_table[VECTOR_BYTES / sizeof(u16_t)]; /* copy of BIOS vectors*/
XX  
XX  #endif /* (CHIP == INTEL) */
XX  
XX  #if (CHIP == M68000)
XX! EXTERN int flush_flag;		/* tells clock when to flush the tty buf */
XX! extern unsigned char font8[];	/* 8 pixel wide font table */
XX! extern unsigned char font16[];	/* 16 pixel wide font table */
XX  extern int keypad;		/* Flag for keypad mode */
XX  extern int app_mode;		/* Flag for arrow key application mode */
XX  #endif
XX--- 38,80 ----
XX  EXTERN int pc_at;		/* PC-AT compatible hardware interface */
XX  EXTERN int ps;			/* PS/2 */
XX  EXTERN int ps_mca;		/* PS/2 with Micro Channel */
XX! EXTERN unsigned int processor;	/* 86, 186, 286, 386, ... */
XX  EXTERN int protected_mode;	/* nonzero if running in Intel protected mode*/
XX  
XX+ /* Debugger control. */
XX+ EXTERN struct farptr_s break_vector;	/* debugger breakpoint hook */
XX+ EXTERN int db_enabled;		/* nonzero if external debugger is enabled */
XX+ EXTERN int db_exists;		/* nonzero if external debugger exists */
XX+ EXTERN struct farptr_s sstep_vector;	/* debugger single-step hook */
XX+ 
XX  /* Video cards and keyboard types. */
XX  EXTERN int color;		/* nonzero if console is color, 0 if mono */
XX! EXTERN int ega;			/* nonzero if console is supports EGA */
XX! EXTERN int vga;			/* nonzero if console is supports VGA */
XX  EXTERN int scan_code;		/* scan code of key pressed to start minix */
XX  EXTERN int snow;		/* nonzero if screen needs snow removal */
XX  
XX  /* Memory sizes. */
XX  EXTERN unsigned ext_memsize;	/* initialized by assembler startup code */
XX  EXTERN unsigned low_memsize;
XX  
XX  /* Miscellaneous. */
XX  EXTERN u16_t Ax, Bx, Cx, Dx, Es;	/* to hold registers for BIOS calls */
XX  EXTERN u16_t vec_table[VECTOR_BYTES / sizeof(u16_t)]; /* copy of BIOS vectors*/
XX  
XX+ /* Variables that are initialized elsewhere are just extern here. */
XX+ extern int using_bios;		/* nonzero to force real mode (for bios_wini)*/
XX+ extern struct segdesc_s gdt[];	/* global descriptor table for protected mode*/
XX+ 
XX  #endif /* (CHIP == INTEL) */
XX  
XX  #if (CHIP == M68000)
XX! /* Variables that are initialized elsewhere are just extern here. */
XX  extern int keypad;		/* Flag for keypad mode */
XX  extern int app_mode;		/* Flag for arrow key application mode */
XX+ extern int STdebKey;		/* nonzero if ctl-alt-Fx detected */
XX+ extern struct tty_struct *cur_cons; /* virtual cons currently displayed */
XX+ extern unsigned char font8[];	/* 8 pixel wide font table (initialized) */
XX+ extern unsigned char font12[];	/* 12 pixel wide font table (initialized) */
XX+ extern unsigned char font16[];	/* 16 pixel wide font table (initialized) */
XX  #endif
X/
Xecho x - i8259.c.d
Xsed '/^X/s///' > i8259.c.d << '/'
XX*** /home/top/ast/minix/1.5/kernel/i8259.c  crc=41616   2189	Sat Apr 21 22:26:23 1990
XX--- /home/top/ast/minix/1.6.25/kernel/i8259.c  crc=03345   2769	Tue Nov  3 21:20:49 1992
XX***************
XX*** 2,7 ****
XX--- 2,8 ----
XX   *	enable_irq:	enable an interrupt line.  The cim...() functions in
XX   *			klib88 are specialized versions of this
XX   *	init_8259:	initialize the 8259(s), since the BIOS does it poorly
XX+  *	soon_reboot:	prepare to reboot the system
XX   */
XX  
XX  #include "kernel.h"
XX***************
XX*** 59,62 ****
XX--- 60,79 ----
XX  	out_byte(INT_CTLMASK, ICW4_PC);
XX    }
XX    out_byte(INT_CTLMASK, ~0);
XX+ }
XX+ 
XX+ 
XX+ /*==========================================================================*
XX+  *				soon_reboot				    *
XX+  *==========================================================================*/
XX+ PUBLIC void soon_reboot()
XX+ {
XX+ /* Prepare to reboot the system.  This mainly stops all interrupts.  lock()
XX+  * is not enough since functions may call unlock() (e.g. panic calls printf
XX+  * which calls set_6845 which calls unlock).  Set the 'rebooting' flag to
XX+  * show that the system is unreliable.
XX+  */
XX+ 
XX+   out_byte(INT_CTLMASK, ~0);
XX+   rebooting = TRUE;
XX  }
X/
Xecho x - kernel.h.d
Xsed '/^X/s///' > kernel.h.d << '/'
XX*** /home/top/ast/minix/1.5/kernel/kernel.h  crc=49326    643	Sat Apr 21 22:26:23 1990
XX--- /home/top/ast/minix/1.6.25/kernel/kernel.h  crc=41561    826	Tue Nov  3 21:20:50 1992
XX***************
XX*** 5,16 ****
XX  #define _MINIX             1	/* tell headers to include MINIX stuff */
XX  #define _SYSTEM            1	/* tell headers that this is the kernel */
XX  
XX  /* The following are so basic, all the *.c files get them automatically. */
XX  #include <minix/config.h>	/* MUST be first */
XX  #include <minix/const.h>
XX  #include <minix/type.h>
XX  
XX- #include <sys/types.h>
XX  #include <limits.h>
XX  #include <errno.h>
XX  
XX--- 5,22 ----
XX  #define _MINIX             1	/* tell headers to include MINIX stuff */
XX  #define _SYSTEM            1	/* tell headers that this is the kernel */
XX  
XX+ /* The ANSI C namespace pollution rules forbid the use of sendrec etc. */
XX+ #define send _send
XX+ #define receive _receive
XX+ #define sendrec _sendrec
XX+ 
XX  /* The following are so basic, all the *.c files get them automatically. */
XX  #include <minix/config.h>	/* MUST be first */
XX+ #include <ansi.h>		/* MUST be second */
XX+ #include <sys/types.h>
XX  #include <minix/const.h>
XX  #include <minix/type.h>
XX  
XX  #include <limits.h>
XX  #include <errno.h>
XX  
XX***************
XX*** 18,21 ****
XX  #include "type.h"
XX  #include "proto.h"
XX  #include "glo.h"
XX- 
XX--- 24,26 ----
X/
Xecho x - keyboard.c.d
Xsed '/^X/s///' > keyboard.c.d << '/'
XX*** /home/top/ast/minix/1.5/kernel/keyboard.c  crc=36166  23181	Sat Apr 21 22:26:23 1990
XX--- /home/top/ast/minix/1.6.25/kernel/keyboard.c  crc=54069  23806	Tue Nov  3 21:20:50 1992
XX***************
XX*** 1,3 ****
XX--- 1,4 ----
XX+ int logit = 0; /*DEBUG*/
XX  /* Keyboard driver for PC's and AT's. */
XX  
XX  #include "kernel.h"
XX***************
XX*** 18,24 ****
XX  #define KB_STATUS	0x64	/* I/O port for status on AT */
XX  
XX  /* PS/2 model 30 keyboard. */
XX! #define PS_KB_STATUS	0x72	/* I/O port for status on ps/2 (???) */
XX  #define PS_KEYBD	0x68	/* I/O port for data on ps/2 */
XX  
XX  /* AT and PS/2 model 30 keyboards. */
XX--- 19,25 ----
XX  #define KB_STATUS	0x64	/* I/O port for status on AT */
XX  
XX  /* PS/2 model 30 keyboard. */
XX! #define PS_KB_STATUS	0x72	/* I/O port for status on ps/2 (?) */
XX  #define PS_KEYBD	0x68	/* I/O port for data on ps/2 */
XX  
XX  /* AT and PS/2 model 30 keyboards. */
XX***************
XX*** 40,45 ****
XX--- 41,48 ----
XX  #define F3		  61
XX  #define F4		  62
XX  #define F5		  63
XX+ #define F6		  64
XX+ #define F7		  65
XX  #define F8		  66
XX  #define F9		  67
XX  #define F10		  68
XX***************
XX*** 61,66 ****
XX--- 64,71 ----
XX  #define US_EXT		   4	/* U.S. extended keyboard */
XX  
XX  /* Miscellaneous. */
XX+ #define CTRL              29	/* scan code for CTRL */
XX+ #define CAPSLOCK          58	/* scan code for Caps lock */
XX  #define CTRL_S		  31	/* scan code for letter S (for CRTL-S) */
XX  #define CONSOLE		   0	/* line number for console */
XX  #define MEMCHECK_ADR   0x472	/* address to stop memory check after reboot */
XX***************
XX*** 199,211 ****
XX  
XX  PRIVATE struct kb_s kb_lines[NR_CONS];
XX  
XX! FORWARD int kb_ack();
XX! FORWARD int kb_wait();
XX! FORWARD void load_dutch_table();
XX! FORWARD void load_olivetti();
XX! FORWARD void load_us_ext();
XX! FORWARD int scan_keyboard();
XX! FORWARD void set_leds();
XX  
XX  /*===========================================================================*
XX   *				keyboard				     *
XX--- 204,218 ----
XX  
XX  PRIVATE struct kb_s kb_lines[NR_CONS];
XX  
XX! FORWARD _PROTOTYPE( int kb_ack, (int data_port) );
XX! FORWARD _PROTOTYPE( int kb_wait, (int status_port) );
XX! FORWARD _PROTOTYPE( void load_dutch_table, (void) );
XX! FORWARD _PROTOTYPE( void load_olivetti, (void) );
XX! FORWARD _PROTOTYPE( void load_us_ext, (void) );
XX! FORWARD _PROTOTYPE( int scan_keyboard, (void) );
XX! FORWARD _PROTOTYPE( void set_leds, (void) );
XX! FORWARD _PROTOTYPE( void reboot, (void) );
XX! FORWARD _PROTOTYPE( void waitkey, (char *prompt) );
XX  
XX  /*===========================================================================*
XX   *				keyboard				     *
XX***************
XX*** 340,345 ****
XX--- 347,362 ----
XX    c = ch & 0177;		/* high-order bit set on key release */
XX    make = (ch & 0200 ? 0 : 1);	/* 1 when key depressed, 0 when key released */
XX  
XX+   /* Until IBM invented the 101-key keyboard, the CTRL key was always to the
XX+    * left of the 'A'.  This fix puts it back there on the 101-key keyboard.
XX+    */
XX+ #if KEYBOARD_84
XX+   if (c == CTRL) 
XX+ 	c = CAPSLOCK;
XX+   else if (c == CAPSLOCK)
XX+ 	c = CTRL;
XX+ #endif
XX+ 
XX    if (alt && keyb_type == DUTCH_EXT)
XX  	code = alt_c[c];
XX    else
XX***************
XX*** 368,397 ****
XX    switch(code - 0200) {
XX      case 0:	shift1 = make;		break;	/* shift key on left */
XX      case 1:	shift2 = make;		break;	/* shift key on right */
XX!     case 2:
XX! #if KEYBOARD_84
XX! /* Until IBM invented the 101-key keyboard, the CTRL key was always to the
XX!  * left of the 'A'.  This fix puts it back there on the 101-key keyboard.
XX!  */
XX! 		if (make && caps_off) {
XX! 			capslock = 1 - capslock;
XX! 			set_leds();
XX! 		}
XX! 		caps_off = 1 - make;    break;	/* caps lock */
XX! #else
XX! 		control = make;		break;	/* control */
XX! #endif
XX      case 3:	alt = make;		break;	/* alt key */
XX!     case 4:	
XX! #if KEYBOARD_84
XX! 		control = make;		break;	/* control */
XX! #else
XX! 		if (make && caps_off) {
XX  			capslock = 1 - capslock;
XX  			set_leds();
XX  		}
XX  		caps_off = 1 - make;    break;	/* caps lock */
XX! #endif
XX      case 5:	if (make && num_off) {
XX  			numlock  = 1 - numlock;
XX  			set_leds();
XX--- 385,399 ----
XX    switch(code - 0200) {
XX      case 0:	shift1 = make;		break;	/* shift key on left */
XX      case 1:	shift2 = make;		break;	/* shift key on right */
XX!     case 2:	control = make;		break;	/* control */
XX      case 3:	alt = make;		break;	/* alt key */
XX! 
XX!     case 4:	if (make && caps_off) {
XX  			capslock = 1 - capslock;
XX  			set_leds();
XX  		}
XX  		caps_off = 1 - make;    break;	/* caps lock */
XX! 
XX      case 5:	if (make && num_off) {
XX  			numlock  = 1 - numlock;
XX  			set_leds();
XX***************
XX*** 571,583 ****
XX    if (ch == F2) map_dmp();	/* print memory map */
XX    if (ch == F3) toggle_scroll();	/* hardware vs. software scrolling */
XX  
XX! #if AM_KERNEL
XX! #if !NONET
XX!   if (ch == F4) net_init();	/* Re-initialise the ethernet card */
XX  #endif
XX!   if (ch == F5) amdump();	/* Dump Amoeba statistics. */
XX! #endif /* AM_KERNEL */
XX! 
XX    if (ch == F8 && control) sigchar(&tty_struct[CONSOLE], SIGINT);
XX    if (ch == F9 && control) sigchar(&tty_struct[CONSOLE], SIGKILL);
XX    return(TRUE);
XX--- 573,583 ----
XX    if (ch == F2) map_dmp();	/* print memory map */
XX    if (ch == F3) toggle_scroll();	/* hardware vs. software scrolling */
XX  
XX! #if NETWORKING_ENABLED
XX!   if (ch == F5) ehw_dump();
XX  #endif
XX! if(ch == F6) logit = 1 - logit; /*DEBUG*/
XX!   if (ch == F7 && control) sigchar(&tty_struct[CONSOLE], SIGQUIT);
XX    if (ch == F8 && control) sigchar(&tty_struct[CONSOLE], SIGINT);
XX    if (ch == F9 && control) sigchar(&tty_struct[CONSOLE], SIGKILL);
XX    return(TRUE);
XX***************
XX*** 616,629 ****
XX  /*==========================================================================*
XX   *				reboot					    *
XX   *==========================================================================*/
XX! PUBLIC void reboot()
XX  {
XX  /* Reboot the machine. */
XX  
XX    static u16_t magic = MEMCHECK_MAG;
XX  
XX!   lock();
XX!   eth_stp();			/* stop ethernet (may be unnecessary) */
XX  
XX    /* Stop BIOS memory test. */
XX    phys_copy(numap(TTY, (vir_bytes) &magic, sizeof magic),
XX--- 616,628 ----
XX  /*==========================================================================*
XX   *				reboot					    *
XX   *==========================================================================*/
XX! PRIVATE void reboot()
XX  {
XX  /* Reboot the machine. */
XX  
XX    static u16_t magic = MEMCHECK_MAG;
XX  
XX!   soon_reboot();
XX  
XX    /* Stop BIOS memory test. */
XX    phys_copy(numap(TTY, (vir_bytes) &magic, sizeof magic),
XX***************
XX*** 641,647 ****
XX  		 * is more of a problem if the fake A20 is in use, as it
XX  		 * would be if the keyboard reset were used for real mode.
XX  		 */
XX! 		kb_wait();
XX  		out_byte(KB_COMMAND,
XX  			 KB_PULSE_OUTPUT | (0x0F & ~(KB_GATE_A20 | KB_RESET)));
XX  	} else {
XX--- 640,646 ----
XX  		 * is more of a problem if the fake A20 is in use, as it
XX  		 * would be if the keyboard reset were used for real mode.
XX  		 */
XX! 		kb_wait(ps ? PS_KB_STATUS : KB_STATUS);
XX  		out_byte(KB_COMMAND,
XX  			 KB_PULSE_OUTPUT | (0x0F & ~(KB_GATE_A20 | KB_RESET)));
XX  	} else {
XX***************
XX*** 657,679 ****
XX  
XX  
XX  /*==========================================================================*
XX!  *				wreboot					    *
XX   *==========================================================================*/
XX! PUBLIC void wreboot()
XX  {
XX! /* Wait for a keystroke, then reboot the machine.  Don't rely on interrupt
XX!  * to provide the keystroke, since this is usually called after a crash,
XX!  * and possibly before interrupts are initialized.
XX   */
XX  
XX!   register int scancode;
XX  
XX-   lock();
XX    milli_delay(1000);		/* pause for a second to ignore key release */
XX    scan_keyboard();		/* ack any old input */
XX!   printf("Type any key to reboot\r\n");
XX    scancode = scan_keyboard();	/* quiescent value (0 on PC, last code on AT)*/
XX    while(scan_keyboard() == scancode)
XX  	;			/* loop until new keypress or any release */
XX    reboot();
XX  }
XX--- 656,693 ----
XX  
XX  
XX  /*==========================================================================*
XX!  *				waitkey					    *
XX   *==========================================================================*/
XX! PRIVATE void waitkey(prompt)
XX! char *prompt;
XX  {
XX! /* Wait for a keystroke.  Use polling, since this is only called after
XX!  * interrupts have been disabled.
XX   */
XX  
XX!   int scancode;
XX  
XX    milli_delay(1000);		/* pause for a second to ignore key release */
XX    scan_keyboard();		/* ack any old input */
XX!   printf(prompt);
XX    scancode = scan_keyboard();	/* quiescent value (0 on PC, last code on AT)*/
XX    while(scan_keyboard() == scancode)
XX  	;			/* loop until new keypress or any release */
XX+ }
XX+ 
XX+ 
XX+ /*==========================================================================*
XX+  *				wreboot					    *
XX+  *==========================================================================*/
XX+ PUBLIC void wreboot()
XX+ {
XX+ /* Wait for keystrokes before printing debugging info and rebooting. */
XX+ 
XX+   soon_reboot();
XX+   waitkey("Type any key to view process table\r\n");
XX+   p_dmp();
XX+   waitkey("Type any key to view memory map\r\n");
XX+   map_dmp();
XX+   waitkey("Type any key to reboot\r\n");
XX    reboot();
XX  }
X/
Xecho x - main.c.d
Xsed '/^X/s///' > main.c.d << '/'
XX*** /home/top/ast/minix/1.5/kernel/main.c  crc=57482   8623	Sat Apr 21 22:26:23 1990
XX--- /home/top/ast/minix/1.6.25/kernel/main.c  crc=27287   8491	Thu Dec 17 00:54:30 1992
XX***************
XX*** 2,8 ****
XX   * initializes the system and starts the ball rolling by setting up the proc
XX   * table, interrupt vectors, and scheduling each task to run to initialize
XX   * itself.
XX!  * 
XX   * The entries into this file are:
XX   *   main:		MINIX main program
XX   *   panic:		abort MINIX due to a fatal error
XX--- 2,8 ----
XX   * initializes the system and starts the ball rolling by setting up the proc
XX   * table, interrupt vectors, and scheduling each task to run to initialize
XX   * itself.
XX!  *
XX   * The entries into this file are:
XX   *   main:		MINIX main program
XX   *   panic:		abort MINIX due to a fatal error
XX***************
XX*** 18,26 ****
XX  #define CMASK4          0x9E	/* mask for Planar Control Register */
XX  #define HIGH_INT          17	/* limit of the interrupt vectors */
XX  
XX! FORWARD void set_vec();
XX  #if !INTEL_32BITS
XX! PRIVATE void (*int_vec[HIGH_INT])() = {
XX    int00, int01, int02, int03, int04, int05, int06, int07,
XX    int08, int09, int10, int11, int12, int13, int14, int15,
XX    int16,
XX--- 18,30 ----
XX  #define CMASK4          0x9E	/* mask for Planar Control Register */
XX  #define HIGH_INT          17	/* limit of the interrupt vectors */
XX  
XX! typedef _PROTOTYPE( void (*vecaddr_t), (void) );
XX! 
XX! FORWARD _PROTOTYPE( void set_vec, (int vec_nr, vecaddr_t addr,
XX! 		phys_clicks base_click) );
XX! 
XX  #if !INTEL_32BITS
XX! PRIVATE vecaddr_t int_vec[HIGH_INT] = {
XX    int00, int01, int02, int03, int04, int05, int06, int07,
XX    int08, int09, int10, int11, int12, int13, int14, int15,
XX    int16,
XX***************
XX*** 28,34 ****
XX  #endif
XX  
XX  /*===========================================================================*
XX!  *                                   main                                    * 
XX   *===========================================================================*/
XX  PUBLIC void main()
XX  {
XX--- 32,38 ----
XX  #endif
XX  
XX  /*===========================================================================*
XX!  *                                   main                                    *
XX   *===========================================================================*/
XX  PUBLIC void main()
XX  {
XX***************
XX*** 52,59 ****
XX    /* Call the stage 2 assembler hooks to finish machine/mode-specific inits.
XX     * The 2 stages are needed to handle modes switches, especially 16->32 bits.
XX     */
XX!   mpx_2hook(); 
XX!   klib_2hook(); 
XX  
XX    /* Clear the process table.
XX     * Set up mappings for proc_addr() and proc_number() macros.
XX--- 56,63 ----
XX    /* Call the stage 2 assembler hooks to finish machine/mode-specific inits.
XX     * The 2 stages are needed to handle modes switches, especially 16->32 bits.
XX     */
XX!   mpx_2hook();
XX!   klib_2hook();
XX  
XX    /* Clear the process table.
XX     * Set up mappings for proc_addr() and proc_number() macros.
XX***************
XX*** 61,67 ****
XX    for (rp = BEG_PROC_ADDR, t = -NR_TASKS; rp < END_PROC_ADDR; ++rp, ++t) {
XX  	rp->p_flags = P_SLOT_FREE;
XX  	rp->p_nr = t;		/* proc number from ptr */
XX! 	(pproc_addr + NR_TASKS)[t] = rp;	/* proc ptr from number */
XX    }
XX  
XX  #if (CHIP == INTEL)
XX--- 65,71 ----
XX    for (rp = BEG_PROC_ADDR, t = -NR_TASKS; rp < END_PROC_ADDR; ++rp, ++t) {
XX  	rp->p_flags = P_SLOT_FREE;
XX  	rp->p_nr = t;		/* proc number from ptr */
XX!         (pproc_addr + NR_TASKS)[t] = rp;        /* proc ptr from number */
XX    }
XX  
XX  #if (CHIP == INTEL)
XX***************
XX*** 88,94 ****
XX  
XX    for (rp = BEG_PROC_ADDR, t = -NR_TASKS; rp <= BEG_USER_ADDR; ++rp, ++t) {
XX  	if (t < 0) {
XX! 		stack_size = tasktab[t+NR_TASKS].stksize;
XX  		rp->p_splimit = ktsb + SAFETY;
XX  		ktsb += stack_size;
XX  		rp->p_reg.sp = ktsb;
XX--- 92,98 ----
XX  
XX    for (rp = BEG_PROC_ADDR, t = -NR_TASKS; rp <= BEG_USER_ADDR; ++rp, ++t) {
XX  	if (t < 0) {
XX! 		stack_size = tasktab[t + NR_TASKS].stksize;
XX  		rp->p_splimit = ktsb + SAFETY;
XX  		ktsb += stack_size;
XX  		rp->p_reg.sp = ktsb;
XX***************
XX*** 123,129 ****
XX    mem_init();
XX  
XX    /* Save the old interrupt vectors. */
XX!   phys_b = umap(cproc_addr(HARDWARE), D, (vir_bytes) vec_table, VECTOR_BYTES);
XX    phys_copy(0L, phys_b, (long) VECTOR_BYTES);	/* save all the vectors */
XX  
XX  #if !INTEL_32BITS
XX--- 127,133 ----
XX    mem_init();
XX  
XX    /* Save the old interrupt vectors. */
XX!   phys_b = umap(proc_addr(HARDWARE), D, (vir_bytes) vec_table, VECTOR_BYTES);
XX    phys_copy(0L, phys_b, (long) VECTOR_BYTES);	/* save all the vectors */
XX  
XX  #if !INTEL_32BITS
XX***************
XX*** 146,156 ****
XX    set_vec(RS232_VECTOR, rs232_int, base_click);
XX    set_vec(FLOPPY_VECTOR, disk_int, base_click);
XX    set_vec(PRINTER_VECTOR, lpr_int, base_click);
XX! #if AM_KERNEL
XX! #if !NONET
XX!   set_vec(ETHER_VECTOR, eth_int, base_click);	/* overwrites RS232 port 2 */
XX  #endif
XX! #endif
XX    if (pc_at) {
XX  	set_vec(AT_WINI_VECTOR, wini_int, base_click);
XX    } else
XX--- 150,161 ----
XX    set_vec(RS232_VECTOR, rs232_int, base_click);
XX    set_vec(FLOPPY_VECTOR, disk_int, base_click);
XX    set_vec(PRINTER_VECTOR, lpr_int, base_click);
XX! 
XX! #if NETWORKING_ENABLED
XX!   /* Overwrite RS232 SECONDARY_VECTOR. */
XX!   set_vec(ETHER_VECTOR, eth_int, code_base);
XX  #endif
XX! 
XX    if (pc_at) {
XX  	set_vec(AT_WINI_VECTOR, wini_int, base_click);
XX    } else
XX***************
XX*** 159,168 ****
XX  	set_vec(PS_KEYB_VECTOR, tty_int, base_click);
XX  #endif /* !INTEL_32BITS */
XX  
XX!   /* Put a ptr to proc table in a known place so it can be found in /dev/mem */
XX!   set_vec( (code_base - 4)/4, (void (*)()) proc, (phys_clicks) 0);
XX!   
XX!   bill_ptr = cproc_addr(IDLE);  /* it has to point somewhere */
XX    lock_pick_proc();
XX  
XX    /* Finish initializing 8259 (needs machine type). */
XX--- 164,178 ----
XX  	set_vec(PS_KEYB_VECTOR, tty_int, base_click);
XX  #endif /* !INTEL_32BITS */
XX  
XX!   /* Put a ptr to proc table in a known place so it can be found in /dev/mem.
XX!    * This is crufty, and fails if the address of the proc table is >= 64K
XX!    * (we should write a phys_bytes number, not a u16_t from half a vector!.
XX!    * However, we need similar hooks for the debugger.  0x600 used to be
XX!    * code_base - the code base is no longer fixed.
XX!    */
XX!   set_vec( (0x600 - 4)/4, (vecaddr_t) proc, (phys_bytes) 0);
XX! 
XX!   bill_ptr = proc_addr(IDLE);  /* it has to point somewhere */
XX    lock_pick_proc();
XX  
XX    /* Finish initializing 8259 (needs machine type). */
XX***************
XX*** 176,185 ****
XX    /* Set planar control registers on PS's.  Fix this.  CMASK4 is magic and
XX     * probably ought to be set by the individual drivers.
XX     */
XX!   if (ps) {
XX! 	port_65 = in_byte(PCR);		/* save Planar Control Register */
XX! 	out_byte(PCR, CMASK4);		/* set Planar Control Register */
XX!   }
XX  
XX    /* Now go to the assembly code to start running the current process. */
XX    restart();
XX--- 186,192 ----
XX    /* Set planar control registers on PS's.  Fix this.  CMASK4 is magic and
XX     * probably ought to be set by the individual drivers.
XX     */
XX!   if (ps) out_byte(PCR, CMASK4);
XX  
XX    /* Now go to the assembly code to start running the current process. */
XX    restart();
XX***************
XX*** 187,206 ****
XX  
XX  
XX  /*===========================================================================*
XX!  *                                   panic                                   * 
XX   *===========================================================================*/
XX  PUBLIC void panic(s,n)
XX! char *s;
XX! int n; 
XX  {
XX  /* The system has run aground of a fatal error.  Terminate execution.
XX   * If the panic originated in MM or FS, the string will be empty and the
XX   * file system already syncked.  If the panic originates in the kernel, we are
XX!  * kind of stuck. 
XX   */
XX  
XX    if (*s != 0) {
XX! 	printf("\r\nKernel panic: %s",s); 
XX  	if (n != NO_NUM) printf(" %d", n);
XX  	printf("\r\n");
XX    }
XX--- 194,214 ----
XX  
XX  
XX  /*===========================================================================*
XX!  *                                   panic                                   *
XX   *===========================================================================*/
XX  PUBLIC void panic(s,n)
XX! _CONST char *s;
XX! int n;
XX  {
XX  /* The system has run aground of a fatal error.  Terminate execution.
XX   * If the panic originated in MM or FS, the string will be empty and the
XX   * file system already syncked.  If the panic originates in the kernel, we are
XX!  * kind of stuck.
XX   */
XX  
XX+   soon_reboot();		/* so printf doesn't try to use sys services */
XX    if (*s != 0) {
XX! 	printf("\r\nKernel panic: %s",s);
XX  	if (n != NO_NUM) printf(" %d", n);
XX  	printf("\r\n");
XX    }
XX***************
XX*** 213,223 ****
XX  
XX  #if (CHIP == INTEL)
XX  /*===========================================================================*
XX!  *                                   set_vec                                 * 
XX   *===========================================================================*/
XX  PRIVATE void set_vec(vec_nr, addr, base_click)
XX  int vec_nr;			/* which vector */
XX! void (*addr)();			/* where to start */
XX  phys_clicks base_click;		/* click where kernel sits in memory */
XX  {
XX  /* Set up an interrupt vector. */
XX--- 221,231 ----
XX  
XX  #if (CHIP == INTEL)
XX  /*===========================================================================*
XX!  *                                   set_vec                                 *
XX   *===========================================================================*/
XX  PRIVATE void set_vec(vec_nr, addr, base_click)
XX  int vec_nr;			/* which vector */
XX! vecaddr_t addr;			/* where to start */
XX  phys_clicks base_click;		/* click where kernel sits in memory */
XX  {
XX  /* Set up an interrupt vector. */
XX***************
XX*** 226,247 ****
XX    phys_bytes phys_b;
XX  
XX    /* Build the vector in the array 'vec'. */
XX!   vec[0] = (unsigned) addr;
XX!   vec[1] = (unsigned) click_to_hclick(base_click);
XX  
XX    /* Copy the vector into place. */
XX!   phys_b = umap(cproc_addr(HARDWARE), D, (vir_bytes) vec, 4);
XX!   phys_copy(phys_b, (phys_bytes) vec_nr*4, (phys_bytes) 4);
XX  }
XX- #endif
XX- 
XX- /*===========================================================================*
XX-  *                                   networking                              * 
XX-  *===========================================================================*/
XX- #if !AM_KERNEL
XX- /* These routines are dummies.  They are only needed when networking is
XX-  * disabled.  They are called in mpx88.s and klib88.s.
XX-  */
XX- PUBLIC void eth_stp() {}		/* stop the ethernet upon reboot */
XX- PUBLIC void dp8390_int(){}		/* Ethernet interrupt */
XX  #endif
XX--- 234,244 ----
XX    phys_bytes phys_b;
XX  
XX    /* Build the vector in the array 'vec'. */
XX!   vec[0] = (u16_t) addr;
XX!   vec[1] = (u16_t) click_to_hclick(base_click);
XX  
XX    /* Copy the vector into place. */
XX!   phys_b = umap(proc_addr(HARDWARE), D, (vir_bytes) vec, (vir_bytes) 4);
XX!   phys_copy(phys_b, (phys_bytes) (vec_nr * 4), (phys_bytes) 4);
XX  }
XX  #endif
X/
Xecho x - memory.c.d
Xsed '/^X/s///' > memory.c.d << '/'
XX*** /home/top/ast/minix/1.5/kernel/memory.c  crc=19537   5598	Sat Apr 21 22:26:23 1990
XX--- /home/top/ast/minix/1.6.25/kernel/memory.c  crc=18837   5989	Tue Nov  3 21:20:54 1992
XX***************
XX*** 9,20 ****
XX   *
XX   *    m_type      DEVICE    PROC_NR     COUNT    POSITION  ADRRESS
XX   * ----------------------------------------------------------------
XX!  * |  DISK_READ | device  | proc nr |  bytes  |  offset | buf ptr |
XX   * |------------+---------+---------+---------+---------+---------|
XX!  * | DISK_WRITE | device  | proc nr |  bytes  |  offset | buf ptr |
XX   * |------------+---------+---------+---------+---------+---------|
XX!  * | DISK_IOCTL | device  |         |  blocks | ram org |         |
XX!  * ----------------------------------------------------------------
XX   * |SCATTERED_IO| device  | proc nr | requests|         | iov ptr |
XX   * ----------------------------------------------------------------
XX   *  
XX--- 9,24 ----
XX   *
XX   *    m_type      DEVICE    PROC_NR     COUNT    POSITION  ADRRESS
XX   * ----------------------------------------------------------------
XX!  * |  DEV_OPEN  | device  | proc nr |         |         |         |
XX   * |------------+---------+---------+---------+---------+---------|
XX!  * |  DEV_CLOSE | device  | proc nr |         |         |         |
XX   * |------------+---------+---------+---------+---------+---------|
XX!  * |  DEV_READ  | device  | proc nr |  bytes  |  offset | buf ptr |
XX!  * |------------+---------+---------+---------+---------+---------|
XX!  * | DEV_WRITE  | device  | proc nr |  bytes  |  offset | buf ptr |
XX!  * |------------+---------+---------+---------+---------+---------|
XX!  * | DEV_IOCTL  | device  |         |  blocks | ram org |         |
XX!  * |------------+---------+---------+---------+---------+---------|
XX   * |SCATTERED_IO| device  | proc nr | requests|         | iov ptr |
XX   * ----------------------------------------------------------------
XX   *  
XX***************
XX*** 38,45 ****
XX  PRIVATE phys_bytes ram_origin[NR_RAMS];	/* origin of each RAM disk  */
XX  PRIVATE phys_bytes ram_limit[NR_RAMS];	/* limit of RAM disk per minor dev. */
XX  
XX! FORWARD int do_mem();
XX! FORWARD int do_setup();
XX  
XX  /*===========================================================================*
XX   *				mem_task				     * 
XX--- 42,49 ----
XX  PRIVATE phys_bytes ram_origin[NR_RAMS];	/* origin of each RAM disk  */
XX  PRIVATE phys_bytes ram_limit[NR_RAMS];	/* limit of RAM disk per minor dev. */
XX  
XX! FORWARD _PROTOTYPE( int do_mem, (message *m_ptr) );
XX! FORWARD _PROTOTYPE( int do_setup, (message *m_ptr) );
XX  
XX  /*===========================================================================*
XX   *				mem_task				     * 
XX***************
XX*** 81,90 ****
XX  
XX  	/* Now carry out the work.  It depends on the opcode. */
XX  	switch(mess.m_type) {
XX! 	    case DISK_READ:	r = do_mem(&mess);	break;
XX! 	    case DISK_WRITE:	r = do_mem(&mess);	break;
XX  	    case SCATTERED_IO:	r = do_vrdwt(&mess, do_mem); break;
XX! 	    case DISK_IOCTL:	r = do_setup(&mess);	break;
XX  	    default:		r = EINVAL;		break;
XX  	}
XX  
XX--- 85,96 ----
XX  
XX  	/* Now carry out the work.  It depends on the opcode. */
XX  	switch(mess.m_type) {
XX! 	    case DEV_OPEN:	r = OK;			break;
XX! 	    case DEV_CLOSE:	r = OK;			break;
XX! 	    case DEV_READ:	r = do_mem(&mess);	break;
XX! 	    case DEV_WRITE:	r = do_mem(&mess);	break;
XX  	    case SCATTERED_IO:	r = do_vrdwt(&mess, do_mem); break;
XX! 	    case DEV_IOCTL:	r = do_setup(&mess);	break;
XX  	    default:		r = EINVAL;		break;
XX  	}
XX  
XX***************
XX*** 105,124 ****
XX  {
XX  /* Read or write /dev/null, /dev/mem, /dev/kmem, /dev/ram or /dev/port. */
XX  
XX!   int device, count, endport, port, portval;
XX    phys_bytes mem_phys, user_phys;
XX  
XX    /* Get minor device number and check for /dev/null. */
XX    device = m_ptr->DEVICE;
XX    if (device < 0 || device >= NR_RAMS) return(ENXIO);	/* bad minor device */
XX!   if (device==NULL_DEV) return(m_ptr->m_type == DISK_READ ? 0 : m_ptr->COUNT);
XX  
XX    /* Set up 'mem_phys' for /dev/mem, /dev/kmem, or /dev/ram. */
XX-   if (m_ptr->POSITION < 0) return(ENXIO);
XX    mem_phys = ram_origin[device] + m_ptr->POSITION;
XX    if (mem_phys >= ram_limit[device]) return(0);
XX    count = m_ptr->COUNT;
XX!   if(mem_phys + count > ram_limit[device]) count = ram_limit[device] - mem_phys;
XX  
XX    /* Determine address where data is to go or to come from. */
XX    user_phys = numap(m_ptr->PROC_NR, (vir_bytes) m_ptr->ADDRESS,
XX--- 111,132 ----
XX  {
XX  /* Read or write /dev/null, /dev/mem, /dev/kmem, /dev/ram or /dev/port. */
XX  
XX!   int device, count;
XX! #if (CHIP == INTEL)
XX!   int endport, port, portval;
XX! #endif
XX    phys_bytes mem_phys, user_phys;
XX  
XX    /* Get minor device number and check for /dev/null. */
XX    device = m_ptr->DEVICE;
XX    if (device < 0 || device >= NR_RAMS) return(ENXIO);	/* bad minor device */
XX!   if (device==NULL_DEV) return(m_ptr->m_type == DEV_READ ? 0 : m_ptr->COUNT);
XX  
XX    /* Set up 'mem_phys' for /dev/mem, /dev/kmem, or /dev/ram. */
XX    mem_phys = ram_origin[device] + m_ptr->POSITION;
XX    if (mem_phys >= ram_limit[device]) return(0);
XX    count = m_ptr->COUNT;
XX!   if (mem_phys + count > ram_limit[device]) count = ram_limit[device]-mem_phys;
XX  
XX    /* Determine address where data is to go or to come from. */
XX    user_phys = numap(m_ptr->PROC_NR, (vir_bytes) m_ptr->ADDRESS,
XX***************
XX*** 131,137 ****
XX  	port = mem_phys;
XX  	mem_phys = umap(proc_ptr, D, (vir_bytes) &portval, (vir_bytes) 1);
XX  	for (endport = port + count; port != endport; ++port) {
XX! 		if (m_ptr->m_type == DISK_READ) {
XX  			portval = in_byte(port);
XX  			phys_copy(mem_phys, user_phys++, (phys_bytes) 1);
XX  		} else {
XX--- 139,145 ----
XX  	port = mem_phys;
XX  	mem_phys = umap(proc_ptr, D, (vir_bytes) &portval, (vir_bytes) 1);
XX  	for (endport = port + count; port != endport; ++port) {
XX! 		if (m_ptr->m_type == DEV_READ) {
XX  			portval = in_byte(port);
XX  			phys_copy(mem_phys, user_phys++, (phys_bytes) 1);
XX  		} else {
XX***************
XX*** 144,150 ****
XX  #endif
XX  
XX    /* Copy the data. */
XX!   if (m_ptr->m_type == DISK_READ)
XX  	phys_copy(mem_phys, user_phys, (long) count);
XX    else
XX  	phys_copy(user_phys, mem_phys, (long) count);
XX--- 152,158 ----
XX  #endif
XX  
XX    /* Copy the data. */
XX!   if (m_ptr->m_type == DEV_READ)
XX  	phys_copy(mem_phys, user_phys, (long) count);
XX    else
XX  	phys_copy(user_phys, mem_phys, (long) count);
X/
Xecho x - misc.c.d
Xsed '/^X/s///' > misc.c.d << '/'
XX*** /home/top/ast/minix/1.5/kernel/misc.c  crc=37356   4371	Sat Apr 21 22:26:23 1990
XX--- /home/top/ast/minix/1.6.25/kernel/misc.c  crc=62964   4391	Tue Nov  3 21:20:54 1992
XX***************
XX*** 32,61 ****
XX   *	0x80: must be checked since BIOS doesn't and it may not be there.
XX   */
XX  
XX    /* Get the size of ordinary memory from the BIOS. */
XX    mem_size[0] = k_to_click(low_memsize);	/* 0 base and type */
XX  
XX- #if SPARE_VIDEO_MEMORY
XX-   /* Spare video memory.  Experimental, it's too slow for program memory
XX-    * except maybe on PC's, and belongs low in a memory hierarchy.
XX-    */
XX-   if (color) {
XX- 	mem_size[1] = MONO_SIZE >> CLICK_SHIFT;
XX- 	mem_base[1] = MONO_BASE >> CLICK_SHIFT;
XX-   } else {
XX- 	mem_size[1] = COLOR_SIZE >> CLICK_SHIFT;
XX- 	mem_base[1] = COLOR_BASE >> CLICK_SHIFT;
XX-   }
XX-   mem_type[1] = 0x80;
XX- #endif
XX- 
XX    if (pc_at) {
XX  	/* Get the size of extended memory from the BIOS.  This is special
XX  	 * except in protected mode, but protected mode is now normal.
XX  	 */
XX  	mem_size[2] = k_to_click(ext_memsize);
XX  	mem_base[2] = EM_BASE >> CLICK_SHIFT;
XX  
XX  	/* Shadow ROM memory. */
XX  	mem_size[3] = SHADOW_MAX >> CLICK_SHIFT;
XX  	mem_base[3] = SHADOW_BASE >> CLICK_SHIFT;
XX--- 32,59 ----
XX   *	0x80: must be checked since BIOS doesn't and it may not be there.
XX   */
XX  
XX+   long ext_clicks;
XX+   phys_clicks max_clicks;
XX+ 
XX    /* Get the size of ordinary memory from the BIOS. */
XX    mem_size[0] = k_to_click(low_memsize);	/* 0 base and type */
XX  
XX    if (pc_at) {
XX  	/* Get the size of extended memory from the BIOS.  This is special
XX  	 * except in protected mode, but protected mode is now normal.
XX+ 	 * If 16M is present (except on 386), reduce it to 16M so the size
XX+ 	 * in clicks fits in a short.
XX  	 */
XX+ 	ext_clicks = k_to_click((long) ext_memsize);	/* clicks as a long */
XX+ 	max_clicks = USHRT_MAX - (EM_BASE >> CLICK_SHIFT);
XX  	mem_size[2] = k_to_click(ext_memsize);
XX  	mem_base[2] = EM_BASE >> CLICK_SHIFT;
XX  
XX+ #if !INTEL_32BITS
XX+ 	/* You can't address more memory than you can count in clicks. */
XX+ 	if (ext_clicks > max_clicks) mem_size[2] = max_clicks;
XX+ #endif
XX+ 
XX  	/* Shadow ROM memory. */
XX  	mem_size[3] = SHADOW_MAX >> CLICK_SHIFT;
XX  	mem_base[3] = SHADOW_BASE >> CLICK_SHIFT;
XX***************
XX*** 75,81 ****
XX   *==========================================================================*/
XX  PUBLIC int do_vrdwt(m_ptr, do_rdwt)
XX  register message *m_ptr;	/* pointer to read or write message */
XX! int (*do_rdwt)();		/* pointer to function which does the work */
XX  {
XX  /* Fetch a vector of i/o requests.  Handle requests one at a time.  Return
XX   * status in the vector.
XX--- 73,79 ----
XX   *==========================================================================*/
XX  PUBLIC int do_vrdwt(m_ptr, do_rdwt)
XX  register message *m_ptr;	/* pointer to read or write message */
XX! rdwt_t do_rdwt;			/* pointer to function which does the work */
XX  {
XX  /* Fetch a vector of i/o requests.  Handle requests one at a time.  Return
XX   * status in the vector.
X/
Xecho x - printer.c.d
Xsed '/^X/s///' > printer.c.d << '/'
XX*** /home/top/ast/minix/1.5/kernel/printer.c  crc=03436  12647	Sat Apr 21 22:26:23 1990
XX--- /home/top/ast/minix/1.6.25/kernel/printer.c  crc=41903  12900	Tue Nov  3 21:20:56 1992
XX***************
XX*** 5,18 ****
XX   * The valid messages and their parameters are:
XX   *
XX   *   HARD_INT:     interrupt handler has finished current chunk of output
XX!  *   TTY_WRITE:    a process wants to write on a terminal
XX   *   CANCEL:       terminate a previous incomplete system call immediately
XX   *
XX   *    m_type      TTY_LINE   PROC_NR    COUNT    ADDRESS
XX   * -------------------------------------------------------
XX   * | HARD_INT    |         |         |         |         |
XX   * |-------------+---------+---------+---------+---------|
XX!  * | TTY_WRITE   |minor dev| proc nr |  count  | buf ptr |
XX   * |-------------+---------+---------+---------+---------|
XX   * | CANCEL      |minor dev| proc nr |         |         |
XX   * -------------------------------------------------------
XX--- 5,18 ----
XX   * The valid messages and their parameters are:
XX   *
XX   *   HARD_INT:     interrupt handler has finished current chunk of output
XX!  *   DEV_WRITE:    a process wants to write on a terminal
XX   *   CANCEL:       terminate a previous incomplete system call immediately
XX   *
XX   *    m_type      TTY_LINE   PROC_NR    COUNT    ADDRESS
XX   * -------------------------------------------------------
XX   * | HARD_INT    |         |         |         |         |
XX   * |-------------+---------+---------+---------+---------|
XX!  * | DEV_WRITE   |minor dev| proc nr |  count  | buf ptr |
XX   * |-------------+---------+---------+---------+---------|
XX   * | CANCEL      |minor dev| proc nr |         |         |
XX   * -------------------------------------------------------
XX***************
XX*** 87,99 ****
XX  PRIVATE phys_bytes user_phys;	/* physical address of remainder of user buf */
XX  PRIVATE int writing;		/* nonzero while write is in progress */
XX  
XX! FORWARD void do_cancel();
XX! FORWARD void do_done();
XX! FORWARD void do_write();
XX! FORWARD void pr_error();
XX! FORWARD void pr_start();
XX! FORWARD void print_init();
XX! FORWARD void reply();
XX  
XX  /*===========================================================================*
XX   *				printer_task				     *
XX--- 87,100 ----
XX  PRIVATE phys_bytes user_phys;	/* physical address of remainder of user buf */
XX  PRIVATE int writing;		/* nonzero while write is in progress */
XX  
XX! FORWARD _PROTOTYPE( void do_cancel, (message *m_ptr) );
XX! FORWARD _PROTOTYPE( void do_done, (void) );
XX! FORWARD _PROTOTYPE( void do_write, (message *m_ptr) );
XX! FORWARD _PROTOTYPE( void pr_error, (int status) );
XX! FORWARD _PROTOTYPE( void pr_start, (void) );
XX! FORWARD _PROTOTYPE( void print_init, (void) );
XX! FORWARD _PROTOTYPE( void reply, (int code, int replyee, int process,
XX! 		int status) );
XX  
XX  /*===========================================================================*
XX   *				printer_task				     *
XX***************
XX*** 109,115 ****
XX    while (TRUE) {
XX  	receive(ANY, &print_mess);
XX  	switch(print_mess.m_type) {
XX! 	    case TTY_WRITE:	do_write(&print_mess);	break;
XX  	    case CANCEL   :	do_cancel(&print_mess);	break;
XX  	    case HARD_INT :	do_done();		break;
XX  	    default:		reply(TASK_REPLY, print_mess.m_source,
XX--- 110,116 ----
XX    while (TRUE) {
XX  	receive(ANY, &print_mess);
XX  	switch(print_mess.m_type) {
XX! 	    case DEV_WRITE:	do_write(&print_mess);	break;
XX  	    case CANCEL   :	do_cancel(&print_mess);	break;
XX  	    case HARD_INT :	do_done();		break;
XX  	    default:		reply(TASK_REPLY, print_mess.m_source,
XX***************
XX*** 126,132 ****
XX  PRIVATE void do_write(m_ptr)
XX  register message *m_ptr;	/* pointer to the newly arrived message */
XX  {
XX! /* The printer is used by sending TTY_WRITE messages to it. Process one. */
XX  
XX    register int r;
XX  
XX--- 127,133 ----
XX  PRIVATE void do_write(m_ptr)
XX  register message *m_ptr;	/* pointer to the newly arrived message */
XX  {
XX! /* The printer is used by sending DEV_WRITE messages to it. Process one. */
XX  
XX    register int r;
XX  
XX***************
XX*** 252,259 ****
XX   * BIOS and initialize the printer.
XX   */
XX  
XX!   obuf_phys = umap(proc_ptr, D, obuf, sizeof obuf);
XX!   phys_copy(0x408L, umap(proc_ptr, D, &port_base, 2), 2L);
XX    out_byte(port_base + 2, INIT_PRINTER);
XX    milli_delay(2);		/* easily satisfies Centronics minimum */
XX    out_byte(port_base + 2, SELECT);
XX--- 253,260 ----
XX   * BIOS and initialize the printer.
XX   */
XX  
XX!   obuf_phys = umap(proc_ptr, D, (vir_bytes)obuf, (vir_bytes)sizeof obuf);
XX!   phys_copy(0x408L, umap(proc_ptr, D, (vir_bytes)&port_base, (vir_bytes)2),2L);
XX    out_byte(port_base + 2, INIT_PRINTER);
XX    milli_delay(2);		/* easily satisfies Centronics minimum */
XX    out_byte(port_base + 2, SELECT);
X/
Xecho x - proc.c.d
Xsed '/^X/s///' > proc.c.d << '/'
XX*** /home/top/ast/minix/1.5/kernel/proc.c  crc=54003  18512	Sat Apr 21 22:26:23 1990
XX--- /home/top/ast/minix/1.6.25/kernel/proc.c  crc=13065  20066	Tue Nov  3 21:20:57 1992
XX***************
XX*** 21,37 ****
XX  
XX  PRIVATE unsigned char switching;	/* nonzero to inhibit interrupt() */
XX  
XX! FORWARD int mini_send();
XX! FORWARD int mini_rec();
XX! FORWARD void pick_proc();
XX! FORWARD void ready();
XX! FORWARD void sched();
XX! FORWARD void unready();
XX  
XX  #if (CHIP == INTEL)
XX  #define CopyMess(s,sp,sm,dp,dm) \
XX! 	cp_mess(s,(sp)->p_map[D].mem_phys,sm,(dp)->p_map[D].mem_phys,dm)
XX  #endif
XX  #if (CHIP == M68000)
XX  #define CopyMess(s,sp,sm,dp,dm) \
XX  	cp_mess(s,sp,sm,dp,dm)
XX--- 21,45 ----
XX  
XX  PRIVATE unsigned char switching;	/* nonzero to inhibit interrupt() */
XX  
XX! FORWARD _PROTOTYPE( int mini_send, (struct proc *caller_ptr, int dest,
XX! 		message *m_ptr) );
XX! FORWARD _PROTOTYPE( int mini_rec, (struct proc *caller_ptr, int src,
XX! 		message *m_ptr) );
XX! FORWARD _PROTOTYPE( void ready, (struct proc *rp) );
XX! FORWARD _PROTOTYPE( void sched, (void) );
XX! FORWARD _PROTOTYPE( void unready, (struct proc *rp) );
XX! FORWARD _PROTOTYPE( void pick_proc, (void) );
XX  
XX+ #if (CHIP == M68000)
XX+ FORWARD _PROTOTYPE( void cp_mess, (int src, struct proc *src_p, message *src_m,
XX+ 		struct proc *dst_p, message *dst_m) );
XX+ #endif
XX+ 
XX  #if (CHIP == INTEL)
XX  #define CopyMess(s,sp,sm,dp,dm) \
XX! 	cp_mess(s, (sp)->p_map[D].mem_phys, (vir_bytes)sm, (dp)->p_map[D].mem_phys, (vir_bytes)dm)
XX  #endif
XX+ 
XX  #if (CHIP == M68000)
XX  #define CopyMess(s,sp,sm,dp,dm) \
XX  	cp_mess(s,sp,sm,dp,dm)
XX***************
XX*** 102,111 ****
XX    if (rdy_head[TASK_Q] != NIL_PROC)
XX  	rdy_tail[TASK_Q]->p_nextready = rp;
XX    else
XX! #if (CHIP != M68000)
XX! 	proc_ptr =
XX! #endif
XX! 	rdy_head[TASK_Q] = rp;
XX    rdy_tail[TASK_Q] = rp;
XX    rp->p_nextready = NIL_PROC;
XX  }
XX--- 110,116 ----
XX    if (rdy_head[TASK_Q] != NIL_PROC)
XX  	rdy_tail[TASK_Q]->p_nextready = rp;
XX    else
XX! 	proc_ptr = rdy_head[TASK_Q] = rp;
XX    rdy_tail[TASK_Q] = rp;
XX    rp->p_nextready = NIL_PROC;
XX  }
XX***************
XX*** 131,139 ****
XX    /* Check for bad system call parameters. */
XX    if (!isoksrc_dest(src_dest)) return(E_BAD_SRC);
XX    rp = proc_ptr;
XX-   if (function != BOTH && isuserp(rp))
XX- 	return(E_NO_PERM);	/* users only do BOTH */
XX  
XX    /* The parameters are ok. Do the call. */
XX    if (function & SEND) {
XX  	/* Function = SEND or BOTH. */
XX--- 136,144 ----
XX    /* Check for bad system call parameters. */
XX    if (!isoksrc_dest(src_dest)) return(E_BAD_SRC);
XX    rp = proc_ptr;
XX  
XX+   if (isuserp(rp) && function != BOTH) return(E_NO_PERM);
XX+   
XX    /* The parameters are ok. Do the call. */
XX    if (function & SEND) {
XX  	/* Function = SEND or BOTH. */
XX***************
XX*** 171,176 ****
XX--- 176,193 ----
XX    dest_ptr = proc_addr(dest);	/* pointer to destination's proc entry */
XX    if (dest_ptr->p_flags & P_SLOT_FREE) return(E_BAD_DEST);	/* dead dest */
XX  
XX+ #if ALLOW_GAP_MESSAGES
XX+   /* This check allows a message to be anywhere in data or stack or gap. 
XX+    * It will have to be made more elaborate later for machines which
XX+    * don't have the gap mapped.
XX+    */
XX+   vb = (vir_bytes) m_ptr;
XX+   vlo = vb >> CLICK_SHIFT;	/* vir click for bottom of message */
XX+   vhi = (vb + MESS_SIZE - 1) >> CLICK_SHIFT;	/* vir click for top of msg */
XX+   if (vlo < caller_ptr->p_map[D].mem_vir || vlo > vhi ||
XX+       vhi >= caller_ptr->p_map[S].mem_vir + caller_ptr->p_map[S].mem_len)
XX+         return(E_BAD_ADDR); 
XX+ #else
XX    /* Check for messages wrapping around top of memory or outside data seg. */
XX    vb = (vir_bytes) m_ptr;
XX    vlo = vb >> CLICK_SHIFT;	/* vir click for bottom of message */
XX***************
XX*** 178,190 ****
XX    if (vhi < vlo ||
XX        vhi - caller_ptr->p_map[D].mem_vir >= caller_ptr->p_map[D].mem_len)
XX  	return(E_BAD_ADDR);
XX  
XX    /* Check for deadlock by 'caller_ptr' and 'dest' sending to each other. */
XX    if (dest_ptr->p_flags & SENDING) {
XX! 	next_ptr = caller_ptr->p_callerq;
XX! 	while (next_ptr != NIL_PROC) {
XX! 		if (next_ptr == dest_ptr) return(ELOCKED);
XX! 		next_ptr = next_ptr->p_sendlink;
XX  	}
XX    }
XX  
XX--- 195,211 ----
XX    if (vhi < vlo ||
XX        vhi - caller_ptr->p_map[D].mem_vir >= caller_ptr->p_map[D].mem_len)
XX  	return(E_BAD_ADDR);
XX+ #endif
XX  
XX    /* Check for deadlock by 'caller_ptr' and 'dest' sending to each other. */
XX    if (dest_ptr->p_flags & SENDING) {
XX! 	next_ptr = proc_addr(dest_ptr->p_sendto);
XX! 	while (TRUE) {
XX! 		if (next_ptr == caller_ptr) return(ELOCKED);
XX! 		if (next_ptr->p_flags & SENDING)
XX! 			next_ptr = proc_addr(next_ptr->p_sendto);
XX! 		else
XX! 			break;
XX  	}
XX    }
XX  
XX***************
XX*** 202,207 ****
XX--- 223,229 ----
XX  	caller_ptr->p_messbuf = m_ptr;
XX  	if (caller_ptr->p_flags == 0) unready(caller_ptr);
XX  	caller_ptr->p_flags |= SENDING;
XX+ 	caller_ptr->p_sendto= dest;
XX  
XX  	/* Process is now blocked.  Put in on the destination's queue. */
XX  	if ( (next_ptr = dest_ptr->p_callerq) == NIL_PROC)
XX***************
XX*** 306,312 ****
XX    /* No one is ready.  Run the idle task.  The idle task might be made an
XX     * always-ready user task to avoid this special case.
XX     */
XX!   bill_ptr = proc_ptr = cproc_addr(IDLE);
XX  }
XX  
XX  
XX--- 328,334 ----
XX    /* No one is ready.  Run the idle task.  The idle task might be made an
XX     * always-ready user task to avoid this special case.
XX     */
XX!   bill_ptr = proc_ptr = proc_addr(IDLE);
XX  }
XX  
XX  
XX***************
XX*** 327,339 ****
XX  	if (rdy_head[TASK_Q] != NIL_PROC)
XX  		/* Add to tail of nonempty queue. */
XX  		rdy_tail[TASK_Q]->p_nextready = rp;
XX! 	else
XX! {
XX! #if (CHIP != M68000)
XX  		proc_ptr =		/* run fresh task next */
XX- #endif
XX  		rdy_head[TASK_Q] = rp;	/* add to empty queue */
XX! }
XX  	rdy_tail[TASK_Q] = rp;
XX  	rp->p_nextready = NIL_PROC;	/* new entry has no successor */
XX  	return;
XX--- 349,358 ----
XX  	if (rdy_head[TASK_Q] != NIL_PROC)
XX  		/* Add to tail of nonempty queue. */
XX  		rdy_tail[TASK_Q]->p_nextready = rp;
XX! 	else {
XX  		proc_ptr =		/* run fresh task next */
XX  		rdy_head[TASK_Q] = rp;	/* add to empty queue */
XX! 	}
XX  	rdy_tail[TASK_Q] = rp;
XX  	rp->p_nextready = NIL_PROC;	/* new entry has no successor */
XX  	return;
XX***************
XX*** 347,353 ****
XX  	rp->p_nextready = NIL_PROC;
XX  	return;
XX    }
XX! #if (CHIP == M68000)
XX    if (isshadowp(rp)) {		/* others are similar */
XX  	if (rdy_head[SHADOW_Q] != NIL_PROC)
XX  		rdy_tail[SHADOW_Q]->p_nextready = rp;
XX--- 366,372 ----
XX  	rp->p_nextready = NIL_PROC;
XX  	return;
XX    }
XX! #if (SHADOWING == 1)
XX    if (isshadowp(rp)) {		/* others are similar */
XX  	if (rdy_head[SHADOW_Q] != NIL_PROC)
XX  		rdy_tail[SHADOW_Q]->p_nextready = rp;
XX***************
XX*** 358,369 ****
XX--- 377,394 ----
XX  	return;
XX    }
XX  #endif
XX+   if (rdy_head[USER_Q] == NIL_PROC)
XX+ 	rdy_tail[USER_Q] = rp;
XX+   rp->p_nextready = rdy_head[USER_Q];
XX+   rdy_head[USER_Q] = rp;
XX+ /*
XX    if (rdy_head[USER_Q] != NIL_PROC)
XX  	rdy_tail[USER_Q]->p_nextready = rp;
XX    else
XX  	rdy_head[USER_Q] = rp;
XX    rdy_tail[USER_Q] = rp;
XX    rp->p_nextready = NIL_PROC;
XX+ */
XX  }
XX  
XX  
XX***************
XX*** 400,406 ****
XX  	}
XX  	qtail = &rdy_tail[SERVER_Q];
XX    } else
XX! #if (CHIP == M68000)
XX    if (isshadowp(rp)) {
XX  	if ( (xp = rdy_head[SHADOW_Q]) == NIL_PROC) return;
XX  	if (xp == rp) {
XX--- 425,431 ----
XX  	}
XX  	qtail = &rdy_tail[SERVER_Q];
XX    } else
XX! #if (SHADOWING == 1)
XX    if (isshadowp(rp)) {
XX  	if ( (xp = rdy_head[SHADOW_Q]) == NIL_PROC) return;
XX  	if (xp == rp) {
XX***************
XX*** 566,581 ****
XX  register struct proc *dst_p;	/* destination proc entry */
XX  message *dst_m;			/* destination buffer */
XX  {
XX!   register vir_clicks clk;
XX  
XX!   if (clk = src_p->p_shadow) {
XX! 	clk -= src_p->p_map[D].mem_phys;
XX! 	src_m = (message *)((char *)src_m + ((phys_bytes)clk << CLICK_SHIFT));
XX    }
XX!   if (clk = dst_p->p_shadow) {
XX! 	clk -= dst_p->p_map[D].mem_phys;
XX! 	dst_m = (message *)((char *)dst_m + ((phys_bytes)clk << CLICK_SHIFT));
XX    }
XX  #ifdef NEEDFSTRUCOPY
XX    phys_copy(src_m,dst_m,(phys_bytes) sizeof(message));
XX  #else
XX--- 591,616 ----
XX  register struct proc *dst_p;	/* destination proc entry */
XX  message *dst_m;			/* destination buffer */
XX  {
XX! #if (SHADOWING == 0)
XX!   /* convert virtual address to physical address */
XX!   /* The caller has already checked if all addresses are within bounds */
XX!   
XX!   src_m = (message *)((char *)src_m + (((phys_bytes)src_p->p_map[D].mem_phys
XX! 				- src_p->p_map[D].mem_vir) << CLICK_SHIFT));
XX!   dst_m = (message *)((char *)dst_m + (((phys_bytes)dst_p->p_map[D].mem_phys
XX! 				- dst_p->p_map[D].mem_vir) << CLICK_SHIFT));
XX! #else
XX!   register phys_bytes correction;
XX  
XX!   if (correction = src_p->p_shadow) {
XX! 	correction = (correction - src_p->p_map[D].mem_phys) << CLICK_SHIFT;
XX! 	src_m = (message *)((char *)src_m + correction);
XX    }
XX!   if (correction = dst_p->p_shadow) {
XX! 	correction = (correction - dst_p->p_map[D].mem_phys) << CLICK_SHIFT;
XX! 	dst_m = (message *)((char *)dst_m + correction);
XX    }
XX+ #endif
XX  #ifdef NEEDFSTRUCOPY
XX    phys_copy(src_m,dst_m,(phys_bytes) sizeof(message));
XX  #else
X/
Xecho x - proc.h.d
Xsed '/^X/s///' > proc.h.d << '/'
XX*** /home/top/ast/minix/1.5/kernel/proc.h  crc=46854   4266	Sat Apr 21 22:26:23 1990
XX--- /home/top/ast/minix/1.6.25/kernel/proc.h  crc=04345   4887	Mon Apr 19 20:59:46 1993
XX***************
XX*** 1,3 ****
XX--- 1,6 ----
XX+ #ifndef PROC_H
XX+ #define PROC_H
XX+ 
XX  /* Here is the declaration of the process table.  It contains the process'
XX   * registers, memory map, accounting, and message send/receive information.
XX   * Many assembly code routines reference fields in it.  The offsets to these
XX***************
XX*** 18,27 ****
XX  #if (CHIP == M68000)
XX    reg_t p_splow;		/* lowest observed stack value */
XX    int p_trap;			/* trap type (only low byte) */
XX    phys_clicks p_shadow;		/* set if shadowed process image */
XX    int p_nflips;			/* statistics */
XX    char p_physio;		/* cannot be (un)shadowed now if set */
XX! 				/* there will be a gap here!! ++jrb */
XX  #endif /* (CHIP == M68000) */
XX  
XX    int p_nr;			/* number of this process (for fast access) */
XX--- 21,38 ----
XX  #if (CHIP == M68000)
XX    reg_t p_splow;		/* lowest observed stack value */
XX    int p_trap;			/* trap type (only low byte) */
XX+ #if (SHADOWING == 0)
XX+   char *p_crp;			/* mmu table pointer (really struct _rpr *) */
XX+ #else
XX    phys_clicks p_shadow;		/* set if shadowed process image */
XX+   int align;			/* make the struct size a multiple of 4 */
XX+ #endif
XX    int p_nflips;			/* statistics */
XX    char p_physio;		/* cannot be (un)shadowed now if set */
XX! #if defined(FPP)
XX!   struct fsave p_fsave;		/* FPP state frame and registers */
XX!   int align2;			/* make the struct size a multiple of 4 */
XX! #endif
XX  #endif /* (CHIP == M68000) */
XX  
XX    int p_nr;			/* number of this process (for fast access) */
XX***************
XX*** 32,52 ****
XX  
XX    int p_flags;			/* P_SLOT_FREE, SENDING, RECEIVING, etc. */
XX    struct mem_map p_map[NR_SEGS];/* memory map */
XX!   int p_pid;			/* process id passed in from MM */
XX  
XX!   time_t user_time;		/* user time in ticks */
XX!   time_t sys_time;		/* sys time in ticks */
XX!   time_t child_utime;		/* cumulative user time of children */
XX!   time_t child_stime;		/* cumulative sys time of children */
XX!   time_t p_alarm;		/* time of next alarm in ticks, or 0 */
XX  
XX    struct proc *p_callerq;	/* head of list of procs wishing to send */
XX    struct proc *p_sendlink;	/* link to next proc wishing to send */
XX    message *p_messbuf;		/* pointer to message buffer */
XX    int p_getfrom;		/* from whom does process want to receive? */
XX  
XX    struct proc *p_nextready;	/* pointer to next ready process */
XX!   int p_pending;		/* bit map for pending signals 1-16 */
XX    unsigned p_pendcount;		/* count of pending and unfinished signals */
XX  };
XX  
XX--- 43,64 ----
XX  
XX    int p_flags;			/* P_SLOT_FREE, SENDING, RECEIVING, etc. */
XX    struct mem_map p_map[NR_SEGS];/* memory map */
XX!   pid_t p_pid;			/* process id passed in from MM */
XX  
XX!   clock_t user_time;		/* user time in ticks */
XX!   clock_t sys_time;		/* sys time in ticks */
XX!   clock_t child_utime;		/* cumulative user time of children */
XX!   clock_t child_stime;		/* cumulative sys time of children */
XX!   clock_t p_alarm;		/* time of next alarm in ticks, or 0 */
XX  
XX    struct proc *p_callerq;	/* head of list of procs wishing to send */
XX    struct proc *p_sendlink;	/* link to next proc wishing to send */
XX    message *p_messbuf;		/* pointer to message buffer */
XX    int p_getfrom;		/* from whom does process want to receive? */
XX+   int p_sendto;
XX  
XX    struct proc *p_nextready;	/* pointer to next ready process */
XX!   sigset_t p_pending;		/* bit map for pending signals */
XX    unsigned p_pendcount;		/* count of pending and unfinished signals */
XX  };
XX  
XX***************
XX*** 73,91 ****
XX  #define isoksusern(n)     ((unsigned) (n) < NR_PROCS)
XX  #define isokusern(n)      ((unsigned) ((n) - LOW_USER) < NR_PROCS - LOW_USER)
XX  #define isrxhardware(n)   ((n) == ANY || (n) == HARDWARE)
XX  #define isservn(n)        ((unsigned) (n) < LOW_USER)
XX! #define istaskp(p)        ((p) < END_TASK_ADDR && (p) != cproc_addr(IDLE))
XX  #define isuserp(p)        ((p) >= BEG_USER_ADDR)
XX  #define proc_addr(n)      (pproc_addr + NR_TASKS)[(n)]
XX- #define cproc_addr(n)     (&(proc + NR_TASKS)[(n)])
XX  #define proc_number(p)    ((p)->p_nr)
XX! #if (CHIP == M68000)
XX! #define isshadowp(p)      ((p)->p_shadow)
XX  #endif
XX  
XX  EXTERN struct proc proc[NR_TASKS + NR_PROCS];	/* process table */
XX  EXTERN struct proc *pproc_addr[NR_TASKS + NR_PROCS];
XX! 				/* ptrs to process table slots (fast) */
XX  EXTERN struct proc *bill_ptr;	/* ptr to process to bill for clock ticks */
XX  EXTERN struct proc *rdy_head[NQ];	/* pointers to ready list headers */
XX  EXTERN struct proc *rdy_tail[NQ];	/* pointers to ready list tails */
XX--- 85,110 ----
XX  #define isoksusern(n)     ((unsigned) (n) < NR_PROCS)
XX  #define isokusern(n)      ((unsigned) ((n) - LOW_USER) < NR_PROCS - LOW_USER)
XX  #define isrxhardware(n)   ((n) == ANY || (n) == HARDWARE)
XX+ #if 0
XX+ /* The old macro.  Why are servers other than MM and FS now not allowed? */
XX  #define isservn(n)        ((unsigned) (n) < LOW_USER)
XX! #endif
XX! #define isservn(n)        ((n) == FS_PROC_NR || (n) == MM_PROC_NR)
XX! #define istaskp(p)        ((p) < END_TASK_ADDR && (p) != proc_addr(IDLE))
XX  #define isuserp(p)        ((p) >= BEG_USER_ADDR)
XX  #define proc_addr(n)      (pproc_addr + NR_TASKS)[(n)]
XX  #define proc_number(p)    ((p)->p_nr)
XX! #if (SHADOWING == 1)
XX! #define isshadowp(p)      ((p)->p_shadow != 0)
XX  #endif
XX  
XX  EXTERN struct proc proc[NR_TASKS + NR_PROCS];	/* process table */
XX  EXTERN struct proc *pproc_addr[NR_TASKS + NR_PROCS];
XX! /* ptrs to process table slots; fast because now a process entry can be found
XX!    by indexing the pproc_addr array, while accessing an element i requires
XX!    a multiplication with sizeof(struct proc) to determine the address */
XX  EXTERN struct proc *bill_ptr;	/* ptr to process to bill for clock ticks */
XX  EXTERN struct proc *rdy_head[NQ];	/* pointers to ready list headers */
XX  EXTERN struct proc *rdy_tail[NQ];	/* pointers to ready list tails */
XX+ 
XX+ #endif /* PROC_H */
X/
Xecho x - protect.c.d
Xsed '/^X/s///' > protect.c.d << '/'
XX*** /home/top/ast/minix/1.5/kernel/protect.c  crc=08966   7777	Sat Apr 21 22:26:23 1990
XX--- /home/top/ast/minix/1.6.25/kernel/protect.c  crc=18643  10717	Tue Dec 15 23:59:24 1992
XX***************
XX*** 1,14 ****
XX! /* This file contains code for initialization of protected mode.
XX!  *
XX!  * The code must run in 16-bit mode (and be compiled with a 16-bit
XX!  * compiler!) even for a 32-bit kernel.
XX   */
XX  
XX  #include "kernel.h"
XX  #include "protect.h"
XX  
XX  #if INTEL_32BITS
XX- #include "protect1.c"		/* local 16-bit versions of some functions */
XX  #define INT_GATE_TYPE (INT_286_GATE | DESC_386_BIT)
XX  #define TSS_TYPE      (AVL_286_TSS  | DESC_386_BIT)
XX  #else
XX--- 1,13 ----
XX! /* This file contains code for initialization of protected mode, to initialize
XX!  * code and data segment descriptors, and to initialize global descriptors
XX!  * for local descriptors in the process table.
XX   */
XX  
XX  #include "kernel.h"
XX+ #include "proc.h"
XX  #include "protect.h"
XX  
XX  #if INTEL_32BITS
XX  #define INT_GATE_TYPE (INT_286_GATE | DESC_386_BIT)
XX  #define TSS_TYPE      (AVL_286_TSS  | DESC_386_BIT)
XX  #else
XX***************
XX*** 17,24 ****
XX  #endif
XX  
XX  struct desctableptr_s {
XX!   u16_t limit;
XX!   u32_t base;			/* really u24_t + pad for 286 */
XX  };
XX  
XX  struct gatedesc_s {
XX--- 16,23 ----
XX  #endif
XX  
XX  struct desctableptr_s {
XX!   char limit[sizeof(u16_t)];
XX!   char base[sizeof(u32_t)];		/* really u24_t + pad for 286 */
XX  };
XX  
XX  struct gatedesc_s {
XX***************
XX*** 74,80 ****
XX  PRIVATE struct gatedesc_s idt[IDT_SIZE];	/* zero-init so none present */
XX  PUBLIC struct tss_s tss;	/* zero init */
XX  
XX! FORWARD void int_gate();
XX  
XX  /*=========================================================================*
XX   *				int_gate				   *
XX--- 73,82 ----
XX  PRIVATE struct gatedesc_s idt[IDT_SIZE];	/* zero-init so none present */
XX  PUBLIC struct tss_s tss;	/* zero init */
XX  
XX! FORWARD _PROTOTYPE( void int_gate, (unsigned vec_nr, phys_bytes base,
XX! 		unsigned dpl_type) );
XX! FORWARD _PROTOTYPE( void sdesc, (struct segdesc_s *segdp, phys_bytes base,
XX! 		phys_bytes size) );
XX  
XX  /*=========================================================================*
XX   *				int_gate				   *
XX***************
XX*** 109,117 ****
XX    phys_bytes code_bytes;
XX    phys_bytes data_bytes;
XX    struct gate_table_s *gtp;
XX  
XX    static struct gate_table_s {
XX! 	void (*gate)();
XX  	unsigned char vec_nr;
XX  	unsigned char privilege;
XX    }
XX--- 111,120 ----
XX    phys_bytes code_bytes;
XX    phys_bytes data_bytes;
XX    struct gate_table_s *gtp;
XX+   struct desctableptr_s *dtp;
XX  
XX    static struct gate_table_s {
XX! 	_PROTOTYPE( void (*gate), (void) );
XX  	unsigned char vec_nr;
XX  	unsigned char privilege;
XX    }
XX***************
XX*** 137,147 ****
XX  	clock_int, CLOCK_VECTOR, INTR_PRIVILEGE,
XX  	tty_int, KEYBOARD_VECTOR, INTR_PRIVILEGE,
XX  	psecondary_int, SECONDARY_VECTOR, INTR_PRIVILEGE,
XX! #if AM_KERNEL
XX! #if !NONET 
XX  	eth_int, ETHER_VECTOR, INTR_PRIVILEGE,
XX  #endif
XX- #endif
XX  	prs232_int, RS232_VECTOR, INTR_PRIVILEGE,
XX  	disk_int, FLOPPY_VECTOR, INTR_PRIVILEGE,
XX  	lpr_int, PRINTER_VECTOR, INTR_PRIVILEGE,
XX--- 140,148 ----
XX  	clock_int, CLOCK_VECTOR, INTR_PRIVILEGE,
XX  	tty_int, KEYBOARD_VECTOR, INTR_PRIVILEGE,
XX  	psecondary_int, SECONDARY_VECTOR, INTR_PRIVILEGE,
XX! #if NETWORKING_ENABLED
XX  	eth_int, ETHER_VECTOR, INTR_PRIVILEGE,
XX  #endif
XX  	prs232_int, RS232_VECTOR, INTR_PRIVILEGE,
XX  	disk_int, FLOPPY_VECTOR, INTR_PRIVILEGE,
XX  	lpr_int, PRINTER_VECTOR, INTR_PRIVILEGE,
XX***************
XX*** 156,168 ****
XX  	code_bytes = (phys_bytes) sizes[0] << CLICK_SHIFT;
XX  
XX    /* Build temporary gdt and idt pointers in GDT where BIOS needs them. */
XX!   ((struct desctableptr_s *) &gdt[BIOS_GDT_INDEX])->limit = sizeof gdt - 1;
XX!   ((struct desctableptr_s *) &gdt[BIOS_GDT_INDEX])->base =
XX! 	data_base + (phys_bytes) (vir_bytes) gdt;
XX!   ((struct desctableptr_s *) &gdt[BIOS_IDT_INDEX])->limit = sizeof idt - 1;
XX!   ((struct desctableptr_s *) &gdt[BIOS_IDT_INDEX])->base =
XX! 	data_base + (phys_bytes) (vir_bytes) idt;
XX  
XX    /* Build segment descriptors for tasks and interrupt handlers. */
XX    init_dataseg(&gdt[DS_INDEX], data_base, data_bytes, INTR_PRIVILEGE);
XX    init_dataseg(&gdt[ES_INDEX], data_base, data_bytes, INTR_PRIVILEGE);
XX--- 157,170 ----
XX  	code_bytes = (phys_bytes) sizes[0] << CLICK_SHIFT;
XX  
XX    /* Build temporary gdt and idt pointers in GDT where BIOS needs them. */
XX!   dtp= (struct desctableptr_s *) &gdt[BIOS_GDT_INDEX];
XX!   * (u16_t *) dtp->limit = sizeof gdt - 1;
XX!   * (u32_t *) dtp->base = data_base + (phys_bytes) (vir_bytes) gdt;
XX  
XX+   dtp= (struct desctableptr_s *) &gdt[BIOS_IDT_INDEX];
XX+   * (u16_t *) dtp->limit = sizeof idt - 1;
XX+   * (u32_t *) dtp->base = data_base + (phys_bytes) (vir_bytes) idt;
XX+ 
XX    /* Build segment descriptors for tasks and interrupt handlers. */
XX    init_dataseg(&gdt[DS_INDEX], data_base, data_bytes, INTR_PRIVILEGE);
XX    init_dataseg(&gdt[ES_INDEX], data_base, data_bytes, INTR_PRIVILEGE);
XX***************
XX*** 189,201 ****
XX    init_dataseg(&gdt[MONO_INDEX], (phys_bytes) MONO_BASE,
XX  	       (phys_bytes) MONO_SIZE, TASK_PRIVILEGE);
XX  
XX- #if AM_KERNEL
XX- #if !NONET
XX  /* Build descriptor for Western Digital Etherplus card buffer. */
XX    init_dataseg(&gdt[EPLUS_INDEX], (phys_bytes) EPLUS_BASE,
XX  		(phys_bytes) EPLUS_SIZE, TASK_PRIVILEGE);
XX- #endif /* !NONET */
XX- #endif /* AM_KERNEL */
XX  
XX    /* Build main TSS.
XX     * This is used only to record the stack pointer to be used after an
XX--- 191,199 ----
XX***************
XX*** 241,244 ****
XX--- 239,327 ----
XX    /* Fix up debugger selectors, now the real-mode values are finished with. */
XX    break_vector.selector = DB_CS_SELECTOR;
XX    sstep_vector.selector = DB_CS_SELECTOR;
XX+ }
XX+ 
XX+ /*=========================================================================*
XX+  *				init_codeseg				   *
XX+  *=========================================================================*/
XX+ PUBLIC void init_codeseg(segdp, base, size, privilege)
XX+ register struct segdesc_s *segdp;
XX+ phys_bytes base;
XX+ phys_bytes size;
XX+ int privilege;
XX+ {
XX+ /* Build descriptor for a code segment. */
XX+ 
XX+   sdesc(segdp, base, size);
XX+   segdp->access = (privilege << DPL_SHIFT)
XX+ 	        | (PRESENT | SEGMENT | EXECUTABLE | READABLE);
XX+ 		/* CONFORMING = 0, ACCESSED = 0 */
XX+ }
XX+ 
XX+ /*=========================================================================*
XX+  *				init_dataseg				   *
XX+  *=========================================================================*/
XX+ PUBLIC void init_dataseg(segdp, base, size, privilege)
XX+ register struct segdesc_s *segdp;
XX+ phys_bytes base;
XX+ phys_bytes size;
XX+ int privilege;
XX+ {
XX+ /* Build descriptor for a data segment. */
XX+ 
XX+   sdesc(segdp, base, size);
XX+   segdp->access = (privilege << DPL_SHIFT) | (PRESENT | SEGMENT | WRITEABLE);
XX+ 		/* EXECUTABLE = 0, EXPAND_DOWN = 0, ACCESSED = 0 */
XX+ }
XX+ 
XX+ /*=========================================================================*
XX+  *				ldt_init				   *
XX+  *=========================================================================*/
XX+ PUBLIC void ldt_init()
XX+ {
XX+ /* Build local descriptors in GDT for LDT's in process table.
XX+  * The LDT's are allocated at compile time in the process table, and
XX+  * initialized whenever a process' map is initialized or changed.
XX+  */
XX+ 
XX+   unsigned ldt_selector;
XX+   register struct proc *rp;
XX+ 
XX+   for (rp = BEG_PROC_ADDR, ldt_selector = FIRST_LDT_INDEX * DESC_SIZE;
XX+        rp < END_PROC_ADDR; ++rp, ldt_selector += DESC_SIZE) {
XX+ 	init_dataseg(&gdt[ldt_selector / DESC_SIZE],
XX+ 		     data_base + (phys_bytes) (vir_bytes) rp->p_ldt,
XX+ 		     (phys_bytes) sizeof rp->p_ldt, INTR_PRIVILEGE);
XX+ 	gdt[ldt_selector / DESC_SIZE].access = PRESENT | LDT;
XX+ 	rp->p_ldt_sel = ldt_selector;
XX+   }
XX+ }
XX+ 
XX+ /*=========================================================================*
XX+  *				sdesc					   *
XX+  *=========================================================================*/
XX+ PRIVATE void sdesc(segdp, base, size)
XX+ register struct segdesc_s *segdp;
XX+ phys_bytes base;
XX+ phys_bytes size;
XX+ {
XX+ /* Fill in the size fields (base, limit and granularity) of a descriptor. */
XX+ 
XX+   segdp->base_low = base;
XX+   segdp->base_middle = base >> BASE_MIDDLE_SHIFT;
XX+ #if INTEL_32BITS
XX+   segdp->base_high = base >> BASE_HIGH_SHIFT;
XX+   --size;			/* convert to a limit, 0 size means 4G */
XX+   if (size > BYTE_GRAN_MAX) {
XX+ 	segdp->limit_low = size >> PAGE_GRAN_SHIFT;
XX+ 	segdp->granularity = GRANULAR | (size >>
XX+ 				     (PAGE_GRAN_SHIFT + GRANULARITY_SHIFT));
XX+   } else {
XX+ 	segdp->limit_low = size;
XX+ 	segdp->granularity = size >> GRANULARITY_SHIFT;
XX+   }
XX+   segdp->granularity |= DEFAULT;	/* means BIG for data seg */
XX+ #else
XX+   segdp->limit_low = size - 1;
XX+ #endif
XX  }
X/
Xecho x - protect.h.d
Xsed '/^X/s///' > protect.h.d << '/'
XX*** /home/top/ast/minix/1.5/kernel/protect.h  crc=50970   6349	Sat Apr 21 22:26:23 1990
XX--- /home/top/ast/minix/1.6.25/kernel/protect.h  crc=18834   6250	Tue Dec 15 23:59:25 1992
XX***************
XX*** 23,40 ****
XX  #define DB_CS16_INDEX   15	/* debugger 16-bit CS for 386 */
XX  #define DB_DS_INDEX     16	/* debugger DS */
XX  #define GDT_INDEX       17	/* GDT DS for debugger */
XX- #define FIRST_LDT_INDEX 18	/* rest of descriptors are LDT's */
XX- #if AM_KERNEL
XX- #if !NONET
XX- #undef FIRST_LDT_INDEX
XX  #define EPLUS_INDEX	18	/* Western Digital Etherplus buffer */
XX  #define FIRST_LDT_INDEX 19	/* rest of descriptors are LDT's */
XX- #endif /* NONET */
XX- #endif /* AM_KERNEL */
XX  
XX  #define BIOS_GDT_SELECTOR 0x08	/* (BIOS_GDT_INDEX * DESC_SIZE) bad for asld */
XX  #define BIOS_IDT_SELECTOR 0x10	/* (BIOS_IDT_INDEX * DESC_SIZE) */
XX  #define DS_SELECTOR       0x18	/* (DS_INDEX * DESC_SIZE) */
XX  #define CS_SELECTOR       0x30	/* (CS_INDEX * DESC_SIZE) */
XX  #define BIOS_CS_SELECTOR  0x38	/* (BIOS_CS_INDEX * DESC_SIZE) */
XX  #define TSS_SELECTOR      0x40	/* (TSS_INDEX * DESC_SIZE) */
XX--- 23,36 ----
XX  #define DB_CS16_INDEX   15	/* debugger 16-bit CS for 386 */
XX  #define DB_DS_INDEX     16	/* debugger DS */
XX  #define GDT_INDEX       17	/* GDT DS for debugger */
XX  #define EPLUS_INDEX	18	/* Western Digital Etherplus buffer */
XX  #define FIRST_LDT_INDEX 19	/* rest of descriptors are LDT's */
XX  
XX  #define BIOS_GDT_SELECTOR 0x08	/* (BIOS_GDT_INDEX * DESC_SIZE) bad for asld */
XX  #define BIOS_IDT_SELECTOR 0x10	/* (BIOS_IDT_INDEX * DESC_SIZE) */
XX  #define DS_SELECTOR       0x18	/* (DS_INDEX * DESC_SIZE) */
XX+ #define ES_SELECTOR       0x20	/* (ES_INDEX * DESC_SIZE) */
XX+ #define SS_SELECTOR       0x28	/* (SS_INDEX * DESC_SIZE) */
XX  #define CS_SELECTOR       0x30	/* (CS_INDEX * DESC_SIZE) */
XX  #define BIOS_CS_SELECTOR  0x38	/* (BIOS_CS_INDEX * DESC_SIZE) */
XX  #define TSS_SELECTOR      0x40	/* (TSS_INDEX * DESC_SIZE) */
XX***************
XX*** 47,57 ****
XX  #define DB_CS16_SELECTOR  0x78	/* (DB_CS16_INDEX * DESC_SIZE) */
XX  #define DB_DS_SELECTOR    0x80	/* (DB_DS_INDEX * DESC_SIZE) */
XX  #define GDT_SELECTOR      0x88	/* (GDT_INDEX * DESC_SIZE) */
XX! #if AM_KERNEL
XX! #if !NONET
XX  #define EPLUS_SELECTOR	  0x91	/* (EPLUS_INDEX * DESC_SIZE) */
XX- #endif /* AM_KERNEL */
XX- #endif /* NONET */
XX  
XX  /* Fixed local descriptors. */
XX  #define CS_LDT_INDEX     0	/* process CS */
XX--- 43,50 ----
XX  #define DB_CS16_SELECTOR  0x78	/* (DB_CS16_INDEX * DESC_SIZE) */
XX  #define DB_DS_SELECTOR    0x80	/* (DB_DS_INDEX * DESC_SIZE) */
XX  #define GDT_SELECTOR      0x88	/* (GDT_INDEX * DESC_SIZE) */
XX! 
XX  #define EPLUS_SELECTOR	  0x91	/* (EPLUS_INDEX * DESC_SIZE) */
XX  
XX  /* Fixed local descriptors. */
XX  #define CS_LDT_INDEX     0	/* process CS */
X/
Xecho x - proto.h.d
Xsed '/^X/s///' > proto.h.d << '/'
XX*** /home/top/ast/minix/1.5/kernel/proto.h  crc=32720   4897	Sat Apr 21 22:26:23 1990
XX--- /home/top/ast/minix/1.6.25/kernel/proto.h  crc=19269  13844	Mon Apr 19 20:59:47 1993
XX***************
XX*** 1,299 ****
XX  /* Function prototypes. */
XX  
XX! /* amoeba.c */
XX! void amint_task();
XX! void amoeba_task();
XX  
XX! /* at_wini.c, bios_wini.c, ps_wini.c, xt_wini.c, stwini.c */
XX! void winchester_task();
XX  
XX  /* clock.c */
XX! void clock_handler();
XX! void clock_task();
XX  
XX! /* dmp.c, stdmp.c */
XX! void map_dmp();
XX! void p_dmp();
XX! void set_name();
XX  
XX  /* floppy.c, stfloppy.c */
XX! void floppy_task();
XX  
XX  /* main.c, stmain.c */
XX! void main();
XX! void panic();
XX  
XX  /* memory.c */
XX! void mem_task();
XX  
XX  /* misc.c */
XX! int do_vrdwt();
XX  
XX  /* printer.c, stprint.c */
XX! void printer_task();
XX  
XX  /* proc.c */
XX! void interrupt();
XX! int lock_mini_send();
XX! void lock_pick_proc();
XX! void lock_ready();
XX! void lock_sched();
XX! void lock_unready();
XX! int sys_call();
XX! void unhold();
XX  
XX  /* system.c */
XX! void cause_sig();
XX! void inform();
XX! phys_bytes numap();
XX! void sys_task();
XX! phys_bytes umap();
XX  
XX  /* tty.c */
XX! void finish();
XX! void sigchar();
XX! void tty_task();
XX  
XX  /* library */
XX! int memcpy();
XX! void printk();
XX! int receive();
XX! int send();
XX! int sendrec();
XX  
XX  #if (CHIP == INTEL)
XX  
XX  /* clock.c */
XX! void milli_delay();
XX! unsigned read_counter();
XX  
XX  /* console.c */
XX! void console();
XX! void flush();
XX! void out_char();
XX! void putc();
XX! void scr_init();
XX! void toggle_scroll();
XX  
XX  /* cstart.c */
XX! void cstart();
XX  
XX  /* exception.c */
XX! void exception();
XX  
XX  /* i8259.c */
XX! void enable_irq();
XX! void init_8259();
XX  
XX  /* keyboard.c */
XX! int func_key();
XX! void kb_init();
XX! int kb_read();
XX! void keyboard();
XX! int letter_code();
XX! int make_break();
XX! void reboot();
XX! void wreboot();
XX  
XX  /* klib*.x */
XX! void bios13();
XX! void build_sig();
XX! phys_bytes check_mem();
XX! void cim_at_wini();
XX! void cim_floppy();
XX! void cim_printer();
XX! void cim_xt_wini();
XX! void cp_mess();
XX! unsigned in_byte();
XX! void klib_1hook();
XX! void klib_2hook();
XX! void lock();
XX! void mpx_1hook();
XX! void mpx_2hook();
XX! void out_byte();
XX! void phys_copy();
XX! void port_read();
XX! void port_write();
XX! void reset();
XX! void scr_down();
XX! void scr_up();
XX! void sim_printer();
XX! unsigned tasim_printer();
XX! int test_and_set();
XX! void unlock();
XX! void vid_copy();
XX! void wait_retrace();
XX  
XX- /* main.c */
XX- void dp8390_int();
XX- void eth_stp();
XX- 
XX  /* misc.c */
XX! void mem_init();
XX  
XX  /* mpx*.x */
XX! void idle_task();
XX! void restart();
XX! void int00(), divide_error();	/* exception handlers, in numerical order */
XX! void int01(), single_step_exception();
XX! void int02(), nmi();
XX! void int03(), breakpoint_exception();
XX! void int04(), overflow();
XX! void int05(), bounds_check();
XX! void int06(), inval_opcode();
XX! void int07(), copr_not_available();
XX! void int08(), double_fault();
XX! void int09(), copr_seg_overrun();
XX! void int10(), inval_tss();
XX! void int11(), segment_not_present();
XX! void int12(), stack_exception();
XX! void int13(), general_protection();
XX! void int14(), page_fault();
XX! void int15();
XX! void int16(), copr_error();	/* end of exception handlers */
XX! void clock_int();		/* hardware interrupt handlers, in order */
XX! void tty_int();
XX! void secondary_int(), psecondary_int(), eth_int();
XX! void rs232_int(), prs232_int();
XX! void disk_int();
XX! void lpr_int();
XX! void wini_int();		/* end of hardware interrupt handlers */
XX! void trp();			/* software interrupt handlers, in order */
XX! void s_call(), p_s_call();	/* end of software interrupt handlers */
XX  
XX  /* printer.c */
XX! void pr_char();
XX! void pr_restart();
XX  
XX  /* protect.c */
XX! void prot_init();
XX  
XX- /* protect1.c */
XX- void init_codeseg();
XX- void init_dataseg();
XX- void ldt_init();
XX- 
XX  /* rs232.c */
XX! void rs232_1handler();
XX! void rs232_2handler();
XX! void rs_inhibit();
XX! int rs_init();
XX! int rs_ioctl();
XX! int rs_read();
XX! void rs_istart();
XX! void rs_istop();
XX! void rs_ocancel();
XX! void rs_setc();
XX! void rs_write();
XX  
XX- /* start.x */
XX- void db();
XX- u16_t get_chrome();
XX- u16_t get_ega();
XX- u16_t get_ext_memsize();
XX- u16_t get_low_memsize();
XX- u16_t get_processor();
XX- u16_t get_word();
XX- void put_word();
XX- 
XX  /* system.c */
XX! void alloc_segments();
XX  
XX- /* tty.c */
XX- void tty_wakeup();
XX- 
XX  #endif /* (CHIP == INTEL) */
XX  
XX  #if (CHIP == M68000)
XX  
XX! /* stdmp.c */
XX! void prname();
XX! void reg_dmp();
XX! void mem_dmp();
XX! void tty_dmp();
XX  
XX  /* stfloppy.c */
XX! void fd_timer();
XX  
XX! /* main.c */
XX! void none();
XX! void rupt();
XX! void trap();
XX! void checksp();
XX! void aciaint();
XX! void fake_int();
XX! void timint();
XX! void mdiint();
XX! void iob();
XX! void idle_task();
XX  
XX- /* proc.c */
XX- void cp_mess();
XX- 
XX  /* rs232.c */
XX! void siaint();
XX! void rs232();
XX! void rs_flush();
XX! void rs_out_char();
XX! int tty_o_done();
XX! void rs_sig();
XX! void init_rs232();
XX! void set_uart();
XX  
XX  /* stcon.c */
XX! void tty_init();
XX! int func_key();
XX! void dump();
XX! void putc();
XX  
XX  /* stdma.c */
XX! void dmagrab();
XX! void dmafree();
XX! void dmaint();
XX! void dmaaddr();
XX! int dmardat();
XX! void dmawdat();
XX! void dmacomm();
XX! int dmastat();
XX  
XX  /* stdskclk.c */
XX! int do_xbms();
XX   
XX- /* stfnt.c */
XX- 
XX  /* stkbd.c */
XX! void kbdint();
XX! void kbdput();
XX! void kb_timer();
XX! void kbdinit();
XX  
XX  /* stshadow.c */
XX! void mkshadow();
XX! void rmshadow();
XX! void unshadow();
XX   
XX  /* stvdu.c */
XX! void flush();
XX! void out_char();
XX! void vducursor();
XX! void vduinit();
XX  
XX! /* copy68k.s */
XX! void flipclicks();
XX! void copyclicks();
XX! void zeroclicks();
XX! void phys_copy();
XX  
XX  /* stdskclks.s */
XX! int rd1byte();
XX! int wr1byte();
XX! long getsupra();
XX! long geticd();
XX  
XX! /* stmpx.s */
XX! int lock();
XX! void unlock();
XX! void restore();
XX! void reboot();
XX  
XX  #endif /* (CHIP == M68000) */
XX--- 1,369 ----
XX  /* Function prototypes. */
XX  
XX! #ifndef PROTO_H
XX! #define PROTO_H
XX  
XX! /* Struct declarations. */
XX! struct proc;
XX! struct tty_struct;
XX  
XX+ /* at_wini.c, bios_wini.c, esdi_wini.c, ps_wini.c, xt_wini.c, stacsi.c */
XX+ _PROTOTYPE( void winchester_task, (void)				);
XX+ 
XX  /* clock.c */
XX! _PROTOTYPE( void clock_handler, (void)					);
XX! _PROTOTYPE( void clock_task, (void)					);
XX! _PROTOTYPE( clock_t get_uptime, (void)					);
XX! _PROTOTYPE( void syn_alrm_task, (void)					);
XX  
XX! /* dmp.c */
XX! _PROTOTYPE( void fork_name, (int p1, int p2)				);
XX! _PROTOTYPE( void map_dmp, (void)					);
XX! _PROTOTYPE( void mem_dmp, (char *adr, int len)				);
XX! _PROTOTYPE( void p_dmp, (void)						);
XX! _PROTOTYPE( void reg_dmp, (struct proc *rp)				);
XX! _PROTOTYPE( void set_name, (int source_nr, int proc_nr, char *ptr)	);
XX! _PROTOTYPE( void tty_dmp, (void)					);
XX  
XX  /* floppy.c, stfloppy.c */
XX! _PROTOTYPE( void floppy_task, (void)					);
XX  
XX  /* main.c, stmain.c */
XX! _PROTOTYPE( void main, (void)						);
XX! _PROTOTYPE( void panic, (const char *s, int n)				);
XX  
XX  /* memory.c */
XX! _PROTOTYPE( void mem_task, (void)					);
XX  
XX  /* misc.c */
XX! _PROTOTYPE( int do_vrdwt, (message *m_ptr, rdwt_t do_rdwt)		);
XX  
XX  /* printer.c, stprint.c */
XX! _PROTOTYPE( void printer_task, (void)					);
XX  
XX  /* proc.c */
XX! _PROTOTYPE( void interrupt, (int task)					);
XX! _PROTOTYPE( int lock_mini_send, (struct proc *caller_ptr,
XX! 		int dest, message *m_ptr)				);
XX! _PROTOTYPE( void lock_pick_proc, (void)					);
XX! _PROTOTYPE( void lock_ready, (struct proc *rp)				);
XX! _PROTOTYPE( void lock_sched, (void)					);
XX! _PROTOTYPE( void lock_unready, (struct proc *rp)			);
XX! _PROTOTYPE( int sys_call, (int function, int src_dest, message *m_ptr)	);
XX! _PROTOTYPE( void unhold, (void)						);
XX  
XX+ /* rs232.c */
XX+ _PROTOTYPE( void rs_inhibit, (int minor, int inhibit)			);
XX+ _PROTOTYPE( int rs_init, (int minor)					);
XX+ _PROTOTYPE( int rs_ioctl, (int minor, int mode, int speeds)		);
XX+ _PROTOTYPE( int rs_read, (int minor, char **bufindirect,
XX+ 		unsigned char *odoneindirect)				);
XX+ _PROTOTYPE( void rs_istart, (int minor)					);
XX+ _PROTOTYPE( void rs_istop, (int minor)					);
XX+ _PROTOTYPE( void rs_ocancel, (int minor)				);
XX+ _PROTOTYPE( void rs_setc, (int minor, int xoff)				);
XX+ _PROTOTYPE( void rs_write, (int minor, char *buf, int nbytes)		);
XX+ 
XX  /* system.c */
XX! _PROTOTYPE( void cause_sig, (int proc_nr, int sig_nr)			);
XX! _PROTOTYPE( void inform, (void)						);
XX! _PROTOTYPE( phys_bytes numap, (int proc_nr, vir_bytes vir_addr, 
XX! 		vir_bytes bytes)					);
XX! _PROTOTYPE( void sys_task, (void)					);
XX! _PROTOTYPE( phys_bytes umap, (struct proc *rp, int seg, vir_bytes vir_addr,
XX! 		vir_bytes bytes)					);
XX  
XX  /* tty.c */
XX! _PROTOTYPE( void finish, (struct tty_struct *tp, int code)		);
XX! _PROTOTYPE( void sigchar, (struct tty_struct *tp, int sig)		);
XX! _PROTOTYPE( void tty_task, (void)					);
XX! _PROTOTYPE( void tty_wakeup, (void)					);
XX  
XX  /* library */
XX! _PROTOTYPE( void *memcpy, (void *_s1, const void *_s2, size_t _n)	);
XX! _PROTOTYPE( void printk, (const char *mess,...)				);
XX! _PROTOTYPE( int receive, (int source, message *mess)			);
XX! _PROTOTYPE( int send, (int to, message *mess)				);
XX! _PROTOTYPE( int sendrec, (int _src_dest, message *_m_ptr)		);
XX  
XX  #if (CHIP == INTEL)
XX  
XX  /* clock.c */
XX! _PROTOTYPE( void milli_delay, (unsigned millisec)			);
XX! _PROTOTYPE( unsigned read_counter, (void)				);
XX  
XX  /* console.c */
XX! _PROTOTYPE( void console, (struct tty_struct *tp)			);
XX! _PROTOTYPE( void flush, (struct tty_struct *tp)				);
XX! _PROTOTYPE( void out_char, (struct tty_struct *tp, int c)		);
XX! _PROTOTYPE( void putk, (int c)						);
XX! _PROTOTYPE( void scr_init, (int minor)					);
XX! _PROTOTYPE( void toggle_scroll, (void)					);
XX  
XX  /* cstart.c */
XX! _PROTOTYPE( void cstart, (U16_t cs, U16_t ds,
XX! 		char *parmoff, U16_t parmseg, size_t parmsize)		);
XX  
XX+ /* ether.c */
XX+ _PROTOTYPE( void ehw_task, (void)					);
XX+ _PROTOTYPE( void ehw_dump, (void)					);
XX+ 
XX  /* exception.c */
XX! _PROTOTYPE( void exception, (unsigned vec_nr)				);
XX  
XX  /* i8259.c */
XX! _PROTOTYPE( void enable_irq, (unsigned irq_nr)				);
XX! _PROTOTYPE( void init_8259, (unsigned master_base, unsigned slave_base)	);
XX! _PROTOTYPE( void soon_reboot, (void)					);
XX  
XX  /* keyboard.c */
XX! _PROTOTYPE( int func_key, (int ch)					);
XX! _PROTOTYPE( void kb_init, (int minor)					);
XX! _PROTOTYPE( int kb_read, (int minor, char **bufindirect,
XX! 		unsigned char *odoneindirect)				);
XX! _PROTOTYPE( void keyboard, (void)					);
XX! _PROTOTYPE( int letter_code, (int scode)				);
XX! _PROTOTYPE( int make_break, (int ch)					);
XX! _PROTOTYPE( void wreboot, (void)					);
XX  
XX  /* klib*.x */
XX! _PROTOTYPE( void bios13, (void)						);
XX! _PROTOTYPE( void build_sig, (char *sig_stuff, struct proc *rp, int sig)	);
XX! _PROTOTYPE( phys_bytes check_mem, (phys_bytes base, phys_bytes size)	);
XX! _PROTOTYPE( void cim_at_wini, (void)					);
XX! _PROTOTYPE( void cim_floppy, (void)					);
XX! _PROTOTYPE( void cim_printer, (void)					);
XX! _PROTOTYPE( void cim_xt_wini, (void)					);
XX! _PROTOTYPE( void cp_mess, (int src,phys_clicks src_clicks,vir_bytes src_offset,
XX! 		phys_clicks dst_clicks, vir_bytes dst_offset)		);
XX! _PROTOTYPE( int in_byte, (port_t port)					);
XX! _PROTOTYPE( int in_word, (port_t port)					);
XX! _PROTOTYPE( void klib_1hook, (void)					);
XX! _PROTOTYPE( void klib_2hook, (void)					);
XX! _PROTOTYPE( void lock, (void)						);
XX! _PROTOTYPE( u16_t mem_rdw, (segm_t segm, vir_bytes offset)		);
XX! _PROTOTYPE( void mpx_1hook, (void)					);
XX! _PROTOTYPE( void mpx_2hook, (void)					);
XX! _PROTOTYPE( void out_byte, (port_t port, int value)			);
XX! _PROTOTYPE( void out_word, (port_t port, int value)			);
XX! _PROTOTYPE( void phys_copy, (phys_bytes source, phys_bytes dest,
XX! 		phys_bytes count)					);
XX! _PROTOTYPE( void port_read, (unsigned port, phys_bytes destination,
XX! 		unsigned bytcount)					);
XX! _PROTOTYPE( void port_write, (unsigned port, phys_bytes source,
XX! 		unsigned bytcount)					);
XX! _PROTOTYPE( void reset, (void)						);
XX! _PROTOTYPE( void scr_down, (unsigned videoseg, int source,int dest,int count));
XX! _PROTOTYPE( void scr_up, (unsigned videoseg, int source, int dest, int count));
XX! _PROTOTYPE( void sim_printer, (void)					);
XX! _PROTOTYPE( unsigned tasim_printer, (void)				);
XX! _PROTOTYPE( int test_and_set, (int *flag)				);
XX! _PROTOTYPE( void unlock, (void)						);
XX! _PROTOTYPE( void vid_copy, (char *buffer, unsigned videobase,
XX! 		int offset, int words)					);
XX! _PROTOTYPE( void wait_retrace, (void)					);
XX  
XX  /* misc.c */
XX! _PROTOTYPE( void mem_init, (void)					);
XX  
XX  /* mpx*.x */
XX! _PROTOTYPE( void idle_task, (void)					);
XX! _PROTOTYPE( void restart, (void)					);
XX! _PROTOTYPE( void db, (void)                                             );
XX! _PROTOTYPE( u16_t get_word, (U16_t segment, u16_t *offset)		);
XX! _PROTOTYPE( void put_word, (U16_t segment, u16_t *offset, U16_t value)	);
XX  
XX+ /* The following are never called from C (pure asm procs). */
XX+ 
XX+ /* Exception handlers, in numerical order. */
XX+ _PROTOTYPE( void int00, (void) ), _PROTOTYPE( divide_error, (void) );
XX+ _PROTOTYPE( void int01, (void) ), _PROTOTYPE( single_step_exception, (void) );
XX+ _PROTOTYPE( void int02, (void) ), _PROTOTYPE( nmi, (void) );
XX+ _PROTOTYPE( void int03, (void) ), _PROTOTYPE( breakpoint_exception, (void) );
XX+ _PROTOTYPE( void int04, (void) ), _PROTOTYPE( overflow, (void) );
XX+ _PROTOTYPE( void int05, (void) ), _PROTOTYPE( bounds_check, (void) );
XX+ _PROTOTYPE( void int06, (void) ), _PROTOTYPE( inval_opcode, (void) );
XX+ _PROTOTYPE( void int07, (void) ), _PROTOTYPE( copr_not_available, (void) );
XX+ _PROTOTYPE( void int08, (void) ), _PROTOTYPE( double_fault, (void) );
XX+ _PROTOTYPE( void int09, (void) ), _PROTOTYPE( copr_seg_overrun, (void) );
XX+ _PROTOTYPE( void int10, (void) ), _PROTOTYPE( inval_tss, (void) );
XX+ _PROTOTYPE( void int11, (void) ), _PROTOTYPE( segment_not_present, (void) );
XX+ _PROTOTYPE( void int12, (void) ), _PROTOTYPE( stack_exception, (void) );
XX+ _PROTOTYPE( void int13, (void) ), _PROTOTYPE( general_protection, (void) );
XX+ _PROTOTYPE( void int14, (void) ), _PROTOTYPE( page_fault, (void) );
XX+ _PROTOTYPE( void int15, (void) );
XX+ _PROTOTYPE( void int16, (void) ), _PROTOTYPE( copr_error, (void) );
XX+ 
XX+ /* Hardware interrupt handlers, in numerical order. */
XX+ _PROTOTYPE( void clock_int, (void) );
XX+ _PROTOTYPE( void tty_int, (void) );
XX+ _PROTOTYPE( void secondary_int, (void) ), _PROTOTYPE( psecondary_int, (void) );
XX+ _PROTOTYPE( void eth_int, (void) );
XX+ _PROTOTYPE( void rs232_int, (void) ), _PROTOTYPE( prs232_int, (void) );
XX+ _PROTOTYPE( void disk_int, (void) );
XX+ _PROTOTYPE( void lpr_int, (void) );
XX+ _PROTOTYPE( void wini_int, (void) );
XX+ 
XX+ /* Software interrupt handlers, in numerical order. */
XX+ _PROTOTYPE( void trp, (void) );
XX+ _PROTOTYPE( void s_call, (void) ), _PROTOTYPE( p_s_call, (void) );
XX+ 
XX  /* printer.c */
XX! _PROTOTYPE( void pr_char, (void)					);
XX! _PROTOTYPE( void pr_restart, (void)					);
XX  
XX  /* protect.c */
XX! _PROTOTYPE( void prot_init, (void)					);
XX! _PROTOTYPE( void init_codeseg, (struct segdesc_s *segdp, phys_bytes base,
XX! 		phys_bytes size, int privilege)				);
XX! _PROTOTYPE( void init_dataseg, (struct segdesc_s *segdp, phys_bytes base,
XX! 		phys_bytes size, int privilege)				);
XX! _PROTOTYPE( void ldt_init, (void)					);
XX  
XX  /* rs232.c */
XX! _PROTOTYPE( void rs232_1handler, (void)					);
XX! _PROTOTYPE( void rs232_2handler, (void)					);
XX  
XX  /* system.c */
XX! _PROTOTYPE( void alloc_segments, (struct proc *rp)			);
XX  
XX  #endif /* (CHIP == INTEL) */
XX  
XX  #if (CHIP == M68000)
XX  
XX! /* cstart.c */
XX! _PROTOTYPE( void cstart, (char *parmoff, size_t parmsize)		);
XX  
XX  /* stfloppy.c */
XX! _PROTOTYPE( void fd_timer, (void)					);
XX  
XX! /* stmain.c */
XX! _PROTOTYPE( void none, (void)						);
XX! _PROTOTYPE( void rupt, (void)						);
XX! _PROTOTYPE( void trap, (void)						);
XX! _PROTOTYPE( void checksp, (void)					);
XX! _PROTOTYPE( void aciaint, (void)					);
XX! _PROTOTYPE( void fake_int, (const char *s, int t)				);
XX! _PROTOTYPE( void timint, (int t)					);
XX! _PROTOTYPE( void mdiint, (void)						);
XX! _PROTOTYPE( void iob, (int t)						);
XX! _PROTOTYPE( void idle_task, (void)					);
XX  
XX  /* rs232.c */
XX! _PROTOTYPE( void siaint, (int type)					);
XX  
XX  /* stcon.c */
XX! _PROTOTYPE( void func_key, (void)					);
XX! _PROTOTYPE( void dump, (void)						);
XX! _PROTOTYPE( void putk, (int c)						);
XX  
XX  /* stdma.c */
XX! _PROTOTYPE( void dmagrab, (int p, dmaint_t func)			);
XX! _PROTOTYPE( void dmafree, (int p)					);
XX! _PROTOTYPE( void dmaint, (void)						);
XX! _PROTOTYPE( void dmaaddr, (phys_bytes ad)				);
XX! _PROTOTYPE( int dmardat, (int mode, int delay)				);
XX! _PROTOTYPE( void dmawdat, (int mode, int data, int delay)		);
XX! _PROTOTYPE( void dmawcmd, (int data, unsigned mode)			);
XX! _PROTOTYPE( void dmacomm, (int mode, int data, int delay)		);
XX! _PROTOTYPE( int dmastat, (int mode, int delay)				);
XX  
XX  /* stdskclk.c */
XX! _PROTOTYPE( int do_xbms, (phys_bytes address, int count, int rw, int minor) );
XX   
XX  /* stkbd.c */
XX! _PROTOTYPE( void kbdint, (void)						);
XX! _PROTOTYPE( void kb_timer, (void)					);
XX! _PROTOTYPE( int kb_read, (int minor, char **bufindirect,
XX! 		unsigned char *odoneindirect)				);
XX! _PROTOTYPE( void kbdinit, (int minor)					);
XX  
XX  /* stshadow.c */
XX! _PROTOTYPE( void mkshadow, (struct proc *p, phys_clicks c2)		);
XX! _PROTOTYPE( void rmshadow, (struct proc *p, phys_clicks *basep,
XX! 		phys_clicks *sizep)					);
XX! _PROTOTYPE( void unshadow, (struct proc *p)				);
XX   
XX  /* stvdu.c */
XX! _PROTOTYPE( void flush, (struct tty_struct *tp)				);
XX! _PROTOTYPE( void console, (struct tty_struct *tp)			);
XX! _PROTOTYPE( void out_char, (struct tty_struct *tp, int c)		);
XX! _PROTOTYPE( void vduinit, (struct tty_struct *tp)			);
XX! _PROTOTYPE( void vduswitch, (struct tty_struct *tp)			);
XX! _PROTOTYPE( void vdusetup, (unsigned int vres, char *vram,
XX! 			    unsigned short *vrgb)			);
XX! _PROTOTYPE( void vbl, (void)						);
XX! _PROTOTYPE( int vdu_loadfont, (message *m_ptr)				);
XX  
XX! /* stwini.c */
XX! _PROTOTYPE( int wini_open, (message *mp)				);
XX! _PROTOTYPE( int wini_rdwt, (message *mp)				);
XX! _PROTOTYPE( int wini_hvrdwt, (message *mp)				);
XX! _PROTOTYPE( int wini_transfer, (int rw, int pnr, int minor,
XX! 		long pos, int count, vir_bytes vadr)			);
XX! _PROTOTYPE( int wini_ioctl, (message *mp)				);
XX! _PROTOTYPE( int wini_close, (message *mp)				);
XX  
XX+ /* stacsi.c */
XX+ _PROTOTYPE( int acsi_cmd, (int drive,  unsigned char *cmd, int cmdlen,
XX+ 		phys_bytes address, phys_bytes data_len,  int rw)	);
XX+ 
XX+ /* stscsi.c */
XX+ _PROTOTYPE( void scsi_task, (void)					);
XX+ _PROTOTYPE( void scsidmaint, (void)					);
XX+ _PROTOTYPE( void scsiint, (void)					);
XX+ _PROTOTYPE( int scsi_cmd, (int drive,  unsigned char *cmd, int cmdlen,
XX+ 		phys_bytes address, phys_bytes data_len,  int rw)	);
XX+ 
XX+ /* klib68k.s */
XX+ _PROTOTYPE( void flipclicks, (phys_clicks c1, phys_clicks c2, phys_clicks n) );
XX+ _PROTOTYPE( void copyclicks, (phys_clicks src, phys_clicks dest,
XX+ 		phys_clicks nclicks)					);
XX+ _PROTOTYPE( void zeroclicks, (phys_clicks dest, phys_clicks nclicks)	);
XX+ _PROTOTYPE( void phys_copy, (phys_bytes src, phys_bytes dest, phys_bytes n) );
XX+ 
XX  /* stdskclks.s */
XX! _PROTOTYPE( int rd1byte, (void)						);
XX! _PROTOTYPE( int wr1byte, (int)						);
XX! _PROTOTYPE( long getsupra, (void)					);
XX! _PROTOTYPE( long geticd, (void)						);
XX  
XX! /* mpx.s */
XX! _PROTOTYPE( int lock, (void)						);
XX! _PROTOTYPE( void unlock, (void)						);
XX! _PROTOTYPE( void restore, (int oldsr)					);
XX! _PROTOTYPE( void reboot, (void)						);
XX! _PROTOTYPE( int test_and_set, (char *flag)				);
XX! _PROTOTYPE( unsigned long get_mem_size, (char *start_addr)			);
XX  
XX+ /* stprint.c */
XX+ #ifdef DEBOUT
XX+ _PROTOTYPE( void prtc, (int c)						);
XX+ #endif
XX+ 
XX+ #ifdef FPP
XX+ /* fpp.c */
XX+ _PROTOTYPE( void fppinit, (void)					);
XX+ _PROTOTYPE( void fpp_new_state, (struct proc *rp)			);
XX+ _PROTOTYPE( void fpp_save, (struct proc *rp, struct cpu_state *p)	);
XX+ _PROTOTYPE( struct cpu_state  *fpp_restore, (struct proc *rp)		);
XX+ 
XX+ /* fpps.s */
XX+ _PROTOTYPE( void _fppsave, (struct state_frame *p)			);
XX+ _PROTOTYPE( void _fppsavereg, (struct fpp_model *p)			);
XX+ _PROTOTYPE( void _fpprestore, (struct state_frame *p)			);
XX+ _PROTOTYPE( void _fpprestreg, (struct fpp_model *p)			);
XX+ #endif
XX+ 
XX+ #if (SHADOWING == 0)
XX+ /* pmmu.c */
XX+ _PROTOTYPE(void pmmuinit , (void)					);
XX+ _PROTOTYPE(void pmmu_init_proc , (struct proc *rp )			);
XX+ _PROTOTYPE(void pmmu_restore , (struct proc *rp )			);
XX+ _PROTOTYPE(void pmmu_delete , (struct proc *rp )			);
XX+ _PROTOTYPE(void pmmu_flush , (struct proc *rp )				);
XX+ #endif
XX+ 
XX  #endif /* (CHIP == M68000) */
XX+ 
XX+ #endif /* PROTO_H */
X/
Xecho x - ps_wini.c.d
Xsed '/^X/s///' > ps_wini.c.d << '/'
XX*** /home/top/ast/minix/1.5/kernel/ps_wini.c  crc=29570  27550	Sat May  5 13:15:11 1990
XX--- /home/top/ast/minix/1.6.25/kernel/ps_wini.c  crc=10327  28340	Tue Nov  3 21:20:59 1992
XX***************
XX*** 11,20 ****
XX   *
XX   *    m_type      DEVICE    PROC_NR     COUNT    POSITION  ADRRESS
XX   * ----------------------------------------------------------------
XX!  * |  DISK_READ | device  | proc nr |  bytes  |  offset | buf ptr |
XX   * |------------+---------+---------+---------+---------+---------|
XX!  * | DISK_WRITE | device  | proc nr |  bytes  |  offset | buf ptr |
XX!  * ----------------------------------------------------------------
XX   * |SCATTERED_IO| device  | proc nr | requests|         | iov ptr |
XX   * ----------------------------------------------------------------
XX   *
XX--- 11,24 ----
XX   *
XX   *    m_type      DEVICE    PROC_NR     COUNT    POSITION  ADRRESS
XX   * ----------------------------------------------------------------
XX!  * |  DEV_OPEN  |         |         |         |         |         |
XX   * |------------+---------+---------+---------+---------+---------|
XX!  * |  DEV_CLOSE |         |         |         |         |         |
XX!  * |------------+---------+---------+---------+---------+---------|
XX!  * |  DEV_READ  | device  | proc nr |  bytes  |  offset | buf ptr |
XX!  * |------------+---------+---------+---------+---------+---------|
XX!  * |  DEV_WRITE | device  | proc nr |  bytes  |  offset | buf ptr |
XX!  * |------------+---------+---------+---------+---------+---------|
XX   * |SCATTERED_IO| device  | proc nr | requests|         | iov ptr |
XX   * ----------------------------------------------------------------
XX   *
XX***************
XX*** 96,102 ****
XX  
XX  /* Variables. */
XX  PRIVATE struct wini {		/* main drive struct, one entry per drive */
XX!   int wn_opcode;		/* DISK_READ or DISK_WRITE */
XX    int wn_procnr;		/* which proc wanted this operation? */
XX    int wn_drive;			/* drive number addressed */
XX    int wn_cylinder;		/* cylinder number addressed */
XX--- 100,106 ----
XX  
XX  /* Variables. */
XX  PRIVATE struct wini {		/* main drive struct, one entry per drive */
XX!   int wn_opcode;		/* DEV_READ or DEV_WRITE */
XX    int wn_procnr;		/* which proc wanted this operation? */
XX    int wn_drive;			/* drive number addressed */
XX    int wn_cylinder;		/* cylinder number addressed */
XX***************
XX*** 124,147 ****
XX  
XX  PRIVATE unsigned char buf[BLOCK_SIZE]; /* Buffer used by the startup routine */
XX  
XX! FORWARD void ch_select();
XX! FORWARD void ch_unselect();
XX! FORWARD int com_out();
XX! FORWARD int controller_ready();
XX! FORWARD void copy_params();
XX! FORWARD void copy_prt();
XX! FORWARD int drive_busy();
XX! FORWARD void init_params();
XX! FORWARD void sort();
XX! FORWARD int w_do_rdwt();
XX! FORWARD int w_reset();
XX! FORWARD int w_transfer();
XX! FORWARD int win_init();
XX! FORWARD int win_results();
XX! FORWARD void set_command();
XX! FORWARD void w_dma_setup();
XX! FORWARD void abort_com();
XX! FORWARD int status();
XX  
XX  /*===========================================================================*
XX   *				winchester_task				     * 
XX--- 128,151 ----
XX  
XX  PRIVATE unsigned char buf[BLOCK_SIZE]; /* Buffer used by the startup routine */
XX  
XX! FORWARD _PROTOTYPE( void ch_select, (void) );
XX! FORWARD _PROTOTYPE( void ch_unselect, (void) );
XX! FORWARD _PROTOTYPE( int com_out, (int nr_words, int attention) );
XX! FORWARD _PROTOTYPE( int controller_ready, (void) );
XX! FORWARD _PROTOTYPE( void copy_params, (unsigned char *src, struct wini *dest));
XX! FORWARD _PROTOTYPE( void copy_prt, (int base_dev) );
XX! FORWARD _PROTOTYPE( void init_params, (void) );
XX! FORWARD _PROTOTYPE( void sort, (struct wini wn[]) );
XX! FORWARD _PROTOTYPE( int w_do_rdwt, (message *m_ptr) );
XX! FORWARD _PROTOTYPE( int w_reset, (void) );
XX! FORWARD _PROTOTYPE( int w_transfer, (struct wini *wn) );
XX! FORWARD _PROTOTYPE( int win_init, (void) );
XX! FORWARD _PROTOTYPE( int win_results, (void) );
XX! FORWARD _PROTOTYPE( void set_command, (struct wini *wn) );
XX! FORWARD _PROTOTYPE( void w_dma_setup, (struct wini *wn) );
XX! FORWARD _PROTOTYPE( void abort_com, (void) );
XX! FORWARD _PROTOTYPE( void dump_isr, (void) );
XX! FORWARD _PROTOTYPE( int status, (void) );
XX  
XX  /*===========================================================================*
XX   *				winchester_task				     * 
XX***************
XX*** 163,169 ****
XX  	/* First wait for a request to read or write a disk block. */
XX  	receive(ANY, &w_mess);	/* get a request to do some work */
XX  	if (w_mess.m_source < 0) {
XX! 		printf("winchester task got message from %d ", w_mess.m_source);
XX  		continue;
XX  	}
XX  	caller = w_mess.m_source;
XX--- 167,173 ----
XX  	/* First wait for a request to read or write a disk block. */
XX  	receive(ANY, &w_mess);	/* get a request to do some work */
XX  	if (w_mess.m_source < 0) {
XX! 		printf("winchester task got message from %d ",w_mess.m_source);
XX  		continue;
XX  	}
XX  	caller = w_mess.m_source;
XX***************
XX*** 171,178 ****
XX  
XX  	/* Now carry out the work. */
XX  	switch(w_mess.m_type) {
XX! 	    case DISK_READ:
XX! 	    case DISK_WRITE:	r = w_do_rdwt(&w_mess);	break;
XX  	    case SCATTERED_IO:	r = do_vrdwt(&w_mess, w_do_rdwt); break;
XX  	    default:		r = EINVAL;		break;
XX  	}
XX--- 175,186 ----
XX  
XX  	/* Now carry out the work. */
XX  	switch(w_mess.m_type) {
XX! 	    case DEV_OPEN:	r = OK;				  break;
XX! 	    case DEV_CLOSE:	r = OK;				  break;
XX! 
XX! 	    case DEV_READ:
XX! 	    case DEV_WRITE:	r = w_do_rdwt(&w_mess);		  break;
XX! 
XX  	    case SCATTERED_IO:	r = do_vrdwt(&w_mess, w_do_rdwt); break;
XX  	    default:		r = EINVAL;		break;
XX  	}
XX***************
XX*** 209,215 ****
XX    wn->wn_drive = device/DEV_PER_DRIVE;	/* save drive number */
XX    if (wn->wn_drive >= nr_drives)
XX  	return(EIO);
XX!   wn->wn_opcode = m_ptr->m_type;	/* DISK_READ or DISK_WRITE */
XX    if (m_ptr->POSITION % BLOCK_SIZE != 0)
XX  	return(EINVAL);
XX    sector = m_ptr->POSITION/SECTOR_SIZE;
XX--- 217,223 ----
XX    wn->wn_drive = device/DEV_PER_DRIVE;	/* save drive number */
XX    if (wn->wn_drive >= nr_drives)
XX  	return(EIO);
XX!   wn->wn_opcode = m_ptr->m_type;	/* DEV_READ or DEV_WRITE */
XX    if (m_ptr->POSITION % BLOCK_SIZE != 0)
XX  	return(EINVAL);
XX    sector = m_ptr->POSITION/SECTOR_SIZE;
XX***************
XX*** 251,257 ****
XX  PRIVATE int w_transfer(wn)
XX  register struct wini *wn;	/* pointer to the drive struct */
XX  {
XX! 	register int i, j, r;	/* indices */
XX  	message dummy;		/* dummy message to recieve interrupts */
XX  
XX  	set_command(wn);	/* setup command block */
XX--- 259,265 ----
XX  PRIVATE int w_transfer(wn)
XX  register struct wini *wn;	/* pointer to the drive struct */
XX  {
XX! 	register int i, r;	/* indices */
XX  	message dummy;		/* dummy message to recieve interrupts */
XX  
XX  	set_command(wn);	/* setup command block */
XX***************
XX*** 303,310 ****
XX   * like the controller refusing to respond.
XX   */
XX  
XX!   int i, r;
XX!   message dummy;
XX  
XX    out_byte(ACR, 0x80);	/* Strobe reset bit high. */
XX    out_byte(ACR, 0);	/* Strobe reset bit low. */
XX--- 311,317 ----
XX   * like the controller refusing to respond.
XX   */
XX  
XX!   int i;
XX  
XX    out_byte(ACR, 0x80);	/* Strobe reset bit high. */
XX    out_byte(ACR, 0);	/* Strobe reset bit low. */
XX***************
XX*** 333,339 ****
XX  {
XX  /* Routine to initialize the drive parameters after boot or reset */
XX  
XX!   register int i, cyl;
XX    message dummy;
XX  
XX  /*
XX--- 340,346 ----
XX  {
XX  /* Routine to initialize the drive parameters after boot or reset */
XX  
XX!   register int i;
XX    message dummy;
XX  
XX  /*
XX***************
XX*** 421,429 ****
XX    return(OK);
XX  }
XX  
XX! /*============================================================================*
XX!  *				win_results				      *
XX!  *============================================================================*/
XX  PRIVATE int win_results()
XX  {
XX  /* Extract results from the controller after an operation.
XX--- 428,436 ----
XX    return(OK);
XX  }
XX  
XX! /*===========================================================================*
XX!  *				win_results				     *
XX!  *===========================================================================*/
XX  PRIVATE int win_results()
XX  {
XX  /* Extract results from the controller after an operation.
XX***************
XX*** 450,458 ****
XX    return(retries);		/* nonzero if ready */
XX  }
XX  
XX! /*============================================================================*
XX!  *				com_out					      *
XX!  *============================================================================*/
XX  PRIVATE int com_out(nr_words, attention)
XX  int nr_words;
XX  int attention;
XX--- 457,465 ----
XX    return(retries);		/* nonzero if ready */
XX  }
XX  
XX! /*===========================================================================*
XX!  *				com_out					     *
XX!  *===========================================================================*/
XX  PRIVATE int com_out(nr_words, attention)
XX  int nr_words;
XX  int attention;
XX***************
XX*** 487,495 ****
XX  
XX  }
XX  
XX! /*============================================================================*
XX!  *				init_params				      *
XX!  *============================================================================*/
XX  PRIVATE void init_params()
XX  {
XX  /* This routine is called at startup to initialize the partition table,
XX--- 494,502 ----
XX  
XX  }
XX  
XX! /*===========================================================================*
XX!  *				init_params				     *
XX!  *===========================================================================*/
XX  PRIVATE void init_params()
XX  {
XX  /* This routine is called at startup to initialize the partition table,
XX***************
XX*** 546,552 ****
XX  	w_mess.COUNT = BLOCK_SIZE;
XX  	w_mess.ADDRESS = (char *) buf;
XX  	w_mess.PROC_NR = WINCHESTER;
XX! 	w_mess.m_type = DISK_READ;
XX  	if (w_do_rdwt(&w_mess) != BLOCK_SIZE) {
XX  		printf("Can't read partition table on winchester %d\n",i);
XX  		milli_delay(20000);
XX--- 553,559 ----
XX  	w_mess.COUNT = BLOCK_SIZE;
XX  	w_mess.ADDRESS = (char *) buf;
XX  	w_mess.PROC_NR = WINCHESTER;
XX! 	w_mess.m_type = DEV_READ;
XX  	if (w_do_rdwt(&w_mess) != BLOCK_SIZE) {
XX  		printf("Can't read partition table on winchester %d\n",i);
XX  		milli_delay(20000);
XX***************
XX*** 562,570 ****
XX  
XX  }
XX  
XX! /*============================================================================*
XX!  *				copy_params				      *
XX!  *============================================================================*/
XX  PRIVATE void copy_params(src, dest)
XX  register unsigned char *src;
XX  register struct wini *dest;
XX--- 569,577 ----
XX  
XX  }
XX  
XX! /*===========================================================================*
XX!  *				copy_params				     *
XX!  *===========================================================================*/
XX  PRIVATE void copy_params(src, dest)
XX  register unsigned char *src;
XX  register struct wini *dest;
XX***************
XX*** 712,718 ****
XX    vir_bytes vir, ct;
XX    phys_bytes user_phys;
XX  
XX!   mode = (wn->wn_opcode == DISK_READ ? DMA_READ : DMA_WRITE);
XX    vir = (vir_bytes) wn->wn_address;
XX    ct = (vir_bytes) BLOCK_SIZE;
XX    user_phys = numap(wn->wn_procnr, vir, BLOCK_SIZE);
XX--- 719,725 ----
XX    vir_bytes vir, ct;
XX    phys_bytes user_phys;
XX  
XX!   mode = (wn->wn_opcode == DEV_READ ? DMA_READ : DMA_WRITE);
XX    vir = (vir_bytes) wn->wn_address;
XX    ct = (vir_bytes) BLOCK_SIZE;
XX    user_phys = numap(wn->wn_procnr, vir, BLOCK_SIZE);
XX***************
XX*** 776,782 ****
XX  /*===========================================================================*
XX   *				dump_isr				     *
XX   *===========================================================================*/
XX! PRIVATE dump_isr()
XX  {
XX  /*
XX   * Dump_isr will print out an informative message of what the controller
XX--- 783,789 ----
XX  /*===========================================================================*
XX   *				dump_isr				     *
XX   *===========================================================================*/
XX! PRIVATE void dump_isr()
XX  {
XX  /*
XX   * Dump_isr will print out an informative message of what the controller
XX***************
XX*** 807,813 ****
XX  PRIVATE void set_command(wn)
XX  register struct wini *wn;
XX  {
XX! 	command[0] = wn->wn_opcode == DISK_READ ? WIN_READ : WIN_WRITE;
XX  	command[1] = ((wn->wn_head << 4) & 0xF0) | 
XX  					((wn->wn_cylinder >> 8) & 0x03);
XX  	command[2] = wn->wn_cylinder & BYTE;
XX--- 814,820 ----
XX  PRIVATE void set_command(wn)
XX  register struct wini *wn;
XX  {
XX! 	command[0] = wn->wn_opcode == DEV_READ ? WIN_READ : WIN_WRITE;
XX  	command[1] = ((wn->wn_head << 4) & 0xF0) | 
XX  					((wn->wn_cylinder >> 8) & 0x03);
XX  	command[2] = wn->wn_cylinder & BYTE;
X/
Xecho x - rs232.c.d
Xsed '/^X/s///' > rs232.c.d << '/'
XX*** /home/top/ast/minix/1.5/kernel/rs232.c  crc=27260  20246	Sat Apr 21 22:26:23 1990
XX--- /home/top/ast/minix/1.6.25/kernel/rs232.c  crc=12091  26842	Tue Nov  3 21:21:01 1992
XX***************
XX*** 1,18 ****
XX  /*==========================================================================*
XX   *		rs232.c - serial driver for 8250 and 16450 UARTs 	    *
XX   *==========================================================================*/
XX  
XX  #include "kernel.h"
XX  #include <sgtty.h>
XX  #include "tty.h"
XX  
XX  /* Switches.
XX   * #define C_RS232_INT_HANDLERS to use the interrupt handlers in this file.
XX   * #define NO_HANDSHAKE to avoid requiring CTS for output.
XX   */
XX  
XX  /* 8250 constants. */
XX- #define DEF_BAUD             1200	/* default baud rate */
XX  #define UART_FREQ         115200L	/* timer frequency */
XX  
XX  /* Interrupt enable bits. */
XX--- 1,33 ----
XX  /*==========================================================================*
XX   *		rs232.c - serial driver for 8250 and 16450 UARTs 	    *
XX+  *		Added support for Atari ST M68901 and YM-2149	--kub	    *
XX   *==========================================================================*/
XX  
XX  #include "kernel.h"
XX  #include <sgtty.h>
XX  #include "tty.h"
XX  
XX+ #if (CHIP != INTEL) && (MACHINE != ATARI)
XX+ #error				/* rs232.c only supports PC/AT and Atari ST */
XX+ #endif
XX+ 
XX+ #if (MACHINE == ATARI)
XX+ #include "staddr.h"
XX+ #include "stsound.h"
XX+ #include "stmfp.h"
XX+ #if (NR_RS_LINES > 1)
XX+ #error				/* Only one physical RS232 line available */
XX+ #endif
XX+ #endif
XX+ 
XX  /* Switches.
XX   * #define C_RS232_INT_HANDLERS to use the interrupt handlers in this file.
XX   * #define NO_HANDSHAKE to avoid requiring CTS for output.
XX   */
XX  
XX+ #if (CHIP == INTEL)		/* PC/AT 8250/16450 chip combination */
XX+ 
XX  /* 8250 constants. */
XX  #define UART_FREQ         115200L	/* timer frequency */
XX  
XX  /* Interrupt enable bits. */
XX***************
XX*** 35,42 ****
XX  #define LC_ADDRESS_DIVISOR   0x80
XX  #define LC_STOP_BITS_SHIFT      2
XX  
XX- #define DATA_BITS_SHIFT         8	/* amount data bits shifted in mode */
XX- 
XX  /* Line status bits. */
XX  #define LS_OVERRUN_ERR          2
XX  #define LS_PARITY_ERR           4
XX--- 50,55 ----
XX***************
XX*** 52,57 ****
XX--- 65,98 ----
XX  /* Modem status bits. */
XX  #define MS_CTS               0x10
XX  
XX+ #else /* MACHINE == ATARI */		/* Atari ST 68901 USART */
XX+ 
XX+ /* Most of the USART constants are already defined in stmfp.h . The local
XX+  * definitions made here are for keeping C code changes smaller.   --kub
XX+  */
XX+ 
XX+ #define UART_FREQ          19200L	/* timer frequency */
XX+ 
XX+ /* Line control bits. */
XX+ #define LC_NO_PARITY            0
XX+ #define LC_DATA_BITS            3
XX+ #define LC_ODD_PARITY       U_PAR
XX+ #define LC_EVEN_PARITY     (U_PAR|U_EVEN)
XX+ 
XX+ /* Line status bits. */
XX+ #define LS_OVERRUN_ERR       R_OE
XX+ #define LS_PARITY_ERR        R_PE
XX+ #define LS_FRAMING_ERR       R_FE
XX+ #define LS_BREAK_INTERRUPT   R_BREAK
XX+ 
XX+ /* Modem status bits. */
XX+ #define MS_CTS               IO_SCTS	/* 0x04 */
XX+ 
XX+ #endif /* CHIP/MACHINE */
XX+ 
XX+ #define DATA_BITS_SHIFT         8	/* amount data bits shifted in mode */
XX+ #define DEF_BAUD             1200	/* default baud rate */
XX+ 
XX  /* Input buffer watermarks.
XX   * The external device is asked to stop sending when the buffer
XX   * exactly reaches high water, or when TTY requests it.
XX***************
XX*** 66,71 ****
XX--- 107,114 ----
XX   */
XX  #define RS_IHIGHWATER (3 * RS_IBUFSIZE / 4)
XX  
XX+ #if (CHIP == INTEL)
XX+ 
XX  /* Macros to handle flow control.
XX   * Interrupts must be off when they are used.
XX   * Time is critical - already the function call for out_byte() is annoying.
XX***************
XX*** 97,105 ****
XX  /* Macro to tell if transmitter is ready. */
XX  #define txready(rs) (in_byte(rs->line_status_port) & LS_TRANSMITTER_READY)
XX  
XX  /* Types. */
XX! typedef char bool_t;		/* boolean */
XX! typedef unsigned port_t;	/* hardware port */
XX  
XX  /* RS232 device structure, one per device. */
XX  struct rs232_s {
XX--- 140,183 ----
XX  /* Macro to tell if transmitter is ready. */
XX  #define txready(rs) (in_byte(rs->line_status_port) & LS_TRANSMITTER_READY)
XX  
XX+ #else /* MACHINE == ATARI */
XX+ 
XX+ /* Macros to handle flow control.
XX+  * Time is critical - already the function call for lock()/restore() is
XX+  * annoying.
XX+  * istart() tells external device we are ready by raising RTS.
XX+  * istop() tells external device we are not ready by dropping RTS.
XX+  * DTR is kept high all the time (it probably should be raised by open and
XX+  * dropped by close of the device). NOTE: The modem lines are active low.
XX+  */
XX+ #define set_porta(msk,val) { register int s = lock();		\
XX+ 			     SOUND->sd_selr = YM_IOA;		\
XX+ 			     SOUND->sd_wdat =			\
XX+ 				SOUND->sd_rdat & (msk) | (val);	\
XX+ 			     restore(s);	}
XX+ #define istart(rs)         { set_porta( ~(PA_SRTS|PA_SDTR),0 ); \
XX+ 			     (rs)->idevready = TRUE;	}
XX+ #define istop(rs)          { set_porta( ~PA_SDTR, PA_SRTS );	\
XX+ 			     (rs)->idevready = FALSE;	}
XX+ 
XX+ /* Macro to tell if device is ready.
XX+  * Don't require DSR, since modems drop this to indicate the line is not
XX+  * ready even when the modem itself is ready.
XX+  * If NO_HANDSHAKE, force the ready bit.
XX+  */
XX+ #if NO_HANDSHAKE
XX+ #define devready(rs)         MS_CTS
XX+ #else
XX+ #define devready(rs)         (~MFP->mf_gpip & MS_CTS)
XX+ #endif
XX+ 
XX+ /* Transmitter ready test */
XX+ #define txready(rs)          (MFP->mf_tsr & (T_EMPTY | T_UE))
XX+ 
XX+ #endif /* CHIP/MACHINE */
XX+ 
XX  /* Types. */
XX! typedef unsigned char bool_t;	/* boolean */
XX  
XX  /* RS232 device structure, one per device. */
XX  struct rs232_s {
XX***************
XX*** 126,131 ****
XX--- 204,210 ----
XX    char *obufend;		/* end of output buffer */
XX    char *optr;			/* next char to output */
XX  
XX+ #if (CHIP == INTEL)
XX    port_t xmit_port;		/* i/o ports */
XX    port_t recv_port;
XX    port_t div_low_port;
XX***************
XX*** 136,141 ****
XX--- 215,221 ----
XX    port_t modem_ctl_port;
XX    port_t line_status_port;
XX    port_t modem_status_port;
XX+ #endif
XX  
XX    unsigned char lstatus;	/* last line status */
XX    unsigned char pad;		/* ensure alignment for 16-bit ints */
XX***************
XX*** 155,178 ****
XX  
XX  #define rs_addr(minor) (p_rs_addr[minor])
XX  
XX  /* 8250 base addresses. */
XX  PRIVATE port_t addr_8250[] = {
XX    0x3F8,			/* COM1: (line 0); COM3 might be at 0x3E8 */
XX    0x2F8,			/* COM2: (line 1); COM4 might be at 0x2E8 */
XX  };
XX  
XX  PUBLIC struct rs232_s rs_lines[NR_RS_LINES];
XX  
XX  #if C_RS232_INT_HANDLERS
XX! FORWARD void in_int();
XX! FORWARD void line_int();
XX! FORWARD void modem_int();
XX! 
XX  #endif
XX- FORWARD void out_int();
XX- FORWARD int rs_config();
XX  
XX  
XX  /* High level routines (should only be called by TTY). */
XX  
XX  /*==========================================================================*
XX--- 235,261 ----
XX  
XX  #define rs_addr(minor) (p_rs_addr[minor])
XX  
XX+ #if (CHIP == INTEL)
XX  /* 8250 base addresses. */
XX  PRIVATE port_t addr_8250[] = {
XX    0x3F8,			/* COM1: (line 0); COM3 might be at 0x3E8 */
XX    0x2F8,			/* COM2: (line 1); COM4 might be at 0x2E8 */
XX  };
XX+ #endif
XX  
XX  PUBLIC struct rs232_s rs_lines[NR_RS_LINES];
XX  
XX  #if C_RS232_INT_HANDLERS
XX! FORWARD _PROTOTYPE( void in_int, (struct rs232_s *rs) );
XX! FORWARD _PROTOTYPE( void line_int, (struct rs232_s *rs) );
XX! FORWARD _PROTOTYPE( void modem_int, (struct rs232_s *rs) );
XX  #endif
XX  
XX+ FORWARD _PROTOTYPE( void out_int, (struct rs232_s *rs) );
XX+ FORWARD _PROTOTYPE( int rs_config, (int minor, int in_baud, int out_baud,
XX+ 		int parity, int stop_bits, int data_bits, int mode) );
XX  
XX+ 
XX  /* High level routines (should only be called by TTY). */
XX  
XX  /*==========================================================================*
XX***************
XX*** 204,209 ****
XX--- 287,299 ----
XX    if (in_baud < 50) in_baud = DEF_BAUD;	/* prevent divide overflow */
XX    if (out_baud < 50) out_baud = DEF_BAUD;	/* prevent divide overflow */
XX    divisor = (int) (UART_FREQ / in_baud);	/* 8250 can't hack 2 speeds */
XX+ #if (CHIP == INTEL)
XX+   switch(in_baud) {		/* HACK */
XX+     case 19300: divisor = 1; break;	/* 115200 */
XX+     case 19400: divisor = 2; break;	/* 57600 */
XX+     case 19500: divisor = 3; break;	/* 38400 */
XX+     case 19600: divisor = 4; break;	/* 28800 */
XX+   }
XX    line_controls = parity | ((stop_bits - 1) << LC_STOP_BITS_SHIFT)
XX  			 | (data_bits - 5);
XX  
XX***************
XX*** 221,226 ****
XX--- 311,342 ----
XX  
XX    /* Change the line controls and reselect the usual registers. */
XX    out_byte(rs->line_ctl_port, line_controls);
XX+ #else /* MACHINE == ATARI */
XX+   line_controls = parity | U_Q16;
XX+   switch (stop_bits) {
XX+ 	case 1:	line_controls |= U_ST1; break;
XX+ 	case 2:	line_controls |= U_ST2; break;
XX+   }
XX+   switch (data_bits) {
XX+ 	case 5:	line_controls |= U_D5; break;
XX+ 	case 6:	line_controls |= U_D6; break;
XX+ 	case 7:	line_controls |= U_D7; break;
XX+ 	case 8:	line_controls |= U_D8; break;
XX+   }
XX+   lock();
XX+   MFP->mf_ucr = line_controls;
XX+   /* Check if baud rate is valid. Some decent baud rates may not work because
XX+    * the timer cannot be programmed exactly enough, e.g. 7200. That is caught
XX+    * by the expressions below which check that the resulting baud rate has a
XX+    * deviation of max. 5%.
XX+    */
XX+   if (((UART_FREQ - (long)  divisor*in_baud >  UART_FREQ / 20) &&
XX+        (UART_FREQ - (long)++divisor*in_baud < -UART_FREQ / 20))   ||
XX+       divisor == 0 || divisor > 256)
XX+ 	printf ("tty line %d: can't set speed %d\n", minor, in_baud);
XX+   else
XX+ 	MFP->mf_tddr = divisor;
XX+ #endif /* CHIP/MACHINE */
XX  
XX    if (mode & RAW)
XX  	rs->ostate |= ORAW;
XX***************
XX*** 292,298 ****
XX--- 408,416 ----
XX  
XX    register struct rs232_s *rs;
XX    int speed;
XX+ #if (CHIP == INTEL)
XX    port_t this_8250;
XX+ #endif
XX  
XX    rs = rs_addr(minor) = &rs_lines[minor];
XX  
XX***************
XX*** 305,310 ****
XX--- 423,429 ----
XX    rs->ihighwater = rs->ibuf1 + RS_IHIGHWATER;
XX    rs->ittyready = TRUE;		/* idevready set to TRUE by istart() */
XX  
XX+ #if (CHIP == INTEL)
XX    /* Precalculate port numbers for speed. Magic numbers in the code (once). */
XX    this_8250 = addr_8250[minor];
XX    rs->xmit_port = this_8250 + 0;
XX***************
XX*** 317,346 ****
XX    rs->modem_ctl_port = this_8250 + 4;
XX    rs->line_status_port = this_8250 + 5;
XX    rs->modem_status_port = this_8250 + 6;
XX  
XX    /* Set up the hardware to a base state, in particular
XX     *	o turn off DTR (MC_DTR) to try to stop the external device.
XX     *	o disable interrupts at the chip level, to force an edge transition
XX     *	  on the 8259 line when interrupts are next enabled and active.
XX     *	  RS232 interrupts are guaranteed to be disabled now by the 8259
XX     *	  mask, but there used to be trouble if the mask was set without
XX     *	  handling a previous interrupt.
XX-    *	o be careful about the divisor latch.  It may be enabled now, and
XX-    *	  that used to cause trouble when interrupts were enabled too early
XX-    *	  (see comment in rs_config()).  Call rs_config() early to avoid this.
XX     */
XX    istop(rs);			/* sets modem_ctl_port */
XX-   out_byte(rs->int_enab_port, 0);
XX    speed = rs_config(minor, DEF_BAUD, DEF_BAUD, LC_NO_PARITY, 1, 8, RAW);
XX  
XX    /* Clear any harmful leftover interrupts.  An output interrupt is harmless
XX     * and will occur when interrupts are enabled anyway.  Set up the output
XX     * queue using the status from clearing the modem status interrupt.
XX     */
XX    in_byte(rs->line_status_port);
XX    in_byte(rs->recv_port);
XX    rs->ostate = devready(rs) | ORAW | OSWREADY;	/* reads modem_ctl_port */
XX  
XX    /* Enable interrupts for both interrupt controller and device. */
XX    if (minor & 1)		/* COM2 on IRQ3 */
XX  	enable_irq(SECONDARY_IRQ);
XX--- 436,473 ----
XX    rs->modem_ctl_port = this_8250 + 4;
XX    rs->line_status_port = this_8250 + 5;
XX    rs->modem_status_port = this_8250 + 6;
XX+ #endif
XX  
XX    /* Set up the hardware to a base state, in particular
XX     *	o turn off DTR (MC_DTR) to try to stop the external device.
XX+    *	o be careful about the divisor latch.  Some BIOS's leave it enabled
XX+    *	  here and that caused trouble (no interrupts) in version 1.5 by
XX+    *	  hiding the interrupt enable port in the next step, and worse trouble
XX+    *	  (continual interrupts) in an old version by hiding the receiver
XX+    *	  port in the first interrupt.  Call rs_config() early to avoid this.
XX     *	o disable interrupts at the chip level, to force an edge transition
XX     *	  on the 8259 line when interrupts are next enabled and active.
XX     *	  RS232 interrupts are guaranteed to be disabled now by the 8259
XX     *	  mask, but there used to be trouble if the mask was set without
XX     *	  handling a previous interrupt.
XX     */
XX    istop(rs);			/* sets modem_ctl_port */
XX    speed = rs_config(minor, DEF_BAUD, DEF_BAUD, LC_NO_PARITY, 1, 8, RAW);
XX+ #if (CHIP == INTEL)
XX+   out_byte(rs->int_enab_port, 0);
XX+ #endif
XX  
XX    /* Clear any harmful leftover interrupts.  An output interrupt is harmless
XX     * and will occur when interrupts are enabled anyway.  Set up the output
XX     * queue using the status from clearing the modem status interrupt.
XX     */
XX+ #if (CHIP == INTEL)
XX    in_byte(rs->line_status_port);
XX    in_byte(rs->recv_port);
XX+ #endif
XX    rs->ostate = devready(rs) | ORAW | OSWREADY;	/* reads modem_ctl_port */
XX  
XX+ #if (CHIP == INTEL)
XX    /* Enable interrupts for both interrupt controller and device. */
XX    if (minor & 1)		/* COM2 on IRQ3 */
XX  	enable_irq(SECONDARY_IRQ);
XX***************
XX*** 348,353 ****
XX--- 475,494 ----
XX  	enable_irq(RS232_IRQ);
XX    out_byte(rs->int_enab_port, IE_LINE_STATUS_CHANGE | IE_MODEM_STATUS_CHANGE
XX  				| IE_RECEIVER_READY | IE_TRANSMITTER_READY);
XX+ #else /* MACHINE == ATARI */
XX+   /* Initialize the 68901 chip, then enable interrupts. */
XX+   MFP->mf_scr = 0x00;
XX+   MFP->mf_tcdcr |= T_Q004;
XX+   MFP->mf_rsr = R_ENA;
XX+   MFP->mf_tsr = T_ENA;
XX+   MFP->mf_aer = (MFP->mf_aer | (IO_SCTS|IO_SDCD)) ^
XX+ 		 (MFP->mf_gpip & (IO_SCTS|IO_SDCD));
XX+   MFP->mf_ddr = (MFP->mf_ddr & ~ (IO_SCTS|IO_SDCD));
XX+   MFP->mf_iera |= (IA_RRDY|IA_RERR|IA_TRDY|IA_TERR);
XX+   MFP->mf_imra |= (IA_RRDY|IA_RERR|IA_TRDY|IA_TERR);
XX+   MFP->mf_ierb |= (IB_SCTS|IB_SDCD);
XX+   MFP->mf_imrb |= (IB_SCTS|IB_SDCD);
XX+ #endif /* CHIP/MACHINE */
XX  
XX    /* Tell external device we are ready. */
XX    istart(rs);
XX***************
XX*** 488,493 ****
XX--- 629,635 ----
XX  /* Low level (interrupt) routines. */
XX  
XX  #if C_RS232_INT_HANDLERS
XX+ #if (CHIP == INTEL)
XX  /*==========================================================================*
XX   *				rs232_1handler				    *
XX   *==========================================================================*/
XX***************
XX*** 559,566 ****
XX--- 701,749 ----
XX    }
XX  #endif
XX  }
XX+ #else /* MACHINE == ATARI */
XX+ /*==========================================================================*
XX+  *				siaint					    *
XX+  *==========================================================================*/
XX+ PUBLIC void siaint(type)
XX+ int    type;	       /* interrupt type */
XX+ {
XX+ /* siaint is the rs232 interrupt procedure for Atari ST's. For ST there are
XX+  * as much as 5 interrupt lines used for rs232. The trap type byte left on the
XX+  * stack by the assembler interrupt handler identifies the interrupt cause.
XX+  */
XX  
XX+   register unsigned char  code;
XX+   register struct rs232_s *rs = &rs_lines[0];
XX+   int s = lock();
XX  
XX+   switch (type & 0x00FF)
XX+   {
XX+ 	case 0x00:	       /* receive buffer full */
XX+ 		in_int(rs);
XX+ 		break;
XX+ 	case 0x01:	       /* receive error */
XX+ 		line_int(rs);
XX+ 		break;
XX+ 	case 0x02:	       /* transmit buffer empty */
XX+ 		out_int(rs);
XX+ 		break;
XX+ 	case 0x03:	       /* transmit error */
XX+ 		code = MFP->mf_tsr;
XX+ 		if (code & ~(T_ENA | T_UE | T_EMPTY))
XX+ 		{
XX+ 		    printf("sia: transmit error: status=%x\r\n", code);
XX+ 		    /* MFP->mf_udr = lastchar; */ /* retry */
XX+ 		}
XX+ 		break;
XX+ 	case 0x04:		/* modem lines change */
XX+ 		modem_int(rs);
XX+ 		break;
XX+   }
XX+   restore(s);
XX+ }
XX+ #endif
XX+ 
XX  /*==========================================================================*
XX   *				in_int					    *
XX   *==========================================================================*/
XX***************
XX*** 570,583 ****
XX  /* Read the data which just arrived.
XX   * If it is the oxoff char, clear OSWREADY, else if OSWREADY was clear, set
XX   * it and restart output (any char does this, not just xon).
XX!  * Put data in the buffer if room, * otherwise discard it.
XX   * Set a flag for the clock interrupt handler to eventually notify TTY.
XX   */
XX  
XX    if (rs->ostate & ORAW)
XX  	*rs->iptr = in_byte(rs->recv_port);
XX    else if ( (*rs->iptr = in_byte(rs->recv_port)) == rs->oxoff)
XX  	rs->ostate &= ~OSWREADY;
XX    else if (!(rs->ostate & OSWREADY)) {
XX  	rs->ostate |= OSWREADY;
XX  	if (txready(rs)) out_int(rs);
XX--- 753,773 ----
XX  /* Read the data which just arrived.
XX   * If it is the oxoff char, clear OSWREADY, else if OSWREADY was clear, set
XX   * it and restart output (any char does this, not just xon).
XX!  * Put data in the buffer if room, otherwise discard it.
XX   * Set a flag for the clock interrupt handler to eventually notify TTY.
XX   */
XX  
XX+ #if (CHIP == INTEL)
XX    if (rs->ostate & ORAW)
XX  	*rs->iptr = in_byte(rs->recv_port);
XX    else if ( (*rs->iptr = in_byte(rs->recv_port)) == rs->oxoff)
XX  	rs->ostate &= ~OSWREADY;
XX+ #else /* MACHINE == ATARI */
XX+   if (rs->ostate & ORAW)
XX+ 	*rs->iptr = MFP->mf_udr;
XX+   else if ( (*rs->iptr = MFP->mf_udr) == rs->oxoff)
XX+ 	rs->ostate &= ~OSWREADY;
XX+ #endif /* CHIP/MACHINE */
XX    else if (!(rs->ostate & OSWREADY)) {
XX  	rs->ostate |= OSWREADY;
XX  	if (txready(rs)) out_int(rs);
XX***************
XX*** 597,603 ****
XX--- 787,799 ----
XX  {
XX  /* Check for and record errors. */
XX  
XX+ #if (CHIP == INTEL)
XX    rs->lstatus = in_byte(rs->line_status_port);
XX+ #else /* MACHINE == ATARI */
XX+   rs->lstatus = MFP->mf_rsr;
XX+   MFP->mf_rsr &= R_ENA;
XX+   rs->pad = MFP->mf_udr;	/* discard char in case of LS_OVERRUN_ERR */
XX+ #endif /* CHIP/MACHINE */
XX    if (rs->lstatus & LS_FRAMING_ERR) ++rs->framing_errors;
XX    if (rs->lstatus & LS_OVERRUN_ERR) ++rs->overrun_errors;
XX    if (rs->lstatus & LS_PARITY_ERR) ++rs->parity_errors;
XX***************
XX*** 615,620 ****
XX--- 811,821 ----
XX   * If the device just became ready, restart output.
XX   */
XX  
XX+ #if (MACHINE == ATARI)
XX+   /* Set active edge interrupt so that next change causes a new interrupt */
XX+   MFP->mf_aer = (MFP->mf_aer | (IO_SCTS|IO_SDCD)) ^
XX+ 		 (MFP->mf_gpip & (IO_SCTS|IO_SDCD));
XX+ #endif
XX    if (!devready(rs))
XX  	rs->ostate &= ~ODEVREADY;
XX    else if (!(rs->ostate & ODEVREADY)) {
XX***************
XX*** 639,651 ****
XX--- 840,860 ----
XX  
XX    if (rs->ostate >= (ODEVREADY | OQUEUED | OSWREADY)) {
XX  	/* Bit test allows ORAW and requires the others. */
XX+ #if (CHIP == INTEL)
XX  	out_byte(rs->xmit_port, *rs->optr);
XX+ #else /* MACHINE == ATARI */
XX+ 	MFP->mf_udr = *rs->optr;
XX+ #endif
XX  	if (++rs->optr >= rs->obufend) {
XX  		tty_events += EVENT_THRESHOLD;
XX  		rs->ostate ^= (ODONE | OQUEUED);  /* ODONE on, OQUEUED off */
XX+ #if (CHIP == INTEL)
XX  		unlock();	/* safe, for complicated reasons */
XX  		tty_wakeup();
XX  		lock();
XX+ #else
XX+ 		tty_wakeup();	/* not save, for unknown reasons !?! */
XX+ #endif
XX  	}
XX    }
XX  }
X/
Xecho x - system.c.d
Xsed '/^X/s///' > system.c.d << '/'
XX*** /home/top/ast/minix/1.5/kernel/system.c  crc=36389  32828	Sat Apr 21 22:26:23 1990
XX--- /home/top/ast/minix/1.6.25/kernel/system.c  crc=01198  41132	Mon Feb  1 21:10:22 1993
XX***************
XX*** 12,29 ****
XX   *   SYS_GETSP	 caller wants to read out some process' stack pointer
XX   *   SYS_TIMES	 caller wants to get accounting times for a process
XX   *   SYS_ABORT	 MM or FS cannot go on; abort MINIX
XX! #if (CHIP == M68000)
XX!  *   SYS_FRESH	 start with a fresh process image during EXEC
XX! #endif
XX!  *   SYS_SIG	 send a signal to a process
XX   *   SYS_KILL	 cause a signal to be sent via MM
XX!  *   SYS_COPY	 requests a block of data to be copied between processes
XX   *   SYS_GBOOT	 copies the boot parameters to a process
XX   *   SYS_UMAP	 compute the physical address for a given virtual address
XX   *   SYS_MEM	 returns the next free chunk of physical memory 
XX   *   SYS_TRACE	 request a trace operation
XX   *
XX!  * Message type m1 is used for all except SYS_SIG and SYS_COPY, both of
XX   * which need special parameter types.
XX   *
XX   *    m_type       PROC1     PROC2      PID     MEM_PTR   
XX--- 12,28 ----
XX   *   SYS_GETSP	 caller wants to read out some process' stack pointer
XX   *   SYS_TIMES	 caller wants to get accounting times for a process
XX   *   SYS_ABORT	 MM or FS cannot go on; abort MINIX
XX!  *   SYS_FRESH	 start with a fresh process image during EXEC (68000 only)
XX!  *   SYS_OLDSIG	 send a signal to a process
XX   *   SYS_KILL	 cause a signal to be sent via MM
XX!  *   SYS_COPY	 request a block of data to be copied between processes
XX!  *   SYS_VCOPY   request a series of data blocks to be copied between procs
XX   *   SYS_GBOOT	 copies the boot parameters to a process
XX   *   SYS_UMAP	 compute the physical address for a given virtual address
XX   *   SYS_MEM	 returns the next free chunk of physical memory 
XX   *   SYS_TRACE	 request a trace operation
XX   *
XX!  * Message type m1 is used for all except SYS_OLDSIG and SYS_COPY, both of
XX   * which need special parameter types.
XX   *
XX   *    m_type       PROC1     PROC2      PID     MEM_PTR   
XX***************
XX*** 41,54 ****
XX   * | SYS_TIMES  | proc nr |         | buf ptr |         |
XX   * |------------+---------+---------+---------+---------|
XX   * | SYS_ABORT  |         |         |         |         |
XX- #if (CHIP == M68000)
XX   * |------------+---------+---------+---------+---------|
XX   * | SYS_FRESH  | proc nr | data_cl |         |         |
XX- #endif
XX   * |------------+---------+---------+---------+---------|
XX   * | SYS_GBOOT  | proc nr |         |         | bootptr |
XX   * ------------------------------------------------------
XX   *
XX   *
XX   *    m_type       m2_i1     m2_i2     m2_l1     m2_l2     
XX   * ------------------------------------------------------
XX--- 40,61 ----
XX   * | SYS_TIMES  | proc nr |         | buf ptr |         |
XX   * |------------+---------+---------+---------+---------|
XX   * | SYS_ABORT  |         |         |         |         |
XX   * |------------+---------+---------+---------+---------|
XX   * | SYS_FRESH  | proc nr | data_cl |         |         |
XX   * |------------+---------+---------+---------+---------|
XX   * | SYS_GBOOT  | proc nr |         |         | bootptr |
XX   * ------------------------------------------------------
XX   *
XX+  *    m_type          m1_i1     m1_i2     m1_i3       m1_p1
XX+  * ----------------+---------+---------+---------+--------------
XX+  * | SYS_VCOPY     |  src p  |  dst p  | vec siz | vc addr     |
XX+  * |---------------+---------+---------+---------+-------------|
XX+  * | SYS_SENDSIG   | proc nr |         |         | smp         |
XX+  * |---------------+---------+---------+---------+-------------|
XX+  * | SYS_SIGRETURN | proc nr |         |         | scp         |
XX+  * |---------------+---------+---------+---------+-------------|
XX+  * | SYS_ENDSIG    | proc nr |         |         |             |
XX+  * -------------------------------------------------------------
XX   *
XX   *    m_type       m2_i1     m2_i2     m2_l1     m2_l2     
XX   * ------------------------------------------------------
XX***************
XX*** 58,64 ****
XX   *
XX   *    m_type       m6_i1     m6_i2     m6_i3     m6_f1     
XX   * ------------------------------------------------------
XX!  * | SYS_SIG    | proc_nr  |  sig    |         | handler |
XX   * ------------------------------------------------------
XX   * | SYS_KILL   | proc_nr  |  sig    |         |         |
XX   * ------------------------------------------------------
XX--- 65,71 ----
XX   *
XX   *    m_type       m6_i1     m6_i2     m6_i3     m6_f1     
XX   * ------------------------------------------------------
XX!  * | SYS_OLDSIG | proc_nr  |  sig    |         | handler |
XX   * ------------------------------------------------------
XX   * | SYS_KILL   | proc_nr  |  sig    |         |         |
XX   * ------------------------------------------------------
XX***************
XX*** 88,93 ****
XX--- 95,101 ----
XX  
XX  #include "kernel.h"
XX  #include <signal.h>
XX+ #include <sys/sigcontext.h>
XX  #include <minix/boot.h>
XX  #include <minix/callnr.h>
XX  #include <minix/com.h>
XX***************
XX*** 96,122 ****
XX  #include "protect.h"
XX  #endif
XX  
XX  PRIVATE message m;
XX  PRIVATE char sig_stuff[SIG_PUSH_BYTES];	/* used to send signals to processes */
XX  
XX! FORWARD int do_abort();
XX! FORWARD int do_copy();
XX! FORWARD int do_exec();
XX! FORWARD int do_fork();
XX! FORWARD int do_gboot();
XX! FORWARD int do_getsp();
XX! FORWARD int do_kill();
XX! FORWARD int do_mem();
XX! FORWARD int do_newmap();
XX! FORWARD int do_sig();
XX! FORWARD int do_times();
XX! FORWARD int do_trace();
XX! FORWARD int do_umap();
XX! FORWARD int do_xit();
XX  #if (CHIP == M68000)
XX! FORWARD void build_sig();
XX  #endif
XX  
XX  /*===========================================================================*
XX   *				sys_task				     *
XX   *===========================================================================*/
XX--- 104,143 ----
XX  #include "protect.h"
XX  #endif
XX  
XX+ /* PSW masks. */
XX+ #define IF_MASK 0x00000200
XX+ #define IOPL_MASK 0x003000
XX+ 
XX  PRIVATE message m;
XX  PRIVATE char sig_stuff[SIG_PUSH_BYTES];	/* used to send signals to processes */
XX  
XX! FORWARD _PROTOTYPE( int do_abort, (message *m_ptr) );
XX! FORWARD _PROTOTYPE( int do_copy, (message *m_ptr) );
XX! FORWARD _PROTOTYPE( int do_exec, (message *m_ptr) );
XX! FORWARD _PROTOTYPE( int do_fork, (message *m_ptr) );
XX! FORWARD _PROTOTYPE( int do_gboot, (message *m_ptr) );
XX! FORWARD _PROTOTYPE( int do_getsp, (message *m_ptr) );
XX! FORWARD _PROTOTYPE( int do_kill, (message *m_ptr) );
XX! FORWARD _PROTOTYPE( int do_mem, (message *m_ptr) );
XX! FORWARD _PROTOTYPE( int do_newmap, (message *m_ptr) );
XX! FORWARD _PROTOTYPE( int do_sendsig, (message *m_ptr) );
XX! FORWARD _PROTOTYPE( int do_oldsig, (message *m_ptr) );
XX! FORWARD _PROTOTYPE( int do_sigreturn, (message *m_ptr) );
XX! FORWARD _PROTOTYPE( int do_endsig, (message *m_ptr) );
XX! FORWARD _PROTOTYPE( int do_times, (message *m_ptr) );
XX! FORWARD _PROTOTYPE( int do_trace, (message *m_ptr) );
XX! FORWARD _PROTOTYPE( int do_umap, (message *m_ptr) );
XX! FORWARD _PROTOTYPE( int do_xit, (message *m_ptr) );
XX! FORWARD _PROTOTYPE( int do_vcopy, (message *m_ptr) );
XX! 
XX  #if (CHIP == M68000)
XX! FORWARD _PROTOTYPE( void build_sig, (char *sig_stuff,struct proc *rp,int sig));
XX  #endif
XX  
XX+ #if (SHADOWING == 1)
XX+ FORWARD _PROTOTYPE( int do_fresh, (message *m_ptr) );
XX+ #endif
XX+ 
XX  /*===========================================================================*
XX   *				sys_task				     *
XX   *===========================================================================*/
XX***************
XX*** 137,148 ****
XX  	    case SYS_GETSP:	r = do_getsp(&m);	break;
XX  	    case SYS_TIMES:	r = do_times(&m);	break;
XX  	    case SYS_ABORT:	r = do_abort(&m);	break;
XX! #if (CHIP == M68000)
XX  	    case SYS_FRESH:	r = do_fresh(&m);	break;
XX  #endif
XX! 	    case SYS_SIG:	r = do_sig(&m);		break;
XX  	    case SYS_KILL:	r = do_kill(&m);	break;
XX  	    case SYS_COPY:	r = do_copy(&m);	break;
XX  	    case SYS_GBOOT:	r = do_gboot(&m);	break;
XX  	    case SYS_UMAP:	r = do_umap(&m);	break;
XX  	    case SYS_MEM:	r = do_mem(&m);		break;
XX--- 158,173 ----
XX  	    case SYS_GETSP:	r = do_getsp(&m);	break;
XX  	    case SYS_TIMES:	r = do_times(&m);	break;
XX  	    case SYS_ABORT:	r = do_abort(&m);	break;
XX! #if (SHADOWING == 1)
XX  	    case SYS_FRESH:	r = do_fresh(&m);	break;
XX  #endif
XX! 	    case SYS_SENDSIG:	r = do_sendsig(&m);	break;
XX! 	    case SYS_ENDSIG:	r = do_endsig(&m);	break;
XX! 	    case SYS_SIGRETURN: r = do_sigreturn(&m);	break;
XX! 	    case SYS_OLDSIG:	r = do_oldsig(&m);	break;
XX  	    case SYS_KILL:	r = do_kill(&m);	break;
XX  	    case SYS_COPY:	r = do_copy(&m);	break;
XX+             case SYS_VCOPY:	r = do_vcopy(&m);	break;
XX  	    case SYS_GBOOT:	r = do_gboot(&m);	break;
XX  	    case SYS_UMAP:	r = do_umap(&m);	break;
XX  	    case SYS_MEM:	r = do_mem(&m);		break;
XX***************
XX*** 178,198 ****
XX    /* Copy parent 'proc' struct to child. */
XX  #if (CHIP == INTEL)
XX    old_ldt_sel = rpc->p_ldt_sel;	/* stop this being obliterated by copy */
XX!   *rpc = *rpp;
XX    rpc->p_ldt_sel = old_ldt_sel;
XX  #else
XX!   phys_copy( rpp, (phys_bytes)proc_addr(m_ptr->PROC2),
XX  	     (phys_bytes)sizeof(struct proc));
XX  #endif 
XX    rpc->p_nr = m_ptr->PROC2;	/* this was obliterated by copy */
XX  
XX! #if (CHIP != M68000)
XX    rpc->p_flags |= NO_MAP;	/* inhibit the process from running */
XX  #endif
XX    rpc->p_flags &= ~(PENDING | SIG_PENDING | P_STOP);
XX! 				/* only one in group should have PENDING */
XX! 				/* child does not inherit trace status */
XX!   rpc->p_pending = 0;
XX    rpc->p_pendcount = 0;
XX    rpc->p_pid = m_ptr->PID;	/* install child's pid */
XX    rpc->p_reg.retreg = 0;	/* child sees pid = 0 to know it is child */
XX--- 203,225 ----
XX    /* Copy parent 'proc' struct to child. */
XX  #if (CHIP == INTEL)
XX    old_ldt_sel = rpc->p_ldt_sel;	/* stop this being obliterated by copy */
XX!   memcpy((char *)rpc, (char *)rpp, sizeof(struct proc));
XX    rpc->p_ldt_sel = old_ldt_sel;
XX  #else
XX!   /* HACK because structure copy is or was slow. */
XX!   phys_copy( (phys_bytes)rpp, (phys_bytes)proc_addr(m_ptr->PROC2),
XX  	     (phys_bytes)sizeof(struct proc));
XX  #endif 
XX    rpc->p_nr = m_ptr->PROC2;	/* this was obliterated by copy */
XX  
XX! #if (SHADOWING == 0)
XX    rpc->p_flags |= NO_MAP;	/* inhibit the process from running */
XX  #endif
XX+ 
XX    rpc->p_flags &= ~(PENDING | SIG_PENDING | P_STOP);
XX! 
XX!   /* Only 1 in group should have PENDING, child does not inherit trace status*/
XX!   sigemptyset(&rpc->p_pending);
XX    rpc->p_pendcount = 0;
XX    rpc->p_pid = m_ptr->PID;	/* install child's pid */
XX    rpc->p_reg.retreg = 0;	/* child sees pid = 0 to know it is child */
XX***************
XX*** 201,210 ****
XX    rpc->sys_time = 0;
XX    rpc->child_utime = 0;
XX    rpc->child_stime = 0;
XX! #if (CHIP == M68000)
XX    rpc->p_nflips = 0;
XX    mkshadow(rpp, (phys_clicks)m_ptr->m1_p1);	/* run child first */
XX  #endif
XX    return(OK);
XX  }
XX  
XX--- 228,240 ----
XX    rpc->sys_time = 0;
XX    rpc->child_utime = 0;
XX    rpc->child_stime = 0;
XX! 
XX! #if (SHADOWING == 1)
XX    rpc->p_nflips = 0;
XX    mkshadow(rpp, (phys_clicks)m_ptr->m1_p1);	/* run child first */
XX  #endif
XX+ 
XX+   fork_name(m_ptr->PROC1, m_ptr->PROC2);
XX    return(OK);
XX  }
XX  
XX***************
XX*** 222,230 ****
XX    vir_bytes vmm, vsys, vn;
XX    int caller;			/* whose space has the new map (usually MM) */
XX    int k;			/* process whose map is to be loaded */
XX- #if (CHIP != M68000)
XX    int old_flags;		/* value of flags before modification */
XX- #endif
XX    struct mem_map *map_ptr;	/* virtual address of map inside caller (MM) */
XX  
XX    /* Extract message parameters and copy new memory map from MM. */
XX--- 252,258 ----
XX***************
XX*** 240,251 ****
XX    vsys = (vir_bytes) rp->p_map;	/* again, careful about sign extension */
XX    if ( (src_phys = umap(rsrc, D, vmm, vn)) == 0)
XX  	panic("bad call to sys_newmap (src)", NO_NUM);
XX!   if ( (dst_phys = umap(proc_ptr, D, vsys, vn)) == 0)
XX  	panic("bad call to sys_newmap (dst)", NO_NUM);
XX    phys_copy(src_phys, dst_phys, pn);
XX  
XX  #if (CHIP != M68000)
XX    alloc_segments(rp);
XX    old_flags = rp->p_flags;	/* save the previous value of the flags */
XX    rp->p_flags &= ~NO_MAP;
XX    if (old_flags != 0 && rp->p_flags == 0) lock_ready(rp);
XX--- 268,283 ----
XX    vsys = (vir_bytes) rp->p_map;	/* again, careful about sign extension */
XX    if ( (src_phys = umap(rsrc, D, vmm, vn)) == 0)
XX  	panic("bad call to sys_newmap (src)", NO_NUM);
XX!   if ( (dst_phys = umap(proc_addr(SYSTASK), D, vsys, vn)) == 0)
XX  	panic("bad call to sys_newmap (dst)", NO_NUM);
XX    phys_copy(src_phys, dst_phys, pn);
XX  
XX+ #if (SHADOWING == 0)
XX  #if (CHIP != M68000)
XX    alloc_segments(rp);
XX+ #else 
XX+   pmmu_init_proc(rp);
XX+ #endif
XX    old_flags = rp->p_flags;	/* save the previous value of the flags */
XX    rp->p_flags &= ~NO_MAP;
XX    if (old_flags != 0 && rp->p_flags == 0) lock_ready(rp);
XX***************
XX*** 274,286 ****
XX  #if (CHIP == M68000)
XX    rp->p_splow = (reg_t) sp;	/* set the stack pointer low water */
XX    rp->p_reg.pc = (reg_t) ((vir_bytes)rp->p_map[T].mem_vir << CLICK_SHIFT);
XX  #else
XX!   rp->p_reg.pc = 0;		/* reset pc */
XX  #endif
XX    rp->p_alarm = 0;		/* reset alarm timer */
XX    rp->p_flags &= ~RECEIVING;	/* MM does not reply to EXEC call */
XX    if (rp->p_flags == 0) lock_ready(rp);
XX!   set_name(m_ptr->PROC1, (char *)sp); /* save command string for F1 display */
XX    return(OK);
XX  }
XX  
XX--- 306,323 ----
XX  #if (CHIP == M68000)
XX    rp->p_splow = (reg_t) sp;	/* set the stack pointer low water */
XX    rp->p_reg.pc = (reg_t) ((vir_bytes)rp->p_map[T].mem_vir << CLICK_SHIFT);
XX+ #ifdef FPP
XX+   /* Initialize fpp for this process */
XX+   fpp_new_state(rp);
XX+ #endif
XX  #else
XX!   rp->p_reg.pc = (reg_t) m_ptr->IP_PTR;	/* reset pc */
XX  #endif
XX    rp->p_alarm = 0;		/* reset alarm timer */
XX    rp->p_flags &= ~RECEIVING;	/* MM does not reply to EXEC call */
XX    if (rp->p_flags == 0) lock_ready(rp);
XX!   set_name(m_ptr->m_source, m_ptr->PROC1, m_ptr->NAME_PTR);
XX! 	/* save command string for F1 display */
XX    return(OK);
XX  }
XX  
XX***************
XX*** 297,305 ****
XX    struct proc *np, *xp;
XX    int parent;			/* number of exiting proc's parent */
XX    int proc_nr;			/* number of process doing the exit */
XX- #if (CHIP == M68000)
XX    phys_clicks base, size;
XX- #endif
XX  
XX    parent = m_ptr->PROC1;	/* slot number of parent process */
XX    proc_nr = m_ptr->PROC2;	/* slot number of exiting process */
XX--- 334,340 ----
XX***************
XX*** 312,324 ****
XX    unlock();
XX    rc->p_alarm = 0;		/* turn off alarm timer */
XX    if (rc->p_flags == 0) lock_unready(rc);
XX! #if (CHIP == M68000)
XX    rmshadow(rc, &base, &size);
XX    m_ptr->m1_i1 = (int)base;
XX    m_ptr->m1_i2 = (int)size;
XX  #endif
XX-   set_name(proc_nr, (char *) 0);	/* disable command printing for F1 */
XX  
XX    /* If the process being terminated happens to be queued trying to send a
XX     * message (i.e., the process was killed by a signal, rather than it doing an
XX     * EXIT), then it must be removed from the message queues.
XX--- 347,361 ----
XX    unlock();
XX    rc->p_alarm = 0;		/* turn off alarm timer */
XX    if (rc->p_flags == 0) lock_unready(rc);
XX! 
XX! #if (SHADOWING == 1)
XX    rmshadow(rc, &base, &size);
XX    m_ptr->m1_i1 = (int)base;
XX    m_ptr->m1_i2 = (int)size;
XX  #endif
XX  
XX+   set_name(proc_nr, proc_nr, (char *)0);      /* disable cmd printing for F1 */
XX+ 
XX    /* If the process being terminated happens to be queued trying to send a
XX     * message (i.e., the process was killed by a signal, rather than it doing an
XX     * EXIT), then it must be removed from the message queues.
XX***************
XX*** 344,351 ****
XX  		}
XX  	}
XX    }
XX    if (rc->p_flags & PENDING) --sig_procs;
XX!   rc->p_pending = 0;
XX    rc->p_pendcount = 0;
XX    rc->p_flags = P_SLOT_FREE;
XX    return(OK);
XX--- 381,392 ----
XX  		}
XX  	}
XX    }
XX+ #if (CHIP == M68000) && (SHADOWING == 0)
XX+   pmmu_delete(rc);	/* we're done remove tables */
XX+ #endif
XX+ 
XX    if (rc->p_flags & PENDING) --sig_procs;
XX!   sigemptyset(&rc->p_pending);
XX    rc->p_pendcount = 0;
XX    rc->p_flags = P_SLOT_FREE;
XX    return(OK);
XX***************
XX*** 364,370 ****
XX  
XX    if (!isoksusern(m_ptr->PROC1)) return(E_BAD_PROC);
XX    rp = proc_addr(m_ptr->PROC1);
XX!   m.STACK_PTR = (char *) rp->p_reg.sp;	/* return sp here (bad type) */
XX    return(OK);
XX  }
XX  
XX--- 405,411 ----
XX  
XX    if (!isoksusern(m_ptr->PROC1)) return(E_BAD_PROC);
XX    rp = proc_addr(m_ptr->PROC1);
XX!   m_ptr->STACK_PTR = (char *) rp->p_reg.sp;	/* return sp here (bad type) */
XX    return(OK);
XX  }
XX  
XX***************
XX*** 382,394 ****
XX    if (!isoksusern(m_ptr->PROC1)) return E_BAD_PROC;
XX    rp = proc_addr(m_ptr->PROC1);
XX  
XX!   /* Insert the four times needed by the TIMES system call in the message. */
XX!   lock();
XX    m_ptr->USER_TIME   = rp->user_time;
XX    m_ptr->SYSTEM_TIME = rp->sys_time;
XX    unlock();
XX    m_ptr->CHILD_UTIME = rp->child_utime;
XX    m_ptr->CHILD_STIME = rp->child_stime;
XX    return(OK);
XX  }
XX  
XX--- 423,436 ----
XX    if (!isoksusern(m_ptr->PROC1)) return E_BAD_PROC;
XX    rp = proc_addr(m_ptr->PROC1);
XX  
XX!   /* Insert the times needed by the TIMES system call in the message. */
XX!   lock();			/* halt the volatile time counters in rp */
XX    m_ptr->USER_TIME   = rp->user_time;
XX    m_ptr->SYSTEM_TIME = rp->sys_time;
XX    unlock();
XX    m_ptr->CHILD_UTIME = rp->child_utime;
XX    m_ptr->CHILD_STIME = rp->child_stime;
XX+   m_ptr->BOOT_TICKS  = get_uptime();
XX    return(OK);
XX  }
XX  
XX***************
XX*** 406,412 ****
XX  }
XX  
XX  
XX! #if (CHIP == M68000)
XX  /*===========================================================================*
XX   *				do_fresh				     * 
XX   *===========================================================================*/
XX--- 448,454 ----
XX  }
XX  
XX  
XX! #if (SHADOWING == 1)
XX  /*===========================================================================*
XX   *				do_fresh				     * 
XX   *===========================================================================*/
XX***************
XX*** 414,427 ****
XX  message *m_ptr;			/* pointer to request message */
XX  {
XX  /* Handle sys_fresh.  Start with fresh process image during EXEC. */
XX    register struct proc *p;
XX    int proc_nr;			/* number of process doing the exec */
XX    phys_clicks base, size;
XX    phys_clicks c1, nc;
XX  
XX    proc_nr = m_ptr->PROC1;	/* slot number of exec-ing process */
XX!   if (proc_nr < 0 || proc_nr >= NR_PROCS)
XX! 	return(E_BAD_PROC);
XX    p = proc_addr(proc_nr);
XX    rmshadow(p, &base, &size);
XX    do_newmap(m_ptr);
XX--- 456,469 ----
XX  message *m_ptr;			/* pointer to request message */
XX  {
XX  /* Handle sys_fresh.  Start with fresh process image during EXEC. */
XX+ 
XX    register struct proc *p;
XX    int proc_nr;			/* number of process doing the exec */
XX    phys_clicks base, size;
XX    phys_clicks c1, nc;
XX  
XX    proc_nr = m_ptr->PROC1;	/* slot number of exec-ing process */
XX!   if (!isokprocn(proc_nr)) return(E_BAD_PROC);
XX    p = proc_addr(proc_nr);
XX    rmshadow(p, &base, &size);
XX    do_newmap(m_ptr);
XX***************
XX*** 434,472 ****
XX    m_ptr->m1_i2 = (int)size;
XX    return(OK);
XX  }
XX! #endif /* (CHIP == M68000) */
XX  
XX- 
XX  /*===========================================================================*
XX!  *				do_sig					     * 
XX   *===========================================================================*/
XX! PRIVATE int do_sig(m_ptr)
XX  message *m_ptr;			/* pointer to request message */
XX  {
XX  /* Handle sys_sig(). Signal a process.  The stack is known to be big enough. */
XX  
XX    register struct proc *rp;
XX    phys_bytes src_phys, dst_phys;
XX    vir_bytes vir_addr, sig_size, new_sp;
XX!   int proc_nr;			/* process number */
XX!   int sig;			/* signal number 1-16 */
XX!   void (*sig_handler)();	/* pointer to the signal handler */
XX  
XX    /* Extract parameters and prepare to build the words that get pushed. */
XX!   proc_nr = m_ptr->PR;		/* process being signalled */
XX!   if (!isokusern(proc_nr)) return(E_BAD_PROC);
XX!   rp = proc_addr(proc_nr);
XX!   sig = m_ptr->SIGNUM;		/* signal number, 1 to 16 */
XX!   if (sig == -1) {
XX! 	/* Except -1 is kludged to mean "finished one KSIG". */
XX! 	if (rp->p_pendcount != 0 &&
XX! 	    --rp->p_pendcount == 0 &&
XX! 	    (rp->p_flags &= ~SIG_PENDING) == 0)
XX! 		lock_ready(rp);
XX! 	return(OK);
XX!   }
XX    sig_handler = m_ptr->FUNC;	/* run time system addr for catching sigs */
XX!   vir_addr = (vir_bytes) sig_stuff;	/* info to be pushed is in 'sig_stuff' */
XX    new_sp = (vir_bytes) rp->p_reg.sp;
XX  
XX    /* Actually build the block of words to push onto the stack. */
XX--- 476,629 ----
XX    m_ptr->m1_i2 = (int)size;
XX    return(OK);
XX  }
XX! #endif /* (SHADOWING == 1) */
XX  
XX  /*===========================================================================*
XX!  *			      do_sendsig				     *
XX   *===========================================================================*/
XX! struct sigframe {
XX!   _PROTOTYPE( void (*sf_retadr), (void) );
XX!   int sf_signo;
XX!   int sf_code;
XX!   struct sigcontext *sf_scp;
XX!   struct sigcontext *sf_scpcopy;
XX! };
XX! 
XX! PRIVATE int do_sendsig(m_ptr)
XX  message *m_ptr;			/* pointer to request message */
XX  {
XX+   struct sigmsg smsg;
XX+   register struct proc *rp;
XX+   phys_bytes src_phys, dst_phys;
XX+   struct sigcontext sc, *scp;
XX+   struct sigframe fr, *frp;
XX+ 
XX+   if (!isokusern(m_ptr->PROC1)) return(E_BAD_PROC);
XX+   rp = proc_addr(m_ptr->PROC1);
XX+ 
XX+   /* Get the sigmsg structure into our address space.  */
XX+   src_phys = umap(proc_addr(MM_PROC_NR), D, (vir_bytes) m_ptr->SIG_CTXT_PTR,
XX+ 		  (vir_bytes) sizeof(struct sigmsg));
XX+   if (src_phys == 0)
XX+ 	panic("do_sendsig can't signal: bad sigmsg address from MM", NO_NUM);
XX+   dst_phys = umap(proc_addr(SYSTASK), S, (vir_bytes) &smsg,
XX+ 		  (vir_bytes) sizeof(struct sigmsg));
XX+   phys_copy(src_phys, dst_phys, (phys_bytes) sizeof(struct sigmsg));
XX+ 
XX+   /* Compute the usr stack pointer value where sigcontext will be stored. */
XX+   scp = (struct sigcontext *) smsg.sm_stkptr - 1;
XX+ 
XX+   /* Copy the registers to the sigcontext structure. */
XX+   memcpy(&sc.sc_regs, &rp->p_reg, sizeof(struct sigregs));
XX+ 
XX+   /* Finish the sigcontext initialization. */
XX+   sc.sc_flags = SC_SIGCONTEXT;
XX+ 
XX+   sc.sc_mask = smsg.sm_mask;
XX+ 
XX+   /* Copy the sigcontext structure to the user's stack. */
XX+   src_phys = umap(proc_addr(SYSTASK), S, (vir_bytes) &sc,
XX+ 		  (vir_bytes) sizeof(struct sigcontext));
XX+   dst_phys = umap(rp, D, (vir_bytes) scp,
XX+ 		  (vir_bytes) sizeof(struct sigcontext));
XX+   if (dst_phys == 0) return(EFAULT);
XX+   phys_copy(src_phys, dst_phys, (phys_bytes) sizeof(struct sigcontext));
XX+ 
XX+   /* Initialize the sigframe structure. */
XX+   frp = (struct sigframe *) scp - 1;
XX+   fr.sf_signo = smsg.sm_signo;
XX+   fr.sf_code = 0;	/* XXX - should be used for type of FP exception */
XX+   fr.sf_scp = scp;
XX+   fr.sf_scpcopy = scp;
XX+   fr.sf_retadr = (void (*)()) smsg.sm_sigreturn;
XX+ 
XX+   /* Copy the sigframe structure to the user's stack. */
XX+   src_phys = umap(proc_addr(SYSTASK), D, (vir_bytes) &fr,
XX+ 		  (vir_bytes) sizeof(struct sigframe));
XX+   dst_phys = umap(rp, D, (vir_bytes) frp, (vir_bytes) sizeof(struct sigframe));
XX+   if (dst_phys == 0) return(EFAULT);
XX+   phys_copy(src_phys, dst_phys, (phys_bytes) sizeof(struct sigframe));
XX+ 
XX+   /* Reset user registers to execute the signal handler. */
XX+   rp->p_reg.sp = (reg_t) frp;
XX+   rp->p_reg.pc = (reg_t) smsg.sm_sighandler;
XX+ 
XX+   return(OK);
XX+ }
XX+ 
XX+ /*===========================================================================*
XX+  *			      do_sigreturn				     *
XX+  *===========================================================================*/
XX+ PRIVATE int do_sigreturn(m_ptr)
XX+ register message *m_ptr;
XX+ {
XX+   struct sigcontext sc;
XX+   register struct proc *rp;
XX+   phys_bytes src_phys, dst_phys;
XX+ 
XX+   if (!isokusern(m_ptr->PROC1)) return(E_BAD_PROC);
XX+   rp = proc_addr(m_ptr->PROC1);
XX+ 
XX+   /* Copy in the sigcontext structure. */
XX+   src_phys = umap(rp, D, (vir_bytes) m_ptr->SIG_CTXT_PTR,
XX+ 		  (vir_bytes) sizeof(struct sigcontext));
XX+   if (src_phys == 0) return(EFAULT);
XX+   dst_phys = umap(proc_addr(SYSTASK), S, (vir_bytes) &sc,
XX+ 		  (vir_bytes) sizeof(struct sigcontext));
XX+   phys_copy(src_phys, dst_phys, (phys_bytes) sizeof(struct sigcontext));
XX+ 
XX+   /* Make sure that this is not just a jmp_buf. */
XX+   if ((sc.sc_flags & SC_SIGCONTEXT) == 0) return(EINVAL);
XX+ 
XX+   /* Fix up only certain key registers if the compiler doesn't use
XX+    * register variables within functions containing setjmp.
XX+    */
XX+   if (sc.sc_flags & SC_NOREGLOCALS) {
XX+ 	rp->p_reg.retreg = sc.sc_retreg;
XX+ 	rp->p_reg.fp = sc.sc_fp;
XX+ 	rp->p_reg.pc = sc.sc_pc;
XX+ 	rp->p_reg.sp = sc.sc_sp;
XX+ 	return (OK);
XX+   }
XX+   sc.sc_psw  = rp->p_reg.psw;
XX+ 
XX+ #if (CHIP == INTEL)
XX+   /* Don't panic kernel if user gave bad selectors. */
XX+   sc.sc_cs = rp->p_reg.cs;
XX+   sc.sc_ds = rp->p_reg.ds;
XX+   sc.sc_es = rp->p_reg.es;
XX+ #if INTEL_32BITS
XX+   sc.sc_fs = rp->p_reg.fs;
XX+   sc.sc_gs = rp->p_reg.gs;
XX+ #endif
XX+ #endif
XX+ 
XX+   /* Restore the registers. */
XX+   memcpy(&rp->p_reg, (char *)&sc.sc_regs, sizeof(struct sigregs));
XX+ 
XX+   return(OK);	
XX+ }
XX+ 
XX+ /*===========================================================================*
XX+  *				do_oldsig				     *
XX+  *===========================================================================*/
XX+ PRIVATE int do_oldsig(m_ptr)
XX+ register message *m_ptr;	/* pointer to request message */
XX+ {
XX  /* Handle sys_sig(). Signal a process.  The stack is known to be big enough. */
XX  
XX    register struct proc *rp;
XX    phys_bytes src_phys, dst_phys;
XX    vir_bytes vir_addr, sig_size, new_sp;
XX!   int sig;			/* signal number, 1 to _NSIG */
XX!   sighandler_t sig_handler;	/* pointer to the signal handler */
XX  
XX    /* Extract parameters and prepare to build the words that get pushed. */
XX!   if (!isokusern(m_ptr->PR)) return(E_BAD_PROC);
XX!   rp = proc_addr(m_ptr->PR);
XX!   sig = m_ptr->SIGNUM;
XX    sig_handler = m_ptr->FUNC;	/* run time system addr for catching sigs */
XX!   vir_addr = (vir_bytes) sig_stuff;	/* info to be pushed is in sig_stuff */
XX    new_sp = (vir_bytes) rp->p_reg.sp;
XX  
XX    /* Actually build the block of words to push onto the stack. */
XX***************
XX*** 475,483 ****
XX    /* Prepare to do the push, and do it. */
XX    sig_size = SIG_PUSH_BYTES;
XX    new_sp -= sig_size;
XX!   src_phys = umap(proc_ptr, D, vir_addr, sig_size);
XX    dst_phys = umap(rp, S, new_sp, sig_size);
XX!   if (dst_phys == 0) panic("do_sig can't signal; SP bad", NO_NUM);
XX    phys_copy(src_phys, dst_phys, (phys_bytes) sig_size);	/* push pc, psw */
XX  
XX    /* Change process' sp and pc to reflect the interrupt. */
XX--- 632,640 ----
XX    /* Prepare to do the push, and do it. */
XX    sig_size = SIG_PUSH_BYTES;
XX    new_sp -= sig_size;
XX!   src_phys = umap(proc_addr(SYSTASK), D, vir_addr, sig_size);
XX    dst_phys = umap(rp, S, new_sp, sig_size);
XX!   if (dst_phys == 0) panic("do_oldsig can't signal; SP bad", NO_NUM);
XX    phys_copy(src_phys, dst_phys, (phys_bytes) sig_size);	/* push pc, psw */
XX  
XX    /* Change process' sp and pc to reflect the interrupt. */
XX***************
XX*** 486,507 ****
XX    return(OK);
XX  }
XX  
XX  
XX! /*===========================================================================
XX!  *				do_kill					     * 
XX   *===========================================================================*/
XX  PRIVATE int do_kill(m_ptr)
XX! message *m_ptr;			/* pointer to request message */
XX  {
XX  /* Handle sys_kill(). Cause a signal to be sent to a process via MM. */
XX  
XX!   int proc_nr;			/* process number */
XX!   int sig;			/* signal number 1-16 */
XX! 
XX!   proc_nr = m_ptr->PR;		/* process being signalled */
XX!   sig = m_ptr->SIGNUM;		/* signal number, 1 to 16 */
XX!   if (!isokusern(proc_nr)) return(E_BAD_PROC);
XX!   cause_sig(proc_nr, sig);
XX    return(OK);
XX  }
XX  
XX--- 643,676 ----
XX    return(OK);
XX  }
XX  
XX+ /*===========================================================================*
XX+  *			      do_endsig 				     *
XX+  *===========================================================================*/
XX+ PRIVATE int do_endsig(m_ptr)
XX+ register message *m_ptr;	/* pointer to request message */
XX+ {
XX+   register struct proc *rp;
XX  
XX!   if (!isokusern(m_ptr->PROC1)) return(E_BAD_PROC);
XX!   rp = proc_addr(m_ptr->PROC1);
XX! 
XX!   /* MM has finished one KSIG. */
XX!   if (rp->p_pendcount != 0 && --rp->p_pendcount == 0
XX!       && (rp->p_flags &= ~SIG_PENDING) == 0)
XX! 	lock_ready(rp);
XX!   return(OK);
XX! }
XX! 
XX! /*===========================================================================*
XX!  *				do_kill					     *
XX   *===========================================================================*/
XX  PRIVATE int do_kill(m_ptr)
XX! register message *m_ptr;	/* pointer to request message */
XX  {
XX  /* Handle sys_kill(). Cause a signal to be sent to a process via MM. */
XX  
XX!   if (!isokusern(m_ptr->PR)) return(E_BAD_PROC);
XX!   cause_sig(m_ptr->PR, m_ptr->SIGNUM);
XX    return(OK);
XX  }
XX  
XX***************
XX*** 510,523 ****
XX   *				do_trace				    *
XX   *==========================================================================*/
XX  
XX! #define PROCNR	(m->m2_i1)
XX! #define REQUEST (m->m2_i2)
XX! #define ADDR	((vir_bytes) m->m2_l1)
XX! #define DATA	(m->m2_l2)
XX  #define VLSIZE	((vir_bytes) sizeof(long))
XX  
XX! PRIVATE int do_trace(m)
XX! register message *m;
XX  {
XX    register struct proc *rp;
XX    phys_bytes src, dst;
XX--- 679,692 ----
XX   *				do_trace				    *
XX   *==========================================================================*/
XX  
XX! #define PROCNR	(m_ptr->m2_i1)
XX! #define REQUEST	(m_ptr->m2_i2)
XX! #define ADDR	((vir_bytes) m_ptr->m2_l1)
XX! #define DATA	(m_ptr->m2_l2)
XX  #define VLSIZE	((vir_bytes) sizeof(long))
XX  
XX! PRIVATE int do_trace(m_ptr)
XX! register message *m_ptr;
XX  {
XX    register struct proc *rp;
XX    phys_bytes src, dst;
XX***************
XX*** 527,570 ****
XX    if (rp->p_flags & P_SLOT_FREE) return(EIO);
XX    switch (REQUEST) {
XX    case -1:			/* stop process */
XX! 	lock_unready(rp);
XX  	rp->p_flags |= P_STOP;
XX  	rp->p_reg.psw &= ~TRACEBIT;	/* clear trace bit */
XX  	return(OK);
XX    case 1:			/* return value from instruction space */
XX  	if (rp->p_map[T].mem_len != 0) {
XX  		if ((src = umap(rp, T, ADDR, VLSIZE)) == 0) return(EIO);
XX! 		dst = umap(proc_ptr, D, (vir_bytes) &DATA, VLSIZE);
XX  		phys_copy(src, dst, (phys_bytes) sizeof(long));
XX  		break;
XX  	}
XX  	/* Text space is actually data space - fall through. */
XX    case 2:			/* return value from data space */
XX  	if ((src = umap(rp, D, ADDR, VLSIZE)) == 0) return(EIO);
XX! 	dst = umap(proc_ptr, D, (vir_bytes) &DATA, VLSIZE);
XX  	phys_copy(src, dst, (phys_bytes) sizeof(long));
XX  	break;
XX    case 3:			/* return value from process table */
XX  	if ((ADDR & (sizeof(long) - 1)) != 0 ||
XX  	    ADDR > sizeof(struct proc) - sizeof(long))
XX  		return(EIO);
XX  	DATA = *(long *) ((char *) rp + (int) ADDR);
XX  	break;
XX    case 4:			/* set value from instruction space */
XX  	if (rp->p_map[T].mem_len != 0) {
XX  		if ((dst = umap(rp, T, ADDR, VLSIZE)) == 0) return(EIO);
XX! 		src = umap(proc_ptr, D, (vir_bytes) &DATA, VLSIZE);
XX  		phys_copy(src, dst, (phys_bytes) sizeof(long));
XX  		DATA = 0;
XX  		break;
XX  	}
XX  	/* Text space is actually data space - fall through. */
XX    case 5:			/* set value from data space */
XX  	if ((dst = umap(rp, D, ADDR, VLSIZE)) == 0) return(EIO);
XX! 	src = umap(proc_ptr, D, (vir_bytes) &DATA, VLSIZE);
XX  	phys_copy(src, dst, (phys_bytes) sizeof(long));
XX  	DATA = 0;
XX  	break;
XX    case 6:			/* set value in process table */
XX  	if ((ADDR & (sizeof(reg_t) - 1)) != 0 ||
XX  	     ADDR > sizeof(struct stackframe_s) - sizeof(reg_t))
XX--- 696,745 ----
XX    if (rp->p_flags & P_SLOT_FREE) return(EIO);
XX    switch (REQUEST) {
XX    case -1:			/* stop process */
XX! 	if (rp->p_flags == 0) lock_unready(rp);
XX  	rp->p_flags |= P_STOP;
XX  	rp->p_reg.psw &= ~TRACEBIT;	/* clear trace bit */
XX  	return(OK);
XX+ 
XX    case 1:			/* return value from instruction space */
XX  	if (rp->p_map[T].mem_len != 0) {
XX  		if ((src = umap(rp, T, ADDR, VLSIZE)) == 0) return(EIO);
XX! 		dst = umap(proc_addr(SYSTASK), D, (vir_bytes) &DATA, VLSIZE);
XX  		phys_copy(src, dst, (phys_bytes) sizeof(long));
XX  		break;
XX  	}
XX  	/* Text space is actually data space - fall through. */
XX+ 
XX    case 2:			/* return value from data space */
XX  	if ((src = umap(rp, D, ADDR, VLSIZE)) == 0) return(EIO);
XX! 	dst = umap(proc_addr(SYSTASK), D, (vir_bytes) &DATA, VLSIZE);
XX  	phys_copy(src, dst, (phys_bytes) sizeof(long));
XX  	break;
XX+ 
XX    case 3:			/* return value from process table */
XX  	if ((ADDR & (sizeof(long) - 1)) != 0 ||
XX  	    ADDR > sizeof(struct proc) - sizeof(long))
XX  		return(EIO);
XX  	DATA = *(long *) ((char *) rp + (int) ADDR);
XX  	break;
XX+ 
XX    case 4:			/* set value from instruction space */
XX  	if (rp->p_map[T].mem_len != 0) {
XX  		if ((dst = umap(rp, T, ADDR, VLSIZE)) == 0) return(EIO);
XX! 		src = umap(proc_addr(SYSTASK), D, (vir_bytes) &DATA, VLSIZE);
XX  		phys_copy(src, dst, (phys_bytes) sizeof(long));
XX  		DATA = 0;
XX  		break;
XX  	}
XX  	/* Text space is actually data space - fall through. */
XX+ 
XX    case 5:			/* set value from data space */
XX  	if ((dst = umap(rp, D, ADDR, VLSIZE)) == 0) return(EIO);
XX! 	src = umap(proc_addr(SYSTASK), D, (vir_bytes) &DATA, VLSIZE);
XX  	phys_copy(src, dst, (phys_bytes) sizeof(long));
XX  	DATA = 0;
XX  	break;
XX+ 
XX    case 6:			/* set value in process table */
XX  	if ((ADDR & (sizeof(reg_t) - 1)) != 0 ||
XX  	     ADDR > sizeof(struct stackframe_s) - sizeof(reg_t))
XX***************
XX*** 587,608 ****
XX  #endif
XX  	if (i == (int) &((struct proc *) 0)->p_reg.psw)
XX  		/* only selected bits are changeable */
XX! 		SETBITS(rp, DATA);
XX  	else
XX  		*(reg_t *) ((char *) &rp->p_reg + i) = (reg_t) DATA;
XX  	DATA = 0;
XX  	break;
XX    case 7:			/* resume execution */
XX  	rp->p_flags &= ~P_STOP;
XX  	if (rp->p_flags == 0) lock_ready(rp);
XX  	DATA = 0;
XX  	break;
XX    case 9:			/* set trace bit */
XX  	rp->p_reg.psw |= TRACEBIT;
XX  	rp->p_flags &= ~P_STOP;
XX  	if (rp->p_flags == 0) lock_ready(rp);
XX  	DATA = 0;
XX  	break;
XX    default:
XX  	return(EIO);
XX    }
XX--- 762,786 ----
XX  #endif
XX  	if (i == (int) &((struct proc *) 0)->p_reg.psw)
XX  		/* only selected bits are changeable */
XX! 		SETPSW(rp, DATA);
XX  	else
XX  		*(reg_t *) ((char *) &rp->p_reg + i) = (reg_t) DATA;
XX  	DATA = 0;
XX  	break;
XX+ 
XX    case 7:			/* resume execution */
XX  	rp->p_flags &= ~P_STOP;
XX  	if (rp->p_flags == 0) lock_ready(rp);
XX  	DATA = 0;
XX  	break;
XX+ 
XX    case 9:			/* set trace bit */
XX  	rp->p_reg.psw |= TRACEBIT;
XX  	rp->p_flags &= ~P_STOP;
XX  	if (rp->p_flags == 0) lock_ready(rp);
XX  	DATA = 0;
XX  	break;
XX+ 
XX    default:
XX  	return(EIO);
XX    }
XX***************
XX*** 632,650 ****
XX    bytes = (phys_bytes) m_ptr->COPY_BYTES;
XX  
XX    /* Compute the source and destination addresses and do the copy. */
XX! #if (CHIP != M68000)
XX    if (src_proc == ABS)
XX  	src_phys = (phys_bytes) m_ptr->SRC_BUFFER;
XX!   else
XX  #endif
XX- 	src_phys = umap(proc_addr(src_proc),src_space,src_vir,(vir_bytes)bytes);
XX  
XX! #if (CHIP != M68000)
XX    if (dst_proc == ABS)
XX  	dst_phys = (phys_bytes) m_ptr->DST_BUFFER;
XX    else
XX  #endif
XX! 	dst_phys = umap(proc_addr(dst_proc),dst_space,dst_vir,(vir_bytes)bytes);
XX  
XX    if (src_phys == 0 || dst_phys == 0) return(EFAULT);
XX    phys_copy(src_phys, dst_phys, bytes);
XX--- 810,840 ----
XX    bytes = (phys_bytes) m_ptr->COPY_BYTES;
XX  
XX    /* Compute the source and destination addresses and do the copy. */
XX! #if (SHADOWING == 0)
XX    if (src_proc == ABS)
XX  	src_phys = (phys_bytes) m_ptr->SRC_BUFFER;
XX!   else {
XX! 	if (bytes != (vir_bytes) bytes)
XX! 		/* This would happen for 64K segments and 16-bit vir_bytes.
XX! 		 * It would happen a lot for do_fork except MM uses ABS
XX! 		 * copies for that case.
XX! 		 */
XX! 		panic("overflow in count in do_copy", NO_NUM);
XX  #endif
XX  
XX! 	src_phys = umap(proc_addr(src_proc), src_space, src_vir,
XX! 			(vir_bytes) bytes);
XX! #if (SHADOWING == 0)
XX! 	}
XX! #endif
XX! 
XX! #if (SHADOWING == 0)
XX    if (dst_proc == ABS)
XX  	dst_phys = (phys_bytes) m_ptr->DST_BUFFER;
XX    else
XX  #endif
XX! 	dst_phys = umap(proc_addr(dst_proc), dst_space, dst_vir,
XX! 			(vir_bytes) bytes);
XX  
XX    if (src_phys == 0 || dst_phys == 0) return(EFAULT);
XX    phys_copy(src_phys, dst_phys, bytes);
XX***************
XX*** 657,663 ****
XX   *===========================================================================*/
XX  PUBLIC void cause_sig(proc_nr, sig_nr)
XX  int proc_nr;			/* process to be signalled */
XX! int sig_nr;			/* signal to be sent in range 1 - 16 */
XX  {
XX  /* A task wants to send a signal to a process.   Examples of such tasks are:
XX   *   TTY wanting to cause SIGINT upon getting a DEL
XX--- 847,853 ----
XX   *===========================================================================*/
XX  PUBLIC void cause_sig(proc_nr, sig_nr)
XX  int proc_nr;			/* process to be signalled */
XX! int sig_nr;			/* signal to be sent, 1 to _NSIG */
XX  {
XX  /* A task wants to send a signal to a process.   Examples of such tasks are:
XX   *   TTY wanting to cause SIGINT upon getting a DEL
XX***************
XX*** 676,684 ****
XX    register struct proc *rp, *mmp;
XX  
XX    rp = proc_addr(proc_nr);
XX!   if (rp->p_pending & (1 << (sig_nr - 1)))
XX  	return;			/* this signal already pending */
XX!   rp->p_pending |= 1 << (sig_nr - 1);
XX    ++rp->p_pendcount;		/* count new signal pending */
XX    if (rp->p_flags & PENDING)
XX  	return;			/* another signal already pending */
XX--- 866,874 ----
XX    register struct proc *rp, *mmp;
XX  
XX    rp = proc_addr(proc_nr);
XX!   if (sigismember(&rp->p_pending, sig_nr))
XX  	return;			/* this signal already pending */
XX!   sigaddset(&rp->p_pending, sig_nr);
XX    ++rp->p_pendcount;		/* count new signal pending */
XX    if (rp->p_flags & PENDING)
XX  	return;			/* another signal already pending */
XX***************
XX*** 686,694 ****
XX    rp->p_flags |= PENDING | SIG_PENDING;
XX    ++sig_procs;			/* count new process pending */
XX  
XX!   mmp = cproc_addr(MM_PROC_NR);
XX!   if ( ((mmp->p_flags & RECEIVING) == 0) || mmp->p_getfrom != ANY)
XX! 	return;
XX    inform();
XX  }
XX  
XX--- 876,883 ----
XX    rp->p_flags |= PENDING | SIG_PENDING;
XX    ++sig_procs;			/* count new process pending */
XX  
XX!   mmp = proc_addr(MM_PROC_NR);
XX!   if ( ((mmp->p_flags & RECEIVING) == 0) || mmp->p_getfrom != ANY) return;
XX    inform();
XX  }
XX  
XX***************
XX*** 711,726 ****
XX    for (rp = BEG_SERV_ADDR; rp < END_PROC_ADDR; rp++)
XX  	if (rp->p_flags & PENDING) {
XX  		m.m_type = KSIG;
XX! 		m.PROC1 = proc_number(rp);
XX  		m.SIG_MAP = rp->p_pending;
XX  		sig_procs--;
XX! 		if (lock_mini_send(cproc_addr(HARDWARE), MM_PROC_NR, &m) != OK)
XX  			panic("can't inform MM", NO_NUM);
XX! 		rp->p_pending = 0;	/* the ball is now in MM's court */
XX  		rp->p_flags &= ~PENDING;/* remains inhibited by SIG_PENDING */
XX  #if (MACHINE == ATARI)
XX  		/* SIGSTKFLT is not generated in the PC version. */
XX! 		if (m.SIG_MAP == (1 << (SIGSTKFLT - 1))) {
XX  			if (rp->p_pendcount != 0 &&
XX  			    --rp->p_pendcount == 0 &&
XX  			    (rp->p_flags &= ~SIG_PENDING) == 0)
XX--- 900,915 ----
XX    for (rp = BEG_SERV_ADDR; rp < END_PROC_ADDR; rp++)
XX  	if (rp->p_flags & PENDING) {
XX  		m.m_type = KSIG;
XX! 		m.SIG_PROC = proc_number(rp);
XX  		m.SIG_MAP = rp->p_pending;
XX  		sig_procs--;
XX! 		if (lock_mini_send(proc_addr(HARDWARE), MM_PROC_NR, &m) != OK)
XX  			panic("can't inform MM", NO_NUM);
XX! 		sigemptyset(&rp->p_pending); /* the ball is now in MM's court */
XX  		rp->p_flags &= ~PENDING;/* remains inhibited by SIG_PENDING */
XX  #if (MACHINE == ATARI)
XX  		/* SIGSTKFLT is not generated in the PC version. */
XX! 		if (sigismember((sigset_t *) &m.SIG_MAP, SIGSTKFLT)) {
XX  			if (rp->p_pendcount != 0 &&
XX  			    --rp->p_pendcount == 0 &&
XX  			    (rp->p_flags &= ~SIG_PENDING) == 0)
XX***************
XX*** 762,768 ****
XX  {
XX  /* Calculate the physical memory address for a given virtual address. */
XX    vir_clicks vc;		/* the virtual address in clicks */
XX!   phys_bytes seg_base, pa;	/* intermediate variables as phys_bytes */
XX  
XX    /* If 'seg' is D it could really be S and vice versa.  T really means T.
XX     * If the virtual address falls in the gap,  it causes a problem. On the
XX--- 951,960 ----
XX  {
XX  /* Calculate the physical memory address for a given virtual address. */
XX    vir_clicks vc;		/* the virtual address in clicks */
XX!   phys_bytes pa;		/* intermediate variables as phys_bytes */
XX! #if (CHIP == INTEL)
XX!   phys_bytes seg_base;
XX! #endif
XX  
XX    /* If 'seg' is D it could really be S and vice versa.  T really means T.
XX     * If the virtual address falls in the gap,  it causes a problem. On the
XX***************
XX*** 783,789 ****
XX  	seg = (vc < rp->p_map[S].mem_vir ? D : S);
XX  #endif
XX  
XX!   if((vir_addr>>CLICK_SHIFT) >= rp->p_map[seg].mem_vir + rp->p_map[seg].mem_len)
XX  	return( (phys_bytes) 0 );
XX  #if (CHIP == INTEL)
XX    seg_base = (phys_bytes) rp->p_map[seg].mem_phys;
XX--- 975,981 ----
XX  	seg = (vc < rp->p_map[S].mem_vir ? D : S);
XX  #endif
XX  
XX!   if((vir_addr>>CLICK_SHIFT) >= rp->p_map[seg].mem_vir+ rp->p_map[seg].mem_len)
XX  	return( (phys_bytes) 0 );
XX  #if (CHIP == INTEL)
XX    seg_base = (phys_bytes) rp->p_map[seg].mem_phys;
XX***************
XX*** 795,804 ****
XX--- 987,1001 ----
XX    return(seg_base + pa);
XX  #endif
XX  #if (CHIP == M68000)
XX+ #if (SHADOWING == 0)
XX+   pa -= (phys_bytes)rp->p_map[seg].mem_vir << CLICK_SHIFT;
XX+   pa += (phys_bytes)rp->p_map[seg].mem_phys << CLICK_SHIFT;
XX+ #else
XX    if (rp->p_shadow && seg != T) {
XX  	pa -= (phys_bytes)rp->p_map[D].mem_phys << CLICK_SHIFT;
XX  	pa += (phys_bytes)rp->p_shadow << CLICK_SHIFT;
XX    }
XX+ #endif
XX    return(pa);
XX  #endif
XX  }
XX***************
XX*** 861,867 ****
XX  
XX    phys_bytes src_phys, dst_phys;
XX  
XX!   src_phys = umap(proc_ptr, D, (vir_bytes) &boot_parameters,
XX  		  (vir_bytes) sizeof(boot_parameters));
XX    if ( (dst_phys = umap(proc_addr(m_ptr->PROC1), D,
XX  			(vir_bytes) m_ptr->MEM_PTR,
XX--- 1058,1064 ----
XX  
XX    phys_bytes src_phys, dst_phys;
XX  
XX!   src_phys = umap(proc_addr(SYSTASK), D, (vir_bytes) &boot_parameters,
XX  		  (vir_bytes) sizeof(boot_parameters));
XX    if ( (dst_phys = umap(proc_addr(m_ptr->PROC1), D,
XX  			(vir_bytes) m_ptr->MEM_PTR,
XX***************
XX*** 896,904 ****
XX  {
XX  /* Return the base and size of the next chunk of memory of a given type. */
XX  
XX- #if (CHIP == INTEL)
XX    unsigned mem;
XX  
XX    for (mem = 0; mem < NR_MEMS; ++mem) {
XX  	if (mem_type[mem] & 0x80) {
XX  	    mem_size[mem] = check_mem((phys_bytes) mem_base[mem]<<CLICK_SHIFT,
XX--- 1093,1101 ----
XX  {
XX  /* Return the base and size of the next chunk of memory of a given type. */
XX  
XX    unsigned mem;
XX  
XX+ #if (CHIP == INTEL)
XX    for (mem = 0; mem < NR_MEMS; ++mem) {
XX  	if (mem_type[mem] & 0x80) {
XX  	    mem_size[mem] = check_mem((phys_bytes) mem_base[mem]<<CLICK_SHIFT,
XX***************
XX*** 913,935 ****
XX  		return(OK);
XX  	}
XX    }
XX-   m_ptr->COUNT = 0;		/* no more */
XX  #endif /* (CHIP == INTEL) */
XX  
XX  #if (MACHINE == ATARI)
XX!   long i;
XX!   static int beenhere = 0;
XX! 
XX!   if (beenhere)
XX! 	m_ptr->COUNT = 0;
XX!   else {
XX! 	/* The ST fills address 0x0436 with the memory size when starting. */
XX! 	phys_copy((phys_bytes)0x0436, (phys_bytes)&i, (phys_bytes)sizeof(i));
XX! 	m_ptr->COUNT =  i >> CLICK_SHIFT;
XX! 	beenhere++;
XX    }
XX  #endif /* (MACHINE == ATARI) */
XX  
XX    m_ptr->POSITION = 0;
XX    return(OK);
XX  }
XX--- 1110,1129 ----
XX  		return(OK);
XX  	}
XX    }
XX  #endif /* (CHIP == INTEL) */
XX  
XX  #if (MACHINE == ATARI)
XX!   for (mem = 0; mem < NR_MEMS; ++mem) {
XX! 	if (mem_size[mem]) {
XX! 		m_ptr->POSITION = mem_base[mem];
XX! 		m_ptr->COUNT = mem_size[mem];
XX! 		mem_size[mem] = 0;
XX! 		return(OK);
XX! 	}
XX    }
XX  #endif /* (MACHINE == ATARI) */
XX  
XX+   m_ptr->COUNT = 0;		/* no more */
XX    m_ptr->POSITION = 0;
XX    return(OK);
XX  }
XX***************
XX*** 950,958 ****
XX  		reg_t	f_pc;
XX    } *fp;
XX  
XX!   fp = (struct frame *)sig_stuff;
XX    fp->f_sig = sig;
XX    fp->f_psw = rp->p_reg.psw;
XX    fp->f_pc = rp->p_reg.pc;
XX  }
XX  #endif /* (CHIP == M68000) */
XX--- 1144,1192 ----
XX  		reg_t	f_pc;
XX    } *fp;
XX  
XX!   fp = (struct frame *) sig_stuff;
XX    fp->f_sig = sig;
XX    fp->f_psw = rp->p_reg.psw;
XX    fp->f_pc = rp->p_reg.pc;
XX  }
XX  #endif /* (CHIP == M68000) */
XX+ 
XX+ /*===========================================================================*
XX+  *				do_vcopy				     *
XX+  *===========================================================================*/
XX+ PRIVATE int do_vcopy(m_ptr)
XX+ register message *m_ptr;	/* pointer to request message */
XX+ {
XX+ /* Handle sys_vcopy(). */
XX+ 
XX+   int src_proc, dst_proc, vect_s, i;
XX+   vir_bytes src_vir, dst_vir, vect_addr;
XX+   phys_bytes src_phys, dst_phys, bytes;
XX+   cpvec_t cpvec_table[CPVEC_NR];
XX+ 
XX+   /* Dismember the command message. */
XX+   src_proc = m_ptr->m1_i1;
XX+   dst_proc = m_ptr->m1_i2;
XX+   vect_s = m_ptr->m1_i3;
XX+   vect_addr = (vir_bytes)m_ptr->m1_p1;
XX+ 
XX+   if (vect_s > CPVEC_NR) return EDOM;
XX+ 
XX+   src_phys= numap (m_ptr->m_source, vect_addr, vect_s * sizeof(cpvec_t));
XX+   if (!src_phys) return E_BAD_ADDR;
XX+   dst_phys= numap (SYSTASK, (vir_bytes)cpvec_table, vect_s * sizeof(cpvec_t));
XX+   if (!dst_phys) panic ("can't umap", 0);
XX+   phys_copy (src_phys, dst_phys, (phys_bytes) (vect_s * sizeof(cpvec_t)));
XX+ 
XX+   for (i = 0; i < vect_s; i++) {
XX+ 	src_vir= cpvec_table[i].cpv_src;
XX+ 	dst_vir= cpvec_table[i].cpv_dst;
XX+ 	bytes= cpvec_table[i].cpv_size;
XX+ 	src_phys = numap(src_proc,src_vir,(vir_bytes)bytes);
XX+ 	dst_phys = numap(dst_proc,dst_vir,(vir_bytes)bytes);
XX+ 	if (src_phys == 0 || dst_phys == 0) return(EFAULT);
XX+ 	phys_copy(src_phys, dst_phys, bytes);
XX+   }
XX+   return(OK);
XX+ }
XX+ 
X/
Xecho x - table.c.d
Xsed '/^X/s///' > table.c.d << '/'
XX*** /home/top/ast/minix/1.5/kernel/table.c  crc=02936   3663	Sat Apr 21 22:26:24 1990
XX--- /home/top/ast/minix/1.6.25/kernel/table.c  crc=07237   3761	Sun Nov 15 23:17:24 1992
XX***************
XX*** 30,51 ****
XX  #include "proc.h"
XX  #include "tty.h"
XX  
XX  /* The startup routine of each task is given below, from -NR_TASKS upwards.
XX   * The order of the names here MUST agree with the numerical values assigned to
XX   * the tasks in <minix/com.h>.
XX   */
XX  #define SMALL_STACK	(128 * sizeof (char *))
XX  
XX! #if (MACHINE == ATARI)
XX! #define	TTY_STACK	(2 * SMALL_STACK)
XX! #define IDLE_STACK	SMALL_STACK
XX  #else
XX! #define	TTY_STACK	SMALL_STACK
XX  #define	IDLE_STACK	(3 * 2 + 3 * 2 + 4 * 2)	/* 3 intr, 3 temps, 4 db */
XX  #endif
XX  #define	PRINTER_STACK	SMALL_STACK
XX  #define	WINCH_STACK	SMALL_STACK
XX! #define	FLOP_STACK	(3*SMALL_STACK/2)
XX  #define	MEM_STACK	SMALL_STACK
XX  #define	CLOCK_STACK	SMALL_STACK
XX  #define	SYS_STACK	SMALL_STACK
XX--- 30,72 ----
XX  #include "proc.h"
XX  #include "tty.h"
XX  
XX+ FORWARD _PROTOTYPE( void ___dummy, (void) );
XX+ 
XX  /* The startup routine of each task is given below, from -NR_TASKS upwards.
XX   * The order of the names here MUST agree with the numerical values assigned to
XX   * the tasks in <minix/com.h>.
XX   */
XX  #define SMALL_STACK	(128 * sizeof (char *))
XX  
XX! #define	TTY_STACK	(3 * SMALL_STACK)
XX! #define SYN_ALRM_STACK	SMALL_STACK
XX! 
XX! #if NETWORKING_ENABLED
XX! #define EHW_STACK	SMALL_STACK
XX  #else
XX! #define EHW_STACK	0
XX! #endif
XX! 
XX! #if (CHIP == INTEL)
XX  #define	IDLE_STACK	(3 * 2 + 3 * 2 + 4 * 2)	/* 3 intr, 3 temps, 4 db */
XX+ #else
XX+ #define IDLE_STACK	SMALL_STACK
XX  #endif
XX+ 
XX  #define	PRINTER_STACK	SMALL_STACK
XX+ 
XX+ #if (CHIP == INTEL)
XX  #define	WINCH_STACK	SMALL_STACK
XX! #else
XX! #define	WINCH_STACK	(2 * SMALL_STACK)
XX! #endif
XX! #if (MACHINE == ATARI)
XX! #define	SCSI_STACK	(2 * SMALL_STACK)
XX! #else
XX! #define	SCSI_STACK	0
XX! #endif
XX! 
XX! #define	FLOP_STACK	(3 * SMALL_STACK)
XX  #define	MEM_STACK	SMALL_STACK
XX  #define	CLOCK_STACK	SMALL_STACK
XX  #define	SYS_STACK	SMALL_STACK
XX***************
XX*** 53,90 ****
XX  
XX  
XX  
XX! #if AM_KERNEL
XX! #	define	AMINT_STACK		(SMALL_STACK*4)
XX! #	define	AMOEBA_STACK		1532
XX! #	define	AMOEBA_STACK_SPACE	(AM_NTASKS*AMOEBA_STACK + AMINT_STACK)
XX! #else
XX! #	define	AMOEBA_STACK_SPACE	0
XX! #endif
XX  
XX- #define	TOT_STACK_SPACE		(TTY_STACK + AMOEBA_STACK_SPACE + \
XX- 				 IDLE_STACK + HARDWARE_STACK + \
XX- 				 PRINTER_STACK + WINCH_STACK + FLOP_STACK + \
XX- 				 MEM_STACK + CLOCK_STACK + SYS_STACK)
XX- 
XX  /*
XX! ** some notes about the following table:
XX! **  1) The tty_task should always be first so that other tasks can use printf
XX! **     if their initialisation has problems.
XX! **  2) If you add a new kernel task, add it after the amoeba_tasks and before
XX! **     the printer task.
XX! **  3) The task name is used for process status (F1 key) and must be six (6)
XX! **     characters in length.  Pad it with blanks if it is too short.
XX! */
XX  
XX  PUBLIC struct tasktab tasktab[] = {
XX  	tty_task,		TTY_STACK,	"TTY   ",
XX! #if AM_KERNEL
XX! 	amint_task,		AMINT_STACK,	"AMINT ",
XX! 	amoeba_task,		AMOEBA_STACK,	"AMTASK",
XX! 	amoeba_task,		AMOEBA_STACK,	"AMTASK",
XX! 	amoeba_task,		AMOEBA_STACK,	"AMTASK",
XX! 	amoeba_task,		AMOEBA_STACK,	"AMTASK",
XX  #endif
XX  	idle_task,		IDLE_STACK,	"IDLE  ",
XX  	printer_task,		PRINTER_STACK,	"PRINTR",
XX  	winchester_task,	WINCH_STACK,	"WINCHE",
XX--- 74,102 ----
XX  
XX  
XX  
XX! #define	TOT_STACK_SPACE		(TTY_STACK + EHW_STACK + \
XX! 	SYN_ALRM_STACK + IDLE_STACK + HARDWARE_STACK + PRINTER_STACK + \
XX! 	WINCH_STACK + FLOP_STACK + MEM_STACK + CLOCK_STACK + SYS_STACK + \
XX! 	SCSI_STACK)
XX  
XX  /*
XX!  * Some notes about the following table:
XX!  *  1) The tty_task should always be first so that other tasks can use printf
XX!  *     if their initialisation has problems.
XX!  *  2) If you add a new kernel task, add it before the printer task.
XX!  *  3) The task name is used for process status (F1 key) and must be six (6)
XX!  *     characters in length.  Pad it with blanks if it is too short.
XX!  */
XX  
XX  PUBLIC struct tasktab tasktab[] = {
XX  	tty_task,		TTY_STACK,	"TTY   ",
XX! #if (MACHINE == ATARI)
XX! 	scsi_task,		SCSI_STACK,	"SCSI  ",
XX  #endif
XX+ #if NETWORKING_ENABLED
XX+ 	ehw_task,		EHW_STACK,	"DL_ETH",
XX+ #endif
XX+ 	syn_alrm_task,		SYN_ALRM_STACK, "SYN_AL",
XX  	idle_task,		IDLE_STACK,	"IDLE  ",
XX  	printer_task,		PRINTER_STACK,	"PRINTR",
XX  	winchester_task,	WINCH_STACK,	"WINCHE",
XX***************
XX*** 95,114 ****
XX  	0,			HARDWARE_STACK,	"HARDWA",
XX  	0,			0,		"MM    ",
XX  	0,			0,		"FS    ",
XX  	0,			0,		"INIT  "
XX  };
XX  
XX  PUBLIC char t_stack[TOT_STACK_SPACE + ALIGNMENT - 1];	/* to be aligned */
XX  
XX  /*
XX! ** The number of kernel tasks must be the same as NR_TASKS.
XX! ** If NR_TASKS is not correct then you will get the compile error:
XX! **   multiple case entry for value 0
XX! ** The function ___dummy is never called.
XX! */
XX  
XX  #define NKT (sizeof tasktab / sizeof (struct tasktab) - (INIT_PROC_NR + 1))
XX! PUBLIC void ___dummy()
XX  {
XX  	switch(0)
XX  	{
XX--- 107,129 ----
XX  	0,			HARDWARE_STACK,	"HARDWA",
XX  	0,			0,		"MM    ",
XX  	0,			0,		"FS    ",
XX+ #if NETWORKING_ENABLED
XX+ 	0,			0,		"NW_TSK",
XX+ #endif
XX  	0,			0,		"INIT  "
XX  };
XX  
XX  PUBLIC char t_stack[TOT_STACK_SPACE + ALIGNMENT - 1];	/* to be aligned */
XX  
XX  /*
XX!  * The number of kernel tasks must be the same as NR_TASKS.
XX!  * If NR_TASKS is not correct then you will get the compile error:
XX!  *   multiple case entry for value 0
XX!  * The function ___dummy is never called.
XX!  */
XX  
XX  #define NKT (sizeof tasktab / sizeof (struct tasktab) - (INIT_PROC_NR + 1))
XX! PRIVATE void ___dummy()
XX  {
XX  	switch(0)
XX  	{
X/
Xecho x - tty.c.d
Xsed '/^X/s///' > tty.c.d << '/'
XX*** /home/top/ast/minix/1.5/kernel/tty.c  crc=19472  35315	Sat Apr 21 22:26:24 1990
XX--- /home/top/ast/minix/1.6.25/kernel/tty.c  crc=12570  39449	Sat Apr 10 19:45:44 1993
XX***************
XX*** 21,44 ****
XX   * The valid messages and their parameters are:
XX   *
XX   *   HARD_INT:     output has been completed or input has arrived
XX!  *   TTY_READ:     a process wants to read from a terminal
XX!  *   TTY_WRITE:    a process wants to write on a terminal
XX!  *   TTY_IOCTL:    a process wants to change a terminal's parameters
XX!  *   TTY_SETPGRP:  indicate a change in a control terminal
XX   *   CANCEL:       terminate a previous incomplete system call immediately
XX   *
XX   *    m_type      TTY_LINE   PROC_NR    COUNT   TTY_SPEK  TTY_FLAGS  ADDRESS
XX!  * |-------------+---------+---------+---------+---------+---------+---------|
XX   * | HARD_INT    |         |         |         |         |         |         |
XX   * |-------------+---------+---------+---------+---------+---------+---------|
XX!  * | TTY_READ    |minor dev| proc nr |  count  |         |         | buf ptr |
XX   * |-------------+---------+---------+---------+---------+---------+---------|
XX!  * | TTY_WRITE   |minor dev| proc nr |  count  |         |         | buf ptr |
XX   * |-------------+---------+---------+---------+---------+---------+---------|
XX!  * | TTY_IOCTL   |minor dev| proc nr |func code|erase etc|  flags  |         |
XX   * |-------------+---------+---------+---------+---------+---------+---------|
XX!  * | TTY_SETPGRP |minor dev| proc nr |         |         |         |         |
XX!  * |-------------+---------+---------+---------+---------+---------+---------
XX   * | CANCEL      |minor dev| proc nr |         |         |         |         |
XX   * ---------------------------------------------------------------------------
XX   */
XX--- 21,50 ----
XX   * The valid messages and their parameters are:
XX   *
XX   *   HARD_INT:     output has been completed or input has arrived
XX!  *   DEV_READ:     a process wants to read from a terminal
XX!  *   DEV_WRITE:    a process wants to write on a terminal
XX!  *   DEV_IOCTL:    a process wants to change a terminal's parameters
XX!  *   DEV_OPEN:     a tty line has been opened
XX!  *   DEV_CLOSE:    a tty line has been closed
XX!  *   TTY_EXIT:     a process group leader has exited
XX   *   CANCEL:       terminate a previous incomplete system call immediately
XX   *
XX   *    m_type      TTY_LINE   PROC_NR    COUNT   TTY_SPEK  TTY_FLAGS  ADDRESS
XX!  * ---------------------------------------------------------------------------
XX   * | HARD_INT    |         |         |         |         |         |         |
XX   * |-------------+---------+---------+---------+---------+---------+---------|
XX!  * | DEV_READ    |minor dev| proc nr |  count  |         |         | buf ptr |
XX   * |-------------+---------+---------+---------+---------+---------+---------|
XX!  * | DEV_WRITE   |minor dev| proc nr |  count  |         |         | buf ptr |
XX   * |-------------+---------+---------+---------+---------+---------+---------|
XX!  * | DEV_IOCTL   |minor dev| proc nr |func code|erase etc|  flags  |         |
XX   * |-------------+---------+---------+---------+---------+---------+---------|
XX!  * | DEV_OPEN    |minor dev| proc nr | #links  |leaderbit|O_NOCTTY |         |
XX!  * |-------------+---------+---------+---------+---------+---------+---------|
XX!  * | DEV_CLOSE   |minor dev| proc nr | #links  |         |         |         |
XX!  * |-------------+---------+---------+---------+---------+---------+---------|
XX!  * | TTY_EXIT    |minor dev| proc nr |         |         |         |         |
XX!  * |-------------+---------+---------+---------+---------+---------+---------|
XX   * | CANCEL      |minor dev| proc nr |         |         |         |         |
XX   * ---------------------------------------------------------------------------
XX   */
XX***************
XX*** 46,55 ****
XX--- 52,68 ----
XX  #include "kernel.h"
XX  #include <sgtty.h>
XX  #include <signal.h>
XX+ #include <fcntl.h>
XX  #include <minix/callnr.h>
XX  #include <minix/com.h>
XX+ #if (CHIP == M68000)
XX+ #include "proc.h"
XX+ #endif
XX  #include "tty.h"
XX  
XX+ #define O_NOCTTY   00400	/* Kludge due to compiler overflow */
XX+ #define O_NONBLOCK 04000	/* ditto */
XX+ 
XX  /* Array and macros to convert line numbers to structure pointers. */
XX  PRIVATE struct tty_struct *p_tty_addr[NR_CONS + NR_RS_LINES];
XX  #define ctty_addr(line) (&tty_struct[(line)])	/* faster if line is const */
XX***************
XX*** 67,98 ****
XX  #define END_TTY   (ctty_addr(NR_CONS + NR_RS_LINES))
XX  
XX  /* Miscellaneous. */
XX! #define LF        '\012'	/* '\n' is not portablly a LF */
XX  
XX  /* Test-and-set flag, set during tty_wakeup().  Remains set if do_int() is
XX   * scheduled until do_int() is finished.
XX   */
XX  PRIVATE int tty_awake;
XX  
XX! FORWARD void back_over();
XX! FORWARD int chuck();
XX! FORWARD void do_cancel();
XX! FORWARD void do_int();
XX! FORWARD void do_ioctl();
XX! FORWARD void do_read();
XX! FORWARD void do_setpgrp();
XX! FORWARD void do_write();
XX! FORWARD void echo();
XX! FORWARD void in1_char();
XX! FORWARD void in_char();
XX! FORWARD int out_process();
XX! FORWARD int rd_chars();
XX! FORWARD void rs_start();
XX! FORWARD void tty_icancel();
XX! FORWARD void tty_init();
XX! FORWARD void tty_ocancel();
XX! FORWARD void tty_reply();
XX! FORWARD void uninhibit();
XX  
XX  /*===========================================================================*
XX   *				tty_task				     *
XX--- 80,118 ----
XX  #define END_TTY   (ctty_addr(NR_CONS + NR_RS_LINES))
XX  
XX  /* Miscellaneous. */
XX! #define LF        '\012'	/* '\n' is not portably a LF */
XX  
XX  /* Test-and-set flag, set during tty_wakeup().  Remains set if do_int() is
XX   * scheduled until do_int() is finished.
XX   */
XX+ #if (CHIP == M68000)
XX+ PRIVATE char tty_awake;
XX+ #else
XX  PRIVATE int tty_awake;
XX+ #endif
XX  
XX! FORWARD _PROTOTYPE( void back_over, (struct tty_struct *tp) );
XX! FORWARD _PROTOTYPE( int chuck, (struct tty_struct *tp) );
XX! FORWARD _PROTOTYPE( void do_cancel, (struct tty_struct *tp, message *m_ptr) );
XX! FORWARD _PROTOTYPE( void do_int, (void) );
XX! FORWARD _PROTOTYPE( void do_ioctl, (struct tty_struct *tp, message *m_ptr) );
XX! FORWARD _PROTOTYPE( void do_ttyopen, (struct tty_struct *tp, message *m_ptr) );
XX! FORWARD _PROTOTYPE( void do_ttyclose, (struct tty_struct *tp, message *m_ptr));
XX! FORWARD _PROTOTYPE( void do_read, (struct tty_struct *tp, message *m_ptr) );
XX! FORWARD _PROTOTYPE( void do_write, (struct tty_struct *tp, message *m_ptr) );
XX! FORWARD _PROTOTYPE( void echo, (struct tty_struct *tp, int c) );
XX! FORWARD _PROTOTYPE( void in1_char, (struct tty_struct *tp, int ch,int echoch));
XX! FORWARD _PROTOTYPE( void in_char, (struct tty_struct *tp, int ch) );
XX! FORWARD _PROTOTYPE( int out_process, (struct tty_struct *tp,
XX! 		char *ubuf, int ucount) );
XX! FORWARD _PROTOTYPE( int rd_chars, (struct tty_struct *tp) );
XX! FORWARD _PROTOTYPE( void rs_start, (struct tty_struct *tp) );
XX! FORWARD _PROTOTYPE( void tty_icancel, (struct tty_struct *tp) );
XX! FORWARD _PROTOTYPE( void tty_init, (void) );
XX! FORWARD _PROTOTYPE( void tty_ocancel, (struct tty_struct *tp) );
XX! FORWARD _PROTOTYPE( void tty_reply, (int code, int replyee, int proc_nr,
XX! 		int status) );
XX! FORWARD _PROTOTYPE( void uninhibit, (struct tty_struct *tp) );
XX  
XX  /*===========================================================================*
XX   *				tty_task				     *
XX***************
XX*** 114,123 ****
XX  	tp = tty_addr(tty_mess.TTY_LINE);
XX  	switch(tty_mess.m_type) {
XX  	    case HARD_INT:	do_int();			break;
XX! 	    case TTY_READ:	do_read(tp, &tty_mess);		break;
XX! 	    case TTY_WRITE:	do_write(tp, &tty_mess);	break;
XX! 	    case TTY_IOCTL:	do_ioctl(tp, &tty_mess);	break;
XX! 	    case TTY_SETPGRP:   do_setpgrp(tp, &tty_mess);	break;
XX  	    case CANCEL:	do_cancel(tp, &tty_mess);	break;
XX  	    default:		tty_reply(TASK_REPLY, tty_mess.m_source,
XX  					  tty_mess.PROC_NR, EINVAL);
XX--- 134,144 ----
XX  	tp = tty_addr(tty_mess.TTY_LINE);
XX  	switch(tty_mess.m_type) {
XX  	    case HARD_INT:	do_int();			break;
XX! 	    case DEV_READ:	do_read(tp, &tty_mess);		break;
XX! 	    case DEV_WRITE:	do_write(tp, &tty_mess);	break;
XX! 	    case DEV_IOCTL:	do_ioctl(tp, &tty_mess);	break;
XX! 	    case DEV_OPEN:	do_ttyopen(tp, &tty_mess);	break;
XX! 	    case DEV_CLOSE:	do_ttyclose(tp, &tty_mess);	break;
XX  	    case CANCEL:	do_cancel(tp, &tty_mess);	break;
XX  	    default:		tty_reply(TASK_REPLY, tty_mess.m_source,
XX  					  tty_mess.PROC_NR, EINVAL);
XX***************
XX*** 165,170 ****
XX--- 186,195 ----
XX    register struct tty_struct *tp;
XX    unsigned wrapcount;
XX  
XX+ #if (MACHINE == ATARI)
XX+   func_key();
XX+ #endif
XX+ 
XX    tp = last_tp;
XX    do {
XX  	if (++tp >= END_TTY) tp = FIRST_TTY;
XX***************
XX*** 250,269 ****
XX  {
XX  /* A character has just been typed in.  Process, save, and echo it. */
XX  
XX!   int mode, sig, scode, c;
XX  
XX    scode = ch;			/* save the scan code */
XX  
XX    /* Function keys are temporarily being used for debug dumps. */
XX    if (isconsole(tp) && func_key(ch))
XX  	return;			/* just processed function key */
XX    mode = tp->tty_mode & (RAW | CBREAK);
XX    if (tp->tty_makebreak == TWO_INTS) {
XX  	c = make_break(ch);	/* console give 2 ints/ch */
XX  	if (c == -1) return;
XX  	ch = c;
XX!   } else if (mode != RAW)
XX! 	ch &= 0177;		/* 7-bit chars except in raw mode */
XX  
XX    /* Processing for COOKED and CBREAK mode contains special checks. */
XX    if (mode == COOKED || mode == CBREAK) {
XX--- 275,301 ----
XX  {
XX  /* A character has just been typed in.  Process, save, and echo it. */
XX  
XX!   int mode, sig, scode;
XX! #if (CHIP == INTEL)
XX!   int c;
XX! #endif
XX  
XX    scode = ch;			/* save the scan code */
XX  
XX+ #if (CHIP == INTEL)
XX    /* Function keys are temporarily being used for debug dumps. */
XX    if (isconsole(tp) && func_key(ch))
XX  	return;			/* just processed function key */
XX+ #endif
XX    mode = tp->tty_mode & (RAW | CBREAK);
XX+ #if (CHIP == INTEL)
XX    if (tp->tty_makebreak == TWO_INTS) {
XX  	c = make_break(ch);	/* console give 2 ints/ch */
XX  	if (c == -1) return;
XX  	ch = c;
XX!   } else
XX! #endif
XX! 	if (mode != RAW) ch &= 0177;	/* 7-bit chars except in raw mode */
XX  
XX    /* Processing for COOKED and CBREAK mode contains special checks. */
XX    if (mode == COOKED || mode == CBREAK) {
XX***************
XX*** 281,286 ****
XX--- 313,323 ----
XX  
XX  		/* Now do kill processing (remove current line). */
XX  		if (ch == tp->tty_kill && tp->tty_escaped == NOT_ESCAPED) {
XX+ 			if (ch < ' ') {
XX+ 				/* Visibly erase line for a control char. */
XX+ 				while (chuck(tp) == OK) back_over(tp);
XX+ 				return;
XX+ 			}
XX  			while(chuck(tp) == OK)	/* keep looping */ ;
XX  			echo(tp, tp->tty_kill);
XX  			echo(tp, '\n');
XX***************
XX*** 345,350 ****
XX--- 382,388 ----
XX    if (ch == '\n' && tp->tty_incount < tp->tty_insize)
XX  	tp->tty_lfct++;		/* count line feeds */
XX  
XX+ #if (CHIP == INTEL)
XX    /* The numeric pad generates ASCII escape sequences: ESC [ letter */
XX    if (isconsole(tp) && (scode = letter_code(scode)) != 0) {
XX  	/* This key is to generate a three-character escape sequence. */
XX***************
XX*** 352,357 ****
XX--- 390,396 ----
XX  	in1_char(tp, BRACKET, BRACKET);
XX  	ch = scode;
XX    }
XX+ #endif
XX  
XX    in1_char(tp, ch, ch);
XX  }
XX***************
XX*** 367,379 ****
XX  /* Echo a character on the terminal. */
XX  
XX    if ( (tp->tty_mode & ECHO) == 0) return;	/* if no echoing, don't echo */
XX! /* MARKER is meaningful only in cooked mode */
XX    if (c != MARKER || tp->tty_mode & (CBREAK | RAW)) {
XX  	if (isconsole(tp)) {
XX  		out_char(tp, c);	/* echo to console */
XX  		flush(tp);		/* force character out onto screen */
XX! 	} else if (tp->tty_etail < tp->tty_ebufend)
XX! 		*tp->tty_etail++ = c;	/* echo to RS232 line */
XX    }
XX  }
XX  
XX--- 406,421 ----
XX  /* Echo a character on the terminal. */
XX  
XX    if ( (tp->tty_mode & ECHO) == 0) return;	/* if no echoing, don't echo */
XX! 
XX!   /* MARKER is meaningful only in cooked mode. */
XX    if (c != MARKER || tp->tty_mode & (CBREAK | RAW)) {
XX  	if (isconsole(tp)) {
XX  		out_char(tp, c);	/* echo to console */
XX  		flush(tp);		/* force character out onto screen */
XX! 	} else {
XX! 		/* Echo to RS232 line. */
XX! 		if (tp->tty_etail < tp->tty_ebufend) *tp->tty_etail++ = c;
XX! 	}
XX    }
XX  }
XX  
XX***************
XX*** 408,418 ****
XX   *				do_read					     *
XX   *===========================================================================*/
XX  PRIVATE void do_read(tp, m_ptr)
XX! register struct tty_struct *tp;
XX  message *m_ptr;			/* pointer to message sent to the task */
XX  {
XX  /* A process wants to read from a terminal. */
XX  
XX    if (tp->tty_inleft > 0) {	/* if someone else is hanging, give up */
XX  	tty_reply(TASK_REPLY, m_ptr->m_source, m_ptr->PROC_NR, EIO);
XX  	return;
XX--- 450,462 ----
XX   *				do_read					     *
XX   *===========================================================================*/
XX  PRIVATE void do_read(tp, m_ptr)
XX! register struct tty_struct *tp;	/* pointer to tty struct */
XX  message *m_ptr;			/* pointer to message sent to the task */
XX  {
XX  /* A process wants to read from a terminal. */
XX  
XX+   int bytesread, nonblocking;
XX+ 
XX    if (tp->tty_inleft > 0) {	/* if someone else is hanging, give up */
XX  	tty_reply(TASK_REPLY, m_ptr->m_source, m_ptr->PROC_NR, EIO);
XX  	return;
XX***************
XX*** 425,431 ****
XX    tp->tty_inleft = m_ptr->COUNT;
XX  
XX    /* Try to get chars.  This call either gets enough, or gets nothing. */
XX!   tty_reply(TASK_REPLY, m_ptr->m_source, (int) tp->tty_inproc, rd_chars(tp));
XX  }
XX  
XX  
XX--- 469,488 ----
XX    tp->tty_inleft = m_ptr->COUNT;
XX  
XX    /* Try to get chars.  This call either gets enough, or gets nothing. */
XX!   bytesread = rd_chars(tp);
XX! 
XX!   /* If nonblocking mode is set, caller is *not* waiting for more characters
XX!    * now, even if it now got less than requested.  If this flag is not reset,
XX!    * the next caller gets the EIO in the if statement first in this function.
XX!    */
XX!   nonblocking = (int) m_ptr->TTY_FLAGS & O_NONBLOCK;	/* nonblocking mode */
XX!   if (bytesread == SUSPEND && nonblocking) {
XX! 	tp->tty_inleft = 0;	/* Make tty free for the next caller */
XX! 	bytesread = EAGAIN;
XX!   }
XX! 
XX!   /* Send result to caller */
XX!   tty_reply(TASK_REPLY, m_ptr->m_source, (int) tp->tty_inproc, bytesread);
XX  }
XX  
XX  
XX***************
XX*** 469,489 ****
XX  	 */
XX  	user_ct = ct;
XX  	if (!(tp->tty_mode & (RAW | CBREAK))) {
XX! 		/* COOKED mode.
XX! 		 * Don't bother counting lines in CBREAK and RAW modes.
XX! 		 */
XX  		for (bufend = rtail + ct; rtail < bufend;) {
XX  			if (*rtail++ == '\n') {
XX! 				user_ct =
XX! 					tp->tty_inleft =
XX! 					ct = rtail - tp->tty_intail;
XX  				tp->tty_lfct--;;
XX  				break;
XX  			}
XX  			if (rtail[-1] == MARKER) {
XX! 				tp->tty_inleft =
XX! 					ct = rtail - tp->tty_intail;
XX! 					user_ct = ct - 1;
XX  				tp->tty_lfct--;
XX  				break;
XX  			}
XX--- 526,544 ----
XX  	 */
XX  	user_ct = ct;
XX  	if (!(tp->tty_mode & (RAW | CBREAK))) {
XX! 		/* COOKED mode.  Don't count lines in CBREAK and RAW modes. */
XX  		for (bufend = rtail + ct; rtail < bufend;) {
XX  			if (*rtail++ == '\n') {
XX! 				user_ct = rtail - tp->tty_intail;
XX! 				tp->tty_inleft = user_ct;
XX! 				ct = user_ct;
XX  				tp->tty_lfct--;;
XX  				break;
XX  			}
XX  			if (rtail[-1] == MARKER) {
XX! 				ct = rtail - tp->tty_intail;
XX! 				tp->tty_inleft = ct;
XX! 				user_ct = ct - 1;
XX  				tp->tty_lfct--;
XX  				break;
XX  			}
XX***************
XX*** 563,568 ****
XX--- 618,627 ----
XX    tp->tty_cum = 0;
XX    tp->tty_waiting = WAITING;
XX  
XX+ #if (CHIP == M68000)
XX+   (proc_addr(tp->tty_outproc))->p_physio = 1;	/* disable (un)shadowing */
XX+ #endif
XX+ 
XX    /* Copy characters from the user process to the terminal. */
XX    (*tp->tty_devstart)(tp);	/* copy data to queue and start I/O */
XX  
XX***************
XX*** 664,669 ****
XX--- 723,734 ----
XX  	flags = (eof <<8);
XX  	break;
XX  
XX+ #if (MACHINE == ATARI)
XX+      case VDU_LOADFONT:
XX+  	r = vdu_loadfont(m_ptr);
XX+ 	break;
XX+ #endif
XX+ 
XX  #ifdef TIOCFLUSH
XX       case TIOCFLUSH:
XX  	/* Discard current input and output. */
XX***************
XX*** 684,703 ****
XX  
XX  
XX  /*===========================================================================*
XX!  *				do_setpgrp				     *
XX   *===========================================================================*/
XX! PRIVATE void do_setpgrp(tp, m_ptr)
XX  register struct tty_struct *tp;
XX  message *m_ptr;			/* pointer to message sent to task */
XX  {
XX! /* A control process group has changed */
XX  
XX!   tp->tty_pgrp = m_ptr->TTY_PGRP;
XX!   tty_reply(TASK_REPLY, m_ptr->m_source, m_ptr->PROC_NR, OK);
XX  }
XX  
XX  
XX  /*===========================================================================*
XX   *				do_cancel				     *
XX   *===========================================================================*/
XX  PRIVATE void do_cancel(tp, m_ptr)
XX--- 749,803 ----
XX  
XX  
XX  /*===========================================================================*
XX!  *				do_ttyopen				     *
XX   *===========================================================================*/
XX! PRIVATE void do_ttyopen(tp, m_ptr)
XX  register struct tty_struct *tp;
XX  message *m_ptr;			/* pointer to message sent to task */
XX  {
XX! /* A tty line has been opened.  See if caller should become controlling tty. */
XX  
XX!   int ctl, r = TRUE;
XX!   register struct tty_struct *rtp;
XX! 
XX!   /* If caller meets the following conditions, it becomes controlling tty. */
XX!   if (m_ptr->TTY_SPEK == 0) r = FALSE;		/* not process group leader */
XX!   if (tp->tty_pgrp != 0) r = FALSE;		/* already is ctl tty */
XX!   if (m_ptr->TTY_FLAGS & O_NOCTTY) r = FALSE;	/* O_NOCTTY set */
XX! 
XX!   for (rtp = &tty_struct[0]; rtp < &tty_struct[NR_CONS + NR_RS_LINES]; rtp++) {
XX! 	if (rtp->tty_pgrp == m_ptr->PROC_NR) r = FALSE;
XX!   }
XX! 
XX!   if (r) tp->tty_pgrp = m_ptr->PROC_NR;
XX!   ctl = (tp->tty_pgrp ? m_ptr->TTY_LINE : NO_CTL_TTY);
XX!   tty_reply(TASK_REPLY, m_ptr->m_source, m_ptr->PROC_NR, ctl);
XX  }
XX  
XX  
XX  /*===========================================================================*
XX+  *				do_ttyclose				     *
XX+  *===========================================================================*/
XX+ PRIVATE void do_ttyclose(tp, m_ptr)
XX+ register struct tty_struct *tp;
XX+ message *m_ptr;			/* pointer to message sent to task */
XX+ {
XX+ /* A tty line has been closed.  See if it is proc grp leader's control tty. */
XX+ 
XX+   int ctl;
XX+ 
XX+   /* TTY_SPEK is now a boolean to tell if it is the last file to close */
XX+   if ((m_ptr->PROC_NR == tp->tty_pgrp) && (m_ptr->TTY_SPEK))
XX+   {
XX+ 	tp->tty_pgrp = 0;
XX+ 	sigchar(tp, SIGHUP);
XX+   }
XX+   ctl = (tp->tty_pgrp ? m_ptr->TTY_LINE : NO_CTL_TTY);
XX+   tty_reply(TASK_REPLY, m_ptr->m_source, m_ptr->PROC_NR, ctl);
XX+ }
XX+ 
XX+ 
XX+ /*===========================================================================*
XX   *				do_cancel				     *
XX   *===========================================================================*/
XX  PRIVATE void do_cancel(tp, m_ptr)
XX***************
XX*** 951,957 ****
XX  		tp->tty_insize = RS_IN_BYTES;
XX  	}
XX  	tp->tty_inphys = umap(proc_ptr, D, (vir_bytes) tp->tty_inbuf,
XX! 			      tp->tty_insize);
XX  	tp->tty_intail = tp->tty_inhead = tp->tty_inbuf;
XX  	tp->tty_outphys = umap(proc_ptr, D, (vir_bytes) tp->tty_ramqueue,
XX  			       sizeof tp->tty_ramqueue);
XX--- 1051,1057 ----
XX  		tp->tty_insize = RS_IN_BYTES;
XX  	}
XX  	tp->tty_inphys = umap(proc_ptr, D, (vir_bytes) tp->tty_inbuf,
XX! 			      (vir_bytes)tp->tty_insize);
XX  	tp->tty_intail = tp->tty_inhead = tp->tty_inbuf;
XX  	tp->tty_outphys = umap(proc_ptr, D, (vir_bytes) tp->tty_ramqueue,
XX  			       sizeof tp->tty_ramqueue);
XX***************
XX*** 969,976 ****
XX--- 1069,1082 ----
XX  		tp->tty_devstart = console;
XX  		tp->tty_mode = CRMOD | XTABS | ECHO;
XX  		tp->tty_makebreak = TWO_INTS;
XX+ #if (CHIP == INTEL)
XX  		scr_init(tp->tty_line);
XX  		kb_init(tp->tty_line);
XX+ #endif
XX+ #if (MACHINE == ATARI)
XX+ 		vduinit(tp);
XX+ 		kbdinit(tp->tty_line);
XX+ #endif
XX  	} else {
XX  		tp->tty_devread = rs_read;
XX  		tp->tty_devstart = rs_start;
XX***************
XX*** 996,1001 ****
XX--- 1102,1110 ----
XX    tp->tty_rwords = 0;
XX    tp->tty_etail = tp->tty_ebuf;
XX    if (isrs232(tp)) rs_ocancel(tp->tty_line);
XX+ #if (CHIP == M68000)
XX+   (proc_addr(tp->tty_outproc))->p_physio = 0;	/* enable (un)shadowing */
XX+ #endif
XX  }
XX  
XX  
X/
Xecho x - tty.h.d
Xsed '/^X/s///' > tty.h.d << '/'
XX*** /home/top/ast/minix/1.5/kernel/tty.h  crc=07201   6653	Sat Apr 21 22:26:24 1990
XX--- /home/top/ast/minix/1.6.25/kernel/tty.h  crc=41790   6680	Tue Nov  3 21:21:08 1992
XX***************
XX*** 1,5 ****
XX- #define NR_CONS            1	/* how many consoles can system handle */
XX- #define	NR_RS_LINES	   2	/* how many rs232 terminals can system handle*/
XX  #define KB_IN_BYTES      200   	/* keyboard input queue size */
XX  #define RS_IN_BYTES   (1024 + 2 * RS_IBUFSIZE)	/* RS232 input queue size */
XX  #define TTY_RAM_WORDS    320	/* ram buffer size */
XX--- 1,3 ----
XX***************
XX*** 16,23 ****
XX  #define XON_CHAR  (char) 021	/* default x-on character (CTRL-Q) */
XX  #define EOT_CHAR  (char) 004	/* CTRL-D */
XX  
XX! /*
XX!  * This MARKER is used as an unambiguous flag for an unescaped end of
XX   * file character.  It is meaningful only in cooked mode.  0200 should
XX   * never be used in cooked mode, since that is supposed to be used only
XX   * for 7-bit ASCII.  Be careful that code only checks
XX--- 14,20 ----
XX  #define XON_CHAR  (char) 021	/* default x-on character (CTRL-Q) */
XX  #define EOT_CHAR  (char) 004	/* CTRL-D */
XX  
XX! /* This MARKER is used as an unambiguous flag for an unescaped end of
XX   * file character.  It is meaningful only in cooked mode.  0200 should
XX   * never be used in cooked mode, since that is supposed to be used only
XX   * for 7-bit ASCII.  Be careful that code only checks
XX***************
XX*** 32,37 ****
XX--- 29,38 ----
XX  #define EVENT_THRESHOLD   64	/* events to accumulate before waking TTY */
XX  #define RS_IBUFSIZE      256	/* RS232 input buffer size */
XX  
XX+ typedef _PROTOTYPE( int (*devread_t), (int minor, char **bufindirect,
XX+ 		unsigned char *odoneindirect) );
XX+ typedef _PROTOTYPE( void (*devstart_t), (struct tty_struct *tp) );
XX+ 
XX  EXTERN struct tty_struct {
XX    /* Input queue.  Typed characters are stored here until read by a program. */
XX    char *tty_inbuf;		/* pointer to input buffer */
XX***************
XX*** 44,50 ****
XX    phys_bytes tty_inphys;	/* physical address of input buffer */
XX    int tty_incount;		/* # chars in tty_inqueue */
XX    int tty_lfct;			/* # line feeds in tty_inqueue */
XX!   int (*tty_devread)();		/* routine to read from low level buffers */
XX  
XX    /* Output section. */
XX    phys_bytes tty_outphys;	/* physical address of output buffer */
XX--- 45,51 ----
XX    phys_bytes tty_inphys;	/* physical address of input buffer */
XX    int tty_incount;		/* # chars in tty_inqueue */
XX    int tty_lfct;			/* # line feeds in tty_inqueue */
XX!   devread_t tty_devread;	/* routine to read from low level buffers */
XX  
XX    /* Output section. */
XX    phys_bytes tty_outphys;	/* physical address of output buffer */
XX***************
XX*** 55,61 ****
XX    char tty_esc_intro;		/* Distinguishing character following ESC */
XX    int tty_esc_parmv[MAX_ESC_PARMS];	/* list of escape parameters */
XX    int *tty_esc_parmp;		/* pointer to current escape parameter */
XX!   void (*tty_devstart)();	/* routine to start actual device output */
XX  
XX    /* Echo buffer. Echoing is also delayed by output in progress. */
XX    char *tty_ebufend;		/* end of echo buffer */
XX--- 56,62 ----
XX    char tty_esc_intro;		/* Distinguishing character following ESC */
XX    int tty_esc_parmv[MAX_ESC_PARMS];	/* list of escape parameters */
XX    int *tty_esc_parmp;		/* pointer to current escape parameter */
XX!   devstart_t tty_devstart;	/* routine to start actual device output */
XX  
XX    /* Echo buffer. Echoing is also delayed by output in progress. */
XX    char *tty_ebufend;		/* end of echo buffer */
X/
Xecho x - type.h.d
Xsed '/^X/s///' > type.h.d << '/'
XX*** /home/top/ast/minix/1.5/kernel/type.h  crc=06615   2669	Sat Apr 21 22:26:24 1990
XX--- /home/top/ast/minix/1.6.25/kernel/type.h  crc=59400   2956	Mon Apr 19 20:59:48 1993
XX***************
XX*** 1,22 ****
XX  struct tasktab {
XX!   void (*initial_pc)();
XX    int stksize;
XX    char name[8];
XX  };
XX  
XX! #if (CHIP == INTEL || CHIP == M68000)
XX  
XX- /* The u.._t types and their derivatives are used when the precise size
XX-  * must be specified for some reason, e.g., to match descriptor table
XX-  * layouts.
XX-  */
XX- typedef unsigned char u8_t;	/* unsigned 8 bits */
XX- typedef unsigned short u16_t;	/* unsigned 16 bits */
XX- typedef unsigned long u32_t;	/* unsigned 32 bits */
XX- 
XX- #endif
XX- 
XX  #if (CHIP == INTEL)
XX  
XX  /* The register type is usually the natural 'unsigned', but not during 386
XX   * initialization, when it has to be unsigned long!
XX--- 1,18 ----
XX+ #ifndef TYPE_H
XX+ #define TYPE_H
XX+ 
XX  struct tasktab {
XX!   _PROTOTYPE( void (*initial_pc), (void) );
XX    int stksize;
XX    char name[8];
XX  };
XX  
XX! typedef _PROTOTYPE( int (*rdwt_t), (message *m_ptr) );
XX! typedef _PROTOTYPE( void (*watchdog_t), (void) );
XX  
XX  #if (CHIP == INTEL)
XX+ typedef unsigned port_t;
XX+ typedef unsigned segm_t;
XX  
XX  /* The register type is usually the natural 'unsigned', but not during 386
XX   * initialization, when it has to be unsigned long!
XX***************
XX*** 44,50 ****
XX    u16_t ds;
XX    reg_t di;			/* di through cx are not accessed in C */
XX    reg_t si;			/* order is to match pusha/popa */
XX!   reg_t bp;
XX    reg_t st;			/* hole for another copy of sp */
XX    reg_t bx;
XX    reg_t dx;
XX--- 40,46 ----
XX    u16_t ds;
XX    reg_t di;			/* di through cx are not accessed in C */
XX    reg_t si;			/* order is to match pusha/popa */
XX!   reg_t fp;			/* bp */
XX    reg_t st;			/* hole for another copy of sp */
XX    reg_t bx;
XX    reg_t dx;
XX***************
XX*** 78,91 ****
XX    u16_t pad;
XX  #endif
XX  };
XX- 
XX  #endif /* (CHIP == INTEL) */
XX  
XX  #if (CHIP == M68000)
XX  typedef u32_t reg_t;		/* machine register */
XX  
XX! /* the name of the following struct and some of the fields are
XX!    chosen for PC compatibility */
XX  struct stackframe_s {
XX    reg_t retreg;			/* d0 */
XX    reg_t d1;
XX--- 74,87 ----
XX    u16_t pad;
XX  #endif
XX  };
XX  #endif /* (CHIP == INTEL) */
XX  
XX  #if (CHIP == M68000)
XX+ typedef _PROTOTYPE( void (*dmaint_t), (void) );
XX+ 
XX  typedef u32_t reg_t;		/* machine register */
XX  
XX! /* The name and fields of this struct were chosen for PC compatibility. */
XX  struct stackframe_s {
XX    reg_t retreg;			/* d0 */
XX    reg_t d1;
XX***************
XX*** 101,110 ****
XX    reg_t a3;
XX    reg_t a4;
XX    reg_t a5;
XX!   reg_t a6;
XX    reg_t sp;			/* also known as a7 */
XX    reg_t pc;
XX    u16_t psw;
XX    u16_t dummy;			/* make size multiple of reg_t for system.c */
XX  };
XX  #endif /* (CHIP == M68000) */
XX--- 97,132 ----
XX    reg_t a3;
XX    reg_t a4;
XX    reg_t a5;
XX!   reg_t fp;			/* also known as a6 */
XX    reg_t sp;			/* also known as a7 */
XX    reg_t pc;
XX    u16_t psw;
XX    u16_t dummy;			/* make size multiple of reg_t for system.c */
XX  };
XX+ 
XX+ struct fsave {
XX+   struct cpu_state {
XX+ 	u16_t i_format;
XX+ 	u32_t i_addr;
XX+ 	u16_t i_state[4];
XX+   } cpu_state;
XX+   struct state_frame {
XX+ 	u8_t frame_type;
XX+ 	u8_t frame_size;
XX+ 	u16_t reserved;
XX+ 	u8_t frame[212];
XX+   } state_frame;
XX+   struct fpp_model {
XX+ 	u32_t fpcr;
XX+ 	u32_t fpsr;
XX+ 	u32_t fpiar;
XX+ 	struct fpN {
XX+ 		u32_t high;
XX+ 		u32_t low;
XX+ 		u32_t mid;
XX+ 	} fpN[8];
XX+   } fpp_model;
XX+ };
XX  #endif /* (CHIP == M68000) */
XX+ 
XX+ #endif /* TYPE_H */
X/
Xecho x - xt_wini.c.d
Xsed '/^X/s///' > xt_wini.c.d << '/'
XX*** /home/top/ast/minix/1.5/kernel/xt_wini.c  crc=17134  27766	Sat Apr 21 22:26:24 1990
XX--- /home/top/ast/minix/1.6.25/kernel/xt_wini.c  crc=03271  28580	Wed Nov  4 14:42:12 1992
XX***************
XX*** 10,19 ****
XX   *
XX   *	m_type	  DEVICE   PROC_NR	COUNT	 POSITION  ADRRESS
XX   * ----------------------------------------------------------------
XX!  * |  DISK_READ | device  | proc nr |  bytes  |	 offset | buf ptr |
XX   * |------------+---------+---------+---------+---------+---------|
XX!  * | DISK_WRITE | device  | proc nr |  bytes  |	 offset | buf ptr |
XX!  * ----------------------------------------------------------------
XX   * |SCATTERED_IO| device  | proc nr | requests|         | iov ptr |
XX   * ----------------------------------------------------------------
XX   *
XX--- 10,23 ----
XX   *
XX   *	m_type	  DEVICE   PROC_NR	COUNT	 POSITION  ADRRESS
XX   * ----------------------------------------------------------------
XX!  * |  DEV_OPEN  |         |         |         |         |         |
XX   * |------------+---------+---------+---------+---------+---------|
XX!  * |  DEV_CLOSE |         |         |         |         |         |
XX!  * |------------+---------+---------+---------+---------+---------|
XX!  * |  DEV_READ  | device  | proc nr |  bytes  |	 offset | buf ptr |
XX!  * |------------+---------+---------+---------+---------+---------|
XX!  * |  DEV_WRITE[D | device  | proc nr |  bytes  |	 offset | buf ptr |
XX!  * |------------+---------+---------+---------+---------+---------|
XX   * |SCATTERED_IO| device  | proc nr | requests|         | iov ptr |
XX   * ----------------------------------------------------------------
XX   *
XX***************
XX*** 52,61 ****
XX  #define WIN_SENSE	0x03	/* command for the controller to get its status */
XX  #define WIN_READ	0x08	/* command for the drive to read */
XX  #define WIN_WRITE	0x0a	/* command for the drive to write */
XX! #define WIN_SPECIFY	0x0C	/* command for the controller to accept params	*/
XX! #define WIN_ECC_READ	0x0D	/* command for the controller to read ecc length */
XX  
XX! #define DMA_INT		   3 /* Command with dma and interrupt */
XX  #define INT		   2	/* Command with interrupt, no dma */
XX  #define NO_DMA_INT	   0	/* Command without dma and interrupt */
XX  
XX--- 56,65 ----
XX  #define WIN_SENSE	0x03	/* command for the controller to get its status */
XX  #define WIN_READ	0x08	/* command for the drive to read */
XX  #define WIN_WRITE	0x0a	/* command for the drive to write */
XX! #define WIN_SPECIFY	0x0C	/* command for the controller: accept params */
XX! #define WIN_ECC_READ	0x0D	/* command for the controller: read ecc len */
XX  
XX! #define DMA_INT		   3	/* Command with dma and interrupt */
XX  #define INT		   2	/* Command with interrupt, no dma */
XX  #define NO_DMA_INT	   0	/* Command without dma and interrupt */
XX  
XX***************
XX*** 84,93 ****
XX  #define NR_DEVICES      (MAX_DRIVES * DEV_PER_DRIVE)
XX  #define MAX_WIN_RETRY  32000	/* max # times to try to output to WIN */
XX  #if AUTO_BIOS
XX! #define AUTO_PARAM     0x1AD	/* drive parameter table starts here in sect 0	*/
XX  #define AUTO_ENABLE	0x10	/* auto bios enabled bit from status reg */
XX! /* some start up parameters in order to extract the drive parameter table */
XX! /* from the winchester. these should not need changed. */
XX  #define AUTO_CYLS	 306	/* default number of cylinders */
XX  #define AUTO_HEADS	   4	/* default number of heads */
XX  #define AUTO_RWC	 307	/* default reduced write cylinder */
XX--- 88,99 ----
XX  #define NR_DEVICES      (MAX_DRIVES * DEV_PER_DRIVE)
XX  #define MAX_WIN_RETRY  32000	/* max # times to try to output to WIN */
XX  #if AUTO_BIOS
XX! #define AUTO_PARAM     0x1AD	/* drive param table starts here in sect 0 */
XX  #define AUTO_ENABLE	0x10	/* auto bios enabled bit from status reg */
XX! 
XX! /* Some start up parameters in order to extract the drive parameter table
XX!  * from the winchester. These should not need changed.
XX!  */
XX  #define AUTO_CYLS	 306	/* default number of cylinders */
XX  #define AUTO_HEADS	   4	/* default number of heads */
XX  #define AUTO_RWC	 307	/* default reduced write cylinder */
XX***************
XX*** 100,106 ****
XX  PUBLIC int using_bios = FALSE;	/* this disk driver does not use the BIOS */
XX  
XX  PRIVATE struct wini {		/* main drive struct, one entry per drive */
XX!   int wn_opcode;		/* DISK_READ or DISK_WRITE */
XX    int wn_procnr;		/* which proc wanted this operation? */
XX    int wn_drive;			/* drive number addressed (<< 5) */
XX    int wn_cylinder;		/* cylinder number addressed */
XX--- 106,112 ----
XX  PUBLIC int using_bios = FALSE;	/* this disk driver does not use the BIOS */
XX  
XX  PRIVATE struct wini {		/* main drive struct, one entry per drive */
XX!   int wn_opcode;		/* DEV_READ or DEV_WRITE */
XX    int wn_procnr;		/* which proc wanted this operation? */
XX    int wn_drive;			/* drive number addressed (<< 5) */
XX    int wn_cylinder;		/* cylinder number addressed */
XX***************
XX*** 115,121 ****
XX    char wn_results[MAX_RESULTS];	/* the controller can give lots of output */
XX  } wini[NR_DEVICES];
XX  
XX! PRIVATE int w_need_reset = FALSE;	 /* set to 1 when controller must be reset	*/
XX  PRIVATE int nr_drives;		 /* Number of drives */
XX  
XX  PRIVATE message w_mess;		/* message buffer for in and out */
XX--- 121,127 ----
XX    char wn_results[MAX_RESULTS];	/* the controller can give lots of output */
XX  } wini[NR_DEVICES];
XX  
XX! PRIVATE int w_need_reset = FALSE; /* set to 1 when controller must be reset */
XX  PRIVATE int nr_drives;		 /* Number of drives */
XX  
XX  PRIVATE message w_mess;		/* message buffer for in and out */
XX***************
XX*** 135,160 ****
XX  	int ctrl_byte;		/* Copied control-byte from bios tables */
XX  } param0, param1;
XX  
XX! FORWARD int check_init();
XX! FORWARD int com_out();
XX! FORWARD void copy_param();
XX! FORWARD void copy_prt();
XX! FORWARD int  hd_wait();
XX! FORWARD void init_params();
XX! FORWARD int old_win_results();
XX! FORWARD int read_ecc();
XX! FORWARD void sort();
XX! FORWARD int w_do_rdwt();
XX! FORWARD void w_dma_setup();
XX! FORWARD int w_reset();
XX! FORWARD int w_transfer();
XX! FORWARD void w_wait_int();
XX! FORWARD void win_out();
XX! FORWARD int win_specify();
XX! FORWARD int win_results();
XX  
XX  /*=========================================================================*
XX!  *							winchester_task					 			   * 
XX   *=========================================================================*/
XX  PUBLIC void winchester_task()
XX  {
XX--- 141,166 ----
XX  	int ctrl_byte;		/* Copied control-byte from bios tables */
XX  } param0, param1;
XX  
XX! FORWARD _PROTOTYPE( int check_init, (void) );
XX! FORWARD _PROTOTYPE( int com_out, (int mode) );
XX! FORWARD _PROTOTYPE( void copy_param, (unsigned char *src, struct param *dest));
XX! FORWARD _PROTOTYPE( void copy_prt, (int base_dev) );
XX! FORWARD _PROTOTYPE( int  hd_wait, (int bits) );
XX! FORWARD _PROTOTYPE( void init_params, (void) );
XX! FORWARD _PROTOTYPE( int old_win_results, (struct wini *wn) );
XX! FORWARD _PROTOTYPE( int read_ecc, (void) );
XX! FORWARD _PROTOTYPE( void sort, (struct wini wn[]) );
XX! FORWARD _PROTOTYPE( int w_do_rdwt, (message *m_ptr) );
XX! FORWARD _PROTOTYPE( void w_dma_setup, (struct wini *wn) );
XX! FORWARD _PROTOTYPE( int w_reset, (void) );
XX! FORWARD _PROTOTYPE( int w_transfer, (struct wini *wn) );
XX! FORWARD _PROTOTYPE( void w_wait_int, (void) );
XX! FORWARD _PROTOTYPE( void win_out, (int val) );
XX! FORWARD _PROTOTYPE( int win_specify, (int drive, struct param *parmp) );
XX! FORWARD _PROTOTYPE( int win_results, (struct wini *wn) );
XX  
XX  /*=========================================================================*
XX!  *				winchester_task	 			   * 
XX   *=========================================================================*/
XX  PUBLIC void winchester_task()
XX  {
XX***************
XX*** 173,179 ****
XX  	/* First wait for a request to read or write a disk block. */
XX  	receive(ANY, &w_mess);	/* get a request to do some work */
XX  	if (w_mess.m_source < 0) {
XX! 		printf("winchester task got message from %d ", w_mess.m_source);
XX  		continue;
XX  	}
XX  	caller = w_mess.m_source;
XX--- 179,185 ----
XX  	/* First wait for a request to read or write a disk block. */
XX  	receive(ANY, &w_mess);	/* get a request to do some work */
XX  	if (w_mess.m_source < 0) {
XX! 		printf("winchester task got message from %d ",w_mess.m_source);
XX  		continue;
XX  	}
XX  	caller = w_mess.m_source;
XX***************
XX*** 181,190 ****
XX  
XX  	/* Now carry out the work. */
XX  	switch(w_mess.m_type) {
XX! 		case DISK_READ:
XX! 		case DISK_WRITE:	r = w_do_rdwt(&w_mess);	break;
XX! 		case SCATTERED_IO:	r = do_vrdwt(&w_mess, w_do_rdwt); break;
XX! 		default:		r = EINVAL;		break;
XX  	}
XX  
XX  	/* Finally, prepare and send the reply message. */
XX--- 187,200 ----
XX  
XX  	/* Now carry out the work. */
XX  	switch(w_mess.m_type) {
XX! 	    case DEV_OPEN:	r = OK;				  break;
XX! 	    case DEV_CLOSE:	r = OK;				  break;
XX! 
XX! 	    case DEV_READ:
XX! 	    case DEV_WRITE:	r = w_do_rdwt(&w_mess);		  break;
XX! 
XX! 	    case SCATTERED_IO:	r = do_vrdwt(&w_mess, w_do_rdwt); break;
XX! 		default:		r = EINVAL;		  break;
XX  	}
XX  
XX  	/* Finally, prepare and send the reply message. */
XX***************
XX*** 198,204 ****
XX  
XX  
XX  /*==========================================================================*
XX!  *								w_do_rdwt						 			* 
XX   *==========================================================================*/
XX  PRIVATE int w_do_rdwt(m_ptr)
XX  message *m_ptr;			/* pointer to read or write w_message */
XX--- 208,214 ----
XX  
XX  
XX  /*==========================================================================*
XX!  *				w_do_rdwt	 			    * 
XX   *==========================================================================*/
XX  PRIVATE int w_do_rdwt(m_ptr)
XX  message *m_ptr;			/* pointer to read or write w_message */
XX***************
XX*** 206,212 ****
XX  /* Carry out a read or write request from the disk. */
XX    register struct wini *wn;
XX    int r, device, errors = 0;
XX!   long sector;
XX  
XX    /* Decode the w_message parameters. */
XX    device = m_ptr->DEVICE;
XX--- 216,222 ----
XX  /* Carry out a read or write request from the disk. */
XX    register struct wini *wn;
XX    int r, device, errors = 0;
XX!   long sector, s;
XX  
XX    /* Decode the w_message parameters. */
XX    device = m_ptr->DEVICE;
XX***************
XX*** 216,228 ****
XX  	return(EINVAL);
XX    wn = &wini[device];		/* 'wn' points to entry for this drive */
XX  
XX!   wn->wn_opcode = m_ptr->m_type;	/* DISK_READ or DISK_WRITE */
XX    if (m_ptr->POSITION % BLOCK_SIZE != 0)
XX  	return(EINVAL);
XX!   sector = m_ptr->POSITION/SECTOR_SIZE;
XX!   if ((sector+BLOCK_SIZE/SECTOR_SIZE) > wn->wn_size)
XX  	return(0);
XX!   sector += wn->wn_low;
XX    wn->wn_cylinder = sector / (wn->wn_heads * NR_SECTORS);
XX    wn->wn_sector =  (sector % NR_SECTORS);
XX    wn->wn_head = (sector % (wn->wn_heads * NR_SECTORS) )/NR_SECTORS;
XX--- 226,238 ----
XX  	return(EINVAL);
XX    wn = &wini[device];		/* 'wn' points to entry for this drive */
XX  
XX!   wn->wn_opcode = m_ptr->m_type;	/* DEV_READ or DEV_WRITE */
XX    if (m_ptr->POSITION % BLOCK_SIZE != 0)
XX  	return(EINVAL);
XX!   s = m_ptr->POSITION;
XX!   if (s < 0 || s > wn->wn_size * SECTOR_SIZE - BLOCK_SIZE)
XX  	return(0);
XX!   sector = s/SECTOR_SIZE + wn->wn_low;
XX    wn->wn_cylinder = sector / (wn->wn_heads * NR_SECTORS);
XX    wn->wn_sector =  (sector % NR_SECTORS);
XX    wn->wn_head = (sector % (wn->wn_heads * NR_SECTORS) )/NR_SECTORS;
XX***************
XX*** 253,259 ****
XX  
XX  
XX  /*==========================================================================*
XX!  *								w_dma_setup					 				* 
XX   *==========================================================================*/
XX  PRIVATE void w_dma_setup(wn)
XX  struct wini *wn;		/* pointer to the drive struct */
XX--- 263,269 ----
XX  
XX  
XX  /*==========================================================================*
XX!  *				w_dma_setup 				    * 
XX   *==========================================================================*/
XX  PRIVATE void w_dma_setup(wn)
XX  struct wini *wn;		/* pointer to the drive struct */
XX***************
XX*** 261,267 ****
XX  /* The IBM PC can perform DMA operations by using the DMA chip.	 To use it,
XX   * the DMA (Direct Memory Access) chip is loaded with the 20-bit memory address
XX   * to by read from or written to, the byte count minus 1, and a read or write
XX!  * opcode.	This routine sets up the DMA chip.	Note that the chip is not
XX   * capable of doing a DMA across a 64K boundary (e.g., you can't read a 
XX   * 512-byte block starting at physical address 65520).
XX   */
XX--- 271,277 ----
XX  /* The IBM PC can perform DMA operations by using the DMA chip.	 To use it,
XX   * the DMA (Direct Memory Access) chip is loaded with the 20-bit memory address
XX   * to by read from or written to, the byte count minus 1, and a read or write
XX!  * opcode.  This routine sets up the DMA chip.  Note that the chip is not
XX   * capable of doing a DMA across a 64K boundary (e.g., you can't read a 
XX   * 512-byte block starting at physical address 65520).
XX   */
XX***************
XX*** 270,276 ****
XX    vir_bytes vir, ct;
XX    phys_bytes user_phys;
XX  
XX!   mode = (wn->wn_opcode == DISK_READ ? DMA_READ : DMA_WRITE);
XX    vir = (vir_bytes) wn->wn_address;
XX    ct = (vir_bytes) wn->wn_count;
XX    user_phys = numap(wn->wn_procnr, vir, ct);
XX--- 280,286 ----
XX    vir_bytes vir, ct;
XX    phys_bytes user_phys;
XX  
XX!   mode = (wn->wn_opcode == DEV_READ ? DMA_READ : DMA_WRITE);
XX    vir = (vir_bytes) wn->wn_address;
XX    ct = (vir_bytes) wn->wn_count;
XX    user_phys = numap(wn->wn_procnr, vir, ct);
XX***************
XX*** 288,294 ****
XX    if (user_phys == 0)
XX  	  panic("FS gave winchester disk driver bad addr", (int) vir);
XX    top_end = (int) (((user_phys + ct - 1) >> 16) & BYTE);
XX!   if (top_end != top_addr) panic("Trying to DMA across 64K boundary", top_addr);
XX  
XX    /* Now set up the DMA registers. */
XX    out_byte(DMA_M2, mode);	/* set the DMA mode */
XX--- 298,304 ----
XX    if (user_phys == 0)
XX  	  panic("FS gave winchester disk driver bad addr", (int) vir);
XX    top_end = (int) (((user_phys + ct - 1) >> 16) & BYTE);
XX!   if (top_end != top_addr) panic("Trying to DMA across 64K boundary",top_addr);
XX  
XX    /* Now set up the DMA registers. */
XX    out_byte(DMA_M2, mode);	/* set the DMA mode */
XX***************
XX*** 301,307 ****
XX  }
XX  
XX  /*=========================================================================*
XX!  *								w_transfer								   *
XX   *=========================================================================*/
XX  PRIVATE int w_transfer(wn)
XX  register struct wini *wn;	/* pointer to the drive struct */
XX--- 311,317 ----
XX  }
XX  
XX  /*=========================================================================*
XX!  *				w_transfer				   *
XX   *=========================================================================*/
XX  PRIVATE int w_transfer(wn)
XX  register struct wini *wn;	/* pointer to the drive struct */
XX***************
XX*** 309,315 ****
XX  /* The drive is now on the proper cylinder.	 Read or write 1 block. */
XX  
XX    /* The command is issued by outputing 6 bytes to the controller chip. */
XX!   command[0] = (wn->wn_opcode == DISK_READ ? WIN_READ : WIN_WRITE);
XX    command[1] = wn->wn_head | wn->wn_drive;
XX    command[2] = (((wn->wn_cylinder & 0x0300) >> 2) | wn->wn_sector);
XX    command[3] = (wn->wn_cylinder & 0xFF);
XX--- 319,325 ----
XX  /* The drive is now on the proper cylinder.	 Read or write 1 block. */
XX  
XX    /* The command is issued by outputing 6 bytes to the controller chip. */
XX!   command[0] = (wn->wn_opcode == DEV_READ ? WIN_READ : WIN_WRITE);
XX    command[1] = wn->wn_head | wn->wn_drive;
XX    command[2] = (((wn->wn_cylinder & 0x0300) >> 2) | wn->wn_sector);
XX    command[3] = (wn->wn_cylinder & 0xFF);
XX***************
XX*** 334,342 ****
XX  }
XX  
XX  
XX! /*===========================================================================*
XX!  *				old_win_results					 * 
XX!  *===========================================================================*/
XX  PRIVATE int old_win_results(wn)
XX  register struct wini *wn;	/* pointer to the drive struct */
XX  {
XX--- 344,352 ----
XX  }
XX  
XX  
XX! /*==========================================================================*
XX!  *				old_win_results				    * 
XX!  *==========================================================================*/
XX  PRIVATE int old_win_results(wn)
XX  register struct wini *wn;	/* pointer to the drive struct */
XX  {
XX***************
XX*** 374,385 ****
XX  
XX  
XX  /*===========================================================================*
XX!  *				win_out						 * 
XX   *===========================================================================*/
XX  PRIVATE void win_out(val)
XX! int val;			/* write this byte to winchester disk controller */
XX  {
XX! /* Output a byte to the controller.	 This is not entirely trivial, since you
XX   * can only write to it when it is listening, and it decides when to listen.
XX   * If the controller refuses to listen, the WIN chip is given a hard reset.
XX   */
XX--- 384,395 ----
XX  
XX  
XX  /*===========================================================================*
XX!  *				win_out					     * 
XX   *===========================================================================*/
XX  PRIVATE void win_out(val)
XX! int val;			/* write byte to winchester disk controller */
XX  {
XX! /* Output a byte to the controller.  This is not entirely trivial, since you
XX   * can only write to it when it is listening, and it decides when to listen.
XX   * If the controller refuses to listen, the WIN chip is given a hard reset.
XX   */
XX***************
XX*** 395,401 ****
XX  }
XX  
XX  /*===========================================================================*
XX!  *				w_reset						 * 
XX   *===========================================================================*/
XX  PRIVATE int w_reset()
XX  {
XX--- 405,411 ----
XX  }
XX  
XX  /*===========================================================================*
XX!  *				w_reset					     * 
XX   *===========================================================================*/
XX  PRIVATE int w_reset()
XX  {
XX***************
XX*** 459,465 ****
XX  
XX  
XX  /*===========================================================================*
XX!  *				w_wait_int					 *
XX   *===========================================================================*/
XX  PRIVATE void w_wait_int()
XX  {
XX--- 469,475 ----
XX  
XX  
XX  /*===========================================================================*
XX!  *				w_wait_int				     *
XX   *===========================================================================*/
XX  PRIVATE void w_wait_int()
XX  {
XX***************
XX*** 477,496 ****
XX  		break;		/* Exit if end of int */
XX    }
XX  
XX! #if	 MONITOR
XX!    if(i > 10) {		/* Some arbitrary limit below which we don't really care */
XX  	if(i == MAX_WIN_RETRY)
XX  		printf("wini: timeout waiting for INTERRUPT status\n");
XX  	else
XX  		printf("wini: %d loops waiting for INTERRUPT status\n", i);
XX     }
XX! #endif	/* MONITOR */
XX  }
XX  
XX  
XX! /*============================================================================*
XX!  *				win_specify					  *
XX!  *============================================================================*/
XX  PRIVATE int win_specify(drive, paramp)
XX  int drive;
XX  struct param *paramp;
XX--- 487,506 ----
XX  		break;		/* Exit if end of int */
XX    }
XX  
XX! #if MONITOR
XX!    if (i > 10) {		/* arbitrary limit below which we don't care */
XX  	if(i == MAX_WIN_RETRY)
XX  		printf("wini: timeout waiting for INTERRUPT status\n");
XX  	else
XX  		printf("wini: %d loops waiting for INTERRUPT status\n", i);
XX     }
XX! #endif /* MONITOR */
XX  }
XX  
XX  
XX! /*===========================================================================*
XX!  *				win_specify				     *
XX!  *===========================================================================*/
XX  PRIVATE int win_specify(drive, paramp)
XX  int drive;
XX  struct param *paramp;
XX***************
XX*** 533,541 ****
XX    return(OK);
XX  }
XX  
XX! /*============================================================================*
XX!  *				check_init					  *
XX!  *============================================================================*/
XX  PRIVATE int check_init()
XX  {
XX  /* Routine to check if controller accepted the parameters */
XX--- 543,551 ----
XX    return(OK);
XX  }
XX  
XX! /*===========================================================================*
XX!  *				check_init				     *
XX!  *===========================================================================*/
XX  PRIVATE int check_init()
XX  {
XX  /* Routine to check if controller accepted the parameters */
XX***************
XX*** 560,568 ****
XX    }
XX  }
XX  
XX! /*============================================================================*
XX!  *				read_ecc					  *
XX!  *============================================================================*/
XX  PRIVATE int read_ecc()
XX  {
XX  /* Read the ecc burst-length and let the controller correct the data */
XX--- 570,578 ----
XX    }
XX  }
XX  
XX! /*===========================================================================*
XX!  *				read_ecc				     *
XX!  *===========================================================================*/
XX  PRIVATE int read_ecc()
XX  {
XX  /* Read the ecc burst-length and let the controller correct the data */
XX***************
XX*** 581,589 ****
XX    return(ERR);
XX  }
XX  
XX! /*============================================================================*
XX!  *				hd_wait						  *
XX!  *============================================================================*/
XX  PRIVATE int hd_wait(bits)
XX  register int bits;
XX  {
XX--- 591,599 ----
XX    return(ERR);
XX  }
XX  
XX! /*===========================================================================*
XX!  *				hd_wait					     *
XX!  *===========================================================================*/
XX  PRIVATE int hd_wait(bits)
XX  register int bits;
XX  {
XX***************
XX*** 603,611 ****
XX  	return(OK);
XX  }
XX  
XX! /*============================================================================*
XX!  *				com_out						  *
XX!  *============================================================================*/
XX  PRIVATE int com_out(mode)
XX  int mode;
XX  {
XX--- 613,621 ----
XX  	return(OK);
XX  }
XX  
XX! /*===========================================================================*
XX!  *				com_out					     *
XX!  *===========================================================================*/
XX  PRIVATE int com_out(mode)
XX  int mode;
XX  {
XX***************
XX*** 662,668 ****
XX    phys_bytes address;
XX  
XX    /* Get the number of drives from the bios */
XX!   phys_copy(0x475L, umap(proc_ptr, D, buf, 1), 1L);
XX    nr_drives = *buf & 0xFF;
XX    if (nr_drives > MAX_DRIVES) nr_drives = MAX_DRIVES;
XX  
XX--- 672,678 ----
XX    phys_bytes address;
XX  
XX    /* Get the number of drives from the bios */
XX!   phys_copy(0x475L, umap(proc_ptr, D, (vir_bytes) buf, 1), 1L);
XX    nr_drives = *buf & 0xFF;
XX    if (nr_drives > MAX_DRIVES) nr_drives = MAX_DRIVES;
XX  
XX***************
XX*** 670,683 ****
XX    i = in_byte(WIN_SELECT);
XX  
XX  #if AUTO_BIOS
XX!   /* Get the drive parameters from sector zero of the drive if the */
XX!   /* autoconfig mode of the controller has been selected */
XX! 
XX    if(i & AUTO_ENABLE) {
XX! 
XX! 	/* set up some phoney parameters so that we can read the first sector */
XX! 	/* from the winchester. all drives will have one cylinder and one head */
XX! 	/* but set up initially to the mini scribe drives from ibm */
XX  	param1.nr_cyl = param0.nr_cyl = AUTO_CYLS;
XX  	param1.nr_heads = param0.nr_heads = AUTO_HEADS;
XX  	param1.reduced_wr = param0.reduced_wr = AUTO_RWC;
XX--- 680,693 ----
XX    i = in_byte(WIN_SELECT);
XX  
XX  #if AUTO_BIOS
XX!   /* Get the drive parameters from sector zero of the drive if the
XX!    * autoconfig mode of the controller has been selected.
XX!    */
XX    if(i & AUTO_ENABLE) {
XX! 	/* Set up some phony parameters so that we can read the first sector
XX! 	 * from the winchester. All drives will have one cylinder and one head
XX! 	 * but set up initially to the mini scribe drives from ibm
XX! 	 */
XX  	param1.nr_cyl = param0.nr_cyl = AUTO_CYLS;
XX  	param1.nr_heads = param0.nr_heads = AUTO_HEADS;
XX  	param1.reduced_wr = param0.reduced_wr = AUTO_RWC;
XX***************
XX*** 695,707 ****
XX  
XX  	if (nr_drives > 1) {
XX  	  
XX! 	  /* generate the request to read the first sector from the winchester */
XX  	  w_mess.DEVICE = DEV_PER_DRIVE;
XX  	  w_mess.POSITION = 0L;
XX  	  w_mess.COUNT = BLOCK_SIZE;
XX  	  w_mess.ADDRESS = (char *) buf;
XX  	  w_mess.PROC_NR = WINCHESTER;
XX! 	  w_mess.m_type = DISK_READ;
XX  	  if(w_do_rdwt(&w_mess) != BLOCK_SIZE)
XX  		panic("cannot read drive parameters from winchester",DEV_PER_DRIVE);
XX  
XX--- 705,717 ----
XX  
XX  	if (nr_drives > 1) {
XX  	  
XX! 	  /* Generate the request to read the first sector from the disk. */
XX  	  w_mess.DEVICE = DEV_PER_DRIVE;
XX  	  w_mess.POSITION = 0L;
XX  	  w_mess.COUNT = BLOCK_SIZE;
XX  	  w_mess.ADDRESS = (char *) buf;
XX  	  w_mess.PROC_NR = WINCHESTER;
XX! 	  w_mess.m_type = DEV_READ;
XX  	  if(w_do_rdwt(&w_mess) != BLOCK_SIZE)
XX  		panic("cannot read drive parameters from winchester",DEV_PER_DRIVE);
XX  
XX***************
XX*** 716,722 ****
XX  	w_mess.COUNT = BLOCK_SIZE;
XX  	w_mess.ADDRESS = (char *) buf;
XX  	w_mess.PROC_NR = WINCHESTER;
XX! 	w_mess.m_type = DISK_READ;
XX  	if(w_do_rdwt(&w_mess) != BLOCK_SIZE)
XX  	  panic("cannot read drive parameters from winchester", 0);
XX  
XX--- 726,732 ----
XX  	w_mess.COUNT = BLOCK_SIZE;
XX  	w_mess.ADDRESS = (char *) buf;
XX  	w_mess.PROC_NR = WINCHESTER;
XX! 	w_mess.m_type = DEV_READ;
XX  	if(w_do_rdwt(&w_mess) != BLOCK_SIZE)
XX  	  panic("cannot read drive parameters from winchester", 0);
XX  
XX***************
XX*** 740,746 ****
XX  
XX    /* Calculate the address off the parameters and copy them to buf */
XX    address = hclick_to_physb(segment) + offset;
XX!   phys_copy(address, umap(proc_ptr, D, buf, 64), 64L);
XX  
XX    /* Copy the parameters to the structures */
XX    copy_param(&buf[type_0 * 16], &param0);
XX--- 750,756 ----
XX  
XX    /* Calculate the address off the parameters and copy them to buf */
XX    address = hclick_to_physb(segment) + offset;
XX!   phys_copy(address, umap(proc_ptr, D, (vir_bytes) buf, 64), 64L);
XX  
XX    /* Copy the parameters to the structures */
XX    copy_param(&buf[type_0 * 16], &param0);
XX***************
XX*** 782,788 ****
XX  	w_mess.COUNT = BLOCK_SIZE;
XX  	w_mess.ADDRESS = (char *) buf;
XX  	w_mess.PROC_NR = WINCHESTER;
XX! 	w_mess.m_type = DISK_READ;
XX  	if (w_do_rdwt(&w_mess) != BLOCK_SIZE) {
XX  		printf("Can't read partition table of winchester %d ", i);
XX  		continue;
XX--- 792,798 ----
XX  	w_mess.COUNT = BLOCK_SIZE;
XX  	w_mess.ADDRESS = (char *) buf;
XX  	w_mess.PROC_NR = WINCHESTER;
XX! 	w_mess.m_type = DEV_READ;
XX  	if (w_do_rdwt(&w_mess) != BLOCK_SIZE) {
XX  		printf("Can't read partition table of winchester %d ", i);
XX  		continue;
XX***************
XX*** 792,798 ****
XX  }
XX  
XX  /*==========================================================================*
XX!  *								copy_param					 				*
XX   *==========================================================================*/
XX  PRIVATE void copy_param(src, dest)
XX  register unsigned char *src;
XX--- 802,808 ----
XX  }
XX  
XX  /*==========================================================================*
XX!  *				copy_param 				    *
XX   *==========================================================================*/
XX  PRIVATE void copy_param(src, dest)
XX  register unsigned char *src;
XX***************
XX*** 800,806 ****
XX  {
XX  /* This routine copies the parameters from src to dest
XX   * and sets the parameters for partition 0 and DEV_PER_DRIVE
XX! */
XX  
XX    dest->nr_cyl = *(u16_t *)src;
XX    dest->nr_heads = (int)src[2];
XX--- 810,816 ----
XX  {
XX  /* This routine copies the parameters from src to dest
XX   * and sets the parameters for partition 0 and DEV_PER_DRIVE
XX!  */
XX  
XX    dest->nr_cyl = *(u16_t *)src;
XX    dest->nr_heads = (int)src[2];
X/
/
