source: rtems/cpukit/libnetworking/rtems/rtems_mii_ioctl_kern.c @ db93c2f

4.104.115
Last change on this file since db93c2f was db93c2f, checked in by Till Straumann <strauman@…>, on 04/15/09 at 03:44:41

2009-04-14 Till Straumann <strauman@…>

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