From f4ab00c556ef8f5aaf77e3691ba63bcc2b022640 Mon Sep 17 00:00:00 2001 From: Kenneth J Davis Date: Sun, 25 Jul 2004 09:55:58 +0000 Subject: [PATCH] patches from Arkady, Lucho, and Bart -- see history.txt for details git-svn-id: https://svn.code.sf.net/p/freedos/svn/kernel/branches/UNSTABLE@1009 6ac86273-5f31-0410-b378-82cca8765d1b --- boot/boot.asm | 165 ++++++++++++------------------- build.bat | 12 ++- config.b | 1 + defaults.bat | 1 + docs/config.txt | 236 +++++++++++++++++++++++++++++++++++++------- docs/contrib.txt | 2 +- docs/history.txt | 26 +++++ drivers/makefile | 2 +- filelist | 2 + hdr/dcb.h | 5 +- hdr/device.h | 2 +- hdr/dirmatch.h | 29 +++--- kernel/dosfns.c | 112 +++++++++------------ kernel/dsk.c | 40 ++++---- kernel/int2f.asm | 2 + kernel/inthndlr.c | 109 ++++++++++---------- kernel/ioctl.c | 20 ++-- kernel/ludivmul.inc | 194 +++++++++++++++++++++--------------- kernel/main.c | 12 ++- kernel/nls.c | 10 +- kernel/proto.h | 8 +- kernel/task.c | 2 +- kernel/vc.cfg | 5 - sys/fdkrncfg.c | 4 - sys/sys.c | 21 ++-- 25 files changed, 599 insertions(+), 423 deletions(-) delete mode 100644 kernel/vc.cfg diff --git a/boot/boot.asm b/boot/boot.asm index af2c527..fac35f1 100644 --- a/boot/boot.asm +++ b/boot/boot.asm @@ -91,50 +91,6 @@ Entry: jmp short real_start ;%define StoreSI bp+3h ;temp store -; To save space, functions that are just called once are -; implemented as macros instead. Four bytes are saved by -; avoiding the call / ret instructions. - - -; GETDRIVEPARMS: Calculate start of some disk areas. -; - -%macro GETDRIVEPARMS 0 - mov si, word [nHidden] - mov di, word [nHidden+2] - add si, word [bsResSectors] - adc di, byte 0 ; DI:SI = first FAT sector - - mov word [fat_start], si - mov word [fat_start+2], di - - mov al, [bsFATs] - cbw - mul word [sectPerFat] ; DX:AX = total number of FAT sectors - - add si, ax - adc di, dx ; DI:SI = first root directory sector - mov word [root_dir_start], si - mov word [root_dir_start+2], di - - ; Calculate how many sectors the root directory occupies. - mov bx, [bsBytesPerSec] - mov cl, 5 ; divide BX by 32 - shr bx, cl ; BX = directory entries per sector - - mov ax, [bsRootDirEnts] - xor dx, dx - div bx - - mov word [RootDirSecs], ax ; AX = sectors per root directory - - add si, ax - adc di, byte 0 ; DI:SI = first data sector - - mov [data_start], si - mov [data_start+2], di -%endmacro - ;----------------------------------------------------------------------- times 0x3E-$+$$ db 0 @@ -216,10 +172,42 @@ dont_use_dl: ; no, rely on [drive] written by SYS mov LBA_SIZE, 10h mov LBA_SECNUM,1 ; initialise LBA packet constants - call print - db "FreeDOS",0 - GETDRIVEPARMS +; GETDRIVEPARMS: Calculate start of some disk areas. +; + mov si, word [nHidden] + mov di, word [nHidden+2] + add si, word [bsResSectors] + adc di, byte 0 ; DI:SI = first FAT sector + + mov word [fat_start], si + mov word [fat_start+2], di + + mov al, [bsFATs] + cbw + mul word [sectPerFat] ; DX:AX = total number of FAT sectors + + add si, ax + adc di, dx ; DI:SI = first root directory sector + mov word [root_dir_start], si + mov word [root_dir_start+2], di + + ; Calculate how many sectors the root directory occupies. + mov bx, [bsBytesPerSec] + mov cl, 5 ; divide BX by 32 + shr bx, cl ; BX = directory entries per sector + + mov ax, [bsRootDirEnts] + xor dx, dx + div bx + + mov word [RootDirSecs], ax ; AX = sectors per root directory + + add si, ax + adc di, byte 0 ; DI:SI = first data sector + + mov [data_start], si + mov [data_start+2], di ; FINDFILE: Searches for the file in the root directory. @@ -235,8 +223,6 @@ dont_use_dl: ; no, rely on [drive] written by SYS mov di, word [RootDirSecs] les bx, [loadsegoff_60] ; es:bx = 60:0 call readDisk - jc jmp_boot_error - les di, [loadsegoff_60] ; es:di = 60:0 @@ -258,10 +244,6 @@ next_entry: mov cx, 11 ffDone: push ax ; store first cluster number -; call print -; db " FAT",0 - - ; GETFATCHAIN: ; @@ -271,20 +253,16 @@ ffDone: ; ; The file must fit in conventional memory, so it can't be larger than ; 640 kb. The sector size must be at least 512 bytes, so the FAT chain -; can't be larger than around 3 kb. +; can't be larger than 2.5 KB (655360 / 512 * 2 = 2560). ; ; Call with: AX = first cluster in chain - ; Load the complete FAT into memory. The FAT can't be larger - ; than 128 kb, so it should fit in the temporary buffer. - les bx, [loadsegoff_60] ; es:bx=60:0 mov di, [sectPerFat] mov ax, word [fat_start] mov dx, word [fat_start+2] call readDisk pop ax ; restore first cluster number -jmp_boot_error: jc boot_error ; Set ES:DI to the temporary storage for the FAT chain. push ds @@ -342,9 +320,6 @@ finished: ; Mark end of FAT chain with 0, so we have a single push cs pop ds - ;call print - ;db " Kernel",0 ; "KERNEL" - ; loadFile: Loads the file into memory, one cluster at a time. @@ -353,10 +328,12 @@ finished: ; Mark end of FAT chain with 0, so we have a single mov si, FATBUF ; set DS:SI to the FAT chain cluster_next: lodsw ; AX = next cluster to read - or ax, ax ; if EOF... - je boot_success ; ...boot was successful + or ax, ax ; EOF? + jne load_next ; no, continue + mov bl,dl ; drive (left from readDisk) + jmp far [loadsegoff_60] ; yes, pass control to kernel - dec ax ; cluster numbers start with 2 +load_next: dec ax ; cluster numbers start with 2 dec ax mov di, word [bsSecPerClust] @@ -365,35 +342,26 @@ cluster_next: lodsw ; AX = next cluster to read add ax, [data_start] adc dx, [data_start+2] ; DX:AX = first sector to read call readDisk - jnc cluster_next + jmp short cluster_next +; shows text after the call to this function. -boot_error: call print - db " err",0 +show: pop si + lodsb ; get character + push si ; stack up potential return address + mov ah,0x0E ; show character + int 0x10 ; via "TTY" mode + cmp al,'.' ; end of string? + jne show ; until done + ret - xor ah,ah - int 0x16 ; wait for a key - int 0x19 ; reboot the machine +boot_error: call show + db "Error! Hit a key to reboot." -boot_success: - ;call print - ;db " GO! ",0 - mov bl, [drive] - jmp far [loadsegoff_60] - - -; prints text after call to this function. - -print_1char: - xor bx, bx ; video page 0 - mov ah, 0x0E ; else print it - int 0x10 ; via TTY mode -print: pop si ; this is the first character -print1: lodsb ; get token - push si ; stack up potential return address - cmp al, 0 ; end of string? - jne print_1char ; until done - ret ; and jump to it + xor ah,ah + int 0x13 ; reset floppy + int 0x16 ; wait for a key + int 0x19 ; reboot the machine ; readDisk: Reads a number of sectors into memory. @@ -401,7 +369,6 @@ print1: lodsb ; get token ; Call with: DX:AX = 32-bit DOS sector number ; DI = number of sectors to read ; ES:BX = destination buffer -; ES must be 64k aligned (1000h, 2000h etc). ; ; Returns: CF set on error ; ES:BX points one byte after the last byte read. @@ -413,6 +380,8 @@ readDisk: push si mov word [LBA_SEG],es mov word [LBA_OFF],bx + call show + db "." read_next: ;******************** LBA_READ ******************************* @@ -487,25 +456,15 @@ read_normal_BIOS: xchg ch, cl ; set cyl no low 8 bits ror cl, 1 ; move track high bits into ror cl, 1 ; bits 7-6 (assumes top = 0) - mov al, byte [sectPerTrack] - sub al, ah ; al has # of sectors left - inc ah ; sector offset from 1 or cl, ah ; merge sector into cylinder + inc cx ; make sector 1-based (1-63) les bx,[LBA_OFF] mov ax, 0x0201 do_int13_read: mov dl, [drive] int 0x13 - -read_finished: - jnc read_ok ; jump if no error - xor ah, ah ; else, reset floppy - int 0x13 -read_next_chained: - jmp short read_next ; read the same sector again - -read_ok: + jc boot_error ; exit on error mov ax, word [bsBytesPerSec] div byte[LBA_PACKET] ; luckily 16 !! add word [LBA_SEG], ax @@ -513,7 +472,7 @@ read_ok: add LBA_SECTOR_0, byte 1 adc LBA_SECTOR_16, byte 0 ; DX:AX = next sector to read dec di ; if there is anything left to read, - jnz read_next_chained ; continue + jnz read_next ; continue mov es,word [LBA_SEG] ; clear carry: unnecessary since adc clears it diff --git a/build.bat b/build.bat index 07841c5..61f0cb5 100644 --- a/build.bat +++ b/build.bat @@ -4,7 +4,7 @@ :- $Id$ :----------------------------------------------------------------------- -:- Syntax: BUILD [-r] [fat32|fat16] [msc|wc|tc|tcpp] [86|186|386] +:- Syntax: BUILD [-r] [fat32|fat16] [msc|wc|tc|tcpp] [86|186|386] [debug] [lfnapi] :- option case is significant !! :----------------------------------------------------------------------- @@ -39,6 +39,9 @@ if "%1" == "86" set XCPU=86 if "%1" == "186" set XCPU=186 if "%1" == "386" set XCPU=386 +if "%1" == "debug" set ALLCFLAGS=%ALLCFLAGS% -DDEBUG +if "%1" == "lfnapi" set ALLCFLAGS=%ALLCFLAGS% -DWITHLFNAPI + shift if not "%1" == "" goto loop_commandline @@ -108,10 +111,13 @@ goto end :----------------------------------------------------------------------- -:abort-cd -cd .. :noenv echo Unable to set necessary environment variables! +goto abort + +:abort-cd +cd .. + :abort echo Compilation was aborted! diff --git a/config.b b/config.b index 5f08918..e17b41c 100644 --- a/config.b +++ b/config.b @@ -109,6 +109,7 @@ set XUPX=upx --8086 --best :----------------------------------------------------------------------- :- select default target: CPU type (default is 86) and :- what FAT system (default is 32) to support +:- NOTE: Turbo C doesn't support 386 CPU. ::set XCPU=86 ::set XCPU=186 diff --git a/defaults.bat b/defaults.bat index 2abde5e..6b711e3 100644 --- a/defaults.bat +++ b/defaults.bat @@ -80,6 +80,7 @@ set MAKE= set XUPX= set XCPU= set XFAT= +set ALLCFLAGS= if not "%OLDPATH%" == "" set PATH=%OLDPATH% set OLDPATH= diff --git a/docs/config.txt b/docs/config.txt index 3bd6b1e..8e98016 100644 --- a/docs/config.txt +++ b/docs/config.txt @@ -1,51 +1,220 @@ -Advanced - FreeDOS specific - CONFIG.SYS processing - -a new command DOSDATA=UMB -DOSDATA=UMB loads some FreeDOS specific stuff in Upper Memory Blocks, -like the RAM that FILESHIGH, LASTDRIVEHIGH, and STACKSHIGH occupy - -a new command ECHO -ECHO does ECHO its argument (surprised ?-) and is executed at -the time the DEVICE= lines are executed. -use it similarly to - - ECHO loading driver 1 - device=Driver1.sys - ECHO driver1 successfully loaded - -a new command called EECHO is also available, for echo-ing ANSI Escape Sequences -(redefines keyboard input for example). +Configuring your DOS system for use: +------------------------------------ +When booting DOS, you will find it only supports a subset of +the devices available on many computers. To support additional +devices and advanced features, device specific driver and +memory resident software most be loaded. This allows the +kernel to be easily extended to support hardware not presently +available and take better advantage of installed hardware +without wasting resources on computers lacking it. This +software is generally loaded during the kernel initialization +phase, with details describing what to load expressed in the +file CONFIG.SYS. The FreeDOS kernel will first look for a +file named FDCONFIG.SYS, should it exist, it will will be used +instead of CONFIG.SYS; this allows the FreeDOS kernel to coexist +and be configured differently than another DOS kernel. There +are additional options available to adjust other aspects of the +kernels behaviour. Note: some options listed below are FreeDOS +specific and will not work when using other/older DOS kernels. +Below is list of all documented FreeDOS config.sys supported +options; additional undocumented options may exist but are not +meant for normal usage. -an undocumented command SCREEN=xx -SCREEN= switches into videomode xxx (INT10/11xx/000) -useful - SCREEN=0x11 -- 28 lines - SCREEN=0x12 -- 43/50 lines (on EGA/VGA) +BREAK +Usage: break=on|off +Set extended Control-C/Control-Break checking to on [default] or off. +When set to on, the kernel will perform the check (and invoke current +handler if pressed) prior to most int 21h calls. When set to off, +the kernel only performs the check on I/O calls using standard streams. +e.g. break=off + +BUFFERS +BUFFERSHIGH +Usage: buffers=nn[,n] where nn is in range 1-99 & n is in range 1-8 +Memory buffers used by the kernel; primary[,secondary] +The secondary buffer option is available for compatibility with +other DOS kernels, but is ignored by the FreeDOS kernel. +e.g. buffers=20 + +COUNTRY +Usage: country=nnn[,[mmm][,[d:][path]file]] +Only limited country=nnn support is presently available. +Enables/sets international features of DOS +nnn is country code (001==US) +mmm is code page (437 is default, 850 is updated form, 1252 for Windows) +[drive][path]file specifies file with country specific data +e.g. country=001,850,C:\FDOS\BIN\COUNTRY.SYS + +DEVICE +Usage: device=[d:][path]file [options] +Load the device driver specified by d:path\file (into conventional +[low 640KB] memory). The options are for the driver itself; refer +to documentation that came with your particular device for supported +options and their usage. +e.g. device=himem.sys + +DEVICEHIGH +Usage: devicehigh=[d:][path]file [options] +This is just like device= statement, except it attempts to load +the device driver into high memory first (failing that it should +load it in conventional memory). +Note: The order you load devices may have a large impact on amount +of free memory available. In general try to load large (in memory +usage) programs into high memory first. +Important: You should have a high memory manager such as FDXMS or +Himem installed (prior device=FDXMS.SYS or device=HIMEM.SYS) before +using this option. +e.g. devicehigh=atapicdd.sys /D:FDCD0001 + +DOS +Usage: dos=high|low,umb|noumb +Indicates whether the kernel should try to load itself into +high memory or only conventional (low), and whether to link +upper memory blocks in with normal memory or not. +Note: only one set need be given, ie dos=high and dos=noumb are ok. +Important: if you specify dos=high[,umb|noumb] then you must also +load a high memory manager (first), ie FDXMS or HIMEM +e.g. dos=high,umb +or dos=low,noumb + +DOSDATA +Usage: dosdata=umb +Try to load kernel data into Upper Memory Blocks; effectively +same as using the HIGH variant of kernel parameters, +such as fileshigh, lastdrivehigh, and stackshigh (does not +effect drivers loaded using device= or install=). +e.g. dosdata=umb + +ECHO +Usage: ECHO Message to be displayed to user. +ECHO displays (echos) its arguments to the console during +config.sys processing when device drivers are loaded (when +DEVICE= lines are executed). +e.g. + ECHO loading driver 1 + device=Driver1.sys + ECHO driver1 successfully loaded + +EECHO +Usage: EECHO Message with ANSI Escape Sequence +EECHO allows for echo-ing ANSI Escape Sequences +(redefines keyboard input for example). Use a dollar sign ($) +to represent the ANSI Escape character. Note: requires an +ansi driver loaded prior to use. + +FCBS +Usage: fcbs=nnn +where nnn is in range 1-255 +Sets the number of File Control Blocks to reserve room for. +As file control blocks have been replaced by file handles +(see files) most applications will not need this value adjusted. +e.g. fcbs=4 + +FILES +FILESHIGH +Usage: files=nnn +where nnn is in range 8-255 (default 8) +Specifies how many files allowed open at once (reserves +memory necessary to support opening this many files). +Note: there are other restrictions, so a given program + may not be able to actually open this many +A good number is 20, though some programs suggest/require +30, 40, or even 255 +e.g. files=20 + +INSTALL +INSTALLHIGH +Usage: install=[d:][path]file [options] +Load the program specified by d:path\file. Generally used to +load TSR (terminate and stay resident) programs with a minimal +environment block. The options are for the program itself; refer +to documentation that came with your particular software for +supported options and usage. +e.g. install=nansi.com + +LASTDRIVE +LASTDRIVEHIGH +Usage: lastdrive=x +where x is last drive letter available for use; A-Z +e.g. lastdrive=z + +NUMLOCK +Usage: numlock=on|off +Set the keyboard number lock to on or off. +e.g. numlock=off + +REM +Usage: rem Your remarks! +This provides the ability to place comments within the configuration +file. The text following the rem until the end of the line is +reached are ignored. This may also be used to temporarily disable +loading a particular device or other option. + +SCREEN +Usage: screen=xx +Switches into videomode xxx (INT10/11xx/000) +where xx should be 0x11 for 28 lines or 0x12 for 43/50 (EGA/VGA) lines + +SET +Usage: set ENVVAR=value +Sets the environment variable to provided value. +e.g. set HOME=C:\home\me + +SHELL +SHELLHIGH +Usage: shell=[d:][path]file [options] +Indicates the shell to use; often used to alter COMMAND.COM's behavior. +Note: it is command.com that processes AUTOEXEC.BAT; by using the +shell option, you can get command.com to process a differently named +file (such as FDAUTO.BAT for coexisting with another DOS using different +configuration options) or run a completely different command interpreter +such as 4DOS or a (unix) sh variant. +e.g. shell=C:\COMMAND.COM /E:256 /P + +STACKS +STACKSHIGH +Usage: stacks=nn,nnn +where nn is in range 0,8-64 and nnn is in range 32-512 +Changes number of stacks available +nn is number of different stacks and nnn is size in bytes of each one +e.g. stacks=16,256 + +SWITCHAR +Usage: switchar=c +Sets the default switchar to character c. Where c is a single character +that is used to indicate a command line parameter is an option switch. +The default is a forward slash (/). Note: This simply sets the value +returned by a get switchar query, it will not effect programs that use +hardcoded switch characters. +e.g. switchar=- + +VERSION +Usage: version=x.y +FreeDOS specific command to specify what DOS version to report. +e.g. version=6.2 -the following advanced config.sys processing options are available: +Advanced - FreeDOS specific CONFIG.SYS menu processing: +------------------------------------------------------- normal FILES=20 DEVICE=MyNetWorkDriver.sys '?' - ALWAYS ask if a single line shall be executed - FILES=20 ?DEVICE=MyNetWorkDriver.sys '!' - NEVER ask if a single line shall be executed, even if single stepping - !FILES=20 !DOS=HIGH,UMB !BUFFERS=30 DEVICE=MyNetWorkDriver.sys - configuration management - you may compose several configurations, using following special commands: @@ -66,8 +235,11 @@ MENUDEFAULT=0,1 ( configuration 0, wait 1 second) 2? device=MyNetworkDriver.SYS -Although this is definitively worse then MSDOS menuing possibilities, -IMHO it's better then nothing. +Although this is different than MSDOS menuing possibilities, it +allows for selecting from multiple options during bootup while +remaining simple. It, however, does not allow for multi-level +menuing based configuration schemes. + It's also possible to combine menu options, to avoid writing thing every time again. @@ -165,11 +337,7 @@ MENUDEFAULT=1,10 ( configuration 1, wait 10 seconds) 4? ECHO You selected menu #4 - - - - - 2002-11-28 - Tom Ehlert 2003-07-15 - Bernd Blaauw -2003-09-18 - Bart Oldeman \ No newline at end of file +2003-09-18 - Bart Oldeman +2004-07-24 - Jeremy Davis diff --git a/docs/contrib.txt b/docs/contrib.txt index f5fede2..15a2570 100644 --- a/docs/contrib.txt +++ b/docs/contrib.txt @@ -1,6 +1,6 @@ These are the known contributors of the FreeDOS kernel. If you have contributed in any way to the kernel, but are not on this list, -please email me at bart@dosemu.org so I can add you to the list! +please email the current kernel maintainer so we can add you to the list! Thanks to all the following for contributing to the FreeDOS kernel: diff --git a/docs/history.txt b/docs/history.txt index f6477f8..ea88b53 100644 --- a/docs/history.txt +++ b/docs/history.txt @@ -1,5 +1,8 @@ 2004 July 8 - UNSTABLE branch -------- Jeremy Davis (jeremyd@computer.org) ++ Changes Bart + * int2f.asm + - bugfix: call_nls: DI register was not preserved + Changes Tom * inthndlr.c - improve handling of case where eg. FindFirst(I:\*.*) fails, causes Int24, @@ -264,6 +267,16 @@ bytes, because Shell=SecPathName+50 and sizeof SecPathName=128). - P_0(): now supported command line without space between command and options (starting from '/'). + * dosfns.c + - common code from DosFindFirst() and DosFindNext() moved to pop_dmp() + - optimization for SftSeek() + * ludivmul.inc + - bugfix: division of long numbers in LDIVMODU macro (used for Watcom) + was wrong. Example: 100000h%8000Fh was gives 0FFFF1h instead 7_FFF1h. + - shorter code. + * inthndlr.c + - fix: INT21/3301 now returns in DL low bit of input value (as in MS-DOS). + - callerARG1 declared as xreg instead UWORD. + Changes Bernd, Aitor, & Arkady * config.c - source: (Bernd) the codepage table rewritten into a smaller layout. @@ -276,6 +289,19 @@ - fix: for MSVC CONST segment should be class CONST, not DATA. * dsk.c - play_dj() now says same words as MS-DOS6. + * boot.asm + - optimize and make more user friendly instead of retrying endlessly + * sys.c + - change OEM Name field to FRDOS4.1 per Eric Auer for better compatibility. + * ludivmul.inc + - 32-bit division code for 386-enabled Watcom kernel. + * inthndlr.c + - fix: for INT21/5F07 and 5F08, before changing bit CDSPHYSDRV, + MS-DOS checks if physical device associated with drive letter. Without + this check MS-FORMAT under FreeDOS was destroys RAMDISK. + + Changes Jeremy + * config.txt + - update to include all CONFIG.SYS options (except ANYDOS) *** Sync - Stable Build 2035 *** 2004 May 30 - Build 2035 diff --git a/drivers/makefile b/drivers/makefile index 978f380..9134834 100644 --- a/drivers/makefile +++ b/drivers/makefile @@ -17,7 +17,7 @@ all: ..\lib\device.lib -$(RM) $*.lib $(LIBUTIL) $(LIBFLAGS) $* $(LIBOBJS) $(LIBTERM) -$(OBJS): $(DEPENDS) +$(OBJS): $(DEPENDS) ../kernel/segs.inc ######################################################################## diff --git a/filelist b/filelist index def97df..b6c5735 100644 --- a/filelist +++ b/filelist @@ -146,6 +146,7 @@ */*/sys/makefile */*/sys/sys.c */*/sys/talloc.c +*/*/sys/turboc.cfg */*/utils/echoto.bat */*/utils/exeflat.c */*/utils/makefile @@ -153,3 +154,4 @@ */*/utils/relocinf.c */*/utils/rmfiles.bat */*/utils/wlinker.bat +*/*/utils/turboc.cfg diff --git a/hdr/dcb.h b/hdr/dcb.h index 32031e3..13bbec0 100644 --- a/hdr/dcb.h +++ b/hdr/dcb.h @@ -80,8 +80,8 @@ struct dpb { ULONG dpb_xdata; ULONG dpb_xsize; /* # of clusters+1 on media */ ULONG dpb_xfatsize; /* # of sectors / FAT */ - ULONG dpb_xrootclst; /* starting cluster of root dir */ - ULONG dpb_xcluster; /* cluster # of first free */ + CLUSTER dpb_xrootclst; /* starting cluster of root dir */ + CLUSTER dpb_xcluster; /* cluster # of first free */ /* -1 if not known */ #endif }; @@ -89,4 +89,3 @@ struct dpb { #define UNKNCLUSTER 0x0000 /* see RBIL INT 21/AH=52 entry */ #define XUNKNCLSTFREE 0xffffffffl /* unknown for DOS */ #define UNKNCLSTFREE 0xffff /* unknown for DOS */ - diff --git a/hdr/device.h b/hdr/device.h index a01bae5..2708a60 100644 --- a/hdr/device.h +++ b/hdr/device.h @@ -174,7 +174,7 @@ typedef struct { /* bits 6-4: reserved (0) */ /* bits 3-0: active FAT number */ UWORD bpb_xfsversion; /* filesystem version */ - ULONG bpb_xrootclst; /* starting cluster of root dir */ + CLUSTER bpb_xrootclst; /* starting cluster of root dir */ UWORD bpb_xfsinfosec; /* FS info sector number, */ /* 0xFFFF if unknown */ UWORD bpb_xbackupsec; /* backup boot sector number */ diff --git a/hdr/dirmatch.h b/hdr/dirmatch.h index c587827..44c5327 100644 --- a/hdr/dirmatch.h +++ b/hdr/dirmatch.h @@ -38,32 +38,25 @@ static BYTE *dirmatch_hRcsId = typedef struct { UBYTE dm_drive; BYTE dm_name_pat[FNAME_SIZE + FEXT_SIZE]; - BYTE dm_attr_srch; + BYTE dm_attr_srch; /* !!! should be UBYTE --avb */ UWORD dm_entry; -#ifdef WITHFAT32 - ULONG dm_dircluster; -#else - UWORD dm_dircluster; + CLUSTER dm_dircluster; +#ifndef WITHFAT32 UWORD reserved; #endif struct { - BITS /* directory has been modified */ - f_dmod:1; - BITS /* directory is the root */ - f_droot:1; - BITS /* fnode is new and needs fill */ - f_dnew:1; - BITS /* fnode is assigned to dir */ - f_ddir:1; - BITS /* filler to avoid a bad bug (feature?) in */ - f_filler:12; /* TC 2.01 */ + BITS f_dmod:1; /* directory has been modified */ + BITS f_droot:1; /* directory is the root */ + BITS f_dnew:1; /* fnode is new and needs fill */ + BITS f_ddir:1; /* fnode is assigned to dir */ + BITS f_filler:12; /* filler to avoid a bad bug */ + /* (feature?) in TC 2.01 */ } dm_flags; /* file flags */ - BYTE dm_attr_fnd; /* found file attribute */ + UBYTE dm_attr_fnd; /* found file attribute */ time dm_time; /* file time */ date dm_date; /* file date */ - LONG dm_size; /* file size */ + ULONG dm_size; /* file size */ BYTE dm_name[FNAME_SIZE + FEXT_SIZE + 2]; /* file name */ } dmatch; - diff --git a/kernel/dosfns.c b/kernel/dosfns.c index ca4639b..5135d4d 100644 --- a/kernel/dosfns.c +++ b/kernel/dosfns.c @@ -308,22 +308,27 @@ long DosRWSft(int sft_idx, size_t n, void FAR * bp, int mode) } } -COUNT SftSeek(int sft_idx, LONG new_pos, COUNT mode) +COUNT SftSeek(int sft_idx, LONG new_pos, unsigned mode) { sft FAR *s = idx_to_sft(sft_idx); if (FP_OFF(s) == (size_t) -1) return DE_INVLDHNDL; /* Test for invalid mode */ - if (mode < 0 || mode > 2) + if (mode > SEEK_END) /* 2 */ return DE_INVLDFUNC; lpCurSft = s; if (s->sft_flags & SFT_FSHARED) { + /* SEEK_SET handled below (s->sft_posit=new_pos) */ + if (mode == SEEK_CUR) + { + new_pos += s->sft_posit; + } /* seek from end of file */ - if (mode == 2) + else if (mode == SEEK_END) { /* * RB list has it as Note: @@ -336,41 +341,24 @@ COUNT SftSeek(int sft_idx, LONG new_pos, COUNT mode) * Mfs.c looks for these mode bits set, so here is my best guess.;^) */ if (s->sft_mode & (O_DENYREAD | O_DENYNONE)) - s->sft_posit = remote_lseek(s, new_pos); + new_pos = remote_lseek(s, new_pos); else - s->sft_posit = s->sft_size + new_pos; - return SUCCESS; + new_pos += s->sft_size; } - if (mode == 0) - { - s->sft_posit = new_pos; - return SUCCESS; - } - if (mode == 1) - { - s->sft_posit += new_pos; - return SUCCESS; - } - return DE_INVLDFUNC; } - /* Do special return for character devices */ - if (s->sft_flags & SFT_FDEVICE) + else if (s->sft_flags & SFT_FDEVICE) { - s->sft_posit = 0l; - return SUCCESS; + new_pos = 0; } else { - LONG result = dos_lseek(s->sft_status, new_pos, mode); - if (result < 0l) - return (int)result; - else - { - s->sft_posit = result; - return SUCCESS; - } + if ((new_pos = dos_lseek(s->sft_status, new_pos, mode)) < 0) + return (int)new_pos; } + + s->sft_posit = new_pos; + return SUCCESS; } ULONG DosSeek(unsigned hndl, LONG new_pos, COUNT mode) @@ -1018,22 +1006,26 @@ COUNT DosChangeDir(BYTE FAR * s) return SUCCESS; } -STATIC VOID pop_dmp(dmatch FAR * dmp) +STATIC int pop_dmp(int rc, dmatch FAR * save_dta) { - dmp->dm_attr_fnd = (BYTE) SearchDir.dir_attrib; - dmp->dm_time = SearchDir.dir_time; - dmp->dm_date = SearchDir.dir_date; - dmp->dm_size = (LONG) SearchDir.dir_size; - ConvertName83ToNameSZ(dmp->dm_name, (BYTE FAR *) SearchDir.dir_name); + dta = save_dta; + if (rc == SUCCESS) + { + fmemcpy(save_dta, &sda_tmp_dm, 21 /*offsetof(save_dta->dm_attr_fnd)*/ ); + save_dta->dm_attr_fnd = SearchDir.dir_attrib; + save_dta->dm_time = SearchDir.dir_time; + save_dta->dm_date = SearchDir.dir_date; + save_dta->dm_size = SearchDir.dir_size; + ConvertName83ToNameSZ(save_dta->dm_name, SearchDir.dir_name); + } + return rc; } -COUNT DosFindFirst(UCOUNT attr, BYTE FAR * name) +COUNT DosFindFirst(UCOUNT attr, const char FAR * name) { - int rc; - register dmatch FAR *dmp = dta; - - rc = truename(name, PriPathName, - CDS_MODE_CHECK_DEV_PATH | CDS_MODE_ALLOW_WILDCARDS); + dmatch FAR *save_dta = dta; + int rc = truename(name, PriPathName, + CDS_MODE_CHECK_DEV_PATH | CDS_MODE_ALLOW_WILDCARDS); if (rc < SUCCESS) return rc; @@ -1065,32 +1057,26 @@ COUNT DosFindFirst(UCOUNT attr, BYTE FAR * name) SearchDir.dir_attrib = D_DEVICE; SearchDir.dir_time = dos_gettime(); SearchDir.dir_date = dos_getdate(); - p = (char *)FP_OFF(get_root(PriPathName)); - memset(SearchDir.dir_name, ' ', FNAME_SIZE + FEXT_SIZE); + p = (const char *)get_root(PriPathName); for (i = 0; i < FNAME_SIZE && *p && *p != '.'; i++) SearchDir.dir_name[i] = *p++; + for (; i < FNAME_SIZE + FEXT_SIZE; i++) + SearchDir.dir_name[i] = ' '; rc = SUCCESS; /* /// End of additions. - Ron Cemer ; heavily edited - Bart Oldeman */ } else rc = dos_findfirst(attr, PriPathName); - dta = dmp; - if (rc == SUCCESS) - { - fmemcpy(dta, &sda_tmp_dm, 21); - pop_dmp(dmp); - } - return rc; + return pop_dmp(rc, save_dta); } COUNT DosFindNext(void) { - COUNT rc; - register dmatch FAR *dmp = dta; + dmatch FAR *save_dta = dta; - /* findnext will always fail on a device name device name or volume id */ - if (dmp->dm_attr_fnd & (D_DEVICE | D_VOLID)) + /* findnext will always fail on a device name or volume id */ + if (save_dta->dm_attr_fnd & (D_DEVICE | D_VOLID)) return DE_NFILES; /* @@ -1111,21 +1097,13 @@ COUNT DosFindNext(void) * (12h, DE_NFILES) */ #if 0 - printf("findnext: %d\n", dmp->dm_drive); + printf("findnext: %d\n", save_dta->dm_drive); #endif - fmemcpy(&sda_tmp_dm, dmp, 21); + fmemcpy(dta = &sda_tmp_dm, save_dta, 21 /*offsetof(save_dta->dm_attr_fnd)*/ ); memset(&SearchDir, 0, sizeof(struct dirent)); - dta = &sda_tmp_dm; - rc = (sda_tmp_dm.dm_drive & 0x80) ? - network_redirector_fp(REM_FINDNEXT, &sda_tmp_dm) : dos_findnext(); - - dta = dmp; - if (rc == SUCCESS) - { - fmemcpy(dmp, &sda_tmp_dm, 21); - pop_dmp(dmp); - } - return rc; + return pop_dmp(sda_tmp_dm.dm_drive & 0x80 + ? network_redirector_fp(REM_FINDNEXT, &sda_tmp_dm) + : dos_findnext(), save_dta); } COUNT DosGetFtime(COUNT hndl, date * dp, time * tp) diff --git a/kernel/dsk.c b/kernel/dsk.c index 39acd12..2b65b24 100644 --- a/kernel/dsk.c +++ b/kernel/dsk.c @@ -711,7 +711,7 @@ STATIC WORD Genblkdev(rqptr rp, ddt * pddt) break; } case 0x67: /* get access flag */ - rp->r_ai->AI_Flag = (descflags / DF_NOACCESS) & 1; /* bit 9 */ + rp->r_ai->AI_Flag = (UBYTE)~(descflags / DF_NOACCESS) & 1; /* bit 9 */ break; default: return failure(E_CMD); @@ -804,32 +804,22 @@ STATIC WORD dskerr(COUNT code) translate LBA sectors into CHS addressing */ -STATIC int LBA_to_CHS(ULONG LBA_address, struct CHS *chs, const ddt * pddt) +STATIC void LBA_to_CHS(ULONG LBA_address, struct CHS *chs, const ddt * pddt) { /* we need the defbpb values since those are taken from the BIOS, not from some random boot sector, except when we're dealing with a floppy */ - const bpb *pbpb = hd(pddt->ddt_descflags) ? &pddt->ddt_defbpb : &pddt->ddt_bpb; - unsigned hs = pbpb->bpb_nsecs * pbpb->bpb_nheads; - unsigned hsrem = (unsigned)(LBA_address % hs); - - LBA_address /= hs; - - if (LBA_address > 1023ul) + const bpb *p = hd(pddt->ddt_descflags) ? &pddt->ddt_defbpb : &pddt->ddt_bpb; + unsigned hs = p->bpb_nsecs * p->bpb_nheads; + chs->Cylinder = 0xffffu; + if (hs > hiword(LBA_address)) /* LBA_address < hs * 0x10000ul */ { -#ifdef DEBUG - printf("LBA-Transfer error : cylinder %lu > 1023\n", LBA_address); -#else - put_string("LBA-Transfer error : cylinder > 1023\n"); -#endif - return 1; + chs->Cylinder = (unsigned)(LBA_address / hs); + hs = (unsigned)(LBA_address % hs); + chs->Head = hs / p->bpb_nsecs; + chs->Sector = hs % p->bpb_nsecs + 1; } - - chs->Cylinder = (UWORD)LBA_address; - chs->Head = hsrem / pbpb->bpb_nsecs; - chs->Sector = hsrem % pbpb->bpb_nsecs + 1; - return 0; } /* Test for 64K boundary crossing and return count small */ @@ -945,8 +935,16 @@ STATIC int LBA_Transfer(ddt * pddt, UWORD mode, VOID FAR * buffer, else { /* transfer data, using old bios functions */ struct CHS chs; - if (LBA_to_CHS(LBA_address, &chs, pddt)) + LBA_to_CHS(LBA_address, &chs, pddt); + if (chs.Cylinder > 1023u) + { +#ifdef DEBUG + printf("IO error: cylinder (%u) > 1023\n", chs.Cylinder); +#else + put_string("IO error: cylinder > 1023\n"); +#endif return failure(E_CMD); /*dskerr(1)*/ + } /* avoid overflow at end of track */ if (count > pddt->ddt_bpb.bpb_nsecs + 1 - chs.Sector) diff --git a/kernel/int2f.asm b/kernel/int2f.asm index 73369ab..e88c388 100644 --- a/kernel/int2f.asm +++ b/kernel/int2f.asm @@ -411,6 +411,7 @@ _call_nls: push bp mov bp, sp push si + push di mov al, [bp + 4] ; subfct mov ah, 0x14 mov si, [bp + 6] ; nlsinfo @@ -427,6 +428,7 @@ _call_nls: jz nostore mov [bp], bx nostore: + pop di pop si pop bp ret diff --git a/kernel/inthndlr.c b/kernel/inthndlr.c index 11999aa..752c4f0 100644 --- a/kernel/inthndlr.c +++ b/kernel/inthndlr.c @@ -74,21 +74,18 @@ VOID ASMCFUNC int21_syscall(iregs FAR * irp) setvec(irp->AL, (intvec)MK_FP(irp->DS, irp->DX)); break; - /* DosVars - get/set dos variables */ - case 0x33: + case 0x33: /* DosVars - get/set dos variables */ switch (irp->AL) { - /* Get Ctrl-C flag */ - case 0x00: + case 0x01: /* Set Ctrl-C flag */ + break_ena = irp->DL & 1; + /* fall through so DL only low bit (as in MS-DOS) */ + + case 0x00: /* Get Ctrl-C flag */ irp->DL = break_ena; break; - /* Set Ctrl-C flag */ - case 0x01: - break_ena = irp->DL & 1; - break; - - case 0x02: /* andrew schulman: get/set extended control break */ + case 0x02: /* andrew schulman: get/set extended control break */ { UBYTE tmp = break_ena; break_ena = irp->DL & 1; @@ -1247,31 +1244,31 @@ dispatch: case 0x5f: if (lr.AL == 7 || lr.AL == 8) { - struct cds FAR *cdsp = &CDSp[lr.DL]; - if (lr.DL >= lastdrive || FP_OFF(cdsp->cdsDpb) == 0) + if (lr.DL < lastdrive) { - rc = DE_INVLDDRV; - goto error_exit; + struct cds FAR *cdsp = CDSp + lr.DL; + if (FP_OFF(cdsp->cdsDpb)) /* letter of physical drive? */ + { + cdsp->cdsFlags &= ~CDSPHYSDRV; + if (lr.AL == 7) + cdsp->cdsFlags |= CDSPHYSDRV; + break; + } } - if (lr.AL == 7) - cdsp->cdsFlags |= CDSPHYSDRV; - else - cdsp->cdsFlags &= ~CDSPHYSDRV; + rc = DE_INVLDDRV; + goto error_exit; } - else + + rc = -(int)network_redirector_mx(REM_DOREDIRECT, &lr, (void *)Int21AX); + /* the remote function manipulates *r directly !, + so we should not copy lr to r here */ + r->AX = rc; + if (rc != SUCCESS) { - rc = (int)network_redirector_mx(REM_DOREDIRECT, &lr, (void *)Int21AX); - /* the remote function manipulates *r directly !, - so we should not copy lr to r here */ - if (rc != SUCCESS) - { - CritErrCode = -rc; /* Maybe set */ - SET_CARRY_FLAG(); - } - r->AX = -rc; - goto real_exit; + SET_CARRY_FLAG(); + CritErrCode = rc; /* Maybe set */ } - break; + goto real_exit; case 0x60: /* TRUENAME */ rc = DosTruename(MK_FP(lr.DS, lr.SI), adjust_far(FP_ES_DI)); @@ -1633,9 +1630,10 @@ STATIC VOID StartTrace(VOID) } #endif -/* this function is called from an assembler wrapper function - and serves the internal dos calls - int2f/12xx and int2f/4a01,4a02. +/* this function is called from an assembler wrapper function and + serves the internal dos calls - int2f/12xx and int2f/4a01,4a02 */ + struct int2f12regs { #ifdef I386 #ifdef __WATCOMC__ @@ -1654,7 +1652,7 @@ struct int2f12regs { UWORD di, si, bp; xreg b, d, c, a; UWORD ip, cs, flags; - UWORD callerARG1; /* used if called from INT2F/12 */ + xreg callerARG1; /* used if called from INT2F/12 */ }; /* WARNING: modifications in `r' are used outside of int2F_12_handler() @@ -1694,12 +1692,12 @@ VOID ASMCFUNC int2F_12_handler(struct int2f12regs r) r.DS = FP_SEG(&nul_dev); break; - case 0x06: /* invoke critical error */ - - /* code, drive number, error, device header */ - r.AL = CriticalError(r.callerARG1 >> 8, - (r.callerARG1 & (EFLG_CHAR << 8)) ? 0 : - r.callerARG1 & 0xff, r.DI, MK_FP(r.BP, r.SI)); + case 0x06: /* invoke critical error */ + /* code, drive number, error, device header */ + r.AL = CriticalError(r.callerARG1.b.h, + (r.callerARG1.b.h & EFLG_CHAR) + ? 0 : r.callerARG1.b.l, + r.DI, MK_FP(r.BP, r.SI)); break; case 0x08: /* decrease SFT reference count */ @@ -1757,18 +1755,15 @@ VOID ASMCFUNC int2F_12_handler(struct int2f12regs r) break; } - case 0x12: /* get length of asciiz string */ - + case 0x12: /* get length of asciiz string */ r.CX = fstrlen(MK_FP(r.ES, r.DI)) + 1; - break; - case 0x13: - /* uppercase character */ - /* for now, ASCII only because nls.c cannot handle DS!=SS */ - r.AL = (unsigned char)r.callerARG1; - if (r.AL >= 'a' && r.AL <= 'z') - r.AL -= 'a' - 'A'; + case 0x13: /* uppercase character */ + /* for now, ASCII only because nls.c cannot handle DS!=SS */ + r.AL = r.callerARG1.b.l; + if (_islower(r.AL)) + r.AL -= (UBYTE)('a' - 'A'); break; case 0x16: @@ -1805,10 +1800,9 @@ VOID ASMCFUNC int2F_12_handler(struct int2f12regs r) ; ; probable use: get sizeof(CDSentry) */ - { - struct cds FAR *cdsp = get_cds(r.callerARG1 & 0xff); - - if (cdsp == NULL) + { + const struct cds FAR *cdsp; + if ((cdsp = get_cds(r.callerARG1.b.l)) == NULL) { r.FLAGS |= FLG_CARRY; break; @@ -1817,7 +1811,7 @@ VOID ASMCFUNC int2F_12_handler(struct int2f12regs r) r.SI = FP_OFF(cdsp); r.FLAGS &= ~FLG_CARRY; break; - } + } case 0x18: /* get caller's registers */ @@ -1880,6 +1874,15 @@ VOID ASMCFUNC int2F_12_handler(struct int2f12regs r) r.FLAGS &= ~FLG_CARRY; break; + /* 0x26-0x29 & 0x2B, internal functions necessary for NLSFUNC */ + case 0x26: /* Open File */ + case 0x27: /* Close File */ + case 0x28: /* Move File Pointer */ + case 0x29: /* Read From File */ + case 0x2B: /* IOctl */ + r.FLAGS |= FLG_CARRY; /* Not implemented yet! */ + break; + case 0x2c: /* added by James Tabor For Zip Drives Return Null Device Pointer */ /* by UDOS+RBIL: get header of SECOND device driver in device chain, diff --git a/kernel/ioctl.c b/kernel/ioctl.c index 3ad15af..63b5674 100644 --- a/kernel/ioctl.c +++ b/kernel/ioctl.c @@ -124,11 +124,20 @@ COUNT DosDevIOctl(lregs * r) attr = dev->dh_attr; break; + case 0x0d: + /* NOTE: CX checked before check if get_dpb()->dpb_device->dh_attr + contains ATTR_GENIOCTL bit set + */ + if ((r->CX & ~0x4021) == 0x084A) + { /* 084A/484A, 084B/484B, 086A/486A, 086B/486B */ + r->AX = 0; /* (lock/unlock logical/physical volume) */ + return SUCCESS; /* simulate success for MS-DOS 7+ SCANDISK etc. --LG */ + } + case 0x04: case 0x05: case 0x08: case 0x09: - case 0x0d: case 0x0e: case 0x0f: case 0x11: @@ -258,17 +267,10 @@ COUNT DosDevIOctl(lregs * r) break; } - case 0x0d: - if ((r->CX & ~0x4021) == 0x084A) - { /* 084A/484A, 084B/484B, 086A/486A, 086B/486B */ - r->AX = 0; /* (lock/unlock logical/physical volume) */ - break; /* simulate success for MS-DOS 7+ SCANDISK etc. --LG */ - } - /* fall through */ - case 0x04: case 0x05: case 0x08: + case 0x0d: case 0x11: execrequest: execrh(&CharReqHdr, dev); diff --git a/kernel/ludivmul.inc b/kernel/ludivmul.inc index decf779..966d271 100644 --- a/kernel/ludivmul.inc +++ b/kernel/ludivmul.inc @@ -1,21 +1,26 @@ -; this one adapted from elks, http://elks.sourceforge.net -; multiply cx:bx * dx:ax, result in dx:ax +; this one adapted from elks, http://elks.sourceforge.net +; multiply cx:bx * dx:ax, result in dx:ax +; optimized by Arkady Belousov: +; dx:ax * cx:bx +; = xh:xl * yh:yl +; = xh:xl*yh*w + xh:xl*yl +; = [xh*yh*w*w +] (xl*yh + xh*yl)*w + xl*yl %macro LMULU 0 - push si - push cx - mov si, ax ; save _ax in si - mov ax, bx ; cx:ax = _cx:_bx - mul dx ; dx:ax = _bx*_dx (forget dx) - xchg cx, ax ; cx = low(_dx*_bx) - mul si ; dx:ax = _cx*_ax (forget dx) - add cx, ax ; cx = low(_cx*_ax + _dx*_bx) - mov ax, si ; restore _ax - mul bx ; dx:ax = _bx*_ax - add dx, cx ; dx = high(_bx*_ax)+low(_cx*_ax + _dx*_bx) - pop cx - pop si + push cx + push si + xchg si,ax ; si=xl (XCHG instead MOV) + xchg ax,dx ; ax=xh (XCHG instead MOV) + mul bx ; dx:ax=xh*yl (forget dx) + xchg cx,ax ; cx=low(xh*yl), ax=yh + mul si ; dx:ax=xl*yh (forget dx) + add cx,ax ; cx=low(xl*yh+xh*yl) + xchg ax,si ; ax=xl (XCHG instead MOV) + mul bx ; dx:ax=xl*yl + add dx,cx + pop si + pop cx ret %endmacro @@ -25,86 +30,111 @@ %macro LDIVMODU 0 ; this one is adapted from an assembly gem: ; gem writer: Norbert Juffa, norbert.juffa@amd.com - ; Dividing 64-bit unsigned integers Assembler / 80386 - -; Here is a division routine for dividing two 64-bit unsigned integers. -; I derived it by modifying some old -; 16-bit code for dividing 32-bit integers that I did several years ago for a -; Turbo-Pascal replacement library. -; If a 64-bit signed integer division is needed, appropriate shell code for -; this routine can easily be written. -; ; (adapted back to 32-bit by Bart Oldeman ;-)) -; -; __U4D divides two unsigned long numbers, the dividend and the divisor +; ...bugfixed and optimized by Arkady Belousov. + +; This macro divides two unsigned long numbers, the dividend and the divisor ; resulting in a quotient and a remainder. ; ; input: -; dx:ax = dividend -; cx:bx = divisor -; +; dx:ax = dividend (x=xh:xl) +; cx:bx = divisor (y=yh:yl) ; output: -; dx:ax = quotient of division of dividend by divisor -; cx:bx = remainder of division of dividend by divisor -; +; dx:ax = quotient of division of dividend by divisor (q=x/y) +; cx:bx = remainder of division of dividend by divisor (r=x%y) ; destroys: ; flags ; +%if XCPU < 386 - test cx, cx ; divisor > 2^32-1 ? - jnz %%big_divisor ; yes, divisor > 32^32-1 - cmp dx, bx ; only one division needed ? (ecx = 0) - jb %%one_div ; yes, one division sufficient + jcxz %%div3216 ; cx=0 -> divisor < 2^16 + push si ; save temp + push di ; variables - xchg cx, ax ; save dividend-lo in cx, ax=0 - xchg ax, dx ; get dividend-hi in ax, dx=0 - div bx ; quotient-hi in eax - xchg ax, cx ; cx = quotient-hi, ax =dividend-lo + push dx ; save + push ax ; dividend x + mov si,bx ; si=yl + mov di,cx ; di:si=cx:bx=y -%%one_div: - div bx ; ax = quotient-lo - mov bx, dx ; bx = remainder-lo - mov dx, cx ; dx = quotient-hi(quotient in dx:ax) - xor cx, cx ; cx = remainder-hi (rem. in cx:bx) - ret - -%%big_divisor: - push si ; save temp - push di ; variables - push dx ; save - push ax ; dividend - mov si, bx ; divisor now in - mov di, cx ; di:bx and cx:si %%shift_loop: - shr dx, 1 ; shift both - rcr ax, 1 ; divisor and - shr di, 1 ; and dividend - rcr bx, 1 ; right by 1 bit - jnz %%shift_loop ; loop if di non-zero (rcr does not touch ZF) - mov di, cx ; restore original divisor (di:si) - div bx ; compute quotient - pop bx ; get dividend lo-word - mov cx, ax ; save quotient - mul di ; quotient * divisor hi-word (low only) - xchg ax, di ; save in di - mov ax, cx ; ax=quotient - mul si ; quotient * divisor lo-word - add dx, di ; dx:ax = quotient * divisor - sub bx, ax ; dividend-lo - (quot.*divisor)-lo - mov ax, cx ; get quotient - pop cx ; restore dividend hi-word - sbb cx, dx ; subtract divisor * quot. from dividend - sbb dx, dx ; 0 if remainder > 0, else FFFFFFFFh - and si, dx ; nothing to add - and di, dx ; back if remainder positive - add bx, si ; correct remaider - adc cx, di ; and quotient if - add ax, dx ; necessary - xor dx, dx ; clear hi-word of quot (ax<=FFFFFFFFh) - pop di ; restore temp - pop si ; variables + shr dx,1 ; shift both + rcr ax,1 ; divisor and + shr cx,1 ; and dividend + rcr bx,1 ; right by 1 bit (rcr preserves ZF) + jnz %%shift_loop ; until zero in cx (divisor < 2^16) + div bx ; ax=quotient q, di:si=y + + mov cx,ax ; cx=q + mul di ; dx:ax=q*yh (forget dx) + xchg bx,ax ; bx=low(q*yh) (XCHG instead MOV) + mov ax,cx ; ax=q + mul si ; dx:ax=q*yl + add dx,bx ; dx:ax=q*y, cx=q + + pop bx ; bx=xl + sub bx,ax ; bx=xl-low(q*y) + xchg ax,cx ; ax=q (XCHG instead MOV) + pop cx ; cx=xh + sbb cx,dx ; cx:bx=x-q*y=remainder r, ax=q + + jae %%div_done ; if remainder < 0 + add bx,si + adc cx,di ; correct remainder (r+=y) + dec ax ; and quotient (q-=1) +%%div_done: + xor dx,dx ; dx:ax=0:q=q + + pop di ; restore temp + pop si ; variables ret -%endmacro \ No newline at end of file +; dx:ax=x, bx=y, cx=0 +; x=xh:xl=xh*w+xl=[xh/y]*y*w+xh%y*w+xl=[xh/y]*y*w+xt +; w=2^16, xh=x/w, xl=x%w, xt=xh%y*w+xl +; remainder = x%y = xt%y +; quotient = [x/y] = [xh/y]*w+xt/y + +%%div3216: + cmp dx,bx ; xh < y ? + jb %%one_div ; yes, one division sufficient + + xchg cx,ax ; ax=0, cx=xl + xchg ax,dx ; dx:ax=0:xh, cx=xl + div bx ; ax=xh/y, dx=xh%y, cx=xl + xchg ax,cx ; dx:ax=xh%y*w+xl=xt, cx=xh/y + +%%one_div: + div bx ; ax=xt/y, dx=xt%d=x%d, cx=xh/y + mov bx,dx ; bx=x%d + mov dx,cx ; dx:ax=xh/y*w+xt/y=x/y + xor cx,cx ; cx:bx=x%d + ret + +%else ; XCPU >= 386 (Svilen Stoianov and Luchezar Georgiev, Varna, Bulgaria) + + push eax ; save eax.high + pop ax + push edx ; save edx.high + push ax + pop eax ; eax=x + push ecx ; save ecx.high + push bx + pop ecx ; ecx=y + + xor edx,edx + div ecx ; eax=q, edx=r + + push edx + pop bx + pop ecx ; restore ecx.high, cx:bx=r + push eax + pop ax + pop edx ; restore edx.high, dx:ax=q + push ax + pop eax ; restore eax.high + ret + +%endif +%endmacro diff --git a/kernel/main.c b/kernel/main.c index 9d453e8..4262859 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -195,6 +195,12 @@ STATIC void PSPInit(void) /* this area reused for master environment */ /*p->ps_cmd.ctCount = 0;*/ /* local command line */ /*p->ps_cmd.ctBuffer[0] = '\r';*/ /* command tail */ + + /* !!! dirty hack: because bug in old FreeCOM, which wrongly + process empty environment in MS-DOS style, garbage empty + environment by dummy variable: --avb + */ + fmemcpy(&p->ps_cmd, "PATH=.", 6/*strlen("PATH=.")*/); } #ifndef __WATCOMC__ @@ -328,8 +334,10 @@ STATIC VOID FsConfig(VOID) for (i = 0; i < LoL->lastdrive; i++) { struct cds FAR *pcds_table = &LoL->CDSp[i]; - fmemcpy(pcds_table->cdsCurrentPath, "A:\\\0", 4); - pcds_table->cdsCurrentPath[0] += i; + pcds_table->cdsCurrentPath[0] = 'A' + i; + pcds_table->cdsCurrentPath[1] = ':'; + pcds_table->cdsCurrentPath[2] = '\\'; + pcds_table->cdsCurrentPath[3] = '\0'; pcds_table->cdsFlags = 0; if (i < LoL->nblkdev && (LONG) dpb != -1l) { diff --git a/kernel/nls.c b/kernel/nls.c index 6810dbe..8e6f0c1 100644 --- a/kernel/nls.c +++ b/kernel/nls.c @@ -122,8 +122,14 @@ COUNT muxLoadPkg(UWORD cp, UWORD cntry) /* make sure the NLSFUNC ID is updated */ #error "NLS_FREEDOS_NLSFUNC_VERSION == NLS_FREEDOS_NLSFUNC_ID" #endif - if (muxGo(0, 0, NLS_FREEDOS_NLSFUNC_VERSION, 0, NLS_FREEDOS_NLSFUNC_ID, 0, - (UWORD *)&id) != 0x14ff) + /* Install check must pass the FreeDOS NLSFUNC version as codepage (cp) and + the FreeDOS NLSFUNC ID as buffer size (bufsize). If they match the + version in NLSFUNC, on return it will set BX (cp on entry) to FreeDOS + NLSFUNC ID. If not NULL, call_nls will set *id = BX on return. + Note: &id should be the pointer offset addressable via SS (SS:BP == &id) + */ + if (muxGo(NLSFUNC_INSTALL_CHECK, 0, NLS_FREEDOS_NLSFUNC_VERSION, + 0, NLS_FREEDOS_NLSFUNC_ID, 0, (UWORD *)&id) != 0x14ff) return DE_FILENOTFND; /* No NLSFUNC --> no load */ if (id != NLS_FREEDOS_NLSFUNC_ID) /* FreeDOS NLSFUNC will return */ return DE_INVLDACC; /* This magic number */ diff --git a/kernel/proto.h b/kernel/proto.h index f72c898..8ed745a 100644 --- a/kernel/proto.h +++ b/kernel/proto.h @@ -77,11 +77,14 @@ long cooked_write(struct dhdr FAR **pdev, size_t n, char FAR *bp); sft FAR *get_sft(UCOUNT); /* dosfns.c */ +#define SEEK_SET 0 +#define SEEK_CUR 1 +#define SEEK_END 2 const char FAR *get_root(const char FAR *); BOOL check_break(void); UCOUNT GenericReadSft(sft far * sftp, UCOUNT n, void FAR * bp, COUNT * err, BOOL force_binary); -COUNT SftSeek(int sft_idx, LONG new_pos, COUNT mode); +COUNT SftSeek(int sft_idx, LONG new_pos, unsigned mode); /*COUNT DosRead(COUNT hndl, UCOUNT n, BYTE FAR * bp, COUNT FAR * err); */ void BinarySftIO(int sft_idx, void *bp, int mode); #define BinaryIO(hndl, bp, mode) BinarySftIO(get_sft_idx(hndl), bp, mode) @@ -101,7 +104,7 @@ BOOL DosGetFree(UBYTE drive, UWORD * spc, UWORD * navc, UWORD * bps, UWORD * nc); COUNT DosGetCuDir(UBYTE drive, BYTE FAR * s); COUNT DosChangeDir(BYTE FAR * s); -COUNT DosFindFirst(UCOUNT attr, BYTE FAR * name); +COUNT DosFindFirst(UCOUNT attr, const char FAR * name); COUNT DosFindNext(void); COUNT DosGetFtime(COUNT hndl, date * dp, time * tp); COUNT DosSetFtimeSft(int sft_idx, date dp, time tp); @@ -374,7 +377,6 @@ void child_psp(seg_t para, seg_t cur_psp, seg_t beyond); void return_user(void); COUNT DosExec(COUNT mode, exec_blk FAR * ep, BYTE FAR * lp); ULONG SftGetFsize(int sft_idx); -VOID InitPSP(VOID); #ifdef __WATCOMC__ # pragma aux return_user aborts #endif diff --git a/kernel/task.c b/kernel/task.c index 1d5b6bd..4e578d1 100644 --- a/kernel/task.c +++ b/kernel/task.c @@ -303,7 +303,7 @@ static void load_transfer(seg_t ds, exec_blk *ep, int mode) if (mode == LOADNGO) { /* build the user area on the stack */ - iregs FAR *irp = (iregs FAR *)(ep->exec.stack - sizeof(iregs)); + iregs FAR *irp = (iregs FAR *)ep->exec.stack - 1; /* start allocating REGs (as in MS-DOS - some demos expect them so --LG) */ /* see http://www.beroset.com/asm/showregs.asm */ diff --git a/kernel/vc.cfg b/kernel/vc.cfg deleted file mode 100644 index af2a42c..0000000 --- a/kernel/vc.cfg +++ /dev/null @@ -1,5 +0,0 @@ --batch -nologo -WX --Zlp1 --f- -Osb1V4e -Gsry --Fc --I..\hdr diff --git a/sys/fdkrncfg.c b/sys/fdkrncfg.c index 36648bd..55daef2 100644 --- a/sys/fdkrncfg.c +++ b/sys/fdkrncfg.c @@ -59,10 +59,6 @@ typedef signed short sword; typedef unsigned long dword; typedef signed long sdword; -/* These structures need to be byte packed, if your compiler - does not do this by default, add the appropriate command, - such as #pragma pack(1) here, protected with #ifdefs of course. -*/ /* Displays command line syntax */ void showUsage(void) diff --git a/sys/sys.c b/sys/sys.c index ee402fe..5d30140 100644 --- a/sys/sys.c +++ b/sys/sys.c @@ -29,7 +29,7 @@ #define DEBUG /* #define DDEBUG */ -#define SYS_VERSION "v3.2" +#define SYS_VERSION "v3.3" #include #include @@ -483,13 +483,13 @@ void truename(char far *dest, const char *src); "int 0x21" \ parm [es di] [si]; -int generic_block_ioctl(unsigned char drive, unsigned cx, unsigned char *par); +int generic_block_ioctl(unsigned drive, unsigned cx, unsigned char *par); #pragma aux generic_block_ioctl = \ "mov ax, 0x440d" \ "int 0x21" \ "sbb ax, ax" \ value [ax] \ - parm [bl] [cx] [dx]; + parm [bx] [cx] [dx]; /* BH must be 0 for lock! */ #else @@ -541,14 +541,14 @@ void reset_drive(int DosDrive) intdos(®s, ®s); } /* reset_drive */ -int generic_block_ioctl(unsigned char drive, unsigned cx, unsigned char *par) +int generic_block_ioctl(unsigned drive, unsigned cx, unsigned char *par) { union REGS regs; regs.x.ax = 0x440d; regs.x.cx = cx; regs.x.dx = (unsigned)par; - regs.h.bl = drive + 1; + regs.x.bx = drive; /* BH must be 0 for lock! */ intdos(®s, ®s); return regs.x.cflag; } /* generic_block_ioctl */ @@ -692,7 +692,7 @@ void put_boot(int drive, char *bsFile, char *kernel_name, int load_seg, int both #endif /* lock drive */ - generic_block_ioctl((unsigned char)drive + 1, 0x84a, NULL); + generic_block_ioctl(drive + 1, 0x84a, NULL); reset_drive(drive); /* suggestion: allow reading from a boot sector or image file here */ @@ -752,7 +752,7 @@ void put_boot(int drive, char *bsFile, char *kernel_name, int load_seg, int both printf("FAT type: FAT32\n"); /* get default bpb (but not for floppies) */ if (drive >= 2 && - generic_block_ioctl((unsigned char)drive + 1, 0x4860, default_bpb) == 0) + generic_block_ioctl(drive + 1, 0x4860, default_bpb) == 0) correct_bpb((struct bootsectortype *)(default_bpb + 7 - 11), bs); #ifdef WITHFAT32 /* copy one of the FAT32 boot sectors */ @@ -767,7 +767,7 @@ void put_boot(int drive, char *bsFile, char *kernel_name, int load_seg, int both { /* copy the FAT12/16 CHS+LBA boot sector */ printf("FAT type: FAT1%c\n", fs + '0' - 10); if (drive >= 2 && - generic_block_ioctl((unsigned char)drive + 1, 0x860, default_bpb) == 0) + generic_block_ioctl(drive + 1, 0x860, default_bpb) == 0) correct_bpb((struct bootsectortype *)(default_bpb + 7 - 11), bs); memcpy(newboot, fs == FAT16 ? fat16com : fat12com, SEC_SIZE); } @@ -782,7 +782,8 @@ void put_boot(int drive, char *bsFile, char *kernel_name, int load_seg, int both bs = (struct bootsectortype *)&newboot; - memcpy(bs->OemName, "FreeDOS ", 8); + /* originally OemName was "FreeDOS", changed for better compatibility */ + memcpy(bs->OemName, "FRDOS4.1", 8); #ifdef WITHFAT32 if (fs == FAT32) @@ -893,7 +894,7 @@ void put_boot(int drive, char *bsFile, char *kernel_name, int load_seg, int both reset_drive(drive); /* unlock_drive */ - generic_block_ioctl((unsigned char)drive + 1, 0x86a, NULL); + generic_block_ioctl(drive + 1, 0x86a, NULL); } /* put_boot */