initial BIOS disk int 13h wrapper, only passively detects and notes floppy disk change

git-svn-id: https://svn.code.sf.net/p/freedos/svn/kernel/branches/UNSTABLE@1154 6ac86273-5f31-0410-b378-82cca8765d1b
This commit is contained in:
Kenneth J Davis 2005-11-20 16:52:45 +00:00
parent 9c7fd183f4
commit b4d8701d5c
4 changed files with 199 additions and 18 deletions

View File

@ -56,6 +56,8 @@ FarTabRetn:
Int2f3:
cmp ah,12h
je IntDosCal ; Dos Internal calls
cmp ah,13h
je IntDosCal ; Install Int13h Hook
cmp ah,16h
je IntDosCal ; Win (Multitasking) Hook
cmp ah,46h

View File

@ -41,7 +41,7 @@ BYTE *RcsId =
#ifdef TSC
STATIC VOID StartTrace(VOID);
static bTraceNext = FALSE;
STATIC bTraceNext = FALSE;
#endif
#if 0 /* Very suspicious, passing structure by value??
@ -1703,6 +1703,9 @@ struct int2f12regs {
xreg callerARG1; /* used if called from INT2F/12 */
};
extern intvec BIOSInt13, UserInt13, BIOSInt19;
/* WARNING: modifications in `r' are used outside of int2F_12_handler()
* On input r.AX==0x12xx, 0x4A01 or 0x4A02
* also handle Windows' DOS notification hooks, r.AH==0x16
@ -1733,6 +1736,17 @@ VOID ASMCFUNC int2F_12_handler(struct int2f12regs r)
r.BX = size;
return;
}
else if (r.AH == 0x13) /* set disk interrupt (13h) handler */
{
/* set new values for int13h calls, and must return old values */
register intvec tmp = UserInt13;
UserInt13 = MK_FP(r.ds, r.DX); /* int13h handler to use */
r.ds = FP_SEG(tmp); r.DX = FP_OFF(tmp);
tmp = BIOSInt13;
BIOSInt13 = MK_FP(r.es, r.BX); /* int13h handler to restore on reboot */
r.es = FP_SEG(tmp); r.BX = FP_OFF(tmp);
return;
}
else if (r.AH == 0x16) /* Window/Multitasking hooks */
{
#ifdef WIN31SUPPORT /* See "DOS Internals" or RBIL under DOSMGR for details */
@ -1915,9 +1929,8 @@ VOID ASMCFUNC int2F_12_handler(struct int2f12regs r)
case 0x80: /* Win Release Time-slice */
{
/* This function is generally only called in idle loops */
enable; /* enable interrupts */
// __emit__(0xf4); /* halt */
asm hlt;
__emit__(0xfb); /* sti; enable interrupts */
__emit__(0xf4); /* hlt; halt until interrupt */
r.AX = 0;
/* DebugPrintf(("Release Time Slice\n")); */
break;
@ -2259,6 +2272,91 @@ error_exit:
r.FLAGS |= FLG_CARRY;
}
/* how registers pushed on stack prior to calling int wrapper function,
when returns these are then popped off, so any changes to these
will effectively set the returned value in these registers
*/
struct intXXregs {
#ifdef I386
/* preserved 386+ only registers, compiler specific */
#endif
UWORD es, ds;
UWORD di, si, bp;
xreg b, d, c, a;
UWORD intreq; /* which interrupt filter request for */
UWORD flags; /* flags duplicated, one pushed by int call ignored */
xreg param;
UWORD ip, cs , oflags;
/* top item of int caller's stack, possibly additional params */
};
/* additional processing for various wrapped/filtered interrupts
WARNING: this function also called during kernel init phase
-- int 13h
filter for BIOS int13h support, only called on int13h error
for ms-dos compatibility this should at minimal
watch for disk-change notification and set internal status
(may be called multiple times in row when BIOS reports same
change multiple times, ie delays clearing disk change status)
TODO: move DMA bounday check from int25/26 to here
Note: use stored user (usually BIOS) hooked int13 handler
-- int 19h
clean up prior to a warm reboot
for ms compatibility this should at a minimal
restore original (or indicated as original) BIOS int13h handler
and any others that may be hooked (including this one)
if himem loaded clear high memory area (clear vdisk signature so himem loads)
*/
VOID ASMCFUNC intXX_filter(struct intXXregs r)
{
DebugPrintf(("int %02xh filter\n", r.intreq));
switch(r.intreq)
{
case 0x19: /* reboot via bootstrap */
{
setvec(0x13, BIOSInt13);
setvec(0x19, BIOSInt19);
/* clear vdisk signature if kernel loaded in hma */
if (version_flags & 0x10)
fmemset(MK_FP(0xffff, 0x0010),0,512);
break;
}
case 0x13: /* error with disk handler */
{
DebugPrintf(("disk error %i [ah=%x] (drive %x)\n", r.a.b.h, r.param.b.h, r.param.b.l));
DebugPrintf(("bx==(%x) cx==(%x) dx==(%x)\n", r.BX, r.CX, r.DX));
/* currently just marks floppy as changed on disk change error */
if ((r.a.b.h == 0x06) && (r.param.b.l < 0x80)) /* diskchange and is it a floppy? */
{
register int i;
/* mark floppy as changed */
for(i=0; i < blk_dev.dh_name[0]; i++)
{
ddt *pddt = getddt(i);
if (pddt->ddt_driveno == r.param.b.l)
{
DebugPrintf(("ddt[%i] match, flags=%04x\n", i, pddt->ddt_descflags));
if ((pddt->ddt_descflags & DF_CHANGELINE) && /* drive must have changeline support */
(pddt->ddt_descflags & DF_CURBPBLOCK)) /* and BPB not currently locked (in-use) */
pddt->ddt_descflags |= DF_DISKCHANGE;
/* or get dpb pointer from ddt and set dpbp->dpb_flags = M_CHANGED; */
}
}
}
break;
}
default:
DebugPrintf(("INT_ERROR!\n"));
break;
}
}
/*
* 2000/09/04 Brian Reifsnyder
* Modified interrupts 0x25 & 0x26 to return more accurate error codes.

View File

@ -652,6 +652,22 @@ _ext_open_action dw 0 ;2DD - extended open action
_ext_open_attrib dw 0 ;2DF - extended open attrib
_ext_open_mode dw 0 ;2E1 - extended open mode
; these 3 placed here so init code and int wrapper can easily access
; holds pointers to actual disk handler routines and interrupt
; vectors that we try to restore before a warm reboot
global _SAVEDIVLST
_SAVEDIVLST:
; used by int13 handler and get/set via int 2f/13h
global _BIOSInt13
global _UserInt13
_BIOSInt13 dd 0 ; used to restore int13 on reboot (see int19 wrapper)
_UserInt13 dd 0 ; actual disk handler used by kernel
global _BIOSInt19
_BIOSInt19 dd 0 ; original int19
; Pad to 0620h
times (300h - ($ - _internal_data)) db 0
global _szNames
@ -846,6 +862,18 @@ initforceEnableA20:
global __HMARelocationTableStart
__HMARelocationTableStart:
global _int13_handler
extern reloc_call_int13_handler
_int13_handler: jmp 0:reloc_call_int13_handler
call near forceEnableA20
#if 0
global _int19_handler
extern reloc_call_int19_handler
_int19_handler: jmp 0:reloc_call_int19_handler
call near forceEnableA20
#endif
global _int2f_handler
extern reloc_call_int2f_handler
_int2f_handler: jmp 0:reloc_call_int2f_handler

View File

@ -30,6 +30,7 @@
#include "portab.h"
#include "init-mod.h"
#include "dyndata.h"
#include "debug.h"
#ifdef VERSION_STRINGS
static BYTE *mainRcsId =
@ -48,6 +49,7 @@ STATIC VOID init_internal_devices(void);
STATIC VOID update_dcb(struct dhdr FAR *);
STATIC VOID init_kernel(VOID);
STATIC VOID do_fixup(VOID);
STATIC VOID signon(VOID);
STATIC VOID init_shell(VOID);
STATIC VOID FsConfig(VOID);
@ -55,6 +57,11 @@ STATIC VOID InitPrinters(VOID);
STATIC VOID InitSerialPorts(VOID);
STATIC void CheckContinueBootFromHarddisk(void);
STATIC void setup_int_vectors(void);
#define setup_fastprint_hook() setvec(0x29, int29_handler) /* required for printf! */
void setvec(unsigned char intno, intvec vector);
#ifdef _MSC_VER
BYTE _acrtused = 0;
@ -67,6 +74,7 @@ __segment DosTextSeg = 0;
#endif
struct lol FAR * const LoL = &DATASTART;
intvec FAR * const savedIVs = &SAVEDIVLST;
void ASMCFUNC FreeDOSmain(void)
{
@ -120,14 +128,25 @@ void ASMCFUNC FreeDOSmain(void)
fmemcpy(&InitKernelConfig, p, sizeof InitKernelConfig);
}
setup_int_vectors();
/* printfs won't work until int29, fast console output hook is installed */
setup_fastprint_hook();
/* check if booting from CD before we hook too many interrupts */
CheckContinueBootFromHarddisk();
/* display copyright info and kernel emulation status */
signon();
init_kernel();
init_shell();
/* finish initial HMA segment relocation (move up until DOS=HIGH known) */
do_fixup();
/* install DOS API and other interrupt service routines, basic kernel functionality works */
setup_int_vectors();
/* initialize all internal variables, process CONFIG.SYS, load drivers, etc */
init_kernel();
init_shell();
init_call_p_0(&Config); /* execute process 0 (the shell) */
}
@ -195,6 +214,30 @@ void setvec(unsigned char intno, intvec vector)
}
#endif
/* ensures int vectors we may need to restore are saved */
STATIC VOID save_int_vectors(VOID)
{
/* we create far pointers otherwise compiler sets value
in initial data segment (IDATA) which does us no good.
*/
extern intvec BIOSInt13, UserInt13, BIOSInt19; /* in kernel.asm */
intvec FAR *pBIOSInt13, FAR *pUserInt13, FAR *pBIOSInt19;
pBIOSInt13 = MK_FP(FP_SEG(savedIVs), FP_OFF(savedIVs));
pUserInt13 = pBIOSInt13 + 1;
pBIOSInt19 = pBIOSInt13 + 2;
/* store for later use by our replacement int13handler */
*pBIOSInt13 = getvec(0x13); /* save original BIOS int 0x13 handler */
*pUserInt13 = *pBIOSInt13; /* default to it for user int 0x13 handler */
*pBIOSInt19 = getvec(0x19); /* save reboot handler so we can clean up a little */
DDebugPrintf(("\n")); /* force anything printed to start on next line after BS */
DDebugPrintf(("BIOSInt13(at %p) is %p\n", pBIOSInt13, *pBIOSInt13));
DDebugPrintf(("BIOSInt19(at %p) is %p\n", pBIOSInt19, *pBIOSInt19));
}
STATIC void setup_int_vectors(void)
{
static struct vec
@ -208,20 +251,27 @@ STATIC void setup_int_vectors(void)
{ 0x1, FP_OFF(empty_handler) }, /* single step */
{ 0x3, FP_OFF(empty_handler) }, /* debug breakpoint */
{ 0x6, FP_OFF(int6_handler) }, /* invalid opcode */
{ 0x13, FP_OFF(int13_handler) }, /* BIOS disk filter */
#if 0
{ 0x19, FP_OFF(int19_handler) }, /* BIOS bootstrap loader, vdisk */
#endif
{ 0x20, FP_OFF(int20_handler) },
{ 0x21, FP_OFF(int21_handler) },
{ 0x21, FP_OFF(int21_handler) }, /* primary DOS API */
{ 0x22, FP_OFF(int22_handler) },
{ 0x24, FP_OFF(int24_handler) },
{ 0x25, FP_OFF(low_int25_handler) },
{ 0x25, FP_OFF(low_int25_handler) }, /* DOS abs read/write calls */
{ 0x26, FP_OFF(low_int26_handler) },
{ 0x27, FP_OFF(int27_handler) },
{ 0x28, FP_OFF(int28_handler) },
{ 0x2a, FP_OFF(int2a_handler) },
{ 0x2f, FP_OFF(int2f_handler) }
{ 0x2f, FP_OFF(int2f_handler) } /* multiplex int */
};
struct vec *pvec;
int i;
save_int_vectors();
/* install default handlers */
for (i = 0x23; i <= 0x3f; i++)
setvec(i, empty_handler);
for (pvec = vectors; pvec < ENDOF(vectors); pvec++)
@ -229,7 +279,7 @@ STATIC void setup_int_vectors(void)
pokeb(0, 0x30 * 4, 0xea);
pokel(0, 0x30 * 4 + 1, (ULONG)cpm_entry);
/* these two are in the device driver area LOWTEXT (0x70) */
/* handlers for int 0x1b and 0x29 are in the device driver area LOWTEXT (0x70) */
setvec(0x1b, got_cbreak);
setvec(0x29, int29_handler); /* required for printf! */
}
@ -251,14 +301,8 @@ STATIC void printIRQvectors(void)
}
#endif
STATIC void init_kernel(void)
STATIC void do_fixup(void)
{
COUNT i;
LoL->os_setver_major = LoL->os_major = MAJOR_RELEASE;
LoL->os_setver_minor = LoL->os_minor = MINOR_RELEASE;
LoL->rev_number = REVISION_SEQ;
/* move kernel to high conventional RAM, just below the init code */
/* Note: kernel.asm actually moves and jumps here, but MoveKernel
must still be called to do the necessary segment fixups */
@ -275,6 +319,15 @@ STATIC void init_kernel(void)
chunk allocated, lpTop. I.e. lpTop is top of free conv memory
*/
lpTop = MK_FP(FP_SEG(lpTop) - 0xfff, 0xfff0);
}
STATIC void init_kernel(void)
{
COUNT i;
LoL->os_setver_major = LoL->os_major = MAJOR_RELEASE;
LoL->os_setver_minor = LoL->os_minor = MINOR_RELEASE;
LoL->rev_number = REVISION_SEQ;
/* Initialize IO subsystem */
init_internal_devices();