Take the gpxe stuff out of the build.
[akaros.git] / kern / drivers / net / mii.c
1 /*
2
3         mii.c: MII interface library
4
5         Ported to gPXE by Daniel Verkamp <daniel@drv.nu>
6         from Linux drivers/net/mii.c
7
8         Maintained by Jeff Garzik <jgarzik@pobox.com>
9         Copyright 2001,2002 Jeff Garzik
10
11         Various code came from myson803.c and other files by
12         Donald Becker.  Copyright:
13
14                 Written 1998-2002 by Donald Becker.
15
16                 This software may be used and distributed according
17                 to the terms of the GNU General Public License (GPL),
18                 incorporated herein by reference.  Drivers based on
19                 or derived from this code fall under the GPL and must
20                 retain the authorship, copyright and license notice.
21                 This file is not a complete program and may only be
22                 used when the entire operating system is licensed
23                 under the GPL.
24
25                 The author may be reached as becker@scyld.com, or C/O
26                 Scyld Computing Corporation
27                 410 Severn Ave., Suite 210
28                 Annapolis MD 21403
29
30 */
31
32 #include <vfs.h>
33 #include <kfs.h>
34 #include <slab.h>
35 #include <kmalloc.h>
36 #include <kref.h>
37 #include <string.h>
38 #include <stdio.h>
39 #include <assert.h>
40 #include <error.h>
41 #include <cpio.h>
42 #include <pmap.h>
43 #include <smp.h>
44 #include <ip.h>
45 #include <mii.h>
46
47 /**
48  * mii_link_ok - is link status up/ok
49  * @mii: the MII interface
50  *
51  * Returns 1 if the MII reports link status up/ok, 0 otherwise.
52  */
53 int
54 mii_link_ok ( struct mii_if_info *mii )
55 {
56         /* first, a dummy read, needed to latch some MII phys */
57         mii->mdio_read ( mii->dev, mii->phy_id, MII_BMSR );
58         if ( mii->mdio_read ( mii->dev, mii->phy_id, MII_BMSR ) & BMSR_LSTATUS )
59                 return 1;
60         return 0;
61 }
62
63 /**
64  * mii_check_link - check MII link status
65  * @mii: MII interface
66  *
67  * If the link status changed (previous != current), call
68  * netif_carrier_on() if current link status is Up or call
69  * netif_carrier_off() if current link status is Down.
70  */
71 void
72 mii_check_link ( struct mii_if_info *mii )
73 {
74 #warning "figure out what to do about etherboot netdev; does ours work?"
75 #if 0
76         int cur_link = mii_link_ok ( mii );
77         int prev_link = netdev_link_ok ( mii->dev );
78
79         if ( cur_link && !prev_link )
80                 netdev_link_up ( mii->dev );
81         else if (prev_link && !cur_link)
82                 netdev_link_down ( mii->dev );
83 #endif
84 }
85
86
87 /**
88  * mii_check_media - check the MII interface for a duplex change
89  * @mii: the MII interface
90  * @ok_to_print: OK to print link up/down messages
91  * @init_media: OK to save duplex mode in @mii
92  *
93  * Returns 1 if the duplex mode changed, 0 if not.
94  * If the media type is forced, always returns 0.
95  */
96 unsigned int
97 mii_check_media ( struct mii_if_info *mii,
98                   unsigned int ok_to_print,
99                   unsigned int init_media )
100 {
101         unsigned int old_carrier, new_carrier = 0;
102         int advertise, lpa, media, duplex;
103         int lpa2 = 0;
104
105         /* if forced media, go no further */
106         if (mii->force_media)
107                 return 0; /* duplex did not change */
108
109         /* check current and old link status */
110         old_carrier = 0; //netdev_link_ok ( mii->dev ) ? 1 : 0;
111         new_carrier = (unsigned int) mii_link_ok ( mii );
112
113         /* if carrier state did not change, this is a "bounce",
114          * just exit as everything is already set correctly
115          */
116         if ( ( ! init_media ) && ( old_carrier == new_carrier ) )
117                 return 0; /* duplex did not change */
118
119         /* no carrier, nothing much to do */
120         if ( ! new_carrier ) {
121                 //netdev_link_down ( mii->dev );
122                 if ( ok_to_print )
123                         printd ( "%s: link down\n", mii->dev->name);
124                 return 0; /* duplex did not change */
125         }
126
127         /*
128          * we have carrier, see who's on the other end
129          */
130         //netdev_link_up ( mii->dev );
131
132         /* get MII advertise and LPA values */
133         if ( ( ! init_media ) && ( mii->advertising ) ) {
134                 advertise = mii->advertising;
135         } else {
136                 advertise = mii->mdio_read ( mii->dev, mii->phy_id, MII_ADVERTISE );
137                 mii->advertising = advertise;
138         }
139         lpa = mii->mdio_read ( mii->dev, mii->phy_id, MII_LPA );
140         if ( mii->supports_gmii )
141                 lpa2 = mii->mdio_read ( mii->dev, mii->phy_id, MII_STAT1000 );
142
143         /* figure out media and duplex from advertise and LPA values */
144         media = mii_nway_result ( lpa & advertise );
145         duplex = ( media & ADVERTISE_FULL ) ? 1 : 0;
146         if ( lpa2 & LPA_1000FULL )
147                 duplex = 1;
148
149         if ( ok_to_print )
150                 printd ( "%s: link up, %sMbps, %s-duplex, lpa 0x%04X\n",
151                          "noname", //mii->dev->name,
152                        lpa2 & ( LPA_1000FULL | LPA_1000HALF ) ? "1000" :
153                        media & ( ADVERTISE_100FULL | ADVERTISE_100HALF ) ? "100" : "10",
154                        duplex ? "full" : "half",
155                        lpa);
156
157         if ( ( init_media ) || ( mii->full_duplex != duplex ) ) {
158                 mii->full_duplex = duplex;
159                 return 1; /* duplex changed */
160         }
161
162         return 0; /* duplex did not change */
163 }