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
)
351 return NDIS_STATUS_FAILURE
;
355 ScatterGatherSendPacket(
356 IN PDEVICE_OBJECT DeviceObject
,
358 IN PSCATTER_GATHER_LIST ScatterGather
,
361 PDMA_CONTEXT DmaContext
= Context
;
362 PLOGICAL_ADAPTER Adapter
= DmaContext
->Adapter
;
363 PNDIS_PACKET Packet
= DmaContext
->Packet
;
366 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
368 NDIS_PER_PACKET_INFO_FROM_PACKET(Packet
,
369 ScatterGatherListPacketInfo
) = ScatterGather
;
371 Status
= proSendPacketToMiniport(Adapter
, Packet
);
373 if (Status
!= NDIS_STATUS_PENDING
) {
374 NDIS_DbgPrint(MAX_TRACE
, ("Completing packet.\n"));
375 MiniSendComplete(Adapter
,
380 ExFreePool(DmaContext
);
384 proSendPacketToMiniport(PLOGICAL_ADAPTER Adapter
, PNDIS_PACKET Packet
)
387 MiniQueueWorkItem(Adapter
, NdisWorkItemSend
, Packet
, FALSE
);
388 return NDIS_STATUS_PENDING
;
391 NDIS_STATUS NdisStatus
;
393 if(MiniIsBusy(Adapter
, NdisWorkItemSend
)) {
394 MiniQueueWorkItem(Adapter
, NdisWorkItemSend
, Packet
, FALSE
);
395 return NDIS_STATUS_PENDING
;
398 if(Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendPacketsHandler
)
400 if(Adapter
->NdisMiniportBlock
.Flags
& NDIS_ATTRIBUTE_DESERIALIZE
)
402 NDIS_DbgPrint(MAX_TRACE
, ("Calling miniport's SendPackets handler\n"));
403 (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendPacketsHandler
)(
404 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, &Packet
, 1);
405 NdisStatus
= NDIS_STATUS_PENDING
;
407 /* SendPackets is called at DISPATCH_LEVEL for all serialized miniports */
408 KeRaiseIrql(DISPATCH_LEVEL
, &RaiseOldIrql
);
410 NDIS_DbgPrint(MAX_TRACE
, ("Calling miniport's SendPackets handler\n"));
411 (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendPacketsHandler
)(
412 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, &Packet
, 1);
414 KeLowerIrql(RaiseOldIrql
);
416 NdisStatus
= NDIS_GET_PACKET_STATUS(Packet
);
417 if (NdisStatus
== NDIS_STATUS_RESOURCES
) {
418 MiniQueueWorkItem(Adapter
, NdisWorkItemSend
, Packet
, TRUE
);
419 NdisStatus
= NDIS_STATUS_PENDING
;
425 if(Adapter
->NdisMiniportBlock
.Flags
& NDIS_ATTRIBUTE_DESERIALIZE
)
427 NDIS_DbgPrint(MAX_TRACE
, ("Calling miniport's Send handler\n"));
428 NdisStatus
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendHandler
)(
429 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, Packet
, Packet
->Private
.Flags
);
430 NDIS_DbgPrint(MAX_TRACE
, ("back from miniport's send handler\n"));
432 /* Send is called at DISPATCH_LEVEL for all serialized miniports */
433 KeRaiseIrql(DISPATCH_LEVEL
, &RaiseOldIrql
);
434 NDIS_DbgPrint(MAX_TRACE
, ("Calling miniport's Send handler\n"));
435 NdisStatus
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendHandler
)(
436 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, Packet
, Packet
->Private
.Flags
);
437 NDIS_DbgPrint(MAX_TRACE
, ("back from miniport's send handler\n"));
438 KeLowerIrql(RaiseOldIrql
);
440 if (NdisStatus
== NDIS_STATUS_RESOURCES
) {
441 MiniQueueWorkItem(Adapter
, NdisWorkItemSend
, Packet
, TRUE
);
442 NdisStatus
= NDIS_STATUS_PENDING
;
454 IN NDIS_HANDLE MacBindingHandle
,
455 IN PNDIS_PACKET Packet
)
457 * FUNCTION: Forwards a request to send a packet to an NDIS miniport
459 * MacBindingHandle = Adapter binding handle
460 * Packet = Pointer to NDIS packet descriptor
462 * NDIS_STATUS_SUCCESS if the packet was successfully sent
463 * NDIS_STATUS_PENDING if the miniport was busy or a serialized miniport returned NDIS_STATUS_RESOURCES
466 PADAPTER_BINDING AdapterBinding
;
467 PLOGICAL_ADAPTER Adapter
;
468 PNDIS_BUFFER NdisBuffer
;
469 PDMA_CONTEXT Context
;
470 NDIS_STATUS NdisStatus
;
474 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
476 ASSERT(MacBindingHandle
);
477 AdapterBinding
= GET_ADAPTER_BINDING(MacBindingHandle
);
479 ASSERT(AdapterBinding
);
480 Adapter
= AdapterBinding
->Adapter
;
484 /* if the following is not true, KeRaiseIrql() below will break */
485 ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL
);
487 /* XXX what is this crazy black magic? */
488 Packet
->Reserved
[1] = (ULONG_PTR
)MacBindingHandle
;
491 * Test the packet to see if it is a MAC loopback.
493 * We may have to loop this packet if miniport cannot.
494 * If dest MAC address of packet == MAC address of adapter,
495 * this is a loopback frame.
498 if ((Adapter
->NdisMiniportBlock
.MacOptions
& NDIS_MAC_OPTION_NO_LOOPBACK
) &&
499 MiniAdapterHasAddress(Adapter
, Packet
))
502 MiniQueueWorkItem(Adapter
, NdisWorkItemSendLoopback
, Packet
, FALSE
);
503 return NDIS_STATUS_PENDING
;
505 return ProIndicatePacket(Adapter
, Packet
);
508 if (Adapter
->NdisMiniportBlock
.ScatterGatherListSize
!= 0)
510 NDIS_DbgPrint(MAX_TRACE
, ("Using Scatter/Gather DMA\n"));
512 NdisQueryPacket(Packet
,
518 Context
= ExAllocatePool(NonPagedPool
, sizeof(DMA_CONTEXT
));
520 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources\n"));
521 return NDIS_STATUS_RESOURCES
;
524 Context
->Adapter
= Adapter
;
525 Context
->Packet
= Packet
;
527 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
529 KeFlushIoBuffers(NdisBuffer
, FALSE
, TRUE
);
531 NdisStatus
= Adapter
->NdisMiniportBlock
.SystemAdapterObject
->DmaOperations
->GetScatterGatherList(
532 Adapter
->NdisMiniportBlock
.SystemAdapterObject
,
533 Adapter
->NdisMiniportBlock
.PhysicalDeviceObject
,
535 MmGetMdlVirtualAddress(NdisBuffer
),
537 ScatterGatherSendPacket
,
541 KeLowerIrql(OldIrql
);
543 if (!NT_SUCCESS(NdisStatus
)) {
544 NDIS_DbgPrint(MIN_TRACE
, ("GetScatterGatherList failed! (%x)\n", NdisStatus
));
548 return NDIS_STATUS_PENDING
;
552 return proSendPacketToMiniport(Adapter
, Packet
);
559 IN NDIS_HANDLE NdisBindingHandle
,
560 IN PPNDIS_PACKET PacketArray
,
561 IN UINT NumberOfPackets
)
563 PADAPTER_BINDING AdapterBinding
= NdisBindingHandle
;
564 PLOGICAL_ADAPTER Adapter
= AdapterBinding
->Adapter
;
566 NDIS_STATUS NdisStatus
;
569 if(Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendPacketsHandler
)
571 if(Adapter
->NdisMiniportBlock
.Flags
& NDIS_ATTRIBUTE_DESERIALIZE
)
573 (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendPacketsHandler
)(
574 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, PacketArray
, NumberOfPackets
);
578 /* SendPackets is called at DISPATCH_LEVEL for all serialized miniports */
579 KeRaiseIrql(DISPATCH_LEVEL
, &RaiseOldIrql
);
580 (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendPacketsHandler
)(
581 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, PacketArray
, NumberOfPackets
);
582 KeLowerIrql(RaiseOldIrql
);
583 for (i
= 0; i
< NumberOfPackets
; i
++)
585 NdisStatus
= NDIS_GET_PACKET_STATUS(PacketArray
[i
]);
586 if (NdisStatus
!= NDIS_STATUS_PENDING
)
587 MiniSendComplete(Adapter
, PacketArray
[i
], NdisStatus
);
593 if(Adapter
->NdisMiniportBlock
.Flags
& NDIS_ATTRIBUTE_DESERIALIZE
)
595 for (i
= 0; i
< NumberOfPackets
; i
++)
597 NdisStatus
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendHandler
)(
598 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, PacketArray
[i
], PacketArray
[i
]->Private
.Flags
);
599 if (NdisStatus
!= NDIS_STATUS_PENDING
)
600 MiniSendComplete(Adapter
, PacketArray
[i
], NdisStatus
);
605 /* Send is called at DISPATCH_LEVEL for all serialized miniports */
606 KeRaiseIrql(DISPATCH_LEVEL
, &RaiseOldIrql
);
607 for (i
= 0; i
< NumberOfPackets
; i
++)
609 NdisStatus
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendHandler
)(
610 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, PacketArray
[i
], PacketArray
[i
]->Private
.Flags
);
611 if (NdisStatus
!= NDIS_STATUS_PENDING
)
612 MiniSendComplete(Adapter
, PacketArray
[i
], NdisStatus
);
614 KeLowerIrql(RaiseOldIrql
);
622 IN NDIS_HANDLE MacBindingHandle
,
623 IN NDIS_HANDLE MacReceiveContext
,
625 IN UINT BytesToTransfer
,
626 IN OUT PNDIS_PACKET Packet
,
627 OUT PUINT BytesTransferred
)
629 * FUNCTION: Forwards a request to copy received data into a protocol-supplied packet
631 * MacBindingHandle = Adapter binding handle
632 * MacReceiveContext = MAC receive context
633 * ByteOffset = Offset in packet to place data
634 * BytesToTransfer = Number of bytes to copy into packet
635 * Packet = Pointer to NDIS packet descriptor
636 * BytesTransferred = Address of buffer to place number of bytes copied
639 PADAPTER_BINDING AdapterBinding
= GET_ADAPTER_BINDING(MacBindingHandle
);
640 PLOGICAL_ADAPTER Adapter
= AdapterBinding
->Adapter
;
644 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
646 /* FIXME: Interrupts must be disabled for adapter */
647 /* XXX sd - why is that true? */
649 if (Packet
== Adapter
->NdisMiniportBlock
.IndicatedPacket
[KeGetCurrentProcessorNumber()]) {
650 NDIS_DbgPrint(MAX_TRACE
, ("LoopPacket\n"));
651 /* NDIS is responsible for looping this packet */
652 NdisCopyFromPacketToPacket(Packet
,
655 Adapter
->NdisMiniportBlock
.IndicatedPacket
[KeGetCurrentProcessorNumber()],
658 return NDIS_STATUS_SUCCESS
;
661 ASSERT(Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.TransferDataHandler
);
663 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
665 Status
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.TransferDataHandler
)(
668 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
,
673 KeLowerIrql(OldIrql
);
686 OUT PNDIS_STATUS Status
,
687 IN NDIS_HANDLE NdisBindingHandle
)
689 * FUNCTION: Closes an adapter opened with NdisOpenAdapter
691 * Status = Address of buffer for status information
692 * NdisBindingHandle = Handle returned by NdisOpenAdapter
695 PADAPTER_BINDING AdapterBinding
= GET_ADAPTER_BINDING(NdisBindingHandle
);
697 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
699 /* Remove from protocol's bound adapters list */
700 ExInterlockedRemoveEntryList(&AdapterBinding
->ProtocolListEntry
, &AdapterBinding
->ProtocolBinding
->Lock
);
702 /* Remove protocol from adapter's bound protocols list */
703 ExInterlockedRemoveEntryList(&AdapterBinding
->AdapterListEntry
, &AdapterBinding
->Adapter
->NdisMiniportBlock
.Lock
);
705 ExFreePool(AdapterBinding
);
707 *Status
= NDIS_STATUS_SUCCESS
;
716 NdisDeregisterProtocol(
717 OUT PNDIS_STATUS Status
,
718 IN NDIS_HANDLE NdisProtocolHandle
)
720 * FUNCTION: Releases the resources allocated by NdisRegisterProtocol
722 * Status = Address of buffer for status information
723 * NdisProtocolHandle = Handle returned by NdisRegisterProtocol
726 PPROTOCOL_BINDING Protocol
= GET_PROTOCOL_BINDING(NdisProtocolHandle
);
728 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
730 /* FIXME: Make sure no adapter bindings exist */
732 /* Remove protocol from global list */
733 ExInterlockedRemoveEntryList(&Protocol
->ListEntry
, &ProtocolListLock
);
735 ExFreePool(Protocol
);
737 *Status
= NDIS_STATUS_SUCCESS
;
747 OUT PNDIS_STATUS Status
,
748 OUT PNDIS_STATUS OpenErrorStatus
,
749 OUT PNDIS_HANDLE NdisBindingHandle
,
750 OUT PUINT SelectedMediumIndex
,
751 IN PNDIS_MEDIUM MediumArray
,
752 IN UINT MediumArraySize
,
753 IN NDIS_HANDLE NdisProtocolHandle
,
754 IN NDIS_HANDLE ProtocolBindingContext
,
755 IN PNDIS_STRING AdapterName
,
757 IN PSTRING AddressingInformation OPTIONAL
)
759 * FUNCTION: Opens an adapter for communication
761 * Status = Address of buffer for status information
762 * OpenErrorStatus = Address of buffer for secondary error code
763 * NdisBindingHandle = Address of buffer for adapter binding handle
764 * SelectedMediumIndex = Address of buffer for selected medium
765 * MediumArray = Pointer to an array of NDIS_MEDIUMs called can support
766 * MediumArraySize = Number of elements in MediumArray
767 * NdisProtocolHandle = Handle returned by NdisRegisterProtocol
768 * ProtocolBindingContext = Pointer to caller suplied context area
769 * AdapterName = Pointer to buffer with name of adapter
770 * OpenOptions = Bitmask with flags passed to next-lower driver
771 * AddressingInformation = Optional pointer to buffer with NIC specific information
776 PLOGICAL_ADAPTER Adapter
;
777 PADAPTER_BINDING AdapterBinding
;
778 PPROTOCOL_BINDING Protocol
= GET_PROTOCOL_BINDING(NdisProtocolHandle
);
780 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
782 if(!NdisProtocolHandle
)
784 NDIS_DbgPrint(MIN_TRACE
, ("NdisProtocolHandle is NULL\n"));
785 *OpenErrorStatus
= *Status
= NDIS_STATUS_FAILURE
;
789 Adapter
= MiniLocateDevice(AdapterName
);
792 NDIS_DbgPrint(MIN_TRACE
, ("Adapter not found.\n"));
793 *Status
= NDIS_STATUS_ADAPTER_NOT_FOUND
;
797 /* Find the media type in the list provided by the protocol driver */
799 for (i
= 0; i
< MediumArraySize
; i
++)
801 if (Adapter
->NdisMiniportBlock
.MediaType
== MediumArray
[i
])
803 *SelectedMediumIndex
= i
;
811 NDIS_DbgPrint(MIN_TRACE
, ("Medium is not supported.\n"));
812 *Status
= NDIS_STATUS_UNSUPPORTED_MEDIA
;
816 /* Now that we have confirmed that the adapter can be opened, create a binding */
818 AdapterBinding
= ExAllocatePool(NonPagedPool
, sizeof(ADAPTER_BINDING
));
821 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
822 *Status
= NDIS_STATUS_RESOURCES
;
826 RtlZeroMemory(AdapterBinding
, sizeof(ADAPTER_BINDING
));
828 AdapterBinding
->ProtocolBinding
= Protocol
;
829 AdapterBinding
->Adapter
= Adapter
;
830 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
= ProtocolBindingContext
;
832 /* Set fields required by some NDIS macros */
833 AdapterBinding
->NdisOpenBlock
.BindingHandle
= (NDIS_HANDLE
)AdapterBinding
;
835 /* Set handlers (some NDIS macros require these) */
837 AdapterBinding
->NdisOpenBlock
.RequestHandler
= ProRequest
;
838 AdapterBinding
->NdisOpenBlock
.ResetHandler
= ProReset
;
839 AdapterBinding
->NdisOpenBlock
.SendHandler
= ProSend
;
840 AdapterBinding
->NdisOpenBlock
.SendPacketsHandler
= ProSendPackets
;
841 AdapterBinding
->NdisOpenBlock
.TransferDataHandler
= ProTransferData
;
843 AdapterBinding
->NdisOpenBlock
.RequestCompleteHandler
=
844 Protocol
->Chars
.RequestCompleteHandler
;
846 /* Put on protocol's bound adapters list */
847 ExInterlockedInsertTailList(&Protocol
->AdapterListHead
, &AdapterBinding
->ProtocolListEntry
, &Protocol
->Lock
);
849 /* Put protocol on adapter's bound protocols list */
850 NDIS_DbgPrint(MAX_TRACE
, ("acquiring miniport block lock\n"));
851 ExInterlockedInsertTailList(&Adapter
->ProtocolListHead
, &AdapterBinding
->AdapterListEntry
, &Adapter
->NdisMiniportBlock
.Lock
);
853 *NdisBindingHandle
= (NDIS_HANDLE
)AdapterBinding
;
855 *Status
= NDIS_STATUS_SUCCESS
;
860 ndisBindMiniportsToProtocol(OUT PNDIS_STATUS Status
, IN PNDIS_PROTOCOL_CHARACTERISTICS ProtocolCharacteristics
)
863 * bind the protocol to all of its miniports
866 * get list of devices from Bind key
867 * call BindAdapterHandler for each
869 OBJECT_ATTRIBUTES ObjectAttributes
;
870 UNICODE_STRING RegistryPath
;
871 WCHAR
*RegistryPathStr
;
874 HANDLE DriverKeyHandle
= NULL
;
875 PKEY_VALUE_PARTIAL_INFORMATION KeyInformation
= NULL
;
877 RegistryPathStr
= ExAllocatePoolWithTag(PagedPool
, sizeof(SERVICES_KEY
) + ProtocolCharacteristics
->Name
.Length
+ sizeof(LINKAGE_KEY
), NDIS_TAG
+ __LINE__
);
880 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
881 *Status
= NDIS_STATUS_RESOURCES
;
885 wcscpy(RegistryPathStr
, SERVICES_KEY
);
886 wcsncat(RegistryPathStr
, ((WCHAR
*)ProtocolCharacteristics
->Name
.Buffer
), ProtocolCharacteristics
->Name
.Length
/ sizeof(WCHAR
));
887 RegistryPathStr
[wcslen(SERVICES_KEY
)+ProtocolCharacteristics
->Name
.Length
/sizeof(WCHAR
)] = 0;
888 wcscat(RegistryPathStr
, LINKAGE_KEY
);
890 RtlInitUnicodeString(&RegistryPath
, RegistryPathStr
);
891 NDIS_DbgPrint(MAX_TRACE
, ("Opening configuration key: %wZ\n", &RegistryPath
));
893 InitializeObjectAttributes(&ObjectAttributes
, &RegistryPath
, OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
894 NtStatus
= ZwOpenKey(&DriverKeyHandle
, KEY_READ
, &ObjectAttributes
);
896 ExFreePool(RegistryPathStr
);
898 if(!NT_SUCCESS(NtStatus
))
900 NDIS_DbgPrint(MIN_TRACE
, ("Unable to open protocol configuration\n"));
901 *Status
= NDIS_STATUS_FAILURE
;
905 NDIS_DbgPrint(MAX_TRACE
, ("Successfully opened the registry configuration\n"));
908 UNICODE_STRING ValueName
;
911 RtlInitUnicodeString(&ValueName
, L
"Bind");
913 NtStatus
= ZwQueryValueKey(DriverKeyHandle
, &ValueName
, KeyValuePartialInformation
, NULL
, 0, &ResultLength
);
914 if(NtStatus
!= STATUS_BUFFER_OVERFLOW
&& NtStatus
!= STATUS_BUFFER_TOO_SMALL
&& NtStatus
!= STATUS_SUCCESS
)
916 NDIS_DbgPrint(MIN_TRACE
, ("Unable to query the Bind value for size\n"));
917 ZwClose(DriverKeyHandle
);
918 *Status
= NDIS_STATUS_FAILURE
;
922 KeyInformation
= ExAllocatePoolWithTag(PagedPool
, sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + ResultLength
, NDIS_TAG
+ __LINE__
);
925 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
926 ZwClose(DriverKeyHandle
);
927 *Status
= NDIS_STATUS_FAILURE
;
931 NtStatus
= ZwQueryValueKey(DriverKeyHandle
, &ValueName
, KeyValuePartialInformation
, KeyInformation
,
932 sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + ResultLength
, &ResultLength
);
934 ZwClose(DriverKeyHandle
);
936 if(!NT_SUCCESS(NtStatus
))
938 NDIS_DbgPrint(MIN_TRACE
, ("Unable to query the Bind value\n"));
939 ExFreePool(KeyInformation
);
940 *Status
= NDIS_STATUS_FAILURE
;
945 for (DataPtr
= (WCHAR
*)KeyInformation
->Data
;
947 DataPtr
+= wcslen(DataPtr
) + 1)
949 /* BindContext is for tracking pending binding operations */
950 VOID
*BindContext
= 0;
951 NDIS_STRING DeviceName
;
952 NDIS_STRING RegistryPath
;
953 WCHAR
*RegistryPathStr
= NULL
;
954 ULONG PathLength
= 0;
956 RtlInitUnicodeString(&DeviceName
, DataPtr
); /* we know this is 0-term */
959 * RegistryPath should be:
960 * \Registry\Machine\System\CurrentControlSet\Services\Nic1\Parameters\Tcpip
962 * This is constructed as follows:
963 * SERVICES_KEY + extracted device name + Protocol name from characteristics
966 PathLength
= sizeof(SERVICES_KEY
) + /* \Registry\Machine\System\CurrentControlSet\Services\ */
967 wcslen( DataPtr
+ 8 ) * sizeof(WCHAR
) + /* Adapter1 (extracted from \Device\Adapter1) */
968 sizeof(PARAMETERS_KEY
) + /* \Parameters\ */
969 ProtocolCharacteristics
->Name
.Length
+ sizeof(WCHAR
); /* Tcpip */
971 RegistryPathStr
= ExAllocatePool(PagedPool
, PathLength
);
974 NDIS_DbgPrint(MIN_TRACE
, ("insufficient resources.\n"));
975 ExFreePool(KeyInformation
);
976 *Status
= NDIS_STATUS_RESOURCES
;
980 wcscpy(RegistryPathStr
, SERVICES_KEY
);
981 wcscat(RegistryPathStr
, DataPtr
+ 8 );
982 wcscat(RegistryPathStr
, PARAMETERS_KEY
);
983 wcsncat(RegistryPathStr
, ProtocolCharacteristics
->Name
.Buffer
, ProtocolCharacteristics
->Name
.Length
/ sizeof(WCHAR
) );
985 RegistryPathStr
[PathLength
/sizeof(WCHAR
) - 1] = 0;
987 RtlInitUnicodeString(&RegistryPath
, RegistryPathStr
);
989 NDIS_DbgPrint(MAX_TRACE
, ("Calling protocol's BindAdapter handler with DeviceName %wZ and RegistryPath %wZ\n",
990 &DeviceName
, &RegistryPath
));
993 BIND_HANDLER BindHandler
= ProtocolCharacteristics
->BindAdapterHandler
;
995 BindHandler(Status
, BindContext
, &DeviceName
, &RegistryPath
, 0);
997 NDIS_DbgPrint(MIN_TRACE
, ("No protocol bind handler specified\n"));
1001 *Status
= NDIS_STATUS_SUCCESS
;
1002 ExFreePool(KeyInformation
);
1010 NdisRegisterProtocol(
1011 OUT PNDIS_STATUS Status
,
1012 OUT PNDIS_HANDLE NdisProtocolHandle
,
1013 IN PNDIS_PROTOCOL_CHARACTERISTICS ProtocolCharacteristics
,
1014 IN UINT CharacteristicsLength
)
1016 * FUNCTION: Registers an NDIS driver's ProtocolXxx entry points
1018 * Status = Address of buffer for status information
1019 * NdisProtocolHandle = Address of buffer for handle used to identify the driver
1020 * ProtocolCharacteristics = Pointer to NDIS_PROTOCOL_CHARACTERISTICS structure
1021 * CharacteristicsLength = Size of structure which ProtocolCharacteristics targets
1023 * - you *must* set NdisProtocolHandle before doing anything that could wind up
1024 * getting BindAdapterHandler, as it will probably call OpenAdapter with this handle
1025 * - the above implies that the initialization of the protocol block must be complete
1028 * - break this function up - probably do a 'ndisRefreshProtocolBindings' function
1029 * - make this thing able to handle >1 protocol
1032 PPROTOCOL_BINDING Protocol
;
1036 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
1038 *NdisProtocolHandle
= NULL
;
1040 /* first validate the PROTOCOL_CHARACTERISTICS */
1041 switch (ProtocolCharacteristics
->MajorNdisVersion
)
1044 /* we don't really want to support ndis3 drivers - so we complain for now */
1045 NDIS_DbgPrint(MID_TRACE
, ("NDIS 3 protocol attempting to register\n"));
1046 MinSize
= sizeof(NDIS30_PROTOCOL_CHARACTERISTICS
);
1050 MinSize
= sizeof(NDIS40_PROTOCOL_CHARACTERISTICS
);
1054 MinSize
= sizeof(NDIS50_PROTOCOL_CHARACTERISTICS
);
1058 *Status
= NDIS_STATUS_BAD_VERSION
;
1059 NDIS_DbgPrint(MIN_TRACE
, ("Incorrect characteristics size\n"));
1063 if (CharacteristicsLength
< MinSize
)
1065 NDIS_DbgPrint(MIN_TRACE
, ("Bad protocol characteristics.\n"));
1066 *Status
= NDIS_STATUS_BAD_CHARACTERISTICS
;
1070 /* set up the protocol block */
1071 Protocol
= ExAllocatePool(NonPagedPool
, sizeof(PROTOCOL_BINDING
));
1074 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
1075 *Status
= NDIS_STATUS_RESOURCES
;
1079 RtlZeroMemory(Protocol
, sizeof(PROTOCOL_BINDING
));
1080 RtlCopyMemory(&Protocol
->Chars
, ProtocolCharacteristics
, MinSize
);
1082 NtStatus
= RtlUpcaseUnicodeString(&Protocol
->Chars
.Name
, &ProtocolCharacteristics
->Name
, TRUE
);
1083 if (!NT_SUCCESS(NtStatus
))
1085 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
1086 ExFreePool(Protocol
);
1087 *Status
= NDIS_STATUS_RESOURCES
;
1091 KeInitializeSpinLock(&Protocol
->Lock
);
1093 InitializeListHead(&Protocol
->AdapterListHead
);
1095 /* We must set this before the call to ndisBindMiniportsToProtocol because the protocol's
1096 * BindAdapter handler might need it */
1098 *NdisProtocolHandle
= Protocol
;
1100 ndisBindMiniportsToProtocol(Status
, &Protocol
->Chars
);
1102 if (*Status
== NDIS_STATUS_SUCCESS
) {
1103 ExInterlockedInsertTailList(&ProtocolListHead
, &Protocol
->ListEntry
, &ProtocolListLock
);
1105 NDIS_DbgPrint(MIN_TRACE
, ("Binding failed (%x)\n", *Status
));
1106 ExFreePool(Protocol
);
1107 *NdisProtocolHandle
= NULL
;
1118 OUT PNDIS_STATUS Status
,
1119 IN NDIS_HANDLE NdisBindingHandle
,
1120 IN PNDIS_REQUEST NdisRequest
)
1122 * FUNCTION: Forwards a request to an NDIS driver
1124 * Status = Address of buffer for status information
1125 * NdisBindingHandle = Adapter binding handle
1126 * NdisRequest = Pointer to request to perform
1129 *Status
= ProRequest(NdisBindingHandle
, NdisRequest
);
1139 OUT PNDIS_STATUS Status
,
1140 IN NDIS_HANDLE NdisBindingHandle
)
1142 *Status
= ProReset(NdisBindingHandle
);
1153 OUT PNDIS_STATUS Status
,
1154 IN NDIS_HANDLE NdisBindingHandle
,
1155 IN PNDIS_PACKET Packet
)
1157 * FUNCTION: Forwards a request to send a packet
1159 * Status = Address of buffer for status information
1160 * NdisBindingHandle = Adapter binding handle
1161 * Packet = Pointer to NDIS packet descriptor
1164 *Status
= ProSend(NdisBindingHandle
, Packet
);
1171 #undef NdisSendPackets
1175 IN NDIS_HANDLE NdisBindingHandle
,
1176 IN PPNDIS_PACKET PacketArray
,
1177 IN UINT NumberOfPackets
)
1179 ProSendPackets(NdisBindingHandle
, PacketArray
, NumberOfPackets
);
1186 #undef NdisTransferData
1190 OUT PNDIS_STATUS Status
,
1191 IN NDIS_HANDLE NdisBindingHandle
,
1192 IN NDIS_HANDLE MacReceiveContext
,
1194 IN UINT BytesToTransfer
,
1195 IN OUT PNDIS_PACKET Packet
,
1196 OUT PUINT BytesTransferred
)
1198 * FUNCTION: Forwards a request to copy received data into a protocol-supplied packet
1200 * Status = Address of buffer for status information
1201 * NdisBindingHandle = Adapter binding handle
1202 * MacReceiveContext = MAC receive context
1203 * ByteOffset = Offset in packet to place data
1204 * BytesToTransfer = Number of bytes to copy into packet
1205 * Packet = Pointer to NDIS packet descriptor
1206 * BytesTransferred = Address of buffer to place number of bytes copied
1209 *Status
= ProTransferData(NdisBindingHandle
,
1222 NdisReEnumerateProtocolBindings(IN NDIS_HANDLE NdisProtocolHandle
)
1224 PPROTOCOL_BINDING Protocol
= NdisProtocolHandle
;
1225 NDIS_STATUS NdisStatus
;
1227 ndisBindMiniportsToProtocol(&NdisStatus
, &Protocol
->Chars
);
1236 NdisGetDriverHandle(
1237 IN PNDIS_HANDLE NdisBindingHandle
,
1238 OUT PNDIS_HANDLE NdisDriverHandle
)
1246 PADAPTER_BINDING Binding
= (PADAPTER_BINDING
)NdisBindingHandle
;
1250 NDIS_DbgPrint(MIN_TRACE
, ("Bad binding handle\n"));
1251 *NdisDriverHandle
= NULL
;
1255 *NdisDriverHandle
= Binding
->Adapter
->NdisMiniportBlock
.DriverHandle
;