if_i82559.c

来自「开放源码实时操作系统源码.」· C语言 代码 · 共 1,724 行 · 第 1/5 页

C
1,724
字号

// GIBENDIAN addressing; A0 and A1 are flipped:
#define RFD_STATUS       0
#define RFD_STATUS_LO    2              // swapped
#define RFD_STATUS_HI    0              // swapped
#define RFD_LINK         4
#define RFD_RDB_ADDR     8
#define RFD_COUNT       14              // swapped
#define RFD_SIZE        12              // swapped
#define RFD_BUFFER      16
#define RFD_SIZEOF      16

#endif // CYG_ADDRESSING_IS_GIBENDIAN



// ------------------------------------------------------------------------
//
//               TRANSMIT FRAME DESCRIPTORS
//
// ------------------------------------------------------------------------

#if (CYG_BYTEORDER == CYG_MSBFIRST)

// Note that CMD/STATUS bits are endian converted - so we don't need
// to fiddle the byteorder when accessing the CMD/STATUS word!

#define TxCB_CMD_TRANSMIT   0x0400      // transmit command
#define TxCB_CMD_SF         0x0800      // 0=simplified, 1=flexible mode
#define TxCB_CMD_NC         0x0010      // 0=CRC insert by controller
#define TxCB_CMD_I          0x0020      // generate interrupt on completion
#define TxCB_CMD_S          0x0040      // suspend on completion
#define TxCB_CMD_EL         0x0080      // last command block in CBL

#define TxCB_COUNT_MASK     0x3fff
#define TxCB_COUNT_EOF      0x8000

#else // Little-endian layout

#define TxCB_COUNT_MASK     0x3fff
#define TxCB_COUNT_EOF      0x8000

#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

#endif // CYG_BYTEORDER

#ifndef CYG_ADDRESSING_IS_GIBENDIAN

// Normal addressing
#define TxCB_STATUS          0
#define TxCB_CMD             2
#define TxCB_LINK            4
#define TxCB_TBD_ADDR        8
#define TxCB_COUNT          12
#define TxCB_TX_THRESHOLD   14
#define TxCB_TBD_NUMBER     15
#define TxCB_BUFFER         16
#define TxCB_SIZEOF         16

#else // CYG_ADDRESSING_IS_GIBENDIAN

// GIBENDIAN addressing; A0 and A1 are flipped:
#define TxCB_STATUS          2          // swapped
#define TxCB_CMD             0          // swapped
#define TxCB_LINK            4
#define TxCB_TBD_ADDR        8
#define TxCB_COUNT          14          // swapped
#define TxCB_TX_THRESHOLD   13          // swapped
#define TxCB_TBD_NUMBER     12          // swapped
#define TxCB_BUFFER         16
#define TxCB_SIZEOF         16
#endif // CYG_ADDRESSING_IS_GIBENDIAN

// ------------------------------------------------------------------------
//
//                   STRUCTURES ADDED FOR PROMISCUOUS MODE
//
// ------------------------------------------------------------------------

#if (CYG_BYTEORDER == CYG_MSBFIRST)

// Note CFG CMD and STATUS swapped, so no need for endian conversion
// in code.
#define CFG_CMD_EL         0x0080
#define CFG_CMD_SUSPEND    0x0040
#define CFG_CMD_INT        0x0020
#define CFG_CMD_IAS        0x0100       // individual address setup
#define CFG_CMD_CONFIGURE  0x0200       // configure
#define CFG_CMD_MULTICAST  0x0300       // Multicast-Setup

#define CFG_STATUS_C       0x0080
#define CFG_STATUS_OK      0x0020

#else // Little-endian 

#define CFG_CMD_EL         0x8000
#define CFG_CMD_SUSPEND    0x4000
#define CFG_CMD_INT        0x2000
#define CFG_CMD_IAS        0x0001       // individual address setup
#define CFG_CMD_CONFIGURE  0x0002       // configure
#define CFG_CMD_MULTICAST  0x0003       // Multicast-Setup

