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 + -
显示快捷键?