3222 lines
67 KiB
C
3222 lines
67 KiB
C
|
||
/*++
|
||
|
||
Copyright (c) 1990-1998 Microsoft Corporation, All Rights Reserved.
|
||
|
||
Module Name:
|
||
|
||
card.c
|
||
|
||
Abstract:
|
||
|
||
Card-specific functions for the NDIS 3.0 Novell 2000 driver.
|
||
|
||
Author:
|
||
|
||
Sean Selitrennikoff
|
||
|
||
Environment:
|
||
|
||
Kernel mode, FSD
|
||
|
||
Revision History:
|
||
|
||
--*/
|
||
|
||
#include "precomp.h"
|
||
|
||
BOOLEAN
|
||
CardSlotTest(
|
||
IN PNE2000_ADAPTER Adapter
|
||
);
|
||
|
||
BOOLEAN
|
||
CardRamTest(
|
||
IN PNE2000_ADAPTER Adapter
|
||
);
|
||
|
||
|
||
#pragma NDIS_PAGEABLE_FUNCTION(CardCheckParameters)
|
||
|
||
BOOLEAN CardCheckParameters(
|
||
IN PNE2000_ADAPTER Adapter
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Checks that the I/O base address is correct.
|
||
|
||
Arguments:
|
||
|
||
Adapter - pointer to the adapter block.
|
||
|
||
Return Value:
|
||
|
||
TRUE, if IoBaseAddress appears correct.
|
||
|
||
--*/
|
||
|
||
{
|
||
UCHAR Tmp;
|
||
|
||
//
|
||
// If adapter responds to a stop command correctly -- assume it is there.
|
||
//
|
||
|
||
//
|
||
// Turn off interrupts first.
|
||
//
|
||
NdisRawWritePortUchar(Adapter->IoPAddr + NIC_INTR_MASK, 0);
|
||
|
||
//
|
||
// Stop the card.
|
||
//
|
||
SyncCardStop(Adapter);
|
||
|
||
//
|
||
// Pause
|
||
//
|
||
NdisStallExecution(2000);
|
||
|
||
//
|
||
// Read response
|
||
//
|
||
NdisRawReadPortUchar(Adapter->IoPAddr + NIC_COMMAND, &Tmp);
|
||
|
||
if ((Tmp == (CR_NO_DMA | CR_STOP)) ||
|
||
(Tmp == (CR_NO_DMA | CR_STOP | CR_START))
|
||
)
|
||
{
|
||
return(TRUE);
|
||
}
|
||
else
|
||
{
|
||
return(FALSE);
|
||
}
|
||
}
|
||
#ifdef NE2000
|
||
|
||
#pragma NDIS_PAGEABLE_FUNCTION(CardSlotTest)
|
||
|
||
|
||
BOOLEAN CardSlotTest(
|
||
IN PNE2000_ADAPTER Adapter
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Checks if the card is in an 8 or 16 bit slot and sets a flag in the
|
||
adapter structure.
|
||
|
||
Arguments:
|
||
|
||
Adapter - pointer to the adapter block.
|
||
|
||
Return Value:
|
||
|
||
TRUE, if all goes well, else FALSE.
|
||
|
||
--*/
|
||
|
||
{
|
||
UCHAR Tmp;
|
||
UCHAR RomCopy[32];
|
||
UCHAR i;
|
||
BOOLEAN found;
|
||
|
||
//
|
||
// Reset the chip
|
||
//
|
||
NdisRawReadPortUchar(Adapter->IoPAddr + NIC_RESET, &Tmp);
|
||
NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RESET, 0xFF);
|
||
|
||
//
|
||
// Go to page 0 and stop
|
||
//
|
||
NdisRawWritePortUchar(Adapter->IoPAddr + NIC_COMMAND, CR_STOP | CR_NO_DMA);
|
||
|
||
//
|
||
// Pause
|
||
//
|
||
NdisStallExecution(2000);
|
||
|
||
//
|
||
// Check that it is stopped
|
||
//
|
||
NdisRawReadPortUchar(Adapter->IoPAddr + NIC_COMMAND, &Tmp);
|
||
if (Tmp != (CR_NO_DMA | CR_STOP))
|
||
{
|
||
IF_LOUD(DbgPrint("Could not stop the card\n");)
|
||
|
||
return(FALSE);
|
||
}
|
||
|
||
//
|
||
// Setup to read from ROM
|
||
//
|
||
NdisRawWritePortUchar(
|
||
Adapter->IoPAddr + NIC_DATA_CONFIG,
|
||
DCR_BYTE_WIDE | DCR_FIFO_8_BYTE | DCR_NORMAL
|
||
);
|
||
|
||
NdisRawWritePortUchar(Adapter->IoPAddr + NIC_INTR_MASK, 0x0);
|
||
|
||
//
|
||
// Ack any interrupts that may be hanging around
|
||
//
|
||
NdisRawWritePortUchar(Adapter->IoPAddr + NIC_INTR_STATUS, 0xFF);
|
||
|
||
//
|
||
// Setup to read in the ROM, the address and byte count.
|
||
//
|
||
NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_ADDR_LSB, 0x0);
|
||
|
||
NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_ADDR_MSB, 0x0);
|
||
|
||
NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_COUNT_LSB, 32);
|
||
|
||
NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_COUNT_MSB, 0x0);
|
||
|
||
NdisRawWritePortUchar(
|
||
Adapter->IoPAddr + NIC_COMMAND,
|
||
CR_DMA_READ | CR_START
|
||
);
|
||
|
||
//
|
||
// Read first 32 bytes in 16 bit mode
|
||
//
|
||
for (i = 0; i < 32; i++)
|
||
{
|
||
NdisRawReadPortUchar(Adapter->IoPAddr + NIC_RACK_NIC, RomCopy + i);
|
||
}
|
||
|
||
IF_VERY_LOUD( DbgPrint("Resetting the chip\n"); )
|
||
|
||
//
|
||
// Reset the chip
|
||
//
|
||
NdisRawReadPortUchar(Adapter->IoPAddr + NIC_RESET, &Tmp);
|
||
NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RESET, 0xFF);
|
||
|
||
//
|
||
// Check ROM for 'B' (byte) or 'W' (word)
|
||
// NOTE: If the buffer has bot BB and WW then use WW instead of BB
|
||
IF_VERY_LOUD( DbgPrint("Checking slot type\n"); )
|
||
|
||
found = FALSE;
|
||
for (i = 16; i < 31; i++)
|
||
{
|
||
if (((RomCopy[i] == 'B') && (RomCopy[i+1] == 'B')) ||
|
||
((RomCopy[i] == 'W') && (RomCopy[i+1] == 'W'))
|
||
)
|
||
{
|
||
if (RomCopy[i] == 'B')
|
||
{
|
||
Adapter->EightBitSlot = TRUE;
|
||
found = TRUE;
|
||
}
|
||
else
|
||
{
|
||
Adapter->EightBitSlot = FALSE;
|
||
found = TRUE;
|
||
break; // Go no farther
|
||
}
|
||
}
|
||
}
|
||
|
||
if (found)
|
||
{
|
||
IF_VERY_LOUD( (Adapter->EightBitSlot?DbgPrint("8 bit slot\n"):
|
||
DbgPrint("16 bit slot\n")); )
|
||
}
|
||
else
|
||
{
|
||
//
|
||
// If neither found -- then not an NE2000
|
||
//
|
||
IF_VERY_LOUD( DbgPrint("Failed slot type\n"); )
|
||
}
|
||
|
||
return(found);
|
||
}
|
||
|
||
#endif // NE2000
|
||
|
||
|
||
|
||
|
||
#pragma NDIS_PAGEABLE_FUNCTION(CardRamTest)
|
||
|
||
BOOLEAN
|
||
CardRamTest(
|
||
IN PNE2000_ADAPTER Adapter
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Finds out how much RAM the adapter has. It starts at 1K and checks thru
|
||
60K. It will set Adapter->RamSize to the appropriate value iff this
|
||
function returns TRUE.
|
||
|
||
Arguments:
|
||
|
||
Adapter - pointer to the adapter block.
|
||
|
||
Return Value:
|
||
|
||
TRUE, if all goes well, else FALSE.
|
||
|
||
--*/
|
||
|
||
{
|
||
PUCHAR RamBase, RamPointer;
|
||
PUCHAR RamEnd;
|
||
|
||
UCHAR TestPattern[]={ 0xAA, 0x55, 0xFF, 0x00 };
|
||
PULONG pTestPattern = (PULONG)TestPattern;
|
||
UCHAR ReadPattern[4];
|
||
PULONG pReadPattern = (PULONG)ReadPattern;
|
||
|
||
for (RamBase = (PUCHAR)0x400; RamBase < (PUCHAR)0x10000; RamBase += 0x400) {
|
||
|
||
//
|
||
// Write Test pattern
|
||
//
|
||
|
||
if (!CardCopyDown(Adapter, RamBase, TestPattern, 4)) {
|
||
|
||
continue;
|
||
|
||
}
|
||
|
||
//
|
||
// Read pattern
|
||
//
|
||
|
||
if (!CardCopyUp(Adapter, ReadPattern, RamBase, 4)) {
|
||
|
||
continue;
|
||
|
||
}
|
||
|
||
IF_VERY_LOUD( DbgPrint("Addr 0x%x: 0x%x, 0x%x, 0x%x, 0x%x\n",
|
||
RamBase,
|
||
ReadPattern[0],
|
||
ReadPattern[1],
|
||
ReadPattern[2],
|
||
ReadPattern[3]
|
||
);
|
||
)
|
||
|
||
|
||
//
|
||
// If they are the same, find the end
|
||
//
|
||
|
||
if (*pReadPattern == *pTestPattern) {
|
||
|
||
for (RamEnd = RamBase; !(PtrToUlong(RamEnd) & 0xFFFF0000); RamEnd += 0x400) {
|
||
|
||
//
|
||
// Write test pattern
|
||
//
|
||
|
||
if (!CardCopyDown(Adapter, RamEnd, TestPattern, 4)) {
|
||
|
||
break;
|
||
|
||
}
|
||
|
||
//
|
||
// Read pattern
|
||
//
|
||
|
||
if (!CardCopyUp(Adapter, ReadPattern, RamEnd, 4)) {
|
||
|
||
break;
|
||
|
||
}
|
||
|
||
if (*pReadPattern != *pTestPattern) {
|
||
|
||
break;
|
||
|
||
}
|
||
|
||
}
|
||
|
||
break;
|
||
|
||
}
|
||
|
||
}
|
||
|
||
IF_LOUD( DbgPrint("RamBase 0x%x, RamEnd 0x%x\n", RamBase, RamEnd); )
|
||
|
||
//
|
||
// If not found, error out
|
||
//
|
||
|
||
if ((RamBase >= (PUCHAR)0x10000) || (RamBase == RamEnd)) {
|
||
|
||
return(FALSE);
|
||
|
||
}
|
||
|
||
//
|
||
// Watch for boundary case when RamEnd is maximum value
|
||
//
|
||
|
||
if ((ULONG_PTR)RamEnd & 0xFFFF0000) {
|
||
|
||
RamEnd -= 0x100;
|
||
|
||
}
|
||
|
||
//
|
||
// Check all of ram
|
||
//
|
||
|
||
for (RamPointer = RamBase; RamPointer < RamEnd; RamPointer += 4) {
|
||
|
||
//
|
||
// Write test pattern
|
||
//
|
||
|
||
if (!CardCopyDown(Adapter, RamPointer, TestPattern, 4)) {
|
||
|
||
return(FALSE);
|
||
|
||
}
|
||
|
||
//
|
||
// Read pattern
|
||
//
|
||
|
||
if (!CardCopyUp(Adapter, ReadPattern, RamBase, 4)) {
|
||
|
||
return(FALSE);
|
||
|
||
}
|
||
|
||
if (*pReadPattern != *pTestPattern) {
|
||
|
||
return(FALSE);
|
||
|
||
}
|
||
|
||
}
|
||
|
||
//
|
||
// Store Results
|
||
//
|
||
|
||
Adapter->RamBase = RamBase;
|
||
Adapter->RamSize = (ULONG)(RamEnd - RamBase);
|
||
|
||
return(TRUE);
|
||
|
||
}
|
||
|
||
#pragma NDIS_PAGEABLE_FUNCTION(CardInitialize)
|
||
|
||
BOOLEAN
|
||
CardInitialize(
|
||
IN PNE2000_ADAPTER Adapter
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Initializes the card into a running state.
|
||
|
||
Arguments:
|
||
|
||
Adapter - pointer to the adapter block.
|
||
|
||
Return Value:
|
||
|
||
TRUE, if all goes well, else FALSE.
|
||
|
||
--*/
|
||
|
||
{
|
||
UCHAR Tmp;
|
||
USHORT i;
|
||
|
||
//
|
||
// Stop the card.
|
||
//
|
||
SyncCardStop(Adapter);
|
||
|
||
//
|
||
// Initialize the Data Configuration register.
|
||
//
|
||
NdisRawWritePortUchar(
|
||
Adapter->IoPAddr + NIC_DATA_CONFIG,
|
||
DCR_AUTO_INIT | DCR_FIFO_8_BYTE
|
||
);
|
||
|
||
//
|
||
// Set Xmit start location
|
||
//
|
||
NdisRawWritePortUchar(Adapter->IoPAddr + NIC_XMIT_START, 0xA0);
|
||
|
||
//
|
||
// Set Xmit configuration
|
||
//
|
||
NdisRawWritePortUchar(Adapter->IoPAddr + NIC_XMIT_CONFIG, 0x0);
|
||
|
||
//
|
||
// Set Receive configuration
|
||
//
|
||
NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RCV_CONFIG, RCR_MONITOR);
|
||
|
||
//
|
||
// Set Receive start
|
||
//
|
||
NdisRawWritePortUchar(Adapter->IoPAddr + NIC_PAGE_START, 0x4);
|
||
|
||
//
|
||
// Set Receive end
|
||
//
|
||
NdisRawWritePortUchar(Adapter->IoPAddr + NIC_PAGE_STOP, 0xFF);
|
||
|
||
//
|
||
// Set Receive boundary
|
||
//
|
||
NdisRawWritePortUchar(Adapter->IoPAddr + NIC_BOUNDARY, 0x4);
|
||
|
||
//
|
||
// Set Xmit bytes
|
||
//
|
||
NdisRawWritePortUchar(Adapter->IoPAddr + NIC_XMIT_COUNT_LSB, 0x3C);
|
||
NdisRawWritePortUchar(Adapter->IoPAddr + NIC_XMIT_COUNT_MSB, 0x0);
|
||
|
||
//
|
||
// Pause
|
||
//
|
||
NdisStallExecution(2000);
|
||
|
||
//
|
||
// Ack all interrupts that we might have produced
|
||
//
|
||
NdisRawWritePortUchar(Adapter->IoPAddr + NIC_INTR_STATUS, 0xFF);
|
||
|
||
//
|
||
// Change to page 1
|
||
//
|
||
NdisRawWritePortUchar(Adapter->IoPAddr + NIC_COMMAND, CR_PAGE1 | CR_STOP);
|
||
|
||
//
|
||
// Set current
|
||
//
|
||
NdisRawWritePortUchar(Adapter->IoPAddr + NIC_CURRENT, 0x4);
|
||
|
||
//
|
||
// Back to page 0
|
||
//
|
||
NdisRawWritePortUchar(Adapter->IoPAddr + NIC_COMMAND, CR_PAGE0 | CR_STOP);
|
||
|
||
//
|
||
// Pause
|
||
//
|
||
NdisStallExecution(2000);
|
||
|
||
//
|
||
// Check that Command register reflects this last command
|
||
//
|
||
NdisRawReadPortUchar(Adapter->IoPAddr + NIC_COMMAND, &Tmp);
|
||
if (!(Tmp & CR_STOP))
|
||
{
|
||
IF_LOUD(DbgPrint("Invalid command register\n");)
|
||
|
||
return(FALSE);
|
||
}
|
||
|
||
//
|
||
// Do initialization errata
|
||
//
|
||
NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_COUNT_LSB, 55);
|
||
|
||
//
|
||
// Setup for a read
|
||
//
|
||
NdisRawWritePortUchar(
|
||
Adapter->IoPAddr + NIC_COMMAND,
|
||
CR_DMA_READ | CR_START
|
||
);
|
||
|
||
#ifdef NE2000
|
||
|
||
//
|
||
// Check if the slot is 8 or 16 bit (affects data transfer rate).
|
||
//
|
||
|
||
if ((Adapter->BusType == NdisInterfaceMca) ||
|
||
(NE2000_PCMCIA == Adapter->CardType))
|
||
{
|
||
Adapter->EightBitSlot = FALSE;
|
||
}
|
||
else
|
||
{
|
||
IF_VERY_LOUD(DbgPrint("CardSlotTest\n");)
|
||
|
||
if (CardSlotTest(Adapter) == FALSE)
|
||
{
|
||
//
|
||
// Stop chip
|
||
//
|
||
SyncCardStop(Adapter);
|
||
|
||
IF_LOUD(DbgPrint(" -- Failed\n");)
|
||
return(FALSE);
|
||
}
|
||
|
||
}
|
||
|
||
#else // NE2000
|
||
|
||
Adapter->EightBitSlot = TRUE;
|
||
|
||
#endif // NE2000
|
||
|
||
//
|
||
// Mask Interrupts
|
||
//
|
||
|
||
NdisRawWritePortUchar(Adapter->IoPAddr + NIC_INTR_MASK, 0x0);
|
||
|
||
//
|
||
// Setup the Adapter for reading ram
|
||
//
|
||
|
||
// NdisRawWritePortUchar(Adapter->IoPAddr + NIC_COMMAND, CR_PAGE0); // robin
|
||
|
||
if (Adapter->EightBitSlot)
|
||
{
|
||
NdisRawWritePortUchar(
|
||
Adapter->IoPAddr + NIC_DATA_CONFIG,
|
||
DCR_FIFO_8_BYTE | DCR_NORMAL | DCR_BYTE_WIDE
|
||
);
|
||
}
|
||
else
|
||
{
|
||
NdisRawWritePortUchar(
|
||
Adapter->IoPAddr + NIC_DATA_CONFIG,
|
||
DCR_FIFO_8_BYTE | DCR_NORMAL | DCR_WORD_WIDE
|
||
);
|
||
}
|
||
|
||
//
|
||
// Clear transmit configuration.
|
||
//
|
||
NdisRawWritePortUchar(Adapter->IoPAddr + NIC_XMIT_CONFIG, 0);
|
||
|
||
//
|
||
// Clear receive configuration.
|
||
//
|
||
NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RCV_CONFIG, 0);
|
||
|
||
//
|
||
// Clear any interrupts
|
||
//
|
||
NdisRawWritePortUchar(Adapter->IoPAddr + NIC_INTR_STATUS, 0xFF);
|
||
|
||
//
|
||
// Stop the chip
|
||
//
|
||
NdisRawWritePortUchar(Adapter->IoPAddr + NIC_COMMAND, CR_NO_DMA | CR_STOP);
|
||
|
||
//
|
||
// Clear any DMA values
|
||
//
|
||
NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_COUNT_LSB, 0);
|
||
|
||
//
|
||
// Clear any DMA values
|
||
//
|
||
NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_COUNT_MSB, 0);
|
||
|
||
//
|
||
// Wait for the reset to complete.
|
||
//
|
||
i = 0x3FFF;
|
||
|
||
while (--i)
|
||
{
|
||
NdisRawReadPortUchar(Adapter->IoPAddr + NIC_INTR_STATUS, &Tmp);
|
||
|
||
if (Tmp & ISR_RESET)
|
||
break;
|
||
|
||
NdisStallExecution(4);
|
||
}
|
||
|
||
//
|
||
// Put card in loopback mode
|
||
//
|
||
NdisRawWritePortUchar(Adapter->IoPAddr + NIC_XMIT_CONFIG, TCR_LOOPBACK);
|
||
|
||
//
|
||
// Start the chip.
|
||
//
|
||
NdisRawWritePortUchar(
|
||
Adapter->IoPAddr + NIC_COMMAND,
|
||
CR_NO_DMA | CR_START
|
||
);
|
||
|
||
//
|
||
// Test for the amount of RAM
|
||
//
|
||
if (NE2000_ISA == Adapter->CardType)
|
||
{
|
||
if (CardRamTest(Adapter) == FALSE)
|
||
{
|
||
//
|
||
// Stop the chip
|
||
//
|
||
SyncCardStop(Adapter);
|
||
|
||
return(FALSE);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
//
|
||
// We know what it is for the pcmcia adapters,
|
||
// so don't waste time on detecting it.
|
||
//
|
||
Adapter->RamBase = (PUCHAR)0x4000;
|
||
Adapter->RamSize = 0x4000;
|
||
}
|
||
|
||
//
|
||
// Stop the chip
|
||
//
|
||
SyncCardStop(Adapter);
|
||
|
||
return(TRUE);
|
||
}
|
||
|
||
|
||
#pragma NDIS_PAGEABLE_FUNCTION(CardReadEthernetAddress)
|
||
|
||
BOOLEAN CardReadEthernetAddress(
|
||
IN PNE2000_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.
|
||
//
|
||
if (NE2000_PCMCIA == Adapter->CardType)
|
||
{
|
||
#if 0
|
||
|
||
NDIS_STATUS Status;
|
||
PUCHAR pAttributeWindow;
|
||
NDIS_PHYSICAL_ADDRESS AttributePhysicalAddress;
|
||
//
|
||
// Setup the physical address for the attribute window.
|
||
//
|
||
NdisSetPhysicalAddressHigh(AttributePhysicalAddress, 0);
|
||
NdisSetPhysicalAddressLow(
|
||
AttributePhysicalAddress,
|
||
Adapter->AttributeMemoryAddress
|
||
);
|
||
|
||
//
|
||
// We need to get the pcmcia information from the tuple.
|
||
//
|
||
Status = NdisMMapIoSpace(
|
||
(PVOID *)&pAttributeWindow,
|
||
Adapter->MiniportAdapterHandle,
|
||
AttributePhysicalAddress,
|
||
Adapter->AttributeMemorySize
|
||
);
|
||
if (NDIS_STATUS_SUCCESS != Status)
|
||
{
|
||
//
|
||
// Failed to setup the attribute window.
|
||
//
|
||
return(FALSE);
|
||
}
|
||
|
||
//
|
||
// Read the ethernet address from the card.
|
||
//
|
||
for (c = 0; c < ETH_LENGTH_OF_ADDRESS; c++)
|
||
{
|
||
NdisReadRegisterUchar(
|
||
(PUCHAR)(pAttributeWindow + CIS_NET_ADDR_OFFSET + c * 2),
|
||
&Adapter->PermanentAddress[c]);
|
||
}
|
||
#endif
|
||
if (ETH_LENGTH_OF_ADDRESS != NdisReadPcmciaAttributeMemory(
|
||
Adapter->MiniportAdapterHandle,
|
||
CIS_NET_ADDR_OFFSET/2,
|
||
Adapter->PermanentAddress,
|
||
ETH_LENGTH_OF_ADDRESS
|
||
))
|
||
{
|
||
return(FALSE);
|
||
}
|
||
|
||
}
|
||
else
|
||
{
|
||
//
|
||
// Setup to read the ethernet address
|
||
//
|
||
NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_COUNT_LSB, 12);
|
||
NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_COUNT_MSB, 0);
|
||
NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_ADDR_LSB, 0);
|
||
NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_ADDR_MSB, 0);
|
||
NdisRawWritePortUchar(
|
||
Adapter->IoPAddr + NIC_COMMAND,
|
||
CR_START | CR_DMA_READ
|
||
);
|
||
|
||
//
|
||
// Read in the station address. (We have to read words -- 2 * 6 -- bytes)
|
||
//
|
||
for (c = 0; c < NE2000_LENGTH_OF_ADDRESS; c++)
|
||
{
|
||
NdisRawReadPortUchar(
|
||
Adapter->IoPAddr + NIC_RACK_NIC,
|
||
&Adapter->PermanentAddress[c]
|
||
);
|
||
}
|
||
}
|
||
|
||
IF_LOUD(
|
||
DbgPrint(
|
||
"Ne2000: 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 PNE2000_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->IoPAddr + NIC_COMMAND,
|
||
CR_STOP | CR_NO_DMA | CR_PAGE0
|
||
);
|
||
|
||
NdisRawReadPortUchar(
|
||
Adapter->IoPAddr + 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->IoPAddr + NIC_DATA_CONFIG,
|
||
DCR_BYTE_WIDE | DCR_NORMAL | DCR_FIFO_8_BYTE
|
||
);
|
||
}
|
||
else
|
||
{
|
||
NdisRawWritePortUchar(
|
||
Adapter->IoPAddr + NIC_DATA_CONFIG,
|
||
DCR_WORD_WIDE | DCR_NORMAL | DCR_FIFO_8_BYTE
|
||
);
|
||
}
|
||
|
||
|
||
NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_COUNT_MSB, 0);
|
||
|
||
NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_COUNT_LSB, 0);
|
||
|
||
NdisRawWritePortUchar(
|
||
Adapter->IoPAddr + NIC_RCV_CONFIG,
|
||
Adapter->NicReceiveConfig
|
||
);
|
||
|
||
NdisRawWritePortUchar(
|
||
Adapter->IoPAddr + NIC_XMIT_CONFIG,
|
||
TCR_LOOPBACK
|
||
);
|
||
|
||
NdisRawWritePortUchar(
|
||
Adapter->IoPAddr + NIC_BOUNDARY,
|
||
Adapter->NicPageStart
|
||
);
|
||
|
||
NdisRawWritePortUchar(
|
||
Adapter->IoPAddr + NIC_PAGE_START,
|
||
Adapter->NicPageStart
|
||
);
|
||
|
||
NdisRawWritePortUchar(
|
||
Adapter->IoPAddr + NIC_PAGE_STOP,
|
||
Adapter->NicPageStop
|
||
);
|
||
|
||
Adapter->Current = Adapter->NicPageStart + (UCHAR)1;
|
||
Adapter->NicNextPacket = Adapter->NicPageStart + (UCHAR)1;
|
||
Adapter->BufferOverflow = FALSE;
|
||
|
||
NdisRawWritePortUchar(Adapter->IoPAddr + NIC_INTR_STATUS, 0xff);
|
||
|
||
NdisRawWritePortUchar(
|
||
Adapter->IoPAddr + NIC_INTR_MASK,
|
||
Adapter->NicInterruptMask
|
||
);
|
||
|
||
|
||
//
|
||
// Move to page 1 to write the station address
|
||
//
|
||
NdisRawWritePortUchar(
|
||
Adapter->IoPAddr + NIC_COMMAND,
|
||
CR_STOP | CR_NO_DMA | CR_PAGE1
|
||
);
|
||
|
||
for (i = 0; i < NE2000_LENGTH_OF_ADDRESS; i++)
|
||
{
|
||
NdisRawWritePortUchar(
|
||
Adapter->IoPAddr + (NIC_PHYS_ADDR + i),
|
||
Adapter->StationAddress[i]
|
||
);
|
||
}
|
||
|
||
Filter = Adapter->PacketFilter;
|
||
|
||
//
|
||
// Write out the multicast addresses
|
||
//
|
||
for (i = 0; i < 8; i++)
|
||
{
|
||
NdisRawWritePortUchar(
|
||
Adapter->IoPAddr + (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->IoPAddr + NIC_CURRENT,
|
||
Adapter->Current
|
||
);
|
||
|
||
|
||
//
|
||
// move back to page 0 and start the card...
|
||
//
|
||
NdisRawWritePortUchar(
|
||
Adapter->IoPAddr + NIC_COMMAND,
|
||
CR_STOP | CR_NO_DMA | CR_PAGE0
|
||
);
|
||
|
||
NdisRawWritePortUchar(
|
||
Adapter->IoPAddr + NIC_COMMAND,
|
||
CR_START | CR_NO_DMA | CR_PAGE0
|
||
);
|
||
|
||
//
|
||
// ... but it is still in loopback mode.
|
||
//
|
||
return(TRUE);
|
||
}
|
||
|
||
VOID CardStop(
|
||
IN PNE2000_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->IoPAddr + NIC_RMT_COUNT_MSB, 0);
|
||
NdisRawWritePortUchar(Adapter->IoPAddr + 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->IoPAddr+NIC_INTR_STATUS, &Tmp);
|
||
if (Tmp & ISR_RESET)
|
||
break;
|
||
|
||
NdisStallExecution(500);
|
||
}
|
||
|
||
if (i == 4)
|
||
{
|
||
IF_LOUD( DbgPrint("RESET\n");)
|
||
IF_LOG( Ne2000Log('R');)
|
||
}
|
||
|
||
//
|
||
// Put the card in loopback mode, then start it.
|
||
//
|
||
NdisRawWritePortUchar(Adapter->IoPAddr + NIC_XMIT_CONFIG, TCR_LOOPBACK);
|
||
NdisRawWritePortUchar(Adapter->IoPAddr + NIC_COMMAND, CR_START | CR_NO_DMA);
|
||
|
||
//
|
||
// At this point the card is still in loopback mode.
|
||
//
|
||
}
|
||
|
||
BOOLEAN CardReset(
|
||
IN PNE2000_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,
|
||
NE2000_ERRMSG_CARD_SETUP
|
||
);
|
||
|
||
return(FALSE);
|
||
}
|
||
|
||
//
|
||
// Restart the chip
|
||
//
|
||
CardStart(Adapter);
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
|
||
BOOLEAN CardCopyDownPacket(
|
||
IN PNE2000_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->IoPAddr + NIC_COMMAND, CR_PAGE0); // robin
|
||
|
||
NdisRawWritePortUchar(
|
||
Adapter->IoPAddr + NIC_RMT_ADDR_LSB,
|
||
LSB(PtrToUlong(XmitBufAddress - 1))
|
||
);
|
||
|
||
NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_ADDR_MSB,
|
||
MSB((PtrToUlong(XmitBufAddress) - 1))
|
||
);
|
||
|
||
// NE2000 PCMCIA CHANGE START
|
||
|
||
//
|
||
// NE2000 PCMCIA CHANGE!!!
|
||
//
|
||
//NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_COUNT_LSB, 0x1 );
|
||
//NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_COUNT_MSB, 0x0 );
|
||
NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_COUNT_LSB, 0x2 );
|
||
NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_COUNT_MSB, 0x0 );
|
||
|
||
//
|
||
// Set direction (Read)
|
||
//
|
||
|
||
NdisRawWritePortUchar( Adapter->IoPAddr + NIC_COMMAND,
|
||
CR_START | CR_PAGE0 | CR_DMA_READ );
|
||
|
||
//
|
||
// NE2000 PCMCIA CHANGE!!!
|
||
//
|
||
//NdisRawReadPortUchar( Adapter->IoPAddr + NIC_RACK_NIC, &Tmp1 );
|
||
NdisRawReadPortUshort( Adapter->IoPAddr + NIC_RACK_NIC, &TmpShort );
|
||
Tmp1 = LSB(TmpShort);
|
||
|
||
// NE2000 PCMCIA CHANGE END
|
||
|
||
//
|
||
// Do Write errata as described on pages 1-143 and
|
||
// 1-144 of the 1992 LAN databook
|
||
//
|
||
|
||
//
|
||
// Set Count and destination address
|
||
//
|
||
ReadBuffer = XmitBufAddress + ((ULONG_PTR)XmitBufAddress & 1);
|
||
|
||
OldAddr = NewAddr = (USHORT)(ReadBuffer);
|
||
|
||
// NdisRawWritePortUchar(Adapter->IoPAddr + NIC_COMMAND, // robin
|
||
// CR_PAGE0 // robin
|
||
// ); // robin
|
||
NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_ADDR_LSB,
|
||
LSB(PtrToUlong(ReadBuffer))
|
||
);
|
||
NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_ADDR_MSB,
|
||
MSB(PtrToUlong(ReadBuffer))
|
||
);
|
||
NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_COUNT_LSB, 0x2 );
|
||
NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_COUNT_MSB, 0x0 );
|
||
|
||
//
|
||
// Set direction (Read)
|
||
//
|
||
NdisRawWritePortUchar(
|
||
Adapter->IoPAddr + NIC_COMMAND,
|
||
CR_START | CR_PAGE0 | CR_DMA_READ
|
||
);
|
||
|
||
//
|
||
// Read from port
|
||
//
|
||
NdisRawReadPortUshort( Adapter->IoPAddr + NIC_RACK_NIC, &TmpShort );
|
||
|
||
//
|
||
// Wait for addr to change
|
||
//
|
||
TmpShort = 0xFFFF;
|
||
|
||
while (TmpShort != 0) {
|
||
|
||
NdisRawReadPortUchar( Adapter->IoPAddr + NIC_CRDA_LSB, &Tmp );
|
||
NewAddr = Tmp;
|
||
NdisRawReadPortUchar( Adapter->IoPAddr + NIC_CRDA_MSB, &Tmp );
|
||
NewAddr |= (Tmp << 8);
|
||
|
||
if (NewAddr != OldAddr) {
|
||
|
||
break;
|
||
|
||
}
|
||
|
||
NdisStallExecution(1);
|
||
|
||
TmpShort--;
|
||
}
|
||
|
||
if (NewAddr == OldAddr) {
|
||
|
||
NdisWriteErrorLogEntry(
|
||
Adapter->MiniportAdapterHandle,
|
||
NDIS_ERROR_CODE_HARDWARE_FAILURE,
|
||
2,
|
||
cardCopyDownPacket,
|
||
(ULONG_PTR)XmitBufAddress
|
||
);
|
||
|
||
return(FALSE);
|
||
|
||
}
|
||
|
||
//
|
||
// Set Count and destination address
|
||
//
|
||
NdisRawWritePortUchar( Adapter->IoPAddr + NIC_RMT_ADDR_LSB,
|
||
LSB(PtrToUlong(XmitBufAddress - 1)) );
|
||
|
||
NdisRawWritePortUchar( Adapter->IoPAddr + NIC_RMT_ADDR_MSB,
|
||
MSB(PtrToUlong(XmitBufAddress - 1)) );
|
||
|
||
NdisRawWritePortUchar( Adapter->IoPAddr + NIC_RMT_COUNT_LSB, 0x2 );
|
||
|
||
NdisRawWritePortUchar( Adapter->IoPAddr + NIC_RMT_COUNT_MSB, 0x0 );
|
||
|
||
//
|
||
// Set direction (Write)
|
||
//
|
||
NdisRawWritePortUchar( Adapter->IoPAddr + NIC_COMMAND,
|
||
CR_START | CR_PAGE0 | CR_DMA_WRITE );
|
||
|
||
//
|
||
// It seems that the card stores words in LOW:HIGH order
|
||
//
|
||
NdisRawWritePortUshort( Adapter->IoPAddr + NIC_RACK_NIC,
|
||
(USHORT)(Tmp1 | ((*CurBufAddress) << 8)) );
|
||
|
||
//
|
||
// Wait for DMA to complete
|
||
//
|
||
Count = 0xFFFF;
|
||
|
||
while (Count) {
|
||
|
||
NdisRawReadPortUchar( Adapter->IoPAddr + NIC_INTR_STATUS, &Tmp1 );
|
||
|
||
if (Tmp1 & ISR_DMA_DONE) {
|
||
|
||
break;
|
||
|
||
} else {
|
||
|
||
Count--;
|
||
NdisStallExecution(4);
|
||
|
||
}
|
||
|
||
}
|
||
|
||
CurBufAddress++;
|
||
XmitBufAddress++;
|
||
PacketLength--;
|
||
CurBufLen--;
|
||
|
||
}
|
||
|
||
//
|
||
// Do Write errata as described on pages 1-143 and 1-144 of
|
||
// the 1992 LAN databook
|
||
//
|
||
|
||
//
|
||
// Set Count and destination address
|
||
//
|
||
ReadBuffer = XmitBufAddress + ((ULONG_PTR)XmitBufAddress & 1);
|
||
|
||
OldAddr = NewAddr = (USHORT)(ReadBuffer);
|
||
|
||
// NdisRawWritePortUchar(Adapter->IoPAddr + NIC_COMMAND, // robin
|
||
// CR_PAGE0 // robin
|
||
// ); // robin
|
||
NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_ADDR_LSB,
|
||
LSB(PtrToUlong(ReadBuffer))
|
||
);
|
||
|
||
NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_ADDR_MSB,
|
||
MSB(PtrToUlong(ReadBuffer))
|
||
);
|
||
NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_COUNT_LSB,
|
||
0x2
|
||
);
|
||
NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_COUNT_MSB,
|
||
0x0
|
||
);
|
||
|
||
//
|
||
// Set direction (Read)
|
||
//
|
||
NdisRawWritePortUchar(
|
||
Adapter->IoPAddr + NIC_COMMAND,
|
||
CR_START | CR_PAGE0 | CR_DMA_READ
|
||
);
|
||
|
||
if (Adapter->EightBitSlot) {
|
||
|
||
//
|
||
// Read from port
|
||
//
|
||
NdisRawReadPortUchar( Adapter->IoPAddr + NIC_RACK_NIC, &Tmp );
|
||
NdisRawReadPortUchar( Adapter->IoPAddr + NIC_RACK_NIC, &Tmp );
|
||
|
||
} else {
|
||
|
||
//
|
||
// Read from port
|
||
//
|
||
NdisRawReadPortUshort( Adapter->IoPAddr + NIC_RACK_NIC, &TmpShort );
|
||
|
||
}
|
||
|
||
//
|
||
// Wait for addr to change
|
||
//
|
||
TmpShort = 0xFFFF;
|
||
|
||
while (TmpShort != 0) {
|
||
|
||
NdisRawReadPortUchar( Adapter->IoPAddr + NIC_CRDA_LSB, &Tmp );
|
||
NewAddr = Tmp;
|
||
NdisRawReadPortUchar( Adapter->IoPAddr + NIC_CRDA_MSB, &Tmp );
|
||
NewAddr |= (Tmp << 8);
|
||
|
||
if (NewAddr != OldAddr) {
|
||
|
||
break;
|
||
|
||
}
|
||
|
||
NdisStallExecution(1);
|
||
|
||
TmpShort--;
|
||
}
|
||
|
||
if (NewAddr == OldAddr) {
|
||
|
||
NdisWriteErrorLogEntry(
|
||
Adapter->MiniportAdapterHandle,
|
||
NDIS_ERROR_CODE_HARDWARE_FAILURE,
|
||
2,
|
||
cardCopyDownPacket,
|
||
(ULONG_PTR)XmitBufAddress
|
||
);
|
||
|
||
return(FALSE);
|
||
|
||
}
|
||
|
||
//
|
||
// Set Count and destination address
|
||
//
|
||
|
||
// NdisRawWritePortUchar( Adapter->IoPAddr + NIC_COMMAND, CR_PAGE0 ); // robin
|
||
|
||
NdisRawWritePortUchar( Adapter->IoPAddr + NIC_RMT_ADDR_LSB,
|
||
LSB(PtrToUlong(XmitBufAddress)) );
|
||
|
||
NdisRawWritePortUchar( Adapter->IoPAddr + NIC_RMT_ADDR_MSB,
|
||
MSB(PtrToUlong(XmitBufAddress)) );
|
||
|
||
NdisRawWritePortUchar( Adapter->IoPAddr + NIC_RMT_COUNT_LSB,
|
||
LSB(PacketLength) );
|
||
|
||
NdisRawWritePortUchar( Adapter->IoPAddr + NIC_RMT_COUNT_MSB,
|
||
MSB(PacketLength) );
|
||
//
|
||
// Set direction (Write)
|
||
//
|
||
NdisRawWritePortUchar( Adapter->IoPAddr + NIC_COMMAND,
|
||
CR_START | CR_PAGE0 | CR_DMA_WRITE );
|
||
|
||
} // setup
|
||
|
||
//
|
||
// Copy the data now
|
||
//
|
||
|
||
do {
|
||
|
||
UINT Count;
|
||
UCHAR Tmp;
|
||
|
||
//
|
||
// Write the previous byte with this one
|
||
//
|
||
if (OddBufLen) {
|
||
|
||
//
|
||
// It seems that the card stores words in LOW:HIGH order
|
||
//
|
||
NdisRawWritePortUshort( Adapter->IoPAddr + NIC_RACK_NIC,
|
||
(USHORT)(*OddBufAddress | ((*CurBufAddress) << 8)) );
|
||
|
||
OddBufLen = FALSE;
|
||
CurBufAddress++;
|
||
CurBufLen--;
|
||
|
||
}
|
||
|
||
if (Adapter->EightBitSlot) { // byte mode
|
||
|
||
NdisRawWritePortBufferUchar(
|
||
Adapter->IoPAddr + NIC_RACK_NIC,
|
||
CurBufAddress,
|
||
CurBufLen
|
||
);
|
||
|
||
} else { // word mode
|
||
|
||
NdisRawWritePortBufferUshort(
|
||
Adapter->IoPAddr + NIC_RACK_NIC,
|
||
(PUSHORT)CurBufAddress,
|
||
(CurBufLen >> 1));
|
||
|
||
//
|
||
// Save trailing byte (if an odd lengthed transfer)
|
||
//
|
||
if (CurBufLen & 0x1) {
|
||
OddBufAddress = CurBufAddress + (CurBufLen - 1);
|
||
OddBufLen = TRUE;
|
||
}
|
||
|
||
}
|
||
|
||
//
|
||
// Wait for DMA to complete
|
||
//
|
||
Count = 0xFFFF;
|
||
while (Count) {
|
||
|
||
NdisRawReadPortUchar(
|
||
Adapter->IoPAddr + NIC_INTR_STATUS,
|
||
&Tmp );
|
||
|
||
if (Tmp & ISR_DMA_DONE) {
|
||
|
||
break;
|
||
|
||
} else {
|
||
|
||
Count--;
|
||
NdisStallExecution(4);
|
||
|
||
}
|
||
|
||
}
|
||
|
||
//
|
||
// Move to the next buffer
|
||
//
|
||
NdisGetNextBuffer(CurBuffer, &CurBuffer);
|
||
|
||
if (CurBuffer){
|
||
NdisQueryBuffer(CurBuffer, (PVOID *)&CurBufAddress, &CurBufLen);
|
||
}
|
||
|
||
//
|
||
// Get address and length of the next buffer
|
||
//
|
||
while (CurBuffer && (CurBufLen == 0)) {
|
||
|
||
NdisGetNextBuffer(CurBuffer, &CurBuffer);
|
||
|
||
if (CurBuffer){
|
||
NdisQueryBuffer(CurBuffer, (PVOID *)&CurBufAddress, &CurBufLen);
|
||
}
|
||
|
||
}
|
||
|
||
} while (CurBuffer);
|
||
|
||
//
|
||
// Write trailing byte (if necessary)
|
||
//
|
||
if (OddBufLen)
|
||
{
|
||
UINT Count;
|
||
UCHAR Tmp;
|
||
USHORT TmpShort;
|
||
|
||
if (NE2000_PCMCIA == Adapter->CardType) {
|
||
// NE2000 PCMCIA CHANGE!!! start
|
||
TmpShort = (USHORT)*OddBufAddress;
|
||
NdisRawWritePortUshort(Adapter->IoPAddr + NIC_RACK_NIC, TmpShort);
|
||
// NE2000 PCMCIA CHANGE!!! end
|
||
}
|
||
else {
|
||
NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RACK_NIC, *OddBufAddress);
|
||
}
|
||
|
||
//
|
||
// Wait for DMA to complete robin-2
|
||
//
|
||
Count = 0xFFFF;
|
||
while (Count) {
|
||
|
||
NdisRawReadPortUchar(
|
||
Adapter->IoPAddr + NIC_INTR_STATUS,
|
||
&Tmp );
|
||
|
||
if (Tmp & ISR_DMA_DONE) {
|
||
break;
|
||
} else {
|
||
Count--;
|
||
NdisStallExecution(4);
|
||
}
|
||
}
|
||
}
|
||
|
||
//
|
||
// Return length written
|
||
//
|
||
*Length = PacketLength;
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
BOOLEAN
|
||
CardCopyDown(
|
||
IN PNE2000_ADAPTER Adapter,
|
||
IN PUCHAR TargetBuffer,
|
||
IN PUCHAR SourceBuffer,
|
||
IN UINT Length
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Copies Length bytes from the SourceBuffer to the card buffer space
|
||
at card address TargetBuffer.
|
||
|
||
Arguments:
|
||
|
||
Adapter - pointer to the adapter block
|
||
|
||
SourceBuffer - Buffer in virtual address space
|
||
|
||
TargetBuffer - Buffer in card address space
|
||
|
||
Length - number of bytes to transfer to card
|
||
|
||
Return Value:
|
||
|
||
TRUE if the transfer completed with no problems.
|
||
|
||
--*/
|
||
|
||
{
|
||
//
|
||
// Temporary place holders for odd alignment transfers
|
||
//
|
||
UCHAR Tmp, TmpSave;
|
||
USHORT TmpShort;
|
||
|
||
//
|
||
// Values for waiting for noticing when a DMA completes.
|
||
//
|
||
USHORT OldAddr, NewAddr;
|
||
|
||
//
|
||
// Count of transfers to do
|
||
//
|
||
USHORT Count;
|
||
|
||
//
|
||
// Address the copy if coming from
|
||
//
|
||
PUCHAR ReadBuffer;
|
||
|
||
|
||
//
|
||
// Skip 0 length copies
|
||
//
|
||
|
||
if (Length == 0) {
|
||
|
||
return(TRUE);
|
||
|
||
}
|
||
|
||
|
||
if (!Adapter->EightBitSlot && ((ULONG_PTR)TargetBuffer & 0x1)) {
|
||
|
||
//
|
||
// 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->IoPAddr + NIC_RMT_ADDR_LSB,
|
||
LSB(PtrToUlong(TargetBuffer - 1))
|
||
);
|
||
|
||
NdisRawWritePortUchar(
|
||
Adapter->IoPAddr + NIC_RMT_ADDR_MSB,
|
||
MSB(PtrToUlong(TargetBuffer - 1))
|
||
);
|
||
|
||
// NE2000 PCMCIA CHANGE!!! start
|
||
//NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_COUNT_LSB, 0x1);
|
||
NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_COUNT_LSB, 0x2);
|
||
NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_COUNT_MSB, 0x0);
|
||
// NE2000 PCMCIA CHANGE!!! end
|
||
|
||
//
|
||
// Set direction (Read)
|
||
//
|
||
|
||
NdisRawWritePortUchar(
|
||
Adapter->IoPAddr + NIC_COMMAND,
|
||
CR_START | CR_PAGE0 | CR_DMA_READ
|
||
);
|
||
|
||
// NE2000 PCMCIA CHANGE!!! start
|
||
//NdisRawReadPortUchar(Adapter->IoPAddr + NIC_RACK_NIC, &TmpSave);
|
||
NdisRawReadPortUshort(Adapter->IoPAddr + NIC_RACK_NIC, &TmpShort);
|
||
TmpSave = LSB(TmpShort);
|
||
// NE2000 PCMCIA CHANGE!!! end
|
||
|
||
//
|
||
// Do Write errata as described on pages 1-143 and 1-144 of the 1992
|
||
// LAN databook
|
||
//
|
||
|
||
//
|
||
// Set Count and destination address
|
||
//
|
||
|
||
ReadBuffer = TargetBuffer + ((ULONG_PTR)TargetBuffer & 1);
|
||
|
||
OldAddr = NewAddr = (USHORT)(ReadBuffer);
|
||
|
||
// NdisRawWritePortUchar(Adapter->IoPAddr + NIC_COMMAND, CR_PAGE0); // robin
|
||
|
||
NdisRawWritePortUchar(
|
||
Adapter->IoPAddr + NIC_RMT_ADDR_LSB,
|
||
LSB(PtrToUlong(ReadBuffer))
|
||
);
|
||
|
||
NdisRawWritePortUchar(
|
||
Adapter->IoPAddr + NIC_RMT_ADDR_MSB,
|
||
MSB(PtrToUlong(ReadBuffer))
|
||
);
|
||
|
||
NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_COUNT_LSB, 0x2);
|
||
NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_COUNT_MSB, 0x0);
|
||
|
||
//
|
||
// Set direction (Read)
|
||
//
|
||
|
||
NdisRawWritePortUchar(
|
||
Adapter->IoPAddr + NIC_COMMAND,
|
||
CR_START | CR_PAGE0 | CR_DMA_READ
|
||
);
|
||
|
||
//
|
||
// Read from port
|
||
//
|
||
|
||
NdisRawReadPortUshort(Adapter->IoPAddr + NIC_RACK_NIC, &TmpShort);
|
||
|
||
//
|
||
// Wait for addr to change
|
||
//
|
||
|
||
TmpShort = 0xFFFF;
|
||
|
||
while (TmpShort != 0) {
|
||
|
||
NdisRawReadPortUchar(
|
||
Adapter->IoPAddr + NIC_CRDA_LSB,
|
||
&Tmp
|
||
);
|
||
|
||
NewAddr = Tmp;
|
||
|
||
NdisRawReadPortUchar(
|
||
Adapter->IoPAddr + NIC_CRDA_MSB,
|
||
&Tmp
|
||
);
|
||
|
||
NewAddr |= (Tmp << 8);
|
||
|
||
if (NewAddr != OldAddr) {
|
||
|
||
break;
|
||
}
|
||
|
||
NdisStallExecution(1);
|
||
|
||
TmpShort--;
|
||
|
||
}
|
||
|
||
if (NewAddr == OldAddr) {
|
||
|
||
return(FALSE);
|
||
|
||
}
|
||
|
||
//
|
||
// Set Count and destination address
|
||
//
|
||
NdisRawWritePortUchar(
|
||
Adapter->IoPAddr + NIC_RMT_ADDR_LSB,
|
||
LSB(PtrToUlong(TargetBuffer - 1))
|
||
);
|
||
|
||
NdisRawWritePortUchar(
|
||
Adapter->IoPAddr + NIC_RMT_ADDR_MSB,
|
||
MSB(PtrToUlong(TargetBuffer - 1))
|
||
);
|
||
|
||
NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_COUNT_LSB, 0x2);
|
||
NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_COUNT_MSB, 0x0);
|
||
|
||
//
|
||
// Set direction (Write)
|
||
//
|
||
|
||
NdisRawWritePortUchar(
|
||
Adapter->IoPAddr + NIC_COMMAND,
|
||
CR_START | CR_PAGE0 | CR_DMA_WRITE
|
||
);
|
||
|
||
//
|
||
// It seems that the card stores words in LOW:HIGH order
|
||
//
|
||
|
||
NdisRawWritePortUshort(
|
||
Adapter->IoPAddr + NIC_RACK_NIC,
|
||
(USHORT)(TmpSave | ((*SourceBuffer) << 8))
|
||
);
|
||
|
||
//
|
||
// Wait for DMA to complete
|
||
//
|
||
|
||
Count = 0xFFFF;
|
||
|
||
while (Count) {
|
||
|
||
NdisRawReadPortUchar(
|
||
Adapter->IoPAddr + NIC_INTR_STATUS,
|
||
&Tmp
|
||
);
|
||
|
||
if (Tmp & ISR_DMA_DONE) {
|
||
|
||
break;
|
||
|
||
} else {
|
||
|
||
Count--;
|
||
|
||
NdisStallExecution(4);
|
||
|
||
}
|
||
|
||
}
|
||
|
||
SourceBuffer++;
|
||
TargetBuffer++;
|
||
Length--;
|
||
|
||
}
|
||
|
||
//
|
||
// Do Write errata as described on pages 1-143 and 1-144 of the 1992
|
||
// LAN databook
|
||
//
|
||
|
||
//
|
||
// Set Count and destination address
|
||
//
|
||
|
||
ReadBuffer = TargetBuffer + ((ULONG_PTR)TargetBuffer & 1);
|
||
|
||
OldAddr = NewAddr = (USHORT)(ReadBuffer);
|
||
|
||
// NdisRawWritePortUchar( // robin
|
||
// Adapter->IoPAddr + NIC_COMMAND, // robin
|
||
// CR_PAGE0 // robin
|
||
// ); // robin
|
||
|
||
NdisRawWritePortUchar(
|
||
Adapter->IoPAddr + NIC_RMT_ADDR_LSB,
|
||
LSB(PtrToUlong(ReadBuffer))
|
||
);
|
||
|
||
NdisRawWritePortUchar(
|
||
Adapter->IoPAddr + NIC_RMT_ADDR_MSB,
|
||
MSB(PtrToUlong(ReadBuffer))
|
||
);
|
||
|
||
NdisRawWritePortUchar(
|
||
Adapter->IoPAddr + NIC_RMT_COUNT_LSB,
|
||
0x2
|
||
);
|
||
|
||
NdisRawWritePortUchar(
|
||
Adapter->IoPAddr + NIC_RMT_COUNT_MSB,
|
||
0x0
|
||
);
|
||
|
||
//
|
||
// Set direction (Read)
|
||
//
|
||
|
||
NdisRawWritePortUchar(
|
||
Adapter->IoPAddr + NIC_COMMAND,
|
||
CR_START | CR_PAGE0 | CR_DMA_READ
|
||
);
|
||
|
||
if (Adapter->EightBitSlot) {
|
||
|
||
//
|
||
// Read from port
|
||
//
|
||
|
||
NdisRawReadPortUchar(
|
||
Adapter->IoPAddr + NIC_RACK_NIC,
|
||
&Tmp
|
||
);
|
||
|
||
|
||
NdisRawReadPortUchar(
|
||
Adapter->IoPAddr + NIC_RACK_NIC,
|
||
&Tmp
|
||
);
|
||
|
||
} else {
|
||
|
||
//
|
||
// Read from port
|
||
//
|
||
|
||
NdisRawReadPortUshort(
|
||
Adapter->IoPAddr + NIC_RACK_NIC,
|
||
&TmpShort
|
||
);
|
||
|
||
}
|
||
|
||
//
|
||
// Wait for addr to change
|
||
//
|
||
|
||
TmpShort = 0xFFFF;
|
||
|
||
while (TmpShort != 0) {
|
||
|
||
NdisRawReadPortUchar(
|
||
Adapter->IoPAddr + NIC_CRDA_LSB,
|
||
&Tmp
|
||
);
|
||
|
||
NewAddr = Tmp;
|
||
|
||
NdisRawReadPortUchar(
|
||
Adapter->IoPAddr + NIC_CRDA_MSB,
|
||
&Tmp
|
||
);
|
||
|
||
NewAddr |= (Tmp << 8);
|
||
|
||
if (NewAddr != OldAddr) {
|
||
|
||
break;
|
||
}
|
||
|
||
NdisStallExecution(1);
|
||
|
||
TmpShort--;
|
||
|
||
}
|
||
|
||
if (NewAddr == OldAddr) {
|
||
|
||
return(FALSE);
|
||
|
||
}
|
||
|
||
//
|
||
// Set Count and destination address
|
||
//
|
||
|
||
// NdisRawWritePortUchar( // robin
|
||
// Adapter->IoPAddr + NIC_COMMAND, // robin
|
||
// CR_PAGE0 // robin
|
||
// ); // robin
|
||
|
||
NdisRawWritePortUchar(
|
||
Adapter->IoPAddr + NIC_RMT_ADDR_LSB,
|
||
LSB(PtrToUlong(TargetBuffer))
|
||
);
|
||
|
||
NdisRawWritePortUchar(
|
||
Adapter->IoPAddr + NIC_RMT_ADDR_MSB,
|
||
MSB(PtrToUlong(TargetBuffer))
|
||
);
|
||
|
||
NdisRawWritePortUchar(
|
||
Adapter->IoPAddr + NIC_RMT_COUNT_LSB,
|
||
LSB(Length)
|
||
);
|
||
|
||
NdisRawWritePortUchar(
|
||
Adapter->IoPAddr + NIC_RMT_COUNT_MSB,
|
||
MSB(Length)
|
||
);
|
||
|
||
//
|
||
// Set direction (Write)
|
||
//
|
||
|
||
NdisRawWritePortUchar(
|
||
Adapter->IoPAddr + NIC_COMMAND,
|
||
CR_START | CR_PAGE0 | CR_DMA_WRITE
|
||
);
|
||
|
||
if (Adapter->EightBitSlot) {
|
||
|
||
//
|
||
// Repeatedly write to out port
|
||
//
|
||
|
||
NdisRawWritePortBufferUchar(
|
||
Adapter->IoPAddr + NIC_RACK_NIC,
|
||
SourceBuffer,
|
||
Length);
|
||
|
||
} else {
|
||
|
||
//
|
||
// Write words to out ports
|
||
//
|
||
|
||
NdisRawWritePortBufferUshort(
|
||
Adapter->IoPAddr + NIC_RACK_NIC,
|
||
(PUSHORT)SourceBuffer,
|
||
(Length >> 1));
|
||
|
||
//
|
||
// Write trailing byte (if necessary)
|
||
//
|
||
if (Length & 0x1)
|
||
{
|
||
SourceBuffer += (Length - 1);
|
||
|
||
// NE2000 PCMCIA CHANGE!!! start
|
||
|
||
//NdisRawWritePortUchar(
|
||
// Adapter->IoPAddr + NIC_RACK_NIC,
|
||
// *SourceBuffer
|
||
//);
|
||
|
||
TmpShort = (USHORT)(*SourceBuffer);
|
||
NdisRawWritePortUshort(
|
||
Adapter->IoPAddr + NIC_RACK_NIC,
|
||
TmpShort
|
||
);
|
||
// NE2000 PCMCIA CHANGE!!! end
|
||
|
||
|
||
}
|
||
|
||
}
|
||
|
||
//
|
||
// Wait for DMA to complete
|
||
//
|
||
|
||
Count = 0xFFFF;
|
||
|
||
while (Count) {
|
||
|
||
NdisRawReadPortUchar(
|
||
Adapter->IoPAddr + NIC_INTR_STATUS,
|
||
&Tmp
|
||
);
|
||
|
||
if (Tmp & ISR_DMA_DONE) {
|
||
|
||
break;
|
||
|
||
} else {
|
||
|
||
Count--;
|
||
|
||
NdisStallExecution(4);
|
||
|
||
}
|
||
|
||
#if DBG
|
||
if (!(Tmp & ISR_DMA_DONE)) {
|
||
|
||
DbgPrint("CopyDownDMA didn't finish!");
|
||
|
||
}
|
||
#endif // DBG
|
||
|
||
}
|
||
|
||
IF_LOG(Ne2000Log('>');)
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
BOOLEAN
|
||
CardCopyUp(
|
||
IN PNE2000_ADAPTER Adapter,
|
||
IN PUCHAR TargetBuffer,
|
||
IN PUCHAR SourceBuffer,
|
||
IN UINT BufferLength
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Copies data from the card to memory.
|
||
|
||
Arguments:
|
||
|
||
Adapter - pointer to the adapter block
|
||
|
||
Target - the target address
|
||
|
||
Source - the source address (on the card)
|
||
|
||
BufferLength - the number of bytes to copy
|
||
|
||
Return Value:
|
||
|
||
TRUE if the transfer completed with no problems.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
//
|
||
// Used to check when the dma is done
|
||
//
|
||
UCHAR IsrValue;
|
||
|
||
//
|
||
// Count of the number of transfers to do
|
||
//
|
||
USHORT Count;
|
||
|
||
//
|
||
// Place holder for port values
|
||
//
|
||
UCHAR Temp;
|
||
|
||
if (BufferLength == 0) {
|
||
|
||
return TRUE;
|
||
|
||
}
|
||
|
||
//
|
||
// Read the Command Register, to make sure it is ready for a write
|
||
//
|
||
NdisRawReadPortUchar(Adapter->IoPAddr+NIC_COMMAND, &Temp);
|
||
|
||
if (Adapter->EightBitSlot) {
|
||
|
||
//
|
||
// If byte mode
|
||
//
|
||
|
||
//
|
||
// Set Count and destination address
|
||
//
|
||
|
||
// NdisRawWritePortUchar( // robin
|
||
// Adapter->IoPAddr + NIC_COMMAND, // robin
|
||
// CR_PAGE0 // robin
|
||
// ); // robin
|
||
|
||
NdisRawWritePortUchar(
|
||
Adapter->IoPAddr + NIC_RMT_ADDR_LSB,
|
||
LSB(PtrToUlong(SourceBuffer))
|
||
);
|
||
|
||
NdisRawWritePortUchar(
|
||
Adapter->IoPAddr + NIC_RMT_ADDR_MSB,
|
||
MSB(PtrToUlong(SourceBuffer))
|
||
);
|
||
|
||
NdisRawWritePortUchar(
|
||
Adapter->IoPAddr + NIC_RMT_COUNT_LSB,
|
||
LSB(BufferLength)
|
||
);
|
||
|
||
NdisRawWritePortUchar(
|
||
Adapter->IoPAddr + NIC_RMT_COUNT_MSB,
|
||
MSB(BufferLength)
|
||
);
|
||
|
||
//
|
||
// Set direction (Read)
|
||
//
|
||
|
||
NdisRawWritePortUchar(
|
||
Adapter->IoPAddr + NIC_COMMAND,
|
||
CR_START | CR_PAGE0 | CR_DMA_READ
|
||
);
|
||
//
|
||
// Repeatedly read from port
|
||
//
|
||
|
||
NdisRawReadPortBufferUchar(
|
||
Adapter->IoPAddr + NIC_RACK_NIC,
|
||
TargetBuffer,
|
||
BufferLength
|
||
);
|
||
|
||
} else {
|
||
|
||
//
|
||
// Else word mode
|
||
//
|
||
|
||
USHORT Tmp;
|
||
|
||
// NdisRawWritePortUchar( // robin
|
||
// Adapter->IoPAddr + NIC_COMMAND, // robin
|
||
// CR_PAGE0 // robin
|
||
// ); // robin
|
||
|
||
//
|
||
// Avoid transfers to odd addresses
|
||
//
|
||
|
||
if ((ULONG_PTR)SourceBuffer & 0x1) {
|
||
|
||
//
|
||
// For odd addresses we need to read previous word and store the
|
||
// second byte
|
||
//
|
||
|
||
//
|
||
// Set Count and Source address
|
||
//
|
||
|
||
NdisRawWritePortUchar(
|
||
Adapter->IoPAddr + NIC_RMT_ADDR_LSB,
|
||
LSB(PtrToUlong(SourceBuffer - 1))
|
||
);
|
||
|
||
NdisRawWritePortUchar(
|
||
Adapter->IoPAddr + NIC_RMT_ADDR_MSB,
|
||
MSB(PtrToUlong(SourceBuffer - 1))
|
||
);
|
||
|
||
NdisRawWritePortUchar(
|
||
Adapter->IoPAddr + NIC_RMT_COUNT_LSB,
|
||
0x2
|
||
);
|
||
|
||
NdisRawWritePortUchar(
|
||
Adapter->IoPAddr + NIC_RMT_COUNT_MSB,
|
||
0x0
|
||
);
|
||
|
||
//
|
||
// Set direction (Read)
|
||
//
|
||
|
||
NdisRawWritePortUchar(
|
||
Adapter->IoPAddr + NIC_COMMAND,
|
||
CR_START | CR_PAGE0 | CR_DMA_READ
|
||
);
|
||
|
||
NdisRawReadPortUshort(
|
||
Adapter->IoPAddr + NIC_RACK_NIC,
|
||
&Tmp
|
||
);
|
||
|
||
*TargetBuffer = MSB(Tmp);
|
||
|
||
//
|
||
// Wait for DMA to complete
|
||
//
|
||
|
||
Count = 0xFFFF;
|
||
|
||
while (Count) {
|
||
|
||
NdisRawReadPortUchar(
|
||
Adapter->IoPAddr + NIC_INTR_STATUS,
|
||
&IsrValue
|
||
);
|
||
|
||
if (IsrValue & ISR_DMA_DONE) {
|
||
|
||
break;
|
||
|
||
} else {
|
||
|
||
Count--;
|
||
|
||
NdisStallExecution(4);
|
||
|
||
}
|
||
|
||
#if DBG
|
||
if (!(IsrValue & ISR_DMA_DONE)) {
|
||
|
||
DbgPrint("CopyUpDMA didn't finish!");
|
||
|
||
}
|
||
#endif // DBG
|
||
|
||
}
|
||
|
||
SourceBuffer++;
|
||
TargetBuffer++;
|
||
BufferLength--;
|
||
}
|
||
|
||
//
|
||
// Set Count and destination address
|
||
//
|
||
|
||
NdisRawWritePortUchar(
|
||
Adapter->IoPAddr + NIC_RMT_ADDR_LSB,
|
||
LSB(PtrToUlong(SourceBuffer))
|
||
);
|
||
|
||
NdisRawWritePortUchar(
|
||
Adapter->IoPAddr + NIC_RMT_ADDR_MSB,
|
||
MSB(PtrToUlong(SourceBuffer))
|
||
);
|
||
|
||
// NE2000 PCMCIA CHANGE!!! start
|
||
|
||
// NdisRawWritePortUchar(
|
||
// Adapter->IoPAddr + NIC_RMT_COUNT_LSB,
|
||
// LSB(BufferLength)
|
||
// );
|
||
//
|
||
// NdisRawWritePortUchar(
|
||
// Adapter->IoPAddr + NIC_RMT_COUNT_MSB,
|
||
// MSB(BufferLength)
|
||
// );
|
||
|
||
if (BufferLength & 1)
|
||
{
|
||
NdisRawWritePortUchar(
|
||
Adapter->IoPAddr + NIC_RMT_COUNT_LSB,
|
||
LSB(BufferLength + 1)
|
||
);
|
||
|
||
NdisRawWritePortUchar(
|
||
Adapter->IoPAddr + NIC_RMT_COUNT_MSB,
|
||
MSB(BufferLength + 1)
|
||
);
|
||
}
|
||
else
|
||
{
|
||
NdisRawWritePortUchar(
|
||
Adapter->IoPAddr + NIC_RMT_COUNT_LSB,
|
||
LSB(BufferLength)
|
||
);
|
||
|
||
NdisRawWritePortUchar(
|
||
Adapter->IoPAddr + NIC_RMT_COUNT_MSB,
|
||
MSB(BufferLength)
|
||
);
|
||
}
|
||
|
||
// NE2000 PCMCIA CHANGE!!! end
|
||
|
||
|
||
//
|
||
// Set direction (Read)
|
||
//
|
||
|
||
NdisRawWritePortUchar(
|
||
Adapter->IoPAddr + NIC_COMMAND,
|
||
CR_START | CR_PAGE0 | CR_DMA_READ
|
||
);
|
||
|
||
//
|
||
// Read words from port
|
||
//
|
||
|
||
NdisRawReadPortBufferUshort(
|
||
Adapter->IoPAddr + NIC_RACK_NIC,
|
||
(PUSHORT)TargetBuffer,
|
||
(BufferLength >> 1));
|
||
|
||
//
|
||
// Read trailing byte (if necessary)
|
||
//
|
||
|
||
if (BufferLength & 1) {
|
||
|
||
TargetBuffer += (BufferLength - 1);
|
||
|
||
// NE2000 PCMCIA CHANGE!!! start
|
||
|
||
//NdisRawReadPortUchar(
|
||
// Adapter->IoPAddr + NIC_RACK_NIC,
|
||
// TargetBuffer
|
||
//);
|
||
|
||
NdisRawReadPortUshort(
|
||
Adapter->IoPAddr + NIC_RACK_NIC,
|
||
&Tmp
|
||
);
|
||
|
||
*TargetBuffer = LSB(Tmp);
|
||
|
||
// NE2000 PCMCIA CHANGE!!! end
|
||
}
|
||
|
||
}
|
||
|
||
//
|
||
// Wait for DMA to complete
|
||
//
|
||
|
||
Count = 0xFFFF;
|
||
|
||
while (Count) {
|
||
|
||
NdisRawReadPortUchar(
|
||
Adapter->IoPAddr + NIC_INTR_STATUS,
|
||
&IsrValue
|
||
);
|
||
|
||
if (IsrValue & ISR_DMA_DONE) {
|
||
|
||
break;
|
||
|
||
} else {
|
||
|
||
Count--;
|
||
|
||
NdisStallExecution(4);
|
||
|
||
}
|
||
|
||
}
|
||
|
||
#if DBG
|
||
if (!(IsrValue & ISR_DMA_DONE)) {
|
||
|
||
DbgPrint("CopyUpDMA didn't finish!\n");
|
||
|
||
}
|
||
|
||
IF_LOG(Ne2000Log('<');)
|
||
|
||
#endif // DBG
|
||
|
||
return TRUE;
|
||
|
||
}
|
||
|
||
ULONG
|
||
CardComputeCrc(
|
||
IN PUCHAR Buffer,
|
||
IN UINT Length
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine 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 is adapted from the comments in the assembly language
|
||
version in _GENREQ.ASM of the DWB NE1000/2000 driver.
|
||
|
||
--*/
|
||
|
||
{
|
||
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 ^ 0x04c11db6) | Carry;
|
||
|
||
}
|
||
|
||
}
|
||
|
||
}
|
||
|
||
return Crc;
|
||
|
||
}
|
||
|
||
|
||
VOID
|
||
CardGetMulticastBit(
|
||
IN UCHAR Address[NE2000_LENGTH_OF_ADDRESS],
|
||
OUT UCHAR * Byte,
|
||
OUT UCHAR * Value
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
For a given multicast address, returns the byte and bit in
|
||
the card multicast registers that it hashes to. Calls
|
||
CardComputeCrc() to determine the CRC value.
|
||
|
||
Arguments:
|
||
|
||
Address - the address
|
||
|
||
Byte - the byte that it hashes to
|
||
|
||
Value - will have a 1 in the relevant bit
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
ULONG Crc;
|
||
UINT BitNumber;
|
||
|
||
//
|
||
// First compute the CRC.
|
||
//
|
||
|
||
Crc = CardComputeCrc(Address, NE2000_LENGTH_OF_ADDRESS);
|
||
|
||
|
||
//
|
||
// The bit number is now in the 6 most significant bits of CRC.
|
||
//
|
||
|
||
BitNumber = (UINT)((Crc >> 26) & 0x3f);
|
||
|
||
*Byte = (UCHAR)(BitNumber / 8);
|
||
*Value = (UCHAR)((UCHAR)1 << (BitNumber % 8));
|
||
}
|
||
|
||
VOID
|
||
CardFillMulticastRegs(
|
||
IN PNE2000_ADAPTER Adapter
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Erases and refills the card multicast registers. Used when
|
||
an address has been deleted and all bits must be recomputed.
|
||
|
||
Arguments:
|
||
|
||
Adapter - pointer to the adapter block
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
UINT i;
|
||
UCHAR Byte, Bit;
|
||
|
||
//
|
||
// First turn all bits off.
|
||
//
|
||
|
||
for (i=0; i<8; i++) {
|
||
|
||
Adapter->NicMulticastRegs[i] = 0;
|
||
|
||
}
|
||
|
||
//
|
||
// Now turn on the bit for each address in the multicast list.
|
||
//
|
||
|
||
for ( ; i > 0; ) {
|
||
|
||
i--;
|
||
|
||
CardGetMulticastBit(Adapter->Addresses[i], &Byte, &Bit);
|
||
|
||
Adapter->NicMulticastRegs[Byte] |= Bit;
|
||
|
||
}
|
||
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
BOOLEAN SyncCardStop(
|
||
IN PVOID SynchronizeContext
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Sets the NIC_COMMAND register to stop the card.
|
||
|
||
Arguments:
|
||
|
||
SynchronizeContext - pointer to the adapter block
|
||
|
||
Return Value:
|
||
|
||
TRUE if the power has failed.
|
||
|
||
--*/
|
||
|
||
{
|
||
PNE2000_ADAPTER Adapter = ((PNE2000_ADAPTER)SynchronizeContext);
|
||
|
||
NdisRawWritePortUchar(
|
||
Adapter->IoPAddr + NIC_COMMAND,
|
||
CR_STOP | CR_NO_DMA
|
||
);
|
||
|
||
return(FALSE);
|
||
}
|
||
|
||
VOID
|
||
CardStartXmit(
|
||
IN PNE2000_ADAPTER Adapter
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Sets the NIC_COMMAND register to start a transmission.
|
||
The transmit buffer number is taken from Adapter->CurBufXmitting
|
||
and the length from Adapter->PacketLens[Adapter->CurBufXmitting].
|
||
|
||
Arguments:
|
||
|
||
Adapter - pointer to the adapter block
|
||
|
||
Return Value:
|
||
|
||
TRUE if the power has failed.
|
||
|
||
--*/
|
||
|
||
{
|
||
UINT Length = Adapter->PacketLens[Adapter->CurBufXmitting];
|
||
UCHAR Tmp;
|
||
|
||
//
|
||
// Prepare the NIC registers for transmission.
|
||
//
|
||
|
||
NdisRawWritePortUchar(Adapter->IoPAddr+NIC_XMIT_START,
|
||
(UCHAR)(Adapter->NicXmitStart + (UCHAR)(Adapter->CurBufXmitting*BUFS_PER_TX)));
|
||
|
||
//
|
||
// Pad the length to 60 (plus CRC will be 64) if needed.
|
||
//
|
||
|
||
if (Length < 60) {
|
||
|
||
Length = 60;
|
||
|
||
}
|
||
|
||
NdisRawWritePortUchar(Adapter->IoPAddr+NIC_XMIT_COUNT_MSB, MSB(Length));
|
||
NdisRawWritePortUchar(Adapter->IoPAddr+NIC_XMIT_COUNT_LSB, LSB(Length));
|
||
|
||
//
|
||
// Start transmission, check for power failure first.
|
||
//
|
||
|
||
NdisRawReadPortUchar(Adapter->IoPAddr+NIC_COMMAND, &Tmp);
|
||
NdisRawWritePortUchar(Adapter->IoPAddr+NIC_COMMAND,
|
||
CR_START | CR_XMIT | CR_NO_DMA);
|
||
|
||
IF_LOG( Ne2000Log('x');)
|
||
|
||
}
|
||
|
||
BOOLEAN
|
||
SyncCardGetCurrent(
|
||
IN PVOID SynchronizeContext
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Gets the value of the CURRENT NIC register and stores it in Adapter->Current
|
||
|
||
Arguments:
|
||
|
||
SynchronizeContext - pointer to the adapter block
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
PNE2000_ADAPTER Adapter = ((PNE2000_ADAPTER)SynchronizeContext);
|
||
|
||
//
|
||
// Have to go to page 1 to read this register
|
||
//
|
||
|
||
NdisRawWritePortUchar(Adapter->IoPAddr+NIC_COMMAND,
|
||
CR_START | CR_NO_DMA | CR_PAGE1);
|
||
|
||
NdisRawReadPortUchar(Adapter->IoPAddr+NIC_CURRENT,
|
||
&Adapter->Current);
|
||
|
||
NdisRawWritePortUchar(Adapter->IoPAddr+NIC_COMMAND,
|
||
CR_START | CR_NO_DMA | CR_PAGE0);
|
||
|
||
return FALSE;
|
||
|
||
}
|
||
|
||
BOOLEAN
|
||
SyncCardGetXmitStatus(
|
||
IN PVOID SynchronizeContext
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Gets the value of the "transmit status" NIC register and stores
|
||
it in Adapter->XmitStatus.
|
||
|
||
Arguments:
|
||
|
||
SynchronizeContext - pointer to the adapter block
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
PNE2000_ADAPTER Adapter = ((PNE2000_ADAPTER)SynchronizeContext);
|
||
|
||
NdisRawReadPortUchar( Adapter->IoPAddr+NIC_XMIT_STATUS, &Adapter->XmitStatus);
|
||
|
||
return FALSE;
|
||
|
||
}
|
||
|
||
VOID
|
||
CardSetBoundary(
|
||
IN PNE2000_ADAPTER Adapter
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Sets the value of the "boundary" NIC register to one behind
|
||
Adapter->NicNextPacket, to prevent packets from being received
|
||
on top of un-indicated ones.
|
||
|
||
Arguments:
|
||
|
||
Adapter - pointer to the adapter block
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
//
|
||
// Have to be careful with "one behind NicNextPacket" when
|
||
// NicNextPacket is the first buffer in receive area.
|
||
//
|
||
|
||
if (Adapter->NicNextPacket == Adapter->NicPageStart) {
|
||
|
||
NdisRawWritePortUchar( Adapter->IoPAddr+NIC_BOUNDARY,
|
||
(UCHAR)(Adapter->NicPageStop-(UCHAR)1));
|
||
|
||
} else {
|
||
|
||
NdisRawWritePortUchar( Adapter->IoPAddr+NIC_BOUNDARY,
|
||
(UCHAR)(Adapter->NicNextPacket-(UCHAR)1));
|
||
|
||
}
|
||
|
||
}
|
||
|
||
BOOLEAN
|
||
SyncCardSetReceiveConfig(
|
||
IN PVOID SynchronizeContext
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Sets the value of the "receive configuration" NIC register to
|
||
the value of Adapter->NicReceiveConfig.
|
||
|
||
Arguments:
|
||
|
||
SynchronizeContext - pointer to the adapter block
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
PNE2000_ADAPTER Adapter = ((PNE2000_ADAPTER)SynchronizeContext);
|
||
|
||
NdisRawWritePortUchar( Adapter->IoPAddr+NIC_RCV_CONFIG, Adapter->NicReceiveConfig);
|
||
|
||
return FALSE;
|
||
|
||
}
|
||
|
||
BOOLEAN
|
||
SyncCardSetAllMulticast(
|
||
IN PVOID SynchronizeContext
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Turns on all the bits in the multicast register. Used when
|
||
the card must receive all multicast packets.
|
||
|
||
Arguments:
|
||
|
||
SynchronizeContext - pointer to the adapter block
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
PNE2000_ADAPTER Adapter = ((PNE2000_ADAPTER)SynchronizeContext);
|
||
UINT i;
|
||
|
||
//
|
||
// Have to move to page 1 to set these registers.
|
||
//
|
||
|
||
NdisRawWritePortUchar( Adapter->IoPAddr+NIC_COMMAND,
|
||
CR_START | CR_NO_DMA | CR_PAGE1);
|
||
|
||
for (i=0; i<8; i++) {
|
||
|
||
NdisRawWritePortUchar( Adapter->IoPAddr+(NIC_MC_ADDR+i), 0xff);
|
||
|
||
}
|
||
|
||
NdisRawWritePortUchar( Adapter->IoPAddr+NIC_COMMAND,
|
||
CR_START | CR_NO_DMA | CR_PAGE0);
|
||
|
||
return FALSE;
|
||
|
||
}
|
||
|
||
BOOLEAN
|
||
SyncCardCopyMulticastRegs(
|
||
IN PVOID SynchronizeContext
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Sets the eight bytes in the card multicast registers.
|
||
|
||
Arguments:
|
||
|
||
SynchronizeContext - pointer to the adapter block
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
PNE2000_ADAPTER Adapter = ((PNE2000_ADAPTER)SynchronizeContext);
|
||
UINT i;
|
||
|
||
//
|
||
// Have to move to page 1 to set these registers.
|
||
//
|
||
|
||
NdisRawWritePortUchar( Adapter->IoPAddr+NIC_COMMAND,
|
||
CR_START | CR_NO_DMA | CR_PAGE1);
|
||
|
||
for (i=0; i<8; i++) {
|
||
|
||
NdisRawWritePortUchar( Adapter->IoPAddr+(NIC_MC_ADDR+i),
|
||
Adapter->NicMulticastRegs[i]);
|
||
|
||
}
|
||
|
||
NdisRawWritePortUchar( Adapter->IoPAddr+NIC_COMMAND,
|
||
CR_START | CR_NO_DMA | CR_PAGE0);
|
||
|
||
return FALSE;
|
||
|
||
}
|
||
|
||
BOOLEAN
|
||
SyncCardAcknowledgeOverflow(
|
||
IN PVOID SynchronizeContext
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Sets the "buffer overflow" bit in the NIC interrupt status register,
|
||
which re-enables interrupts of that type.
|
||
|
||
Arguments:
|
||
|
||
SynchronizeContext - pointer to the adapter block
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
PNE2000_ADAPTER Adapter = ((PNE2000_ADAPTER)SynchronizeContext);
|
||
UCHAR AcknowledgeMask = 0;
|
||
|
||
if (Adapter->InterruptStatus & ISR_RCV_ERR) {
|
||
|
||
SyncCardUpdateCounters(Adapter);
|
||
|
||
}
|
||
|
||
return FALSE;
|
||
|
||
}
|
||
|
||
BOOLEAN
|
||
SyncCardUpdateCounters(
|
||
IN PVOID SynchronizeContext
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Updates the values of the three counters (frame alignment errors,
|
||
CRC errors, and missed packets).
|
||
|
||
Arguments:
|
||
|
||
SynchronizeContext - pointer to the adapter block
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
PNE2000_ADAPTER Adapter = ((PNE2000_ADAPTER)SynchronizeContext);
|
||
UCHAR Tmp;
|
||
|
||
NdisRawReadPortUchar( Adapter->IoPAddr+NIC_FAE_ERR_CNTR, &Tmp);
|
||
Adapter->FrameAlignmentErrors += Tmp;
|
||
|
||
NdisRawReadPortUchar( Adapter->IoPAddr+NIC_CRC_ERR_CNTR, &Tmp);
|
||
Adapter->CrcErrors += Tmp;
|
||
|
||
NdisRawReadPortUchar( Adapter->IoPAddr+NIC_MISSED_CNTR, &Tmp);
|
||
Adapter->MissedPackets += Tmp;
|
||
|
||
return FALSE;
|
||
|
||
}
|
||
|
||
BOOLEAN
|
||
SyncCardHandleOverflow(
|
||
IN PVOID SynchronizeContext
|
||
)
|
||
|
||
/*++<
|
||
|
||
Routine Description:
|
||
|
||
Sets all the flags for dealing with a receive overflow, stops the card
|
||
and acknowledges all outstanding interrupts.
|
||
|
||
Arguments:
|
||
|
||
SynchronizeContext - pointer to the adapter block
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
PNE2000_ADAPTER Adapter = ((PNE2000_ADAPTER)SynchronizeContext);
|
||
UCHAR Status;
|
||
|
||
IF_LOG( Ne2000Log('F');)
|
||
|
||
//
|
||
// Turn on the STOP bit in the Command register.
|
||
//
|
||
|
||
SyncCardStop(Adapter);
|
||
|
||
//
|
||
// 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.
|
||
//
|
||
//
|
||
|
||
NdisStallExecution(2000);
|
||
|
||
//
|
||
// Save whether we were transmitting to avoid a timing problem
|
||
// where an indication resulted in a send.
|
||
//
|
||
|
||
if (!(Adapter->InterruptStatus & (ISR_XMIT | ISR_XMIT_ERR))) {
|
||
|
||
CardGetInterruptStatus(Adapter,&Status);
|
||
if (!(Status & (ISR_XMIT | ISR_XMIT_ERR))) {
|
||
|
||
Adapter->OverflowRestartXmitDpc = Adapter->TransmitInterruptPending;
|
||
|
||
IF_LOUD( DbgPrint("ORXD=%x\n",Adapter->OverflowRestartXmitDpc); )
|
||
}
|
||
|
||
}
|
||
|
||
Adapter->TransmitInterruptPending = FALSE;
|
||
|
||
//
|
||
// Clear the Remote Byte Count register so that ISR_RESET
|
||
// will come on.
|
||
//
|
||
|
||
NdisRawWritePortUchar( Adapter->IoPAddr+NIC_RMT_COUNT_MSB, 0);
|
||
NdisRawWritePortUchar( Adapter->IoPAddr+NIC_RMT_COUNT_LSB, 0);
|
||
|
||
//
|
||
// According to National Semiconductor, the next check is necessary
|
||
// See Step 5. of the overflow process
|
||
//
|
||
// NOTE: The setting of variables to check if the transmit has completed
|
||
// cannot be done here because anything in the ISR has already been ack'ed
|
||
// inside the main DPC. Thus, the setting of the variables, described in
|
||
// the Handbook was moved to the main DPC.
|
||
//
|
||
// Continued: If you did the check here, you will doubly transmit most
|
||
// packets that happened to be on the card when the overflow occurred.
|
||
//
|
||
|
||
//
|
||
// Put the card in loopback mode, then start it.
|
||
//
|
||
|
||
NdisRawWritePortUchar( Adapter->IoPAddr+NIC_XMIT_CONFIG, TCR_LOOPBACK);
|
||
|
||
//
|
||
// Start the card. This does not Undo the loopback mode.
|
||
//
|
||
|
||
NdisRawWritePortUchar( Adapter->IoPAddr+NIC_COMMAND, CR_START | CR_NO_DMA);
|
||
|
||
return FALSE;
|
||
|
||
}
|
||
|