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

📄 lan91c11x.c

📁 umon bootloader source code, support mips cpu.
💻 C
📖 第 1 页 / 共 2 页
字号:

                if (packet_num & LAN_FIFOPORT_RCVFIFO_EMPTY)
                {
                		if (EtherVerbose)
                    	    printf("lan91c11x WARNING: nothing on rx FIFO. \n");
                        return 0;
                }
                // definitely got a packet
                EtherRFRAMECnt++;

                // tell the lan91c11x to move the received packet to the
                // data area so we can process it
                lan91c11x_wr(LAN_PTR, LAN_PTR_RCV
                                                        | LAN_PTR_AUTOINC
                                                        | LAN_PTR_READ);

                for(i = 0; i < 100; i++);                       /* delay necessary between POINTER */
                                                                                        /* and DATA access. */
                rfsw = lan91c11x_rd(LAN_DATA1);         /* Receive frame status word */
                count = lan91c11x_rd(LAN_DATA1);        /* Byte count. */
                if (count < 16)
                {
                		if (EtherVerbose)
                        	printf("lan91c11x Invalid receive count = 0x%04x, Status Word = 0x%04x.\n", count, rfsw);
                        return 0;
                }
                count &= 0x7ff;                                         /* Upper 5 bits are reserved. */
                count -= 4;                                                     /* Deduct for RFSW and ByteCount */
                if (!(rfsw & LAN_RFSW_ODD_LEN))         /* Deduct for CTRL byte and possibly */
                        pktsize = count - 2;                    /* one more because len != odd. */
                else
                        pktsize = count - 1;
                data = (ushort *)pktbuf;                        // we do 16-bit reads
                if (count >= 1600)
                {
                		if (EtherVerbose)
                        	printf("lan91c11x geteinbuf() overflow (cnt=0x%04x)\n",count);
                        enreset();
                        eninit();
                        return 0;       // no packets available
                }

                // retreive the receieve packet
                if (count & 1) count++;
                while(count > 0)
                {
                        *data++ = lan91c11x_rd(LAN_DATA1);
                        count -= 2;
                }

                // tell the lan91c11x to release the memory used by this packet
                lan91c11x_wr(LAN_MMU_CMD, LAN_MMU_CMD_RMRELRXFRAME);

                // check the frame for errors and update the appropriate counters
                if (rfsw & (LAN_RFSW_ALGN_ERR
                                  | LAN_RFSW_BADCRC
                                  | LAN_RFSW_TOOLNG
                                  | LAN_RFSW_TOOSHORT))
                {
                        if (rfsw & LAN_RFSW_ALGN_ERR) {
                                EtherALGNERRCnt++;
                				if (EtherVerbose)
                            	    printf("Frame alignment error!\n");
                        }
                        if (rfsw & LAN_RFSW_BADCRC) {
                                EtherBADCRCCnt++;
                				if (EtherVerbose)
                                	printf("Bad CRC!\n");
                        }
                        if (rfsw & LAN_RFSW_TOOLNG) {
                                EtherTOOLONGCnt++;
                				if (EtherVerbose)
                                	printf("Frame too long!\n");
                        }
                        if (rfsw & LAN_RFSW_TOOLNG) {
                                EtherTOOSHORTCnt++;
                				if (EtherVerbose)
                                	printf("Frame too short!\n");
                        }
                        return(-1);
                }
                processPACKET((struct ether_header *)pktbuf, pktsize);

                if (EtherVerbose == SHOW_ALL){
                        printf("lan91c11x: Receive Packet Complete.\n");
                }
                return count;
        } // if RCV_INT
        return 0;
}
                                        


void
lan91c11x_show_stats(void)
{
	ushort status;

	printf("Receiver overrun errors: %d\n",EtherRXOVRNCnt);
	printf("Alignment errors:        %d\n",EtherALGNERRCnt);
	printf("Bad CRC errors:          %d\n",EtherBADCRCCnt);
	printf("Packet too long errors:  %d\n",EtherTOOLONGCnt);
	printf("Packet too short errors: %d\n",EtherTOOSHORTCnt);
	printf("Wait-for-alloc timeouts: %d\n",EtherWFATMTCnt);

	status = lan91c11x_phy(PHY_INT, 0, 0);
	printf("Link: %dBaseT %s duplex\n",
		status & PHY_INT_SPDDET ? 100 : 10,
		status & PHY_INT_DPLXDET ? "full" : "half");
}

