📄 send.c
字号:
// re-aquire spinlock.
//
NdisDprReleaseSpinLock(&pXmitDmaQ->lock);
NdisMCoSendComplete(
NDIS_STATUS_SUCCESS,
pVc->NdisVcHandle,
Packet);
DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO,
("TbAtm155TxInterruptOnCompletion: Pkt %x\n", Packet));
DBGPRINT(DBG_COMP_TXIOC, DBG_LEVEL_INFO,
("TbAtm155TxIOC: Pkt %x VC:%lx(OK)\n", Packet, pVc->VpiVci.Vci));
NdisDprAcquireSpinLock(&pXmitDmaQ->lock);
//
// Check if any packets are waiting in the
// waiting segment queue, SegWait, of the VC.
//
tbAtm155QueuePacketsToDmaWaitQueue(pXmitSegInfo);
NdisDprAcquireSpinLock(&pVc->lock);
NdisInterlockedIncrement((PLONG)&pAdapter->StatInfo.XmitPdusOk);
pVc->StatInfo.XmitPdusOk++;
//
// Dereference the VC's reference count.
//
// If we only have the creation reference and the VC
// is waiting to be deactivated then we are done here....
//
tbAtm155DereferenceVc(pVc);
if ((1 == pVc->References) && (VC_TEST_FLAG(pVc, fVC_DEACTIVATING)))
{
NdisDprReleaseSpinLock(&pVc->lock);
NdisDprReleaseSpinLock(&pXmitDmaQ->lock);
//
// This VC is finished.
//
TbAtm155DeactivateVcComplete(pVc->Adapter, pVc);
NdisDprAcquireSpinLock(&pXmitDmaQ->lock);
}
else
{
NdisDprReleaseSpinLock(&pVc->lock);
}
} // end of FOR
//
// Update to handled index of Tx report queue.
//
pXmitDmaQ->PrevTxReportQIndex = CurrentTxReportQIdx;
DBGPRINT(DBG_COMP_SEND_ERR, DBG_LEVEL_ERR,
("RemainingXmitSlots 0x%lx\n", pXmitDmaQ->RemainingTransmitSlots));
NdisDprReleaseSpinLock(&pXmitDmaQ->lock);
//
// Send packets out from DmaWait queues.
//
tbAtm155ProcessTransmitDmaWaitQueue(pAdapter, NULL, TRUE);
DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO,
("<==TbAtm155TxInterruptOnCompletion\n"));
}
VOID
TbAtm155SendPackets(
IN NDIS_HANDLE MiniportVcContext,
IN PPNDIS_PACKET PacketArray,
IN UINT NumberOfPackets
)
/*++
Routine Description:
This routine is the entry point to send packets on this miniport.
Arguments:
MiniportVcContext - This is the pointer to our VC_BLOCK.
PacketArray - Array of PNDIS_PACKETS to send on a given VC.
NumberOfPackets - Number of packets in the PacketArray.
Return Value:
Status is set for each packet in the PacketArray.
--*/
{
PVC_BLOCK pVc = (PVC_BLOCK)MiniportVcContext;
UINT c;
PPNDIS_PACKET CurrentPkt;
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
ULONG VcReferences;
PNDIS_PACKET pErrorPacket = NULL;
PNDIS_PACKET pNextErrorPacket = NULL;
BOOLEAN fDeactivationComplete = FALSE;
NDIS_HANDLE NdisVcHandle;
PADAPTER_BLOCK pAdapter = pVc->Adapter;
#if DBG
ULONG dbgVcFlags;
#endif // end of DBG
DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO,
("==>TbAtm155SendPackets\n"));
DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO,
("PacketArray: 0x%lx, NumberOfPackets: %ld\n", PacketArray, NumberOfPackets));
do {
NdisAcquireSpinLock(&pAdapter->lock);
//
// Set this flag to prevent handling reset while we are processing send packets.
//
ADAPTER_SET_FLAG(pAdapter, fADAPTER_PROCESSING_SENDPACKETS);
NdisReleaseSpinLock(&pAdapter->lock);
NdisAcquireSpinLock(&pVc->lock);
NdisVcHandle = pVc->NdisVcHandle;
//
// Is the adapter resetting?
//
#if DBG
dbgVcFlags = pVc->Flags;
#endif // end of DBG
if (VC_TEST_FLAG(pVc, fVC_RESET_IN_PROGRESS) ||
!VC_TEST_FLAG(pVc, (fVC_ACTIVE | fVC_TRANSMIT)) ||
ADAPTER_TEST_FLAG(pAdapter, fADAPTER_HARDWARE_FAILURE))
{
#if DBG
DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_ERR, ("pVc(%lx), Flags(%lx), dbgVcFlags(%lx)\n",
pVc->VpiVci.Vci, pVc->Flags, dbgVcFlags));
#endif // end of DBG
//
// What status should we complete the packet with?
//
#if TB_CHK4HANG
Status = NDIS_STATUS_RESET_IN_PROGRESS;
if (!VC_TEST_FLAG(pVc, (fVC_ACTIVE | fVC_TRANSMIT)))
{
Status = NDIS_STATUS_FAILURE;
}
#else
Status = VC_TEST_FLAG(pVc, fVC_RESET_IN_PROGRESS) ?
NDIS_STATUS_RESET_IN_PROGRESS : NDIS_STATUS_FAILURE;
#endif // end of TB_CHK4HANG
NdisReleaseSpinLock(&pVc->lock);
//
// Complete the packets.
//
for (c = 0, CurrentPkt = PacketArray;
(c < NumberOfPackets);
c++, CurrentPkt++)
{
NDIS_SET_PACKET_STATUS(PacketArray[c], Status);
//
// Place the packet on the error list. If pErrorPacket is NULL
// it will initialize the Tail of the Linked list.
//
PACKET_RESERVED_FROM_PACKET(*CurrentPkt)->Next = pErrorPacket;
pErrorPacket = *CurrentPkt;
}
DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_ERR,
("tbAtm155SendPackets: Failing due to invalid VC(%lx) state.\n",
pVc->VpiVci.Vci));
DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO,
("<==TbAtm155SendPackets\n"));
break;
}
//
// Reference the VC so that it doesn't go away while we are sending.
// We don't need the VC_BLOCK lock acquired for this whole routine.
//
tbAtm155ReferenceVc(pVc);
//
// Add references for all submitted packets. In case we fail one or more
// packets, we'll dereference those later.
//
// We must add these references right here, because we may encounter
// send completion interrupts before this routine finishes, and those
// can cause the VC to be dereferenced away.
//
pVc->References += NumberOfPackets;
NdisReleaseSpinLock(&pVc->lock);
//
// We reference the VC block for every packet that gets queued.
//
VcReferences = 0;
//
// Start processing the packet array.
//
for (c = 0, CurrentPkt = PacketArray;
c < NumberOfPackets;
c++, CurrentPkt++)
{
PNDIS_BUFFER Buffer;
UINT PacketLength;
UINT PhysicalBufferCount;
UINT BufferCount;
USHORT DataSize;
USHORT DataSizeMod;
UCHAR NumOfPaddingBytes;
PPACKET_RESERVED Reserved;
PMEDIA_SPECIFIC_INFORMATION pMediaInfo;
ULONG SizeMediaInfo;
PATM_AAL_OOB_INFO pAtmOob;
Reserved = PACKET_RESERVED_FROM_PACKET(*CurrentPkt);
Reserved->Next = NULL;
//
// If there is any OOB data then it had better be correct.
//
NDIS_GET_PACKET_MEDIA_SPECIFIC_INFO(*CurrentPkt, &pMediaInfo, &SizeMediaInfo);
if ((0 != SizeMediaInfo) && (NULL != pMediaInfo))
{
pAtmOob = (PATM_AAL_OOB_INFO)pMediaInfo->ClassInformation;
//
// We have media specific information.
// verify the type, size, and AAL type it is for.
//
if ((NdisClassAtmAALInfo != pMediaInfo->ClassId) ||
(sizeof(ATM_AAL_OOB_INFO) != pMediaInfo->Size) ||
(pVc->AALType != ((PATM_AAL_OOB_INFO)pMediaInfo->ClassInformation)->AalType))
{
DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_ERR,
("Packet contains OOB data that is invalid!\n"));
NDIS_SET_PACKET_STATUS(*CurrentPkt, NDIS_STATUS_FAILURE);
//
// Place the packet on the error list.
//
if (NULL != pErrorPacket)
{
Reserved->Next = pErrorPacket;
}
pErrorPacket = *CurrentPkt;
continue;
}
}
//
// Get the information that we need from the packet.
//
NdisQueryPacket(
*CurrentPkt,
&PhysicalBufferCount,
&BufferCount,
&Buffer,
&PacketLength);
//
// If this is an AAL5 transmission then we need to
// determine if any padding is needed. This must be on a
// cell granularity.
//
if (AAL_TYPE_AAL5 == pVc->AALType)
{
if (MAX_AAL5_PDU_SIZE < (ULONG)PacketLength)
{
DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_ERR,
("PacketLength is larger than SegmentSize.\n"));
NDIS_SET_PACKET_STATUS(*CurrentPkt, NDIS_STATUS_FAILURE);
//
// Place the packet on the error list.
//
if (NULL != pErrorPacket)
{
Reserved->Next = pErrorPacket;
}
pErrorPacket = *CurrentPkt;
continue;
}
//
// For AAL5, we need to calculate the padding bytes.
//
DataSize = (USHORT)PacketLength;
DataSizeMod = DataSize % CELL_PAYLOAD_SIZE;
if (DataSizeMod > 40)
{
NumOfPaddingBytes = (UCHAR)(96 - DataSizeMod);
}
else
{
NumOfPaddingBytes = (UCHAR)(48 - DataSizeMod);
}
//
// Save the padding bytes for this AAL5 packet.
//
NumOfPaddingBytes -= sizeof(AAL5_PDU_TRAILER);
DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO,
("NumOfPaddingBytes: 0x%lx, PacketLength: 0x%lx\n",
NumOfPaddingBytes, PacketLength));
//
// We also need an extra buffer for the AAL5 PDU trailer.
//
PhysicalBufferCount++;
}
else
{
//
// There is no padding byte needed for AAL5 packet.
//
NumOfPaddingBytes = 0;
}
//
// Save the amount of segmentation room, number of physical buffers,
// and the pointer to the VC_BLOCK that is need for the transmit of
// the current packet in our packet reserved section.
//
// Initialize the database of chained reserved packet.
//
Reserved->PaddingBytesNeeded = NumOfPaddingBytes;
Reserved->PhysicalBufferCount = (UCHAR)PhysicalBufferCount;
Reserved->PadTrailerBufIndexInUse = 0x0FF; // the buffer is not used.
Reserved->pVc = pVc;
//
// The packet is always pending.
//
NDIS_SET_PACKET_STATUS(*CurrentPkt, NDIS_STATUS_PENDING);
DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO,
("TbAtm155SendPacketPending: Pkt %x\n", *CurrentPkt));
//
// We are going to keep the packet so we can increment the reference
// count on the VC.
//
VcReferences++;
//
// Send the packet to the segmentation engine. This routine will
// continue sending the packet on if there are card resources
// available.
//
dbgLogSendPacket(pVc->DebugInfo, *CurrentPkt, 0, 0, ' qsp');
tbAtm155ProcessSegmentQueue(pVc->XmitSegInfo, *CurrentPkt);
}
//
// Add references to the VC_BLOCK for every packet that was queued.
//
NdisAcquireSpinLock(&pVc->lock);
//
// Fix the references to reflect the packets that we did not
// queue for sending.
//
ASSERT(VcReferences <= NumberOfPackets);
pVc->References -= (NumberOfPackets - VcReferences);
//
// Remove the reference for the send path.
//
tbAtm155DereferenceVc(pVc);
if ((1 == pVc->References) && (VC_TEST_FLAG(pVc, fVC_DEACTIVATING)))
{
//
// This VC is finished. Don't complete deactivation right now,
// but set a flag and do it below. This is so that we complete
// any errored packets before the deactivate-complete.
//
fDeactivationComplete = TRUE;
}
NdisReleaseSpinLock(&pVc->lock);
} while (FALSE);
//
// Did any packets error out?
//
while (NULL != pErrorPacket)
{
pNextErrorPacket = PACKET_RESERVED_FROM_PACKET(pErrorPacket)->Next;
NdisInterlockedIncrement((PLONG)&pVc->Adapter->StatInfo.XmitPdusError);
NdisInterlockedIncrement((PLONG)&pVc->StatInfo.XmitPdusError);
NdisMCoSendComplete(
NDIS_GET_PACKET_STATUS(pErrorPacket),
NdisVcHandle,
pErrorPacket);
DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_ERR,
("TbAtm155SendPacketError: Pkt %x\n", pErrorPacket));
pErrorPacket = pNextErrorPacket;
}
if (fDeactivationComplete)
{
TbAtm155DeactivateVcComplete(pVc->Adapter, pVc);
}
NdisAcquireSpinLock(&pAdapter->lock);
ADAPTER_CLEAR_FLAG(pAdapter, fADAPTER_PROCESSING_SENDPACKETS);
if (ADAPTER_TEST_FLAG(pAdapter, fADAPTER_RESET_REQUESTED) && !ADAPTER_TEST_FLAG(pAdapter, fADAPTER_PROCESSING_INTERRUPTS))
{
ADAPTER_SET_FLAG(pAdapter, fADAPTER_RESET_IN_PROGRESS);
ADAPTER_CLEAR_FLAG(pAdapter, fADAPTER_RESET_REQUESTED);
NdisReleaseSpinLock(&pAdapter->lock);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -