if_mcf5272.c
来自「eCos操作系统源码」· C语言 代码 · 共 1,887 行 · 第 1/5 页
C
1,887 行
//==========================================================================//// dev/if_MCF5272_fec.c//// Ethernet device driver for MCF5272's Fast Ethernet Controller (FEC)////==========================================================================//####ECOSGPLCOPYRIGHTBEGIN####// -------------------------------------------// This file is part of eCos, the Embedded Configurable Operating System.// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.//// 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####//==========================================================================// Ethernet device driver for Fast Ethernet MCF5272_fec#include <pkgconf/io_eth_drivers.h>#include <cyg/hal/drv_api.h>#include <cyg/io/eth/netdev.h>#include <cyg/io/eth/eth_drv.h>#include <cyg/devs/eth/nbuf.h>#include <cyg/devs/eth/if_mcf5272.h>#include <cyg/devs/eth/if_mcf5272_private_data.h>#include <cyg/infra/cyg_ass.h>#include <sys/param.h>#include <net/if.h>/* Function to retrieve the Ethernet address of the device from the device's database. We declare it weak so that other routines can overide it. */externC const void*db_get_eth_address(void) __attribute__ ((weak));/***************************************************************************** The following functions provide an interface directly to theethernet driver for applications that wish to circumvent the IP stack. Applications that wish to take advantage of this should overridethese routine with their own. Leaving these routines as default routesall data through the IP stack.*****************************************************************************/externC int_teth_rx_pkt_filter(u8_t* pkt, uint_t pkt_len) __attribute__ ((weak));externC voideth_tx_check(struct eth_drv_sg * sg_list, unsigned int sg_len) __attribute__ ((weak));externC voideth_send_done(unsigned long tag) __attribute__ ((weak));externC int_teth_send(struct eth_drv_sg * sg_list, unsigned int sg_len, int total_len, unsigned long tag);static MCF5272_fec_priv_data_t MCF5272_fec_priv_data;/* Interrupt strcture and handles. */static cyg_interrupt MCF5272_fec_rx_interrupt;static cyg_interrupt MCF5272_fec_tx_interrupt;static cyg_handle_t MCF5272_fec_rx_interrupt_handle;static cyg_handle_t MCF5272_fec_tx_interrupt_handle;// Interrupt handlerstatic void MCF5272_fec_int(struct eth_drv_sc *sc);static int MCF5272_fec_int_vector(struct eth_drv_sc *sc);// This DSR handles the ethernet [logical] processingstatic void MCF5272_fec_deliver(struct eth_drv_sc * sc);static void MCF5272_fec_stop(struct eth_drv_sc *sc);static voidMCF5272_fec_send(struct eth_drv_sc *sc, struct eth_drv_sg *sg_list, int sg_len, int total_len, unsigned long key);static voidMCF5272_fec_common_send(struct eth_drv_sc *sc, struct eth_drv_sg *sg_list, int sg_len, int total_len, unsigned long key, tx_key_type_t key_type);static intMCF5272_fec_isr(cyg_vector_t vector, cyg_addrword_t data, HAL_SavedRegisters *regs);// One-second call back alarmstatic void one_second_alarm_func(cyg_handle_t alarm, cyg_addrword_t data);// Retrieve statisticsstatic void MCF5272_get_stats(struct eth_drv_sc *sc, MCF5272_FEC_DIAG* stats);ETH_DRV_SC(MCF5272_fec_sc, &MCF5272_fec_priv_data, // Driver specific data "eth0", // Name for this interface MCF5272_fec_start, MCF5272_fec_stop, MCF5272_fec_control, MCF5272_fec_can_send, MCF5272_fec_send, MCF5272_fec_recv, MCF5272_fec_deliver, MCF5272_fec_int, MCF5272_fec_int_vector);/* Device name */static const char ether_device_name[] = "MCF5272-eth";NETDEVTAB_ENTRY(MCF5272_fec_netdev, ether_device_name, MCF5272_fec_init, &MCF5272_fec_sc);/******************************************************************************* db_get_eth_address() - Returns the default Ethernet address.*/const void* db_get_eth_address(void){ /* Just use an obviously invalid address until someone overrides this */ /* routine to provide their own address. */ static const unsigned char enaddr[] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 }; return (const void*)enaddr;}/******************************************************************************* MCF5272_fec_init() - Routine that initializes the FEC. INPUT: tab - Pointer to the network device table. */static bool MCF5272_fec_init(struct cyg_netdevtab_entry *tab){ struct eth_drv_sc *sc = (struct eth_drv_sc *)tab->device_instance; const u8_t *enaddr; /* Indicate that the ethernet driver is down. */ PMCF5272_FEC_DATA(sc)->operational = ETH_DEV_DOWN; /* Initialize the entire driver private area to zero. */ memset((char*)sc->driver_private, sizeof(MCF5272_fec_priv_data_t), 0); /* Initialize the buffers structure. This strucre contains transmit */ /* and receive buffer descriptor managment information. */ nbuf_init(PBUF_INFO(sc)); /* Start a alarm that will trigger every second. This alarm will */ /* periodically update the recevie and transmit statistics. */ cyg_clock_to_counter(cyg_real_time_clock(), &(((MCF5272_fec_priv_data_t*)sc->driver_private)->counter_h)); cyg_alarm_create(((MCF5272_fec_priv_data_t*)sc->driver_private)->counter_h, one_second_alarm_func, (cyg_addrword_t)(MCF5272_fec_priv_data_t*)sc->driver_private, &(((MCF5272_fec_priv_data_t*)sc->driver_private)->alarm_h), &(((MCF5272_fec_priv_data_t*)sc->driver_private)->alarm)); cyg_alarm_initialize(((MCF5272_fec_priv_data_t*)sc->driver_private)->alarm_h, cyg_current_time()+ (1*SEC_IN_NS)/CYGNUM_KERNEL_COUNTERS_RTC_PERIOD, (1*SEC_IN_NS)/CYGNUM_KERNEL_COUNTERS_RTC_PERIOD); /* Initialize environment, setup receive, transmit and non-critical */ /* interrupt handlers. */ cyg_drv_interrupt_create(CYGNUM_HAL_VECTOR_ERX, MCF5272_INT_LEVEL, // Priority (cyg_addrword_t)sc, // Data item passed to interrupt handler (cyg_ISR_t *)MCF5272_fec_isr, (cyg_DSR_t *)eth_drv_dsr, &MCF5272_fec_rx_interrupt_handle, &MCF5272_fec_rx_interrupt); cyg_drv_interrupt_create(CYGNUM_HAL_VECTOR_ETX, MCF5272_INT_LEVEL, // Priority (cyg_addrword_t)sc, // Data item passed to interrupt handler (cyg_ISR_t *)MCF5272_fec_isr, (cyg_DSR_t *)eth_drv_dsr, &MCF5272_fec_tx_interrupt_handle, &MCF5272_fec_tx_interrupt); /* Attach interrupt here in order to start receiving interrupt from */ /* the FEC. */ cyg_drv_interrupt_attach(MCF5272_fec_rx_interrupt_handle); cyg_drv_interrupt_attach(MCF5272_fec_tx_interrupt_handle); put_reg(MCF5272_SIM->gpio.pbcnt, 0x55550000 | (get_reg(MCF5272_SIM->gpio.pbcnt) & 0x0000FFFF)); /* Reset the FEC - equivalent to a hard reset. */ put_reg(MCF5272_SIM->enet.ecr, MCF5272_FEC_ECR_RESET); /* Wait for the reset sequence to complete. */ while(get_reg(MCF5272_SIM->enet.ecr) & MCF5272_FEC_ECR_RESET); /* Set the Ethernet control register to zero to disable the FEC. */ put_reg(MCF5272_SIM->enet.ecr, 0); /* Set the source address for the controller. */ /* Initialize physical address register by copying our adapter */ /* address from the device's permanent storage. */ enaddr = (cyg_uint8*)db_get_eth_address(); put_reg(MCF5272_SIM->enet.malr,0 | (enaddr[0] <<24) | (enaddr[1] <<16) | (enaddr[2] <<8) | (enaddr[3] <<0)); put_reg(MCF5272_SIM->enet.maur,0 | (enaddr[4] <<24) | (enaddr[5] <<16)); /* Initialize the hash table registers to ignore hash checking to */ /* detect multicast Etherhet addresses. */ put_reg(MCF5272_SIM->enet.htur, 0); put_reg(MCF5272_SIM->enet.htlr, 0); /* Set Receive Buffer Size. This is the size for each receive */ /* buffer. */ put_reg(MCF5272_SIM->enet.emrbr, (uint16)RX_BUFFER_SIZE); /* Point to the start of the circular Rx buffer descriptor queue. */ put_reg(MCF5272_SIM->enet.erdsr, nbuf_get_start(PBUF_INFO(sc), Rx)); /* Point to the start of the circular Tx buffer descriptor queue. */ put_reg(MCF5272_SIM->enet.etdsr, nbuf_get_start(PBUF_INFO(sc), Tx)); /* Set the FIFO transmit highwater mark to 128 bytes. Frame */ /* transmission begins when the number of bytes selected by this field */ /* are written into the transmit FIFO, if an end of frame has been */ /* written to the FIFIO, or if the FIFO is full before selected number */ /* of bytes are written. */ put_reg(MCF5272_SIM->enet.tfwr, MCF5272_FEC_XWMRK_128); /* Clear any interrupts by setting all bits in the EIR register. */ put_reg(MCF5272_SIM->enet.eir, 0xFFFFFFFF); /* Set the tranceiver interface to MII mode. */ put_reg(MCF5272_SIM->enet.rcr, 0 | MCF5272_FEC_RCR_MII_MODE); // | MCF5272_FEC_RCR_DRT); /* Set the mode is ETH_MODE_SIMPLEX. We are assuming the device is */ /* half-duplex mode. */ PMCF5272_FEC_DATA(sc)->duplex = ETH_MODE_SIMPLEX; /* The default speed is 10 Mbs. */ PMCF5272_FEC_DATA(sc)->speed = ETH_SPEED_10MB; /* Write the maximum frame length and setup so we can receive */ /* broadcast packets. */ put_reg(MCF5272_SIM->enet.mflr, MCF5272_FEC_MFLR_BRDCAST | sizeof(eth_frame_hdr)); /* Check for heartbeat count and enable full-duplex transmit. The */ /* hearbeat check is performed following end of transmission and the HB */ /* bit in the status reguster is set if the collision input does not */ /* assert within the heartbeat window. */ /* NOTE: We disable full duplex mode because we notice that we're */ /* getting Receive CRC erors. */ put_reg(MCF5272_SIM->enet.tcr, 0 |MCF5272_FEC_TCR_HBC); //| MCF5272_FEC_TCR_FDEN); /* Set the MII frequency divider. The MII_SPEED controls the */ /* frequency of the MII management interface clock relative to the */ /* system clock. We set MII speed to 7 because the system clock */ /* frequency is 66 Mhz. */ put_reg(MCF5272_SIM->enet.mscr, 7<<1); /* Initialize upper level driver. */ (sc->funs->eth_drv->init)(sc, (unsigned char *)enaddr); /* Return true to indicate that the driver initialization has */ /* completed successfully. */ return true;}/* This function is called to "start up" the interface. It may be *//* called multiple times, even when the hardware is already running. It *//* will be called whenever something "hardware oriented" changes and should *//* leave the hardware ready to send/receive packets. */static voidMCF5272_fec_start(struct eth_drv_sc *sc, cyg_uint8 *enaddr, int flags){ /* Initialize the buffers structure. This strucre contains transmit */ /* and receive buffer descriptor managment information. We initialize */ /* again here becuase we don't know the internal state of the buffer */ /* descriptor pointer in the FEC if the FEC was disabled after calling */ /* MCF5272_fec_stop. */ if (PMCF5272_FEC_DATA(sc)->operational != ETH_DEV_UP) { nbuf_init(PBUF_INFO(sc)); } /* Unmask the Transmit and Receive frame interrupt to handle the */ /* interrupts. */ /* Unmask the Internal Bus Errorso we can detect any internal bus */ /* error when the FEC tries to acess the internal bus. */ put_reg(MCF5272_SIM->enet.eimr, get_reg(MCF5272_SIM->enet.eimr) | MCF5272_FEC_INTERRUPT_MASK); /* Enable FEC. */ put_reg(MCF5272_SIM->enet.ecr, MCF5272_FEC_ECR_ETHER_EN); /* Indicate that there have been empty receive buffers produced. */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?