Mail Archives: djgpp/1994/06/27/14:17:59
I sent the message before, but I never recevied it back from the list server,
so I'm assuming it didn't get out and sending it again. Sorry if this is ends
up being a duplication.
-------------------------------------------------------------------------------
> I want my programs to be able to successfully catch I/O errors with a
> floppy disk. This is not a problem if the disk is full, for instance, but if
> there is actually no disk in the drive then I get the DOS "Abort, Retry, Fail"
> message repeatedly on my screen. What's the easiest way to beat DOS to it and
> have MY program be able to handle a no-disk situation?
Well one question, how does one normally do it in real mode program? Typically
one uses the harderr() functions to establish a catch function, however the
harderr() functions aren't in the DJGPP library. Right after v1.11 came out I
wrote the follow code. It still has a couple problems, but it is still usable.
I ment to finish it up befor generally releasing it but its been a while and I
just haven't had the time (or need) to finish it. Therefore I figured I might
as well release it now, and maybe someone else can finish it up.
The code has the following known problems:
1. I never wrote the hardretn() or _hardretn() functions. This was
because the program I needed the harderr() functions for didn't need
them. Also I didn't think they would be anywhere near trivial. I
thoughts are one will have to play with the real mode stack to get this
to work. This might not even be possible.
2. I wrote this assuming non-DPMI operation (see MK_FP macro). Again
the program I needed this for could be restricted to VCPI only system.
I also seem to think I didn't even need to examine that pointer
anyways, so it's a moot point.
3. This code can suffer from the virtual memory system. (Example: A
program sets the hard-error catch function. Then much later on the
program experiences a hard-error. However, in the mean time, the VM
system swapped out the harderr() code, thus the interrupt vector was
pointing to who knows what.)
This did bite me in my program. Between when I set the hard-error
catch and when the hard-error occured I did a system() call which
swapped out everything. My work around was to re-set the catch
function right after a system() call. Better probably would have been
right befor where the hard-error was expected. Basically all I needed
to do was touch something in the harderr()'s code-page so that it would
be swapped it.
The actuall solution should be, use a DPMI call to lock the harderr()'s
code so that it won't be swapped out. Currently however GO32 doesn't
support this call. So such a fix would only work under DPMI until GO32
is updated. Weither or not it should be harderr()'s or the calls
responsibility to lock the catch-function is to be desided. I'd
probably say that harderr() should lock to page that the catch function
starts in plus a bit (thus one or two pages), this would help in blind
porting. But it really should be the programmers responsibility to
verify that this is correct, locking any additional pages needed.
Potter
-------------------------------------------------------------------------------
FILE: harderr.h
-------------------------------------------------------------------------------
#if !defined( harderr_h )
#define harderr_h
#if defined( __cplusplus )
void _harderr ( void (*fn)( unsigned device_error_code,
unsigned errval,
unsigned *devhdr ) );
void harderr ( int (*fn)( int error_value,
int device_error_code,
int device_header_segment,
int device_header_offset ) );
#else
void _harderr ( void (*fn)() );
void harderr ( int (*fn)() );
#endif
void _hardresume ( int ret );
void _hardretn ( int ret );
void hardresume ( int ret );
void hardretn ( int ret );
/* constants for _hardresume(), hardresume(), or harderr() */
#define _HARDERR_IGNORE 0x0 /* Ignore the error */
#define _HARDERR_RETRY 0x1 /* Retry the operation */
#define _HARDERR_ABORT 0x2 /* Terminate the program */
#define _HARDERR_FAIL 0x3 /* Terminate the function */
#endif
-------------------------------------------------------------------------------
FILE: harderr.c
-------------------------------------------------------------------------------
#include <dmalloc.h>
#include <dos.h>
#include <sys/types.h>
#include <dpmi.h>
#include <go32.h>
#include <pc.h>
#include <setjmp.h>
#include <stdio.h>
#define __cplusplus /* to get full prototypes */
# include "harderr.h"
#undef __cplusplus
#define INTERRUPT 0x24
#define MK_FP( seg, off ) ((void*)( ((seg)<<4) + (off) + 0xE0000000 ))
typedef int (*generic_fn_ptr)( void );
typedef void (*microsoft_fn)(
unsigned device_error_code,
unsigned errval,
unsigned *devhdr
);
typedef int (*borland_fn)(
int error_value,
int device_error_code,
int device_header_segment,
int device_header_offset
);
typedef enum he_style_e {
STYLE_MICROSOFT,
STYLE_BORLAND
} he_style_t;
typedef enum he_handler_ret_method_e {
HRM_UNKNOWN,
HRM_RESUME,
/* HRM_RETN * Not implemented */
} he_handler_ret_method_t;
static _go32_dpmi_seginfo dpmi_info;
/*extern*/ _go32_dpmi_registers dpmi_regs;
static he_style_t he_style;
static generic_fn_ptr he_func = NULL;
static jmp_buf he_jmp_buf;
static int he_resume_val;
static /*interrupt*/
void harderr_handler( _go32_dpmi_registers *r ) {
switch( (he_handler_ret_method_t)setjmp( he_jmp_buf ) ) {
case HRM_UNKNOWN:
if ( he_style == STYLE_MICROSOFT ) {
((microsoft_fn)(he_func))( r->x.ax, r->x.di,
MK_FP( r->x.bp, r->x.si ) );
r->h.al = _HARDERR_ABORT;
} else {
r->h.al =
((borland_fn)(he_func))( r->x.di & 0xff, r->x.ax,
r->x.bp, r->x.si );
}
return;
case HRM_RESUME:
r->h.al = he_resume_val;
return;
}
}
static
void __harderr(
generic_fn_ptr fn
) {
if ( he_func != NULL ) {
_go32_dpmi_free_real_mode_callback( &dpmi_info );
}
he_func = fn;
dpmi_info.pm_offset = (int)harderr_handler;
_go32_dpmi_allocate_real_mode_callback_iret( &dpmi_info, &dpmi_regs );
_go32_dpmi_set_real_mode_interrupt_vector( INTERRUPT, &dpmi_info );
}
extern
void _harderr(
void (*fn)( unsigned device_error_code,
unsigned errval,
unsigned *devhdr )
) {
he_style = STYLE_MICROSOFT;
__harderr( (generic_fn_ptr)fn );
}
void harderr(
int (*fn)( int error_value,
int device_error_code,
int device_header_segment,
int device_header_offset )
) {
he_style = STYLE_BORLAND;
__harderr( (generic_fn_ptr)fn );
}
void _hardresume(
int ret
) {
he_resume_val = ret;
longjmp( he_jmp_buf, HRM_RESUME );
}
void hardresume(
int ret
) {
_hardresume( ret );
}
void _hardretn(
int ret
) {
/* to be implemented */
}
void hardretn(
int ret
) {
_hardretn( ret );
}
- Raw text -