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

📄 if_8139.c

📁 开放源码实时操作系统源码.
💻 C
📖 第 1 页 / 共 4 页
字号:
//==========================================================================
//
//      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|IR_FUN)

/* 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_ALONE
static cyg_uint32 rltk8139_isr(cyg_vector_t vector, cyg_addrword_t data);
#endif

#ifdef ETH_DRV_SET_MC_LIST
static 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);
#endif

static 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 CYGPKG_DEVS_ETH_RLTK_8139_WRITE_EEPROM
static cyg_uint16 rltk8139_eeprom_read( char *cpErAddr, cyg_uint8 Cmd, cyg_uint8 RomAdr );
static void rltk8139_eeprom_write( char *cpErAddr, cyg_uint8 Cmd, cyg_uint8 RomAdr, cyg_uint16 SrcData );
#endif

#ifdef DEBUG_RLTK8139_DRIVER
void rltk8139_print_state(struct eth_drv_sc *sc);
#endif

#ifdef CYGPKG_DEVS_ETH_RLTK_8139_WRITE_EEPROM
#define EEPROM_CMD_READ         0x06  // eeprom read command
#define EEPROM_CMD_WRITE        0x05  // eeprom write command
#define EEPROM_PG_ON            0x80
#define EEPROM_PG_EECS          0x08
#define EEPROM_PG_EESK          0x04
#define EEPROM_PG_EEDI          0x02
#define EEPROM_PG_EEDO          0x01
#define EEPROM_WR_BUSY_RETRIES  100   // ready wait re-try count


#define	EEPROM_MASK(_param0_,_param1_)            ((_param0_ & _param1_) ? EEPROM_PG_EEDI : 0 )





#define EEPROM_WR_DATA(_addr_,_txdata_)           HAL_WRITE_UINT8(_addr_,_txdata_);



#define EEPROM_WR_DATAPULSE(_addr_,_txdata_)      HAL_WRITE_UINT8(_addr_,_txdata_); \

                                                  cyg_thread_delay(0); \
                                                  HAL_WRITE_UINT8(_addr_,_txdata_ | EEPROM_PG_EESK);



#define EEPROM_RD_DATA(_addr_,_txdata_,_rxdata_)  { \

                                                  cyg_uint16  read_data; \
                                                  HAL_WRITE_UINT8(_addr_,_txdata_); \

                                                  cyg_thread_delay(1); \

                                                  HAL_READ_UINT8(_addr_, read_data); \
                                                  _rxdata_ <<= 1; \

                                                  _rxdata_ |= ((read_data & EEPROM_PG_EEDO) ? 0x0001 : 0x0000 ); \

                                                  HAL_WRITE_UINT8(_addr_,_txdata_ | EEPROM_PG_EESK); }

#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 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 & 0xff) << 8) | ((value & 0xff00) >> 8)) );
}

static inline void
OUTL(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_uint8
INB(cyg_uint32 io_address)
{
  cyg_uint8 d;
  HAL_READ_UINT8(io_address, d);
  return d;
}

static inline cyg_uint16
INW(cyg_uint32 io_address)
{
  cyg_uint16 d;
  HAL_READ_UINT16( io_address, d );
  return (((d & 0xff) << 8) | ((d & 0xff00) >> 8));
}

static inline cyg_uint32
INL(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 3
static pci_identifier_t
known_8139_aliases[CYGNUM_DEVS_ETH_RLTK_8139_KNOWN_ALIASES] = {
  { 0x10ec, 0x8139, NULL }, /* This is the official RealTek vendor/device code of 8139D(L) */
  { 0x11db, 0x1234, NULL}, /* SEGA DreamCast BroadBandAdapter */
  { 0x10ec, 0x8129, NULL } /* This is the official RealTek vendor/device code of 8139C(L) */
};


/*
 * Check if the device description matches a known 8139 alias.
 */
static cyg_bool
rltk8139_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 bool
rltk8139_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 */
  pci_device_id = CYG_PCI_NULL_DEVID;
  do {
    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.

⌨️ 快捷键说明

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