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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [devs/] [eth/] [powerpc/] [quicc/] [current/] [src/] [if_quicc.c] - Blame information for rev 810

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

Line No. Rev Author Line
1 786 skrzyp
//==========================================================================
2
//
3
//      dev/if_quicc.c
4
//
5
//      Ethernet device driver for PowerPC QUICC (MPC8xx) 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 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: gthomas, nickg
44
// Date:         2000-01-10
45
// Purpose:      
46
// Description:  hardware driver for MPC8xx QUICC
47
//              
48
//
49
//####DESCRIPTIONEND####
50
//
51
//==========================================================================
52
 
53
// Ethernet device driver for MPC8xx QUICC
54
 
55
#include <pkgconf/system.h>
56
#include <pkgconf/devs_eth_powerpc_quicc.h>
57
#include <pkgconf/io_eth_drivers.h>
58
 
59
#ifdef CYGPKG_NET
60
#include <pkgconf/net.h>
61
#endif
62
 
63
#include <cyg/infra/cyg_type.h>
64
#include <cyg/infra/diag.h>
65
 
66
#include <cyg/hal/hal_arch.h>
67
#include <cyg/hal/hal_cache.h>
68
#include <cyg/hal/hal_intr.h>
69
#include <cyg/hal/drv_api.h>
70
 
71
#include <cyg/io/eth/netdev.h>
72
#include <cyg/io/eth/eth_drv.h>
73
 
74
#include "quicc_eth.h"
75
 
76
static unsigned char quicc_eth_rxbufs[CYGNUM_DEVS_ETH_POWERPC_QUICC_RxNUM]
77
                                     [CYGNUM_DEVS_ETH_POWERPC_QUICC_BUFSIZE] __attribute__((aligned(HAL_DCACHE_LINE_SIZE)));
78
static unsigned char quicc_eth_txbufs[CYGNUM_DEVS_ETH_POWERPC_QUICC_TxNUM]
79
                                     [CYGNUM_DEVS_ETH_POWERPC_QUICC_BUFSIZE]  __attribute__((aligned(HAL_DCACHE_LINE_SIZE)));
80
 
81
static struct quicc_eth_info quicc_eth0_info;
82
static unsigned char _default_enaddr[] = { 0x08, 0x00, 0x3E, 0x28, 0x79, 0xB8};
83
static unsigned char enaddr[6];
84
#ifdef CYGPKG_REDBOOT
85
#include <pkgconf/redboot.h>
86
#ifdef CYGSEM_REDBOOT_FLASH_CONFIG
87
#include <redboot.h>
88
#include <flash_config.h>
89
RedBoot_config_option("Network hardware address [MAC]",
90
                      quicc_esa,
91
                      ALWAYS_ENABLED, true,
92
                      CONFIG_ESA, 0
93
    );
94
#endif
95
#endif
96
 
97
// For fetching the ESA from RedBoot
98
#include <cyg/hal/hal_if.h>
99
#ifndef CONFIG_ESA
100
#define CONFIG_ESA 6
101
#endif
102
 
103
ETH_DRV_SC(quicc_eth0_sc,
104
           &quicc_eth0_info,   // Driver specific data
105
           "eth0",             // Name for this interface
106
           quicc_eth_start,
107
           quicc_eth_stop,
108
           quicc_eth_control,
109
           quicc_eth_can_send,
110
           quicc_eth_send,
111
           quicc_eth_recv,
112
           quicc_eth_deliver,
113
           quicc_eth_int,
114
           quicc_eth_int_vector);
115
 
116
NETDEVTAB_ENTRY(quicc_netdev,
117
                "quicc_eth",
118
                quicc_eth_init,
119
                &quicc_eth0_sc);
120
 
121
// LED activity [exclusive of hardware bits]
122
#ifndef _get_led
123
#define _get_led()  
124
#define _set_led(v) 
125
#endif
126
#ifndef LED_TxACTIVE
127
#define LED_TxACTIVE  7
128
#define LED_RxACTIVE  6
129
#define LED_IntACTIVE 5
130
#endif
131
 
132
static void
133
set_led(int bit)
134
{
135
  _set_led(_get_led() | (1<<bit));
136
}
137
 
138
static void
139
clear_led(int bit)
140
{
141
  _set_led(_get_led() & ~(1<<bit));
142
}
143
 
144
#ifdef CYGINT_IO_ETH_INT_SUPPORT_REQUIRED
145
static cyg_interrupt quicc_eth_interrupt;
146
static cyg_handle_t  quicc_eth_interrupt_handle;
147
#endif
148
static void          quicc_eth_int(struct eth_drv_sc *data);
149
static void          quicc_eth_command(struct eth_drv_sc *sc, unsigned long cmd);
150
 
151
#ifdef CYGINT_IO_ETH_INT_SUPPORT_REQUIRED
152
// This ISR is called when the ethernet interrupt occurs
153
static int
154
quicc_eth_isr(cyg_vector_t vector, cyg_addrword_t data, HAL_SavedRegisters *regs)
155
{
156
    cyg_drv_interrupt_mask(QUICC_ETH_INT);
157
    cyg_drv_interrupt_acknowledge(QUICC_ETH_INT);
158
    return (CYG_ISR_HANDLED|CYG_ISR_CALL_DSR);  // Run the DSR
159
}
160
#endif
161
 
162
// Deliver function (ex-DSR) handles the ethernet [logical] processing
163
static void
164
quicc_eth_deliver(struct eth_drv_sc * sc)
165
{
166
    quicc_eth_int(sc);
167
#ifdef CYGINT_IO_ETH_INT_SUPPORT_REQUIRED
168
    // Allow interrupts to happen again
169
    cyg_drv_interrupt_unmask(QUICC_ETH_INT);
170
#endif
171
}
172
 
173
//
174
// Initialize the interface - performed at system startup
175
// This function must set up the interface, including arranging to
176
// handle interrupts, etc, so that it may be "started" cheaply later.
177
//
178
static bool
179
quicc_eth_init(struct cyg_netdevtab_entry *tab)
180
{
181
    struct eth_drv_sc *sc = (struct eth_drv_sc *)tab->device_instance;
182
    struct quicc_eth_info *qi = (struct quicc_eth_info *)sc->driver_private;
183
    volatile EPPC *eppc = (volatile EPPC *)eppc_base();
184
    struct cp_bufdesc *rxbd, *txbd;
185
    unsigned char *RxBUF, *TxBUF, *ep, *ap;
186
    volatile struct ethernet_pram *enet_pram;
187
    volatile struct scc_regs *scc;
188
    int TxBD, RxBD;
189
    int cache_state;
190
    int i;
191
    bool esa_ok = false;
192
 
193
#ifdef QUICC_ETH_FETCH_ESA
194
    QUICC_ETH_FETCH_ESA(esa_ok);
195
#endif
196
 
197
    if (!esa_ok) {
198
#if defined(CYGPKG_REDBOOT) && \
199
    defined(CYGSEM_REDBOOT_FLASH_CONFIG)
200
        esa_ok = flash_get_config("quicc_esa", enaddr, CONFIG_ESA);
201
#else
202
        esa_ok = CYGACC_CALL_IF_FLASH_CFG_OP(CYGNUM_CALL_IF_FLASH_CFG_GET,
203
                                             "quicc_esa", enaddr, CONFIG_ESA);
204
#endif
205
        if (!esa_ok) {
206
            // Can't figure out ESA
207
            diag_printf("QUICC_ETH - Warning! ESA unknown\n");
208
            memcpy(&enaddr, &_default_enaddr, sizeof(enaddr));
209
        }
210
    }
211
 
212
    // Ensure consistent state between cache and what the QUICC sees
213
    HAL_DCACHE_IS_ENABLED(cache_state);
214
    if (cache_state) {
215
        HAL_DCACHE_SYNC();
216
        HAL_DCACHE_DISABLE();
217
    }
218
 
219
#ifdef CYGINT_IO_ETH_INT_SUPPORT_REQUIRED
220
    // Set up to handle interrupts
221
    cyg_drv_interrupt_create(QUICC_ETH_INT,
222
                             CYGARC_SIU_PRIORITY_HIGH,
223
                             (cyg_addrword_t)sc, //  Data item passed to interrupt handler
224
                             (cyg_ISR_t *)quicc_eth_isr,
225
                             (cyg_DSR_t *)eth_drv_dsr,
226
                             &quicc_eth_interrupt_handle,
227
                             &quicc_eth_interrupt);
228
    cyg_drv_interrupt_attach(quicc_eth_interrupt_handle);
229
    cyg_drv_interrupt_acknowledge(QUICC_ETH_INT);
230
    cyg_drv_interrupt_unmask(QUICC_ETH_INT);
231
#endif
232
 
233
    qi->pram = enet_pram = &eppc->pram[QUICC_ETH_SCC].enet_scc;
234
    qi->ctl = scc = &eppc->scc_regs[QUICC_ETH_SCC];  // Use SCCx
235
 
236
    // Shut down ethernet, in case it is already running
237
    scc->scc_gsmr_l &= ~(QUICC_SCC_GSML_ENR | QUICC_SCC_GSML_ENT);
238
 
239
    memset((void *)enet_pram, 0, sizeof(*enet_pram));
240
 
241
    TxBD = _mpc8xx_allocBd(CYGNUM_DEVS_ETH_POWERPC_QUICC_TxNUM * sizeof(struct cp_bufdesc));
242
    RxBD = _mpc8xx_allocBd(CYGNUM_DEVS_ETH_POWERPC_QUICC_RxNUM * sizeof(struct cp_bufdesc));
243
 
244
    txbd = (struct cp_bufdesc *)((char *)eppc + TxBD);
245
    rxbd = (struct cp_bufdesc *)((char *)eppc + RxBD);
246
    qi->tbase = txbd;
247
    qi->txbd = txbd;
248
    qi->tnext = txbd;
249
    qi->rbase = rxbd;
250
    qi->rxbd = rxbd;
251
    qi->rnext = rxbd;
252
    qi->txactive = 0;
253
 
254
    RxBUF = &quicc_eth_rxbufs[0][0];
255
    TxBUF = &quicc_eth_txbufs[0][0];
256
 
257
    // setup buffer descriptors
258
    for (i = 0;  i < CYGNUM_DEVS_ETH_POWERPC_QUICC_RxNUM;  i++) {
259
        rxbd->length = 0;
260
        rxbd->buffer = RxBUF;
261
        rxbd->ctrl   = QUICC_BD_CTL_Ready | QUICC_BD_CTL_Int;
262
        RxBUF += CYGNUM_DEVS_ETH_POWERPC_QUICC_BUFSIZE;
263
        rxbd++;
264
    }
265
    rxbd--;
266
    rxbd->ctrl |= QUICC_BD_CTL_Wrap;  // Last buffer
267
    for (i = 0;  i < CYGNUM_DEVS_ETH_POWERPC_QUICC_TxNUM;  i++) {
268
        txbd->length = 0;
269
        txbd->buffer = TxBUF;
270
        txbd->ctrl   = 0;
271
        TxBUF += CYGNUM_DEVS_ETH_POWERPC_QUICC_BUFSIZE;
272
        txbd++;
273
    }
274
    txbd--;
275
    txbd->ctrl |= QUICC_BD_CTL_Wrap;  // Last buffer
276
 
277
    // Set up parallel ports for connection to ethernet tranceiver
278
    eppc->pio_papar |= (QUICC_ETH_PA_RXD | QUICC_ETH_PA_TXD);
279
    eppc->pio_padir &= ~(QUICC_ETH_PA_RXD | QUICC_ETH_PA_TXD);
280
    eppc->pio_paodr &= ~QUICC_ETH_PA_TXD;
281
 
282
    eppc->pio_pcpar &= ~(QUICC_ETH_PC_COLLISION | QUICC_ETH_PC_Rx_ENABLE);
283
    eppc->pio_pcdir &= ~(QUICC_ETH_PC_COLLISION | QUICC_ETH_PC_Rx_ENABLE);
284
    eppc->pio_pcso  |= (QUICC_ETH_PC_COLLISION | QUICC_ETH_PC_Rx_ENABLE);
285
 
286
    eppc->pio_papar |= (QUICC_ETH_PA_Tx_CLOCK | QUICC_ETH_PA_Rx_CLOCK);
287
    eppc->pio_padir &= ~(QUICC_ETH_PA_Tx_CLOCK | QUICC_ETH_PA_Rx_CLOCK);
288
 
289
    // Set up clock routing
290
    eppc->si_sicr &= ~QUICC_ETH_SICR_MASK;
291
    eppc->si_sicr |= QUICC_ETH_SICR_ENET;
292
    eppc->si_sicr &= ~QUICC_ETH_SICR_ENABLE;
293
 
294
    // Set up DMA mode
295
    eppc->dma_sdcr = 0x0001;
296
 
297
    // Initialize shared PRAM
298
    enet_pram->rbase = RxBD;
299
    enet_pram->tbase = TxBD;
300
 
301
    // Set Big Endian mode
302
    enet_pram->rfcr = QUICC_SCC_FCR_BE;
303
    enet_pram->tfcr = QUICC_SCC_FCR_BE;
304
 
305
    // Size of receive buffers
306
    enet_pram->mrblr = CYGNUM_DEVS_ETH_POWERPC_QUICC_BUFSIZE;
307
 
308
    // Initialize CRC calculations
309
    enet_pram->c_pres = 0xFFFFFFFF;
310
    enet_pram->c_mask = 0xDEBB20E3;  // Actual CRC formula
311
    enet_pram->crcec = 0;
312
    enet_pram->alec = 0;
313
    enet_pram->disfc = 0;
314
 
315
    // Frame padding
316
    enet_pram->pads = 0x8888;
317
    enet_pram->pads = 0x0000;
318
 
319
    // Retries
320
    enet_pram->ret_lim = 15;
321
    enet_pram->ret_cnt = 0;
322
 
323
    // Frame sizes
324
    enet_pram->mflr = IEEE_8023_MAX_FRAME;
325
    enet_pram->minflr = IEEE_8023_MIN_FRAME;
326
    enet_pram->maxd1 = CYGNUM_DEVS_ETH_POWERPC_QUICC_BUFSIZE;
327
    enet_pram->maxd2 = CYGNUM_DEVS_ETH_POWERPC_QUICC_BUFSIZE;
328
 
329
    // Group address hash
330
    enet_pram->gaddr1 = 0;
331
    enet_pram->gaddr2 = 0;
332
    enet_pram->gaddr3 = 0;
333
    enet_pram->gaddr4 = 0;
334
 
335
    // Device physical address
336
    ep = &enaddr[sizeof(enaddr)];
337
    ap = (unsigned char *)&enet_pram->paddr_h;
338
    for (i = 0;  i < sizeof(enaddr);  i++) {
339
        *ap++ = *--ep;
340
    }
341
 
342
    // Persistence counter
343
    enet_pram->p_per = 0;
344
 
345
    // Individual address filter
346
    enet_pram->iaddr1 = 0;
347
    enet_pram->iaddr2 = 0;
348
    enet_pram->iaddr3 = 0;
349
    enet_pram->iaddr4 = 0;
350
 
351
    // Temp address
352
    enet_pram->taddr_h = 0;
353
    enet_pram->taddr_m = 0;
354
    enet_pram->taddr_l = 0;
355
 
356
    // Initialize the CPM (set up buffer pointers, etc).
357
    quicc_eth_command(sc, QUICC_CPM_CR_INIT_TXRX);
358
 
359
    // Clear any pending interrupt/exceptions
360
    scc->scc_scce = 0xFFFF;
361
 
362
    // Enable interrupts
363
    scc->scc_sccm = QUICC_SCCE_INTS | QUICC_SCCE_GRC | QUICC_SCCE_BSY;
364
 
365
    // Set up SCCx to run in ethernet mode
366
    scc->scc_gsmr_h = 0;
367
    scc->scc_gsmr_l = QUICC_SCC_GSML_TCI | QUICC_SCC_GSML_TPL_48 |
368
        QUICC_SCC_GSML_TPP_01 | QUICC_SCC_GSML_MODE_ENET;
369
 
370
    // Sync delimiters
371
    scc->scc_dsr = 0xD555;
372
 
373
    // Protocol specifics (as if GSML wasn't enough)
374
    scc->scc_psmr = QUICC_PMSR_ENET_CRC | QUICC_PMSR_SEARCH_AFTER_22 |
375
        QUICC_PMSR_RCV_SHORT_FRAMES;
376
 
377
#ifdef QUICC_ETH_ENABLE
378
    QUICC_ETH_ENABLE();
379
#endif
380
 
381
#ifdef QUICC_ETH_RESET_PHY
382
    QUICC_ETH_RESET_PHY();
383
#endif
384
 
385
    // Enable ethernet interface
386
#ifdef QUICC_ETH_PC_Tx_ENABLE
387
    eppc->pio_pcpar |= QUICC_ETH_PC_Tx_ENABLE;
388
    eppc->pio_pcdir &= ~QUICC_ETH_PC_Tx_ENABLE;
389
#else
390
    eppc->pip_pbpar |= QUICC_ETH_PB_Tx_ENABLE;
391
    eppc->pip_pbdir |= QUICC_ETH_PB_Tx_ENABLE;
392
#endif
393
 
394
    if (cache_state)
395
        HAL_DCACHE_ENABLE();
396
 
397
    // Initialize upper level driver
398
    (sc->funs->eth_drv->init)(sc, (unsigned char *)&enaddr);
399
 
400
    // Set LED state
401
    clear_led(LED_TxACTIVE);
402
    clear_led(LED_RxACTIVE);
403
 
404
    return true;
405
}
406
 
407
//
408
// This function is called to shut down the interface.
409
//
410
static void
411
quicc_eth_stop(struct eth_drv_sc *sc)
412
{
413
    struct quicc_eth_info *qi = (struct quicc_eth_info *)sc->driver_private;
414
    volatile struct scc_regs *scc = qi->ctl;
415
 
416
    // Disable the device!
417
    scc->scc_gsmr_l &= ~(QUICC_SCC_GSML_ENR | QUICC_SCC_GSML_ENT);
418
}
419
 
420
//
421
// This function is called to "start up" the interface.  It may be called
422
// multiple times, even when the hardware is already running.  It will be
423
// called whenever something "hardware oriented" changes and should leave
424
// the hardware ready to send/receive packets.
425
//
426
static void
427
quicc_eth_start(struct eth_drv_sc *sc, unsigned char *enaddr, int flags)
428
{
429
    struct quicc_eth_info *qi = (struct quicc_eth_info *)sc->driver_private;
430
    volatile struct scc_regs *scc = qi->ctl;
431
 
432
    // Enable the device!
433
    scc->scc_gsmr_l |= QUICC_SCC_GSML_ENR | QUICC_SCC_GSML_ENT;
434
}
435
 
436
//
437
// This function is called for low level "control" operations
438
//
439
static int
440
quicc_eth_control(struct eth_drv_sc *sc, unsigned long key,
441
                  void *data, int length)
442
{
443
    switch (key) {
444
    case ETH_DRV_SET_MAC_ADDRESS:
445
        return 0;
446
        break;
447
 
448
#ifdef ETH_DRV_GET_IF_STATS
449
    case ETH_DRV_GET_IF_STATS:
450
    {
451
        struct ether_drv_stats *p = (struct ether_drv_stats *)data;
452
        struct quicc_eth_info *qi = (struct quicc_eth_info *)sc->driver_private;
453
 
454
        strcpy( p->description, "QUICC (MPC8xx) SCC Ethernet" );
455
        CYG_ASSERT( 48 > strlen(p->description), "Description too long" );
456
 
457
        // Really need to determine the following values properly, for
458
        // now just assume the link is up, full duplex, unknown speed.
459
 
460
        p->operational = 3;            // LINK UP
461
        p->duplex = 1;
462
        p->speed = 0;
463
 
464
        {
465
            p->supports_dot3        = false;
466
 
467
            // Those commented out are not available on this chip.
468
 
469
            p->tx_good              = qi->tx_good             ;
470
            //p->tx_max_collisions    = qi->tx_max_collisions ;
471
            p->tx_late_collisions   = qi->tx_late_collisions  ;
472
            p->tx_underrun          = qi->tx_underrun         ;
473
            p->tx_carrier_loss      = qi->tx_carrier_loss     ;
474
            p->tx_deferred          = qi->tx_deferred         ;
475
            //p->tx_sqetesterrors   = qi->tx_sqetesterrors    ;
476
            //p->tx_single_collisions = qi->tx_single_collisions;
477
            //p->tx_mult_collisions   = qi->tx_mult_collisions  ;
478
            //p->tx_total_collisions  = qi->tx_total_collisions ;
479
            p->rx_good              = qi->rx_good             ;
480
            p->rx_crc_errors        = qi->rx_crc_errors       ;
481
            p->rx_align_errors      = qi->rx_align_errors     ;
482
            p->rx_resource_errors   = qi->rx_resource_errors  ;
483
            p->rx_overrun_errors    = qi->rx_overrun_errors   ;
484
            p->rx_collisions        = qi->rx_collisions       ;
485
            p->rx_short_frames      = qi->rx_short_frames     ;
486
            p->rx_too_long_frames   = qi->rx_long_frames      ;
487
            //p->rx_symbol_errors   = qi->rx_symbol_errors    ;
488
 
489
            p->interrupts           = qi->interrupts          ;
490
            p->rx_count             = qi->rx_count            ;
491
            p->rx_deliver           = qi->rx_deliver          ;
492
            p->rx_resource          = qi->rx_resource         ;
493
            p->rx_restart           = qi->rx_restart          ;
494
            p->tx_count             = qi->tx_count            ;
495
            p->tx_complete          = qi->tx_complete         ;
496
            p->tx_dropped           = qi->tx_dropped          ;
497
        }
498
 
499
        p->tx_queue_len = CYGNUM_DEVS_ETH_POWERPC_QUICC_TxNUM;
500
 
501
        return 0; // OK
502
    }
503
#endif
504
 
505
 
506
    default:
507
        return 1;
508
        break;
509
    }
510
}
511
 
512
//
513
// This function is called to see if another packet can be sent.
514
// It should return the number of packets which can be handled.
515
// Zero should be returned if the interface is busy and can not send any more.
516
//
517
static int
518
quicc_eth_can_send(struct eth_drv_sc *sc)
519
{
520
    struct quicc_eth_info *qi = (struct quicc_eth_info *)sc->driver_private;
521
 
522
    return (qi->txactive < CYGNUM_DEVS_ETH_POWERPC_QUICC_TxNUM);
523
}
524
 
525
//
526
// This routine is called to send data to the hardware.
527
static void
528
quicc_eth_send(struct eth_drv_sc *sc, struct eth_drv_sg *sg_list, int sg_len,
529
               int total_len, unsigned long key)
530
{
531
    struct quicc_eth_info *qi = (struct quicc_eth_info *)sc->driver_private;
532
    volatile struct cp_bufdesc *txbd, *txfirst;
533
    volatile char *bp;
534
    int i, txindex, cache_state;
535
    unsigned int ctrl;
536
 
537
    qi->tx_count++;
538
 
539
    // Find a free buffer
540
    txbd = txfirst = qi->txbd;
541
    if ((txbd->ctrl & (QUICC_BD_CTL_Ready | QUICC_BD_CTL_Int )))
542
#ifdef CYGPKG_NET
543
            panic ("No free xmit buffers");
544
#else
545
            diag_printf("QUICC Ethernet: No free xmit buffers\n");
546
#endif
547
 
548
    // Remember the next buffer to try
549
    if (txbd->ctrl & QUICC_BD_CTL_Wrap) {
550
        qi->txbd = qi->tbase;
551
    } else {
552
        qi->txbd = txbd+1;
553
    }
554
    txindex = ((unsigned long)txbd - (unsigned long)qi->tbase) / sizeof(*txbd);
555
    qi->txkey[txindex] = key;
556
    // Set up buffer
557
    txbd->length = total_len;
558
    bp = txbd->buffer;
559
    for (i = 0;  i < sg_len;  i++) {
560
        memcpy((void *)bp, (void *)sg_list[i].buf, sg_list[i].len);
561
        bp += sg_list[i].len;
562
    }
563
    // Note: the MPC8xx does not seem to snoop/invalidate the data cache properly!
564
    HAL_DCACHE_IS_ENABLED(cache_state);
565
    if (cache_state) {
566
        HAL_DCACHE_FLUSH(txbd->buffer, txbd->length);  // Make sure no stale data
567
    }
568
    // Send it on it's way
569
    ctrl = txbd->ctrl & ~QUICC_BD_TX_PAD;
570
    if (txbd->length < IEEE_8023_MIN_FRAME) {
571
        ctrl |= QUICC_BD_TX_PAD;
572
    }
573
    txbd->ctrl = ctrl | QUICC_BD_CTL_Ready | QUICC_BD_CTL_Int |
574
        QUICC_BD_TX_LAST | QUICC_BD_TX_TC;
575
    qi->txactive++;
576
    set_led(LED_TxACTIVE);
577
}
578
 
579
//
580
// This function is called when a packet has been received.  It's job is
581
// to prepare to unload the packet from the hardware.  Once the length of
582
// the packet is known, the upper layer of the driver can be told.  When
583
// the upper layer is ready to unload the packet, the internal function
584
// 'quicc_eth_recv' will be called to actually fetch it from the hardware.
585
//
586
static void
587
quicc_eth_RxEvent(struct eth_drv_sc *sc)
588
{
589
    struct quicc_eth_info *qi = (struct quicc_eth_info *)sc->driver_private;
590
    volatile struct cp_bufdesc *rxbd;
591
 
592
 
593
    rxbd = qi->rnext;
594
    while ((rxbd->ctrl & (QUICC_BD_CTL_Ready | QUICC_BD_CTL_Int)) == QUICC_BD_CTL_Int) {
595
 
596
        qi->rx_count++;
597
 
598
        if( rxbd->ctrl & QUICC_BD_RX_MISS )
599
        {
600
            qi->rx_miss++;
601
        }
602
        if( rxbd->ctrl & QUICC_BD_RX_LG )
603
        {
604
            qi->rx_long_frames++;
605
        }
606
        if( rxbd->ctrl & QUICC_BD_RX_NO )
607
        {
608
            qi->rx_align_errors++;
609
        }
610
        if( rxbd->ctrl & QUICC_BD_RX_SH )
611
        {
612
            qi->rx_short_frames++;
613
        }
614
        if( rxbd->ctrl & QUICC_BD_RX_CR )
615
        {
616
            qi->rx_crc_errors++;
617
        }
618
        if( rxbd->ctrl & QUICC_BD_RX_OV )
619
        {
620
            qi->rx_overrun_errors++;
621
        }
622
 
623
        if( rxbd->ctrl & QUICC_BD_RX_CL )
624
        {
625
            qi->rx_collisions++;
626
        }
627
 
628
        if( (rxbd->ctrl & QUICC_BD_RX_ERRORS) == 0 )
629
        {
630
            qi->rx_good++;
631
 
632
            // OK frame - Prepare for callback
633
            qi->rxbd = rxbd;  // Save for callback
634
            set_led(LED_RxACTIVE);
635
            // Remove the CRC from the end
636
            (sc->funs->eth_drv->recv)(sc, rxbd->length - 4);
637
 
638
            clear_led(LED_RxACTIVE);
639
        }
640
 
641
 
642
        // Clear flags and wrap if needed else step up BD pointer 
643
        if (rxbd->ctrl & QUICC_BD_CTL_Wrap)
644
        {
645
            rxbd->ctrl = QUICC_BD_CTL_Ready | QUICC_BD_CTL_Int | QUICC_BD_CTL_Wrap;
646
            rxbd = qi->rbase;
647
        }
648
        else
649
        {
650
            rxbd->ctrl = QUICC_BD_CTL_Ready | QUICC_BD_CTL_Int;
651
            rxbd++;
652
        }
653
 
654
    }
655
    // Remember where we left off
656
    qi->rnext = (struct cp_bufdesc *)rxbd;
657
}
658
 
659
//
660
// This function is called as a result of the "eth_drv_recv()" call above.
661
// It's job is to actually fetch data for a packet from the hardware once
662
// memory buffers have been allocated for the packet.  Note that the buffers
663
// may come in pieces, using a scatter-gather list.  This allows for more
664
// efficient processing in the upper layers of the stack.
665
//
666
static void
667
quicc_eth_recv(struct eth_drv_sc *sc, struct eth_drv_sg *sg_list, int sg_len)
668
{
669
    struct quicc_eth_info *qi = (struct quicc_eth_info *)sc->driver_private;
670
    unsigned char *bp;
671
    int i, cache_state;
672
    int sg_list_null_buffer = 0;
673
 
674
    bp = (unsigned char *)qi->rxbd->buffer;
675
    // Note: the MPC8xx does not seem to snoop/invalidate the data cache properly!
676
    HAL_DCACHE_IS_ENABLED(cache_state);
677
    if (cache_state) {
678
        HAL_DCACHE_INVALIDATE(qi->rxbd->buffer, qi->rxbd->length);  // Make sure no stale data
679
    }
680
    for (i = 0;  i < sg_len;  i++) {
681
        if (sg_list[i].buf != 0) {
682
            memcpy((void *)sg_list[i].buf, bp, sg_list[i].len);
683
            bp += sg_list[i].len;
684
        }
685
        else
686
            sg_list_null_buffer = 1;
687
    }
688
 
689
    // A NULL sg_list buffer usually means no mbufs, so we don't count
690
    // it as a delivery, instead we count it as a resource error.
691
 
692
    if (!sg_list_null_buffer)
693
        qi->rx_deliver++;
694
    else
695
        qi->rx_resource++;
696
 
697
}
698
 
699
static void
700
quicc_eth_command( struct eth_drv_sc *sc, unsigned long cmd)
701
{
702
   volatile EPPC *eppc = (volatile EPPC *)eppc_base();
703
 
704
   eppc->cp_cr = QUICC_CPM_SCCx | cmd | QUICC_CPM_CR_BUSY;
705
   while (eppc->cp_cr & QUICC_CPM_CR_BUSY )
706
       continue;
707
}
708
 
709
static void
710
quicc_eth_TxEvent(struct eth_drv_sc *sc, int stat)
711
{
712
    struct quicc_eth_info *qi = (struct quicc_eth_info *)sc->driver_private;
713
    volatile struct cp_bufdesc *txbd;
714
    int txindex;
715
    bool restart = false;
716
 
717
    txbd = qi->tnext;
718
 
719
    while ((txbd->ctrl & (QUICC_BD_CTL_Ready | QUICC_BD_CTL_Int)) == QUICC_BD_CTL_Int) {
720
 
721
        txindex = ((unsigned long)txbd - (unsigned long)qi->tbase) / sizeof(*txbd);
722
 
723
        qi->tx_complete++;
724
 
725
        (sc->funs->eth_drv->tx_done)(sc, qi->txkey[txindex], 0);
726
        txbd->ctrl &= ~QUICC_BD_CTL_Int;  // Reset int pending bit
727
 
728
        if (txbd->ctrl & QUICC_BD_TX_LC )
729
            qi->tx_late_collisions++, restart = true;
730
        if (txbd->ctrl & QUICC_BD_TX_RL )
731
            qi->tx_retransmit_error++, restart = true;
732
        if (txbd->ctrl & QUICC_BD_TX_UN )
733
            qi->tx_underrun++, restart = true;
734
        if (txbd->ctrl & QUICC_BD_TX_CSL )
735
            qi->tx_carrier_loss++;
736
        if (txbd->ctrl & QUICC_BD_TX_HB )
737
            qi->tx_heartbeat_loss++;
738
        if (txbd->ctrl & QUICC_BD_TX_DEF )
739
            qi->tx_deferred++;
740
 
741
        if( (txbd->ctrl & QUICC_BD_TX_ERRORS) == 0 )
742
            qi->tx_good++;
743
 
744
 
745
        if (txbd->ctrl & QUICC_BD_CTL_Wrap) {
746
            txbd->ctrl = QUICC_BD_CTL_Wrap;
747
            txbd = qi->tbase;
748
        } else {
749
            txbd->ctrl = 0;
750
            txbd++;
751
        }
752
        qi->txactive--;
753
    }
754
 
755
    if (qi->txactive == 0) {
756
        clear_led(LED_TxACTIVE);
757
    }
758
 
759
    // Remember where we left off
760
    qi->tnext = (struct cp_bufdesc *)txbd;
761
 
762
    if (restart)
763
    {
764
        quicc_eth_command(sc,QUICC_CPM_CR_RESTART_TX);
765
        qi->tx_restart++;
766
    }
767
 
768
}
769
 
770
//
771
// Interrupt processing
772
//
773
static void
774
quicc_eth_int(struct eth_drv_sc *sc)
775
{
776
    struct quicc_eth_info *qi = (struct quicc_eth_info *)sc->driver_private;
777
    volatile struct scc_regs *scc = qi->ctl;
778
    unsigned short scce;
779
 
780
    qi->interrupts++;
781
 
782
    while ( (scce = scc->scc_scce) != 0 )
783
    {
784
        scc->scc_scce = scce;
785
 
786
        if ( (scce & (QUICC_SCCE_TXE | QUICC_SCCE_TX)) != 0)
787
        {
788
            quicc_eth_TxEvent(sc, scce);
789
        }
790
        if ( (scce & ( QUICC_SCCE_RXF | QUICC_SCCE_RX )) != 0)
791
        {
792
            quicc_eth_RxEvent(sc);
793
        }
794
        if ( (scce & QUICC_SCCE_BSY) != 0)
795
        {
796
            qi->rx_resource_errors++;
797
        }
798
        if ( (scce & QUICC_SCCE_GRC) != 0 )
799
        {
800
            quicc_eth_command(sc, QUICC_CPM_CR_RESTART_TX);
801
            qi->tx_restart++;
802
            quicc_eth_command(sc, QUICC_CPM_CR_HUNT_MODE);
803
            qi->rx_restart++;
804
        }
805
    }
806
}
807
 
808
//
809
// Interrupt vector
810
//
811
static int
812
quicc_eth_int_vector(struct eth_drv_sc *sc)
813
{
814
    return (QUICC_ETH_INT);
815
}

powered by: WebSVN 2.1.0

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