📄 nnetdrv.c
字号:
* sshort : not used in this driver.
* UINT32 : contains a pointer to the local hostname.
* UINT32 : not used in this driver.
*
* OUTPUTS
*
* sshort : NU_SUCCESS if everything goes as planned, a negative number
* otherwise.
*
******************************************************************************/
STATUS VDRV_Open (UINT8 *ether_addr, DV_DEVICE_ENTRY *device)
{
CHAR *aInterfaceType[] = {"Internal",
"Isa",
"Eisa",
"MicroChannel",
"TurboChannel" };
HKEY hKey;
UINT stat;
DWORD valueDWORD, dataSize = 4;
PHYSICAL_MEMORY_INFO pmi;
DWORD cbReturned;
VOID *pointer;
INT i;
SNMP_ifDescr(device->dev_index, "VNET Driver: Software revision 1.1");
SNMP_ifType(device->dev_index, 6);
SNMP_ifMtu(device->dev_index, device->dev_mtu);
SNMP_ifSpeed(device->dev_index, 10000000); /* 10 Mbps */
/* First retrieve the virtual address of the common memory buffer.
* Later this address will be mapped into our own address space. */
stat = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
"SYSTEM\\CURRENTCONTROLSET\\SERVICES\\NDISMNT\\COMMEMCONFIG",
0, KEY_ALL_ACCESS, &hKey);
/* Read the starting address of the commomn memory area. */
dataSize = sizeof(pmi.CommonMemAddr);
stat = RegQueryValueEx(hKey, "COMMEMSTART", NULL, &valueDWORD,
(UINT8 *)&pmi.CommonMemAddr,
&dataSize);
/* Read the size of the commomn memory area. */
dataSize = sizeof(pmi.Length);
stat = RegQueryValueEx(hKey, "COMMEMSIZE", NULL, &valueDWORD,
(UINT8 *)&pmi.Length,
&dataSize);
pmi.InterfaceType = (INTERFACE_TYPE) 0; // Internal
pmi.BusNumber = (ULONG) 0; // Standard 80x86
pmi.AddressSpace = (LONG) 0; // Memory
NDISComMemStart = pmi.CommonMemAddr;
/* Get a handle to the virtual Nucleus NET ethernet driver. */
hDriver = CreateFile ("\\\\.\\VNET", GENERIC_READ | GENERIC_WRITE,
0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED,
NULL);
if (hDriver == INVALID_HANDLE_VALUE) {
return -1;
}
/* Try to map the common memory area into the local address space. */
if (!DeviceIoControl (hDriver,
(DWORD) IOCTL_MAP_COMMON_MEMORY_AREA,
&pmi,
sizeof(PHYSICAL_MEMORY_INFO),
&CommonMemPtr,
sizeof(PVOID),
&cbReturned,
0
) )
{
return -1;
}
/* So far so good. Now check to see if NDIS has initialized the common
memory area. Note that the NDIS driver must execute first. If NDIS
has not executed then exit.
*/
if (CommonMemPtr->MNT_an_ready != MNT_READY)
{
return -1;
}
/* The MNT anchor was ready. Now verify that the MNT header was also
initialized by NDIS. Note that the MNT_an_pHdr field in the anchor
structure is not really a pointer to the MNT_HEADER, but an offset from
the beginning of the common memory area to the MNT_HEADER.
*/
MNT_Header_Ptr = ItoKval(CommonMemPtr->MNT_an_pHdr,
PMNT_HEADER,
CommonMemPtr);
if (MNT_Header_Ptr->MNT_hdr_ready != MNT_READY)
{
return -1;
}
/* Copy the number of possible MNT processes. */
if((VNET_Ncpu = MNT_Header_Ptr->MNT_hdr_ncpu) <= 0)
{
return -1;
}
/* Lookup the ID used by this virtual node. */
if (VDRV_Lookup_ID(device->dev_net_if_name) != NU_SUCCESS)
return -1;
/* Find an unused cpu desc in the common memory. */
if (VDRV_Init_MNT_DESC(MNT_Header_Ptr, MNT_ID) != NU_SUCCESS)
{
return -1;
}
if(VDRV_Lookup_Default_Gateway(device) != NU_SUCCESS)
return -1;
if(VDRV_Lookup_Base_Ether() != NU_SUCCESS)
return -1;
/* Initialize our ethernet address. The first 5 octets of the ethernet
address are all 0. */
for(i=0; i<5; i++)
Ether_Addr[i] = 0;
/* The last octet of the ethernet address is the our ID + the base ether. */
Ether_Addr[5] = (CHAR)((CHAR)MNT_ID + VNET_BaseEtherAddr);
NU_Get_Address(ether_addr, 0, 0);
/* Initialize the Physical address in the MIB. */
SNMP_ifPhysAddress(device->dev_index, ether_addr);
/* Initialize the vector table entry for the virtual network ISR. For other
simulated interrupts (timer, uart) this is done in INT_Initialize. I
chose to do it here so that MNT would not need to be modified to
accomodate the virtual network. */
INT_Vector_Table[VNETPRIO] = VDRV_ISR;
/* Initialize the device vector field. It will be used later in the
receive ISR. The vector is used to detect which device a packet is
received on. */
device->dev_vect = VNETPRIO;
/* Register the recive ISR with the OS. */
if (NU_Register_LISR(VNETPRIO, VDRV_ISR, &oldlisr) != NU_SUCCESS)
return (-1);
/* create the HISR for handleing the simulated interrupt. */
if (NU_Allocate_Memory (&System_Memory,
&pointer,
2000,
NU_NO_SUSPEND) != NU_SUCCESS)
{
NERRS_Log_Error (NERR_FATAL, __FILE__, __LINE__);
}
if (NU_Create_HISR (&Recv_HISR, "ETHRHISR",
VDRV_Recv_HISR,
0, pointer, 2000)!= NU_SUCCESS)
{
NERRS_Log_Error (NERR_FATAL, __FILE__, __LINE__);
}
/* Create the NT thread that will retrieve arriving packets. The thread's
entry point is NU_Recv_Packet.
*/
Recv_Thread_ID.thread_hdl = CreateThread (NULL, 0,
(LPTHREAD_START_ROUTINE) NU_Recv_Packet,
NULL, 0, &Recv_Thread_ID.thread_id);
if (Recv_Thread_ID.thread_hdl == NULL) {
return(-1);
}
/* Allocate memory to for the input and output buffers to the
DeviceIoControl call. These buffers are only used in VDRV_Xmit_Packet.
Rather than allocate the memory each time VDRV_Xmit_Packet is called I
chose to allocate them once here and reuse them each time VDRV_Xmit_Packet
is called. The memory is deallocated in NU_Close_Driver.
*/
if (NU_Allocate_Memory(&System_Memory, &mRinggetInput,
sizeof(ULONG) * (1 + VNET_Ncpu),
NU_NO_SUSPEND) != NU_SUCCESS)
return (-1);
if (NU_Allocate_Memory(&System_Memory, &mRingputInfo,
sizeof(ULONG) * (2 + (2 * VNET_Ncpu)),
NU_NO_SUSPEND) != NU_SUCCESS)
return (-1);
if (NU_Allocate_Memory(&System_Memory, &mGeneventOut,
sizeof(ULONG) * (3 + VNET_Ncpu),
NU_NO_SUSPEND) != NU_SUCCESS)
return (-1);
/* Set the current status to operational. */
SNMP_ifAdminStatus(device->dev_index, 1);
SNMP_ifOperStatus(device->dev_index, 1);
return NU_SUCCESS;
} /* VDRV_Open */
/******************************************************************************
* FUNCTION
*
* NU_Close_Driver
*
* DESCRIPTION
*
* This closes the driver. It reverses many of the actions performed by
* VDRV_Open. After execution of this function packets can no longer be
* transmitted or recieved.
*
*AUTHOR
*
* Glen Johnson
*
* INPUTS
*
* none
*
* OUTPUTS
*
* sshort : NU_SUCCESS if everything goes as planned, a negative number
* otherwise.
*
******************************************************************************/
STATUS NU_Close_Driver(VOID)
{
NU_Deallocate_Memory(mRinggetInput);
NU_Deallocate_Memory(mRingputInfo);
NU_Deallocate_Memory(mGeneventOut);
VDRV_Driver_Closing = 1;
if(CloseHandle(hDriver) != TRUE)
return(-1);
else
return (NU_SUCCESS);
}/* end NU_Close_Driver */
/******************************************************************************
* FUNCTION
*
* NU_Recv_Packet
*
* DESCRIPTION
*
* This function is the entry point for an NT thread. Upon executing this
* thread will check to see if there are any packets in the receive ring.
* If not it waits for an NT event to be sent indicating that an packet has
* arrived. The event is our simulated interrupt. When the event oocurs
* The ISR will be called to pull tha packet off of the network. The
* process is repeated until the driver closes.
*
* AUTHOR
*
* Glen Johnson
*
* INPUTS
*
* No inputs to this function.
*
* OUTPUTS
*
* none
*
******************************************************************************/
VOID NU_Recv_Packet (LPDWORD unusedParam)
{
HANDLE hEvt;
BOOL status;
DWORD dwData;
OVERLAPPED ovl;
IOCTL_OUT_GETEVENT geteventInfo;
INT oldlevel;
/* Create the event that will be used to signal the arrival of a packet. */
hEvt = CreateEvent (NULL, TRUE, FALSE, NULL);
if (!hEvt) {
demo_exit(0);
}
ovl.hEvent = hEvt;
/* Go ahead and raise the interrupt level, just in case there may be
something waiting when we get here. This should not be the case.
*/
/* If there is already an interrupt service routine executing that is a
higher priority than that of the virtual network then suspend. This
thread will be restarted in that "ISR" is complete.
*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -