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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [devs/] [eth/] [powerpc/] [fec/] [v2_0/] [src/] [if_fec.c] - Blame information for rev 174

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 27 unneback
//==========================================================================
2
//
3
//      dev/if_fec.c
4
//
5
//      Fast ethernet device driver for PowerPC MPC8xxT boards
6
//
7
//==========================================================================
8
//####ECOSGPLCOPYRIGHTBEGIN####
9
// -------------------------------------------
10
// This file is part of eCos, the Embedded Configurable Operating System.
11
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
12
// Copyright (C) 2002 Gary Thomas
13
//
14
// eCos is free software; you can redistribute it and/or modify it under
15
// the terms of the GNU General Public License as published by the Free
16
// Software Foundation; either version 2 or (at your option) any later version.
17
//
18
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
19
// 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 along
24
// with eCos; if not, write to the Free Software Foundation, Inc.,
25
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
26
//
27
// As a special exception, if other files instantiate templates or use macros
28
// or inline functions from this file, or you compile this file and link it
29
// with other works to produce a work based on this file, this file does not
30
// by itself cause the resulting work to be covered by the GNU General Public
31
// License. However the source code for this file must still be made available
32
// in accordance with section (3) of the GNU General Public License.
33
//
34
// This exception does not invalidate any other reasons why a work based on
35
// this file might be covered by the GNU General Public License.
36
//
37
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
38
// at http://sources.redhat.com/ecos/ecos-license/
39
// -------------------------------------------
40
//####ECOSGPLCOPYRIGHTEND####
41
//==========================================================================
42
//#####DESCRIPTIONBEGIN####
43
//
44
// Author(s):    gthomas
45
// Contributors: gthomas
46
// Date:         2001-01-21
47
// Purpose:      
48
// Description:  hardware driver for MPC8xxT FEC
49
//              
50
//
51
//####DESCRIPTIONEND####
52
//
53
//==========================================================================
54
 
55
// Ethernet device driver for MPC8xx FEC
56
 
57
#include <pkgconf/system.h>
58
#include <pkgconf/devs_eth_powerpc_fec.h>
59
#include <pkgconf/io_eth_drivers.h>
60
#include CYGDAT_DEVS_FEC_ETH_INL
61
 
62
#ifdef CYGPKG_NET
63
#include <pkgconf/net.h>
64
#endif
65
 
66
#include <cyg/infra/cyg_type.h>
67
#include <cyg/infra/diag.h>
68
 
69
#include <cyg/hal/hal_arch.h>
70
#include <cyg/hal/hal_cache.h>
71
#include <cyg/hal/hal_intr.h>
72
#include <cyg/hal/drv_api.h>
73
#include <cyg/hal/hal_if.h>
74
#include <cyg/hal/ppc_regs.h>
75
 
76
#include <cyg/io/eth/netdev.h>
77
#include <cyg/io/eth/eth_drv.h>
78
 
79
#include "fec.h"
80
 
81
// Define this to force the buffer descriptors into the EPPC memory
82
#define FEC_USE_EPPC_BD
83
 
84
#ifndef FEC_USE_EPPC_BD
85
static struct fec_bd fec_eth_rxring[CYGNUM_DEVS_ETH_POWERPC_FEC_RxNUM];
86
static struct fec_bd fec_eth_txring[CYGNUM_DEVS_ETH_POWERPC_FEC_TxNUM];
87
#endif
88
static unsigned char fec_eth_rxbufs[CYGNUM_DEVS_ETH_POWERPC_FEC_RxNUM+1]
89
                                   [CYGNUM_DEVS_ETH_POWERPC_FEC_BUFSIZE];
90
static unsigned char fec_eth_txbufs[CYGNUM_DEVS_ETH_POWERPC_FEC_TxNUM+1]
91
                                   [CYGNUM_DEVS_ETH_POWERPC_FEC_BUFSIZE];
92
 
93
static struct fec_eth_info fec_eth0_info;
94
static unsigned char _default_enaddr[] = { 0x08, 0x00, 0x3E, 0x28, 0x7A, 0xBA};
95
static unsigned char enaddr[6];
96
#ifdef CYGPKG_REDBOOT
97
#include <pkgconf/redboot.h>
98
#ifdef CYGSEM_REDBOOT_FLASH_CONFIG
99
#include <redboot.h>
100
#include <flash_config.h>
101
RedBoot_config_option("Network hardware address [MAC]",
102
                      fec_esa,
103
                      ALWAYS_ENABLED, true,
104
                      CONFIG_ESA, 0
105
    );
106
#endif
107
#endif
108
 
109
#define os_printf diag_printf
110
 
111
// For fetching the ESA from RedBoot
112
#include <cyg/hal/hal_if.h>
113
#ifndef CONFIG_ESA
114
#define CONFIG_ESA 6
115
#endif
116
 
117
ETH_DRV_SC(fec_eth0_sc,
118
           &fec_eth0_info,   // Driver specific data
119
           "eth0",             // Name for this interface
120
           fec_eth_start,
121
           fec_eth_stop,
122
           fec_eth_control,
123
           fec_eth_can_send,
124
           fec_eth_send,
125
           fec_eth_recv,
126
           fec_eth_deliver,
127
           fec_eth_int,
128
           fec_eth_int_vector);
129
 
130
NETDEVTAB_ENTRY(fec_netdev,
131
                "fec_eth",
132
                fec_eth_init,
133
                &fec_eth0_sc);
134
 
135
#ifdef CYGINT_IO_ETH_INT_SUPPORT_REQUIRED
136
#define _FEC_USE_INTS
137
#ifdef _FEC_USE_INTS
138
static cyg_interrupt fec_eth_interrupt;
139
static cyg_handle_t  fec_eth_interrupt_handle;
140
#else
141
#define STACK_SIZE CYGNUM_HAL_STACK_SIZE_MINIMUM
142
static char fec_fake_int_stack[STACK_SIZE];
143
static cyg_thread fec_fake_int_thread_data;
144
static cyg_handle_t fec_fake_int_thread_handle;
145
static void fec_fake_int(cyg_addrword_t);
146
#endif // _FEC_USE_INTS
147
#endif // CYGINT_IO_ETH_INT_SUPPORT_REQUIRED
148
static void          fec_eth_int(struct eth_drv_sc *data);
149
 
150
#ifndef FEC_ETH_INT
151
#error  FEC_ETH_INT must be defined
152
#endif
153
 
154
#ifndef FEC_ETH_PHY
155
#error  FEC_ETH_PHY must be defined
156
#endif
157
 
158
#ifndef FEC_ETH_RESET_PHY
159
#define FEC_ETH_RESET_PHY()
160
#endif
161
 
162
#ifndef FEC_EPPC_BD_OFFSET
163
#define FEC_EPPC_BD_OFFSET CYGNUM_DEVS_ETH_POWERPC_FEC_BD_OFFSET
164
#endif
165
 
166
// LED activity [exclusive of hardware bits]
167
#ifndef _get_led
168
#define _get_led()  
169
#define _set_led(v) 
170
#endif
171
#ifndef LED_TxACTIVE
172
#define LED_TxACTIVE  7
173
#define LED_RxACTIVE  6
174
#define LED_IntACTIVE 5
175
#endif
176
 
177
static void
178
set_led(int bit)
179
{
180
  _set_led(_get_led() | (1<<bit));
181
}
182
 
183
static void
184
clear_led(int bit)
185
{
186
  _set_led(_get_led() & ~(1<<bit));
187
}
188
 
189
#ifdef _FEC_USE_INTS
190
// This ISR is called when the ethernet interrupt occurs
191
static int
192
fec_eth_isr(cyg_vector_t vector, cyg_addrword_t data, HAL_SavedRegisters *regs)
193
{
194
    cyg_drv_interrupt_mask(FEC_ETH_INT);
195
    return (CYG_ISR_HANDLED|CYG_ISR_CALL_DSR);  // Run the DSR
196
}
197
#endif
198
 
199
// Deliver function (ex-DSR) handles the ethernet [logical] processing
200
static void
201
fec_eth_deliver(struct eth_drv_sc * sc)
202
{
203
    fec_eth_int(sc);
204
#ifdef _FEC_USE_INTS
205
    // Allow interrupts to happen again
206
    cyg_drv_interrupt_acknowledge(FEC_ETH_INT);
207
    cyg_drv_interrupt_unmask(FEC_ETH_INT);
208
#endif
209
}
210
 
211
#ifdef CYGSEM_DEVS_ETH_POWERPC_FEC_RESET_PHY
212
//
213
// PHY unit access (via MII channel)
214
//
215
static void
216
phy_write(int reg, int addr, unsigned short data)
217
{
218
    volatile EPPC *eppc = (volatile EPPC *)eppc_base();
219
    volatile struct fec *fec = (volatile struct fec *)((unsigned char *)eppc + FEC_OFFSET);
220
    int timeout = 0x100000;
221
 
222
    fec->iEvent = iEvent_MII;
223
    fec->MiiData = MII_Start | MII_Write | MII_Phy(addr) | MII_Reg(reg) | MII_TA | data;
224
    while (!(fec->iEvent & iEvent_MII) && (--timeout > 0)) ;
225
}
226
 