//--------------------------------------------------------------------------
// lan91c11x_phy()
//
// This function reads or writes a register in the lan91c11x PHY
//
ushort lan91c11x_phy(uchar phyreg, ushort phydata, int phy_dir)
{
        int i;
        ushort mask;
        ushort bits[64];        // array to hold the writes to the LAN_MGMT Register
        int clk_idx = 0;
        int input_idx = 0;

        // 32 consecutive ones on MDO to establish sync
        for (i = 0; i < 32; ++i)
                bits[clk_idx++] = LAN_MGMT_MDOE | LAN_MGMT_MDO;

        // Start code <01>
        bits[clk_idx++] = LAN_MGMT_MDOE;
        bits[clk_idx++] = LAN_MGMT_MDOE | LAN_MGMT_MDO;

        if (phy_dir == 0)       // read
        {
                // Read command <10>
                bits[clk_idx++] = LAN_MGMT_MDOE | LAN_MGMT_MDO;
                bits[clk_idx++] = LAN_MGMT_MDOE;
        }
        else
        {
                // Write command <01>
                bits[clk_idx++] = LAN_MGMT_MDOE;
                bits[clk_idx++] = LAN_MGMT_MDOE | LAN_MGMT_MDO;
        }

        // Output the PHY address, msb first - Internal PHY is address 0
        for (i = 0; i < 5; ++i)
        {
                        bits[clk_idx++] = LAN_MGMT_MDOE;
        }

        // Output the phy register number, msb first
        mask = 0x10;
        for (i = 0; i < 5; ++i)
                {
                if (phyreg & mask)
                        bits[clk_idx++] = LAN_MGMT_MDOE | LAN_MGMT_MDO;
                else
                        bits[clk_idx++] = LAN_MGMT_MDOE;


                // Shift to next lowest bit
                mask >>= 1;
                }

        if (phy_dir == 0)       // read
        {
                // 1 extra bit time for turnaround
                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;
        }
        else    // write
        {
                // 2 extra bit times for turnaround
                bits[clk_idx++] = 0;
                bits[clk_idx++] = 0;

                // Write out 16 bits of data, msb first
                mask = 0x8000;
                for (i = 0; i < 16; ++i)
                {
                        if (phydata & mask)
                                bits[clk_idx++] = LAN_MGMT_MDOE | LAN_MGMT_MDO;
                        else
                                bits[clk_idx++] = LAN_MGMT_MDOE;

                        // Shift to next lowest bit
                        mask >>= 1;
                }
        } // else write

        // Final clock bit
        bits[clk_idx++] = 0;

        // Turn off all MII Interface bits
        lan91c11x_wr(LAN_MGMT, lan91c11x_rd(LAN_MGMT) & 0xfff0);

        // Clock all 64 cycles
        for (i = 0; i < sizeof bits; ++i)
                {
                // Clock Low - output data
                lan91c11x_wr(LAN_MGMT, bits[i]);
                monDelay(2);

                // Clock Hi - input data
                lan91c11x_wr(LAN_MGMT, bits[i] | LAN_MGMT_MCLK);
                monDelay(2);
                bits[i] |= lan91c11x_rd(LAN_MGMT) & LAN_MGMT_MDI;
                }

        // Return to idle state
        // Set clock to low, data to low, and output tristated
        lan91c11x_wr(LAN_MGMT, lan91c11x_rd(LAN_MGMT) & 0xfff0);
        monDelay(2);

        if (phy_dir == 0)       // read
        {
                // Recover input data
                phydata = 0;
                for (i = 0; i < 16; ++i)
                {
                        phydata <<= 1;


                        if (bits[input_idx++] & LAN_MGMT_MDI)
                                phydata |= 0x0001;
                }
                if (EtherVerbose == SHOW_ALL)
                {
                        printf("Read lan91c11x_phy_register(): phyreg=%x,phydata=%x\n",
                        phyreg, phydata);
                }
        } // if read
        else // write
        {
                if (EtherVerbose == SHOW_ALL)
                {
                        printf("Wrote lan91c11x_phy_register(): phyreg=%x,phydata=%x\n",
                        phyreg, phydata);
                }
        }
        return(phydata);        
}

//--------------------------------------------------------------------------
// lan91c11x_phy()
//
// This function configures the lan91c11x PHY using autonegotiation
//
int lan91c11x_phy_cfg()
{
        int timeout;
        ushort my_phy_caps; // My PHY capabilities
        ushort my_ad_caps; // My Advertised capabilities
        ushort status = 0;

        // Reset the PHY, setting all other bits to zero
        lan91c11x_phy(PHY_CNTL, PHY_CNTL_RST, 1);

        // Wait for the reset to complete, or time out
        timeout = 3000; // Wait up to 3 seconds
        while (timeout--)
        {
                if (!(lan91c11x_phy(PHY_CNTL, 0, 0) & PHY_CNTL_RST)) break;
                monDelay(2); // wait 2 millisec
        }


        if (timeout < 1)
        {
                printf("lan91c11x PHY Reset Timed Out!\n");
                return -1;
        }

        // Copy our capabilities from PHY_STAT to PHY_AD
        my_phy_caps = lan91c11x_phy(PHY_STAT, 0, 0);
        my_ad_caps  = PHY_AD_CSMA; // I am CSMA capable

        if (my_phy_caps & PHY_STAT_CAP_T4)
                my_ad_caps |= PHY_AD_T4;

        if (my_phy_caps & PHY_STAT_CAP_TXF)
                my_ad_caps |= PHY_AD_TX_FDX;

        if (my_phy_caps & PHY_STAT_CAP_TXH)
                my_ad_caps |= PHY_AD_TX_HDX;

        if (my_phy_caps & PHY_STAT_CAP_TF)
                my_ad_caps |= PHY_AD_10_FDX;

        if (my_phy_caps & PHY_STAT_CAP_TH)
                my_ad_caps |= PHY_AD_10_HDX;

        lan91c11x_phy(PHY_AD, my_ad_caps, 1);

        if (EtherVerbose)
 	       printf("lan91c11x phy advertised caps=%x\n", my_ad_caps);

        // Restart auto-negotiation process in order to advertise my caps
        lan91c11x_phy(PHY_CNTL, (PHY_CNTL_ANEG_EN | PHY_CNTL_ANEG_RST), 1);

        // Wait for the auto-negotiation to complete.  This may take from
        // 2 to 3 seconds.
        timeout = 50; 
        while (timeout--)
                {
                status = lan91c11x_phy(PHY_STAT, 0, 0);
                if (status & PHY_STAT_ANEG_ACK)
                {
                        // auto-negotiate complete
                        break;
                }

                monDelay(2); // wait 2 millisec

                // Restart auto-negotiation again if remote fault
                if (status & PHY_STAT_REM_FLT)
                {
                        printf("lan91c11x phy remote fault detected.\n");

                        // Restart auto-negotiation
                        printf("lan91c11x phy restarting auto-negotiation.\n");
                        lan91c11x_phy(PHY_CNTL, (PHY_CNTL_ANEG_EN 
                                                                   | PHY_CNTL_ANEG_RST 
                                                                   | PHY_CNTL_SPEED 
                                                                   | PHY_CNTL_DPLX), 1);

                } // if remote fault
        }       // while autonegotiate

        if (timeout < 1)
        {
                printf("lan91c11x phy auto-negotiate timed out.\n");
                lan91c11x_phy(PHY_CNTL,0,1);
        }

        // Fail if we detected an auto-negotiate remote fault
        if (status & PHY_STAT_REM_FLT)
                {
                printf("lan91c11x phy remote fault detected, aborting autonegotiate process.\n");
                return -1;
                }

        // Display auto-negotiation results
        status = lan91c11x_phy(PHY_INT, 0, 0);
		if (EtherVerbose) {
	        if ( status & PHY_INT_SPDDET )
                printf("lan91c11x phy Link Speed = 100BaseT\n");
	        else
                printf("lan91c11x phy Link Speed = 10BaseT\n");

	        if ( status & PHY_INT_DPLXDET )
                printf("lan91c11x phy Link Duplex = Full\n");
	        else
                printf("lan91c11x phy Link Duplex = Half\n");
		}
        return 0;
}


#endif // INCLUDE_ETHERNET

⌨️ 快捷键说明

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