Mail Archives: djgpp/2001/12/05/10:44:19
Well, I got the critical interrupt working when the program is working under
both DOS and Windows. It's not particularly pretty, but it works... I
detect whether we are running Windows or not (iRunningWindows), and change
the behavoir based on that change. If I am running Windows, I use getch, if
not I use port 0x60 to read the keyboard scan codes (I didn't want to use
this method under Windows because it kills system performance when the
critical error occurs). Maybe this will help someone out in the future.
Here is the code:
#define IRQ24 0x24
#define AKEY 30
#define RKEY 19
#define FKEY 33
#define IKEY 23
//======================================
// Structures and type definitions
//======================================
//======================================
// Static and external variables
//======================================
// Singleton data
SysInts *SysInts::pclInstance = 0; //
instance pointer
int SysInts::iInstanceCount = 0; //
instantiation counter
MsgWinClass *SysInts::pclMsgWin = 0;
__dpmi_regs SysInts::rm_regs;
int SysInts::iRunningWindows = 0;
//XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
//XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
// Interrupt handlers
//XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
//XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
void SysInts::rm_new24h (__dpmi_regs *r)
{
InputHandler *pclInput;
int iError;
char ch=0;
int _al = r->h.al;
iError = r->x.di;
pclInput = InputHandler::pclInstantiate();
// pclMsgWin->iPrintf (M_WINDOW,"Error: di:%04X ax:%04X bx:%04X cx:%04X
dx:%04X",r->x.di,r->x.ax, r->x.bx, r->x.cx, r->x.dx);
pclMsgWin->iPrintf (M_WINDOW,"Error: ");
switch (iError)
{
case WRITEPROTECT:
pclMsgWin->iPrintf (M_WINDOW,"Write Protect Failure");
break;
case UNKNOWNUNIT:
pclMsgWin->iPrintf (M_WINDOW,"Unknown Unit");
break;
case DRIVENOTREADY:
pclMsgWin->iPrintf (M_WINDOW,"Drive Not Ready");
break;
case UNKNOWNCOMMAND:
pclMsgWin->iPrintf (M_WINDOW,"Unknown Command");
break;
case CRCERROR:
pclMsgWin->iPrintf (M_WINDOW,"CRC Data Error");
break;
case BADREQUEST:
pclMsgWin->iPrintf (M_WINDOW,"Bad Request Structure Length");
break;
case SEEKERROR:
pclMsgWin->iPrintf (M_WINDOW,"Seek Error");
break;
case UNKNOWNMEDIA:
pclMsgWin->iPrintf (M_WINDOW,"Unknown Media");
break;
case SECTORNOTFOUND:
pclMsgWin->iPrintf (M_WINDOW,"Sector Not Found");
break;
case OUTOFPAPER:
pclMsgWin->iPrintf (M_WINDOW,"Out of Paper");
break;
case WRITEFAULT:
pclMsgWin->iPrintf (M_WINDOW,"Write Fault");
break;
case READFAULT:
pclMsgWin->iPrintf (M_WINDOW,"Read Fault");
break;
case GENERALFAILURE:
pclMsgWin->iPrintf (M_WINDOW,"General Failure");
break;
case INVALIDCHANGE:
pclMsgWin->iPrintf (M_WINDOW,"Invalid Media Change");
break;
}
pclMsgWin->iPrintf (M_WINDOW,"\nAbort, Retry, Ignore, Fail ?");
//If we are running windows, we can use the getch() method,
if (iRunningWindows)
{
while (0==ch)
{
ch=pclInput->uGetKey ();
ch|=0x20;
if ( (ch!='a') && (ch!='r') && (ch!='f') && (ch!='i') )
{
ch=0;
}
}
switch (ch)
{
case 'a':
pclMsgWin->iPrintf (M_WINDOW,"a");
_al |= CRITFAIL;
break;
case 'r':
pclMsgWin->iPrintf (M_WINDOW,"r");
_al |= CRITRETRY;
break;
case 'f':
pclMsgWin->iPrintf (M_WINDOW,"f");
_al |= CRITFAIL;
break;
case 'i':
pclMsgWin->iPrintf (M_WINDOW,"i");
_al |= CRITIGNORE;
break;
}
}
//Othewise we need to use the inport method
else
{
while (0==ch)
{
unsigned char control_kbd;
ch = inportb (0x60);
control_kbd = inportb (0x61);
outportb (0x61, control_kbd | 0x80);
outportb (0x61, control_kbd);
outportb (0x20, inportb (0x20));
if ( (ch!=AKEY) && (ch!=RKEY) && (ch!=IKEY) && (ch!=FKEY) )
{
ch=0;
}
}
switch (ch)
{
case AKEY: //'a'
pclMsgWin->iPrintf (M_WINDOW,"a");
_al |= CRITFAIL;
break;
case RKEY: //'r'
pclMsgWin->iPrintf (M_WINDOW,"r");
_al |= CRITRETRY;
break;
case FKEY: //'f'
pclMsgWin->iPrintf (M_WINDOW,"f");
_al |= CRITFAIL;
break;
case IKEY: //'i'
pclMsgWin->iPrintf (M_WINDOW,"i");
_al |= CRITIGNORE;
break;
}
}
pclMsgWin->iPrintf (M_WINDOW,"\n");
r->h.al=_al;
}
SysInts::SysInts()
{
disable ();
char *windir_var; // Variable for environmental variables.
iRunningWindows=FALSE;
pclMsgWin = MsgWinClass::pclInstantiate();
//The reason we check for the CAPITAL version, is in case the case of the
WINDIR
//variable has been changed.
windir_var = getenv( "WINDIR" );
if( NULL==windir_var )
{
windir_var = getenv( "windir" );
//if( windir_var != NULL )
//sBIOSLOCK += WINDOWS;
}
if( windir_var != NULL )
{
iRunningWindows = TRUE;
}
// Prepare for the call to allocate_real_mode_callback_iret
rm_new_handler.pm_offset = (unsigned long)&rm_new24h;
rm_new_handler.pm_selector = _my_cs();
// Allocate a real mode callback
_go32_dpmi_allocate_real_mode_callback_iret(&rm_new_handler, &rm_regs);
// Set the vectors appropriately
_go32_dpmi_get_real_mode_interrupt_vector (IRQ24, &rm_old_handler);
_go32_dpmi_set_real_mode_interrupt_vector (IRQ24, &rm_new_handler);
enable ();
} // end of Protected constructor
SysInts::~SysInts()
{
disable ();
pclMsgWin->vRelease ();
_go32_dpmi_set_real_mode_interrupt_vector (IRQ24, &rm_old_handler);
enable ();
} // end of Protected destructor
- Raw text -