/*************************************************************************** Routine Description: The R6040Send 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 adapter. Packet - A pointer to a descriptor for the packet that is to be transmitted. SendFlags - Optional send flags Notes: This miniport driver will always accept a send. This is because the R6040 has limited send resources and the driver needs packets to copy to the adapter immediately after a transmit completes in order to keep the adapter as busy as possible. This is not required for other adapters, as they have enough resources to keep the transmitter busy until the wrapper submits the next packet. *****************************************************************************/ NDIS_STATUS R6040Send( IN NDIS_HANDLE MiniportAdapterContext, IN PNDIS_PACKET Packet, IN UINT Flags) { PR6040_ADAPTER Adapter = (PR6040_ADAPTER)(MiniportAdapterContext); NdisAcquireSpinLock(&Adapter->SendLock); //RETAILMSG(R6040DBG, (TEXT("<"))); // Put the packet on the send queue. if (Adapter->FirstPacket == NULL) { Adapter->FirstPacket = Packet; } else { RESERVED(Adapter->LastPacket)->Next = Packet; } RESERVED(Packet)->Next = NULL; Adapter->LastPacket = Packet; // Process the next send R6040DoNextSend(Adapter); //RETAILMSG(R6040DBG, (TEXT(">\r\n"))); NdisReleaseSpinLock(&Adapter->SendLock); return(NDIS_STATUS_PENDING); }
/******************************************************************************* ** ** Function userial_set_port ** ** Description Configure UART port name ** ** Returns 0 : Success ** Otherwise : Fail ** *******************************************************************************/ int userial_set_port(char *p_conf_name, char *p_conf_value, int param) { RESERVED(p_conf_name); RESERVED(param); strlcpy(vnd_userial.port_name, p_conf_value, VND_PORT_NAME_MAXLEN); return 0; }
NTSTATUS PacketRead( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) { POPEN_INSTANCE open; PNDIS_PACKET pPacket; NDIS_STATUS status; NTSTATUS ntStatus; PIO_STACK_LOCATION irpSp; // DebugPrint(("Read\n")); open = DeviceObject->DeviceExtension; IoIncrement(open); if(!open->Bound) { ntStatus = STATUS_DEVICE_NOT_READY; goto ERROR; } irpSp = IoGetCurrentIrpStackLocation(Irp); if (irpSp->Parameters.Read.Length < ETHERNET_HEADER_LENGTH) { ntStatus = STATUS_BUFFER_TOO_SMALL; goto ERROR; } NdisAllocatePacket( &status, &pPacket, open->PacketPool ); if (status != NDIS_STATUS_SUCCESS) { // DebugPrint(("Packet: Read- No free packets\n")); ntStatus = STATUS_INSUFFICIENT_RESOURCES; goto ERROR; } RESERVED(pPacket)->Irp=Irp; RESERVED(pPacket)->pMdl=NULL; IoMarkIrpPending(Irp); IoSetCancelRoutine(Irp, PacketCancelRoutine); ExInterlockedInsertTailList( &open->RcvList, &RESERVED(pPacket)->ListElement, &open->RcvQSpinLock); return STATUS_PENDING; ERROR: Irp->IoStatus.Status = ntStatus; IoCompleteRequest (Irp, IO_NO_INCREMENT); IoDecrement(open); return ntStatus; }
PNDIS_PACKET PacketCopy( IN PNDIS_PACKET Packet, OUT PLONG CloneCount ) { if (CloneCount) *CloneCount = InterlockedIncrement( &(RESERVED(Packet)->Cloned) ); else InterlockedIncrement( &(RESERVED(Packet)->Cloned) ); return Packet; }
DWORD PacketRead(POPEN_INSTANCE Open, DWORD dwDDB, DWORD hDevice, PDIOCPARAMETERS pDiocParms) { // read a packet NDIS_STATUS Status; PNDIS_PACKET pPacket; // Check that the buffer can hold a max length Ethernet packet if (pDiocParms->cbOutBuffer < ETHERNET_PACKET_LENGTH) { *(DWORD *)(pDiocParms->lpcbBytesReturned) = 0; // Need bigger buffer return NDIS_STATUS_SUCCESS; } PacketAllocatePacketBuffer(&Status, Open, &pPacket, pDiocParms, IOCTL_EPACKET_READ); if (Status == NDIS_STATUS_SUCCESS) { // Put this packet in a list of pending reads. // The receive indication handler will attempt to remove packets // from this list for use in transfer data calls NdisAcquireSpinLock(&Open->RcvQSpinLock); // fixed 6.11.97 InsertTailList(&Open->RcvList, &RESERVED(pPacket)->ListElement); NdisReleaseSpinLock(&Open->RcvQSpinLock); } return -1; // This will make DeviceIOControl return ERROR_IO_PENDING }
VOID ProtocolSendComplete( IN NDIS_HANDLE ProtocolBindingContext, IN PNDIS_PACKET pPacket, IN NDIS_STATUS Status ) { OPEN_INSTANCE *pOpen = (OPEN_INSTANCE *)ProtocolBindingContext; PIRP pIrp = RESERVED(pPacket)->pIrp; PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation(pIrp); // 释放封包 NdisFreePacket(pPacket); // 完成IRP请求 if(Status == NDIS_STATUS_SUCCESS) { pIrp->IoStatus.Information = pIrpSp->Parameters.Write.Length; pIrp->IoStatus.Status = STATUS_SUCCESS; DbgPrint(" ProtoDrv: Send data success \n"); } else { pIrp->IoStatus.Information = 0; pIrp->IoStatus.Status = STATUS_UNSUCCESSFUL; } IoCompleteRequest(pIrp, IO_NO_INCREMENT); IoDecrement(pOpen); }
NTSTATUS PacketCancelReadIrps( IN PDEVICE_OBJECT DeviceObject ) { POPEN_INSTANCE open = DeviceObject->DeviceExtension; PLIST_ENTRY thisEntry; PIRP pendingIrp; PNDIS_PACKET myPacket = NULL; PPACKET_RESERVED reserved; PMDL mdl; // DebugPrint(("PacketCancelReadIrps\n")); // Walk through the RcvList and cancel all read IRPs. while( thisEntry = ExInterlockedRemoveHeadList( &open->RcvList, &open->RcvQSpinLock )) { reserved=CONTAINING_RECORD(thisEntry,PACKET_RESERVED,ListElement); myPacket=CONTAINING_RECORD(reserved,NDIS_PACKET,ProtocolReserved); ASSERT(myPacket); pendingIrp = RESERVED(myPacket)->Irp; NdisFreePacket(myPacket); // DebugPrint(("Cancelled : 0%0x\n", pendingIrp)); IoSetCancelRoutine(pendingIrp, NULL); pendingIrp->IoStatus.Information = 0; pendingIrp->IoStatus.Status = STATUS_CANCELLED; IoCompleteRequest(pendingIrp, IO_NO_INCREMENT); IoDecrement(open); } return STATUS_SUCCESS; }
__inline LpxCopyEthLpxHeadersToLpxReserved( PNDIS_PACKET Packet, PVOID EthHeader, USHORT EthType, PVOID LpxHeader, UINT LpxHeaderSize ){ RtlCopyMemory( &RESERVED(Packet)->EthernetHeader, EthHeader, ETHERNET_HEADER_LENGTH ); // Override ether type in case of LLC SNAP RESERVED(Packet)->EthernetHeader.Type = EthType; RtlCopyMemory( &RESERVED(Packet)->LpxHeader, LpxHeader, LpxHeaderSize ); RESERVED(Packet)->HeaderCopied = TRUE; }
PNDIS_PACKET PacketClone( IN PNDIS_PACKET Packet ) { InterlockedIncrement(&(RESERVED(Packet)->Cloned)); InterlockedIncrement(&NumberOfCloned); return Packet; }
NDIS_STATUS NDIS_API PacketReceiveIndicate(IN NDIS_HANDLE ProtocolBindingContext, IN NDIS_HANDLE MacReceiveContext, IN PVOID HeaderBuffer, IN UINT HeaderBufferSize, IN PVOID LookaheadBuffer, IN UINT LookaheadBufferSize, IN UINT PacketSize) { // upcall on packet arrival POPEN_INSTANCE Open; PLIST_ENTRY PacketListEntry; PNDIS_PACKET pPacket; NDIS_STATUS Status; UINT BytesTransfered = 0; PPACKET_RESERVED pReserved; if (HeaderBufferSize != ETHERNET_HEADER_LENGTH) return NDIS_STATUS_NOT_ACCEPTED; Open = (POPEN_INSTANCE) ProtocolBindingContext; // See if there are any pending reads that we can satisfy NdisAcquireSpinLock(&Open->RcvQSpinLock); // fixed 5.11.97 if (IsListEmpty(&Open->RcvList)) { NdisReleaseSpinLock(&Open->RcvQSpinLock); return NDIS_STATUS_NOT_ACCEPTED; } PacketListEntry = RemoveHeadList(&Open->RcvList); NdisReleaseSpinLock(&Open->RcvQSpinLock); pReserved = CONTAINING_RECORD(PacketListEntry, PACKET_RESERVED, ListElement); pPacket = CONTAINING_RECORD(pReserved, NDIS_PACKET, ProtocolReserved); // Copy the MAC header NdisMoveMemory(RESERVED(pPacket)->lpBuffer, HeaderBuffer, HeaderBufferSize); // Call the Mac to transfer the data portion of the packet NdisTransferData(&Status, Open->AdapterHandle, MacReceiveContext, 0, PacketSize, pPacket, &BytesTransfered); if (Status == NDIS_STATUS_PENDING) return NDIS_STATUS_PENDING; if (Status == NDIS_STATUS_SUCCESS) { PacketTransferDataComplete(Open, pPacket, Status, BytesTransfered); return NDIS_STATUS_SUCCESS; } PacketTransferDataComplete(Open, pPacket, Status, 0); return NDIS_STATUS_SUCCESS; }
NTSTATUS DispatchWrite(PDEVICE_OBJECT pDevObj, PIRP pIrp) { NTSTATUS status; // 取得描述适配器的OPEN_INSTANCE结构的指针 OPEN_INSTANCE *pOpen = (OPEN_INSTANCE *)pDevObj->DeviceExtension; // 增加IO引用计数 IoIncrement(pOpen); do { if(!pOpen->bBound) { status = STATUS_DEVICE_NOT_READY; break; } // 从封包池中申请一个封包 PNDIS_PACKET pPacket; NdisAllocatePacket((NDIS_STATUS*)&status, &pPacket, pOpen->hPacketPool); if(status != NDIS_STATUS_SUCCESS) // 封包被申请完了! { status = STATUS_INSUFFICIENT_RESOURCES; break; } RESERVED(pPacket)->pIrp = pIrp; // 保存IRP指针,在完成例程中还要使用 // 附加写缓冲区到封包 NdisChainBufferAtFront(pPacket, pIrp->MdlAddress); // 注意,既然我们已经标识此IRP未决,我们必须返回STATUS_PENDING,即便是 // 我们恰巧同步完成了这个IRP IoMarkIrpPending(pIrp); // 发送封包到下层NIC设备 NdisSend((NDIS_STATUS*)&status, pOpen->hAdapter, pPacket); if(status != NDIS_STATUS_PENDING) { ProtocolSendComplete(pOpen, pPacket, status); } return STATUS_PENDING; }while(FALSE); if(status != STATUS_SUCCESS) { IoDecrement(pOpen); pIrp->IoStatus.Information = 0; pIrp->IoStatus.Status = status; IoCompleteRequest(pIrp, IO_NO_INCREMENT); } return status; }
PNDIS_PACKET PacketCopy( IN PNDIS_PACKET Packet, OUT PLONG Cloned ) { ASSERT(Cloned) ; *Cloned = InterlockedIncrement(&(RESERVED(Packet)->Cloned)); InterlockedIncrement(&NumberOfCloned); return Packet; }
VOID PacketTransferDataComplete ( IN NDIS_HANDLE ProtocolBindingContext, IN PNDIS_PACKET pPacket, IN NDIS_STATUS Status, IN UINT BytesTransfered ) { PIO_STACK_LOCATION irpSp; POPEN_INSTANCE open; PIRP irp; PMDL pMdl; // DebugPrint(("Packet: TransferDataComplete\n")); open = (POPEN_INSTANCE)ProtocolBindingContext; irp = RESERVED(pPacket)->Irp; irpSp = IoGetCurrentIrpStackLocation(irp); pMdl = RESERVED(pPacket)->pMdl; if(pMdl) IoFreeMdl(pMdl); NdisFreePacket(pPacket); if(Status == NDIS_STATUS_SUCCESS) { irp->IoStatus.Status = STATUS_SUCCESS; irp->IoStatus.Information = BytesTransfered+ETHERNET_HEADER_LENGTH; } else { irp->IoStatus.Status = STATUS_UNSUCCESSFUL; irp->IoStatus.Information = 0; } // DebugPrint(("BytesTransfered:%d\n", irp->IoStatus.Information)); IoCompleteRequest(irp, IO_NO_INCREMENT); IoDecrement(open); }
static void reserved_c () { RESERVED(__inline__); RESERVED(__inline); RESERVED(inline); RESERVED(do); RESERVED(struct); RESERVED(case); RESERVED(for); RESERVED(short); RESERVED(union); RESERVED(sizeof); RESERVED(register); RESERVED(break); RESERVED(auto); RESERVED(continue); RESERVED(const); RESERVED(default); RESERVED(enum); RESERVED(else); RESERVED(extern); RESERVED(goto); RESERVED(if); RESERVED(long); RESERVED(return); RESERVED(signed); RESERVED(static); RESERVED(switch); RESERVED(typedef); RESERVED(unsigned); RESERVED(volatile); RESERVED(while); RESERVED(__asm__); #ifdef GNU_VIOLATIONS RESERVED(__typeof__); RESERVED(__label__); RESERVED(_Complex); #endif RESERVED(void); RESERVED(int); RESERVED(char); RESERVED(float); RESERVED(double); }
INT PacketReceivePacket( IN NDIS_HANDLE ProtocolBindingContext, IN PNDIS_PACKET Packet ) { UINT bytesTransfered = 0; POPEN_INSTANCE open; PIRP irp; PNDIS_PACKET myPacket; PLIST_ENTRY packetListEntry; ULONG bufferLength; PPACKET_RESERVED reserved; PIO_STACK_LOCATION irpSp; PMDL mdl; PVOID startAddress; NTSTATUS status; // DebugPrint(("PacketReceivePacket\n")); open = (POPEN_INSTANCE)ProtocolBindingContext; packetListEntry = ExInterlockedRemoveHeadList( &open->RcvList, &open->RcvQSpinLock ); if (packetListEntry == NULL) { // DebugPrint(("No pending read, dropping packets\n")); return 0; } reserved = CONTAINING_RECORD(packetListEntry,PACKET_RESERVED,ListElement); myPacket = CONTAINING_RECORD(reserved,NDIS_PACKET,ProtocolReserved); irp = RESERVED(myPacket)->Irp; irpSp = IoGetCurrentIrpStackLocation(irp); // We don't have to worry about the situation where the IRP is cancelled // after we remove it from the queue and before we reset the cancel // routine because the cancel routine has been coded to cancel an IRP // only if it's in the queue. IoSetCancelRoutine(irp, NULL); // Following block of code locks the destination packet // MDLs in a safe manner. This is a temporary workaround // for NdisCopyFromPacketToPacket that currently doesn't use // safe functions to lock pages of MDL. This is required to // prevent system from bugchecking under low memory resources. // { PVOID virtualAddress; PNDIS_BUFFER firstBuffer, nextBuffer; ULONG totalLength; NdisQueryPacket(Packet, NULL, NULL, &firstBuffer, &totalLength); while( firstBuffer ) { NdisQueryBufferSafe( firstBuffer, &virtualAddress, &totalLength, NormalPagePriority ); if(!virtualAddress) { status = STATUS_INSUFFICIENT_RESOURCES; goto CleanExit; } NdisGetNextBuffer(firstBuffer, &nextBuffer); firstBuffer = nextBuffer; } } NdisChainBufferAtFront( myPacket, irp->MdlAddress ); bufferLength=irpSp->Parameters.Read.Length; NdisCopyFromPacketToPacket( myPacket, 0, bufferLength, Packet, 0, &bytesTransfered ); CleanExit: NdisFreePacket(myPacket); irp->IoStatus.Status = status; irp->IoStatus.Information = bytesTransfered; IoCompleteRequest(irp, IO_NO_INCREMENT); // DebugPrint(("BytesTransfered:%d\n", bytesTransfered)); IoDecrement(open); return 0; }
/** * Called when a pagefault occurs, is in charge of fixing the fault and swapping * if necessary. */ void cPageFault(isrVal_t registers) { addr_t page = getCR2(); addr_t page_addr = page & ~(0xFFF); #ifdef PAGEDBG printf("PG!\n"); printf("Fault addr: %X\nPage index: %X\n", page, page_addr); printf("Fault type: %X\n", registers.errCode); printf("EIP: %X\nESP: %X\nESP: %X\n", registers.eip, registers.procesp, registers.esp); printf("eax: %X\tebx: %X\necx: %X\tedx: %X\n", registers.eax, registers.ebx, registers.ecx, registers.edx); #endif if (registers.cs != 0x8 && registers.cs != 0x18) panic("Incorrect frame!"); if (USER(registers.errCode)) panic("Userspace isn't implemented yet!"); if (RESERVED(registers.errCode)) panic("A reserved bit has been set!\n"); if (PRESENT(registers.errCode)) panic("Illegal operation!"); addr_t pd = getPageDir(); /** * The data bit only works if a specific bit is set. See intel docs volume 3 * for more information. */ if (DATA(registers.errCode)) { #ifdef PAGEDBG printf("Trying to access unimplemented data!\n"); #endif if (WRITE(registers.errCode)) { #ifdef PAGEDBG printf("Faulted a write attempt!\n"); printf("Adding page!\n"); #endif if (USER(registers.errCode)) { //Add a user page! } else { #ifdef PAGEDBG printf("Adding a kernel page!\n"); #endif if (idx_kernel_space == MAP_NOMAP) panic("Kernel page map not correctly initialised!"); int ret = page_alloc_page (idx_kernel_space, page_addr, (void*)pd, FALSE); if (ret != -E_SUCCESS) { printf("ERRCODE: %X\n", -ret); panic("Couldn't alloc page!"); } #ifdef PAGEDBG printf("Phys of %X = %X\n", page, page_phys_addr(page, (void*)pd)); #endif } } else { #ifdef PAGEDBG printf("Faulted a read attempt!\n"); #endif // Assume the page may be read! if (idx_kernel_space == MAP_NOMAP) panic("Kernel page map not correctly initialised!"); int ret = page_alloc_page(idx_kernel_space, page_addr, (void*)pd, FALSE); if (ret != -E_SUCCESS) { printf("ERRCODE: %X\n", -ret); panic("Couldn't alloc page!"); } #ifdef PAGEDBG printf("Phys of %X = %X\n", page, page_phys_addr(page, (void*)pd)); #endif } } else { #ifdef PAGEDBG panic("Trying to run unimplemented code!\n"); #endif } #ifdef UNDEFINED printf("Page faults currently under construction!\n"); #endif }
NTSTATUS PacketAllocate( IN PSERVICE_POINT ServicePoint, IN ULONG PacketLength, IN PDEVICE_CONTEXT DeviceContext, IN UCHAR Type, IN PUCHAR CopyData, IN ULONG CopyDataLength, IN PIO_STACK_LOCATION IrpSp, OUT PNDIS_PACKET *Packet ) { NTSTATUS status; PUCHAR packetData; PNDIS_BUFFER pNdisBuffer; PNDIS_BUFFER pNdisBufferData; PNDIS_PACKET packet; USHORT port; DebugPrint(3, ("PacketAllocate, PacketLength = %d, Numberofpackets = %d\n", PacketLength, NumberOfPackets)); // if(ServicePoint && ServicePoint->SmpState == SMP_SYN_RECV) // return STATUS_INSUFFICIENT_RESOURCES; if(DeviceContext == NULL) { DebugPrint(1, ("[LPX]PacketAllocate: DeviceContext is NULL!!!\n")); return STATUS_INVALID_PARAMETER; } if(DeviceContext->LpxPacketPool == NULL) { DebugPrint(1, ("[LPX]PacketAllocate: DeviceContext->LpxPacketPool is NULL!!!\n")); return STATUS_INVALID_PARAMETER; } NdisAllocatePacket(&status, &packet, DeviceContext->LpxPacketPool); if(status != NDIS_STATUS_SUCCESS) { DebugPrint(1, ("[LPX]PacketAllocate: NdisAllocatePacket Failed!!!\n")); return STATUS_INSUFFICIENT_RESOURCES; } status = NdisAllocateMemory( &packetData, PacketLength ); if(status != NDIS_STATUS_SUCCESS) { DebugPrint(1, ("[LpxSmp]PacketAllocate: Can't Allocate Memory packet.\n")); NdisFreePacket(packet); *Packet = NULL; return status; } NdisAllocateBuffer( &status, &pNdisBuffer, DeviceContext->LpxBufferPool, packetData, PacketLength ); if(!NT_SUCCESS(status)) { NdisFreePacket(packet); *Packet = NULL; NdisFreeMemory(packetData); DebugPrint(1, ("[LPX]PacketAllocate: Can't Allocate Buffer!!!\n")); return status; } switch(Type) { case SEND_TYPE: if(ServicePoint && &ServicePoint->SmpContext) { RtlCopyMemory(&packetData[0], ServicePoint->DestinationAddress.Node, ETHERNET_ADDRESS_LENGTH ); RtlCopyMemory(&packetData[ETHERNET_ADDRESS_LENGTH], ServicePoint->SourceAddress.Node, ETHERNET_ADDRESS_LENGTH ); port = HTONS(ETH_P_LPX); RtlCopyMemory(&packetData[ETHERNET_ADDRESS_LENGTH*2], &port, //&ServicePoint->DestinationAddress.Port, 2 ); } if(CopyDataLength) { NdisAllocateBuffer( &status, &pNdisBufferData, DeviceContext->LpxBufferPool, CopyData, CopyDataLength ); if(!NT_SUCCESS(status)) { NdisFreePacket(packet); *Packet = NULL; NdisFreeMemory(packetData); DebugPrint(1, ("[LPX]PacketAllocate: Can't Allocate Buffer For CopyData!!!\n")); return status; } NdisChainBufferAtFront(packet, pNdisBufferData); } break; case RECEIVE_TYPE: NdisMoveMappedMemory( packetData, CopyData, CopyDataLength ); break; } // RESERVED(packet)->ServicePoint = ServicePoint; RESERVED(packet)->Cloned = 0; RESERVED(packet)->IrpSp = IrpSp; RESERVED(packet)->Type = Type; RESERVED(packet)->LpxSmpHeader = NULL; if(IrpSp == NULL) { DebugPrint(2, ("[LPX] PacketAllocate: No IrpSp\n")) ; } NdisChainBufferAtFront(packet, pNdisBuffer); InterlockedIncrement(&NumberOfPackets); *Packet = packet; return STATUS_SUCCESS; }
VOID PacketFree( IN PNDIS_PACKET Packet ) { PLPX_RESERVED reserved = RESERVED(Packet); PUCHAR packetData; PNDIS_BUFFER pNdisBuffer; UINT uiLength; LONG clone ; DebugPrint(3, ("PacketFree reserved->type = %d\n", reserved->Type)); switch(reserved->Type) { case SEND_TYPE: clone = InterlockedDecrement(&reserved->Cloned); if(clone >= 0) { return; } pNdisBuffer = NULL; NdisUnchainBufferAtFront(Packet, &pNdisBuffer); if(pNdisBuffer) { NdisQueryBufferSafe( pNdisBuffer, &packetData, &uiLength, HighPagePriority ); NdisFreeMemory(packetData); NdisFreeBuffer(pNdisBuffer); } pNdisBuffer = NULL; NdisUnchainBufferAtFront(Packet, &pNdisBuffer); while(pNdisBuffer) { NdisFreeBuffer(pNdisBuffer); pNdisBuffer = NULL; NdisUnchainBufferAtFront(Packet, &pNdisBuffer); } if(reserved->IrpSp != NULL) { LpxDereferenceSendIrp(reserved->IrpSp); } else { DebugPrint(2, ("[LPX] PacketFree: No IrpSp\n")) ; } break; case RECEIVE_TYPE: if(reserved->LpxSmpHeader) //ExFreePool(reserved->LpxSmpHeader); NdisFreeMemory(reserved->LpxSmpHeader); pNdisBuffer = NULL; NdisUnchainBufferAtFront(Packet, &pNdisBuffer); if(pNdisBuffer) { NdisQueryBufferSafe( pNdisBuffer, &packetData, &uiLength, HighPagePriority ); NdisFreeMemory(packetData); NdisFreeBuffer(pNdisBuffer); } reserved->PacketDataOffset = 0; break; } NdisFreePacket(Packet); InterlockedDecrement(&NumberOfPackets); DebugPrint(2, ("Packet REALLY Freed Numberofpackets = %d\n", NumberOfPackets)); }
INT LpxProtocolReceivePacket( IN NDIS_HANDLE ProtocolBindingContext, IN PNDIS_PACKET Packet ){ PDEVICE_CONTEXT deviceContext; PNDIS_BUFFER ndisFirstBuffer; PVOID firstBuffer; UINT firstBufferSize; UINT totalBufferSize; USHORT protocol; PNDIS_PACKET packet = NULL; NDIS_STATUS status; INT pktReferenceCount = 0; UINT addiLlcHeaderSize = 0; PLPX_HEADER lpxHeader; USHORT lpxHeaderSize; UINT lpxPayload; UINT rawDataOffset; DebugPrint( 4, ("ProtocolReceivePacket: Entered\n") ); deviceContext = (PDEVICE_CONTEXT)ProtocolBindingContext; // // Check to see if the device context is initialized. // ASSERT( deviceContext->NdisBindingHandle ); if (!FlagOn(deviceContext->LpxFlags, LPX_DEVICE_CONTEXT_START) || FlagOn(deviceContext->LpxFlags, LPX_DEVICE_CONTEXT_STOP)) { DebugPrint( 4,("Device is not initialized. Drop packet\n") ); return 0; } // // validation // NdisGetFirstBufferFromPacket( Packet, &ndisFirstBuffer, &firstBuffer, &firstBufferSize, &totalBufferSize); if (firstBufferSize < ETHERNET_HEADER_LENGTH) { DebugPrint( 1, ("ProtocolReceivePacket: FirstBufferSize = %x\n", firstBufferSize) ); return 0; } protocol = ((PETHERNET_HEADER)firstBuffer)->Type; // // Discard 802.2 LLC SNAP field. // // if Ether Type less than 0x0600 ( 1536 ) // if (NTOHS(protocol) < 0x0600 && NTOHS(protocol) != 0x0060 && // LOOP: Ethernet Loopback NTOHS(protocol) != 0x0200 && // PUP : Xerox PUP packet NTOHS(protocol) != 0x0201) { // PUPAP: Xerox PUP address trans packet protocol = *(PUSHORT)((PUCHAR)firstBuffer + ETHERNET_HEADER_LENGTH + LENGTH_8022LLCSNAP - 2); if(firstBufferSize >= LENGTH_8022LLCSNAP) firstBufferSize -= LENGTH_8022LLCSNAP; else { DebugPrint( 1, ("ProtocolReceivePacket: Too small first buffer\n") ); return 0; } if(totalBufferSize >= LENGTH_8022LLCSNAP) totalBufferSize -= LENGTH_8022LLCSNAP; else { DebugPrint( 1, ("ProtocolReceivePacket: Too small total buffer\n") ); return 0; } addiLlcHeaderSize = LENGTH_8022LLCSNAP; } if (protocol != HTONS(ETH_P_LPX)) { DebugPrint( 4, ("ProtocolReceivePacket: Type = %x\n", protocol) ); return 0; } if(totalBufferSize < ETHERNET_HEADER_LENGTH + addiLlcHeaderSize + sizeof(LPX_HEADER)) { DebugPrint( 1, ("ProtocolReceivePacket: too small packet(1).\n")); return 0; } // // Extract LPX header information // // lpxHeader = (PLPX_HEADER)((PBYTE)firstBuffer + ETHERNET_HEADER_LENGTH + addiLlcHeaderSize); lpxHeaderSize = sizeof(LPX_HEADER); lpxPayload = NTOHS(lpxHeader->PacketSize & ~LPX_TYPE_MASK) - lpxHeaderSize; #if __LPX_OPTION_ADDRESSS__ if (FlagOn(lpxHeader->Option, LPX_OPTION_SOURCE_ADDRESS)) { lpxHeaderSize += ETHERNET_ADDRESS_LENGTH; } if (FlagOn(lpxHeader->Option, LPX_OPTION_DESTINATION_ADDRESS)) { lpxHeaderSize += ETHERNET_ADDRESS_LENGTH; } #endif if(totalBufferSize < ETHERNET_HEADER_LENGTH + addiLlcHeaderSize + lpxHeaderSize + lpxPayload) { DebugPrint( 1, ("ProtocolReceivePacket: too small packet(2).\n")); return 0; } // // DROP PACKET for DEBUGGING!!!! // #if 1 //DBG // Enabled for testing if (PacketRxDropRate) { PacketRxCountForDrop++; if ((PacketRxCountForDrop % 1000) <= PacketRxDropRate) { PLPX_HEADER lpxHeader = (PLPX_HEADER)((PUCHAR)firstBuffer + addiLlcHeaderSize); #if 0 if ((PacketRxCountForDrop % (PacketRxDropRate*20)) == 0) DebugPrint( 1, ("[Drop(%x,%x,%x))]\n", NTOHS(lpxHeader->Lsctl), NTOHS(lpxHeader->Sequence), NTOHS(lpxHeader->AckSequence)) ); #endif DebugPrint( 1, ("D\n") ); return 0; } } #endif ASSERT( addiLlcHeaderSize == 0 ); DebugPrint( 4, ("ProtocolReceivePacket: TotalBuffSz = %d, FirstBuffSz = %d, LPX_HEADER size = %d\n", totalBufferSize, firstBufferSize, sizeof(LPX_HEADER)) ); // // If the miniport is out of resources, we can't queue // this packet - make a copy if this is so. // if (NDIS_GET_PACKET_STATUS(Packet) == NDIS_STATUS_RESOURCES) { UINT bytesCopied; DebugPrint( 1, ("ProtocolReceivePacket: Miniport reported low packet resources.\n")); status = RcvPacketAlloc( deviceContext, lpxPayload, &packet ); if (status == STATUS_SUCCESS) { ASSERT( packet->Private.NdisPacketFlags & fPACKET_ALLOCATED_BY_NDIS ); // // Copy lpx payload. payload contains only data. // NdisCopyFromPacketToPacket( packet, 0, lpxPayload, Packet, ETHERNET_HEADER_LENGTH + addiLlcHeaderSize + lpxHeaderSize, &bytesCopied); ASSERT(lpxPayload == bytesCopied); } rawDataOffset = 0; pktReferenceCount = 0; } else { PLPX_RESERVED externalReserved; // // No need to allocate new NDIS packet and copy data to the new NDIS packet. // But, NDIS miniport allocates only 4 * sizeof(PVOID) for protocol reserved context. // We should allocate our own. // packet = Packet; status = NdisAllocateMemoryWithTag(&externalReserved, sizeof(LPX_RESERVED), LPX_MEM_TAG_EXTERNAL_RESERVED); if(status == NDIS_STATUS_SUCCESS) { RtlZeroMemory(externalReserved, sizeof(LPX_RESERVED)); // By setting the external reserved field, RESERVED() uses external reserved context automatically. ((PLPX_RESERVED)packet->ProtocolReserved)->ExternalReserved = externalReserved; // Initialize LPX reserved context instead of RcvPacketAlloc(). RESERVED(packet)->Cloned = 0; RESERVED(packet)->Type = LPX_PACKET_TYPE_RECEIVE; RESERVED(packet)->RecvFlags |= LPX_RESERVED_RECVFLAG_ALLOC_MINIPORT; // set data offset // Because NDIS miniport allocated the packet, the NDIS packet contains whole raw packet data. rawDataOffset = ETHERNET_HEADER_LENGTH + addiLlcHeaderSize + lpxHeaderSize; lpxPayload += rawDataOffset; // return one reference count indicating LPX will call NdisReturnPackets() once. pktReferenceCount = 1; } } if (status != NDIS_STATUS_SUCCESS) { return 0; } // // Init LPX reserved context // LpxCopyEthLpxHeadersToLpxReserved(packet, firstBuffer, protocol, lpxHeader, lpxHeaderSize); RESERVED(Packet)->Packet = packet; RESERVED(Packet)->RecvTime = CurrentTime(); RESERVED(Packet)->PacketRawDataLength = lpxPayload; RESERVED(Packet)->PacketRawDataOffset = rawDataOffset; // // Queue to the device context. // ExInterlockedInsertTailList( &deviceContext->PacketInProgressList, &(RESERVED(Packet)->ListEntry), &deviceContext->PacketInProgressQSpinLock ); return pktReferenceCount; }
VOID LpxTransferDataComplete( IN NDIS_HANDLE ProtocolBindingContext, IN PNDIS_PACKET Packet, IN NDIS_STATUS Status, IN UINT BytesTransfered ) { PDEVICE_CONTEXT pDeviceContext; PLPX_HEADER lpxHeader; PNDIS_BUFFER firstBuffer; PUCHAR packetData; UINT packetDataLength; USHORT lpxHeaderSize; UNREFERENCED_PARAMETER( BytesTransfered ); pDeviceContext = (PDEVICE_CONTEXT)ProtocolBindingContext; if (Status != NDIS_STATUS_SUCCESS) { ASSERT( FALSE ); DebugPrint( 1, ("[LPX] LpxTransferDataComplete error %x\n", Status) ); PacketFree( pDeviceContext, Packet ); return; } if (RESERVED(Packet)->HeaderCopied == FALSE) { NdisQueryPacket( Packet, NULL, NULL, &firstBuffer, NULL ); NdisQueryBufferSafe( firstBuffer, &packetData, &packetDataLength, HighPagePriority ); lpxHeader = (PLPX_HEADER)(packetData + RESERVED(Packet)->PacketRawDataOffset); lpxHeaderSize = sizeof(LPX_HEADER); #if __LPX_OPTION_ADDRESSS__ if (FlagOn(lpxHeader->Option, LPX_OPTION_SOURCE_ADDRESS)) { lpxHeaderSize += ETHERNET_ADDRESS_LENGTH; } if (FlagOn(lpxHeader->Option, LPX_OPTION_DESTINATION_ADDRESS)) { lpxHeaderSize += ETHERNET_ADDRESS_LENGTH; } #endif RtlCopyMemory( &RESERVED(Packet)->LpxHeader, lpxHeader, lpxHeaderSize ); RESERVED(Packet)->HeaderCopied = TRUE; RESERVED(Packet)->PacketRawDataLength = RESERVED(Packet)->PacketRawDataOffset + NTOHS(lpxHeader->PacketSize & ~LPX_TYPE_MASK); RESERVED(Packet)->PacketRawDataOffset += lpxHeaderSize; } lpxHeaderSize = sizeof(LPX_HEADER); #if __LPX_OPTION_ADDRESSS__ if (FlagOn(RESERVED(Packet)->LpxHeader.Option, LPX_OPTION_SOURCE_ADDRESS)) { if (!FlagOn(RESERVED(Packet)->LpxHeader.Option, LPX_OPTION_DESTINATION_ADDRESS)) { RtlCopyMemory( RESERVED(Packet)->OptionSourceAddress, RESERVED(Packet)->OptionDestinationAddress, ETHERNET_ADDRESS_LENGTH ); } lpxHeaderSize += ETHERNET_ADDRESS_LENGTH; ASSERT( RtlEqualMemory(RESERVED(Packet)->EthernetHeader.SourceAddress, RESERVED(Packet)->OptionSourceAddress, ETHERNET_ADDRESS_LENGTH) ); } if (FlagOn(RESERVED(Packet)->LpxHeader.Option, LPX_OPTION_DESTINATION_ADDRESS)) { lpxHeaderSize += ETHERNET_ADDRESS_LENGTH; ASSERT( RtlEqualMemory(RESERVED(Packet)->EthernetHeader.DestinationAddress, RESERVED(Packet)->OptionDestinationAddress, ETHERNET_ADDRESS_LENGTH) ); } #endif if (NTOHS(RESERVED(Packet)->LpxHeader.PacketSize & ~LPX_TYPE_MASK) - lpxHeaderSize != RESERVED(Packet)->PacketRawDataLength - RESERVED(Packet)->PacketRawDataOffset) { ASSERT( FALSE ); PacketFree( pDeviceContext, Packet ); return; } ExInterlockedInsertTailList( &pDeviceContext->PacketInProgressList, &(RESERVED(Packet)->ListEntry), &pDeviceContext->PacketInProgressQSpinLock ); return; }
NDIS_STATUS LpxReceiveIndication ( IN NDIS_HANDLE ProtocolBindingContext, IN NDIS_HANDLE MacReceiveContext, IN PVOID HeaderBuffer, IN UINT HeaderBufferSize, IN PVOID LookAheadBuffer, IN UINT LookAheadBufferSize, IN UINT PacketSize ) /*++ Routine Description: This routine receives control from the physical provider as an indication that a frame has been received on the physical link. This routine is time critical, so we only allocate a buffer and copy the packet into it. We also perform minimal validation on this packet. It gets queued to the device context to allow for processing later. Arguments: BindingContext - The Adapter Binding specified at initialization time. ReceiveContext - A magic cookie for the MAC. HeaderBuffer - pointer to a buffer containing the packet header. HeaderBufferSize - the size of the header. LookaheadBuffer - pointer to a buffer containing the negotiated minimum amount of buffer I get to look at (not including header). LookaheadBufferSize - the size of the above. May be less than asked for, if that's all there is. PacketSize - Overall size of the packet (not including header). Return Value: NDIS_STATUS - status of operation, one of: NDIS_STATUS_SUCCESS if packet accepted, NDIS_STATUS_NOT_RECOGNIZED if not recognized by protocol, NDIS_any_other_thing if I understand, but can't handle. --*/ { PDEVICE_CONTEXT deviceContext; USHORT protocol; PNDIS_PACKET packet; NDIS_STATUS status; UINT bytesTransfered = 0; UINT startOffset = 0; DebugPrint( 4, ("LpxReceiveIndication, Entered\n") ); deviceContext = (PDEVICE_CONTEXT)ProtocolBindingContext; // // validation // if (HeaderBufferSize != ETHERNET_HEADER_LENGTH) { DebugPrint( 4, ("HeaderBufferSize = %x\n", HeaderBufferSize) ); return NDIS_STATUS_NOT_RECOGNIZED; } RtlCopyMemory( (PUCHAR)&protocol, &((PUCHAR)HeaderBuffer)[12], sizeof(USHORT) ); // // Discard 802.2 LLC SNAP field. // // if Ether Type less than 0x0600 ( 1536 ) // if (NTOHS(protocol) < 0x0600 && protocol != HTONS(0x0060) && // LOOP: Ethernet Loopback protocol != HTONS(0x0200) && // PUP : Xerox PUP packet protocol != HTONS(0x0201)) { // PUPAP: Xerox PUP address trans packet #if __LPX__ NdisCopyLookaheadData( (PUCHAR)&protocol, &((PUCHAR)LookAheadBuffer)[LENGTH_8022LLCSNAP - 2], sizeof(USHORT), deviceContext->MacOptions ); #endif PacketSize -= LENGTH_8022LLCSNAP; LookAheadBufferSize -= LENGTH_8022LLCSNAP; startOffset = LENGTH_8022LLCSNAP; } if (protocol != HTONS(ETH_P_LPX)) { DebugPrint( 4, ("Type = %x\n", protocol) ); return NDIS_STATUS_NOT_RECOGNIZED; } // // Check to see if the device context is initialized. // //ACQUIRE_DPC_SPIN_LOCK( &deviceContext->SpinLock ); if (!FlagOn(deviceContext->LpxFlags, LPX_DEVICE_CONTEXT_START) || FlagOn(deviceContext->LpxFlags, LPX_DEVICE_CONTEXT_STOP)) { //RELEASE_DPC_SPIN_LOCK( &deviceContext->SpinLock ); DebugPrint( 4,("Device is not initialized. Drop packet\n") ); return NDIS_STATUS_NOT_RECOGNIZED; } ASSERT( deviceContext->NdisBindingHandle ); //RELEASE_DPC_SPIN_LOCK( &deviceContext->SpinLock ); // // DROP PACKET for DEBUGGING!!!! // #if 1 //DBG // Enabled for testing if (PacketRxDropRate) { PacketRxCountForDrop++; if ((PacketRxCountForDrop % 1000) <= PacketRxDropRate) { PLPX_HEADER lpxHeader = (PLPX_HEADER)LookAheadBuffer; #if 0 if ((PacketRxCountForDrop % (PacketRxDropRate*20)) == 0) DebugPrint( 1, ("[Drop(%x,%x,%x))]\n", NTOHS(lpxHeader->Lsctl), NTOHS(lpxHeader->Sequence), NTOHS(lpxHeader->AckSequence)) ); #endif DebugPrint( 1, ("D") ); return NDIS_STATUS_NOT_RECOGNIZED; } } #endif ASSERT( startOffset == 0 ); DebugPrint( 4, ("LpxReceiveIndication, PacketSize = %d, LookAheadBufferSize = %d, LPX_HEADER size = %d\n", PacketSize, LookAheadBufferSize, sizeof(LPX_HEADER)) ); if (LookAheadBufferSize >= sizeof(LPX_HEADER)) { PNDIS_BUFFER firstBuffer; PUCHAR packetData; PLPX_HEADER lpxHeader; USHORT lpxHeaderSize; lpxHeader = (PLPX_HEADER)((PBYTE)LookAheadBuffer + startOffset); lpxHeaderSize = sizeof(LPX_HEADER); #if __LPX_OPTION_ADDRESSS__ if (FlagOn(lpxHeader->Option, LPX_OPTION_SOURCE_ADDRESS)) { lpxHeaderSize += ETHERNET_ADDRESS_LENGTH; } if (FlagOn(lpxHeader->Option, LPX_OPTION_DESTINATION_ADDRESS)) { lpxHeaderSize += ETHERNET_ADDRESS_LENGTH; } #endif if (NTOHS(lpxHeader->PacketSize & ~LPX_TYPE_MASK) == lpxHeaderSize) { status = RcvPacketAlloc( deviceContext, 0, &packet ); if (status == STATUS_SUCCESS) { NdisCopyLookaheadData( &RESERVED(packet)->EthernetHeader, HeaderBuffer, ETHERNET_HEADER_LENGTH, deviceContext->MacOptions ); RESERVED(packet)->EthernetHeader.Type = protocol; RESERVED(packet)->RecvTime = CurrentTime(); RtlCopyMemory( &RESERVED(packet)->LpxHeader, lpxHeader, lpxHeaderSize ); RESERVED(packet)->HeaderCopied = TRUE; RESERVED(packet)->PacketRawDataLength = 0; RESERVED(packet)->PacketRawDataOffset = 0; LpxTransferDataComplete( deviceContext, packet, NDIS_STATUS_SUCCESS, LookAheadBufferSize ); return NDIS_STATUS_SUCCESS; } } else if (LookAheadBufferSize >= NTOHS(lpxHeader->PacketSize & ~LPX_TYPE_MASK)) { status = RcvPacketAlloc( deviceContext, NTOHS(lpxHeader->PacketSize & ~LPX_TYPE_MASK) - lpxHeaderSize, &packet ); if (status == STATUS_SUCCESS) { NdisCopyLookaheadData( &RESERVED(packet)->EthernetHeader, HeaderBuffer, ETHERNET_HEADER_LENGTH, deviceContext->MacOptions ); RESERVED(packet)->EthernetHeader.Type = protocol; RESERVED(packet)->RecvTime = CurrentTime(); RtlCopyMemory( &RESERVED(packet)->LpxHeader, lpxHeader, lpxHeaderSize ); RESERVED(packet)->HeaderCopied = TRUE; RESERVED(packet)->PacketRawDataLength = NTOHS(lpxHeader->PacketSize & ~LPX_TYPE_MASK) - lpxHeaderSize; RESERVED(packet)->PacketRawDataOffset = 0; NdisQueryPacket( packet, NULL, NULL, &firstBuffer, NULL ); packetData = MmGetMdlVirtualAddress( firstBuffer ); NdisCopyLookaheadData( packetData, (PBYTE)LookAheadBuffer + startOffset + lpxHeaderSize, RESERVED(packet)->PacketRawDataLength, deviceContext->MacOptions ); LpxTransferDataComplete( deviceContext, packet, NDIS_STATUS_SUCCESS, LookAheadBufferSize ); return NDIS_STATUS_SUCCESS; } } else { status = RcvPacketAlloc( deviceContext, startOffset + NTOHS(lpxHeader->PacketSize & ~LPX_TYPE_MASK), &packet ); if (status == STATUS_SUCCESS) { NdisCopyLookaheadData( &RESERVED(packet)->EthernetHeader, HeaderBuffer, ETHERNET_HEADER_LENGTH, deviceContext->MacOptions ); RESERVED(packet)->EthernetHeader.Type = protocol; RESERVED(packet)->RecvTime = CurrentTime(); RtlCopyMemory( &RESERVED(packet)->LpxHeader, lpxHeader, lpxHeaderSize ); RESERVED(packet)->HeaderCopied = TRUE; RESERVED(packet)->PacketRawDataLength = startOffset + NTOHS(lpxHeader->PacketSize & ~LPX_TYPE_MASK); RESERVED(packet)->PacketRawDataOffset = startOffset + lpxHeaderSize; } } } else { PLPX_HEADER lpxHeader; PNDIS_BUFFER firstBuffer; PUCHAR packetData; UINT packetDataLength; ASSERT( FALSE ); status = RcvPacketAlloc( deviceContext, PacketSize, &packet ); if (status == STATUS_SUCCESS) { RtlCopyMemory( &RESERVED(packet)->EthernetHeader, HeaderBuffer, ETHERNET_HEADER_LENGTH ); RESERVED(packet)->EthernetHeader.Type = protocol; RESERVED(packet)->RecvTime = CurrentTime(); RESERVED(packet)->PacketRawDataLength = PacketSize; RESERVED(packet)->PacketRawDataOffset = startOffset; NdisQueryPacket( packet, NULL, NULL, &firstBuffer, NULL ); NdisQueryBufferSafe( firstBuffer, &packetData, &packetDataLength, HighPagePriority ); lpxHeader = (PLPX_HEADER)(packetData + RESERVED(packet)->PacketRawDataOffset); RtlZeroMemory( lpxHeader, sizeof(LPX_HEADER) ); RESERVED(packet)->HeaderCopied = FALSE; } } if (status != NDIS_STATUS_SUCCESS) { return NDIS_STATUS_NOT_RECOGNIZED; } ASSERT( packet->Private.NdisPacketFlags & fPACKET_ALLOCATED_BY_NDIS ); if (deviceContext->NdisBindingHandle) { //ASSERT( FALSE ); NdisTransferData( &status, deviceContext->NdisBindingHandle, MacReceiveContext, 0, //RESERVED(packet)->PacketRawDataOffset, RESERVED(packet)->PacketRawDataLength, packet, &bytesTransfered ); if (status == NDIS_STATUS_PENDING) { LPX_ASSERT( FALSE ); status = NDIS_STATUS_SUCCESS; } else if (status == NDIS_STATUS_SUCCESS) { LpxTransferDataComplete( deviceContext, packet, status, bytesTransfered ); } else { LPX_ASSERT( FALSE ); DebugPrint( 1, ("NdisTransferData() failed. STATUS=%08lx\n", status) ); } } else { status = NDIS_STATUS_NOT_RECOGNIZED; DebugPrint( 1, ("Invalid device status. STATUS=%08lx\n", status) ); } return status; }
VOID PacketAllocatePacketBuffer(PNDIS_STATUS pStatus, POPEN_INSTANCE pOpen, PNDIS_PACKET *ppPacket, PDIOCPARAMETERS pDiocParms, DWORD FunctionCode ) { // allocate a buffer for reading/writing PNDIS_BUFFER pNdisBuffer; PNDIS_PACKET pPacket; // Try to get a packet from our list of free ones NdisAllocatePacket(pStatus, ppPacket, pOpen->PacketPool); if (*pStatus != NDIS_STATUS_SUCCESS) { *(DWORD *)(pDiocParms->lpcbBytesReturned) = 0; return; } pPacket = *ppPacket; // Buffers used asynchronously must be page locked switch (FunctionCode) { case IOCTL_EPACKET_READ: RESERVED(pPacket)->lpBuffer = (PVOID)PacketPageLock(pDiocParms->lpvOutBuffer, pDiocParms->cbOutBuffer); RESERVED(pPacket)->cbBuffer = pDiocParms->cbOutBuffer; break; case IOCTL_EPACKET_WRITE: RESERVED(pPacket)->lpBuffer = (PVOID)PacketPageLock(pDiocParms->lpvInBuffer, pDiocParms->cbInBuffer); RESERVED(pPacket)->cbBuffer = pDiocParms->cbInBuffer; break; default: // recycle the packet NdisReinitializePacket(pPacket); // Put the packet on the free queue NdisFreePacket(pPacket); *(DWORD *)(pDiocParms->lpcbBytesReturned) = 0; *pStatus = NDIS_STATUS_NOT_ACCEPTED; return; } RESERVED(pPacket)->lpcbBytesReturned = (PVOID)PacketPageLock(pDiocParms->lpcbBytesReturned, sizeof(DWORD)); RESERVED(pPacket)->lpoOverlapped = (PVOID)PacketPageLock(pDiocParms->lpoOverlapped, sizeof(OVERLAPPED)); RESERVED(pPacket)->hDevice = pDiocParms->hDevice; RESERVED(pPacket)->tagProcess = pDiocParms->tagProcess; switch (FunctionCode) { case IOCTL_EPACKET_READ: NdisAllocateBuffer(pStatus, &pNdisBuffer, pOpen->BufferPool, (PVOID)(RESERVED(pPacket)->lpBuffer + ETHERNET_HEADER_LENGTH), pDiocParms->cbOutBuffer); break; case IOCTL_EPACKET_WRITE: NdisAllocateBuffer(pStatus, &pNdisBuffer, pOpen->BufferPool, (PVOID)RESERVED(pPacket)->lpBuffer, pDiocParms->cbInBuffer); break; } if (*pStatus == NDIS_STATUS_SUCCESS) NdisChainBufferAtFront(pPacket, pNdisBuffer); // Attach buffer to Packet else { NdisReinitializePacket(pPacket); // recycle the packet NdisFreePacket(pPacket); // Put the packet on the free queue *(DWORD *)(pDiocParms->lpcbBytesReturned) = 0; } }
VOID PacketFree2 ( IN PNDIS_PACKET Packet ) { PLPX_RESERVED reserved = RESERVED(Packet); PUCHAR packetData; PNDIS_BUFFER pNdisBuffer; UINT uiLength; LONG clone; LONG BufferSeq; BOOLEAN allocMiniport = FALSE; PLPX_RESERVED externalReserved; DebugPrint( 3, ("PacketFree reserved->type = %d\n", reserved->Type) ); ASSERT( Packet->Private.NdisPacketFlags & fPACKET_ALLOCATED_BY_NDIS ); switch (reserved->Type) { case LPX_PACKET_TYPE_SEND: clone = InterlockedDecrement( &reserved->Cloned ); if(clone >= 0) { return; } pNdisBuffer = NULL; BufferSeq = 0; NdisUnchainBufferAtFront( Packet, &pNdisBuffer ); while (pNdisBuffer) { // // Assuming the first data buffer comes from user application // the others are created in LPX for padding, etc. // Free the memory of the others. // if (BufferSeq == 0) { #if DBG NdisQueryBufferSafe( pNdisBuffer, &packetData, &uiLength, HighPagePriority ); ASSERT( packetData == (PCHAR)&RESERVED(Packet)->EthernetHeader ); #endif } else if (BufferSeq == 1) { // UserBuffer } else if (BufferSeq == 2) { // Padding NdisQueryBufferSafe( pNdisBuffer, &packetData, &uiLength, HighPagePriority ); LpxFreeMemoryWithLpxTag( packetData ); } else { ASSERT( FALSE ); } NdisFreeBuffer( pNdisBuffer ); pNdisBuffer = NULL; NdisUnchainBufferAtFront( Packet, &pNdisBuffer ); BufferSeq ++; } if (reserved->IrpSp != NULL) { PIRP _Irp = IRP_SEND_IRP( reserved->IrpSp ); ASSERT( reserved->NdisStatus == NDIS_STATUS_SUCCESS || reserved->NdisStatus == NDIS_STATUS_NOT_ACCEPTED || !NT_SUCCESS(reserved->NdisStatus) ); if (!NT_SUCCESS(reserved->NdisStatus)) { _Irp->IoStatus.Status = reserved->NdisStatus; } //INC_IRP_RETRANSMITS( _Irp, reserved->Retransmits ); LpxDereferenceSendIrp( "Destroy packet", reserved->IrpSp, RREF_PACKET ); } else { DebugPrint( 3, ("[LPX] PacketFree: No IrpSp\n") ) ; } break; case LPX_PACKET_TYPE_RECEIVE: // // If the packet allocated by NIC miniport, break here. // if(RESERVED(Packet)->RecvFlags & LPX_RESERVED_RECVFLAG_ALLOC_MINIPORT) { allocMiniport = TRUE; break; } pNdisBuffer = NULL; NdisUnchainBufferAtFront( Packet, &pNdisBuffer ); #if __LPX_STATISTICS__ { LARGE_INTEGER systemTime; KeQuerySystemTime( &systemTime ); RESERVED(Packet)->DeviceContext->NumberOfRecvPackets ++; RESERVED(Packet)->DeviceContext->FreeTimeOfRecvPackets.QuadPart += systemTime.QuadPart - RESERVED(Packet)->RecvTime2.QuadPart; RESERVED(Packet)->DeviceContext->BytesOfRecvPackets.QuadPart += sizeof(LPX_HEADER) + RESERVED(Packet)->PacketRawDataLength; if (RESERVED(Packet)->PacketRawDataLength) { RESERVED(Packet)->DeviceContext->NumberOfLargeRecvPackets ++; RESERVED(Packet)->DeviceContext->FreeTimeOfLargeRecvPackets.QuadPart += systemTime.QuadPart - RESERVED(Packet)->RecvTime2.QuadPart; RESERVED(Packet)->DeviceContext->BytesOfLargeRecvPackets.QuadPart += sizeof(LPX_HEADER) + RESERVED(Packet)->PacketRawDataLength; } else { RESERVED(Packet)->DeviceContext->NumberOfSmallRecvPackets ++; RESERVED(Packet)->DeviceContext->FreeTimeOfSmallRecvPackets.QuadPart += systemTime.QuadPart - RESERVED(Packet)->RecvTime2.QuadPart; RESERVED(Packet)->DeviceContext->BytesOfSmallRecvPackets.QuadPart += sizeof(LPX_HEADER); } } #endif if (pNdisBuffer) { NdisQueryBufferSafe( pNdisBuffer, &packetData, &uiLength, HighPagePriority ); LpxFreeMemoryWithLpxTag( packetData ); NdisFreeBuffer( pNdisBuffer ); } break; default: ASSERT(FALSE); return; } // // Free external protocol reserved context. // externalReserved = ((PLPX_RESERVED)(Packet->ProtocolReserved))->ExternalReserved; if(externalReserved) { NdisFreeMemory(externalReserved, sizeof(LPX_RESERVED), 0); } ASSERT( Packet->Private.NdisPacketFlags & fPACKET_ALLOCATED_BY_NDIS ); if(allocMiniport) { // // Return the packet allocated by NIC miniport // NdisReturnPackets(&Packet, 1); } else { NdisFreePacket( Packet ); InterlockedDecrement( &NumberOfAllockPackets ); DebugPrint( 3, ("Packet REALLY Freed NumberOfAllockPackets = %d\n", NumberOfAllockPackets) ); } }
/*************************************************************************** Routine Description: This routine examines if the packet at the head of the packet list can be copied to the adapter, and does so. Arguments: Adapter - Pointer to the adapter block. Return Value: None *****************************************************************************/ void R6040DoNextSend(PR6040_ADAPTER Adapter) { // The packet to process. PNDIS_PACKET Packet; // The current destination transmit buffer. // XMIT_BUF TmpBuf1; // Length of the packet ULONG Len; //RETAILMSG(R6040DBG, (TEXT("+"))); // Check if we have enough resources and a packet to process while ((Adapter->FirstPacket != NULL) /*&&!Adapter->Tx_free_cnt*/) { // If we're shutting down, just get out of here (card may not be present) if (Adapter->ShuttingDown) { RETAILMSG(R6040DBG, (TEXT("R6040DoNextSend(): Shutdown detected\r\n"))); break; } //If Queue full if (Adapter->Tx_free_cnt <= 0) { RETAILMSG(R6040DBG, (TEXT("R6040DoNextSend(): Queue full\r\n"))); break; } // Get the length of the packet. NdisQueryPacket( Adapter->FirstPacket, NULL, NULL, NULL, &Len ); //RETAILMSG(R6040DBG, (TEXT("R6040DoNextSend(): packet length = %d\r\n"), Len)); // Remove the packet from the queue. Packet = Adapter->FirstPacket; Adapter->FirstPacket = RESERVED(Packet)->Next; if (Packet == Adapter->LastPacket) { Adapter->LastPacket = NULL; } // Copy down the packet. if (CardCopyDownPacket(Adapter, Packet, &Adapter->PacketLens[Adapter->Tx_desc_add]) == FALSE) { RETAILMSG(R6040DBG, (TEXT("R6040DoNextSend(): Copy Down packet error\r\n"))); NdisReleaseSpinLock(&Adapter->SendLock); NdisMSendComplete( Adapter->MiniportAdapterHandle, Packet, NDIS_STATUS_FAILURE ); NdisAcquireSpinLock(&Adapter->SendLock); continue; } // Ack the send immediately. If for some reason it // should fail, the protocol should be able to handle // the retransmit. NdisReleaseSpinLock(&Adapter->SendLock); //RETAILMSG(R6040DBG, (TEXT("R6040DoNextSend(): NdisMSendComplete \r\n"))); NdisMSendComplete( Adapter->MiniportAdapterHandle, Packet, NDIS_STATUS_SUCCESS ); NdisAcquireSpinLock(&Adapter->SendLock); } //RETAILMSG(R6040DBG, (TEXT("-"))); }
VOID PacketCancelRoutine ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) { POPEN_INSTANCE open = DeviceObject->DeviceExtension; KIRQL oldIrql; PIRP irpToComplete = NULL; PLIST_ENTRY thisEntry, listHead; PIRP pendingIrp; PNDIS_PACKET myPacket = NULL; PPACKET_RESERVED reserved; PMDL mdl; // Don't assume that the IRP being cancelled is in the queue. // Only complete the IRP if it IS in the queue. // // Must acquire the local spinlock before releasing // the global cancel spinlock // // DebugPrint(("PacketCancelRoutine\n")); oldIrql = Irp->CancelIrql; // One should not intermix KeAcquireSpinLock(AtDpcLevel) // and ExInterlocked...List() functions on the same spinlock if the // routines that use the lock run at IRQL > DISPATCH_LEVEL. // After acquiring the lock using Ke function, if we got interrupted // and entered into an ISR and tried to manipulate the list using // ExInterlocked...List function with the same lock, we deadlock. // In this sample we can safely do that because none of our routines // will be called at IRQL > DISPATCH_LEVEL. KeAcquireSpinLockAtDpcLevel(&open->RcvQSpinLock); IoReleaseCancelSpinLock( KeGetCurrentIrql() ); listHead = &open->RcvList; for( thisEntry = listHead->Flink; thisEntry != listHead; thisEntry = thisEntry->Flink ) { reserved=CONTAINING_RECORD(thisEntry,PACKET_RESERVED,ListElement); myPacket=CONTAINING_RECORD(reserved,NDIS_PACKET,ProtocolReserved); pendingIrp = RESERVED(myPacket)->Irp; if (pendingIrp == Irp) { RemoveEntryList(thisEntry); irpToComplete = pendingIrp; break; } } KeReleaseSpinLock(&open->RcvQSpinLock, oldIrql); if(irpToComplete) { // DebugPrint(("Cancelling IRP\n")); // ASSERT(myPacket); NdisFreePacket(myPacket); irpToComplete->IoStatus.Status = STATUS_CANCELLED; irpToComplete->IoStatus.Information = 0; IoCompleteRequest(irpToComplete, IO_NO_INCREMENT); IoDecrement(open); } }
NTSTATUS SendPacketAlloc ( IN PDEVICE_CONTEXT DeviceContext, IN PTP_ADDRESS Address, IN UCHAR DestinationAddressNode[], IN PUCHAR UserData, IN ULONG UserDataLength, IN PIO_STACK_LOCATION IrpSp, IN UCHAR Option, OUT PNDIS_PACKET *Packet ) { NTSTATUS status; PUCHAR packetHeader = NULL; PNDIS_BUFFER packetHeaderBuffer = NULL; ULONG packetHeaderLength; PNDIS_BUFFER userDataBuffer = NULL; PUCHAR paddingData = NULL; PNDIS_BUFFER paddingDataBuffer = NULL; PNDIS_PACKET packet = NULL; USHORT etherType; packetHeaderLength = ETHERNET_HEADER_LENGTH + sizeof(LPX_HEADER); #if __LPX_OPTION_ADDRESSS__ if (FlagOn(Option, LPX_OPTION_SOURCE_ADDRESS)) { packetHeaderLength += ETHERNET_ADDRESS_LENGTH; } if (FlagOn(Option, LPX_OPTION_DESTINATION_ADDRESS)) { packetHeaderLength += ETHERNET_ADDRESS_LENGTH; } #endif ASSERT( packetHeaderLength + UserDataLength <= ETHERNET_HEADER_LENGTH + DeviceContext->MaxUserData ); DebugPrint( 3, ("SendPacketAlloc, packetHeaderLength = %d, NumberOfAllockPackets = %d\n", packetHeaderLength, NumberOfAllockPackets) ); ASSERT( DeviceContext ); ASSERT( DeviceContext->LpxPacketPool != NULL ); do { NdisAllocatePacket( &status, &packet, DeviceContext->LpxPacketPool ); if (status != NDIS_STATUS_SUCCESS) { ASSERT( FALSE ); LPX_ASSERT( status == NDIS_STATUS_RESOURCES ); return status; } RtlZeroMemory( RESERVED(packet), sizeof(LPX_RESERVED) ); ASSERT( packet->Private.NdisPacketFlags & fPACKET_ALLOCATED_BY_NDIS ); packetHeader = (PCHAR)&RESERVED(packet)->EthernetHeader; NdisAllocateBuffer( &status, &packetHeaderBuffer, DeviceContext->LpxBufferPool, packetHeader, packetHeaderLength ); if (!NT_SUCCESS(status)) { ASSERT( status == NDIS_STATUS_FAILURE ); ASSERT( FALSE ); break; } if (UserData && UserDataLength) { NdisAllocateBuffer( &status, &userDataBuffer, DeviceContext->LpxBufferPool, UserData, UserDataLength ); if(!NT_SUCCESS(status)) { ASSERT( status == NDIS_STATUS_FAILURE ); ASSERT( FALSE ); break; } } ////////////////////////////////////////////////////////////////////////// // // Add padding to fix Under-60byte bug of NDAS chip 2.0. // if (packetHeaderLength == ETHERNET_HEADER_LENGTH + sizeof(LPX_HEADER)) { UINT totalPacketLength; totalPacketLength = packetHeaderLength + UserDataLength; if (totalPacketLength >= ETHERNET_HEADER_LENGTH + sizeof(LPX_HEADER) + 4 && totalPacketLength <= 56) { LONG paddingLen = 60 - totalPacketLength; DebugPrint( 4, ("[LpxSmp]TransmitDataPacket: Adding padding to support NDAS chip 2.0\n") ); status = LpxAllocateMemoryWithLpxTag( &paddingData, paddingLen ); if (status != NDIS_STATUS_SUCCESS) { ASSERT( status == NDIS_STATUS_FAILURE ); ASSERT( FALSE ); break; } NdisAllocateBuffer( &status, &paddingDataBuffer, DeviceContext->LpxBufferPool, paddingData, paddingLen ); if (status != NDIS_STATUS_SUCCESS) { ASSERT( status == NDIS_STATUS_FAILURE ); ASSERT( FALSE ); break; } RtlZeroMemory( paddingData, paddingLen ); RtlCopyMemory( paddingData + paddingLen - 4, UserData + UserDataLength - 4, 4 ); } } // // End of padding routine. // ////////////////////////////////////////////////////////////////////////// } while(0); if (status == STATUS_SUCCESS) { RtlCopyMemory( &packetHeader[0], DestinationAddressNode, ETHERNET_ADDRESS_LENGTH ); RtlCopyMemory( &packetHeader[ETHERNET_ADDRESS_LENGTH], Address->NetworkName->Node, ETHERNET_ADDRESS_LENGTH ); etherType = HTONS( ETH_P_LPX ); RtlCopyMemory( &packetHeader[ETHERNET_ADDRESS_LENGTH*2], ðerType, 2 ); #if __LPX_OPTION_ADDRESSS__ if (FlagOn(Option, LPX_OPTION_DESTINATION_ADDRESS)) { RtlCopyMemory( RESERVED(packet)->OptionDestinationAddress, DestinationAddressNode, ETHERNET_ADDRESS_LENGTH ); } if (FlagOn(Option, LPX_OPTION_SOURCE_ADDRESS)) { if (FlagOn(Option, LPX_OPTION_DESTINATION_ADDRESS)) { RtlCopyMemory( RESERVED(packet)->OptionSourceAddress, Address->NetworkName->Node, ETHERNET_ADDRESS_LENGTH ); } else { RtlCopyMemory( RESERVED(packet)->OptionDestinationAddress, Address->NetworkName->Node, ETHERNET_ADDRESS_LENGTH ); } } #endif RESERVED(packet)->LpxHeader.PacketSize = HTONS( (USHORT)(packetHeaderLength - ETHERNET_HEADER_LENGTH + UserDataLength) ); RESERVED(packet)->LpxHeader.Option = Option; RESERVED(packet)->Cloned = 0; RESERVED(packet)->IrpSp = IrpSp; RESERVED(packet)->Type = LPX_PACKET_TYPE_SEND; RESERVED(packet)->Packet = packet; if (IrpSp == NULL) { DebugPrint( 3, ("[LPX] PacketAllocate: No IrpSp\n") ) ; } if (paddingDataBuffer) NdisChainBufferAtFront( packet, paddingDataBuffer ); if (userDataBuffer) NdisChainBufferAtFront( packet, userDataBuffer ); NdisChainBufferAtFront( packet, packetHeaderBuffer ); InterlockedIncrement( &NumberOfAllockPackets ); *Packet = packet; } else { if (paddingDataBuffer) NdisFreeBuffer( paddingDataBuffer ); if( paddingData) LpxFreeMemoryWithLpxTag( paddingData ); if (userDataBuffer) NdisFreeBuffer( userDataBuffer ); if (packetHeaderBuffer) NdisFreeBuffer( packetHeaderBuffer ); if (packet) NdisFreePacket( packet ); *Packet = NULL; DebugPrint( 1, ("[LPX]PacketAllocate: Can't Allocate Buffer For CopyData!!!\n") ); } return status; }
NDIS_STATUS PacketReceiveIndicate ( IN NDIS_HANDLE ProtocolBindingContext, IN NDIS_HANDLE MacReceiveContext, IN PVOID HeaderBuffer, IN UINT HeaderBufferSize, IN PVOID LookAheadBuffer, IN UINT LookaheadBufferSize, IN UINT PacketSize ) { POPEN_INSTANCE open; PIO_STACK_LOCATION irpSp; PIRP irp; PLIST_ENTRY packetListEntry; PNDIS_PACKET pPacket; ULONG sizeToTransfer; NDIS_STATUS status; UINT bytesTransfered = 0; ULONG bufferLength; PPACKET_RESERVED reserved; PMDL pMdl; // DebugPrint(("ReceiveIndicate\n")); open= (POPEN_INSTANCE)ProtocolBindingContext; if (HeaderBufferSize > ETHERNET_HEADER_LENGTH) { return NDIS_STATUS_SUCCESS; } // See if there are any pending read that we can satisfy packetListEntry = ExInterlockedRemoveHeadList( &open->RcvList, &open->RcvQSpinLock ); if (packetListEntry == NULL) { // DebugPrint(("No pending read, dropping packets\n")); return NDIS_STATUS_NOT_ACCEPTED; } reserved = CONTAINING_RECORD(packetListEntry,PACKET_RESERVED,ListElement); pPacket = CONTAINING_RECORD(reserved,NDIS_PACKET,ProtocolReserved); irp = RESERVED(pPacket)->Irp; irpSp = IoGetCurrentIrpStackLocation(irp); // We don't have to worry about the situation where the IRP is cancelled // after we remove it from the queue and before we reset the cancel // routine because the cancel routine has been coded to cancel an IRP // only if it's in the queue. IoSetCancelRoutine(irp, NULL); bufferLength = irpSp->Parameters.Read.Length-ETHERNET_HEADER_LENGTH; sizeToTransfer = (PacketSize < bufferLength) ? PacketSize : bufferLength; NdisMoveMappedMemory( MmGetSystemAddressForMdlSafe(irp->MdlAddress, NormalPagePriority), HeaderBuffer, HeaderBufferSize ); pMdl=IoAllocateMdl( MmGetMdlVirtualAddress(irp->MdlAddress), MmGetMdlByteCount(irp->MdlAddress), FALSE, FALSE, NULL ); if (pMdl == NULL) { // DebugPrint(("Packet: Read-Failed to allocate Mdl\n")); status = NDIS_STATUS_RESOURCES; goto ERROR; } IoBuildPartialMdl( irp->MdlAddress, pMdl, ((PUCHAR)MmGetMdlVirtualAddress(irp->MdlAddress))+ETHERNET_HEADER_LENGTH, 0 ); pMdl->Next = NULL; RESERVED(pPacket)->pMdl=pMdl; NdisChainBufferAtFront(pPacket,pMdl); NdisTransferData( &status, open->AdapterHandle, MacReceiveContext, 0, sizeToTransfer, pPacket, &bytesTransfered ); if (status == NDIS_STATUS_PENDING) { return NDIS_STATUS_SUCCESS; } ERROR: PacketTransferDataComplete( open, pPacket, status, bytesTransfered ); return NDIS_STATUS_SUCCESS; }
NTSTATUS RcvPacketAlloc ( IN PDEVICE_CONTEXT DeviceContext, IN ULONG PacketDataLength, OUT PNDIS_PACKET *Packet ) { NTSTATUS status; PUCHAR packetData = NULL; PNDIS_BUFFER packetDataBuffer = NULL; PNDIS_PACKET packet = NULL; DebugPrint( 3, ("RcvPacketAlloc, PacketLength = %d, NumberOfAllockPackets = %d\n", PacketDataLength, NumberOfAllockPackets) ); ASSERT( DeviceContext ); ASSERT( DeviceContext->LpxPacketPool != NULL ); ASSERT( PacketDataLength <= DeviceContext->MaxUserData ); do { NdisAllocatePacket( &status, &packet, DeviceContext->LpxPacketPool ); if (status != NDIS_STATUS_SUCCESS) { ASSERT( status == NDIS_STATUS_RESOURCES ); ASSERT( FALSE ); return status; } RtlZeroMemory( RESERVED(packet), sizeof(LPX_RESERVED) ); ASSERT( packet->Private.NdisPacketFlags & fPACKET_ALLOCATED_BY_NDIS ); if (PacketDataLength) { status = LpxAllocateMemoryWithLpxTag( &packetData, PacketDataLength ); if (status != NDIS_STATUS_SUCCESS) { ASSERT( status == NDIS_STATUS_FAILURE ); ASSERT( FALSE ); break; } NdisAllocateBuffer( &status, &packetDataBuffer, DeviceContext->LpxBufferPool, packetData, PacketDataLength ); if (!NT_SUCCESS(status)) { ASSERT( status == NDIS_STATUS_FAILURE ); ASSERT( FALSE ); break; } NdisChainBufferAtFront( packet, packetDataBuffer ); } } while(0); if (status == STATUS_SUCCESS) { RESERVED(packet)->Cloned = 0; RESERVED(packet)->Type = LPX_PACKET_TYPE_RECEIVE; RESERVED(packet)->Packet = packet; InterlockedIncrement( &NumberOfAllockPackets ); *Packet = packet; #if __LPX_STATISTICS__ KeQuerySystemTime( &RESERVED(packet)->RecvTime2 ); RESERVED(packet)->DeviceContext = DeviceContext; #endif } else { if (packetDataBuffer) NdisFreeBuffer( packetDataBuffer ); if (packetData) LpxFreeMemoryWithLpxTag( packetData ); if (packet) NdisFreePacket( packet ); *Packet = NULL; DebugPrint( 1, ("[LPX]RcvPacketAlloc: Can't Allocate Buffer For CopyData!!!\n") ); } return status; }