📄 if_ixdp2400.c
字号:
//==========================================================================
//
// if_ixdp2400.c
//
// Ethernet drivers
// Intel IXDP2400 and PRO/100+ platform specific support
//
//==========================================================================
//####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, 2001 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): hmt, gthomas
// Contributors: Ron Spence, Pacific Softworks; msalter
// Date: 2000-02-01
// Purpose:
// Description: hardware driver for 82559 Intel PRO/100+ ethernet on
// a Intel XScale IXDP2400 development board
//
//
//####DESCRIPTIONEND####
//
//==========================================================================
#include <pkgconf/system.h>
#include <pkgconf/devs_eth_arm_ixdp2400.h>
#include <cyg/infra/cyg_type.h>
#include <cyg/infra/cyg_ass.h>
#include <cyg/hal/hal_arch.h>
#include <cyg/hal/hal_intr.h>
#include <cyg/hal/hal_io.h>
#include <cyg/hal/hal_cache.h>
#include <cyg/hal/drv_api.h>
#include <netdev.h>
#include <eth_drv.h>
#include <cyg/hal/cfg_utility.h>
#include <redboot.h>
#ifdef CYGPKG_NET
#include <pkgconf/net.h>
#include <net/if.h> /* Needed for struct ifnet */
#else
#include <cyg/hal/hal_if.h>
#define diag_printf printf
#endif
#ifdef CYGPKG_IO_PCI
#include <cyg/io/pci.h>
// So we can check the validity of the PCI window against the MLTs opinion,
// and thereby what the malloc heap consumes willy-nilly:
#include CYGHWR_MEMORY_LAYOUT_H
#else
#error "Need PCI package here"
#endif
#define MAX_RX_DESCRIPTORS 128
#define MAX_TX_DESCRIPTORS 128
// Exported statistics and the like
#include <cyg/devs/eth/ixdp2400_info.h>
#include <eth_drv_stats.h>
// ------------------------------------------------------------------------
//#define USE_MEM_ADRS
//#define USE_21555_PRI_NIC
#ifdef USE_21555_PRI_NIC
#define USE_MEM_ADRS
#endif
#ifdef CYGDBG_DEVS_ETH_ARM_IXDP2400_CHATTER
#define DEBUG_82559 // This one prints stuff as packets come and go
#define DEBUG // Startup printing mainly
#define DEBUG_EE // Some EEPROM specific retries &c
#endif
#define os_printf diag_printf
#define db_printf diag_printf
// ------------------------------------------------------------------------
// I/O access macros as inlines for type safety
static inline cyg_uint8 INB(cyg_uint32 io_address)
{ return *((volatile cyg_uint8 *)io_address);
}
static inline cyg_uint16 INW(cyg_uint32 io_address)
{ cyg_uint16 temp_rdw;
temp_rdw = *((volatile cyg_uint16 *)io_address);
#ifdef USE_MEM_ADRS
return swap16(temp_rdw);
#else
return temp_rdw;
#endif
}
static inline cyg_uint32 INL(cyg_uint32 io_address)
{ cyg_uint32 temp_rdl;
temp_rdl = *((volatile cyg_uint32 *)io_address);
#ifdef USE_MEM_ADRS
return swap32(temp_rdl);
#else
return temp_rdl;
#endif
}
static inline void OUTB(cyg_uint8 value, cyg_uint32 io_address)
{
#ifdef A0_REV
cyg_uint8 temp_wrb;
#endif
*((volatile cyg_uint8 *)io_address) = value;
#ifdef A0_REV
temp_wrb = INB(io_address);
#endif
}
static inline void OUTW(cyg_uint16 value, cyg_uint32 io_address)
{
#ifdef A0_REV
cyg_uint16 temp_wrw;
#endif
#ifdef USE_MEM_ADRS
*((volatile cyg_uint16 *)io_address) = swap16(value);
#else
*((volatile cyg_uint16 *)io_address) = value;
#endif
#ifdef A0_REV
temp_wrw = INW(io_address);
#endif
}
static inline void OUTL(cyg_uint32 value, cyg_uint32 io_address)
{
#ifdef A0_REV
cyg_uint32 temp_wrl;
#endif
#ifdef USE_MEM_ADRS
*((volatile cyg_uint32 *)io_address) = swap32(value);
#else
*((volatile cyg_uint32 *)io_address) = value;
#endif
#ifdef A0_REV
temp_wrl = INL(io_address);
#endif
}
#ifdef USE_21555_PRI_NIC
#define VIRT_TO_BUS(_x_) ((cyg_uint32)((cyg_uint32)(_x_) | 0x81000000))
#define BUS_TO_VIRT(_x_) ((cyg_uint32)((cyg_uint32)(_x_) & ~(0x81000000)))
#else
// Bus masters can get to all of SDRAM using direct mapping.
#define VIRT_TO_BUS(_x_) ((cyg_uint32)((cyg_uint32)(_x_) | (*(PCI_DRAM_BAR_REG) & ~0xF)))
#define BUS_TO_VIRT(_x_) ((cyg_uint32)((cyg_uint32)(_x_) & ~(*(PCI_DRAM_BAR_REG) & ~0xF)))
#endif
// ------------------------------------------------------------------------
//
// 82559 REGISTER OFFSETS (I/O SPACE)
//
// ------------------------------------------------------------------------
#ifdef USE_MEM_ADRS
#define SCBStatus 0 // Rx/Command Unit command and status.
#define SCBCmd 2 // Rx/Command Unit command and status.
#define SCBPointer 4 // General purpose pointer.
#define SCBPort 8 // Misc. commands and operands.
#define SCBflash 12 // Flash memory control.
#define SCBeeprom 14 // EEPROM memory control.
#define SCBCtrlMDI 16 // MDI interface control.
#define SCBEarlyRx 20 // Early receive byte count.
#define SCBGenControl 28 // 82559 General Control Register
#define SCBGenStatus 29 // 82559 General Status register
#else /* USE_MEM_ADRS */
#ifdef __ARMEB__
#define SCBStatus 0x2 // Rx/Command Unit command and status.
#define SCBCmd 0x0 // Rx/Command Unit command and status.
#define SCBPointer 0x4 // General purpose pointer.
#define SCBPort 0x8 // Misc. commands and operands.
#define SCBflash 0xE // Flash memory control.
#define SCBeeprom 0xC // EEPROM memory control.
#define SCBCtrlMDI 0x10 // MDI interface control.
#define SCBEarlyRx 0x14 // Early receive byte count.
#define SCBGenControl 0x1F // 82559 General Control Register
#define SCBGenStatus 0x1E // 82559 General Status register
#else /*__ARMEB__ */
#define SCBStatus 0 // Rx/Command Unit command and status.
#define SCBCmd 2 // Rx/Command Unit command and status.
#define SCBPointer 4 // General purpose pointer.
#define SCBPort 8 // Misc. commands and operands.
#define SCBflash 12 // Flash memory control.
#define SCBeeprom 14 // EEPROM memory control.
#define SCBCtrlMDI 16 // MDI interface control.
#define SCBEarlyRx 20 // Early receive byte count.
#define SCBGenControl 28 // 82559 General Control Register
#define SCBGenStatus 29 // 82559 General Status register
#endif
#endif
// ------------------------------------------------------------------------
//
// 82559 SCB STATUS WORD DEFNITIONS
//
// ------------------------------------------------------------------------
#define SCB_STATUS_CX 0x8000 // CU finished command (transmit)
#define SCB_STATUS_FR 0x4000 // frame received
#define SCB_STATUS_CNA 0x2000 // CU left active state
#define SCB_STATUS_RNR 0x1000 // receiver left ready state
#define SCB_STATUS_MDI 0x0800 // MDI read/write cycle done
#define SCB_STATUS_SWI 0x0400 // software generated interrupt
#define SCB_STATUS_FCP 0x0100 // flow control pause interrupt
#define SCB_INTACK_MASK 0xFD00 // all the above
#define SCB_INTACK_TX (SCB_STATUS_CX | SCB_STATUS_CNA)
#define SCB_INTACK_RX (SCB_STATUS_FR | SCB_STATUS_RNR)
// ------------------------------------------------------------------------
//
// 82559 PORT INTERFACE COMMANDS
//
// ------------------------------------------------------------------------
#define I82559_RESET 0x00000000 // software reset
#define I82559_SELFTEST 0x00000001 // 82559 selftest command
#define I82559_SELECTIVE_RESET 0x00000002
#define I82559_DUMP 0x00000003
#define I82559_DUMP_WAKEUP 0x00000007
// ------------------------------------------------------------------------
//
// 82559 EEPROM INTERFACE
//
// ------------------------------------------------------------------------
// EEPROM_Ctrl bits.
#define EE_SHIFT_CLK 0x01 // EEPROM shift clock.
#define EE_CS 0x02 // EEPROM chip select.
#define EE_DATA_WRITE 0x04 // EEPROM chip data in.
#define EE_DATA_READ 0x08 // EEPROM chip data out.
#define EE_ENB (0x4800 | EE_CS)
#define udelay(usec) hal_delay_us(usec)
// Delay between EEPROM clock transitions.
#define eeprom_delay(usec) udelay(usec);
// The EEPROM commands include the always-set leading bit.
#define EE_WRITE_CMD(a) (5 << (a))
#define EE_READ_CMD(a) (6 << (a))
#define EE_ERASE_CMD(a) (7 << (a))
#define EE_WRITE_EN_CMD(a) (19 << ((a)-2))
#define EE_WRITE_DIS_CMD(a) (16 << ((a)-2))
#define EE_ERASE_ALL_CMD(a) (18 << ((a)-2))
#define EE_TOP_CMD_BIT(a) ((a)+2) // Counts down to zero
#define EE_TOP_DATA_BIT (15) // Counts down to zero
#define EEPROM_ENABLE_DELAY (10) // Delay at chip select
#define EEPROM_SK_DELAY (2) // Delay between clock edges *and* data
// read or transition; 3 of these per bit.
#define EEPROM_DONE_DELAY (100) // Delay when all done
// ------------------------------------------------------------------------
//
// SYSTEM CONTROL BLOCK COMMANDS
//
// ------------------------------------------------------------------------
// CU COMMANDS
#define CU_NOP 0x0000
#define CU_START 0x0010
#define CU_RESUME 0x0020
#define CU_STATSADDR 0x0040 // Load Dump Statistics ctrs addr
#define CU_SHOWSTATS 0x0050 // Dump statistics counters.
#define CU_ADDR_LOAD 0x0060 // Base address to add to CU commands
#define CU_DUMPSTATS 0x0070 // Dump then reset stats counters.
// RUC COMMANDS
#define RUC_NOP 0x0000
#define RUC_START 0x0001
#define RUC_RESUME 0x0002
#define RUC_ABORT 0x0004
#define RUC_ADDR_LOAD 0x0006 // (seems not to clear on acceptance)
#define RUC_RESUMENR 0x0007
#define SCB_M 0x0100 // 0 = enable interrupt, 1 = disable
#define SCB_SI 0x0200 // 1 - cause device to interrupt
#define CU_STATUS_MASK 0x00C0
#define RU_STATUS_MASK 0x003C
#define RU_STATUS_IDLE (0<<2)
#define RU_STATUS_SUS (1<<2)
#define RU_STATUS_NORES (2<<2)
#define RU_STATUS_READY (4<<2)
#define RU_STATUS_NO_RBDS_SUS ((1<<2)|(8<<2))
#define RU_STATUS_NO_RBDS_NORES ((2<<2)|(8<<2))
#define RU_STATUS_NO_RBDS_READY ((4<<2)|(8<<2))
#define MAX_MEM_RESERVED_IOCTL 1000
// ------------------------------------------------------------------------
//
// RECEIVE FRAME DESCRIPTORS
//
// ------------------------------------------------------------------------
typedef struct rfd {
volatile union {
cyg_uint32 u32_status; // result of receive operation
cyg_uint16 u16_status[2];
} u_status;
volatile cyg_uint32 link; // offset from RU base to next RFD
volatile cyg_uint32 rdb_address; // pointer to Rx data buffer
#ifdef __ARMEB__
volatile cyg_uint32 size:16,
eof:1,
f:1,
count:14;
#else
volatile cyg_uint32 count:14, // number of bytes received +
f:1, // + EOF & F flags
eof:1,
size:16; // size of the data buffer
#endif
volatile cyg_uint8 buffer[0]; // data buffer (simple mode)
} RFD;
// The status is split into two shorts to get atomic access to the EL bit;
// the upper word is not written by the device, so we can just hit it,
// leaving the lower word (which the device updates) alone. Otherwise
// there's a race condition between software moving the end-of-list (EL)
// bit round and the device writing into the previous slot.
#define rxstatus u_status.u32_status
#ifdef __ARMEB__
#define rxstatus_hi u_status.u16_status[0]
#define rxstatus_lo u_status.u16_status[1]
#else
#define rxstatus_hi u_status.u16_status[1]
#define rxstatus_lo u_status.u16_status[0]
#endif
#define RFD_STATUS_EL 0x80000000 // 1=last RFD in RFA
#define RFD_STATUS_S 0x40000000 // 1=suspend RU after receiving frame
#define RFD_STATUS_H 0x00100000 // 1=RFD is a header RFD
#define RFD_STATUS_SF 0x00080000 // 0=simplified, 1=flexible mode
#define RFD_STATUS_C 0x00008000 // completion of received frame
#define RFD_STATUS_OK 0x00002000 // frame received with no errors
#define RFD_STATUS_HI_EL 0x8000 // 1=last RFD in RFA
#define RFD_STATUS_HI_S 0x4000 // 1=suspend RU after receiving frame
#define RFD_STATUS_HI_H 0x0010 // 1=RFD is a header RFD
#define RFD_STATUS_HI_SF 0x0008 // 0=simplified, 1=flexible mode
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -