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");
278 else
279 printf("link still down.\n");
280#endif
281
282
283// write32n(0xea001428, 0x01805508);
284 write32n(0xea001428, 0x01005508);
285 write32n(0xea001410, __builtin_bswap32(0x00101c11)); // enable RX
286 write32n(0xea001400, __builtin_bswap32(0x00001c01)); // enable TX
287
288 return 0;
289}
290
291static struct pbuf *enet_linkinput(struct enet_context *context)
292{
293 volatile uint32_t *d = context->rx_descriptor_base + context->rx_descriptor_rptr * 4;
294 memdcbf((void*)d, 0x10);
295 if (__builtin_bswap32(d[1]) & 0x80000000) /* check ownership */
296 {
297// printf("no data!\n");
298 return 0;
299 }
300
301// printf("RX descriptor %d contains data!\n", context->rx_descriptor_rptr);
302// printf("%08x %08x %08x %08x\n",
303// __builtin_bswap32(d[0]),
304// __builtin_bswap32(d[1]),
305// __builtin_bswap32(d[2]),
306// __builtin_bswap32(d[3]));
307
308 int size = __builtin_bswap32(d[0]) & 0xFFFF;
309 void *phys_addr = context->rx_receive_base + context->rx_descriptor_rptr * MTU;
310 memdcbf(phys_addr, size);
311
312 // hexdump(phys_addr, size);
313
314 struct pbuf *p = pbuf_alloc(PBUF_RAW, size, PBUF_POOL), *q;
315
316 if (p != NULL) {
317 int rptr = 0;
318 /* We iterate over the pbuf chain until we have read the entire
319 packet into the pbuf. */
320 for(q = p; q != NULL; q = q->next) {
321 /* Read enough bytes to fill this pbuf in the chain. The
322 available data in the pbuf is given by the q->len
323 variable. */
324 memcpy(q->payload, phys_addr + rptr, q->len);
325 rptr += q->len;
326 }
327#ifdef LINK_STATS
328 lwip_stats.link.recv++;
329#endif /* LINK_STATS */
330 } else {
331#ifdef LINK_STATS
332 lwip_stats.link.memerr++;
333 lwip_stats.link.drop++;
334#endif /* LINK_STATS */
335 }
336
337 /* reclaim descriptor */
338 d[2] = __builtin_bswap32(virt_to_phys(context->rx_receive_base + context->rx_descriptor_rptr * MTU));
339 d[3] = __builtin_bswap32(MTU | ((context->rx_descriptor_rptr == RX_DESCRIPTOR_NUM - 1) ? 0x80000000 : 0));
340 d[0] = __builtin_bswap32(0);
341 d[1] = __builtin_bswap32(0xc0000000);
342 memdcbst((void*)d, 0x10);
343
344 context->rx_descriptor_rptr++;
346
347 return p;
348}
349
350static err_t enet_linkoutput(struct netif *netif, struct pbuf *p)
351{
352 struct pbuf *q;
353 struct enet_context *context = (struct enet_context *) netif->state;
354
355// printf("enet linkoutput\n");
356
357 void *dstptr = context->tx_buffer_base + context->tx_descriptor_wptr * MTU;
358 int offset = 0;
359
360 for(q = p; q != NULL; q = q->next) {
361 memcpy(dstptr + offset, q->payload, q->len);
362 offset += q->len;
363 }
364
365 memdcbst((void*)dstptr, p->tot_len);
366 tx_data(context, dstptr, p->tot_len);
367
368// printf("ok, data transmitted!\n");
369
370 return 0;
371}
372
373/*
374static err_t
375enet_output(struct netif *netif, struct pbuf *p,
376 struct ip_addr_t *ipaddr)
377{
378// printf("ENET OUTPUT\n");
379 //return etharp_output(netif, ipaddr, p);
380 return etharp_output(netif, p, ipaddr); //lwip 1.3.0
381}
382*/
383
384static void
385enet_input(struct netif *netif)
386{
387 struct enet_context *context = (struct enet_context *) netif->state;
388 struct eth_hdr *ethhdr;
389 struct pbuf *p;
390
391 p = enet_linkinput(context);
392
393 if (p == NULL)
394 return;
395
396#if LINK_STATS
397 lwip_stats.link.recv++;
398#endif /* LINK_STATS */
399
400 ethhdr = p->payload;
401
402 /* pass to network layer */
403 if (ethernet_input(p, netif) != ERR_OK) {
404 pbuf_free(p);
405 p = NULL;
406 }
407}
408
409int cnt;
410
411void
413{
414// printf("\r%08x", mfdec());
415 enet_input(netif);
416}
417
418
419void enet_quiesce(void)
420{
421 write32n(0xea001400, 0);
422 write32n(0xea001410, 0);
423}
#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:412
#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:419
int cnt
Definition: enet.c:409
#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:536
u32 size
Definition: iso9660.c:537
u32 uint32_t
Definition: libfdt_env.h:11
void * mem_malloc(mem_size_t size)
Definition: mem.c:494
#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