smc.c

来自「PXA255 WINCE 4.2 BSP ,该BSP是商用的。」· C语言 代码 · 共 1,031 行 · 第 1/3 页

C
1,031
字号

    // Get the currently pending interrupts
    wInterruptReg = ReadWord( INTERRUPT_REG );
    // Disable any more interrupts
    WriteWord( INTERRUPT_REG, 0 );

    EDBG_ADAPTERMSG(ZONE_INTR,("+SMC_ISR: Ints pending: %X\n",wInterruptReg));

    if(wInterruptReg & RX_OVRN_INT)
    {
        EDBG_DEBUGLED(LED_OVERRUN,wInterruptReg);
        EDBG_ADAPTERMSG(ZONE_WARNING,("RX_OVRN_INT\n"));
        WriteWord( INTERRUPT_REG, RX_OVRN_INT);
    }

    // This interrupt indicates that the RX buffer is not empty.  It just stays asserted until
    //  all the Frames are read out of the buffer.  I will accept one of these and set the fFrameReceived
    //  flag to indicate this to the GetFrame() routine, then I'll disable the interrupt from here.
    //  After GetFrame() gets called it will check the buffer and if it is empty it will re-enable the
    //  interrupt.
    if(wInterruptReg & RCV_INT)
    {
        fFrameReceived = 1;
        wInterruptReg &= (~RCV_INTM);
    }

    // Restore the interrupt mask register, with possible modification
    WriteWord( INTERRUPT_REG, (USHORT)(wInterruptReg & 0xFF00) );
    WriteWord( BANKSEL_REG, wBankSave );

    EDBG_ADAPTERMSG(ZONE_INTR,("-SMC_ISR: Ints pending: %X, fFrameReceived: %u\n", wInterruptReg, fFrameReceived));
}

#ifdef SMC_DUMP_FRAMES
static void DumpEtherFrame( BYTE *pFrame, WORD cwFrameLength )
{

    int i,j;

    EdbgOutputDebugString( "Frame Buffer Address: 0x%X\r\n", pFrame );
    EdbgOutputDebugString( "To: %B:%B:%B:%B:%B:%B  From: %B:%B:%B:%B:%B:%B  Type: 0x%H  Length: %u\r\n",
                           pFrame[0], pFrame[1], pFrame[2], pFrame[3], pFrame[4], pFrame[5],
                           pFrame[6], pFrame[7], pFrame[8], pFrame[9], pFrame[10], pFrame[11],
                           ntohs(*((UINT16 *)(pFrame + 12))), cwFrameLength );
    for(i = 0; i < cwFrameLength / 16; i++)
    {
        for(j = 0; j < 16; j++)
            EdbgOutputDebugString( " %B", pFrame[i*16 + j] );
        EdbgOutputDebugString( "\r\n" );
    }
    for(j = 0; j < cwFrameLength % 16; j++)
        EdbgOutputDebugString( " %B", pFrame[i*16 + j] );
    EdbgOutputDebugString( "\r\n" );
}
#endif

// The read and write EEPROM routines access the 64 word by 16-bit EEPROM that is attached to the
//  91C94.  There are locations within the EEPROM that the chip does not need and can be used to
//  store other important information.  The memory map of the EEPROM is given in the ethernet.doc
//  spec.  The procedure used here for accessing these words is discussed on pages 88 and 89 of
//  the SMC91C94 spec.
BOOL SMCReadEEPROM( UINT16 EEPROMAddress , UINT16 *pwVal)
{

    //DWORD dwCurTime;
    UINT16 controlRegister;
    BOOL readComplete;
    WriteWord( BANKSEL_REG, BANK2 );
    WriteWord( POINTER_REG, (USHORT)((EEPROMAddress & 0x003F) | 0x6000) );
    WriteWord( BANKSEL_REG, BANK1 );
    controlRegister = ReadWord((USHORT)(CONTROL_REG));
    WriteWord( BANKSEL_REG, BANK1 );
    WriteWord( CONTROL_REG, (USHORT)(controlRegister | 0x0006));

    // Loop until EEPROM data is retrieved
    //dwCurTime = OEMEthGetSecs();
    readComplete = 1;
    //while( ReadWord( CONTROL_REG ) & 0x0003 ) {
    while(readComplete)
    {
        WriteWord( BANKSEL_REG, BANK1 );
        readComplete = ReadWord( CONTROL_REG ) & 0x0003;
        // if ((OEMEthGetSecs() - dwCurTime) > 2) {
        //     EdbgOutputDebugString("!SMCReadEEPROM read timed out\n");
        //     return FALSE;
        // }
    }
    WriteWord( BANKSEL_REG, BANK1 );
    *pwVal = ReadWord( GENERAL_REG );
    return TRUE;
}

