From c1b189648047e7e6910f9f1a0b24ed217e83eeb0 Mon Sep 17 00:00:00 2001 From: Bart Oldeman Date: Mon, 9 Jul 2001 22:19:33 +0000 Subject: [PATCH] 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 --- build.bat | 13 + docs/build.txt | 8 + docs/history.txt | 74 ++- docs/relnotes.txt | 177 +++++++ drivers/floppy.asm | 142 +++++- hdr/dirmatch.h | 4 + hdr/fat.h | 7 +- hdr/fcb.h | 5 +- hdr/fnode.h | 5 +- hdr/sft.h | 4 + hdr/version.h | 2 +- kernel/blockio.c | 52 +- kernel/config.c | 158 +++--- kernel/console.asm | 9 +- kernel/disk.h | 68 +++ kernel/dosfns.c | 7 +- kernel/dsk.c | 1180 +++++++++++++++++--------------------------- kernel/dyndata.c | 11 + kernel/dyndata.h | 25 + kernel/dyninit.c | 109 ++++ kernel/fatdir.c | 89 +++- kernel/fatfs.c | 206 ++++++-- kernel/fattab.c | 136 +++-- kernel/fcbfns.c | 60 ++- kernel/globals.h | 7 + kernel/init-mod.h | 8 + kernel/initdisk.c | 985 ++++++++++++++++++++++++++++++++++++ kernel/inithma.c | 303 +++++++----- kernel/int2f.asm | 7 +- kernel/inthndlr.c | 58 ++- kernel/ioctl.c | 9 +- kernel/kernel.asm | 42 +- kernel/kernel.cfg | 1 + kernel/kernel.mak | 71 ++- kernel/main.c | 11 +- kernel/nls.c | 31 +- kernel/segs.inc | 6 +- sys/sys.c | 166 +++++-- 38 files changed, 3084 insertions(+), 1172 deletions(-) create mode 100644 docs/relnotes.txt create mode 100644 kernel/disk.h create mode 100644 kernel/dyndata.c create mode 100644 kernel/dyndata.h create mode 100644 kernel/dyninit.c create mode 100644 kernel/initdisk.c diff --git a/build.bat b/build.bat index b249898..8a58445 100644 --- a/build.bat +++ b/build.bat @@ -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 .. diff --git a/docs/build.txt b/docs/build.txt index f5af049..4421bc5 100644 --- a/docs/build.txt +++ b/docs/build.txt @@ -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) diff --git a/docs/history.txt b/docs/history.txt index 220bedd..4e95694 100644 --- a/docs/history.txt +++ b/docs/history.txt @@ -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: diff --git a/docs/relnotes.txt b/docs/relnotes.txt new file mode 100644 index 0000000..787c31b --- /dev/null +++ b/docs/relnotes.txt @@ -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 +#include +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) diff --git a/drivers/floppy.asm b/drivers/floppy.asm index e5443de..7890dc2 100644 --- a/drivers/floppy.asm +++ b/drivers/floppy.asm @@ -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 diff --git a/hdr/dirmatch.h b/hdr/dirmatch.h index 0767990..8d686ed 100644 --- a/hdr/dirmatch.h +++ b/hdr/dirmatch.h @@ -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 */ diff --git a/hdr/fat.h b/hdr/fat.h index 6a287a0..b316ad7 100644 --- a/hdr/fat.h +++ b/hdr/fat.h @@ -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 */ diff --git a/hdr/fcb.h b/hdr/fcb.h index ac63ca9..1b97f58 100644 --- a/hdr/fcb.h +++ b/hdr/fcb.h @@ -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 */ diff --git a/hdr/fnode.h b/hdr/fnode.h index d7d3d87..ff56de3 100644 --- a/hdr/fnode.h +++ b/hdr/fnode.h @@ -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; diff --git a/hdr/sft.h b/hdr/sft.h index 7decb20..47d5a49 100644 --- a/hdr/sft.h +++ b/hdr/sft.h @@ -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 */ diff --git a/hdr/version.h b/hdr/version.h index b570340..31cfec1 100644 --- a/hdr/version.h +++ b/hdr/version.h @@ -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" diff --git a/kernel/blockio.c b/kernel/blockio.c index 098213a..f7dc357 100644 --- a/kernel/blockio.c +++ b/kernel/blockio.c @@ -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 */ diff --git a/kernel/config.c b/kernel/config.c index d9b60d7..3446cbf 100644 --- a/kernel/config.c +++ b/kernel/config.c @@ -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; } + diff --git a/kernel/console.asm b/kernel/console.asm index 8705147..f43661a 100644 --- a/kernel/console.asm +++ b/kernel/console.asm @@ -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) diff --git a/kernel/disk.h b/kernel/disk.h new file mode 100644 index 0000000..a50df6f --- /dev/null +++ b/kernel/disk.h @@ -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 */ +}; diff --git a/kernel/dosfns.c b/kernel/dosfns.c index 482da59..b77f73c 100644 --- a/kernel/dosfns.c +++ b/kernel/dosfns.c @@ -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; diff --git a/kernel/dsk.c b/kernel/dsk.c index 59bbd6a..c4a8a4c 100644 --- a/kernel/dsk.c +++ b/kernel/dsk.c @@ -26,14 +26,23 @@ #include "portab.h" #include "globals.h" +#include "disk.h" #ifdef VERSION_STRINGS static BYTE *dskRcsId = "$Id$"; #endif /* * $Log$ - * Revision 1.16 2001/04/29 17:34:40 bartoldeman - * A new SYS.COM/config.sys single stepping/console output/misc fixes. + * Revision 1.17 2001/07/09 22:19:33 bartoldeman + * LBA/FCB/FAT/SYS/Ctrl-C/ioctl fixes + memory savings + * + * Revision 1.17 2001/05/13 tomehlert + * Added full support for LBA hard drives + * initcode moved (mostly) to initdisk.c + * lower interface partly redesigned + * + * Revision 1.16 2001/04/29 brianreifsnyder + * Added phase 1 support for LBA hard drives * * Revision 1.15 2001/04/16 01:45:26 bartoldeman * Fixed handles, config.sys drivers, warnings. Enabled INT21/AH=6C, printf %S/%Fs @@ -138,9 +147,9 @@ static BYTE *dskRcsId = "$Id$"; */ #if defined(DEBUG) - #define PartCodePrintf(x) printf x + #define DebugPrintf(x) printf x #else - #define PartCodePrintf(x) + #define DebugPrintf(x) #endif #define STATIC @@ -153,10 +162,16 @@ BOOL fl_reset(WORD); COUNT fl_readdasd(WORD); COUNT fl_diskchanged(WORD); COUNT fl_rd_status(WORD); + COUNT fl_read(WORD, WORD, WORD, WORD, WORD, BYTE FAR *); COUNT fl_write(WORD, WORD, WORD, WORD, WORD, BYTE FAR *); COUNT fl_verify(WORD, WORD, WORD, WORD, WORD, BYTE FAR *); -BOOL fl_format(WORD, BYTE FAR *); + +extern COUNT fl_lba_ReadWrite (BYTE drive, WORD mode, + struct _bios_LBA_address_packet FAR *dap_p); + +int LBA_Transfer(struct DriveParamS *driveParam ,UWORD mode, VOID FAR *buffer, + ULONG LBA_address,unsigned total, UWORD *transferred); #else BOOL fl_reset(); COUNT fl_readdasd(); @@ -165,52 +180,26 @@ COUNT fl_rd_status(); COUNT fl_read(); COUNT fl_write(); COUNT fl_verify(); -BOOL fl_format(); #endif -#define NDEV 8 /* only one for demo */ -#define SEC_SIZE 512 /* size of sector in bytes */ -#define N_RETRY 5 /* number of retries permitted */ #define NENTRY 26 /* total size of dispatch table */ extern BYTE FAR nblk_rel; - /* this buffer must not overlap a 64K boundary - due to DMA transfers - this is certainly true, if located somewhere - at 0xf+1000 and must hold already during BOOT time - */ -union -{ - BYTE bytes[1 * SEC_SIZE]; - boot boot_sector; -} DiskTransferBuffer; - - -STATIC struct media_info -{ - ULONG mi_size; /* physical sector count */ - UWORD mi_heads; /* number of heads (sides) */ - UWORD mi_cyls; /* number of cyl/drive */ - UWORD mi_sectors; /* number of sectors/cyl */ - ULONG mi_offset; /* relative partition offset */ - BYTE mi_drive; /* BIOS drive number */ - ULONG mi_FileOC; /* Count of Open files on Drv */ - - UWORD mi_BeginCylinder; - BYTE mi_BeginHead; - BYTE mi_BeginSector; - - struct FS_info - { - ULONG serialno; - BYTE volume[11]; - BYTE fstype[8]; - }fs; -}; +#define LBA_READ 0x4200 +#define LBA_WRITE 0x4300 +UWORD LBA_WRITE_VERIFY = 0x4302; +#define LBA_VERIFY 0x4400 +extern void __int__(int); + /* this buffer must not overlap a 64K boundary + due to DMA transfers + this is certainly true, if located somewhere + at 0xf+1000 and must hold already during BOOT time + */ +UBYTE DiskTransferBuffer[1 * SEC_SIZE]; static struct Access_info { @@ -218,40 +207,39 @@ static struct Access_info BYTE AI_Flag; }; -STATIC struct media_info miarray[NDEV]; /* Internal media info structs */ -STATIC bpb bpbarray[NDEV]; /* BIOS parameter blocks */ -STATIC bpb *bpbptrs[NDEV]; /* pointers to bpbs */ +struct media_info *miarrayptr; /* Internal media info structs */ +bpb bpbarray[NDEV]; /* BIOS parameter blocks */ +/* STATIC bpb *bpbptrs[NDEV]; pointers to bpbs */ /*TE - array access functions */ -struct media_info *getPMiarray(int dev) { return &miarray[dev];} +struct media_info *getPMiarray(int dev) { return &miarrayptr[dev];} bpb *getPBpbarray(unsigned dev){ return &bpbarray[dev];} #define N_PART 4 /* number of partitions per - table partition */ + table partition */ -STATIC COUNT nUnits; /* number of returned units */ +COUNT nUnits; /* number of returned units */ #define PARTOFF 0x1be #ifdef PROTO -WORD _dsk_init(rqptr), - mediachk(rqptr), - bldbpb(rqptr), - blockio(rqptr), - IoctlQueblk(rqptr), - Genblkdev(rqptr), - Getlogdev(rqptr), - Setlogdev(rqptr), - blk_Open(rqptr), - blk_Close(rqptr), - blk_Media(rqptr), - blk_noerr(rqptr), - blk_nondr(rqptr), - blk_error(rqptr); -COUNT ltop(WORD *, WORD *, WORD *, COUNT, COUNT, ULONG, byteptr); +WORD + _dsk_init (rqptr rq, struct media_info *pmiarray), + mediachk (rqptr rq, struct media_info *pmiarray), + bldbpb (rqptr rq, struct media_info *pmiarray), + blockio (rqptr rq, struct media_info *pmiarray), + IoctlQueblk(rqptr rq, struct media_info *pmiarray), + Genblkdev (rqptr rq, struct media_info *pmiarray), + Getlogdev (rqptr rq, struct media_info *pmiarray), + Setlogdev (rqptr rq, struct media_info *pmiarray), + blk_Open (rqptr rq, struct media_info *pmiarray), + blk_Close (rqptr rq, struct media_info *pmiarray), + blk_Media (rqptr rq, struct media_info *pmiarray), + blk_noerr (rqptr rq, struct media_info *pmiarray), + blk_nondr (rqptr rq, struct media_info *pmiarray), + blk_error (rqptr rq, struct media_info *pmiarray); WORD dskerr(COUNT); -COUNT processtable(int table_type,COUNT ptDrive, BYTE ptHead, UWORD ptCylinder, BYTE ptSector, LONG ptAccuOff, UWORD PartitionDone); #else WORD _dsk_init(), mediachk(), @@ -268,7 +256,6 @@ WORD _dsk_init(), blk_nondr(), blk_error(); WORD dskerr(); -COUNT processtable(); #endif /* */ @@ -276,7 +263,7 @@ COUNT processtable(); /* */ #ifdef PROTO -static WORD(*dispatch[NENTRY]) (rqptr) = +static WORD(*dispatch[NENTRY]) (rqptr rq, struct media_info *pmiarray) = #else static WORD(*dispatch[NENTRY]) () = #endif @@ -309,329 +296,19 @@ static WORD(*dispatch[NENTRY]) () = IoctlQueblk /* Ioctl Query */ }; -#define SIZEOF_PARTENT 16 -#define PRIMARY 0x01 -#define PRIMARY2 0x02 + + -#define FAT12 0x01 -#define FAT16SMALL 0x04 -#define EXTENDED 0x05 -#define FAT16LARGE 0x06 -#define EXTENDED_INT32 0x0f /* like 0x05, but uses extended INT32 */ #define hd(x) ((x) & 0x80) +/* ----------------------------------------------------------------------- */ +/* F U N C T I O N S --------------------------------------------------- */ +/* ----------------------------------------------------------------------- */ -ULONG StartSector(WORD ptDrive, unsigned BeginCylinder, - unsigned BeginHead, - unsigned BeginSector, - ULONG peStartSector, - ULONG ptAccuOff) -{ - iregs regs; - - unsigned heads,sectors; - ULONG startPos; - ULONG oldStartPos; - - regs.a.x = 0x0800; /* get drive parameters */ - regs.d.x = ptDrive; - intr(0x13, ®s); - - if ((regs.a.x & 0xff) != 0) - { - PartCodePrintf(("error getting drive parameters for drive %x\n", ptDrive)); - return peStartSector+ptAccuOff; - } - - /* cylinders = (regs.c.x >>8) | ((regs.c.x & 0x0c) << 2); */ - heads = (regs.d.x >> 8) + 1; - sectors = regs.c.x & 0x3f; - - startPos = ((ULONG)BeginCylinder * heads + BeginHead) * sectors + BeginSector - 1; - PartCodePrintf((" CHS %x %x %x (%d %d %d) --> %lx ( %ld)\n", - BeginCylinder, BeginHead, BeginSector, - BeginCylinder, BeginHead, BeginSector, - startPos, startPos)); - - - oldStartPos = peStartSector + ptAccuOff; - - PartCodePrintf(("oldStartPos = %lx - ", oldStartPos)); - - - if (startPos != oldStartPos) - { - PartCodePrintf(("PART TABLE mismatch for drive %x, CHS=%d %d %d, startsec %d, offset %ld\n", - ptDrive, BeginCylinder, BeginHead,BeginSector, - peStartSector, ptAccuOff)); - - PartCodePrintf((" old startpos = %ld, new startpos = %ld, using new\n", - oldStartPos, startPos)); - } - - return startPos; -} - -/* - 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. - -******************************************************** - -I don't know, if I did it right, but I tried to do it that way. TE - -*/ -COUNT processtable(int table_type,COUNT ptDrive, BYTE ptHead, UWORD ptCylinder, - BYTE ptSector, LONG ptAccuOff, UWORD PartitionDone ) -{ - struct /* Temporary partition table */ - { - BYTE peBootable; - BYTE peBeginHead; - BYTE peBeginSector; - UWORD peBeginCylinder; - BYTE peFileSystem; - BYTE peEndHead; - BYTE peEndSector; - UWORD peEndCylinder; - LONG peStartSector; - LONG peSectors; - } - temp_part[N_PART], - *ptemp_part; /*TE*/ - - int retry; - UBYTE packed_byte, - pb1; - BYTE *p; - int partition_chain = 0; - int ret; -/* ULONG newStartPos;*/ - UWORD partMask; - int loop; - -restart: /* yes, it's a GOTO >:-) */ - - /* if someone has a circular linked - extended partition list, stop it sooner or later */ - if (partition_chain > 64) - return PartitionDone; - - - PartCodePrintf(("searching partition table at %x %x %x %x %lx\n", - ptDrive, ptCylinder, ptHead, ptSector, ptAccuOff)); - - /* Read partition table */ - for ( retry = N_RETRY; --retry >= 0; ) - { - ret = fl_read((WORD) ptDrive, (WORD) ptHead, (WORD) ptCylinder, - (WORD) ptSector, (WORD) 1, (byteptr) & DiskTransferBuffer); - if (ret == 0) - break; - } - if (ret != 0) - return PartitionDone; - - /* Read each partition into temporary array */ - - p = (BYTE *) & DiskTransferBuffer.bytes[PARTOFF]; - - for (ptemp_part = &temp_part[0]; - ptemp_part < &temp_part[N_PART]; ptemp_part++) - { - - getbyte((VOID *) (p+0), &ptemp_part->peBootable); - getbyte((VOID *) (p+1), &ptemp_part->peBeginHead); - getbyte((VOID *) (p+2), &packed_byte); - ptemp_part->peBeginSector = packed_byte & 0x3f; - getbyte((VOID *) (p+3), &pb1); - ptemp_part->peBeginCylinder = pb1 + ((UWORD) (0xc0 & packed_byte) << 2); - getbyte((VOID *) (p+4), &ptemp_part->peFileSystem); - getbyte((VOID *) (p+5), &ptemp_part->peEndHead); - getbyte((VOID *) (p+6), &packed_byte); - ptemp_part->peEndSector = packed_byte & 0x3f; - getbyte((VOID *) (p+7), &pb1); - ptemp_part->peEndCylinder = pb1 + ((UWORD) (0xc0 & packed_byte) << 2); - getlong((VOID *) (p+8), &ptemp_part->peStartSector); - getlong((VOID *) (p+12), &ptemp_part->peSectors); - - p += SIZEOF_PARTENT; /* == 16 */ - } - - /* Walk through the table, add DOS partitions to global - array and process extended partitions */ - - /* when searching the EXT chain, - must skip primary partitions */ - if ( table_type==PRIMARY || - table_type==PRIMARY2 || - partition_chain!=0 ) - { - /* do this for - 0) all active partitions - 1) the first primary partition - */ - for (loop = 0; loop < 2; loop++) - { - for (ptemp_part = &temp_part[0], partMask = 1; - ptemp_part < &temp_part[N_PART] && nUnits < NDEV; - partMask <<= 1,ptemp_part++) - { - - - if (loop == 0 && /* scan for only for active */ - !ptemp_part->peBootable) - { - continue; - } - - if (PartitionDone & partMask) /* don't reassign partitions */ - { - continue; - } - - if ( ptemp_part->peFileSystem == FAT12 || - ptemp_part->peFileSystem == FAT16SMALL || - ptemp_part->peFileSystem == FAT16LARGE ) - { - - struct media_info *pmiarray = getPMiarray(nUnits); - - pmiarray->mi_drive = ptDrive; - - pmiarray->mi_offset = StartSector(ptDrive, - ptemp_part->peBeginCylinder, - ptemp_part->peBeginHead, - ptemp_part->peBeginSector, - ptemp_part->peStartSector, - ptAccuOff); - - pmiarray->mi_BeginCylinder = ptemp_part->peBeginCylinder; - pmiarray->mi_BeginHead = ptemp_part->peBeginHead; - pmiarray->mi_BeginSector = ptemp_part->peBeginSector; - - - nUnits++; - - - PartitionDone |= partMask; - - if ( table_type==PRIMARY ) - { - return PartitionDone; /* we are done */ - } - - } /* end FAT16 detected */ - } /* end PArtitionentry 0..3 */ - } /* end of loop 0..1 for active, nonactive */ - } /* if ( table_type==PRIMARY ) */ - - /* search for EXT partitions only on 2. run */ - if (table_type==EXTENDED) - { - for (ptemp_part = &temp_part[0]; - ptemp_part < &temp_part[N_PART] && nUnits < NDEV; ptemp_part++) - { - if ( (ptemp_part->peFileSystem == EXTENDED || - ptemp_part->peFileSystem == EXTENDED_INT32 ) ) - { - /* restart with new extended part table, don't recurs */ - partition_chain++; - - ptHead = ptemp_part->peBeginHead; - ptCylinder = ptemp_part->peBeginCylinder; - ptSector = ptemp_part->peBeginSector; - ptAccuOff = ptemp_part->peStartSector + ptAccuOff; - - PartitionDone = 0; /* not important for EXTENDED */ - - goto restart; - } - } - } - - return PartitionDone; -} COUNT FAR blk_driver(rqptr rp) { @@ -642,103 +319,21 @@ COUNT FAR blk_driver(rqptr rp) return failure(E_FAILURE); /* general failure */ } else - return ((*dispatch[rp->r_command]) (rp)); + return ((*dispatch[rp->r_command]) (rp, getPMiarray(rp->r_unit))); } -WORD _dsk_init(rqptr rp) +/* disk init is done in diskinit.c, so this should never be called */ +WORD _dsk_init(rqptr rp, struct media_info *pmiarray) { - extern COUNT fl_nrdrives(VOID); - COUNT HardDrive, - nHardDisk, - Unit; - struct media_info *pmiarray; - bpb *pbpbarray; - UBYTE foundPartitions[16]; - - - /* Reset the drives */ - fl_reset(0x80); - - /* Initial number of disk units */ - nUnits = 2; - - /* Setup media info and BPBs arrays */ - for (Unit = 0; Unit < NDEV; Unit++) - { - pmiarray = getPMiarray(Unit); - - pmiarray->mi_size = 720l; - pmiarray->mi_heads = 2; - pmiarray->mi_cyls = 40; - pmiarray->mi_sectors = 9; - pmiarray->mi_offset = 0l; - pmiarray->mi_drive = Unit; - - pmiarray->mi_BeginCylinder = 0; /* initialize for floppies */ - pmiarray->mi_BeginHead = 0; - pmiarray->mi_BeginSector = 1; - - - pmiarray->fs.serialno = 0x12345678l; - - pbpbarray = 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; - - bpbptrs[Unit] = pbpbarray; - } - - nHardDisk = fl_nrdrives(); - - nHardDisk = min(nHardDisk,sizeof(foundPartitions)); - - /* 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 */ - - PartCodePrintf(("DSK init: found %d disk drives\n",nHardDisk)); - - - /* Process primary partition table 1 partition only */ - for (HardDrive = 0; HardDrive < nHardDisk; HardDrive++) - { - foundPartitions[HardDrive] = - processtable(PRIMARY, (HardDrive | 0x80), 0, 0l, 1, 0l,0); - } - /* Process extended partition table */ - for (HardDrive = 0; HardDrive < nHardDisk; HardDrive++) - { - processtable(EXTENDED, (HardDrive | 0x80), 0, 0l, 1, 0l,0); - } - - /* Process primary a 2nd time */ - for (HardDrive = 0; HardDrive < nHardDisk; HardDrive++) - { - processtable(PRIMARY2, (HardDrive | 0x80), 0, 0l, 1, 0l,foundPartitions[HardDrive]); - } - - rp->r_nunits = nUnits; - rp->r_bpbptr = bpbptrs; - rp->r_endaddr = device_end(); - nblk_rel = nUnits; /* make device header reflect units */ - return S_DONE; + UNREFERENCED_PARAMETER(rp); + UNREFERENCED_PARAMETER(pmiarray); + fatal("No disk init!"); + return S_DONE; /* to keep the compiler happy */ } -static WORD mediachk(rqptr rp) +WORD mediachk(rqptr rp, struct media_info *pmiarray) { - COUNT drive = miarray[rp->r_unit].mi_drive; + COUNT drive = pmiarray->drive.driveno; COUNT result; /* if it's a hard drive, media never changes */ @@ -747,7 +342,7 @@ static WORD mediachk(rqptr rp) else /* else, check floppy status */ { - if ((result = fl_readdasd(drive)) == 2) /* if we can detect a change ... */ + if ((result = fl_readdasd(drive)) == 2) /* if we can detect a change ... */ { if ((result = fl_diskchanged(drive)) == 1) /* check if it has changed... */ rp->r_mcretcode = M_CHANGED; @@ -770,75 +365,79 @@ static WORD mediachk(rqptr rp) */ STATIC WORD RWzero(rqptr rp, WORD t) { - REG retry = N_RETRY; - WORD ret; struct media_info *pmiarray = getPMiarray(rp->r_unit); + UWORD done; - do - { - ret = (t == 0 ? fl_read : fl_write)( - (WORD) pmiarray->mi_drive, - (WORD) pmiarray->mi_BeginHead, - (WORD) pmiarray->mi_BeginCylinder, - (WORD) pmiarray->mi_BeginSector, - (WORD) 1, (byteptr) & DiskTransferBuffer); - } - while (ret != 0 && --retry > 0); - return ret; + return LBA_Transfer(&pmiarray->drive, + t == 0 ? LBA_READ : LBA_WRITE, + (UBYTE FAR *)&DiskTransferBuffer, + pmiarray->mi_offset,1,&done); } /* 0 if not set, 1 = a, 2 = b, etc, assume set. page 424 MS Programmer's Ref. */ -static WORD Getlogdev(rqptr rp) +static WORD Getlogdev(rqptr rp, struct media_info *pmiarray) { BYTE x = rp->r_unit; + + UNREFERENCED_PARAMETER(pmiarray); + x++; if( x > nblk_rel ) - return failure(E_UNIT); + return failure(E_UNIT); rp->r_unit = x; return S_DONE; } -static WORD Setlogdev(rqptr rp) +static WORD Setlogdev(rqptr rp, struct media_info *pmiarray) { - UNREFERENCED_PARAMETER(rp); + UNREFERENCED_PARAMETER(rp); + UNREFERENCED_PARAMETER(pmiarray); + return S_DONE; } -static WORD blk_Open(rqptr rp) +static WORD blk_Open(rqptr rp, struct media_info *pmiarray) { - miarray[rp->r_unit].mi_FileOC++; + UNREFERENCED_PARAMETER(rp); + + pmiarray->mi_FileOC++; return S_DONE; } -static WORD blk_Close(rqptr rp) +static WORD blk_Close(rqptr rp, struct media_info *pmiarray) { - miarray[rp->r_unit].mi_FileOC--; + UNREFERENCED_PARAMETER(rp); + + pmiarray->mi_FileOC--; return S_DONE; } -static WORD blk_nondr(rqptr rp) +static WORD blk_nondr(rqptr rp, struct media_info *pmiarray) { - UNREFERENCED_PARAMETER(rp); + UNREFERENCED_PARAMETER(rp); + UNREFERENCED_PARAMETER(pmiarray); + return S_BUSY|S_DONE; } -static WORD blk_Media(rqptr rp) +static WORD blk_Media(rqptr rp, struct media_info *pmiarray) { - if (hd( miarray[rp->r_unit].mi_drive)) - return S_BUSY|S_DONE; /* Hard Drive */ + UNREFERENCED_PARAMETER(rp); + + if (hd( pmiarray->drive.driveno)) + return S_BUSY|S_DONE; /* Hard Drive */ else - return S_DONE; /* Floppy */ + return S_DONE; /* Floppy */ } -STATIC WORD bldbpb(rqptr rp) +STATIC WORD bldbpb(rqptr rp, struct media_info *pmiarray) { ULONG count; bpb *pbpbarray; - struct media_info *pmiarray; WORD head,/*track,*/sector,ret; ret = RWzero( rp, 0); @@ -849,29 +448,28 @@ STATIC WORD bldbpb(rqptr rp) /*TE ~ 200 bytes*/ pbpbarray = getPBpbarray(rp->r_unit); - getword(&((((BYTE *) & DiskTransferBuffer.bytes[BT_BPB]))[BPB_NBYTE]), &pbpbarray->bpb_nbyte); - getbyte(&((((BYTE *) & DiskTransferBuffer.bytes[BT_BPB]))[BPB_NSECTOR]), &pbpbarray->bpb_nsector); - getword(&((((BYTE *) & DiskTransferBuffer.bytes[BT_BPB]))[BPB_NRESERVED]), &pbpbarray->bpb_nreserved); - getbyte(&((((BYTE *) & DiskTransferBuffer.bytes[BT_BPB]))[BPB_NFAT]), &pbpbarray->bpb_nfat); - getword(&((((BYTE *) & DiskTransferBuffer.bytes[BT_BPB]))[BPB_NDIRENT]), &pbpbarray->bpb_ndirent); - getword(&((((BYTE *) & DiskTransferBuffer.bytes[BT_BPB]))[BPB_NSIZE]), &pbpbarray->bpb_nsize); - getword(&((((BYTE *) & DiskTransferBuffer.bytes[BT_BPB]))[BPB_NSIZE]), &pbpbarray->bpb_nsize); - getbyte(&((((BYTE *) & DiskTransferBuffer.bytes[BT_BPB]))[BPB_MDESC]), &pbpbarray->bpb_mdesc); - getword(&((((BYTE *) & DiskTransferBuffer.bytes[BT_BPB]))[BPB_NFSECT]), &pbpbarray->bpb_nfsect); - getword(&((((BYTE *) & DiskTransferBuffer.bytes[BT_BPB]))[BPB_NSECS]), &pbpbarray->bpb_nsecs); - getword(&((((BYTE *) & DiskTransferBuffer.bytes[BT_BPB]))[BPB_NHEADS]), &pbpbarray->bpb_nheads); - getlong(&((((BYTE *) & DiskTransferBuffer.bytes[BT_BPB])[BPB_HIDDEN])), &pbpbarray->bpb_hidden); - getlong(&((((BYTE *) & DiskTransferBuffer.bytes[BT_BPB])[BPB_HUGE])), &pbpbarray->bpb_huge); + getword(&((((BYTE *) & DiskTransferBuffer[BT_BPB]))[BPB_NBYTE]), &pbpbarray->bpb_nbyte); + getbyte(&((((BYTE *) & DiskTransferBuffer[BT_BPB]))[BPB_NSECTOR]), &pbpbarray->bpb_nsector); + getword(&((((BYTE *) & DiskTransferBuffer[BT_BPB]))[BPB_NRESERVED]), &pbpbarray->bpb_nreserved); + getbyte(&((((BYTE *) & DiskTransferBuffer[BT_BPB]))[BPB_NFAT]), &pbpbarray->bpb_nfat); + getword(&((((BYTE *) & DiskTransferBuffer[BT_BPB]))[BPB_NDIRENT]), &pbpbarray->bpb_ndirent); + getword(&((((BYTE *) & DiskTransferBuffer[BT_BPB]))[BPB_NSIZE]), &pbpbarray->bpb_nsize); + getword(&((((BYTE *) & DiskTransferBuffer[BT_BPB]))[BPB_NSIZE]), &pbpbarray->bpb_nsize); + getbyte(&((((BYTE *) & DiskTransferBuffer[BT_BPB]))[BPB_MDESC]), &pbpbarray->bpb_mdesc); + getword(&((((BYTE *) & DiskTransferBuffer[BT_BPB]))[BPB_NFSECT]), &pbpbarray->bpb_nfsect); + getword(&((((BYTE *) & DiskTransferBuffer[BT_BPB]))[BPB_NSECS]), &pbpbarray->bpb_nsecs); + getword(&((((BYTE *) & DiskTransferBuffer[BT_BPB]))[BPB_NHEADS]), &pbpbarray->bpb_nheads); + getlong(&((((BYTE *) & DiskTransferBuffer[BT_BPB])[BPB_HIDDEN])), &pbpbarray->bpb_hidden); + getlong(&((((BYTE *) & DiskTransferBuffer[BT_BPB])[BPB_HUGE])), &pbpbarray->bpb_huge); - pmiarray = getPMiarray(rp->r_unit); /* Needs fat32 offset code */ - getlong(&((((BYTE *) & DiskTransferBuffer.bytes[0x27])[0])), &pmiarray->fs.serialno); + getlong(&((((BYTE *) & DiskTransferBuffer[0x27])[0])), &pmiarray->fs.serialno); - memcpy(pmiarray->fs.volume,&DiskTransferBuffer.bytes[0x2B], 11); - memcpy(pmiarray->fs.fstype,&DiskTransferBuffer.bytes[0x36], 8); + memcpy(pmiarray->fs.volume,&DiskTransferBuffer[0x2B], 11); + memcpy(pmiarray->fs.fstype,&DiskTransferBuffer[0x36], 8); @@ -892,19 +490,19 @@ STATIC WORD bldbpb(rqptr rp) pbpbarray->bpb_nsize == 0 ? pbpbarray->bpb_huge : pbpbarray->bpb_nsize; - getword((&(((BYTE *) & DiskTransferBuffer.bytes[BT_BPB])[BPB_NHEADS])), &pmiarray->mi_heads); - head = pmiarray->mi_heads; - getword((&(((BYTE *) & DiskTransferBuffer.bytes[BT_BPB])[BPB_NSECS])), &pmiarray->mi_sectors); + getword((&(((BYTE *) & DiskTransferBuffer[BT_BPB])[BPB_NHEADS])), &pmiarray->drive.chs.Head); + head = pmiarray->drive.chs.Head; + getword((&(((BYTE *) & DiskTransferBuffer[BT_BPB])[BPB_NSECS])), &pmiarray->drive.chs.Sector); if (pmiarray->mi_size == 0) - getlong(&((((BYTE *) & DiskTransferBuffer.bytes[BT_BPB])[BPB_HUGE])), &pmiarray->mi_size); - sector = pmiarray->mi_sectors; + getlong(&((((BYTE *) & DiskTransferBuffer[BT_BPB])[BPB_HUGE])), &pmiarray->mi_size); + sector = pmiarray->drive.chs.Sector; if (head == 0 || sector == 0) { tmark(); return failure(E_FAILURE); } - pmiarray->mi_cyls = count / (head * sector); + pmiarray->drive.chs.Cylinder = count / (head * sector); tmark(); #ifdef DSK_DEBUG @@ -916,215 +514,165 @@ STATIC WORD bldbpb(rqptr rp) return S_DONE; } -STATIC COUNT write_and_verify(WORD drive, WORD head, WORD track, WORD sector, - WORD count, BYTE FAR * buffer) -{ - REG COUNT ret; - ret = fl_write(drive, head, track, sector, count, buffer); - if (ret != 0) - return ret; - return fl_verify(drive, head, track, sector, count, buffer); -} - -static WORD IoctlQueblk(rqptr rp) +static WORD IoctlQueblk(rqptr rp, struct media_info *pmiarray) { + UNREFERENCED_PARAMETER(pmiarray); + switch(rp->r_count){ - case 0x0846: - case 0x0847: - case 0x0860: - case 0x0866: - case 0x0867: - break; - default: - return failure(E_CMD); + case 0x0846: + case 0x0847: + case 0x0860: + case 0x0866: + case 0x0867: + break; + default: + return failure(E_CMD); } return S_DONE; } -static WORD Genblkdev(rqptr rp) +STATIC WORD Genblkdev(rqptr rp,struct media_info *pmiarray) { int ret; - struct media_info *pmiarray = getPMiarray(rp->r_unit); switch(rp->r_count){ - case 0x0860: /* get device parameters */ - { - struct gblkio FAR * gblp = (struct gblkio FAR *) rp->r_trans; - REG COUNT x = 5,y = 1,z = 0; + case 0x0860: /* get device parameters */ + { + struct gblkio FAR * gblp = (struct gblkio FAR *) rp->r_trans; + REG COUNT x = 5,y = 1,z = 0; - if (!hd(pmiarray->mi_drive)){ - y = 2; - x = 8; /* any odd ball drives return this */ - if (pmiarray->mi_size <= 0xffff) - switch((UWORD)pmiarray->mi_size) - { - case 640: - case 720: /* 320-360 */ - x = 0; - z = 1; - break; - case 1440: /* 720 */ - x = 2; - break; - case 2400: /* 1.2 */ - x = 1; - break; - case 2880: /* 1.44 */ - x = 7; - break; - case 5760: /* 2.88 almost forgot this one*/ - x = 9; - break; - } - } - gblp->gbio_devtype = (UBYTE) x; - gblp->gbio_devattrib = (UWORD) y; - gblp->gbio_media = (UBYTE) z; - gblp->gbio_ncyl = pmiarray->mi_cyls; - fmemcpy(&gblp->gbio_bpb, &bpbarray[rp->r_unit], sizeof(gblp->gbio_bpb)); - gblp->gbio_nsecs = bpbarray[rp->r_unit].bpb_nsector; + if (!hd(pmiarray->drive.driveno)){ + y = 2; + x = 8; /* any odd ball drives return this */ + if (pmiarray->mi_size <= 0xffff) + switch((UWORD)pmiarray->mi_size) + { + case 640: + case 720: /* 320-360 */ + x = 0; + z = 1; break; - } - case 0x0866: /* get volume serial number */ - { - struct Gioc_media FAR * gioc = (struct Gioc_media FAR *) rp->r_trans; - struct FS_info FAR * fs = &pmiarray->fs; + case 1440: /* 720 */ + x = 2; + break; + case 2400: /* 1.2 */ + x = 1; + break; + case 2880: /* 1.44 */ + x = 7; + break; + case 5760: /* 2.88 almost forgot this one*/ + x = 9; + break; + } + } + gblp->gbio_devtype = (UBYTE) x; + gblp->gbio_devattrib = (UWORD) y; + gblp->gbio_media = (UBYTE) z; + gblp->gbio_ncyl = pmiarray->drive.chs.Cylinder; + fmemcpy(&gblp->gbio_bpb, &bpbarray[rp->r_unit], sizeof(gblp->gbio_bpb)); + gblp->gbio_nsecs = bpbarray[rp->r_unit].bpb_nsector; + break; + } + case 0x0866: /* get volume serial number */ + { + struct Gioc_media FAR * gioc = (struct Gioc_media FAR *) rp->r_trans; + struct FS_info FAR * fs = &pmiarray->fs; - gioc->ioc_serialno = fs->serialno; - fmemcpy(gioc->ioc_volume,fs->volume,11); - fmemcpy(gioc->ioc_fstype, fs->fstype,8); - } - break; - case 0x0846: /* set volume serial number */ - { - struct Gioc_media FAR * gioc = (struct Gioc_media FAR *) rp->r_trans; - struct FS_info FAR * fs = (struct FS_info FAR *) &DiskTransferBuffer.bytes[0x27]; + gioc->ioc_serialno = fs->serialno; + fmemcpy(gioc->ioc_volume,fs->volume,11); + fmemcpy(gioc->ioc_fstype, fs->fstype,8); + } + break; + case 0x0846: /* set volume serial number */ + { + struct Gioc_media FAR * gioc = (struct Gioc_media FAR *) rp->r_trans; + struct FS_info FAR * fs = (struct FS_info FAR *) &DiskTransferBuffer[0x27]; - ret = RWzero( rp, 0); - if (ret != 0) - return (dskerr(ret)); + ret = RWzero( rp, 0); + if (ret != 0) + return (dskerr(ret)); - fs->serialno = gioc->ioc_serialno; - pmiarray->fs.serialno = fs->serialno; + fs->serialno = gioc->ioc_serialno; + pmiarray->fs.serialno = fs->serialno; - ret = RWzero( rp, 1); - if (ret != 0) - return (dskerr(ret)); - } - break; - case 0x0867: /* get access flag, always on*/ - { - struct Access_info FAR * ai = (struct Access_info FAR *) rp->r_trans; - ai->AI_Flag = 1; - } - break; - case 0x0847: /* set access flag, no real use*/ - break; - default: - return failure(E_CMD); + ret = RWzero( rp, 1); + if (ret != 0) + return (dskerr(ret)); + } + break; + case 0x0867: /* get access flag, always on*/ + { + struct Access_info FAR * ai = (struct Access_info FAR *) rp->r_trans; + ai->AI_Flag = 1; + } + break; + case 0x0847: /* set access flag, no real use*/ + break; + default: + return failure(E_CMD); } return S_DONE; } -WORD blockio(rqptr rp) +WORD blockio(rqptr rp, struct media_info *pmiarray) { - REG retry = N_RETRY, - remaining; - UWORD cmd, - total; - ULONG start; - byteptr trans; - WORD head,track,sector,ret,count; - - COUNT(*action) (WORD, WORD, WORD, WORD, WORD, BYTE FAR *); - - struct media_info *pmiarray = getPMiarray(rp->r_unit); + ULONG start; + WORD ret; + int action; - cmd = rp->r_command; - total = 0; - trans = rp->r_trans; - tmark(); - remaining = rp->r_count; - start = (rp->r_start != HUGECOUNT ? rp->r_start : rp->r_huge) - + pmiarray->mi_offset; - while(remaining > 0) - { - count = ltop(&track, §or, &head, rp->r_unit, remaining, start, trans); - - /*printf("dskAction %02x THS=%x-%x-%x block=%lx\n", rp->r_unit,track, head, sector, start);*/ - - do - { - switch (cmd) - { - case C_INPUT: - action = fl_read; - break; - case C_OUTPUT: - action = fl_write; - break; - case C_OUTVFY: - action = write_and_verify; - break; + switch (rp->r_command){ + case C_INPUT: action = LBA_READ; break; + case C_OUTPUT:action = LBA_WRITE; break; + case C_OUTVFY:action = LBA_WRITE_VERIFY; break; default: - return failure(E_FAILURE); - } - - - if (count && FP_SEG(trans) != 0xffff) - { - ret = action((WORD) pmiarray->mi_drive, head, track, sector, - count, trans); - } - else - { - count = 1; - /* buffer crosses DMA boundary, use scratchpad */ - /* use scratchpad also, if going to HIGH memory */ + return failure(E_FAILURE); + } + - if (cmd != C_INPUT) - fbcopy(trans, &DiskTransferBuffer, SEC_SIZE); - ret = action((WORD) pmiarray->mi_drive, head, track, sector, - 1, (byteptr)&DiskTransferBuffer); - if (cmd == C_INPUT) - fbcopy(&DiskTransferBuffer, trans, SEC_SIZE); - } - if (ret != 0) - fl_reset((WORD) pmiarray->mi_drive); - } - while (ret != 0 && --retry > 0); + tmark(); + start = (rp->r_start != HUGECOUNT ? rp->r_start : rp->r_huge); + + if (start >= pmiarray->mi_size || + start + rp->r_count > pmiarray->mi_size) + { + return 0x0408; + } + start += pmiarray->mi_offset; + + ret = LBA_Transfer(&pmiarray->drive ,action, + rp->r_trans, + start, rp->r_count,(UWORD*)&rp->r_count); + if (ret != 0) { - rp->r_count = total; return dskerr(ret); } - total += count; - remaining -= count; - trans += count * SEC_SIZE; - start += count; - } - rp->r_count = total; - return S_DONE; + return S_DONE; } -static WORD blk_error(rqptr rp) +STATIC WORD blk_error(rqptr rp, struct media_info *pmiarray) { + UNREFERENCED_PARAMETER(pmiarray); + rp->r_count = 0; return failure(E_FAILURE); /* general failure */ } -static WORD blk_noerr(rqptr rp) +STATIC WORD blk_noerr(rqptr rp, struct media_info *pmiarray) { - UNREFERENCED_PARAMETER(rp); + UNREFERENCED_PARAMETER(rp); + UNREFERENCED_PARAMETER(pmiarray); + return S_DONE; } -static WORD dskerr(COUNT code) +STATIC WORD dskerr(COUNT code) { /* printf("diskette error:\nhead = %d\ntrack = %d\nsector = %d\ncount = %d\n", head, track, sector, count); */ @@ -1132,9 +680,10 @@ static WORD dskerr(COUNT code) { case 1: /* invalid command - general failure */ if (code & 0x08) - return (E_FAILURE); + return S_ERROR | E_NOTRDY; /* failure(E_NOTRDY); at least on yhe INT25 route, + 0x8002 is returned */ else - return failure(E_CMD); + return failure(E_CMD); case 2: /* address mark not found - general failure */ return failure(E_FAILURE); @@ -1144,56 +693,221 @@ static WORD dskerr(COUNT code) default: if (code & 0x80) /* time-out */ - return failure(E_NOTRDY); + return failure(E_NOTRDY); else if (code & 0x40) /* seek error */ - return failure(E_SEEK); + return failure(E_SEEK); else if (code & 0x10) /* CRC error */ - return failure(E_CRC); + return failure(E_CRC); else if (code & 0x04) - return failure(E_NOTFND); + return failure(E_NOTFND); else - return failure(E_FAILURE); + return failure(E_FAILURE); } } -/* */ -/* Do logical block number to physical head/track/sector mapping */ -/* */ -COUNT ltop(WORD * trackp, WORD * sectorp, WORD * headp, COUNT unit, COUNT count, ULONG strt_sect, byteptr strt_addr) + +/* + translate LBA sectors into CHS addressing +*/ + +void LBA_to_CHS(struct CHS *chs, ULONG LBA_address, struct DriveParamS *driveparam) { -#ifdef I86 - UWORD utemp; -#endif - struct media_info *pmiarray; - + chs->Sector = LBA_address% driveparam->chs.Sector + 1; -#ifdef I86 -/*TE*/ - /* Adjust for segmented architecture */ - utemp = (((UWORD) mk_segment(strt_addr) << 4) + mk_offset(strt_addr)); - /* Test for 64K boundary crossing and return count large */ - /* enough not to exceed the threshold. */ - -#define SEC_SHIFT 9 /* = 0x200 = 512 */ - - utemp >>= SEC_SHIFT; - - if (count > (0xffff >> SEC_SHIFT) - utemp) - { - count = (0xffff >> SEC_SHIFT) - utemp; - } + LBA_address /= driveparam->chs.Sector; -#endif - -/*TE*/ - pmiarray = getPMiarray(unit); - - *trackp = strt_sect / (pmiarray->mi_heads * pmiarray->mi_sectors); - *sectorp = strt_sect % pmiarray->mi_sectors + 1; - *headp = (strt_sect % (pmiarray->mi_heads * pmiarray->mi_sectors)) - / pmiarray->mi_sectors; - if (*sectorp + count > pmiarray->mi_sectors + 1) - count = pmiarray->mi_sectors + 1 - *sectorp; - return count; + chs->Head = LBA_address % driveparam->chs.Head; + chs->Cylinder = LBA_address / driveparam->chs.Head; } + + + /* Test for 64K boundary crossing and return count small */ + /* enough not to exceed the threshold. */ + +STATIC unsigned DMA_max_transfer(void FAR *buffer, unsigned count) +{ + UWORD utemp = (((UWORD) FP_SEG(buffer) << 4) + FP_OFF(buffer)); + +#define SEC_SHIFT 9 /* = 0x200 = 512 */ + + utemp >>= SEC_SHIFT; + + if (count > (0xffff >> SEC_SHIFT) - utemp) + { + count = (0xffff >> SEC_SHIFT) - utemp; + } + + return count; +} + + + +/* + int LBA_Transfer( + struct DriveParamS *driveParam, physical characteristics of drive + UWORD mode, LBA_READ/WRITE/WRITE_VERIFY + VOID FAR *buffer, user buffer + ULONG LBA_address, absolute sector address + unsigned totaltodo, number of sectors to transfer + UWORD *transferred sectors actually transferred + + Read/Write/Write+verify some sectors, using LBA addressing. + + + This function handles all the minor details, including: + + retry in case of errors + + crossing the 64K DMA boundary + + translation to CHS addressing if necessary + + crossing track boundaries (necessary for some BIOS's + + High memory doesn't work very well, use internal buffer + + write with verify details for LBA + +*/ + +int LBA_Transfer(struct DriveParamS *driveParam ,UWORD mode, VOID FAR *buffer, + ULONG LBA_address,unsigned totaltodo, UWORD *transferred) +{ + static struct _bios_LBA_address_packet dap = { + 16,0,0,0,0,0,0 + }; + + unsigned count; + unsigned error_code; + struct CHS chs; + void FAR *transfer_address; + + int num_retries; + + *transferred = 0; + + + if (LBA_address+totaltodo > driveParam->total_sectors) + { + printf("LBA-Transfer error : address overflow = %lu > %lu max\n",LBA_address+totaltodo,driveParam->total_sectors); + return 1; + } + + + for ( ;totaltodo != 0; ) + { + count = totaltodo; + + count = min(count, 0x7f); + + + /* avoid overflowing 64K DMA boundary */ + count = DMA_max_transfer(buffer,count); + + + if (FP_SEG(buffer) == 0xffff || count == 0) + { + transfer_address = DiskTransferBuffer; + count = 1; + + if ((mode & 0xff00) == (LBA_WRITE & 0xff00)) + { + fmemcpy(DiskTransferBuffer,buffer,512); + } + } + else { + transfer_address = buffer; + } + + + + for ( num_retries = 0; num_retries < N_RETRY; num_retries++) + { + if (driveParam->LBA_supported) + { + dap.number_of_blocks = count; + + dap.buffer_address = transfer_address; + + dap.block_address_high = 0; /* clear high part */ + dap.block_address = LBA_address; /* clear high part */ + + + /* Load the registers and call the interrupt. */ + + if (driveParam->WriteVerifySupported || mode != LBA_WRITE_VERIFY) + { + + error_code = fl_lba_ReadWrite(driveParam->driveno,mode, &dap); + } + else { + /* verify requested, but not supported */ + error_code = fl_lba_ReadWrite(driveParam->driveno,LBA_WRITE, &dap); + + if (error_code == 0) + { + error_code = fl_lba_ReadWrite(driveParam->driveno,LBA_VERIFY, &dap); + } + } + } + else + { /* transfer data, using old bios functions */ + + LBA_to_CHS(&chs, LBA_address, driveParam); + + /* avoid overflow at end of track */ + + if (chs.Sector + count > driveParam->chs.Sector + 1) + { + count = driveParam->chs.Sector + 1 - chs.Sector; + } + + if (chs.Cylinder > 1023) + { + printf("LBA-Transfer error : cylinder %u > 1023\n", chs.Cylinder); + return 1; + } + + error_code = (mode == LBA_READ ? fl_read : fl_write)( + driveParam->driveno, + chs.Head, chs.Cylinder, chs.Sector, + count, transfer_address); + + if (error_code == 0 && + mode == LBA_WRITE_VERIFY) + { + error_code = fl_verify( + driveParam->driveno, + chs.Head, chs.Cylinder, chs.Sector, + count, transfer_address); + } + } + if (error_code == 0) + break; + + fl_reset(driveParam->driveno); + + } /* end of retries */ + + if (error_code) + { + return error_code; + } + + /* copy to user buffer if nesessary */ + if (transfer_address == DiskTransferBuffer && + (mode & 0xff00) == (LBA_READ & 0xff00)) + { + fmemcpy(buffer,DiskTransferBuffer,512); + } + + *transferred += count; + LBA_address += count; + totaltodo -= count; + + buffer = add_far(buffer,count*512); + } + + return(error_code); +} diff --git a/kernel/dyndata.c b/kernel/dyndata.c new file mode 100644 index 0000000..0b376f8 --- /dev/null +++ b/kernel/dyndata.c @@ -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; diff --git a/kernel/dyndata.h b/kernel/dyndata.h new file mode 100644 index 0000000..ddec7ae --- /dev/null +++ b/kernel/dyndata.h @@ -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 */ + ]; + }; diff --git a/kernel/dyninit.c b/kernel/dyninit.c new file mode 100644 index 0000000..fd2c127 --- /dev/null +++ b/kernel/dyninit.c @@ -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; +} diff --git a/kernel/fatdir.c b/kernel/fatdir.c index 5103e4d..3fa66b4 100644 --- a/kernel/fatdir.c +++ b/kernel/fatdir.c @@ -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); } diff --git a/kernel/fatfs.c b/kernel/fatfs.c index 466e07e..f238346 100644 --- a/kernel/fatfs.c +++ b/kernel/fatfs.c @@ -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 +} diff --git a/kernel/fattab.c b/kernel/fattab.c index 3e7d0cc..095fc20 100644 --- a/kernel/fattab.c +++ b/kernel/fattab.c @@ -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 diff --git a/kernel/fcbfns.c b/kernel/fcbfns.c index 6cd08c3..be825e1 100644 --- a/kernel/fcbfns.c +++ b/kernel/fcbfns.c @@ -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 diff --git a/kernel/globals.h b/kernel/globals.h index 856dc11..0f18cb7 100644 --- a/kernel/globals.h +++ b/kernel/globals.h @@ -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 diff --git a/kernel/init-mod.h b/kernel/init-mod.h index 67a48e3..c28bba9 100644 --- a/kernel/init-mod.h +++ b/kernel/init-mod.h @@ -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; diff --git a/kernel/initdisk.c b/kernel/initdisk.c new file mode 100644 index 0000000..360e1fb --- /dev/null +++ b/kernel/initdisk.c @@ -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, ®s) 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,®s); + + + 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,®s); + + + 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,®s); + + + 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, ®s); + 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,®s); + + 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,®s); +} + +/* + 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, ®s); + } +#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; +} diff --git a/kernel/inithma.c b/kernel/inithma.c index 30fd242..71be97e 100644 --- a/kernel/inithma.c +++ b/kernel/inithma.c @@ -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 (;;); +} diff --git a/kernel/int2f.asm b/kernel/int2f.asm index 9da2917..1b6a4f8 100644 --- a/kernel/int2f.asm +++ b/kernel/int2f.asm @@ -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 diff --git a/kernel/inthndlr.c b/kernel/inthndlr.c index cc74fab..41ef73a 100644 --- a/kernel/inthndlr.c +++ b/kernel/inthndlr.c @@ -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; } diff --git a/kernel/ioctl.c b/kernel/ioctl.c index bb10cb1..9c77aaa 100644 --- a/kernel/ioctl.c +++ b/kernel/ioctl.c @@ -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; diff --git a/kernel/kernel.asm b/kernel/kernel.asm index 24bfb71..96ad29e 100644 --- a/kernel/kernel.asm +++ b/kernel/kernel.asm @@ -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 diff --git a/kernel/kernel.cfg b/kernel/kernel.cfg index c92038f..38d5ef5 100644 --- a/kernel/kernel.cfg +++ b/kernel/kernel.cfg @@ -6,6 +6,7 @@ -d -k- -vi- +-w -wpro -weas -wpre diff --git a/kernel/kernel.mak b/kernel/kernel.mak index 32a3a5c..4169455 100644 --- a/kernel/kernel.mak +++ b/kernel/kernel.mak @@ -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 \ diff --git a/kernel/main.c b/kernel/main.c index 44bafe2..f34ef75 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -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(); diff --git a/kernel/nls.c b/kernel/nls.c index df08f3e..1dfe9d5 100644 --- a/kernel/nls.c +++ b/kernel/nls.c @@ -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" */ diff --git a/kernel/segs.inc b/kernel/segs.inc index 9aea54c..c550eeb 100644 --- a/kernel/segs.inc +++ b/kernel/segs.inc @@ -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 diff --git a/sys/sys.c b/sys/sys.c index 4cd08d0..dd3e533 100644 --- a/sys/sys.c +++ b/sys/sys.c @@ -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,®s,®s); + + 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,®s,®s); + + 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,®s,®s,&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);