2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS NDIS library
4 * FILE: ndis/protocol.c
5 * PURPOSE: Routines used by NDIS protocol drivers
6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
7 * Vizzini (vizzini@plasmic.com)
9 * CSH 01/08-2000 Created
10 * 09-13-2003 Vizzini Updates for SendPackets support
16 #define SERVICES_KEY L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\"
17 #define LINKAGE_KEY L"\\Linkage"
18 #define PARAMETERS_KEY L"\\Parameters\\"
20 LIST_ENTRY ProtocolListHead
;
21 KSPIN_LOCK ProtocolListLock
;
25 typedef struct _DMA_CONTEXT
{
26 PLOGICAL_ADAPTER Adapter
;
28 } DMA_CONTEXT
, *PDMA_CONTEXT
;
32 NET_PNP_EVENT_CODE EventCode
,
34 ULONG EventBufferLength
)
36 PNET_PNP_EVENT PnPEvent
;
38 PnPEvent
= ExAllocatePool(PagedPool
, sizeof(NET_PNP_EVENT
));
40 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources\n"));
44 RtlZeroMemory(PnPEvent
, sizeof(NET_PNP_EVENT
));
46 PnPEvent
->NetEvent
= EventCode
;
48 if (EventBuffer
!= NULL
)
50 PnPEvent
->Buffer
= ExAllocatePool(PagedPool
, EventBufferLength
);
51 if (!PnPEvent
->Buffer
)
53 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources\n"));
58 PnPEvent
->BufferLength
= EventBufferLength
;
60 RtlCopyMemory(PnPEvent
->Buffer
, EventBuffer
, PnPEvent
->BufferLength
);
67 ProSendAndFreePnPEvent(
68 PLOGICAL_ADAPTER Adapter
,
69 PNET_PNP_EVENT PnPEvent
,
72 PLIST_ENTRY CurrentEntry
;
74 PADAPTER_BINDING AdapterBinding
;
76 CurrentEntry
= Adapter
->ProtocolListHead
.Flink
;
78 while (CurrentEntry
!= &Adapter
->ProtocolListHead
)
80 AdapterBinding
= CONTAINING_RECORD(CurrentEntry
, ADAPTER_BINDING
, AdapterListEntry
);
82 Status
= (*AdapterBinding
->ProtocolBinding
->Chars
.PnPEventHandler
)(
83 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
,
86 if (Status
== NDIS_STATUS_PENDING
)
88 IoMarkIrpPending(Irp
);
89 /* Yes, I know this is stupid */
90 PnPEvent
->NdisReserved
[0] = (ULONG_PTR
)Irp
;
91 PnPEvent
->NdisReserved
[1] = (ULONG_PTR
)CurrentEntry
->Flink
;
92 return NDIS_STATUS_PENDING
;
94 else if (Status
!= NDIS_STATUS_SUCCESS
)
96 if (PnPEvent
->Buffer
) ExFreePool(PnPEvent
->Buffer
);
101 CurrentEntry
= CurrentEntry
->Flink
;
104 if (PnPEvent
->Buffer
) ExFreePool(PnPEvent
->Buffer
);
105 ExFreePool(PnPEvent
);
107 return NDIS_STATUS_SUCCESS
;
113 IN PDEVICE_OBJECT DeviceObject
,
116 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)DeviceObject
->DeviceExtension
;
117 PNET_PNP_EVENT PnPEvent
;
118 PIO_STACK_LOCATION Stack
= IoGetCurrentIrpStackLocation(Irp
);
120 ASSERT(Stack
->Parameters
.Power
.Type
== DevicePowerState
);
122 PnPEvent
= ProSetupPnPEvent(NetEventSetPower
, &Stack
->Parameters
.Power
.State
, sizeof(NDIS_DEVICE_POWER_STATE
));
124 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources\n"));
125 return NDIS_STATUS_RESOURCES
;
128 return ProSendAndFreePnPEvent(Adapter
, PnPEvent
, Irp
);
134 IN PDEVICE_OBJECT DeviceObject
,
137 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)DeviceObject
->DeviceExtension
;
138 PNET_PNP_EVENT PnPEvent
;
139 PIO_STACK_LOCATION Stack
= IoGetCurrentIrpStackLocation(Irp
);
141 ASSERT(Stack
->Parameters
.Power
.Type
== DevicePowerState
);
143 PnPEvent
= ProSetupPnPEvent(NetEventQueryPower
, &Stack
->Parameters
.Power
.State
, sizeof(NDIS_DEVICE_POWER_STATE
));
145 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources\n"));
146 return NDIS_STATUS_RESOURCES
;
149 return ProSendAndFreePnPEvent(Adapter
, PnPEvent
, Irp
);
155 NdisIPnPQueryStopDevice(
156 IN PDEVICE_OBJECT DeviceObject
,
159 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)DeviceObject
->DeviceExtension
;
160 PNET_PNP_EVENT PnPEvent
;
162 PnPEvent
= ProSetupPnPEvent(NetEventQueryRemoveDevice
, NULL
, 0);
164 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources\n"));
165 return NDIS_STATUS_RESOURCES
;
168 return ProSendAndFreePnPEvent(Adapter
, PnPEvent
, Irp
);
173 NdisIPnPCancelStopDevice(
174 IN PDEVICE_OBJECT DeviceObject
,
177 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)DeviceObject
->DeviceExtension
;
178 PNET_PNP_EVENT PnPEvent
;
180 PnPEvent
= ProSetupPnPEvent(NetEventCancelRemoveDevice
, NULL
, 0);
182 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources\n"));
183 return NDIS_STATUS_RESOURCES
;
186 return ProSendAndFreePnPEvent(Adapter
, PnPEvent
, Irp
);
195 NdisCompleteBindAdapter(
196 IN NDIS_HANDLE BindAdapterContext
,
197 IN NDIS_STATUS Status
,
198 IN NDIS_STATUS OpenStatus
)
200 * FUNCTION: Indicates a packet to bound protocols
202 * Adapter = Pointer to logical adapter
203 * Packet = Pointer to packet to indicate
205 * Status of operation
207 * - FIXME: partially-implemented
210 PROTOCOL_BINDING
*Protocol
= (PROTOCOL_BINDING
*)BindAdapterContext
;
212 if (!NT_SUCCESS(Status
)) {
213 NDIS_DbgPrint(MIN_TRACE
, ("Binding failed (%x)\n", Status
));
217 /* Put protocol binding struct on global list */
218 ExInterlockedInsertTailList(&ProtocolListHead
, &Protocol
->ListEntry
, &ProtocolListLock
);
226 NdisCompleteUnbindAdapter(
227 IN NDIS_HANDLE UnbindAdapterContext
,
228 IN NDIS_STATUS Status
)
230 /* We probably need to do more here but for now we just do
231 * the opposite of what NdisCompleteBindAdapter does
234 PROTOCOL_BINDING
*Protocol
= (PROTOCOL_BINDING
*)UnbindAdapterContext
;
236 if (!NT_SUCCESS(Status
)) {
237 NDIS_DbgPrint(MIN_TRACE
, ("Unbinding failed (%x)\n", Status
));
241 ExInterlockedRemoveEntryList(&Protocol
->ListEntry
, &ProtocolListLock
);
247 PLOGICAL_ADAPTER Adapter
,
250 * FUNCTION: Indicates a packet to bound protocols
252 * Adapter = Pointer to logical adapter
253 * Packet = Pointer to packet to indicate
255 * STATUS_SUCCESS in all cases
257 * - XXX ATM, this only handles loopback packets - is that its designed function?
263 PUCHAR LookaheadBuffer
;
265 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
268 MiniDisplayPacket(Packet
);
271 LookaheadBuffer
= ExAllocatePool(NonPagedPool
, Adapter
->NdisMiniportBlock
.CurrentLookahead
+ Adapter
->MediumHeaderSize
);
272 if (!LookaheadBuffer
) {
273 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources\n"));
274 return NDIS_STATUS_RESOURCES
;
277 NdisQueryPacket(Packet
, NULL
, NULL
, NULL
, &PacketLength
);
279 NDIS_DbgPrint(MAX_TRACE
, ("acquiring miniport block lock\n"));
280 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
282 BufferedLength
= CopyPacketToBuffer(LookaheadBuffer
, Packet
, 0, Adapter
->NdisMiniportBlock
.CurrentLookahead
+
283 Adapter
->MediumHeaderSize
);
284 Adapter
->NdisMiniportBlock
.IndicatedPacket
[KeGetCurrentProcessorNumber()] = Packet
;
286 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
288 if (BufferedLength
> Adapter
->MediumHeaderSize
)
290 /* XXX Change this to call SendPackets so we don't have to duplicate this wacky logic */
291 MiniIndicateData(Adapter
, NULL
, LookaheadBuffer
, Adapter
->MediumHeaderSize
,
292 &LookaheadBuffer
[Adapter
->MediumHeaderSize
], BufferedLength
- Adapter
->MediumHeaderSize
,
293 PacketLength
- Adapter
->MediumHeaderSize
);
297 MiniIndicateData(Adapter
, NULL
, LookaheadBuffer
, Adapter
->MediumHeaderSize
, NULL
, 0, 0);
300 ExFreePool(LookaheadBuffer
);
302 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
304 Adapter
->NdisMiniportBlock
.IndicatedPacket
[KeGetCurrentProcessorNumber()] = NULL
;
306 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
308 return NDIS_STATUS_SUCCESS
;
314 IN NDIS_HANDLE MacBindingHandle
,
315 IN PNDIS_REQUEST NdisRequest
)
317 * FUNCTION: Forwards a request to an NDIS miniport
319 * MacBindingHandle = Adapter binding handle
320 * NdisRequest = Pointer to request to perform
322 * Status of operation
325 PADAPTER_BINDING AdapterBinding
;
326 PLOGICAL_ADAPTER Adapter
;
327 PNDIS_REQUEST_MAC_BLOCK MacBlock
= (PNDIS_REQUEST_MAC_BLOCK
)NdisRequest
->MacReserved
;
329 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
331 ASSERT(MacBindingHandle
);
332 AdapterBinding
= GET_ADAPTER_BINDING(MacBindingHandle
);
334 ASSERT(AdapterBinding
->Adapter
);
335 Adapter
= AdapterBinding
->Adapter
;
337 MacBlock
->Binding
= &AdapterBinding
->NdisOpenBlock
;
340 MiniQueueWorkItem(Adapter
, NdisWorkItemRequest
, NdisRequest
, FALSE
);
341 return NDIS_STATUS_PENDING
;
343 if (MiniIsBusy(Adapter
, NdisWorkItemRequest
)) {
344 MiniQueueWorkItem(Adapter
, NdisWorkItemRequest
, NdisRequest
, FALSE
);
345 return NDIS_STATUS_PENDING
;
348 return MiniDoRequest(Adapter
, NdisRequest
);
355 IN NDIS_HANDLE MacBindingHandle
)
357 PADAPTER_BINDING AdapterBinding
= MacBindingHandle
;
359 /* FIXME: Wait for all packets to be sent */
361 return MiniReset(AdapterBinding
->Adapter
);
365 ScatterGatherSendPacket(
366 IN PDEVICE_OBJECT DeviceObject
,
368 IN PSCATTER_GATHER_LIST ScatterGather
,
371 PDMA_CONTEXT DmaContext
= Context
;
372 PLOGICAL_ADAPTER Adapter
= DmaContext
->Adapter
;
373 PNDIS_PACKET Packet
= DmaContext
->Packet
;
376 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
378 NDIS_PER_PACKET_INFO_FROM_PACKET(Packet
,
379 ScatterGatherListPacketInfo
) = ScatterGather
;
381 Status
= proSendPacketToMiniport(Adapter
, Packet
);
383 if (Status
!= NDIS_STATUS_PENDING
) {
384 NDIS_DbgPrint(MAX_TRACE
, ("Completing packet.\n"));
385 MiniSendComplete(Adapter
,
390 ExFreePool(DmaContext
);
394 proSendPacketToMiniport(PLOGICAL_ADAPTER Adapter
, PNDIS_PACKET Packet
)
397 MiniQueueWorkItem(Adapter
, NdisWorkItemSend
, Packet
, FALSE
);
398 return NDIS_STATUS_PENDING
;
401 NDIS_STATUS NdisStatus
;
403 if(MiniIsBusy(Adapter
, NdisWorkItemSend
)) {
404 MiniQueueWorkItem(Adapter
, NdisWorkItemSend
, Packet
, FALSE
);
405 return NDIS_STATUS_PENDING
;
408 if(Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendPacketsHandler
)
410 if(Adapter
->NdisMiniportBlock
.Flags
& NDIS_ATTRIBUTE_DESERIALIZE
)
412 NDIS_DbgPrint(MAX_TRACE
, ("Calling miniport's SendPackets handler\n"));
413 (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendPacketsHandler
)(
414 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, &Packet
, 1);
415 NdisStatus
= NDIS_STATUS_PENDING
;
417 /* SendPackets is called at DISPATCH_LEVEL for all serialized miniports */
418 KeRaiseIrql(DISPATCH_LEVEL
, &RaiseOldIrql
);
420 NDIS_DbgPrint(MAX_TRACE
, ("Calling miniport's SendPackets handler\n"));
421 (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendPacketsHandler
)(
422 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, &Packet
, 1);
424 KeLowerIrql(RaiseOldIrql
);
426 NdisStatus
= NDIS_GET_PACKET_STATUS(Packet
);
427 if (NdisStatus
== NDIS_STATUS_RESOURCES
) {
428 MiniQueueWorkItem(Adapter
, NdisWorkItemSend
, Packet
, TRUE
);
429 NdisStatus
= NDIS_STATUS_PENDING
;
435 if(Adapter
->NdisMiniportBlock
.Flags
& NDIS_ATTRIBUTE_DESERIALIZE
)
437 NDIS_DbgPrint(MAX_TRACE
, ("Calling miniport's Send handler\n"));
438 NdisStatus
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendHandler
)(
439 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, Packet
, Packet
->Private
.Flags
);
440 NDIS_DbgPrint(MAX_TRACE
, ("back from miniport's send handler\n"));
442 /* Send is called at DISPATCH_LEVEL for all serialized miniports */
443 KeRaiseIrql(DISPATCH_LEVEL
, &RaiseOldIrql
);
444 NDIS_DbgPrint(MAX_TRACE
, ("Calling miniport's Send handler\n"));
445 NdisStatus
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendHandler
)(
446 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, Packet
, Packet
->Private
.Flags
);
447 NDIS_DbgPrint(MAX_TRACE
, ("back from miniport's send handler\n"));
448 KeLowerIrql(RaiseOldIrql
);
450 if (NdisStatus
== NDIS_STATUS_RESOURCES
) {
451 MiniQueueWorkItem(Adapter
, NdisWorkItemSend
, Packet
, TRUE
);
452 NdisStatus
= NDIS_STATUS_PENDING
;
464 IN NDIS_HANDLE MacBindingHandle
,
465 IN PNDIS_PACKET Packet
)
467 * FUNCTION: Forwards a request to send a packet to an NDIS miniport
469 * MacBindingHandle = Adapter binding handle
470 * Packet = Pointer to NDIS packet descriptor
472 * NDIS_STATUS_SUCCESS if the packet was successfully sent
473 * NDIS_STATUS_PENDING if the miniport was busy or a serialized miniport returned NDIS_STATUS_RESOURCES
476 PADAPTER_BINDING AdapterBinding
;
477 PLOGICAL_ADAPTER Adapter
;
478 PNDIS_BUFFER NdisBuffer
;
479 PDMA_CONTEXT Context
;
480 NDIS_STATUS NdisStatus
;
484 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
486 ASSERT(MacBindingHandle
);
487 AdapterBinding
= GET_ADAPTER_BINDING(MacBindingHandle
);
489 ASSERT(AdapterBinding
);
490 Adapter
= AdapterBinding
->Adapter
;
494 /* if the following is not true, KeRaiseIrql() below will break */
495 ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL
);
497 /* XXX what is this crazy black magic? */
498 Packet
->Reserved
[1] = (ULONG_PTR
)MacBindingHandle
;
501 * Test the packet to see if it is a MAC loopback.
503 * We may have to loop this packet if miniport cannot.
504 * If dest MAC address of packet == MAC address of adapter,
505 * this is a loopback frame.
508 if ((Adapter
->NdisMiniportBlock
.MacOptions
& NDIS_MAC_OPTION_NO_LOOPBACK
) &&
509 MiniAdapterHasAddress(Adapter
, Packet
))
512 MiniQueueWorkItem(Adapter
, NdisWorkItemSendLoopback
, Packet
, FALSE
);
513 return NDIS_STATUS_PENDING
;
515 return ProIndicatePacket(Adapter
, Packet
);
518 if (Adapter
->NdisMiniportBlock
.ScatterGatherListSize
!= 0)
520 NDIS_DbgPrint(MIN_TRACE
, ("Using Scatter/Gather DMA\n"));
522 NdisQueryPacket(Packet
,
528 Context
= ExAllocatePool(NonPagedPool
, sizeof(DMA_CONTEXT
));
530 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources\n"));
531 return NDIS_STATUS_RESOURCES
;
534 Context
->Adapter
= Adapter
;
535 Context
->Packet
= Packet
;
537 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
539 KeFlushIoBuffers(NdisBuffer
, FALSE
, TRUE
);
541 NdisStatus
= Adapter
->NdisMiniportBlock
.SystemAdapterObject
->DmaOperations
->GetScatterGatherList(
542 Adapter
->NdisMiniportBlock
.SystemAdapterObject
,
543 Adapter
->NdisMiniportBlock
.PhysicalDeviceObject
,
545 MmGetMdlVirtualAddress(NdisBuffer
),
547 ScatterGatherSendPacket
,
551 KeLowerIrql(OldIrql
);
553 if (!NT_SUCCESS(NdisStatus
)) {
554 NDIS_DbgPrint(MIN_TRACE
, ("GetScatterGatherList failed! (%x)\n", NdisStatus
));
558 return NDIS_STATUS_PENDING
;
562 return proSendPacketToMiniport(Adapter
, Packet
);
569 IN NDIS_HANDLE NdisBindingHandle
,
570 IN PPNDIS_PACKET PacketArray
,
571 IN UINT NumberOfPackets
)
573 PADAPTER_BINDING AdapterBinding
= NdisBindingHandle
;
574 PLOGICAL_ADAPTER Adapter
= AdapterBinding
->Adapter
;
576 NDIS_STATUS NdisStatus
;
579 if(Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendPacketsHandler
)
581 if(Adapter
->NdisMiniportBlock
.Flags
& NDIS_ATTRIBUTE_DESERIALIZE
)
583 (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendPacketsHandler
)(
584 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, PacketArray
, NumberOfPackets
);
588 /* SendPackets is called at DISPATCH_LEVEL for all serialized miniports */
589 KeRaiseIrql(DISPATCH_LEVEL
, &RaiseOldIrql
);
590 (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendPacketsHandler
)(
591 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, PacketArray
, NumberOfPackets
);
592 KeLowerIrql(RaiseOldIrql
);
593 for (i
= 0; i
< NumberOfPackets
; i
++)
595 NdisStatus
= NDIS_GET_PACKET_STATUS(PacketArray
[i
]);
596 if (NdisStatus
!= NDIS_STATUS_PENDING
)
597 MiniSendComplete(Adapter
, PacketArray
[i
], NdisStatus
);
603 if(Adapter
->NdisMiniportBlock
.Flags
& NDIS_ATTRIBUTE_DESERIALIZE
)
605 for (i
= 0; i
< NumberOfPackets
; i
++)
607 NdisStatus
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendHandler
)(
608 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, PacketArray
[i
], PacketArray
[i
]->Private
.Flags
);
609 if (NdisStatus
!= NDIS_STATUS_PENDING
)
610 MiniSendComplete(Adapter
, PacketArray
[i
], NdisStatus
);
615 /* Send is called at DISPATCH_LEVEL for all serialized miniports */
616 KeRaiseIrql(DISPATCH_LEVEL
, &RaiseOldIrql
);
617 for (i
= 0; i
< NumberOfPackets
; i
++)
619 NdisStatus
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendHandler
)(
620 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, PacketArray
[i
], PacketArray
[i
]->Private
.Flags
);
621 if (NdisStatus
!= NDIS_STATUS_PENDING
)
622 MiniSendComplete(Adapter
, PacketArray
[i
], NdisStatus
);
624 KeLowerIrql(RaiseOldIrql
);
632 IN NDIS_HANDLE MacBindingHandle
,
633 IN NDIS_HANDLE MacReceiveContext
,
635 IN UINT BytesToTransfer
,
636 IN OUT PNDIS_PACKET Packet
,
637 OUT PUINT BytesTransferred
)
639 * FUNCTION: Forwards a request to copy received data into a protocol-supplied packet
641 * MacBindingHandle = Adapter binding handle
642 * MacReceiveContext = MAC receive context
643 * ByteOffset = Offset in packet to place data
644 * BytesToTransfer = Number of bytes to copy into packet
645 * Packet = Pointer to NDIS packet descriptor
646 * BytesTransferred = Address of buffer to place number of bytes copied
649 PADAPTER_BINDING AdapterBinding
= GET_ADAPTER_BINDING(MacBindingHandle
);
650 PLOGICAL_ADAPTER Adapter
= AdapterBinding
->Adapter
;
654 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
656 /* FIXME: Interrupts must be disabled for adapter */
657 /* XXX sd - why is that true? */
659 if (Adapter
->NdisMiniportBlock
.IndicatedPacket
[KeGetCurrentProcessorNumber()]) {
660 NDIS_DbgPrint(MAX_TRACE
, ("LoopPacket\n"));
661 /* NDIS is responsible for looping this packet */
662 NdisCopyFromPacketToPacket(Packet
,
663 ByteOffset
+ Adapter
->MediumHeaderSize
,
664 BytesToTransfer
+ Adapter
->MediumHeaderSize
,
665 Adapter
->NdisMiniportBlock
.IndicatedPacket
[KeGetCurrentProcessorNumber()],
668 return NDIS_STATUS_SUCCESS
;
671 ASSERT(Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.TransferDataHandler
);
673 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
675 Status
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.TransferDataHandler
)(
678 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
,
683 KeLowerIrql(OldIrql
);
696 OUT PNDIS_STATUS Status
,
697 IN NDIS_HANDLE NdisBindingHandle
)
699 * FUNCTION: Closes an adapter opened with NdisOpenAdapter
701 * Status = Address of buffer for status information
702 * NdisBindingHandle = Handle returned by NdisOpenAdapter
705 PADAPTER_BINDING AdapterBinding
= GET_ADAPTER_BINDING(NdisBindingHandle
);
707 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
709 /* Remove from protocol's bound adapters list */
710 ExInterlockedRemoveEntryList(&AdapterBinding
->ProtocolListEntry
, &AdapterBinding
->ProtocolBinding
->Lock
);
712 /* Remove protocol from adapter's bound protocols list */
713 ExInterlockedRemoveEntryList(&AdapterBinding
->AdapterListEntry
, &AdapterBinding
->Adapter
->NdisMiniportBlock
.Lock
);
715 ExFreePool(AdapterBinding
);
717 *Status
= NDIS_STATUS_SUCCESS
;
726 NdisDeregisterProtocol(
727 OUT PNDIS_STATUS Status
,
728 IN NDIS_HANDLE NdisProtocolHandle
)
730 * FUNCTION: Releases the resources allocated by NdisRegisterProtocol
732 * Status = Address of buffer for status information
733 * NdisProtocolHandle = Handle returned by NdisRegisterProtocol
736 PPROTOCOL_BINDING Protocol
= GET_PROTOCOL_BINDING(NdisProtocolHandle
);
738 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
740 /* FIXME: Make sure no adapter bindings exist */
742 /* Remove protocol from global list */
743 ExInterlockedRemoveEntryList(&Protocol
->ListEntry
, &ProtocolListLock
);
745 ExFreePool(Protocol
);
747 *Status
= NDIS_STATUS_SUCCESS
;
757 OUT PNDIS_STATUS Status
,
758 OUT PNDIS_STATUS OpenErrorStatus
,
759 OUT PNDIS_HANDLE NdisBindingHandle
,
760 OUT PUINT SelectedMediumIndex
,
761 IN PNDIS_MEDIUM MediumArray
,
762 IN UINT MediumArraySize
,
763 IN NDIS_HANDLE NdisProtocolHandle
,
764 IN NDIS_HANDLE ProtocolBindingContext
,
765 IN PNDIS_STRING AdapterName
,
767 IN PSTRING AddressingInformation OPTIONAL
)
769 * FUNCTION: Opens an adapter for communication
771 * Status = Address of buffer for status information
772 * OpenErrorStatus = Address of buffer for secondary error code
773 * NdisBindingHandle = Address of buffer for adapter binding handle
774 * SelectedMediumIndex = Address of buffer for selected medium
775 * MediumArray = Pointer to an array of NDIS_MEDIUMs called can support
776 * MediumArraySize = Number of elements in MediumArray
777 * NdisProtocolHandle = Handle returned by NdisRegisterProtocol
778 * ProtocolBindingContext = Pointer to caller suplied context area
779 * AdapterName = Pointer to buffer with name of adapter
780 * OpenOptions = Bitmask with flags passed to next-lower driver
781 * AddressingInformation = Optional pointer to buffer with NIC specific information
786 PLOGICAL_ADAPTER Adapter
;
787 PADAPTER_BINDING AdapterBinding
;
788 PPROTOCOL_BINDING Protocol
= GET_PROTOCOL_BINDING(NdisProtocolHandle
);
790 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
792 if(!NdisProtocolHandle
)
794 NDIS_DbgPrint(MIN_TRACE
, ("NdisProtocolHandle is NULL\n"));
795 *OpenErrorStatus
= *Status
= NDIS_STATUS_FAILURE
;
799 Adapter
= MiniLocateDevice(AdapterName
);
802 NDIS_DbgPrint(MIN_TRACE
, ("Adapter not found.\n"));
803 *Status
= NDIS_STATUS_ADAPTER_NOT_FOUND
;
807 /* Find the media type in the list provided by the protocol driver */
809 for (i
= 0; i
< MediumArraySize
; i
++)
811 if (Adapter
->NdisMiniportBlock
.MediaType
== MediumArray
[i
])
813 *SelectedMediumIndex
= i
;
821 NDIS_DbgPrint(MIN_TRACE
, ("Medium is not supported.\n"));
822 *Status
= NDIS_STATUS_UNSUPPORTED_MEDIA
;
826 /* Now that we have confirmed that the adapter can be opened, create a binding */
828 AdapterBinding
= ExAllocatePool(NonPagedPool
, sizeof(ADAPTER_BINDING
));
831 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
832 *Status
= NDIS_STATUS_RESOURCES
;
836 RtlZeroMemory(AdapterBinding
, sizeof(ADAPTER_BINDING
));
838 AdapterBinding
->ProtocolBinding
= Protocol
;
839 AdapterBinding
->Adapter
= Adapter
;
840 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
= ProtocolBindingContext
;
842 /* Set fields required by some NDIS macros */
843 AdapterBinding
->NdisOpenBlock
.BindingHandle
= (NDIS_HANDLE
)AdapterBinding
;
845 /* Set handlers (some NDIS macros require these) */
847 AdapterBinding
->NdisOpenBlock
.RequestHandler
= ProRequest
;
848 AdapterBinding
->NdisOpenBlock
.ResetHandler
= ProReset
;
849 AdapterBinding
->NdisOpenBlock
.SendHandler
= ProSend
;
850 AdapterBinding
->NdisOpenBlock
.SendPacketsHandler
= ProSendPackets
;
851 AdapterBinding
->NdisOpenBlock
.TransferDataHandler
= ProTransferData
;
853 AdapterBinding
->NdisOpenBlock
.RequestCompleteHandler
=
854 Protocol
->Chars
.RequestCompleteHandler
;
856 /* Put on protocol's bound adapters list */
857 ExInterlockedInsertTailList(&Protocol
->AdapterListHead
, &AdapterBinding
->ProtocolListEntry
, &Protocol
->Lock
);
859 /* Put protocol on adapter's bound protocols list */
860 NDIS_DbgPrint(MAX_TRACE
, ("acquiring miniport block lock\n"));
861 ExInterlockedInsertTailList(&Adapter
->ProtocolListHead
, &AdapterBinding
->AdapterListEntry
, &Adapter
->NdisMiniportBlock
.Lock
);
863 *NdisBindingHandle
= (NDIS_HANDLE
)AdapterBinding
;
865 *Status
= NDIS_STATUS_SUCCESS
;
870 ndisBindMiniportsToProtocol(OUT PNDIS_STATUS Status
, IN PNDIS_PROTOCOL_CHARACTERISTICS ProtocolCharacteristics
)
873 * bind the protocol to all of its miniports
876 * get list of devices from Bind key
877 * call BindAdapterHandler for each
879 OBJECT_ATTRIBUTES ObjectAttributes
;
880 UNICODE_STRING RegistryPath
;
881 WCHAR
*RegistryPathStr
;
884 HANDLE DriverKeyHandle
= NULL
;
885 PKEY_VALUE_PARTIAL_INFORMATION KeyInformation
= NULL
;
887 RegistryPathStr
= ExAllocatePoolWithTag(PagedPool
, sizeof(SERVICES_KEY
) + ProtocolCharacteristics
->Name
.Length
+ sizeof(LINKAGE_KEY
), NDIS_TAG
+ __LINE__
);
890 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
891 *Status
= NDIS_STATUS_RESOURCES
;
895 wcscpy(RegistryPathStr
, SERVICES_KEY
);
896 wcsncat(RegistryPathStr
, ((WCHAR
*)ProtocolCharacteristics
->Name
.Buffer
), ProtocolCharacteristics
->Name
.Length
/ sizeof(WCHAR
));
897 RegistryPathStr
[wcslen(SERVICES_KEY
)+ProtocolCharacteristics
->Name
.Length
/sizeof(WCHAR
)] = 0;
898 wcscat(RegistryPathStr
, LINKAGE_KEY
);
900 RtlInitUnicodeString(&RegistryPath
, RegistryPathStr
);
901 NDIS_DbgPrint(MAX_TRACE
, ("Opening configuration key: %wZ\n", &RegistryPath
));
903 InitializeObjectAttributes(&ObjectAttributes
, &RegistryPath
, OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
904 NtStatus
= ZwOpenKey(&DriverKeyHandle
, KEY_READ
, &ObjectAttributes
);
906 ExFreePool(RegistryPathStr
);
908 if(!NT_SUCCESS(NtStatus
))
910 NDIS_DbgPrint(MIN_TRACE
, ("Unable to open protocol configuration\n"));
911 *Status
= NDIS_STATUS_FAILURE
;
915 NDIS_DbgPrint(MAX_TRACE
, ("Successfully opened the registry configuration\n"));
918 UNICODE_STRING ValueName
;
921 RtlInitUnicodeString(&ValueName
, L
"Bind");
923 NtStatus
= ZwQueryValueKey(DriverKeyHandle
, &ValueName
, KeyValuePartialInformation
, NULL
, 0, &ResultLength
);
924 if(NtStatus
!= STATUS_BUFFER_OVERFLOW
&& NtStatus
!= STATUS_BUFFER_TOO_SMALL
&& NtStatus
!= STATUS_SUCCESS
)
926 NDIS_DbgPrint(MIN_TRACE
, ("Unable to query the Bind value for size\n"));
927 ZwClose(DriverKeyHandle
);
928 *Status
= NDIS_STATUS_FAILURE
;
932 KeyInformation
= ExAllocatePoolWithTag(PagedPool
, sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + ResultLength
, NDIS_TAG
+ __LINE__
);
935 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
936 ZwClose(DriverKeyHandle
);
937 *Status
= NDIS_STATUS_FAILURE
;
941 NtStatus
= ZwQueryValueKey(DriverKeyHandle
, &ValueName
, KeyValuePartialInformation
, KeyInformation
,
942 sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + ResultLength
, &ResultLength
);
944 ZwClose(DriverKeyHandle
);
946 if(!NT_SUCCESS(NtStatus
))
948 NDIS_DbgPrint(MIN_TRACE
, ("Unable to query the Bind value\n"));
949 ExFreePool(KeyInformation
);
950 *Status
= NDIS_STATUS_FAILURE
;
955 for (DataPtr
= (WCHAR
*)KeyInformation
->Data
;
957 DataPtr
+= wcslen(DataPtr
) + 1)
959 /* BindContext is for tracking pending binding operations */
960 VOID
*BindContext
= 0;
961 NDIS_STRING DeviceName
;
962 NDIS_STRING RegistryPath
;
963 WCHAR
*RegistryPathStr
= NULL
;
964 ULONG PathLength
= 0;
966 RtlInitUnicodeString(&DeviceName
, DataPtr
); /* we know this is 0-term */
969 * RegistryPath should be:
970 * \Registry\Machine\System\CurrentControlSet\Services\Nic1\Parameters\Tcpip
972 * This is constructed as follows:
973 * SERVICES_KEY + extracted device name + Protocol name from characteristics
976 PathLength
= sizeof(SERVICES_KEY
) + /* \Registry\Machine\System\CurrentControlSet\Services\ */
977 wcslen( DataPtr
+ 8 ) * sizeof(WCHAR
) + /* Adapter1 (extracted from \Device\Adapter1) */
978 sizeof(PARAMETERS_KEY
) + /* \Parameters\ */
979 ProtocolCharacteristics
->Name
.Length
+ sizeof(WCHAR
); /* Tcpip */
981 RegistryPathStr
= ExAllocatePool(PagedPool
, PathLength
);
984 NDIS_DbgPrint(MIN_TRACE
, ("insufficient resources.\n"));
985 ExFreePool(KeyInformation
);
986 *Status
= NDIS_STATUS_RESOURCES
;
990 wcscpy(RegistryPathStr
, SERVICES_KEY
);
991 wcscat(RegistryPathStr
, DataPtr
+ 8 );
992 wcscat(RegistryPathStr
, PARAMETERS_KEY
);
993 wcsncat(RegistryPathStr
, ProtocolCharacteristics
->Name
.Buffer
, ProtocolCharacteristics
->Name
.Length
/ sizeof(WCHAR
) );
995 RegistryPathStr
[PathLength
/sizeof(WCHAR
) - 1] = 0;
997 RtlInitUnicodeString(&RegistryPath
, RegistryPathStr
);
999 NDIS_DbgPrint(MAX_TRACE
, ("Calling protocol's BindAdapter handler with DeviceName %wZ and RegistryPath %wZ\n",
1000 &DeviceName
, &RegistryPath
));
1003 BIND_HANDLER BindHandler
= ProtocolCharacteristics
->BindAdapterHandler
;
1006 BindHandler(Status
, BindContext
, &DeviceName
, &RegistryPath
, 0);
1007 NDIS_DbgPrint(MIN_TRACE
, ("%wZ's BindAdapter handler returned 0x%x for %wZ\n", &ProtocolCharacteristics
->Name
, *Status
, &DeviceName
));
1010 NDIS_DbgPrint(MIN_TRACE
, ("No protocol bind handler specified\n"));
1014 *Status
= NDIS_STATUS_SUCCESS
;
1015 ExFreePool(KeyInformation
);
1023 NdisRegisterProtocol(
1024 OUT PNDIS_STATUS Status
,
1025 OUT PNDIS_HANDLE NdisProtocolHandle
,
1026 IN PNDIS_PROTOCOL_CHARACTERISTICS ProtocolCharacteristics
,
1027 IN UINT CharacteristicsLength
)
1029 * FUNCTION: Registers an NDIS driver's ProtocolXxx entry points
1031 * Status = Address of buffer for status information
1032 * NdisProtocolHandle = Address of buffer for handle used to identify the driver
1033 * ProtocolCharacteristics = Pointer to NDIS_PROTOCOL_CHARACTERISTICS structure
1034 * CharacteristicsLength = Size of structure which ProtocolCharacteristics targets
1036 * - you *must* set NdisProtocolHandle before doing anything that could wind up
1037 * getting BindAdapterHandler, as it will probably call OpenAdapter with this handle
1038 * - the above implies that the initialization of the protocol block must be complete
1041 * - break this function up - probably do a 'ndisRefreshProtocolBindings' function
1042 * - make this thing able to handle >1 protocol
1045 PPROTOCOL_BINDING Protocol
;
1048 PNET_PNP_EVENT PnPEvent
;
1050 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
1052 *NdisProtocolHandle
= NULL
;
1054 /* first validate the PROTOCOL_CHARACTERISTICS */
1055 switch (ProtocolCharacteristics
->MajorNdisVersion
)
1058 /* we don't really want to support ndis3 drivers - so we complain for now */
1059 NDIS_DbgPrint(MID_TRACE
, ("NDIS 3 protocol attempting to register\n"));
1060 MinSize
= sizeof(NDIS30_PROTOCOL_CHARACTERISTICS
);
1064 MinSize
= sizeof(NDIS40_PROTOCOL_CHARACTERISTICS
);
1068 MinSize
= sizeof(NDIS50_PROTOCOL_CHARACTERISTICS
);
1072 *Status
= NDIS_STATUS_BAD_VERSION
;
1073 NDIS_DbgPrint(MIN_TRACE
, ("Incorrect characteristics size\n"));
1077 if (CharacteristicsLength
< MinSize
)
1079 NDIS_DbgPrint(MIN_TRACE
, ("Bad protocol characteristics.\n"));
1080 *Status
= NDIS_STATUS_BAD_CHARACTERISTICS
;
1084 /* set up the protocol block */
1085 Protocol
= ExAllocatePool(NonPagedPool
, sizeof(PROTOCOL_BINDING
));
1088 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
1089 *Status
= NDIS_STATUS_RESOURCES
;
1093 RtlZeroMemory(Protocol
, sizeof(PROTOCOL_BINDING
));
1094 RtlCopyMemory(&Protocol
->Chars
, ProtocolCharacteristics
, MinSize
);
1096 NtStatus
= RtlUpcaseUnicodeString(&Protocol
->Chars
.Name
, &ProtocolCharacteristics
->Name
, TRUE
);
1097 if (!NT_SUCCESS(NtStatus
))
1099 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
1100 ExFreePool(Protocol
);
1101 *Status
= NDIS_STATUS_RESOURCES
;
1105 KeInitializeSpinLock(&Protocol
->Lock
);
1107 InitializeListHead(&Protocol
->AdapterListHead
);
1109 /* We must set this before the call to ndisBindMiniportsToProtocol because the protocol's
1110 * BindAdapter handler might need it */
1112 *NdisProtocolHandle
= Protocol
;
1114 ndisBindMiniportsToProtocol(Status
, &Protocol
->Chars
);
1116 /* Should we only send this if ndisBindMiniportsToProtocol succeeds? */
1117 PnPEvent
= ProSetupPnPEvent(NetEventBindsComplete
, NULL
, 0);
1120 if (Protocol
->Chars
.PnPEventHandler
)
1122 /* We call this with a NULL binding context because it affects all bindings */
1123 NtStatus
= (*Protocol
->Chars
.PnPEventHandler
)(NULL
,
1126 /* FIXME: We don't support this yet */
1127 ASSERT(NtStatus
!= NDIS_STATUS_PENDING
);
1130 ExFreePool(PnPEvent
);
1133 if (*Status
== NDIS_STATUS_SUCCESS
) {
1134 ExInterlockedInsertTailList(&ProtocolListHead
, &Protocol
->ListEntry
, &ProtocolListLock
);
1136 NDIS_DbgPrint(MIN_TRACE
, ("Binding failed (%x)\n", *Status
));
1137 ExFreePool(Protocol
);
1138 *NdisProtocolHandle
= NULL
;
1149 OUT PNDIS_STATUS Status
,
1150 IN NDIS_HANDLE NdisBindingHandle
,
1151 IN PNDIS_REQUEST NdisRequest
)
1153 * FUNCTION: Forwards a request to an NDIS driver
1155 * Status = Address of buffer for status information
1156 * NdisBindingHandle = Adapter binding handle
1157 * NdisRequest = Pointer to request to perform
1160 *Status
= ProRequest(NdisBindingHandle
, NdisRequest
);
1170 OUT PNDIS_STATUS Status
,
1171 IN NDIS_HANDLE NdisBindingHandle
)
1173 *Status
= ProReset(NdisBindingHandle
);
1184 OUT PNDIS_STATUS Status
,
1185 IN NDIS_HANDLE NdisBindingHandle
,
1186 IN PNDIS_PACKET Packet
)
1188 * FUNCTION: Forwards a request to send a packet
1190 * Status = Address of buffer for status information
1191 * NdisBindingHandle = Adapter binding handle
1192 * Packet = Pointer to NDIS packet descriptor
1195 *Status
= ProSend(NdisBindingHandle
, Packet
);
1202 #undef NdisSendPackets
1206 IN NDIS_HANDLE NdisBindingHandle
,
1207 IN PPNDIS_PACKET PacketArray
,
1208 IN UINT NumberOfPackets
)
1210 ProSendPackets(NdisBindingHandle
, PacketArray
, NumberOfPackets
);
1217 #undef NdisTransferData
1221 OUT PNDIS_STATUS Status
,
1222 IN NDIS_HANDLE NdisBindingHandle
,
1223 IN NDIS_HANDLE MacReceiveContext
,
1225 IN UINT BytesToTransfer
,
1226 IN OUT PNDIS_PACKET Packet
,
1227 OUT PUINT BytesTransferred
)
1229 * FUNCTION: Forwards a request to copy received data into a protocol-supplied packet
1231 * Status = Address of buffer for status information
1232 * NdisBindingHandle = Adapter binding handle
1233 * MacReceiveContext = MAC receive context
1234 * ByteOffset = Offset in packet to place data
1235 * BytesToTransfer = Number of bytes to copy into packet
1236 * Packet = Pointer to NDIS packet descriptor
1237 * BytesTransferred = Address of buffer to place number of bytes copied
1240 *Status
= ProTransferData(NdisBindingHandle
,
1253 NdisReEnumerateProtocolBindings(IN NDIS_HANDLE NdisProtocolHandle
)
1255 PPROTOCOL_BINDING Protocol
= NdisProtocolHandle
;
1256 NDIS_STATUS NdisStatus
;
1258 ndisBindMiniportsToProtocol(&NdisStatus
, &Protocol
->Chars
);
1267 NdisGetDriverHandle(
1268 IN PNDIS_HANDLE NdisBindingHandle
,
1269 OUT PNDIS_HANDLE NdisDriverHandle
)
1277 PADAPTER_BINDING Binding
= (PADAPTER_BINDING
)NdisBindingHandle
;
1281 NDIS_DbgPrint(MIN_TRACE
, ("Bad binding handle\n"));
1282 *NdisDriverHandle
= NULL
;
1286 *NdisDriverHandle
= Binding
->Adapter
->NdisMiniportBlock
.DriverHandle
;