LibXenon
Bare-metal Xbox 360 homebrew library
Loading...
Searching...
No Matches
enet.c
Go to the documentation of this file.
1//#include "lwipopts.h"
2#include "lwip/opt.h"
3#include "lwip/def.h"
4#include "lwip/mem.h"
5#include "lwip/pbuf.h"
6#include "lwip/sys.h"
7#include "lwip/stats.h"
8#include "lwip/timers.h"
9#include "netif/etharp.h"
10
11#include <time/time.h>
13#include <ppc/cache.h>
14#include <pci/io.h>
16
17#define TX_DESCRIPTOR_NUM 0x10
18#define RX_DESCRIPTOR_NUM 0x10
19#define MTU 1528
20#define MEM(x) (0x80000000|(long)(x))
21
23{
27
31
32 struct eth_addr *ethaddr;
33};
34
35static int enet_open(struct netif *ctx);
36static struct pbuf *enet_linkinput(struct enet_context *context);
37static err_t enet_linkoutput(struct netif *netif, struct pbuf *p);
38//static err_t enet_output(struct netif *netif, struct pbuf *p, ip_addr_t *ipaddr);
39
40static unsigned short phy_read(int addr)
41{
42 write32n(0xea001444, __builtin_bswap32((addr << 11) | 0x50));
43 do {mdelay(1);} while (__builtin_bswap32(read32n(0xea001444)) & 0x10);
44 return __builtin_bswap32(read32n(0xea001444)) >> 16;
45}
46
47static void phy_write(int addr, unsigned short data)
48{
49 write32n(0xea001444, __builtin_bswap32((addr << 11) | 0x70 | (data << 16)));
50 do {mdelay(1);} while (__builtin_bswap32(read32n(0xea001444)) & 0x10);
51}
52
53static void wait_empty_tx(struct enet_context *context)
54{
55// printf(">> CURRENT TX PTR: %08x\n", __builtin_bswap32(read32n(0xea00140c)));
56 while (__builtin_bswap32(context->tx_descriptor_base[context->tx_descriptor_wptr * 4 + 1]) & 0x80000000); // busy
57}
58
59static inline int virt_to_phys(volatile void *ptr)
60{
61 return ((long)ptr) & 0x7FFFFFFF;
62}
63
64static void tx_data(struct enet_context *context, unsigned char *data, int len)
65{
66 wait_empty_tx(context);
67 int descnr = context->tx_descriptor_wptr;
68 volatile uint32_t *descr = context->tx_descriptor_base + descnr * 4;
69
70// printf("using tx descriptor %d\n", descnr);
71
72// printf("really before %08x %08x %08x %08x\n", descr[0], descr[1], descr[2], descr[3]);
73
74 descr[0] = __builtin_bswap32(len);
75 descr[2] = __builtin_bswap32(virt_to_phys(data));
76 descr[3] = __builtin_bswap32(len | ((descnr == TX_DESCRIPTOR_NUM - 1) ? 0x80000000 : 0));
77 descr[1] = __builtin_bswap32(0xc0230000); // ownership, ...
78
79// printf("data at %08x\n", virt_to_phys(data));
80
81 memdcbst((void*)descr, 0x10);
82
83// printf("before %08x %08x %08x %08x\n", descr[0], descr[1], descr[2], descr[3]);
84
85 write32n(0xea001400, read32n(0xea001400) | __builtin_bswap32(0x10)); // Q0_START
86
87// printf("after %08x %08x %08x %08x\n", descr[0], descr[1], descr[2], descr[3]);
88
89 context->tx_descriptor_wptr++;
91
92 write32n(0xea001410, __builtin_bswap32(0x00101c11)); // enable RX
93
94// printf("TX\n");
95}
96
97static void tx_init(struct enet_context *context, void *base)
98{
99 int i;
100
101 context->tx_descriptor_base = base;
102 context->tx_descriptor_wptr = 0;
103
104 for (i=0; i < TX_DESCRIPTOR_NUM; ++i)
105 {
106 /* tx descriptors */
107 context->tx_descriptor_base[i * 4 + 0] = 0;
108 context->tx_descriptor_base[i * 4 + 1] = 0;
109 context->tx_descriptor_base[i * 4 + 2] = 0;
110 if (i != TX_DESCRIPTOR_NUM - 1)
111 context->tx_descriptor_base[i * 4 + 3] = 0;
112 else
113 context->tx_descriptor_base[i * 4 + 3] = __builtin_bswap32(0x80000000);
114 }
115
116 memdcbst((void*)context->tx_descriptor_base, TX_DESCRIPTOR_NUM * 0x10);
117
118 context->tx_buffer_base = base + TX_DESCRIPTOR_NUM * 0x10;
119
120 write32n(0xea001400, __builtin_bswap32(0x00001c00));
121 write32n(0xea001404, __builtin_bswap32(virt_to_phys(context->tx_descriptor_base)));
122 write32n(0xea001400, __builtin_bswap32(0x00011c00));
123 write32n(0xea001404, __builtin_bswap32(virt_to_phys(context->tx_descriptor_base)));
124 write32n(0xea001400, __builtin_bswap32(0x00001c00));
125}
126
127
128static void rx_init(struct enet_context *context, void *base)
129{
130 int i;
131
132 context->rx_descriptor_base = base;
133 context->rx_receive_base = base + RX_DESCRIPTOR_NUM * 0x10;
134 context->rx_descriptor_rptr = 0;
135
136 /* setup rx descriptors */
137 for (i=0; i < RX_DESCRIPTOR_NUM; ++i)
138 {
139 context->rx_descriptor_base[i * 4 + 0] = __builtin_bswap32(0);
140 context->rx_descriptor_base[i * 4 + 1] = __builtin_bswap32(0xc0000000);
141 context->rx_descriptor_base[i * 4 + 2] = __builtin_bswap32(virt_to_phys(context->rx_receive_base + i * MTU));
142 context->rx_descriptor_base[i * 4 + 3] = __builtin_bswap32(MTU | ((i == RX_DESCRIPTOR_NUM - 1) ? 0x80000000 : 0));
143 }
144 memdcbst((void*)context->rx_descriptor_base, RX_DESCRIPTOR_NUM * 0x10);
145
146 write32n(0xea001414, __builtin_bswap32(virt_to_phys(context->rx_descriptor_base))); // RX queue start
147 write32n(0xea001440, 0x1100004);
148 write32n(0xea001450, 0);
149}
150
151
152//static void arp_timer(void *arg)
153//{
154// etharp_tmr();
155// //sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL);
156//}
157
159{
160 struct enet_context * context;
161
162 context = (struct enet_context *)mem_malloc(sizeof(struct enet_context));
163 if(context == NULL) {
164 printf("enet: Failed to allocate context memory.\n");
165 return ERR_MEM;
166 } else {
167 memset(context, 0, sizeof(struct enet_context));
168
169 // enet_write_mac_address(context, m);
171 }
172
173 netif->state = context;
174 netif->name[0] = 'e';
175 netif->name[1] = 'n';
176 netif->output = etharp_output; //enet_output; //lwip 1.3.0
177 netif->linkoutput = enet_linkoutput;
178 context->ethaddr = (struct eth_addr *)&(netif->hwaddr[0]);
179
180 netif->hwaddr_len = 6;
181 netif->mtu = 1500;
183
184#if LWIP_NETIF_HOSTNAME
185 netif->hostname = "XeLL";
186#endif
187
188 //printf("NETIF at %p\n", netif);
189
190 enet_open(netif);
191 etharp_init();
192 //sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL);
193 return ERR_OK;
194}
195
196
197static int enet_open(struct netif *netif)
198{
199 int tries=10;
200 struct enet_context *context = (struct enet_context *) netif->state;
201
202 //printf("NIC reset\n");
203 write32n(0xea001424, 0); // disable interrupts
204 write32n(0xea001428, 0x01805508);
205 //printf("reset: %08x\n", read32n(0xea001428));
206 udelay(100);
207 write32n(0xea001428, 0x01005508);
208
209 write32n(0xea001444, __builtin_bswap32(4));
210 udelay(100);
211 write32n(0xea001444, __builtin_bswap32(0));
212 //printf("1478 before: %08x\n", read32n(0xea001478));
213 // Set MTU
214 write32n(0xea001478, 0xf2050000); //printf("1478: %08x\n", read32n(0xea001478));
215
216 // important
217 write32n(0xea001450, 0x60230000);
218
219 // mac 1+2
220 write32n(0xea001478, 0xF2050000 | (netif->hwaddr[0] << 8) | (netif->hwaddr[1] << 0));
221 write32n(0xea00147c, (netif->hwaddr[2] << 24) | (netif->hwaddr[3] << 16) | (netif->hwaddr[4] << 8) | (netif->hwaddr[5] << 0) );
222
223 write32n(0xea001460, 0x380e0000 | (netif->hwaddr[0] << 8) | (netif->hwaddr[1] << 0));
224 write32n(0xea001464, (netif->hwaddr[2] << 24) | (netif->hwaddr[3] << 16) | (netif->hwaddr[4] << 8) | (netif->hwaddr[5] << 0) );
225
226 // multicast hash
227 write32n(0xea001468, 0);
228 write32n(0xea00146c, 0);
229
230 write32n(0xea001400, 0x001c0000);
231 write32n(0xea001410, __builtin_bswap32(0x00101c00));
232
233 write32n(0xea001440, 0x01190004);
234
235 void *base = (void*)memalign(0x10000,0x10000);
236
237 //printf("init tx\n");
238 tx_init(context, (void*)MEM(base));
239 //printf("init rx\n");
240 rx_init(context, (void*)MEM(base + 0x8000));
241
242 write32n(0xea001440, 0x01100004);
243
244#if 1
245 printf("Reinit PHY...\n");
246
247 // get PHY out of reset state
248 xenon_gpio_control(0,0,0x10);
249 xenon_gpio_control(4,0,0x10);
250
251 phy_write(0, 0x9000);
252
253 while (phy_read(0) & 0x8000){
254 mdelay(500);
255 tries--;
256 if (tries<=0) break;
257 };
258
259// phy_write(0x10, 0x8058);
260// phy_write(4, 0x5e1);
261// phy_write(0x14, 0x4048);
262
263 int linkstate = phy_read(1);
264 if (!(linkstate & 4))
265 {
266 tries=10;
267
268 printf("Waiting for link...");
269 while (!(phy_read(1) & 4)){
270 mdelay(500);
271 tries--;
272 if (tries<=0) break;
273 };
274 }
275
276 if (phy_read(1) & 4) {
277 printf("link up!\n");
279 } else {
280 printf("link still down.\n");
282 }
283#endif
284
285
286// write32n(0xea001428, 0x01805508);
287 write32n(0xea001428, 0x01005508);
288 write32n(0xea001410, __builtin_bswap32(0x00101c11)); // enable RX
289 write32n(0xea001400, __builtin_bswap32(0x00001c01)); // enable TX
290
291 return 0;
292}
293
294static struct pbuf *enet_linkinput(struct enet_context *context)
295{
296 volatile uint32_t *d = context->rx_descriptor_base + context->rx_descriptor_rptr * 4;
297 memdcbf((void*)d, 0x10);
298 if (__builtin_bswap32(d[1]) & 0x80000000) /* check ownership */
299 {
300// printf("no data!\n");
301 return 0;
302 }
303
304// printf("RX descriptor %d contains data!\n", context->rx_descriptor_rptr);
305// printf("%08x %08x %08x %08x\n",
306// __builtin_bswap32(d[0]),
307// __builtin_bswap32(d[1]),
308// __builtin_bswap32(d[2]),
309// __builtin_bswap32(d[3]));
310
311 int size = __builtin_bswap32(d[0]) & 0xFFFF;
312 void *phys_addr = context->rx_receive_base + context->rx_descriptor_rptr * MTU;
313 memdcbf(phys_addr, size);
314
315 // hexdump(phys_addr, size);
316
317 struct pbuf *p = pbuf_alloc(PBUF_RAW, size, PBUF_POOL), *q;
318
319 if (p != NULL) {
320 int rptr = 0;
321 /* We iterate over the pbuf chain until we have read the entire
322 packet into the pbuf. */
323 for(q = p; q != NULL; q = q->next) {
324 /* Read enough bytes to fill this pbuf in the chain. The
325 available data in the pbuf is given by the q->len
326 variable. */
327 memcpy(q->payload, phys_addr + rptr, q->len);
328 rptr += q->len;
329 }
330#ifdef LINK_STATS
331 lwip_stats.link.recv++;
332#endif /* LINK_STATS */
333 } else {
334#ifdef LINK_STATS
335 lwip_stats.link.memerr++;
336 lwip_stats.link.drop++;
337#endif /* LINK_STATS */
338 }
339
340 /* reclaim descriptor */
341 d[2] = __builtin_bswap32(virt_to_phys(context->rx_receive_base + context->rx_descriptor_rptr * MTU));
342 d[3] = __builtin_bswap32(MTU | ((context->rx_descriptor_rptr == RX_DESCRIPTOR_NUM - 1) ? 0x80000000 : 0));
343 d[0] = __builtin_bswap32(0);
344 d[1] = __builtin_bswap32(0xc0000000);
345 memdcbst((void*)d, 0x10);
346
347 context->rx_descriptor_rptr++;
349
350 return p;
351}
352
353static err_t enet_linkoutput(struct netif *netif, struct pbuf *p)
354{
355 struct pbuf *q;
356 struct enet_context *context = (struct enet_context *) netif->state;
357
358// printf("enet linkoutput\n");
359
360 void *dstptr = context->tx_buffer_base + context->tx_descriptor_wptr * MTU;
361 int offset = 0;
362
363 for(q = p; q != NULL; q = q->next) {
364 memcpy(dstptr + offset, q->payload, q->len);
365 offset += q->len;
366 }
367
368 memdcbst((void*)dstptr, p->tot_len);
369 tx_data(context, dstptr, p->tot_len);
370
371// printf("ok, data transmitted!\n");
372
373 return 0;
374}
375
376/*
377static err_t
378enet_output(struct netif *netif, struct pbuf *p,
379 struct ip_addr_t *ipaddr)
380{
381// printf("ENET OUTPUT\n");
382 //return etharp_output(netif, ipaddr, p);
383 return etharp_output(netif, p, ipaddr); //lwip 1.3.0
384}
385*/
386
387static void
388enet_input(struct netif *netif)
389{
390 struct enet_context *context = (struct enet_context *) netif->state;
391 struct eth_hdr *ethhdr;
392 struct pbuf *p;
393
394 p = enet_linkinput(context);
395
396 if (p == NULL)
397 return;
398
399#if LINK_STATS
400 lwip_stats.link.recv++;
401#endif /* LINK_STATS */
402
403 ethhdr = p->payload;
404
405 /* pass to network layer */
406 if (ethernet_input(p, netif) != ERR_OK) {
407 pbuf_free(p);
408 p = NULL;
409 }
410}
411
412int cnt;
413
414void
416{
417// printf("\r%08x", mfdec());
418 enet_input(netif);
419}
420
421
422void enet_quiesce(void)
423{
424 write32n(0xea001400, 0);
425 write32n(0xea001410, 0);
426}
#define base
#define NULL
Definition: def.h:47
void memdcbf(void *addr, int len)
void memdcbst(void *addr, int len)
void enet_poll(struct netif *netif)
Definition: enet.c:415
#define MTU
Definition: enet.c:19
err_t enet_init(struct netif *netif)
Definition: enet.c:158
#define RX_DESCRIPTOR_NUM
Definition: enet.c:18
void enet_quiesce(void)
Definition: enet.c:422
int cnt
Definition: enet.c:412
#define MEM(x)
Definition: enet.c:20
#define TX_DESCRIPTOR_NUM
Definition: enet.c:17
#define ERR_MEM
Definition: err.h:53
#define ERR_OK
Definition: err.h:52
s8_t err_t
Definition: err.h:47
u32 ptr
Definition: iso9660.c:557
u32 size
Definition: iso9660.c:558
u32 uint32_t
Definition: libfdt_env.h:11
void * mem_malloc(mem_size_t size)
Definition: mem.c:494
void netif_set_link_down(struct netif *netif)
Definition: netif.c:574
void netif_set_link_up(struct netif *netif)
Definition: netif.c:535
#define NETIF_FLAG_ETHARP
Definition: netif.h:88
#define NETIF_FLAG_BROADCAST
Definition: netif.h:72
struct pbuf * pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
Definition: pbuf.c:207
u8_t pbuf_free(struct pbuf *p)
Definition: pbuf.c:618
@ PBUF_POOL
Definition: pbuf.h:61
@ PBUF_RAW
Definition: pbuf.h:54
void * rx_receive_base
Definition: enet.c:25
struct eth_addr * ethaddr
Definition: enet.c:32
int rx_descriptor_rptr
Definition: enet.c:26
volatile uint32_t * tx_descriptor_base
Definition: enet.c:28
void * tx_buffer_base
Definition: enet.c:30
volatile uint32_t * rx_descriptor_base
Definition: enet.c:24
int tx_descriptor_wptr
Definition: enet.c:29
Definition: netif.h:136
u8_t flags
Definition: netif.h:192
char name[2]
Definition: netif.h:194
void * state
Definition: netif.h:172
netif_output_fn output
Definition: netif.h:151
u8_t hwaddr[NETIF_MAX_HWADDR_LEN]
Definition: netif.h:190
u16_t mtu
Definition: netif.h:186
netif_linkoutput_fn linkoutput
Definition: netif.h:155
u8_t hwaddr_len
Definition: netif.h:188
Definition: pbuf.h:79
u16_t tot_len
Definition: pbuf.h:93
struct pbuf * next
Definition: pbuf.h:81
u16_t len
Definition: pbuf.h:96
void * payload
Definition: pbuf.h:84
void mdelay(int u)
Definition: time.c:17
void udelay(int u)
Definition: time.c:12
void xenon_config_get_mac_addr(unsigned char *hwaddr)
Definition: xenon_config.c:74
void xenon_gpio_control(uint32_t reg, uint32_t clear, uint32_t set)
Definition: xenon_gpio.c:6
union @15 data