📄 card.c
字号:
{
NdisRawWritePortUchar(
Adapter->IoAddr + NIC_DATA_CONFIG,
DCR_FIFO_8_BYTE | DCR_NORMAL | DCR_WORD_WIDE
);
}
//
// Clear transmit configuration.
//
NdisRawWritePortUchar(Adapter->IoAddr + NIC_XMIT_CONFIG, 0);
//
// Clear receive configuration.
//
NdisRawWritePortUchar(Adapter->IoAddr + NIC_RCV_CONFIG, 0);
//
// Clear any interrupts
//
NdisRawWritePortUchar(Adapter->IoAddr + NIC_INTR_STATUS, 0xFF);
//
// Stop the chip
//
NdisRawWritePortUchar(Adapter->IoAddr + NIC_COMMAND, CR_NO_DMA | CR_STOP);
//
// Clear any DMA values
//
NdisRawWritePortUchar(Adapter->IoAddr + NIC_RMT_COUNT_LSB, 0);
//
// Clear any DMA values
//
NdisRawWritePortUchar(Adapter->IoAddr + NIC_RMT_COUNT_MSB, 0);
//
// Wait for the reset to complete.
//
i = 0x3FFF;
while (--i)
{
NdisRawReadPortUchar(Adapter->IoAddr + NIC_INTR_STATUS, &Tmp);
if (Tmp & ISR_RESET)
break;
NdisStallExecution(4);
}
//
// Put card in loopback mode
//
NdisRawWritePortUchar(Adapter->IoAddr + NIC_XMIT_CONFIG, TCR_LOOPBACK);
//
// Start the chip.
//
NdisRawWritePortUchar(
Adapter->IoAddr + NIC_COMMAND,
CR_NO_DMA | CR_START
);
//
// Test for the amount of RAM
//
CardRamTest(Adapter);
//
// Stop the chip
//
SyncCardStop(Adapter);
return(TRUE);
}
#pragma NDIS_PAGEABLE_FUNCTION(CardReadEthernetAddress)
BOOLEAN CardReadEthernetAddress(
IN PRTL8139_ADAPTER Adapter
)
/*++
Routine Description:
Reads in the Ethernet address from the Novell 2000.
Arguments:
Adapter - pointer to the adapter block.
Return Value:
The address is stored in Adapter->PermanentAddress, and StationAddress if it
is currently zero.
--*/
{
UINT c;
//
// Things are done a little differently for PCMCIA adapters.
//
//
// Setup to read the ethernet address
//
NdisRawWritePortUchar(Adapter->IoAddr + NIC_RMT_COUNT_LSB, 12);
NdisRawWritePortUchar(Adapter->IoAddr + NIC_RMT_COUNT_MSB, 0);
NdisRawWritePortUchar(Adapter->IoAddr + NIC_RMT_ADDR_LSB, 0);
NdisRawWritePortUchar(Adapter->IoAddr + NIC_RMT_ADDR_MSB, 0);
NdisRawWritePortUchar(
Adapter->IoAddr + NIC_COMMAND,
CR_START | CR_DMA_READ | CR_PAGE1
);
//
// Read in the station address. (We have to read words -- 2 * 6 -- bytes)
//
for (c = 0; c < RTL8139_LENGTH_OF_ADDRESS; c++)
{
NdisRawReadPortUchar(
Adapter->IoAddr + NIC_PHYS_ADDR+c,
&Adapter->PermanentAddress[c]
);
}
IF_LOUD(
DbgPrint(
"RTL8139: PermanentAddress [ %02x-%02x-%02x-%02x-%02x-%02x ]\n",
Adapter->PermanentAddress[0],
Adapter->PermanentAddress[1],
Adapter->PermanentAddress[2],
Adapter->PermanentAddress[3],
Adapter->PermanentAddress[4],
Adapter->PermanentAddress[5]
);
)
//
// Use the burned in address as the station address, unless the
// registry specified an override value.
//
if ((Adapter->StationAddress[0] == 0x00) &&
(Adapter->StationAddress[1] == 0x00) &&
(Adapter->StationAddress[2] == 0x00) &&
(Adapter->StationAddress[3] == 0x00) &&
(Adapter->StationAddress[4] == 0x00) &&
(Adapter->StationAddress[5] == 0x00)
)
{
Adapter->StationAddress[0] = Adapter->PermanentAddress[0];
Adapter->StationAddress[1] = Adapter->PermanentAddress[1];
Adapter->StationAddress[2] = Adapter->PermanentAddress[2];
Adapter->StationAddress[3] = Adapter->PermanentAddress[3];
Adapter->StationAddress[4] = Adapter->PermanentAddress[4];
Adapter->StationAddress[5] = Adapter->PermanentAddress[5];
}
return(TRUE);
}
BOOLEAN
CardSetup(
IN PRTL8139_ADAPTER Adapter
)
/*++
Routine Description:
Sets up the card.
Arguments:
Adapter - pointer to the adapter block, which must be initialized.
Return Value:
TRUE if successful.
--*/
{
UINT i;
UINT Filter;
UCHAR Tmp;
//
// Write to and read from CR to make sure it is there.
//
NdisRawWritePortUchar(
Adapter->IoAddr + NIC_COMMAND,
CR_STOP | CR_NO_DMA | CR_PAGE0
);
NdisRawReadPortUchar(
Adapter->IoAddr + NIC_COMMAND,
&Tmp
);
if ((Tmp & (CR_STOP | CR_NO_DMA | CR_PAGE0)) !=
(CR_STOP | CR_NO_DMA | CR_PAGE0)
)
{
return(FALSE);
}
//
// Set up the registers in the correct sequence, as defined by
// the 8390 specification.
//
if (Adapter->EightBitSlot)
{
NdisRawWritePortUchar(
Adapter->IoAddr + NIC_DATA_CONFIG,
DCR_BYTE_WIDE | DCR_NORMAL | DCR_FIFO_8_BYTE
);
}
else
{
NdisRawWritePortUchar(
Adapter->IoAddr + NIC_DATA_CONFIG,
DCR_WORD_WIDE | DCR_NORMAL | DCR_FIFO_8_BYTE
);
}
NdisRawWritePortUchar(Adapter->IoAddr + NIC_RMT_COUNT_MSB, 0);
NdisRawWritePortUchar(Adapter->IoAddr + NIC_RMT_COUNT_LSB, 0);
NdisRawWritePortUchar(
Adapter->IoAddr + NIC_RCV_CONFIG,
Adapter->NicReceiveConfig
);
NdisRawWritePortUchar(
Adapter->IoAddr + NIC_XMIT_CONFIG,
TCR_LOOPBACK
);
NdisRawWritePortUchar(
Adapter->IoAddr + NIC_BOUNDARY,
Adapter->NicPageStart
);
NdisRawWritePortUchar(
Adapter->IoAddr + NIC_PAGE_START,
Adapter->NicPageStart
);
NdisRawWritePortUchar(
Adapter->IoAddr + NIC_PAGE_STOP,
Adapter->NicPageStop
);
Adapter->Current = Adapter->NicPageStart + (UCHAR)1;
Adapter->NicNextPacket = Adapter->NicPageStart + (UCHAR)1;
Adapter->BufferOverflow = FALSE;
NdisRawWritePortUchar(Adapter->IoAddr + NIC_INTR_STATUS, 0xff);
NdisRawWritePortUchar(
Adapter->IoAddr + NIC_INTR_MASK,
Adapter->NicInterruptMask
);
//
// Move to page 1 to write the station address
//
NdisRawWritePortUchar(
Adapter->IoAddr + NIC_COMMAND,
CR_STOP | CR_NO_DMA | CR_PAGE1
);
for (i = 0; i < RTL8139_LENGTH_OF_ADDRESS; i++)
{
NdisRawWritePortUchar(
Adapter->IoAddr + (NIC_PHYS_ADDR + i),
Adapter->StationAddress[i]
);
}
Filter = Adapter->PacketFilter;
//
// Write out the multicast addresses
//
for (i = 0; i < 8; i++)
{
NdisRawWritePortUchar(
Adapter->IoAddr + (NIC_MC_ADDR + i),
(UCHAR)((Filter & NDIS_PACKET_TYPE_ALL_MULTICAST) ?
0xff : Adapter->NicMulticastRegs[i])
);
}
//
// Write out the current receive buffer to receive into
//
NdisRawWritePortUchar(
Adapter->IoAddr + NIC_CURRENT,
Adapter->Current
);
//
// move back to page 0 and start the card...
//
NdisRawWritePortUchar(
Adapter->IoAddr + NIC_COMMAND,
CR_STOP | CR_NO_DMA | CR_PAGE0
);
NdisRawWritePortUchar(
Adapter->IoAddr + NIC_COMMAND,
CR_START | CR_NO_DMA | CR_PAGE0
);
//
// ... but it is still in loopback mode.
//
return(TRUE);
}
VOID CardStop(
IN PRTL8139_ADAPTER Adapter
)
/*++
Routine Description:
Stops the card.
Arguments:
Adapter - pointer to the adapter block
Return Value:
None.
--*/
{
UINT i;
UCHAR Tmp;
//
// Turn on the STOP bit in the Command register.
//
SyncCardStop(Adapter);
//
// Clear the Remote Byte Count register so that ISR_RESET
// will come on.
//
NdisRawWritePortUchar(Adapter->IoAddr + NIC_RMT_COUNT_MSB, 0);
NdisRawWritePortUchar(Adapter->IoAddr + NIC_RMT_COUNT_LSB, 0);
//
// Wait for ISR_RESET, but only for 1.6 milliseconds (as
// described in the March 1991 8390 addendum), since that
// is the maximum time for a software reset to occur.
//
//
for (i = 0; i < 4; i++)
{
NdisRawReadPortUchar(Adapter->IoAddr+NIC_INTR_STATUS, &Tmp);
if (Tmp & ISR_RESET)
break;
NdisStallExecution(500);
}
if (i == 4)
{
IF_LOUD( DbgPrint("RESET\n");)
IF_LOG( RTL8139Log('R');)
}
//
// Put the card in loopback mode, then start it.
//
NdisRawWritePortUchar(Adapter->IoAddr + NIC_XMIT_CONFIG, TCR_LOOPBACK);
NdisRawWritePortUchar(Adapter->IoAddr + NIC_COMMAND, CR_START | CR_NO_DMA);
//
// At this point the card is still in loopback mode.
//
}
BOOLEAN CardReset(
IN PRTL8139_ADAPTER Adapter
)
/*++
Routine Description:
Resets the card.
Arguments:
Adapter - pointer to the adapter block
Return Value:
TRUE if everything is OK.
--*/
{
//
// Stop the chip
//
CardStop(Adapter);
//
// Wait for the card to finish any receives or transmits
//
NdisStallExecution(2000);
//
// CardSetup() does a software reset.
//
if (!CardSetup(Adapter))
{
NdisWriteErrorLogEntry(
Adapter->MiniportAdapterHandle,
NDIS_ERROR_CODE_HARDWARE_FAILURE,
2,
cardReset,
RTL8139_ERRMSG_CARD_SETUP
);
return(FALSE);
}
//
// Restart the chip
//
CardStart(Adapter);
return TRUE;
}
BOOLEAN CardCopyDownPacket(
IN PRTL8139_ADAPTER Adapter,
IN PNDIS_PACKET Packet,
OUT PUINT Length
)
/*++
Routine Description:
Copies the packet Packet down starting at the beginning of
transmit buffer XmitBufferNum, fills in Length to be the
length of the packet.
Arguments:
Adapter - pointer to the adapter block
Packet - the packet to copy down
Return Value:
Length - the length of the data in the packet in bytes.
TRUE if the transfer completed with no problems.
--*/
{
//
// Addresses of the Buffers to copy from and to.
//
PUCHAR CurBufAddress;
PUCHAR OddBufAddress;
PUCHAR XmitBufAddress;
//
// Length of each of the above buffers
//
UINT CurBufLen;
UINT PacketLength;
//
// Was the last transfer of an odd length?
//
BOOLEAN OddBufLen = FALSE;
//
// Current NDIS_BUFFER that is being copied from
//
PNDIS_BUFFER CurBuffer;
//
// Programmed I/O, have to transfer the data.
//
NdisQueryPacket(Packet, NULL, NULL, &CurBuffer, &PacketLength);
//
// Skip 0 length copies
//
if (PacketLength == 0) {
return(TRUE);
}
//
// Get the starting buffer address
//
XmitBufAddress = (PUCHAR)Adapter->XmitStart +
Adapter->NextBufToFill*TX_BUF_SIZE;
//
// Get address and length of the first buffer in the packet
//
NdisQueryBuffer(CurBuffer, (PVOID *)&CurBufAddress, &CurBufLen);
while (CurBuffer && (CurBufLen == 0)) {
NdisGetNextBuffer(CurBuffer, &CurBuffer);
NdisQueryBuffer(CurBuffer, (PVOID *)&CurBufAddress, &CurBufLen);
}
//
// set up the card
//
{
//
// Temporary places for holding values for transferring to
// an odd aligned address on 16-bit slots.
//
UCHAR Tmp;
UCHAR Tmp1;
USHORT TmpShort;
//
// Values for waiting for noticing when a DMA completes.
//
USHORT OldAddr, NewAddr;
//
// Count of transfers to do
//
USHORT Count;
//
// Buffer to read from for odd aligned transfers
//
PUCHAR ReadBuffer;
if (!Adapter->EightBitSlot && ((ULONG_PTR)XmitBufAddress & 0x1)) {
//
// Avoid transfers to odd addresses in word mode.
//
// For odd addresses we need to read first to get the previous
// byte and then merge it with our first byte.
//
//
// Set Count and Source address
//
// NdisRawWritePortUchar(Adapter->IoAddr + NIC_COMMAND, CR_PAGE0); // robin
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -