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

📄 tlan.c

📁 linux下从网卡远程启动
💻 C
📖 第 1 页 / 共 4 页
字号:
#define EB51#ifdef EB50#define __unused __attribute__((unused))#endif/****************************************************************************    tlan.c -- Etherboot device driver for the Texas Instruments ThunderLAN*    Written 2003-2003 by Timothy Legge <tlegge@rogers.com>**    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., 675 Mass Ave, Cambridge, MA 02139, USA.**    Portions of this code based on:*	lan.c: Linux ThunderLan Driver:**	by James Banks**  	(C) 1997-1998 Caldera, Inc.*	(C) 1998 James Banks*	(C) 1999-2001 Torben Mathiasen*	(C) 2002 Samuel Chessman**    REVISION HISTORY:*    ================*    v1.0	07-08-2003	timlegge	Initial not quite working version*    v1.1	07-27-2003	timlegge	Sync 5.0 and 5.1 versions*    v1.2	08-19-2003	timlegge	Implement Multicast Support*    v1.3	08-23-2003	timlegge	Fix the transmit Function*    v1.4	01-17-2004	timlegge	Initial driver output cleanup    *    *    Indent Options: indent -kr -i8***************************************************************************//* to get some global routines like printf */#include "etherboot.h"/* to get the interface to the body of the program */#include "nic.h"/* to get the PCI support functions, if this is a PCI NIC */#include "pci.h"#include "timer.h"#include "tlan.h"#define drv_version "v1.4"#define drv_date "01-17-2004"/* NIC specific static variables go here */#define HZ 100#define TX_TIME_OUT	  (6*HZ)#ifdef EB50#define	cpu_to_le32(val) (val)#define	le32_to_cpu(val) (val)#define	virt_to_bus(x) ((unsigned long) x)#define	bus_to_virt(x) ((unsigned long) x)#endif/* Condensed operations for readability. */#define virt_to_le32desc(addr)  cpu_to_le32(virt_to_bus(addr))#define le32desc_to_virt(addr)  bus_to_virt(le32_to_cpu(addr))static void TLan_ResetLists(struct nic *nic __unused);static void TLan_ResetAdapter(struct nic *nic __unused);static void TLan_FinishReset(struct nic *nic __unused);static void TLan_EeSendStart(u16);static int TLan_EeSendByte(u16, u8, int);static void TLan_EeReceiveByte(u16, u8 *, int);static int TLan_EeReadByte(u16 io_base, u8, u8 *);static void TLan_PhyDetect(struct nic *nic);static void TLan_PhyPowerDown(struct nic *nic);static void TLan_PhyPowerUp(struct nic *nic);static void TLan_SetMac(struct nic *nic __unused, int areg, char *mac);static void TLan_PhyReset(struct nic *nic);static void TLan_PhyStartLink(struct nic *nic);static void TLan_PhyFinishAutoNeg(struct nic *nic);#ifdef MONITORstatic void TLan_PhyMonitor(struct nic *nic);#endifstatic void refill_rx(struct nic *nic __unused);static int TLan_MiiReadReg(struct nic *nic __unused, u16, u16, u16 *);static void TLan_MiiSendData(u16, u32, unsigned);static void TLan_MiiSync(u16);static void TLan_MiiWriteReg(struct nic *nic __unused, u16, u16, u16);const char *media[] = {	"10BaseT-HD ", "10BaseT-FD ", "100baseTx-HD ",	"100baseTx-FD", "100baseT4", 0};/* This much match tlan_pci_tbl[]!  */enum tlan_nics {	NETEL10 = 0, NETEL100 = 1, NETFLEX3I = 2, THUNDER = 3, NETFLEX3B =	    4, NETEL100PI = 5,	NETEL100D = 6, NETEL100I = 7, OC2183 = 8, OC2325 = 9, OC2326 =	    10, NETELLIGENT_10_100_WS_5100 = 11,	NETELLIGENT_10_T2 = 12};struct pci_id_info {	const char *name;	int nic_id;	struct match_info {		u32 pci, pci_mask, subsystem, subsystem_mask;		u32 revision, revision_mask;	/* Only 8 bits. */	} id;	u32 flags;	u16 addrOfs;		/* Address Offset */};static struct pci_id_info tlan_pci_tbl[] = {	{"Compaq Netelligent 10 T PCI UTP", NETEL10,	 {0xae340e11, 0xffffffff, 0, 0, 0, 0},	 TLAN_ADAPTER_ACTIVITY_LED, 0x83},	{"Compaq Netelligent 10/100 TX PCI UTP", NETEL100,	 {0xae320e11, 0xffffffff, 0, 0, 0, 0},	 TLAN_ADAPTER_ACTIVITY_LED, 0x83},	{"Compaq Integrated NetFlex-3/P", NETFLEX3I,	 {0xae350e11, 0xffffffff, 0, 0, 0, 0},	 TLAN_ADAPTER_NONE, 0x83},	{"Compaq NetFlex-3/P", THUNDER,	 {0xf1300e11, 0xffffffff, 0, 0, 0, 0},	 TLAN_ADAPTER_UNMANAGED_PHY | TLAN_ADAPTER_BIT_RATE_PHY, 0x83},	{"Compaq NetFlex-3/P", NETFLEX3B,	 {0xf1500e11, 0xffffffff, 0, 0, 0, 0},	 TLAN_ADAPTER_NONE, 0x83},	{"Compaq Netelligent Integrated 10/100 TX UTP", NETEL100PI,	 {0xae430e11, 0xffffffff, 0, 0, 0, 0},	 TLAN_ADAPTER_ACTIVITY_LED, 0x83},	{"Compaq Netelligent Dual 10/100 TX PCI UTP", NETEL100D,	 {0xae400e11, 0xffffffff, 0, 0, 0, 0},	 TLAN_ADAPTER_NONE, 0x83},	{"Compaq Netelligent 10/100 TX Embedded UTP", NETEL100I,	 {0xb0110e11, 0xffffffff, 0, 0, 0, 0},	 TLAN_ADAPTER_NONE, 0x83},	{"Olicom OC-2183/2185", OC2183,	 {0x0013108d, 0xffffffff, 0, 0, 0, 0},	 TLAN_ADAPTER_USE_INTERN_10, 0x83},	{"Olicom OC-2325", OC2325,	 {0x0012108d, 0xffffffff, 0, 0, 0, 0},	 TLAN_ADAPTER_UNMANAGED_PHY, 0xF8},	{"Olicom OC-2326", OC2326,	 {0x0014108d, 0xffffffff, 0, 0, 0, 0},	 TLAN_ADAPTER_USE_INTERN_10, 0xF8},	{"Compaq Netelligent 10/100 TX UTP", NETELLIGENT_10_100_WS_5100,	 {0xb0300e11, 0xffffffff, 0, 0, 0, 0},	 TLAN_ADAPTER_ACTIVITY_LED, 0x83},	{"Compaq Netelligent 10 T/2 PCI UTP/Coax", NETELLIGENT_10_T2,	 {0xb0120e11, 0xffffffff, 0, 0, 0, 0},	 TLAN_ADAPTER_NONE, 0x83},	{"Compaq NetFlex-3/E", 0,	/* EISA card */	 {0, 0, 0, 0, 0, 0},	 TLAN_ADAPTER_ACTIVITY_LED | TLAN_ADAPTER_UNMANAGED_PHY |	 TLAN_ADAPTER_BIT_RATE_PHY, 0x83},	{"Compaq NetFlex-3/E", 0,	/* EISA card */	 {0, 0, 0, 0, 0, 0},	 TLAN_ADAPTER_ACTIVITY_LED, 0x83},	{0, 0,	 {0, 0, 0, 0, 0, 0},	 0, 0},};struct TLanList {	u32 forward;	u16 cStat;	u16 frameSize;	struct {		u32 count;		u32 address;	} buffer[TLAN_BUFFERS_PER_LIST];};struct TLanList tx_ring[TLAN_NUM_TX_LISTS];static unsigned char txb[TLAN_MAX_FRAME_SIZE * TLAN_NUM_TX_LISTS];struct TLanList rx_ring[TLAN_NUM_RX_LISTS];static unsigned char rxb[TLAN_MAX_FRAME_SIZE * TLAN_NUM_RX_LISTS];typedef u8 TLanBuffer[TLAN_MAX_FRAME_SIZE];int chip_idx;/****************************************************************** TLAN Private Information Structure*****************************************************************/struct tlan_private {	unsigned short vendor_id;	/* PCI Vendor code */	unsigned short dev_id;	/* PCI Device code */	const char *nic_name;	u8 *padBuffer;	u8 *rxBuffer;	struct TLanList *rx_head_desc;	u32 rxHead;	u32 rxTail;	u32 rxEocCount;	unsigned int cur_rx, dirty_rx;	/* Producer/consumer ring indicies */	unsigned int cur_tx, dirty_tx;	unsigned rx_buf_sz;	/* Based on mtu + Slack */	struct TLanList *txList;	struct TLanList *rxList;	u8 *txBuffer;	u32 txHead;	u32 txInProgress;	u32 txTail;	int eoc;	u32 txBusyCount;	u32 phyOnline;	u32 timerSetAt;	u32 timerType;	u32 adapterRev;	u32 aui;	u32 debug;	u32 duplex;	u32 phy[2];	u32 phyNum;	u32 speed;	u8 tlanRev;	u8 tlanFullDuplex;	char devName[8];	u8 link;	u8 is_eisa;	u8 neg_be_verbose;} TLanPrivateInfo;static struct tlan_private *priv;u32 BASE;/****************************************************************	TLan_ResetLists**	Returns:*		Nothing*	Parms:*		dev	The device structure with the list*			stuctures to be reset.**	This routine sets the variables associated with managing*	the TLAN lists to their initial values.***************************************************************/void TLan_ResetLists(struct nic *nic __unused){	int i;	struct TLanList *list;	priv->txHead = 0;	priv->txTail = 0;	for (i = 0; i < TLAN_NUM_TX_LISTS; i++) {		list = &tx_ring[i];		list->cStat = TLAN_CSTAT_UNUSED;/*		list->buffer[0].address = 0; */		list->buffer[0].address = virt_to_bus(txb + 				(i * TLAN_MAX_FRAME_SIZE)); 		list->buffer[2].count = 0;		list->buffer[2].address = 0;		list->buffer[9].address = 0;/*		list->forward = 0; */	}	priv->cur_rx = 0;	priv->rx_buf_sz = (TLAN_MAX_FRAME_SIZE);	priv->rx_head_desc = &rx_ring[0];	/* Initialize all the Rx descriptors */	for (i = 0; i < TLAN_NUM_RX_LISTS; i++) {		rx_ring[i].forward = virt_to_le32desc(&rx_ring[i + 1]);		rx_ring[i].cStat = TLAN_CSTAT_READY;		rx_ring[i].frameSize = TLAN_MAX_FRAME_SIZE;		rx_ring[i].buffer[0].count =		    TLAN_MAX_FRAME_SIZE | TLAN_LAST_BUFFER;		rx_ring[i].buffer[0].address =		    virt_to_le32desc(&rxb[i * TLAN_MAX_FRAME_SIZE]);		rx_ring[i].buffer[1].count = 0;		rx_ring[i].buffer[1].address = 0;	}	/* Mark the last entry as wrapping the ring */	rx_ring[i - 1].forward = virt_to_le32desc(&rx_ring[0]);	priv->dirty_rx = (unsigned int) (i - TLAN_NUM_RX_LISTS);} /* TLan_ResetLists *//****************************************************************	TLan_Reset**	Returns:*		0*	Parms:*		dev	Pointer to device structure of adapter*			to be reset.**	This function resets the adapter and it's physical*	device.  See Chap. 3, pp. 9-10 of the "ThunderLAN*	Programmer's Guide" for details.  The routine tries to*	implement what is detailed there, though adjustments*	have been made.***************************************************************/void TLan_ResetAdapter(struct nic *nic __unused){	int i;	u32 addr;	u32 data;	u8 data8;	priv->tlanFullDuplex = FALSE;	priv->phyOnline = 0;/*  1.	Assert reset bit. */	data = inl(BASE + TLAN_HOST_CMD);	data |= TLAN_HC_AD_RST;	outl(data, BASE + TLAN_HOST_CMD);	udelay(1000);/*  2.	Turn off interrupts. ( Probably isn't necessary ) */	data = inl(BASE + TLAN_HOST_CMD);	data |= TLAN_HC_INT_OFF;	outl(data, BASE + TLAN_HOST_CMD);/*  3.	Clear AREGs and HASHs. */	for (i = TLAN_AREG_0; i <= TLAN_HASH_2; i += 4) {		TLan_DioWrite32(BASE, (u16) i, 0);	}/*  4.	Setup NetConfig register. */	data =	    TLAN_NET_CFG_1FRAG | TLAN_NET_CFG_1CHAN | TLAN_NET_CFG_PHY_EN;	TLan_DioWrite16(BASE, TLAN_NET_CONFIG, (u16) data);/*  5.	Load Ld_Tmr and Ld_Thr in HOST_CMD. */	outl(TLAN_HC_LD_TMR | 0x3f, BASE + TLAN_HOST_CMD);	outl(TLAN_HC_LD_THR | 0x0, BASE + TLAN_HOST_CMD);/*  6.	Unreset the MII by setting NMRST (in NetSio) to 1. */	outw(TLAN_NET_SIO, BASE + TLAN_DIO_ADR);	addr = BASE + TLAN_DIO_DATA + TLAN_NET_SIO;	TLan_SetBit(TLAN_NET_SIO_NMRST, addr);/*  7.	Setup the remaining registers. */	if (priv->tlanRev >= 0x30) {		data8 = TLAN_ID_TX_EOC | TLAN_ID_RX_EOC;		TLan_DioWrite8(BASE, TLAN_INT_DIS, data8);	}	TLan_PhyDetect(nic);	data = TLAN_NET_CFG_1FRAG | TLAN_NET_CFG_1CHAN;	if (tlan_pci_tbl[chip_idx].flags & TLAN_ADAPTER_BIT_RATE_PHY) {		data |= TLAN_NET_CFG_BIT;		if (priv->aui == 1) {			TLan_DioWrite8(BASE, TLAN_ACOMMIT, 0x0a);		} else if (priv->duplex == TLAN_DUPLEX_FULL) {			TLan_DioWrite8(BASE, TLAN_ACOMMIT, 0x00);			priv->tlanFullDuplex = TRUE;		} else {			TLan_DioWrite8(BASE, TLAN_ACOMMIT, 0x08);		}	}	if (priv->phyNum == 0) {		data |= TLAN_NET_CFG_PHY_EN;	}	TLan_DioWrite16(BASE, TLAN_NET_CONFIG, (u16) data);	if (tlan_pci_tbl[chip_idx].flags & TLAN_ADAPTER_UNMANAGED_PHY) {		TLan_FinishReset(nic);	} else {		TLan_PhyPowerDown(nic);	}}	/* TLan_ResetAdapter */void TLan_FinishReset(struct nic *nic){	u8 data;	u32 phy;	u8 sio;	u16 status;	u16 partner;	u16 tlphy_ctl;	u16 tlphy_par;	u16 tlphy_id1, tlphy_id2;	int i;	phy = priv->phy[priv->phyNum];	data = TLAN_NET_CMD_NRESET | TLAN_NET_CMD_NWRAP;	if (priv->tlanFullDuplex) {		data |= TLAN_NET_CMD_DUPLEX;	}	TLan_DioWrite8(BASE, TLAN_NET_CMD, data);	data = TLAN_NET_MASK_MASK4 | TLAN_NET_MASK_MASK5;	if (priv->phyNum == 0) {		data |= TLAN_NET_MASK_MASK7;	}	TLan_DioWrite8(BASE, TLAN_NET_MASK, data);	TLan_DioWrite16(BASE, TLAN_MAX_RX, ((1536) + 7) & ~7);	TLan_MiiReadReg(nic, phy, MII_GEN_ID_HI, &tlphy_id1);	TLan_MiiReadReg(nic, phy, MII_GEN_ID_LO, &tlphy_id2);	if ((tlan_pci_tbl[chip_idx].flags & TLAN_ADAPTER_UNMANAGED_PHY)	    || (priv->aui)) {		status = MII_GS_LINK;		printf("TLAN:  %s: Link forced.\n", priv->nic_name);	} else {		TLan_MiiReadReg(nic, phy, MII_GEN_STS, &status);		udelay(1000);		TLan_MiiReadReg(nic, phy, MII_GEN_STS, &status);

⌨️ 快捷键说明

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