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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [orpmon/] [drivers/] [eth.c] - Blame information for rev 1767

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

Line No. Rev Author Line
1 1495 jcastillo
#include "board.h"
2
#if OC_LAN==1
3
 
4 809 simons
#include "common.h"
5
#include "support.h"
6
#include "uart.h"
7
#include "eth.h"
8 855 markom
#include "int.h"
9 809 simons
#include "spr_defs.h"
10
 
11
extern int printf (const char *fmt, ...);
12
extern void lolev_ie(void);
13
extern void lolev_idis(void);
14
 
15
int tx_next;  /* Next buffer to be given to the user */
16
int tx_last;  /* Next buffer to be checked if packet sent */
17
int tx_full;
18
int rx_next;  /* Next buffer to be checked for new packet and given to the user */
19 828 markom
void (*receive)(volatile unsigned char *add, int len); /* Pointer to function to be called
20 809 simons
                                        when frame is received */
21
 
22 834 simons
unsigned long eth_data[((ETH_TXBD_NUM + ETH_RXBD_NUM) * ETH_MAXBUF_LEN)/4] = {0};
23
#undef ETH_DATA_BASE
24
#define ETH_DATA_BASE ((unsigned long)eth_data)
25
 
26 833 simons
static void
27
print_packet(unsigned long add, int len)
28
{
29
  int i;
30
 
31 855 markom
  printf("ipacket: add = %lx len = %d\n", add, len);
32 833 simons
  for(i = 0; i < len; i++) {
33
      if(!(i % 16))
34
          printf("\n");
35
      printf(" %.2x", *(((unsigned char *)add) + i));
36
  }
37
  printf("\n");
38
}
39
 
40 809 simons
void init_tx_bd_pool(void)
41
{
42
  eth_bd  *bd;
43
  int i;
44
 
45
  bd = (eth_bd *)ETH_BD_BASE;
46
 
47 855 markom
  for(i = 0; i < ETH_TXBD_NUM; i++) {
48 809 simons
    /* Set Tx BD status */
49 834 simons
    bd[i].len_status = 0 << 16 | ETH_TX_BD_PAD | ETH_TX_BD_CRC | ETH_RX_BD_IRQ;
50 809 simons
 
51
    /* Initialize Tx buffer pointer */
52 833 simons
    bd[i].addr = ETH_DATA_BASE + (i * ETH_MAXBUF_LEN);
53 809 simons
  }
54
 
55 834 simons
  bd[i-1].len_status |= ETH_TX_BD_WRAP; // Last Tx BD - Wrap
56 809 simons
}
57
 
58
void init_rx_bd_pool(void)
59
{
60
  eth_bd  *bd;
61
  int i;
62
 
63
  bd = (eth_bd *)ETH_BD_BASE + ETH_TXBD_NUM;
64
 
65
  for(i = 0; i < ETH_RXBD_NUM; i++){
66
 
67 833 simons
    /* Set Rx BD status */
68 834 simons
    bd[i].len_status = 0 << 16 | ETH_RX_BD_EMPTY | ETH_RX_BD_IRQ;
69 809 simons
 
70 833 simons
    /* Initialize Rx buffer pointer */
71
    bd[i].addr = ETH_DATA_BASE + ((ETH_TXBD_NUM + i) * ETH_MAXBUF_LEN);
72 809 simons
  }
73
 
74 842 simons
  bd[i-1].len_status |= ETH_RX_BD_WRAP; // Last Rx BD - Wrap
75 809 simons
}
76
 
77 855 markom
/* Ethernet interrupt handler */
78
void eth_int (void)
79
{
80
}
81
 
82 809 simons
void eth_init (void (*rec)(volatile unsigned char *, int))
83
{
84
  /* Reset ethernet core */
85
  REG32(ETH_REG_BASE + ETH_MODER) = ETH_MODER_RST;    /* Reset ON */
86
  REG32(ETH_REG_BASE + ETH_MODER) &= ~ETH_MODER_RST;  /* Reset OFF */
87
 
88
  /* Setting TX BD number */
89 1017 simons
  REG32(ETH_REG_BASE + ETH_TX_BD_NUM) = ETH_TXBD_NUM;
90 809 simons
 
91 1030 simons
  // Set PHY to 10 Mbps full duplex
92
  REG32(ETH_REG_BASE + ETH_MIIADDRESS) = 0<<8;
93
  REG32(ETH_REG_BASE + ETH_MIITX_DATA) = 0x0100;
94
  REG32(ETH_REG_BASE + ETH_MIICOMMAND) = ETH_MIICOMMAND_WCTRLDATA;
95 1031 simons
  while(REG32(ETH_REG_BASE + ETH_MIISTATUS) & ETH_MIISTATUS_BUSY);
96 1030 simons
 
97
  while(1){
98
    REG32(ETH_REG_BASE + ETH_MIIADDRESS) = 1<<8;
99
    REG32(ETH_REG_BASE + ETH_MIICOMMAND) = ETH_MIICOMMAND_RSTAT;
100 1031 simons
    while(REG32(ETH_REG_BASE + ETH_MIISTATUS) & ETH_MIISTATUS_BUSY);
101 1030 simons
    if(REG32(ETH_REG_BASE + ETH_MIIRX_DATA) & 0x04)
102
      break;
103
  }
104 1031 simons
 
105 809 simons
  /* Set min/max packet length */
106 1029 simons
  REG32(ETH_REG_BASE + ETH_PACKETLEN) = 0x00400600;
107 809 simons
 
108
  /* Set IPGT register to recomended value */
109
  REG32(ETH_REG_BASE + ETH_IPGT) =  0x00000012;
110
 
111
  /* Set IPGR1 register to recomended value */
112
  REG32(ETH_REG_BASE + ETH_IPGR1) =  0x0000000c;
113
 
114
  /* Set IPGR2 register to recomended value */
115
  REG32(ETH_REG_BASE + ETH_IPGR2) =  0x00000012;
116
 
117
  /* Set COLLCONF register to recomended value */
118 833 simons
  REG32(ETH_REG_BASE + ETH_COLLCONF) =  0x000f003f;
119 809 simons
 
120
#if 0
121
  REG32(ETH_REG_BASE + ETH_CTRLMODER) = OETH_CTRLMODER_TXFLOW | OETH_CTRLMODER_RXFLOW;
122
#else
123
  REG32(ETH_REG_BASE + ETH_CTRLMODER) = 0;
124
#endif
125
 
126
  /* Initialize RX and TX buffer descriptors */
127
  init_rx_bd_pool();
128
  init_tx_bd_pool();
129
 
130
  /* Initialize tx pointers */
131
  tx_next = 0;
132
  tx_last = 0;
133
  tx_full = 0;
134
 
135
  /* Initialize rx pointers */
136
  rx_next = 0;
137
  receive = rec;
138
 
139
  /* Set local MAC address */
140
  REG32(ETH_REG_BASE + ETH_MAC_ADDR1) = ETH_MACADDR0 << 8 |
141
            ETH_MACADDR1;
142
  REG32(ETH_REG_BASE + ETH_MAC_ADDR0) = ETH_MACADDR2 << 24 |
143
            ETH_MACADDR3 << 16 |
144
            ETH_MACADDR4 << 8 |
145
            ETH_MACADDR5;
146
 
147
  /* Clear all pending interrupts */
148
  REG32(ETH_REG_BASE + ETH_INT) = 0xffffffff;
149
 
150
  /* Promisc, IFG, CRCEn */
151
  REG32(ETH_REG_BASE + ETH_MODER) |= ETH_MODER_PAD | ETH_MODER_IFG | ETH_MODER_CRCEN;
152
 
153
  /* Enable interrupt sources */
154
#if 0
155
  regs->int_mask = ETH_INT_MASK_TXB        |
156
                   ETH_INT_MASK_TXE        |
157
                   ETH_INT_MASK_RXF        |
158
                   ETH_INT_MASK_RXE        |
159
                   ETH_INT_MASK_BUSY       |
160
                   ETH_INT_MASK_TXC        |
161
                   ETH_INT_MASK_RXC;
162 833 simons
#else
163
  REG32(ETH_REG_BASE + ETH_INT_MASK) = 0x00000000;
164 809 simons
#endif
165
 
166
  /* Enable receiver and transmiter */
167
  REG32(ETH_REG_BASE + ETH_MODER) |= ETH_MODER_RXEN | ETH_MODER_TXEN;
168
 
169 855 markom
  /* Register interrupt handler */
170
  int_add (ETH_IRQ, eth_int);
171 809 simons
}
172
 
173
/* Returns pointer to next free buffer; NULL if none available */
174
void *eth_get_tx_buf ()
175
{
176
  eth_bd  *bd;
177
  unsigned long add;
178
 
179
  if(tx_full)
180
    return (void *)0;
181
 
182
  bd = (eth_bd *)ETH_BD_BASE;
183
 
184 834 simons
  if(bd[tx_next].len_status & ETH_TX_BD_READY)
185 809 simons
    return (void *)0;
186
 
187
  add = bd[tx_next].addr;
188
 
189
  tx_next = (tx_next + 1) & ETH_TXBD_NUM_MASK;
190
 
191
  if(tx_next == tx_last)
192
    tx_full = 1;
193
 
194
  return (void *)add;
195
}
196
 
