LBA/FCB/FAT/SYS/Ctrl-C/ioctl fixes + memory savings

git-svn-id: https://svn.code.sf.net/p/freedos/svn/kernel/trunk@260 6ac86273-5f31-0410-b378-82cca8765d1b
This commit is contained in:
Bart Oldeman 2001-07-09 22:19:33 +00:00
parent 68375764dd
commit c1b1896480
38 changed files with 3084 additions and 1172 deletions

View File

@ -5,6 +5,9 @@ rem batch file to build everything
rem $Id$
rem $Log$
rem Revision 1.5 2001/07/09 22:19:30 bartoldeman
rem LBA/FCB/FAT/SYS/Ctrl-C/ioctl fixes + memory savings
rem
rem Revision 1.4 2001/03/22 04:13:30 bartoldeman
rem Change LF to CR/LF in batch files.
rem
@ -78,6 +81,16 @@ if errorlevel 1 goto abort
cd ..\kernel
%MAKE% -fkernel.mak production
if errorlevel 1 goto abort
cd..
:- if you like, put some finalizing commands (like copy to floppy)
:- into build2.bat
if exist build2.bat call build2
goto end
:abort
cd ..

View File

@ -20,6 +20,11 @@ You will also need to download the latest version of NASM and Turbo C
where) and then be sure to edit the CONFIG.MAK file to reflect where
you put the tools.
*TE******* Make sure to use the NASMR version, as the DosExtender version
_seems_ to produce wrong code. the tested version is
NASM98R, 06/04/99, 202.606 bytes.
This program will now compile with Turbo C 2.01 (now freely
available!), Turbo C 3.0, Borland C 4.51 & 5.01. It should work with
other Borland compilers as well.
@ -65,6 +70,9 @@ component. Study the makefile to better understand this.
$Id$
$Log$
Revision 1.4 2001/07/09 22:19:33 bartoldeman
LBA/FCB/FAT/SYS/Ctrl-C/ioctl fixes + memory savings
Revision 1.3 2000/08/15 03:42:17 jhall1
update to the bugs.txt file to point the user to the bug database at
the FreeDOS web site (http://www.freedos.org/bugs)

View File

@ -1,3 +1,51 @@
2001 Jul 9 - Build 2024/d
-------- Bart Oldeman (bart.oldeman@bristol.ac.uk)
+ fixes Bart:
* fixed Ctrl-C (Ctrl-S and Ctrl-Q still missing).
* ioctl EOF fix (DJGPP less&gdb problem reported by Martin Stromberg)
* INT21/AH=29 (Parse Filename into FCB) fix (NC problem reported
by Ken Martwick) with clean up from Tom.
* ioctl should do a media_check before calling the block driver:
this fixes bug #726 (first dir gave serial no. 1234-5678).
* initdisk.c now uses the init data segment.
+ fixes Tom:
* fixes for INT21/AH=32; this should cure the problems with
Brian's new format.
* more SYS fixes.
+ added Tom:
* some more diagnostics (123) to aid finding bugs when booting from
a hard disk.
from 2001 jun 23 : KE2024BP
+ fixes Tom:
* FAT FS: would not expand files correctly, if lseek()
beyond EOF (see also relnotes.txt)
* FcbFindFirst/Next made compatible with MSDOS CHKDSK
* saved even more bytes (now 24 buffers in HMA :-)
from KE2024BM
+ added Tom:
* a mechanism, to regain near data (like miarray, bpbarray,...)
this is somewhat braindamaging, moving the kernel up and down,
working with different CS/DS combinations, but somehow working, :-)
miarray allocated, using this mechanism.
* made f_nodes near (2 K saving in HMA_TEXT)
this technic might as well applied to CDs, DPB, sft's, ...
this even saves a few bytes on stack :-)
from 2001 May 21: Build2024L
+ Fixes Tom:
* Clustersize 64K made working (one small ULONG was missing)
* check for drive existence for INT25/26
* NDEV = max number of possible harddisk partitions bumped
from 8 to 20 (my testconfiguration has 13)
+ Added tom:
* LBA support for disks > 8GB (with the help from Brian
Reifsnyder, see also relnotes.txt)
* moved initialization for DISK (partition scanning) to INIT_CODE
2001 Jun 2 - Build 2024
-------- Bart Oldeman (bart.oldeman@bristol.ac.uk)
+ Fixes Tom:
@ -11,10 +59,12 @@
while config.sys parsing.
+ Fixes Bart:
* INT 21 0A - Dos Buffered Input reworked
* init_PSPSet() fix for setting the PSP
+ Added tom:
* slighly better buffer handling (search BFR_UNCACHE)
now go more FAT+DIR sectors, less DATA sectors into cache
* dos_mkdir tuned (was ~0.5 sec on 64K cluster partitions)
2001 Apr 29 - Build 2024
-------- Bart Oldeman (bart.oldeman@bristol.ac.uk)
+ Fixes Bart:
@ -37,30 +87,6 @@
* Default lastdrive should be 5 (E) not 6 (F).
* fixed not ignoring whitespace after '=' in config.sys
* noted INT21/AX=3800 bug for getting the country. Put in a workaround for now.
2001 Apr 29 - Build 2024
-------- Bart Oldeman (bart.oldeman@bristol.ac.uk)
+ Fixes Bart:
* fixed the "TYPE > FOO.TXT" poor man's editor.
* use "fast console output" (int 29) when applicable.
* moved 5 FILES to DOS DS:00CC and fixed the SFT linked list.
* cleaned up findfirst/findnext for redirected drives.
* moved IO segments to 0x70 as this matches other DOS'es.
Tom:
* more VDISK changes (changed slightly by Bart)
* check for presence of A:/B: (changed by Bart to use the BIOS equipment flag
from INT11 instead of INT13).
* added F5/F8 stepping through config.sys; default SHELL=COMMAND.COM /P/E:256
Use ESC to stop single stepping, F5 to skip remaining config.sys/autoexec.bat.
* new sys: uses INT25/26 instead of the low level INT13 related kernel code from
floppy.asm (see also comments in sys.c) + a few fixes (also boot.asm related)
from Bart.
* Hopefully fixed DateTime Changed + ATTRIB |= ARCHIVE bug.
* Combined clk and blk driver entries as much as possible.
* cleaned up dsk.c and saved more bytes.
Przemyslaw Czerpak:
* Default lastdrive should be 5 (E) not 6 (F).
* fixed not ignoring whitespace after '=' in config.sys
* noted INT21/AX=3800 bug for getting the country. Put in a workaround for now.
2001 Apr 21 - Build 2024
-------- Bart Oldeman (bart.oldeman@bristol.ac.uk)
+ Fixes Tom:

177
docs/relnotes.txt Normal file
View File

@ -0,0 +1,177 @@
Release notes for kernel 2024d and its development predecessors
2024BL,M,N: we think that by now we have ironed out most of these
bugs, but be careful nonetheless.
About KE2024BL:
*********************************************************
* *
* THIS IS A BETA RELEASE *
* *
* BE CAREFUL *
* *
* SAVE YOUR DATA. SAVE OFTEN. *
* *
* THIS RELEASE MAY DESTROY YOUR DISK COMPLETELY *
* *
*********************************************************
KE2024BL introduced full LBA support; i.e. disk may be up to
2^32 * 512 bytes = 2000 GB large.
also new is the working of 64K FAT clustersize for a max
logical disksize of 2^16 * 64K = ~4 GB.
KE2024BM is its follower, with some more bugfixes.
How dangerous is it?
The KE2024BL kernel has been send by private mail to some of us,
has been tested on 7 maschines with and without LBA support.
No errors (other then the known bugs) were reported.
And KE2024BM is pretty conservativ, before it accepts and uses
a disk.
the main problem may be, that a disk recognized by an older
kernel, will no longer work with the new one, because strange
partitioning scemes, although nothing like that has been reported.
So, if after booting you see all your drives, containing resonable
data, it should be pretty save to use.
Be a bit careful, nevertheless.
full LBA support and 64K FAT clustersize for a max
logical disksize of 2^16 * 64K = ~4 GB
were have been tested in the following way:
on my 30GB disk, a partition with 1.7 GB for 32K clusters and
3.5 GB for 64K clusters created. the 3.5 GB partition was created,
using Win2K.
my WINNT directory (~350MB) was copied there - (using VC)
once for 32K,
for 64K,
xcopy c:\WINNT j:\WINNT /s
xcopy j:\WINNT j:\WINN1 /s
xcopy j:\WINN1 j:\WINN2 /s
xcopy j:\WINN2 j:\WINN3 /s
xcopy j:\WINN3 j:\WINN4 /s
to fill the disk.
the 350 MB files (WINNT for 32K, WINN4 for 64K) were then
compared to the original file. they were identical.
no, not all files were copied due to restrictions in MAX_PATH_SIZE,
but the files, that were copied, compared ok.
the files were also readable with WinNT, and they were identical, too.
WinNT chkdsk was content with the disk.
next, the kernel source was copied to this drive, compiled,
and verified.
so, it _seems_ to work for me.
known issues:
* VC will say, that the disk has size of 0 byte, with 0 byte free.
this is not a kernel bug.
VC simply multiplies BytesPerSec*SecPerCluster, gets
128*512 = 0x10000, and saves the low part, which is 0.
* the behaviour for filesize at or above 2GB (where the sign
gets negative) is completely untested. test it, if you like
* there are some bugs, when the pathlength is around 64.
this may lead to incontinent (sorry, inconsistent) behaviour,
like
you can MKDIR a directory, but not CHDIR to it
and similiar things.
some of them found and removed, but there are probably more
to be found yet. fortunately, none lead to data loss :-)
*********************************************************
* *
* BE CAREFUL *
* AND SAVE YOUR DATA. SAVE OFTEN. *
* *
*********************************************************
Bugs and fixes in the FAT filesystem (tested on KE2024BN)
---------------------------------------------------------
KE2024BM:
Disk Full not detected in a compatible way.
it was possible to create a directory(pointing to nowhere),
even if disk was full.
---------------------------------------------------------
DosGetFreeSpace is wrong (verified on KE2022, too):
when creating files, the 2nd and following clusters are
counted twice when created.
simply copy one file to another, delete 2nd file;
watch free space before and after.
corrected in KE2024BP
---------------------------------------------------------
#include <stdio.h>
#include <io.h>
main()
{
FILE *fd = fopen("test.dat","w");
int fdn = fileno(fd);
lseek(fdn,10000,SEEK_CUR);
write(fdn,"hello world",10);
}
creates file of DirSize 10010 bytes, but reserves
a single FAT entry cluster
this is obviously nonsense.
and there is no "hello world" in it :-(
cured by FATFS.C,
/* Now that we've found a free FAT entry, mark it as the last */
/* entry and save it. */
/* BUG!! this caused wrong allocation, if file was created,
then seeked, then written */
+ fnp->f_cluster =
fnp->f_dir.dir_start = free_fat;
--------------------------------------------------------------
when a big file is created, and cut afterward, the filespace is NOT freed
try:
copy command.com xx
dir
echo >xx
dir
and compare disk free info.
the space is freed, however, if xx is deleted after that.
--------------------------------------------------------------
regards
tom ehlert (tom.ehlert@ginko.de)

View File

@ -30,6 +30,13 @@
; $Id$
;
; $Log$
; Revision 1.7 2001/07/09 22:19:33 bartoldeman
; LBA/FCB/FAT/SYS/Ctrl-C/ioctl fixes + memory savings
;
;
; Revision 1.7 2001/04/29 brianreifsnyder
; Added phase 1 support for LBA hard drives
;
; Revision 1.6 2001/04/22 01:19:33 bartoldeman
; Avoid sys warning and have a VDISK signature in the HMA
;
@ -285,7 +292,7 @@ fl_error:
%if 0
global _fl_format
_fl_format:
@ -315,3 +322,136 @@ _fl_nrdrives:
fl_nrd1:
pop di
ret
%endif
; ---------------------------------------------------------------------------
; LBA Specific Code
;
;
; Added by: Brian E. Reifsnyder
; ---------------------------------------------------------------------------
;
;
; Check for Enhanced Disk Drive support (EDD). If EDD is supported then
; LBA can be utilized to access the hard disk.
;
; unsigned int lba_support(WORD hard_disk_number)
;
; returns TRUE if LBA can be utilized
;
%if 0
global _fl_lba_support
_fl_lba_support:
push bp ; C entry
mov bp,sp
mov dl,[bp+4] ; get the drive number
mov ah,41h ; cmd CHECK EXTENSIONS PRESENT
mov bx,55aah
int 13h ; check for int 13h extensions
jc fl_lba_support_no_lba
; if carry set, don't use LBA
cmp bx,0aa55h
jne fl_lba_support_no_lba
; if bx!=0xaa55, don't use LBA
test cl,01h
jz fl_lba_support_no_lba
; if DAP cannot be used, don't use
; LBA
mov ax,0001h ; return TRUE (LBA supported)
pop bp ; C exit
ret
fl_lba_support_no_lba
xor ax,ax ; return FALSE (LBA not supported)
pop bp ; C exit
ret
;
; Read Sectors
;
; COUNT fl_lba_read(WORD drive, WORD dap_segment, WORD dap_offset);
;
; Reads one or more sectors.
;
; Returns 0 if successful, error code otherwise.
;
;
; Write Sectors
;
; COUNT fl_lba_write(WORD drive, WORD dap_segment, WORD dap_offset);
;
; Writes one or more sectors.
;
; Returns 0 if successful, error code otherwise.
;
global _fl_lba_read
_fl_lba_read:
mov ah,42h ; cmd READ
jmp short fl_lba_common
global _fl_lba_write
_fl_lba_write:
mov ax,4300h ; cmd WRITE without verify
jmp short fl_lba_common
global _fl_lba_write_and_verify
_fl_lba_write_and_verify:
mov ax,4302h ; cmd WRITE with VERIFY
jmp short fl_lba_common ; This has been added for
; possible future use
global _fl_lba_verify
_fl_lba_verify:
mov ah,44h ; cmd VERIFY
fl_lba_common:
push bp ; C entry
mov bp,sp
push ds
mov dl,[bp+4] ; get the drive (if or'ed 80h its
; hard drive.
lds si,[bp+6] ; get far dap pointer
int 13h ; read from/write to drive
mov al,ah ; place any error code into al
xor ah,ah ; zero out ah
pop ds
pop bp
ret
%endif
; COUNT fl_lba_ReadWrite(BYTE drive, UWORD mode, VOID FAR *dap_p)
;
; Returns 0 if successful, error code otherwise.
;
global _fl_lba_ReadWrite
_fl_lba_ReadWrite:
push bp ; C entry
mov bp,sp
push ds
push si ; wasn't in kernel < KE2024Bo6!!
mov dl,[bp+4] ; get the drive (if or'ed 80h its
mov ax,[bp+6] ; get the command
lds si,[bp+8] ; get far dap pointer
int 13h ; read from/write to drive
mov al,ah ; place any error code into al
xor ah,ah ; zero out ah
pop si
pop ds
pop bp
ret

View File

@ -36,6 +36,9 @@ static BYTE *dirmatch_hRcsId = "$Id$";
/*
* $Log$
* Revision 1.5 2001/07/09 22:19:33 bartoldeman
* LBA/FCB/FAT/SYS/Ctrl-C/ioctl fixes + memory savings
*
* Revision 1.4 2001/04/16 01:45:26 bartoldeman
* Fixed handles, config.sys drivers, warnings. Enabled INT21/AH=6C, printf %S/%Fs
*
@ -115,6 +118,7 @@ typedef struct
f_filler:11; /* TC 2.01 */
}
dm_flags; /* file flags */
UWORD dm_dirstart;
BYTE dm_attr_fnd; /* found file attribute */

View File

@ -36,6 +36,9 @@ static BYTE *fat_hRcsId = "$Id$";
/*
* $Log$
* Revision 1.7 2001/07/09 22:19:33 bartoldeman
* LBA/FCB/FAT/SYS/Ctrl-C/ioctl fixes + memory savings
*
* Revision 1.6 2001/04/15 03:21:50 bartoldeman
* See history.txt for the list of fixes.
*
@ -123,8 +126,8 @@ static BYTE *fat_hRcsId = "$Id$";
#define FAT_MAGIC16 ((unsigned)65526l)
#define FAT_MAGIC32 268435456l
#define ISFAT32(dpbp) (((dpbp)->dpb_size)>FAT_MAGIC16 || ((dpbp)->dpb_size)<=FAT_MAGIC32 )
#define ISFAT16(dpbp) (((dpbp)->dpb_size)>FAT_MAGIC || ((dpbp)->dpb_size)<=FAT_MAGIC16 )
#define ISFAT32(dpbp) (((dpbp)->dpb_size)>FAT_MAGIC16 && ((dpbp)->dpb_size)<=FAT_MAGIC32 )
#define ISFAT16(dpbp) (((dpbp)->dpb_size)>FAT_MAGIC && ((dpbp)->dpb_size)<=FAT_MAGIC16 )
#define ISFAT12(dpbp) (((dpbp)->dpb_size)<=FAT_MAGIC)
/* FAT file system directory entry */

View File

@ -36,6 +36,9 @@ static BYTE *fcb_hRcsId = "$Id$";
/*
* $Log$
* Revision 1.4 2001/07/09 22:19:33 bartoldeman
* LBA/FCB/FAT/SYS/Ctrl-C/ioctl fixes + memory savings
*
* Revision 1.3 2000/05/25 20:56:19 jimtabor
* Fixed project history
*
@ -144,7 +147,7 @@ typedef struct
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; /* offset 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 */

View File

@ -36,6 +36,9 @@ static BYTE *fnode_hRcsId = "$Id$";
/*
* $Log$
* Revision 1.7 2001/07/09 22:19:33 bartoldeman
* LBA/FCB/FAT/SYS/Ctrl-C/ioctl fixes + memory savings
*
* Revision 1.6 2001/06/03 14:16:17 bartoldeman
* BUFFERS tuning and misc bug fixes/cleanups (2024c).
*
@ -129,4 +132,4 @@ struct f_node
UWORD f_boff; /* the byte in the cluster */
};
typedef struct f_node FAR * f_node_ptr;
typedef struct f_node * f_node_ptr;

View File

@ -35,6 +35,9 @@ static BYTE *sft_hRcsId = "$Id$";
/*
* $Log$
* Revision 1.4 2001/07/09 22:19:33 bartoldeman
* LBA/FCB/FAT/SYS/Ctrl-C/ioctl fixes + memory savings
*
* Revision 1.3 2000/05/25 20:56:19 jimtabor
* Fixed project history
*
@ -114,6 +117,7 @@ typedef struct
struct dhdr FAR *
_sft_dev; /* device driver for char dev */
}
sft_dcb_or_dev;
WORD sft_stclust; /* Starting cluster */
time sft_time; /* File time */

View File

@ -44,4 +44,4 @@ static BYTE *date_hRcsId = "$Id$";
#define REVISION_MINOR 1
#define REVISION_SEQ 24
#define BUILD 2024
#define SUB_BUILD "c"
#define SUB_BUILD "d"

View File

@ -34,9 +34,12 @@
#ifdef VERSION_STRINGS
static BYTE *blockioRcsId = "$Id$";
#endif
/*
* $Log$
* Revision 1.11 2001/07/09 22:19:33 bartoldeman
* LBA/FCB/FAT/SYS/Ctrl-C/ioctl fixes + memory savings
*
* Revision 1.10 2001/06/03 14:16:17 bartoldeman
* BUFFERS tuning and misc bug fixes/cleanups (2024c).
*
@ -553,10 +556,13 @@ UWORD dskxfer(COUNT dsk, ULONG blkno, VOID FAR * buf, UWORD numblocks, COUNT mod
REG struct dpb FAR *dpbp = CDSp->cds_table[dsk].cdsDpb;
if ((UCOUNT)dsk >= lastdrive ||
!(CDSp->cds_table[dsk].cdsFlags & CDSPHYSDRV))
if ((UCOUNT)dsk >= lastdrive )
{
return -1; /* illegal command */
return 0x0201; /* illegal command */
}
if (!(CDSp->cds_table[dsk].cdsFlags & CDSPHYSDRV))
{
return 0x0201; /* illegal command */
}
#if 1
@ -574,10 +580,19 @@ UWORD dskxfer(COUNT dsk, ULONG blkno, VOID FAR * buf, UWORD numblocks, COUNT mod
{
IoReqHdr.r_length = sizeof(request);
IoReqHdr.r_unit = dpbp->dpb_subunit;
IoReqHdr.r_command =
mode == DSKWRITE ?
(verify_ena ? C_OUTVFY : C_OUTPUT)
: C_INPUT;
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_trans = (BYTE FAR *) buf;
@ -592,11 +607,24 @@ UWORD dskxfer(COUNT dsk, ULONG blkno, VOID FAR * buf, UWORD numblocks, COUNT mod
execrh((request FAR *) & IoReqHdr, dpbp->dpb_device);
if (!(IoReqHdr.r_status & S_ERROR) && (IoReqHdr.r_status & S_DONE))
break;
else
{
/* 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);
/* Changed 9/4/00 BER */
return (IoReqHdr.r_status);
/* Skip the abort, retry, fail code...it needs fixed...BER */
/* End of change */
@ -616,8 +644,8 @@ UWORD dskxfer(COUNT dsk, ULONG blkno, VOID FAR * buf, UWORD numblocks, COUNT mod
default:
goto loop;
}
}
}
} /* retry loop */
/* *** Changed 9/4/00 BER */
return 0; /* Success! Return 0 for a successful operation. */
/* End of change */

View File

@ -29,6 +29,9 @@
#include "portab.h"
#include "init-mod.h"
#include "dyndata.h"
/*
These are the far variables from the DOS data segment that we need here. The
@ -39,7 +42,7 @@
-- Bart
*/
extern struct buffer FAR * FAR lastbuf;/* tail of ditto */
extern struct f_node FAR * FAR f_nodes; /* pointer to the array */
extern f_node_ptr FAR f_nodes; /* pointer to the array */
extern UWORD FAR f_nodes_cnt, /* number of allocated f_nodes */
FAR first_mcb; /* Start of user memory */
@ -78,8 +81,17 @@ extern UWORD FAR ram_top, /* How much ram in Kbytes
static BYTE *RcsId = "$Id$";
#endif
#ifdef DEBUG
#define DebugPrintf(x) printf x
#else
#define DebugPrintf(x)
#endif
/*
* $Log$
* Revision 1.24 2001/07/09 22:19:33 bartoldeman
* LBA/FCB/FAT/SYS/Ctrl-C/ioctl fixes + memory savings
*
* Revision 1.23 2001/06/03 14:16:17 bartoldeman
* BUFFERS tuning and misc bug fixes/cleanups (2024c).
*
@ -374,6 +386,8 @@ INIT void PreConfig(void)
UmbState = 0;
/* Initialize the base memory pointers */
DynFree(0);
if ( HMATextIsAvailable )
@ -391,9 +405,7 @@ INIT void PreConfig(void)
/* the dms_scratch buffer is statically allocated
in the DSK module */
/* dma_scratch = (BYTE FAR *) KernelAllocDma(BUFFERSIZE); */
#ifdef DEBUG
/* printf("Preliminary DMA scratchpad allocated at 0x%p\n",dma_scratch);*/
#endif
/* DebugPrintf(("Preliminary DMA scratchpad allocated at 0x%p\n",dma_scratch));*/
@ -405,8 +417,12 @@ INIT void PreConfig(void)
#endif
/* Initialize the file table */
f_nodes = (struct f_node FAR *)
KernelAlloc(Config.cfgFiles * sizeof(struct f_node));
/* f_nodes = (f_node_ptr)
KernelAlloc(Config.cfgFiles * sizeof(struct f_node));*/
f_nodes = (f_node_ptr)
DynAlloc("f_nodes", Config.cfgFiles , sizeof(struct f_node));
f_nodes_cnt = Config.cfgFiles;
/* sfthead = (sfttbl FAR *)&basesft; */
@ -427,11 +443,11 @@ INIT void PreConfig(void)
KernelAlloc(blk_dev.dh_name[0]*sizeof(struct dpb));
#ifdef DEBUG
printf("Preliminary f_node allocated at at 0x%p\n",f_nodes);
printf("Preliminary FCB table allocated at 0x%p\n",FCBp);
printf("Preliminary sft table allocated at 0x%p\n",sfthead->sftt_next);
printf("Preliminary CDS table allocated at 0x%p\n",CDSp);
printf("Preliminary DPB table allocated at 0x%p\n",DPBp);
printf("Preliminary:\n f_node 0x%p",f_nodes);
/* printf(" FCB table 0x%p\n",FCBp);*/
printf(" sft table 0x%p\n",sfthead->sftt_next);
printf(" CDS table 0x%p\n",CDSp);
printf(" DPB table 0x%p\n",DPBp);
#endif
/* Done. Now initialize the MCB structure */
@ -467,14 +483,45 @@ INIT void PostConfig(void)
if (lastdrive < nblkdev )
lastdrive = nblkdev ;
/* initialize NEAR allocated things */
DynFree(Config.cfgFiles * sizeof(struct f_node));
/* Initialize the file table */
f_nodes = (f_node_ptr)
DynAlloc("f_nodes", Config.cfgFiles , sizeof(struct f_node));
f_nodes_cnt = Config.cfgFiles; /* and the number of allocated files */
/* Initialize the base memory pointers from last time. */
/*
if the kernel could be moved to HMA, everything behind the dynamic
near data is free.
otherwise, the kernel is moved down - behind the dynamic allocated data,
and allocation starts after the kernel.
*/
if ( HMATextIsAvailable )
lpOldLast = lpBase = AlignParagraph((BYTE FAR *) & _HMATextStart);
else
lpOldLast = lpBase = AlignParagraph((BYTE FAR *) & _InitTextStart);
lpBase = AlignParagraph((BYTE FAR *)DynLast()+0x0f);
else
{
lpBase = AlignParagraph((BYTE FAR *)DynLast()+0x0f);
DebugPrintf(("HMA not available, moving text to %x\n",FP_SEG(lpBase)));
MoveKernel(FP_SEG(lpBase));
lpBase = AlignParagraph((BYTE FAR *)lpBase + HMAFree + 0x0f);
DebugPrintf(("kernel is low, start alloc at %p",lpBase));
}
DebugPrintf(("starting FAR allocations at %p\n",lpBase));
lpOldLast = lpBase;
/* Begin by initializing our system buffers */
/* dma_scratch = (BYTE FAR *) KernelAllocDma(BUFFERSIZE); */
@ -492,11 +539,6 @@ INIT void PostConfig(void)
/* printf("%d buffers allocated at 0x%p\n", Config.cfgBuffers,buffers); */
#endif
/* Initialize the file table */
f_nodes = (struct f_node FAR *)
KernelAlloc(Config.cfgFiles * sizeof(struct f_node));
f_nodes_cnt = Config.cfgFiles; /* and the number of allocated files */
/* sfthead = (sfttbl FAR *)&basesft; */
/* FCBp = (sfttbl FAR *)&FcbSft; */
/* FCBp = (sfttbl FAR *)
@ -516,25 +558,20 @@ INIT void PostConfig(void)
#ifdef DEBUG
printf("f_node allocated at 0x%p\n",f_nodes);
printf("FCB table allocated at 0x%p\n",FCBp);
printf("sft table allocated at 0x%p\n",sfthead->sftt_next);
printf("CDS table allocated at 0x%p\n",CDSp);
printf("DPB table allocated at 0x%p\n",DPBp);
printf("Final: \n f_node 0x%p\n",f_nodes);
/* printf(" FCB table 0x%p\n",FCBp);*/
printf(" sft table 0x%p\n",sfthead->sftt_next);
printf(" CDS table 0x%p\n",CDSp);
printf(" DPB table 0x%p\n",DPBp);
#endif
if (Config.cfgStacks)
{
VOID FAR *stackBase = KernelAlloc(Config.cfgStacks * Config.cfgStackSize);
init_stacks(stackBase, Config.cfgStacks, Config.cfgStackSize);
#ifdef DEBUG
printf("Stacks allocated at %p\n",stackBase);
#endif
DebugPrintf(("Stacks allocated at %p\n",stackBase));
}
#ifdef DEBUG
printf("Allocation completed: top at 0x%p\n",lpBase);
#endif
DebugPrintf(("Allocation completed: top at 0x%p\n",lpBase));
}
@ -546,9 +583,9 @@ INIT VOID configDone(VOID)
if (lastdrive < nblkdev) {
#ifdef DEBUG
printf("lastdrive %c too small upping it to: %c\n", lastdrive + 'A', nblkdev + 'A' -1);
#endif /* DEBUG */
DebugPrintf(("lastdrive %c too small upping it to: %c\n", lastdrive + 'A', nblkdev + 'A' -1));
lastdrive = nblkdev;
CDSp = (cdstbl FAR *)
KernelAlloc(0x58 * lastdrive);
@ -568,21 +605,19 @@ INIT VOID configDone(VOID)
if(umb_start != FP_SEG(upBase) ){
/* make last block normal with SC for the devices */
UCOUNT umr_new = FP_SEG(upBase) + ((FP_OFF(upBase) + 0x0f) >> 4);
UCOUNT umr_new = FP_SEG(upBase) + ((FP_OFF(upBase) + 0x0f) >> 4);
mumcb_init((mcb FAR *) (MK_FP(uppermem_root, 0)), umr_new - uppermem_root - 1);
mumcb_init((mcb FAR *) (MK_FP(uppermem_root, 0)), umr_new - uppermem_root - 1);
uppermem_root = umr_new;
zumcb_init((mcb FAR *) (MK_FP(uppermem_root, 0)),
uppermem_root = umr_new;
zumcb_init((mcb FAR *) (MK_FP(uppermem_root, 0)),
(umb_start + UMB_top ) - uppermem_root - 1);
upBase += 16;
upBase += 16;
}
}
}
#ifdef DEBUG
printf("UMB Allocation completed: top at 0x%p\n",upBase);
#endif
DebugPrintf(("UMB Allocation completed: top at 0x%p\n",upBase));
/* The standard handles should be reopened here, because
we may have loaded new console or printer drivers in CONFIG.SYS */
@ -598,27 +633,21 @@ INIT VOID DoConfig(VOID)
/* Check to see if we have a config.sys file. If not, just */
/* exit since we don't force the user to have one. */
if ((nFileDesc = open("fdconfig.sys", 0)) < 0)
if ((nFileDesc = open("fdconfig.sys", 0)) >= 0)
{
#ifdef DEBUG
printf("FDCONFIG.SYS not found\n");
#endif
DebugPrintf(("Reading FDCONFIG.SYS...\n"));
}
else
{
DebugPrintf(("FDCONFIG.SYS not found\n"));
if ((nFileDesc = open("config.sys", 0)) < 0)
{
#ifdef DEBUG
printf("CONFIG.SYS not found\n");
#endif
DebugPrintf(("CONFIG.SYS not found\n"));
return;
}
#ifdef DEBUG
else
printf("Reading CONFIG.SYS...\n");
#endif
DebugPrintf(("Reading CONFIG.SYS...\n"));
}
#ifdef DEBUG
else
printf("Reading FDCONFIG.SYS...\n");
#endif
/* Have one -- initialize. */
nCfgLine = 0;
@ -663,7 +692,7 @@ INIT VOID DoConfig(VOID)
*pLine = 0;
pLine = szLine;
/* Skip leading white space and get verb. */
pLine = scan(pLine, szBuf);
@ -678,15 +707,15 @@ INIT VOID DoConfig(VOID)
if (pEntry->pass >= 0 && pEntry->pass != nPass)
continue;
if ( SkipLine(pLineStart)) /* F5/F8 processing */
continue;
if ( SkipLine(pLineStart)) /* F5/F8 processing */
continue;
pLine = skipwh(pLine);
if ('=' != *pLine)
CfgFailure(pLine);
CfgFailure(pLine);
else /* YES. DO IT */
(*(pEntry->func)) (skipwh(pLine+1));
(*(pEntry->func)) (skipwh(pLine+1));
@ -1555,3 +1584,4 @@ INIT VOID SetAnyDos(BYTE * pLine)
UNREFERENCED_PARAMETER(pLine);
ReturnAnyDosVersionExpected = TRUE;
}

View File

@ -28,6 +28,9 @@
; $Header$
;
; $Log$
; Revision 1.7 2001/07/09 22:19:33 bartoldeman
; LBA/FCB/FAT/SYS/Ctrl-C/ioctl fixes + memory savings
;
; Revision 1.6 2001/04/15 03:21:50 bartoldeman
; See history.txt for the list of fixes.
;
@ -166,7 +169,7 @@ CommonNdRdExit:
jnz ConNdRd2 ; Jump if there's a char waiting
mov ah,1
int 16h ; Get status, if zf=0 al=char
jz ConNdRd4 ; Jump if chrar available
jz ConNdRd4 ; Jump if no char available
or ax,ax ; Zero ?
jnz ConNdRd1 ; Jump if not zero
int 16h ; get status, if zf=0 al=char
@ -178,7 +181,7 @@ ConNdRd1:
mov al,CTL_P
ConNdRd2:
lds bx,[_ReqPktPtr] ; Set the status
lds bx,[cs:_ReqPktPtr] ; Set the status
mov [bx+0Dh],al
ConNdRd3:
@ -285,7 +288,7 @@ ConIS1:
mov al,CTL_P
ConIS2:
lds bx,[_ReqPktPtr] ; Set the status
lds bx,[cs:_ReqPktPtr] ; Set the status
mov [bx+0Dh],al
ConCharReady:
jmp _IOExit ; key ready (busy=0)

68
kernel/disk.h Normal file
View File

@ -0,0 +1,68 @@
/*
DISK.H
common constants + structures, shared between
DSK.C and INITDISK.C
note:
*/
#define MAX_HARD_DRIVE 8
#define N_RETRY 5 /* number of retries permitted */
#define NDEV 20 /* only one for demo */
#define SEC_SIZE 512 /* size of sector in bytes */
#define LBA_READ 0x4200
#define LBA_WRITE 0x4300
/* physical characteristics of a drive */
struct CHS {
ULONG Cylinder;
UWORD Head;
UWORD Sector;
};
struct DriveParamS
{
UBYTE driveno; /* = 0x8x */
unsigned LBA_supported:1; /* set, if INT13 extensions enabled */
unsigned WriteVerifySupported:1; /* */
ULONG total_sectors;
struct CHS chs; /* for normal INT 13 */
};
struct media_info
{
struct DriveParamS drive; /* physical charactereistics of drive */
ULONG mi_size; /* physical sector count */
ULONG mi_offset; /* relative partition offset */
ULONG mi_FileOC; /* Count of Open files on Drv */
struct FS_info
{
ULONG serialno;
BYTE volume[11];
BYTE fstype[8];
}fs;
};
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 */
};

View File

@ -37,6 +37,9 @@ static BYTE *dosfnsRcsId = "$Id$";
* /// Added SHARE support. 2000/09/04 Ron Cemer
*
* $Log$
* Revision 1.19 2001/07/09 22:19:33 bartoldeman
* LBA/FCB/FAT/SYS/Ctrl-C/ioctl fixes + memory savings
*
* Revision 1.18 2001/06/03 14:16:17 bartoldeman
* BUFFERS tuning and misc bug fixes/cleanups (2024c).
*
@ -591,7 +594,9 @@ UCOUNT DosWrite(COUNT hndl, UCOUNT n, BYTE FAR * bp, COUNT FAR * err)
/* /// End of additions for SHARE - Ron Cemer */
WriteCount = writeblock(s->sft_status, bp, n, &rc);
if (rc < SUCCESS)
/* if (rc < SUCCESS) */
if (rc == DE_ACCESS || /* -5 Access denied */
rc == DE_INVLDHNDL ) /* -6 Invalid handle */
{
*err = rc;
return 0;

File diff suppressed because it is too large Load Diff

11
kernel/dyndata.c Normal file
View File

@ -0,0 +1,11 @@
/*
DYNDATA.C
this serves as a placeholder in the near data segment
alll data herein goes to special segment
DYN_DATA AFTER BSS, but immediately before HMA_TEXT
*/
#include "dyndata.h"
struct DynS Dyn;

25
kernel/dyndata.h Normal file
View File

@ -0,0 +1,25 @@
/*
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 *DynAlloc(char far *what, unsigned num, unsigned size);
void DynFree(unsigned memory_needed);
void far *DynLast(void);
struct DynS {
unsigned Allocated;
unsigned UsedByDiskInit;
unsigned AllocMax;
char Buffer[1000 /* for InitDisk - Miarray's */
+ 16 * 71 /* initial f_nodes */
+200 /* give some extra bytes */
];
};

109
kernel/dyninit.c Normal file
View File

@ -0,0 +1,109 @@
/*
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
FCB's, 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;
void *DynAlloc(char FAR *what, unsigned num, unsigned size)
{
void *now;
unsigned total = num * size;
UNREFERENCED_PARAMETER(what);
DebugPrintf(("DYNDATA:allocating %Fs - %u * %u bytes, total %u, %u..%u\n",
what, num, size, total, Dyn.Allocated,Dyn.Allocated+total));
if (total > Dyn.AllocMax - Dyn.Allocated)
{
printf("DYNDATA overflow");
for (;;);
}
now = (void*)&Dyn.Buffer[Dyn.Allocated];
Dyn.Allocated += total;
return now;
}
void DynFree(unsigned memory_needed)
{
if (memory_needed == 0) /* this is pass 0 */
{
Dyn.Allocated = 1000; /* this reserves space for initDisk */
Dyn.AllocMax = sizeof(Dyn.Buffer);
}
else {
/* enlarge kernel data segment to 64K */
if (memory_needed + Dyn.UsedByDiskInit > sizeof(Dyn.Buffer))
{
if ((ULONG)memory_needed + Dyn.UsedByDiskInit > 0xffff)
{
printf("PANIC:Dyn %lu\n",memory_needed + Dyn.UsedByDiskInit);
for (;;);
}
MoveKernel(FP_SEG(&Dyn.UsedByDiskInit) + 0x1000);
Dyn.AllocMax = 0xffff - (unsigned)&Dyn.Buffer;
}
Dyn.Allocated = Dyn.UsedByDiskInit;
}
DebugPrintf(("DYNDATA:free to %u, max %u\n",Dyn.Allocated,Dyn.AllocMax));
}
void FAR *DynLast()
{
DebugPrintf(("dynamic data end at %p\n",(void FAR *)(Dyn.Buffer+Dyn.Allocated)));
return Dyn.Buffer+Dyn.Allocated;
}

View File

@ -36,6 +36,9 @@ static BYTE *fatdirRcsId = "$Id$";
/*
* $Log$
* Revision 1.17 2001/07/09 22:19:33 bartoldeman
* LBA/FCB/FAT/SYS/Ctrl-C/ioctl fixes + memory savings
*
* Revision 1.16 2001/06/03 14:16:17 bartoldeman
* BUFFERS tuning and misc bug fixes/cleanups (2024c).
*
@ -601,9 +604,9 @@ COUNT dos_findfirst(UCOUNT attr, BYTE FAR * name)
static BYTE local_name[FNAME_SIZE + 1],
local_ext[FEXT_SIZE + 1];
/*
printf("ff %s", Tname);
*/
/* 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). Since we don't want to lose fnodes every */
@ -612,11 +615,13 @@ COUNT dos_findfirst(UCOUNT attr, BYTE FAR * name)
/* current directory, do a seek and read, then close the fnode. */
/* Start out by initializing the dirmatch structure. */
fmemset(dmp, sizeof(*dmp),0);
dmp->dm_drive = default_drive;
dmp->dm_entry = 0;
/* dmp->dm_entry = 0;
dmp->dm_cluster = 0;
dmp->dm_attr_srch = attr | D_RDONLY | D_ARCHIVE;
*/
dmp->dm_attr_srch = attr;
/* Parse out the drive, file name and file extension. */
i = ParseDosName((BYTE FAR *)name, &nDrive, &LocalPath[2], local_name, local_ext, TRUE);
@ -642,7 +647,7 @@ COUNT dos_findfirst(UCOUNT attr, BYTE FAR * name)
/* Now build a directory. */
if (!LocalPath[2])
strcpy(&LocalPath[2], ".");
fstrcpy(&LocalPath[0], current_ldt->cdsCurrentPath);
/* Build the match pattern out of the passed string */
/* copy the part of the pattern which belongs to the filename and is fixed */
@ -687,6 +692,8 @@ COUNT dos_findfirst(UCOUNT attr, BYTE FAR * name)
}
/* Now open this directory so that we can read the */
/* fnode entry and do a match on it. */
/* printf("dir_open %Fs\n",(BYTE FAR *) LocalPath);*/
if ((fnp = dir_open((BYTE FAR *) LocalPath)) == NULL)
return DE_PATHNOTFND;
@ -728,6 +735,14 @@ COUNT dos_findfirst(UCOUNT attr, BYTE FAR * name)
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)
{
@ -740,6 +755,8 @@ COUNT dos_findnext(void)
{
return DE_NFILES;
}
memset(fnp, 0, sizeof(*fnp));
/* Force the fnode into read-write mode */
fnp->f_mode = RDWR;
@ -758,18 +775,30 @@ COUNT dos_findnext(void)
/* Search through the directory to find the entry, but do a */
/* seek first. */
if (dmp->dm_entry > 0)
{
fnp->f_diroff = (dmp->dm_entry - 1) * DIRENT_SIZE;
fnp->f_flags.f_dnew = FALSE;
}
else
{
fnp->f_diroff = 0;
fnp->f_flags.f_dnew = TRUE;
}
fnp->f_offset = fnp->f_highwater = fnp->f_diroff;
fnp->f_cluster = dmp->dm_cluster;
fnp->f_offset = fnp->f_diroff;
fnp->f_dirstart =
fnp->f_dir.dir_start =
fnp->f_cluster =
dmp->dm_dirstart;
fnp->f_flags.f_droot = fnp->f_dirstart == 0;
fnp->f_flags.f_ddir = TRUE;
fnp->f_flags.f_dfull = FALSE;
fnp->f_cluster_offset = 0l; /*JPP */
fnp->f_flags.f_dmod = dmp->dm_flags.f_dmod;
fnp->f_flags.f_droot = dmp->dm_flags.f_droot;
fnp->f_flags.f_dnew = dmp->dm_flags.f_dnew;
fnp->f_flags.f_ddir = dmp->dm_flags.f_ddir;
fnp->f_flags.f_dfull = dmp->dm_flags.f_dfull;
fnp->f_dirstart = dmp->dm_dirstart;
/* Loop through the directory */
while (dir_read(fnp) == DIRENT_SIZE)
@ -782,11 +811,12 @@ COUNT dos_findnext(void)
/*
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. FD assumes the user knows what they need
to see.
files are returned.
RdOnly + Archive bits are ignored
*/
/* Test the attribute as the final step */
if (!(~dmp->dm_attr_srch & fnp->f_dir.dir_attrib))
if (!(~dmp->dm_attr_srch & (fnp->f_dir.dir_attrib & ~(D_RDONLY|D_ARCHIVE))))
{
found = TRUE;
break;
@ -799,7 +829,20 @@ COUNT dos_findnext(void)
/* If found, transfer it to the dmatch structure */
if (found)
{
extern VOID FAR *FcbFindFirstDirPtr;
if (FcbFindFirstDirPtr)
{
/* this works MUCH better, then converting
83 -> ASCIIZ ->83;
specifically ".", ".."
*/
fmemcpy(FcbFindFirstDirPtr, &fnp->f_dir, 32);
}
pop_dmp(dmp, fnp);
}
/* return the result */
release_f_node(fnp);
@ -807,19 +850,21 @@ COUNT dos_findnext(void)
return found ? SUCCESS : DE_NFILES;
}
static VOID pop_dmp(dmatch FAR * dmp, f_node_ptr fnp)
STATIC VOID pop_dmp(dmatch FAR * dmp, f_node_ptr fnp)
{
dmp->dm_attr_fnd = fnp->f_dir.dir_attrib;
dmp->dm_time = fnp->f_dir.dir_time;
dmp->dm_date = fnp->f_dir.dir_date;
dmp->dm_size = fnp->f_dir.dir_size;
/* dmp -> dm_cluster = fnp -> f_cluster; /* */
dmp->dm_cluster = fnp->f_dir.dir_start; /* TE */
dmp->dm_dirstart= fnp->f_dirstart;
/*
dmp->dm_flags.f_droot = fnp->f_flags.f_droot;
dmp->dm_flags.f_ddir = fnp->f_flags.f_ddir;
dmp->dm_flags.f_dmod = fnp->f_flags.f_dmod;
dmp->dm_flags.f_dnew = fnp->f_flags.f_dnew;
*/
ConvertName83ToNameSZ((BYTE FAR *)dmp->dm_name, (BYTE FAR *) fnp->f_dir.dir_name);
}

View File

@ -35,10 +35,21 @@ BYTE *RcsId = "$Id$";
#endif
/*
* TE 12 jun 2001 bugs corrected
* handles disk full (in a incompatible way :-( )
* allows use of last cluster
* prevents mkdir, if disk is full (was creating crosslinked dirs)
* bugs detected, but NOT corrected
* on disk full, MSDOS will NOT write any byte, simply return SUCCESS, 0 bytes
* FreeDOS will write all possible bytes, then close file(BUG)
*
* the dos_mkdir/extenddir (with getblock() instead of getblockOver) was a real
* performance killer on large drives. (~0.5 sec /dos_mkdir) TE
*
* $Log$
* Revision 1.19 2001/07/09 22:19:33 bartoldeman
* LBA/FCB/FAT/SYS/Ctrl-C/ioctl fixes + memory savings
*
* Revision 1.18 2001/06/03 14:16:17 bartoldeman
* BUFFERS tuning and misc bug fixes/cleanups (2024c).
*
@ -231,7 +242,7 @@ BYTE *RcsId = "$Id$";
/* */
/* function prototypes */
/* */
f_node_ptrxlt_fd(COUNT);
f_node_ptr xlt_fd(COUNT);
COUNT xlt_fnp(f_node_ptr);
f_node_ptr split_path(BYTE FAR *, BYTE *, BYTE *, BYTE *);
BOOL find_fname(f_node_ptr, BYTE *, BYTE *);
@ -251,6 +262,7 @@ BOOL extend(f_node_ptr);
COUNT extend_dir(f_node_ptr);
BOOL first_fat(f_node_ptr);
COUNT map_cluster(f_node_ptr, COUNT);
STATIC VOID shrink_file(f_node_ptr fnp);
/************************************************************************/
/* */
@ -356,6 +368,8 @@ COUNT dos_close(COUNT fd)
fnp->f_dir.dir_attrib |= D_ARCHIVE;
fnp->f_dir.dir_time = dos_gettime();
fnp->f_dir.dir_date = dos_getdate();
shrink_file(fnp); /* reduce allocated filesize in FAT */
}
fnp->f_dir.dir_size = fnp->f_highwater;
@ -659,9 +673,10 @@ COUNT dos_delete(BYTE FAR * path)
if (find_fname(fnp, szFileName, szFileExt))
{
/* The only permissable attribute is archive, */
/* TE +hidden + system */
/* check for any other bit set. If it is, give */
/* an access error. */
if (fnp->f_dir.dir_attrib & ~D_ARCHIVE)
if (fnp->f_dir.dir_attrib & ~(D_ARCHIVE | D_HIDDEN | D_SYSTEM))
{
dir_close(fnp);
return DE_ACCESS;
@ -1136,20 +1151,23 @@ STATIC UWORD find_fat_free(f_node_ptr fnp)
/* Search the FAT table looking for the first free */
/* entry. */
for (; idx < fnp->f_dpb->dpb_size; idx++)
for (; idx <= fnp->f_dpb->dpb_size; idx++)
{
if (next_cluster(fnp->f_dpb, idx) == FREE)
break;
}
/* No empty clusters, disk is FULL! */
if (idx >= fnp->f_dpb->dpb_size)
if (idx > fnp->f_dpb->dpb_size)
{
fnp->f_dpb->dpb_cluster = UNKNCLUSTER;
dir_close(fnp);
return LONG_LAST_CLUSTER;
}
if (fnp->f_dpb->dpb_nfreeclst != UNKNCLSTFREE)
fnp->f_dpb->dpb_nfreeclst--; /* TE: moved from link_fat() */
/* return the free entry */
fnp->f_dpb->dpb_cluster = idx;
return idx;
@ -1166,6 +1184,7 @@ COUNT dos_mkdir(BYTE FAR * dir)
struct buffer FAR *bp;
UWORD free_fat;
UWORD parent;
COUNT ret;
/* first split the passed dir into comopnents (i.e. - */
/* path to new directory and name of new directory */
@ -1204,9 +1223,7 @@ COUNT dos_mkdir(BYTE FAR * dir)
dir_close(fnp);
return DE_ACCESS;
}
else
{
BOOL is_free;
/* Reset the directory by a close followed by */
/* an open */
@ -1219,22 +1236,37 @@ COUNT dos_mkdir(BYTE FAR * dir)
/* it in building the new file. */
/* Note that if we're in the root and we don't */
/* find an empty slot, we need to abort. */
if (((is_free = find_free(fnp)) == 0) && (fnp->f_flags.f_droot))
if (find_free(fnp) == 0)
{
fnp->f_flags.f_dmod = FALSE;
dir_close(fnp);
return DE_TOOMANY;
}
if (fnp->f_flags.f_droot)
{
fnp->f_flags.f_dmod = FALSE;
dir_close(fnp);
return DE_TOOMANY;
}
/* Otherwise just expand the directory */
else if (!is_free && !(fnp->f_flags.f_droot))
{
COUNT ret;
if ((ret = extend_dir(fnp)) != SUCCESS)
return ret;
}
/* get an empty cluster, so that we make it into a */
/* directory. */
/* TE this has to be done (and failed) BEFORE the dir entry */
/* is changed */
free_fat = find_fat_free(fnp);
/* No empty clusters, disk is FULL! Translate into a */
/* useful error message. */
if (free_fat == LONG_LAST_CLUSTER)
{
dir_close(fnp);
return DE_HNDLDSKFULL;
}
/* put the fnode's name into the directory. */
fbcopy((BYTE FAR *) szFileName,
(BYTE FAR *) fnp->f_dir.dir_name, FNAME_SIZE);
@ -1257,19 +1289,7 @@ COUNT dos_mkdir(BYTE FAR * dir)
fnp->f_highwater = 0l;
fnp->f_offset = 0l;
}
/* get an empty cluster, so that we make it into a */
/* directory. */
free_fat = find_fat_free(fnp);
/* No empty clusters, disk is FULL! Translate into a */
/* useful error message. */
if (free_fat == LONG_LAST_CLUSTER)
{
dir_close(fnp);
return DE_HNDLDSKFULL;
}
/* Mark the cluster in the FAT as used */
fnp->f_dir.dir_start = fnp->f_cluster = free_fat;
@ -1441,7 +1461,10 @@ STATIC BOOL first_fat(f_node_ptr fnp)
/* Now that we've found a free FAT entry, mark it as the last */
/* entry and save it. */
fnp->f_dir.dir_start = free_fat;
/* BUG!! this caused wrong allocation, if file was created,
then seeked, then written */
fnp->f_cluster =
fnp->f_dir.dir_start = free_fat;
link_fat(fnp->f_dpb, (UCOUNT) free_fat, LONG_LAST_CLUSTER);
/* Mark the directory so that the entry is updated */
@ -1574,7 +1597,8 @@ UCOUNT readblock(COUNT fd, VOID FAR * buffer, UCOUNT count, COUNT * err)
}
/* Another test is to check for a seek past EOF */
if (!fnp->f_flags.f_ddir && (fnp->f_offset >= fnp->f_dir.dir_size))
/* if (!fnp->f_flags.f_ddir && (fnp->f_offset >= fnp->f_dir.dir_size)) BUG :-< */
if (!fnp->f_flags.f_ddir && (fnp->f_offset >= fnp->f_highwater))
{
*err = SUCCESS;
return 0;
@ -1667,7 +1691,7 @@ UCOUNT readblock(COUNT fd, VOID FAR * buffer, UCOUNT count, COUNT * err)
/* Do an EOF test and return whatever was transferred */
/* but only for regular files. */
if (!(fnp->f_flags.f_ddir)
&& (fnp->f_offset >= fnp->f_dir.dir_size))
&& (fnp->f_offset >= fnp->f_highwater))
{
*err = SUCCESS;
return ret_cnt;
@ -1697,7 +1721,7 @@ UCOUNT readblock(COUNT fd, VOID FAR * buffer, UCOUNT count, COUNT * err)
xfr_cnt = min(to_xfer, secsize - fnp->f_boff);
else
xfr_cnt = (UWORD)min(min(to_xfer, secsize - fnp->f_boff),
fnp->f_dir.dir_size - fnp->f_offset);
fnp->f_highwater - fnp->f_offset);
fbcopy((BYTE FAR *) & bp->b_buffer[fnp->f_boff], buffer, xfr_cnt);
@ -1705,7 +1729,7 @@ UCOUNT readblock(COUNT fd, VOID FAR * buffer, UCOUNT count, COUNT * err)
probably not reused later
*/
if (xfr_cnt == sizeof(bp->b_buffer) ||
fnp->f_offset + xfr_cnt == fnp->f_dir.dir_size )
fnp->f_offset + xfr_cnt == fnp->f_highwater )
{
bp->b_flag |= BFR_UNCACHE;
}
@ -1759,6 +1783,9 @@ UCOUNT writeblock(COUNT fd, VOID FAR * buffer, UCOUNT count, COUNT * err)
return 0;
}
fnp->f_flags.f_dmod = TRUE; /* mark file as modified */
/* Test that we are really about to do a data transfer. If the */
/* count is zero and the mode is XFR_READ, just exit. (Any */
/* read with a count of zero is a nop). */
@ -1767,11 +1794,34 @@ UCOUNT writeblock(COUNT fd, VOID FAR * buffer, UCOUNT count, COUNT * err)
/* file length to the current length (truncates it). */
/* */
/* NOTE: doing this up front saves a lot of headaches later. */
if (count == 0)
{
/* NOTE: doing this up front made a lot of headaches later :-( TE */
/* FAT allocation has to be extended if necessary TE */
*err = SUCCESS;
if (fnp->f_highwater < fnp->f_offset)
{
switch (map_cluster(fnp, XFR_WRITE))
{
case DE_SEEK:
*err = DE_SEEK;
dir_close(fnp);
break;
default:
dir_close(fnp);
*err = DE_HNDLDSKFULL;
break;
case SUCCESS:
break;
}
}
fnp->f_highwater = fnp->f_offset;
merge_file_changes(fnp, FALSE); /* /// Added - Ron Cemer */
*err = SUCCESS;
return 0;
}
@ -2071,8 +2121,11 @@ UWORD dos_free(struct dpb FAR *dpbp)
* * (ULONG) (dpbp->dpb_clsmask + 1) - (dpbp->dpb_data + 1) )
* / (dpbp->dpb_clsmask + 1) ) + 2;
*/
UWORD max_cluster = ( ((ULONG) dpbp->dpb_size * (ULONG) (dpbp->dpb_clsmask + 1))
/*?? UWORD max_cluster = ( ((ULONG) dpbp->dpb_size * (ULONG) (dpbp->dpb_clsmask + 1))
/ (dpbp->dpb_clsmask + 1) ) + 1;
*/
UWORD max_cluster = dpbp->dpb_size + 1;
if (dpbp->dpb_nfreeclst != UNKNCLSTFREE)
return dpbp->dpb_nfreeclst;
@ -2363,3 +2416,88 @@ struct dhdr FAR *select_unit(COUNT drive)
}
#endif
/* TE
if the current filesize in FAT is larger then the dir_size
it's truncated here.
the BUG was:
copy COMMAND.COM xxx
echo >xxx
then, the dirsize of xxx was set to ~20, but the allocated
FAT entries not returned.
this code corrects this
Unfortunately, this code _nearly_ works, but fails one of the
Apps tested (VB ISAM); so it's disabled for the moment
*/
STATIC VOID shrink_file(f_node_ptr fnp)
{
#if 0
UNREFERENCED_PARAMETER(fnp);
#else
ULONG lastoffset = fnp->f_offset; /* has to be saved */
UCOUNT next,st;
struct dpb FAR *dpbp = fnp->f_dpb;
fnp->f_offset = fnp->f_highwater; /* end of file */
if (map_cluster(fnp, XFR_READ) != SUCCESS) /* error, don't truncate */
goto done;
st = fnp->f_cluster;
if (st == FREE) /* first cluster is free, done */
goto done;
next = next_cluster(dpbp, st);
if ( next == LONG_LAST_CLUSTER) /* last cluster found */
goto done;
/* Loop from start until either a FREE entry is */
/* encountered (due to a fractured file system) of the */
/* last cluster is encountered. */
/* zap the FAT pointed to */
if (fnp->f_highwater == 0)
{
fnp->f_dir.dir_start = FREE;
link_fat(dpbp, st, FREE);
}
else
{
link_fat(dpbp, st,LONG_LAST_CLUSTER);
}
for ( st = next; st != LONG_LAST_CLUSTER; st = next)
{
/* get the next cluster pointed to */
next = next_cluster(dpbp, st);
/* just exit if a damaged file system exists */
if (next == FREE)
return;
/* zap the FAT pointed to */
link_fat(dpbp, st, FREE);
/* and the start of free space pointer */
if ((dpbp->dpb_cluster == UNKNCLUSTER)
|| (dpbp->dpb_cluster > st))
dpbp->dpb_cluster = st;
}
done:
fnp->f_offset = lastoffset; /* has to be restored */
#endif
}

View File

@ -35,6 +35,9 @@ static BYTE *RcsId = "$Id$";
/*
* $Log$
* Revision 1.7 2001/07/09 22:19:33 bartoldeman
* LBA/FCB/FAT/SYS/Ctrl-C/ioctl fixes + memory savings
*
* Revision 1.6 2001/06/03 14:16:17 bartoldeman
* BUFFERS tuning and misc bug fixes/cleanups (2024c).
*
@ -170,12 +173,38 @@ struct buffer FAR *getFATblock(UWORD cluster, struct dpb FAR *dpbp)
UCOUNT link_fat(struct dpb FAR *dpbp, UCOUNT Cluster1, REG UCOUNT Cluster2)
{
UCOUNT res;
if (ISFAT12(dpbp))
return link_fat12(dpbp, Cluster1, Cluster2);
res = link_fat12(dpbp, Cluster1, Cluster2);
else if (ISFAT16(dpbp))
return link_fat16(dpbp, Cluster1, Cluster2);
res = link_fat16(dpbp, Cluster1, Cluster2);
else
return DE_BLKINVLD;
/* update the free space count */
if (res == SUCCESS)
if (dpbp->dpb_nfreeclst != UNKNCLSTFREE)
{
if (Cluster2 == FREE)
{
/* update the free space count for returned */
/* cluster */
++dpbp->dpb_nfreeclst;
}
/* update the free space count for removed */
/* cluster */
/* BUG: was counted twice for 2nd,.. cluster. moved to find_fat_free() */
/* else {
--dpbp->dpb_nfreeclst;
}
*/
}
return res;
}
UCOUNT link_fat16(struct dpb FAR *dpbp, UCOUNT Cluster1, UCOUNT Cluster2)
@ -199,21 +228,6 @@ UCOUNT link_fat16(struct dpb FAR *dpbp, UCOUNT Cluster1, UCOUNT Cluster2)
bp->b_flag |= BFR_DIRTY | BFR_VALID;
/* Return successful. */
/* update the free space count */
if (Cluster2 == FREE)
{
/* update the free space count for returned */
/* cluster */
if (dpbp->dpb_nfreeclst != UNKNCLSTFREE)
++dpbp->dpb_nfreeclst;
}
else
{
/* update the free space count for removed */
/* cluster */
if (dpbp->dpb_nfreeclst != UNKNCLSTFREE)
--dpbp->dpb_nfreeclst;
}
return SUCCESS;
}
@ -266,22 +280,6 @@ UCOUNT link_fat12(struct dpb FAR *dpbp, UCOUNT Cluster1, UCOUNT Cluster2)
*fbp1 = (*fbp1 & 0xf0) | ((Cluster2 >> 8) & 0x0f);
}
/* update the free space count */
if (Cluster2 == FREE)
{
/* update the free space count for returned */
/* cluster */
if (dpbp->dpb_nfreeclst != UNKNCLSTFREE)
++dpbp->dpb_nfreeclst;
}
else
{
/* update the free space count for removed */
/* cluster */
if (dpbp->dpb_nfreeclst != UNKNCLSTFREE)
--dpbp->dpb_nfreeclst;
}
return SUCCESS;
}
@ -330,6 +328,11 @@ UWORD next_cl16(struct dpb FAR *dpbp, UCOUNT ClusterNum)
}
#if 0
/* old version - correct, but a bit complicated coded.
it's also on one of the critical stack path's
*/
UWORD next_cl12(struct dpb FAR *dpbp, REG UCOUNT ClusterNum)
{
REG UBYTE FAR *fbp0,
@ -378,3 +381,70 @@ UWORD next_cl12(struct dpb FAR *dpbp, REG UCOUNT ClusterNum)
ClusterNum = LONG_BAD;
return ClusterNum;
}
#else
/* new version - 50 byte smaller, saves 10 bytes on stack :-)
*/
UWORD next_cl12(struct dpb FAR *dpbp, REG UCOUNT ClusterNum)
{
union {
UBYTE bytes[2];
UCOUNT word;
} clusterbuff;
UCOUNT idx;
struct buffer FAR *bp;
/* Get the block that this cluster is in */
bp = getFATblock(ClusterNum , dpbp);
if (bp == NULL)
return LONG_BAD;
/* form an index so that we can read the block as a */
/* byte array */
idx = (((ClusterNum << 1) + ClusterNum) >> 1) % dpbp->dpb_secsize;
clusterbuff.bytes[0] = bp->b_buffer[idx];
clusterbuff.bytes[1] = bp->b_buffer[idx+1]; /* next byte, will be overwritten,
if not valid */
/* 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. */
if (idx >= dpbp->dpb_secsize - 1)
{
bp = getFATblock(ClusterNum +1, dpbp);
if (bp == 0)
return LONG_BAD;
clusterbuff.bytes[1] = bp->b_buffer[0];
}
/* Now to unpack the contents of the FAT entry. Odd and */
/* even bytes are packed differently. */
#ifndef I86 /* the latter assumes byte ordering */
if (ClusterNum & 0x01)
ClusterNum = ((clusterbuff.byte[0] & 0xf0) >> 4) | (clusterbuff.byte[1] << 4);
else
ClusterNum = clusterbuff.byte[0] | ((clusterbuff.byte[0] & 0x0f) << 8);
#else
if (ClusterNum & 0x01)
ClusterNum = (unsigned short)clusterbuff.word >> 4;
else
ClusterNum = clusterbuff.word & 0x0fff;
#endif
if ((ClusterNum & MASK) == MASK)
ClusterNum = LONG_LAST_CLUSTER;
else if ((ClusterNum & BAD) == BAD)
ClusterNum = LONG_BAD;
return ClusterNum;
}
#endif

View File

