iPXE
mii.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 * 02110-1301, USA.
18 *
19 * You can also choose to distribute this program under the terms of
20 * the Unmodified Binary Distribution Licence (as given in the file
21 * COPYING.UBDL), provided that you have satisfied its requirements.
22 */
23
24FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25FILE_SECBOOT ( PERMITTED );
26
27#include <string.h>
28#include <unistd.h>
29#include <errno.h>
30#include <ipxe/mii.h>
31
32/** @file
33 *
34 * Media Independent Interface
35 *
36 */
37
38/**
39 * Restart autonegotiation
40 *
41 * @v mii MII device
42 * @ret rc Return status code
43 */
44int mii_restart ( struct mii_device *mii ) {
45 int bmcr;
46 int rc;
47
48 /* Read BMCR */
49 bmcr = mii_read ( mii, MII_BMCR );
50 if ( bmcr < 0 ) {
51 rc = bmcr;
52 DBGC ( mii, "MII %p could not read BMCR: %s\n",
53 mii, strerror ( rc ) );
54 return rc;
55 }
56
57 /* Enable and restart autonegotiation */
58 bmcr |= ( BMCR_ANENABLE | BMCR_ANRESTART );
59 if ( ( rc = mii_write ( mii, MII_BMCR, bmcr ) ) != 0 ) {
60 DBGC ( mii, "MII %p could not write BMCR: %s\n",
61 mii, strerror ( rc ) );
62 return rc;
63 }
64
65 DBGC ( mii, "MII %p restarted autonegotiation\n", mii );
66 return 0;
67}
68
69/**
70 * Reset MII device
71 *
72 * @v mii MII device
73 * @ret rc Return status code
74 */
75int mii_reset ( struct mii_device *mii ) {
76 unsigned int i;
77 int bmcr;
78 int rc;
79
80 /* Power-up, enable autonegotiation and initiate reset */
81 if ( ( rc = mii_write ( mii, MII_BMCR,
82 ( BMCR_RESET | BMCR_ANENABLE ) ) ) != 0 ) {
83 DBGC ( mii, "MII %p could not write BMCR: %s\n",
84 mii, strerror ( rc ) );
85 return rc;
86 }
87
88 /* Wait for reset to complete */
89 for ( i = 0 ; i < MII_RESET_MAX_WAIT_MS ; i++ ) {
90
91 /* Check if reset has completed */
92 bmcr = mii_read ( mii, MII_BMCR );
93 if ( bmcr < 0 ) {
94 rc = bmcr;
95 DBGC ( mii, "MII %p could not read BMCR: %s\n",
96 mii, strerror ( rc ) );
97 return rc;
98 }
99
100 /* If reset is not complete, delay 1ms and retry */
101 if ( bmcr & BMCR_RESET ) {
102 mdelay ( 1 );
103 continue;
104 }
105
106 /* Force autonegotation on again, in case it was
107 * cleared by the reset.
108 */
109 if ( ( rc = mii_restart ( mii ) ) != 0 )
110 return rc;
111
112 DBGC ( mii, "MII %p reset after %dms\n", mii, i );
113 return 0;
114 }
115
116 DBGC ( mii, "MII %p timed out waiting for reset\n", mii );
117 return -ETIMEDOUT;
118}
119
120/**
121 * Update link status via MII
122 *
123 * @v mii MII device
124 * @v netdev Network device
125 * @ret rc Return status code
126 */
128 int bmsr;
129 int link;
130 int rc;
131
132 /* Read BMSR */
133 bmsr = mii_read ( mii, MII_BMSR );
134 if ( bmsr < 0 ) {
135 rc = bmsr;
136 return rc;
137 }
138
139 /* Report link status */
140 link = ( bmsr & BMSR_LSTATUS );
141 DBGC ( mii, "MII %p link %s (BMSR %#04x)\n",
142 mii, ( link ? "up" : "down" ), bmsr );
143 if ( link ) {
145 } else {
147 }
148
149 return 0;
150}
151
152/**
153 * Find PHY address
154 *
155 * @v mii MII device
156 * @ret rc Return status code
157 */
158int mii_find ( struct mii_device *mii ) {
159 unsigned int address;
160 int id;
161
162 /* Try all possible PHY addresses */
163 for ( address = 0 ; address <= MII_MAX_PHY_ADDRESS ; address++ ) {
164 mii->address = address;
165 id = mii_read ( mii, MII_PHYSID1 );
166 if ( ( id > 0x0000 ) && ( id < 0xffff ) ) {
167 DBGC ( mii, "MII %p found PHY at address %d\n",
168 mii, address );
169 return 0;
170 }
171 }
172
173 DBGC ( mii, "MII %p failed to find an address\n", mii );
174 return -ENOENT;
175}
u32 link
Link to next descriptor.
Definition ar9003_mac.h:1
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
#define MII_BMCR
Definition atl1e.h:871
#define MII_BMSR
Definition atl1e.h:872
#define MII_PHYSID1
Definition atl1e.h:873
uint8_t id
Request identifier.
Definition ena.h:1
uint64_t address
Base address.
Definition ena.h:13
static int mii_read(int phy_id, int location)
Definition epic100.c:500
Error codes.
static struct net_device * netdev
Definition gdbudp.c:53
#define DBGC(...)
Definition compiler.h:505
#define FILE_LICENCE(_licence)
Declare a particular licence as applying to a file.
Definition compiler.h:896
#define ENOENT
No such file or directory.
Definition errno.h:515
#define ETIMEDOUT
Connection timed out.
Definition errno.h:670
#define FILE_SECBOOT(_status)
Declare a file's UEFI Secure Boot permission status.
Definition compiler.h:926
String functions.
Media Independent Interface.
static int mii_write(struct mii_device *mii, unsigned int reg, unsigned int data)
Write to MII register.
Definition mii.h:105
#define MII_RESET_MAX_WAIT_MS
Maximum time to wait for a reset, in milliseconds.
Definition mii.h:143
#define MII_MAX_PHY_ADDRESS
Maximum PHY address.
Definition mii.h:146
int mii_reset(struct mii_device *mii)
Reset MII device.
Definition mii.c:75
int mii_restart(struct mii_device *mii)
Restart autonegotiation.
Definition mii.c:44
int mii_check_link(struct mii_device *mii, struct net_device *netdev)
Update link status via MII.
Definition mii.c:127
int mii_find(struct mii_device *mii)
Find PHY address.
Definition mii.c:158
#define BMCR_RESET
Definition mii.h:53
#define BMCR_ANRESTART
Definition mii.h:47
#define BMCR_ANENABLE
Definition mii.h:50
#define BMSR_LSTATUS
Definition mii.h:58
void netdev_link_down(struct net_device *netdev)
Mark network device as having link down.
Definition netdevice.c:231
static void netdev_link_up(struct net_device *netdev)
Mark network device as having link up.
Definition netdevice.h:789
static struct mii_phy mii
char * strerror(int errno)
Retrieve string representation of error number.
Definition strerror.c:79
An MII device.
Definition mii.h:50
A network device.
Definition netdevice.h:353
void mdelay(unsigned long msecs)
Delay for a fixed number of milliseconds.
Definition timer.c:79