VirtualBox

source: vbox/trunk/src/VBox/Devices/PC/Etherboot-src/drivers/net/mtd80x.c@ 1300

Last change on this file since 1300 was 1, checked in by vboxsync, 55 years ago

import

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 36.1 KB
Line 
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 */
133enum 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*/
144enum chip_capability_flags {
145 HAS_MII_XCVR,
146 HAS_CHIP_XCVR,
147};
148
149static
150struct chip_info
151{
152 u16 dev_id;
153 int flag;
154}
155mtd80x_chips[] = {
156 {0x0800, HAS_MII_XCVR},
157 {0x0803, HAS_CHIP_XCVR},
158 {0x0891, HAS_MII_XCVR}
159 };
160static int chip_cnt = sizeof( mtd80x_chips ) / sizeof( struct chip_info );
161
162/* Offsets to the Command and Status Registers. */
163enum 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. */
193enum 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. */
216enum 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 */
238enum 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
255enum rx_desc_control_bits {
256 RXIC = 0x00800000, /* interrupt control */
257 RBSShift = 0,
258};
259
260enum 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
273enum 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
368TX Descriptor. All descriptors point to a
369part of this buffer */
370static 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
374RX Descriptor All descriptors point to a
375part of this buffer */
376static u8 rxb[PKT_BUF_SZ * RX_RING_SIZE]
377__attribute__ ((aligned(8)));
378
379/* The Tulip Rx and Tx buffer descriptors. */
380struct 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
392struct 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
430static struct mtd_private mtdx;
431
432static int mdio_read(struct nic * , int phy_id, int location);
433static void mdio_write(struct nic * , int phy_id, int location, int value);
434static void getlinktype(struct nic * );
435static void getlinkstatus(struct nic * );
436static void set_rx_mode(struct nic *);
437
438/**************************************************************************
439 * init_ring - setup the tx and rx descriptors
440 *************************************************************************/
441static 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/**************************************************************************
481RESET - Reset Adapter
482***************************************************************************/
483static 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/**************************************************************************
528POLL - Wait for a frame
529***************************************************************************/
530static 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/**************************************************************************
580TRANSMIT - Transmit a frame
581***************************************************************************/
582static 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/**************************************************************************
643DISABLE - Turn off ethernet interface
644***************************************************************************/
645static 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/**************************************************************************
656PROBE - Look for an adapter, this routine's visible to the outside
657***************************************************************************/
658
659static 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
764static 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/**************************************************************************/
772static 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/**************************************************************************/
788static 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
808static 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
826static 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
874static 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
912static 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
945static 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
978static 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
1082struct 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};
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette