// Read the packet data from the transmit packet queue void NeoRead(void *buf) { NEO_QUEUE *q; UINT num; BOOL left; // Validate arguments if (buf == NULL) { return; } // Copy the packets one by one from the queue num = 0; left = TRUE; NeoLockPacketQueue(); { while (TRUE) { if (num >= NEO_MAX_PACKET_EXCHANGE) { if (ctx->PacketQueue == NULL) { left = FALSE; } break; } q = NeoGetNextQueue(); if (q == NULL) { left = FALSE; break; } NEO_SIZE_OF_PACKET(buf, num) = q->Size; NeoCopy(NEO_ADDR_OF_PACKET(buf, num), q->Buf, q->Size); num++; NeoFreeQueue(q); } } NeoUnlockPacketQueue(); NEO_NUM_PACKET(buf) = num; NEO_LEFT_FLAG(buf) = left; if (left == FALSE) { NeoReset(ctx->Event); } else { NeoSet(ctx->Event); } return; }
// Release the control device void NeoFreeControlDevice() { if (ctx == NULL) { return; } if (ctx->Opened != FALSE) { // Delete the event NeoSet(ctx->Event); NeoFreeEvent(ctx->Event); ctx->Event = NULL; ctx->Opened = FALSE; } // Delet the device NdisMDeregisterDevice(ctx->NdisControl); }
// Packet send handler void NeoNdisSendPackets(NDIS_HANDLE MiniportAdapterContext, NDIS_PACKET **PacketArray, UINT NumberOfPackets) { UCHAR *Buf,*BufCopy; PNDIS_BUFFER Buffer; UCHAR *Tmp; UINT PacketLength; UINT CurrentLength; UINT i; if (ctx == NULL) { return; } // Update the connection state NeoCheckConnectState(); if (NumberOfPackets == 0) { // The number of packets is 0 return; } if (NeoNdisSendPacketsHaltCheck(PacketArray, NumberOfPackets) == FALSE) { // Device is stopped return; } // Operation of the packet queue NeoLockPacketQueue(); { if (NeoNdisSendPacketsHaltCheck(PacketArray, NumberOfPackets) == FALSE) { // Device is stopped NeoUnlockPacketQueue(); return; } // Place the packet in the queue in order for (i = 0;i < NumberOfPackets;i++) { // Get a packet NdisQueryPacket(PacketArray[i], NULL, NULL, &Buffer, &PacketLength); // Extract the packet. // Memory allocated here is used for the queue and is released at the time of releasing the queue. Buf = NeoMalloc(PacketLength); BufCopy = Buf; while (Buffer) { NdisQueryBuffer(Buffer, &Tmp, &CurrentLength); if (CurrentLength == 0) { // Complete break; } NeoCopy(BufCopy, Tmp, CurrentLength); BufCopy += CurrentLength; NdisGetNextBuffer(Buffer, &Buffer); } // Process this packet if (PacketLength > NEO_MIN_PACKET_SIZE) { if (PacketLength > NEO_MAX_PACKET_SIZE) { // Packet is too large NDIS_SET_PACKET_STATUS(PacketArray[i], NDIS_STATUS_FAILURE); if (g_is_win8) { NdisMSendComplete(ctx->NdisMiniport, PacketArray[i], NDIS_STATUS_FAILURE); } ctx->Status.NumPacketSendError++; NeoFree(Buf); } else { // Insert the packet into the queue NeoInsertQueue(Buf, PacketLength); NDIS_SET_PACKET_STATUS(PacketArray[i], NDIS_STATUS_SUCCESS); if (g_is_win8) { NdisMSendComplete(ctx->NdisMiniport, PacketArray[i], NDIS_STATUS_SUCCESS); } ctx->Status.NumPacketSend++; } } else { // Release if the packet doesn't contain data NDIS_SET_PACKET_STATUS(PacketArray[i], NDIS_STATUS_SUCCESS); if (g_is_win8) { NdisMSendComplete(ctx->NdisMiniport, PacketArray[i], NDIS_STATUS_SUCCESS); } NeoFree(Buf); } } } NeoUnlockPacketQueue(); // Reception event NeoSet(ctx->Event); }
// Packet send handler void NeoNdisSendNetBufferLists(NDIS_HANDLE MiniportAdapterContext, NET_BUFFER_LIST *NetBufferLists, NDIS_PORT_NUMBER PortNumber, ULONG SendFlags) { if (ctx == NULL) { return; } // Update the connection state NeoCheckConnectState(); if (NeoNdisSendPacketsHaltCheck(NetBufferLists) == FALSE) { // Device is stopped return; } // Operation of the packet queue NeoLockPacketQueue(); { NET_BUFFER_LIST *nbl; if (NeoNdisSendPacketsHaltCheck(NetBufferLists) == FALSE) { // Device is stopped NeoUnlockPacketQueue(); return; } nbl = NetBufferLists; while (nbl != NULL) { NET_BUFFER *nb = NET_BUFFER_LIST_FIRST_NB(nbl); while (nb != NULL) { UINT size = NET_BUFFER_DATA_LENGTH(nb); if (size >= NEO_MIN_PACKET_SIZE && size <= NEO_MAX_PACKET_SIZE) { UCHAR *buf = NeoMalloc(size); void *ptr; ptr = NdisGetDataBuffer(nb, size, buf, 1, 0); if (ptr == NULL) { ctx->Status.NumPacketSendError++; ctx->Status.Int64NumSendError++; NeoFree(buf); } else { if (ptr != buf) { NeoCopy(buf, ptr, size); } NeoInsertQueue(buf, size); ctx->Status.NumPacketSend++; if (buf[0] & 0x40) { ctx->Status.Int64NumSendBroadcast++; ctx->Status.Int64BytesSendBroadcast += (UINT64)size; } else { ctx->Status.Int64NumSendUnicast++; ctx->Status.Int64BytesSendUnicast += (UINT64)size; } ctx->Status.Int64BytesSendTotal += (UINT64)size; } } else { ctx->Status.NumPacketSendError++; ctx->Status.Int64NumSendError++; } nb = NET_BUFFER_NEXT_NB(nb); } nbl = NET_BUFFER_LIST_NEXT_NBL(nbl); } } NeoUnlockPacketQueue(); // Notify the transmission completion NdisMSendNetBufferListsComplete(ctx->NdisMiniport, NetBufferLists, NDIS_STATUS_SUCCESS); // Reception event NeoSet(ctx->Event); }