From f07a4c844da9f0ecae5bbee1ab94be56505f26f7 Mon Sep 17 00:00:00 2001 From: Thomas Bushnell Date: Tue, 25 Feb 1997 21:28:37 +0000 Subject: Initial source --- 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 ++ 13 files changed, 1654 insertions(+) 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 (limited to 'i386/dos/i16') 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 + +#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 +#include + + +/* 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 +#include + +#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(¶s); + } + 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 +#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 + +#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 + +#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 + +#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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 +#include +#include +#include + +#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" -- cgit v1.2.3