📄 send.c
字号:
//---------------------------------------------------------------------------
//
// Copyright (C) 1996-1997. Unpublished Work of Crystal Semiconductor Corp.
// All Rights Reserved.
//
// THIS WORK IS AN UNPUBLISHED WORK AND CONTAINS CONFIDENTIAL,
// PROPRIETARY AND TRADE SECRET INFORMATION OF CRYSTAL SEMICONDUCTOR.
// ACCESS TO THIS WORK IS RESTRICTED TO (I) CRYSTAL SEMICONDUCTOR EMPLOYEES
// WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF THEIR
// ASSIGNMENTS AND (II) ENTITIES OTHER THAN CRYSTAL SEMICONDUCTOR WHO
// HAVE ENTERED INTO APPROPRIATE LICENSE AGREEMENTS. NO PART OF THIS
// WORK MAY BE USED, PRACTICED, PERFORMED, COPIED, DISTRIBUTED, REVISED,
// MODIFIED, TRANSLATED, ABRIDGED, CONDENSED, EXPANDED, COLLECTED,
// COMPILED,LINKED,RECAST, TRANSFORMED, ADAPTED IN ANY FORM OR BY ANY
// MEANS,MANUAL, MECHANICAL, CHEMICAL, ELECTRICAL, ELECTRONIC, OPTICAL,
// BIOLOGICAL, OR OTHERWISE WITHOUT THE PRIOR WRITTEN PERMISSION AND
// CONSENT OF CRYSTAL SEMICONDUCTOR . ANY USE OR EXPLOITATION OF THIS WORK
// WITHOUT THE PRIOR WRITTEN CONSENT OF CRYSTAL SEMICONDUCTOR COULD
// SUBJECT THE PERPETRATOR TO CRIMINAL AND CIVIL LIABILITY.
//
//---------------------------------------------------------------------------
#include "cs8900a.h"
#include "cshrd.h"
void PurgeTransmitQueue(PCHIP pChip);
void CopyPacketToChip( PCHIP pChip );
WORD BidForTransmit( PCHIP pChip );
/*++
Routine Description:
The CrystalSend request instructs a driver to transmit a packet through
the adapter onto the medium.
Arguments:
MiniportAdapterContext - Context registered with the wrapper, really
a pointer to the Virtual Protocol context.
Packet - A pointer to a descriptor for the packet that is to be
transmitted.
SendFlags - Optional send flags
Return Value:
The function value is the status of the operation.
--*/
extern NDIS_STATUS CrystalSend(IN NDIS_HANDLE MiniportAdapterContext,
IN PNDIS_PACKET Packet,
IN UINT SendFlags)
{
UINT PacketLength;
PTRANSMIT_QUEUE_ELEMENT TxPacket;
PCD pData;
VPM_SetupMiniContext;
pData = pChip->pData;
PRINTRETAILMSG(1, (TEXT("==>CS8900:CrystalSend\r\n")));
//
//put in VC20Send checks
//
if ((pChip->Config.DetectedMediaType == MEDIA_NONE) ||
(pChip->Config.DetectedMediaType == MEDIA_PENDING))
{
pvMini_Context->XmitErrors++;
return NDIS_STATUS_SUCCESS;
}
NdisQueryPacket( Packet,0L,0L,0L,&PacketLength);
if ( (PacketLength > CRYSTAL_INDICATE_MAXIMUM) ||
(PacketLength < CRYSTAL_MINIMUM_FRAME_SIZE))
{
pvMini_Context->XmitErrors++;
return NDIS_STATUS_SUCCESS;
}
TxPacket = (PTRANSMIT_QUEUE_ELEMENT) &Packet->MiniportReserved;
TxPacket->PacketSize = PacketLength;
ENQ_PACKET( TxPacket, pData->TransmitQueue );
if (!(pData->TransmitInProgress))
{
pData->TransmitInProgress = TRUE;
if ( BidForTransmit(pChip) == SUCCESS )
{
CopyPacketToChip(pChip);
}
} /* endif */
PRINTRETAILMSG(1, (TEXT("<==CS8900:CrystalSend\r\n")));
return NDIS_STATUS_PENDING;
}
#ifndef NDIS30_MINIPORT
extern
VOID CrystalSendPackets(
IN NDIS_HANDLE MiniportAdapterContext,
IN PPNDIS_PACKET PacketArray,
IN UINT NumberOfPackets
)
{
UINT i;
NDIS_STATUS Status;
PRINTRETAILMSG(1, (TEXT("==>CS8900:CrystalSendPackets\r\n")));
for (i=0; i<NumberOfPackets; i++, PacketArray++)
{
Status = CrystalSend( MiniportAdapterContext, *PacketArray, 0 );
NDIS_SET_PACKET_STATUS(*PacketArray, Status );
}
PRINTRETAILMSG(1, (TEXT("<==CS8900:CrystalSendPackets\r\n")));
};
#endif
void VpsSendError( PCHIP pChip, WORD Errors )
{
VPM_SetupMiniContextFromPchip;
PRINTRETAILMSG(1, (TEXT("==>CS8900:VpsSendError\r\n")));
// Keep track of OKs, Errors and confirm packet if necessary
pvMini_Context->XmitErrors++;
if (Errors & TX_ERR_EXCESS_COLL)
pvMini_Context->XmitMaxCollisions++;
if (Errors & TX_ERR_UNDERRUN)
pvMini_Context->XmitUnderrun++;
if (Errors & TX_ERR_LOSS_CRS)
pvMini_Context->XmitLostCRS++;
PRINTRETAILMSG(1, (TEXT("<==CS8900:VpsSendError\r\n")));
};
void PurgeTransmitQueue(PCHIP pChip)
{
PCD pData = pChip->pData;
PTRANSMIT_QUEUE_ELEMENT TxPacket;
PVPMINIPDATA pvMini_Context = (PVPMINIPDATA)(pChip->pPSD);
NDIS_HANDLE MiniportAdapterHandle = pvMini_Context->vpMiniportAdapterHandle;
PNDIS_PACKET Packet;
PRINTRETAILMSG(1, (TEXT("==>CS8900:PurgeTransmitQueue\r\n")));
DEQ_PACKET(&TxPacket, pData->TransmitQueue);
while(TxPacket != NULL)
{
pvMini_Context->XmitOKs++;
Packet = CONTAINING_RECORD(TxPacket,NDIS_PACKET,MiniportReserved);
NdisMSendComplete(MiniportAdapterHandle,
Packet,
NDIS_STATUS_SUCCESS
);
DEQ_PACKET(&TxPacket, pData->TransmitQueue)
} /* endfor */
PRINTRETAILMSG(1, (TEXT("<==CS8900:PurgeTransmitQueue\r\n")));
};
void CopyPacketToChip( PCHIP pChip )
{
PCD pData = pChip->pData;
//
// Holds the virtual address of the current buffer.
//
PVOID VirtualAddress;
//
// Holds the length of the current buffer of the packet.
//
DWORD CurrentLength;
//
// Holds the length of the Packet.
//
DWORD BytesToCopy;
//
// Keep a local variable of BytesCopied so we aren't referencing
// through a pointer.
//
DWORD LocalBytesCopied = 0;
//
// First packet to be processed.
//
PTRANSMIT_QUEUE_ELEMENT TxPacket;
//
// This flag indicates that an odd byte is to be transferred in the previous
// fragment which is to be transferred with a byte from next fragment
//
WORD OddWordFlag = FALSE;
//
// The variable to store the odd byte to be transferred with the next
// fragment.
//
WORD OddWordValue = 0;
WORD i;
PNDIS_BUFFER pNDISBuffer;
PNDIS_PACKET Packet;
/* "&wAligned1" is aligned to a 16 bit boundary address. */
WORD wAligned1;
PRINTRETAILMSG(1, (TEXT("==>CS8900:CopyPacketToChip\r\n")));
TxPacket = pData->TransmitQueue.Head;
if (TxPacket == NULL)
{
PRINTRETAILMSG(1, (TEXT("<==CS8900:CopyPacketToChip 111\r\n")));
return;
}
BytesToCopy = TxPacket->PacketSize;
Packet = CONTAINING_RECORD(TxPacket,NDIS_PACKET,MiniportReserved);
NdisQueryPacket( Packet,0L,0L,&pNDISBuffer,0L);
NdisQueryBuffer(pNDISBuffer,&VirtualAddress,&CurrentLength);
while (LocalBytesCopied < BytesToCopy)
{
while (!CurrentLength)
{
NdisGetNextBuffer(pNDISBuffer,&pNDISBuffer);
NdisQueryBuffer(pNDISBuffer,&VirtualAddress,&CurrentLength);
}
#if 0
{
BYTE *buf = (BYTE *)VirtualAddress;
RETAILMSG(1, (TEXT("Send length = %d: "), CurrentLength));
for(i = 0; i < CurrentLength; i++)
RETAILMSG(1, (TEXT("%02x-"), buf[i]));
RETAILMSG(1, (TEXT("\r\n")));
}
#endif
LocalBytesCopied += CurrentLength;
//
// Copy the data.
//
//
// Decrement the fragment length left to be transmitted as a byte
// from this fragment was transmitted with a byte left to be
// transmitted from previous fragment.
//
if(OddWordFlag)
{
OddWordValue |= ((USHORT)(*(PUCHAR)VirtualAddress)) << 8;
v_pCS8900Regs->DATA0 = OddWordValue;
CurrentLength--;
OddWordFlag = FALSE;
OddWordValue=0;
((PUCHAR)VirtualAddress)++;
}
/* ARM can read/write only 16 bit data at a time under WinCE.
NdisRawWritePortUlong() does NOT work for ARM.*/
if ( (ULONG)VirtualAddress & 0x1 != 0)
{
for (i=0; i < CurrentLength/2; i++)
{
/* for ARM 16 bit data-write alignment*/
/* VirtualAddress may not point to a 16 bit boundary address. Use
memcpy() to move data from unaligned memory to aligned memory.
It works since memcpy() casts pointers it copies to char* */
//memcpy(&wAligned1, (WORD*)VirtualAddress, sizeof(WORD));
wAligned1 = ((BYTE *)VirtualAddress)[1];
wAligned1 = wAligned1 << 8 | ((BYTE *)VirtualAddress)[0];
v_pCS8900Regs->DATA0 = wAligned1;
++((WORD*)VirtualAddress);
} /* end for */
} /* end if */
else
{
for (i=0; i < CurrentLength/2; i++)
v_pCS8900Regs->DATA0 = *((PWORD)VirtualAddress)++;
} /* end else */
if ( CurrentLength % 2 == 1 )
{
//
// Store the byte from the current fragment to be transmitted
// with the next fragment and set the odd_bytes flag.
//
OddWordValue = *((PUCHAR)VirtualAddress);
OddWordFlag = TRUE;
}
CurrentLength = 0;
} // end of while loop.
if(OddWordFlag)
v_pCS8900Regs->DATA0 = OddWordValue;
PRINTRETAILMSG(1, (TEXT("<==CS8900:CopyPacketToChip\r\n")));
};
WORD BidForTransmit( PCHIP pChip )
{
WORD Data;
PCD pData = pChip->pData;
PRINTRETAILMSG(1, (TEXT("==>CS8900: BidForTransmit \r\n")));
pData->TransmitStarted = TRUE;
v_pCS8900Regs->TXCMD = pData->TransmitCommand;
v_pCS8900Regs->TXLENGTH = pData->TransmitQueue.Head->PacketSize;
//
// Now, check whether the chip is ready to transmit by checking the
// Ready for transmit bit of the BusStatusRegister.
//
Data = ReadPacketPage(CRYSTAL_BUS_STATUS_REGISTER);
if(Data & CRYSTAL_BSR_TX_BID_ERROR)
{
pData->StartTX = TRUE; // Better start another TX at end of next interrupt
// Assumes Receives are cause of bid failure
PRINTRETAILMSG(1, (TEXT("<==CS8900: BidForTransmit FAILURE 1\r\n")));
return FAILURE;
}
if(Data & CRYSTAL_BSR_READY_FOR_TRANSMIT_NOW)
{
PRINTRETAILMSG(1, (TEXT("<==CS8900: BidForTransmit SUCCESS\r\n")));
return SUCCESS;
}
else
pData->TransmitBidPending = TRUE;
PRINTRETAILMSG(1, (TEXT("<==CS8900: BidForTransmit FAILURE 2\r\n")));
return FAILURE;
};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -