Warnings purge of drivers (continued)
[gpxe.git] / src / drivers / net / mtd80x.c
blob5d8987c7583eb2e180a71ab894b77c84fd667975
1 /**************************************************************************
3 * mtd80x.c: Etherboot device driver for the mtd80x Ethernet chip.
4 * Written 2004-2004 by Erdem Güven <zuencap@yahoo.com>
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.
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.
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.
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
24 ***************************************************************************/
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 <gpxe/pci.h>
32 #include <gpxe/ethernet.h>
34 /* Condensed operations for readability. */
35 #define virt_to_le32desc(addr) cpu_to_le32(virt_to_bus(addr))
36 #define le32desc_to_virt(addr) bus_to_virt(le32_to_cpu(addr))
37 #define get_unaligned(ptr) (*(ptr))
40 /* Operational parameters that are set at compile time. */
42 /* Keep the ring sizes a power of two for compile efficiency. */
43 /* The compiler will convert <unsigned>'%'<2^N> into a bit mask. */
44 /* Making the Tx ring too large decreases the effectiveness of channel */
45 /* bonding and packet priority. */
46 /* There are no ill effects from too-large receive rings. */
47 #define TX_RING_SIZE 2
48 #define TX_QUEUE_LEN 10 /* Limit ring entries actually used. */
49 #define RX_RING_SIZE 4
51 /* Operational parameters that usually are not changed. */
52 /* Time in jiffies before concluding the transmitter is hung. */
53 #define HZ 100
54 #define TX_TIME_OUT (6*HZ)
56 /* Allocation size of Rx buffers with normal sized Ethernet frames.
57 Do not change this value without good reason. This is not a limit,
58 but a way to keep a consistent allocation size among drivers.
60 #define PKT_BUF_SZ 1536
62 /* Generic MII registers. */
64 #define MII_BMCR 0x00 /* Basic mode control register */
65 #define MII_BMSR 0x01 /* Basic mode status register */
66 #define MII_PHYSID1 0x02 /* PHYS ID 1 */
67 #define MII_PHYSID2 0x03 /* PHYS ID 2 */
68 #define MII_ADVERTISE 0x04 /* Advertisement control reg */
69 #define MII_LPA 0x05 /* Link partner ability reg */
70 #define MII_EXPANSION 0x06 /* Expansion register */
71 #define MII_DCOUNTER 0x12 /* Disconnect counter */
72 #define MII_FCSCOUNTER 0x13 /* False carrier counter */
73 #define MII_NWAYTEST 0x14 /* N-way auto-neg test reg */
74 #define MII_RERRCOUNTER 0x15 /* Receive error counter */
75 #define MII_SREVISION 0x16 /* Silicon revision */
76 #define MII_RESV1 0x17 /* Reserved... */
77 #define MII_LBRERROR 0x18 /* Lpback, rx, bypass error */
78 #define MII_PHYADDR 0x19 /* PHY address */
79 #define MII_RESV2 0x1a /* Reserved... */
80 #define MII_TPISTATUS 0x1b /* TPI status for 10mbps */
81 #define MII_NCONFIG 0x1c /* Network interface config */
83 /* Basic mode control register. */
84 #define BMCR_RESV 0x007f /* Unused... */
85 #define BMCR_CTST 0x0080 /* Collision test */
86 #define BMCR_FULLDPLX 0x0100 /* Full duplex */
87 #define BMCR_ANRESTART 0x0200 /* Auto negotiation restart */
88 #define BMCR_ISOLATE 0x0400 /* Disconnect DP83840 from MII */
89 #define BMCR_PDOWN 0x0800 /* Powerdown the DP83840 */
90 #define BMCR_ANENABLE 0x1000 /* Enable auto negotiation */
91 #define BMCR_SPEED100 0x2000 /* Select 100Mbps */
92 #define BMCR_LOOPBACK 0x4000 /* TXD loopback bits */
93 #define BMCR_RESET 0x8000 /* Reset the DP83840 */
95 /* Basic mode status register. */
96 #define BMSR_ERCAP 0x0001 /* Ext-reg capability */
97 #define BMSR_JCD 0x0002 /* Jabber detected */
98 #define BMSR_LSTATUS 0x0004 /* Link status */
99 #define BMSR_ANEGCAPABLE 0x0008 /* Able to do auto-negotiation */
100 #define BMSR_RFAULT 0x0010 /* Remote fault detected */
101 #define BMSR_ANEGCOMPLETE 0x0020 /* Auto-negotiation complete */
102 #define BMSR_RESV 0x07c0 /* Unused... */
103 #define BMSR_10HALF 0x0800 /* Can do 10mbps, half-duplex */
104 #define BMSR_10FULL 0x1000 /* Can do 10mbps, full-duplex */
105 #define BMSR_100HALF 0x2000 /* Can do 100mbps, half-duplex */
106 #define BMSR_100FULL 0x4000 /* Can do 100mbps, full-duplex */
107 #define BMSR_100BASE4 0x8000 /* Can do 100mbps, 4k packets */
109 /* Advertisement control register. */
110 #define ADVERTISE_SLCT 0x001f /* Selector bits */
111 #define ADVERTISE_CSMA 0x0001 /* Only selector supported */
112 #define ADVERTISE_10HALF 0x0020 /* Try for 10mbps half-duplex */
113 #define ADVERTISE_10FULL 0x0040 /* Try for 10mbps full-duplex */
114 #define ADVERTISE_100HALF 0x0080 /* Try for 100mbps half-duplex */
115 #define ADVERTISE_100FULL 0x0100 /* Try for 100mbps full-duplex */
116 #define ADVERTISE_100BASE4 0x0200 /* Try for 100mbps 4k packets */
117 #define ADVERTISE_RESV 0x1c00 /* Unused... */
118 #define ADVERTISE_RFAULT 0x2000 /* Say we can detect faults */
119 #define ADVERTISE_LPACK 0x4000 /* Ack link partners response */
120 #define ADVERTISE_NPAGE 0x8000 /* Next page bit */
122 #define ADVERTISE_FULL (ADVERTISE_100FULL | ADVERTISE_10FULL | \
123 ADVERTISE_CSMA)
124 #define ADVERTISE_ALL (ADVERTISE_10HALF | ADVERTISE_10FULL | \
125 ADVERTISE_100HALF | ADVERTISE_100FULL)
127 /* for different PHY */
128 enum phy_type_flags {
129 MysonPHY = 1,
130 AhdocPHY = 2,
131 SeeqPHY = 3,
132 MarvellPHY = 4,
133 Myson981 = 5,
134 LevelOnePHY = 6,
135 OtherPHY = 10,
138 /* A chip capabilities table*/
139 enum chip_capability_flags {
140 HAS_MII_XCVR,
141 HAS_CHIP_XCVR,
144 #if 0 /* not used */
145 static
146 struct chip_info
148 u16 dev_id;
149 int flag;
151 mtd80x_chips[] = {
152 {0x0800, HAS_MII_XCVR},
153 {0x0803, HAS_CHIP_XCVR},
154 {0x0891, HAS_MII_XCVR}
156 static int chip_cnt = sizeof( mtd80x_chips ) / sizeof( struct chip_info );
157 #endif
159 /* Offsets to the Command and Status Registers. */
160 enum mtd_offsets {
161 PAR0 = 0x0, /* physical address 0-3 */
162 PAR1 = 0x04, /* physical address 4-5 */
163 MAR0 = 0x08, /* multicast address 0-3 */
164 MAR1 = 0x0C, /* multicast address 4-7 */
165 FAR0 = 0x10, /* flow-control address 0-3 */
166 FAR1 = 0x14, /* flow-control address 4-5 */
167 TCRRCR = 0x18, /* receive & transmit configuration */
168 BCR = 0x1C, /* bus command */
169 TXPDR = 0x20, /* transmit polling demand */
170 RXPDR = 0x24, /* receive polling demand */
171 RXCWP = 0x28, /* receive current word pointer */
172 TXLBA = 0x2C, /* transmit list base address */
173 RXLBA = 0x30, /* receive list base address */
174 ISR = 0x34, /* interrupt status */
175 IMR = 0x38, /* interrupt mask */
176 FTH = 0x3C, /* flow control high/low threshold */
177 MANAGEMENT = 0x40, /* bootrom/eeprom and mii management */
178 TALLY = 0x44, /* tally counters for crc and mpa */
179 TSR = 0x48, /* tally counter for transmit status */
180 BMCRSR = 0x4c, /* basic mode control and status */
181 PHYIDENTIFIER = 0x50, /* phy identifier */
182 ANARANLPAR = 0x54, /* auto-negotiation advertisement and link
183 partner ability */
184 ANEROCR = 0x58, /* auto-negotiation expansion and pci conf. */
185 BPREMRPSR = 0x5c, /* bypass & receive error mask and phy status */
188 /* Bits in the interrupt status/enable registers. */
189 /* The bits in the Intr Status/Enable registers, mostly interrupt sources. */
190 enum intr_status_bits {
191 RFCON = 0x00020000, /* receive flow control xon packet */
192 RFCOFF = 0x00010000, /* receive flow control xoff packet */
193 LSCStatus = 0x00008000, /* link status change */
194 ANCStatus = 0x00004000, /* autonegotiation completed */
195 FBE = 0x00002000, /* fatal bus error */
196 FBEMask = 0x00001800, /* mask bit12-11 */
197 ParityErr = 0x00000000, /* parity error */
198 TargetErr = 0x00001000, /* target abort */
199 MasterErr = 0x00000800, /* master error */
200 TUNF = 0x00000400, /* transmit underflow */
201 ROVF = 0x00000200, /* receive overflow */
202 ETI = 0x00000100, /* transmit early int */
203 ERI = 0x00000080, /* receive early int */
204 CNTOVF = 0x00000040, /* counter overflow */
205 RBU = 0x00000020, /* receive buffer unavailable */
206 TBU = 0x00000010, /* transmit buffer unavilable */
207 TI = 0x00000008, /* transmit interrupt */
208 RI = 0x00000004, /* receive interrupt */
209 RxErr = 0x00000002, /* receive error */
212 /* Bits in the NetworkConfig register. */
213 enum rx_mode_bits {
214 RxModeMask = 0xe0,
215 AcceptAllPhys = 0x80, /* promiscuous mode */
216 AcceptBroadcast = 0x40, /* accept broadcast */
217 AcceptMulticast = 0x20, /* accept mutlicast */
218 AcceptRunt = 0x08, /* receive runt pkt */
219 ALP = 0x04, /* receive long pkt */
220 AcceptErr = 0x02, /* receive error pkt */
222 AcceptMyPhys = 0x00000000,
223 RxEnable = 0x00000001,
224 RxFlowCtrl = 0x00002000,
225 TxEnable = 0x00040000,
226 TxModeFDX = 0x00100000,
227 TxThreshold = 0x00e00000,
229 PS1000 = 0x00010000,
230 PS10 = 0x00080000,
231 FD = 0x00100000,
234 /* Bits in network_desc.status */
235 enum rx_desc_status_bits {
236 RXOWN = 0x80000000, /* own bit */
237 FLNGMASK = 0x0fff0000, /* frame length */
238 FLNGShift = 16,
239 MARSTATUS = 0x00004000, /* multicast address received */
240 BARSTATUS = 0x00002000, /* broadcast address received */
241 PHYSTATUS = 0x00001000, /* physical address received */
242 RXFSD = 0x00000800, /* first descriptor */
243 RXLSD = 0x00000400, /* last descriptor */
244 ErrorSummary = 0x80, /* error summary */
245 RUNT = 0x40, /* runt packet received */
246 LONG = 0x20, /* long packet received */
247 FAE = 0x10, /* frame align error */
248 CRC = 0x08, /* crc error */
249 RXER = 0x04, /* receive error */
252 enum rx_desc_control_bits {
253 RXIC = 0x00800000, /* interrupt control */
254 RBSShift = 0,
257 enum tx_desc_status_bits {
258 TXOWN = 0x80000000, /* own bit */
259 JABTO = 0x00004000, /* jabber timeout */
260 CSL = 0x00002000, /* carrier sense lost */
261 LC = 0x00001000, /* late collision */
262 EC = 0x00000800, /* excessive collision */
263 UDF = 0x00000400, /* fifo underflow */
264 DFR = 0x00000200, /* deferred */
265 HF = 0x00000100, /* heartbeat fail */
266 NCRMask = 0x000000ff, /* collision retry count */
267 NCRShift = 0,
270 enum tx_desc_control_bits {
271 TXIC = 0x80000000, /* interrupt control */
272 ETIControl = 0x40000000, /* early transmit interrupt */
273 TXLD = 0x20000000, /* last descriptor */
274 TXFD = 0x10000000, /* first descriptor */
275 CRCEnable = 0x08000000, /* crc control */
276 PADEnable = 0x04000000, /* padding control */
277 RetryTxLC = 0x02000000, /* retry late collision */
278 PKTSMask = 0x3ff800, /* packet size bit21-11 */
279 PKTSShift = 11,
280 TBSMask = 0x000007ff, /* transmit buffer bit 10-0 */
281 TBSShift = 0,
284 /* BootROM/EEPROM/MII Management Register */
285 #define MASK_MIIR_MII_READ 0x00000000
286 #define MASK_MIIR_MII_WRITE 0x00000008
287 #define MASK_MIIR_MII_MDO 0x00000004
288 #define MASK_MIIR_MII_MDI 0x00000002
289 #define MASK_MIIR_MII_MDC 0x00000001
291 /* ST+OP+PHYAD+REGAD+TA */
292 #define OP_READ 0x6000 /* ST:01+OP:10+PHYAD+REGAD+TA:Z0 */
293 #define OP_WRITE 0x5002 /* ST:01+OP:01+PHYAD+REGAD+TA:10 */
295 /* ------------------------------------------------------------------------- */
296 /* Constants for Myson PHY */
297 /* ------------------------------------------------------------------------- */
298 #define MysonPHYID 0xd0000302
299 /* 89-7-27 add, (begin) */
300 #define MysonPHYID0 0x0302
301 #define StatusRegister 18
302 #define SPEED100 0x0400 // bit10
303 #define FULLMODE 0x0800 // bit11
304 /* 89-7-27 add, (end) */
306 /* ------------------------------------------------------------------------- */
307 /* Constants for Seeq 80225 PHY */
308 /* ------------------------------------------------------------------------- */
309 #define SeeqPHYID0 0x0016
311 #define MIIRegister18 18
312 #define SPD_DET_100 0x80
313 #define DPLX_DET_FULL 0x40
315 /* ------------------------------------------------------------------------- */
316 /* Constants for Ahdoc 101 PHY */
317 /* ------------------------------------------------------------------------- */
318 #define AhdocPHYID0 0x0022
320 #define DiagnosticReg 18
321 #define DPLX_FULL 0x0800
322 #define Speed_100 0x0400
324 /* 89/6/13 add, */
325 /* -------------------------------------------------------------------------- */
326 /* Constants */
327 /* -------------------------------------------------------------------------- */
328 #define MarvellPHYID0 0x0141
329 #define LevelOnePHYID0 0x0013
331 #define MII1000BaseTControlReg 9
332 #define MII1000BaseTStatusReg 10
333 #define SpecificReg 17
335 /* for 1000BaseT Control Register */
336 #define PHYAbletoPerform1000FullDuplex 0x0200
337 #define PHYAbletoPerform1000HalfDuplex 0x0100
338 #define PHY1000AbilityMask 0x300
340 // for phy specific status register, marvell phy.
341 #define SpeedMask 0x0c000
342 #define Speed_1000M 0x08000
343 #define Speed_100M 0x4000
344 #define Speed_10M 0
345 #define Full_Duplex 0x2000
347 // 89/12/29 add, for phy specific status register, levelone phy, (begin)
348 #define LXT1000_100M 0x08000
349 #define LXT1000_1000M 0x0c000
350 #define LXT1000_Full 0x200
351 // 89/12/29 add, for phy specific status register, levelone phy, (end)
353 #if 0
354 /* for 3-in-1 case */
355 #define PS10 0x00080000
356 #define FD 0x00100000
357 #define PS1000 0x00010000
358 #endif
360 /* for PHY */
361 #define LinkIsUp 0x0004
362 #define LinkIsUp2 0x00040000
364 /* Create a static buffer of size PKT_BUF_SZ for each
365 RX and TX Descriptor. All descriptors point to a
366 part of this buffer */
367 struct {
368 u8 txb[PKT_BUF_SZ * TX_RING_SIZE] __attribute__ ((aligned(8)));
369 u8 rxb[PKT_BUF_SZ * RX_RING_SIZE] __attribute__ ((aligned(8)));
370 } mtd80x_bufs __shared;
371 #define txb mtd80x_bufs.txb
372 #define rxb mtd80x_bufs.rxb
374 /* The Tulip Rx and Tx buffer descriptors. */
375 struct mtd_desc
377 s32 status;
378 s32 control;
379 u32 buffer;
380 u32 next_desc;
381 struct mtd_desc *next_desc_logical;
382 u8* skbuff;
383 u32 reserved1;
384 u32 reserved2;
387 struct mtd_private
389 struct mtd_desc rx_ring[RX_RING_SIZE];
390 struct mtd_desc tx_ring[TX_RING_SIZE];
392 /* Frequently used values: keep some adjacent for cache effect. */
393 int flags;
394 struct pci_dev *pci_dev;
395 unsigned long crvalue;
396 unsigned long bcrvalue;
397 /*unsigned long imrvalue;*/
398 struct mtd_desc *cur_rx;
399 struct mtd_desc *lack_rxbuf;
400 int really_rx_count;
401 struct mtd_desc *cur_tx;
402 struct mtd_desc *cur_tx_copy;
403 int really_tx_count;
404 int free_tx_count;
405 unsigned int rx_buf_sz; /* Based on MTU+slack. */
407 /* These values are keep track of the transceiver/media in use. */
408 unsigned int linkok;
409 unsigned int line_speed;
410 unsigned int duplexmode;
411 unsigned int default_port:
412 4; /* Last dev->if_port value. */
413 unsigned int PHYType;
415 /* MII transceiver section. */
416 int mii_cnt; /* MII device addresses. */
417 unsigned char phys[1]; /* MII device addresses. */
419 /*other*/
420 const char *nic_name;
421 int ioaddr;
422 u16 dev_id;
425 static struct mtd_private mtdx;
427 static int mdio_read(struct nic * , int phy_id, int location);
428 static void getlinktype(struct nic * );
429 static void getlinkstatus(struct nic * );
430 static void set_rx_mode(struct nic *);
432 /**************************************************************************
433 * init_ring - setup the tx and rx descriptors
434 *************************************************************************/
435 static void init_ring(struct nic *nic __unused)
437 int i;
439 mtdx.cur_rx = &mtdx.rx_ring[0];
441 mtdx.rx_buf_sz = PKT_BUF_SZ;
442 /*mtdx.rx_head_desc = &mtdx.rx_ring[0];*/
444 /* Initialize all Rx descriptors. */
445 /* Fill in the Rx buffers. Handle allocation failure gracefully. */
446 for (i = 0; i < RX_RING_SIZE; i++)
448 mtdx.rx_ring[i].status = RXOWN;
449 mtdx.rx_ring[i].control = mtdx.rx_buf_sz << RBSShift;
450 mtdx.rx_ring[i].next_desc = virt_to_le32desc(&mtdx.rx_ring[i+1]);
451 mtdx.rx_ring[i].next_desc_logical = &mtdx.rx_ring[i+1];
452 mtdx.rx_ring[i].buffer = virt_to_le32desc(&rxb[i * PKT_BUF_SZ]);
453 mtdx.rx_ring[i].skbuff = &rxb[i * PKT_BUF_SZ];
455 /* Mark the last entry as wrapping the ring. */
456 mtdx.rx_ring[i-1].next_desc = virt_to_le32desc(&mtdx.rx_ring[0]);
457 mtdx.rx_ring[i-1].next_desc_logical = &mtdx.rx_ring[0];
459 /* We only use one transmit buffer, but two
460 * descriptors so transmit engines have somewhere
461 * to point should they feel the need */
462 mtdx.tx_ring[0].status = 0x00000000;
463 mtdx.tx_ring[0].buffer = virt_to_bus(&txb[0]);
464 mtdx.tx_ring[0].next_desc = virt_to_le32desc(&mtdx.tx_ring[1]);
466 /* This descriptor is never used */
467 mtdx.tx_ring[1].status = 0x00000000;
468 mtdx.tx_ring[1].buffer = 0; /*virt_to_bus(&txb[1]); */
469 mtdx.tx_ring[1].next_desc = virt_to_le32desc(&mtdx.tx_ring[0]);
471 return;
474 /**************************************************************************
475 RESET - Reset Adapter
476 ***************************************************************************/
477 static void mtd_reset( struct nic *nic )
479 /* Reset the chip to erase previous misconfiguration. */
480 outl(0x00000001, mtdx.ioaddr + BCR);
482 init_ring(nic);
484 outl(virt_to_bus(mtdx.rx_ring), mtdx.ioaddr + RXLBA);
485 outl(virt_to_bus(mtdx.tx_ring), mtdx.ioaddr + TXLBA);
487 /* Initialize other registers. */
488 /* Configure the PCI bus bursts and FIFO thresholds. */
489 mtdx.bcrvalue = 0x10; /* little-endian, 8 burst length */
490 mtdx.crvalue = 0xa00; /* rx 128 burst length */
492 if ( mtdx.dev_id == 0x891 ) {
493 mtdx.bcrvalue |= 0x200; /* set PROG bit */
494 mtdx.crvalue |= 0x02000000; /* set enhanced bit */
497 outl( mtdx.bcrvalue, mtdx.ioaddr + BCR);
499 /* Restart Rx engine if stopped. */
500 outl(0, mtdx.ioaddr + RXPDR);
502 getlinkstatus(nic);
503 if (mtdx.linkok)
505 static const char* texts[]={"half","full","10","100","1000"};
506 getlinktype(nic);
507 DBG ( "Link is OK : %s %s\n", texts[mtdx.duplexmode-1], texts[mtdx.line_speed+1] );
508 } else
510 DBG ( "No link!!!\n" );
513 mtdx.crvalue |= /*TxEnable |*/ RxEnable | TxThreshold;
514 set_rx_mode(nic);
516 /* Clear interrupts by setting the interrupt mask. */
517 outl(FBE | TUNF | CNTOVF | RBU | TI | RI, mtdx.ioaddr + ISR);
518 outl( 0, mtdx.ioaddr + IMR);
521 /**************************************************************************
522 POLL - Wait for a frame
523 ***************************************************************************/
524 static int mtd_poll(struct nic *nic, __unused int retrieve)
526 s32 rx_status = mtdx.cur_rx->status;
527 int retval = 0;
529 if( ( rx_status & RXOWN ) != 0 )
531 return 0;
534 if (rx_status & ErrorSummary)
535 { /* there was a fatal error */
536 printf( "%s: Receive error, Rx status %8.8x, Error(s) %s%s%s\n",
537 mtdx.nic_name, (unsigned int) rx_status,
538 (rx_status & (LONG | RUNT)) ? "length_error ":"",
539 (rx_status & RXER) ? "frame_error ":"",
540 (rx_status & CRC) ? "crc_error ":"" );
541 retval = 0;
542 } else if( !((rx_status & RXFSD) && (rx_status & RXLSD)) )
544 /* this pkt is too long, over one rx buffer */
545 printf("Pkt is too long, over one rx buffer.\n");
546 retval = 0;
547 } else
548 { /* this received pkt is ok */
549 /* Omit the four octet CRC from the length. */
550 short pkt_len = ((rx_status & FLNGMASK) >> FLNGShift) - 4;
552 DBG ( " netdev_rx() normal Rx pkt length %d"
553 " status %x.\n", pkt_len, (unsigned int) rx_status );
555 nic->packetlen = pkt_len;
556 memcpy(nic->packet, mtdx.cur_rx->skbuff, pkt_len);
558 retval = 1;
561 while( ( mtdx.cur_rx->status & RXOWN ) == 0 )
563 mtdx.cur_rx->status = RXOWN;
564 mtdx.cur_rx = mtdx.cur_rx->next_desc_logical;
567 /* Restart Rx engine if stopped. */
568 outl(0, mtdx.ioaddr + RXPDR);
570 return retval;
573 /**************************************************************************
574 TRANSMIT - Transmit a frame
575 ***************************************************************************/
576 static void mtd_transmit(
577 struct nic *nic,
578 const char *dest, /* Destination */
579 unsigned int type, /* Type */
580 unsigned int size, /* size */
581 const char *data) /* Packet */
583 u32 to;
584 u32 tx_status;
585 unsigned int nstype = htons ( type );
587 memcpy( txb, dest, ETH_ALEN );
588 memcpy( txb + ETH_ALEN, nic->node_addr, ETH_ALEN );
589 memcpy( txb + 2 * ETH_ALEN, &nstype, 2 );
590 memcpy( txb + ETH_HLEN, data, size );
592 size += ETH_HLEN;
593 size &= 0x0FFF;
594 while( size < ETH_ZLEN )
596 txb[size++] = '\0';
599 mtdx.tx_ring[0].control = TXLD | TXFD | CRCEnable | PADEnable;
600 mtdx.tx_ring[0].control |= (size << PKTSShift); /* pkt size */
601 mtdx.tx_ring[0].control |= (size << TBSShift); /* buffer size */
602 mtdx.tx_ring[0].status = TXOWN;
604 /* Point to transmit descriptor */
605 outl(virt_to_bus(mtdx.tx_ring), mtdx.ioaddr + TXLBA);
606 /* Enable Tx */
607 outl( mtdx.crvalue | TxEnable, mtdx.ioaddr + TCRRCR);
608 /* Wake the potentially-idle transmit channel. */
609 outl(0, mtdx.ioaddr + TXPDR);
611 to = currticks() + TX_TIME_OUT;
612 while(( mtdx.tx_ring[0].status & TXOWN) && (currticks() < to));
614 /* Disable Tx */
615 outl( mtdx.crvalue & (~TxEnable), mtdx.ioaddr + TCRRCR);
617 tx_status = mtdx.tx_ring[0].status;
618 if (currticks() >= to){
619 DBG ( "TX Time Out" );
620 } else if( tx_status & (CSL | LC | EC | UDF | HF)){
621 printf( "Transmit error: %8.8x %s %s %s %s %s\n",
622 (unsigned int) tx_status,
623 tx_status & EC ? "abort" : "",
624 tx_status & CSL ? "carrier" : "",
625 tx_status & LC ? "late" : "",
626 tx_status & UDF ? "fifo" : "",
627 tx_status & HF ? "heartbeat" : "" );
630 /*hex_dump( txb, size );*/
631 /*pause();*/
633 DBG ( "TRANSMIT\n" );
636 /**************************************************************************
637 DISABLE - Turn off ethernet interface
638 ***************************************************************************/
639 static void mtd_disable ( struct nic *nic ) {
641 /* Disable Tx Rx*/
642 outl( mtdx.crvalue & (~TxEnable) & (~RxEnable), mtdx.ioaddr + TCRRCR );
644 /* Reset the chip to erase previous misconfiguration. */
645 mtd_reset(nic);
647 DBG ( "DISABLE\n" );
650 static struct nic_operations mtd_operations = {
651 .connect = dummy_connect,
652 .poll = mtd_poll,
653 .transmit = mtd_transmit,
654 .irq = dummy_irq,
658 static struct pci_device_id mtd80x_nics[] = {
659 PCI_ROM(0x1516, 0x0800, "MTD800", "Myson MTD800"),
660 PCI_ROM(0x1516, 0x0803, "MTD803", "Surecom EP-320X"),
661 PCI_ROM(0x1516, 0x0891, "MTD891", "Myson MTD891"),
664 PCI_DRIVER ( mtd80x_driver, mtd80x_nics, PCI_NO_CLASS );
666 /**************************************************************************
667 PROBE - Look for an adapter, this routine's visible to the outside
668 ***************************************************************************/
670 static int mtd_probe ( struct nic *nic, struct pci_device *pci ) {
672 int i;
674 if (pci->ioaddr == 0)
675 return 0;
677 pci_fill_nic ( nic, pci );
678 adjust_pci_device(pci);
680 mtdx.nic_name = pci->driver_name;
681 mtdx.dev_id = pci->device;
682 mtdx.ioaddr = nic->ioaddr;
684 /* read ethernet id */
685 for (i = 0; i < 6; ++i)
687 nic->node_addr[i] = inb(mtdx.ioaddr + PAR0 + i);
690 if (memcmp(nic->node_addr, "\0\0\0\0\0\0", 6) == 0)
692 return 0;
695 DBG ( "%s: ioaddr %4.4x MAC %s\n", mtdx.nic_name, mtdx.ioaddr, eth_ntoa ( nic->node_addr ) );
697 /* Reset the chip to erase previous misconfiguration. */
698 outl(0x00000001, mtdx.ioaddr + BCR);
700 /* find the connected MII xcvrs */
702 if( mtdx.dev_id != 0x803 )
704 int phy, phy_idx = 0;
706 for (phy = 1; phy < 32 && phy_idx < 1; phy++) {
707 int mii_status = mdio_read(nic, phy, 1);
709 if (mii_status != 0xffff && mii_status != 0x0000) {
710 mtdx.phys[phy_idx] = phy;
712 DBG ( "%s: MII PHY found at address %d, status "
713 "0x%4.4x.\n", mtdx.nic_name, phy, mii_status );
714 /* get phy type */
716 unsigned int data;
718 data = mdio_read(nic, mtdx.phys[phy_idx], 2);
719 if (data == SeeqPHYID0)
720 mtdx.PHYType = SeeqPHY;
721 else if (data == AhdocPHYID0)
722 mtdx.PHYType = AhdocPHY;
723 else if (data == MarvellPHYID0)
724 mtdx.PHYType = MarvellPHY;
725 else if (data == MysonPHYID0)
726 mtdx.PHYType = Myson981;
727 else if (data == LevelOnePHYID0)
728 mtdx.PHYType = LevelOnePHY;
729 else
730 mtdx.PHYType = OtherPHY;
732 phy_idx++;
736 mtdx.mii_cnt = phy_idx;
737 if (phy_idx == 0) {
738 printf("%s: MII PHY not found -- this device may "
739 "not operate correctly.\n", mtdx.nic_name);
741 } else {
742 mtdx.phys[0] = 32;
743 /* get phy type */
744 if (inl(mtdx.ioaddr + PHYIDENTIFIER) == MysonPHYID ) {
745 mtdx.PHYType = MysonPHY;
746 DBG ( "MysonPHY\n" );
747 } else {
748 mtdx.PHYType = OtherPHY;
749 DBG ( "OtherPHY\n" );
753 getlinkstatus(nic);
754 if( !mtdx.linkok )
756 printf("No link!!!\n");
757 return 0;
760 mtd_reset( nic );
762 /* point to NIC specific routines */
763 nic->nic_op = &mtd_operations;
764 return 1;
768 /**************************************************************************/
769 static void set_rx_mode(struct nic *nic __unused)
771 u32 mc_filter[2]; /* Multicast hash filter */
772 u32 rx_mode;
774 /* Too many to match, or accept all multicasts. */
775 mc_filter[1] = mc_filter[0] = ~0;
776 rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys;
778 outl(mc_filter[0], mtdx.ioaddr + MAR0);
779 outl(mc_filter[1], mtdx.ioaddr + MAR1);
781 mtdx.crvalue = ( mtdx.crvalue & ~RxModeMask ) | rx_mode;
782 outb( mtdx.crvalue, mtdx.ioaddr + TCRRCR);
784 /**************************************************************************/
785 static unsigned int m80x_read_tick(void)
786 /* function: Reads the Timer tick count register which decrements by 2 from */
787 /* 65536 to 0 every 1/36.414 of a second. Each 2 decrements of the */
788 /* count represents 838 nsec's. */
789 /* input : none. */
790 /* output : none. */
792 unsigned char tmp;
793 int value;
795 outb((char) 0x06, 0x43); // Command 8254 to latch T0's count
797 // now read the count.
798 tmp = (unsigned char) inb(0x40);
799 value = ((int) tmp) << 8;
800 tmp = (unsigned char) inb(0x40);
801 value |= (((int) tmp) & 0xff);
802 return (value);
805 static void m80x_delay(unsigned int interval)
806 /* function: to wait for a specified time. */
807 /* input : interval ... the specified time. */
808 /* output : none. */
810 unsigned int interval1, interval2, i = 0;
812 interval1 = m80x_read_tick(); // get initial value
815 interval2 = m80x_read_tick();
816 if (interval1 < interval2)
817 interval1 += 65536;
818 ++i;
819 } while (((interval1 - interval2) < (u16) interval) && (i < 65535));
823 static u32 m80x_send_cmd_to_phy(long miiport, int opcode, int phyad, int regad)
825 u32 miir;
826 int i;
827 unsigned int mask, data;
829 /* enable MII output */
830 miir = (u32) inl(miiport);
831 miir &= 0xfffffff0;
833 miir |= MASK_MIIR_MII_WRITE + MASK_MIIR_MII_MDO;
835 /* send 32 1's preamble */
836 for (i = 0; i < 32; i++) {
837 /* low MDC; MDO is already high (miir) */
838 miir &= ~MASK_MIIR_MII_MDC;
839 outl(miir, miiport);
841 /* high MDC */
842 miir |= MASK_MIIR_MII_MDC;
843 outl(miir, miiport);
846 /* calculate ST+OP+PHYAD+REGAD+TA */
847 data = opcode | (phyad << 7) | (regad << 2);
849 /* sent out */
850 mask = 0x8000;
851 while (mask) {
852 /* low MDC, prepare MDO */
853 miir &= ~(MASK_MIIR_MII_MDC + MASK_MIIR_MII_MDO);
854 if (mask & data)
855 miir |= MASK_MIIR_MII_MDO;
857 outl(miir, miiport);
858 /* high MDC */
859 miir |= MASK_MIIR_MII_MDC;
860 outl(miir, miiport);
861 m80x_delay(30);
863 /* next */
864 mask >>= 1;
865 if (mask == 0x2 && opcode == OP_READ)
866 miir &= ~MASK_MIIR_MII_WRITE;
868 return miir;
871 static int mdio_read(struct nic *nic __unused, int phyad, int regad)
873 long miiport = mtdx.ioaddr + MANAGEMENT;
874 u32 miir;
875 unsigned int mask, data;
877 miir = m80x_send_cmd_to_phy(miiport, OP_READ, phyad, regad);
879 /* read data */
880 mask = 0x8000;
881 data = 0;
882 while (mask)
884 /* low MDC */
885 miir &= ~MASK_MIIR_MII_MDC;
886 outl(miir, miiport);
888 /* read MDI */
889 miir = inl(miiport);
890 if (miir & MASK_MIIR_MII_MDI)
891 data |= mask;
893 /* high MDC, and wait */
894 miir |= MASK_MIIR_MII_MDC;
895 outl(miir, miiport);
896 m80x_delay((int) 30);
898 /* next */
899 mask >>= 1;
902 /* low MDC */
903 miir &= ~MASK_MIIR_MII_MDC;
904 outl(miir, miiport);
906 return data & 0xffff;
909 #if 0 /* not used */
910 static void mdio_write(struct nic *nic __unused, int phyad, int regad,
911 int data)
913 long miiport = mtdx.ioaddr + MANAGEMENT;
914 u32 miir;
915 unsigned int mask;
917 miir = m80x_send_cmd_to_phy(miiport, OP_WRITE, phyad, regad);
919 /* write data */
920 mask = 0x8000;
921 while (mask)
923 /* low MDC, prepare MDO */
924 miir &= ~(MASK_MIIR_MII_MDC + MASK_MIIR_MII_MDO);
925 if (mask & data)
926 miir |= MASK_MIIR_MII_MDO;
927 outl(miir, miiport);
929 /* high MDC */
930 miir |= MASK_MIIR_MII_MDC;
931 outl(miir, miiport);
933 /* next */
934 mask >>= 1;
937 /* low MDC */
938 miir &= ~MASK_MIIR_MII_MDC;
939 outl(miir, miiport);
941 return;
943 #endif
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. */
950 unsigned int i, DelayTime = 0x1000;
952 mtdx.linkok = 0;
954 if (mtdx.PHYType == MysonPHY)
956 for (i = 0; i < DelayTime; ++i) {
957 if (inl(mtdx.ioaddr + BMCRSR) & LinkIsUp2) {
958 mtdx.linkok = 1;
959 return;
961 // delay
962 m80x_delay(100);
964 } else
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;
971 // delay
972 m80x_delay(100);
978 static void getlinktype(struct nic *dev)
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
992 if (mtdx.PHYType == SeeqPHY) { /* this PHY is SEEQ 80225 */
993 unsigned int data;
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;
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 */
1017 /* 89/6/13 add, (begin) */
1018 else if (mtdx.PHYType == MarvellPHY) {
1019 unsigned int data;
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 */
1034 /* 89/6/13 add, (end) */
1035 /* 89/7/27 add, (begin) */
1036 else if (mtdx.PHYType == Myson981) {
1037 unsigned int data;
1039 data = mdio_read(dev, mtdx.phys[0], StatusRegister);
1041 if (data & SPEED100)
1042 mtdx.line_speed = 2;
1043 else
1044 mtdx.line_speed = 1;
1046 if (data & FULLMODE)
1047 mtdx.duplexmode = 2;
1048 else
1049 mtdx.duplexmode = 1;
1051 /* 89/7/27 add, (end) */
1052 /* 89/12/29 add */
1053 else if (mtdx.PHYType == LevelOnePHY) {
1054 unsigned int data;
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 */
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;
1081 DRIVER ( "MTD80X", nic_driver, pci_driver, mtd80x_driver,
1082 mtd_probe, mtd_disable );