|
@@ -0,0 +1,310 @@
|
|
1
|
+
|
|
2
|
+#ifndef __SIS190_H__
|
|
3
|
+#define __SIS190_H__
|
|
4
|
+
|
|
5
|
+#include <stdint.h>
|
|
6
|
+#include <stdio.h>
|
|
7
|
+#include <stdlib.h>
|
|
8
|
+#include <stddef.h>
|
|
9
|
+#include <string.h>
|
|
10
|
+#include <unistd.h>
|
|
11
|
+#include <assert.h>
|
|
12
|
+#include <byteswap.h>
|
|
13
|
+#include <errno.h>
|
|
14
|
+#include <mii.h>
|
|
15
|
+#include <gpxe/ethernet.h>
|
|
16
|
+#include <gpxe/if_ether.h>
|
|
17
|
+#include <gpxe/io.h>
|
|
18
|
+#include <gpxe/iobuf.h>
|
|
19
|
+#include <gpxe/malloc.h>
|
|
20
|
+#include <gpxe/netdevice.h>
|
|
21
|
+#include <gpxe/pci.h>
|
|
22
|
+#include <gpxe/timer.h>
|
|
23
|
+
|
|
24
|
+#define PCI_VENDOR_ID_SI 0x1039
|
|
25
|
+
|
|
26
|
+#define PHY_MAX_ADDR 32
|
|
27
|
+#define PHY_ID_ANY 0x1f
|
|
28
|
+#define MII_REG_ANY 0x1f
|
|
29
|
+
|
|
30
|
+#define DRV_VERSION "1.3"
|
|
31
|
+#define DRV_NAME "sis190"
|
|
32
|
+#define SIS190_DRIVER_NAME DRV_NAME " Gigabit Ethernet driver " DRV_VERSION
|
|
33
|
+#define PFX DRV_NAME ": "
|
|
34
|
+
|
|
35
|
+#define sis190_rx_quota(count, quota) count
|
|
36
|
+
|
|
37
|
+#define NUM_TX_DESC 8 /* [8..1024] */
|
|
38
|
+#define NUM_RX_DESC 8 /* [8..8192] */
|
|
39
|
+#define TX_RING_BYTES (NUM_TX_DESC * sizeof(struct TxDesc))
|
|
40
|
+#define RX_RING_BYTES (NUM_RX_DESC * sizeof(struct RxDesc))
|
|
41
|
+#define RX_BUF_SIZE 1536
|
|
42
|
+#define RX_BUF_MASK 0xfff8
|
|
43
|
+
|
|
44
|
+#define RING_ALIGNMENT 256
|
|
45
|
+
|
|
46
|
+#define SIS190_REGS_SIZE 0x80
|
|
47
|
+
|
|
48
|
+/* Enhanced PHY access register bit definitions */
|
|
49
|
+#define EhnMIIread 0x0000
|
|
50
|
+#define EhnMIIwrite 0x0020
|
|
51
|
+#define EhnMIIdataShift 16
|
|
52
|
+#define EhnMIIpmdShift 6 /* 7016 only */
|
|
53
|
+#define EhnMIIregShift 11
|
|
54
|
+#define EhnMIIreq 0x0010
|
|
55
|
+#define EhnMIInotDone 0x0010
|
|
56
|
+
|
|
57
|
+/* Write/read MMIO register */
|
|
58
|
+#define SIS_W8(reg, val) writeb ((val), ioaddr + (reg))
|
|
59
|
+#define SIS_W16(reg, val) writew ((val), ioaddr + (reg))
|
|
60
|
+#define SIS_W32(reg, val) writel ((val), ioaddr + (reg))
|
|
61
|
+#define SIS_R8(reg) readb (ioaddr + (reg))
|
|
62
|
+#define SIS_R16(reg) readw (ioaddr + (reg))
|
|
63
|
+#define SIS_R32(reg) readl (ioaddr + (reg))
|
|
64
|
+
|
|
65
|
+#define SIS_PCI_COMMIT() SIS_R32(IntrControl)
|
|
66
|
+
|
|
67
|
+enum sis190_registers {
|
|
68
|
+ TxControl = 0x00,
|
|
69
|
+ TxDescStartAddr = 0x04,
|
|
70
|
+ rsv0 = 0x08, // reserved
|
|
71
|
+ TxSts = 0x0c, // unused (Control/Status)
|
|
72
|
+ RxControl = 0x10,
|
|
73
|
+ RxDescStartAddr = 0x14,
|
|
74
|
+ rsv1 = 0x18, // reserved
|
|
75
|
+ RxSts = 0x1c, // unused
|
|
76
|
+ IntrStatus = 0x20,
|
|
77
|
+ IntrMask = 0x24,
|
|
78
|
+ IntrControl = 0x28,
|
|
79
|
+ IntrTimer = 0x2c, // unused (Interupt Timer)
|
|
80
|
+ PMControl = 0x30, // unused (Power Mgmt Control/Status)
|
|
81
|
+ rsv2 = 0x34, // reserved
|
|
82
|
+ ROMControl = 0x38,
|
|
83
|
+ ROMInterface = 0x3c,
|
|
84
|
+ StationControl = 0x40,
|
|
85
|
+ GMIIControl = 0x44,
|
|
86
|
+ GIoCR = 0x48, // unused (GMAC IO Compensation)
|
|
87
|
+ GIoCtrl = 0x4c, // unused (GMAC IO Control)
|
|
88
|
+ TxMacControl = 0x50,
|
|
89
|
+ TxLimit = 0x54, // unused (Tx MAC Timer/TryLimit)
|
|
90
|
+ RGDelay = 0x58, // unused (RGMII Tx Internal Delay)
|
|
91
|
+ rsv3 = 0x5c, // reserved
|
|
92
|
+ RxMacControl = 0x60,
|
|
93
|
+ RxMacAddr = 0x62,
|
|
94
|
+ RxHashTable = 0x68,
|
|
95
|
+ // Undocumented = 0x6c,
|
|
96
|
+ RxWolCtrl = 0x70,
|
|
97
|
+ RxWolData = 0x74, // unused (Rx WOL Data Access)
|
|
98
|
+ RxMPSControl = 0x78, // unused (Rx MPS Control)
|
|
99
|
+ rsv4 = 0x7c, // reserved
|
|
100
|
+};
|
|
101
|
+
|
|
102
|
+enum sis190_register_content {
|
|
103
|
+ /* IntrStatus */
|
|
104
|
+ SoftInt = 0x40000000, // unused
|
|
105
|
+ Timeup = 0x20000000, // unused
|
|
106
|
+ PauseFrame = 0x00080000, // unused
|
|
107
|
+ MagicPacket = 0x00040000, // unused
|
|
108
|
+ WakeupFrame = 0x00020000, // unused
|
|
109
|
+ LinkChange = 0x00010000,
|
|
110
|
+ RxQEmpty = 0x00000080,
|
|
111
|
+ RxQInt = 0x00000040,
|
|
112
|
+ TxQ1Empty = 0x00000020, // unused
|
|
113
|
+ TxQ1Int = 0x00000010,
|
|
114
|
+ TxQ0Empty = 0x00000008, // unused
|
|
115
|
+ TxQ0Int = 0x00000004,
|
|
116
|
+ RxHalt = 0x00000002,
|
|
117
|
+ TxHalt = 0x00000001,
|
|
118
|
+
|
|
119
|
+ /* {Rx/Tx}CmdBits */
|
|
120
|
+ CmdReset = 0x10,
|
|
121
|
+ CmdRxEnb = 0x08, // unused
|
|
122
|
+ CmdTxEnb = 0x01,
|
|
123
|
+ RxBufEmpty = 0x01, // unused
|
|
124
|
+
|
|
125
|
+ /* Cfg9346Bits */
|
|
126
|
+ Cfg9346_Lock = 0x00, // unused
|
|
127
|
+ Cfg9346_Unlock = 0xc0, // unused
|
|
128
|
+
|
|
129
|
+ /* RxMacControl */
|
|
130
|
+ AcceptErr = 0x20, // unused
|
|
131
|
+ AcceptRunt = 0x10, // unused
|
|
132
|
+ AcceptBroadcast = 0x0800,
|
|
133
|
+ AcceptMulticast = 0x0400,
|
|
134
|
+ AcceptMyPhys = 0x0200,
|
|
135
|
+ AcceptAllPhys = 0x0100,
|
|
136
|
+
|
|
137
|
+ /* RxConfigBits */
|
|
138
|
+ RxCfgFIFOShift = 13,
|
|
139
|
+ RxCfgDMAShift = 8, // 0x1a in RxControl ?
|
|
140
|
+
|
|
141
|
+ /* TxConfigBits */
|
|
142
|
+ TxInterFrameGapShift = 24,
|
|
143
|
+ TxDMAShift = 8, /* DMA burst value (0-7) is shift this many bits */
|
|
144
|
+
|
|
145
|
+ LinkStatus = 0x02, // unused
|
|
146
|
+ FullDup = 0x01, // unused
|
|
147
|
+
|
|
148
|
+ /* TBICSRBit */
|
|
149
|
+ TBILinkOK = 0x02000000, // unused
|
|
150
|
+};
|
|
151
|
+
|
|
152
|
+struct TxDesc {
|
|
153
|
+ volatile u32 PSize;
|
|
154
|
+ volatile u32 status;
|
|
155
|
+ volatile u32 addr;
|
|
156
|
+ volatile u32 size;
|
|
157
|
+};
|
|
158
|
+
|
|
159
|
+struct RxDesc {
|
|
160
|
+ volatile u32 PSize;
|
|
161
|
+ volatile u32 status;
|
|
162
|
+ volatile u32 addr;
|
|
163
|
+ volatile u32 size;
|
|
164
|
+};
|
|
165
|
+
|
|
166
|
+enum _DescStatusBit {
|
|
167
|
+ /* _Desc.status */
|
|
168
|
+ OWNbit = 0x80000000, // RXOWN/TXOWN
|
|
169
|
+ INTbit = 0x40000000, // RXINT/TXINT
|
|
170
|
+ CRCbit = 0x00020000, // CRCOFF/CRCEN
|
|
171
|
+ PADbit = 0x00010000, // PREADD/PADEN
|
|
172
|
+ /* _Desc.size */
|
|
173
|
+ RingEnd = 0x80000000,
|
|
174
|
+ /* TxDesc.status */
|
|
175
|
+ LSEN = 0x08000000, // TSO ? -- FR
|
|
176
|
+ IPCS = 0x04000000,
|
|
177
|
+ TCPCS = 0x02000000,
|
|
178
|
+ UDPCS = 0x01000000,
|
|
179
|
+ BSTEN = 0x00800000,
|
|
180
|
+ EXTEN = 0x00400000,
|
|
181
|
+ DEFEN = 0x00200000,
|
|
182
|
+ BKFEN = 0x00100000,
|
|
183
|
+ CRSEN = 0x00080000,
|
|
184
|
+ COLEN = 0x00040000,
|
|
185
|
+ THOL3 = 0x30000000,
|
|
186
|
+ THOL2 = 0x20000000,
|
|
187
|
+ THOL1 = 0x10000000,
|
|
188
|
+ THOL0 = 0x00000000,
|
|
189
|
+
|
|
190
|
+ WND = 0x00080000,
|
|
191
|
+ TABRT = 0x00040000,
|
|
192
|
+ FIFO = 0x00020000,
|
|
193
|
+ LINK = 0x00010000,
|
|
194
|
+ ColCountMask = 0x0000ffff,
|
|
195
|
+ /* RxDesc.status */
|
|
196
|
+ IPON = 0x20000000,
|
|
197
|
+ TCPON = 0x10000000,
|
|
198
|
+ UDPON = 0x08000000,
|
|
199
|
+ Wakup = 0x00400000,
|
|
200
|
+ Magic = 0x00200000,
|
|
201
|
+ Pause = 0x00100000,
|
|
202
|
+ DEFbit = 0x00200000,
|
|
203
|
+ BCAST = 0x000c0000,
|
|
204
|
+ MCAST = 0x00080000,
|
|
205
|
+ UCAST = 0x00040000,
|
|
206
|
+ /* RxDesc.PSize */
|
|
207
|
+ TAGON = 0x80000000,
|
|
208
|
+ RxDescCountMask = 0x7f000000, // multi-desc pkt when > 1 ? -- FR
|
|
209
|
+ ABORT = 0x00800000,
|
|
210
|
+ SHORT = 0x00400000,
|
|
211
|
+ LIMIT = 0x00200000,
|
|
212
|
+ MIIER = 0x00100000,
|
|
213
|
+ OVRUN = 0x00080000,
|
|
214
|
+ NIBON = 0x00040000,
|
|
215
|
+ COLON = 0x00020000,
|
|
216
|
+ CRCOK = 0x00010000,
|
|
217
|
+ RxSizeMask = 0x0000ffff
|
|
218
|
+ /*
|
|
219
|
+ * The asic could apparently do vlan, TSO, jumbo (sis191 only) and
|
|
220
|
+ * provide two (unused with Linux) Tx queues. No publically
|
|
221
|
+ * available documentation alas.
|
|
222
|
+ */
|
|
223
|
+};
|
|
224
|
+
|
|
225
|
+enum sis190_eeprom_access_register_bits {
|
|
226
|
+ EECS = 0x00000001, // unused
|
|
227
|
+ EECLK = 0x00000002, // unused
|
|
228
|
+ EEDO = 0x00000008, // unused
|
|
229
|
+ EEDI = 0x00000004, // unused
|
|
230
|
+ EEREQ = 0x00000080,
|
|
231
|
+ EEROP = 0x00000200,
|
|
232
|
+ EEWOP = 0x00000100 // unused
|
|
233
|
+};
|
|
234
|
+
|
|
235
|
+/* EEPROM Addresses */
|
|
236
|
+enum sis190_eeprom_address {
|
|
237
|
+ EEPROMSignature = 0x00,
|
|
238
|
+ EEPROMCLK = 0x01, // unused
|
|
239
|
+ EEPROMInfo = 0x02,
|
|
240
|
+ EEPROMMACAddr = 0x03
|
|
241
|
+};
|
|
242
|
+
|
|
243
|
+enum sis190_feature {
|
|
244
|
+ F_HAS_RGMII = 1,
|
|
245
|
+ F_PHY_88E1111 = 2,
|
|
246
|
+ F_PHY_BCM5461 = 4
|
|
247
|
+};
|
|
248
|
+
|
|
249
|
+struct sis190_private {
|
|
250
|
+ void *mmio_addr;
|
|
251
|
+ struct pci_device *pci_device;
|
|
252
|
+ struct net_device *dev;
|
|
253
|
+ u32 cur_rx;
|
|
254
|
+ u32 cur_tx;
|
|
255
|
+ u32 dirty_rx;
|
|
256
|
+ u32 dirty_tx;
|
|
257
|
+ u32 rx_dma;
|
|
258
|
+ u32 tx_dma;
|
|
259
|
+ struct RxDesc *RxDescRing;
|
|
260
|
+ struct TxDesc *TxDescRing;
|
|
261
|
+ struct io_buffer *Rx_iobuf[NUM_RX_DESC];
|
|
262
|
+ struct io_buffer *Tx_iobuf[NUM_TX_DESC];
|
|
263
|
+ struct mii_if_info mii_if;
|
|
264
|
+ struct list_head first_phy;
|
|
265
|
+ u32 features;
|
|
266
|
+};
|
|
267
|
+
|
|
268
|
+struct sis190_phy {
|
|
269
|
+ struct list_head list;
|
|
270
|
+ int phy_id;
|
|
271
|
+ u16 id[2];
|
|
272
|
+ u16 status;
|
|
273
|
+ u8 type;
|
|
274
|
+};
|
|
275
|
+
|
|
276
|
+enum sis190_phy_type {
|
|
277
|
+ UNKNOWN = 0x00,
|
|
278
|
+ HOME = 0x01,
|
|
279
|
+ LAN = 0x02,
|
|
280
|
+ MIX = 0x03
|
|
281
|
+};
|
|
282
|
+
|
|
283
|
+static struct mii_chip_info {
|
|
284
|
+ const char *name;
|
|
285
|
+ u16 id[2];
|
|
286
|
+ unsigned int type;
|
|
287
|
+ u32 feature;
|
|
288
|
+} mii_chip_table[] = {
|
|
289
|
+ { "Atheros PHY", { 0x004d, 0xd010 }, LAN, 0 },
|
|
290
|
+ { "Atheros PHY AR8012", { 0x004d, 0xd020 }, LAN, 0 },
|
|
291
|
+ { "Broadcom PHY BCM5461", { 0x0020, 0x60c0 }, LAN, F_PHY_BCM5461 },
|
|
292
|
+ { "Broadcom PHY AC131", { 0x0143, 0xbc70 }, LAN, 0 },
|
|
293
|
+ { "Agere PHY ET1101B", { 0x0282, 0xf010 }, LAN, 0 },
|
|
294
|
+ { "Marvell PHY 88E1111", { 0x0141, 0x0cc0 }, LAN, F_PHY_88E1111 },
|
|
295
|
+ { "Realtek PHY RTL8201", { 0x0000, 0x8200 }, LAN, 0 },
|
|
296
|
+ { NULL, { 0x00, 0x00 }, 0, 0 }
|
|
297
|
+};
|
|
298
|
+
|
|
299
|
+static const struct {
|
|
300
|
+ const char *name;
|
|
301
|
+} sis_chip_info[] = {
|
|
302
|
+ { "SiS 190 PCI Fast Ethernet adapter" },
|
|
303
|
+ { "SiS 191 PCI Gigabit Ethernet adapter" },
|
|
304
|
+};
|
|
305
|
+
|
|
306
|
+static void sis190_phy_task(struct sis190_private *tp);
|
|
307
|
+static void sis190_free(struct net_device *dev);
|
|
308
|
+static inline void sis190_init_rxfilter(struct net_device *dev);
|
|
309
|
+
|
|
310
|
+#endif
|