mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
369 lines
7.6 KiB
369 lines
7.6 KiB
/*++
|
|
|
|
Copyright (c) 1992 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
send.c
|
|
|
|
Abstract:
|
|
|
|
This file handles sending packets the Ungermann Bass Ethernet Controller.
|
|
This driver conforms to the NDIS 3.0 interface.
|
|
|
|
|
|
Author:
|
|
|
|
Brian Lieuallen (BrianLie) 07/02/92
|
|
|
|
|
|
Environment:
|
|
|
|
Kernel Mode Operating Systems : NT and other lesser OS's
|
|
|
|
Revision History:
|
|
|
|
Brian Lieuallen BrianLie 12/15/93
|
|
Made it a mini-port
|
|
|
|
|
|
--*/
|
|
|
|
|
|
|
|
#include <ndis.h>
|
|
#include <efilter.h>
|
|
|
|
#include "niudata.h"
|
|
#include "debug.h"
|
|
|
|
#include "ubhard.h"
|
|
#include "ubsoft.h"
|
|
#include "ubnei.h"
|
|
|
|
#include "map.h"
|
|
|
|
|
|
BOOLEAN
|
|
CardSend(
|
|
IN PUBNEI_ADAPTER pAdapter,
|
|
IN PNDIS_PACKET pPacket,
|
|
IN UINT PacketLength
|
|
);
|
|
|
|
|
|
|
|
BOOLEAN
|
|
UbneiMapSendBufferSync(
|
|
PSEND_SYNC_CONTEXT pSync
|
|
);
|
|
|
|
BOOLEAN
|
|
UbneiGiveSendBufferToCardSync(
|
|
PSEND_SYNC_CONTEXT pSync
|
|
);
|
|
|
|
|
|
|
|
|
|
NDIS_STATUS
|
|
UbneiMacSend(
|
|
IN NDIS_HANDLE MacBindingHandle,
|
|
IN PNDIS_PACKET pPacket,
|
|
IN UINT Flags
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
MacSend
|
|
|
|
|
|
Arguments:
|
|
See NDIS 3.0 spec
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
|
|
{
|
|
PUBNEI_ADAPTER pAdapter = MacBindingHandle;
|
|
UINT PacketLength;
|
|
BOOLEAN SendResult;
|
|
|
|
IF_LOG('s');
|
|
|
|
ASSERT_RECEIVE_WINDOW( pAdapter);
|
|
|
|
IF_SEND_LOUD(DbgPrint("MacSend called Packets\n");)
|
|
|
|
NdisQueryPacket(pPacket, NULL, NULL, NULL, &PacketLength);
|
|
|
|
//
|
|
// Here we check to make sure the packet meets some size constraints
|
|
//
|
|
|
|
if (PacketLength < 14 || PacketLength > 1514) {
|
|
|
|
IF_LOUD(DbgPrint("MovePacketToCard: Packet too long or too short\n");)
|
|
|
|
return NDIS_STATUS_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
// No packets queued, so we have a good chance
|
|
// being able to complete this send right now.
|
|
// After all the card has enough buffers for
|
|
// ~32 full size frames.
|
|
//
|
|
|
|
SendResult=CardSend(pAdapter, pPacket, PacketLength);
|
|
|
|
if (SendResult) {
|
|
//
|
|
// It's gone, were out of here!
|
|
//
|
|
// Since we sent it down to the card we don't need the card
|
|
// to generate an interrupt
|
|
//
|
|
ASSERT_RECEIVE_WINDOW( pAdapter);
|
|
|
|
UBNEI_MOVE_UCHAR_TO_SHARED_RAM(&(((PLOWNIUDATA)(pAdapter->pCardRam))->HostQueuedTransmits),0);
|
|
|
|
NdisMSendResourcesAvailable(pAdapter->NdisAdapterHandle);
|
|
|
|
return NDIS_STATUS_SUCCESS;
|
|
|
|
} else {
|
|
//
|
|
// No card buffers left, queue it and tell the card
|
|
// to interrupt us when there is room.
|
|
//
|
|
IF_LOUD(DbgPrint("UBNEI: No card send resources\n");)
|
|
|
|
IF_LOG('o');
|
|
|
|
pAdapter->WaitingForXmitInterrupt=TRUE;
|
|
|
|
ASSERT_RECEIVE_WINDOW( pAdapter);
|
|
|
|
UBNEI_MOVE_UCHAR_TO_SHARED_RAM(&(((PLOWNIUDATA)(pAdapter->pCardRam))->HostQueuedTransmits),1);
|
|
|
|
return NDIS_STATUS_RESOURCES;
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
BOOLEAN
|
|
CardSend(
|
|
IN PUBNEI_ADAPTER pAdapter,
|
|
IN PNDIS_PACKET pPacket,
|
|
IN UINT PacketLength
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
This routine checks the cards transmit ring buffer to see if
|
|
a send can take place. If it can then it removes the buffer
|
|
from the free transmit buffer ring buffer and places it on
|
|
the to be transimitted ring buffer.
|
|
|
|
|
|
Arguments:
|
|
|
|
pAdapt - pointer to the adapter block
|
|
|
|
Return Value:
|
|
returns TRUE if it was able to copy the send data to the card
|
|
|
|
FALSE indicates that there are no free transmit buffers currently
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
SEND_SYNC_CONTEXT SyncContext;
|
|
|
|
BOOLEAN OkToSend;
|
|
|
|
SyncContext.pAdapter=pAdapter;
|
|
|
|
|
|
if (PacketLength<60) {
|
|
|
|
PacketLength=60;
|
|
|
|
}
|
|
|
|
SyncContext.PacketLength=PacketLength;
|
|
|
|
OkToSend=NdisMSynchronizeWithInterrupt(
|
|
&pAdapter->NdisInterrupt,
|
|
UbneiMapSendBufferSync,
|
|
&SyncContext
|
|
);
|
|
|
|
if (OkToSend) {
|
|
//
|
|
// If we can send now the sync routine left the correct
|
|
// window mapped in for us to copy to the send buffer
|
|
//
|
|
{
|
|
PUCHAR CurAddress, BufAddress;
|
|
UINT Len;
|
|
PNDIS_BUFFER CurBuffer;
|
|
|
|
//
|
|
// Memory mapped, just copy each buffer over.
|
|
//
|
|
|
|
NdisQueryPacket(pPacket, NULL, NULL, &CurBuffer, NULL);
|
|
|
|
CurAddress = SyncContext.SendBuffer;
|
|
|
|
while (CurBuffer) {
|
|
|
|
NdisQueryBuffer(CurBuffer, (PVOID *)&BufAddress, &Len);
|
|
|
|
UBNEI_MOVE_MEM_TO_SHARED_RAM(CurAddress, BufAddress, Len);
|
|
|
|
CurAddress += Len;
|
|
|
|
NdisGetNextBuffer(CurBuffer, &CurBuffer);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
NdisMSynchronizeWithInterrupt(
|
|
&pAdapter->NdisInterrupt,
|
|
UbneiGiveSendBufferToCardSync,
|
|
&SyncContext
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
return OkToSend;
|
|
|
|
|
|
}
|
|
|
|
|
|
BOOLEAN
|
|
UbneiMapSendBufferSync(
|
|
PSEND_SYNC_CONTEXT pSync
|
|
)
|
|
|
|
{
|
|
PUBNEI_ADAPTER pAdapter=pSync->pAdapter;
|
|
PHIGHNIUDATA pDataWindow = (PHIGHNIUDATA) pAdapter->pDataWindow;
|
|
|
|
PTBD pTBD;
|
|
|
|
UCHAR TmpUchar2;
|
|
UCHAR MapWindow;
|
|
|
|
USHORT TbdOffset;
|
|
USHORT BufferOffset;
|
|
|
|
|
|
SET_DATAWINDOW(pAdapter,INTERRUPT_ENABLED);
|
|
|
|
//
|
|
// Check to see if there are any free TBD descriptors. If not then
|
|
// we can't do any sends now
|
|
//
|
|
|
|
UBNEI_MOVE_SHARED_RAM_TO_UCHAR(&pSync->TbdIndex, &(pDataWindow->FreeTDBs.SRB_ReadPtr[0]));
|
|
UBNEI_MOVE_SHARED_RAM_TO_UCHAR(&TmpUchar2, &(pDataWindow->FreeTDBs.SRB_WritePtr[0]));
|
|
|
|
if (pSync->TbdIndex == TmpUchar2 ) {
|
|
SET_RECDWINDOW(pAdapter,INTERRUPT_ENABLED);
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Get the address of the TBD in the NIU data segment
|
|
//
|
|
|
|
UBNEI_MOVE_SHARED_RAM_TO_USHORT(&TbdOffset,
|
|
&(pDataWindow->FreeTDBs.SRB_Offsets[pSync->TbdIndex])
|
|
);
|
|
|
|
pTBD=(PTBD)((PUCHAR)pAdapter->pCardRam+TbdOffset);
|
|
|
|
//
|
|
// Set the length of the frame to be sent in the TBD
|
|
//
|
|
|
|
UBNEI_MOVE_USHORT_TO_SHARED_RAM(&(pTBD->TBD_Frame_Length), (USHORT)pSync->PacketLength);
|
|
UBNEI_MOVE_USHORT_TO_SHARED_RAM(&(pTBD->TBD_EOF_and_Length), (USHORT)pSync->PacketLength | 0x8000);
|
|
|
|
//
|
|
// Get a pointer to the TBD buffer located in the NIU code segment
|
|
// Under the current version of download code the transmit buffer is
|
|
// is 1514 bytes long, so this makes things easy
|
|
//
|
|
|
|
UBNEI_MOVE_SHARED_RAM_TO_USHORT(&BufferOffset, &(pTBD->TBD_Buffer_offset));
|
|
|
|
pSync->SendBuffer=(PUCHAR)pAdapter->pCardRam + BufferOffset;
|
|
|
|
//
|
|
// Set the map register to point to the correct window to access
|
|
// the send buffer
|
|
//
|
|
|
|
UBNEI_MOVE_SHARED_RAM_TO_UCHAR(&MapWindow, &(pTBD->TBD_Buffer_Map));
|
|
|
|
pAdapter->MapRegSync.NewMapRegister=MapWindow | INTERRUPT_ENABLED;
|
|
|
|
UbneiMapRegisterChangeSync(&pAdapter->MapRegSync);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
BOOLEAN
|
|
UbneiGiveSendBufferToCardSync(
|
|
PSEND_SYNC_CONTEXT pSync
|
|
)
|
|
|
|
{
|
|
PUBNEI_ADAPTER pAdapter=pSync->pAdapter;
|
|
PHIGHNIUDATA pDataWindow = (PHIGHNIUDATA) pAdapter->pDataWindow;
|
|
|
|
UCHAR TmpUchar1;
|
|
|
|
|
|
SET_DATAWINDOW(pAdapter,INTERRUPT_ENABLED);
|
|
|
|
//
|
|
// To actually give the data to the NIU to send, we remove the this
|
|
// TBD from the FreeTDB buffer and add it to XmtFrames buffer
|
|
//
|
|
|
|
UBNEI_MOVE_UCHAR_TO_SHARED_RAM(&(pDataWindow->FreeTDBs.SRB_ReadPtr[0]), pSync->TbdIndex + 1);
|
|
|
|
UBNEI_MOVE_SHARED_RAM_TO_UCHAR(&TmpUchar1, &(pDataWindow->XmtFrames.SRB_WritePtr[0]));
|
|
UBNEI_MOVE_UCHAR_TO_SHARED_RAM(&(pDataWindow->XmtFrames.SRB_WritePtr[0]), TmpUchar1 + 1);
|
|
|
|
SET_RECDWINDOW(pAdapter,INTERRUPT_ENABLED);
|
|
|
|
return TRUE;
|
|
}
|