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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [devs/] [eth/] [opencores/] [ethmac/] [current/] [src/] [if_ethmac.c] - Blame information for rev 843

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 798 skrzyp
//==========================================================================
2
//
3
//      if_ethmac.c
4
//
5
//      OpenCores ETHMAC controller driver
6
//
7
//==========================================================================
8
// ####ECOSGPLCOPYRIGHTBEGIN####                                            
9
// -------------------------------------------                              
10
// This file is part of eCos, the Embedded Configurable Operating System.   
11
// Copyright (C) 2003, 2004 Free Software Foundation, Inc.                  
12
//
13
// eCos is free software; you can redistribute it and/or modify it under    
14
// the terms of the GNU General Public License as published by the Free     
15
// Software Foundation; either version 2 or (at your option) any later      
16
// version.                                                                 
17
//
18
// eCos is distributed in the hope that it will be useful, but WITHOUT      
19
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or    
20
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License    
21
// for more details.                                                        
22
//
23
// You should have received a copy of the GNU General Public License        
24
// along with eCos; if not, write to the Free Software Foundation, Inc.,    
25
// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.            
26
//
27
// As a special exception, if other files instantiate templates or use      
28
// macros or inline functions from this file, or you compile this file      
29
// and link it with other works to produce a work based on this file,       
30
// this file does not by itself cause the resulting work to be covered by   
31
// the GNU General Public License. However the source code for this file    
32
// must still be made available in accordance with section (3) of the GNU   
33
// General Public License v2.                                               
34
//
35
// This exception does not invalidate any other reasons why a work based    
36
// on this file might be covered by the GNU General Public License.         
37
// -------------------------------------------                              
38
// ####ECOSGPLCOPYRIGHTEND####                                              
39
//#####DESCRIPTIONBEGIN####
40
//
41
// Author(s):    Piotr Skrzypek (pskrzypek@antmicro.com)
42
// Date:         2012-04-10
43
// Purpose:      
44
// Description:  
45
//
46
//####DESCRIPTIONEND####
47
//
48
//==========================================================================
49
 
50
#include <cyg/infra/cyg_type.h>
51
#include <cyg/hal/hal_io.h>
52
#include <cyg/hal/hal_arch.h>
53
#include <cyg/infra/diag.h>
54
#include <cyg/hal/drv_api.h>
55
#include <cyg/io/eth/netdev.h>
56
#include <cyg/io/eth/eth_drv.h>
57 843 skrzyp
#include <string.h>
58 798 skrzyp
 
59
// Settings exported from CDL
60
#include <pkgconf/devs_eth_opencores_ethmac.h>
61
 
62
// ETHMAC address space
63
#define ETHMAC_BASE 0x92000000
64
#define ETHMAC_REG_BASE   (ETHMAC_BASE)
65
#define ETHMAC_BD_BASE    (ETHMAC_BASE + 0x400)
66
#define ETHMAC_TX_BD_BASE (ETHMAC_BD_BASE)
67
#define ETHMAC_RX_BD_BASE (ETHMAC_BD_BASE + 0x200)
68
 
69
// Register space
70
#define ETHMAC_MODER         0x000
71
#define ETHMAC_INT_SOURCE    0x004
72
#define ETHMAC_INT_MASK      0x008
73
#define ETHMAC_IPGT          0x00C
74
#define ETHMAC_IPGR1         0x010
75
#define ETHMAC_IPGR2         0x014
76
#define ETHMAC_PACKETLEN     0x018
77
#define ETHMAC_COLLCONF      0x01C
78
#define ETHMAC_TX_BD_NUM     0x020
79
#define ETHMAC_CTRLMODER     0x024
80
#define ETHMAC_MIIMODER      0x028
81
#define ETHMAC_MIICOMMAND    0x02C
82
#define ETHMAC_MIIADDRESS    0x030
83
#define ETHMAC_MIITX_DATA    0x034
84
#define ETHMAC_MIIRX_DATA    0x038
85
#define ETHMAC_MIISTATUS     0x03C
86
#define ETHMAC_MAC_ADDR0     0x040
87
#define ETHMAC_MAC_ADDR1     0x044
88
#define ETHMAC_ETH_HASH0_ADR 0x048
89
#define ETHMAC_ETH_HASH1_ADR 0x04C
90
#define ETHMAC_ETH_TXCTRL    0x050
91
 
92
// MODER bits
93
#define ETHMAC_MODER_RECSMALL 0x00010000
94
#define ETHMAC_MODER_PAD      0x00008000
95
#define ETHMAC_MODER_HUGEN    0x00004000
96
#define ETHMAC_MODER_CRCEN    0x00002000
97
#define ETHMAC_MODER_DLYCRCEN 0x00001000
98
#define ETHMAC_MODER_FULLD    0x00000400
99
#define ETHMAC_MODER_EXDFREN  0x00000200
100
#define ETHMAC_MODER_NOBCKOF  0x00000100
101
#define ETHMAC_MODER_LOOPBCK  0x00000080
102
#define ETHMAC_MODER_IFG      0x00000040
103
#define ETHMAC_MODER_PRO      0x00000020
104
#define ETHMAC_MODER_IAM      0x00000010
105
#define ETHMAC_MODER_BRO      0x00000008
106
#define ETHMAC_MODER_NOPRE    0x00000004
107
#define ETHMAC_MODER_TXEN     0x00000002
108
#define ETHMAC_MODER_RXEN     0x00000001
109
 
110
// INT_SOURCE bits
111
#define ETHMAC_INT_SOURCE_RXC  0x00000040
112
#define ETHMAC_INT_SOURCE_TXC  0x00000020
113
#define ETHMAC_INT_SOURCE_BUSY 0x00000010
114
#define ETHMAC_INT_SOURCE_RXE  0x00000008
115
#define ETHMAC_INT_SOURCE_RXB  0x00000004
116
#define ETHMAC_INT_SOURCE_TXE  0x00000002
117
#define ETHMAC_INT_SOURCE_TXB  0x00000001
118
 
119
// INT_MASK bits
120
#define ETHMAC_INT_MASK_RXC_M  0x00000040
121
#define ETHMAC_INT_MASK_TXC_M  0x00000020
122
#define ETHMAC_INT_MASK_BUSY_M 0x00000010
123
#define ETHMAC_INT_MASK_RXE_M  0x00000008
124
#define ETHMAC_INT_MASK_RXF_M  0x00000004
125
#define ETHMAC_INT_MASK_TXE_M  0x00000002
126
#define ETHMAC_INT_MASK_TXB_M  0x00000001
127
 
128
// CTRLMODER bits
129
#define ETHMAC_CTRLMODER_TXFLOW  0x00000004
130
#define ETHMAC_CTRLMODER_RXFLOW  0x00000002
131
#define ETHMAC_CTRLMODER_PASSALL 0x00000001
132
 
133
// MIIMODER bits
134
#define ETHMAC_MIIMODER_MIINOPRE 0x00000100
135
 
136
// MIICOMMAND bits
137
#define ETHMAC_MIICOMMAND_WCTRLDATA 0x00000004
138
#define ETHMAC_MIICOMMAND_RSTAT     0x00000002
139
#define ETHMAC_MIICOMMAND_SCANSTAT  0x00000001
140
 
141
// MIISTATUS bits
142
#define ETHMAC_MIISTATUS_NVALID   0x00000004
143
#define ETHMAC_MIISTATUS_BUSY     0x00000002
144
#define ETHMAC_MIISTATUS_LINKFAIL 0x00000001
145
 
146
// TXCTRL bits
147
#define ETHMAC_TXCTRL_TXPAUSERQ 0x00010000
148
 
149
// TX BD bits
150
#define ETHMAC_TX_BD_RD   0x8000
151
#define ETHMAC_TX_BD_IRQ  0x4000
152
#define ETHMAC_TX_BD_WR   0x2000
153
#define ETHMAC_TX_BD_PAD  0x1000
154
#define ETHMAC_TX_BD_CRC  0x0800
155
#define ETHMAC_TX_BD_UR   0x0100
156
#define ETHMAC_TX_BD_RTRY 0x00F0
157
#define ETHMAC_TX_BD_RL   0x0008
158
#define ETHMAC_TX_BD_LC   0x0004
159
#define ETHMAC_TX_BD_DF   0x0002
160
#define ETHMAC_TX_BD_CS   0x0001
161
 
162
// RX BD bits
163
#define ETHMAC_RX_BD_E   0x8000
164
#define ETHMAC_RX_BD_IRQ 0x4000
165
#define ETHMAC_RX_BD_WR  0x2000
166
#define ETHMAC_RX_BD_CF  0x0100
167
#define ETHMAC_RX_BD_M   0x0080
168
#define ETHMAC_RX_BD_OR  0x0040
169
#define ETHMAC_RX_BD_IS  0x0020
170
#define ETHMAC_RX_BD_DN  0x0010
171
#define ETHMAC_RX_BD_TL  0x0008
172
#define ETHMAC_RX_BD_SF  0x0004
173
#define ETHMAC_RX_BD_CRC 0x0002
174
#define ETHMAC_RX_BD_LC  0x0001
175
 
176
typedef struct {
177
 
178
        // Buffer to store received frames
179
        char rx_buffer[CYGPKG_DEVS_ETH_OPENCORES_ETHMAC_RXBUF_COUNT]
180
                      [CYGPKG_DEVS_ETH_OPENCORES_ETHMAC_PACKETLEN];
181
 
182
        // Number of rx buffer descriptor that ETHMAC is pointing to
183
        int rx_head;
184
 
185
        // Array of keys (handlers given by the stack) 
186
        unsigned long tx_key[CYGPKG_DEVS_ETH_OPENCORES_ETHMAC_TXBUF_COUNT];
187
 
188
        // Buffer to store frames for transmission
189
        char tx_buffer[CYGPKG_DEVS_ETH_OPENCORES_ETHMAC_TXBUF_COUNT]
190
                      [CYGPKG_DEVS_ETH_OPENCORES_ETHMAC_PACKETLEN];
191
 
192
        // Number of tx buffer descriptor that ETHMAC is pointing to
193
        int tx_head;
194
 
195
        // Number of descriptors waiting to be transmitted by ETHMAC
196
        int tx_count;
197
 
198
        // Interrupt resources
199
        cyg_handle_t int_handle;
200
        cyg_interrupt int_object;
201
 
202
} ethmac_eth_t;
203
 
204
ethmac_eth_t eth0_data;
205
 
206
ETH_DRV_SC(ethmac_eth0_sc,
207
           (void*) &eth0_data,
208
           "eth0",
209
           ethmac_eth_start,
210
           ethmac_eth_stop,
211
           ethmac_eth_control,
212
           ethmac_eth_can_send,
213
           ethmac_eth_send,
214
           ethmac_eth_recv,
215
           ethmac_eth_deliver,
216
           ethmac_eth_poll,
217
           ethmac_eth_int_vector);
218
 
219
NETDEVTAB_ENTRY(ethmac_netdev,
220
                "ethmac_eth0",
221
                ethmac_eth_init,
222
                &ethmac_eth0_sc);
223
 
224
static void ethmac_eth_debug(char *msg) {
225
        //diag_printf("\033[31;1m%s\033[0m\n", msg);
226
}
227
 
228
static int ethmac_eth_isr(cyg_vector_t vector, cyg_addrword_t data) {
229
 
230
        // Mask the interrupt in PIC, and call generic network DSR.
231
        // This DSR will call ethmac_eth_deliver. The interrupt will be
232
        // unmasked there.
233
        cyg_drv_interrupt_mask(CYGPKG_DEVS_ETH_OPENCORES_ETHMAC_INT);
234
        cyg_drv_interrupt_acknowledge(CYGPKG_DEVS_ETH_OPENCORES_ETHMAC_INT);
235
 
236
        return(CYG_ISR_HANDLED | CYG_ISR_CALL_DSR);
237
}
238
 
239
static bool ethmac_eth_init(struct cyg_netdevtab_entry *tab) {
240
 
241
        struct eth_drv_sc *sc = tab->device_instance;
242
        ethmac_eth_t *data = sc->driver_private;
243
 
244
        // ETHMAC uses buffer descriptors that store a pointer to
245
        // RAM memory. The transmit / receive queue is made from
246
        // multiple buffer descriptors, serviced in a round robin
247
        // manner. Following is the initialization of those descriptors.
248
        int i;
249
        cyg_uint32 reg;
250
 
251
        // TX buffer descriptors
252
        reg = ETHMAC_TX_BD_IRQ | ETHMAC_TX_BD_PAD | ETHMAC_TX_BD_CRC;
253
        for(i = 0; i < CYGPKG_DEVS_ETH_OPENCORES_ETHMAC_TXBUF_COUNT; i++) {
254
                HAL_WRITE_UINT32(ETHMAC_TX_BD_BASE + (i * 8), reg);
255
                HAL_WRITE_UINT32(ETHMAC_TX_BD_BASE + (i * 8) + 4,
256
                                 (cyg_uint32)&data->tx_buffer[i][0]);
257
        }
258
        reg |= ETHMAC_TX_BD_WR;
259
        i--;
260
        HAL_WRITE_UINT32(ETHMAC_TX_BD_BASE + (i * 8), reg);
261
 
262
        data->tx_head = 0;
263
        data->tx_count = 0;
264
 
265
        // RX buffer descriptors
266
        reg = CYGPKG_DEVS_ETH_OPENCORES_ETHMAC_PACKETLEN << 16 |
267
              ETHMAC_RX_BD_E | ETHMAC_RX_BD_IRQ;
268
        for(i = 0; i < CYGPKG_DEVS_ETH_OPENCORES_ETHMAC_RXBUF_COUNT; i++) {
269
                HAL_WRITE_UINT32(ETHMAC_RX_BD_BASE + (i * 8), reg);
270
                HAL_WRITE_UINT32(ETHMAC_RX_BD_BASE + (i * 8) + 4,
271
                                 (cyg_uint32)&data->rx_buffer[i][0]);
272
        }
273
        reg |= ETHMAC_RX_BD_WR;
274
        i--;
275
        HAL_WRITE_UINT32(ETHMAC_RX_BD_BASE + (i * 8), reg);
276
 
277
        data->rx_head = 0;
278
 
279
        // Below is a configuration of ETHMAC peripheral. The stack
280
        // sends here frames without the preamble and CRC, so we need
281
        // to enable them in the peripheral.
282
 
283
        // Disable MAC (just in case)
284
        HAL_READ_UINT32(ETHMAC_REG_BASE + ETHMAC_MODER, reg);
285
        reg &= ~(ETHMAC_MODER_TXEN | ETHMAC_MODER_RXEN);
286
        HAL_WRITE_UINT32(ETHMAC_REG_BASE + ETHMAC_MODER, reg);
287
 
288
        // Enable Full Duplex mode, CRC and PADDING
289
        HAL_READ_UINT32(ETHMAC_REG_BASE + ETHMAC_MODER, reg);
290
        #ifdef CYGPKG_DEVS_ETH_OPENCORES_ETHMAC_FULLDUPLEX
291
        reg |= ETHMAC_MODER_FULLD;
292
        #endif
293
        reg |= ETHMAC_MODER_CRCEN | ETHMAC_MODER_PAD;
294
        HAL_WRITE_UINT32(ETHMAC_REG_BASE + ETHMAC_MODER, reg);
295
 
296
        #ifdef CYGPKG_DEVS_ETH_OPENCORES_ETHMAC_FULLDUPLEX
297
        // Reconfigure timing if full duplex mode was selected
298
        HAL_WRITE_UINT32(ETHMAC_REG_BASE + ETHMAC_IPGT, 0x15);
299
 
300
        // Enable PAUSE frames
301
        reg = ETHMAC_CTRLMODER_RXFLOW | ETHMAC_CTRLMODER_TXFLOW;
302
        HAL_WRITE_UINT32(ETHMAC_REG_BASE + ETHMAC_CTRLMODER, reg);
303
        #endif
304
 
305
        // Configure packet size
306
        reg = (0x40 << 16) | CYGPKG_DEVS_ETH_OPENCORES_ETHMAC_PACKETLEN;
307
        HAL_WRITE_UINT32(ETHMAC_REG_BASE + ETHMAC_PACKETLEN, reg);
308
 
309
        // Clear possible interrupts
310
        HAL_WRITE_UINT32(ETHMAC_REG_BASE + ETHMAC_INT_SOURCE, 0x7F);
311
 
312
        // Set MAC address
313
        unsigned char mac_addr[6] = { CYGPKG_DEVS_ETH_OPENCORES_ETHMAC_MACADDR };
314
        reg = mac_addr[0] << 8 | mac_addr[1];
315
        HAL_WRITE_UINT32(ETHMAC_REG_BASE + ETHMAC_MAC_ADDR1, reg);
316
        reg = mac_addr[2] << 24 | mac_addr[3] << 16 | mac_addr[4] << 8 | mac_addr[5];
317
        HAL_WRITE_UINT32(ETHMAC_REG_BASE + ETHMAC_MAC_ADDR0, reg);
318
 
319
        // Attach an interrupt
320
        cyg_drv_interrupt_create((cyg_vector_t)CYGPKG_DEVS_ETH_OPENCORES_ETHMAC_INT,
321
                                 (cyg_priority_t)CYGPKG_DEVS_ETH_OPENCORES_ETHMAC_INT_PRIO,
322
                                 (cyg_addrword_t) sc,
323
                                 (cyg_ISR_t*)ethmac_eth_isr,
324
                                 (cyg_DSR_t*)eth_drv_dsr,
325
                                 (cyg_handle_t*)&data->int_handle,
326
                                 (cyg_interrupt*)&data->int_object);
327
        cyg_drv_interrupt_attach(data->int_handle);
328
        cyg_drv_interrupt_acknowledge(CYGPKG_DEVS_ETH_OPENCORES_ETHMAC_INT);
329
        cyg_drv_interrupt_unmask(CYGPKG_DEVS_ETH_OPENCORES_ETHMAC_INT);
330
 
331
        // Initialize upper level driver by sending MAC address
332
        (sc->funs->eth_drv->init)(sc, mac_addr);
333
 
334
        return 1;
335
}
336
 
