mirror of https://github.com/FDOS/kernel.git
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:
parent
9c7fd183f4
commit
b4d8701d5c
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in New Issue