2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS NDIS library
4 * FILE: ndis/miniport.c
5 * PURPOSE: Routines used by NDIS miniport drivers
6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
8 * CSH 01/08-2000 Created
13 /* Number of medias we know */
14 #define MEDIA_ARRAY_SIZE 15
16 static NDIS_MEDIUM MediaArray
[MEDIA_ARRAY_SIZE
] = {
24 NdisMediumArcnet878_2
,
26 NdisMediumWirelessWan
,
35 LIST_ENTRY MiniportListHead
;
36 KSPIN_LOCK MiniportListLock
;
37 LIST_ENTRY AdapterListHead
;
38 KSPIN_LOCK AdapterListLock
;
44 * FUNCTION: Worker function for MiniportXxx functions
46 * Context = Pointer to context information (MINIPORT_DRIVER)
52 PLOGICAL_ADAPTER
MiniLocateDevice(
53 PNDIS_STRING AdapterName
)
55 * FUNCTION: Returns the logical adapter object for a specific adapter
57 * AdapterName = Pointer to name of adapter
59 * Pointer to logical adapter object, or NULL if none was found.
60 * If found, the adapter is referenced for the caller. The caller
61 * is responsible for dereferencing after use
66 PLIST_ENTRY CurrentMEntry
;
67 PLIST_ENTRY CurrentAEntry
;
68 PMINIPORT_DRIVER Miniport
;
69 PLOGICAL_ADAPTER Adapter
;
71 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Called. AdapterName (0x%X).\n", AdapterName
));
73 KeAcquireSpinLock(&MiniportListLock
, &OldIrql1
);
74 CurrentMEntry
= MiniportListHead
.Flink
;
75 while (CurrentMEntry
!= &MiniportListHead
) {
76 Miniport
= CONTAINING_RECORD(CurrentMEntry
, MINIPORT_DRIVER
, ListEntry
);
78 KeAcquireSpinLock(&AdapterListLock
, &OldIrql2
);
79 CurrentAEntry
= AdapterListHead
.Flink
;
80 while (CurrentAEntry
!= &AdapterListHead
) {
81 Adapter
= CONTAINING_RECORD(CurrentAEntry
, LOGICAL_ADAPTER
, ListEntry
);
83 if (RtlCompareUnicodeString(AdapterName
, &Adapter
->DeviceName
, TRUE
) == 0) {
84 ReferenceObject(Adapter
);
85 KeReleaseSpinLock(&AdapterListLock
, OldIrql2
);
86 KeReleaseSpinLock(&MiniportListLock
, OldIrql1
);
90 CurrentAEntry
= CurrentAEntry
->Flink
;
92 KeReleaseSpinLock(&AdapterListLock
, OldIrql2
);
94 CurrentMEntry
= CurrentMEntry
->Flink
;
96 KeReleaseSpinLock(&MiniportListLock
, OldIrql1
);
103 MiniQueryInformation(
104 PLOGICAL_ADAPTER Adapter
,
109 * FUNCTION: Queries a logical adapter for properties
111 * Adapter = Pointer to the logical adapter object to query
112 * Oid = Specifies the oid to query for
113 * Size = If non-zero overrides the length in the adapter object
114 * BytesWritten = Address of buffer to place number of bytes written
116 * Status of operation
118 * If the specified buffer is too small, a new buffer is allocated,
119 * and the query is attempted again
122 NDIS_STATUS NdisStatus
;
125 if (Adapter
->QueryBufferLength
== 0) {
126 Adapter
->QueryBuffer
= ExAllocatePool(NonPagedPool
, 32);
128 if (!Adapter
->QueryBuffer
) {
129 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
130 return NDIS_STATUS_RESOURCES
;
133 Adapter
->QueryBufferLength
= 32;
136 BytesNeeded
= (Size
= 0)? Adapter
->QueryBufferLength
: Size
;
138 NdisStatus
= (*Adapter
->Miniport
->Chars
.QueryInformationHandler
)(
139 Adapter
, Oid
, &BytesNeeded
,
140 Adapter
->QueryBufferLength
,
141 BytesWritten
, &BytesNeeded
);
143 if ((NT_SUCCESS(NdisStatus
)) || (NdisStatus
== NDIS_STATUS_PENDING
)) {
144 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Miniport returned status (0x%X).\n", NdisStatus
));
148 if (NdisStatus
== NDIS_STATUS_INVALID_LENGTH
) {
149 ExFreePool(Adapter
->QueryBuffer
);
151 Adapter
->QueryBufferLength
+= BytesNeeded
;
152 Adapter
->QueryBuffer
= ExAllocatePool(
153 NonPagedPool
, Adapter
->QueryBufferLength
);
155 if (!Adapter
->QueryBuffer
) {
156 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
157 return NDIS_STATUS_RESOURCES
;
160 NdisStatus
= (*Adapter
->Miniport
->Chars
.QueryInformationHandler
)(
161 Adapter
, Oid
, Adapter
->QueryBuffer
, Size
, BytesWritten
, &BytesNeeded
);
171 IN NDIS_HANDLE LogHandle
)
180 IN NDIS_HANDLE MiniportAdapterHandle
,
182 OUT PNDIS_HANDLE LogHandle
)
186 return NDIS_STATUS_FAILURE
;
192 NdisMDeregisterAdapterShutdownHandler(
193 IN NDIS_HANDLE MiniportHandle
)
202 IN NDIS_HANDLE LogHandle
)
211 IN NDIS_HANDLE MiniportAdapterHandle
,
212 IN NDIS_STATUS GeneralStatus
,
213 IN PVOID StatusBuffer
,
214 IN UINT StatusBufferSize
)
222 NdisMIndicateStatusComplete(
223 IN NDIS_HANDLE MiniportAdapterHandle
)
231 NdisInitializeWrapper(
232 OUT PNDIS_HANDLE NdisWrapperHandle
,
233 IN PVOID SystemSpecific1
,
234 IN PVOID SystemSpecific2
,
235 IN PVOID SystemSpecific3
)
237 * FUNCTION: Notifies the NDIS library that a new miniport is initializing
239 * NdisWrapperHandle = Address of buffer to place NDIS wrapper handle
240 * SystemSpecific1 = Pointer to the driver's driver object
241 * SystemSpecific2 = Pointer to the driver's registry path
242 * SystemSpecific3 = Always NULL
245 PMINIPORT_DRIVER Miniport
;
247 Miniport
= ExAllocatePool(NonPagedPool
, sizeof(MINIPORT_DRIVER
));
249 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
250 *NdisWrapperHandle
= NULL
;
254 RtlZeroMemory(Miniport
, sizeof(MINIPORT_DRIVER
));
256 KeInitializeSpinLock(&Miniport
->Lock
);
258 Miniport
->RefCount
= 1;
260 ExInitializeWorkItem(&Miniport
->WorkItem
, MiniportWorker
, Miniport
);
262 Miniport
->DriverObject
= (PDRIVER_OBJECT
)SystemSpecific1
;
263 /* FIXME: Copy RegistryPath */
264 //Miniport->RegistryPath = SystemSpecific2;
266 /* Put miniport in global miniport list */
267 ExInterlockedInsertTailList(&MiniportListHead
,
268 &Miniport
->ListEntry
,
271 *NdisWrapperHandle
= Miniport
;
277 NdisMRegisterAdapterShutdownHandler(
278 IN NDIS_HANDLE MiniportHandle
,
279 IN PVOID ShutdownContext
,
280 IN ADAPTER_SHUTDOWN_HANDLER ShutdownHandler
)
288 NdisMRegisterMiniport(
289 IN NDIS_HANDLE NdisWrapperHandle
,
290 IN PNDIS_MINIPORT_CHARACTERISTICS MiniportCharacteristics
,
291 IN UINT CharacteristicsLength
)
293 * FUNCTION: Registers a miniport's MiniportXxx entry points with the NDIS library
295 * NdisWrapperHandle = Pointer to handle returned by NdisMInitializeWrapper
296 * MiniportCharacteristics = Pointer to a buffer with miniport characteristics
297 * CharacteristicsLength = Number of bytes in characteristics buffer
299 * Status of operation
304 NDIS_STATUS NdisStatus
;
305 UINT SelectedMediumIndex
;
306 PLOGICAL_ADAPTER Adapter
;
307 PMINIPORT_DRIVER Miniport
= GET_MINIPORT_DRIVER(NdisWrapperHandle
);
309 switch (MiniportCharacteristics
->MajorNdisVersion
) {
311 MinSize
= sizeof(NDIS30_MINIPORT_CHARACTERISTICS
);
315 MinSize
= sizeof(NDIS40_MINIPORT_CHARACTERISTICS
);
319 MinSize
= sizeof(NDIS50_MINIPORT_CHARACTERISTICS
);
323 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Bad miniport characteristics version.\n"));
324 return NDIS_STATUS_BAD_VERSION
;
327 if (CharacteristicsLength
< MinSize
) {
328 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Bad miniport characteristics.\n"));
329 return NDIS_STATUS_BAD_CHARACTERISTICS
;
332 /* Check if mandatory MiniportXxx functions are specified */
333 if ((!MiniportCharacteristics
->HaltHandler
) ||
334 (!MiniportCharacteristics
->InitializeHandler
)||
335 (!MiniportCharacteristics
->QueryInformationHandler
) ||
336 (!MiniportCharacteristics
->ResetHandler
) ||
337 (!MiniportCharacteristics
->SetInformationHandler
)) {
338 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Bad miniport characteristics.\n"));
339 return NDIS_STATUS_BAD_CHARACTERISTICS
;
342 if (MiniportCharacteristics
->MajorNdisVersion
== 0x03) {
343 if (!MiniportCharacteristics
->SendHandler
) {
344 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Bad miniport characteristics.\n"));
345 return NDIS_STATUS_BAD_CHARACTERISTICS
;
347 } else if (MiniportCharacteristics
->MajorNdisVersion
>= 0x04) {
349 if ((!MiniportCharacteristics
->SendHandler
) &&
350 (!MiniportCharacteristics
->SendPacketsHandler
)) {
351 NDIS_DbgPrint(DEBUG_MINIPORT
, ("Bad miniport characteristics.\n"));
352 return NDIS_STATUS_BAD_CHARACTERISTICS
;
356 RtlCopyMemory(&Miniport
->Chars
, MiniportCharacteristics
, MinSize
);
358 Adapter
= ExAllocatePool(NonPagedPool
, sizeof(LOGICAL_ADAPTER
));
360 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
361 return NDIS_STATUS_RESOURCES
;
364 RtlZeroMemory(Adapter
, sizeof(LOGICAL_ADAPTER
));
365 KeInitializeSpinLock(&Adapter
->Lock
);
366 Adapter
->RefCount
= 1;
367 Adapter
->Miniport
= Miniport
;
369 /* Create the device object for this adapter */
370 /* FIXME: Use GUIDs */
371 RtlInitUnicodeString(&Adapter
->DeviceName
, L
"\\Device\\ne2000");
372 Status
= IoCreateDevice(Miniport
->DriverObject
, 0, &Adapter
->DeviceName
,
373 FILE_DEVICE_PHYSICAL_NETCARD
, 0, FALSE
, &Adapter
->DeviceObject
);
374 if (!NT_SUCCESS(Status
)) {
375 NDIS_DbgPrint(MIN_TRACE
, ("Could not create device object.\n"));
377 return NDIS_STATUS_FAILURE
;
380 /* Put adapter in adapter list for this miniport */
381 ExInterlockedInsertTailList(&Miniport
->AdapterListHead
,
382 &Adapter
->MiniportListEntry
,
385 /* Put adapter in global adapter list */
386 ExInterlockedInsertTailList(&AdapterListHead
,
390 /* Call MiniportInitialize */
391 (*Miniport
->Chars
.InitializeHandler
)(
393 &SelectedMediumIndex
,
397 NULL
/* FIXME: WrapperConfigurationContext */);
399 return NDIS_STATUS_SUCCESS
;
406 IN NDIS_HANDLE MiniportAdapterHandle
,
407 IN NDIS_STATUS Status
,
408 IN BOOLEAN AddressingReset
)
417 IN NDIS_HANDLE MiniportAdapterHandle
,
418 IN PNDIS_PACKET Packet
,
419 IN NDIS_STATUS Status
)
427 NdisMSendResourcesAvailable(
428 IN NDIS_HANDLE MiniportAdapterHandle
)
437 IN NDIS_HANDLE MiniportAdapterHandle
,
438 IN NDIS_HANDLE MiniportAdapterContext
,
439 IN BOOLEAN BusMaster
,
440 IN NDIS_INTERFACE_TYPE AdapterType
)
442 * FUNCTION: Informs the NDIS library of significant features of the caller's NIC
444 * MiniportAdapterHandle = Handle input to MiniportInitialize
445 * MiniportAdapterContext = Pointer to context information
446 * BusMaster = Specifies TRUE if the caller's NIC is a busmaster DMA device
447 * AdapterType = Specifies the I/O bus interface of the caller's NIC
450 PLOGICAL_ADAPTER Adapter
= GET_LOGICAL_ADAPTER(MiniportAdapterHandle
);
452 Adapter
->MiniportAdapterContext
= MiniportAdapterHandle
;
453 Adapter
->Attributes
= BusMaster
? NDIS_ATTRIBUTE_BUS_MASTER
: 0;
454 Adapter
->AdapterType
= AdapterType
;
455 Adapter
->AttributesSet
= TRUE
;
461 NdisMSetAttributesEx(
462 IN NDIS_HANDLE MiniportAdapterHandle
,
463 IN NDIS_HANDLE MiniportAdapterContext
,
464 IN UINT CheckForHangTimeInSeconds OPTIONAL
,
465 IN ULONG AttributeFlags
,
466 IN NDIS_INTERFACE_TYPE AdapterType
)
468 * FUNCTION: Informs the NDIS library of significant features of the caller's NIC
470 * MiniportAdapterHandle = Handle input to MiniportInitialize
471 * MiniportAdapterContext = Pointer to context information
472 * CheckForHangTimeInSeconds = Specifies interval in seconds at which
473 * MiniportCheckForHang should be called
474 * AttributeFlags = Bitmask that indicates specific attributes
475 * AdapterType = Specifies the I/O bus interface of the caller's NIC
485 IN ULONG MicrosecondsToSleep
)
493 NdisMSynchronizeWithInterrupt(
494 IN PNDIS_MINIPORT_INTERRUPT Interrupt
,
495 IN PVOID SynchronizeFunction
,
496 IN PVOID SynchronizeContext
)
507 IN NDIS_HANDLE LogHandle
,
509 IN UINT LogBufferSize
)
513 return NDIS_STATUS_FAILURE
;
519 NdisTerminateWrapper(
520 IN NDIS_HANDLE NdisWrapperHandle
,
521 IN PVOID SystemSpecific
)
523 * FUNCTION: Releases resources allocated by a call to NdisMInitializeWrapper
525 * NdisWrapperHandle = Handle returned by NdisMInitializeWrapper
526 * SystemSpecific = Always NULL
529 ExFreePool(NdisWrapperHandle
);