source: rtems-libbsd/rtemsbsd/rtems/rtems_mii_ioctl_kern.c @ e58b898

55-freebsd-126-freebsd-12freebsd-9.3
Last change on this file since e58b898 was 410e305, checked in by Sebastian Huber <sebastian.huber@…>, on 12/06/13 at 08:57:59

Add RTEMS legacy MII support

  • 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 <machine/rtems-bsd-kernel-space.h>
57
58#include <rtems/bsd/sys/param.h>
59#include <sys/mbuf.h>
60#include <sys/socket.h>
61#include <sys/sockio.h>
62#include <net/ethernet.h>
63#include <net/if.h>
64
65#include <rtems/rtems_mii_ioctl.h>
66
67#include <errno.h>
68
69
70#define DEBUG
71
72
73#ifndef MII_1000TCR
74#define MII_1000TCR MII_100T2CR
75#endif
76
77#ifndef MII_1000TSR
78#define MII_1000TSR MII_100T2SR
79#endif
80
81int
82rtems_mii_ioctl (struct rtems_mdio_info *info, void *uarg, uint32_t cmd,
83                 int *media)
84{
85  uint32_t bmcr, bmsr, aner, bmcr2 = 0, bmsr2 = 0, anar, lpar;
86  int phy = IFM_INST (*media);
87  uint32_t tmp;
88  int subtype = 0, options = 0;
89
90  switch (cmd) {
91  default:
92    return EINVAL;
93
94#ifdef DEBUG
95  case 0:
96#endif
97  case SIOCGIFMEDIA:
98    if (info->mdio_r (phy, uarg, MII_BMCR, &bmcr))
99      return EINVAL;
100        /* read BMSR twice to clear latched link status low */
101    if (info->mdio_r (phy, uarg, MII_BMSR, &bmsr))
102      return EINVAL;
103    if (info->mdio_r (phy, uarg, MII_BMSR, &bmsr))
104      return EINVAL;
105    if (info->mdio_r (phy, uarg, MII_ANER, &aner))
106      return EINVAL;
107    if (info->has_gmii) {
108      if (info->mdio_r (phy, uarg, MII_1000TCR, &bmcr2))
109        return EINVAL;
110      if (info->mdio_r (phy, uarg, MII_1000TSR, &bmsr2))
111        return EINVAL;
112    }
113
114    /* link status */
115    if (BMSR_LINK & bmsr)
116      options |= IFM_LINK_OK;
117
118    /* do we have autonegotiation disabled ? */
119    if (!(BMCR_AUTOEN & bmcr)) {
120      options |= IFM_ANEG_DIS;
121
122      /* duplex is enforced */
123      options |= BMCR_FDX & bmcr ? IFM_FDX : IFM_HDX;
124
125      /* determine speed */
126      switch (BMCR_SPEED (bmcr)) {
127      case BMCR_S10:
128        subtype = IFM_10_T;
129        break;
130      case BMCR_S100:
131        subtype = IFM_100_TX;
132        break;
133      case BMCR_S1000:
134        subtype = IFM_1000_T;
135        break;
136      default:
137        return ENOTSUP;         /* ?? */
138      }
139    } else if (!(BMSR_LINK & bmsr) || !(BMSR_ACOMP & bmsr)) {
140      subtype = IFM_NONE;
141    } else {
142      /* everything ok on our side */
143
144          if ( ! (ANER_LPAN & aner) ) {
145                /* Link partner doesn't autonegotiate --> our settings are the
146                 * result of 'parallel detect' (in particular: duplex status is HALF
147                 * according to the standard!).
148                 * Let them know that something's fishy...
149                 */
150                options |= IFM_ANEG_DIS;
151          }
152
153      tmp = ((bmcr2 << 2) & bmsr2) & (GTSR_LP_1000THDX | GTSR_LP_1000TFDX);
154      if (tmp) {
155        if (GTSR_LP_1000TFDX & tmp)
156          options |= IFM_FDX;
157        subtype = IFM_1000_T;
158      } else {
159        if (info->mdio_r (phy, uarg, MII_ANAR, &anar))
160          return EINVAL;
161        if (info->mdio_r (phy, uarg, MII_ANLPAR, &lpar))
162          return EINVAL;
163        if (ANLPAR_ACK & lpar) {
164          /* this is a negotiated link; otherwise we merely detect the partner's ability */
165        }
166        tmp = anar & lpar;
167        if (ANLPAR_TX_FD & tmp) {
168          options |= IFM_FDX;
169          subtype = IFM_100_TX;
170        } else if (ANLPAR_T4 & tmp) {
171          subtype = IFM_100_T4;
172        } else if (ANLPAR_TX & tmp) {
173          subtype = IFM_100_TX;
174        } else if (ANLPAR_10_FD & tmp) {
175          options |= IFM_FDX;
176          subtype = IFM_10_T;
177        } else {
178          subtype = IFM_10_T;
179        }
180      }
181    }
182
183    *media = IFM_MAKEWORD (IFM_ETHER, subtype, options, phy);
184
185    break;
186
187#ifdef DEBUG
188  case 1:
189#endif
190  case SIOCSIFMEDIA:
191    if (IFM_ETHER != IFM_TYPE (*media))
192      return EINVAL;
193
194    if (info->mdio_r (phy, uarg, MII_BMSR, &bmsr))
195      return EINVAL;
196
197    tmp = (IFM_FDX & *media);
198
199    switch (IFM_SUBTYPE (*media)) {
200    default:
201      return ENOTSUP;
202
203    case IFM_AUTO:
204      bmcr = BMCR_AUTOEN | BMCR_STARTNEG;
205      tmp = 0;
206      break;
207
208    case IFM_1000_T:
209      if (!info->has_gmii)
210        return ENOTSUP;
211
212      if (info->mdio_r (phy, uarg, MII_EXTSR, &bmsr2))
213        return EINVAL;
214
215      if (!(bmsr2 & (tmp ? EXTSR_1000TFDX : EXTSR_1000THDX)))
216        return EOPNOTSUPP;
217
218          /* NOTE: gige standard demands auto-negotiation for gige links.
219           *       Disabling autoneg did NOT work on the PHYs I tried
220           *       (BCM5421S, intel 82540).
221           *       I've seen drivers that simply change what they advertise
222           *       to the desired gig mode and re-negotiate.
223           *       We could do that here, too, but we don't see the point -
224           *       If autoneg works fine then we can as well use it.
225           */
226      bmcr = BMCR_S1000;
227      break;
228
229    case IFM_100_TX:
230      if (!(bmsr & (tmp ? BMSR_100TXFDX : BMSR_100TXHDX)))
231        return EOPNOTSUPP;
232      bmcr = BMCR_S100;
233      break;
234
235    case IFM_10_T:
236      if (!(bmsr & (tmp ? BMSR_10TFDX : BMSR_10THDX)))
237        return EOPNOTSUPP;
238      bmcr = BMCR_S10;
239      break;
240    }
241
242    if (tmp)
243      bmcr |= BMCR_FDX;
244
245    if (info->mdio_w (phy, uarg, MII_BMCR, bmcr))
246      return EINVAL;
247
248    /* TODO: should we adapt advertised capabilites ? */
249
250    break;
251  }
252
253  return 0;
254}
Note: See TracBrowser for help on using the repository browser.