apps/mii-diag/libmii.c

Go to the documentation of this file.
00001 /* libmii.c: MII diagnostic and setup library.
00002 
00003         Copyright 1997-2003 by Donald Becker.
00004         This version released under the Gnu General Public License,
00005         incorporated herein by reference.
00006         This source code may be distributed without modification using the
00007         existing notice.  Any modification to this source code must include a
00008         full notice as described in the GPL
00009         Contact the author for use under other terms.
00010 
00011         The author may be reached as becker@scyld.com, or C/O
00012          Scyld Computing Corporation
00013          914 Bay Ridge Road, Suite 220
00014          Annapolis MD 21403
00015 
00016    References
00017         http://www.scyld.com/expert/NWay.html
00018         http://www.national.com/pf/DP/DP83840A.html
00019 */
00020 
00021 static const char version_msg[] =
00022 "libmii.c:v2.11 2/28/2005  Donald Becker (becker@scyld.com)\n"
00023 " http://www.scyld.com/diag/index.html\n";
00024 
00025 /* This library exports the following functions:
00026     IOADDR: A token passed to the mdio_read() function.
00027     PHY_ID: The MII transceiver address, passed uninterpreted to mdio_read().
00028 */
00029 void show_mii_details(long ioaddr, int phy_id);
00030 int monitor_mii(long ioaddr, int phy_id);
00031 
00032 /* This library expects to be able to call the following functions: */
00033 extern int mdio_read(long ioaddr, int phy_id, int mii_reg_num);
00034 
00035 #include <unistd.h>
00036 #include <stdio.h>
00037 #include <time.h>
00038 #include <sys/time.h>
00039 
00040 #include <sys/types.h>
00041 typedef u_int32_t u32;
00042 typedef u_int16_t u16;
00043 typedef u_int8_t u8;
00044 
00045 static const char *media_names[] = {
00046         "10baseT", "10baseT-FD", "100baseTx", "100baseTx-FD", "100baseT4",
00047         "Flow-control", 0,
00048 };
00049 
00050 static void ns83843(long ioaddr, int phy_id);
00051 static void qs6612(long ioaddr, int phy_id);
00052 static void smsc83c180(long ioaddr, int phy_id);
00053 static void tdk78q2120(long ioaddr, int phy_id);
00054 static void davicom_dm9101(long ioaddr, int phy_id);
00055 static void intel_i553(long ioaddr, int phy_id);
00056 static void enablesemi(long ioaddr, int phy_id);
00057 static void amd_pna(long ioaddr, int phy_id);
00058 static void amd_tx(long ioaddr, int phy_id);
00059 static void admtek(long ioaddr, int phy_id);
00060 static void lu3x31(long ioaddr, int phy_id);
00061 static void myson981(long ioaddr, int phy_id);
00062 static void via_tahoe(long ioaddr, int phy_id);
00063 static void via_vt6103(long ioaddr, int phy_id);
00064 static void via_vt6105(long ioaddr, int phy_id);
00065 static void intel(long ioaddr, int phy_id);
00066 
00067 struct mii_partnum {
00068         const char *vendor;                             /* Vendor name. */
00069         u16      phy_id0;                               /* Vendor ID (alternate ver. of ieee_oui[]) */
00070         u16      phy_id1;                               /* Vendor ID (alternate ver. of ieee_oui[]) */
00071         unsigned char ieee_oui[3];      /* IEEE-assigned organizationally unique ID */
00072         char flags;
00073         void (*(func))(long xcvr_if, int phy_id);/* Function to emit more info. */
00074 } static oui_map[] = {
00075         {"Unknown transceiver type", 0x0000, 0x0000, {0,}, 0, NULL,},
00076         {"National Semiconductor 83840A", 0x2000, 0x5c01, {0,}, 0, NULL,},
00077         {"National Semiconductor 83843",  0x2000, 0x5c10, {0,}, 0, ns83843, },
00078         {"Level One LXT970", 0x7810, 0x0000, {0,}, 0, NULL, },
00079         {"Level One LXT971", 0x7810, 0x0001, {0,}, 0, NULL, },
00080         {"Level One LXT971A",0x7810, 0x0003, {0,}, 0, NULL, },
00081         {"Level One (unknown type)", 0, 0, {0x1e,0x04,0x00}, 0, NULL, },
00082         {"Davicom DM9101", 0x0181, 0xB800, {0,}, 0, davicom_dm9101, },
00083         {"Davicom (unknown type)", 0, 0, {0x00, 0x60, 0x6e}, 0, davicom_dm9101, },
00084         {"Quality Semiconductor QS6612", 0x0181, 0x4410, {0,}, 0, qs6612},
00085         {"Quality Semiconductor (unknown type)", 0,0, {0x00, 0x60, 0x51}, 0, NULL},
00086         {"SMSC 83c180", 0x0282, 0x1C51, {0}, 0, smsc83c180, },
00087         {"TDK Semi 78Q2120 rev. 2", 0x0300, 0xE542, {0,}, 0, tdk78q2120, },
00088         {"TDK Semi 78Q2120 rev. 3", 0x0300, 0xE543, {0,}, 0, tdk78q2120, },
00089         {"TDK Semi 78Q2120 rev. 11", 0x0300, 0xE54B, {0,}, 0, tdk78q2120, },
00090         {"TDK transceiver (unknown type)", 0,0, {0x00, 0xc0, 0x39}, 0, tdk78q2120},
00091         {"Intel (unknown type)", 0,0, {0x00, 0xf8, 0x00}, 0, intel_i553},
00092         {"Enable Semiconductor EL40-331", 0x0043, 0x7411, {0,}, 0, enablesemi},
00093         {"AMD 79c901A.1 HomePNA", 0x0000, 0x6B91, {0,}, 0, amd_pna},
00094         {"AMD 79c901A.2 HomePNA", 0x0000, 0x6B92, {0,}, 0, amd_pna},
00095         {"AMD 79c901A.3 HomePNA", 0x0000, 0x6B93, {0,}, 0, amd_pna},
00096         {"AMD 79c901A.3 10baseT", 0x0000, 0x6B71, {0,}, 0, amd_tx},
00097         {"AdHoc Technology AH101LF", 0x0022, 0x561B, {0,}, 0, tdk78q2120},
00098         {"Altimata Communications AC101LF", 0x0022, 0x5523, {0,}, 0, tdk78q2120},
00099         {"Altimata Comm (unknown type)", 0, 0, {0x00,0x10,0xA9}, 0, tdk78q2120},
00100         {"ASIX (unknown type)", 0, 0, {0x00,0xC0,0xB4}, 0, tdk78q2120},
00101         {"ADMtek AN983 Comet", 0x0022, 0x5410, {0,}, 0, admtek},
00102         {"ADMtek AN985 Comet", 0x0022, 0x5513, {0,}, 0, admtek},
00103         {"ADMtek (unknown type)", 0, 0, {0x00,0xe0,0x92}, 0, admtek},
00104         {"Lucent LU6612", 0x0180, 0x7641, {0,}, 0, qs6612},
00105         {"Lucent LU3X31", 0x0043, 0x7411, {0,}, 0, lu3x31},
00106         {"LSI Logic (Seeq) 80225", 0, 0, {0x00,0xA0,0x7D}, 0, NULL},
00107         {"Myson MTD981", 0x0302, 0xD000, {0,}, 0, myson981},
00108         {"Myson (unknown type)", 0, 0, {0x00,0xC0,0xB4,}, 0, myson981},
00109         {"Alta/Kendin Sundance", 0x0022, 0x1720, {0,}, 0, NULL},
00110         {"Alta/Kendin Sundance", 0, 0, {0x00,0x08,0x85}, 0, NULL},
00111         {"VIA Tahoe VT6103", 0x0101, 0x8f20, {0,}, 0, via_vt6103},
00112         {"VIA Tahoe VT6104", 0x0101, 0x8f30, {0,}, 0, via_tahoe},
00113         {"VIA Rhine VT6105", 0x0101, 0x8f22, {0,}, 0, via_vt6105},
00114         {"Intel 82557 series", 0x02a8, 0x0150, {0,}, 0, intel},
00115         {"Intel 82555 rev 1", 0x02a8, 0x0151, {0,}, 0, intel},
00116         {"Intel 82559 transceiver", 0x02a8, 0x0154, {0,}, 0, intel},
00117         {"Intel 82555 series transceiver", 0,0, {0x00,0xaa,0x00}, 0, intel},
00118         {0, },
00119 };
00120 
00121 static u16 mii_val[32];
00122 
00123 void show_mii_details(long ioaddr, int phy_id)
00124 {
00125         int mii_reg, i, vendor = 0;
00126         u16 bmcr, bmsr, new_bmsr;
00127 
00128         /* This may not be omitted from the output. */
00129         printf("%s", version_msg);
00130         printf(" MII PHY #%d transceiver registers:", phy_id);
00131         for (mii_reg = 0; mii_reg < 32; mii_reg++) {
00132                 mii_val[mii_reg] = mdio_read(ioaddr, phy_id, mii_reg);
00133                 printf("%s %4.4x", (mii_reg % 8) == 0 ? "\n  " : "",
00134                            mii_val[mii_reg]);
00135         }
00136         printf(".\n");
00137         if (mii_val[0] == 0xffff) {
00138                 printf("  No MII transceiver present!.\n");
00139                 return;
00140         }
00141         bmcr = mii_val[0];
00142         bmsr = mii_val[1];
00143         printf(" Basic mode control register 0x%4.4x:", bmcr);
00144         if (bmcr & 0x1000)
00145                 printf(" Auto-negotiation enabled.\n");
00146         else
00147                 printf(" Auto-negotiation disabled!\n"
00148                            "   Speed fixed at 10%s mbps, %s-duplex.\n",
00149                            bmcr & 0x2000 ? "0" : "",
00150                            bmcr & 0x0100 ? "full":"half");
00151         if (bmcr & 0x8000)
00152                 printf("  Transceiver currently being reset!\n");
00153         if (bmcr & 0x4000)
00154                 printf("  Transceiver in loopback mode!\n");
00155         if (bmcr & 0x0800)
00156                 printf("  Transceiver powered down!\n");
00157         if (bmcr & 0x0400)
00158                 printf("  Transceiver isolated from the MII!\n");
00159         if (bmcr & 0x0200)
00160                 printf("  Restarted auto-negotiation in progress!\n");
00161         if (bmcr & 0x0080)
00162                 printf("  Internal Collision-Test enabled!\n");
00163         
00164         new_bmsr = mdio_read(ioaddr, phy_id, 1);
00165         printf(" Basic mode status register 0x%4.4x ... %4.4x.\n"
00166                    "   Link status: %sestablished.\n"
00167                    "   Capable of ",
00168                    bmsr, new_bmsr,
00169                    bmsr & 0x0004 ? "" :
00170                     (new_bmsr & 0x0004) ? "previously broken, but now re" : "not ");
00171         if (bmsr & 0xF800) {
00172                 for (i = 15; i >= 11; i--)
00173                         if (bmsr & (1<<i))
00174                                 printf(" %s", media_names[i-11]);
00175         } else
00176                 printf("<Warning! No media capabilities>");
00177 
00178         printf(".\n"
00179                    "   %s to perform Auto-negotiation, negotiation %scomplete.\n",
00180                    bmsr & 0x0008 ? "Able" : "Unable",
00181                    bmsr & 0x0020 ? "" : "not ");
00182 
00183         if (bmsr & 0x0010)
00184                 printf(" Remote fault detected!\n");
00185         if (bmsr & 0x0002)
00186                 printf("   *** Link Jabber! ***\n");
00187 
00188         if (mii_val[2] ^ mii_val[3]) {          /* Eliminate 0x0000 and 0xffff IDs. */
00189                 unsigned char oui_0 = mii_val[2] >> 10;
00190                 unsigned char oui_1 = mii_val[2] >> 2;
00191                 unsigned char oui_2 = (mii_val[2] << 6) | (mii_val[3] >> 10);
00192 
00193                 printf(" Vendor ID is %2.2x:%2.2x:%2.2x:--:--:--, model %d rev. %d.\n",
00194                            oui_0, oui_1, oui_2,
00195                            ((mii_val[3] >> 4) & 0x3f), mii_val[3] & 0x0f);
00196                 for ( i = 0; oui_map[i].vendor; i++)
00197                         /* We match either the Phy ID or the IEEE OUI. */
00198                         if ((oui_map[i].phy_id0 == mii_val[2] &&
00199                                  oui_map[i].phy_id1 == mii_val[3]) ||
00200                                 (oui_map[i].ieee_oui[0] == oui_0 &&
00201                                  oui_map[i].ieee_oui[1] == oui_1 &&
00202                                  oui_map[i].ieee_oui[2] == oui_2)) {
00203                                 printf("   Vendor/Part: %s.\n", oui_map[i].vendor);
00204                                 vendor = i;
00205                                 break;
00206                         }
00207                 if (oui_map[i].vendor == NULL)
00208                         printf("   No specific information is known about this transceiver"
00209                                    " type.\n");
00210         } else
00211                 printf(" This transceiver has no vendor identification.\n");
00212 
00213         {
00214                 int nway_advert = mii_val[4];
00215                 int lkpar = mii_val[5];
00216                 printf(" I'm advertising %4.4x:", nway_advert);
00217                 for (i = 10; i >= 5; i--)
00218                         if (nway_advert & (1<<i))
00219                                 printf(" %s", media_names[i-5]);
00220                 printf("\n   Advertising %sadditional info pages.\n",
00221                            nway_advert & 0x8000 ? "" : "no ");
00222                 if ((nway_advert & 31) == 1)
00223                         printf("   IEEE 802.3 CSMA/CD protocol.\n");
00224                 else
00225                         printf("   Using an unknown (non 802.3) encapsulation.\n");
00226                 printf(" Link partner capability is %4.4x:",
00227                            lkpar);
00228                 for (i = 10; i >= 5; i--)
00229                         if (lkpar & (1<<i))
00230                                 printf(" %s", media_names[i-5]);
00231                 printf(".\n   Negotiation %s.\n",
00232                            lkpar & 0x4000 ? " completed" : "did not complete");
00233         }
00234         if (oui_map[vendor].func)
00235                 oui_map[vendor].func(ioaddr, phy_id);
00236 
00237 }
00238 
00239 int monitor_mii(long ioaddr, int phy_id)
00240 {
00241         int i, last_event = 0;
00242         unsigned short new_1, baseline_1 = mdio_read(ioaddr, phy_id, 1);
00243         struct timeval tv, sleepval;
00244         time_t cur_time;
00245         char timebuf[12];
00246 
00247         if (baseline_1 == 0xffff) {
00248                 fprintf(stderr, "No MII transceiver present to monitor.\n");
00249                 return -1;
00250         }
00251 
00252         gettimeofday(&tv, NULL);
00253         cur_time = tv.tv_sec;
00254         strftime(timebuf, sizeof(timebuf), "%H:%M:%S", localtime(&cur_time));
00255 
00256         printf("Monitoring the MII transceiver status.\n"
00257                    "%s.%03d  Baseline value of MII BMSR (basic mode status register)"
00258                    " is %4.4x.\n", timebuf, (int)tv.tv_usec/1000, baseline_1);
00259         while (1) {
00260                 new_1 = mdio_read(ioaddr, phy_id, 1);
00261                 if (new_1 == 0xffff) {
00262                         fprintf(stderr, "The MII transceiver is no longer accessable!\n");
00263                         return -1;
00264                 }
00265                 if (new_1 != baseline_1) {
00266                         gettimeofday(&tv, NULL);
00267                         cur_time = tv.tv_sec;
00268                         strftime(timebuf, sizeof(timebuf), "%H:%M:%S",
00269                                          localtime(&cur_time));
00270                         printf("%s.%03d  MII BMSR now %4.4x: %4s link, NWay %s, "
00271                                    "%3sJabber%s (%4.4x).\n",
00272                                    timebuf, (int)tv.tv_usec/1000, new_1,
00273                                    new_1 & 0x04 ? "Good" : "no",
00274                                    new_1 & 0x20 ? "done" : "busy",
00275                                    new_1 & 0x02 ? "" : "No ",
00276                                    new_1 & 0x10 ? ", remote fault" : "",
00277                                    mdio_read(ioaddr, phy_id, 5)
00278                                    );
00279                         if (!(baseline_1 & 0x20)  && (new_1 & 0x20)) {
00280                                 int lkpar = mdio_read(ioaddr, phy_id, 5);
00281                                 printf("   New link partner capability is %4.4x %4.4x:",
00282                                            lkpar, mdio_read(ioaddr, phy_id, 6));
00283                                 switch (lkpar) {
00284                                 case 0x45e1: printf(" 10/100 switch w/ flow control"); break;
00285                                 case 0x41e1: printf(" 10/100 HD+FD switch"); break;
00286                                 case 0x40a1: printf(" 10/100 bridged repeater"); break;
00287                                 case 0x4081: printf(" 100baseTx repeater w/autonegotation");
00288                                         break;
00289                                 case 0x0081: printf(" 100baseTx (no autonegotation)"); break;
00290                                 case 0x4021: printf(" 10baseT repeater w/autonegotation");
00291                                         break;
00292                                 case 0x0021: printf(" 10baseT (no autonegotation)"); break;
00293                                 default:
00294                                         for (i = 9; i >= 5; i--)
00295                                                 if (lkpar & (1<<i))
00296                                                         printf(" %s", media_names[i-5]);
00297                                 }
00298                                 printf(".\n");
00299                         }
00300                         fflush(stdout);
00301                         baseline_1 = new_1;
00302                         last_event = 0;
00303                 }
00304                 sleepval.tv_sec = 0;
00305                 sleepval.tv_usec = last_event++ > 30 ? 200000 : 1000;
00306                 select(0, 0, 0, 0, &sleepval);                  /* Or just sleep(1); */
00307         }
00308         printf("  Value of MII BMSR (basic mode status register) is %4.4x.\n",
00309                    mdio_read(ioaddr, phy_id, 1));
00310         return 0;
00311 }
00312 
00313 /* Emit transceiver-specific info. */
00314 
00315 struct msg_tbl { int bitmask;  char *msg; };
00316 
00317 static void msg_if_set(const int val, const struct msg_tbl msg_tbl[])
00318 {
00319         int i;
00320         for (i = 0; msg_tbl[i].bitmask; i++)
00321                 if (msg_tbl[i].bitmask & val)
00322                         printf(" %s\n", msg_tbl[i].msg);
00323 }
00324 
00325 static void msg_if_set_fmt(const int val, const struct msg_tbl msg_tbl[],
00326                                                    const char *fmt)
00327 {
00328         int i;
00329         for (i = 0; msg_tbl[i].bitmask; i++)
00330                 if (msg_tbl[i].bitmask & val)
00331                         printf(fmt, msg_tbl[i].msg);
00332 }
00333 
00334 static void qs6612(long ioaddr, int phy_id)
00335 {
00336         printf("  QS6612 extra registers: Mode %4.4x.\n"
00337                    "    Interrupt source %4.4x, mask %4.4x.\n"
00338                    "    PHY control %4.4x.\n",
00339                    mii_val[17], mii_val[29], mii_val[30], mii_val[31]);
00340         return;
00341 }
00342 
00343 static void ns83843(long ioaddr, int phy_id)
00344 {
00345         printf("  NatSemi 83843 extra registers:\n"
00346                    "    PHY status %4.4x\n"
00347                    "    %s link, %d Mb/sec %s duplex\n"
00348                    "    MII interrupts %sabled, %s pending.\n"
00349                    "    Events since last read\n"
00350                    "     Link disconnects %d\n"
00351                    "     False carriers %d\n"
00352                    "     Receive errors %d\n"
00353                    "    Link beat is currently %sstable\n",
00354                    mii_val[0x10],
00355                    mii_val[10] & 0x0001 ? "Valid" : "Invalid",
00356                    mii_val[10] & 0x0002 ? 10 : 100, 
00357                    mii_val[10] & 0x0004 ? "full" : "half", 
00358                    mii_val[0x11] & 0x0002 ? "en":"dis",
00359                    mii_val[0x10] & 0x0100 ? "interrupt": "none",
00360                    mii_val[0x13], mii_val[0x14], mii_val[0x15],
00361                    mii_val[0x16] & 0x0010 ? "UN" : "");
00362         return;
00363 }
00364 static void smsc83c180(long ioaddr, int phy_id)
00365 {
00366         int mii_reg25 = mii_val[25];
00367         printf("  SMSC 83c180 extra registers:\n"
00368                    "    Auto-negotiation status 0x%4.4x.\n"
00369                    "      10baseT polarity is %s.\n"
00370                    "      PHY address is %d.\n"
00371                    "      Auto-negotiation %scomplete, 1%s0Mbps %s duplex.\n"
00372                    "    Rx symbol errors since last read %d.\n",
00373                    mii_reg25,
00374                    mii_reg25 & 0x2000 ? "normal" : "reversed",
00375                    (mii_reg25>>8) & 0x1F,
00376                    mii_reg25 & 0x0080 ? "did not " : "",
00377                    mii_reg25 & 0x0020 ? "0" : "",
00378                    mii_reg25 & 0x0040 ? "full" : "half",
00379                    mdio_read(ioaddr, phy_id, 26));
00380         return;
00381 }
00382 
00383 static const char *tdk_events[8] = {
00384         "Jabber", "Rx error", "Negotiation page received", "Link detection fault",
00385         "Link partner acknowledge", "Link status change", "Remote partner fault",
00386         "Auto-Negotiation complete"};
00387 
00388 static const struct msg_tbl tdk_reg16[] = {
00389         {0x8000, " Transceiver is in repeater mode!"},
00390         {0x4000, " Interrupt pin set to active high."},
00391         {0x2000, " Reserved bit 12 is unexpectedly set."},
00392         {0x1000, " Transmit pins are internally disconnected."},
00393         {0x0800, " 10baseT signal quality test is disabled."},
00394         {0x0400, " 10baseT loopback mode."},
00395         {0, 0},
00396 };
00397 
00398 static void tdk78q2120(long ioaddr, int phy_id)
00399 {
00400         int mii_reg16 = mii_val[16];
00401         int mii_reg17 = mii_val[17];
00402         int mii_reg18 = mii_val[18];
00403         int i;
00404         printf("  TDK format vendor-specific registers 16..18 are "
00405                    "0x%4.4x 0x%4.4x 0x%4.4x\n", mii_reg16, mii_reg17, mii_reg18);
00406         printf("      Link polarity is %s %s.\n"
00407                    "%s%s"
00408                    "      Auto-negotiation %s, 1%s0Mbps %s duplex.\n"
00409                    "      Rx link in %s state, PLL %s.\n",
00410                    mii_reg16 & 0x0020 ? "OVERRIDDEN to" : "detected as",
00411                    mii_reg16 & 0x0010 ? "reversed" : "normal",
00412                    mii_reg16 & 0x0002 ?
00413                    "     100baseTx Coding and scrambling is disabled!\n":"",
00414                    mii_reg16 & 0x0001 ? "     Rx_CLK power-save mode is enabled!\n":"",
00415                    mii_reg18 & 0x1000 ? "had no common media" : "complete",
00416                    mii_reg18 & 0x0400 ? "0" : "",
00417                    mii_reg18 & 0x0800 ? "full" : "half",
00418                    mii_reg18 & 0x0200 ? "pass" : "fail",
00419                    mii_reg18 & 0x0100 ? "slipped since last read" : "locked");
00420 
00421         msg_if_set(mii_reg16, tdk_reg16);
00422         if (mii_reg17 & 0x00ff) {
00423                 printf("      Events since last read:");
00424                 for (i = 0; i < 8; i++)
00425                         if (mii_reg17 & (1 << i))
00426                                 printf("  %s", tdk_events[i]);
00427         } else
00428                 printf("      No new link status events.");
00429 
00430         if (mii_reg17 & 0xff00) {
00431                 printf("\n      Events that will raise an interrupt:");
00432                 for (i = 0; i < 8; i++)
00433                         if (mii_reg17 & (0x100 << i))
00434                                 printf("  %s", tdk_events[i]);
00435         }
00436         printf("\n");
00437         return;
00438 }
00439 
00440 static void davicom_dm9101(long ioaddr, int phy_id)
00441 {
00442         printf("  Davicom vendor specific registers: 0x%4.4x 0x%4.4x 0x%4.4x.\n",
00443                    mii_val[16], mii_val[17], mii_val[18]);
00444 }
00445 static void intel_i553(long ioaddr, int phy_id)
00446 {
00447         printf("  This transceiver is 100baseT4 only!  Register 16 is %4.4x.\n",
00448                    mii_val[16]);
00449 }
00450 /* http://www.enablesemi.com/cgi-bin/byteserve/Products/Docs/3VCardBus.pdf */
00451 static void enablesemi(long ioaddr, int phy_id)
00452 {
00453         printf("  Isolated %d times, %d false carrier events, %d Rx errors.\n",
00454                    mii_val[18], mii_val[19], mii_val[21]);
00455         printf("  Cable polarity is %s, 100Mb PLL is %slocked.\n",
00456                    mii_val[28]&0x8000 ? "reversed" : "normal",
00457                    mii_val[27]&0x2000 ? "" : "un");
00458 }
00459 /* The amd79c901 contains both PNA and 10/100 management registers.
00460    http://www.amd.com/products/npd/techdocs/22304.pdf
00461 */
00462 static void amd_pna(long ioaddr, int phy_id)
00463 {
00464         printf("  HomePNA transceiver in %s speed, %s power mode.\n",
00465                    mii_val[16] & 4 ? "high" : "low",
00466                    mii_val[16] & 2 ? "high" : "low");
00467         printf("  HomePNA noise level %d, peak power %d..\n",
00468                    mii_val[25] >> 8, mii_val[25] & 0xff);
00469 }
00470 static void amd_tx(long ioaddr, int phy_id)
00471 {
00472         int mii_reg25 = mii_val[25];
00473         printf("  AMD vendor specific registers: 0x%4.4x 0x%4.4x 0x%4.4x.\n",
00474                    mii_val[16], mii_val[17], mii_val[18]);
00475         printf("  The link is %s in 10%s %s duplex mode, autonegotiation state "
00476                    "has%s changed.\n",
00477                    mii_reg25 & 8 ? "up" : "down",
00478                    mii_reg25 & 1 ? "0baseTx" : "baseT",
00479                    mii_reg25 & 4 ? "full" : "half",
00480                    mii_reg25 & 2 ? "" : " not");
00481 }
00482 
00483 static const struct msg_tbl admtek_reg21[] = {
00484         {0x4000, " Link test diabled: Ignoring lack of 10baseT link beat."},
00485         {0x2000, " Link forced up."},
00486         {0x1000, " Tx jabber check disabled."},
00487         {0x0080, " Transmitting 'Far End Fault'!"},
00488         {0x0040, " Rx error count full."},
00489         {0x0008, " Remote loop back enabled."},
00490         {0, 0},
00491 };
00492 
00493 static void admtek(long ioaddr, int phy_id)
00494 {
00495 
00496         printf("  ADMtek vendor specific registers information:\n"
00497                    "   Cable length is approximately %d meters.\n"
00498                    "   The receiver has lost lock %d times since last check and "
00499                    "had %d error events.\n",
00500                    ((mii_val[20] & 0x00f0) >> 4)*10,
00501                    mii_val[23], mii_val[23]);
00502         msg_if_set(mii_val[21], admtek_reg21);
00503         tdk78q2120(ioaddr, phy_id);
00504 }
00505 
00506 static void lu3x31(long ioaddr, int phy_id)
00507 {
00508         printf("  Lucent vendor specific registers 17: 0x%4.4x"
00509                    " 29: 0x%4.4x 30: 0x%4.4x 31: 0x%4.4x.\n",
00510                    mii_val[17], mii_val[29], mii_val[30], mii_val[31]);
00511 }
00512 
00513 static const struct msg_tbl myson_reg16[] = {
00514         {0x0080, " Far end fault enabled."},
00515         {0x0040, " Transformer ratio 1.25:1."},
00516         {0x0020, " Polarity correction diabled."},
00517         {0x0010, " Link is forced up regardless of link beat."},
00518         {0x0004, " Bypass Jabber check."},
00519         {0x0001, " 100baseFx mode selected."},
00520         {0, 0},
00521 };
00522 
00523 static void myson981(long ioaddr, int phy_id)
00524 {
00525         int i, mii_reg17 = mii_val[17];
00526 
00527         printf("  Myson mtd981 extra registers: %4.4x %4.4x %4.4x %4.4x.\n",
00528                    mii_val[16], mii_val[17], mii_val[18], mii_val[19]);
00529         msg_if_set(mii_val[16] & 0xC800, tdk_reg16);
00530         msg_if_set(mii_val[16], myson_reg16);
00531 
00532         if (mii_reg17 & 0x00ff) {
00533                 printf("      Events since last read:");
00534                 for (i = 0; i < 8; i++)
00535                         if (mii_reg17 & (1 << i))
00536                                 printf("  %s", tdk_events[i]);
00537         } else
00538                 printf("      No new link status events.");
00539         if (mii_reg17 & 0xff00) {
00540                 printf("\n      Events that will raise an interrupt:");
00541                 for (i = 0; i < 8; i++)
00542                         if (mii_reg17 & (0x100 << i))
00543                                 printf("  %s", tdk_events[i]);
00544         }
00545         printf("\n");
00546 
00547         return;
00548 }
00549 
00550 /* These are much like the TDK events in reversed order. */
00551 static const struct msg_tbl via_reg17[] = {
00552         {0x0001, "Auto-Negotiation complete"},
00553         {0x0002, "Remote fault detected"},
00554         {0x0004, "Link failure detected"},
00555         {0x0008, "Bad Start Stream detected"},
00556         {0x0010, "Parallel detection fault"},
00557         {0x0020, "Extended negotiation page received"},
00558         {0x0040, "5B/4B code error detected"},
00559         {0x0080, "Jabber detected"},
00560         {0, 0},
00561 };
00562 
00563 static void via_tahoe(long ioaddr, int phy_id)
00564 {
00565         int mii_reg16 = mii_val[16];
00566         int mii_reg17 = mii_val[17];
00567         int mii_reg18 = mii_val[18];
00568 
00569         printf("  VIA Tahoe extended registers: 16 %4.4x  #17 %4.4x  #18 %4.4x.\n",
00570                    mii_reg16, mii_reg17, mii_reg18);
00571         msg_if_set_fmt(mii_reg17, via_reg17, "   %s\n");
00572         printf("   Link %s 10%s Mbps %s duplex\n",
00573                    mii_reg18 & 0x2000 ? "up" : "down",
00574                    mii_reg18 & 0x0400 ? "0" : "",
00575                    mii_reg18 & 0x0800 ? "full" : "half");
00576 }
00577 
00578 /* Information from
00579    http://www.via.com.tw/en/datasheet/DS6103110.pdf
00580 */
00581    
00582 static void via_vt6103(long ioaddr, int phy_id)
00583 {
00584         printf("  VIA vt6103 error counts since the last check:\n"
00585                    "   The link has failed %d times.\n"
00586                    "   The receiver has lost lock %d times.\n"
00587                    "   There have been %d false carrier/SQE error.\n",
00588                    mii_val[21], mii_val[22], mii_val[23]);
00589 }
00590 
00591 /* Information from
00592    http://www.via.com.tw/en/Networking/DS6105LOM100.pdf
00593 */
00594 
00595 static void via_vt6105(long ioaddr, int phy_id)
00596 {
00597         printf("  VIA vt6105 PHY status:\n"
00598                    "   Duplex %s  speed %s\n",
00599                    mii_val[20] & 0x0001 ? "full" : "half",
00600                    mii_val[20] & 0x0002 ? "100" : "10");
00601 }
00602 
00603 /* Information from
00604    http://www.via.com.tw/en/Networking/DS6105LOM100.pdf
00605 */
00606 static void intel(long ioaddr, int phy_id)
00607 {
00608         printf("  Intel 8255* PHY #%d extended management registers:\n"
00609                    "    Error counts, cleared when read:\n"
00610                    "     False carriers %d\n"
00611                    "     Link disconnects %d\n"
00612                    "     Receive errors %d\n"
00613                    "     Rx symbol errors %d.\n"
00614                    "     Rx 10Mbps Early End-Of-Frame errors %d.\n"
00615                    "     Rx 100Mbps Early End-Of-Frame errors %d.\n"
00616                    "     Tx jabber errors %d.\n",
00617                    mii_val[18],
00618                    mii_val[19], mii_val[20], mii_val[21], mii_val[22], mii_val[23],
00619                    mii_val[24], mii_val[25]);
00620 }
00621 
00622 
00623 /*
00624  * Local variables:
00625  *  compile-command: "cc -O -Wall -c libmii.c"
00626  *  c-indent-level: 4
00627  *  c-basic-offset: 4
00628  *  tab-width: 4
00629  * End:
00630  */

Generated on Fri Nov 28 00:06:21 2008 for elphel by  doxygen 1.5.1