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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [bootloaders/] [orpmon/] [drivers/] [eth.c] - Blame information for rev 248

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

Line No. Rev Author Line
1 2 marcus.erl
#include "board.h"
2
#if OC_LAN==1
3
 
4
#include "common.h"
5
#include "support.h"
6
#include "uart.h"
7
#include "eth.h"
8
#include "int.h"
9 246 julius
#include "spr-defs.h"
10 2 marcus.erl
 
11 140 julius
//#define PRINT_PACKETS
12
//#define ETHPHY_10MBPS
13
 
14 2 marcus.erl
extern int printf (const char *fmt, ...);
15
extern void lolev_ie(void);
16
extern void lolev_idis(void);
17
 
18
int tx_next;  /* Next buffer to be given to the user */
19
int tx_last;  /* Next buffer to be checked if packet sent */
20
int tx_full;
21
int rx_next;  /* Next buffer to be checked for new packet and given to the user */
22
void (*receive)(volatile unsigned char *add, int len); /* Pointer to function to be called
23
                                        when frame is received */
24 140 julius
int eth_monitor_enabled;
25 2 marcus.erl
 
26 140 julius
//unsigned long eth_data[((ETH_TXBD_NUM + ETH_RXBD_NUM) * ETH_MAXBUF_LEN)/4] = {0};
27
//#undef ETH_DATA_BASE
28
//#define ETH_DATA_BASE ((unsigned long)eth_data)
29 2 marcus.erl
 
30 140 julius
 
31 2 marcus.erl
static void
32
print_packet(unsigned long add, int len)
33
{
34
  int i;
35
 
36
  printf("ipacket: add = %lx len = %d\n", add, len);
37
  for(i = 0; i < len; i++) {
38 140 julius
      if(!(i % 16)) printf("\n");
39
      else if(!(i % 8)) printf(" "); // space here, so output is like wireshark
40 2 marcus.erl
      printf(" %.2x", *(((unsigned char *)add) + i));
41
  }
42
  printf("\n");
43
}
44
 
45
void init_tx_bd_pool(void)
46
{
47
  eth_bd  *bd;
48
  int i;
49
 
50
  bd = (eth_bd *)ETH_BD_BASE;
51
 
52
  for(i = 0; i < ETH_TXBD_NUM; i++) {
53
    /* Set Tx BD status */
54
    bd[i].len_status = 0 << 16 | ETH_TX_BD_PAD | ETH_TX_BD_CRC | ETH_RX_BD_IRQ;
55
 
56
    /* Initialize Tx buffer pointer */
57
    bd[i].addr = ETH_DATA_BASE + (i * ETH_MAXBUF_LEN);
58
  }
59
 
60
  bd[i-1].len_status |= ETH_TX_BD_WRAP; // Last Tx BD - Wrap
61
}
62
 
63
void init_rx_bd_pool(void)
64
{
65
  eth_bd  *bd;
66
  int i;
67
 
68
  bd = (eth_bd *)ETH_BD_BASE + ETH_TXBD_NUM;
69
 
70
  for(i = 0; i < ETH_RXBD_NUM; i++){
71
 
72
    /* Set Rx BD status */
73
    bd[i].len_status = 0 << 16 | ETH_RX_BD_EMPTY | ETH_RX_BD_IRQ;
74
 
75
    /* Initialize Rx buffer pointer */
76
    bd[i].addr = ETH_DATA_BASE + ((ETH_TXBD_NUM + i) * ETH_MAXBUF_LEN);
77
  }
78
 
79
  bd[i-1].len_status |= ETH_RX_BD_WRAP; // Last Rx BD - Wrap
80
}
81
 
82 140 julius
 
83
void eth_traffic_monitor(void)
84
{
85
 volatile oeth_regs *regs;
86
  regs = (oeth_regs *)(ETH_REG_BASE);
87
 
88
  uint  int_events;
89
  int serviced;
90
  int i;
91
 
92
  serviced = 0;
93
 
94
  /* Get the interrupt events that caused us to be here.
95
   */
96
  int_events = regs->int_src;
97
  regs->int_src = int_events;
98
 
99
  printf("\n=tx_ | %x | %x | %x | %x | %x | %x | %x | %x\n",
100
         ((oeth_bd *)(ETH_BD_BASE))->len_status,
101
         ((oeth_bd *)(ETH_BD_BASE+8))->len_status,
102
         ((oeth_bd *)(ETH_BD_BASE+16))->len_status,
103
         ((oeth_bd *)(ETH_BD_BASE+24))->len_status,
104
         ((oeth_bd *)(ETH_BD_BASE+32))->len_status,
105
         ((oeth_bd *)(ETH_BD_BASE+40))->len_status,
106
         ((oeth_bd *)(ETH_BD_BASE+48))->len_status,
107
         ((oeth_bd *)(ETH_BD_BASE+56))->len_status);
108
 
109
  printf("=rx_ | %x | %x | %x | %x | %x | %x | %x | %x\n",
110
         ((oeth_bd *)(ETH_BD_BASE+64))->len_status,
111
         ((oeth_bd *)(ETH_BD_BASE+64+8))->len_status,
112
         ((oeth_bd *)(ETH_BD_BASE+64+16))->len_status,
113
         ((oeth_bd *)(ETH_BD_BASE+64+24))->len_status,
114
         ((oeth_bd *)(ETH_BD_BASE+64+32))->len_status,
115
         ((oeth_bd *)(ETH_BD_BASE+64+40))->len_status,
116
         ((oeth_bd *)(ETH_BD_BASE+64+48))->len_status,
117
         ((oeth_bd *)(ETH_BD_BASE+64+56))->len_status);
118
 
119
  printf("=int | txb %d | txe %d | rxb %d | rxe %d | busy %d\n",
120
         (int_events & ETH_INT_TXB) > 0,
121
         (int_events & ETH_INT_TXE) > 0,
122
         (int_events & ETH_INT_RXF) > 0,
123
         (int_events & ETH_INT_RXE) > 0,
124
         (int_events & ETH_INT_BUSY) > 0);
125
 
126
 
127
  /* Check for receive busy, i.e. packets coming but no place to
128
   * put them.
129
   */
130
  if (int_events & ETH_INT_BUSY ) {
131
    serviced |= 0x4;
132
    printf("eth: busy!");
133
  }
134
 
135
  /* Handle receive event
136
   */
137
  if (int_events & (ETH_INT_RXF | ETH_INT_RXE)) {
138
    serviced |= 0x1;
139
    volatile oeth_bd *rx_bdp;
140
    rx_bdp = ((oeth_bd *)ETH_BD_BASE) + ETH_TXBD_NUM;
141
    /* Find RX buffers marked as having received data */
142
    for(i = 0; i < ETH_RXBD_NUM; i++)
143
      {
144
        if(!(rx_bdp[i].len_status & ETH_RX_BD_EMPTY))
145
          {
146
            print_packet(rx_bdp[i].addr, rx_bdp[i].len_status >> 16);
147
            rx_bdp[i].len_status &= ~ETH_RX_BD_STATS;  /* Clear stats */
148
            rx_bdp[i].len_status |= ETH_RX_BD_EMPTY; /* Mark RX BD as empty */
149
          }
150
      }
151
  }
152
 
153
  /* Handle transmit event
154
   */
155
  if (int_events & (ETH_INT_TXB | ETH_INT_TXE)) {
156
    serviced |= 0x2;
157
    volatile oeth_bd *tx_bd;
158
    tx_bd = (volatile oeth_bd *)ETH_BD_BASE; /* Search from beginning*/
159
    for(i = 0; i < ETH_TXBD_NUM; i++)
160
      {
161
        /* Looking for buffer NOT ready for transmit */
162
        if((!(tx_bd[i].len_status & (ETH_TX_BD_READY))) &&
163
           (tx_bd[i].len_status & (ETH_TX_BD_IRQ)))
164
          {
165
            print_packet(tx_bd[i].addr, (tx_bd[i].len_status >> 16));
166
            tx_bd[i].len_status &= ~ETH_TX_BD_IRQ;
167
          }
168
      }
169
 
170
  }
171
 
172
  if (serviced == 0)
173
    printf("\neth interrupt called but nothing serviced\n");
174
 
175
}
176
 
177
 
178 2 marcus.erl
/* Ethernet interrupt handler */
179
void eth_int (void)
180
{
181 140 julius
  printf("eth-int!\n");
182
  if (eth_monitor_enabled)
183
    eth_traffic_monitor();
184
  //REG32(ETH_REG_BASE + ETH_INT) = 0xffffffff;
185
 
186 2 marcus.erl
}
187
 
