embox

Форк
0
372 строки · 11.2 Кб
1
/**
2
 * @file
3
 * @brief RDC R6040 PCI Fast Ethernet MAC support
4
 * @description Low level ring-buffer manipulation for r6040 ethernet.
5
 *
6
 * @date 25.03.11
7
 * @author Nikolay Korotky
8
 */
9

10
#include <asm/io.h>
11
#include <string.h>
12
#include <unistd.h>
13
#include <stdint.h>
14
#include <kernel/time/ktime.h>
15
#include <embox/unit.h>
16
#include <net/l2/ethernet.h>
17
#include <net/skbuff.h>
18
#include <net/netdevice.h>
19
#include <kernel/irq.h>
20
#include <net/l0/net_entry.h>
21

22
#include "r6040.h"
23

24
EMBOX_UNIT_INIT(r6040_init);
25

26
#define INTERRUPTS_ENABLE 0
27

28
/* PHY CHIP Address */
29
#define PHY1_ADDR      1       /* For MAC1 */
30
#define PHY2_ADDR      3       /* For MAC2 */
31
#define PHY_MODE       0x3100  /* PHY CHIP Register 0 */
32
#define PHY_CAP        0x01E1  /* PHY CHIP Register 4 */
33

34
/* RDC MAC I/O Size */
35
#define R6040_IO_SIZE   256
36

37
//TODO: get from PCI
38
#define IOADDR         0xe800
39

40
/* MAC registers */
41
#define MCR0           (IOADDR + 0x00) /* Control register 0 */
42
#define MCR0_PROMISC   0x0020          /* Promiscuous mode */
43
#define MCR0_HASH_EN   0x0100          /* Enable multicast hash table function */
44
#define MCR1           (IOADDR + 0x04) /* Control register 1 */
45
#define MAC_RST        0x0001          /* Reset the MAC */
46
#define MBCR           (IOADDR + 0x08) /* Bus control */
47
#define MT_ICR         (IOADDR + 0x0C) /* TX interrupt control */
48
#define MR_ICR         (IOADDR + 0x10) /* RX interrupt control */
49
#define MTPR           (IOADDR + 0x14) /* TX poll command register */
50
#define MR_BSR         (IOADDR + 0x18) /* RX buffer size */
51
#define MR_DCR         (IOADDR + 0x1A) /* RX descriptor control */
52
#define MLSR           (IOADDR + 0x1C) /* Last status */
53
#define MMDIO          (IOADDR + 0x20) /* MDIO control register */
54
#define MDIO_WRITE     0x4000          /* MDIO write */
55
#define MDIO_READ      0x2000          /* MDIO read  */
56
#define MMRD           (IOADDR + 0x24) /* MDIO read data register  */
57
#define MMWD           (IOADDR + 0x28) /* MDIO write data register */
58
#define TX_START_LOW   (IOADDR + 0x2c) /* TX descriptor start address 0 */
59
#define TX_START_HIGH  (IOADDR + 0x30) /* TX descriptor start address 1 */
60
#define RX_START_LOW   (IOADDR + 0x34) /* RX descriptor start address 0 */
61
#define RX_START_HIGH  (IOADDR + 0x38) /* RX descriptor start address 1 */
62
#define MISR           (IOADDR + 0x3c) /* Status register */
63
#define MIER           (IOADDR + 0x40) /* INT enable register */
64
#define MSK_INT        0x0000          /* Mask off interrupts */
65
#define RX_FINISH      0x0001          /* RX finished */
66
#define RX_NO_DESC     0x0002          /* No RX descriptor available */
67
#define RX_FIFO_FULL   0x0004          /* RX FIFO full */
68
#define RX_EARLY       0x0008          /* RX early */
69
#define TX_FINISH      0x0010          /* TX finished */
70
#define TX_EARLY       0x0080          /* TX early */
71
#define EVENT_OVRFL    0x0100          /* Event counter overflow */
72
#define LINK_CHANGED   0x0200          /* PHY link changed */
73
#define ME_CISR        (IOADDR + 0x44) /* Event counter INT status */
74
#define ME_CIER        (IOADDR + 0x48) /* Event counter INT enable */
75
#define MR_CNT         (IOADDR + 0x50) /* Successfully received packet counter */
76
#define ME_CNT0        (IOADDR + 0x52) /* Event counter 0 */
77
#define ME_CNT1        (IOADDR + 0x54) /* Event counter 1 */
78
#define ME_CNT2        (IOADDR + 0x56) /* Event counter 2 */
79
#define ME_CNT3        (IOADDR + 0x58) /* Event counter 3 */
80
#define MT_CNT         (IOADDR + 0x5A) /* Successfully transmit packet counter */
81
#define ME_CNT4        (IOADDR + 0x5C) /* Event counter 4 */
82
#define MP_CNT         (IOADDR + 0x5E) /* Pause frame counter register */
83
#define MAR0           (IOADDR + 0x60) /* Hash table 0 */
84
#define MAR1           (IOADDR + 0x62) /* Hash table 1 */
85
#define MAR2           (IOADDR + 0x64) /* Hash table 2 */
86
#define MAR3           (IOADDR + 0x66) /* Hash table 3 */
87