227
static bool
228
phy_read(int reg, int addr, unsigned short *val)
229
{
230
    volatile EPPC *eppc = (volatile EPPC *)eppc_base();
231
    volatile struct fec *fec = (volatile struct fec *)((unsigned char *)eppc + FEC_OFFSET);
232
    int timeout = 0x100000;
233
 
234
    fec->iEvent = iEvent_MII;
235
    fec->MiiData = MII_Start | MII_Read | MII_Phy(addr) | MII_Reg(reg) | MII_TA;
236
    while (!(fec->iEvent & iEvent_MII)) {
237
        if (--timeout <= 0) {
238
            return false;
239
        }
240
    }
241
    *val = fec->MiiData & 0x0000FFFF;
242
    return true;
243
}
244
#endif // CYGSEM_DEVS_ETH_POWERPC_FEC_RESET_PHY
245
 
246
//
247
// [re]Initialize the ethernet controller
248
//   Done separately since shutting down the device requires a 
249
//   full reconfiguration when re-enabling.
250
//   when 
251
static bool
252
fec_eth_reset(struct eth_drv_sc *sc, unsigned char *enaddr, int flags)
253
{
254
    struct fec_eth_info *qi = (struct fec_eth_info *)sc->driver_private;
255
    volatile EPPC *eppc = (volatile EPPC *)eppc_base();
256
    volatile struct fec *fec = (volatile struct fec *)((unsigned char *)eppc + FEC_OFFSET);
257
    volatile struct fec_bd *rxbd, *txbd;
258
    unsigned char *RxBUF, *TxBUF;
259
    int cache_state, int_state;
260
    int i;
261
 
262
    // Ignore unless device is idle/stopped
263
    if ((qi->fec->eControl & eControl_EN) != 0) {
264
        return true;
265
    }
266
 
267
    // Make sure interrupts are off while we mess with the device
268
    HAL_DISABLE_INTERRUPTS(int_state);
269
 
270
    // Ensure consistent state between cache and what the FEC sees
271
    HAL_DCACHE_IS_ENABLED(cache_state);
272
    if (cache_state)
273
      HAL_DCACHE_SYNC();
274
    HAL_DCACHE_DISABLE();
275
 
276
    // Shut down ethernet controller, in case it is already running
277
    fec->eControl = eControl_RESET;
278
    i = 0;
279
    while ((fec->eControl & eControl_RESET) != 0) {
280
      if (++i >= 500000) {
281
        os_printf("FEC Ethernet does not reset\n");
282
        if (cache_state)
283
          HAL_DCACHE_ENABLE();
284
        HAL_RESTORE_INTERRUPTS(int_state);
285
        return false;
286
      }
287
    }
288
 
289
    fec->iMask  = 0x0000000;  // Disables all interrupts
290
    fec->iEvent = 0xFFFFFFFF; // Clear all interrupts
291
    fec->iVector = (1<<29);   // Caution - must match FEC_ETH_INT above
292
 
293
#define ROUNDUP(b,s) (((unsigned long)(b) + (s-1)) & ~(s-1))
294
#ifdef FEC_USE_EPPC_BD
295
    txbd = (struct fec_bd *)(FEC_EPPC_BD_OFFSET + (cyg_uint32)eppc);
296
    rxbd = &txbd[CYGNUM_DEVS_ETH_POWERPC_FEC_TxNUM];
297
#else
298
    txbd = fec_eth_txring;
299
    rxbd = fec_eth_rxring;
300
#endif
301
    qi->tbase = qi->txbd = qi->tnext = txbd;
302
    qi->rbase = qi->rxbd = qi->rnext = rxbd;
303
    qi->txactive = 0;
304
 
305
    RxBUF = (unsigned char *)ROUNDUP(&fec_eth_rxbufs[0][0], 32);
306
    TxBUF = (unsigned char *)ROUNDUP(&fec_eth_txbufs[0][0], 32);
307
 
308
    // setup buffer descriptors
309
    for (i = 0;  i < CYGNUM_DEVS_ETH_POWERPC_FEC_RxNUM;  i++) {
310
        rxbd->length = 0;
311
        rxbd->buffer = RxBUF;
312
        rxbd->ctrl   = FEC_BD_Rx_Empty;
313
        RxBUF += CYGNUM_DEVS_ETH_POWERPC_FEC_BUFSIZE;
314
        rxbd++;
315
    }
316
    rxbd--;
317
    rxbd->ctrl |= FEC_BD_Rx_Wrap;  // Last buffer
318
    for (i = 0;  i < CYGNUM_DEVS_ETH_POWERPC_FEC_TxNUM;  i++) {
319
        txbd->length = 0;
320
        txbd->buffer = TxBUF;
321
        txbd->ctrl   = 0;
322
        TxBUF += CYGNUM_DEVS_ETH_POWERPC_FEC_BUFSIZE;
323
        txbd++;
324
    }
325
    txbd--;
326
    txbd->ctrl |= FEC_BD_Tx_Wrap;  // Last buffer
327
 
328
    // Reset interrupts
329
    fec->iMask  = 0x00000000;  // No interrupts enabled
330
    fec->iEvent = 0xFFFFFFFF;  // Clear all interrupts
331
 
332
    // Initialize shared PRAM
333
    fec->RxRing = qi->rbase;
334
    fec->TxRing = qi->tbase;
335
 
336
    // Size of receive buffers
337
    fec->RxBufSize = CYGNUM_DEVS_ETH_POWERPC_FEC_BUFSIZE;
338
 
339
    // Receiver control
340
    fec->RxControl = RxControl_MII | RxControl_DRT;
341
//    fec->RxControl = RxControl_MII | RxControl_LOOP | RxControl_PROM;
342
    fec->RxHash = IEEE_8023_MAX_FRAME; // Largest possible ethernet frame
343
 
344
    // Transmit control
345
    fec->TxControl = 4+0;
346
 
347
    // Use largest possible Tx FIFO
348
    fec->TxWater = 3;
349
 
350
    // DMA control
351
    fec->FunCode = ((2<<29) | (2<<27) | (0<<24));
352
 
353
    // MII speed control (50MHz)
354
    fec->MiiSpeed = 0x14;
355
 
356
    // Group address hash
357
    fec->hash[0] = 0;
358
    fec->hash[1] = 0;
359
 
360
    // Device physical address
361
    fec->addr[0] = *(unsigned long *)&enaddr[0];
362
    fec->addr[1] = *(unsigned long *)&enaddr[4];
363
    // os_printf("FEC ESA = %08x/%08x\n", fec->addr[0], fec->addr[1]);
364
 
365
    // Enable device
366
    fec->eControl = eControl_EN | eControl_MUX;
367
    fec->RxUpdate = 0x0F0F0F0F;  // Any write tells machine to look for work
368
 
369
#ifdef _FEC_USE_INTS
370
    // Set up for interrupts
371
    fec->iMask = iEvent_TFINT | iEvent_TXB |
372
                 iEvent_RFINT | iEvent_RXB;
373
    fec->iEvent = 0xFFFFFFFF;  // Clear all interrupts
374
#endif
375
 
376
    if (cache_state)
377
        HAL_DCACHE_ENABLE();
378
 
379
    // Set LED state
380
    clear_led(LED_TxACTIVE);
381
    clear_led(LED_RxACTIVE);
382
 
383
    HAL_RESTORE_INTERRUPTS(int_state);
384
    return true;
385
}
386
 
387
//
388
// Initialize the interface - performed at system startup
389
// This function must set up the interface, including arranging to
390
// handle interrupts, etc, so that it may be "started" cheaply later.
391
//
392
static bool
393
fec_eth_init(struct cyg_netdevtab_entry *tab)
394
{
395
    struct eth_drv_sc *sc = (struct eth_drv_sc *)tab->device_instance;
396
    struct fec_eth_info *qi = (struct fec_eth_info *)sc->driver_private;
397
    volatile EPPC *eppc = (volatile EPPC *)eppc_base();
398
    volatile struct fec *fec = (volatile struct fec *)((unsigned char *)eppc + FEC_OFFSET);
399
    int cache_state;
400
    unsigned long proc_rev;
401
    bool esa_ok;
402
#ifdef CYGSEM_DEVS_ETH_POWERPC_FEC_RESET_PHY
403
    int phy_timeout = 5*1000;  // Wait 5 seconds max for link to clear
404
    bool phy_ok;
405
    unsigned short phy_state = 0;
406
#endif
407
 
408
    // Ensure consistent state between cache and what the FEC sees
409
    HAL_DCACHE_IS_ENABLED(cache_state);
410
    if (cache_state)
411
      HAL_DCACHE_SYNC();
412
    HAL_DCACHE_DISABLE();
413
 
414
    qi->fec = fec;
415
    fec_eth_stop(sc);  // Make sure it's not running yet
416
 
417
#ifdef CYGINT_IO_ETH_INT_SUPPORT_REQUIRED
418
#ifdef _FEC_USE_INTS
419
    // Set up to handle interrupts
420
    cyg_drv_interrupt_create(FEC_ETH_INT,
421
                             CYGARC_SIU_PRIORITY_HIGH,
422
                             (cyg_addrword_t)sc, //  Data item passed to interrupt handler
423
                             (cyg_ISR_t *)fec_eth_isr,
424
                             (cyg_DSR_t *)eth_drv_dsr,
425
                             &fec_eth_interrupt_handle,
426
                             &fec_eth_interrupt);
427
    cyg_drv_interrupt_attach(fec_eth_interrupt_handle);
428
    cyg_drv_interrupt_acknowledge(FEC_ETH_INT);
429
    cyg_drv_interrupt_unmask(FEC_ETH_INT);
430
#else // _FEC_USE_INTS
431
    // Hack - use a thread to simulate interrupts
432
    cyg_thread_create(1,                 // Priority
433
                      fec_fake_int,   // entry
434
                      (cyg_addrword_t)sc, // entry parameter
435
                      "CS8900 int",      // Name
436
                      &fec_fake_int_stack[0],         // Stack
437
                      STACK_SIZE,        // Size
438
                      &fec_fake_int_thread_handle,    // Handle
439
                      &fec_fake_int_thread_data       // Thread data structure
440
            );
441
    cyg_thread_resume(fec_fake_int_thread_handle);  // Start it
442
#endif
443
#endif
444
 
445
    // Set up parallel port for connection to ethernet tranceiver
446
    eppc->pio_pdpar = 0x1FFF;
447
    CYGARC_MFSPR( CYGARC_REG_PVR, proc_rev );
448
#define PROC_REVB 0x0020
449
    if ((proc_rev & 0x0000FFFF) == PROC_REVB) {
450
        eppc->pio_pddir = 0x1C58;
451
    } else {
452
        eppc->pio_pddir = 0x1FFF;
453
    }
454
 
455
    // Get physical device address
456
#ifdef CYGPKG_REDBOOT
457
#ifdef CYGSEM_REDBOOT_FLASH_CONFIG
458
    esa_ok = flash_get_config("fec_esa", enaddr, CONFIG_ESA);
459
#else
460
    esa_ok = false;
461
#endif
462
#else
463
    esa_ok = CYGACC_CALL_IF_FLASH_CFG_OP(CYGNUM_CALL_IF_FLASH_CFG_GET,
464
                                         "fec_esa", enaddr, CONFIG_ESA);
465
#endif
466
    if (!esa_ok) {
467
        // Can't figure out ESA
468
        os_printf("FEC_ETH - Warning! ESA unknown\n");
469
        memcpy(&enaddr, &_default_enaddr, sizeof(enaddr));
470
    }
471
 
472
    // Configure the device
473
    if (!fec_eth_reset(sc, enaddr, 0)) {
474
        return false;
475
    }
476
 
477
    fec->iEvent = 0xFFFFFFFF;  // Clear all interrupts
478
 
479
#ifdef CYGSEM_DEVS_ETH_POWERPC_FEC_RESET_PHY
480
    // Reset PHY (transceiver)
481
    FEC_ETH_RESET_PHY();
482
 
483
    phy_ok = 0;
484
    if (phy_read(PHY_BMSR, FEC_ETH_PHY, &phy_state)) {
485
        if ((phy_state & PHY_BMSR_LINK) !=  PHY_BMSR_LINK) {
486
            unsigned short reset_mode;
487
            int i;
488
            phy_write(PHY_BMCR, FEC_ETH_PHY, PHY_BMCR_RESET);
489
            for (i = 0;  i < 10;  i++) {
490
                phy_ok = phy_read(PHY_BMCR, FEC_ETH_PHY, &phy_state);
491
                if (!phy_ok) break;
492
                if (!(phy_state & PHY_BMCR_RESET)) break;
493
            }
494
            if (!phy_ok || (phy_state & PHY_BMCR_RESET)) {
495
                os_printf("FEC: Can't get PHY unit to soft reset: %x\n", phy_state);
496
                return false;
497
            }
498
 
499
            fec->iEvent = 0xFFFFFFFF;  // Clear all interrupts
500
            reset_mode = PHY_BMCR_RESTART;
501
#ifdef CYGNUM_DEVS_ETH_POWERPC_FEC_LINK_MODE_Auto
502
            reset_mode |= PHY_BMCR_AUTO_NEG;
503
#endif
504
#ifdef CYGNUM_DEVS_ETH_POWERPC_FEC_LINK_MODE_100Mb
505
            reset_mode |= PHY_BMCR_100MB;
506
#endif
507
            phy_write(PHY_BMCR, FEC_ETH_PHY, reset_mode);
508
            while (phy_timeout-- >= 0) {
509
                int ev = fec->iEvent;
510
                unsigned short state;
511
                fec->iEvent = ev;
512
                if (ev & iEvent_MII) {
513
                    phy_ok = phy_read(PHY_BMSR, FEC_ETH_PHY, &state);
514
                    if (phy_ok && (state & PHY_BMSR_LINK)) {
515
                        break;
516
                    } else {
517
                        CYGACC_CALL_IF_DELAY_US(10000);   // 10ms
518
                    }
519
                }
520
            }
521
            if (phy_timeout <= 0) {
522
                os_printf("** FEC Warning: PHY LINK UP failed\n");
523
            }
524
        }
525
        else {
526
            os_printf("** FEC Info: PHY LINK already UP \n");
527
        }
528
    }
529
#endif // CYGSEM_DEVS_ETH_POWERPC_FEC_RESET_PHY
530
 
531
    // Initialize upper level driver
532
    (sc->funs->eth_drv->init)(sc, (unsigned char *)&enaddr);
533
 
534
    if (cache_state)
535
      HAL_DCACHE_ENABLE();
536
 
537
    return true;
538
}
539
 
