📄 if_ebsa285.c
字号:
//==========================================================================//// if_ebsa285.c//// Ethernet drivers// Intel EBSA285 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 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// Date: 2000-02-01// Purpose: // Description: hardware driver for 82559 Intel PRO/100+ ethernet and// Intel StrongARM EBSA-285 development boards// ////####DESCRIPTIONEND####////==========================================================================#include <pkgconf/system.h>#include <pkgconf/devs_eth_arm_ebsa285.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/infra/diag.h>#include <cyg/hal/drv_api.h>#include <netdev.h>#include <eth_drv.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// Exported statistics and the like#include <cyg/devs/eth/ebsa285_info.h>#include <eth_drv_stats.h>// ------------------------------------------------------------------------#ifdef CYGDBG_DEVS_ETH_ARM_EBSA285_CHATTER#define notDEBUG_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 safetystatic inline void OUTB(cyg_uint8 value, cyg_uint32 io_address){ *((volatile cyg_uint8 *)io_address) = value; }static inline void OUTW(cyg_uint16 value, cyg_uint32 io_address){ *((volatile cyg_uint16 *)io_address) = value; }static inline void OUTL(cyg_uint32 value, cyg_uint32 io_address){ *((volatile cyg_uint32 *)io_address) = value; }static inline cyg_uint8 INB(cyg_uint32 io_address){ return *((volatile cyg_uint8 *)io_address); }static inline cyg_uint16 INW(cyg_uint32 io_address){ return *((volatile cyg_uint16 *)io_address); }static inline cyg_uint32 INL(cyg_uint32 io_address){ return *((volatile cyg_uint32 *)io_address); }#define VIRT_TO_BUS( _x_ ) virt_to_bus((cyg_uint32)(_x_))static inline cyg_uint32 virt_to_bus(cyg_uint32 p_memory){ return (p_memory - CYGHWR_HAL_ARM_EBSA285_PCI_MEM_MAP_BASE); }#define BUS_TO_VIRT( _x_ ) bus_to_virt((cyg_uint32)(_x_))static inline cyg_uint32 bus_to_virt(cyg_uint32 p_memory){ return (p_memory + CYGHWR_HAL_ARM_EBSA285_PCI_MEM_MAP_BASE); }// ------------------------------------------------------------------------// // 82559 REGISTER OFFSETS (I/O SPACE) // // ------------------------------------------------------------------------#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// ------------------------------------------------------------------------//// 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)// 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 volatile cyg_uint32 count:14, // number of bytes received + f:1, // + EOF & F flags eof:1, size:16; // size of the data buffer 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#define rxstatus_hi u_status.u16_status[1]#define rxstatus_lo u_status.u16_status[0]#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#define RFD_STATUS_LO_C 0x8000 // completion of received frame#define RFD_STATUS_LO_OK 0x2000 // frame received with no errors#define RFD_RX_CRC 0x00000800 // crc error#define RFD_RX_ALIGNMENT 0x00000400 // alignment error#define RFD_RX_RESOURCE 0x00000200 // out of space, no resources#define RFD_RX_DMA_OVER 0x00000100 // DMA overrun#define RFD_RX_SHORT 0x00000080 // short frame error#define RFD_RX_LENGTH 0x00000020 //#define RFD_RX_ERROR 0x00000010 // receive error#define RFD_RX_NO_ADR_MATCH 0x00000004 // no address match#define RFD_RX_IA_MATCH 0x00000002 // individual address does not match#define RFD_RX_TCO 0x00000001 // TCO indicationtypedef struct rbd { volatile cyg_uint32 count:14, // bytes used in buffer f:1, // buffer has been used (filled) eof:1; // last receive buffer in frame volatile cyg_uint32 next_rbd; // next RBD (RU base relative) volatile cyg_uint32 buffer_address; // address of receive data buffer volatile cyg_uint32 size:15, // size of the associated buffer el:1; // buffer of this RBD is last} RBD;// ------------------------------------------------------------------------//// TRANSMIT FRAME DESCRIPTORS//// ------------------------------------------------------------------------typedef struct txcb { volatile cyg_uint32 txstatus:16, // result of transmit operation command:16; // transmit command volatile cyg_uint32 link; // offset from RU base to next RFD volatile cyg_uint32 tbd_address; // pointer to Rx data buffer volatile cyg_uint32 count:15, // number of bytes in transmit buffer eof:1, tx_threshold:8, tbd_number:8; volatile cyg_uint8 buffer[0]; // data buffer (simple mode)} TxCB;#define TxCB_CMD_TRANSMIT 0x0004 // transmit command#define TxCB_CMD_SF 0x0008 // 0=simplified, 1=flexible mode#define TxCB_CMD_NC 0x0010 // 0=CRC insert by controller#define TxCB_CMD_I 0x2000 // generate interrupt on completion#define TxCB_CMD_S 0x4000 // suspend on completion#define TxCB_CMD_EL 0x8000 // last command block in CBL// ------------------------------------------------------------------------//// STRUCTURES ADDED FOR PROMISCUOUS MODE//// ------------------------------------------------------------------------typedef struct { cyg_uint32 cb_status_word:13, cb_ok:1, cb_dc:1, cb_complete:1, cb_cmd:3, cb_cmd_word:10, cb_int:1, cb_suspend:1, cb_el:1; cyg_uint32 cb_link_offset;} CB_STRUCT;typedef struct { CB_STRUCT cb_entry; cyg_uint8 config_bytes[24];} CONFIG_CMD_STRUCT;// ------------------------------------------------------------------------//// STATISTICAL COUNTER STRUCTURE//// ------------------------------------------------------------------------#ifdef KEEP_STATISTICSSTATISTICS statistics[2];I82559_COUNTERS i82559_counters[2];#endif // KEEP_STATISTICS// ------------------------------------------------------------------------//// DEVICES AND PACKET QUEUES//// ------------------------------------------------------------------------#define MAX_RX_PACKET_SIZE 1536 // maximum Rx packet size#define MAX_TX_PACKET_SIZE 1536 // maximum Tx packet size// This is encapsulated here so that a change to > 2 interfaces can// easily be accommodated.#define IF_BAD_82559( _p_ ) \ CYG_ASSERT( (&i82559[0] == (_p_)) || (&i82559[1] == (_p_)), \ "Bad pointer-to-i82559" ); \ if ( (&i82559[0] != (_p_)) && (&i82559[1] != (_p_)) )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -