DrvRecvThread

The Receive Thread (RT) is started from the RtndConfigure routine by calling CreateRealtimeThread. The RtndConfigure routine normally passes the local card information structure pointer as a parameter to the DrvRecvThread routine, though this is driver dependent and up to the driver developer.

The RT is responsible for reading data from the NIC after it is signaled by the Interrupt Service Thread (IST).

The Receive Thread performs the following functions:

  1. Wait for a receive interrupt event with WaitForSingleObject.
  2. Get a stack receive packet to place data into with RtnGetPacket.
  3. Get a pointer to the packet data area with RtnDecodePacket.
  4. Copy the received data into the packet data area.
  5. Queue the new packet in the driver receive queue with RtnQueueRecvPacket.
  6. If the NIC supports multiple packet reception, then the driver may check for any additional received packets, essentially returning to step two above until all packets have been read from the card and placed in the driver receive queue with RtnQueueRecvPacket.
  7. Process all queued packets by calling RtnProcessRecvQueue.
  8. Return to step one above and wait for another receive interrupt event.

Syntax

static
ULONG
WINAPI
DrvRecvThread(
    DRVDEV* pCardInfo
);

Parameters

pCardInfo

Pointer to local card information structure for this instance of the driver.

Return Values

None - Does not actually return.

Process Context

DrvRecvThread is always run within the process context of the RtxTcpIp Protocol Stack.

Example: Skeleton Receive Thread

static
ULONG
WINAPI
DrvRecvThread
(
      DRVDEV* pCardInfo )
{
      for (;;)
      {
            void* pRecvBuf; // a receive message buffer pointer
            void *tndp;
            void *mp;
            unsigned long dataLength;
            int packet_length;
            // wait until one or more packets are received
            WaitForSingleObject (pCardInfo->hRecvEvent, INFINITE);
            RtnEnterCriticalLock (&pCardInfo->drvCritSect);
            // device-specific code to read the packets
            // from the NIC goes here
            // once a valid received packet is available, do this:
            RtnLeaveCriticalLock (&pCardInfo->drvCritSect);
            // set packet_length to length of new received
            // packet here ...
            packet_length = 1234;
            // get a queued buffer from the stack to place data into
            mp = RtnGetPacket (pCardInfo->ndp, packet_length);
            if (mp == NULL)
            {
                  // no buffers available, print message or something
            }
            else
            {
                  // get the actual data location pointer
                  RtnDecodePacket (mp, &((unsigned long) tndp),
                  &((unsigned long) pRecvBuf), &dataLength);
                  // copy the frame into the stack's buffer here
                  //(and set dataLength)
                  dataLength = packet_length;
                  // queue the packet in this device's receive queue
                  RtnQueueRecvPacket (pCardInfo->ndp, mp, dataLength);
            }
            RtnEnterCriticalLock (&pCardInfo->drvCritSect);
            // any additional device-specific code goes here
            RtnLeaveCriticalLock (&pCardInfo->drvCritSect);
            // if any packets have been received,
            //pass packet(s) up to the stack
            RtnProcessRecvQueue (pCardInfo->ndp);
      }
}
IntervalZero.com | Support | Give Feedback