540
//
541
// This function is called to shut down the interface.
542
//
543
static void
544
fec_eth_stop(struct eth_drv_sc *sc)
545
{
546
    struct fec_eth_info *qi = (struct fec_eth_info *)sc->driver_private;
547
 
548
    // Disable the device!
549
    qi->fec->eControl &= ~eControl_EN;
550
}
551
 
552
//
553
// This function is called to "start up" the interface.  It may be called
554
// multiple times, even when the hardware is already running.  It will be
555
// called whenever something "hardware oriented" changes and should leave
556
// the hardware ready to send/receive packets.
557
//
558
static void
559
fec_eth_start(struct eth_drv_sc *sc, unsigned char *enaddr, int flags)
560
{
561
    // Enable the device!
562
    fec_eth_reset(sc, enaddr, flags);
563
}
564
 
565
//
566
// This function is called for low level "control" operations
567
//
568
static int
569
fec_eth_control(struct eth_drv_sc *sc, unsigned long key,
570
                  void *data, int length)
571
{
572
#ifdef ETH_DRV_SET_MC_ALL
573
    struct fec_eth_info *qi = (struct fec_eth_info *)sc->driver_private;
574
    volatile struct fec *fec = qi->fec;
575
#endif
576
 
577
    switch (key) {
578
    case ETH_DRV_SET_MAC_ADDRESS:
579
        return 0;
580
        break;
581
#ifdef ETH_DRV_SET_MC_ALL
582
    case ETH_DRV_SET_MC_ALL:
583
    case ETH_DRV_SET_MC_LIST:
584
        fec->RxControl &= ~RxControl_PROM;
585
        fec->hash[0] = 0xFFFFFFFF;
586
        fec->hash[1] = 0xFFFFFFFF;
587
        return 0;
588
        break;
589
#endif
590
    default:
591
        return 1;
592
        break;
593
    }
594
}
595
 
596
//
597
// This function is called to see if another packet can be sent.
598
// It should return the number of packets which can be handled.
599
// Zero should be returned if the interface is busy and can not send any more.
600
//
601
static int
602
fec_eth_can_send(struct eth_drv_sc *sc)
603
{
604
    struct fec_eth_info *qi = (struct fec_eth_info *)sc->driver_private;
605
 
606
    return (qi->txactive < CYGNUM_DEVS_ETH_POWERPC_FEC_TxNUM);
607
}
608
 
609
//
610
// This routine is called to send data to the hardware.
611
 
612
static void
613
fec_eth_send(struct eth_drv_sc *sc, struct eth_drv_sg *sg_list, int sg_len,
614
               int total_len, unsigned long key)
615
{
616
    struct fec_eth_info *qi = (struct fec_eth_info *)sc->driver_private;
617
    volatile struct fec_bd *txbd, *txfirst;
618
    volatile char *bp;
619
    int i, txindex, cache_state;
620
 
621
    // Find a free buffer
622
    txbd = txfirst = qi->txbd;
623
    while (txbd->ctrl & FEC_BD_Tx_Ready) {
624
        // This buffer is busy, move to next one
625
        if (txbd->ctrl & FEC_BD_Tx_Wrap) {
626
            txbd = qi->tbase;
627
        } else {
628
            txbd++;
629
        }
630
        if (txbd == txfirst) {
631
#ifdef CYGPKG_NET
632
            panic ("No free xmit buffers");
633
#else
634
            os_printf("FEC Ethernet: No free xmit buffers\n");
635
#endif
636
        }
637
    }
638
    // Set up buffer
639
    bp = txbd->buffer;
640
    for (i = 0;  i < sg_len;  i++) {
641
        memcpy((void *)bp, (void *)sg_list[i].buf, sg_list[i].len);
642
        bp += sg_list[i].len;
643
    }
644
    txbd->length = total_len;
645
    txindex = ((unsigned long)txbd - (unsigned long)qi->tbase) / sizeof(*txbd);
646
    qi->txkey[txindex] = key;
647
    // Note: the MPC860 does not seem to snoop/invalidate the data cache properly!
648
    HAL_DCACHE_IS_ENABLED(cache_state);
649
    if (cache_state) {
650
        HAL_DCACHE_FLUSH(txbd->buffer, txbd->length);  // Make sure no stale data
651
    }
652
    // Send it on it's way
653
    txbd->ctrl |= FEC_BD_Tx_Ready | FEC_BD_Tx_Last | FEC_BD_Tx_TC;
654
#ifndef FEC_USE_EPPC_BD
655
    if (cache_state) {
656
        HAL_DCACHE_FLUSH(fec_eth_txring, sizeof(fec_eth_txring));  // Make sure no stale data
657
    }
658
#endif
659
    qi->txactive++;
660
    qi->fec->TxUpdate = 0x01000000;  // Any write tells machine to look for work
661
    set_led(LED_TxACTIVE);
662
    // Remember the next buffer to try
663
    if (txbd->ctrl & FEC_BD_Tx_Wrap) {
664
        qi->txbd = qi->tbase;
665
    } else {
666
        qi->txbd = txbd+1;
667
    }
668
}
669
 
670
//
671
// This function is called when a packet has been received.  It's job is
672
// to prepare to unload the packet from the hardware.  Once the length of
673
// the packet is known, the upper layer of the driver can be told.  When
674
// the upper layer is ready to unload the packet, the internal function
675
// 'fec_eth_recv' will be called to actually fetch it from the hardware.
676
//
677
static void
678
fec_eth_RxEvent(struct eth_drv_sc *sc)
679
{
680
    struct fec_eth_info *qi = (struct fec_eth_info *)sc->driver_private;
681
    volatile struct fec_bd *rxbd, *rxfirst;
682
    int cache_state;
683
 
684
    // Note: the MPC860 does not seem to snoop/invalidate the data cache properly!
685
    HAL_DCACHE_IS_ENABLED(cache_state);
686
#ifndef FEC_USE_EPPC_BD
687
    if (cache_state) {
688
        HAL_DCACHE_INVALIDATE(fec_eth_rxring, sizeof(fec_eth_rxring));  // Make sure no stale data
689
    }
690
#endif
691
    rxbd = rxfirst = qi->rnext;
692
    while (true) {
693
        if ((rxbd->ctrl & FEC_BD_Rx_Empty) == 0) {
694
            qi->rxbd = rxbd;  // Save for callback
695
            set_led(LED_RxACTIVE);
696
            (sc->funs->eth_drv->recv)(sc, rxbd->length);
697
        }
698
        if (rxbd->ctrl & FEC_BD_Rx_Wrap) {
699
            rxbd = qi->rbase;
700
        } else {
701
            rxbd++;
702
        }
703
        if (rxbd == rxfirst) {
704
            break;
705
        }
706
    }
707
    // Remember where we left off
708
    qi->rnext = (struct fec_bd *)rxbd;
709
#ifndef FEC_USE_EPPC_BD
710
    if (cache_state) {
711
        HAL_DCACHE_INVALIDATE(fec_eth_rxring, sizeof(fec_eth_rxring));  // Make sure no stale data
712
    }
713
#endif
714
    qi->fec->RxUpdate = 0x0F0F0F0F;  // Any write tells machine to look for work
715
}
716
 
