📄 if_i82559.c
字号:
#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_STATISTICSSTATISTICS 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, char *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);static voideth_dsr(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data);static cyg_uint32eth_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_LISTstatic 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_EEPROMstatic voidprogram_eeprom(cyg_uint32 ioaddr, cyg_uint32 eeprom_size, cyg_uint8 *data);static voidwrite_eeprom(long ioaddr, int location, int addr_len, unsigned short value);static intwrite_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 inlinevoid 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 voidudelay(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 # omit both from any restoration: #/ old = 0; */ return old;}static inline voidUnMask82559Interrupt(struct i82559* p_i82559, int old){#ifdef CYGPRI_DEVS_ETH_INTEL_I82559_UNMASK_INTERRUPTS CYGPRI_DEVS_ETH_INTEL_I82559_UNMASK_INTERRUPTS(p_i82559,old);#else // We must only unmask (enable) those which were unmasked before, // according to the bits in old. if (old & 1) cyg_drv_interrupt_unmask(p_i82559->vector);#ifdef CYGNUM_DEVS_ETH_INTEL_I82559_SEPARATE_MUX_INTERRUPT if (old & 2) cyg_drv_interrupt_mask(CYGNUM_DEVS_ETH_INTEL_I82559_SEPARATE_MUX_INTERRUPT);#endif#endif}static inline voidAcknowledge82559Interrupt(struct i82559* p_i82559){#ifdef CYGPRI_DEVS_ETH_INTEL_I82559_ACK_INTERRUPTS CYGPRI_DEVS_ETH_INTEL_I82559_ACK_INTERRUPTS(p_i82559);#else cyg_drv_interrupt_acknowledge(p_i82559->vector);#ifdef CYGNUM_DEVS_ETH_INTEL_I82559_SEPARATE_MUX_INTERRUPT cyg_drv_interrupt_acknowledge(CYGNUM_DEVS_ETH_INTEL_I82559_SEPARATE_MUX_INTERRUPT);#endif#endif#ifdef CYGPRI_DEVS_ETH_INTEL_I82559_INTERRUPT_ACK_LOOP CYGPRI_DEVS_ETH_INTEL_I82559_INTERRUPT_ACK_LOOP(p_i82559);#endif}static inline voidCheck82559TxLockupTimeout(struct i82559* p_i82559){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -