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