summaryrefslogtreecommitdiff
path: root/i386/dos/i16
diff options
context:
space:
mode:
authorThomas Bushnell <thomas@gnu.org>1997-02-25 21:28:37 +0000
committerThomas Bushnell <thomas@gnu.org>1997-02-25 21:28:37 +0000
commitf07a4c844da9f0ecae5bbee1ab94be56505f26f7 (patch)
tree12b07c7e578fc1a5f53dbfde2632408491ff2a70 /i386/dos/i16
Initial source
Diffstat (limited to 'i386/dos/i16')
-rw-r--r--i386/dos/i16/gdt.h32
-rw-r--r--i386/dos/i16/gdt_sels.h36
-rw-r--r--i386/dos/i16/i16_crt0.S274
-rw-r--r--i386/dos/i16/i16_crt0.h32
-rw-r--r--i386/dos/i16/i16_dos.h146
-rw-r--r--i386/dos/i16/i16_dos_mem.c182
-rw-r--r--i386/dos/i16/i16_exit.c50
-rw-r--r--i386/dos/i16/i16_main.c60
-rw-r--r--i386/dos/i16/i16_putchar.c36
-rw-r--r--i386/dos/i16/i16_vcpi.c564
-rw-r--r--i386/dos/i16/i16_xms.c175
-rw-r--r--i386/dos/i16/idt.h39
-rw-r--r--i386/dos/i16/phys_mem_sources.h28
13 files changed, 1654 insertions, 0 deletions
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"