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

📄 rtl_rtl8139_drv.c

📁 最新rtlinux内核源码
💻 C
📖 第 1 页 / 共 3 页
字号:
/*         8139too.c: A RealTek RTL-8139 Fast Ethernet driver for Linux.         Maintained by Jeff Garzik <jgarzik@mandrakesoft.com>        Copyright 2000,2001 Jeff Garzik         Much code comes from Donald Becker's rtl8139.c driver,        versions 1.13 and older.  This driver was originally based        on rtl8139.c version 1.07.  Header of rtl8139.c version 1.13:         -----<snip>-----                 Written 1997-2001 by Donald Becker.                This software may be used and distributed according to the                terms of the GNU General Public License (GPL), incorporated                herein by reference.  Drivers based on or derived from this                code fall under the GPL and must retain the authorship,                copyright and license notice.  This file is not a complete                program and may only be used when the entire operating                system is licensed under the GPL.                 This driver is for boards based on the RTL8129 and RTL8139                PCI ethernet chips.                 The author may be reached as becker@scyld.com, or C/O Scyld                Computing Corporation 410 Severn Ave., Suite 210 Annapolis                MD 21403                Support and updates available at                http://www.scyld.com/network/rtl8139.html                Twister-tuning table provided by Kinston                <shangh@realtek.com.tw>.         -----<snip>-----        This software may be used and distributed according to the terms        of the GNU General Public License, incorporated herein by reference.         Contributors:                 Donald Becker - he wrote the original driver, kudos to him!                (but please don't e-mail him for support, this isn't his driver)                 Tigran Aivazian - bug fixes, skbuff free cleanup                 Martin Mares - suggestions for PCI cleanup                 David S. Miller - PCI DMA and softnet updates                 Ernst Gill - fixes ported from BSD driver                 Daniel Kobras - identified specific locations of                        posted MMIO write bugginess                 Gerard Sharp - bug fix, testing and feedback                David Ford - Rx ring wrap fix                Dan DeMaggio - swapped RTL8139 cards with me, and allowed me                to find and fix a crucial bug on older chipsets.                 Donald Becker/Chris Butterworth/Marcus Westergren -                Noticed various Rx packet size-related buglets.                 Santiago Garcia Mantinan - testing and feedback                 Jens David - 2.2.x kernel backports                 Martin Dennett - incredibly helpful insight on undocumented                features of the 8139 chips                 Jean-Jacques Michel - bug fix                 Tobias Ringstr鰉 - Rx interrupt status checking suggestion                 Andrew Morton - Clear blocked signals, avoid                buffer overrun setting current->comm.        Submitting bug reports:                 "rtl8139-diag -mmmaaavvveefN" output                enable RTL8139_DEBUG below, and look at 'dmesg' or kernel log                 See 8139too.txt for more details. -----------------------------------------------------------------------------2001/09/21Comments by ShuChen Shao 1.This driver is originally based on 8139too.c version "0.9.15". 2.It has been enhanced to support RTL8139C+ PCI ethernet chips and tested in 2.4.2 kernel. 3.RTL8139C+ PCI ethernet chips is set to support C+ mode by default.  If FORCE_C_Mode below is enable, the RTL8139C+ chip will be forced to support C mode  after reboot. 4.This program can be compiled at /usr/src/linux-2.4.2/drivers/net/ using the attached Makefile.  And the object file named 8139too.o should be moved to the directory  /lib/modules/2.4.2-2/kernel/drivers/net/ -----------------------------------------------------------------------------=====================================================================================                          PORTING TO RT-LINUX===================================================================================== 15 May 2003                         ByungGi Baek <gi@realtimewave.com||weapon100@empal.com>             1. This driver is originally based on 8139too.c            2. This   file  is also based  in   one file  part  of the            RTL-lwIP TCP/IP   stack.   The  file  is: rt_3c905x_phys.c            which   author      is:       Sergio    Perez      Alca駃z            <serpeal@upvnet.upv.es>            3. This file is compiled and tested on RTL-lwIP-0.2.1            4.  Unload the original 8139  linux  driver then load this            driver. 12     January    2004            Sergio Perez Alca駃z <serpeal@upvnet.upv.es> Departamento            de Inform醫ica de Sistemas y Computadores Universidad            Polit閏nica de Valencia	    The RTL-lwIP project  has  been supported by   the Spanish	    Government     Research   Office   (CICYT)    under  grant	    TIC2002-04123-C03-03  SISTEMAS DE  TIEMPO REAL EMPOTRADOS,	    FIABLES Y  DISTRIBUIDOS  BASADOS EN  COMPONENTES  Valencia	    (Spain)	    -Removed threads  registration (to  better comply with the	    POSIX standard).            -Added  a semaphore   to block   threads  when they    are            performing a read and there are not packets available.	    -Modified to use the  new release of DIDMA (Dynamic Memory	    Allocator) now called TLSF. ===================================================================================== */#include "rtl_rtl8139_drv.h"#include "netif/net_policy/FIFO_policy.h"#include "rt_pci.h"MODULE_LICENSE("GPL");static sem_t rtl8139_sem;static struct net_policy_operations rt_rtl8139_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 rt_rtl8139_rx_buffer;#define RTL8139_MAJOR 	205#define RTL8139_NAME 	"rtl"#define RTL8139_SIGNAL 	RTL_SIGUSR1static int rt_rtl8139_read_eeprom (void *ioaddr, int location, int addr_len);static int rt_rtl8139_mdio_read (struct pci_dev *dev, int phy_id, int location);static void rt_rtl8139_mdio_write (struct pci_dev *dev, int phy_id, int location, int val);struct pci_dev *init_rtl8139_device(void);int start_up_rtl8139_device(struct pci_dev *dev);static int dev_rtl8139_open(struct pci_dev *dev);static int rt_rtl8139_open (struct rtl_file *filp);static int rt_rtl8139_release (struct rtl_file *filp);static ssize_t rt_rtl8139_write(struct rtl_file *filp, const char *buf, size_t count, loff_t* ppos);static int rt_rtl8139_ioctl(struct rtl_file * filp, unsigned int request, unsigned long other);static ssize_t rt_rtl8139_read(struct rtl_file *filp, char *buf, size_t count, loff_t* ppos);void rt_rtl8139_send_signal(void);static struct rtl_file_operations rt_rtl8139_fops = {        NULL,        rt_rtl8139_read,        rt_rtl8139_write,        rt_rtl8139_ioctl,        NULL,        rt_rtl8139_open,        rt_rtl8139_release};static int rt_rtl8139_inside_the_interrupt_handler = 0, rt_rtl8139_trying_to_close = 0;static int rt_rtl8139_interrupted = 0, rt_rtl8139_writting = 0;/* Maximum events (Rx packets, etc.) to handle at each interrupt. */static int rt_rtl8139_max_interrupt_work = 20;unsigned char rt_rtl8139_ip_addr[2][4]={{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}};                     static int rt_rtl8139_n_filters = 0;unsigned char rt_rtl8139_registered = 0x00, rt_rtl8139_opened = 0x00, rt_rtl8139_sended = 0x01;struct pci_dev *rtl8139dev;struct rtl8139_private rtl_8139_tp;  /***************************************************************************************/int rt_rtl8139_obtain_mac_address(unsigned char *mac){  	int i;  	for(i=0; i<6; i++)    		mac[i]=rtl_8139_tp.dev_addr[i];  	return 0;}/*************************************************************************************/int rt_rtl8139_set_ip_filter(long ipaddr){  	if(rt_rtl8139_n_filters<=1){    		rt_rtl8139_ip_addr[rt_rtl8139_n_filters][0]=ipaddr & 0x000000ff; rt_rtl8139_ip_addr[rt_rtl8139_n_filters][1]= (ipaddr >> 8) & 0x000000ff;    		rt_rtl8139_ip_addr[rt_rtl8139_n_filters][2]= (ipaddr >> 16) & 0x000000ff; rt_rtl8139_ip_addr[rt_rtl8139_n_filters][3]= (ipaddr >> 24) & 0x000000ff;    		rt_rtl8139_n_filters++;    		return 0;  	}   	rtl_printf("You cannot set more than 2 IP filters !!");  	return -1;}/* The data sheet doesn't describe the Rx ring at all, so I'm guessing at the   field alignments and semantics. */static void rt_rtl8139_rx_interrupt (struct pci_dev *dev){        unsigned char *rx_ring;        u16 cur_rx;  	unsigned char mine = 0x01;   	unsigned char multicast_packet= 0x01;  	unsigned char arp_request_for_me = 0x01 ;  	void *ioaddr = rtl_8139_tp.mmio_addr;	int i, j;        rx_ring = rtl_8139_tp.rx_ring;        cur_rx = rtl_8139_tp.cur_rx;        while ((RTL_R8 (ChipCmd) & RxBufEmpty) == 0) {                int ring_offset = cur_rx % RX_BUF_LEN;                u32 rx_status;                unsigned int rx_size;                unsigned int pkt_size;                unsigned char *skb;                 /* read size+status of next frame from DMA ring buffer */                rx_status = le32_to_cpu (*(u32 *) (rx_ring + ring_offset));                rx_size = rx_status >> 16;                pkt_size = rx_size - 4;                if (rx_size == 0xfff0)                        break;                if ((rx_size > (MAX_ETH_FRAME_SIZE+4)) || (!(rx_status & RxStatusOK))) {                        return;                }				skb = &rx_ring[ring_offset+4]; 		rtl_8139_tp.stats.rx_bytes += pkt_size;		rtl_8139_tp.stats.rx_packets++;		  		for(i=0; i<6; i++){    			if(skb[i] == rtl_8139_tp.dev_addr[i]) {      				continue;    			} else{      				mine = 0x00;      				break;    			}  		}  		if(mine == 0x01) {    		   goto accept_frame;		}  		if((skb[12]==0x08) && (skb[13]==0x06)){    		    for(j=0; j<rt_rtl8139_n_filters; j++){      			for(i=0; i<4;i++){        			if(skb[38+i]==rt_rtl8139_ip_addr[j][i]) {          				continue;        			} else{          				arp_request_for_me = 0x00;          				break;        			}      			}    		    }  		}else    		arp_request_for_me = 0x00;		  		for(i=0; i<6; i++){    			if(skb[i] == 0xff)      				continue;    			else{      				multicast_packet = 0x00;      				break;    			}  		}accept_frame:  		if((mine == 0x01) || ((multicast_packet==0x01) && (arp_request_for_me==0x01))){     		   rtl_8139_tp.rx_frames_for_us++;    		   if(rt_rtl8139_policy.add_frame_to_buffer(&rt_rtl8139_rx_buffer,skb,pkt_size)== 0){		     sem_post(&rtl8139_sem);		     rtl_schedule();    		   }		}                 cur_rx = (cur_rx + rx_size + 4 + 3) & ~3;                RTL_W16_F (RxBufPtr, cur_rx - 16);  		mine = 0x01;   		multicast_packet= 0x01;  		arp_request_for_me = 0x01 ;        }        rtl_8139_tp.cur_rx = cur_rx;}               /***************************************************************************************/static int rt_rtl8139_send_packet(const char *buffer, size_t size){  	unsigned char *buff;  	void *ioaddr = rtl_8139_tp.mmio_addr;  	int entry, len = 0;   	rt_rtl8139_writting = 1;  	/* Calculate the next Tx descriptor entry. */  	entry = rtl_8139_tp.cur_tx % NUM_TX_DESC;  	buff = rtl_8139_tp.tx_buf[entry];  	if(buff) {		memcpy(buff, buffer, size);		len = sizeof(buff);  	}  	rtl_8139_tp.tx_info[entry].mapping = pci_map_single (rtl_8139_tp.pci_dev, rtl_8139_tp.tx_buf[entry], size, PCI_DMA_TODEVICE);  	RTL_W32 (TxAddr0 + (entry * 4), rtl_8139_tp.tx_info[entry].mapping);  	rtl_8139_tp.cur_tx++;                                                                                  	/* Note: the chip doesn't have auto-pad! */  	RTL_W32 (TxStatus0 + (entry * sizeof (u32)),                 rtl_8139_tp.tx_flag | (size >= ETH_ZLEN ? size : ETH_ZLEN));  	rt_rtl8139_writting = 0;   	return size;                                                                                        }static void rt_rtl8139_tx_interrupt (struct pci_dev *dev){  	void *ioaddr = rtl_8139_tp.mmio_addr;        unsigned long dirty_tx, tx_left;          dirty_tx = rtl_8139_tp.dirty_tx;        tx_left = rtl_8139_tp.cur_tx - dirty_tx;        while (tx_left > 0) {                int entry = dirty_tx % NUM_TX_DESC;                int txstatus;                 txstatus = RTL_R32 (TxStatus0 + (entry * sizeof (u32)));                 if (!(txstatus & (TxStatOK | TxUnderrun | TxAborted)))                        break;  /* It still hasn't been Txed */                /* Note: TxCarrierLost is always asserted at 100mbps. */                if (txstatus & (TxOutOfWindow | TxAborted)) {                        /* There was an major error, log it. */                        rtl_printf ("Transmit error, Tx status %8.8x.\n",                                 txstatus);                        rtl_8139_tp.stats.tx_errors++;                        if (txstatus & TxAborted) {                                rtl_8139_tp.stats.tx_aborted_errors++;                                RTL_W32 (TxConfig, TxClearAbt | (TX_DMA_BURST << TxDMAShift));                        }                        if (txstatus & TxCarrierLost)                                rtl_8139_tp.stats.tx_carrier_errors++;                        if (txstatus & TxOutOfWindow)                                rtl_8139_tp.stats.tx_window_errors++;#ifdef ETHER_STATS                        if ((txstatus & 0x0f000000) == 0x0f000000)                                rtl_8139_tp.stats.collisions16++;#endif                } else {                        if (txstatus & TxUnderrun) {                                /* Add 64 to the Tx FIFO threshold. */                                if (rtl_8139_tp.tx_flag < 0x00300000)                                        rtl_8139_tp.tx_flag += 0x00020000;                                rtl_8139_tp.stats.tx_fifo_errors++;                        }                        rtl_8139_tp.stats.collisions += (txstatus >> 24) & 15;                        rtl_8139_tp.stats.tx_bytes += txstatus & 0x7ff;                        rtl_8139_tp.stats.tx_packets++;                }                /* Free the original skb. */                if (rtl_8139_tp.tx_info[entry].mapping != 0) {                        pci_unmap_single(rtl_8139_tp.pci_dev,                                         rtl_8139_tp.tx_info[entry].mapping,                                         rtl_8139_tp.tx_info[entry].skb->len,                                         PCI_DMA_TODEVICE);                        rtl_8139_tp.tx_info[entry].mapping = 0;                }                rtl_8139_tp.tx_info[entry].skb = NULL;                 dirty_tx++;                tx_left--;        } #ifdef RTL8139_DEBUG        if (rtl_8139_tp.cur_tx - dirty_tx > NUM_TX_DESC) {                printk (KERN_ERR "%s: Out-of-sync dirty pointer, %ld vs. %ld.\n",                        dev->name, dirty_tx, rtl_8139_tp.cur_tx);                dirty_tx += NUM_TX_DESC;        }#endif /* RTL8139_NDEBUG */        /* only wake the queue if we did work, and the queue is stopped */        if (rtl_8139_tp.dirty_tx != dirty_tx) {                rtl_8139_tp.dirty_tx = dirty_tx;        }}                                                                         /* The interrupt handler does all of the Rx thread work and cleans up   after the Tx thread. */unsigned int  rt_rtl8139_interrupt (unsigned int irq, struct pt_regs *regs){

⌨️ 快捷键说明

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