📄 smsc9118.c
字号:
volatile DWORD dwReg;
// Enable RX
dwReg = Lan_GetMacRegDW(pAdapter->lan9118_data.dwLanBase, MAC_CR);
dwReg |= MAC_CR_RXEN_;
Lan_SetMacRegDW(pAdapter->lan9118_data.dwLanBase, MAC_CR, dwReg);
// Wait for at least 64uSec
DelayUsingFreeRun(pAdapter, 64L);
}
NDIS_STATUS
SetMulticastAddressListForRev1(IN PSMSC9118_ADAPTER pAdapter)
{
DWORD dwLinkMode;
dwLinkMode = pAdapter->lan9118_data.dwLinkMode;
if (dwLinkMode == LINK_10MPS_HALF)
{
DisableMacRxEn(pAdapter);
Lan_SetMacRegDW(pAdapter->lan9118_data.dwLanBase, HASHL, pAdapter->ucNicMulticastRegs[0]);
Lan_SetMacRegDW(pAdapter->lan9118_data.dwLanBase, HASHH, pAdapter->ucNicMulticastRegs[1]);
EnableMacRxEn(pAdapter);
}
else if (dwLinkMode == LINK_10MPS_FULL)
{
DWORD dwReg;
// 10/FD Case
dwReg = Lan_GetMacRegDW(pAdapter->lan9118_data.dwLanBase, MAC_CR);
if (dwReg & MAC_CR_RXEN_)
{
SetRegDW(pAdapter->lan9118_data.dwLanBase, INT_STS, INT_STS_RXSTOP_INT_);
// Enable Interrupt
Lan_EnableInterrupt((PLAN9118_DATA)&pAdapter->lan9118_data, INT_EN_RXSTOP_INT_EN_);
dwReg = Lan_GetMacRegDW(pAdapter->lan9118_data.dwLanBase, MAC_CR);
dwReg &= ~MAC_CR_RXEN_;
Lan_SetMacRegDW(pAdapter->lan9118_data.dwLanBase, MAC_CR, dwReg);
return (NDIS_STATUS_PENDING);
}
else
{
Lan_SetMacRegDW(pAdapter->lan9118_data.dwLanBase, HASHL, pAdapter->ucNicMulticastRegs[0]);
Lan_SetMacRegDW(pAdapter->lan9118_data.dwLanBase, HASHH, pAdapter->ucNicMulticastRegs[1]);
// Enable RX_EN
Lan_SetMacRegDW(pAdapter->lan9118_data.dwLanBase, MAC_CR,
Lan_GetMacRegDW(pAdapter->lan9118_data.dwLanBase, MAC_CR) |
MAC_CR_RXEN_);
}
}
else if ((dwLinkMode == LINK_100MPS_FULL) ||
(dwLinkMode == LINK_100MPS_HALF))
{
DWORD dwReg;
dwReg = Lan_GetMacRegDW(pAdapter->lan9118_data.dwLanBase, MAC_CR);
if (dwReg & MAC_CR_RXEN_)
{
// 100/FD/HD Case
pAdapter->f100RxEnWorkaroundDone = 0L;
// Initiate SWINT Interrupt
Lan_EnableInterrupt((PLAN9118_DATA)&pAdapter->lan9118_data, INT_EN_SW_INT_EN_);
return (NDIS_STATUS_PENDING);
}
else
{
UpdateFilterAndMacReg(pAdapter);
// Enable RX
EnableMacRxEn(pAdapter);
}
}
else
{
// no link
// nothing to do
}
return NDIS_STATUS_SUCCESS;
}
/*----------------------------------------------------------------------------
SetMulticastAddressList
*/
NDIS_STATUS
SetMulticastAddressList (IN PSMSC9118_ADAPTER pAdapter)
{
UINT uiIndex;
UCHAR Table;
DWORD dwBit;
NDIS_STATUS Ret = NDIS_STATUS_SUCCESS;
SMSC_TRACE0(DBG_INIT,"+SetMulticastAddressList\r\n");
pAdapter->ucNicMulticastRegs[0] = 0UL;
pAdapter->ucNicMulticastRegs[1] = 0UL;
for (uiIndex = 0U; uiIndex < DEFAULT_MULTICASTLISTMAX; uiIndex++)
{
SMSC_TRACE6(DBG_MULTICAST,"%x-%x-%x-%x-%x-%x\r\n", pAdapter->ucAddresses[uiIndex][0], pAdapter->ucAddresses[uiIndex][1],
pAdapter->ucAddresses[uiIndex][2], pAdapter->ucAddresses[uiIndex][3],
pAdapter->ucAddresses[uiIndex][4], pAdapter->ucAddresses[uiIndex][5]);
GetMulticastBit (pAdapter->ucAddresses[uiIndex], &Table, &dwBit);
SMSC_TRACE2(DBG_MULTICAST,"Table=0x%x, dwBit=0x%x\r\n", Table, dwBit);
pAdapter->ucNicMulticastRegs[Table] |= dwBit;
SMSC_TRACE2(DBG_MULTICAST,"ucNicMulticastRegs[0]=0x%x, ucNicMulticastRegs[1]=0x%x\r\n", pAdapter->ucNicMulticastRegs[0], pAdapter->ucNicMulticastRegs[1]);
}
// workaround for 118/117/116/115 A1 (REV_ID = 0x011x0001)
if (((pAdapter->lan9118_data.dwIdRev) & 0xFFF0FFFFUL) == 0x01100001UL)
{
Ret = SetMulticastAddressListForRev1(pAdapter);
}
else
{
Lan_SetMacRegDW(pAdapter->lan9118_data.dwLanBase, HASHL, pAdapter->ucNicMulticastRegs[0]);
Lan_SetMacRegDW(pAdapter->lan9118_data.dwLanBase, HASHH, pAdapter->ucNicMulticastRegs[1]);
}
SMSC_TRACE2(DBG_MULTICAST,"HASHH=0x%x, HASHL=0x%x\r\n", Lan_GetMacRegDW(pAdapter->lan9118_data.dwLanBase, HASHH),
Lan_GetMacRegDW(pAdapter->lan9118_data.dwLanBase, HASHL));
SMSC_TRACE0(DBG_INIT,"-SetMulticastAddressList\r\n");
return Ret;
}
NDIS_STATUS
SetPacketFilterForRev1(IN PSMSC9118_ADAPTER pAdapter)
{
DWORD dwLinkMode;
dwLinkMode = pAdapter->lan9118_data.dwLinkMode;
if (dwLinkMode == LINK_10MPS_HALF)
{
DisableMacRxEn(pAdapter);
Smsc9118SetMacFilter(pAdapter);
EnableMacRxEn(pAdapter);
}
else if (dwLinkMode == LINK_10MPS_FULL)
{
DWORD dwReg;
// 10/FD Case
// Disable RX
dwReg = Lan_GetMacRegDW(pAdapter->lan9118_data.dwLanBase, MAC_CR);
if (dwReg & MAC_CR_RXEN_)
{
SetRegDW(pAdapter->lan9118_data.dwLanBase, INT_STS, INT_STS_RXSTOP_INT_);
// Enable
Lan_EnableInterrupt((PLAN9118_DATA)&pAdapter->lan9118_data, INT_EN_RXSTOP_INT_EN_);
dwReg = Lan_GetMacRegDW(pAdapter->lan9118_data.dwLanBase, MAC_CR);
dwReg &= ~MAC_CR_RXEN_;
Lan_SetMacRegDW(pAdapter->lan9118_data.dwLanBase, MAC_CR, dwReg);
return (NDIS_STATUS_PENDING);
}
else
{
Smsc9118SetMacFilter(pAdapter);
EnableMacRxEn(pAdapter);
}
}
else if ((dwLinkMode == LINK_100MPS_FULL) ||
(dwLinkMode == LINK_100MPS_HALF))
{
DWORD dwReg;
dwReg = Lan_GetMacRegDW(pAdapter->lan9118_data.dwLanBase, MAC_CR);
if (dwReg & MAC_CR_RXEN_)
{
// 100/FD/HD Case
pAdapter->f100RxEnWorkaroundDone = 0L;
// Initiate SWINT Interrupt
Lan_EnableInterrupt((PLAN9118_DATA)&pAdapter->lan9118_data, INT_EN_SW_INT_EN_);
return (NDIS_STATUS_PENDING);
}
else
{
UpdateFilterAndMacReg(pAdapter);
// Enable RX
EnableMacRxEn(pAdapter);
}
}
else
{
// no link
// nothing to do
}
return NDIS_STATUS_SUCCESS;
}
/*----------------------------------------------------------------------------
SetPacketFilter
*/
NDIS_STATUS
SetPacketFilter(IN PSMSC9118_ADAPTER pAdapter)
{
DWORD dwReg;
NDIS_STATUS Ret = NDIS_STATUS_SUCCESS;
SMSC_TRACE0(DBG_MULTICAST,"+SetPacketFilter\r\n");
// workaround for 118/117/116/115 A1 (REV_ID = 0x011x0001)
if (((pAdapter->lan9118_data.dwIdRev) & 0xFFF0FFFFUL) == 0x01100001UL)
{
Ret = SetPacketFilterForRev1(pAdapter);
}
else
{
dwReg = Lan_GetMacRegDW(pAdapter->lan9118_data.dwLanBase, MAC_CR);
dwReg &= ~MAC_CR_RXEN_;
Lan_SetMacRegDW(pAdapter->lan9118_data.dwLanBase, MAC_CR, dwReg);
dwReg &= (~(MAC_CR_MCPAS_ | MAC_CR_PRMS_ | MAC_CR_INVFILT_ | MAC_CR_HFILT_ | MAC_CR_HPFILT_ | MAC_CR_BCAST_));
if (pAdapter->ulPacketFilter & (DWORD)NDIS_PACKET_TYPE_ALL_MULTICAST)
{
dwReg |= MAC_CR_MCPAS_;
}
if (pAdapter->ulPacketFilter & (DWORD)NDIS_PACKET_TYPE_PROMISCUOUS)
{
dwReg |= MAC_CR_PRMS_;
}
if (pAdapter->ulPacketFilter & (DWORD)NDIS_PACKET_TYPE_MULTICAST)
{
dwReg |= MAC_CR_HPFILT_;
}
// FIXME
dwReg |= MAC_CR_RXEN_;
Lan_SetMacRegDW(pAdapter->lan9118_data.dwLanBase, MAC_CR, dwReg);
}
SMSC_TRACE1(DBG_MULTICAST,"***(after) MAC_CR=0x%x\r\n",
Lan_GetMacRegDW(pAdapter->lan9118_data.dwLanBase, MAC_CR));
SMSC_TRACE1(DBG_MULTICAST,"*** ADDRH=0x%x\r\n",
Lan_GetMacRegDW(pAdapter->lan9118_data.dwLanBase, ADDRH));
SMSC_TRACE1(DBG_MULTICAST,"*** ADDRL=0x%x\r\n",
Lan_GetMacRegDW(pAdapter->lan9118_data.dwLanBase, ADDRL));
SMSC_TRACE0(DBG_MULTICAST,"-SetPacketFilter\r\n");
return Ret;
}
/*----------------------------------------------------------------------------
Smsc9118SetInformation
NDIS miniport function
*/
NDIS_STATUS
Smsc9118SetInformation (IN NDIS_HANDLE hMiniportAdapterContext,
IN NDIS_OID Oid,
IN PVOID pInformationBuffer,
IN ULONG ulInformationBufferLength,
OUT PULONG pulBytesRead,
OUT PULONG pulBytesNeeded)
{
SMSC9118_ADAPTER * const pAdapter = (PSMSC9118_ADAPTER)(hMiniportAdapterContext);
const UCHAR * const pucInfoBuffer = (PUCHAR)(pInformationBuffer);
ULONG ulPacketFilter, ulLookAhead;
NDIS_STATUS StatusToReturn = NDIS_STATUS_SUCCESS;
const NDIS_PM_PACKET_PATTERN *pPattern;
NDIS_DEVICE_POWER_STATE PowerState; //power management
SMSC_TRACE1(DBG_INIT,"+Smsc9118SetInformation[0x%x]\r\n", Oid);
switch (Oid)
{
case OID_802_3_MULTICAST_LIST:
SMSC_TRACE0(DBG_MULTICAST," OID_802_3_MULTICAST_LIST\r\n");
if ((ulInformationBufferLength % (DWORD)ETHER_LENGTH_OF_ADDRESS) != 0UL)
{
StatusToReturn = NDIS_STATUS_INVALID_LENGTH;
*pulBytesRead = 0UL;
*pulBytesNeeded = 0UL;
break;
}
if (sizeof(pAdapter->ucAddresses) < (UINT)ulInformationBufferLength)
{
StatusToReturn = NDIS_STATUS_INVALID_LENGTH;
*pulBytesRead = 0UL;
*pulBytesNeeded = 0UL;
break;
}
NdisZeroMemory(pAdapter->ucAddresses, DEFAULT_MULTICASTLISTMAX*ETHER_LENGTH_OF_ADDRESS);
// Set Multicast addresses
NdisMoveMemory (pAdapter->ucAddresses, pInformationBuffer, (UINT)ulInformationBufferLength);
StatusToReturn = SetMulticastAddressList(pAdapter);
break;
case OID_GEN_CURRENT_PACKET_FILTER:
SMSC_TRACE0(DBG_MULTICAST," OID_GEN_CURRENT_PACKET_FILTER\r\n");
if (ulInformationBufferLength != 4UL)
{
StatusToReturn = NDIS_STATUS_INVALID_LENGTH;
*pulBytesRead = 0UL;
*pulBytesNeeded = 0UL;
break;
}
NdisMoveMemory (&ulPacketFilter, pucInfoBuffer, 4U);
if (ulPacketFilter & (DWORD)(NDIS_PACKET_TYPE_SOURCE_ROUTING | NDIS_PACKET_TYPE_SMT |
NDIS_PACKET_TYPE_MAC_FRAME | NDIS_PACKET_TYPE_FUNCTIONAL |
NDIS_PACKET_TYPE_ALL_FUNCTIONAL | NDIS_PACKET_TYPE_GROUP))
{
StatusToReturn = NDIS_STATUS_NOT_SUPPORTED;
*pulBytesRead = 4UL;
*pulBytesNeeded = 0UL;
RETAILMSG(1, (TEXT("Error! PacketFilter = 0x%08x\r\n"), ulPacketFilter));
break;
}
pAdapter->ulPacketFilter = ulPacketFilter;
StatusToReturn = SetPacketFilter(pAdapter);
break;
case OID_GEN_CURRENT_LOOKAHEAD:
SMSC_TRACE0(DBG_INIT," OID_GEN_CURRENT_LOOKAHEAD\r\n");
if (ulInformationBufferLength != 4UL)
{
StatusToReturn = NDIS_STATUS_INVALID_LENGTH;
*pulBytesRead = 0UL;
*pulBytesNeeded = 0UL;
break;
}
NdisMoveMemory (&ulLookAhead, pucInfoBuffer, 4U);
if (ulLookAhead <= (DWORD)MAX_LOOKAHEAD) {
pAdapter->ulMaxLookAhead = ulLookAhead;
}
else {
StatusToReturn = NDIS_STATUS_INVALID_LENGTH;
}
break;
//
// Power Management
//
case OID_PNP_SET_POWER:
SMSC_TRACE0(DBG_POWER," OID_PNP_SET_POWER\r\n");
PowerState = *(PNDIS_DEVICE_POWER_STATE)pInformationBuffer;
SetPowerState(pAdapter, PowerState);
break;
case OID_PNP_ADD_WAKE_UP_PATTERN:
SMSC_TRACE0(DBG_POWER," OID_PNP_ADD_WAKE_UP_PATTERN\r\n");
pPattern = (PNDIS_PM_PACKET_PATTERN)pInformationBuffer;
SMSC_TRACE1(DBG_POWER,"MaskSize=%d\r\n", pPattern->MaskSize);
SMSC_TRACE2(DBG_POWER,"PatternOffset=%d(0x%x)\r\n", pPattern->PatternOffset, pPattern->PatternOffset);
SMSC_TRACE1(DBG_POWER,"PatternSize=%d\r\n", pPattern->PatternSize);
if ((pPattern->PatternSize < 13UL) ||
(pPattern->MaskSize < 2UL) ||
(pPattern->MaskSize > 6UL)) //pPattern->MaskSize always <6(?)
{
// Pattern is too short, since 9118 start checking after MAC dst/src address.
if (pPattern->PatternSize < 13UL) {
SMSC_TRACE0(DBG_POWER, "WAKEUP Pattern Error: PatternSize is smaller than 13 bytes.\r\n");
}
if (pPattern->MaskSize < 2UL) {
SMSC_TRACE0(DBG_POWER, "WAKEUP Pattern Error: MaskSize is smaller than 2 bytes.\r\n");
}
else if (pPattern->MaskSize > 6UL) {
SMSC_TRACE0(DBG_POWER, "WAKEUP Pattern Error: MaskSize is larger than 6 bytes.\r\n");
}
else {
SMSC_TRACE0(DBG_POWER, "WAKEUP Pattern Error: Error! 2 <= MaskSize <= 6\r\n");
}
StatusToReturn = NDIS_STATUS_NOT_ACCEPTED;
break;
}
else
{
if ( ((pAdapter->Wuff.FilterCommands)&(FILTER3_ENABLE|FILTER2_ENABLE|FILTER1_ENABLE|FILTER0_ENABLE)) ==
(FILTER3_ENABLE|FILTER2_ENABLE|FILTER1_ENABLE|FILTER0_ENABLE) )
{
//All Wuff slots are used.
SMSC_TRACE0(DBG_POWER,"No filter is available(all 4 filters in use).\r\n");
StatusToReturn = NDIS_STATUS_RESOURCES;
break;
}
else
{
//There is at least one filter available.
if( !((pAdapter->Wuff.FilterCommands)&FILTER0_ENABLE) )
{
SetWakeUpFrameFilter(pAdapter, pPattern, 0UL);
(pAdapter->Wuff.FilterCommands) |= FILTER0_ENABLE;
(pAdapter->Wuff.FilterCommands) &= ~FILTER0_ADDR_TYPE;
}
else
{
if( !((pAdapter->Wuff.FilterCommands)&FILTER1_ENABLE) )
{
SetWakeUpFrameFilter(pAdapter, pPattern, 1UL);
(pAdapter->Wuff.FilterCommands) |= FILTER1_ENABLE;
(pAdapter->Wuff.FilterCommands) &= ~FILTER1_ADDR_TYPE;
}
else
{
if( !((pAdapter->Wuff.FilterCommands)&FILTER2_ENABLE) )
{
SetWakeUpFrameFilter(pAdapter, pPattern, 2UL);
(pAdapter->Wuff.FilterCommands) |= FILTER2_ENABLE;
(pAdapter->Wuff.FilterCommands) &= ~FILTER2_ADDR_TYPE;
}
else
{
if( !((pAdapter->Wuff.FilterCommands)&FILTER3_ENABLE) )
{
SetWakeUpFrameFilter(pAdapter
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -