|
|
1.1 root 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: 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 <ipxe/pci.h>
34: #include <ipxe/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: *************************************************************************/
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: ***************************************************************************/
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: ***************************************************************************/
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: ***************************************************************************/
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: ***************************************************************************/
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:
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->id->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: /**************************************************************************/
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: /**************************************************************************/
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:
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:
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:
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:
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:
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 );
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.