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

📄 if_iq80310.c

📁 基于ecos的redboot
💻 C
📖 第 1 页 / 共 5 页
字号:

	if (temp1 & MDI_STAT_LINK) // speed only valid with good LNK
	    link_speed = (phy_addr_reg & I82555_100_MBPS) ? SPEED_100M : SPEED_10M;
#ifdef DEBUG
	else
	    os_printf ("Connect Speed is NOT VALID\n");
#endif
    }

    if ((phy_id & 0xfffffff0) == ICS1890_PHY_ID) {
#ifdef DEBUG
	os_printf ("Integrated Circuit Systems ICS1890 PHY detected...\n");
	os_printf ("Revision = %c\n", 'A' + (phy_id & REVISION_MASK));
#endif
	// dummy read for reliable status
	(void)readMDI (ioaddr, MDI_DEFAULT_PHY_ADDR, ICS1890_QUICKPOLL_REG);
	temp1 = readMDI (ioaddr, MDI_DEFAULT_PHY_ADDR, ICS1890_QUICKPOLL_REG);

	if (temp1 & QUICK_LINK_VALID) // speed only valid with good LNK
	    link_speed = (temp1 & QUICK_100_MBPS) ? SPEED_100M : SPEED_10M;
#ifdef DEBUG
	else
	    os_printf ("Connect Speed is NOT VALID\n");
#endif
    }

    if ((phy_id & 0xfffffff0) == DP83840_PHY_ID) {
#ifdef DEBUG
	os_printf ("National DP83840 PHY detected...\n");
	os_printf ("Revision = %c\n", 'A' + (phy_id & REVISION_MASK));
#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, DP83840_PHY_ADDR_REG);

	if (temp1 & MDI_STAT_LINK) // speed only valid with good LNK
	    link_speed = (phy_addr_reg & PHY_ADDR_SPEED_10_MBPS) ? SPEED_10M : SPEED_100M;
#ifdef DEBUG
	else
	    os_printf ("Connect Speed is NOT VALID\n");
#endif
    }

    if ((phy_id & 0xfffffff0) == I82553_PHY_ID)	{
#ifdef DEBUG
	os_printf ("Intel 82553 PHY detected...\n");
	os_printf ("Revision = %c\n", 'A' + (phy_id & REVISION_MASK));
#endif
	broadcom_flag = true;
    }

    if (phy_id == I82553_REVAB_PHY_ID) {
#ifdef DEBUG
	os_printf ("Intel 82553 PHY detected...\n");
	os_printf ("Revision = B\n");
#endif
	broadcom_flag = true;
    }

    if (broadcom_flag == true) {
	temp2 = readMDI (ioaddr, MDI_DEFAULT_PHY_ADDR, I82553_PHY_EXT_REG0);

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

	if (temp1 & MDI_STAT_LINK) { // speed only valid with good LNK
	    link_speed = (temp2 & EXT_REG0_100_MBPS) ? SPEED_100M : SPEED_10M;
#ifdef DEBUG
	} else {
	    os_printf ("Connect Speed is NOT VALID\n");
#endif
	}
    }

#ifdef KEEP_STATISTICS
#ifdef CYGDBG_DEVS_ETH_ARM_IQ80310_KEEP_82559_STATISTICS
    p_i82559->p_statistics =
        p_statistics = pciwindow_mem_alloc(sizeof(I82559_COUNTERS));
    memset(p_statistics, 0xFFFFFFFF, sizeof(I82559_COUNTERS));
    wait_for_cmd_done(ioaddr); // make sure no command operating
                                        // set statistics dump address
    OUTL(VIRT_TO_BUS(p_statistics), ioaddr + SCBPointer);
    OUTW(SCB_M | CU_STATSADDR, ioaddr + SCBCmd);

    wait_for_cmd_done(ioaddr); // make sure no command operating
    OUTW(SCB_M | CU_DUMPSTATS, ioaddr + SCBCmd); // start register dump
#endif
#endif

    // Set the base address
    wait_for_cmd_done(ioaddr);
    OUTL(0, ioaddr + SCBPointer);       // load ru base address = 0
    OUTW(SCB_M | RUC_ADDR_LOAD, ioaddr + SCBCmd);
    udelay( 1000 );                     // load pointer to Rx Ring
    OUTL(VIRT_TO_BUS(p_i82559->rx_ring[0]), ioaddr + SCBPointer);
    OUTW(RUC_START, ioaddr + SCBCmd);
    
    p_i82559->active = 1;

    initPHY(ioaddr, phy_id);

#ifdef CYGPKG_NET
    if (( 0
#ifdef ETH_DRV_FLAGS_PROMISC_MODE
         != (flags & ETH_DRV_FLAGS_PROMISC_MODE)
#endif
        ) || (ifp->if_flags & IFF_PROMISC)
        ) {
        eth_set_promiscuous_mode(p_i82559);
    }
#endif
#ifdef DEBUG
    {
        int status = i82559_status( sc );
        os_printf("i82559_start %d flg %x Link = %s, %s Mbps, %s Duplex\n",
                  p_i82559->index,
                  *(int *)p_i82559,
                  status & GEN_STATUS_LINK ? "Up" : "Down",
                  status & GEN_STATUS_100MBPS ?  "100" : "10",
                  status & GEN_STATUS_FDX ? "Full" : "Half");
    }
#endif
}

// ------------------------------------------------------------------------
//
//  Function : i82559_status
//
// ------------------------------------------------------------------------
int i82559_status( struct eth_drv_sc *sc )
{
    int status;
    struct i82559 *p_i82559;
    cyg_uint32 ioaddr;
    p_i82559 = (struct i82559 *)sc->driver_private;
    
    IF_BAD_82559( p_i82559 ) {
#ifdef DEBUG
        os_printf( "i82559_status: Bad device pointer %x\n", p_i82559 );
#endif
        return 0;
    }

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

    status = INB(ioaddr + SCBGenStatus);

    return status;
}

// ------------------------------------------------------------------------
//
//  Function : BringDown82559
//
// ------------------------------------------------------------------------

static void i82559_stop( struct eth_drv_sc *sc )
{
    struct i82559 *p_i82559;

    p_i82559 = (struct i82559 *)sc->driver_private;

    IF_BAD_82559( p_i82559 ) {
#ifdef DEBUG
        os_printf( "i82559_stop: Bad device pointer %x\n", p_i82559 );
#endif
        return;
    }
   
#ifdef DEBUG
    os_printf("i82559_stop %d flg %x\n", p_i82559->index, *(int *)p_i82559 );
#endif

    p_i82559->active = 0;               // stop people tormenting it
    i82559_reset(p_i82559);             // that should stop it

    ResetRxRing( p_i82559 );
    ResetTxRing( p_i82559 );
}


// ------------------------------------------------------------------------
//
//  Function : InitRxRing
//
// ------------------------------------------------------------------------
static void InitRxRing(struct i82559* p_i82559)
{
    int i;
    RFD *rfd;
    RFD *p_rfd = 0;
#ifdef DEBUG_82559
    os_printf("InitRxRing %d\n", p_i82559->index);
#endif
    for ( i = 0; i < MAX_RX_DESCRIPTORS; i++ ) {
        rfd = (RFD *)pciwindow_mem_alloc(sizeof(RFD) + MAX_RX_PACKET_SIZE);
        p_i82559->rx_ring[i] = rfd;
        if ( i )
            p_rfd->link = VIRT_TO_BUS(rfd);
        p_rfd = (RFD *)rfd;
    }
    // link last RFD to first:
    p_rfd->link = VIRT_TO_BUS(p_i82559->rx_ring[0]);

    ResetRxRing( p_i82559 );
}

// ------------------------------------------------------------------------
//
//  Function : ResetRxRing
//
// ------------------------------------------------------------------------
static void ResetRxRing(struct i82559* p_i82559)
{
    RFD *p_rfd;
    int i;
#ifdef DEBUG_82559
    os_printf("ResetRxRing %d\n", p_i82559->index);
#endif
    for ( i = 0; i < MAX_RX_DESCRIPTORS; i++ ) {
        p_rfd = p_i82559->rx_ring[i];
        CYG_ASSERT( (cyg_uint8 *)p_rfd >= i82559_heap_base, "rfd under" );
        CYG_ASSERT( (cyg_uint8 *)p_rfd <  i82559_heap_free, "rfd over" );
        CYG_ASSERT( p_i82559->rx_ring[
                 ( i ? (i-1) : (MAX_RX_DESCRIPTORS-1) )
            ]->link == VIRT_TO_BUS(p_rfd), "rfd linked list broken" );
        p_rfd->rxstatus = 0;
        p_rfd->count = 0;
        p_rfd->f = 0;
        p_rfd->eof = 0;
        p_rfd->rdb_address = 0xFFFFFFFF;
        p_rfd->size = MAX_RX_PACKET_SIZE;
    }
    p_i82559->next_rx_descriptor = 0;
    // And set an end-of-list marker in the previous one.
    p_rfd->rxstatus = RFD_STATUS_EL;
}

