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

📄 if_mahwah.c

📁 Intel XScale PXA255 引导Linux的Redboot 版bootloader源代码!
💻 C
📖 第 1 页 / 共 5 页
字号:
// ------------------------------------------------------------------------// Instantiate the interfaces that we have:// number of interfaces#define MAX_82559 CYGNUM_DEVS_ETH_ARM_MAHWAH_DEV_COUNT I82559 i82559[MAX_82559];               // i82559 device info. structure// eth0ETH_DRV_SC(mahwah_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(mahwah_netdev0,                 "mahwah-0",                 mahwah_i82559_init,                 &mahwah_sc0);#if (MAX_82559 > 1)// eth1ETH_DRV_SC(mahwah_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(mahwah_netdev1,                 "mahwah-1",                 mahwah_i82559_init,                 &mahwah_sc1);#elseint mahwah_netdev1 = -1; // for asserts about valid addressesint mahwah_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 *)&mahwah_netdev0) ||               \                ((void *)ndp == (void *)&mahwah_netdev1), "Bad ndp" );    \    CYG_ASSERT( ((void *)sc == (void *)&mahwah_sc0) ||                    \                ((void *)sc == (void *)&mahwah_sc1), "Bad sc" );          \    CYG_ASSERT( (void *)p_i82559 == sc->driver_private, "sc pointer bad" );\CYG_MACRO_END// ------------------------------------------------------------------------//// 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_MAHWAH_WRITE_EEPROMstatic void program_eeprom(cyg_uint32 , cyg_uint32 , cyg_uint8 * );#endif#ifdef CYGPKG_NETstatic int eth_set_promiscuous_mode(struct i82559* p_i82559);#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 // inlinevoid wait_for_cmd_done(long scb_ioaddr){    register int CSRstatus;    register int wait = 0x100000;    do CSRstatus = INB(scb_ioaddr + SCBCmd) ;    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){    int cpu_intr;    int old;    int mybits =         (1 << (p_i82559->vector)) |        (1 << CYGNUM_HAL_INTERRUPT_PCI_IRQ);    HAL_DISABLE_INTERRUPTS( cpu_intr );    old = *SA110_IRQCONT_IRQENABLE;    *SA110_IRQCONT_IRQENABLECLEAR = mybits; // clear mybits    HAL_RESTORE_INTERRUPTS( cpu_intr );    /* 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 void UnMask82559Interrupt(struct i82559* p_i82559, int old){    // We must only unmask (enable) those which were unmasked before,    // according to the bits in old.    *SA110_IRQCONT_IRQENABLESET = old &        ((1 << (p_i82559->vector)) |         (1 << CYGNUM_HAL_INTERRUPT_PCI_IRQ));}#ifdef CYGDBG_USE_ASSERTS // an indication of a debug buildstatic int acknowledge82559interrupt_compensating = 0;#endifstatic void Acknowledge82559Interrupt(struct i82559* p_i82559){    int sources, mask;    cyg_uint32 ioaddr;    cyg_uint16 status;    int loops = 64;    // SA110/285 does nothing in interrupt_acknowledge, so we can comment these    // all out.  So this routine really boils down to    //   "wait for the device to stop interrupting before we unmask"    // The calls are all left in place, for documentary purposes.    cyg_drv_interrupt_acknowledge(p_i82559->vector);    cyg_drv_interrupt_acknowledge(CYGNUM_HAL_INTERRUPT_PCI_IRQ);    // 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    mask = (1 << p_i82559->vector); // Do not include the MUX vector or we    sources = *SA110_IRQCONT_IRQSTATUS; //...get hung on the other 82559    status = INW(ioaddr + SCBStatus);    while ( ((0 != (sources & mask)) || (0 != (status & SCB_INTACK_MASK)))            && --loops >= 0) {        OUTW( status & SCB_INTACK_MASK, ioaddr + SCBStatus);        cyg_drv_interrupt_acknowledge(p_i82559->vector);        cyg_drv_interrupt_acknowledge(CYGNUM_HAL_INTERRUPT_PCI_IRQ);#ifdef CYGDBG_USE_ASSERTS        acknowledge82559interrupt_compensating++; // verify this is executed#endif        sources = *SA110_IRQCONT_IRQSTATUS;        status = INW(ioaddr + SCBStatus);    }    CYG_ASSERT( loops >= 0, "Acknowledge82559Interrupt" );}static void udelay(int delay){  int i;  // the loop is going to take 3 ticks.  At 228 MHz, to give uS, multiply  // by 228/3 = 76 near enough.  No volatile is needed on i; gcc recognizes  // delay loops and does NOT elide them.  for ( i = 76 * delay; i ; i--)    ;}// ------------------------------------------------------------------------// Memory management//// Simply carve off from the front of the PCI mapped window into real memorystatic void *pciwindow_mem_alloc(int size){    void *p_memory;    int _size = size;    CYG_ASSERT(        (CYGHWR_HAL_ARM_PCI_MEM_MAP_BASE <= (int)i82559_heap_free)        &&        ((CYGHWR_HAL_ARM_PCI_MEM_MAP_BASE +           CYGHWR_HAL_ARM_PCI_MEM_MAP_SIZE) > (int)i82559_heap_free)        &&        (0 < i82559_heap_size)        &&        (CYGHWR_HAL_ARM_PCI_MEM_MAP_SIZE >= i82559_heap_size)        &&        (CYGHWR_HAL_ARM_PCI_MEM_MAP_BASE == (int)i82559_heap_base),        "Heap variables corrupted" );    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;    }    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;        if ( 0 == retval )            break; // The dummy zero est arrive'    }#ifdef DEBUG_EE    os_printf( "eeprom data bits %d (ioaddr %x)\n", i, ee_addr );#endif    if ( 6 != i && 8 != i ) {#ifdef DEBUG_EE        os_printf( "*****EEPROM data bits not 6 or 8*****\n" );#endif        i = 6;    }    addrbits = i;    // clear the dataval, leave the clock low to read in the data regardless    OUTW(EE_ENB, ee_addr);    eeprom_delay(1);        retval = INW(ee_addr);    if ( (EE_DATA_READ & retval) != 0 ) {#ifdef DEBUG_EE        os_printf( "Size EEPROM: Dummy data bit not 0, reg %x\n" , retval );#endif    }    eeprom_delay(1);        for (i = EE_TOP_DATA_BIT; i >= 0; i--) {        OUTW(EE_ENB | EE_SHIFT_CLK, ee_addr);        eeprom_delay(EEPROM_SK_DELAY);        retval = INW(ee_addr);        eeprom_delay(EEPROM_SK_DELAY);        OUTW(EE_ENB, ee_addr);        eeprom_delay(EEPROM_SK_DELAY);    }        // Terminate the EEPROM access.    OUTW(EE_ENB & ~EE_CS, ee_addr);    eeprom_delay(EEPROM_DONE_DELAY);        return addrbits;}// ------------------------------------------------------------------------////                       READ EEPROM//// ------------------------------------------------------------------------static int read_eeprom(long ioaddr, int location, int addr_len){    unsigned short retval = 0;    int ee_addr = ioaddr + SCBeeprom;    int read_cmd = location | EE_READ_CMD(addr_len);    int i, tries = 10; try_again:    // 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, changing only one bit per time.    for (i = EE_TOP_CMD_BIT(addr_len); i >= 0; i--) {        short dataval = (read_cmd & (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);    }    // clear the dataval, leave the clock low    OUTW(EE_ENB, ee_addr);    eeprom_delay(1);        retval = INW(ee_addr);    // This should show a zero in the data read bit to confirm that the    // address transfer is compelete.  If not, go to the start and try    // again!    if ( (0 != (retval & EE_DATA_READ)) && (tries-- > 0) ) {    // Terminate the EEPROM access.        OUTW(EE_ENB & ~EE_CS, ee_addr);        eeprom_delay(EEPROM_DONE_DELAY);#ifdef DEBUG_EE        os_printf( "Warning: Retrying EEPROM read word %d, address %x, try %d\n",                   location,  ee_addr, tries+1 );#endif        goto try_again;    }    // This fires with one device on one of the customer boards!    // (but is OK on all other h/w.  Worrying huh.)    if ( (EE_DATA_READ & retval) != 0 ) {#ifdef DEBUG_EE        os_printf( "Read EEPROM: Dummy data bit not 0, reg %x\n" , retval );#endif    }    eeprom_delay(1);    retval = 0;    for (i = EE_TOP_DATA_BIT; i >= 0; i--) {        OUTW(EE_ENB | EE_SHIFT_CLK, ee_addr);        eeprom_delay(EEPROM_SK_DELAY);        retval = (retval << 1) | ((INW(ee_addr) & EE_DATA_READ) ? 1 : 0);        eeprom_delay(EEPROM_SK_DELAY);        OUTW(EE_ENB, ee_addr);        eeprom_delay(EEPROM_SK_DELAY);    }    

⌨️ 快捷键说明

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