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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [devs/] [eth/] [powerpc/] [fcc/] [current/] [src/] [if_fcc.c] - Blame information for rev 786

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 786 skrzyp
//==========================================================================
2
//
3
//      dev/if_fcc.c
4
//
5
//      Fast ethernet device driver for PowerPC MPC8xxx (QUICC-II) 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, 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
//==========================================================================
40
//#####DESCRIPTIONBEGIN####
41
//
42
// Author(s):    gthomas
43
// Contributors: mtek, pfine
44
// Date:         2003-08-19
45
// Purpose:      
46
// Description:  hardware driver for MPC8xxx FCC
47
//              
48
//
49
//####DESCRIPTIONEND####
50
//
51
//==========================================================================
52
 
53
#include <pkgconf/devs_eth_powerpc_fcc.h>
54
#include <cyg/infra/cyg_type.h>
55
#include <cyg/infra/diag.h>
56
 
57
#include <cyg/hal/hal_arch.h>
58
#include <cyg/hal/hal_cache.h>
59
#include <cyg/hal/hal_intr.h>
60
#include <cyg/hal/drv_api.h>
61
#include <cyg/hal/hal_if.h>
62
#include <cyg/hal/mpc8xxx.h>
63
 
64
#include <cyg/io/eth/netdev.h>
65
#include <cyg/io/eth/eth_drv.h>
66
 
67
#ifdef CYGPKG_NET
68
#include <pkgconf/net.h>
69
#endif
70
 
71
#ifdef CYGPKG_DEVS_ETH_PHY
72
#include <cyg/io/eth_phy.h>
73
#endif
74
 
75
#include "fcc.h"
76
 
77
#ifdef CYGPKG_REDBOOT
78
#include <pkgconf/redboot.h>
79
#ifdef CYGSEM_REDBOOT_FLASH_CONFIG
80
#include <redboot.h>
81
#include <flash_config.h>
82
#endif
83
#endif
84
 
85
#ifdef CYGDAT_DEVS_FCC_ETH_INL
86
#include CYGDAT_DEVS_FCC_ETH_CDL   // platform configury
87
#include CYGDAT_DEVS_FCC_ETH_INL   // platform details
88
#else
89
#error "No board instance defined!"
90
#endif
91
 
92
#define ALIGN_TO_CACHE_LINES(x)  ( (long)((x) + 31) & 0xffffffe0 )
93
 
94
// Buffer descriptors are in dual ported RAM, which is marked non-cached
95
#define FCC_BDs_NONCACHED
96
 
97
#define os_printf diag_printf
98
 
99
// CONFIG_ESA and CONFIG_BOOL are defined in redboot/include/flash_config.h
100
#ifndef CONFIG_ESA
101
#define CONFIG_ESA 6      // ethernet address length ...
102
#endif
103
 
104
#ifndef CONFIG_BOOL
105
#define CONFIG_BOOL 1
106
#endif
107
 
108
static void          fcc_eth_int(struct eth_drv_sc *data);
109
 
110
// This ISR is called when the ethernet interrupt occurs
111
#ifdef CYGPKG_NET
112
static int
113
fcc_eth_isr(cyg_vector_t vector, cyg_addrword_t data, HAL_SavedRegisters *regs)
114
{
115
    struct eth_drv_sc *sc = (struct eth_drv_sc *)data;
116
    struct fcc_eth_info *qi = (struct fcc_eth_info *)sc->driver_private;
117
 
118
    cyg_drv_interrupt_mask(qi->int_vector);
119
    return (CYG_ISR_HANDLED|CYG_ISR_CALL_DSR);  // Run the DSR
120
}
121
#endif
122
 
123
// Deliver function (ex-DSR) handles the ethernet [logical] processing
124
static void
125
fcc_eth_deliver(struct eth_drv_sc * sc)
126
{
127
#ifdef CYGPKG_NET
128
    struct fcc_eth_info *qi = (struct fcc_eth_info *)sc->driver_private;
129
#endif
130
 
131
    fcc_eth_int(sc);
132
#ifdef CYGPKG_NET
133
    //  Clearing the event register acknowledges FCC interrupt ...
134
    cyg_drv_interrupt_unmask(qi->int_vector);
135
#endif
136
 
137
}
138
 
139
 
140
// Initialize the interface - performed at system startup
141
// This function must set up the interface, including arranging to
142
// handle interrupts, etc, so that it may be "started" cheaply later.
143
static bool
144
fcc_eth_init(struct cyg_netdevtab_entry *dtp)
145
{
146
    struct eth_drv_sc *sc = (struct eth_drv_sc *)dtp->device_instance;
147
    struct fcc_eth_info *qi = (struct fcc_eth_info *)sc->driver_private;
148
    volatile t_Fcc_Pram  *fcc =  (volatile t_Fcc_Pram *)0;
149
    volatile t_EnetFcc_Pram *E_fcc;
150
    int i, fcc_chan;
151
    bool esa_ok;
152
    unsigned char *c_ptr;
153
    unsigned char _enaddr[6];
154
    unsigned long rxbase, txbase;
155
    struct fcc_bd *rxbd, *txbd;
156
    // The FCC seems rather picky about these...
157
    static long rxbd_base = 0x3000;
158
    static long txbd_base = 0xB000;
159
#ifdef CYGPKG_DEVS_ETH_PHY
160
    unsigned short phy_state = 0;
161
#endif
162
 
163
    // Set up pointers to FCC controller
164
    switch (qi->int_vector) {
165
    case CYGNUM_HAL_INTERRUPT_FCC1:
166
        qi->fcc_reg = &(IMM->fcc_regs[FCC1]);
167
        fcc =  (volatile t_Fcc_Pram *)((unsigned long)IMM + FCC1_PRAM_OFFSET);
168
        fcc_chan = FCC1_PAGE_SUBBLOCK;
169
        break;
170
    case CYGNUM_HAL_INTERRUPT_FCC2:
171
        qi->fcc_reg = &(IMM->fcc_regs[FCC2]);
172
        fcc =  (volatile t_Fcc_Pram *)((unsigned long)IMM + FCC2_PRAM_OFFSET);
173
        fcc_chan = FCC2_PAGE_SUBBLOCK;
174
        break;
175
        case CYGNUM_HAL_INTERRUPT_FCC3:
176
                qi->fcc_reg = &(IMM->fcc_regs[FCC3]);
177
        fcc =  (volatile t_Fcc_Pram *)((unsigned long)IMM + FCC3_PRAM_OFFSET);
178
        fcc_chan = FCC3_PAGE_SUBBLOCK;
179
        break;
180
    default:
181
        os_printf("Can't initialize '%s' - unknown FCC!\n", dtp->name);
182
        return false;
183
    }
184
 
185
    // just in case :  disable Transmit and Receive 
186
    qi->fcc_reg->fcc_gfmr &= ~(FCC_GFMR_EN_Rx | FCC_GFMR_EN_Tx);
187
 
188
    // Try to read the ethernet address of the transciever ...
189
#ifdef CYGPKG_REDBOOT
190
    esa_ok = flash_get_config(qi->esa_key, _enaddr, CONFIG_ESA);
191
#else
192
    esa_ok = CYGACC_CALL_IF_FLASH_CFG_OP(CYGNUM_CALL_IF_FLASH_CFG_GET,
193
                                         qi->esa_key, _enaddr, CONFIG_ESA);
194
#endif
195
    if (esa_ok) {
196
        memcpy(qi->enaddr, _enaddr, sizeof(qi->enaddr));
197
    } else {
198
        // No 'flash config' data available - use default
199
        os_printf("FCC_ETH - Warning! Using default ESA for '%s'\n", dtp->name);
200
    }
201
 
202
    // Initialize Receive Buffer Descriptors
203
    rxbase = rxbd_base;
204
    fcc->riptr = rxbase;           // temp work buffer
205
    fcc->mrblr = FCC_PRAM_MRBLR;   // Max Rx buffer 
206
    fcc->rstate &= FCC_FCR_INIT;
207
    fcc->rstate |= FCC_FCR_MOT_BO;
208
    rxbase += 64;
209
    rxbd_base += sizeof(struct fcc_bd)*qi->rxnum + 64;
210
    rxbd = (struct fcc_bd *)(CYGARC_IMM_BASE + rxbase);
211
    fcc->rbase = (CYG_WORD)rxbd;
212
    c_ptr = qi->rxbuf;
213
    qi->rbase = rxbd;
214
    qi->rxbd  = rxbd;
215
    qi->rnext = rxbd;
216
 
217
    for (i = 0; i < qi->rxnum; i++, rxbd++) {
218
        rxbd->ctrl   = (FCC_BD_Rx_Empty | FCC_BD_Rx_Int);
219
        rxbd->length = 0;                   // reset 
220
        c_ptr = (unsigned char *) ALIGN_TO_CACHE_LINES(c_ptr);
221
        rxbd->buffer = (volatile unsigned char *)c_ptr;
222
        c_ptr += CYGNUM_DEVS_ETH_POWERPC_FCC_BUFSIZE;
223
    }
224
    rxbd--;
225
    rxbd->ctrl |= FCC_BD_Rx_Wrap;
226
 
227
    // Initialize Transmit Buffer Descriptors
228
    txbase = txbd_base;
229
    fcc->tiptr = txbase;   // in dual port RAM (see 28-11)
230
    fcc->tstate &= FCC_FCR_INIT;
231
    fcc->tstate |= FCC_FCR_MOT_BO;
232
    txbase += 64;
233
    txbd_base += sizeof(struct fcc_bd)*qi->txnum + 64;
234
    txbd = (struct fcc_bd *)(CYGARC_IMM_BASE + txbase);
235
    fcc->tbase = (CYG_WORD)txbd;
236
    c_ptr = qi->txbuf;
237
    qi->tbase = txbd;
238
    qi->txbd  = txbd;
239
    qi->tnext = txbd;
240
 
241
    for (i = 0; i < qi->txnum; i++, txbd++) {
242
        txbd->ctrl   = (FCC_BD_Tx_Pad | FCC_BD_Tx_Int);
243
        txbd->length = 0;   // reset : Write before send
244
        c_ptr = (unsigned char *) ALIGN_TO_CACHE_LINES(c_ptr);
245
        txbd->buffer = (volatile unsigned char  *)c_ptr;
246
        c_ptr += CYGNUM_DEVS_ETH_POWERPC_FCC_BUFSIZE;
247
    }
248
    txbd--;
249
    txbd->ctrl |= FCC_BD_Tx_Wrap;
250
 
251
    // Ethernet Specific FCC Parameter RAM Initialization     
252
    E_fcc = &(fcc->SpecificProtocol.e);
253
    E_fcc->c_mask   = FCC_PRAM_C_MASK; // (see 30-9)
254
    E_fcc->c_pres   = FCC_PRAM_C_PRES;
255
    E_fcc->crcec    = 0;
256
    E_fcc->alec     = 0;
257
    E_fcc->disfc    = 0;
258
    E_fcc->ret_lim  = FCC_PRAM_RETLIM;
259
    E_fcc->p_per    = FCC_PRAM_PER_LO;
260
    E_fcc->gaddr_h  = 0;
261
    E_fcc->gaddr_l  = 0;
262
    E_fcc->tfcstat  = 0;
263
    E_fcc->mflr     = FCC_MAX_FLR;
264
 
265
    E_fcc->paddr1_h = ((short)qi->enaddr[5] << 8) | qi->enaddr[4];
266
    E_fcc->paddr1_m = ((short)qi->enaddr[3] << 8) | qi->enaddr[2];
267
    E_fcc->paddr1_l = ((short)qi->enaddr[1] << 8) | qi->enaddr[0];
268
 
269
    E_fcc->iaddr_h  = 0;
270
    E_fcc->iaddr_l  = 0;
271
    E_fcc->minflr   = FCC_MIN_FLR;
272
    E_fcc->taddr_h  = 0;
273
    E_fcc->taddr_m  = 0;
274
    E_fcc->taddr_l  = 0;
275
    E_fcc->pad_ptr  = fcc->tiptr; // No special padding char ...
276
    E_fcc->cf_type  = 0;
277
    E_fcc->maxd1    = FCC_PRAM_MAXD;
278
    E_fcc->maxd2    = FCC_PRAM_MAXD;
279
 
280
    // FCC register initialization 
281
    qi->fcc_reg->fcc_gfmr = FCC_GFMR_INIT;
282
    qi->fcc_reg->fcc_psmr = FCC_PSMR_INIT;
283
    qi->fcc_reg->fcc_dsr  = FCC_DSR_INIT;
284
 
285
#ifdef CYGPKG_NET
286
    // clear the events of FCCX
287
    qi->fcc_reg->fcc_fcce = 0xFFFF;
288
    qi->fcc_reg->fcc_fccm = FCC_EV_TXE | FCC_EV_TXB | FCC_EV_RXF;
289
 
290
    // Set up to handle interrupts
291
    cyg_drv_interrupt_create(qi->int_vector,
292
                             0,  // Highest //CYGARC_SIU_PRIORITY_HIGH,
293
                             (cyg_addrword_t)sc, //  Data passed to ISR
294
                             (cyg_ISR_t *)fcc_eth_isr,
295
                             (cyg_DSR_t *)eth_drv_dsr,
296
                             &qi->fcc_eth_interrupt_handle,
297
                             &qi->fcc_eth_interrupt);
298
    cyg_drv_interrupt_attach(qi->fcc_eth_interrupt_handle);
299
    cyg_drv_interrupt_acknowledge(qi->int_vector);
300
    cyg_drv_interrupt_unmask(qi->int_vector);
301
#else
302
 
303
    // Mask the interrupts 
304
    qi->fcc_reg->fcc_fccm = 0;
305
#endif
306
 
307
    // Issue Init RX & TX Parameters Command for FCCx
308
    while ((IMM->cpm_cpcr & CPCR_FLG) != CPCR_READY_TO_RX_CMD);
309
    IMM->cpm_cpcr = CPCR_INIT_TX_RX_PARAMS |
310
        fcc_chan |
311
        CPCR_MCN_FCC |
312
        CPCR_FLG;              /* ISSUE COMMAND */
313
    while ((IMM->cpm_cpcr & CPCR_FLG) != CPCR_READY_TO_RX_CMD);
314
 
315
    // Operating mode
316
    if (!_eth_phy_init(qi->phy)) {
317
        return false;
318
    }
319
#ifdef CYGSEM_DEVS_ETH_POWERPC_FCC_RESET_PHY
320
    _eth_phy_reset(qi->phy);
321
#endif
322
    phy_state = _eth_phy_state(qi->phy);
323
    os_printf("FCC %s: ", sc->dev_name);
324
    if ((phy_state & ETH_PHY_STAT_LINK) != 0) {
325
        if ((phy_state & ETH_PHY_STAT_100MB) != 0) {
326
            // Link can handle 100Mb
327
            os_printf("100Mb");
328
            if ((phy_state & ETH_PHY_STAT_FDX) != 0) {
329
                os_printf("/Full Duplex");
330
            }
331
        } else {
332
            // Assume 10Mb, half duplex
333
            os_printf("10Mb");
334
        }
335
    } else {
336
        os_printf("/***NO LINK***\n");
337
#ifdef CYGPKG_REDBOOT
338
        return false;
339
#endif
340
    }
341
    os_printf("\n");
342
 
343
 
344
    // Initialize upper level driver for ecos
345
    (sc->funs->eth_drv->init)(sc, (unsigned char *)&qi->enaddr);
346
 
347
    return true;
348
}
349
 
350
//
351
// This function is called to "start up" the interface.  It may be called
352
// multiple times, even when the hardware is already running.  It will be
353
// called whenever something "hardware oriented" changes and should leave
354
// the hardware ready to send/receive packets.
355
//
356
static void
357
fcc_eth_start(struct eth_drv_sc *sc, unsigned char *enaddr, int flags)
358
{
359
  struct fcc_eth_info *qi = (struct fcc_eth_info *)sc->driver_private;
360
 
361
  // Enable the device : 
362
  // Set the ENT/ENR bits in the GFMR -- Enable Transmit/Receive
363
  qi->fcc_reg->fcc_gfmr |= (FCC_GFMR_EN_Rx | FCC_GFMR_EN_Tx);
364
 
365
}
366
 
367
//
368
// This function is called to shut down the interface.
369
//
370
static void
371
fcc_eth_stop(struct eth_drv_sc *sc)
372
{
373
  struct fcc_eth_info *qi = (struct fcc_eth_info *)sc->driver_private;
374
 
375
  // Disable the device : 
376
  // Clear the ENT/ENR bits in the GFMR -- Disable Transmit/Receive
377
  qi->fcc_reg->fcc_gfmr &= ~(FCC_GFMR_EN_Rx | FCC_GFMR_EN_Tx);
378
}
379
 
380
 
381
//
382
// This function is called for low level "control" operations
383
//
384
static int
385
fcc_eth_control(struct eth_drv_sc *sc, unsigned long key,
386
                void *data, int length)
387
{
388
  switch (key) {
389
  case ETH_DRV_SET_MAC_ADDRESS:
390
    return 0;
391
    break;
392
  default:
393
    return 1;
394
    break;
395
  }
396
}
397
 
398
 
399
//
400
// This function is called to see if another packet can be sent.
401
// It should return the number of packets which can be handled.
402
// Zero should be returned if the interface is busy and can not send any more.
403
//
404
static int
405
fcc_eth_can_send(struct eth_drv_sc *sc)
406
{
407
  struct fcc_eth_info *qi = (struct fcc_eth_info *)sc->driver_private;
408
  volatile struct fcc_bd *txbd = qi->txbd;
409
#ifndef FCC_BDs_NONCACHED
410
  int cache_state;
411
#endif
412
 
413
#ifndef FCC_BDs_NONCACHED
414
  HAL_DCACHE_IS_ENABLED(cache_state);
415
  if (cache_state) {
416
    HAL_DCACHE_INVALIDATE(fcc_eth_txring,
417
                          8*CYGNUM_DEVS_ETH_POWERPC_FCC_TxNUM);
418
  }
419
#endif
420
 
421
  return ((txbd->ctrl & (FCC_BD_Tx_TC | FCC_BD_Tx_Ready)) == 0);
422
}
423
 
424
//
425
// This routine is called to send data to the hardware.
426
static void
427
fcc_eth_send(struct eth_drv_sc *sc, struct eth_drv_sg *sg_list, int sg_len,
428
             int total_len, unsigned long key)
429
{
430
  struct fcc_eth_info *qi = (struct fcc_eth_info *)sc->driver_private;
431
  struct fcc_bd *txbd, *txfirst;
432
  volatile char *bp;
433
  int i, txindex;
434
  int cache_state;
435
 
436
  HAL_DCACHE_IS_ENABLED(cache_state);
437
#ifndef FCC_BDs_NONCACHED
438
  if (cache_state) {
439
    HAL_DCACHE_INVALIDATE(fcc_eth_txring,
440
                          8*CYGNUM_DEVS_ETH_POWERPC_FCC_TxNUM);
441
  }
442
#endif
443
 
444
  // Find a free buffer
445
  txbd = txfirst = qi->txbd;
446
  while (txbd->ctrl & FCC_BD_Tx_Ready) {
447
    // This buffer is busy, move to next one
448
    if (txbd->ctrl & FCC_BD_Tx_Wrap) {
449
      txbd = qi->tbase;
450
    } else {
451
      txbd++;
452
    }
453
    if (txbd == txfirst) {
454
#ifdef CYGPKG_NET
455
      panic ("No free xmit buffers");
456
#else
457
      os_printf("FCC Ethernet: No free xmit buffers\n");
458
#endif
459
    }
460
  }
461
 
462
  // Remember the next buffer to try
463
  if (txbd->ctrl & FCC_BD_Tx_Wrap) {
464
    qi->txbd = qi->tbase;
465
  } else {
466
    qi->txbd = txbd+1;
467
  }
468
 
469
  txindex = ((unsigned long)txbd - (unsigned long)qi->tbase) / sizeof(*txbd);
470
  qi->txkey[txindex] = key;
471
 
472
  // Set up buffer
473
  txbd->length = total_len;
474
  bp = txbd->buffer;
475
  for (i = 0;  i < sg_len;  i++) {
476
    memcpy((void *)bp, (void *)sg_list[i].buf, sg_list[i].len);
477
    bp += sg_list[i].len;
478
  }
479
 
480
  // Make sure no stale data buffer ...
481
  if (cache_state) {
482
    HAL_DCACHE_FLUSH(txbd->buffer, txbd->length);
483
  }
484
 
485
  // Send it on it's way
486
  txbd->ctrl |= FCC_BD_Tx_Ready | FCC_BD_Tx_Last | FCC_BD_Tx_TC;
487
 
488
#ifndef FCC_BDs_NONCACHED
489
  if (cache_state) {
490
    HAL_DCACHE_FLUSH(fcc_eth_txring,
491
                     8*CYGNUM_DEVS_ETH_POWERPC_FCC_TxNUM);
492
  }
493
#endif  
494
 
495
}
496
 
