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

📄 if_ixdp2400.c

📁 基于ecos的redboot
💻 C
📖 第 1 页 / 共 5 页
字号:

#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 indication


typedef 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
#ifdef __ARMEB__
	volatile cyg_uint32 tbd_number:8,
		tx_threshold:8,
		eof:1,
		count:15;
#else
    volatile cyg_uint32 count:15,       // number of bytes in transmit buffer
        eof:1,
        tx_threshold:8,
        tbd_number:8;
#endif
    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_STATISTICS
STATISTICS 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_)) )

// ------------------------------------------------------------------------
// Instantiate the interfaces that we have:

// number of interfaces
#define MAX_82559 1

I82559 i82559[MAX_82559];               // i82559 device info. structure

// eth0

ETH_DRV_SC(ixdp2400_sc0,
           &i82559[0],                  // Driver specific data
           "eth0",                      // Name for this interface
           i82559_start,
           i82559_stop,
           i82559_ioctl,
           i82559_can_send,
           i82559_send,
           i82559_recv,
           i82559_deliver,
           i82559_poll,
           i82559_int_vector
    );

NETDEVTAB_ENTRY(ixdp2400_netdev0, 
                "ixdp2400-0", 
                ixdp2400_i82559_init, 
                &ixdp2400_sc0);

#if (MAX_82559 > 1)

// eth1

ETH_DRV_SC(ixdp2400_sc1,
           &i82559[1],                  // Driver specific data
           "eth1",                      // Name for this interface
           i82559_start,
           i82559_stop,
           i82559_ioctl,
           i82559_can_send,
           i82559_send,
           i82559_recv,
           i82559_deliver,
           i82559_poll,
           i82559_int_vector
    );

NETDEVTAB_ENTRY(ixdp2400_netdev1, 
                "ixdp2400-1", 
                ixdp2400_i82559_init, 
                &ixdp2400_sc1);

#else
int ixdp2400_netdev1 = -1; // for asserts about valid addresses
int ixdp2400_sc1 = -1;
#endif // eth1 is included

// This is in a macro so that if more devices arrive it can easily be changed
#define CHECK_NDP_SC_LINK() CYG_MACRO_START                                \
    CYG_ASSERT( ((void *)ndp == (void *)&ixdp2400_netdev0) ||               \
                ((void *)ndp == (void *)&ixdp2400_netdev1), "Bad ndp" );    \
    CYG_ASSERT( ((void *)sc == (void *)&ixdp2400_sc0) ||                    \
                ((void *)sc == (void *)&ixdp2400_sc1), "Bad sc" );          \
    CYG_ASSERT( (void *)p_i82559 == sc->driver_private, "sc pointer bad" );\
CYG_MACRO_END

externC cyg_uint32 board_rev;
extern struct board_config *board_config_data;

// ------------------------------------------------------------------------
//
// Managing the memory that is windowed onto the PCI bus
//
// ------------------------------------------------------------------------

static cyg_uint32 i82559_heap_size;
static cyg_uint8 *i82559_heap_base;
static cyg_uint8 *i82559_heap_free;

static void *mem_reserved_ioctl = (void*)0;
// uncacheable memory reserved for ioctl calls

// ------------------------------------------------------------------------
//
//                       FUNCTION PROTOTYPES
//
// ------------------------------------------------------------------------

static int pci_init_find_82559s(void);

static void i82559_reset(struct i82559* p_i82559);

static void InitRxRing(struct i82559* p_i82559);
static void ResetRxRing(struct i82559* p_i82559);
static void InitTxRing(struct i82559* p_i82559);
static void ResetTxRing(struct i82559* p_i82559);

#ifdef CYGPKG_DEVS_ETH_ARM_IXDP2400_WRITE_EEPROM
static void program_eeprom(cyg_uint32 , cyg_uint32 , cyg_uint8 * );
#endif
#ifdef CYGPKG_NET
static int eth_set_promiscuous_mode(struct i82559* p_i82559);
#endif

// ------------------------------------------------------------------------
// We use this as a templete when writing a new MAC address into the
// eeproms. The MAC address in the first few bytes is over written
// with the correct MAC address and then the whole lot is programmed
// into the serial EEPROM. The checksum is calculated on the fly and
// sent instead of the last two bytes.
// The values are copied from the Intel EtherPro10/100+ &c devices
// in the EBSA boards.

#ifdef CYGPKG_DEVS_ETH_ARM_IXDP2400_WRITE_EEPROM

#define ee00 0x00, 0x00 // shorthand

static char eeprom_burn[126] = { 
/* halfword addresses! */
/*  0: */  0x00, 0x00,   0x00, 0x00,       0x00, 0x00,   0x03, 0x04,
/*  4: */     ee00   ,   0x01, 0x02,       0x01, 0x47,      ee00   ,
/*  8: */  0x97, 0x72,   0x05, 0x57,       0x80, 0x40,   0x00, 0x00,
/*  C: */  0x00, 0x00,      ee00   ,          ee00   ,      ee00   ,
/* 10: */     ee00   ,      ee00   ,          ee00   ,      ee00   ,
/* 14: */     ee00   ,      ee00   ,          ee00   ,      ee00   ,
/* 18: */     ee00   ,      ee00   ,          ee00   ,      ee00   ,
/* 1C: */     ee00   ,      ee00   ,          ee00   ,      ee00   ,
/* 20: */     ee00   ,      ee00   ,          ee00   ,      ee00   ,
/* 24: */     ee00   ,      ee00   ,          ee00   ,      ee00   ,
/* 28: */     ee00   ,      ee00   ,          ee00   ,      ee00   ,
/* 2C: */     ee00   ,      ee00   ,          ee00   ,      ee00   ,
/* 30: */  0x28, 0x01,      ee00   ,          ee00   ,      ee00   ,
/* 34: */     ee00   ,      ee00   ,          ee00   ,      ee00   ,
/* 38: */     ee00   ,      ee00   ,          ee00   ,      ee00   ,
/* 3C: */     ee00   ,      ee00   ,          ee00   
};
#undef ee00

#endif

// debugging/logging only:
void dump_txcb(TxCB *p_txcb);
void DisplayStatistics(void);
void update_statistics(struct i82559* p_i82559);
void dump_rfd(RFD *p_rfd, int anyway );
void dump_all_rfds( int intf );
void dump_packet(cyg_uint8 *p_buffer, int length);

// ------------------------------------------------------------------------
// utilities
// ------------------------------------------------------------------------

static // inline
void wait_for_cmd_done(long scb_ioaddr)
{
    register int CSRstatus;
    register int wait = 100000;
    do
	{
		udelay(10);
#ifdef USE_MEM_ADRS
		CSRstatus = INB(scb_ioaddr + SCBCmd) ; // Just read the command byte
#else
        CSRstatus = INB(scb_ioaddr + SCBCmd +1) ; // Just read the command byte
#endif
	}while( CSRstatus && --wait > 0);
	CYG_ASSERT( wait > 0, "wait_for_cmd_done" );
}

// Short circuit the drv_interrupt_XXX API once we are started:

static inline int Mask82559Interrupt(struct i82559* p_i82559)
{
    hal_interrupt_mask(p_i82559->vector);

    return p_i82559->vector;
}


static inline void UnMask82559Interrupt(struct i82559* p_i82559, int old)
{
    hal_interrupt_unmask(p_i82559->vector);
}

#ifdef CYGDBG_USE_ASSERTS // an indication of a debug build
static int acknowledge82559interrupt_compensating = 0;
#endif

static void Acknowledge82559Interrupt(struct i82559* p_i82559)
{
    cyg_uint32 ioaddr;
    cyg_uint16 status;
    int loops = 64;

    cyg_drv_interrupt_acknowledge(p_i82559->vector);

    // It appears that some time can be taken before the interrupt source
    // *really* quietens down... this is ugly, but effective.
    // Without it, we get "Spurious Interrupt!" failures.
    ioaddr = p_i82559->io_address; // get I/O address for 82559

    status = INW(ioaddr + SCBStatus);
    while ((0 != (status & SCB_INTACK_MASK)) && --loops >= 0) {
        OUTW( status & SCB_INTACK_MASK, ioaddr + SCBStatus);
        cyg_drv_interrupt_acknowledge(p_i82559->vector);
#ifdef CYGDBG_USE_ASSERTS
        acknowledge82559interrupt_compensating++; // verify this is executed
#endif
        status = INW(ioaddr + SCBStatus);
    }
    CYG_ASSERT( loops >= 0, "Acknowledge82559Interrupt" );
}

// ------------------------------------------------------------------------
// Memory management
//
// Simply carve off from the front of the PCI mapped window into real memory

static void *pciwindow_mem_alloc(int size)
{
    void *p_memory;
    int _size = size;

    p_memory = (void *)0;
    size = (size + 3) & ~3;
    if ( (i82559_heap_free+size) < (i82559_heap_base+i82559_heap_size) ) {
        cyg_uint32 *p;
        p_memory = (void *)i82559_heap_free;
        i82559_heap_free += size;
        for ( p = (cyg_uint32 *)p_memory; _size > 0; _size -= 4 )
            *p++ = 0;
    }
	else
	{
		printf("Couldn't get the PCI mapped memory window\n");
	}

    return p_memory;
}

// ------------------------------------------------------------------------
//
//                       GET EEPROM SIZE
//
// ------------------------------------------------------------------------
static int get_eeprom_size(long ioaddr)
{
    unsigned short retval = 0;
    int ee_addr = ioaddr + SCBeeprom;
    int i, addrbits;

    // Should already be not-selected, but anyway:
    OUTW(EE_ENB & ~EE_CS, ee_addr);
    eeprom_delay(EEPROM_ENABLE_DELAY);
    OUTW(EE_ENB, ee_addr);
    eeprom_delay(EEPROM_ENABLE_DELAY);
    
    // Shift the read command bits out.
    for (i = 2; i >= 0; i--) {
        short dataval = (6 & (1 << i)) ? EE_DATA_WRITE : 0;
        OUTW(EE_ENB | dataval               , ee_addr);
        eeprom_delay(EEPROM_SK_DELAY);
        OUTW(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr);
        eeprom_delay(EEPROM_SK_DELAY);
        OUTW(EE_ENB | dataval               , ee_addr);
        eeprom_delay(EEPROM_SK_DELAY);
    }
    // Now clock out address zero, looking for the dummy 0 data bit
    for ( i = 1; i <= 12; i++ ) {
        OUTW(EE_ENB               , ee_addr);
        eeprom_delay(EEPROM_SK_DELAY);
        OUTW(EE_ENB | EE_SHIFT_CLK, ee_addr);
        eeprom_delay(EEPROM_SK_DELAY);
        OUTW(EE_ENB               , ee_addr);
        eeprom_delay(EEPROM_SK_DELAY);
        retval = INW(ee_addr) & EE_DATA_READ;

⌨️ 快捷键说明

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