firda.c
来自「S3C24A0的完整BSP包,对开发此芯片的开发者很有用.」· C语言 代码 · 共 2,000 行 · 第 1/5 页
C
2,000 行
*************************************************************************
* MiniportSend
*************************************************************************
*
*
* Transmits a packet through the network interface card onto the medium.
*
*
*
*/
NDIS_STATUS MiniportSend(
IN NDIS_HANDLE MiniportAdapterContext,
IN PNDIS_PACKET Packet,
IN UINT Flags
)
{
NDIS_STATUS stat;
BOOLEAN TxWasActive;
IrDevice *thisDev = CONTEXT_TO_DEV(MiniportAdapterContext);
LOG(TEXT("==> MiniportSend"), 0);
DBGOUT((TEXT("==> MiniportSend(0x%x, packet = 0x%x)"),
(UINT)MiniportAdapterContext, Packet));
DEBUGMSG(DBG_TX | DBG_TRACE_TX,
(TEXT("+MiniportSend(pkt = 0x%x)\r\n"), Packet));
//
// If we have temporarily lost access to the hardware, don't queue up any sends.
// return failure until we regain access to the hw.
//
NdisAcquireSpinLock(&thisDev->Lock);
if (thisDev->resourcesReleased){
DEBUGMSG(DBGIRDA, (TEXT("Resource Released\r\n")));
NdisReleaseSpinLock(&thisDev->Lock);
ASSERT(FALSE);
return (NDIS_STATUS_FAILURE);
}
IRFIR_LOG_NDIS_PACKET(LOG_TXFRAME, Packet);
if (thisDev->currentSpeed > MAX_SIR_SPEED)
{
DEBUGMSG(DBG_TRACE_TX, (TEXT("MSend => MIR | FIR\r\n")));
TxWasActive = (thisDev->AdapterState==ADAPTER_TX);
thisDev->AdapterState = ADAPTER_TX;
NDIS_SET_PACKET_STATUS(Packet, NDIS_STATUS_PENDING);
InsertTailList(&thisDev->SendQueue,
(PLIST_ENTRY)Packet->MiniportReserved);
if (!TxWasActive)
{
DEBUGMSG(DBG_TRACE_TX, (TEXT("MSend => TX idle, do work...\r\n")));
//
// Complete the Receive DMA before starting the next
// set of transmits.
//
NdisMCompleteDmaTransfer(&stat, thisDev->DmaHandle,
thisDev->rcvDmaBuffer,
thisDev->rcvDmaOffset,
thisDev->rcvDmaSize, FALSE);
DEBUGMSG(DBG_TRACE_TX, (TEXT("MSend: CompleteDma returned 0x%x\r\n"),
stat));
if (!RegStats.RxWindow) {
LOG(TEXT("SendPacketsHandler - RxWindow has zero value"), 0);
DBGOUT((TEXT("SendPacketsHandler - RxWindow has zero value")));
}
if (RegStats.RxDPC_Window > 1) {
RegStats.RxDPC_G1_Count++;
}
RegStats.RxWindowMax = MAX(RegStats.RxWindowMax, RegStats.RxWindow);
RegStats.RxWindow = 0;
RegStats.RxDPC_WindowMax = MAX(RegStats.RxDPC_WindowMax, RegStats.RxDPC_Window);
RegStats.RxDPC_Window = 0;
//
// Use DMA swap bit to switch to DMA to Transmit.
//
//
// Kick off the first transmit.
//
FIR_Send(thisDev);
}
else {
DEBUGFIR(DBGIRDA, (TEXT("MSend: TX active, queue packet\r\n")));
}
stat = NDIS_STATUS_PENDING;
}
else
{
stat = SendCommPacket(thisDev, Packet);
DEBUGMSG(DBG_TRACE_TX, (TEXT("MSend: SendCommPacket returned 0x%x\r\n"),
stat));
}
NdisReleaseSpinLock(&thisDev->Lock);
LOG(TEXT("<== MiniportSend"), 1);
DBGOUT((TEXT("<== MiniportSend [%s]"), DBG_NDIS_RESULT_STR(stat)));
DEBUGMSG(DBG_TX | DBG_TRACE_TX, (TEXT("-MiniportSend [0x%x]\r\n"), stat));
return (stat);
}
/*
*************************************************************************
* MiniportTransferData
*************************************************************************
*
*
* Copies the contents of the received packet to a specified packet buffer.
*
*
*
*/
NDIS_STATUS MiniportTransferData(
OUT PNDIS_PACKET Packet,
OUT PUINT BytesTransferred,
IN NDIS_HANDLE MiniportAdapterContext,
IN NDIS_HANDLE MiniportReceiveContext,
IN UINT ByteOffset,
IN UINT BytesToTransfer
)
{
RETAILMSG(DBGIRDA, (TEXT("MiniportTransferData - should not get called.")));
/*
* We always pass the entire packet up in the indicate-receive call,
* so we will never get this callback.
* (We can't do anything but return failure anyway,
* since NdisMIndicateReceivePacket does not pass up a packet context).
*/
ASSERT(FALSE);
*BytesTransferred = 0;
return NDIS_STATUS_FAILURE;
}
/*
*************************************************************************
* ReturnPacketHandler
*************************************************************************
*
* When NdisMIndicateReceivePacket returns asynchronously,
* the protocol returns ownership of the packet to the miniport via this function.
*
*/
VOID ReturnPacketHandler(NDIS_HANDLE MiniportAdapterContext, PNDIS_PACKET Packet)
{
IrDevice *thisDev = CONTEXT_TO_DEV(MiniportAdapterContext);
rcvBuffer *rcvBuf;
DBGOUT((TEXT("ReturnPacketHandler(0x%x, packet = 0x%x)"),
(UINT)MiniportAdapterContext, Packet));
NdisAcquireSpinLock(&thisDev->Lock);
RegStats.ReturnPacketHandlerCalled++;
//
// MiniportReserved contains the pointer to our rcvBuffer
//
rcvBuf = *(rcvBuffer**) Packet->MiniportReserved;
VerifyNdisPacket(Packet, 1);
if (rcvBuf->state == STATE_PENDING){
PNDIS_BUFFER ndisBuf;
DBGPKT((TEXT("Reclaimed rcv packet 0x%x."), (UINT)Packet));
LOG_PacketUnchain(thisDev, rcvBuf->packet);
NdisUnchainBufferAtFront(Packet, &ndisBuf);
if (ndisBuf){
NdisFreeBuffer(ndisBuf);
}
if (!rcvBuf->isDmaBuf)
{
InsertTailList(&thisDev->rcvBufBuf,RCV_BUF_TO_LIST_ENTRY(rcvBuf->dataBuf));
// ASSERT the pointer is actually outside our FIR DMA buffer
ASSERT(rcvBuf->dataBuf < thisDev->portInfo.dmaReadBuf ||
rcvBuf->dataBuf >= thisDev->portInfo.dmaReadBuf+RCV_DMA_SIZE);
}
rcvBuf->dataBuf = NULL;
rcvBuf->state = STATE_FREE;
LOG_RemoveEntryList(thisDev, rcvBuf);
RemoveEntryList(&rcvBuf->listEntry);
VerifyNdisPacket(rcvBuf->packet, 0);
InsertHeadList(&thisDev->rcvBufFree, &rcvBuf->listEntry);
}
else {
LOG(TEXT("Error: Packet in ReturnPacketHandler was not PENDING"), 0);
DBGERR((TEXT("Packet in ReturnPacketHandler was not PENDING.")));
}
VerifyNdisPacket(rcvBuf->packet, 1);
NdisReleaseSpinLock(&thisDev->Lock);
}
/*
*************************************************************************
* AllocateCompleteHandler
*************************************************************************
*
* Indicate completion of an NdisMAllocateSharedMemoryAsync call.
* We never call that function, so we should never get entered here.
*
*/
VOID AllocateCompleteHandler( NDIS_HANDLE MiniportAdapterContext,
PVOID VirtualAddress,
PNDIS_PHYSICAL_ADDRESS PhysicalAddress,
ULONG Length,
PVOID Context)
{
DBGERR((TEXT("AllocateCompleteHandler - should not get called")));
}
/*
*************************************************************************
* PortReadyForWrite
*************************************************************************
*
* Called when COM port is ready for another write packet.
* Send the first frame in the send queue.
*
* Return TRUE iff send succeeded.
*
* NOTE: Do not call inside of interrupt context.
*
*/
NDIS_STATUS PortReadyForWrite(IrDevice *thisDev, BOOLEAN firstBufIsPending)
{
NDIS_STATUS Result = NDIS_STATUS_FAILURE;
BOOLEAN sendSucceeded;
PLIST_ENTRY ListEntry;
#if 0
DEBUGMSG(DBG_TX, (TEXT("prfw\r\n")));
DBGOUT((TEXT("PortReadyForWrite(dev=0x%x, %xh, %hs)"),
(UINT)thisDev,
thisDev->portInfo.ioBase,
(CHAR *)(firstBufIsPending ? "pend" : "not pend")));
#endif
ListEntry = MyRemoveHeadList(&thisDev->SendQueue);
if (ListEntry){
PNDIS_PACKET packetToSend = CONTAINING_RECORD(ListEntry,
NDIS_PACKET,
MiniportReserved);
PNDIS_IRDA_PACKET_INFO packetInfo;
/*
* Enforce the minimum turnaround time that must transpire
* after the last receive.
*/
packetInfo = GetPacketInfo(packetToSend);
//
// NOTE: Don't use NdisStallExecution for turnaround delay since
// you shouldn't stall for more than 60 us. Calling
// NdisStallExecution for large times will degrade system
// performance.
//
if (packetInfo->MinTurnAroundTime){
UINT usecToWait = packetInfo->MinTurnAroundTime;
UINT msecToWait;
packetInfo->MinTurnAroundTime = 0;
InsertHeadList(&thisDev->SendQueue, (PLIST_ENTRY)packetToSend->MiniportReserved);
// Ndis timer has a 1ms granularity (in theory). Let's round off.
msecToWait = (usecToWait<1000) ? 1 : (usecToWait+500)/1000;
#ifdef UNDER_CE
NdisMSetTimer(&thisDev->TurnaroundTimer, msecToWait);
#else // UNDER_CE
NdisSetTimer(&thisDev->TurnaroundTimer, msecToWait);
#endif //!UNDER_CE
return NDIS_STATUS_PENDING; // Say we're successful. We'll come back here.
}
/*
* See if this was the last packet before we need to change
* speed.
*/
if (packetToSend == thisDev->lastPacketAtOldSpeed){
thisDev->lastPacketAtOldSpeed = NULL;
thisDev->setSpeedAfterCurrentSendPacket = TRUE;
}
/*
* Send one packet to the COMM port.
*/
DBGPKT((TEXT("Sending packet 0x%x (0x%x)."),
thisDev->packetsSent++, (UINT)packetToSend));
sendSucceeded = DoSend(thisDev, packetToSend);
/*
* If the buffer we just sent was pending
* (i.e. we returned NDIS_STATUS_PENDING for it in MiniportSend),
* then hand the sent packet back to the protocol.
* Otherwise, we're just delivering it synchronously from MiniportSend.
*/
if (firstBufIsPending){
DBGOUT((TEXT("Calling NdisMSendComplete")));
NdisMSendComplete(thisDev->ndisAdapterHandle, packetToSend,
(NDIS_STATUS)(sendSucceeded ? NDIS_STATUS_SUCCESS : NDIS_STATUS_FAILURE));
// If the packet was pended, it means this packet was not just
// received in MiniportSend. If we're being called from there,
// we want them to pend the packet they just did receive, so we
// return PENDING.
Result = NDIS_STATUS_PENDING;
}
else
{
Result = sendSucceeded ? NDIS_STATUS_SUCCESS : NDIS_STATUS_FAILURE;
}
}
DBGOUT((TEXT("PortReadyForWrite done.")));
return Result;
}
/*
*************************************************************************
* DriverEntry
*************************************************************************
*
* Only include if IRMINI is a stand-alone driver.
*
*/
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath);
#pragma NDIS_INIT_FUNCTION(DriverEntry)
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
{
NTSTATUS result = STATUS_SUCCESS, stat;
NDIS_HANDLE wrapperHandle;
NDIS40_MINIPORT_CHARACTERISTICS info;
RETAILMSG(DBGIRDA, (TEXT("==> DriverEntry(0x%x, 0x%x\r\n)"), DriverObject, RegistryPath));
#ifndef UNDER_CE
if (AbortLoad)
{
return STATUS_CANCELLED;
}
#endif // !UNDER_CE
NdisMInitializeWrapper( (PNDIS_HANDLE)&wrapperHandle,
DriverObject,
RegistryPath,
NULL
);
DEBUGFIR(DBGIRDA, (TEXT("NDIS wrapper handle is 0x%xh\r\n"), wrapperHandle));
memset(&info, 0, sizeof(info));
info.MajorNdisVersion = (UCHAR)NDIS_MAJOR_VERSION;
info.MinorNdisVersion = (UCHAR)NDIS_MINOR_VERSION;
info.CheckForHangHandler = MiniportCheckForHang;
info.HaltHandler = MiniportHalt;
info.InitializeHandler = MiniportInitialize;
info.QueryInformationHandler = MiniportQueryInformation;
info.ReconfigureHandler = MiniportReconfigure;
info.ResetHandler = MiniportReset;
info.SendHandler = MiniportSend;
info.SetInformationHandler =
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?