// ------------------------------------------------------------------------
//
//  Function : PacketRxReady        (Called from delivery thread)
//
// ------------------------------------------------------------------------
static void PacketRxReady(struct i82559* p_i82559)
{
    RFD *p_rfd;
    int next_descriptor;
    int length, ints;
    struct cyg_netdevtab_entry *ndp;
    struct eth_drv_sc *sc;
    cyg_uint32 ioaddr;
    cyg_uint16 status;

    ndp = (struct cyg_netdevtab_entry *)(p_i82559->ndp);
    sc = (struct eth_drv_sc *)(ndp->device_instance);

    CHECK_NDP_SC_LINK();

    ioaddr = p_i82559->io_address;

    next_descriptor = p_i82559->next_rx_descriptor;
    p_rfd = p_i82559->rx_ring[next_descriptor];

    CYG_ASSERT( (cyg_uint8 *)p_rfd >= i82559_heap_base, "rfd under" );
    CYG_ASSERT( (cyg_uint8 *)p_rfd <  i82559_heap_free, "rfd over" );

    while ( p_rfd->rxstatus & RFD_STATUS_C ) {
        p_rfd->rxstatus_hi |= RFD_STATUS_HI_EL;
        length = p_rfd->count;

#ifdef DEBUG_82559
        os_printf( "Device %d (eth%d), rx descriptor %d:\n", 
                   p_i82559->index, p_i82559->index, next_descriptor );
//        dump_rfd( p_rfd, 1 );
#endif

        p_i82559->next_rx_descriptor = next_descriptor;
        // Check for bogusly short packets; can happen in promisc mode:
        // Asserted against and checked by upper layer driver.
#ifdef CYGPKG_NET
        if ( length > sizeof( struct ether_header ) )
            // then it is acceptable; offer the data to the network stack
#endif
        (sc->funs->eth_drv->recv)( sc, length );

        p_rfd->count = 0;
        p_rfd->f = 0;
        p_rfd->eof = 0;
        p_rfd->rxstatus_lo = 0;

        // The just-emptied slot is now ready for re-use and already marked EL;
        // we can now remove the EL marker from the previous one.
        if ( 0 == next_descriptor )
            p_rfd = p_i82559->rx_ring[ MAX_RX_DESCRIPTORS-1 ];
        else
            p_rfd = p_i82559->rx_ring[ next_descriptor-1 ];
        // The previous one: check it *was* marked before clearing.
        CYG_ASSERT( p_rfd->rxstatus_hi & RFD_STATUS_HI_EL, "No prev EL" );
        p_rfd->rxstatus_hi = 0; // that word is not written by the device.

#ifdef KEEP_STATISTICS
        statistics[p_i82559->index].rx_deliver++;
#endif
        if (++next_descriptor >= MAX_RX_DESCRIPTORS)
            next_descriptor = 0;
        p_rfd = p_i82559->rx_ring[next_descriptor];

        CYG_ASSERT( (cyg_uint8 *)p_rfd >= i82559_heap_base, "rfd under" );
        CYG_ASSERT( (cyg_uint8 *)p_rfd <  i82559_heap_free, "rfd over" );
#ifdef CYGPKG_REDBOOT
	// FIXME. Temporary hack for expediency.
	// Need to make this decision at runtime.
	break;
#endif
    }

    // See if the RU has gone idle (usually because of out of resource
    // condition) and restart it if needs be.
    ints = Mask82559Interrupt(p_i82559);
    status = INW(ioaddr + SCBStatus);
    if ( RU_STATUS_READY != (status & RU_STATUS_MASK) ) {
        // Acknowledge the RX INT sources
        OUTW( SCB_INTACK_RX, ioaddr + SCBStatus);
        // (see pages 6-10 & 6-90)

#ifdef KEEP_STATISTICS
        statistics[p_i82559->index].rx_restart++;
#endif
        // There's an end-of-list marker out there somewhere...
        // So mop it up; it takes a little time but this is infrequent.
        ResetRxRing( p_i82559 );  
        next_descriptor = 0;        // re-initialize next desc.
        // wait for SCB command complete
        wait_for_cmd_done(ioaddr);
        // load pointer to Rx Ring
        OUTL(VIRT_TO_BUS(p_i82559->rx_ring[0]),
             ioaddr + SCBPointer);
        OUTW(RUC_START, ioaddr + SCBCmd);
        Acknowledge82559Interrupt(p_i82559);
    }
    UnMask82559Interrupt(p_i82559, ints);

    p_i82559->next_rx_descriptor = next_descriptor;
}

// and the callback function

static void i82559_recv( struct eth_drv_sc *sc,
                         struct eth_drv_sg *sg_list, int sg_len )
{
    struct i82559 *p_i82559;
    RFD *p_rfd;
    int next_descriptor;
    int total_len;
    struct eth_drv_sg *last_sg;
    volatile cyg_uint8 *from_p;

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

    next_descriptor = p_i82559->next_rx_descriptor;
    p_rfd = p_i82559->rx_ring[next_descriptor];
    
    CYG_ASSERT( (cyg_uint8 *)p_rfd >= i82559_heap_base, "rfd under" );
    CYG_ASSERT( (cyg_uint8 *)p_rfd <  i82559_heap_free, "rfd over" );

    CYG_ASSERT( p_rfd->rxstatus & RFD_STATUS_C, "No complete frame" );
    CYG_ASSERT( p_rfd->rxstatus & RFD_STATUS_EL, "No marked frame" );

    CYG_ASSERT( p_rfd->rxstatus_lo & RFD_STATUS_LO_C, "No complete frame 2" );
    CYG_ASSERT( p_rfd->rxstatus_hi & RFD_STATUS_HI_EL, "No marked frame 2" );
    
    if ( 0 == (p_rfd->rxstatus & RFD_STATUS_C) )
        return;
        
    total_len = p_rfd->count;

⌨️ 快捷键说明

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