3 Copyright (c) 1992-2000 Microsoft Corporation
11 Ndis Intermediate Miniport driver sample. This is a passthru driver.
27 #pragma NDIS_INIT_FUNCTION(DriverEntry)
29 NDIS_HANDLE ProtHandle = NULL;
30 NDIS_HANDLE DriverHandle = NULL;
31 NDIS_MEDIUM MediumArray[4] =
33 NdisMedium802_3, // Ethernet
34 NdisMedium802_5, // Token-ring
35 NdisMediumFddi, // Fddi
36 NdisMediumWan // NDISWAN
39 NDIS_SPIN_LOCK GlobalLock;
41 PADAPT pAdaptList = NULL;
42 LONG MiniportCount = 0;
44 NDIS_HANDLE NdisWrapperHandle;
47 // To support ioctls from user-mode:
51 #define STR(x) STR2(x)
52 #define DOSPREFIX "\\DosDevices\\"
53 #define NTPREFIX "\\Device\\"
54 #define WIDEN2(x) L ## x
55 #define WIDEN(x) WIDEN2(x)
56 #define LINKNAME_STRING WIDEN(DOSPREFIX) WIDEN(STR(MODULENAME))
57 #define NTDEVICE_STRING WIDEN(NTPREFIX) WIDEN(STR(MODULENAME))
58 #define PROTOCOLNAME_STRING WIDEN(STR(MODULENAME))
60 NDIS_HANDLE NdisDeviceHandle = NULL;
61 PDEVICE_OBJECT ControlDeviceObject = NULL;
65 PS_DEVICE_STATE_READY = 0, // ready for create/delete
66 PS_DEVICE_STATE_CREATING, // create operation in progress
67 PS_DEVICE_STATE_DELETING // delete operation in progress
68 } ControlDeviceState = PS_DEVICE_STATE_READY;
74 IN PDRIVER_OBJECT DriverObject,
75 IN PUNICODE_STRING RegistryPath
81 First entry point to be called, when this driver is loaded.
82 Register with NDIS as an intermediate driver.
86 DriverObject - pointer to the system's driver object structure
89 RegistryPath - system's registry path for this driver
93 STATUS_SUCCESS if all initialization is successful, STATUS_XXX
99 NDIS_PROTOCOL_CHARACTERISTICS PChars;
100 NDIS_MINIPORT_CHARACTERISTICS MChars;
103 Status = NDIS_STATUS_SUCCESS;
104 NdisAllocateSpinLock(&GlobalLock);
106 NdisMInitializeWrapper(&NdisWrapperHandle, DriverObject, RegistryPath, NULL);
111 // Register the miniport with NDIS. Note that it is the miniport
112 // which was started as a driver and not the protocol. Also the miniport
113 // must be registered prior to the protocol since the protocol's BindAdapter
114 // handler can be initiated anytime and when it is, it must be ready to
115 // start driver instances.
118 NdisZeroMemory(&MChars, sizeof(NDIS_MINIPORT_CHARACTERISTICS));
120 MChars.MajorNdisVersion = PASSTHRU_MAJOR_NDIS_VERSION;
121 MChars.MinorNdisVersion = PASSTHRU_MINOR_NDIS_VERSION;
123 MChars.InitializeHandler = MPInitialize;
124 MChars.QueryInformationHandler = MPQueryInformation;
125 MChars.SetInformationHandler = MPSetInformation;
126 MChars.ResetHandler = NULL;
127 MChars.TransferDataHandler = MPTransferData;
128 MChars.HaltHandler = MPHalt;
129 #ifdef NDIS51_MINIPORT
130 MChars.CancelSendPacketsHandler = MPCancelSendPackets;
131 MChars.PnPEventNotifyHandler = MPDevicePnPEvent;
132 MChars.AdapterShutdownHandler = MPAdapterShutdown;
133 #endif // NDIS51_MINIPORT
136 // We will disable the check for hang timeout so we do not
137 // need a check for hang handler!
139 MChars.CheckForHangHandler = NULL;
140 MChars.ReturnPacketHandler = MPReturnPacket;
143 // Either the Send or the SendPackets handler should be specified.
144 // If SendPackets handler is specified, SendHandler is ignored
146 MChars.SendHandler = MPSend; // IPFW: use MPSend, not SendPackets
147 MChars.SendPacketsHandler = NULL;
149 Status = NdisIMRegisterLayeredMiniport(NdisWrapperHandle,
153 if (Status != NDIS_STATUS_SUCCESS)
159 NdisMRegisterUnloadHandler(NdisWrapperHandle, PtUnload);
163 // Now register the protocol.
165 NdisZeroMemory(&PChars, sizeof(NDIS_PROTOCOL_CHARACTERISTICS));
166 PChars.MajorNdisVersion = PASSTHRU_PROT_MAJOR_NDIS_VERSION;
167 PChars.MinorNdisVersion = PASSTHRU_PROT_MINOR_NDIS_VERSION;
170 // Make sure the protocol-name matches the service-name
171 // (from the INF) under which this protocol is installed.
172 // This is needed to ensure that NDIS can correctly determine
173 // the binding and call us to bind to miniports below.
175 NdisInitUnicodeString(&Name, PROTOCOLNAME_STRING); // Protocol name
177 PChars.OpenAdapterCompleteHandler = PtOpenAdapterComplete;
178 PChars.CloseAdapterCompleteHandler = PtCloseAdapterComplete;
179 PChars.SendCompleteHandler = PtSendComplete;
180 PChars.TransferDataCompleteHandler = PtTransferDataComplete;
182 PChars.ResetCompleteHandler = PtResetComplete;
183 PChars.RequestCompleteHandler = PtRequestComplete;
184 PChars.ReceiveHandler = PtReceive;
185 PChars.ReceiveCompleteHandler = PtReceiveComplete;
186 PChars.StatusHandler = PtStatus;
187 PChars.StatusCompleteHandler = PtStatusComplete;
188 PChars.BindAdapterHandler = PtBindAdapter;
189 PChars.UnbindAdapterHandler = PtUnbindAdapter;
190 PChars.UnloadHandler = PtUnloadProtocol;
192 PChars.ReceivePacketHandler = PtReceivePacket;
193 PChars.PnPEventHandler= PtPNPHandler;
195 NdisRegisterProtocol(&Status,
198 sizeof(NDIS_PROTOCOL_CHARACTERISTICS));
200 if (Status != NDIS_STATUS_SUCCESS)
202 NdisIMDeregisterLayeredMiniport(DriverHandle);
206 NdisIMAssociateMiniport(DriverHandle, ProtHandle);
210 if (Status != NDIS_STATUS_SUCCESS)
212 NdisTerminateWrapper(NdisWrapperHandle, NULL);
215 ipfw_module_init(); // IPFW - start the system
229 Register an ioctl interface - a device object to be used for this
230 purpose is created by NDIS when we call NdisMRegisterDevice.
232 This routine is called whenever a new miniport instance is
233 initialized. However, we only create one global device object,
234 when the first miniport instance is initialized. This routine
235 handles potential race conditions with PtDeregisterDevice via
236 the ControlDeviceState and MiniportCount variables.
238 NOTE: do not call this from DriverEntry; it will prevent the driver
239 from being unloaded (e.g. on uninstall).
247 NDIS_STATUS_SUCCESS if we successfully register a device object.
251 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
252 UNICODE_STRING DeviceName;
253 UNICODE_STRING DeviceLinkUnicodeString;
254 PDRIVER_DISPATCH DispatchTable[IRP_MJ_MAXIMUM_FUNCTION+1];
256 DBGPRINT(("==>PtRegisterDevice\n"));
258 NdisAcquireSpinLock(&GlobalLock);
262 if (1 == MiniportCount)
264 ASSERT(ControlDeviceState != PS_DEVICE_STATE_CREATING);
267 // Another thread could be running PtDeregisterDevice on
268 // behalf of another miniport instance. If so, wait for
271 while (ControlDeviceState != PS_DEVICE_STATE_READY)
273 NdisReleaseSpinLock(&GlobalLock);
275 NdisAcquireSpinLock(&GlobalLock);
278 ControlDeviceState = PS_DEVICE_STATE_CREATING;
280 NdisReleaseSpinLock(&GlobalLock);
283 NdisZeroMemory(DispatchTable, (IRP_MJ_MAXIMUM_FUNCTION+1) * sizeof(PDRIVER_DISPATCH));
285 DispatchTable[IRP_MJ_CREATE] = PtDispatch;
286 DispatchTable[IRP_MJ_CLEANUP] = PtDispatch;
287 DispatchTable[IRP_MJ_CLOSE] = PtDispatch;
288 // IPFW we use DevIoControl ?
289 DispatchTable[IRP_MJ_DEVICE_CONTROL] = DevIoControl;
292 NdisInitUnicodeString(&DeviceName, NTDEVICE_STRING);
293 NdisInitUnicodeString(&DeviceLinkUnicodeString, LINKNAME_STRING);
296 // Create a device object and register our dispatch handlers
299 Status = NdisMRegisterDevice(
302 &DeviceLinkUnicodeString,
304 &ControlDeviceObject,
308 NdisAcquireSpinLock(&GlobalLock);
310 ControlDeviceState = PS_DEVICE_STATE_READY;
313 NdisReleaseSpinLock(&GlobalLock);
315 DBGPRINT(("<==PtRegisterDevice: %x\n", Status));
323 IN PDEVICE_OBJECT DeviceObject,
329 Process IRPs sent to this device.
333 DeviceObject - pointer to a device object
334 Irp - pointer to an I/O Request Packet
338 NTSTATUS - STATUS_SUCCESS always - change this when adding
339 real code to handle ioctls.
343 PIO_STACK_LOCATION irpStack;
344 NTSTATUS status = STATUS_SUCCESS;
346 UNREFERENCED_PARAMETER(DeviceObject);
348 DBGPRINT(("==>Pt Dispatch\n"));
349 irpStack = IoGetCurrentIrpStackLocation(Irp);
352 switch (irpStack->MajorFunction)
363 case IRP_MJ_DEVICE_CONTROL:
365 // Add code here to handle ioctl commands sent to passthru.
372 Irp->IoStatus.Status = status;
373 IoCompleteRequest(Irp, IO_NO_INCREMENT);
375 DBGPRINT(("<== Pt Dispatch\n"));
390 Deregister the ioctl interface. This is called whenever a miniport
391 instance is halted. When the last miniport instance is halted, we
392 request NDIS to delete the device object
396 NdisDeviceHandle - Handle returned by NdisMRegisterDevice
400 NDIS_STATUS_SUCCESS if everything worked ok
404 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
406 DBGPRINT(("==>PassthruDeregisterDevice\n"));
408 NdisAcquireSpinLock(&GlobalLock);
410 ASSERT(MiniportCount > 0);
414 if (0 == MiniportCount)
417 // All miniport instances have been halted. Deregister
418 // the control device.
421 ASSERT(ControlDeviceState == PS_DEVICE_STATE_READY);
424 // Block PtRegisterDevice() while we release the control
425 // device lock and deregister the device.
427 ControlDeviceState = PS_DEVICE_STATE_DELETING;
429 NdisReleaseSpinLock(&GlobalLock);
431 if (NdisDeviceHandle != NULL)
433 Status = NdisMDeregisterDevice(NdisDeviceHandle);
434 NdisDeviceHandle = NULL;
437 NdisAcquireSpinLock(&GlobalLock);
438 ControlDeviceState = PS_DEVICE_STATE_READY;
441 NdisReleaseSpinLock(&GlobalLock);
443 DBGPRINT(("<== PassthruDeregisterDevice: %x\n", Status));
450 IN PDRIVER_OBJECT DriverObject
453 // PassThru driver unload function
456 UNREFERENCED_PARAMETER(DriverObject);
458 DBGPRINT(("PtUnload: entered\n"));
462 NdisIMDeregisterLayeredMiniport(DriverHandle);
464 NdisFreeSpinLock(&GlobalLock);
466 ipfw_module_exit(); // IPFW unloading dummynet
468 DBGPRINT(("PtUnload: done!\n"));