kernel 2026b changes

git-svn-id: https://svn.code.sf.net/p/freedos/svn/kernel/trunk@382 6ac86273-5f31-0410-b378-82cca8765d1b
This commit is contained in:
Bart Oldeman 2002-05-08 22:49:35 +00:00
parent bbbd0ce42f
commit 2098578b1b
33 changed files with 636 additions and 954 deletions

View File

@ -206,7 +206,7 @@ cont: mov ds, ax
mov [drive], dl ; BIOS passes drive number in DL
call print
db "Loading FreeDOS...",13,10,"ROOT",0
db "Loading FreeDOS ",0
%ifdef CALCPARAMS
GETDRIVEPARMS
@ -370,7 +370,7 @@ boot_error: call print
int 0x19 ; reboot the machine
boot_success: call print
db " GO!",13,10,0
db " GO! ",0
mov bl, [drive]
jmp word LOADSEG:0

View File

@ -99,7 +99,7 @@ cont: mov ds, ax
mov [drive], dl ; BIOS passes drive number in DL
call print
db "Loading FreeDOS...",13,10,0
db "Loading FreeDOS ",0
; FINDFILE: Searches for the file in the root directory.
;

View File

@ -40,10 +40,6 @@ segment HMA_TEXT
_ReadPCClock:
xor ah,ah
int 1ah
mov bx,sp
mov bx,[bx+2]
mov [bx],dx
mov [bx+2],cx
extern _DaysSinceEpoch ; ; update days if necessary
mov ah,0
@ -51,6 +47,9 @@ _ReadPCClock:
add word [_DaysSinceEpoch ],ax ; *some* BIOS's accumulate several days
adc word [_DaysSinceEpoch+2],0 ;
mov ax,dx ; set return value
mov dx,cx
ret
; Log: rdpcclk.asm,v

View File

@ -4,7 +4,7 @@
@if \%COMPILER% == \TURBOCPP set MAKE=%TP1_BASE%\bin\make
@if \%COMPILER% == \TC3 set MAKE=%TC3_BASE%\bin\make
@if \%COMPILER% == \BC5 set MAKE=%BC5_BASE%\bin\make
@if \%COMPILER% == \WATCOM set MAKE=%WATCOM%\binw\wmake /ms
@if \%COMPILER% == \MSCL8 set MAKE=%MS_BASE%\nmake /nologo
@if \%COMPILER% == \WATCOM set MAKE=wmake /ms
@if \%COMPILER% == \MSCL8 set MAKE=%MS_BASE%\bin\nmake /nologo
:make_set

View File

@ -58,7 +58,7 @@ struct buffer {
LONG _b_huge_blkno; /* DOS-C: actual block number if >= 0xffff */
} _b;
#endif
BYTE b_buffer[BUFFERSIZE]; /* 512 byte sectors for now */
UBYTE b_buffer[BUFFERSIZE]; /* 512 byte sectors for now */
};
#define b_dpbp _b._b_dpbp

View File

@ -80,12 +80,12 @@ typedef struct {
UBYTE FAR *ps_filetab; /* 34 open file table pointer */
VOID FAR *ps_prevpsp; /* 38 previous psp pointer */
BYTE FAR *ps_dta; /* 3c process dta address */
BYTE ps_fill2[16];
UBYTE ps_unix[3]; /* unix style call - 0xcd 0x21 0xcb */
BYTE ps_fill3[9];
BYTE ps_fill2[16]; /* 40 */
UBYTE ps_unix[3]; /* 50 unix style call - 0xcd 0x21 0xcb */
BYTE ps_fill3[9]; /* 53 */
union {
struct {
fcb _ps_fcb1; /* first command line argument */
fcb _ps_fcb1; /* 5c first command line argument */
} _u1;
struct {
BYTE fill4[16];

View File

@ -49,6 +49,6 @@ static BYTE *date_hRcsId =
#define REVISION_MINOR 1
#define REVISION_SEQ 26
#define BUILD "2026"
#define SUB_BUILD "a"
#define KERNEL_VERSION_STRING "1.1.26a" /*#REVISION_MAJOR "." #REVISION_MINOR "." #REVISION_SEQ */
#define KERNEL_BUILD_STRING "2026a" /*#BUILD SUB_BUILD */
#define SUB_BUILD "b"
#define KERNEL_VERSION_STRING "1.1.26b" /*#REVISION_MAJOR "." #REVISION_MINOR "." #REVISION_SEQ */
#define KERNEL_BUILD_STRING "2026b" /*#BUILD SUB_BUILD */

View File

@ -128,8 +128,8 @@ BYTE askThisSingleCommand = FALSE; /* ?device= device?= */
BYTE DontAskThisSingleCommand = FALSE; /* !files= */
COUNT MenuTimeout = -1;
BYTE MenuSelected = 0;
BYTE MenuLine = 0;
BYTE MenuSelected = 0;
UCOUNT MenuLine = 0;
UCOUNT Menus = 0;
STATIC VOID zumcb_init(UCOUNT seg, UWORD size);
@ -633,7 +633,7 @@ VOID DoConfig(int pass)
}
close(nFileDesc);
if (nPass == 0)
{
DoMenu();
@ -703,20 +703,15 @@ STATIC BOOL SkipLine(char *pLine)
{
short key;
static char initialized = FALSE;
if (!initialized)
if (InitKernelConfig.SkipConfigSeconds >= 0)
{
initialized = TRUE;
if (InitKernelConfig.SkipConfigSeconds < 0)
return FALSE;
if (InitKernelConfig.SkipConfigSeconds > 0)
printf("Press F8 to trace or F5 to skip CONFIG.SYS/AUTOEXEC.BAT");
key = GetBiosKey(InitKernelConfig.SkipConfigSeconds); /* wait 2 seconds */
InitKernelConfig.SkipConfigSeconds = -1;
if (key == 0x3f00) /* F5 */
{
@ -737,10 +732,10 @@ STATIC BOOL SkipLine(char *pLine)
return TRUE;
/* 1?device=CDROM.SYS */
/* 2?device=OAKROM.SYS */
/* 3?device=EMM386.EXE NOEMS */
if (MenuLine != 0 &&
MenuSelected != MenuLine)
/* 12?device=OAKROM.SYS */
/* 123?device=EMM386.EXE NOEMS */
if ( MenuLine != 0 &&
(MenuLine & (1 << MenuSelected)) == 0)
return TRUE;
if (DontAskThisSingleCommand) /* !files=30 */
@ -924,7 +919,7 @@ STATIC VOID Dosmem(BYTE * pLine)
for (pTmp = szBuf; *pTmp != '\0'; pTmp++)
*pTmp = toupper(*pTmp);
printf("DOS called with %s\n", szBuf);
/* printf("DOS called with %s\n", szBuf); */
for (pTmp = szBuf;;)
{
@ -1295,14 +1290,22 @@ STATIC BYTE * scan(BYTE * s, BYTE * d)
MenuLine = 0;
/* does the line start with "1?" */
/* does the line start with "123?" */
if (s[1] == '?' && s[0] >= '0' && s[0] <= '9')
if (isnum(s))
{
MenuLine = s[0];
Menus |= 1 << (MenuLine - '0');
s = skipwh(s+2);
unsigned numbers = 0;
for ( ; isnum(s); s++)
numbers |= 1 << (*s -'0');
if (*s == '?')
{
MenuLine = numbers;
Menus |= numbers;
s = skipwh(s+1);
}
}
/* !dos=high,umb ?? */
if (*s == '!')
@ -1613,7 +1616,9 @@ STATIC VOID CfgMenu(BYTE * pLine)
STATIC VOID DoMenu(void)
{
if (Menus == 0)
return;
return;
InitKernelConfig.SkipConfigSeconds = -1;
Menus |= 1 << 0; /* '0' Menu always allowed */
@ -1667,7 +1672,7 @@ STATIC VOID DoMenu(void)
if (key >= '0' && key <= '9')
if (Menus & (1 << (key - '0')))
{
MenuSelected = key; break;
MenuSelected = key - '0'; break;
}
}
printf("\n");
@ -1688,7 +1693,7 @@ STATIC VOID CfgMenuDefault(BYTE * pLine)
/* Format: STACKS = stacks [, stackSize] */
pLine = GetNumArg(pLine, &num);
MenuSelected = '0' + num;
MenuSelected = num;
pLine = skipwh(pLine);
if (*pLine == ',')

View File

@ -269,8 +269,6 @@ UCOUNT GenericReadSft(sft FAR * s, UCOUNT n, BYTE FAR * bp,
else
/* a block read */
{
COUNT rc;
/* /// Added for SHARE - Ron Cemer */
if (IsShareInstalled())
{
@ -290,9 +288,9 @@ UCOUNT GenericReadSft(sft FAR * s, UCOUNT n, BYTE FAR * bp,
}
/* /// End of additions for SHARE - Ron Cemer */
ReadCount = readblock(s->sft_status, bp, n, &rc);
*err = rc;
return (rc == SUCCESS ? ReadCount : 0);
ReadCount = rwblock(s->sft_status, bp, n, XFR_READ);
*err = SUCCESS;
return ReadCount;
}
*err = SUCCESS;
return 0;
@ -445,8 +443,6 @@ UCOUNT DosWriteSft(sft FAR * s, UCOUNT n, const BYTE FAR * bp, COUNT FAR * err)
else
/* a block write */
{
COUNT rc;
/* /// Added for SHARE - Ron Cemer */
if (IsShareInstalled())
{
@ -466,20 +462,10 @@ UCOUNT DosWriteSft(sft FAR * s, UCOUNT n, const BYTE FAR * bp, COUNT FAR * err)
}
/* /// End of additions for SHARE - Ron Cemer */
WriteCount = writeblock(s->sft_status, bp, n, &rc);
WriteCount = rwblock(s->sft_status, (BYTE FAR *)bp, n, XFR_WRITE);
s->sft_size = dos_getcufsize(s->sft_status);
/* if (rc < SUCCESS) */
if (rc == DE_ACCESS || /* -5 Access denied */
rc == DE_INVLDHNDL) /* -6 Invalid handle */
{
*err = rc;
return 0;
}
else
{
*err = SUCCESS;
return WriteCount;
}
*err = SUCCESS;
return WriteCount;
}
*err = SUCCESS;
return 0;
@ -1041,20 +1027,26 @@ BOOL DosGetFree(UBYTE drive, UCOUNT FAR * spc, UCOUNT FAR * navc,
if (cdsp->cdsFlags & CDSNETWDRV)
{
if (*nc == 0xffff)
{
/* Undoc DOS says, its not supported for
network drives. so it's probably OK */
/*printf("FatGetDrvData not yet supported over network drives\n"); */
if (remote_getfree(cdsp, rg) != SUCCESS)
return FALSE;
}
remote_getfree(cdsp, rg);
/* for int21/ah=1c:
Undoc DOS says, its not supported for
network drives. so it's probably OK */
/* some programs such as RHIDE want it though and
the redirector can provide all info
- Bart, 2002 Apr 1 */
if (*nc != 0xffff)
{
*navc = (COUNT) rg[3];
rg[0] &= 0xff;
/* zero media ID (high part) */
}
*spc = (COUNT) rg[0];
*nc = (COUNT) rg[1];
*bps = (COUNT) rg[2];
*navc = (COUNT) rg[3];
return TRUE;
}
@ -1187,6 +1179,15 @@ COUNT DosGetCuDir(UBYTE drive, BYTE FAR * s)
current_ldt = &CDSp->cds_table[drive];
if ((current_ldt->cdsFlags & CDSNETWDRV) == 0)
{
if (current_ldt->cdsDpb == 0)
return DE_INVLDDRV;
if ((media_check(current_ldt->cdsDpb) < 0))
return DE_INVLDDRV;
}
cp = &current_ldt->cdsCurrentPath[current_ldt->cdsJoinOffset];
if (*cp == '\0')
s[0] = '\0';
@ -1361,6 +1362,7 @@ COUNT DosFindNext(void)
fmemset(dta, 0, sizeof(dmatch));
p = dta;
dta = (BYTE FAR *) TempBuffer;
current_ldt = &CDSp->cds_table[((dmatch *) TempBuffer)->dm_drive];
rc = (((dmatch *) TempBuffer)->dm_drive & 0x80) ?
remote_findnext((VOID FAR *) current_ldt) : dos_findnext();

View File

@ -114,14 +114,12 @@ ULONG dsk_lasttime = 0;
STATIC VOID tmark(ddt *pddt)
{
ReadPCClock(&pddt->ddt_fh.ddt_lasttime);
pddt->ddt_fh.ddt_lasttime = ReadPCClock();
}
STATIC BOOL tdelay(ddt *pddt, ULONG ticks)
{
ULONG now;
ReadPCClock(&now);
return now - pddt->ddt_fh.ddt_lasttime >= ticks;
return ReadPCClock() - pddt->ddt_fh.ddt_lasttime >= ticks;
}
#define N_PART 4 /* number of partitions per
@ -141,6 +139,7 @@ STATIC dsk_proc _dsk_init, mediachk, bldbpb, blockio, IoctlQueblk,
Genblkdev, Getlogdev, Setlogdev, blk_Open, blk_Close,
blk_Media, blk_noerr, blk_nondr, blk_error;
STATIC WORD getbpb(ddt * pddt);
#ifdef PROTO
STATIC WORD dskerr(COUNT);
#else
@ -278,6 +277,16 @@ STATIC WORD mediachk(rqptr rp, ddt * pddt)
else
{
rp->r_mcretcode = diskchange(pddt);
if (rp->r_mcretcode == M_DONT_KNOW)
{
/* don't know but can check serial number ... */
ULONG serialno = pddt->ddt_serialno;
COUNT result = getbpb(pddt);
if (result != 0)
return (result);
if (serialno != pddt->ddt_serialno)
rp->r_mcretcode = M_CHANGED;
}
}
return S_DONE;
}
@ -395,8 +404,7 @@ STATIC WORD getbpb(ddt * pddt)
if (ret != 0)
return (dskerr(ret));
getword(&((((BYTE *) & DiskTransferBuffer[BT_BPB]))[0]),
&pbpbarray->bpb_nbyte);
pbpbarray->bpb_nbyte = getword(&DiskTransferBuffer[BT_BPB]);
if (DiskTransferBuffer[0x1fe] != 0x55
|| DiskTransferBuffer[0x1ff] != 0xaa || pbpbarray->bpb_nbyte != 512)
@ -426,23 +434,20 @@ STATIC WORD getbpb(ddt * pddt)
if (pbpbarray->bpb_nfsect != 0)
{
/* FAT16/FAT12 boot sector */
getlong(&((((BYTE *) & DiskTransferBuffer[0x27])[0])),
&pddt->ddt_serialno);
pddt->ddt_serialno = getlong(&DiskTransferBuffer[0x27]);
memcpy(pddt->ddt_volume, &DiskTransferBuffer[0x2B], 11);
memcpy(pddt->ddt_fstype, &DiskTransferBuffer[0x36], 8);
}
else
{
/* FAT32 boot sector */
getlong(&((((BYTE *) & DiskTransferBuffer[0x43])[0])),
&pddt->ddt_serialno);
pddt->ddt_serialno = getlong(&DiskTransferBuffer[0x43]);
memcpy(pddt->ddt_volume, &DiskTransferBuffer[0x47], 11);
memcpy(pddt->ddt_fstype, &DiskTransferBuffer[0x52], 8);
pbpbarray->bpb_ndirent = 512;
}
#else
getlong(&((((BYTE *) & DiskTransferBuffer[0x27])[0])),
&pddt->ddt_serialno);
pddt->ddt_serialno = getlong(&DiskTransferBuffer[0x27]);
memcpy(pddt->ddt_volume, &DiskTransferBuffer[0x2B], 11);
memcpy(pddt->ddt_fstype, &DiskTransferBuffer[0x36], 8);
#endif

View File

@ -163,7 +163,6 @@ COUNT dos_close(COUNT fd)
if (fnp->f_flags.f_dmod)
{
fnp->f_dir.dir_attrib |= D_ARCHIVE;
if (fnp->f_flags.f_ddate == FALSE)
{
fnp->f_dir.dir_time = dos_gettime();
@ -279,25 +278,17 @@ f_node_ptr split_path(BYTE * path, BYTE * fname, BYTE * fext)
STATIC BOOL find_fname(f_node_ptr fnp, BYTE * fname, BYTE * fext, int attr)
{
BOOL found = FALSE;
while (dir_read(fnp) == 1)
{
if (fnp->f_dir.dir_name[0] != '\0')
if (fnp->f_dir.dir_name[0] != DELETED
&& fcmp(fname, (BYTE *) fnp->f_dir.dir_name, FNAME_SIZE)
&& fcmp(fext, (BYTE *) fnp->f_dir.dir_ext, FEXT_SIZE)
&& (fnp->f_dir.dir_attrib & ~(D_RDONLY | D_ARCHIVE | attr)) == 0)
{
if (fnp->f_dir.dir_name[0] == DELETED)
continue;
if (fcmp(fname, (BYTE *) fnp->f_dir.dir_name, FNAME_SIZE)
&& fcmp(fext, (BYTE *) fnp->f_dir.dir_ext, FEXT_SIZE)
&& (fnp->f_dir.dir_attrib & ~(D_RDONLY | D_ARCHIVE | attr)) == 0)
{
found = TRUE;
break;
}
return TRUE;
}
}
return found;
return FALSE;
}
/* Description.
@ -836,7 +827,6 @@ STATIC BOOL find_free(f_node_ptr fnp)
/* */
date dos_getdate()
{
#ifndef NOTIME
BYTE WeekDay, Month, MonthDay;
COUNT Year;
date Date;
@ -848,12 +838,6 @@ date dos_getdate()
(BYTE FAR *) & MonthDay, (COUNT FAR *) & Year);
Date = DT_ENCODE(Month, MonthDay, Year - EPOCH_YEAR);
return Date;
#else
return 0;
#endif
}
/* */
@ -861,7 +845,6 @@ date dos_getdate()
/* */
time dos_gettime()
{
#ifndef NOTIME
BYTE Hour, Minute, Second, Hundredth;
/* First - get the system time set by either the user */
@ -870,9 +853,6 @@ time dos_gettime()
(BYTE FAR *) & Minute,
(BYTE FAR *) & Second, (BYTE FAR *) & Hundredth);
return TM_ENCODE(Hour, Minute, Second / 2);
#else
return 0;
#endif
}
/* */
@ -1391,7 +1371,6 @@ COUNT map_cluster(REG f_node_ptr fnp, COUNT mode)
/* If there are no more free fat entries, then we are full! */
if (!first_fat(fnp))
{
dir_close(fnp);
return DE_HNDLDSKFULL;
}
}
@ -1453,300 +1432,6 @@ COUNT map_cluster(REG f_node_ptr fnp, COUNT mode)
return SUCCESS;
}
/*
comments read optimization for large reads: read total clusters in one piece
running a program like
while (1) {
read(fd, header, sizeof(header)); // small read
read(fd, buffer, header.size); // where size is large, up to 63K
// with average ~32K
}
FreeDOS 2025 is really slow.
on a P200 with modern 30GB harddisk, doing above for a 14.5 MB file
MSDOS 6.22 clustersize 8K ~2.5 sec (accumulates over clusters, reads for 63 sectors seen),
IBM PCDOS 7.0 8K ~4.3
IBM PCDOS 7.0 16K ~2.8
FreeDOS ke2025 ~17.5
with the read optimization (ke2025a),
clustersize 8K ~6.5 sec
clustersize 16K ~4.2 sec
it was verified with IBM feature tool,
that the drive read ahead cache (says it) is on. still this huge difference ;-)
it's coded pretty conservative to avoid all special cases,
so it shouldn't break anything :-)
possible further optimization:
collect read across clusters (if file is not fragmented).
MSDOS does this (as readcounts up to 63 sectors where seen)
specially important for diskettes, where clustersize is 1 sector
the same should be done for writes as well
the time to compile the complete kernel (on some P200) is
reduced from 67 to 56 seconds - in an otherwise identical configuration.
it's not clear if this improvement shows up elsewhere, but it shouldn't harm either
TE 10/18/01 14:00
collect read across clusters (if file is not fragmented) done.
seems still to work :-))
no large performance gains visible, but should now work _much_
better for the people, that complain about slow floppy access
the
fnp->f_offset +to_xfer < fnp->f_highwater && avoid EOF problems
condition can probably _carefully_ be dropped
TE 10/18/01 19:00
*/
/* Read block from disk */
UCOUNT readblock(COUNT fd, VOID FAR * buffer, UCOUNT count, COUNT * err)
{
REG f_node_ptr fnp;
REG struct buffer FAR *bp;
UCOUNT xfr_cnt = 0;
UCOUNT ret_cnt = 0;
UWORD secsize;
UCOUNT to_xfer = count;
ULONG currentblock;
#if defined( DEBUG ) && 0
if (bDumpRdWrParms)
{
printf("readblock:fd %02x buffer %04x:%04x count %x\n",
fd, FP_SEG(buffer), FP_OFF(buffer), count);
}
#endif
/* Translate the fd into an fnode pointer, since all internal */
/* operations are achieved through fnodes. */
fnp = xlt_fd(fd);
/* If the fd was invalid because it was out of range or the */
/* requested file was not open, tell the caller and exit */
/* note: an invalid fd is indicated by a 0 return */
if (fnp == (f_node_ptr) 0 || fnp->f_count <= 0)
{
*err = DE_INVLDHNDL;
return 0;
}
/* Test that we are really about to do a data transfer. If the
count is zero, just exit. (Any read with a count of zero is a nop). */
/* NOTE: doing this up front saves a lot of headaches later. */
if (count == 0)
{
*err = SUCCESS;
return 0;
}
/* Another test is to check for a seek past EOF */
/* 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;
}
/* test that we have a valid mode for this fnode */
if (fnp->f_mode != RDONLY && fnp->f_mode != RDWR)
{
*err = DE_INVLDACC;
return 0;
}
/* The variable secsize will be used later. */
secsize = fnp->f_dpb->dpb_secsize;
/* Adjust the far pointer from user space to supervisor space */
buffer = adjust_far((VOID FAR *) buffer);
/* Do the data transfer. Use block transfer methods so that we */
/* can utilize memory management in future DOS-C versions. */
while (ret_cnt < count)
{
/* 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_highwater))
{
*err = SUCCESS;
return ret_cnt;
}
/* Position the file to the fnode's pointer position. This is */
/* done by updating the fnode's cluster, block (sector) and */
/* byte offset so that read becomes a simple data move */
/* out of the block data buffer. */
/* The more difficult scenario is the (more common) */
/* file offset case. Here, we need to take the fnode's */
/* offset pointer (f_offset) and translate it into a */
/* relative cluster position, cluster block (sector) */
/* offset (f_sector) and byte offset (f_boff). Once we */
/* have this information, we need to translate the */
/* relative cluster position into an absolute cluster */
/* position (f_cluster). This is unfortunate because it */
/* requires a linear search through the file's FAT */
/* entries. It made sense when DOS was originally */
/* designed as a simple floppy disk operating system */
/* where the FAT was contained in core, but now */
/* requires a search through the FAT blocks. */
/* */
/* The algorithm in this function takes advantage of */
/* the blockio block buffering scheme to simplify the */
/* task. */
#ifdef DISPLAY_GETBLOCK
printf("readblock: ");
#endif
if (map_cluster(fnp, XFR_READ) != SUCCESS)
{
*err = DE_SEEK;
dir_close(fnp);
return ret_cnt;
}
/* Compute the block within the cluster and the offset */
/* within the block. */
fnp->f_sector = (fnp->f_offset / secsize) & fnp->f_dpb->dpb_clsmask;
fnp->f_boff = fnp->f_offset % secsize;
currentblock = clus2phys(fnp->f_cluster, fnp->f_dpb) + fnp->f_sector;
/* see comments above */
if (!fnp->f_flags.f_ddir && /* don't experiment with directories yet */
fnp->f_boff == 0) /* complete sectors only */
{
static ULONG startoffset;
UCOUNT sectors_to_read, sectors_wanted;
startoffset = fnp->f_offset;
/* avoid EOF problems */
sectors_wanted =
((UCOUNT) min(fnp->f_highwater - fnp->f_offset, to_xfer)) /
secsize;
if (sectors_wanted < 2)
goto normal_read;
sectors_to_read = fnp->f_dpb->dpb_clsmask + 1 - fnp->f_sector;
sectors_to_read = min(sectors_to_read, sectors_wanted);
fnp->f_offset += sectors_to_read * secsize;
while (sectors_to_read < sectors_wanted)
{
if (map_cluster(fnp, XFR_READ) != SUCCESS)
break;
if (clus2phys(fnp->f_cluster, fnp->f_dpb) !=
currentblock + sectors_to_read)
break;
sectors_to_read += fnp->f_dpb->dpb_clsmask + 1;
sectors_to_read = min(sectors_to_read, sectors_wanted);
fnp->f_offset = startoffset + sectors_to_read * secsize;
}
xfr_cnt = sectors_to_read * secsize;
/* avoid caching trouble */
DeleteBlockInBufferCache(currentblock,
currentblock + sectors_to_read - 1,
fnp->f_dpb->dpb_unit);
if (dskxfer(fnp->f_dpb->dpb_unit,
currentblock,
(VOID FAR *) buffer, sectors_to_read, DSKREAD))
{
fnp->f_offset = startoffset;
*err = DE_BLKINVLD;
return ret_cnt;
}
goto update_pointers;
}
/* normal read: just the old, buffer = sector based read */
normal_read:
#ifdef DSK_DEBUG
printf("read %d links; dir offset %ld, cluster %lx\n",
fnp->f_count, fnp->f_diroff, fnp->f_cluster);
#endif
/* Get the block we need from cache */
bp = getblock(currentblock
/*clus2phys(fnp->f_cluster, fnp->f_dpb) + fnp->f_sector */
, fnp->f_dpb->dpb_unit);
#ifdef DISPLAY_GETBLOCK
printf("DATA (readblock)\n");
#endif
if (bp == NULL) /* (struct buffer *)0 --> DS:0 !! */
{
*err = DE_BLKINVLD;
return ret_cnt;
}
/* transfer a block */
/* Transfer size as either a full block size, or the */
/* requested transfer size, whichever is smaller. */
/* Then compare to what is left, since we can transfer */
/* a maximum of what is left. */
if (fnp->f_flags.f_ddir)
xfr_cnt = min(to_xfer, secsize - fnp->f_boff);
else
xfr_cnt = (UWORD) min(min(to_xfer, secsize - fnp->f_boff),
fnp->f_highwater - fnp->f_offset);
fmemcpy(buffer, &bp->b_buffer[fnp->f_boff], xfr_cnt);
/* complete buffer read ?
probably not reused later
*/
if (xfr_cnt == sizeof(bp->b_buffer) ||
fnp->f_offset + xfr_cnt == fnp->f_highwater)
{
bp->b_flag |= BFR_UNCACHE;
}
/* update pointers and counters */
fnp->f_offset += xfr_cnt;
update_pointers:
ret_cnt += xfr_cnt;
to_xfer -= xfr_cnt;
buffer = add_far((VOID FAR *) buffer, (ULONG) xfr_cnt);
}
*err = SUCCESS;
return ret_cnt;
}
/* extends a file from f_highwater to f_offset */
/* Proper OS's write zeros in between, but DOS just adds */
/* garbage sectors, and lets the caller do the zero filling */
@ -1827,24 +1512,90 @@ STATIC COUNT dos_extend(f_node_ptr fnp)
return SUCCESS;
}
/* Write block to disk */
UCOUNT writeblock(COUNT fd, const VOID FAR * buffer, UCOUNT count, COUNT * err)
/*
comments read optimization for large reads: read total clusters in one piece
running a program like
while (1) {
read(fd, header, sizeof(header)); // small read
read(fd, buffer, header.size); // where size is large, up to 63K
// with average ~32K
}
FreeDOS 2025 is really slow.
on a P200 with modern 30GB harddisk, doing above for a 14.5 MB file
MSDOS 6.22 clustersize 8K ~2.5 sec (accumulates over clusters, reads for 63 sectors seen),
IBM PCDOS 7.0 8K ~4.3
IBM PCDOS 7.0 16K ~2.8
FreeDOS ke2025 ~17.5
with the read optimization (ke2025a),
clustersize 8K ~6.5 sec
clustersize 16K ~4.2 sec
it was verified with IBM feature tool,
that the drive read ahead cache (says it) is on. still this huge difference ;-)
it's coded pretty conservative to avoid all special cases,
so it shouldn't break anything :-)
possible further optimization:
collect read across clusters (if file is not fragmented).
MSDOS does this (as readcounts up to 63 sectors where seen)
specially important for diskettes, where clustersize is 1 sector
the same should be done for writes as well
the time to compile the complete kernel (on some P200) is
reduced from 67 to 56 seconds - in an otherwise identical configuration.
it's not clear if this improvement shows up elsewhere, but it shouldn't harm either
TE 10/18/01 14:00
collect read across clusters (if file is not fragmented) done.
seems still to work :-))
no large performance gains visible, but should now work _much_
better for the people, that complain about slow floppy access
the
fnp->f_offset +to_xfer < fnp->f_highwater && avoid EOF problems
condition can probably _carefully_ be dropped
TE 10/18/01 19:00
*/
/* Read/write block from disk */
/* checking for valid access was already done by the functions in
dosfns.c */
UCOUNT rwblock(COUNT fd, VOID FAR * buffer, UCOUNT count, int mode)
{
REG f_node_ptr fnp;
struct buffer FAR *bp;
REG struct buffer FAR *bp;
UCOUNT xfr_cnt = 0;
UCOUNT ret_cnt = 0;
UWORD secsize;
UCOUNT to_xfer = count;
ULONG currentblock;
#ifdef DEBUG
#if 0 /*DSK_DEBUG*/
if (bDumpRdWrParms)
{
printf("writeblock: fd %02d buffer %04x:%04x count %d\n",
fd, (COUNT) FP_SEG(buffer), (COUNT) FP_OFF(buffer), count);
printf("rwblock:fd %02x buffer %04x:%04x count %x\n",
fd, FP_SEG(buffer), FP_OFF(buffer), count);
}
#endif
/* Translate the fd into an fnode pointer, since all internal */
/* operations are achieved through fnodes. */
fnp = xlt_fd(fd);
@ -1854,25 +1605,19 @@ UCOUNT writeblock(COUNT fd, const VOID FAR * buffer, UCOUNT count, COUNT * err)
/* note: an invalid fd is indicated by a 0 return */
if (fnp == (f_node_ptr) 0 || fnp->f_count <= 0)
{
*err = DE_INVLDHNDL;
return 0;
}
/* test that we have a valid mode for this fnode */
if (fnp->f_mode != WRONLY && fnp->f_mode != RDWR)
if (mode==XFR_WRITE)
{
*err = DE_INVLDACC;
return 0;
fnp->f_dir.dir_attrib |= D_ARCHIVE;
fnp->f_flags.f_dmod = TRUE; /* mark file as modified */
fnp->f_flags.f_ddate = FALSE; /* set date not valid any more */
if (dos_extend(fnp) != SUCCESS)
return 0;
}
fnp->f_flags.f_dmod = TRUE; /* mark file as modified */
fnp->f_flags.f_ddate = FALSE; /* set date not valid any more */
/* extend file from fnp->f_highwater to fnp->f_offset */
*err = dos_extend(fnp);
if (*err != SUCCESS)
return 0;
/* 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). */
@ -1888,8 +1633,11 @@ UCOUNT writeblock(COUNT fd, const VOID FAR * buffer, UCOUNT count, COUNT * err)
/* FAT allocation has to be extended if necessary TE */
/* Now done in dos_extend BO */
/* remove all the following allocated clusters in shrink_file */
fnp->f_highwater = fnp->f_offset;
shrink_file(fnp);
if (mode == XFR_WRITE)
{
fnp->f_highwater = fnp->f_offset;
shrink_file(fnp);
}
return 0;
}
@ -1903,35 +1651,17 @@ UCOUNT writeblock(COUNT fd, const VOID FAR * buffer, UCOUNT count, COUNT * err)
/* can utilize memory management in future DOS-C versions. */
while (ret_cnt < count)
{
/* Do an EOF test and return whatever was transferred */
/* but only for regular files. */
if (mode == XFR_READ && !(fnp->f_flags.f_ddir) && (fnp->f_offset >= fnp->f_highwater))
{
return ret_cnt;
}
/* Position the file to the fnode's pointer position. This is */
/* done by updating the fnode's cluster, block (sector) and */
/* byte offset so that read or write becomes a simple data move */
/* into or out of the block data buffer. */
if (fnp->f_offset == 0l)
{
/* For the write case, a newly created file */
/* will have a start cluster of FREE. If we're */
/* doing a write and this is the first time */
/* through, allocate a new cluster to the file. */
if (checkdstart(fnp->f_dir, FREE))
if (!first_fat(fnp)) /* get a free cluster */
{ /* error means disk full */
dir_close(fnp);
*err = DE_HNDLDSKFULL;
return ret_cnt;
}
/* complete the common operations of */
/* initializing to the starting cluster and */
/* setting all offsets to zero. */
fnp->f_cluster = fnp->f_flags.f_ddir ? fnp->f_dirstart :
getdstart(fnp->f_dir);
fnp->f_cluster_offset = 0l;
fnp->f_back = LONG_LAST_CLUSTER;
fnp->f_sector = 0;
fnp->f_boff = 0;
merge_file_changes(fnp, FALSE); /* /// Added - Ron Cemer */
}
/* The more difficult scenario is the (more common) */
/* file offset case. Here, we need to take the fnode's */
@ -1950,16 +1680,15 @@ UCOUNT writeblock(COUNT fd, const VOID FAR * buffer, UCOUNT count, COUNT * err)
/* The algorithm in this function takes advantage of */
/* the blockio block buffering scheme to simplify the */
/* task. */
else
{
#ifdef DISPLAY_GETBLOCK
printf("writeblock: ");
printf("rwblock: ");
#endif
if (map_cluster(fnp, XFR_WRITE) != SUCCESS)
{
*err = DE_HNDLDSKFULL;
return ret_cnt;
}
if (map_cluster(fnp, mode) != SUCCESS)
{
return ret_cnt;
}
if (mode == XFR_WRITE)
{
merge_file_changes(fnp, FALSE); /* /// Added - Ron Cemer */
}
@ -1968,46 +1697,89 @@ UCOUNT writeblock(COUNT fd, const VOID FAR * buffer, UCOUNT count, COUNT * err)
fnp->f_sector = (fnp->f_offset / secsize) & fnp->f_dpb->dpb_clsmask;
fnp->f_boff = fnp->f_offset % secsize;
currentblock = clus2phys(fnp->f_cluster, fnp->f_dpb) + fnp->f_sector;
/* see comments above */
if (!fnp->f_flags.f_ddir && /* don't experiment with directories yet */
fnp->f_boff == 0) /* complete sectors only */
{
static ULONG startoffset;
UCOUNT sectors_to_xfer, sectors_wanted;
startoffset = fnp->f_offset;
sectors_wanted = to_xfer;
/* avoid EOF problems */
if (mode == XFR_READ && to_xfer > fnp->f_highwater - fnp->f_offset)
sectors_wanted = (UCOUNT)(fnp->f_highwater - fnp->f_offset);
sectors_wanted /= secsize;
if (sectors_wanted == 0)
goto normal_xfer;
sectors_to_xfer = fnp->f_dpb->dpb_clsmask + 1 - fnp->f_sector;
sectors_to_xfer = min(sectors_to_xfer, sectors_wanted);
fnp->f_offset += sectors_to_xfer * secsize;
while (sectors_to_xfer < sectors_wanted)
{
if (map_cluster(fnp, mode) != SUCCESS)
break;
if (clus2phys(fnp->f_cluster, fnp->f_dpb) !=
currentblock + sectors_to_xfer)
break;
sectors_to_xfer += fnp->f_dpb->dpb_clsmask + 1;
sectors_to_xfer = min(sectors_to_xfer, sectors_wanted);
fnp->f_offset = startoffset + sectors_to_xfer * secsize;
}
xfr_cnt = sectors_to_xfer * secsize;
/* avoid caching trouble */
DeleteBlockInBufferCache(currentblock,
currentblock + sectors_to_xfer - 1,
fnp->f_dpb->dpb_unit);
if (dskxfer(fnp->f_dpb->dpb_unit,
currentblock,
(VOID FAR *) buffer, sectors_to_xfer,
mode == XFR_READ ? DSKREAD : DSKWRITE))
{
fnp->f_offset = startoffset;
return ret_cnt;
}
goto update_pointers;
}
/* normal read: just the old, buffer = sector based read */
normal_xfer:
#ifdef DSK_DEBUG
printf("write %d links; dir offset %ld, cluster %d\n",
fnp->f_count, fnp->f_diroff, fnp->f_cluster);
printf("r/w %d links; dir offset %ld, cluster %d, mode %x\n",
fnp->f_count, fnp->f_diroff, fnp->f_cluster, mode);
#endif
/* /// Moved xfr_cnt calculation from below so we can
use it to help decide how to get the block:
read-modify-write using getblock() if we are only
going to write part of the block, or
write using getbuf() if we are going to write
the entire block.
- Ron Cemer */
xfr_cnt = min(to_xfer, secsize - fnp->f_boff);
/* get a buffer to store the block in */
/* /// BUG!!! Added conditional to only use getbuf() if we're going
to write the entire block, which is faster because it does
not first read the block from disk. However, if we are
going to only write part of the block, we MUST use the
getblock() call, which first reads the block from disk.
Without this modification, the kernel was writing garbage
to the file when sequential writes were attempted at less
than the block size. This was causing problems with
piping and redirection in FreeCOM, as well as many other
potential problems.
- Ron Cemer */
if ((fnp->f_boff == 0) && (xfr_cnt == secsize))
/* Get the block we need from cache */
bp = getblock(currentblock
/*clus2phys(fnp->f_cluster, fnp->f_dpb) + fnp->f_sector */
, fnp->f_dpb->dpb_unit);
#ifdef DISPLAY_GETBLOCK
printf("DATA (rwblock)\n");
#endif
if (bp == NULL) /* (struct buffer *)0 --> DS:0 !! */
{
bp = getblockOver(clus2phys(fnp->f_cluster, fnp->f_dpb) +
fnp->f_sector, fnp->f_dpb->dpb_unit);
}
else
{
bp = getblock(clus2phys(fnp->f_cluster, fnp->f_dpb) +
fnp->f_sector, fnp->f_dpb->dpb_unit);
}
if (bp == NULL)
{
*err = DE_BLKINVLD;
return ret_cnt;
}
@ -2016,32 +1788,51 @@ UCOUNT writeblock(COUNT fd, const VOID FAR * buffer, UCOUNT count, COUNT * err)
/* requested transfer size, whichever is smaller. */
/* Then compare to what is left, since we can transfer */
/* a maximum of what is left. */
/* /// Moved xfr_cnt calculation to above getbuf/getblock calls so we can
use it to help decide which one to call.
- Ron Cemer
xfr_cnt = min(to_xfer, secsize - fnp->f_boff);
*/
fmemcpy(&bp->b_buffer[fnp->f_boff], buffer, xfr_cnt);
bp->b_flag |= BFR_DIRTY | BFR_VALID;
if (!fnp->f_flags.f_ddir && mode == XFR_READ)
xfr_cnt = (UWORD) min(xfr_cnt, fnp->f_highwater - fnp->f_offset);
if (xfr_cnt == sizeof(bp->b_buffer)) /* probably not used later */
/* transfer a block */
/* Transfer size as either a full block size, or the */
/* requested transfer size, whichever is smaller. */
/* Then compare to what is left, since we can transfer */
/* a maximum of what is left. */
if (mode == XFR_WRITE)
{
fmemcpy(&bp->b_buffer[fnp->f_boff], buffer, xfr_cnt);
bp->b_flag |= BFR_DIRTY | BFR_VALID;
}
else
{
fmemcpy(buffer, &bp->b_buffer[fnp->f_boff], xfr_cnt);
}
/* complete buffer transferred ?
probably not reused later
*/
if (xfr_cnt == sizeof(bp->b_buffer) ||
(mode == XFR_READ && fnp->f_offset + xfr_cnt == fnp->f_highwater))
{
bp->b_flag |= BFR_UNCACHE;
}
/* update pointers and counters */
fnp->f_offset += xfr_cnt;
update_pointers:
ret_cnt += xfr_cnt;
to_xfer -= xfr_cnt;
fnp->f_offset += xfr_cnt;
buffer = add_far((VOID FAR *) buffer, (ULONG) xfr_cnt);
if (fnp->f_offset > fnp->f_highwater)
if (mode == XFR_WRITE)
{
fnp->f_highwater = fnp->f_offset;
fnp->f_dir.dir_size = fnp->f_highwater;
if (fnp->f_offset > fnp->f_highwater)
{
fnp->f_highwater = fnp->f_offset;
fnp->f_dir.dir_size = fnp->f_highwater;
}
merge_file_changes(fnp, FALSE); /* /// Added - Ron Cemer */
}
merge_file_changes(fnp, FALSE); /* /// Added - Ron Cemer */
}
*err = SUCCESS;
return ret_cnt;
}
@ -2310,6 +2101,8 @@ VOID bpb_to_dpb(bpb FAR * bpbp, REG struct dpb FAR * dpbp)
COUNT media_check(REG struct dpb FAR * dpbp)
{
BYTE status;
/* First test if anyone has changed the removable media */
FOREVER
{
@ -2343,7 +2136,8 @@ COUNT media_check(REG struct dpb FAR * dpbp)
}
}
switch (MediaReqHdr.r_mcretcode | dpbp->dpb_flags)
status = MediaReqHdr.r_mcretcode | dpbp->dpb_flags;
switch (status)
{
case M_NOT_CHANGED:
/* It was definitely not changed, so ignore it */
@ -2392,10 +2186,15 @@ COUNT media_check(REG struct dpb FAR * dpbp)
}
}
#ifdef WITHFAT32
bpb_to_dpb(MediaReqHdr.r_bpptr, dpbp, TRUE);
/* extend dpb only for internal or FAT32 devices */
bpb_to_dpb(MediaReqHdr.r_bpptr, dpbp,
ISFAT32(dpbp) || FP_SEG(dpbp) == FP_SEG(&os_major));
#else
bpb_to_dpb(MediaReqHdr.r_bpptr, dpbp);
#endif
/* need to change to root directory if changed */
if (status == M_CHANGED)
CDSp->cds_table[dpbp->dpb_unit].cdsCurrentPath[3] = '\0';
return SUCCESS;
}
}

View File

@ -34,21 +34,9 @@ static BYTE *RcsId =
"$Id$";
#endif
#ifdef PROTO
UCOUNT link_fat12(struct dpb FAR *, CLUSTER, CLUSTER);
UCOUNT link_fat16(struct dpb FAR *, CLUSTER, CLUSTER);
UCOUNT link_fat32(struct dpb FAR *, CLUSTER, CLUSTER);
CLUSTER next_cl12(struct dpb FAR *, CLUSTER);
CLUSTER next_cl16(struct dpb FAR *, CLUSTER);
CLUSTER next_cl32(struct dpb FAR *, CLUSTER);
#else
UCOUNT link_fat12();
UCOUNT link_fat16();
UCOUNT link_fat32();
CLUSTER next_cl12();
CLUSTER next_cl16();
CLUSTER next_cl32();
#endif
STATIC unsigned link_fat12(struct dpb FAR *, unsigned, unsigned);
STATIC unsigned link_fat16(struct dpb FAR *, unsigned, unsigned);
STATIC unsigned link_fat32(struct dpb FAR *, CLUSTER, CLUSTER);
/************************************************************************/
/* */
@ -158,15 +146,15 @@ void write_fsinfo(struct dpb FAR * dpbp)
/* 12 bytes are compressed to 9 bytes */
/* */
UCOUNT link_fat(struct dpb FAR * dpbp, CLUSTER Cluster1,
unsigned link_fat(struct dpb FAR * dpbp, CLUSTER Cluster1,
REG CLUSTER Cluster2)
{
UCOUNT res;
unsigned res;
if (ISFAT12(dpbp))
res = link_fat12(dpbp, Cluster1, Cluster2);
res = link_fat12(dpbp, (unsigned)Cluster1, (unsigned)Cluster2);
else if (ISFAT16(dpbp))
res = link_fat16(dpbp, Cluster1, Cluster2);
res = link_fat16(dpbp, (unsigned)Cluster1, (unsigned)Cluster2);
#ifdef WITHFAT32
else if (ISFAT32(dpbp))
res = link_fat32(dpbp, Cluster1, Cluster2);
@ -212,10 +200,10 @@ UCOUNT link_fat(struct dpb FAR * dpbp, CLUSTER Cluster1,
}
#ifdef WITHFAT32
UCOUNT link_fat32(struct dpb FAR * dpbp, CLUSTER Cluster1,
STATIC unsigned link_fat32(struct dpb FAR * dpbp, CLUSTER Cluster1,
CLUSTER Cluster2)
{
UCOUNT idx;
unsigned idx;
struct buffer FAR *bp;
/* Get the block that this cluster is in */
@ -230,7 +218,7 @@ UCOUNT link_fat32(struct dpb FAR * dpbp, CLUSTER Cluster1,
/* Finally, put the word into the buffer and mark the */
/* buffer as dirty. */
fputlong((DWORD FAR *) & Cluster2, (VOID FAR *) & (bp->b_buffer[idx]));
fputlong(&bp->b_buffer[idx], Cluster2);
bp->b_flag |= BFR_DIRTY | BFR_VALID;
/* Return successful. */
@ -240,10 +228,10 @@ UCOUNT link_fat32(struct dpb FAR * dpbp, CLUSTER Cluster1,
#endif
STATIC UCOUNT link_fat16(struct dpb FAR * dpbp, CLUSTER Cluster1,
CLUSTER Cluster2)
STATIC unsigned link_fat16(struct dpb FAR * dpbp, unsigned Cluster1,
unsigned Cluster2)
{
UCOUNT idx;
unsigned idx;
struct buffer FAR *bp;
/* Get the block that this cluster is in */
@ -254,11 +242,11 @@ STATIC UCOUNT link_fat16(struct dpb FAR * dpbp, CLUSTER Cluster1,
/* form an index so that we can read the block as a */
/* byte array */
idx = (UWORD) ((Cluster1 * SIZEOF_CLST16) % dpbp->dpb_secsize);
idx = (Cluster1 * SIZEOF_CLST16) % dpbp->dpb_secsize;
/* Finally, put the word into the buffer and mark the */
/* buffer as dirty. */
fputword((WORD FAR *) & Cluster2, (VOID FAR *) & (bp->b_buffer[idx]));
fputword(&bp->b_buffer[idx], Cluster2);
bp->b_flag |= BFR_DIRTY | BFR_VALID;
/* Return successful. */
@ -266,11 +254,11 @@ STATIC UCOUNT link_fat16(struct dpb FAR * dpbp, CLUSTER Cluster1,
return SUCCESS;
}
STATIC UCOUNT link_fat12(struct dpb FAR * dpbp, CLUSTER Cluster1,
CLUSTER Cluster2)
STATIC unsigned link_fat12(struct dpb FAR * dpbp, unsigned Cluster1,
unsigned Cluster2)
{
REG UBYTE FAR *fbp0, FAR * fbp1;
UCOUNT idx;
unsigned idx;
struct buffer FAR *bp, FAR * bp1;
/* Get the block that this cluster is in */
@ -280,12 +268,15 @@ STATIC UCOUNT link_fat12(struct dpb FAR * dpbp, CLUSTER Cluster1,
/* form an index so that we can read the block as a */
/* byte array */
idx = (UCOUNT) (((Cluster1 << 1) + Cluster1) >> 1) % dpbp->dpb_secsize;
idx = (unsigned) (((Cluster1 << 1) + Cluster1) >> 1) % dpbp->dpb_secsize;
/* Test to see if the cluster straddles the block. If */
/* it does, get the next block and use both to form the */
/* the FAT word. Otherwise, just point to the next */
/* block. */
fbp0 = &bp->b_buffer[idx];
fbp1 = fbp0 + 1;
if (idx >= dpbp->dpb_secsize - 1)
{
bp1 = getFATblock(Cluster1 + 1, dpbp);
@ -294,11 +285,8 @@ STATIC UCOUNT link_fat12(struct dpb FAR * dpbp, CLUSTER Cluster1,
bp1->b_flag |= BFR_DIRTY | BFR_VALID;
fbp1 = (UBYTE FAR *) & (bp1->b_buffer[0]);
fbp1 = &bp1->b_buffer[0];
}
else
fbp1 = (UBYTE FAR *) & (bp->b_buffer[idx + 1]);
fbp0 = (UBYTE FAR *) & (bp->b_buffer[idx]);
bp->b_flag |= BFR_DIRTY | BFR_VALID;
/* Now pack the value in */
@ -338,16 +326,15 @@ CLUSTER next_cluster(struct dpb FAR * dpbp, CLUSTER ClusterNum)
{
union {
UBYTE bytes[2];
UCOUNT word;
unsigned word;
} clusterbuff;
UCOUNT idx;
unsigned idx;
/* form an index so that we can read the block as a */
/* byte array */
idx =
(UCOUNT) (((ClusterNum << 1) +
ClusterNum) >> 1) % dpbp->dpb_secsize;
idx = ((((unsigned)ClusterNum << 1) + (unsigned)ClusterNum) >> 1) %
dpbp->dpb_secsize;
clusterbuff.bytes[0] = bp->b_buffer[idx];
@ -395,26 +382,13 @@ CLUSTER next_cluster(struct dpb FAR * dpbp, CLUSTER ClusterNum)
{
UWORD res;
#ifndef I86
UCOUNT idx;
/* form an index so that we can read the block as a */
/* byte array */
idx = (ClusterNum * SIZEOF_CLST16) % dpbp->dpb_secsize;
/* and get the cluster number */
/* Get the cluster number, */
res = fgetword(&bp->b_buffer[((unsigned)ClusterNum * SIZEOF_CLST16) %
dpbp->dpb_secsize]);
fgetword((VOID FAR *) & (bp->b_buffer[idx]), (WORD FAR *) & res);
#else
/* this saves 2 WORDS of stack :-) */
res =
*(UWORD FAR *) & (bp->
b_buffer[(UCOUNT)
((ClusterNum * SIZEOF_CLST16) %
dpbp->dpb_secsize)]);
#endif
if (res >= MASK16)
return LONG_LAST_CLUSTER;
if (res == BAD16)
@ -427,11 +401,8 @@ CLUSTER next_cluster(struct dpb FAR * dpbp, CLUSTER ClusterNum)
{
UDWORD res;
res =
*(UDWORD FAR *) & (bp->
b_buffer[(UCOUNT)
((ClusterNum * SIZEOF_CLST32) %
dpbp->dpb_secsize)]);
res = fgetlong(&bp->b_buffer[((unsigned)ClusterNum * SIZEOF_CLST32) %
dpbp->dpb_secsize]);
if (res > LONG_BAD)
return LONG_LAST_CLUSTER;

View File

@ -62,13 +62,27 @@ static dmatch Dmatch;
VOID FatGetDrvData(UCOUNT drive, UCOUNT FAR * spc, UCOUNT FAR * bps,
UCOUNT FAR * nc, BYTE FAR ** mdp)
{
static BYTE mdb;
UCOUNT navc;
/* get the data available from dpb */
*nc = 0xffff; /* pass 0xffff to skip free count */
if (DosGetFree((UBYTE) drive, spc, &navc, bps, nc))
{
struct cds FAR *cdsp =
&CDSp->cds_table[(drive == 0 ? default_drive : drive - 1)];
/* Point to the media desctriptor for this drive */
*mdp = (BYTE FAR *) & (CDSp->cds_table[drive].cdsDpb->dpb_mdb);
if (cdsp->cdsFlags & CDSNETWDRV)
{
mdb = *spc >> 8;
*mdp = &mdb;
*spc &= 0xff;
}
else
{
*mdp = (BYTE FAR *) & (cdsp->cdsDpb->dpb_mdb);
}
}
}
#define PARSE_SEP_STOP 0x01

View File

@ -399,7 +399,10 @@ VOID ASMCFUNC FAR CharMapSrvc(VOID);
VOID ASMCFUNC FAR set_stack(VOID);
VOID ASMCFUNC FAR restore_stack(VOID);
/*VOID INRPT FAR handle_break(VOID); */
VOID ASMCFUNC ReadPCClock(ULONG *);
BOOL ASMCFUNC ReadATClock(BYTE *, BYTE *, BYTE *, BYTE *);
ULONG ASMCFUNC ReadPCClock(VOID);
VOID ASMCFUNC WriteATClock(BYTE *, BYTE, BYTE, BYTE);
VOID ASMCFUNC WritePCClock(ULONG);
BYTE FAR * ASMCFUNC device_end(VOID);
COUNT ASMCFUNC kb_data(VOID);
COUNT ASMCFUNC kb_input(VOID);
@ -427,25 +430,25 @@ COUNT con();
/* special word packing prototypes */
/* */
#ifdef NATIVE
#define getlong(vp, lp) (*(LONG *)(lp)=*(LONG *)(vp))
#define getword(vp, wp) (*(WORD *)(wp)=*(WORD *)(vp))
#define getbyte(vp, bp) (*(BYTE *)(bp)=*(BYTE *)(vp))
#define fgetlong(vp, lp) (*(LONG FAR *)(lp)=*(LONG FAR *)(vp))
#define fgetword(vp, wp) (*(WORD FAR *)(wp)=*(WORD FAR *)(vp))
#define fgetbyte(vp, bp) (*(BYTE FAR *)(bp)=*(BYTE FAR *)(vp))
#define fputlong(lp, vp) (*(LONG FAR *)(vp)=*(LONG FAR *)(lp))
#define fputword(wp, vp) (*(WORD FAR *)(vp)=*(WORD FAR *)(wp))
#define fputbyte(bp, vp) (*(BYTE FAR *)(vp)=*(BYTE FAR *)(bp))
#define getlong(vp) (*(UDWORD *)(vp))
#define getword(vp) (*(UWORD *)(vp))
#define getbyte(vp) (*(UBYTE *)(vp))
#define fgetlong(vp) (*(UDWORD FAR *)(vp))
#define fgetword(vp) (*(UWORD FAR *)(vp))
#define fgetbyte(vp) (*(UBYTE FAR *)(vp))
#define fputlong(vp, l) (*(UDWORD FAR *)(vp)=l)
#define fputword(vp, w) (*(UWORD FAR *)(vp)=w)
#define fputbyte(vp, b) (*(UBYTE FAR *)(vp)=b)
#else
#ifdef PROTO
VOID getword(VOID *, WORD *);
VOID getbyte(VOID *, BYTE *);
VOID fgetlong(VOID FAR *, LONG FAR *);
VOID fgetword(VOID FAR *, WORD FAR *);
VOID fgetbyte(VOID FAR *, BYTE FAR *);
VOID fputlong(LONG FAR *, VOID FAR *);
VOID fputword(WORD FAR *, VOID FAR *);
VOID fputbyte(BYTE FAR *, VOID FAR *);
WORD getword(VOID *);
BYTE getbyte(VOID *);
LONG fgetlong(VOID FAR *);
WORD fgetword(VOID FAR *);
BYTE fgetbyte(VOID FAR *);
VOID fputlong(VOID FAR *, UDWORD);
VOID fputword(VOID FAR *, UWORD);
VOID fputbyte(VOID FAR *, UBYTE);
#else
VOID getword();
VOID getbyte();

View File

@ -42,6 +42,9 @@ extern COUNT DOSFAR nUnits;
extern UWORD DOSFAR LBA_WRITE_VERIFY;
/* floppy parameter table, at 70:xxxx */
extern unsigned char DOSTEXTFAR int1e_table[0xe];
/*
* Rev 1.0 13 May 2001 tom ehlert
* Initial revision.
@ -611,7 +614,7 @@ void DosDefinePartition(struct DriveParamS *driveParam,
{
LBA_to_CHS(&chs, StartSector, driveParam);
printf("%c: HD%d", 'A' + nUnits, (driveParam->driveno & 0x7f) + 1);
printf("\r%c: HD%d", 'A' + nUnits, (driveParam->driveno & 0x7f) + 1);
if (extendedPartNo)
printf(" Ext:%d", extendedPartNo);
@ -1237,6 +1240,14 @@ void ReadAllPartitionTables(void)
ddt FAR *pddt;
static iregs regs;
/* quick adjustment of diskette parameter table */
fmemcpy(int1e_table, *(char FAR * FAR *)MK_FP(0, 0x1e*4), sizeof(int1e_table));
/* enforce min. 9 sectors per track */
if (int1e_table[4] < 9)
int1e_table[4] = 9;
/* and adjust int1e */
setvec(0x1e, (intvec)int1e_table);
/* Setup media info and BPBs arrays for floppies */
for (Unit = 0; Unit < nUnits; Unit++)
{
@ -1339,7 +1350,7 @@ void ReadAllPartitionTables(void)
/* disk initialization: returns number of units */
COUNT dsk_init()
{
printf(" - InitDisk\n");
printf(" - InitDisk");
#ifdef DEBUG
{

View File

@ -37,7 +37,7 @@ static BYTE *RcsId =
UWORD init_oem(void)
{
UWORD top_k;
UWORD top_k = 0;
#ifndef __TURBOC__
asm

View File

@ -58,6 +58,10 @@ struct HugeSectorBlock {
BYTE FAR *buf;
};
/* must be global/file scope, Turbo C uses the wrong segment for
* function scope */
STATIC const char dbcsTable[] = {0, 0, 0, 0};
/* Normal entry. This minimizes user stack usage by avoiding local */
/* variables needed for the rest of the handler. */
/* this here works on the users stack !! and only very few functions
@ -1325,7 +1329,6 @@ dispatch:
/* UNDOCUMENTED: Double byte and korean tables */
case 0x63:
{
static char *dbcsTable = "\0\0\0\0";
r->DS = FP_SEG(dbcsTable);
r->SI = FP_OFF(dbcsTable);
#if 0

View File

@ -230,7 +230,9 @@ _nul_intr:
pop es
retf
; floppy parameter table
global _int1e_table
_int1e_table: times 0eh db 0
;************************************************************
; KERNEL FIXED DATA AREA

View File

@ -33,7 +33,7 @@
#include "init-dat.h"
GLOBAL BYTE copyright[] =
"(C) Copyright 1995-2001 Pasquale J. Villani and The FreeDOS Project.\n"
"(C) Copyright 1995-2002 Pasquale J. Villani and The FreeDOS Project.\n"
"All Rights Reserved. This is free software and comes with ABSOLUTELY NO\n"
"WARRANTY; you can redistribute it and/or modify it under the terms of the\n"
"GNU General Public License as published by the Free Software Foundation;\n"
@ -174,13 +174,13 @@ VOID ASMCFUNC FreeDOSmain(void)
/* clear the Init BSS area (what normally the RTL does */
memset(_ib_start, 0, _ib_end - _ib_start);
signon();
init_kernel();
#ifdef DEBUG
/* Non-portable message kludge alert! */
printf("KERNEL: Boot drive = %c\n", 'A' + BootDrive - 1);
#endif
signon();
kernel();
}
@ -361,9 +361,9 @@ STATIC VOID FsConfig(VOID)
STATIC VOID signon()
{
printf("\n%S", (void FAR *)os_release);
printf("\r%S", (void FAR *)os_release);
printf("Kernel compatibility %d.%d", os_major, os_minor);
printf("Kernel compatibility %d.%d", MAJOR_RELEASE, MINOR_RELEASE);
#if defined(__TURBOC__)
printf(" - TURBOC");
@ -393,6 +393,7 @@ STATIC void kernel()
int rc;
extern char MenuSelected;
extern unsigned Menus;
BYTE master_env[32];
char *masterenv_ptr = master_env;
@ -405,9 +406,9 @@ STATIC void kernel()
masterenv_ptr += sprintf(masterenv_ptr, "PATH=.");
/* export the current selected config menu */
if (MenuSelected)
if (Menus)
{
masterenv_ptr += sprintf(masterenv_ptr, "CONFIG=%c", MenuSelected);
masterenv_ptr += sprintf(masterenv_ptr, "CONFIG=%c", MenuSelected+'0');
}
exb.exec.env_seg = DOS_PSP + 8;
@ -463,8 +464,8 @@ STATIC void kernel()
}
exb.exec.cmd_line = (CommandTail FAR *) & Cmd;
exb.exec.fcb_1 = exb.exec.fcb_2 = (fcb FAR *) 0;
exb.exec.fcb_1 = exb.exec.fcb_2 = (fcb FAR *) 0xfffffffful;
#ifdef DEBUG
printf("Process 0 starting: %s\n\n", Config.cfgInit);
#endif

View File

@ -168,43 +168,43 @@ HEADERS=\
# XXX: I generated these using `gcc -MM' and `sed', so they may not be
# completely correct... -- ror4
#blockio.obj: blockio.c $(HEADERS) $(CONFIGURATION)
blockio.obj: blockio.c $(HEADERS) $(CONFIGURATION)
#break.obj: break.c $(HEADERS) $(CONFIGURATION)
break.obj: break.c $(HEADERS) $(CONFIGURATION)
#chario.obj: chario.c $(HEADERS) $(CONFIGURATION)
chario.obj: chario.c $(HEADERS) $(CONFIGURATION)
#dosfns.obj: dosfns.c $(HEADERS) $(CONFIGURATION)
dosfns.obj: dosfns.c $(HEADERS) $(CONFIGURATION)
#dosnames.obj: dosnames.c $(HEADERS) $(CONFIGURATION)
dosnames.obj: dosnames.c $(HEADERS) $(CONFIGURATION)
#dsk.obj: dsk.c $(HEADERS) $(CONFIGURATION)
dsk.obj: dsk.c $(HEADERS) $(CONFIGURATION)
#error.obj: error.c $(HEADERS) $(CONFIGURATION)
error.obj: error.c $(HEADERS) $(CONFIGURATION)
#fatdir.obj: fatdir.c $(HEADERS) $(CONFIGURATION)
fatdir.obj: fatdir.c $(HEADERS) $(CONFIGURATION)
#fatfs.obj: fatfs.c $(HEADERS) $(CONFIGURATION)
fatfs.obj: fatfs.c $(HEADERS) $(CONFIGURATION)
#fattab.obj: fattab.c $(HEADERS) $(CONFIGURATION)
fattab.obj: fattab.c $(HEADERS) $(CONFIGURATION)
#fcbfns.obj: fcbfns.c $(HEADERS) $(CONFIGURATION)
fcbfns.obj: fcbfns.c $(HEADERS) $(CONFIGURATION)
#inthndlr.obj: inthndlr.c $(HEADERS) $(CONFIGURATION)
inthndlr.obj: inthndlr.c $(HEADERS) $(CONFIGURATION)
#ioctl.obj: ioctl.c $(HEADERS) $(CONFIGURATION)
ioctl.obj: ioctl.c $(HEADERS) $(CONFIGURATION)
#memmgr.obj: memmgr.c $(HEADERS) $(CONFIGURATION)
memmgr.obj: memmgr.c $(HEADERS) $(CONFIGURATION)
#misc.obj: misc.c $(HEADERS) $(CONFIGURATION)
misc.obj: misc.c $(HEADERS) $(CONFIGURATION)
#lfnapi.obj: lfnapi.c $(HEADERS) $(CONFIGURATION)
lfnapi.obj: lfnapi.c $(HEADERS) $(CONFIGURATION)
#newstuff.obj: newstuff.c $(HEADERS) $(CONFIGURATION)
newstuff.obj: newstuff.c $(HEADERS) $(CONFIGURATION)
#network.obj: network.c $(HEADERS) $(CONFIGURATION)
network.obj: network.c $(HEADERS) $(CONFIGURATION)
#nls.obj: nls.c $(HEADERS) $(CONFIGURATION)
nls.obj: nls.c $(HEADERS) $(CONFIGURATION)
# \
# 001-437.nls

View File

@ -286,8 +286,13 @@ stopIt: /* reached from FIRST_FIT on match */
*/
COUNT DosMemLargest(UWORD FAR * size)
{
REG mcb FAR *p;
seg dummy;
*size = 0;
DosMemAlloc(0xffff, LARGEST, &dummy, size);
return *size ? SUCCESS : DE_NOMEM;
#if 0
REG mcb FAR *p;
/* Initialize */
p = ((mem_access_mode & (FIRST_FIT_UO | FIRST_FIT_U)) && uppermem_link
&& uppermem_root != 0xffff) ? para2far(uppermem_root) : para2far(first_mcb);
@ -320,7 +325,7 @@ COUNT DosMemLargest(UWORD FAR * size)
/* If *size is still zero, aka nothing had changed, either no unused
block was found at all or a zero-length block only.
Both is considered as a failure */
return *size ? SUCCESS : DE_NOMEM;
#endif
}
/*

View File

@ -393,6 +393,7 @@ COUNT truename(char FAR * src, char FAR * dest, COUNT t)
char c, *bufend = buf + (sizeof(buf) - 1);
int gotAnyWildcards = 0;
int seglen, copylen, state;
int error = DE_PATHNOTFND;
while ((*src) && (bufp < bufend))
{
/* Skip duplicated slashes. */
@ -404,7 +405,12 @@ COUNT truename(char FAR * src, char FAR * dest, COUNT t)
for (seglen = 0;; seglen++)
{
c = src[seglen];
if ((c == '\0') || (c == '/') || (c == '\\'))
if (c == '\0')
{
error = DE_FILENOTFND;
break;
}
else if ((c == '/') || (c == '\\'))
break;
}
if (seglen > 0)
@ -426,7 +432,7 @@ COUNT truename(char FAR * src, char FAR * dest, COUNT t)
else
{
/* .. in root dir illegal */
return DE_PATHNOTFND;
return error;
}
}
else
@ -434,7 +440,7 @@ COUNT truename(char FAR * src, char FAR * dest, COUNT t)
/* New segment. If any wildcards in previous
segment(s), this is an invalid path. */
if (gotAnyWildcards || src[0] == '.')
return DE_PATHNOTFND;
return error;
/* Append current path segment to result. */
*(bufp++) = '\\';
if (bufp >= bufend)
@ -456,8 +462,6 @@ COUNT truename(char FAR * src, char FAR * dest, COUNT t)
break;
copylen++;
}
copylen = 0;
state = 1; /* Go wait for dot */
break;
}
if (c == '.')
@ -465,26 +469,17 @@ COUNT truename(char FAR * src, char FAR * dest, COUNT t)
if (src[i + 1] != '.' && i + 1 < seglen)
*(bufp++) = '.';
copylen = 0;
state = 2; /* Copy extension next */
state = 1; /* Copy extension next */
break;
}
*(bufp++) = c;
copylen++;
if (copylen >= FNAME_SIZE)
if (copylen < FNAME_SIZE)
{
copylen = 0;
state = 1; /* Go wait for dot */
*(bufp++) = c;
copylen++;
break;
}
break;
case 1: /* Looking for dot so we can copy exten */
if (src[i] == '.' && src[i + 1] != '.' && i + 1 < seglen)
{
*(bufp++) = '.';
state = 2;
}
break;
case 2: /* Copying extension */
case 1: /* Copying extension */
if (c == '*')
{
while (copylen < FEXT_SIZE)
@ -494,20 +489,13 @@ COUNT truename(char FAR * src, char FAR * dest, COUNT t)
break;
copylen++;
}
i = seglen; /* Done with segment */
break;
}
if (c == '.')
return error;
if (copylen < FEXT_SIZE)
{
i = seglen; /* Done with segment */
break;
}
*(bufp++) = c;
copylen++;
if (copylen >= FEXT_SIZE)
{
i = seglen; /* Done with segment */
break;
*(bufp++) = c;
copylen++;
}
break;
}

View File

@ -366,15 +366,20 @@ COUNT do_printf(CONST BYTE * fmt, BYTE ** arg)
void hexd(char *title, UBYTE FAR * p, COUNT numBytes)
{
int loop;
printf("%s%04x|", title, FP_SEG(p));
for (loop = 0; loop < numBytes; loop++)
printf("%02x ", p[loop]);
printf("|");
int loop, start = 0;
printf("%s", title);
if (numBytes > 16)
printf("\n");
for (loop = 0; loop < numBytes; loop++)
printf("%c", p[loop] < 0x20 ? '.' : p[loop]);
printf("\n");
for (start = 0; start < numBytes; start += 16)
{
printf("%p|", p+start);
for (loop = start; loop < numBytes && loop < start+16;loop++)
printf("%02x ", p[loop]);
for (loop = start; loop < numBytes && loop < start+16;loop++)
printf("%c", p[loop] < 0x20 ? '.' : p[loop]);
printf("\n");
}
}
#ifdef TEST

View File

@ -177,7 +177,7 @@ _spawn_int23:
;; complete the jump to INT-23 via RETF and restore BP
xchg word [bp-4], bp
stc ;; set default action --> terminate
clc ;; set default action --> resume
; invoke the int 23 handler its address has been constructed
;; on the stack
retf

View File

@ -158,8 +158,7 @@ BOOL dos_setfsize(COUNT fd, LONG size);
COUNT dos_mkdir(BYTE * dir);
BOOL last_link(f_node_ptr fnp);
COUNT map_cluster(REG f_node_ptr fnp, COUNT mode);
UCOUNT readblock(COUNT fd, VOID FAR * buffer, UCOUNT count, COUNT * err);
UCOUNT writeblock(COUNT fd, const VOID FAR * buffer, UCOUNT count, COUNT * err);
UCOUNT rwblock(COUNT fd, VOID FAR * buffer, UCOUNT count, int mode);
COUNT dos_read(COUNT fd, VOID FAR * buffer, UCOUNT count);
COUNT dos_write(COUNT fd, const VOID FAR * buffer, UCOUNT count);
LONG dos_lseek(COUNT fd, LONG foffset, COUNT origin);
@ -184,16 +183,7 @@ void read_fsinfo(struct dpb FAR * dpbp);
void write_fsinfo(struct dpb FAR * dpbp);
UCOUNT link_fat(struct dpb FAR * dpbp, CLUSTER Cluster1,
REG CLUSTER Cluster2);
UCOUNT link_fat32(struct dpb FAR * dpbp, CLUSTER Cluster1,
CLUSTER Cluster2);
UCOUNT link_fat16(struct dpb FAR * dpbp, CLUSTER Cluster1,
CLUSTER Cluster2);
UCOUNT link_fat12(struct dpb FAR * dpbp, CLUSTER Cluster1,
CLUSTER Cluster2);
CLUSTER next_cluster(struct dpb FAR * dpbp, REG CLUSTER ClusterNum);
CLUSTER next_cl32(struct dpb FAR * dpbp, REG CLUSTER ClusterNum);
CLUSTER next_cl16(struct dpb FAR * dpbp, REG CLUSTER ClusterNum);
CLUSTER next_cl12(struct dpb FAR * dpbp, REG CLUSTER ClusterNum);
/* fcbfns.c */
VOID DosOutputString(BYTE FAR * s);

View File

@ -30,61 +30,37 @@
#include "globals.h"
#ifdef VERSION_STRINGS
static BYTE *RcsId =
static char *RcsId =
"$Id$";
#endif
#ifdef PROTO
VOID ASMCFUNC WriteATClock(BYTE *, BYTE, BYTE, BYTE);
VOID ASMCFUNC WritePCClock(ULONG);
COUNT BcdToByte(COUNT);
COUNT BcdToWord(BYTE *, UWORD *, UWORD *, UWORD *);
COUNT ByteToBcd(COUNT);
VOID DayToBcd(BYTE *, UWORD *, UWORD *, UWORD *);
#else
VOID WriteATClock();
VOID WritePCClock();
COUNT BcdToByte();
COUNT BcdToWord();
COUNT ByteToBcd();
VOID DayToBcd();
#endif
/* */
/* WARNING - THIS DRIVER IS NON-PORTABLE!!!! */
/* */
extern UWORD days[2][13]; /* this is defined by SYSTIME.C */
static struct ClockRecord clk;
/*
static BYTE bcdDays[4];
static UWORD Month,
Day,
Year;
static BYTE bcdMinutes;
static BYTE bcdHours;
/ ** static BYTE bcdHundredths;* /
static BYTE bcdSeconds;
static ULONG Ticks;
*/
UWORD ASM DaysSinceEpoch = 0;
typedef UDWORD ticks_t;
BOOL ASMCFUNC ReadATClock(BYTE *, BYTE *, BYTE *, BYTE *);
STATIC COUNT BcdToByte(COUNT x)
STATIC int ByteToBcd(int x)
{
return ((((x) >> 4) & 0xf) * 10 + ((x) & 0xf));
return ((x / 10) << 4) | (x % 10);
}
STATIC int BcdToByte(int x)
{
return ((x >> 4) & 0xf) * 10 + (x & 0xf);
}
STATIC void DayToBcd(BYTE * x, unsigned mon, unsigned day, unsigned yr)
{
x[1] = ByteToBcd(mon);
x[0] = ByteToBcd(day);
x[3] = ByteToBcd(yr / 100);
x[2] = ByteToBcd(yr % 100);
}
WORD ASMCFUNC FAR clk_driver(rqptr rp)
{
COUNT c;
const UWORD *pdays;
BYTE bcd_days[4], bcd_minutes, bcd_hours, bcd_seconds;
ULONG Ticks;
UWORD Month, Day, Year;
switch (rp->r_command)
{
@ -92,6 +68,8 @@ WORD ASMCFUNC FAR clk_driver(rqptr rp)
/* If AT clock exists, copy AT clock time to system clock */
if (!ReadATClock(bcd_days, &bcd_hours, &bcd_minutes, &bcd_seconds))
{
ticks_t seconds;
DaysSinceEpoch =
DaysFromYearMonthDay(100 * BcdToByte(bcd_days[3]) +
BcdToByte(bcd_days[2]),
@ -100,16 +78,16 @@ WORD ASMCFUNC FAR clk_driver(rqptr rp)
/*
* This is a rather tricky calculation. The number of timer ticks per
* second is not exactly 18.2, but rather 0x1800b0 / 86400 = 19663 / 1080
* (the timer interrupt updates the midnight flag when the tick count
* reaches 0x1800b0). Fortunately, 86400 * 19663 = 1698883200 < ULONG_MAX,
* so we can simply multiply the number of seconds by 19663 without
* worrying about overflow. :) -- ror4
* second is not exactly 18.2, but rather 1193180 / 65536
* where 1193180 = 0x1234dc
* The timer interrupt updates the midnight flag when the tick count
* reaches 0x1800b0 -- ror4.
*/
Ticks = (3600ul * BcdToByte(bcd_hours) +
60ul * BcdToByte(bcd_minutes) +
BcdToByte(bcd_seconds)) * 19663ul / 1080ul;
WritePCClock(Ticks);
seconds =
60 * (ticks_t)(60 * BcdToByte(bcd_hours) + BcdToByte(bcd_minutes)) +
BcdToByte(bcd_seconds);
WritePCClock(seconds * 0x12 + ((seconds * 0x34dc) >> 16));
}
/* rp->r_endaddr = device_end(); not needed - bart */
rp->r_nunits = 0;
@ -117,170 +95,86 @@ WORD ASMCFUNC FAR clk_driver(rqptr rp)
case C_INPUT:
{
ULONG remainder, hs;
ReadPCClock(&Ticks);
struct ClockRecord clk;
int tmp;
ticks_t ticks;
clk.clkDays = DaysSinceEpoch;
/*
* Another tricky calculation (after the one in `main.c'). This time
* we do have a problem with overflow, because we need to extract the
* 1/100s portion too. The scaling factor is now
* (100 x 86400) / 0x1800b0 = 108000 / 19663. -- ror4
*/
hs = 0;
#if 0
if (Ticks >= 64 * 19663ul)
{
hs += 64 * 108000ul;
Ticks -= 64 * 19663ul;
}
if (Ticks >= 32 * 19663ul)
{
hs += 32 * 108000ul;
Ticks -= 32 * 19663ul;
}
if (Ticks >= 16 * 19663ul)
{
hs += 16 * 108000ul;
Ticks -= 16 * 19663ul;
}
if (Ticks >= 8 * 19663ul)
{
hs += 8 * 108000ul;
Ticks -= 8 * 19663ul;
}
if (Ticks >= 4 * 19663ul)
{
hs += 4 * 108000ul;
Ticks -= 4 * 19663ul;
}
if (Ticks >= 2 * 19663ul)
{
hs += 2 * 108000ul;
Ticks -= 2 * 19663ul;
}
if (Ticks >= 19663ul)
{
hs += 108000ul;
Ticks -= 19663ul;
}
#else
{
UWORD q1 = Ticks / 19663ul;
/* The scaling factor is now
6553600/1193180 = 327680/59659 = 65536*5/59659 */
ticks = 5 * ReadPCClock();
ticks = ((ticks / 59659u) << 16) + ((ticks % 59659u) << 16) / 59659u;
tmp = (int)(ticks / 6000);
clk.clkHours = tmp / 60;
clk.clkMinutes = tmp % 60;
Ticks -= q1 * 19663ul;
hs = q1 * 108000ul;
}
#endif
/*
* Now Ticks < 19663, so Ticks * 108000 < 2123604000 < ULONG_MAX.
* *phew* -- ror4
*/
hs += Ticks * 108000ul / 19663ul;
clk.clkHours = hs / 360000ul;
remainder = hs % 360000ul;
clk.clkMinutes = remainder / 6000ul;
remainder %= 6000ul;
clk.clkSeconds = remainder / 100ul;
clk.clkHundredths = remainder % 100ul;
}
fmemcpy(rp->r_trans, &clk,
min(sizeof(struct ClockRecord), rp->r_count));
tmp = (int)(ticks % 6000);
clk.clkSeconds = tmp / 100;
clk.clkHundredths = tmp % 100;
fmemcpy(rp->r_trans, &clk,
min(sizeof(struct ClockRecord), rp->r_count));
}
return S_DONE;
case C_OUTPUT:
rp->r_count = min(rp->r_count, sizeof(struct ClockRecord));
fmemcpy(&clk, rp->r_trans, rp->r_count);
/* Set PC Clock first */
DaysSinceEpoch = clk.clkDays;
{
ULONG hs;
hs = 360000ul * clk.clkHours +
6000ul * clk.clkMinutes +
100ul * clk.clkSeconds + clk.clkHundredths;
Ticks = 0;
#if 0
if (hs >= 64 * 108000ul)
{
Ticks += 64 * 19663ul;
hs -= 64 * 108000ul;
}
if (hs >= 32 * 108000ul)
{
Ticks += 32 * 19663ul;
hs -= 32 * 108000ul;
}
if (hs >= 16 * 108000ul)
{
Ticks += 16 * 19663ul;
hs -= 16 * 108000ul;
}
if (hs >= 8 * 108000ul)
{
Ticks += 8 * 19663ul;
hs -= 8 * 108000ul;
}
if (hs >= 4 * 108000ul)
{
Ticks += 4 * 19663ul;
hs -= 4 * 108000ul;
}
if (hs >= 2 * 108000ul)
{
Ticks += 2 * 19663ul;
hs -= 2 * 108000ul;
}
if (hs >= 108000ul)
{
Ticks += 19663ul;
hs -= 108000ul;
}
#else
{
UWORD q1 = hs / 108000ul;
int c;
const unsigned short *pdays;
unsigned Month, Day, Year;
struct ClockRecord clk;
ticks_t hs, Ticks;
rp->r_count = min(rp->r_count, sizeof(struct ClockRecord));
fmemcpy(&clk, rp->r_trans, rp->r_count);
hs -= q1 * 108000ul;
Ticks = q1 * 19663ul;
/* Set PC Clock first */
DaysSinceEpoch = clk.clkDays;
hs = 6000 * (ticks_t)(60 * clk.clkHours + clk.clkMinutes) +
(ticks_t)(100 * clk.clkSeconds + clk.clkHundredths);
/* The scaling factor is now
1193180/6553600 = 59659/327680 = 59659/65536/5 */
Ticks = ((hs >> 16) * 59659u + (((hs & 0xffff) * 59659u) >> 16)) / 5;
WritePCClock(Ticks);
/* Now set AT clock */
/* Fix year by looping through each year, subtracting */
/* the appropriate number of days for that year. */
for (Year = 1980, c = clk.clkDays;;)
{
pdays = is_leap_year_monthdays(Year);
if (c >= pdays[12])
{
++Year;
c -= pdays[12];
}
else
break;
}
/* c contains the days left and count the number of */
/* days for that year. Use this to index the table. */
for (Month = 1; Month < 13; ++Month)
{
if (pdays[Month] > c)
{
Day = c - pdays[Month - 1] + 1;
break;
}
}
#endif
Ticks += hs * 19663ul / 108000ul;
DayToBcd(bcd_days, Month, Day, Year);
bcd_minutes = ByteToBcd(clk.clkMinutes);
bcd_hours = ByteToBcd(clk.clkHours);
bcd_seconds = ByteToBcd(clk.clkSeconds);
WriteATClock(bcd_days, bcd_hours, bcd_minutes, bcd_seconds);
}
WritePCClock(Ticks);
/* Now set AT clock */
/* Fix year by looping through each year, subtracting */
/* the appropriate number of days for that year. */
for (Year = 1980, c = clk.clkDays;;)
{
pdays = is_leap_year_monthdays(Year);
if (c >= pdays[12])
{
++Year;
c -= pdays[12];
}
else
break;
}
/* c contains the days left and count the number of */
/* days for that year. Use this to index the table. */
for (Month = 1; Month < 13; ++Month)
{
if (pdays[Month] > c)
{
Day = c - pdays[Month - 1] + 1;
break;
}
}
DayToBcd((BYTE *) bcd_days, &Month, &Day, &Year);
bcd_minutes = ByteToBcd(clk.clkMinutes);
bcd_hours = ByteToBcd(clk.clkHours);
bcd_seconds = ByteToBcd(clk.clkSeconds);
WriteATClock(bcd_days, bcd_hours, bcd_minutes, bcd_seconds);
return S_DONE;
case C_OFLUSH:
@ -296,19 +190,6 @@ WORD ASMCFUNC FAR clk_driver(rqptr rp)
}
}
COUNT ByteToBcd(COUNT x)
{
return ((x / 10) << 4) | (x % 10);
}
VOID DayToBcd(BYTE * x, UWORD * mon, UWORD * day, UWORD * yr)
{
x[1] = ByteToBcd(*mon);
x[0] = ByteToBcd(*day);
x[3] = ByteToBcd(*yr / 100);
x[2] = ByteToBcd(*yr % 100);
}
/*
* Log: sysclk.c,v - for newer entries do "cvs log sysclk.c"
*

View File

@ -36,90 +36,89 @@ static BYTE *syspackRcsId =
#endif
#ifdef NONNATIVE
VOID getlong(REG VOID * vp, LONG * lp)
UDWORD getlong(REG VOID * vp)
{
*lp = (((BYTE *) vp)[0] & 0xff) +
((((BYTE *) vp)[1] & 0xff) << 8) +
((((BYTE *) vp)[2] & 0xff) << 16) +
((((BYTE *) vp)[3] & 0xff) << 24);
return (((UBYTE *) vp)[0] & 0xff) +
((((UBYTE *) vp)[1] & 0xff) << 8) +
((((UBYTE *) vp)[2] & 0xff) << 16) +
((((UBYTE *) vp)[3] & 0xff) << 24);
}
VOID getword(REG VOID * vp, WORD * wp)
UWORD getword(REG VOID * vp)
{
*wp = (((BYTE *) vp)[0] & 0xff) + ((((BYTE *) vp)[1] & 0xff) << 8);
return (((UBYTE *) vp)[0] & 0xff) + ((((UBYTE *) vp)[1] & 0xff) << 8);
}
VOID getbyte(VOID * vp, BYTE * bp)
UBYTE getbyte(VOID * vp)
{
*bp = *((BYTE *) vp);
return *((BYTE *) vp);
}
VOID fgetword(REG VOID FAR * vp, WORD FAR * wp)
UWORD fgetword(REG VOID FAR * vp)
{
*wp =
(((BYTE FAR *) vp)[0] & 0xff) + ((((BYTE FAR *) vp)[1] & 0xff) << 8);
return (((UBYTE FAR *) vp)[0] & 0xff) + ((((UBYTE FAR *) vp)[1] & 0xff) << 8);
}
VOID fgetlong(REG VOID FAR * vp, LONG FAR * lp)
UDWORD fgetlong(REG VOID FAR * vp)
{
*lp = (((BYTE *) vp)[0] & 0xff) +
((((BYTE *) vp)[1] & 0xff) << 8) +
((((BYTE *) vp)[2] & 0xff) << 16) +
((((BYTE *) vp)[3] & 0xff) << 24);
return (((UBYTE *) vp)[0] & 0xff) +
((((UBYTE *) vp)[1] & 0xff) << 8) +
((((UBYTE *) vp)[2] & 0xff) << 16) +
((((UBYTE *) vp)[3] & 0xff) << 24);
}
VOID fgetbyte(VOID FAR * vp, BYTE FAR * bp)
UBYTE fgetbyte(VOID FAR * vp)
{
*bp = *((BYTE FAR *) vp);
return *((UBYTE FAR *) vp);
}
VOID fputlong(LONG FAR * lp, VOID FAR * vp)
VOID fputlong(VOID FAR * vp, UDWORD l)
{
REG BYTE FAR *bp = (BYTE FAR *) vp;
REG UBYTE FAR *bp = (UBYTE FAR *) vp;
bp[0] = *lp & 0xff;
bp[1] = (*lp >> 8) & 0xff;
bp[2] = (*lp >> 16) & 0xff;
bp[3] = (*lp >> 24) & 0xff;
bp[0] = l & 0xff;
bp[1] = (l >> 8) & 0xff;
bp[2] = (l >> 16) & 0xff;
bp[3] = (l >> 24) & 0xff;
}
VOID fputword(WORD FAR * wp, VOID FAR * vp)
VOID fputword(VOID FAR * vp, UWORD w)
{
REG BYTE FAR *bp = (BYTE FAR *) vp;
REG UBYTE FAR *bp = (UBYTE FAR *) vp;
bp[0] = *wp & 0xff;
bp[1] = (*wp >> 8) & 0xff;
bp[0] = w & 0xff;
bp[1] = (w >> 8) & 0xff;
}
VOID fputbyte(BYTE FAR * bp, VOID FAR * vp)
VOID fputbyte(VOID FAR * vp, UBYTE b)
{
*(BYTE FAR *) vp = *bp;
*(UBYTE FAR *) vp = b;
}
VOID getdirent(BYTE FAR * vp, struct dirent FAR * dp)
VOID getdirent(UBYTE FAR * vp, struct dirent FAR * dp)
{
fmemcpy(dp->dir_name, &vp[DIR_NAME], FNAME_SIZE);
fmemcpy(dp->dir_ext, &vp[DIR_EXT], FEXT_SIZE);
fgetbyte(&vp[DIR_ATTRIB], (BYTE FAR *) & dp->dir_attrib);
fgetword(&vp[DIR_TIME], (WORD FAR *) & dp->dir_time);
fgetword(&vp[DIR_DATE], (WORD FAR *) & dp->dir_date);
fgetword(&vp[DIR_START], (WORD FAR *) & dp->dir_start);
fgetlong(&vp[DIR_SIZE], (LONG FAR *) & dp->dir_size);
dp->dir_attrib = fgetbyte(&vp[DIR_ATTRIB]);
dp->dir_time = fgetword(&vp[DIR_TIME]);
dp->dir_date = fgetword(&vp[DIR_DATE]);
dp->dir_start = fgetword(&vp[DIR_START]);
dp->dir_size = fgetlong(&vp[DIR_SIZE]);
}
VOID putdirent(struct dirent FAR * dp, BYTE FAR * vp)
VOID putdirent(struct dirent FAR * dp, UBYTE FAR * vp)
{
REG COUNT i;
REG BYTE FAR *p;
fmemcpy(&vp[DIR_NAME], dp->dir_name, FNAME_SIZE);
fmemcpy(&vp[DIR_EXT], dp->dir_ext, FEXT_SIZE);
fputbyte((BYTE FAR *) & dp->dir_attrib, &vp[DIR_ATTRIB]);
fputword((WORD FAR *) & dp->dir_time, &vp[DIR_TIME]);
fputword((WORD FAR *) & dp->dir_date, &vp[DIR_DATE]);
fputword((WORD FAR *) & dp->dir_start, &vp[DIR_START]);
fputlong((LONG FAR *) & dp->dir_size, &vp[DIR_SIZE]);
for (i = 0, p = (BYTE FAR *) & vp[DIR_RESERVED]; i < 10; i++)
fputbyte(&vp[DIR_ATTRIB], dp->dir_attrib);
fputword(&vp[DIR_TIME], dp->dir_time);
fputword(&vp[DIR_DATE], dp->dir_date);
fputword(&vp[DIR_START], dp->dir_start);
fputlong(&vp[DIR_SIZE], dp->dir_size);
for (i = 0, p = (UBYTE FAR *) & vp[DIR_RESERVED]; i < 10; i++)
*p++ = NULL;
}
#endif

View File

@ -98,19 +98,14 @@ VOID DosGetTime(BYTE FAR * hp, BYTE FAR * mp, BYTE FAR * sp,
COUNT DosSetTime(BYTE h, BYTE m, BYTE s, BYTE hd)
{
BYTE Month, DayOfMonth, DayOfWeek;
COUNT Year;
DosGetDate((BYTE FAR *) & DayOfWeek, (BYTE FAR *) & Month,
(BYTE FAR *) & DayOfMonth, (COUNT FAR *) & Year);
/* for ClkRecord.clkDays */
ExecuteClockDriverRequest(C_INPUT);
ClkRecord.clkHours = h;
ClkRecord.clkMinutes = m;
ClkRecord.clkSeconds = s;
ClkRecord.clkHundredths = hd;
ClkRecord.clkDays = DaysFromYearMonthDay(Year, Month, DayOfMonth);
ExecuteClockDriverRequest(C_OUTPUT);
if (ClkReqHdr.r_status & S_ERROR)
@ -172,10 +167,7 @@ UWORD Month, DayOfMonth, Year;
|| DayOfMonth < 1 || DayOfMonth > pdays[Month] - pdays[Month - 1])
return DE_INVLDDATA;
DosGetTime((BYTE FAR *) & ClkRecord.clkHours,
(BYTE FAR *) & ClkRecord.clkMinutes,
(BYTE FAR *) & ClkRecord.clkSeconds,
(BYTE FAR *) & ClkRecord.clkHundredths);
ExecuteClockDriverRequest(C_INPUT);
ClkRecord.clkDays = DaysFromYearMonthDay(Year, Month, DayOfMonth);

View File

@ -241,8 +241,10 @@ VOID new_psp(psp FAR * p, int psize)
/* first command line argument */
p->ps_fcb1.fcb_drive = 0;
fmemset(p->ps_fcb1.fcb_fname, ' ', FNAME_SIZE + FEXT_SIZE);
/* second command line argument */
p->ps_fcb2.fcb_drive = 0;
fmemset(p->ps_fcb2.fcb_fname, ' ', FNAME_SIZE + FEXT_SIZE);
/* local command line */
p->ps_cmd_count = 0; /* command tail */
@ -265,8 +267,11 @@ STATIC UWORD patchPSP(UWORD pspseg, UWORD envseg, exec_blk FAR * exb,
/* complete the psp by adding the command line and FCBs */
fmemcpy(psp->ps_cmd, exb->exec.cmd_line->ctBuffer, 127);
fmemcpy(&psp->ps_fcb1, exb->exec.fcb_1, 16);
fmemcpy(&psp->ps_fcb2, exb->exec.fcb_2, 16);
if (FP_OFF(exb->exec.fcb_1) != 0xffff)
{
fmemcpy(&psp->ps_fcb1, exb->exec.fcb_1, 16);
fmemcpy(&psp->ps_fcb2, exb->exec.fcb_2, 16);
}
psp->ps_cmd_count = exb->exec.cmd_line->ctCount;
/* identify the mcb as this functions' */

View File

@ -4,8 +4,7 @@
# Use these for WATCOM 11.0c
COMPILERPATH=$(WATCOM)
COMPILERBIN=$(WATCOM)\binw
CC=$(COMPILERBIN)\wcl
CC=wcl
INCLUDEPATH=$(COMPILERPATH)\H
INCLUDE=$(COMPILERPATH)\h
EDPATH=$(COMPILERPATH)\EDDAT
@ -17,12 +16,12 @@ TARGETOPT=-0
!endif
LIBPATH=$(COMPILERPATH)\lib286
LIBUTIL=$(COMPILERBIN)\wlib
LIBUTIL=wlib
LIBPLUS=
LIBTERM=
CFLAGST=-zp=1 -mt -os -s -we -e=3 -w=2
CFLAGSC=-zp=1 -mc -os -s -we -e=3 -w=2
CFLAGST=-zp=1 -mt -os -s -we -e=3 -wx
CFLAGSC=-zp=1 -mc -os -s -we -e=3 -wx
TARGET=KWC
@ -60,7 +59,7 @@ MATH_INSERT= +i4d +i4m
# -3 optimization for 386 - given in CONFIG.MAK, not here
#
ALLCFLAGS=-I..\hdr $(TARGETOPT) $(ALLCFLAGS) -zq -os -s -e=5 -j -zl -zp=1 -we
ALLCFLAGS=-I..\hdr $(TARGETOPT) $(ALLCFLAGS) -zq -os -s -e=5 -j -zl -zp=1 -wx -we
INITCFLAGS=$(ALLCFLAGS) -nt=INIT_TEXT -nc=INIT -nd=I -g=I_GROUP
CFLAGS=$(ALLCFLAGS) -nt=HMA_TEXT -nc=HMA -g=HGROUP
INITPATCH=..\utils\patchobj __U4D=_IU4D __U4M=_IU4M

View File

@ -28,6 +28,7 @@ extern int CDECL printf(CONST BYTE * fmt, ...);
extern int CDECL sprintf(BYTE * buff, CONST BYTE * fmt, ...);
#ifdef __WATCOMC__
unsigned _dos_close(int handle);
#define close _dos_close
#define SEEK_SET 0
int open(const char *pathname, int flags, ...);

View File

@ -66,6 +66,7 @@ extern WORD CDECL sprintf(BYTE * buff, CONST BYTE * fmt, ...);
#ifndef __WATCOMC__
#include <io.h>
#else
int unlink(const char *pathname);
/* some non-conforming functions to make the executable smaller */
int open(const char *pathname, int flags, ...)
{
@ -819,7 +820,7 @@ BOOL copy(COUNT drive, BYTE * srcPath, BYTE * rootPath, BYTE * file)
return TRUE;
}
/* Log: sys.c,v see "cvs log sys.c" for newer entries.
/* Log: sys.c,v see "cvs log sys.c" for newer entries. */
/* version 2.2 jeremyd 2001/9/20
Changed so if no source given or only source drive (no path)

View File

@ -13,6 +13,7 @@
*****************************************************************************/
#include <stdio.h>
#include <io.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>