欢迎来到虫虫下载站 | 资源下载 资源专辑 关于我们
虫虫下载站

if_lan91cxx.c

eCos操作系统源码
C
第 1 页 / 共 4 页
字号:
    stat = CYG_LE16_TO_CPU(stat);    len = get_data(sc);    len = CYG_LE16_TO_CPU(len) - 6;     // minus header/footer words#endif#ifdef KEEP_STATISTICS    if ( stat & LAN91CXX_RX_STATUS_ALIGNERR ) INCR_STAT( rx_align_errors );    //if ( stat & LAN91CXX_RX_STATUS_BCAST    ) INCR_STAT(  );    if ( stat & LAN91CXX_RX_STATUS_BADCRC   ) INCR_STAT( rx_crc_errors );    if ( stat & LAN91CXX_RX_STATUS_TOOLONG  ) INCR_STAT( rx_too_long_frames );    if ( stat & LAN91CXX_RX_STATUS_TOOSHORT ) INCR_STAT( rx_short_frames );    //if ( stat & LAN91CXX_RX_STATUS_MCAST    ) INCR_STAT(  );#endif // KEEP_STATISTICS    if ((stat & LAN91CXX_RX_STATUS_BAD) == 0) {        INCR_STAT( rx_good );        // Then it's OK        if( LAN91CXX_RX_STATUS_IS_ODD(cpd,stat) )            len++;#if DEBUG & 1        db_printf("RxEvent good rx - stat: 0x%04x, len: 0x%04x\n", stat, len);#endif        // Check for bogusly short packets; can happen in promisc mode:        // Asserted against and checked by upper layer driver.#ifdef CYGPKG_NET        if ( len > sizeof( struct ether_header ) )            // then it is acceptable; offer the data to the network stack#endif        (sc->funs->eth_drv->recv)(sc, len);        return;    }    // Not OK for one reason or another...#if DEBUG & 1    db_printf("RxEvent - bad rx: stat: 0x%04x, len: 0x%04x\n", stat, len);#endif    // Free packet    put_reg(sc, LAN91CXX_MMU_COMMAND, LAN91CXX_MMU_remrel_rx_frame);}//// This function is called as a result of the "eth_drv_recv()" call above.// Its job is to actually fetch data for a packet from the hardware once// memory buffers have been allocated for the packet.  Note that the buffers// may come in pieces, using a scatter-gather list.  This allows for more// efficient processing in the upper layers of the stack.//static voidlan91cxx_recv(struct eth_drv_sc *sc, struct eth_drv_sg *sg_list, int sg_len){#if (4 & DEBUG) || defined(CYGPKG_INFRA_DEBUG) || \    defined(KEEP_STATISTICS) || defined(LAN91CXX_IS_LAN91C111)    struct lan91cxx_priv_data *cpd =         (struct lan91cxx_priv_data *)sc->driver_private;#endif    int i;    short mlen=0, plen;    rxd_t *data=NULL, val;    unsigned char *cp, cval;    DEBUG_FUNCTION();    INCR_STAT( rx_deliver );    put_reg(sc, LAN91CXX_POINTER, (LAN91CXX_POINTER_RCV | LAN91CXX_POINTER_READ |                                 LAN91CXX_POINTER_AUTO_INCR));    val = get_data(sc);    // packet length (minus header/footer)#ifdef LAN91CXX_32BIT_RX    val = CYG_LE32_TO_CPU(val);    plen = (val >> 16) - 6;#else    val = CYG_LE16_TO_CPU(val);    plen = get_data(sc);    plen = CYG_LE16_TO_CPU(plen) - 6;#endif    if( LAN91CXX_RX_STATUS_IS_ODD(cpd,val) )	plen++;    for (i = 0;  i < sg_len;  i++) {        data = (rxd_t *)sg_list[i].buf;        mlen = sg_list[i].len;        CYG_ASSERT(0 == (mlen & (sizeof(*data) - 1)) || (i == (sg_len-1)), "odd length");#if DEBUG & 1        db_printf("%s : mlen %x, plen %x\n", __FUNCTION__, mlen, plen);#endif        if (data) {            while (mlen >= sizeof(*data)) {                *data++ = get_data(sc);                mlen -= sizeof(*data);                plen -= sizeof(*data);            }        }        else { // must actively discard ie. read it from the chip anyway.            while (mlen >= sizeof(*data)) {                (void)get_data(sc);                mlen -= sizeof(*data);                plen -= sizeof(*data);            }        }    }    val = get_data(sc); // Read control word (and potential data) unconditionally#ifdef LAN91CXX_32BIT_RX    val = CYG_LE32_TO_CPU(val);    if (plen & 2) {	if (data)	    *(cyg_uint16 *)data = val & 0xffff;	cp = (unsigned char *)data + 2;	val >>= 16;	mlen -= 2;    } else#else    val = CYG_LE16_TO_CPU(val);#endif	cp = (unsigned char *)data;    CYG_ASSERT(val & LAN91CXX_CONTROLBYTE_RX,                "Controlbyte is not for Rx");    CYG_ASSERT( (1 == mlen) == (0 != LAN91CXX_CONTROLBYTE_IS_ODD(cpd,val)),                 "Controlbyte does not match");    if (data && (1 == mlen) && LAN91CXX_CONTROLBYTE_IS_ODD(cpd,val) ) {        cval = val & 0x00ff;    // last byte contains data        *cp = cval;    }    val = get_reg(sc, LAN91CXX_FIFO_PORTS);#if DEBUG & 4    if ( 0x8000 & val ) // Then the Rx FIFO is empty        db_printf("#####Rx packet NOT freed, stat is %x (expected %x)\n",                    val, cpd->rxpacket);    else        db_printf("#####Rx packet freed %x (expected %x)\n",                    0xff & (val >> 8), cpd->rxpacket );#endif    CYG_ASSERT( (0xff & (val >> 8)) == cpd->rxpacket, "Unexpected rx packet" );    // Free packet    put_reg(sc, LAN91CXX_MMU_COMMAND, LAN91CXX_MMU_remrel_rx_frame);}static voidlan91cxx_poll(struct eth_drv_sc *sc){    unsigned short event;    struct lan91cxx_priv_data *cpd =         (struct lan91cxx_priv_data *)sc->driver_private;//    DEBUG_FUNCTION();    while (1) {        cyg_drv_interrupt_acknowledge(cpd->interrupt);        // Get the (unmasked) requests        event = get_reg(sc, LAN91CXX_INTERRUPT);        event = event & (event >> 8) & 0xff;        if (0 == event)            break;#if 0        if (event & LAN91CXX_INTERRUPT_ERCV_INT) {            // Early receive interrupt        }        else if (event & LAN91CXX_INTERRUPT_EPH_INT) {            // ethernet protocol handler failures        }        else if (event & LAN91CXX_INTERRUPT_RX_OVRN_INT) {            // receive overrun        }        else if (event & LAN91CXX_INTERRUPT_ALLOC_INT) {            // allocation interrupt        }        else#endif        if (event & LAN91CXX_INTERRUPT_TX_SET) {            lan91cxx_TxEvent(sc, event);        }        if (event & LAN91CXX_INTERRUPT_RCV_INT) {            lan91cxx_RxEvent(sc);        }        if (event & ~(LAN91CXX_INTERRUPT_TX_SET | LAN91CXX_INTERRUPT_RCV_INT))            db_printf("%s: Unknown interrupt: 0x%04x\n",			__FUNCTION__, event);    }}#ifdef LAN91CXX_IS_LAN91C111static cyg_uint16lan91cxx_read_phy(struct eth_drv_sc *sc, cyg_uint8 phyaddr, cyg_uint8 phyreg){    int i, mask, input_idx, clk_idx = 0;    cyg_uint16 mii_reg, value;    cyg_uint8 bits[64];    // 32 consecutive ones on MDO to establish sync    for (i = 0; i < 32; ++i)	bits[clk_idx++] = LAN91CXX_MGMT_MDOE | LAN91CXX_MGMT_MDO;    // Start code <01>    bits[clk_idx++] = LAN91CXX_MGMT_MDOE;    bits[clk_idx++] = LAN91CXX_MGMT_MDOE | LAN91CXX_MGMT_MDO;    // Read command <10>    bits[clk_idx++] = LAN91CXX_MGMT_MDOE | LAN91CXX_MGMT_MDO;    bits[clk_idx++] = LAN91CXX_MGMT_MDOE;    // Output the PHY address, msb first    for (mask = 0x10; mask; mask >>= 1) {	if (phyaddr & mask)	    bits[clk_idx++] = LAN91CXX_MGMT_MDOE | LAN91CXX_MGMT_MDO;	else	    bits[clk_idx++] = LAN91CXX_MGMT_MDOE;    }    // Output the phy register number, msb first    for (mask = 0x10; mask; mask >>= 1) {	if (phyreg & mask)	    bits[clk_idx++] = LAN91CXX_MGMT_MDOE | LAN91CXX_MGMT_MDO;	else	    bits[clk_idx++] = LAN91CXX_MGMT_MDOE;    }    // Tristate and turnaround (1 bit times)    bits[clk_idx++] = 0;    // Input starts at this bit time    input_idx = clk_idx;    // Will input 16 bits    for (i = 0; i < 16; ++i)	bits[clk_idx++] = 0;    // Final clock bit    bits[clk_idx++] = 0;    // Get the current MII register value    mii_reg = get_reg(sc, LAN91CXX_MGMT);    // Turn off all MII Interface bits    mii_reg &= ~(LAN91CXX_MGMT_MDOE | LAN91CXX_MGMT_MCLK | 		 LAN91CXX_MGMT_MDI | LAN91CXX_MGMT_MDO);    // Clock all 64 cycles    for (i = 0; i < sizeof(bits); ++i) {	// Clock Low - output data	put_reg(sc, LAN91CXX_MGMT, mii_reg | bits[i]);	HAL_DELAY_US(50);	// Clock Hi - input data	put_reg(sc, LAN91CXX_MGMT, mii_reg | bits[i] | LAN91CXX_MGMT_MCLK);	HAL_DELAY_US(50);	bits[i] |= get_reg(sc, LAN91CXX_MGMT) & LAN91CXX_MGMT_MDI;    }    // Return to idle state    put_reg(sc, LAN91CXX_MGMT, mii_reg);    HAL_DELAY_US(50);    // Recover input data    for (value = 0, i = 0; i < 16; ++i) {	value <<= 1;	if (bits[input_idx++] & LAN91CXX_MGMT_MDI)	    value |= 1;    }    return value;}static voidlan91cxx_write_phy(struct eth_drv_sc *sc, cyg_uint8 phyaddr,		   cyg_uint8 phyreg, cyg_uint16 value){    int i, mask, clk_idx = 0;    cyg_uint16 mii_reg;    cyg_uint8 bits[65];    // 32 consecutive ones on MDO to establish sync    for (i = 0; i < 32; ++i)	bits[clk_idx++] = LAN91CXX_MGMT_MDOE | LAN91CXX_MGMT_MDO;    // Start code <01>    bits[clk_idx++] = LAN91CXX_MGMT_MDOE;    bits[clk_idx++] = LAN91CXX_MGMT_MDOE | LAN91CXX_MGMT_MDO;    // Write command <01>    bits[clk_idx++] = LAN91CXX_MGMT_MDOE;    bits[clk_idx++] = LAN91CXX_MGMT_MDOE | LAN91CXX_MGMT_MDO;    // Output the PHY address, msb first    for (mask = 0x10; mask; mask >>= 1) {	if (phyaddr & mask)	    bits[clk_idx++] = LAN91CXX_MGMT_MDOE | LAN91CXX_MGMT_MDO;	else	    bits[clk_idx++] = LAN91CXX_MGMT_MDOE;    }    // Output the phy register number, msb first    for (mask = 0x10; mask; mask >>= 1) {	if (phyreg & mask)	    bits[clk_idx++] = LAN91CXX_MGMT_MDOE | LAN91CXX_MGMT_MDO;	else	    bits[clk_idx++] = LAN91CXX_MGMT_MDOE;    }    // Tristate and turnaround (2 bit times)    bits[clk_idx++] = 0;    bits[clk_idx++] = 0;    // Write out 16 bits of data, msb first    for (mask = 0x8000; mask; mask >>= 1) {	if (value & mask)	    bits[clk_idx++] = LAN91CXX_MGMT_MDOE | LAN91CXX_MGMT_MDO;	else	    bits[clk_idx++] = LAN91CXX_MGMT_MDOE;    }    // Final clock bit (tristate)    bits[clk_idx++] = 0;    // Get the current MII register value    mii_reg = get_reg(sc, LAN91CXX_MGMT);    // Turn off all MII Interface bits    mii_reg &= ~(LAN91CXX_MGMT_MDOE | LAN91CXX_MGMT_MCLK | 		 LAN91CXX_MGMT_MDI | LAN91CXX_MGMT_MDO);    // Clock all cycles    for (i = 0; i < sizeof(bits); ++i) {	// Clock Low - output data	put_reg(sc, LAN91CXX_MGMT, mii_reg | bits[i]);	HAL_DELAY_US(50);	// Clock Hi - input data	put_reg(sc, LAN91CXX_MGMT, mii_reg | bits[i] | LAN91CXX_MGMT_MCLK);	HAL_DELAY_US(50);//	bits[i] |= get_reg(sc, LAN91CXX_MGMT) & LAN91CXX_MGMT_MDI;    }    // Return to idle state    put_reg(sc, LAN91CXX_MGMT, mii_reg);    HAL_DELAY_US(50);}#endif // LAN91CXX_IS_LAN91C111// EOF if_lan91cxx.c

⌨️ 快捷键说明

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