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

📄 if_ixdp2400.c

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

		/* do BIG endian support */
       *( (unsigned long*)&p_rfd->rdb_address +1) = swap32( * ((unsigned long*) &p_rfd->rdb_address +1));
    }
    p_i82559->next_rx_descriptor = 0;
    // And set an end-of-list marker in the previous one.
    p_rfd->rxstatus = swap32(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;
    volatile 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 ( swap32(p_rfd->rxstatus) & RFD_STATUS_C ) {
		RFD temprfd;
#ifdef PKT_DEBUG
		printf("received a packet\n");
#endif

		*((unsigned long *)(&(temprfd.rdb_address) + 1)) = swap32(*((unsigned long *)(&(p_rfd->rdb_address) + 1)));
		length = temprfd.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->rxstatus = swap32(RFD_STATUS_EL);
		temprfd.count = 0;
        temprfd.f = 0;
        temprfd.eof = 0;
        temprfd.size = MAX_RX_PACKET_SIZE;
		*((unsigned long *)(&(p_rfd->rdb_address) + 1)) = swap32(*((unsigned long *)(&(temprfd.rdb_address) + 1)));

        // 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" );
		temprfd.rxstatus = swap32(p_rfd->rxstatus);
		temprfd.rxstatus_hi = 0;
		p_rfd->rxstatus = swap32(temprfd.rxstatus);

#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(SCB_M | RUC_START, ioaddr + SCBCmd);

		/* wait for RU to start */
		status = INW(ioaddr + SCBStatus);
		while(RU_STATUS_READY != (status & RU_STATUS_MASK))
		{
			status = INW(ioaddr + SCBStatus);
		}

        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;
	RFD temprfd;

    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 == (swap32(p_rfd->rxstatus) & RFD_STATUS_C) )
        return;
        
    *((unsigned long *)(&(temprfd.rdb_address) + 1)) = swap32(*((unsigned long *)(&(p_rfd->rdb_address) + 1)));
    total_len = temprfd.count;
    
#ifdef DEBUG_82559
    os_printf("Rx %d %x (status %x): %d sg's, %d bytes\n",
              p_i82559->index, (int)p_i82559, p_rfd->rxstatus, sg_len, total_len);
#endif

    // Copy the data to the network stack
    from_p = &p_rfd->buffer[0];

    // check we have memory to copy into; we would be called even if
    // caller was out of memory in order to maintain our state.
    if ( 0 == sg_len || 0 == sg_list )
        return; // caller was out of mbufs

    CYG_ASSERT( 0 < sg_len, "sg_len underflow" );
    CYG_ASSERT( MAX_ETH_DRV_SG >= sg_len, "sg_len overflow" );

    for ( last_sg = &sg_list[sg_len]; sg_list < last_sg; sg_list++ ) {
        cyg_uint8 *to_p;
        int l;
            
        to_p = (cyg_uint8 *)(sg_list->buf);
        l = sg_list->len;

        CYG_ASSERT( 0 <= l, "sg length -ve" );

        if ( 0 >= l || 0 == to_p )
            return; // caller was out of mbufs

        if ( l > total_len )
            l = total_len;

        memcpy( to_p, (unsigned char *)from_p, l );
        from_p += l;
        total_len -= l;
    }

    CYG_ASSERT( 0 == total_len, "total_len mismatch in rx" );
    CYG_ASSERT( last_sg == sg_list, "sg count mismatch in rx" );
    CYG_ASSERT( &p_rfd->buffer[0] < from_p, "from_p wild in rx" );
    CYG_ASSERT( &p_rfd->buffer[0] + MAX_RX_PACKET_SIZE >= from_p,
                "from_p overflow in rx" );
#ifdef DEBUG_82559
	//update_statistics(p_i82559);
	//DisplayStatistics();
#endif
}    


// ------------------------------------------------------------------------
//
//  Function : InitTxRing
//
// ------------------------------------------------------------------------
static void InitTxRing(struct i82559* p_i82559)
{
    int i;
    cyg_uint32 ioaddr;
	TxCB *txcb;
    TxCB *p_txcb = 0;

#ifdef DEBUG_82559
    os_printf("InitTxRing %d\n", p_i82559->index);
#endif
    ioaddr = p_i82559->io_address;

    for (i = 0; i < MAX_TX_DESCRIPTORS; i++) {
		txcb = (TxCB *)pciwindow_mem_alloc(sizeof(TxCB) + MAX_TX_PACKET_SIZE);
		p_i82559->tx_ring[i] = txcb;
		if(i)
			p_txcb->link = swap32(VIRT_TO_BUS(txcb));
        p_txcb = txcb;
    }
    // link last TxCB to first:
    p_txcb->link = swap32(VIRT_TO_BUS(p_i82559->tx_ring[0]));

    ResetTxRing(p_i82559);
}