497
//
498
// This function is called when a packet has been received.  It's job is
499
// to prepare to unload the packet from the hardware.  Once the length of
500
// the packet is known, the upper layer of the driver can be told.  When
501
// the upper layer is ready to unload the packet, the internal function
502
// 'fcc_eth_recv' will be called to actually fetch it from the hardware.
503
//
504
static void
505
fcc_eth_RxEvent(struct eth_drv_sc *sc)
506
{
507
  struct fcc_eth_info *qi = (struct fcc_eth_info *)sc->driver_private;
508
  struct fcc_bd *rxbd;
509
  int cache_state;
510
 
511
  HAL_DCACHE_IS_ENABLED(cache_state);
512
#ifndef FCC_BDs_NONCACHED
513
  if (cache_state) {
514
    HAL_DCACHE_INVALIDATE(fcc_eth_rxring,
515
                          8*CYGNUM_DEVS_ETH_POWERPC_FCC_RxNUM);
516
  }
517
#endif
518
 
519
  rxbd = qi->rnext;
520
  while ((rxbd->ctrl & FCC_BD_Rx_Empty) == 0) {
521
    qi->rxbd = rxbd;  // Save for callback
522
 
523
    // This is the right way of doing it, but dcbi has a bug ...
524
    //    if (cache_state) {
525
    //      HAL_DCACHE_INVALIDATE(rxbd->buffer, rxbd->length); 
526
    //    }
527
    if ((rxbd->ctrl & FCC_BD_Rx_ERRORS) == 0) {
528
        (sc->funs->eth_drv->recv)(sc, rxbd->length);
529
#if 1 // Coherent caches?
530
        if (cache_state) {
531
            HAL_DCACHE_FLUSH(rxbd->buffer, rxbd->length);
532
        }
533
#endif
534
    }
535
    // Reset control flags to known [empty] state, clearing error bits
536
    if (rxbd->ctrl & FCC_BD_Rx_Wrap) {
537
      rxbd->ctrl = FCC_BD_Rx_Empty | FCC_BD_Rx_Int | FCC_BD_Rx_Wrap;
538
      rxbd = qi->rbase;
539
    } else {
540
      rxbd->ctrl = FCC_BD_Rx_Empty | FCC_BD_Rx_Int;
541
      rxbd++;
542
    }
543
  }
544
  // Remember where we left off
545
  qi->rnext = (struct fcc_bd *)rxbd;
546
 
547
  // Make sure no stale data
548
#ifndef FCC_BDs_NONCACHED
549
  if (cache_state) {
550
    HAL_DCACHE_FLUSH(fcc_eth_rxring,
551
                     8*CYGNUM_DEVS_ETH_POWERPC_FCC_RxNUM);
552
  }
553
#endif
554
 
555
}
556
 
557
//
558
// This function is called as a result of the "eth_drv_recv()" call above.
559
// It's job is to actually fetch data for a packet from the hardware once
560
// memory buffers have been allocated for the packet.  Note that the buffers
561
// may come in pieces, using a scatter-gather list.  This allows for more
562
// efficient processing in the upper layers of the stack.
563
//
564
static void
565
fcc_eth_recv(struct eth_drv_sc *sc, struct eth_drv_sg *sg_list, int sg_len)
566
{
567
  struct fcc_eth_info *qi = (struct fcc_eth_info *)sc->driver_private;
568
  unsigned char *bp;
569
  int i;
570
 
571
  bp = (unsigned char *)qi->rxbd->buffer;
572
 
573
  for (i = 0;  i < sg_len;  i++) {
574
    if (sg_list[i].buf != 0) {
575
      memcpy((void *)sg_list[i].buf, bp, sg_list[i].len);
576
      bp += sg_list[i].len;
577
    }
578
  }
579
 
580
}
581
 
