dosirq.c
资源名称:tcpmp.rar [点击查看]
上传用户:wstnjxml
上传日期:2014-04-03
资源大小:7248k
文件大小:8k
源码类别:
Windows CE
开发平台:
C/C++
- /*
- Implementation of IRQ routines on DOS
- Copyright (C) 1999 by Andrew Zabolotny, <bit@eltech.ru>
- 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 <dpmi.h>
- #include <go32.h>
- #include <dos.h>
- #include <sys/nearptr.h>
- #include <malloc.h>
- unsigned int __irq_stack_size = 0x4000;
- unsigned int __irq_stack_count = 1;
- static void __int_stub_template()
- {
- /* *INDENT-OFF* */
- asm(" pushaln"
- " pushl %dsn"
- " pushl %esn"
- " pushl %fsn"
- " pushl %gsn"
- " movw $0x1234,%axn" /* Get DPMI data selector */
- " movw %ax,%dsn" /* Set DS and ES to data selector */
- " movw %ax,%esn"
- " movl $0x12345678,%ebxn" /* Interrupt stack top */
- " movl (%ebx),%ecxn"
- " movl %ecx,%edxn"
- " subl $0x12345678,%ecxn" /* Subtract irq_stack_count */
- " movl %ecx,(%ebx)n"
- " movw %ss,%sin" /* Save old SS:ESP */
- " movl %esp,%edin"
- " movl %edx,%espn" /* Set SS:ESP to interrupt stack */
- " movw %ax,%ssn"
- " pushl %esin"
- " pushl %edin"
- " pushl %ebxn"
- " pushl %edxn"
- " call 1fn" /* Call user interrupt handler */
- "1: popl %edxn"
- " popl %ebxn"
- " movl %edx,(%ebx)n"
- " popl %edin"
- " popl %esin"
- " movl %edi,%espn" /* Restore old SS:ESP */
- " movw %si,%ssn"
- " popl %gsn"
- " popl %fsn"
- " popl %esn"
- " popl %dsn"
- " popaln"
- " iretn");
- /* *INDENT-ON* */
- }
- #include <stdio.h>
- 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 = 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)) {
- 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);
- free((void *)info->pm_offset);
- }
- irq_handle *irq_hook(int irqno, void (*handler) (), unsigned long size)
- {
- int interrupt;
- 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 = malloc(sizeof(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(irq_handle);
- if (__dpmi_lock_linear_region(&struct_info)) {
- 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(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(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);
- free(irq);
- }
- /*---------------------------------------------- IRQ detection mechanism -----*/
- static 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(&__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, 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(&__irq_count, 0, sizeof(__irq_count));
- __irq_mask = 0;
- if (oldirq)
- enable();
- }
- /* ex:set ts=4: */