summaryrefslogtreecommitdiffstats
path: root/qemu/roms/ipxe/src/drivers/net/smsc75xx.h
blob: 2463b72a1b0fbd91b4678071ed6bda55b9a101b0 (plain)
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
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
#ifndef _SMSC75XX_H
#define _SMSC75XX_H

/** @file
 *
 * SMSC LAN75xx USB Ethernet driver
 *
 */

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );

#include <ipxe/usb.h>
#include <ipxe/usbnet.h>
#include <ipxe/if_ether.h>
#include <ipxe/mii.h>

/** Register write command */
#define SMSC75XX_REGISTER_WRITE					\
	( USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE |	\
	  USB_REQUEST_TYPE ( 0xa0 ) )

/** Register read command */
#define SMSC75XX_REGISTER_READ					\
	( USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE |	\
	  USB_REQUEST_TYPE ( 0xa1 ) )

/** Get statistics command */
#define SMSC75XX_GET_STATISTICS					\
	( USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE |	\
	  USB_REQUEST_TYPE ( 0xa2 ) )

/** Interrupt status register */
#define SMSC75XX_INT_STS 0x00c
#define SMSC75XX_INT_STS_RDFO_INT	0x00400000UL	/**< RX FIFO overflow */
#define SMSC75XX_INT_STS_PHY_INT	0x00020000UL	/**< PHY interrupt */

/** Hardware configuration register */
#define SMSC75XX_HW_CFG 0x010
#define SMSC75XX_HW_CFG_BIR		0x00000080UL	/**< Bulk IN use NAK */
#define SMSC75XX_HW_CFG_LRST		0x00000002UL	/**< Soft lite reset */

/** Interrupt endpoint control register */
#define SMSC75XX_INT_EP_CTL 0x038
#define SMSC75XX_INT_EP_CTL_RDFO_EN	0x00400000UL	/**< RX FIFO overflow */
#define SMSC75XX_INT_EP_CTL_PHY_EN	0x00020000UL	/**< PHY interrupt */

/** Bulk IN delay register */
#define SMSC75XX_BULK_IN_DLY 0x03c
#define SMSC75XX_BULK_IN_DLY_SET(ticks)	( (ticks) << 0 ) /**< Delay / 16.7ns */

/** EEPROM command register */
#define SMSC75XX_E2P_CMD 0x040
#define SMSC75XX_E2P_CMD_EPC_BSY	0x80000000UL	/**< EPC busy */
#define SMSC75XX_E2P_CMD_EPC_CMD_READ	0x00000000UL	/**< READ command */
#define SMSC75XX_E2P_CMD_EPC_ADDR(addr) ( (addr) << 0 )	/**< EPC address */

/** EEPROM data register */
#define SMSC75XX_E2P_DATA 0x044
#define SMSC75XX_E2P_DATA_GET(e2p_data) \
	( ( (e2p_data) >> 0 ) & 0xff )			/**< EEPROM data */

/** MAC address EEPROM address */
#define SMSC75XX_EEPROM_MAC 0x01

/** Receive filtering engine control register */
#define SMSC75XX_RFE_CTL 0x060
#define SMSC75XX_RFE_CTL_AB		0x00000400UL	/**< Accept broadcast */
#define SMSC75XX_RFE_CTL_AM		0x00000200UL	/**< Accept multicast */
#define SMSC75XX_RFE_CTL_AU		0x00000100UL	/**< Accept unicast */

/** FIFO controller RX FIFO control register */
#define SMSC75XX_FCT_RX_CTL 0x090
#define SMSC75XX_FCT_RX_CTL_EN		0x80000000UL	/**< FCT RX enable */
#define SMSC75XX_FCT_RX_CTL_BAD		0x02000000UL	/**< Store bad frames */

/** FIFO controller TX FIFO control register */
#define SMSC75XX_FCT_TX_CTL 0x094
#define SMSC75XX_FCT_TX_CTL_EN		0x80000000UL	/**< FCT TX enable */

/** MAC receive register */
#define SMSC75XX_MAC_RX 0x104
#define SMSC75XX_MAC_RX_MAX_SIZE(mtu)	( (mtu) << 16 )	/**< Max frame size */
#define SMSC75XX_MAC_RX_MAX_SIZE_DEFAULT \
	SMSC75XX_MAC_RX_MAX_SIZE ( ETH_FRAME_LEN + 4 /* VLAN */ + 4 /* CRC */ )
#define SMSC75XX_MAC_RX_FCS		0x00000010UL	/**< FCS stripping */
#define SMSC75XX_MAC_RX_EN		0x00000001UL	/**< RX enable */

/** MAC transmit register */
#define SMSC75XX_MAC_TX 0x108
#define SMSC75XX_MAC_TX_EN		0x00000001UL	/**< TX enable */

/** MAC receive address high register */
#define SMSC75XX_RX_ADDRH 0x118

/** MAC receive address low register */
#define SMSC75XX_RX_ADDRL 0x11c

/** MII access register */
#define SMSC75XX_MII_ACCESS 0x120
#define SMSC75XX_MII_ACCESS_PHY_ADDRESS	0x00000800UL	/**< PHY address */
#define SMSC75XX_MII_ACCESS_MIIRINDA(addr) ( (addr) << 6 ) /**< MII register */
#define SMSC75XX_MII_ACCESS_MIIWNR	0x00000002UL	/**< MII write */
#define SMSC75XX_MII_ACCESS_MIIBZY	0x00000001UL	/**< MII busy */

/** MII data register */
#define SMSC75XX_MII_DATA 0x124
#define SMSC75XX_MII_DATA_SET(data)	( (data) << 0 )	/**< Set data */
#define SMSC75XX_MII_DATA_GET(mii_data) \
	( ( (mii_data) >> 0 ) & 0xffff )		/**< Get data */

/** PHY interrupt source MII register */
#define SMSC75XX_MII_PHY_INTR_SOURCE 29

/** PHY interrupt mask MII register */
#define SMSC75XX_MII_PHY_INTR_MASK 30

/** PHY interrupt: auto-negotiation complete */
#define SMSC75XX_PHY_INTR_ANEG_DONE	0x0040

/** PHY interrupt: link down */
#define SMSC75XX_PHY_INTR_LINK_DOWN	0x0010

/** MAC address perfect filter N high register */
#define SMSC75XX_ADDR_FILTH(n) ( 0x300 + ( 8 * (n) ) )
#define SMSC75XX_ADDR_FILTH_VALID	0x80000000UL	/**< Address valid */

/** MAC address perfect filter N low register */
#define SMSC75XX_ADDR_FILTL(n) ( 0x304 + ( 8 * (n) ) )

/** MAC address */
union smsc75xx_mac {
	/** MAC receive address registers */
	struct {
		/** MAC receive address low register */
		uint32_t l;
		/** MAC receive address high register */
		uint32_t h;
	} __attribute__ (( packed )) addr;
	/** Raw MAC address */
	uint8_t raw[ETH_ALEN];
};

/** Receive packet header */
struct smsc75xx_rx_header {
	/** RX command word */
	uint32_t command;
	/** VLAN tag */
	uint16_t vtag;
	/** Checksum */
	uint16_t csum;
	/** Two-byte padding used to align Ethernet payload */
	uint16_t pad;
} __attribute__ (( packed ));

/** Receive error detected */
#define SMSC75XX_RX_RED 0x00400000UL

/** Transmit packet header */
struct smsc75xx_tx_header {
	/** TX command word */
	uint32_t command;
	/** VLAN tag */
	uint16_t tag;
	/** Maximum segment size */
	uint16_t mss;
} __attribute__ (( packed ));

/** Insert frame checksum and pad */
#define SMSC75XX_TX_FCS 0x00400000UL

/** Interrupt packet format */
struct smsc75xx_interrupt {
	/** Current value of INT_STS register */
	uint32_t int_sts;
} __attribute__ (( packed ));