@ -35,6 +35,9 @@ static BYTE *RcsId = "$Id$";
/*
* $Log$
* Revision 1.12 2001/07/09 22:19:33 bartoldeman
* LBA/FCB/FAT/SYS/Ctrl-C/ioctl fixes + memory savings
*
* Revision 1.11 2001/06/03 14:16:17 bartoldeman
* BUFFERS tuning and misc bug fixes/cleanups (2024c).
*
@ -160,6 +163,9 @@ VOID MoveDirInfo();
static dmatch Dmatch;
VOID FAR *FcbFindFirstDirPtr = NULL;
VOID FatGetDrvData(UCOUNT drive, COUNT FAR * spc, COUNT FAR * bps,
COUNT FAR * nc, BYTE FAR ** mdp)
{
@ -221,7 +227,7 @@ VOID FatGetDrvData(UCOUNT drive, COUNT FAR * spc, COUNT FAR * bps,
WORD FcbParseFname(int wTestMode, BYTE FAR ** lpFileName, fcb FAR * lpFcb)
{
COUNT nIndex;
WORD wRetCode = PARSE_RET_NOWILD;
WORD wRetCodeName,wRetCodeExt;
/* pjv -- ExtFcbToFcb? */
/* Start out with some simple stuff first. Check if we are */
@ -255,27 +261,24 @@ WORD FcbParseFname(int wTestMode, BYTE FAR ** lpFileName, fcb FAR * lpFcb)
/* Now check for drive specification */
if (*(*lpFileName + 1) == ':')
{
REG BYTE Drive = DosUpFChar(**lpFileName);
/* non-portable construct to be changed */
if (Drive < 'A' || Drive > 'Z')
return PARSE_RET_BADDRIVE;
Drive -= ('A' - 1);
REG UBYTE Drive = DosUpFChar(**lpFileName) - 'A' + 1;
if (Drive >= lastdrive)
return PARSE_RET_BADDRIVE;
else
lpFcb->fcb_drive = Drive;
lpFcb->fcb_drive = Drive;
*lpFileName += 2;
}
/* Now to format the file name into the string */
*lpFileName = GetNameField(*lpFileName, (BYTE FAR *) lpFcb->fcb_fname, FNAME_SIZE, (BOOL *) & wRetCode);
*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 *) & wRetCode);
*lpFileName = GetNameField(++*lpFileName, (BYTE FAR *) lpFcb->fcb_fext, FEXT_SIZE, (BOOL *) & wRetCodeExt);
return wRetCode ? PARSE_RET_WILD : PARSE_RET_NOWILD;
return (wRetCodeName|wRetCodeExt) ? PARSE_RET_WILD : PARSE_RET_NOWILD;
}
BYTE FAR *ParseSkipWh(BYTE FAR * lpFileName)
@ -668,7 +671,7 @@ BOOL FcbCreate(xfcb FAR * lpXfcb)
return FALSE;
}
static fcb FAR *ExtFcbToFcb(xfcb FAR * lpExtFcb)
STATIC fcb FAR *ExtFcbToFcb(xfcb FAR * lpExtFcb)
{
if (*((UBYTE FAR *) lpExtFcb) == 0xff)
return &lpExtFcb->xfcb_fcb;
@ -676,7 +679,7 @@ static fcb FAR *ExtFcbToFcb(xfcb FAR * lpExtFcb)
return (fcb FAR *) lpExtFcb;
}
static fcb FAR *CommonFcbInit(xfcb FAR * lpExtFcb, BYTE * pszBuffer,
STATIC fcb FAR *CommonFcbInit(xfcb FAR * lpExtFcb, BYTE * pszBuffer,
COUNT * pCurDrive)
{
fcb FAR *lpFcb;
@ -952,6 +955,12 @@ BOOL FcbRename(xfcb FAR * lpXfcb)
}
}
#if 0
/* TE:the MoveDirInfo() is now done by simply copying the dirEntry into the FCB
this prevents problems with ".", ".." and saves code
*/
void MoveDirInfo(dmatch FAR * lpDmatch, struct dirent FAR * lpDir)
{
BYTE FAR *lpToName,
@ -998,6 +1007,7 @@ void MoveDirInfo(dmatch FAR * lpDmatch, struct dirent FAR * lpDir)
lpDir->dir_start = lpDmatch->dm_cluster;
lpDir->dir_size = lpDmatch->dm_size;
}
#endif
BOOL FcbClose(xfcb FAR * lpXfcb)
{
@ -1068,17 +1078,22 @@ BOOL FcbFindFirst(xfcb FAR * lpXfcb)
*lpDir++ = FcbDrive;
FcbFindFirstDirPtr = lpDir;
if (dos_findfirst(wAttr, SecPathName) != SUCCESS)
{
FcbFindFirstDirPtr = NULL;
dta = lpPsp->ps_dta;
return FALSE;
}
MoveDirInfo((dmatch FAR *) & Dmatch, (struct dirent FAR *)lpDir);
FcbFindFirstDirPtr = NULL;
lpFcb->fcb_dirclst = Dmatch.dm_cluster;
lpFcb->fcb_diroff = Dmatch.dm_entry;
/*
MoveDirInfo((dmatch FAR *) & Dmatch, (struct dirent FAR *)lpDir);
*/
lpFcb->fcb_dirclst = Dmatch.dm_dirstart;
lpFcb->fcb_strtclst = Dmatch.dm_entry;
/*
This is undocumented and seen using Pcwatch and Ramview.
@ -1126,19 +1141,26 @@ BOOL FcbFindNext(xfcb FAR * lpXfcb)
DosUpFMem((BYTE FAR *) Dmatch.dm_name_pat, FNAME_SIZE + FEXT_SIZE);
Dmatch.dm_attr_srch = wAttr;
Dmatch.dm_entry = lpFcb->fcb_diroff;
Dmatch.dm_entry = lpFcb->fcb_strtclst;
Dmatch.dm_cluster = lpFcb->fcb_dirclst;
Dmatch.dm_dirstart= lpFcb->fcb_dirclst;
FcbFindFirstDirPtr = lpDir;
if (dos_findnext() != SUCCESS)
{
FcbFindFirstDirPtr = NULL;
dta = lpPsp->ps_dta;
CritErrCode = 0x12;
return FALSE;
}
FcbFindFirstDirPtr = NULL;
/*
MoveDirInfo((dmatch FAR *) & Dmatch, (struct dirent FAR *)lpDir);
lpFcb->fcb_dirclst = Dmatch.dm_cluster;
lpFcb->fcb_diroff = Dmatch.dm_entry;
*/
lpFcb->fcb_dirclst = Dmatch.dm_dirstart;
lpFcb->fcb_strtclst = Dmatch.dm_entry;
lpFcb->fcb_sftno = Dmatch.dm_drive;
#if 0

View File

@ -36,6 +36,9 @@ static BYTE *Globals_hRcsId = "$Id$";
/*
* $Log$
* Revision 1.14 2001/07/09 22:19:33 bartoldeman
* LBA/FCB/FAT/SYS/Ctrl-C/ioctl fixes + memory savings
*
* Revision 1.13 2001/06/03 14:16:17 bartoldeman
* BUFFERS tuning and misc bug fixes/cleanups (2024c).
*
@ -270,6 +273,10 @@ static BYTE *Globals_hRcsId = "$Id$";
/* Blockio constants */
#define DSKWRITE 1 /* dskxfr function parameters */
#define DSKREAD 2
#define DSKWRITEINT26 3
#define DSKREADINT25 4
/* FAT cluster special flags */
#define FREE 0x000

View File

@ -133,6 +133,9 @@ INIT BYTE FAR *KernelAlloc(WORD nBytes);
INIT COUNT Umb_Test(void);
INIT BYTE *GetStringArg(BYTE * pLine, BYTE * pszString);
/* diskinit.c */
COUNT dsk_init(VOID);
/* int2f.asm */
COUNT Umb_Test(void);
@ -189,3 +192,8 @@ INIT VOID init_fatal(BYTE * err_msg);
/* prf.c */
WORD init_printf(CONST BYTE * fmt,...);
void MoveKernel(unsigned NewKernelSegment);
extern WORD HMAFree; /* first byte in HMA not yet used */
extern unsigned CurrentKernelSegment;

985
kernel/initdisk.c Normal file
View File

@ -0,0 +1,985 @@
/****************************************************************/
/* */
/* initDISK.c */
/* */
/* 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. */
/****************************************************************/
#include "portab.h"
#include "init-mod.h"
#include "disk.h"
#include "dyndata.h"
#ifdef VERSION_STRINGS
static BYTE *dskRcsId = "$Id$";
#endif
/*
data shared between DSK.C and INITDISK.C
*/
extern struct media_info * FAR miarrayptr; /* Internal media info structs */
extern UBYTE FAR DiskTransferBuffer[1 * SEC_SIZE];
extern COUNT FAR nUnits;
extern UWORD FAR LBA_WRITE_VERIFY;
/*
* Rev 1.0 13 May 2001 tom ehlert
* Initial revision.
*
* this module implements the disk scanning for DOS accesible partitions
* the drive letter ordering is somewhat chaotic, but like MSDOS does it.
*
* this module expects to run with CS = INIT_TEXT, like other init_code,
* but SS = DS = DATA = DOS_DS, unlike other init_code.
*
* history:
* 1.0 extracted the disk init code from DSK.C
* added LBA support
* moved code to INIT_TEXT
* done the funny code segment stuff to switch between INIT_TEXT and TEXT
* added a couple of snity checks for partitions
*
****************************************************************************
*
* Implementation note:
* this module needs some interfacing to INT 13
* how to implement them
*
* a) using inline assembly
* _ASM mov ax,0x1314
*
* b) using assembly routines in some external FLOPPY.ASM
*
* c) using the funny TURBO-C style
* _AX = 0x1314
*
* d) using intr(intno, &regs) method.
*
* whynot's
*
* a) this is my personal favorite, combining the best aof all worlds.
* TURBO-C does support inline assembly, but only by using TASM,
* which is not free.
* so - unfortunately- its excluded.
*
* b) keeping funny memory model in sync with external assembly
* routines is everything, but not fun
*
* c) you never know EXACT, what the compiler does, if its a bit
* more complicated. does
* _DL = drive & 0xff
* _BL = driveParam.chs.Sector;
* destroy any other register? sure? _really_ sure?
* at least, it has it's surprises.
* and - I found a couple of optimizer induced bugs (TC 2.01)
* believe me.
* it was coded - and operational that way.
* but - there are many surprises waiting there. so I opted against.
*
*
* d) this method is somewhat clumsy and certainly not the
* fastest way to do things.
* on the other hand, this is INIT code, executed once.
* and scince it's the only portable method, I opted for it.
*
* e) and all this is my private opinion. tom ehlert.
*
*/
/*#define DEBUG*/
#define _BETA_ /* messages for initial phase only */
#if defined(DEBUG)
#define DebugPrintf(x) printf x
#else
#define DebugPrintf(x)
#endif
#if defined(_BETA_)
#define BetaPrintf(x) printf x
#else
#define BetaPrintf(x)
#endif
#define LBA_to_CHS init_LBA_to_CHS
/*
internal global data
*/
UBYTE GlobalEnableLBAsupport = 1; /* = 0 --> disable LBA support */
struct DriveParamS InitDriveParam[MAX_HARD_DRIVE];
/*
translate LBA sectors into CHS addressing
copied and pasted from dsk.c!
*/
void init_LBA_to_CHS(struct CHS *chs, ULONG LBA_address, struct DriveParamS *driveparam)
{
chs->Sector = LBA_address% driveparam->chs.Sector + 1;
LBA_address /= driveparam->chs.Sector;
chs->Head = LBA_address % driveparam->chs.Head;
chs->Cylinder = LBA_address / driveparam->chs.Head;
}
void printCHS(char *title,struct CHS *chs)
{
printf("%s",title);
printf("%4lu-%u-%u",chs->Cylinder, chs->Head, chs->Sector);
}
/*
reason for this modules existence:
we have found a partition, and add them to the global
partition structure.
*/
void DosDefinePartition(struct DriveParamS *driveParam,
ULONG StartSector, ULONG NumSectors)
{
extern struct DynS FAR Dyn;
struct media_info FAR *pmiarray = &((struct media_info FAR *)&Dyn.Buffer[0])[nUnits];
struct CHS chs;
if ( nUnits >= NDEV)
{
printf("more Partitions detected then possible, max = %d\n", NDEV);
return; /* we are done */
}
fmemcpy((BYTE FAR*)&pmiarray->drive, (BYTE FAR*)driveParam, sizeof(struct DriveParamS));
if (pmiarray->drive.LBA_supported)
DebugPrintf(("LBA enabled for drive %c:\n", 'A'+nUnits));
pmiarray->mi_offset = StartSector;
pmiarray->mi_size = NumSectors;
#ifdef _BETA_ /* Alain whishes to keep this in later versions, too */
LBA_to_CHS(&chs,StartSector,driveParam);
printf("%c: disk %02x",
'A' + nUnits,
driveParam->driveno);
printCHS(" CHS= ",&chs);
printf(" start = %5luMB,size =%5lu",
StartSector/2048,NumSectors/2048);
printf("\n");
#endif
nUnits++;
}
void __int__(int);
/*
interesting macros - used internally only
*/
#define SCAN_PRIMARYBOOT 0x00
#define SCAN_PRIMARY 0x01
#define SCAN_EXTENDED 0x02
#define SCAN_PRIMARY2 0x03
#define FAT12 0x01
#define FAT16SMALL 0x04
#define EXTENDED 0x05
#define FAT16LARGE 0x06
#define FAT32 0x0b /* FAT32 partition that ends before the 8.4 */
/* GB boundary */
#define FAT32_LBA 0x0c /* FAT32 partition that ends after the 8.4GB */
/* boundary. LBA is needed to access this. */
#define FAT16_LBA 0x0e /* like 0x06, but it is supposed to end past */
/* the 8.4GB boundary */
#define EXTENDED_LBA 0x0f /* like 0x05, but it is supposed to end past */
#define IsExtPartition(parttyp) ((parttyp) == EXTENDED || \
(parttyp) == EXTENDED_LBA )
#define IsFAT16Partition(parttyp) ((parttyp) == FAT12 || \
(parttyp) == FAT16SMALL || \
(parttyp) == FAT16LARGE || \
(parttyp) == FAT16_LBA )
/* local - returned and used for BIOS interface INT 13, AH=48*/
struct _bios_LBA_disk_parameterS {
UWORD size;
UWORD information;
ULONG cylinders;
ULONG heads;
ULONG sectors;
ULONG totalSect;
ULONG totalSectHigh;
UWORD BytesPerSector;
ULONG eddparameters;
} ;
/* Get the parameters of the hard disk */
int LBA_Get_Drive_Parameters(int drive,struct DriveParamS *driveParam)
{
iregs regs;
struct _bios_LBA_disk_parameterS lba_bios_parameters;
if (driveParam->driveno)
return driveParam->driveno;
driveParam->LBA_supported = FALSE;
drive |= 0x80;
/* for tests - disable LBA support,
even if exists */
if (!GlobalEnableLBAsupport)
{
goto StandardBios;
}
/* check for LBA support */
regs.b.x = 0x55aa;
regs.a.b.h = 0x41;
regs.d.b.l = drive;
init_call_intr(0x13,&regs);
if (regs.b.x != 0xaa55 || (regs.flags & 0x01) )
{
goto StandardBios;
}
/* by ralph :
if DAP cannot be used, don't use
LBA
*/
if ((regs.c.x & 1) == 0)
{
goto StandardBios;
}
/* drive supports LBA addressing */
/* version 1.0, 2.0 have different verify */
if (regs.a.x < 0x2100)
LBA_WRITE_VERIFY = 0x4301;
lba_bios_parameters.size = sizeof(lba_bios_parameters);
regs.si = FP_OFF(&lba_bios_parameters);
regs.ds = FP_SEG(&lba_bios_parameters);
regs.a.b.h = 0x48;
regs.d.b.l = drive;
init_call_intr(0x13,&regs);
if (regs.flags & 0x01)
{
goto StandardBios;
}
/* verify maximum settings, we can't handle more */
if (lba_bios_parameters.heads > 0xffff ||
lba_bios_parameters.sectors > 0xffff ||
lba_bios_parameters.totalSectHigh != 0 )
{
printf("Drive is too large to handle, using only 1'st 8 GB\n"
" drive %02x heads %lu sectors %lu , total=0x%lx-%08lx\n",
drive,
(ULONG)lba_bios_parameters.heads,
(ULONG)lba_bios_parameters.sectors,
(ULONG)lba_bios_parameters.sectors,
(ULONG)lba_bios_parameters.totalSectHigh);
goto StandardBios;
}
if (lba_bios_parameters.information & 8)
{
driveParam->WriteVerifySupported = 1;
}
else
driveParam->WriteVerifySupported = 0;
driveParam->total_sectors = lba_bios_parameters.totalSect;
/* if we arrive here, success */
driveParam->LBA_supported = TRUE;
StandardBios: /* old way to get parameters */
regs.a.b.h = 0x08;
regs.d.b.l = drive;
init_call_intr(0x13,&regs);
if (regs.flags & 0x01)
goto ErrorReturn;
driveParam->chs.Head = (regs.d.x >> 8) + 1;
driveParam->chs.Sector = (regs.c.x & 0x3f);
driveParam->chs.Cylinder = (regs.c.x >> 8) | ((regs.c.x & 0xc0) << 2);
if (!driveParam->LBA_supported)
{
driveParam->total_sectors =
min(driveParam->chs.Cylinder,1023)
* driveParam->chs.Head
* driveParam->chs.Sector;
}
driveParam->driveno = drive;
DebugPrintf(("drive parameters %02x - %04lu-%u-%u",
drive,driveParam->chs.Cylinder,
drive,driveParam->chs.Head,
drive,driveParam->chs.Sector));
DebugPrintf((" total size %luMB\n\n",driveParam->total_sectors/2048));
ErrorReturn:
return driveParam->driveno;
}
struct PartTableEntry /* INTERNAL representation of partition table entry */
{
UBYTE Bootable;
UBYTE FileSystem;
struct CHS Begin;
struct CHS End;
ULONG RelSect;
ULONG NumSect;
};
/*
converts physical into logical representation of partition entry
*/
ConvPartTableEntryToIntern(struct PartTableEntry *pEntry, UBYTE FAR * pDisk)
{
int i;
if (pDisk[0x1fe] != 0x55 || pDisk[0x1ff] != 0xaa)
{
memset(pEntry,0, 4 * sizeof(struct PartTableEntry));
return FALSE;
}
pDisk += 0x1be;
for (i = 0; i < 4; i++,pDisk += 16,pEntry++)
{
pEntry->Bootable = *(UBYTE FAR*)(pDisk+0);
pEntry->FileSystem = *(UBYTE FAR*)(pDisk+4);
pEntry->Begin.Head = *(UBYTE FAR*)(pDisk+1);
pEntry->Begin.Sector = *(UBYTE FAR*)(pDisk+2) & 0x3f;
pEntry->Begin.Cylinder = *(UBYTE FAR*)(pDisk+3) +
((UWORD) (0xc0 & *(UBYTE FAR*)(pDisk+2)) << 2);
pEntry->End.Head = *(UBYTE FAR*)(pDisk+5);
pEntry->End.Sector = *(UBYTE FAR*)(pDisk+6) & 0x3f;
pEntry->End.Cylinder = *(UBYTE FAR*)(pDisk+7) +
((UWORD) (0xc0 & *(UBYTE FAR*)(pDisk+6)) << 2);
pEntry->RelSect = *(ULONG FAR*)(pDisk+8);
pEntry->NumSect = *(ULONG FAR*)(pDisk+12);
}
return TRUE;
}
ScanForPrimaryPartitions(struct DriveParamS *driveParam,int scan_type,
struct PartTableEntry *pEntry, ULONG startSector,
int partitionsToIgnore
)
{
int i;
struct CHS chs,end;
ULONG partitionStart;
for (i = 0; i < 4; i++,pEntry++)
{
if (pEntry->FileSystem == 0)
continue;
if (partitionsToIgnore & (1 << i))
continue;
if (IsExtPartition(pEntry->FileSystem))
continue;
if (scan_type == SCAN_PRIMARYBOOT && !pEntry->Bootable)
continue;
partitionStart = startSector + pEntry->RelSect;
if (!IsFAT16Partition(pEntry->FileSystem))
{
continue;
}
/*
some sanity checks, that partition
structure is OK
*/
LBA_to_CHS(&chs, partitionStart,driveParam);
LBA_to_CHS(&end, partitionStart+pEntry->NumSect-1,driveParam);
/* some FDISK's enter for partitions
> 8 GB cyl = 1023, other (cyl&1023)
*/
if ( ((chs.Cylinder & 0x3ff) != pEntry->Begin.Cylinder &&
1023 != pEntry->Begin.Cylinder ) ||
chs.Head != pEntry->Begin.Head ||
chs.Sector != pEntry->Begin.Sector )
{
printf("NOT using suspect partition %u FS %02x:",
i, pEntry->FileSystem);
printCHS(" start calc ",&chs);
printCHS(" != ",&pEntry->Begin);
printf("\n");
continue;
}
if (((end.Cylinder & 0x3ff) != pEntry->End.Cylinder &&
1023 != pEntry->End.Cylinder ) ||
end.Head != pEntry->End.Head ||
end.Sector != pEntry->End.Sector )
{
printf("NOT using suspect partition %u FS %02x:",
i, pEntry->FileSystem);
printCHS(" end calc ",&end);
printCHS(" != ",&pEntry->End);
printf("\n");
continue;
}
if (chs.Cylinder > 1023 || end.Cylinder > 1023)
{
if (!driveParam->LBA_supported)
{
printf("can't use LBA partition without LBA support - part %u FS %02x",
i, pEntry->FileSystem);
printCHS(" start ",&chs);
printCHS(", end ", &end);
printf("\n");
continue;
}
/* else its a diagnostic message only */
#ifdef _BETA_
printf("found and using LBA partition %u FS %02x",
i, pEntry->FileSystem);
printCHS(" start ",&chs);
printCHS(", end ", &end);
printf("\n");
#endif
}
/*
here we have a partition table in our hand !!
*/
partitionsToIgnore |= 1 << i;
DosDefinePartition(driveParam,partitionStart, pEntry->NumSect);
if (scan_type == SCAN_PRIMARYBOOT ||
scan_type == SCAN_PRIMARY )
{
return partitionsToIgnore;
}
}
return partitionsToIgnore;
}
void BIOS_drive_reset(unsigned drive);
int Read1LBASector(struct DriveParamS *driveParam, unsigned drive, ULONG LBA_address, void FAR *buffer)
{
static struct _bios_LBA_address_packet dap = {
16,0,0,0,0,0,0
};
struct CHS chs;
iregs regs;
int num_retries;
if (LBA_address >= driveParam->total_sectors)
{
printf("LBA-Transfer error : address overflow = %lu > %lu max\n",LBA_address+1,driveParam->total_sectors);
return 1;
}
for ( num_retries = 0; num_retries < N_RETRY; num_retries++)
{
regs.d.b.l = drive | 0x80;
if (driveParam->LBA_supported)
{
dap.number_of_blocks = 1;
dap.buffer_address = buffer;
dap.block_address_high = 0; /* clear high part */
dap.block_address = LBA_address; /* clear high part */
/* Load the registers and call the interrupt. */
regs.a.b.h = 0x42;
regs.si = FP_OFF(&dap);
regs.ds = FP_SEG(&dap);
}
else
{ /* transfer data, using old bios functions */
init_LBA_to_CHS(&chs, LBA_address, driveParam);
/* avoid overflow at end of track */
if (chs.Cylinder > 1023)
{
printf("LBA-Transfer error : cylinder %u > 1023\n", chs.Cylinder);
return 1;
}
regs.a.x = 0x0201;
regs.b.x = FP_OFF(buffer);
regs.c.x = ((chs.Cylinder&0xff) << 8) + ((chs.Cylinder&0x300) >> 2) + chs.Sector;
regs.d.b.h = chs.Head;
regs.es = FP_SEG(buffer);
} /* end of retries */
init_call_intr(0x13, &regs);
if ((regs.flags & FLG_CARRY) == 0) break;
BIOS_drive_reset(driveParam->driveno);
}
return regs.flags & FLG_CARRY ? 1 : 0;
}
/* Load the Partition Tables and get information on all drives */
int ProcessDisk(int scanType, unsigned drive, int PartitionsToIgnore)
{
struct PartTableEntry PTable[4];
ULONG RelSectorOffset;
ULONG ExtendedPartitionOffset;
int iPart;
int strangeHardwareLoop;
int num_extended_found = 0;
struct DriveParamS *driveParam = &InitDriveParam[drive&0x7f];
/* Get the hard drive parameters and ensure that the drive exists. */
/* If there was an error accessing the drive, skip that drive. */
if (!LBA_Get_Drive_Parameters(drive,driveParam))
{
printf("can't get drive parameters for drive %02x\n",drive);
return PartitionsToIgnore;
}
RelSectorOffset = 0; /* boot sector */
ExtendedPartitionOffset = 0; /* not found yet */
/* Read the Primary Partition Table. */
ReadNextPartitionTable:
strangeHardwareLoop = 0;
strange_restart:
if (Read1LBASector(driveParam, drive, RelSectorOffset, DiskTransferBuffer))
{
printf("Error reading partition table drive %02x sector %lu",drive,RelSectorOffset);
return PartitionsToIgnore;
}
if (!ConvPartTableEntryToIntern(PTable, DiskTransferBuffer))
{
/* there is some strange hardware out in the world,
which returns OK on first read, but the data are
rubbish. simply retrying works fine.
there is no logic behind this, but it works TE */
if (++strangeHardwareLoop < 3)
goto strange_restart;
printf("illegal partition table - drive %02x sector %lu\n",drive,RelSectorOffset);
return PartitionsToIgnore;
}
if ( scanType==SCAN_PRIMARYBOOT ||
scanType==SCAN_PRIMARY ||
scanType==SCAN_PRIMARY2 ||
num_extended_found !=0 )
{
PartitionsToIgnore = ScanForPrimaryPartitions(driveParam,scanType,
PTable, RelSectorOffset,PartitionsToIgnore);
}
if (scanType != SCAN_EXTENDED)
{
return PartitionsToIgnore;
}
/* scan for extended partitions now */
PartitionsToIgnore = 0;
for (iPart=0; iPart < 4; iPart++)
{
if (IsExtPartition(PTable[iPart].FileSystem))
{
RelSectorOffset = ExtendedPartitionOffset + PTable[iPart].RelSect;
if (ExtendedPartitionOffset == 0)
{
ExtendedPartitionOffset = PTable[iPart].RelSect;
}
num_extended_found++;
if (num_extended_found > 30)
{
printf("found more then 30 extended partitions, terminated\n");
return 0;
}
goto ReadNextPartitionTable;
}
}
return PartitionsToIgnore;
}
BIOS_nrdrives(void)
{
iregs regs;
regs.a.b.h = 0x08;
regs.d.b.l = 0x80;
init_call_intr(0x13,&regs);
if (regs.flags & 1)
{
printf("no hard disks detected\n");
return 0;
}
return regs.d.b.l;
}
void BIOS_drive_reset(unsigned drive)
{
iregs regs;
regs.d.b.l = drive | 0x80;
regs.a.b.h = 0;
init_call_intr(0x13,&regs);
}
/*
thats what MSDN says:
How Windows 2000 Assigns, Reserves, and Stores Drive Letters
ID: q234048
BASIC Disk - Drive Letter Assignment Rules
The following are the basic disk drive letter assignment rules for Windows 2000:
Scan all fixed hard disks as they are enumerated, assign drive letters
starting with any active primary partitions (if there is one), otherwise,
scan the first primary partition on each drive. Assign next available
letter starting with C:
Repeat scan for all fixed hard disks and removable (JAZ, MO) disks
and assign drive letters to all logical drives in an extended partition,
or the removable disk(s) as enumerated. Assign next available letter
starting with C:
Finally, repeat scan for all fixed hard disk drives, and assign drive
letters to all remaining primary partitions. Assign next available letter
starting with C:
Floppy drives. Assign letter starting with A:
CD-ROM drives. Assign next available letter starting with D:
*************************************************************************
Order in Which MS-DOS and Windows Assign Drive Letters
ID: q51978
MORE INFORMATION
The following occurs at startup:
MS-DOS checks all installed disk devices, assigning the drive letter A
to the first physical floppy disk drive that is found.
If a second physical floppy disk drive is present, it is assigned drive letter B. If it is not present, a logical drive B is created that uses the first physical floppy disk drive.
Regardless of whether a second floppy disk drive is present,
MS-DOS then assigns the drive letter C to the primary MS-DOS
partition on the first physical hard disk, and then goes on
to check for a second hard disk.
If a second physical hard disk is found, and a primary partition exists
on the second physical drive, the primary MS-DOS partition on the second
physical hard drive is assigned the letter D. MS-DOS version 5.0, which
supports up to eight physical drives, will continue to search for more
physical hard disk drives at this point. For example, if a third physical
hard disk is found, and a primary partition exists on the third physical
drive, the primary MS-DOS partition on the third physical hard drive is
assigned the letter E.
MS-DOS returns to the first physical hard disk drive and assigns drive
letters to any additional logical drives (in extended MS-DOS partitions)
on that drive in sequence.
MS-DOS repeats this process for the second physical hard disk drive,
if present. MS-DOS 5.0 will repeat this process for up to eight physical
hard drives, if present. After all logical drives (in extended MS-DOS
partitions) have been assigned drive letters, MS-DOS 5.0 returns to
the first physical drive and assigns drive letters to any other primary
MS-DOS partitions that exist, then searches other physical drives for
additional primary MS-DOS partitions. This support for multiple primary
MS-DOS partitions was added to version 5.0 for backward compatibility
with the previous OEM MS-DOS versions that support multiple primary partitions.
After all logical drives on the hard disk(s) have been assigned drive
letters, drive letters are assigned to drives installed using DRIVER.SYS
or created using RAMDRIVE.SYS in the order in which the drivers are loaded
in the CONFIG.SYS file. Which drive letters are assigned to which devices
can be influenced by changing the order of the device drivers or, if necessary,
by creating "dummy" drive letters with DRIVER.SYS.
********************************************************
or
as rather well documented, DOS searches 1st) 1 primary patitions on
all drives, 2nd) all extended partitions. that
makes many people (including me) unhappy, as all DRIVES D:,E:...
on 1st disk will move up/down, if other disk with
primary partitions are added/removed, but
thats the way it is (hope I got it right)
TE (with a little help from my friends)
see also above for WIN2000,DOS,MSDN
I don't know, if I did it right, but I tried to do it that way. TE
***********************************************************************/
void ReadAllPartitionTables(void)
{
UBYTE foundPartitions[MAX_HARD_DRIVE];
int HardDrive;
int nHardDisk = BIOS_nrdrives();
struct media_info FAR *pmiarray;
int Unit;
extern struct DynS FAR Dyn;
/* struct media_info *miarrayptr; /* Internal media info structs */
__int__(0x03);
miarrayptr = (struct media_info *)&Dyn.Buffer[0];
for (Unit = 0; Unit < NDEV; Unit++)
{
pmiarray = &((struct media_info FAR *)&Dyn.Buffer[0])[Unit];
pmiarray->drive.driveno = Unit;
pmiarray->drive.total_sectors = 1440*2;
pmiarray->drive.chs.Head = 2;
pmiarray->drive.chs.Cylinder = 40;
pmiarray->drive.chs.Sector = 9;
pmiarray->drive.LBA_supported = FALSE;
pmiarray->mi_size = 1440*2;
pmiarray->mi_offset = 0l;
pmiarray->fs.serialno = 0x12345678l;
}
nHardDisk = min(nHardDisk,MAX_HARD_DRIVE-1);
memset(foundPartitions,0,sizeof(foundPartitions));
DebugPrintf(("DSK init: found %d disk drives\n",nHardDisk));
/* Reset the drives */
for (HardDrive = 0; HardDrive < nHardDisk; HardDrive++)
BIOS_drive_reset(HardDrive);
/* Process primary partition table 1 partition only */
for (HardDrive = 0; HardDrive < nHardDisk; HardDrive++)
{
foundPartitions[HardDrive] =
ProcessDisk(SCAN_PRIMARYBOOT, HardDrive, 0);
if (foundPartitions[HardDrive] == 0)
foundPartitions[HardDrive] = ProcessDisk(SCAN_PRIMARY, HardDrive, 0);
}
/* Process extended partition table */
for (HardDrive = 0; HardDrive < nHardDisk; HardDrive++)
{
ProcessDisk(SCAN_EXTENDED, HardDrive , 0);
}
/* Process primary a 2nd time */
for (HardDrive = 0; HardDrive < nHardDisk; HardDrive++)
{
ProcessDisk(SCAN_PRIMARY2, HardDrive ,foundPartitions[HardDrive]);
}
Dyn.UsedByDiskInit = nUnits * sizeof(struct media_info);
}
/*TE - array access functions */
extern bpb FAR bpbarray[NDEV];
bpb FAR *init_getPBpbarray(unsigned dev){ return &bpbarray[dev];}
/* disk initialization: returns number of units */
COUNT dsk_init()
{
COUNT Unit;
bpb FAR *pbpbarray;
printf(" - InitDisk\n");
#ifdef DEBUG
{
iregs regs;
regs.a.x = 0x1112; /* select 43 line mode - more space for partinfo */
regs.b.x = 0;
init_call_intr(0x10, &regs);
}
#endif
/* Reset the drives */
BIOS_drive_reset(0);
/* Initial number of disk units */
nUnits = 2;
/* Setup media info and BPBs arrays */
for (Unit = 0; Unit < NDEV; Unit++)
{
pbpbarray = init_getPBpbarray(Unit);
pbpbarray->bpb_nbyte = SEC_SIZE;
pbpbarray->bpb_nsector = 2;
pbpbarray->bpb_nreserved = 1;
pbpbarray->bpb_nfat = 2;
pbpbarray->bpb_ndirent = 112;
pbpbarray->bpb_nsize = 720l;
pbpbarray->bpb_mdesc = 0xfd;
pbpbarray->bpb_nfsect = 2;
}
ReadAllPartitionTables();
return nUnits;
}

View File

@ -67,6 +67,7 @@
#include "portab.h"
#include "init-mod.h"
extern BYTE FAR version_flags; /* minor version number */
extern BYTE
@ -80,6 +81,9 @@ static BYTE *RcsId = "$Id$";
/*
* $Log$
* Revision 1.7 2001/07/09 22:19:33 bartoldeman
* LBA/FCB/FAT/SYS/Ctrl-C/ioctl fixes + memory savings
*
* Revision 1.6 2001/04/29 17:34:40 bartoldeman
* A new SYS.COM/config.sys single stepping/console output/misc fixes.
*
@ -128,6 +132,8 @@ extern void FAR *DetectXMSDriver(VOID);
#define HMAInitPrintf(x)
#endif
void MoveKernel(unsigned NewKernelSegment);
#ifdef DEBUG
VOID hdump(BYTE FAR *p)
@ -249,10 +255,6 @@ int EnableHMA(VOID)
int MoveKernelToHMA()
{
UBYTE FAR *HMASource;
unsigned len;
if (DosLoadedInHMA)
{
@ -297,137 +299,8 @@ int MoveKernelToHMA()
return FALSE;
}
MoveKernel(0xffff);
/* C) we have HMA, copy HMA_TEXT up to 0xffff:0..ffff */
{
UBYTE FAR *HMADest = MK_FP(HMASEGMENT,0x0000);
len = FP_OFF(_HMATextEnd) - FP_OFF(_HMATextStart);
HMASource = (UBYTE FAR *)_HMATextStart;
len += FP_OFF(HMASource) & 0x000f;
FP_OFF(HMASource) &= 0xfff0;
HMASource += HMAOFFSET;
HMADest += HMAOFFSET;
len -= HMAOFFSET;
HMAInitPrintf(("HMA moving %p up to %p for %04x bytes\n",
HMASource, HMADest, len));
fmemcpy(HMADest, HMASource, len);
HMAFree = FP_OFF(HMADest)+len; /* first free byte after HMA_TEXT */
}
{
/* 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 {
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
FAR _HMARelocationTableStart[],
FAR _HMARelocationTableEnd[];
struct RelocationTable FAR *rp, rtemp ;
UWORD HMATextSegment = FP_SEG( _HMATextStart );
/* verify, that all entries are valid */
for (rp = _HMARelocationTableStart; rp < _HMARelocationTableEnd; rp++)
{
if (rp->jmpFar != 0xea || /* jmp FAR */
rp->jmpSegment != HMATextSegment || /* will only relocate HMA_TEXT */
rp->callNear != 0xe8 || /* call NEAR */
0)
{
printf("illegal relocation entry # %d\n",rp - _HMARelocationTableStart);
goto errorReturn;
}
}
/* OK, all valid, go to relocate*/
for (rp = _HMARelocationTableStart; rp < _HMARelocationTableEnd; rp++)
{
struct RelocatedEntry FAR *rel = (struct RelocatedEntry FAR *)rp;
fmemcpy(&rtemp, rp, sizeof(rtemp));
rel->jmpFar = rtemp.jmpFar;
rel->jmpSegment = HMASEGMENT;
rel->jmpOffset = rtemp.jmpOffset;
rel->callNear = rtemp.callNear;
rel->callOffset = rtemp.callOffset+5; /* near calls are relative */
}
}
{
struct initRelocationTable {
UBYTE callNear;
UWORD callOffset;
UBYTE jmpFar;
UWORD jmpOffset;
UWORD jmpSegment;
};
extern struct initRelocationTable
_HMAinitRelocationTableStart[],
_HMAinitRelocationTableEnd[];
struct initRelocationTable *rp;
/* verify, that all entries are valid */
UWORD HMATextSegment = FP_SEG( _HMATextStart );
for (rp = _HMAinitRelocationTableStart; rp < _HMAinitRelocationTableEnd; rp++)
{
if (
rp->callNear != 0xe8 || /* call NEAR */
rp->jmpFar != 0xea || /* jmp FAR */
rp->jmpSegment != HMATextSegment || /* will only relocate HMA_TEXT */
0)
{
printf("illegal init relocation entry # %d\n",
rp - _HMAinitRelocationTableStart);
goto errorReturn;
}
}
/* OK, all valid, go to relocate*/
for (rp = _HMAinitRelocationTableStart; rp < _HMAinitRelocationTableEnd; rp++)
{
rp->jmpSegment = HMASEGMENT;
rp->callOffset = rp->callOffset-5; /* near calls are relative */
}
}
{
/* E) up to now, nothing really bad was done.
@ -437,8 +310,6 @@ int MoveKernelToHMA()
cause INT 3 on all accesses to this area
*/
fmemset(HMASource, 0xcc, len);
HMAInitPrintf(("HMA text segment filled with INT 3\n"));
DosLoadedInHMA = TRUE;
}
@ -575,3 +446,163 @@ VOID FAR *HMAalloc(COUNT bytesToAllocate)
return HMAptr;
}
unsigned CurrentKernelSegment = 0;
void MoveKernel(unsigned NewKernelSegment)
{
UBYTE FAR *HMADest;
UBYTE FAR *HMASource;
unsigned len;
__int__(3);
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)
{
unsigned i; UBYTE FAR *s,FAR *d;
for (i = 0, s = HMASource,d = HMADest; i < len; i++)
d[i] = s[i];
}
else {
/* might overlap */
unsigned i; UBYTE FAR *s,FAR *d;
for (i = len, s = HMASource,d = HMADest; i != 0; i--)
d[i] = s[i];
}
HMAFree = FP_OFF(HMADest)+len; /* first free byte after HMA_TEXT */
{
/* 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 {
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
FAR _HMARelocationTableStart[],
FAR _HMARelocationTableEnd[];
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 != CurrentKernelSegment || /* will only relocate HMA_TEXT */
rp->callNear != 0xe8 || /* call NEAR */
0)
{
printf("illegal relocation entry # %d\n",rp - _HMARelocationTableStart);
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;
}
}
{
struct initRelocationTable {
UBYTE callNear;
UWORD callOffset;
UBYTE jmpFar;
UWORD jmpOffset;
UWORD jmpSegment;
};
extern struct initRelocationTable
_HMAinitRelocationTableStart[],
_HMAinitRelocationTableEnd[];
struct initRelocationTable *rp;
/* verify, that all entries are valid */
for (rp = _HMAinitRelocationTableStart; rp < _HMAinitRelocationTableEnd; rp++)
{
if (
rp->callNear != 0xe8 || /* call NEAR */
rp->jmpFar != 0xea || /* jmp FAR */
rp->jmpSegment != CurrentKernelSegment || /* will only relocate HMA_TEXT */
0)
{
printf("illegal init relocation entry # %d\n",
rp - _HMAinitRelocationTableStart);
goto errorReturn;
}
}
/* OK, all valid, go to relocate*/
for (rp = _HMAinitRelocationTableStart; rp < _HMAinitRelocationTableEnd; rp++)
{
rp->jmpSegment = NewKernelSegment;
}
}
CurrentKernelSegment = NewKernelSegment;
return;
errorReturn:
for (;;);
}

