| 
				
			 | 
			
			
				
				@@ -17,6 +17,10 @@ 
			 | 
		
		
	
		
			
			| 
				17
			 | 
			
				17
			 | 
			
			
				
				 /*********************************************************************/ 
			 | 
		
		
	
		
			
			| 
				18
			 | 
			
				18
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				19
			 | 
			
				19
			 | 
			
			
				
				 /* 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				20
			 | 
			
			
				
				+  27 May 2006	mcb30@users.sourceforge.net (Michael Brown) 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				21
			 | 
			
			
				
				+     Rewrote to use the new net driver API, the updated PCI API, and 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				22
			 | 
			
			
				
				+     the generic three-wire serial device support for EEPROM access. 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				23
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				20
			 | 
			
				24
			 | 
			
			
				
				   28 Dec 2002	ken_yap@users.sourceforge.net (Ken Yap) 
			 | 
		
		
	
		
			
			| 
				21
			 | 
			
				25
			 | 
			
			
				
				      Put in virt_to_bus calls to allow Etherboot relocation. 
			 | 
		
		
	
		
			
			| 
				22
			 | 
			
				26
			 | 
			
			
				
				  
			 | 
		
		
	
	
		
			
			| 
				
			 | 
			
			
				
				@@ -62,26 +66,47 @@ 
			 | 
		
		
	
		
			
			| 
				62
			 | 
			
				66
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				63
			 | 
			
				67
			 | 
			
			
				
				 */ 
			 | 
		
		
	
		
			
			| 
				64
			 | 
			
				68
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				65
			 | 
			
				
			 | 
			
			
				
				-#include "etherboot.h" 
			 | 
		
		
	
		
			
			| 
				66
			 | 
			
				
			 | 
			
			
				
				-#include "nic.h" 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				69
			 | 
			
			
				
				+#include <io.h> 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				70
			 | 
			
			
				
				+#include <errno.h> 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				71
			 | 
			
			
				
				+#include <vsprintf.h> 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				72
			 | 
			
			
				
				+#include <timer.h> 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				73
			 | 
			
			
				
				+#include <malloc.h> 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				74
			 | 
			
			
				
				+#include <byteswap.h> 
			 | 
		
		
	
		
			
			| 
				67
			 | 
			
				75
			 | 
			
			
				
				 #include <gpxe/pci.h> 
			 | 
		
		
	
		
			
			| 
				68
			 | 
			
				
			 | 
			
			
				
				-#include "timer.h" 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				76
			 | 
			
			
				
				+#include <gpxe/if_ether.h> 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				77
			 | 
			
			
				
				+#include <gpxe/ethernet.h> 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				78
			 | 
			
			
				
				+#include <gpxe/pkbuff.h> 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				79
			 | 
			
			
				
				+#include <gpxe/netdevice.h> 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				80
			 | 
			
			
				
				+#include <gpxe/nvs/threewire.h> 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				81
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				82
			 | 
			
			
				
				+#define TX_RING_SIZE 4 
			 | 
		
		
	
		
			
			| 
				69
			 | 
			
				83
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				70
			 | 
			
				
			 | 
			
			
				
				-#define RTL_TIMEOUT (1*TICKS_PER_SEC) 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				84
			 | 
			
			
				
				+struct rtl8139_tx { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				85
			 | 
			
			
				
				+	unsigned int next; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				86
			 | 
			
			
				
				+	struct pk_buff *pkb[TX_RING_SIZE]; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				87
			 | 
			
			
				
				+}; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				88
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				89
			 | 
			
			
				
				+struct rtl8139_rx { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				90
			 | 
			
			
				
				+	void *ring; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				91
			 | 
			
			
				
				+	unsigned int offset; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				92
			 | 
			
			
				
				+}; 
			 | 
		
		
	
		
			
			| 
				71
			 | 
			
				93
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				72
			 | 
			
				
			 | 
			
			
				
				-/* PCI Tuning Parameters 
			 | 
		
		
	
		
			
			| 
				73
			 | 
			
				
			 | 
			
			
				
				-   Threshold is bytes transferred to chip before transmission starts. */ 
			 | 
		
		
	
		
			
			| 
				74
			 | 
			
				
			 | 
			
			
				
				-#define TX_FIFO_THRESH 256      /* In bytes, rounded down to 32 byte units. */ 
			 | 
		
		
	
		
			
			| 
				75
			 | 
			
				
			 | 
			
			
				
				-#define RX_FIFO_THRESH  4       /* Rx buffer level before first PCI xfer.  */ 
			 | 
		
		
	
		
			
			| 
				76
			 | 
			
				
			 | 
			
			
				
				-#define RX_DMA_BURST    4       /* Maximum PCI burst, '4' is 256 bytes */ 
			 | 
		
		
	
		
			
			| 
				77
			 | 
			
				
			 | 
			
			
				
				-#define TX_DMA_BURST    4       /* Calculate as 16<<val. */ 
			 | 
		
		
	
		
			
			| 
				78
			 | 
			
				
			 | 
			
			
				
				-#define NUM_TX_DESC     4       /* Number of Tx descriptor registers. */ 
			 | 
		
		
	
		
			
			| 
				79
			 | 
			
				
			 | 
			
			
				
				-#define TX_BUF_SIZE	ETH_FRAME_LEN	/* FCS is added by the chip */ 
			 | 
		
		
	
		
			
			| 
				80
			 | 
			
				
			 | 
			
			
				
				-#define RX_BUF_LEN_IDX 0	/* 0, 1, 2 is allowed - 8,16,32K rx buffer */ 
			 | 
		
		
	
		
			
			| 
				81
			 | 
			
				
			 | 
			
			
				
				-#define RX_BUF_LEN (8192 << RX_BUF_LEN_IDX) 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				94
			 | 
			
			
				
				+struct rtl8139_nic { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				95
			 | 
			
			
				
				+	struct threewire eeprom; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				96
			 | 
			
			
				
				+	unsigned short ioaddr; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				97
			 | 
			
			
				
				+	struct rtl8139_tx tx; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				98
			 | 
			
			
				
				+	struct rtl8139_rx rx; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				99
			 | 
			
			
				
				+}; 
			 | 
		
		
	
		
			
			| 
				82
			 | 
			
				100
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				83
			 | 
			
				
			 | 
			
			
				
				-#undef DEBUG_TX 
			 | 
		
		
	
		
			
			| 
				84
			 | 
			
				
			 | 
			
			
				
				-#undef DEBUG_RX 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				101
			 | 
			
			
				
				+/* Tuning Parameters */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				102
			 | 
			
			
				
				+#define TX_FIFO_THRESH	256	/* In bytes, rounded down to 32 byte units. */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				103
			 | 
			
			
				
				+#define RX_FIFO_THRESH	4	/* Rx buffer level before first PCI xfer.  */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				104
			 | 
			
			
				
				+#define RX_DMA_BURST	4	/* Maximum PCI burst, '4' is 256 bytes */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				105
			 | 
			
			
				
				+#define TX_DMA_BURST	4	/* Calculate as 16<<val. */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				106
			 | 
			
			
				
				+#define TX_IPG		3	/* This is the only valid value */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				107
			 | 
			
			
				
				+#define RX_BUF_LEN_IDX	0	/* 0, 1, 2 is allowed - 8,16,32K rx buffer */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				108
			 | 
			
			
				
				+#define RX_BUF_LEN ( (8192 << RX_BUF_LEN_IDX) ) 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				109
			 | 
			
			
				
				+#define RX_BUF_PAD 4 
			 | 
		
		
	
		
			
			| 
				85
			 | 
			
				110
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				86
			 | 
			
				111
			 | 
			
			
				
				 /* Symbolic offsets to registers. */ 
			 | 
		
		
	
		
			
			| 
				87
			 | 
			
				112
			 | 
			
			
				
				 enum RTL8139_registers { 
			 | 
		
		
	
	
		
			
			| 
				
			 | 
			
			
				
				@@ -159,327 +184,300 @@ enum CSCRBits { 
			 | 
		
		
	
		
			
			| 
				159
			 | 
			
				184
			 | 
			
			
				
				 	CSCR_LinkDownCmd=0x0f3c0, 
			 | 
		
		
	
		
			
			| 
				160
			 | 
			
				185
			 | 
			
			
				
				 }; 
			 | 
		
		
	
		
			
			| 
				161
			 | 
			
				186
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				162
			 | 
			
				
			 | 
			
			
				
				-/* Bits in RxConfig. */ 
			 | 
		
		
	
		
			
			| 
				163
			 | 
			
				
			 | 
			
			
				
				-enum rx_mode_bits { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				187
			 | 
			
			
				
				+enum RxConfigBits { 
			 | 
		
		
	
		
			
			| 
				164
			 | 
			
				188
			 | 
			
			
				
				 	RxCfgWrap=0x80, 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				189
			 | 
			
			
				
				+	Eeprom9356=0x40, 
			 | 
		
		
	
		
			
			| 
				165
			 | 
			
				190
			 | 
			
			
				
				 	AcceptErr=0x20, AcceptRunt=0x10, AcceptBroadcast=0x08, 
			 | 
		
		
	
		
			
			| 
				166
			 | 
			
				191
			 | 
			
			
				
				 	AcceptMulticast=0x04, AcceptMyPhys=0x02, AcceptAllPhys=0x01, 
			 | 
		
		
	
		
			
			| 
				167
			 | 
			
				192
			 | 
			
			
				
				 }; 
			 | 
		
		
	
		
			
			| 
				168
			 | 
			
				193
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				169
			 | 
			
				
			 | 
			
			
				
				-static unsigned int cur_rx,cur_tx; 
			 | 
		
		
	
		
			
			| 
				170
			 | 
			
				
			 | 
			
			
				
				- 
			 | 
		
		
	
		
			
			| 
				171
			 | 
			
				
			 | 
			
			
				
				-/* The RTL8139 can only transmit from a contiguous, aligned memory block.  */ 
			 | 
		
		
	
		
			
			| 
				172
			 | 
			
				
			 | 
			
			
				
				-struct { 
			 | 
		
		
	
		
			
			| 
				173
			 | 
			
				
			 | 
			
			
				
				-	unsigned char tx_buffer[TX_BUF_SIZE] __attribute__((aligned(4))); 
			 | 
		
		
	
		
			
			| 
				174
			 | 
			
				
			 | 
			
			
				
				-	unsigned char rx_ring[RX_BUF_LEN+16] __attribute__((aligned(4))); 
			 | 
		
		
	
		
			
			| 
				175
			 | 
			
				
			 | 
			
			
				
				-} rtl8139_bufs __shared; 
			 | 
		
		
	
		
			
			| 
				176
			 | 
			
				
			 | 
			
			
				
				-#define tx_buffer rtl8139_bufs.tx_buffer 
			 | 
		
		
	
		
			
			| 
				177
			 | 
			
				
			 | 
			
			
				
				-#define rx_ring rtl8139_bufs.rx_ring 
			 | 
		
		
	
		
			
			| 
				178
			 | 
			
				
			 | 
			
			
				
				- 
			 | 
		
		
	
		
			
			| 
				179
			 | 
			
				
			 | 
			
			
				
				-static int rtl8139_probe(struct nic *nic,struct pci_device *pci); 
			 | 
		
		
	
		
			
			| 
				180
			 | 
			
				
			 | 
			
			
				
				-static int read_eeprom(struct nic *nic, int location, int addr_len); 
			 | 
		
		
	
		
			
			| 
				181
			 | 
			
				
			 | 
			
			
				
				-static void rtl_reset(struct nic *nic); 
			 | 
		
		
	
		
			
			| 
				182
			 | 
			
				
			 | 
			
			
				
				-static void rtl_transmit(struct nic *nic, const char *destaddr, 
			 | 
		
		
	
		
			
			| 
				183
			 | 
			
				
			 | 
			
			
				
				-	unsigned int type, unsigned int len, const char *data); 
			 | 
		
		
	
		
			
			| 
				184
			 | 
			
				
			 | 
			
			
				
				-static int rtl_poll(struct nic *nic, int retrieve); 
			 | 
		
		
	
		
			
			| 
				185
			 | 
			
				
			 | 
			
			
				
				-static void rtl_disable(struct nic *nic, struct pci_device *pci); 
			 | 
		
		
	
		
			
			| 
				186
			 | 
			
				
			 | 
			
			
				
				-static void rtl_irq(struct nic *nic, irq_action_t action); 
			 | 
		
		
	
		
			
			| 
				187
			 | 
			
				
			 | 
			
			
				
				-static struct nic_operations rtl_operations; 
			 | 
		
		
	
		
			
			| 
				188
			 | 
			
				
			 | 
			
			
				
				-static struct pci_driver rtl8139_driver; 
			 | 
		
		
	
		
			
			| 
				189
			 | 
			
				
			 | 
			
			
				
				- 
			 | 
		
		
	
		
			
			| 
				190
			 | 
			
				
			 | 
			
			
				
				-static int rtl8139_probe ( struct nic *nic, struct pci_device *pci ) { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				194
			 | 
			
			
				
				+/*  EEPROM access */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				195
			 | 
			
			
				
				+#define EE_MODE_PROGRAM	0x80 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				196
			 | 
			
			
				
				+#define EE_MODE_NORMAL	0x00 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				197
			 | 
			
			
				
				+#define EE_CS		0x08	/* EEPROM chip select */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				198
			 | 
			
			
				
				+#define EE_SK		0x04	/* EEPROM shift clock */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				199
			 | 
			
			
				
				+#define EE_DI		0x02	/* Data in */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				200
			 | 
			
			
				
				+#define EE_DO		0x01	/* Data out */ 
			 | 
		
		
	
		
			
			| 
				191
			 | 
			
				201
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				192
			 | 
			
				
			 | 
			
			
				
				-	int i; 
			 | 
		
		
	
		
			
			| 
				193
			 | 
			
				
			 | 
			
			
				
				-	int speed10, fullduplex; 
			 | 
		
		
	
		
			
			| 
				194
			 | 
			
				
			 | 
			
			
				
				-	int addr_len; 
			 | 
		
		
	
		
			
			| 
				195
			 | 
			
				
			 | 
			
			
				
				-	unsigned short *ap = (unsigned short*)nic->node_addr; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				202
			 | 
			
			
				
				+/* Offsets within EEPROM (these are word offsets) */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				203
			 | 
			
			
				
				+#define EE_MAC 7 
			 | 
		
		
	
		
			
			| 
				196
			 | 
			
				204
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				197
			 | 
			
				
			 | 
			
			
				
				-	/* Copy ioaddr and IRQ from PCI information */ 
			 | 
		
		
	
		
			
			| 
				198
			 | 
			
				
			 | 
			
			
				
				-	pci_fill_nic ( nic, pci ); 
			 | 
		
		
	
		
			
			| 
				199
			 | 
			
				
			 | 
			
			
				
				-	nic->ioaddr = pci->ioaddr; 
			 | 
		
		
	
		
			
			| 
				200
			 | 
			
				
			 | 
			
			
				
				-	nic->irqno = pci->irq; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				205
			 | 
			
			
				
				+static inline struct rtl8139_nic * three_to_rtl ( struct threewire *three ) { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				206
			 | 
			
			
				
				+	return container_of ( three, struct rtl8139_nic, eeprom ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				207
			 | 
			
			
				
				+} 
			 | 
		
		
	
		
			
			| 
				201
			 | 
			
				208
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				202
			 | 
			
				
			 | 
			
			
				
				-	adjust_pci_device(pci); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				209
			 | 
			
			
				
				+static void rtl_setcs ( struct threewire *three, int cs ) { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				210
			 | 
			
			
				
				+	struct rtl8139_nic *rtl = three_to_rtl ( three ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				211
			 | 
			
			
				
				+	unsigned int eereg; 
			 | 
		
		
	
		
			
			| 
				203
			 | 
			
				212
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				204
			 | 
			
				
			 | 
			
			
				
				-	/* Bring the chip out of low-power mode. */ 
			 | 
		
		
	
		
			
			| 
				205
			 | 
			
				
			 | 
			
			
				
				-	outb(0x00, nic->ioaddr + Config1); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				213
			 | 
			
			
				
				+	eereg = cs ? ( EE_MODE_PROGRAM | EE_CS ) : ( EE_MODE_NORMAL ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				214
			 | 
			
			
				
				+	outb ( eereg, rtl->ioaddr + Cfg9346 ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				215
			 | 
			
			
				
				+} 
			 | 
		
		
	
		
			
			| 
				206
			 | 
			
				216
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				207
			 | 
			
				
			 | 
			
			
				
				-	addr_len = read_eeprom(nic,0,8) == 0x8129 ? 8 : 6; 
			 | 
		
		
	
		
			
			| 
				208
			 | 
			
				
			 | 
			
			
				
				-	for (i = 0; i < 3; i++) 
			 | 
		
		
	
		
			
			| 
				209
			 | 
			
				
			 | 
			
			
				
				-	  *ap++ = read_eeprom(nic,i + 7,addr_len); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				217
			 | 
			
			
				
				+static void rtl_setsk ( struct threewire *three, int sk ) { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				218
			 | 
			
			
				
				+	struct rtl8139_nic *rtl = three_to_rtl ( three ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				219
			 | 
			
			
				
				+	unsigned int eereg; 
			 | 
		
		
	
		
			
			| 
				210
			 | 
			
				220
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				211
			 | 
			
				
			 | 
			
			
				
				-	rtl_reset(nic); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				221
			 | 
			
			
				
				+	eereg = inb ( rtl->ioaddr + Cfg9346 ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				222
			 | 
			
			
				
				+	eereg = ( eereg & ~EE_SK ) | ( sk ? EE_SK : 0 ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				223
			 | 
			
			
				
				+	outb ( eereg, rtl->ioaddr + Cfg9346 ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				224
			 | 
			
			
				
				+} 
			 | 
		
		
	
		
			
			| 
				212
			 | 
			
				225
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				213
			 | 
			
				
			 | 
			
			
				
				-	speed10 = inb(nic->ioaddr + MediaStatus) & MSRSpeed10; 
			 | 
		
		
	
		
			
			| 
				214
			 | 
			
				
			 | 
			
			
				
				-	nic->mbps = speed10 ? 10 : 100; 
			 | 
		
		
	
		
			
			| 
				215
			 | 
			
				
			 | 
			
			
				
				-	fullduplex = inw(nic->ioaddr + MII_BMCR) & BMCRDuplex; 
			 | 
		
		
	
		
			
			| 
				216
			 | 
			
				
			 | 
			
			
				
				-	nic->duplex = fullduplex ? FULL_DUPLEX : HALF_DUPLEX; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				226
			 | 
			
			
				
				+static void rtl_setdi ( struct threewire *three, int di ) { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				227
			 | 
			
			
				
				+	struct rtl8139_nic *rtl = three_to_rtl ( three ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				228
			 | 
			
			
				
				+	unsigned int eereg; 
			 | 
		
		
	
		
			
			| 
				217
			 | 
			
				229
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				218
			 | 
			
				
			 | 
			
			
				
				-	nic->nic_op	= &rtl_operations; 
			 | 
		
		
	
		
			
			| 
				219
			 | 
			
				
			 | 
			
			
				
				-	return 1; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				230
			 | 
			
			
				
				+	eereg = inb ( rtl->ioaddr + Cfg9346 ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				231
			 | 
			
			
				
				+	eereg = ( eereg & ~EE_DI ) | ( di ? EE_DI : 0 ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				232
			 | 
			
			
				
				+	outb ( eereg, rtl->ioaddr + Cfg9346 ); 
			 | 
		
		
	
		
			
			| 
				220
			 | 
			
				233
			 | 
			
			
				
				 } 
			 | 
		
		
	
		
			
			| 
				221
			 | 
			
				234
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				222
			 | 
			
				
			 | 
			
			
				
				-/* Serial EEPROM section. */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				235
			 | 
			
			
				
				+static int rtl_getdo ( struct threewire *three ) { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				236
			 | 
			
			
				
				+	struct rtl8139_nic *rtl = three_to_rtl ( three ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				237
			 | 
			
			
				
				+	unsigned int eereg; 
			 | 
		
		
	
		
			
			| 
				223
			 | 
			
				238
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				224
			 | 
			
				
			 | 
			
			
				
				-/*  EEPROM_Ctrl bits. */ 
			 | 
		
		
	
		
			
			| 
				225
			 | 
			
				
			 | 
			
			
				
				-#define EE_SHIFT_CLK    0x04    /* EEPROM shift clock. */ 
			 | 
		
		
	
		
			
			| 
				226
			 | 
			
				
			 | 
			
			
				
				-#define EE_CS           0x08    /* EEPROM chip select. */ 
			 | 
		
		
	
		
			
			| 
				227
			 | 
			
				
			 | 
			
			
				
				-#define EE_DATA_WRITE   0x02    /* EEPROM chip data in. */ 
			 | 
		
		
	
		
			
			| 
				228
			 | 
			
				
			 | 
			
			
				
				-#define EE_WRITE_0      0x00 
			 | 
		
		
	
		
			
			| 
				229
			 | 
			
				
			 | 
			
			
				
				-#define EE_WRITE_1      0x02 
			 | 
		
		
	
		
			
			| 
				230
			 | 
			
				
			 | 
			
			
				
				-#define EE_DATA_READ    0x01    /* EEPROM chip data out. */ 
			 | 
		
		
	
		
			
			| 
				231
			 | 
			
				
			 | 
			
			
				
				-#define EE_ENB          (0x80 | EE_CS) 
			 | 
		
		
	
		
			
			| 
				232
			 | 
			
				
			 | 
			
			
				
				- 
			 | 
		
		
	
		
			
			| 
				233
			 | 
			
				
			 | 
			
			
				
				-/* 
			 | 
		
		
	
		
			
			| 
				234
			 | 
			
				
			 | 
			
			
				
				-	Delay between EEPROM clock transitions. 
			 | 
		
		
	
		
			
			| 
				235
			 | 
			
				
			 | 
			
			
				
				-	No extra delay is needed with 33Mhz PCI, but 66Mhz may change this. 
			 | 
		
		
	
		
			
			| 
				236
			 | 
			
				
			 | 
			
			
				
				-*/ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				239
			 | 
			
			
				
				+	eereg = ( inb ( rtl->ioaddr + Cfg9346 ) & EE_DO ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				240
			 | 
			
			
				
				+	return eereg; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				241
			 | 
			
			
				
				+} 
			 | 
		
		
	
		
			
			| 
				237
			 | 
			
				242
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				238
			 | 
			
				
			 | 
			
			
				
				-#define eeprom_delay()  inl(ee_addr) 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				243
			 | 
			
			
				
				+static struct threewire_operations rtl_three_ops = { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				244
			 | 
			
			
				
				+	.setcs = rtl_setcs, 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				245
			 | 
			
			
				
				+	.setsk = rtl_setsk, 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				246
			 | 
			
			
				
				+	.setdi = rtl_setdi, 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				247
			 | 
			
			
				
				+	.getdo = rtl_getdo, 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				248
			 | 
			
			
				
				+}; 
			 | 
		
		
	
		
			
			| 
				239
			 | 
			
				249
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				240
			 | 
			
				
			 | 
			
			
				
				-/* The EEPROM commands include the alway-set leading bit. */ 
			 | 
		
		
	
		
			
			| 
				241
			 | 
			
				
			 | 
			
			
				
				-#define EE_WRITE_CMD    (5) 
			 | 
		
		
	
		
			
			| 
				242
			 | 
			
				
			 | 
			
			
				
				-#define EE_READ_CMD     (6) 
			 | 
		
		
	
		
			
			| 
				243
			 | 
			
				
			 | 
			
			
				
				-#define EE_ERASE_CMD    (7) 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				250
			 | 
			
			
				
				+/** 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				251
			 | 
			
			
				
				+ * Set up for EEPROM access 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				252
			 | 
			
			
				
				+ * 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				253
			 | 
			
			
				
				+ * @v rtl		RTL8139 NIC 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				254
			 | 
			
			
				
				+ */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				255
			 | 
			
			
				
				+static void rtl_init_eeprom ( struct rtl8139_nic *rtl ) { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				256
			 | 
			
			
				
				+	int ee9356; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				257
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				258
			 | 
			
			
				
				+	ee9356 = ( inw ( rtl->ioaddr + RxConfig ) & Eeprom9356 ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				259
			 | 
			
			
				
				+	DBG ( "EEPROM is an %s\n", ee9356 ? "AT93C56" : "AT93C46" ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				260
			 | 
			
			
				
				+	rtl->eeprom.ops = &rtl_three_ops; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				261
			 | 
			
			
				
				+	rtl->eeprom.adrsize = 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				262
			 | 
			
			
				
				+		( ee9356 ? AT93C56_ORG16_ADRSIZE : AT93C46_ORG16_ADRSIZE ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				263
			 | 
			
			
				
				+	rtl->eeprom.datasize = 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				264
			 | 
			
			
				
				+		( ee9356 ? AT93C56_ORG16_DATASIZE : AT93C46_ORG16_DATASIZE ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				265
			 | 
			
			
				
				+	rtl->eeprom.udelay = 1; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				266
			 | 
			
			
				
				+} 
			 | 
		
		
	
		
			
			| 
				244
			 | 
			
				267
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				245
			 | 
			
				
			 | 
			
			
				
				-static int read_eeprom(struct nic *nic, int location, int addr_len) 
			 | 
		
		
	
		
			
			| 
				246
			 | 
			
				
			 | 
			
			
				
				-{ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				268
			 | 
			
			
				
				+/** 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				269
			 | 
			
			
				
				+ * Read the MAC address 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				270
			 | 
			
			
				
				+ * 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				271
			 | 
			
			
				
				+ * @v rtl		RTL8139 NIC 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				272
			 | 
			
			
				
				+ * @v mac_addr		Buffer to contain MAC address (ETH_ALEN bytes) 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				273
			 | 
			
			
				
				+ */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				274
			 | 
			
			
				
				+static void rtl_read_mac ( struct rtl8139_nic *rtl, uint8_t *mac_addr ) { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				275
			 | 
			
			
				
				+	union { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				276
			 | 
			
			
				
				+		uint16_t word; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				277
			 | 
			
			
				
				+		uint8_t bytes[2]; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				278
			 | 
			
			
				
				+	} u; 
			 | 
		
		
	
		
			
			| 
				247
			 | 
			
				279
			 | 
			
			
				
				 	int i; 
			 | 
		
		
	
		
			
			| 
				248
			 | 
			
				
			 | 
			
			
				
				-	unsigned int retval = 0; 
			 | 
		
		
	
		
			
			| 
				249
			 | 
			
				
			 | 
			
			
				
				-	long ee_addr = nic->ioaddr + Cfg9346; 
			 | 
		
		
	
		
			
			| 
				250
			 | 
			
				
			 | 
			
			
				
				-	int read_cmd = location | (EE_READ_CMD << addr_len); 
			 | 
		
		
	
		
			
			| 
				251
			 | 
			
				
			 | 
			
			
				
				- 
			 | 
		
		
	
		
			
			| 
				252
			 | 
			
				
			 | 
			
			
				
				-	outb(EE_ENB & ~EE_CS, ee_addr); 
			 | 
		
		
	
		
			
			| 
				253
			 | 
			
				
			 | 
			
			
				
				-	outb(EE_ENB, ee_addr); 
			 | 
		
		
	
		
			
			| 
				254
			 | 
			
				
			 | 
			
			
				
				-	eeprom_delay(); 
			 | 
		
		
	
		
			
			| 
				255
			 | 
			
				
			 | 
			
			
				
				- 
			 | 
		
		
	
		
			
			| 
				256
			 | 
			
				
			 | 
			
			
				
				-	/* Shift the read command bits out. */ 
			 | 
		
		
	
		
			
			| 
				257
			 | 
			
				
			 | 
			
			
				
				-	for (i = 4 + addr_len; i >= 0; i--) { 
			 | 
		
		
	
		
			
			| 
				258
			 | 
			
				
			 | 
			
			
				
				-		int dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0; 
			 | 
		
		
	
		
			
			| 
				259
			 | 
			
				
			 | 
			
			
				
				-		outb(EE_ENB | dataval, ee_addr); 
			 | 
		
		
	
		
			
			| 
				260
			 | 
			
				
			 | 
			
			
				
				-		eeprom_delay(); 
			 | 
		
		
	
		
			
			| 
				261
			 | 
			
				
			 | 
			
			
				
				-		outb(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr); 
			 | 
		
		
	
		
			
			| 
				262
			 | 
			
				
			 | 
			
			
				
				-		eeprom_delay(); 
			 | 
		
		
	
		
			
			| 
				263
			 | 
			
				
			 | 
			
			
				
				-	} 
			 | 
		
		
	
		
			
			| 
				264
			 | 
			
				
			 | 
			
			
				
				-	outb(EE_ENB, ee_addr); 
			 | 
		
		
	
		
			
			| 
				265
			 | 
			
				
			 | 
			
			
				
				-	eeprom_delay(); 
			 | 
		
		
	
		
			
			| 
				266
			 | 
			
				
			 | 
			
			
				
				- 
			 | 
		
		
	
		
			
			| 
				267
			 | 
			
				
			 | 
			
			
				
				-	for (i = 16; i > 0; i--) { 
			 | 
		
		
	
		
			
			| 
				268
			 | 
			
				
			 | 
			
			
				
				-		outb(EE_ENB | EE_SHIFT_CLK, ee_addr); 
			 | 
		
		
	
		
			
			| 
				269
			 | 
			
				
			 | 
			
			
				
				-		eeprom_delay(); 
			 | 
		
		
	
		
			
			| 
				270
			 | 
			
				
			 | 
			
			
				
				-		retval = (retval << 1) | ((inb(ee_addr) & EE_DATA_READ) ? 1 : 0); 
			 | 
		
		
	
		
			
			| 
				271
			 | 
			
				
			 | 
			
			
				
				-		outb(EE_ENB, ee_addr); 
			 | 
		
		
	
		
			
			| 
				272
			 | 
			
				
			 | 
			
			
				
				-		eeprom_delay(); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				280
			 | 
			
			
				
				+	 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				281
			 | 
			
			
				
				+	DBG ( "MAC address is " ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				282
			 | 
			
			
				
				+	for ( i = 0 ; i < ( ETH_ALEN / 2 ) ; i++ ) { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				283
			 | 
			
			
				
				+		u.word = cpu_to_le16 ( threewire_read ( &rtl->eeprom, 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				284
			 | 
			
			
				
				+							EE_MAC + i ) ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				285
			 | 
			
			
				
				+		*mac_addr++ = u.bytes[0]; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				286
			 | 
			
			
				
				+		*mac_addr++ = u.bytes[1]; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				287
			 | 
			
			
				
				+		DBG ( "%02x%02x", u.bytes[0], u.bytes[1] ); 
			 | 
		
		
	
		
			
			| 
				273
			 | 
			
				288
			 | 
			
			
				
				 	} 
			 | 
		
		
	
		
			
			| 
				274
			 | 
			
				
			 | 
			
			
				
				- 
			 | 
		
		
	
		
			
			| 
				275
			 | 
			
				
			 | 
			
			
				
				-	/* Terminate the EEPROM access. */ 
			 | 
		
		
	
		
			
			| 
				276
			 | 
			
				
			 | 
			
			
				
				-	outb(~EE_CS, ee_addr); 
			 | 
		
		
	
		
			
			| 
				277
			 | 
			
				
			 | 
			
			
				
				-	eeprom_delay(); 
			 | 
		
		
	
		
			
			| 
				278
			 | 
			
				
			 | 
			
			
				
				-	return retval; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				289
			 | 
			
			
				
				+	DBG ( "\n" ); 
			 | 
		
		
	
		
			
			| 
				279
			 | 
			
				290
			 | 
			
			
				
				 } 
			 | 
		
		
	
		
			
			| 
				280
			 | 
			
				291
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				281
			 | 
			
				
			 | 
			
			
				
				-static const unsigned int rtl8139_rx_config =  
			 | 
		
		
	
		
			
			| 
				282
			 | 
			
				
			 | 
			
			
				
				-	(RX_BUF_LEN_IDX << 11) | 
			 | 
		
		
	
		
			
			| 
				283
			 | 
			
				
			 | 
			
			
				
				-	(RX_FIFO_THRESH << 13) | 
			 | 
		
		
	
		
			
			| 
				284
			 | 
			
				
			 | 
			
			
				
				-	(RX_DMA_BURST << 8); 
			 | 
		
		
	
		
			
			| 
				285
			 | 
			
				
			 | 
			
			
				
				-	 
			 | 
		
		
	
		
			
			| 
				286
			 | 
			
				
			 | 
			
			
				
				-static void set_rx_mode(struct nic *nic) { 
			 | 
		
		
	
		
			
			| 
				287
			 | 
			
				
			 | 
			
			
				
				-	unsigned int mc_filter[2]; 
			 | 
		
		
	
		
			
			| 
				288
			 | 
			
				
			 | 
			
			
				
				-	int rx_mode; 
			 | 
		
		
	
		
			
			| 
				289
			 | 
			
				
			 | 
			
			
				
				-	/* !IFF_PROMISC */ 
			 | 
		
		
	
		
			
			| 
				290
			 | 
			
				
			 | 
			
			
				
				-	rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; 
			 | 
		
		
	
		
			
			| 
				291
			 | 
			
				
			 | 
			
			
				
				-	mc_filter[1] = mc_filter[0] = 0xffffffff; 
			 | 
		
		
	
		
			
			| 
				292
			 | 
			
				
			 | 
			
			
				
				- 
			 | 
		
		
	
		
			
			| 
				293
			 | 
			
				
			 | 
			
			
				
				-	outl(rtl8139_rx_config | rx_mode, nic->ioaddr + RxConfig); 
			 | 
		
		
	
		
			
			| 
				294
			 | 
			
				
			 | 
			
			
				
				- 
			 | 
		
		
	
		
			
			| 
				295
			 | 
			
				
			 | 
			
			
				
				-	outl(mc_filter[0], nic->ioaddr + MAR0 + 0); 
			 | 
		
		
	
		
			
			| 
				296
			 | 
			
				
			 | 
			
			
				
				-	outl(mc_filter[1], nic->ioaddr + MAR0 + 4); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				292
			 | 
			
			
				
				+/** 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				293
			 | 
			
			
				
				+ * Reset NIC 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				294
			 | 
			
			
				
				+ * 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				295
			 | 
			
			
				
				+ * @v rtl		RTL8139 NIC 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				296
			 | 
			
			
				
				+ * 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				297
			 | 
			
			
				
				+ * Issues a hardware reset and waits for the reset to complete. 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				298
			 | 
			
			
				
				+ */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				299
			 | 
			
			
				
				+static void rtl_reset ( struct rtl8139_nic *rtl ) { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				300
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				301
			 | 
			
			
				
				+	/* Reset chip */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				302
			 | 
			
			
				
				+	outb ( CmdReset, rtl->ioaddr + ChipCmd ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				303
			 | 
			
			
				
				+	mdelay ( 10 ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				304
			 | 
			
			
				
				+	rtl->tx.next = 0; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				305
			 | 
			
			
				
				+	rtl->rx.offset = 0; 
			 | 
		
		
	
		
			
			| 
				297
			 | 
			
				306
			 | 
			
			
				
				 } 
			 | 
		
		
	
		
			
			| 
				298
			 | 
			
				307
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				299
			 | 
			
				
			 | 
			
			
				
				-static int rtl_connect ( struct nic *nic ) { 
			 | 
		
		
	
		
			
			| 
				300
			 | 
			
				
			 | 
			
			
				
				-	if (inb(nic->ioaddr + MediaStatus) & MSRLinkFail) { 
			 | 
		
		
	
		
			
			| 
				301
			 | 
			
				
			 | 
			
			
				
				-		printf("Cable not connected or other link failure\n"); 
			 | 
		
		
	
		
			
			| 
				302
			 | 
			
				
			 | 
			
			
				
				-		return 0; 
			 | 
		
		
	
		
			
			| 
				303
			 | 
			
				
			 | 
			
			
				
				-	} 
			 | 
		
		
	
		
			
			| 
				304
			 | 
			
				
			 | 
			
			
				
				-	return 1; 
			 | 
		
		
	
		
			
			| 
				305
			 | 
			
				
			 | 
			
			
				
				-} 
			 | 
		
		
	
		
			
			| 
				306
			 | 
			
				
			 | 
			
			
				
				-	 
			 | 
		
		
	
		
			
			| 
				307
			 | 
			
				
			 | 
			
			
				
				-static void rtl_reset(struct nic* nic) 
			 | 
		
		
	
		
			
			| 
				308
			 | 
			
				
			 | 
			
			
				
				-{ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				308
			 | 
			
			
				
				+/** 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				309
			 | 
			
			
				
				+ * Open NIC 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				310
			 | 
			
			
				
				+ * 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				311
			 | 
			
			
				
				+ * @v netdev		Net device 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				312
			 | 
			
			
				
				+ * @ret rc		Return status code 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				313
			 | 
			
			
				
				+ */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				314
			 | 
			
			
				
				+static int rtl_open ( struct net_device *netdev ) { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				315
			 | 
			
			
				
				+	struct rtl8139_nic *rtl = netdev->priv; 
			 | 
		
		
	
		
			
			| 
				309
			 | 
			
				316
			 | 
			
			
				
				 	int i; 
			 | 
		
		
	
		
			
			| 
				310
			 | 
			
				317
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				311
			 | 
			
				
			 | 
			
			
				
				-	outb(CmdReset, nic->ioaddr + ChipCmd); 
			 | 
		
		
	
		
			
			| 
				312
			 | 
			
				
			 | 
			
			
				
				- 
			 | 
		
		
	
		
			
			| 
				313
			 | 
			
				
			 | 
			
			
				
				-	cur_rx = 0; 
			 | 
		
		
	
		
			
			| 
				314
			 | 
			
				
			 | 
			
			
				
				-	cur_tx = 0; 
			 | 
		
		
	
		
			
			| 
				315
			 | 
			
				
			 | 
			
			
				
				- 
			 | 
		
		
	
		
			
			| 
				316
			 | 
			
				
			 | 
			
			
				
				-	/* Give the chip 10ms to finish the reset. */ 
			 | 
		
		
	
		
			
			| 
				317
			 | 
			
				
			 | 
			
			
				
				-	load_timer2(10*TICKS_PER_MS); 
			 | 
		
		
	
		
			
			| 
				318
			 | 
			
				
			 | 
			
			
				
				-	while ((inb(nic->ioaddr + ChipCmd) & CmdReset) != 0 && 
			 | 
		
		
	
		
			
			| 
				319
			 | 
			
				
			 | 
			
			
				
				-	       timer2_running()) 
			 | 
		
		
	
		
			
			| 
				320
			 | 
			
				
			 | 
			
			
				
				-		/* wait */; 
			 | 
		
		
	
		
			
			| 
				321
			 | 
			
				
			 | 
			
			
				
				- 
			 | 
		
		
	
		
			
			| 
				322
			 | 
			
				
			 | 
			
			
				
				-	for (i = 0; i < ETH_ALEN; i++) 
			 | 
		
		
	
		
			
			| 
				323
			 | 
			
				
			 | 
			
			
				
				-		outb(nic->node_addr[i], nic->ioaddr + MAC0 + i); 
			 | 
		
		
	
		
			
			| 
				324
			 | 
			
				
			 | 
			
			
				
				- 
			 | 
		
		
	
		
			
			| 
				325
			 | 
			
				
			 | 
			
			
				
				-	/* Must enable Tx/Rx before setting transfer thresholds! */ 
			 | 
		
		
	
		
			
			| 
				326
			 | 
			
				
			 | 
			
			
				
				-	outb(CmdRxEnb | CmdTxEnb, nic->ioaddr + ChipCmd); 
			 | 
		
		
	
		
			
			| 
				327
			 | 
			
				
			 | 
			
			
				
				-	outl((RX_FIFO_THRESH<<13) | (RX_BUF_LEN_IDX<<11) | (RX_DMA_BURST<<8), 
			 | 
		
		
	
		
			
			| 
				328
			 | 
			
				
			 | 
			
			
				
				-		nic->ioaddr + RxConfig);	  /* accept no frames yet!  */ 
			 | 
		
		
	
		
			
			| 
				329
			 | 
			
				
			 | 
			
			
				
				-	outl((TX_DMA_BURST<<8)|0x03000000, nic->ioaddr + TxConfig); 
			 | 
		
		
	
		
			
			| 
				330
			 | 
			
				
			 | 
			
			
				
				- 
			 | 
		
		
	
		
			
			| 
				331
			 | 
			
				
			 | 
			
			
				
				-	/* The Linux driver changes Config1 here to use a different LED pattern 
			 | 
		
		
	
		
			
			| 
				332
			 | 
			
				
			 | 
			
			
				
				-	 * for half duplex or full/autodetect duplex (for full/autodetect, the 
			 | 
		
		
	
		
			
			| 
				333
			 | 
			
				
			 | 
			
			
				
				-	 * outputs are TX/RX, Link10/100, FULL, while for half duplex it uses 
			 | 
		
		
	
		
			
			| 
				334
			 | 
			
				
			 | 
			
			
				
				-	 * TX/RX, Link100, Link10).  This is messy, because it doesn't match 
			 | 
		
		
	
		
			
			| 
				335
			 | 
			
				
			 | 
			
			
				
				-	 * the inscription on the mounting bracket.  It should not be changed 
			 | 
		
		
	
		
			
			| 
				336
			 | 
			
				
			 | 
			
			
				
				-	 * from the configuration EEPROM default, because the card manufacturer 
			 | 
		
		
	
		
			
			| 
				337
			 | 
			
				
			 | 
			
			
				
				-	 * should have set that to match the card.  */ 
			 | 
		
		
	
		
			
			| 
				338
			 | 
			
				
			 | 
			
			
				
				- 
			 | 
		
		
	
		
			
			| 
				339
			 | 
			
				
			 | 
			
			
				
				-#ifdef	DEBUG_RX 
			 | 
		
		
	
		
			
			| 
				340
			 | 
			
				
			 | 
			
			
				
				-	printf("rx ring address is %X\n",(unsigned long)rx_ring); 
			 | 
		
		
	
		
			
			| 
				341
			 | 
			
				
			 | 
			
			
				
				-#endif 
			 | 
		
		
	
		
			
			| 
				342
			 | 
			
				
			 | 
			
			
				
				-	outl((unsigned long)virt_to_bus(rx_ring), nic->ioaddr + RxBuf); 
			 | 
		
		
	
		
			
			| 
				343
			 | 
			
				
			 | 
			
			
				
				- 
			 | 
		
		
	
		
			
			| 
				344
			 | 
			
				
			 | 
			
			
				
				- 
			 | 
		
		
	
		
			
			| 
				345
			 | 
			
				
			 | 
			
			
				
				- 
			 | 
		
		
	
		
			
			| 
				346
			 | 
			
				
			 | 
			
			
				
				-	/* If we add multicast support, the MAR0 register would have to be 
			 | 
		
		
	
		
			
			| 
				347
			 | 
			
				
			 | 
			
			
				
				-	 * initialized to 0xffffffffffffffff (two 32 bit accesses).  Etherboot 
			 | 
		
		
	
		
			
			| 
				348
			 | 
			
				
			 | 
			
			
				
				-	 * only needs broadcast (for ARP/RARP/BOOTP/DHCP) and unicast.  */ 
			 | 
		
		
	
		
			
			| 
				349
			 | 
			
				
			 | 
			
			
				
				- 
			 | 
		
		
	
		
			
			| 
				350
			 | 
			
				
			 | 
			
			
				
				-	outb(CmdRxEnb | CmdTxEnb, nic->ioaddr + ChipCmd); 
			 | 
		
		
	
		
			
			| 
				351
			 | 
			
				
			 | 
			
			
				
				-	 
			 | 
		
		
	
		
			
			| 
				352
			 | 
			
				
			 | 
			
			
				
				-	outl(rtl8139_rx_config, nic->ioaddr + RxConfig); 
			 | 
		
		
	
		
			
			| 
				353
			 | 
			
				
			 | 
			
			
				
				-	 
			 | 
		
		
	
		
			
			| 
				354
			 | 
			
				
			 | 
			
			
				
				-	/* Start the chip's Tx and Rx process. */ 
			 | 
		
		
	
		
			
			| 
				355
			 | 
			
				
			 | 
			
			
				
				-	outl(0, nic->ioaddr + RxMissed); 
			 | 
		
		
	
		
			
			| 
				356
			 | 
			
				
			 | 
			
			
				
				- 
			 | 
		
		
	
		
			
			| 
				357
			 | 
			
				
			 | 
			
			
				
				-	/* set_rx_mode */ 
			 | 
		
		
	
		
			
			| 
				358
			 | 
			
				
			 | 
			
			
				
				-	set_rx_mode(nic); 
			 | 
		
		
	
		
			
			| 
				359
			 | 
			
				
			 | 
			
			
				
				-	 
			 | 
		
		
	
		
			
			| 
				360
			 | 
			
				
			 | 
			
			
				
				-	/* Disable all known interrupts by setting the interrupt mask. */ 
			 | 
		
		
	
		
			
			| 
				361
			 | 
			
				
			 | 
			
			
				
				-	outw(0, nic->ioaddr + IntrMask); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				318
			 | 
			
			
				
				+	/* Program the MAC address */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				319
			 | 
			
			
				
				+	for ( i = 0 ; i < ETH_ALEN ; i++ ) 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				320
			 | 
			
			
				
				+		outb ( netdev->ll_addr[i], rtl->ioaddr + MAC0 + i ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				321
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				322
			 | 
			
			
				
				+	/* Set up RX ring */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				323
			 | 
			
			
				
				+	rtl->rx.ring = malloc ( RX_BUF_LEN + RX_BUF_PAD ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				324
			 | 
			
			
				
				+	if ( ! rtl->rx.ring ) 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				325
			 | 
			
			
				
				+		return -ENOMEM; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				326
			 | 
			
			
				
				+	outl ( virt_to_bus ( rtl->rx.ring ), rtl->ioaddr + RxBuf ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				327
			 | 
			
			
				
				+	DBG ( "RX ring at %lx\n", virt_to_bus ( rtl->rx.ring ) ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				328
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				329
			 | 
			
			
				
				+	/* Enable TX and RX */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				330
			 | 
			
			
				
				+	outb ( ( CmdRxEnb | CmdTxEnb ), rtl->ioaddr + ChipCmd ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				331
			 | 
			
			
				
				+	outl ( ( ( RX_FIFO_THRESH << 13 ) | ( RX_BUF_LEN_IDX << 11 ) | 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				332
			 | 
			
			
				
				+		 ( RX_DMA_BURST << 8 ) | AcceptBroadcast | AcceptMulticast | 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				333
			 | 
			
			
				
				+		 AcceptMyPhys ), rtl->ioaddr + RxConfig ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				334
			 | 
			
			
				
				+	outl ( 0xffffffffUL, rtl->ioaddr + MAR0 + 0 ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				335
			 | 
			
			
				
				+	outl ( 0xffffffffUL, rtl->ioaddr + MAR0 + 4 ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				336
			 | 
			
			
				
				+	outl ( ( ( TX_DMA_BURST << 8 ) | ( TX_IPG << 24 ) ), 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				337
			 | 
			
			
				
				+	       rtl->ioaddr + TxConfig ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				338
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				339
			 | 
			
			
				
				+	return 0; 
			 | 
		
		
	
		
			
			| 
				362
			 | 
			
				340
			 | 
			
			
				
				 } 
			 | 
		
		
	
		
			
			| 
				363
			 | 
			
				341
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				364
			 | 
			
				
			 | 
			
			
				
				-static void rtl_transmit(struct nic *nic, const char *destaddr, 
			 | 
		
		
	
		
			
			| 
				365
			 | 
			
				
			 | 
			
			
				
				-	unsigned int type, unsigned int len, const char *data) 
			 | 
		
		
	
		
			
			| 
				366
			 | 
			
				
			 | 
			
			
				
				-{ 
			 | 
		
		
	
		
			
			| 
				367
			 | 
			
				
			 | 
			
			
				
				-	unsigned int status, to, nstype; 
			 | 
		
		
	
		
			
			| 
				368
			 | 
			
				
			 | 
			
			
				
				-	unsigned long txstatus; 
			 | 
		
		
	
		
			
			| 
				369
			 | 
			
				
			 | 
			
			
				
				- 
			 | 
		
		
	
		
			
			| 
				370
			 | 
			
				
			 | 
			
			
				
				-	/* nstype assignment moved up here to avoid gcc 3.0.3 compiler bug */ 
			 | 
		
		
	
		
			
			| 
				371
			 | 
			
				
			 | 
			
			
				
				-	nstype = htons(type); 
			 | 
		
		
	
		
			
			| 
				372
			 | 
			
				
			 | 
			
			
				
				-	memcpy(tx_buffer, destaddr, ETH_ALEN); 
			 | 
		
		
	
		
			
			| 
				373
			 | 
			
				
			 | 
			
			
				
				-	memcpy(tx_buffer + ETH_ALEN, nic->node_addr, ETH_ALEN); 
			 | 
		
		
	
		
			
			| 
				374
			 | 
			
				
			 | 
			
			
				
				-	memcpy(tx_buffer + 2 * ETH_ALEN, &nstype, 2); 
			 | 
		
		
	
		
			
			| 
				375
			 | 
			
				
			 | 
			
			
				
				-	memcpy(tx_buffer + ETH_HLEN, data, len); 
			 | 
		
		
	
		
			
			| 
				376
			 | 
			
				
			 | 
			
			
				
				- 
			 | 
		
		
	
		
			
			| 
				377
			 | 
			
				
			 | 
			
			
				
				-	len += ETH_HLEN; 
			 | 
		
		
	
		
			
			| 
				378
			 | 
			
				
			 | 
			
			
				
				-#ifdef	DEBUG_TX 
			 | 
		
		
	
		
			
			| 
				379
			 | 
			
				
			 | 
			
			
				
				-	printf("sending %d bytes ethtype %hX\n", len, type); 
			 | 
		
		
	
		
			
			| 
				380
			 | 
			
				
			 | 
			
			
				
				-#endif 
			 | 
		
		
	
		
			
			| 
				381
			 | 
			
				
			 | 
			
			
				
				- 
			 | 
		
		
	
		
			
			| 
				382
			 | 
			
				
			 | 
			
			
				
				-	/* Note: RTL8139 doesn't auto-pad, send minimum payload (another 4 
			 | 
		
		
	
		
			
			| 
				383
			 | 
			
				
			 | 
			
			
				
				-	 * bytes are sent automatically for the FCS, totalling to 64 bytes). */ 
			 | 
		
		
	
		
			
			| 
				384
			 | 
			
				
			 | 
			
			
				
				-	while (len < ETH_ZLEN) { 
			 | 
		
		
	
		
			
			| 
				385
			 | 
			
				
			 | 
			
			
				
				-		tx_buffer[len++] = '\0'; 
			 | 
		
		
	
		
			
			| 
				386
			 | 
			
				
			 | 
			
			
				
				-	} 
			 | 
		
		
	
		
			
			| 
				387
			 | 
			
				
			 | 
			
			
				
				- 
			 | 
		
		
	
		
			
			| 
				388
			 | 
			
				
			 | 
			
			
				
				-	outl((unsigned long)virt_to_bus(tx_buffer), nic->ioaddr + TxAddr0 + cur_tx*4); 
			 | 
		
		
	
		
			
			| 
				389
			 | 
			
				
			 | 
			
			
				
				-	outl(((TX_FIFO_THRESH<<11) & 0x003f0000) | len, 
			 | 
		
		
	
		
			
			| 
				390
			 | 
			
				
			 | 
			
			
				
				-		nic->ioaddr + TxStatus0 + cur_tx*4); 
			 | 
		
		
	
		
			
			| 
				391
			 | 
			
				
			 | 
			
			
				
				- 
			 | 
		
		
	
		
			
			| 
				392
			 | 
			
				
			 | 
			
			
				
				-	to = currticks() + RTL_TIMEOUT; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				342
			 | 
			
			
				
				+/** 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				343
			 | 
			
			
				
				+ * Close NIC 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				344
			 | 
			
			
				
				+ * 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				345
			 | 
			
			
				
				+ * @v netdev		Net device 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				346
			 | 
			
			
				
				+ */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				347
			 | 
			
			
				
				+static void rtl_close ( struct net_device *netdev ) { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				348
			 | 
			
			
				
				+	struct rtl8139_nic *rtl = netdev->priv; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				349
			 | 
			
			
				
				+	int i; 
			 | 
		
		
	
		
			
			| 
				393
			 | 
			
				350
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				394
			 | 
			
				
			 | 
			
			
				
				-	do { 
			 | 
		
		
	
		
			
			| 
				395
			 | 
			
				
			 | 
			
			
				
				-		status = inw(nic->ioaddr + IntrStatus); 
			 | 
		
		
	
		
			
			| 
				396
			 | 
			
				
			 | 
			
			
				
				-		/* Only acknlowledge interrupt sources we can properly handle 
			 | 
		
		
	
		
			
			| 
				397
			 | 
			
				
			 | 
			
			
				
				-		 * here - the RxOverflow/RxFIFOOver MUST be handled in the 
			 | 
		
		
	
		
			
			| 
				398
			 | 
			
				
			 | 
			
			
				
				-		 * rtl_poll() function.  */ 
			 | 
		
		
	
		
			
			| 
				399
			 | 
			
				
			 | 
			
			
				
				-		outw(status & (TxOK | TxErr | PCIErr), nic->ioaddr + IntrStatus); 
			 | 
		
		
	
		
			
			| 
				400
			 | 
			
				
			 | 
			
			
				
				-		if ((status & (TxOK | TxErr | PCIErr)) != 0) break; 
			 | 
		
		
	
		
			
			| 
				401
			 | 
			
				
			 | 
			
			
				
				-	} while (currticks() < to); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				351
			 | 
			
			
				
				+	/* Reset the hardware to disable everything in one go */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				352
			 | 
			
			
				
				+	rtl_reset ( rtl ); 
			 | 
		
		
	
		
			
			| 
				402
			 | 
			
				353
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				403
			 | 
			
				
			 | 
			
			
				
				-	txstatus = inl(nic->ioaddr+ TxStatus0 + cur_tx*4); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				354
			 | 
			
			
				
				+	/* Free RX ring */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				355
			 | 
			
			
				
				+	free ( rtl->rx.ring ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				356
			 | 
			
			
				
				+	rtl->rx.ring = NULL; 
			 | 
		
		
	
		
			
			| 
				404
			 | 
			
				357
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				405
			 | 
			
				
			 | 
			
			
				
				-	if (status & TxOK) { 
			 | 
		
		
	
		
			
			| 
				406
			 | 
			
				
			 | 
			
			
				
				-		cur_tx = (cur_tx + 1) % NUM_TX_DESC; 
			 | 
		
		
	
		
			
			| 
				407
			 | 
			
				
			 | 
			
			
				
				-#ifdef	DEBUG_TX 
			 | 
		
		
	
		
			
			| 
				408
			 | 
			
				
			 | 
			
			
				
				-		printf("tx done (%d ticks), status %hX txstatus %X\n", 
			 | 
		
		
	
		
			
			| 
				409
			 | 
			
				
			 | 
			
			
				
				-			to-currticks(), status, txstatus); 
			 | 
		
		
	
		
			
			| 
				410
			 | 
			
				
			 | 
			
			
				
				-#endif 
			 | 
		
		
	
		
			
			| 
				411
			 | 
			
				
			 | 
			
			
				
				-	} else { 
			 | 
		
		
	
		
			
			| 
				412
			 | 
			
				
			 | 
			
			
				
				-#ifdef	DEBUG_TX 
			 | 
		
		
	
		
			
			| 
				413
			 | 
			
				
			 | 
			
			
				
				-		printf("tx timeout/error (%d ticks), status %hX txstatus %X\n", 
			 | 
		
		
	
		
			
			| 
				414
			 | 
			
				
			 | 
			
			
				
				-			currticks()-to, status, txstatus); 
			 | 
		
		
	
		
			
			| 
				415
			 | 
			
				
			 | 
			
			
				
				-#endif 
			 | 
		
		
	
		
			
			| 
				416
			 | 
			
				
			 | 
			
			
				
				-		rtl_reset(nic); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				358
			 | 
			
			
				
				+	/* Free any old TX buffers that hadn't yet completed */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				359
			 | 
			
			
				
				+	for ( i = 0 ; i < TX_RING_SIZE ; i++ ) { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				360
			 | 
			
			
				
				+		if ( rtl->tx.pkb[i] ) { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				361
			 | 
			
			
				
				+			free_pkb ( rtl->tx.pkb[i] ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				362
			 | 
			
			
				
				+			rtl->tx.pkb[i] = NULL; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				363
			 | 
			
			
				
				+			DBG ( "TX id %d discarded\n", i ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				364
			 | 
			
			
				
				+		} 
			 | 
		
		
	
		
			
			| 
				417
			 | 
			
				365
			 | 
			
			
				
				 	} 
			 | 
		
		
	
		
			
			| 
				418
			 | 
			
				366
			 | 
			
			
				
				 } 
			 | 
		
		
	
		
			
			| 
				419
			 | 
			
				367
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				420
			 | 
			
				
			 | 
			
			
				
				-static int rtl_poll(struct nic *nic, int retrieve) 
			 | 
		
		
	
		
			
			| 
				421
			 | 
			
				
			 | 
			
			
				
				-{ 
			 | 
		
		
	
		
			
			| 
				422
			 | 
			
				
			 | 
			
			
				
				-	unsigned int status; 
			 | 
		
		
	
		
			
			| 
				423
			 | 
			
				
			 | 
			
			
				
				-	unsigned int ring_offs; 
			 | 
		
		
	
		
			
			| 
				424
			 | 
			
				
			 | 
			
			
				
				-	unsigned int rx_size, rx_status; 
			 | 
		
		
	
		
			
			| 
				425
			 | 
			
				
			 | 
			
			
				
				- 
			 | 
		
		
	
		
			
			| 
				426
			 | 
			
				
			 | 
			
			
				
				-	if (inb(nic->ioaddr + ChipCmd) & RxBufEmpty) { 
			 | 
		
		
	
		
			
			| 
				427
			 | 
			
				
			 | 
			
			
				
				-		return 0; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				368
			 | 
			
			
				
				+/**  
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				369
			 | 
			
			
				
				+ * Transmit packet 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				370
			 | 
			
			
				
				+ * 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				371
			 | 
			
			
				
				+ * @v netdev	Network device 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				372
			 | 
			
			
				
				+ * @v pkb	Packet buffer 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				373
			 | 
			
			
				
				+ * @ret rc	Return status code 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				374
			 | 
			
			
				
				+ */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				375
			 | 
			
			
				
				+static int rtl_transmit ( struct net_device *netdev, struct pk_buff *pkb ) { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				376
			 | 
			
			
				
				+	struct rtl8139_nic *rtl = netdev->priv; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				377
			 | 
			
			
				
				+	int align; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				378
			 | 
			
			
				
				+	int pad_len; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				379
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				380
			 | 
			
			
				
				+	/* Check for space in TX ring */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				381
			 | 
			
			
				
				+	if ( rtl->tx.pkb[rtl->tx.next] != NULL ) { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				382
			 | 
			
			
				
				+		printf ( "TX overflow\n" ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				383
			 | 
			
			
				
				+		free_pkb ( pkb ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				384
			 | 
			
			
				
				+		return -ENOBUFS; 
			 | 
		
		
	
		
			
			| 
				428
			 | 
			
				385
			 | 
			
			
				
				 	} 
			 | 
		
		
	
		
			
			| 
				429
			 | 
			
				386
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				430
			 | 
			
				
			 | 
			
			
				
				-	/* There is a packet ready */ 
			 | 
		
		
	
		
			
			| 
				431
			 | 
			
				
			 | 
			
			
				
				-	if ( ! retrieve ) return 1; 
			 | 
		
		
	
		
			
			| 
				432
			 | 
			
				
			 | 
			
			
				
				- 
			 | 
		
		
	
		
			
			| 
				433
			 | 
			
				
			 | 
			
			
				
				-	status = inw(nic->ioaddr + IntrStatus); 
			 | 
		
		
	
		
			
			| 
				434
			 | 
			
				
			 | 
			
			
				
				-	/* See below for the rest of the interrupt acknowledges.  */ 
			 | 
		
		
	
		
			
			| 
				435
			 | 
			
				
			 | 
			
			
				
				-	outw(status & ~(RxFIFOOver | RxOverflow | RxOK), nic->ioaddr + IntrStatus); 
			 | 
		
		
	
		
			
			| 
				436
			 | 
			
				
			 | 
			
			
				
				- 
			 | 
		
		
	
		
			
			| 
				437
			 | 
			
				
			 | 
			
			
				
				-#ifdef	DEBUG_RX 
			 | 
		
		
	
		
			
			| 
				438
			 | 
			
				
			 | 
			
			
				
				-	printf("rtl_poll: int %hX ", status); 
			 | 
		
		
	
		
			
			| 
				439
			 | 
			
				
			 | 
			
			
				
				-#endif 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				387
			 | 
			
			
				
				+	/* Align packet data */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				388
			 | 
			
			
				
				+	align = ( virt_to_bus ( pkb->data ) & 0x3 ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				389
			 | 
			
			
				
				+	pkb_push ( pkb, align ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				390
			 | 
			
			
				
				+	memmove ( pkb->data, pkb->data + align, pkb_len ( pkb ) - align ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				391
			 | 
			
			
				
				+	pkb_unput ( pkb, align ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				392
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				393
			 | 
			
			
				
				+	/* Pad to minimum packet length */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				394
			 | 
			
			
				
				+	pad_len = ( ETH_ZLEN - pkb_len ( pkb ) ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				395
			 | 
			
			
				
				+	if ( pad_len > 0 ) 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				396
			 | 
			
			
				
				+		memset ( pkb_put ( pkb, pad_len ), 0, pad_len ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				397
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				398
			 | 
			
			
				
				+	/* Add to TX ring */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				399
			 | 
			
			
				
				+	DBG ( "TX id %d at %lx+%x\n", rtl->tx.next, 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				400
			 | 
			
			
				
				+	      virt_to_bus ( pkb->data ), pkb_len ( pkb ) ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				401
			 | 
			
			
				
				+	rtl->tx.pkb[rtl->tx.next] = pkb; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				402
			 | 
			
			
				
				+	outl ( virt_to_bus ( pkb->data ), 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				403
			 | 
			
			
				
				+	       rtl->ioaddr + TxAddr0 + 4 * rtl->tx.next ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				404
			 | 
			
			
				
				+	outl ( ( ( ( TX_FIFO_THRESH & 0x7e0 ) << 11 ) | pkb_len ( pkb ) ), 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				405
			 | 
			
			
				
				+	       rtl->ioaddr + TxStatus0 + 4 * rtl->tx.next ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				406
			 | 
			
			
				
				+	rtl->tx.next = ( rtl->tx.next + 1 ) % TX_RING_SIZE; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				407
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				408
			 | 
			
			
				
				+	return 0; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				409
			 | 
			
			
				
				+} 
			 | 
		
		
	
		
			
			| 
				440
			 | 
			
				410
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				441
			 | 
			
				
			 | 
			
			
				
				-	ring_offs = cur_rx % RX_BUF_LEN; 
			 | 
		
		
	
		
			
			| 
				442
			 | 
			
				
			 | 
			
			
				
				-	rx_status = *(unsigned int*)(rx_ring + ring_offs); 
			 | 
		
		
	
		
			
			| 
				443
			 | 
			
				
			 | 
			
			
				
				-	rx_size = rx_status >> 16; 
			 | 
		
		
	
		
			
			| 
				444
			 | 
			
				
			 | 
			
			
				
				-	rx_status &= 0xffff; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				411
			 | 
			
			
				
				+/**  
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				412
			 | 
			
			
				
				+ * Poll for received packets 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				413
			 | 
			
			
				
				+ * 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				414
			 | 
			
			
				
				+ * @v netdev	Network device 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				415
			 | 
			
			
				
				+ */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				416
			 | 
			
			
				
				+static void rtl_poll ( struct net_device *netdev ) { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				417
			 | 
			
			
				
				+	struct rtl8139_nic *rtl = netdev->priv; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				418
			 | 
			
			
				
				+	unsigned int status; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				419
			 | 
			
			
				
				+	unsigned int tsad; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				420
			 | 
			
			
				
				+	unsigned int rx_status; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				421
			 | 
			
			
				
				+	unsigned int rx_len; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				422
			 | 
			
			
				
				+	struct pk_buff *rx_pkb; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				423
			 | 
			
			
				
				+	int wrapped_len; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				424
			 | 
			
			
				
				+	int i; 
			 | 
		
		
	
		
			
			| 
				445
			 | 
			
				425
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				446
			 | 
			
				
			 | 
			
			
				
				-	if ((rx_status & (RxBadSymbol|RxRunt|RxTooLong|RxCRCErr|RxBadAlign)) || 
			 | 
		
		
	
		
			
			| 
				447
			 | 
			
				
			 | 
			
			
				
				-	    (rx_size < ETH_ZLEN) || (rx_size > ETH_FRAME_LEN + 4)) { 
			 | 
		
		
	
		
			
			| 
				448
			 | 
			
				
			 | 
			
			
				
				-		printf("rx error %hX\n", rx_status); 
			 | 
		
		
	
		
			
			| 
				449
			 | 
			
				
			 | 
			
			
				
				-		rtl_reset(nic);	/* this clears all interrupts still pending */ 
			 | 
		
		
	
		
			
			| 
				450
			 | 
			
				
			 | 
			
			
				
				-		return 0; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				426
			 | 
			
			
				
				+	/* Acknowledge interrupts */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				427
			 | 
			
			
				
				+	status = inw ( rtl->ioaddr + IntrStatus ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				428
			 | 
			
			
				
				+	if ( ! status ) 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				429
			 | 
			
			
				
				+		return; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				430
			 | 
			
			
				
				+	outw ( status, rtl->ioaddr + IntrStatus ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				431
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				432
			 | 
			
			
				
				+	/* Handle TX completions */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				433
			 | 
			
			
				
				+	tsad = inw ( rtl->ioaddr + TxSummary ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				434
			 | 
			
			
				
				+	for ( i = 0 ; i < TX_RING_SIZE ; i++ ) { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				435
			 | 
			
			
				
				+		if ( ( rtl->tx.pkb[i] != NULL ) && ( tsad & ( 1 << i ) ) ) { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				436
			 | 
			
			
				
				+			DBG ( "TX id %d complete\n", i ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				437
			 | 
			
			
				
				+			free_pkb ( rtl->tx.pkb[i] ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				438
			 | 
			
			
				
				+			rtl->tx.pkb[i] = NULL; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				439
			 | 
			
			
				
				+		} 
			 | 
		
		
	
		
			
			| 
				451
			 | 
			
				440
			 | 
			
			
				
				 	} 
			 | 
		
		
	
		
			
			| 
				452
			 | 
			
				441
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				453
			 | 
			
				
			 | 
			
			
				
				-	/* Received a good packet */ 
			 | 
		
		
	
		
			
			| 
				454
			 | 
			
				
			 | 
			
			
				
				-	nic->packetlen = rx_size - 4;	/* no one cares about the FCS */ 
			 | 
		
		
	
		
			
			| 
				455
			 | 
			
				
			 | 
			
			
				
				-	if (ring_offs+4+rx_size-4 > RX_BUF_LEN) { 
			 | 
		
		
	
		
			
			| 
				456
			 | 
			
				
			 | 
			
			
				
				-		int semi_count = RX_BUF_LEN - ring_offs - 4; 
			 | 
		
		
	
		
			
			| 
				457
			 | 
			
				
			 | 
			
			
				
				- 
			 | 
		
		
	
		
			
			| 
				458
			 | 
			
				
			 | 
			
			
				
				-		memcpy(nic->packet, rx_ring + ring_offs + 4, semi_count); 
			 | 
		
		
	
		
			
			| 
				459
			 | 
			
				
			 | 
			
			
				
				-		memcpy(nic->packet+semi_count, rx_ring, rx_size-4-semi_count); 
			 | 
		
		
	
		
			
			| 
				460
			 | 
			
				
			 | 
			
			
				
				-#ifdef	DEBUG_RX 
			 | 
		
		
	
		
			
			| 
				461
			 | 
			
				
			 | 
			
			
				
				-		printf("rx packet %d+%d bytes", semi_count,rx_size-4-semi_count); 
			 | 
		
		
	
		
			
			| 
				462
			 | 
			
				
			 | 
			
			
				
				-#endif 
			 | 
		
		
	
		
			
			| 
				463
			 | 
			
				
			 | 
			
			
				
				-	} else { 
			 | 
		
		
	
		
			
			| 
				464
			 | 
			
				
			 | 
			
			
				
				-		memcpy(nic->packet, rx_ring + ring_offs + 4, nic->packetlen); 
			 | 
		
		
	
		
			
			| 
				465
			 | 
			
				
			 | 
			
			
				
				-#ifdef	DEBUG_RX 
			 | 
		
		
	
		
			
			| 
				466
			 | 
			
				
			 | 
			
			
				
				-		printf("rx packet %d bytes", rx_size-4); 
			 | 
		
		
	
		
			
			| 
				467
			 | 
			
				
			 | 
			
			
				
				-#endif 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				442
			 | 
			
			
				
				+	/* Handle received packets */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				443
			 | 
			
			
				
				+	while ( ! ( inw ( rtl->ioaddr + ChipCmd ) & RxBufEmpty ) ) { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				444
			 | 
			
			
				
				+		rx_status = * ( ( uint16_t * ) 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				445
			 | 
			
			
				
				+				( rtl->rx.ring + rtl->rx.offset ) ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				446
			 | 
			
			
				
				+		rx_len = * ( ( uint16_t * ) 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				447
			 | 
			
			
				
				+			     ( rtl->rx.ring + rtl->rx.offset + 2 ) ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				448
			 | 
			
			
				
				+		if ( rx_status & RxOK ) { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				449
			 | 
			
			
				
				+			DBG ( "RX packet at offset %x+%x\n", rtl->rx.offset, 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				450
			 | 
			
			
				
				+			      rx_len ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				451
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				452
			 | 
			
			
				
				+			rx_pkb = alloc_pkb ( rx_len ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				453
			 | 
			
			
				
				+			if ( ! rx_pkb ) { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				454
			 | 
			
			
				
				+				/* Leave packet for next call to poll() */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				455
			 | 
			
			
				
				+				break; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				456
			 | 
			
			
				
				+			} 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				457
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				458
			 | 
			
			
				
				+			wrapped_len = ( ( rtl->rx.offset + 4 + rx_len ) 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				459
			 | 
			
			
				
				+					- RX_BUF_LEN ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				460
			 | 
			
			
				
				+			if ( wrapped_len < 0 ) 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				461
			 | 
			
			
				
				+				wrapped_len = 0; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				462
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				463
			 | 
			
			
				
				+			memcpy ( pkb_put ( rx_pkb, rx_len - wrapped_len ), 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				464
			 | 
			
			
				
				+				 rtl->rx.ring + rtl->rx.offset + 4, 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				465
			 | 
			
			
				
				+				 rx_len - wrapped_len ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				466
			 | 
			
			
				
				+			memcpy ( pkb_put ( rx_pkb, wrapped_len ), 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				467
			 | 
			
			
				
				+				 rtl->rx.ring, wrapped_len ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				468
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				469
			 | 
			
			
				
				+			netdev_rx ( netdev, rx_pkb ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				470
			 | 
			
			
				
				+		} else { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				471
			 | 
			
			
				
				+			DBG ( "RX bad packet (status %#04x len %d)\n", 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				472
			 | 
			
			
				
				+			      rx_status, rx_len ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				473
			 | 
			
			
				
				+		} 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				474
			 | 
			
			
				
				+		rtl->rx.offset = ( ( ( rtl->rx.offset + 4 + rx_len + 3 ) & ~3 ) 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				475
			 | 
			
			
				
				+				   % RX_BUF_LEN ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				476
			 | 
			
			
				
				+		outw ( rtl->rx.offset - 16, rtl->ioaddr + RxBufPtr ); 
			 | 
		
		
	
		
			
			| 
				468
			 | 
			
				477
			 | 
			
			
				
				 	} 
			 | 
		
		
	
		
			
			| 
				469
			 | 
			
				
			 | 
			
			
				
				-#ifdef	DEBUG_RX 
			 | 
		
		
	
		
			
			| 
				470
			 | 
			
				
			 | 
			
			
				
				-	printf(" at %X type %hhX%hhX rxstatus %hX\n", 
			 | 
		
		
	
		
			
			| 
				471
			 | 
			
				
			 | 
			
			
				
				-		(unsigned long)(rx_ring+ring_offs+4), 
			 | 
		
		
	
		
			
			| 
				472
			 | 
			
				
			 | 
			
			
				
				-		nic->packet[12], nic->packet[13], rx_status); 
			 | 
		
		
	
		
			
			| 
				473
			 | 
			
				
			 | 
			
			
				
				-#endif 
			 | 
		
		
	
		
			
			| 
				474
			 | 
			
				
			 | 
			
			
				
				-	cur_rx = (cur_rx + rx_size + 4 + 3) & ~3; 
			 | 
		
		
	
		
			
			| 
				475
			 | 
			
				
			 | 
			
			
				
				-	outw(cur_rx - 16, nic->ioaddr + RxBufPtr); 
			 | 
		
		
	
		
			
			| 
				476
			 | 
			
				
			 | 
			
			
				
				-	/* See RTL8139 Programming Guide V0.1 for the official handling of 
			 | 
		
		
	
		
			
			| 
				477
			 | 
			
				
			 | 
			
			
				
				-	 * Rx overflow situations.  The document itself contains basically no 
			 | 
		
		
	
		
			
			| 
				478
			 | 
			
				
			 | 
			
			
				
				-	 * usable information, except for a few exception handling rules.  */ 
			 | 
		
		
	
		
			
			| 
				479
			 | 
			
				
			 | 
			
			
				
				-	outw(status & (RxFIFOOver | RxOverflow | RxOK), nic->ioaddr + IntrStatus); 
			 | 
		
		
	
		
			
			| 
				480
			 | 
			
				
			 | 
			
			
				
				-	return 1; 
			 | 
		
		
	
		
			
			| 
				481
			 | 
			
				478
			 | 
			
			
				
				 } 
			 | 
		
		
	
		
			
			| 
				482
			 | 
			
				479
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				480
			 | 
			
			
				
				+#if 0 
			 | 
		
		
	
		
			
			| 
				483
			 | 
			
				481
			 | 
			
			
				
				 static void rtl_irq(struct nic *nic, irq_action_t action) 
			 | 
		
		
	
		
			
			| 
				484
			 | 
			
				482
			 | 
			
			
				
				 { 
			 | 
		
		
	
		
			
			| 
				485
			 | 
			
				483
			 | 
			
			
				
				 	unsigned int mask; 
			 | 
		
		
	
	
		
			
			| 
				
			 | 
			
			
				
				@@ -489,10 +487,10 @@ static void rtl_irq(struct nic *nic, irq_action_t action) 
			 | 
		
		
	
		
			
			| 
				489
			 | 
			
				487
			 | 
			
			
				
				 	switch ( action ) { 
			 | 
		
		
	
		
			
			| 
				490
			 | 
			
				488
			 | 
			
			
				
				 	case DISABLE : 
			 | 
		
		
	
		
			
			| 
				491
			 | 
			
				489
			 | 
			
			
				
				 	case ENABLE : 
			 | 
		
		
	
		
			
			| 
				492
			 | 
			
				
			 | 
			
			
				
				-		mask = inw(nic->ioaddr + IntrMask); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				490
			 | 
			
			
				
				+		mask = inw(rtl->ioaddr + IntrMask); 
			 | 
		
		
	
		
			
			| 
				493
			 | 
			
				491
			 | 
			
			
				
				 		mask = mask & ~interested; 
			 | 
		
		
	
		
			
			| 
				494
			 | 
			
				492
			 | 
			
			
				
				 		if ( action == ENABLE ) mask = mask | interested; 
			 | 
		
		
	
		
			
			| 
				495
			 | 
			
				
			 | 
			
			
				
				-		outw(mask, nic->ioaddr + IntrMask); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				493
			 | 
			
			
				
				+		outw(mask, rtl->ioaddr + IntrMask); 
			 | 
		
		
	
		
			
			| 
				496
			 | 
			
				494
			 | 
			
			
				
				 		break; 
			 | 
		
		
	
		
			
			| 
				497
			 | 
			
				495
			 | 
			
			
				
				 	case FORCE : 
			 | 
		
		
	
		
			
			| 
				498
			 | 
			
				496
			 | 
			
			
				
				 		/* Apparently writing a 1 to this read-only bit of a 
			 | 
		
		
	
	
		
			
			| 
				
			 | 
			
			
				
				@@ -501,32 +499,88 @@ static void rtl_irq(struct nic *nic, irq_action_t action) 
			 | 
		
		
	
		
			
			| 
				501
			 | 
			
				499
			 | 
			
			
				
				 		 * not to write a datasheet, read the one for the 
			 | 
		
		
	
		
			
			| 
				502
			 | 
			
				500
			 | 
			
			
				
				 		 * RTL8139... 
			 | 
		
		
	
		
			
			| 
				503
			 | 
			
				501
			 | 
			
			
				
				 		 */ 
			 | 
		
		
	
		
			
			| 
				504
			 | 
			
				
			 | 
			
			
				
				-		outb(EROK, nic->ioaddr + RxEarlyStatus); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				502
			 | 
			
			
				
				+		outb(EROK, rtl->ioaddr + RxEarlyStatus); 
			 | 
		
		
	
		
			
			| 
				505
			 | 
			
				503
			 | 
			
			
				
				 		break; 
			 | 
		
		
	
		
			
			| 
				506
			 | 
			
				504
			 | 
			
			
				
				 	} 
			 | 
		
		
	
		
			
			| 
				507
			 | 
			
				505
			 | 
			
			
				
				 } 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				506
			 | 
			
			
				
				+#endif 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				507
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				508
			 | 
			
			
				
				+/** 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				509
			 | 
			
			
				
				+ * Probe PCI device 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				510
			 | 
			
			
				
				+ * 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				511
			 | 
			
			
				
				+ * @v pci	PCI device 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				512
			 | 
			
			
				
				+ * @v id	PCI ID 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				513
			 | 
			
			
				
				+ * @ret rc	Return status code 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				514
			 | 
			
			
				
				+ */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				515
			 | 
			
			
				
				+static int rtl_probe ( struct pci_device *pci, 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				516
			 | 
			
			
				
				+		       const struct pci_device_id *id __unused ) { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				517
			 | 
			
			
				
				+	struct net_device *netdev; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				518
			 | 
			
			
				
				+	struct rtl8139_nic *rtl = NULL; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				519
			 | 
			
			
				
				+	int rc; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				520
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				521
			 | 
			
			
				
				+	/* Fix up PCI device */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				522
			 | 
			
			
				
				+	adjust_pci_device ( pci ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				523
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				524
			 | 
			
			
				
				+	/* Allocate net device */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				525
			 | 
			
			
				
				+	netdev = alloc_etherdev ( sizeof ( *rtl ) ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				526
			 | 
			
			
				
				+	if ( ! netdev ) { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				527
			 | 
			
			
				
				+		rc = -ENOMEM; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				528
			 | 
			
			
				
				+		goto err; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				529
			 | 
			
			
				
				+	} 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				530
			 | 
			
			
				
				+	rtl = netdev->priv; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				531
			 | 
			
			
				
				+	pci_set_drvdata ( pci, netdev ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				532
			 | 
			
			
				
				+	memset ( rtl, 0, sizeof ( *rtl ) ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				533
			 | 
			
			
				
				+	rtl->ioaddr = pci->ioaddr; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				534
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				535
			 | 
			
			
				
				+	/* Reset the NIC, set up EEPROM access and read MAC address */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				536
			 | 
			
			
				
				+	rtl_reset ( rtl ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				537
			 | 
			
			
				
				+	rtl_init_eeprom ( rtl ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				538
			 | 
			
			
				
				+	rtl_read_mac ( rtl, netdev->ll_addr ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				539
			 | 
			
			
				
				+	 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				540
			 | 
			
			
				
				+	/* Point to NIC specific routines */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				541
			 | 
			
			
				
				+	//	netdev->open	 = rtl_open; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				542
			 | 
			
			
				
				+	//	netdev->close	 = rtl_close; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				543
			 | 
			
			
				
				+	netdev->transmit = rtl_transmit; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				544
			 | 
			
			
				
				+	netdev->poll	 = rtl_poll; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				545
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				546
			 | 
			
			
				
				+	/* Register network device */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				547
			 | 
			
			
				
				+	if ( ( rc = register_netdev ( netdev ) ) != 0 ) 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				548
			 | 
			
			
				
				+		goto err; 
			 | 
		
		
	
		
			
			| 
				508
			 | 
			
				549
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				509
			 | 
			
				
			 | 
			
			
				
				-static void rtl_disable ( struct nic *nic, struct pci_device *pci __unused ) { 
			 | 
		
		
	
		
			
			| 
				510
			 | 
			
				
			 | 
			
			
				
				-	nic_disable ( nic ); 
			 | 
		
		
	
		
			
			| 
				511
			 | 
			
				
			 | 
			
			
				
				-	/* merge reset and disable */ 
			 | 
		
		
	
		
			
			| 
				512
			 | 
			
				
			 | 
			
			
				
				-	rtl_reset(nic); 
			 | 
		
		
	
		
			
			| 
				513
			 | 
			
				550
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				514
			 | 
			
				
			 | 
			
			
				
				-	/* reset the chip */ 
			 | 
		
		
	
		
			
			| 
				515
			 | 
			
				
			 | 
			
			
				
				-	outb(CmdReset, nic->ioaddr + ChipCmd); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				551
			 | 
			
			
				
				+#warning "Hack alert" 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				552
			 | 
			
			
				
				+	rtl_open ( netdev ); 
			 | 
		
		
	
		
			
			| 
				516
			 | 
			
				553
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				517
			 | 
			
				
			 | 
			
			
				
				-	/* 10 ms timeout */ 
			 | 
		
		
	
		
			
			| 
				518
			 | 
			
				
			 | 
			
			
				
				-	load_timer2(10*TICKS_PER_MS); 
			 | 
		
		
	
		
			
			| 
				519
			 | 
			
				
			 | 
			
			
				
				-	while ((inb(nic->ioaddr + ChipCmd) & CmdReset) != 0 && timer2_running()) 
			 | 
		
		
	
		
			
			| 
				520
			 | 
			
				
			 | 
			
			
				
				-		/* wait */; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				554
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				555
			 | 
			
			
				
				+	return 0; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				556
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				557
			 | 
			
			
				
				+ err: 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				558
			 | 
			
			
				
				+	/* Disable NIC */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				559
			 | 
			
			
				
				+	if ( rtl ) 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				560
			 | 
			
			
				
				+		rtl_reset ( rtl ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				561
			 | 
			
			
				
				+	/* Free net device */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				562
			 | 
			
			
				
				+	free_netdev ( netdev ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				563
			 | 
			
			
				
				+	return rc; 
			 | 
		
		
	
		
			
			| 
				521
			 | 
			
				564
			 | 
			
			
				
				 } 
			 | 
		
		
	
		
			
			| 
				522
			 | 
			
				565
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				523
			 | 
			
				
			 | 
			
			
				
				-static struct nic_operations rtl_operations = { 
			 | 
		
		
	
		
			
			| 
				524
			 | 
			
				
			 | 
			
			
				
				-	.connect	= rtl_connect, 
			 | 
		
		
	
		
			
			| 
				525
			 | 
			
				
			 | 
			
			
				
				-	.poll		= rtl_poll, 
			 | 
		
		
	
		
			
			| 
				526
			 | 
			
				
			 | 
			
			
				
				-	.transmit	= rtl_transmit, 
			 | 
		
		
	
		
			
			| 
				527
			 | 
			
				
			 | 
			
			
				
				-	.irq		= rtl_irq, 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				566
			 | 
			
			
				
				+/** 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				567
			 | 
			
			
				
				+ * Remove PCI device 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				568
			 | 
			
			
				
				+ * 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				569
			 | 
			
			
				
				+ * @v pci	PCI device 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				570
			 | 
			
			
				
				+ */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				571
			 | 
			
			
				
				+static void rtl_remove ( struct pci_device *pci ) { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				572
			 | 
			
			
				
				+	struct net_device *netdev = pci_get_drvdata ( pci ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				573
			 | 
			
			
				
				+	struct rtl8139_nic *rtl = netdev->priv; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				574
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				575
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				576
			 | 
			
			
				
				+#warning "Hack alert"	 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				577
			 | 
			
			
				
				+	rtl_close ( netdev ); 
			 | 
		
		
	
		
			
			| 
				528
			 | 
			
				578
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				529
			 | 
			
				
			 | 
			
			
				
				-}; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				579
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				580
			 | 
			
			
				
				+	unregister_netdev ( netdev ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				581
			 | 
			
			
				
				+	rtl_reset ( rtl ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				582
			 | 
			
			
				
				+	free_netdev ( netdev ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				583
			 | 
			
			
				
				+} 
			 | 
		
		
	
		
			
			| 
				530
			 | 
			
				584
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				531
			 | 
			
				585
			 | 
			
			
				
				 static struct pci_device_id rtl8139_nics[] = { 
			 | 
		
		
	
		
			
			| 
				532
			 | 
			
				586
			 | 
			
			
				
				 PCI_ROM(0x10ec, 0x8129, "rtl8129",       "Realtek 8129"), 
			 | 
		
		
	
	
		
			
			| 
				
			 | 
			
			
				
				@@ -545,7 +599,9 @@ PCI_ROM(0x14ea, 0xab07, "fnw3800tx",     "Planex FNW-3800-TX"), 
			 | 
		
		
	
		
			
			| 
				545
			 | 
			
				599
			 | 
			
			
				
				 PCI_ROM(0xffff, 0x8139, "clone-rtl8139", "Cloned 8139"), 
			 | 
		
		
	
		
			
			| 
				546
			 | 
			
				600
			 | 
			
			
				
				 }; 
			 | 
		
		
	
		
			
			| 
				547
			 | 
			
				601
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				548
			 | 
			
				
			 | 
			
			
				
				-PCI_DRIVER ( rtl8139_driver, rtl8139_nics, PCI_NO_CLASS ); 
			 | 
		
		
	
		
			
			| 
				549
			 | 
			
				
			 | 
			
			
				
				- 
			 | 
		
		
	
		
			
			| 
				550
			 | 
			
				
			 | 
			
			
				
				-DRIVER ( "RTL8139", nic_driver, pci_driver, rtl8139_driver, 
			 | 
		
		
	
		
			
			| 
				551
			 | 
			
				
			 | 
			
			
				
				-	 rtl8139_probe, rtl_disable ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				602
			 | 
			
			
				
				+struct pci_driver rtl8139_driver __pci_driver = { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				603
			 | 
			
			
				
				+	.ids = rtl8139_nics, 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				604
			 | 
			
			
				
				+	.id_count = ( sizeof ( rtl8139_nics ) / sizeof ( rtl8139_nics[0] ) ), 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				605
			 | 
			
			
				
				+	.probe = rtl_probe, 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				606
			 | 
			
			
				
				+	.remove = rtl_remove, 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				607
			 | 
			
			
				
				+}; 
			 |