📄 rtl8139.c
字号:
// Caller ** MUST HAVE ** called RTL8139InitDMABuffer()
//
sRTL8139.pucTxBuffer = (PUCHAR)(dwTxStartAddress);
sRTL8139.pucRxBuffer = (PUCHAR)(dwRxStartAddress);
sRTL8139.puLastRxAddress = sRTL8139.pucRxBuffer + dwRxLength - 1;
PRINTF (1, ("RTL8139Init():: TxBuff[0x%x] - RxBuff[0x%x] - LastRx[0x%x]\r\n",
sRTL8139.pucTxBuffer,
sRTL8139.pucRxBuffer,
sRTL8139.puLastRxAddress));
////////////////////////////////////////////////////////////////////////////
// First stop, soft reset the NIC, and fill up the MacAddr.
//
if( NULL != MacAddr ) {
WRITE_PORT_UCHAR(RTL_CR, RTL8139_COMMAND_RESET);
while(READ_PORT_UCHAR(RTL_CR) & RTL8139_COMMAND_RESET)
;
WRITE_PORT_UCHAR(
RTL_CR,
(RTL8139_COMMAND_TX_ENABLE | RTL8139_COMMAND_RX_ENABLE));
dwScrap = READ_PORT_ULONG(RTL_IDR0);
sRTL8139.usMacAddr[0] = (USHORT)(dwScrap);
sRTL8139.usMacAddr[1] = (USHORT)(dwScrap >> 16);
dwScrap = READ_PORT_ULONG(RTL_IDR4);
sRTL8139.usMacAddr[2] = (USHORT)(dwScrap);
PRINTF (1, ("RTL8139Init:: MAC = %B-%B-%B-%B-%B-%B\r\n",
sRTL8139.usMacAddr[0] & 0x00FF,
sRTL8139.usMacAddr[0] >> 8,
sRTL8139.usMacAddr[1] & 0x00FF,
sRTL8139.usMacAddr[1] >> 8,
sRTL8139.usMacAddr[2] & 0x00FF,
sRTL8139.usMacAddr[2] >> 8));
memcpy(
&(MacAddr[0]),
&(sRTL8139.usMacAddr[0]),
6);
}
#ifndef AUTO_NEGOTIATE
////////////////////////////////////////////////////////////////////////////
// Currently hardcode to:
// - 10Mbps
// - Auto negotiation disabled.
// - Simplex
//
PRINTF (1, ("Hardcoded to 10Mbps..\r\n"));
usScrap = READ_PORT_USHORT(RTL_BMCR);
usScrap &= ~(RTL_100MBPS | RTL_FULL_DUPLEX | RTL_AUTO_NEGOTIATE_ENABLE);
WRITE_PORT_USHORT(RTL_BMCR, usScrap);
#else
//
// Auto Negotiate!!
//
PRINTF (1, ("RTL8139 ethdbg library: AutoNegotiate..\r\n"));
WRITE_PORT_USHORT(RTL_BMCR, 0x1000);
#endif
////////////////////////////////////////////////////////////////////////////
// Prepare the TX buffers & descriptors.
//
for (i = 0x00 ; i < NUM_TX_DESC ; i++)
{
WRITE_PORT_ULONG(
RTL_TSAD_X(i),
TO_REAL((DWORD)(sRTL8139.pucTxBuffer + i * ONE_BUFFER_SIZE)));
}
////////////////////////////////////////////////////////////////////////////
// TX DMA burst size per TX DMA burst.
//
WRITE_PORT_ULONG(
RTL_TCR,
(TX_DMA_BURST_SIZE) | 0x03000000);
//
// Init multicast registers to 0
//
memset(
g_pucMulticastList,
0x00,
MAX_MULTICAST_LIST * 6);
g_dwMulticastListInUse = 0x00;
RTL8139HWSetMCRegs(NULL, FALSE);
////////////////////////////////////////////////////////////////////////////
// Now, prepare the RX buffers & descriptors and RX Mode.
// Hardcode to accept only broadcast and myself.
//
g_dwRCR = RX_BROADCAST |
RX_UNICAST |
dwRxLengthBit |
RX_DMA_BURST_SIZE |
RX_ACCEPT_RUNT;
WRITE_PORT_ULONG (RTL_RCR, g_dwRCR);
WRITE_PORT_ULONG(
RTL_RBSTART,
TO_REAL((DWORD)(sRTL8139.pucRxBuffer)));
WRITE_PORT_USHORT(
RTL_ANAR,
0x21);
WRITE_PORT_USHORT(
RTL_ISR,
0xffff);
#if 0
DumpAll8139Regs();
#endif
return TRUE;
} // RTL8139Init()
////////////////////////////////////////////////////////////////////////////////
// RTL8139EnableInts()
//
void
RTL8139EnableInts(void)
{
PRINTF (1, ("+RTL8139EnableInts()..\r\n"));
////////////////////////////////////////////////////////////////////////////
// We are only interested in RX interrupts.
// Also turn on TX interrupts for quick purge of TX descriptors..
//
WRITE_PORT_USHORT(
RTL_IMR,
0x05);
PRINTF (1, ("-RTL8139EnableInts()..\r\n"));
} // RTL8139EnableInts()
////////////////////////////////////////////////////////////////////////////////
// RTL8139DisableInts()
//
void
RTL8139DisableInts(void)
{
PRINTF (0, ("RTL8139DisableInts()..\r\n"));
WRITE_PORT_USHORT(
RTL_IMR,
0x00);
} // RTL8139DisableInts()
#define RX_ERR_ISE (1 << 5)
#define RX_ERR_RUNT (1 << 4)
#define RX_ERR_LONG (1 << 3)
#define RX_ERR_CRC (1 << 2)
#define RX_ERR_FAE (1 << 1)
#define BAD_RX_PACKET \
(RX_ERR_ISE | RX_ERR_RUNT | RX_ERR_LONG | RX_ERR_CRC | RX_ERR_FAE)
////////////////////////////////////////////////////////////////////////////////
// ExtractData()
// This function will take the buffer pointer and it's start and end address.
// It will extract dwSize amount of bytes and handle the wrap around case.
//
UCHAR *
ExtractData(
UCHAR *pucSource,
UCHAR *pucSourceHead,
UCHAR *pucSourceTail,
UCHAR *pucDest,
DWORD dwSize)
{
PRINTF (0, ("Extracting fr [0x%x] - to [0x%x] - H[0x%x] - T[0x%x] - tot [%d]\r\n",
pucSource,
pucDest,
pucSourceHead,
pucSourceTail,
dwSize));
if (pucSource + dwSize <= pucSourceTail)
{
////////////////////////////////////////////////////////////////////////
// No problem, straight copy.
//
memcpy(
pucDest,
pucSource,
dwSize);
PRINTF (0, ("Returning: [0x%x]\r\n",
(pucSource + dwSize)));
return (pucSource + dwSize);
}
else
{
DWORD dwFirstCopySize;
////////////////////////////////////////////////////////////////////////
// Wrap around copy..
//
dwFirstCopySize = pucSourceTail - pucSource + 1;
memcpy(
pucDest,
pucSource,
dwFirstCopySize);
memcpy(
pucDest + dwFirstCopySize,
pucSourceHead,
dwSize - dwFirstCopySize);
PRINTF (0, ("ReturningWrap: [0x%x]\r\n",
(pucSource + (dwSize - dwFirstCopySize))));
return (pucSourceHead + (dwSize - dwFirstCopySize));
}
} // ExtractData()
////////////////////////////////////////////////////////////////////////////////
// RTL8139GetFrame()
// Fill up pbData with the next availabe packet in the RX FIFO.
//
UINT16
RTL8139GetFrame(BYTE *pbData, UINT16 *pwLength)
{
PACKET_HEADER PacketHeader;
UCHAR *pucRxBuffer;
PRINTF (0, ("RTL8139GetFrame()..\r\n"));
*pwLength = 0x00;
if (!(READ_PORT_UCHAR(RTL_CR) & RTL8139_COMMAND_BUFFER_EMPTY))
{
pucRxBuffer = sRTL8139.pucRxBuffer + sRTL8139.dwCurrentRxOffset;
PRINTF (0, ("$ "));
PRINTF (0, ("[a] [0x%x]\r\n", pucRxBuffer));
////////////////////////////////////////////////////////////////////////
// Now, the first 4 bytes form the PACKET_HEADER.
//
pucRxBuffer = ExtractData(
pucRxBuffer,
sRTL8139.pucRxBuffer,
sRTL8139.puLastRxAddress,
(PUCHAR)&PacketHeader,
sizeof(PACKET_HEADER));
PRINTF (0, ("[b] [0x%x]\r\n", pucRxBuffer));
PRINTF (0, (">> One RX packet:: Offset = [0x%x] - Header = [0x%x] - Length = [%d] bytes.\r\n",
sRTL8139.dwCurrentRxOffset,
PacketHeader.usPacketHeader,
PacketHeader.usPacketLength));
if (PacketHeader.usPacketHeader & BAD_RX_PACKET)
{
PRINTF (1, ("Bad RX packet [Header: 0x%x -- Length : [%d]]...\r\n",
PacketHeader.usPacketHeader,
PacketHeader.usPacketLength));
pucRxBuffer = ExtractData(
pucRxBuffer,
sRTL8139.pucRxBuffer,
sRTL8139.puLastRxAddress,
pbData,
PacketHeader.usPacketLength);
sRTL8139.dwCurrentRxOffset =
(pucRxBuffer - sRTL8139.pucRxBuffer + 3) & ~3;
WRITE_PORT_USHORT(
RTL_CAPR,
(USHORT)(sRTL8139.dwCurrentRxOffset - 0x10));
// ack the interrupt so we can get interrupted again
WRITE_PORT_USHORT(
RTL_ISR,
0xffff);
return 0x00;
}
else
{
pucRxBuffer = ExtractData(
pucRxBuffer,
sRTL8139.pucRxBuffer,
sRTL8139.puLastRxAddress,
pbData,
PacketHeader.usPacketLength);
PRINTF (0, ("[c] [0x%x]\r\n", pucRxBuffer));
*pwLength = (PacketHeader.usPacketLength - 4);
// DumpMemory(
// pbData,
// 48);
sRTL8139.dwCurrentRxOffset =
(pucRxBuffer - sRTL8139.pucRxBuffer + 3) & ~3;
PRINTF (0, ("[d] Offset = [0x%x]\r\n",
sRTL8139.dwCurrentRxOffset));
}
WRITE_PORT_USHORT(
RTL_CAPR,
(USHORT)(sRTL8139.dwCurrentRxOffset - 0x10));
return *pwLength;
}
else
{
PRINTF (0, ("# "));
// ack the interrupt so we can get interrupted again
WRITE_PORT_USHORT(
RTL_ISR,
0xffff);
return 0x00;
}
} // RTL8139GetFrame()
////////////////////////////////////////////////////////////////////////////////
// RTL8139SendFrame()
// 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 return immediately regardless of whether transmission
// has successfully been performed.
//
#define TX_OWN_BIT (1 << 13)
#define TX_TOK_BIT (1 << 15)
#define TX_ABORT (1 << 30)
#define FREE_TX_DESCRIPTOR (TX_TOK_BIT)
#define GET_TSD(x) \
(READ_PORT_ULONG(RTL_TSD_X(x)) & FREE_TX_DESCRIPTOR)
void
PurgeTxDescriptors()
{
int i = 0x00;
while((sRTL8139.dwFreeTxDescriptors < NUM_TX_DESC) &&
(GET_TSD(sRTL8139.dwCurrentHwTxDescriptor) & FREE_TX_DESCRIPTOR))
{
i++;
NEXT(sRTL8139.dwCurrentHwTxDescriptor, NUM_TX_DESC);
sRTL8139.dwFreeTxDescriptors++;
}
////////////////////////////////////////////////////////////////////////////
// If it was transmit abort in any of the TX desc, restart it.
//
if (!i)
{
for (i = 0 ; i < 4 ; i++)
{
if (READ_PORT_ULONG(RTL_TSD_X(i)) & TX_ABORT)
{
PRINTF (1, ("* "));
WRITE_PORT_ULONG(
RTL_TCR,
TX_DMA_BURST_SIZE | TX_CLEAR_ABORT | 0x03000000);
break;
}
}
}
} // PurgeTxDescriptors()
UINT16
RTL8139SendFrame(BYTE *pbData, DWORD dwLength)
{
DWORD i;
DWORD dwWaitTime;
BOOL bLastTry = FALSE;
PRINTF (0, ("RTL8139SendFrame()..\r\n"));
PRINTF (0, ("[0x%x] ",
READ_PORT_USHORT(RTL_ISR)));
////////////////////////////////////////////////////////////////////////////
// Check if the current TX descriptor is available.
// If not then we loop wait till it is available.
//
dwWaitTime = 100000;
while (sRTL8139.dwFreeTxDescriptors == 0)
{
PurgeTxDescriptors();
PRINTF (0, ("![%d, %x - %x - %x - %x] [0x%x]",
sRTL8139.dwCurrentHwTxDescriptor,
READ_PORT_ULONG(RTL_TSD_X(0)),
READ_PORT_ULONG(RTL_TSD_X(1)),
READ_PORT_ULONG(RTL_TSD_X(2)),
READ_PORT_ULONG(RTL_TSD_X(3)),
READ_PORT_USHORT(RTL_ISR)));
////////////////////////////////////////////////////////////////////////
// Oh well, chip is toasted... SOFT RESET it.
//
if (!--dwWaitTime)
{
USHORT usDummy[3];
PRINTF (1, ("@ "));
dwWaitTime = 100000;
PRINTF (1, ("< TX Reset >\r\n"));
PRINTF (1, ("HW Descriptor [%d] :: SW Descriptor [%d] :: Free = [%d]",
sRTL8139.dwCurrentHwTxDescriptor,
sRTL8139.dwCurrentTxDescriptor,
sRTL8139.dwFreeTxDescriptors));
DumpAll8139Regs();
WRITE_PORT_UCHAR(
RTL_CR,
(RTL8139_COMMAND_RX_ENABLE));
WRITE_PORT_UCHAR(
RTL_CR,
(RTL8139_COMMAND_TX_ENABLE | RTL8139_COMMAND_RX_ENABLE));
RTL8139DisableInts();
RTL8139Init(
(PBYTE)sRTL8139.dwBaseIO,
sRTL8139.dwMemOffset,
usDummy);
RTL8139EnableInts();
}
}
sRTL8139.dwFreeTxDescriptors--;
////////////////////////////////////////////////////////////////////////////
// So we are definitely using this descriptor.
// Advance it for the next call.
//
i = sRTL8139.dwCurrentTxDescriptor;
NEXT(sRTL8139.dwCurrentTxDescriptor, NUM_TX_DESC);
PRINTF (0, ("RTL8139SendFrame() using index: [%d] :: Size = [%d]\r\n",
i,
dwLength));
////////////////////////////////////////////////////////////////////////////
// Copy the user data and set it to go.
//
memcpy(
sRTL8139.pucTxBuffer + i * ONE_BUFFER_SIZE,
pbData,
dwLength);
#if 0
DumpMemory(
pbData,
dwLength);
DumpMemory(
sRTL8139.pucTxBuffer + i * ONE_BUFFER_SIZE,
dwLength);
#endif
WRITE_PORT_ULONG(
RTL_TSAD_X(i),
TO_REAL((DWORD)(sRTL8139.pucTxBuffer + i * ONE_BUFFER_SIZE)));
////////////////////////////////////////////////////////////////////////////
// Minimum packet size required by RTL
//
if (dwLength < 60)
{
memset(
(sRTL8139.pucTxBuffer + i * ONE_BUFFER_SIZE) + dwLength,
0x00,
60 - dwLength);
dwLength = 60;
}
////////////////////////////////////////////////////////////////////////////
// Send it out now..
// 8 bytes threshold.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -