📄 if_edb7xxx.c
字号:
//==========================================================================//// dev/if_edb7xxx.c//// Ethernet device driver for Cirrus Logic EDB7xxx using CS8900////==========================================================================//####COPYRIGHTBEGIN####// // ------------------------------------------- // The contents of this file are subject to the Red Hat eCos Public License // Version 1.1 (the "License"); you may not use this file except in // compliance with the License. You may obtain a copy of the License at // http://www.redhat.com/ // // Software distributed under the License is distributed on an "AS IS" // basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the // License for the specific language governing rights and limitations under // the License. // // The Original Code is eCos - Embedded Configurable Operating System, // released September 30, 1998. // // The Initial Developer of the Original Code is Red Hat. // Portions created by Red Hat are // Copyright (C) 1998, 1999, 2000 Red Hat, Inc. // All Rights Reserved. // ------------------------------------------- // //####COPYRIGHTEND####//####BSDCOPYRIGHTBEGIN####//// -------------------------------------------//// Portions of this software may have been derived from OpenBSD or other sources,// and are covered by the appropriate copyright disclaimers included herein.//// -------------------------------------------////####BSDCOPYRIGHTEND####//==========================================================================//#####DESCRIPTIONBEGIN####//// Author(s): gthomas// Contributors: gthomas// Date: 2000-01-10// Purpose: // Description: hardware driver for CS8900 ethernet// ////####DESCRIPTIONEND####////==========================================================================// Ethernet device driver for Cirrus Logic EDB7xxx// Based on CS8900A#include <pkgconf/system.h>#include <pkgconf/devs_eth_arm_edb7xxx.h>#ifdef CYGPKG_NET#include <pkgconf/net.h>#include <cyg/kernel/kapi.h>#endif#include <cyg/infra/cyg_type.h>#include <cyg/hal/hal_arch.h>#include <cyg/hal/hal_intr.h>#include <cyg/infra/diag.h>#include <cyg/hal/drv_api.h>#include <netdev.h>#include <eth_drv.h>#ifndef CYGSEM_ARM_EDB7XXX_SET_ESA#ifdef CYGPKG_REDBOOT#include <pkgconf/redboot.h>#ifdef CYGSEM_REDBOOT_FLASH_CONFIG#include <redboot.h>#include <flash_config.h>RedBoot_config_option("Network hardware address [MAC]", edb7xxx_esa, ALWAYS_ENABLED, true, CONFIG_ESA );#endif#endif#endif#define INTS_DONT_WORK#undef INTS_DONT_WORK#ifdef INTS_DONT_WORK#define STACK_SIZE CYGNUM_HAL_STACK_SIZE_MINIMUMstatic char cs8900_fake_int_stack[STACK_SIZE];static cyg_thread cs8900_fake_int_thread_data;static cyg_handle_t cs8900_fake_int_thread_handle;static void cs8900_fake_int(cyg_addrword_t);#endif#define CS8900_BASE 0x20000000#include "cs8900.h"#define ETHER_ADDR_LEN 6extern int net_debug; // FIXMEstruct cs8900_priv_data { int txbusy; // A packet has been sent unsigned long txkey; // Used to ack when packet sent#ifdef CYGPKG_NET cyg_tick_count_t txstart;#endif} _cs8900_priv_data;ETH_DRV_SC(edb7xxx_sc, &_cs8900_priv_data, // Driver specific data "eth0", // Name for this interface cs8900_start, cs8900_stop, cs8900_control, cs8900_can_send, cs8900_send, cs8900_recv, cs8900_deliver, // "pseudoDSR" called from fast net thread cs8900_int, // poll function, encapsulates ISR and DSR cs8900_int_vector);NETDEVTAB_ENTRY(edb7xxx_netdev, "edb7xxx", edb7xxx_cs8900_init, &edb7xxx_sc);#ifdef CYGSEM_ARM_EDB7XXX_SET_ESAstatic unsigned char enaddr[] = CYGDAT_ARM_EDB7XXX_ESA;#elsestatic unsigned char enaddr[ETHER_ADDR_LEN];#endifstatic void cs8900_int(struct eth_drv_sc *sc);static cyg_interrupt cs8900_interrupt;static cyg_handle_t cs8900_interrupt_handle;// This ISR is called when the ethernet interrupt occursstatic intcs8900_isr(cyg_vector_t vector, cyg_addrword_t data, HAL_SavedRegisters *regs){ cyg_drv_interrupt_mask(CYGNUM_HAL_INTERRUPT_EINT3); return (CYG_ISR_HANDLED|CYG_ISR_CALL_DSR); // Run the DSR}// The deliver function (ex-DSR) handles the ethernet [logical] processingstatic voidcs8900_deliver(struct eth_drv_sc *sc){ cs8900_int(sc); // Allow interrupts to happen again cyg_drv_interrupt_acknowledge(CYGNUM_HAL_INTERRUPT_EINT3); cyg_drv_interrupt_unmask(CYGNUM_HAL_INTERRUPT_EINT3);}static intcs8900_int_vector(struct eth_drv_sc *sc){ return (CYGNUM_HAL_INTERRUPT_EINT3);}static bool edb7xxx_cs8900_init(struct cyg_netdevtab_entry *tab){ struct eth_drv_sc *sc = (struct eth_drv_sc *)tab->device_instance; unsigned short chip_type, chip_rev, chip_status; int i; // Initialize environment, setup interrupt handler cyg_drv_interrupt_create(CYGNUM_HAL_INTERRUPT_EINT3, 99, // Priority - what goes here? (cyg_addrword_t)sc, // Data item passed to interrupt handler (cyg_ISR_t *)cs8900_isr, (cyg_DSR_t *)eth_drv_dsr, // The logical driver DSR &cs8900_interrupt_handle, &cs8900_interrupt); cyg_drv_interrupt_attach(cs8900_interrupt_handle); cyg_drv_interrupt_acknowledge(CYGNUM_HAL_INTERRUPT_EINT3); cyg_drv_interrupt_unmask(CYGNUM_HAL_INTERRUPT_EINT3);#ifdef INTS_DONT_WORK cyg_thread_create(1, // Priority cs8900_fake_int, // entry 0, // entry parameter "CS8900 int", // Name &cs8900_fake_int_stack[0], // Stack STACK_SIZE, // Size &cs8900_fake_int_thread_handle, // Handle &cs8900_fake_int_thread_data // Thread data structure ); cyg_thread_resume(cs8900_fake_int_thread_handle); // Start it#endif chip_type = get_reg(PP_ChipID); chip_rev = get_reg(PP_ChipRev);#if 0 diag_printf("CS8900 - type: %x, rev: %x\n", chip_type, chip_rev);#endif // Fetch hardware address#if defined(CYGPKG_REDBOOT) && \ defined(CYGSEM_REDBOOT_FLASH_CONFIG) && \ !defined(CYGSEM_ARM_EDB7XXX_SET_ESA) flash_get_config("edb7xxx_esa", enaddr, CONFIG_ESA);#else for (i = 0; i < ETHER_ADDR_LEN; i += 2) { unsigned short esa_reg = get_reg(PP_IA+i); enaddr[i] = esa_reg & 0xFF; enaddr[i+1] = esa_reg >> 8; }#endif put_reg(PP_SelfCtl, PP_SelfCtl_Reset); // Reset chip while ((get_reg(PP_SelfStat) & PP_SelfStat_InitD) == 0) ; chip_status = get_reg(PP_SelfStat);#if 0 diag_printf("CS8900 - status: %x (%sEEPROM present)\n", chip_status, chip_status&PP_SelfStat_EEPROM ? "" : "no ");#endif // Set up hardware address for (i = 0; i < ETHER_ADDR_LEN; i += 2) { put_reg(PP_LAF+i, 0xFFFF); put_reg(PP_IA+i, enaddr[i] | (enaddr[i+1] << 8)); } // Initialize upper level driver (sc->funs->eth_drv->init)(sc, enaddr); return true;}static voidcs8900_stop(struct eth_drv_sc *sc){ put_reg(PP_SelfCtl, PP_SelfCtl_Reset); // Reset chip while ((get_reg(PP_SelfStat) & PP_SelfStat_InitD) == 0) ; }//// 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -