/* _install_irq: * Installs a hardware interrupt handler for the specified irq, allocating * an asm wrapper function which will save registers and handle the stack * switching. The C function should return zero to exit the interrupt with * an iret instruction, and non-zero to chain to the old handler. */ int _install_irq(int num, int (*handler)(void)) { __dpmi_paddr addr; int c; for (c=0; c<MAX_IRQS; c++) { if (_irq_handler[c].handler == NULL) { addr.selector = _my_cs(); switch (c) { case 0: addr.offset32 = (long)_irq_wrapper_0; break; case 1: addr.offset32 = (long)_irq_wrapper_1; break; case 2: addr.offset32 = (long)_irq_wrapper_2; break; case 3: addr.offset32 = (long)_irq_wrapper_3; break; case 4: addr.offset32 = (long)_irq_wrapper_4; break; case 5: addr.offset32 = (long)_irq_wrapper_5; break; case 6: addr.offset32 = (long)_irq_wrapper_6; break; case 7: addr.offset32 = (long)_irq_wrapper_7; break; default: return -1; } _irq_handler[c].handler = handler; _irq_handler[c].number = num; __dpmi_get_protected_mode_interrupt_vector(num, &_irq_handler[c].old_vector); __dpmi_set_protected_mode_interrupt_vector(num, &addr); return 0; } } return -1; }
static void update_async() { int time = tl_process_group(asyncgroup); if (time != -1) { struct itimerval t; t.it_interval.tv_sec = 0; t.it_interval.tv_usec = 0; t.it_value.tv_sec = time / 1000000; t.it_value.tv_usec = time % 1000000; if (!reghandler) { #ifdef __DJGPP__ _go32_dpmi_seginfo pmint; pmint.pm_selector=_my_cs(); pmint.pm_offset=&alarmhandler; _go32_dpmi_chain_protected_mode_interrupt_vector(0x1c,&pmint); #endif signal(SIGALRM, alarmhandler), reghandler = 1; } setitimer(ITIMER_REAL, &t, &t); registered = 1; } else if (registered) { struct itimerval t; t.it_interval.tv_sec = 0; t.it_interval.tv_usec = 0; t.it_value.tv_sec = 0; t.it_value.tv_usec = 0; setitimer(ITIMER_REAL, &t, &t); registered = 0; } }
/* go to background: TSR */ void msdosBackground (void) { __djgpp_set_ctrl_c(0); saveState(&mainState); if (!setjmp(mainContext)) { __dpmi_regs regs; /* set a chained Protected Mode Timer IRQ handler */ timerSeginfo.pm_selector = _my_cs(); timerSeginfo.pm_offset = (unsigned long)&timerInterruptHandler; _go32_dpmi_get_protected_mode_interrupt_vector(TIMER_INTERRUPT, &origTimerSeginfo); _go32_dpmi_chain_protected_mode_interrupt_vector(TIMER_INTERRUPT, &timerSeginfo); /* set a real mode DOS Idle handler which calls back our Idle handler */ idleSeginfo.pm_selector = _my_cs(); idleSeginfo.pm_offset = (unsigned long)&idleInterruptHandler; memset(&idleRegisters, 0, sizeof(idleRegisters)); _go32_dpmi_get_real_mode_interrupt_vector(IDLE_INTERRUPT, &origIdleSeginfo); _go32_dpmi_allocate_real_mode_callback_iret(&idleSeginfo, &idleRegisters); _go32_dpmi_set_real_mode_interrupt_vector(IDLE_INTERRUPT, &idleSeginfo); /* Get InDos and Critical flags addresses */ regs.h.ah = 0X34; __dpmi_int(DOS_INTERRUPT, ®s); inDosFlagPointer = msdosMakeAddress(regs.x.es, regs.x.bx); regs.x.ax = 0X5D06; __dpmi_int(DOS_INTERRUPT, ®s); criticalOffset = msdosMakeAddress(regs.x.ds, regs.x.si); /* We are ready */ isBackgrounded = 1; regs.x.ax = 0X3100; msdosBreakAddress(0X100/*psp*/ + _go32_info_block.size_of_transfer_buffer, 0, ®s.x.dx, NULL); __dpmi_int(DOS_INTERRUPT, ®s); /* shouldn't be reached */ logMessage(LOG_ERR, "TSR installation failed"); isBackgrounded = 0; } saveState(&interruptState); restoreState(&mainState); }
/* go to background: TSR */ void msdosBackground(void) { saveState(&mainState); if (!setjmp(mainCtx)) { __dpmi_regs regs; /* set a chained Protected Mode Timer IRQ handler */ timerSeginfo.pm_selector = _my_cs(); timerSeginfo.pm_offset = (unsigned long)&timerInt; _go32_dpmi_get_protected_mode_interrupt_vector(TIMER_INT, &origTimerSeginfo); _go32_dpmi_chain_protected_mode_interrupt_vector(TIMER_INT, &timerSeginfo); /* set a real mode DOS Idle handler which calls back our Idle handler */ idleSeginfo.pm_selector = _my_cs(); idleSeginfo.pm_offset = (unsigned long)&idleInt; memset(&idleRegs, 0, sizeof(idleRegs)); _go32_dpmi_get_real_mode_interrupt_vector(IDLE_INT, &origIdleSeginfo); _go32_dpmi_allocate_real_mode_callback_iret(&idleSeginfo, &idleRegs); _go32_dpmi_set_real_mode_interrupt_vector(IDLE_INT, &idleSeginfo); /* Get InDos and Critical flags addresses */ regs.h.ah = 0x34; __dpmi_int(DOS_INT, ®s); inDosOffset = regs.x.es*16 + regs.x.bx; regs.x.ax = 0x5D06; __dpmi_int(DOS_INT, ®s); criticalOffset = regs.x.ds*16 + regs.x.si; /* We are ready */ atexit(tsr_exit); backgrounded = 1; regs.x.ax = 0x3100; regs.x.dx = (/* PSP */ 256 + _go32_info_block.size_of_transfer_buffer) / 16; __dpmi_int(DOS_INT, ®s); /* shouldn't be reached */ logMessage(LOG_ERR,"Installation failed"); backgrounded = 0; } saveState(&intState); restoreState(&mainState); }
/* init_mouse: * Helper for initialising the int 0x33 driver and installing an RMCB. */ static int init_mouse(void (*handler)(__dpmi_regs *r)) { __dpmi_regs r; int num_buttons; /* initialise the int 0x33 driver */ r.x.ax = 0; __dpmi_int(0x33, &r); if (r.x.ax == 0) return -1; num_buttons = r.x.bx; if (num_buttons == 0xFFFF) num_buttons = 2; /* create and activate a real mode callback */ if (handler) { LOCK_VARIABLE(mouse_regs); #ifdef ALLEGRO_DJGPP /* djgpp version uses libc routines to set up the RMCB */ { LOCK_VARIABLE(mouse_seginfo); mouse_seginfo.pm_offset = (int)handler; mouse_seginfo.pm_selector = _my_cs(); if (_go32_dpmi_allocate_real_mode_callback_retf(&mouse_seginfo, &mouse_regs) != 0) return -1; r.x.ax = 0x0C; r.x.cx = 0x7F; r.x.dx = mouse_seginfo.rm_offset; r.x.es = mouse_seginfo.rm_segment; __dpmi_int(0x33, &r); } #elif defined ALLEGRO_WATCOM /* Watcom version relies on the DOS extender to do it for us */ { struct SREGS sregs; union REGS inregs, outregs; inregs.w.ax = 0x0C; inregs.w.cx = 0x7F; inregs.x.edx = _allocate_real_mode_callback(handler, &mouse_regs); segread(&sregs); sregs.es = _my_cs(); int386x(0x33, &inregs, &outregs, &sregs); } #else #error unknown platform #endif } return num_buttons; }
/* _install_irq: * Installs a hardware interrupt handler for the specified irq, allocating * an asm wrapper function which will save registers and handle the stack * switching. The C function should return zero to exit the interrupt with * an iret instruction, and non-zero to chain to the old handler. */ int _install_irq ( int irq, int (*handler)(void) ) { int c ; if ( irq_virgin ) { /* first time we've been called? */ unsigned char *p ; #if defined(__WATCOMC__) && !defined(__386__) /* must keep SEGMENT(_isr_stack) == SS for C/L/H module */ p = NormalizeEven(_isr_stack) + IRQ_STACKS*STACK_SIZE ; #else p = (unsigned char*)malloc(IRQ_STACKS*STACK_SIZE) ; if ( p == NULL ) return -1 ; #if defined(__386__) _lock_data(p,IRQ_STACKS*STACK_SIZE) ; p = (unsigned char*)((int)(p+IRQ_STACKS*STACK_SIZE-15) & (~3)) ; #else p = NormalizeEven(p) + IRQ_STACKS*STACK_SIZE ; #endif #endif for ( c = IRQ_STACKS ; --c >= 0 ; ) { _irq_stack[c] = p ; /* WATCOM C/Large data: p can't be normalized */ p -= STACK_SIZE ; } #if defined(__DJGPP__) _lock_data(&sldata,LOCKED_DATA_SIZE) ; _lock_code(&sltext,LOCKED_TEXT_SIZE) ; #endif LOCK_VARIABLE(_irq_handler) ; LOCK_VARIABLE(_irq_stack) ; LOCK_FUNCTION(_irq_wrapper_0) ; for ( c = 0 ; c < MAX_IRQS ; c++ ) { _irq_handler[c].handler = NULL ; _irq_handler[c].irq = -1 ; } irq_virgin = 0 ; } for ( c = 0 ; c < MAX_IRQS ; c++ ) { if ( _irq_handler[c].handler == NULL ) { ISR addr ; int vector = irq + (irq < 8 ? 8 : 0x70-8) ; _irq_handler[c].handler = handler ; _irq_handler[c].irq = irq ; #if defined(__DJGPP__) /* or PMODE/W, but not DOS4G/W */ addr.selector = _my_cs() ; switch ( c ) { case 0 : addr.offset32 = (long)_irq_wrapper_0 ; break ; case 1 : addr.offset32 = (long)_irq_wrapper_1 ; break ; case 2 : addr.offset32 = (long)_irq_wrapper_2 ; break ; case 3 : addr.offset32 = (long)_irq_wrapper_3 ; break ; } _pm_getvect(vector,&_irq_handler[c].old_vector) ; _pm_setvect(vector,&addr) ; #else switch ( c ) { case 0 : addr = (ISR)_irq_wrapper_0 ; break ; case 1 : addr = (ISR)_irq_wrapper_1 ; break ; case 2 : addr = (ISR)_irq_wrapper_2 ; break ; case 3 : addr = (ISR)_irq_wrapper_3 ; break ; } _irq_handler[c].old_vector = _dos_getvect(vector) ; _dos_setvect(vector,addr) ; #endif return 0 ; } } return -1 ; }
int _lock_code ( void *_lockaddr, unsigned long _locksize ) { return _lock_memory(_my_cs(),_lockaddr,_locksize) ; }