1 |
349 |
julius |
//////////////////////////////////////////////////////////////////////
|
2 |
|
|
//// ////
|
3 |
|
|
//// Interrupt-driven Ethernet MAC test code for use on board ////
|
4 |
|
|
//// ////
|
5 |
|
|
//// Description ////
|
6 |
|
|
//// Controllable ping program - also responds to ARP requests ////
|
7 |
|
|
//// ////
|
8 |
|
|
//// Author(s): ////
|
9 |
|
|
//// - jb, jb@orsoc.se, with parts taken from Linux kernel ////
|
10 |
|
|
//// open_eth driver. ////
|
11 |
|
|
//// ////
|
12 |
|
|
//// ////
|
13 |
|
|
//////////////////////////////////////////////////////////////////////
|
14 |
|
|
//// ////
|
15 |
|
|
//// Copyright (C) 2009 Authors and OPENCORES.ORG ////
|
16 |
|
|
//// ////
|
17 |
|
|
//// This source file may be used and distributed without ////
|
18 |
|
|
//// restriction provided that this copyright statement is not ////
|
19 |
|
|
//// removed from the file and that any derivative work contains ////
|
20 |
|
|
//// the original copyright notice and the associated disclaimer. ////
|
21 |
|
|
//// ////
|
22 |
|
|
//// This source file is free software; you can redistribute it ////
|
23 |
|
|
//// and/or modify it under the terms of the GNU Lesser General ////
|
24 |
|
|
//// Public License as published by the Free Software Foundation; ////
|
25 |
|
|
//// either version 2.1 of the License, or (at your option) any ////
|
26 |
|
|
//// later version. ////
|
27 |
|
|
//// ////
|
28 |
|
|
//// This source is distributed in the hope that it will be ////
|
29 |
|
|
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
|
30 |
|
|
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
|
31 |
|
|
//// PURPOSE. See the GNU Lesser General Public License for more ////
|
32 |
|
|
//// details. ////
|
33 |
|
|
//// ////
|
34 |
|
|
//// You should have received a copy of the GNU Lesser General ////
|
35 |
|
|
//// Public License along with this source; if not, download it ////
|
36 |
|
|
//// from http://www.opencores.org/lgpl.shtml ////
|
37 |
|
|
//// ////
|
38 |
|
|
//////////////////////////////////////////////////////////////////////
|
39 |
|
|
|
40 |
408 |
julius |
#include "cpu-utils.h"
|
41 |
349 |
julius |
#include "board.h"
|
42 |
|
|
#include "int.h"
|
43 |
|
|
#include "uart.h"
|
44 |
409 |
julius |
#include "ethmac.h"
|
45 |
349 |
julius |
#include "printf.h"
|
46 |
|
|
#include "eth-phy-mii.h"
|
47 |
|
|
|
48 |
|
|
volatile unsigned tx_done;
|
49 |
|
|
static int next_tx_buf_num;
|
50 |
|
|
|
51 |
496 |
julius |
#define OUR_IP_BYTES 0xc0,0xa8,0x64,0x9b // 192.168.100.155
|
52 |
|
|
#define OUR_IP_LONG 0xc0a8649b
|
53 |
349 |
julius |
|
54 |
496 |
julius |
//#define OUR_IP_BYTES 0xc0,0xa8,0x0,0x5a // 192.168.0.90
|
55 |
|
|
//#define OUR_IP_LONG 0xc0a8005a
|
56 |
408 |
julius |
|
57 |
411 |
julius |
//#define OUR_IP_BYTES 0xc0,0xa8,0x1,0x22 // 192.168.1.34
|
58 |
|
|
//#define OUR_IP_LONG 0xc0a80122
|
59 |
|
|
|
60 |
479 |
julius |
//#define OUR_IP_BYTES 0xc0,0xa8,0x1,0x2 // 192.168.1.2
|
61 |
|
|
//#define OUR_IP_LONG 0xc0a80102
|
62 |
408 |
julius |
|
63 |
415 |
julius |
//#define OUR_IP_BYTES 0xac,0x1e,0x0,0x2 // 172.30.0.2
|
64 |
|
|
//#define OUR_IP_LONG 0xac1e0002
|
65 |
|
|
|
66 |
349 |
julius |
static char our_ip[4] = {OUR_IP_BYTES};
|
67 |
|
|
|
68 |
496 |
julius |
#define DEST_IP_BYTES 0xc0,0xa8,0x64,0x69 // 192 .168.100.105
|
69 |
479 |
julius |
//#define DEST_IP_BYTES 0xc0,0xa8,0x01,0x08 // 192 .168.1.8
|
70 |
496 |
julius |
//#define DEST_IP_BYTES 0xc0,0xa8,0x00,0x0f // 192 .168.0.15
|
71 |
415 |
julius |
//#define DEST_IP_BYTES 0xac,0x1e,0x0,0x01 // 172.30.0.1
|
72 |
349 |
julius |
|
73 |
496 |
julius |
#define BCAST_DEST_IP_BYTES 0xc0,0xa8,0x64,0xff // 192.168.100.255
|
74 |
|
|
//#define BCAST_DEST_IP_BYTES 0xc0,0xa8,0x01,0xff // 192.168.1.255
|
75 |
|
|
//#define BCAST_DEST_IP_BYTES 0xc0,0xa8,0x00,0xff // 192.168.0.255
|
76 |
435 |
julius |
|
77 |
349 |
julius |
/* Functions in this file */
|
78 |
|
|
void ethmac_setup(void);
|
79 |
|
|
void oeth_printregs(void);
|
80 |
|
|
void ethphy_init(void);
|
81 |
|
|
void oeth_dump_bds();
|
82 |
|
|
/* Interrupt functions */
|
83 |
|
|
void oeth_interrupt(void);
|
84 |
|
|
static void oeth_rx(void);
|
85 |
|
|
static void oeth_tx(void);
|
86 |
411 |
julius |
/* Function to calculate checksum of ping responses we send */
|
87 |
|
|
unsigned short calculate_checksum(char* dats, unsigned int len) ;
|
88 |
349 |
julius |
|
89 |
411 |
julius |
// Global used to control whether we print out packets as we receive them
|
90 |
|
|
int print_packet_contents;
|
91 |
349 |
julius |
|
92 |
|
|
/* Let the ethernet packets use a space beginning here for buffering */
|
93 |
|
|
#define ETH_BUFF_BASE 0x01000000
|
94 |
|
|
|
95 |
|
|
|
96 |
|
|
#define RXBUFF_PREALLOC 1
|
97 |
|
|
#define TXBUFF_PREALLOC 1
|
98 |
|
|
//#undef RXBUFF_PREALLOC
|
99 |
|
|
//#undef TXBUFF_PREALLOC
|
100 |
|
|
|
101 |
|
|
/* The transmitter timeout
|
102 |
|
|
*/
|
103 |
|
|
#define TX_TIMEOUT (2*HZ)
|
104 |
|
|
|
105 |
|
|
/* Buffer number (must be 2^n)
|
106 |
|
|
*/
|
107 |
425 |
julius |
#define OETH_RXBD_NUM 64
|
108 |
|
|
#define OETH_TXBD_NUM 64
|
109 |
349 |
julius |
#define OETH_RXBD_NUM_MASK (OETH_RXBD_NUM-1)
|
110 |
|
|
#define OETH_TXBD_NUM_MASK (OETH_TXBD_NUM-1)
|
111 |
|
|
|
112 |
|
|
/* Buffer size
|
113 |
|
|
*/
|
114 |
|
|
#define OETH_RX_BUFF_SIZE 2048
|
115 |
|
|
#define OETH_TX_BUFF_SIZE 2048
|
116 |
|
|
|
117 |
|
|
/* Buffer size (if not XXBUF_PREALLOC
|
118 |
|
|
*/
|
119 |
|
|
#define MAX_FRAME_SIZE 0x600
|
120 |
|
|
//#define MAX_FRAME_SIZE 2500
|
121 |
|
|
|
122 |
|
|
/* The buffer descriptors track the ring buffers.
|
123 |
|
|
*/
|
124 |
|
|
struct oeth_private {
|
125 |
|
|
//struct sk_buff* rx_skbuff[OETH_RXBD_NUM];
|
126 |
|
|
//struct sk_buff* tx_skbuff[OETH_TXBD_NUM];
|
127 |
|
|
|
128 |
|
|
unsigned short tx_next;/* Next buffer to be sent */
|
129 |
|
|
unsigned short tx_last;/* Next buffer to be checked if packet sent */
|
130 |
|
|
unsigned short tx_full;/* Buffer ring fuul indicator */
|
131 |
|
|
unsigned short rx_cur; /* Next buffer to be checked if packet received */
|
132 |
|
|
|
133 |
|
|
oeth_regs *regs; /* Address of controller registers. */
|
134 |
|
|
oeth_bd *rx_bd_base; /* Address of Rx BDs. */
|
135 |
|
|
oeth_bd *tx_bd_base; /* Address of Tx BDs. */
|
136 |
|
|
|
137 |
|
|
// struct net_device_stats stats;
|
138 |
|
|
};
|
139 |
|
|
|
140 |
|
|
void oeth_printregs(void)
|
141 |
|
|
{
|
142 |
|
|
volatile oeth_regs *regs;
|
143 |
|
|
regs = (oeth_regs *)(OETH_REG_BASE);
|
144 |
|
|
|
145 |
|
|
printf("Oeth regs: Mode Register : 0x%lx\n",
|
146 |
|
|
(unsigned long) regs->moder); /* Mode Register */
|
147 |
|
|
printf("Oeth regs: Interrupt Source Register 0x%lx\n",
|
148 |
|
|
(unsigned long) regs->int_src); /* Interrupt Source Register */
|
149 |
|
|
printf("Oeth regs: Interrupt Mask Register 0x%lx\n",
|
150 |
|
|
(unsigned long) regs->int_mask); /* Interrupt Mask Register */
|
151 |
|
|
printf("Oeth regs: Back to Bak Inter Packet Gap Register 0x%lx\n",
|
152 |
|
|
(unsigned long) regs->ipgt); /* Back to Bak Inter Packet Gap Register */
|
153 |
|
|
printf("Oeth regs: Non Back to Back Inter Packet Gap Register 1 0x%lx\n",
|
154 |
|
|
(unsigned long) regs->ipgr1); /* Non Back to Back Inter Packet Gap Register 1 */
|
155 |
|
|
printf("Oeth regs: Non Back to Back Inter Packet Gap Register 2 0x%lx\n",
|
156 |
|
|
(unsigned long) regs->ipgr2); /* Non Back to Back Inter Packet Gap Register 2 */
|
157 |
|
|
printf("Oeth regs: Packet Length Register (min. and max.) 0x%lx\n",
|
158 |
|
|
(unsigned long) regs->packet_len); /* Packet Length Register (min. and max.) */
|
159 |
|
|
printf("Oeth regs: Collision and Retry Configuration Register 0x%lx\n",
|
160 |
|
|
(unsigned long) regs->collconf); /* Collision and Retry Configuration Register */
|
161 |
|
|
printf("Oeth regs: Transmit Buffer Descriptor Number Register 0x%lx\n",
|
162 |
|
|
(unsigned long) regs->tx_bd_num); /* Transmit Buffer Descriptor Number Register */
|
163 |
|
|
printf("Oeth regs: Control Module Mode Register 0x%lx\n",
|
164 |
|
|
(unsigned long) regs->ctrlmoder); /* Control Module Mode Register */
|
165 |
|
|
printf("Oeth regs: MII Mode Register 0x%lx\n",
|
166 |
|
|
(unsigned long) regs->miimoder); /* MII Mode Register */
|
167 |
|
|
printf("Oeth regs: MII Command Register 0x%lx\n",
|
168 |
|
|
(unsigned long) regs->miicommand); /* MII Command Register */
|
169 |
|
|
printf("Oeth regs: MII Address Register 0x%lx\n",
|
170 |
|
|
(unsigned long) regs->miiaddress); /* MII Address Register */
|
171 |
|
|
printf("Oeth regs: MII Transmit Data Register 0x%lx\n",
|
172 |
|
|
(unsigned long) regs->miitx_data); /* MII Transmit Data Register */
|
173 |
|
|
printf("Oeth regs: MII Receive Data Register 0x%lx\n",
|
174 |
|
|
(unsigned long) regs->miirx_data); /* MII Receive Data Register */
|
175 |
|
|
printf("Oeth regs: MII Status Register 0x%lx\n",
|
176 |
|
|
(unsigned long) regs->miistatus); /* MII Status Register */
|
177 |
|
|
printf("Oeth regs: MAC Individual Address Register 0 0x%lx\n",
|
178 |
|
|
(unsigned long) regs->mac_addr0); /* MAC Individual Address Register 0 */
|
179 |
|
|
printf("Oeth regs: MAC Individual Address Register 1 0x%lx\n",
|
180 |
|
|
(unsigned long) regs->mac_addr1); /* MAC Individual Address Register 1 */
|
181 |
|
|
printf("Oeth regs: Hash Register 0 0x%lx\n",
|
182 |
|
|
(unsigned long) regs->hash_addr0); /* Hash Register 0 */
|
183 |
|
|
printf("Oeth regs: Hash Register 1 0x%lx\n",
|
184 |
|
|
(unsigned long) regs->hash_addr1); /* Hash Register 1 */
|
185 |
|
|
|
186 |
|
|
}
|
187 |
|
|
|
188 |
|
|
static int last_char;
|
189 |
|
|
|
190 |
|
|
void spin_cursor(void)
|
191 |
|
|
{
|
192 |
|
|
#ifdef RTLSIM
|
193 |
|
|
return;
|
194 |
|
|
#endif
|
195 |
|
|
volatile unsigned int i; // So the loop doesn't get optimised away
|
196 |
|
|
printf(" \r");
|
197 |
|
|
if (last_char == 0)
|
198 |
|
|
printf("/");
|
199 |
|
|
else if (last_char == 1)
|
200 |
|
|
printf("-");
|
201 |
|
|
else if (last_char == 2)
|
202 |
|
|
printf("\\");
|
203 |
|
|
else if (last_char == 3)
|
204 |
|
|
printf("|");
|
205 |
|
|
else if (last_char == 4)
|
206 |
|
|
printf("/");
|
207 |
|
|
else if (last_char == 5)
|
208 |
|
|
printf("-");
|
209 |
|
|
else if (last_char == 6)
|
210 |
|
|
printf("\\");
|
211 |
|
|
else if (last_char == 7)
|
212 |
|
|
{
|
213 |
|
|
printf("|");
|
214 |
|
|
last_char=-1;
|
215 |
|
|
}
|
216 |
|
|
|
217 |
|
|
last_char++;
|
218 |
|
|
|
219 |
|
|
for(i=0;i<150000;i++);
|
220 |
|
|
|
221 |
|
|
}
|
222 |
|
|
|
223 |
|
|
#define PHYNUM 7
|
224 |
|
|
|
225 |
|
|
/* Scan the MIIM bus for PHYs */
|
226 |
|
|
void scan_ethphys(void)
|
227 |
|
|
{
|
228 |
|
|
unsigned int phynum,regnum, i;
|
229 |
|
|
|
230 |
|
|
volatile oeth_regs *regs;
|
231 |
|
|
regs = (oeth_regs *)(OETH_REG_BASE);
|
232 |
|
|
|
233 |
|
|
regs->miitx_data = 0;
|
234 |
|
|
|
235 |
|
|
for(phynum=0;phynum<32;phynum++)
|
236 |
|
|
{
|
237 |
|
|
for (regnum=0;regnum<8;regnum++)
|
238 |
|
|
{
|
239 |
|
|
printf("scan_ethphys: phy %d r%d ",phynum, regnum);
|
240 |
|
|
|
241 |
|
|
/* Now actually perform the read on the MIIM bus*/
|
242 |
|
|
regs->miiaddress = (regnum << 8) | phynum; /* Basic Control Register */
|
243 |
|
|
regs->miicommand = OETH_MIICOMMAND_RSTAT;
|
244 |
|
|
|
245 |
|
|
while(!(regs->miistatus & OETH_MIISTATUS_BUSY)); /* Wait for command to be registered*/
|
246 |
|
|
|
247 |
|
|
regs->miicommand = 0;
|
248 |
|
|
|
249 |
|
|
while(regs->miistatus & OETH_MIISTATUS_BUSY);
|
250 |
|
|
|
251 |
|
|
printf("%x\n",regs->miirx_data);
|
252 |
|
|
}
|
253 |
|
|
}
|
254 |
|
|
}
|
255 |
|
|
|
256 |
|
|
|
257 |
|
|
/* Scan the MIIM bus for PHYs */
|
258 |
|
|
void scan_ethphy(unsigned int phynum)
|
259 |
|
|
{
|
260 |
|
|
unsigned int regnum, i;
|
261 |
|
|
|
262 |
|
|
volatile oeth_regs *regs;
|
263 |
|
|
regs = (oeth_regs *)(OETH_REG_BASE);
|
264 |
|
|
|
265 |
|
|
regs->miitx_data = 0;
|
266 |
|
|
|
267 |
415 |
julius |
for (regnum=0;regnum<32;regnum++)
|
268 |
349 |
julius |
{
|
269 |
|
|
printf("scan_ethphy%d: r%x ",phynum, regnum);
|
270 |
|
|
|
271 |
|
|
/* Now actually perform the read on the MIIM bus*/
|
272 |
|
|
regs->miiaddress = (regnum << 8) | phynum; /* Basic Control Register */
|
273 |
|
|
regs->miicommand = OETH_MIICOMMAND_RSTAT;
|
274 |
|
|
|
275 |
|
|
while(!(regs->miistatus & OETH_MIISTATUS_BUSY)); /* Wait for command to be registered*/
|
276 |
|
|
|
277 |
|
|
regs->miicommand = 0;
|
278 |
|
|
|
279 |
|
|
while(regs->miistatus & OETH_MIISTATUS_BUSY);
|
280 |
|
|
|
281 |
|
|
printf("%x\n",regs->miirx_data);
|
282 |
|
|
}
|
283 |
|
|
|
284 |
|
|
}
|
285 |
|
|
|
286 |
|
|
|
287 |
|
|
|
288 |
|
|
void ethmac_scanstatus(void)
|
289 |
|
|
{
|
290 |
|
|
volatile oeth_regs *regs;
|
291 |
|
|
regs = (oeth_regs *)(OETH_REG_BASE);
|
292 |
|
|
|
293 |
|
|
|
294 |
|
|
printf("Oeth: regs->miistatus %x regs->miirx_data %x\n",regs->miistatus, regs->miirx_data);
|
295 |
|
|
regs->miiaddress = 0;
|
296 |
|
|
regs->miitx_data = 0;
|
297 |
|
|
regs->miicommand = OETH_MIICOMMAND_SCANSTAT;
|
298 |
|
|
printf("Oeth: regs->miiaddress %x regs->miicommand %x\n",regs->miiaddress, regs->miicommand);
|
299 |
|
|
//regs->miicommand = 0;
|
300 |
|
|
volatile int i; for(i=0;i<1000;i++);
|
301 |
|
|
while(regs->miistatus & OETH_MIISTATUS_BUSY) ;
|
302 |
|
|
//spin_cursor();
|
303 |
|
|
//printf("\r");
|
304 |
|
|
//or32_exit(0);
|
305 |
|
|
}
|
306 |
|
|
|
307 |
|
|
void
|
308 |
|
|
eth_mii_write(char phynum, short regnum, short data)
|
309 |
|
|
{
|
310 |
|
|
static volatile oeth_regs *regs = (oeth_regs *)(OETH_REG_BASE);
|
311 |
|
|
regs->miiaddress = (regnum << 8) | phynum;
|
312 |
|
|
regs->miitx_data = data;
|
313 |
|
|
regs->miicommand = OETH_MIICOMMAND_WCTRLDATA;
|
314 |
|
|
regs->miicommand = 0;
|
315 |
|
|
while(regs->miistatus & OETH_MIISTATUS_BUSY);
|
316 |
|
|
}
|
317 |
|
|
|
318 |
|
|
short
|
319 |
|
|
eth_mii_read(char phynum, short regnum)
|
320 |
|
|
{
|
321 |
|
|
static volatile oeth_regs *regs = (oeth_regs *)(OETH_REG_BASE);
|
322 |
|
|
regs->miiaddress = (regnum << 8) | phynum;
|
323 |
|
|
regs->miicommand = OETH_MIICOMMAND_RSTAT;
|
324 |
|
|
regs->miicommand = 0;
|
325 |
|
|
while(regs->miistatus & OETH_MIISTATUS_BUSY);
|
326 |
|
|
|
327 |
|
|
return regs->miirx_data;
|
328 |
|
|
}
|
329 |
|
|
|
330 |
|
|
|
331 |
|
|
void
|
332 |
|
|
ethphy_reset(int phynum)
|
333 |
|
|
{
|
334 |
|
|
eth_mii_write(phynum, MII_BMCR,
|
335 |
|
|
(eth_mii_read(phynum,MII_BMCR)|BMCR_RESET));
|
336 |
|
|
}
|
337 |
|
|
|
338 |
|
|
|
339 |
|
|
void
|
340 |
|
|
ethphy_reneg(int phynum)
|
341 |
|
|
{
|
342 |
|
|
eth_mii_write(phynum, MII_BMCR,
|
343 |
|
|
(eth_mii_read(phynum,MII_BMCR)|BMCR_ANRESTART));
|
344 |
|
|
}
|
345 |
|
|
|
346 |
|
|
void
|
347 |
|
|
ethphy_set_10mbit(int phynum)
|
348 |
|
|
{
|
349 |
|
|
// Hardset PHY to just use 10Mbit mode
|
350 |
|
|
short cr = eth_mii_read(phynum, MII_BMCR);
|
351 |
|
|
cr &= ~BMCR_ANENABLE; // Clear auto negotiate bit
|
352 |
|
|
cr &= ~BMCR_SPEED100; // Clear fast eth. bit
|
353 |
|
|
eth_mii_write(phynum, MII_BMCR, cr);
|
354 |
|
|
}
|
355 |
|
|
|
356 |
|
|
void
|
357 |
|
|
ethphy_set_100mbit(int phynum)
|
358 |
|
|
{
|
359 |
|
|
// Hardset PHY to just use 10Mbit mode
|
360 |
|
|
short cr = eth_mii_read(phynum, MII_BMCR);
|
361 |
|
|
cr &= !BMCR_ANENABLE; // Clear auto negotiate bit
|
362 |
|
|
cr |= BMCR_SPEED100; // Clear fast eth. bit
|
363 |
|
|
eth_mii_write(phynum, MII_BMCR, cr);
|
364 |
|
|
}
|
365 |
|
|
|
366 |
|
|
void
|
367 |
|
|
ethphy_set_autoneg(int phynum)
|
368 |
|
|
{
|
369 |
|
|
// Hardset PHY to just use 10Mbit mode
|
370 |
|
|
short cr = eth_mii_read(phynum, MII_BMCR);
|
371 |
|
|
cr |= BMCR_ANENABLE; // Clear auto negotiate bit
|
372 |
|
|
eth_mii_write(phynum, MII_BMCR, cr);
|
373 |
|
|
}
|
374 |
|
|
|
375 |
|
|
|
376 |
|
|
|
377 |
|
|
void m88e111_config_init(int phyaddr)
|
378 |
|
|
{
|
379 |
|
|
short ctl;
|
380 |
|
|
short adv;
|
381 |
|
|
#if 1
|
382 |
|
|
// Soft reset
|
383 |
|
|
eth_mii_write(phyaddr, MII_BMCR, BMCR_RESET);
|
384 |
|
|
while(eth_mii_read(phyaddr, MII_BMCR) & BMCR_RESET);
|
385 |
|
|
|
386 |
|
|
ctl = eth_mii_read(phyaddr, MII_BMCR);
|
387 |
|
|
ctl &= ~(BMCR_SPD2);
|
388 |
|
|
eth_mii_write(phyaddr, MII_BMCR, ctl);
|
389 |
|
|
|
390 |
|
|
eth_mii_read(phyaddr, MII_ADVERTISE);
|
391 |
|
|
adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4 | ADVERTISE_1000XFULL
|
392 |
|
|
|ADVERTISE_1000XHALF | ADVERTISE_1000XPAUSE |
|
393 |
|
|
ADVERTISE_1000XPSE_ASYM);
|
394 |
|
|
adv |= ADVERTISE_10HALF;
|
395 |
|
|
adv |= ADVERTISE_10FULL;
|
396 |
|
|
adv |= ADVERTISE_100HALF;
|
397 |
|
|
adv |= ADVERTISE_100FULL;
|
398 |
|
|
eth_mii_write(phyaddr, MII_ADVERTISE, adv);
|
399 |
|
|
// Disable gigabit???
|
400 |
|
|
adv = eth_mii_read(phyaddr, MII_M1011_PHY_SPEC_CONTROL);
|
401 |
|
|
adv &= ~(MII_1000BASETCONTROL_FULLDUPLEXCAP |
|
402 |
|
|
MII_1000BASETCONTROL_HALFDUPLEXCAP);
|
403 |
|
|
eth_mii_write(phyaddr, MII_M1011_PHY_SPEC_CONTROL, adv);
|
404 |
|
|
// Even more disable gigabit?!
|
405 |
|
|
adv = eth_mii_read(phyaddr, MII_CTRL1000);
|
406 |
|
|
adv &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF);
|
407 |
|
|
eth_mii_write(phyaddr, MII_CTRL1000, adv);
|
408 |
|
|
|
409 |
|
|
// Restart autoneg
|
410 |
|
|
printf("Resetting phy...\n");
|
411 |
|
|
eth_mii_write(phyaddr, MII_BMCR, BMCR_RESET);
|
412 |
|
|
ctl = eth_mii_read(phyaddr, MII_BMCR);
|
413 |
|
|
ctl |= (BMCR_ANENABLE | BMCR_ANRESTART);
|
414 |
|
|
eth_mii_write(phyaddr, MII_BMCR, ctl);
|
415 |
|
|
#endif
|
416 |
|
|
|
417 |
|
|
#if 0
|
418 |
|
|
// Adapted from kernel: drivers/net/phy/marvell.c
|
419 |
|
|
// Soft reset
|
420 |
|
|
eth_mii_write(phyaddr, MII_BMCR, BMCR_RESET);
|
421 |
|
|
|
422 |
|
|
eth_mii_write(phyaddr, 0x1d, 0x1f);
|
423 |
|
|
eth_mii_write(phyaddr, 0x1e, 0x200c);
|
424 |
|
|
eth_mii_write(phyaddr, 0x1d, 0x5);
|
425 |
|
|
eth_mii_write(phyaddr, 0x1e, 0);
|
426 |
|
|
eth_mii_write(phyaddr, 0x1e, 0x100);
|
427 |
|
|
#define MII_M1011_PHY_SCR 0x10
|
428 |
|
|
#define MII_M1011_PHY_SCR_AUTO_CROSS 0x0060
|
429 |
|
|
eth_mii_write(phyaddr, MII_M1011_PHY_SCR,
|
430 |
|
|
MII_M1011_PHY_SCR_AUTO_CROSS);
|
431 |
|
|
#define MII_M1111_PHY_LED_CONTROL 0x18
|
432 |
|
|
#define MII_M1111_PHY_LED_DIRECT 0x4100
|
433 |
|
|
eth_mii_write(phyaddr, MII_M1111_PHY_LED_CONTROL,
|
434 |
|
|
MII_M1111_PHY_LED_DIRECT);
|
435 |
|
|
|
436 |
|
|
adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4 | ADVERTISE_PAUSE_CAP |
|
437 |
|
|
ADVERTISE_PAUSE_ASYM);
|
438 |
|
|
adv |= ADVERTISE_10HALF;
|
439 |
|
|
adv |= ADVERTISE_10FULL;
|
440 |
|
|
adv |= ADVERTISE_100HALF;
|
441 |
|
|
adv |= ADVERTISE_100FULL;
|
442 |
|
|
adv |= ADVERTISE_PAUSE_CAP;
|
443 |
|
|
adv |= ADVERTISE_PAUSE_ASYM;
|
444 |
|
|
eth_mii_write(phyaddr, MII_ADVERTISE, adv);
|
445 |
|
|
|
446 |
|
|
|
447 |
|
|
ctl = eth_mii_read(phyaddr, MII_BMCR);
|
448 |
|
|
ctl |= (BMCR_ANENABLE | BMCR_ANRESTART);
|
449 |
|
|
eth_mii_write(phyaddr, MII_BMCR, ctl);
|
450 |
|
|
|
451 |
|
|
#endif
|
452 |
|
|
|
453 |
|
|
#if 0
|
454 |
|
|
ctl = eth_mii_read(phyaddr, MII_BMCR);
|
455 |
|
|
ctl &= ~(BMCR_ANENABLE); // Disable autoneg...
|
456 |
|
|
// Try forcing config
|
457 |
|
|
ctl = BMCR_SPEED100 | BMCR_FULLDPLX;
|
458 |
|
|
eth_mii_write(phyaddr, MII_BMCR, ctl);
|
459 |
|
|
|
460 |
|
|
|
461 |
|
|
|
462 |
|
|
|
463 |
|
|
#endif
|
464 |
|
|
|
465 |
|
|
}
|
466 |
|
|
|
467 |
|
|
|
468 |
|
|
void ethphy_print_status(int phyaddr)
|
469 |
|
|
{
|
470 |
|
|
short regnum, ctl;
|
471 |
|
|
int bitnum;
|
472 |
|
|
int bitset;
|
473 |
|
|
printf("phyaddr %d\n",phyaddr);
|
474 |
|
|
for (regnum = 0;regnum<16; regnum++)
|
475 |
|
|
{
|
476 |
|
|
ctl = eth_mii_read(phyaddr, regnum);
|
477 |
|
|
printf("\treg 0x%x: ", regnum);
|
478 |
|
|
switch(regnum)
|
479 |
|
|
{
|
480 |
|
|
case 0:
|
481 |
|
|
printf("basic control\n");
|
482 |
|
|
for(bitnum = 0; bitnum<16;bitnum++)
|
483 |
|
|
{
|
484 |
|
|
bitset = !!(ctl & (1<<bitnum));
|
485 |
|
|
switch(bitnum)
|
486 |
|
|
{
|
487 |
|
|
case 0:
|
488 |
|
|
printf("\t\tbit%d:\t%d \t(disable transmitter)\n",bitnum,bitset);
|
489 |
|
|
break;
|
490 |
|
|
case 6:
|
491 |
|
|
printf("\t\tbit%d:\t%d \t(msb speed (1000))\n",bitnum,bitset);
|
492 |
|
|
break;
|
493 |
|
|
case 7:
|
494 |
|
|
printf("\t\tbit%d:\t%d \t(collision test)\n",bitnum,bitset);
|
495 |
|
|
break;
|
496 |
|
|
case 8:
|
497 |
|
|
printf("\t\tbit%d:\t%d \t(duplex mode)\n",bitnum,bitset);
|
498 |
|
|
break;
|
499 |
|
|
case 9:
|
500 |
|
|
printf("\t\tbit%d:\t%d \t(restart autoneg)\n",bitnum,bitset);
|
501 |
|
|
break;
|
502 |
|
|
case 10:
|
503 |
|
|
printf("\t\tbit%d:\t%d \t(isloate)\n",bitnum,bitset);
|
504 |
|
|
break;
|
505 |
|
|
case 11:
|
506 |
|
|
printf("\t\tbit%d:\t%d \t(power down)\n",bitnum,bitset);
|
507 |
|
|
break;
|
508 |
|
|
case 12:
|
509 |
|
|
printf("\t\tbit%d:\t%d \t(autoneg enable)\n",bitnum,bitset);
|
510 |
|
|
break;
|
511 |
|
|
case 13:
|
512 |
|
|
printf("\t\tbit%d:\t%d \t(speed select)\n",bitnum,bitset);
|
513 |
|
|
break;
|
514 |
|
|
case 14:
|
515 |
|
|
printf("\t\tbit%d:\t%d \t(loop back)\n",bitnum,bitset);
|
516 |
|
|
break;
|
517 |
|
|
case 15:
|
518 |
|
|
printf("\t\tbit%d:\t%d \t(reset)\n",bitnum,bitset);
|
519 |
|
|
break;
|
520 |
|
|
default:
|
521 |
|
|
break;
|
522 |
|
|
}
|
523 |
|
|
}
|
524 |
|
|
break;
|
525 |
|
|
case 1:
|
526 |
|
|
printf("basic status\n");
|
527 |
|
|
for(bitnum = 0; bitnum<16;bitnum++)
|
528 |
|
|
{
|
529 |
|
|
bitset = !!(ctl & (1<<bitnum));
|
530 |
|
|
switch(bitnum)
|
531 |
|
|
{
|
532 |
|
|
case 0:
|
533 |
|
|
printf("\t\tbit%d:\t%d \t(extend capability)\n",bitnum,bitset);
|
534 |
|
|
break;
|
535 |
|
|
case 1:
|
536 |
|
|
printf("\t\tbit%d:\t%d \t(jabber detect)\n",bitnum,bitset);
|
537 |
|
|
break;
|
538 |
|
|
case 2:
|
539 |
|
|
printf("\t\tbit%d:\t%d \t(link status)\n",bitnum,bitset);
|
540 |
|
|
break;
|
541 |
|
|
case 3:
|
542 |
|
|
printf("\t\tbit%d:\t%d \t(autoneg capability)\n",bitnum,bitset);
|
543 |
|
|
break;
|
544 |
|
|
case 4:
|
545 |
|
|
printf("\t\tbit%d:\t%d \t(remote fault)\n",bitnum,bitset);
|
546 |
|
|
break;
|
547 |
|
|
case 5:
|
548 |
|
|
printf("\t\tbit%d:\t%d \t(autoneg complete)\n",bitnum,bitset);
|
549 |
|
|
break;
|
550 |
|
|
case 6:
|
551 |
|
|
printf("\t\tbit%d:\t%d \t(no preamble)\n",bitnum,bitset);
|
552 |
|
|
break;
|
553 |
|
|
case 11:
|
554 |
|
|
printf("\t\tbit%d:\t%d \t(10base-t half dup.)\n",bitnum,bitset);
|
555 |
|
|
break;
|
556 |
|
|
case 12:
|
557 |
|
|
printf("\t\tbit%d:\t%d \t(10base-t full dup.)\n",bitnum,bitset);
|
558 |
|
|
break;
|
559 |
|
|
case 13:
|
560 |
|
|
printf("\t\tbit%d:\t%d \t(100base-t half dup.)\n",bitnum,bitset);
|
561 |
|
|
break;
|
562 |
|
|
case 14:
|
563 |
|
|
printf("\t\tbit%d:\t%d \t(100base-t full dup.)\n",bitnum,bitset);
|
564 |
|
|
break;
|
565 |
|
|
case 15:
|
566 |
|
|
printf("\t\tbit%d:\t%d \t(100base-t4)\n",bitnum,bitset);
|
567 |
|
|
break;
|
568 |
|
|
default:
|
569 |
|
|
break;
|
570 |
|
|
|
571 |
|
|
}
|
572 |
|
|
}
|
573 |
|
|
break;
|
574 |
|
|
case 4:
|
575 |
|
|
printf("autoneg advertise reg\n");
|
576 |
|
|
for(bitnum = 0; bitnum<16;bitnum++)
|
577 |
|
|
{
|
578 |
|
|
bitset = !!(ctl & (1<<bitnum));
|
579 |
|
|
switch(bitnum)
|
580 |
|
|
{
|
581 |
|
|
case 5:
|
582 |
|
|
printf("\t\tbit%d:\t%d \t(10mbps cap.)\n",bitnum,bitset);
|
583 |
|
|
break;
|
584 |
|
|
case 6:
|
585 |
|
|
printf("\t\tbit%d:\t%d \t(10base-5 full dup. cap.)\n",bitnum,bitset);
|
586 |
|
|
break;
|
587 |
|
|
case 7:
|
588 |
|
|
printf("\t\tbit%d:\t%d \t(100base-tx cap.)\n",bitnum,bitset);
|
589 |
|
|
break;
|
590 |
|
|
case 8:
|
591 |
|
|
printf("\t\tbit%d:\t%d \t(100base-tx full dup. cap.)\n",bitnum,bitset);
|
592 |
|
|
break;
|
593 |
|
|
case 9:
|
594 |
|
|
printf("\t\tbit%d:\t%d \t(100base-t4 cap.)\n",bitnum,bitset);
|
595 |
|
|
break;
|
596 |
|
|
case 10:
|
597 |
|
|
printf("\t\tbit%d:\t%d \t(pause cap.)\n",bitnum,bitset);
|
598 |
|
|
break;
|
599 |
|
|
case 13:
|
600 |
|
|
printf("\t\tbit%d:\t%d \t(remote fault sup.)\n",bitnum,bitset);
|
601 |
|
|
break;
|
602 |
|
|
case 15:
|
603 |
|
|
printf("\t\tbit%d:\t%d \t(next page cap.)\n",bitnum,bitset);
|
604 |
|
|
break;
|
605 |
|
|
|
606 |
|
|
default:
|
607 |
|
|
break;
|
608 |
|
|
}
|
609 |
|
|
}
|
610 |
|
|
break;
|
611 |
|
|
case 5:
|
612 |
|
|
printf("autoneg link partner ability\n");
|
613 |
|
|
for(bitnum = 0; bitnum<16;bitnum++)
|
614 |
|
|
{
|
615 |
|
|
bitset = !!(ctl & (1<<bitnum));
|
616 |
|
|
switch(bitnum)
|
617 |
|
|
{
|
618 |
|
|
case 5:
|
619 |
|
|
printf("\t\tbit%d:\t%d \t(10mbps cap.)\n",bitnum,bitset);
|
620 |
|
|
break;
|
621 |
|
|
case 6:
|
622 |
|
|
printf("\t\tbit%d:\t%d \t(10base-5 full dup. cap.)\n",bitnum,bitset);
|
623 |
|
|
break;
|
624 |
|
|
case 7:
|
625 |
|
|
printf("\t\tbit%d:\t%d \t(100base-tx cap.)\n",bitnum,bitset);
|
626 |
|
|
break;
|
627 |
|
|
case 8:
|
628 |
|
|
printf("\t\tbit%d:\t%d \t(100base-tx full dup. cap.)\n",bitnum,bitset);
|
629 |
|
|
break;
|
630 |
|
|
case 9:
|
631 |
|
|
printf("\t\tbit%d:\t%d \t(100base-t4 cap.)\n",bitnum,bitset);
|
632 |
|
|
break;
|
633 |
|
|
case 10:
|
634 |
|
|
printf("\t\tbit%d:\t%d \t(pause cap bit0)\n",bitnum,bitset);
|
635 |
|
|
break;
|
636 |
|
|
case 11:
|
637 |
|
|
printf("\t\tbit%d:\t%d \t(pause cap bit1)\n",bitnum,bitset);
|
638 |
|
|
break;
|
639 |
|
|
|
640 |
|
|
case 13:
|
641 |
|
|
printf("\t\tbit%d:\t%d \t(remote fault sup.)\n",bitnum,bitset);
|
642 |
|
|
break;
|
643 |
|
|
case 14:
|
644 |
|
|
printf("\t\tbit%d:\t%d \t(acknowledge)\n",bitnum,bitset);
|
645 |
|
|
break;
|
646 |
|
|
case 15:
|
647 |
|
|
printf("\t\tbit%d:\t%d \t(next page cap.)\n",bitnum,bitset);
|
648 |
|
|
break;
|
649 |
|
|
|
650 |
|
|
default:
|
651 |
|
|
break;
|
652 |
|
|
}
|
653 |
|
|
}
|
654 |
|
|
break;
|
655 |
|
|
case 9:
|
656 |
|
|
printf("1000mbit advertise\n");
|
657 |
|
|
for(bitnum = 0; bitnum<16;bitnum++)
|
658 |
|
|
{
|
659 |
|
|
bitset = !!(ctl & (1<<bitnum));
|
660 |
|
|
switch(bitnum)
|
661 |
|
|
{
|
662 |
|
|
case 8:
|
663 |
|
|
printf("\t\tbit%d:\t%d \t(1000base-t half dup)\n",bitnum,bitset);
|
664 |
|
|
break;
|
665 |
|
|
case 9:
|
666 |
|
|
printf("\t\tbit%d:\t%d \t(1000base-t full dup)\n",bitnum,bitset);
|
667 |
|
|
break;
|
668 |
|
|
default:
|
669 |
|
|
break;
|
670 |
|
|
}
|
671 |
|
|
}
|
672 |
|
|
break;
|
673 |
|
|
case 0xf:
|
674 |
|
|
printf("extended status\n");
|
675 |
|
|
for(bitnum = 0; bitnum<16;bitnum++)
|
676 |
|
|
{
|
677 |
|
|
bitset = !!(ctl & (1<<bitnum));
|
678 |
|
|
switch(bitnum)
|
679 |
|
|
{
|
680 |
|
|
case 12:
|
681 |
|
|
printf("\t\tbit%d:\t%d \t(1000mb half dup.)\n",bitnum,bitset);
|
682 |
|
|
break;
|
683 |
|
|
case 13:
|
684 |
|
|
printf("\t\tbit%d:\t%d \t(1000mb full dup.)\n",bitnum,bitset);
|
685 |
|
|
break;
|
686 |
|
|
default:
|
687 |
|
|
break;
|
688 |
|
|
}
|
689 |
|
|
}
|
690 |
|
|
break;
|
691 |
|
|
/* case 1:
|
692 |
|
|
for(bitnum = 0; bitnum<16;bitnum++)
|
693 |
|
|
{
|
694 |
|
|
bitset = !!(ctl & (1<<bitnum));
|
695 |
|
|
switch(bitnum)
|
696 |
|
|
{
|
697 |
|
|
case 0:
|
698 |
|
|
printf("\t\tbit%d:\t%d \t()\n",bitnum,bitset);
|
699 |
|
|
break;
|
700 |
|
|
default:
|
701 |
|
|
break;
|
702 |
|
|
}
|
703 |
|
|
}
|
704 |
|
|
break;
|
705 |
|
|
*/
|
706 |
|
|
default:
|
707 |
|
|
printf("ignored\n");
|
708 |
|
|
break;
|
709 |
|
|
}
|
710 |
|
|
}
|
711 |
|
|
|
712 |
|
|
|
713 |
|
|
|
714 |
|
|
}
|
715 |
|
|
|
716 |
|
|
void ethphy_init(void)
|
717 |
|
|
{
|
718 |
|
|
|
719 |
|
|
/* Init the Alaska 88E1111 Phy */
|
720 |
|
|
char alaska88e1111_ml501_phynum = 0x7;
|
721 |
|
|
m88e111_config_init(alaska88e1111_ml501_phynum);
|
722 |
|
|
|
723 |
|
|
return;
|
724 |
|
|
|
725 |
|
|
/* Init, reset */
|
726 |
|
|
short ctl = eth_mii_read(alaska88e1111_ml501_phynum, MII_BMCR);
|
727 |
|
|
ctl &= ~(BMCR_FULLDPLX|BMCR_SPEED100|BMCR_SPD2|BMCR_ANENABLE);
|
728 |
|
|
ctl |= BMCR_SPEED100; // 100MBit
|
729 |
|
|
ctl |= BMCR_FULLDPLX; // Full duplex
|
730 |
|
|
eth_mii_write(alaska88e1111_ml501_phynum, MII_BMCR, ctl);
|
731 |
|
|
|
732 |
|
|
// Setup Autoneg
|
733 |
|
|
short adv = eth_mii_read(alaska88e1111_ml501_phynum, MII_ADVERTISE);
|
734 |
|
|
adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4 | ADVERTISE_1000XFULL
|
735 |
|
|
|ADVERTISE_1000XHALF | ADVERTISE_1000XPAUSE |
|
736 |
|
|
ADVERTISE_1000XPSE_ASYM);
|
737 |
|
|
adv |= ADVERTISE_10HALF;
|
738 |
|
|
adv |= ADVERTISE_10FULL;
|
739 |
|
|
adv |= ADVERTISE_100HALF;
|
740 |
|
|
adv |= ADVERTISE_100FULL;
|
741 |
|
|
eth_mii_write(alaska88e1111_ml501_phynum, MII_ADVERTISE, adv);
|
742 |
|
|
// Disable gigabit???
|
743 |
|
|
adv = eth_mii_read(alaska88e1111_ml501_phynum, MII_M1011_PHY_SPEC_CONTROL);
|
744 |
|
|
adv &= ~(MII_1000BASETCONTROL_FULLDUPLEXCAP |
|
745 |
|
|
MII_1000BASETCONTROL_HALFDUPLEXCAP);
|
746 |
|
|
eth_mii_write(alaska88e1111_ml501_phynum, MII_M1011_PHY_SPEC_CONTROL, adv);
|
747 |
|
|
// Even more disable gigabit?!
|
748 |
|
|
adv = eth_mii_read(alaska88e1111_ml501_phynum, MII_CTRL1000);
|
749 |
|
|
adv &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF);
|
750 |
|
|
eth_mii_write(alaska88e1111_ml501_phynum, MII_CTRL1000, adv);
|
751 |
|
|
|
752 |
|
|
// Restart autoneg
|
753 |
|
|
printf("Resetting phy...\n");
|
754 |
|
|
ctl = eth_mii_read(alaska88e1111_ml501_phynum, MII_BMCR);
|
755 |
|
|
ctl |= (BMCR_ANENABLE | BMCR_ANRESTART);
|
756 |
|
|
eth_mii_write(alaska88e1111_ml501_phynum, MII_BMCR, ctl);
|
757 |
|
|
|
758 |
|
|
printf("\nOeth: PHY control reg: 0x%.4x\n",
|
759 |
|
|
eth_mii_read(alaska88e1111_ml501_phynum, MII_BMCR));
|
760 |
|
|
printf("Oeth: PHY control reg: 0x%.4x\n",
|
761 |
|
|
eth_mii_read(alaska88e1111_ml501_phynum, MII_BMSR));
|
762 |
|
|
printf("Oeth: PHY id0: 0x%.4x\n",
|
763 |
|
|
eth_mii_read(alaska88e1111_ml501_phynum, MII_PHYSID1));
|
764 |
|
|
printf("Oeth: PHY id1: 0x%.4x\n",
|
765 |
|
|
eth_mii_read(alaska88e1111_ml501_phynum, MII_PHYSID2));
|
766 |
|
|
printf("Oeth: PHY adv: 0x%.4x\n",
|
767 |
|
|
eth_mii_read(alaska88e1111_ml501_phynum, MII_ADVERTISE));
|
768 |
|
|
printf("Oeth: PHY lpa: 0x%.4x\n",
|
769 |
|
|
eth_mii_read(alaska88e1111_ml501_phynum, MII_LPA));
|
770 |
|
|
printf("Oeth: PHY physpec: 0x%.4x\n",
|
771 |
|
|
eth_mii_read(alaska88e1111_ml501_phynum, MII_M1011_PHY_SPEC_CONTROL));
|
772 |
|
|
printf("Oeth: PHY expansion: 0x%.4x\n",
|
773 |
|
|
eth_mii_read(alaska88e1111_ml501_phynum, MII_EXPANSION ));
|
774 |
|
|
printf("Oeth: PHY ctrl1000: 0x%.4x\n",
|
775 |
|
|
eth_mii_read(alaska88e1111_ml501_phynum, MII_CTRL1000));
|
776 |
|
|
printf("Oeth: PHY stat1000: 0x%.4x\n",
|
777 |
|
|
eth_mii_read(alaska88e1111_ml501_phynum, MII_STAT1000));
|
778 |
|
|
printf("Oeth: PHY estatus: 0x%.4x\n",
|
779 |
|
|
eth_mii_read(alaska88e1111_ml501_phynum, MII_ESTATUS));
|
780 |
|
|
|
781 |
|
|
|
782 |
|
|
}
|
783 |
|
|
|
784 |
|
|
|
785 |
|
|
void ethmac_setup(void)
|
786 |
|
|
{
|
787 |
|
|
// from arch/or32/drivers/open_eth.c
|
788 |
|
|
volatile oeth_regs *regs;
|
789 |
|
|
|
790 |
|
|
regs = (oeth_regs *)(OETH_REG_BASE);
|
791 |
|
|
|
792 |
|
|
/*printf("\nbefore reset\n\n");
|
793 |
|
|
oeth_printregs();*/
|
794 |
|
|
|
795 |
|
|
/* Reset MII mode module */
|
796 |
|
|
regs->miimoder = OETH_MIIMODER_RST; /* MII Reset ON */
|
797 |
|
|
regs->miimoder &= ~OETH_MIIMODER_RST; /* MII Reset OFF */
|
798 |
|
|
regs->miimoder = 0x64; /* Clock divider for MII Management interface */
|
799 |
|
|
|
800 |
|
|
/* Reset the controller.
|
801 |
|
|
*/
|
802 |
|
|
regs->moder = OETH_MODER_RST; /* Reset ON */
|
803 |
|
|
regs->moder &= ~OETH_MODER_RST; /* Reset OFF */
|
804 |
|
|
|
805 |
|
|
//printf("\nafter reset\n\n");
|
806 |
|
|
//oeth_printregs();
|
807 |
|
|
|
808 |
|
|
/* Setting TXBD base to OETH_TXBD_NUM.
|
809 |
|
|
*/
|
810 |
|
|
regs->tx_bd_num = OETH_TXBD_NUM;
|
811 |
|
|
|
812 |
|
|
|
813 |
|
|
/* Set min/max packet length
|
814 |
|
|
*/
|
815 |
|
|
//regs->packet_len = 0x00400600;
|
816 |
|
|
regs->packet_len = (0x0040 << 16) | (MAX_FRAME_SIZE & 0xffff);
|
817 |
|
|
|
818 |
|
|
/* Set IPGT register to recomended value
|
819 |
|
|
*/
|
820 |
|
|
regs->ipgt = 0x12;
|
821 |
|
|
|
822 |
|
|
/* Set IPGR1 register to recomended value
|
823 |
|
|
*/
|
824 |
|
|
regs->ipgr1 = 0x0000000c;
|
825 |
|
|
|
826 |
|
|
/* Set IPGR2 register to recomended value
|
827 |
|
|
*/
|
828 |
|
|
regs->ipgr2 = 0x00000012;
|
829 |
|
|
|
830 |
|
|
/* Set COLLCONF register to recomended value
|
831 |
|
|
*/
|
832 |
|
|
regs->collconf = 0x000f003f;
|
833 |
|
|
|
834 |
|
|
/* Set control module mode
|
835 |
|
|
*/
|
836 |
|
|
#if 0
|
837 |
|
|
regs->ctrlmoder = OETH_CTRLMODER_TXFLOW | OETH_CTRLMODER_RXFLOW;
|
838 |
|
|
#else
|
839 |
|
|
regs->ctrlmoder = 0;
|
840 |
|
|
#endif
|
841 |
|
|
|
842 |
|
|
/* Clear MIIM registers */
|
843 |
|
|
regs->miitx_data = 0;
|
844 |
|
|
regs->miiaddress = 0;
|
845 |
|
|
regs->miicommand = 0;
|
846 |
|
|
|
847 |
|
|
regs->mac_addr1 = ETH_MACADDR0 << 8 | ETH_MACADDR1;
|
848 |
411 |
julius |
regs->mac_addr0 = ETH_MACADDR2 << 24 | ETH_MACADDR3 << 16 |
|
849 |
|
|
ETH_MACADDR4 << 8 | ETH_MACADDR5;
|
850 |
349 |
julius |
|
851 |
|
|
/* Clear all pending interrupts
|
852 |
|
|
*/
|
853 |
|
|
regs->int_src = 0xffffffff;
|
854 |
|
|
|
855 |
|
|
/* Promisc, IFG, CRCEn
|
856 |
|
|
*/
|
857 |
411 |
julius |
regs->moder |= OETH_MODER_PRO | OETH_MODER_PAD | OETH_MODER_IFG |
|
858 |
|
|
OETH_MODER_CRCEN | OETH_MODER_FULLD;
|
859 |
349 |
julius |
|
860 |
|
|
/* Enable interrupt sources.
|
861 |
|
|
*/
|
862 |
|
|
|
863 |
|
|
regs->int_mask = OETH_INT_MASK_TXB |
|
864 |
|
|
OETH_INT_MASK_TXE |
|
865 |
|
|
OETH_INT_MASK_RXF |
|
866 |
|
|
OETH_INT_MASK_RXE |
|
867 |
|
|
OETH_INT_MASK_BUSY |
|
868 |
|
|
OETH_INT_MASK_TXC |
|
869 |
|
|
OETH_INT_MASK_RXC;
|
870 |
435 |
julius |
|
871 |
349 |
julius |
// Buffer setup stuff
|
872 |
|
|
volatile oeth_bd *tx_bd, *rx_bd;
|
873 |
|
|
int i,j,k;
|
874 |
|
|
|
875 |
|
|
/* Initialize TXBD pointer
|
876 |
|
|
*/
|
877 |
|
|
tx_bd = (volatile oeth_bd *)OETH_BD_BASE;
|
878 |
|
|
|
879 |
|
|
/* Initialize RXBD pointer
|
880 |
|
|
*/
|
881 |
|
|
rx_bd = ((volatile oeth_bd *)OETH_BD_BASE) + OETH_TXBD_NUM;
|
882 |
|
|
|
883 |
|
|
/* Preallocated ethernet buffer setup */
|
884 |
|
|
unsigned long mem_addr = ETH_BUFF_BASE; /* Defined at top */
|
885 |
|
|
|
886 |
411 |
julius |
// Setup TX Buffers
|
887 |
|
|
for(i = 0; i < OETH_TXBD_NUM; i++) {
|
888 |
|
|
//tx_bd[i].len_status = OETH_TX_BD_PAD | OETH_TX_BD_CRC | OETH_RX_BD_IRQ;
|
889 |
|
|
tx_bd[i].len_status = OETH_TX_BD_PAD | OETH_TX_BD_CRC;
|
890 |
|
|
tx_bd[i].addr = mem_addr;
|
891 |
|
|
mem_addr += OETH_TX_BUFF_SIZE;
|
892 |
349 |
julius |
}
|
893 |
|
|
tx_bd[OETH_TXBD_NUM - 1].len_status |= OETH_TX_BD_WRAP;
|
894 |
|
|
|
895 |
411 |
julius |
// Setup RX buffers
|
896 |
|
|
for(i = 0; i < OETH_RXBD_NUM; i++) {
|
897 |
|
|
rx_bd[i].len_status = OETH_RX_BD_EMPTY | OETH_RX_BD_IRQ; // Init. with IRQ
|
898 |
|
|
rx_bd[i].addr = mem_addr;
|
899 |
|
|
mem_addr += OETH_RX_BUFF_SIZE;
|
900 |
349 |
julius |
}
|
901 |
411 |
julius |
rx_bd[OETH_RXBD_NUM - 1].len_status |= OETH_RX_BD_WRAP; // Last buffer wraps
|
902 |
349 |
julius |
|
903 |
|
|
/* Enable receiver and transmiter
|
904 |
|
|
*/
|
905 |
|
|
regs->moder |= OETH_MODER_RXEN | OETH_MODER_TXEN;
|
906 |
|
|
|
907 |
|
|
next_tx_buf_num = 0; // init tx buffer pointer
|
908 |
|
|
|
909 |
|
|
return;
|
910 |
|
|
}
|
911 |
|
|
|
912 |
|
|
void
|
913 |
|
|
ethmac_togglehugen(void)
|
914 |
|
|
{
|
915 |
|
|
|
916 |
|
|
volatile oeth_regs *regs;
|
917 |
|
|
regs = (oeth_regs *)(OETH_REG_BASE);
|
918 |
|
|
|
919 |
|
|
regs->moder ^= OETH_MODER_HUGEN; // Toggle huge packet enable
|
920 |
|
|
|
921 |
|
|
if (regs->moder & OETH_MODER_HUGEN) // If we just enabled huge packets
|
922 |
|
|
regs->packet_len = (0x0040 << 16) | (((64*1024)-4) & 0xffff);
|
923 |
|
|
else
|
924 |
|
|
// back to normal
|
925 |
|
|
regs->packet_len = (0x0040 << 16) | (MAX_FRAME_SIZE & 0xffff);
|
926 |
|
|
|
927 |
|
|
return;
|
928 |
|
|
|
929 |
|
|
}
|
930 |
|
|
|
931 |
|
|
void
|
932 |
|
|
oeth_reset_tx_bd_pointer(void)
|
933 |
|
|
{
|
934 |
|
|
printf("Resetting TX BD pointer\n");
|
935 |
|
|
// from arch/or32/drivers/open_eth.c
|
936 |
|
|
volatile oeth_regs *regs;
|
937 |
|
|
regs = (oeth_regs *)(OETH_REG_BASE);
|
938 |
|
|
|
939 |
|
|
// Toggle TXEN bit, resetting TX BD number
|
940 |
|
|
regs->moder &= OETH_MODER_TXEN;
|
941 |
|
|
regs->moder |= OETH_MODER_TXEN;
|
942 |
|
|
|
943 |
|
|
next_tx_buf_num = 0; // init tx buffer pointer
|
944 |
|
|
|
945 |
|
|
}
|
946 |
|
|
|
947 |
|
|
|
948 |
|
|
|
949 |
|
|
/* Find the next available transmit buffer */
|
950 |
|
|
struct oeth_bd* get_next_tx_bd()
|
951 |
|
|
{
|
952 |
|
|
|
953 |
|
|
int i;
|
954 |
|
|
volatile oeth_bd *tx_bd;
|
955 |
|
|
tx_bd = (volatile oeth_bd *)OETH_BD_BASE; /* Search from beginning*/
|
956 |
|
|
|
957 |
|
|
/* Go through the TX buffs, search for unused one */
|
958 |
|
|
for(i = next_tx_buf_num; i < OETH_TXBD_NUM; i++) {
|
959 |
|
|
|
960 |
|
|
if(!(tx_bd[i].len_status & OETH_TX_BD_READY)) /* Looking for buffer NOT ready for transmit. ie we can manipulate it */
|
961 |
|
|
{
|
962 |
411 |
julius |
if (print_packet_contents)
|
963 |
|
|
printf("Oeth: Using TX_bd at 0x%lx\n",(unsigned long)&tx_bd[i]);
|
964 |
|
|
|
965 |
349 |
julius |
if (next_tx_buf_num == OETH_TXBD_NUM-1) next_tx_buf_num = 0;
|
966 |
|
|
else next_tx_buf_num++;
|
967 |
|
|
|
968 |
|
|
return (struct oeth_bd*) &tx_bd[i];
|
969 |
|
|
}
|
970 |
|
|
|
971 |
|
|
if ((i == OETH_TXBD_NUM-1) && (next_tx_buf_num != 0))
|
972 |
|
|
i = 0;
|
973 |
|
|
|
974 |
|
|
}
|
975 |
|
|
|
976 |
|
|
printf("No free tx buffers\n");
|
977 |
|
|
/* Set to null our returned buffer */
|
978 |
|
|
tx_bd = (volatile oeth_bd *) 0;
|
979 |
|
|
return (struct oeth_bd*) tx_bd;
|
980 |
|
|
|
981 |
|
|
}
|
982 |
|
|
|
983 |
|
|
/* print packet contents */
|
984 |
|
|
static void
|
985 |
|
|
oeth_print_packet(unsigned long add, int len)
|
986 |
|
|
{
|
987 |
|
|
|
988 |
|
|
int truncate = (len > 256);
|
989 |
|
|
int length_to_print = truncate ? 256 : len;
|
990 |
|
|
|
991 |
|
|
int i;
|
992 |
|
|
printf("\nipacket: add = %lx len = %d\n", add, len);
|
993 |
|
|
for(i = 0; i < length_to_print; i++) {
|
994 |
|
|
if(!(i % 8))
|
995 |
|
|
printf(" ");
|
996 |
|
|
if(!(i % 16))
|
997 |
|
|
printf("\n");
|
998 |
|
|
printf(" %.2x", *(((unsigned char *)add) + i));
|
999 |
|
|
|
1000 |
|
|
}
|
1001 |
|
|
printf("\n");
|
1002 |
|
|
|
1003 |
|
|
if (truncate)
|
1004 |
|
|
printf("\ttruncated....\n");
|
1005 |
|
|
|
1006 |
|
|
}
|
1007 |
|
|
|
1008 |
|
|
/* Setup buffer descriptors with data */
|
1009 |
|
|
/* length is in BYTES */
|
1010 |
|
|
void tx_packet(void* data, int length)
|
1011 |
|
|
{
|
1012 |
|
|
volatile oeth_regs *regs;
|
1013 |
|
|
regs = (oeth_regs *)(OETH_REG_BASE);
|
1014 |
|
|
|
1015 |
|
|
volatile oeth_bd *tx_bd;
|
1016 |
|
|
volatile int i;
|
1017 |
|
|
|
1018 |
|
|
|
1019 |
|
|
tx_bd = (volatile oeth_bd *)OETH_BD_BASE;
|
1020 |
|
|
tx_bd = (struct oeth_bd*) &tx_bd[next_tx_buf_num];
|
1021 |
|
|
|
1022 |
|
|
/*if((tx_bd = (volatile oeth_bd *) get_next_tx_bd()) == NULL)
|
1023 |
|
|
{
|
1024 |
|
|
printf("No more TX buffers available\n");
|
1025 |
|
|
return;
|
1026 |
|
|
}
|
1027 |
|
|
*/
|
1028 |
411 |
julius |
if (print_packet_contents)
|
1029 |
|
|
printf("Oeth: Using TX_bd buffer address: 0x%lx\n",(unsigned long) tx_bd->addr);
|
1030 |
349 |
julius |
|
1031 |
|
|
/* Clear all of the status flags.
|
1032 |
|
|
*/
|
1033 |
|
|
tx_bd->len_status &= ~OETH_TX_BD_STATS;
|
1034 |
|
|
|
1035 |
|
|
/* If the frame is short, tell CPM to pad it.
|
1036 |
|
|
*/
|
1037 |
|
|
#define ETH_ZLEN 60 /* Min. octets in frame sans FCS */
|
1038 |
|
|
if (length <= ETH_ZLEN)
|
1039 |
|
|
tx_bd->len_status |= OETH_TX_BD_PAD;
|
1040 |
|
|
else
|
1041 |
|
|
tx_bd->len_status &= ~OETH_TX_BD_PAD;
|
1042 |
|
|
|
1043 |
|
|
//printf("Oeth: Copying %d bytes from 0x%lx to TX_bd buffer at 0x%lx\n",length,(unsigned long) data,(unsigned long) tx_bd->addr);
|
1044 |
|
|
|
1045 |
|
|
/* Copy the data into the transmit buffer, byte at a time */
|
1046 |
|
|
char* data_p = (char*) data;
|
1047 |
|
|
char* data_b = (char*) tx_bd->addr;
|
1048 |
|
|
for(i=0;i<length;i++)
|
1049 |
|
|
{
|
1050 |
|
|
data_b[i] = data_p[i];
|
1051 |
|
|
}
|
1052 |
|
|
//printf("Oeth: Data copied to buffer\n");
|
1053 |
|
|
|
1054 |
|
|
/* Set the length of the packet's data in the buffer descriptor */
|
1055 |
|
|
tx_bd->len_status = (tx_bd->len_status & 0x0000ffff) |
|
1056 |
|
|
((length&0xffff) << 16);
|
1057 |
|
|
|
1058 |
|
|
//oeth_print_packet(tx_bd->addr, (tx_bd->len_status >> 16));
|
1059 |
|
|
|
1060 |
|
|
/* Send it on its way. Tell controller its ready, interrupt when sent
|
1061 |
|
|
* and to put the CRC on the end.
|
1062 |
|
|
*/
|
1063 |
|
|
tx_bd->len_status |= (OETH_TX_BD_READY | OETH_TX_BD_CRC | OETH_TX_BD_IRQ);
|
1064 |
|
|
|
1065 |
|
|
next_tx_buf_num = (next_tx_buf_num + 1) & OETH_TXBD_NUM_MASK;
|
1066 |
|
|
|
1067 |
|
|
return;
|
1068 |
|
|
|
1069 |
|
|
|
1070 |
|
|
}
|
1071 |
|
|
|
1072 |
|
|
/* enable RX, loop waiting for arrived packets and print them out */
|
1073 |
|
|
void oeth_monitor_rx(void)
|
1074 |
|
|
{
|
1075 |
|
|
volatile oeth_regs *regs;
|
1076 |
|
|
regs = (oeth_regs *)(OETH_REG_BASE);
|
1077 |
|
|
|
1078 |
|
|
/* Set RXEN in MAC MODER */
|
1079 |
|
|
regs->moder = OETH_MODER_RXEN | regs->moder;
|
1080 |
|
|
|
1081 |
|
|
|
1082 |
|
|
volatile oeth_bd *rx_bd;
|
1083 |
|
|
rx_bd = ((volatile oeth_bd *)OETH_BD_BASE) + OETH_TXBD_NUM;
|
1084 |
|
|
|
1085 |
|
|
volatile int i;
|
1086 |
|
|
|
1087 |
|
|
for(i=0;i<OETH_RXBD_NUM;i++)
|
1088 |
|
|
{
|
1089 |
|
|
if (!(rx_bd[i].len_status & OETH_RX_BD_EMPTY)) /* Not empty */
|
1090 |
|
|
{
|
1091 |
|
|
// Something in this buffer!
|
1092 |
|
|
printf("Oeth: RX in buf %d - len_status: 0x%lx\n",i, rx_bd[i].len_status);
|
1093 |
|
|
oeth_print_packet(rx_bd[i].addr, rx_bd[i].len_status >> 16);
|
1094 |
|
|
/* Clear recieved bit */
|
1095 |
|
|
rx_bd[i].len_status |= OETH_RX_BD_EMPTY;
|
1096 |
|
|
printf("\t end of packet\n\n");
|
1097 |
|
|
}
|
1098 |
|
|
}
|
1099 |
|
|
}
|
1100 |
|
|
|
1101 |
|
|
/* Print out all buffer descriptors */
|
1102 |
|
|
void oeth_dump_bds()
|
1103 |
|
|
{
|
1104 |
|
|
unsigned long* bd_base = (unsigned long*) OETH_BD_BASE;
|
1105 |
|
|
|
1106 |
|
|
int i;
|
1107 |
|
|
for(i=0;i<OETH_TXBD_NUM;i++)
|
1108 |
|
|
{
|
1109 |
|
|
printf("oeth: tx_bd%d: len_status: %lx ",i,*bd_base++);
|
1110 |
|
|
printf("addr: %lx\n", *bd_base++);
|
1111 |
|
|
}
|
1112 |
|
|
|
1113 |
|
|
for(i=0;i<OETH_RXBD_NUM;i++)
|
1114 |
|
|
{
|
1115 |
|
|
printf("oeth: rx_bd%d: len_status: %lx ",i,*bd_base++);
|
1116 |
|
|
printf("addr: %lx\n", *bd_base++);
|
1117 |
|
|
}
|
1118 |
|
|
|
1119 |
|
|
}
|
1120 |
|
|
|
1121 |
|
|
|
1122 |
|
|
|
1123 |
|
|
char broadcast_ping_packet[] = {
|
1124 |
|
|
0xff,0xff,0xff,0xff,0xff,0xff, /*SRC MAC*/
|
1125 |
|
|
0x00, 0x12, 0x34, 0x56, 0x78, 0x9a, /*SRC MAC*/
|
1126 |
|
|
0x08,0x00,
|
1127 |
|
|
0x45,
|
1128 |
|
|
0x00,
|
1129 |
|
|
// 0x00,0x54, /* length */
|
1130 |
|
|
0x01,0x1c, /* length */
|
1131 |
|
|
0x00,0x00,
|
1132 |
|
|
0x40,
|
1133 |
|
|
0x00,
|
1134 |
|
|
0x40,
|
1135 |
|
|
0x01,
|
1136 |
435 |
julius |
0xb5,0x8f,
|
1137 |
349 |
julius |
OUR_IP_BYTES, /* Source IP */
|
1138 |
435 |
julius |
BCAST_DEST_IP_BYTES, /* Dest. IP */
|
1139 |
349 |
julius |
/* ICMP Message body */
|
1140 |
|
|
0x08,0x00,0x7d,0x65,0xa7,0x20,0x00,0x01,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,
|
1141 |
|
|
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,
|
1142 |
|
|
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,
|
1143 |
|
|
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,
|
1144 |
|
|
90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,
|
1145 |
|
|
111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,
|
1146 |
|
|
130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,
|
1147 |
|
|
149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,
|
1148 |
|
|
168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,
|
1149 |
|
|
187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,
|
1150 |
|
|
206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,
|
1151 |
|
|
225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,
|
1152 |
|
|
244,245,246,247,248,249,250,251,252,253,254,255};
|
1153 |
|
|
|
1154 |
|
|
|
1155 |
|
|
char big_ping_packet[] = {
|
1156 |
|
|
0x00, 0x24, 0xe8, 0x91, 0x7c, 0x0d, /*DST MAC*/
|
1157 |
|
|
//0xff,0xff,0xff,0xff,0xff,0xff, /*SRC MAC*/
|
1158 |
|
|
0x00, 0x12, 0x34, 0x56, 0x78, 0x9a, /*SRC MAC*/
|
1159 |
|
|
0x08,0x00,
|
1160 |
|
|
0x45,
|
1161 |
|
|
0x00,
|
1162 |
|
|
0x05,0xdc, /* length */
|
1163 |
|
|
0x00,0x00,
|
1164 |
|
|
0x40,
|
1165 |
|
|
0x00,
|
1166 |
|
|
0x40,
|
1167 |
|
|
0x01,
|
1168 |
|
|
0xea,0xcb, /* Header checksum */
|
1169 |
|
|
OUR_IP_BYTES, /* Source IP */
|
1170 |
|
|
DEST_IP_BYTES, /* Dest. IP */
|
1171 |
|
|
/* ICMP Message body */
|
1172 |
|
|
0x08,0x00, /* Type */
|
1173 |
|
|
0x04,0x48, /* ICMP checksum */
|
1174 |
|
|
0x02,0x00, /* Identifier */
|
1175 |
|
|
0x3a,0x00, /* sequence number */
|
1176 |
|
|
0x61,0x62,0x63,0x64,0x65,0x66,0x67,
|
1177 |
|
|
0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,0x70,0x71,0x72,0x73,0x74,0x75,0x76,
|
1178 |
|
|
0x77,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,
|
1179 |
|
|
0x6f,0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x61,0x62,0x63,0x64,0x65,0x66,
|
1180 |
|
|
0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,0x70,0x71,0x72,0x73,0x74,0x75,
|
1181 |
|
|
0x76,0x77,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,
|
1182 |
|
|
0x6e,0x6f,0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x61,0x62,0x63,0x64,0x65,
|
1183 |
|
|
0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,0x70,0x71,0x72,0x73,0x74,
|
1184 |
|
|
0x75,0x76,0x77,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,
|
1185 |
|
|
0x6d,0x6e,0x6f,0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x61,0x62,0x63,0x64,
|
1186 |
|
|
0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,0x70,0x71,0x72,0x73,
|
1187 |
|
|
0x74,0x75,0x76,0x77,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,
|
1188 |
|
|
0x6c,0x6d,0x6e,0x6f,0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x61,0x62,0x63,
|
1189 |
|
|
0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,0x70,0x71,0x72,
|
1190 |
|
|
0x73,0x74,0x75,0x76,0x77,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,
|
1191 |
|
|
0x6b,0x6c,0x6d,0x6e,0x6f,0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x61,0x62,
|
1192 |
|
|
0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,0x70,0x71,
|
1193 |
|
|
0x72,0x73,0x74,0x75,0x76,0x77,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,
|
1194 |
|
|
0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x61,
|
1195 |
|
|
0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,0x70,
|
1196 |
|
|
0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,
|
1197 |
|
|
0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,
|
1198 |
|
|
0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,
|
1199 |
|
|
0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x61,0x62,0x63,0x64,0x65,0x66,0x67,
|
1200 |
|
|
0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,0x70,0x71,0x72,0x73,0x74,0x75,0x76,
|
1201 |
|
|
0x77,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,
|
1202 |
|
|
0x6f,0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x61,0x62,0x63,0x64,0x65,0x66,
|
1203 |
|
|
0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,0x70,0x71,0x72,0x73,0x74,0x75,
|
1204 |
|
|
0x76,0x77,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,
|
1205 |
|
|
0x6e,0x6f,0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x61,0x62,0x63,0x64,0x65,
|
1206 |
|
|
0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,0x70,0x71,0x72,0x73,0x74,
|
1207 |
|
|
0x75,0x76,0x77,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,
|
1208 |
|
|
0x6d,0x6e,0x6f,0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x61,0x62,0x63,0x64,
|
1209 |
|
|
0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,0x70,0x71,0x72,0x73,
|
1210 |
|
|
0x74,0x75,0x76,0x77,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,
|
1211 |
|
|
0x6c,0x6d,0x6e,0x6f,0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x61,0x62,0x63,
|
1212 |
|
|
0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,0x70,0x71,0x72,
|
1213 |
|
|
0x73,0x74,0x75,0x76,0x77,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,
|
1214 |
|
|
0x6b,0x6c,0x6d,0x6e,0x6f,0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x61,0x62,
|
1215 |
|
|
0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,0x70,0x71,
|
1216 |
|
|
0x72,0x73,0x74,0x75,0x76,0x77,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,
|
1217 |
|
|
0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x61,
|
1218 |
|
|
0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,0x70,
|
1219 |
|
|
0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,
|
1220 |
|
|
0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,
|
1221 |
|
|
0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,
|
1222 |
|
|
0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x61,0x62,0x63,0x64,0x65,0x66,0x67,
|
1223 |
|
|
0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,0x70,0x71,0x72,0x73,0x74,0x75,0x76,
|
1224 |
|
|
0x77,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,
|
1225 |
|
|
0x6f,0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x61,0x62,0x63,0x64,0x65,0x66,
|
1226 |
|
|
0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,0x70,0x71,0x72,0x73,0x74,0x75,
|
1227 |
|
|
0x76,0x77,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,
|
1228 |
|
|
0x6e,0x6f,0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x61,0x62,0x63,0x64,0x65,
|
1229 |
|
|
0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,0x70,0x71,0x72,0x73,0x74,
|
1230 |
|
|
0x75,0x76,0x77,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,
|
1231 |
|
|
0x6d,0x6e,0x6f,0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x61,0x62,0x63,0x64,
|
1232 |
|
|
0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,0x70,0x71,0x72,0x73,
|
1233 |
|
|
0x74,0x75,0x76,0x77,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,
|
1234 |
|
|
0x6c,0x6d,0x6e,0x6f,0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x61,0x62,0x63,
|
1235 |
|
|
0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,0x70,0x71,0x72,
|
1236 |
|
|
0x73,0x74,0x75,0x76,0x77,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,
|
1237 |
|
|
0x6b,0x6c,0x6d,0x6e,0x6f,0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x61,0x62,
|
1238 |
|
|
0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,0x70,0x71,
|
1239 |
|
|
0x72,0x73,0x74,0x75,0x76,0x77,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,
|
1240 |
|
|
0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x61,
|
1241 |
|
|
0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,0x70,
|
1242 |
|
|
0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,
|
1243 |
|
|
0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,
|
1244 |
|
|
0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,
|
1245 |
|
|
0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x61,0x62,0x63,0x64,0x65,0x66,0x67,
|
1246 |
|
|
0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,0x70,0x71,0x72,0x73,0x74,0x75,0x76,
|
1247 |
|
|
0x77,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,
|
1248 |
|
|
0x6f,0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x61,0x62,0x63,0x64,0x65,0x66,
|
1249 |
|
|
0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,0x70,0x71,0x72,0x73,0x74,0x75,
|
1250 |
|
|
0x76,0x77,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,
|
1251 |
|
|
0x6e,0x6f,0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x61,0x62,0x63,0x64,0x65,
|
1252 |
|
|
0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,0x70,0x71,0x72,0x73,0x74,
|
1253 |
|
|
0x75,0x76,0x77,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,
|
1254 |
|
|
0x6d,0x6e,0x6f,0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x61,0x62,0x63,0x64,
|
1255 |
|
|
0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,0x70,0x71,0x72,0x73,
|
1256 |
|
|
0x74,0x75,0x76,0x77,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,
|
1257 |
|
|
0x6c,0x6d,0x6e,0x6f,0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x61,0x62,0x63,
|
1258 |
|
|
0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,0x70,0x71,0x72,
|
1259 |
|
|
0x73,0x74,0x75,0x76,0x77,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,
|
1260 |
|
|
0x6b,0x6c,0x6d,0x6e,0x6f,0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x61,0x62,
|
1261 |
|
|
0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,0x70,0x71,
|
1262 |
|
|
0x72,0x73,0x74,0x75,0x76,0x77,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,
|
1263 |
|
|
0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x61,
|
1264 |
|
|
0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,0x70,
|
1265 |
|
|
0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,
|
1266 |
|
|
0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,
|
1267 |
|
|
0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,
|
1268 |
|
|
0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x61,0x62,0x63,0x64,0x65,0x66,0x67,
|
1269 |
|
|
0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,0x70,0x71,0x72,0x73,0x74,0x75,0x76,
|
1270 |
|
|
0x77,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,
|
1271 |
|
|
0x6f,0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x61,0x62,0x63,0x64,0x65,0x66,
|
1272 |
|
|
0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,0x70,0x71,0x72,0x73,0x74,0x75,
|
1273 |
|
|
0x76,0x77,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,
|
1274 |
|
|
0x6e,0x6f,0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77};
|
1275 |
|
|
|
1276 |
|
|
|
1277 |
|
|
/* This should be 98 bytes big */
|
1278 |
|
|
char ping_packet[] = {
|
1279 |
|
|
0x00, 0x24, 0xe8, 0x91, 0x7c, 0x0d, /*DST MAC*/
|
1280 |
|
|
//0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /*DST MAC*/
|
1281 |
|
|
0x00, 0x12, 0x34, 0x56, 0x78, 0x9a, /*SRC MAC*/
|
1282 |
|
|
0x08, 0x00, /*TYPE*/
|
1283 |
|
|
/* IP */
|
1284 |
|
|
0x45, /* Version, header length*/
|
1285 |
|
|
0x00, /* Differentiated services field */
|
1286 |
|
|
0x00, 0x54, /* Total length */
|
1287 |
|
|
0x00, 0x00, /* Identification */
|
1288 |
|
|
0x40, /* Flags */
|
1289 |
|
|
0x00, /* Fragment offset */
|
1290 |
|
|
0x40, /* Time to live */
|
1291 |
|
|
0x01, /* Protocol (0x01 = ICMP */
|
1292 |
|
|
0xf0, 0x53, /* Header checksum */
|
1293 |
|
|
//0xc0, 0xa8, 0x64, 0xDE, /* Source IP */
|
1294 |
|
|
OUR_IP_BYTES, /* Source IP */
|
1295 |
|
|
DEST_IP_BYTES, /* Dest. IP */
|
1296 |
|
|
/* ICMP Message body */
|
1297 |
|
|
0x08, 0x00, 0x9a, 0xd4, 0xc8, 0x18, 0x00, 0x01, 0xd9, 0x8c, 0x54,
|
1298 |
|
|
0x4a, 0x7b, 0x37, 0x01, 0x00, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
|
1299 |
|
|
0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
|
1300 |
|
|
0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
|
1301 |
|
|
0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e,
|
1302 |
|
|
0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37
|
1303 |
|
|
};
|
1304 |
|
|
|
1305 |
|
|
void send_test_packet()
|
1306 |
|
|
{
|
1307 |
|
|
|
1308 |
|
|
/*Send packet */
|
1309 |
|
|
//tx_packet((void*) ping_packet, 102);
|
1310 |
|
|
tx_packet((void*) broadcast_ping_packet, 102);
|
1311 |
|
|
|
1312 |
|
|
}
|
1313 |
|
|
|
1314 |
|
|
|
1315 |
|
|
/* The interrupt handler.
|
1316 |
|
|
*/
|
1317 |
|
|
void
|
1318 |
|
|
oeth_interrupt(void)
|
1319 |
|
|
{
|
1320 |
|
|
|
1321 |
|
|
volatile oeth_regs *regs;
|
1322 |
|
|
regs = (oeth_regs *)(OETH_REG_BASE);
|
1323 |
|
|
|
1324 |
|
|
uint int_events;
|
1325 |
|
|
int serviced;
|
1326 |
|
|
|
1327 |
|
|
serviced = 0;
|
1328 |
|
|
|
1329 |
|
|
/* Get the interrupt events that caused us to be here.
|
1330 |
|
|
*/
|
1331 |
|
|
int_events = regs->int_src;
|
1332 |
|
|
regs->int_src = int_events;
|
1333 |
|
|
|
1334 |
|
|
|
1335 |
|
|
/* Indicate busy */
|
1336 |
|
|
if (int_events & OETH_INT_BUSY)
|
1337 |
|
|
{
|
1338 |
|
|
printf("\tBusy flag\n");
|
1339 |
|
|
/*
|
1340 |
|
|
printf("\n=tx_ | %x | %x | %x | %x | %x | %x | %x | %x\n",
|
1341 |
|
|
((oeth_bd *)(OETH_BD_BASE))->len_status,
|
1342 |
|
|
((oeth_bd *)(OETH_BD_BASE+8))->len_status,
|
1343 |
|
|
((oeth_bd *)(OETH_BD_BASE+16))->len_status,
|
1344 |
|
|
((oeth_bd *)(OETH_BD_BASE+24))->len_status,
|
1345 |
|
|
((oeth_bd *)(OETH_BD_BASE+32))->len_status,
|
1346 |
|
|
((oeth_bd *)(OETH_BD_BASE+40))->len_status,
|
1347 |
|
|
((oeth_bd *)(OETH_BD_BASE+48))->len_status,
|
1348 |
|
|
((oeth_bd *)(OETH_BD_BASE+56))->len_status);
|
1349 |
|
|
*/
|
1350 |
|
|
printf("=rx_ | %x | %x | %x | %x | %x | %x | %x | %x\n",
|
1351 |
|
|
((oeth_bd *)(OETH_BD_BASE+64))->len_status,
|
1352 |
|
|
((oeth_bd *)(OETH_BD_BASE+64+8))->len_status,
|
1353 |
|
|
((oeth_bd *)(OETH_BD_BASE+64+16))->len_status,
|
1354 |
|
|
((oeth_bd *)(OETH_BD_BASE+64+24))->len_status,
|
1355 |
|
|
((oeth_bd *)(OETH_BD_BASE+64+32))->len_status,
|
1356 |
|
|
((oeth_bd *)(OETH_BD_BASE+64+40))->len_status,
|
1357 |
|
|
((oeth_bd *)(OETH_BD_BASE+64+48))->len_status,
|
1358 |
|
|
((oeth_bd *)(OETH_BD_BASE+64+56))->len_status);
|
1359 |
|
|
|
1360 |
|
|
printf("=int | txb %d | txe %d | rxb %d | rxe %d | busy %d\n",
|
1361 |
|
|
(int_events & OETH_INT_TXB) > 0,
|
1362 |
|
|
(int_events & OETH_INT_TXE) > 0,
|
1363 |
|
|
(int_events & OETH_INT_RXF) > 0,
|
1364 |
|
|
(int_events & OETH_INT_RXE) > 0,
|
1365 |
|
|
(int_events & OETH_INT_BUSY) > 0);
|
1366 |
|
|
}
|
1367 |
|
|
|
1368 |
|
|
/* Handle receive event in its own function.
|
1369 |
|
|
*/
|
1370 |
|
|
if (int_events & (OETH_INT_RXF | OETH_INT_RXE)) {
|
1371 |
|
|
serviced |= 0x1;
|
1372 |
|
|
oeth_rx();
|
1373 |
|
|
}
|
1374 |
|
|
|
1375 |
|
|
/* Handle transmit event in its own function.
|
1376 |
|
|
*/
|
1377 |
|
|
if (int_events & (OETH_INT_TXB | OETH_INT_TXE)) {
|
1378 |
|
|
serviced |= 0x2;
|
1379 |
|
|
oeth_tx();
|
1380 |
|
|
serviced |= 0x2;
|
1381 |
|
|
|
1382 |
|
|
}
|
1383 |
|
|
|
1384 |
|
|
return;
|
1385 |
|
|
}
|
1386 |
|
|
|
1387 |
|
|
// ARP stuff
|
1388 |
|
|
|
1389 |
|
|
typedef unsigned long IPaddr_t;
|
1390 |
|
|
|
1391 |
|
|
/*
|
1392 |
|
|
* Ethernet header
|
1393 |
|
|
*/
|
1394 |
|
|
typedef struct {
|
1395 |
|
|
unsigned char et_dest[6]; /* Destination node */
|
1396 |
|
|
unsigned char et_src[6]; /* Source node */
|
1397 |
|
|
unsigned short et_protlen; /* Protocol or length */
|
1398 |
|
|
unsigned char et_dsap; /* 802 DSAP */
|
1399 |
|
|
unsigned char et_ssap; /* 802 SSAP */
|
1400 |
|
|
unsigned char et_ctl; /* 802 control */
|
1401 |
|
|
unsigned char et_snap1; /* SNAP */
|
1402 |
|
|
unsigned char et_snap2;
|
1403 |
|
|
unsigned char et_snap3;
|
1404 |
|
|
unsigned short et_prot; /* 802 protocol */
|
1405 |
|
|
} Ethernet_t;
|
1406 |
|
|
|
1407 |
|
|
#define ETHER_HDR_SIZE 14 /* Ethernet header size */
|
1408 |
|
|
#define E802_HDR_SIZE 22 /* 802 ethernet header size */
|
1409 |
|
|
#define PROT_IP 0x0800 /* IP protocol */
|
1410 |
|
|
#define PROT_ARP 0x0806 /* IP ARP protocol */
|
1411 |
|
|
#define PROT_RARP 0x8035 /* IP ARP protocol */
|
1412 |
|
|
|
1413 |
|
|
|
1414 |
|
|
/*
|
1415 |
|
|
* Internet Protocol (IP) header.
|
1416 |
|
|
*/
|
1417 |
|
|
typedef struct {
|
1418 |
|
|
unsigned char ip_hl_v; /* header length and version*/
|
1419 |
|
|
unsigned char ip_tos; /* type of service */
|
1420 |
|
|
unsigned short ip_len; /* total length */
|
1421 |
|
|
unsigned short ip_id; /* identification */
|
1422 |
|
|
unsigned short ip_off; /* fragment offset field */
|
1423 |
|
|
unsigned char ip_ttl; /* time to live */
|
1424 |
|
|
unsigned char ip_p; /* protocol */
|
1425 |
|
|
unsigned short ip_sum; /* checksum */
|
1426 |
|
|
IPaddr_t ip_src; /* Source IP address */
|
1427 |
|
|
IPaddr_t ip_dst; /* Destination IP address */
|
1428 |
|
|
unsigned short udp_src; /* UDP source port */
|
1429 |
|
|
unsigned short udp_dst; /* UDP destination port */
|
1430 |
|
|
unsigned short udp_len; /* Length of UDP packet */
|
1431 |
|
|
unsigned short udp_xsum; /* Checksum */
|
1432 |
|
|
} IP_t;
|
1433 |
|
|
|
1434 |
|
|
#define IP_HDR_SIZE_NO_UDP (sizeof (IP_t) - 8)
|
1435 |
|
|
#define IP_HDR_SIZE (sizeof (IP_t))
|
1436 |
|
|
|
1437 |
|
|
#define IPPROTO_ICMP 1 /* Internet Control Message Protocol */
|
1438 |
|
|
#define IPPROTO_UDP 17 /* User Datagram Protocol */
|
1439 |
|
|
|
1440 |
|
|
|
1441 |
|
|
/*
|
1442 |
|
|
* ICMP stuff (just enough to handle (host) redirect messages)
|
1443 |
|
|
*/
|
1444 |
|
|
#define ICMP_REDIRECT 5 /* Redirect (change route) */
|
1445 |
|
|
|
1446 |
|
|
/* Codes for REDIRECT. */
|
1447 |
|
|
#define ICMP_REDIR_NET 0 /* Redirect Net */
|
1448 |
|
|
#define ICMP_REDIR_HOST 1 /* Redirect Host */
|
1449 |
|
|
|
1450 |
|
|
#define ICMP_TYPE_ECHO_REPLY 0x00
|
1451 |
|
|
#define ICMP_TYPE_ECHO_REQ 0x08
|
1452 |
|
|
|
1453 |
|
|
unsigned char ip_reply_packet[0x600] __attribute__ ((aligned (4))); // Save space for a full ICMP reply packet
|
1454 |
|
|
|
1455 |
|
|
typedef struct {
|
1456 |
|
|
unsigned char type;
|
1457 |
|
|
unsigned char code;
|
1458 |
|
|
unsigned short checksum;
|
1459 |
|
|
union {
|
1460 |
|
|
struct {
|
1461 |
|
|
unsigned short id;
|
1462 |
|
|
unsigned short sequence;
|
1463 |
|
|
} echo;
|
1464 |
|
|
unsigned long gateway;
|
1465 |
|
|
struct {
|
1466 |
|
|
unsigned short __unused;
|
1467 |
|
|
unsigned short mtu;
|
1468 |
|
|
} frag;
|
1469 |
|
|
} un;
|
1470 |
|
|
} ICMP_t;
|
1471 |
|
|
|
1472 |
|
|
// From http://lkml.indiana.edu/hypermail/linux/kernel/9612.3/0060.html
|
1473 |
|
|
unsigned short calculate_checksum(char* dats, unsigned int len)
|
1474 |
|
|
{
|
1475 |
|
|
unsigned int itr;
|
1476 |
|
|
unsigned long accum = 0;
|
1477 |
|
|
unsigned long longsum;
|
1478 |
|
|
|
1479 |
|
|
// Sum all pairs of data
|
1480 |
|
|
for(itr=0;itr<(len & ~0x1);itr+=2)
|
1481 |
|
|
accum += (unsigned long)(((dats[itr]<<8)&0xff00)|(dats[itr+1]&0x00ff));
|
1482 |
|
|
|
1483 |
|
|
if (len & 0x1) // Do leftover
|
1484 |
|
|
accum += (unsigned long) ((dats[itr-1]<<8)&0xff00);
|
1485 |
|
|
|
1486 |
|
|
longsum = (unsigned long) (accum & 0xffff);
|
1487 |
|
|
longsum += (unsigned long) (accum >> 16); // Sum the carries
|
1488 |
|
|
longsum += (longsum >> 16);
|
1489 |
|
|
return (unsigned short)((longsum ^ 0xffff) & 0xffff);
|
1490 |
|
|
|
1491 |
|
|
}
|
1492 |
|
|
|
1493 |
|
|
void
|
1494 |
|
|
packet_check_icmp_header(void * pkt)
|
1495 |
|
|
{
|
1496 |
|
|
Ethernet_t * eth_pkt;
|
1497 |
|
|
IP_t * ip;
|
1498 |
|
|
ICMP_t * icmp;
|
1499 |
|
|
|
1500 |
|
|
unsigned int zero = 0;
|
1501 |
|
|
|
1502 |
|
|
eth_pkt = (Ethernet_t *) pkt;
|
1503 |
|
|
|
1504 |
|
|
// Check it's for our MAC
|
1505 |
|
|
char* eth_pkt_dst_mac = (char*) eth_pkt;
|
1506 |
|
|
if (!(
|
1507 |
|
|
((eth_pkt_dst_mac[0] == (char) ETH_MACADDR0) && // Either our MAC
|
1508 |
|
|
(eth_pkt_dst_mac[1] == (char) ETH_MACADDR1) &&
|
1509 |
|
|
(eth_pkt_dst_mac[2] == (char) ETH_MACADDR2) &&
|
1510 |
|
|
(eth_pkt_dst_mac[3] == (char) ETH_MACADDR3) &&
|
1511 |
|
|
(eth_pkt_dst_mac[4] == (char) ETH_MACADDR4) &&
|
1512 |
|
|
(eth_pkt_dst_mac[5] == (char) ETH_MACADDR5)) ||
|
1513 |
|
|
((eth_pkt_dst_mac[0] == (char) 0xff) && // or broadcast MAC
|
1514 |
|
|
(eth_pkt_dst_mac[1] == (char) 0xff) &&
|
1515 |
|
|
(eth_pkt_dst_mac[2] == (char) 0xff) &&
|
1516 |
|
|
(eth_pkt_dst_mac[3] == (char) 0xff) &&
|
1517 |
|
|
(eth_pkt_dst_mac[4] == (char) 0xff) &&
|
1518 |
|
|
(eth_pkt_dst_mac[5] == (char) 0xff))
|
1519 |
|
|
)
|
1520 |
|
|
)
|
1521 |
|
|
|
1522 |
|
|
return ;
|
1523 |
|
|
|
1524 |
|
|
// Check it's an IP packet
|
1525 |
|
|
if (!(eth_pkt->et_protlen == PROT_IP))
|
1526 |
|
|
return ;
|
1527 |
|
|
|
1528 |
|
|
pkt += ETHER_HDR_SIZE; // Skip eth header stuff
|
1529 |
|
|
|
1530 |
|
|
ip = (IP_t*) pkt;
|
1531 |
|
|
|
1532 |
|
|
// Check if this is an ICMP packet
|
1533 |
|
|
if (!(ip->ip_p == IPPROTO_ICMP))
|
1534 |
|
|
return ;
|
1535 |
|
|
|
1536 |
|
|
// Check if this is for our IP, get pointer to the DST IP part of IP header
|
1537 |
|
|
// which is end of IP section - 4 bytes
|
1538 |
|
|
char * internet_protocol_adr = ((unsigned char*)ip + (IP_HDR_SIZE_NO_UDP-4));
|
1539 |
|
|
|
1540 |
|
|
if (!((internet_protocol_adr[0] == our_ip[0]) &&
|
1541 |
|
|
(internet_protocol_adr[1] == our_ip[1]) &&
|
1542 |
|
|
(internet_protocol_adr[2] == our_ip[2]) &&
|
1543 |
|
|
(internet_protocol_adr[3] == our_ip[3])))
|
1544 |
|
|
return ;
|
1545 |
|
|
|
1546 |
|
|
pkt += IP_HDR_SIZE_NO_UDP;
|
1547 |
|
|
|
1548 |
|
|
icmp = (ICMP_t*) pkt;
|
1549 |
|
|
|
1550 |
|
|
// Currently we only support replying to echo (ping) requests
|
1551 |
|
|
|
1552 |
|
|
// Check for ICMP echo request type
|
1553 |
|
|
if (!(icmp->type == ICMP_TYPE_ECHO_REQ))
|
1554 |
|
|
return;
|
1555 |
|
|
|
1556 |
|
|
// Go ahead and construct a response packet
|
1557 |
|
|
// Setup pointers
|
1558 |
|
|
Ethernet_t * reply_pkt = (Ethernet_t *) &ip_reply_packet[0];
|
1559 |
|
|
IP_t * reply_IP = (IP_t*) &ip_reply_packet[ETHER_HDR_SIZE];
|
1560 |
|
|
ICMP_t * reply_ICMP = (ICMP_t*) &ip_reply_packet[ETHER_HDR_SIZE+
|
1561 |
|
|
IP_HDR_SIZE_NO_UDP];
|
1562 |
|
|
// Setup Ethernet header
|
1563 |
|
|
// Copy source MAC to destination MAC
|
1564 |
|
|
memcpy( (void*)&reply_pkt->et_dest , (void*)ð_pkt->et_src , 6);
|
1565 |
|
|
reply_pkt->et_src[0] = ETH_MACADDR0;
|
1566 |
|
|
reply_pkt->et_src[1] = ETH_MACADDR1;
|
1567 |
|
|
reply_pkt->et_src[2] = ETH_MACADDR2;
|
1568 |
|
|
reply_pkt->et_src[3] = ETH_MACADDR3;
|
1569 |
|
|
reply_pkt->et_src[4] = ETH_MACADDR4;
|
1570 |
|
|
reply_pkt->et_src[5] = ETH_MACADDR5;
|
1571 |
|
|
reply_pkt->et_protlen = PROT_IP;
|
1572 |
|
|
|
1573 |
|
|
// IP header
|
1574 |
|
|
reply_IP->ip_hl_v = 0x45; // version 4, 20 byte long header, not 100% on this!
|
1575 |
|
|
reply_IP->ip_tos = 0x00 ; // ToS (DSCP) - usually used for QoS, set to 0
|
1576 |
|
|
unsigned short ip_indicated_length;
|
1577 |
|
|
// First copy total length indicated in received IP header to a variable, we
|
1578 |
|
|
// need it again later...
|
1579 |
|
|
memcpy ((void*)&ip_indicated_length, (void*)&ip->ip_len, 2);
|
1580 |
|
|
// Now copy into reply IP packet
|
1581 |
|
|
memcpy ((void*)&reply_IP->ip_len, (void*)&ip_indicated_length, 2);
|
1582 |
|
|
memcpy ((void*)&reply_IP->ip_id, (void*)&ip->ip_id, 2); // Copy ID
|
1583 |
|
|
reply_IP->ip_ttl = 0x40; // Packet TTL - 64, typical value
|
1584 |
|
|
reply_IP->ip_p = IPPROTO_ICMP; // Duh, this is an ICMP echo reply
|
1585 |
|
|
// Clear header checksum for now
|
1586 |
|
|
|
1587 |
|
|
memcpy ((void*)&reply_IP->ip_sum, (void*)&zero, 2);
|
1588 |
|
|
memcpy ((void*)&reply_IP->ip_src, (void*)&our_ip[0], 4); // Copy in our IP
|
1589 |
|
|
// "...return to sender... budupbadah address ....KNOWN ..."
|
1590 |
|
|
// WTF this memcpy() fails with alignment error...(?!?!)
|
1591 |
|
|
//memcpy (&reply_IP->ip_dst, &ip->ip_src, sizeof(IPaddr_t));
|
1592 |
|
|
//...OK then, do it manually.....
|
1593 |
|
|
unsigned char *ptr1, *ptr2;
|
1594 |
|
|
ptr1 = &reply_IP->ip_dst; ptr2 = &ip->ip_src;
|
1595 |
|
|
ptr1[0] = ptr2[0];
|
1596 |
|
|
ptr1[1] = ptr2[1];
|
1597 |
|
|
ptr1[2] = ptr2[2];
|
1598 |
|
|
ptr1[3] = ptr2[3];
|
1599 |
|
|
|
1600 |
|
|
// Now calculate the CRC, probably move this to a fuction....
|
1601 |
|
|
unsigned short ip_sum = 0; // Initialise checksum value to 0
|
1602 |
|
|
int itr;
|
1603 |
|
|
char* sum_data_ptr = (char*)reply_IP;
|
1604 |
|
|
ip_sum = calculate_checksum(sum_data_ptr,IP_HDR_SIZE_NO_UDP);
|
1605 |
|
|
/*
|
1606 |
|
|
for(itr=0;itr<IP_HDR_SIZE_NO_UDP;itr+=2)
|
1607 |
|
|
ip_sum += (((sum_data_ptr[itr]<<8)&0xff00)|(sum_data_ptr[itr+1]&0x00ff));
|
1608 |
|
|
while (ip_sum>>16)
|
1609 |
|
|
ip_sum = (ip_sum & 0xffff) + (ip_sum>>16);
|
1610 |
|
|
ip_sum = ~ip_sum;
|
1611 |
|
|
*/
|
1612 |
|
|
|
1613 |
|
|
memcpy ((void*)&reply_IP->ip_sum, (void*)&ip_sum, 2);
|
1614 |
|
|
|
1615 |
|
|
//
|
1616 |
|
|
// Now construct ICMP part of packet
|
1617 |
|
|
//
|
1618 |
|
|
reply_ICMP->type = ICMP_TYPE_ECHO_REPLY; // ping response type
|
1619 |
|
|
reply_ICMP->code = icmp->code; // ICMP code same as sender (is this right?)
|
1620 |
|
|
|
1621 |
|
|
// Clear ICMP checksum for now
|
1622 |
|
|
memcpy ((void*)&reply_ICMP->checksum, (void*)&zero, 2);
|
1623 |
|
|
|
1624 |
|
|
//
|
1625 |
|
|
// Simply copy in the data from the received packet
|
1626 |
|
|
// Figure out how much there is after the checksum
|
1627 |
|
|
// It should be :
|
1628 |
|
|
// length_from_received_IP_header - IP_header_length - initial_ICMP_packet_dat
|
1629 |
|
|
//
|
1630 |
|
|
unsigned long icmp_data_length = ip_indicated_length - IP_HDR_SIZE_NO_UDP - 4;
|
1631 |
|
|
memcpy ((void*)&reply_ICMP->un,(void*)&icmp->un, icmp_data_length);
|
1632 |
|
|
|
1633 |
|
|
// Now calculate checksum for ICMP data
|
1634 |
|
|
unsigned short icmp_sum = 0;
|
1635 |
|
|
sum_data_ptr = (char*)reply_ICMP;
|
1636 |
|
|
icmp_sum = calculate_checksum(sum_data_ptr,icmp_data_length+4);
|
1637 |
|
|
|
1638 |
|
|
memcpy ((void*)&reply_ICMP->checksum, (void*)&icmp_sum, 2);
|
1639 |
|
|
|
1640 |
|
|
// All done!
|
1641 |
|
|
|
1642 |
|
|
tx_packet((void*)ip_reply_packet,ETHER_HDR_SIZE+ip_indicated_length);
|
1643 |
|
|
|
1644 |
|
|
}
|
1645 |
|
|
|
1646 |
|
|
|
1647 |
|
|
|
1648 |
|
|
/*
|
1649 |
|
|
* Address Resolution Protocol (ARP) header.
|
1650 |
|
|
*/
|
1651 |
|
|
typedef struct
|
1652 |
|
|
{
|
1653 |
|
|
unsigned short ar_hrd; /* Format of hardware address */
|
1654 |
|
|
# define ARP_ETHER 1 /* Ethernet hardware address */
|
1655 |
|
|
unsigned short ar_pro; /* Format of protocol address */
|
1656 |
|
|
unsigned char ar_hln; /* Length of hardware address */
|
1657 |
|
|
unsigned char ar_pln; /* Length of protocol address */
|
1658 |
|
|
unsigned short ar_op; /* Operation */
|
1659 |
|
|
# define ARPOP_REQUEST 1 /* Request to resolve address */
|
1660 |
|
|
# define ARPOP_REPLY 2 /* Response to previous request */
|
1661 |
|
|
|
1662 |
|
|
# define RARPOP_REQUEST 3 /* Request to resolve address */
|
1663 |
|
|
# define RARPOP_REPLY 4 /* Response to previous request */
|
1664 |
|
|
|
1665 |
|
|
/*
|
1666 |
|
|
* The remaining fields are variable in size, according to
|
1667 |
|
|
* the sizes above, and are defined as appropriate for
|
1668 |
|
|
* specific hardware/protocol combinations.
|
1669 |
|
|
*/
|
1670 |
|
|
unsigned char ar_data[0];
|
1671 |
|
|
#if 0
|
1672 |
|
|
unsigned char ar_sha[]; /* Sender hardware address */
|
1673 |
|
|
unsigned char ar_spa[]; /* Sender protocol address */
|
1674 |
|
|
unsigned char ar_tha[]; /* Target hardware address */
|
1675 |
|
|
unsigned char ar_tpa[]; /* Target protocol address */
|
1676 |
|
|
#endif /* 0 */
|
1677 |
|
|
} ARP_t;
|
1678 |
|
|
|
1679 |
|
|
#define ARP_HDR_SIZE (8+20) /* Size assuming ethernet */
|
1680 |
|
|
|
1681 |
|
|
char arp_reply_packet[(ETHER_HDR_SIZE + ARP_HDR_SIZE)];
|
1682 |
|
|
|
1683 |
|
|
void
|
1684 |
|
|
packet_check_arp_header(void * pkt)
|
1685 |
|
|
{
|
1686 |
|
|
Ethernet_t * eth_pkt;
|
1687 |
|
|
|
1688 |
|
|
ARP_t * arp;
|
1689 |
|
|
|
1690 |
|
|
//printf("packet_check_arp_header: pkt data at 0x%.8x\n",(unsigned long) pkt);
|
1691 |
|
|
eth_pkt = (Ethernet_t *) pkt;
|
1692 |
|
|
|
1693 |
|
|
if (eth_pkt->et_protlen == 0x0806)
|
1694 |
|
|
{
|
1695 |
|
|
// Is an ARP request
|
1696 |
|
|
// Check the IP
|
1697 |
|
|
pkt += ETHER_HDR_SIZE; // Skip eth header stuff
|
1698 |
|
|
//printf("Is ARP protocol\npkt header now at 0x%.8x\n",pkt);
|
1699 |
|
|
|
1700 |
|
|
arp = (ARP_t*) pkt;
|
1701 |
|
|
|
1702 |
|
|
if (arp->ar_hrd == ARP_ETHER && arp->ar_op == ARPOP_REQUEST)
|
1703 |
|
|
{
|
1704 |
|
|
// Skip forward to the target I.P address
|
1705 |
|
|
|
1706 |
|
|
char * internet_protocol_adr = (((unsigned long)&arp->ar_data[0]) + (arp->ar_hln * 2) + (arp->ar_pln));
|
1707 |
|
|
|
1708 |
|
|
//printf("Is ARP ethernet request\ncheck adr at 0x%.8x\n",internet_protocol_adr);
|
1709 |
|
|
if ((internet_protocol_adr[0] == our_ip[0]) &&
|
1710 |
|
|
(internet_protocol_adr[1] == our_ip[1]) &&
|
1711 |
|
|
(internet_protocol_adr[2] == our_ip[2]) &&
|
1712 |
|
|
(internet_protocol_adr[3] == our_ip[3]))
|
1713 |
|
|
{
|
1714 |
|
|
//printf("Got valid ARP request\n");
|
1715 |
|
|
// Send ARP reply
|
1716 |
|
|
|
1717 |
|
|
Ethernet_t * reply_pkt = (Ethernet_t *)&arp_reply_packet[0];
|
1718 |
|
|
ARP_t * reply_arp = (ARP_t*)&arp_reply_packet[ETHER_HDR_SIZE];
|
1719 |
|
|
memcpy( (void*)&reply_pkt->et_dest , (void*)ð_pkt->et_src , 6);
|
1720 |
|
|
reply_pkt->et_src[0] = ETH_MACADDR0;
|
1721 |
|
|
reply_pkt->et_src[1] = ETH_MACADDR1;
|
1722 |
|
|
reply_pkt->et_src[2] = ETH_MACADDR2;
|
1723 |
|
|
reply_pkt->et_src[3] = ETH_MACADDR3;
|
1724 |
|
|
reply_pkt->et_src[4] = ETH_MACADDR4;
|
1725 |
|
|
reply_pkt->et_src[5] = ETH_MACADDR5;
|
1726 |
|
|
reply_pkt->et_protlen = 0x0806;
|
1727 |
|
|
// ARP part of packet
|
1728 |
|
|
reply_arp->ar_hrd = ARP_ETHER;
|
1729 |
|
|
reply_arp->ar_pro = 0x0800; // IP Protocol
|
1730 |
|
|
reply_arp->ar_hln = 0x06;
|
1731 |
|
|
reply_arp->ar_pln = 0x04;
|
1732 |
|
|
reply_arp->ar_op = ARPOP_REPLY;
|
1733 |
|
|
// My MAC
|
1734 |
|
|
memcpy( (void*)&reply_arp->ar_data[0] , (void*)&reply_pkt->et_src , 6);
|
1735 |
|
|
// My IP
|
1736 |
|
|
memcpy( (void*)&reply_arp->ar_data[6] , (void*)&our_ip , 4);
|
1737 |
|
|
// Their MAC
|
1738 |
|
|
memcpy( (void*)&reply_arp->ar_data[10] , (void*)ð_pkt->et_src , 6);
|
1739 |
|
|
// Their IP
|
1740 |
|
|
char * their_internet_protocol_adr =
|
1741 |
|
|
(((unsigned long)&arp->ar_data[0]) + arp->ar_hln );
|
1742 |
|
|
memcpy( (void*)&reply_arp->ar_data[16] , (void*)&their_internet_protocol_adr[0] , 4);
|
1743 |
|
|
|
1744 |
|
|
tx_packet((void*)arp_reply_packet,(ETHER_HDR_SIZE+ARP_HDR_SIZE) );
|
1745 |
|
|
|
1746 |
|
|
}
|
1747 |
|
|
}
|
1748 |
|
|
}
|
1749 |
|
|
}
|
1750 |
|
|
|
1751 |
|
|
|
1752 |
|
|
|
1753 |
|
|
static void
|
1754 |
|
|
oeth_rx(void)
|
1755 |
|
|
{
|
1756 |
|
|
volatile oeth_regs *regs;
|
1757 |
|
|
regs = (oeth_regs *)(OETH_REG_BASE);
|
1758 |
|
|
|
1759 |
|
|
volatile oeth_bd *rx_bdp;
|
1760 |
|
|
int pkt_len, i;
|
1761 |
|
|
int bad = 0;
|
1762 |
|
|
|
1763 |
|
|
rx_bdp = ((oeth_bd *)OETH_BD_BASE) + OETH_TXBD_NUM;
|
1764 |
|
|
|
1765 |
411 |
julius |
if (print_packet_contents)
|
1766 |
|
|
printf("rx");
|
1767 |
349 |
julius |
|
1768 |
|
|
/* Find RX buffers marked as having received data */
|
1769 |
|
|
for(i = 0; i < OETH_RXBD_NUM; i++)
|
1770 |
|
|
{
|
1771 |
|
|
if(!(rx_bdp[i].len_status & OETH_RX_BD_EMPTY)){ /* Looking for NOT empty buffers desc. */
|
1772 |
|
|
/* Check status for errors.
|
1773 |
|
|
*/
|
1774 |
|
|
if (rx_bdp[i].len_status & (OETH_RX_BD_TOOLONG | OETH_RX_BD_SHORT)) {
|
1775 |
|
|
bad = 1;
|
1776 |
|
|
}
|
1777 |
|
|
if (rx_bdp[i].len_status & OETH_RX_BD_DRIBBLE) {
|
1778 |
|
|
bad = 1;
|
1779 |
|
|
}
|
1780 |
|
|
if (rx_bdp[i].len_status & OETH_RX_BD_CRCERR) {
|
1781 |
|
|
bad = 1;
|
1782 |
|
|
}
|
1783 |
|
|
if (rx_bdp[i].len_status & OETH_RX_BD_OVERRUN) {
|
1784 |
|
|
bad = 1;
|
1785 |
|
|
}
|
1786 |
|
|
if (rx_bdp[i].len_status & OETH_RX_BD_MISS) {
|
1787 |
|
|
|
1788 |
|
|
}
|
1789 |
|
|
if (rx_bdp[i].len_status & OETH_RX_BD_LATECOL) {
|
1790 |
|
|
bad = 1;
|
1791 |
|
|
}
|
1792 |
|
|
|
1793 |
|
|
if (bad) {
|
1794 |
425 |
julius |
printf("RXE: 0x%x\n",rx_bdp[i].len_status & OETH_RX_BD_STATS);
|
1795 |
349 |
julius |
rx_bdp[i].len_status &= ~OETH_RX_BD_STATS;
|
1796 |
|
|
rx_bdp[i].len_status |= OETH_RX_BD_EMPTY;
|
1797 |
425 |
julius |
bad = 0;
|
1798 |
349 |
julius |
continue;
|
1799 |
|
|
}
|
1800 |
|
|
else {
|
1801 |
|
|
|
1802 |
|
|
/* Process the incoming frame.
|
1803 |
|
|
*/
|
1804 |
|
|
pkt_len = rx_bdp[i].len_status >> 16;
|
1805 |
|
|
|
1806 |
|
|
/* Do something here with the data - copy it into userspace, perhaps. */
|
1807 |
|
|
// See if it's an ARP packet
|
1808 |
|
|
packet_check_arp_header((void *)rx_bdp[i].addr );
|
1809 |
|
|
// See if it's an ICMP echo request
|
1810 |
|
|
packet_check_icmp_header((void *)rx_bdp[i].addr );
|
1811 |
411 |
julius |
if (print_packet_contents)
|
1812 |
|
|
{
|
1813 |
|
|
oeth_print_packet(rx_bdp[i].addr, rx_bdp[i].len_status >> 16);
|
1814 |
|
|
printf("\t end of packet\n\n");
|
1815 |
|
|
}
|
1816 |
349 |
julius |
/* finish up */
|
1817 |
|
|
rx_bdp[i].len_status &= ~OETH_RX_BD_STATS; /* Clear stats */
|
1818 |
|
|
rx_bdp[i].len_status |= OETH_RX_BD_EMPTY; /* Mark RX BD as empty */
|
1819 |
|
|
|
1820 |
|
|
|
1821 |
|
|
}
|
1822 |
|
|
}
|
1823 |
|
|
}
|
1824 |
|
|
}
|
1825 |
|
|
|
1826 |
|
|
|
1827 |
|
|
|
1828 |
|
|
static void
|
1829 |
|
|
oeth_tx(void)
|
1830 |
|
|
{
|
1831 |
|
|
volatile oeth_bd *tx_bd;
|
1832 |
|
|
int i;
|
1833 |
411 |
julius |
if (print_packet_contents)
|
1834 |
|
|
printf("tx");
|
1835 |
|
|
|
1836 |
349 |
julius |
tx_bd = (volatile oeth_bd *)OETH_BD_BASE; /* Search from beginning*/
|
1837 |
|
|
|
1838 |
|
|
/* Go through the TX buffs, search for one that was just sent */
|
1839 |
|
|
for(i = 0; i < OETH_TXBD_NUM; i++)
|
1840 |
|
|
{
|
1841 |
|
|
/* Looking for buffer NOT ready for transmit. and IRQ enabled */
|
1842 |
|
|
if( (!(tx_bd[i].len_status & (OETH_TX_BD_READY))) && (tx_bd[i].len_status & (OETH_TX_BD_IRQ)) )
|
1843 |
|
|
{
|
1844 |
|
|
//oeth_print_packet(tx_bd[i].addr, (tx_bd[i].len_status >> 16));
|
1845 |
|
|
/* Single threaded so no chance we have detected a buffer that has had its IRQ bit set but not its BD_READ flag. Maybe this won't work in linux */
|
1846 |
|
|
tx_bd[i].len_status &= ~OETH_TX_BD_IRQ;
|
1847 |
|
|
|
1848 |
|
|
/* Probably good to check for TX errors here */
|
1849 |
425 |
julius |
// Check if either carrier sense lost or colission indicated
|
1850 |
|
|
if (tx_bd[i].len_status & OETH_TX_BD_STATS)
|
1851 |
|
|
printf("TXER: 0x%x\n",(tx_bd[i].len_status & OETH_TX_BD_STATS));
|
1852 |
349 |
julius |
|
1853 |
411 |
julius |
if (print_packet_contents)
|
1854 |
|
|
printf("T%d",i);
|
1855 |
349 |
julius |
}
|
1856 |
|
|
}
|
1857 |
|
|
return;
|
1858 |
|
|
}
|
1859 |
|
|
|
1860 |
|
|
|
1861 |
|
|
int main ()
|
1862 |
|
|
{
|
1863 |
411 |
julius |
|
1864 |
|
|
print_packet_contents = 0; // Default to not printing packet contents.
|
1865 |
|
|
|
1866 |
408 |
julius |
/* Initialise vector handler */
|
1867 |
349 |
julius |
int_init();
|
1868 |
|
|
|
1869 |
|
|
/* Install ethernet interrupt handler, it is enabled here too */
|
1870 |
|
|
int_add(ETH0_IRQ, oeth_interrupt, 0);
|
1871 |
|
|
|
1872 |
408 |
julius |
/* Enable interrupts */
|
1873 |
|
|
cpu_enable_user_interrupts();
|
1874 |
349 |
julius |
|
1875 |
|
|
last_char=0; /* Variable init for spin_cursor() */
|
1876 |
|
|
next_tx_buf_num = 4; /* init for tx buffer counter */
|
1877 |
|
|
|
1878 |
|
|
uart_init(DEFAULT_UART); // init the UART before we can printf
|
1879 |
|
|
printf("\n\teth ping program\n\n");
|
1880 |
|
|
printf("\n\tboard IP: %d.%d.%d.%d\n",our_ip[0]&0xff,our_ip[1]&0xff,
|
1881 |
|
|
our_ip[2]&0xff,our_ip[3]&0xff);
|
1882 |
|
|
|
1883 |
|
|
ethmac_setup(); /* Configure MAC, TX/RX BDs and enable RX and TX in MODER */
|
1884 |
|
|
|
1885 |
|
|
//scan_ethphys(); /* Scan MIIM bus for PHYs */
|
1886 |
411 |
julius |
//ethphy_init(); /* Attempt reset and configuration of PHY via MIIM */
|
1887 |
349 |
julius |
//ethmac_scanstatus(); /* Enable scanning of status register via MIIM */
|
1888 |
|
|
|
1889 |
|
|
/* Loop, monitoring user input from TTY */
|
1890 |
|
|
while(1)
|
1891 |
|
|
{
|
1892 |
|
|
char c;
|
1893 |
|
|
|
1894 |
|
|
while(!uart_check_for_char(DEFAULT_UART))
|
1895 |
|
|
{
|
1896 |
|
|
spin_cursor();
|
1897 |
411 |
julius |
//oeth_monitor_rx();
|
1898 |
349 |
julius |
}
|
1899 |
|
|
|
1900 |
|
|
c = uart_getc(DEFAULT_UART);
|
1901 |
|
|
|
1902 |
|
|
if (c == 's')
|
1903 |
|
|
tx_packet((void*) ping_packet, 98);
|
1904 |
435 |
julius |
else if (c == 'S')
|
1905 |
349 |
julius |
tx_packet((void*)big_ping_packet, 1514);
|
1906 |
435 |
julius |
else if (c == 'h')
|
1907 |
349 |
julius |
scan_ethphys();
|
1908 |
435 |
julius |
else if (c == 'i')
|
1909 |
349 |
julius |
ethphy_init();
|
1910 |
435 |
julius |
else if (c == 'P')
|
1911 |
415 |
julius |
{
|
1912 |
|
|
print_packet_contents = print_packet_contents ? 0 : 1;
|
1913 |
|
|
if (print_packet_contents)
|
1914 |
|
|
printf("Enabling packet dumping\n");
|
1915 |
|
|
else
|
1916 |
|
|
printf("Packet dumping disabled\n");
|
1917 |
|
|
}
|
1918 |
435 |
julius |
else if (c == 'p')
|
1919 |
349 |
julius |
oeth_printregs();
|
1920 |
435 |
julius |
else if (c == '0')
|
1921 |
349 |
julius |
scan_ethphy(0);
|
1922 |
435 |
julius |
else if (c == '1')
|
1923 |
349 |
julius |
scan_ethphy(1);
|
1924 |
435 |
julius |
else if (c == '7')
|
1925 |
349 |
julius |
{
|
1926 |
415 |
julius |
//scan_ethphy(7);
|
1927 |
|
|
//ethphy_print_status(7);
|
1928 |
|
|
printf("ext_sr 0x%x\n",eth_mii_read(0x7, 0x1b));
|
1929 |
349 |
julius |
}
|
1930 |
435 |
julius |
else if (c == 'r')
|
1931 |
415 |
julius |
{
|
1932 |
|
|
ethphy_reset(7);
|
1933 |
|
|
printf("PHY reset\n");
|
1934 |
|
|
}
|
1935 |
435 |
julius |
else if (c == 'R')
|
1936 |
415 |
julius |
{
|
1937 |
|
|
//oeth_reset_tx_bd_pointer();
|
1938 |
|
|
ethmac_setup();
|
1939 |
|
|
printf("MAC reset\n");
|
1940 |
|
|
}
|
1941 |
435 |
julius |
else if (c == 'n')
|
1942 |
415 |
julius |
ethphy_reneg(7);
|
1943 |
435 |
julius |
else if (c == 'N')
|
1944 |
415 |
julius |
ethphy_set_autoneg(7);
|
1945 |
435 |
julius |
else if (c == 'm')
|
1946 |
349 |
julius |
ethmac_togglehugen();
|
1947 |
435 |
julius |
else if (c == 't')
|
1948 |
349 |
julius |
ethphy_set_10mbit(0);
|
1949 |
435 |
julius |
else if (c == 'w')
|
1950 |
415 |
julius |
{
|
1951 |
|
|
// Play with HWCFG mode of Alaska 88e1111 Phy
|
1952 |
|
|
c = uart_getc(DEFAULT_UART);
|
1953 |
|
|
short newvalue;
|
1954 |
|
|
// c is an ascii char, let's convert it to actual hex value
|
1955 |
|
|
if (c >= 'A' && c <= 'F')
|
1956 |
|
|
newvalue = c - (65 - 10);
|
1957 |
|
|
else if (c >= 'a' && c <= 'f')
|
1958 |
|
|
newvalue = c - (99 - 10);
|
1959 |
|
|
else if (c >= '0' && c <= '9')
|
1960 |
|
|
newvalue = c - 48;
|
1961 |
|
|
|
1962 |
|
|
// Take this value and or it into the bottom bit (supposedly ext_sr)
|
1963 |
|
|
#define MII_M1111_PHY_EXT_SR 0x1b
|
1964 |
|
|
short ext_sr;
|
1965 |
|
|
ext_sr = eth_mii_read(0x7, MII_M1111_PHY_EXT_SR);
|
1966 |
|
|
#define MII_M1111_HWCFG_MODE_MASK 0xf
|
1967 |
|
|
ext_sr &= ~MII_M1111_HWCFG_MODE_MASK;
|
1968 |
|
|
ext_sr |= (short) newvalue;
|
1969 |
|
|
eth_mii_write(0x7, MII_M1111_PHY_EXT_SR, ext_sr);
|
1970 |
|
|
printf("ext_sr updated to - 0x%x\n",eth_mii_read(0x7, MII_M1111_PHY_EXT_SR));
|
1971 |
|
|
}
|
1972 |
435 |
julius |
else if ( c == 'b' )
|
1973 |
349 |
julius |
{
|
1974 |
|
|
printf("\n\t---\n");
|
1975 |
|
|
oeth_dump_bds();
|
1976 |
|
|
printf("\t---\n");
|
1977 |
|
|
}
|
1978 |
435 |
julius |
|
1979 |
|
|
else if ( c == 'B' )
|
1980 |
|
|
{
|
1981 |
|
|
tx_packet((void*) broadcast_ping_packet, 298);
|
1982 |
|
|
}
|
1983 |
349 |
julius |
|
1984 |
|
|
}
|
1985 |
|
|
|
1986 |
|
|
}
|