source: rtems/cpukit/libnetworking/rtems/rtems_mii_ioctl_kern.c @ 1e0cc86

5
Last change on this file since 1e0cc86 was 65c6425, checked in by Joel Sherrill <joel.sherrill@…>, on 05/03/12 at 17:24:46

Remove CVS Id Strings (manual edits after script)

These modifications were required by hand after running the script.
In some cases, the file names did not match patterns. In others,
the format of the file did not match any common patterns.

  • Property mode set to 100644
File size: 6.9 KB
Line 
1/* Simple (default) implementation for SIOCGIFMEDIA/SIOCSIFMEDIA
2 * to be used by ethernet drivers [from their ioctl].
3 *
4 * KERNEL PART (support for drivers)
5 *
6 * NOTE: This much simpler than the BSD ifmedia API
7 */
8
9/*
10 * Authorship
11 * ----------
12 * This software was created by
13 *     Till Straumann <strauman@slac.stanford.edu>, 2005,
14 *         Stanford Linear Accelerator Center, Stanford University.
15 *
16 * Acknowledgement of sponsorship
17 * ------------------------------
18 * This software was produced by
19 *     the Stanford Linear Accelerator Center, Stanford University,
20 *         under Contract DE-AC03-76SFO0515 with the Department of Energy.
21 *
22 * Government disclaimer of liability
23 * ----------------------------------
24 * Neither the United States nor the United States Department of Energy,
25 * nor any of their employees, makes any warranty, express or implied, or
26 * assumes any legal liability or responsibility for the accuracy,
27 * completeness, or usefulness of any data, apparatus, product, or process
28 * disclosed, or represents that its use would not infringe privately owned
29 * rights.
30 *
31 * Stanford disclaimer of liability
32 * --------------------------------
33 * Stanford University makes no representations or warranties, express or
34 * implied, nor assumes any liability for the use of this software.
35 *
36 * Stanford disclaimer of copyright
37 * --------------------------------
38 * Stanford University, owner of the copyright, hereby disclaims its
39 * copyright and all other rights in this software.  Hence, anyone may
40 * freely use it for any purpose without restriction.
41 *
42 * Maintenance of notices
43 * ----------------------
44 * In the interest of clarity regarding the origin and status of this
45 * SLAC software, this and all the preceding Stanford University notices
46 * are to remain affixed to any copy or derivative of this software made
47 * or distributed by the recipient and are to be affixed to any copy of
48 * software made or distributed by the recipient that contains a copy or
49 * derivative of this software.
50 *
51 * ------------------ SLAC Software Notices, Set 4 OTT.002a, 2004 FEB 03
52 */
53
54/* include first to avoid 'malloc' clash with rtems_bsdnet_malloc() hack */
55
56#include <rtems.h>
57#include <rtems/rtems_bsdnet.h>
58#include <sys/mbuf.h>
59#include <sys/socket.h>
60#include <sys/sockio.h>
61#include <net/ethernet.h>
62#include <net/if.h>
63
64#ifndef __KERNEL__
65#define __KERNEL__
66#endif
67
68#include <rtems/rtems_mii_ioctl.h>
69
70#include <errno.h>
71
72
73#define DEBUG
74
75
76#ifndef MII_1000TCR
77#define MII_1000TCR MII_100T2CR
78#endif
79
80#ifndef MII_1000TSR
81#define MII_1000TSR MII_100T2SR
82#endif
83
84int
85rtems_mii_ioctl (struct rtems_mdio_info *info, void *uarg, uint32_t cmd,
86                 int *media)
87{
88  uint32_t bmcr, bmsr, aner, bmcr2 = 0, bmsr2 = 0, anar, lpar;
89  int phy = IFM_INST (*media);
90  uint32_t tmp;
91  int subtype = 0, options = 0;
92
93  switch (cmd) {
94  default:
95    return EINVAL;
96
97#ifdef DEBUG
98  case 0:
99#endif
100  case SIOCGIFMEDIA:
101    if (info->mdio_r (phy, uarg, MII_BMCR, &bmcr))
102      return EINVAL;
103        /* read BMSR twice to clear latched link status low */
104    if (info->mdio_r (phy, uarg, MII_BMSR, &bmsr))
105      return EINVAL;
106    if (info->mdio_r (phy, uarg, MII_BMSR, &bmsr))
107      return EINVAL;
108    if (info->mdio_r (phy, uarg, MII_ANER, &aner))
109      return EINVAL;
110    if (info->has_gmii) {
111      if (info->mdio_r (phy, uarg, MII_1000TCR, &bmcr2))
112        return EINVAL;
113      if (info->mdio_r (phy, uarg, MII_1000TSR, &bmsr2))
114        return EINVAL;
115    }
116
117    /* link status */
118    if (BMSR_LINK & bmsr)
119      options |= IFM_LINK_OK;
120
121    /* do we have autonegotiation disabled ? */
122    if (!(BMCR_AUTOEN & bmcr)) {
123      options |= IFM_ANEG_DIS;
124
125      /* duplex is enforced */
126      options |= BMCR_FDX & bmcr ? IFM_FDX : IFM_HDX;
127
128      /* determine speed */
129      switch (BMCR_SPEED (bmcr)) {
130      case BMCR_S10:
131        subtype = IFM_10_T;
132        break;
133      case BMCR_S100:
134        subtype = IFM_100_TX;
135        break;
136      case BMCR_S1000:
137        subtype = IFM_1000_T;
138        break;
139      default:
140        return ENOTSUP;         /* ?? */
141      }
142    } else if (!(BMSR_LINK & bmsr) || !(BMSR_ACOMP & bmsr)) {
143      subtype = IFM_NONE;
144    } else {
145      /* everything ok on our side */
146
147          if ( ! (ANER_LPAN & aner) ) {
148                /* Link partner doesn't autonegotiate --> our settings are the
149                 * result of 'parallel detect' (in particular: duplex status is HALF
150                 * according to the standard!).
151                 * Let them know that something's fishy...
152                 */
153                options |= IFM_ANEG_DIS;
154          }
155
156      tmp = ((bmcr2 << 2) & bmsr2) & (GTSR_LP_1000THDX | GTSR_LP_1000TFDX);
157      if (tmp) {
158        if (GTSR_LP_1000TFDX & tmp)
159          options |= IFM_FDX;
160        subtype = IFM_1000_T;
161      } else {
162        if (info->mdio_r (phy, uarg, MII_ANAR, &anar))
163          return EINVAL;
164        if (info->mdio_r (phy, uarg, MII_ANLPAR, &lpar))
165          return EINVAL;
166        if (ANLPAR_ACK & lpar) {
167          /* this is a negotiated link; otherwise we merely detect the partner's ability */
168        }
169        tmp = anar & lpar;
170        if (ANLPAR_TX_FD & tmp) {
171          options |= IFM_FDX;
172          subtype = IFM_100_TX;
173        } else if (ANLPAR_T4 & tmp) {
174          subtype = IFM_100_T4;
175        } else if (ANLPAR_TX & tmp) {
176          subtype = IFM_100_TX;
177        } else if (ANLPAR_10_FD & tmp) {
178          options |= IFM_FDX;
179          subtype = IFM_10_T;
180        } else {
181          subtype = IFM_10_T;
182        }
183      }
184    }
185
186    *media = IFM_MAKEWORD (IFM_ETHER, subtype, options, phy);
187
188    break;
189
190#ifdef DEBUG
191  case 1:
192#endif
193  case SIOCSIFMEDIA:
194    if (IFM_ETHER != IFM_TYPE (*media))
195      return EINVAL;
196
197    if (info->mdio_r (phy, uarg, MII_BMSR, &bmsr))
198      return EINVAL;
199
200    tmp = (IFM_FDX & *media);
201
202    switch (IFM_SUBTYPE (*media)) {
203    default:
204      return ENOTSUP;
205
206    case IFM_AUTO:
207      bmcr = BMCR_AUTOEN | BMCR_STARTNEG;
208      tmp = 0;
209      break;
210
211    case IFM_1000_T:
212      if (!info->has_gmii)
213        return ENOTSUP;
214
215      if (info->mdio_r (phy, uarg, MII_EXTSR, &bmsr2))
216        return EINVAL;
217
218      if (!(bmsr2 & (tmp ? EXTSR_1000TFDX : EXTSR_1000THDX)))
219        return EOPNOTSUPP;
220
221          /* NOTE: gige standard demands auto-negotiation for gige links.
222           *       Disabling autoneg did NOT work on the PHYs I tried
223           *       (BCM5421S, intel 82540).
224           *       I've seen drivers that simply change what they advertise
225           *       to the desired gig mode and re-negotiate.
226           *       We could do that here, too, but we don't see the point -
227           *       If autoneg works fine then we can as well use it.
228           */
229      bmcr = BMCR_S1000;
230      break;
231
232    case IFM_100_TX:
233      if (!(bmsr & (tmp ? BMSR_100TXFDX : BMSR_100TXHDX)))
234        return EOPNOTSUPP;
235      bmcr = BMCR_S100;
236      break;
237
238    case IFM_10_T:
239      if (!(bmsr & (tmp ? BMSR_10TFDX : BMSR_10THDX)))
240        return EOPNOTSUPP;
241      bmcr = BMCR_S10;
242      break;
243    }
244
245    if (tmp)
246      bmcr |= BMCR_FDX;
247
248    if (info->mdio_w (phy, uarg, MII_BMCR, bmcr))
249      return EINVAL;
250
251    /* TODO: should we adapt advertised capabilites ? */
252
253    break;
254  }
255
256  return 0;
257}
Note: See TracBrowser for help on using the repository browser.