summaryrefslogblamecommitdiffstats
path: root/private/ntos/ndis/ubnei/send.c
blob: ecadbca4dae748c85a812df4ee1a59f0ab0b53b3 (plain) (tree)
















































































































































































































































































































































































                                                                                                       
/*++

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;
}