www.delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/2001/12/05/10:44:19

X-Authentication-Warning: delorie.com: mailnull set sender to djgpp-bounces using -f
Message-ID: <271DBBEEA095D511B80D009027DE7D670DD136@mcoexc01.mlm.maxtor.com>
From: "Dykstra, Sean" <Sean_Dykstra AT maxtor DOT com>
To: "'djgpp AT delorie DOT com'" <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)
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

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019