1 | /**************************************************************************
|
---|
2 | *
|
---|
3 | * mtd80x.c: Etherboot device driver for the mtd80x Ethernet chip.
|
---|
4 | * Written 2004-2004 by Erdem Güven <[email protected]>
|
---|
5 | *
|
---|
6 | * This program is free software; you can redistribute it and/or modify
|
---|
7 | * it under the terms of the GNU General Public License as published by
|
---|
8 | * the Free Software Foundation; either version 2 of the License, or
|
---|
9 | * (at your option) any later version.
|
---|
10 | *
|
---|
11 | * This program is distributed in the hope that it will be useful,
|
---|
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
---|
14 | * GNU General Public License for more details.
|
---|
15 | *
|
---|
16 | * You should have received a copy of the GNU General Public License
|
---|
17 | * along with this program; if not, write to the Free Software
|
---|
18 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
---|
19 | *
|
---|
20 | * Portions of this code based on:
|
---|
21 | * fealnx.c: A Linux device driver for the mtd80x Ethernet chip
|
---|
22 | * Written 1998-2000 by Donald Becker
|
---|
23 | *
|
---|
24 | ***************************************************************************/
|
---|
25 |
|
---|
26 | /* to get some global routines like printf */
|
---|
27 | #include "etherboot.h"
|
---|
28 | /* to get the interface to the body of the program */
|
---|
29 | #include "nic.h"
|
---|
30 | /* to get the PCI support functions, if this is a PCI NIC */
|
---|
31 | #include "pci.h"
|
---|
32 |
|
---|
33 | #if 0
|
---|
34 | #define DBGPRNT( x ) printf x
|
---|
35 | #else
|
---|
36 | #define DBGPRNT( x )
|
---|
37 | #endif
|
---|
38 |
|
---|
39 | /* Condensed operations for readability. */
|
---|
40 | #define virt_to_le32desc(addr) cpu_to_le32(virt_to_bus(addr))
|
---|
41 | #define le32desc_to_virt(addr) bus_to_virt(le32_to_cpu(addr))
|
---|
42 | #define get_unaligned(ptr) (*(ptr))
|
---|
43 |
|
---|
44 |
|
---|
45 | /* Operational parameters that are set at compile time. */
|
---|
46 |
|
---|
47 | /* Keep the ring sizes a power of two for compile efficiency. */
|
---|
48 | /* The compiler will convert <unsigned>'%'<2^N> into a bit mask. */
|
---|
49 | /* Making the Tx ring too large decreases the effectiveness of channel */
|
---|
50 | /* bonding and packet priority. */
|
---|
51 | /* There are no ill effects from too-large receive rings. */
|
---|
52 | #define TX_RING_SIZE 2
|
---|
53 | #define TX_QUEUE_LEN 10 /* Limit ring entries actually used. */
|
---|
54 | #define RX_RING_SIZE 4
|
---|
55 |
|
---|
56 | /* Operational parameters that usually are not changed. */
|
---|
57 | /* Time in jiffies before concluding the transmitter is hung. */
|
---|
58 | #define HZ 100
|
---|
59 | #define TX_TIME_OUT (6*HZ)
|
---|
60 |
|
---|
61 | /* Allocation size of Rx buffers with normal sized Ethernet frames.
|
---|
62 | Do not change this value without good reason. This is not a limit,
|
---|
63 | but a way to keep a consistent allocation size among drivers.
|
---|
64 | */
|
---|
65 | #define PKT_BUF_SZ 1536
|
---|
66 |
|
---|
67 | /* Generic MII registers. */
|
---|
68 |
|
---|
69 | #define MII_BMCR 0x00 /* Basic mode control register */
|
---|
70 | #define MII_BMSR 0x01 /* Basic mode status register */
|
---|
71 | #define MII_PHYSID1 0x02 /* PHYS ID 1 */
|
---|
72 | #define MII_PHYSID2 0x03 /* PHYS ID 2 */
|
---|
73 | #define MII_ADVERTISE 0x04 /* Advertisement control reg */
|
---|
74 | #define MII_LPA 0x05 /* Link partner ability reg */
|
---|
75 | #define MII_EXPANSION 0x06 /* Expansion register */
|
---|
76 | #define MII_DCOUNTER 0x12 /* Disconnect counter */
|
---|
77 | #define MII_FCSCOUNTER 0x13 /* False carrier counter */
|
---|
78 | #define MII_NWAYTEST 0x14 /* N-way auto-neg test reg */
|
---|
79 | #define MII_RERRCOUNTER 0x15 /* Receive error counter */
|
---|
80 | #define MII_SREVISION 0x16 /* Silicon revision */
|
---|
81 | #define MII_RESV1 0x17 /* Reserved... */
|
---|
82 | #define MII_LBRERROR 0x18 /* Lpback, rx, bypass error */
|
---|
83 | #define MII_PHYADDR 0x19 /* PHY address */
|
---|
84 | #define MII_RESV2 0x1a /* Reserved... */
|
---|
85 | #define MII_TPISTATUS 0x1b /* TPI status for 10mbps */
|
---|
86 | #define MII_NCONFIG 0x1c /* Network interface config */
|
---|
87 |
|
---|
88 | /* Basic mode control register. */
|
---|
89 | #define BMCR_RESV 0x007f /* Unused... */
|
---|
90 | #define BMCR_CTST 0x0080 /* Collision test */
|
---|
91 | #define BMCR_FULLDPLX 0x0100 /* Full duplex */
|
---|
92 | #define BMCR_ANRESTART 0x0200 /* Auto negotiation restart */
|
---|
93 | #define BMCR_ISOLATE 0x0400 /* Disconnect DP83840 from MII */
|
---|
94 | #define BMCR_PDOWN 0x0800 /* Powerdown the DP83840 */
|
---|
95 | #define BMCR_ANENABLE 0x1000 /* Enable auto negotiation */
|
---|
96 | #define BMCR_SPEED100 0x2000 /* Select 100Mbps */
|
---|
97 | #define BMCR_LOOPBACK 0x4000 /* TXD loopback bits */
|
---|
98 | #define BMCR_RESET 0x8000 /* Reset the DP83840 */
|
---|
99 |
|
---|
100 | /* Basic mode status register. */
|
---|
101 | #define BMSR_ERCAP 0x0001 /* Ext-reg capability */
|
---|
102 | #define BMSR_JCD 0x0002 /* Jabber detected */
|
---|
103 | #define BMSR_LSTATUS 0x0004 /* Link status */
|
---|
104 | #define BMSR_ANEGCAPABLE 0x0008 /* Able to do auto-negotiation */
|
---|
105 | #define BMSR_RFAULT 0x0010 /* Remote fault detected */
|
---|
106 | #define BMSR_ANEGCOMPLETE 0x0020 /* Auto-negotiation complete */
|
---|
107 | #define BMSR_RESV 0x07c0 /* Unused... */
|
---|
108 | #define BMSR_10HALF 0x0800 /* Can do 10mbps, half-duplex */
|
---|
109 | #define BMSR_10FULL 0x1000 /* Can do 10mbps, full-duplex */
|
---|
110 | #define BMSR_100HALF 0x2000 /* Can do 100mbps, half-duplex */
|
---|
111 | #define BMSR_100FULL 0x4000 /* Can do 100mbps, full-duplex */
|
---|
112 | #define BMSR_100BASE4 0x8000 /* Can do 100mbps, 4k packets */
|
---|
113 |
|
---|
114 | /* Advertisement control register. */
|
---|
115 | #define ADVERTISE_SLCT 0x001f /* Selector bits */
|
---|
116 | #define ADVERTISE_CSMA 0x0001 /* Only selector supported */
|
---|
117 | #define ADVERTISE_10HALF 0x0020 /* Try for 10mbps half-duplex */
|
---|
118 | #define ADVERTISE_10FULL 0x0040 /* Try for 10mbps full-duplex */
|
---|
119 | #define ADVERTISE_100HALF 0x0080 /* Try for 100mbps half-duplex */
|
---|
120 | #define ADVERTISE_100FULL 0x0100 /* Try for 100mbps full-duplex */
|
---|
121 | #define ADVERTISE_100BASE4 0x0200 /* Try for 100mbps 4k packets */
|
---|
122 | #define ADVERTISE_RESV 0x1c00 /* Unused... */
|
---|
123 | #define ADVERTISE_RFAULT 0x2000 /* Say we can detect faults */
|
---|
124 | #define ADVERTISE_LPACK 0x4000 /* Ack link partners response */
|
---|
125 | #define ADVERTISE_NPAGE 0x8000 /* Next page bit */
|
---|
126 |
|
---|
127 | #define ADVERTISE_FULL (ADVERTISE_100FULL | ADVERTISE_10FULL | \
|
---|
128 | ADVERTISE_CSMA)
|
---|
129 | #define ADVERTISE_ALL (ADVERTISE_10HALF | ADVERTISE_10FULL | \
|
---|
130 | ADVERTISE_100HALF | ADVERTISE_100FULL)
|
---|
131 |
|
---|
132 | /* for different PHY */
|
---|
133 | enum phy_type_flags {
|
---|
134 | MysonPHY = 1,
|
---|
135 | AhdocPHY = 2,
|
---|
136 | SeeqPHY = 3,
|
---|
137 | MarvellPHY = 4,
|
---|
138 | Myson981 = 5,
|
---|
139 | LevelOnePHY = 6,
|
---|
140 | OtherPHY = 10,
|
---|
141 | };
|
---|
142 |
|
---|
143 | /* A chip capabilities table*/
|
---|
144 | enum chip_capability_flags {
|
---|
145 | HAS_MII_XCVR,
|
---|
146 | HAS_CHIP_XCVR,
|
---|
147 | };
|
---|
148 |
|
---|
149 | static
|
---|
150 | struct chip_info
|
---|
151 | {
|
---|
152 | u16 dev_id;
|
---|
153 | int flag;
|
---|
154 | }
|
---|
155 | mtd80x_chips[] = {
|
---|
156 | {0x0800, HAS_MII_XCVR},
|
---|
157 | {0x0803, HAS_CHIP_XCVR},
|
---|
158 | {0x0891, HAS_MII_XCVR}
|
---|
159 | };
|
---|
160 | static int chip_cnt = sizeof( mtd80x_chips ) / sizeof( struct chip_info );
|
---|
161 |
|
---|
162 | /* Offsets to the Command and Status Registers. */
|
---|
163 | enum mtd_offsets {
|
---|
164 | PAR0 = 0x0, /* physical address 0-3 */
|
---|
165 | PAR1 = 0x04, /* physical address 4-5 */
|
---|
166 | MAR0 = 0x08, /* multicast address 0-3 */
|
---|
167 | MAR1 = 0x0C, /* multicast address 4-7 */
|
---|
168 | FAR0 = 0x10, /* flow-control address 0-3 */
|
---|
169 | FAR1 = 0x14, /* flow-control address 4-5 */
|
---|
170 | TCRRCR = 0x18, /* receive & transmit configuration */
|
---|
171 | BCR = 0x1C, /* bus command */
|
---|
172 | TXPDR = 0x20, /* transmit polling demand */
|
---|
173 | RXPDR = 0x24, /* receive polling demand */
|
---|
174 | RXCWP = 0x28, /* receive current word pointer */
|
---|
175 | TXLBA = 0x2C, /* transmit list base address */
|
---|
176 | RXLBA = 0x30, /* receive list base address */
|
---|
177 | ISR = 0x34, /* interrupt status */
|
---|
178 | IMR = 0x38, /* interrupt mask */
|
---|
179 | FTH = 0x3C, /* flow control high/low threshold */
|
---|
180 | MANAGEMENT = 0x40, /* bootrom/eeprom and mii management */
|
---|
181 | TALLY = 0x44, /* tally counters for crc and mpa */
|
---|
182 | TSR = 0x48, /* tally counter for transmit status */
|
---|
183 | BMCRSR = 0x4c, /* basic mode control and status */
|
---|
184 | PHYIDENTIFIER = 0x50, /* phy identifier */
|
---|
185 | ANARANLPAR = 0x54, /* auto-negotiation advertisement and link
|
---|
186 | partner ability */
|
---|
187 | ANEROCR = 0x58, /* auto-negotiation expansion and pci conf. */
|
---|
188 | BPREMRPSR = 0x5c, /* bypass & receive error mask and phy status */
|
---|
189 | };
|
---|
190 |
|
---|
191 | /* Bits in the interrupt status/enable registers. */
|
---|
192 | /* The bits in the Intr Status/Enable registers, mostly interrupt sources. */
|
---|
193 | enum intr_status_bits {
|
---|
194 | RFCON = 0x00020000, /* receive flow control xon packet */
|
---|
195 | RFCOFF = 0x00010000, /* receive flow control xoff packet */
|
---|
196 | LSCStatus = 0x00008000, /* link status change */
|
---|
197 | ANCStatus = 0x00004000, /* autonegotiation completed */
|
---|
198 | FBE = 0x00002000, /* fatal bus error */
|
---|
199 | FBEMask = 0x00001800, /* mask bit12-11 */
|
---|
200 | ParityErr = 0x00000000, /* parity error */
|
---|
201 | TargetErr = 0x00001000, /* target abort */
|
---|
202 | MasterErr = 0x00000800, /* master error */
|
---|
203 | TUNF = 0x00000400, /* transmit underflow */
|
---|
204 | ROVF = 0x00000200, /* receive overflow */
|
---|
205 | ETI = 0x00000100, /* transmit early int */
|
---|
206 | ERI = 0x00000080, /* receive early int */
|
---|
207 | CNTOVF = 0x00000040, /* counter overflow */
|
---|
208 | RBU = 0x00000020, /* receive buffer unavailable */
|
---|
209 | TBU = 0x00000010, /* transmit buffer unavilable */
|
---|
210 | TI = 0x00000008, /* transmit interrupt */
|
---|
211 | RI = 0x00000004, /* receive interrupt */
|
---|
212 | RxErr = 0x00000002, /* receive error */
|
---|
213 | };
|
---|
214 |
|
---|
215 | /* Bits in the NetworkConfig register. */
|
---|
216 | enum rx_mode_bits {
|
---|
217 | RxModeMask = 0xe0,
|
---|
218 | AcceptAllPhys = 0x80, /* promiscuous mode */
|
---|
219 | AcceptBroadcast = 0x40, /* accept broadcast */
|
---|
220 | AcceptMulticast = 0x20, /* accept mutlicast */
|
---|
221 | AcceptRunt = 0x08, /* receive runt pkt */
|
---|
222 | ALP = 0x04, /* receive long pkt */
|
---|
223 | AcceptErr = 0x02, /* receive error pkt */
|
---|
224 |
|
---|
225 | AcceptMyPhys = 0x00000000,
|
---|
226 | RxEnable = 0x00000001,
|
---|
227 | RxFlowCtrl = 0x00002000,
|
---|
228 | TxEnable = 0x00040000,
|
---|
229 | TxModeFDX = 0x00100000,
|
---|
230 | TxThreshold = 0x00e00000,
|
---|
231 |
|
---|
232 | PS1000 = 0x00010000,
|
---|
233 | PS10 = 0x00080000,
|
---|
234 | FD = 0x00100000,
|
---|
235 | };
|
---|
236 |
|
---|
237 | /* Bits in network_desc.status */
|
---|
238 | enum rx_desc_status_bits {
|
---|
239 | RXOWN = 0x80000000, /* own bit */
|
---|
240 | FLNGMASK = 0x0fff0000, /* frame length */
|
---|
241 | FLNGShift = 16,
|
---|
242 | MARSTATUS = 0x00004000, /* multicast address received */
|
---|
243 | BARSTATUS = 0x00002000, /* broadcast address received */
|
---|
244 | PHYSTATUS = 0x00001000, /* physical address received */
|
---|
245 | RXFSD = 0x00000800, /* first descriptor */
|
---|
246 | RXLSD = 0x00000400, /* last descriptor */
|
---|
247 | ErrorSummary = 0x80, /* error summary */
|
---|
248 | RUNT = 0x40, /* runt packet received */
|
---|
249 | LONG = 0x20, /* long packet received */
|
---|
250 | FAE = 0x10, /* frame align error */
|
---|
251 | CRC = 0x08, /* crc error */
|
---|
252 | RXER = 0x04, /* receive error */
|
---|
253 | };
|
---|
254 |
|
---|
255 | enum rx_desc_control_bits {
|
---|
256 | RXIC = 0x00800000, /* interrupt control */
|
---|
257 | RBSShift = 0,
|
---|
258 | };
|
---|
259 |
|
---|
260 | enum tx_desc_status_bits {
|
---|
261 | TXOWN = 0x80000000, /* own bit */
|
---|
262 | JABTO = 0x00004000, /* jabber timeout */
|
---|
263 | CSL = 0x00002000, /* carrier sense lost */
|
---|
264 | LC = 0x00001000, /* late collision */
|
---|
265 | EC = 0x00000800, /* excessive collision */
|
---|
266 | UDF = 0x00000400, /* fifo underflow */
|
---|
267 | DFR = 0x00000200, /* deferred */
|
---|
268 | HF = 0x00000100, /* heartbeat fail */
|
---|
269 | NCRMask = 0x000000ff, /* collision retry count */
|
---|
270 | NCRShift = 0,
|
---|
271 | };
|
---|
272 |
|
---|
273 | enum tx_desc_control_bits {
|
---|
274 | TXIC = 0x80000000, /* interrupt control */
|
---|
275 | ETIControl = 0x40000000, /* early transmit interrupt */
|
---|
276 | TXLD = 0x20000000, /* last descriptor */
|
---|
277 | TXFD = 0x10000000, /* first descriptor */
|
---|
278 | CRCEnable = 0x08000000, /* crc control */
|
---|
279 | PADEnable = 0x04000000, /* padding control */
|
---|
280 | RetryTxLC = 0x02000000, /* retry late collision */
|
---|
281 | PKTSMask = 0x3ff800, /* packet size bit21-11 */
|
---|
282 | PKTSShift = 11,
|
---|
283 | TBSMask = 0x000007ff, /* transmit buffer bit 10-0 */
|
---|
284 | TBSShift = 0,
|
---|
285 | };
|
---|
286 |
|
---|
287 | /* BootROM/EEPROM/MII Management Register */
|
---|
288 | #define MASK_MIIR_MII_READ 0x00000000
|
---|
289 | #define MASK_MIIR_MII_WRITE 0x00000008
|
---|
290 | #define MASK_MIIR_MII_MDO 0x00000004
|
---|
291 | #define MASK_MIIR_MII_MDI 0x00000002
|
---|
292 | #define MASK_MIIR_MII_MDC 0x00000001
|
---|
293 |
|
---|
294 | /* ST+OP+PHYAD+REGAD+TA */
|
---|
295 | #define OP_READ 0x6000 /* ST:01+OP:10+PHYAD+REGAD+TA:Z0 */
|
---|
296 | #define OP_WRITE 0x5002 /* ST:01+OP:01+PHYAD+REGAD+TA:10 */
|
---|
297 |
|
---|
298 | /* ------------------------------------------------------------------------- */
|
---|
299 | /* Constants for Myson PHY */
|
---|
300 | /* ------------------------------------------------------------------------- */
|
---|
301 | #define MysonPHYID 0xd0000302
|
---|
302 | /* 89-7-27 add, (begin) */
|
---|
303 | #define MysonPHYID0 0x0302
|
---|
304 | #define StatusRegister 18
|
---|
305 | #define SPEED100 0x0400 // bit10
|
---|
306 | #define FULLMODE 0x0800 // bit11
|
---|
307 | /* 89-7-27 add, (end) */
|
---|
308 |
|
---|
309 | /* ------------------------------------------------------------------------- */
|
---|
310 | /* Constants for Seeq 80225 PHY */
|
---|
311 | /* ------------------------------------------------------------------------- */
|
---|
312 | #define SeeqPHYID0 0x0016
|
---|
313 |
|
---|
314 | #define MIIRegister18 18
|
---|
315 | #define SPD_DET_100 0x80
|
---|
316 | #define DPLX_DET_FULL 0x40
|
---|
317 |
|
---|
318 | /* ------------------------------------------------------------------------- */
|
---|
319 | /* Constants for Ahdoc 101 PHY */
|
---|
320 | /* ------------------------------------------------------------------------- */
|
---|
321 | #define AhdocPHYID0 0x0022
|
---|
322 |
|
---|
323 | #define DiagnosticReg 18
|
---|
324 | #define DPLX_FULL 0x0800
|
---|
325 | #define Speed_100 0x0400
|
---|
326 |
|
---|
327 | /* 89/6/13 add, */
|
---|
328 | /* -------------------------------------------------------------------------- */
|
---|
329 | /* Constants */
|
---|
330 | /* -------------------------------------------------------------------------- */
|
---|
331 | #define MarvellPHYID0 0x0141
|
---|
332 | #define LevelOnePHYID0 0x0013
|
---|
333 |
|
---|
334 | #define MII1000BaseTControlReg 9
|
---|
335 | #define MII1000BaseTStatusReg 10
|
---|
336 | #define SpecificReg 17
|
---|
337 |
|
---|
338 | /* for 1000BaseT Control Register */
|
---|
339 | #define PHYAbletoPerform1000FullDuplex 0x0200
|
---|
340 | #define PHYAbletoPerform1000HalfDuplex 0x0100
|
---|
341 | #define PHY1000AbilityMask 0x300
|
---|
342 |
|
---|
343 | // for phy specific status register, marvell phy.
|
---|
344 | #define SpeedMask 0x0c000
|
---|
345 | #define Speed_1000M 0x08000
|
---|
346 | #define Speed_100M 0x4000
|
---|
347 | #define Speed_10M 0
|
---|
348 | #define Full_Duplex 0x2000
|
---|
349 |
|
---|
350 | // 89/12/29 add, for phy specific status register, levelone phy, (begin)
|
---|
351 | #define LXT1000_100M 0x08000
|
---|
352 | #define LXT1000_1000M 0x0c000
|
---|
353 | #define LXT1000_Full 0x200
|
---|
354 | // 89/12/29 add, for phy specific status register, levelone phy, (end)
|
---|
355 |
|
---|
356 | #if 0
|
---|
357 | /* for 3-in-1 case */
|
---|
358 | #define PS10 0x00080000
|
---|
359 | #define FD 0x00100000
|
---|
360 | #define PS1000 0x00010000
|
---|
361 | #endif
|
---|
362 |
|
---|
363 | /* for PHY */
|
---|
364 | #define LinkIsUp 0x0004
|
---|
365 | #define LinkIsUp2 0x00040000
|
---|
366 |
|
---|
367 | /* Create a static buffer of size PKT_BUF_SZ for each
|
---|
368 | TX Descriptor. All descriptors point to a
|
---|
369 | part of this buffer */
|
---|
370 | static u8 txb[PKT_BUF_SZ * TX_RING_SIZE]
|
---|
371 | __attribute__ ((aligned(8)));
|
---|
372 |
|
---|
373 | /* Create a static buffer of size PKT_BUF_SZ for each
|
---|
374 | RX Descriptor All descriptors point to a
|
---|
375 | part of this buffer */
|
---|
376 | static u8 rxb[PKT_BUF_SZ * RX_RING_SIZE]
|
---|
377 | __attribute__ ((aligned(8)));
|
---|
378 |
|
---|
379 | /* The Tulip Rx and Tx buffer descriptors. */
|
---|
380 | struct mtd_desc
|
---|
381 | {
|
---|
382 | s32 status;
|
---|
383 | s32 control;
|
---|
384 | u32 buffer;
|
---|
385 | u32 next_desc;
|
---|
386 | struct mtd_desc *next_desc_logical;
|
---|
387 | u8* skbuff;
|
---|
388 | u32 reserved1;
|
---|
389 | u32 reserved2;
|
---|
390 | };
|
---|
391 |
|
---|
392 | struct mtd_private
|
---|
393 | {
|
---|
394 | struct mtd_desc rx_ring[RX_RING_SIZE];
|
---|
395 | struct mtd_desc tx_ring[TX_RING_SIZE];
|
---|
396 |
|
---|
397 | /* Frequently used values: keep some adjacent for cache effect. */
|
---|
398 | int flags;
|
---|
399 | struct pci_dev *pci_dev;
|
---|
400 | unsigned long crvalue;
|
---|
401 | unsigned long bcrvalue;
|
---|
402 | /*unsigned long imrvalue;*/
|
---|
403 | struct mtd_desc *cur_rx;
|
---|
404 | struct mtd_desc *lack_rxbuf;
|
---|
405 | int really_rx_count;
|
---|
406 | struct mtd_desc *cur_tx;
|
---|
407 | struct mtd_desc *cur_tx_copy;
|
---|
408 | int really_tx_count;
|
---|
409 | int free_tx_count;
|
---|
410 | unsigned int rx_buf_sz; /* Based on MTU+slack. */
|
---|
411 |
|
---|
412 | /* These values are keep track of the transceiver/media in use. */
|
---|
413 | unsigned int linkok;
|
---|
414 | unsigned int line_speed;
|
---|
415 | unsigned int duplexmode;
|
---|
416 | unsigned int default_port:
|
---|
417 | 4; /* Last dev->if_port value. */
|
---|
418 | unsigned int PHYType;
|
---|
419 |
|
---|
420 | /* MII transceiver section. */
|
---|
421 | int mii_cnt; /* MII device addresses. */
|
---|
422 | unsigned char phys[1]; /* MII device addresses. */
|
---|
423 |
|
---|
424 | /*other*/
|
---|
425 | const char *nic_name;
|
---|
426 | int ioaddr;
|
---|
427 | u16 dev_id;
|
---|
428 | };
|
---|
429 |
|
---|
430 | static struct mtd_private mtdx;
|
---|
431 |
|
---|
432 | static int mdio_read(struct nic * , int phy_id, int location);
|
---|
433 | static void mdio_write(struct nic * , int phy_id, int location, int value);
|
---|
434 | static void getlinktype(struct nic * );
|
---|
435 | static void getlinkstatus(struct nic * );
|
---|
436 | static void set_rx_mode(struct nic *);
|
---|
437 |
|
---|
438 | /**************************************************************************
|
---|
439 | * init_ring - setup the tx and rx descriptors
|
---|
440 | *************************************************************************/
|
---|
441 | static void init_ring(struct nic *nic)
|
---|
442 | {
|
---|
443 | int i;
|
---|
444 |
|
---|
445 | mtdx.cur_rx = &mtdx.rx_ring[0];
|
---|
446 |
|
---|
447 | mtdx.rx_buf_sz = PKT_BUF_SZ;
|
---|
448 | /*mtdx.rx_head_desc = &mtdx.rx_ring[0];*/
|
---|
449 |
|
---|
450 | /* Initialize all Rx descriptors. */
|
---|
451 | /* Fill in the Rx buffers. Handle allocation failure gracefully. */
|
---|
452 | for (i = 0; i < RX_RING_SIZE; i++)
|
---|
453 | {
|
---|
454 | mtdx.rx_ring[i].status = RXOWN;
|
---|
455 | mtdx.rx_ring[i].control = mtdx.rx_buf_sz << RBSShift;
|
---|
456 | mtdx.rx_ring[i].next_desc = virt_to_le32desc(&mtdx.rx_ring[i+1]);
|
---|
457 | mtdx.rx_ring[i].next_desc_logical = &mtdx.rx_ring[i+1];
|
---|
458 | mtdx.rx_ring[i].buffer = virt_to_le32desc(&rxb[i * PKT_BUF_SZ]);
|
---|
459 | mtdx.rx_ring[i].skbuff = &rxb[i * PKT_BUF_SZ];
|
---|
460 | }
|
---|
461 | /* Mark the last entry as wrapping the ring. */
|
---|
462 | mtdx.rx_ring[i-1].next_desc = virt_to_le32desc(&mtdx.rx_ring[0]);
|
---|
463 | mtdx.rx_ring[i-1].next_desc_logical = &mtdx.rx_ring[0];
|
---|
464 |
|
---|
465 | /* We only use one transmit buffer, but two
|
---|
466 | * descriptors so transmit engines have somewhere
|
---|
467 | * to point should they feel the need */
|
---|
468 | mtdx.tx_ring[0].status = 0x00000000;
|
---|
469 | mtdx.tx_ring[0].buffer = virt_to_bus(&txb[0]);
|
---|
470 | mtdx.tx_ring[0].next_desc = virt_to_le32desc(&mtdx.tx_ring[1]);
|
---|
471 |
|
---|
472 | /* This descriptor is never used */
|
---|
473 | mtdx.tx_ring[1].status = 0x00000000;
|
---|
474 | mtdx.tx_ring[1].buffer = 0; /*virt_to_bus(&txb[1]); */
|
---|
475 | mtdx.tx_ring[1].next_desc = virt_to_le32desc(&mtdx.tx_ring[0]);
|
---|
476 |
|
---|
477 | return;
|
---|
478 | }
|
---|
479 |
|
---|
480 | /**************************************************************************
|
---|
481 | RESET - Reset Adapter
|
---|
482 | ***************************************************************************/
|
---|
483 | static void mtd_reset(struct nic *nic)
|
---|
484 | {
|
---|
485 | /* Reset the chip to erase previous misconfiguration. */
|
---|
486 | outl(0x00000001, mtdx.ioaddr + BCR);
|
---|
487 |
|
---|
488 | init_ring(nic);
|
---|
489 |
|
---|
490 | outl(virt_to_bus(mtdx.rx_ring), mtdx.ioaddr + RXLBA);
|
---|
491 | outl(virt_to_bus(mtdx.tx_ring), mtdx.ioaddr + TXLBA);
|
---|
492 |
|
---|
493 | /* Initialize other registers. */
|
---|
494 | /* Configure the PCI bus bursts and FIFO thresholds. */
|
---|
495 | mtdx.bcrvalue = 0x10; /* little-endian, 8 burst length */
|
---|
496 | mtdx.crvalue = 0xa00; /* rx 128 burst length */
|
---|
497 |
|
---|
498 | if ( mtdx.dev_id == 0x891 ) {
|
---|
499 | mtdx.bcrvalue |= 0x200; /* set PROG bit */
|
---|
500 | mtdx.crvalue |= 0x02000000; /* set enhanced bit */
|
---|
501 | }
|
---|
502 |
|
---|
503 | outl( mtdx.bcrvalue, mtdx.ioaddr + BCR);
|
---|
504 |
|
---|
505 | /* Restart Rx engine if stopped. */
|
---|
506 | outl(0, mtdx.ioaddr + RXPDR);
|
---|
507 |
|
---|
508 | getlinkstatus(nic);
|
---|
509 | if (mtdx.linkok)
|
---|
510 | {
|
---|
511 | char* texts[]={"half","full","10","100","1000"};
|
---|
512 | getlinktype(nic);
|
---|
513 | DBGPRNT(("Link is OK : %s %s\n", texts[mtdx.duplexmode-1], texts[mtdx.line_speed+1] ));
|
---|
514 | } else
|
---|
515 | {
|
---|
516 | DBGPRNT(("No link!!!\n"));
|
---|
517 | }
|
---|
518 |
|
---|
519 | mtdx.crvalue |= /*TxEnable |*/ RxEnable | TxThreshold;
|
---|
520 | set_rx_mode(nic);
|
---|
521 |
|
---|
522 | /* Clear interrupts by setting the interrupt mask. */
|
---|
523 | outl(FBE | TUNF | CNTOVF | RBU | TI | RI, mtdx.ioaddr + ISR);
|
---|
524 | outl( 0, mtdx.ioaddr + IMR);
|
---|
525 | }
|
---|
526 |
|
---|
527 | /**************************************************************************
|
---|
528 | POLL - Wait for a frame
|
---|
529 | ***************************************************************************/
|
---|
530 | static int mtd_poll(struct nic *nic)
|
---|
531 | {
|
---|
532 | s32 rx_status = mtdx.cur_rx->status;
|
---|
533 | int retval = 0;
|
---|
534 |
|
---|
535 | if( ( rx_status & RXOWN ) != 0 )
|
---|
536 | {
|
---|
537 | return 0;
|
---|
538 | }
|
---|
539 |
|
---|
540 | if (rx_status & ErrorSummary)
|
---|
541 | { /* there was a fatal error */
|
---|
542 | printf( "%s: Receive error, Rx status %8.8x, Error(s) %s%s%s\n",
|
---|
543 | mtdx.nic_name, rx_status ,
|
---|
544 | (rx_status & (LONG | RUNT)) ? "length_error ":"",
|
---|
545 | (rx_status & RXER) ? "frame_error ":"",
|
---|
546 | (rx_status & CRC) ? "crc_error ":"" );
|
---|
547 | retval = 0;
|
---|
548 | } else if( !((rx_status & RXFSD) && (rx_status & RXLSD)) )
|
---|
549 | {
|
---|
550 | /* this pkt is too long, over one rx buffer */
|
---|
551 | printf("Pkt is too long, over one rx buffer.\n");
|
---|
552 | retval = 0;
|
---|
553 | } else
|
---|
554 | { /* this received pkt is ok */
|
---|
555 | /* Omit the four octet CRC from the length. */
|
---|
556 | short pkt_len = ((rx_status & FLNGMASK) >> FLNGShift) - 4;
|
---|
557 |
|
---|
558 | DBGPRNT(( " netdev_rx() normal Rx pkt length %d"
|
---|
559 | " status %x.\n", pkt_len, rx_status));
|
---|
560 |
|
---|
561 | nic->packetlen = pkt_len;
|
---|
562 | memcpy(nic->packet, mtdx.cur_rx->skbuff, pkt_len);
|
---|
563 |
|
---|
564 | retval = 1;
|
---|
565 | }
|
---|
566 |
|
---|
567 | while( ( mtdx.cur_rx->status & RXOWN ) == 0 )
|
---|
568 | {
|
---|
569 | mtdx.cur_rx->status = RXOWN;
|
---|
570 | mtdx.cur_rx = mtdx.cur_rx->next_desc_logical;
|
---|
571 | }
|
---|
572 |
|
---|
573 | /* Restart Rx engine if stopped. */
|
---|
574 | outl(0, mtdx.ioaddr + RXPDR);
|
---|
575 |
|
---|
576 | return retval;
|
---|
577 | }
|
---|
578 |
|
---|
579 | /**************************************************************************
|
---|
580 | TRANSMIT - Transmit a frame
|
---|
581 | ***************************************************************************/
|
---|
582 | static void mtd_transmit(
|
---|
583 | struct nic *nic,
|
---|
584 | const char *dest, /* Destination */
|
---|
585 | unsigned int type, /* Type */
|
---|
586 | unsigned int size, /* size */
|
---|
587 | const char *data) /* Packet */
|
---|
588 | {
|
---|
589 | u32 to;
|
---|
590 | u32 tx_status;
|
---|
591 | unsigned int nstype = htons ( type );
|
---|
592 |
|
---|
593 | memcpy( txb, dest, ETH_ALEN );
|
---|
594 | memcpy( txb + ETH_ALEN, nic->node_addr, ETH_ALEN );
|
---|
595 | memcpy( txb + 2 * ETH_ALEN, &nstype, 2 );
|
---|
596 | memcpy( txb + ETH_HLEN, data, size );
|
---|
597 |
|
---|
598 | size += ETH_HLEN;
|
---|
599 | size &= 0x0FFF;
|
---|
600 | while( size < ETH_ZLEN )
|
---|
601 | {
|
---|
602 | txb[size++] = '\0';
|
---|
603 | }
|
---|
604 |
|
---|
605 | mtdx.tx_ring[0].control = TXLD | TXFD | CRCEnable | PADEnable;
|
---|
606 | mtdx.tx_ring[0].control |= (size << PKTSShift); /* pkt size */
|
---|
607 | mtdx.tx_ring[0].control |= (size << TBSShift); /* buffer size */
|
---|
608 | mtdx.tx_ring[0].status = TXOWN;
|
---|
609 |
|
---|
610 | /* Point to transmit descriptor */
|
---|
611 | outl(virt_to_bus(mtdx.tx_ring), mtdx.ioaddr + TXLBA);
|
---|
612 | /* Enable Tx */
|
---|
613 | outl( mtdx.crvalue | TxEnable, mtdx.ioaddr + TCRRCR);
|
---|
614 | /* Wake the potentially-idle transmit channel. */
|
---|
615 | outl(0, mtdx.ioaddr + TXPDR);
|
---|
616 |
|
---|
617 | to = currticks() + TX_TIME_OUT;
|
---|
618 | while(( mtdx.tx_ring[0].status & TXOWN) && (currticks() < to));
|
---|
619 |
|
---|
620 | /* Disable Tx */
|
---|
621 | outl( mtdx.crvalue & (~TxEnable), mtdx.ioaddr + TCRRCR);
|
---|
622 |
|
---|
623 | tx_status = mtdx.tx_ring[0].status;
|
---|
624 | if (currticks() >= to){
|
---|
625 | DBGPRNT(("TX Time Out"));
|
---|
626 | } else if( tx_status & (CSL | LC | EC | UDF | HF)){
|
---|
627 | printf("Transmit error: %s %s %s %s %s.\n",
|
---|
628 | tx_status,
|
---|
629 | tx_status & EC ? "abort" : "",
|
---|
630 | tx_status & CSL ? "carrier" : "",
|
---|
631 | tx_status & LC ? "late" : "",
|
---|
632 | tx_status & UDF ? "fifo" : "",
|
---|
633 | tx_status & HF ? "heartbeat" : "" );
|
---|
634 | }
|
---|
635 |
|
---|
636 | /*hex_dump( txb, size );*/
|
---|
637 | /*pause();*/
|
---|
638 |
|
---|
639 | DBGPRNT(("TRANSMIT\n"));
|
---|
640 | }
|
---|
641 |
|
---|
642 | /**************************************************************************
|
---|
643 | DISABLE - Turn off ethernet interface
|
---|
644 | ***************************************************************************/
|
---|
645 | static void mtd_disable(struct dev *dev)
|
---|
646 | {
|
---|
647 | /* put the card in its initial state */
|
---|
648 | /* Disable Tx Rx*/
|
---|
649 | outl( mtdx.crvalue & (~TxEnable) & (~RxEnable), mtdx.ioaddr + TCRRCR);
|
---|
650 | /* Reset the chip to erase previous misconfiguration. */
|
---|
651 | mtd_reset((struct nic *) dev);
|
---|
652 | DBGPRNT(("DISABLE\n"));
|
---|
653 | }
|
---|
654 |
|
---|
655 | /**************************************************************************
|
---|
656 | PROBE - Look for an adapter, this routine's visible to the outside
|
---|
657 | ***************************************************************************/
|
---|
658 |
|
---|
659 | static int mtd_probe(struct dev *dev, struct pci_device *pci)
|
---|
660 | {
|
---|
661 | struct nic *nic = (struct nic *)dev;
|
---|
662 | int i;
|
---|
663 |
|
---|
664 | if (pci->ioaddr == 0)
|
---|
665 | {
|
---|
666 | return 0;
|
---|
667 | }
|
---|
668 |
|
---|
669 | printf(" - ");
|
---|
670 |
|
---|
671 | /* Mask the bit that says "this is an io addr" */
|
---|
672 | mtdx.ioaddr = pci->ioaddr & ~3;
|
---|
673 |
|
---|
674 | adjust_pci_device(pci);
|
---|
675 |
|
---|
676 | mtdx.nic_name = pci->name;
|
---|
677 | mtdx.dev_id = pci->dev_id;
|
---|
678 |
|
---|
679 | /* read ethernet id */
|
---|
680 | for (i = 0; i < 6; ++i)
|
---|
681 | {
|
---|
682 | nic->node_addr[i] = inb(mtdx.ioaddr + PAR0 + i);
|
---|
683 | }
|
---|
684 |
|
---|
685 | if (memcmp(nic->node_addr, "\0\0\0\0\0", 6) == 0)
|
---|
686 | {
|
---|
687 | return 0;
|
---|
688 | }
|
---|
689 |
|
---|
690 | DBGPRNT(("%s : ioaddr %#hX, addr %!\n",mtdx.nic_name, mtdx.ioaddr, nic->node_addr));
|
---|
691 |
|
---|
692 | /* Reset the chip to erase previous misconfiguration. */
|
---|
693 | outl(0x00000001, mtdx.ioaddr + BCR);
|
---|
694 |
|
---|
695 | /* find the connected MII xcvrs */
|
---|
696 |
|
---|
697 | if( mtdx.dev_id != 0x803 )
|
---|
698 | {
|
---|
699 | int phy, phy_idx = 0;
|
---|
700 |
|
---|
701 | for (phy = 1; phy < 32 && phy_idx < 1; phy++) {
|
---|
702 | int mii_status = mdio_read(nic, phy, 1);
|
---|
703 |
|
---|
704 | if (mii_status != 0xffff && mii_status != 0x0000) {
|
---|
705 | mtdx.phys[phy_idx] = phy;
|
---|
706 |
|
---|
707 | DBGPRNT(("%s: MII PHY found at address %d, status "
|
---|
708 | "0x%4.4x.\n", mtdx.nic_name, phy, mii_status));
|
---|
709 | /* get phy type */
|
---|
710 | {
|
---|
711 | unsigned int data;
|
---|
712 |
|
---|
713 | data = mdio_read(nic, mtdx.phys[phy_idx], 2);
|
---|
714 | if (data == SeeqPHYID0)
|
---|
715 | mtdx.PHYType = SeeqPHY;
|
---|
716 | else if (data == AhdocPHYID0)
|
---|
717 | mtdx.PHYType = AhdocPHY;
|
---|
718 | else if (data == MarvellPHYID0)
|
---|
719 | mtdx.PHYType = MarvellPHY;
|
---|
720 | else if (data == MysonPHYID0)
|
---|
721 | mtdx.PHYType = Myson981;
|
---|
722 | else if (data == LevelOnePHYID0)
|
---|
723 | mtdx.PHYType = LevelOnePHY;
|
---|
724 | else
|
---|
725 | mtdx.PHYType = OtherPHY;
|
---|
726 | }
|
---|
727 | phy_idx++;
|
---|
728 | }
|
---|
729 | }
|
---|
730 |
|
---|
731 | mtdx.mii_cnt = phy_idx;
|
---|
732 | if (phy_idx == 0) {
|
---|
733 | printf("%s: MII PHY not found -- this device may "
|
---|
734 | "not operate correctly.\n", mtdx.nic_name);
|
---|
735 | }
|
---|
736 | } else {
|
---|
737 | mtdx.phys[0] = 32;
|
---|
738 | /* get phy type */
|
---|
739 | if (inl(mtdx.ioaddr + PHYIDENTIFIER) == MysonPHYID ) {
|
---|
740 | mtdx.PHYType = MysonPHY;
|
---|
741 | DBGPRNT(("MysonPHY\n"));
|
---|
742 | } else {
|
---|
743 | mtdx.PHYType = OtherPHY;
|
---|
744 | DBGPRNT(("OtherPHY\n"));
|
---|
745 | }
|
---|
746 | }
|
---|
747 |
|
---|
748 | getlinkstatus(nic);
|
---|
749 | if( !mtdx.linkok )
|
---|
750 | {
|
---|
751 | printf("No link!!!\n");
|
---|
752 | return 0;
|
---|
753 | }
|
---|
754 |
|
---|
755 | mtd_reset( nic );
|
---|
756 |
|
---|
757 | /* point to NIC specific routines */
|
---|
758 | dev->disable = mtd_disable;
|
---|
759 | nic->poll = mtd_poll;
|
---|
760 | nic->transmit = mtd_transmit;
|
---|
761 | return 1;
|
---|
762 | }
|
---|
763 |
|
---|
764 | static struct pci_id mtd80x_nics[] =
|
---|
765 | {
|
---|
766 | PCI_ROM(0x1516, 0x0800, "MTD800", "Myson MTD800"),
|
---|
767 | PCI_ROM(0x1516, 0x0803, "MTD803", "Surecom EP-320X"),
|
---|
768 | PCI_ROM(0x1516, 0x0891, "MTD891", "Myson MTD891"),
|
---|
769 | };
|
---|
770 |
|
---|
771 | /**************************************************************************/
|
---|
772 | static void set_rx_mode(struct nic *nic)
|
---|
773 | {
|
---|
774 | u32 mc_filter[2]; /* Multicast hash filter */
|
---|
775 | u32 rx_mode;
|
---|
776 |
|
---|
777 | /* Too many to match, or accept all multicasts. */
|
---|
778 | mc_filter[1] = mc_filter[0] = ~0;
|
---|
779 | rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys;
|
---|
780 |
|
---|
781 | outl(mc_filter[0], mtdx.ioaddr + MAR0);
|
---|
782 | outl(mc_filter[1], mtdx.ioaddr + MAR1);
|
---|
783 |
|
---|
784 | mtdx.crvalue = ( mtdx.crvalue & ~RxModeMask ) | rx_mode;
|
---|
785 | outb( mtdx.crvalue, mtdx.ioaddr + TCRRCR);
|
---|
786 | }
|
---|
787 | /**************************************************************************/
|
---|
788 | static unsigned int m80x_read_tick(void)
|
---|
789 | /* function: Reads the Timer tick count register which decrements by 2 from */
|
---|
790 | /* 65536 to 0 every 1/36.414 of a second. Each 2 decrements of the */
|
---|
791 | /* count represents 838 nsec's. */
|
---|
792 | /* input : none. */
|
---|
793 | /* output : none. */
|
---|
794 | {
|
---|
795 | unsigned char tmp;
|
---|
796 | int value;
|
---|
797 |
|
---|
798 | outb((char) 0x06, 0x43); // Command 8254 to latch T0's count
|
---|
799 |
|
---|
800 | // now read the count.
|
---|
801 | tmp = (unsigned char) inb(0x40);
|
---|
802 | value = ((int) tmp) << 8;
|
---|
803 | tmp = (unsigned char) inb(0x40);
|
---|
804 | value |= (((int) tmp) & 0xff);
|
---|
805 | return (value);
|
---|
806 | }
|
---|
807 |
|
---|
808 | static void m80x_delay(unsigned int interval)
|
---|
809 | /* function: to wait for a specified time. */
|
---|
810 | /* input : interval ... the specified time. */
|
---|
811 | /* output : none. */
|
---|
812 | {
|
---|
813 | unsigned int interval1, interval2, i = 0;
|
---|
814 |
|
---|
815 | interval1 = m80x_read_tick(); // get initial value
|
---|
816 | do
|
---|
817 | {
|
---|
818 | interval2 = m80x_read_tick();
|
---|
819 | if (interval1 < interval2)
|
---|
820 | interval1 += 65536;
|
---|
821 | ++i;
|
---|
822 | } while (((interval1 - interval2) < (u16) interval) && (i < 65535));
|
---|
823 | }
|
---|
824 |
|
---|
825 |
|
---|
826 | static u32 m80x_send_cmd_to_phy(long miiport, int opcode, int phyad, int regad)
|
---|
827 | {
|
---|
828 | u32 miir;
|
---|
829 | int i;
|
---|
830 | unsigned int mask, data;
|
---|
831 |
|
---|
832 | /* enable MII output */
|
---|
833 | miir = (u32) inl(miiport);
|
---|
834 | miir &= 0xfffffff0;
|
---|
835 |
|
---|
836 | miir |= MASK_MIIR_MII_WRITE + MASK_MIIR_MII_MDO;
|
---|
837 |
|
---|
838 | /* send 32 1's preamble */
|
---|
839 | for (i = 0; i < 32; i++) {
|
---|
840 | /* low MDC; MDO is already high (miir) */
|
---|
841 | miir &= ~MASK_MIIR_MII_MDC;
|
---|
842 | outl(miir, miiport);
|
---|
843 |
|
---|
844 | /* high MDC */
|
---|
845 | miir |= MASK_MIIR_MII_MDC;
|
---|
846 | outl(miir, miiport);
|
---|
847 | }
|
---|
848 |
|
---|
849 | /* calculate ST+OP+PHYAD+REGAD+TA */
|
---|
850 | data = opcode | (phyad << 7) | (regad << 2);
|
---|
851 |
|
---|
852 | /* sent out */
|
---|
853 | mask = 0x8000;
|
---|
854 | while (mask) {
|
---|
855 | /* low MDC, prepare MDO */
|
---|
856 | miir &= ~(MASK_MIIR_MII_MDC + MASK_MIIR_MII_MDO);
|
---|
857 | if (mask & data)
|
---|
858 | miir |= MASK_MIIR_MII_MDO;
|
---|
859 |
|
---|
860 | outl(miir, miiport);
|
---|
861 | /* high MDC */
|
---|
862 | miir |= MASK_MIIR_MII_MDC;
|
---|
863 | outl(miir, miiport);
|
---|
864 | m80x_delay(30);
|
---|
865 |
|
---|
866 | /* next */
|
---|
867 | mask >>= 1;
|
---|
868 | if (mask == 0x2 && opcode == OP_READ)
|
---|
869 | miir &= ~MASK_MIIR_MII_WRITE;
|
---|
870 | }
|
---|
871 | return miir;
|
---|
872 | }
|
---|
873 |
|
---|
874 | static int mdio_read(struct nic *nic, int phyad, int regad)
|
---|
875 | {
|
---|
876 | long miiport = mtdx.ioaddr + MANAGEMENT;
|
---|
877 | u32 miir;
|
---|
878 | unsigned int mask, data;
|
---|
879 |
|
---|
880 | miir = m80x_send_cmd_to_phy(miiport, OP_READ, phyad, regad);
|
---|
881 |
|
---|
882 | /* read data */
|
---|
883 | mask = 0x8000;
|
---|
884 | data = 0;
|
---|
885 | while (mask)
|
---|
886 | {
|
---|
887 | /* low MDC */
|
---|
888 | miir &= ~MASK_MIIR_MII_MDC;
|
---|
889 | outl(miir, miiport);
|
---|
890 |
|
---|
891 | /* read MDI */
|
---|
892 | miir = inl(miiport);
|
---|
893 | if (miir & MASK_MIIR_MII_MDI)
|
---|
894 | data |= mask;
|
---|
895 |
|
---|
896 | /* high MDC, and wait */
|
---|
897 | miir |= MASK_MIIR_MII_MDC;
|
---|
898 | outl(miir, miiport);
|
---|
899 | m80x_delay((int) 30);
|
---|
900 |
|
---|
901 | /* next */
|
---|
902 | mask >>= 1;
|
---|
903 | }
|
---|
904 |
|
---|
905 | /* low MDC */
|
---|
906 | miir &= ~MASK_MIIR_MII_MDC;
|
---|
907 | outl(miir, miiport);
|
---|
908 |
|
---|
909 | return data & 0xffff;
|
---|
910 | }
|
---|
911 |
|
---|
912 | static void mdio_write(struct nic *nic, int phyad, int regad, int data)
|
---|
913 | {
|
---|
914 | long miiport = mtdx.ioaddr + MANAGEMENT;
|
---|
915 | u32 miir;
|
---|
916 | unsigned int mask;
|
---|
917 |
|
---|
918 | miir = m80x_send_cmd_to_phy(miiport, OP_WRITE, phyad, regad);
|
---|
919 |
|
---|
920 | /* write data */
|
---|
921 | mask = 0x8000;
|
---|
922 | while (mask)
|
---|
923 | {
|
---|
924 | /* low MDC, prepare MDO */
|
---|
925 | miir &= ~(MASK_MIIR_MII_MDC + MASK_MIIR_MII_MDO);
|
---|
926 | if (mask & data)
|
---|
927 | miir |= MASK_MIIR_MII_MDO;
|
---|
928 | outl(miir, miiport);
|
---|
929 |
|
---|
930 | /* high MDC */
|
---|
931 | miir |= MASK_MIIR_MII_MDC;
|
---|
932 | outl(miir, miiport);
|
---|
933 |
|
---|
934 | /* next */
|
---|
935 | mask >>= 1;
|
---|
936 | }
|
---|
937 |
|
---|
938 | /* low MDC */
|
---|
939 | miir &= ~MASK_MIIR_MII_MDC;
|
---|
940 | outl(miir, miiport);
|
---|
941 |
|
---|
942 | return;
|
---|
943 | }
|
---|
944 |
|
---|
945 | static void getlinkstatus(struct nic *nic)
|
---|
946 | /* function: Routine will read MII Status Register to get link status. */
|
---|
947 | /* input : dev... pointer to the adapter block. */
|
---|
948 | /* output : none. */
|
---|
949 | {
|
---|
950 | unsigned int i, DelayTime = 0x1000;
|
---|
951 |
|
---|
952 | mtdx.linkok = 0;
|
---|
953 |
|
---|
954 | if (mtdx.PHYType == MysonPHY)
|
---|
955 | {
|
---|
956 | for (i = 0; i < DelayTime; ++i) {
|
---|
957 | if (inl(mtdx.ioaddr + BMCRSR) & LinkIsUp2) {
|
---|
958 | mtdx.linkok = 1;
|
---|
959 | return;
|
---|
960 | }
|
---|
961 | // delay
|
---|
962 | m80x_delay(100);
|
---|
963 | }
|
---|
964 | } else
|
---|
965 | {
|
---|
966 | for (i = 0; i < DelayTime; ++i) {
|
---|
967 | if (mdio_read(nic, mtdx.phys[0], MII_BMSR) & BMSR_LSTATUS) {
|
---|
968 | mtdx.linkok = 1;
|
---|
969 | return;
|
---|
970 | }
|
---|
971 | // delay
|
---|
972 | m80x_delay(100);
|
---|
973 | }
|
---|
974 | }
|
---|
975 | }
|
---|
976 |
|
---|
977 |
|
---|
978 | static void getlinktype(struct nic *dev)
|
---|
979 | {
|
---|
980 | if (mtdx.PHYType == MysonPHY)
|
---|
981 | { /* 3-in-1 case */
|
---|
982 | if (inl(mtdx.ioaddr + TCRRCR) & FD)
|
---|
983 | mtdx.duplexmode = 2; /* full duplex */
|
---|
984 | else
|
---|
985 | mtdx.duplexmode = 1; /* half duplex */
|
---|
986 | if (inl(mtdx.ioaddr + TCRRCR) & PS10)
|
---|
987 | mtdx.line_speed = 1; /* 10M */
|
---|
988 | else
|
---|
989 | mtdx.line_speed = 2; /* 100M */
|
---|
990 | } else
|
---|
991 | {
|
---|
992 | if (mtdx.PHYType == SeeqPHY) { /* this PHY is SEEQ 80225 */
|
---|
993 | unsigned int data;
|
---|
994 |
|
---|
995 | data = mdio_read(dev, mtdx.phys[0], MIIRegister18);
|
---|
996 | if (data & SPD_DET_100)
|
---|
997 | mtdx.line_speed = 2; /* 100M */
|
---|
998 | else
|
---|
999 | mtdx.line_speed = 1; /* 10M */
|
---|
1000 | if (data & DPLX_DET_FULL)
|
---|
1001 | mtdx.duplexmode = 2; /* full duplex mode */
|
---|
1002 | else
|
---|
1003 | mtdx.duplexmode = 1; /* half duplex mode */
|
---|
1004 | } else if (mtdx.PHYType == AhdocPHY) {
|
---|
1005 | unsigned int data;
|
---|
1006 |
|
---|
1007 | data = mdio_read(dev, mtdx.phys[0], DiagnosticReg);
|
---|
1008 | if (data & Speed_100)
|
---|
1009 | mtdx.line_speed = 2; /* 100M */
|
---|
1010 | else
|
---|
1011 | mtdx.line_speed = 1; /* 10M */
|
---|
1012 | if (data & DPLX_FULL)
|
---|
1013 | mtdx.duplexmode = 2; /* full duplex mode */
|
---|
1014 | else
|
---|
1015 | mtdx.duplexmode = 1; /* half duplex mode */
|
---|
1016 | }
|
---|
1017 | /* 89/6/13 add, (begin) */
|
---|
1018 | else if (mtdx.PHYType == MarvellPHY) {
|
---|
1019 | unsigned int data;
|
---|
1020 |
|
---|
1021 | data = mdio_read(dev, mtdx.phys[0], SpecificReg);
|
---|
1022 | if (data & Full_Duplex)
|
---|
1023 | mtdx.duplexmode = 2; /* full duplex mode */
|
---|
1024 | else
|
---|
1025 | mtdx.duplexmode = 1; /* half duplex mode */
|
---|
1026 | data &= SpeedMask;
|
---|
1027 | if (data == Speed_1000M)
|
---|
1028 | mtdx.line_speed = 3; /* 1000M */
|
---|
1029 | else if (data == Speed_100M)
|
---|
1030 | mtdx.line_speed = 2; /* 100M */
|
---|
1031 | else
|
---|
1032 | mtdx.line_speed = 1; /* 10M */
|
---|
1033 | }
|
---|
1034 | /* 89/6/13 add, (end) */
|
---|
1035 | /* 89/7/27 add, (begin) */
|
---|
1036 | else if (mtdx.PHYType == Myson981) {
|
---|
1037 | unsigned int data;
|
---|
1038 |
|
---|
1039 | data = mdio_read(dev, mtdx.phys[0], StatusRegister);
|
---|
1040 |
|
---|
1041 | if (data & SPEED100)
|
---|
1042 | mtdx.line_speed = 2;
|
---|
1043 | else
|
---|
1044 | mtdx.line_speed = 1;
|
---|
1045 |
|
---|
1046 | if (data & FULLMODE)
|
---|
1047 | mtdx.duplexmode = 2;
|
---|
1048 | else
|
---|
1049 | mtdx.duplexmode = 1;
|
---|
1050 | }
|
---|
1051 | /* 89/7/27 add, (end) */
|
---|
1052 | /* 89/12/29 add */
|
---|
1053 | else if (mtdx.PHYType == LevelOnePHY) {
|
---|
1054 | unsigned int data;
|
---|
1055 |
|
---|
1056 | data = mdio_read(dev, mtdx.phys[0], SpecificReg);
|
---|
1057 | if (data & LXT1000_Full)
|
---|
1058 | mtdx.duplexmode = 2; /* full duplex mode */
|
---|
1059 | else
|
---|
1060 | mtdx.duplexmode = 1; /* half duplex mode */
|
---|
1061 | data &= SpeedMask;
|
---|
1062 | if (data == LXT1000_1000M)
|
---|
1063 | mtdx.line_speed = 3; /* 1000M */
|
---|
1064 | else if (data == LXT1000_100M)
|
---|
1065 | mtdx.line_speed = 2; /* 100M */
|
---|
1066 | else
|
---|
1067 | mtdx.line_speed = 1; /* 10M */
|
---|
1068 | }
|
---|
1069 | // chage crvalue
|
---|
1070 | // mtdx.crvalue&=(~PS10)&(~FD);
|
---|
1071 | mtdx.crvalue &= (~PS10) & (~FD) & (~PS1000);
|
---|
1072 | if (mtdx.line_speed == 1)
|
---|
1073 | mtdx.crvalue |= PS10;
|
---|
1074 | else if (mtdx.line_speed == 3)
|
---|
1075 | mtdx.crvalue |= PS1000;
|
---|
1076 | if (mtdx.duplexmode == 2)
|
---|
1077 | mtdx.crvalue |= FD;
|
---|
1078 | }
|
---|
1079 | }
|
---|
1080 |
|
---|
1081 |
|
---|
1082 | struct pci_driver mtd80x_driver __pci_driver ={
|
---|
1083 | .type = NIC_DRIVER,
|
---|
1084 | .name = "MTD80X",
|
---|
1085 | .probe = mtd_probe,
|
---|
1086 | .ids = mtd80x_nics,
|
---|
1087 | .id_count = sizeof(mtd80x_nics)/sizeof(mtd80x_nics[0]),
|
---|
1088 | .class = 0,
|
---|
1089 | };
|
---|