View File

@ -30,6 +30,9 @@
; $Id$
;
; $Log$
; Revision 1.9 2001/07/09 22:19:33 bartoldeman
; LBA/FCB/FAT/SYS/Ctrl-C/ioctl fixes + memory savings
;
; Revision 1.8 2001/04/02 23:18:30 bartoldeman
; Misc, zero terminated device names and redirector bugs fixed.
;
@ -375,7 +378,7 @@ _Umb_Test
push bx
push cs ; setup far return
mov ax, umbt1
mov ax, umbt1
push ax
push es ; push the driver entry point
push bx
@ -401,7 +404,7 @@ umbtc:
pop es
push cs
mov ax, umbt2
mov ax, umbt2
push ax
push es
push bx

View File

@ -37,6 +37,9 @@ BYTE *RcsId = "$Id$";
/*
* $Log$
* Revision 1.25 2001/07/09 22:19:33 bartoldeman
* LBA/FCB/FAT/SYS/Ctrl-C/ioctl fixes + memory savings
*
* Revision 1.24 2001/06/03 14:16:18 bartoldeman
* BUFFERS tuning and misc bug fixes/cleanups (2024c).
*
@ -489,7 +492,7 @@ dispatch:
case 0x0a:
((keyboard FAR *) FP_DS_DX)->kb_count = 0;
sti((keyboard FAR *) FP_DS_DX);
((keyboard FAR *) FP_DS_DX)->kb_count--;
((keyboard FAR *) FP_DS_DX)->kb_count --;
break;
/* Check Stdin Status */
@ -869,29 +872,44 @@ dispatch:
/* Get DPB */
case 0x32:
r->DL = ( r->DL == 0 ? default_drive : r->DL - 1);
if (r->DL < lastdrive)
/* r->DL is NOT changed by MS 6.22 */
/* INT21/32 is documented to reread the DPB */
{
struct dpb FAR *dpb;
UCOUNT drv = r->DL;
if (drv == 0) drv = default_drive;
else drv--;
if (drv >= lastdrive)
{
r->AL = 0xFF;
CritErrCode = 0x0f;
break;
}
dpb = CDSp->cds_table[drv].cdsDpb;
if (dpb == 0 ||
CDSp->cds_table[drv].cdsFlags & CDSNETWDRV)
{
r->AL = 0xFF;
CritErrCode = 0x0f;
break;
}
dpb->dpb_flags = M_CHANGED; /* force reread of drive BPB/DPB */
if (media_check(dpb) < 0)
{
struct dpb FAR *dpb = CDSp->cds_table[r->DL].cdsDpb;
if (dpb == 0 ||
(CDSp->cds_table[r->DL].cdsFlags & CDSNETWDRV) ||
media_check(dpb) < 0)
{
r->AL = 0xff;
CritErrCode = 0x0f;
break;
}
r->DS = FP_SEG(dpb);
r->BX = FP_OFF(dpb);
r->AL = 0;
}
else {
r->AL = 0xFF;
CritErrCode = 0x0f;
r->DS = FP_SEG(dpb);
r->BX = FP_OFF(dpb);
r->AL = 0;
}
}
break;
/*
case 0x33:
see int21_syscall
@ -1772,14 +1790,14 @@ VOID int2526_handler(WORD mode, struct int25regs FAR * r)
BYTE FAR *buf;
UBYTE drv;
if (mode == 0x26) mode = DSKWRITE;
else mode = DSKREAD;
if (mode == 0x26) mode = DSKWRITEINT26;
else mode = DSKREADINT25;
drv = r->ax;
if (drv >= lastdrive)
{
r->ax = 0x202;
r->ax = 0x201;
r->flags |= FLG_CARRY;
return;
}

View File

@ -35,6 +35,9 @@ static BYTE *RcsId = "$Id$";
/*
* $Log$
* Revision 1.10 2001/07/09 22:19:33 bartoldeman
* LBA/FCB/FAT/SYS/Ctrl-C/ioctl fixes + memory savings
*
* Revision 1.9 2001/06/03 14:16:18 bartoldeman
* BUFFERS tuning and misc bug fixes/cleanups (2024c).
*
@ -270,6 +273,10 @@ COUNT DosDevIOctl(iregs FAR * r)
{
return DE_INVLDDRV;
}
if (media_check(dpbp) < 0)
{
return DE_INVLDDRV;
}
if ( ((r->AL == 0x04 ) && !(dpbp->dpb_device->dh_attr & ATTR_IOCTL))
|| ((r->AL == 0x05 ) && !(dpbp->dpb_device->dh_attr & ATTR_IOCTL))
|| ((r->AL == 0x11) && !(dpbp->dpb_device->dh_attr & ATTR_QRYIOCTL))
@ -312,7 +319,7 @@ COUNT DosDevIOctl(iregs FAR * r)
case 0x06:
if (s->sft_flags & SFT_FDEVICE)
{
r->AL = s->sft_flags & SFT_FEOF ? 0 : 0xFF;
r->AL = s->sft_flags & SFT_FEOF ? 0xFF : 0;
}
else
r->AL = s->sft_posit >= s->sft_size ? 0xFF : 0;

View File

@ -28,6 +28,9 @@
; $Id$
;
; $Log$
; Revision 1.14 2001/07/09 22:19:33 bartoldeman
; LBA/FCB/FAT/SYS/Ctrl-C/ioctl fixes + memory savings
;
; Revision 1.13 2001/06/03 14:16:18 bartoldeman
; BUFFERS tuning and misc bug fixes/cleanups (2024c).
;
@ -142,7 +145,18 @@ segment PSP
STACK_SIZE equ 384/2 ; stack allocated in words
..start:
entry: jmp far kernel_start
entry:
push ax
push bx
pushf
mov ax, 0e31h ; '1' Tracecode - kernel entered
mov bx, 00f0h
int 010h
popf
pop bx
pop ax
jmp far kernel_start
beyond_entry: resb 256-(beyond_entry-entry)
; scratch area for data (DOS_PSP)
@ -154,6 +168,17 @@ segment INIT_TEXT
; kernel start-up
;
kernel_start:
push ax
push bx
pushf
mov ax, 0e32h ; '2' Tracecode - kernel entered
mov bx, 00f0h
int 010h
popf
pop bx
pop ax
mov ax,IGROUP
cli
mov ss,ax
@ -197,6 +222,17 @@ cont: ; inititalize api stacks for high water tests
mov es,ax
mov bp,sp ; and set up stack frame for c
sti ; now enable them
push ax
push bx
pushf
mov ax, 0e33h ; '3' Tracecode - kernel entered
mov bx, 00f0h
int 010h
popf
pop bx
pop ax
inc bl
jns floppy
add bl,3-1-128
@ -918,10 +954,10 @@ __EnableA20:
enableUsingXMSdriver:
mov ah,3
UsingXMSdriver:
UsingXMSdriver:
push bx
call far [cs:_XMSDriverAddress]
pop bx
pop bx
retf
global __DisableA20

View File

@ -6,6 +6,7 @@
-d
-k-
-vi-
-w
-wpro
-weas
-wpre

View File

@ -5,6 +5,9 @@
#
# $Log$
# Revision 1.11 2001/07/09 22:19:33 bartoldeman
# LBA/FCB/FAT/SYS/Ctrl-C/ioctl fixes + memory savings
#
# Revision 1.10 2001/04/21 22:32:53 bartoldeman
# Init DS=Init CS, fixed stack overflow problems and misc bugs.
#
@ -129,6 +132,23 @@
RELEASE = 1.00
# Compiler and Options for Borland C++
# ------------------------------------
#
# -zAname ¦ ¦ Code class
# -zBname ¦ ¦ BSS class
# -zCname ¦ ¦ Code segment
# -zDname ¦ ¦ BSS segment
# -zEname ¦ ¦ Far segment
# -zFname ¦ ¦ Far class
# -zGname ¦ ¦ BSS group
# -zHname ¦ ¦ Far group
# -zPname ¦ ¦ Code group
# -zRname ¦ ¦ Data segment
# -zSname ¦ ¦ Data group
# -zTname ¦ ¦ Data class
# -zX ¦«¦ Use default name for "X"
#
# Compiler and Options for Borland C++
# ------------------------------------
@ -170,6 +190,7 @@ EXE_dependencies = \
dosfns.obj \
dosnames.obj \
dsk.obj \
initdisk.obj \
entry.obj \
error.obj \
execrh.obj \
@ -203,7 +224,9 @@ EXE_dependencies = \
syspack.obj \
systime.obj \
task.obj \
inithma.obj
inithma.obj \
DynData.obj \
DynInit.obj
# *Explicit Rules*
@ -226,13 +249,13 @@ clean:
kernel.exe: $(EXE_dependencies) $(LIBS)
$(RM) kernel.lib
$(LIBUTIL) kernel +entry +io +blockio +chario +dosfns +console
$(LIBUTIL) kernel +printer +serial +dsk +error +fatdir +fatfs
$(LIBUTIL) kernel +printer +serial +dsk +initdisk+error +fatdir +fatfs
$(LIBUTIL) kernel +fattab +fcbfns +initoem +initHMA+inthndlr +ioctl +nls_hc
$(LIBUTIL) kernel +main +config +memmgr +misc +newstuff +nls +intr
$(LIBUTIL) kernel +dosnames +prf +initprf +strings +network +sysclk +syspack
$(LIBUTIL) kernel +systime +task +int2f +irqstack +apisupt
$(LIBUTIL) kernel +asmsupt +execrh +nlssupt +procsupt +break
$(LIBUTIL) kernel +dosidle
$(LIBUTIL) kernel +dosidle+dyndata+dyninit
$(RM) kernel.bak
$(LINK) /m/c/L$(LIBPATH) kernel,kernel,kernel,kernel+$(LIBS);
$(RM) kernel.lib
@ -277,7 +300,7 @@ config.obj: config.c init-mod.h $(HDR)portab.h globals.h \
$(HDR)fat.h $(HDR)fcb.h $(HDR)tail.h $(HDR)process.h $(HDR)dcb.h \
$(HDR)sft.h $(HDR)cds.h $(HDR)exe.h $(HDR)fnode.h \
$(HDR)dirmatch.h $(HDR)file.h $(HDR)clock.h $(HDR)kbd.h \
$(HDR)error.h $(HDR)version.h proto.h turboc.cfg
$(HDR)error.h $(HDR)version.h proto.h turboc.cfg dyndata.h
$(CC) $(INITCFLAGS) -c config.c
initoem.obj: initoem.c init-mod.h $(HDR)portab.h globals.h \
@ -285,7 +308,7 @@ initoem.obj: initoem.c init-mod.h $(HDR)portab.h globals.h \
$(HDR)fat.h $(HDR)fcb.h $(HDR)tail.h $(HDR)process.h $(HDR)dcb.h \
$(HDR)sft.h $(HDR)cds.h $(HDR)exe.h $(HDR)fnode.h \
$(HDR)dirmatch.h $(HDR)file.h $(HDR)clock.h $(HDR)kbd.h \
$(HDR)error.h $(HDR)version.h proto.h turboc.cfg
$(HDR)error.h $(HDR)version.h proto.h turboc.cfg dyndata.h
$(CC) $(INITCFLAGS) -c initoem.c
main.obj: main.c init-mod.h $(HDR)portab.h globals.h $(HDR)device.h \
@ -293,7 +316,7 @@ main.obj: main.c init-mod.h $(HDR)portab.h globals.h $(HDR)device.h \
$(HDR)fcb.h $(HDR)tail.h $(HDR)process.h $(HDR)dcb.h $(HDR)sft.h \
$(HDR)cds.h $(HDR)exe.h $(HDR)fnode.h $(HDR)dirmatch.h \
$(HDR)file.h $(HDR)clock.h $(HDR)kbd.h $(HDR)error.h \
$(HDR)version.h proto.h turboc.cfg
$(HDR)version.h proto.h turboc.cfg dyndata.h
$(CC) $(INITCFLAGS) -c main.c
initHMA.obj: initHMA.c init-mod.h $(HDR)portab.h globals.h $(HDR)device.h \
@ -301,9 +324,40 @@ initHMA.obj: initHMA.c init-mod.h $(HDR)portab.h globals.h $(HDR)device.h \
$(HDR)fcb.h $(HDR)tail.h $(HDR)process.h $(HDR)dcb.h $(HDR)sft.h \
$(HDR)cds.h $(HDR)exe.h $(HDR)fnode.h $(HDR)dirmatch.h \
$(HDR)file.h $(HDR)clock.h $(HDR)kbd.h $(HDR)error.h \
$(HDR)version.h proto.h turboc.cfg
$(HDR)version.h proto.h turboc.cfg dyndata.h
$(CC) $(INITCFLAGS) -c initHMA.c
DynInit.obj: DynInit.c init-mod.h $(HDR)portab.h globals.h $(HDR)device.h \
$(HDR)mcb.h $(HDR)pcb.h $(HDR)date.h $(HDR)time.h $(HDR)fat.h \
$(HDR)fcb.h $(HDR)tail.h $(HDR)process.h $(HDR)dcb.h $(HDR)sft.h \
$(HDR)cds.h $(HDR)exe.h $(HDR)fnode.h $(HDR)dirmatch.h \
$(HDR)file.h $(HDR)clock.h $(HDR)kbd.h $(HDR)error.h \
$(HDR)version.h proto.h turboc.cfg dyndata.h
$(CC) $(INITCFLAGS) -c DynInit.c
initdisk.obj: initdisk.c disk.h $(HDR)portab.h globals.h $(HDR)device.h $(HDR)mcb.h \
$(HDR)pcb.h $(HDR)date.h $(HDR)time.h $(HDR)fat.h $(HDR)fcb.h \
$(HDR)tail.h $(HDR)process.h $(HDR)dcb.h $(HDR)sft.h $(HDR)cds.h \
$(HDR)exe.h $(HDR)fnode.h $(HDR)dirmatch.h $(HDR)file.h \
$(HDR)clock.h $(HDR)kbd.h $(HDR)error.h $(HDR)version.h proto.h \
turboc.cfg dyndata.h
$(CC) $(INITCFLAGS) -c initDISK.c
# -zBname ¦ ¦ BSS class
# -zDname ¦ ¦ BSS segment
# -zEname ¦ ¦ Far segment
# -zFname ¦ ¦ Far class
# -zGname ¦ ¦ BSS group
# -zHname ¦ ¦ Far group
# -zRname ¦ ¦ Data segment
# -zSname ¦ ¦ Data group
# -zTname ¦ ¦ Data class
dynDATA.obj: dynDATA.c dynDATA.H
$(CC) -c -zRDYN_DATA -zTDYN_DATA -zDDYN_DATA -zBDYN_DATA dynDATA.c
#the printf for INIT_TEXT:
initprf.obj: prf.c $(HDR)portab.h turboc.cfg
$(CC) -DFORINIT $(INITCFLAGS) -oinitprf.obj -c prf.c
@ -345,13 +399,14 @@ dosnames.obj: dosnames.c $(HDR)portab.h globals.h $(HDR)device.h \
$(HDR)file.h $(HDR)clock.h $(HDR)kbd.h $(HDR)error.h \
$(HDR)version.h proto.h turboc.cfg
dsk.obj: dsk.c $(HDR)portab.h globals.h $(HDR)device.h $(HDR)mcb.h \
dsk.obj: dsk.c disk.h $(HDR)portab.h globals.h $(HDR)device.h $(HDR)mcb.h \
$(HDR)pcb.h $(HDR)date.h $(HDR)time.h $(HDR)fat.h $(HDR)fcb.h \
$(HDR)tail.h $(HDR)process.h $(HDR)dcb.h $(HDR)sft.h $(HDR)cds.h \
$(HDR)exe.h $(HDR)fnode.h $(HDR)dirmatch.h $(HDR)file.h \
$(HDR)clock.h $(HDR)kbd.h $(HDR)error.h $(HDR)version.h proto.h \
turboc.cfg
error.obj: error.c $(HDR)portab.h globals.h $(HDR)device.h \
$(HDR)mcb.h $(HDR)pcb.h $(HDR)date.h $(HDR)time.h $(HDR)fat.h \
$(HDR)fcb.h $(HDR)tail.h $(HDR)process.h $(HDR)dcb.h $(HDR)sft.h \

View File

@ -71,6 +71,9 @@ static BYTE *mainRcsId = "$Id$";
/*
* $Log$
* Revision 1.18 2001/07/09 22:19:33 bartoldeman
* LBA/FCB/FAT/SYS/Ctrl-C/ioctl fixes + memory savings
*
* Revision 1.17 2001/06/03 14:16:18 bartoldeman
* BUFFERS tuning and misc bug fixes/cleanups (2024c).
*
@ -309,8 +312,14 @@ INIT void init_kernel(void)
/* Do first initialization of system variable buffers so that */
/* we can read config.sys later. */
lastdrive = Config.cfgLastdrive;
PreConfig();
init_device((struct dhdr FAR *)&blk_dev, NULL, NULL, ram_top);
/* init_device((struct dhdr FAR *)&blk_dev, NULL, NULL, ram_top); */
blk_dev.dh_name[0] = dsk_init();
/* Number of units */
if (blk_dev.dh_name[0] > 0)
update_dcb(&blk_dev);
/* Now config the temporary file system */
FsConfig();

