📄 ne2000adapter.cpp
字号:
}
}
}
return(NDIS_STATUS_SUCCESS);
}
}
/*** end of Handlers ***/
/*++
Routine Description:
Called when a new adapter should be registered. It allocates space for
the adapter, initializes the adapter's block, registers resources
with the wrapper and initializes the physical adapter.
Arguments:
WrapperConfigurationContext - Handle passed by the Ndis
ConfigError - Was there an error during configuration reading.
ConfigErrorValue - Value to log if there is an error.
Return Value:
Indicates the success or failure of the registration.
--*/
NDIS_STATUS KdNe2000Adapter::Register(NDIS_HANDLE WrapperConfigurationContext,
BOOLEAN ConfigError,
ULONG ConfigErrorValue)
{
// Temporary looping variable.
UINT i;
// General purpose return from NDIS calls
NDIS_STATUS status;
// check that NumBuffers <= MAX_XMIT_BUFS
if (Info.NumBuffers > MAX_XMIT_BUFS)
return(NDIS_STATUS_RESOURCES);
// Check for a configuration error
if (ConfigError)
{
// Log Error and exit.
NdisWriteErrorLogEntry(
GetMiniportAdapterHandle(),
NDIS_ERROR_CODE_UNSUPPORTED_CONFIGURATION,
1,
ConfigErrorValue
);
return(NDIS_STATUS_FAILURE);
}
// Set Attr was already called with default values - we dont take any chances and call SetAttr
// with the values we want
SetAttr(FALSE,Info.BusType);
// Register the port addresses.
status = RegisterIoPortRange((PVOID *)(&(Info.IoPAddr)),(ULONG)Info.IoBaseAddr,0x20);
if (status != NDIS_STATUS_SUCCESS)
return(status);
if (NE2000_ISA == Info.CardType)
{
// Check that the IoBaseAddress seems to be correct.
DebugDump(DBG_LEVEL4,("Checking Parameters\n"));
if (!CardCheckParameters())
{
// The card does not seem to be there, fail silently.
DebugDump(DBG_LEVEL4,(" -- Failed\n"));
NdisWriteErrorLogEntry(
GetMiniportAdapterHandle(),
NDIS_ERROR_CODE_ADAPTER_NOT_FOUND,
0);
status = NDIS_STATUS_ADAPTER_NOT_FOUND;
goto fail2;
}
DebugDump(DBG_LEVEL4,(" -- Success\n"));
}
// Initialize the card.
DebugDump(DBG_LEVEL4,("CardInitialize\n"));
if (!CardInitialize())
{
// Card seems to have failed.
DebugDump(DBG_LEVEL4,(" -- Failed\n"));
NdisWriteErrorLogEntry(
GetMiniportAdapterHandle(),
NDIS_ERROR_CODE_ADAPTER_NOT_FOUND,
0
);
status = NDIS_STATUS_ADAPTER_NOT_FOUND;
goto fail2;
}
DebugDump(DBG_LEVEL4,(" -- Success\n"));
// For programmed I/O, we will refer to transmit/receive memory in
// terms of offsets in the card's 64K address space.
Info.XmitStart = Info.RamBase;
// For the NicXXX fields, always use the addressing system
// containing the MSB only).
Info.NicXmitStart = (UCHAR)(((ULONG)Info.XmitStart) >> 8);
// The start of the receive space.
Info.PageStart = Info.XmitStart +
(Info.NumBuffers * TX_BUF_SIZE);
Info.NicPageStart = Info.NicXmitStart +
(UCHAR)(Info.NumBuffers * BUFS_PER_TX);
ASSERT(Info.PageStart < (Info.RamBase + Info.RamSize));
// The end of the receive space.
Info.PageStop = Info.XmitStart + Info.RamSize;
Info.NicPageStop = Info.NicXmitStart + (UCHAR)(Info.RamSize >> 8);
ASSERT(Info.PageStop <= (Info.RamBase + Info.RamSize));
DebugDump(DBG_LEVEL3,("Xmit Start (0x%x, 0x%x) : Rcv Start (0x%x, 0x%x) : Rcv End (0x%x, 0x%x)\n",
Info.XmitStart,
Info.NicXmitStart,
Info.PageStart,
Info.NicPageStart,
(ULONG)Info.PageStop,
Info.NicPageStop
));
// Initialize the receive variables.
Info.NicReceiveConfig = RCR_REJECT_ERR;
// Initialize the transmit buffer control.
Info.CurBufXmitting = (XMIT_BUF)-1;
// Initialize the transmit buffer states.
for (i = 0; i < Info.NumBuffers; i++)
Info.BufferStatus[i] = EMPTY;
// Read the Ethernet address off of the PROM.
if (!CardReadEthernetAddress())
{
DebugDump(DBG_LEVEL3,("Could not read the ethernet address\n"));
NdisWriteErrorLogEntry(
GetMiniportAdapterHandle(),
NDIS_ERROR_CODE_ADAPTER_NOT_FOUND,
0
);
status = NDIS_STATUS_ADAPTER_NOT_FOUND;
goto fail2;
}
// Now initialize the NIC and Gate Array registers.
Info.NicInterruptMask = IMR_RCV | IMR_XMIT | IMR_XMIT_ERR | IMR_OVERFLOW;
// Link us on to the chain of adapters for this driver.
GetMiniportOwner()->AddAdapter(this);
// Setup the card based on the initialization information
DebugDump(DBG_LEVEL4,("Setup\n"));
if (!CardSetup())
{
// The NIC could not be written to.
NdisWriteErrorLogEntry(
GetMiniportAdapterHandle(),
NDIS_ERROR_CODE_ADAPTER_NOT_FOUND,
0
);
DebugDump(DBG_LEVEL4,(" -- Failed\n"));
status = NDIS_STATUS_ADAPTER_NOT_FOUND;
goto fail3;
}
DebugDump(DBG_LEVEL4,(" -- Success\n"));
// Initialize the interrupt.
status = RegisterInterrupt(
Info.InterruptNumber,
Info.InterruptNumber,
FALSE,
FALSE,
NdisInterruptLatched);
if (status != NDIS_STATUS_SUCCESS)
{
NdisWriteErrorLogEntry(
GetMiniportAdapterHandle(),
NDIS_ERROR_CODE_INTERRUPT_CONNECT,
0 );
goto fail3;
}
DebugDump(DBG_LEVEL3,("Interrupt Connected\n"));
// Start up the adapter.
CardStart(this);
// Initialization completed successfully.
DebugDump(DBG_LEVEL3,(" [ Ne2000 ] : OK\n"));
return(NDIS_STATUS_SUCCESS);
// Code to unwind what has already been set up when a part of
// initialization fails, which is jumped into at various
// points based on where the failure occurred. Jumping to
// a higher-numbered failure point will execute the code
// for that block and all lower-numbered ones.
fail3:
// Take us out of the AdapterQueue.
GetMiniportOwner()->RemoveAdapter(this);
//
// We already enabled the interrupt on the card, so
// turn it off.
NdisRawWritePortUchar(Info.IoPAddr+NIC_COMMAND, CR_STOP);
fail2:
DeregisterIoPortRange((ULONG)Info.IoBaseAddr,0x20,(PVOID)Info.IoPAddr);
return(status);
}
/*++
Routine Description:
This routine examines if the packet at the head of the packet
list can be copied to the adapter, and does so.Called by the SendHandler
each time there is a new packet to send and also each time after we receive a
TransmitComplete Interrupt
--*/
VOID KdNe2000Adapter::DoNextSend()
{
// The packet to process.
PNDIS_PACKET Packet;
// The current destination transmit buffer.
XMIT_BUF TmpBuf1;
// Length of the packet
ULONG Len;
// Temporary looping variable
ULONG i;
IF_LOG( Ne2000Log('s'); )
// Check if we have enough resources and a packet to process
while((Info.FirstPacket != NULL) &&
(Info.BufferStatus[Info.NextBufToFill] == EMPTY))
{
// Get the length of the packet.
NdisQueryPacket(Info.FirstPacket, NULL, NULL, NULL, (UINT *)&Len);
// Convert length to the number of transmit buffers needed.
Len = (Len + 255) >> 8;
// If not transmitting
if (Info.CurBufXmitting == -1)
{
// Then check from the next free buffer if the packet will
// fit.
if (Info.BufferStatus[Info.NextBufToXmit] == EMPTY)
{
// It won't fit at the end, so put it at the first buffer
if (Info.NextBufToFill + Len > MAX_XMIT_BUFS)
{
Info.NextBufToFill = 0;
}
}
else
{
// Check if this packet will fit before the packet on the
// adapter.
if (Info.NextBufToXmit > Info.NextBufToFill)
{
if (Info.NextBufToFill + Len > Info.NextBufToXmit)
{
IF_LOG( Ne2000Log('^'); )
IF_LOG( Ne2000Log('S'); )
break;
}
}
else
{
// Check if it will fit after the packet already on the
// adapter.
if (Info.NextBufToFill + Len > MAX_XMIT_BUFS)
{
Info.NextBufToFill = 0;
if (Info.NextBufToFill + Len > Info.NextBufToXmit)
{
IF_LOG( Ne2000Log('%'); )
IF_LOG( Ne2000Log('S'); )
break;
}
}
}
}
}
else
{
// Check if the packet will fit before the packet currently
// transmitting
if (Info.CurBufXmitting > Info.NextBufToFill)
{
if (Info.NextBufToFill + Len > Info.CurBufXmitting)
{
IF_LOG( Ne2000Log('$'); )
IF_LOG( Ne2000Log('S'); )
break;
}
}
else
{
// Check if it will fit after the packet currently transmitting
if (Info.NextBufToFill + Len > MAX_XMIT_BUFS)
{
Info.NextBufToFill = 0;
if (Info.NextBufToFill + Len > Info.CurBufXmitting)
{
IF_LOG( Ne2000Log('!'); )
IF_LOG( Ne2000Log('S'); )
break;
}
}
}
}
// Set starting location
TmpBuf1 = Info.NextBufToFill;
// Remove the packet from the queue.
Packet = Info.FirstPacket;
Info.FirstPacket = RESERVED(Packet)->Next;
if (Packet == Info.LastPacket)
{
Info.LastPacket = NULL;
}
// Store the packet in the list
Info.Packets[TmpBuf1] = Packet;
// Copy down the packet.
if (CardCopyDownPacket(Packet,&Info.PacketLens[TmpBuf1]) == FALSE)
{
for (i = TmpBuf1; i < TmpBuf1 + Len; i++)
{
Info.BufferStatus[i] = EMPTY;
}
Info.Packets[TmpBuf1] = NULL;
IF_LOG( Ne2000Log('F'); )
IF_LOG( Ne2000Log('S'); )
SendComplete(Packet, NDIS_STATUS_FAILURE);
continue;
}
// Pad short packets with blanks.
if (Info.PacketLens[TmpBuf1] < 60)
{
(VOID)CardCopyDown(
((PUCHAR)Info.XmitStart +
TmpBuf1*TX_BUF_SIZE +
Info.PacketLens[TmpBuf1]),
BlankBuffer,
60-Info.PacketLens[TmpBuf1]
);
}
// Set the buffer status
for (i = TmpBuf1; i < (TmpBuf1 + Len); i++)
{
Info.BufferStatus[i] = FULL;
}
// Update next free buffer
Info.NextBufToFill += Len;
if (Info.NextBufToFill == MAX_XMIT_BUFS)
{
Info.NextBufToFill = 0;
}
// See whether to start the transmission.
if (Info.CurBufXmitting == -1)
{
// OK to start transmission.
if (Info.BufferStatus[Info.NextBufToXmit] == EMPTY &&
Info.NextBufToFill != Info.NextBufToXmit)
{
Info.NextBufToXmit = 0;
}
Info.CurBufXmitting = Info.NextBufToXmit;
IF_LOG( Ne2000Log('4');)
// If we are currently handling an overflow, then we need to let
// the overflow handler send this packet...
if (Info.BufferOverflow)
{
Info.OverflowRestartXmitDpc = TRUE;
IF_LOG( Ne2000Log('O');)
DebugDump(DBG_LEVEL3, ("Info.OverflowRestartXmitDpc set:copy and send"));
}
else
{
// This is used to check if stopping the chip prevented
// a transmit complete interrupt from coming through (it
// is cleared in the ISR if a transmit DPC is queued).
Info.TransmitInterruptPending = TRUE;
IF_LOG( Ne2000Log('9'); )
CardStartXmit();
}
}
// Ack the send immediately. If for some reason it
// should fail, the protocol should be able to handle
// the retransmit.
IF_LOG( Ne2000Log('S'); )
SendComplete(Packet,NDIS_STATUS_SUCCESS);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -