📄 rtl_posix_if.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(ð_sem); rtl_no_interrupts (flags); len = eth_policy.extract_frame_of_buffer(ð_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(ð_sem); eth_policy.dealloc_rx_buffer(ð_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(ð_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(ð_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 *) ð_rx_buffer,buffer,len); rtl_restore_interrupts (flags); if(!ret){ if(!nonblock) sem_post(ð_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 + -