⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 emu_irq.c

📁 一个linux下rs485驱动程序的源代码
💻 C
字号:
/*******************************************************************  User space IRQ handling emulator for i386 Linux based PCs  It uses VM86_PLUS services developed for DOSEMU  emu_irq.c  (C) Copyright 1998 by Pavel Pisa   This code is distributed under the Gnu General Public Licence.   See file COPYING for details. *******************************************************************/#include <unistd.h>#include <stdio.h>#include <stdlib.h>#include <signal.h>#include <errno.h>#include <string.h>#include <asm/vm86.h>#include <sys/syscall.h>#include "emu_irq.h"#define NEW_SYS_vm86  166static inline int vm86_plus(int function, int param){	int __res;	__asm__ __volatile__("int $0x80\n"	:"=a" (__res):"a" ((int)NEW_SYS_vm86), "b" (function), "c" (param));	return __res;} int emu_irq_initialized=0;struct emu_irq {    emu_irq_handler *handler;    void   *dev_id;  } emu_irq_arr[16]={{0,},};void emu_irq_hanle_sig(int signo){ unsigned emu_irq_set;  int intno;  int ret;  if(!emu_irq_initialized) return;  emu_irq_set = vm86_plus(VM86_GET_IRQ_BITS,0);  intno=0;  while (emu_irq_set)  {    if((emu_irq_set&1)&&emu_irq_arr[intno].handler)    { ret = vm86_plus(VM86_GET_AND_RESET_IRQ,intno);      emu_irq_arr[intno].handler(intno,emu_irq_arr[intno].dev_id,NULL);    };    emu_irq_set>>=1;    intno++;  }};void release_all_emu_irq(void);int request_emu_irq(unsigned int intno, emu_irq_handler *handler,                    unsigned long flags, const char *device, void *dev_id){ int ret;  if(!emu_irq_initialized)  { struct sigaction emu_irq_sig;    struct sigaction old_sig;    memset(&emu_irq_sig,0,sizeof(emu_irq_sig));    emu_irq_initialized=1;    emu_irq_sig.sa_handler=emu_irq_hanle_sig;    sigemptyset(&emu_irq_sig.sa_mask);    emu_irq_sig.sa_flags=SA_RESTART;    emu_irq_sig.sa_restorer=0;    sigaction(EMU_IRQ_SIG,&emu_irq_sig,&old_sig);    atexit(&release_all_emu_irq);  };  if (intno>=16) return -EINVAL;  if (emu_irq_arr[intno].handler) return -EINVAL;  emu_irq_arr[intno].handler=handler;  emu_irq_arr[intno].dev_id=dev_id;  ret = vm86_plus(VM86_REQUEST_IRQ,(EMU_IRQ_SIG<<8)| intno);  if (ret!=intno)  { emu_irq_arr[intno].handler=NULL;    return -EPERM;  };  return ret;};int  release_emu_irq(int intno, void *dev_id){ int ret;  ret = vm86_plus(VM86_FREE_IRQ,intno);  emu_irq_arr[intno].handler=NULL;  return ret;};void release_all_emu_irq(void){ int intno; if(emu_irq_initialized) {  for(intno=0;intno<16;intno++)   if(emu_irq_arr[intno].handler!=NULL)     release_emu_irq(intno,emu_irq_arr[intno].dev_id);  emu_irq_initialized=0; };};/*******************************************************************//* usage example */#if 0#include <asm/io.h>#include <linux/serial_reg.h>void my_irq_handler(int intno, void *dev_id, void *regs){  int irq_src;  int rec_chr;  unsigned long ser_port_base=*(int *)dev_id;  printf("Emulated irq %d!\n",intno);   while(!((irq_src=inb(ser_port_base+UART_IIR))&UART_IIR_NO_INT))  {     switch (irq_src & UART_IIR_ID)    {      case UART_IIR_RDI:        printf("RI : ");        rec_chr=inb(ser_port_base+UART_RX);        printf("rec  0x%02x ",rec_chr);        if (rec_chr>=' ')printf("'%c'",rec_chr);        break;      case UART_IIR_THRI:        printf("TI : ");        break;      case UART_IIR_RLSI:        printf("RM : ");        printf("lsr  0x%02x",inb(ser_port_base+UART_LSR));        break;      case UART_IIR_MSI:        printf("MI : ");        printf("msr  0x%02x",inb(ser_port_base+UART_MSR));        break;    };    printf("\n");  };};int main(int argc, char **argv){ int ret;  unsigned long ser_port_base=0x2F8;  unsigned ser_irq=3;  int key;  int lcr_mode;  int ier_enable;  int baud_div;   ret=ioperm(ser_port_base,8l,1);  if (ret<0) { perror("cannot request ioports"); return 4;};  ret = request_emu_irq(ser_irq, my_irq_handler, 0, "test", &ser_port_base);  if (ret<0) { perror("cannot request interrupt"); return 4;};  outb(0x00,ser_port_base+UART_MCR);  outb(UART_LCR_DLAB,ser_port_base+UART_LCR);  baud_div=12;  outb(baud_div,ser_port_base+UART_DLL);  outb(baud_div>>8,ser_port_base+UART_DLM);  /* UART_LCR_SPAR,UART_LCR_EPAR,UART_LCR_PARITY,UART_LCR_STOP */  /* UART_LCR_WLEN8 */  lcr_mode=UART_LCR_WLEN8;  outb(lcr_mode,ser_port_base+UART_LCR);  ier_enable=UART_IER_MSI | UART_IER_THRI | UART_IER_RDI | UART_IER_RLSI;  outb(ier_enable,ser_port_base+UART_IER);  outb(UART_IIR_NO_INT,ser_port_base+UART_IIR);  inb(ser_port_base+UART_LSR);  inb(ser_port_base+UART_MSR);  inb(ser_port_base+UART_IIR);  inb(ser_port_base);  outb(0x0F,ser_port_base+UART_MCR);  outb(0x55,ser_port_base);  do {    key=getchar();    switch (key)    {      case 'c': outb(0x01,ser_port_base+UART_IIR); break;      case 's': if(!(inb(ser_port_base+UART_IIR)&UART_IIR_NO_INT)) printf("#");                inb(ser_port_base+UART_LSR); break;      case 'm': inb(ser_port_base+UART_MSR); break;      case 'r': inb(ser_port_base+UART_RX); break;      case 't': outb(0x55,ser_port_base+UART_TX); break;      case 'l': outb(0x0D,ser_port_base+UART_TX); break;    };  } while(key!='q');  // getchar();  outb(0x00,ser_port_base+UART_IER);  outb(0x00,ser_port_base+UART_MCR);  release_emu_irq(ser_irq, &ser_port_base);  ioperm(ser_port_base,8l,0);    return 0;};#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -