⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 if_fcc.c

📁 eCos操作系统源码
💻 C
📖 第 1 页 / 共 2 页
字号:
//==========================================================================////      dev/if_fcc.c////      Fast ethernet device driver for PowerPC MPC8xxx (QUICC-II) boards////==========================================================================//####ECOSGPLCOPYRIGHTBEGIN####// -------------------------------------------// This file is part of eCos, the Embedded Configurable Operating System.// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.// Copyright (C) 2002, 2003, 2004 Gary Thomas//// eCos is free software; you can redistribute it and/or modify it under// the terms of the GNU General Public License as published by the Free// Software Foundation; either version 2 or (at your option) any later version.//// eCos is distributed in the hope that it will be useful, but WITHOUT ANY// WARRANTY; without even the implied warranty of MERCHANTABILITY or// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License// for more details.//// You should have received a copy of the GNU General Public License along// with eCos; if not, write to the Free Software Foundation, Inc.,// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.//// As a special exception, if other files instantiate templates or use macros// or inline functions from this file, or you compile this file and link it// with other works to produce a work based on this file, this file does not// by itself cause the resulting work to be covered by the GNU General Public// License. However the source code for this file must still be made available// in accordance with section (3) of the GNU General Public License.//// This exception does not invalidate any other reasons why a work based on// this file might be covered by the GNU General Public License.//// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.// at http://sources.redhat.com/ecos/ecos-license/// -------------------------------------------//####ECOSGPLCOPYRIGHTEND####//==========================================================================//#####DESCRIPTIONBEGIN####//// Author(s):    gthomas// Contributors: mtek, pfine// Date:         2003-08-19// Purpose:      // Description:  hardware driver for MPC8xxx FCC//              ////####DESCRIPTIONEND####////==========================================================================#include <pkgconf/devs_eth_powerpc_fcc.h>#include <cyg/infra/cyg_type.h>#include <cyg/infra/diag.h>#include <cyg/hal/hal_arch.h>#include <cyg/hal/hal_cache.h>#include <cyg/hal/hal_intr.h>#include <cyg/hal/drv_api.h>#include <cyg/hal/hal_if.h>#include <cyg/hal/mpc8xxx.h>#include <cyg/io/eth/netdev.h>#include <cyg/io/eth/eth_drv.h>#ifdef CYGPKG_NET#include <pkgconf/net.h>#endif#ifdef CYGPKG_DEVS_ETH_PHY#include <cyg/io/eth_phy.h>#endif#include "fcc.h"#ifdef CYGPKG_REDBOOT#include <pkgconf/redboot.h>#ifdef CYGSEM_REDBOOT_FLASH_CONFIG#include <redboot.h>#include <flash_config.h>#endif#endif#ifdef CYGDAT_DEVS_FCC_ETH_INL#include CYGDAT_DEVS_FCC_ETH_CDL   // platform configury#include CYGDAT_DEVS_FCC_ETH_INL   // platform details#else#error "No board instance defined!"#endif#define ALIGN_TO_CACHE_LINES(x)  ( (long)((x) + 31) & 0xffffffe0 )// Buffer descriptors are in dual ported RAM, which is marked non-cached#define FCC_BDs_NONCACHED#define os_printf diag_printf// CONFIG_ESA and CONFIG_BOOL are defined in redboot/include/flash_config.h#ifndef CONFIG_ESA#define CONFIG_ESA 6      // ethernet address length ...#endif#ifndef CONFIG_BOOL#define CONFIG_BOOL 1#endifstatic void          fcc_eth_int(struct eth_drv_sc *data);// This ISR is called when the ethernet interrupt occurs#ifdef CYGPKG_NETstatic intfcc_eth_isr(cyg_vector_t vector, cyg_addrword_t data, HAL_SavedRegisters *regs){    struct eth_drv_sc *sc = (struct eth_drv_sc *)data;    struct fcc_eth_info *qi = (struct fcc_eth_info *)sc->driver_private;    cyg_drv_interrupt_mask(qi->int_vector);    return (CYG_ISR_HANDLED|CYG_ISR_CALL_DSR);  // Run the DSR}#endif// Deliver function (ex-DSR) handles the ethernet [logical] processingstatic voidfcc_eth_deliver(struct eth_drv_sc * sc){#ifdef CYGPKG_NET    struct fcc_eth_info *qi = (struct fcc_eth_info *)sc->driver_private;#endif    fcc_eth_int(sc);#ifdef CYGPKG_NET    //  Clearing the event register acknowledges FCC interrupt ...    cyg_drv_interrupt_unmask(qi->int_vector);#endif}// Initialize the interface - performed at system startup// This function must set up the interface, including arranging to// handle interrupts, etc, so that it may be "started" cheaply later.static bool fcc_eth_init(struct cyg_netdevtab_entry *dtp){    struct eth_drv_sc *sc = (struct eth_drv_sc *)dtp->device_instance;    struct fcc_eth_info *qi = (struct fcc_eth_info *)sc->driver_private;    volatile t_Fcc_Pram  *fcc =  (volatile t_Fcc_Pram *)0;    volatile t_EnetFcc_Pram *E_fcc;    int i, fcc_chan;    bool esa_ok;    unsigned char *c_ptr;    unsigned char _enaddr[6];    unsigned long rxbase, txbase;    struct fcc_bd *rxbd, *txbd;    // The FCC seems rather picky about these...    static long rxbd_base = 0x3000;    static long txbd_base = 0xB000;#ifdef CYGPKG_DEVS_ETH_PHY    unsigned short phy_state = 0;#endif    // Set up pointers to FCC controller    switch (qi->int_vector) {    case CYGNUM_HAL_INTERRUPT_FCC1:        qi->fcc_reg = &(IMM->fcc_regs[FCC1]);        fcc =  (volatile t_Fcc_Pram *)((unsigned long)IMM + FCC1_PRAM_OFFSET);        fcc_chan = FCC1_PAGE_SUBBLOCK;        break;    case CYGNUM_HAL_INTERRUPT_FCC2:        qi->fcc_reg = &(IMM->fcc_regs[FCC2]);        fcc =  (volatile t_Fcc_Pram *)((unsigned long)IMM + FCC2_PRAM_OFFSET);        fcc_chan = FCC2_PAGE_SUBBLOCK;        break;	case CYGNUM_HAL_INTERRUPT_FCC3:		qi->fcc_reg = &(IMM->fcc_regs[FCC3]);        fcc =  (volatile t_Fcc_Pram *)((unsigned long)IMM + FCC3_PRAM_OFFSET);        fcc_chan = FCC3_PAGE_SUBBLOCK;        break;    default:        os_printf("Can't initialize '%s' - unknown FCC!\n", dtp->name);        return false;    }    // just in case :  disable Transmit and Receive     qi->fcc_reg->fcc_gfmr &= ~(FCC_GFMR_EN_Rx | FCC_GFMR_EN_Tx);        // Try to read the ethernet address of the transciever ...#ifdef CYGPKG_REDBOOT    esa_ok = flash_get_config(qi->esa_key, _enaddr, CONFIG_ESA);#else    esa_ok = CYGACC_CALL_IF_FLASH_CFG_OP(CYGNUM_CALL_IF_FLASH_CFG_GET,                                          qi->esa_key, _enaddr, CONFIG_ESA);#endif    if (esa_ok) {        memcpy(qi->enaddr, _enaddr, sizeof(qi->enaddr));    } else {        // No 'flash config' data available - use default        os_printf("FCC_ETH - Warning! Using default ESA for '%s'\n", dtp->name);    }    // Initialize Receive Buffer Descriptors    rxbase = rxbd_base;    fcc->riptr = rxbase;           // temp work buffer    fcc->mrblr = FCC_PRAM_MRBLR;   // Max Rx buffer     fcc->rstate &= FCC_FCR_INIT;    fcc->rstate |= FCC_FCR_MOT_BO;    rxbase += 64;    rxbd_base += sizeof(struct fcc_bd)*qi->rxnum + 64;    rxbd = (struct fcc_bd *)(CYGARC_IMM_BASE + rxbase);    fcc->rbase = (CYG_WORD)rxbd;    c_ptr = qi->rxbuf;    qi->rbase = rxbd;    qi->rxbd  = rxbd;    qi->rnext = rxbd;    for (i = 0; i < qi->rxnum; i++, rxbd++) {        rxbd->ctrl   = (FCC_BD_Rx_Empty | FCC_BD_Rx_Int);        rxbd->length = 0;                   // reset         c_ptr = (unsigned char *) ALIGN_TO_CACHE_LINES(c_ptr);        rxbd->buffer = (volatile unsigned char *)c_ptr;        c_ptr += CYGNUM_DEVS_ETH_POWERPC_FCC_BUFSIZE;    }    rxbd--;    rxbd->ctrl |= FCC_BD_Rx_Wrap;    // Initialize Transmit Buffer Descriptors    txbase = txbd_base;    fcc->tiptr = txbase;   // in dual port RAM (see 28-11)    fcc->tstate &= FCC_FCR_INIT;    fcc->tstate |= FCC_FCR_MOT_BO;    txbase += 64;    txbd_base += sizeof(struct fcc_bd)*qi->txnum + 64;    txbd = (struct fcc_bd *)(CYGARC_IMM_BASE + txbase);    fcc->tbase = (CYG_WORD)txbd;    c_ptr = qi->txbuf;    qi->tbase = txbd;    qi->txbd  = txbd;    qi->tnext = txbd;    for (i = 0; i < qi->txnum; i++, txbd++) {        txbd->ctrl   = (FCC_BD_Tx_Pad | FCC_BD_Tx_Int);          txbd->length = 0;   // reset : Write before send        c_ptr = (unsigned char *) ALIGN_TO_CACHE_LINES(c_ptr);        txbd->buffer = (volatile unsigned char  *)c_ptr;        c_ptr += CYGNUM_DEVS_ETH_POWERPC_FCC_BUFSIZE;    }    txbd--;    txbd->ctrl |= FCC_BD_Tx_Wrap;        // Ethernet Specific FCC Parameter RAM Initialization         E_fcc = &(fcc->SpecificProtocol.e);    E_fcc->c_mask   = FCC_PRAM_C_MASK; // (see 30-9)    E_fcc->c_pres   = FCC_PRAM_C_PRES;    E_fcc->crcec    = 0;    E_fcc->alec     = 0;    E_fcc->disfc    = 0;    E_fcc->ret_lim  = FCC_PRAM_RETLIM;    E_fcc->p_per    = FCC_PRAM_PER_LO;    E_fcc->gaddr_h  = 0;    E_fcc->gaddr_l  = 0;    E_fcc->tfcstat  = 0;    E_fcc->mflr     = FCC_MAX_FLR;    E_fcc->paddr1_h = ((short)qi->enaddr[5] << 8) | qi->enaddr[4];    E_fcc->paddr1_m = ((short)qi->enaddr[3] << 8) | qi->enaddr[2];    E_fcc->paddr1_l = ((short)qi->enaddr[1] << 8) | qi->enaddr[0];    E_fcc->iaddr_h  = 0;    E_fcc->iaddr_l  = 0;    E_fcc->minflr   = FCC_MIN_FLR;    E_fcc->taddr_h  = 0;    E_fcc->taddr_m  = 0;    E_fcc->taddr_l  = 0;    E_fcc->pad_ptr  = fcc->tiptr; // No special padding char ...    E_fcc->cf_type  = 0;    E_fcc->maxd1    = FCC_PRAM_MAXD;    E_fcc->maxd2    = FCC_PRAM_MAXD;    // FCC register initialization     qi->fcc_reg->fcc_gfmr = FCC_GFMR_INIT;     qi->fcc_reg->fcc_psmr = FCC_PSMR_INIT;    qi->fcc_reg->fcc_dsr  = FCC_DSR_INIT;#ifdef CYGPKG_NET    // clear the events of FCCX    qi->fcc_reg->fcc_fcce = 0xFFFF;       qi->fcc_reg->fcc_fccm = FCC_EV_TXE | FCC_EV_TXB | FCC_EV_RXF;    // Set up to handle interrupts    cyg_drv_interrupt_create(qi->int_vector,                             0,  // Highest //CYGARC_SIU_PRIORITY_HIGH,                             (cyg_addrword_t)sc, //  Data passed to ISR                             (cyg_ISR_t *)fcc_eth_isr,                             (cyg_DSR_t *)eth_drv_dsr,                             &qi->fcc_eth_interrupt_handle,                             &qi->fcc_eth_interrupt);    cyg_drv_interrupt_attach(qi->fcc_eth_interrupt_handle);    cyg_drv_interrupt_acknowledge(qi->int_vector);    cyg_drv_interrupt_unmask(qi->int_vector);#else    // Mask the interrupts     qi->fcc_reg->fcc_fccm = 0;#endif    // Issue Init RX & TX Parameters Command for FCCx    while ((IMM->cpm_cpcr & CPCR_FLG) != CPCR_READY_TO_RX_CMD);     IMM->cpm_cpcr = CPCR_INIT_TX_RX_PARAMS |        fcc_chan |        CPCR_MCN_FCC |         CPCR_FLG;              /* ISSUE COMMAND */    while ((IMM->cpm_cpcr & CPCR_FLG) != CPCR_READY_TO_RX_CMD);     // Operating mode    if (!_eth_phy_init(qi->phy)) {        return false;    }#ifdef CYGSEM_DEVS_ETH_POWERPC_FCC_RESET_PHY    _eth_phy_reset(qi->phy);#endif    phy_state = _eth_phy_state(qi->phy);    os_printf("FCC %s: ", sc->dev_name);    if ((phy_state & ETH_PHY_STAT_LINK) != 0) {        if ((phy_state & ETH_PHY_STAT_100MB) != 0) {            // Link can handle 100Mb            os_printf("100Mb");            if ((phy_state & ETH_PHY_STAT_FDX) != 0) {                os_printf("/Full Duplex");            }         } else {            // Assume 10Mb, half duplex            os_printf("10Mb");        }    } else {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -