FreeDOS kernel current - 2041+svn1709

This commit is contained in:
KJD 2012-10-14 20:08:06 -04:00
parent 1cef75adce
commit c431157156
167 changed files with 50246 additions and 0 deletions

92
RELEASE.BAT Normal file
View File

@ -0,0 +1,92 @@
@ECHO OFF
IF "%1"=="" GOTO USAGE
REM goto to just below trunk and tags directory, assume ran in trunk directory
CD ..
ECHO tag SVN with release version - svn copy trunk/ tags/ke%1
svn copy https://freedos.svn.sourceforge.net/svnroot/freedos/kernel/trunk/ https://freedos.svn.sourceforge.net/svnroot/freedos/kernel/tags/ke%1 -m "Tag kernel release %1"
PAUSE
ECHO svn export to get clean tree
if EXIST SOURCE RMDIR /S /Q SOURCE > NUL
svn export https://freedos.svn.sourceforge.net/svnroot/freedos/kernel/tags/ke%1 SOURCE\ke%1
REM svn export https://freedos.svn.sourceforge.net/svnroot/freedos/kernel/trunk SOURCE\ke%1
SET VERSION=%1
SET LSMRET=SRC
SET LSMFILE=SOURCE\ke%1\docs\fdkernel.lsm
GOTO LSM
:SRC
ECHO zipping source
7z.exe a -tzip -mx9 -mpass15 -r ke%1s.zip SOURCE\*
ECHO creating APPINFO and expected packaging dir structure
ECHO using working configuration file
COPY trunk\CONFIG.BAT SOURCE\ke%1 > NUL
CD SOURCE\ke%1
ECHO build and packaging
SET VERSION=%1 (FAT12/FAT16)
SET FAT=16
SET BZKRET=F16
GOTO BZK
:F16
SET VERSION=%1 (FAT12/FAT16/FAT32)
SET FAT=32
SET BZKRET=F32
GOTO BZK
:F32
ECHO clean up
CD ..\..
RMDIR /S /Q SOURCE > NUL
ECHO Done.
SET BZKRET=
GOTO DONE
:BZK
ECHO build kernel %VERSION%
CALL build.bat /D KERNEL_VERSION /V "%1 " 86 upx fat%FAT%
DEL BIN\K??86??.sys
SET LSMRET=BZK_2
SET LSMFILE=docs\fdkernel.lsm
GOTO LSM
:BZK_2
SET LSMRET=
ECHO zipping FAT%FAT% release version
7z.exe a -tzip -mx9 -mpass15 -r ..\..\ke%1_86f%FAT%.zip BIN\* DOCS\*
ECHO restructuring and zipping update package
DEL BIN\K??86??.* > NUL
MKDIR DOC
MKDIR DOC\KERNEL
COPY DOCS\* DOC\KERNEL\
MKDIR APPINFO
MOVE DOC\KERNEL\*.lsm APPINFO\
7z.exe a -tzip -mx9 -mpass15 -r ..\..\kernel%FAT%.zip APPINFO\* BIN\* DOC\*
ECHO cleaning up between builds
CALL clobber.bat
RMDIR /S /Q DOC
RMDIR /S /Q APPINFO
GOTO %BZKRET%
:LSM
ECHO Begin3>%LSMFILE%
ECHO Title: The FreeDOS Kernel>>%LSMFILE%
ECHO Version: %VERSION%>>%LSMFILE%
ECHO Entered-date: %DATE%>>%LSMFILE%
ECHO Description: The FreeDOS Kernel>>%LSMFILE%
ECHO Keywords: kernel, FreeDOS, DOS, MSDOS>>%LSMFILE%
ECHO Author: (developers: can be reached on the freedos-kernel mailing list)>>%LSMFILE%
ECHO Maintained-by: freedos-kernel@lists.sourceforge.net>>%LSMFILE%
ECHO Primary-site: http://freedos.sourceforge.net/kernel/>>%LSMFILE%
ECHO Alternate-site: http://www.fdos.org/kernel/>>%LSMFILE%
ECHO Alternate-site: https://freedos.svn.sourceforge.net/svnroot/freedos>>%LSMFILE%
ECHO Original-site: http://www.gcfl.net/pub/FreeDOS/kernel>>%LSMFILE%
ECHO Platforms: DOS, FreeDOS, DOSEMU (OpenWatcom C or Turbo C, NASM, UPX)>>%LSMFILE%
ECHO Copying-policy: GPL2>>%LSMFILE%
ECHO End>>%LSMFILE%
SET LSMFILE=
SET VERSION=
GOTO %LSMRET%
:USAGE
ECHO Tag and build release kernels - usage: RELEASE {VERSION} e.g. RELEASE 2039
:DONE

3
bin/autoexec.bat Normal file
View File

@ -0,0 +1,3 @@
@echo off
echo Welcome to FreeDOS (http://www.freedos.org)!
path=a:\

5
bin/config.sys Normal file
View File

@ -0,0 +1,5 @@
rem dos=high
rem device=fdxms.sys (or himem.sys)
files=20
buffers=20
rem screen=0x12

36
bin/install.bat Normal file
View File

@ -0,0 +1,36 @@
@echo off
rem
rem Create a distribution floppy
rem
rem $Header$
set D=A:
if "%1" == "b:" set D=B:
if "%1" == "B:" set D=B:
if "%1" == "b" set D=B:
if "%1" == "B" set D=B:
echo This utility will create a distribution floppy on the disk in drive %D%
pause
rem try to transfer system files -- abort if it cannot.
sys %D%
if errorlevel 1 goto out
rem copy remaining files
echo copying remaining files...
echo copying autoexec.bat...
copy autoexec.bat %D%
echo copying config.sys..
copy config.sys %D%
echo copying sys.com..
copy sys.com %D%
label %D% freedos
rem exit methods
goto done
:out
echo Floppy creation aborted
:done
set D=

541
boot/boot.asm Normal file
View File

@ -0,0 +1,541 @@
;
; File:
; boot.asm
; Description:
; DOS-C boot
;
; Copyright (c) 1997;
; Svante Frey
; All Rights Reserved
;
; This file is part of DOS-C.
;
; DOS-C is free software; you can redistribute it and/or
; modify it under the terms of the GNU General Public License
; as published by the Free Software Foundation; either version
; 2, or (at your option) any later version.
;
; DOS-C is distributed in the hope that it will be useful, but
; WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
; the GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public
; License along with DOS-C; see the file COPYING. If not,
; write to the Free Software Foundation, 675 Mass Ave,
; Cambridge, MA 02139, USA.
;
;
; +--------+ 1FE0:7E00
; |BOOT SEC|
; |RELOCATE|
; |--------| 1FE0:7C00
; |LBA PKT |
; |--------| 1FE0:7BC0
; |--------| 1FE0:7BA0
; |BS STACK|
; |--------|
; |4KBRDBUF| used to avoid crossing 64KB DMA boundary
; |--------| 1FE0:63A0
; | |
; |--------| 1FE0:3000
; | CLUSTER|
; | LIST |
; |--------| 1FE0:2000
; | |
; |--------| 0000:7E00
; |BOOT SEC| overwritten by max 128k FAT buffer
; |ORIGIN | and later by max 134k loaded kernel
; |--------| 0000:7C00
; | |
; |--------|
; |KERNEL | also used as max 128k FAT buffer
; |LOADED | before kernel loading starts
; |--------| 0060:0000
; | |
; +--------+
;%define ISFAT12 1
;%define ISFAT16 1
segment .text
%define BASE 0x7c00
org BASE
Entry: jmp short real_start
nop
; bp is initialized to 7c00h
%define bsOemName bp+0x03 ; OEM label
%define bsBytesPerSec bp+0x0b ; bytes/sector
%define bsSecPerClust bp+0x0d ; sectors/allocation unit
%define bsResSectors bp+0x0e ; # reserved sectors
%define bsFATs bp+0x10 ; # of fats
%define bsRootDirEnts bp+0x11 ; # of root dir entries
%define bsSectors bp+0x13 ; # sectors total in image
%define bsMedia bp+0x15 ; media descrip: fd=2side9sec, etc...
%define sectPerFat bp+0x16 ; # sectors in a fat
%define sectPerTrack bp+0x18 ; # sectors/track
%define nHeads bp+0x1a ; # heads
%define nHidden bp+0x1c ; # hidden sectors
%define nSectorHuge bp+0x20 ; # sectors if > 65536
%define drive bp+0x24 ; drive number
%define extBoot bp+0x26 ; extended boot signature
%define volid bp+0x27
%define vollabel bp+0x2b
%define filesys bp+0x36
%define LOADSEG 0x0060
%define FATBUF 0x2000 ; offset of temporary buffer for FAT
; chain
; Some extra variables
;%define StoreSI bp+3h ;temp store
;-----------------------------------------------------------------------
times 0x3E-$+$$ db 0
; using bp-Entry+loadseg_xxx generates smaller code than using just
; loadseg_xxx, where bp is initialized to Entry, so bp-Entry equals 0
%define loadsegoff_60 bp-Entry+loadseg_off
%define loadseg_60 bp-Entry+loadseg_seg
%define LBA_PACKET bp-0x40
%define LBA_SIZE word [LBA_PACKET] ; size of packet, should be 10h
%define LBA_SECNUM word [LBA_PACKET+2] ; number of sectors to read
%define LBA_OFF LBA_PACKET+4 ; buffer to read/write to
%define LBA_SEG LBA_PACKET+6
%define LBA_SECTOR_0 word [LBA_PACKET+8 ] ; LBA starting sector #
%define LBA_SECTOR_16 word [LBA_PACKET+10]
%define LBA_SECTOR_32 word [LBA_PACKET+12]
%define LBA_SECTOR_48 word [LBA_PACKET+14]
%define READBUF 0x63A0 ; max 4KB buffer (min 2KB stack), == stacktop-0x1800
%define READADDR_OFF BP-0x60-0x1804 ; pointer within user buffer
%define READADDR_SEG BP-0x60-0x1802
%define PARAMS LBA_PACKET+0x10
;%define RootDirSecs PARAMS+0x0 ; # of sectors root dir uses
%define fat_start PARAMS+0x2 ; first FAT sector
%define root_dir_start PARAMS+0x6 ; first root directory sector
%define data_start PARAMS+0x0a ; first data sector
;-----------------------------------------------------------------------
; ENTRY
;-----------------------------------------------------------------------
real_start:
cli
cld
xor ax, ax
mov ds, ax
mov bp, BASE
; a reset should not be needed here
; int 0x13 ; reset drive
; int 0x12 ; get memory available in AX
; mov ax, 0x01e0
; mov cl, 6 ; move boot sector to higher memory
; shl ax, cl
; sub ax, 0x07e0
mov ax, 0x1FE0
mov es, ax
mov si, bp
mov di, bp
mov cx, 0x0100
rep movsw
jmp word 0x1FE0:cont
loadseg_off dw 0
loadseg_seg dw LOADSEG
cont:
mov ds, ax
mov ss, ax
lea sp, [bp-0x60]
sti
;
; Note: some BIOS implementations may not correctly pass drive number
; in DL, however we work around this in SYS.COM by NOP'ing out the use of DL
; (formerly we checked for [drive]==0xff; update sys.c if code moves)
;
mov [drive], dl ; rely on BIOS drive number in DL
mov LBA_SIZE, 10h
mov LBA_SECNUM,1 ; initialise LBA packet constants
mov word [LBA_SEG],ds
mov word [LBA_OFF],READBUF
; 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
push ax
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.
;
; Returns:
; AX = first cluster of file
; First, read the whole root directory
; into the temporary buffer.
mov ax, word [root_dir_start]
mov dx, word [root_dir_start+2]
pop di ; mov di, word [RootDirSecs]
les bx, [loadsegoff_60] ; es:bx = 60:0
call readDisk
les di, [loadsegoff_60] ; es:di = 60:0
; Search for KERNEL.SYS file name, and find start cluster.
next_entry: mov cx, 11
mov si, filename
push di
repe cmpsb
pop di
mov ax, [es:di+0x1A]; get cluster number from directory entry
je ffDone
add di, byte 0x20 ; go to next directory entry
cmp byte [es:di], 0 ; if the first byte of the name is 0,
jnz next_entry ; there is no more files in the directory
jc boot_error ; fail if not found
ffDone:
push ax ; store first cluster number
; GETFATCHAIN:
;
; Reads the FAT chain and stores it in a temporary buffer in the first
; 64 kb. The FAT chain is stored an array of 16-bit cluster numbers,
; ending with 0.
;
; 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 2.5 KB (655360 / 512 * 2 = 2560).
;
; Call with: AX = first cluster in chain
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
; Set ES:DI to the temporary storage for the FAT chain.
push ds
pop es
mov ds, [loadseg_60]
mov di, FATBUF
next_clust: stosw ; store cluster number
mov si, ax ; SI = cluster number
%ifdef ISFAT12
; This is a FAT-12 disk.
fat_12: add si, si ; multiply cluster number by 3...
add si, ax
shr si, 1 ; ...and divide by 2
lodsw
; If the cluster number was even, the cluster value is now in
; bits 0-11 of AX. If the cluster number was odd, the cluster
; value is in bits 4-15, and must be shifted right 4 bits. If
; the number was odd, CF was set in the last shift instruction.
jnc fat_even
mov cl, 4
shr ax, cl
fat_even: and ah, 0x0f ; mask off the highest 4 bits
cmp ax, 0x0ff8 ; check for EOF
jb next_clust ; continue if not EOF
%endif
%ifdef ISFAT16
; This is a FAT-16 disk. The maximal size of a 16-bit FAT
; is 128 kb, so it may not fit within a single 64 kb segment.
fat_16: mov dx, [loadseg_60]
add si, si ; multiply cluster number by two
jnc first_half ; if overflow...
add dh, 0x10 ; ...add 64 kb to segment value
first_half: mov ds, dx ; DS:SI = pointer to next cluster
lodsw ; AX = next cluster
cmp ax, 0xfff8 ; >= FFF8 = 16-bit EOF
jb next_clust ; continue if not EOF
%endif
finished: ; Mark end of FAT chain with 0, so we have a single
; EOF marker for both FAT-12 and FAT-16 systems.
xor ax, ax
stosw
push cs
pop ds
; loadFile: Loads the file into memory, one cluster at a time.
les bx, [loadsegoff_60] ; set ES:BX to load address 60:0
mov si, FATBUF ; set DS:SI to the FAT chain
cluster_next: lodsw ; AX = next cluster to read
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
load_next: dec ax ; cluster numbers start with 2
dec ax
mov di, word [bsSecPerClust]
and di, 0xff ; DI = sectors per cluster
mul di
add ax, [data_start]
adc dx, [data_start+2] ; DX:AX = first sector to read
call readDisk
jmp short cluster_next
; shows text after the call to this function.
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
boot_error: call show
; db "Error! Hit a key to reboot."
db "Error!."
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.
;
; Call with: DX:AX = 32-bit DOS sector number
; DI = number of sectors to read
; ES:BX = destination buffer
;
; Returns: CF set on error
; ES:BX points one byte after the last byte read.
readDisk: push si
mov LBA_SECTOR_0,ax
mov LBA_SECTOR_16,dx
mov word [READADDR_SEG], es
mov word [READADDR_OFF], bx
call show
db "."
read_next:
;******************** LBA_READ *******************************
; check for LBA support
mov ah,041h ;
mov bx,055aah ;
mov dl, [drive]
; NOTE: sys must be updated if location changes!!!
test dl,dl ; don't use LBA addressing on A:
jz read_normal_BIOS ; might be a (buggy)
; CDROM-BOOT floppy emulation
int 0x13
jc read_normal_BIOS
shr cx,1 ; CX must have 1 bit set
sbb bx,0aa55h - 1 ; tests for carry (from shr) too!
jne read_normal_BIOS
; OK, drive seems to support LBA addressing
lea si,[LBA_PACKET]
; setup LBA disk block
mov LBA_SECTOR_32,bx ; bx is 0 if extended 13h mode supported
mov LBA_SECTOR_48,bx
mov ah,042h
jmp short do_int13_read
read_normal_BIOS:
;******************** END OF LBA_READ ************************
mov cx,LBA_SECTOR_0
mov dx,LBA_SECTOR_16
;
; translate sector number to BIOS parameters
;
;
; abs = sector offset in track
; + head * sectPerTrack offset in cylinder
; + track * sectPerTrack * nHeads offset in platter
;
mov al, [sectPerTrack]
mul byte [nHeads]
xchg ax, cx
; cx = nHeads * sectPerTrack <= 255*63
; dx:ax = abs
div cx
; ax = track, dx = sector + head * sectPertrack
xchg ax, dx
; dx = track, ax = sector + head * sectPertrack
div byte [sectPerTrack]
; dx = track, al = head, ah = sector
mov cx, dx
; cx = track, al = head, ah = sector
; the following manipulations are necessary in order to
; properly place parameters into registers.
; ch = cylinder number low 8 bits
; cl = 7-6: cylinder high two bits
; 5-0: sector
mov dh, al ; save head into dh for 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)
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
jc boot_error ; exit on error
mov ax, word [bsBytesPerSec]
push di
mov si,READBUF ; copy read in sector data to
les di,[READADDR_OFF] ; user provided buffer
mov cx, ax
; shr cx, 1 ; convert bytes to word count
; rep movsw
rep movsb
pop di
; div byte[LBA_PACKET] ; luckily 16 !!
mov cl, 4
shr ax, cl ; adjust segment pointer by increasing
add word [READADDR_SEG], ax ; by paragraphs read in (per sector)
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 ; continue
les bx, [READADDR_OFF]
; clear carry: unnecessary since adc clears it
pop si
ret
times 0x01f1-$+$$ db 0
filename db "KERNEL SYS",0,0
sign dw 0xAA55
%ifdef DBGPRNNUM
; DEBUG print hex digit routines
PrintLowNibble: ; Prints low nibble of AL, AX is destroyed
and AL, 0Fh ; ignore upper nibble
cmp AL, 09h ; if greater than 9, then don't base on '0', base on 'A'
jbe .printme
add AL, 7 ; convert to character A-F
.printme:
add AL, '0' ; convert to character 0-9
mov AH,0x0E ; show character
int 0x10 ; via "TTY" mode
retn
PrintAL: ; Prints AL, AX is preserved
push AX ; store value so we can process a nibble at a time
shr AL, 4 ; move upper nibble into lower nibble
call PrintLowNibble
pop AX ; restore for other nibble
push AX ; but save so we can restore original AX
call PrintLowNibble
pop AX ; restore for other nibble
retn
PrintNumber: ; Prints (in Hex) value in AX, AX is preserved
xchg AH, AL ; high byte 1st
call PrintAL
xchg AH, AL ; now low byte
call PrintAL
retn
%endif

392
boot/boot32.asm Normal file
View File

@ -0,0 +1,392 @@
; +--------+
; | |
; | |
; |--------| 4000:0000
; | |
; | FAT |
; | |
; |--------| 2000:0000
; |BOOT SEC|
; |RELOCATE|
; |--------| 1FE0:0000
; | |
; | |
; | |
; | |
; |--------|
; |BOOT SEC|
; |ORIGIN | 07C0:0000
; |--------|
; | |
; | |
; | |
; |--------|
; |KERNEL |
; |LOADED |
; |--------| 0060:0000
; | |
; +--------+
;%define MULTI_SEC_READ 1
segment .text
%define BASE 0x7c00
org BASE
Entry: jmp short real_start
nop
; bp is initialized to 7c00h
%define bsOemName bp+0x03 ; OEM label
%define bsBytesPerSec bp+0x0b ; bytes/sector
%define bsSecPerClust bp+0x0d ; sectors/allocation unit
%define bsResSectors bp+0x0e ; # reserved sectors
%define bsFATs bp+0x10 ; # of fats
%define bsRootDirEnts bp+0x11 ; # of root dir entries
%define bsSectors bp+0x13 ; # sectors total in image
%define bsMedia bp+0x15 ; media descrip: fd=2side9sec, etc...
%define sectPerFat bp+0x16 ; # sectors in a fat
%define sectPerTrack bp+0x18 ; # sectors/track
%define nHeads bp+0x1a ; # heads
%define nHidden bp+0x1c ; # hidden sectors
%define nSectorHuge bp+0x20 ; # sectors if > 65536
%define xsectPerFat bp+0x24 ; Sectors/Fat
%define xrootClst bp+0x2c ; Starting cluster of root directory
%define drive bp+0x40 ; Drive number
times 0x5a-$+$$ db 0
%define LOADSEG 0x0060
%define FATSEG 0x2000
%define fat_sector bp+0x48 ; last accessed sector of the FAT
%define loadsegoff_60 bp+loadseg_off-Entry ; FAR pointer = 60:0
%define loadseg_60 bp+loadseg_seg-Entry
%define fat_start bp+0x5e ; first FAT sector
%define data_start bp+0x62 ; first data sector
%define fat_secmask bp+0x66 ; number of clusters in a FAT sector - 1
%define fat_secshift bp+0x68 ; fat_secmask+1 = 2^fat_secshift
;-----------------------------------------------------------------------
; ENTRY
;-----------------------------------------------------------------------
real_start: cld
cli
sub ax, ax
mov ds, ax
mov bp, 0x7c00
mov ax, 0x1FE0
mov es, ax
mov si, bp
mov di, bp
mov cx, 0x0100
rep movsw ; move boot code to the 0x1FE0:0x0000
jmp word 0x1FE0:cont
loadseg_off dw 0
loadseg_seg dw LOADSEG
cont: mov ds, ax
mov ss, ax
lea sp, [bp-0x20]
sti
mov [drive], dl ; BIOS passes drive number in DL
; call print
; db "Loading ",0
; Calc Params
; Fat_Start
mov si, word [nHidden]
mov di, word [nHidden+2]
add si, word [bsResSectors]
adc di, byte 0
mov word [fat_start], si
mov word [fat_start+2], di
; Data_Start
mov al, [bsFATs]
cbw
push ax
mul word [xsectPerFat+2]
add di, ax
pop ax
mul word [xsectPerFat]
add ax, si
adc dx, di
mov word[data_start], ax
mov word[data_start+2], dx
; fat_secmask
mov ax, word[bsBytesPerSec]
shr ax, 1
shr ax, 1
dec ax
mov word [fat_secmask], ax
; fat_secshift
; cx = temp
; ax = fat_secshift
xchg ax, cx ; cx = 0 after movsw
inc cx
secshift: inc ax
shr cx, 1
cmp cx, 1
jne secshift
mov byte [fat_secshift], al
dec cx
; FINDFILE: Searches for the file in the root directory.
;
; Returns:
; DX:AX = first cluster of file
mov word [fat_sector], cx ; CX is 0 after "dec"
mov word [fat_sector + 2], cx
mov ax, word [xrootClst]
mov dx, word [xrootClst + 2]
ff_next_cluster:
push dx ; save cluster
push ax
call convert_cluster
jc boot_error ; EOC encountered
ff_next_sector:
push bx ; save sector count
les bx, [loadsegoff_60]
call readDisk
push dx ; save sector
push ax
mov ax, [bsBytesPerSec]
; Search for KERNEL.SYS file name, and find start cluster.
ff_next_entry: mov cx, 11
mov si, filename
mov di, ax
sub di, 0x20
repe cmpsb
jz ff_done
sub ax, 0x20
jnz ff_next_entry
pop ax ; restore sector
pop dx
pop bx ; restore sector count
dec bx
jnz ff_next_sector
ff_find_next_cluster:
pop ax ; restore current cluster
pop dx
call next_cluster
jmp short ff_next_cluster
ff_done:
mov ax, [es:di+0x1A-11] ; get cluster number
mov dx, [es:di+0x14-11]
c4:
sub bx, bx ; ES points to LOADSEG
c5: push dx
push ax
push bx
call convert_cluster
jc boot_success
mov di, bx
pop bx
c6:
call readDisk
dec di
jnz c6
pop ax
pop dx
call next_cluster
jmp short c5
boot_error:
xor ah,ah
int 0x16 ; wait for a key
int 0x19 ; reboot the machine
; input:
; DX:AX - cluster
; output:
; DX:AX - next cluster
; CX = 0
; modify:
; DI
next_cluster:
push es
mov di, ax
and di, [fat_secmask]
mov cx, [fat_secshift]
cn_loop:
shr dx,1
rcr ax,1
dec cx
jnz cn_loop ; DX:AX fat sector where our
; cluster resides
; DI - cluster index in this
; sector
shl di,1 ; DI - offset in the sector
shl di,1
add ax, [fat_start]
adc dx, [fat_start+2] ; DX:AX absolute fat sector
push bx
mov bx, FATSEG
mov es, bx
sub bx, bx
cmp ax, [fat_sector]
jne cn1 ; if the last fat sector we
; read was this, than skip
cmp dx,[fat_sector+2]
je cn_exit
cn1:
mov [fat_sector],ax ; save the fat sector number,
mov [fat_sector+2],dx ; we are going to read
call readDisk
cn_exit:
pop bx
mov ax, [es:di] ; DX:AX - next cluster
mov dx, [es:di + 2] ;
pop es
ret
boot_success:
mov bl, [drive]
jmp far [loadsegoff_60]
; Convert cluster to the absolute sector
;input:
; DX:AX - target cluster
;output:
; DX:AX - absoulute sector
; BX - [bsSectPerClust]
;modify:
; CX
convert_cluster:
cmp dx,0x0fff
jne c3
cmp ax,0xfff8
jb c3 ; if cluster is EOC (carry is set), do ret
stc
ret
c3:
mov cx, dx ; sector = (cluster - 2)*clussize +
; + data_start
sub ax, 2
sbb cx, byte 0 ; CX:AX == cluster - 2
mov bl, [bsSecPerClust]
sub bh, bh
xchg cx, ax ; AX:CX == cluster - 2
mul bx ; first handle high word
; DX must be 0 here
xchg ax, cx ; then low word
mul bx
add dx, cx ; DX:AX target sector
add ax, [data_start]
adc dx, [data_start + 2]
ret
; 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
;input:
; DX:AX - 32-bit DOS sector number
; ES:BX - destination buffer
;output:
; ES:BX points one byte after the last byte read.
; DX:AX - next sector
;modify:
; ES if DI * bsBytesPerSec >= 65536, CX
readDisk:
read_next: push dx
push ax
;
; translate sector number to BIOS parameters
;
;
; abs = sector offset in track
; + head * sectPerTrack offset in cylinder
; + track * sectPerTrack * nHeads offset in platter
;
xchg ax, cx
mov al, [sectPerTrack]
mul byte [nHeads]
xchg ax, cx
; cx = nHeads * sectPerTrack <= 255*63
; dx:ax = abs
div cx
; ax = track, dx = sector + head * sectPertrack
xchg ax, dx
; dx = track, ax = sector + head * sectPertrack
div byte [sectPerTrack]
; dx = track, al = head, ah = sector
mov cx, dx
; cx = track, al = head, ah = sector
; the following manipulations are necessary in order to
; properly place parameters into registers.
; ch = cylinder number low 8 bits
; cl = 7-6: cylinder high two bits
; 5-0: sector
mov dh, al ; save head into dh for 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)
inc ah ; sector offset from 1
or cl, ah ; merge sector into cylinder
mov ax, 0x0201
mov dl, [drive]
int 0x13
pop ax
pop dx
jnc read_ok ; jump if no error
xor ah, ah ; else, reset floppy
int 0x13
jmp short read_next
read_ok:
add bx, word [bsBytesPerSec]
jnc no_incr_es ; if overflow...
mov cx, es
add ch, 0x10 ; ...add 1000h to ES
mov es, cx
no_incr_es:
add ax,byte 1
adc dx,byte 0
ret
times 0x01f1-$+$$ db 0
filename db "KERNEL SYS",0,0
sign dw 0xAA55

403
boot/boot32lb.asm Normal file
View File

@ -0,0 +1,403 @@
; This is an LBA-enabled FreeDOS FAT32 boot sector (single sector!).
; You can use and copy source code and binaries under the terms of the
; GNU Public License (GPL), version 2 or newer. See www.gnu.org for more.
; Based on earlier work by FreeDOS kernel hackers, modified heavily by
; Eric Auer and Jon Gentle in 7 / 2003.
;
; Features: Uses LBA and calculates all variables from BPB/EBPB data,
; thus making partition move / resize / image-restore easier. FreeDOS
; can boot from FAT32 partitions which start > 8 GB boundary with this
; boot sector. Disk geometry knowledge is not needed for booting.
;
; Windows uses 2-3 sectors for booting (sector stage, statistics sector,
; filesystem stage). Only using 1 sector for FreeDOS makes multi-booting
; of FreeDOS and Windows on the same filesystem easier.
;
; Requirements: LBA BIOS and 386 or better CPU. Use the older CHS-only
; boot sector if you want FAT32 on really old PCs (problems: you cannot
; boot from > 8 GB boundary, cannot move / resize / ... without applying
; SYS again if you use the CHS-only FAT32 boot sector).
;
; FAT12 / FAT16 hints: Use the older CHS-only boot sector unless you
; have to boot from > 8 GB. The LBA-and-CHS FAT12 / FAT16 boot sector
; needs applying SYS again after move / resize / ... a variant of that
; boot sector without CHS support but with better move / resize / ...
; support would be good for use on LBA harddisks.
; Memory layout for the FreeDOS FAT32 single stage boot process:
; ...
; |-------| 1FE0:7E00
; |BOOTSEC|
; |RELOC. |
; |-------| 1FE0:7C00
; ...
; |-------| 2000:0200
; | FAT | (only 1 sector buffered)
; |-------| 2000:0000
; ...
; |-------| 0000:7E00
; |BOOTSEC| overwritten by the kernel, so the
; |ORIGIN | bootsector relocates itself up...
; |-------| 0000:7C00
; ...
; |-------|
; |KERNEL | maximum size 134k (overwrites bootsec origin)
; |LOADED | (holds 1 sector directory buffer before kernel load)
; |-------| 0060:0000
; ...
segment .text
org 0x7c00 ; this is a boot sector
Entry: jmp short real_start
nop
; bp is initialized to 7c00h
; %define bsOemName bp+0x03 ; OEM label (8)
%define bsBytesPerSec bp+0x0b ; bytes/sector (dw)
%define bsSecPerClust bp+0x0d ; sectors/allocation unit (db)
%define bsResSectors bp+0x0e ; # reserved sectors (dw)
%define bsFATs bp+0x10 ; # of fats (db)
; %define bsRootDirEnts bp+0x11 ; # of root dir entries (dw, 0 for FAT32)
; (FAT32 has root dir in a cluster chain)
; %define bsSectors bp+0x13 ; # sectors total in image (dw, 0 for FAT32)
; (if 0 use nSectorHuge even if FAT16)
; %define bsMedia bp+0x15 ; media descriptor: fd=2side9sec, etc... (db)
; %define sectPerFat bp+0x16 ; # sectors in a fat (dw, 0 for FAT32)
; (FAT32 always uses xsectPerFat)
%define sectPerTrack bp+0x18 ; # sectors/track
; %define nHeads bp+0x1a ; # heads (dw)
%define nHidden bp+0x1c ; # hidden sectors (dd)
; %define nSectorHuge bp+0x20 ; # sectors if > 65536 (dd)
%define xsectPerFat bp+0x24 ; Sectors/Fat (dd)
; +0x28 dw flags (for fat mirroring)
; +0x2a dw filesystem version (usually 0)
%define xrootClst bp+0x2c ; Starting cluster of root directory (dd)
; +0x30 dw -1 or sector number of fs.-info sector
; +0x32 dw -1 or sector number of boot sector backup
; (+0x34 .. +0x3f reserved)
%define drive bp+0x40 ; Drive number
%define loadsegoff_60 bp+loadseg_off-Entry
%define LOADSEG 0x0060
%define FATSEG 0x2000
%define fat_secshift fat_afterss-1 ; each fat sector describes 2^??
; clusters (db) (selfmodifying)
%define fat_sector bp+0x44 ; last accessed FAT sector (dd)
; (overwriting unused bytes)
%define fat_start bp+0x48 ; first FAT sector (dd)
; (overwriting unused bytes)
%define data_start bp+0x4c ; first data sector (dd)
; (overwriting unused bytes)
times 0x5a-$+$$ db 0
; not used: [0x42] = byte 0x29 (ext boot param flag)
; [0x43] = dword serial
; [0x47] = label (padded with 00, 11 bytes)
; [0x52] = "FAT32",32,32,32 (not used by Windows)
; ([0x5a] is where FreeDOS parts start)
;-----------------------------------------------------------------------
; ENTRY
;-----------------------------------------------------------------------
real_start: cld
cli
sub ax, ax
mov ds, ax
mov bp, 0x7c00
mov ax, 0x1FE0
mov es, ax
mov si, bp
mov di, bp
mov cx, 0x0100
rep movsw ; move boot code to the 0x1FE0:0x0000
jmp word 0x1FE0:cont
loadseg_off dw 0, LOADSEG
; -------------
cont: mov ds, ax
mov ss, ax ; stack and BP-relative moves up, too
lea sp, [bp-0x20]
sti
mov [drive], dl ; BIOS passes drive number in DL
mov si, msg_LoadFreeDOS
call print ; modifies AX BX SI
; -------------
; CALCPARAMS: figure out where FAT and DATA area starts
; (modifies EAX EDX, sets fat_start and data_start variables)
calc_params: xor eax, eax
mov [fat_sector], eax ; init buffer status
; first, find fat_start:
mov ax, [bsResSectors] ; no movzx eax, word... needed
add eax, [nHidden]
mov [fat_start], eax ; first FAT sector
mov [data_start], eax ; (only first part of value)
; next, find data_start:
mov eax, [bsFATs] ; no movzx ... byte needed:
; the 2 dw after the bsFATs db are 0 by FAT32 definition :-).
imul dword [xsectPerFat] ; (also changes edx)
add [data_start], eax ; first DATA sector
; (adding in RAM is shorter!)
; finally, find fat_secshift:
mov ax, 512 ; default sector size (means default shift)
; shift = log2(secSize) - log2(fatEntrySize)
;--- mov cl, 9-2 ; shift is 7 for 512 bytes per sector
fatss_scan: cmp ax, [bsBytesPerSec]
jz fatss_found
add ax,ax
;--- inc cx
inc word [fat_secshift] ;XXX ; initially 9-2 (byte!)
jmp short fatss_scan ; try other sector sizes
fatss_found:
;--- mov [fat_secshift], cl
; -------------
; FINDFILE: Searches for the file in the root directory.
; Returns: EAX = first cluster of file
mov eax, [xrootClst] ; root dir cluster
ff_next_clust: push eax ; save cluster
call convert_cluster
jc boot_error ; EOC encountered
; EDX is clust/sector, EAX is sector
ff_next_sector: les bx, [loadsegoff_60] ; load to loadseg:0
call readDisk
;--- push eax ; save sector
;--- xor ax, ax ; first dir. entry in this sector
xor di, di ;XXX
; Search for KERNEL.SYS file name, and find start cluster.
ff_next_entry: mov cx, 11
mov si, filename
;--- mov di, ax
repe cmpsb
jz ff_done ; note that di now is at dirent+11
;--- add ax, 0x20 ; next directory entry
;--- cmp ax, [bsBytesPerSec] ; end of sector reached?
add di, byte 0x20 ;XXX
and di, byte -0x20 ; 0xffe0 ;XXX
cmp di, [bsBytesPerSec] ;XXX
jnz ff_next_entry
;--- pop eax ; restore sector
dec dx ; next sector in cluster
jnz ff_next_sector
ff_walk_fat: pop eax ; restore current cluster
call next_cluster ; find next cluster
jmp ff_next_clust
ff_done: push word [es:di+0x14-11] ; get cluster number HI
push word [es:di+0x1A-11] ; get cluster number LO
pop eax ; convert to 32bit
sub bx, bx ; ES points to LOADSEG
; (kernel -> ES:BX)
; -------------
read_kernel: push eax
call convert_cluster
jc boot_success ; EOC encountered - done
; EDX is sectors in cluster, EAX is sector
rk_in_cluster: call readDisk
dec dx
jnz rk_in_cluster ; loop over sect. in cluster
rk_walk_fat: pop eax
call next_cluster
jmp read_kernel
;-----------------------------------------------------------------------
boot_success: mov bl, [drive]
jmp far [loadsegoff_60]
;-----------------------------------------------------------------------
boot_error: mov si, msg_BootError
call print ; modifies AX BX SI
wait_key: xor ah,ah
int 0x16 ; wait for a key
reboot: int 0x19 ; reboot the machine
;-----------------------------------------------------------------------
; given a cluster number, find the number of the next cluster in
; the FAT chain. Needs fat_secshift and fat_start.
; input: EAX - cluster
; output: EAX - next cluster
next_cluster: push es
push di
push bx
mov di, ax
shl di, 2 ; 32bit FAT
push ax
mov ax, [bsBytesPerSec]
dec ax
and di, ax ; mask to sector size
pop ax
shr eax, 7 ; e.g. 9-2 for 512 by/sect.
fat_afterss: ; selfmodifying code: previous byte is patched!
; (to hold the fat_secshift value)
add eax, [fat_start] ; absolute sector number now
mov bx, FATSEG
mov es, bx
sub bx, bx
cmp eax, [fat_sector] ; already buffered?
jz cn_buffered
mov [fat_sector],eax ; number of buffered sector
call readDisk
cn_buffered: and byte [es:di+3],0x0f ; mask out top 4 bits
mov eax, [es:di] ; read next cluster number
pop bx
pop di
pop es
ret
;-----------------------------------------------------------------------
; Convert cluster number to the absolute sector number
; ... or return carry if EndOfChain! Needs data_start.
; input: EAX - target cluster
; output: EAX - absolute sector
; EDX - [bsSectPerClust] (byte)
; carry clear
; (if carry set, EAX/EDX unchanged, end of chain)
convert_cluster:
cmp eax, 0x0ffffff8 ; if end of cluster chain...
jnb end_of_chain
; sector = (cluster-2) * clustersize + data_start
dec eax
dec eax
movzx edx, byte [bsSecPerClust]
push edx
mul edx
pop edx
add eax, [data_start]
; here, carry is unset (unless parameters are wrong)
ret
end_of_chain: stc ; indicate EOC by carry
ret
;-----------------------------------------------------------------------
; PRINT - prints string DS:SI
; modifies AX BX SI
printchar: xor bx, bx ; video page 0
mov ah, 0x0e ; print it
int 0x10 ; via TTY mode
print: lodsb ; get token
cmp al, 0 ; end of string?
jne printchar ; until done
ret ; return to caller
;-----------------------------------------------------------------------
; Read a sector from disk, using LBA
; input: EAX - 32-bit DOS sector number
; ES:BX - destination buffer
; (will be filled with 1 sector of data)
; output: ES:BX points one byte after the last byte read.
; EAX - next sector
readDisk: push dx
push si
push di
read_next: push eax ; would ax be enough?
mov di, sp ; remember parameter block end
;--- db 0x66 ; operand size override (push dword)
push byte 0 ;XXX ; other half of the 32 bits at [C]
; (did not trust "o32 push byte 0" opcode)
push byte 0 ; [C] sector number high 32bit
push eax ; [8] sector number low 32bit
push es ; [6] buffer segment
push bx ; [4] buffer offset
push byte 1 ; [2] 1 sector (word)
push byte 16 ; [0] size of parameter block (word)
mov si, sp
mov dl, [drive]
mov ah, 42h ; disk read
int 0x13
mov sp, di ; remove parameter block from stack
; (without changing flags!)
pop eax ; would ax be enough?
jnc read_ok ; jump if no error
push ax ; !!
xor ah, ah ; else, reset and retry
int 0x13
pop ax ; !!
jmp read_next
read_ok: inc eax ; next sector
add bx, word [bsBytesPerSec]
jnc no_incr_es ; if overflow...
mov dx, es
add dh, 0x10 ; ...add 1000h to ES
mov es, dx
no_incr_es: pop di
pop si
pop dx
ret
;-----------------------------------------------------------------------
msg_LoadFreeDOS db "Loading FreeDOS ",0
times 0x01ee-$+$$ db 0
msg_BootError db "No "
; currently, only "kernel.sys not found" gives a message,
; but read errors in data or root or fat sectors do not.
filename db "KERNEL SYS"
sign dw 0, 0xAA55
; Win9x uses all 4 bytes as magic value here.

33
boot/makefile Normal file
View File

@ -0,0 +1,33 @@
#
# makefile for DOS-C boot
#
!include "../mkfiles/generic.mak"
production: fat12com.bin fat16com.bin fat32chs.bin fat32lba.bin oemfat12.bin oemfat16.bin
fat12com.bin: boot.asm
$(NASM) -dISFAT12 boot.asm -l$*.lst -ofat12com.bin
fat16com.bin: boot.asm
$(NASM) -dISFAT16 boot.asm -l$*.lst -ofat16com.bin
fat32chs.bin: boot32.asm
$(NASM) boot32.asm -l$*.lst -ofat32chs.bin
fat32lba.bin: boot32lb.asm
$(NASM) boot32lb.asm -l$*.lst -ofat32lba.bin
oemfat12.bin: oemboot.asm
$(NASM) -dISFAT12 oemboot.asm -l$*.lst -ooemfat12.bin
oemfat16.bin: oemboot.asm
$(NASM) -dISFAT16 oemboot.asm -l$*.lst -ooemfat16.bin
clobber: clean
-$(RM) *.bin status.me
clean:
-$(RM) *.lst *.map *.bak *.obj

648
boot/oemboot.asm Normal file
View File

@ -0,0 +1,648 @@
;
; File:
; oemboot.asm
; 2004, Kenneth J. Davis
; Copyright (c) 200?, <add name here>
; Description:
; OEM boot sector for FreeDOS compatible with IBM's (R) PC-DOS,
; and Microsoft's (R) MS-DOS. It may work with older OpenDOS/DR-DOS,
; although the standard FreeDOS boot sector is needed with ver 7+
; releases. May work with other versions of DOS that use
; IBMBIO.COM/IBMDOS.COM pair. This boot sector loads only up
; to 58 sectors (29KB) of the kernel (IBMBIO.COM) to 0x70:0 then
; jumps to it. As best I can tell, PC-DOS (and MS-DOS up to version
; 6.xx behaves similar) expects on entry for:
; ch = media id byte in the boot sector
; dl = BIOS drive booted from (0x00=A:, 0x80=C:, ...)
; ax:bx = the starting (LBA) sector of cluster 2 (ie the 1st
; data sector, which is 0x0000:0021 for FAT12)
; ?note? IBMBIO.COM/IO.SYS may use ax:bx and cluster # stored
; elsewhere (perhaps dir entry still at 0x50:0) to determine
; starting sector for full loading of kernel file.
; it also expects the boot sector (in particular the BPB)
; to still be at 0x0:7C00, the directory entry for IBMBIO.COM
; (generally first entry of first sector of the root directory)
; at 0x50:0 (DOS Data Area). The original boot sector may update
; the floppy disk parameter table (int 1Eh), but we don't so
; may fail for any systems where the changes (???) are needed.
; If the above conditions are not met, then IBMBIO.COM will
; print the not a bootable disk error message.
;
; For MS-DOS >= 7 (ie Win9x DOS) the following conditions
; must be met:
; bp = 0x7C00, ie offset boot sector loaded at
; [bp-4] = the starting (LBA) sector of cluster 2 (ie the 1st
; data sector [this is the same as ax:bx for earlier versions
; and dx:ax in Win9x boot sector]
; The starting cluster of the kernel file is stored in
; di for FAT 12/16 (where si is a don't care) and si:di
; for FAT 32.
; The values for ax,bx,cx,dx,ds and the stack do not
; seem to be important (used by IO.SYS) and so may be any value
; (though dx:ax=[data_start], cx=0, bx=0x0f00 on FAT12 or
; 0x0700 on FAT32, ds=0, ss:sp=0:7b??)
; the boot time stack may store the original int1E floppy
; parameter table, otherwise nothing else important seems
; stored there and I am unsure if even this value is used
; beyond boot sector code.
;
; This boot sector only supports FAT12/FAT16 as PC-DOS
; does not support FAT32 and newer FAT32 capable DOSes
; probably have different boot requirements; also do NOT
; use it to boot the FreeDOS kernel as it expects to be
; fully loaded by boot sector (> 29KB & usually to 0x60:0).
;
; WARNING: PC-DOS has additional requirements, in particular,
; it may expect that IBMBIO.COM and IBMDOS.COM be the 1st
; two entries in the root directory (even before the label)
; and that they occupy the 1st consecutive data sectors.
; Newer releases may support other positions, but still
; generally should occupy consecutive sectors. These conditions
; can usually be met by running sys on a freshly formatted
; and un-label'd disk.
;
;
; Derived From:
; boot.asm
; DOS-C boot
;
; Copyright (c) 1997, 2000-2004
; Svante Frey, Jim Hall, Jim Tabor, Bart Oldeman,
; Tom Ehlert, Eric Auer, Luchezar Georgiev, Jon Gentle
; and Michal H. Tyc (DR-DOS adaptation, boot26dr.asm)
; All Rights Reserved
;
; This file is part of FreeDOS.
;
; DOS-C is free software; you can redistribute it and/or
; modify it under the terms of the GNU General Public License
; as published by the Free Software Foundation; either version
; 2, or (at your option) any later version.
;
; DOS-C is distributed in the hope that it will be useful, but
; WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
; the GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public
; License along with DOS-C; see the file COPYING. If not,
; write to the Free Software Foundation, 675 Mass Ave,
; Cambridge, MA 02139, USA.
;
;
; +--------+
; | CLUSTER|
; | LIST |
; |--------| 0000:7F00
; |LBA PKT |
; |--------| 0000:7E00 (0:BP+200)
; |BOOT SEC| contains BPB
; |ORIGIN |
; |--------| 0000:7C00 (0:BP)
; |VARS | only known is 1st data sector (start of cluster 2)
; |--------| 0000:7BFC (DS:[BP-4])
; |STACK | minimal 256 bytes (1/2 sector)
; |- - - - |
; |KERNEL | kernel loaded here (max 58 sectors, 29KB)
; |LOADED | also used as FAT buffer
; |--------| 0070:0000 (0:0700)
; |DOS DA/ | DOS Data Area,
; |ROOT DIR| during boot contains directory entries
; |--------| 0000:0500
; |BDA | BIOS Data Area
; +--------+ 0000:0400
; |IVT | Interrupt Vector Table
; +--------+ 0000:0000
CPU 8086 ; enable assembler warnings to limit instruction set
;%define ISFAT12 1 ; only 1 of these should be set,
;%define ISFAT16 1 ; defines which FAT is supported
%define TRYLBAREAD 1 ; undefine to use only CHS int 13h
%define SETROOTDIR 1 ; if defined dir entry copied to 0:500
%define LOOPONERR 1 ; if defined on error simply loop forever
;%define RETRYALWAYS 1 ; if defined retries read forever
;%define WINBOOT 1 ; use win9x kernel calling conventions (name & jmp addr)
;%define MSCOMPAT 1 ; sets default filename to MSDOS IO.SYS
%ifdef WINBOOT ; if set also change from PC-DOS to
%ifndef MSCOMPAT ; kernel name to MS-DOS kernel name
%define MSCOMPAT
%endif
%endif
segment .text
%define BASE 0x7c00 ; boot sector originally at 0x0:BASE
%define LOADSEG 0x0070 ; segment to load kernel at LOADSEG:0
%define LOADEND 0x07b0 ; limit reads to below this segment
; LOADSEG+29KB, else data overwritten
%define FATBUF bp-0x7500 ; offset of temporary buffer for FAT
; chain 0:FATBUF = 0:0700 = LOADSEG:0
%define ROOTDIR bp-0x7700 ; offset to buffer for root directory
; entry of kernel 0:ROOTDIR
%define CLUSTLIST bp+0x0300 ; zero terminated list of clusters
; that the kernel occupies
; Some extra variables
; using bp-Entry+variable_name generates smaller code than using just
; variable_name, where bp is initialized to Entry, so bp-Entry equals 0
%define LBA_PACKET bp+0x0200 ; immediately after boot sector
%define LBA_SIZE word [LBA_PACKET] ; size of packet, should be 10h
%define LBA_SECNUM word [LBA_PACKET+2] ; number of sectors to read
%define LBA_OFF LBA_PACKET+4 ; buffer to read/write to
%define LBA_SEG LBA_PACKET+6
%define LBA_SECTOR_0 word [LBA_PACKET+8 ] ; LBA starting sector #
%define LBA_SECTOR_16 word [LBA_PACKET+10]
%define LBA_SECTOR_32 word [LBA_PACKET+12]
%define LBA_SECTOR_48 word [LBA_PACKET+14]
%define PARAMS LBA_PACKET+0x10
;%define RootDirSecs PARAMS+0x0 ; # of sectors root dir uses
%define fat_start PARAMS+0x2 ; first FAT sector
;%define root_dir_start PARAMS+0x6 ; first root directory sector
%define first_cluster PARAMS+0x0a ; starting cluster of kernel file
%define data_start bp-4 ; first data sector (win9x expects here)
;-----------------------------------------------------------------------
org BASE
Entry: jmp short real_start
nop
; bp is initialized to 7c00h
%define bsOemName bp+0x03 ; OEM label
%define bsBytesPerSec bp+0x0b ; bytes/sector
%define bsSecPerClust bp+0x0d ; sectors/allocation unit
%define bsResSectors bp+0x0e ; # reserved sectors
%define bsFATs bp+0x10 ; # of fats
%define bsRootDirEnts bp+0x11 ; # of root dir entries
%define bsSectors bp+0x13 ; # sectors total in image
%define bsMedia bp+0x15 ; media descrip: fd=2side9sec, etc...
%define sectPerFat bp+0x16 ; # sectors in a fat
%define sectPerTrack bp+0x18 ; # sectors/track
%define nHeads bp+0x1a ; # heads
%define nHidden bp+0x1c ; # hidden sectors
%define nSectorHuge bp+0x20 ; # sectors if > 65536
%define drive bp+0x24 ; drive number
%define extBoot bp+0x26 ; extended boot signature
%define volid bp+0x27
%define vollabel bp+0x2b
%define filesys bp+0x36
;-----------------------------------------------------------------------
; times 0x3E-$+$$ db 0
;
; Instead of zero-fill,
; initialize BPB with values suitable for a 1440 K floppy
;
db 'IBM 5.0' ; OEM label
dw 512 ; bytes per sector
db 1 ; sectors per cluster
dw 1 ; reserved sectors
db 2 ; number of FATs
dw 224 ; root directory entries
dw 80 * 36 ; total sectors on disk
db 0xF0 ; media descriptor
dw 9 ; sectors per 1 FAT copy
dw 18 ; sectors per track
dw 2 ; number of heads
dd 0 ; hidden sectors
dd 0 ; big total sectors
db 0 ; boot unit
db 0 ; reserved
db 0x29 ; extended boot record id
dd 0x12345678 ; volume serial number
db 'NO NAME '; volume label
db 'FAT12 ' ; filesystem id
;-----------------------------------------------------------------------
; ENTRY
;-----------------------------------------------------------------------
real_start:
cli ; disable interrupts until stack ready
cld ; all string operations increment
xor ax, ax ; ensure our segment registers ready
mov ds, ax ; cs=ds=es=ss=0x0000
mov es, ax
mov ss, ax
mov bp, BASE
lea sp, [bp-4] ; for DOS <7 this may be [bp]
; For compatibility, diskette parameter vector updated.
; lea di [bp+0x3E] ; use 7c3e([bp+3e]) for PC-DOS,
; ;lea di [bp] ; but 7c00([bp]) for DR-DOS 7 bug
; mov bx, 4 * 1eh ; stored at int 1E's vector
; lds si, [bx] ; fetch current int 1eh pointer
; push ds ; store original 1eh pointer at stack top
; push si ; so can restore later if needed
;
; Copy table to new location
; mov cl, 11 ; the parameter table is 11 bytes
; rep movsb ; and copy the parameter block
; mov ds, ax ; restore DS
;
; Note: make desired changes to table here
;
; Update int1E to new location
; mov [bx+2], 0 ; set to 0:bp or 0:bp+3e as appropriate
; mov word [bx], 0x7c3e ; (use 0x7c00 for DR-DOS)
sti ; enable interrupts
; If updated floppy parameter table then must notify BIOS
; Otherwise a reset should not be needed here.
; int 0x13 ; reset drive (AX=0)
;
; Note: some BIOS implementations may not correctly pass drive number
; in DL, however we work around this in SYS.COM by NOP'ing out the use of DL
; (formerly we checked for [drive]==0xff; update sys.c if code moves)
;
mov [drive], dl ; rely on BIOS drive number in DL
; 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
push di ; mov word [root_dir_start+2], di
push si ; mov word [root_dir_start], si
; 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 ; set AX = sectors per root directory
push ax ; mov word [RootDirSecs], ax
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.
;
; Returns:
; AX = first cluster of file
; First, read the root directory into buffer.
; into the temporary buffer. (max 29KB or overruns stuff)
pop di ; mov di, word [RootDirSecs]
pop ax ; mov ax, word [root_dir_start]
pop dx ; mov dx, word [root_dir_start+2]
lea bx, [ROOTDIR] ; es:bx = 0:0500
push es ; save pointer to ROOTDIR
call readDisk
pop es ; restore pointer to ROOTDIR
lea si, [ROOTDIR] ; ds:si = 0:0500
; Search for kernel file name, and find start cluster.
next_entry: mov cx, 11
mov di, filename
push si
repe cmpsb
pop si
mov ax, [si+0x1A]; get cluster number from directory entry
je ffDone
add si, byte 0x20 ; go to next directory entry
jc boot_error ; fail if not found and si wraps
cmp byte [si], 0 ; if the first byte of the name is 0,
jnz next_entry ; there are no more files in the directory
ffDone:
mov [first_cluster], ax ; store first cluster number
%ifdef SETROOTDIR
; copy over this portion of root dir to 0x0:500 for PC-DOS
; (this may allow IBMBIO.COM to start in any directory entry)
lea di, [ROOTDIR] ; es:di = 0:0500
mov cx, 32 ; limit to this 1 entry (rest don't matter)
rep movsw
%endif
; GETFATCHAIN:
;
; Reads the FAT chain and stores it in a temporary buffer in the first
; 64 kb. The FAT chain is stored an array of 16-bit cluster numbers,
; ending with 0.
;
; 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 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
lea bx, [FATBUF] ; es:bx = 0:0700
mov di, [sectPerFat]
mov ax, word [fat_start]
mov dx, word [fat_start+2]
call readDisk
; Set ES:DI to the temporary storage for the FAT chain.
push ds
pop es
lea di, [CLUSTLIST]
; Set DS:0 to FAT data we loaded
mov ax, LOADSEG
mov ds, ax ; ds:0 = 0x70:0 = 0:FATBUF
mov ax, [first_cluster] ; restore first cluster number
push ds ; store LOADSEG
next_clust: stosw ; store cluster number
mov si, ax ; SI = cluster number
%ifdef ISFAT12
; This is a FAT-12 disk.
fat_12: add si, si ; multiply cluster number by 3...
add si, ax
shr si, 1 ; ...and divide by 2
lodsw
; If the cluster number was even, the cluster value is now in
; bits 0-11 of AX. If the cluster number was odd, the cluster
; value is in bits 4-15, and must be shifted right 4 bits. If
; the number was odd, CF was set in the last shift instruction.
jnc fat_even
mov cl, 4
shr ax, cl
fat_even: and ah, 0x0f ; mask off the highest 4 bits
cmp ax, 0x0ff8 ; check for EOF
jb next_clust ; continue if not EOF
%endif
%ifdef ISFAT16
; This is a FAT-16 disk. The maximal size of a 16-bit FAT
; is 128 kb, so it may not fit within a single 64 kb segment.
fat_16: mov dx, LOADSEG
add si, si ; multiply cluster number by two
jnc first_half ; if overflow...
add dh, 0x10 ; ...add 64 kb to segment value
first_half: mov ds, dx ; DS:SI = pointer to next cluster
lodsw ; AX = next cluster
cmp ax, 0xfff8 ; >= FFF8 = 16-bit EOF
jb next_clust ; continue if not EOF
%endif
finished: ; Mark end of FAT chain with 0, so we have a single
; EOF marker for both FAT-12 and FAT-16 systems.
xor ax, ax
stosw
push cs
pop ds
; loadFile: Loads the file into memory, one cluster at a time.
pop es ; set ES:BX to load address 70:0
xor bx, bx
lea si, [CLUSTLIST] ; set DS:SI to the FAT chain
cluster_next: lodsw ; AX = next cluster to read
or ax, ax ; EOF?
jne load_next ; no, continue
; dl set to drive by readDisk
mov ch, [bsMedia] ; ch set to media id
mov ax, [data_start+2] ; ax:bx set to 1st data sector
mov bx, [data_start] ;
mov di, [first_cluster] ; set di (si:di on FAT32) to starting cluster #
%ifdef WINBOOT
jmp LOADSEG:0x0200 ; yes, pass control to kernel
%else
jmp LOADSEG:0000 ; yes, pass control to kernel
%endif
; failed to boot
boot_error:
call show
; db "Error! Hit a key to reboot."
db "):."
%ifdef LOOPONERR
jmp $
%else
; Note: should restore floppy paramater table address at int 0x1E
xor ah,ah
int 0x13 ; reset floppy
int 0x16 ; wait for a key
int 0x19 ; reboot the machine
%endif
load_next: dec ax ; cluster numbers start with 2
dec ax
mov di, word [bsSecPerClust]
and di, 0xff ; DI = sectors per cluster
mul di
add ax, [data_start]
adc dx, [data_start+2] ; DX:AX = first sector to read
call readDisk
jmp short cluster_next
; shows text after the call to this function.
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
; readDisk: Reads a number of sectors into memory.
;
; Call with: DX:AX = 32-bit DOS sector number
; DI = number of sectors to read
; ES:BX = destination buffer
;
; Returns: CF set on error
; ES:BX points one byte after the last byte read.
; Exits early if LBA_SEG == LOADEND.
readDisk: push si ; preserve cluster #
mov LBA_SECTOR_0,ax
mov LBA_SECTOR_16,dx
mov word [LBA_SEG], es
mov word [LBA_OFF], bx
call show
db "."
read_next:
; initialize constants
mov LBA_SIZE, 10h ; LBA packet is 16 bytes
mov LBA_SECNUM,1 ; reset LBA count if error
; limit kernel loading to 29KB, preventing stack & boot sector being overwritten
cmp word [LBA_SEG], LOADEND ; skip reading if past the end
je read_skip ; of kernel file buffer
;******************** LBA_READ *******************************
; check for LBA support
%ifdef TRYLBAREAD
mov ah,041h ;
mov bx,055aah ;
mov dl, [drive] ; BIOS drive, 0=A:, 80=C:
test dl,dl ; don't use LBA addressing on A:
jz read_normal_BIOS ; might be a (buggy)
; CDROM-BOOT floppy emulation
int 0x13
jc read_normal_BIOS
shr cx,1 ; CX must have 1 bit set
sbb bx,0aa55h - 1 ; tests for carry (from shr) too!
jne read_normal_BIOS
; OK, drive seems to support LBA addressing
lea si,[LBA_PACKET]
; setup LBA disk block
mov LBA_SECTOR_32,bx ; bx is 0 if extended 13h mode supported
mov LBA_SECTOR_48,bx
mov ah,042h
jmp short do_int13_read
%endif
read_normal_BIOS:
;******************** END OF LBA_READ ************************
mov cx, LBA_SECTOR_0
mov dx, LBA_SECTOR_16
;
; translate sector number to BIOS parameters
;
;
; abs = sector offset in track
; + head * sectPerTrack offset in cylinder
; + track * sectPerTrack * nHeads offset in platter
;
mov al, [sectPerTrack]
mul byte [nHeads]
xchg ax, cx
; cx = nHeads * sectPerTrack <= 255*63
; dx:ax = abs
div cx
; ax = track, dx = sector + head * sectPertrack
xchg ax, dx
; dx = track, ax = sector + head * sectPertrack
div byte [sectPerTrack]
; dx = track, al = head, ah = sector
mov cx, dx
; cx = track, al = head, ah = sector
; the following manipulations are necessary in order to
; properly place parameters into registers.
; ch = cylinder number low 8 bits
; cl = 7-6: cylinder high two bits
; 5-0: sector
mov dh, al ; save head into dh for 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)
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:
%ifdef RETRYALWAYS
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
%else
jc boot_error ; exit on error
%endif
read_ok:
mov ax, word [bsBytesPerSec]
mov cl, 4 ; adjust segment pointer by increasing
shr ax, cl
add word [LBA_SEG], ax ; by paragraphs read in (per sector)
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,
%ifdef RETRYALWAYS
jnz read_next_chained ; continue
%else
jnz read_next ; continue
%endif
read_skip:
mov es, word [LBA_SEG] ; load adjusted segment value
; clear carry: unnecessary since adc clears it
pop si
ret
times 0x01f1-$+$$ db 0
%ifdef MSCOMPAT
filename db "IO SYS"
%else
filename db "IBMBIO COM"
%endif
db 0,0
sign dw 0xAA55

178
build.bat Normal file
View File

@ -0,0 +1,178 @@
@echo off
rem batch file to build everything
rem IF NOTHING COMPILES, CHECK IF YOUR CVS CHECKOUT USES CORRECT DOS LINEBREAKS
if NOT "%1" == "/?" goto start
echo ":-----------------------------------------------------------------------"
echo ":- Syntax: BUILD [-r] [fat32|fat16] [msc|wc|tc|tcpp|bc] [86|186|386] "
echo ":- [debug] [lfnapi] [/L #] [/D value] [list] [upx] [win] "
echo ":- option case is significant !! "
echo ":- Note: Open Watcom (wc) is the preferred compiler "
echo ":-----------------------------------------------------------------------"
goto end
:start
:- assume an error until successful build
set XERROR=1
if "%XERROR%" == "" goto noenv
if "%1" == "-r" call clobber.bat
if "%1" == "-r" shift
if not exist config.bat echo You must copy CONFIG.B to CONFIG.BAT and edit it to reflect your setup!
if not exist config.bat goto abort
call config.bat
:-if "%LAST%" == "" goto noenv
set dos4g=quiet
:-----------------------------------------------------------------------
:- following is command line handling
:- options on the commandline overwrite default settings
:-----------------------------------------------------------------------
:loop_commandline
if "%1" == "fat32" set XFAT=32
if "%1" == "fat16" set XFAT=16
if "%1" == "msc" set COMPILER=MSCL8
if "%1" == "wc" set COMPILER=WATCOM
if "%1" == "tc" set COMPILER=TC2
if "%1" == "tcpp" set COMPILER=TURBOCPP
if "%1" == "bc" set COMPILER=BC
if "%1" == "86" set XCPU=86
if "%1" == "186" set XCPU=186
if "%1" == "386" set XCPU=386
if "%1" == "x86" goto setCPU
if "%1" == "upx" set XUPX=upx --8086 --best
if "%1" == "debug" set ALLCFLAGS=%ALLCFLAGS% -DDEBUG
if "%1" == "lfnapi" set ALLCFLAGS=%ALLCFLAGS% -DWITHLFNAPI
if "%1" == "win" set ALLCFLAGS=%ALLCFLAGS% -DWIN31SUPPORT
if "%1" == "win" set NASMFLAGS=%NASMFLAGS% -DWIN31SUPPORT
if "%1" == "list" set NASMFLAGS=%NASMFLAGS% -l$*.lst
if "%1" == "/L" goto setLoadSeg
if "%1" == "/D" goto setDefine
:nextOption
shift
if not "%1" == "" goto loop_commandline
call default.bat
:-if "%LAST%" == "" goto noenv
:-----------------------------------------------------------------------
:- finally - we are going to compile
:-----------------------------------------------------------------------
echo USING OPTIONS of C=[%ALLCFLAGS%] ASM=[%NASMFLAGS%]
echo.
echo Process UTILS ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
echo.
cd utils
%MAKE% production
if errorlevel 1 goto abort-cd
echo.
echo Process LIB ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
echo.
cd ..\lib
%MAKE%
if errorlevel 1 goto abort-cd
echo.
echo Process DRIVERS ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
echo.
cd ..\drivers
%MAKE% production
if errorlevel 1 goto abort-cd
echo.
echo Process BOOT +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
echo.
cd ..\boot
%MAKE% production
if errorlevel 1 goto abort-cd
echo.
echo Process SYS ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
echo.
cd ..\sys
%MAKE% production
if errorlevel 1 goto abort-cd
if NOT "%XUPX%" == "" %XUPX% ..\bin\sys.com
echo.
echo Process KERNEL +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
echo.
cd ..\kernel
%MAKE% production
if errorlevel 1 goto abort-cd
cd ..
set XERROR=
:- if you like, put finalizing commands (like copy to floppy) into build2.bat
if exist build2.bat call build2.bat
echo.
echo Processing is done.
goto end
:-----------------------------------------------------------------------
:setLoadSeg
shift
if "%1" == "" echo you MUST specify load segment eg 0x60 with /L option
if "%1" == "" goto abort
set LOADSEG=%1
goto nextOption
:setCPU
shift
if "%1" == "" echo you MUST specify compiler's cpu cmd line argument, eg -5
if "%1" == "" goto abort
set XCPU_EX=%1
goto nextOption
:setDefine
shift
:- Give extra compiler DEFINE flags here
if "%1" == "" echo you MUST specify value to define with /D option
if "%1" == "" echo such as /D DEBUG : extra DEBUG output
if "%1" == "" echo or /D DOSEMU : printf output goes to dosemu log
if "%1" == "" echo or /D WIN31SUPPORT : enable Win 3.x hooks
if "%1" == "" goto abort
if "%2" == "/V" goto :setDefineWithValue
set ALLCFLAGS=%ALLCFLAGS% -D%1
set NASMFLAGS=%NASMFLAGS% -D%1
goto nextOption
:setDefineWithValue
set ALLCFLAGS=%ALLCFLAGS% -D%1=%3
set NASMFLAGS=%NASMFLAGS% -D%1=%3
shift
shift
goto nextOption
:noenv
echo Unable to set necessary environment variables!
goto abort
:abort-cd
cd ..
:abort
echo Compilation was aborted!
:end
call default.bat clearset

110
buildall.bat Normal file
View File

@ -0,0 +1,110 @@
@echo off
rem IF NOTHING COMPILES, CHECK IF YOUR CVS CHECKOUT USES CORRECT DOS LINEBREAKS
:- $Id: buildall.bat 1305 2006-10-31 21:13:02Z bartoldeman $
:----------------------------------------------------------
:- batch file to build _many_ KERNELS, hope build works.
:- takes 3 minutes on my(TE) Win2K/P700. your milage may vary :-)
:----------------------------------------------------------
if "%1" == "$SUMMARY" goto summary
set onerror=if not "%XERROR%" == "" goto daswarwohlnix
:***** MSCL kernels
call config.bat
set dos4g=quiet
if "%MS_BASE%" == "" goto no_ms
call build -r msc 386 fat16
%ONERROR%
call build -r msc 186 fat16
%ONERROR%
call build -r msc 86 fat16
%ONERROR%
call build -r msc 386 fat32
%ONERROR%
call build -r msc 186 fat32
%ONERROR%
call build -r msc 86 fat32
%ONERROR%
:no_ms
:***** TC 2.01 kernels
if "%TC2_BASE%" == "" goto no_tc
call build -r tc 186 fat16
%ONERROR%
call build -r tc 86 fat16
%ONERROR%
call build -r tc 186 fat32
%ONERROR%
call build -r tc 86 fat32
%ONERROR%
:no_tc
:***** (Open) Watcom kernels
if "%WATCOM%" == "" goto no_wc
call build -r wc 386 fat32
%ONERROR%
call build -r wc 386 fat16
%ONERROR%
call build -r wc 86 fat32
%ONERROR%
call build -r wc 86 fat16
%ONERROR%
:no_wc
:***** now rebuild the default kernel
call build -r
:**************************************************************
:* now we build a summary of all kernels HMA size + total size
:* Yes, I know - "mit Linux waer das nicht passiert" :-)
:* at least, it's possible with standard DOS tools
:**************************************************************
set Sumfile=bin\ksummary.txt
set TempSumfile=bin\tsummary.txt
:****echo >%TempSumfile% Summary of all kernels build
:****echo.|date >>%TempSumfile%
:****echo.|time >>%TempSumfile%
:****for %%i in (bin\k*.map) do call %0 $SUMMARY %%i
if exist %Sumfile% del %Sumfile%
if exist %TempSumfile% del %TempSumfile%
>ktemp.bat
for %%i in (bin\k*.map) do echo call %0 $SUMMARY %%i >>ktemp.bat
sort <ktemp.bat >ktemps.bat
call ktemps.bat
del ktemp.bat
del ktemps.bat
echo >>%Sumfile% Summary of all kernels build
echo.|date >>%Sumfile%
echo.|time >>%Sumfile%
find <%TempSumfile% "H" >>%Sumfile%
del %TempSumfile%
set TempSumfile=
set Sumfile=
goto end
:summary
echo H************************************************* %2 >>%TempSumfile%
find<%2 " HMA_TEXT"|find/V "HMA_TEXT_START"|find/V "HMA_TEXT_END">>%TempSumfile%
find<%2 " STACK">>%TempSumfile%
goto end
:************* done with summary *********************************
:daswarwohlnix
echo Sorry, something didn't work as expected :-(
set ONERROR=
:end

37
clean.bat Normal file
View File

@ -0,0 +1,37 @@
@echo off
:- batch file to clean everything
:- $Id: clean.bat 1181 2006-05-20 20:45:59Z mceric $
if not exist config.bat echo You must copy CONFIG.B to CONFIG.BAT and edit it to reflect your setup!
if not exist config.bat goto end
call config.bat
call default.bat
cd utils
%MAKE% clean
cd ..\lib
%MAKE% clean
cd ..\drivers
%MAKE% clean
cd ..\boot
%MAKE% clean
cd ..\sys
%MAKE% clean
cd ..\kernel
%MAKE% clean
cd ..\hdr
if exist *.bak del *.bak
cd ..
if exist *.bak del *.bak
:end
default.bat clearset

38
clobber.bat Normal file
View File

@ -0,0 +1,38 @@
@echo off
:- batch file to clobber everything
:- $Id: clobber.bat 1181 2006-05-20 20:45:59Z mceric $
if not exist config.bat echo You must copy CONFIG.B to CONFIG.BAT and edit it to reflect your setup!
if not exist config.bat goto end
call config.bat
call default.bat
cd utils
%MAKE% clobber
cd ..\lib
%MAKE% clobber
cd ..\drivers
%MAKE% clobber
cd ..\boot
%MAKE% clobber
cd ..\sys
%MAKE% clobber
cd ..\kernel
%MAKE% clobber
cd ..\hdr
if exist *.bak del *.bak
cd ..
if exist *.bak del *.bak
if exist status.me del status.me
:end
default.bat clearset

119
config.b Normal file
View File

@ -0,0 +1,119 @@
:-
:- batch file that is included in all other batch files for configuration
:-
:-****************************************************************
:- NOTICE! You must edit and rename this file to CONFIG.BAT! *
:-****************************************************************
:-*********************************************************************
:- determine your compiler settings
:-
:- you have to
:- search for XNASM - and set the path for NASM
:- search for COMPILER - and set your compiler
:- search for ??_BASE - and set the path to your compiler
:-
:-*********************************************************************
:-**********************************************************************
:-- define NASM executable - remember - it should not be protected
:- mode DJGPP version if you're using Windows NT/2k/XP to compile
:- also: DJGPP-nasm crashes when using protected mode Borland's make
:-**********************************************************************
set XNASM=c:\bin\nasm16
:**********************************************************************
:- define your COMPILER type here, pick one of them
:**********************************************************************
:- Turbo C 2.01
set COMPILER=TC2
:- Turbo C++ 1.01
:- set COMPILER=TURBOCPP
:- Turbo C 3.0
:- set COMPILER=TC3
:- Borland C
:- set COMPILER=BC5
:- Microsoft C
:- set COMPILER=MSCL8
:- Watcom C
:- set COMPILER=WATCOM
:-**********************************************************************
:-- where is the BASE dir of your compiler(s) ??
:-**********************************************************************
set TC2_BASE=c:\tc201
:- set TP1_BASE=c:\tcpp
:- set TC3_BASE=c:\tc3
:- set BC5_BASE=c:\bc5
:- set MS_BASE=c:\msvc
:- if WATCOM maybe you need to set your WATCOM environment variables
:- and path
:- if not \%WATCOM% == \ goto watcom_defined
:- set WATCOM=c:\watcom
:- set PATH=%PATH%;%WATCOM%\binw
:watcom_defined
:-**********************************************************************
:- where is UPX and which options to use?
:-**********************************************************************
set XUPX=upx --8086 --best
:- or use set XUPX=
:- if you don't want to use it
:-**********************************************************************
:- (optionally) which linker to use:
:- (otherwise will be determined automatically)
:-
:- WARNING TLINK needs to be in your PATH!
:-**********************************************************************
:- Turbo Link
:- set XLINK=tlink /m/c/s/l
:- Microsoft Link
:- set XLINK=d:\qb\link /ma
:- set XLINK=%MS_BASE%\bin\link /ONERROR:NOEXE /ma /nologo
:- WATCOM Link (wlinker is a batch file calling ms2wlink and wlink)
:- set XLINK=..\utils\wlinker /ma /nologo
:- set path for Turbo Link - use OLDPATH to restore normal path
:- set OLDPATH=%PATH%
:- set PATH=%PATH%;%TC2_BASE%
:**********************************************************************
:* optionally define your MAKE type here, if not then
:* it will be automatically determined, pick one of them
:* use MS nmake if you want to compile with MSCL
:**********************************************************************
:- Borland MAKE
:- set MAKE=%TC2_BASE%\make
:- Watcom MAKE in MS mode
:- set MAKE=%WATCOM%\binw\wmake /ms
:- Microsoft MAKE
:- set MAKE=%MS_BASE%\bin\nmake /nologo
:**********************************************************************
:* select your default target: required CPU and what FAT system to support
:**********************************************************************
set XCPU=86
:- set XCPU=186
:- set XCPU=386
set XFAT=16
:- set XFAT=32
:- Give extra compiler DEFINE flags here
:- such as -DDEBUG : extra DEBUG output
:- -DDOSEMU : printf output goes to dosemu log
:- set ALLCFLAGS=-DDEBUG
:-
:- $Id: config.b 864 2004-04-11 12:21:25Z bartoldeman $
:-

65
config.m Normal file
View File

@ -0,0 +1,65 @@
#
# Linux cross compilation only!
# config file that is included in the main makefile for configuration
#
#****************************************************************
# NOTICE! If you edit you must rename this file to config.mak!*
#****************************************************************
#**********************************************************************
#- define NASM executable
#**********************************************************************
XNASM=nasm
#**********************************************************************
#- where is the BASE dir of your compiler(s) ??
#**********************************************************************
# if WATCOM maybe you need to set your WATCOM environment variables
# and path
ifndef WATCOM
WATCOM=$(HOME)/watcom
PATH:=$(WATCOM)/binl:$(PATH)
endif
#**********************************************************************
# where is UPX and which options to use?
#**********************************************************************
XUPX=upx --8086 --best
# or use
#unexport XUPX
# without the # if you don't want to use it
#**********************************************************************
# (optionally) which linker to use:
# (otherwise will be determined automatically)
# WATCOM Link
#XLINK=wlink
#*********************************************************************
# optionally define your MAKE type here, if not then
# it will be automatically determined, pick one of them
# use MS nmake if you want to compile with MSCL
#*********************************************************************
# Watcom MAKE in MS mode
#MAKE=wmake -ms -h
#*********************************************************************
# select your default target: required CPU and what FAT system to support
#*********************************************************************
XCPU=86
# XCPU=186
# XCPU=386
XFAT=16
# XFAT=32
# Give extra compiler DEFINE flags here
# such as -DDEBUG : extra DEBUG output
# -DDOSEMU : printf output goes to dosemu log
# set ALLCFLAGS=-DDEBUG

82
default.bat Normal file
View File

@ -0,0 +1,82 @@
@echo off
:- $Id: default.bat 1482 2009-07-11 16:59:43Z perditionc $
:- with option clearset, clears all config.bat-made environment variables
:- without options, MAKE / LINK / ... are set to defaults based on COMPILER ...
if "%1" == "clearset" goto clearset
:-----------------------------------------------------------------------
if not "%COMPILER%" == "" goto skip_cc
set COMPILER=WATCOM
echo No compiler specified, defaulting to Open Watcom
:skip_cc
:-----------------------------------------------------------------------
if not "%MAKE%" == "" goto skip_make
if "%COMPILER%" == "TC2" set MAKE=%TC2_BASE%\make
if "%COMPILER%" == "TURBOCPP" set MAKE=%TP1_BASE%\bin\make
if "%COMPILER%" == "TC3" set MAKE=%TC3_BASE%\bin\make
if "%COMPILER%" == "BC5" set MAKE=%BC5_BASE%\bin\make
if "%COMPILER%" == "WATCOM" set MAKE=wmake /ms /h
if "%COMPILER%" == "MSCL8" set MAKE=%MS_BASE%\bin\nmake /nologo
echo Make is %MAKE%.
:skip_make
:-----------------------------------------------------------------------
if not "%XLINK%" == "" goto skip_xlink
if "%COMPILER%" == "TC2" set XLINK=%TC2_BASE%\tlink /m/c
if "%COMPILER%" == "TURBOCPP" set XLINK=%TP1_BASE%\bin\tlink /m/c
if "%COMPILER%" == "TC3" set XLINK=%TC3_BASE%\bin\tlink /m/c
if "%COMPILER%" == "BC5" set XLINK=%BC5_BASE%\bin\tlink /m/c
if "%COMPILER%" == "WATCOM" set XLINK=..\utils\wlinker /ma/nologo
if "%COMPILER%" == "MSCL8" set XLINK=%MS_BASE%\bin\link /ONERROR:NOEXE /ma /nologo
echo Linker is %XLINK%.
:skip_xlink
:-----------------------------------------------------------------------
if not "%XUPX%" == "" set UPXOPT=-U
if "%XUPX%" == "" set UPXOPT=
goto end
:-----------------------------------------------------------------------
:clearset
if not "%OLDPATH%" == "" set PATH=%OLDPATH%
if not "%OLDPATH%" == "" set OLDPATH=
set MAKE=
set COMPILER=
set ALLCFLAGS=
set CFLAGS=
set XCPU=
set XCPU_EX=
set XFAT=
set XLINK=
set TC2_BASE=
set TP1_BASE=
set TC3_BASE=
set BC5_BASE=
set MS_BASE=
set XNASM=
set NASMFLAGS=
set XUPX=
set UPXOPT=
set LOADSEG=
:end

8
docs/bugs.txt Normal file
View File

@ -0,0 +1,8 @@
The current bug database is available on the web at
http://sourceforge.net/tracker/?group_id=5109&atid=105109
Please request an account if you want to report or
update bugs. Reading the database needs no login.
Thanks!

120
docs/build.txt Normal file
View File

@ -0,0 +1,120 @@
Building on DOS or Windows:
===========================
To build the operating system a batch file (BUILD.BAT) is included
to make life easier. This file is in the FDKERNEL directory of the
distribution. In addition, there is a corresponding batch file
(CLEAN.BAT) to clean up the source directories.
There is a CONFIG.B file that specifies all the paths and names of
the compiler, assembler, etc. that you want to use. You MUST copy
it to CONFIG.BAT first, then edit it to reflect your setup.
The reason for this copying of files is that when new releases of the
kernel come out, you can extract them over your previous source, and
not have to worry about resetting up your configuration because your
CONFIG.BAT file will not get replaced!
Building on Linux:
==================
To cross compile on Linux you need to install Open Watcom 1.8 from
www.openwatcom.org and NASM which is probably included in your
distribution. You can then copy config.m to config.mak and adjust
for the same reasons mentioned above.
Use the following commands:
- to build:
make all
- to build, overriding a config.mak setting, e.g.:
make all XCPU=386
- to clean:
make clean
- to clobber (delete everything that was generated):
make clobber
Notes:
======
The recommended compiler and assembler at the time of writing (2009/05/19)
are OpenWatcom 1.8 and NASM 2.05.01.
You may need to download the latest version of NASM and a C compiler
Be sure to edit the CONFIG.BAT file to reflect where you put the tools.
You can find NASM at http://nasm.sourceforge.net. Version 0.98.36 or
later is strongly recommended. The older 0.98 will also work fine, but
any version in between is likely to fail. It's best to use a NASM
that is native to your host; that is, when compiling in Windows, use
the win32 version. The DJGPP version is less likely to run out of
memory than the DOS version.
Optionally, the kernel can be compressed using UPX. You can find
UPX at http://upx.sourceforge.net. Simply adjust config.bat to
enable it.
This kernel compiles with Turbo C 2.01, Turbo C++ 1.01 (now freely
available!), Turbo C 3.0, Borland C 4.51 & 5.01. It should work with
other Borland and Microsoft compilers and (Open)Watcom C. GCC can
compile the kernel but the result does *not* work (no 16-bit x86 support).
The OpenWatcom 1.0 compiler (or later) for DOS can be downloaded at
www.openwatcom.org: you need at least the following zips from
ftp://ftp.openwatcom.org/watcom/zips/
(see ftp://ftp.openwatcom.org/watcom/zips/layout.txt)
cm_core_all - Core binaries (All hosts)
cm_core_dos - Core binaries (DOS host)
cm_core_doswin - Core binaries (DOS & Win hosts)
cm_clib_hdr - C runtime library header files
cm_clib_a16 - C runtime libraries (16-bit all targets)
cm_clib_d16 - C runtime libraries (16-bit DOS)
clib_a16 - C runtime libraries (16-bit all targets)
clib_d16 - C runtime libraries (16-bit DOS)
core_doswin - Core binaries (DOS & Win16 hosts)
c_doswin - C compiler (DOS & Win16 hosts)
ext_dos4gw - DOS/4GW DOS extender
Replace "dos" by "nt" for an NT/Win9x host or "os2" for an OS/2 host.
The host needs to be a 386+ with at least 8MB of memory.
If you feel hardy, read on to understand the directory structure. A
more complete description of the build environment is contained in a
companion book, "The FreeDOS Kernel" (ISBN: 0-87930-436-7) published
by R&D Books, an imprint of Miller Freeman of Lawrence, Kansas (USA)
and distributed in the USA and Canada by Publishers Group West. See
the file README.TXT for more details.
Directory Structure
-------------------
fdkernel root directory
+-----bin holds image of distribution disk
+-----boot boot.bin (boot sector)
+-----docs documentation directory
+-----drivers DEVICE.LIB
+-----hdr common *.h files
+-----kernel The kernel itself
+-----lib LIBM.LIB and DEVICE.LIB
+-----sys SYS.COM and supporting programs
+-----utils Miscellaneous utilities
Organization in a nutshell
--------------------------
Each component or group of utilities is segregated into its own
directory. In order to build that component or utility, a makefile
exists in the directory that bears the component's or utility's
basename.
Each makefile has at least two targets, production and clean. The
target production builds the expected component or utility and the
component clean cleans up the directory for distribution. The
makefile may have at least one additional target that builds the
component. Study the makefile to better understand this.
---------------------------------------------------------------------
$Id: build.txt 1387 2009-05-19 21:39:29Z bartoldeman $

480
docs/config.txt Normal file
View File

@ -0,0 +1,480 @@
Title: Config.sys Options
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
kernel's 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.
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.
Example: break=off
BUFFERS
BUFFERSHIGH
Usage: buffers=nn[,m] where nn is in range 1-99 & m 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. In MS DOS,
a secondary buffer can used to read-ahead data. FreeDOS does not do
this. Buffers are stored in HMA by FreeDOS, unless you select nn to
allocate more buffers than fit in HMA. If nn is smaller, unused HMA
space will be used for further buffers until something else allocates
the HMA space for something else. Even then, at least nn buffers will
always be available. You can set nn to a negative value to disable
the use of unused HMA space: BUFFERS=-10 only uses 10 buffers, further
free space in the HMA will just stay unused. Because the buffers can
use the HMA anyway, BUFFERSHIGH does the same as BUFFERS for now, but
shows a note about that to inform the user that it does not use UMB.
Example: buffers=20
COUNTRY
Usage: country=nnn[,[mmm][,[d:][path]file]]
Enables/sets international features of DOS by selecting a country
code and (only with the unstable / devel kernel) optionally also
a codepage and country file. The stable kernel only uses the nnn
value. For full support, use the unstable / devel kernel. You also
need a COUNTRY.SYS file for the latter, while the former ignores the
filename argument and only sets date/time/number formats, using values
compiled into the kernel for a few common countries. It does not set
sort order and upper/lower case translation tables. NLSFUNC can only
be used with the unstable kernel.
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
Example: 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.
Example: 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.
Example: devicehigh=xcdrom.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
Example: dos=high,umb
Example: dos=low,noumb
DOSDATA
Usage: dosdata=umb
Try to load kernel data into Upper Memory Blocks; effectively
same as using the [name]HIGH variant of kernel parameters,
such as fileshigh, lastdrivehigh, and stackshigh (does not
effect drivers loaded using device= or install=).
Example: 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).
Example:
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 like NANSI loaded prior to use.
Example: EECHO feeling $[33;44;1m blue :-)
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) and FreeDOS dynamically simulates FCBS from the
handle data as needed, nnn is simply ignored by FreeDOS.
Example: 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
Example: files=20
IDLEHALT
Usage: idlehalt=n
where n can be -1, 0, 1 or higher (default 0)
Activates built-in kernel energy saving functionality if n is
not 0. Value -1 enables all hooks, 1 enables only "safe" hooks,
CPU halted only if kernel is waiting for CON char device input.
Further hooks for n=-1 and n>0 depend on the kernel version:
In addition to the safe hooks, other hooks can get activated,
for example one for int 0x2f, ax=0x1680 "release time slice".
Note: In rare cases, entering or leaving HLT mode (which causes
big changes in CPU power consumption) can cause crashes if
cheap power supplies or mainboards cannot properly filter
the transients. Underclocking the whole system may help.
Linux always does a few HLT at boot time, to force a hang
on buggy systems early (boot with no-hlt to disable HLT).
P90 may have buggy HLT? www.tavi.co.uk/ps2pages/ohland/halt.html
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.
Example: install=nansi.com
KEYBUF
Usage: keybuf=n[,m]
where n is in 0xac-0xde or 0x106-0x1de range and m is max 0x200
Relocate keyboard buffer from the default location at
0x40:0x1e-0x3e to 0x40:n-m. The buffer must be more
than 32 bytes and must not touch offsets 0x100-0x105.
Default for m is "next multiple of 0x100 after n".
Note: Some BIOSes store data in the 0xac-0xff area. BASICA will
use the 0x106-0x120 area. Other hardware, drivers or apps
can collide with KEYBUF, too, so use it at your own risk.
A reasonably safe choice should be "keybuf=0x140,0x1c0".
LASTDRIVE
LASTDRIVEHIGH
Usage: lastdrive=x
where x is last drive letter available for use; A-Z
Example: lastdrive=z
MENU
Usage: menu [text]
where text is the text you want to be shown while running
config.sys. Menu displays a menu while running config.sys.
Use menudefault to set a time delayed default option.
Lines that begin with 1? will only be processed if the user
presses 1. Lines beginning with 23? will be loaded if the
user presses either 2 or 3. Options other than 0 can only
be selected if at least one "numbers?" line actually uses
them, as shown in the example below.
Example:
menu Please Select Configuration:
menu
menu Option 0 basic stuff only
menu Option 1 CD-ROM
menu Option 2 TROUSERS
menu Option 3 CD-ROM and TROUSERS
0?echo you selected option 0
13?device=xcdrom.sys /D:FDCD0001
23?install=trousers.com
MENUCOLOR
Usage: menucolor foreground[,background]
Use Menucolor before the menu config command, to create a
full screen menu which supports the arrow cursor keys.
The following colors can be used for foreground and background:
0=Black; 1=Blue; 2=Green; 3=Cyan; 4=Red; 5=Magenta;
6=Brown; 7=Light Gray
The following colors can only be used for the foreground:
8=Dark Gray; 9=Light Blue; 10=Light Green; 11=Light Cyan;
12=Light Red; 13=Light Magenta; 14=Yellow; 15=White.
If you do not use MENUCOLOR, the menu will not be full
screen, so some of the BIOS, bootloader and kernel init
messages (list of drives, version info...) stays visible.
To change the colour to white text on blue, use the following:
Example: menucolor 15,1
MENUDEFAULT
Usage: menudefault=defaultoption,delay
where delay is the delay time in seconds and defaultoption is the
used standard option if the delay time is over. Menudefault sets
a time delayed default option for a config.sys menu: If no key
has been pressed during [delay] seconds, the default choice is
activated. Pressing a key stops the countdown, the kernel will
wait infinitely for the user to make a selection. Note that some
virtual machines like Bochs can have broken (too fast) timing.
Example: menudefault=0,5
NUMLOCK
Usage: numlock=on|off
Set the keyboard number lock to on or off.
Example: 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 is ignored. This may also be used to temporarily disable
loading a particular device or other option. A synonym for REM is
the semicolon, see the examples.
Example: REM DOS=HIGH,UMB
Example: ;DOS=HIGH,UMB
SCREEN
Usage: screen=xx
Switches into videomode xxx (INT10/11xx/000)
where xx should be 0x11 for 8x14 font (28 lines VGA, 25 lines EGA)
or 0x12 for 8x8 font (43 lines EGA, 50 lines VGA) or 0x14 for the
default VGA font (25 lines VGA). Some newer graphics cards may not
have 8x14 fonts in the BIOS. In that case, a driver can be loaded
to load a suitable font in RAM, but SCREEN=0x11 should not be used.
If xx is less than 15 (0x0f), it is treated as screen mode number,
for example 1 for CGA 40x25 color text or 7 for monochrome text.
Example: SCREEN=0x12
SET
Usage: set ENVVAR=value
Sets the environment variable to provided value.
Example: 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.
Example: shell=C:\4DOS.COM /E:256 /P
Example: SHELL=C:\FDOS\bin\command.com C:\FDOS\bin /E:1024 /P=C:\fdauto.bat
STACKS
STACKSHIGH
Usage: stacks=nn,mmm
where nn is in range 0,8-64 and nnn is in range 32-512
Changes number and size of hardware interrupt stacks available
nn is number of different stacks and mmm is size in bytes of each one
In some cases you can use "stacks=0,0" to use only standard stacks
instead of letting DOS allocate extra stacks for hardware interrupts.
Example: 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. The switch character is the sign used to
mark options, for example the "/" in "DIR /w". Good values: "/" and "-".
Example: switchar=-
SWITCHES
Usage: switches=/E[:xxx] /F /K /N /W
Adjusts boot time processing behaviour.
/E enables moving of EBDA (Extended BIOS Data Area), optionally a
size in kilobytes may be specified [xxx, in range of 48-1024]
/F skips the delay checking for F5/F8 keystroke before processing
config.sys [equivalent to SYS CONFIG skipconfigseconds=0]
F5 and F8 are only processed if pressed before DOS boots but
after the keyboard is set up - right moment is easy to miss.
/K forces treating of keyboard as 86 key keyboard, not 102/105 key.
Might be useful with BIOSes or drivers which have no or broken
handling for 102/105 key keyboards.
/N disables F5/F8 support [equivalent to kernel config (SYS CONFIG,
run SYS CONFIG /? for explanations) skipconfigseconds=-1]
F5 (skip config) and F8 (single step config.sys) are ignored.
/W is NOT supported in FreeDOS. This option in MS DOS would set a flag
for Windows 3.0 to skip loading wina20.386 from the root directory.
VERSION
Usage: version=x.y
FreeDOS specific command to specify what DOS version to report. For
a kernel with FAT32 support, 7.10 is a good choice. Otherwise, 5.0
and 6.22 are common values. FreeCOM command.com "ver /r" displays
both the reported and the FreeDOS internal version numbers.
Example: version=6.22
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:
MENU
MENU select your configuration
MENU
MENU use (1) for CDROM operation
MENU use (2) for NETWORK configuration
MENU use (3) to load neither CDROM nor NETWORK drivers
MENU
MENUDEFAULT=3,60 (configuration 3, wait 60 seconds)
rem CDROM
1? device=CDROM.SYS
rem NETWORK
2? device=MyNetworkDriver.SYS
rem Menu items can only be selected if at least one line uses them:
3? echo Basic configuration selected
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.
constructions like 0?devicehigh?=cdrom.sys are also possible
("if menu option 0 chosen, ask if you want to load this driver")
the selected configuration can be determined in AUTOEXEC.BAT in the
environment variable CONFIG like
if %CONFIG% == 0 echo configuration 0 selected
however, if you have no MENUs in config.sys, then %config% has no value,
thus resulting in "IF == 0 echo configuration 0 selected."
(which causes syntax errors as there's nothing on the left side of == )
That's why you better use something like:
if [%config%]==[0] echo configuration 0 selected. -or-
if "%config%"=="0" echo configuration 0 selected.
then if there is no menu you have: "IF []==[0] echo configuration 0 selected."
(which will of course output nothing)
thus my config.sys now looks like
!files=20
!dos=high,umb
!break=off
!buffers=30
!screen=0x12
!lastdrive=z
!shell=\command.com /p /e:512 /MSG
MENU
MENU 0 - SoftIce+HIMEM+Network (default)
MENU 1 - SoftIce+HIMEM
MENU 2 - HIMEM+EMM386
MENU
MENUDEFAULT=0,0
01? DEVICE=C:\NUMEGA\S-ICE.EXE /TRA 3000 /SYM 400
012?DEVICE=himem.exe
01? DEVICE=UMBPCI.SYS
2? DEVICE=EMM386.EXE NOEMS
0?device=c:\ntclient\ifshlp.sys
DEVICE=xcdrom.sys /D:MSCD000
Full Screen Menus (thanks to Rune Espeseth)
Use MENUCOLOR=foreground[,background] to obtain a full screen menu
where you can use the arrow keys. Example (note that box drawing
characters are used that look strange in other character sets):
REM *** This is the FreeDos Config.sys ***
REM *** executed before autoexec.bat ***
REM *** Set white foreground, red background ***
menucolor=7,4
files=20
buffers=20
REM *** The Menu ***
MENU
MENU *-------------------------------------------------------*
MENU ! My Menu - FreeDOS rules! !
MENU *-------------------------------------------------------*
MENU ! !
MENU ! 1. Test with border !
MENU ! !
MENU ! 2. Another test... !
MENU ! !
MENU ! 3. Third choice !
MENU ! !
MENU ! 4. Fourth choice. !
MENU ! !
MENU *-------------------------------------------------------*
MENU
MENUDEFAULT=1,10 ( configuration 1, wait 10 seconds)
REM 1st choice
1?ECHO You selected menu #1
REM 2nd choice
2?ECHO You selected menu #2
REM 3rd choice
3?ECHO You selected menu #3
REM 4th choice
4?ECHO You selected menu #4
2002-11-28 - Tom Ehlert
2003-07-15 - Bernd Blaauw
2003-09-18 - Bart Oldeman
2004-07-24 - Jeremy Davis
...
2008-22-01 - Fritz Mueller / Eric Auer

44
docs/contrib.txt Normal file
View File

@ -0,0 +1,44 @@
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 the current kernel maintainer so we can add you to the list!
Thanks to all the following for contributing to the FreeDOS kernel:
Aitor Santamaria (aitor.sm@wanadoo.es)
Arkady Belousov (ark@mos.ru)
Bart Oldeman (bart@dosemu.org)
Bernd Blaauw (bblaauw@home.nl)
Brian Reifsnyder (reifsnyderb@mindspring.com)
Charles Dye (raster@highfiber.com)
Eduardo Casino (casino_e@terra.es)
Eric Auer (e.auer@jpberlin.de)
Eric Biederman (ebiederm+eric@ccr.net)
Eric Luttmann (ecl@users.sourceforge.net)
Fritz Mueller (fritz.mueller@mail.com)
Geraldo Netto (geraldonetto@gmail.com)
Helmut Fritsch (helmut.fritsch@gcd-hs.de)
James Tabor (jimtabor@infohwy.com)
Jason Hood (jadoxa@yahoo.com.au)
Jens Horstmeier (Jens.Horstmeier@abg1.siemens.de)
Jeremy Davis (jeremyd@fdos.org)
Jim Hall (jhall@freedos.org)
John Price (linux-guru@gcfl.net)
Kolya Ksenev (7207@mx.csd.tsu.ru)
Lixing Yuan (yuanlixg@china.com)
Luchezar Georgiev (lig@linux.tu-varna.acad.bg)
Martin Stromberg (ams@ludd.luth.se)
Michal Bakowski (mb@orad.pl)
Ron Cemer (roncemer@gte.net)
"ror4" (ror4@angelfire.com)
Rune Espeseth (re@icd.no)
Steffen Kaiser (Steffen.Kaiser@fh-rhein-sieg.de)
Steve Miller (SMiller@dsfx.com)
Tom Ehlert (te@drivesnapshot.de)
Victor Vlasenko (victor_vlasenko@hotbox.ru)
At this place we should also thank Ralf Brown for his interrupt list.
It is a truely invaluable resource for us.
And last, but not least, a big thanks to Pasquale J. Villani
(patv@iop.com), who is the original author of DOS-C, on which
the FreeDOS kernel is based.

340
docs/copying Normal file
View File

@ -0,0 +1,340 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation
Inc., 51 Franklin Street, Fifth Floor Boston, MA 02110-1301 USA
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.

13
docs/fdkernel.lsm Normal file
View File

@ -0,0 +1,13 @@
Begin3
Title: The FreeDOS Kernel
Version: SVN
Entered-date: N/A
Description: The FreeDOS Kernel
Keywords: kernel, FreeDOS, DOS, MSDOS
Author: (developers: can be reached on the freedos-kernel mailing list)
Maintained-by: freedos-kernel@lists.sourceforge.net
Primary-site: http://freedos.sourceforge.net/kernel/
Original-site: http://www.gcfl.net/pub/FreeDOS/kernel
Platforms: DOS, FreeDOS, DOSEMU (OpenWatcom C or Turbo C, NASM, optionally UPX)
Copying-policy: GPL2
End

3911
docs/history.txt Normal file

File diff suppressed because it is too large Load Diff

198
docs/intfns.txt Normal file
View File

@ -0,0 +1,198 @@
Technical Data
DOS-C Systems Calls
The following table represents the industry standard kernel DOS calls
currently supported by DOS-C. This list is for FreeDOS build 2036 (5/2006).
int 20: Terminated Current Process
Supported
int 21: DOS System Call
Supported. See table below.
int 21 Description State Ver Status
---------------------------------------------------------------------------
00h Terminate Program superseded 1.00 supported
01h Read Keyboard with Echo superseded 1.00 supported
02h Display Character superseded 1.00 supported
03h Auxilliary Input superseded 1.00 supported
04h Auxilliary Output superseded 1.00 supported
05h Print Character superseded 1.00 supported
06h Direct Console I/O active 1.00 supported
07h Direct Console Input active 1.00 supported
08h Read Keyboard Without Echo active 1.00 supported
09h Display String superseded 1.00 supported
0ah Buffered Keyboard Input superseded 1.00 supported
0bh Check Keyboard Status active 1.00 supported
0ch Flush Buffer, Read Keyboard active 1.00 supported
0dh Reset Drive active 1.00 supported
0eh Set Default Drive active 1.00 supported
0fh Open File with FCB superseded 1.00 supported
10h Close File with FCB superseded 1.00 supported
11h Find First File with FCB superseded 1.00 supported
12h Find Next File with FCB superseded 1.00 supported
13h Delete File with FCB superseded 1.00 supported
14h Sequential Read superseded 1.00 supported
15h Sequential Write superseded 1.00 supported
16h Create File with FCB superseded 1.00 supported
17h Rename File with FCB superseded 1.00 supported
18h CP/M compatibility obsolete 1.00 supported
19h Get Default Drive active 1.00 supported
1ah Set Disk Transfer Address active 1.00 supported
1bh Get Default Drive Data superseded 2.00 supported
1ch Get Drive Data superseded 2.00 supported
1dh CP/M compatibility obsolete 1.00 supported
1eh CP/M compatibility obsolete 1.00 supported
1fh Get Default DPB active 5.00 supported
20h CP/M compatibility obsolete 1.00 supported
21h Random Read superseded 1.00 supported
22h Random Write superseded 1.00 supported
23h Get File Size superseded 1.00 supported
24h Set Random Record Number superseded 1.00 supported
25h Set Interrupt Vector active 1.00 supported
26h Create New PSP superseded 1.00 supported
27h Random Block Read superseded 1.00 supported
28h Random Block Write superseded 1.00 supported
29h Parse Filename active 1.00 supported
2ah Get Date active 1.00 supported
2bh Set Date active 1.00 supported
2ch Get Time active 1.00 supported
2dh Set Time active 1.00 supported
2eh Set/Reset Verify Flag active 1.00 supported
2fh Get DTA active 2.00 supported
30h Get Version Number active 2.00 supported
31h Keep Program active 2.00 supported
32h Get DPB active 5.00 supported
3300h Get CTRL+C Check Flag active 2.00 supported
3301h Set CTRL+C Check Flag active 2.00 supported
3305h Get Startup Drive active 2.00 supported
3306h Get MS-DOS Version active 5.00 supported
33ffh Get DOS-C Release superset supported
34h Get InDOS Flag Address active 2.00 supported
35h Get Interrupt Vector active 2.00 supported
36h Get Disk Free Space active 2.00 supported
37h Get/Set Switchar undocumented 2.00 supported
38h Get/Set Country Information active 2.00 supported
39h Create Directory active 2.00 supported
3ah Remove Directory active 2.00 supported
3bh Change Current Directory active 2.00 supported
3ch Create File with Handle active 2.00 supported
3dh Open File with Handle active 2.00 supported
3eh Close File with Handle active 2.00 supported
3fh Read File or Device active 2.00 supported
40h Write File or Device active 2.00 supported
41h Delete File active 2.00 supported
42h Move File Pointer active 2.00 supported
4300h Get File Attributes active 2.00 supported
4301h Set File Attributes active 2.00 supported
44h Ioctl entry active 2.00 supported
45h Duplicate File Handle active 2.00 supported
46h Force Duplicate File Handle active 2.00 supported
47h Get Current Directory active 2.00 supported
48h Allocate Memory active 2.00 supported
49h Free Allocated Memory active 2.00 supported
4ah Set Memory Block Size active 2.00 supported
4b00h Load and Execute Program active 2.00 supported
4b01h Load Program active 5.00 supported
4b03h Load Overlay active 2.00 supported
4b05h Set Execution State active 5.00 PLANNED
4ch End Program active 2.00 supported
4dh Get Child-Program Return Value active 2.00 supported
4eh Find First File active 2.00 supported
4fh Find Next File active 2.00 supported
50h Set PSP Address active 2.00 supported
51h Get PSP Address active 2.00 supported
52h Get List of Lists undocumented 2.00 supported
53h Translate BPB to DPB undocumented supported
54h Get Verify State active 2.00 supported
55h Create New Psp undocumented 2.00 supported
56h Rename File active 2.00 supported
5700h Get File Date and Time active 2.00 supported
5701h Set File Date and Time active 2.00 supported
5800h Get Allocation Strategy active 3.00 supported
5801h Set Allocation Strategy active 3.00 supported
5802h Get Upper-Memory Link active 5.00 supported
5803h Set Upper-Memory Link active 5.00 supported
59h Get Extended Error active 3.00 supported
5ah Create Temporary File active 3.00 supported
5bh Create New File active 3.00 supported
5ch Lock/Unlock File active 3.10 supported
5d00h Server Function Call active 3.10 supported
5d01h Commit All Files active 3.10 NOTE 3
5d02h Close File by Name active 3.10 NOTE 3
5d03h Close All Files for Computer active 3.10 NOTE 3
5d04h Close All Files for Process active 3.10 NOTE 3
5d05h Get Open File List active 3.10 NOTE 3
5d06h Get Multiple SDA active 4.00 supported
5d07h Get Redirected Printer Mode active 3.10 supported
5d08h Set Redirected Printer Mode active 4.00 supported
5d09h Flush Redirected Printer Output active 4.00 supported
5d0ah Set Extended Error active 4.00 supported
5eh Generic Network Functions #1 active 3.10 supported
5fh Generic Network Functions #2 active 3.10 supported
60h Truename function undocumented 3.00 supported
61h UNUSED obsolete supported
62h Get current PSP active 3.00 supported
63h Multibyte char ops undocumented 3.20 NOTE 1
64h ? undocumented returns error
65h NLS Functions active 3.30 supported
66h Code Page Functions active 3.30 supported
67h Set Maximum Handle Count active 3.30 supported
68h Commit File active 3.30 supported
69h GET/SET DISK SERIAL NUMBER active 4.00 supported
6ah COMMIT FILE (same as 68h) active 4.00 supported
6bh NULL FUNCTION active 5.00 supported
6ch Extended Open/Create active 4.00 supported
71h LONG FILENAME FUNCTIONS active 7.00 NOTE 2
int 22: Program Termination Address.
Supported.
int 23: Ctrl-C/Ctrl_Break Handler.
Supported.
int 24: Critical Error Handler
Dummy routine default.
int 25: Absolute Disk Read
Supported.
int 26: Absolute Disk Write
Supported.
int 27: TSR
Supported.
int 28: DOS Idle.
Supported.
int 29: Fast Console Output.
Supported.
int 2F: DOS Multiplex.
Supported (not ALL functions, but MOST functions supported)
Notes:
Note 1 - function 63 Returns error code and lead byte table pointer
DS:SI (function 0). Functions 1 and 2 return error code -1
(Korean Hangul keyboard input method not supported), but our
UNSTABLE kernels can contain more NLSFUNC / COUNTRY support.
Note 2 - for LFN support, you can load a separate driver like DOSLFN.
It will hook int 21 and provide long file name functionality.
Note 3 - planned, but the implementation will be in SHARE. The DOS
kernel only calls hooks (via far call) in a table which is
right before the SFT (list of lists [4] points to SFT). As
long as our SHARE does not support the hooks, they are not
supported either, the unused hook table would waste memory.
License
-------
See COPYING in DOS-C root directory for license.
---------------------------------------------------------------------
$Id: intfns.txt 1344 2007-07-28 18:29:50Z mceric $

21
docs/lfnapi.txt Normal file
View File

@ -0,0 +1,21 @@
FreeDOS LFN helper API.
struct lfn_inode
{
UNICODE name[261];
struct dirent l_dir; /* this file's dir entry image */
ULONG l_diroff; /* offset of the dir entry */
};
typedef struct lfn_inode FAR * lfn_inode_ptr;
COUNT lfn_allocate_inode(VOID);
COUNT lfn_free_inode(COUNT handle);
COUNT lfn_setup_inode(COUNT handle, ULONG dirstart, ULONG diroff);
COUNT lfn_create_entries(COUNT handle, lfn_inode_ptr lip);
COUNT lfn_dir_read(COUNT handle, lfn_inode_ptr lip);
COUNT lfn_dir_write(COUNT handle);

11
docs/mkboot.txt Normal file
View File

@ -0,0 +1,11 @@
To create a bootable floppy suitable for copying the system to
another drive:
1. Change directory (if necessary) to where the FreeDOS Kernel BIN
directory.
3. Enter the command "install" to transfer the system files to the
diskette in drive A. If you want to install on drive B, type
"install b:"
4. Write protect this disk and use it to boot from.

191
docs/nls.txt Normal file
View File

@ -0,0 +1,191 @@
Current version: $Id: nls.txt 59 2000-08-06 04:42:32Z jimtabor $
This document describes all aspects of the implementation
of NLS in the FreeDOS kernel -- 2000/06/16 ska
Note:
At this time this document contains only an overall description
of how the FreeDOS NLS works; detailed implementation details are
found in HDR\NLS.H and KERNEL\NLS_LOAD.C. When the FreeDOS developers
finally adopted the current scheme, the larger comments of both
files will be merged into a single document -> this file.
= TOC
= Capabilites of the current implementation.
Tested is:
+ DOS-38 - Get Country Information
+ DOS-65-[2A][0-2] - upcase normal/filename characters
+ DOS-65-23 - YesNo prompt character
+ DOS-65-01 - Get Extended Country Information
+ DOS-65-0[24] - Get pointer to normal/filename upcase table
+ DOS-65-05 - Get pointer to filename terminator table
+ DOS-65-06 - Get pointer to collating sequence table
+ DOS-65-07 - Get pointer to DBCS table
Note: Because I don't know how this used, only an empty table
has been verified to work properly.
+ DOS-66-01 - Get active codepage
+ MUX-14-00 - Installation check
+ MUX-14-02 - Get extended country information
+ MUX-14-04 - Get country information
+ MUX-14-FE - DRDOS get extended country information
+ MUX-14-23 - validate Yes/No prompt (FreeDOS extension)
+ MUX-14-22 - upcase normal character area (FreeDOS extension)
+ MUX-14-A2 - upcase filename character area (FreeDOS extension)
Not implemented is:
+ DOS-65-00 - Change DOS-65-XX information
+ DOS-66-02 - Set active codepage
Note: The rough interface is available, but no code to actually
to change the codepage.
+ external TSR "NLSFUNC"
+ MUX-14-FF - DRDOS prepare codepage
Not validated is:
+ DOS-38 - Set Country code, because:
1) it relies on DOS-66-02 (Set active code page) and
2) requires external NLSFUNC.
+ COUNTRY= statement in CONFIG.SYS (code avilable, but not tested at all)
+ MUX-14-01 - change codepage & MUX-14-03 - Set codepage, because
the meaning of them is not intentional to me. Both function perform
the same request currently, to change the current codepage or country
code or both (though, see DOS-66-02).
= Supported NLS packages
A NLS package may contain data only or data and code.
If the NLS package shall not contain any code, it must conform to the
code already included within the kernel; otherwise an external TSR,
usually NLSFUNC, must provide all code by hooking and intercepting
the MUX-14-XX API.
In order to support the external NLSFUNC, all requests for DOS-XX are
re-routed through MUX-14; but because the NLS API must work, even if no
NLSFUNC has been loaded, the kernel implements a MUX-14 interface of its
own and performs all MUX-14 requests.
However, because the channeling of each request through the MUX chain
is considered a very heavy operation (aka time-consuming), flags are
introduced when to _bypass_ the MUX chain and directly call the
function, which would be activated, if the request would reach the
MUX-14 interface of the kernel.
Because the kernel can only load NLS packages structurally identical to
U.S.A./CP437 per definition, the kernel automatically sets those flags,
thus, retreives all information from them without to channel the request
through the MUX interrupt chain.
The term "structurally identical" is explained in NLS.H.
= Using NLS functions from within the kernel
There are functions to:
+ upcase normal characters: DosUpMem(), DosUpString(), DosUpChar()
+ upcase filename characters: DosUpFMem(), DosUpFString(), DosUpFChar()
+ verify yes/no prompt characters: DosYesNo()
+ retreive data (country informaion): DosGetData() [DOS-65-XX],
DosGetCountryInformation() [DOS-38]
They implement the usual DOS interface and refer to the country code and
codepage by the usual UWORD numbers; NLS_DEFAULT can be used to specify
"current country/codepage". The "Up*()" functions always use the currently
active NLS package.
These functions are also called by the INT-21 handler.
Because of the MUX chain support these functions more or less wrap the
real functions only and check the flags whether to call the internal
function directly or re-route the request through MUX.
Therefore NLS data must not be accessed directly from outside the NLS
implementation, but through these functions only.
CAUTION: The DOS NLS differs between "normal" characters and "filename"
characters, that's why one must call DosUpFString() to upcase a
filename rather than DosUpString()!
Note: The NLS subsystem is robust against any type of characters,
that means DosUpFMem() can be called with any type of junk, except
the pointer to the buffer must not be NULL.
= NLS and fileformats (UNF)
The current implementation does not implemented everything MS-DOS like,
this includes the internal NLS information block and the fileformat of
COUNTRY.SYS. Both structures shall be updated to increase performance,
rather than require the kernel to simulate old and obsolated interfaces.
To overcome the traditional problem with ever-changing structures
a toolset is provided to represent the NLS package in an implementation-
independed way and read/write/manipulate etc. pp. this data.
In the final state NLSFUNC will automatically detect the structures
and transform them into the structure required by the kernel.
To minimize the complexity of these data transformation processes
an independed fileformat called UNF (Uniform NLS file Format) has been
founded, which is totally plain text (except comments) and somewhat
human-readable. Tools will be provided to convert any or particular binary
forms of NLS packages into UNF and back.
Currently available tools:
GRAB_UNF: Extracts all information from the current NLS API and dumps it
into an UNF file. Supports standard information and DOS-65-03 (lowercase).
UNF2HC: Transforms an UNF file into the format of the hardcoded NLS package
ready to be used when the kernel is make'ed.
= Testing / Verifying NLS
Above mentioned UNF toolset includes:
GRAB_UNF: Dump NLS package into UNF file and
NLSUPTST: Test upcase API (DOS-65-2[0-2]).
Testing steps:
1) Generate an UpCase test verifaction file by running "NLSUPTST /c" on
a DOS computer that is entitled to run a good NLS.
Alternatively download an UP file corresponding to your locale,
that means <country>-<codepage>.UP (without the angle brackets).
Note: The numerical country code and codepage must match the settings
of your testee system!
2) Do the same an generate an sample UNF of a good NLS, by running
"GRAB_UNF.EXE" or download one from the internet. the filename is:
<country>-<codepage>.UNF
Note: If you manually edit the file, run "READ_UNF <filename>" to
check the file for errors and dump it in the very same format as
GRAB_UNF will.
3) Copy GRAB_UNF.EXE, NLSUPTST.EXE and the UP file onto the testee, e.g.
floppy. Make sure no .UNF file is located there.
4) Create the CONFIG.SYS with only the minimum settings, more than
a COUNTRY= and a SHELL= are usually NOT required.
5) Create an AUTOEXEC.BAT with this contents (strip leading tabs):
GRAB_UNF.EXE
NLSUPTST.EXE
Note: If you have NLS_DEBUG enabled, a lot of noise will be displayed!
6) Reboot the testee
7) The GRAB_UNF.EXE will display its success by:
"NLS info file for <country>-<codepage> has been created sucessfully"
In this case an UNF file has been created <-> the only way to see this
success status, if NLS_DEBUG is enabled within the kernel.
8) At some point you should see an error message or the good news:
"NLS passed all DOS-65-2[0-2] tests"
This means that NLSUPTST was successful, because there is no other
way to detect this, NLSUPTST must be placed last.
9) Compare the <country>-<codepage>.UNF file form the directory you
run GRAB_UNF.EXE in with the _equally_ named sample file.
Both must be 100% identical, even the number of spaces are.
If COMMAND.COM fails to run AUTOEXEC.BAT, change the SHELL= line within
CONFIG.SYS into:
SHELL=GRAB_UNF.EXE
-and-
SHELL=NLSUPTST.EXE
and boot the testee once with each line.
What do these tests miss?
+ None of these tests try to change neither country code nor code page.
+ By default, these tests cannot override the internal performance flags
and so either the direct-calling or the MUX-re-routing mechanism
is tested, but never both.

64
docs/readme.cvs Normal file
View File

@ -0,0 +1,64 @@
Thanks to Bart Oldeman for helping us with moving the FreeDOS source code
from CVS to Subversion! The old CVS repository is still available for
browsing, but will no longer be used for managing FreeDOS Projects - and
will probably be deleted later. Please use Subversion for the FreeDOS
kernel, FreeCOM (FreeDOS command.com), Install, and Mem.
Bart has also written a Subversion at SourceForge Mini How-to:
http://fd-doc.sourceforge.net/wiki/index.php?n=FdDocEn.SVN
This information was mostly lifted from SourceForge.net:
https://sourceforge.net/svn/?group_id
FreeDOS Subversion:
Subversion (SVN) is a tool used by many software developers to manage
changes within their source code tree. SVN provides the means to store not
only the current version of a piece of source code, but a record of all
changes (and who made those changes) that have occurred to that source code.
Use of SVN is particularly common on projects with multiple developers,
since SVN ensures changes made by one developer are not accidentally removed
when another developer posts their changes to the source tree.
In order to access a Subversion repository, you must install a special piece
of software called a Subversion client. Subversion clients are available for
most any operating system.
To get a working copy, do svn co URL freedos where URL is the complete path
to the trunk of the project you want. For example:
FreeDOS kernel
https://freedos.svn.sourceforge.net/svnroot/freedos/kernel/trunk
FreeDOS FreeCOM
https://freedos.svn.sourceforge.net/svnroot/freedos/freecom/trunk
FreeDOS MEM
https://freedos.svn.sourceforge.net/svnroot/freedos/mem/trunk
FreeDOS Install
https://freedos.svn.sourceforge.net/svnroot/freedos/install/trunk
Be careful NOT to use the top level
* https://freedos.svn.sourceforge.net/svnroot/freedos URL
instead of one of the trunk URLs. This will pull all modules, tags and/or
branches of the project - it will be huge. Instead, you will want to use
/trunk to the URL to check out only the trunk code (main development line).
Though Subversion repositories are most commonly accessed using a special
piece of software called a Subversion client, SourceForge also provides a
web-based interface to view Subversion repositories. Browsing the Subversion
tree gives you a great view into the current status of this project's code.
You may also view the complete history of any file in the repository.
* Browse Subversion repository
http://freedos.svn.sourceforge.net/viewvc/freedos/
FreeDOS is a trademark of Jim Hall.
Note: Readonly access via the old CVS interface worked as follows:
To check out the code, first log in:
cvs -z3 -d:pserver:anonymous@cvs.freedos.sourceforge.net:/cvsroot/freedos login
Password: Press the Enter key.
Then, to get the kernel code:
cvs -z3 -d:pserver:anonymous@cvs.freedos.sourceforge.net:/cvsroot/freedos checkout kernel

38
docs/readme.txt Normal file
View File

@ -0,0 +1,38 @@
INTRODUCTION
------------
This archive contains the current FreeDOS Kernel, also
known as DOS-C, originally written by Pasquale J. Villani.
The FreeDOS Kernel is available from http://freedos.sourceforge.net/
It's also available from http://www.dosemu.org/ (somewhere on there).
The FreeDOS Kernel is also available through the FreeDOS Project at
http://www.freedos.org/
See the DOCS directory for more documentation and information about
the FreeDOS Kernel.
Contents of zip files:
ke20xx_16.zip : binaries for 8086, FAT16
ke20xx_32.zip : binaries for 8086, FAT16, FAT32
ke20xxsrc.zip : sources for the kernel
BUG REPORTS
-----------
If you have found a bug, think you have found a bug, or would just
like to make a suggestion, go to the bug tracking web page at
http://sourceforge.net/tracker/?group_id=5109&atid=105109
An archive of old (Bugzilla) items is at www.freedos.org/bugzilla/
There is also a feature request tracker on our SourceForge pages at
http://sourceforge.net/tracker/?atid=355109&group_id=5109&func=browse
Copyright
---------
DOS-C is (c) Copyright 1995, 1996 by Pasquale J. Villani
All Rights Reserved.

223
docs/sys.txt Normal file
View File

@ -0,0 +1,223 @@
FreeDOS System Installer v3.6e - Nov 13, 2009
documentation by:
Jeremy Davis
Bart Oldeman
SYS's standard behavior is very similar (though in
my opinion improved) to that of other DOSes.
SYS /? (or no options) should provide a general usage,
and SYS CONFIG /help (or SYS CONFIG /?) should
provide usage for the new configuration options.
The best documentation is the source itself, but
we try to keep this document updated.
Usage: SYS [source] drive: [bootsect] [{option}]
source = A:,B:,C:\KERNEL\BIN\,etc., or current directory if not given
dest = drive (A:,B:,C:,... or A,B,C,...) to install system to
bootsect = name of 512-byte boot sector file image for drive:
to write to *instead* of real boot sector
{option} is one or more of the following:
/BOTH : write to *both* the real boot sector and the image file
/BOOTONLY: do *not* copy kernel / shell, only update boot sector or image
/UPDATE : copy kernel and update boot sector (do *not* copy shell)
/OEM : indicates boot sector, filenames, and load segment to use
/OEM:FD use FreeDOS compatible settings
/OEM:DR use DR DOS 7+ compatible settings (same as /OEM)
/OEM:PC use PC-DOS compatible settings
/OEM:MS use MS-DOS compatible settings
/OEM:W9x use MS Win9x DOS compatible settings
default is /OEM:AUTO, select DOS based on existing files
/K name : name of kernel to use in boot sector instead of KERNEL.SYS
/L segm : hex load segment to use in boot sector instead of 0x60
/B btdrv : hex BIOS # of boot drive set in bs, 0=A:, 80=1st hd,...
/FORCE : override automatic selection of BIOS related settings
/FORCE:BSDRV (/FORCEDRV) use boot drive # set in bootsector
/FORCE:BIOSDRV use boot drive # provided by BIOS
/FORCE:AUTO select LBA or CHS depending on BIOS availability
/FORCE:LBA always use LBA
/FORCE:CHS always use CHS
/NOBAKBS : skips copying boot sector to backup bs, FAT32 only else ignored
/SKFN filename : copy from filename to KERNEL.SYS; settings same as /OEM:FD
/SCFN filename : copy from filename to COMMAND.COM
/BACKUPBS [path]filename : save current bs before overwriting
/DUMPBS [path]filename : save current bs and exit
/RESTORBS [path]filename : overwrite bs and exit
/VERBOSE : display additional (debug) output
SYS CONFIG /help
The simplest usage:
SYS dest:
dest should be the drive (A:, B:, C:, ...) you wish
to be bootable with FreeDOS (kernel & command.com)
When using this form, KERNEL.SYS and COMMAND.COM
must reside either in the current directory (which
is searched first) or in recent revisions may also
be in the root directory of the current drive.
Complete form:
SYS [source] dest: [bootsect [/BOTH]]
Here dest is the same as before, but this time
you specify where KERNEL.SYS and COMMAND.COM are.
Source may simply be a drive (in this case it
is similar to PC & MS SYS). The current directory
of the specified drive is first searched for
KERNEL.SYS & COMMAND.COM and if not found then
the root directory of the specified drive is tried.
Alternatively, you may specify a path (either fully
qualified or relative) to where KERNEL.SYS and
COMMAND.COM may be found; note that this should
only search this directory and will fail if they
are not found, ie it will not check for them on
the root directory of the drive specified when
a path is given. It should also fail if the
source and destination drive are both the same
and would result in trying to SYS from the root
to the root (ie trying to SYS from C:\ to C:\).
If you specify a name for "bootsect", for instance,
bootsect.fd, SYS will write to that file instead of
the real boot sector. You will obtain a 512-byte file
containing the boot sector, which can then be used
for dual booting or diagnostic purposes.
If you also specify BOTH, sys will write to both
the image file and the boot sector.
The FORCE options override the default actions
to use. On FAT32 drives /FORCE:LBA and /FORCE:CHS
will select which boot sector code is used (default
same as /FORCE:AUTO will choose based on query of
BIOS support for LBA extensions and use LBA if it
is supported else only CHS will be used). On FAT12
and FAT16 drives specifying /FORCE:LBA will ensure
even 1st floppy drive attempts to use LBA support
(note that CHS may still be used if LBA check fails)
and /FORCE:CHS will always bypass use of LBA extensions.
Kernel Configuration Options:
Simplest form:
SYS CONFIG
This will simply display the current settings
for the file KERNEL.SYS in the current directory.
It is useful to see what the options are currently
set to, what options are supported, and should
show valid values along with defaults (defaults are
the valid values with a '*' next to them).
Optionally specify file:
SYS CONFIG [drive][path]KERNEL.SYS
This form behaves as above, except will display
the settings for the kernel file you specify.
drive and path are optional, and generally just
a \ will be used to indicate root directory of
current drive. KERNEL.SYS specifies the filename
of the kernel, which may not be "KERNEL.SYS",
for example when testing you want to alter
KERNTEST.SYS and later copy (or rename) this to
KERNEL.SYS for booting.
Changing options:
SYS CONFIG OPTION1=value [OPTION2=value ...]
This form will read the current settings from
the kernel (KERNEL.SYS in the current directory)
and set the options specified to the value given.
If the value is potentially invalid (too large, too
small, etc) then a warning will be displayed, but
the change will still occur. The kernel file is
only updated if at least one option is different from the
current settings. If you wish to force the kernel
file to be written to, then set the same option
twice (OPTION1=oddvalue OPTION1=desiredvalue), with
the 1st time the value being different from the
current one and the rightmost one being the desired
value. Currently three options are supported.
Note: currently only the 1st three letters are
actually checked, so they may be abreviated to
DLA, SHO, and SKI and with my recent patch you may
specify the value as either a decimal number 0,10,255,...
or as a hexidecimal number 0x0,0xA, 0xFF...
DLASORT which may be set to 0 or 1
DLASORT=0 or DLASORT=1
This option is for specifying whether Drive Letter
Assignment should follow the normal MSDOS way of
all primary partitions across drives and then
extended partitions, or the more logical
all partitions (primary & extended) on the 1st
drive, then repeat for all following drives
(all primary & extended, then try next drive).
0 corresponds to MS way and 1 corresponds to first
drive completely, then next ...
SHOWDRIVEASSIGNMENT which may be 0 or 1
SHOWDRIVEASSIGNMENT=0 or SHOWDRIVEASSIGNMENT=1
If 1 then the normal drive assignment information
is displayed upon booting. If 0 then this information
is supressed (not shown).
SKIPCONFIGSECONDS which may be -128 to 127.
A negative value ( < 0 ) indicates that F5/F8
processing will be skipped (the kernel won't check
if you pressed these keys, so you can't skip config
file (CONFIG.SYS) processing). A 0 means you must
have pressed the key precisely for when the kernel
checks for it - essentially skipping, though a well
timed finger will still get to use it. And any value
greater than 0 is the number of seconds the kernel will
display the prompt and wait for you to press the key
before assuming you didn't.
FORCELBA which may be 0 or 1
FORCELBA=0 or FORCELBA=1
If 1 then the kernel will use LBA (extended INT13)
techniques to address all partitions if possible,
even if these have a non-LBA partition type and
are completely below cylinder 1023 (usually the 8GB
boundary). This is 0 by default, for compatibility
reasons. Setting this to 1 may bypass some buggy
BIOSes and gives slightly better performance.
GLOBALENABLELBASUPPORT which maybe 0 or 1
GLOBALENABLELBASUPPORT=0 or GLOBALENABLELBASUPPORT=1
If 0 then LBA will be completely disabled, irrespective
of the FORCELBA setting. You need this if FreeDOS thinks
you have LBA available, but in reality you do not.
This setting is set to 1 by default.
Example: To set the kernel in the current directory
to have a timeout of 5 seconds (default is 2) run
SYS CONFIG SKI=5
Changing options of specified file:
SYS CONFIG [drive][path]KERNEL.SYS OPTION1=value ...]
This is just like previous section on setting options,
except the first argument after CONFIG specifies which
kernel file to use. The filename is the same form used
for displaying options of specified kernel file described
above.
Example2: To set a kernel in the root directory to
not show drive assignment and change the timeout
to never check
SYS CONFIG \KERNEL.SYS SKI=-1 SHOWDRIVEASSIGNMENT=0x0

229
drivers/floppy.asm Normal file
View File

@ -0,0 +1,229 @@
;
; File:
; floppy.asm
; Description:
; floppy disk driver primitives
;
; Copyright (c) 1995
; Pasquale J. Villani
; All Rights Reserved
;
; This file is part of DOS-C.
;
; DOS-C is free software; you can redistribute it and/or
; modify it under the terms of the GNU General Public License
; as published by the Free Software Foundation; either version
; 2, or (at your option) any later version.
;
; DOS-C is distributed in the hope that it will be useful, but
; WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
; the GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public
; License along with DOS-C; see the file COPYING. If not,
; write to the Free Software Foundation, 675 Mass Ave,
; Cambridge, MA 02139, USA.
;
; $Id: floppy.asm 980 2004-06-19 19:41:47Z perditionc $
;
%include "../kernel/segs.inc"
segment HMA_TEXT
;
; BOOL ASMPASCAL fl_reset(WORD drive);
;
; Reset both the diskette and hard disk system.
; returns TRUE if successful.
;
global FL_RESET
FL_RESET:
pop ax ; return address
pop dx ; drive (DL only)
push ax ; restore address
mov ah,0 ; BIOS reset diskette & fixed disk
int 13h
sbb ax,ax ; carry set indicates error, AX=-CF={-1,0}
inc ax ; ...return TRUE (1) on success,
ret ; else FALSE (0) on failure
;
; COUNT ASMPASCAL fl_diskchanged(WORD drive);
;
; Read disk change line status.
; returns 1 if disk has changed, 0 if not, 0xFFFF if error.
;
global FL_DISKCHANGED
FL_DISKCHANGED:
pop ax ; return address
pop dx ; drive (DL only, 00h-7Fh)
push ax ; restore stack
push si ; preserve value
mov ah,16h ; read change status type
xor si,si ; RBIL: avoid crash on AT&T 6300
int 13h
pop si ; restore
sbb al,al ; AL=-CF={-1,0} where 0==no change
jnc fl_dc ; carry set on error or disk change
cmp ah,6 ; if AH==6 then disk change, else error
jne fl_dc ; if error, return -1
mov al, 1 ; set change occurred
fl_dc: cbw ; extend AL into AX, AX={1,0,-1}
ret ; note: AH=0 on no change, AL set above
;
; Format tracks (sector should be 0).
; COUNT ASMPASCAL fl_format(WORD drive, WORD head, WORD track, WORD sector, WORD count, UBYTE FAR *buffer);
; Reads one or more sectors.
; COUNT ASMPASCAL fl_read (WORD drive, WORD head, WORD track, WORD sector, WORD count, UBYTE FAR *buffer);
; Writes one or more sectors.
; COUNT ASMPASCAL fl_write (WORD drive, WORD head, WORD track, WORD sector, WORD count, UBYTE FAR *buffer);
; COUNT ASMPASCAL fl_verify(WORD drive, WORD head, WORD track, WORD sector, WORD count, UBYTE FAR *buffer);
;
; Returns 0 if successful, error code otherwise.
;
global FL_FORMAT
FL_FORMAT:
mov ah,5 ; format track
jmp short fl_common
global FL_READ
FL_READ:
mov ah,2 ; read sector(s)
jmp short fl_common
global FL_VERIFY
FL_VERIFY:
mov ah,4 ; verify sector(s)
jmp short fl_common
global FL_WRITE
FL_WRITE:
mov ah,3 ; write sector(s)
fl_common:
push bp ; setup stack frame
mov bp,sp
mov cx,[bp+0Ch] ; cylinder number
mov al,1 ; this should be an error code
cmp ch,3 ; this code can't write above 3FFh=1023
ja fl_error ; as cylinder # is limited to 10 bits.
xchg ch,cl ; ch=low 8 bits of cyl number
ror cl,1 ; bits 8-9 of cylinder number...
ror cl,1 ; ...to bits 6-7 in CL
or cl,[bp+0Ah] ; or in the sector number (bits 0-5)
mov al,[bp+08h] ; count of sectors to read/write/...
les bx,[bp+04h] ; Load 32 bit buffer ptr into ES:BX
mov dl,[bp+10h] ; drive (if or'ed 80h its a hard drive)
mov dh,[bp+0Eh] ; get the head number
int 13h ; process sectors
sbb al,al ; carry: al=ff, else al=0
and al,ah ; carry: error code, else 0
fl_error:
mov ah,0 ; extend AL into AX without sign extension
pop bp
ret 14
;
; COUNT ASMPASCAL fl_lba_ReadWrite(BYTE drive, WORD mode, void FAR * dap_p);
;
; Returns 0 if successful, error code otherwise.
;
global FL_LBA_READWRITE
FL_LBA_READWRITE:
push bp ; setup stack frame
mov bp,sp
push ds
push si ; wasn't in kernel < KE2024Bo6!!
mov dl,[bp+10] ; drive (if or'ed with 80h a hard drive)
mov ax,[bp+8] ; get the command
lds si,[bp+4] ; get far dap pointer
int 13h ; read from/write to drive
pop si
pop ds
pop bp
mov al,ah ; place any error code into al
mov ah,0 ; zero out ah
ret 8
;
; void ASMPASCAL fl_readkey (void);
;
global FL_READKEY
FL_READKEY: xor ah, ah
int 16h
ret
;
; COUNT ASMPASCAL fl_setdisktype (WORD drive, WORD type);
;
global FL_SETDISKTYPE
FL_SETDISKTYPE:
pop bx ; return address
pop ax ; disk format type (al)
pop dx ; drive number (dl)
push bx ; restore stack
mov ah,17h ; floppy set disk type for format
int 13h
ret_AH:
mov al,ah ; place any error code into al
mov ah,0 ; zero out ah
ret
;
; COUNT ASMPASCAL fl_setmediatype (WORD drive, WORD tracks, WORD sectors);
;
global FL_SETMEDIATYPE
FL_SETMEDIATYPE:
pop ax ; return address
pop bx ; sectors/track
pop cx ; number of tracks
pop dx ; drive number
push ax ; restore stack
push di
dec cx ; number of cylinders - 1 (last cyl number)
xchg ch,cl ; CH=low 8 bits of last cyl number
ror cl,1 ; extract bits 8-9 of cylinder number...
ror cl,1 ; ...into cl bit 6-7
or cl,bl ; sectors/track (bits 0-5) or'd with high cyl bits 7-6
mov ah,18h ; disk set media type for format
int 13h
jc skipint1e
push es
xor dx,dx
mov es,dx
cli
pop word [es:0x1e*4+2] ; set int 0x1e table to es:di
mov [es:0x1e*4 ], di
sti
skipint1e:
pop di
jmp short ret_AH

49
drivers/makefile Normal file
View File

@ -0,0 +1,49 @@
#
# makefile for device.lib
#
# $Id: makefile 1387 2009-05-19 21:39:29Z bartoldeman $
#
!include "../mkfiles/generic.mak"
# MICROSOFT C
# -----------
#MODEL = s
#CFLAGS = /c /Gs /A$(MODEL)
#AFLAGS = /Mx /Dmem$(MODEL)=1
#TERM = ;
# BORLAND C
# -----------
#MODEL = s
#CFLAGS = -c -m$(MODEL)
#AFLAGS = /Mx /Dmem$(MODEL)=1
#LIBFLAGS = /c
OBJS = floppy.obj rdpcclk.obj wrpcclk.obj wratclk.obj
LIBOBJS= +floppy.obj +rdpcclk.obj +wrpcclk.obj +wratclk.obj
# Build the LIBRARY
# -----------------
all: production
production: ../lib/device.lib
../lib/device.lib: device.lib
$(CP) device.lib ..$(DIRSEP)lib
clobber: clean
-$(RM) device.lib status.me ..$(DIRSEP)lib$(DIRSEP)device.lib
clean:
-$(RM) *.obj *.bak *.crf *.xrf *.map *.lst *.cod *.err
device.lib : $(OBJS)
-$(RM) device.lib
$(LIBUTIL) $(LIBFLAGS) device $(LIBOBJS) $(LIBTERM)

53
drivers/rdpcclk.asm Normal file
View File

@ -0,0 +1,53 @@
;
; File:
; rdpcclk.asm
; Description:
; read the PC style clock from bios
;
; Copyright (c) 1995
; Pasquale J. Villani
; All Rights Reserved
;
; This file is part of DOS-C.
;
; DOS-C is free software; you can redistribute it and/or
; modify it under the terms of the GNU General Public License
; as published by the Free Software Foundation; either version
; 2, or (at your option) any later version.
;
; DOS-C is distributed in the hope that it will be useful, but
; WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
; the GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public
; License along with DOS-C; see the file COPYING. If not,
; write to the Free Software Foundation, 675 Mass Ave,
; Cambridge, MA 02139, USA.
;
; $Header$
;
%include "../kernel/segs.inc"
segment HMA_TEXT
;
; ULONG ReadPCClock(void)
;
global READPCCLOCK
READPCCLOCK:
mov ah,0
int 1ah
extern _DaysSinceEpoch ; ; update days if necessary
; (ah is still 0, al contains midnight flag)
add word [_DaysSinceEpoch ],ax ; *some* BIOSes accumulate several days
adc word [_DaysSinceEpoch+2],byte 0;
; set return value dx:ax
xchg ax,cx ; ax=_cx, cx=_ax
xchg ax,dx ; dx=_cx, ax=_dx (cx=_ax)
ret

63
drivers/wratclk.asm Normal file
View File

@ -0,0 +1,63 @@
;
; File:
; wratclk.asm
; Description:
; WriteATClock - sysclock support
;
; Copyright (c) 1995
; Pasquale J. Villani
; All Rights Reserved
;
; This file is part of DOS-C.
;
; DOS-C is free software; you can redistribute it and/or
; modify it under the terms of the GNU General Public License
; as published by the Free Software Foundation; either version
; 2, or (at your option) any later version.
;
; DOS-C is distributed in the hope that it will be useful, but
; WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
; the GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public
; License along with DOS-C; see the file COPYING. If not,
; write to the Free Software Foundation, 675 Mass Ave,
; Cambridge, MA 02139, USA.
;
; $Header$
;
%include "../kernel/segs.inc"
segment HMA_TEXT
;
; VOID WriteATClock(bcdDays, bcdHours, bcdMinutes, bcdSeconds)
; BYTE *bcdDays;
; BYTE bcdHours;
; BYTE bcdMinutes;
; BYTE bcdSeconds;
;
global WRITEATCLOCK
WRITEATCLOCK:
push bp
mov bp,sp
; bcdSeconds = 4
; bcdMinutes = 6
; bcdHours = 8
; bcdDays = 10
mov ch,byte [bp+8] ;bcdHours
mov cl,byte [bp+6] ;bcdMinutes
mov dh,byte [bp+4] ;bcdSeconds
mov dl,0
mov ah,3
int 1ah
mov bx,word [bp+10] ;bcdDays
mov dx,word [bx]
mov cx,word [bx+2]
mov ah,5
int 1ah
pop bp
ret 8

49
drivers/wrpcclk.asm Normal file
View File

@ -0,0 +1,49 @@
;
; File:
; wrpcclk.asm
; Description:
; WritePCClock - sysclock support
;
; Copyright (c) 1995
; Pasquale J. Villani
; All Rights Reserved
;
; This file is part of DOS-C.
;
; DOS-C is free software; you can redistribute it and/or
; modify it under the terms of the GNU General Public License
; as published by the Free Software Foundation; either version
; 2, or (at your option) any later version.
;
; DOS-C is distributed in the hope that it will be useful, but
; WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
; the GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public
; License along with DOS-C; see the file COPYING. If not,
; write to the Free Software Foundation, 675 Mass Ave,
; Cambridge, MA 02139, USA.
;
; $Header$
;
%include "../kernel/segs.inc"
segment HMA_TEXT
;
; VOID WritePCClock(Ticks)
; ULONG Ticks;
;
global WRITEPCCLOCK
WRITEPCCLOCK:
; Ticks = 4
pop ax ; return address
pop dx
pop cx ; Ticks
push ax ; restore stack
mov ah,1
int 1ah
ret

153
filelist Normal file
View File

@ -0,0 +1,153 @@
*/*/build.bat
*/*/buildall.bat
*/*/clean.bat
*/*/clobber.bat
*/*/config.b
*/*/filelist
*/*/default.bat
*/*/makefile
*/*/boot/boot.asm
*/*/boot/boot32.asm
*/*/boot/boot32lb.asm
*/*/boot/makefile
*/*/docs/bugs.txt
*/*/docs/build.txt
*/*/docs/config.txt
*/*/docs/contrib.txt
*/*/docs/copying
*/*/docs/fdkernel.lsm
*/*/docs/history.txt
*/*/docs/intfns.txt
*/*/docs/lfnapi.txt
*/*/docs/mkboot.txt
*/*/docs/nls.txt
*/*/docs/readme.cvs
*/*/docs/readme.txt
*/*/docs/sys.txt
*/*/drivers/floppy.asm
*/*/drivers/makefile
*/*/drivers/rdpcclk.asm
*/*/drivers/wratclk.asm
*/*/drivers/wrpcclk.asm
*/*/hdr/algnbyte.h
*/*/hdr/algndflt.h
*/*/hdr/buffer.h
*/*/hdr/cds.h
*/*/hdr/clock.h
*/*/hdr/date.h
*/*/hdr/dcb.h
*/*/hdr/device.h
*/*/hdr/dirmatch.h
*/*/hdr/error.h
*/*/hdr/exe.h
*/*/hdr/fat.h
*/*/hdr/fcb.h
*/*/hdr/file.h
*/*/hdr/fnode.h
*/*/hdr/kbd.h
*/*/hdr/kconfig.h
*/*/hdr/lol.h
*/*/hdr/mcb.h
*/*/hdr/network.h
*/*/hdr/nls.h
*/*/hdr/pcb.h
*/*/hdr/portab.h
*/*/hdr/process.h
*/*/hdr/sft.h
*/*/hdr/stacks.inc
*/*/hdr/tail.h
*/*/hdr/time.h
*/*/hdr/version.h
*/*/hdr/xstructs.h
*/*/kernel/nls/001-437.hc
*/*/kernel/nls/001-437.unf
*/*/kernel/nls/001-437.up
*/*/kernel/nls/049-850.hc
*/*/kernel/nls/049-850.unf
*/*/kernel/nls/049-850.up
*/*/kernel/nls/files
*/*/kernel/apisupt.asm
*/*/kernel/asmsupt.asm
*/*/kernel/blockio.c
*/*/kernel/break.c
*/*/kernel/chario.c
*/*/kernel/config.c
*/*/kernel/config.h
*/*/kernel/console.asm
*/*/kernel/dosfns.c
*/*/kernel/dosidle.asm
*/*/kernel/dosnames.c
*/*/kernel/dsk.c
*/*/kernel/dyndata.h
*/*/kernel/dyninit.c
*/*/kernel/entry.asm
*/*/kernel/error.c
*/*/kernel/execrh.asm
*/*/kernel/fatdir.c
*/*/kernel/fatfs.c
*/*/kernel/fattab.c
*/*/kernel/fcbfns.c
*/*/kernel/globals.h
*/*/kernel/init-dat.h
*/*/kernel/init-mod.h
*/*/kernel/initclk.c
*/*/kernel/initdisk.c
*/*/kernel/inithma.c
*/*/kernel/initoem.c
*/*/kernel/int2f.asm
*/*/kernel/inthndlr.c
*/*/kernel/intr.asm
*/*/kernel/makefile
*/*/kernel/io.asm
*/*/kernel/io.inc
*/*/kernel/ioctl.c
*/*/kernel/iprf.c
*/*/kernel/irqstack.asm
*/*/kernel/kernel.asm
*/*/kernel/kernel.cfg
*/*/kernel/lfnapi.c
*/*/kernel/ludivmul.inc
*/*/kernel/main.c
*/*/kernel/memdisk.asm
*/*/kernel/memmgr.c
*/*/kernel/misc.c
*/*/kernel/network.c
*/*/kernel/newstuff.c
*/*/kernel/nls.c
*/*/kernel/nls_hc.asm
*/*/kernel/nls_load.c
*/*/kernel/nlssupt.asm
*/*/kernel/prf.c
*/*/kernel/printer.asm
*/*/kernel/procsupt.asm
*/*/kernel/proto.h
*/*/kernel/segs.inc
*/*/kernel/serial.asm
*/*/kernel/strings.c
*/*/kernel/sysclk.c
*/*/kernel/syspack.c
*/*/kernel/systime.c
*/*/kernel/task.c
*/*/kernel/turboc.cfg
*/*/lib/makefile
*/*/mkfiles/generic.mak
*/*/mkfiles/bc5.mak
*/*/mkfiles/mscl8.mak
*/*/mkfiles/tc2.mak
*/*/mkfiles/tc3.mak
*/*/mkfiles/turbocpp.mak
*/*/mkfiles/watcom.mak
*/*/sys/fdkrncfg.c
*/*/sys/bin2c.c
*/*/sys/makefile
*/*/sys/sys.c
*/*/sys/talloc.c
*/*/utils/echoto.bat
*/*/utils/exeflat.c
*/*/utils/indent.ini
*/*/utils/makefile
*/*/utils/patchobj.c
*/*/utils/proto.bat
*/*/utils/relocinf.c
*/*/utils/rmfiles.bat
*/*/utils/wlinker.bat

13
hdr/algnbyte.h Normal file
View File

@ -0,0 +1,13 @@
#if defined(_MSC_VER)
#if _MSC_VER >= 700
#pragma warning(disable:4103)
#endif
#pragma pack(1)
#elif defined(_QC) || defined(__WATCOMC__) || defined(__GNUC__)
#pragma pack(1)
#elif defined(__ZTC__)
#pragma ZTC align 1
#elif defined(__TURBOC__) && (__TURBOC__ > 0x202)
#pragma option -a-
#endif

7
hdr/algndflt.h Normal file
View File

@ -0,0 +1,7 @@
#if defined (_MSC_VER) || defined(_QC) || defined(__WATCOMC__) || defined(__GNUC__)
#pragma pack()
#elif defined (__ZTC__)
#pragma ZTC align
#elif defined(__TURBOC__) && (__TURBOC__ > 0x202)
#pragma option -a.
#endif

64
hdr/buffer.h Normal file
View File

@ -0,0 +1,64 @@
/****************************************************************/
/* */
/* buffer.h */
/* */
/* Sector buffer structure */
/* */
/* Copyright (c) 2001 */
/* Bart Oldeman */
/* */
/* Largely taken from globals.h: */
/* Copyright (c) 1995, 1996 */
/* Pasquale J. Villani */
/* All Rights Reserved */
/* */
/* This file is part of DOS-C. */
/* */
/* DOS-C is free software; you can redistribute it and/or */
/* modify it under the terms of the GNU General Public License */
/* as published by the Free Software Foundation; either version */
/* 2, or (at your option) any later version. */
/* */
/* DOS-C is distributed in the hope that it will be useful, but */
/* WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See */
/* the GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public */
/* License along with DOS-C; see the file COPYING. If not, */
/* write to the Free Software Foundation, 675 Mass Ave, */
/* Cambridge, MA 02139, USA. */
/****************************************************************/
#ifdef MAIN
#ifdef VERSION_STRINGS
static BYTE *buffer_hRcsId =
"$Id: buffer.h 1702 2012-02-04 08:46:16Z perditionc $";
#endif
#endif
#include "dsk.h" /* only for MAX_SEC_SIZE */
#define BUFFERSIZE MAX_SEC_SIZE
struct buffer {
UWORD b_next; /* next buffer in LRU list */
UWORD b_prev; /* previous buffer in LRU list */
BYTE b_unit; /* disk for this buffer */
BYTE b_flag; /* buffer flags */
ULONG b_blkno; /* block for this buffer */
UBYTE b_copies; /* number of copies to write */
UWORD b_offset; /* offset in sectors between copies
to write for FAT sectors */
struct dpb FAR *b_dpbp; /* pointer to DPB */
UWORD b_remotesz; /* size of remote buffer if remote */
BYTE b_padding;
UBYTE b_buffer[BUFFERSIZE]; /* 512 byte sectors for now */
};
#define BFR_DIRTY 0x40 /* buffer modified */
#define BFR_VALID 0x20 /* buffer contains valid data */
#define BFR_DATA 0x08 /* buffer is from data area */
#define BFR_DIR 0x04 /* buffer is from dir area */
#define BFR_FAT 0x02 /* buffer is from fat area */
#define BFR_UNCACHE 0x01 /* buffer to be released ASAP */

91
hdr/cds.h Normal file
View File

@ -0,0 +1,91 @@
/****************************************************************/
/* */
/* cds.h */
/* */
/* Current Directory structures */
/* */
/* Copyright (c) 1995 */
/* Pasquale J. Villani */
/* All Rights Reserved */
/* */
/* This file is part of DOS-C. */
/* */
/* DOS-C is free software; you can redistribute it and/or */
/* modify it under the terms of the GNU General Public License */
/* as published by the Free Software Foundation; either version */
/* 2, or (at your option) any later version. */
/* */
/* DOS-C is distributed in the hope that it will be useful, but */
/* WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See */
/* the GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public */
/* License along with DOS-C; see the file COPYING. If not, */
/* write to the Free Software Foundation, 675 Mass Ave, */
/* Cambridge, MA 02139, USA. */
/****************************************************************/
#define MAX_CDSPATH 67
struct cds {
BYTE cdsCurrentPath[MAX_CDSPATH];
UWORD cdsFlags; /* see below */
struct dpb FAR *cdsDpb; /* if != 0, associated DPB */
union {
BYTE FAR *_cdsRedirRec; /* IFS record */
struct {
UWORD _cdsStrtClst; /* if local path (Flags & CDSPHYSDRV):
start cluster of CWD; root == 0,
never access == 0xFFFF */
UWORD _cdsParam;
} _cdsRedir;
} _cdsUnion;
UWORD cdsStoreUData;
#define cdsJoinOffset cdsBackslashOffset
WORD cdsBackslashOffset; /* Position of "root directory" backslash for
this drive within CurrentPath[]
prerequisites:
+ ofs <= strlen(currentPath)
+ if UNC: ofs > share component
if local path: ofs > colon
*/
BYTE cdsNetFlag1; /* According to PCDOS 7 Tech Ref: IFS drive, 2=IFS, 4=NetUse */
BYTE FAR *cdsIfs; /* Pointer to Installable File System Header */
UWORD cdsNetFlags2; /* File System specific data */
};
#define cdsStrtClst _cdsUnion._cdsRedir._cdsStrtClst
#define cdsRedirRec _cdsUnion._cdsRedirRec
#define cdsParam _cdsUnion._cdsRedir._cdsParam
/* Bits for cdsFlags (OR combination) */
#define CDSNETWDRV 0x8000
#define CDSPHYSDRV 0x4000
#define CDSJOINED 0x2000 /* not in combination with NETWDRV or SUBST */
#define CDSSUBST 0x1000 /* not in combination with NETWDRV or JOINED */
#define CDS_HIDDEN (1 << 7) /* hide drive from redirector's list */
/* NETWORK PHYSICAL meaning
0 0 drive not accessable
0 1 local file system
1 0 networked file system (UNC naming convention)
1 1 installable file system (IFS)
*/
#define CDSMODEMASK (CDSNETWDRV | CDSPHYSDRV)
/* #define CDSVALID (CDSNETWDRV | CDSPHYSDRV) */
#define CDSVALID CDSMODEMASK
#define IS_DEVICE 0x20
#define IS_NETWORK 0x40
#define CDS_MODE_SKIP_PHYSICAL 0x01 /* don't resolve SUBST, JOIN, NETW */
#define CDS_MODE_CHECK_DEV_PATH 0x02 /* check for existence of device path */
#define CDS_MODE_ALLOW_WILDCARDS 0x04 /* allow wildcards in "truename" */

47
hdr/clock.h Normal file
View File

@ -0,0 +1,47 @@
/****************************************************************/
/* */
/* clock.h */
/* */
/* Clock Driver data structures & declarations */
/* */
/* November 26, 1991 */
/* */
/* Adapted to DOS/NT June 12, 1993 */
/* */
/* Copyright (c) 1995 */
/* Pasquale J. Villani */
/* All Rights Reserved */
/* */
/* This file is part of DOS-C. */
/* */
/* DOS-C is free software; you can redistribute it and/or */
/* modify it under the terms of the GNU General Public License */
/* as published by the Free Software Foundation; either version */
/* 2, or (at your option) any later version. */
/* */
/* DOS-C is distributed in the hope that it will be useful, but */
/* WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See */
/* the GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public */
/* License along with DOS-C; see the file COPYING. If not, */
/* write to the Free Software Foundation, 675 Mass Ave, */
/* Cambridge, MA 02139, USA. */
/****************************************************************/
#ifdef MAIN
#ifdef VERSION_STRINGS
static BYTE *clock_hRcsId =
"$Id: clock.h 485 2002-12-09 00:17:15Z bartoldeman $";
#endif
#endif
struct ClockRecord {
UWORD clkDays; /* days since Jan 1, 1980. */
UBYTE clkMinutes; /* residual minutes. */
UBYTE clkHours; /* residual hours. */
UBYTE clkHundredths; /* residual hundredths of a second. */
UBYTE clkSeconds; /* residual seconds. */
};

57
hdr/date.h Normal file
View File

@ -0,0 +1,57 @@
/****************************************************************/
/* */
/* date.h */
/* */
/* DOS General Date Structure */
/* */
/* Copyright (c) 1995 */
/* Pasquale J. Villani */
/* All Rights Reserved */
/* */
/* This file is part of DOS-C. */
/* */
/* DOS-C is free software; you can redistribute it and/or */
/* modify it under the terms of the GNU General Public License */
/* as published by the Free Software Foundation; either version */
/* 2, or (at your option) any later version. */
/* */
/* DOS-C is distributed in the hope that it will be useful, but */
/* WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See */
/* the GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public */
/* License along with DOS-C; see the file COPYING. If not, */
/* write to the Free Software Foundation, 675 Mass Ave, */
/* Cambridge, MA 02139, USA. */
/****************************************************************/
/* TC 2.01 complains if `date' is defined twice. -- ror4 */
#ifndef DOSC_DATE_H
#define DOSC_DATE_H
#ifdef MAIN
#ifdef VERSION_STRINGS
static BYTE *date_hRcsId =
"$Id: date.h 485 2002-12-09 00:17:15Z bartoldeman $";
#endif
#endif
/* FAT file date - takes the form of yyyy yyym mmmd dddd where physical */
/* year=1980+yyyyyy */
#define DT_YEAR(d) (((d)>>9)&0x7f)
#define DT_MONTH(d) (((d)>>5)&0x0f)
#define DT_DAY(d) ((d)&0x1f)
#define DT_ENCODE(m,d,y) ((((m)&0x0f)<<5)|((d)&0x1f)|(((y)&0x7f)<<9))
#define EPOCH_WEEKDAY 2 /* Tuesday (i. e.- 0 == Sunday) */
#define EPOCH_MONTH 1 /* January */
#define EPOCH_DAY 1 /* 1 for January 1 */
#define EPOCH_YEAR 1980 /* for Tues 1-1-80 epoch */
typedef UWORD date;
#endif

92
hdr/dcb.h Normal file
View File

@ -0,0 +1,92 @@
/****************************************************************/
/* */
/* dcb.h */
/* */
/* DOS Device Control Block Structure */
/* */
/* November 20, 1991 */
/* */
/* Copyright (c) 1995 */
/* Pasquale J. Villani */
/* All Rights Reserved */
/* */
/* This file is part of DOS-C. */
/* */
/* DOS-C is free software; you can redistribute it and/or */
/* modify it under the terms of the GNU General Public License */
/* as published by the Free Software Foundation; either version */
/* 2, or (at your option) any later version. */
/* */
/* DOS-C is distributed in the hope that it will be useful, but */
/* WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See */
/* the GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public */
/* License along with DOS-C; see the file COPYING. If not, */
/* write to the Free Software Foundation, 675 Mass Ave, */
/* Cambridge, MA 02139, USA. */
/****************************************************************/
#ifdef MAIN
#ifdef VERSION_STRINGS
static BYTE *clock_hRcsId =
"$Id: dcb.h 485 2002-12-09 00:17:15Z bartoldeman $";
#endif
#endif
/* Internal drive parameter block */
struct dpb {
BYTE dpb_unit; /* unit for error reporting */
BYTE dpb_subunit; /* the sub-unit for driver */
UWORD dpb_secsize; /* sector size */
UBYTE dpb_clsmask; /* mask (sectors/cluster-1) */
UBYTE dpb_shftcnt; /* log base 2 of cluster size */
UWORD dpb_fatstrt; /* FAT start sector */
UBYTE dpb_fats; /* # of FAT copies */
UWORD dpb_dirents; /* # of dir entries */
UWORD dpb_data; /* start of data area */
UWORD dpb_size; /* # of clusters+1 on media */
UWORD dpb_fatsize; /* # of sectors / FAT */
UWORD dpb_dirstrt; /* start sec. of root dir */
struct dhdr FAR * /* pointer to device header */
dpb_device;
UBYTE dpb_mdb; /* media descr. byte */
BYTE dpb_flags; /* -1 = force MEDIA CHK */
struct dpb FAR * /* next dpb in chain */
dpb_next; /* -1 = end */
UWORD dpb_cluster; /* cluster # of first free */
/* -1 if not known */
#ifndef WITHFAT32
UWORD dpb_nfreeclst; /* number of free clusters */
/* -1 if not known */
#else
union {
struct {
UWORD dpb_nfreeclst_lo;
UWORD dpb_nfreeclst_hi;
} dpb_nfreeclst_st;
ULONG _dpb_xnfreeclst; /* number of free clusters */
/* -1 if not known */
} dpb_nfreeclst_un;
#define dpb_nfreeclst dpb_nfreeclst_un.dpb_nfreeclst_st.dpb_nfreeclst_lo
#define dpb_xnfreeclst dpb_nfreeclst_un._dpb_xnfreeclst
UWORD dpb_xflags; /* extended flags, see bpb */
UWORD dpb_xfsinfosec; /* FS info sector number, */
/* 0xFFFF if unknown */
UWORD dpb_xbackupsec; /* backup boot sector number */
/* 0xFFFF if unknown */
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 */
/* -1 if not known */
#endif
};
#define UNKNCLUSTER 0x0000 /* see RBIL INT 21/AH=52 entry */
#define XUNKNCLSTFREE 0xffffffffl /* unknown for DOS */
#define UNKNCLSTFREE 0xffff /* unknown for DOS */

145
hdr/debug.h Normal file
View File

@ -0,0 +1,145 @@
/****************************************************************/
/* */
/* debug.h */
/* */
/* Routines to assist in debugging the kernel */
/* */
/* January, 2005 */
/* */
/* Copyright (c) 2005 */
/* FreeDOS kernel dev. */
/* All Rights Reserved */
/* */
/* This file is part of DOS-C. */
/* */
/* DOS-C is free software; you can redistribute it and/or */
/* modify it under the terms of the GNU General Public License */
/* as published by the Free Software Foundation; either version */
/* 2, or (at your option) any later version. */
/* */
/* DOS-C is distributed in the hope that it will be useful, but */
/* WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See */
/* the GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public */
/* License along with DOS-C; see the file COPYING. If not, */
/* write to the Free Software Foundation, 675 Mass Ave, */
/* Cambridge, MA 02139, USA. */
/****************************************************************/
#ifndef __DEBUG_H
#define __DEBUG_H
/* #define DEBUG (usually via 'build debug') to
enable debug support.
NOTE: this file included by INIT time code and normal
resident code, so use care for all memory references
*/
/* allow output even in non-debug builds */
#if 0
#ifndef DEBUG_NEED_PRINTF
#define DEBUG_NEED_PRINTF
#endif
#endif
/* use to limit output to debug builds */
#ifdef DEBUG
#ifdef DEBUG_PRINT_COMPORT
#define DebugPrintf(x) dbgc_printf x
#else
#define DebugPrintf(x) printf x
#endif
#else
#define DebugPrintf(x)
#endif
/* use to disable a chunk of debug output, but
keep around for later use. */
#define DDebugPrintf(x)
/* enable or disable various chunks of debug output */
/* show stored IRQ vectors */
/* #define DEBUGIRQ */
/* show output related to moving kernel into HMA */
#ifdef DEBUG
#define HMAInitPrintf(x) DebugPrintf(x)
#else
#define HMAInitPrintf(x)
#endif
/* display output during kernel config processing phase */
/* #define DEBUGCFG */
#ifdef DEBUGCFG
#define CfgDbgPrintf(x) DebugPrintf(x)
#else
#define CfgDbgPrintf(x)
#endif
/* display info on various DOS functions (dosfns.c) */
/* #define DEBUGDOSFNS */
#ifdef DEBUGDOSFNS
#define DFnsDbgPrintf(x) DebugPrintf(x)
#else
#define DFnsDbgPrintf(x)
#endif
/* extra debug output related to chdir */
/* #define CHDIR_DEBUG */
/* extra debug output related to findfirst */
/* #define FIND_DEBUG */
/* display info on various DOS directory functions (fatdir.c) */
/* #define DEBUGFATDIR */
#ifdef DEBUGFATDIR
#define FDirDbgPrintf(x) DebugPrintf(x)
#else
#define FDirDbgPrintf(x)
#endif
/* extra debug output when transferring I/O chunks of data */
/* #define DISPLAY_GETBLOCK */
/* extra output during read/write operations */
/* #define DSK_DEBUG */
/* display info on various FAT handling functions (fatfs.c) */
/* #define DEBUGFATFS */
#ifdef DEBUGFATFS
#define FatFSDbgPrintf(x) DebugPrintf(x)
#else
#define FatFSDbgPrintf(x)
#endif
/* debug truename */
/* #define DEBUG_TRUENAME */
#ifdef DEBUG_TRUENAME
#define tn_printf(x) DebugPrintf(x)
#else
#define tn_printf(x)
#endif
/* ensure printf is prototyped */
#if defined(DEBUG) || defined(DEBUGIRQ) || defined(DEBUGCFG) || \
defined(DEBUGDOSFNS) || defined(CHDIR_DEBUG) || defined(FIND_DEBUG) || \
defined(DEBUGFATDIR) || defined(DEBUGFATFS) || \
defined(FORCEPRINTF)
#ifndef DEBUG_NEED_PRINTF
#define DEBUG_NEED_PRINTF
#endif
#endif
#ifdef DEBUG_NEED_PRINTF
int VA_CDECL printf(CONST char * fmt, ...);
#ifdef DEBUG_PRINT_COMPORT
int VA_CDECL dbgc_printf(CONST char * fmt, ...);
#endif
#endif
#endif /* __DEBUG_H */

506
hdr/device.h Normal file
View File

@ -0,0 +1,506 @@
/****************************************************************/
/* */
/* device.h */
/* Device Driver Header File */
/* */
/* November 20, 1991 */
/* */
/* Copyright (c) 1995 */
/* Pasquale J. Villani */
/* All Rights Reserved */
/* */
/* This file is part of DOS-C. */
/* */
/* DOS-C is free software; you can redistribute it and/or */
/* modify it under the terms of the GNU General Public License */
/* as published by the Free Software Foundation; either version */
/* 2, or (at your option) any later version. */
/* */
/* DOS-C is distributed in the hope that it will be useful, but */
/* WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See */
/* the GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public */
/* License along with DOS-C; see the file COPYING. If not, */
/* write to the Free Software Foundation, 675 Mass Ave, */
/* Cambridge, MA 02139, USA. */
/****************************************************************/
/*
* Status Word Bits
*/
#define S_ERROR 0x8000 /* Error bit */
#define S_BUSY 0x0200 /* Device busy bit */
#define S_DONE 0x0100 /* Device operation completed */
#define S_MASK 0x00ff /* Mask to extract error code */
/*
* MEDIA Descriptor Byte Bits
*/
#define MD_2SIDE 1 /* MEDIA is two sided */
#define MD_8SECTOR 2 /* MEDIA is eight sectored */
#define MD_REMOVABLE 4 /* MEDIA is removable (floppy) */
/*
* Media Return Codes
*/
#define M_CHANGED -1 /* MEDIA was changed */
#define M_DONT_KNOW 0 /* MEDIA state unkown */
#define M_NOT_CHANGED 1 /* MEDIA was not changed */
/*
* Error Return Codes
*/
#define E_WRPRT 0 /* Write Protect */
#define E_UNIT 1 /* Unknown Unit */
#define E_NOTRDY 2 /* Device Not Ready */
#define E_CMD 3 /* Unknown Command */
#define E_CRC 4 /* Crc Error */
#define E_LENGTH 5 /* Bad Length */
#define E_SEEK 6 /* Seek Error */
#define E_MEDIA 7 /* Unknown MEDIA */
#define E_NOTFND 8 /* Sector Not Found */
#define E_PAPER 9 /* No Paper */
#define E_WRITE 10 /* Write Fault */
#define E_READ 11 /* Read Fault */
#define E_FAILURE 12 /* General Failure */
/*
* Command codes
*/
#define C_INIT 0x00 /* Initialize */
#define C_MEDIACHK 0x01 /* MEDIA Check */
#define C_BLDBPB 0x02 /* Build BPB */
#define C_IOCTLIN 0x03 /* Ioctl In */
#define C_INPUT 0x04 /* Input (Read) */
#define C_NDREAD 0x05 /* Non-destructive Read */
#define C_ISTAT 0x06 /* Input Status */
#define C_IFLUSH 0x07 /* Input Flush */
#define C_OUTPUT 0x08 /* Output (Write) */
#define C_OUTVFY 0x09 /* Output with verify */
#define C_OSTAT 0x0a /* Output */
#define C_OFLUSH 0x0b /* Output Flush */
#define C_IOCTLOUT 0x0c /* Ioctl Out */
#define C_OPEN 0x0d /* Device Open */
#define C_CLOSE 0x0e /* Device Close */
#define C_REMMEDIA 0x0f /* Removable MEDIA */
#define C_OUB 0x10 /* Output till busy */
#define C_GENIOCTL 0x13 /* Generic Ioctl */
#define C_GETLDEV 0x17 /* Get Logical Device */
#define C_SETLDEV 0x18 /* Set Logical Device */
#define C_IOCTLQRY 0x19 /* Ioctl Query */
/*
* Convienence macros
*/
#define failure(x) (S_ERROR+S_DONE+x)
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
/*
* structures
*/
/* Device header */
struct dhdr {
struct dhdr
FAR *dh_next;
UWORD dh_attr;
VOID(*dh_strategy) (void);
VOID(*dh_interrupt) (void);
UBYTE dh_name[8];
};
#define ATTR_SUBST 0x8000
#define ATTR_CHAR 0x8000
#define ATTR_IOCTL 0x4000
#define ATTR_BLDFAT 0x2000
#define ATTR_REMOTE 0x1000
#define ATTR_EXCALLS 0x0800
#define ATTR_QRYIOCTL 0x0080
#define ATTR_GENIOCTL 0x0040
#define ATTR_RAW 0x0400
#define ATTR_FASTCON 0x0010
#define ATTR_CLOCK 0x0008
#define ATTR_NULL 0x0004
#define ATTR_CONOUT 0x0002
#define ATTR_HUGE 0x0002
#define ATTR_CONIN 0x0001
/* */
/* Bios Parameter Block structure */
/* */
#define FAT_NO_MIRRORING 0x80
#define BPB_SIZEOF 31 /* size of the standard BPB */
typedef struct {
UWORD bpb_nbyte; /* Bytes per Sector */
UBYTE bpb_nsector; /* Sectors per Allocation Unit */
UWORD bpb_nreserved; /* # Reserved Sectors */
UBYTE bpb_nfat; /* # FATs */
UWORD bpb_ndirent; /* # Root Directory entries */
UWORD bpb_nsize; /* Size in sectors */
UBYTE bpb_mdesc; /* MEDIA Descriptor Byte */
UWORD bpb_nfsect; /* FAT size in sectors */
UWORD bpb_nsecs; /* Sectors per track */
UWORD bpb_nheads; /* Number of heads */
ULONG bpb_hidden; /* Hidden sectors */
ULONG bpb_huge; /* Size in sectors if */
/* bpb_nsize == 0 */
#ifdef WITHFAT32
ULONG bpb_xnfsect; /* FAT size in sectors if */
/* bpb_nfsect == 0 */
UWORD bpb_xflags; /* extended flags */
/* bit 7: disable mirroring */
/* bits 6-4: reserved (0) */
/* bits 3-0: active FAT number */
UWORD bpb_xfsversion; /* filesystem version */
ULONG bpb_xrootclst; /* starting cluster of root dir */
UWORD bpb_xfsinfosec; /* FS info sector number, */
/* 0xFFFF if unknown */
UWORD bpb_xbackupsec; /* backup boot sector number */
/* 0xFFFF if unknown */
#endif
} bpb;
#define N_RETRY 5 /* number of retries permitted */
#include "dsk.h"
#define LBA_READ 0x4200
#define LBA_WRITE 0x4300
struct _bios_LBA_address_packet
/* Used to access a hard disk via LBA */
/* Added by Brian E. Reifsnyder */
{
unsigned char packet_size; /* size of this packet...set to 16 */
unsigned char reserved_1; /* set to 0...unused */
unsigned char number_of_blocks; /* 0 < number_of_blocks < 128 */
unsigned char reserved_2; /* set to 0...unused */
UBYTE far *buffer_address; /* addr of transfer buffer */
unsigned long block_address; /* LBA address */
unsigned long block_address_high; /* high bytes of LBA addr...unused */
};
struct CHS {
UWORD Cylinder;
UWORD Head;
UWORD Sector;
};
/* DOS 4.0-7.0 drive data table (see RBIL at INT2F,AX=0803) */
typedef struct ddtstruct {
struct ddtstruct FAR *ddt_next;
/* pointer to next table (offset FFFFh if last table) */
UBYTE ddt_driveno; /* physical unit number (for INT 13) */
UBYTE ddt_logdriveno; /* logical drive number (0=A:) */
bpb ddt_bpb; /* BIOS Parameter Block */
UBYTE ddt_flags;
/* bit 6: 16-bit FAT instead of 12-bit
bit 7: unsupportable disk (all accesses will return Not Ready) */
UWORD ddt_FileOC; /* Count of Open files on Drv */
UBYTE ddt_type; /* device type */
UWORD ddt_descflags; /* bit flags describing drive */
UWORD ddt_ncyl; /* number of cylinders
(for partition only, if hard disk) */
bpb ddt_defbpb; /* BPB for default (highest) capacity supported */
UBYTE ddt_reserved[6]; /* (part of BPB above) */
UBYTE ddt_ltrack; /* last track accessed */
union {
ULONG ddt_lasttime; /* removable media: time of last access
in clock ticks (FFFFFFFFh if never) */
struct {
UWORD ddt_part; /* partition (FFFFh = primary, 0001h = extended)
always 0001h for DOS 5+ */
UWORD ddt_abscyl; /* absolute cylinder number of partition's
start on physical drive
(FFFFh if primary partition in DOS 4.x) */
} ddt_hd;
} ddt_fh;
UBYTE ddt_volume[12]; /* ASCIIZ volume label or "NO NAME " if none
(apparently taken from extended boot record
rather than root directory) */
ULONG ddt_serialno; /* serial number */
UBYTE ddt_fstype[9]; /* ASCIIZ filesystem type ("FAT12 " or "FAT16 ") */
ULONG ddt_offset; /* relative partition offset */
} ddt;
/* description flag bits */
#define DF_FIXED 0x001 /* fixed media, ie hard drive */
#define DF_CHANGELINE 0x002 /* door lock or disk change detection reported as supported */
#define DF_CURBPBLOCK 0x004 /* current BPB locked, use existing BPB instead of building one */
#define DF_SAMESIZE 0x008 /* all sectors in a track are the same size */
#define DF_MULTLOG 0x010 /* physical drive represents multiple logical ones, eg A: & B: */
#define DF_CURLOG 0x020 /* active (current) logical drive for this physical drive */
#define DF_DISKCHANGE 0x040 /* disk change was detected */
#define DF_DPCHANGED 0x080 /* device parameters changed */
#define DF_REFORMAT 0x100 /* disk formatted so BPB has changed */
#define DF_NOACCESS 0x200 /* don't allow access (read or write) to fixed media */
/* freedos specific flag bits */
#define DF_LBA 0x400
#define DF_WRTVERIFY 0x800
/* typedef struct ddtstruct ddt;*/
struct gblkio {
UBYTE gbio_spcfunbit;
UBYTE gbio_devtype;
UWORD gbio_devattrib;
UWORD gbio_ncyl;
UBYTE gbio_media;
bpb gbio_bpb;
UWORD gbio_nsecs;
};
struct gblkfv /* for format / verify track */
{
UBYTE gbfv_spcfunbit;
UWORD gbfv_head;
UWORD gbfv_cyl;
UWORD gbfv_ntracks;
};
struct gblkrw /* for read / write track */
{
UBYTE gbrw_spcfunbit;
UWORD gbrw_head;
UWORD gbrw_cyl;
UWORD gbrw_sector;
UWORD gbrw_nsecs;
UBYTE FAR *gbrw_buffer;
};
struct Gioc_media {
WORD ioc_level;
ULONG ioc_serialno;
BYTE ioc_volume[11];
BYTE ioc_fstype[8];
};
struct Access_info {
BYTE AI_spec;
BYTE AI_Flag;
};
/* */
/* Boot Block (Super Block) */
/* */
/* See BPB comments for the offsets below */
/* */
#define BT_JUMP 0
#define BT_OEM 3
#define BT_BPB 11
#define BT_SIZEOF 36
typedef struct {
BYTE bt_jump[3]; /* Boot Jump opcodes */
BYTE bt_oem[8]; /* OEM Name */
bpb bt_bpb; /* BPB for this media/device */
WORD bt_nsecs; /* # Sectors per Track */
WORD bt_nheads; /* # Heads */
WORD bt_hidden; /* # Hidden sectors */
LONG bt_huge; /* use if nsecs == 0 */
BYTE bt_drvno;
BYTE bt_reserv;
BYTE bt_btid;
ULONG bt_serialno;
BYTE bt_volume[11];
BYTE bt_fstype[8];
} boot;
/* File system information structure */
struct fsinfo {
UDWORD fi_signature; /* must be 0x61417272 */
DWORD fi_nfreeclst; /* number of free clusters, -1 if unknown */
DWORD fi_cluster; /* most recently allocated cluster, -1 if unknown */
UBYTE fi_reserved[12];
};
typedef boot super; /* Alias for boot structure */
typedef struct {
UBYTE r_length; /* Request Header length */
UBYTE r_unit; /* Unit Code */
UBYTE r_command; /* Command Code */
UWORD r_status; /* Status */
BYTE r_reserved[8]; /* DOS Reserved Area */
union {
struct {
UBYTE _r_nunits; /* number of units */
BYTE FAR *_r_endaddr; /* Ending Address */
bpb *FAR * _r_bpbptr; /* ptr to BPB array */
UBYTE _r_firstunit;
} _r_init;
struct {
BYTE _r_meddesc; /* MEDIA Descriptor */
BYTE _r_retcode; /* Return Code */
BYTE FAR * _r_vid; /* volume id */
} _r_media;
struct {
BYTE _r_meddesc; /* MEDIA Descriptor */
boot FAR * _r_fat; /* boot sector pointer */
bpb FAR * _r_bpbpt; /* ptr to BPB table */
} _r_bpb;
struct {
BYTE _r_meddesc; /* MEDIA Descriptor */
BYTE FAR * _r_trans; /* Transfer Address */
UWORD _r_count; /* Byte/Sector Count */
UWORD _r_start; /* Starting Sector No. */
BYTE FAR * _r_vid; /* Pointer to volume id */
LONG _r_huge; /* for > 32Mb drives */
} _r_rw;
struct {
unsigned char _r_ndbyte; /* Byte Read From Device */
} _r_nd;
struct {
UBYTE _r_cat; /* Category code */
UBYTE _r_fun; /* Function code */
UWORD _r_si; /* Contents of SI and DI */
UWORD _r_di; /* (PC DOS 7 Technical Update, pp 104,105) */
union
{
struct gblkio FAR *_r_io;
struct gblkrw FAR *_r_rw;
struct gblkfv FAR *_r_fv;
struct Gioc_media FAR *_r_gioc;
struct Access_info FAR *_r_ai;
} _r_par; /* Pointer to param. block from 440C/440D */
} _r_gen;
} _r_x;
} request;
#define HUGECOUNT 0xffff
#define MAXSHORT 0xffffl
/*
* Macros to assist request structure legibility
*/
/* Init packet macros */
#define r_nunits _r_x._r_init._r_nunits
#define r_endaddr _r_x._r_init._r_endaddr
#define r_bpbptr _r_x._r_init._r_bpbptr
#define r_firstunit _r_x._r_init._r_firstunit
/* MEDIA Check packet macros */
#define r_mcmdesc _r_x._r_media._r_meddesc
#define r_mcretcode _r_x._r_media._r_retcode
#define r_mcvid _r_x._r_media._r_vid
/* Build BPB packet macros */
#define r_bpmdesc _r_x._r_bpb._r_meddesc
#define r_bpfat _r_x._r_bpb._r_fat
#define r_bpptr _r_x._r_bpb._r_bpbpt
/* rw packet macros */
#define r_meddesc _r_x._r_rw._r_meddesc
#define r_trans _r_x._r_rw._r_trans
#define r_count _r_x._r_rw._r_count
#define r_start _r_x._r_rw._r_start
#define r_rwvid _r_x._r_rw._r_vid
#define r_huge _r_x._r_rw._r_huge
/* ndread packet macros */
#define r_ndbyte _r_x._r_nd._r_ndbyte
/* generic IOCTL and IOCTL query macros */
#define r_cat _r_x._r_gen._r_cat
#define r_fun _r_x._r_gen._r_fun
#define r_si _r_x._r_gen._r_si
#define r_di _r_x._r_gen._r_di
#define r_rw _r_x._r_gen._r_par._r_rw
#define r_io _r_x._r_gen._r_par._r_io
#define r_fv _r_x._r_gen._r_par._r_fv
#define r_gioc _r_x._r_gen._r_par._r_gioc
#define r_ai _r_x._r_gen._r_par._r_ai
/*
*interrupt support (spl & splx) support - IBM style
*/
#define I_NONE 0 /* Initial value */
/* predefined interrupt levels - 8259 support */
#define IRQ0 0x01 /* Level 0 - highest */
#define IRQ1 0x02
#define IRQ2 0x04
#define IRQ3 0x08
#define IRQ4 0x10
#define IRQ5 0x20
#define IRQ6 0x40
#define IRQ7 0x80 /* Level 7 - lowest */
/* standard hardware configuration */
#define I_RTC IRQ0 /* Timer */
#define I_KBD IRQ1 /* Keyboard */
#define I_COM2 IRQ3 /* COM1: */
#define I_COM1 IRQ4 /* COM2: */
#define I_HDC IRQ5 /* Fixed disk */
#define I_FDC IRQ6 /* Diskette */
#define I_PRT IRQ7 /* Printer */
/* standard hardware vectors - 8259 defined */
#define V_RTC 0x08 /* Timer */
#define V_KBD 0x09 /* Keyboard */
#define V_LEV2 0x0a /* Level 2 - uncomitted */
#define V_COM2 0x0b /* COM1: */
#define V_COM1 0x0c /* COM2: */
#define V_HDC 0x0d /* Fixed disk */
#define V_FDC 0x0e /* Diskette */
#define V_PRT 0x0f /* Printer */
#define V_LEV0 0x08 /* Level 0 - highest */
#define V_LEV1 0x09
#define V_LEV2 0x0a /* Level 2 - uncomitted */
#define V_LEV3 0x0b
#define V_LEV4 0x0c
#define V_LEV5 0x0d
#define V_LEV6 0x0e
#define V_LEV7 0x0f /* Level 7 - lowest */
/*
*/
typedef request FAR *rqptr;
typedef bpb FAR *bpbptr;
typedef BYTE FAR *byteptr;
typedef struct dhdr FAR *dhdrptr;
extern request /* I/O Request packets */
ASM CharReqHdr, ASM IoReqHdr, ASM MediaReqHdr;
/* dsk.c */
COUNT ASMCFUNC FAR blk_driver(rqptr rp);
ddt * getddt(int dev);
/* error.c */
COUNT char_error(request * rq, struct dhdr FAR * lpDevice);
COUNT block_error(request * rq, COUNT nDrive, struct dhdr FAR * lpDevice, int mode);
/* sysclk.c */
WORD ASMCFUNC FAR clk_driver(rqptr rp);
/* execrh.asm */
#if defined(__WATCOMC__) && _M_IX86 >= 300
WORD execrh(request FAR *, struct dhdr FAR *);
#pragma aux execrh "^" parm reverse routine [] modify [ax bx cx dx es fs gs]
#else
WORD ASMPASCAL execrh(request FAR *, struct dhdr FAR *);
#endif
/*
* end of device.h
*/

54
hdr/dirmatch.h Normal file
View File

@ -0,0 +1,54 @@
/****************************************************************/
/* */
/* dirmatch.h */
/* */
/* FAT File System Match Data Structure */
/* */
/* January 4, 1992 */
/* */
/* Copyright (c) 1995 */
/* Pasquale J. Villani */
/* All Rights Reserved */
/* */
/* This file is part of DOS-C. */
/* */
/* DOS-C is free software; you can redistribute it and/or */
/* modify it under the terms of the GNU General Public License */
/* as published by the Free Software Foundation; either version */
/* 2, or (at your option) any later version. */
/* */
/* DOS-C is distributed in the hope that it will be useful, but */
/* WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See */
/* the GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public */
/* License along with DOS-C; see the file COPYING. If not, */
/* write to the Free Software Foundation, 675 Mass Ave, */
/* Cambridge, MA 02139, USA. */
/****************************************************************/
#ifdef MAIN
#ifdef VERSION_STRINGS
static BYTE *dirmatch_hRcsId =
"$Id: dirmatch.h 1415 2009-06-02 13:18:24Z bartoldeman $";
#endif
#endif
typedef struct {
UBYTE dm_drive;
BYTE dm_name_pat[FNAME_SIZE + FEXT_SIZE];
UBYTE dm_attr_srch;
UWORD dm_entry;
CLUSTER dm_dircluster;
#ifndef WITHFAT32
UWORD reserved;
#endif
UWORD reserved2;
UBYTE dm_attr_fnd; /* found file attribute */
time dm_time; /* file time */
date dm_date; /* file date */
ULONG dm_size; /* file size */
BYTE dm_name[FNAME_SIZE + FEXT_SIZE + 2]; /* file name */
} dmatch;

31
hdr/dsk.h Normal file
View File

@ -0,0 +1,31 @@
/****************************************************************/
/* */
/* dsk.h */
/* Disk access Header File */
/* */
/* Copyright (c) 2012 */
/* FreeDOS */
/* All Rights Reserved */
/* */
/* This file is part of DOS-C. */
/* */
/* DOS-C is free software; you can redistribute it and/or */
/* modify it under the terms of the GNU General Public License */
/* as published by the Free Software Foundation; either version */
/* 2, or (at your option) any later version. */
/* */
/* DOS-C is distributed in the hope that it will be useful, but */
/* WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See */
/* the GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public */
/* License along with DOS-C; see the file COPYING. If not, */
/* write to the Free Software Foundation, 675 Mass Ave, */
/* Cambridge, MA 02139, USA. */
/****************************************************************/
#ifndef MAX_SEC_SIZE
#define MAX_SEC_SIZE (1*512) /* max supported size of sector in bytes */
#endif

88
hdr/error.h Normal file
View File

@ -0,0 +1,88 @@
/****************************************************************/
/* */
/* error.h */
/* */
/* DOS-C error return codes */
/* */
/* December 1, 1991 */
/* */
/* Copyright (c) 1995 */
/* Pasquale J. Villani */
/* All Rights Reserved */
/* */
/* This file is part of DOS-C. */
/* */
/* DOS-C is free software; you can redistribute it and/or */
/* modify it under the terms of the GNU General Public License */
/* as published by the Free Software Foundation; either version */
/* 2, or (at your option) any later version. */
/* */
/* DOS-C is distributed in the hope that it will be useful, but */
/* WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See */
/* the GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public */
/* License along with DOS-C; see the file COPYING. If not, */
/* write to the Free Software Foundation, 675 Mass Ave, */
/* Cambridge, MA 02139, USA. */
/****************************************************************/
#ifdef MAIN
#ifdef VERSION_STRINGS
static BYTE *error_hRcsId =
"$Id: error.h 485 2002-12-09 00:17:15Z bartoldeman $";
#endif
#endif
/* Internal system error returns */
#define SUCCESS 0 /* Function was successful */
#define DE_INVLDFUNC -1 /* Invalid function number */
#define DE_FILENOTFND -2 /* File not found */
#define DE_PATHNOTFND -3 /* Path not found */
#define DE_TOOMANY -4 /* Too many open files */
#define DE_ACCESS -5 /* Access denied */
#define DE_INVLDHNDL -6 /* Invalid handle */
#define DE_MCBDESTRY -7 /* Memory control blocks shot */
#define DE_NOMEM -8 /* Insufficient memory */
#define DE_INVLDMCB -9 /* Invalid memory control block */
#define DE_INVLDENV -10 /* Invalid enviornement */
#define DE_INVLDFMT -11 /* Invalid format */
#define DE_INVLDACC -12 /* Invalid access */
#define DE_INVLDDATA -13 /* Invalid data */
#define DE_INVLDDRV -15 /* Invalid drive */
#define DE_RMVCUDIR -16 /* Attempt remove current dir */
#define DE_DEVICE -17 /* Not same device */
#define DE_NFILES -18 /* No more files */
#define DE_WRTPRTCT -19 /* No more files */
#define DE_BLKINVLD -20 /* invalid block */
#define DE_INVLDBUF -24 /* invalid buffer size, ext fnc */
#define DE_SEEK -25 /* error on file seek */
#define DE_HNDLDSKFULL -28 /* handle disk full (?) */
#define DE_INVLDPARM -0x57 /* invalid parameter */
#define DE_DEADLOCK -36
#define DE_LOCK -39
#define DE_FILEEXISTS -80 /* File exists */
/* Critical error flags */
#define EFLG_READ 0x00 /* Read error */
#define EFLG_WRITE 0x01 /* Write error */
#define EFLG_RSVRD 0x00 /* Error in rserved area */
#define EFLG_FAT 0x02 /* Error in FAT area */
#define EFLG_DIR 0x04 /* Error in dir area */
#define EFLG_DATA 0x06 /* Error in data area */
#define EFLG_ABORT 0x08 /* Handler can abort */
#define EFLG_RETRY 0x10 /* Handler can retry */
#define EFLG_IGNORE 0x20 /* Handler can ignore */
#define EFLG_CHAR 0x80 /* Error in char or FAT image */
/* error results returned after asking user */
/* MS-DOS compatible -- returned by CriticalError */
#define CONTINUE 0
#define RETRY 1
#define ABORT 2
#define FAIL 3

57
hdr/exe.h Normal file
View File

@ -0,0 +1,57 @@
/****************************************************************/
/* */
/* exe.h */
/* */
/* DOS EXE Header Data Structure */
/* */
/* December 1, 1991 */
/* */
/* Copyright (c) 1995 */
/* Pasquale J. Villani */
/* All Rights Reserved */
/* */
/* This file is part of DOS-C. */
/* */
/* DOS-C is free software; you can redistribute it and/or */
/* modify it under the terms of the GNU General Public License */
/* as published by the Free Software Foundation; either version */
/* 2, or (at your option) any later version. */
/* */
/* DOS-C is distributed in the hope that it will be useful, but */
/* WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See */
/* the GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public */
/* License along with DOS-C; see the file COPYING. If not, */
/* write to the Free Software Foundation, 675 Mass Ave, */
/* Cambridge, MA 02139, USA. */
/****************************************************************/
#ifdef MAIN
#ifdef VERSION_STRINGS
static BYTE *exe_hRcsId =
"$Id: exe.h 485 2002-12-09 00:17:15Z bartoldeman $";
#endif
#endif
typedef struct {
UWORD exSignature;
UWORD exExtraBytes;
UWORD exPages;
UWORD exRelocItems;
UWORD exHeaderSize;
UWORD exMinAlloc;
UWORD exMaxAlloc;
UWORD exInitSS;
UWORD exInitSP;
UWORD exCheckSum;
UWORD exInitIP;
UWORD exInitCS;
UWORD exRelocTable;
UWORD exOverlay;
} exe_header;
#define MAGIC 0x5a4d
#define OLD_MAGIC 0x4d5a

152
hdr/fat.h Normal file
View File

@ -0,0 +1,152 @@
/****************************************************************/
/* */
/* fat.h */
/* */
/* FAT File System data structures & declarations */
/* */
/* November 26, 1991 */
/* */
/* Copyright (c) 1995 */
/* Pasquale J. Villani */
/* All Rights Reserved */
/* */
/* This file is part of DOS-C. */
/* */
/* DOS-C is free software; you can redistribute it and/or */
/* modify it under the terms of the GNU General Public License */
/* as published by the Free Software Foundation; either version */
/* 2, or (at your option) any later version. */
/* */
/* DOS-C is distributed in the hope that it will be useful, but */
/* WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See */
/* the GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public */
/* License along with DOS-C; see the file COPYING. If not, */
/* write to the Free Software Foundation, 675 Mass Ave, */
/* Cambridge, MA 02139, USA. */
/****************************************************************/
#ifdef MAIN
#ifdef VERSION_STRINGS
static BYTE *fat_hRcsId =
"$Id: fat.h 1448 2009-06-16 21:45:17Z bartoldeman $";
#endif
#endif
/* FAT file system attribute bits */
#define D_NORMAL 0 /* normal */
#define D_RDONLY 0x01 /* read-only file */
#define D_HIDDEN 0x02 /* hidden */
#define D_SYSTEM 0x04 /* system */
#define D_VOLID 0x08 /* volume id */
#define D_DIR 0x10 /* subdir */
#define D_ARCHIVE 0x20 /* archive bit */
/* /// Added D_DEVICE bit. - Ron Cemer */
#define D_DEVICE 0x40 /* device bit */
#define D_LFN (D_RDONLY | D_HIDDEN | D_SYSTEM | D_VOLID)
#define D_ALL (D_RDONLY | D_HIDDEN | D_SYSTEM | D_DIR | D_ARCHIVE)
/* FAT file name constants */
#define FNAME_SIZE 8
#define FEXT_SIZE 3
/* FAT deleted flag */
#define DELETED '\x5' /* if first char, delete file */
#define EXT_DELETED '\xe5' /* external deleted flag */
/* Test for 16 bit or 12 bit FAT */
#define SIZEOF_CLST16 2
#define SIZEOF_CLST32 4
/* FAT cluster special flags */
#define FREE 0x000
#ifdef WITHFAT32
#define LONG_LAST_CLUSTER 0x0FFFFFFFUL
#define LONG_BAD 0x0FFFFFF7UL
#else
#define LONG_LAST_CLUSTER 0xFFFF
#define LONG_BAD 0xFFF7
#endif
#define MASK16 0xFFF8
#define BAD16 0xFFF7
#define MASK12 0xFF8
#define BAD12 0xFF7
/* magic constants: even though FF7 is BAD so FF6 could be a valid cluster
no., MS docs specify that FF5 is the maximal possible cluster number
for FAT12; similar for 16 and 32 */
#define FAT_MAGIC 4085
#define FAT_MAGIC16 65525U
#define FAT_MAGIC32 268435455UL
/* int ISFAT32(struct dpb FAR *dpbp);*/
#define ISFAT32(x) _ISFAT32(x)
/*
#define _ISFAT32(dpbp) (((dpbp)->dpb_size)>FAT_MAGIC16 && ((dpbp)->dpb_size)<=FAT_MAGIC32 )
*/
#define _ISFAT32(dpbp) (((dpbp)->dpb_fatsize)==0)
#define ISFAT16(dpbp) (((dpbp)->dpb_size)>FAT_MAGIC && ((dpbp)->dpb_size)<=FAT_MAGIC16 )
#define ISFAT12(dpbp) ((((dpbp)->dpb_size)-1)<FAT_MAGIC)
/* dpb_size == 0 for FAT32, hence doing -1 here */
/* FAT file system directory entry */
struct dirent {
char dir_name[FNAME_SIZE + FEXT_SIZE]; /* Filename + extension in FCB format */
UBYTE dir_attrib; /* File Attribute */
UBYTE dir_case; /* File case */
UBYTE dir_crtimems; /* Milliseconds */
UWORD dir_crtime; /* Creation time */
UWORD dir_crdate; /* Creation date */
UWORD dir_accdate; /* Last access date */
UWORD dir_start_high; /* High word of the cluster */
time dir_time; /* Time file created/updated */
date dir_date; /* Date file created/updated */
UWORD dir_start; /* Starting cluster */
/* 1st available = 2 */
ULONG dir_size; /* File size in bytes */
};
struct lfn_entry {
UBYTE lfn_id; /* Sequence number for this LFN entry */
UNICODE lfn_name0_4[5]; /* First 5 characters of LFN */
UBYTE lfn_attrib; /* LFN attribute, should be D_LFN == 0x0f */
UBYTE lfn_reserved1;
UBYTE lfn_checksum; /* Checksum for the corresponding 8.3 name */
UNICODE lfn_name5_10[6]; /* Next 6 characters of LFN */
UWORD lfn_reserved2;
UNICODE lfn_name11_12[2]; /* Last 2 characters of LFN */
};
/* */
/* filesystem sizeof(dirent) - may be different from core */
/* */
#ifdef WITHFAT32
struct dpb;
CLUSTER getdstart(struct dpb FAR *dpbp, struct dirent *dentry);
void setdstart(struct dpb FAR *dpbp, struct dirent *dentry, CLUSTER value);
#else
#define getdstart(dpbp, dentry) \
((dentry)->dir_start)
#define setdstart(dpbp, dentry, value) \
(((dentry)->dir_start) = (UWORD)(value))
#endif
#define DIR_NAME 0
#define DIR_EXT FNAME_SIZE
#define DIR_ATTRIB (FNAME_SIZE+FEXT_SIZE)
#define DIR_RESERVED (FNAME_SIZE+FEXT_SIZE+1)
#define DIR_START_HIGH (FNAME_SIZE+FEXT_SIZE+9)
#define DIR_TIME (FNAME_SIZE+FEXT_SIZE+11)
#define DIR_DATE (FNAME_SIZE+FEXT_SIZE+13)
#define DIR_START (FNAME_SIZE+FEXT_SIZE+15)
#define DIR_SIZE (FNAME_SIZE+FEXT_SIZE+17)
#define DIRENT_SIZE 32

120
hdr/fcb.h Normal file
View File

@ -0,0 +1,120 @@
/****************************************************************/
/* */
/* fcb.h */
/* */
/* FAT FCB and extended FCB data structures & declarations */
/* */
/* November 23, 1991 */
/* */
/* Copyright (c) 1995 */
/* Pasquale J. Villani */
/* All Rights Reserved */
/* */
/* This file is part of DOS-C. */
/* */
/* DOS-C is free software; you can redistribute it and/or */
/* modify it under the terms of the GNU General Public License */
/* as published by the Free Software Foundation; either version */
/* 2, or (at your option) any later version. */
/* */
/* DOS-C is distributed in the hope that it will be useful, but */
/* WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See */
/* the GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public */
/* License along with DOS-C; see the file COPYING. If not, */
/* write to the Free Software Foundation, 675 Mass Ave, */
/* Cambridge, MA 02139, USA. */
/****************************************************************/
#ifdef MAIN
#ifdef VERSION_STRINGS
static BYTE *fcb_hRcsId =
"$Id: fcb.h 485 2002-12-09 00:17:15Z bartoldeman $";
#endif
#endif
/* fcb convience defines */
/* block device info */
#define FID_CHARDEV 0x80 /* 1 defines character device */
/* 0 defines block file */
#define FID_NOWRITE 0x40 /* 0 file dirty (write occured) */
/* 1 file has no changes */
#define FID_MASK 0x3f /* file # */
/* char device info */
#define FID_EOF 0x40 /* 1 = no eof detected */
/* 0 = end of file on input */
#define FID_BINARY 0x20 /* 1 = binary (raw) mode device */
/* 0 = ascii (cooked) mode device */
#define FID_CLOCK 0x08 /* Clock device */
#define FID_NULL 0x04 /* Null device */
#define FID_CONOUT 0x02 /* Console output device */
#define FID_CONIN 0x01 /* Console input device */
#ifndef FNAME_SIZE
#define FNAME_SIZE 8 /* limit on file name */
#endif
#ifndef FEXT_SIZE
#define FEXT_SIZE 3 /* limit on extension */
#endif
#ifndef FDFLT_DRIVE
#define FDFLT_DRIVE 0 /* default drive */
#endif
#define PARSE_SEP_STOP 0x01
#define PARSE_DFLT_DRIVE 0x02
#define PARSE_BLNK_FNAME 0x04
#define PARSE_BLNK_FEXT 0x08
#define PARSE_RET_NOWILD 0
#define PARSE_RET_WILD 1
#define PARSE_RET_BADDRIVE 0xff
#define FCB_READ 0
#define FCB_WRITE 1
/* File Control Block (FCB) */
typedef struct {
UBYTE fcb_drive; /* Drive number 0=default, 1=A, etc */
BYTE fcb_fname[FNAME_SIZE]; /* File name */
BYTE fcb_fext[FEXT_SIZE]; /* File name Extension */
UWORD fcb_cublock; /* Current block number of */
/* 128 records/block, for seq. r/w */
UWORD fcb_recsiz; /* Logical record size in bytes, */
/* default = 128 */
ULONG fcb_fsize; /* File size in bytes */
date fcb_date; /* Date file created */
time fcb_time; /* Time of last write */
/* the following are reserved by system */
BYTE fcb_sftno; /* Device ID */
BYTE fcb_attrib_hi; /* share info, dev attrib word hi */
BYTE fcb_attrib_lo; /* dev attrib word lo, open mode */
UWORD fcb_strtclst; /* file starting cluster */
UWORD fcb_dirclst; /* cluster of the dir entry */
UBYTE fcb_diroff_unused; /* offset of the dir entry */
/* end reserved */
UBYTE fcb_curec; /* Current block number of */
ULONG fcb_rndm; /* Current relative record number */
} fcb;
/* FAT extended fcb */
typedef struct {
UBYTE xfcb_flag; /* 0xff indicates Extended FCB */
BYTE xfcb_resvrd[5]; /* Reserved */
UBYTE xfcb_attrib; /* Attribute */
fcb xfcb_fcb;
} xfcb;
typedef struct {
UBYTE renDriveID; /* drive no. */
BYTE renOldName[8]; /* Old Filename */
BYTE renOldExtent[3]; /* Old File Extension */
BYTE renReserved1[5];
BYTE renNewName[8]; /* New Filename */
BYTE renNewExtent[3]; /* New FileExtension */
BYTE renReserved2[9];
} rfcb;

81
hdr/file.h Normal file
View File

@ -0,0 +1,81 @@
/****************************************************************/
/* */
/* file.h */
/* */
/* DOS File mode flags */
/* */
/* December 1, 1991 */
/* */
/* Copyright (c) 1995 */
/* Pasquale J. Villani */
/* All Rights Reserved */
/* */
/* This file is part of DOS-C. */
/* */
/* DOS-C is free software; you can redistribute it and/or */
/* modify it under the terms of the GNU General Public License */
/* as published by the Free Software Foundation; either version */
/* 2, or (at your option) any later version. */
/* */
/* DOS-C is distributed in the hope that it will be useful, but */
/* WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See */
/* the GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public */
/* License along with DOS-C; see the file COPYING. If not, */
/* write to the Free Software Foundation, 675 Mass Ave, */
/* Cambridge, MA 02139, USA. */
/****************************************************************/
#ifdef MAIN
#ifdef VERSION_STRINGS
static BYTE *file_hRcsId =
"$Id: file.h 831 2004-03-27 00:27:11Z bartoldeman $";
#endif
#endif
/* 0 = CON, standard input, can be redirected */
/* 1 = CON, standard output, can be redirected */
/* 2 = CON, standard error */
/* 3 = AUX, auxiliary */
/* 4 = PRN, list device */
/* 5 = 1st user file ... */
#define STDIN 0
#define STDOUT 1
#define STDERR 2
#define STDAUX 3
#define STDPRN 4
/* mode bits */
#define O_VALIDMASK 0xfff3 /* valid open mask */
#define O_RDONLY 0x0000
#define O_WRONLY 0x0001
#define O_RDWR 0x0002
#define O_ACCMODE 0x0003
/* bits 2, 3 reserved */
/* bits 4, 5, 6 sharing modes */
#define O_SHAREMASK 0x0070 /* mask to isolate shared bits */
#define O_DENYALL 0x0010 /* sharing bits */
#define O_DENYWRITE 0x0020 /* " " */
#define O_DENYREAD 0x0030 /* " " */
#define O_DENYNONE 0x0040 /* " " */
#define O_NETFCB 0x0070 /* networked fcb */
#define O_NOINHERIT 0x0080
#define O_OPEN 0x0100 /* not */
#define O_TRUNC 0x0200 /* both */
#define O_CREAT 0x0400
#define O_LEGACY 0x0800
#define O_LARGEFILE 0x1000
#define O_NOCRIT 0x2000
#define O_SYNC 0x4000
#define O_FCB 0x8000
/* status for extended open */
enum {S_OPENED = 1, S_CREATED = 2, S_REPLACED = 3};

65
hdr/fnode.h Normal file
View File

@ -0,0 +1,65 @@
/****************************************************************/
/* */
/* fnode.h */
/* */
/* Internal File Node for FAT File System */
/* */
/* January 4, 1992 */
/* */
/* Copyright (c) 1995 */
/* Pasquale J. Villani */
/* All Rights Reserved */
/* */
/* This file is part of DOS-C. */
/* */
/* DOS-C is free software; you can redistribute it and/or */
/* modify it under the terms of the GNU General Public License */
/* as published by the Free Software Foundation; either version */
/* 2, or (at your option) any later version. */
/* */
/* DOS-C is distributed in the hope that it will be useful, but */
/* WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See */
/* the GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public */
/* License along with DOS-C; see the file COPYING. If not, */
/* write to the Free Software Foundation, 675 Mass Ave, */
/* Cambridge, MA 02139, USA. */
/****************************************************************/
#ifdef MAIN
#ifdef VERSION_STRINGS
static BYTE *fnode_hRcsId =
"$Id: fnode.h 1432 2009-06-10 16:10:54Z bartoldeman $";
#endif
#endif
struct f_node {
UWORD f_flags; /* file flags */
dmatch *f_dmp; /* this file's dir match */
struct dirent f_dir; /* this file's dir entry image */
ULONG f_dirsector; /* the sector containing dir entry*/
UBYTE f_diridx; /* offset/32 of dir entry in sec*/
/* when dir is not root */
struct dpb FAR *f_dpb; /* the block device for file */
ULONG f_offset; /* byte offset for next op */
CLUSTER f_cluster_offset; /* relative cluster number within file */
CLUSTER f_cluster; /* the cluster we are at */
UBYTE f_sft_idx; /* corresponding SFT index */
};
typedef struct f_node *f_node_ptr;
struct lfn_inode {
UNICODE l_name[261]; /* Long file name string */
/* If the string is empty, */
/* then file has the 8.3 name */
struct dirent l_dir; /* Directory entry image */
UWORD l_diroff; /* Current directory entry offset */
};
typedef struct lfn_inode FAR * lfn_inode_ptr;

48
hdr/kbd.h Normal file
View File

@ -0,0 +1,48 @@
/****************************************************************/
/* */
/* kbd.h */
/* */
/* Buffered Keyboard Input data structures & declarations */
/* */
/* July 5, 1993 */
/* */
/* Copyright (c) 1995 */
/* Pasquale J. Villani */
/* All Rights Reserved */
/* */
/* This file is part of DOS-C. */
/* */
/* DOS-C is free software; you can redistribute it and/or */
/* modify it under the terms of the GNU General Public License */
/* as published by the Free Software Foundation; either version */
/* 2, or (at your option) any later version. */
/* */
/* DOS-C is distributed in the hope that it will be useful, but */
/* WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See */
/* the GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public */
/* License along with DOS-C; see the file COPYING. If not, */
/* write to the Free Software Foundation, 675 Mass Ave, */
/* Cambridge, MA 02139, USA. */
/****************************************************************/
#ifdef MAIN
#ifdef VERSION_STRINGS
static BYTE *kbd_hRcsId =
"$Id: kbd.h 485 2002-12-09 00:17:15Z bartoldeman $";
#endif
#endif
#define LINEBUFSIZECON 128
#define KBD_MAXLENGTH LINEBUFSIZECON+1 /* the above + LF */
#define LINEBUFSIZE0A 256 /* maximum length for int21/ah=0a */
/* Keyboard buffer */
typedef struct {
UBYTE kb_size; /* size of buffer in bytes */
UBYTE kb_count; /* number of bytes returned */
BYTE kb_buf[KBD_MAXLENGTH]; /* the buffer itself */
} keyboard;

36
hdr/kconfig.h Normal file
View File

@ -0,0 +1,36 @@
/*
KConfig.h
DLASortByDriveNo
0 : Drive Letter Assignement ike MSDOS
1 : DLA - first drive completely first, then to next drive
InitDiskShowDriveAssignment
0 : don't show what drive/partition assigned to what drive letter
1 : show info
SkipConfigSeconds:
< 0 : not possible to skip config.sys
= 0 : only possible if already pressed before, no message
> 0 : wait so long for F5/F8
BootHarddiskSeconds: boots by default - and without user interaction - from HD
<= 0: normal
> 0:
display message
' hit any key to continue to boot from 'diskette or CD'
wait ## seconds
if no key hit, boot from HD
*/
typedef struct _KernelConfig {
char CONFIG[6]; /* "CONFIG" */
unsigned short ConfigSize;
unsigned char DLASortByDriveNo;
unsigned char InitDiskShowDriveAssignment;
signed char SkipConfigSeconds;
unsigned char ForceLBA;
unsigned char GlobalEnableLBAsupport; /* = 0 --> disable LBA support */
signed char BootHarddiskSeconds;
} KernelConfig;

91
hdr/lol.h Normal file
View File

@ -0,0 +1,91 @@
/****************************************************************/
/* */
/* lol.h */
/* */
/* DOS List of Lists structure */
/* */
/* Copyright (c) 2003 */
/* Bart Oldeman */
/* All Rights Reserved */
/* */
/* This file is part of DOS-C. */
/* */
/* DOS-C is free software; you can redistribute it and/or */
/* modify it under the terms of the GNU General Public License */
/* as published by the Free Software Foundation; either version */
/* 2, or (at your option) any later version. */
/* */
/* DOS-C is distributed in the hope that it will be useful, but */
/* WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See */
/* the GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public */
/* License along with DOS-C; if not, write to the Free Software */
/* Foundation, Inc., 59 Temple Place, Suite 330, */
/* Boston, MA 02111-1307 USA. */
/****************************************************************/
enum {LOC_CONV=0, LOC_HMA=1};
/* note: we start at DOSDS:0, but the "official" list of lists starts a
little later at DOSDS:26 (this is what is returned by int21/ah=52) */
struct lol {
char filler[0x22];
char *inputptr; /* -4 Pointer to unread CON input */
unsigned short first_mcb; /* -2 Start of user memory */
struct dpb far *DPBp; /* 0 First drive Parameter Block */
struct sfttbl far *sfthead; /* 4 System File Table head */
struct dhdr far *clock; /* 8 CLOCK$ device */
struct dhdr far *syscon; /* c console device */
unsigned short maxsecsize; /* 10 max bytes per sector for any blkdev */
void far *inforecptr; /* 12 pointer to disk buffer info record */
struct cds far *CDSp; /* 16 Current Directory Structure */
struct sfttbl far *FCBp; /* 1a FCB table pointer */
unsigned short nprotfcb; /* 1e number of protected fcbs */
unsigned char nblkdev; /* 20 number of block devices */
unsigned char lastdrive; /* 21 value of last drive */
struct dhdr nul_dev; /* 22 NUL device driver header(no pointer!)*/
unsigned char njoined; /* 34 number of joined devices */
unsigned short specialptr; /* 35 pointer to list of spec. prog(unused)*/
void far *setverPtr; /* 37 pointer to SETVER list */
void (*a20ptr)(void); /* 3b pointer to fix A20 ctrl */
unsigned short recentpsp; /* 3d PSP of most recently exec'ed prog */
unsigned short nbuffers; /* 3f Number of buffers */
unsigned short nlookahead; /* 41 Number of lookahead buffers */
unsigned char BootDrive; /* 43 bootdrive (1=A:) */
unsigned char cpu; /* 44 CPU family [was unused dword moves] */
unsigned short xmssize; /* 45 extended memory size in KB */
struct buffer far *firstbuf; /* 47 head of buffers linked list */
unsigned short dirtybuf; /* 4b number of dirty buffers */
struct buffer far *lookahead;/* 4d pointer to lookahead buffer */
unsigned short slookahead; /* 51 number of lookahead sectors */
unsigned char bufloc; /* 53 BUFFERS loc (1=HMA) */
char far *deblock_buf; /* 54 pointer to workspace buffer */
char filler2[5]; /* 58 ???/unused */
unsigned char int24fail; /* 5d int24 fail while making i/o stat call*/
unsigned char memstrat; /* 5e memory allocation strat during exec */
unsigned char a20count; /* 5f nr. of int21 calls for which a20 off */
unsigned char VgaSet; /* 60 bitflags switches=/w, int21/4b05 */
unsigned short unpack; /* 61 offset of unpack code start */
unsigned char uppermem_link; /* 63 UMB Link flag */
unsigned short min_pars; /* 64 minimum para req by program execed */
unsigned short uppermem_root;/* 66 Start of umb chain (usually 9fff) */
unsigned short last_para; /* 68 para: start scanning during memalloc */
/* ANY ITEM BELOW THIS POINT MAY CHANGE */
/* FreeDOS specific entries */
unsigned char os_setver_minor;/*6a settable minor DOS version */
unsigned char os_setver_major;/*6b settable major DOS version */
unsigned char os_minor; /* 6c minor DOS version */
unsigned char os_major; /* 6d major DOS version */
unsigned char rev_number; /* 6e DOS revision#, only 3 bits */
unsigned char version_flags; /* 6f DOS version flags */
char *os_release; /* 70 near pointer to os_release string */
#ifdef WIN31SUPPORT
unsigned short winInstanced; /* WinInit called */
unsigned long winStartupInfo[4];
unsigned short instanceTable[5];
#endif
};

69
hdr/mcb.h Normal file
View File

@ -0,0 +1,69 @@
/****************************************************************/
/* */
/* mcb.h */
/* */
/* Memory Control Block data structures and declarations */
/* */
/* November 23, 1991 */
/* */
/* Copyright (c) 1995 */
/* Pasquale J. Villani */
/* All Rights Reserved */
/* */
/* This file is part of DOS-C. */
/* */
/* DOS-C is free software; you can redistribute it and/or */
/* modify it under the terms of the GNU General Public License */
/* as published by the Free Software Foundation; either version */
/* 2, or (at your option) any later version. */
/* */
/* DOS-C is distributed in the hope that it will be useful, but */
/* WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See */
/* the GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public */
/* License along with DOS-C; see the file COPYING. If not, */
/* write to the Free Software Foundation, 675 Mass Ave, */
/* Cambridge, MA 02139, USA. */
/****************************************************************/
#ifdef MAIN
#ifdef VERSION_STRINGS
static BYTE *mcb_hRcsId =
"$Id: mcb.h 822 2004-03-25 00:20:20Z bartoldeman $";
#endif
#endif
#define LARGEST -1
#define FIRST_FIT 0
#define BEST_FIT 1
#define LAST_FIT 2
#define FIRST_FIT_UO 0x40
#define BEST_FIT_UO 0x41
#define LAST_FIT_UO 0x42
#define FIRST_FIT_U 0x80
#define BEST_FIT_U 0x81
#define LAST_FIT_U 0x82
#define FIT_U_MASK 0xc0
#define FIT_MASK 0x3f
#define MCB_NORMAL 0x4d
#define MCB_LAST 0x5a
#define DOS_PSP 0x0060 /* 0x0008 What? seg 8 =0:0080 */
#define FREE_PSP 0
#define MCB_SIZE(x) ((((LONG)(x))<<4)+sizeof(mcb))
typedef UWORD seg;
typedef UWORD offset;
typedef struct {
BYTE m_type; /* mcb type - chain or end */
UWORD m_psp; /* owner id via psp segment */
UWORD m_size; /* size of segment in paragraphs */
BYTE m_fill[3];
BYTE m_name[8]; /* owner name limited to 8 bytes */
} mcb;

80
hdr/network.h Normal file
View File

@ -0,0 +1,80 @@
/****************************************************************/
/* */
/* network.h */
/* */
/* DOS Networking */
/* */
/* October 10, 1999 */
/* */
/* Copyright (c) 1999 */
/* James Tabor */
/* All Rights Reserved */
/* */
/* This file is part of DOS-C. */
/* */
/* DOS-C is free software; you can redistribute it and/or */
/* modify it under the terms of the GNU General Public License */
/* as published by the Free Software Foundation; either version */
/* 2, or (at your option) any later version. */
/* */
/* DOS-C is distributed in the hope that it will be useful, but */
/* WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See */
/* the GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public */
/* License along with DOS-C; see the file COPYING. If not, */
/* write to the Free Software Foundation, 675 Mass Ave, */
/* Cambridge, MA 02139, USA. */
/****************************************************************/
/* Defines for remote access functions */
#define REM_RMDIR 0x1101
#define REM_MKDIR 0x1103
#define REM_CHDIR 0x1105
#define REM_CLOSE 0x1106
#define REM_FLUSH 0x1107
#define REM_READ 0x1108
#define REM_WRITE 0x1109
#define REM_LOCK 0x110a
#define REM_UNLOCK 0x110b
#define REM_GETSPACE 0x110c
#define REM_SETATTR 0x110e
#define REM_GETATTRZ 0x110f
#define REM_RENAME 0x1111
#define REM_DELETE 0x1113
#define REM_OPEN 0x1116
#define REM_CREATE 0x1117
#define REM_CRTRWOCDS 0x1118
#define REM_FND1WOCDS 0x1119
#define REM_FINDFIRST 0x111B
#define REM_FINDNEXT 0x111C
#define REM_CLOSEALL 0x111d
#define REM_DOREDIRECT 0x111e
#define REM_PRINTSET 0x111f
#define REM_FLUSHALL 0x1120
#define REM_LSEEK 0x1121
#define REM_PROCESS_END 0x1122
#define REM_FILENAME 0x1123
#define REM_PRINTREDIR 0x1125
#define REM_EXTOC 0x112e
struct rgds {
UWORD r_spc;
UWORD r_navc;
UWORD r_bps;
UWORD r_nc;
};
struct remote_fileattrib {
UWORD rfa_file; /* File Attributes */
union {
ULONG rfa_filesize; /* file size */
struct {
UWORD rfa_filesize_lo; /* DI Low */
UWORD rfa_filesize_hi; /* BX High */
} _split_rfa_fz;
} rfa_fz_union;
UWORD rfa_time;
UWORD rfa_date;
};

628
hdr/nls.h Normal file
View File

@ -0,0 +1,628 @@
/****************************************************************/
/* */
/* NLS.H */
/* FreeDOS */
/* */
/* National Language Support data structures */
/* */
/* Copyright (c) 2000 */
/* Steffen Kaiser */
/* All Rights Reserved */
/* */
/* This file is part of FreeDOS. */
/* */
/* DOS-C is free software; you can redistribute it and/or */
/* modify it under the terms of the GNU General Public License */
/* as published by the Free Software Foundation; either version */
/* 2, or (at your option) any later version. */
/* */
/* DOS-C is distributed in the hope that it will be useful, but */
/* WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See */
/* the GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public */
/* License along with DOS-C; see the file COPYING. If not, */
/* write to the Free Software Foundation, 675 Mass Ave, */
/* Cambridge, MA 02139, USA. */
/****************************************************************/
/* one byte alignment */
#include <algnbyte.h>
/*
* Description of the organization of NLS information -- 2000/02/13 ska
*
* Glossar:
* NLS package -- NLS information incl. any code required to access or
* correctly interprete this particular information
*
* Abbreviation:
* (NLS) pkg -- NLS package
*
* The code included into the kernel does "only" support NLS packages
* structurally compatible with the one of the U.S.A. / CP437.
* I guess that most NLS packages has been tweaked to be compatible,
* so that this is not a real limitation, but for all other packages
* the external NLSFUNC can supply every piece of code necessary.
* To allow this the interface between the kernel and NLSFUNC has been
* extended; at the same time the interface has been reduced, because some
* of the API functions do not seem to offer any functionality required
* for now. This, however, may be a misinterpretation because of
* lack of understanding.
*
* The supported structure consists of the following assumptions:
* 1) The pkg must contain the tables 2 (Upcase character), 4
* (Upcase filename character) and 5 (filename termination
* characters); because they are used internally.
* 2) The tables 2 and 4 must contain exactly 128 (0x80) characters.
* The character at index 0 corresponses to character 128 (0x80).
* The characters in the range of 0..0x7f are constructed out of
* the 7-bit US-ASCII (+ control characters) character set and are
* upcased not through the table, but by the expression:
* (ch >= 'a' && ch <= 'z')? ch - 'a' + 'A': ch
* with: 'a' == 97; 'z' == 122; 'A' == 65
* 3) The data to be returned by DOS-65 is enlisted in the
* nlsPointer[] array of the nlsPackage structure, including
* the DOS-65-01 data, which always must be last entry of the
* array.
* 4) DOS-38 returns the 34 bytes beginning with the byte at offset
* 4 behind the size field of DOS-65-01.
*
* It seems that pure DOS can internally maintain two NLS pkgs:
* NLS#1: The hardcoded pkg of U.S.A. on CP437, and
* NLS#2: the pkg loaded via COUNTRY= from within CONFIG.SYS.
* I do interprete this behaviour as follows:
* CONFIG.SYS is read in more passes; before COUTRY= can be evaluated,
* many actions must be performed, e.g. to load kernel at all, open
* CONFIG.SYS and begin reading. The kernel requires at least two
* NLS information _before_ COUNTRY= has been evaluated - both upcase
* tables. To not implement the same function multiple times, e.g.
* to upcase with and without table, the kernel uses the default
* NLS pkg until a more appropriate one can be loaded and hopes that
* the BIOS (and the user) can live with its outcome.
* Though, theoretically, the hardcoded NLS pkg could be purged
* or overwritten once the COUNTRY= statement has been evaluated.
* It would be possible that this NLS pkg internally performs different
* purposes, for now this behaviour will be kept.
*
* The current implementation extends the above "two maintained
* NLS pkgs" into that the kernel chains all NLS pkgs loaded in
* memory into one single linked list. When the user does neither
* wants to load other NLS pkgs without executing NLSFUNC and the
* loaded NLS pkgs do not contain code themselves, no other code is
* required, but some memory to store the NLS pkgs into.
*
* Furthermore, because the kernel needs to include the code for the
* hardcoded NLS pkg anyway, every NLS pkg can use it; so only
* NLS pkgs that structurally differ from U.S.A./CP437 actually need
* to add any code and residently install the MUX handler for NLSFUNC.
* This technique reduces the overhead calling the MUX handler, when
* it is not needed.
* However, NLSFUNC is always required if the user wants to return
* information about NLS pkgs _not_ loaded into memory.
*
*=== Attention: Because the nlsInfoBlock structure differs from the
*=== the "traditional" (aka MS) implementation, the MUX-14 interface
*=== is _not_ MS-compatible, although all the registers etc.
*=== do conform. -- 2000/02/26 ska
*
* Previous failed attempts to implement NLS handling and a full-
* featured MUX-14 supporting any-structured NLS pkgs suggest
* to keep the implement as simple as possible and keep the
* optimization direction off balance and to tend toward either
* an optimization for speed or size.
*
* The most problem is that the MUX interrupt chain is considered
* highly overcrowded, so if the kernels invokes it itself, the
* performance might decrease dramatically; on the other side, the
* more complex the interface between kernel and a _probably_ installed
* external NLSFUNC becomes the more difficult all the stuff is becoming
* and, most importantly, the size grows unnecessarily, because many
* people don't use NLSFUNC at all.
*
* The kernel uses the NLS pkg itself for two operations:
* 1) DOS-65-2x and DOS-65-Ax: Upcase character, string, memory area, &
* 2) whenever a filename is passed into the kernel, its components
* must be identified, invalid characters must be detected
* and, finally, all letters must be uppercased.
* I do not consider operation 1) an action critical for performance,
* because traditional DOS programming praxis says: Do it Yourself; so
* one can consider oneself lucky that a program aquires the upcase
* table once in its life time (I mean: lucky the program calls NLS at all).
* Operation 2), in opposite, might dramatically reduce performance, if
* it lacks proper implementations.
*
* Straight forward implementation:
* The basic implementation of the NLS channels all requests of DOS-65,
* DOS-66, and DOS-38 through MUX-14. Hereby, any external program, such
* as NLSFUNC, may (or may not) install a piece of code to filter
* one, few, or all requests in order to perform them itself, by default
* all requests will end within the root of the MUX interrupt, which is
* located within the kernel itself. An access path could look like this:
* 1. Call to DOS-65-XX, DOS-66-XX, or DOS-38.
* 2. The kernel is enterred through the usual INT-21 API handler.
* 3. The request is decoded and one of the NLS.C function is called.
* 4. This function packs a new request and calls MUX-14.
* 5. Every TSR/driver hooking INT-2F will check, if the request is
* directed for itself;
* 5.1. If not, the request is passed on to the next item of the MUX
* interrupt chain;
* 5.2. If so, the TSR, e.g. NLSFUNC, tests if the request is to be
* performed internally;
* 5.2.1. If so, the request is performed and the MUX-14 call is
* terminated (goto step 8.)
* 5.2.2. If not, the request is passed on (see step 5.1.)
* 6. If all TSRs had their chance to filter requests, but none decided
* to perform the request itself, the kernel is (re-)enterred
* through its INT-2F (MUX) API handler.
* 7. Here the request is decoded again and performed with the kernel-
* internal code; then the MUX-14 call is terminated.
* 8. When the MUX-14 call returns, it has setup all return parameters
* already, so the INT-21 call is terminated as well.
*
* Note: The traditional MUX-14 is NOT supported to offer functionality
* to the kernel at the first place, but to let the kernel access and
* return any values they must be loaded into memory, but the user may
* request information through the DOS-65 interface of NLS pkgs _not_
* already loaded. Theoretically, NLSFUNC needs not allocate any internal
* buffer to load the data into, because the user already supplied one;
* also if the kernel would instruct NLSFUNC to load the requested
* NLS pkg, more memory than necessary would be allocated. However, all
* except subfunction 1 return a _pointer_ to the data rather than the
* data itself; that means that NLSFUNC must cache the requested data
* somewhere, but how long?
*
* Performance tweaks:
* When the system -- This word applies to the combination of kernel and
* any loaded MUX-14 extension á la NLSFUNC here. -- uppercases
* _filenames_, it must perform a DOS-65-A2 internally. In the basic
* implementation this request would be channeled through MUX-14, even
* if there is no external NLSFUNC at all. Also, when a NLS pkg had
* been loaded by the kernel itself, it complies to above mentioned
* rules and it is very unlikely that it is necessary to probe if
* a MUX-14 TSR might want to perform the request itself. Therefore
* each NLS pkg contains some flags that allow the kernel to bypass
* the MUX-14 request and invoke the proper function directly. Both
* default NLS pkgs will have those flags enabled, because they are
* already loaded into memory and must comply to the rules.
*
* Note: Those flags do not alter the way the request is actually
* performed, but the MUX-14 call is omitted only (steps 4. through 6.).
*
* ======= Description of the API
*
* There are three APIs to be supported by NLS:
* 1) DOS API: DOS-38, DOS-65, DOS-66;
* 2) MUX-14, and
* 3) internal: upcasing filenames.
*
* 1) and 2) address the used NLS pkg by the country code / codepage pair.
* 3) uses the currently active NLS pkg only; furthermore, these functions
* more or less match DOS-64-A*. Therefore, the NLS system merges the
* interfaces 1) and 3) and offers function suitable for both ones.
*
* Both 1) and 3) must channel the request through the MUX chain, if
* appropriate, whereas 2) is the back-end and does natively process the
* request totally on its own.
*
* The API of 1) and 3) consists of:
* + DosUpChar(), DosUpString(), and DosUpMem(): to upcase an object
* (DOS-65-2[0-2]);
* + DosYesNo(): to check a character, if it is the yes or no prompt
* (DOS-65-23);
* + DosUpFChar(), DosUpFString(), and DosUpFMem(): to upcase an object
* for filenames (DOS-65-A[0-2]);
* + DosGetData(): to retreive certain information (DOS-38, all the
* other DOS-65-** subfunctions);
* + DosSetCountry(): to change the currently active country code
* (DOS-38);
* + DosSetCodepage(): to change the currently active codepage (DOS-66).
*
* The API of 2) consists of:
* + syscall_MUX14().
* This function is invoked for all MUX-14 requests and recieves the
* registers of the particular INT-2F call, it will then decode the
* registers and pass the request forth to a NLS-internal interface
* consisting of the following "static" functions:
* + nlsUpMem(): called for DosUp*(),
* + nlsUpFMem(): called for DosUpF*(),
* + nlsYesNo(): called for DosYesNo(),
* + nlsGetData(): called for DosGetData(),&
* + nlsSetPackage(): called for DosSetCountry() and DosSetCodepage().
* In opposite of the APIs 1) through 3) the NLS-internal functions address
* the NLS pkg to operate upon by a (struct nlsInfoBlock *) pointer.
*
* This designs supports to easily implement to bypass the MUX chain to
* speed up especially the internal API to upcase filenames, because
* the Dos*() functions can decide do not pass the request through MUX,
* but directly call the nls*() function instead. This way it is ensured
* that the performed actions are the same in both cases and, with repect
* to the functions that operate with the currently active NLS pkg, the
* performance is rather high, because one can use the globally available
* pointer to the current NLS pkg and need not search for a country code/
* codepage pair.
*
* ======== Compile-time options
*
* Win9x supports to change the individual portions of a NLS pkg
* through DOS-65-00; also there are no references what happens when
* a program changes the areas addressed by returned pointers. The
* current implementation does _not_ support changes of the NLS pkg
* except by invoking DOS-38 (Set Country Code) or DOS-66 (Set Codepage).
* Future implementations might offer this ability; to reduce the
* overhead introduced by this feature, the macro NLS_MODIFYABLE_DATA
* enables the appropriate code.
* NLS_MODIFYABLE_DATA is *disabled* by default.
*
* The tables 2 and 4 (upcase tables) are accessed relatively often,
* but theoretically these tables could be located at any position
* of the pointer array. If the macro NLS_REORDER_POINTERS is enabled,
* both NLSFUNC and the internal loader will reorder the pointers
* array so that mandatory tables are located at predictable indexes.
* This removes that the kernel must search for the table when
* one of the DOS-65-[2A]x functions is called or a filename has been
* passed in (which must be uppercased to be suitable for internal
* purpose). However, when some program try to tweak the internal
* tables this assumption could be wrong.
* This setting has any effect only, if the kernel tries to access
* information itself; it is ignored when the user calls DOS-65-0x
* to return such pointer.
* NLS_REORDER_POINTERS is *enabled* by default.
* UPDATE: With NLS_REORDER_POINTERS, now table 7 (DBCS) is also
* expected to be located at a predictable index. -- eca
*/
/* Define if some user program possibly modifies the value of the internal
tables or the DOS-65-00 (Set Country Information) API function
is to be supported. */
/* Currently unimplemented! -- 2000/02/13 ska*/
/* #define NLS_MODIFYABLE_DATA */
/* Define if the pointer array shall be reordered to allow a quick
access to often used and mandatoryly present tables. */
#define NLS_REORDER_POINTERS
/*
* How the kernel and NLSFUNC communicate with each other
*/
/* Must be pased to and returned by NLSFUNC upon MUX-14-00 */
#define NLS_FREEDOS_NLSFUNC_ID 0x534b
/* What version of nlsInfo and accompanying associations
Must be passed to NLSFUNC upon MUX-14-00 to identify the
correct kernel to the tools. */
#define NLS_FREEDOS_NLSFUNC_VERSION 0xFD02
/* Represents a call to DOS-38 within DOS-65 handlers.
Current implementation relys on 0x101! */
#define NLS_DOS_38 0x101
/* NLSFUNC may return NLS_REDO to instruct the kernel to
try to perform the same action another time. This is most
useful if the kernel only loads the NLS pkg into memory so
the kernel will find it and will process the request internally
now. */
#define NLS_REDO 353
/* Codes of the subfunctions of external NLSFUNC */
#define NLSFUNC_INSTALL_CHECK 0
#define NLSFUNC_DOS38 4
#define NLSFUNC_GETDATA 2
#define NLSFUNC_DRDOS_GETDATA 0xfe
#define NLSFUNC_LOAD_PKG 3
#define NLSFUNC_LOAD_PKG2 1
#define NLSFUNC_UPMEM 0x22
#define NLSFUNC_YESNO 0x23
#define NLSFUNC_FILE_UPMEM 0xa2
/* The NLS implementation flags encode what feature is in effect;
a "1" in the bitfield means that the feature is active.
All currently non-defined bits are to be zero to allow future
useage. */
#define NLS_CODE_MODIFYABLE_DATA 0x0001
#define NLS_CODE_REORDER_POINTERS 0x0002
/* NLS package useage flags encode what feature is in effect for this
particular package:
a "1" in the bitfield means that the feature is active/enabled.
All currently non-defined bits are to be zero to allow future
useage. */
#define NLS_FLAG_DIRECT_UPCASE 0x0001 /* DOS-65-2[012], */
#define NLS_FLAG_DIRECT_FUPCASE 0x0002 /* DOS-65-A[012], internal */
#define NLS_FLAG_DIRECT_YESNO 0x0004 /* DOS-65-23 */
#define NLS_FLAG_DIRECT_GETDATA 0x0008 /* DOS-65-XX, DOS-38 */
#define NLS_FLAG_HARDCODED (NLS_FLAG_DIRECT_UPCASE \
| NLS_FLAG_DIRECT_FUPCASE \
| NLS_FLAG_DIRECT_YESNO \
| NLS_FLAG_DIRECT_GETDATA)
/* No codepage / country code given */
#define NLS_DEFAULT ((UWORD)-1)
struct CountrySpecificInfo {
short CountryID; /* = W1 W437 # Country ID & Codepage */
short CodePage;
short DateFormat; /* Date format: 0/1/2: U.S.A./Europe/Japan */
char CurrencyString[5]; /* '$' ,'EUR' */
char ThousandSeparator[2]; /* ',' # Thousand's separator */
char DecimalPoint[2]; /* '.' # Decimal point */
char DateSeparator[2]; /* '-' */
char TimeSeparator[2]; /* ':' */
char CurrencyFormat; /* = 0 # Currency format (bit array)
0Fh BYTE currency format
bit 2 = set if currency symbol replaces decimal point
bit 1 = number of spaces between value and currency symbol
bit 0 = 0 if currency symbol precedes value
1 if currency symbol follows value
*/
char CurrencyPrecision; /* = 2 # Currency precision */
char TimeFormat; /* = 0 # time format: 0/1: 12/24 houres */
};
/*
* This is the data in the exact order returned by DOS-65-01
*/
struct nlsExtCntryInfo {
UBYTE subfct; /* always 1 */
WORD size; /* size of this structure
without this WORD itself */
WORD countryCode; /* current country code */
WORD codePage; /* current code page (CP) */
/*
* This is the data in the exact order as to return on
* DOS-38; it is also the most (important) part of DOS-65-01
*/
/* Note: The ASCIZ strings might become
a totally different understanding with
DBCS (Double Byte Character Support) */
WORD dateFmt; /* order of portions of date
0: mm/dd/yyyy (USA)
1: dd/mm/yyyy (Europe)
2: yyyy/mm/dd (Japan)
*/
char curr[5]; /* ASCIZ of currency string */
char thSep[2]; /* ASCIZ of thousand's separator */
char point[2]; /* ASCIZ of decimal point */
char dateSep[2]; /* ASCIZ of date separator */
char timeSep[2]; /* ASCIZ of time separator */
BYTE currFmt; /* format of currency:
bit 0: currency string is placed
0: before number
1: behind number
bit 1: currency string and number are
separated by a space
0: No
1: Yes
bit 2: currency string replaces decimal
sign
0: No
1: Yes
*/
BYTE prescision; /* of monetary numbers */
BYTE timeFmt; /* time format:
0: 12 hours (append AM/PM)
1: 24 houres
*/
VOID(FAR * upCaseFct) (VOID); /* far call to a function upcasing the
character in register AL */
char dataSep[2]; /* ASCIZ of separator in data records */
};
struct nlsPointer { /* Information of DOS-65-0X is addressed
by a pointer */
UBYTE subfct; /* number of the subfunction */
VOID FAR *pointer; /* the pointer to be returned when the subfunction
of DOS-65 is called (Note: won't work for
subfunctions 0, 1, 0x20, 0x21, 0x22, 0x23,
0xA0, 0xA1,& 0xA2 */
};
struct nlsPackage { /* the contents of one chain item of the
list of NLS packages */
struct nlsPackage FAR *nxt; /* next item in chain */
UWORD cntry, cp; /* country ID / codepage of this NLS pkg */
int flags; /* direct access and other flags */
/* Note: Depending on the flags above all remaining
portions may be omitted, if the external NLSFUNC-like
MUX-14 processor does not require them and performs
all actions itself, so that the kernel never tries to
fetch this information itself. */
UWORD yeschar; /* yes / no character DOS-65-23 */
UWORD nochar;
unsigned numSubfct; /* number of supported sub-functions */
struct nlsPointer nlsPointers[1]; /* grows dynamically */
};
struct nlsDBCS { /* The internal structure is unknown to me */
UWORD numEntries;
UWORD dbcsTbl[1];
};
struct nlsCharTbl {
/* table containing a list of characters */
UWORD numEntries; /* number of entries of this table.
If <= 0x80, the first element of
the table corresponse to character 0x80 */
unsigned char tbl[1]; /* grows dynamically */
};
#define nlsChBuf(len) struct nlsCharTbl##len { \
UWORD numEntries; \
unsigned char tbl[len]; \
}
nlsChBuf(128);
nlsChBuf(256);
/* in file names permittable characters for DOS-65-05 */
struct nlsFnamTerm {
WORD size; /* size of this structure */
BYTE dummy1;
char firstCh, lastCh; /* first, last permittable character */
BYTE dummy2;
char firstExcl, lastExcl; /* first, last excluded character */
BYTE dummy3;
BYTE numSep; /* number of file name separators */
char separators[1]; /* grows dynamically */
};
struct nlsInfoBlock { /* This block contains all information
shared by the kernel and the external NLSFUNC program */
char FAR *fname; /* filename from COUNTRY=;
maybe tweaked by NLSFUNC */
UWORD sysCodePage; /* system code page */
unsigned flags; /* implementation flags */
struct nlsPackage FAR *actPkg; /* current NLS package */
struct nlsPackage FAR *chain; /* first item of info chain --
hardcoded U.S.A./CP437 */
};
extern struct nlsInfoBlock ASM nlsInfo;
extern struct nlsPackage FAR ASM nlsPackageHardcoded;
/* These are the "must have" tables within the hard coded NLS pkg */
extern struct nlsFnamTerm FAR ASM nlsFnameTermHardcoded;
extern struct nlsDBCS FAR ASM nlsDBCSHardcoded;
extern struct nlsCharTbl FAR ASM nlsUpcaseHardcoded;
extern struct nlsCharTbl FAR ASM nlsFUpcaseHardcoded;
extern struct nlsCharTbl FAR ASM nlsCollHardcoded;
extern struct nlsExtCntryInfo FAR ASM nlsCntryInfoHardcoded;
extern BYTE FAR hcTablesStart[], hcTablesEnd[];
/***********************************************************************
***** Definitions & Declarations for COUNTRY.SYS **********************
***********************************************************************/
/* Note: These definitions are shared among all tools accessing the
COUNTRY.SYS file as well -- 2000/06/11 ska*/
/* File structure:
S0: Base (Primary) structure -- file header
Offset Size Meaning
0 array ID string "FreeDOS COUNTRY.SYS v1.0\r\n"
26 array Copyright etc. (plain 7bit ASCII text)
26+N 2byte \x1a\0
26+N+2 array padded with \0 upto next offset
128 word number of country/codepage pairs (N1)
130 8byte country code / codepage entries (S1)
130+8*N1 end of array
===
S1: structure of country/codepage pair
Offset Size Meaning
0 dword relative position of table definition (S2)
4 word codepage ID
6 word country code
8 end of structure
===
S2: table definition of one country/codepage pair
Offset Size Meaning
0 word number of function entries (N2)
2 8byte function definition (S3)
2+8*N2 end of array
===
S3: function definition
Offset Size Meaning
0 dword relative position of function data (see S4)
4 word number of bytes of data
6 byte function ID (same as passed to DOS-65-XX)
7 byte reserved for future use (currently 0 (zero))
8 end of structure
===
S4: function data
In opposite of the structures and arrays, the function data
is just a structure-less stream of bytes, which is used as it is.
Currently no validation check is performed over this data.
That means, for instance, that a definition of function 2 (upcase
table) has length 130 and the data consists of a word value with
the length (128) and 128 bytes individual information.
That way the DBCS is implemented exactly the same way as all the
other tables; the only exception is pseudo-table 0x23.
===
"relative position" means this DWord specifies the amount of bytes
between end of the current structure and the data the pointer is
referring to. This shall enable future implementations to embed
COUNTRY.SYS into other files.
*/
#define CSYS_FD_IDSTRING "FreeDOS COUNTRY.SYS v1.0\r\n\x1a"
#if 0
struct csys_function { /* S3: function definition */
UDWORD csys_rpos; /* relative position to actual data */
UWORD csys_length;
UBYTE csys_fctID; /* As passed to DOS-65-XX */
UBYTE csys_reserved1; /* always 0, reserved for future use */
};
struct csys_ccDefinition { /* S1: country/codepage reference */
UDWORD csys_rpos; /* moving the 4byte value to the front
can increase performance */
UWORD csys_cp;
UWORD csys_cntry;
};
#endif
struct csys_ccDefinition { /* country/codepage reference */
UDWORD csys_pos; /* moving the 4byte value to the front
can increase performance */
UWORD csys_cntry;
UWORD csys_cp;
UWORD csys_size1; /* size of nlsPackage struct rpos is pointing to */
/* initially the object rpos is pointing to conforms to a
struct nlsPackage, where:
struct nlsPackage FAR *nxt; is missing
UWORD cntry, cp; is missing
int flags; is NLS_FLAG_HARDCODED, if the
kernel is to handle the data of its own
UWORD yeschar; is filled
UWORD nochar; is filled
unsigned numSubfct; is filled
struct nlsPointer nlsPointers[1]; is filled
the pointer member is the absolute
position of the data within the file
of this structure:
UWORD count
count bytes
The "count" value is not a part
of the data itself.
Also: The data must be ordered corresponding to
NLS_CODE_REORDER_POINTERS.
Also: The last nlsPointer is subfct #1 _incl_ all its
data [is the extended country information: struct nlsExtCntryInfo]
*/
};
struct csys_numEntries { /* helper structure for "number of entries" */
UWORD csys_entries;
};
/* Header of the COUNTRY.SYS file */
struct nlsCSys_fileHeader { /* COUNTRY.SYS header */
unsigned char csys_idstring[sizeof(CSYS_FD_IDSTRING)];
UWORD csys_maxTotalSize; /* maximal size of the total amount of
any individual definition, that includes
the nlsPackage skeleton and the sum of
all bytes required to load all the
subfunctions individually.
--> The code is to allocate maxTotalSize
and load any country definition of this
file into this buffer without any
overflow. */
DWORD csys_posIndex; /* absolute position of index table */
};
/* Structure created by CountryInfoLoad() */
struct nlsCSys_loadPackage {
UWORD csys_size;
struct nlsPackage csys_pkg;
};
/* standard alignment */
#include <algndflt.h>
#ifdef DEBUG
/* Enable debugging of NLS part */
/* Caution: Enabling NLS debugging usually generates
_a_lot_ of noise. */
/*& #define NLS_DEBUG */
#endif

172
hdr/pcb.h Normal file
View File

@ -0,0 +1,172 @@
/****************************************************************/
/* */
/* pcb.h */
/* */
/* Process Control and Interrupt data structures */
/* */
/* November 26, 1991 */
/* */
/* Copyright (c) 1995 */
/* Pasquale J. Villani */
/* All Rights Reserved */
/* */
/* This file is part of DOS-C. */
/* */
/* DOS-C is free software; you can redistribute it and/or */
/* modify it under the terms of the GNU General Public License */
/* as published by the Free Software Foundation; either version */
/* 2, or (at your option) any later version. */
/* */
/* DOS-C is distributed in the hope that it will be useful, but */
/* WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See */
/* the GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public */
/* License along with DOS-C; see the file COPYING. If not, */
/* write to the Free Software Foundation, 675 Mass Ave, */
/* Cambridge, MA 02139, USA. */
/****************************************************************/
/***************************************************************
2000/03/22 ska
There is a newly documented (though used previously) side effect
of the definitions and assumptions made herein:
The assembly sources may use a macro named "PUSH$ALL" to push
all processor registers onto the stack, see example below:
PUSH$ALL
mov ax, sp
...
push ax
call _c_function
pop cx
The stack pointer immediately after the PUSH$ALL macro shall point to
a structure used as an "iregs" structure within the C language.
Therefore the internal of the structure "iregs" _must_ always
match the implementation of the macro "PUSH$ALL".
*/
#ifndef __PCB_H
#define __PCB_H
#ifdef MAIN
#ifdef VERSION_STRINGS
static BYTE *pcb_hRcsId =
"$Id: pcb.h 1316 2007-05-15 17:48:47Z bartoldeman $";
#endif
#endif
/* Force one-byte alignment for all the internal structures, see above */
#include <algnbyte.h>
/* */
/* interrupt handler structure definition */
/* */
typedef union {
UWORD x; /* access mode for ax, bx, etc. */
struct {
UBYTE l; /* access mode for al, bl, etc. */
UBYTE h; /* access mode for ah, bh, etc. */
} b;
} xreg;
/* The structure assumes that:
1) An interrupt was invoked, &
2) the PUSH$ALL macro was invoked immediately after that.
Furthermore, the PUSH$ALL macro must push ES first and AX last.
-- 2000/03/22 ska*/
/* maps MS-DOS unique stacking order */
typedef struct _iregss {
xreg a, b, c, d;
UWORD si, di, bp, ds, es;
UWORD ip, cs, flags;
} iregs;
/* struct used for local copy of registers */
typedef struct {
xreg a, b, c, d;
UWORD si, di, ds, es;
} lregs;
/* Registers directly passed to syscall;
must be the same order as iregs!
Is used to define parameters. */
#define DIRECT_IREGS \
xreg a, xreg b, xreg c, xreg d, \
UWORD si, UWORD di, UWORD bp, UWORD ds, UWORD es, \
UWORD ip, UWORD cs, UWORD flags
/* Process control block for task switching */
typedef struct {
UWORD pc_ss;
UWORD pc_sp;
iregs pc_regs;
} pcb;
/* Note: The following figure is not made by myself and I assume that
the order of "ES" through "AX" are misinterpreted?! -- 2000/03/22 ska*/
/* For MSC, the following offsets must match the assembly process */
/* support offsets */
/* NOTE: Alignemnts must be set to 1 (-Zp1) */
/* ss: 0 */
/* sp: 2 */
/* es: 4 */
/* ds: 6 */
/* di: 8 */
/* si: 10 */
/* bp: 12 */
/* sp: 14 NOTE: not used in this structure */
/* bx: 16 */
/* dx: 18 */
/* cx: 20 */
/* ax: 22 */
/* ip: 24 */
/* cs: 26 */
/* flags: 28 */
/* */
/* For Borland C, the following offsets must match the assembly process */
/* support offsets */
/* ss: 0 */
/* sp: 2 */
/* bp: 4 */
/* di: 6 */
/* si: 8 */
/* ds: 10 */
/* es: 12 */
/* dx: 14 */
/* cx: 16 */
/* bx: 18 */
/* ax: 20 */
/* ip: 22 */
/* cs: 24 */
/* flags: 26 */
#define BP bp
#define DI di
#define SI si
#define DS ds
#define ES es
#define DX d.x
#define CX c.x
#define BX b.x
#define AX a.x
#define DH d.b.h
#define CH c.b.h
#define BH b.b.h
#define AH a.b.h
#define DL d.b.l
#define CL c.b.l
#define BL b.b.l
#define AL a.b.l
#define IP ip
#define CS cs
#define FLAGS flags
#define FLG_ZERO 0x0040
#define FLG_CARRY 0x0001
/* Allow default alignment from now on */
#include <algndflt.h>
#endif

325
hdr/portab.h Normal file
View File

@ -0,0 +1,325 @@
/****************************************************************/
/* */
/* portab.h */
/* */
/* DOS-C portability typedefs, etc. */
/* */
/* May 1, 1995 */
/* */
/* Copyright (c) 1995 */
/* Pasquale J. Villani */
/* All Rights Reserved */
/* */
/* This file is part of DOS-C. */
/* */
/* DOS-C is free software; you can redistribute it and/or */
/* modify it under the terms of the GNU General Public License */
/* as published by the Free Software Foundation; either version */
/* 2, or (at your option) any later version. */
/* */
/* DOS-C is distributed in the hope that it will be useful, but */
/* WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See */
/* the GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public */
/* License along with DOS-C; see the file COPYING. If not, */
/* write to the Free Software Foundation, 675 Mass Ave, */
/* Cambridge, MA 02139, USA. */
/****************************************************************/
#ifdef MAIN
#ifdef VERSION_STRINGS
static char *portab_hRcsId =
"$Id: portab.h 1121 2005-03-15 15:25:08Z perditionc $";
#endif
#endif
/****************************************************************/
/* */
/* Machine dependant portable types. Note that this section is */
/* used primarily for segmented architectures. Common types and */
/* types used relating to segmented operations are found here. */
/* */
/* Be aware that segmented architectures impose on linear */
/* architectures because they require special types to be used */
/* throught the code that must be reduced to empty preprocessor */
/* replacements in the linear machine. */
/* */
/* #ifdef <segmeted machine> */
/* # define FAR far */
/* # define NEAR near */
/* #endif */
/* */
/* #ifdef <linear machine> */
/* # define FAR */
/* # define NEAR */
/* #endif */
/* */
/****************************************************************/
/* commandline overflow - removing -DI86 TE */
#if defined(__TURBOC__)
#define I86
#define CDECL cdecl
#if __TURBOC__ > 0x202
/* printf callers do the right thing for tc++ 1.01 but not tc 2.01 */
#define VA_CDECL
#else
#define VA_CDECL cdecl
#endif
#define PASCAL pascal
void __int__(int);
#ifndef FORSYS
void __emit__(char, ...);
#define disable() __emit__(0xfa)
#define enable() __emit__(0xfb)
#endif
#elif defined (_MSC_VER)
#define I86
#define asm __asm
#pragma warning(disable: 4761) /* "integral size mismatch in argument;
conversion supplied" */
#define CDECL _cdecl
#define VA_CDECL
#define PASCAL pascal
#define __int__(intno) asm int intno;
#define disable() asm cli
#define enable() asm sti
#define _CS getCS()
static unsigned short __inline getCS(void)
{
asm mov ax, cs;
}
#define _SS getSS()
static unsigned short __inline getSS(void)
{
asm mov ax, ss;
}
#elif defined(__WATCOMC__) /* don't know a better way */
#define I86
#define __int__(intno) asm int intno;
void disable(void);
#pragma aux disable = "cli" modify exact [];
void enable(void);
#pragma aux enable = "sti" modify exact [];
#define asm __asm
#define far __far
#define CDECL __cdecl
#define VA_CDECL
#define PASCAL pascal
#define _CS getCS()
unsigned short getCS(void);
#pragma aux getCS = "mov dx,cs" value [dx] modify exact[dx];
#define _SS getSS()
unsigned short getSS(void);
#pragma aux getSS = "mov dx,ss" value [dx] modify exact[dx];
#if !defined(FORSYS) && !defined(EXEFLAT) && _M_IX86 >= 300
#pragma aux default parm [ax dx cx] modify [ax dx es fs] /* min.unpacked size */
#endif
/* enable Possible loss of precision warning for compatibility with Borland */
#pragma enable_message(130)
#if _M_IX86 >= 300 || defined(M_I386)
#define I386
#endif
#elif defined (_MYMC68K_COMILER_)
#define MC68K
#elif defined(__GNUC__)
/* for warnings only ! */
#define MC68K
#else
#error Unknown compiler
We might even deal with a pre-ANSI compiler. This will certainly not compile.
#endif
#ifdef I86
#if _M_IX86 >= 300 || defined(M_I386)
#define I386
#elif _M_IX86 >= 100 || defined(M_I286)
#define I186
#endif
#endif
#ifdef MC68K
#define far /* No far type */
#define interrupt /* No interrupt type */
#define VOID void
#define FAR /* linear architecture */
#define NEAR /* " " */
#define INRPT interrupt
#define REG register
#define API int /* linear architecture */
#define NONNATIVE
#define PARASIZE 4096 /* "paragraph" size */
#define CDECL
#define PASCAL
#ifdef __GNUC__
#define CONST const
#define PROTO
typedef __SIZE_TYPE__ size_t;
#else
#define CONST
typedef unsigned size_t;
#endif
#endif
#ifdef I86
#define VOID void
#define FAR far /* segment architecture */
#define NEAR near /* " " */
#define INRPT interrupt
#define CONST const
#define REG register
#define API int far pascal /* segment architecture */
#define NATIVE
#define PARASIZE 16 /* "paragraph" size */
typedef unsigned size_t;
#endif
/* functions, that are shared between C and ASM _must_
have a certain calling standard. These are declared
as 'ASMCFUNC', and is (and will be ?-) cdecl */
#define ASMCFUNC CDECL
#define ASMPASCAL PASCAL
#define ASM ASMCFUNC
/* */
/* Boolean type & definitions of TRUE and FALSE boolean values */
/* */
typedef int BOOL;
#define FALSE (1==0)
#define TRUE (1==1)
/* */
/* Common pointer types */
/* */
#ifndef NULL
#define NULL 0
#endif
/* */
/* Convienence defines */
/* */
#define FOREVER while(TRUE)
#ifndef max
#define max(a,b) (((a) > (b)) ? (a) : (b))
#endif
#ifndef min
#define min(a,b) (((a) < (b)) ? (a) : (b))
#endif
/* */
/* Common byte, 16 bit and 32 bit types */
/* */
typedef char BYTE;
typedef short WORD;
typedef long DWORD;
typedef unsigned char UBYTE;
typedef unsigned short UWORD;
typedef unsigned long UDWORD;
typedef short SHORT;
typedef unsigned int BITS; /* for use in bit fields(!) */
typedef int COUNT;
typedef unsigned int UCOUNT;
typedef unsigned long ULONG;
#ifdef WITHFAT32
typedef unsigned long CLUSTER;
#else
typedef unsigned short CLUSTER;
#endif
typedef unsigned short UNICODE;
#if defined(STATICS) || defined(__WATCOMC__)
#define STATIC static /* local calls inside module */
#else
#define STATIC
#endif
#ifdef UNIX
typedef char FAR *ADDRESS;
#else
typedef void FAR *ADDRESS;
#endif
#ifdef STRICT
typedef signed long LONG;
#else
#define LONG long
#endif
#define MK_UWORD(hib,lob) (((UWORD)(hib) << 8u) | (UBYTE)(lob))
#define MK_ULONG(hiw,low) (((ULONG)(hiw) << 16u) | (UWORD)(low))
/* General far pointer macros */
#ifdef I86
#ifndef MK_FP
#if defined(__WATCOMC__)
#define MK_FP(seg,ofs) (((UWORD)(seg)):>((VOID *)(ofs)))
#elif defined(__TURBOC__) && (__TURBOC__ > 0x202)
#define MK_FP(seg,ofs) ((void _seg *)(seg) + (void near *)(ofs))
#else
#define MK_FP(seg,ofs) ((void FAR *)(((ULONG)(seg)<<16)|(UWORD)(ofs)))
#endif
#define pokeb(seg, ofs, b) (*((unsigned char far *)MK_FP(seg,ofs)) = b)
#define poke(seg, ofs, w) (*((unsigned far *)MK_FP(seg,ofs)) = w)
#define pokew poke
#define pokel(seg, ofs, l) (*((unsigned long far *)MK_FP(seg,ofs)) = l)
#define peekb(seg, ofs) (*((unsigned char far *)MK_FP(seg,ofs)))
#define peek(seg, ofs) (*((unsigned far *)MK_FP(seg,ofs)))
#define peekw peek
#define peekl(seg, ofs) (*((unsigned long far *)MK_FP(seg,ofs)))
#if defined(__TURBOC__) && (__TURBOC__ > 0x202)
#define FP_SEG(fp) ((unsigned)(void _seg *)(void far *)(fp))
#else
#define FP_SEG(fp) ((unsigned)((ULONG)(VOID FAR *)(fp)>>16))
#endif
#define FP_OFF(fp) ((unsigned)(fp))
#endif
#endif
#ifdef MC68K
#define MK_FP(seg,ofs) ((VOID *)(&(((BYTE *)(size_t)(seg))[(ofs)])))
#define FP_SEG(fp) (0)
#define FP_OFF(fp) ((size_t)(fp))
#endif
typedef VOID (FAR ASMCFUNC * intvec) (void);
#define MK_PTR(type,seg,ofs) ((type FAR*) MK_FP (seg, ofs))
#if __TURBOC__ > 0x202
# define MK_SEG_PTR(type,seg) ((type _seg*) (seg))
#else
# define _seg FAR
# define MK_SEG_PTR(type,seg) MK_PTR (type, seg, 0)
#endif
/*
this suppresses the warning
unreferenced parameter 'x'
and (hopefully) generates no code
*/
#define UNREFERENCED_PARAMETER(x) (void)x;
#ifdef I86 /* commandline overflow - removing /DPROTO TE */
#define PROTO
#endif
#define LENGTH(x) (sizeof(x)/sizeof(x[0]))

110
hdr/process.h Normal file
View File

@ -0,0 +1,110 @@
/****************************************************************/
/* */
/* process.h */
/* */
/* DOS exec data structures & declarations */
/* */
/* November 23, 1991 */
/* */
/* Copyright (c) 1995 */
/* Pasquale J. Villani */
/* All Rights Reserved */
/* */
/* This file is part of DOS-C. */
/* */
/* DOS-C is free software; you can redistribute it and/or */
/* modify it under the terms of the GNU General Public License */
/* as published by the Free Software Foundation; either version */
/* 2, or (at your option) any later version. */
/* */
/* DOS-C is distributed in the hope that it will be useful, but */
/* WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See */
/* the GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public */
/* License along with DOS-C; see the file COPYING. If not, */
/* write to the Free Software Foundation, 675 Mass Ave, */
/* Cambridge, MA 02139, USA. */
/****************************************************************/
/* Modes available as first argument to the spawnxx functions. */
#define P_WAIT 0 /* child runs separately, parent waits until exit */
#define P_NOWAIT 1 /* both concurrent -- not implemented */
#define P_OVERLAY 2 /* child replaces parent, parent no longer exists */
typedef struct {
union {
struct {
UWORD load_seg;
UWORD reloc;
} _load;
struct {
UWORD env_seg;
CommandTail FAR *cmd_line;
fcb FAR *fcb_1;
fcb FAR *fcb_2;
BYTE FAR *stack;
BYTE FAR *start_addr;
} _exec;
} ldata;
} exec_blk;
#define exec ldata._exec
#define load ldata._load
typedef struct {
UWORD ps_exit; /* 00 CP/M-like exit point: int 20 */
UWORD ps_size; /* 02 segment of first byte beyond */
/* memory allocated to program */
BYTE ps_fill1; /* 04 single char fill=0 */
/* CP/M-like entry point */
/* offsets 5-9 are a far call to absolute address 0:00C0h
encoded using 1MB wrap form of address (e.g. 0F01D:FEF0h)
for compatiblity with CP/M apps that do a near call to psp:5
and expect size (KB) of allocated segment in word at offset 6 */
UBYTE ps_farcall; /* 05 far call opcode */
VOID(FAR ASMCFUNC * ps_reentry) (void); /* 06 re-entry point */
intvec ps_isv22, /* 0a terminate address */
ps_isv23, /* 0e ctrl-break address */
ps_isv24; /* 12 critical error address */
UWORD ps_parent; /* 16 parent psp segment */
UBYTE ps_files[20]; /* 18 file table - 0xff is unused */
UWORD ps_environ; /* 2c environment paragraph */
BYTE FAR *ps_stack; /* 2e user stack pointer - int 21 */
UWORD ps_maxfiles; /* 32 maximum open files */
UBYTE FAR *ps_filetab; /* 34 open file table pointer */
VOID FAR *ps_prevpsp; /* 38 previous psp pointer */
UBYTE ps_fill2; /* 3c unused */
UBYTE ps_truename; /* 3d [unused] append truename flag int2f/B711h */
UBYTE ps_netx_taskid[2]; /* 3e [Novell only field] task id */
UWORD ps_retdosver; /* 40 [unused] version to return on int21/30h */
UWORD pdb_next; /* 42 [Win only field] PSP chain */
UBYTE ps_fill2b[4]; /* 44 unused, 4 bytes */
UBYTE ps_olddos; /* 48 [Win only field] DOS/Win program */
UBYTE ps_fill2c[7]; /* 49 unused, 7 bytes */
UBYTE ps_unix[3]; /* 50 unix style call - 0xcd 0x21 0xcb */
BYTE ps_fill3[9]; /* 53 */
union {
struct {
fcb _ps_fcb1; /* 5c first command line argument */
} _u1;
struct {
BYTE fill4[16];
fcb _ps_fcb2; /* second command line argument */
} _u2;
struct {
BYTE fill5[36];
CommandTail _ps_cmd;
} _u3;
} _u;
} psp;
#define ps_fcb1 _u._u1._ps_fcb1
#define ps_fcb2 _u._u2._ps_fcb2
#define ps_cmd _u._u3._ps_cmd

143
hdr/sft.h Normal file
View File

@ -0,0 +1,143 @@
/****************************************************************/
/* */
/* sft.h */
/* DOS-C */
/* */
/* DOS System File Table Structure */
/* */
/* Copyright (c) 1995, 1996 */
/* Pasquale J. Villani */
/* All Rights Reserved */
/* */
/* This file is part of DOS-C. */
/* */
/* DOS-C is free software; you can redistribute it and/or */
/* modify it under the terms of the GNU General Public License */
/* as published by the Free Software Foundation; either version */
/* 2, or (at your option) any later version. */
/* */
/* DOS-C is distributed in the hope that it will be useful, but */
/* WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See */
/* the GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public */
/* License along with DOS-C; see the file COPYING. If not, */
/* write to the Free Software Foundation, 675 Mass Ave, */
/* Cambridge, MA 02139, USA. */
/****************************************************************/
#ifdef MAIN
#ifdef VERSION_STRINGS
static BYTE *sft_hRcsId =
"$Id: sft.h 1429 2009-06-09 18:50:03Z bartoldeman $";
#endif
#endif
#define SFTMAX 128
/* Handle Definition entry */
typedef struct {
WORD sft_count; /* 00 - reference count */
WORD sft_mode; /* 02 - open mode - see below */
BYTE sft_attrib; /* 04 - file attribute - dir style */
union /* 05 */
{
WORD _sft_flags;
struct {
BYTE _sft_flags_lo;
BYTE _sft_flags_hi;
} _split_sft_flags;
} sft_flags_union;
union /* 07 */
{
struct dpb FAR *_sft_dcb; /* The device control block */
struct dhdr FAR *_sft_dev; /* device driver for char dev */
} sft_dcb_or_dev;
#ifdef WITHFAT32
UWORD sft_relclust_high; /* 0b - High part of relative cluster */
#else
CLUSTER sft_stclust; /* 0b - Starting cluster */
#endif
time sft_time; /* 0d - File time */
date sft_date; /* 0f - File date */
ULONG sft_size; /* 11 - File size */
ULONG sft_posit; /* 15 - Current file position */
UWORD sft_relclust; /* 19 - File relative cluster (low part) */
ULONG sft_dirsector; /* 1b - Sector containing cluster */
UBYTE sft_diridx; /* 1f - directory index */
BYTE sft_name[11]; /* 20 - dir style file name */
#ifdef WITHFAT32
CLUSTER sft_stclust; /* 2b - Starting cluster */
#else
BYTE FAR *sft_bshare; /* 2b - backward link of file sharing sft */
#endif
WORD sft_mach; /* 2f - machine number - network apps */
WORD sft_psp; /* 31 - owner psp */
WORD sft_shroff; /* 33 - Sharing offset */
CLUSTER sft_cuclust; /* 35 - File current cluster */
#ifdef WITHFAT32
UWORD sft_pad;
#else
BYTE FAR *sft_ifsptr; /* 37 - pointer to IFS driver for file, 0000000h if native DOS */
#endif
} sft;
/* SFT Table header definition */
typedef struct _sftheader {
struct sfttbl FAR * /* link to next table in list */
sftt_next;
WORD sftt_count; /* # of handle definition */
/* entries, this table */
} sftheader;
/* System File Definition List */
typedef struct sfttbl {
struct sfttbl FAR * /* link to next table in list */
sftt_next;
WORD sftt_count; /* # of handle definition */
/* entries, this table */
sft sftt_table[SFTMAX]; /* The array of sft for block */
} sfttbl;
/* defines for sft use */
#define SFT_MASK 0x0060 /* splits device data */
/* flag bits */
/* the following bit is for redirection */
#define SFT_FSHARED 0x8000 /* Networked access */
/* the following entry differntiates char & block access */
#define SFT_FDEVICE 0x0080 /* device entry */
/* the following bits are file (block) unique */
#define SFT_FDATE 0x4000 /* File date set */
#define SFT_FCLEAN 0x0040 /* File has not been written to */
#define SFT_FDMASK 0x003f /* File mask for drive no */
/* the following bits are device (char) unique */
#define SFT_FIOCTL 0x4000 /* IOCTL support - device */
#define SFT_FOCRM 0x0800 /* Open/Close/RM bit in device attribute*/
#define SFT_FEOF 0x0040 /* device eof */
#define SFT_FBINARY 0x0020 /* device binary mode */
#define SFT_FSPECIAL 0x0010 /* int 29 support */
#define SFT_FCLOCK 0x0008 /* device is clock */
#define SFT_FNUL 0x0004 /* device is nul */
#define SFT_FCONOUT 0x0002 /* device is console output */
#define SFT_FCONIN 0x0001 /* device is console input */
/* Convenience defines */
#define sft_dcb sft_dcb_or_dev._sft_dcb
#define sft_dev sft_dcb_or_dev._sft_dev
#define sft_flags sft_flags_union._sft_flags
#define sft_flags_hi sft_flags_union._split_sft_flags._sft_flags_hi
#define sft_flags_lo sft_flags_union._split_sft_flags._sft_flags_lo
/* defines for LSEEK */
#define SEEK_SET 0u
#define SEEK_CUR 1u
#define SEEK_END 2u

198
hdr/stacks.inc Normal file
View File

@ -0,0 +1,198 @@
;
; File:
; stacks.inc
; Description:
; Macro support for register stack frame
;
; Copyright (c) 1998
; Pasquale J. Villani
; All Rights Reserved
;
; This file is part of DOS-C.
;
; DOS-C is free software; you can redistribute it and/or
; modify it under the terms of the GNU General Public License
; as published by the Free Software Foundation; either version
; 2, or (at your option) any later version.
;
; DOS-C is distributed in the hope that it will be useful, but
; WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
; the GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public
; License along with DOS-C; see the file COPYING. If not,
; write to the Free Software Foundation, 675 Mass Ave,
; Cambridge, MA 02139, USA.
;
; $Id: stacks.inc 1591 2011-05-06 01:46:55Z bartoldeman $
;
;
; Standard stack frame used throughout DOS-C
;
; MS-DOS specific
;
; +---------------+
; | irp hi | 26
; +---------------+
; | irp low | 24
; +---------------+
; | flags | 22
; +---------------+
; | cs | 20
; +---------------+
; | ip | 18
; +---------------+
; | es | 16
; +---------------+
; | ds | 14
; +---------------+
; | bp | 12
; +---------------+
; | di | 10
; +---------------+
; | si | 8
; +---------------+
; | dx | 6
; +---------------+
; | cx | 4
; +---------------+
; | bx | 2
; +---------------+
; | ax | 0
; +---------------+
;
;; Note: The order of the pushed registers _must_ match with the definition
;; of the "iregs" structure within PCB.H, because a pointer to the last
;; pushed register is used as a pointer to a "iregs" structure within the
;; called C sources! -- 2000/03/22 ska
; Don't use `struc RegFrame' etc. here because it interferes with segment
; definitions.
reg_ax equ 0
reg_bx equ 2
reg_cx equ 4
reg_dx equ 6
reg_si equ 8
reg_di equ 10
reg_bp equ 12
reg_ds equ 14
reg_es equ 16
reg_ip equ 18
reg_cs equ 20
reg_flags equ 22
irp_low equ 24
irp_hi equ 26
%macro PUSH$ALL 0
push es
push ds
push bp
push di
push si
push dx
push cx
push bx
push ax
%endmacro
%macro POP$ALL 0
pop ax
pop bx
pop cx
pop dx
pop si
pop di
pop bp
pop ds
pop es
%endmacro
; I386.inc - 10/25/01 by tom ehlert
;
; compiling the kernel for 386 will (sometimes) change the
; high part of (some) registers, which will be (sometimes) be used
; later
;
; assumption:
; we have never seen MSVC to use anything but eax, ecx, edx,
; nor have we seen Borland C to use anything but eax, ebx, edx,
; so we only protect eax, ebx or ecx, edx to conserve stack space
;
; to save even more stack space, we save only HIGH part of regs
; at some expense of slower execution. it's easier anyway :-)
;
; WATCOM only uses FS: and GS: (using -zff and -zgf) and never
; any high part of the 386 registers
;
%IF XCPU < 386
; no need to save/restore anything
; error 1 2 3
%macro Protect386Registers 0
%endmacro
%macro RestoreSP 0
mov sp, bp
%endmacro
%macro Restore386Registers 0
%endmacro
%ELSE
%ifdef WATCOM
%macro Protect386Registers 0
push fs
push gs
%endmacro
%macro RestoreSP 0
lea sp, [bp-4]
%endmacro
%macro Restore386Registers 0
pop gs
pop fs
%endmacro
%else
%macro Protect386Registers 0
push eax
pop ax
%ifdef MSCL8
push ecx
pop cx
%else ;BC5
push ebx
pop bx
%endif
push edx
pop dx
%endmacro
%macro RestoreSP 0
lea sp, [bp-6]
%endmacro
%macro Restore386Registers 0
push dx
pop edx
%ifdef MSCL8
push cx
pop ecx
%else ;BC5
push bx
pop ebx
%endif
push ax
pop eax
%endmacro
%endif
%ENDIF

44
hdr/tail.h Normal file
View File

@ -0,0 +1,44 @@
/****************************************************************/
/* */
/* tail.h */
/* */
/* Command tail data structures */
/* */
/* July 1, 1993 */
/* */
/* Copyright (c) 1995 */
/* Pasquale J. Villani */
/* All Rights Reserved */
/* */
/* This file is part of DOS-C. */
/* */
/* DOS-C is free software; you can redistribute it and/or */
/* modify it under the terms of the GNU General Public License */
/* as published by the Free Software Foundation; either version */
/* 2, or (at your option) any later version. */
/* */
/* DOS-C is distributed in the hope that it will be useful, but */
/* WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See */
/* the GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public */
/* License along with DOS-C; see the file COPYING. If not, */
/* write to the Free Software Foundation, 675 Mass Ave, */
/* Cambridge, MA 02139, USA. */
/****************************************************************/
#ifdef MAIN
#ifdef VERSION_STRINGS
static BYTE *tail_hRcsId =
"$Id: tail.h 485 2002-12-09 00:17:15Z bartoldeman $";
#endif
#endif
#define CTBUFFERSIZE 127
typedef struct {
UBYTE ctCount; /* number of bytes returned */
char ctBuffer[CTBUFFERSIZE]; /* the buffer itself */
} CommandTail;

56
hdr/time.h Normal file
View File

@ -0,0 +1,56 @@
/****************************************************************/
/* */
/* time.h */
/* */
/* DOS General Time Structure */
/* */
/* January 21, 1993 */
/* */
/* Copyright (c) 1995 */
/* Pasquale J. Villani */
/* All Rights Reserved */
/* */
/* This file is part of DOS-C. */
/* */
/* DOS-C is free software; you can redistribute it and/or */
/* modify it under the terms of the GNU General Public License */
/* as published by the Free Software Foundation; either version */
/* 2, or (at your option) any later version. */
/* */
/* DOS-C is distributed in the hope that it will be useful, but */
/* WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See */
/* the GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public */
/* License along with DOS-C; see the file COPYING. If not, */
/* write to the Free Software Foundation, 675 Mass Ave, */
/* Cambridge, MA 02139, USA. */
/****************************************************************/
/* TC 2.01 complains if `time' is defined twice. -- ror4 */
#ifndef DOSC_TIME_H
#define DOSC_TIME_H
#ifdef MAIN
#ifdef VERSION_STRINGS
static BYTE *time_hRcsId =
"$Id: time.h 942 2004-05-23 15:00:37Z bartoldeman $";
#endif
#endif
typedef UWORD time;
struct dostime
{
unsigned char minute, hour, hundredth, second;
};
struct dosdate
{
unsigned short year;
unsigned char monthday, month;
};
#endif

51
hdr/version.h Normal file
View File

@ -0,0 +1,51 @@
/****************************************************************/
/* */
/* version.h */
/* */
/* Common version information */
/* */
/* Copyright (c) 1997 */
/* Pasquale J. Villani */
/* All Rights Reserved */
/* */
/* This file is part of DOS-C. */
/* */
/* DOS-C is free software; you can redistribute it and/or */
/* modify it under the terms of the GNU General Public License */
/* as published by the Free Software Foundation; either version */
/* 2, or (at your option) any later version. */
/* */
/* DOS-C is distributed in the hope that it will be useful, but */
/* WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See */
/* the GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public */
/* License along with DOS-C; see the file COPYING. If not, */
/* write to the Free Software Foundation, 675 Mass Ave, */
/* Cambridge, MA 02139, USA. */
/****************************************************************/
/* The version the kernel reports as compatible with */
#ifdef WITHFAT32
#define MAJOR_RELEASE 7
#define MINOR_RELEASE 10
#else
#define MAJOR_RELEASE 6
#define MINOR_RELEASE 22
#endif
/* The actual kernel revision, 2000+REVISION_SEQ = 2.REVISION_SEQ */
#define REVISION_SEQ 42 /* returned in BL by int 21 function 30 */
#define OEM_ID 0xfd /* FreeDOS, returned in BH by int 21 30 */
/* Used for version information displayed to user at boot (& stored in os_release string) */
#ifndef KERNEL_VERSION
#define KERNEL_VERSION "- SVN "
#endif
/* actual version string */
#define KVS(v,s,o) "FreeDOS kernel " v "(build 20" #s " OEM:" #o ") [compiled " __DATE__ "]\n"
#define xKVS(v,s,o) KVS(v,s,o)
#define KERNEL_VERSION_STRING xKVS(KERNEL_VERSION, REVISION_SEQ, OEM_ID)

39
hdr/win.h Normal file
View File

@ -0,0 +1,39 @@
#ifndef __WINSUPPORT_H
#define __WINSUPPORT_H
#ifdef WIN31SUPPORT /* defined to enable kernel hooks for win3.x compatibility */
extern UWORD winInstanced; /* internal flag marking if Windows is active */
/* contains information about data that must be kept for each active DOS
instance, ie data that can NOT be shared between multiple VMs.
*/
struct WinStartupInfo
{
UWORD winver; /* this structure version, matches Windows version */
ULONG next; /* far pointer to next WinStartupInfo structure or NULL */
ULONG vddName; /* far pointer to ASCIIZ pathname of virtual device driver */
ULONG vddInfo; /* far pointer to vdd reference data or NULL if vddName=NULL */
ULONG instanceTable; /* far pointer to array of instance data */
ULONG optInstanceTable; /* used only if winver set to 0x400 (w95)*/
};
extern struct WinStartupInfo winStartupInfo;
/* contains a list of offsets relative to DOS data segment of
various internal variables.
*/
struct WinPatchTable
{
UWORD dosver;
UWORD OffTempDS;
UWORD OffTempBX;
UWORD OffInDOS;
UWORD OffMachineID;
UWORD OffCritSectPatches;
UWORD OffLastMCBSeg; /* used by Win 3.1 if DOS version 5 or higher */
};
extern struct WinPatchTable winPatchTable;
#endif /* WIN31SUPPORT */
#endif /* __WINSUPPORT_H */

83
hdr/xstructs.h Normal file
View File

@ -0,0 +1,83 @@
/****************************************************************/
/* */
/* xstructs.h */
/* */
/* Extended DOS 7.0+ structures */
/* */
/****************************************************************/
#ifdef MAIN
#ifdef VERSION_STRINGS
static BYTE *XStructs_hRcsId =
"$Id: xstructs.h 1457 2009-06-26 20:00:41Z bartoldeman $";
#endif
#endif
struct xdpbdata {
UWORD xdd_dpbsize;
struct dpb xdd_dpb;
};
struct xfreespace {
UWORD xfs_datasize; /* size of this structure */
union {
UWORD requested; /* requested structure version */
UWORD actual; /* actual structure version */
} xfs_version;
ULONG xfs_clussize; /* number of sectors per cluster */
ULONG xfs_secsize; /* number of bytes per sector */
ULONG xfs_freeclusters; /* number of available clusters */
ULONG xfs_totalclusters; /* total number of clusters on the drive */
ULONG xfs_freesectors; /* number of physical sectors available */
ULONG xfs_totalsectors; /* total number of physical sectors */
ULONG xfs_freeunits; /* number of available allocation units */
ULONG xfs_totalunits; /* total allocation units */
UBYTE xfs_reserved[8];
};
struct xdpbforformat {
UWORD xdff_datasize; /* size of this structure */
union {
UWORD requested; /* requested structure version */
UWORD actual; /* actual structure version */
} xdff_version;
UDWORD xdff_function; /* function number:
00h invalidate DPB counts
01h rebuild DPB from BPB
02h force media change
03h get/set active FAT number and mirroring
04h get/set root directory cluster number
*/
union {
struct {
DWORD nfreeclst; /* # free clusters
(-1 - unknown, 0 - don't change) */
DWORD cluster; /* cluster # of first free
(-1 - unknown, 0 - don't change) */
UDWORD reserved[2];
} setdpbcounts;
struct {
UDWORD unknown;
bpb FAR *bpbp;
UDWORD reserved[2];
} rebuilddpb;
struct {
DWORD new; /* new active FAT/mirroring state, or -1 to get
bits 3-0: the 0-based FAT number of the active FAT
bits 6-4: reserved (0)
bit 7: do not mirror active FAT to inactive FATs
or:
set new root directory cluster, -1 - get current
*/
DWORD old; /* previous active FAT/mirroring state (as above)
or
get previous root directory cluster
*/
UDWORD reserved[2];
} setget;
} xdff_f;
};
COUNT DosGetExtFree(BYTE FAR * DriveString, struct xfreespace FAR * xfsp);

130
kernel/apisupt.asm Normal file
View File

@ -0,0 +1,130 @@
; File:
; apisupt.asm
; Description:
; Assembly support routines for stack manipulation, etc.
;
; Copyright (c) 1995, 1998
; Pasquale J. Villani
; All Rights Reserved
;
; This file is part of DOS-C.
;
; DOS-C is free software; you can redistribute it and/or
; modify it under the terms of the GNU General Public License
; as published by the Free Software Foundation; either version
; 2, or (at your option) any later version.
;
; DOS-C is distributed in the hope that it will be useful, but
; WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
; the GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public
; License along with DOS-C; see the file COPYING. If not,
; write to the Free Software Foundation, 675 Mass Ave,
; Cambridge, MA 02139, USA.
;
; $Id: apisupt.asm 538 2003-03-12 22:43:53Z bartoldeman $
;
%include "segs.inc"
segment HMA_TEXT
%if 0
extern _api_sp:wrt DGROUP ; api stacks - for context
extern _api_ss:wrt DGROUP ; switching
extern _usr_sp:wrt DGROUP ; user stacks
extern _usr_ss:wrt DGROUP
global _set_stack
;
; void set_stack(void) -
; save current stack and setup our local stack
;
_set_stack:
; save foreground stack
; we need to get the return values from the stack
; since the current stack will change
pop ax ;get return offset
; Save the flags so that we can restore correct interrupt
; state later. We need to disable interrupts so that we
; don't trash memory with new sp-old ss combination
pushf
pop dx
cli
; save bp
push bp
mov cx, sp
neg cx
; save away foreground process' stack
push word [_usr_ss]
push word [_usr_sp]
mov word [_usr_ss],ss
mov word [_usr_sp],sp
; setup our local stack
mov ss,word [_api_ss]
mov sp,word [_api_sp]
add cx, sp
add bp, cx
; setup for ret
push ax
; now restore interrupt state
push dx
popf
ret
;
; void restore_stack(void) -
; restore foreground stack, throw ours away
;
global _restore_stack
_restore_stack:
; we need to get the return values from the stack
; since the current stack will change
pop cx ;get return offset
; Save the flags so that we can restore correct interrupt
; state later. We need to disable interrupts so that we
; don't trash memory with new sp-old ss combination
pushf
pop dx
cli
; save background stack
mov word [_api_ss],ss
mov word [_api_sp],sp
; restore foreground stack here
mov ss,word [_usr_ss]
mov sp,word [_usr_sp]
pop word [_usr_sp]
pop word [_usr_ss]
; make bp relative to our stack frame
pop bp
;mov bp,sp
; setup for ret
push cx
; now restore interrupt state
push dx
popf
ret
%endif

554
kernel/asmsupt.asm Normal file
View File

@ -0,0 +1,554 @@
; File:
; asmsupt.asm
; Description:
; Assembly support routines for miscellaneous functions
;
; Copyright (c) 1995, 1998
; Pasquale J. Villani
; All Rights Reserved
;
; This file is part of DOS-C.
;
; DOS-C is free software; you can redistribute it and/or
; modify it under the terms of the GNU General Public License
; as published by the Free Software Foundation; either version
; 2, or (at your option) any later version.
;
; DOS-C is distributed in the hope that it will be useful, but
; WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
; the GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public
; License along with DOS-C; see the file COPYING. If not,
; write to the Free Software Foundation, 675 Mass Ave,
; Cambridge, MA 02139, USA.
;
; version 1.4 by tom.ehlert@ginko.de
; added some more functions
; changed bcopy, scopy, sncopy,...
; to memcpy, strcpy, strncpy
; Bart Oldeman: optimized a bit: see /usr/include/bits/string.h from
; glibc 2.2
;
; $Id: asmsupt.asm 1568 2011-04-09 02:42:51Z bartoldeman $
;
; for OW on Linux:
%ifdef owlinux
%define WATCOM
%endif
%ifdef WATCOM
%ifdef _INIT
%define WATCOM_INIT ; no seperate init segment for watcom.
%endif
%endif
%ifndef WATCOM_INIT
%include "segs.inc"
%ifdef _INIT
segment INIT_TEXT
%define FMEMCPYBACK INIT_FMEMCPYBACK
%define MEMCPY INIT_MEMCPY
%define FMEMCPY INIT_FMEMCPY
%define MEMSET INIT_MEMSET
%define FMEMSET INIT_FMEMSET
%define STRCPY INIT_STRCPY
%define FSTRCPY INIT_FSTRCPY
%define STRLEN INIT_STRLEN
%define FSTRLEN INIT_FSTRLEN
%define FMEMCHR INIT_FMEMCHR
%define FSTRCHR INIT_FSTRCHR
%define STRCHR INIT_STRCHR
%define FSTRCMP INIT_FSTRCMP
%define STRCMP INIT_STRCMP
%define FSTRNCMP INIT_FSTRNCMP
%define STRNCMP INIT_STRNCMP
%define FMEMCMP INIT_FMEMCMP
%define MEMCMP INIT_MEMCMP
%else
segment HMA_TEXT
%endif
;*********************************************************************
; this implements some of the common string handling functions
;
; every function has 1 entry
;
; NEAR FUNC()
;
; currently done:
;
; fmemcpyBack(void FAR *dest, void FAR *src, int count)
; memcpy(void *dest, void *src, int count)
; fmemcpy(void FAR *dest, void FAR *src, int count)
; memset(void *dest, int ch, int count);
; fmemset(void FAR *dest, int ch, int count);
; strcpy (void *dest, void *src);
; fstrcpy (void FAR*dest, void FAR *src);
; strlen (void *dest);
; fstrlen (void FAR*dest);
; fmemchr (BYTE FAR *src , int ch);
; fstrchr (BYTE FAR *src , int ch);
; strchr (BYTE *src , int ch);
; fstrcmp (BYTE FAR *s1 , BYTE FAR *s2);
; strcmp (BYTE *s1 , BYTE *s2);
; fstrncmp(BYTE FAR *s1 , BYTE FAR *s2, int count);
; strncmp(BYTE *s1 , BYTE *s2, int count);
; fmemcmp(BYTE FAR *s1 , BYTE FAR *s2, int count);
; memcmp(BYTE *s1 , BYTE *s2, int count);
;***********************************************
; pascal_setup - set up the standard calling frame for C-functions
; and save registers needed later
; also preload the args for the near functions
; di=arg1
; si=arg2
; cx=arg3
;
pascal_setup:
pop ax ; get return address
push bp ; Standard C entry
mov bp,sp
%ifdef WATCOM
push bx
push cx
push es
%endif
push si
push di
push ds
; Set both ds and es to same segment (for near copy)
push ds
pop es
; Set direction to autoincrement
cld
mov bl,6 ; majority (4) wants that
mov cx,[4+bp] ; majority (8) wants that (near and far)
mov si,[6+bp] ; majority (3) wants that (near)
mov di,[8+bp] ; majority (3) wants that (near)
jmp ax
;***********************************************
;
; VOID memcpy(REG BYTE *s, REG BYTE *d, REG COUNT n);
;
global MEMCPY
MEMCPY:
call pascal_setup
;mov cx,[4+bp] - preset above
;mov si,[6+bp] - preset above
;mov di,[8+bp] - preset above
;mov bl,6 - preset above
domemcpy:
; And do the built-in byte copy, but do a 16-bit transfer
; whenever possible.
shr cx,1
rep movsw
jnc memcpy_return
movsb
memcpy_return:
%if 0 ; only needed for fmemcpyback
cld
%endif
;
; pascal_return - pop saved registers and do return
;
jmp short pascal_return
;************************************************************
;
; VOID fmemcpy(REG BYTE FAR *d, REG BYTE FAR *s,REG COUNT n);
; VOID fmemcpyBack(REG BYTE FAR *d, REG BYTE FAR *s,REG COUNT n);
;
global FMEMCPY
%if 0
global FMEMCPYBACK
FMEMCPYBACK:
std ; force to copy the string in reverse order
%endif
FMEMCPY:
call pascal_setup
; Get the repetition count, n preset above
; mov cx,[bp+4]
; Get the far source pointer, s
lds si,[bp+6]
; Get the far destination pointer d
les di,[bp+10]
mov bl,10
jmp short domemcpy
;***************************************************************
;
; VOID fmemset(REG VOID FAR *d, REG BYTE ch, REG COUNT n);
;
global FMEMSET
FMEMSET:
call pascal_setup
; Get the repetition count, n - preset above
; mov cx,[bp+4]
; Get the fill byte ch
mov ax,[bp+6]
; Get the far source pointer, s
les di,[bp+8]
mov bl,8
domemset:
mov ah, al
shr cx,1
rep stosw
jnc pascal_return
stosb
jmp short pascal_return
;***************************************************************
;
; VOID memset(REG VOID *d, REG BYTE ch, REG COUNT n);
;
global MEMSET
MEMSET:
call pascal_setup
; Get the repitition count, n - preset above
; mov cx,[bp+4]
; Get the char ch
mov ax, [bp+6]
; Get the far source pointer, d - preset above
; mov di,[bp+8]
;mov bl, 6 ; preset above
jmp short domemset
;*****
pascal_return:
lds di, [bp] ; return address in ds, saved bp in di
mov bh, 0
add bp, bx ; point bp to "as if there were 0 args"
mov [bp+2], ds ; put return address at first arg
mov [bp], di ; saved bp below that one
pop ds
pop di
pop si
%ifdef WATCOM
pop es
pop cx
pop bx
%endif
mov sp,bp
pop bp
ret
;*****************************************************************
; fstrcpy (void FAR*dest, void FAR *src);
%ifndef _INIT
global FSTRCPY
FSTRCPY:
call pascal_setup
; Get the source pointer, ss
lds si,[bp+4]
; and the destination pointer, d
les di,[bp+8]
mov bl,8
jmp short dostrcpy
%endif
;******
global STRCPY
STRCPY:
call pascal_setup
; Get the source pointer, ss
mov si,[bp+4]
; and the destination pointer, d
mov di,[bp+6]
mov bl,4
dostrcpy:
strcpy_loop:
lodsb
stosb
test al,al
jne strcpy_loop
jmp short pascal_return
;******************************************************************
%ifndef _INIT
global FSTRLEN
FSTRLEN:
call pascal_setup
; Get the source pointer, ss
les di,[bp+4]
mov bl,4
jmp short dostrlen
%endif
;**********************************************
global STRLEN
STRLEN:
call pascal_setup
; Get the source pointer, ss
mov di,[bp+4]
mov bl,2
dostrlen:
mov al,0
mov cx,0xffff
repne scasb
mov ax,cx
not ax
dec ax
jmp short pascal_return
;************************************************************
; strchr (BYTE *src , int ch);
global STRCHR
STRCHR:
call pascal_setup
; Get the source pointer, ss
; mov cx,[bp+4] - preset above
; mov si,[bp+6] - preset above
mov bl,4
strchr_loop:
lodsb
cmp al,cl
je strchr_found
test al,al
jne strchr_loop
strchr_retzero:
xor ax, ax ; return NULL if not found
mov dx, ax ; for fstrchr()
jmp short pascal_return
strchr_found:
mov ax, si
mov dx, ds ; for fstrchr()
strchr_found1:
dec ax
jmp short pascal_return
%ifndef _INIT
;*****
; fstrchr (BYTE far *src , int ch);
global FSTRCHR
FSTRCHR:
call pascal_setup
; Get ch (preset above)
;mov cx, [bp+4]
;and the source pointer, src
lds si, [bp+6]
;mov bl, 6 - preset above
jmp short strchr_loop
;******
global FMEMCHR
FMEMCHR:
call pascal_setup
; Get the length - preset above
; mov cx, [bp+4]
; and the search value
mov ax, [bp+6]
; and the source pointer, ss
les di, [bp+8]
mov bl, 8
jcxz strchr_retzero
repne scasb
jne strchr_retzero
mov dx, es
mov ax, di
jmp short strchr_found1
;**********************************************************************
global FSTRCMP
FSTRCMP:
call pascal_setup
; Get the source pointer, ss
lds si,[bp+4]
; and the destination pointer, d
les di,[bp+8]
mov bl,8
%if 0
jmp short dostrcmp
;******
global STRCMP
STRCMP:
call pascal_setup
mov bl,4
; Get the source pointer, ss
; mov si,[bp+4]
; and the destination pointer, d
; mov di,[bp+6]
xchg si,di
dostrcmp:
%endif
; replace strncmp(s1,s2)-->
; strncmp(s1,s2,0xffff)
mov cx,0xffff
%if 0
jmp short dostrncmp
;**********************************************************************
global FSTRNCMP
FSTRNCMP:
call pascal_setup
; Get the source pointer, ss
lds si,[bp+4]
; and the destination pointer, d
les di,[bp+8]
mov cx,[bp+12]
mov bl,10
jmp short dostrncmp
;******
global _strncmp
_strncmp:
call pascal_setup
; Get the source pointer, ss
;mov si,[bp+4]
; and the destination pointer, d
;mov di,[bp+6]
;mov cx,[bp+8]
xchg si,di
dostrncmp:
%endif
jcxz strncmp_retzero
strncmp_loop:
lodsb
scasb
jne strncmp_done
test al,al
loopne strncmp_loop
jmp short strncmp_retzero
%endif
;**********************************************************************
; fmemcmp(BYTE FAR *s1 , BYTE FAR *s2, int count);
global FMEMCMP
FMEMCMP:
call pascal_setup
; the length - preset above
; mov cx, [bp+4]
; Get the source pointer, ss
les di,[bp+6]
; and the destination pointer, d
lds si,[bp+10]
mov bl,10
jmp short domemcmp
;******
; memcmp(BYTE *s1 , BYTE *s2, int count);
global MEMCMP
MEMCMP:
call pascal_setup
; all preset: Get the source pointer, ss
;mov si,[bp+6]
; and the destination pointer, d
;mov di,[bp+8]
;mov cx,[bp+4]
;mov bl,6
xchg si,di
domemcmp:
jcxz strncmp_retzero
repe cmpsb
jne strncmp_done
strncmp_retzero:
xor ax, ax
jmp short strncmp_done2
strncmp_done:
lahf
ror ah,1
%ifdef _INIT
strncmp_done2: jmp short pascal_return
%else
strncmp_done2: jmp pascal_return
%endif
%endif

517
kernel/blockio.c Normal file
View File

@ -0,0 +1,517 @@
/****************************************************************/
/* */
/* blockio.c */
/* DOS-C */
/* */
/* Block cache functions and device driver interface */
/* */
/* Copyright (c) 1995 */
/* Pasquale J. Villani */
/* All Rights Reserved */
/* */
/* This file is part of DOS-C. */
/* */
/* DOS-C is free software; you can redistribute it and/or */
/* modify it under the terms of the GNU General Public License */
/* as published by the Free Software Foundation; either version */
/* 2, or (at your option) any later version. */
/* */
/* DOS-C is distributed in the hope that it will be useful, but */
/* WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See */
/* the GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public */
/* License along with DOS-C; see the file COPYING. If not, */
/* write to the Free Software Foundation, 675 Mass Ave, */
/* Cambridge, MA 02139, USA. */
/* */
/****************************************************************/
#include "portab.h"
#include "globals.h"
#ifdef VERSION_STRINGS
static BYTE *blockioRcsId =
"$Id: blockio.c 1702 2012-02-04 08:46:16Z perditionc $";
#endif
#define b_next(bp) ((struct buffer FAR *)(MK_FP(FP_SEG(bp), bp->b_next)))
#define b_prev(bp) ((struct buffer FAR *)(MK_FP(FP_SEG(bp), bp->b_prev)))
#define bufptr(fbp) ((struct buffer FAR *)(MK_FP(FP_SEG(bp), fbp)))
/************************************************************************/
/* */
/* block cache routines */
/* */
/************************************************************************/
/* #define DISPLAY_GETBLOCK */
STATIC BOOL flush1(struct buffer FAR * bp);
/*
this searches the buffer list for the given disk/block.
returns:
a far pointer to the buffer.
If the buffer is found the UNCACHE bit is not set and else it is set.
new:
upper layer may set UNCACHE attribute
UNCACHE buffers are recycled first.
intended to be used for full sector reads into application buffer
resets UNCACHE upon a "HIT" -- so then this buffer will not be
recycled anymore.
*/
STATIC void move_buffer(struct buffer FAR *bp, size_t firstbp)
{
/* connect bp->b_prev and bp->b_next */
b_next(bp)->b_prev = bp->b_prev;
b_prev(bp)->b_next = bp->b_next;
/* insert bp between firstbp and firstbp->b_prev */
bp->b_prev = bufptr(firstbp)->b_prev;
bp->b_next = firstbp;
b_next(bp)->b_prev = FP_OFF(bp);
b_prev(bp)->b_next = FP_OFF(bp);
}
STATIC struct buffer FAR *searchblock(ULONG blkno, COUNT dsk)
{
int fat_count = 0;
struct buffer FAR *bp;
size_t lastNonFat = 0;
size_t uncacheBuf = 0;
seg bufseg = FP_SEG(firstbuf);
size_t firstbp = FP_OFF(firstbuf);
#ifdef DISPLAY_GETBLOCK
printf("[searchblock %d, blk %ld, buf ", dsk, blkno);
#endif
/* Search through buffers to see if the required block */
/* is already in a buffer */
bp = MK_FP(bufseg, firstbp);
do
{
if ((bp->b_blkno == blkno) &&
(bp->b_flag & BFR_VALID) && (bp->b_unit == dsk))
{
/* found it -- rearrange LRU links */
#ifdef DISPLAY_GETBLOCK
printf("HIT %04x:%04x]\n", FP_SEG(bp), FP_OFF(bp));
#endif
bp->b_flag &= ~BFR_UNCACHE; /* reset uncache attribute */
if (FP_OFF(bp) != firstbp)
{
*(UWORD *)&firstbuf = FP_OFF(bp);
move_buffer(bp, firstbp);
}
return bp;
}
if (bp->b_flag & BFR_UNCACHE)
uncacheBuf = FP_OFF(bp);
if (bp->b_flag & BFR_FAT)
fat_count++;
else
lastNonFat = FP_OFF(bp);
bp = b_next(bp);
} while (FP_OFF(bp) != firstbp);
/*
now take either the last buffer in chain (not used recently)
or, if we are low on FAT buffers, the last non FAT buffer
*/
if (uncacheBuf)
{
bp = bufptr(uncacheBuf);
}
else if (bp->b_flag & BFR_FAT && fat_count < 3 && lastNonFat)
{
bp = bufptr(lastNonFat);
}
else
{
bp = b_prev(bufptr(firstbp));
}
bp->b_flag |= BFR_UNCACHE; /* set uncache attribute */
#ifdef DISPLAY_GETBLOCK
printf("MISS, replace %04x:%04x]\n", FP_SEG(bp), FP_OFF(bp));
#endif
if (FP_OFF(bp) != firstbp) /* move to front */
{
move_buffer(bp, firstbp);
*(UWORD *)&firstbuf = FP_OFF(bp);
}
return bp;
}
BOOL DeleteBlockInBufferCache(ULONG blknolow, ULONG blknohigh, COUNT dsk, int mode)
{
struct buffer FAR *bp = firstbuf;
/* Search through buffers to see if the required block */
/* is already in a buffer */
do
{
if (blknolow <= bp->b_blkno &&
bp->b_blkno <= blknohigh &&
(bp->b_flag & BFR_VALID) && (bp->b_unit == dsk))
{
if (mode == XFR_READ)
flush1(bp);
else
bp->b_flag = 0;
}
bp = b_next(bp);
}
while (FP_OFF(bp) != FP_OFF(firstbuf));
return FALSE;
}
#if TOM
void dumpBufferCache(void)
{
struct buffer FAR *bp = firstbuf;
int printed = 0;
/* Search through buffers to see if the required block */
/* is already in a buffer */
do
{
printf("%8lx %02x ", bp->b_blkno, bp->b_flag);
if (++printed % 6 == 0)
printf("\n");
bp = b_next(bp);
}
while (FP_OFF(bp) != FP_OFF(firstbuf));
printf("\n");
}
#endif
/* */
/* Return the address of a buffer structure containing the */
/* requested block. */
/* if overwrite is set, then no need to read first */
/* */
/* returns: */
/* requested block with data */
/* failure: */
/* returns NULL */
/* */
struct buffer FAR *getblk(ULONG blkno, COUNT dsk, BOOL overwrite)
{
/* Search through buffers to see if the required block */
/* is already in a buffer */
struct buffer FAR *bp = searchblock(blkno, dsk);
if (!(bp->b_flag & BFR_UNCACHE))
{
return bp;
}
/* The block we need is not in a buffer, we must make a buffer */
/* available, and fill it with the desired block */
/* take the buffer that lbp points to and flush it, then read new block. */
if (!flush1(bp))
return NULL;
/* Fill the indicated disk buffer with the current track and sector */
if (!overwrite && dskxfer(dsk, blkno, bp->b_buffer, 1, DSKREAD))
{
return NULL;
}
bp->b_flag = BFR_VALID | BFR_DATA;
bp->b_unit = dsk;
bp->b_blkno = blkno;
return bp;
}
/* */
/* Mark all buffers for a disk as not valid */
/* */
VOID setinvld(REG COUNT dsk)
{
struct buffer FAR *bp = firstbuf;
do
{
if (bp->b_unit == dsk)
bp->b_flag = 0;
bp = b_next(bp);
}
while (FP_OFF(bp) != FP_OFF(firstbuf));
}
/* Check if there is at least one dirty buffer */
/* */
BOOL dirty_buffers(REG COUNT dsk)
{
struct buffer FAR *bp = firstbuf;
do
{
if (bp->b_unit == dsk &&
(bp->b_flag & (BFR_VALID | BFR_DIRTY)) == (BFR_VALID | BFR_DIRTY))
return TRUE;
bp = b_next(bp);
}
while (FP_OFF(bp) != FP_OFF(firstbuf));
return FALSE;
}
/* */
/* */
/* Flush all buffers for a disk */
/* */
/* returns: */
/* TRUE on success */
/* */
BOOL flush_buffers(REG COUNT dsk)
{
struct buffer FAR *bp = firstbuf;
REG BOOL ok = TRUE;
bp = firstbuf;
do
{
if (bp->b_unit == dsk)
if (!flush1(bp))
ok = FALSE;
bp = b_next(bp);
}
while (FP_OFF(bp) != FP_OFF(firstbuf));
return ok;
}
/* */
/* Write one disk buffer */
/* */
STATIC BOOL flush1(struct buffer FAR * bp)
{
BOOL ok = TRUE;
if ((bp->b_flag & (BFR_VALID | BFR_DIRTY)) == (BFR_VALID | BFR_DIRTY))
{
#ifdef WITHFAT32
ULONG b_offset = 0;
#else
UWORD b_offset = 0;
#endif
UBYTE b_copies = 1;
ULONG blkno = bp->b_blkno;
if (bp->b_flag & BFR_FAT)
{
b_copies = bp->b_copies;
b_offset = bp->b_offset;
#ifdef WITHFAT32
if (b_offset == 0) /* FAT32 FS */
b_offset = bp->b_dpbp->dpb_xfatsize;
#endif
}
while (b_copies--)
{
if (dskxfer(bp->b_unit, blkno, bp->b_buffer, 1, DSKWRITE))
ok = FALSE;
blkno += b_offset;
}
}
bp->b_flag &= ~BFR_DIRTY; /* even if error, mark not dirty */
if (!ok) /* otherwise system has trouble */
bp->b_flag &= ~BFR_VALID; /* continuing. */
return ok;
}
/* */
/* Write all disk buffers */
/* */
BOOL flush(void)
{
REG struct buffer FAR *bp = firstbuf;
REG BOOL ok;
ok = TRUE;
do
{
if (!flush1(bp))
ok = FALSE;
bp->b_flag &= ~BFR_VALID;
bp = b_next(bp);
}
while (FP_OFF(bp) != FP_OFF(firstbuf));
network_redirector(REM_FLUSHALL);
return (ok);
}
/************************************************************************/
/* */
/* Device Driver Interface Functions */
/* */
/************************************************************************/
/* */
/* Transfer one or more blocks to/from disk */
/* */
UWORD dskxfer(COUNT dsk, ULONG blkno, VOID FAR * buf, UWORD numblocks,
COUNT mode)
{
register struct dpb FAR *dpbp = get_dpb(dsk);
if (dpbp == NULL)
{
return 0x0201; /* illegal command */
}
#if TOM
#define KeyboardShiftState() (*(BYTE FAR *)(MK_FP(0x40,0x17)))
if (KeyboardShiftState() & 0x01)
{
printf("dskxfer:%s %x - %lx %u\n", mode == DSKWRITE ? "write" : "read",
dsk, blkno, numblocks);
if ((KeyboardShiftState() & 0x03) == 3)
dumpBufferCache();
}
#endif
for (;;)
{
IoReqHdr.r_length = sizeof(request);
IoReqHdr.r_unit = dpbp->dpb_subunit;
switch (mode)
{
case DSKWRITE:
if (verify_ena)
{
IoReqHdr.r_command = C_OUTVFY;
break;
}
/* else fall through */
case DSKWRITEINT26:
IoReqHdr.r_command = C_OUTPUT;
break;
case DSKREADINT25:
case DSKREAD:
IoReqHdr.r_command = C_INPUT;
break;
default:
return 0x0100; /* illegal command */
}
IoReqHdr.r_status = 0;
IoReqHdr.r_meddesc = dpbp->dpb_mdb;
IoReqHdr.r_count = numblocks;
if ((dpbp->dpb_device->dh_attr & ATTR_HUGE) || blkno >= MAXSHORT)
{
IoReqHdr.r_start = HUGECOUNT;
IoReqHdr.r_huge = blkno;
}
else
IoReqHdr.r_start = (UWORD)blkno;
/*
* Some drivers normalise transfer address so HMA transfers are disastrous!
* Then transfer block through xferbuf (DiskTransferBuffer doesn't work!)
* (But this won't work for multi-block HMA transfers... are there any?)
*/
if (FP_SEG(buf) >= 0xa000 && numblocks == 1 && bufloc != LOC_CONV)
{
IoReqHdr.r_trans = deblock_buf;
if (mode == DSKWRITE)
fmemcpy(deblock_buf, buf, dpbp->dpb_secsize);
execrh((request FAR *) & IoReqHdr, dpbp->dpb_device);
if (mode == DSKREAD)
fmemcpy(buf, deblock_buf, dpbp->dpb_secsize);
}
else
{
IoReqHdr.r_trans = (BYTE FAR *) buf;
execrh((request FAR *) & IoReqHdr, dpbp->dpb_device);
}
if ((IoReqHdr.r_status & (S_ERROR | S_DONE)) == S_DONE)
break;
/* INT25/26 (_SEEMS_ TO) return immediately with 0x8002,
if drive is not online,...
normal operations (DIR) wait for ABORT/RETRY
other condition codes not tested
*/
if (mode >= DSKWRITEINT26)
return (IoReqHdr.r_status);
loop:
switch (block_error(&IoReqHdr, dpbp->dpb_unit, dpbp->dpb_device, mode))
{
case ABORT:
case FAIL:
return (IoReqHdr.r_status);
case RETRY:
continue;
case CONTINUE:
break;
default:
goto loop;
}
break;
} /* retry loop */
/* *** Changed 9/4/00 BER */
return 0; /* Success! Return 0 for a successful operation. */
/* End of change */
}
/*
this removes any (additionally allocated) buffers
from the HMA buffer chain, because they get allocated to the 'user'
*/
void AllocateHMASpace (size_t lowbuffer, size_t highbuffer)
{
REG struct buffer FAR *bp = firstbuf;
int n;
if (FP_SEG(bp) != 0xffff)
return;
n = LoL_nbuffers;
do
{
/* check if buffer intersects with requested area */
if (FP_OFF(bp) < highbuffer && FP_OFF(bp+1) > lowbuffer)
{
flush1(bp);
/* unlink bp from buffer chain */
b_prev(bp)->b_next = bp->b_next;
b_next(bp)->b_prev = bp->b_prev;
if (FP_OFF(bp) == FP_OFF(firstbuf))
firstbuf = b_next(bp);
LoL_nbuffers--;
}
bp = b_next(bp);
}
while (--n);
}

93
kernel/break.c Normal file
View File

@ -0,0 +1,93 @@
/****************************************************************/
/* */
/* break.c */
/* FreeDOS */
/* */
/* Control Break detection and handling */
/* */
/* Copyright (c) 1999 */
/* Steffen Kaiser */
/* All Rights Reserved */
/* */
/* This file is part of DOS-C. */
/* */
/* DOS-C is free software; you can redistribute it and/or */
/* modify it under the terms of the GNU General Public License */
/* as published by the Free Software Foundation; either version */
/* 2, or (at your option) any later version. */
/* */
/* DOS-C is distributed in the hope that it will be useful, but */
/* WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See */
/* the GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public */
/* License along with DOS-C; see the file COPYING. If not, */
/* write to the Free Software Foundation, 675 Mass Ave, */
/* Cambridge, MA 02139, USA. */
/****************************************************************/
#include "portab.h"
#include "globals.h"
#include "proto.h"
#ifdef VERSION_STRINGS
static BYTE *RcsId =
"$Id: break.c 885 2004-04-14 15:40:51Z bartoldeman $";
#endif
#define CB_FLG *(UBYTE FAR*)MK_FP(0x0, 0x471)
#define CB_MSK 0x80
/* Check for ^Break/^C.
* Three sources are available:
* 1) flag at 40:71 bit 7
* 2) syscon stream (usually CON:)
* 3) i/o stream (if unequal to syscon, e.g. AUX)
*/
unsigned char ctrl_break_pressed(void)
{
return CB_FLG & CB_MSK;
}
unsigned char check_handle_break(struct dhdr FAR **pdev)
{
unsigned char c = CTL_C;
if (!ctrl_break_pressed())
c = (unsigned char)ndread(&syscon);
if (c != CTL_C && *pdev != syscon)
c = (unsigned char)ndread(pdev);
if (c == CTL_C)
handle_break(pdev, -1);
return c;
}
/*
* Handles a ^Break state
*
* Actions:
* 1) clear the ^Break flag
* 2) clear the STDIN stream
* 3) echo ^C to sft_out or pdev if sft_out==-1
* 4) decrease the InDOS flag as the kernel drops back to user space
* 5) invoke INT-23 and never come back
*/
void handle_break(struct dhdr FAR **pdev, int sft_out)
{
char *buf = "^C\r\n";
CB_FLG &= ~CB_MSK; /* reset the ^Break flag */
con_flush(pdev);
if (sft_out == -1)
cooked_write(pdev, 4, buf);
else
DosRWSft(sft_out, 4, buf, XFR_FORCE_WRITE);
if (!ErrorMode) /* within int21_handler, InDOS is not incremented */
if (InDOS)
--InDOS; /* fail-safe */
spawn_int23(); /* invoke user INT-23 and never come back */
}

548
kernel/chario.c Normal file
View File

@ -0,0 +1,548 @@
/****************************************************************/
/* */
/* chario.c */
/* DOS-C */
/* */
/* Character device functions and device driver interface */
/* */
/* Copyright (c) 1994 */
/* Pasquale J. Villani */
/* All Rights Reserved */
/* */
/* This file is part of DOS-C. */
/* */
/* DOS-C is free software; you can redistribute it and/or */
/* modify it under the terms of the GNU General Public License */
/* as published by the Free Software Foundation; either version */
/* 2, or (at your option) any later version. */
/* */
/* DOS-C is distributed in the hope that it will be useful, but */
/* WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See */
/* the GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public */
/* License along with DOS-C; see the file COPYING. If not, */
/* write to the Free Software Foundation, 675 Mass Ave, */
/* Cambridge, MA 02139, USA. */
/* */
/****************************************************************/
#include "portab.h"
#ifdef VERSION_STRINGS
static BYTE *charioRcsId =
"$Id: chario.c 1413 2009-06-01 13:41:03Z bartoldeman $";
#endif
#include "globals.h"
STATIC int CharRequest(struct dhdr FAR **pdev, unsigned command)
{
struct dhdr FAR *dev = *pdev;
CharReqHdr.r_command = command;
CharReqHdr.r_unit = 0;
CharReqHdr.r_status = 0;
CharReqHdr.r_length = sizeof(request);
execrh(&CharReqHdr, dev);
if (CharReqHdr.r_status & S_ERROR)
{
for (;;) {
switch (char_error(&CharReqHdr, dev))
{
case ABORT:
case FAIL:
return DE_INVLDACC;
case CONTINUE:
CharReqHdr.r_count = 0;
return 0;
case RETRY:
return 1;
}
}
}
return SUCCESS;
}
long BinaryCharIO(struct dhdr FAR **pdev, size_t n, void FAR * bp,
unsigned command)
{
int err;
do
{
CharReqHdr.r_count = n;
CharReqHdr.r_trans = bp;
err = CharRequest(pdev, command);
} while (err == 1);
return err == SUCCESS ? (long)CharReqHdr.r_count : err;
}
STATIC int CharIO(struct dhdr FAR **pdev, unsigned char ch, unsigned command)
{
int err = (int)BinaryCharIO(pdev, 1, &ch, command);
if (err == 0)
return 256;
if (err < 0)
return err;
return ch;
}
/* STATE FUNCTIONS */
STATIC void CharCmd(struct dhdr FAR **pdev, unsigned command)
{
while (CharRequest(pdev, command) == 1);
}
STATIC int Busy(struct dhdr FAR **pdev)
{
CharCmd(pdev, C_ISTAT);
return CharReqHdr.r_status & S_BUSY;
}
void con_flush(struct dhdr FAR **pdev)
{
CharCmd(pdev, C_IFLUSH);
}
/* if the sft is invalid, then we just monitor syscon */
struct dhdr FAR *sft_to_dev(sft FAR *s)
{
if (FP_OFF(s) == (size_t) -1)
return syscon;
if (s->sft_flags & SFT_FDEVICE)
return s->sft_dev;
return NULL;
}
int StdinBusy(void)
{
sft FAR *s = get_sft(STDIN);
struct dhdr FAR *dev = sft_to_dev(s);
if (dev)
return Busy(&dev);
return s->sft_posit >= s->sft_size;
}
/* get character from the console - this is how DOS gets
CTL_C/CTL_S/CTL_P when outputting */
int ndread(struct dhdr FAR **pdev)
{
CharCmd(pdev, C_NDREAD);
if (CharReqHdr.r_status & S_BUSY)
return -1;
return CharReqHdr.r_ndbyte;
}
/* OUTPUT FUNCTIONS */
#ifdef __WATCOMC__
void fast_put_char(char c);
#pragma aux fast_put_char = "int 29h" parm[al] modify exact [bx]
#else
/* writes a character in raw mode using int29 for speed */
STATIC void fast_put_char(unsigned char chr)
{
#if defined(__TURBOC__)
_AL = chr;
__int__(0x29);
#elif defined(I86)
asm
{
mov al, byte ptr chr;
int 0x29;
}
#endif
}
#endif
void update_scr_pos(unsigned char c, unsigned char count)
{
unsigned char scrpos = scr_pos;
if (c == CR)
scrpos = 0;
else if (c == BS) {
if (scrpos > 0)
scrpos--;
} else if (c != LF && c != BELL) {
scrpos += count;
}
scr_pos = scrpos;
}
STATIC int raw_get_char(struct dhdr FAR **pdev, BOOL check_break);
long cooked_write(struct dhdr FAR **pdev, size_t n, char FAR *bp)
{
size_t xfer;
/* bit 7 means fastcon; low 5 bits count number of characters */
unsigned char fast_counter = ((*pdev)->dh_attr & ATTR_FASTCON) << 3;
for (xfer = 0; xfer < n; xfer++)
{
int err;
unsigned char count = 1, c = *bp++;
if (c == CTL_Z)
break;
/* write a character in cooked mode; maybe with printer echo;
handles TAB expansion */
if (c == HT) {
count = 8 - (scr_pos & 7);
c = ' ';
}
update_scr_pos(c, count);
do {
/* if not fast then < 0x80; always check
otherwise check every 32 characters */
if (fast_counter <= 0x80 && check_handle_break(pdev) == CTL_S)
raw_get_char(pdev, TRUE); /* Test for hold char and ctl_c */
fast_counter++;
fast_counter &= 0x9f;
if (PrinterEcho)
DosWrite(STDPRN, 1, &c);
if (fast_counter & 0x80)
fast_put_char(c);
else
{
err = CharIO(pdev, c, C_OUTPUT);
if (err < 0)
return err;
}
} while (--count != 0);
}
return xfer;
}
/* writes character for disk file or device */
void write_char(int c, int sft_idx)
{
unsigned char ch = (unsigned char)c;
DosRWSft(sft_idx, 1, &ch, XFR_FORCE_WRITE);
}
void write_char_stdout(int c)
{
unsigned char count = 1;
unsigned flags = get_sft(STDOUT)->sft_flags;
/* ah=2, ah=9 should expand tabs even for raw devices and disk files */
if ((flags & (SFT_FDEVICE|SFT_FBINARY)) != SFT_FDEVICE)
{
if (c == HT) {
count = 8 - (scr_pos & 7);
c = ' ';
}
/* for raw CONOUT devices already updated in dosfns.c */
if ((flags & (SFT_FDEVICE|SFT_FCONOUT)) != (SFT_FDEVICE|SFT_FCONOUT))
update_scr_pos(c, count);
}
do {
write_char(c, get_sft_idx(STDOUT));
} while (--count != 0);
}
#define iscntrl(c) ((unsigned char)(c) < ' ')
/* this is for handling things like ^C, mostly used in echoed input */
STATIC int echo_char(int c, int sft_idx)
{
int out = c;
if (iscntrl(c) && c != HT && c != LF && c != CR)
{
write_char('^', sft_idx);
out += '@';
}
write_char(out, sft_idx);
return c;
}
STATIC void destr_bs(int sft_idx)
{
write_char(BS, sft_idx);
write_char(' ', sft_idx);
write_char(BS, sft_idx);
}
/* READ FUNCTIONS */
long cooked_read(struct dhdr FAR **pdev, size_t n, char FAR *bp)
{
unsigned xfer = 0;
int c;
while(n--)
{
c = raw_get_char(pdev, TRUE);
if (c < 0)
return c;
if (c == 256)
break;
*bp++ = c;
xfer++;
if ((unsigned char)c == CTL_Z)
break;
}
return xfer;
}
STATIC unsigned char read_char_sft_dev(int sft_in, int sft_out,
struct dhdr FAR **pdev,
BOOL check_break)
{
unsigned char c;
if (*pdev)
{
FOREVER
{
if (ctrl_break_pressed())
{
c = CTL_C;
break;
}
if (!Busy(pdev))
{
c = CharIO(pdev, 0, C_INPUT);
break;
}
if (check_break && *pdev != syscon)
check_handle_break(&syscon);
/* the idle int is only safe if we're using the character stack */
if (user_r->AH < 0xd)
DosIdle_int();
}
}
else
DosRWSft(sft_in, 1, &c, XFR_READ);
/* check for break or stop on sft_in, echo to sft_out */
if (check_break && (c == CTL_C || c == CTL_S))
{
if (c == CTL_S)
c = read_char_sft_dev(sft_in, sft_out, pdev, FALSE);
if (c == CTL_C)
handle_break(pdev, sft_out);
/* DOS oddity: if you press ^S somekey ^C then ^C does not break */
c = read_char(sft_in, sft_out, FALSE);
}
return c;
}
STATIC int raw_get_char(struct dhdr FAR **pdev, BOOL check_break)
{
return read_char_sft_dev(-1, -1, pdev, check_break);
}
unsigned char read_char(int sft_in, int sft_out, BOOL check_break)
{
struct dhdr FAR *dev = sft_to_dev(idx_to_sft(sft_in));
return read_char_sft_dev(sft_in, sft_out, &dev, check_break);
}
STATIC unsigned char read_char_check_break(int sft_in, int sft_out)
{
return read_char(sft_in, sft_out, TRUE);
}
unsigned char read_char_stdin(BOOL check_break)
{
return read_char(get_sft_idx(STDIN), get_sft_idx(STDOUT), check_break);
}
/* reads a line (buffered, called by int21/ah=0ah, 3fh) */
void read_line(int sft_in, int sft_out, keyboard FAR * kp)
{
unsigned c;
unsigned cu_pos = scr_pos;
unsigned count = 0, stored_pos = 0;
unsigned size = kp->kb_size, stored_size = kp->kb_count;
BOOL insert = FALSE, first = TRUE;
if (size == 0)
return;
/* the stored line is invalid unless it ends with a CR */
if (kp->kb_buf[stored_size] != CR)
stored_size = 0;
do
{
unsigned new_pos = stored_size;
c = read_char_check_break(sft_in, sft_out);
if (c == 0)
c = (unsigned)read_char_check_break(sft_in, sft_out) << 8;
switch (c)
{
case LF:
/* show LF if it's not the first character. Never store it */
if (!first)
{
write_char(CR, sft_out);
write_char(LF, sft_out);
}
break;
case CTL_F:
break;
case RIGHT:
case F1:
if (stored_pos < stored_size && count < size - 1)
local_buffer[count++] = echo_char(kp->kb_buf[stored_pos++], sft_out);
break;
case F2:
case F4:
/* insert/delete up to character c */
{
unsigned char c2 = read_char_check_break(sft_in, sft_out);
new_pos = stored_pos;
if (c2 == 0)
{
read_char_check_break(sft_in, sft_out);
}
else
{
char FAR *sp = fmemchr(&kp->kb_buf[stored_pos],
c2, stored_size - stored_pos);
if (sp != NULL)
new_pos = (FP_OFF(sp) - FP_OFF(&kp->kb_buf[stored_pos])) + 1;
}
}
/* fall through */
case F3:
if (c != F4) /* not delete */
{
while (stored_pos < new_pos && count < size - 1)
local_buffer[count++] = echo_char(kp->kb_buf[stored_pos++], sft_out);
}
stored_pos = new_pos;
break;
case F5:
fmemcpy(kp->kb_buf, local_buffer, count);
stored_size = count;
write_char('@', sft_out);
goto start_new_line;
case INS:
insert = !insert;
break;
case DEL:
stored_pos++;
break;
case LEFT:
case CTL_BS:
case BS:
if (count > 0)
{
unsigned new_pos;
char c2 = local_buffer[--count];
if (c2 == HT)
{
unsigned i;
new_pos = cu_pos;
for (i = 0; i < count; i++)
{
if (local_buffer[i] == HT)
new_pos = (new_pos + 8) & ~7;
else if (iscntrl(local_buffer[i]))
new_pos += 2;
else
new_pos++;
}
do
destr_bs(sft_out);
while (scr_pos > new_pos);
}
else
{
if (iscntrl(c2))
destr_bs(sft_out);
destr_bs(sft_out);
}
}
if (stored_pos > 0)
stored_pos--;
break;
case ESC:
write_char('\\', sft_out);
start_new_line:
write_char(CR, sft_out);
write_char(LF, sft_out);
for (count = 0; count < cu_pos; count++)
write_char(' ', sft_out);
count = 0;
stored_pos = 0;
insert = FALSE;
break;
case F6:
c = CTL_Z;
/* fall through */
default:
if (count < size - 1 || c == CR)
local_buffer[count++] = echo_char(c, sft_out);
else
write_char(BELL, sft_out);
if (stored_pos < stored_size && !insert)
stored_pos++;
break;
}
first = FALSE;
} while (c != CR);
fmemcpy(kp->kb_buf, local_buffer, count);
/* if local_buffer overflows into the CON default buffer we
must invalidate it */
if (count > LINEBUFSIZECON)
kb_buf.kb_size = 0;
/* kb_count does not include the final CR */
kp->kb_count = count - 1;
}
/* called by handle func READ (int21/ah=3f) */
size_t read_line_handle(int sft_idx, size_t n, char FAR * bp)
{
size_t chars_left;
if (inputptr == NULL)
{
/* can we reuse kb_buf or was it overwritten? */
if (kb_buf.kb_size != LINEBUFSIZECON)
{
kb_buf.kb_count = 0;
kb_buf.kb_size = LINEBUFSIZECON;
}
read_line(sft_idx, sft_idx, &kb_buf);
kb_buf.kb_buf[kb_buf.kb_count + 1] = echo_char(LF, sft_idx);
inputptr = kb_buf.kb_buf;
if (*inputptr == CTL_Z)
{
inputptr = NULL;
return 0;
}
}
chars_left = &kb_buf.kb_buf[kb_buf.kb_count + 2] - inputptr;
if (n > chars_left)
n = chars_left;
fmemcpy(bp, inputptr, n);
inputptr += n;
if (n == chars_left)
inputptr = NULL;
return n;
}

2568
kernel/config.c Normal file

File diff suppressed because it is too large Load Diff

46
kernel/config.h Normal file
View File

@ -0,0 +1,46 @@
/****************************************************************/
/* */
/* config.h */
/* DOS-C */
/* */
/* Global data structures and declarations */
/* */
/* Copyright (c) 2000 */
/* Steffen Kaiser */
/* All Rights Reserved */
/* */
/* This file is part of DOS-C. */
/* */
/* DOS-C is free software; you can redistribute it and/or */
/* modify it under the terms of the GNU General Public License */
/* as published by the Free Software Foundation; either version */
/* 2, or (at your option) any later version. */
/* */
/* DOS-C is distributed in the hope that it will be useful, but */
/* WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See */
/* the GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public */
/* License along with DOS-C; see the file COPYING. If not, */
/* write to the Free Software Foundation, 675 Mass Ave, */
/* Cambridge, MA 02139, USA. */
/****************************************************************/
struct config { /* Configuration variables */
UBYTE cfgDosDataUmb;
BYTE cfgBuffers; /* number of buffers in the system */
UBYTE cfgFiles; /* number of available files */
UBYTE cfgFilesHigh;
UBYTE cfgFcbs; /* number of available FCBs */
UBYTE cfgProtFcbs; /* number of protected FCBs */
BYTE *cfgInit; /* init of command.com */
BYTE *cfgInitTail; /* command.com's tail */
UBYTE cfgLastdrive; /* last drive */
UBYTE cfgLastdriveHigh;
BYTE cfgStacks; /* number of stacks */
BYTE cfgStacksHigh;
UWORD cfgStackSize; /* stacks size for each stack */
UBYTE cfgP_0_startmode; /* load command.com high or not */
unsigned ebda2move; /* value for switches=/E:nnnn */
};

254
kernel/console.asm Normal file
View File

@ -0,0 +1,254 @@
;
; File:
; console.asm
; Description:
; Console device driver
;
; Copyright (c) 1998
; Pasquale J. Villani
; All Rights Reserved
;
; This file is part of DOS-C.
;
; DOS-C is free software; you can redistribute it and/or
; modify it under the terms of the GNU General Public License
; as published by the Free Software Foundation; either version
; 2, or (at your option) any later version.
;
; DOS-C is distributed in the hope that it will be useful, but
; WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
; the GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public
; License along with DOS-C; see the file COPYING. If not,
; write to the Free Software Foundation, 675 Mass Ave,
; Cambridge, MA 02139, USA.
;
; $Header$
;
%include "io.inc"
segment _IO_FIXED_DATA
global ConTable
ConTable db 0Ah
dw ConInit
dw _IOExit
dw _IOExit
dw _IOCommandError
dw ConRead
dw CommonNdRdExit
dw CommonNdRdExit
dw ConInpFlush
dw ConWrite
dw ConWrite
dw _IOExit
CTL_PRT_SCREEN equ 7200h
CTL_P equ 10h
segment _LOWTEXT
uScanCode db 0 ; Scan code for con: device
global _kbdType
_kbdType db 0 ; 00 for 84key, 10h for 102key
global ConInit
ConInit:
xor ax,ax
mov ds,ax
mov al,[496h]
and al,10h
mov byte[cs:_kbdType],al ; enhanced keyboard if bit 4 set
jmp _IOExit
;
; Name:
; ConRead
;
; Function:
; Read to address in es:di characters from the keyboard. Cx contains
; a count of how many characters are to be transferred.
;
; Description:
; Calls KbdRdChar to read the characters. Destroys ax.
;
global ConRead
ConRead:
jcxz ConRead2 ; Exit if read of zero
ConRead1:
call KbdRdChar ; Get a char from kbd in al
stosb ; Store al to es:[di]
loop ConRead1 ; Loop until all are read
ConRead2:
jmp _IOExit
readkey:
mov ah,[cs:_kbdType]
int 16h
checke0: cmp al,0xe0 ; must check for 0xe0 scan code
jne .ret
or ah,ah ; check for Greek alpha
jz .ret
mov al,0 ; otherwise destroy the 0xe0
.ret: retn
;
; Name:
; KbdRdChar
;
; Function:
; Read a character from the keyboard.
;
; Description:
; This subroutine reads a character from the keyboard. It also handles
; a couple of special functions.
; It converts ctrl-printscreen to a control-P.
; It also accounts for extended scan codes by saving off
; the high byte of the return and returning it if it was non-zero on
; the previous read.
;
global KbdRdChar
KbdRdChar:
xor ax,ax ; Zero the scratch register
xchg [cs:uScanCode],al ; and swap with scan code
; now AL is set if previous key was extended,
; and previous is erased in any case
or al,al ; Test to see if it was set
jnz KbdRdRtn ; Exit if it was, returning it
call readkey ; get keybd char in al, ah=scan
or ax,ax ; Zero ?
jz KbdRdChar ; Loop if it is
cmp ax,CTL_PRT_SCREEN ; Ctrl-Print screen?
jne KbdRd1 ; Nope, keep going
mov al,CTL_P ; Yep, make it ^P
KbdRd1:
or al,al ; Extended key?
jnz KbdRdRtn ; Nope, just exit
mov [cs:uScanCode],ah ; Yep, save the scan code
KbdRdRtn:
retn
;
; Name:
; CommonNdRdExit
;
; Function:
; Checks the keyboard input buffer.
;
; Description:
; Calls int 16 (get status). Sets Busy-Flag in status field. Destroys ax.
;
global CommonNdRdExit
CommonNdRdExit: ; *** tell if key waiting and return its ASCII if yes
mov al,[cs:uScanCode] ; Test for last scan code
; now AL is set if previous key was extended,
or al,al ; Was it zero ?
jnz ConNdRd2 ; Jump if there's a char waiting
mov ah,1
add ah,[cs:_kbdType]
int 16h ; Get status, if zf=0 al=char
jz ConNdRd4 ; Jump if no char available
call checke0 ; check for e0 scancode
or ax,ax ; Zero ?
jnz ConNdRd1 ; Jump if not zero
call readkey
jmp short CommonNdRdExit
; if char was there but 0, fetch and retry...
; (why do we check uScanCode here?)
ConNdRd1:
cmp ax,CTL_PRT_SCREEN ; Was ctl+prntscrn key pressed?
jne ConNdRd2 ; Jump if not
mov al,CTL_P
ConNdRd2:
lds bx,[cs:_ReqPktPtr] ; Set the status
cmp byte[bx+2],6 ; input status call?
je ConNdRd3
mov [bx+0Dh],al ; return the ASCII of that key
ConNdRd3:
jmp _IOExit
ConNdRd4:
jmp _IODone
global ConInpFlush
ConInpFlush: ; *** flush that keyboard queue
call KbdInpChar ; get all available keys
jmp _IOExit ; do not even remember the last one
KbdInpChar: ; *** get ??00 or the last waiting key after flushing the queue
xor ax,ax
mov byte [cs:uScanCode],al
KbdInpCh1:
mov ah,1
add ah,[cs:_kbdType]
int 16h ; get status, if zf=0 al=char
jz KbdInpRtnZero ; Jump if zero
; returns 0 or the last key that was waiting in AL
call readkey
jmp short KbdInpCh1
; just read any key that is waiting, then check if
; more keys are waiting. if not, return AL of this
; key (which is its ASCII). AH (scan) discarded!
KbdInpRtnZero: mov ah,1 ; if anybody wants "1 if no key was waiting"!
KbdInpRtn:
retn
global ConWrite
ConWrite:
jcxz ConNdRd3 ; Exit if nothing to write
ConWr1:
mov al,[es:di]
inc di
int 29h ; Do fast output call
loop ConWr1 ; Loop if more to output
jmp _IOExit
CBreak:
mov byte [cs:uScanCode],3 ; Put a ^C into the buffer
IntRetn:
iret
; global _cso
;_cso
; push bp
; mov bp,sp
; push ax
; mov ax,[bp+4]
; int 29h
; pop ax
; pop bp
; retn
global _int29_handler
_int29_handler:
push ax
push si
push di
push bp
push bx
mov ah,0Eh
mov bx,7
int 10h ; write char al, teletype mode
pop bx
pop bp
pop di
pop si
pop ax
iret

5108
kernel/country.asm Normal file

File diff suppressed because it is too large Load Diff

74
kernel/cpu.asm Normal file
View File

@ -0,0 +1,74 @@
; File:
; cpu.asm
; Description:
; Query basic CPU running on
;
; DOS-C
; Copyright (c) 2012
; FreeDOS
; All Rights Reserved
;
; This file is part of DOS-C.
;
; DOS-C is free software; you can redistribute it and/or
; modify it under the terms of the GNU General Public License
; as published by the Free Software Foundation; either version
; 2, or (at your option) any later version.
;
; DOS-C is distributed in the hope that it will be useful, but
; WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
; the GNU General Public License for more details.
;
;
%include "segs.inc"
segment INIT_TEXT
CPU 386
;*********************************************************************
;
; UWORD query_cpu() based on Eric Auer's public domain cpulevel.asm
; input: none
; output: ax = cpu, 0=8086/8088, 1=186/188, 2=286, 3=386+
global _query_cpu
_query_cpu:
; save registers, assumes enough space on stack & valid stack frame setup
;push ax - no need to save, return value saved here
push bx
push cx
pushf ; save flags
; begin check, assume x86 unless later family detected
xor bx, bx ; 808x or 186 highest detected family stored in bx
push bx
popf ; try to clear all flag bits
pushf ; copy flags to ax so we can test if clear succeeded
pop ax
and ax, 0f000h
cmp ax, 0f000h
jnz is286 ; no the 4 msb stuck set to 1, so is a 808x or 8018x
mov ax,1 ; determine if 8086 or 186
mov cl,64 ; try to shift further than size of ax
shr ax,cl
or ax,ax
jz is086 ; 186 ignores the upper bits of cl
mov bx, 1 ; 186: above 808x, below 286
is086: jmp short cleanup
is286: mov bx, 2 ; at least 286
mov ax, 0f000h
push ax
popf ; try to set 4 msb of flags
pushf ; copy flags to ax so we can test if clear succeeded
pop ax
test ax, 0f000h
jz cleanup ; 4 msb stuck to 0: 80286
mov bx, 3 ; at least 386
cleanup:
mov ax, bx ; return CPU family
popf
pop cx
pop bx
retn

1377
kernel/dosfns.c Normal file

File diff suppressed because it is too large Load Diff

96
kernel/dosidle.asm Normal file
View File

@ -0,0 +1,96 @@
; File:
; DosIdle.asm
; Description:
; Dos Idle Interrupt Call
;
; DOS-C
; Copyright (c) 1995, 1999
; James B. Tabor
; All Rights Reserved
;
; This file is part of DOS-C.
;
; DOS-C is free software; you can redistribute it and/or
; modify it under the terms of the GNU General Public License
; as published by the Free Software Foundation; either version
; 2, or (at your option) any later version.
;
; DOS-C is distributed in the hope that it will be useful, but
; WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
; the GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public
; License along with DOS-C; see the file COPYING. If not,
; write to the Free Software Foundation, 675 Mass Ave,
; Cambridge, MA 02139, USA.
;
;
%include "segs.inc"
PSP_USERSP equ 2eh
PSP_USERSS equ 30h
segment HMA_TEXT
global _DosIdle_int
global _DosIdle_hlt
extern _InDOS:wrt DGROUP
extern _cu_psp:wrt DGROUP
extern _MachineId:wrt DGROUP
extern critical_sp:wrt DGROUP
extern _user_r:wrt DGROUP
; variables as the following are "part of" module inthndlr.c
; because of the define MAIN before include globals.h there!
extern _HaltCpuWhileIdle:wrt DGROUP
extern _DGROUP_:wrt HMA_TEXT
;
_DosIdle_hlt:
push ds
mov ds, [cs:_DGROUP_]
cmp byte [_HaltCpuWhileIdle],1
jb DosId0
pushf
sti
hlt ; save some energy :-)
popf
DosId0: pop ds
retn
;
_DosIdle_int:
call _DosIdle_hlt
push ds
mov ds, [cs:_DGROUP_]
cmp byte [_InDOS],1
ja DosId1
call Do_DosI
DosId1:
pop ds
retn
Do_DosI:
push ax
push es
push word [_MachineId]
push word [_user_r]
push word [_user_r+2]
mov es,word [_cu_psp]
push word [es:PSP_USERSS]
push word [es:PSP_USERSP]
int 28h
mov es,word [_cu_psp]
pop word [es:PSP_USERSP]
pop word [es:PSP_USERSS]
pop word [_user_r+2]
pop word [_user_r]
pop word [_MachineId]
pop es
pop ax
ret
; segment _DATA ; belongs to DGROUP
; whatever db whatever

1088
kernel/dsk.c Normal file

File diff suppressed because it is too large Load Diff

19
kernel/dyndata.h Normal file
View File

@ -0,0 +1,19 @@
/*
DynData.h
declarations for dynamic NEAR data allocations
the DynBuffer must initially be large enough to hold
the PreConfig data.
after the disksystem has been initialized, the kernel is
moveable and Dyn.Buffer resizable, but not before
*/
void far *DynAlloc(char *what, unsigned num, unsigned size);
void far *DynLast(void);
void DynFree(void *ptr);
struct DynS {
unsigned Allocated;
char Buffer[1];
};

98
kernel/dyninit.c Normal file
View File

@ -0,0 +1,98 @@
/*
DYNINIT.C
this serves requests from the INIT modules to
allocate dynamic data.
kernel layout:
00000H 000FFH 00100H PSP PSP
00100H 004E1H 003E2H _TEXT CODE
004E2H 007A7H 002C6H _IO_TEXT CODE
007A8H 008E5H 0013EH _IO_FIXED_DATA CODE
008F0H 0139FH 00AB0H _FIXED_DATA DATA
013A0H 019F3H 00654H _DATA DATA
019F4H 0240DH 00A1AH _BSS BSS
additionally:
DYN_DATA DYN
02610H 0F40EH 0CDFFH HMA_TEXT HMA
FCBs, f_nodes, buffers,...
drivers
0F410H 122DFH 02ED0H INIT_TEXT INIT
122E0H 12AA5H 007C6H ID ID
12AA6H 12CBFH 0021AH IB IB
purpose is to move the HMA_TEXT = resident kernel
around, so that below it - after BSS, there is data
addressable near by the kernel, to hold some arrays
like f_nodes
making f_nodes near saves ~2.150 code in HMA
*/
#include "portab.h"
#include "init-mod.h"
#include "dyndata.h"
#if defined(DEBUG)
#define DebugPrintf(x) printf x
#else
#define DebugPrintf(x)
#endif
/*extern struct DynS FAR Dyn;*/
#ifndef __TURBOC__
#include "init-dat.h"
extern struct DynS DOSFAR ASM Dyn;
#else
extern struct DynS FAR ASM Dyn;
#endif
void far *DynAlloc(char *what, unsigned num, unsigned size)
{
void far *now;
unsigned total = num * size;
struct DynS far *Dynp = MK_FP(FP_SEG(LoL), FP_OFF(&Dyn));
#ifndef DEBUG
UNREFERENCED_PARAMETER(what);
#endif
if ((ULONG) total + Dynp->Allocated > 0xffff)
{
printf("PANIC:Dyn %lu\n", (ULONG) total + Dynp->Allocated);
for (;;) ;
}
DebugPrintf(("DYNDATA:allocating %s - %u * %u bytes, total %u, %u..%u\n",
what, num, size, total, Dynp->Allocated,
Dynp->Allocated + total));
now = (void far *)&Dynp->Buffer[Dynp->Allocated];
fmemset(now, 0, total);
Dynp->Allocated += total;
return now;
}
void DynFree(void *ptr)
{
struct DynS far *Dynp = MK_FP(FP_SEG(LoL), FP_OFF(&Dyn));
Dynp->Allocated = (char *)ptr - (char *)Dynp->Buffer;
}
void FAR * DynLast()
{
struct DynS far *Dynp = MK_FP(FP_SEG(LoL), FP_OFF(&Dyn));
DebugPrintf(("dynamic data end at %p\n",
(void FAR *)(Dynp->Buffer + Dynp->Allocated)));
return Dynp->Buffer + Dynp->Allocated;
}

671
kernel/entry.asm Normal file
View File

@ -0,0 +1,671 @@
;
; File:
; entry.asm
; Description:
; System call entry code
;
; Copyright (c) 1998
; Pasquale J. Villani
; All Rights Reserved
;
; This file is part of DOS-C.
;
; DOS-C is free software; you can redistribute it and/or
; modify it under the terms of the GNU General Public License
; as published by the Free Software Foundation; either version
; 2, or (at your option) any later version.
;
; DOS-C is distributed in the hope that it will be useful, but
; WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
; the GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public
; License along with DOS-C; see the file COPYING. If not,
; write to the Free Software Foundation, 675 Mass Ave,
; Cambridge, MA 02139, USA.
;
; $Id: entry.asm 1701 2012-01-16 22:06:21Z perditionc $
;
%include "segs.inc"
%include "stacks.inc"
segment HMA_TEXT
extern _int21_syscall
extern _int21_service
extern _int2526_handler
extern _error_tos:wrt DGROUP
extern _char_api_tos:wrt DGROUP
extern _disk_api_tos:wrt DGROUP
extern _user_r:wrt DGROUP
extern _ErrorMode:wrt DGROUP
extern _InDOS:wrt DGROUP
extern _cu_psp:wrt DGROUP
extern _MachineId:wrt DGROUP
extern critical_sp:wrt DGROUP
extern int21regs_seg:wrt DGROUP
extern int21regs_off:wrt DGROUP
extern _Int21AX:wrt DGROUP
extern _DGROUP_
global reloc_call_cpm_entry
global reloc_call_int20_handler
global reloc_call_int21_handler
global reloc_call_low_int25_handler
global reloc_call_low_int26_handler
global reloc_call_int27_handler
;
; MS-DOS CP/M style entry point
;
; VOID FAR
; cpm_entry(iregs UserRegs)
;
; For CP/M compatibility allow a program to invoke any DOS API function
; between 0 and 24h by doing a near call to psp:0005h which embeds a far call
; to absolute address 0:00C0h (int vector 30h & 31h) or FFFF:00D0 (hma).
; 0:00C0h contains the jmp instruction to reloc_call_cpm_entry which should
; be duplicated in hma to ensure correct operation with either state of A20 line.
; Note: int 31h is also used for DPMI but only in protected mode.
; Upon entry the stack has a near return offset (desired return address offset)
; and far return seg:offset (desired return segment of PSP, and useless offset
; which if used will return to the data, not code, at offset 0ah after far call
; in psp). We convert it to a normal call and correct the stack to appear same
; as if invoked via an int 21h call including proper return address.
;
reloc_call_cpm_entry:
; Stack is:
; return offset
; psp seg
; 000ah
;
add sp, byte 2 ; remove unneeded far return offset 0ah
pushf ; start setting up int 21h stack
;
; now stack is
; return offset
; psp seg
; flags
;
push bp
mov bp,sp ; set up reference frame
;
; reference frame stack is
; return offset bp + 6
; psp seg bp + 4
; flags bp + 2
; bp <--- bp
;
push ax
mov ax,[2+bp] ; get the flags
xchg ax,[6+bp] ; swap with return address
mov [2+bp],ax
pop ax ; restore working registers
pop bp
;
; Done. Stack is
; flags
; psp seg (alias .COM cs)
; return offset
;
cmp cl,024h ; restrict calls to functions 0-24h
ja cpm_error
mov ah,cl ; get the call # from cl to ah
jmp reloc_call_int21_handler ; do the system call
cpm_error: mov al,0
iret ; cleanup stack and return to caller
;
; interrupt zero divide handler:
; print a message 'Interrupt divide by zero'
; Terminate the current process
;
; VOID INRPT far
; int20_handler(iregs UserRegs)
;
print_hex: mov cl, 12
hex_loop:
mov ax, dx
shr ax, cl
and al, 0fh
cmp al, 10
sbb al, 69h
das
mov bx, 0070h
mov ah, 0eh
int 10h
sub cl, 4
jae hex_loop
ret
divide_by_zero_message db 0dh,0ah,'Interrupt divide by zero, stack:',0dh,0ah,0
global reloc_call_int0_handler
reloc_call_int0_handler:
mov si,divide_by_zero_message
zero_message_loop:
mov al, [cs:si]
test al,al
je zero_done
inc si
mov bx, 0070h
mov ah, 0eh
int 10h
jmp short zero_message_loop
zero_done:
mov bp, sp
xor si, si ; print 13 words of stack for debugging LUDIV etc.
stack_loop:
mov dx, [bp+si]
call print_hex
mov al, ' '
int 10h
inc si
inc si
cmp si, byte 13*2
jb stack_loop
mov al, 0dh
int 10h
mov al, 0ah
int 10h
mov ax,04c7fh ; terminate with errorlevel 127
int 21h
sti
thats_it: hlt
jmp short thats_it ; it might be command.com that nukes
invalid_opcode_message db 0dh,0ah,'Invalid Opcode at ',0
global reloc_call_int6_handler
reloc_call_int6_handler:
mov si,invalid_opcode_message
jmp short zero_message_loop
global reloc_call_int19_handler
reloc_call_int19_handler:
; from Japheth's public domain code (JEMFBHLP.ASM)
; restores int 10,13,15,19,1b and then calls the original int 19.
cld
xor ax,ax
mov es,ax
mov al,70h
mov ds,ax
mov si,100h
mov cx,5
cli
nextitem: lodsb
mov di,ax
%if XCPU >= 186
shl di,2
%else
shl di,1
shl di,1
%endif
movsw
movsw
loop nextitem
int 19h
;
; Terminate the current process
;
; VOID INRPT far
; int20_handler(iregs UserRegs)
;
reloc_call_int20_handler:
mov ah,0 ; terminate through int 21h
;
; MS-DOS system call entry point
;
; VOID INRPT far
; int21_handler(iregs UserRegs)
;
reloc_call_int21_handler:
;
; Create the stack frame for C call. This is done to
; preserve machine state and provide a C structure for
; access to registers.
;
; Since this is an interrupt routine, CS, IP and flags were
; pushed onto the stack by the processor, completing the
; stack frame.
;
; NB: stack frame is MS-DOS dependent and not compatible
; with compiler interrupt stack frames.
;
sti
PUSH$ALL
mov bp,sp
;
; Create kernel reference frame.
;
; NB: At this point, SS != DS and won't be set that way
; until later when which stack to run on is determined.
;
int21_reentry:
Protect386Registers
mov dx,[cs:_DGROUP_]
mov ds,dx
cmp ah,25h
je int21_user
cmp ah,33h
je int21_user
cmp ah,35h
je int21_user
cmp ah,50h
je int21_user
cmp ah,51h
je int21_user
cmp ah,62h
jne int21_1
int21_user:
call dos_crit_sect
push ss
push bp
call _int21_syscall
pop cx
pop cx
jmp short int21_ret
;
; normal entry, use one of our 4 stacks
;
; DX=DGROUP
; CX=STACK
; SI=userSS
; BX=userSP
int21_1:
mov si,ss ; save user stack, to be retored later
;
; Now DS is set, let's save our stack for rentry (???TE)
;
; I don't know who needs that, but ... (TE)
;
mov word [_user_r+2],ss
mov word [_user_r],bp ; store and init
;
; Decide which stack to run on.
;
; Unlike previous versions of DOS-C, we need to do this here
; to guarantee the user stack for critical error handling.
; We need to do the int 24h from this stack location.
;
; There are actually four stacks to run on. The first is the
; user stack which is determined by system call number in
; AH. The next is the error stack determined by _ErrorMode.
; Then there's the character stack also determined by system
; call number. Finally, all others run on the disk stack.
; They are evaluated in that order.
cmp byte [_ErrorMode],0
je int21_2
int21_onerrorstack:
mov cx,_error_tos
cli
mov ss,dx
mov sp,cx
sti
push si ; user SS:SP
push bp
call _int21_service
jmp short int21_exit_nodec
int21_2: inc byte [_InDOS]
mov cx,_char_api_tos
or ah,ah
jz int21_3
cmp ah,0ch
jbe int21_normalentry
int21_3:
call dos_crit_sect
mov cx,_disk_api_tos
int21_normalentry:
cli
mov ss,dx
mov sp,cx
sti
;
; Push the far pointer to the register frame for
; int21_syscall and remainder of kernel.
;
push si ; user SS:SP
push bp
call _int21_service
int21_exit: dec byte [_InDOS]
;
; Recover registers from system call. Registers and flags
; were modified by the system call.
;
int21_exit_nodec:
pop bp ; get back user stack
pop si
global _int21_iret
_int21_iret:
cli
mov ss,si
RestoreSP
int21_ret:
Restore386Registers
POP$ALL
;
; ... and return.
;
iret
;
; end Dos Critical Section 0 thur 7
;
;
dos_crit_sect:
mov [_Int21AX],ax ; needed!
push ax ; This must be here!!!
mov ah,82h ; re-enrty sake before disk stack
int 2ah ; Calling Server Hook!
pop ax
ret
;
; Terminate the current process
;
; VOID INRPT far
; int27_handler(iregs UserRegs)
;
reloc_call_int27_handler:
;
; First convert the memory to paragraphs
;
add dx,byte 0fh ; round up
rcr dx,1
shr dx,1
shr dx,1
shr dx,1
;
; ... then use the standard system call
;
mov ax,3100h
jmp reloc_call_int21_handler ; terminate through int 21h
;
;
reloc_call_low_int26_handler:
sti
pushf
push ax
mov ax,026h
jmp short int2526
reloc_call_low_int25_handler:
sti
pushf
push ax
mov ax,025h
int2526:
push cx
push dx
push bx
push sp
push bp
push si
push di
push ds
push es
mov cx, sp ; save stack frame
mov dx, ss
cld
mov bx, [cs:_DGROUP_]
mov ds, bx
; setup our local stack
cli
mov ss,bx
mov sp,_disk_api_tos
sti
Protect386Registers
push dx
push cx ; save user stack
push dx ; SS:SP -> user stack
push cx
push ax ; was set on entry = 25,26
call _int2526_handler
add sp, byte 6
pop cx
pop dx ; restore user stack
Restore386Registers
; restore foreground stack here
cli
mov ss, dx
mov sp, cx
pop es
pop ds
pop di
pop si
pop bp
pop bx ; pop off sp value
pop bx
pop dx
pop cx
pop ax
popf
retf ; Bug-compatiblity with MS-DOS.
; This function is supposed to leave the original
; flag image on the stack.
CONTINUE equ 00h
RETRY equ 01h
ABORT equ 02h
FAIL equ 03h
OK_IGNORE equ 20h
OK_RETRY equ 10h
OK_FAIL equ 08h
PSP_PARENT equ 16h
PSP_USERSP equ 2eh
PSP_USERSS equ 30h
;
; COUNT
; CriticalError(COUNT nFlag, COUNT nDrive, COUNT nError, struct dhdr FAR *lpDevice);
;
global _CriticalError
_CriticalError:
;
; Skip critical error routine if handler is active
;
cmp byte [_ErrorMode],0
je CritErr05 ; Jump if equal
mov ax,FAIL
retn
;
; Do local error processing
;
CritErr05:
;
; C Entry
;
push bp
mov bp,sp
push si
push di
;
; Get parameters
;
mov ah,byte [bp+4] ; nFlags
mov al,byte [bp+6] ; nDrive
mov di,word [bp+8] ; nError
;
; make cx:si point to dev header
; after registers restored use bp:si
;
mov si,word [bp+10] ; lpDevice Offset
mov cx,word [bp+12] ; lpDevice segment
;
; Now save real ss:sp and retry info in internal stack
;
cli
mov es,[_cu_psp]
push word [es:PSP_USERSS]
push word [es:PSP_USERSP]
push word [_MachineId]
push word [int21regs_seg]
push word [int21regs_off]
push word [_user_r+2]
push word [_user_r]
mov [critical_sp],sp
;
; do some clean up because user may never return
;
inc byte [_ErrorMode]
dec byte [_InDOS]
;
; switch to user's stack
;
mov ss,[es:PSP_USERSS]
mov bp,[es:PSP_USERSP]
RestoreSP
Restore386Registers
mov bp,cx
;
; and call critical error handler
;
int 24h ; DOS Critical error handler
;
; recover context
;
cld
cli
mov bp, [cs:_DGROUP_]
mov ds,bp
mov ss,bp
mov sp,[critical_sp]
pop word [_user_r]
pop word [_user_r+2]
pop word [int21regs_off]
pop word [int21regs_seg]
pop word [_MachineId]
mov es,[_cu_psp]
pop word [es:PSP_USERSP]
pop word [es:PSP_USERSS]
mov bp, sp
mov ah, byte [bp+4+4] ; restore old AH from nFlags
sti ; Enable interrupts
;
; clear flags
;
mov byte [_ErrorMode],0
inc byte [_InDOS]
;
; Check for ignore and force fail if not ok
cmp al,CONTINUE
jne CritErr10 ; not ignore, keep testing
test ah,OK_IGNORE
jnz CritErr10
mov al,FAIL
;
; Check for retry and force fail if not ok
;
CritErr10:
cmp al,RETRY
jne CritErr20 ; not retry, keep testing
test ah,OK_RETRY
jnz CritErr20
mov al,FAIL
;
; You know the drill, but now it's different.
; check for fail and force abort if not ok
;
CritErr20:
cmp al,FAIL
jne CritErr30 ; not fail, do exit processing
test ah,OK_FAIL
jnz CritErr30
mov al,ABORT
;
; OK, if it's abort we do extra processing. Otherwise just
; exit.
;
CritErr30:
cmp al,ABORT
je CritErrAbort ; process abort
CritErrExit:
xor ah,ah ; clear out top for return
pop di
pop si
pop bp
ret
;
; Abort processing.
;
CritErrAbort:
mov ax,[_cu_psp]
mov es,ax
cmp ax,[es:PSP_PARENT]
mov al,FAIL
jz CritErrExit
cli
mov bp,word [_user_r+2] ;Get frame
mov ss,bp
mov bp,word [_user_r]
mov sp,bp
mov byte [_ErrorMode],1 ; flag abort
mov ax,4C00h
mov [bp+reg_ax],ax
sti
jmp int21_reentry ; restart the system call

95
kernel/error.c Normal file
View File

@ -0,0 +1,95 @@
/****************************************************************/
/* */
/* error.c */
/* */
/* Main Kernel Error Handler Functions */
/* */
/* Copyright (c) 1995 */
/* Pasquale J. Villani */
/* All Rights Reserved */
/* */
/* This file is part of DOS-C. */
/* */
/* DOS-C is free software; you can redistribute it and/or */
/* modify it under the terms of the GNU General Public License */
/* as published by the Free Software Foundation; either version */
/* 2, or (at your option) any later version. */
/* */
/* DOS-C is distributed in the hope that it will be useful, but */
/* WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See */
/* the GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public */
/* License along with DOS-C; see the file COPYING. If not, */
/* write to the Free Software Foundation, 675 Mass Ave, */
/* Cambridge, MA 02139, USA. */
/****************************************************************/
#include "portab.h"
#ifdef VERSION_STRINGS
static BYTE *errorRcsId =
"$Id: error.c 709 2003-09-24 19:34:11Z bartoldeman $";
#endif
#include "globals.h"
#ifdef DEBUG
/* error registers */
VOID dump(void)
{
printf("Register Dump [AH = %02x CS:IP = %04x:%04x FLAGS = %04x]\n",
error_regs.AH, error_regs.CS, error_regs.IP, error_regs.FLAGS);
printf("AX:%04x BX:%04x CX:%04x DX:%04x\n",
error_regs.AX, error_regs.BX, error_regs.CX, error_regs.DX);
printf("SI:%04x DI:%04x DS:%04x ES:%04x\n",
error_regs.SI, error_regs.DI, error_regs.DS, error_regs.ES);
}
#endif
/* issue a panic message for corrupted data structures */
VOID panic(BYTE * s)
{
put_string("\nPANIC: ");
put_string(s);
put_string("\nSystem halted");
for (;;) ;
}
#ifdef IPL
/* issue an internal error message */
VOID fatal(BYTE * err_msg)
{
printf("\nInternal IPL error - %s\nSystem halted\n", err_msg);
exit(-1);
}
#else
/* issue an internal error message */
#if 0
VOID fatal(BYTE * err_msg)
{
printf("\nInternal kernel error - \n");
panic(err_msg);
}
#endif
#endif
/* Abort, retry or fail for character devices */
COUNT char_error(request * rq, struct dhdr FAR * lpDevice)
{
CritErrCode = (rq->r_status & S_MASK) + 0x13;
return CriticalError(EFLG_CHAR | EFLG_ABORT | EFLG_RETRY | EFLG_IGNORE,
0, rq->r_status & S_MASK, lpDevice);
}
/* Abort, retry or fail for block devices */
COUNT block_error(request * rq, COUNT nDrive, struct dhdr FAR * lpDevice,
int mode)
{
CritErrCode = (rq->r_status & S_MASK) + 0x13;
return CriticalError(EFLG_ABORT | EFLG_RETRY | EFLG_IGNORE |
(mode == DSKWRITE ? EFLG_WRITE : 0),
nDrive, rq->r_status & S_MASK, lpDevice);
}

95
kernel/execrh.asm Normal file
View File

@ -0,0 +1,95 @@
;
; File:
; execrh.asm
; Description:
; request handler for calling device drivers
;
; Copyright (c) 1995, 1998
; Pasquale J. Villani
; All Rights Reserved
;
; This file is part of DOS-C.
;
; DOS-C is free software; you can redistribute it and/or
; modify it under the terms of the GNU General Public License
; as published by the Free Software Foundation; either version
; 2, or (at your option) any later version.
;
; DOS-C is distributed in the hope that it will be useful, but
; WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
; the GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public
; License along with DOS-C; see the file COPYING. If not,
; write to the Free Software Foundation, 675 Mass Ave,
; Cambridge, MA 02139, USA.
;
; $Id: execrh.asm 1184 2006-05-20 20:49:59Z mceric $
;
%include "segs.inc"
%include "stacks.inc"
segment HMA_TEXT
; EXECRH
; Execute Device Request
;
; execrh(rhp, dhp)
; request far *rhp;
; struct dhdr far *dhp;
;
;
; The stack is very critical in here.
;
global EXECRH
global INIT_EXECRH
%macro EXECRHM 0
push bp ; perform c entry
mov bp,sp
push si
push ds ; sp=bp-8
lds si,[bp+4] ; ds:si = device header
les bx,[bp+8] ; es:bx = request header
mov ax, [si+6] ; construct strategy address
mov [bp+4], ax
push si ; the bloody fucking RTSND.DOS
push di ; driver destroys SI,DI (tom 14.2.03)
call far[bp+4] ; call far the strategy
pop di
pop si
; Protect386Registers ; old free-EMM386 versions destroy regs in their INIT method
mov ax,[si+8] ; construct 'interrupt' address
mov [bp+4],ax ; construct interrupt address
call far[bp+4] ; call far the interrupt
; Restore386Registers ; less stack load and better performance...
sti ; damm driver turn off ints
cld ; has gone backwards
pop ds
pop si
pop bp
ret 8
%endmacro
EXECRH:
EXECRHM
%ifndef WATCOM
segment INIT_TEXT
INIT_EXECRH:
EXECRHM
%endif

482
kernel/fatdir.c Normal file
View File

@ -0,0 +1,482 @@
/****************************************************************/
/* */
/* fatdir.c */
/* DOS-C */
/* */
/* FAT File System dir Functions */
/* */
/* Copyright (c) 1995 */
/* Pasquale J. Villani */
/* All Rights Reserved */
/* */
/* This file is part of DOS-C. */
/* */
/* DOS-C is free software; you can redistribute it and/or */
/* modify it under the terms of the GNU General Public License */
/* as published by the Free Software Foundation; either version */
/* 2, or (at your option) any later version. */
/* */
/* DOS-C is distributed in the hope that it will be useful, but */
/* WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See */
/* the GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public */
/* License along with DOS-C; see the file COPYING. If not, */
/* write to the Free Software Foundation, 675 Mass Ave, */
/* Cambridge, MA 02139, USA. */
/****************************************************************/
#include "portab.h"
#include "globals.h"
#ifdef VERSION_STRINGS
static BYTE *fatdirRcsId =
"$Id: fatdir.c 1561 2011-04-08 15:35:23Z bartoldeman $";
#endif
/* Description.
* Initialize a fnode so that it will point to the directory with
* dirstart starting cluster; in case of passing dirstart == 0
* fnode will point to the start of a root directory */
VOID dir_init_fnode(f_node_ptr fnp, CLUSTER dirstart)
{
/* reset the directory flags */
fnp->f_sft_idx = 0xff;
fnp->f_dmp = &sda_tmp_dm;
if (fnp == &fnode[1])
fnp->f_dmp = &sda_tmp_dm_ren;
fnp->f_offset = 0l;
fnp->f_cluster_offset = 0;
/* root directory */
#ifdef WITHFAT32
if (dirstart == 0)
if (ISFAT32(fnp->f_dpb))
dirstart = fnp->f_dpb->dpb_xrootclst;
#endif
fnp->f_cluster = fnp->f_dmp->dm_dircluster = dirstart;
}
f_node_ptr dir_open(register const char *dirname, BOOL split, f_node_ptr fnp)
{
int i;
char *fcbname;
/* determine what drive and dpb we are using... */
fnp->f_dpb = get_dpb(dirname[0]-'A');
/* Perform all directory common handling after all special */
/* handling has been performed. */
/* truename() already did a media check() */
/* Walk the directory tree to find the starting cluster */
/* */
/* Start from the root directory (dirstart = 0) */
/* The CDS's cdsStartCls may be used to shorten the search
beginning at the CWD, see mapPath() and CDS.H in order
to enable this behaviour there.
-- 2001/09/04 ska*/
dir_init_fnode(fnp, 0);
fnp->f_dmp->dm_entry = 0;
dirname += 2; /* Assume FAT style drive */
fcbname = fnp->f_dmp->dm_name_pat;
while(*dirname != '\0')
{
/* skip the path seperator */
++dirname;
/* don't continue if we're at the end: this check is */
/* for root directories, the only fully-qualified path */
/* names that end in a \ */
if (*dirname == '\0')
break;
/* Convert the name into an absolute name for */
/* comparison... */
dirname = ConvertNameSZToName83(fcbname, dirname);
/* do not continue if we split the filename off and are */
/* at the end */
if (split && *dirname == '\0')
break;
/* Now search through the directory to */
/* find the entry... */
i = FALSE;
while (dir_read(fnp) == 1)
{
if (!(fnp->f_dir.dir_attrib & D_VOLID) &&
fcbmatch(fcbname, fnp->f_dir.dir_name))
{
i = TRUE;
break;
}
fnp->f_dmp->dm_entry++;
}
if (!i || !(fnp->f_dir.dir_attrib & D_DIR))
{
return (f_node_ptr) 0;
}
else
{
/* make certain we've moved off */
/* root */
dir_init_fnode(fnp, getdstart(fnp->f_dpb, &fnp->f_dir));
fnp->f_dmp->dm_entry = 0;
}
}
return fnp;
}
/* swap internal and external delete flags */
STATIC void swap_deleted(char *name)
{
if (name[0] == DELETED || name[0] == EXT_DELETED)
name[0] ^= EXT_DELETED - DELETED; /* 0xe0 */
}
/* Description.
* Read next consequitive directory entry, pointed by fnp.
* If some error occures the other critical
* fields aren't changed, except those used for caching.
* The fnp->f_dmp->dm_entry always corresponds to the directory entry
* which has been read.
* Return value.
* 1 - all OK, directory entry having been read is not empty.
* 0 - Directory entry is empty.
* DE_SEEK - Attempt to read beyound the end of the directory.
* DE_BLKINVLD - Invalid block.
* Note. Empty directory entries always resides at the end of the directory. */
COUNT dir_read(REG f_node_ptr fnp)
{
struct buffer FAR *bp;
REG UWORD secsize = fnp->f_dpb->dpb_secsize;
unsigned sector;
unsigned entry = fnp->f_dmp->dm_entry;
/* can't have more than 65535 directory entries */
if (entry >= 65535U)
return DE_SEEK;
/* Determine if we hit the end of the directory. If we have, */
/* bump the offset back to the end and exit. If not, fill the */
/* dirent portion of the fnode, set the SFT_FCLEAN bit and leave,*/
/* but only for root directories */
if (fnp->f_dmp->dm_dircluster == 0)
{
if (entry >= fnp->f_dpb->dpb_dirents)
return DE_SEEK;
fnp->f_dirsector = entry / (secsize / DIRENT_SIZE) +
fnp->f_dpb->dpb_dirstrt;
}
else
{
/* Do a "seek" to the directory position */
fnp->f_offset = entry * (ULONG)DIRENT_SIZE;
/* Search through the FAT to find the block */
/* that this entry is in. */
if (map_cluster(fnp, XFR_READ) != SUCCESS)
return DE_SEEK;
/* Compute the block within the cluster and the */
/* offset within the block. */
sector = (UBYTE)(fnp->f_offset / secsize) & fnp->f_dpb->dpb_clsmask;
fnp->f_dirsector = clus2phys(fnp->f_cluster, fnp->f_dpb) + sector;
/* Get the block we need from cache */
}
bp = getblock(fnp->f_dirsector, fnp->f_dpb->dpb_unit);
#ifdef DISPLAY_GETBLOCK
printf("DIR (dir_read)\n");
#endif
/* Now that we have the block for our entry, get the */
/* directory entry. */
if (bp == NULL)
return DE_BLKINVLD;
bp->b_flag &= ~(BFR_DATA | BFR_FAT);
bp->b_flag |= BFR_DIR | BFR_VALID;
fnp->f_diridx = entry % (secsize / DIRENT_SIZE);
getdirent(&bp->b_buffer[fnp->f_diridx * DIRENT_SIZE], &fnp->f_dir);
swap_deleted(fnp->f_dir.dir_name);
/* and for efficiency, stop when we hit the first */
/* unused entry. */
/* either returns 1 or 0 */
return (fnp->f_dir.dir_name[0] != '\0');
}
/* Description.
* Writes directory entry pointed by fnp to disk. In case of erroneous
* situation fnode is released.
* The caller should set
* 1. F_DMOD flag if original directory entry was modified.
* Return value.
* TRUE - all OK.
* FALSE - error occured (fnode is released).
*/
BOOL dir_write_update(REG f_node_ptr fnp, BOOL update)
{
struct buffer FAR *bp;
UBYTE FAR *vp;
/* Update the entry if it was modified by a write or create... */
if (!update || (fnp->f_flags & (SFT_FCLEAN|SFT_FDATE)) != SFT_FCLEAN)
{
bp = getblock(fnp->f_dirsector, fnp->f_dpb->dpb_unit);
/* Now that we have a block, transfer the directory */
/* entry into the block. */
if (bp == NULL)
return FALSE;
#ifdef DISPLAY_GETBLOCK
printf("DIR (dir_write)\n");
#endif
swap_deleted(fnp->f_dir.dir_name);
vp = &bp->b_buffer[fnp->f_diridx * DIRENT_SIZE];
if (update)
{
/* only update fields that are also in the SFT, for dos_close/commit */
fmemcpy(&vp[DIR_NAME], fnp->f_dir.dir_name, FNAME_SIZE + FEXT_SIZE);
fputbyte(&vp[DIR_ATTRIB], fnp->f_dir.dir_attrib);
fputword(&vp[DIR_TIME], fnp->f_dir.dir_time);
fputword(&vp[DIR_DATE], fnp->f_dir.dir_date);
fputword(&vp[DIR_START], fnp->f_dir.dir_start);
#ifdef WITHFAT32
if (ISFAT32(fnp->f_dpb))
fputword(&vp[DIR_START_HIGH], fnp->f_dir.dir_start_high);
#endif
fputlong(&vp[DIR_SIZE], fnp->f_dir.dir_size);
}
else
{
putdirent(&fnp->f_dir, vp);
}
swap_deleted(fnp->f_dir.dir_name);
bp->b_flag &= ~(BFR_DATA | BFR_FAT);
bp->b_flag |= BFR_DIR | BFR_DIRTY | BFR_VALID;
}
/* Clear buffers after directory write or DOS close */
return flush_buffers(fnp->f_dpb->dpb_unit);
}
#ifndef IPL
COUNT dos_findfirst(UCOUNT attr, BYTE * name)
{
REG f_node_ptr fnp;
REG dmatch *dmp = &sda_tmp_dm;
/* printf("ff %Fs\n", name);*/
/* The findfirst/findnext calls are probably the worst of the */
/* DOS calls. They must work somewhat on the fly (i.e. - open */
/* but never close). The near fnodes now work this way. Every */
/* time a directory is searched, we will initialize the DOS */
/* dirmatch structure and then for every find, we will open the */
/* current directory, do a seek and read. */
/* first: findfirst("D:\\") returns DE_NFILES */
if (name[3] == '\0')
return DE_NFILES;
/* Now open this directory so that we can read the */
/* fnode entry and do a match on it. */
if ((fnp = split_path(name, &fnode[0])) == NULL)
return DE_PATHNOTFND;
/* Now search through the directory to find the entry... */
/* Special handling - the volume id is only in the root */
/* directory and only searched for once. So we need to open */
/* the root and return only the first entry that contains the */
/* volume id bit set (while ignoring LFN entries). */
/* RBIL: ignore ReaDONLY and ARCHIVE bits but DEVICE ignored too*/
/* For compatibility with bad search requests, only treat as */
/* volume search if only volume bit set, else ignore it. */
if ((attr & ~(D_RDONLY | D_ARCHIVE | D_DEVICE)) == D_VOLID)
/* if ONLY label wanted redirect search to root dir */
dir_init_fnode(fnp, 0);
/* Now further initialize the dirmatch structure. */
dmp->dm_drive = name[0] - 'A';
dmp->dm_attr_srch = attr;
return dos_findnext();
}
/*
BUGFIX TE 06/28/01
when using FcbFindXxx, the only information available is
the cluster number + entrycount. everything else MUST\
be recalculated.
a good test for this is MSDOS CHKDSK, which now (seems too) work
*/
COUNT dos_findnext(void)
{
REG f_node_ptr fnp;
REG dmatch *dmp;
/* Select the default to help non-drive specified path */
/* searches... */
fnp = &fnode[0];
dmp = &sda_tmp_dm;
fnp->f_dpb = get_dpb(dmp->dm_drive);
if (media_check(fnp->f_dpb) < 0)
return DE_NFILES;
dir_init_fnode(fnp, dmp->dm_dircluster);
/* Search through the directory to find the entry, but do a */
/* seek first. */
/* Loop through the directory */
while (dir_read(fnp) == 1)
{
++dmp->dm_entry;
if (fnp->f_dir.dir_name[0] != DELETED
&& (fnp->f_dir.dir_attrib & D_LFN) != D_LFN)
{
if (fcmp_wild(dmp->dm_name_pat, fnp->f_dir.dir_name, FNAME_SIZE + FEXT_SIZE))
{
/*
MSD Command.com uses FCB FN 11 & 12 with attrib set to 0x16.
Bits 0x21 seem to get set some where in MSD so Rd and Arc
files are returned.
RdOnly + Archive bits are ignored
*/
/* Test the attribute as the final step */
/* It's either a special volume label search or an */
/* attribute inclusive search. The attribute inclusive search */
/* can also find volume labels if you set e.g. D_DIR|D_VOLUME */
UBYTE attr_srch;
attr_srch = dmp->dm_attr_srch & ~(D_RDONLY | D_ARCHIVE | D_DEVICE);
if (attr_srch == D_VOLID)
{
if (!(fnp->f_dir.dir_attrib & D_VOLID))
continue;
}
else if (~attr_srch & (D_DIR | D_SYSTEM | D_HIDDEN | D_VOLID) &
fnp->f_dir.dir_attrib)
continue;
/* If found, transfer it to the dmatch structure */
memcpy(&SearchDir, &fnp->f_dir, sizeof(struct dirent));
/* return the result */
return SUCCESS;
}
}
}
#ifdef DEBUG
printf("dos_findnext: %11s\n", fnp->f_dir.dir_name);
#endif
/* return the result */
return DE_NFILES;
}
#endif
/*
this receives a name in 11 char field NAME+EXT and builds
a zeroterminated string
unfortunately, blanks are allowed in filenames. like
"test e", " test .y z",...
so we have to work from the last blank backward
*/
void ConvertName83ToNameSZ(BYTE FAR * destSZ, BYTE FAR * srcFCBName)
{
int loop;
int noExtension = FALSE;
if (*srcFCBName == '.')
{
noExtension = TRUE;
}
fmemcpy(destSZ, srcFCBName, FNAME_SIZE);
srcFCBName += FNAME_SIZE;
for (loop = FNAME_SIZE; --loop >= 0;)
{
if (destSZ[loop] != ' ')
break;
}
destSZ += loop + 1;
if (!noExtension) /* not for ".", ".." */
{
for (loop = FEXT_SIZE; --loop >= 0;)
{
if (srcFCBName[loop] != ' ')
break;
}
if (loop >= 0)
{
*destSZ++ = '.';
fmemcpy(destSZ, srcFCBName, loop + 1);
destSZ += loop + 1;
}
}
*destSZ = '\0';
}
#if 0
/*
returns the asciiSZ length of a 8.3 filename
*/
int FileName83Length(BYTE * filename83)
{
BYTE buff[13];
ConvertName83ToNameSZ(buff, filename83);
return strlen(buff);
}
#endif
/* this routine converts a name portion of a fully qualified path */
/* name, so . and .. are not allowed, only straightforward 8+3 names */
const char *ConvertNameSZToName83(char *fcbname, const char *dirname)
{
int i;
memset(fcbname, ' ', FNAME_SIZE + FEXT_SIZE);
for (i = 0; i < FNAME_SIZE + FEXT_SIZE; i++, dirname++)
{
char c = *dirname;
if (c == '.')
i = FNAME_SIZE - 1;
else if (c != '\0' && c != '\\')
fcbname[i] = c;
else
break;
}
return dirname;
}

1870
kernel/fatfs.c Normal file

File diff suppressed because it is too large Load Diff

413
kernel/fattab.c Normal file
View File

@ -0,0 +1,413 @@
/****************************************************************/
/* */
/* fattab.c */
/* */
/* FAT File System Table Functions */
/* */
/* Copyright (c) 1995 */
/* Pasquale J. Villani */
/* All Rights Reserved */
/* */
/* This file is part of DOS-C. */
/* */
/* DOS-C is free software; you can redistribute it and/or */
/* modify it under the terms of the GNU General Public License */
/* as published by the Free Software Foundation; either version */
/* 2, or (at your option) any later version. */
/* */
/* DOS-C is distributed in the hope that it will be useful, but */
/* WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See */
/* the GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public */
/* License along with DOS-C; see the file COPYING. If not, */
/* write to the Free Software Foundation, 675 Mass Ave, */
/* Cambridge, MA 02139, USA. */
/****************************************************************/
#include "portab.h"
#include "globals.h"
#ifdef VERSION_STRINGS
static BYTE *RcsId =
"$Id: fattab.c 1631 2011-06-13 16:27:34Z bartoldeman $";
#endif
/************************************************************************/
/* */
/* cluster/sector routines */
/* */
/************************************************************************/
/* special "impossible" "Cluster2" value of 1 denotes reading the
cluster number rather than overwriting it */
#define READ_CLUSTER 1
#ifndef ISFAT32
int ISFAT32(struct dpb FAR * dpbp)
{
return _ISFAT32(dpbp);
}
#endif
void clusterMessage(const char * msg, CLUSTER clussec)
{
put_string("Run chkdsk: Bad FAT ");
put_string(msg);
#ifdef WITHFAT32
put_unsigned((unsigned)(clussec >> 16), 16, 4);
#endif
put_unsigned((unsigned)(clussec & 0xffffu), 16, 4);
put_console('\n');
}
struct buffer FAR *getFATblock(struct dpb FAR * dpbp, CLUSTER clussec)
{
/* *** why dpbp->dpb_unit? only useful to know in context of the dpbp...? *** */
struct buffer FAR *bp = getblock(clussec, dpbp->dpb_unit);
if (bp)
{
bp->b_flag &= ~(BFR_DATA | BFR_DIR);
bp->b_flag |= BFR_FAT | BFR_VALID;
bp->b_dpbp = dpbp;
bp->b_copies = dpbp->dpb_fats;
bp->b_offset = dpbp->dpb_fatsize; /* 0 for FAT32 but blockio.c knows that */
#ifdef WITHFAT32
if (ISFAT32(dpbp))
{
if (dpbp->dpb_xflags & FAT_NO_MIRRORING)
bp->b_copies = 1;
}
#endif
} else {
clusterMessage("I/O: 0x",clussec);
}
return bp;
}
#ifdef WITHFAT32
void read_fsinfo(struct dpb FAR * dpbp)
{
struct buffer FAR *bp;
struct fsinfo FAR *fip;
CLUSTER cluster;
if (dpbp->dpb_xfsinfosec == 0xffff)
return;
bp = getblock(dpbp->dpb_xfsinfosec, dpbp->dpb_unit);
bp->b_flag &= ~(BFR_DATA | BFR_DIR | BFR_FAT | BFR_DIRTY);
bp->b_flag |= BFR_VALID;
fip = (struct fsinfo FAR *)&bp->b_buffer[0x1e4];
/* need to range check values because they may not be correct */
cluster = fip->fi_nfreeclst;
if (cluster >= dpbp->dpb_xsize)
cluster = XUNKNCLSTFREE;
dpbp->dpb_xnfreeclst = cluster;
cluster = fip->fi_cluster;
if (cluster < 2 || cluster > dpbp->dpb_xsize)
cluster = UNKNCLUSTER;
dpbp->dpb_xcluster = cluster;
}
void write_fsinfo(struct dpb FAR * dpbp)
{
struct buffer FAR *bp;
struct fsinfo FAR *fip;
if (dpbp->dpb_xfsinfosec == 0xffff)
return;
bp = getblock(dpbp->dpb_xfsinfosec, dpbp->dpb_unit);
bp->b_flag &= ~(BFR_DATA | BFR_DIR | BFR_FAT);
bp->b_flag |= BFR_VALID;
fip = (struct fsinfo FAR *)&bp->b_buffer[0x1e4];
if (fip->fi_nfreeclst != dpbp->dpb_xnfreeclst ||
fip->fi_cluster != dpbp->dpb_xcluster)
bp->b_flag |= BFR_DIRTY; /* only flag for update if we had real news */
fip->fi_nfreeclst = dpbp->dpb_xnfreeclst;
fip->fi_cluster = dpbp->dpb_xcluster;
}
#endif
/* */
/* The FAT file system is difficult to trace through FAT table. */
/* There are two kinds of FATs, 12 bit and 16 bit. The 16 bit */
/* FAT is the easiest, since it is nothing more than a series */
/* of UWORDs. The 12 bit FAT is difficult, because it packs 3 */
/* FAT entries into two BYTEs. These are packed as follows: */
/* */
/* 0x0003 0x0004 0x0005 0x0006 0x0007 0x0008 0x0009 ... */
/* */
/* are packed as */
/* */
/* 0x03 0x40 0x00 0x05 0x60 0x00 0x07 0x80 0x00 0x09 ... */
/* */
/* 12 bytes are compressed to 9 bytes */
/* */
/* either read the value at Cluster1 (if Cluster2 is READ_CLUSTER) */
/* or write the Cluster2 value to the FAT entry at Cluster1 */
/* Read is always via next_cluster wrapper which has extra checks */
/* It might make sense to manually check old values before a write */
/* returns: the cluster number (or 1 on error) for read mode */
/* returns: SUCCESS (or 1 on error) for write mode */
CLUSTER link_fat(struct dpb FAR * dpbp, CLUSTER Cluster1,
REG CLUSTER Cluster2)
{
struct buffer FAR *bp;
unsigned idx;
unsigned secdiv; /* FAT entries per sector; nibbles for FAT12! */
unsigned char wasfree;
CLUSTER clussec = Cluster1;
CLUSTER max_cluster = dpbp->dpb_size;
#ifdef WITHFAT32
if (ISFAT32(dpbp))
max_cluster = dpbp->dpb_xsize;
#endif
if (clussec <= 1 || clussec > max_cluster) /* try to read out of range? */
{
clusterMessage("index: 0x",clussec); /* bad array offset */
return 1;
}
/* Cluster2 can 0 (FREE) or 1 (READ_CLUSTER), a cluster nr. >= 2, */
/* (range check this case!) LONG_LAST_CLUSTER or LONG_BAD here... */
if (Cluster2 < LONG_BAD && Cluster2 > max_cluster) /* writing bad value? */
{
clusterMessage("write: 0x",Cluster2); /* refuse to write bad value */
return 1;
}
secdiv = dpbp->dpb_secsize;
if (ISFAT12(dpbp))
{
clussec = (unsigned)clussec * 3;
secdiv *= 2;
}
else /* FAT16 or FAT32 */
{
secdiv /= 2;
#ifdef WITHFAT32
if (ISFAT32(dpbp))
secdiv /= 2;
#endif
}
/* idx is a pointer to an index which is the nibble offset of the FAT
entry within the sector for FAT12, or word offset for FAT16, or
dword offset for FAT32 */
idx = (unsigned)(clussec % secdiv);
clussec /= secdiv;
clussec += dpbp->dpb_fatstrt;
#ifdef WITHFAT32
if (ISFAT32(dpbp) && (dpbp->dpb_xflags & FAT_NO_MIRRORING))
{
/* we must modify the active fat,
it's number is in the 0-3 bits of dpb_xflags */
clussec += (dpbp->dpb_xflags & 0xf) * dpbp->dpb_xfatsize;
}
#endif
/* Get the block that this cluster is in */
bp = getFATblock(dpbp, clussec);
if (bp == NULL) {
return 1; /* the only error code possible here */
}
if (ISFAT12(dpbp))
{
REG UBYTE FAR *fbp0, FAR * fbp1;
struct buffer FAR * bp1;
unsigned cluster, cluster2;
/* form an index so that we can read the block as a */
/* byte array */
idx /= 2;
/* Test to see if the cluster straddles the block. If */
/* it does, get the next block and use both to form the */
/* the FAT word. Otherwise, just point to the next */
/* block. */
fbp0 = &bp->b_buffer[idx];
/* pointer to next byte, will be overwritten, if not valid */
fbp1 = fbp0 + 1;
if (idx >= (unsigned)dpbp->dpb_secsize - 1)
{
/* blockio.c LRU logic ensures that bp != bp1 */
bp1 = getFATblock(dpbp, (unsigned)clussec + 1);
if (bp1 == 0)
return 1; /* the only error code possible here */
if (Cluster2 != READ_CLUSTER)
bp1->b_flag |= BFR_DIRTY | BFR_VALID;
fbp1 = &bp1->b_buffer[0];
}
cluster = *fbp0 | (*fbp1 << 8);
{
unsigned res = cluster;
/* Now to unpack the contents of the FAT entry. Odd and */
/* even bytes are packed differently. */
if (Cluster1 & 0x01)
cluster >>= 4;
cluster &= 0x0fff;
if ((unsigned)Cluster2 == READ_CLUSTER)
{
if (cluster >= MASK12)
return LONG_LAST_CLUSTER;
if (cluster == BAD12)
return LONG_BAD;
return cluster;
}
wasfree = 0;
if (cluster == FREE)
wasfree = 1;
cluster = res;
}
/* Cluster2 may be set to LONG_LAST_CLUSTER == 0x0FFFFFFFUL or 0xFFFF */
/* -- please don't remove this mask! */
cluster2 = (unsigned)Cluster2 & 0x0fff;
/* Now pack the value in */
if ((unsigned)Cluster1 & 0x01)
{
cluster &= 0x000f;
cluster2 <<= 4;
}
else
{
cluster &= 0xf000;
}
cluster |= cluster2;
*fbp0 = (UBYTE)cluster;
*fbp1 = (UBYTE)(cluster >> 8);
}
else if (ISFAT16(dpbp))
{
/* form an index so that we can read the block as a */
/* byte array */
/* and get the cluster number */
UWORD res = fgetword(&bp->b_buffer[idx * 2]);
if ((unsigned)Cluster2 == READ_CLUSTER)
{
if (res >= MASK16)
return LONG_LAST_CLUSTER;
if (res == BAD16)
return LONG_BAD;
return res;
}
/* Finally, put the word into the buffer and mark the */
/* buffer as dirty. */
fputword(&bp->b_buffer[idx * 2], (UWORD)Cluster2);
wasfree = 0;
if (res == FREE)
wasfree = 1;
}
#ifdef WITHFAT32
else if (ISFAT32(dpbp))
{
/* form an index so that we can read the block as a */
/* byte array */
UDWORD res = fgetlong(&bp->b_buffer[idx * 4]) & LONG_LAST_CLUSTER;
if (Cluster2 == READ_CLUSTER)
{
if (res > LONG_BAD)
return LONG_LAST_CLUSTER;
return res;
}
/* Finally, put the word into the buffer and mark the */
/* buffer as dirty. */
fputlong(&bp->b_buffer[idx * 4], Cluster2 & LONG_LAST_CLUSTER);
wasfree = 0;
if (res == FREE)
wasfree = 1;
}
#endif
else {
put_string("Bad DPB!\n"); /* FAT1x size field > 65525U (see fat.h) */
return 1;
}
/* update the free space count */
bp->b_flag |= BFR_DIRTY | BFR_VALID;
if (Cluster2 == FREE || wasfree)
{
int adjust = 0;
if (!wasfree)
adjust = 1;
else if (Cluster2 != FREE)
adjust = -1;
#ifdef WITHFAT32
if (ISFAT32(dpbp) && dpbp->dpb_xnfreeclst != XUNKNCLSTFREE)
{
/* update the free space count for returned */
/* cluster */
dpbp->dpb_xnfreeclst += adjust;
write_fsinfo(dpbp);
}
else
#endif
if (dpbp->dpb_nfreeclst != UNKNCLSTFREE)
dpbp->dpb_nfreeclst += adjust;
}
return SUCCESS;
}
/* Given the disk parameters, and a cluster number, this function */
/* looks at the FAT, and returns the next cluster in the clain or */
/* 0 if there is no chain, 1 on error, LONG_LAST_CLUSTER at end. */
CLUSTER next_cluster(struct dpb FAR * dpbp, CLUSTER ClusterNum)
{
CLUSTER candidate, following, max_cluster;
candidate = link_fat(dpbp, ClusterNum, READ_CLUSTER);
/* empty (0) error (1) bad (LONG_BAD) last (>LONG_BAD) need no checks */
#if 0
if (candidate == ClusterNum)
return 1; /* chain has a tiny loop - easy but boring error check */
#endif
if (candidate < 2 || candidate >= LONG_BAD)
return candidate;
max_cluster = dpbp->dpb_size;
#ifdef WITHFAT32
if (ISFAT32(dpbp))
max_cluster = dpbp->dpb_xsize;
#endif
/* FAT entry points to a possibly invalid next cluster */
following = link_fat(dpbp, candidate, READ_CLUSTER);
if (following<2 || (following < LONG_BAD && following > max_cluster))
{
/* chain must not contain free or out of range clusters */
clusterMessage("value: 0x",following); /* read returned bad value */
return 1; /* only possible error code here */
}
/* without checking "following", a chain can dangle to a free cluster: */
/* if that cluster is later used by another chain, you get cross links */
return candidate;
}
/* check if the selected cluster is free (faster than next_cluster) */
BOOL is_free_cluster(struct dpb FAR * dpbp, CLUSTER ClusterNum)
{
return (link_fat(dpbp, ClusterNum, READ_CLUSTER) == FREE);
}

713
kernel/fcbfns.c Normal file
View File

@ -0,0 +1,713 @@
/****************************************************************/
/* */
/* fcbfns.c */
/* */
/* Old CP/M Style Function Handlers for Kernel */
/* */
/* Copyright (c) 1995 */
/* Pasquale J. Villani */
/* All Rights Reserved */
/* */
/* This file is part of DOS-C. */
/* */
/* DOS-C is free software; you can redistribute it and/or */
/* modify it under the terms of the GNU General Public License */
/* as published by the Free Software Foundation; either version */
/* 2, or (at your option) any later version. */
/* */
/* DOS-C is distributed in the hope that it will be useful, but */
/* WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See */
/* the GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public */
/* License along with DOS-C; see the file COPYING. If not, */
/* write to the Free Software Foundation, 675 Mass Ave, */
/* Cambridge, MA 02139, USA. */
/****************************************************************/
#include "portab.h"
#include "globals.h"
#ifdef VERSION_STRINGS
static BYTE *RcsId =
"$Id: fcbfns.c 1405 2009-05-26 20:44:44Z bartoldeman $";
#endif
#define FCB_SUCCESS 0
#define FCB_ERR_NODATA 1
#define FCB_ERR_SEGMENT_WRAP 2
#define FCB_ERR_EOF 3
#define FCB_ERROR 0xff
STATIC fcb FAR *ExtFcbToFcb(xfcb FAR * lpExtFcb);
STATIC fcb FAR *CommonFcbInit(xfcb FAR * lpExtFcb, BYTE * pszBuffer,
COUNT * pCurDrive);
STATIC void FcbNameInit(fcb FAR * lpFcb, BYTE * pszBuffer, COUNT * pCurDrive);
STATIC void FcbNextRecord(fcb FAR * lpFcb);
STATIC void FcbCalcRec(xfcb FAR * lpXfcb);
#define TestCmnSeps(lpFileName) (*lpFileName && strchr(":<|>+=,", *lpFileName) != NULL)
#define TestFieldSeps(lpFileName) ((unsigned char)*lpFileName <= ' ' || strchr("/\"[]<>|.", *lpFileName) != NULL)
static dmatch Dmatch;
BYTE FAR *FatGetDrvData(UBYTE drive, UBYTE * pspc, UWORD * bps, UWORD * nc)
{
static BYTE mdb;
UWORD spc;
/* get the data available from dpb */
spc = DosGetFree(drive, NULL, bps, nc);
if (spc != 0xffff)
{
struct dpb FAR *dpbp = get_dpb(drive == 0 ? default_drive : drive - 1);
/* Point to the media desctriptor for this drive */
*pspc = (UBYTE)spc;
if (dpbp == NULL)
{
mdb = spc >> 8;
spc &= 0xff;
return &mdb;
}
else
{
return (BYTE FAR *) & (dpbp->dpb_mdb);
}
}
return NULL;
}
#define PARSE_SEP_STOP 0x01
#define PARSE_DFLT_DRIVE 0x02
#define PARSE_BLNK_FNAME 0x04
#define PARSE_BLNK_FEXT 0x08
#define PARSE_RET_NOWILD 0
#define PARSE_RET_WILD 1
#define PARSE_RET_BADDRIVE 0xff
#ifndef IPL
UWORD FcbParseFname(UBYTE *wTestMode, const BYTE FAR * lpFileName, fcb FAR * lpFcb)
{
WORD wRetCodeName = FALSE, wRetCodeExt = FALSE;
/* pjv -- ExtFcbToFcb? */
if (!(*wTestMode & PARSE_SEP_STOP))
{
lpFileName = ParseSkipWh(lpFileName);
if (TestCmnSeps(lpFileName))
++lpFileName;
}
/* Undocumented "feature," we skip white space anyway */
lpFileName = ParseSkipWh(lpFileName);
/* Now check for drive specification */
if (*(lpFileName + 1) == ':')
{
/* non-portable construct to be changed */
REG UBYTE Drive = DosUpFChar(*lpFileName) - 'A';
if (get_cds(Drive) == NULL)
{
*wTestMode = PARSE_RET_BADDRIVE;
return FP_OFF(lpFileName);
}
lpFcb->fcb_drive = Drive + 1;
lpFileName += 2;
} else if (!(*wTestMode & PARSE_DFLT_DRIVE)) {
lpFcb->fcb_drive = FDFLT_DRIVE;
}
/* Undocumented behavior, set record number & record size to 0 */
lpFcb->fcb_cublock = lpFcb->fcb_recsiz = 0;
if (!(*wTestMode & PARSE_BLNK_FNAME))
{
fmemset(lpFcb->fcb_fname, ' ', FNAME_SIZE);
}
if (!(*wTestMode & PARSE_BLNK_FEXT))
{
fmemset(lpFcb->fcb_fext, ' ', FEXT_SIZE);
}
/* special cases: '.' and '..' */
if (*lpFileName == '.')
{
lpFcb->fcb_fname[0] = '.';
++lpFileName;
if (*lpFileName == '.')
{
lpFcb->fcb_fname[1] = '.';
++lpFileName;
}
*wTestMode = PARSE_RET_NOWILD;
return FP_OFF(lpFileName);
}
/* Now to format the file name into the string */
lpFileName =
GetNameField(lpFileName, (BYTE FAR *) lpFcb->fcb_fname, FNAME_SIZE,
(BOOL *) & wRetCodeName);
/* Do we have an extension? If do, format it else return */
if (*lpFileName == '.')
lpFileName =
GetNameField(++lpFileName, (BYTE FAR *) lpFcb->fcb_fext,
FEXT_SIZE, (BOOL *) & wRetCodeExt);
*wTestMode = (wRetCodeName | wRetCodeExt) ? PARSE_RET_WILD : PARSE_RET_NOWILD;
return FP_OFF(lpFileName);
}
const BYTE FAR * ParseSkipWh(const BYTE FAR * lpFileName)
{
while (*lpFileName == ' ' || *lpFileName == '\t')
++lpFileName;
return lpFileName;
}
#if 0 /* defined above */
BOOL TestCmnSeps(BYTE FAR * lpFileName)
{
BYTE *pszTest, *pszCmnSeps = ":<|>+=,";
for (pszTest = pszCmnSeps; *pszTest != '\0'; ++pszTest)
if (*lpFileName == *pszTest)
return TRUE;
return FALSE;
}
#endif
#if 0
BOOL TestFieldSeps(BYTE FAR * lpFileName)
{
BYTE *pszTest, *pszCmnSeps = "/\"[]<>|.";
/* Another non-portable construct */
if (*lpFileName <= ' ')
return TRUE;
for (pszTest = pszCmnSeps; *pszTest != '\0'; ++pszTest)
if (*lpFileName == *pszTest)
return TRUE;
return FALSE;
}
#endif
const BYTE FAR * GetNameField(const BYTE FAR * lpFileName, BYTE FAR * lpDestField,
COUNT nFieldSize, BOOL * pbWildCard)
{
COUNT nIndex = 0;
BYTE cFill = ' ';
while (*lpFileName != '\0' && !TestFieldSeps(lpFileName)
&& nIndex < nFieldSize)
{
if (*lpFileName == ' ')
break;
if (*lpFileName == '*')
{
*pbWildCard = TRUE;
cFill = '?';
++lpFileName;
break;
}
if (*lpFileName == '?')
*pbWildCard = TRUE;
*lpDestField++ = DosUpFChar(*lpFileName++);
++nIndex;
}
/* Blank out remainder of field on exit */
fmemset(lpDestField, cFill, nFieldSize - nIndex);
return lpFileName;
}
STATIC VOID FcbNextRecord(fcb FAR * lpFcb)
{
if (++lpFcb->fcb_curec >= 128)
{
lpFcb->fcb_curec = 0;
++lpFcb->fcb_cublock;
}
}
STATIC ULONG FcbRec(fcb FAR *lpFcb)
{
return ((ULONG) lpFcb->fcb_cublock * 128) + lpFcb->fcb_curec;
}
UBYTE FcbReadWrite(xfcb FAR * lpXfcb, UCOUNT recno, int mode)
{
ULONG lPosit;
long nTransfer;
fcb FAR *lpFcb;
unsigned size;
unsigned long bigsize;
unsigned recsiz;
/* Convert to fcb if necessary */
lpFcb = ExtFcbToFcb(lpXfcb);
recsiz = lpFcb->fcb_recsiz;
bigsize = (ULONG)recsiz * recno;
if (bigsize > 0xffff)
return FCB_ERR_SEGMENT_WRAP;
size = (unsigned)bigsize;
if (FP_OFF(dta) + size < FP_OFF(dta))
return FCB_ERR_SEGMENT_WRAP;
/* Now update the fcb and compute where we need to position */
/* to. */
lPosit = FcbRec(lpFcb) * recsiz;
if ((CritErrCode = -SftSeek(lpFcb->fcb_sftno, lPosit, 0)) != SUCCESS)
return FCB_ERR_NODATA;
/* Do the read */
nTransfer = DosRWSft(lpFcb->fcb_sftno, size, dta, mode & ~XFR_FCB_RANDOM);
if (nTransfer < 0)
CritErrCode = -(int)nTransfer;
/* Now find out how we will return and do it. */
if (mode & XFR_WRITE)
lpFcb->fcb_fsize = SftGetFsize(lpFcb->fcb_sftno);
/* if end-of-file, then partial read should count last record */
if (mode & XFR_FCB_RANDOM && recsiz > 0)
lpFcb->fcb_rndm += ((unsigned)nTransfer + recsiz - 1) / recsiz;
size -= (unsigned)nTransfer;
if (size == 0)
{
FcbNextRecord(lpFcb);
return FCB_SUCCESS;
}
size %= lpFcb->fcb_recsiz;
if (mode & XFR_READ && size > 0)
{
fmemset((char FAR *)dta + (unsigned)nTransfer, 0, size);
FcbNextRecord(lpFcb);
return FCB_ERR_EOF;
}
return FCB_ERR_NODATA;
}
UBYTE FcbGetFileSize(xfcb FAR * lpXfcb)
{
int FcbDrive, sft_idx;
unsigned recsiz;
/* Build a traditional DOS file name */
fcb FAR *lpFcb = CommonFcbInit(lpXfcb, SecPathName, &FcbDrive);
recsiz = lpFcb->fcb_recsiz;
/* check for a device */
if (!lpFcb || IsDevice(SecPathName) || (recsiz == 0))
return FCB_ERROR;
sft_idx = (short)DosOpenSft(SecPathName, O_LEGACY | O_RDONLY | O_OPEN, 0);
if (sft_idx >= 0)
{
ULONG fsize;
/* Get the size */
fsize = SftGetFsize(sft_idx);
/* compute the size and update the fcb */
lpFcb->fcb_rndm = (fsize + (recsiz - 1)) / recsiz;
/* close the file and leave */
if ((CritErrCode = -DosCloseSft(sft_idx, FALSE)) == SUCCESS)
return FCB_SUCCESS;
}
else
CritErrCode = -sft_idx;
return FCB_ERROR;
}
void FcbSetRandom(xfcb FAR * lpXfcb)
{
/* Convert to fcb if necessary */
fcb FAR *lpFcb = ExtFcbToFcb(lpXfcb);
/* Now update the fcb and compute where we need to position */
/* to. */
lpFcb->fcb_rndm = FcbRec(lpFcb);
}
void FcbCalcRec(xfcb FAR * lpXfcb)
{
/* Convert to fcb if necessary */
fcb FAR *lpFcb = ExtFcbToFcb(lpXfcb);
/* Now update the fcb and compute where we need to position */
/* to. */
lpFcb->fcb_cublock = (UWORD)(lpFcb->fcb_rndm / 128);
lpFcb->fcb_curec = (UBYTE)lpFcb->fcb_rndm & 127;
}
UBYTE FcbRandomBlockIO(xfcb FAR * lpXfcb, UWORD *nRecords, int mode)
{
UBYTE nErrorCode;
fcb FAR *lpFcb;
unsigned long old;
FcbCalcRec(lpXfcb);
/* Convert to fcb if necessary */
lpFcb = ExtFcbToFcb(lpXfcb);
old = lpFcb->fcb_rndm;
nErrorCode = FcbReadWrite(lpXfcb, *nRecords, mode);
*nRecords = (UWORD)(lpFcb->fcb_rndm - old);
/* Now update the fcb */
FcbCalcRec(lpXfcb);
return nErrorCode;
}
UBYTE FcbRandomIO(xfcb FAR * lpXfcb, int mode)
{
UWORD uwCurrentBlock;
UBYTE ucCurrentRecord;
UBYTE nErrorCode;
fcb FAR *lpFcb;
FcbCalcRec(lpXfcb);
/* Convert to fcb if necessary */
lpFcb = ExtFcbToFcb(lpXfcb);
uwCurrentBlock = lpFcb->fcb_cublock;
ucCurrentRecord = lpFcb->fcb_curec;
nErrorCode = FcbReadWrite(lpXfcb, 1, mode);
lpFcb->fcb_cublock = uwCurrentBlock;
lpFcb->fcb_curec = ucCurrentRecord;
return nErrorCode;
}
/* FcbOpen and FcbCreate
Expects lpXfcb to point to a valid, unopened FCB, containing file name to open (create)
Create will attempt to find the file name in the current directory, if found truncates
setting file size to 0, otherwise if does not exist will create the new file; the
FCB is filled in same as the open call.
On any error returns FCB_ERROR
On success returns FCB_SUCCESS, and sets the following fields (other non-system reserved ones left unchanged)
drive identifier (fcb_drive) set to actual drive (1=A, 2=B, ...; always >0 if not device)
current block number (fcb_cublock) to 0
file size (fcb_fsize) value from directory entry (0 if create)
record size (fcb_recsiz) to 128; set to 0 for devices
time & date (fcb_time & fcb_date) values from directory entry
fcb_sftno, fcb_attrib_hi/_lo, fcb_strtclst, fcb_dirclst/off_unused are for internal use (system reserved)
*/
UBYTE FcbOpen(xfcb FAR * lpXfcb, unsigned flags)
{
sft FAR *sftp;
COUNT sft_idx, FcbDrive;
unsigned attr = 0;
/* Build a traditional DOS file name */
fcb FAR *lpFcb = CommonFcbInit(lpXfcb, SecPathName, &FcbDrive);
if ((flags & O_CREAT) && lpXfcb->xfcb_flag == 0xff)
/* pass attribute without constraints (dangerous for directories) */
attr = lpXfcb->xfcb_attrib;
sft_idx = (short)DosOpenSft(SecPathName, flags, attr);
if (sft_idx < 0)
{
CritErrCode = -sft_idx;
return FCB_ERROR;
}
sftp = idx_to_sft(sft_idx);
sftp->sft_mode |= O_FCB;
lpFcb->fcb_sftno = sft_idx;
lpFcb->fcb_cublock = 0;
/* should not be cleared, programs e.g. GEM depend on these values remaining unchanged
lpFcb->fcb_curec = 0;
lpFcb->fcb_rndm = 0;
*/
lpFcb->fcb_recsiz = 0; /* true for devices */
if (!(sftp->sft_flags & SFT_FDEVICE)) /* check for a device */
{
lpFcb->fcb_drive = FcbDrive;
lpFcb->fcb_recsiz = 128;
}
lpFcb->fcb_fsize = sftp->sft_size;
lpFcb->fcb_date = sftp->sft_date;
lpFcb->fcb_time = sftp->sft_time;
return FCB_SUCCESS;
}
STATIC fcb FAR *ExtFcbToFcb(xfcb FAR * lpExtFcb)
{
if (*((UBYTE FAR *) lpExtFcb) == 0xff)
sda_lpFcb = &lpExtFcb->xfcb_fcb;
else
sda_lpFcb = (fcb FAR *) lpExtFcb;
return sda_lpFcb;
}
STATIC fcb FAR *CommonFcbInit(xfcb FAR * lpExtFcb, BYTE * pszBuffer,
COUNT * pCurDrive)
{
fcb FAR *lpFcb;
/* convert to fcb if needed first */
sda_lpFcb = lpFcb = ExtFcbToFcb(lpExtFcb);
/* Build a traditional DOS file name */
FcbNameInit(lpFcb, pszBuffer, pCurDrive);
/* and return the fcb pointer */
return lpFcb;
}
STATIC void FcbNameInit(fcb FAR * lpFcb, BYTE * szBuffer, COUNT * pCurDrive)
{
BYTE *pszBuffer = szBuffer;
/* Build a traditional DOS file name */
*pCurDrive = default_drive + 1;
if (lpFcb->fcb_drive != 0)
{
*pCurDrive = lpFcb->fcb_drive;
pszBuffer[0] = 'A' + lpFcb->fcb_drive - 1;
pszBuffer[1] = ':';
pszBuffer += 2;
}
ConvertName83ToNameSZ(pszBuffer, lpFcb->fcb_fname);
}
UBYTE FcbDelete(xfcb FAR * lpXfcb)
{
COUNT FcbDrive;
UBYTE result = FCB_SUCCESS;
void FAR *lpOldDta = dta;
/* Build a traditional DOS file name */
CommonFcbInit(lpXfcb, SecPathName, &FcbDrive);
/* check for a device */
if (IsDevice(SecPathName))
{
result = FCB_ERROR;
}
else
{
int attr = (lpXfcb->xfcb_flag == 0xff ? lpXfcb->xfcb_attrib : D_ALL);
dmatch Dmatch;
dta = &Dmatch;
if ((CritErrCode = -DosFindFirst(attr, SecPathName)) != SUCCESS)
{
result = FCB_ERROR;
}
else do
{
SecPathName[0] = 'A' + FcbDrive - 1;
SecPathName[1] = ':';
strcpy(&SecPathName[2], Dmatch.dm_name);
if (DosDelete(SecPathName, attr) != SUCCESS)
{
result = FCB_ERROR;
break;
}
}
while ((CritErrCode = -DosFindNext()) == SUCCESS);
}
dta = lpOldDta;
return result;
}
UBYTE FcbRename(xfcb FAR * lpXfcb)
{
rfcb FAR *lpRenameFcb;
COUNT FcbDrive;
UBYTE result = FCB_SUCCESS;
void FAR *lpOldDta = dta;
/* Build a traditional DOS file name */
lpRenameFcb = (rfcb FAR *) CommonFcbInit(lpXfcb, SecPathName, &FcbDrive);
/* check for a device */
if (IsDevice(SecPathName))
{
result = FCB_ERROR;
}
else
{
dmatch Dmatch;
COUNT result;
wAttr = (lpXfcb->xfcb_flag == 0xff ? lpXfcb->xfcb_attrib : D_ALL);
dta = &Dmatch;
if ((CritErrCode = -DosFindFirst(wAttr, SecPathName)) != SUCCESS)
{
result = FCB_ERROR;
}
else do
{
/* 'A:' + '.' + '\0' */
BYTE loc_szBuffer[2 + FNAME_SIZE + 1 + FEXT_SIZE + 1];
fcb LocalFcb;
BYTE *pToName;
const BYTE FAR *pFromPattern = Dmatch.dm_name;
int i;
UBYTE mode = 0;
FcbParseFname(&mode, pFromPattern, &LocalFcb);
/* Overlay the pattern, skipping '?' */
/* I'm cheating because this assumes that the */
/* struct alignments are on byte boundaries */
pToName = LocalFcb.fcb_fname;
pFromPattern = lpRenameFcb->renNewName;
for (i = 0; i < FNAME_SIZE + FEXT_SIZE; i++)
{
if (*pFromPattern != '?')
*pToName = *pFromPattern;
pToName++;
pFromPattern++;
}
SecPathName[0] = 'A' + FcbDrive - 1;
SecPathName[1] = ':';
strcpy(&SecPathName[2], Dmatch.dm_name);
result = truename(SecPathName, PriPathName, 0);
if (result < SUCCESS || (result & IS_DEVICE))
{
result = FCB_ERROR;
break;
}
/* now to build a dos name again */
LocalFcb.fcb_drive = FcbDrive;
FcbNameInit(&LocalFcb, loc_szBuffer, &FcbDrive);
result = truename(loc_szBuffer, SecPathName, 0);
if (result < SUCCESS || (result & (IS_NETWORK|IS_DEVICE)) == IS_DEVICE
|| DosRenameTrue(PriPathName, SecPathName, wAttr) != SUCCESS)
{
result = FCB_ERROR;
break;
}
}
while ((CritErrCode = -DosFindNext()) == SUCCESS);
}
dta = lpOldDta;
return result;
}
/* TE:the MoveDirInfo() is now done by simply copying the dirEntry into the FCB
this prevents problems with ".", ".." and saves code
BO:use global SearchDir, as produced by FindFirst/Next
*/
UBYTE FcbClose(xfcb FAR * lpXfcb)
{
sft FAR *s;
/* Convert to fcb if necessary */
fcb FAR *lpFcb = ExtFcbToFcb(lpXfcb);
/* An already closed FCB can be closed again without error */
if (lpFcb->fcb_sftno == (BYTE) 0xff)
return FCB_SUCCESS;
/* Get the SFT block that contains the SFT */
if ((s = idx_to_sft(lpFcb->fcb_sftno)) == (sft FAR *) - 1)
return FCB_ERROR;
/* change time and set file size */
s->sft_size = lpFcb->fcb_fsize;
if (!(s->sft_flags & SFT_FSHARED))
dos_merge_file_changes(lpFcb->fcb_sftno);
DosSetFtimeSft(lpFcb->fcb_sftno, lpFcb->fcb_date, lpFcb->fcb_time);
if ((CritErrCode = -DosCloseSft(lpFcb->fcb_sftno, FALSE)) == SUCCESS)
{
lpFcb->fcb_sftno = (BYTE) 0xff;
return FCB_SUCCESS;
}
return FCB_ERROR;
}
/* close all files the current process opened by FCBs */
VOID FcbCloseAll()
{
COUNT idx = 0;
sft FAR *sftp;
for (idx = 0; (sftp = idx_to_sft(idx)) != (sft FAR *) - 1; idx++)
if ((sftp->sft_mode & O_FCB) && sftp->sft_psp == cu_psp)
DosCloseSft(idx, FALSE);
}
UBYTE FcbFindFirstNext(xfcb FAR * lpXfcb, BOOL First)
{
void FAR *orig_dta = dta;
BYTE FAR *lpDir;
COUNT FcbDrive;
fcb FAR *lpFcb;
/* First, move the dta to a local and change it around to match */
/* our functions. */
lpDir = dta;
dta = &Dmatch;
/* Next initialze local variables by moving them from the fcb */
lpFcb = CommonFcbInit(lpXfcb, SecPathName, &FcbDrive);
/* Reconstrct the dirmatch structure from the fcb - doesn't hurt for first */
Dmatch.dm_drive = lpFcb->fcb_sftno;
fmemcpy(Dmatch.dm_name_pat, lpFcb->fcb_fname, FNAME_SIZE + FEXT_SIZE);
DosUpFMem((BYTE FAR *) Dmatch.dm_name_pat, FNAME_SIZE + FEXT_SIZE);
Dmatch.dm_attr_srch = wAttr;
Dmatch.dm_entry = lpFcb->fcb_strtclst;
Dmatch.dm_dircluster = lpFcb->fcb_dirclst;
wAttr = D_ALL;
if ((xfcb FAR *) lpFcb != lpXfcb)
{
wAttr = lpXfcb->xfcb_attrib;
fmemcpy(lpDir, lpXfcb, 7);
lpDir += 7;
}
CritErrCode = -(First ? DosFindFirst(wAttr, SecPathName) : DosFindNext());
if (CritErrCode != SUCCESS)
{
dta = orig_dta;
return FCB_ERROR;
}
*lpDir++ = FcbDrive;
fmemcpy(lpDir, &SearchDir, sizeof(struct dirent));
lpFcb->fcb_dirclst = (UWORD) Dmatch.dm_dircluster;
lpFcb->fcb_strtclst = Dmatch.dm_entry;
/*
This is undocumented and seen using Pcwatch and Ramview.
The First byte is the current directory count and the second seems
to be the attribute byte.
*/
lpFcb->fcb_sftno = Dmatch.dm_drive; /* MSD seems to save this @ fcb_date. */
#if 0
lpFcb->fcb_cublock = Dmatch.dm_entry;
lpFcb->fcb_cublock *= 0x100;
lpFcb->fcb_cublock += wAttr;
#endif
dta = orig_dta;
return FCB_SUCCESS;
}
#endif

429
kernel/globals.h Normal file
View File

@ -0,0 +1,429 @@
/****************************************************************/
/* */
/* globals.h */
/* DOS-C */
/* */
/* Global data structures and declarations */
/* */
/* Copyright (c) 1995, 1996 */
/* Pasquale J. Villani */
/* All Rights Reserved */
/* */
/* This file is part of DOS-C. */
/* */
/* DOS-C is free software; you can redistribute it and/or */
/* modify it under the terms of the GNU General Public License */
/* as published by the Free Software Foundation; either version */
/* 2, or (at your option) any later version. */
/* */
/* DOS-C is distributed in the hope that it will be useful, but */
/* WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See */
/* the GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public */
/* License along with DOS-C; see the file COPYING. If not, */
/* write to the Free Software Foundation, 675 Mass Ave, */
/* Cambridge, MA 02139, USA. */
/****************************************************************/
#ifdef VERSION_STRINGS
#ifdef MAIN
static BYTE *Globals_hRcsId =
"$Id: globals.h 1705 2012-02-07 08:10:33Z perditionc $";
#endif
#endif
#include "device.h"
#include "mcb.h"
#include "pcb.h"
#include "date.h"
#include "time.h"
#include "fat.h"
#include "fcb.h"
#include "tail.h"
#include "process.h"
#include "sft.h"
#include "cds.h"
#include "exe.h"
#include "dirmatch.h"
#include "fnode.h"
#include "file.h"
#include "clock.h"
#include "kbd.h"
#include "error.h"
#include "version.h"
#include "network.h"
#include "buffer.h"
#include "dcb.h"
#include "xstructs.h"
/* fatfs.c */
#ifdef WITHFAT32
VOID bpb_to_dpb(bpb FAR * bpbp, REG struct dpb FAR * dpbp, BOOL extended);
#else
VOID bpb_to_dpb(bpb FAR * bpbp, REG struct dpb FAR * dpbp);
#endif
#ifdef WITHFAT32
struct dpb FAR *GetDriveDPB(UBYTE drive, COUNT * rc);
#endif
extern struct dpb
FAR * ASM DPBp; /* First drive Parameter Block */
/* JPP: for testing/debuging disk IO */
/*#define DISPLAY_GETBLOCK */
/* */
/* Convience switch for maintaining variables in a single location */
/* */
#ifdef MAIN
#define GLOBAL
#else
#define GLOBAL extern
#endif
/* */
/* Convience definitions of TRUE and FALSE */
/* */
#ifndef TRUE
#define TRUE (1)
#endif
#ifndef FALSE
#define FALSE (0)
#endif
/* */
/* Constants and macros */
/* */
/* Defaults and limits - System wide */
#define NAMEMAX MAX_CDSPATH /* Maximum path for CDS */
/* internal error from failure or aborted operation */
#define ERROR -1
#define OK 0
/* internal transfer direction flags */
#define XFR_READ 1
#define XFR_WRITE 2
#define XFR_FORCE_WRITE 3
/* flag to update fcb_rndm field */
#define XFR_FCB_RANDOM 4
#define RDONLY 0
#define WRONLY 1
#define RDWR 2
/* special ascii code equates */
#define SPCL 0x00
#define CTL_C 0x03
#define CTL_F 0x06
#define BELL 0x07
#define BS 0x08
#define HT 0x09
#define LF 0x0a
#define CR 0x0d
#define CTL_P 0x10
#define CTL_Q 0x11
#define CTL_S 0x13
#define CTL_Z 0x1a
#define ESC 0x1b
#define CTL_BS 0x7f
#define INS 0x5200
#define DEL 0x5300
#define F1 0x3b00
#define F2 0x3c00
#define F3 0x3d00
#define F4 0x3e00
#define F5 0x3f00
#define F6 0x4000
#define LEFT 0x4b00
#define RIGHT 0x4d00
/* Blockio constants */
#define DSKWRITE 1 /* dskxfr function parameters */
#define DSKREAD 2
#define DSKWRITEINT26 3
#define DSKREADINT25 4
/* NLS character table type */
typedef BYTE *UPMAP;
/* */
/* External Assembly variables */
/* */
extern struct dhdr
FAR ASM clk_dev, /* Clock device driver */
FAR ASM con_dev, /* Console device driver */
FAR ASM prn_dev, /* Generic printer device driver */
FAR ASM aux_dev, /* Generic aux device driver */
FAR ASM blk_dev; /* Block device (Disk) driver */
extern COUNT *error_tos, /* error stack */
disk_api_tos, /* API handler stack - disk fns */
char_api_tos; /* API handler stack - char fns */
extern BYTE FAR _HMATextAvailable, /* first byte of available CODE area */
FAR _HMATextStart[], /* first byte of HMAable CODE area */
FAR _HMATextEnd[]; /* and the last byte of it */
extern
BYTE DosLoadedInHMA; /* if InitHMA has moved DOS up */
extern struct ClockRecord
ASM ClkRecord;
/* */
/* Global variables */
/* */
extern BYTE ASM os_setver_major,/* editable major version number */
ASM os_setver_minor, /* editable minor version number */
ASM os_major, /* major version number */
ASM os_minor, /* minor version number */
ASM rev_number, /* minor version number */
ASM version_flags; /* minor version number */
#ifdef DEBUG
GLOBAL WORD bDumpRegs
#ifdef MAIN
= FALSE;
#else
;
#endif
GLOBAL WORD bDumpRdWrParms
#ifdef MAIN
= FALSE;
#else
;
#endif
#endif
#if 0 /* defined in MAIN.C now to save low memory */
GLOBAL BYTE copyright[] =
"(C) Copyright 1995-2006 Pasquale J. Villani and The FreeDOS Project.\n"
"All Rights Reserved. This is free software and comes with ABSOLUTELY NO\n"
"WARRANTY; you can redistribute it and/or modify it under the terms of the\n"
"GNU General Public License as published by the Free Software Foundation;\n"
"either version 2, or (at your option) any later version.\n";
#endif
GLOBAL const BYTE ASM os_release[]
#ifdef MAIN
= KERNEL_VERSION_STRING
#if 0
"For technical information and description of the DOS-C operating system\n\
consult \"FreeDOS Kernel\" by Pat Villani, published by Miller\n\
Freeman Publishing, Lawrence KS, USA (ISBN 0-87930-436-7).\n\
\n"
#endif
#endif
;
/* Globally referenced variables - WARNING: ORDER IS DEFINED IN */
/* KERNEL.ASM AND MUST NOT BE CHANGED. DO NOT CHANGE ORDER BECAUSE THEY */
/* ARE DOCUMENTED AS UNDOCUMENTED (?) AND HAVE MANY PROGRAMS AND TSRs */
/* ACCESSING THEM */
extern UWORD ASM NetBios;
extern BYTE * ASM net_name;
extern BYTE ASM net_set_count;
extern BYTE ASM NetDelay, ASM NetRetry;
extern UWORD ASM first_mcb, /* Start of user memory */
ASM uppermem_root; /* Start of umb chain (usually 9fff) */
extern char * ASM inputptr; /* pointer to unread CON input */
extern sfttbl FAR * ASM sfthead; /* System File Table head */
extern struct dhdr
FAR * ASM clock, /* CLOCK$ device */
FAR * ASM syscon; /* console device */
extern WORD ASM maxsecsize; /* largest sector size in use (can use) */
extern struct buffer
FAR *ASM firstbuf; /* head of buffers linked list */
enum {LOC_CONV=0, LOC_HMA=1};
extern unsigned char ASM bufloc; /* 0=conv, 1=HMA */
extern void far * ASM deblock_buf; /* pointer to workspace buffer */
GLOBAL char FAR *firstAvailableBuf;
extern struct cds FAR * ASM CDSp; /* Current Directory Structure */
extern
struct cds FAR * ASM current_ldt;
extern LONG ASM current_filepos; /* current file position */
extern sfttbl FAR * ASM FCBp; /* FCB table pointer */
extern WORD ASM nprotfcb; /* number of protected fcbs */
extern UBYTE ASM nblkdev, /* number of block devices */
ASM lastdrive, /* value of last drive */
ASM uppermem_link, /* UMB Link flag */
ASM PrinterEcho; /* Printer Echo Flag */
extern UWORD ASM LoL_nbuffers; /* Number of buffers */
extern struct dhdr
ASM nul_dev;
extern UBYTE ASM mem_access_mode; /* memory allocation scheme */
extern BYTE ASM ErrorMode, /* Critical error flag */
ASM InDOS, /* In DOS critical section */
ASM OpenMode, /* File Open Attributes */
ASM SAttr, /* Attrib Mask for Dir Search */
ASM dosidle_flag, ASM Server_Call, ASM CritErrLocus, ASM CritErrAction,
ASM CritErrClass, ASM VgaSet,
ASM njoined; /* number of joined devices */
extern UWORD ASM Int21AX;
extern COUNT ASM CritErrCode;
extern BYTE FAR * ASM CritErrDev;
extern struct dirent
ASM SearchDir;
extern struct {
COUNT nDrive;
BYTE szName[FNAME_SIZE + 1];
BYTE szExt[FEXT_SIZE + 1];
} ASM FcbSearchBuffer;
extern struct /* Path name parsing buffer */
{
BYTE _PriPathName[128];
} ASM _PriPathBuffer;
#define PriPathName _PriPathBuffer._PriPathName
extern struct /* Alternate path name parsing buffer */
{
BYTE _SecPathName[128];
} ASM _SecPathBuffer;
#define SecPathName _SecPathBuffer._SecPathName
extern UWORD ASM wAttr;
extern BYTE ASM default_drive; /* default drive for dos */
extern dmatch ASM sda_tmp_dm; /* Temporary directory match buffer */
extern dmatch ASM sda_tmp_dm_ren; /* 2nd Temporary directory match buffer */
extern BYTE
ASM internal_data[], /* sda areas */
ASM swap_always[], /* " " */
ASM swap_indos[], /* " " */
ASM tsr, /* true if program is TSR */
ASM break_flg, /* true if break was detected */
ASM break_ena; /* break enabled flag */
extern void FAR * ASM dta; /* Disk transfer area (kludge) */
extern seg ASM cu_psp; /* current psp segment */
extern iregs FAR * ASM user_r; /* User registers for int 21h call */
extern struct dirent /* Temporary directory entry */
ASM DirEntBuffer;
extern fcb FAR * ASM sda_lpFcb; /* Pointer to users fcb */
extern sft FAR * ASM lpCurSft;
extern BYTE ASM verify_ena, /* verify enabled flag */
ASM switchar; /* switch char */
extern UWORD ASM return_code; /* Process termination rets */
extern UBYTE ASM BootDrive, /* Drive we came up from */
ASM CPULevel, /* CPU family, 0=8086, 1=186, ... */
ASM scr_pos; /* screen position for bs, ht, etc */
/*extern WORD
NumFloppies; !!*//* How many floppies we have */
extern keyboard ASM kb_buf;
extern char ASM local_buffer[LINEBUFSIZE0A];
extern UBYTE DiskTransferBuffer[/*SEC_SIZE*/];
extern struct cds
ASM TempCDS;
/* start of uncontrolled variables */
#ifdef DEBUG
GLOBAL iregs error_regs; /* registers for dump */
GLOBAL WORD dump_regs; /* dump registers of bad call */
#endif
/* */
/* Function prototypes - automatically generated */
/* */
#include "proto.h"
/* Process related functions - not under automatic generation. */
/* Typically, these are in ".asm" files. */
VOID ASMCFUNC FAR cpm_entry(VOID)
/*INRPT FAR handle_break(VOID) */ ;
COUNT ASMCFUNC
CriticalError(COUNT nFlag, COUNT nDrive, COUNT nError,
struct dhdr FAR * lpDevice);
VOID ASMCFUNC FAR CharMapSrvc(VOID);
#if 0
VOID ASMCFUNC FAR set_stack(VOID);
VOID ASMCFUNC FAR restore_stack(VOID);
#endif
/*VOID INRPT FAR handle_break(VOID); */
ULONG ASMPASCAL ReadPCClock(VOID);
VOID ASMPASCAL WriteATClock(BYTE *, BYTE, BYTE, BYTE);
VOID ASMPASCAL WritePCClock(ULONG);
intvec getvec(unsigned char);
#ifdef __WATCOMC__
#pragma aux (pascal) ReadPCClock modify exact [ax cx dx]
#pragma aux (pascal) WriteATClock modify exact [ax bx cx dx]
#pragma aux (pascal) WritePCClock modify exact [ax cx dx]
#endif
/* */
/* special word packing prototypes */
/* */
#ifdef NATIVE
#define getlong(vp) (*(UDWORD *)(vp))
#define getword(vp) (*(UWORD *)(vp))
#define getbyte(vp) (*(UBYTE *)(vp))
#define fgetlong(vp) (*(UDWORD FAR *)(vp))
#define fgetword(vp) (*(UWORD FAR *)(vp))
#define fgetbyte(vp) (*(UBYTE FAR *)(vp))
#define fputlong(vp, l) (*(UDWORD FAR *)(vp)=l)
#define fputword(vp, w) (*(UWORD FAR *)(vp)=w)
#define fputbyte(vp, b) (*(UBYTE FAR *)(vp)=b)
#else
UDWORD getlong(VOID *);
UWORD getword(VOID *);
UBYTE getbyte(VOID *);
UDWORD fgetlong(VOID FAR *);
UWORD fgetword(VOID FAR *);
UBYTE fgetbyte(VOID FAR *);
VOID fputlong(VOID FAR *, UDWORD);
VOID fputword(VOID FAR *, UWORD);
VOID fputbyte(VOID FAR *, UBYTE);
#endif
#ifndef __WATCOMC__
#define setvec setvec_resident
#endif
void setvec(unsigned char intno, intvec vector);
/*#define is_leap_year(y) ((y) & 3 ? 0 : (y) % 100 ? 1 : (y) % 400 ? 0 : 1) */
/* ^Break handling */
#ifdef __WATCOMC__
#pragma aux (cdecl) spawn_int23 aborts;
#endif
void ASMCFUNC spawn_int23(void); /* procsupt.asm */
void ASMCFUNC DosIdle_hlt(void); /* dosidle.asm */
GLOBAL BYTE ReturnAnyDosVersionExpected;
GLOBAL BYTE ASM HaltCpuWhileIdle;
/* near fnodes:
* fnode[0] is used internally for almost all cases.
* fnode[1] is only used for:
* 1) rename (target)
* 2) rmdir (checks if the directory to remove is empty)
* 3) commit (copies, than closes fnode[0])
* 3) merge_file_changes (for SHARE)
*/
GLOBAL struct f_node fnode[2];

32
kernel/init-dat.h Normal file
View File

@ -0,0 +1,32 @@
/* Included by initialisation functions */
#if _MSC_VER != 0
extern __segment DosDataSeg; /* serves for all references to the DOS DATA segment
necessary for MSC+our funny linking model
*/
extern __segment DosTextSeg;
#define DOSFAR __based(DosDataSeg)
#define DOSTEXTFAR __based(DosTextSeg)
#elif defined(__TURBOC__)
#define DOSFAR FAR
#define DOSTEXTFAR FAR
#elif defined(__WATCOMC__)
#define DOSFAR FAR
#define DOSTEXTFAR FAR
#elif !defined(I86)
#define DOSFAR
#define DOSTEXTFAR
#else
#error unknown compiler - please adjust
We might even deal with a pre-ANSI compiler. This will certainly not compile.
#endif

336
kernel/init-mod.h Normal file
View File

@ -0,0 +1,336 @@
/* Included by initialisation functions */
#define IN_INIT_MOD
#include "version.h"
#include "date.h"
#include "time.h"
#include "mcb.h"
#include "sft.h"
#include "fat.h"
#include "file.h"
#include "cds.h"
#include "device.h"
#include "kbd.h"
#include "error.h"
#include "fcb.h"
#include "tail.h"
#include "process.h"
#include "pcb.h"
#include "nls.h"
#include "buffer.h"
#include "dcb.h"
#include "lol.h"
#include "init-dat.h"
#include "kconfig.h"
/* MSC places uninitialized data into COMDEF records,
that end up in DATA segment. this can't be tolerated in INIT code.
please make sure, that ALL data in INIT is initialized !!
These guys are marked BSS_INIT to mark that they really should be BSS
but can't be because of MS
*/
#ifdef _MSC_VER
#define BSS_INIT(x) = x
#else
#define BSS_INIT(x)
#endif
extern struct _KernelConfig InitKernelConfig;
/*
* Functions in `INIT_TEXT' may need to call functions in `_TEXT'. The entry
* calls for the latter functions therefore need to be wrapped up with far
* entry points.
*/
#define printf init_printf
#define sprintf init_sprintf
#ifndef __WATCOMC__
#define execrh init_execrh
#define memcpy init_memcpy
#define fmemcpy init_fmemcpy
#define fmemset init_fmemset
#define fmemcmp init_fmemcmp
#define memcmp init_memcmp
#define memset init_memset
#define strchr init_strchr
#define strcpy init_strcpy
#define strlen init_strlen
#define fstrlen init_fstrlen
#endif
#define open init_DosOpen
/* execrh.asm */
#ifndef __WATCOMC__
WORD ASMPASCAL execrh(request FAR *, struct dhdr FAR *);
#endif
/* asmsupt.asm */
VOID ASMPASCAL memset( void *s, int ch, size_t n);
VOID ASMPASCAL fmemset( void FAR *s, int ch, size_t n);
int ASMPASCAL memcmp(const void *m1, const void *m2, size_t n);
int ASMPASCAL fmemcmp(const void FAR *m1, const void FAR *m2, size_t n);
VOID ASMPASCAL memcpy( void *d, const void *s, size_t n);
VOID ASMPASCAL fmemcpy( void FAR *d, const void FAR *s, size_t n);
VOID ASMPASCAL strcpy(char *d, const char *s);
size_t ASMPASCAL strlen(const char *s);
size_t ASMPASCAL fstrlen(const char FAR *s);
char * ASMPASCAL strchr(const char *s, int ch);
#ifdef __WATCOMC__
/* bx, cx, dx and es not used or clobbered for all asmsupt.asm functions except
(f)memchr/(f)strchr (which clobber dx) */
#pragma aux (pascal) pascal_ax modify exact [ax]
#pragma aux (pascal_ax) memset
#pragma aux (pascal_ax) fmemset
#pragma aux (pascal_ax) memcpy
#pragma aux (pascal_ax) fmemcpy
#pragma aux (pascal_ax) memcmp modify nomemory
#pragma aux (pascal_ax) fmemcmp modify nomemory
#pragma aux (pascal_ax) strcpy
#pragma aux (pascal_ax) strlen modify nomemory
#pragma aux (pascal_ax) fstrlen modify nomemory
#pragma aux (pascal) strchr modify exact [ax dx] nomemory
#endif
#undef LINESIZE
#define LINESIZE KBD_MAXLENGTH
/*inithma.c*/
extern BYTE DosLoadedInHMA;
void MoveKernel(unsigned NewKernelSegment);
void setvec(unsigned char intno, intvec vector);
#ifndef __WATCOMC__
#define getvec init_getvec
#endif
intvec getvec(unsigned char intno);
#define GLOBAL extern
#define NAMEMAX MAX_CDSPATH /* Maximum path for CDS */
#define NFILES 16 /* number of files in table */
#define NFCBS 16 /* number of fcbs */
#define NSTACKS 8 /* number of stacks */
#define STACKSIZE 256 /* default stacksize */
#define NLAST 5 /* last drive */
#define NUMBUFF 20 /* Number of track buffers at INIT time */
/* -- must be at least 3 */
#define MAX_HARD_DRIVE 8
#define NDEV 26 /* up to Z: */
#include "config.h" /* config structure */
/* config.c */
extern struct config Config;
VOID PreConfig(VOID);
VOID PreConfig2(VOID);
VOID DoConfig(int pass);
VOID PostConfig(VOID);
VOID configDone(VOID);
VOID FAR * KernelAlloc(size_t nBytes, char type, int mode);
void FAR * KernelAllocPara(size_t nPara, char type, char *name, int mode);
char *strcat(char * d, const char * s);
BYTE * GetStringArg(BYTE * pLine, BYTE * pszString);
void DoInstall(void);
UWORD GetBiosKey(int timeout);
/* diskinit.c */
COUNT dsk_init(VOID);
/* int2f.asm */
COUNT ASMPASCAL Umb_Test(void);
COUNT ASMPASCAL UMB_get_largest(void FAR * driverAddress,
UCOUNT * seg, UCOUNT * size);
#ifdef __WATCOMC__
#pragma aux (pascal) UMB_get_largest modify exact [ax bx cx dx]
#endif
/* inithma.c */
int MoveKernelToHMA(void);
VOID FAR * HMAalloc(COUNT bytesToAllocate);
/* initoem.c */
unsigned init_oem(void);
void movebda(size_t bytes, unsigned new_seg);
unsigned ebdasize(void);
/* dosidle.asm */
extern void ASM DosIdle_hlt(VOID);
/* intr.asm */
/*
* Invoke interrupt "nr" with all registers from *rp loaded
* into the processor registers (except: SS, SP,& flags)
* On return, all processor registers are stored into *rp (including
* flags).
*/
unsigned ASMPASCAL init_call_intr(int nr, iregs * rp);
unsigned ASMPASCAL read(int fd, void *buf, unsigned count);
int ASMPASCAL open(const char *pathname, int flags);
int ASMPASCAL close(int fd);
int ASMPASCAL dup2(int oldfd, int newfd);
ULONG ASMPASCAL lseek(int fd, long position);
seg ASMPASCAL allocmem(UWORD size);
void ASMPASCAL init_PSPSet(seg psp_seg);
int ASMPASCAL init_DosExec(int mode, exec_blk * ep, char * lp);
int ASMPASCAL init_setdrive(int drive);
int ASMPASCAL init_switchar(int chr);
void ASMPASCAL keycheck(void);
void ASMPASCAL set_DTA(void far *dta);
#ifdef __WATCOMC__
#pragma aux (pascal) init_call_intr modify exact [ax]
#pragma aux (pascal) read modify exact [ax bx cx dx]
#pragma aux (pascal) init_DosOpen modify exact [ax bx dx]
#pragma aux (pascal) close modify exact [ax bx]
#pragma aux (pascal) dup2 modify exact [ax bx cx]
#pragma aux (pascal) allocmem modify exact [ax bx]
#pragma aux (pascal) init_PSPSet modify exact [ax bx]
#pragma aux (pascal) init_DosExec modify exact [ax bx dx es]
#pragma aux (pascal) init_setdrive modify exact [ax bx dx]
#pragma aux (pascal) init_switchar modify exact [ax bx dx]
#pragma aux (pascal) keycheck modify exact [ax]
#pragma aux (pascal) set_DTA modify exact [ax bx dx]
#endif
/* irqstack.asm */
VOID ASMCFUNC init_stacks(VOID FAR * stack_base, COUNT nStacks,
WORD stackSize);
/* inthndlr.c */
VOID ASMCFUNC FAR int21_entry(iregs UserRegs);
VOID ASMCFUNC int21_service(iregs far * r);
VOID ASMCFUNC FAR int0_handler(void);
VOID ASMCFUNC FAR int6_handler(void);
VOID ASMCFUNC FAR int19_handler(void);
VOID ASMCFUNC FAR empty_handler(void);
VOID ASMCFUNC FAR int20_handler(void);
VOID ASMCFUNC FAR int21_handler(void);
VOID ASMCFUNC FAR int22_handler(void);
VOID ASMCFUNC FAR int24_handler(void);
VOID ASMCFUNC FAR low_int25_handler(void);
VOID ASMCFUNC FAR low_int26_handler(void);
VOID ASMCFUNC FAR int27_handler(void);
VOID ASMCFUNC FAR int28_handler(void);
VOID ASMCFUNC FAR int29_handler(void);
VOID ASMCFUNC FAR int2a_handler(void);
VOID ASMCFUNC FAR int2f_handler(void);
VOID ASMCFUNC FAR cpm_entry(void);
/* kernel.asm */
VOID ASMCFUNC FAR init_call_p_0(struct config FAR *Config); /* P_0, actually */
/* main.c */
VOID ASMCFUNC FreeDOSmain(void);
BOOL init_device(struct dhdr FAR * dhp, char * cmdLine,
COUNT mode, char FAR **top);
VOID init_fatal(BYTE * err_msg);
/* prf.c */
int VA_CDECL init_printf(CONST char * fmt, ...);
int VA_CDECL init_sprintf(char * buff, CONST char * fmt, ...);
/* procsupt.asm */
VOID ASMCFUNC FAR got_cbreak(void);
/* initclk.c */
extern void Init_clk_driver(void);
extern UWORD HMAFree; /* first byte in HMA not yet used */
extern unsigned CurrentKernelSegment;
extern struct _KernelConfig FAR ASM LowKernelConfig;
extern WORD days[2][13];
extern BYTE FAR *lpTop;
extern BYTE ASM _ib_start[], ASM _ib_end[], ASM _init_end[];
extern UWORD ram_top; /* How much ram in Kbytes */
extern char singleStep;
extern char SkipAllConfig;
extern char master_env[128];
extern struct lol FAR *LoL;
extern struct dhdr DOSTEXTFAR ASM blk_dev; /* Block device (Disk) driver */
extern struct buffer FAR *DOSFAR firstAvailableBuf; /* first 'available' buffer */
extern struct lol ASM FAR DATASTART;
extern BYTE DOSFAR ASM _HMATextAvailable, /* first byte of available CODE area */
FAR ASM _HMATextStart[], /* first byte of HMAable CODE area */
FAR ASM _HMATextEnd[], DOSFAR ASM break_ena; /* break enabled flag */
extern BYTE DOSFAR ASM _InitTextStart[], /* first available byte of ram */
DOSFAR ASM _InitTextEnd[],
DOSFAR ReturnAnyDosVersionExpected,
DOSFAR ASM HaltCpuWhileIdle;
extern BYTE FAR ASM internal_data[];
extern unsigned char FAR ASM kbdType;
extern struct {
char ThisIsAConstantOne;
short TableSize;
struct CountrySpecificInfo C;
} FAR ASM nlsCountryInfoHardcoded;
/*
data shared between DSK.C and INITDISK.C
*/
extern UWORD DOSFAR LBA_WRITE_VERIFY;
/* original interrupt vectors, at 70:xxxx */
extern struct lowvec {
unsigned char intno;
intvec isv;
} DOSTEXTFAR ASM intvec_table[5];
/* floppy parameter table, at 70:xxxx */
extern unsigned char DOSTEXTFAR ASM int1e_table[0xe];
extern char DOSFAR DiskTransferBuffer[/*MAX_SEC_SIZE*/]; /* in dsk.c */
struct RelocationTable {
UBYTE jmpFar;
UWORD jmpOffset;
UWORD jmpSegment;
UBYTE callNear;
UWORD callOffset;
};
struct RelocatedEntry {
UBYTE callNear;
UWORD callOffset;
UBYTE jmpFar;
UWORD jmpOffset;
UWORD jmpSegment;
};
extern struct RelocationTable
DOSFAR ASM _HMARelocationTableStart[],
DOSFAR ASM _HMARelocationTableEnd[];
extern void FAR *DOSFAR ASM XMSDriverAddress;
extern VOID ASMPASCAL FAR _EnableA20(VOID);
extern VOID ASMPASCAL FAR _DisableA20(VOID);
extern void FAR * ASMPASCAL DetectXMSDriver(VOID);
extern int ASMPASCAL init_call_XMScall(void FAR * driverAddress, UWORD ax,
UWORD dx);
#ifdef __WATCOMC__
#pragma aux (pascal) DetectXMSDriver modify exact [ax dx]
#pragma aux (pascal) _EnableA20 modify exact [ax]
#pragma aux (pascal) _DisableA20 modify exact [ax]
#endif
#if defined(WATCOM) && 0
ULONG ASMCFUNC FAR MULULUS(ULONG mul1, UWORD mul2); /* MULtiply ULong by UShort */
ULONG ASMCFUNC FAR MULULUL(ULONG mul1, ULONG mul2); /* MULtiply ULong by ULong */
ULONG ASMCFUNC FAR DIVULUS(ULONG mul1, UWORD mul2); /* DIVide ULong by UShort */
ULONG ASMCFUNC FAR DIVMODULUS(ULONG mul1, UWORD mul2, UWORD * rem); /* DIVide ULong by UShort */
#endif

74
kernel/initclk.c Normal file
View File

@ -0,0 +1,74 @@
/****************************************************************/
/* */
/* initclk.c */
/* */
/* System Clock Driver - initialization */
/* */
/* Copyright (c) 1995 */
/* Pasquale J. Villani */
/* All Rights Reserved */
/* */
/* This file is part of DOS-C. */
/* */
/* DOS-C is free software; you can redistribute it and/or */
/* modify it under the terms of the GNU General Public License */
/* as published by the Free Software Foundation; either version */
/* 2, or (at your option) any later version. */
/* */
/* DOS-C is distributed in the hope that it will be useful, but */
/* WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See */
/* the GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public */
/* License along with DOS-C; see the file COPYING. If not, */
/* write to the Free Software Foundation, 675 Mass Ave, */
/* Cambridge, MA 02139, USA. */
/****************************************************************/
#include "portab.h"
#include "init-mod.h"
#ifdef VERSION_STRINGS
static char *RcsId =
"$Id: initclk.c 1359 2008-03-09 16:11:10Z mceric $";
#endif
/* */
/* WARNING - THIS DRIVER IS NON-PORTABLE!!!! */
/* */
STATIC int InitBcdToByte(int x)
{
return ((x >> 4) & 0xf) * 10 + (x & 0xf);
}
void Init_clk_driver(void)
{
static iregs regsT = {0x200}; /* ah=0x02 */
static iregs regsD = {0x400, 0, 0x1400, 0x101};
/* ah=4, ch=20^ ^cl=0, ^dh=dl=1 (2000/1/1)
* (above date will be set on error) */
iregs dosregs;
init_call_intr(0x1a, &regsT); /* get BIOS time */
init_call_intr(0x1a, &regsD); /* get BIOS date */
/* DosSetDate */
dosregs.a.b.h = 0x2b;
dosregs.c.x = 100 * InitBcdToByte(regsD.c.b.h) /* century */
+ InitBcdToByte(regsD.c.b.l);/* year */
/* A BIOS with y2k (year 2000) bug will always report year 19nn */
if ((dosregs.c.x >= 1900) && (dosregs.c.x < 1980)) dosregs.c.x += 100;
dosregs.d.b.h = InitBcdToByte(regsD.d.b.h); /* month */
dosregs.d.b.l = InitBcdToByte(regsD.d.b.l); /* day */
init_call_intr(0x21, &dosregs);
/* DosSetTime */
dosregs.a.b.h = 0x2d;
dosregs.c.b.l = InitBcdToByte(regsT.c.b.l); /* minutes */
dosregs.c.b.h = InitBcdToByte(regsT.c.b.h); /* hours */
dosregs.d.b.h = InitBcdToByte(regsT.d.b.h); /*seconds */
dosregs.d.b.l = 0;
init_call_intr(0x21, &dosregs);
}

1401
kernel/initdisk.c Normal file

File diff suppressed because it is too large Load Diff

410
kernel/inithma.c Normal file
View File

@ -0,0 +1,410 @@
/****************************************************************/
/* */
/* initHMA.c */
/* DOS-C */
/* */
/* move kernel to HMA area */
/* */
/* Copyright (c) 2001 */
/* tom ehlert */
/* All Rights Reserved */
/* */
/* This file is part of DOS-C. */
/* */
/* DOS-C is free software; you can redistribute it and/or */
/* modify it under the terms of the GNU General Public License */
/* as published by the Free Software Foundation; either version */
/* 2, or (at your option) any later version. */
/* */
/* DOS-C is distributed in the hope that it will be useful, but */
/* WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See */
/* the GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public */
/* License along with DOS-C; see the file COPYING. If not, */
/* write to the Free Software Foundation, 675 Mass Ave, */
/* Cambridge, MA 02139, USA. */
/****************************************************************/
/*
current status:
load FreeDOS high, if DOS=HIGH detected
suppress High Loading, if any SHIFT status detected (for debugging)
if no XMS driver (HIMEM,FDXMS,...) loaded, should work
cooperation with XMS drivers as follows:
copy HMA_TEXT segment up.
after each loaded DEVICE=SOMETHING.SYS, try to request the HMA
(XMS function 0x01).
if no XMS driver detected, during ONFIG.SYS processing,
create a dummy VDISK entry in high memory
this works with
FD FDXMS - no problems detected
MS HIMEM.SYS (from DOS 6.2, 9-30-93)
works if and only if
/TESTMEM:OFF
is given
otherwise HIMEM will TEST AND ZERO THE HIGH MEMORY+HMA.
so, in CONFIG.C, if "HIMEM.SYS" is detected, a "/TESTMEM:OFF"
parameter is forced.
*/
#include "portab.h"
#include "init-mod.h"
#ifdef VERSION_STRINGS
static BYTE *RcsId =
"$Id: inithma.c 956 2004-05-24 17:07:04Z bartoldeman $";
#endif
BYTE DosLoadedInHMA BSS_INIT(FALSE); /* set to TRUE if loaded HIGH */
BYTE HMAclaimed BSS_INIT(0); /* set to TRUE if claimed from HIMEM */
UWORD HMAFree BSS_INIT(0); /* first byte in HMA not yet used */
STATIC void InstallVDISK(void);
#ifdef DEBUG
#ifdef __TURBOC__
#define int3() __int__(3);
#else
void int3()
{
__asm int 3;
}
#endif
#else
#define int3()
#endif
#ifdef DEBUG
#define HMAInitPrintf(x) printf x
#else
#define HMAInitPrintf(x)
#endif
#ifdef DEBUG
VOID hdump(BYTE FAR * p)
{
int loop;
HMAInitPrintf(("%p", p));
for (loop = 0; loop < 16; loop++)
HMAInitPrintf(("%02x ", p[loop]));
printf("\n");
}
#else
#define hdump(ptr)
#endif
#define KeyboardShiftState() (*(BYTE FAR *)(MK_FP(0x40,0x17)))
/*
this tests, if the HMA area can be enabled.
if so, it simply leaves it on
*/
STATIC int EnabledA20(void)
{
return fmemcmp(MK_FP(0, 0), MK_FP(0xffff, 0x0010), 128);
}
int EnableHMA(VOID)
{
_EnableA20();
if (!EnabledA20())
{
printf("HMA can't be enabled\n");
return FALSE;
}
_DisableA20();
#ifdef DEBUG
if (EnabledA20())
{
printf("HMA can't be disabled - no problem for us\n");
}
#endif
_EnableA20();
if (!EnabledA20())
{
printf("HMA can't be enabled second time\n");
return FALSE;
}
HMAInitPrintf(("HMA success - leaving enabled\n"));
return TRUE;
}
/*
move the kernel up to high memory
this is very unportable
if we thin we succeeded, we return TRUE, else FALSE
*/
#define HMAOFFSET 0x20
#define HMASEGMENT 0xffff
int MoveKernelToHMA()
{
void far *xms_addr;
if (DosLoadedInHMA)
{
return TRUE;
}
if ((xms_addr = DetectXMSDriver()) == NULL)
return FALSE;
XMSDriverAddress = xms_addr;
#ifdef DEBUG
/* A) for debugging purpose, suppress this,
if any shift key is pressed
*/
if (KeyboardShiftState() & 0x0f)
{
printf("Keyboard state is %0x, NOT moving to HMA\n",
KeyboardShiftState());
return FALSE;
}
#endif
/* B) check out, if we can have HMA */
if (!EnableHMA())
{
printf("Can't enable HMA area (the famous A20), NOT moving to HMA\n");
return FALSE;
}
/* allocate HMA through XMS driver */
if (HMAclaimed == 0 &&
(HMAclaimed =
init_call_XMScall(xms_addr, 0x0100, 0xffff)) == 0)
{
printf("Can't reserve HMA area ??\n");
return FALSE;
}
MoveKernel(0xffff);
{
/* E) up to now, nothing really bad was done.
but now, we reuse the HMA area. bad things will happen
to find bugs early,
cause INT 3 on all accesses to this area
*/
DosLoadedInHMA = TRUE;
}
/*
on finalize, will install a VDISK
*/
InstallVDISK();
/* report the fact we are running high through int 21, ax=3306 */
LoL->version_flags |= 0x10;
return TRUE;
}
/*
now protect against HIMEM/FDXMS/... by simulating a VDISK
FDXMS should detect us and not give HMA access to ohers
unfortunately this also disables HIMEM completely
so: we install this after all drivers have been loaded
*/
STATIC void InstallVDISK(void)
{
static struct { /* Boot-Sektor of a RAM-Disk */
UBYTE dummy1[3]; /* HIMEM.SYS uses 3, but FDXMS uses 2 */
char Name[5];
BYTE dummy2[3];
WORD BpS;
BYTE dummy3[6];
WORD Sektoren;
BYTE dummy4;
} VDISK_BOOT_SEKTOR = {
{
0xcf, ' ', ' '},
{
'V', 'D', 'I', 'S', 'K'},
{
' ', ' ', ' '}, 512,
{
'F', 'D', 'O', 'S', ' ', ' '}, 128, /* 128*512 = 64K */
' '};
if (!DosLoadedInHMA)
return;
fmemcpy(MK_FP(0xffff, 0x0010), &VDISK_BOOT_SEKTOR,
sizeof(VDISK_BOOT_SEKTOR));
*(WORD FAR *) MK_FP(0xffff, 0x002e) = 1024 + 64;
}
/*
this allocates some bytes from the HMA area
only available if DOS=HIGH was successful
*/
VOID FAR * HMAalloc(COUNT bytesToAllocate)
{
VOID FAR *HMAptr;
if (!DosLoadedInHMA)
return NULL;
if (HMAFree > 0xfff0 - bytesToAllocate)
return NULL;
HMAptr = MK_FP(0xffff, HMAFree);
/* align on 16 byte boundary */
HMAFree = (HMAFree + bytesToAllocate + 0xf) & 0xfff0;
/*printf("HMA allocated %d byte at %x\n", bytesToAllocate, HMAptr); */
fmemset(HMAptr, 0, bytesToAllocate);
return HMAptr;
}
unsigned CurrentKernelSegment = 0;
void MoveKernel(unsigned NewKernelSegment)
{
UBYTE FAR *HMADest;
UBYTE FAR *HMASource;
unsigned len;
unsigned jmpseg = CurrentKernelSegment;
if (CurrentKernelSegment == 0)
CurrentKernelSegment = FP_SEG(_HMATextEnd);
if (CurrentKernelSegment == 0xffff)
return;
HMASource =
MK_FP(CurrentKernelSegment, (FP_OFF(_HMATextStart) & 0xfff0));
HMADest = MK_FP(NewKernelSegment, 0x0000);
len = (FP_OFF(_HMATextEnd) | 0x000f) - (FP_OFF(_HMATextStart) & 0xfff0);
if (NewKernelSegment == 0xffff)
{
HMASource += HMAOFFSET;
HMADest += HMAOFFSET;
len -= HMAOFFSET;
}
HMAInitPrintf(("HMA moving %p up to %p for %04x bytes\n",
HMASource, HMADest, len));
if (NewKernelSegment < CurrentKernelSegment ||
NewKernelSegment == 0xffff)
fmemcpy(HMADest, HMASource, len);
/* else it's the very first relocation: handled by kernel.asm */
HMAFree = (FP_OFF(HMADest) + len + 0xf) & 0xfff0;
/* first free byte after HMA_TEXT on 16 byte boundary */
{
/* D) but it only makes sense, if we can relocate
all our entries to make use of HMA
*/
/* this is for a
call near enableA20
jmp far kernelentry
style table
*/
struct RelocationTable FAR *rp, rtemp;
/* verify, that all entries are valid */
for (rp = _HMARelocationTableStart; rp < _HMARelocationTableEnd; rp++)
{
if (rp->jmpFar != 0xea || /* jmp FAR */
rp->jmpSegment != jmpseg || /* will only relocate HMA_TEXT */
rp->callNear != 0xe8 || /* call NEAR */
0)
{
printf("illegal relocation entry # %d\n",
(FP_OFF(rp) -
FP_OFF(_HMARelocationTableStart)) /
sizeof(struct RelocationTable));
int3();
goto errorReturn;
}
}
/* OK, all valid, go to relocate */
for (rp = _HMARelocationTableStart; rp < _HMARelocationTableEnd; rp++)
{
if (NewKernelSegment == 0xffff)
{
struct RelocatedEntry FAR *rel = (struct RelocatedEntry FAR *)rp;
fmemcpy(&rtemp, rp, sizeof(rtemp));
rel->jmpFar = rtemp.jmpFar;
rel->jmpSegment = NewKernelSegment;
rel->jmpOffset = rtemp.jmpOffset;
rel->callNear = rtemp.callNear;
rel->callOffset = rtemp.callOffset + 5; /* near calls are relative */
}
else
rp->jmpSegment = NewKernelSegment;
}
if (NewKernelSegment == 0xffff)
{
/* jmp far cpm_entry (copy from 0:c0) */
pokeb(0xffff, 0x30 * 4 + 0x10, 0xea);
pokel(0xffff, 0x30 * 4 + 0x11, (ULONG)cpm_entry);
}
}
CurrentKernelSegment = NewKernelSegment;
return;
errorReturn:
for (;;) ;
}

73
kernel/initoem.c Normal file
View File

@ -0,0 +1,73 @@
/****************************************************************/
/* */
/* initoem.c */
/* */
/* OEM Initializattion Functions */
/* */
/* Copyright (c) 1995 */
/* Pasquale J. Villani */
/* All Rights Reserved */
/* */
/* This file is part of DOS-C. */
/* */
/* DOS-C is free software; you can redistribute it and/or */
/* modify it under the terms of the GNU General Public License */
/* as published by the Free Software Foundation; either version */
/* 2, or (at your option) any later version. */
/* */
/* DOS-C is distributed in the hope that it will be useful, but */
/* WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See */
/* the GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public */
/* License along with DOS-C; see the file COPYING. If not, */
/* write to the Free Software Foundation, 675 Mass Ave, */
/* Cambridge, MA 02139, USA. */
/* */
/****************************************************************/
#include "portab.h"
#include "init-mod.h"
#ifdef VERSION_STRINGS
static BYTE *RcsId =
"$Id: initoem.c 1321 2007-05-21 02:16:36Z bartoldeman $";
#endif
#define EBDASEG 0x40e
#define RAMSIZE 0x413
unsigned init_oem(void)
{
iregs r;
init_call_intr(0x12, &r);
return r.a.x;
}
void movebda(size_t bytes, unsigned new_seg)
{
unsigned old_seg = peek(0, EBDASEG);
fmemcpy(MK_FP(new_seg, 0), MK_FP(old_seg, 0), bytes);
poke(0, EBDASEG, new_seg);
poke(0, RAMSIZE, ram_top);
}
unsigned ebdasize(void)
{
unsigned ebdaseg = peek(0, EBDASEG);
unsigned ramsize = ram_top;
if (ramsize == peek(0, RAMSIZE))
if (ramsize * 64 == ebdaseg && ramsize < 640 && peek(0, RAMSIZE) == ramsize)
{
unsigned ebdasz = peekb(ebdaseg, 0);
/* sanity check: is there really no more than 63 KB?
* must be at 640k (all other values never seen and are untested)
*/
if (ebdasz <= 63 && ramsize + ebdasz == 640)
return ebdasz * 1024U;
}
return 0;
}

539
kernel/int2f.asm Normal file
View File

@ -0,0 +1,539 @@
;
; File:
; int2f.asm
; Description:
; multiplex interrupt support code
;
; Copyright (c) 1996, 1998
; Pasquale J. Villani
; All Rights Reserved
;
; This file is part of DOS-C.
;
; DOS-C is free software; you can redistribute it and/or
; modify it under the terms of the GNU General Public License
; as published by the Free Software Foundation; either version
; 2, or (at your option) any later version.
;
; DOS-C is distributed in the hope that it will be useful, but
; WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
; the GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public
; License along with DOS-C; see the file COPYING. If not,
; write to the Free Software Foundation, 675 Mass Ave,
; Cambridge, MA 02139, USA.
;
; $Id: int2f.asm 1591 2011-05-06 01:46:55Z bartoldeman $
;
%include "segs.inc"
%include "stacks.inc"
segment HMA_TEXT
extern _cu_psp:wrt DGROUP
extern _HaltCpuWhileIdle:wrt DGROUP
extern _syscall_MUX14
extern _DGROUP_
global reloc_call_int2f_handler
reloc_call_int2f_handler:
sti ; Enable interrupts
cmp ah,11h ; Network interrupt?
jne Int2f3 ; No, continue
Int2f1:
or al,al ; Installation check?
jz FarTabRetn ; yes, just return
Int2f2:
mov ax,1 ; TE 07/13/01
; at least for redirected INT21/5F44
; --> 2f/111e
; the error code is AX=0001 = unknown function
stc
FarTabRetn:
retf 2 ; Return far
WinIdle: ; only HLT if at haltlevel 2+
push ds
mov ds, [cs:_DGROUP_]
cmp byte [_HaltCpuWhileIdle],2
pop ds
jb FarTabRetn
pushf
sti
hlt ; save some energy :-)
popf
push ds
mov ds, [cs:_DGROUP_]
cmp byte [_HaltCpuWhileIdle],3
pop ds
jb FarTabRetn
mov al,0 ; even admit we HLTed ;-)
jmp short FarTabRetn
Int2f3: cmp ax,1680h ; Win "release time slice"
je WinIdle
cmp ah,16h
je FarTabRetn ; other Win Hook return fast
cmp ah,12h
je IntDosCal ; Dos Internal calls
cmp ax,4a01h
je IntDosCal ; Dos Internal calls
cmp ax,4a02h
je IntDosCal ; Dos Internal calls
%ifdef WITHFAT32
cmp ax,4a33h ; Check DOS version 7
jne Check4Share
xor ax,ax ; no undocumented shell strings
iret
Check4Share:
%endif
cmp ah,10h ; SHARE.EXE interrupt?
je Int2f1 ; yes, do installation check
cmp ah,08h
je DriverSysCal ; DRIVER.SYS calls
cmp ah,14h ; NLSFUNC.EXE interrupt?
jne Int2f?iret ; yes, do installation check
Int2f?14: ;; MUX-14 -- NLSFUNC API
;; all functions are passed to syscall_MUX14
push bp ; Preserve BP later on
Protect386Registers
PUSH$ALL
mov ds, [cs:_DGROUP_]
call _syscall_MUX14
pop bp ; Discard incoming AX
push ax ; Correct stack for POP$ALL
POP$ALL
Restore386Registers
mov bp, sp
or ax, ax
jnz Int2f?14?1 ; must return set carry
;; -6 == -2 (CS), -2 (IP), -2 (flags)
;; current SP = on old_BP
and BYTE [bp-6], 0feh ; clear carry as no error condition
pop bp
iret
Int2f?14?1: or BYTE [bp-6], 1
pop bp
Int2f?iret:
iret
; DRIVER.SYS calls - now only 0803.
DriverSysCal:
extern _Dyn:wrt DGROUP
cmp al, 3
jne Int2f?iret
mov ds, [cs:_DGROUP_]
mov di, _Dyn+2
jmp short Int2f?iret
;**********************************************************************
; internal dos calls INT2F/12xx and INT2F/4A01,4A02 - handled through C
;**********************************************************************
IntDosCal:
; set up register frame
;struct int2f12regs
;{
; [space for 386 regs]
; UWORD es,ds;
; UWORD di,si,bp,bx,dx,cx,ax;
; UWORD ip,cs,flags;
; UWORD callerARG1;
;}
push ax
push cx
push dx
push bx
push bp
push si
push di
push ds
push es
cld
%if XCPU >= 386
%ifdef WATCOM
mov si,fs
mov di,gs
%else
Protect386Registers
%endif
%endif
mov ds,[cs:_DGROUP_]
extern _int2F_12_handler
call _int2F_12_handler
%if XCPU >= 386
%ifdef WATCOM
mov fs,si
mov gs,di
%else
Restore386Registers
%endif
%endif
pop es
pop ds
pop di
pop si
pop bp
pop bx
pop dx
pop cx
pop ax
iret
global SHARE_CHECK
SHARE_CHECK:
mov ax, 0x1000
int 0x2f
ret
; DOS calls this to see if it's okay to open the file.
; Returns a file_table entry number to use (>= 0) if okay
; to open. Otherwise returns < 0 and may generate a critical
; error. If < 0 is returned, it is the negated error return
; code, so DOS simply negates this value and returns it in
; AX.
; STATIC int share_open_check(char * filename,
; /* pointer to fully qualified filename */
; unsigned short pspseg,
; /* psp segment address of owner process */
; int openmode,
; /* 0=read-only, 1=write-only, 2=read-write */
; int sharemode) /* SHARE_COMPAT, etc... */
global SHARE_OPEN_CHECK
SHARE_OPEN_CHECK:
mov es, si ; save si
pop ax ; return address
pop dx ; sharemode;
pop cx ; openmode;
pop bx ; pspseg;
pop si ; filename
push ax ; return address
mov ax, 0x10a0
int 0x2f ; returns ax
mov si, es ; restore si
ret
; DOS calls this to record the fact that it has successfully
; closed a file, or the fact that the open for this file failed.
; STATIC void share_close_file(int fileno) /* file_table entry number */
global SHARE_CLOSE_FILE
SHARE_CLOSE_FILE:
pop ax
pop bx
push ax
mov ax, 0x10a1
int 0x2f
ret
; DOS calls this to determine whether it can access (read or
; write) a specific section of a file. We call it internally
; from lock_unlock (only when locking) to see if any portion
; of the requested region is already locked. If pspseg is zero,
; then it matches any pspseg in the lock table. Otherwise, only
; locks which DO NOT belong to pspseg will be considered.
; Returns zero if okay to access or lock (no portion of the
; region is already locked). Otherwise returns non-zero and
; generates a critical error (if allowcriter is non-zero).
; If non-zero is returned, it is the negated return value for
; the DOS call.
;STATIC int share_access_check(unsigned short pspseg,
; /* psp segment address of owner process */
; int fileno, /* file_table entry number */
; unsigned long ofs, /* offset into file */
; unsigned long len, /* length (in bytes) of region to access */
; int allowcriter) /* allow a critical error to be generated */
global SHARE_ACCESS_CHECK
SHARE_ACCESS_CHECK:
mov ax, 0x10a2
share_common:
push bp
mov bp, sp
push si
push di
mov bx, [bp + 16] ; pspseg
mov cx, [bp + 14] ; fileno
mov si, [bp + 12] ; high word of ofs
mov di, [bp + 10] ; low word of ofs
les dx, [bp + 6] ; len
or ax, [bp + 4] ; allowcriter/unlock
int 0x2f
pop di
pop si
pop bp
ret 14 ; returns ax
; DOS calls this to lock or unlock a specific section of a file.
; Returns zero if successfully locked or unlocked. Otherwise
; returns non-zero.
; If the return value is non-zero, it is the negated error
; return code for the DOS 0x5c call. */
;STATIC int share_lock_unlock(unsigned short pspseg, /* psp segment address of owner process */
; int fileno, /* file_table entry number */
; unsigned long ofs, /* offset into file */
; unsigned long len, /* length (in bytes) of region to lock or unlock */
; int unlock) /* one to unlock; zero to lock */
global SHARE_LOCK_UNLOCK
SHARE_LOCK_UNLOCK:
mov ax,0x10a4
jmp short share_common
; Int 2F Multipurpose Remote System Calls
;
; added by James Tabor jimtabor@infohwy.com
; changed by Bart Oldeman
;
; assume ss == ds after setup of stack in entry
; sumtimes return data *ptr is the push stack word
;
remote_lseek: ; arg is a pointer to the long seek value
mov bx, cx
mov dx, [bx]
mov cx, [bx+2]
; "fall through"
remote_getfattr:
clc ; set to succeed
int 2fh
jc ret_neg_ax
jmp short ret_int2f
remote_lock_unlock:
mov dx, cx ; parameter block (dx) in arg
mov bx, cx
mov bl, [bx + 8] ; unlock or not
mov cx, 1
int 0x2f
jnc ret_set_ax_to_carry
mov ah, 0
jmp short ret_neg_ax
;long ASMPASCAL network_redirector_mx(unsigned cmd, void far *s, void *arg)
global NETWORK_REDIRECTOR_MX
NETWORK_REDIRECTOR_MX:
pop bx ; ret address
pop cx ; stack value (arg); cx in remote_rw
pop dx ; off s
pop es ; seg s
pop ax ; cmd (ax)
push bx ; ret address
call_int2f:
push bp
push si
push di
cmp al, 0fh
je remote_getfattr
mov di, dx ; es:di -> s and dx is used for 1125!
cmp al, 08h
je remote_rw
cmp al, 09h
je remote_rw
cmp al, 0ah
je remote_lock_unlock
cmp al, 21h
je remote_lseek
cmp al, 22h
je remote_process_end
cmp al, 23h
je qremote_fn
push cx ; arg
cmp al, 0ch
je remote_getfree
cmp al, 1eh
je remote_print_doredir
cmp al, 1fh
je remote_print_doredir
int2f_call:
xor cx, cx ; set to succeed; clear carry and CX
int 2fh
pop bx
jnc ret_set_ax_to_cx
ret_neg_ax:
neg ax
ret_int2f:
pop di
pop si
pop bp
ret
ret_set_ax_to_cx: ; ext_open or rw -> status from CX in AX
; otherwise CX was set to zero above
xchg ax, cx ; set ax:=cx (one byte shorter than mov)
jmp short ret_int2f
remote_print_doredir: ; di points to an lregs structure
mov es,[di+0xe]
mov bx,[di+2]
mov cx,[di+4]
mov dx,[di+6]
mov si,[di+8]
lds di,[di+0xa]
clc ; set to succeed
int 2fh
pop bx ; restore stack and ds=ss
push ss
pop ds
jc ret_neg_ax
ret_set_ax_to_carry: ; carry => -1 else 0 (SUCCESS)
sbb ax, ax
jmp short ret_int2f
remote_getfree:
clc ; set to succeed
int 2fh
pop di ; retrieve pushed pointer arg
jc ret_set_ax_to_carry
mov [di],ax
mov [di+2],bx
mov [di+4],cx
mov [di+6],dx
jmp short ret_set_ax_to_carry
remote_rw:
clc ; set to succeed
int 2fh
jc ret_min_dx_ax
xor dx, dx ; dx:ax := dx:cx = bytes read
jmp short ret_set_ax_to_cx
ret_min_dx_ax: neg ax
cwd
jmp short ret_int2f
qremote_fn:
mov bx, cx
lds si, [bx]
jmp short int2f_restore_ds
remote_process_end: ; Terminate process
mov ds, [_cu_psp]
int2f_restore_ds:
clc
int 2fh
push ss
pop ds
jmp short ret_set_ax_to_carry
; extern UWORD ASMPASCAL call_nls(UWORD bp, UWORD FAR *buf,
; UWORD subfct, UWORD cp, UWORD cntry, UWORD bufsize);
extern _nlsInfo:wrt DGROUP
global CALL_NLS
CALL_NLS:
pop es ; ret addr
pop cx ; bufsize
pop dx ; cntry
pop bx ; cp
pop ax ; sub fct
mov ah, 0x14
push es ; ret addr
push bp
mov bp, sp
push si
push di
mov si, _nlsInfo ; nlsinfo
les di, [bp + 4] ; buf
mov bp, [bp + 8] ; bp
int 0x2f
mov dx, bx ; return id in high word
pop di
pop si
pop bp
ret 6
; extern UWORD ASMPASCAL floppy_change(UWORD drives)
global FLOPPY_CHANGE
FLOPPY_CHANGE:
pop cx ; ret addr
pop dx ; drives
push cx ; ret addr
mov ax, 0x4a00
xor cx, cx
int 0x2f
mov ax, cx ; return
ret
;
; Test to see if a umb driver has been loaded.
; if so, retrieve largest available block+size
;
; From RB list and Dosemu xms.c.
;
; Call the XMS driver "Request upper memory block" function with:
; AH = 10h
; DX = size of block in paragraphs
; Return: AX = status
; 0001h success
; BX = segment address of UMB
; DX = actual size of block
; 0000h failure
; BL = error code (80h,B0h,B1h) (see #02775)
; DX = largest available block
;
; (Table 02775)
; Values for XMS error code returned in BL:
; 00h successful
; 80h function not implemented
; B0h only a smaller UMB is available
; B1h no UMBs are available
; B2h UMB segment number is invalid
;
segment INIT_TEXT
; int ASMPASCAL UMB_get_largest(void FAR * driverAddress,
; UCOUNT * seg, UCOUNT * size);
global UMB_GET_LARGEST
UMB_GET_LARGEST:
push bp
mov bp,sp
mov dx,0xffff ; go for broke!
mov ax,1000h ; get the UMBs
call far [bp+8] ; Call the driver
;
; bl = 0xB0 and ax = 0 so do it again.
;
cmp bl,0xb0 ; fail safe
jne umbt_error
and dx,dx ; if it returns a size of zero.
je umbt_error
mov ax,1000h ; dx set with largest size
call far [bp+8] ; Call the driver
cmp ax,1
jne umbt_error
; now return the segment
; and the size
mov cx,bx ; *seg = segment
mov bx, [bp+6]
mov [bx],cx
mov bx, [bp+4] ; *size = size
mov [bx],dx
umbt_ret:
pop bp
ret 8 ; this was called NEAR!!
umbt_error: xor ax,ax
jmp short umbt_ret

2086
kernel/inthndlr.c Normal file

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More