📄 nnetdrv.c
字号:
while (interrupt_level >= VNETPRIO) {
Recv_Thread_Suspended++;
SuspendThread(Recv_Thread_ID.thread_hdl);
Recv_Thread_Suspended--;
continue;
}
/* Higher priority ISRs are done. Raise the priority level to that of the
virtual network.
*/
oldlevel = interrupt_level;
interrupt_level = VNETPRIO;
In_ISR++;
/* Initialize the input to the NT network driver. */
geteventInfo.MemPtr = NDISComMemStart;
geteventInfo.RingPtr = ItoKval(
MNT_Header_Ptr->MNT_hdr_cpuDesc[MNT_ID].MNT_cd_pInputRing,
PMNT_RING,
NDISComMemStart);
geteventInfo.Id = MNT_ID;
/* Retrieve packets until the application closes. */
do {
status = DeviceIoControl (hDriver,
IOCTL_GETEVENT,
&geteventInfo,
sizeof(geteventInfo),
NULL,
0,
&dwData,
&ovl);
/* If a status of success was returned there was a packet waiting.
Get it.
*/
if(status)
{
/* A packet had was waiting. Call the ISR to retrieve it. */
(*VectorTable[VNETPRIO])(VNETPRIO);
}
/* If the IRP was marked as pending then wait. */
else if (GetLastError() == ERROR_IO_PENDING)
{
In_ISR--;
interrupt_level = oldlevel;
/* Wait for a packet to arrive. */
WaitForSingleObject (hEvt, INFINITE);
/* Check to see if this thread was restarted because the application
is closing. If so get out of the loop. */
if (VDRV_Driver_Closing)
break;
/* A packet has arrived. Wait until higher priority ISRs are done
before continueing. */
while (interrupt_level >= VNETPRIO) {
Recv_Thread_Suspended++;
SuspendThread(Recv_Thread_ID.thread_hdl);
Recv_Thread_Suspended--;
continue;
}
oldlevel = interrupt_level;
interrupt_level = VNETPRIO;
In_ISR++;
/* Invoke the ISR to process the new packet. */
(*VectorTable[VNETPRIO])(VNETPRIO);
ResetEvent (hEvt);
}
else {
demo_exit (0);
}
} while (1);
} /* end NU_Recv_Packet */
/******************************************************************************
* FUNCTION
*
* VDRV_Xmit_Packet
*
* DESCRIPTION
*
* This function places a packet onto the "physical meduim". In this case
* the physical medium is a common memory area. Broadcast packets must
* be copied to the receive ring of every active MNT process. Unicast
* packets are copied only to the receive ring of the destination MNT
* process.
*
* AUTHOR
*
* Glen Johnson
*
* INPUTS
*
* UINT8 * : pointer to the packet to be sent
* UINT16 : size in bytes of the packet to be sent.
*
* OUTPUTS
*
* sshort : Returns NU_SUCCESS if ok, else -1
*
*
******************************************************************************/
STATUS VDRV_Xmit_Packet (DV_DEVICE_ENTRY *device, NET_BUFFER *pack_addr)
{
IOCTL_OUT_RINGGET ringgetInfo;
IOCTL_OUT_RINGPUT ringputInfo;
IOCTL_OUT_GENEVENT geneventInfo;
IOCTL_OUT_MULTI_RINGGET mRinggetInfo;
DLAYER *dlayer;
DWORD cbReturned;
LONG dest_id;
INT bufferOffset = 0;
INT ringputStatus;
MNT_BUF_NODE *buf_node_ptr;
INT status;
INT count = 0, bytes_copied;
ULONG i, successCount;
MNT_CPU_DESC *mnt_cpu_ptr;
NET_BUFFER *buf_ptr = pack_addr;
#ifndef PACKET
/* Note that the PACKET conditional compilation flag affects not only the
driver but the Nucleus NET library, as well. PACKET must be defined in
the file TARGET.H.
*/
#error PACKET must be defined at compile time.
#endif
#if (INCLUDE_SNMP == NU_TRUE)
/* Is this a unicast or a non-unicast packet. */
if (buf_ptr->mem_flags & NET_BCAST)
SNMP_ifOutNUcastPkts_Inc(device->dev_index);
else
SNMP_ifOutUcastPkts_Inc(device->dev_index);
#endif
/*
* Check to make sure that the message has the minimum of at least 60
* bytes long. If not just set the new length, since hardware will do
* the checksum for the whole block.
*/
if (pack_addr->mem_total_data_len < 60)
pack_addr->mem_total_data_len = pack_addr->data_len = 60;
/* Make sure the packet will fit in a ring buffer. */
if(pack_addr->mem_total_data_len > MNT_BUFFER_SIZE)
{
SNMP_ifOutDiscards_Inc(device->dev_index);
return -1;
}
/* Is this a broadcast or multicast packet? If so some extra work must be
done to make sure that everyone gets it.
*/
dlayer = (DLAYER *)pack_addr->data_ptr;
if ( (memcmp(dlayer->dest, NET_Ether_Broadaddr, 6) == 0) ||
pack_addr->mem_flags & NET_MCAST )
{
/* This packet must be broadcast to all active nodes. This includes
each active virtual node and the NDIS driver. The following count
should include all nodes, including NDIS. The MNT descriptor at
index 0 will be NDIS.
*/
mnt_cpu_ptr = MNT_Header_Ptr->MNT_hdr_cpuDesc;
for (i = 0; i < VNET_Ncpu; i++)
{
/* If this descriptor is active and it is not ours, then count
it. Also go ahead and fill in part of the data structure that
will be used as the output to Multi Ringput. This will save some
effort later.
*/
if ((mnt_cpu_ptr->MNT_cd_active) && (i != MNT_ID))
{
/* Fill in the ring ptr field. This will be used when a ringput
is performed. */
mRingputInfo->Buf[count].RingPtr = ItoKval(
mnt_cpu_ptr->MNT_cd_pInputRing,
PMNT_RING,
NDISComMemStart);
/* Store the ID for this MNT process. This will be used later
to generate the event that will restart the MNT process. */
mGeneventOut->MNTID[count] = i;
count++;
}
/* Point to the next CPU descriptor. */
mnt_cpu_ptr++;
}
mRinggetInfo.Count = count;
mRinggetInfo.MemPtr = NDISComMemStart;
mRinggetInfo.RingPtr = ItoKval(MNT_Header_Ptr->MNT_hdr_pFreeRing,
PMNT_RING,
NDISComMemStart);
status = DeviceIoControl (hDriver,
(DWORD) IOCTL_MULTI_RINGGET,
&mRinggetInfo,
sizeof(IOCTL_OUT_MULTI_RINGGET),
mRinggetInput,
sizeof(ULONG) * (1 + mRinggetInfo.Count),
&cbReturned,
0);
/* If a status of failure is returned and no buffers were allocated,
then return failure. Note that it is possible for failure to be
returned and some (not all) buffers were also allocated. In the
later case we want to process those buffers that were allocated.
Otherwise, they will be lost.
*/
if ( (!status) && (!mRinggetInput->Count) )
{
SNMP_ifOutErrors_Inc(device->dev_index);
/* This is a complete failure, no buffers were allocated. */
NERRS_Log_Error (NERR_FATAL, __FILE__, __LINE__);
return -1;
}
else if (mRinggetInput->Count < mRinggetInfo.Count)
{
/* This was a partial failure. Some buffers were allocated. Go
ahead and process those that were allocated and log an error
message.
*/
}
for (i=0; i < mRinggetInput->Count; i++)
{
buf_node_ptr = ItoKval(mRinggetInput->BuffOffset[i],
PMNT_BUF_NODE,
CommonMemPtr);
/* Go ahead and fill in part of the structure that will be used as
input to MULTI_RINGPUT.
*/
mRingputInfo->Buf[i].BuffOffset = mRinggetInput->BuffOffset[i];
/* Copy the packet into the buffer chain. */
/* Do the parent buffer first */
memcpy((CHAR *)CommonMemPtr + (ULONG)buf_node_ptr->MNT_b_addr,
buf_ptr->data_ptr, buf_ptr->data_len);
/* Update the bytes copied. */
bytes_copied = buf_ptr->data_len;
/* Loop through the chain if needed and copy all buffers. */
while (buf_ptr->next_buffer != NU_NULL)
{
/* Move to the next buffer in the chain */
buf_ptr = buf_ptr->next_buffer;
/* Copy the data */
memcpy((CHAR *)CommonMemPtr + (ULONG)buf_node_ptr->MNT_b_addr + bytes_copied,
buf_ptr->mem_packet, buf_ptr->data_len);
/* Update the bytes copied. */
bytes_copied += buf_ptr->data_len;
} /* end while there are buffers in the chain */
buf_node_ptr -> MNT_b_len = (UINT16) pack_addr->mem_total_data_len;
/* Reset the buffer pointer */
buf_ptr = pack_addr;
}
/* Initialize the output to MULTI_RINGPUT. Recall that the array of MNT
ID's and the array of MNT_RING ptrs were filled in up above.
*/
mRingputInfo->MemPtr = NDISComMemStart;
mRingputInfo->Count = mRinggetInput->Count;
status = DeviceIoControl (hDriver,
(DWORD) IOCTL_MULTI_RINGPUT,
mRingputInfo,
sizeof(ULONG) * (2 + (2 * mRingputInfo->Count)),
&successCount,
sizeof(ULONG),
&cbReturned,
0);
/* successCount now contains the number of buffers that were successfully
put. Make sure all of them were put back. */
if(successCount < mRingputInfo->Count)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -