summaryrefslogtreecommitdiffstats
path: root/src/include/ipxe/mii.h
blob: 89fc92a4af4ce349d8ac45993909a51decb2854b (plain) (blame)
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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
#ifndef _IPXE_MII_H
#define _IPXE_MII_H

/** @file
 *
 * Media Independent Interface
 *
 */

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );

#include <mii.h>
#include <ipxe/netdevice.h>

struct mii_interface;

/** MII interface operations */
struct mii_operations {
	/**
	 * Read from MII register
	 *
	 * @v mdio		MII interface
	 * @v phy		PHY address
	 * @v reg		Register address
	 * @ret data		Data read, or negative error
	 */
	int ( * read ) ( struct mii_interface *mdio, unsigned int phy,
			 unsigned int reg );
	/**
	 * Write to MII register
	 *
	 * @v mdio		MII interface
	 * @v phy		PHY address
	 * @v reg		Register address
	 * @v data		Data to write
	 * @ret rc		Return status code
	 */
	int ( * write ) ( struct mii_interface *mdio, unsigned int phy,
			  unsigned int reg, unsigned int data );
};

/** An MII interface */
struct mii_interface {
	/** Interface operations */
	struct mii_operations *op;
};

/** An MII device */
struct mii_device {
	/** MII interface */
	struct mii_interface *mdio;
	/** PHY address */
	unsigned int address;
};

/**
 * Initialise MII interface
 *
 * @v mdio		MII interface
 * @v op		MII interface operations
 */
static inline __attribute__ (( always_inline )) void
mdio_init ( struct mii_interface *mdio, struct mii_operations *op ) {
	mdio->op = op;
}

/**
 * Initialise MII device
 *
 * @v mii		MII device
 * @v mdio		MII interface
 * @v address		PHY address
 */
static inline __attribute__ (( always_inline )) void
mii_init ( struct mii_device *mii, struct mii_interface *mdio,
	   unsigned int address ) {
	mii->mdio = mdio;
	mii->address = address;
}

/**
 * Read from MII register
 *
 * @v mii		MII device
 * @v reg		Register address
 * @ret data		Data read, or negative error
 */
static inline __attribute__ (( always_inline )) int
mii_read ( struct mii_device *mii, unsigned int reg ) {
	struct mii_interface *mdio = mii->mdio;

	return mdio->op->read ( mdio, mii->address, reg );
}

/**
 * Write to MII register
 *
 * @v mii		MII device
 * @v reg		Register address
 * @v data		Data to write
 * @ret rc		Return status code
 */
static inline __attribute__ (( always_inline )) int
mii_write ( struct mii_device *mii, unsigned int reg, unsigned int data ) {
	struct mii_interface *mdio = mii->mdio;

	return mdio->op->write ( mdio, mii->address, reg, data );
}

/**
 * Dump MII registers (for debugging)
 *
 * @v mii		MII device
 */
static inline void
mii_dump ( struct mii_device *mii ) {
	unsigned int i;
	int data;

	/* Do nothing unless debug output is enabled */
	if ( ! DBG_LOG )
		return;

	/* Dump basic MII register set */
	for ( i = 0 ; i < 16 ; i++ ) {
		if ( ( i % 8 ) == 0 ) {
			DBGC ( mii, "MII %p registers %02x-%02x:",
			       mii, i, ( i + 7 ) );
		}
		data = mii_read ( mii, i );
		if ( data >= 0 ) {
			DBGC ( mii, " %04x", data );
		} else {
			DBGC ( mii, " XXXX" );
		}
		if ( ( i % 8 ) == 7 )
			DBGC ( mii, "\n" );
	}
}

/** Maximum time to wait for a reset, in milliseconds */
#define MII_RESET_MAX_WAIT_MS 500

/** Maximum PHY address */
#define MII_MAX_PHY_ADDRESS 31

extern int mii_restart ( struct mii_device *mii );
extern int mii_reset ( struct mii_device *mii );
extern int mii_check_link ( struct mii_device *mii,
			    struct net_device *netdev );
extern int mii_find ( struct mii_device *mii );

#endif /* _IPXE_MII_H */