X-Authentication-Warning: delorie.com: mailnull set sender to djgpp-bounces using -f Message-ID: <271DBBEEA095D511B80D009027DE7D670DD136@mcoexc01.mlm.maxtor.com> From: "Dykstra, Sean" To: "'djgpp AT delorie DOT com'" Subject: RE: Critical Error Interrupt Help - fixed! Date: Wed, 5 Dec 2001 08:39:31 -0700 MIME-Version: 1.0 X-Mailer: Internet Mail Service (5.5.2653.19) Content-Type: text/plain; charset="iso-8859-1" Reply-To: djgpp AT delorie DOT com 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