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

📄 smc.c

📁 WinCE5.0BSP for Renesas SH7770
💻 C
📖 第 1 页 / 共 3 页
字号:
    EdbgOutputDebugString( "SMC Ethernet card detected at I/O base 0x%X\r\n",pbEthernetBase);

    // Read the MAC address from the 91C94.  This should have been read in from the EEPROM during reset
	if( NULL != MacAddr ) {
	    WriteWord( BANKSEL_REG, BANK1 );
	    MacAddr[0] = ReadWord( MACADDR_REG0 );
	    MacAddr[1] = ReadWord( MACADDR_REG1 );
	    MacAddr[2] = ReadWord( MACADDR_REG2 );
	
    	EdbgOutputDebugString("SMC Ethernet Address: %B:%B:%B:%B:%B:%B\r\n",
        	                  MacAddr[0] & 0x00FF, MacAddr[0] >> 8,
            	              MacAddr[1] & 0x00FF, MacAddr[1] >> 8,
                	          MacAddr[2] & 0x00FF, MacAddr[2] >> 8);
	}

	WriteWord( BANKSEL_REG, BANK1 );
	WriteWord( CONFIG_REG, 0xB0B1 );
    
    // Initialize the control register
    WriteWord( BANKSEL_REG, BANK1 );

    WriteWord( CONTROL_REG, 0x0120 );//Unset AUTO RELEASE bit

    // Initialize transmit control register
    WriteWord( BANKSEL_REG, BANK0 );
    WriteWord( TCR_REG, TCR_REG_INIT );

    // Initialize interrupt mask register (all ints disabled to start)
    WriteWord( BANKSEL_REG, BANK2 );
    WriteWord( INTERRUPT_REG, 0);

    // The receive register should be the last thing initialzed so that we don't start
    //  getting Frames before we're ready for them.
    
    // Initialize the Receive Control Register (Pg 39 of the SMC91C94 spec):
    WriteWord( BANKSEL_REG, BANK0 );
    WriteWord( RCR_REG, RCR_REG_INIT );

    EdbgOutputDebugString("SMC Reset complete2\r\n");
    
    // Even if the card is present, it likes to have a second to stabilize before the first transmission
    while( OEMEthGetSecs() - dwStartTime < 2 );
    

    AutoNegotiation();

    EdbgOutputDebugString( "-SMCInit\r\n");
    return TRUE;
}

// Interrupts left disabled at init, call this function to turn them on
void
SMCEnableInts()
{
    // Only enable receive interrupts (we poll for Tx completion)
    wIntMask = RCV_INTM;
    WriteWord( BANKSEL_REG, BANK2 );
    WriteWord( INTERRUPT_REG, wIntMask );
}

void
SMCDisableInts()
{
    wIntMask = 0;
    WriteWord( BANKSEL_REG, BANK2 );
    WriteWord( INTERRUPT_REG, wIntMask );
}

DWORD
SMCGetPendingInterrupts()
{
    WORD wInts;
    DWORD dwRet = 0;
    UINT16 wBankSave;

    // I need to save/restore the affected registers in the 91C94
    wBankSave = ReadWord( BANKSEL_REG );
    WriteWord( BANKSEL_REG, BANK2 );
    wInts = ReadWord(INTERRUPT_REG);

    // Just check for Rx int
    if (wInts & (RCV_INT | RX_OVRN_INT)) {
        dwRet = INTR_TYPE_RX;
    }
    
    WriteWord( BANKSEL_REG, wBankSave );

    return dwRet;
}

//
// This routine is used by the OAL to configure the debug Ethernet driver. Currently
// the following options are defined:
//     OPT_BROADCAST_FILTERING  -- If set, filter out all broadcast packets except ARP packets
// 
DWORD
SMCSetOptions(DWORD dwOptions)
{
    DWORD dwOldOptions = dwConfigOptions;
    dwConfigOptions = dwOptions;
    return dwOldOptions;
}

static BOOL
SMCReleaseMemory (UINT16 wCmd)
{
    DWORD dwStartTime;
    
    // issuem the release command
    WriteWord (MMUCOMMAND_REG, wCmd);

    // Wait until release finishes executing
    dwStartTime = OEMEthGetSecs();
    while (ReadWord (MMUCOMMAND_REG) & MMU_CMD_BUSY) {
        if ((OEMEthGetSecs() - dwStartTime) > 2) {
            EdbgOutputDebugString ("!GetFrame: Timed out releasing memory (wCmd = %u)\n", wCmd);
            return FALSE;
        }
    }
    return TRUE;
}

static UINT16
SMCRetrieveFrame (BYTE *pbData, UINT16 *pwLength)
{
    UINT16 i, wStatusWord;
    UINT16 *pwData = (UINT16 *)pbData;
    UINT16 wLen;
    
    // Setup pointer address register to point to first byte of Frame
    WriteWord( POINTER_REG, 0xE000 );

    // read status and filter frames if error detected
    if (!((wStatusWord = ReadWord (DATA_REG)) & FRAME_FILTER)) {

        // The top bits of the byte count are reserved, so mask those (pg 26 of SMC91C94 spec).
        // The byte count includes the status word, byte count and control byte so subtract 6
        wLen = (0x07FF & ReadWord( DATA_REG )) - 6;
        EDBG_DEBUGLED(LED_PKTLEN,*pwLength);

        if (*pwLength < wLen) {
            EdbgOutputDebugString("SMC111: received packet larger (%u) than buffer (%u)\n",wLen, *pwLength);
            return 0x0800;  // frame too long
        }

        // For broadcast frames, filter out all except for ARPs
        i=0;
        if ((dwConfigOptions & OPT_BROADCAST_FILTERING) && (wStatusWord & BROADCAST_FILTER_BIT)) {
            for (; i< sizeof(EthernetFrameHeader); i++)
                *pwData++ = ReadWord( DATA_REG );
            if (ntohs(((EthernetFrameHeader UNALIGNED *)pbData)->wFrameType) != 0x0806) {
                return BROADCAST_FILTER_BIT;    // broadcast, not ARPs
            }
        }

        wStatusWord = 0;
        *pwLength = wLen;   // set return length
        
        // Read all but the last word, which will contain the control word
        wLen >>= 1;    // in words
        EDBG_DEBUGLED(LED_COPY,0);
        for( ; i < wLen; i++ )
            *pwData++ = ReadWord( DATA_REG );
        EDBG_DEBUGLED(LED_COPY,wLen);
            
        // Now check to see if there were an odd number of bytes sent.  If so, I have to extract the
        //  last one (pg 27 of the SCM91C94 spec).
        wLen = ReadWord( DATA_REG );
        if (wLen & 0x2000) {
            *pwData = (BYTE)wLen;
            (*pwLength)++;
        }
    }
    return wStatusWord;
}

// This routine is polled to find out if a frame has been received.  If there are no frames
//  in the RX FIFO, the routine will return 0.  If there was a frame that was received correctly,
//  it will be stored in pwData, otherwise it will be discarded.  
UINT16
SMCGetFrame( BYTE *pbData, UINT16 *pwLength )
{
    UINT16 wStatusWord;    // some error value
    WORD wInt;
    
    EDBG_ADAPTERMSG(ZONE_RECV,("+GetFrame\n"));
    EDBG_DEBUGLED(LED_GETFRAME_ENTRY,0);

    if ((DWORD) pbData & 1) {
        EdbgOutputDebugString ("!SMCGetFrame: Data MUST be 16bit aligned\r\n");
        return FALSE;
    }
    // For the bootloader we don't want to deal with interrupts, so I'll poll the ISR routine
    WriteWord( BANKSEL_REG, BANK2 );
    WriteWord (INTERRUPT_REG, 0);

    do {

        wInt = ReadWord (INTERRUPT_REG);
        if (wInt & RX_OVRN_INT) {
            // ack
            WriteWord (INTERRUPT_REG, RX_OVRN_INT);
            EDBG_ADAPTERMSG(ZONE_WARNING,("!GetFrame: RX Overrun, wInt = 0x%x\n", wInt));
        }
        if (!(wInt & RCV_INT)) {
            WriteWord (INTERRUPT_REG, wIntMask);    // re-enable interrupt
            return FALSE;   // no data
        }
    
        // receive the frame
        wStatusWord = SMCRetrieveFrame (pbData, pwLength);

        // Release the memory for the received Frame
        SMCReleaseMemory (CMD_REM_REL_TOP);

#ifdef SMC_DUMP_FRAMES        
        DumpEtherFrame(pbData, *pwLength);
#endif
        // Check the status word for errors (pg 28 of the SMC91C94 spec).
        if (wStatusWord & 0x8000)
            EdbgOutputDebugString( "GetFrame() - Receive Alignment Error\n" );
        if (wStatusWord & 0x2000)
            EdbgOutputDebugString( "GetFrame() - CRC Error\n" );
        if (wStatusWord & 0x0800)
            EdbgOutputDebugString( "GetFrame() - Frame Was Too Long\n" );
        if (wStatusWord & 0x0400)
            EdbgOutputDebugString( "GetFrame() - Frame Was Too Short\n" );

//      if (wStatusWord & 0x4000) 
//          EdbgOutputDebugString( "GetFrame() - Broadcast\n" );

    } while (wStatusWord);

    // re-enable interrupt only if there is no pending frame
    if (!(ReadWord (INTERRUPT_REG) & RCV_INT))
        WriteWord (INTERRUPT_REG, wIntMask);

    // debug message.
    EDBG_ADAPTERMSG(ZONE_RECV,("-GetFrame %s, *pwLength = %u\n", wStatusWord? "Fail" : "Success", *pwLength));
    EDBG_DEBUGLED(LED_GETFRAME_EXIT, wStatusWord);

	if (!wStatusWord && *pwLength>=4)
		*pwLength -=4;// Take away CRC
    return !wStatusWord;

} // GetFrame()



// This routine should be called with a pointer to the ethernet frame data.  It is the caller's
//  responsibility to fill in all information including the destination and source addresses and
//  the frame type.  The length parameter gives the number of bytes in the ethernet frame.
// The routine will not return until the frame has been transmitted or an error has occured.  If
//  the frame transmits successfully, 0 is returned.  If an error occured, a message is sent to
//  the serial port and the routine returns non-zero.


UINT16 SMCSendFrame( BYTE *pbData, DWORD dwLength ) 
{

    static UINT16 wFrameHandle;
    UINT16 cwBufferSize;
    UINT16 wCompletionCode = 0;
    UINT16 *pwData;
    DWORD  dwStartTime;
    BOOL bErr = FALSE;
    UINT16 wInt;
    DWORD i;
    UINT16 wTxDonePacketNum;
    static BOOL flgFirst=TRUE;

    if ((DWORD) pbData & 1) {
        EdbgOutputDebugString ("!SMCSendFrame: Data MUST be 16bit aligned\r\n");
        return FALSE;
    }

    WriteWord( BANKSEL_REG, BANK2 );
    WriteWord (INTERRUPT_REG, 0);

    EDBG_DEBUGLED(LED_SENDFRAME_ENTRY,0);
    EDBG_ADAPTERMSG(ZONE_SEND,("+SendFrame, dwLength: %u\n",dwLength));

#ifdef SMC_DUMP_FRAMES    
    DumpEtherFrame(pbData, (USHORT)dwLength);
#endif        

    // Calculate the amount of memory needed. This needs to be rounded up to an even number
    cwBufferSize = 2 + 2 + (UINT16)dwLength + 1;
    if (cwBufferSize & 1)
        cwBufferSize++;



	if(flgFirst) {
		flgFirst = FALSE;
	    // Allocate memory in the buffer for the Frame
    	WriteWord( MMUCOMMAND_REG, CMD_ALLOC | (UINT16)(1500 >> 8) );

	    // Loop here until the request is satisfied, or we timeout
    	dwStartTime = OEMEthGetSecs();
    	while (!((wInt = ReadWord( INTERRUPT_REG )) & ALLOC_INT)) {
        	if (OEMEthGetSecs() - dwStartTime > 2) {
            	EdbgOutputDebugString("Timed out waiting for ALLOC_INT\n");

            	// Get the status word so that it can be returned.
            	WriteWord( POINTER_REG, 0x2000 );
            	wCompletionCode = ReadWord( DATA_REG );
            	WriteWord (INTERRUPT_REG, wIntMask);
            	return wCompletionCode;
        	}
    	}
    	wFrameHandle = (0x3f00 & ReadWord( PNR_ARR_REG )) >> 8;
	}

    // Now write the Frame into the buffer (Pg 39 of the SMC91C94 spec)
    WriteWord( PNR_ARR_REG, wFrameHandle );
    WriteWord( POINTER_REG, 0x4000 );

    // Write the Status Word
    WriteWord( DATA_REG, 0 );
    // Write the byte count = status word + byte count + data area + control byte
    WriteWord( DATA_REG, cwBufferSize );
    // Now write all except possibly the last data byte
    pwData = (UINT16 *)pbData;
    for( i = 0; i < (dwLength >> 1); i++ )
        WriteWord( DATA_REG, *pwData++ );
    // If the number of data bytes was odd we can put that just before the Control Byte
    if (dwLength & 1)
        WriteWord( DATA_REG, (0x3000) | *(pbData + dwLength - 1));
    // Otherwise, the number of bytes is even, and I'll just pad the last byte with 0
    else
        WriteWord( DATA_REG, 0x1000 );

    // Enqueue Frame number into TX FIFO
    WriteWord( MMUCOMMAND_REG, CMD_ENQ_TX );

    bErr = TRUE;
    dwStartTime = OEMEthGetSecs();
    while (OEMEthGetSecs() - dwStartTime < 2) {
        wInt = ReadWord (INTERRUPT_REG);
        if (wInt & TX_INT) {

              wTxDonePacketNum = ReadWord (FIFOPORTS_REG);
              wTxDonePacketNum &= 0x003f;
              WriteWord( PNR_ARR_REG, wTxDonePacketNum );

              WriteWord( POINTER_REG, 0x2000 );
              if ( ReadWord( DATA_REG ) & EPH_TX_OK) {
                 bErr = FALSE;
              } else {
                 bErr = TRUE;
              }

            break;
        }
    }
    if (bErr)
        EdbgOutputDebugString( "SendFrame timeout waiting for TX interrupt! INTERRUPT_REG = 0x%x\r\n", wInt);

    if (bErr) {
        // Get the status word so that it can be returned.
        WriteWord( POINTER_REG, 0x2000 );
        wCompletionCode = ReadWord( DATA_REG );

        SendFrameError("!EDBG error ",wCompletionCode);
        

⌨️ 快捷键说明

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