Blame view

drivers/net/mii.c 12.3 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
  /*
  
  	mii.c: MII interface library
  
  	Maintained by Jeff Garzik <jgarzik@pobox.com>
  	Copyright 2001,2002 Jeff Garzik
  
  	Various code came from myson803.c and other files by
  	Donald Becker.  Copyright:
  
  		Written 1998-2002 by Donald Becker.
  
  		This software may be used and distributed according
  		to the terms of the GNU General Public License (GPL),
  		incorporated herein by reference.  Drivers based on
  		or derived from this code fall under the GPL and must
  		retain the authorship, copyright and license notice.
  		This file is not a complete program and may only be
  		used when the entire operating system is licensed
  		under the GPL.
  
  		The author may be reached as becker@scyld.com, or C/O
  		Scyld Computing Corporation
  		410 Severn Ave., Suite 210
  		Annapolis MD 21403
  
  
   */
  
  #include <linux/kernel.h>
  #include <linux/module.h>
  #include <linux/netdevice.h>
  #include <linux/ethtool.h>
5974700c2   Ben Hutchings   mii: Rewrite mii_...
34
35
36
37
  #include <linux/mdio.h>
  
  static u32 mii_get_an(struct mii_if_info *mii, u16 addr)
  {
5974700c2   Ben Hutchings   mii: Rewrite mii_...
38
39
40
  	int advert;
  
  	advert = mii->mdio_read(mii->dev, mii->phy_id, addr);
28011cf19   Matt Carlson   net: Add ethtool ...
41

37f07023d   Matt Carlson   net: Change mii t...
42
  	return mii_lpa_to_ethtool_lpa_t(advert);
5974700c2   Ben Hutchings   mii: Rewrite mii_...
43
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
44

32684ec61   Randy Dunlap   mii: add kernel-d...
45
46
47
48
49
  /**
   * mii_ethtool_gset - get settings that are specified in @ecmd
   * @mii: MII interface
   * @ecmd: requested ethtool_cmd
   *
8ae6daca8   David Decotigny   ethtool: Call eth...
50
51
52
   * The @ecmd parameter is expected to have been cleared before calling
   * mii_ethtool_gset().
   *
32684ec61   Randy Dunlap   mii: add kernel-d...
53
54
   * Returns 0 for success, negative on error.
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
55
56
57
  int mii_ethtool_gset(struct mii_if_info *mii, struct ethtool_cmd *ecmd)
  {
  	struct net_device *dev = mii->dev;
5974700c2   Ben Hutchings   mii: Rewrite mii_...
58
59
  	u16 bmcr, bmsr, ctrl1000 = 0, stat1000 = 0;
  	u32 nego;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
  
  	ecmd->supported =
  	    (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full |
  	     SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full |
  	     SUPPORTED_Autoneg | SUPPORTED_TP | SUPPORTED_MII);
  	if (mii->supports_gmii)
  		ecmd->supported |= SUPPORTED_1000baseT_Half |
  			SUPPORTED_1000baseT_Full;
  
  	/* only supports twisted-pair */
  	ecmd->port = PORT_MII;
  
  	/* only supports internal transceiver */
  	ecmd->transceiver = XCVR_INTERNAL;
  
  	/* this isn't fully supported at higher layers */
  	ecmd->phy_address = mii->phy_id;
5974700c2   Ben Hutchings   mii: Rewrite mii_...
77
  	ecmd->mdio_support = MDIO_SUPPORTS_C22;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
78
79
  
  	ecmd->advertising = ADVERTISED_TP | ADVERTISED_MII;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
80
81
  
  	bmcr = mii->mdio_read(dev, mii->phy_id, MII_BMCR);
5974700c2   Ben Hutchings   mii: Rewrite mii_...
82
  	bmsr = mii->mdio_read(dev, mii->phy_id, MII_BMSR);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
83
  	if (mii->supports_gmii) {
5974700c2   Ben Hutchings   mii: Rewrite mii_...
84
85
   		ctrl1000 = mii->mdio_read(dev, mii->phy_id, MII_CTRL1000);
  		stat1000 = mii->mdio_read(dev, mii->phy_id, MII_STAT1000);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
86
87
88
89
  	}
  	if (bmcr & BMCR_ANENABLE) {
  		ecmd->advertising |= ADVERTISED_Autoneg;
  		ecmd->autoneg = AUTONEG_ENABLE;
6aa20a223   Jeff Garzik   drivers/net: Trim...
90

5974700c2   Ben Hutchings   mii: Rewrite mii_...
91
  		ecmd->advertising |= mii_get_an(mii, MII_ADVERTISE);
28011cf19   Matt Carlson   net: Add ethtool ...
92
  		if (mii->supports_gmii)
37f07023d   Matt Carlson   net: Change mii t...
93
94
  			ecmd->advertising |=
  					mii_ctrl1000_to_ethtool_adv_t(ctrl1000);
5974700c2   Ben Hutchings   mii: Rewrite mii_...
95
96
97
  
  		if (bmsr & BMSR_ANEGCOMPLETE) {
  			ecmd->lp_advertising = mii_get_an(mii, MII_LPA);
28011cf19   Matt Carlson   net: Add ethtool ...
98
  			ecmd->lp_advertising |=
37f07023d   Matt Carlson   net: Change mii t...
99
  					mii_stat1000_to_ethtool_lpa_t(stat1000);
5974700c2   Ben Hutchings   mii: Rewrite mii_...
100
101
102
103
104
105
106
107
  		} else {
  			ecmd->lp_advertising = 0;
  		}
  
  		nego = ecmd->advertising & ecmd->lp_advertising;
  
  		if (nego & (ADVERTISED_1000baseT_Full |
  			    ADVERTISED_1000baseT_Half)) {
707394972   David Decotigny   ethtool: cosmetic...
108
  			ethtool_cmd_speed_set(ecmd, SPEED_1000);
5974700c2   Ben Hutchings   mii: Rewrite mii_...
109
110
111
  			ecmd->duplex = !!(nego & ADVERTISED_1000baseT_Full);
  		} else if (nego & (ADVERTISED_100baseT_Full |
  				   ADVERTISED_100baseT_Half)) {
707394972   David Decotigny   ethtool: cosmetic...
112
  			ethtool_cmd_speed_set(ecmd, SPEED_100);
5974700c2   Ben Hutchings   mii: Rewrite mii_...
113
  			ecmd->duplex = !!(nego & ADVERTISED_100baseT_Full);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
114
  		} else {
707394972   David Decotigny   ethtool: cosmetic...
115
  			ethtool_cmd_speed_set(ecmd, SPEED_10);
5974700c2   Ben Hutchings   mii: Rewrite mii_...
116
  			ecmd->duplex = !!(nego & ADVERTISED_10baseT_Full);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
117
118
119
  		}
  	} else {
  		ecmd->autoneg = AUTONEG_DISABLE;
707394972   David Decotigny   ethtool: cosmetic...
120
121
122
123
124
125
  		ethtool_cmd_speed_set(ecmd,
  				      ((bmcr & BMCR_SPEED1000 &&
  					(bmcr & BMCR_SPEED100) == 0) ?
  				       SPEED_1000 :
  				       ((bmcr & BMCR_SPEED100) ?
  					SPEED_100 : SPEED_10)));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
126
127
  		ecmd->duplex = (bmcr & BMCR_FULLDPLX) ? DUPLEX_FULL : DUPLEX_HALF;
  	}
5974700c2   Ben Hutchings   mii: Rewrite mii_...
128
  	mii->full_duplex = ecmd->duplex;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
129
130
131
132
  	/* ignore maxtxpkt, maxrxpkt for now */
  
  	return 0;
  }
32684ec61   Randy Dunlap   mii: add kernel-d...
133
134
135
136
137
138
139
  /**
   * mii_ethtool_sset - set settings that are specified in @ecmd
   * @mii: MII interface
   * @ecmd: requested ethtool_cmd
   *
   * Returns 0 for success, negative on error.
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
140
141
142
  int mii_ethtool_sset(struct mii_if_info *mii, struct ethtool_cmd *ecmd)
  {
  	struct net_device *dev = mii->dev;
25db03388   David Decotigny   ethtool: Use full...
143
  	u32 speed = ethtool_cmd_speed(ecmd);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
144

25db03388   David Decotigny   ethtool: Use full...
145
146
147
  	if (speed != SPEED_10 &&
  	    speed != SPEED_100 &&
  	    speed != SPEED_1000)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
148
149
150
151
152
153
154
155
156
157
158
  		return -EINVAL;
  	if (ecmd->duplex != DUPLEX_HALF && ecmd->duplex != DUPLEX_FULL)
  		return -EINVAL;
  	if (ecmd->port != PORT_MII)
  		return -EINVAL;
  	if (ecmd->transceiver != XCVR_INTERNAL)
  		return -EINVAL;
  	if (ecmd->phy_address != mii->phy_id)
  		return -EINVAL;
  	if (ecmd->autoneg != AUTONEG_DISABLE && ecmd->autoneg != AUTONEG_ENABLE)
  		return -EINVAL;
25db03388   David Decotigny   ethtool: Use full...
159
  	if ((speed == SPEED_1000) && (!mii->supports_gmii))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
160
  		return -EINVAL;
6aa20a223   Jeff Garzik   drivers/net: Trim...
161

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
162
  	/* ignore supported, maxtxpkt, maxrxpkt */
6aa20a223   Jeff Garzik   drivers/net: Trim...
163

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
  	if (ecmd->autoneg == AUTONEG_ENABLE) {
  		u32 bmcr, advert, tmp;
  		u32 advert2 = 0, tmp2 = 0;
  
  		if ((ecmd->advertising & (ADVERTISED_10baseT_Half |
  					  ADVERTISED_10baseT_Full |
  					  ADVERTISED_100baseT_Half |
  					  ADVERTISED_100baseT_Full |
  					  ADVERTISED_1000baseT_Half |
  					  ADVERTISED_1000baseT_Full)) == 0)
  			return -EINVAL;
  
  		/* advertise only what has been requested */
  		advert = mii->mdio_read(dev, mii->phy_id, MII_ADVERTISE);
  		tmp = advert & ~(ADVERTISE_ALL | ADVERTISE_100BASE4);
  		if (mii->supports_gmii) {
  			advert2 = mii->mdio_read(dev, mii->phy_id, MII_CTRL1000);
  			tmp2 = advert2 & ~(ADVERTISE_1000HALF | ADVERTISE_1000FULL);
  		}
37f07023d   Matt Carlson   net: Change mii t...
183
  		tmp |= ethtool_adv_to_mii_adv_t(ecmd->advertising);
28011cf19   Matt Carlson   net: Add ethtool ...
184
185
  
  		if (mii->supports_gmii)
37f07023d   Matt Carlson   net: Change mii t...
186
187
  			tmp2 |=
  			      ethtool_adv_to_mii_ctrl1000_t(ecmd->advertising);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
188
189
190
191
192
193
  		if (advert != tmp) {
  			mii->mdio_write(dev, mii->phy_id, MII_ADVERTISE, tmp);
  			mii->advertising = tmp;
  		}
  		if ((mii->supports_gmii) && (advert2 != tmp2))
  			mii->mdio_write(dev, mii->phy_id, MII_CTRL1000, tmp2);
6aa20a223   Jeff Garzik   drivers/net: Trim...
194

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
195
196
197
198
199
200
201
202
203
204
205
  		/* turn on autonegotiation, and force a renegotiate */
  		bmcr = mii->mdio_read(dev, mii->phy_id, MII_BMCR);
  		bmcr |= (BMCR_ANENABLE | BMCR_ANRESTART);
  		mii->mdio_write(dev, mii->phy_id, MII_BMCR, bmcr);
  
  		mii->force_media = 0;
  	} else {
  		u32 bmcr, tmp;
  
  		/* turn off auto negotiation, set speed and duplexity */
  		bmcr = mii->mdio_read(dev, mii->phy_id, MII_BMCR);
6aa20a223   Jeff Garzik   drivers/net: Trim...
206
  		tmp = bmcr & ~(BMCR_ANENABLE | BMCR_SPEED100 |
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
207
  			       BMCR_SPEED1000 | BMCR_FULLDPLX);
25db03388   David Decotigny   ethtool: Use full...
208
  		if (speed == SPEED_1000)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
209
  			tmp |= BMCR_SPEED1000;
25db03388   David Decotigny   ethtool: Use full...
210
  		else if (speed == SPEED_100)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
211
212
213
214
215
216
217
218
219
220
221
222
223
  			tmp |= BMCR_SPEED100;
  		if (ecmd->duplex == DUPLEX_FULL) {
  			tmp |= BMCR_FULLDPLX;
  			mii->full_duplex = 1;
  		} else
  			mii->full_duplex = 0;
  		if (bmcr != tmp)
  			mii->mdio_write(dev, mii->phy_id, MII_BMCR, tmp);
  
  		mii->force_media = 1;
  	}
  	return 0;
  }
32684ec61   Randy Dunlap   mii: add kernel-d...
224
225
226
227
  /**
   * mii_check_gmii_support - check if the MII supports Gb interfaces
   * @mii: the MII interface
   */
43ec6e95e   Dale Farnsworth   [PATCH] mii: Add ...
228
229
230
231
232
233
234
235
236
237
238
239
240
  int mii_check_gmii_support(struct mii_if_info *mii)
  {
  	int reg;
  
  	reg = mii->mdio_read(mii->dev, mii->phy_id, MII_BMSR);
  	if (reg & BMSR_ESTATEN) {
  		reg = mii->mdio_read(mii->dev, mii->phy_id, MII_ESTATUS);
  		if (reg & (ESTATUS_1000_TFULL | ESTATUS_1000_THALF))
  			return 1;
  	}
  
  	return 0;
  }
