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

📄 if_iq80310.c

📁 基于ecos的redboot
💻 C
📖 第 1 页 / 共 5 页
字号:
    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;
}

// ------------------------------------------------------------------------
//
//                       MDI
//
// ------------------------------------------------------------------------

#define SPEED_NOLINK	0
#define SPEED_10M		10
#define SPEED_100M		100

// MDI Control Register
typedef union
{
    struct
    {
    	cyg_uint32 data   : 16;	// data to write or data read
    	cyg_uint32 regAdd  : 5;	// PHY register address
    	cyg_uint32 phyAdd  : 5;	// PHY address
    	cyg_uint32 op      : 2;	// opcode, 1 for MDI write, 2 for MDI read
    	cyg_uint32 ready   : 1;	// 1 = operation complete
    	cyg_uint32 intEnab : 1;	// 1 = interrupt at end of cycle
    	cyg_uint32 rsrv    : 2;	// reserved
    } bits;
    cyg_uint32 word;
} MDICTL;

static cyg_uint16 readMDI (long ioaddr, cyg_uint8 phyAdd, cyg_uint8 regAdd)
{
    int mdi_addr = ioaddr + SCBCtrlMDI;
    MDICTL mdiCtrl;
    int num_ms = 0; 

    // prepare for the MDI operation
    mdiCtrl.bits.ready = MDI_NOT_READY;
    mdiCtrl.bits.intEnab = MDI_POLLED;	// no interrupts
    mdiCtrl.bits.op = MDI_READ_OP;
    mdiCtrl.bits.phyAdd = phyAdd & 0x1f;
    mdiCtrl.bits.regAdd = regAdd & 0x1f;

    // start the operation
    OUTL(mdiCtrl.word, mdi_addr);

    // delay a bit
    udelay (1000);

    // poll for completion */
    mdiCtrl.word = INL(mdi_addr);

    while ((mdiCtrl.bits.ready == MDI_NOT_READY) && (num_ms != 2000)) { // wait max 2secs
	mdiCtrl.word = INL(mdi_addr);
	udelay(1000);
	num_ms++;
    }	
	
    if (num_ms >= 2000)	{
	CYG_FAIL ("readMDI Timeout!\n");
	return -1;
    }
    else 
	return (cyg_uint16)mdiCtrl.bits.data;
}


static void writeMDI (long ioaddr, cyg_uint8 phyAdd, cyg_uint8 regAdd, cyg_uint16 data)
{
    int mdi_addr = ioaddr + SCBCtrlMDI;
    register MDICTL mdiCtrl;
    int num_ms = 0;

    // prepare for the MDI operation
    mdiCtrl.bits.ready = MDI_NOT_READY;
    mdiCtrl.bits.intEnab = MDI_POLLED;  // no interrupts
    mdiCtrl.bits.op = MDI_WRITE_OP;
    mdiCtrl.bits.phyAdd = phyAdd & 0x1f;
    mdiCtrl.bits.regAdd = regAdd & 0x1f;
    mdiCtrl.bits.data = data & 0xffff;

    // start the operation
    OUTL(mdiCtrl.word, mdi_addr);

    // delay a bit
    udelay(1000);

    // poll for completion
    mdiCtrl.word = INL(mdi_addr);

    while ((mdiCtrl.bits.ready == MDI_NOT_READY) && (num_ms != 2000)) {
	mdiCtrl.word = INL(mdi_addr);
	udelay(1000);
	num_ms++;
    }	
    if (num_ms >= 2000)
	CYG_FAIL ("writeMDI Timeout!\n");
 
    return;
}

static int initPHY (long ioaddr, cyg_uint32 device_type)
{
    cyg_uint16 temp_reg;
    cyg_uint8 revision;

    // strip off revision and phy. id information
    revision = (cyg_uint8)(device_type & REVISION_MASK);
    device_type &= ~REVISION_MASK;

    switch (device_type) {
      case ICS1890_PHY_ID: 
	temp_reg = readMDI(ioaddr, MDI_DEFAULT_PHY_ADDR, MDI_PHY_CTRL); // get ready for loopback setting
	writeMDI(ioaddr, MDI_DEFAULT_PHY_ADDR, MDI_PHY_CTRL, temp_reg);
	break;
		
      case DP83840_PHY_ID:  // set the Intel-specified "must set" bits
	temp_reg = readMDI(ioaddr, MDI_DEFAULT_PHY_ADDR, DP83840_PCR_REG);
	temp_reg |= (PCR_TXREADY_SEL | PCR_FCONNECT);
	writeMDI (ioaddr, MDI_DEFAULT_PHY_ADDR, DP83840_PCR_REG, temp_reg);

	// get ready for loopback setting
	temp_reg = readMDI (ioaddr, MDI_DEFAULT_PHY_ADDR, DP83840_LOOPBACK_REG);
	temp_reg &= CLEAR_LOOP_BITS;
	writeMDI (ioaddr, MDI_DEFAULT_PHY_ADDR, DP83840_LOOPBACK_REG, temp_reg);
	break;

      case I82553_PHY_ID:
      case I82553_REVAB_PHY_ID:
      case I82555_PHY_ID:
	break;

      default:
	return 1;
	break;
  }

  return 0;
}





// ------------------------------------------------------------------------
//
//                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 bool
iq80310_i82559_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;
    cyg_uint16 checksum;
    int count;
    int i, ints;
    int addr_length;
    cyg_uint8 mac_address[6];
    struct i82559 *p_i82559;

#ifdef DEBUG
    db_printf("iq80310_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" );
#endif
            return 0;
        }
    }

    if ( ! p_i82559->found ) // no device on PCI bus
        return (0);

    ioaddr = p_i82559->io_address; // get I/O address for 82559

#ifdef DEBUG
    os_printf("Init82559 %d @ %x\n82559 Self Test\n",
              p_i82559->index, (int)ndp);
#endif

    ints = Mask82559Interrupt(p_i82559);

    wait_for_cmd_done(ioaddr); // make sure no command operating

    i82559_reset(p_i82559);

    // Perform a system self-test. (get enough mem to round address)
    if ( (selftest = (cyg_uint32)pciwindow_mem_alloc(32) ) == 0)
        return (0);
    p_selftest = (cyg_uint32 *) ((selftest + 15) & ~0xf);

    p_selftest[0] = p_selftest[1] = -1;
        
    OUTL( (VIRT_TO_BUS(p_selftest)) | I82559_SELFTEST, ioaddr + SCBPort);
    count = 0x1FFFFF;                // Timeout for self-test.
    do {
        udelay(10);
    } while ( (p_selftest[1] == -1)  &&  (--count >= 0) );

    Acknowledge82559Interrupt(p_i82559);
    UnMask82559Interrupt(p_i82559, ints );
    
    if (count < 0) {
        // Test timed out.
#ifdef DEBUG
        os_printf("Self test failed\n");
#endif
        return (0);
    }
#ifdef DEBUG
    os_printf("  General self-test: %s.\n"
              "  serial sub-system self-test: %s.\n"
              "  Internal registers self-test: %s.\n"
              "  ROM checksum self-test: %s (%08X).\n",
              p_selftest[1] & 0x1000 ? "failed" : "passed",
              p_selftest[1] & 0x0020 ? "failed" : "passed",
              p_selftest[1] & 0x0008 ? "failed" : "passed",
              p_selftest[1] & 0x0004 ? "failed" : "passed",
              p_selftest[0]);
#endif

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

    for (checksum = 0, i = 0, count = 0; count < 64; 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) {
            mac_address[i++] = value & 0xFF;
            mac_address[i++] = (value >> 8) & 0xFF;
        }
    }

    // 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 0
    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
#endif
    {
        p_i82559->mac_addr_ok = 1;
#ifdef DEBUG_EE
        os_printf("Valid EEPROM checksum\n");
#endif
    }
#ifdef DEBUG
    os_printf("MAC Address = %02X %02X %02X %02X %02X %02X\n",
              mac_address[0], mac_address[1], mac_address[2], mac_address[3],
              mac_address[4], mac_address[5]);
#endif

    // record the MAC address in the device structure
    p_i82559->mac_address[0] = mac_address[0];
    p_i82559->mac_address[1] = mac_address[1];
    p_i82559->mac_address[2] = mac_address[2];
    p_i82559->mac_address[3] = mac_address[3];
    p_i82559->mac_address[4] = mac_address[4];
    p_i82559->mac_address[5] = mac_address[5];
    
    // and record the net dev pointer
    p_i82559->ndp = (void *)ndp;
    
    InitRxRing(p_i82559);
    InitTxRing(p_i82559);

    // Initialize upper level driver
    if ( p_i82559->mac_addr_ok )
        (sc->funs->eth_drv->init)(sc, &(p_i82559->mac_address[0]) );
    else
        (sc->funs->eth_drv->init)(sc, 0 );

    return (1);
}

// ------------------------------------------------------------------------
//
//  Function : i82559_start
//
// ------------------------------------------------------------------------
static void i82559_start( struct eth_drv_sc *sc,
                          unsigned char *enaddr, int flags )
{
    struct i82559 *p_i82559;
    cyg_uint32 ioaddr, phy_id;
    cyg_uint16 phy_addr_reg, temp1, temp2;
    int broadcom_flag = false;
    int link_speed = SPEED_NOLINK;
#ifdef KEEP_STATISTICS
    void *p_statistics;
#endif
#ifdef CYGPKG_NET
    struct ifnet *ifp = &sc->sc_arpcom.ac_if;
#endif

    p_i82559 = (struct i82559 *)sc->driver_private;
    
    IF_BAD_82559( p_i82559 ) {
#ifdef DEBUG
        os_printf( "i82559_start: Bad device pointer %x\n", p_i82559 );
#endif
        return;
    }

    if ( ! p_i82559->mac_addr_ok ) {
#ifdef DEBUG
        os_printf("i82559_start %d: invalid MAC address, "
                  "can't bring up interface\n",
                  p_i82559->index );
#endif
        return;
    }

    if ( p_i82559->active )
        i82559_stop( sc );

    ioaddr = p_i82559->io_address; // get 82559's I/O address

    phy_id = readMDI(ioaddr ,MDI_DEFAULT_PHY_ADDR, MDI_PHY_ID_1) << 16;
    phy_id |= readMDI(ioaddr ,MDI_DEFAULT_PHY_ADDR, MDI_PHY_ID_2);

    if ((phy_id & 0xfffffff0) == I82555_PHY_ID)	{
#ifdef DEBUG
	os_printf ("Intel 82555/558 PHY detected...\n");
#endif
	// dummy read for reliable status
	(void)readMDI (ioaddr, MDI_DEFAULT_PHY_ADDR, MDI_PHY_STAT);
    
	temp1 = readMDI (ioaddr, MDI_DEFAULT_PHY_ADDR, MDI_PHY_STAT);

	phy_addr_reg = readMDI (ioaddr, MDI_DEFAULT_PHY_ADDR, I82555_STATCTRL_REG);

⌨️ 快捷键说明

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