OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [orpsocv2/] [sw/] [tests/] [ethmac/] [board/] [ethmac-ping.c] - Blame information for rev 530

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.