00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 FILE_LICENCE ( GPL2_OR_LATER );
00027
00028
00029 #include "etherboot.h"
00030
00031 #include "nic.h"
00032
00033 #include <gpxe/pci.h>
00034 #include <gpxe/ethernet.h>
00035 #include <mii.h>
00036
00037
00038 #define virt_to_le32desc(addr) cpu_to_le32(virt_to_bus(addr))
00039 #define le32desc_to_virt(addr) bus_to_virt(le32_to_cpu(addr))
00040 #define get_unaligned(ptr) (*(ptr))
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050 #define TX_RING_SIZE 2
00051 #define TX_QUEUE_LEN 10
00052 #define RX_RING_SIZE 4
00053
00054
00055
00056 #define HZ 100
00057 #define TX_TIME_OUT (6*HZ)
00058
00059
00060
00061
00062
00063 #define PKT_BUF_SZ 1536
00064
00065
00066 enum phy_type_flags {
00067 MysonPHY = 1,
00068 AhdocPHY = 2,
00069 SeeqPHY = 3,
00070 MarvellPHY = 4,
00071 Myson981 = 5,
00072 LevelOnePHY = 6,
00073 OtherPHY = 10,
00074 };
00075
00076
00077 enum chip_capability_flags {
00078 HAS_MII_XCVR,
00079 HAS_CHIP_XCVR,
00080 };
00081
00082 #if 0
00083 static
00084 struct chip_info
00085 {
00086 u16 dev_id;
00087 int flag;
00088 }
00089 mtd80x_chips[] = {
00090 {0x0800, HAS_MII_XCVR},
00091 {0x0803, HAS_CHIP_XCVR},
00092 {0x0891, HAS_MII_XCVR}
00093 };
00094 static int chip_cnt = sizeof( mtd80x_chips ) / sizeof( struct chip_info );
00095 #endif
00096
00097
00098 enum mtd_offsets {
00099 PAR0 = 0x0,
00100 PAR1 = 0x04,
00101 MAR0 = 0x08,
00102 MAR1 = 0x0C,
00103 FAR0 = 0x10,
00104 FAR1 = 0x14,
00105 TCRRCR = 0x18,
00106 BCR = 0x1C,
00107 TXPDR = 0x20,
00108 RXPDR = 0x24,
00109 RXCWP = 0x28,
00110 TXLBA = 0x2C,
00111 RXLBA = 0x30,
00112 ISR = 0x34,
00113 IMR = 0x38,
00114 FTH = 0x3C,
00115 MANAGEMENT = 0x40,
00116 TALLY = 0x44,
00117 TSR = 0x48,
00118 BMCRSR = 0x4c,
00119 PHYIDENTIFIER = 0x50,
00120 ANARANLPAR = 0x54,
00121
00122 ANEROCR = 0x58,
00123 BPREMRPSR = 0x5c,
00124 };
00125
00126
00127
00128 enum intr_status_bits {
00129 RFCON = 0x00020000,
00130 RFCOFF = 0x00010000,
00131 LSCStatus = 0x00008000,
00132 ANCStatus = 0x00004000,
00133 FBE = 0x00002000,
00134 FBEMask = 0x00001800,
00135 ParityErr = 0x00000000,
00136 TargetErr = 0x00001000,
00137 MasterErr = 0x00000800,
00138 TUNF = 0x00000400,
00139 ROVF = 0x00000200,
00140 ETI = 0x00000100,
00141 ERI = 0x00000080,
00142 CNTOVF = 0x00000040,
00143 RBU = 0x00000020,
00144 TBU = 0x00000010,
00145 TI = 0x00000008,
00146 RI = 0x00000004,
00147 RxErr = 0x00000002,
00148 };
00149
00150
00151 enum rx_mode_bits {
00152 RxModeMask = 0xe0,
00153 AcceptAllPhys = 0x80,
00154 AcceptBroadcast = 0x40,
00155 AcceptMulticast = 0x20,
00156 AcceptRunt = 0x08,
00157 ALP = 0x04,
00158 AcceptErr = 0x02,
00159
00160 AcceptMyPhys = 0x00000000,
00161 RxEnable = 0x00000001,
00162 RxFlowCtrl = 0x00002000,
00163 TxEnable = 0x00040000,
00164 TxModeFDX = 0x00100000,
00165 TxThreshold = 0x00e00000,
00166
00167 PS1000 = 0x00010000,
00168 PS10 = 0x00080000,
00169 FD = 0x00100000,
00170 };
00171
00172
00173 enum rx_desc_status_bits {
00174 RXOWN = 0x80000000,
00175 FLNGMASK = 0x0fff0000,
00176 FLNGShift = 16,
00177 MARSTATUS = 0x00004000,
00178 BARSTATUS = 0x00002000,
00179 PHYSTATUS = 0x00001000,
00180 RXFSD = 0x00000800,
00181 RXLSD = 0x00000400,
00182 ErrorSummary = 0x80,
00183 RUNT = 0x40,
00184 LONG = 0x20,
00185 FAE = 0x10,
00186 CRC = 0x08,
00187 RXER = 0x04,
00188 };
00189
00190 enum rx_desc_control_bits {
00191 RXIC = 0x00800000,
00192 RBSShift = 0,
00193 };
00194
00195 enum tx_desc_status_bits {
00196 TXOWN = 0x80000000,
00197 JABTO = 0x00004000,
00198 CSL = 0x00002000,
00199 LC = 0x00001000,
00200 EC = 0x00000800,
00201 UDF = 0x00000400,
00202 DFR = 0x00000200,
00203 HF = 0x00000100,
00204 NCRMask = 0x000000ff,
00205 NCRShift = 0,
00206 };
00207
00208 enum tx_desc_control_bits {
00209 TXIC = 0x80000000,
00210 ETIControl = 0x40000000,
00211 TXLD = 0x20000000,
00212 TXFD = 0x10000000,
00213 CRCEnable = 0x08000000,
00214 PADEnable = 0x04000000,
00215 RetryTxLC = 0x02000000,
00216 PKTSMask = 0x3ff800,
00217 PKTSShift = 11,
00218 TBSMask = 0x000007ff,
00219 TBSShift = 0,
00220 };
00221
00222
00223 #define MASK_MIIR_MII_READ 0x00000000
00224 #define MASK_MIIR_MII_WRITE 0x00000008
00225 #define MASK_MIIR_MII_MDO 0x00000004
00226 #define MASK_MIIR_MII_MDI 0x00000002
00227 #define MASK_MIIR_MII_MDC 0x00000001
00228
00229
00230 #define OP_READ 0x6000
00231 #define OP_WRITE 0x5002
00232
00233
00234
00235
00236 #define MysonPHYID 0xd0000302
00237
00238 #define MysonPHYID0 0x0302
00239 #define StatusRegister 18
00240 #define SPEED100 0x0400 // bit10
00241 #define FULLMODE 0x0800 // bit11
00242
00243
00244
00245
00246
00247 #define SeeqPHYID0 0x0016
00248
00249 #define MIIRegister18 18
00250 #define SPD_DET_100 0x80
00251 #define DPLX_DET_FULL 0x40
00252
00253
00254
00255
00256 #define AhdocPHYID0 0x0022
00257
00258 #define DiagnosticReg 18
00259 #define DPLX_FULL 0x0800
00260 #define Speed_100 0x0400
00261
00262
00263
00264
00265
00266 #define MarvellPHYID0 0x0141
00267 #define LevelOnePHYID0 0x0013
00268
00269 #define MII1000BaseTControlReg 9
00270 #define MII1000BaseTStatusReg 10
00271 #define SpecificReg 17
00272
00273
00274 #define PHYAbletoPerform1000FullDuplex 0x0200
00275 #define PHYAbletoPerform1000HalfDuplex 0x0100
00276 #define PHY1000AbilityMask 0x300
00277
00278
00279 #define SpeedMask 0x0c000
00280 #define Speed_1000M 0x08000
00281 #define Speed_100M 0x4000
00282 #define Speed_10M 0
00283 #define Full_Duplex 0x2000
00284
00285
00286 #define LXT1000_100M 0x08000
00287 #define LXT1000_1000M 0x0c000
00288 #define LXT1000_Full 0x200
00289
00290
00291 #if 0
00292
00293 #define PS10 0x00080000
00294 #define FD 0x00100000
00295 #define PS1000 0x00010000
00296 #endif
00297
00298
00299 #define LinkIsUp 0x0004
00300 #define LinkIsUp2 0x00040000
00301
00302
00303
00304
00305 struct {
00306 u8 txb[PKT_BUF_SZ * TX_RING_SIZE] __attribute__ ((aligned(8)));
00307 u8 rxb[PKT_BUF_SZ * RX_RING_SIZE] __attribute__ ((aligned(8)));
00308 } mtd80x_bufs __shared;
00309 #define txb mtd80x_bufs.txb
00310 #define rxb mtd80x_bufs.rxb
00311
00312
00313 struct mtd_desc
00314 {
00315 s32 status;
00316 s32 control;
00317 u32 buffer;
00318 u32 next_desc;
00319 struct mtd_desc *next_desc_logical;
00320 u8* skbuff;
00321 u32 reserved1;
00322 u32 reserved2;
00323 };
00324
00325 struct mtd_private
00326 {
00327 struct mtd_desc rx_ring[RX_RING_SIZE];
00328 struct mtd_desc tx_ring[TX_RING_SIZE];
00329
00330
00331 int flags;
00332 struct pci_dev *pci_dev;
00333 unsigned long crvalue;
00334 unsigned long bcrvalue;
00335
00336 struct mtd_desc *cur_rx;
00337 struct mtd_desc *lack_rxbuf;
00338 int really_rx_count;
00339 struct mtd_desc *cur_tx;
00340 struct mtd_desc *cur_tx_copy;
00341 int really_tx_count;
00342 int free_tx_count;
00343 unsigned int rx_buf_sz;
00344
00345
00346 unsigned int linkok;
00347 unsigned int line_speed;
00348 unsigned int duplexmode;
00349 unsigned int default_port:
00350 4;
00351 unsigned int PHYType;
00352
00353
00354 int mii_cnt;
00355 unsigned char phys[1];
00356
00357
00358 const char *nic_name;
00359 int ioaddr;
00360 u16 dev_id;
00361 };
00362
00363 static struct mtd_private mtdx;
00364
00365 static int mdio_read(struct nic * , int phy_id, int location);
00366 static void getlinktype(struct nic * );
00367 static void getlinkstatus(struct nic * );
00368 static void set_rx_mode(struct nic *);
00369
00370
00371
00372
00373 static void init_ring(struct nic *nic __unused)
00374 {
00375 int i;
00376
00377 mtdx.cur_rx = &mtdx.rx_ring[0];
00378
00379 mtdx.rx_buf_sz = PKT_BUF_SZ;
00380
00381
00382
00383
00384 for (i = 0; i < RX_RING_SIZE; i++)
00385 {
00386 mtdx.rx_ring[i].status = RXOWN;
00387 mtdx.rx_ring[i].control = mtdx.rx_buf_sz << RBSShift;
00388 mtdx.rx_ring[i].next_desc = virt_to_le32desc(&mtdx.rx_ring[i+1]);
00389 mtdx.rx_ring[i].next_desc_logical = &mtdx.rx_ring[i+1];
00390 mtdx.rx_ring[i].buffer = virt_to_le32desc(&rxb[i * PKT_BUF_SZ]);
00391 mtdx.rx_ring[i].skbuff = &rxb[i * PKT_BUF_SZ];
00392 }
00393
00394 mtdx.rx_ring[i-1].next_desc = virt_to_le32desc(&mtdx.rx_ring[0]);
00395 mtdx.rx_ring[i-1].next_desc_logical = &mtdx.rx_ring[0];
00396
00397
00398
00399
00400 mtdx.tx_ring[0].status = 0x00000000;
00401 mtdx.tx_ring[0].buffer = virt_to_bus(&txb[0]);
00402 mtdx.tx_ring[0].next_desc = virt_to_le32desc(&mtdx.tx_ring[1]);
00403
00404
00405 mtdx.tx_ring[1].status = 0x00000000;
00406 mtdx.tx_ring[1].buffer = 0;
00407 mtdx.tx_ring[1].next_desc = virt_to_le32desc(&mtdx.tx_ring[0]);
00408
00409 return;
00410 }
00411
00412
00413
00414
00415 static void mtd_reset( struct nic *nic )
00416 {
00417
00418 outl(0x00000001, mtdx.ioaddr + BCR);
00419
00420 init_ring(nic);
00421
00422 outl(virt_to_bus(mtdx.rx_ring), mtdx.ioaddr + RXLBA);
00423 outl(virt_to_bus(mtdx.tx_ring), mtdx.ioaddr + TXLBA);
00424
00425
00426
00427 mtdx.bcrvalue = 0x10;
00428 mtdx.crvalue = 0xa00;
00429
00430 if ( mtdx.dev_id == 0x891 ) {
00431 mtdx.bcrvalue |= 0x200;
00432 mtdx.crvalue |= 0x02000000;
00433 }
00434
00435 outl( mtdx.bcrvalue, mtdx.ioaddr + BCR);
00436
00437
00438 outl(0, mtdx.ioaddr + RXPDR);
00439
00440 getlinkstatus(nic);
00441 if (mtdx.linkok)
00442 {
00443 static const char* texts[]={"half","full","10","100","1000"};
00444 getlinktype(nic);
00445 DBG ( "Link is OK : %s %s\n", texts[mtdx.duplexmode-1], texts[mtdx.line_speed+1] );
00446 } else
00447 {
00448 DBG ( "No link!!!\n" );
00449 }
00450
00451 mtdx.crvalue |= RxEnable | TxThreshold;
00452 set_rx_mode(nic);
00453
00454
00455 outl(FBE | TUNF | CNTOVF | RBU | TI | RI, mtdx.ioaddr + ISR);
00456 outl( 0, mtdx.ioaddr + IMR);
00457 }
00458
00459
00460
00461
00462 static int mtd_poll(struct nic *nic, __unused int retrieve)
00463 {
00464 s32 rx_status = mtdx.cur_rx->status;
00465 int retval = 0;
00466
00467 if( ( rx_status & RXOWN ) != 0 )
00468 {
00469 return 0;
00470 }
00471
00472 if (rx_status & ErrorSummary)
00473 {
00474 printf( "%s: Receive error, Rx status %8.8x, Error(s) %s%s%s\n",
00475 mtdx.nic_name, (unsigned int) rx_status,
00476 (rx_status & (LONG | RUNT)) ? "length_error ":"",
00477 (rx_status & RXER) ? "frame_error ":"",
00478 (rx_status & CRC) ? "crc_error ":"" );
00479 retval = 0;
00480 } else if( !((rx_status & RXFSD) && (rx_status & RXLSD)) )
00481 {
00482
00483 printf("Pkt is too long, over one rx buffer.\n");
00484 retval = 0;
00485 } else
00486 {
00487
00488 short pkt_len = ((rx_status & FLNGMASK) >> FLNGShift) - 4;
00489
00490 DBG ( " netdev_rx() normal Rx pkt length %d"
00491 " status %x.\n", pkt_len, (unsigned int) rx_status );
00492
00493 nic->packetlen = pkt_len;
00494 memcpy(nic->packet, mtdx.cur_rx->skbuff, pkt_len);
00495
00496 retval = 1;
00497 }
00498
00499 while( ( mtdx.cur_rx->status & RXOWN ) == 0 )
00500 {
00501 mtdx.cur_rx->status = RXOWN;
00502 mtdx.cur_rx = mtdx.cur_rx->next_desc_logical;
00503 }
00504
00505
00506 outl(0, mtdx.ioaddr + RXPDR);
00507
00508 return retval;
00509 }
00510
00511
00512
00513
00514 static void mtd_transmit(
00515 struct nic *nic,
00516 const char *dest,
00517 unsigned int type,
00518 unsigned int size,
00519 const char *data)
00520 {
00521 u32 to;
00522 u32 tx_status;
00523 unsigned int nstype = htons ( type );
00524
00525 memcpy( txb, dest, ETH_ALEN );
00526 memcpy( txb + ETH_ALEN, nic->node_addr, ETH_ALEN );
00527 memcpy( txb + 2 * ETH_ALEN, &nstype, 2 );
00528 memcpy( txb + ETH_HLEN, data, size );
00529
00530 size += ETH_HLEN;
00531 size &= 0x0FFF;
00532 while( size < ETH_ZLEN )
00533 {
00534 txb[size++] = '\0';
00535 }
00536
00537 mtdx.tx_ring[0].control = TXLD | TXFD | CRCEnable | PADEnable;
00538 mtdx.tx_ring[0].control |= (size << PKTSShift);
00539 mtdx.tx_ring[0].control |= (size << TBSShift);
00540 mtdx.tx_ring[0].status = TXOWN;
00541
00542
00543 outl(virt_to_bus(mtdx.tx_ring), mtdx.ioaddr + TXLBA);
00544
00545 outl( mtdx.crvalue | TxEnable, mtdx.ioaddr + TCRRCR);
00546
00547 outl(0, mtdx.ioaddr + TXPDR);
00548
00549 to = currticks() + TX_TIME_OUT;
00550 while(( mtdx.tx_ring[0].status & TXOWN) && (currticks() < to));
00551
00552
00553 outl( mtdx.crvalue & (~TxEnable), mtdx.ioaddr + TCRRCR);
00554
00555 tx_status = mtdx.tx_ring[0].status;
00556 if (currticks() >= to){
00557 DBG ( "TX Time Out" );
00558 } else if( tx_status & (CSL | LC | EC | UDF | HF)){
00559 printf( "Transmit error: %8.8x %s %s %s %s %s\n",
00560 (unsigned int) tx_status,
00561 tx_status & EC ? "abort" : "",
00562 tx_status & CSL ? "carrier" : "",
00563 tx_status & LC ? "late" : "",
00564 tx_status & UDF ? "fifo" : "",
00565 tx_status & HF ? "heartbeat" : "" );
00566 }
00567
00568
00569
00570
00571 DBG ( "TRANSMIT\n" );
00572 }
00573
00574
00575
00576
00577 static void mtd_disable ( struct nic *nic ) {
00578
00579
00580 outl( mtdx.crvalue & (~TxEnable) & (~RxEnable), mtdx.ioaddr + TCRRCR );
00581
00582
00583 mtd_reset(nic);
00584
00585 DBG ( "DISABLE\n" );
00586 }
00587
00588 static struct nic_operations mtd_operations = {
00589 .connect = dummy_connect,
00590 .poll = mtd_poll,
00591 .transmit = mtd_transmit,
00592 .irq = dummy_irq,
00593
00594 };
00595
00596 static struct pci_device_id mtd80x_nics[] = {
00597 PCI_ROM(0x1516, 0x0800, "MTD800", "Myson MTD800", 0),
00598 PCI_ROM(0x1516, 0x0803, "MTD803", "Surecom EP-320X", 0),
00599 PCI_ROM(0x1516, 0x0891, "MTD891", "Myson MTD891", 0),
00600 };
00601
00602 PCI_DRIVER ( mtd80x_driver, mtd80x_nics, PCI_NO_CLASS );
00603
00604
00605
00606
00607
00608 static int mtd_probe ( struct nic *nic, struct pci_device *pci ) {
00609
00610 int i;
00611
00612 if (pci->ioaddr == 0)
00613 return 0;
00614
00615 adjust_pci_device(pci);
00616
00617 nic->ioaddr = pci->ioaddr;
00618 nic->irqno = 0;
00619
00620 mtdx.nic_name = pci->driver_name;
00621 mtdx.dev_id = pci->device;
00622 mtdx.ioaddr = nic->ioaddr;
00623
00624
00625 for (i = 0; i < 6; ++i)
00626 {
00627 nic->node_addr[i] = inb(mtdx.ioaddr + PAR0 + i);
00628 }
00629
00630 if (memcmp(nic->node_addr, "\0\0\0\0\0\0", 6) == 0)
00631 {
00632 return 0;
00633 }
00634
00635 DBG ( "%s: ioaddr %4.4x MAC %s\n", mtdx.nic_name, mtdx.ioaddr, eth_ntoa ( nic->node_addr ) );
00636
00637
00638 outl(0x00000001, mtdx.ioaddr + BCR);
00639
00640
00641
00642 if( mtdx.dev_id != 0x803 )
00643 {
00644 int phy, phy_idx = 0;
00645
00646 for (phy = 1; phy < 32 && phy_idx < 1; phy++) {
00647 int mii_status = mdio_read(nic, phy, 1);
00648
00649 if (mii_status != 0xffff && mii_status != 0x0000) {
00650 mtdx.phys[phy_idx] = phy;
00651
00652 DBG ( "%s: MII PHY found at address %d, status "
00653 "0x%4.4x.\n", mtdx.nic_name, phy, mii_status );
00654
00655 {
00656 unsigned int data;
00657
00658 data = mdio_read(nic, mtdx.phys[phy_idx], 2);
00659 if (data == SeeqPHYID0)
00660 mtdx.PHYType = SeeqPHY;
00661 else if (data == AhdocPHYID0)
00662 mtdx.PHYType = AhdocPHY;
00663 else if (data == MarvellPHYID0)
00664 mtdx.PHYType = MarvellPHY;
00665 else if (data == MysonPHYID0)
00666 mtdx.PHYType = Myson981;
00667 else if (data == LevelOnePHYID0)
00668 mtdx.PHYType = LevelOnePHY;
00669 else
00670 mtdx.PHYType = OtherPHY;
00671 }
00672 phy_idx++;
00673 }
00674 }
00675
00676 mtdx.mii_cnt = phy_idx;
00677 if (phy_idx == 0) {
00678 printf("%s: MII PHY not found -- this device may "
00679 "not operate correctly.\n", mtdx.nic_name);
00680 }
00681 } else {
00682 mtdx.phys[0] = 32;
00683
00684 if (inl(mtdx.ioaddr + PHYIDENTIFIER) == MysonPHYID ) {
00685 mtdx.PHYType = MysonPHY;
00686 DBG ( "MysonPHY\n" );
00687 } else {
00688 mtdx.PHYType = OtherPHY;
00689 DBG ( "OtherPHY\n" );
00690 }
00691 }
00692
00693 getlinkstatus(nic);
00694 if( !mtdx.linkok )
00695 {
00696 printf("No link!!!\n");
00697 return 0;
00698 }
00699
00700 mtd_reset( nic );
00701
00702
00703 nic->nic_op = &mtd_operations;
00704 return 1;
00705 }
00706
00707
00708
00709 static void set_rx_mode(struct nic *nic __unused)
00710 {
00711 u32 mc_filter[2];
00712 u32 rx_mode;
00713
00714
00715 mc_filter[1] = mc_filter[0] = ~0;
00716 rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys;
00717
00718 outl(mc_filter[0], mtdx.ioaddr + MAR0);
00719 outl(mc_filter[1], mtdx.ioaddr + MAR1);
00720
00721 mtdx.crvalue = ( mtdx.crvalue & ~RxModeMask ) | rx_mode;
00722 outb( mtdx.crvalue, mtdx.ioaddr + TCRRCR);
00723 }
00724
00725 static unsigned int m80x_read_tick(void)
00726
00727
00728
00729
00730
00731 {
00732 unsigned char tmp;
00733 int value;
00734
00735 outb((char) 0x06, 0x43);
00736
00737
00738 tmp = (unsigned char) inb(0x40);
00739 value = ((int) tmp) << 8;
00740 tmp = (unsigned char) inb(0x40);
00741 value |= (((int) tmp) & 0xff);
00742 return (value);
00743 }
00744
00745 static void m80x_delay(unsigned int interval)
00746
00747
00748
00749 {
00750 unsigned int interval1, interval2, i = 0;
00751
00752 interval1 = m80x_read_tick();
00753 do
00754 {
00755 interval2 = m80x_read_tick();
00756 if (interval1 < interval2)
00757 interval1 += 65536;
00758 ++i;
00759 } while (((interval1 - interval2) < (u16) interval) && (i < 65535));
00760 }
00761
00762
00763 static u32 m80x_send_cmd_to_phy(long miiport, int opcode, int phyad, int regad)
00764 {
00765 u32 miir;
00766 int i;
00767 unsigned int mask, data;
00768
00769
00770 miir = (u32) inl(miiport);
00771 miir &= 0xfffffff0;
00772
00773 miir |= MASK_MIIR_MII_WRITE + MASK_MIIR_MII_MDO;
00774
00775
00776 for (i = 0; i < 32; i++) {
00777
00778 miir &= ~MASK_MIIR_MII_MDC;
00779 outl(miir, miiport);
00780
00781
00782 miir |= MASK_MIIR_MII_MDC;
00783 outl(miir, miiport);
00784 }
00785
00786
00787 data = opcode | (phyad << 7) | (regad << 2);
00788
00789
00790 mask = 0x8000;
00791 while (mask) {
00792
00793 miir &= ~(MASK_MIIR_MII_MDC + MASK_MIIR_MII_MDO);
00794 if (mask & data)
00795 miir |= MASK_MIIR_MII_MDO;
00796
00797 outl(miir, miiport);
00798
00799 miir |= MASK_MIIR_MII_MDC;
00800 outl(miir, miiport);
00801 m80x_delay(30);
00802
00803
00804 mask >>= 1;
00805 if (mask == 0x2 && opcode == OP_READ)
00806 miir &= ~MASK_MIIR_MII_WRITE;
00807 }
00808 return miir;
00809 }
00810
00811 static int mdio_read(struct nic *nic __unused, int phyad, int regad)
00812 {
00813 long miiport = mtdx.ioaddr + MANAGEMENT;
00814 u32 miir;
00815 unsigned int mask, data;
00816
00817 miir = m80x_send_cmd_to_phy(miiport, OP_READ, phyad, regad);
00818
00819
00820 mask = 0x8000;
00821 data = 0;
00822 while (mask)
00823 {
00824
00825 miir &= ~MASK_MIIR_MII_MDC;
00826 outl(miir, miiport);
00827
00828
00829 miir = inl(miiport);
00830 if (miir & MASK_MIIR_MII_MDI)
00831 data |= mask;
00832
00833
00834 miir |= MASK_MIIR_MII_MDC;
00835 outl(miir, miiport);
00836 m80x_delay((int) 30);
00837
00838
00839 mask >>= 1;
00840 }
00841
00842
00843 miir &= ~MASK_MIIR_MII_MDC;
00844 outl(miir, miiport);
00845
00846 return data & 0xffff;
00847 }
00848
00849 #if 0
00850 static void mdio_write(struct nic *nic __unused, int phyad, int regad,
00851 int data)
00852 {
00853 long miiport = mtdx.ioaddr + MANAGEMENT;
00854 u32 miir;
00855 unsigned int mask;
00856
00857 miir = m80x_send_cmd_to_phy(miiport, OP_WRITE, phyad, regad);
00858
00859
00860 mask = 0x8000;
00861 while (mask)
00862 {
00863
00864 miir &= ~(MASK_MIIR_MII_MDC + MASK_MIIR_MII_MDO);
00865 if (mask & data)
00866 miir |= MASK_MIIR_MII_MDO;
00867 outl(miir, miiport);
00868
00869
00870 miir |= MASK_MIIR_MII_MDC;
00871 outl(miir, miiport);
00872
00873
00874 mask >>= 1;
00875 }
00876
00877
00878 miir &= ~MASK_MIIR_MII_MDC;
00879 outl(miir, miiport);
00880
00881 return;
00882 }
00883 #endif
00884
00885 static void getlinkstatus(struct nic *nic)
00886
00887
00888
00889 {
00890 unsigned int i, DelayTime = 0x1000;
00891
00892 mtdx.linkok = 0;
00893
00894 if (mtdx.PHYType == MysonPHY)
00895 {
00896 for (i = 0; i < DelayTime; ++i) {
00897 if (inl(mtdx.ioaddr + BMCRSR) & LinkIsUp2) {
00898 mtdx.linkok = 1;
00899 return;
00900 }
00901
00902 m80x_delay(100);
00903 }
00904 } else
00905 {
00906 for (i = 0; i < DelayTime; ++i) {
00907 if (mdio_read(nic, mtdx.phys[0], MII_BMSR) & BMSR_LSTATUS) {
00908 mtdx.linkok = 1;
00909 return;
00910 }
00911
00912 m80x_delay(100);
00913 }
00914 }
00915 }
00916
00917
00918 static void getlinktype(struct nic *dev)
00919 {
00920 if (mtdx.PHYType == MysonPHY)
00921 {
00922 if (inl(mtdx.ioaddr + TCRRCR) & FD)
00923 mtdx.duplexmode = 2;
00924 else
00925 mtdx.duplexmode = 1;
00926 if (inl(mtdx.ioaddr + TCRRCR) & PS10)
00927 mtdx.line_speed = 1;
00928 else
00929 mtdx.line_speed = 2;
00930 } else
00931 {
00932 if (mtdx.PHYType == SeeqPHY) {
00933 unsigned int data;
00934
00935 data = mdio_read(dev, mtdx.phys[0], MIIRegister18);
00936 if (data & SPD_DET_100)
00937 mtdx.line_speed = 2;
00938 else
00939 mtdx.line_speed = 1;
00940 if (data & DPLX_DET_FULL)
00941 mtdx.duplexmode = 2;
00942 else
00943 mtdx.duplexmode = 1;
00944 } else if (mtdx.PHYType == AhdocPHY) {
00945 unsigned int data;
00946
00947 data = mdio_read(dev, mtdx.phys[0], DiagnosticReg);
00948 if (data & Speed_100)
00949 mtdx.line_speed = 2;
00950 else
00951 mtdx.line_speed = 1;
00952 if (data & DPLX_FULL)
00953 mtdx.duplexmode = 2;
00954 else
00955 mtdx.duplexmode = 1;
00956 }
00957
00958 else if (mtdx.PHYType == MarvellPHY) {
00959 unsigned int data;
00960
00961 data = mdio_read(dev, mtdx.phys[0], SpecificReg);
00962 if (data & Full_Duplex)
00963 mtdx.duplexmode = 2;
00964 else
00965 mtdx.duplexmode = 1;
00966 data &= SpeedMask;
00967 if (data == Speed_1000M)
00968 mtdx.line_speed = 3;
00969 else if (data == Speed_100M)
00970 mtdx.line_speed = 2;
00971 else
00972 mtdx.line_speed = 1;
00973 }
00974
00975
00976 else if (mtdx.PHYType == Myson981) {
00977 unsigned int data;
00978
00979 data = mdio_read(dev, mtdx.phys[0], StatusRegister);
00980
00981 if (data & SPEED100)
00982 mtdx.line_speed = 2;
00983 else
00984 mtdx.line_speed = 1;
00985
00986 if (data & FULLMODE)
00987 mtdx.duplexmode = 2;
00988 else
00989 mtdx.duplexmode = 1;
00990 }
00991
00992
00993 else if (mtdx.PHYType == LevelOnePHY) {
00994 unsigned int data;
00995
00996 data = mdio_read(dev, mtdx.phys[0], SpecificReg);
00997 if (data & LXT1000_Full)
00998 mtdx.duplexmode = 2;
00999 else
01000 mtdx.duplexmode = 1;
01001 data &= SpeedMask;
01002 if (data == LXT1000_1000M)
01003 mtdx.line_speed = 3;
01004 else if (data == LXT1000_100M)
01005 mtdx.line_speed = 2;
01006 else
01007 mtdx.line_speed = 1;
01008 }
01009
01010
01011 mtdx.crvalue &= (~PS10) & (~FD) & (~PS1000);
01012 if (mtdx.line_speed == 1)
01013 mtdx.crvalue |= PS10;
01014 else if (mtdx.line_speed == 3)
01015 mtdx.crvalue |= PS1000;
01016 if (mtdx.duplexmode == 2)
01017 mtdx.crvalue |= FD;
01018 }
01019 }
01020
01021 DRIVER ( "MTD80X", nic_driver, pci_driver, mtd80x_driver,
01022 mtd_probe, mtd_disable );