582
static void
583
fcc_eth_TxEvent(struct eth_drv_sc *sc, int stat)
584
{
585
  struct fcc_eth_info *qi = (struct fcc_eth_info *)sc->driver_private;
586
  struct fcc_bd *txbd;
587
  int txindex;
588
#ifndef FCC_BDs_NONCACHED
589
  int cache_state;
590
#endif
591
 
592
#ifndef FCC_BDs_NONCACHED
593
  // Make sure no stale data
594
  HAL_DCACHE_IS_ENABLED(cache_state);
595
  if (cache_state) {
596
    HAL_DCACHE_INVALIDATE(fcc_eth_txring,
597
                          8*CYGNUM_DEVS_ETH_POWERPC_FCC_TxNUM);
598
  }
599
#endif
600
 
601
  txbd = qi->tnext;
602
  // Note: TC field is used to indicate the buffer has/had data in it
603
  while ( (txbd->ctrl & (FCC_BD_Tx_TC | FCC_BD_Tx_Ready)) == FCC_BD_Tx_TC ) {
604
      if ((txbd->ctrl & FCC_BD_Tx_ERRORS) != 0) {
605
#if 0
606
          diag_printf("FCC Tx error BD: %x/%x- ", txbd, txbd->ctrl);
607
          if ((txbd->ctrl & FCC_BD_Tx_LC) != 0) diag_printf("Late Collision/");
608
          if ((txbd->ctrl & FCC_BD_Tx_RL) != 0) diag_printf("Retry limit/");
609
//          if ((txbd->ctrl & FCC_BD_Tx_RC) != 0) diag_printf("Late Collision/");
610
          if ((txbd->ctrl & FCC_BD_Tx_UN) != 0) diag_printf("Underrun/");
611
          if ((txbd->ctrl & FCC_BD_Tx_CSL) != 0) diag_printf("Carrier Lost/");
612
          diag_printf("\n");
613
#endif
614
      }
615
 
616
    txindex = ((unsigned long)txbd - (unsigned long)qi->tbase) / sizeof(*txbd);
617
    (sc->funs->eth_drv->tx_done)(sc, qi->txkey[txindex], 0);
618
    txbd->ctrl &= ~FCC_BD_Tx_TC;
619
    if (txbd->ctrl & FCC_BD_Tx_Wrap) {
620
      txbd = qi->tbase;
621
    } else {
622
      txbd++;
623
    }
624
  }
625
  // Remember where we left off
626
  qi->tnext = (struct fcc_bd *)txbd;
627
 
628
  // Make sure no stale data  
629
#ifndef FCC_BDs_NONCACHED
630
  if (cache_state) {
631
    HAL_DCACHE_FLUSH(fcc_eth_txring,
632
                     8*CYGNUM_DEVS_ETH_POWERPC_FCC_TxNUM);
633
  }
634
#endif
635
 
636
}
637
 
638
//
639
// Interrupt processing
640
//
641
static void
642
fcc_eth_int(struct eth_drv_sc *sc)
643
{
644
  struct fcc_eth_info *qi = (struct fcc_eth_info *)sc->driver_private;
645
  unsigned short iEvent;
646
 
647
  while ((iEvent = qi->fcc_reg->fcc_fcce) != 0){
648
    // Clear pending interrupts (writing 1's to this register)
649
    qi->fcc_reg->fcc_fcce = iEvent;
650
    // Tx Done or Tx Error
651
    if ( iEvent & (FCC_EV_TXB | FCC_EV_TXE) ) {
652
      fcc_eth_TxEvent(sc, iEvent);
653
    }
654
    // Complete or non-complete frame receive
655
    if (iEvent & (FCC_EV_RXF | FCC_EV_RXB) ) {
656
      fcc_eth_RxEvent(sc);
657
    }
658
  }
659
}
660
 
661
//
662
// Interrupt vector
663
//
664
static int
665
fcc_eth_int_vector(struct eth_drv_sc *sc)
666
{
667
    struct fcc_eth_info *qi = (struct fcc_eth_info *)sc->driver_private;
668
    return (qi->int_vector);
669
}
670
 

powered by: WebSVN 2.1.0

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