337
static void ethmac_eth_start(struct eth_drv_sc *sc,
338
                             unsigned char *enaddr,
339
                             int flags) {
340
        cyg_uint32 reg;
341
 
342
        // Enable transceiver
343
        HAL_READ_UINT32(ETHMAC_REG_BASE + ETHMAC_MODER, reg);
344
        reg |= ETHMAC_MODER_TXEN | ETHMAC_MODER_RXEN;
345
        HAL_WRITE_UINT32(ETHMAC_REG_BASE + ETHMAC_MODER, reg);
346
 
347
        // Enable interrutps. We want to track transmission and
348
        // reception of data frames only. Control frames are ignored.
349
        // They are not passed to the host.
350
        reg = ETHMAC_INT_MASK_RXE_M | ETHMAC_INT_MASK_RXF_M |
351
              ETHMAC_INT_MASK_TXE_M | ETHMAC_INT_MASK_TXB_M;
352
        HAL_WRITE_UINT32(ETHMAC_REG_BASE + ETHMAC_INT_MASK, reg);
353
 
354
}
355
 
356
static void ethmac_eth_stop(struct eth_drv_sc *sc) {
357
        cyg_uint32 reg;
358
 
359
        // Disable transceiver
360
        HAL_READ_UINT32(ETHMAC_REG_BASE + ETHMAC_MODER, reg);
361
        reg &= ~(ETHMAC_MODER_TXEN | ETHMAC_MODER_RXEN);
362
        HAL_WRITE_UINT32(ETHMAC_REG_BASE + ETHMAC_MODER, reg);
363
 
364
        // Disable interrupts
365
        reg = 0;
366
        HAL_WRITE_UINT32(ETHMAC_REG_BASE + ETHMAC_INT_MASK, reg);
367
 
368
}
369
 
