⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 send.c

📁 PXA255/270平台的 CS8900网卡驱动程序
💻 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 + -