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 798

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

powered by: WebSVN 2.1.0

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