370
static int ethmac_eth_control(struct eth_drv_sc *sc,
371
                          unsigned long key,
372
                          void *data,
373
                          int len) {
374
        //TODO implement following keys:
375
        //ETH_DRV_GET_MAC_ADDRESS
376
        //ETH_DRV_SET_MAC_ADDRESS
377
        //ETH_DRV_GET_IF_STATS_UD
378
        //ETH_DRV_GET_IF_STATS
379
        //ETH_DRV_SET_MC_LIST
380
        //ETH_DRV_SET_MC_ALL
381
        return -1;
382
}
383
 
384
static int ethmac_eth_can_send(struct eth_drv_sc *sc) {
385
 
386
        ethmac_eth_t *data = sc->driver_private;
387
 
388
        // This function should return the number of free transmission
389
        // slots.
390
 
391
        int slots;
392
 
393
        cyg_drv_dsr_lock();
394
        slots = CYGPKG_DEVS_ETH_OPENCORES_ETHMAC_TXBUF_COUNT - data->tx_count;
395
        cyg_drv_dsr_unlock();
396
 
397
        return slots;
398
}
399
 
400
static void ethmac_eth_send(struct eth_drv_sc *sc,
401
                           struct eth_drv_sg *sg_list,
402
                           int sg_len,
403
                           int total_len,
404
                           unsigned long key) {
405
 
406
        // Reject too big frames
407
        if(total_len > CYGPKG_DEVS_ETH_OPENCORES_ETHMAC_PACKETLEN) {
408
 
409
                // Immediately notify the stack, that transmission failed
410
                sc->funs->eth_drv->tx_done(sc, key, -1);
411
                return;
412
        }
413
 
414
        ethmac_eth_t *data = sc->driver_private;
415
 
416
        // Determine the next free buffer descriptor
417
        int free_bd;
418
        cyg_drv_dsr_lock();
419
        free_bd = (data->tx_head + data->tx_count) % CYGPKG_DEVS_ETH_OPENCORES_ETHMAC_TXBUF_COUNT;
420
        cyg_drv_dsr_unlock();
421
 
422
        // Upper stack gives us a scatter-gather list. We need to assemble that into one
423
        // single packet. We store the packet directly in the transmission buffer.
424
        int i, j;
425
        j = 0;
426
        for(i = 0; i < sg_len; i++) {
427
                memcpy(&data->tx_buffer[free_bd][j], (char*)sg_list[i].buf, sg_list[i].len);
428
                j += sg_list[i].len;
429
        }
430
 
431
        // Store key (handler) so it will be possible to notify the stack later
432
        data->tx_key[free_bd] = key;
433
 
434
        // Reconfigure the buffer descriptor so notify ETHMAC it is ready for transmission
435
        cyg_uint32 reg;
436
        reg = (total_len << 16) | ETHMAC_TX_BD_RD | ETHMAC_TX_BD_IRQ | ETHMAC_TX_BD_PAD | ETHMAC_TX_BD_CRC;
437
        if(free_bd == CYGPKG_DEVS_ETH_OPENCORES_ETHMAC_TXBUF_COUNT - 1) {
438
                reg |= ETHMAC_TX_BD_WR;
439
        }
440
        HAL_WRITE_UINT32(ETHMAC_TX_BD_BASE + (8 * free_bd), reg);
441
 
442
        // Update queue control variables
443
        cyg_drv_dsr_lock();
444
        data->tx_count++;
445
        cyg_drv_dsr_unlock();
446
 
447
}
448
 
449
static void ethmac_eth_recv(struct eth_drv_sc *sc,
450
                            struct eth_drv_sg *sg_list,
451
                            int sg_len) {
452
 
453
        ethmac_eth_t *data = sc->driver_private;
454
 
455
        // This function is called by the upper layer as a result of calling
456
        // _recv callback. We need to move data from reception buffer
457
        // to given scatter-gather list.
458
 
459
        if(sg_list == NULL) {
460
                return;
461
        }
462
 
463
        // Copy..
464
        int i, j;
465
        j = 0;
466
        for(i = 0; i < sg_len; i++) {
467
                if(sg_list[i].buf) {
468
                        memcpy((char*)sg_list[i].buf, data->rx_buffer[data->rx_head] + j, sg_list[i].len);
469
                        j += sg_list[i].len;
470
                }
471
        }
472
 
473
}
474
 
475
static void ethmac_eth_deliver(struct eth_drv_sc *sc) {
476
 
477
        // This function is called from default network DSR provided
478
        // by common eCos package. Is is called when network
479
        // interrupt occurs. It simply calls _poll to analyze status
480
        // registers. Interrupt flags in MAC registers are cleared in 
481
        // _poll function.
482
        ethmac_eth_poll(sc);
483
 
484
        // Unmask the interrupt
485
        cyg_drv_interrupt_unmask(CYGPKG_DEVS_ETH_OPENCORES_ETHMAC_INT);
486
 
487
}
488
 
489
static void ethmac_eth_poll(struct eth_drv_sc *sc) {
490
 
491
        cyg_uint32 reg;
492
        ethmac_eth_t *data = sc->driver_private;
493
 
494
        // This function is designed to be idempotent. It can be called multiple
495
        // times. We don't need to count how many interrupts occured.
496
        // This function analyzes ETHMAC status registers to find out if any
497
        // packets were received or transmitted. 
498
 
499
        // Check if any packets were received
500
 
501
        // Clear flags associated with reception
502
        reg = ETHMAC_INT_SOURCE_RXC | ETHMAC_INT_SOURCE_BUSY |
503
              ETHMAC_INT_SOURCE_RXE | ETHMAC_INT_SOURCE_RXB;
504
        HAL_WRITE_UINT32(ETHMAC_REG_BASE + ETHMAC_INT_SOURCE, reg);
505
 
506
        // Traverse receive buffer descriptors to see if any frames were received
507
 
508
        cyg_uint32 errors = ETHMAC_RX_BD_CF | ETHMAC_RX_BD_M |
509
                            ETHMAC_RX_BD_OR | ETHMAC_RX_BD_IS |
510
                            ETHMAC_RX_BD_DN | ETHMAC_RX_BD_TL |
511
                            ETHMAC_RX_BD_SF | ETHMAC_RX_BD_CRC |
512
                            ETHMAC_RX_BD_LC;
513
 
514
        cyg_drv_dsr_lock();
515
 
516
        while(1) {
517
 
518
                HAL_READ_UINT32(ETHMAC_RX_BD_BASE + (8*data->rx_head), reg);
519
 
520
                if(reg & ETHMAC_RX_BD_E) {
521
                        // This buffer descriptor is not filled yet
522
                        break;
523
                }
524
 
525
                if(reg & errors) {
526
                        if(reg & ETHMAC_RX_BD_CF)
527
                                ethmac_eth_debug("RX Control frame");
528
                        if(reg & ETHMAC_RX_BD_M)
529
                                ethmac_eth_debug("RX Miss");
530
                        if(reg & ETHMAC_RX_BD_OR)
531
                                ethmac_eth_debug("RX Overrun");
532
                        if(reg & ETHMAC_RX_BD_IS)
533
                                ethmac_eth_debug("RX Invalid symbol");
534
                        if(reg & ETHMAC_RX_BD_DN)
535
                                ethmac_eth_debug("RX Dribble nibble");
536
                        if(reg & ETHMAC_RX_BD_TL)
537
                                ethmac_eth_debug("RX Too long");
538
                        if(reg & ETHMAC_RX_BD_SF)
539
                                ethmac_eth_debug("RX Short frame");
540
                        if(reg & ETHMAC_RX_BD_CRC)
541
                                ethmac_eth_debug("RX CRC error");
542
                        if(reg & ETHMAC_RX_BD_LC)
543
                                ethmac_eth_debug("RX Late collision");
544
                }
545
                else {
546
                        // We need to notify the stack to prepare buffers for this frame.
547
                        // Last 4 bytes need to be cut as ETHMAC attaches CRC behind
548
                        // frames.
549
                        int size = reg >> 16;
550
                        size -= 4;
551
                        sc->funs->eth_drv->recv(sc, size);
552
                }
553
 
554
                // Reconfigure buffer descriptor so it can accept new frame
555
                reg = CYGPKG_DEVS_ETH_OPENCORES_ETHMAC_PACKETLEN << 16 |
556
                      ETHMAC_RX_BD_E | ETHMAC_RX_BD_IRQ;
557
                if(data->rx_head == CYGPKG_DEVS_ETH_OPENCORES_ETHMAC_RXBUF_COUNT-1) {
558
                        reg |= ETHMAC_RX_BD_WR;
559
                }
560
                HAL_WRITE_UINT32(ETHMAC_RX_BD_BASE + (8*data->rx_head), reg);
561
 
562
                // Update queue control variables
563
                data->rx_head = (data->rx_head + 1) % CYGPKG_DEVS_ETH_OPENCORES_ETHMAC_RXBUF_COUNT;
564
 
565
        }
566
 
567
        cyg_drv_dsr_unlock();
568
 
569
        // Check if any packets were sent
570
 
571
        // Clear flags associated with transmission
572
        reg = ETHMAC_INT_SOURCE_TXC | ETHMAC_INT_SOURCE_TXE |
573
              ETHMAC_INT_SOURCE_TXB;
574
        HAL_WRITE_UINT32(ETHMAC_REG_BASE + ETHMAC_INT_SOURCE, reg);
575
 
576
        // Traverse transmit buffer descriptors to see if any frames were transmitted
577
 
578
        errors = ETHMAC_TX_BD_UR | ETHMAC_TX_BD_RL |
579
                 ETHMAC_TX_BD_LC | ETHMAC_TX_BD_CS;
580
 
581
        cyg_drv_dsr_lock();
582
 
583
        while(1) {
584
 
585
                HAL_READ_UINT32(ETHMAC_TX_BD_BASE + (8*data->tx_head), reg);
586
 
587
                if((reg & ETHMAC_TX_BD_RD) || (data->tx_count == 0)) {
588
                        // This buffer descriptor is not yet transmitted or
589
                        // there are no buffer descriptors to transmit.
590
                        break;
591
                }
592
 
593
                if(reg & errors) {
594
                        if(reg & ETHMAC_TX_BD_UR)
595
                                ethmac_eth_debug("TX Underrun");
596
                        if(reg & ETHMAC_TX_BD_RL)
597
                                ethmac_eth_debug("TX Retransmission limit");
598
                        if(reg & ETHMAC_TX_BD_LC)
599
                                ethmac_eth_debug("TX Late collision");
600
                        if(reg & ETHMAC_TX_BD_CS)
601
                                ethmac_eth_debug("TX Carrier lost");
602
 
603
                        // Notify the stack that transmission failed.
604
                        sc->funs->eth_drv->tx_done(sc, data->tx_key[data->tx_head], -1);
605
                }
606
                else {
607
                        // Notify the stack that transmission succeeded.
608
                        sc->funs->eth_drv->tx_done(sc, data->tx_key[data->tx_head], 0);
609
                }
610
 
611
                // Update queue control variables.
612
                data->tx_count--;
613
                data->tx_head = (data->tx_head + 1) % CYGPKG_DEVS_ETH_OPENCORES_ETHMAC_TXBUF_COUNT;
614
        }
615
 
616
        cyg_drv_dsr_unlock();
617
 
618
}
619
 
620
static int ethmac_eth_int_vector(struct eth_drv_sc *sc) {
621
 
622
        return CYGPKG_DEVS_ETH_OPENCORES_ETHMAC_INT;
623
 
624
}
625
 
626
 
627
// ------------------------------------------------------------------------
628
// EOF if_ethmac.c

powered by: WebSVN 2.1.0

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