197
/* Send a packet at address */
198
void eth_send (void *buf, unsigned long len)
199
{
200
  eth_bd  *bd;
201
 
202
  bd = (eth_bd *)ETH_BD_BASE;
203
 
204
  bd[tx_last].addr = (unsigned long)buf;
205 834 simons
  bd[tx_last].len_status &= 0x0000ffff & ~ETH_TX_BD_STATS;
206
  bd[tx_last].len_status |= len << 16 | ETH_TX_BD_READY;
207 809 simons
 
208
  tx_last = (tx_last + 1) & ETH_TXBD_NUM_MASK;
209
  tx_full = 0;
210
}
211
 
212
/* Waits for packet and pass it to the upper layers */
213
unsigned long eth_rx (void)
214
{
215
  eth_bd  *bd;
216
  unsigned long len = 0;
217
 
218
  bd = (eth_bd *)ETH_BD_BASE + ETH_TXBD_NUM;
219
 
220
  while(1) {
221
 
222
    int bad = 0;
223
 
224 834 simons
    if(bd[rx_next].len_status & ETH_RX_BD_EMPTY)
225 809 simons
      return len;
226
 
227 834 simons
    if(bd[rx_next].len_status & ETH_RX_BD_OVERRUN) {
228 809 simons
      printf("eth rx: ETH_RX_BD_OVERRUN\n");
229
      bad = 1;
230
    }
231 834 simons
    if(bd[rx_next].len_status & ETH_RX_BD_INVSIMB) {
232 809 simons
      printf("eth rx: ETH_RX_BD_INVSIMB\n");
233
      bad = 1;
234
    }
235 834 simons
    if(bd[rx_next].len_status & ETH_RX_BD_DRIBBLE) {
236 809 simons
      printf("eth rx: ETH_RX_BD_DRIBBLE\n");
237
      bad = 1;
238
    }
239 834 simons
    if(bd[rx_next].len_status & ETH_RX_BD_TOOLONG) {
240 809 simons
      printf("eth rx: ETH_RX_BD_TOOLONG\n");
241
      bad = 1;
242
    }
243 834 simons
    if(bd[rx_next].len_status & ETH_RX_BD_SHORT) {
244 809 simons
      printf("eth rx: ETH_RX_BD_SHORT\n");
245
      bad = 1;
246
    }
247 834 simons
    if(bd[rx_next].len_status & ETH_RX_BD_CRCERR) {
248 809 simons
      printf("eth rx: ETH_RX_BD_CRCERR\n");
249
      bad = 1;
250
    }
251 834 simons
    if(bd[rx_next].len_status & ETH_RX_BD_LATECOL) {
252 809 simons
      printf("eth rx: ETH_RX_BD_LATECOL\n");
253
      bad = 1;
254
    }
255
 
256
    if(!bad) {
257 834 simons
      receive((void *)bd[rx_next].addr, bd[rx_next].len_status >> 16);
258
      len += bd[rx_next].len_status >> 16;
259 809 simons
    }
260
 
261 834 simons
    bd[rx_next].len_status &= ~ETH_RX_BD_STATS;
262
    bd[rx_next].len_status |= ETH_RX_BD_EMPTY;
263 809 simons
 
264
    rx_next = (rx_next + 1) & ETH_RXBD_NUM_MASK;
265
  }
266
}
267
 
268
void eth_int_enable(void)
269
{
270
  REG32(ETH_REG_BASE + ETH_INT_MASK) =  ETH_INT_MASK_TXB        |
271
                                        ETH_INT_MASK_TXE        |
272
                                        ETH_INT_MASK_RXF        |
273
                                        ETH_INT_MASK_RXE        |
274
                                        ETH_INT_MASK_BUSY       |
275
                                        ETH_INT_MASK_TXC        |
276
                                        ETH_INT_MASK_RXC;
277
}
278
 
279
void eth_halt(void)
280
{
281
  /* Enable receiver and transmiter */
282
  REG32(ETH_REG_BASE + ETH_MODER) &= ~(ETH_MODER_RXEN | ETH_MODER_TXEN);
283
}
284 1495 jcastillo
#endif

powered by: WebSVN 2.1.0

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