BOOL SMCWriteEEPROM( UINT16 EEPROMAddress, UINT16 Data )
{
    DWORD dwCurTime;
    BOOL writeComplete;
    UINT16 controlRegister;
    WriteWord( BANKSEL_REG, BANK2 );
    WriteWord( POINTER_REG, (USHORT)((EEPROMAddress & 0x003F) | 0x6000) );
    WriteWord( BANKSEL_REG, BANK1 );
    WriteWord( GENERAL_REG, Data );
    WriteWord( BANKSEL_REG, BANK1 );
    controlRegister = ReadWord((USHORT)(CONTROL_REG));
    WriteWord( BANKSEL_REG, BANK1 );
    WriteWord( CONTROL_REG, (USHORT)(controlRegister | 0x0005));

    // Loop until EEPROM data is written
    dwCurTime = OEMEthGetSecs();
    writeComplete = 1;
    while(writeComplete)
    {
        //EdbgOutputDebugString("Waiting for STORE bit to clear.\n");
        WriteWord( BANKSEL_REG, BANK1 );
        writeComplete = ReadWord( CONTROL_REG ) & 0x0003;

        //if ((OEMEthGetSecs() - dwCurTime) > 5) {
        //	  EdbgOutputDebugString("!SMCWriteEEPROM read timed out\n");
        //    return FALSE;
        //}
    }
    return TRUE;
}

// Read the value on the IOS lines, used to indicate the status of the switches on both the Odo
// Ethernet board, and the SMC eval board.
UINT16 SMCReadSwitches(void)
{
    WriteWord( BANKSEL_REG, BANK3 );
    return ReadWord(MGMT_REG) >> 8;
}


#if (WINCEOSVER >= 400)
////////////////////////////////////////////////////////////////////////////////
//	SMCComputeCrc()
//	
//	Description:
//
//		Runs the AUTODIN II CRC algorithm on buffer Buffer of length Length.
//
//	Arguments:
//
//		Buffer - the input buffer
//		Length - the length of Buffer
//
//	Return value:
//
//		The 32-bit CRC value.
//
//	Note:
//
//		This function is adopted from netcard\ne2000 miniport driver.
//		
ULONG
SMCComputeCrc(
             IN PUCHAR Buffer,
             IN UINT Length)
{
    ULONG Crc, Carry;
    UINT i, j;
    UCHAR CurByte;

    Crc = 0xffffffff;

    for(i = 0; i < Length; i++)
    {
        CurByte = Buffer[i];

        for(j = 0; j < 8; j++)
        {
            Carry = ((Crc & 0x80000000) ? 1 : 0) ^ (CurByte & 0x01);
            Crc <<= 1;
            CurByte >>= 1;

            if(Carry)
            {
                Crc = (Crc ^ 0x04c11db7) | Carry;
//                Crc = (Crc ^ 0x04c11db6) | Carry;
            }
        }
    }

    return Crc;

}   //	SMCComputeCrc()


////////////////////////////////////////////////////////////////////////////////
//	SMCMulticastList()
//	
//	Description:
//
//		This function is used to set multicast addresses. This routine
//		accepts an array of multicast addresses and replaces the current
//		set of addresses with the new set.
//
//	Arguments:
//
//		pucMulticastAddresses	:: The list of multicast addressses.
//		dwNoOfAddresses			:: The number of addresses in the list.
//
//	Return value:
//
//		TRUE if successful, FALSE otherwise.
//

BOOL SMCMulticastList( PUCHAR pucMulticastAddresses, DWORD dwNoOfAddresses )
{
    UINT    i;
    UCHAR   NicMulticastRegs[8];        // register image
    DWORD   dwCRC;
	DWORD	Reg;
	DWORD	Bit;

    EdbgOutputDebugString( "+SMCMulticastList( 0x%x, %d )\r\n", 
		pucMulticastAddresses, dwNoOfAddresses );

	// Trace requested multicast addresses

    for( i=0; i<dwNoOfAddresses; i++ ) 
    {
        EdbgOutputDebugString( " Add Multicast Group [%d] = %x-%x-%x-%x-%x-%x\r\n",
			i,
			pucMulticastAddresses[6*i + 0],
			pucMulticastAddresses[6*i + 1],
			pucMulticastAddresses[6*i + 2],
			pucMulticastAddresses[6*i + 3],
			pucMulticastAddresses[6*i + 4],
			pucMulticastAddresses[6*i + 5]);
    }

    // Reset all bits to start

    memset( NicMulticastRegs, 0, sizeof(NicMulticastRegs) );

    // Turn on the bit for each address in the multicast list.

    for( i=0; i < dwNoOfAddresses; i++) 
    {
        dwCRC = SMCComputeCrc( &pucMulticastAddresses[6*i], 6 );

        // From SMC Spec:
		//
		// First compute the CRC32 of the destination address.
		// The six most significant bits are the hash value. The
		// upper 3 bits determine the multicast register MT0-MT7, 
		// the next 3 bits determine the bit within the register.

		Reg = dwCRC >> 29;					// top  3 bits
		Bit = (dwCRC >> 26) & 0x07;			// next 3 bits 
        EdbgOutputDebugString( " Setting Bit %d in Reg %d\r\n", Bit, Reg );

		// Update register image

        NicMulticastRegs[ Reg ] |= (1 << Bit);
    }

	// Trace the new image

    EdbgOutputDebugString( " New MulticastRegs (0-7) = %x-%x-%x-%x-%x-%x-%x-%x\r\n",        
		NicMulticastRegs[0],
		NicMulticastRegs[1],
		NicMulticastRegs[2],
		NicMulticastRegs[3],
		NicMulticastRegs[4],
		NicMulticastRegs[5],
		NicMulticastRegs[6],
		NicMulticastRegs[7]);
    
    //	Update the h/w registers

    WriteWord( BANKSEL_REG, BANK3);
    WriteWord( MULTITAB_REG0, *(PWORD)&NicMulticastRegs[0] );
    WriteWord( MULTITAB_REG1, *(PWORD)&NicMulticastRegs[2] );
    WriteWord( MULTITAB_REG2, *(PWORD)&NicMulticastRegs[4] );
    WriteWord( MULTITAB_REG3, *(PWORD)&NicMulticastRegs[6] ); 

	// Verify the h/w registers by reading back

    EdbgOutputDebugString( " Read back: %x-%x-%x-%x\r\n",
		ReadWord( MULTITAB_REG0 ),
		ReadWord( MULTITAB_REG1 ),
		ReadWord( MULTITAB_REG2 ),
		ReadWord( MULTITAB_REG3 ));

    EdbgOutputDebugString( "-SMCMulticastList()\r\n" );

	// Indicate success

    return( TRUE );
}

////////////////////////////////////////////////////////////////////////////////
//	SMCCurrentPacketFilter()
//	
//	Description:
//
//		This function is called to set the h/w filter.
//		We support:
//			PROMISCUOUS, ALL MULTICAST, BROADCAST, DIRECTED.
//
//	Arguments:
//
//		dwFilter::	The filter mode 
//
//	Return value:
//
//		TRUE if successful, FALSE otherwise.
//

void SMCCurrentPacketFilter( DWORD dwFilter)
{
    //
    //	EDBG always receive directed and broadcast as a minimum.
    //	So our default will be RCR_REG_INIT..
    //

    WORD    wRxControlReg = RCR_REG_INIT;

    if(dwFilter & PACKET_TYPE_ALL_MULTICAST)
        wRxControlReg |= 0x04;

    if(dwFilter & PACKET_TYPE_PROMISCUOUS)
        wRxControlReg |= 0x02;


    //
    //	I think Broadcast is always received for smc9000, so we don't
    //	need to do anything to this flag..
    //    

    EdbgOutputDebugString("SMC9000:: Set filter to : [0x%x]\r\n",
                          wRxControlReg);

    WriteWord (BANKSEL_REG, BANK0);
    WriteWord (RCR_REG, wRxControlReg);

}

#endif  // WINCEOSVER >= 400


⌨️ 快捷键说明

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