/*++ Copyright (c) 1990 Microsoft Corporation Module Name: send.c Abstract: This file contains the code for putting a packet through the staged allocation for transmission. This is a process of 1) Calculating the what would need to be done to the packet so that the packet can be transmitted on the hardware. 2) Potentially allocating adapter buffers and copying user data to those buffers so that the packet data is transmitted under the hardware constraints. 3) Allocating enough hardware ring entries so that the packet can be transmitted. 4) Relinquish thos ring entries to the hardware. The overall structure and most of the code is taken from the Lance driver by Tony Ercolano. Author: Anthony V. Ercolano (Tonye) 12-Sept-1990 Adam Barr (adamba) 16-Nov-1990 Environment: Kernel Mode - Or whatever is the equivalent. Revision History: --*/ #include #include #include #include #if DEVL #define STATIC #else #define STATIC static #endif #if DBG extern INT IbmtokDbg; extern UCHAR Packets[5][64]; extern UCHAR NextPacket; #endif #ifdef CHECK_DUP_SENDS // // CHECK_DUP_SENDS enables checking ownership of packets, to // make sure we are not given the same packet twice, or // complete the same packet twice. // #define PACKET_LIST_SIZE 50 PNDIS_PACKET IbmtokPacketList[PACKET_LIST_SIZE]; IbmtokPacketListSize = 0; IbmtokPacketsAdded = 0; IbmtokPacketsRemoved = 0; VOID IbmtokAddPacketToList( PIBMTOK_ADAPTER Adapter, PNDIS_PACKET NewPacket ) { INT i; ++IbmtokPacketsAdded; for (i=0; i Adapter->MaxTransmittablePacket)) { return(NDIS_STATUS_INVALID_PACKET); } NdisAcquireSpinLock(&Adapter->Lock); Adapter->References++; if (Adapter->Unplugged) { StatusToReturn = NDIS_STATUS_DEVICE_FAILED; } else if (!Adapter->NotAcceptingRequests) { PIBMTOK_OPEN Open; PIBMTOK_RESERVED Reserved = PIBMTOK_RESERVED_FROM_PACKET(Packet); Open = PIBMTOK_OPEN_FROM_BINDING_HANDLE(MacBindingHandle); if (!Open->BindingShuttingDown) { // // We do not have to increment the open count. Since we hold // the lock for the entire function we cannot have the open // removed out from under us. // // // NOTE NOTE NOTE !!!!!! // // There is an assumption in the code that no pointer // (which are really handles) to an ndis packet will have // its low bit set. (Always have even byte alignment.) // ASSERT(!((UINT)Packet & 1)); // // ALL packets go on the wire (loopback is done // by the card). // #ifdef CHECK_DUP_SENDS IbmtokAddPacketToList(Adapter, Packet); #endif Reserved->MacBindingHandle = MacBindingHandle; Reserved->Packet = Packet; if (Adapter->FirstTransmit == NULL) { Adapter->FirstTransmit = Packet; } else { PIBMTOK_RESERVED_FROM_PACKET(Adapter->LastTransmit)->Next = Packet; } Adapter->LastTransmit = Packet; Reserved->Next = NULL; // // Increment the reference on the open since it // will be leaving this packet around on the transmit // queues. // Open->References++; // // This will send the transmit SRB command // if the SRB is available. // IbmtokProcessSrbRequests( Adapter ); } else { StatusToReturn = NDIS_STATUS_CLOSING; } } else { if (Adapter->ResetInProgress) { StatusToReturn = NDIS_STATUS_RESET_IN_PROGRESS; } else if (Adapter->AdapterNotOpen) { StatusToReturn = NDIS_STATUS_FAILURE; } else { NdisWriteErrorLogEntry( Adapter->NdisAdapterHandle, NDIS_ERROR_CODE_DRIVER_FAILURE, 2, IBMTOK_ERRMSG_INVALID_STATE, 2 ); } } // // This macro assumes it is called with the lock held, // and releases it. // IBMTOK_DO_DEFERRED(Adapter); return StatusToReturn; }