]>
Commit | Line | Data |
---|---|---|
cd1a2927 MT |
1 | --- rtl8139.c.old 2004-01-25 17:49:38.000000000 +0000 |
2 | +++ rtl8139.c 2004-01-25 18:20:29.000000000 +0000 | |
3 | @@ -161,19 +161,11 @@ | |
4 | /* The RTL8139 can only transmit from a contiguous, aligned memory block. */ | |
5 | static unsigned char tx_buffer[TX_BUF_SIZE] __attribute__((aligned(4))); | |
6 | ||
7 | -/* I know that this is a MEGA HACK, but the tagged boot image specification | |
8 | - * states that we can do whatever we want below 0x10000 - so we do! */ | |
9 | -/* But we still give the user the choice of using an internal buffer | |
10 | - just in case - Ken */ | |
11 | -#ifdef USE_LOWMEM_BUFFER | |
12 | -#define rx_ring ((unsigned char *)(0x10000 - (RX_BUF_LEN + 16))) | |
13 | -#else | |
14 | static unsigned char rx_ring[RX_BUF_LEN+16] __attribute__((aligned(4))); | |
15 | -#endif | |
16 | ||
17 | struct nic *rtl8139_probe(struct nic *nic, unsigned short *probeaddrs, | |
18 | struct pci_device *pci); | |
19 | -static int read_eeprom(int location); | |
20 | +static int read_eeprom(int location, int addr_len); | |
21 | static void rtl_reset(struct nic *nic); | |
22 | static void rtl_transmit(struct nic *nic, const char *destaddr, | |
23 | unsigned int type, unsigned int len, const char *data); | |
24 | @@ -186,6 +178,8 @@ | |
25 | { | |
26 | int i; | |
27 | int speed10, fullduplex; | |
28 | + int addr_len; | |
29 | + unsigned short *ap = (unsigned short*)nic->node_addr; | |
30 | ||
31 | /* There are enough "RTL8139" strings on the console already, so | |
32 | * be brief and concentrate on the interesting pieces of info... */ | |
33 | @@ -199,15 +193,9 @@ | |
34 | /* Bring the chip out of low-power mode. */ | |
35 | outb(0x00, ioaddr + Config1); | |
36 | ||
37 | - if (read_eeprom(0) != 0xffff) { | |
38 | - unsigned short *ap = (unsigned short*)nic->node_addr; | |
39 | - for (i = 0; i < 3; i++) | |
40 | - *ap++ = read_eeprom(i + 7); | |
41 | - } else { | |
42 | - unsigned char *ap = (unsigned char*)nic->node_addr; | |
43 | - for (i = 0; i < ETH_ALEN; i++) | |
44 | - *ap++ = inb(ioaddr + MAC0 + i); | |
45 | - } | |
46 | + addr_len = read_eeprom(0,8) == 0x8129 ? 8 : 6; | |
47 | + for (i = 0; i < 3; i++) | |
48 | + *ap++ = read_eeprom(i + 7,addr_len); | |
49 | ||
50 | speed10 = inb(ioaddr + MediaStatus) & MSRSpeed10; | |
51 | fullduplex = inw(ioaddr + MII_BMCR) & BMCRDuplex; | |
52 | @@ -217,6 +205,10 @@ | |
53 | ||
54 | rtl_reset(nic); | |
55 | ||
56 | + if (inb(ioaddr + MediaStatus) & MSRLinkFail) { | |
57 | + printf("Cable not connected or other link failure\n"); | |
58 | + return(0); | |
59 | + } | |
60 | nic->reset = rtl_reset; | |
61 | nic->poll = rtl_poll; | |
62 | nic->transmit = rtl_transmit; | |
63 | @@ -244,22 +236,23 @@ | |
64 | #define eeprom_delay() inl(ee_addr) | |
65 | ||
66 | /* The EEPROM commands include the alway-set leading bit. */ | |
67 | -#define EE_WRITE_CMD (5 << 6) | |
68 | -#define EE_READ_CMD (6 << 6) | |
69 | -#define EE_ERASE_CMD (7 << 6) | |
70 | +#define EE_WRITE_CMD (5) | |
71 | +#define EE_READ_CMD (6) | |
72 | +#define EE_ERASE_CMD (7) | |
73 | ||
74 | -static int read_eeprom(int location) | |
75 | +static int read_eeprom(int location, int addr_len) | |
76 | { | |
77 | int i; | |
78 | unsigned int retval = 0; | |
79 | long ee_addr = ioaddr + Cfg9346; | |
80 | - int read_cmd = location | EE_READ_CMD; | |
81 | + int read_cmd = location | (EE_READ_CMD << addr_len); | |
82 | ||
83 | outb(EE_ENB & ~EE_CS, ee_addr); | |
84 | outb(EE_ENB, ee_addr); | |
85 | + eeprom_delay(); | |
86 | ||
87 | /* Shift the read command bits out. */ | |
88 | - for (i = 10; i >= 0; i--) { | |
89 | + for (i = 4 + addr_len; i >= 0; i--) { | |
90 | int dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0; | |
91 | outb(EE_ENB | dataval, ee_addr); | |
92 | eeprom_delay(); | |
93 | @@ -279,9 +272,28 @@ | |
94 | ||
95 | /* Terminate the EEPROM access. */ | |
96 | outb(~EE_CS, ee_addr); | |
97 | + eeprom_delay(); | |
98 | return retval; | |
99 | } | |
100 | ||
101 | +static const unsigned int rtl8139_rx_config = | |
102 | + (RX_BUF_LEN_IDX << 11) | | |
103 | + (RX_FIFO_THRESH << 13) | | |
104 | + (RX_DMA_BURST << 8); | |
105 | + | |
106 | +static void set_rx_mode(struct nic *nic) { | |
107 | + unsigned int mc_filter[2]; | |
108 | + int rx_mode; | |
109 | + /* !IFF_PROMISC */ | |
110 | + rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; | |
111 | + mc_filter[1] = mc_filter[0] = 0xffffffff; | |
112 | + | |
113 | + outl(rtl8139_rx_config | rx_mode, ioaddr + RxConfig); | |
114 | + | |
115 | + outl(mc_filter[0], ioaddr + MAR0 + 0); | |
116 | + outl(mc_filter[1], ioaddr + MAR0 + 4); | |
117 | +} | |
118 | + | |
119 | static void rtl_reset(struct nic* nic) | |
120 | { | |
121 | int i; | |
122 | @@ -316,17 +328,24 @@ | |
123 | #ifdef DEBUG_RX | |
124 | printf("rx ring address is %X\n",(unsigned long)rx_ring); | |
125 | #endif | |
126 | - outl((unsigned long)rx_ring, ioaddr + RxBuf); | |
127 | + outl((unsigned long)rx_ring, ioaddr + RxBuf); | |
128 | + | |
129 | + | |
130 | ||
131 | - /* Start the chip's Tx and Rx process. */ | |
132 | - outl(0, ioaddr + RxMissed); | |
133 | - /* set_rx_mode */ | |
134 | - outb(AcceptBroadcast|AcceptMyPhys, ioaddr + RxConfig); | |
135 | /* If we add multicast support, the MAR0 register would have to be | |
136 | * initialized to 0xffffffffffffffff (two 32 bit accesses). Etherboot | |
137 | * only needs broadcast (for ARP/RARP/BOOTP/DHCP) and unicast. */ | |
138 | + | |
139 | outb(CmdRxEnb | CmdTxEnb, ioaddr + ChipCmd); | |
140 | + | |
141 | + outl(rtl8139_rx_config, ioaddr + RxConfig); | |
142 | + | |
143 | + /* Start the chip's Tx and Rx process. */ | |
144 | + outl(0, ioaddr + RxMissed); | |
145 | ||
146 | + /* set_rx_mode */ | |
147 | + set_rx_mode(nic); | |
148 | + | |
149 | /* Disable all known interrupts by setting the interrupt mask. */ | |
150 | outw(0, ioaddr + IntrMask); | |
151 | } | |
152 | @@ -337,10 +356,11 @@ | |
153 | unsigned int status, to, nstype; | |
154 | unsigned long txstatus; | |
155 | ||
156 | + /* nstype assignment moved up here to avoid gcc 3.0.3 compiler bug */ | |
157 | + nstype = htons(type); | |
158 | memcpy(tx_buffer, destaddr, ETH_ALEN); | |
159 | memcpy(tx_buffer + ETH_ALEN, nic->node_addr, ETH_ALEN); | |
160 | - nstype = htons(type); | |
161 | - memcpy(tx_buffer + 2 * ETH_ALEN, (char*)&nstype, 2); | |
162 | + memcpy(tx_buffer + 2 * ETH_ALEN, &nstype, 2); | |
163 | memcpy(tx_buffer + ETH_HLEN, data, len); | |
164 | ||
165 | len += ETH_HLEN; | |
166 | @@ -354,7 +374,7 @@ | |
167 | tx_buffer[len++] = '\0'; | |
168 | } | |
169 | ||
170 | - outl((unsigned long)tx_buffer, ioaddr + TxAddr0 + cur_tx*4); | |
171 | + outl((unsigned long)tx_buffer, ioaddr + TxAddr0 + cur_tx*4); | |
172 | outl(((TX_FIFO_THRESH<<11) & 0x003f0000) | len, | |
173 | ioaddr + TxStatus0 + cur_tx*4); | |
174 | ||
175 | @@ -448,6 +468,8 @@ | |
176 | ||
177 | static void rtl_disable(struct nic *nic) | |
178 | { | |
179 | + rtl_reset(nic); | |
180 | + | |
181 | /* reset the chip */ | |
182 | outb(CmdReset, ioaddr + ChipCmd); | |
183 |