if_i21143.c
来自「eCos操作系统源码」· C语言 代码 · 共 1,953 行 · 第 1/5 页
C
1,953 行
l = sg_list->len; if ( l > total_len ) l = total_len; // Ensure the mbuf contents really is in RAM where DMA can see it. // (Must round to cache lines apparantly for some MIPS) HAL_DCACHE_STORE( ((CYG_ADDRESS)from_p) &~(HAL_DCACHE_LINE_SIZE-1), l + HAL_DCACHE_LINE_SIZE ); // There are two pointer, length pairs in each descriptor. We only // bother using the first one - the code saved is small but so is // the overhead of memory. bp->buf1 = CYGHWR_PCI_VIRT_TO_BUS( from_p ); // uncached real RAM address bp->buf2 = 0; // Record length and add endring flag iff end of ring - never leave // it blank in memory! x = (l << DES1_B1SIZE_SHIFT) & DES1_B1SIZE_MASK; // plus zero buf2 size. if ( (TX_DESCRIPTORS-1) == bufcount ) x |= DES1_ENDRING; bp->des1 = x; // Leave writing the zeroth bufdesc DES0 until all are complete: // the tx engine will be stopped looking there. if ( 0 < bufcount ) // then we can write DES0 also. bp->des0 = DES0_STATUS_OWN_OPEN; total_len -= l; bp++; bufcount++; 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( bp > &p_i21143->tx_ring[0], "bp underflow" ); bp--; // back to the last-used bp. bufcount--; p_i21143->tx_endbuf = bufcount; // record that we are busy p_i21143->tx_keys[0] = key; // and the key to return CYG_ASSERT( bp < &p_i21143->tx_ring[ TX_DESCRIPTORS ], "bp underflow" ); // Mark this the last valid buffer. bp->des1 |= TDES1_CONTROL_LAST | TDES1_CONTROL_INTERRUPT; CYG_ASSERT( &(p_i21143->tx_ring[bufcount]) == bp, "Bp/bufcount misstep" ); bp++; bufcount++; // Make the rest be null links for ( /* bp */ ; bp < &p_i21143->tx_ring[ TX_DESCRIPTORS ]; bp++ ) { bp->buf1 = 0; bp->buf2 = 0; x = 0; // zero size for both buffers if ( (TX_DESCRIPTORS-1) == bufcount ) x |= DES1_ENDRING; bp->des1 = x; bp->des0 = DES0_STATUS_OWN_OPEN; bufcount++; } // Now it's safe to write the zeroth descriptor: p_i21143->tx_ring->des1 |= TDES1_CONTROL_FIRST; p_i21143->tx_ring->des0 = DES0_STATUS_OWN_OPEN;#ifdef DEBUG_TRAFFIC_TXDETAILS dump_tx_details( p_i21143, "i21143_send" );#endif // And start off the tx system x = INL( CSR_STATUS );#ifdef DEBUG_TRAFFIC diag_printf( "i21143_send: ready, status %08x %s\n", x, (CSR_STATUS_TXSTATUS & x) != CSR_STATUS_TXSTATUS_STOPPED ? "Running" : "Stopped" );#endif if ( CSR_STATUS_TXSTATUS_STOPPED == (CSR_STATUS_TXSTATUS & x) ) { cyg_uint32 l; // Then we must initialize and start the tx machine OUTL( CYGHWR_PCI_VIRT_TO_BUS( (cyg_uint32)p_i21143->tx_ring ), CSR_TXBASE ); l = INL( CSR_OPMODE ); l |= CSR_OPMODE_TX_START; OUTL( l, CSR_OPMODE ); } else if ( CSR_STATUS_TXSTATUS_SUSPENDED == (CSR_STATUS_TXSTATUS & x) ) { // Then we just have to ping it OUTL( 0, CSR_TXPOLL ); } else {#ifdef DEBUG_TRAFFIC diag_printf( "i21143_send: tx not ready %x CSR_STATUS %08x\n", p_i21143, x );#endif CYG_FAIL( "Tx is not ready to tx" ); // Try to recover by brutal means... i21143_stop( sc ); // will return the key i21143_start( sc, NULL, 0 ); }}// ------------------------------------------------------------------------//// Function : i21143_reset//// ------------------------------------------------------------------------static voidi21143_reset(struct i21143* p_i21143){ cyg_uint32 ioaddr = p_i21143->io_address; cyg_uint32 l; int i, status; // First stop the tx and rx engines - doc suggests that's necessary // before writing the reset reg, but it seems a little paranoid. l = INL( CSR_OPMODE ); l &=~ (CSR_OPMODE_RX_START | CSR_OPMODE_TX_START); OUTL( l, CSR_OPMODE ); for ( i = 0; i < 10000; i++) { l = INL( CSR_STATUS ); if ( ((CSR_STATUS_TXSTATUS & l) == CSR_STATUS_TXSTATUS_STOPPED) && ((CSR_STATUS_RXSTATUS & l) == CSR_STATUS_RXSTATUS_STOPPED) ) break; }#ifdef DEBUG_STARTSTOPRESET diag_printf( "i21143_reset: rx and tx idle after %d iters, status %x\n", i, l );#endif // Acknowledge all the interrupts from these activities // within the device: OUTL( 0xffffffff, CSR_STATUS ); // clear all bits // Now reset the device. We are going to re-init all params anyway, so // ignore other settings: OUTL( CSR_BUSMODE_RESET, CSR_BUSMODE ); udelay( 100 ); // let reset take effect. "50 PCI clock cycles" for ( i = 0; i < 10000; i++) { l = INL( CSR_BUSMODE ); if ( (CSR_BUSMODE_RESET & l) == 0 ) break; }#ifdef DEBUG_STARTSTOPRESET diag_printf( "i21143_reset: reset zero after %d iters, busmode %x\n", i, l );#endif // Gross initialization OUTL( 0 // No other options // CSR_BUSMODE_PM // CSR_BUSMODE_WIE // CSR_BUSMODE_RLE // CSR_BUSMODE_RME // CSR_BUSMODE_DBO_BE // CSR_BUSMODE_DBO_LE // CSR_BUSMODE_TAP_SHIFT | (1 << CSR_BUSMODE_CAL_SHIFT) | (4 << CSR_BUSMODE_PBL_SHIFT) // CSR_BUSMODE_ENDIAN_BE // CSR_BUSMODE_ENDIAN_LE // CSR_BUSMODE_DSL_SHIFT // CSR_BUSMODE_BAR // CSR_BUSMODE_RESET , CSR_BUSMODE ); // No interrupt sources enabled yet OUTL( 0, CSR_INTR_ENABLE ); OUTL( 0 // CSR_ROM_MII_MGT_MDI | CSR_ROM_MII_MGT_MOM_READ // CSR_ROM_MII_MGT_MDO // CSR_ROM_MII_MGT_MDC // CSR_ROM_MII_MGT_RD // CSR_ROM_MII_MGT_WR // CSR_ROM_MII_MGT_BR // CSR_ROM_MII_MGT_SR // CSR_ROM_MII_MGT_REG // CSR_ROM_MII_MGT_SR_DO // CSR_ROM_MII_MGT_SR_DI // CSR_ROM_MII_MGT_SR_CK // CSR_ROM_MII_MGT_SR_CS | 0xff, CSR_ROM_MII_MGT ); // ----------------------------------- // Now find out about the status of the PHY via MII#if 0 // Try resetting the PHY and power-cycling it: mii_write_register( ioaddr, PHY_CONTROL_REG, PHY_CONTROL_RESET | PHY_CONTROL_AUTONEG_EN); while (1) { int v; v = mii_read_register( ioaddr, PHY_CONTROL_REG ); if ( 0 == (v & PHY_CONTROL_RESET) ) break; } mii_write_register( ioaddr, PHY_CONTROL_REG, PHY_CONTROL_POWERDOWN | PHY_CONTROL_MII_DIS | PHY_CONTROL_AUTONEG_EN ); udelay( 1000 ); mii_write_register( ioaddr, PHY_CONTROL_REG, PHY_CONTROL_AUTONEG_EN | PHY_CONTROL_AUTONEG_RST ); udelay( 1000 ); while (1) { int v; v = mii_read_register( ioaddr, PHY_STATUS_REG ); if ( PHY_STATUS_AUTONEG_ACK & v ) break; } #endif#ifdef DEBUG_DUMP_REGS debug_dump_regs( ioaddr, MII );#endif status = i21143_status( p_i21143 ); p_i21143->line_status = status; // record it for SNMP info#ifdef DEBUG_STARTSTOPRESET diag_printf("i21143_reset %d flg %x Link = %s, %s Mbps, %s Duplex\n", p_i21143->index, *(int *)p_i21143, (GEN_STATUS_LINK & status) ? "Up" : "Down", (GEN_STATUS_100MBPS & status) ? "100" : "10", (GEN_STATUS_FDX & status) ? "Full" : "Half");#endif OUTL( -1, CSR_ROM_PGM_ADDR ); OUTL( 0, CSR_INTR_MITIGATION ); // CSR13, 14 = 0; select SIA mode temporarily.// OUTL( CSR_OPMODE_MUST_BE_ONE, CSR_OPMODE); OUTL( CSR_SIA_CONN_DEFAULT, CSR_SIA_CONN ); OUTL( CSR_SIA_TXRX_DEFAULT, CSR_SIA_TXRX ); OUTL( CSR_SIA_GPPORT_DEFAULT, CSR_SIA_GPPORT ); // Last one, CSR6 l = 0 | CSR_OPMODE_SC // CSR_OPMODE_RA // CSR_OPMODE_IGNOREMSB | CSR_OPMODE_MUST_BE_ONE // CSR_OPMODE_SCR do not set for MII mode // CSR_OPMODE_PCS do not set for MII mode // CSR_OPMODE_TTM set for 10Mb, not set for 100Mb | CSR_OPMODE_SF // Set the store&forward bit so we can keep- | CSR_OPMODE_HBD // -up at 100Mbit | CSR_OPMODE_PS_MIISYM | CSR_OPMODE_CA // CSR_OPMODE_TX_THRES_SHIFT // CSR_OPMODE_TX_START // CSR_OPMODE_FC // (0 << CSR_OPMODE_LOOPBACK_SHIFT) // CSR_OPMODE_FD // CSR_OPMODE_MULTICAST // Pass all multicast // CSR_OPMODE_PROMISC // Promisc mode // CSR_OPMODE_SB // CSR_OPMODE_IF // Inverse filtering (!) // CSR_OPMODE_PB // CSR_OPMODE_HO // 0: Perfect filter // CSR_OPMODE_RX_START // 1: hashing for /all/ addresses // CSR_OPMODE_HP // 0: Perfect filter of N address ; // 1: imperfect hash filter + 1 fixed addr if ( GEN_STATUS_FDX & status ) l |= CSR_OPMODE_FD; if ( ! (GEN_STATUS_100MBPS & status) ) l |= CSR_OPMODE_TTM; OUTL( l, CSR_OPMODE );}// ------------------------------------------------------------------------//// INTERRUPT HANDLERS//// ------------------------------------------------------------------------static cyg_uint32eth_isr(cyg_vector_t vector, cyg_addrword_t data){ cyg_drv_interrupt_mask( vector ); #ifdef DEBUG_TRAFFIC diag_printf( "i21143_isr, vector %d\n", vector );#endif return CYG_ISR_CALL_DSR; // schedule DSR}// An indirection is used because (if we have multiple devices) we don't// know all the "sc" values at the time the interrupts are created.static void eth_dsr(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data){ struct i21143* p_i21143 = (struct i21143 *)data; struct cyg_netdevtab_entry *ndp = (struct cyg_netdevtab_entry *)(p_i21143->ndp); struct eth_drv_sc *sc = (struct eth_drv_sc *)(ndp->device_instance); INCR_STAT( interrupts ); // but here, it must be a *sc: eth_drv_dsr( vector, count, (cyg_addrword_t)sc );}// ------------------------------------------------------------------------// Deliver routine:voidi21143_deliver(struct eth_drv_sc *sc){ struct i21143* p_i21143 = (struct i21143 *)(sc->driver_private); cyg_uint32 status; cyg_uint32 ioaddr; IF_BAD_21143( p_i21143 ) {#ifdef DEBUG_TRAFFIC diag_printf( "i21143_deliver: Bad device pointer %x\n", p_i21143 );#endif return; } ioaddr = p_i21143->io_address; status = INL( CSR_STATUS );#ifdef DEBUG_TRAFFIC diag_printf( "i21143_deliver: status %08x\n", status );#endif // Acknowledge all INT sources that were active OUTL( status, CSR_STATUS ); // Search for link status changes if ( i21143_status_changed( p_i21143 ) ) {#ifdef DEBUG_TRAFFIC diag_printf( "i21143_can_send: status changed\n" );#endif i21143_stop( sc ); i21143_start( sc, NULL, 0 ); } if ( (CSR_STATUS_TBU | CSR_STATUS_TX_STOPPED | CSR_STATUS_TX_INTR) & status ) { TxDone( p_i21143 ); } if ( (CSR_STATUS_RX_STOPPED | CSR_STATUS_RBU | CSR_STATUS_RX_INTR) & status ) { PacketRxReady( p_i21143 ); } cyg_drv_interrupt_acknowledge(p_i21143->vector); cyg_drv_interrupt_unmask( p_i21143->vector );}// ------------------------------------------------------------------------// Device table entry to operate the chip in a polled mode.// Only diddle the interface we were asked to!voidi21143_poll(struct eth_drv_sc *sc){ struct i21143 *p_i21143; p_i21143 = (struct i21143 *)sc->driver_private; IF_BAD_21143( p_i21143 ) {#ifdef DEBUG_TRAFFIC diag_printf( "i21143_poll: Bad device pointer %x\n", p_i21143 );#endif return; } // As it happens, this driver always requests the DSR to be cal
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?