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

📄 if_i82559.c

📁 intel82559的以太网驱动
💻 C
📖 第 1 页 / 共 5 页
字号:
#ifdef CYGHWR_DEVS_ETH_INTEL_I82559_RESET_TIMEOUT#ifdef CYGHWR_DEVS_ETH_INTEL_I82559_TIMEOUT_FIRED    int ints = Mask82559Interrupt(p_i82559);    if ( p_i82559->tx_in_progress &&        (p_i82559->tx_descriptor_timeout == p_i82559->tx_descriptor_active) ) {        if ( CYGHWR_DEVS_ETH_INTEL_I82559_TIMEOUT_FIRED( p_i82559->platform_timeout ) ) {            // Then reset the device; the TX unit is locked up.            cyg_uint32 ioaddr = p_i82559->io_address;            // Wait some time afterwards for chip to settle.            OUTL(I82559_SELECTIVE_RESET, ioaddr + SCBPort);#ifdef CYGDBG_USE_ASSERTS            missed_interrupt.lockup_timeouts++;#endif            udelay(20);        }    }    else {        // All is well:        CYGHWR_DEVS_ETH_INTEL_I82559_RESET_TIMEOUT( p_i82559->platform_timeout );        p_i82559->tx_descriptor_timeout = p_i82559->tx_descriptor_active;    }    UnMask82559Interrupt(p_i82559,ints);#endif#endif}// ------------------------------------------------------------------------// 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_INTEL_I82559_PCI_MEM_MAP_BASE <= (int)i82559_heap_free)        &&        ((CYGHWR_INTEL_I82559_PCI_MEM_MAP_BASE +           CYGHWR_INTEL_I82559_PCI_MEM_MAP_SIZE) > (int)i82559_heap_free)        &&        (0 < i82559_heap_size)        &&        (CYGHWR_INTEL_I82559_PCI_MEM_MAP_SIZE >= i82559_heap_size)        &&        (CYGHWR_INTEL_I82559_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;    }#ifdef CYGHWR_DEVS_ETH_INTEL_I82559_PCIMEM_DISCONTIGUOUS    // Then the underlying physical address can have breaks in it.    // We cannot use such a block, clearly, so we just discard and re-do.    if ( p_memory ) {        char *bpm = (char *)VIRT_TO_BUS( p_memory );        char *bmf = (char *)VIRT_TO_BUS( i82559_heap_free );                if ( bpm + size != bmf ) {            // then we found a break; retry:            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;            }        }    }#endif    CYG_ASSERT(        NULL == p_memory ||        VIRT_TO_BUS( p_memory ) + size == VIRT_TO_BUS( i82559_heap_free ),        "Discontiguous PCI memory in real addresses" );    return p_memory;}// ------------------------------------------------------------------------////                       GET EEPROM SIZE//// ------------------------------------------------------------------------#ifndef CYGHWR_DEVS_ETH_INTEL_I82559_HAS_NO_EEPROMstatic intget_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 && 1 != i) {#ifdef DEBUG_EE        os_printf( "*****EEPROM data bits not 6, 8 or 1*****\n" );#endif        i = 6; // guess, to complete this routine        addrbits = 1; // Flag no eeprom here.    }    else        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 intread_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);    }        // Terminate the EEPROM access.    OUTW(EE_ENB & ~EE_CS, ee_addr);    eeprom_delay(EEPROM_DONE_DELAY);        return retval;}static intread_eeprom_esa(struct i82559 *p_i82559, char *addr){    int addr_length, i, count;    cyg_uint16 checksum;    cyg_uint32 ioaddr = p_i82559->io_address;    // read eeprom and get 82559's mac address    addr_length = get_eeprom_size(ioaddr);    // (this is the length of the *EEPROM*s address, not MAC address)    // If length is 1, it _probably_ means there's no EEPROM    // present.  Couldn't find an explicit mention of this in the    // docs, but length=1 appears to be the behaviour in that case.    if (1 == addr_length) {#ifdef DEBUG_EE	os_printf("Error: No EEPROM present for device %d\n", 		  p_i82559->index);#endif    } else {	for (checksum = 0, i = 0, count = 0; count < (1 << addr_length); count++) {	    cyg_uint16 value;	    // read word from eeprom	    value = read_eeprom(ioaddr, count, addr_length);#ifdef DEBUG_EE	    os_printf( "%2d: %04x\n", count, value );#endif	    checksum += value;	    if (count < 3) {		addr[i++] = value & 0xFF;		addr[i++] = (value >> 8) & 0xFF;	    }	}#ifndef CYGHWR_DEVS_ETH_INTEL_I82559_HAS_ONE_EEPROM_WITHOUT_CRC	// If the EEPROM checksum is wrong, the MAC address read	// from the EEPROM is probably wrong as well. In that	// case, we don't set mac_addr_ok, but continue the	// initialization. If then somebody calls i82559_start	// without calling eth_set_mac_address() first, we refuse	// to bring up the interface, because running with an	// invalid MAC address is not a very brilliant idea.        	if ((checksum & 0xFFFF) != 0xBABA)  {	    // selftest verified checksum, verify again#ifdef DEBUG_EE	    os_printf("Warning: Invalid EEPROM checksum %04X for device %d\n",		      checksum, p_i82559->index);#endif	} else // trailing block#endif // ! CYGHWR_DEVS_ETH_INTEL_I82559_HAS_ONE_EEPROM_WITHOUT_CRC        {#ifdef DEBUG_EE	    os_printf("Valid EEPROM checksum\n");#endif	    return 1;	}    }    return 0;}#endif // ! CYGHWR_DEVS_ETH_INTEL_I82559_HAS_NO_EEPROM// ------------------------------------------------------------------------////                NETWORK INTERFACE INITIALIZATION////  Function : Init82559////  Description ://       This routine resets, configures, and initializes the chip.//       It also clears the ethernet statistics structure, and selects//       which statistics are supported by this driver.//// ------------------------------------------------------------------------static booli82559_init(struct cyg_netdevtab_entry * ndp){    static int initialized = 0; // only probe PCI et al *once*    struct eth_drv_sc *sc;    cyg_uint32 selftest;    volatile cyg_uint32 *p_selftest;    cyg_uint32 ioaddr;    int count;    int ints;    struct i82559 *p_i82559;    cyg_uint8 mac_address[ETHER_ADDR_LEN];#ifdef DEBUG    //    db_printf("intel_i82559_init\n");#endif    sc = (struct eth_drv_sc *)(ndp->device_instance);    p_i82559 = (struct i82559 *)(sc->driver_private);    IF_BAD_82559( p_i82559 ) {#ifdef DEBUG        os_printf( "Bad device private pointer %x\n", sc->driver_private );#endif        return 0;    }    CHECK_NDP_SC_LINK();    if ( 0 == initialized++ ) {        // then this is the first time ever:        if ( ! pci_init_find_82559s() ) {#ifdef DEBUG            os_printf( "pci_init_find_82559s failed\n" );#endif

⌨️ 快捷键说明

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