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

📄 rtl_e100.c

📁 最新rtlinux内核源码
💻 C
📖 第 1 页 / 共 5 页
字号:
 /*******************************************************************************    Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.    This program is free software; you can redistribute it and/or modify it   under the terms of the GNU General Public License as published by the Free   Software Foundation; either version 2 of the License, or (at your option)   any later version.    This program 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 General Public License for   more details.    You should have received a copy of the GNU General Public License along with  this program; if not, write to the Free Software Foundation, Inc., 59   Temple Place - Suite 330, Boston, MA  02111-1307, USA.    The full GNU General Public License is included in this distribution in file called LICENSE.    Contact Information:  Linux NICS <linux.nics@intel.com>  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497*******************************************************************************//***********************************************************************                                                                     ** INTEL CORPORATION                                                   **                                                                     ** This software is supplied under the terms of the license included   ** above.  All use of this driver must be in accordance with the terms ** of that license.                                                    **                                                                     ** Module Name:  e100_main.c                                           **                                                                     ** Abstract:     Functions for the driver entry points like load,      **               unload, open and close. All board specific calls made **               by the network interface section of the driver.       **                                                                     ** Environment:  This file is intended to be specific to the Linux     **               operating system.                                     **                                                                     ***********************************************************************//* Change Log *  * 2.2.21	02/11/03 * o Removed marketing brand strings. Instead, Using generic string  *   "Intel(R) PRO/100 Network Connection" for all adapters. * o Implemented ethtool -S option * o Strip /proc/net/PRO_LAN_Adapters files for kernel driver * o Bug fix: Read wrong byte in EEPROM when offset is odd number * o Bug fix: PHY loopback test fails on ICH devices * o Bug fix: System panic on e100_close when repeating Hot Remove and  *   Add in a team * o Bug fix: Linux Bonding driver claims adapter's link loss because of *   not updating last_rx field * o Bug fix: e100 does not check validity of MAC address * o New feature: added ICH5 support *  * 2.1.27	11/20/02 *   o Bug fix: Device command timeout due to SMBus processing during init *   o Bug fix: Not setting/clearing I (Interrupt) bit in tcb correctly *   o Bug fix: Not using EEPROM WoL setting as default in ethtool *   o Bug fix: Not able to set autoneg on using ethtool when interface down *   o Bug fix: Not able to change speed/duplex using ethtool/mii *     when interface up *   o Bug fix: Ethtool shows autoneg on when forced to 100/Full *   o Bug fix: Compiler error when CONFIG_PROC_FS not defined *   o Bug fix: 2.5.44 e100 doesn't load with preemptive kernel enabled *     (sleep while holding spinlock) *   o Bug fix: 2.1.24-k1 doesn't display complete statistics *   o Bug fix: System panic due to NULL watchdog timer dereference during *     ifconfig down, rmmod and insmod * * 2.1.24       10/7/02 **********************************************************************Changelog: June 29,2004: The file is changed by, Deyu Liu,to port the e100 adapter to RTLinux-GPLComputer Science Department, The Florida State University,USA<bullleo2003@yahoo.com>CHANGELOG:    November      25,    2004    Sergio    P閞ez     Alca駃z(serpeal@upvnet.upv.es):   o  Bug fix: the  use of the function schedule_timeout(HZ  / 50 + 1)   can cause an  exception in the  RTLinux context. It  should only be   used in the Linux context. It's  been replaced with usleep().      o Bug   fix: the use  of the  function set_current_state()  is only   needed in the  Linux driver.  Using it in  the  RTLinux context may   cause Linux to be hanged.CHANGELOG:     December    1,      2004     Sergio     P閞ez   Alca駃z(serpeal@upvnet.upv.es):  o Driver modified to provide the O_NOBLOCK access mode (non-blocking   access).   o Driver  modified  to  support  the  zero  copy  technique  or  not,   depending on the options set in the reddopts.h.  o Driver modified to support the FAKE architecture  described in the  reddoopts.h***********************************************************************/ #include <linux/config.h>#include <net/checksum.h>#include <linux/tcp.h>#include <linux/udp.h>#include "drivers/rtl_e100main_drv.h"#include "drivers/rtl_e100_ucode.h"#include "drivers/rtl_e100_config.h"#include "drivers/rtl_e100_phy.h"MODULE_AUTHOR("Intel Corporation, <linux.nics@intel.com>");MODULE_DESCRIPTION("Intel(R) PRO/100 Network Driver");MODULE_LICENSE("GPL");static int rt_e100_interrupted = 0, rt_e100_writting = 0;extern void e100_force_speed_duplex_to_phy(void);static void e100_get_speed_duplex_caps(void);#define E100_EEPROM_MAGIC 0x1234extern void e100_config_wol(void);/* Global Data structures and variables */char e100_copyright[] __devinitdata = "Copyright (c) 2003 Intel Corporation";char e100_driver_version[]="2.2.21-k1";const char *e100_full_driver_name = "Intel(R) PRO/100 Network Driver";char e100_short_driver_name[] = "e100";static int e100nics = 0;#ifdef CONFIG_PM/*struct notifier_block e100_notifier_reboot = {        .notifier_call  = e100_notify_reboot,        .next           = NULL,        .priority       = 0	};*/#endif/*********************************************************************//*! This is a GCC extension to ANSI C. *  See the item "Labeled Elements in Initializers" in the section *  "Extensions to the C Language Family" of the GCC documentation. *********************************************************************/#define E100_PARAM_INIT { [0 ... E100_MAX_NIC] = -1 }/* All parameters are treated the same, as an integer array of values. * This macro just reduces the need to repeat the same declaration code * over and over (plus this helps to avoid typo bugs). */#define E100_PARAM(X, S)                                        \        static const int X[E100_MAX_NIC + 1] = E100_PARAM_INIT; \        MODULE_PARM(X, "1-" __MODULE_STRING(E100_MAX_NIC) "i"); \        MODULE_PARM_DESC(X, S);/* ====================================================================== */static int e100_open(struct pci_dev *);static int e100_found1(struct pci_dev *pcid);static inline void e100_tx_skb_free(tcb_t *tcb);static inline struct rx_list_elem *e100_get_rx_struct(void);static unsigned char e100_init(void);void e100_isolate_driver(void);static unsigned int e100intr(unsigned int, struct pt_regs *);static void rt_e100_print_brd_conf(void);static int e100_pci_setup(struct pci_dev *);static u8 e100_sw_init(void);static void e100_tco_workaround(void);static unsigned char e100_alloc_space(void);static void e100_dealloc_space(void);static int e100_alloc_tcb_pool(void);static void e100_setup_tcb_pool(tcb_t *, unsigned int);static void e100_free_tcb_pool(void);static int e100_alloc_rfd_pool(void);static void e100_free_rfd_pool(void);static void e100_rd_eaddr(void);static void e100_rd_pwa_no(void);extern u16 e100_eeprom_read( u16);extern void e100_eeprom_write_block( u16, u16 *, u16);extern u16 e100_eeprom_size(void);u16 e100_eeprom_calculate_chksum(void);static unsigned char e100_clr_cntrs(void);static unsigned char e100_load_microcode(void);static unsigned char e100_hw_init(void);static unsigned char e100_setup_iaaddr( u8 *);static void e100_start_ru(void);static void e100_check_options(int board);static void e100_set_int_option(int *, int, int, int, int, char *);static void e100_set_bool_option(int, u32, int,				 char *);unsigned char e100_wait_exec_cmplx( u32, u8, u8);void e100_exec_cmplx( u32, u8);static inline tcb_t *e100_prepare_xmit_buff(const char *buffer, size_t size);/***************************************************************************************//* This function is called in the cleanup_module function, and it must do other stuff  *//* not done in the cleanup_module function in order to "close" the driver. In some     *//* implementations this function could be empty.                                       *//***************************************************************************************/static void other_stuff_closing(void){}/***************************************************************************************//* This function is used to send a packet. It writes into the internal buffers of the  *//* card.                                                                               *//***************************************************************************************/static int rt_eth_send_packet(const char *buffer, size_t size){  rt_e100_writting = 1;  e100_prepare_xmit_buff(buffer,size);  private_data.cur_tx++;  rt_e100_writting = 0;  return size;}/***************************************************************************************//* This function does internal initialisations of the card. It writes into internal    *//* registers and checks the card capabilities.                                         *//***************************************************************************************/int start_up_device(struct pci_dev *dev){  int rc=0;  rc=e100_found1(dev);return rc;}/** * e100_get_rx_struct - retrieve cell to hold skb buff from the pool * @private_data: atapter's private data struct * * Returns the new cell to hold sk_buff or %NULL. */static inline struct rx_list_elem *e100_get_rx_struct(){	struct rx_list_elem *rx_struct = NULL;	if (!list_empty(&(private_data.rx_struct_pool))) {		rx_struct = list_entry(private_data.rx_struct_pool.next,				       struct rx_list_elem, list_elem);		list_del(&(rx_struct->list_elem));	}	return rx_struct;}/** * e100_alloc_skb - allocate an skb for the adapter * @private_data: atapter's private data struct * * Allocates skb with enough room for rfd, and data, and reserve non-data space. * Returns the new cell with sk_buff or %NULL. */static inline struct rx_list_elem *e100_alloc_skb(void){	unsigned char *new_skb;	u32 skb_size = sizeof (rfd_t);	struct rx_list_elem *rx_struct;	new_skb = (unsigned char *) rtl_malloc(skb_size);	if (new_skb) {		/* The IP data should be 		   DWORD aligned. since the ethernet header is 14 bytes long, 		   we need to reserve 2 extra bytes so that the TCP/IP headers		   will be DWORD aligned. modified		skb_reserve(new_skb, 2);*/		if ((rx_struct = e100_get_rx_struct()) == NULL)			goto err;		rx_struct->skb = new_skb;		rx_struct->dma_addr = pci_map_single(private_data.pdev, new_skb, sizeof (rfd_t),PCI_DMA_FROMDEVICE);		if (!rx_struct->dma_addr)			goto err;		/* reserve the header*/		rx_struct->skb += private_data.rfd_size;		return rx_struct;	} else {		return NULL;	}err:	return NULL;}/** * e100_add_skb_to_end - add an skb to the end of our rfd list * @private_data: atapter's private data struct * @rx_struct: rx_list_elem with the new skb * * Adds a newly allocated skb to the end of our rfd list. */inline voide100_add_skb_to_end(struct rx_list_elem *rx_struct){	rfd_t *rfdn;		/* The new rfd */	rfd_t *rfd;		/* The old rfd */	struct rx_list_elem *rx_struct_last;	rfdn = RFD_POINTER(rx_struct->skb, private_data);	rfdn->rfd_header.cb_status = 0;	/*indicate the last RFD*/	rfdn->rfd_header.cb_cmd = __constant_cpu_to_le16(RFD_EL_BIT);	rfdn->rfd_act_cnt = 0;	rfdn->rfd_sz = __constant_cpu_to_le16(RFD_DATA_SIZE);	/*for the last RFD, wrap around*/	if (private_data.skb_req==1)	  put_unaligned(cpu_to_le32(((struct rx_list_elem *)(private_data.active_rx_list.next))->dma_addr),			((u32 *) (&(rfdn->rfd_header.cb_lnk_ptr))));	pci_dma_sync_single(private_data.pdev, rx_struct->dma_addr, private_data.rfd_size,			    PCI_DMA_TODEVICE);	if (!list_empty(&(private_data.active_rx_list))) {		rx_struct_last = list_entry(private_data.active_rx_list.prev,					    struct rx_list_elem, list_elem);		rfd = RFD_POINTER(rx_struct_last->skb, private_data);		pci_dma_sync_single(private_data.pdev, rx_struct_last->dma_addr,				    4, PCI_DMA_FROMDEVICE);		put_unaligned(cpu_to_le32(rx_struct->dma_addr),			      ((u32 *) (&(rfd->rfd_header.cb_lnk_ptr))));		pci_dma_sync_single(private_data.pdev, rx_struct_last->dma_addr,				    8, PCI_DMA_TODEVICE);		rfd->rfd_header.cb_cmd &=			__constant_cpu_to_le16((u16) ~RFD_EL_BIT);		pci_dma_sync_single(private_data.pdev, rx_struct_last->dma_addr,				    4, PCI_DMA_TODEVICE);	}	list_add_tail(&(rx_struct->list_elem), &(private_data.active_rx_list));}static inline voide100_alloc_skbs(void){	for (; private_data.skb_req > 0; private_data.skb_req--) {		struct rx_list_elem *rx_struct;		if ((rx_struct = e100_alloc_skb()) == NULL)			return;		e100_add_skb_to_end( rx_struct);	}}void e100_tx_srv(void);u32 e100_rx_srv(void);void e100_clear_pools(void);static void e100_clear_structs(struct pci_dev *);E100_PARAM(TxDescriptors, "Number of transmit descriptors");E100_PARAM(RxDescriptors, "Number of receive descriptors");E100_PARAM(XsumRX, "Disable or enable Receive Checksum offload");E100_PARAM(e100_speed_duplex, "Speed and Duplex settings");E100_PARAM(ucode, "Disable or enable microcode loading");E100_PARAM(ber, "Value for the BER correction algorithm");E100_PARAM(flow_control, "Disable or enable Ethernet PAUSE frames processing");E100_PARAM(IntDelay, "Value for CPU saver's interrupt delay");E100_PARAM(BundleSmallFr, "Disable or enable interrupt bundling of small frames");E100_PARAM(BundleMax, "Maximum number for CPU saver's packet bundling");E100_PARAM(IFS, "Disable or enable the adaptive IFS algorithm");/** * e100_exec_cmd - issue a comand * @private_data: atapter's private data struct * @scb_cmd_low: the command that is to be issued * * This general routine will issue a command to the e100. */static inline voide100_exec_cmd(u8 cmd_low){	writeb(cmd_low, &(private_data.scb->scb_cmd_low));	readw(&(private_data.scb->scb_status));	}/** * e100_wait_scb - wait for SCB to clear * @private_data: atapter's private data struct * * This routine checks to see if the e100 has accepted a command. * It does so by checking the command field in the SCB, which will * be zeroed by the e100 upon accepting a command.  The loop waits * for up to 1 millisecond for command acceptance. * * Returns: *      true if the SCB cleared within 1 millisecond. *      false if it didn't clear within 1 millisecond */unsigned chare100_wait_scb(){	int i;	/* loop on the scb for a few times */	for (i = 0; i < 100; i++) {		if (!readb(&private_data.scb->scb_cmd_low))			return true;		cpu_relax();	}	/* it didn't work. do it the slow way using udelay()s */	for (i = 0; i < E100_MAX_SCB_WAIT; i++) {		if (!readb(&private_data.scb->scb_cmd_low))			return true;		cpu_relax();		udelay(1);	}	return false;}/** * e100_wait_exec_simple - issue a command * @private_data: atapter's private data struct * @scb_cmd_low: the command that is to be issued * * This general routine will issue a command to the e100 after waiting for * the previous command to finish. * * Returns: *      true if the command was issued to the chip successfully *      false if the command was not issued to the chip */inline unsigned chare100_wait_exec_simple(u8 scb_cmd_low){  /*wait one scb command to be ACKed*/	if (!e100_wait_scb()) {		rtl_printf(KERN_DEBUG "e100: e100_wait_exec_simple: failed\n");#ifdef E100_CU_DEBUG		

⌨️ 快捷键说明

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