📄 rtl8139.c
字号:
OUTPORT32((UINT32*)(g_rtl8139.address + RTL_MAR0), 0);
OUTPORT32((UINT32*)(g_rtl8139.address + RTL_MAR4), 0);
// Configure RX
if (g_rtl8139.rxSize >= 64 * 1024) {
u32 = RCR_RBLEN64;
} else if (g_rtl8139.rxSize >= 32 * 1024) {
u32 = RCR_RBLEN32;
} else if (g_rtl8139.rxSize >= 16 * 1024) {
u32 = RCR_RBLEN16;
} else {
u32 = RCR_RBLEN8;
}
u32 |= RCR_RXFTH16 | RCR_MXDMA16 | RCR_AR | RCR_AB | RCR_APM;
OUTPORT32((UINT32*)(g_rtl8139.address + RTL_RCR), u32);
OUTPORT32(
(UINT32*)(g_rtl8139.address + RTL_RBSTART),
OALVAtoPA((VOID*)g_rtl8139.rxBuffer)
);
// Actual filter
g_rtl8139.filter = PACKET_TYPE_DIRECTED | PACKET_TYPE_BROADCAST;
// Clear all interrupts
OUTPORT16((UINT16*)(g_rtl8139.address + RTL_ISR), 0xFFFF);
// Done
rc = TRUE;
clean:
OALMSGS(OAL_ETHER&&OAL_FUNC, (L"-RTL8139Init(rc = %d)\r\n", rc));
return rc;
}
//------------------------------------------------------------------------------
//
// Function: RTL8139SendFrame
//
UINT16 RTL8139SendFrame(UINT8 *pData, UINT32 length)
{
UINT32 *pTsd;
UINT32 buffer, start;
OALMSGS(OAL_ETHER&&OAL_VERBOSE, (
L"+RTL8139SendFrame(0x%08x, %d)\r\n", pData, length
));
// Wait until buffer is released by hardware
pTsd = (UINT32*)(g_rtl8139.address + RTL_TSD0 + (g_rtl8139.txPos << 2));
start = OALGetTickCount();
while ((INPORT32(pTsd) & TSR_OWN) == 0) {
if ((OALGetTickCount() - start) > 2000) {
OALMSGS(OAL_ERROR, (L"ERROR: RTL8139SendFrame: Send timeout\r\n"));
return 1;
}
}
// Copy data to buffer
buffer = g_rtl8139.txBuffer + g_rtl8139.txPos * MAC_TX_BUFFER_SIZE;
memcpy((VOID*)buffer, pData, length);
if (length < 60) {
memset((VOID*)(buffer + length), 0, 60 - length);
length = 60;
}
// Write TSD register to start send
OUTPORT32(pTsd, length);
// Move to next position
if (++g_rtl8139.txPos >= MAC_TX_BUFFERS) g_rtl8139.txPos = 0;
OALMSGS(OAL_ETHER&&OAL_VERBOSE, (L"-RTL8139SendFrame(rc = 0)\r\n"));
return 0;
}
//------------------------------------------------------------------------------
//
// Function: RTL8139GetFrame
//
UINT16 RTL8139GetFrame(UINT8 *pData, UINT16 *pLength)
{
UINT16 offset, length, status, len1;
BOOL ok;
OALMSGS(OAL_ETHER&&OAL_VERBOSE, (
L"+RTL8139GetFrame(0x%08x, %d)\r\n", pData, *pLength
));
length = 0;
ok = FALSE;
while ((INPORT8((UINT8*)(g_rtl8139.address + RTL_CR)) & CR_BUFE) == 0) {
// Get read offset
offset = INPORT16((UINT16*)(g_rtl8139.address + RTL_CAPR)) + 0x10;
// Read packet status and length
status = *(UINT16*)(g_rtl8139.rxBuffer + offset);
length = *(UINT16*)(g_rtl8139.rxBuffer + offset + 2) - 4;
offset += 4;
if (offset >= g_rtl8139.rxSize) offset = 0;
// When packet is OK copy it to buffer
if ((status & RSR_ROK) != 0 && length <= *pLength) {
len1 = g_rtl8139.rxSize - offset;
if (length <= len1) {
memcpy(pData, (VOID*)(g_rtl8139.rxBuffer + offset), length);
} else {
memcpy(pData, (VOID*)(g_rtl8139.rxBuffer + offset), len1);
memcpy(pData + len1, (VOID*)g_rtl8139.rxBuffer, length - len1);
}
ok = TRUE;
}
// Update read offset
offset += (length + 7) & ~3;
if (offset >= g_rtl8139.rxSize) offset -= g_rtl8139.rxSize;
OUTPORT16((UINT16*)(g_rtl8139.address + RTL_CAPR), offset - 0x10);
// If packet is ok, we have all we need
if (ok) break;
length = 0;
}
// If there isn't a packet ack the interrupt
if (length == 0) OUTPORT16((UINT16*)(g_rtl8139.address + RTL_ISR), 0xFFFF);
// Return packet size
*pLength = length;
OALMSGS(OAL_ETHER&&OAL_VERBOSE, (
L"-RTL8139GetFrame(length = %d)\r\n", length
));
return length;
}
//------------------------------------------------------------------------------
//
// Function: RTL8139EnableInts
//
VOID RTL8139EnableInts()
{
OALMSGS(OAL_ETHER&&OAL_FUNC, (L"+RTL8139EnableInts\r\n"));
// We are only interested in RX interrupts
OUTPORT16((UINT16*)(g_rtl8139.address + RTL_IMR), IR_ROK);
OALMSGS(OAL_ETHER&&OAL_FUNC, (L"-RTL8139EnableInts\r\n"));
}
//------------------------------------------------------------------------------
//
// Function: RTL8139DisableInts
//
VOID RTL8139DisableInts()
{
OALMSGS(OAL_ETHER&&OAL_FUNC, (L"+RTL8139DisableInts\r\n"));
OUTPORT16((UINT16*)(g_rtl8139.address + RTL_IMR), 0);
OALMSGS(OAL_ETHER&&OAL_FUNC, (L"-RTL8139DisableInts\r\n"));
}
//------------------------------------------------------------------------------
//
// Function: RTL8139CurrentPacketFiler
//
VOID RTL8139CurrentPacketFilter(UINT32 filter)
{
UINT32 ctrl;
OALMSGS(OAL_ETHER&&OAL_FUNC, (
L"+RTL8139CurrentPacketFilter(0x%08x)\r\n", filter
));
ctrl = INPORT32((UINT32*)(g_rtl8139.address + RTL_RCR));
// First set hash functions
if (
(filter & PACKET_TYPE_PROMISCUOUS) != 0 ||
(filter & PACKET_TYPE_ALL_MULTICAST) != 0
) {
OUTPORT32((UINT32*)(g_rtl8139.address + RTL_MAR0), 0xFFFFFFFF);
OUTPORT32((UINT32*)(g_rtl8139.address + RTL_MAR4), 0xFFFFFFFF);
} else {
OUTPORT32((UINT32*)(g_rtl8139.address + RTL_MAR0), g_rtl8139.hash[0]);
OUTPORT32((UINT32*)(g_rtl8139.address + RTL_MAR4), g_rtl8139.hash[1]);
}
// Then global
if (
(filter & PACKET_TYPE_PROMISCUOUS) != 0 ||
(filter & PACKET_TYPE_ALL_MULTICAST) != 0 ||
(filter & PACKET_TYPE_MULTICAST) != 0
) {
ctrl |= RCR_AM;
} else {
ctrl &= ~RCR_AM;
}
if ((filter & PACKET_TYPE_PROMISCUOUS) != 0) {
ctrl |= RCR_AAP;
} else {
ctrl &= ~RCR_AAP;
}
// Set filter to hardware
OUTPORT32((UINT32*)(g_rtl8139.address + RTL_RCR), ctrl);
// Save actual filter
g_rtl8139.filter = filter;
OALMSGS(OAL_ETHER&&OAL_FUNC, (L"-RTL8139CurrentPacketFilter\r\n"));
}
//------------------------------------------------------------------------------
//
// Function: RTL8139MulticastList
//
BOOL RTL8139MulticastList(UINT8 *pAddresses, UINT32 count)
{
UINT32 i, crc, bit;
UINT8 hash[8];
OALMSGS(OAL_ETHER&&OAL_FUNC, (
L"+RTL8139MulticastList(0x%08x, %d)\r\n", pAddresses, count
));
memset(hash, 0, sizeof(hash));
for (i = 0; i < count; i++) {
crc = ComputeCRC(pAddresses, 6);
bit = (crc >> 26) & 0x3f;
hash[bit >> 3] |= 1 << (bit & 0x07);
pAddresses += 6;
}
g_rtl8139.hash[0] = (hash[3] << 24)|(hash[2] << 16)|(hash[1] << 8)|hash[0];
g_rtl8139.hash[1] = (hash[7] << 24)|(hash[6] << 16)|(hash[5] << 8)|hash[4];
// But update only if all multicast and promiscuous mode aren't active
if (
(g_rtl8139.filter & PACKET_TYPE_ALL_MULTICAST) == 0 &&
(g_rtl8139.filter & PACKET_TYPE_PROMISCUOUS) == 0
) {
OUTPORT32((UINT32*)(g_rtl8139.address + RTL_MAR0), g_rtl8139.hash[0]);
OUTPORT32((UINT32*)(g_rtl8139.address + RTL_MAR4), g_rtl8139.hash[1]);
}
OALMSGS(OAL_ETHER&&OAL_FUNC, (L"-RTL8139MulticastList(rc = 1)\r\n"));
return TRUE;
}
//------------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -