From f07a4c844da9f0ecae5bbee1ab94be56505f26f7 Mon Sep 17 00:00:00 2001
From: Thomas Bushnell <thomas@gnu.org>
Date: Tue, 25 Feb 1997 21:28:37 +0000
Subject: Initial source

---
 i386/dos/dos_buf.c              |  29 +++
 i386/dos/dos_check_err.c        |  36 +++
 i386/dos/dos_close.c            |  39 +++
 i386/dos/dos_fstat.c            |  75 ++++++
 i386/dos/dos_gettimeofday.c     |  77 ++++++
 i386/dos/dos_io.h               |  85 ++++++
 i386/dos/dos_open.c             | 158 +++++++++++
 i386/dos/dos_read.c             |  75 ++++++
 i386/dos/dos_rename.c           |  80 ++++++
 i386/dos/dos_seek.c             |  45 ++++
 i386/dos/dos_tcgetattr.c        |  51 ++++
 i386/dos/dos_unlink.c           |  48 ++++
 i386/dos/dos_write.c            |  75 ++++++
 i386/dos/i16/gdt.h              |  32 +++
 i386/dos/i16/gdt_sels.h         |  36 +++
 i386/dos/i16/i16_crt0.S         | 274 +++++++++++++++++++
 i386/dos/i16/i16_crt0.h         |  32 +++
 i386/dos/i16/i16_dos.h          | 146 +++++++++++
 i386/dos/i16/i16_dos_mem.c      | 182 +++++++++++++
 i386/dos/i16/i16_exit.c         |  50 ++++
 i386/dos/i16/i16_main.c         |  60 +++++
 i386/dos/i16/i16_putchar.c      |  36 +++
 i386/dos/i16/i16_vcpi.c         | 564 ++++++++++++++++++++++++++++++++++++++++
 i386/dos/i16/i16_xms.c          | 175 +++++++++++++
 i386/dos/i16/idt.h              |  39 +++
 i386/dos/i16/phys_mem_sources.h |  28 ++
 i386/dos/putchar.c              |  41 +++
 27 files changed, 2568 insertions(+)
 create mode 100644 i386/dos/dos_buf.c
 create mode 100644 i386/dos/dos_check_err.c
 create mode 100644 i386/dos/dos_close.c
 create mode 100644 i386/dos/dos_fstat.c
 create mode 100644 i386/dos/dos_gettimeofday.c
 create mode 100644 i386/dos/dos_io.h
 create mode 100644 i386/dos/dos_open.c
 create mode 100644 i386/dos/dos_read.c
 create mode 100644 i386/dos/dos_rename.c
 create mode 100644 i386/dos/dos_seek.c
 create mode 100644 i386/dos/dos_tcgetattr.c
 create mode 100644 i386/dos/dos_unlink.c
 create mode 100644 i386/dos/dos_write.c
 create mode 100644 i386/dos/i16/gdt.h
 create mode 100644 i386/dos/i16/gdt_sels.h
 create mode 100644 i386/dos/i16/i16_crt0.S
 create mode 100644 i386/dos/i16/i16_crt0.h
 create mode 100644 i386/dos/i16/i16_dos.h
 create mode 100644 i386/dos/i16/i16_dos_mem.c
 create mode 100644 i386/dos/i16/i16_exit.c
 create mode 100644 i386/dos/i16/i16_main.c
 create mode 100644 i386/dos/i16/i16_putchar.c
 create mode 100644 i386/dos/i16/i16_vcpi.c
 create mode 100644 i386/dos/i16/i16_xms.c
 create mode 100644 i386/dos/i16/idt.h
 create mode 100644 i386/dos/i16/phys_mem_sources.h
 create mode 100644 i386/dos/putchar.c

(limited to 'i386/dos')

