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

4.104.114.84.95
Last change on this file since e131ac0 was e131ac0, checked in by Till Straumann <strauman@…>, on 11/03/05 at 03:09:45

2005-11-02 straumanatslacdotstanford.edu

  • libnetworking/Makefile.am, libnetworking/preinstall.am: Added simple implementation of ethernet media ioctl SIOCSIFMEDIA/SIOCGIFMEDIA for mii compliant phys.
  • libnetworking/rtems/rtems_mii_ioctl.c, libnetworking/rtems/rtems_mii_ioctl.h, libnetworking/rtems/rtems_mii_ioctl_kern.c: New files.
  • Property mode set to 100644
File size: 4.3 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/* Author: Till Straumann, <straumanatslacdotstandorddotedu>, 2005 */
12
13/* include first to avoid 'malloc' clash with rtems_bsdnet_malloc() hack */
14
15#include <rtems.h>
16#include <rtems/rtems_bsdnet.h>
17#include <sys/mbuf.h>
18#include <sys/socket.h>
19#include <sys/sockio.h>
20#include <net/ethernet.h>
21#include <net/if.h>
22
23#ifndef __KERNEL__
24#define __KERNEL__
25#endif
26
27#include <rtems/rtems_mii_ioctl.h>
28
29#include <sys/errno.h>
30
31
32#define DEBUG
33
34
35#ifndef MII_1000TCR
36#define MII_1000TCR MII_100T2CR
37#endif
38
39#ifndef MII_1000TSR
40#define MII_1000TSR MII_100T2SR
41#endif
42
43int
44rtems_mii_ioctl (struct rtems_mdio_info *info, void *uarg, int cmd,
45                 int *media)
46{
47  unsigned32 bmcr, bmsr, bmcr2 = 0, bmsr2 = 0, anar, lpar;
48  int phy = IFM_INST (*media);
49  unsigned tmp;
50  int subtype = 0, options = 0;
51
52  switch (cmd) {
53  default:
54    return EINVAL;
55
56#ifdef DEBUG
57  case 0:
58#endif
59  case SIOCGIFMEDIA:
60    if (info->mdio_r (phy, uarg, MII_BMCR, &bmcr))
61      return EINVAL;
62    if (info->mdio_r (phy, uarg, MII_BMSR, &bmsr))
63      return EINVAL;
64    if (info->has_gmii) {
65      if (info->mdio_r (phy, uarg, MII_1000TCR, &bmcr2))
66        return EINVAL;
67      if (info->mdio_r (phy, uarg, MII_1000TSR, &bmsr2))
68        return EINVAL;
69    }
70
71    /* link status */
72    if (BMSR_LINK & bmsr)
73      options |= IFM_LINK_OK;
74
75    /* do we have autonegotiation disabled ? */
76    if (!(BMCR_AUTOEN & bmcr)) {
77      options |= IFM_ANEG_DIS;
78
79      /* duplex is enforced */
80      options |= BMCR_FDX & bmcr ? IFM_FDX : IFM_HDX;
81
82      /* determine speed */
83      switch (BMCR_SPEED (bmcr)) {
84      case BMCR_S10:
85        subtype = IFM_10_T;
86        break;
87      case BMCR_S100:
88        subtype = IFM_100_TX;
89        break;
90      case BMCR_S1000:
91        subtype = IFM_1000_T;
92        break;
93      default:
94        return ENOTSUP;         /* ?? */
95      }
96    } else if (!(BMSR_LINK & bmsr) || !(BMSR_ACOMP & bmsr)) {
97      subtype = IFM_NONE;
98    } else {
99      /* everything ok */
100
101      tmp = ((bmcr2 >> 2) & bmsr2) & (GTSR_LP_1000THDX | GTSR_LP_1000TFDX);
102      if (tmp) {
103        if (GTSR_LP_1000TFDX & tmp)
104          options |= IFM_FDX;
105        subtype = IFM_1000_T;
106      } else {
107        if (info->mdio_r (phy, uarg, MII_ANAR, &anar))
108          return EINVAL;
109        if (info->mdio_r (phy, uarg, MII_ANLPAR, &lpar))
110          return EINVAL;
111        if (ANLPAR_ACK & lpar) {
112          /* this is a negotiated link; otherwise we merely detect the partner's ability */
113        }
114        tmp = anar & lpar;
115        if (ANLPAR_TX_FD & tmp) {
116          options |= IFM_FDX;
117          subtype = IFM_100_TX;
118        } else if (ANLPAR_T4 & tmp) {
119          subtype = IFM_100_T4;
120        } else if (ANLPAR_TX & tmp) {
121          subtype = IFM_100_TX;
122        } else if (ANLPAR_10_FD & tmp) {
123          options |= IFM_FDX;
124          subtype = IFM_10_T;
125        } else {
126          subtype = IFM_10_T;
127        }
128      }
129    }
130
131    *media = IFM_MAKEWORD (IFM_ETHER, subtype, options, phy);
132
133    break;
134
135#ifdef DEBUG
136  case 1:
137#endif
138  case SIOCSIFMEDIA:
139    if (IFM_ETHER != IFM_TYPE (*media))
140      return EINVAL;
141
142    if (info->mdio_r (phy, uarg, MII_BMSR, &bmsr))
143      return EINVAL;
144
145    tmp = (IFM_FDX & *media);
146
147    switch (IFM_SUBTYPE (*media)) {
148    default:
149      return ENOTSUP;
150
151    case IFM_AUTO:
152      bmcr = BMCR_AUTOEN | BMCR_STARTNEG;
153      tmp = 0;
154      break;
155
156    case IFM_1000_T:
157      if (!info->has_gmii)
158        return ENOTSUP;
159
160      if (info->mdio_r (phy, uarg, MII_EXTSR, &bmsr2))
161        return EINVAL;
162
163      if (!(bmsr2 & (tmp ? EXTSR_1000TFDX : EXTSR_1000THDX)))
164        return EOPNOTSUPP;
165      bmcr = BMCR_S1000;
166      break;
167
168    case IFM_100_TX:
169      if (!(bmsr & (tmp ? BMSR_100TXFDX : BMSR_100TXHDX)))
170        return EOPNOTSUPP;
171      bmcr = BMCR_S100;
172      break;
173
174    case IFM_10_T:
175      if (!(bmsr & (tmp ? BMSR_10TFDX : BMSR_10THDX)))
176        return EOPNOTSUPP;
177      bmcr = BMCR_S10;
178      break;
179    }
180
181    if (tmp)
182      bmcr |= BMCR_FDX;
183
184    if (info->mdio_w (phy, uarg, MII_BMCR, bmcr))
185      return EINVAL;
186
187    /* TODO: should we adapt advertised capabilites ? */
188
189    break;
190  }
191
192  return 0;
193}
Note: See TracBrowser for help on using the repository browser.