88
#define MAC_SM         (IOADDR + 0xAC) /* MAC status machine */
89

90
#define TX_DCNT         0x80    /* TX descriptor count */
91
#define RX_DCNT         0x80    /* RX descriptor count */
92
#define MAX_BUF_SIZE    0x600
93
//#define RX_DESC_SIZE    (RX_DCNT * sizeof(struct eth_desc))
94
//#define TX_DESC_SIZE    (TX_DCNT * sizeof(struct eth_desc))
95
#define MBCR_DEFAULT    0x012A  /* MAC Bus Control Register */
96

97
/* Descriptor status */
98
#define DSC_OWNER_MAC   0x8000  /* MAC is the owner of this descriptor */
99
#define DSC_RX_OK       0x4000  /* RX was successful */
100
#define DSC_RX_ERR      0x0800  /* RX PHY error */
101
#define DSC_RX_ERR_DRI  0x0400  /* RX dribble packet */
102
#define DSC_RX_ERR_BUF  0x0200  /* RX length exceeds buffer size */
103
#define DSC_RX_ERR_LONG 0x0100  /* RX length > maximum packet length */
104
#define DSC_RX_ERR_RUNT 0x0080  /* RX packet length < 64 byte */
105
#define DSC_RX_ERR_CRC  0x0040  /* RX CRC error */
106
#define DSC_RX_BCAST    0x0020  /* RX broadcast (no error) */
107
#define DSC_RX_MCAST    0x0010  /* RX multicast (no error) */
108
#define DSC_RX_MCH_HIT  0x0008  /* RX multicast hit in hash table (no error) */
109
#define DSC_RX_MIDH_HIT 0x0004  /* RX MID table hit (no error) */
110
#define DSC_RX_IDX_MID_MASK 3   /* RX mask for the index of matched MIDx */
111

112
/* RX and TX interrupts that we handle */
113
#define RX_INTS        (RX_FIFO_FULL | RX_NO_DESC | RX_FINISH)
114
#define TX_INTS        (TX_FINISH)
115
#define INT_MASK       (RX_INTS | TX_INTS)
116

117
/**
118
 * Descriptor definition and manip functions.
119
 * doubles as the TX and RX descriptor
120
 */
121
typedef struct eth_desc {
122
	volatile uint16_t status;
123
	uint16_t       dlen;
124
	unsigned char *buf;
125
	struct eth_desc *DNX;
126
	unsigned short HIDX;
127
	unsigned short Reserved1;
128
	unsigned short Reserved2;
129
	/* Extra info, used by driver */
130
	unsigned short dlen_orig;
131
} __attribute__((aligned(32))) eth_desc_t;
132

133
static uint8_t descrxbuff[0x800];
134
static uint8_t etherrxbuff[0x800];
135

136
/* Pass in the next pointer */
137
static eth_desc_t *rxd_init(size_t pkt_size) {
138
	eth_desc_t *rxd = (eth_desc_t *) descrxbuff;
139
	unsigned char *pkt = (unsigned char *) etherrxbuff;
140

141
	/* Clear it */
142
	memset(rxd, 0, sizeof(eth_desc_t));
143

144
	/* clear pkt area */
145
	memset(pkt, 0, pkt_size);
146

147
	/* Make this one owned by the MAC */
148
	rxd->status = DSC_OWNER_MAC;
149

150
	/* Set the buffer pointer */
151
	rxd->buf = pkt;
152
	rxd->dlen = pkt_size;
153

154
	return rxd;
155
}
156

157
static void r6040_tx_enable(void) {
158
	unsigned short tmp = in16(MCR0);
159
	out16(tmp | (1 << 12), MCR0);
160
}
161

162
static void r6040_tx_disable(void) {
163
	unsigned short tmp = in16(MCR0);
164
	out16(tmp & ~(1 << 12), MCR0);
165
}
166

167
void r6040_rx_enable(void) {
168
	unsigned short tmp = in16(MCR0);
169
	out16(tmp | (1 << 1), MCR0);
170
//	out16(2, MCR0);
171
}
172

173
static void r6040_rx_disable(void) {
174
	out8(0, MCR0);
175
}
176

177
static void r6040_set_tx_start(eth_desc_t* desc) {
178
	unsigned long tmp = (unsigned long) desc;
179
	out16((tmp & 0xffff), TX_START_LOW);
180
	tmp >>= 16;
181
	out16((tmp & 0xffff), TX_START_HIGH);
182
}
183

184
static void r6040_set_rx_start(eth_desc_t* desc) {
185
	unsigned long tmp = (unsigned long) desc;
186
	out16((tmp & 0xffff), RX_START_LOW);
187
	tmp >>= 16;
188
	out16((tmp & 0xffff), RX_START_HIGH);
189
}
190
#include <kernel/printk.h>
191
#if INTERRUPTS_ENABLE
192
/* The RDC interrupt handler */
193
static irq_return_t irq_handler(unsigned int irq_num, void *dev_id) {
194
	uint16_t misr, status;
195

196
	printk("IRQ!\n");
197

198
	/* Save MIER */
199
	misr = in16(MIER);
200
	/* Mask off RDC MAC interrupt */
201
	out16(MSK_INT, MIER);
202
	/* Read MISR status and clear */
203
	status = in16(MISR);
204

205
	if (status == 0x0000 || status == 0xffff) {
206
		/* Restore RDC MAC interrupt */
207
		out16(misr, MIER);
208
		return IRQ_NONE;
209
	}
210
	//TODO:
211

212
	/* Restore RDC MAC interrupt */
213
	out16(misr, MIER);
214
	return IRQ_HANDLED;
215
}
216
#endif
217
/* Interface */
218

219
/* Keep track of what we've allocated, so we can easily walk it */
220
eth_desc_t *g_rx_descriptor_list[R6040_RX_DESCRIPTORS];
221
eth_desc_t *g_rx_descriptor_next;
222
eth_desc_t *g_tx_descriptor_next;
223

224
#if 0
225
/* Disable packet reception */
226
void r6040_done(void) {
227
	out8(0, MCR0);
228
}
229
#endif
230

231
static void discard_descriptor(void) {
232
	/* reset the length field to original value. */
233
	g_rx_descriptor_next->dlen = g_rx_descriptor_next->dlen_orig;
234
	g_rx_descriptor_next->status = DSC_OWNER_MAC; /* give back to the MAC */
235
	g_rx_descriptor_next = g_rx_descriptor_next->DNX; /* Move along */
236
}
237

238
/* Returns size of pkt, or zero if none received */
239
size_t r6040_rx(unsigned char* pkt, size_t max_len) {
240
	size_t ret = 0;
241
	printk("MIER=0x%08x\n", *((unsigned int *) MIER));
242
	printk("MISR=0x%08x\n", *((unsigned int *) MISR));
243
	printk("MR_ICR=0x%08x\n", *((unsigned int *) MR_ICR));
244

245
	if (g_rx_descriptor_next->status & DSC_OWNER_MAC) {
246
		/* Still owned by the MAC, nothing received */
247
		return ret;
248
	}
249

250
	if (!(g_rx_descriptor_next->status & DSC_RX_OK)) {
251
		/* Descriptor descarded with error */
252
		discard_descriptor();
253
		return ret;
254
	}
255

256
	/* If the buffer isn't long enough discard this packet */
257
	if (g_rx_descriptor_next->dlen > max_len) {
258
		/* Descriptor descarded (buffer too short) */
259
		discard_descriptor();
260
		return ret;
261
	}
262

263
	/* Otherwise copy out and advance buffer pointer */
264

265
	memcpy(pkt, g_rx_descriptor_next->buf, g_rx_descriptor_next->dlen);
266
	ret = g_rx_descriptor_next->dlen;
267
	ret -= 4;   /* chop the checksum, we don't need it */
268
	discard_descriptor();
269
	return ret;
270
}
271

272
/* queue packet for transmission */
273
void r6040_tx(unsigned char* pkt, size_t length) {
274
	r6040_tx_disable();
275

276
	/* copy this packet into the transmit descriptor */
277
	memset(g_tx_descriptor_next->buf, 0, 60);
278

279
	memcpy(g_tx_descriptor_next->buf, pkt, length);
280
	g_tx_descriptor_next->dlen = (length < 60) ? 60 : length;
281

282
	/* Copy the descriptor address (will have been set to zero by last op) */
283
	r6040_set_tx_start(g_tx_descriptor_next);
284

285
	/* Make the mac own it */
286
	g_tx_descriptor_next->status = DSC_OWNER_MAC;
287

288
	//desc_dump(g_tx_descriptor_next);
289

290
	/* Start xmit */
291
	r6040_tx_enable();
292

293
	/* poll for mac to no longer own it */
294
	while (g_tx_descriptor_next->status & DSC_OWNER_MAC) {};
295
	/* Stop any other activity */
296
	r6040_tx_disable();
297

298
	//desc_dump(g_tx_descriptor_next);
299
}
300

301
unsigned short r6040_mdio_read(int reg, int phy) {
302
	out8(MDIO_READ + reg + (phy << 8), MMDIO);
303
	/* Wait for the read bit to be cleared */
304
	while (in16(MMDIO) & MDIO_READ);
305
	return in16(MMRD);
306
}
307

308
/* Wait for linkup, or timeout. */
309
int r6040_wait_linkup(void) {
310
	unsigned short tmp, i;
311

312
	for (i = 0; i < 300; i++) {
313
		/* Check if link up. */
314
		tmp = r6040_mdio_read(1, 1) & (1 << 2);
315
		if (tmp) {
316
			return 1;
317
		}
318
		/* Wait 10mS more */
319
		ksleep(10);
320
	}
321
	return 0;
322
}
323

324
int r6040_open(struct net_device *dev) {
325
#if INTERRUPTS_ENABLE
326
	if (-1 == irq_attach(0x0a, irq_handler, 0, dev, "RDC r6040")) {
327
		return -1;
328
	}
329
	out16(0, MT_ICR);
330
	out16(0, MR_ICR);
331
	out16(INT_MASK, MIER);
332
#endif
333
	return 0;
334

335
}
336
#if INTERRUPTS_ENABLE
337
static int r6040_stop(struct net_device *dev) {
338
	return 0;
339

340
}
341

342
static const struct net_driver r6040_drv_ops = {
343
//	.xmit = r6040_xmit,
344
	.start       = r6040_open,
345
	.stop       = r6040_stop,
346
//	.set_macaddr = set_mac_address
347
};
348
#endif
349

350

351
/* setup descriptors, start packet reception */
352
static int r6040_init(void) {
353
	size_t i;
354
	r6040_wait_linkup();
355
	r6040_rx_disable();
356
	r6040_tx_disable();
357
	for (i = 0; i < R6040_RX_DESCRIPTORS; i++) {
358
		/* most packets will be no larger than this */
359
		g_rx_descriptor_list[i] = rxd_init(1536);
360
		if (i) {
361
			g_rx_descriptor_list[i - 1]->DNX = g_rx_descriptor_list[i];
362
		}
363
	}
364
	/* Make ring buffer */
365
	g_rx_descriptor_list[R6040_RX_DESCRIPTORS - 1]->DNX = g_rx_descriptor_list[0];
366
	r6040_set_rx_start(g_rx_descriptor_list[0]);
367
	g_rx_descriptor_next = g_rx_descriptor_list[0];
368
	g_tx_descriptor_next = rxd_init(1536);
369

370
	r6040_rx_enable();
371
	return 0;
372
}
373

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.