188 140 julius
void eth_reset_phy(void)
189
{
190
  /* Reset Eth PHY via MDIO*/
191
  printf("Resetting PHY, waiting for link");
192
  REG32(ETH_REG_BASE + ETH_MIIADDRESS) = (0<<8)|(ETH_MDIOPHYADDR&0xff);
193
  REG32(ETH_REG_BASE + ETH_MIITX_DATA) = 0x8000; // Bit 15 = 1: RESET
194
  REG32(ETH_REG_BASE + ETH_MIICOMMAND) = ETH_MIICOMMAND_WCTRLDATA;
195
  while(REG32(ETH_REG_BASE + ETH_MIISTATUS) & ETH_MIISTATUS_BUSY);
196
 
197
  sleep(100);
198
 
199
  while(1){
200
    printf(".");
201
    REG32(ETH_REG_BASE + ETH_MIIADDRESS) = (0<<8)|(ETH_MDIOPHYADDR&0xff);
202
    REG32(ETH_REG_BASE + ETH_MIICOMMAND) = ETH_MIICOMMAND_RSTAT;
203
    while(REG32(ETH_REG_BASE + ETH_MIISTATUS) & ETH_MIISTATUS_BUSY);
204
    if(!(REG32(ETH_REG_BASE + ETH_MIIRX_DATA) & 0x8000)) // If reset clear
205
      break;
206
  }
207
}
208
 
209
 
210 2 marcus.erl
void eth_init (void (*rec)(volatile unsigned char *, int))
211
{
212
  /* Reset ethernet core */
213
  REG32(ETH_REG_BASE + ETH_MODER) = ETH_MODER_RST;    /* Reset ON */
214
  REG32(ETH_REG_BASE + ETH_MODER) &= ~ETH_MODER_RST;  /* Reset OFF */
215
 
216
  /* Setting TX BD number */
217
  REG32(ETH_REG_BASE + ETH_TX_BD_NUM) = ETH_TXBD_NUM;
218 140 julius
 
219
#ifdef ETHPHY_10MBPS
220 2 marcus.erl
  // Set PHY to 10 Mbps full duplex
221
  REG32(ETH_REG_BASE + ETH_MIIADDRESS) = 0<<8;
222
  REG32(ETH_REG_BASE + ETH_MIITX_DATA) = 0x0100;
223
  REG32(ETH_REG_BASE + ETH_MIICOMMAND) = ETH_MIICOMMAND_WCTRLDATA;
224
  while(REG32(ETH_REG_BASE + ETH_MIISTATUS) & ETH_MIISTATUS_BUSY);
225
 
226
  while(1){
227
    REG32(ETH_REG_BASE + ETH_MIIADDRESS) = 1<<8;
228
    REG32(ETH_REG_BASE + ETH_MIICOMMAND) = ETH_MIICOMMAND_RSTAT;
229
    while(REG32(ETH_REG_BASE + ETH_MIISTATUS) & ETH_MIISTATUS_BUSY);
230
    if(REG32(ETH_REG_BASE + ETH_MIIRX_DATA) & 0x04)
231
      break;
232
  }
233 140 julius
 
234
#endif
235 2 marcus.erl
 
236
  /* Set min/max packet length */
237
  REG32(ETH_REG_BASE + ETH_PACKETLEN) = 0x00400600;
238
 
239
  /* Set IPGT register to recomended value */
240
  REG32(ETH_REG_BASE + ETH_IPGT) =  0x00000012;
241
 
242
  /* Set IPGR1 register to recomended value */
243
  REG32(ETH_REG_BASE + ETH_IPGR1) =  0x0000000c;
244
 
245
  /* Set IPGR2 register to recomended value */
246
  REG32(ETH_REG_BASE + ETH_IPGR2) =  0x00000012;
247
 
248
  /* Set COLLCONF register to recomended value */
249
  REG32(ETH_REG_BASE + ETH_COLLCONF) =  0x000f003f;
250
 
251
#if 0
252 140 julius
  REG32(ETH_REG_BASE + ETH_CTRLMODER) = ETH_CTRLMODER_TXFLOW | ETH_CTRLMODER_RXFLOW;
253 2 marcus.erl
#else
254
  REG32(ETH_REG_BASE + ETH_CTRLMODER) = 0;
255
#endif
256
 
257
  /* Initialize RX and TX buffer descriptors */
258
  init_rx_bd_pool();
259
  init_tx_bd_pool();
260
 
261
  /* Initialize tx pointers */
262
  tx_next = 0;
263
  tx_last = 0;
264
  tx_full = 0;
265
 
266
  /* Initialize rx pointers */
267
  rx_next = 0;
268
  receive = rec;
269
 
270
  /* Set local MAC address */
271
  REG32(ETH_REG_BASE + ETH_MAC_ADDR1) = ETH_MACADDR0 << 8 |
272
            ETH_MACADDR1;
273
  REG32(ETH_REG_BASE + ETH_MAC_ADDR0) = ETH_MACADDR2 << 24 |
274
            ETH_MACADDR3 << 16 |
275
            ETH_MACADDR4 << 8 |
276
            ETH_MACADDR5;
277
 
278
  /* Clear all pending interrupts */
279
  REG32(ETH_REG_BASE + ETH_INT) = 0xffffffff;
280
 
281
  /* Promisc, IFG, CRCEn */
282
  REG32(ETH_REG_BASE + ETH_MODER) |= ETH_MODER_PAD | ETH_MODER_IFG | ETH_MODER_CRCEN;
283
 
284
  /* Enable interrupt sources */
285
#if 0
286 140 julius
  REG32(ETH_REG_BASE + ETH_INT_MASK)= ETH_INT_MASK_TXB        |
287 2 marcus.erl
                   ETH_INT_MASK_TXE        |
288
                   ETH_INT_MASK_RXF        |
289
                   ETH_INT_MASK_RXE        |
290
                   ETH_INT_MASK_BUSY       |
291
                   ETH_INT_MASK_TXC        |
292
                   ETH_INT_MASK_RXC;
293 140 julius
  eth_monitor_enabled = 1;
294 2 marcus.erl
#else
295
  REG32(ETH_REG_BASE + ETH_INT_MASK) = 0x00000000;
296 140 julius
  printf("eth_init: monitor disabled at startup\n");
297
  eth_monitor_enabled = 0;
298 2 marcus.erl
#endif
299
 
300
  /* Enable receiver and transmiter */
301
  REG32(ETH_REG_BASE + ETH_MODER) |= ETH_MODER_RXEN | ETH_MODER_TXEN;
302
 
303
  /* Register interrupt handler */
304
  int_add (ETH_IRQ, eth_int);
305
}
306
 
307
/* Returns pointer to next free buffer; NULL if none available */
308
void *eth_get_tx_buf ()
309
{
310
  eth_bd  *bd;
311
  unsigned long add;
312
 
313
  if(tx_full)
314
    return (void *)0;
315
 
316
  bd = (eth_bd *)ETH_BD_BASE;
317
 
318
  if(bd[tx_next].len_status & ETH_TX_BD_READY)
319
    return (void *)0;
320
 
321
  add = bd[tx_next].addr;
322
 
323
  tx_next = (tx_next + 1) & ETH_TXBD_NUM_MASK;
324
 
325
  if(tx_next == tx_last)
326 140 julius
      tx_full = 1;
327 2 marcus.erl
 
328
  return (void *)add;
329
}
330
 
331
/* Send a packet at address */
332
void eth_send (void *buf, unsigned long len)
333
{
334 140 julius
    eth_bd  *bd;
335 246 julius
    int i;
336 2 marcus.erl
 
337 140 julius
#ifdef PRINT_PACKETS  
338
  printf("transmitted packet:\t");
339
  print_packet(buf, len);
340
#endif
341
 
342 2 marcus.erl
  bd = (eth_bd *)ETH_BD_BASE;
343
 
344
  bd[tx_last].addr = (unsigned long)buf;
345 246 julius
 
346 140 julius
 retry_eth_send:
347 2 marcus.erl
  bd[tx_last].len_status &= 0x0000ffff & ~ETH_TX_BD_STATS;
348 140 julius
  if (eth_monitor_enabled) // enable IRQ when sending
349
    bd[tx_last].len_status |= ETH_TX_BD_IRQ;
350 2 marcus.erl
  bd[tx_last].len_status |= len << 16 | ETH_TX_BD_READY;
351
 
352 140 julius
  /*
353
  while (bd[tx_last].len_status & ETH_TX_BD_READY);
354
  printf("packet tx\n");
355
  // Check it was sent OK
356
  if ( bd[tx_last].len_status & 0x2)
357
    {
358
      printf("eth_send: carrier sense lost (txbd: 0x%x), deferred, retrying\n",
359
             bd[tx_last].len_status);
360
      sleep(1000);
361
      goto retry_eth_send;
362
    }
363
  */
364 2 marcus.erl
  tx_last = (tx_last + 1) & ETH_TXBD_NUM_MASK;
365
  tx_full = 0;
366 140 julius
 
367 2 marcus.erl
}
368
 
369
/* Waits for packet and pass it to the upper layers */
370
unsigned long eth_rx (void)
371
{
372
  eth_bd  *bd;
373
  unsigned long len = 0;
374 246 julius
  int i;
375 2 marcus.erl
 
376
  bd = (eth_bd *)ETH_BD_BASE + ETH_TXBD_NUM;
377 140 julius
 
378 2 marcus.erl
  while(1) {
379
 
380
    int bad = 0;
381
 
382
    if(bd[rx_next].len_status & ETH_RX_BD_EMPTY)
383
      return len;
384 246 julius
 
385 2 marcus.erl
    if(bd[rx_next].len_status & ETH_RX_BD_OVERRUN) {
386
      printf("eth rx: ETH_RX_BD_OVERRUN\n");
387
      bad = 1;
388
    }
389
    if(bd[rx_next].len_status & ETH_RX_BD_INVSIMB) {
390
      printf("eth rx: ETH_RX_BD_INVSIMB\n");
391
      bad = 1;
392
    }
393
    if(bd[rx_next].len_status & ETH_RX_BD_DRIBBLE) {
394
      printf("eth rx: ETH_RX_BD_DRIBBLE\n");
395
      bad = 1;
396
    }
397
    if(bd[rx_next].len_status & ETH_RX_BD_TOOLONG) {
398
      printf("eth rx: ETH_RX_BD_TOOLONG\n");
399
      bad = 1;
400
    }
401
    if(bd[rx_next].len_status & ETH_RX_BD_SHORT) {
402
      printf("eth rx: ETH_RX_BD_SHORT\n");
403
      bad = 1;
404
    }
405
    if(bd[rx_next].len_status & ETH_RX_BD_CRCERR) {
406
      printf("eth rx: ETH_RX_BD_CRCERR\n");
407
      bad = 1;
408
    }
409
    if(bd[rx_next].len_status & ETH_RX_BD_LATECOL) {
410
      printf("eth rx: ETH_RX_BD_LATECOL\n");
411
      bad = 1;
412
    }
413
 
414
    if(!bad) {
415 140 julius
#ifdef PRINT_PACKETS
416
      printf("received packet:\t");
417
      print_packet(bd[rx_next].addr, bd[rx_next].len_status >> 16);
418
#endif
419 246 julius
 
420 2 marcus.erl
      receive((void *)bd[rx_next].addr, bd[rx_next].len_status >> 16);
421
      len += bd[rx_next].len_status >> 16;
422
    }
423
 
424
    bd[rx_next].len_status &= ~ETH_RX_BD_STATS;
425
    bd[rx_next].len_status |= ETH_RX_BD_EMPTY;
426
 
427
    rx_next = (rx_next + 1) & ETH_RXBD_NUM_MASK;
428
  }
429
}
430
 
431
void eth_int_enable(void)
432
{
433
  REG32(ETH_REG_BASE + ETH_INT_MASK) =  ETH_INT_MASK_TXB        |
434
                                        ETH_INT_MASK_TXE        |
435
                                        ETH_INT_MASK_RXF        |
436
                                        ETH_INT_MASK_RXE        |
437
                                        ETH_INT_MASK_BUSY       |
438
                                        ETH_INT_MASK_TXC        |
439
                                        ETH_INT_MASK_RXC;
440
}
441
 
442 140 julius
void eth_int_disable(void)
443
{
444
  REG32(ETH_REG_BASE + ETH_INT_MASK) = 0;
445
}
446
 
447 2 marcus.erl
void eth_halt(void)
448
{
449 140 julius
  /* Disable receiver and transmiter */
450 2 marcus.erl
  REG32(ETH_REG_BASE + ETH_MODER) &= ~(ETH_MODER_RXEN | ETH_MODER_TXEN);
451
}
452 140 julius
 
453
 
454
void eth_toggle_traffic_mon(void)
455
{
456
  if (!eth_monitor_enabled)
457
    {
458
      printf("eth_toggle_traffic_mon: traffic monitor ENABLED\n");
459
      printf("eth_toggle_traffic_mon: Warning - do not enable during tftp boot!\n");
460
      eth_monitor_enabled = 1;
461
      eth_int_enable();
462
    }
463
  else
464
    {
465
      eth_int_disable();
466
      eth_monitor_enabled = 0;
467
      printf("eth_toggle_traffic_mon: traffic monitor DISABLED\n");
468
 
469
 
470
    }
471
 
472
}
473 2 marcus.erl
#endif

powered by: WebSVN 2.1.0

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