#define CFG_STATUS_C       0x8000
#define CFG_STATUS_OK      0x2000

#endif  // CYG_BYTEORDER

#ifndef CYG_ADDRESSING_IS_GIBENDIAN

// Normal addressing
#define CFG_STATUS          0
#define CFG_CMD             2
#define CFG_CB_LINK_OFFSET  4
#define CFG_BYTES           8
#define CFG_SIZEOF          32

#else // CYG_ADDRESSING_IS_GIBENDIAN

// GIBENDIAN addressing; A0 and A1 are flipped:
#define CFG_STATUS          2
#define CFG_CMD             0
#define CFG_CB_LINK_OFFSET  4
#define CFG_BYTES           8
#define CFG_SIZEOF          32

#endif // CYG_ADDRESSING_IS_GIBENDIAN

// Normal addressing
#define CFG_MC_LIST_BYTES 8
#define CFG_MC_LIST_DATA 10

// ------------------------------------------------------------------------
//
//                       STATISTICAL COUNTER STRUCTURE
//
// ------------------------------------------------------------------------
#ifdef KEEP_STATISTICS
STATISTICS statistics[CYGNUM_DEVS_ETH_INTEL_I82559_DEV_COUNT];
I82559_COUNTERS i82559_counters[CYGNUM_DEVS_ETH_INTEL_I82559_DEV_COUNT];
#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


// ------------------------------------------------------------------------
// Use arrays provided by platform header to verify pointers.
#ifdef CYGDBG_USE_ASSERTS
#define CHECK_NDP_SC_LINK()                                             \
    CYG_MACRO_START                                                     \
    int i, valid_netdev = 0, valid_sc = 0;                              \
    for(i = 0; i < CYGNUM_DEVS_ETH_INTEL_I82559_DEV_COUNT; i++) {       \
        if (i82559_netdev_array[i] == ndp) valid_netdev = 1;            \
        if (i82559_sc_array[i] == sc) valid_sc = 1;                     \
        if (valid_sc || valid_netdev) break;                            \
    }                                                                   \
    CYG_ASSERT( valid_netdev, "Bad ndp" );                              \
    CYG_ASSERT( valid_sc, "Bad sc" );                                   \
    CYG_ASSERT( (void *)p_i82559 == i82559_sc_array[i]->driver_private, \
                "sc pointer bad" );                                     \
    CYG_MACRO_END
#else
#define CHECK_NDP_SC_LINK()
#endif

#define IF_BAD_82559( _p_ )                                             \
if (({                                                                  \
    int i, valid_p = 0;                                                 \
    for(i = 0; i < CYGNUM_DEVS_ETH_INTEL_I82559_DEV_COUNT; i++) {       \
        if (i82559_priv_array[i] == (_p_)) {                            \
            valid_p = 1;                                                \
            break;                                                      \
        }                                                               \
    }                                                                   \
    CYG_ASSERT(valid_p, "Bad pointer-to-i82559");                       \
    (!valid_p);                                                         \
}))

// ------------------------------------------------------------------------
//
// 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 i82559_restart(struct i82559 *p_i82559);
static int eth_set_mac_address(struct i82559* p_i82559, cyg_uint8 *addr, int eeprom );

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);

#if defined(CYGHWR_DEVS_ETH_INTEL_I82559_MISSED_INTERRUPT) || \
  defined(CYGNUM_DEVS_ETH_INTEL_I82559_SEPARATE_MUX_INTERRUPT) || \
  !defined(CYGPKG_IO_ETH_DRIVERS_STAND_ALONE)
static void
eth_dsr(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data);
#endif
static cyg_uint32
eth_isr(cyg_vector_t vector, cyg_addrword_t data);

static int i82559_configure(struct i82559* p_i82559, int promisc,
                            int oversized, int multicast_all);
#ifdef ETH_DRV_SET_MC_LIST
static int i82559_set_multicast(struct i82559* p_i82559,
                                int num_addrs,
                                cyg_uint8 *address_list );
