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

📄 rtl_posix_if.h

📁 最新rtlinux内核源码
💻 H
字号:
#include <rtl_sync.h>#include <rtl_core.h>#include <rtl_printf.h>#include <time.h>#include <asm/io.h>#include <rtl_posixio.h>#include <sys/mman.h>#include <errno.h>#include <unistd.h>#include <rtl.h>#include <rtl_malloc.h>#include <rtl_sema.h>#include <reddopts.h>#include <rt_pci.h>#include "net_policy/FIFO_policy.h"//The functions that will implement the POSIX interfacestatic int rtl_eth_open (struct rtl_file *filp);static int rtl_eth_release (struct rtl_file *filp);static ssize_t rtl_eth_write(struct rtl_file *filp, const char *buf, size_t count, loff_t* ppos);static int rtl_eth_ioctl(struct rtl_file * filp, unsigned int request, unsigned long other);static ssize_t rtl_eth_read(struct rtl_file *filp, char *buf, size_t count, loff_t* ppos);//Other functions that the driver must providestatic int rt_eth_send_packet(const char *buffer, size_t size);static int eth_close(struct pci_dev *dev);static void eth_remove_one (struct pci_dev *pdev);static struct pci_dev *init_eth_device(void);static int start_up_device(struct pci_dev *dev);static void other_stuff_closing(void);//void init(void);static struct rtl_file_operations rtl_fops = {       	NULL, 	rtl_eth_read,	rtl_eth_write,	rtl_eth_ioctl,	NULL,	rtl_eth_open,	rtl_eth_release};struct rtl_file_operations *fops = &rtl_fops;static int nfilters = 0;static unsigned char ip_addr[2][4]={{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}};static int inside_the_interrupt_handler = 0, trying_to_close = 0;static sem_t eth_sem;static struct net_policy_operations eth_policy = {  FIFO_add_frame_to_buffer,  FIFO_extract_frame_of_buffer,  FIFO_initialize_rx_buffer,  FIFO_dealloc_rx_buffer,};static struct fifo_rx_buffer_t eth_rx_buffer;struct pci_dev *eth_dev;static unsigned char eth_registered = 0x00, eth_opened = 0x00;static int nonblock = 0;/*************************************************************************************//* This function is used to set an IP filter to the incoming packets. It is accessed *//* by means of ioctl. Only two IP filters are allowed.                               */  /*************************************************************************************/static int rt_eth_set_ip_filter(unsigned long ipaddr){  if(nfilters<=1){    ip_addr[nfilters][0]=ipaddr & 0x000000ff;     ip_addr[nfilters][1]= (ipaddr >> 8) & 0x000000ff;     ip_addr[nfilters][2]= (ipaddr >> 16) & 0x000000ff;     ip_addr[nfilters][3]= (ipaddr >> 24) & 0x000000ff;     nfilters++;    return 0;  }   rtl_printf("You cannot set more than 2 IP filters !!");  return -1;}/***************************************************************************************//* This function is used to get the MAC address of the ethernet card. It is accessed   *//* by means of ioctl.                                                                  *//***************************************************************************************/static int rt_eth_obtain_mac_address(unsigned char *mac){  int i;  for(i=0; i<6; i++)    mac[i]=private_data.dev_addr[i];  return 0;}/***************************************************************************************//* This function implements the read call. Makes buf to point to an internal buffer    *//* and returns the lenght of that buffer. The packet returned depends on the policy    *//* selected.                                                                           *//***************************************************************************************/static ssize_t rtl_eth_read(struct rtl_file *filp, char *buf, size_t count, loff_t* ppos){  rtl_irqstate_t flags;  int len;  char *buffer = buf;#ifdef _NO_ZERO_COPY_API_  struct memory receive_buffer;  buffer = (char *) &receive_buffer;#endif  if(!nonblock)    sem_wait(&eth_sem);  rtl_no_interrupts (flags);  len = eth_policy.extract_frame_of_buffer(&eth_rx_buffer, buffer);  rtl_restore_interrupts (flags);#ifdef _NO_ZERO_COPY_API_  memcpy(buf, receive_buffer.mem, len);#endif  return len;}/***************************************************************************************//* This function implements the ioctl call.                                            *//***************************************************************************************/static int rtl_eth_ioctl(struct rtl_file * filp, unsigned int request, unsigned long other){  switch(request) {  case 1:           /* set_ip_filter */    rt_eth_set_ip_filter(other);    break;  case 2:           /* obtain_mac_address */    rt_eth_obtain_mac_address((unsigned char *)other);    break;  }  return 0;}/***************************************************************************************//* This function implements the close call. It stalls the card and frees resources.    *//***************************************************************************************/static int rtl_eth_release (struct rtl_file *filp){  rtl_irqstate_t state;  rtl_no_interrupts(state);    eth_close(eth_dev);    eth_remove_one(eth_dev);    if(eth_opened == 0x01){    if(!nonblock)      sem_destroy(&eth_sem);    eth_policy.dealloc_rx_buffer(&eth_rx_buffer);  }    eth_opened = 0x00;  rtl_restore_interrupts(state);  return 0;}/***************************************************************************************//* This function implements the write call. It is not a blocking function, that means  *//* that writting returns inmediatly, it doesn't waits till the packet has been sent.   *//* The return value is always the size of the buffer being sent.                       *//***************************************************************************************/static ssize_t rtl_eth_write(struct rtl_file *filp, const char *buf, size_t count, loff_t* ppos){  ssize_t tmp;   rtl_irqstate_t state;  rtl_no_interrupts(state);  tmp=rt_eth_send_packet(buf,count);  rtl_restore_interrupts(state);  return tmp;}/***************************************************************************************//* This function implements the open call. It initialises the card. The card starts    *//* receiving packets.                                                                  *//***************************************************************************************/static int rtl_eth_open (struct rtl_file *filp){  if(eth_opened == 0x00){    //First enable the pci device     if((eth_dev = init_eth_device())!=NULL){      if ((filp->f_flags & O_NONBLOCK) ||(filp->f_flags & O_NDELAY))	nonblock=1;      else	sem_init(&eth_sem, 0, 0);            //Now initialize the HW      start_up_device(eth_dev);      eth_opened = 0x01;      return MAJOR_NUMBER;    }else{      rtl_printf("ERROR: Couldn't initialize device %s\n", ETH_NAME);      return -1;    }  }  rtl_printf("Device %s is already opened\n", ETH_NAME);  return -1;}/***************************************************************************************//* This function is used to initialise the pci and the buffering subsystem.            *//***************************************************************************************/static struct pci_dev *init_eth_device(void){  struct pci_dev *dev;  /* First of all, we must get a pointer to the pci_dev structure */  if((dev = rt_pci_find_device(ETH_VENDOR_ID, ETH_DEVICE_ID, NULL))== NULL)    return NULL;  eth_policy.initialize_rx_buffer(&eth_rx_buffer);  /* Let's enable the device */  if (rt_pci_enable_device(dev)){    rtl_printf("PCI ERROR: Can't enable device %s\n", ETH_NAME);    return NULL;  }  return dev;}/***************************************************************************************//* This function is used to filter only those packets that are REALLY addressed to us. *//* If it is a packet that we want, then the function unblocks the reader so he can     *//* read the packet.                                                                    *//***************************************************************************************/static int filter_incoming_packet(unsigned char *buffer, unsigned int len){  unsigned char mine = 0x01, multicast_packet= 0x01, arp_request_for_me = 0x01 ;  int i, j;  /* A NIC receives all the packets in the LAN so we will receive an interrupt for each one of those. */  /* As we only want those packets sent to us we must filter them. So, we will only receive packets   */  /* directly sent us (i.e. destination address is ours) and those ARP frames which ask for our MAC.  */  /* An ARP improvement consist on receive all ARP request packets in the LAN, so, at least, we could */  /* know the pair IP and MAC address of those computers performing the request. As most of the       */  /* frames in a LAN are ARP request frames the overhead produced by receiving all of them would be   */  /* considerable, so we won't bother with this improvement.                                          */  //Is this frame for us??  for(i=0; i<6; i++){    if(buffer[i] == private_data.dev_addr[i])      continue;    else{      mine = 0x00;      break;    }  }  if(mine == 0x01) goto accept_frame;  // Is it a multicast frame??  for(i=0; i<6; i++){    if(buffer[i] == 0xff)      continue;    else{      multicast_packet = 0x00;      break;    }  }#ifndef _RECEIVE_ALL_BROADCASTS_				        if(multicast_packet == 0x01){    // Is an ARP frame???    if((buffer[12]==0x08) && (buffer[13]==0x06)){      // It asks for my IP??      for(j=0; j<nfilters; j++){	for(i=0; i<4;i++){	  if(buffer[38+i]==ip_addr[j][i])	    continue;	  else{	    arp_request_for_me = 0x00;   	    break;	  }	}      }    }else      arp_request_for_me = 0x00;     }#endif accept_frame:  if((mine == 0x01) || ((multicast_packet==0x01) #ifndef _RECEIVE_ALL_BROADCASTS_				      			&& (arp_request_for_me==0x01)#endif						)){    rtl_irqstate_t flags;    int ret;    private_data.rx_frames_for_us++;    //Protected Section    rtl_no_interrupts (flags);    ret = eth_policy.add_frame_to_buffer((void *) &eth_rx_buffer,buffer,len);    rtl_restore_interrupts (flags);    if(!ret){      if(!nonblock)	sem_post(&eth_sem);      rtl_schedule();     }  }  return 0;}/***************************************************************************************//* This function is called when the driver module is inserted. It registers the device *//* , letting other modules to use it by means of the calls read, write, close, open    *//* and ioctl.                                                                          *//***************************************************************************************/int init_module(void){  printk("\n\n\nRT-Linux driver for the Ethernet Card %s being loaded\n\n\n", CARD_NAME);#ifdef _FAKE_DRIVER_  init();#endif  if (rtl_register_rtldev (MAJOR_NUMBER, ETH_NAME, &rtl_fops)) {    printk ("RTLinux /dev/%s: unable to get RTLinux major %d\n", ETH_NAME, MAJOR_NUMBER);    return -EIO;  }else{    printk("Registered device: /dev/%s major number %d\n",ETH_NAME, MAJOR_NUMBER);    eth_registered = 0x01;    return 0;  }}/***************************************************************************************//* This function is called when removing the driver module. It makes sure that there   *//* are no pending executions of the interrupt handler. It releases the ethernet card   *//* and frees all resources. The driver is unregistered.                                *//***************************************************************************************/void cleanup_module(void){  int inside = 1;  rtl_irqstate_t state;  if((eth_opened == 0x01) || inside_the_interrupt_handler){    trying_to_close = 1;    /* Since inside the interrupt handler there's a call to the scheduler, there may  */    /* be an execution of the interrupt handler that hasn't been completely executed. */    /* The card cannot be released in that case, so we must be sure that there is no  */    /* interrupt handler execution pending. Otherwise, that may crash the system.     */    while(inside){      rtl_no_interrupts(state);                  if(inside_the_interrupt_handler){	rtl_restore_interrupts(state);	usleep(10);      }else{	rtl_hard_disable_irq(private_data.pdev->irq);        	rtl_restore_interrupts(state);	inside = 0;      }    }      other_stuff_closing();  }  if(eth_registered == 0x01){    printk("Unregistering device /dev/%s\n",ETH_NAME);    rtl_unregister_rtldev(MAJOR_NUMBER,ETH_NAME);  }  printk("\n\n\nRT-Linux driver for the Ethernet Card %s being removed\n\n\n",CARD_NAME);}

⌨️ 快捷键说明

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