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
));
42 RtlZeroMemory(PnPEvent
, sizeof(NET_PNP_EVENT
));
44 PnPEvent
->NetEvent
= EventCode
;
46 if (EventBuffer
!= NULL
)
48 PnPEvent
->Buffer
= ExAllocatePool(PagedPool
, EventBufferLength
);
49 if (!PnPEvent
->Buffer
)
55 PnPEvent
->BufferLength
= EventBufferLength
;
57 RtlCopyMemory(PnPEvent
->Buffer
, EventBuffer
, PnPEvent
->BufferLength
);
64 ProSendAndFreePnPEvent(
65 PLOGICAL_ADAPTER Adapter
,
66 PNET_PNP_EVENT PnPEvent
,
69 PLIST_ENTRY CurrentEntry
;
71 PADAPTER_BINDING AdapterBinding
;
73 CurrentEntry
= Adapter
->ProtocolListHead
.Flink
;
75 while (CurrentEntry
!= &Adapter
->ProtocolListHead
)
77 AdapterBinding
= CONTAINING_RECORD(CurrentEntry
, ADAPTER_BINDING
, AdapterListEntry
);
79 Status
= (*AdapterBinding
->ProtocolBinding
->Chars
.PnPEventHandler
)(
80 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
,
83 if (Status
== NDIS_STATUS_PENDING
)
85 IoMarkIrpPending(Irp
);
86 /* Yes, I know this is stupid */
87 PnPEvent
->NdisReserved
[0] = (ULONG_PTR
)Irp
;
88 PnPEvent
->NdisReserved
[1] = (ULONG_PTR
)CurrentEntry
->Flink
;
89 return NDIS_STATUS_PENDING
;
91 else if (Status
!= NDIS_STATUS_SUCCESS
)
93 if (PnPEvent
->Buffer
) ExFreePool(PnPEvent
->Buffer
);
98 CurrentEntry
= CurrentEntry
->Flink
;
101 if (PnPEvent
->Buffer
) ExFreePool(PnPEvent
->Buffer
);
102 ExFreePool(PnPEvent
);
104 return NDIS_STATUS_SUCCESS
;
110 IN PDEVICE_OBJECT DeviceObject
,
113 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)DeviceObject
->DeviceExtension
;
114 PNET_PNP_EVENT PnPEvent
;
115 PIO_STACK_LOCATION Stack
= IoGetCurrentIrpStackLocation(Irp
);
117 ASSERT(Stack
->Parameters
.Power
.Type
== DevicePowerState
);
119 PnPEvent
= ProSetupPnPEvent(NetEventSetPower
, &Stack
->Parameters
.Power
.State
, sizeof(NDIS_DEVICE_POWER_STATE
));
121 return NDIS_STATUS_RESOURCES
;
123 return ProSendAndFreePnPEvent(Adapter
, PnPEvent
, Irp
);
129 IN PDEVICE_OBJECT DeviceObject
,
132 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)DeviceObject
->DeviceExtension
;
133 PNET_PNP_EVENT PnPEvent
;
134 PIO_STACK_LOCATION Stack
= IoGetCurrentIrpStackLocation(Irp
);
136 ASSERT(Stack
->Parameters
.Power
.Type
== DevicePowerState
);
138 PnPEvent
= ProSetupPnPEvent(NetEventQueryPower
, &Stack
->Parameters
.Power
.State
, sizeof(NDIS_DEVICE_POWER_STATE
));
140 return NDIS_STATUS_RESOURCES
;
142 return ProSendAndFreePnPEvent(Adapter
, PnPEvent
, Irp
);
148 NdisIPnPQueryStopDevice(
149 IN PDEVICE_OBJECT DeviceObject
,
152 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)DeviceObject
->DeviceExtension
;
153 PNET_PNP_EVENT PnPEvent
;
155 PnPEvent
= ProSetupPnPEvent(NetEventQueryRemoveDevice
, NULL
, 0);
157 return NDIS_STATUS_RESOURCES
;
159 return ProSendAndFreePnPEvent(Adapter
, PnPEvent
, Irp
);
164 NdisIPnPCancelStopDevice(
165 IN PDEVICE_OBJECT DeviceObject
,
168 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)DeviceObject
->DeviceExtension
;
169 PNET_PNP_EVENT PnPEvent
;
171 PnPEvent
= ProSetupPnPEvent(NetEventCancelRemoveDevice
, NULL
, 0);
173 return NDIS_STATUS_RESOURCES
;
175 return ProSendAndFreePnPEvent(Adapter
, PnPEvent
, Irp
);
184 NdisCompleteBindAdapter(
185 IN NDIS_HANDLE BindAdapterContext
,
186 IN NDIS_STATUS Status
,
187 IN NDIS_STATUS OpenStatus
)
189 * FUNCTION: Indicates a packet to bound protocols
191 * Adapter = Pointer to logical adapter
192 * Packet = Pointer to packet to indicate
194 * Status of operation
196 * - FIXME: partially-implemented
199 PROTOCOL_BINDING
*Protocol
= (PROTOCOL_BINDING
*)BindAdapterContext
;
201 if (!NT_SUCCESS(Status
)) return;
203 /* Put protocol binding struct on global list */
204 ExInterlockedInsertTailList(&ProtocolListHead
, &Protocol
->ListEntry
, &ProtocolListLock
);
212 NdisCompleteUnbindAdapter(
213 IN NDIS_HANDLE UnbindAdapterContext
,
214 IN NDIS_STATUS Status
)
216 /* We probably need to do more here but for now we just do
217 * the opposite of what NdisCompleteBindAdapter does
220 PROTOCOL_BINDING
*Protocol
= (PROTOCOL_BINDING
*)UnbindAdapterContext
;
222 if (!NT_SUCCESS(Status
)) return;
224 ExInterlockedRemoveEntryList(&Protocol
->ListEntry
, &ProtocolListLock
);
230 PLOGICAL_ADAPTER Adapter
,
233 * FUNCTION: Indicates a packet to bound protocols
235 * Adapter = Pointer to logical adapter
236 * Packet = Pointer to packet to indicate
238 * STATUS_SUCCESS in all cases
240 * - XXX ATM, this only handles loopback packets - is that its designed function?
246 PUCHAR LookaheadBuffer
;
248 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
251 MiniDisplayPacket(Packet
);
254 LookaheadBuffer
= ExAllocatePool(NonPagedPool
, Adapter
->NdisMiniportBlock
.CurrentLookahead
+ Adapter
->MediumHeaderSize
);
255 if (!LookaheadBuffer
)
256 return NDIS_STATUS_RESOURCES
;
258 NdisQueryPacket(Packet
, NULL
, NULL
, NULL
, &PacketLength
);
260 NDIS_DbgPrint(MAX_TRACE
, ("acquiring miniport block lock\n"));
261 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
263 BufferedLength
= CopyPacketToBuffer(LookaheadBuffer
, Packet
, 0, Adapter
->NdisMiniportBlock
.CurrentLookahead
);
265 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
267 if (BufferedLength
> Adapter
->MediumHeaderSize
)
269 /* XXX Change this to call SendPackets so we don't have to duplicate this wacky logic */
270 MiniIndicateData(Adapter
, NULL
, LookaheadBuffer
, Adapter
->MediumHeaderSize
,
271 &LookaheadBuffer
[Adapter
->MediumHeaderSize
], BufferedLength
- Adapter
->MediumHeaderSize
,
272 PacketLength
- Adapter
->MediumHeaderSize
);
276 MiniIndicateData(Adapter
, NULL
, LookaheadBuffer
, Adapter
->MediumHeaderSize
, NULL
, 0, 0);
279 ExFreePool(LookaheadBuffer
);
281 return NDIS_STATUS_SUCCESS
;
287 IN NDIS_HANDLE MacBindingHandle
,
288 IN PNDIS_REQUEST NdisRequest
)
290 * FUNCTION: Forwards a request to an NDIS miniport
292 * MacBindingHandle = Adapter binding handle
293 * NdisRequest = Pointer to request to perform
295 * Status of operation
298 PADAPTER_BINDING AdapterBinding
;
299 PLOGICAL_ADAPTER Adapter
;
300 PNDIS_REQUEST_MAC_BLOCK MacBlock
= (PNDIS_REQUEST_MAC_BLOCK
)NdisRequest
->MacReserved
;
302 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
304 ASSERT(MacBindingHandle
);
305 AdapterBinding
= GET_ADAPTER_BINDING(MacBindingHandle
);
307 ASSERT(AdapterBinding
->Adapter
);
308 Adapter
= AdapterBinding
->Adapter
;
310 MacBlock
->Binding
= &AdapterBinding
->NdisOpenBlock
;
313 MiniQueueWorkItem(Adapter
, NdisWorkItemRequest
, NdisRequest
, FALSE
);
314 return NDIS_STATUS_PENDING
;
316 if (MiniIsBusy(Adapter
, NdisWorkItemRequest
)) {
317 MiniQueueWorkItem(Adapter
, NdisWorkItemRequest
, NdisRequest
, FALSE
);
318 return NDIS_STATUS_PENDING
;
321 return MiniDoRequest(Adapter
, NdisRequest
);
328 IN NDIS_HANDLE MacBindingHandle
)
332 return NDIS_STATUS_FAILURE
;
336 ScatterGatherSendPacket(
337 IN PDEVICE_OBJECT DeviceObject
,
339 IN PSCATTER_GATHER_LIST ScatterGather
,
342 PDMA_CONTEXT DmaContext
= Context
;
343 PLOGICAL_ADAPTER Adapter
= DmaContext
->Adapter
;
344 PNDIS_PACKET Packet
= DmaContext
->Packet
;
347 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
349 NDIS_PER_PACKET_INFO_FROM_PACKET(Packet
,
350 ScatterGatherListPacketInfo
) = ScatterGather
;
352 Status
= proSendPacketToMiniport(Adapter
, Packet
);
354 if (Status
!= NDIS_STATUS_PENDING
) {
355 NDIS_DbgPrint(MAX_TRACE
, ("Completing packet.\n"));
356 MiniSendComplete(Adapter
,
361 ExFreePool(DmaContext
);
365 proSendPacketToMiniport(PLOGICAL_ADAPTER Adapter
, PNDIS_PACKET Packet
)
368 MiniQueueWorkItem(Adapter
, NdisWorkItemSend
, Packet
, FALSE
);
369 return NDIS_STATUS_PENDING
;
372 NDIS_STATUS NdisStatus
;
374 if(MiniIsBusy(Adapter
, NdisWorkItemSend
)) {
375 MiniQueueWorkItem(Adapter
, NdisWorkItemSend
, Packet
, FALSE
);
376 return NDIS_STATUS_PENDING
;
379 if(Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendPacketsHandler
)
381 if(Adapter
->NdisMiniportBlock
.Flags
& NDIS_ATTRIBUTE_DESERIALIZE
)
383 NDIS_DbgPrint(MAX_TRACE
, ("Calling miniport's SendPackets handler\n"));
384 (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendPacketsHandler
)(
385 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, &Packet
, 1);
386 NdisStatus
= NDIS_STATUS_PENDING
;
388 /* SendPackets is called at DISPATCH_LEVEL for all serialized miniports */
389 KeRaiseIrql(DISPATCH_LEVEL
, &RaiseOldIrql
);
391 NDIS_DbgPrint(MAX_TRACE
, ("Calling miniport's SendPackets handler\n"));
392 (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendPacketsHandler
)(
393 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, &Packet
, 1);
395 KeLowerIrql(RaiseOldIrql
);
397 NdisStatus
= NDIS_GET_PACKET_STATUS(Packet
);
398 if (NdisStatus
== NDIS_STATUS_RESOURCES
) {
399 MiniQueueWorkItem(Adapter
, NdisWorkItemSend
, Packet
, TRUE
);
400 NdisStatus
= NDIS_STATUS_PENDING
;
406 if(Adapter
->NdisMiniportBlock
.Flags
& NDIS_ATTRIBUTE_DESERIALIZE
)
408 NDIS_DbgPrint(MAX_TRACE
, ("Calling miniport's Send handler\n"));
409 NdisStatus
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendHandler
)(
410 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, Packet
, Packet
->Private
.Flags
);
411 NDIS_DbgPrint(MAX_TRACE
, ("back from miniport's send handler\n"));
413 /* Send is called at DISPATCH_LEVEL for all serialized miniports */
414 KeRaiseIrql(DISPATCH_LEVEL
, &RaiseOldIrql
);
415 NDIS_DbgPrint(MAX_TRACE
, ("Calling miniport's Send handler\n"));
416 NdisStatus
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendHandler
)(
417 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, Packet
, Packet
->Private
.Flags
);
418 NDIS_DbgPrint(MAX_TRACE
, ("back from miniport's send handler\n"));
419 KeLowerIrql(RaiseOldIrql
);
421 if (NdisStatus
== NDIS_STATUS_RESOURCES
) {
422 MiniQueueWorkItem(Adapter
, NdisWorkItemSend
, Packet
, TRUE
);
423 NdisStatus
= NDIS_STATUS_PENDING
;
435 IN NDIS_HANDLE MacBindingHandle
,
436 IN PNDIS_PACKET Packet
)
438 * FUNCTION: Forwards a request to send a packet to an NDIS miniport
440 * MacBindingHandle = Adapter binding handle
441 * Packet = Pointer to NDIS packet descriptor
443 * NDIS_STATUS_SUCCESS if the packet was successfully sent
444 * NDIS_STATUS_PENDING if the miniport was busy or a serialized miniport returned NDIS_STATUS_RESOURCES
447 PADAPTER_BINDING AdapterBinding
;
448 PLOGICAL_ADAPTER Adapter
;
449 PNDIS_BUFFER NdisBuffer
;
450 PDMA_CONTEXT Context
;
451 NDIS_STATUS NdisStatus
;
455 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
457 ASSERT(MacBindingHandle
);
458 AdapterBinding
= GET_ADAPTER_BINDING(MacBindingHandle
);
460 ASSERT(AdapterBinding
);
461 Adapter
= AdapterBinding
->Adapter
;
465 /* if the following is not true, KeRaiseIrql() below will break */
466 ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL
);
468 /* XXX what is this crazy black magic? */
469 Packet
->Reserved
[1] = (ULONG_PTR
)MacBindingHandle
;
472 * Test the packet to see if it is a MAC loopback.
474 * We may have to loop this packet if miniport cannot.
475 * If dest MAC address of packet == MAC address of adapter,
476 * this is a loopback frame.
479 if ((Adapter
->NdisMiniportBlock
.MacOptions
& NDIS_MAC_OPTION_NO_LOOPBACK
) &&
480 MiniAdapterHasAddress(Adapter
, Packet
))
483 MiniQueueWorkItem(Adapter
, NdisWorkItemSendLoopback
, Packet
, FALSE
);
484 return NDIS_STATUS_PENDING
;
486 return ProIndicatePacket(Adapter
, Packet
);
489 if (Adapter
->NdisMiniportBlock
.ScatterGatherListSize
!= 0)
491 NDIS_DbgPrint(MAX_TRACE
, ("Using Scatter/Gather DMA\n"));
493 NdisQueryPacket(Packet
,
499 Context
= ExAllocatePool(NonPagedPool
, sizeof(DMA_CONTEXT
));
501 return NDIS_STATUS_RESOURCES
;
503 Context
->Adapter
= Adapter
;
504 Context
->Packet
= Packet
;
506 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
508 KeFlushIoBuffers(NdisBuffer
, FALSE
, TRUE
);
510 NdisStatus
= Adapter
->NdisMiniportBlock
.SystemAdapterObject
->DmaOperations
->GetScatterGatherList(
511 Adapter
->NdisMiniportBlock
.SystemAdapterObject
,
512 Adapter
->NdisMiniportBlock
.PhysicalDeviceObject
,
514 MmGetMdlVirtualAddress(NdisBuffer
),
516 ScatterGatherSendPacket
,
520 KeLowerIrql(OldIrql
);
522 if (!NT_SUCCESS(NdisStatus
)) {
523 NDIS_DbgPrint(MIN_TRACE
, ("GetScatterGatherList failed!\n"));
527 return NDIS_STATUS_PENDING
;
531 return proSendPacketToMiniport(Adapter
, Packet
);
538 IN NDIS_HANDLE NdisBindingHandle
,
539 IN PPNDIS_PACKET PacketArray
,
540 IN UINT NumberOfPackets
)
542 PADAPTER_BINDING AdapterBinding
= NdisBindingHandle
;
543 PLOGICAL_ADAPTER Adapter
= AdapterBinding
->Adapter
;
545 NDIS_STATUS NdisStatus
;
548 if(Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendPacketsHandler
)
550 if(Adapter
->NdisMiniportBlock
.Flags
& NDIS_ATTRIBUTE_DESERIALIZE
)
552 (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendPacketsHandler
)(
553 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, PacketArray
, NumberOfPackets
);
557 /* SendPackets is called at DISPATCH_LEVEL for all serialized miniports */
558 KeRaiseIrql(DISPATCH_LEVEL
, &RaiseOldIrql
);
559 (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendPacketsHandler
)(
560 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, PacketArray
, NumberOfPackets
);
561 KeLowerIrql(RaiseOldIrql
);
562 for (i
= 0; i
< NumberOfPackets
; i
++)
564 NdisStatus
= NDIS_GET_PACKET_STATUS(PacketArray
[i
]);
565 if (NdisStatus
!= NDIS_STATUS_PENDING
)
566 MiniSendComplete(Adapter
, PacketArray
[i
], NdisStatus
);
572 if(Adapter
->NdisMiniportBlock
.Flags
& NDIS_ATTRIBUTE_DESERIALIZE
)
574 for (i
= 0; i
< NumberOfPackets
; i
++)
576 NdisStatus
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendHandler
)(
577 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, PacketArray
[i
], PacketArray
[i
]->Private
.Flags
);
578 if (NdisStatus
!= NDIS_STATUS_PENDING
)
579 MiniSendComplete(Adapter
, PacketArray
[i
], NdisStatus
);
584 /* Send is called at DISPATCH_LEVEL for all serialized miniports */
585 KeRaiseIrql(DISPATCH_LEVEL
, &RaiseOldIrql
);
586 for (i
= 0; i
< NumberOfPackets
; i
++)
588 NdisStatus
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendHandler
)(
589 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, PacketArray
[i
], PacketArray
[i
]->Private
.Flags
);
590 if (NdisStatus
!= NDIS_STATUS_PENDING
)
591 MiniSendComplete(Adapter
, PacketArray
[i
], NdisStatus
);
593 KeLowerIrql(RaiseOldIrql
);
601 IN NDIS_HANDLE MacBindingHandle
,
602 IN NDIS_HANDLE MacReceiveContext
,
604 IN UINT BytesToTransfer
,
605 IN OUT PNDIS_PACKET Packet
,
606 OUT PUINT BytesTransferred
)
608 * FUNCTION: Forwards a request to copy received data into a protocol-supplied packet
610 * MacBindingHandle = Adapter binding handle
611 * MacReceiveContext = MAC receive context
612 * ByteOffset = Offset in packet to place data
613 * BytesToTransfer = Number of bytes to copy into packet
614 * Packet = Pointer to NDIS packet descriptor
615 * BytesTransferred = Address of buffer to place number of bytes copied
618 PADAPTER_BINDING AdapterBinding
= GET_ADAPTER_BINDING(MacBindingHandle
);
619 PLOGICAL_ADAPTER Adapter
= AdapterBinding
->Adapter
;
623 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
625 /* FIXME: Interrupts must be disabled for adapter */
626 /* XXX sd - why is that true? */
628 if (Packet
== Adapter
->NdisMiniportBlock
.IndicatedPacket
[KeGetCurrentProcessorNumber()]) {
629 NDIS_DbgPrint(MAX_TRACE
, ("LoopPacket\n"));
630 /* NDIS is responsible for looping this packet */
631 NdisCopyFromPacketToPacket(Packet
,
634 Adapter
->NdisMiniportBlock
.IndicatedPacket
[KeGetCurrentProcessorNumber()],
637 return NDIS_STATUS_SUCCESS
;
640 ASSERT(Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.TransferDataHandler
);
642 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
644 Status
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.TransferDataHandler
)(
647 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
,
652 KeLowerIrql(OldIrql
);
665 OUT PNDIS_STATUS Status
,
666 IN NDIS_HANDLE NdisBindingHandle
)
668 * FUNCTION: Closes an adapter opened with NdisOpenAdapter
670 * Status = Address of buffer for status information
671 * NdisBindingHandle = Handle returned by NdisOpenAdapter
674 PADAPTER_BINDING AdapterBinding
= GET_ADAPTER_BINDING(NdisBindingHandle
);
676 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
678 /* Remove from protocol's bound adapters list */
679 ExInterlockedRemoveEntryList(&AdapterBinding
->ProtocolListEntry
, &AdapterBinding
->ProtocolBinding
->Lock
);
681 /* Remove protocol from adapter's bound protocols list */
682 ExInterlockedRemoveEntryList(&AdapterBinding
->AdapterListEntry
, &AdapterBinding
->Adapter
->NdisMiniportBlock
.Lock
);
684 ExFreePool(AdapterBinding
);
686 *Status
= NDIS_STATUS_SUCCESS
;
695 NdisDeregisterProtocol(
696 OUT PNDIS_STATUS Status
,
697 IN NDIS_HANDLE NdisProtocolHandle
)
699 * FUNCTION: Releases the resources allocated by NdisRegisterProtocol
701 * Status = Address of buffer for status information
702 * NdisProtocolHandle = Handle returned by NdisRegisterProtocol
705 PPROTOCOL_BINDING Protocol
= GET_PROTOCOL_BINDING(NdisProtocolHandle
);
707 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
709 /* FIXME: Make sure no adapter bindings exist */
711 /* Remove protocol from global list */
712 ExInterlockedRemoveEntryList(&Protocol
->ListEntry
, &ProtocolListLock
);
714 ExFreePool(Protocol
);
716 *Status
= NDIS_STATUS_SUCCESS
;
726 OUT PNDIS_STATUS Status
,
727 OUT PNDIS_STATUS OpenErrorStatus
,
728 OUT PNDIS_HANDLE NdisBindingHandle
,
729 OUT PUINT SelectedMediumIndex
,
730 IN PNDIS_MEDIUM MediumArray
,
731 IN UINT MediumArraySize
,
732 IN NDIS_HANDLE NdisProtocolHandle
,
733 IN NDIS_HANDLE ProtocolBindingContext
,
734 IN PNDIS_STRING AdapterName
,
736 IN PSTRING AddressingInformation OPTIONAL
)
738 * FUNCTION: Opens an adapter for communication
740 * Status = Address of buffer for status information
741 * OpenErrorStatus = Address of buffer for secondary error code
742 * NdisBindingHandle = Address of buffer for adapter binding handle
743 * SelectedMediumIndex = Address of buffer for selected medium
744 * MediumArray = Pointer to an array of NDIS_MEDIUMs called can support
745 * MediumArraySize = Number of elements in MediumArray
746 * NdisProtocolHandle = Handle returned by NdisRegisterProtocol
747 * ProtocolBindingContext = Pointer to caller suplied context area
748 * AdapterName = Pointer to buffer with name of adapter
749 * OpenOptions = Bitmask with flags passed to next-lower driver
750 * AddressingInformation = Optional pointer to buffer with NIC specific information
755 PLOGICAL_ADAPTER Adapter
;
756 PADAPTER_BINDING AdapterBinding
;
757 PPROTOCOL_BINDING Protocol
= GET_PROTOCOL_BINDING(NdisProtocolHandle
);
759 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
761 if(!NdisProtocolHandle
)
763 NDIS_DbgPrint(MAX_TRACE
, ("NdisProtocolHandle is NULL\n"));
764 *OpenErrorStatus
= *Status
= NDIS_STATUS_FAILURE
;
768 Adapter
= MiniLocateDevice(AdapterName
);
771 NDIS_DbgPrint(MIN_TRACE
, ("Adapter not found.\n"));
772 *Status
= NDIS_STATUS_ADAPTER_NOT_FOUND
;
776 /* Find the media type in the list provided by the protocol driver */
778 for (i
= 0; i
< MediumArraySize
; i
++)
780 if (Adapter
->NdisMiniportBlock
.MediaType
== MediumArray
[i
])
782 *SelectedMediumIndex
= i
;
790 NDIS_DbgPrint(MIN_TRACE
, ("Medium is not supported.\n"));
791 *Status
= NDIS_STATUS_UNSUPPORTED_MEDIA
;
795 /* Now that we have confirmed that the adapter can be opened, create a binding */
797 AdapterBinding
= ExAllocatePool(NonPagedPool
, sizeof(ADAPTER_BINDING
));
800 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
801 *Status
= NDIS_STATUS_RESOURCES
;
805 RtlZeroMemory(AdapterBinding
, sizeof(ADAPTER_BINDING
));
807 AdapterBinding
->ProtocolBinding
= Protocol
;
808 AdapterBinding
->Adapter
= Adapter
;
809 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
= ProtocolBindingContext
;
811 /* Set fields required by some NDIS macros */
812 AdapterBinding
->NdisOpenBlock
.BindingHandle
= (NDIS_HANDLE
)AdapterBinding
;
814 /* Set handlers (some NDIS macros require these) */
816 AdapterBinding
->NdisOpenBlock
.RequestHandler
= ProRequest
;
817 AdapterBinding
->NdisOpenBlock
.ResetHandler
= ProReset
;
818 AdapterBinding
->NdisOpenBlock
.SendHandler
= ProSend
;
819 AdapterBinding
->NdisOpenBlock
.SendPacketsHandler
= ProSendPackets
;
820 AdapterBinding
->NdisOpenBlock
.TransferDataHandler
= ProTransferData
;
822 AdapterBinding
->NdisOpenBlock
.RequestCompleteHandler
=
823 Protocol
->Chars
.RequestCompleteHandler
;
825 /* Put on protocol's bound adapters list */
826 ExInterlockedInsertTailList(&Protocol
->AdapterListHead
, &AdapterBinding
->ProtocolListEntry
, &Protocol
->Lock
);
828 /* Put protocol on adapter's bound protocols list */
829 NDIS_DbgPrint(MAX_TRACE
, ("acquiring miniport block lock\n"));
830 ExInterlockedInsertTailList(&Adapter
->ProtocolListHead
, &AdapterBinding
->AdapterListEntry
, &Adapter
->NdisMiniportBlock
.Lock
);
832 *NdisBindingHandle
= (NDIS_HANDLE
)AdapterBinding
;
834 *Status
= NDIS_STATUS_SUCCESS
;
839 ndisBindMiniportsToProtocol(OUT PNDIS_STATUS Status
, IN PNDIS_PROTOCOL_CHARACTERISTICS ProtocolCharacteristics
)
842 * bind the protocol to all of its miniports
845 * get list of devices from Bind key
846 * call BindAdapterHandler for each
848 OBJECT_ATTRIBUTES ObjectAttributes
;
849 UNICODE_STRING RegistryPath
;
850 WCHAR
*RegistryPathStr
;
853 HANDLE DriverKeyHandle
= NULL
;
854 PKEY_VALUE_PARTIAL_INFORMATION KeyInformation
= NULL
;
856 RegistryPathStr
= ExAllocatePoolWithTag(PagedPool
, sizeof(SERVICES_KEY
) + ProtocolCharacteristics
->Name
.Length
+ sizeof(LINKAGE_KEY
), NDIS_TAG
+ __LINE__
);
859 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
860 *Status
= NDIS_STATUS_RESOURCES
;
864 wcscpy(RegistryPathStr
, SERVICES_KEY
);
865 wcsncat(RegistryPathStr
, ((WCHAR
*)ProtocolCharacteristics
->Name
.Buffer
), ProtocolCharacteristics
->Name
.Length
/ sizeof(WCHAR
));
866 RegistryPathStr
[wcslen(SERVICES_KEY
)+ProtocolCharacteristics
->Name
.Length
/sizeof(WCHAR
)] = 0;
867 wcscat(RegistryPathStr
, LINKAGE_KEY
);
869 RtlInitUnicodeString(&RegistryPath
, RegistryPathStr
);
870 NDIS_DbgPrint(MAX_TRACE
, ("Opening configuration key: %wZ\n", &RegistryPath
));
872 InitializeObjectAttributes(&ObjectAttributes
, &RegistryPath
, OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
873 NtStatus
= ZwOpenKey(&DriverKeyHandle
, KEY_READ
, &ObjectAttributes
);
875 ExFreePool(RegistryPathStr
);
877 if(!NT_SUCCESS(NtStatus
))
879 NDIS_DbgPrint(MIN_TRACE
, ("Unable to open protocol configuration\n"));
880 *Status
= NDIS_STATUS_FAILURE
;
884 NDIS_DbgPrint(MAX_TRACE
, ("Successfully opened the registry configuration\n"));
887 UNICODE_STRING ValueName
;
890 RtlInitUnicodeString(&ValueName
, L
"Bind");
892 NtStatus
= ZwQueryValueKey(DriverKeyHandle
, &ValueName
, KeyValuePartialInformation
, NULL
, 0, &ResultLength
);
893 if(NtStatus
!= STATUS_BUFFER_OVERFLOW
&& NtStatus
!= STATUS_BUFFER_TOO_SMALL
&& NtStatus
!= STATUS_SUCCESS
)
895 NDIS_DbgPrint(MIN_TRACE
, ("Unable to query the Bind value for size\n"));
896 ZwClose(DriverKeyHandle
);
897 *Status
= NDIS_STATUS_FAILURE
;
901 KeyInformation
= ExAllocatePoolWithTag(PagedPool
, sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + ResultLength
, NDIS_TAG
+ __LINE__
);
904 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
905 ZwClose(DriverKeyHandle
);
906 *Status
= NDIS_STATUS_FAILURE
;
910 NtStatus
= ZwQueryValueKey(DriverKeyHandle
, &ValueName
, KeyValuePartialInformation
, KeyInformation
,
911 sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + ResultLength
, &ResultLength
);
913 ZwClose(DriverKeyHandle
);
915 if(!NT_SUCCESS(NtStatus
))
917 NDIS_DbgPrint(MIN_TRACE
, ("Unable to query the Bind value\n"));
918 ExFreePool(KeyInformation
);
919 *Status
= NDIS_STATUS_FAILURE
;
924 for (DataPtr
= (WCHAR
*)KeyInformation
->Data
;
926 DataPtr
+= wcslen(DataPtr
) + 1)
928 /* BindContext is for tracking pending binding operations */
929 VOID
*BindContext
= 0;
930 NDIS_STRING DeviceName
;
931 NDIS_STRING RegistryPath
;
932 WCHAR
*RegistryPathStr
= NULL
;
933 ULONG PathLength
= 0;
935 RtlInitUnicodeString(&DeviceName
, DataPtr
); /* we know this is 0-term */
938 * RegistryPath should be:
939 * \Registry\Machine\System\CurrentControlSet\Services\Nic1\Parameters\Tcpip
941 * This is constructed as follows:
942 * SERVICES_KEY + extracted device name + Protocol name from characteristics
945 PathLength
= sizeof(SERVICES_KEY
) + /* \Registry\Machine\System\CurrentControlSet\Services\ */
946 wcslen( DataPtr
+ 8 ) * sizeof(WCHAR
) + /* Adapter1 (extracted from \Device\Adapter1) */
947 sizeof(PARAMETERS_KEY
) + /* \Parameters\ */
948 ProtocolCharacteristics
->Name
.Length
+ sizeof(WCHAR
); /* Tcpip */
950 RegistryPathStr
= ExAllocatePool(PagedPool
, PathLength
);
953 NDIS_DbgPrint(MIN_TRACE
, ("insufficient resources.\n"));
954 ExFreePool(KeyInformation
);
955 *Status
= NDIS_STATUS_RESOURCES
;
959 wcscpy(RegistryPathStr
, SERVICES_KEY
);
960 wcscat(RegistryPathStr
, DataPtr
+ 8 );
961 wcscat(RegistryPathStr
, PARAMETERS_KEY
);
962 wcsncat(RegistryPathStr
, ProtocolCharacteristics
->Name
.Buffer
, ProtocolCharacteristics
->Name
.Length
/ sizeof(WCHAR
) );
964 RegistryPathStr
[PathLength
/sizeof(WCHAR
) - 1] = 0;
966 RtlInitUnicodeString(&RegistryPath
, RegistryPathStr
);
968 NDIS_DbgPrint(MAX_TRACE
, ("Calling protocol's BindAdapter handler with DeviceName %wZ and RegistryPath %wZ\n",
969 &DeviceName
, &RegistryPath
));
972 BIND_HANDLER BindHandler
= ProtocolCharacteristics
->BindAdapterHandler
;
974 BindHandler(Status
, BindContext
, &DeviceName
, &RegistryPath
, 0);
976 NDIS_DbgPrint(MID_TRACE
, ("No protocol bind handler specified\n"));
980 *Status
= NDIS_STATUS_SUCCESS
;
981 ExFreePool(KeyInformation
);
989 NdisRegisterProtocol(
990 OUT PNDIS_STATUS Status
,
991 OUT PNDIS_HANDLE NdisProtocolHandle
,
992 IN PNDIS_PROTOCOL_CHARACTERISTICS ProtocolCharacteristics
,
993 IN UINT CharacteristicsLength
)
995 * FUNCTION: Registers an NDIS driver's ProtocolXxx entry points
997 * Status = Address of buffer for status information
998 * NdisProtocolHandle = Address of buffer for handle used to identify the driver
999 * ProtocolCharacteristics = Pointer to NDIS_PROTOCOL_CHARACTERISTICS structure
1000 * CharacteristicsLength = Size of structure which ProtocolCharacteristics targets
1002 * - you *must* set NdisProtocolHandle before doing anything that could wind up
1003 * getting BindAdapterHandler, as it will probably call OpenAdapter with this handle
1004 * - the above implies that the initialization of the protocol block must be complete
1007 * - break this function up - probably do a 'ndisRefreshProtocolBindings' function
1008 * - make this thing able to handle >1 protocol
1011 PPROTOCOL_BINDING Protocol
;
1015 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
1017 *NdisProtocolHandle
= NULL
;
1019 /* first validate the PROTOCOL_CHARACTERISTICS */
1020 switch (ProtocolCharacteristics
->MajorNdisVersion
)
1023 /* we don't really want to support ndis3 drivers - so we complain for now */
1024 NDIS_DbgPrint(MID_TRACE
, ("NDIS 3 protocol attempting to register\n"));
1025 MinSize
= sizeof(NDIS30_PROTOCOL_CHARACTERISTICS
);
1029 MinSize
= sizeof(NDIS40_PROTOCOL_CHARACTERISTICS
);
1033 MinSize
= sizeof(NDIS50_PROTOCOL_CHARACTERISTICS
);
1037 *Status
= NDIS_STATUS_BAD_VERSION
;
1038 NDIS_DbgPrint(MIN_TRACE
, ("Incorrect characteristics size\n"));
1042 if (CharacteristicsLength
< MinSize
)
1044 NDIS_DbgPrint(MIN_TRACE
, ("Bad protocol characteristics.\n"));
1045 *Status
= NDIS_STATUS_BAD_CHARACTERISTICS
;
1049 /* set up the protocol block */
1050 Protocol
= ExAllocatePool(NonPagedPool
, sizeof(PROTOCOL_BINDING
));
1053 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
1054 *Status
= NDIS_STATUS_RESOURCES
;
1058 RtlZeroMemory(Protocol
, sizeof(PROTOCOL_BINDING
));
1059 RtlCopyMemory(&Protocol
->Chars
, ProtocolCharacteristics
, MinSize
);
1061 NtStatus
= RtlUpcaseUnicodeString(&Protocol
->Chars
.Name
, &ProtocolCharacteristics
->Name
, TRUE
);
1062 if (!NT_SUCCESS(NtStatus
))
1064 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
1065 ExFreePool(Protocol
);
1066 *Status
= NDIS_STATUS_RESOURCES
;
1070 KeInitializeSpinLock(&Protocol
->Lock
);
1072 InitializeListHead(&Protocol
->AdapterListHead
);
1074 /* We must set this before the call to ndisBindMiniportsToProtocol because the protocol's
1075 * BindAdapter handler might need it */
1077 *NdisProtocolHandle
= Protocol
;
1079 ndisBindMiniportsToProtocol(Status
, &Protocol
->Chars
);
1081 if (*Status
== NDIS_STATUS_SUCCESS
) {
1082 ExInterlockedInsertTailList(&ProtocolListHead
, &Protocol
->ListEntry
, &ProtocolListLock
);
1084 ExFreePool(Protocol
);
1085 *NdisProtocolHandle
= NULL
;
1096 OUT PNDIS_STATUS Status
,
1097 IN NDIS_HANDLE NdisBindingHandle
,
1098 IN PNDIS_REQUEST NdisRequest
)
1100 * FUNCTION: Forwards a request to an NDIS driver
1102 * Status = Address of buffer for status information
1103 * NdisBindingHandle = Adapter binding handle
1104 * NdisRequest = Pointer to request to perform
1107 *Status
= ProRequest(NdisBindingHandle
, NdisRequest
);
1117 OUT PNDIS_STATUS Status
,
1118 IN NDIS_HANDLE NdisBindingHandle
)
1120 *Status
= ProReset(NdisBindingHandle
);
1131 OUT PNDIS_STATUS Status
,
1132 IN NDIS_HANDLE NdisBindingHandle
,
1133 IN PNDIS_PACKET Packet
)
1135 * FUNCTION: Forwards a request to send a packet
1137 * Status = Address of buffer for status information
1138 * NdisBindingHandle = Adapter binding handle
1139 * Packet = Pointer to NDIS packet descriptor
1142 *Status
= ProSend(NdisBindingHandle
, Packet
);
1149 #undef NdisSendPackets
1153 IN NDIS_HANDLE NdisBindingHandle
,
1154 IN PPNDIS_PACKET PacketArray
,
1155 IN UINT NumberOfPackets
)
1157 ProSendPackets(NdisBindingHandle
, PacketArray
, NumberOfPackets
);
1164 #undef NdisTransferData
1168 OUT PNDIS_STATUS Status
,
1169 IN NDIS_HANDLE NdisBindingHandle
,
1170 IN NDIS_HANDLE MacReceiveContext
,
1172 IN UINT BytesToTransfer
,
1173 IN OUT PNDIS_PACKET Packet
,
1174 OUT PUINT BytesTransferred
)
1176 * FUNCTION: Forwards a request to copy received data into a protocol-supplied packet
1178 * Status = Address of buffer for status information
1179 * NdisBindingHandle = Adapter binding handle
1180 * MacReceiveContext = MAC receive context
1181 * ByteOffset = Offset in packet to place data
1182 * BytesToTransfer = Number of bytes to copy into packet
1183 * Packet = Pointer to NDIS packet descriptor
1184 * BytesTransferred = Address of buffer to place number of bytes copied
1187 *Status
= ProTransferData(NdisBindingHandle
,
1200 NdisReEnumerateProtocolBindings(IN NDIS_HANDLE NdisProtocolHandle
)
1202 PPROTOCOL_BINDING Protocol
= NdisProtocolHandle
;
1203 NDIS_STATUS NdisStatus
;
1205 ndisBindMiniportsToProtocol(&NdisStatus
, &Protocol
->Chars
);
1214 NdisGetDriverHandle(
1215 IN PNDIS_HANDLE NdisBindingHandle
,
1216 OUT PNDIS_HANDLE NdisDriverHandle
)
1224 PADAPTER_BINDING Binding
= (PADAPTER_BINDING
)NdisBindingHandle
;
1228 *NdisDriverHandle
= NULL
;
1232 *NdisDriverHandle
= Binding
->Adapter
->NdisMiniportBlock
.DriverHandle
;