#endif // ETH_DRV_SET_MC_ALL
#ifdef CYGPKG_DEVS_ETH_INTEL_I82559_WRITE_EEPROM
static void
program_eeprom(cyg_uint32 ioaddr, cyg_uint32 eeprom_size, cyg_uint8 *data);
static void
write_eeprom(long ioaddr, int location, int addr_len, unsigned short value);
static int
write_enable_eeprom(long ioaddr,  int addr_len);
#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);

static void i82559_stop( struct eth_drv_sc *sc );

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

typedef enum {
    WAIT_RU,                            // wait before RU cmd
    WAIT_CU                             // wait before CU cmd
} cmd_wait_t;

static inline
void 
wait_for_cmd_done(long scb_ioaddr, cmd_wait_t type)
{
    register int status;
    register int wait;

    wait = 0x100000;
    do status = INW(scb_ioaddr + SCBCmd) /* nothing */ ;
    while( (0 != ((CU_CMD_MASK | RU_CMD_MASK) & status)) && --wait >= 0);

    if ( wait <= 0 ) {
        // Then we timed out; reset the device and try again...
        OUTL(I82559_SELECTIVE_RESET, scb_ioaddr + SCBPort);
#ifdef CYGDBG_USE_ASSERTS
        missed_interrupt.waitcmd_timeouts++;
#endif
        wait = 0x100000;
        do status = INW(scb_ioaddr + SCBCmd) /* nothing */;
        while( (0 != ((CU_CMD_MASK | RU_CMD_MASK) & status)) && --wait >= 0);
    }

    // special case - don't complain about RUC_ADDR_LOAD as it doesn't clear
    // on some silicon
    if ( RUC_ADDR_LOAD != (status & RU_CMD_MASK) )
        CYG_ASSERT( wait > 0, "wait_for_cmd_done: cmd busy" );

    if (WAIT_CU == type) {
        // Also check CU is idle
        wait = 0x100000;
        do status = INW(scb_ioaddr + SCBStatus) /* nothing */;
        while( (status & CU_STATUS_MASK) && --wait >= 0);
        if ( wait <= 0 ) {
            // Then we timed out; reset the device and try again...
            OUTL(I82559_SELECTIVE_RESET, scb_ioaddr + SCBPort);
#ifdef CYGDBG_USE_ASSERTS
            missed_interrupt.waitcmd_timeouts_cu++;
#endif
            wait = 0x100000;
            do status = INW(scb_ioaddr + SCBCmd) /* nothing */;
            while( (0 != ((CU_CMD_MASK | RU_CMD_MASK) & status)) && --wait >= 0);
        }

        CYG_ASSERT( wait > 0, "wait_for_cmd_done: CU busy" );

    } else if (WAIT_RU == type) {
        // Can't see any active state in the doc to check for 
    }
}

// ------------------------------------------------------------------------

static void
udelay(int delay)
{
    CYGACC_CALL_IF_DELAY_US(delay);
}

// ------------------------------------------------------------------------
// If we are demuxing for all interrupt sources, we must mask and unmask
// *all* interrupt sources together.

static inline int 
Mask82559Interrupt(struct i82559* p_i82559)
{
    int old = 0;

#ifdef CYGPRI_DEVS_ETH_INTEL_I82559_MASK_INTERRUPTS
    CYGPRI_DEVS_ETH_INTEL_I82559_MASK_INTERRUPTS(p_i82559,old);
#else
//    if (query_enabled)
    old |= 1;
    cyg_drv_interrupt_mask(p_i82559->vector);
#ifdef CYGNUM_DEVS_ETH_INTEL_I82559_SEPARATE_MUX_INTERRUPT
//    if (query_enabled)
    old |= 2;
    cyg_drv_interrupt_mask(CYGNUM_DEVS_ETH_INTEL_I82559_SEPARATE_MUX_INTERRUPT);
#endif
#endif
    /* it may prove necessary to do something like this
    if ( mybits != (mybits & old) )
        /# then at least one of them was disabled, so

⌨️ 快捷键说明

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