X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?p=dosdemo;a=blobdiff_plain;f=libs%2Fmikmod%2Fdrivers%2Fdos%2Fdosirq.c;fp=libs%2Fmikmod%2Fdrivers%2Fdos%2Fdosirq.c;h=0000000000000000000000000000000000000000;hp=9b0e21f5f85da17583ccc633f55030dcb534ac8c;hb=b2c24e9d5b637bb78d18a377d9957c07d0759030;hpb=67c749060592270c9cd8b4f7dafe7d7c7a61a614 diff --git a/libs/mikmod/drivers/dos/dosirq.c b/libs/mikmod/drivers/dos/dosirq.c deleted file mode 100644 index 9b0e21f..0000000 --- a/libs/mikmod/drivers/dos/dosirq.c +++ /dev/null @@ -1,323 +0,0 @@ -/* - Implementation of IRQ routines on DOS - Copyright (C) 1999 by Andrew Zabolotny, - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the Free - Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "dosirq.h" - -#include -#include -#include -#include -#include -#include -#include "mikmod.h" /* for MikMod_malloc() & co */ - -unsigned int __irq_stack_size = 0x4000; -unsigned int __irq_stack_count = 1; - -static void __int_stub_template (void) -{ -/* *INDENT-OFF* */ - asm(" pushal\n" - " pushl %ds\n" - " pushl %es\n" - " pushl %fs\n" - " pushl %gs\n" - " movw $0x1234,%ax\n" /* Get DPMI data selector */ - " movw %ax,%ds\n" /* Set DS and ES to data selector */ - " movw %ax,%es\n" - " movl $0x12345678,%ebx\n" /* Interrupt stack top */ - " movl (%ebx),%ecx\n" - " movl %ecx,%edx\n" - " subl $0x12345678,%ecx\n" /* Subtract irq_stack_count */ - " movl %ecx,(%ebx)\n" - " movw %ss,%si\n" /* Save old SS:ESP */ - " movl %esp,%edi\n" - " movl %edx,%esp\n" /* Set SS:ESP to interrupt stack */ - " movw %ax,%ss\n" - " pushl %esi\n" - " pushl %edi\n" - " pushl %ebx\n" - " pushl %edx\n" - " call 1f\n" /* Call user interrupt handler */ - "1: popl %edx\n" - " popl %ebx\n" - " movl %edx,(%ebx)\n" - " popl %edi\n" - " popl %esi\n" - " movl %edi,%esp\n" /* Restore old SS:ESP */ - " movw %si,%ss\n" - " popl %gs\n" - " popl %fs\n" - " popl %es\n" - " popl %ds\n" - " popal\n" - " iret\n"); -/* *INDENT-ON* */ -} - -#include - -static int _allocate_iret_wrapper(_go32_dpmi_seginfo * info) -{ - unsigned char *irqtpl = (unsigned char *)__int_stub_template; - unsigned char *irqend, *irqwrapper, *tmp; - __dpmi_meminfo handler_info; - unsigned int wrappersize; - - /* First, skip until pushal */ - while (*irqtpl != 0x60) - irqtpl++; - /* Now find the iret */ - irqend = irqtpl; - while (*irqend++ != 0xcf); - - wrappersize = 4 + __irq_stack_size * __irq_stack_count + 4 + - ((long)irqend - (long)irqtpl); - irqwrapper = (unsigned char *) MikMod_malloc(wrappersize); - /* Lock the wrapper */ - handler_info.address = __djgpp_base_address + (unsigned long)irqwrapper; - handler_info.size = wrappersize; - if (__dpmi_lock_linear_region(&handler_info)) { - MikMod_free(irqwrapper); - return -1; - } - - /* First comes the interrupt wrapper size */ - *(unsigned long *)irqwrapper = wrappersize; - - /* Next comes the interrupt stack */ - tmp = irqwrapper + 4 + __irq_stack_size * __irq_stack_count; - - /* The following dword is interrupt stack pointer */ - *((void **)tmp) = tmp; - tmp += 4; - - /* Now comes the interrupt wrapper itself */ - memcpy(tmp, irqtpl, irqend - irqtpl); - *(unsigned short *)(tmp + 9) = _my_ds(); - *(unsigned long *)(tmp + 16) = (unsigned long)tmp - 4; - *(unsigned long *)(tmp + 26) = __irq_stack_size; - *(unsigned long *)(tmp + 46) = - info->pm_offset - (unsigned long)(tmp + 50); - - info->pm_offset = (unsigned long)tmp; - info->pm_selector = _my_cs(); - - return 0; -} - -static void _free_iret_wrapper(_go32_dpmi_seginfo * info) -{ - __dpmi_meminfo handler_info; - - info->pm_offset -= 4 + __irq_stack_size * __irq_stack_count + 4; - - handler_info.address = __djgpp_base_address + info->pm_offset; - handler_info.size = *(unsigned long *)info->pm_offset; - __dpmi_unlock_linear_region(&handler_info); - - MikMod_free((void *)info->pm_offset); -} - -struct irq_handle *irq_hook(int irqno, void (*handler)(), unsigned long size) -{ - int interrupt; - struct irq_handle *irq; - __dpmi_version_ret version; - __dpmi_meminfo handler_info, struct_info; - _go32_dpmi_seginfo info; - unsigned long old_sel, old_ofs; - - __dpmi_get_version(&version); - if (irqno < 8) - interrupt = version.master_pic + irqno; - else - interrupt = version.slave_pic + (irqno - 8); - - if (_go32_dpmi_get_protected_mode_interrupt_vector(interrupt, &info)) - return NULL; - - old_sel = info.pm_selector; - old_ofs = info.pm_offset; - - info.pm_offset = (unsigned long)handler; - if (_allocate_iret_wrapper(&info)) - return NULL; - - /* Lock the interrupt handler in memory */ - handler_info.address = __djgpp_base_address + (unsigned long)handler; - handler_info.size = size; - if (__dpmi_lock_linear_region(&handler_info)) { - _free_iret_wrapper(&info); - return NULL; - } - - irq = (struct irq_handle *) MikMod_malloc(sizeof(struct irq_handle)); - irq->c_handler = handler; - irq->handler_size = size; - irq->handler = info.pm_offset; - irq->prev_selector = old_sel; - irq->prev_offset = old_ofs; - irq->int_num = interrupt; - irq->irq_num = irqno; - irq->pic_base = irqno < 8 ? PIC1_BASE : PIC2_BASE; - - struct_info.address = __djgpp_base_address + (unsigned long)irq; - struct_info.size = sizeof(struct irq_handle); - if (__dpmi_lock_linear_region(&struct_info)) { - MikMod_free(irq); - __dpmi_unlock_linear_region(&handler_info); - _free_iret_wrapper(&info); - return NULL; - } - - _go32_dpmi_set_protected_mode_interrupt_vector(interrupt, &info); - - irq->pic_mask = irq_state(irq); - return irq; -} - -void irq_unhook(struct irq_handle *irq) -{ - _go32_dpmi_seginfo info; - __dpmi_meminfo mem_info; - - if (!irq) - return; - - /* Restore the interrupt vector */ - irq_disable(irq); - info.pm_offset = irq->prev_offset; - info.pm_selector = irq->prev_selector; - _go32_dpmi_set_protected_mode_interrupt_vector(irq->int_num, &info); - - /* Unlock the interrupt handler */ - mem_info.address = __djgpp_base_address + (unsigned long)irq->c_handler; - mem_info.size = irq->handler_size; - __dpmi_unlock_linear_region(&mem_info); - - /* Unlock the irq_handle structure */ - mem_info.address = __djgpp_base_address + (unsigned long)irq; - mem_info.size = sizeof(struct irq_handle); - __dpmi_unlock_linear_region(&mem_info); - - info.pm_offset = irq->handler; - _free_iret_wrapper(&info); - - /* If IRQ was enabled before we hooked, restore enabled state */ - if (irq->pic_mask) - irq_enable(irq); - else - irq_disable(irq); - - MikMod_free(irq); -} - -/*---------------------------------------------- IRQ detection mechanism -----*/ -static struct irq_handle *__irqs[16]; -static int (*__irq_confirm) (int irqno); -static volatile unsigned int __irq_mask; -static volatile unsigned int __irq_count[16]; - -#define DECLARE_IRQ_HANDLER(irqno) \ -static void __irq##irqno##_handler () \ -{ \ - if (irq_check (__irqs [irqno]) && __irq_confirm (irqno)) \ - { \ - __irq_count [irqno]++; \ - __irq_mask |= (1 << irqno); \ - } \ - irq_ack (__irqs [irqno]); \ -} - -/* *INDENT-OFF* */ -DECLARE_IRQ_HANDLER(0) -DECLARE_IRQ_HANDLER(1) -DECLARE_IRQ_HANDLER(2) -DECLARE_IRQ_HANDLER(3) -DECLARE_IRQ_HANDLER(4) -DECLARE_IRQ_HANDLER(5) -DECLARE_IRQ_HANDLER(6) -DECLARE_IRQ_HANDLER(7) -DECLARE_IRQ_HANDLER(8) -DECLARE_IRQ_HANDLER(9) -DECLARE_IRQ_HANDLER(10) -DECLARE_IRQ_HANDLER(11) -DECLARE_IRQ_HANDLER(12) -DECLARE_IRQ_HANDLER(13) -DECLARE_IRQ_HANDLER(14) -DECLARE_IRQ_HANDLER(15) -/* *INDENT-ON* */ - -static void (*__irq_handlers[16]) () = { - __irq0_handler, __irq1_handler, __irq2_handler, __irq3_handler, - __irq4_handler, __irq5_handler, __irq6_handler, __irq7_handler, - __irq8_handler, __irq9_handler, __irq10_handler, __irq11_handler, - __irq12_handler, __irq13_handler, __irq14_handler, __irq15_handler}; - -void irq_detect_start(unsigned int irqs, int (*irq_confirm) (int irqno)) -{ - int i; - - __irq_mask = 0; - __irq_confirm = irq_confirm; - memset(&__irqs, 0, sizeof(__irqs)); - memset((void *) &__irq_count, 0, sizeof(__irq_count)); - - /* Hook all specified IRQs */ - for (i = 1; i <= 15; i++) - if (irqs & (1 << i)) { - __irqs[i] = irq_hook(i, __irq_handlers[i], 200); - /* Enable the interrupt */ - irq_enable(__irqs[i]); - } - /* Enable IRQ2 if we need at least one IRQ above 7 */ - if (irqs & 0xff00) - _irq_enable(2); -} - -void irq_detect_end() -{ - int i; - for (i = 15; i >= 1; i--) - if (__irqs[i]) - irq_unhook(__irqs[i]); -} - -int irq_detect_get(int irqno, unsigned int *irqmask) -{ - int oldirq = disable(); - int count = __irq_count[irqno]; - *irqmask = __irq_mask; - __irq_mask = 0; - if (oldirq) - enable(); - return count; -} - -void irq_detect_clear() -{ - int oldirq = disable(); - memset((void *) &__irq_count, 0, sizeof(__irq_count)); - __irq_mask = 0; - if (oldirq) - enable(); -} - -/* ex:set ts=4: */