32684ec61   Randy Dunlap   mii: add kernel-d...
241
242
243
244
245
246
  /**
   * mii_link_ok - is link status up/ok
   * @mii: the MII interface
   *
   * Returns 1 if the MII reports link status up/ok, 0 otherwise.
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
247
248
249
250
251
252
253
254
  int mii_link_ok (struct mii_if_info *mii)
  {
  	/* first, a dummy read, needed to latch some MII phys */
  	mii->mdio_read(mii->dev, mii->phy_id, MII_BMSR);
  	if (mii->mdio_read(mii->dev, mii->phy_id, MII_BMSR) & BMSR_LSTATUS)
  		return 1;
  	return 0;
  }
32684ec61   Randy Dunlap   mii: add kernel-d...
255
256
257
258
259
260
  /**
   * mii_nway_restart - restart NWay (autonegotiation) for this interface
   * @mii: the MII interface
   *
   * Returns 0 on success, negative on error.
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
  int mii_nway_restart (struct mii_if_info *mii)
  {
  	int bmcr;
  	int r = -EINVAL;
  
  	/* if autoneg is off, it's an error */
  	bmcr = mii->mdio_read(mii->dev, mii->phy_id, MII_BMCR);
  
  	if (bmcr & BMCR_ANENABLE) {
  		bmcr |= BMCR_ANRESTART;
  		mii->mdio_write(mii->dev, mii->phy_id, MII_BMCR, bmcr);
  		r = 0;
  	}
  
  	return r;
  }
32684ec61   Randy Dunlap   mii: add kernel-d...
277
278
279
280
281
282
283
284
  /**
   * mii_check_link - check MII link status
   * @mii: MII interface
   *
   * If the link status changed (previous != current), call
   * netif_carrier_on() if current link status is Up or call
   * netif_carrier_off() if current link status is Down.
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
285
286
287
288
289
290
291
292
293
294
  void mii_check_link (struct mii_if_info *mii)
  {
  	int cur_link = mii_link_ok(mii);
  	int prev_link = netif_carrier_ok(mii->dev);
  
  	if (cur_link && !prev_link)
  		netif_carrier_on(mii->dev);
  	else if (prev_link && !cur_link)
  		netif_carrier_off(mii->dev);
  }
32684ec61   Randy Dunlap   mii: add kernel-d...
295
296
297
298
299
300
301
302
303
  /**
   * mii_check_media - check the MII interface for a duplex change
   * @mii: the MII interface
   * @ok_to_print: OK to print link up/down messages
   * @init_media: OK to save duplex mode in @mii
   *
   * Returns 1 if the duplex mode changed, 0 if not.
   * If the media type is forced, always returns 0.
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
  unsigned int mii_check_media (struct mii_if_info *mii,
  			      unsigned int ok_to_print,
  			      unsigned int init_media)
  {
  	unsigned int old_carrier, new_carrier;
  	int advertise, lpa, media, duplex;
  	int lpa2 = 0;
  
  	/* if forced media, go no further */
  	if (mii->force_media)
  		return 0; /* duplex did not change */
  
  	/* check current and old link status */
  	old_carrier = netif_carrier_ok(mii->dev) ? 1 : 0;
  	new_carrier = (unsigned int) mii_link_ok(mii);
  
  	/* if carrier state did not change, this is a "bounce",
  	 * just exit as everything is already set correctly
  	 */
  	if ((!init_media) && (old_carrier == new_carrier))
  		return 0; /* duplex did not change */
  
  	/* no carrier, nothing much to do */
  	if (!new_carrier) {
  		netif_carrier_off(mii->dev);
  		if (ok_to_print)
967faf3b7   Joe Perches   mii: Convert prin...
330
331
  			netdev_info(mii->dev, "link down
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
  		return 0; /* duplex did not change */
  	}
  
  	/*
  	 * we have carrier, see who's on the other end
  	 */
  	netif_carrier_on(mii->dev);
  
  	/* get MII advertise and LPA values */
  	if ((!init_media) && (mii->advertising))
  		advertise = mii->advertising;
  	else {
  		advertise = mii->mdio_read(mii->dev, mii->phy_id, MII_ADVERTISE);
  		mii->advertising = advertise;
  	}
  	lpa = mii->mdio_read(mii->dev, mii->phy_id, MII_LPA);
  	if (mii->supports_gmii)
  		lpa2 = mii->mdio_read(mii->dev, mii->phy_id, MII_STAT1000);
  
  	/* figure out media and duplex from advertise and LPA values */
  	media = mii_nway_result(lpa & advertise);
  	duplex = (media & ADVERTISE_FULL) ? 1 : 0;
  	if (lpa2 & LPA_1000FULL)
  		duplex = 1;
  
  	if (ok_to_print)
967faf3b7   Joe Perches   mii: Convert prin...
358
359
360
361
362
363
364
  		netdev_info(mii->dev, "link up, %uMbps, %s-duplex, lpa 0x%04X
  ",
  			    lpa2 & (LPA_1000FULL | LPA_1000HALF) ? 1000 :
  			    media & (ADVERTISE_100FULL | ADVERTISE_100HALF) ?
  			    100 : 10,
  			    duplex ? "full" : "half",
  			    lpa);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
365
366
367
368
369
370
371
372
  
  	if ((init_media) || (mii->full_duplex != duplex)) {
  		mii->full_duplex = duplex;
  		return 1; /* duplex changed */
  	}
  
  	return 0; /* duplex did not change */
  }
32684ec61   Randy Dunlap   mii: add kernel-d...
373
374
375
376
377
378
379
380
381
382
  /**
   * generic_mii_ioctl - main MII ioctl interface
   * @mii_if: the MII interface
   * @mii_data: MII ioctl data structure
   * @cmd: MII ioctl command
   * @duplex_chg_out: pointer to @duplex_changed status if there was no
   *	ioctl error
   *
   * Returns 0 on success, negative on error.
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
  int generic_mii_ioctl(struct mii_if_info *mii_if,
  		      struct mii_ioctl_data *mii_data, int cmd,
  		      unsigned int *duplex_chg_out)
  {
  	int rc = 0;
  	unsigned int duplex_changed = 0;
  
  	if (duplex_chg_out)
  		*duplex_chg_out = 0;
  
  	mii_data->phy_id &= mii_if->phy_id_mask;
  	mii_data->reg_num &= mii_if->reg_num_mask;
  
  	switch(cmd) {
  	case SIOCGMIIPHY:
  		mii_data->phy_id = mii_if->phy_id;
  		/* fall through */
  
  	case SIOCGMIIREG:
  		mii_data->val_out =
  			mii_if->mdio_read(mii_if->dev, mii_data->phy_id,
  					  mii_data->reg_num);
  		break;
  
  	case SIOCSMIIREG: {
  		u16 val = mii_data->val_in;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
  		if (mii_data->phy_id == mii_if->phy_id) {
  			switch(mii_data->reg_num) {
  			case MII_BMCR: {
  				unsigned int new_duplex = 0;
  				if (val & (BMCR_RESET|BMCR_ANENABLE))
  					mii_if->force_media = 0;
  				else
  					mii_if->force_media = 1;
  				if (mii_if->force_media &&
  				    (val & BMCR_FULLDPLX))
  					new_duplex = 1;
  				if (mii_if->full_duplex != new_duplex) {
  					duplex_changed = 1;
  					mii_if->full_duplex = new_duplex;
  				}
  				break;
  			}
  			case MII_ADVERTISE:
  				mii_if->advertising = val;
  				break;
  			default:
  				/* do nothing */
  				break;
  			}
  		}
  
  		mii_if->mdio_write(mii_if->dev, mii_data->phy_id,
  				   mii_data->reg_num, val);
  		break;
  	}
  
  	default:
  		rc = -EOPNOTSUPP;
  		break;
  	}
  
  	if ((rc == 0) && (duplex_chg_out) && (duplex_changed))
  		*duplex_chg_out = 1;
  
  	return rc;
  }
  
  MODULE_AUTHOR ("Jeff Garzik <jgarzik@pobox.com>");
  MODULE_DESCRIPTION ("MII hardware support library");
  MODULE_LICENSE("GPL");
  
  EXPORT_SYMBOL(mii_link_ok);
  EXPORT_SYMBOL(mii_nway_restart);
  EXPORT_SYMBOL(mii_ethtool_gset);
  EXPORT_SYMBOL(mii_ethtool_sset);
  EXPORT_SYMBOL(mii_check_link);
  EXPORT_SYMBOL(mii_check_media);
43ec6e95e   Dale Farnsworth   [PATCH] mii: Add ...
461
  EXPORT_SYMBOL(mii_check_gmii_support);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
462
  EXPORT_SYMBOL(generic_mii_ioctl);