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

📄 if_8139.c

📁 eCos操作系统源码
💻 C
📖 第 1 页 / 共 3 页
字号:
//==========================================================================////      if_8139.c////	RealTek 8139 ethernet driver////==========================================================================//####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####//####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):    Eric Doenges// Contributors: Chris Nimmers, Gary Thomas, Andy Dyer// Date:         2003-07-09// Purpose:// Description:  hardware driver for RealTek 8139 ethernet// Notes:        This is a very basic driver that will send and receive//               packets and not much else. A lot of features of the 8139//               are not supported (power management, MII interface,//               access to the serial eeprom, 'twister tuning', etc.).////               Many of the configuration options (like media type and//               speed) the 8139 has are taken directly from the serial//               eeprom and are not currently configurable from this driver.////               I've tentatively added some code to handle cache coherency//               issues for platforms that do not have a separate address//               space for uncached memory access and do not do cache//               snooping for PCI bus masters. This code can be activated by//               defining CYGPKG_DEVS_ETH_RLTK_8139_SOFTWARE_CACHE_COHERENCY//               in the platform specific .inl file. Note that if//               CYGPKG_DEVS_ETH_RLTK_8139_SOFTWARE_CACHE_COHERENCY is//               defined, the .inl file is also responsible for making sure//               the receive and transmit buffers are located in memory in//               such a way that flushing or invalidating cache lines for//               these buffers will not affect any other buffers. See the//               README in the doc directory for some suggestions on how//               to do this.////               Since the official data sheet for this chip is a bit//               vague, I had to look at the Linux and OpenBSD drivers to//               understand the basic workings of the chip; however, I have//               not copied any code from those drivers to avoid tainting//               eCos' license.////        FIXME:////####DESCRIPTIONEND####////==========================================================================#include <pkgconf/system.h>#ifdef CYGPKG_IO_ETH_DRIVERS#include <pkgconf/io_eth_drivers.h>#endif#include <pkgconf/devs_eth_rltk_8139.h>#include <cyg/infra/cyg_type.h>#include <cyg/infra/cyg_ass.h>#include <cyg/infra/diag.h>#include <cyg/hal/hal_arch.h>#include <cyg/hal/drv_api.h>#include <cyg/hal/hal_cache.h>#include <cyg/io/eth/netdev.h>#include <cyg/io/eth/eth_drv.h>#include <string.h> /* for memset */#ifdef CYGPKG_IO_PCI#include <cyg/io/pci.h>#else#error "This driver requires the PCI package (CYGPKG_IO_PCI)"#endif#include <cyg/io/pci.h>/* Necessary for memory mapping macros */#include CYGHWR_MEMORY_LAYOUT_H/* Check if we should be dumping debug information or not */#if defined CYGDBG_DEVS_ETH_RLTK_8139_CHATTER \    && (CYGDBG_DEVS_ETH_RLTK_8139_CHATTER > 0)#define DEBUG_RLTK8139_DRIVER#endif#include "if_8139.h"/* Which interrupts we will handle */#define RLTK8139_IRQ (IR_SERR|IR_FOVW|IR_RXOVW|IR_TER|IR_TOK|IR_RER|IR_ROK)/* Allow platform-specific configuration of the driver */#ifndef CYGDAT_DEVS_ETH_RLTK_8139_INL#error "CYGDAT_DEVS_ETH_RLTK_8139_INL not defined"#else#include CYGDAT_DEVS_ETH_RLTK_8139_INL#endif#ifndef CYGHWR_RLTK_8139_PLF_INIT#define CYGHWR_RLTK_8139_PLF_INIT(sc) do {} while(0)#endif/* * If software cache coherency is required, the HAL_DCACHE_INVALIDATE * hal macro must be defined as well. */#ifdef CYGPKG_DEVS_ETH_RLTK_8139_SOFTWARE_CACHE_COHERENCY#if !defined HAL_DCACHE_INVALIDATE || !defined HAL_DCACHE_FLUSH#error "HAL_DCACHE_INVALIDATE/HAL_DCACHE_FLUSH not defined for this platform but CYGPKG_DEVS_ETH_RLTK_8139_CACHE_COHERENCY was defined."#endif#endif/* Local driver function declarations */#ifndef CYGPKG_IO_ETH_DRIVERS_STAND_ALONEstatic cyg_uint32 rltk8139_isr(cyg_vector_t vector, cyg_addrword_t data);#endif#ifdef ETH_DRV_SET_MC_LISTstatic cyg_uint32 ether_crc(cyg_uint8 *data, int length);static void rltk8139_set_multicast_list(Rltk8139_t *rltk8139_info,                                        struct eth_drv_mc_list *mc_list);#endifstatic void rltk8139_reset(struct eth_drv_sc *sc);static bool rltk8139_init(struct cyg_netdevtab_entry *tab);static void rltk8139_start(struct eth_drv_sc *sc, unsigned char *enaddr,                           int flags);static void rltk8139_stop(struct eth_drv_sc *sc);static int rltk8139_control(struct eth_drv_sc *sc, unsigned long key,                            void *data, int   data_length);static int rltk8139_can_send(struct eth_drv_sc *sc);static void rltk8139_send(struct eth_drv_sc *sc, struct eth_drv_sg *sg_list,                          int sg_len, int total_len, unsigned long key);static void rltk8139_recv(struct eth_drv_sc *sc, struct eth_drv_sg *sg_list,                          int sg_len);static void rltk8139_deliver(struct eth_drv_sc *sc);static void rltk8139_poll(struct eth_drv_sc *sc);static int rltk8139_int_vector(struct eth_drv_sc *sc);#ifdef DEBUG_RLTK8139_DRIVERvoid rltk8139_print_state(struct eth_drv_sc *sc);#endif/* * Define inline functions to access the card. This will also handle * endianess issues in one place. This code was lifted from the eCos * i82559 driver. */#if (CYG_BYTEORDER == CYG_MSBFIRST)#define HAL_CTOLE32(x)  ((((x) & 0xff) << 24) | (((x) & 0xff00) << 8) | (((x) & 0xff0000) >> 8) | (((x) >> 24) & 0xff))#define HAL_LE32TOC(x)  ((((x) & 0xff) << 24) | (((x) & 0xff00) << 8) | (((x) & 0xff0000) >> 8) | (((x) >> 24) & 0xff))#define HAL_CTOLE16(x)  ((((x) & 0xff) << 8) | (((x) & 0xff00) >> 8))#define HAL_LE16TOC(x)  ((((x) & 0xff) << 8) | (((x) & 0xff00) >> 8))static inline voidOUTB(cyg_uint8 value,          cyg_uint32 io_address){  HAL_WRITE_UINT8( io_address, value);}static inline voidOUTW(cyg_uint16 value, cyg_uint32 io_address){  HAL_WRITE_UINT16(io_address,                   (((value & 0xff) << 8) | ((value & 0xff00) >> 8)) );}static inline voidOUTL(cyg_uint32 value, cyg_uint32 io_address){  HAL_WRITE_UINT32(io_address,                   ((((value) & 0xff) << 24) | (((value) & 0xff00) << 8)                    | (((value) & 0xff0000) >> 8)                    | (((value) >> 24) & 0xff)) );}static inline cyg_uint8INB(cyg_uint32 io_address){  cyg_uint8 d;  HAL_READ_UINT8(io_address, d);  return d;}static inline cyg_uint16INW(cyg_uint32 io_address){  cyg_uint16 d;  HAL_READ_UINT16( io_address, d );  return (((d & 0xff) << 8) | ((d & 0xff00) >> 8));}static inline cyg_uint32INL(cyg_uint32 io_address){  cyg_uint32 d;  HAL_READ_UINT32(io_address, d);  return ((((d) & 0xff) << 24) | (((d) & 0xff00) << 8)          | (((d) & 0xff0000) >> 8) | (((d) >> 24) & 0xff));}#else// Maintaining the same styleee as above...#define HAL_CTOLE32(x)  ((((x))))#define HAL_LE32TOC(x)  ((((x))))#define HAL_CTOLE16(x)  ((((x))))#define HAL_LE16TOC(x)  ((((x))))static inline void OUTB(cyg_uint8  value, cyg_uint32 io_address){   HAL_WRITE_UINT8( io_address, value );   }static inline void OUTW(cyg_uint16 value, cyg_uint32 io_address){   HAL_WRITE_UINT16( io_address, value );   }static inline void OUTL(cyg_uint32 value, cyg_uint32 io_address){   HAL_WRITE_UINT32( io_address, value );   }static inline cyg_uint8  INB(cyg_uint32 io_address){   cyg_uint8  _t_; HAL_READ_UINT8(  io_address, _t_ ); return _t_;   }static inline cyg_uint16 INW(cyg_uint32 io_address){   cyg_uint16 _t_; HAL_READ_UINT16( io_address, _t_ ); return _t_;   }static inline cyg_uint32 INL(cyg_uint32 io_address){   cyg_uint32 _t_; HAL_READ_UINT32( io_address, _t_ ); return _t_;   }#endif // byteorder/* * Table of all known PCI device/vendor ID combinations for the RealTek 8139. * Add them as you get to know them. */#define CYGNUM_DEVS_ETH_RLTK_8139_KNOWN_ALIASES 2static pci_identifier_tknown_8139_aliases[CYGNUM_DEVS_ETH_RLTK_8139_KNOWN_ALIASES] = {  { 0x10ec, 0x8139, NULL }, /* This is the offical RealTek vendor/device code */  { 0x11db, 0x1234, NULL} /* SEGA DreamCast BroadBandAdapter */};/* * Check if the device description matches a known 8139 alias. */static cyg_boolrltk8139_find_match_func(cyg_uint16 vendor_id, cyg_uint16 device_id,                         cyg_uint32 class_id, void *p){  int i;  for (i = 0; i < CYGNUM_DEVS_ETH_RLTK_8139_KNOWN_ALIASES; ++i) {    if (((known_8139_aliases[i].vendor_id == PCI_ANY_ID) ||         (known_8139_aliases[i].vendor_id == vendor_id)) &&        ((known_8139_aliases[i].device_id == PCI_ANY_ID) ||         (known_8139_aliases[i].device_id == device_id)))      return true;  }  return false;}/* * Find the Nth 8139 device on all attached PCI busses and do some initial * PCI-type initialization. Also setup the interrupt for use in eCos. */static boolrltk8139_find(int n_th, struct eth_drv_sc *sc){  Rltk8139_t *rltk8139_info;  cyg_pci_device_id pci_device_id;  cyg_pci_device pci_device_info;  cyg_uint16 command;  int found = -1;  /* Go through all PCI devices until we find the Nth 8139 chip */  do {    pci_device_id = CYG_PCI_NULL_DEVID;    if (!cyg_pci_find_matching(&rltk8139_find_match_func, NULL,                               &pci_device_id))      return false;    else      found += 1;  } while (found != n_th);  /* Save device ID in driver private data in case we ever need it again */  rltk8139_info = (Rltk8139_t *)(sc->driver_private);  rltk8139_info->pci_device_id = pci_device_id;  /* Now that we have found the device, we can extract some data about it */  cyg_pci_get_device_info(pci_device_id, &pci_device_info);  /* Get the assigned interrupt and set up ISR and DSR for it. */  if (cyg_pci_translate_interrupt(&pci_device_info, &rltk8139_info->vector)) {#ifdef DEBUG_RLTK8139_DRIVER    diag_printf(" Wired to HAL interrupt vector %d\n", rltk8139_info->vector);#endif#ifndef CYGPKG_IO_ETH_DRIVERS_STAND_ALONE    /*     * Note that we use the generic eth_drv_dsr routine instead of     * our own.     */    cyg_drv_interrupt_create(rltk8139_info->vector, 0,                             (CYG_ADDRWORD)sc,                             rltk8139_isr,                             eth_drv_dsr,                             &rltk8139_info->interrupt_handle,                             &rltk8139_info->interrupt);    cyg_drv_interrupt_attach(rltk8139_info->interrupt_handle);#endif  }  else {#ifdef DEBUG_RLTK8139_DRIVER    diag_printf(" Does not generate interrupts.\n");#endif  }  /*   * Call 'cyg_pci_configure_device' for those platforms that do not   * configure the PCI bus during HAL initialization. According to Nick   * Garnett, there are good reasons to not configure PCI devices during HAL   * initialization. Also according to Nick, calling   * 'cyg_pci_configure_device' for devices already configured should have no   * effect and thus is safe to do.   */  if (cyg_pci_configure_device(&pci_device_info)) {#ifdef DEBUG_RLTK8139_DRIVER    int i;    diag_printf("Found device #%d on bus %d, devfn 0x%02x:\n", n_th,                CYG_PCI_DEV_GET_BUS(pci_device_id),                CYG_PCI_DEV_GET_DEVFN(pci_device_id));    if (pci_device_info.command & CYG_PCI_CFG_COMMAND_ACTIVE)      diag_printf(" Note that board is active. Probed"                  " sizes and CPU addresses are invalid!\n");    diag_printf(" Vendor    0x%04x", pci_device_info.vendor);    diag_printf("\n Device    0x%04x", pci_device_info.device);    diag_printf("\n Command   0x%04x, Status 0x%04x\n",                pci_device_info.command, pci_device_info.status)      ;    diag_printf(" Class/Rev 0x%08x", pci_device_info.class_rev);    diag_printf("\n Header 0x%02x\n", pci_device_info.header_type);    diag_printf(" SubVendor 0x%04x, Sub ID 0x%04x\n",                pci_device_info.header.normal.sub_vendor,                pci_device_info.header.normal.sub_id);    for(i = 0; i < CYG_PCI_MAX_BAR; i++) {      diag_printf(" BAR[%d]    0x%08x /", i, pci_device_info.base_address[i]);      diag_printf(" probed size 0x%08x / CPU addr 0x%08x\n",                  pci_device_info.base_size[i], pci_device_info.base_map[i]);    }#endif  }  else {#ifdef DEBUG_RLTK8139_DRIVER    diag_printf("Failed to configure 8139 device #%d\n", n_th);#endif    return false;  }  /*   * Enable memory mapped and port based I/O and busmastering. We currently   * only support IO space accesses; memory mapping is enabled so that bit   * DVRLOAD in CONFIG1 is cleared automatically.   *   * NOTE: it seems that for some configurations/HALs, the device is already   *       activated at this point, even though eCos' documentation suggests   *       it shouldn't be. At least in my case, this is not a problem.   */  cyg_pci_read_config_uint16(pci_device_info.devid, CYG_PCI_CFG_COMMAND,                             &command);  command |= (CYG_PCI_CFG_COMMAND_IO | CYG_PCI_CFG_COMMAND_MEMORY              | CYG_PCI_CFG_COMMAND_MASTER);  cyg_pci_write_config_uint16(pci_device_info.devid, CYG_PCI_CFG_COMMAND,                              command);  /*   * This is the base address used to talk to the device. The 8139's IOAR   * and MEMAR registers are BAR0 and BAR1, respectively.   */  rltk8139_info->base_address = pci_device_info.base_map[0];  /*   * Read the MAC address. The RealTek data sheet seems to claim this should   * only be read in 4 byte accesses, but the code below works just fine.   */  for (found = 0; found < 6; ++found)    rltk8139_info->mac[found] = INB(rltk8139_info->base_address + IDR0 + found);  /*   * This is the indicator for "uses an interrupt". The code was lifted

⌨️ 快捷键说明

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