// ------------------------------------------------------------------------
//
//  Function : ResetTxRing
//
// ------------------------------------------------------------------------
static void ResetTxRing(struct i82559* p_i82559)
{
    int i;
    cyg_uint32 ioaddr;

#ifdef DEBUG_82559
    os_printf("ResetTxRing %d\n", p_i82559->index);
#endif
    ioaddr = p_i82559->io_address;
    p_i82559->tx_descriptor_add =
        p_i82559->tx_descriptor_active = 
        p_i82559->tx_descriptor_remove = 0;
    p_i82559->tx_in_progress =
        p_i82559->tx_queue_full = 0;

    for ( i = 0; i < MAX_TX_DESCRIPTORS; i++) {
        TxCB *p_txcb = p_i82559->tx_ring[i];
        CYG_ASSERT( (cyg_uint8 *)p_txcb >= i82559_heap_base, "txcb under" );
        CYG_ASSERT( (cyg_uint8 *)p_txcb <  i82559_heap_free, "txcb over" );

        p_txcb->txstatus = 0;
        p_txcb->command = 0;
        p_txcb->tbd_address = 0xFFFFFFFF;
        p_txcb->tbd_number = 0;
        p_txcb->tx_threshold = 16;
        p_txcb->eof = 1;
        p_txcb->count = 0;
		*((unsigned long *)(&(p_txcb->tbd_address) + 1)) = swap32(*((unsigned long *)(&(p_txcb->tbd_address) + 1)) );
        p_i82559->tx_keys[i] = 0;
    }
    
    wait_for_cmd_done(ioaddr);
    OUTL(0, ioaddr + SCBPointer);
    OUTW(SCB_M | CU_ADDR_LOAD, ioaddr + SCBCmd);
}

// ------------------------------------------------------------------------
//
//  Function : TxMachine          (Called from FG & ISR)
//
// This steps the Tx Machine onto the next record if necessary - allowing
// for missed interrupts, and so on.
// ------------------------------------------------------------------------

static void TxMachine(struct i82559* p_i82559)
{
    int tx_descriptor_active;
    cyg_uint32 ioaddr;

    tx_descriptor_active = p_i82559->tx_descriptor_active;
    ioaddr = p_i82559->io_address;  
    
    // See if the CU is idle when we think it isn't; this is the only place
    // tx_descriptor_active is advanced. (Also recovers from a dropped intr)
    if ( p_i82559->tx_in_progress ) {
		cyg_uint16 status;
        status = INW(ioaddr + SCBStatus);
        if ( 0 == (status & CU_STATUS_MASK) ) {
            // It is idle.  So ack the TX interrupts
            OUTW( SCB_INTACK_TX, ioaddr + SCBStatus);
            // (see pages 6-10 & 6-90)

            // and step on to the next queued tx.
            p_i82559->tx_in_progress = 0;
            if ( ++tx_descriptor_active >= MAX_TX_DESCRIPTORS )
                tx_descriptor_active = 0;
            p_i82559->tx_descriptor_active = tx_descriptor_active;
        }
    }

    // is the CU idle, and there a next tx to set going?
    if ( ( ! p_i82559->tx_in_progress )
         && p_i82559->tx_descriptor_add != tx_descriptor_active ) {
        TxCB *p_txcb;

#ifdef PKT_DEBUG
		printf("sending packet %d\n", tx_descriptor_active);
#endif
        p_txcb = p_i82559->tx_ring[tx_descriptor_active];
        CYG_ASSERT( (cyg_uint8 *)p_txcb >= i82559_heap_base, "txcb under" );
        CYG_ASSERT( (cyg_uint8 *)p_txcb <  i82559_heap_free, "txcb over" );
#ifdef DEBUG_82559
		{
			cyg_uint32 key = 1;

			os_printf("Tx %d %x: Starting Engines, KEY %x\n",
				p_i82559->index, (int)p_i82559, key );
		}
#endif
        // make sure no command operating
        wait_for_cmd_done(ioaddr);
        // start Tx operation
        OUTL(VIRT_TO_BUS(p_txcb), ioaddr + SCBPointer);
        OUTW(SCB_M | CU_START, ioaddr + SCBCmd);
        p_i82559->tx_in_progress = 1;
    }
}

// ------------------------------------------------------------------------
//
//  Function : TxDone          (Called from delivery thread)
//
// This returns Tx's from the Tx Machine to the stack (ie. reports
// completion) - allowing for missed interrupts, and so on.
// ------------------------------------------------------------------------

static void TxDone(struct i82559* p_i82559)
{
    struct cyg_netdevtab_entry *ndp;
    struct eth_drv_sc *sc;
    int tx_descriptor_remove = p_i82559->tx_descriptor_remove;

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

⌨️ 快捷键说明

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