************************************************************************
* Jouni Miettunen * jon@stekt.oulu.fi * Oulu * Finland * Europe * 1995 *

		Intermediate Programmer Tutorial #001
		Copyright (c) 1995 by Jouni Miettunen
		      Version 1 - 20 March 1995

		Critical Error (0x24) Handler

** INTRODUCTION

There are two kind of interrupts in DOS: hardware interrupts generated
by hardware devices, such as a printer or a disk drive, and software
interrupts generated by system software and/or user applications. When
an interrupt occurs, the execution of the user application is halted for
a moment, the program environment stored and the interrupt served.

There is a thing called "interrupt vector table" that has pointers to
all the Interrupt Service Routines (ISR). When an interrupt occurs, an
ISR to handle it will be located in the interrupt vector table based on
the number of the interrupt and system execution will continue with it.
Hopefully the provided ISR will take care of the problem with grace and
afterwards the user application execution can be continued where it was
halted. Unfortunately this is not always the case.

Hardware interrupts usually signal a fatal error with the operation of
peripheral devices and can cause the user program to crash, sometimes
bringing down even the whole system. The most usual occurance of such an
error is the dreaded message

	Not ready reading drive A
	Abort, Retry, Fail?_

The purpose of this tutorial is to demonstrate how you can replace the
default critical error (0x24) handler in the interrupt vector table and
take care of the problem yourself. There is nothing worse than a program
suddenly asking "Abort, Retry, Fail?", especially if it has a Graphical
User Interface (GUI).

** FUNCTION PROTOTYPES

The used functions were provided by Borland C/C++ compiler, but are
supported by other DOS C/C++ compilers, too. With Microsoft C and QuickC
please use _harderr, _hardresume and _hardretn function names. These
functions are unique to DOS and cannot be ported to other systems.

#include <dos.h>

void harderr	( int (*handler)(int error, int ax, int bp, int si)	);
void hardresure	( int command						);
void hardretn	( int error						);

Please remember that BIOS and DOS are mostly not reentrant. Within your
ISR routines you better not call any functions using DOS BIOS calls eg.
beware printf(). BIOS calls 0x01 to 0x0C and 0x59 should be safe to use.

** HARDERR()

This function sets up as the new hardware interrupt 0x24 service routine
your own function pointed by the function pointer *handler. It will be
called whenever a hardware error occurs, which usually is a disk I/O
error. The arguments are DOS error number and the values of AX, BP and
SI registers. The handler may return the value

	0 - ignore the error and continue the user application
	1 - retry whatever you tried to do
	2 - abort the user application

Error is the DOS error value passed by the system to 0x24 handler

	0 - Write protect
	1 - Unknown unit (source of error not known)
	2 - Drive not ready
	3 - Unknown command
	4 - Data error (CRC)
	5 - Bad request (lenght of "drive request structure")
	6 - Seek error
	7 - Unknown media type
	8 - Sector not found
	9 - Printer out of paper
	A - Write fault
	B - Read fault
	C - General failure
	D - reserved
	E - reserved
	F - Invalid disk change

If argument AX is negative ie. bit 15 is set, there was a device error
and you'll have to find more info at the device driver header located at
the memory address BS:SI. If word at (BS:SI + 4) is zero, there was a
bad memory image of FAT. If the word is negative (bit 15 set), look at
the word last 4 bits (bits 0-3 of 15) at the address told in BS:SI

	0001 - error in standard input
	0010 - error in standard output
	0100 - error in NULL device
	1000 - error in clock device

If AX is not negative ie. bit 15 is not set, there was a disk error. The
disk drive in question is identified at the low-order byte of AX (AX &
0xff), so that 0 == A drive