diff --git a/i386/dos/dos_buf.c b/i386/dos/dos_buf.c
new file mode 100644
index 0000000..5c7fcd8
--- /dev/null
+++ b/i386/dos/dos_buf.c
@@ -0,0 +1,29 @@
+/* 
+ * Copyright (c) 1995-1994 The University of Utah and
+ * the Computer Systems Laboratory at the University of Utah (CSL).
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify and distribute this software is hereby
+ * granted provided that (1) source code retains these copyright, permission,
+ * and disclaimer notices, and (2) redistributions including binaries
+ * reproduce the notices in supporting documentation, and (3) all advertising
+ * materials mentioning features or use of this software display the following
+ * acknowledgement: ``This product includes software developed by the
+ * Computer Systems Laboratory at the University of Utah.''
+ *
+ * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS
+ * IS" CONDITION.  THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF
+ * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * CSL requests users of this software to return to csl-dist@cs.utah.edu any
+ * improvements that they make and grant CSL redistribution rights.
+ *
+ *      Author: Bryan Ford, University of Utah CSL
+ */
+
+#include "dos_io.h"
+
+#ifndef DOS_BUF_DYNAMIC
+char dos_buf[DOS_BUF_SIZE];
+#endif
+
diff --git a/i386/dos/dos_check_err.c b/i386/dos/dos_check_err.c
new file mode 100644
index 0000000..07aa651
--- /dev/null
+++ b/i386/dos/dos_check_err.c
@@ -0,0 +1,36 @@
+/* 
+ * Copyright (c) 1995-1994 The University of Utah and
+ * the Computer Systems Laboratory at the University of Utah (CSL).
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify and distribute this software is hereby
+ * granted provided that (1) source code retains these copyright, permission,
+ * and disclaimer notices, and (2) redistributions including binaries
+ * reproduce the notices in supporting documentation, and (3) all advertising
+ * materials mentioning features or use of this software display the following
+ * acknowledgement: ``This product includes software developed by the
+ * Computer Systems Laboratory at the University of Utah.''
+ *
+ * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS
+ * IS" CONDITION.  THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF
+ * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * CSL requests users of this software to return to csl-dist@cs.utah.edu any
+ * improvements that they make and grant CSL redistribution rights.
+ *
+ *      Author: Bryan Ford, University of Utah CSL
+ */
+
+#include <mach/error.h>
+#include <mach/machine/eflags.h>
+
+#include "dos_io.h"
+
+int dos_check_err(struct real_call_data *rcd)
+{
+	if (rcd->flags & EFL_CF)
+		return err_dos + (rcd->eax & 0xffff);
+	else
+		return 0;
+}
+
diff --git a/i386/dos/dos_close.c b/i386/dos/dos_close.c
new file mode 100644
index 0000000..d3d0d00
--- /dev/null
+++ b/i386/dos/dos_close.c
@@ -0,0 +1,39 @@
+/* 
+ * Copyright (c) 1995-1994 The University of Utah and
+ * the Computer Systems Laboratory at the University of Utah (CSL).
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify and distribute this software is hereby
+ * granted provided that (1) source code retains these copyright, permission,
+ * and disclaimer notices, and (2) redistributions including binaries
+ * reproduce the notices in supporting documentation, and (3) all advertising
+ * materials mentioning features or use of this software display the following
+ * acknowledgement: ``This product includes software developed by the
+ * Computer Systems Laboratory at the University of Utah.''
+ *
+ * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS
+ * IS" CONDITION.  THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF
+ * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * CSL requests users of this software to return to csl-dist@cs.utah.edu any
+ * improvements that they make and grant CSL redistribution rights.
+ *
+ *      Author: Bryan Ford, University of Utah CSL
+ */
+
+#include <unistd.h>
+#include <errno.h>
+
+#include "dos_io.h"
+
+int dos_close(dos_fd_t fd)
+{
+	struct real_call_data real_call_data;
+
+	dos_init_rcd(&real_call_data);
+	real_call_data.eax = 0x3e00;
+	real_call_data.ebx = fd;
+	real_int(0x21, &real_call_data);
+	return dos_check_err(&real_call_data);
+}
+
diff --git a/i386/dos/dos_fstat.c b/i386/dos/dos_fstat.c
new file mode 100644
index 0000000..0c48016
--- /dev/null
+++ b/i386/dos/dos_fstat.c
@@ -0,0 +1,75 @@
+/* 
+ * Copyright (c) 1995-1994 The University of Utah and
+ * the Computer Systems Laboratory at the University of Utah (CSL).
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify and distribute this software is hereby
+ * granted provided that (1) source code retains these copyright, permission,
+ * and disclaimer notices, and (2) redistributions including binaries
+ * reproduce the notices in supporting documentation, and (3) all advertising
+ * materials mentioning features or use of this software display the following
+ * acknowledgement: ``This product includes software developed by the
+ * Computer Systems Laboratory at the University of Utah.''
+ *
+ * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS
+ * IS" CONDITION.  THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF
+ * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * CSL requests users of this software to return to csl-dist@cs.utah.edu any
+ * improvements that they make and grant CSL redistribution rights.
+ *
+ *      Author: Bryan Ford, University of Utah CSL
+ */
+
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/stat.h>
+
+#include "dos_io.h"
+
+int dos_fstat(dos_fd_t fd, struct stat *st)
+{
+	int err;
+	int actual = 0;
+	struct real_call_data real_call_data;
+	vm_offset_t old_pos, new_pos;
+
+	dos_init_rcd(&real_call_data);
+
+	bzero(st, sizeof(*st));
+	st->st_nlink = 1;
+	st->st_mode = S_IRWXU | S_IRWXG | S_IRWXO; /* XXX attributes */
+
+	/* Get device information,
+	   which will tell us whether this is a character device
+	   or a regular file.  */
+	real_call_data.eax = 0x4400;
+	real_call_data.ebx = fd;
+	real_int(0x21, &real_call_data);
+	if (err = dos_check_err(&real_call_data))
+		return err;
+	if (real_call_data.edx & (1<<7))
+		st->st_mode |= S_IFCHR;
+	else
+		st->st_mode |= S_IFREG;
+
+	/* XXX get date/time with int 21 5700 */
+
+	/* Get file size by seeking to the end and back.  */
+	if (!dos_seek(fd, 0, 1, &old_pos)
+	    && !dos_seek(fd, 0, 2, &st->st_size))
+	{
+		if (err = dos_seek(fd, old_pos, 0, &new_pos))
+			return err;
+		if (new_pos != old_pos)
+			return EIO;/*XXX*/
+	}
+
+	/* Always assume 512-byte blocks for now... */
+	st->st_blocks = (st->st_size + 511) / 512;
+	st->st_blksize = 512;
+
+	return 0;
+}
+
diff --git a/i386/dos/dos_gettimeofday.c b/i386/dos/dos_gettimeofday.c
new file mode 100644
index 0000000..3b61bab
--- /dev/null
+++ b/i386/dos/dos_gettimeofday.c
@@ -0,0 +1,77 @@
+/* 
+ * Copyright (c) 1995-1994 The University of Utah and
+ * the Computer Systems Laboratory at the University of Utah (CSL).
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify and distribute this software is hereby
+ * granted provided that (1) source code retains these copyright, permission,
+ * and disclaimer notices, and (2) redistributions including binaries
+ * reproduce the notices in supporting documentation, and (3) all advertising
+ * materials mentioning features or use of this software display the following
+ * acknowledgement: ``This product includes software developed by the
+ * Computer Systems Laboratory at the University of Utah.''
+ *
+ * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS
+ * IS" CONDITION.  THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF
+ * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * CSL requests users of this software to return to csl-dist@cs.utah.edu any
+ * improvements that they make and grant CSL redistribution rights.
+ *
+ *      Author: Bryan Ford, University of Utah CSL
+ */
+
+#include <unistd.h>
+#include <errno.h>
+#include <sys/time.h>
+
+#include "dos_io.h"
+#include "debug.h"
+
+int dos_gettimeofday(struct timeval *tv, struct timezone *tz)
+{
+	static int daysofmonth[12] = {31, 28, 31, 30, 31, 30, 31,
+				      31, 30, 31, 30, 31};
+
+	struct real_call_data real_call_data;
+	int err;
+
+	dos_init_rcd(&real_call_data);
+
+	if (tv)
+	{
+		int year, month, day, hour, min, sec, hund;
+
+		real_call_data.eax = 0x2a00;
+		real_int(0x21, &real_call_data);
+		year = real_call_data.ecx & 0xffff;
+		month = (real_call_data.edx >> 8) & 0xff;
+		day = real_call_data.edx & 0xff;
+		real_call_data.eax = 0x2c00;
+		real_int(0x21, &real_call_data);
+		if (err = dos_check_err(&real_call_data))
+			return err;
+
+		hour = (real_call_data.ecx >> 8) & 0xff;
+		min = real_call_data.ecx & 0xff;
+		sec = (real_call_data.edx >> 8) & 0xff;
+		hund = real_call_data.edx & 0xff;
+
+		tv->tv_sec = (year - 1970) * (365 * 24 * 60 * 60);
+		tv->tv_sec += (year - 1970) / 4 * (24 * 60 * 60); /* XXX??? */
+		tv->tv_sec += daysofmonth[month-1] * (24 * 60 * 60);
+		if ((((year - 1970) % 4) == 0) && (month > 2)) /* XXX??? */
+			tv->tv_sec += 24 * 60 * 60;
+		tv->tv_sec += day * 24 * 60 * 60;
+		tv->tv_sec += hour * 60 * 60;
+		tv->tv_sec += min * 60;
+		tv->tv_sec += sec;
+		tv->tv_usec = hund * (1000000 / 100);
+	}
+	if (tz)
+		return EINVAL; /*XXX*/
+
+	assert(tz == 0);
+	return 0;
+}
+
diff --git a/i386/dos/dos_io.h b/i386/dos/dos_io.h
new file mode 100644
index 0000000..990d08c
--- /dev/null
+++ b/i386/dos/dos_io.h
@@ -0,0 +1,85 @@
+/* 
+ * Copyright (c) 1995-1994 The University of Utah and
+ * the Computer Systems Laboratory at the University of Utah (CSL).
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify and distribute this software is hereby
+ * granted provided that (1) source code retains these copyright, permission,
+ * and disclaimer notices, and (2) redistributions including binaries
+ * reproduce the notices in supporting documentation, and (3) all advertising
+ * materials mentioning features or use of this software display the following
+ * acknowledgement: ``This product includes software developed by the
+ * Computer Systems Laboratory at the University of Utah.''
+ *
+ * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS
+ * IS" CONDITION.  THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF
+ * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * CSL requests users of this software to return to csl-dist@cs.utah.edu any
+ * improvements that they make and grant CSL redistribution rights.
+ *
+ *      Author: Bryan Ford, University of Utah CSL
+ */
+#ifndef _i386_kernel_dos_dos_io_h_
+#define _i386_kernel_dos_dos_io_h_
+
+#include <mach/machine/vm_types.h>
+
+#include "real.h"
+#include "debug.h"
+
+struct stat;
+struct timeval;
+struct timezone;
+struct termios;
+
+typedef int dos_fd_t;
+
+/* Maximum number of bytes we can read or write with one DOS call
+   to or from memory not in the low 1MB accessible to DOS.
+   Must be less than 64KB.
+   Try to keep this size on a sector (512-byte) boundary for performance.  */
+#ifndef DOS_BUF_SIZE
+#define DOS_BUF_SIZE 0x1000
+#endif
+
+/* If DOS_BUF_DYNAMIC is set, then dos_buf is a pointer
+   which must be provided and initialized by calling code.
+   Otherwise, the dos_buf is a statically-allocated bss array.  */
+#ifdef DOS_BUF_DYNAMIC
+extern char *dos_buf;
+#else
+extern char dos_buf[DOS_BUF_SIZE];
+#endif
+
+int dos_check_err(struct real_call_data *rcd);
+
+int dos_open(const char *s, int flags, int create_mode, dos_fd_t *out_fh);
+int dos_close(dos_fd_t fd);
+int dos_read(dos_fd_t fd, void *buf, vm_size_t size, vm_size_t *out_actual);
+int dos_write(dos_fd_t fd, const void *buf, vm_size_t size, vm_size_t *out_actual);
+int dos_seek(dos_fd_t fd, vm_offset_t offset, int whence, vm_offset_t *out_newpos);
+int dos_fstat(dos_fd_t fd, struct stat *st);
+int dos_tcgetattr(dos_fd_t fd, struct termios *t);
+int dos_rename(const char *oldpath, const char *newpath);
+int dos_unlink(const char *filename);
+
+int dos_gettimeofday(struct timeval *tv, struct timezone *tz);
+
+#define dos_init_rcd(rcd) real_call_data_init(rcd)
+
+#define real_set_ds_dx(ptr)				\
+	({ unsigned ofs = (unsigned)(ptr);		\
+	   assert(ofs < 0x10000);			\
+	   real_call_data.ds = real_cs;			\
+	   real_call_data.edx = ofs;			\
+	})
+#define real_set_es_di(ptr)				\
+	({ unsigned ofs = (unsigned)(ptr);		\
+	   assert(ofs < 0x10000);			\
+	   real_call_data.es = real_cs;			\
+	   real_call_data.edi = ofs;			\
+	})
+
+
+#endif _i386_kernel_dos_dos_io_h_
diff --git a/i386/dos/dos_open.c b/i386/dos/dos_open.c
new file mode 100644
index 0000000..7e6ef2b
--- /dev/null
+++ b/i386/dos/dos_open.c
@@ -0,0 +1,158 @@
+/* 
+ * Copyright (c) 1995-1994 The University of Utah and
+ * the Computer Systems Laboratory at the University of Utah (CSL).
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify and distribute this software is hereby
+ * granted provided that (1) source code retains these copyright, permission,
+ * and disclaimer notices, and (2) redistributions including binaries
+ * reproduce the notices in supporting documentation, and (3) all advertising
+ * materials mentioning features or use of this software display the following
+ * acknowledgement: ``This product includes software developed by the
+ * Computer Systems Laboratory at the University of Utah.''
+ *
+ * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS
+ * IS" CONDITION.  THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF
+ * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * CSL requests users of this software to return to csl-dist@cs.utah.edu any
+ * improvements that they make and grant CSL redistribution rights.
+ *
+ *      Author: Bryan Ford, University of Utah CSL
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <errno.h>
+
+#include "dos_io.h"
+#include "vm_param.h"
+#include "debug.h"
+
+int dos_open(const char *s, int flags, int mode, dos_fd_t *out_fh)
+{
+	struct real_call_data real_call_data;
+	int err = EINVAL; /*XXX*/
+	vm_offset_t dos_buf_phys = (vm_offset_t)kvtophys(dos_buf);
+
+	assert(dos_buf); assert(dos_buf_phys);
+	assert(dos_buf_phys < 0x100000);
+
+	dos_init_rcd(&real_call_data);
+
+	if (strlen(s)+1 > DOS_BUF_SIZE)
+		return E2BIG;
+	strcpy(dos_buf, s);
+	real_call_data.ds = dos_buf_phys >> 4;
+	real_call_data.edx = dos_buf_phys & 15;
+
+	/* Possible situations:
+
+	-	3d
+	C	3d || 3c
+	 T	3d (ensure that it exists), close, 3c
+	CT	3c
+	  X	3d
+	C X	3d (ensure that it doesn't exist), 3c
+	 TX	3d (ensure that it exists), close, 3c
+	CTX	3d (ensure that it doesn't exist), 3c
+	*/
+
+	if ((flags & (O_CREAT | O_EXCL | O_TRUNC)) != (O_CREAT | O_TRUNC))
+	{
+		/* First try opening the file with function 0x3D.  */
+		real_call_data.eax = 0x3d40 | (flags & O_ACCMODE);
+		real_call_data.ecx = 0;
+		real_int(0x21, &real_call_data);
+		err = dos_check_err(&real_call_data);
+		if (!err)
+			*out_fh = real_call_data.eax & 0xffff;
+	}
+
+	/* Now based on the result, determine what to do next.  */
+	switch (flags & (O_CREAT | O_EXCL | O_TRUNC))
+	{
+		case 0:
+		case 0 | O_EXCL:
+			if (!err)
+				goto success;
+			else
+				return err;
+		case O_CREAT:
+			if (!err)
+				goto success;
+			else
+				break;
+		case O_CREAT | O_EXCL:
+		case O_CREAT | O_TRUNC | O_EXCL:
+			if (!err)
+			{
+				/* The file exists, but wasn't supposed to.
+				   Close it and return an error.  */
+				dos_close(real_call_data.eax & 0xffff);
+				return EEXIST;
+			}
+			else
+				break;
+		case O_TRUNC:
+		case O_TRUNC | O_EXCL:
+			if (!err)
+			{
+				/* We've verified that the file exists -
+				   now close it and reopen it with CREAT
+				   so it'll be truncated as requested.  */
+				dos_close(real_call_data.eax & 0xffff);
+				break;
+			}
+			else
+				return err;
+		case O_CREAT | O_TRUNC:
+			/* This is the one case in which
+			   we didn't try to open the file above at all.
+			   Just fall on through and open it with CREAT.  */
+			break;
+	}
+
+	/* Now try opening the file with DOS's CREAT call,
+	   which truncates the file if it already exists.  */
+	real_call_data.eax = 0x3c00;
+	real_call_data.ecx = mode & S_IWUSR ? 0 : 1;
+	real_int(0x21, &real_call_data);
+	if (!(err = dos_check_err(&real_call_data)))
+	{
+		*out_fh = real_call_data.eax & 0xffff;
+
+		/* We don't have to worry about O_APPEND here,
+		   because we know the file starts out empty.  */
+
+		return 0;
+	}
+
+	return err;
+
+	success:
+
+	/* If the caller requested append access,
+	   just seek to the end of the file once on open.
+	   We can't implement full POSIX behavior here without help,
+	   since DOS file descriptors don't have an append mode.
+	   To get full POSIX behavior,
+	   the caller must seek to the end of the file before every write.
+	   However, seeking to the end only on open
+	   is probably enough for most typical uses.  */
+	if (flags & O_APPEND)
+	{
+		vm_offset_t newpos;
+		err = dos_seek(*out_fh, 0, SEEK_END, &newpos);
+		if (err)
+		{
+			dos_close(*out_fh);
+			return err;
+		}
+	}
+
+	return 0;
+}
+
diff --git a/i386/dos/dos_read.c b/i386/dos/dos_read.c
new file mode 100644
index 0000000..ae7213f
--- /dev/null
+++ b/i386/dos/dos_read.c
@@ -0,0 +1,75 @@
+/* 
+ * Copyright (c) 1995-1994 The University of Utah and
+ * the Computer Systems Laboratory at the University of Utah (CSL).
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify and distribute this software is hereby
+ * granted provided that (1) source code retains these copyright, permission,
+ * and disclaimer notices, and (2) redistributions including binaries
+ * reproduce the notices in supporting documentation, and (3) all advertising
+ * materials mentioning features or use of this software display the following
+ * acknowledgement: ``This product includes software developed by the
+ * Computer Systems Laboratory at the University of Utah.''
+ *
+ * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS
+ * IS" CONDITION.  THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF
+ * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * CSL requests users of this software to return to csl-dist@cs.utah.edu any
+ * improvements that they make and grant CSL redistribution rights.
+ *
+ *      Author: Bryan Ford, University of Utah CSL
+ */
+
+#include <unistd.h>
+#include <errno.h>
+
+#include "dos_io.h"
+#include "vm_param.h"
+
+int dos_read(dos_fd_t fd, void *buf, vm_size_t size, vm_size_t *out_actual)
+{
+	int err;
+	int actual = 0;
+	struct real_call_data real_call_data;
+	vm_offset_t dos_buf_phys = (vm_offset_t)kvtophys(dos_buf);
+
+	assert(dos_buf); assert(dos_buf_phys);
+	assert(dos_buf_phys < 0x100000);
+
+	dos_init_rcd(&real_call_data);
+
+	while (size > 0)
+	{
+		int little_size = size;
+		int little_actual;
+
+		if (little_size > DOS_BUF_SIZE)
+			little_size = DOS_BUF_SIZE;
+
+		real_call_data.eax = 0x3f00;
+		real_call_data.ebx = fd;
+		real_call_data.ecx = little_size;
+		real_call_data.ds = dos_buf_phys >> 4;
+		real_call_data.edx = dos_buf_phys & 15;
+		real_int(0x21, &real_call_data);
+		if (err = dos_check_err(&real_call_data))
+			return err;
+		little_actual = real_call_data.eax & 0xffff;
+		assert(little_actual <= little_size);
+
+		/* XXX don't copy if buf is <1MB */
+		memcpy(buf, dos_buf, little_actual);
+
+		buf += little_actual;
+		size -= little_actual;
+		actual += little_actual;
+
+		if (little_actual < little_size)
+			break;
+	}
+
+	*out_actual = actual;
+	return 0;
+}
+
diff --git a/i386/dos/dos_rename.c b/i386/dos/dos_rename.c
new file mode 100644
index 0000000..e780ba4
--- /dev/null
+++ b/i386/dos/dos_rename.c
@@ -0,0 +1,80 @@
+/* 
+ * Copyright (c) 1995-1994 The University of Utah and
+ * the Computer Systems Laboratory at the University of Utah (CSL).
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify and distribute this software is hereby
+ * granted provided that (1) source code retains these copyright, permission,
+ * and disclaimer notices, and (2) redistributions including binaries
+ * reproduce the notices in supporting documentation, and (3) all advertising
+ * materials mentioning features or use of this software display the following
+ * acknowledgement: ``This product includes software developed by the
+ * Computer Systems Laboratory at the University of Utah.''
+ *
+ * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS
+ * IS" CONDITION.  THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF
+ * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * CSL requests users of this software to return to csl-dist@cs.utah.edu any
+ * improvements that they make and grant CSL redistribution rights.
+ *
+ *      Author: Bryan Ford, University of Utah CSL
+ */
+
+#include <unistd.h>
+#include <errno.h>
+
+#include "dos_io.h"
+#include "vm_param.h"
+
+int dos_rename(const char *oldpath, const char *newpath)
+{
+	/* This function isn't fully atomic like on Unix,
+	   but it's as close as I know how to do under DOS.  */
+
+	struct real_call_data real_call_data;
+	vm_offset_t dos_buf_phys = (vm_offset_t)kvtophys(dos_buf);
+	int err;
+
+	dos_init_rcd(&real_call_data);
+
+	/* Put the oldpath in the first half of dos_buf,
+	   and the newpath in the second half.  */
+	if ((strlen(oldpath)+1 > DOS_BUF_SIZE/2)
+	    || (strlen(newpath)+1 > DOS_BUF_SIZE/2))
+		{ errno = E2BIG; return -1; }
+	strcpy(dos_buf, oldpath);
+	strcpy(dos_buf+DOS_BUF_SIZE/2, newpath);
+
+	/* Try once to rename the file.  */
+	real_call_data.eax = 0x5600;
+	real_call_data.ds = dos_buf_phys >> 4;
+	real_call_data.edx = dos_buf_phys & 15;
+	real_call_data.es = dos_buf_phys >> 4;
+	real_call_data.edi = (dos_buf_phys & 15) + DOS_BUF_SIZE/2;
+	real_int(0x21, &real_call_data);
+
+	/* If that failed, delete newpath and then retry the rename.
+	   We _hope_ the failure was because newpath already existed;
+	   the DOS error codes I'm getting back seem to be bogus.  */
+	if (err = dos_check_err(&real_call_data))
+	{
+		real_call_data.eax = 0x4100;
+		real_call_data.ds = dos_buf_phys >> 4;
+		real_call_data.edx = (dos_buf_phys & 15) + DOS_BUF_SIZE/2;
+		real_int(0x21, &real_call_data);
+		if (err = dos_check_err(&real_call_data))
+			return err;
+
+		real_call_data.eax = 0x5600;
+		real_call_data.ds = dos_buf_phys >> 4;
+		real_call_data.edx = dos_buf_phys & 15;
+		real_call_data.es = dos_buf_phys >> 4;
+		real_call_data.edi = (dos_buf_phys & 15) + DOS_BUF_SIZE/2;
+		real_int(0x21, &real_call_data);
+		err = dos_check_err(&real_call_data);
+	}
+
+	return err;
+}
+
diff --git a/i386/dos/dos_seek.c b/i386/dos/dos_seek.c
new file mode 100644
index 0000000..ba61d87
--- /dev/null
+++ b/i386/dos/dos_seek.c
@@ -0,0 +1,45 @@
+/* 
+ * Copyright (c) 1995-1994 The University of Utah and
+ * the Computer Systems Laboratory at the University of Utah (CSL).
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify and distribute this software is hereby
+ * granted provided that (1) source code retains these copyright, permission,
+ * and disclaimer notices, and (2) redistributions including binaries
+ * reproduce the notices in supporting documentation, and (3) all advertising
+ * materials mentioning features or use of this software display the following
+ * acknowledgement: ``This product includes software developed by the
+ * Computer Systems Laboratory at the University of Utah.''
+ *
+ * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS
+ * IS" CONDITION.  THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF
+ * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * CSL requests users of this software to return to csl-dist@cs.utah.edu any
+ * improvements that they make and grant CSL redistribution rights.
+ *
+ *      Author: Bryan Ford, University of Utah CSL
+ */
+
+#include <unistd.h>
+#include <errno.h>
+
+#include "dos_io.h"
+
+int dos_seek(dos_fd_t fd, vm_offset_t offset, int whence, vm_offset_t *out_newpos)
+{
+	struct real_call_data real_call_data;
+	int err;
+
+	dos_init_rcd(&real_call_data);
+	real_call_data.eax = 0x4200 | whence;
+	real_call_data.ebx = fd;
+	real_call_data.ecx = (unsigned)offset >> 16;
+	real_call_data.edx = (unsigned)offset & 0xffff;
+	real_int(0x21, &real_call_data);
+	if (err = dos_check_err(&real_call_data))
+		return err;
+	*out_newpos = (real_call_data.edx << 16) | (real_call_data.eax & 0xffff);
+	return 0;
+}
+
diff --git a/i386/dos/dos_tcgetattr.c b/i386/dos/dos_tcgetattr.c
new file mode 100644
index 0000000..8f0d493
--- /dev/null
+++ b/i386/dos/dos_tcgetattr.c
@@ -0,0 +1,51 @@
+/* 
+ * Copyright (c) 1995-1994 The University of Utah and
+ * the Computer Systems Laboratory at the University of Utah (CSL).
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify and distribute this software is hereby
+ * granted provided that (1) source code retains these copyright, permission,
+ * and disclaimer notices, and (2) redistributions including binaries
+ * reproduce the notices in supporting documentation, and (3) all advertising
+ * materials mentioning features or use of this software display the following
+ * acknowledgement: ``This product includes software developed by the
+ * Computer Systems Laboratory at the University of Utah.''
+ *
+ * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS
+ * IS" CONDITION.  THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF
+ * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * CSL requests users of this software to return to csl-dist@cs.utah.edu any
+ * improvements that they make and grant CSL redistribution rights.
+ *
+ *      Author: Bryan Ford, University of Utah CSL
+ */
+
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/termios.h>
+
+#include "dos_io.h"
+
+int dos_tcgetattr(dos_fd_t fd, struct termios *t)
+{
+	int err;
+	struct real_call_data real_call_data;
+
+	dos_init_rcd(&real_call_data);
+
+	bzero(t, sizeof(*t));
+
+	/* First make sure this is actually a character device.  */
+	real_call_data.eax = 0x4400;
+	real_call_data.ebx = fd;
+	real_int(0x21, &real_call_data);
+	if (err = dos_check_err(&real_call_data))
+		return err;
+	if (!(real_call_data.edx & (1<<7)))
+		return ENOTTY;
+
+	return 0;
+}
+
diff --git a/i386/dos/dos_unlink.c b/i386/dos/dos_unlink.c
new file mode 100644
index 0000000..cb169bb
--- /dev/null
+++ b/i386/dos/dos_unlink.c
@@ -0,0 +1,48 @@
+/* 
+ * Copyright (c) 1995-1994 The University of Utah and
+ * the Computer Systems Laboratory at the University of Utah (CSL).
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify and distribute this software is hereby
+ * granted provided that (1) source code retains these copyright, permission,
+ * and disclaimer notices, and (2) redistributions including binaries
+ * reproduce the notices in supporting documentation, and (3) all advertising
+ * materials mentioning features or use of this software display the following
+ * acknowledgement: ``This product includes software developed by the
+ * Computer Systems Laboratory at the University of Utah.''
+ *
+ * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS
+ * IS" CONDITION.  THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF
+ * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * CSL requests users of this software to return to csl-dist@cs.utah.edu any
+ * improvements that they make and grant CSL redistribution rights.
+ *
+ *      Author: Bryan Ford, University of Utah CSL
+ */
+
+#include <unistd.h>
+#include <errno.h>
+
+#include "dos_io.h"
+#include "vm_param.h"
+
+int dos_unlink(const char *filename)
+{
+	struct real_call_data real_call_data;
+	vm_offset_t dos_buf_phys = (vm_offset_t)kvtophys(dos_buf);
+
+	dos_init_rcd(&real_call_data);
+
+	if (strlen(filename)+1 > DOS_BUF_SIZE)
+		return E2BIG;
+	strcpy(dos_buf, filename);
+
+	real_call_data.eax = 0x4100;
+	real_call_data.ds = dos_buf_phys >> 4;
+	real_call_data.edx = dos_buf_phys & 15;
+	real_int(0x21, &real_call_data);
+
+	return dos_check_err(&real_call_data);
+}
+
diff --git a/i386/dos/dos_write.c b/i386/dos/dos_write.c
new file mode 100644
index 0000000..5dab8f9
--- /dev/null
+++ b/i386/dos/dos_write.c
@@ -0,0 +1,75 @@
+/* 
+ * Copyright (c) 1995-1994 The University of Utah and
+ * the Computer Systems Laboratory at the University of Utah (CSL).
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify and distribute this software is hereby
+ * granted provided that (1) source code retains these copyright, permission,
+ * and disclaimer notices, and (2) redistributions including binaries
+ * reproduce the notices in supporting documentation, and (3) all advertising
+ * materials mentioning features or use of this software display the following
+ * acknowledgement: ``This product includes software developed by the
+ * Computer Systems Laboratory at the University of Utah.''
+ *
+ * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS
+ * IS" CONDITION.  THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF
+ * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * CSL requests users of this software to return to csl-dist@cs.utah.edu any
+ * improvements that they make and grant CSL redistribution rights.
+ *
+ *      Author: Bryan Ford, University of Utah CSL
+ */
+
+#include <unistd.h>
+#include <errno.h>
+
+#include "dos_io.h"
+#include "vm_param.h"
+
+int dos_write(dos_fd_t fd, const void *buf, vm_size_t size, vm_size_t *out_actual)
+{
+	int err;
+	int actual = 0;
+	struct real_call_data real_call_data;
+	vm_offset_t dos_buf_phys = (vm_offset_t)kvtophys(dos_buf);
+
+	assert(dos_buf); assert(dos_buf_phys);
+	assert(dos_buf_phys < 0x100000);
+
+	dos_init_rcd(&real_call_data);
+
+	while (size > 0)
+	{
+		int little_size = size;
+		int little_actual;
+
+		if (little_size > DOS_BUF_SIZE)
+			little_size = DOS_BUF_SIZE;
+
+		/* XXX don't copy if buf is <1MB */
+		memcpy(dos_buf, buf, little_size);
+
+		real_call_data.eax = 0x4000;
+		real_call_data.ebx = fd;
+		real_call_data.ecx = little_size;
+		real_call_data.ds = dos_buf_phys >> 4;
+		real_call_data.edx = dos_buf_phys & 15;
+		real_int(0x21, &real_call_data);
+		if (err = dos_check_err(&real_call_data))
+			return err;
+		little_actual = real_call_data.eax & 0xffff;
+		assert(little_actual <= little_size);
+
+		buf += little_actual;
+		size -= little_actual;
+		actual += little_actual;
+
+		if (little_actual < little_size)
+			break;
+	}
+
+	*out_actual = actual;
+	return 0;
+}
+
diff --git a/i386/dos/i16/gdt.h b/i386/dos/i16/gdt.h
new file mode 100644
index 0000000..3dad28b
--- /dev/null
+++ b/i386/dos/i16/gdt.h
@@ -0,0 +1,32 @@
+/* 
+ * Copyright (c) 1995-1994 The University of Utah and
+ * the Computer Systems Laboratory at the University of Utah (CSL).
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify and distribute this software is hereby
+ * granted provided that (1) source code retains these copyright, permission,
+ * and disclaimer notices, and (2) redistributions including binaries
+ * reproduce the notices in supporting documentation, and (3) all advertising
+ * materials mentioning features or use of this software display the following
+ * acknowledgement: ``This product includes software developed by the
+ * Computer Systems Laboratory at the University of Utah.''
+ *
+ * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS
+ * IS" CONDITION.  THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF
+ * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * CSL requests users of this software to return to csl-dist@cs.utah.edu any
+ * improvements that they make and grant CSL redistribution rights.
+ *
+ *      Author: Bryan Ford, University of Utah CSL
+ */
+#ifndef _I386_DOS_GDT_
+#define _I386_DOS_GDT_
+
+#define cpu_gdt_init_VCPI_CS(cpu)
+#define cpu_gdt_init_VCPI_2(cpu)
+#define cpu_gdt_init_VCPI_3(cpu)
+
+#include_next "gdt.h"
+
+#endif _I386_DOS_GDT_
diff --git a/i386/dos/i16/gdt_sels.h b/i386/dos/i16/gdt_sels.h
new file mode 100644
index 0000000..25e7d96
--- /dev/null
+++ b/i386/dos/i16/gdt_sels.h
@@ -0,0 +1,36 @@
+/* 
+ * Copyright (c) 1995-1994 The University of Utah and
+ * the Computer Systems Laboratory at the University of Utah (CSL).
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify and distribute this software is hereby
+ * granted provided that (1) source code retains these copyright, permission,
+ * and disclaimer notices, and (2) redistributions including binaries
+ * reproduce the notices in supporting documentation, and (3) all advertising
+ * materials mentioning features or use of this software display the following
+ * acknowledgement: ``This product includes software developed by the
+ * Computer Systems Laboratory at the University of Utah.''
+ *
+ * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS
+ * IS" CONDITION.  THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF
+ * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * CSL requests users of this software to return to csl-dist@cs.utah.edu any
+ * improvements that they make and grant CSL redistribution rights.
+ *
+ *      Author: Bryan Ford, University of Utah CSL
+ */
+
+#include "config.h"
+
+#include_next "gdt_sels.h"
+
+#ifdef ENABLE_VCPI
+
+/* Segment descriptors for use by a VCPI server.  */
+gdt_sel(VCPI_CS)
+gdt_sel(VCPI_2)
+gdt_sel(VCPI_3)
+
+#endif ENABLE_VCPI
+
diff --git a/i386/dos/i16/i16_crt0.S b/i386/dos/i16/i16_crt0.S
new file mode 100644
index 0000000..f21c6a6
--- /dev/null
+++ b/i386/dos/i16/i16_crt0.S
@@ -0,0 +1,274 @@
+/* 
+ * Copyright (c) 1995-1994 The University of Utah and
+ * the Computer Systems Laboratory at the University of Utah (CSL).
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify and distribute this software is hereby
+ * granted provided that (1) source code retains these copyright, permission,
+ * and disclaimer notices, and (2) redistributions including binaries
+ * reproduce the notices in supporting documentation, and (3) all advertising
+ * materials mentioning features or use of this software display the following
+ * acknowledgement: ``This product includes software developed by the
+ * Computer Systems Laboratory at the University of Utah.''
+ *
+ * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS
+ * IS" CONDITION.  THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF
+ * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * CSL requests users of this software to return to csl-dist@cs.utah.edu any
+ * improvements that they make and grant CSL redistribution rights.
+ *
+ *      Author: Bryan Ford, University of Utah CSL
+ */
+
+#include <mach/machine/asm.h>
+
+#include "config.h"
+#include "i16_crt0.h"
+
+	.code16
+	.text
+
+ENTRY(i16_entry)
+	/* DOS starts us up with our stack pointer pointing
+	   to the very top of our BSS segment.
+	   ds and es point to the PSP.  */
+
+#define DELAY jmp 1f; 1: jmp 1f; 1: jmp 1f; 1:
+
+	/* Check to make sure we're running on a 386 or higher -
+	   _without_ using any 32-bit instructions of course.
+	   Tricky, since gas doesn't support 16-bit addressing modes. :-)
+	   We can't produce any 16-bit relocations either,
+	   because ELF doesn't support them.
+	   This code is basically straight out of the Pentium manual,
+	   except gassed of coursed.  */
+	pushfw
+	DELAY
+	popw	%bx
+	movw	$0xfff,%ax
+	andw	%bx,%ax
+	pushw	%ax
+	DELAY
+	popfw
+	DELAY
+	pushfw
+	DELAY
+	popw	%ax
+	and	$0xf000,%ax
+	cmpw	$0xf000,%ax
+
+	je	1f
+	orw	$0xf000,%bx
+	pushw	%bx
+	DELAY
+	popfw
+	DELAY
+	pushfw
+	DELAY
+	popw	%ax
+	andw	$0xf000,%ax
+	jnz	4f
+1:
+	/* Gak!  We're running on an 8086/8088/80286!  */
+	callw	5f
+	.ascii	"This program requires a 386 or better.\r\n\0"
+5:	popw	%si
+	movw	%cs,%ax
+	movw	%ax,%ds
+	cld
+2:	lodsb
+	orb	%al,%al
+	jz	3f
+	movb	$0x02,%ah
+	movb	%al,%dl
+	int	$0x21
+	jmp	2b
+3:	movw	$0x4c02,%ax
+	int	$0x21
+4:
+	/* Now we can use 32-bit instructions all we want.  */
+
+	/* Save the PSP segment address (dx).  */
+	movw	%ds,%dx
+
+	/* Find our real-mode code segment (ax).  */
+	movw	%cs,%ax
+
+#ifdef ENABLE_PAGE_ALIGNED_KERNEL
+	/* Move our code and data so that everything is on a page boundary.
+	   Theoretically we _could_ go past the end of available memory,
+	   since we're not checking, but it's enormously unlikely.  */
+	std
+	movw	%ax,%ds
+	addw	$0xff,%ax
+	andw	$0xff00,%ax
+	movw	%ax,%es
+	movl	$EXT(edata),%ecx
+	subl	$EXT(i16_entry_2),%ecx
+	movl	$EXT(edata)-1,%esi
+	movw	%si,%di
+	rep
+	movsb
+
+	/* Start running at the new address.  */
+	pushl	$EXT(i16_entry_2)
+	movw	%ax,2(%esp)
+	lretw
+
+ENTRY(i16_entry_2)
+	/* We're now page aligned.  */
+#endif ENABLE_PAGE_ALIGNED_KERNEL
+
+	/* Load the data segment registers appropriately.  */
+	movw	%ax,%es
+	movw	%ax,%ss
+
+	/* Start using a real stack.  */
+	movl	$EXT(crt0_stack)+CRT0_STACK_SIZE,%esp
+
+	/* Clear our BSS segment.  */
+	movl	$EXT(edata),%edi
+	movl	$EXT(end),%ecx
+	subw	%di,%cx
+	xorb	%al,%al
+	cld
+	rep
+	stosb
+
+	/* Find the size of the environment array (si) 
+	   and the number of environment variables plus one (bx).
+	   The PSP segment is still in dx.  */
+	movw	%dx,%ds
+	movw	0x2c,%ds
+	xorw	%si,%si
+1:	lodsb
+	orb	%al,%al
+	jnz	1b
+	lodsb
+	orb	%al,%al
+	jnz	1b
+
+	/* Allocate space for the environment array on the stack.
+	   Also make sure the top 16 bits of ESP are cleared,
+	   and that the stack pointer is longword aligned.  */
+	subw	%si,%sp
+	andl	$0x0000fffc,%esp
+
+	/* Copy the environment array to the local stack.
+	   We present it backwards, but big deal - shouldn't matter.  */
+	xorl	%edi,%edi
+	movw	%sp,%di
+	xorl	%esi,%esi
+	pushl	%esi
+	jmp	3f
+2:	pushl	%edi
+	stosb
+1:	lodsb
+	stosb
+	orb	%al,%al
+	jnz	1b
+3:	lodsb
+	orb	%al,%al
+	jnz	2b
+	movl	%esp,%cs:EXT(environ)
+
+	/* Copy the program name to the local stack;
+	   it will be used as argv[0].  */
+	lodsw
+	movw	%si,%bx
+1:	pushw	$0
+	lodsb
+	orb	%al,%al
+	jz	2f
+	lodsb
+	orb	%al,%al
+	jnz	1b
+2:	movw	%bx,%si
+	movw	%sp,%di
+3:	lodsb
+	stosb
+	orb	%al,%al
+	jnz	3b
+	movl	%esp,%ebp
+
+	/* Build argv[1..n] from the command tail in the PSP.
+	   Count the arguments in ebx.  */
+	movw	%dx,%ds
+	xorl	%ecx,%ecx
+	xorl	%ebx,%ebx
+	movb	0x80,%cl	/* get size of command tail */
+	incw	%cx		/* plus the return character */
+	movw	$0x80,%si
+	addw	%cx,%si		/* si = ptr to return character */
+	movw 	%sp,%di
+	decw	%di
+	subw	%cx,%sp		/* allocate space on the stack */
+	andw	$0xfffc,%sp
+	pushl	%ebx
+	std
+1:	xorb	%al,%al		/* store a null terminator for this arg */
+	stosb
+	incl	%ebx
+2:	cmpw	$0x80,%si
+	je	5f
+	lodsb			/* scan backwards for the end of an arg */
+	cmpb	$0x20,%al
+	jbe	2b
+3:	stosb			/* copy the arg */
+	cmpw	$0x80,%si
+	je	4f
+	lodsb
+	cmpb	$0x20,%al
+	ja	3b
+4:	movw	%di,%cx		/* push an arg pointer */
+	incw	%cx
+	pushl	%ecx
+	jmp	1b
+5:
+
+	/* Push the argv[0] pointer.  */
+	pushl	%ebp
+
+	/* Push the argument and envirnonment parameters on the stack.  */
+	movl	%esp,%eax
+	pushl	%cs:EXT(environ)
+	pushl	%eax
+	pushl	%ebx
+
+	/* Release all conventional memory above the top of our BSS.
+	   The PSP segment is still in dx.  */
+	movl	$EXT(end)+15,%ebx
+	shrw	$4,%bx
+	movw	%cs,%ax
+	addw	%ax,%bx
+	subw	%dx,%bx
+	movw	%dx,%es
+	movb	$0x4a,%ah
+	int	$0x21
+
+	/* Load the normal data segment registers.  */
+	movw	%cs,%ax
+	movw	%ax,%ds
+	movw	%ax,%es
+
+	/* GCC wants the direction flag cleared at all times.  */
+	cld
+
+	/* Initialize the bss and run the program.  */
+	call	EXT(i16_main)
+
+	.globl	EXT(crt0_stack)
+	.comm	EXT(crt0_stack),CRT0_STACK_SIZE
+
+	.globl	EXT(environ)
+	.comm	EXT(environ),4
+
+
+	.data
+
+	.section .anno,"aw",@progbits
+	P2ALIGN(4)
+	.globl	__ANNO_START__
+__ANNO_START__:
+
diff --git a/i386/dos/i16/i16_crt0.h b/i386/dos/i16/i16_crt0.h
new file mode 100644
index 0000000..352d1cb
--- /dev/null
+++ b/i386/dos/i16/i16_crt0.h
@@ -0,0 +1,32 @@
+/* 
+ * Copyright (c) 1995-1994 The University of Utah and
+ * the Computer Systems Laboratory at the University of Utah (CSL).
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify and distribute this software is hereby
+ * granted provided that (1) source code retains these copyright, permission,
+ * and disclaimer notices, and (2) redistributions including binaries
+ * reproduce the notices in supporting documentation, and (3) all advertising
+ * materials mentioning features or use of this software display the following
+ * acknowledgement: ``This product includes software developed by the
+ * Computer Systems Laboratory at the University of Utah.''
+ *
+ * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS
+ * IS" CONDITION.  THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF
+ * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * CSL requests users of this software to return to csl-dist@cs.utah.edu any
+ * improvements that they make and grant CSL redistribution rights.
+ *
+ *      Author: Bryan Ford, University of Utah CSL
+ */
+#ifndef _I386_DOS_I16_CRT0_H_
+#define _I386_DOS_I16_CRT0_H_
+
+#define CRT0_STACK_SIZE 4096
+
+#ifndef ASSEMBLER
+extern char crt0_stack[CRT0_STACK_SIZE];
+#endif
+
+#endif _I386_DOS_I16_CRT0_H_
diff --git a/i386/dos/i16/i16_dos.h b/i386/dos/i16/i16_dos.h
new file mode 100644
index 0000000..27b0ca4
--- /dev/null
+++ b/i386/dos/i16/i16_dos.h
@@ -0,0 +1,146 @@
+/* 
+ * Copyright (c) 1995-1994 The University of Utah and
+ * the Computer Systems Laboratory at the University of Utah (CSL).
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify and distribute this software is hereby
+ * granted provided that (1) source code retains these copyright, permission,
+ * and disclaimer notices, and (2) redistributions including binaries
+ * reproduce the notices in supporting documentation, and (3) all advertising
+ * materials mentioning features or use of this software display the following
+ * acknowledgement: ``This product includes software developed by the
+ * Computer Systems Laboratory at the University of Utah.''
+ *
+ * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS
+ * IS" CONDITION.  THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF
+ * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * CSL requests users of this software to return to csl-dist@cs.utah.edu any
+ * improvements that they make and grant CSL redistribution rights.
+ *
+ *      Author: Bryan Ford, University of Utah CSL
+ */
+#ifndef _I16DOS_H_
+#define _I16DOS_H_
+
+#include <mach/inline.h>
+#include <mach/machine/far_ptr.h>
+
+
+/* Returns 16-bit DOS version number:
+   major version number in high byte, minor in low byte.  */
+MACH_INLINE unsigned short i16_dos_version(void)
+{
+	unsigned short dos_version_swapped;
+	asm volatile("int $0x21" : "=a" (dos_version_swapped) : "a" (0x3000));
+	return (dos_version_swapped >> 8) | (dos_version_swapped << 8);
+}
+
+MACH_INLINE void i16_dos_putchar(int c)
+{
+	asm volatile("int $0x21" : : "a" (0x0200), "d" (c));
+}
+
+MACH_INLINE void i16_dos_exit(int rc)
+{
+	asm volatile("int $0x21" : : "a" (0x4c00 | (rc & 0xff)));
+}
+
+MACH_INLINE void i16_dos_get_int_vec(int vecnum, struct far_pointer_16 *out_vec)
+{
+	asm volatile("
+		pushw	%%es
+		int	$0x21
+		movw	%%es,%0
+		popw	%%es
+	" : "=r" (out_vec->seg), "=b" (out_vec->ofs)
+	  : "a" (0x3500 | vecnum));
+}
+
+MACH_INLINE void i16_dos_set_int_vec(int vecnum, struct far_pointer_16 *new_vec)
+{
+	asm volatile("
+		pushw	%%ds
+		movw	%1,%%ds
+		int	$0x21
+		popw	%%ds
+	" :
+	  : "a" (0x2500 | vecnum),
+	    "r" (new_vec->seg), "d" (new_vec->ofs));
+}
+
+/* Open a DOS file and return the new file handle.
+   Returns -1 if an error occurs.  */
+MACH_INLINE int i16_dos_open(const char *filename, int access)
+{
+	int fh;
+	asm volatile("
+		int	$0x21
+		jnc	1f
+		movl	$-1,%%eax
+	1:
+	" : "=a" (fh) : "a" (0x3d00 | access), "d" (filename));
+	return fh;
+}
+
+MACH_INLINE void i16_dos_close(int fh)
+{
+	asm volatile("int $0x21" : : "a" (0x3e00), "b" (fh));
+}
+
+MACH_INLINE int i16_dos_get_device_info(int fh)
+{
+	int info_word;
+	asm volatile("
+		int	$0x21
+		jnc	1f
+		movl	$-1,%%edx
+	1:
+	" : "=d" (info_word) : "a" (0x4400), "b" (fh), "d" (0));
+	return info_word;
+}
+
+MACH_INLINE int i16_dos_get_output_status(int fh)
+{
+	int status;
+	asm volatile("
+		int	$0x21
+		movzbl	%%al,%%eax
+		jnc	1f
+		movl	$-1,%%eax
+	1:
+	" : "=a" (status) : "a" (0x4407), "b" (fh));
+	return status;
+}
+
+MACH_INLINE int i16_dos_alloc(unsigned short *inout_paras)
+{
+	int seg;
+	asm volatile("
+		int	$0x21
+		jnc	1f
+		movl	$-1,%%eax
+	1:
+	" : "=a" (seg), "=b" (*inout_paras)
+	  : "a" (0x4800), "b" (*inout_paras));
+	return seg;
+}
+
+MACH_INLINE int i16_dos_free(unsigned short seg)
+{
+	asm volatile("
+		pushw	%%es
+		movw	%1,%%es
+		int	$0x21
+		popw	%%es
+	" : : "a" (0x4900), "r" (seg) : "eax");
+}
+
+MACH_INLINE unsigned short i16_dos_get_psp_seg(void)
+{
+	unsigned short psp_seg;
+	asm volatile("int $0x21" : "=b" (psp_seg) : "a" (0x6200));
+	return psp_seg;
+}
+
+#endif _I16DOS_H_
diff --git a/i386/dos/i16/i16_dos_mem.c b/i386/dos/i16/i16_dos_mem.c
new file mode 100644
index 0000000..e78398d
--- /dev/null
+++ b/i386/dos/i16/i16_dos_mem.c
@@ -0,0 +1,182 @@
+/* 
+ * Copyright (c) 1995-1994 The University of Utah and
+ * the Computer Systems Laboratory at the University of Utah (CSL).
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify and distribute this software is hereby
+ * granted provided that (1) source code retains these copyright, permission,
+ * and disclaimer notices, and (2) redistributions including binaries
+ * reproduce the notices in supporting documentation, and (3) all advertising
+ * materials mentioning features or use of this software display the following
+ * acknowledgement: ``This product includes software developed by the
+ * Computer Systems Laboratory at the University of Utah.''
+ *
+ * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS
+ * IS" CONDITION.  THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF
+ * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * CSL requests users of this software to return to csl-dist@cs.utah.edu any
+ * improvements that they make and grant CSL redistribution rights.
+ *
+ *      Author: Bryan Ford, University of Utah CSL
+ */
+
+#include <mach/machine/code16.h>
+#include <mach/machine/vm_types.h>
+
+#include "i16_dos.h"
+#include "config.h"
+
+
+
+/* These aren't static because vcpi and dpmi code need to grab DOS memory
+   before we've switched to protected mode and memory has been collected.  */
+vm_offset_t dos_mem_phys_free_mem;
+vm_size_t dos_mem_phys_free_size;
+
+
+CODE32
+
+void dos_mem_collect(void)
+{
+	if (dos_mem_phys_free_mem)
+	{
+		phys_mem_add(dos_mem_phys_free_mem, dos_mem_phys_free_size);
+		dos_mem_phys_free_mem = 0;
+	}
+}
+
+CODE16
+
+void i16_dos_mem_check()
+{
+	unsigned short paras = 0xf000;
+	int dos_mem_seg;
+
+	/* Allocate as big a chunk of memory as we can find.  */
+	do
+	{
+		if (paras == 0)
+			return;
+		dos_mem_seg = i16_dos_alloc(&paras);
+	}
+	while (dos_mem_seg < 0);
+
+	dos_mem_phys_free_mem = dos_mem_seg << 4;
+	dos_mem_phys_free_size = paras << 4;
+
+#ifdef ENABLE_CODE_CHECK
+	i16_code_copy();
+#endif
+}
+
+
+#ifdef ENABLE_CODE_CHECK
+
+/* Big humongo kludge to help in finding random code-trashing bugs.
+   We copy the entire text segment upon initialization,
+   and then check it later as necessary.  */
+
+#include <mach/machine/proc_reg.h>
+#include "vm_param.h"
+
+extern char etext[], i16_entry_2[];
+
+static int code_copy_seg;
+
+static int i16_code_copy()
+{
+	int text_size = (int)etext & ~0xf;
+	int i;
+
+	if (dos_mem_phys_free_size < text_size)
+		return;
+
+	code_copy_seg = dos_mem_phys_free_mem >> 4;
+	dos_mem_phys_free_mem += text_size;
+	dos_mem_phys_free_size -= text_size;
+
+	set_fs(code_copy_seg);
+	for (i = 0; i < text_size; i += 4)
+		asm volatile("
+			movl (%%ebx),%%eax
+			movl %%eax,%%fs:(%%ebx)
+		" : : "b" (i) : "eax");
+}
+
+void i16_code_check(int dummy)
+{
+	int text_size = (int)etext & ~0xf;
+	int i, old, new;
+	int found = 0;
+
+	if (!code_copy_seg)
+		return;
+
+	set_fs(code_copy_seg);
+	for (i = (int)i16_entry_2; i < text_size; i += 4)
+	{
+		asm volatile("
+			movl (%%ebx),%%eax
+			movl %%fs:(%%ebx),%%ecx
+		" : "=a" (new), "=c" (old) : "b" (i));
+		if (old != new)
+		{
+			found = 1;
+			i16_writehexw(i);
+			i16_putchar(' ');
+			i16_writehexl(old);
+			i16_putchar(' ');
+			i16_writehexl(new);
+			i16_putchar('\r');
+			i16_putchar('\n');
+		}
+	}
+	if (found)
+	{
+		code_copy_seg = 0;
+		i16_writehexl((&dummy)[-1]);
+		i16_die(" DOS extender code trashed!");
+	}
+}
+
+CODE32
+
+void code_check(int dummy)
+{
+	int text_size = (int)etext & ~0xf;
+	unsigned char *new = 0, *old = (void*)phystokv(code_copy_seg*16);
+	int found = 0;
+	int i;
+
+	if (!code_copy_seg)
+		return;
+
+	for (i = (int)i16_entry_2; (i < text_size) && (found < 10); i++)
+	{
+		/* In several places we have to self-modify an int instruction,
+		   or the segment value in an absolute long jmp instruction,
+		   so ignore any changes preceded by those opcodes.  */
+		if ((new[i] != old[i])
+		    && (old[i-1] != 0xcd)
+		    && (old[i-6] != 0xea))
+		{
+			if (!found)
+			{
+				found = 1;
+				about_to_die(1);
+			}
+			printf("%08x addr %04x was %02x now %02x\n",
+				(&dummy)[-1], i, old[i], new[i]);
+		}
+	}
+	if (found)
+	{
+		code_copy_seg = 0;
+		die("%08x DOS extender code trashed!", (&dummy)[-1]);
+	}
+}
+
+CODE16
+
+#endif ENABLE_CODE_CHECK
diff --git a/i386/dos/i16/i16_exit.c b/i386/dos/i16/i16_exit.c
new file mode 100644
index 0000000..04b943c
--- /dev/null
+++ b/i386/dos/i16/i16_exit.c
@@ -0,0 +1,50 @@
+/* 
+ * Copyright (c) 1995-1994 The University of Utah and
+ * the Computer Systems Laboratory at the University of Utah (CSL).
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify and distribute this software is hereby
+ * granted provided that (1) source code retains these copyright, permission,
+ * and disclaimer notices, and (2) redistributions including binaries
+ * reproduce the notices in supporting documentation, and (3) all advertising
+ * materials mentioning features or use of this software display the following
+ * acknowledgement: ``This product includes software developed by the
+ * Computer Systems Laboratory at the University of Utah.''
+ *
+ * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS
+ * IS" CONDITION.  THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF
+ * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * CSL requests users of this software to return to csl-dist@cs.utah.edu any
+ * improvements that they make and grant CSL redistribution rights.
+ *
+ *      Author: Bryan Ford, University of Utah CSL
+ */
+
+#include <mach/machine/code16.h>
+
+#include "config.h"
+#include "i16_dos.h"
+
+
+CODE16
+
+void i16_exit(int rc)
+{
+	/* Clean up properly.  */
+	i16_ext_mem_shutdown();
+	i16_xms_shutdown();
+#ifdef ENABLE_VCPI
+	i16_vcpi_shutdown();
+#endif
+#ifdef ENABLE_DPMI
+	i16_dpmi_shutdown();
+#endif
+#ifdef ENABLE_CODE_CHECK
+	i16_code_check();
+#endif
+
+	/* Call the DOS exit function.  */
+	i16_dos_exit(rc);
+}
+
diff --git a/i386/dos/i16/i16_main.c b/i386/dos/i16/i16_main.c
new file mode 100644
index 0000000..5558d09
--- /dev/null
+++ b/i386/dos/i16/i16_main.c
@@ -0,0 +1,60 @@
+/* 
+ * Copyright (c) 1995-1994 The University of Utah and
+ * the Computer Systems Laboratory at the University of Utah (CSL).
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify and distribute this software is hereby
+ * granted provided that (1) source code retains these copyright, permission,
+ * and disclaimer notices, and (2) redistributions including binaries
+ * reproduce the notices in supporting documentation, and (3) all advertising
+ * materials mentioning features or use of this software display the following
+ * acknowledgement: ``This product includes software developed by the
+ * Computer Systems Laboratory at the University of Utah.''
+ *
+ * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS
+ * IS" CONDITION.  THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF
+ * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * CSL requests users of this software to return to csl-dist@cs.utah.edu any
+ * improvements that they make and grant CSL redistribution rights.
+ *
+ *      Author: Bryan Ford, University of Utah CSL
+ */
+
+#include <mach/machine/code16.h>
+
+#include "config.h"
+#include "i16_dos.h"
+
+
+CODE16
+
+int argc;
+char **argv;
+
+void i16_main(int _argc, char **_argv)
+{
+	argc = _argc;
+	argv = _argv;
+
+	i16_init();
+
+	/* Make sure we're running on a good enough DOS version.  */
+	if (i16_dos_version() < 0x300)
+		i16_die("DOS 3.00 or higher required.");
+
+	/* See if we're running in a DPMI or VCPI environment.
+	   If either of these are successful, they don't return.  */
+	i16_dos_mem_check();
+#ifdef ENABLE_DPMI
+	i16_dpmi_check();
+#endif
+	i16_xms_check();
+	i16_ext_mem_check();
+#ifdef ENABLE_VCPI
+	i16_vcpi_check();
+#endif
+
+	i16_raw_start();
+}
+
diff --git a/i386/dos/i16/i16_putchar.c b/i386/dos/i16/i16_putchar.c
new file mode 100644
index 0000000..911cbe4
--- /dev/null
+++ b/i386/dos/i16/i16_putchar.c
@@ -0,0 +1,36 @@
+/* 
+ * Copyright (c) 1995-1994 The University of Utah and
+ * the Computer Systems Laboratory at the University of Utah (CSL).
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify and distribute this software is hereby
+ * granted provided that (1) source code retains these copyright, permission,
+ * and disclaimer notices, and (2) redistributions including binaries
+ * reproduce the notices in supporting documentation, and (3) all advertising
+ * materials mentioning features or use of this software display the following
+ * acknowledgement: ``This product includes software developed by the
+ * Computer Systems Laboratory at the University of Utah.''
+ *
+ * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS
+ * IS" CONDITION.  THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF
+ * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * CSL requests users of this software to return to csl-dist@cs.utah.edu any
+ * improvements that they make and grant CSL redistribution rights.
+ *
+ *      Author: Bryan Ford, University of Utah CSL
+ */
+
+#include <mach/machine/code16.h>
+
+#include "i16_dos.h"
+
+CODE16
+
+void i16_putchar(int ch)
+{
+	if (ch == '\n')
+		i16_dos_putchar('\r');
+	i16_dos_putchar(ch);
+}
+
diff --git a/i386/dos/i16/i16_vcpi.c b/i386/dos/i16/i16_vcpi.c
new file mode 100644
index 0000000..e021d6b
--- /dev/null
+++ b/i386/dos/i16/i16_vcpi.c
@@ -0,0 +1,564 @@
+/* 
+ * Copyright (c) 1995-1994 The University of Utah and
+ * the Computer Systems Laboratory at the University of Utah (CSL).
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify and distribute this software is hereby
+ * granted provided that (1) source code retains these copyright, permission,
+ * and disclaimer notices, and (2) redistributions including binaries
+ * reproduce the notices in supporting documentation, and (3) all advertising
+ * materials mentioning features or use of this software display the following
+ * acknowledgement: ``This product includes software developed by the
+ * Computer Systems Laboratory at the University of Utah.''
+ *
+ * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS
+ * IS" CONDITION.  THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF
+ * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * CSL requests users of this software to return to csl-dist@cs.utah.edu any
+ * improvements that they make and grant CSL redistribution rights.
+ *
+ *      Author: Bryan Ford, University of Utah CSL
+ */
+
+#include <mach/boolean.h>
+#include <mach/vm_param.h>
+#include <mach/machine/code16.h>
+#include <mach/machine/vm_types.h>
+#include <mach/machine/paging.h>
+#include <mach/machine/eflags.h>
+#include <mach/machine/proc_reg.h>
+#include <mach/machine/far_ptr.h>
+#include <mach/machine/vcpi.h>
+#include <mach/machine/asm.h>
+
+#include "config.h"
+#include "i16.h"
+#include "i16_dos.h"
+#include "cpu.h"
+#include "real.h"
+#include "debug.h"
+#include "vm_param.h"
+
+#ifdef ENABLE_VCPI
+
+static boolean_t ems_page_allocated;
+static unsigned short ems_handle;
+
+static vm_offset_t vcpi_pdir, vcpi_ptable0;
+
+struct far_pointer_32 vcpi_pmode_entry = {0, VCPI_CS};
+struct vcpi_switch_data vcpi_switch_data;
+
+static struct pseudo_descriptor gdt_pdesc, idt_pdesc;
+
+static boolean_t pic_reprogrammed;
+
+/* Save area for the DOS interrupt vectors
+   that used to be in the place we relocated the master PIC to.  */
+static struct far_pointer_16 master_save_vecs[8];
+
+
+#ifdef ENABLE_PAGING
+#define VCPI_PAGING_INIT(pdir_pa, first_unmapped_pa) vcpi_paging_init(pdir_pa, first_unmapped_pa)
+#else
+#define VCPI_PAGING_INIT(pdir_pa, first_unmapped_pa) ((void)0)
+#endif
+
+#ifdef ENABLE_KERNEL_LDT
+#define KERNEL_LDT_INIT() (vcpi_switch_data.ldt_sel = KERNEL_LDT)
+#else
+#define KERNEL_LDT_INIT() ((void)0)
+#endif
+
+
+CODE16
+
+static void i16_vcpi_switch_to_pmode()
+{
+	extern vm_offset_t boot_image_pa;
+
+	i16_cli();
+
+	i16_assert(i16_get_ds() == i16_get_cs());
+	i16_assert(i16_get_es() == i16_get_cs());
+	i16_assert(i16_get_ss() == i16_get_cs());
+
+	/* Make sure the TSS isn't marked busy.  */
+	cpu[0].tables.gdt[KERNEL_TSS_IDX].access &= ~ACC_TSS_BUSY;
+
+	/* Ask the VCPI server to switch to protected mode.  */
+	asm volatile("
+		movl	%%esp,%%edx
+		int	$0x67
+	"SEXT(pmode_return)":
+		movl	%%edx,%%esp
+		movw	%2,%%dx
+		movw	%%dx,%%ss
+		movw	%%dx,%%ds
+		movw	%%dx,%%es
+		xorw	%%dx,%%dx
+		movw	%%dx,%%fs
+		movw	%%dx,%%gs
+	" :
+	  : "a" ((unsigned short)0xde0c),
+	    "S" (boot_image_pa + (vm_offset_t)&vcpi_switch_data),
+	    "i" (KERNEL_DS)
+	  : "eax", "edx", "esi");
+
+	/* Make sure the direction flag is still clear.  */
+	i16_cld();
+}
+
+static void i16_vcpi_switch_to_real_mode()
+{
+	i16_cli();
+
+	/* As requested by VCPI spec... */
+	i16_clts();
+
+	/* Perform the switch.  */
+	asm volatile("
+		movl	%%esp,%%edx
+		pushl	%1
+		pushl	%1
+		pushl	%1
+		pushl	%1
+		pushl	%1
+		pushl	%%edx
+		pushl	$0
+		pushl	%1
+		pushl	$1f
+		movw	%2,%%ds
+		lcall	%%ss:"SEXT(vcpi_pmode_entry)"
+	1:
+	" :
+	  : "a" ((unsigned short)0xde0c),
+	    "r" ((unsigned)real_cs),
+	    "r" ((unsigned short)LINEAR_DS)
+	  : "eax", "edx");
+
+	i16_assert(!(i16_get_eflags() & EFL_IF));
+	i16_assert(i16_get_ds() == i16_get_cs());
+	i16_assert(i16_get_es() == i16_get_cs());
+	i16_assert(i16_get_ss() == i16_get_cs());
+
+	/* Make sure the direction flag is still clear.  */
+	i16_cld();
+}
+
+CODE32
+
+static void vcpi_real_int(int intnum, struct real_call_data *rcd)
+{
+	do_16bit(
+		unsigned int eflags;
+
+		i16_vcpi_switch_to_real_mode();
+		i16_real_int(intnum, rcd);
+		i16_vcpi_switch_to_pmode();
+	);
+}
+
+static void vcpi_exit(int rc)
+{
+	do_16bit(
+		i16_vcpi_switch_to_real_mode();
+		i16_exit(rc);
+		while (1);
+	);
+}
+
+CODE16
+
+static inline void
+i16_vcpi_set_int_vecs(unsigned short master, unsigned short slave)
+{
+	unsigned short rc;
+
+	i16_assert(!(get_eflags() & EFL_IF));
+	asm volatile("int $0x67"
+		: "=a" (rc)
+		: "a" ((unsigned short)0xde0b),
+		  "b" ((unsigned short)master),
+		  "c" ((unsigned short)slave));
+	i16_assert((rc & 0xff00) == 0);
+	i16_assert(!(get_eflags() & EFL_IF));
+}
+
+/* Find a (hopefully) empty set of interrupt vectors
+   to use for the master hardware interrupts.
+   We assume that eight interrupt vectors in a row
+   that all have the same value are unused.
+   If VCPI servers weren't so brain-damaged
+   and took care of this during interrupt reflection
+   (like we do when running in raw mode),
+   this kludgery wouldn't be needed...  */
+static int i16_find_free_vec_range()
+{
+	/* i will track the first vector in a range;
+	   j will track the last.  */
+	int i, j;
+	struct far_pointer_16 iv, jv;
+
+	j = 0xff;
+	i16_dos_get_int_vec(j, &jv);
+
+	for (i = j-1; ; i--)
+	{
+		if (i == 0x50)
+		{
+			/* No completely free sets found.
+			   Stop here and just use 0x50-0x57.  */
+			break;
+		}
+
+		i16_dos_get_int_vec(i, &iv);
+		if ((iv.ofs != jv.ofs) || (iv.seg != jv.seg))
+		{
+			/* Vector contents changed.  */
+			j = i;
+			jv = iv;
+			continue;
+		}
+
+		if ((j-i+1 >= 8) && ((i & 7) == 0))
+		{
+			/* Found a free range.  */
+			break;
+		}
+	}
+
+	return i;
+}
+
+void i16_vcpi_check()
+{
+	extern vm_offset_t dos_mem_phys_free_mem;
+	extern vm_offset_t dos_mem_phys_free_size;
+	extern void pmode_return();
+	extern vm_offset_t boot_image_pa;
+	extern void (*i16_switch_to_real_mode)();
+	extern void (*i16_switch_to_pmode)();
+
+	unsigned short rc;
+	unsigned short first_free_pte;
+	unsigned short vcpi_ver;
+
+	i16_assert(boot_image_pa == kvtophys(0));
+
+	/* Check for presence of EMM driver.  */
+	{
+		int dev_info, out_status;
+		int fh;
+
+		fh = i16_dos_open("EMMXXXX0", 0);
+		if (fh < 0)
+			return;
+		dev_info = i16_dos_get_device_info(fh);
+		out_status = i16_dos_get_output_status(fh);
+		i16_dos_close(fh);
+		if ((dev_info < 0) || !(dev_info & 0x80)
+		    || (out_status != 0xff))
+			return;
+	}
+
+	/* Allocate an EMS page to force the EMM to be turned on.
+	   If it fails, keep going anyway -
+	   it may simply mean all the EMS pages are allocated.  */
+	asm volatile("int $0x67"
+			: "=a" (rc),
+			  "=d" (ems_handle)
+			: "a" ((unsigned short)0x4300),
+			  "b" ((unsigned short)1));
+	if (!(rc & 0xff00))
+		ems_page_allocated = TRUE;
+
+	/* Check for VCPI.  */
+	asm volatile("int $0x67" : "=a" (rc), "=b" (vcpi_ver) : "a" ((unsigned short)0xde00));
+	if (rc & 0xff00)
+		return;
+	i16_assert(vcpi_ver >= 0x0100);
+
+	/* OK, it's there - we're now committed to using VCPI.  */
+	i16_switch_to_real_mode = i16_vcpi_switch_to_real_mode;
+	i16_switch_to_pmode = i16_vcpi_switch_to_pmode;
+	real_int = vcpi_real_int;
+	real_exit = vcpi_exit;
+
+	do_debug(i16_puts("VCPI detected"));
+
+	/* Allocate a page directory and page table from low DOS memory.  */
+	{
+		vm_offset_t new_dos_mem;
+
+		new_dos_mem = ((dos_mem_phys_free_mem + PAGE_MASK) & ~PAGE_MASK)
+				+ PAGE_SIZE*2;
+		if ((!dos_mem_phys_free_mem)
+		    || (new_dos_mem - dos_mem_phys_free_mem
+		        > dos_mem_phys_free_size))
+			i16_die("not enough low DOS memory available");
+		dos_mem_phys_free_size -= new_dos_mem - dos_mem_phys_free_mem;
+		dos_mem_phys_free_mem = new_dos_mem;
+		vcpi_pdir = new_dos_mem - PAGE_SIZE*2;
+		vcpi_ptable0 = vcpi_pdir + PAGE_SIZE;
+	}
+
+	/* Initialize them.  */
+	{
+		int i;
+		pt_entry_t pde0 = vcpi_ptable0
+			| INTEL_PTE_VALID | INTEL_PTE_WRITE | INTEL_PTE_USER;
+
+		set_fs(vcpi_pdir >> 4);
+		asm volatile("movl %0,%%fs:(0)" : : "r" (pde0));
+		for (i = 1; i < NPDES + NPTES; i++)
+			asm volatile("movl $0,%%fs:(,%0,4)" : : "r" (i));
+	}
+
+	/* Initialize the protected-mode interface.  */
+	asm volatile("
+		pushw	%%es
+		movw	%4,%%es
+		int	$0x67
+		popw	%%es
+	"
+		: "=a" (rc),
+		  "=b" (vcpi_pmode_entry.ofs),
+		  "=D" (first_free_pte)
+		: "a" ((unsigned short)0xde01),
+		  "r" ((unsigned short)(vcpi_ptable0 >> 4)),
+		  "D" (0),
+		  "S" (&cpu[0].tables.gdt[VCPI_CS_IDX]));
+	i16_assert((rc & 0xff00) == 0);
+	i16_assert(get_ds() == get_cs());
+	i16_assert(get_es() == get_cs());
+
+#ifdef DEBUG
+	/* Sanity check: make sure the server did what it was supposed to do.  */
+
+	i16_assert((cpu[0].tables.gdt[VCPI_CS_IDX].access & ACC_P|ACC_CODE) == ACC_P|ACC_CODE);
+	if (cpu[0].tables.gdt[VCPI_CS_IDX].granularity & SZ_G)
+		i16_assert(vcpi_pmode_entry.ofs <
+			   (((vm_offset_t)cpu[0].tables.gdt[VCPI_CS_IDX].limit_high << 28)
+			    | ((vm_offset_t)cpu[0].tables.gdt[VCPI_CS_IDX].limit_low << 12)
+			    | (vm_offset_t)0xfff));
+	else
+		i16_assert(vcpi_pmode_entry.ofs <
+			   (((vm_offset_t)cpu[0].tables.gdt[VCPI_CS_IDX].limit_high << 16)
+			    | (vm_offset_t)cpu[0].tables.gdt[VCPI_CS_IDX].limit_low));
+
+	i16_assert(first_free_pte/sizeof(pt_entry_t) >= 1*1024*1024/PAGE_SIZE);
+	i16_assert(first_free_pte/sizeof(pt_entry_t) <= 4*1024*1024/PAGE_SIZE);
+
+	{
+		int i;
+
+		for (i = 0; i < 1*1024*1024/PAGE_SIZE; i++)
+		{
+			pt_entry_t entry;
+
+			set_ds(vcpi_ptable0 >> 4);
+			entry = ((pt_entry_t*)0)[i];
+			set_ds(get_cs());
+			i16_assert(entry & INTEL_PTE_VALID);
+			if (i < 0xf0000/PAGE_SIZE)
+				i16_assert(entry & INTEL_PTE_WRITE);
+			i16_assert(entry & INTEL_PTE_USER);
+			i16_assert(!(entry & INTEL_PTE_AVAIL));
+		}
+	}
+#endif /* DEBUG */
+
+	/* Find the VCPI server's hardware interrupt vector mappings.  */
+	asm volatile("int $0x67"
+		: "=a" (rc),
+		  "=b" (irq_master_base),
+		  "=c" (irq_slave_base)
+		: "a" ((unsigned short)0xde0a));
+	i16_assert((rc & 0xff00) == 0);
+	irq_master_base &= 0xffff;
+	irq_slave_base &= 0xffff;
+	i16_assert((irq_master_base & 7) == 0);
+	i16_assert((irq_master_base == 0x08) || (irq_master_base >= 0x20));
+	i16_assert((irq_slave_base & 7) == 0);
+	i16_assert(irq_slave_base >= 0x20);
+
+	/* If they're the usual DOS values, change them.  */
+	if (irq_master_base == 0x08)
+	{
+		pic_reprogrammed = TRUE;
+
+		i16_cli();
+
+		irq_master_base = i16_find_free_vec_range();
+
+		/* Save the old vectors in that range
+		   and set them to a copy of vectors 8-15.  */
+		{
+			int i;
+
+			for (i = 0; i < 8; i++)
+			{
+				struct far_pointer_16 hw_vec;
+
+				i16_dos_get_int_vec(irq_master_base+i,
+						    &master_save_vecs[i]);
+				i16_dos_get_int_vec(0x08+i, &hw_vec);
+				i16_dos_set_int_vec(irq_master_base+i, &hw_vec);
+			}
+		}
+
+		/* Reprogram the PIC.  */
+		i16_pic_set_master(irq_master_base);
+
+		/* Inform the VCPI server.  */
+		i16_vcpi_set_int_vecs(irq_master_base, irq_slave_base);
+	}
+
+	/* Initialize the switch-to-pmode data structure.  */
+	vcpi_switch_data.phys_pdir = vcpi_pdir;
+	vcpi_switch_data.lin_gdt = boot_image_pa+(vm_offset_t)&gdt_pdesc.limit;
+	vcpi_switch_data.lin_idt = boot_image_pa+(vm_offset_t)&idt_pdesc.limit;
+	vcpi_switch_data.tss_sel = KERNEL_TSS;
+	vcpi_switch_data.entry_eip = (unsigned short)(vm_offset_t)&pmode_return;
+	vcpi_switch_data.entry_cs = KERNEL_16_CS;
+
+	/* Initialize the GDT and IDT pseudo-descriptors.  */
+	gdt_pdesc.limit = sizeof(cpu[0].tables.gdt)-1;
+	gdt_pdesc.linear_base = boot_image_pa + (vm_offset_t)&cpu[0].tables.gdt;
+	idt_pdesc.limit = sizeof(cpu[0].tables.idt)-1;
+	idt_pdesc.linear_base = boot_image_pa + (vm_offset_t)&cpu[0].tables.idt;
+
+	/* Set the GDT to temporary settings
+	   just for getting into pmode the first time.  */
+	i16_gdt_init_temp();
+
+	/* VCPI insists on loading a TSS immediately on entering pmode,
+	   so initialize the KERNEL_TSS descriptor in the GDT.  */
+	i16_fill_gdt_descriptor(&cpu[0], KERNEL_TSS,
+				boot_image_pa + (vm_offset_t)&cpu[0].tables.tss,
+				sizeof(cpu[0].tables.tss)-1,
+				ACC_PL_K|ACC_TSS, 0);
+	cpu[0].tables.tss.io_bit_map_offset = sizeof(cpu[0].tables.tss);
+
+#if 0
+	/* Dump the various VCPI data structures, for debugging.  */
+	{
+		int i;
+
+		i16_puts("Switch data");
+		i16_writehexl(switch_data.phys_pdir); i16_putchar(' ');
+		i16_writehexl(switch_data.lin_gdt); i16_putchar(' ');
+		i16_writehexl(switch_data.lin_idt); i16_putchar(' ');
+		i16_writehexw(switch_data.ldt_sel); i16_putchar(' ');
+		i16_writehexw(switch_data.tss_sel); i16_putchar(' ');
+		i16_writehexl(switch_data.entry_eip); i16_putchar(' ');
+		i16_writehexw(switch_data.entry_cs); i16_puts("");
+
+		i16_puts("GDT pdesc");
+		i16_writehexw(gdt_pdesc.limit); i16_putchar(' ');
+		i16_writehexl(gdt_pdesc.linear_base); i16_puts("");
+
+		i16_puts("IDT pdesc");
+		i16_writehexw(idt_pdesc.limit); i16_putchar(' ');
+		i16_writehexl(idt_pdesc.linear_base); i16_puts("");
+
+		i16_puts("GDT");
+		for (i = 0; i < GDTSZ; i++)
+		{
+			i16_writehexw(i*8); i16_putchar(' ');
+			i16_writehexll(*((long long*)&cpu[0].tables.gdt[i]));
+			i16_puts("");
+		}
+	}
+#endif
+
+	/* Switch into pmode briefly to initialize the CPU tables and such.  */
+	i16_vcpi_switch_to_pmode();
+	i16_do_32bit(
+
+		/* Note that right now we can only access the first 1MB of memory,
+		   because paging is enabled and that's the only memory region that's been mapped.
+		   The rest of physical memory won't be mapped until VCPI_PAGING_INIT,
+		   but VCPI_PAGING_INIT requires allocating memory for page tables,
+		   and we can't call phys_mem_collect() to provide memory to the allocator
+		   until all physical memory can be read and written.
+		   To get out of this catch-22,
+		   we call dos_mem_collect() beforehand here
+		   to make low DOS memory available for allocation by VCPI_PAGING_INIT.
+		   The call to phys_mem_collect() later will cause dos_mem_collect
+		   to be called a second time, but it'll just do nothing then.  */
+		dos_mem_collect();
+
+		/* Initialize the basic CPU tables.  */
+		cpu_init(&cpu[0]);
+
+		/* Initialize the paging system.  */
+		VCPI_PAGING_INIT(vcpi_pdir, (vm_offset_t)first_free_pte / 4 * PAGE_SIZE);
+
+		/* Now that we can access all physical memory,
+		   collect the remaining memory regions we discovered while in 16-bit mode
+		   and add them to our free memory list.  */
+		phys_mem_collect();
+
+		/* Initialize the hardware interrupt vectors in the IDT.  */
+		idt_irq_init();
+
+		/* Now that we have an initialized LDT descriptor, start using it.  */
+		KERNEL_LDT_INIT();
+
+		/* Switch to real mode and back again once more,
+		   to make sure everything's loaded properly.  */
+		do_16bit(
+			i16_vcpi_switch_to_real_mode();
+			i16_vcpi_switch_to_pmode();
+		);
+
+		vcpi_start();
+	);
+}
+
+/* Shouldn't be necessary, but just in case the end of the above function,
+   containing the .code16, gets "optimized away"...  */
+CODE16
+
+void i16_vcpi_shutdown()
+{
+	if (pic_reprogrammed)
+	{
+		pic_reprogrammed = FALSE;
+
+		i16_cli();
+
+		i16_assert(irq_master_base >= 0x20);
+
+		/* Reprogram the PIC.  */
+		i16_pic_set_master(0x08);
+
+		/* Inform the VCPI server.  */
+		i16_vcpi_set_int_vecs(0x08, irq_slave_base);
+
+		/* Restore the old interrupt vectors.  */
+		{
+			int i;
+
+			for (i = 0; i < 8; i++)
+			{
+				i16_dos_set_int_vec(irq_master_base+i,
+						    &master_save_vecs[i]);
+			}
+		}
+
+		i16_sti();
+	}
+
+	if (ems_page_allocated)
+	{
+		ems_page_allocated = 0;
+		asm volatile("int $0x67" : : "a" (0x4500), "d" (ems_handle));
+	}
+}
+
+#endif ENABLE_VCPI
+
diff --git a/i386/dos/i16/i16_xms.c b/i386/dos/i16/i16_xms.c
new file mode 100644
index 0000000..ba75d5c
--- /dev/null
+++ b/i386/dos/i16/i16_xms.c
@@ -0,0 +1,175 @@
+/* 
+ * Copyright (c) 1995-1994 The University of Utah and
+ * the Computer Systems Laboratory at the University of Utah (CSL).
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify and distribute this software is hereby
+ * granted provided that (1) source code retains these copyright, permission,
+ * and disclaimer notices, and (2) redistributions including binaries
+ * reproduce the notices in supporting documentation, and (3) all advertising
+ * materials mentioning features or use of this software display the following
+ * acknowledgement: ``This product includes software developed by the
+ * Computer Systems Laboratory at the University of Utah.''
+ *
+ * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS
+ * IS" CONDITION.  THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF
+ * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * CSL requests users of this software to return to csl-dist@cs.utah.edu any
+ * improvements that they make and grant CSL redistribution rights.
+ *
+ *      Author: Bryan Ford, University of Utah CSL
+ */
+
+#include <mach/machine/code16.h>
+#include <mach/machine/vm_types.h>
+#include <mach/machine/far_ptr.h>
+#include <mach/machine/asm.h>
+
+#include "i16_a20.h"
+#include "phys_mem.h"
+#include "debug.h"
+
+
+struct far_pointer_16 xms_control;
+
+#define CALL_XMS "lcallw "SEXT(xms_control)
+
+
+static vm_offset_t xms_phys_free_mem;
+static vm_size_t xms_phys_free_size;
+
+static short free_handle;
+static char free_handle_allocated;
+static char free_handle_locked;
+
+
+CODE32
+
+void xms_mem_collect(void)
+{
+	if (xms_phys_free_mem)
+	{
+		phys_mem_add(xms_phys_free_mem, xms_phys_free_size);
+		xms_phys_free_mem = 0;
+	}
+}
+
+CODE16
+
+static void i16_xms_enable_a20(void)
+{
+	short success;
+	asm volatile(CALL_XMS : "=a" (success) : "a" (0x0500) : "ebx");
+	if (!success)
+		i16_die("XMS error: can't enable A20 line");
+}
+
+static void i16_xms_disable_a20(void)
+{
+	short success;
+	asm volatile(CALL_XMS : "=a" (success) : "a" (0x0600) : "ebx");
+	if (!success)
+		i16_die("XMS error: can't disable A20 line");
+}
+
+void i16_xms_check()
+{
+	unsigned short rc;
+	unsigned short free_k;
+
+	/* Check for an XMS server.  */
+	asm volatile("
+		int $0x2f
+	" : "=a" (rc)
+	  : "a" (0x4300));
+	if ((rc & 0xff) != 0x80)
+		return;
+
+	/* Get XMS driver's control function.  */
+	asm volatile("
+		pushl	%%ds
+		pushl	%%es
+		int	$0x2f
+		movw	%%es,%0
+		popl	%%es
+		popl	%%ds
+	" : "=r" (xms_control.seg), "=b" (xms_control.ofs)
+	  : "a" (0x4310));
+
+	/* See how much memory is available.  */
+	asm volatile(CALL_XMS
+	  : "=a" (free_k)
+	  : "a" (0x0800)
+	  : "ebx", "edx");
+	if (free_k * 1024 == 0)
+		return;
+
+	xms_phys_free_size = (unsigned)free_k * 1024;
+
+	/* Grab the biggest memory block we can get.  */
+	asm volatile(CALL_XMS
+	  : "=a" (rc), "=d" (free_handle)
+	  : "a" (0x0900), "d" (free_k)
+	  : "ebx");
+	if (!rc)
+		i16_die("XMS error: can't allocate extended memory");
+
+	free_handle_allocated = 1;
+
+	/* Lock it down.  */
+	asm volatile(CALL_XMS "
+		shll	$16,%%edx
+		movw	%%bx,%%dx
+	" : "=a" (rc), "=d" (xms_phys_free_mem)
+	  : "a" (0x0c00), "d" (free_handle)
+	  : "ebx");
+	if (!rc)
+		i16_die("XMS error: can't lock down extended memory");
+
+	free_handle_locked = 1;
+
+	/* We need to update phys_mem_max here
+	   instead of just letting phys_mem_add() do it
+	   when the memory is collected with phys_mem_collect(),
+	   because VCPI initialization needs to know the top of physical memory
+	   before phys_mem_collect() is called.
+	   See i16_vcpi.c for the gross details.  */
+	if (phys_mem_max < xms_phys_free_mem + xms_phys_free_size)
+		phys_mem_max = xms_phys_free_mem + xms_phys_free_size;
+
+	i16_enable_a20 = i16_xms_enable_a20;
+	i16_disable_a20 = i16_xms_disable_a20;
+
+	do_debug(i16_puts("XMS detected"));
+}
+
+void i16_xms_shutdown()
+{
+	unsigned short rc;
+
+	if (free_handle_locked)
+	{
+		/* Unlock our memory block.  */
+		asm volatile(CALL_XMS
+		  : "=a" (rc)
+		  : "a" (0x0d00), "d" (free_handle)
+		  : "ebx");
+		free_handle_locked = 0;
+		if (!rc)
+			i16_die("XMS error: can't unlock extended memory");
+	}
+
+	if (free_handle_allocated)
+	{
+		/* Free the memory block.  */
+		asm volatile(CALL_XMS
+		  : "=a" (rc)
+		  : "a" (0x0a00), "d" (free_handle)
+		  : "ebx");
+		free_handle_allocated = 0;
+		if (!rc)
+			i16_die("XMS error: can't free extended memory");
+	}
+}
+
diff --git a/i386/dos/i16/idt.h b/i386/dos/i16/idt.h
new file mode 100644
index 0000000..5469196
--- /dev/null
+++ b/i386/dos/i16/idt.h
@@ -0,0 +1,39 @@
+/* 
+ * Copyright (c) 1995-1994 The University of Utah and
+ * the Computer Systems Laboratory at the University of Utah (CSL).
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify and distribute this software is hereby
+ * granted provided that (1) source code retains these copyright, permission,
+ * and disclaimer notices, and (2) redistributions including binaries
+ * reproduce the notices in supporting documentation, and (3) all advertising
+ * materials mentioning features or use of this software display the following
+ * acknowledgement: ``This product includes software developed by the
+ * Computer Systems Laboratory at the University of Utah.''
+ *
+ * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS
+ * IS" CONDITION.  THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF
+ * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * CSL requests users of this software to return to csl-dist@cs.utah.edu any
+ * improvements that they make and grant CSL redistribution rights.
+ *
+ *      Author: Bryan Ford, University of Utah CSL
+ */
+#ifndef _I386_DOS_IDT_
+#define _I386_DOS_IDT_
+
+#include "config.h"
+
+#ifdef ENABLE_VCPI
+
+/* We need a maximum-size IDT in order to run as a VCPI client,
+   because someone else may already have reprogrammed the PIC
+   to point to any set of vectors.  */
+#define IDTSZ 256
+
+#endif ENABLE_VCPI
+
+#include_next "idt.h"
+
+#endif _I386_DOS_IDT_
diff --git a/i386/dos/i16/phys_mem_sources.h b/i386/dos/i16/phys_mem_sources.h
new file mode 100644
index 0000000..249e14a
--- /dev/null
+++ b/i386/dos/i16/phys_mem_sources.h
@@ -0,0 +1,28 @@
+/* 
+ * Copyright (c) 1995-1994 The University of Utah and
+ * the Computer Systems Laboratory at the University of Utah (CSL).
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify and distribute this software is hereby
+ * granted provided that (1) source code retains these copyright, permission,
+ * and disclaimer notices, and (2) redistributions including binaries
+ * reproduce the notices in supporting documentation, and (3) all advertising
+ * materials mentioning features or use of this software display the following
+ * acknowledgement: ``This product includes software developed by the
+ * Computer Systems Laboratory at the University of Utah.''
+ *
+ * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS
+ * IS" CONDITION.  THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF
+ * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * CSL requests users of this software to return to csl-dist@cs.utah.edu any
+ * improvements that they make and grant CSL redistribution rights.
+ *
+ *      Author: Bryan Ford, University of Utah CSL
+ */
+
+pms(dos_mem)
+pms(xms_mem)
+/*pms(vcpi_mem) XXX */
+
+#include_next "phys_mem_sources.h"
diff --git a/i386/dos/putchar.c b/i386/dos/putchar.c
new file mode 100644
index 0000000..9b5d59b
--- /dev/null
+++ b/i386/dos/putchar.c
@@ -0,0 +1,41 @@
+/* 
+ * Copyright (c) 1995-1994 The University of Utah and
+ * the Computer Systems Laboratory at the University of Utah (CSL).
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify and distribute this software is hereby
+ * granted provided that (1) source code retains these copyright, permission,
+ * and disclaimer notices, and (2) redistributions including binaries
+ * reproduce the notices in supporting documentation, and (3) all advertising
+ * materials mentioning features or use of this software display the following
+ * acknowledgement: ``This product includes software developed by the
+ * Computer Systems Laboratory at the University of Utah.''
+ *
+ * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS
+ * IS" CONDITION.  THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF
+ * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * CSL requests users of this software to return to csl-dist@cs.utah.edu any
+ * improvements that they make and grant CSL redistribution rights.
+ *
+ *      Author: Bryan Ford, University of Utah CSL
+ */
+
+#include <mach/machine/eflags.h>
+
+#include "real.h"
+
+int putchar(int c)
+{
+	struct real_call_data rcd;
+
+	if (c == '\n')
+		putchar('\r');
+
+	real_call_data_init(&rcd);
+	rcd.eax = 0x0200;
+	rcd.edx = c;
+	real_int(0x21, &rcd);
+	return rcd.flags & EFL_CF ? -1 : 0;
+}
+
-- 
cgit v1.2.3