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
);
284 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
286 if (BufferedLength
> Adapter
->MediumHeaderSize
)
288 /* XXX Change this to call SendPackets so we don't have to duplicate this wacky logic */
289 MiniIndicateData(Adapter
, NULL
, LookaheadBuffer
, Adapter
->MediumHeaderSize
,
290 &LookaheadBuffer
[Adapter
->MediumHeaderSize
], BufferedLength
- Adapter
->MediumHeaderSize
,
291 PacketLength
- Adapter
->MediumHeaderSize
);
295 MiniIndicateData(Adapter
, NULL
, LookaheadBuffer
, Adapter
->MediumHeaderSize
, NULL
, 0, 0);
298 ExFreePool(LookaheadBuffer
);
300 return NDIS_STATUS_SUCCESS
;
306 IN NDIS_HANDLE MacBindingHandle
,
307 IN PNDIS_REQUEST NdisRequest
)
309 * FUNCTION: Forwards a request to an NDIS miniport
311 * MacBindingHandle = Adapter binding handle
312 * NdisRequest = Pointer to request to perform
314 * Status of operation
317 PADAPTER_BINDING AdapterBinding
;
318 PLOGICAL_ADAPTER Adapter
;
319 PNDIS_REQUEST_MAC_BLOCK MacBlock
= (PNDIS_REQUEST_MAC_BLOCK
)NdisRequest
->MacReserved
;
321 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
323 ASSERT(MacBindingHandle
);
324 AdapterBinding
= GET_ADAPTER_BINDING(MacBindingHandle
);
326 ASSERT(AdapterBinding
->Adapter
);
327 Adapter
= AdapterBinding
->Adapter
;
329 MacBlock
->Binding
= &AdapterBinding
->NdisOpenBlock
;
332 MiniQueueWorkItem(Adapter
, NdisWorkItemRequest
, NdisRequest
, FALSE
);
333 return NDIS_STATUS_PENDING
;
335 if (MiniIsBusy(Adapter
, NdisWorkItemRequest
)) {
336 MiniQueueWorkItem(Adapter
, NdisWorkItemRequest
, NdisRequest
, FALSE
);
337 return NDIS_STATUS_PENDING
;
340 return MiniDoRequest(Adapter
, NdisRequest
);
347 IN NDIS_HANDLE MacBindingHandle
)
349 PADAPTER_BINDING AdapterBinding
= MacBindingHandle
;
351 /* FIXME: Wait for all packets to be sent */
353 return MiniReset(AdapterBinding
->Adapter
);
357 ScatterGatherSendPacket(
358 IN PDEVICE_OBJECT DeviceObject
,
360 IN PSCATTER_GATHER_LIST ScatterGather
,
363 PDMA_CONTEXT DmaContext
= Context
;
364 PLOGICAL_ADAPTER Adapter
= DmaContext
->Adapter
;
365 PNDIS_PACKET Packet
= DmaContext
->Packet
;
368 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
370 NDIS_PER_PACKET_INFO_FROM_PACKET(Packet
,
371 ScatterGatherListPacketInfo
) = ScatterGather
;
373 Status
= proSendPacketToMiniport(Adapter
, Packet
);
375 if (Status
!= NDIS_STATUS_PENDING
) {
376 NDIS_DbgPrint(MAX_TRACE
, ("Completing packet.\n"));
377 MiniSendComplete(Adapter
,
382 ExFreePool(DmaContext
);
386 proSendPacketToMiniport(PLOGICAL_ADAPTER Adapter
, PNDIS_PACKET Packet
)
389 MiniQueueWorkItem(Adapter
, NdisWorkItemSend
, Packet
, FALSE
);
390 return NDIS_STATUS_PENDING
;
393 NDIS_STATUS NdisStatus
;
395 if(MiniIsBusy(Adapter
, NdisWorkItemSend
)) {
396 MiniQueueWorkItem(Adapter
, NdisWorkItemSend
, Packet
, FALSE
);
397 return NDIS_STATUS_PENDING
;
400 if(Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendPacketsHandler
)
402 if(Adapter
->NdisMiniportBlock
.Flags
& NDIS_ATTRIBUTE_DESERIALIZE
)
404 NDIS_DbgPrint(MAX_TRACE
, ("Calling miniport's SendPackets handler\n"));
405 (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendPacketsHandler
)(
406 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, &Packet
, 1);
407 NdisStatus
= NDIS_STATUS_PENDING
;
409 /* SendPackets is called at DISPATCH_LEVEL for all serialized miniports */
410 KeRaiseIrql(DISPATCH_LEVEL
, &RaiseOldIrql
);
412 NDIS_DbgPrint(MAX_TRACE
, ("Calling miniport's SendPackets handler\n"));
413 (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendPacketsHandler
)(
414 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, &Packet
, 1);
416 KeLowerIrql(RaiseOldIrql
);
418 NdisStatus
= NDIS_GET_PACKET_STATUS(Packet
);
419 if (NdisStatus
== NDIS_STATUS_RESOURCES
) {
420 MiniQueueWorkItem(Adapter
, NdisWorkItemSend
, Packet
, TRUE
);
421 NdisStatus
= NDIS_STATUS_PENDING
;
427 if(Adapter
->NdisMiniportBlock
.Flags
& NDIS_ATTRIBUTE_DESERIALIZE
)
429 NDIS_DbgPrint(MAX_TRACE
, ("Calling miniport's Send handler\n"));
430 NdisStatus
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendHandler
)(
431 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, Packet
, Packet
->Private
.Flags
);
432 NDIS_DbgPrint(MAX_TRACE
, ("back from miniport's send handler\n"));
434 /* Send is called at DISPATCH_LEVEL for all serialized miniports */
435 KeRaiseIrql(DISPATCH_LEVEL
, &RaiseOldIrql
);
436 NDIS_DbgPrint(MAX_TRACE
, ("Calling miniport's Send handler\n"));
437 NdisStatus
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendHandler
)(
438 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, Packet
, Packet
->Private
.Flags
);
439 NDIS_DbgPrint(MAX_TRACE
, ("back from miniport's send handler\n"));
440 KeLowerIrql(RaiseOldIrql
);
442 if (NdisStatus
== NDIS_STATUS_RESOURCES
) {
443 MiniQueueWorkItem(Adapter
, NdisWorkItemSend
, Packet
, TRUE
);
444 NdisStatus
= NDIS_STATUS_PENDING
;
456 IN NDIS_HANDLE MacBindingHandle
,
457 IN PNDIS_PACKET Packet
)
459 * FUNCTION: Forwards a request to send a packet to an NDIS miniport
461 * MacBindingHandle = Adapter binding handle
462 * Packet = Pointer to NDIS packet descriptor
464 * NDIS_STATUS_SUCCESS if the packet was successfully sent
465 * NDIS_STATUS_PENDING if the miniport was busy or a serialized miniport returned NDIS_STATUS_RESOURCES
468 PADAPTER_BINDING AdapterBinding
;
469 PLOGICAL_ADAPTER Adapter
;
470 PNDIS_BUFFER NdisBuffer
;
471 PDMA_CONTEXT Context
;
472 NDIS_STATUS NdisStatus
;
476 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
478 ASSERT(MacBindingHandle
);
479 AdapterBinding
= GET_ADAPTER_BINDING(MacBindingHandle
);
481 ASSERT(AdapterBinding
);
482 Adapter
= AdapterBinding
->Adapter
;
486 /* if the following is not true, KeRaiseIrql() below will break */
487 ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL
);
489 /* XXX what is this crazy black magic? */
490 Packet
->Reserved
[1] = (ULONG_PTR
)MacBindingHandle
;
493 * Test the packet to see if it is a MAC loopback.
495 * We may have to loop this packet if miniport cannot.
496 * If dest MAC address of packet == MAC address of adapter,
497 * this is a loopback frame.
500 if ((Adapter
->NdisMiniportBlock
.MacOptions
& NDIS_MAC_OPTION_NO_LOOPBACK
) &&
501 MiniAdapterHasAddress(Adapter
, Packet
))
504 MiniQueueWorkItem(Adapter
, NdisWorkItemSendLoopback
, Packet
, FALSE
);
505 return NDIS_STATUS_PENDING
;
507 return ProIndicatePacket(Adapter
, Packet
);
510 if (Adapter
->NdisMiniportBlock
.ScatterGatherListSize
!= 0)
512 NDIS_DbgPrint(MIN_TRACE
, ("Using Scatter/Gather DMA\n"));
514 NdisQueryPacket(Packet
,
520 Context
= ExAllocatePool(NonPagedPool
, sizeof(DMA_CONTEXT
));
522 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources\n"));
523 return NDIS_STATUS_RESOURCES
;
526 Context
->Adapter
= Adapter
;
527 Context
->Packet
= Packet
;
529 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
531 KeFlushIoBuffers(NdisBuffer
, FALSE
, TRUE
);
533 NdisStatus
= Adapter
->NdisMiniportBlock
.SystemAdapterObject
->DmaOperations
->GetScatterGatherList(
534 Adapter
->NdisMiniportBlock
.SystemAdapterObject
,
535 Adapter
->NdisMiniportBlock
.PhysicalDeviceObject
,
537 MmGetMdlVirtualAddress(NdisBuffer
),
539 ScatterGatherSendPacket
,
543 KeLowerIrql(OldIrql
);
545 if (!NT_SUCCESS(NdisStatus
)) {
546 NDIS_DbgPrint(MIN_TRACE
, ("GetScatterGatherList failed! (%x)\n", NdisStatus
));
550 return NDIS_STATUS_PENDING
;
554 return proSendPacketToMiniport(Adapter
, Packet
);
561 IN NDIS_HANDLE NdisBindingHandle
,
562 IN PPNDIS_PACKET PacketArray
,
563 IN UINT NumberOfPackets
)
565 PADAPTER_BINDING AdapterBinding
= NdisBindingHandle
;
566 PLOGICAL_ADAPTER Adapter
= AdapterBinding
->Adapter
;
568 NDIS_STATUS NdisStatus
;
571 if(Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendPacketsHandler
)
573 if(Adapter
->NdisMiniportBlock
.Flags
& NDIS_ATTRIBUTE_DESERIALIZE
)
575 (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendPacketsHandler
)(
576 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, PacketArray
, NumberOfPackets
);
580 /* SendPackets is called at DISPATCH_LEVEL for all serialized miniports */
581 KeRaiseIrql(DISPATCH_LEVEL
, &RaiseOldIrql
);
582 (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendPacketsHandler
)(
583 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, PacketArray
, NumberOfPackets
);
584 KeLowerIrql(RaiseOldIrql
);
585 for (i
= 0; i
< NumberOfPackets
; i
++)
587 NdisStatus
= NDIS_GET_PACKET_STATUS(PacketArray
[i
]);
588 if (NdisStatus
!= NDIS_STATUS_PENDING
)
589 MiniSendComplete(Adapter
, PacketArray
[i
], NdisStatus
);
595 if(Adapter
->NdisMiniportBlock
.Flags
& NDIS_ATTRIBUTE_DESERIALIZE
)
597 for (i
= 0; i
< NumberOfPackets
; i
++)
599 NdisStatus
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendHandler
)(
600 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, PacketArray
[i
], PacketArray
[i
]->Private
.Flags
);
601 if (NdisStatus
!= NDIS_STATUS_PENDING
)
602 MiniSendComplete(Adapter
, PacketArray
[i
], NdisStatus
);
607 /* Send is called at DISPATCH_LEVEL for all serialized miniports */
608 KeRaiseIrql(DISPATCH_LEVEL
, &RaiseOldIrql
);
609 for (i
= 0; i
< NumberOfPackets
; i
++)
611 NdisStatus
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendHandler
)(
612 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, PacketArray
[i
], PacketArray
[i
]->Private
.Flags
);
613 if (NdisStatus
!= NDIS_STATUS_PENDING
)
614 MiniSendComplete(Adapter
, PacketArray
[i
], NdisStatus
);
616 KeLowerIrql(RaiseOldIrql
);
624 IN NDIS_HANDLE MacBindingHandle
,
625 IN NDIS_HANDLE MacReceiveContext
,
627 IN UINT BytesToTransfer
,
628 IN OUT PNDIS_PACKET Packet
,
629 OUT PUINT BytesTransferred
)
631 * FUNCTION: Forwards a request to copy received data into a protocol-supplied packet
633 * MacBindingHandle = Adapter binding handle
634 * MacReceiveContext = MAC receive context
635 * ByteOffset = Offset in packet to place data
636 * BytesToTransfer = Number of bytes to copy into packet
637 * Packet = Pointer to NDIS packet descriptor
638 * BytesTransferred = Address of buffer to place number of bytes copied
641 PADAPTER_BINDING AdapterBinding
= GET_ADAPTER_BINDING(MacBindingHandle
);
642 PLOGICAL_ADAPTER Adapter
= AdapterBinding
->Adapter
;
646 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
648 /* FIXME: Interrupts must be disabled for adapter */
649 /* XXX sd - why is that true? */
651 if (Packet
== Adapter
->NdisMiniportBlock
.IndicatedPacket
[KeGetCurrentProcessorNumber()]) {
652 NDIS_DbgPrint(MAX_TRACE
, ("LoopPacket\n"));
653 /* NDIS is responsible for looping this packet */
654 NdisCopyFromPacketToPacket(Packet
,
657 Adapter
->NdisMiniportBlock
.IndicatedPacket
[KeGetCurrentProcessorNumber()],
660 return NDIS_STATUS_SUCCESS
;
663 ASSERT(Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.TransferDataHandler
);
665 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
667 Status
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.TransferDataHandler
)(
670 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
,
675 KeLowerIrql(OldIrql
);
688 OUT PNDIS_STATUS Status
,
689 IN NDIS_HANDLE NdisBindingHandle
)
691 * FUNCTION: Closes an adapter opened with NdisOpenAdapter
693 * Status = Address of buffer for status information
694 * NdisBindingHandle = Handle returned by NdisOpenAdapter
697 PADAPTER_BINDING AdapterBinding
= GET_ADAPTER_BINDING(NdisBindingHandle
);
699 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
701 /* Remove from protocol's bound adapters list */
702 ExInterlockedRemoveEntryList(&AdapterBinding
->ProtocolListEntry
, &AdapterBinding
->ProtocolBinding
->Lock
);
704 /* Remove protocol from adapter's bound protocols list */
705 ExInterlockedRemoveEntryList(&AdapterBinding
->AdapterListEntry
, &AdapterBinding
->Adapter
->NdisMiniportBlock
.Lock
);
707 ExFreePool(AdapterBinding
);
709 *Status
= NDIS_STATUS_SUCCESS
;
718 NdisDeregisterProtocol(
719 OUT PNDIS_STATUS Status
,
720 IN NDIS_HANDLE NdisProtocolHandle
)
722 * FUNCTION: Releases the resources allocated by NdisRegisterProtocol
724 * Status = Address of buffer for status information
725 * NdisProtocolHandle = Handle returned by NdisRegisterProtocol
728 PPROTOCOL_BINDING Protocol
= GET_PROTOCOL_BINDING(NdisProtocolHandle
);
730 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
732 /* FIXME: Make sure no adapter bindings exist */
734 /* Remove protocol from global list */
735 ExInterlockedRemoveEntryList(&Protocol
->ListEntry
, &ProtocolListLock
);
737 ExFreePool(Protocol
);
739 *Status
= NDIS_STATUS_SUCCESS
;
749 OUT PNDIS_STATUS Status
,
750 OUT PNDIS_STATUS OpenErrorStatus
,
751 OUT PNDIS_HANDLE NdisBindingHandle
,
752 OUT PUINT SelectedMediumIndex
,
753 IN PNDIS_MEDIUM MediumArray
,
754 IN UINT MediumArraySize
,
755 IN NDIS_HANDLE NdisProtocolHandle
,
756 IN NDIS_HANDLE ProtocolBindingContext
,
757 IN PNDIS_STRING AdapterName
,
759 IN PSTRING AddressingInformation OPTIONAL
)
761 * FUNCTION: Opens an adapter for communication
763 * Status = Address of buffer for status information
764 * OpenErrorStatus = Address of buffer for secondary error code
765 * NdisBindingHandle = Address of buffer for adapter binding handle
766 * SelectedMediumIndex = Address of buffer for selected medium
767 * MediumArray = Pointer to an array of NDIS_MEDIUMs called can support
768 * MediumArraySize = Number of elements in MediumArray
769 * NdisProtocolHandle = Handle returned by NdisRegisterProtocol
770 * ProtocolBindingContext = Pointer to caller suplied context area
771 * AdapterName = Pointer to buffer with name of adapter
772 * OpenOptions = Bitmask with flags passed to next-lower driver
773 * AddressingInformation = Optional pointer to buffer with NIC specific information
778 PLOGICAL_ADAPTER Adapter
;
779 PADAPTER_BINDING AdapterBinding
;
780 PPROTOCOL_BINDING Protocol
= GET_PROTOCOL_BINDING(NdisProtocolHandle
);
782 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
784 if(!NdisProtocolHandle
)
786 NDIS_DbgPrint(MIN_TRACE
, ("NdisProtocolHandle is NULL\n"));
787 *OpenErrorStatus
= *Status
= NDIS_STATUS_FAILURE
;
791 Adapter
= MiniLocateDevice(AdapterName
);
794 NDIS_DbgPrint(MIN_TRACE
, ("Adapter not found.\n"));
795 *Status
= NDIS_STATUS_ADAPTER_NOT_FOUND
;
799 /* Find the media type in the list provided by the protocol driver */
801 for (i
= 0; i
< MediumArraySize
; i
++)
803 if (Adapter
->NdisMiniportBlock
.MediaType
== MediumArray
[i
])
805 *SelectedMediumIndex
= i
;
813 NDIS_DbgPrint(MIN_TRACE
, ("Medium is not supported.\n"));
814 *Status
= NDIS_STATUS_UNSUPPORTED_MEDIA
;
818 /* Now that we have confirmed that the adapter can be opened, create a binding */
820 AdapterBinding
= ExAllocatePool(NonPagedPool
, sizeof(ADAPTER_BINDING
));
823 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
824 *Status
= NDIS_STATUS_RESOURCES
;
828 RtlZeroMemory(AdapterBinding
, sizeof(ADAPTER_BINDING
));
830 AdapterBinding
->ProtocolBinding
= Protocol
;
831 AdapterBinding
->Adapter
= Adapter
;
832 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
= ProtocolBindingContext
;
834 /* Set fields required by some NDIS macros */
835 AdapterBinding
->NdisOpenBlock
.BindingHandle
= (NDIS_HANDLE
)AdapterBinding
;
837 /* Set handlers (some NDIS macros require these) */
839 AdapterBinding
->NdisOpenBlock
.RequestHandler
= ProRequest
;
840 AdapterBinding
->NdisOpenBlock
.ResetHandler
= ProReset
;
841 AdapterBinding
->NdisOpenBlock
.SendHandler
= ProSend
;
842 AdapterBinding
->NdisOpenBlock
.SendPacketsHandler
= ProSendPackets
;
843 AdapterBinding
->NdisOpenBlock
.TransferDataHandler
= ProTransferData
;
845 AdapterBinding
->NdisOpenBlock
.RequestCompleteHandler
=
846 Protocol
->Chars
.RequestCompleteHandler
;
848 /* Put on protocol's bound adapters list */
849 ExInterlockedInsertTailList(&Protocol
->AdapterListHead
, &AdapterBinding
->ProtocolListEntry
, &Protocol
->Lock
);
851 /* Put protocol on adapter's bound protocols list */
852 NDIS_DbgPrint(MAX_TRACE
, ("acquiring miniport block lock\n"));
853 ExInterlockedInsertTailList(&Adapter
->ProtocolListHead
, &AdapterBinding
->AdapterListEntry
, &Adapter
->NdisMiniportBlock
.Lock
);
855 *NdisBindingHandle
= (NDIS_HANDLE
)AdapterBinding
;
857 *Status
= NDIS_STATUS_SUCCESS
;
862 ndisBindMiniportsToProtocol(OUT PNDIS_STATUS Status
, IN PNDIS_PROTOCOL_CHARACTERISTICS ProtocolCharacteristics
)
865 * bind the protocol to all of its miniports
868 * get list of devices from Bind key
869 * call BindAdapterHandler for each
871 OBJECT_ATTRIBUTES ObjectAttributes
;
872 UNICODE_STRING RegistryPath
;
873 WCHAR
*RegistryPathStr
;
876 HANDLE DriverKeyHandle
= NULL
;
877 PKEY_VALUE_PARTIAL_INFORMATION KeyInformation
= NULL
;
879 RegistryPathStr
= ExAllocatePoolWithTag(PagedPool
, sizeof(SERVICES_KEY
) + ProtocolCharacteristics
->Name
.Length
+ sizeof(LINKAGE_KEY
), NDIS_TAG
+ __LINE__
);
882 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
883 *Status
= NDIS_STATUS_RESOURCES
;
887 wcscpy(RegistryPathStr
, SERVICES_KEY
);
888 wcsncat(RegistryPathStr
, ((WCHAR
*)ProtocolCharacteristics
->Name
.Buffer
), ProtocolCharacteristics
->Name
.Length
/ sizeof(WCHAR
));
889 RegistryPathStr
[wcslen(SERVICES_KEY
)+ProtocolCharacteristics
->Name
.Length
/sizeof(WCHAR
)] = 0;
890 wcscat(RegistryPathStr
, LINKAGE_KEY
);
892 RtlInitUnicodeString(&RegistryPath
, RegistryPathStr
);
893 NDIS_DbgPrint(MAX_TRACE
, ("Opening configuration key: %wZ\n", &RegistryPath
));
895 InitializeObjectAttributes(&ObjectAttributes
, &RegistryPath
, OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
896 NtStatus
= ZwOpenKey(&DriverKeyHandle
, KEY_READ
, &ObjectAttributes
);
898 ExFreePool(RegistryPathStr
);
900 if(!NT_SUCCESS(NtStatus
))
902 NDIS_DbgPrint(MIN_TRACE
, ("Unable to open protocol configuration\n"));
903 *Status
= NDIS_STATUS_FAILURE
;
907 NDIS_DbgPrint(MAX_TRACE
, ("Successfully opened the registry configuration\n"));
910 UNICODE_STRING ValueName
;
913 RtlInitUnicodeString(&ValueName
, L
"Bind");
915 NtStatus
= ZwQueryValueKey(DriverKeyHandle
, &ValueName
, KeyValuePartialInformation
, NULL
, 0, &ResultLength
);
916 if(NtStatus
!= STATUS_BUFFER_OVERFLOW
&& NtStatus
!= STATUS_BUFFER_TOO_SMALL
&& NtStatus
!= STATUS_SUCCESS
)
918 NDIS_DbgPrint(MIN_TRACE
, ("Unable to query the Bind value for size\n"));
919 ZwClose(DriverKeyHandle
);
920 *Status
= NDIS_STATUS_FAILURE
;
924 KeyInformation
= ExAllocatePoolWithTag(PagedPool
, sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + ResultLength
, NDIS_TAG
+ __LINE__
);
927 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
928 ZwClose(DriverKeyHandle
);
929 *Status
= NDIS_STATUS_FAILURE
;
933 NtStatus
= ZwQueryValueKey(DriverKeyHandle
, &ValueName
, KeyValuePartialInformation
, KeyInformation
,
934 sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + ResultLength
, &ResultLength
);
936 ZwClose(DriverKeyHandle
);
938 if(!NT_SUCCESS(NtStatus
))
940 NDIS_DbgPrint(MIN_TRACE
, ("Unable to query the Bind value\n"));
941 ExFreePool(KeyInformation
);
942 *Status
= NDIS_STATUS_FAILURE
;
947 for (DataPtr
= (WCHAR
*)KeyInformation
->Data
;
949 DataPtr
+= wcslen(DataPtr
) + 1)
951 /* BindContext is for tracking pending binding operations */
952 VOID
*BindContext
= 0;
953 NDIS_STRING DeviceName
;
954 NDIS_STRING RegistryPath
;
955 WCHAR
*RegistryPathStr
= NULL
;
956 ULONG PathLength
= 0;
958 RtlInitUnicodeString(&DeviceName
, DataPtr
); /* we know this is 0-term */
961 * RegistryPath should be:
962 * \Registry\Machine\System\CurrentControlSet\Services\Nic1\Parameters\Tcpip
964 * This is constructed as follows:
965 * SERVICES_KEY + extracted device name + Protocol name from characteristics
968 PathLength
= sizeof(SERVICES_KEY
) + /* \Registry\Machine\System\CurrentControlSet\Services\ */
969 wcslen( DataPtr
+ 8 ) * sizeof(WCHAR
) + /* Adapter1 (extracted from \Device\Adapter1) */
970 sizeof(PARAMETERS_KEY
) + /* \Parameters\ */
971 ProtocolCharacteristics
->Name
.Length
+ sizeof(WCHAR
); /* Tcpip */
973 RegistryPathStr
= ExAllocatePool(PagedPool
, PathLength
);
976 NDIS_DbgPrint(MIN_TRACE
, ("insufficient resources.\n"));
977 ExFreePool(KeyInformation
);
978 *Status
= NDIS_STATUS_RESOURCES
;
982 wcscpy(RegistryPathStr
, SERVICES_KEY
);
983 wcscat(RegistryPathStr
, DataPtr
+ 8 );
984 wcscat(RegistryPathStr
, PARAMETERS_KEY
);
985 wcsncat(RegistryPathStr
, ProtocolCharacteristics
->Name
.Buffer
, ProtocolCharacteristics
->Name
.Length
/ sizeof(WCHAR
) );
987 RegistryPathStr
[PathLength
/sizeof(WCHAR
) - 1] = 0;
989 RtlInitUnicodeString(&RegistryPath
, RegistryPathStr
);
991 NDIS_DbgPrint(MAX_TRACE
, ("Calling protocol's BindAdapter handler with DeviceName %wZ and RegistryPath %wZ\n",
992 &DeviceName
, &RegistryPath
));
995 BIND_HANDLER BindHandler
= ProtocolCharacteristics
->BindAdapterHandler
;
997 BindHandler(Status
, BindContext
, &DeviceName
, &RegistryPath
, 0);
999 NDIS_DbgPrint(MIN_TRACE
, ("No protocol bind handler specified\n"));
1003 *Status
= NDIS_STATUS_SUCCESS
;
1004 ExFreePool(KeyInformation
);
1012 NdisRegisterProtocol(
1013 OUT PNDIS_STATUS Status
,
1014 OUT PNDIS_HANDLE NdisProtocolHandle
,
1015 IN PNDIS_PROTOCOL_CHARACTERISTICS ProtocolCharacteristics
,
1016 IN UINT CharacteristicsLength
)
1018 * FUNCTION: Registers an NDIS driver's ProtocolXxx entry points
1020 * Status = Address of buffer for status information
1021 * NdisProtocolHandle = Address of buffer for handle used to identify the driver
1022 * ProtocolCharacteristics = Pointer to NDIS_PROTOCOL_CHARACTERISTICS structure
1023 * CharacteristicsLength = Size of structure which ProtocolCharacteristics targets
1025 * - you *must* set NdisProtocolHandle before doing anything that could wind up
1026 * getting BindAdapterHandler, as it will probably call OpenAdapter with this handle
1027 * - the above implies that the initialization of the protocol block must be complete
1030 * - break this function up - probably do a 'ndisRefreshProtocolBindings' function
1031 * - make this thing able to handle >1 protocol
1034 PPROTOCOL_BINDING Protocol
;
1037 PNET_PNP_EVENT PnPEvent
;
1039 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
1041 *NdisProtocolHandle
= NULL
;
1043 /* first validate the PROTOCOL_CHARACTERISTICS */
1044 switch (ProtocolCharacteristics
->MajorNdisVersion
)
1047 /* we don't really want to support ndis3 drivers - so we complain for now */
1048 NDIS_DbgPrint(MID_TRACE
, ("NDIS 3 protocol attempting to register\n"));
1049 MinSize
= sizeof(NDIS30_PROTOCOL_CHARACTERISTICS
);
1053 MinSize
= sizeof(NDIS40_PROTOCOL_CHARACTERISTICS
);
1057 MinSize
= sizeof(NDIS50_PROTOCOL_CHARACTERISTICS
);
1061 *Status
= NDIS_STATUS_BAD_VERSION
;
1062 NDIS_DbgPrint(MIN_TRACE
, ("Incorrect characteristics size\n"));
1066 if (CharacteristicsLength
< MinSize
)
1068 NDIS_DbgPrint(MIN_TRACE
, ("Bad protocol characteristics.\n"));
1069 *Status
= NDIS_STATUS_BAD_CHARACTERISTICS
;
1073 /* set up the protocol block */
1074 Protocol
= ExAllocatePool(NonPagedPool
, sizeof(PROTOCOL_BINDING
));
1077 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
1078 *Status
= NDIS_STATUS_RESOURCES
;
1082 RtlZeroMemory(Protocol
, sizeof(PROTOCOL_BINDING
));
1083 RtlCopyMemory(&Protocol
->Chars
, ProtocolCharacteristics
, MinSize
);
1085 NtStatus
= RtlUpcaseUnicodeString(&Protocol
->Chars
.Name
, &ProtocolCharacteristics
->Name
, TRUE
);
1086 if (!NT_SUCCESS(NtStatus
))
1088 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
1089 ExFreePool(Protocol
);
1090 *Status
= NDIS_STATUS_RESOURCES
;
1094 KeInitializeSpinLock(&Protocol
->Lock
);
1096 InitializeListHead(&Protocol
->AdapterListHead
);
1098 /* We must set this before the call to ndisBindMiniportsToProtocol because the protocol's
1099 * BindAdapter handler might need it */
1101 *NdisProtocolHandle
= Protocol
;
1103 ndisBindMiniportsToProtocol(Status
, &Protocol
->Chars
);
1105 /* Should we only send this if ndisBindMiniportsToProtocol succeeds? */
1106 PnPEvent
= ProSetupPnPEvent(NetEventBindsComplete
, NULL
, 0);
1109 if (Protocol
->Chars
.PnPEventHandler
)
1111 /* We call this with a NULL binding context because it affects all bindings */
1112 NtStatus
= (*Protocol
->Chars
.PnPEventHandler
)(NULL
,
1115 /* FIXME: We don't support this yet */
1116 ASSERT(NtStatus
!= NDIS_STATUS_PENDING
);
1119 ExFreePool(PnPEvent
);
1122 if (*Status
== NDIS_STATUS_SUCCESS
) {
1123 ExInterlockedInsertTailList(&ProtocolListHead
, &Protocol
->ListEntry
, &ProtocolListLock
);
1125 NDIS_DbgPrint(MIN_TRACE
, ("Binding failed (%x)\n", *Status
));
1126 ExFreePool(Protocol
);
1127 *NdisProtocolHandle
= NULL
;
1138 OUT PNDIS_STATUS Status
,
1139 IN NDIS_HANDLE NdisBindingHandle
,
1140 IN PNDIS_REQUEST NdisRequest
)
1142 * FUNCTION: Forwards a request to an NDIS driver
1144 * Status = Address of buffer for status information
1145 * NdisBindingHandle = Adapter binding handle
1146 * NdisRequest = Pointer to request to perform
1149 *Status
= ProRequest(NdisBindingHandle
, NdisRequest
);
1159 OUT PNDIS_STATUS Status
,
1160 IN NDIS_HANDLE NdisBindingHandle
)
1162 *Status
= ProReset(NdisBindingHandle
);
1173 OUT PNDIS_STATUS Status
,
1174 IN NDIS_HANDLE NdisBindingHandle
,
1175 IN PNDIS_PACKET Packet
)
1177 * FUNCTION: Forwards a request to send a packet
1179 * Status = Address of buffer for status information
1180 * NdisBindingHandle = Adapter binding handle
1181 * Packet = Pointer to NDIS packet descriptor
1184 *Status
= ProSend(NdisBindingHandle
, Packet
);
1191 #undef NdisSendPackets
1195 IN NDIS_HANDLE NdisBindingHandle
,
1196 IN PPNDIS_PACKET PacketArray
,
1197 IN UINT NumberOfPackets
)
1199 ProSendPackets(NdisBindingHandle
, PacketArray
, NumberOfPackets
);
1206 #undef NdisTransferData
1210 OUT PNDIS_STATUS Status
,
1211 IN NDIS_HANDLE NdisBindingHandle
,
1212 IN NDIS_HANDLE MacReceiveContext
,
1214 IN UINT BytesToTransfer
,
1215 IN OUT PNDIS_PACKET Packet
,
1216 OUT PUINT BytesTransferred
)
1218 * FUNCTION: Forwards a request to copy received data into a protocol-supplied packet
1220 * Status = Address of buffer for status information
1221 * NdisBindingHandle = Adapter binding handle
1222 * MacReceiveContext = MAC receive context
1223 * ByteOffset = Offset in packet to place data
1224 * BytesToTransfer = Number of bytes to copy into packet
1225 * Packet = Pointer to NDIS packet descriptor
1226 * BytesTransferred = Address of buffer to place number of bytes copied
1229 *Status
= ProTransferData(NdisBindingHandle
,
1242 NdisReEnumerateProtocolBindings(IN NDIS_HANDLE NdisProtocolHandle
)
1244 PPROTOCOL_BINDING Protocol
= NdisProtocolHandle
;
1245 NDIS_STATUS NdisStatus
;
1247 ndisBindMiniportsToProtocol(&NdisStatus
, &Protocol
->Chars
);
1256 NdisGetDriverHandle(
1257 IN PNDIS_HANDLE NdisBindingHandle
,
1258 OUT PNDIS_HANDLE NdisDriverHandle
)
1266 PADAPTER_BINDING Binding
= (PADAPTER_BINDING
)NdisBindingHandle
;
1270 NDIS_DbgPrint(MIN_TRACE
, ("Bad binding handle\n"));
1271 *NdisDriverHandle
= NULL
;
1275 *NdisDriverHandle
= Binding
->Adapter
->NdisMiniportBlock
.DriverHandle
;