View File

@ -44,6 +44,9 @@ static BYTE *RcsId = "$Id$";
/*
* $Log$
* Revision 1.8 2001/07/09 22:19:33 bartoldeman
* LBA/FCB/FAT/SYS/Ctrl-C/ioctl fixes + memory savings
*
* Revision 1.7 2001/06/03 14:16:18 bartoldeman
* BUFFERS tuning and misc bug fixes/cleanups (2024c).
*
@ -124,7 +127,7 @@ struct nlsInfoBlock nlsInfo = {
/*== DS:SI _always_ points to global NLS info structure <-> no
* subfct can use these registers for anything different. ==ska*/
static COUNT muxGo(int subfct, iregs *rp)
STATIC COUNT muxGo(int subfct, iregs *rp)
{
log( ("NLS: muxGo(): subfct=%x, cntry=%u, cp=%u, ES:DI=%04x:%04x\n", subfct
, rp->DX, rp->BX, rp->ES, rp->DI) );
@ -162,7 +165,7 @@ COUNT muxLoadPkg(UWORD cp, UWORD cntry)
return muxGo(NLSFUNC_LOAD_PKG, &r);
}
static int muxBufGo(int subfct, int bp, UWORD cp, UWORD cntry, UWORD bufsize
STATIC int muxBufGo(int subfct, int bp, UWORD cp, UWORD cntry, UWORD bufsize
, VOID FAR *buf)
{ iregs r;
@ -195,7 +198,7 @@ log( ("NLS: muxBufGo(): subfct=%x, BP=%u, cp=%u, cntry=%u, len=%u, buf=%04x:%04x
* Also resolves the default values (-1) into the currently
* active codepage/country code.
*/
static struct nlsPackage FAR *searchPackage(UWORD cp, UWORD cntry)
STATIC struct nlsPackage FAR *searchPackage(UWORD cp, UWORD cntry)
{ struct nlsPackage FAR *nls;
if(cp == NLS_DEFAULT)
@ -213,7 +216,7 @@ static struct nlsPackage FAR *searchPackage(UWORD cp, UWORD cntry)
/* For various robustnesses reasons and to simplify the implementation
at other places, locateSubfct() returns NULL (== "not found"),
if nls == NULL on entry. */
static VOID FAR *locateSubfct(struct nlsPackage FAR *nls, int subfct)
STATIC VOID FAR *locateSubfct(struct nlsPackage FAR *nls, int subfct)
{ int cnt;
struct nlsPointer FAR *p;
@ -232,7 +235,7 @@ static VOID FAR *locateSubfct(struct nlsPackage FAR *nls, int subfct)
function is guaranteed to return valid pointers, rather than
to let the user (some kernel function) deal with non-existing
tables -- 2000/02/26 ska*/
static VOID FAR *getTable(UBYTE subfct, struct nlsPackage FAR *nls)
STATIC VOID FAR *getTable(UBYTE subfct, struct nlsPackage FAR *nls)
{ struct nlsPointer FAR *poi;
if((poi = locateSubfct(nls, subfct)) != NULL)
@ -258,7 +261,7 @@ static VOID FAR *getTable(UBYTE subfct, struct nlsPackage FAR *nls)
* the code to push bufsize, buf, call cpyBuf() and return its result.
* The parameter were ordered to allow this code optimization.
*/
static COUNT cpyBuf(VOID FAR *dst, UWORD dstlen
STATIC COUNT cpyBuf(VOID FAR *dst, UWORD dstlen
, VOID FAR *src, UWORD srclen)
{
if(srclen <= dstlen) {
@ -274,7 +277,7 @@ static COUNT cpyBuf(VOID FAR *dst, UWORD dstlen
* This function assumes that 'map' is adjusted such that
* map[0x80] is the uppercase of character 0x80.
*== 128 byte chartables, lower range conform to 7bit-US-ASCII ==ska*/
static VOID upMMem(UBYTE FAR *map, UBYTE FAR * str, unsigned len)
STATIC VOID upMMem(UBYTE FAR *map, UBYTE FAR * str, unsigned len)
{
REG unsigned c;
@ -316,7 +319,7 @@ printf("NLS: upMMem(): result=\"");
the direct-access interface.
subfct == NLS_DOS_38 is a value > 0xff in order to not clash
with subfunctions valid to be passed as DOS-65-XX. */
static int nlsGetData(struct nlsPackage FAR *nls, int subfct, UBYTE FAR *buf
STATIC int nlsGetData(struct nlsPackage FAR *nls, int subfct, UBYTE FAR *buf
, unsigned bufsize)
{ VOID FAR *poi;
@ -385,7 +388,7 @@ VOID nlsCPchange(UWORD cp)
* appropriate codepage on its own.
*/
static COUNT nlsSetPackage(struct nlsPackage FAR *nls)
STATIC COUNT nlsSetPackage(struct nlsPackage FAR *nls)
{
if(nls->cp != nlsInfo.actPkg->cp) /* Codepage gets changed -->
inform all character drivers thereabout.
@ -397,7 +400,7 @@ static COUNT nlsSetPackage(struct nlsPackage FAR *nls)
return SUCCESS;
}
static COUNT DosSetPackage(UWORD cp, UWORD cntry)
STATIC COUNT DosSetPackage(UWORD cp, UWORD cntry)
{ struct nlsPackage FAR*nls; /* NLS package to use to return the info from */
/* nls := NLS package of cntry/codepage */
@ -409,18 +412,18 @@ static COUNT DosSetPackage(UWORD cp, UWORD cntry)
return muxLoadPkg(cp, cntry);
}
static void nlsUpMem(struct nlsPackage FAR *nls, VOID FAR *str, int len)
STATIC void nlsUpMem(struct nlsPackage FAR *nls, VOID FAR *str, int len)
{
log( ("NLS: nlsUpMem()\n") );
upMMem(getCharTbl2(nls), (UBYTE FAR*)str, len);
}
static void nlsFUpMem(struct nlsPackage FAR *nls, VOID FAR *str, int len)
STATIC void nlsFUpMem(struct nlsPackage FAR *nls, VOID FAR *str, int len)
{
log( ("NLS: nlsFUpMem()\n") );
upMMem(getCharTbl4(nls), (UBYTE FAR*)str, len);
}
static VOID xUpMem(struct nlsPackage FAR *nls, VOID FAR * str, unsigned len)
STATIC VOID xUpMem(struct nlsPackage FAR *nls, VOID FAR * str, unsigned len)
/* upcase a memory area */
{
log( ("NLS: xUpMem(): cp=%u, cntry=%u\n", nls->cp, nls->cntry) );
@ -431,7 +434,7 @@ log( ("NLS: xUpMem(): cp=%u, cntry=%u\n", nls->cp, nls->cntry) );
muxBufGo(NLSFUNC_UPMEM, 0, nls->cp, nls->cntry, len, str);
}
static int nlsYesNo(struct nlsPackage FAR *nls, unsigned char ch)
STATIC int nlsYesNo(struct nlsPackage FAR *nls, unsigned char ch)
{
assertDSeqSS(); /* because "&ch" */

View File

@ -29,6 +29,9 @@
; $Header$
;
; $Log$
; Revision 1.8 2001/07/09 22:19:33 bartoldeman
; LBA/FCB/FAT/SYS/Ctrl-C/ioctl fixes + memory savings
;
; Revision 1.7 2001/04/29 17:34:40 bartoldeman
; A new SYS.COM/config.sys single stepping/console output/misc fixes.
;
@ -68,7 +71,7 @@
group PGROUP PSP
group TGROUP _TEXT _IO_TEXT _IO_FIXED_DATA
group DGROUP _FIXED_DATA _DATA _BSSSTART _BSS _BSSEND
group DGROUP _FIXED_DATA _DATA _BSSSTART _BSS _BSSEND DYN_DATA
group HGROUP HMA_TEXT_START HMA_TEXT HMA_TEXT_END
group IGROUP INIT_TEXT_START INIT_TEXT INIT_TEXT_END ID_B ID ID_E IB_B IB IB_E
@ -81,6 +84,7 @@ segment _DATA class=DATA align=2
segment _BSSSTART class=BSS align=2
segment _BSS class=BSS align=2
segment _BSSEND class=BSS
segment DYN_DATA class=DYN_DATA
segment HMA_TEXT_START class=HMA align=16
segment HMA_TEXT class=HMA
segment HMA_TEXT_END class=HMA

166
sys/sys.c
View File

@ -25,6 +25,17 @@
675 Mass Ave, Cambridge, MA 02139, USA.
***************************************************************/
/* $Log$
* Revision 1.7 2001/07/09 22:19:33 bartoldeman
* LBA/FCB/FAT/SYS/Ctrl-C/ioctl fixes + memory savings
*
/* Revision 2.1 tomehlert 2001/4/26
changed the file system detection code.
*/
/* Revision 2.0 tomehlert 2001/4/26
no direct access to the disk any more, this is FORMAT's job
@ -44,33 +55,9 @@
size is no ~7500 byte vs. ~13690 before
*/
/* $Log$
* Revision 1.6 2001/04/29 17:34:41 bartoldeman
* /* Revision 2.1 tomehlert 2001/4/26
*
* changed the file system detection code.
* */
*
* /* Revision 2.0 tomehlert 2001/4/26
*
* no direct access to the disk any more, this is FORMAT's job
* no floppy.asm anymore, no segmentation problems.
* no access to partition tables
*
* instead copy boot sector using int25/int26 = absdiskread()/write
*
* if xxDOS is able to handle the disk, SYS should work
*
* additionally some space savers:
*
* replaced fopen() by open()
*
* included (slighly modified) PRF.c from kernel
*
* size is no ~7500 byte vs. ~13690 before
* */
*
/* Revision 1.6 2001/04/29 17:34:41 bartoldeman
/* A new SYS.COM/config.sys single stepping/console output/misc fixes.
/*
/* Revision 1.5 2001/03/25 17:11:54 bartoldeman
/* Fixed sys.com compilation. Updated to 2023. Also: see history.txt.
/*
@ -203,7 +190,7 @@ UBYTE newboot[SEC_SIZE], oldboot[SEC_SIZE];
VOID main(COUNT argc, char **argv)
{
printf("FreeDOS System Installer v1.0\n\n");
printf("FreeDOS System Installer v2.1\n\n");
if (argc != 2)
{
@ -277,6 +264,38 @@ VOID dump_sector(unsigned char far * sec)
#endif
/*
TC absRead not functional on MSDOS 6.2, large disks
MSDOS requires int25, CX=ffff for drives > 32MB
*/
int MyAbsReadWrite(char DosDrive, int count, ULONG sector, void *buffer, unsigned intno)
{
struct {
unsigned long sectorNumber;
unsigned short count;
void far *address;
} diskReadPacket;
int retval;
union REGS regs;
diskReadPacket.sectorNumber = sector;
diskReadPacket.count = count;
diskReadPacket.address = buffer;
regs.h.al = DosDrive;
regs.x.bx = (short)&diskReadPacket;
regs.x.cx = 0xffff;
if (intno != 0x25 && intno != 0x26) return 0xff;
int86(intno,&regs,&regs);
return regs.x.cflag ? 0xff : 0;
}
VOID put_boot(COUNT drive)
{
COUNT i, z;
@ -284,13 +303,18 @@ VOID put_boot(COUNT drive)
WORD count;
ULONG temp;
struct bootsectortype *bs;
int fs;
union REGS regs;
struct SREGS sregs;
char drivename[] = "A:\\";
unsigned char x[0x40];
#ifdef DEBUG
printf("Reading old bootsector from drive %c:\n",drive+'A');
#endif
if (absread(drive, 1, 0, oldboot) != 0)
if (MyAbsReadWrite(drive, 1, 0, oldboot,0x25) != 0)
{
printf("can't read old boot sector for drive %c:\n", drive +'A');
exit(1);
@ -302,23 +326,95 @@ VOID put_boot(COUNT drive)
dump_sector(oldboot);
#endif
bs = (struct bootsectortype *) & oldboot;
if ((bs->bsFileSysType[4] == '6') && (bs->bsBootSignature == 0x29))
{
memcpy(newboot, b_fat16, SEC_SIZE); /* copy FAT16 boot sector */
printf("FAT type: FAT16\n");
fs = 16;
}
else
{
memcpy(newboot, b_fat12, SEC_SIZE); /* copy FAT12 boot sector */
printf("FAT type: FAT12\n");
fs = 12;
}
/*
the above code is not save enough for me (TE), so we change the
FS detection method to GetFreeDiskSpace().
this should work, as the disk was writeable, so GetFreeDiskSpace should work.
*/
regs.h.ah = 0x36; /* get drive free space */
regs.h.dl = drive+1; /* 1 = 'A',... */
int86(0x21,&regs,&regs);
if (regs.x.ax == 0xffff)
{
printf("can't get free disk space for %c:\n", drive+'A');
exit(1);
}
if (regs.x.dx <= 0xff6)
{
if (fs != 12) printf("warning : new detection overrides old detection\a\n");
fs = 12;
}
else {
if (fs != 16) printf("warning : new detection overrides old detection\a\n");
fs = 16;
/* fs = 16/32.
we don't want to crash a FAT32 drive
*/
segread(&sregs);
sregs.es = sregs.ds;
regs.x.ax = 0x7303; /* get extended drive free space */
drivename[0] = 'A' + drive;
regs.x.dx = (unsigned)&drivename;
regs.x.di = (unsigned)&x;
regs.x.cx = sizeof(x);
int86x(0x21,&regs,&regs,&sregs);
if (regs.x.cflag) /* error --> no Win98 --> no FAT32 */
{
printf("get extended drive space not supported --> no FAT32\n");
}
else {
if (*(unsigned long *)(x+0x2c) /* total number of clusters */
> (unsigned)65526l)
{
fs = 32;
}
}
}
if (fs == 16)
{
memcpy(newboot, b_fat16, SEC_SIZE); /* copy FAT16 boot sector */
printf("FAT type: FAT16\n");
}
else if (fs == 12)
{
memcpy(newboot, b_fat12, SEC_SIZE); /* copy FAT12 boot sector */
printf("FAT type: FAT12\n");
}
else {
printf("FAT type: FAT32\n");
printf("Sorry, we don't have a FAT32 boot sector (yet)\n");
printf(" for this reason, we can't make the drive bootable\n");
exit(1);
}
/* Copy disk parameter from old sector to new sector */
memcpy(&newboot[SBOFFSET], &oldboot[SBOFFSET], SBSIZE);
bs = (struct bootsectortype *) & newboot;
memcpy(bs->OemName, "FreeDOS ",8);
#ifdef STORE_BOOT_INFO
/* TE thinks : never, see above */
@ -366,7 +462,7 @@ VOID put_boot(COUNT drive)
printf("writing new bootsector to drive %c:\n",drive+'A');
#endif
if (abswrite(drive, 1, 0, newboot) != 0)
if (MyAbsReadWrite(drive, 1, 0, newboot,0x26) != 0)
{
printf("Can't write new boot sector to drive %c:\n", drive +'A');
exit(1);