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

📄 if_iq80310.c

📁 移植到WLIT项目的redboot源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
}// ------------------------------------------------------------------------////  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->link = VIRT_TO_BUS((cyg_uint32)p_txcb);        p_txcb->tbd_address = 0xFFFFFFFF;        p_txcb->tbd_number = 0;        p_txcb->tx_threshold = 16;        p_txcb->eof = 1;        p_txcb->count = 0;        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;        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        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(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_instance);    CHECK_NDP_SC_LINK();        // "Done" txen are from here to active, OR     // the remove one if the queue is full AND its status is nonzero:    while (  (tx_descriptor_remove != p_i82559->tx_descriptor_active) ||             ( p_i82559->tx_queue_full &&              (0 != p_i82559->tx_ring[ tx_descriptor_remove ]->txstatus) ) ) {        unsigned long key = p_i82559->tx_keys[ tx_descriptor_remove ];#ifdef DEBUG_82559        os_printf("TxDone %d %x: KEY %x\n",                  p_i82559->index, (int)p_i82559, key );#endif        (sc->funs->eth_drv->tx_done)( sc, key, 1 /* status */ );                if ( ++tx_descriptor_remove >= MAX_TX_DESCRIPTORS )            tx_descriptor_remove = 0;        p_i82559->tx_descriptor_remove = tx_descriptor_remove;        p_i82559->tx_queue_full = 0;    }}// ------------------------------------------------------------------------////  Function : i82559_can_send//// ------------------------------------------------------------------------static int i82559_can_send(struct eth_drv_sc *sc){    struct i82559 *p_i82559;    int ints;    p_i82559 = (struct i82559 *)sc->driver_private;    IF_BAD_82559( p_i82559 ) {#ifdef DEBUG        os_printf( "i82559_send: Bad device pointer %x\n", p_i82559 );#endif        return 0;    }        // Advance TxMachine atomically    ints = Mask82559Interrupt(p_i82559);    TxMachine(p_i82559);    Acknowledge82559Interrupt(p_i82559); // This can eat an Rx interrupt, so    PacketRxReady(p_i82559);    UnMask82559Interrupt(p_i82559,ints);    return ! p_i82559->tx_queue_full;}// ------------------------------------------------------------------------////  Function : i82559_send//// ------------------------------------------------------------------------static void i82559_send(struct eth_drv_sc *sc,            struct eth_drv_sg *sg_list, int sg_len, int total_len,            unsigned long key){    struct i82559 *p_i82559;    int tx_descriptor_add, ints;    TxCB *p_txcb;    cyg_uint32 ioaddr;    p_i82559 = (struct i82559 *)sc->driver_private;    IF_BAD_82559( p_i82559 ) {#ifdef DEBUG        os_printf( "i82559_send: Bad device pointer %x\n", p_i82559 );#endif        return;    }#ifdef DEBUG_82559    os_printf("Tx %d %x: %d sg's, %d bytes, KEY %x\n",              p_i82559->index, (int)p_i82559, sg_len, total_len, key );#endif    if ( ! p_i82559->active )        return;                         // device inactive, no return#ifdef KEEP_STATISTICS    statistics[p_i82559->index].tx_count++;#endif    ioaddr = p_i82559->io_address;      // get device I/O address    if ( p_i82559->tx_queue_full ) {#ifdef KEEP_STATISTICS        statistics[p_i82559->index].tx_dropped++;#endif#ifdef DEBUG_82559        os_printf( "i82559_send: Queue full, device %x, key %x\n",                   p_i82559, key );#endif    }    else {        struct eth_drv_sg *last_sg;        volatile cyg_uint8 *to_p;        tx_descriptor_add = p_i82559->tx_descriptor_add;        p_i82559->tx_keys[tx_descriptor_add] = key;        p_txcb = p_i82559->tx_ring[tx_descriptor_add];        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 = TxCB_CMD_TRANSMIT | TxCB_CMD_S                                | TxCB_CMD_I | TxCB_CMD_EL;        p_txcb->link = VIRT_TO_BUS((cyg_uint32)p_txcb);        p_txcb->tbd_address = 0xFFFFFFFF;        p_txcb->tbd_number = 0;        p_txcb->tx_threshold = 16;        p_txcb->eof = 1;        p_txcb->count = total_len;        // Copy from the sglist into the txcb        to_p = &p_txcb->buffer[0];        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 *from_p;            int l;                        from_p = (cyg_uint8 *)(sg_list->buf);            l = sg_list->len;            if ( l > total_len )                l = total_len;            memcpy( (unsigned char *)to_p, from_p, l );            to_p += l;            total_len -= l;            if ( 0 > total_len )                 break; // Should exit via sg_last normally        }        CYG_ASSERT( 0 == total_len, "length mismatch in tx" );        CYG_ASSERT( last_sg == sg_list, "sg count mismatch in tx" );        CYG_ASSERT( &p_txcb->buffer[0] < to_p, "to_p wild in tx" );        CYG_ASSERT( &p_txcb->buffer[0] + MAX_TX_PACKET_SIZE >= to_p,                    "to_p overflow in tx" );          // Next descriptor        if ( ++tx_descriptor_add >= MAX_TX_DESCRIPTORS)            tx_descriptor_add = 0;        p_i82559->tx_descriptor_add = tx_descriptor_add;        // From this instant, interrupts can advance the world and start,        // even complete, this tx request...        if ( p_i82559->tx_descriptor_remove == tx_descriptor_add )            p_i82559->tx_queue_full = 1;    }    // Try advancing the Tx Machine regardless    // no more interrupts until started    ints = Mask82559Interrupt(p_i82559);    // Check that either:    //     tx is already active, there is other stuff queued,    // OR  this tx just added is the current active one    // OR  this tx just added is already complete    CYG_ASSERT(        // The machine is busy:        (p_i82559->tx_in_progress == 1) ||        // or: The machine is idle and this just added is the next one        (((p_i82559->tx_descriptor_add-1) == p_i82559->tx_descriptor_active)         || ((0 == p_i82559->tx_descriptor_add) &&             ((MAX_TX_DESCRIPTORS-1) == p_i82559->tx_descriptor_active))) ||        // or: This tx is already complete        (p_i82559->tx_descriptor_add == p_i82559->tx_descriptor_active),                "Active/add mismatch" );    // Advance TxMachine atomically    TxMachine(p_i82559);    Acknowledge82559Interrupt(p_i82559); // This can eat an Rx interrupt, so    PacketRxReady(p_i82559);    UnMask82559Interrupt(p_i82559, ints);}// ------------------------------------------------------------------------////  Function : i82559_reset//// ------------------------------------------------------------------------static void i82559_reset(struct i82559* p_i82559){    cyg_uint32 ioaddr;    int count;    ioaddr = p_i82559->io_address;    // make sure no command operating    wait_for_cmd_done(ioaddr);        OUTL(I82559_SELECTIVE_RESET, ioaddr + SCBPort);      for (count = 10 ; count-- ; ) {        udelay(1000);    }    OUTL(I82559_RESET, ioaddr + SCBPort);        for (count = 10 ; count-- ; ) {      udelay(1000);    }}// ------------------------------------------------------------------------////                       INTERRUPT HANDLERS//// ------------------------------------------------------------------------static cyg_uint32 eth_isr(cyg_vector_t vector, cyg_addrword_t data){    struct i82559* p_i82559 = (struct i82559 *)data;    cyg_uint16 status;    cyg_uint32 ioaddr;    IF_BAD_82559( p_i82559 ) {#ifdef DEBUG        os_printf( "i82559_isr: Bad device pointer %x\n", p_i82559 );#endif        return 0;    }    ioaddr = p_i82559->io_address;    status = INW(ioaddr + SCBStatus);    // Acknowledge all INT sources that were active    OUTW( status & SCB_INTACK_MASK, ioaddr + SCBStatus);    // (see pages 6-10 & 6-90)#ifdef KEEP_STATISTICS    statistics[p_i82559->index].interrupts++;    // receiver left ready state ?    if ( status & SCB_STATUS_RNR )        statistics[p_i82559->index].rx_resource++;    // frame receive interrupt ?    if ( status & SCB_STATUS_FR )        statistics[p_i82559->index].rx_count++;    // transmit interrupt ?    if ( status & SCB_STATUS_CX )        statistics[p_i82559->index].tx_complete++;#endif    // Advance the Tx Machine regardless    TxMachine(p_i82559);    // it should have settled down now...    Acknowledge82559Interrupt(p_i82559);    return CYG_ISR_CALL_DSR;        // schedule DSR}// ------------------------------------------------------------------------static void eth_dsr(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data){    struct i82559* p_i82559 = (struct i82559 *)data;    struct cyg_netdevtab_entry *ndp =        (struct cyg_netdevtab_entry *)(p_i82559->ndp);    struct eth_drv_sc *sc = (struct eth_drv_sc *)(ndp->device_instance);    // but here, it must be a *sc:    eth_drv_dsr( vector, count, (cyg_addrword_t)sc );}// ------------------------------------------------------------------------// This is called from the functi

⌨️ 快捷键说明

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