diff options
author | jlemon <jlemon@FreeBSD.org> | 1997-09-30 22:04:06 +0000 |
---|---|---|
committer | jlemon <jlemon@FreeBSD.org> | 1997-09-30 22:04:06 +0000 |
commit | d41bb2bc87f29068e4d03f319a4989911f2cd73c (patch) | |
tree | 648a56a6242ed5ba9d08e736053edb3c7c0a6194 /usr.bin/doscmd | |
parent | 0f45f2fb69fa51d32a49bcda72f6de056fdf4b0a (diff) | |
download | FreeBSD-src-d41bb2bc87f29068e4d03f319a4989911f2cd73c.zip FreeBSD-src-d41bb2bc87f29068e4d03f319a4989911f2cd73c.tar.gz |
Add support for EMS emulation to doscmd. This requires changing the
interface for callbacks to doscmd from DOS, obsoleting the instbsdi
redirector. (redir.com replaces it)
A temporary hack is in place so the instbsdi program will (hopefully) work
in the short term.
Submitted by: Helmut F. Wirth <hfwirth@ping.at>
Diffstat (limited to 'usr.bin/doscmd')
-rw-r--r-- | usr.bin/doscmd/Makefile | 22 | ||||
-rw-r--r-- | usr.bin/doscmd/Makefile.dos | 47 | ||||
-rw-r--r-- | usr.bin/doscmd/README.booting_dos | 20 | ||||
-rw-r--r-- | usr.bin/doscmd/doscmd.1 | 19 | ||||
-rw-r--r-- | usr.bin/doscmd/doscmd.c | 7 | ||||
-rw-r--r-- | usr.bin/doscmd/doscmd.h | 11 | ||||
-rw-r--r-- | usr.bin/doscmd/ems.c | 1696 | ||||
-rw-r--r-- | usr.bin/doscmd/ems.h | 313 | ||||
-rw-r--r-- | usr.bin/doscmd/emsdriv.S | 261 | ||||
-rw-r--r-- | usr.bin/doscmd/emsdriv.sys.uu | 11 | ||||
-rw-r--r-- | usr.bin/doscmd/emuint.c | 111 | ||||
-rw-r--r-- | usr.bin/doscmd/emuint.h | 50 | ||||
-rw-r--r-- | usr.bin/doscmd/instbsdi.c | 55 | ||||
-rw-r--r-- | usr.bin/doscmd/instbsdi.exe.uu | 172 | ||||
-rw-r--r-- | usr.bin/doscmd/intff.c | 10 | ||||
-rw-r--r-- | usr.bin/doscmd/redir.S | 122 | ||||
-rw-r--r-- | usr.bin/doscmd/redir.com.uu | 6 | ||||
-rw-r--r-- | usr.bin/doscmd/trap.c | 9 | ||||
-rw-r--r-- | usr.bin/doscmd/xms.c | 116 |
19 files changed, 2757 insertions, 301 deletions
diff --git a/usr.bin/doscmd/Makefile b/usr.bin/doscmd/Makefile index c8754e7..1c35787 100644 --- a/usr.bin/doscmd/Makefile +++ b/usr.bin/doscmd/Makefile @@ -5,11 +5,12 @@ PROG= doscmd MAN1= doscmd.1 SRCS= AsyncIO.c ParseBuffer.c bios.c callback.c cpu.c dos.c cmos.c config.c \ - cwd.c debug.c disktab.c doscmd.c exe.c i386-pinsn.c int.c int10.c \ - int13.c int14.c int16.c int17.c int1a.c int2f.c intff.c mem.c mouse.c \ - net.c port.c setver.c signal.c timer.c trace.c trap.c tty.c xms.c + cwd.c debug.c disktab.c doscmd.c ems.c emuint.c exe.c i386-pinsn.c \ + int.c int10.c int13.c int14.c int16.c int17.c int1a.c int2f.c intff.c \ + mem.c mouse.c net.c port.c setver.c signal.c timer.c trace.c trap.c \ + tty.c xms.c -CLEANFILES= doscmd.kernel crt0.o doscmd_loader.o instbsdi.exe +CLEANFILES= doscmd.kernel crt0.o doscmd_loader.o redir.com emsdriv.sys BINGRP= kmem EXEGRP= bin @@ -31,13 +32,18 @@ afterinstall: install ${COPY} -o ${BINOWN} -g ${EXEGRP} -m ${EXEMODE} \ doscmd.kernel ${DESTDIR}/usr/libexec/doscmd.kernel install -c -o ${BINOWN} -g ${EXEGRP} -m ${EXEMODE} \ - instbsdi.exe ${DESTDIR}/usr/libdata/doscmd/ + redir.com ${DESTDIR}/usr/libdata/doscmd/ + install -c -o ${BINOWN} -g ${EXEGRP} -m ${EXEMODE} \ + emsdriv.sys ${DESTDIR}/usr/libdata/doscmd/ -doscmd: doscmd.kernel ${LIBCRT0} doscmd_loader.o instbsdi.exe +doscmd: doscmd.kernel ${LIBCRT0} doscmd_loader.o redir.com emsdriv.sys ld -e start -dc -dp -o doscmd /usr/lib/crt0.o doscmd_loader.o -lgcc -lc -instbsdi.exe: instbsdi.exe.uu - uudecode ${.CURDIR}/instbsdi.exe.uu +redir.com: redir.com.uu + uudecode ${.CURDIR}/redir.com.uu + +emsdriv.sys: emsdriv.sys.uu + uudecode ${.CURDIR}/emsdriv.sys.uu .include <bsd.prog.mk> diff --git a/usr.bin/doscmd/Makefile.dos b/usr.bin/doscmd/Makefile.dos new file mode 100644 index 0000000..5951bee --- /dev/null +++ b/usr.bin/doscmd/Makefile.dos @@ -0,0 +1,47 @@ +# Special makefile for the as86/ld86 tools +# +# This is used only to make the dos tools. It is not used in the normal +# build process, except one of the *.S files is changed. The ready to +# use tools are included as uuencoded files. +# To use this makefile you must have Bruce Evans bcc package installed +# + +AS86 = as86 +LD86 = ld86 + +OBJS = redir.o emsdriv.o +DOSPROG = redir.com emsdriv.sys +DOSDIST = redir.com.uu emsdriv.sys.uu + +all: ${DOSPROG} ${DOSDIST} + +redir.com: redir.o + $(LD86) -T 0 -s -o ${.PREFIX}.tmp ${.ALLSRC} + dd if=${.PREFIX}.tmp of=${.TARGET} bs=1 skip=288 + rm -f ${.PREFIX}.tmp + +emsdriv.sys: emsdriv.o + $(LD86) -T 0 -s -o ${.PREFIX}.tmp ${.ALLSRC} + dd if=${.PREFIX}.tmp of=${.TARGET} bs=1 skip=32 + rm -f ${.PREFIX}.tmp + +redir.com.uu: redir.com + uuencode redir.com redir.com > redir.com.uu + +emsdriv.sys.uu: emsdriv.sys + uuencode emsdriv.sys emsdriv.sys > emsdriv.sys.uu + +clean: + rm -f ${DOSPROG} ${OBJS} + +allclean: + rm -f ${DOSPROG} ${DOSDIST} ${OBJS} + + +# Rule for as86 +.S.o: + $(AS86) -0 -o ${.TARGET} ${.IMPSRC} + + + + diff --git a/usr.bin/doscmd/README.booting_dos b/usr.bin/doscmd/README.booting_dos index 6172442..3f0098b 100644 --- a/usr.bin/doscmd/README.booting_dos +++ b/usr.bin/doscmd/README.booting_dos @@ -29,10 +29,10 @@ To install DOS on a pseudo hard disk under doscmd: 2) Insert a floppy disk into the A: drive which is bootable to MS-DOS and has the commands fdisk, format and sys on it. You should also - copy the file instbsdi.exe onto the floppy by either mounting it + copy the file redir.com onto the floppy by either mounting it with the msdos file system type or by using mtools. - (i.e. mwrite instbsdi.exe a:) + (i.e. mwrite redir.com a:) 3) run doscmd. @@ -72,18 +72,26 @@ To install DOS on a pseudo hard disk under doscmd: ^Z > copy con: autoexec.bat @echo off - instbsdi.exe + redir.com ^Z 16) Quit doscmd. - 17) You know have a bootable pseudo disk which will automatically call - the magic "instbsdi" program, which installs BSDI disks. To use + 17) You now have a bootable pseudo disk which will automatically call + the magic "redir" program, which installs FreeBSD disks. To use them add lines to your .doscmdrc such as: assign D: /usr/dos assign P: -ro /usr/prb - Not ethat you will not always be able to access every file due to + Note that you will not always be able to access every file due to naming problems. + + 18) To use the new EMS memory you need to copy the file emsdriv.sys + to your DOS boot disk (disk image) in the same way you copied + redir.com. The use it in your "config.sys" from DOS: + device=C:\emsdriv.sys + where C: is your boot drive (supply the correct letter, if needed) + and emsdriv.sys is the driver. You could load it high. It should + report "Doscmd EMS 4.0 driver installed". diff --git a/usr.bin/doscmd/doscmd.1 b/usr.bin/doscmd/doscmd.1 index c1e1ba3..76e4e31 100644 --- a/usr.bin/doscmd/doscmd.1 +++ b/usr.bin/doscmd/doscmd.1 @@ -37,7 +37,7 @@ .Nd run a subset of real-mode DOS programs .Sh SYNOPSIS .Nm doscmd -.Fl 23AbDEfHIMOPRrtVvxz +.Fl 23AbDEfHIMOPRrtVvXxYz .Fl c Ar file .Fl d Ar file .Fl i Ar port Ns Xo @@ -263,6 +263,11 @@ can be used with or without .\" .\" .\" +.It Fl Y +Enable debugging of the EMS operations. +.\" +.\" +.\" .It Fl z Cause .Nm doscmd @@ -315,7 +320,7 @@ to be assigned as the specified drive. If the .Fl ro flag is specified, it is a read only file system. These assignments will not take place when booting DOS until the -.Pa /usr/dos/instbsdi.exe +.Pa /usr/libdata/doscmd/redir.com binary is run. .\" .\" @@ -622,10 +627,10 @@ must exist, so use the command touch to create it. .It 2 Insert a floppy disk into the A: drive which is bootable to MS-DOS and has the commands fdisk, format and sys on it. You should also -copy the file instbsdi.exe onto the floppy by either mounting it +copy the file redir.com onto the floppy by either mounting it with the msdos file system type or by using mtools (e.g., -.Li mwrite instbsdi.exe a: ). +.Li mwrite redir.com a: ). .It 3 run doscmd. .It 4 @@ -672,7 +677,7 @@ LASTDRIVE=Z ^Z > copy con: autoexec.bat @echo off -instbsdi.exe +redir.com ^Z .Ed .It 15 @@ -680,8 +685,8 @@ Quit doscmd. .It 16 You know have a bootable pseudo disk which will automatically call the magic -.Li instbsdi -program, which installs BSD/OS disks. To use +.Li redir +program, which installs FreeBSD disks. To use them add lines to your .doscmdrc such as: .Bd -literal -offset indent assign D: /usr/dos diff --git a/usr.bin/doscmd/doscmd.c b/usr.bin/doscmd/doscmd.c index 295b6a4..2bfa3cf 100644 --- a/usr.bin/doscmd/doscmd.c +++ b/usr.bin/doscmd/doscmd.c @@ -29,7 +29,7 @@ * * BSDI doscmd.c,v 2.3 1996/04/08 19:32:30 bostic Exp * - * $Id: doscmd.c,v 1.1 1997/08/09 01:42:41 dyson Exp $ + * $Id: doscmd.c,v 1.2 1997/08/15 23:41:23 jlemon Exp $ */ #include <sys/types.h> @@ -489,7 +489,7 @@ do_args(int argc, char *argv[]) FILE *fp; char *col; - while ((c = getopt (argc, argv, "234Oc:TkCIEMPRLAU:S:HDtzvVxXfbri:o:d:")) != -1) { + while ((c = getopt (argc, argv, "234Oc:TkCIEMPRLAU:S:HDtzvVxXYfbri:o:d:")) != -1) { switch (c) { case 'd': if (fp = fopen(optarg, "w")) { @@ -572,6 +572,9 @@ do_args(int argc, char *argv[]) case 'X': debug_flags |= D_XMS; break; + case 'Y': + debug_flags |= D_EMS; + break; case 'L': debug_flags |= D_PRINTER; break; diff --git a/usr.bin/doscmd/doscmd.h b/usr.bin/doscmd/doscmd.h index 27aa07f..9d420d9 100644 --- a/usr.bin/doscmd/doscmd.h +++ b/usr.bin/doscmd/doscmd.h @@ -29,7 +29,7 @@ * * BSDI doscmd.h,v 2.3 1996/04/08 19:32:32 bostic Exp * - * $Id: doscmd.h,v 1.1 1997/08/09 01:43:09 dyson Exp $ + * $Id: doscmd.h,v 1.2 1997/08/15 23:41:24 jlemon Exp $ */ @@ -107,6 +107,7 @@ extern int debug_flags; #define D_DEBUGIN 0x0400000 #define D_DOSCALL 0x0800000 /* MS-DOS function results */ #define D_XMS 0x1000000 /* XMS calls */ +#define D_EMS 0x2000000 /* EMS calls */ #define TTYF_ECHO 0x00000001 #define TTYF_ECHONL 0x00000003 @@ -179,6 +180,9 @@ extern void mem_change_owner(int addr, int owner); extern int int2f_11(regcontext_t *REGS); extern void intff(regcontext_t *REGS); +/* emuint.c */ +extern void emuint(regcontext_t *REGS); + /* trap.c */ extern void fake_int(regcontext_t *REGS, int); extern void sigtrap(struct sigframe *sf); @@ -235,6 +239,11 @@ extern void get_raw_extmemory_info(regcontext_t *REGS); extern void initHMA(void); extern u_long xms_maxsize; +/* ems.c */ +extern int ems_init(); +extern void ems_entry(regcontext_t *REGS); +extern u_long ems_frame_addr; + /****************************** dirty below here ******************************/ extern u_long pending[]; /* pending interrupts */ diff --git a/usr.bin/doscmd/ems.c b/usr.bin/doscmd/ems.c new file mode 100644 index 0000000..25b68db --- /dev/null +++ b/usr.bin/doscmd/ems.c @@ -0,0 +1,1696 @@ +/*- + * Copyright (c) 1997 Helmut Wirth <hfwirth@ping.at> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice immediately at the beginning of the file, witout modification, + * this list of conditions, and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $Id$ + */ + +/* + * EMS memory emulation + * + * To emulate Expanded Memory we use a DOS driver (emsdriv.sys) which + * routes calls to int 0x67 to this emulator routine. The main entry point + * is ems_entry(..). The emulator needs to be initialized before the first + * call. The first step of the initialization is done during program startup + * the second part is done during DOS boot, from a call of the DOS driver. + * The DOS driver is neccessary because DOS programs look for it to + * determine if EMS is available. + * + * To emulate a configurable amount of EMS memory we use a file created + * at startup with the size of the configured EMS memory. This file is + * mapped into the EMS window like any DOS memory manager would do, using + * mmap calls. + * + * The emulation follows the LIM EMS 4.0 standard. Not all functions of it + * are implemented yet. The "alter page map and jump" and "alter page map + * and call" functions are not implemented, because they are rather hard to + * do. (It would mean a call to the emulator executes a routine in EMS + * memory and returns to the emulator, the emulator switches the page map + * and then returns to the DOS program.) LINUX does not emulate this + * functions and I think they were very rarely used by DOS applications. + * + * Credits: To the writers of LINUX dosemu, I looked at their code + */ + +#include <sys/types.h> +#include <sys/param.h> +#include <sys/mman.h> +#include <unistd.h> + +#include "doscmd.h" +#include "ems.h" + +/* Will be configurable */ +u_long ems_max_size = EMS_MAXSIZE * 1024; +u_long ems_frame_addr = EMS_FRAME_ADDR; + +/* + * Method for EMS: Allocate a mapfile with the size of EMS memory + * and map the needed part into the page frame + */ + +#define EMS_MAP_PATH "/var/tmp/" /* Use a big file system */ +#define EMS_MAP_FILE "doscmd.XXXXXX" +static int mapfile_fd = -1; + +/* Pages are always 16 kB in size. The page frame is 64 kB, there are + * 4 positions (0..3) for a page to map in. The pages are numbered from 0 to + * the highest 16 kB page in the mapfile, depending on the EMS size + */ + +EMS_mapping_context ems_mapping_context; + +/* Handle and page management (see ems.h) */ + +/* The handle array. If the pointer is NULL, the handle is unallocated */ +static EMS_handle *ems_handle[EMS_NUM_HANDLES]; +static u_long ems_alloc_handles; +/* The active handle, if any */ +static short active_handle; + +/* The page array. It is malloced at runtime, depending on the total + * allocation size + */ + +static EMS_page *ems_page = NULL; +static u_long ems_total_pages; +static u_long ems_alloc_pages; +static u_long ems_free_pages; + +/* Local structure used for region copy and move operations */ + +struct copydesc { +#define SRC_EMS 1 +#define DST_EMS 2 + short copytype; /* Type of source and destination memory */ + EMS_addr src_addr; /* Combined pointer for source */ + EMS_addr dst_addr; /* Combined pointer for destination */ + u_long rest_len; /* Lenght to copy */ +}; + + +/* Local prototypes */ +static int init_mapfile(); +static void map_page(u_long pagenum, u_char position, short handle, + int unmaponly); +static EMS_handle *get_new_handle(long npages); +static void context_to_handle(short handle); +static long find_next_free_handle(); +static short lookup_handle(Hname *hp); +static void allocate_pages_to_handle(u_short handle, long npages); +static void allocate_handle(short handle, long npages); +static void reallocate_pages_to_handle(u_short handle, long npages); +static void free_handle(short handle); +static void free_pages_of_handle(short handle); +static void restore_context(EMS_mapping_context *emc); +static void save_context_to_dos(EMScontext *emp); +static int check_saved_context(EMScontext *emp); +static void *get_valid_pointer(u_short seg, u_short offs, u_long size); +static u_long move_ems_to_conv(short handle, u_short src_seg, + u_short src_offset, u_long dst_addr, u_long length); +static u_long move_conv_to_ems(u_long src_addr, u_short dst_handle, + u_short dst_seg, u_short dst_offset, u_long length); +static u_long move_ems_to_ems(u_short src_hande, u_short src_seg, + u_short src_offset, u_short dst_handle, + u_short dst_seg, u_short dst_offset, u_long length); + + +/* + * EMS initialization routine: Return 1, if successful, return 0 if + * init problem or EMS disabled + */ + +int +ems_init() +{ + int i; + + if (ems_max_size == 0) + return 0; + if (init_mapfile() == 0) + return 0; + /* Sanity */ + bzero((void *)(&ems_handle[0]), sizeof(ems_handle)); + ems_total_pages = ems_max_size / EMS_PAGESIZE; + ems_alloc_pages = 0; + ems_free_pages = ems_total_pages; + ems_alloc_handles = 0; + active_handle = 0; + /* Malloc the page array */ + ems_page = (EMS_page *)malloc(sizeof(EMS_page) * ems_total_pages); + if (ems_page == NULL) { + debug(D_ALWAYS, "Could not malloc page array, EMS disabled\n"); + ems_frame_addr = 0; + ems_max_size = 0; + ems_total_pages = 0; + return 0; + } + for (i = 0; i < ems_total_pages; i++) { + ems_page[i].handle = 0; + ems_page[i].status = EMS_FREE; + } + debug(D_EMS, "EMS: Emulation init OK.\n"); + return 1; +} + + +/* Main entry point */ + +void +ems_entry(regcontext_t *REGS) +{ + /* + * If EMS is not enabled, the DOS ems.exe module should not have + * been loaded. If it is loaded anyway, report software malfunction + */ + if (ems_max_size == 0) { + R_AH = EMS_SW_MALFUNC; + debug(D_EMS, "EMS emulation not enabled\n"); + return; + } + + switch (R_AH) + { + case GET_MANAGER_STATUS: + debug(D_EMS, "EMS: Get manager status\n"); + R_AH = EMS_SUCCESS; + break; + + case GET_PAGE_FRAME_SEGMENT: + debug(D_EMS, "EMS: Get page frame segment\n"); + R_BX = ems_frame_addr >> 4; + R_AH = EMS_SUCCESS; + break; + + case GET_PAGE_COUNTS: + R_BX = ems_total_pages - ems_alloc_pages; + R_DX = ems_total_pages; + debug(D_EMS, "EMS: Get page count: Returned total=%d, free=%d\n", + R_DX, R_BX); + R_AH = EMS_SUCCESS; + break; + + case GET_HANDLE_AND_ALLOCATE: + { + u_short npages; + short handle; + + npages = R_BX; + debug(D_EMS, "EMS: Get handle and allocate %d pages: ", npages); + + /* Enough handles? */ + if ((handle = find_next_free_handle()) < 0) { + debug(D_EMS,"Return error:No handles\n"); + R_AH = EMS_OUT_OF_HANDLES; + break; + } + /* Enough memory for this request ? */ + if (npages > ems_free_pages) { + debug(D_EMS,"Return error:Request too big\n"); + R_AH = EMS_OUT_OF_LOG; + break; + } + if (npages > ems_total_pages) { + debug(D_EMS,"Return error:Request too big\n"); + R_AH = EMS_OUT_OF_PHYS; + break; + } + /* Not allowed to allocate zero pages with this function */ + if (npages == 0) { + debug(D_EMS,"Return error:Cannot allocate 0 pages\n"); + R_AH = EMS_ZERO_PAGES; + break; + } + /* Allocate the handle */ + allocate_handle(handle, npages); + + /* Allocate the pages */ + allocate_pages_to_handle(handle, npages); + R_DX = handle; + R_AH = EMS_SUCCESS; + debug(D_EMS,"Return success:Handle = %d\n", handle); + break; + } + + case MAP_UNMAP: + { + u_char position; + u_short hpagenum, spagenum; + short handle; + + debug(D_EMS, "EMS: Map/Unmap handle=%d, pos=%d, pagenum=%d ", + R_DX, R_AL, R_BX); + handle = R_DX; + position = R_AL; + if (position > 3) { + debug(D_EMS, "invalid position\n"); + R_AH = EMS_ILL_PHYS; + break; + } + hpagenum = R_BX; + /* This succeeds without a valid handle ! */ + if (hpagenum == 0xffff) { + /* Unmap only */ + map_page(0, position, handle, 1); + debug(D_EMS, "(unmap only) success\n"); + R_AH = EMS_SUCCESS; + break; + } + if (handle > 255 || handle == 0 || ems_handle[handle] == NULL) { + R_AH = EMS_INV_HANDLE; + debug(D_EMS, "invalid handle\n"); + break; + } + if (hpagenum >= ems_handle[handle]->npages) { + R_AH = EMS_LOGPAGE_TOOBIG; + debug(D_EMS, "invalid pagenumber\n"); + break; + } + spagenum = ems_handle[handle]->pagenum[hpagenum]; + map_page(spagenum, position, handle, 0); + debug(D_EMS, "success\n"); + R_AH = EMS_SUCCESS; + break; + } + + case DEALLOCATE_HANDLE: + { + short handle; + + /* Handle valid ? */ + handle = R_DX; + debug(D_EMS, "EMS: Deallocate handle %d\n", handle); + if (handle > 255 || ems_handle[handle] == NULL) { + R_AH = EMS_INV_HANDLE; + break; + } + /* Mapping context saved ? */ + if (ems_handle[handle]->mcontext != NULL) { + R_AH = EMS_SAVED_MAP; + break; + } + + free_pages_of_handle(handle); + free_handle(handle); + R_AH = EMS_SUCCESS; + break; + } + + case GET_EMM_VERSION: + debug(D_EMS, "EMS: Get version\n"); + R_AL = EMS_VERSION; + R_AH = EMS_SUCCESS; + break; + + case SAVE_PAGE_MAP: + { + short handle; + + debug(D_EMS, "EMS: Save page map\n"); + handle = R_DX; + if (handle > 255 || handle == 0 || ems_handle[handle] == NULL) { + R_AH = EMS_INV_HANDLE; + break; + } + if (ems_handle[handle]->mcontext != NULL) { + /* There is already a context saved */ + if (memcmp((void *)ems_handle[handle]->mcontext, + (void *)&ems_mapping_context, + sizeof(EMS_mapping_context)) == 0) + R_AH = EMS_ALREADY_SAVED; + else + R_AH = EMS_NO_ROOM_TO_SAVE; + break; + } + context_to_handle(handle); + R_AH = EMS_SUCCESS; + break; + } + + case RESTORE_PAGE_MAP: + { + short handle; + + debug(D_EMS, "EMS: Restore page map\n"); + handle = R_DX; + if (handle > 255 || handle == 0 || ems_handle[handle] == NULL) { + R_AH = EMS_INV_HANDLE; + break; + } + if (ems_handle[handle]->mcontext == NULL) { + R_AH = EMS_NO_SAVED_CONTEXT; + break; + } + restore_context(ems_handle[handle]->mcontext); + free((void *)ems_handle[handle]->mcontext); + ems_handle[handle]->mcontext = NULL; + R_AH = EMS_SUCCESS; + break; + } + + case RESERVED_1: + case RESERVED_2: + debug(D_ALWAYS, "Reserved function called: %02x\n", R_AH); + R_AH = EMS_FUNC_NOSUP; + break; + + case GET_HANDLE_COUNT: + debug(D_EMS, "EMS: Get handle count\n"); + R_BX = ems_alloc_handles + 1; + R_AH = EMS_SUCCESS; + break; + + case GET_PAGES_OWNED: + { + short handle; + + debug(D_EMS, "EMS: Get pages owned\n"); + /* Handle valid ? */ + handle = R_DX; + if (handle > 255 || ems_handle[handle] == NULL) { + R_AH = EMS_INV_HANDLE; + break; + } + if (handle == 0) + R_BX = 0; + else + R_BX = ems_handle[handle]->npages; + R_AH = EMS_SUCCESS; + break; + } + + case GET_PAGES_FOR_ALL: + { + EMShandlepage *ehp; + int safecount; + int i; + + debug(D_EMS, "EMS: Get pages for all\n"); + /* Get the address passed from DOS app */ + ehp = (EMShandlepage *)get_valid_pointer(R_ES, R_DI, + sizeof(EMShandlepage) * ems_alloc_handles); + if (ehp == NULL) { + R_AH = EMS_SW_MALFUNC; + break; + } + + R_BX = ems_alloc_handles; + safecount = 0; + for (i = 0; i < 255; i++) { + if (ems_handle[i] != NULL) { + if (safecount > (ems_alloc_handles+1)) + fatal("EMS: ems_alloc_handles is wrong, cannot continue\n"); + ehp->handle = i; + ehp->npages = ems_handle[i]->npages; + ehp++; + safecount++; + } + } + R_AH = EMS_SUCCESS; + break; + } + + case PAGE_MAP: + /* This function is a nuisance. It was invented to save time and + * memory, but in our case it is useless. We have to support it + * but we use the same save memory as for the page map function. + * It uses only 20 bytes anyway. We store/restore the entire mapping + */ + case PAGE_MAP_PARTIAL: + { + u_long addr; + int subfunction; + EMScontext *src, *dest; + + debug(D_EMS, "EMS: Page map "); + subfunction = R_AL; + if (R_AH == PAGE_MAP_PARTIAL) { + debug(D_EMS, "partial "); + /* Page map partial has slightly different subfunctions + * GET_SET does not exist and is GET_SIZE in this case + */ + if (subfunction == GET_SET) + subfunction = GET_SIZE; + } + switch (subfunction) + { + case GET: + { + debug(D_EMS, "get\n"); + /* Get the address passed from DOS app */ + dest = (EMScontext *)get_valid_pointer(R_ES, R_DI, + sizeof(EMScontext)); + if (dest == NULL) { + R_AH = EMS_SW_MALFUNC; + break; + } + save_context_to_dos(dest); + R_AH = EMS_SUCCESS; + break; + } + case SET: + { + debug(D_EMS, "set\n"); + src = (EMScontext *)get_valid_pointer(R_DS, R_SI, + sizeof(EMScontext)); + if (src == NULL) { + R_AH = EMS_SW_MALFUNC; + break; + } + if (check_saved_context(src) == 0) { + R_AH = EMS_SAVED_CONTEXT_BAD; + break; + } + restore_context(&src->ems_saved_context); + R_AH = EMS_SUCCESS; + break; + } + case GET_SET: + { + debug(D_EMS, "get/set\n"); + dest = (EMScontext *)get_valid_pointer(R_ES, R_DI, + sizeof(EMScontext)); + if (dest == NULL) { + R_AH = EMS_SW_MALFUNC; + break; + } + save_context_to_dos(dest); + src = (EMScontext *)get_valid_pointer(R_DS, R_SI, + sizeof(EMScontext)); + if (src == NULL) { + R_AH = EMS_SW_MALFUNC; + break; + } + if (check_saved_context(src) == 0) { + R_AH = EMS_SAVED_CONTEXT_BAD; + break; + } + restore_context(&src->ems_saved_context); + R_AH = EMS_SUCCESS; + break; + } + case GET_SIZE: + debug(D_EMS, "get size\n"); + R_AL = (sizeof(EMScontext) + 1) & 0xfe; + R_AH = EMS_SUCCESS; + break; + default: + debug(D_EMS, "invalid subfunction\n"); + R_AH = EMS_INVALID_SUB; + break; + } + break; + } + + case MAP_UNMAP_MULTI_HANDLE: + { + u_char position; + u_short hpagenum, spagenum; + short handle; + EMSmapunmap *mp; + int n_entry, i; + + + debug(D_EMS, "EMS: Map/Unmap multiple "); + + if ((n_entry = R_CX) > 3) { + R_AH = EMS_ILL_PHYS; + } + + /* This is valid according to the LIM EMS 4.0 spec */ + if (n_entry == 0) { + R_AH = EMS_SUCCESS; + break; + } + + handle = R_DX; + if (handle > 255 || handle == 0 || ems_handle[handle] == NULL) { + R_AH = EMS_INV_HANDLE; + break; + } + + mp = (EMSmapunmap *)get_valid_pointer(R_DS, R_SI, + sizeof(EMSmapunmap) * n_entry); + if (mp == NULL) { + R_AH = EMS_SW_MALFUNC; + break; + } + + R_AH = EMS_SUCCESS; + /* Walk through the table and map/unmap */ + for (i = 0; i < n_entry; i++) { + hpagenum = mp->log; + /* Method is in R_AL */ + if (R_AL == 0) { + debug(D_EMS, "phys page method\n"); + if (mp->phys <= 3) { + position = mp->phys; + } else { + R_AH = EMS_ILL_PHYS; + break; + } + } else if (R_AL == 1) { + /* Compute position from segment address */ + u_short p_seg; + + debug(D_EMS, "segment method\n"); + p_seg = mp->phys; + p_seg -= ems_frame_addr; + p_seg /= EMS_PAGESIZE; + if (p_seg <= 3) { + position = p_seg; + } else { + R_AH = EMS_ILL_PHYS; + break; + } + } else { + debug(D_EMS, "invalid subfunction\n"); + R_AH = EMS_INVALID_SUB; + break; + } + + mp++; + if (hpagenum == 0xffff) { + /* Unmap only */ + map_page(0, position, handle, 1); + continue; + } + if (hpagenum >= ems_handle[handle]->npages) { + R_AH = EMS_LOGPAGE_TOOBIG; + break; + } + spagenum = ems_handle[handle]->pagenum[hpagenum]; + map_page(spagenum, position, handle, 0); + } + break; + } + + case REALLOC_PAGES: + { + short handle; + u_long newpages; + + debug(D_EMS, "EMS: Realloc pages "); + + handle = R_DX; + if (handle > 255 || handle == 0 || ems_handle[handle] == NULL) { + R_AH = EMS_INV_HANDLE; + debug(D_EMS, "invalid handle\n"); + break; + } + newpages = R_BX; + debug(D_EMS, "changed from %d to %d pages\n", + ems_handle[handle]->npages, newpages); + + /* Case 1: Realloc to zero pages */ + if (newpages == 0) { + free_pages_of_handle(handle); + R_AH = EMS_SUCCESS; + break; + } + /* Case 2: New allocation is equal to allocated number */ + if (newpages == ems_handle[handle]->npages) { + R_AH = EMS_SUCCESS; + break; + } + /* Case 3: Reallocate to bigger and smaller sizes */ + if (newpages > ems_handle[handle]->npages) { + if (newpages > ems_free_pages) { + R_AH = EMS_OUT_OF_LOG; + break; + } + if (newpages > ems_total_pages) { + R_AH = EMS_OUT_OF_PHYS; + break; + } + } + reallocate_pages_to_handle(handle, newpages); + R_AH = EMS_SUCCESS; + break; + } + + /* We do not support nonvolatile pages */ + case HANDLE_ATTRIBUTES: + debug(D_EMS, "Handle attributes called\n"); + switch (R_AL) { + case GET: + case SET: + R_AH = EMS_FEAT_NOSUP; + break; + case HANDLE_CAPABILITY: + R_AL = 0; /* Volatile only */ + R_AH = EMS_SUCCESS; + break; + default: + R_AH = EMS_FUNC_NOSUP; + break; + } + break; + + case HANDLE_NAME: + { + short handle; + Hname *hp; + + handle = R_DX; + if (handle > 255 || handle == 0 || ems_handle[handle] == NULL) { + R_AH = EMS_INV_HANDLE; + debug(D_EMS, "invalid handle\n"); + break; + } + switch (R_AL) { + case GET: + if ((hp = (Hname *)get_valid_pointer(R_ES, R_DI, 8)) + == NULL) { + R_AH = EMS_SW_MALFUNC; + break; + } + *hp = ems_handle[handle]->hname; + R_AH = EMS_SUCCESS; + break; + + case SET: + if ((hp = (Hname *)get_valid_pointer(R_DS, R_SI, 8)) + == NULL) { + R_AH = EMS_SW_MALFUNC; + break; + } + /* If the handle name is not 0, it may not exist */ + if ((hp->ul_hn[0] | hp->ul_hn[1]) != 0) { + if (lookup_handle(hp) == 0) { + ems_handle[handle]->hname = *hp; + R_AH = EMS_SUCCESS; + } else { + R_AH = EMS_NAME_EXISTS; + break; + } + } else { + /* Name is deleted (set to zeros) */ + ems_handle[handle]->hname = *hp; + R_AH = EMS_SUCCESS; + } + break; + + default: + R_AH = EMS_FUNC_NOSUP; + break; + } + break; + } + + case HANDLE_DIRECTORY: + { + int i; + EMShandledir *hdp; + Hname *hp; + short handle; + + switch(R_AL) { + case GET: + hdp = (EMShandledir *)get_valid_pointer(R_ES, R_DI, + sizeof(EMShandledir) * ems_alloc_handles); + if (hdp == NULL) { + R_AH = EMS_SW_MALFUNC; + break; + } + for (i = 0; i < EMS_NUM_HANDLES; i++) { + if (ems_handle[i] != NULL) { + hdp->log = i; + hdp->name = ems_handle[i]->hname; + } + } + R_AH = EMS_SUCCESS; + break; + + case HANDLE_SEARCH: + hp = (Hname *)get_valid_pointer(R_DS, R_SI, 8); + if (hp == NULL) { + R_AH = EMS_SW_MALFUNC; + break; + } + /* Cannot search for NULL handle name */ + if ((hp->ul_hn[0] | hp->ul_hn[1]) != 0) { + R_AH = EMS_NAME_EXISTS; + break; + } + if ((handle = lookup_handle(hp)) == 0) { + R_AH = EMS_HNAME_NOT_FOUND; + } else { + R_DX = handle; + R_AH = EMS_SUCCESS; + } + break; + + case GET_TOTAL_HANDLES: + R_AH = EMS_SUCCESS; + R_BX = EMS_NUM_HANDLES; /* Includes OS handle */ + break; + + default: + R_AH = EMS_FUNC_NOSUP; + break; + } + break; + } + + + /* I do not know if we need this. LINUX emulation leaves it out + * so I leave it out too for now. + */ + case ALTER_PAGEMAP_JUMP: + debug(D_ALWAYS, "Alter pagemap and jump used!\n"); + R_AH = EMS_FUNC_NOSUP; + break; + case ALTER_PAGEMAP_CALL: + debug(D_ALWAYS, "Alter pagemap and call used!\n"); + R_AH = EMS_FUNC_NOSUP; + break; + + + case MOVE_MEMORY_REGION: + { + EMSmovemem *emvp; + u_long src_addr, dst_addr; + u_short src_handle, dst_handle; + + if (R_AL == EXCHANGE) + debug(D_EMS, "EMS: Exchange memory region "); + else + debug(D_EMS, "EMS: Move memory region "); + + emvp = (EMSmovemem *)get_valid_pointer(R_DS, R_SI, + sizeof(EMSmovemem)); + if (emvp == NULL) { + debug(D_EMS, "Invalid structure pointer\n"); + R_AH = EMS_SW_MALFUNC; + break; + } + /* Zero length is not an error */ + if (emvp->length == 0) { + debug(D_EMS, "Zero length\n"); + R_AH = EMS_SUCCESS; + break; + } + /* Some checks */ + if (emvp->src_type == EMS_MOVE_CONV) { + /* Conventional memory source */ + src_addr = N_GETPTR(emvp->src_seg, emvp->src_offset); + /* May not exceed conventional memory */ + if ((src_addr + emvp->length) > 640 * 1024) { + R_AH = EMS_SW_MALFUNC; + break; + } + } else { + /* Check the handle */ + src_handle = emvp->src_handle; + if (src_handle > 255 || src_handle == 0 || + ems_handle[src_handle] == NULL) { + R_AH = EMS_INV_HANDLE; + debug(D_EMS, "invalid source handle\n"); + break; + } + /* Offset may not exceed page size */ + if (emvp->src_offset >= (16 * 1024)) { + R_AH = EMS_PAGEOFFSET; + debug(D_EMS, "source page offset too big\n"); + break; + } + } + + if (emvp->dst_type == EMS_MOVE_CONV) { + /* Conventional memory source */ + dst_addr = N_GETPTR(emvp->dst_seg, emvp->dst_offset); + /* May not exceed conventional memory */ + if ((dst_addr + emvp->length) > 640 * 1024) { + R_AH = EMS_SW_MALFUNC; + break; + } + } else { + /* Check the handle */ + dst_handle = emvp->dst_handle; + if (dst_handle > 255 || dst_handle == 0 || + ems_handle[dst_handle] == NULL) { + R_AH = EMS_INV_HANDLE; + debug(D_EMS, "invalid destination handle\n"); + break; + } + /* Offset may not exceed page size */ + if (emvp->dst_offset >= (16 * 1024)) { + R_AH = EMS_PAGEOFFSET; + debug(D_EMS, "destination page offset too big\n"); + break; + } + } + + if (R_AL == MOVE) { + /* If it is conventional memory only, do it */ + if (emvp->src_type == EMS_MOVE_CONV && + emvp->dst_type == EMS_MOVE_CONV) { + memmove((void *)dst_addr, (void *)src_addr, + (size_t) emvp->length); + debug(D_EMS, "conventional to conventional memory done\n"); + R_AH = EMS_SUCCESS; + break; + } + if (emvp->src_type == EMS_MOVE_EMS && + emvp->dst_type == EMS_MOVE_CONV) + R_AH = move_ems_to_conv(src_handle, emvp->src_seg, + emvp->src_offset, dst_addr, emvp->length); + else if (emvp->src_type == EMS_MOVE_CONV && + emvp->dst_type == EMS_MOVE_EMS) + R_AH = move_conv_to_ems(src_addr, dst_handle, + emvp->dst_seg, emvp->dst_offset, emvp->length); + else + R_AH = move_ems_to_ems(src_handle, emvp->src_seg, + emvp->src_offset, dst_handle, emvp->dst_seg, + emvp->dst_offset, emvp->length); + debug(D_EMS, " done\n"); + break; + } else { + /* exchange memory region */ + + /* We need a scratch area for the exchange */ + void *buffer; + if ((buffer = malloc(emvp->length)) == NULL) + fatal("EMS: Could not malloc scratch area for exchange"); + + /* If it is conventional memory only, do it */ + if (emvp->src_type == EMS_MOVE_CONV && + emvp->dst_type == EMS_MOVE_CONV) { + /* destination -> buffer */ + memmove(buffer, (void *)dst_addr, (size_t) emvp->length); + /* Source -> destination */ + memmove((void *)dst_addr, (void *)src_addr, + (size_t) emvp->length); + /* Buffer -> source */ + memmove((void *)src_addr, buffer, (size_t) emvp->length); + free(buffer); + debug(D_EMS, "conventional to conventional memory done\n"); + R_AH = EMS_SUCCESS; + break; + } + + /* Exchange EMS with conventional */ + if (emvp->src_type == EMS_MOVE_EMS && + emvp->dst_type == EMS_MOVE_CONV) { + /* Destination -> buffer */ + memmove(buffer, (void *)dst_addr, (size_t) emvp->length); + /* Source -> destination */ + R_AH = move_ems_to_conv(src_handle, emvp->src_seg, + emvp->src_offset, dst_addr, emvp->length); + if (R_AH != EMS_SUCCESS) { + free(buffer); + break; + } + /* Buffer -> source */ + R_AH = move_conv_to_ems((u_long)buffer, src_handle, + emvp->src_seg, emvp->src_offset, emvp->length); + + /* Exchange conventional with EMS */ + } else if (emvp->src_type == EMS_MOVE_CONV && + emvp->dst_type == EMS_MOVE_EMS) { + /* Destination -> buffer */ + R_AH = move_ems_to_conv(dst_handle, emvp->dst_seg, + emvp->dst_offset, (u_long)buffer, emvp->length); + if (R_AH != EMS_SUCCESS) { + free(buffer); + break; + } + /* Source -> destination */ + R_AH = move_conv_to_ems((u_long)buffer, dst_handle, + emvp->dst_seg, emvp->dst_offset, emvp->length); + /* Buffer -> source */ + memmove(buffer, (void *)src_addr, (size_t) emvp->length); + + /* Exchange EMS with EMS */ + } else { + /* Destination -> buffer */ + R_AH = move_ems_to_conv(dst_handle, emvp->dst_seg, + emvp->dst_offset, (u_long)buffer, emvp->length); + if (R_AH != EMS_SUCCESS) { + free(buffer); + break; + } + /* Source -> destination */ + R_AH = move_ems_to_ems(src_handle, emvp->src_seg, + emvp->src_offset, dst_handle, emvp->dst_seg, + emvp->dst_offset, emvp->length); + if (R_AH != EMS_SUCCESS) { + free(buffer); + break; + } + /* Buffer -> source */ + R_AH = move_conv_to_ems((u_long)buffer, src_handle, + emvp->src_seg, emvp->src_offset, emvp->length); + } + free(buffer); + } + debug(D_EMS, " done\n"); + break; + } + + case GET_MAPPABLE_PHYS_ADDR: + { + switch (R_AL) { + case GET_ARRAY: + { + EMSaddrarray *eadp; + int i; + u_short seg; + + eadp = (EMSaddrarray *)get_valid_pointer(R_ES, R_DI, + sizeof(EMSaddrarray) * 4); + if (eadp == NULL) { + R_AH = EMS_SW_MALFUNC; + break; + } + for (i = 0, seg = (ems_frame_addr >> 4); i < 4; i++) { + eadp->segm = seg; + eadp->phys = i; + eadp++; + seg += 1024; + } + R_AH = EMS_SUCCESS; + break; + } + case GET_ARRAY_ENTRIES: + /* There are always 4 positions, 4*16kB = 64kB */ + R_CX = 4; + R_AH = EMS_SUCCESS; + break; + default: + R_AH = EMS_FUNC_NOSUP; + break; + } + break; + } + + /* This is an OS function in the LIM EMS 4.0 standard: It is + * usable only by an OS and its use can be disabled for all other + * programs. I think we do not need to support it. It is not + * implemented and it reports "disabled" to any caller. + */ + case GET_HW_CONFIGURATION: + R_AH = EMS_FUNCTION_DISABLED; + break; + + /* This function is a little different, it was defined with + * LIM EMS 4.0: It is allowed to allocate zero pages and raw + * page size (i.e. page size != 16kB) is supported. We have + * only 16kB pages, so the second difference does not matter. + */ + case ALLOCATE_PAGES: + { + u_short npages; + short handle; + + npages = R_BX; + debug(D_EMS, "EMS: Get handle and allocate %d pages: ", npages); + + /* Enough handles? */ + if ((handle = find_next_free_handle()) < 0) { + debug(D_EMS,"Return error:No handles\n"); + R_AH = EMS_OUT_OF_HANDLES; + break; + } + /* Enough memory for this request ? */ + if (npages > ems_free_pages) { + debug(D_EMS,"Return error:Request too big\n"); + R_AH = EMS_OUT_OF_LOG; + break; + } + if (npages > ems_total_pages) { + debug(D_EMS,"Return error:Request too big\n"); + R_AH = EMS_OUT_OF_PHYS; + break; + } + + /* Allocate the handle */ + allocate_handle(handle, npages); + + /* Allocate the pages */ + allocate_pages_to_handle(handle, npages); + R_DX = handle; + R_AH = EMS_SUCCESS; + debug(D_EMS,"Return success:Handle = %d\n", handle); + break; + } + + /* This is an OS function in the LIM EMS 4.0 standard: It is + * usable only by an OS and its use can be disabled for all other + * programs. I think we do not need to support it. It is not + * implemented and it reports "disabled" to any caller. + */ + case ALTERNATE_MAP_REGISTER: + R_AH = EMS_FUNCTION_DISABLED; + break; + + /* We cannot support that ! */ + case PREPARE_WARMBOOT: + R_AH = EMS_FUNC_NOSUP; + break; + + case OS_FUNCTION_SET: + R_AH = EMS_FUNCTION_DISABLED; + break; + +unknown: + default: + debug(D_ALWAYS, "EMS: Unknown function called: %02x\n", R_AH); + R_AH = EMS_FUNC_NOSUP; + break; + } +} + +/* Initialize the EMS memory: Return 1 on success, 0 on failure */ + +static int +init_mapfile() +{ + char path[256]; + int mfd; + + /* Sanity */ + if (ems_max_size == 0) + return; + strcpy(path, EMS_MAP_PATH); + strcat(path, EMS_MAP_FILE); + + mfd = mkstemp(path); + + if (mfd < 0) { + debug(D_ALWAYS, "Could not create EMS mapfile, "); + goto fail; + } + unlink(path); + mapfile_fd = squirrel_fd(mfd); + + if (lseek(mapfile_fd, (off_t)(ems_max_size - 1), 0) < 0) { + debug(D_ALWAYS, "Could not seek into EMS mapfile, "); + goto fail; + } + if (write(mapfile_fd, "", 1) < 0) { + debug(D_ALWAYS, "Could not write to EMS mapfile, "); + goto fail; + } + /* Unmap the entire page frame */ + if (munmap((caddr_t)ems_frame_addr, 64 * 1024) < 0) { + debug(D_ALWAYS, "Could not unmap EMS page frame, "); + goto fail; + } + /* DOS programs will access the page frame without allocating + * pages first. Microsoft diagnose MSD.EXE does this, for example + * We need to have memory here to avoid segmentation violation + */ + if (mmap((caddr_t)ems_frame_addr, 64 * 1024, + PROT_EXEC | PROT_READ | PROT_WRITE, + MAP_ANON | MAP_FIXED | MAP_INHERIT | MAP_SHARED, + -1, 0) < 0) { + debug(D_ALWAYS, "Could not map EMS page frame, "); + goto fail; + } + bzero((void *)&ems_mapping_context, sizeof(EMS_mapping_context)); + return (1); + +fail: + debug(D_ALWAYS, "EMS disabled\n"); + ems_max_size = 0; + ems_frame_addr = 0; + return (0); +} + +/* Map/Unmap pages into one of four positions in the frame segment */ + +static void +map_page(u_long pagenum, u_char position, short handle, int unmaponly) +{ + caddr_t map_addr; + size_t len; + off_t file_offs; + + if (position > 3) + fatal("EMS: Internal error: Mapping position\n"); + + map_addr = (caddr_t)(ems_frame_addr + (1024 * 16 * (u_long)position)); + len = 1024 * 16; + file_offs = (off_t)(pagenum * 16 * 1024); + + if (ems_mapping_context.pos_mapped[position]) { + if (munmap(map_addr, len) < 0) { + fatal("EMS unmapping error: %s\nCannot recover\n", + strerror(errno)); + } + ems_page[ems_mapping_context.pos_pagenum[position]].status + &= ~EMS_MAPPED; + ems_mapping_context.pos_mapped[position] = 0; + ems_mapping_context.handle[position] = 0; + } + if (unmaponly) { + /* DOS programs will access the page frame without allocating + * pages first. Microsoft diagnose MSD.EXE does this, for example + * We need to have memory here to avoid segmentation violation + */ + if (mmap((caddr_t)ems_frame_addr, 64 * 1024, + PROT_EXEC | PROT_READ | PROT_WRITE, + MAP_ANON | MAP_FIXED | MAP_INHERIT | MAP_SHARED, + -1, 0) < 0) + fatal("Could not map EMS page frame during unmap only\n"); + return; + } + if (mmap(map_addr, len, + PROT_EXEC | PROT_READ | PROT_WRITE, + MAP_FILE | MAP_FIXED | MAP_INHERIT | MAP_SHARED, + mapfile_fd, file_offs) < 0) { + fatal("EMS mapping error: %s\nCannot recover\n", strerror(errno)); + } + ems_mapping_context.pos_mapped[position] = 1; + ems_mapping_context.pos_pagenum[position] = pagenum; + ems_mapping_context.handle[position] = handle; + ems_page[pagenum].status |= EMS_MAPPED; +} + +/* Get a pointer from VM86 app, check it and return it. This returns NULL + * if the pointer is not valid. We can check only for very limited + * criteria: The pointer and the area defined by size may not point to + * memory over 1MB and it may not may to addresses under 1kB, because there + * is the VM86 interrupt table. + */ +static void +*get_valid_pointer(u_short seg, u_short offs, u_long size) +{ + u_long addr; + addr = N_GETPTR(seg, offs); + /* Check bounds */ + if ((addr + size) >= (1024 * 1024) || addr < 1024) + return NULL; + else + return (void *)addr; +} + +/* Malloc a new handle */ +static EMS_handle +*get_new_handle(long npages) +{ + EMS_handle *ehp; + size_t dynsize = sizeof(EMS_handle) + sizeof(short) * npages; + + if ((ehp = calloc(1, dynsize)) == NULL) + fatal("Cannot malloc EMS handle, cannot continue\n"); + return ehp; +} + +/* Allocate a mapping context to a handle */ +static void +context_to_handle(short handle) +{ + EMS_mapping_context *emc; + + if (ems_handle[handle] == NULL) + fatal("EMS context_to_handle called with invalid handle\n"); + if ((emc = calloc(1, sizeof(EMS_mapping_context))) == NULL) + fatal("EMS Cannot malloc mapping context, cannot continue\n"); + ems_handle[handle]->mcontext = emc; + memmove((void *)emc, (void *)&ems_mapping_context, + sizeof(EMS_mapping_context)); +} + +/* Find the next free handle, returns -1 if there are no more handles */ +static long +find_next_free_handle() +{ + int i; + + if (ems_alloc_handles >= 255) + return (-1); + /* handle 0 is OS handle */ + for (i = 1; i < EMS_NUM_HANDLES; i++) { + if (ems_handle[i] == NULL) + return (i); + } + fatal("EMS handle count garbled, should not happen\n"); +} + +/* Look for a named handle, returns 0 if not found, else handle */ +static short +lookup_handle(Hname *hp) +{ + int i; + + for (i = 1; i < EMS_NUM_HANDLES; i++) { + if (ems_handle[i] != NULL) { + if (hp->ul_hn[0] == ems_handle[i]->hname.ul_hn[0] && + hp->ul_hn[1] == ems_handle[i]->hname.ul_hn[1]) + return (i); + } + } + return (0); +} + +/* Malloc a new handle struct and put into array at index handle */ +static void +allocate_handle(short handle, long npages) +{ + if (ems_handle[handle] != NULL) + fatal("EMS allocate_handle, handle was not free\n"); + ems_handle[handle] = get_new_handle(npages); + ems_alloc_handles++; +} + +/* Free a handle, return its memory. Call this *after* freeing the + * allocated pages ! + */ +static void +free_handle(short handle) +{ + if (ems_handle[handle] == NULL) + fatal("EMS free_handle, handle was free\n"); + if (ems_handle[handle]->mcontext != NULL) + free((void *)ems_handle[handle]->mcontext); + free((void *)ems_handle[handle]); + ems_handle[handle] = NULL; + ems_alloc_handles--; +} + + +/* Allocates npages to handle. Call this routine only after you have + * ensured there are enough free pages *and* the new handle is in place + * in the handle array ! + */ +static void +allocate_pages_to_handle(u_short handle, long npages) +{ + int syspagenum; + int pages_to_alloc = npages; + int allocpagenum = 0; + + /* sanity */ + if (handle > 255 || ems_handle[handle] == NULL) + fatal("EMS allocate_pages_to_handle called with invalid handle\n"); + + ems_handle[handle]->npages = npages; + for (syspagenum = 0; syspagenum < ems_total_pages; syspagenum++) { + if (ems_page[syspagenum].status == EMS_FREE) { + ems_page[syspagenum].handle = handle; + ems_page[syspagenum].status = EMS_ALLOCED; + ems_handle[handle]->pagenum[allocpagenum] = syspagenum; + allocpagenum++; + pages_to_alloc--; + if (pages_to_alloc == 0) + break; + } + } + if (pages_to_alloc > 0) + fatal("EMS allocate_pages_to_handle found not enough free pages\n"); + ems_alloc_pages += npages; + ems_free_pages -= npages; +} + +/* Reallocates npages to handle. Call this routine only after you have + * ensured there are enough free pages *and* the new handle is in place + * in the handle array ! + */ +static void +reallocate_pages_to_handle(u_short handle, long npages) +{ + int syspagenum; + int pages_to_alloc; + int allocpagenum; + long delta; + size_t dynsize; + EMS_handle *emp; + + /* sanity */ + if (handle > 255 || ems_handle[handle] == NULL) + fatal("EMS allocate_pages_to_handle called with invalid handle\n"); + + delta = npages - ems_handle[handle]->npages; + if (delta > 0) { + /* Grow array size and allocation */ + + emp = ems_handle[handle]; + dynsize = sizeof(EMS_handle) + sizeof(short) * npages; + + /* First step: Make room in the handle pagenum array */ + if ((emp = (EMS_handle *)realloc((void *)emp, dynsize)) == NULL) + fatal("Cannot malloc EMS handle, cannot continue\n"); + ems_handle[handle] = emp; + + /* Second step: Add pages to the handle */ + pages_to_alloc = delta; + allocpagenum = ems_handle[handle]->npages; + ems_handle[handle]->npages = npages; + for (syspagenum = 0; syspagenum < ems_total_pages; syspagenum++) { + if (ems_page[syspagenum].status == EMS_FREE) { + ems_page[syspagenum].handle = handle; + ems_page[syspagenum].status = EMS_ALLOCED; + ems_handle[handle]->pagenum[allocpagenum] = syspagenum; + allocpagenum++; + pages_to_alloc--; + if (pages_to_alloc == 0) + break; + } + } + if (pages_to_alloc > 0) + fatal("EMS allocate_pages_to_handle found not enough free pages\n"); + + } else { + /* Shrink array size and allocation */ + + /* First step: Deallocate all pages from new size to old size */ + for (allocpagenum = npages; + allocpagenum < ems_handle[handle]->npages; + allocpagenum++) { + syspagenum = ems_handle[handle]->pagenum[allocpagenum]; + + /* sanity */ + if (syspagenum > ems_total_pages) + fatal("EMS free_pages_of_handle found invalid page number\n"); + if (!(ems_page[syspagenum].status & EMS_ALLOCED)) + fatal("EMS free_pages_of_handle tried to free page already free\n"); + ems_page[syspagenum].handle = 0; + ems_page[syspagenum].status = EMS_FREE; + } + + /* Second step: Shrink the dynamic array of the handle */ + dynsize = sizeof(EMS_handle) + sizeof(short) * npages; + emp = ems_handle[handle]; + if ((emp = (EMS_handle *)realloc((void *)emp, dynsize)) == NULL) + fatal("Cannot realloc EMS handle, cannot continue\n"); + ems_handle[handle] = emp; + ems_handle[handle]->npages = npages; + } + ems_alloc_pages += delta; + ems_free_pages -= delta; +} + +/* Free all pages belonging to a handle, handle must be valid */ +static void +free_pages_of_handle(short handle) +{ + int allocpagenum; + int syspagenum; + int npages; + + /* sanity */ + + if (handle > 255 || ems_handle[handle] == NULL) + fatal("EMS free_pages_of_handle called with invalid handle\n"); + + if ((npages = ems_handle[handle]->npages) == 0) + return; + + for (allocpagenum = 0; allocpagenum < npages; allocpagenum++) { + syspagenum = ems_handle[handle]->pagenum[allocpagenum]; + /* sanity */ + if (syspagenum > ems_total_pages) + fatal("EMS free_pages_of_handle found invalid page number\n"); + if (!(ems_page[syspagenum].status & EMS_ALLOCED)) + fatal("EMS free_pages_of_handle tried to free page already free\n"); + ems_page[syspagenum].handle = 0; + ems_page[syspagenum].status = EMS_FREE; + } + ems_alloc_pages -= npages; + ems_free_pages += npages; +} + +/* Restore a saved mapping context, overwrites current mapping context */ +static void +restore_context(EMS_mapping_context *emc) +{ + int i; + + for (i = 0; i < 4; i++) { + ems_mapping_context.handle[i] = emc->handle[i]; + if (emc->pos_mapped[i] != 0 && + ems_mapping_context.pos_pagenum[i] != emc->pos_pagenum[i]) { + map_page(emc->pos_pagenum[i], (u_char) i, emc->handle[i], 0); + } else { + ems_mapping_context.pos_mapped[i] = 0; + } + } +} + +/* Prepare a special context save block for DOS and save it to + * VM86 memory + */ +static void +save_context_to_dos(EMScontext *emp) +{ + int i, end; + EMScontext context; + u_short *sp; + u_short sum; + + context.ems_saved_context = ems_mapping_context; + context.magic = EMS_SAVEMAGIC; + context.checksum = 0; + sp = (u_short *)&context; + end = sizeof(EMScontext) / sizeof(short); + /* Generate checksum */ + for (i = 0, sum = 0; i < end; i++) { + sum += *sp++; + sum &= 0xffff; + } + context.checksum = 0x10000L - sum; + /* Save it to VM86 memory */ + *emp = context; +} + +/* Check a context returned from VM86 app for validity, return 0, if + * not valid, else return 1 + */ +static int +check_saved_context(EMScontext *emp) +{ + int i, end; + u_short *sp; + u_short sum; + + if (emp->magic != EMS_SAVEMAGIC) + return 0; + + sp = (u_short *)emp; + end = sizeof(EMScontext) / sizeof(short); + /* Generate checksum */ + for (i = 0, sum = 0; i < end; i++) { + sum += *sp++; + sum &= 0xffff; + } + if (sum != 0) + return 0; + else + return 1; +} + +/* Helper routine for the move routines below: Check if length bytes + * can be moved from/to handle pages (i.e are there enough pages) + */ +static int +check_alloc_pages(u_short handle, u_short firstpage, u_short offset, + u_long length) +{ + u_long nbytes; + + if (firstpage > ems_handle[handle]->npages) + return (0); + nbytes = (ems_handle[handle]->npages - firstpage) * EMS_PAGESIZE - offset; + return (ems_handle[handle]->npages >= nbytes); +} + +/* Copy a block of memory up to the next 16kB boundary in the source + * to the destination in upward direction (i.e. with ascending addresses) + * XXX Could be an inline function. + */ +static void +copy_block_up(struct copydesc *cdp) +{ + size_t size; + void *srcp; + void *dstp; + + /* If source or both memory types are EMS, source determines the + * block lenght, else destination determines the block lenght + */ + if (cdp->copytype & SRC_EMS) + size = EMS_PAGESIZE - cdp->EMS_OFFS(src_addr); + else + size = EMS_PAGESIZE - cdp->EMS_OFFS(dst_addr); + + if (size > cdp->rest_len) + size = cdp->rest_len; + + /* If src is EMS memory, it is mapped into position 0 */ + if (cdp->copytype & SRC_EMS) + srcp = (void *)(ems_frame_addr + cdp->EMS_OFFS(src_addr)); + else + srcp = (void *)(cdp->EMS_PTR(src_addr)); + + /* If dest is EMS memory, it is mapped into position 1,2 */ + if (cdp->copytype & DST_EMS) + dstp = (void *)(ems_frame_addr + EMS_PAGESIZE + + cdp->EMS_OFFS(dst_addr)); + else + dstp = (void *)(cdp->EMS_PTR(dst_addr)); + + /* Move this block */ + memmove(dstp, srcp, size); + + /* Update the copy descriptor: This updates the address of both + * conventional and EMS memory + */ + cdp->EMS_PTR(src_addr) += size; + cdp->EMS_PTR(dst_addr) += size; + + cdp->rest_len -= size; +} + + +/* Move EMS memory starting with handle page src_seg and offset src_offset + * to conventional memory dst_addr for length bytes + * dst_addr is checked, handle is valid + */ +static u_long +move_ems_to_conv(short src_handle, u_short src_seg, + u_short src_offset, u_long dst_addr, u_long length) +{ + EMS_mapping_context ems_saved_context; + EMS_handle *ehp; + int pageindx = src_seg; + struct copydesc cd; + + if (check_alloc_pages(src_handle, src_seg, src_offset, length) == 0) + return EMS_MOVE_OVERFLOW; + + ehp = ems_handle[src_handle]; + + /* Prepare the move: Save the mapping context */ + ems_saved_context = ems_mapping_context; + + /* Setup the copy descriptor struct */ + + cd.copytype = SRC_EMS; + cd.EMS_PAGE(src_addr) = ehp->pagenum[pageindx]; + cd.EMS_OFFS(src_addr) = src_offset; + cd.EMS_PTR(dst_addr) = dst_addr; + cd.rest_len = length; + + do { + /* Map for the first block copy, source is mapped to position zero */ + map_page(cd.EMS_PAGE(src_addr), 0, src_handle, 0); + copy_block_up(&cd); + } while(cd.rest_len > 0); + + /* Restore the original mapping */ + restore_context(&ems_saved_context); + return EMS_SUCCESS; +} + +/* Move conventional memory starting with src_addr + * to EMS memory starting with handle page src_seg and offset src_offset + * for length bytes + * dst_addr is checked, handle is valid + */ +static u_long +move_conv_to_ems(u_long src_addr, u_short dst_handle, u_short dst_seg, + u_short dst_offset, u_long length) +{ + EMS_mapping_context ems_saved_context; + EMS_handle *ehp; + int pageindx = dst_seg; + struct copydesc cd; + + if (check_alloc_pages(dst_handle, dst_seg, dst_offset, length) == 0) + return EMS_MOVE_OVERFLOW; + + ehp = ems_handle[dst_handle]; + + /* Prepare the move: Save the mapping context */ + ems_saved_context = ems_mapping_context; + + /* Setup the copy descriptor struct */ + + cd.copytype = DST_EMS; + cd.EMS_PAGE(dst_addr) = ehp->pagenum[pageindx]; + cd.EMS_OFFS(dst_addr) = dst_offset; + cd.EMS_PTR(src_addr) = src_addr; + cd.rest_len = length; + + do { + map_page(cd.EMS_PAGE(dst_addr), 1, dst_handle, 0); + copy_block_up(&cd); + } while(cd.rest_len > 0); + + /* Restore the original mapping */ + restore_context(&ems_saved_context); + return EMS_SUCCESS; +} + +static u_long +move_ems_to_ems(u_short src_handle, u_short src_seg, u_short src_offset, + u_short dst_handle, u_short dst_seg, u_short dst_offset, + u_long length) +{ + EMS_mapping_context ems_saved_context; + EMS_handle *src_hp, *dst_hp; + struct copydesc cd; + + if (check_alloc_pages(src_handle, src_seg, src_offset, length) == 0) + return EMS_MOVE_OVERFLOW; + if (check_alloc_pages(dst_handle, dst_seg, dst_offset, length) == 0) + return EMS_MOVE_OVERFLOW; + + src_hp = ems_handle[src_handle]; + dst_hp = ems_handle[dst_handle]; + + /* Prepare the move: Save the mapping context */ + ems_saved_context = ems_mapping_context; + + /* Setup the copy descriptor struct */ + + cd.copytype = SRC_EMS | DST_EMS; + cd.EMS_PAGE(src_addr) = src_hp->pagenum[src_seg]; + cd.EMS_OFFS(src_addr) = src_offset; + cd.EMS_PAGE(dst_addr) = dst_hp->pagenum[dst_seg]; + cd.EMS_OFFS(dst_addr) = dst_offset; + cd.rest_len = length; + + /* Copy */ + do { + map_page(cd.EMS_PAGE(src_addr), 0, src_handle, 0); + map_page(cd.EMS_PAGE(dst_addr), 1, dst_handle, 0); + /* If there are more pages, map the next destination page to + * position 2. This removes a compare between source and dest + * offsets. + */ + if (cd.EMS_PAGE(dst_addr) < dst_hp->npages) + map_page((cd.EMS_PAGE(dst_addr) + 1), 2, dst_handle, 0); + copy_block_up(&cd); + } while(cd.rest_len > 0); + + /* Restore the original mapping */ + restore_context(&ems_saved_context); + return EMS_SUCCESS; +} diff --git a/usr.bin/doscmd/ems.h b/usr.bin/doscmd/ems.h new file mode 100644 index 0000000..866a551 --- /dev/null +++ b/usr.bin/doscmd/ems.h @@ -0,0 +1,313 @@ +/*- + * Copyright (c) 1997 Helmut Wirth <hfwirth@ping.at> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice immediately at the beginning of the file, witout modification, + * this list of conditions, and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $Id$ + */ + +#ifndef EMS_H +#define EMS_H + +/* Header for ems.c, the EMS emulation */ + +/* Global definitions, some of them will be configurable in the future */ + +#define EMS_NUM_HANDLES 256 /* Includes OS handle 0 */ +#define EMS_MAXSIZE 1024 /* In kbytes */ +#define EMS_MAX_PHYS 4 /* Frame is 64kB */ +#define EMS_FRAME_ADDR 0xe0000 +#define EMS_VERSION 0x40 /* Version 4.0 */ +#define EMS_PAGESIZE (16 *1024) /* page size in bytes */ +#define EMS_SAVEMAGIC 0xAFFE /* magic number */ + +/* These are the LIM EMS 3.0 calls */ +#define GET_MANAGER_STATUS 0x40 +#define GET_PAGE_FRAME_SEGMENT 0x41 +#define GET_PAGE_COUNTS 0x42 +#define GET_HANDLE_AND_ALLOCATE 0x43 +#define MAP_UNMAP 0x44 +#define DEALLOCATE_HANDLE 0x45 +#define GET_EMM_VERSION 0x46 +#define SAVE_PAGE_MAP 0x47 +#define RESTORE_PAGE_MAP 0x48 +#define RESERVED_1 0x49 +#define RESERVED_2 0x4a +#define GET_HANDLE_COUNT 0x4b +#define GET_PAGES_OWNED 0x4c +#define GET_PAGES_FOR_ALL 0x4d + +/* LIM EMS 4.0 calls */ +/* Global subfunctions for the LIM EMS 4.0 calls */ +#define GET 0x0 +#define SET 0x1 +/* Modes for Map/Unmap and AlterandCall/AlterAndJump */ +#define PHYS_ADDR 0x0 +#define SEG_ADDR 0x0 + +/* Page map functions */ +#define PAGE_MAP 0x4e +#define PAGE_MAP_PARTIAL 0x4f +/* Page map subfunctions */ +#define GET_SET 0x2 +#define GET_SIZE 0x3 + +#define MAP_UNMAP_MULTI_HANDLE 0x50 + +#define REALLOC_PAGES 0x51 + +#define HANDLE_ATTRIBUTES 0x52 +/* Subfunctions */ +#define HANDLE_CAPABILITY 0x2 + +#define HANDLE_NAME 0x53 + +#define HANDLE_DIRECTORY 0x54 +#define HANDLE_SEARCH 0x1 +#define GET_TOTAL_HANDLES 0x2 + +#define ALTER_PAGEMAP_JUMP 0x55 +#define ALTER_PAGEMAP_CALL 0x56 +/* Subfunction for call */ +#define GET_STACK_SIZE 0x2 + +#define MOVE_MEMORY_REGION 0x57 +/* Subfunctions */ +#define MOVE 0x0 +#define EXCHANGE 0x1 + +#define GET_MAPPABLE_PHYS_ADDR 0x58 +/* Subfunctions */ +#define GET_ARRAY 0x0 +#define GET_ARRAY_ENTRIES 0x1 + +#define GET_HW_CONFIGURATION 0x59 +/* Subfunctions */ +#define GET_HW_ARRAY 0x0 +#define GET_RAW_PAGE_COUNT 0x1 + +#define ALLOCATE_PAGES 0x5a +/* Subfunctions */ +#define ALLOC_STANDARD 0x0 +#define ALLOC_RAW 0x1 + +#define ALTERNATE_MAP_REGISTER 0x5b +/* Subfunctions */ +#define GET_SAVE_ARRAY_SIZE 0x2 +#define ALLOCATE_REGISTER_SET 0x3 +#define DEALLOCATE_REGISTER_SET 0x4 +#define ALLOCATE_DMA 0x5 +#define ENABLE_DMA 0x6 +#define DISABLE_DMA 0x7 +#define DEALLOCATE_DMA 0x8 + +#define PREPARE_WARMBOOT 0x5c + +#define OS_FUNCTION_SET 0x5d +/* Subfunctions */ +#define ENABLE 0x0 +#define DISABLE 0x1 +#define RETURN_KEY 0x2 + +/* End of call definitions */ + +/* EMS errors */ + +#define EMS_SUCCESS 0x0 +#define EMS_SW_MALFUNC 0x80 +#define EMS_HW_MALFUNC 0x81 +#define EMS_INV_HANDLE 0x83 +#define EMS_FUNC_NOSUP 0x84 +#define EMS_OUT_OF_HANDLES 0x85 +#define EMS_SAVED_MAP 0x86 +#define EMS_OUT_OF_PHYS 0x87 +#define EMS_OUT_OF_LOG 0x88 +#define EMS_ZERO_PAGES 0x89 +#define EMS_LOGPAGE_TOOBIG 0x8a +#define EMS_ILL_PHYS 0x8b +#define EMS_NO_ROOM_TO_SAVE 0x8c +#define EMS_ALREADY_SAVED 0x8d +#define EMS_NO_SAVED_CONTEXT 0x8e +#define EMS_INVALID_SUB 0x8f +#define EMS_INVALID_ATTR 0x90 +#define EMS_FEAT_NOSUP 0x91 +#define EMS_MOVE_OVERLAP1 0x92 +#define EMS_MOVE_OVERFLOW 0x93 +#define EMS_PAGEOFFSET 0x95 +#define EMS_MOVE_OVERLAP2 0x97 +#define EMS_HNAME_NOT_FOUND 0xa0 +#define EMS_NAME_EXISTS 0xa1 +#define EMS_SAVED_CONTEXT_BAD 0xa3 +#define EMS_FUNCTION_DISABLED 0xa4 + +/* + * EMS handles: The handle contains at its end an array of pointers to + * its allocated pages. The array is of size npages. Handle structs are + * malloced at runtime. + * Page numbering: Every page is 16kB, always. The pages are numbered + * from 0 to highest page, depending on total EMS memory. Every handle + * has pages allocated and this pages too are numbered from 0 to highest + * page allocated. This are *not* the same numbers, because there may be + * holes in the allocation. + * Page numbers are unsigned short, which will give us 65536 * 16 kB (1GB) + * pages to handle at maximum. This should be enough for the next years. + */ + +typedef struct { + short handle[4]; /* Handle for each mapping */ + u_char pos_mapped[4]; /* Boolean value, 1 if something is mapped */ + u_char pos_pagenum[4]; /* Page number currently mapped into position */ +} EMS_mapping_context; + + +/* This union is for copying operations of the handle name only */ +typedef union { + u_char uc_hn[8]; + u_long ul_hn[2]; +} Hname; + +typedef struct { + Hname hname; + u_long npages; + /* The mapping context for save/restore page map */ + EMS_mapping_context *mcontext; + /* The pagenum here is the number in the system page array. The + * logical page number connected with this handle is the index into + * this array. + */ + u_short pagenum[0]; + /* Will grow here, depending on allocation */ +} EMS_handle; + +/* + * The connection between every page in the system and the handles is + * maintained by an array of these structs. The array is indexed by the + * page numbers. + */ + +typedef struct { + short handle; /* The handle this page belongs to */ +#define EMS_FREE 0 +#define EMS_ALLOCED 1 +#define EMS_MAPPED 2 + u_short status; /* room for misc information */ +} EMS_page; + +/* + * The combined pointer into EMS memory: offs is the offset into an EMS + * page, page is the page index inside the region allocated to a handle. + * This depends on EMS_PAGESIZE. + * This is used for copy and move operations. + */ + +typedef struct { + u_long offs:14; + u_long page:18; +} EMS_combi; + +typedef union { + u_long ua_addr; /* Conventional address pointer */ + EMS_combi ua_emsaddr; /* EMS address pointer */ +} EMS_addr; + +#define EMS_OFFS(u) u.ua_emsaddr.offs +#define EMS_PAGE(u) u.ua_emsaddr.page +#define EMS_PTR(u) u.ua_addr + +/* + * EMS info structure, only used to pass information to and from + * DOS + */ + +typedef struct { + u_short handle __attribute__ ((packed)); /* handle */ + u_short npages __attribute__ ((packed)); /* pages allocated */ +} EMShandlepage; + +/* + * EMS map/unmap multiple, only used to pass information to and from + * DOS + */ + +typedef struct { + u_short log __attribute__ ((packed)); /* logical page number */ + u_short phys __attribute__ ((packed)); /* physical page (position) or + segment address inside frame */ +} EMSmapunmap; + +/* + * EMS handle directory, only used to pass information to and from + * DOS + */ + +typedef struct { + u_short log __attribute__ ((packed)); /* logical page number */ + Hname name __attribute__ ((packed)); /* Handle name */ + +} EMShandledir; + +/* + * Structure for get/set page map: This structure is used to save and + * restore the page map from DOS memory. A program can get the mapping + * context and later set (restore) it. To avoid errors we add a magic + * number and a checksum. + */ + +typedef struct { + u_short magic; /* Magic number */ + u_short checksum; /* Checksum over entire structure */ + EMS_mapping_context ems_saved_context; +} EMScontext; + +/* + * EMS physical address array, only used to pass information to and from + * DOS + */ + +typedef struct { + u_short segm __attribute__ ((packed)); /* segment address inside frame */ + u_short phys __attribute__ ((packed)); /* physical page (position) */ +} EMSaddrarray; + +/* + * EMS move memory call structure, only used to pass information to and from + * DOS + */ + +typedef struct { + u_long length __attribute__ ((packed)); /* length of region */ +#define EMS_MOVE_CONV 0 +#define EMS_MOVE_EMS 1 + u_char src_type __attribute__ ((packed)); /* source type (0,1) */ + u_short src_handle __attribute__ ((packed)); /* source handle */ + u_short src_offset __attribute__ ((packed)); /* source offset */ + u_short src_seg __attribute__ ((packed)); /* source type */ + u_char dst_type __attribute__ ((packed)); /* destination type (0,1) */ + u_short dst_handle __attribute__ ((packed)); /* destination handle */ + u_short dst_offset __attribute__ ((packed)); /* destination offset */ + u_short dst_seg __attribute__ ((packed)); /* destination type */ +} EMSmovemem; + +#endif /* EMS_H */ diff --git a/usr.bin/doscmd/emsdriv.S b/usr.bin/doscmd/emsdriv.S new file mode 100644 index 0000000..ffa2c98 --- /dev/null +++ b/usr.bin/doscmd/emsdriv.S @@ -0,0 +1,261 @@ +! Copyright (c) 1997 Helmut Wirth <hfwirth@ping.at> +! All rights reserved. +! +! Redistribution and use in source and binary forms, with or without +! modification, are permitted provided that the following conditions +! are met: +! 1. Redistributions of source code must retain the above copyright +! notice immediately at the beginning of the file, witout modification, +! this list of conditions, and the following disclaimer. +! 2. Redistributions in binary form must reproduce the above copyright +! notice, this list of conditions and the following disclaimer in the +! documentation and/or other materials provided with the distribution. +! 3. The name of the author may not be used to endorse or promote products +! derived from this software without specific prior written permission. +! +! THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +! IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +! OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +! IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +! INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +! NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +! DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +! THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +! (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +! THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +! +! $Id$ + + +! +! This driver is needed for Expanded Memory emulation (EMS). A driver +! is needed here, because EMS drivers are installed as DOS devices +! with the name "EMMXXXX0" and programs look for such a device while +! checking the existence of EMS. +! The driver is installed by CONFIG.SYS, it has no options. It uses +! the emulator callback interrupt 0xff to initialize the EMS subsystem. +! If EMS is not configured or if there is an error inside the emulator +! the driver reports failure and does not install itself. +! If all works, the driver changes the interrupt vector for int 0x67 to +! point at itself. The resident part of the drivers simlpy routes calls +! to int 0x67 to the correct subfunction of the emulator callback interrupt. + +use16 + +.text +.bss +.data +.align 0 + + .org 0 + +NumFunc = 15 + +! Emulator interrupt entry +EmulatorINT = 0xFF + +! Emulator EMS callback function +EMU_EMS = 0x2 +EMU_EMS_CTL = 0 +EMU_EMS_CALL = 1 + +! DOS print message +DOSMesg = 0x9 + +cr = 0xd +lf = 0xa +eom = '$' ! DOS end of string + +EMSintnum = 0x67 +Intoffset = (EMSintnum * 4) + +.globl _main +_main: + +driverhead: + .long -1 ! link to next device driver + .word 0xC000 ! attribute word for driver + .word Strategy ! ptr to strategy routine + .word Interrupt ! ptr to interrupt service routine + .ascii "EMMXXXX0" ! logical device name + +reqhead: + .long 0 + +vectordone: + .word 0 ! != 0 , if vector installed + +FuncTable: + .word InitDrv ! initialize driver + .word Noop ! media Check + .word Noop ! build BPB + .word Noop ! Ioctl + .word Noop ! read + .word Noop ! non destructive read + .word Noop ! input status + .word Noop ! flush input + .word Noop ! write + .word Noop ! write with verify + .word Noop ! output status + .word Noop ! flush output + .word Noop ! ioctl output + .word Noop ! open device + .word Noop ! close device + .word Noop ! removeable media check + +Strategy: + seg cs + mov [reqhead], bx + seg cs + mov [reqhead+2],es + retf + +Interrupt: + push ax + push bx + push cx + push dx + push ds + push es + push di + push si + push bp + + push cs + pop ds + + les di,[reqhead] ! load pointer to request header + + seg es + movb bl,[di+2] + xorb bh,bh + cmp bx, #NumFunc + jle dointr + call errorhandler + jmp intrend + +dointr: + shl bx,#1 + call [bx+FuncTable] + les di,[reqhead] ! load pointer to request header + +intrend: + or ax,#0x100 ! done bit + seg es + mov [di+3],ax + + pop bp + pop si + pop di + pop es + pop ds + pop dx + pop cx + pop bx + pop ax + retf + +errorhandler: + mov ax,#0x8003 ! report error to caller + ret + + +! This is done for all functions except init. It supports the different +! methods for an EMS installation check described in the LIM EMS 4.0 spec +Noop: + call installvector + xor ax,ax + ret + +! The interrupt vector installed for int 0x67 points to this routine +intr67: + push ax ! Save original AX + mov ah, #EMU_EMS ! Emuint function + mov al, #EMU_EMS_CALL ! Emuint subfunction + int EmulatorINT ! Call emulator for EMS + iret + +installvector: + push cs + pop ds ! load DS to use local data + mov ax,[vectordone] + cmp ax,#0 + jne isinstalled ! already installed + + push di ! save request header pointer + push es + + mov ax, #0 ! write the new interrupt vector + mov es, ax + mov di, #Intoffset + seg es + mov [di], #intr67 + seg es + mov [di+2], cs + + pop es + pop di + + mov ax,#1 + mov [vectordone],ax + +isinstalled: + ret + +InitDrv: + push cs + pop ds + push ax + mov ah, #EMU_EMS ! Emuint function + mov al, #EMU_EMS_CTL ! Emuint subfunction + int EmulatorINT + cmp ax,#0 ! check if successful + je Fail + + call installvector + + push cs + pop ds + + mov ah, #DOSMesg + mov dx, #Success + int 0x21 + + seg es + mov [di+14], #InitDrv ! address break for driver + seg es + mov [di+16], cs + + xor ax,ax + ret + +Fail: + push cs + pop ds + mov ah, #DOSMesg + mov dx, #Failure + int 0x21 + + seg es + movb [di+13],#0 + seg es + mov [di+20],cs + seg es + mov [di+14],#0 ! address break == 0, no driver + seg es + mov [di+16],cs + ret + + +Success: + .ascii "Doscmd EMS 4.0 driver installed" + .byte cr,lf,eom + +Failure: + .byte cr,lf,lf + .ascii "EMS emulation is disabled" + .byte cr,lf + .ascii "Driver not installed" + .byte cr,lf,lf,eom + + end diff --git a/usr.bin/doscmd/emsdriv.sys.uu b/usr.bin/doscmd/emsdriv.sys.uu new file mode 100644 index 0000000..fae517e --- /dev/null +++ b/usr.bin/doscmd/emsdriv.sys.uu @@ -0,0 +1,11 @@ +begin 644 emsdriv.sys +M_____P#`.`!#`$5-35A86%@P````````M`"``(``@`"``(``@`"``(``@`"` +M`(``@`"``(``@``NB1X2`"Z,!A0`RU!345(>!E=650X?Q#X2`":*70(P_X/[ +M#WX%Z!P`ZPG1X_]7&,0^$@`-``$FB44#75Y?!Q]:65M8R[@#@,/H"P`QP,-0 +MM`*P`<W_SPX?H18`/0``=1M7!K@``([`OYP!)L<%A@`FC$T"!U^X`0"C%@## +M#A]0M`*P`,W_/0``=!GHR?\.'[0)NO@`S2$FQT4.M``FC$T0,<###A^T";H: +M`<TA)L9%#0`FC$T4)L=%#@``)HQ-$,-$;W-C;60@14U3(#0N,"!D<FEV97(@ +M:6YS=&%L;&5D#0HD#0H*14U3(&5M=6QA=&EO;B!I<R!D:7-A8FQE9`T*1')I +5=F5R(&YO="!I;G-T86QL960-"@HD +` +end diff --git a/usr.bin/doscmd/emuint.c b/usr.bin/doscmd/emuint.c new file mode 100644 index 0000000..1b2bfdd7 --- /dev/null +++ b/usr.bin/doscmd/emuint.c @@ -0,0 +1,111 @@ +/*- + * Copyright (c) 1997 Helmut Wirth <hfwirth@ping.at> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice immediately at the beginning of the file, witout modification, + * this list of conditions, and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $Id$ + */ + +#include <sys/param.h> +#include <ctype.h> +#include "doscmd.h" +#include "emuint.h" + +/* The central entry point for the emulator interrupt. This is used by + * different special programs to call the emulator from VM86 space. + * Look at emuint.h for definitions and a list of the currently defined + * subfunctions. + * To call emuint from VM86 space do: + * push ax Save original ax value (*must be done* !) + * mov ah, funcnum Emuint function number to ah + * mov al, subfunc Subfunction number, optional, depening on func + * int 0xff + * .. + * .. + * Emuint saves the function and subfunction numbers internally, then + * pops ax off the stack and calls the function handler with the original + * value in ax. + */ +void +emuint(regcontext_t *REGS) +{ + u_short func, subfunc; + + /* Remove function number from stack */ + func = R_AH; + subfunc = R_AL; + + R_AX = N_POP(REGS); + + /* Call the function handler, subfunction is ignored, if unused */ + switch (func) + { + /* The redirector call */ + case EMU_REDIR: + intff(REGS); + break; + + /* EMS call, used by emsdriv.sys */ + case EMU_EMS: + { + switch (subfunc) + { + case EMU_EMS_CTL: + R_AX = (u_short)ems_init(); + break; + + case EMU_EMS_CALL: + ems_entry(REGS); + break; + + default: + debug(D_ALWAYS, "Undefined subfunction for EMS call\n"); + break; + } + break; + } + + default: + debug(D_ALWAYS, "Emulator interrupt called with undefined function %02x\n", func); + + /* + * XXX + * temporary backwards compatability with instbsdi.exe + * remove after a while. + */ + fprintf(stderr, "***\n*** WARNING - unknown emuint function\n"); + fprintf(stderr, "*** Continuing; assuming instbsdi redirector.\n"); + fprintf(stderr, "*** Please install the new redirector"); + fprintf(stderr, " `redir.com' as soon as possible.\n"); + fprintf(stderr, "*** This compatability hack is not permanent.\n"); + fprintf(stderr, "***\n"); + N_PUSH(R_AX, REGS); + R_BX = R_ES; + R_DX = R_DI; + R_DI = R_DS; + intff(REGS); + break; + } +} diff --git a/usr.bin/doscmd/emuint.h b/usr.bin/doscmd/emuint.h new file mode 100644 index 0000000..d90b60e --- /dev/null +++ b/usr.bin/doscmd/emuint.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 1997 Helmut Wirth <hfwirth@ping.at> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice immediately at the beginning of the file, witout modification, + * this list of conditions, and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $Id$ + */ + + +/* + * The emulator helper interrupt: + * + * Interrupt 0xFF is used by some emulator functions. It is a portal into + * the emulator and cannot be used by ordinary DOS applications directly + * The interrupt 0xFF is called by helper functions under DOS (such as + * the redirector interfcae and the EMS emulation). + * There are functions and subfunctions defined. (See emuint.c for details) + */ + +/* The redirector interface (formerly instbsdi.exe) */ +#define EMU_REDIR 0x1 /* Function for redirector interface */ +/* No subfunctions defined */ + +/* Expanded memory (EMS) driver callback */ +#define EMU_EMS 0x2 /* Function for EMS driver control */ +/* subfunctions for EMS */ +#define EMU_EMS_CTL 0x0 /* Control function, used during init */ +#define EMU_EMS_CALL 0x1 /* Callback, calls are routed via this */ diff --git a/usr.bin/doscmd/instbsdi.c b/usr.bin/doscmd/instbsdi.c deleted file mode 100644 index bfad58b..0000000 --- a/usr.bin/doscmd/instbsdi.c +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) 1992, 1993, 1996 - * Berkeley Software Design, Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Berkeley Software - * Design, Inc. - * - * THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL Berkeley Software Design, Inc. BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * BSDI instbsdi.c,v 2.2 1996/04/08 19:32:39 bostic Exp - */ - -#include <dos.h> -#include <string.h> - -main(int ac, char **av) -{ - union REGS in, out, tmp; - struct SREGS seg, stmp; - - memset(&out, 0, sizeof(out)); - out.h.ah = 0x52; - int86x(0x21, &out, &tmp, &stmp); - - seg.es = stmp.es; - in.x.di = tmp.x.bx; - - out.x.ax = 0x5D06; - int86x(0x21, &out, &tmp, &stmp); - - seg.ds = stmp.ds; - in.x.si = tmp.x.si; - - int86x(0xff, &in, &out, &seg); -} diff --git a/usr.bin/doscmd/instbsdi.exe.uu b/usr.bin/doscmd/instbsdi.exe.uu deleted file mode 100644 index e775c06..0000000 --- a/usr.bin/doscmd/instbsdi.exe.uu +++ /dev/null @@ -1,172 +0,0 @@ -begin 644 instbsdi.exe -M35JK``8`!``@`($`__^+```(.VR.````'@````$`"@!P`)D````C`0``G@!P -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M````````````````````````````````````````````58OLN#H`Z+T"N`X` -M4"O`4(U&SE#H80:#Q`;&1L]2C4;J4(U&\E"-1LY0N"$`4.BS!8/$"(M&ZHE& -MQHM&](E&YL=&S@9=C4;J4(U&\E"-1LY0N"$`4.B,!8/$"(M&\(E&S(M&^HE& -MY(U&QE"-1LY0C4;<4+C_`%#H:@6+Y5W#M##-(3P"<P+-(+]L`(LV`@`K]X'^ -M`!!R`[X`$/J.UX'$[@'[<Q`6'^CW`3/`4.AV!+C_3,TA@^3^-HDF2``VB29$ -M`(O&L033X$@VHT(``_>)-@(`C,,KWO?;M$K-(3:,'KD`%@?\O^P!N?`!*\\S -MP/.J%A_H.P`6'^B2`^@!`C/M_S;:`/\VV`#_-M8`Z/+^4.CB`+AL`([8N`,` -M-L<&1@`$`E#H>P'H_0.X_P!0_Q9&`+0PS2&CNP"X`#7-(8D>IP",!JD`#A^X -M`"6Z(@'-(18?BPX(`>,NC@:Y`":+-BP`Q08*`8S:,]LV_QX&`7,%%A_I30$V -MQ08.`8S:NP,`-O\>!@$6'XX&N0`FBPXL`.,VCL$S_R:`/0!T++D,`+Z:`/.F -M=`NY_W\SP/*N=1GKY08>!Q^+][_"`*R8D:S^P'0!2*KB]Q8?NP0`@*?"`+^X -M`$3-(7(*]L*`=`6`C\(`0$MYY[X2`;\2`>BB`+X2`;\2`>B*`,-5B^R^[`&_ -M[`'H?0"^$@&_$@'H=`#K`U6+[+X2`;\2`>AF`+X2`;\2`>AL`.BY``O`=`N# -M?@0`=07'1@3_`+D/`+L%`/:'P@`!=`2T/LTA0^+RZ`<`BT8$M$S-(8L."`'C -M![L"`/\>!@$>Q1:G`+@`)<TA'X`^Y```=`T>H.4`Q1;F`+0ES2$?PSOW<PI/ -M3XL-X_;_T>ORPSOW<PZ#[P2+!0M%`G3R_QWK[L,`58OLN/P`4.A[`H,^Z@`` -M=`3_%NH`N/\`4.AI`HOE7<.X`@#I6_Y9B]PKV'(*.Q[L`'($B^/_X3/`Z47^ -M5C/VN4(`,N3\K#+@XON`]%5T#>BN_[@!`%#H+`*X`0!>PX\&[@"Z`@`X%KL` -M="F.!KD`)HX&+`",!MX`,\"9N0"`,__RKJYU^T='B3[<`+G___*N]]&+T;\! -M`+Z!`(X>N0"L/"!T^SP)=/<\#71O"L!T:T=.K#P@=.@\"73D/`UT7`K`=%@\ -M(G0D/%QT`T+KY#/)0:P\7'3Z/")T!`/1Z].+P='I$]&H`77*ZP%.K#P-="L* -MP'0G/")TNCQ<=`-"Z^PSR4&L/%QT^CPB=`0#T>O;B\'1Z1/1J`%UTNN7%A^) -M/M8``]='T><#UX#B_BOBB\2CV`"+V`/[%@<VB3]#0\4VW`"LJ@K`=?J^@0`V -MCAZY`.L#,\"JK#P@=/L\"73W/`UU`^E_``K`=0/K>9`VB3]#0TZL/"!TVSP) -M=-<\#71B"L!T7CPB="<\7'0#JNOD,\E!K#Q<=/H\(G0&L%SSJNO1L%S1Z?.J -M<P:P(JKKQ4ZL/`UT+@K`="H\(G2W/%QT`ZKK[#/)0:P\7'3Z/")T!K!<\ZKK -MV;!<T>GSJG.6L"*JZ\TSP*H6'\<'``#_)NX`58OL58X>N0`SR8O!B^F+^4F+ -M-BP`"_9T$([&)H`^````=`;RKD6N=?I%ET`D_HO]T>4#Q18?5[\)`.B%`%^+ -MSXO]`_B)+MH`'@>.WC/V2>,3@3P[0W0%B7X`146LJ@K`=?KB[8E.`!8?78OE -M7<-5B^Q65QX'BU8$OAH!K3O"=!!`EG0,ES/`N?__\JZ+]^OKEE]>B^5=P@(` -M58OL5_]V!.C+_PO`=!22B_HSP+G___*N]]%)NP(`M$#-(5^+Y5W"`@"+T`,& -M2`!R-3D&0@!S)04/`%#1V+$#T^B,V8L>N0`KRP/!CL.+V+1*S2%8<A`D\$BC -M0@"5BRY(``$62`##B\?ID?MR$S/`B^5=PW/X4.@8`%B+Y5W#<P?H#@"X__^9 -MB^5=PS+DZ`$`PZ*^``KD=2.`/KL``W(-/")S#3P@<@6P!>L'D#P3=@*P$[OP -M`->8H[,`PXK$Z_=5B^Q65QZ#[`K&1O3-BT8$B$;U/"5T"CPF=`;&1O;+ZPS& -M1OC+QD;W1,9&]D2,5O*-1O2)1O"+?@:+!8M=`HM-!(M5!HMU"/]U"HM^"HX% -MCET&7U7_7O!=_%<>%A^+?@J,!8]%!HM^"(D%B5T"B4T$B54&B74(CT4*<@0S -M]NL(Z$K_O@$`BP6)=0R#Q`H?7UZ+Y5W#58OLB]>,V([`BWX$B]^+3@CC%8I& -M!HK@]\<!`'0"JDG1Z?.K$\GSJHOZDUW#`````````````````````````$U3 -M(%)U;BU4:6UE($QI8G)A<GD@+2!#;W!Y<FEG:'0@*&,I(#$Y.#@L($UI8W)O -M<V]F="!#;W)P$0``````&P(``&P````````````````````````````````` -M```````````````````````````````````````````````````````````` -M`````````$@`.T-?1DE,15])3D9/```````````````````````````````` -M```4`(&!@0$!````````````````````````````X`!L`$,````````````` -M`/`"````%@("&`T)#`P,!P@6%O\2#1("_P``````````````````/#Q.35-' -M/CX``%(V,#`P#0HM('-T86-K(&]V97)F;&]W#0H``P!2-C`P,PT*+2!I;G1E -M9V5R(&1I=FED92!B>2`P#0H`"0!2-C`P.0T*+2!N;W0@96YO=6=H('-P86-E -M(&9O<B!E;G9I<F]N;65N=`T*`/P`#0H`_P!R=6XM=&EM92!E<G)O<B```@!2 -M-C`P,@T*+2!F;&]A=&EN9R!P;VEN="!N;W0@;&]A9&5D#0H``0!2-C`P,0T* -M+2!N=6QL('!O:6YT97(@87-S:6=N;65N=`T*`/___XD$BU[\N``"B4<"B40" -MQ@<!@$P&`K@!`%Z+Y5W#58OL@^P"5H-^!`!T6X%^!C@!=`>!?@9``75VBUX& -MBD<'F%#H_@V#Q`(+P'1DBT8&+3`!L0/3^(O(T>`#P='@!=`!B4;^_W8&Z$L` -M@\0"BU[^Q@<`QT<"``"+7@:+\RO`B02)1P3K*I"+7@:!?P2@`W0'@7\$H`=U -M&(I'!YA0Z*,-@\0""\!T"?]V!N@(`(/$`EZ+Y5W#58OL@^P$5U:+=@0K_XI$ -M!B0#/`)U1O9$!@AU&8O>@>LP`;$#T_N+P]'C`]C1X_:'T`$!=">+!"M$!(E& -M_`O`?AM0_W0$BD0'F%#H8PF#Q`8[1OQT!X!,!B"___^+1`2)!,=$`@``B\=> -M7XOE7<-5B^RX9`'H(?E75HMV!HV&GOZCC`.+1@BC?`.+1@2C<`/'!H8#``#' -M!H0#``#I?`*`/"5T`^E8`L<&B`,!`"O`HW@#HW0#HX(#HW8#HX`#HWX#HW(# -MHVX#HWH#QP:2`R``@'P!,'4\1L<&D@,P`.LS@#PK=0W_!G@#QP9^`P``ZR*0 -M@#P@=0V#/G@#`'45_P9^`^L/_P9N`^L)@#PM=='_!GH#1HH$F%#H]0>#Q`(+ -MP'7H5KB.`U#H9@>#Q`2+\(,^C@,`?0S_!GH#H8X#]]BCC@.`/"YU(_\&@`-& -M5KB(`U#H/`>#Q`2+\(,^B`,`?0K'!H@#`0#_#H`#B@28/48`=#(]3@!T-3UH -M`'0@/6P`=0;'!G8#`@"#/G8#`'4%@#Q,=0%&@#P`=1OIB`''!G8#`0#KX\<& -M=@,0`.O;QP9V`P@`Z].*!)B)AIS^/44`=`H]1P!T!3U8`'4)_P9T`X.&G/X@ -MBX:<_BUC`#T5`'8#Z10!`\"3+O^GE@R+'GP#BQ^AA`.)!X,&?`,"Z6D!D/\& -M@@/'!FX#``"X"@!0Z'\!@\0"Z5$!D+@(`.OPD/\&<@/_!G0#@SZ``P!U"<<& -MB@,!`.L'D,<&B@,``/\&@`/'!H@#!`"#/G8#"'4#Z8@`*\"C=@.)1OPY!HX# -M=">AC@.)1OR#/GH#`'0)QP:.`P``ZQ*0@RZ.`P6AC@,+P'T"*\"CC@.#!GP# -M`K@0`%#H_P"#Q`*X.@!0Z,\#@\0"@W[\`'0B@SYZ`P!T%8M&_"T%`*..`PO` -M?0(KP*..`^L'D,<&C@,``(,N?`,$N!``4.B^`(/$`ND?_[@0`.DO_RO`4.CB -M`>DJ_Y"X`0#K\Y#_MIS^Z+D"Z1G_@SYV`P!T`XO&3HO^1X`]`'0%@#TE=?6+ -MQRO&4!Y6Z.T#@\0&B_>`/`!T`^E\_8,^A`,`=5F+'G`#]D<&('1/N/__ZTU" -M#%X+2`Q(#$@,4@Q>"U(,4@Q2#%(,1@MR"W@+4@Q2##@,4@Q:"U(,4@PR#(,^ -MA@,`=!.#/H0#`'40BQYP`_9'!B!UM^L$1NN9D*&$`UY?B^5=PY!5B^R#[!A7 -M5H-^!`IT!/\&@@.#/G8#`G0'@SYV`Q!U%HL>?`.+!XM7`HE&_(E6_H,&?`,$ -MZRJ#/H(#`'01BQY\`XL'B4;\QT;^``#K#I"+'GP#BP>9B4;\B5;^@P9\`P*# -M/FX#`'0-BT;\"T;^=`6+1@3K`BO`HY`#BS:,`X,^@@,`=2J#?OX`?22#?@0* -M=1?&!"U&BT;\BU;^]]B#T@#WVHE&_(E6_L=&^`$`ZP7'1O@``(U&Z(OX_W8$ -M5_]V_O]V_.@S"8/$"(,^@`,`="%7Z`D)@\0"BPZ(`RO(B4[TZP60Q@0P1HO! -M20O`?_6)3O2+#G0#B@6(!`O)=`<\87P#@"P@1D>`??\`=>F#/H(#`'44H7@# -M"P9^`W0+@W[X`'4%N`$`ZP(KP%#HL@*#Q`)>7XOE7<.058OL@^P05U:#?@0` -M=!2^`0"A?`.)1OB,7OJ#!GP#`NF1`(,^=@,0=1>+'GP#BP>+5P*)1OB)5OJ# -M!GP#!.L5D(L>?`.+!XE&_(E&^(Q>^H,&?`,"@SYV`Q!U#8M&^`M&^G44N$H" -MZPF#?OP`=0FX40*)1OB,7OJ+1OB+5OJ)1O*)5O0K]CDV@`-T'(L.B`/K#I#$ -M7O+_1O(F@#\`=!5&.\Y^$.OMD$;$7O+_1O(F@#\`=?.+/HX#*_Z#/GH#`'4' -M5^@>`8/$`E;_=OK_=OCH;P&#Q`:#/GH#`'0'5^@#`8/$`EY?B^5=PU6+[(/L -M!*%\`XE&_H-^!&=T!H-^!$=U!+`!ZP(JP(A&_(,^@`,`=0;'!H@#!@"`?OP` -M=`V#/H@#`'4&QP:(`P$`_S9T`_\VB`/_=@3_-HP#_W;^_Q9T`H/$"H!^_`!T -M$H,^;@,`=0O_-HP#_Q9V`H/$`H,^;@,`=!*#/H@#`'4+_S:,`_\6>@*#Q`*# -M!GP#",<&D`,``*%X`PL&?@-T$_]V_O\6?`*#Q`(+P'0%N`$`ZP(KP%#H"`&+ -MY5W#58OL5H,^A@,`=2^+'G`#_T\">`Z*1@2+-_\'B`0JY.L+D%/_=@3HE?:# -MQ`1`=0?_!H8#ZP60_P:$`UY=PY!5B^R#[`)75H,^A@,`=4F+=@0+]GY"ZQ7_ -M-G`#_S:2`^A=]H/$!$!U!/\&A@.+QDX+P'X6BQYP`_]/`GC;H)(#BS__!X@% -M*N3KW(,^A@,`=0>+1@0!!H0#7E^+Y5W#58OL@^P"5U:+=@B#/H8#`'50ZQS_ -M-G`#Q%X$)HH'F%#H__6#Q`1`=03_!H8#_T8$B\9."\!T'8L><`/_3P)XU,1> -M!":*!XL><`.+/_\'B`4JY.O2@SZ&`P!U!XM&"`$&A`->7XOE7<-5B^R#[`I7 -M5HLVC`,KP(E&_(E&^H,^D@,P=1@Y!H`#=!(Y!G(#=`8Y!HH#=0;'!I(#(`"+ -M/HX#5NC#!8/$`HE&^"OX*WX$@SYZ`P!U&(`\+743@SZ2`S!U#*R84.B=_H/$ -M`O].^(,^D@,P=`L+_WX'@SYZ`P!T&8-^!`!T!O]&^NA?`(,^D`,`=`;_1OSH -M:@"#/GH#`'4F5^B?_H/$`H-^!`!T"8-^^@!U`^@U`(,^D`,`=`F#?OP`=0/H -M/0#_=O@>5NC3_H/$!H,^>@,`=`W'!I(#(`!7Z&'^@\0"7E^+Y5W#@SYX`P!T -M!;@K`.L#N"``4.@'_H/$`L.0N#``4.C[_8/$`H,^D`,0=1>#/G0#`'0&N%@` -MZP20N'@`4.C=_8/$`L.058OL@^P$5U:+=@;'1OX!`(`\*G4/BQY\`XL_@P9\ -M`P)&ZTB0@#PM=0;'1O[__T8K_X`\,'PU@#PY?S`Y/H`#=0N`/#!U!L<&D@,P -M`(H$F(O/T>'1X0//T>$#R(/I,(OY1H`\,'P%@#PY?N&+1O[W[XOXBUX$B3^+ -MQEY?B^5=PY!5B^R#[`)6OE@"BDX$ZP*01H`\`'0*.@QU]K@!`.L#D"O`7HOE -M7<.058OL@^P$BUX$.Q[J`'(%N``)ZRKW1@@`@'1(@WX*`'0:,\F+T;@!0LTA -M<DOW1@H"`'4.`T8&$U8(>2BX`!;YZS:)5OZ)1OR+T;@"0LTA`T8&$U8(>0V+ -M3OZ+5ORX`$+-(>O8BU8&BTX(BD8*M$+-(7(%@*?L`/WIQ?)5B^R#[`B+7@0[ -M'NH`<@>X``GYZ:_R]H?L`"!T"[@"0C/)B]'-(7+K]H?L`(!T;HM6!AX',\") -M1OZ)1OS\5U:+^HORB6;XBTX(XU2P"O*N=4KHU``]J`!V2(/L`HO<N@`"/2@" -M<P.Z@``KXHO4B_H6!XM."*P\"G0,._MT&:KB].@C`.MAL`T[^W4#Z!@`JK`* -M_T;\Z^/H#0#KXEY?ZU7K13/`Z9WM4%-1B\\KRN,0BUX$M$#-(7(-`4;^"\!T -M!EE;6(OZPX/$"',$M`GK'O:'[`!`=`N+7@:`/QIU`_CK#/FX`!SK!HM&_BM& -M_(MF^%Y?Z='QBTX("\EU!8O!Z<7QBU8&M$#-(7,$M`GKY`O`=>#VA^P`0'0* -MB]J`/QIU`_CKS_FX`!SKR5FA%@$[Q',&*\3WV/_A,\#K^E6+[(M>!`O;=`2` -M3_X!B^5=PU6+[%97NUX"@S\`=2D>![@%`.AS`74%,\"9ZR1`)/ZC7@*C8`*6 -MQP0!`(/&!,=$_O[_B39D`HM.!(S8CL#H"0!?7HOE7</IS@!!=/J`X?Z#^>YS -M\HMW`ORMB_ZH`71"2#O!<Q6+T`/PK:@!=#0#P@4"`(OWB43^Z^:+_G0,`_F) -M3/XKP4B)!>L%`_G^3/Z+QHS:C-$[T70%)HP>;`*)?P+#)L8&<@("/?[_="6+ -M_@/PK:@!=/*+_D@[P7.]B]`#\*VH`73B`\(%`@"+]XE$_NOFBT<("\!T!([8 -MZQ0F_@YR`G01C-B,USO'=`4FCAYH`HLWZ[R+=P8SP.AJ`#O&=`TD`4!`F.A> -M`'0-_DW^Z!P`=`663D[KF8S8C-$[P70$)J-L`HL'B4<",\"9PU&+1?ZH`70# -M*\A)04&Z_W\F.Q9N`G8$T>IU]8O!`\9R%0/"<@WWTB/"*\;H#`!U"/?2T>IU -MY3/`6<-24>@=`'085XO^B_`#\L=$_O[_B7<&B]8KUTJ)5?Y865K#4U`STAY2 -M4E"X`0!0!A_H#P"#Q`B#^O\?6EMT`@O2PP!5B^Q65P:#?@@`=3B_<@"+5@:+ -M1@1(=0?H4P!R)^M(BS;"`$AT$3OW=`V+1`*)1@Q6Z#H`7G,P@\8$@?["`',$ -M"])U!KC__YGK'8O:@\,/T=NQ`]/KM$C-(7+IDHD$B50"B3;"`#/`!U]>B^5= -MPXM.#(OW.4P"=`R#Q@2!_L(`=?+YZS^+V@,<<CF+TX[!._=U!CD>;`!S)H/# -M#]';T>O1Z]'K._=U"0/9H>,`*]B.P+1*S2%R#3OW=02)%FP`DH<$B]'#58OL -MB]>,V([`BWX$,\"Y___RKO?129&+^EW#`%6+[%97LP#IY@!5B^R+7@0['NH` -M?1&#^P!\#/:'[`!`=`6X`0#K`C/`B^5=PP!5B^Q65QZ#[`K&1O3-BT8$B$;U -M/"5T"CPF=`;&1O;+ZPS&1OC+QD;W1,9&]D2,5O*-1O2)1O"+?@:+!8M=`HM- -M!(M5!HMU"/]U"HM^"HX%CET&7U7_7O!=_%<>%A^+?@J,!8]%!HM^"(D%B5T" -MB4T$B54&B74(CT4*<@0S]NL(Z$[NO@$`BP6)=0R#Q`H?7UZ+Y5W#58OLB]>, -MV([`BWX$B]^+3@CC%8I&!HK@]\<!`'0"JDG1Z?.K$\GSJHOZDUW#`(M."HM& -M!(M6!HM^"%<>!_R3"L!T$X/Y"G4."])Y"K`MJO?;@](`]]J+]Y(ST@O`=`+W -M\9/W\9*'TP0P/#EV`@0GJHO""\-UXH@%3ZR&!8A$_XU$`3O'<O)87UZ+Y5W# -M``````````````````````````````!-4R!2=6XM5&EM92!,:6)R87)Y("T@ -M0V]P>7)I9VAT("AC*2`Q.3@X+"!-:6-R;W-O9G0@0V]R<!$`3$],(&ES(&%T -M("4P-'@Z)3`T>`H`4T1!(&ES(&%T("4P-'@Z)3`T>`H``````#L"``"$`0`` -M```````````````````````````````````````````````````````````` -M``````````````````````````````````````!R`#M#7T9)3$5?24Y&3P`` -M````````````````````````````````%`"!@8$!`0`````````````````` -M``````````H!A`%#``````````````"@"@```!8"`A@-"0P,#`<(%A;_$@T2 -M`O\``*`%``"@!0$``````````@$````````"`@```````(0#`````````@0` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````!```"```````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M``````````````````#(`2AN=6QL*0`H;G5L;"D`*RT@(P`````````````` -M```````````@`````/`"\`+P`O`"\`(``````````````````````````!0& -M/#Q.35-'/CX``%(V,#`P#0HM('-T86-K(&]V97)F;&]W#0H``P!2-C`P,PT* -M+2!I;G1E9V5R(&1I=FED92!B>2`P#0H`"0!2-C`P.0T*+2!N;W0@96YO=6=H -M('-P86-E(&9O<B!E;G9I<F]N;65N=`T*`/P`#0H`_P!R=6XM=&EM92!E<G)O -M<B```@!2-C`P,@T*+2!F;&]A=&EN9R!P;VEN="!N;W0@;&]A9&5D#0H``0!2 -E-C`P,0T*+2!N=6QL('!O:6YT97(@87-S:6=N;65N=`T*`/___V5D -` -end diff --git a/usr.bin/doscmd/intff.c b/usr.bin/doscmd/intff.c index e27ac0e..0633246 100644 --- a/usr.bin/doscmd/intff.c +++ b/usr.bin/doscmd/intff.c @@ -29,7 +29,7 @@ * * BSDI intff.c,v 2.2 1996/04/08 19:32:56 bostic Exp * - * $Id: intff.c,v 1.8 1996/09/23 09:59:25 miff Exp $ + * $Id: intff.c,v 1.1 1997/08/09 01:42:51 dyson Exp $ */ #include "doscmd.h" @@ -787,17 +787,17 @@ init_drives(void) } } + void intff(regcontext_t *REGS) { - if (lol && sda) { /* already been called? */ + if (lol && sda) { /* already been called? */ debug(D_REDIR, "redirector duplicate install ignored\n"); return; } - lol = (LOL *)N_GETPTR(R_ES, R_DI); /* where DOS keeps its goodies */ - sda = (SDA *)N_GETPTR(R_DS, R_SI); - + lol = (LOL *)N_GETPTR(R_BX, R_DX); /* where DOS keeps its goodies */ + sda = (SDA *)N_GETPTR(R_DI, R_SI); init_drives(); /* initialise dispatcher */ diff --git a/usr.bin/doscmd/redir.S b/usr.bin/doscmd/redir.S new file mode 100644 index 0000000..4cb4e2e --- /dev/null +++ b/usr.bin/doscmd/redir.S @@ -0,0 +1,122 @@ +! Copyright (c) 1997 Helmut Wirth <hfwirth@ping.at> +! All rights reserved. +! +! Redistribution and use in source and binary forms, with or without +! modification, are permitted provided that the following conditions +! are met: +! 1. Redistributions of source code must retain the above copyright +! notice immediately at the beginning of the file, witout modification, +! this list of conditions, and the following disclaimer. +! 2. Redistributions in binary form must reproduce the above copyright +! notice, this list of conditions and the following disclaimer in the +! documentation and/or other materials provided with the distribution. +! 3. The name of the author may not be used to endorse or promote products +! derived from this software without specific prior written permission. +! +! THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +! IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +! OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +! IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +! INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +! NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +! DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +! THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +! (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +! THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +! +! $Id$ + + +! +! This is the new redirector program, it replaces instbsdi.exe +! The program fetches some pointers from DOS and reports them back to +! the emulator via the emulator interrupt 0xff. It does not stay resident. + +use16 + +.text +.bss +.data +.align 0 + +! Emulator interrupt entry +EmulatorINT = 0xFF +! Emulator redirector function +EmulatorRED = 0x1 + +! DOS interrupt +DOSInt = 0x21 + +! DOS get list of lists call, returns pointer to system vars in ES:BX +DOSGetList = 0x52 + +! DOS get swappable area, returns DOS swappable area in DS:SI +DOSGetSwapD = 0x5D06 + +! DOS terminate program with return code +DOSExit = 0x4C + +! DOS print message +DOSMesg = 0x9 + +cr = 0xd +lf = 0xa +eom = '$' ! DOS end of string + + .org 0x100 + +.globl _main +_main: + + mov ah, #DOSGetList + int DOSInt + jc Fail + mov [_list], bx + mov ax, es + mov [_list+2], ax + push ds + mov ax, #DOSGetSwapD + int DOSInt + mov ax, ds + pop ds + jc Fail + mov [_swap], si + mov [_swap+2], ax + push ax + mov ah, #EmulatorRED + mov dx, [_list] + mov bx, [_list+2] + mov si, [_swap] + mov di, [_swap+2] + int EmulatorINT + xor al, al ! return 0 + jmp Exit +Fail: + mov ah, #DOSMesg + mov dx, #ErrorMessage + int DOSInt + mov al, #1 ! return 1 +Exit: + mov ah, #DOSExit + int DOSInt +! +! Should never get to this point +! + nop + nop + hlt + +! The two pointers are found using the DOS calls +! and passed to the redirector interface via int FF +! The two pointers are passed in BX:DX (list) and DI:SI (swap) + +.align 2 + +_list: .word 0 + .word 0 +_swap: .word 0 + .word 0 + +ErrorMessage: + .ascii "Error installing redirector interface" + .byte cr,lf,eom, 0 diff --git a/usr.bin/doscmd/redir.com.uu b/usr.bin/doscmd/redir.com.uu new file mode 100644 index 0000000..0bdf492 --- /dev/null +++ b/usr.bin/doscmd/redir.com.uu @@ -0,0 +1,6 @@ +begin 644 redir.com +MM%+-(7(TB1Y*`8S`HTP!'K@&7<TAC-@?<B")-DX!HU`!4+0!BQ9*`8L>3`&+ +M-DX!BSY0`<W_,,#K";0)NE(!S2&P`;1,S2&0D/0``````````$5R<F]R(&EN +B<W1A;&QI;F<@<F5D:7)E8W1O<B!I;G1E<F9A8V4-"B0````` +` +end diff --git a/usr.bin/doscmd/trap.c b/usr.bin/doscmd/trap.c index 7f11368..a3d5af0 100644 --- a/usr.bin/doscmd/trap.c +++ b/usr.bin/doscmd/trap.c @@ -29,7 +29,7 @@ * * BSDI trap.c,v 2.3 1996/04/08 19:33:08 bostic Exp * - * $Id: trap.c,v 1.10 1996/10/02 00:31:43 miff Exp $ + * $Id: trap.c,v 1.1 1997/08/09 01:42:58 dyson Exp $ */ #include "doscmd.h" @@ -63,7 +63,7 @@ fake_int(regcontext_t *REGS, int intnum) int2f(®S->sc); break; case 0xff: /* doscmd special */ - intff(REGS); + emuint(REGS); break; default: /* should not get here */ if (vflag) dump_regs(REGS); @@ -581,7 +581,7 @@ sigalrm(struct sigframe *sf) update_counter = 0; /* remember we've updated */ video_update(®S->sc); hardint(0x08); -/* debug(D_ALWAYS,"\n"); */ +/* debug(D_ALWAYS,"\n"); */ if (tmode) tracetrap(REGS); @@ -604,6 +604,9 @@ sigfpe(struct sigframe *sf) regcontext_t *REGS = (regcontext_t *)(&sf->sf_sc); if (R_EFLAGS & PSL_VM) { + dump_regs(REGS); + debug(D_ALWAYS, "DOS program caused floating point fault\n"); +/*XXX Look into that !! */ fake_int(REGS, 0); /* call handler XXX rather bogus, eh? */ return; } diff --git a/usr.bin/doscmd/xms.c b/usr.bin/doscmd/xms.c index f9df109..81ba91b 100644 --- a/usr.bin/doscmd/xms.c +++ b/usr.bin/doscmd/xms.c @@ -25,7 +25,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id$ + * $Id: xms.c,v 1.2 1997/08/15 23:41:25 jlemon Exp $ */ /* @@ -111,7 +111,10 @@ xms_init(void) add_block(&UMB_freelist, create_block(0xd0000, 64*1024)); /*XXX check for EMS emulation, when it is done! */ /* 0xE0000 to 0xEffff */ - add_block(&UMB_freelist, create_block(0xe0000, 64*1024)); + +/* This is used as window for EMS, will be configurable ! */ +/* add_block(&UMB_freelist, create_block(0xe0000, 64*1024)); */ + merge_blocks(); xms_vector = insert_generic_trampoline( @@ -142,8 +145,7 @@ add_block(UMB_block **listp, UMB_block *blk) if (*listp == NULL) { *listp = blk; blk->next = NULL; - } - else { + } else { /* Insert at the start */ bp = obp = *listp; if (blk->addr < bp->addr) { @@ -156,8 +158,7 @@ add_block(UMB_block **listp, UMB_block *blk) if (blk->addr > bp->addr) { obp = bp; continue; - } - else { + } else { obp->next = blk; blk->next = bp; return; @@ -228,10 +229,10 @@ merge_blocks() bp->size += mergebp->size; bp->next = mergebp->next; free(mergebp); - } - else + } else { /* Goto next block */ bp = bp->next; + } } while (bp != NULL); } @@ -485,13 +486,19 @@ static void xms_entry(regcontext_t *REGS) { - if (R_AH != 0) { - if (HMA_a20 < 0) { /* This feature is disabled */ - R_AX = 0x0; - R_BL = XMS_HMA_NOT_MANAGED; - return; - } + if (R_AH != 0) vec_grabbed = 1; + + /* If the HMA feature is disabled these calls are "not managed" */ + if (HMA_a20 < 0) { + if (R_AH == XMS_ALLOCATE_HIGH_MEMORY || R_AH == XMS_FREE_HIGH_MEMORY || + R_AH == XMS_GLOBAL_ENABLE_A20 || R_AH == XMS_GLOBAL_DISABLE_A20 || + R_AH == XMS_LOCAL_ENABLE_A20 || R_AH == XMS_LOCAL_DISABLE_A20 || + R_AH == XMS_QUERY_A20) { + R_AX = 0x0; + R_BL = XMS_HMA_NOT_MANAGED; + return; + } } switch (R_AH) { @@ -513,8 +520,7 @@ xms_entry(regcontext_t *REGS) if (HMA_allocated) { R_AX = 0x0; R_BL = XMS_HMA_ALREADY_USED; - } - else { + } else { HMA_allocated = 1; R_AX = 0x1; R_BL = XMS_SUCCESS; @@ -527,8 +533,7 @@ xms_entry(regcontext_t *REGS) HMA_allocated = 0; R_AX = 0x1; R_BL = XMS_SUCCESS; - } - else { + } else { R_AX = 0x0; R_BL = XMS_HMA_NOT_ALLOCATED; } @@ -588,8 +593,19 @@ xms_entry(regcontext_t *REGS) break; case XMS_QUERY_FREE_EXTENDED_MEMORY: - R_AX = R_DX = xms_free_mem / 1024; - R_BL = XMS_SUCCESS; + /* DOS MEM.EXE chokes, if the HMA is enabled and the reported + * free space includes the HMA. So we subtract 64kB from the + * space reported, if the HMA is enabled. + */ + if (HMA_a20 < 0) + R_EAX = R_EDX = xms_free_mem / 1024; + else + R_EAX = R_EDX = (xms_free_mem / 1024) - 64; + + if (xms_free_mem == 0) + R_BL = XMS_FULL; + else + R_BL = XMS_SUCCESS; debug(D_XMS, "XMS: Query free EMM: Returned %dkB\n", R_AX); break; @@ -626,10 +642,10 @@ xms_entry(regcontext_t *REGS) * but with no memory attached ? XMS specs are unclear on * that point. Linux implementation does it this way. */ - if (req_siz == 0) + if (req_siz == 0) { /* This handle is reserved, but has size 0 and no address */ xms_hand[hindx].addr = XMS_NULL_ALLOC; - else { + } else { if ((mem = malloc(req_siz)) == NULL) fatal("XMS: Cannot malloc !"); xms_hand[hindx].addr = (u_long)mem; @@ -663,13 +679,13 @@ xms_entry(regcontext_t *REGS) R_AX = 0x0; R_BL = XMS_INVALID_HANDLE; debug(D_XMS, " Invalid handle\n"); - } - else if (xms_hand[hindx].num_locks > 0) { + + } else if (xms_hand[hindx].num_locks > 0) { R_AX = 0x0; R_BL = XMS_BLOCK_IS_LOCKED; debug(D_XMS, " Is locked\n"); - } - else { + + } else { if (xms_hand[hindx].addr != XMS_NULL_ALLOC) { free((void *)xms_hand[hindx].addr); xms_free_mem += xms_hand[hindx].size; @@ -724,7 +740,7 @@ xms_entry(regcontext_t *REGS) srcoffs = eptr->src_offset; dstoffs = eptr->dst_offset; n = eptr->nbytes; - /* Lenght must be even, see XMS spec */ + /* Length must be even, see XMS spec */ if (n & 1) { R_AX = 0x0; R_BL = XMS_INVALID_LENGTH; @@ -746,8 +762,7 @@ xms_entry(regcontext_t *REGS) break; } srcptr += srcoffs; - } - else { + } else { srcptr = VECPTR(srcoffs); /* Sanity check: Don't allow srcptr pointing to * emulator data above 1M @@ -775,8 +790,7 @@ xms_entry(regcontext_t *REGS) break; } dstptr += dstoffs; - } - else { + } else { dstptr = VECPTR(dstoffs); /* Sanity check: Don't allow dstptr pointing to * emulator data above 1M @@ -863,7 +877,7 @@ xms_entry(regcontext_t *REGS) { int hnum,hindx; - debug(D_XMS, "XMS: Get handle information: DX=%04x\n, R_DX"); + debug(D_XMS, "XMS: Get handle information: DX=%04x\n", R_DX); hnum = R_DX; if (hnum > NUM_HANDLES || hnum == 0) { R_AX = 0x0; @@ -933,8 +947,7 @@ xms_entry(regcontext_t *REGS) fatal("XMS: Cannot malloc !"); xms_hand[hindx].addr = (u_long)mem; xms_hand[hindx].size = req_siz; - } - else { + } else { if ((mem = realloc((void *)xms_hand[hindx].addr,req_siz)) == NULL) fatal("XMS: Cannot realloc !"); @@ -978,13 +991,13 @@ xms_entry(regcontext_t *REGS) R_AX = 0x0; R_BL = XMS_NO_UMBS_AVAILABLE; R_DX = 0x0; - } - else if (bp->size < req_siz) { + + } else if (bp->size < req_siz) { R_AX = 0x0; R_BL = XMS_REQUESTED_UMB_TOO_BIG; R_DX = bp->size / 16; - } - else { + + } else { UMB_block *newbp; /* Found a block large enough. Split it into the size * we need, rest remains on the free list. New block @@ -1011,8 +1024,7 @@ xms_entry(regcontext_t *REGS) if ((blk = find_allocated_block(req_addr)) == NULL) { R_AX = 0x0; R_BL = XMS_INVALID_UMB_SEGMENT; - } - else { + } else { /* Move the block from the alloc list to the free list * and try to do garbage collection */ @@ -1037,6 +1049,27 @@ xms_entry(regcontext_t *REGS) R_BL = XMS_NOT_IMPLEMENTED; break; + /* Some test programs use this call */ + case XMS_QUERY_FREE_EXTENDED_MEMORY_LARGE: + /* DOS MEM.EXE chokes, if the HMA is enabled and the reported + * free space includes the HMA. So we subtract 64kB from the + * space reported, if the HMA is enabled. + */ + if (HMA_a20 < 0) + R_EAX = R_EDX = xms_free_mem / 1024; + else + R_EAX = R_EDX = (xms_free_mem / 1024) - 64; + /* ECX should return the highest address of any memory block + * We return 1MB + size of extended memory + */ + R_ECX = 1024 * 1024 + xms_maxsize -1; + if (xms_free_mem == 0) + R_BL = XMS_FULL; + else + R_BL = XMS_SUCCESS; + debug(D_XMS, "XMS: Query free EMM(large): Returned %dkB\n", R_AX); + break; + /* These are the same as the above functions, but they use 32 bit * registers (i.e. EDX instead of DX). This is for allocations of * more than 64MB. I think this will hardly be used in the emulator @@ -1044,10 +1077,9 @@ xms_entry(regcontext_t *REGS) * spec. If something breaks because they are not here, I can implement * them */ - case XMS_QUERY_FREE_EXTENDED_MEMORY_LARGE: case XMS_ALLOCATE_EXTENDED_MEMORY_LARGE: case XMS_FREE_EXTENDED_MEMORY_LARGE: - debug(D_XMS, "XMS: 8x function called, not implemented\n"); + debug(D_XMS, "XMS: %02x function called, not implemented\n", R_AH); R_AX = 0x0; R_BL = XMS_NOT_IMPLEMENTED; break; |