717
//
718
// This function is called as a result of the "eth_drv_recv()" call above.
719
// It's job is to actually fetch data for a packet from the hardware once
720
// memory buffers have been allocated for the packet.  Note that the buffers
721
// may come in pieces, using a scatter-gather list.  This allows for more
722
// efficient processing in the upper layers of the stack.
723
//
724
static void
725
fec_eth_recv(struct eth_drv_sc *sc, struct eth_drv_sg *sg_list, int sg_len)
726
{
727
    struct fec_eth_info *qi = (struct fec_eth_info *)sc->driver_private;
728
    unsigned char *bp;
729
    int i, cache_state;
730
 
731
    bp = (unsigned char *)qi->rxbd->buffer;
732
    // Note: the MPC860 does not seem to snoop/invalidate the data cache properly!
733
    HAL_DCACHE_IS_ENABLED(cache_state);
734
    if (cache_state) {
735
        HAL_DCACHE_INVALIDATE(qi->rxbd->buffer, qi->rxbd->length);  // Make sure no stale data
736
    }
737
    for (i = 0;  i < sg_len;  i++) {
738
        if (sg_list[i].buf != 0) {
739
            memcpy((void *)sg_list[i].buf, bp, sg_list[i].len);
740
            bp += sg_list[i].len;
741
        }
742
    }
743
    qi->rxbd->ctrl |= FEC_BD_Rx_Empty;
744
    clear_led(LED_RxACTIVE);
745
}
746
 
747
static void
748
fec_eth_TxEvent(struct eth_drv_sc *sc)
749
{
750
    struct fec_eth_info *qi = (struct fec_eth_info *)sc->driver_private;
751
    volatile struct fec_bd *txbd;
752
    int key, txindex, cache_state;
753
 
754
    HAL_DCACHE_IS_ENABLED(cache_state);
755
#ifndef FEC_USE_EPPC_BD
756
    if (cache_state) {
757
        HAL_DCACHE_FLUSH(fec_eth_txring, sizeof(fec_eth_txring));  // Make sure no stale data
758
    }
759
#endif
760
    txbd = qi->tnext;
761
    // Note: TC field is used to indicate the buffer has/had data in it
762
    while ((txbd->ctrl & (FEC_BD_Tx_Ready|FEC_BD_Tx_TC)) == FEC_BD_Tx_TC) {
763
        txindex = ((unsigned long)txbd - (unsigned long)qi->tbase) / sizeof(*txbd);
764
        if ((key = qi->txkey[txindex]) != 0) {
765
            qi->txkey[txindex] = 0;
766
            (sc->funs->eth_drv->tx_done)(sc, key, 0);
767
        }
768
        if (--qi->txactive == 0) {
769
          clear_led(LED_TxACTIVE);
770
        }
771
        txbd->ctrl &= ~FEC_BD_Tx_TC;
772
        if (txbd->ctrl & FEC_BD_Tx_Wrap) {
773
            txbd = qi->tbase;
774
        } else {
775
            txbd++;
776
        }
777
    }
778
    // Remember where we left off
779
    qi->tnext = (struct fec_bd *)txbd;
780
#ifndef FEC_USE_EPPC_BD
781
    if (cache_state) {
782
        HAL_DCACHE_FLUSH(fec_eth_txring, sizeof(fec_eth_txring));  // Make sure no stale data
783
    }
784
#endif
785
}
786
 
787
//
788
// Interrupt processing
789
//
790
static void
791
fec_eth_int(struct eth_drv_sc *sc)
792
{
793
    struct fec_eth_info *qi = (struct fec_eth_info *)sc->driver_private;
794
    unsigned long event;
795
 
796
    while ((event = qi->fec->iEvent) != 0) {
797
        if ((event & iEvent_TFINT) != 0) {
798
            fec_eth_TxEvent(sc);
799
        }
800
        if ((event & iEvent_RFINT) != 0) {
801
            fec_eth_RxEvent(sc);
802
        }
803
        qi->fec->iEvent = event;  // Reset the bits we handled
804
    }
805
}
806
 
807
//
808
// Interrupt vector
809
//
810
static int
811
fec_eth_int_vector(struct eth_drv_sc *sc)
812
{
813
    return (FEC_ETH_INT);
814
}
815
 
816
#if defined(CYGINT_IO_ETH_INT_SUPPORT_REQUIRED) && ~defined(_FEC_USE_INTS)
817
void
818
fec_fake_int(cyg_addrword_t param)
819
{
820
    struct eth_drv_sc *sc = (struct eth_drv_sc *) param;
821
    int int_state;
822
 
823
    while (true) {
824
      cyg_thread_delay(1);  // 10ms
825
      HAL_DISABLE_INTERRUPTS(int_state);
826
      fec_eth_int(sc);
827
      HAL_RESTORE_INTERRUPTS(int_state);
828
    }
829
}
830
#endif

powered by: WebSVN 2.1.0

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