/** Byte count statistics */
struct smsc75xx_byte_statistics {
	/** Unicast byte count */
	uint32_t unicast;
	/** Broadcast byte count */
	uint32_t broadcast;
	/** Multicast byte count */
	uint32_t multicast;
} __attribute__ (( packed ));

/** Frame count statistics */
struct smsc75xx_frame_statistics {
	/** Unicast frames */
	uint32_t unicast;
	/** Broadcast frames */
	uint32_t broadcast;
	/** Multicast frames */
	uint32_t multicast;
	/** Pause frames */
	uint32_t pause;
	/** Frames by length category */
	uint32_t len[7];
} __attribute__ (( packed ));

/** Receive error statistics */
struct smsc75xx_rx_error_statistics {
	/** FCS errors */
	uint32_t fcs;
	/** Alignment errors */
	uint32_t alignment;
	/** Fragment errors */
	uint32_t fragment;
	/** Jabber errors */
	uint32_t jabber;
	/** Undersize frame errors */
	uint32_t undersize;
	/** Oversize frame errors */
	uint32_t oversize;
	/** Dropped frame errors */
	uint32_t dropped;
} __attribute__ (( packed ));

/** Receive statistics */
struct smsc75xx_rx_statistics {
	/** Error statistics */
	struct smsc75xx_rx_error_statistics err;
	/** Byte count statistics */
	struct smsc75xx_byte_statistics byte;
	/** Frame count statistics */
	struct smsc75xx_frame_statistics frame;
} __attribute__ (( packed ));

/** Transmit error statistics */
struct smsc75xx_tx_error_statistics {
	/** FCS errors */
	uint32_t fcs;
	/** Excess deferral errors */
	uint32_t deferral;
	/** Carrier errors */
	uint32_t carrier;
	/** Bad byte count */
	uint32_t count;
	/** Single collisions */
	uint32_t single;
	/** Multiple collisions */
	uint32_t multiple;
	/** Excession collisions */
	uint32_t excessive;
	/** Late collisions */
	uint32_t late;
} __attribute__ (( packed ));

/** Transmit statistics */
struct smsc75xx_tx_statistics {
	/** Error statistics */
	struct smsc75xx_tx_error_statistics err;
	/** Byte count statistics */
	struct smsc75xx_byte_statistics byte;
	/** Frame count statistics */
	struct smsc75xx_frame_statistics frame;
} __attribute__ (( packed ));

/** Statistics */
struct smsc75xx_statistics {
	/** Receive statistics */
	struct smsc75xx_rx_statistics rx;
	/** Transmit statistics */
	struct smsc75xx_tx_statistics tx;
} __attribute__ (( packed ));

/** A SMSC75xx network device */
struct smsc75xx_device {
	/** USB device */
	struct usb_device *usb;
	/** USB bus */
	struct usb_bus *bus;
	/** Network device */
	struct net_device *netdev;
	/** USB network device */
	struct usbnet_device usbnet;
	/** MII interface */
	struct mii_interface mii;
	/** Interrupt status */
	uint32_t int_sts;
};

/** Reset delay (in microseconds) */
#define SMSC75XX_RESET_DELAY_US 2

/** Maximum time to wait for EEPROM (in milliseconds) */
#define SMSC75XX_EEPROM_MAX_WAIT_MS 100

/** Maximum time to wait for MII (in milliseconds) */
#define SMSC75XX_MII_MAX_WAIT_MS 100

/** Interrupt maximum fill level
 *
 * This is a policy decision.
 */
#define SMSC75XX_INTR_MAX_FILL 2

/** Bulk IN maximum fill level
 *
 * This is a policy decision.
 */
#define SMSC75XX_IN_MAX_FILL 8

/** Bulk IN buffer size */
#define SMSC75XX_IN_MTU						\
	( sizeof ( struct smsc75xx_rx_header ) +		\
	  ETH_FRAME_LEN + 4 /* possible VLAN header */ )

#endif /* _SMSC75XX_H */