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
;
29 NdisCompleteBindAdapter(
30 IN NDIS_HANDLE BindAdapterContext
,
31 IN NDIS_STATUS Status
,
32 IN NDIS_STATUS OpenStatus
)
34 * FUNCTION: Indicates a packet to bound protocols
36 * Adapter = Pointer to logical adapter
37 * Packet = Pointer to packet to indicate
41 * - FIXME: partially-implemented
44 PROTOCOL_BINDING
*Protocol
= (PROTOCOL_BINDING
*)BindAdapterContext
;
46 if (!NT_SUCCESS(Status
)) return;
48 /* Put protocol binding struct on global list */
49 ExInterlockedInsertTailList(&ProtocolListHead
, &Protocol
->ListEntry
, &ProtocolListLock
);
55 PLOGICAL_ADAPTER Adapter
,
58 * FUNCTION: Indicates a packet to bound protocols
60 * Adapter = Pointer to logical adapter
61 * Packet = Pointer to packet to indicate
63 * STATUS_SUCCESS in all cases
65 * - XXX ATM, this only handles loopback packets - is that its designed function?
72 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
75 MiniDisplayPacket(Packet
);
78 NdisQueryPacket(Packet
, NULL
, NULL
, NULL
, &PacketLength
);
80 NDIS_DbgPrint(MAX_TRACE
, ("acquiring miniport block lock\n"));
81 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
83 Adapter
->NdisMiniportBlock
.IndicatedPacket
[KeGetCurrentProcessorNumber()] = Packet
;
84 BufferedLength
= CopyPacketToBuffer(Adapter
->LookaheadBuffer
, Packet
, 0, Adapter
->NdisMiniportBlock
.CurrentLookahead
);
86 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
88 if (BufferedLength
> Adapter
->MediumHeaderSize
)
90 /* XXX Change this to call SendPackets so we don't have to duplicate this wacky logic */
91 MiniIndicateData(Adapter
, NULL
, Adapter
->LookaheadBuffer
, Adapter
->MediumHeaderSize
,
92 &Adapter
->LookaheadBuffer
[Adapter
->MediumHeaderSize
], BufferedLength
- Adapter
->MediumHeaderSize
,
93 PacketLength
- Adapter
->MediumHeaderSize
);
97 MiniIndicateData(Adapter
, NULL
, Adapter
->LookaheadBuffer
, Adapter
->MediumHeaderSize
, NULL
, 0, 0);
100 NDIS_DbgPrint(MAX_TRACE
, ("acquiring miniport block lock\n"));
101 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
103 Adapter
->NdisMiniportBlock
.IndicatedPacket
[KeGetCurrentProcessorNumber()] = NULL
;
105 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
107 return STATUS_SUCCESS
;
113 IN NDIS_HANDLE MacBindingHandle
,
114 IN PNDIS_REQUEST NdisRequest
)
116 * FUNCTION: Forwards a request to an NDIS miniport
118 * MacBindingHandle = Adapter binding handle
119 * NdisRequest = Pointer to request to perform
121 * Status of operation
125 PADAPTER_BINDING AdapterBinding
;
126 PLOGICAL_ADAPTER Adapter
;
127 PNDIS_REQUEST_MAC_BLOCK MacBlock
= (PNDIS_REQUEST_MAC_BLOCK
)NdisRequest
->MacReserved
;
129 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
131 ASSERT(MacBindingHandle
);
132 AdapterBinding
= GET_ADAPTER_BINDING(MacBindingHandle
);
134 ASSERT(AdapterBinding
->Adapter
);
135 Adapter
= AdapterBinding
->Adapter
;
137 MacBlock
->Binding
= &AdapterBinding
->NdisOpenBlock
;
140 * If the miniport is already busy, queue a workitem
142 NDIS_DbgPrint(MAX_TRACE
, ("acquiring miniport block lock\n"));
143 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
145 if (Adapter
->MiniportBusy
) {
146 MiniQueueWorkItem(Adapter
, NdisWorkItemRequest
, (PVOID
)NdisRequest
);
147 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
148 return NDIS_STATUS_PENDING
;
151 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
153 return MiniDoRequest(Adapter
, NdisRequest
);
159 IN NDIS_HANDLE MacBindingHandle
)
163 return NDIS_STATUS_FAILURE
;
169 IN NDIS_HANDLE MacBindingHandle
,
170 IN PNDIS_PACKET Packet
)
172 * FUNCTION: Forwards a request to send a packet to an NDIS miniport
174 * MacBindingHandle = Adapter binding handle
175 * Packet = Pointer to NDIS packet descriptor
177 * NDIS_STATUS_SUCCESS if the packet was successfully sent
178 * NDIS_STATUS_PENDING if the miniport was busy or a serialized miniport returned NDIS_STATUS_RESOURCES
184 KIRQL SpinOldIrql
, RaiseOldIrql
;
185 PADAPTER_BINDING AdapterBinding
;
186 PLOGICAL_ADAPTER Adapter
;
187 NDIS_STATUS NdisStatus
;
189 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
191 ASSERT(MacBindingHandle
);
192 AdapterBinding
= GET_ADAPTER_BINDING(MacBindingHandle
);
194 ASSERT(AdapterBinding
);
195 Adapter
= AdapterBinding
->Adapter
;
199 /* if the following is not true, KeRaiseIrql() below will break */
200 ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL
);
202 /* XXX what is this crazy black magic? */
203 Packet
->Reserved
[0] = (ULONG_PTR
)MacBindingHandle
;
206 * Test the packet to see if it is a MAC loopback.
208 * We may have to loop this packet if miniport cannot.
209 * If dest MAC address of packet == MAC address of adapter,
210 * this is a loopback frame.
213 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &SpinOldIrql
);
215 if ((Adapter
->NdisMiniportBlock
.MacOptions
& NDIS_MAC_OPTION_NO_LOOPBACK
) &&
216 MiniAdapterHasAddress(Adapter
, Packet
))
218 if(Adapter
->MiniportBusy
) {
219 MiniQueueWorkItem(Adapter
, NdisWorkItemSendLoopback
, Packet
);
220 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, SpinOldIrql
);
221 return NDIS_STATUS_PENDING
;
224 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, SpinOldIrql
);
226 return ProIndicatePacket(Adapter
, Packet
);
228 if(Adapter
->MiniportBusy
) {
229 MiniQueueWorkItem(Adapter
, NdisWorkItemSend
, Packet
);
230 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, SpinOldIrql
);
231 return NDIS_STATUS_PENDING
;
234 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, SpinOldIrql
);
236 if(Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendPacketsHandler
)
238 if(Adapter
->NdisMiniportBlock
.Flags
& NDIS_ATTRIBUTE_DESERIALIZE
)
240 NDIS_DbgPrint(MAX_TRACE
, ("Calling miniport's SendPackets handler\n"));
241 (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendPacketsHandler
)(
242 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, &Packet
, 1);
243 NdisStatus
= NDIS_GET_PACKET_STATUS(Packet
);
245 /* SendPackets is called at DISPATCH_LEVEL for all serialized miniports */
246 KeRaiseIrql(DISPATCH_LEVEL
, &RaiseOldIrql
);
248 NDIS_DbgPrint(MAX_TRACE
, ("Calling miniport's SendPackets handler\n"));
249 (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendPacketsHandler
)(
250 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, &Packet
, 1);
252 KeLowerIrql(RaiseOldIrql
);
254 NdisStatus
= NDIS_GET_PACKET_STATUS(Packet
);
255 if( NdisStatus
== NDIS_STATUS_RESOURCES
) {
256 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &SpinOldIrql
);
257 MiniQueueWorkItem(Adapter
, NdisWorkItemSend
, Packet
);
258 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, SpinOldIrql
);
259 NdisStatus
= NDIS_STATUS_PENDING
;
265 if(Adapter
->NdisMiniportBlock
.Flags
& NDIS_ATTRIBUTE_DESERIALIZE
)
267 NDIS_DbgPrint(MAX_TRACE
, ("Calling miniport's Send handler\n"));
268 NdisStatus
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendHandler
)(
269 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, Packet
, 0);
270 NDIS_DbgPrint(MAX_TRACE
, ("back from miniport's send handler\n"));
272 /* Send is called at DISPATCH_LEVEL for all serialized miniports */
273 KeRaiseIrql(DISPATCH_LEVEL
, &RaiseOldIrql
);
274 NDIS_DbgPrint(MAX_TRACE
, ("Calling miniport's Send handler\n"));
275 NdisStatus
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendHandler
)(
276 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, Packet
, 0);
277 NDIS_DbgPrint(MAX_TRACE
, ("back from miniport's send handler\n"));
278 KeLowerIrql(RaiseOldIrql
);
279 if( NdisStatus
== NDIS_STATUS_RESOURCES
) {
280 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &SpinOldIrql
);
281 MiniQueueWorkItem(Adapter
, NdisWorkItemSend
, Packet
);
282 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, SpinOldIrql
);
283 NdisStatus
= NDIS_STATUS_PENDING
;
295 IN NDIS_HANDLE NdisBindingHandle
,
296 IN PPNDIS_PACKET PacketArray
,
297 IN UINT NumberOfPackets
)
299 PADAPTER_BINDING AdapterBinding
= NdisBindingHandle
;
300 PLOGICAL_ADAPTER Adapter
= AdapterBinding
->Adapter
;
302 NDIS_STATUS NdisStatus
;
305 if(Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendPacketsHandler
)
307 if(Adapter
->NdisMiniportBlock
.Flags
& NDIS_ATTRIBUTE_DESERIALIZE
)
309 (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendPacketsHandler
)(
310 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, PacketArray
, NumberOfPackets
);
311 for (i
= 0; i
< NumberOfPackets
; i
++)
313 NdisStatus
= NDIS_GET_PACKET_STATUS(PacketArray
[i
]);
314 if (NdisStatus
!= NDIS_STATUS_PENDING
)
315 MiniSendComplete(Adapter
, PacketArray
[i
], NdisStatus
);
320 /* SendPackets is called at DISPATCH_LEVEL for all serialized miniports */
321 KeRaiseIrql(DISPATCH_LEVEL
, &RaiseOldIrql
);
322 (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendPacketsHandler
)(
323 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, PacketArray
, NumberOfPackets
);
324 KeLowerIrql(RaiseOldIrql
);
325 for (i
= 0; i
< NumberOfPackets
; i
++)
327 NdisStatus
= NDIS_GET_PACKET_STATUS(PacketArray
[i
]);
328 if (NdisStatus
!= NDIS_STATUS_PENDING
)
329 MiniSendComplete(Adapter
, PacketArray
[i
], NdisStatus
);
335 if(Adapter
->NdisMiniportBlock
.Flags
& NDIS_ATTRIBUTE_DESERIALIZE
)
337 for (i
= 0; i
< NumberOfPackets
; i
++)
339 NdisStatus
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendHandler
)(
340 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, PacketArray
[i
], 0);
341 if (NdisStatus
!= NDIS_STATUS_PENDING
)
342 MiniSendComplete(Adapter
, PacketArray
[i
], NdisStatus
);
347 /* Send is called at DISPATCH_LEVEL for all serialized miniports */
348 KeRaiseIrql(DISPATCH_LEVEL
, &RaiseOldIrql
);
349 for (i
= 0; i
< NumberOfPackets
; i
++)
351 NdisStatus
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendHandler
)(
352 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, PacketArray
[i
], 0);
353 if (NdisStatus
!= NDIS_STATUS_PENDING
)
354 MiniSendComplete(Adapter
, PacketArray
[i
], NdisStatus
);
356 KeLowerIrql(RaiseOldIrql
);
364 IN NDIS_HANDLE MacBindingHandle
,
365 IN NDIS_HANDLE MacReceiveContext
,
367 IN UINT BytesToTransfer
,
368 IN OUT PNDIS_PACKET Packet
,
369 OUT PUINT BytesTransferred
)
371 * FUNCTION: Forwards a request to copy received data into a protocol-supplied packet
373 * MacBindingHandle = Adapter binding handle
374 * MacReceiveContext = MAC receive context
375 * ByteOffset = Offset in packet to place data
376 * BytesToTransfer = Number of bytes to copy into packet
377 * Packet = Pointer to NDIS packet descriptor
378 * BytesTransferred = Address of buffer to place number of bytes copied
381 PADAPTER_BINDING AdapterBinding
= GET_ADAPTER_BINDING(MacBindingHandle
);
382 PLOGICAL_ADAPTER Adapter
= AdapterBinding
->Adapter
;
386 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
388 /* FIXME: Interrupts must be disabled for adapter */
389 /* XXX sd - why is that true? */
391 if (Packet
== Adapter
->NdisMiniportBlock
.IndicatedPacket
[KeGetCurrentProcessorNumber()]) {
392 NDIS_DbgPrint(MAX_TRACE
, ("LoopPacket\n"));
393 /* NDIS is responsible for looping this packet */
394 NdisCopyFromPacketToPacket(Packet
,
397 Adapter
->NdisMiniportBlock
.IndicatedPacket
[KeGetCurrentProcessorNumber()],
400 return NDIS_STATUS_SUCCESS
;
403 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
405 Status
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.TransferDataHandler
)(
408 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
,
413 KeLowerIrql(OldIrql
);
426 OUT PNDIS_STATUS Status
,
427 IN NDIS_HANDLE NdisBindingHandle
)
429 * FUNCTION: Closes an adapter opened with NdisOpenAdapter
431 * Status = Address of buffer for status information
432 * NdisBindingHandle = Handle returned by NdisOpenAdapter
436 PADAPTER_BINDING AdapterBinding
= GET_ADAPTER_BINDING(NdisBindingHandle
);
438 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
440 /* Remove from protocol's bound adapters list */
441 KeAcquireSpinLock(&AdapterBinding
->ProtocolBinding
->Lock
, &OldIrql
);
442 RemoveEntryList(&AdapterBinding
->ProtocolListEntry
);
443 KeReleaseSpinLock(&AdapterBinding
->ProtocolBinding
->Lock
, OldIrql
);
445 /* Remove protocol from adapter's bound protocols list */
446 NDIS_DbgPrint(MAX_TRACE
, ("acquiring miniport block lock\n"));
447 KeAcquireSpinLock(&AdapterBinding
->Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
448 RemoveEntryList(&AdapterBinding
->AdapterListEntry
);
449 KeReleaseSpinLock(&AdapterBinding
->Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
451 ExFreePool(AdapterBinding
);
453 *Status
= NDIS_STATUS_SUCCESS
;
462 NdisDeregisterProtocol(
463 OUT PNDIS_STATUS Status
,
464 IN NDIS_HANDLE NdisProtocolHandle
)
466 * FUNCTION: Releases the resources allocated by NdisRegisterProtocol
468 * Status = Address of buffer for status information
469 * NdisProtocolHandle = Handle returned by NdisRegisterProtocol
473 PPROTOCOL_BINDING Protocol
= GET_PROTOCOL_BINDING(NdisProtocolHandle
);
475 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
477 /* FIXME: Make sure no adapter bindings exist */
479 /* Remove protocol from global list */
480 KeAcquireSpinLock(&ProtocolListLock
, &OldIrql
);
481 RemoveEntryList(&Protocol
->ListEntry
);
482 KeReleaseSpinLock(&ProtocolListLock
, OldIrql
);
484 ExFreePool(Protocol
);
486 *Status
= NDIS_STATUS_SUCCESS
;
496 OUT PNDIS_STATUS Status
,
497 OUT PNDIS_STATUS OpenErrorStatus
,
498 OUT PNDIS_HANDLE NdisBindingHandle
,
499 OUT PUINT SelectedMediumIndex
,
500 IN PNDIS_MEDIUM MediumArray
,
501 IN UINT MediumArraySize
,
502 IN NDIS_HANDLE NdisProtocolHandle
,
503 IN NDIS_HANDLE ProtocolBindingContext
,
504 IN PNDIS_STRING AdapterName
,
506 IN PSTRING AddressingInformation OPTIONAL
)
508 * FUNCTION: Opens an adapter for communication
510 * Status = Address of buffer for status information
511 * OpenErrorStatus = Address of buffer for secondary error code
512 * NdisBindingHandle = Address of buffer for adapter binding handle
513 * SelectedMediumIndex = Address of buffer for selected medium
514 * MediumArray = Pointer to an array of NDIS_MEDIUMs called can support
515 * MediumArraySize = Number of elements in MediumArray
516 * NdisProtocolHandle = Handle returned by NdisRegisterProtocol
517 * ProtocolBindingContext = Pointer to caller suplied context area
518 * AdapterName = Pointer to buffer with name of adapter
519 * OpenOptions = Bitmask with flags passed to next-lower driver
520 * AddressingInformation = Optional pointer to buffer with NIC specific information
525 PLOGICAL_ADAPTER Adapter
;
526 PADAPTER_BINDING AdapterBinding
;
527 PPROTOCOL_BINDING Protocol
= GET_PROTOCOL_BINDING(NdisProtocolHandle
);
529 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
531 if(!NdisProtocolHandle
)
533 NDIS_DbgPrint(MAX_TRACE
, ("NdisProtocolHandle is NULL\n"));
534 *OpenErrorStatus
= *Status
= NDIS_STATUS_FAILURE
;
538 Adapter
= MiniLocateDevice(AdapterName
);
541 NDIS_DbgPrint(MIN_TRACE
, ("Adapter not found.\n"));
542 *Status
= NDIS_STATUS_ADAPTER_NOT_FOUND
;
546 /* Find the media type in the list provided by the protocol driver */
548 for (i
= 0; i
< MediumArraySize
; i
++)
550 if (Adapter
->NdisMiniportBlock
.MediaType
== MediumArray
[i
])
552 *SelectedMediumIndex
= i
;
560 NDIS_DbgPrint(MIN_TRACE
, ("Medium is not supported.\n"));
561 *Status
= NDIS_STATUS_UNSUPPORTED_MEDIA
;
565 /* Now that we have confirmed that the adapter can be opened, create a binding */
567 AdapterBinding
= ExAllocatePool(NonPagedPool
, sizeof(ADAPTER_BINDING
));
570 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
571 *Status
= NDIS_STATUS_RESOURCES
;
575 RtlZeroMemory(AdapterBinding
, sizeof(ADAPTER_BINDING
));
577 AdapterBinding
->ProtocolBinding
= Protocol
;
578 AdapterBinding
->Adapter
= Adapter
;
579 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
= ProtocolBindingContext
;
581 /* Set fields required by some NDIS macros */
582 AdapterBinding
->NdisOpenBlock
.BindingHandle
= (NDIS_HANDLE
)AdapterBinding
;
584 /* Set handlers (some NDIS macros require these) */
586 AdapterBinding
->NdisOpenBlock
.RequestHandler
= ProRequest
;
587 AdapterBinding
->NdisOpenBlock
.ResetHandler
= ProReset
;
588 AdapterBinding
->NdisOpenBlock
.SendHandler
= ProSend
;
589 AdapterBinding
->NdisOpenBlock
.SendPacketsHandler
= ProSendPackets
;
590 AdapterBinding
->NdisOpenBlock
.TransferDataHandler
= ProTransferData
;
592 AdapterBinding
->NdisOpenBlock
.RequestCompleteHandler
=
593 Protocol
->Chars
.RequestCompleteHandler
;
596 /* XXX this looks fishy */
597 /* OK, this really *is* fishy - it bugchecks */
598 /* Put on protocol's bound adapters list */
599 ExInterlockedInsertTailList(&Protocol
->AdapterListHead
, &AdapterBinding
->ProtocolListEntry
, &Protocol
->Lock
);
602 /* XXX so does this */
603 /* Put protocol on adapter's bound protocols list */
604 NDIS_DbgPrint(MAX_TRACE
, ("acquiring miniport block lock\n"));
605 ExInterlockedInsertTailList(&Adapter
->ProtocolListHead
, &AdapterBinding
->AdapterListEntry
, &Adapter
->NdisMiniportBlock
.Lock
);
607 *NdisBindingHandle
= (NDIS_HANDLE
)AdapterBinding
;
609 *Status
= NDIS_STATUS_SUCCESS
;
618 NdisRegisterProtocol(
619 OUT PNDIS_STATUS Status
,
620 OUT PNDIS_HANDLE NdisProtocolHandle
,
621 IN PNDIS_PROTOCOL_CHARACTERISTICS ProtocolCharacteristics
,
622 IN UINT CharacteristicsLength
)
624 * FUNCTION: Registers an NDIS driver's ProtocolXxx entry points
626 * Status = Address of buffer for status information
627 * NdisProtocolHandle = Address of buffer for handle used to identify the driver
628 * ProtocolCharacteristics = Pointer to NDIS_PROTOCOL_CHARACTERISTICS structure
629 * CharacteristicsLength = Size of structure which ProtocolCharacteristics targets
631 * - you *must* set NdisProtocolHandle before doing anything that could wind up
632 * getting BindAdapterHandler, as it will probably call OpenAdapter with this handle
633 * - the above implies that the initialization of the protocol block must be complete
636 * - break this function up - probably do a 'ndisRefreshProtocolBindings' function
637 * - make this thing able to handle >1 protocol
640 PPROTOCOL_BINDING Protocol
;
643 HANDLE DriverKeyHandle
= NULL
;
644 PKEY_VALUE_PARTIAL_INFORMATION KeyInformation
= NULL
;
647 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
649 *NdisProtocolHandle
= NULL
;
651 /* first validate the PROTOCOL_CHARACTERISTICS */
652 switch (ProtocolCharacteristics
->MajorNdisVersion
)
655 /* we don't really want to support ndis3 drivers - so we complain for now */
656 NDIS_DbgPrint(MID_TRACE
, ("NDIS 3 protocol attempting to register\n"));
657 MinSize
= sizeof(NDIS30_PROTOCOL_CHARACTERISTICS
);
661 MinSize
= sizeof(NDIS40_PROTOCOL_CHARACTERISTICS
);
665 MinSize
= sizeof(NDIS50_PROTOCOL_CHARACTERISTICS
);
669 *Status
= NDIS_STATUS_BAD_VERSION
;
670 NDIS_DbgPrint(MIN_TRACE
, ("Incorrect characteristics size\n"));
674 if (CharacteristicsLength
< MinSize
)
676 NDIS_DbgPrint(MIN_TRACE
, ("Bad protocol characteristics.\n"));
677 *Status
= NDIS_STATUS_BAD_CHARACTERISTICS
;
681 /* set up the protocol block */
682 Protocol
= ExAllocatePool(NonPagedPool
, sizeof(PROTOCOL_BINDING
));
685 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
686 *Status
= NDIS_STATUS_RESOURCES
;
690 RtlZeroMemory(Protocol
, sizeof(PROTOCOL_BINDING
));
691 RtlCopyMemory(&Protocol
->Chars
, ProtocolCharacteristics
, MinSize
);
693 NtStatus
= RtlUpcaseUnicodeString(&Protocol
->Chars
.Name
, &ProtocolCharacteristics
->Name
, TRUE
);
694 if (!NT_SUCCESS(NtStatus
))
696 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
697 ExFreePool(Protocol
);
698 *Status
= NDIS_STATUS_RESOURCES
;
702 KeInitializeSpinLock(&Protocol
->Lock
);
704 InitializeListHead(&Protocol
->AdapterListHead
);
707 * bind the protocol to all of its miniports
710 * get list of devices from Bind key
711 * call BindAdapterHandler for each
714 OBJECT_ATTRIBUTES ObjectAttributes
;
715 UNICODE_STRING RegistryPath
;
716 WCHAR
*RegistryPathStr
;
718 RegistryPathStr
= ExAllocatePoolWithTag(PagedPool
, sizeof(SERVICES_KEY
) + ProtocolCharacteristics
->Name
.Length
+ sizeof(LINKAGE_KEY
), NDIS_TAG
+ __LINE__
);
721 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
722 ExFreePool(Protocol
);
723 *Status
= NDIS_STATUS_RESOURCES
;
727 wcscpy(RegistryPathStr
, SERVICES_KEY
);
728 wcsncat(RegistryPathStr
, ((WCHAR
*)ProtocolCharacteristics
->Name
.Buffer
), ProtocolCharacteristics
->Name
.Length
/ sizeof(WCHAR
));
729 RegistryPathStr
[wcslen(SERVICES_KEY
)+ProtocolCharacteristics
->Name
.Length
/sizeof(WCHAR
)] = 0;
730 wcscat(RegistryPathStr
, LINKAGE_KEY
);
732 RtlInitUnicodeString(&RegistryPath
, RegistryPathStr
);
733 NDIS_DbgPrint(MAX_TRACE
, ("Opening configuration key: %wZ\n", &RegistryPath
));
735 InitializeObjectAttributes(&ObjectAttributes
, &RegistryPath
, OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
736 NtStatus
= ZwOpenKey(&DriverKeyHandle
, KEY_READ
, &ObjectAttributes
);
738 ExFreePool(RegistryPathStr
);
740 if(!NT_SUCCESS(NtStatus
))
742 NDIS_DbgPrint(MIN_TRACE
, ("Unable to open protocol configuration\n"));
743 ExFreePool(Protocol
);
744 *Status
= NDIS_STATUS_FAILURE
;
749 NDIS_DbgPrint(MAX_TRACE
, ("Successfully opened the registry configuration\n"));
752 UNICODE_STRING ValueName
;
755 RtlInitUnicodeString(&ValueName
, L
"Bind");
757 NtStatus
= ZwQueryValueKey(DriverKeyHandle
, &ValueName
, KeyValuePartialInformation
, NULL
, 0, &ResultLength
);
758 if(NtStatus
!= STATUS_BUFFER_OVERFLOW
&& NtStatus
!= STATUS_BUFFER_TOO_SMALL
&& NtStatus
!= STATUS_SUCCESS
)
760 NDIS_DbgPrint(MIN_TRACE
, ("Unable to query the Bind value for size\n"));
761 ZwClose(DriverKeyHandle
);
762 ExFreePool(Protocol
);
763 *Status
= NDIS_STATUS_FAILURE
;
767 KeyInformation
= ExAllocatePoolWithTag(PagedPool
, sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + ResultLength
, NDIS_TAG
+ __LINE__
);
770 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
771 ZwClose(DriverKeyHandle
);
772 ExFreePool(Protocol
);
773 *Status
= NDIS_STATUS_FAILURE
;
777 NtStatus
= ZwQueryValueKey(DriverKeyHandle
, &ValueName
, KeyValuePartialInformation
, KeyInformation
,
778 sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + ResultLength
, &ResultLength
);
780 ZwClose(DriverKeyHandle
);
782 if(!NT_SUCCESS(NtStatus
))
784 NDIS_DbgPrint(MIN_TRACE
, ("Unable to query the Bind value\n"));
785 ExFreePool(KeyInformation
);
786 ExFreePool(Protocol
);
787 *Status
= NDIS_STATUS_FAILURE
;
792 for (DataPtr
= (WCHAR
*)KeyInformation
->Data
;
794 DataPtr
+= wcslen(DataPtr
) + 1)
796 /* BindContext is for tracking pending binding operations */
797 VOID
*BindContext
= 0;
798 NDIS_STRING DeviceName
;
799 NDIS_STRING RegistryPath
;
800 WCHAR
*RegistryPathStr
= NULL
;
801 ULONG PathLength
= 0;
803 RtlInitUnicodeString(&DeviceName
, DataPtr
); /* we know this is 0-term */
806 * RegistryPath should be:
807 * \Registry\Machine\System\CurrentControlSet\Services\Nic1\Parameters\Tcpip
809 * This is constructed as follows:
810 * SERVICES_KEY + extracted device name + Protocol name from characteristics
813 PathLength
= sizeof(SERVICES_KEY
) + /* \Registry\Machine\System\CurrentControlSet\Services\ */
814 wcslen( DataPtr
+ 8 ) * sizeof(WCHAR
) + /* Adapter1 (extracted from \Device\Adapter1) */
815 sizeof(PARAMETERS_KEY
) + /* \Parameters\ */
816 ProtocolCharacteristics
->Name
.Length
+ sizeof(WCHAR
); /* Tcpip */
818 RegistryPathStr
= ExAllocatePool(PagedPool
, PathLength
);
821 NDIS_DbgPrint(MIN_TRACE
, ("insufficient resources.\n"));
822 ExFreePool(KeyInformation
);
823 ExFreePool(Protocol
);
824 *Status
= NDIS_STATUS_RESOURCES
;
828 wcscpy(RegistryPathStr
, SERVICES_KEY
);
829 wcscat(RegistryPathStr
, DataPtr
+ 8 );
830 wcscat(RegistryPathStr
, PARAMETERS_KEY
);
831 wcsncat(RegistryPathStr
, ProtocolCharacteristics
->Name
.Buffer
, ProtocolCharacteristics
->Name
.Length
/ sizeof(WCHAR
) );
833 RegistryPathStr
[PathLength
/sizeof(WCHAR
) - 1] = 0;
835 RtlInitUnicodeString(&RegistryPath
, RegistryPathStr
);
837 NDIS_DbgPrint(MAX_TRACE
, ("Calling protocol's BindAdapter handler with DeviceName %wZ and RegistryPath %wZ\n",
838 &DeviceName
, &RegistryPath
));
840 /* XXX SD must do something with bind context */
841 *NdisProtocolHandle
= Protocol
;
844 BIND_HANDLER BindHandler
= ProtocolCharacteristics
->BindAdapterHandler
;
846 BindHandler(Status
, BindContext
, &DeviceName
, &RegistryPath
, 0);
848 NDIS_DbgPrint(MID_TRACE
, ("No protocol bind handler specified\n"));
852 (*(Protocol->Chars.BindAdapterHandler))(Status, BindContext, &DeviceName, &RegistryPath, 0);
855 if(*Status
== NDIS_STATUS_SUCCESS
)
857 /* Put protocol binding struct on global list */
858 ExInterlockedInsertTailList(&ProtocolListHead
, &Protocol
->ListEntry
, &ProtocolListLock
);
860 else if(*Status
!= NDIS_STATUS_PENDING
)
862 NDIS_DbgPrint(MIN_TRACE
, ("ProtocolBindAdapter failed with status 0x%x\n", *Status
));
863 ExFreePool(Protocol
);
864 ExFreePool(KeyInformation
);
865 *NdisProtocolHandle
= NULL
;
870 ExFreePool(KeyInformation
);
871 *Status
= NDIS_STATUS_SUCCESS
;
881 OUT PNDIS_STATUS Status
,
882 IN NDIS_HANDLE NdisBindingHandle
,
883 IN PNDIS_REQUEST NdisRequest
)
885 * FUNCTION: Forwards a request to an NDIS driver
887 * Status = Address of buffer for status information
888 * NdisBindingHandle = Adapter binding handle
889 * NdisRequest = Pointer to request to perform
892 *Status
= ProRequest(NdisBindingHandle
, NdisRequest
);
902 OUT PNDIS_STATUS Status
,
903 IN NDIS_HANDLE NdisBindingHandle
)
905 *Status
= ProReset(NdisBindingHandle
);
916 OUT PNDIS_STATUS Status
,
917 IN NDIS_HANDLE NdisBindingHandle
,
918 IN PNDIS_PACKET Packet
)
920 * FUNCTION: Forwards a request to send a packet
922 * Status = Address of buffer for status information
923 * NdisBindingHandle = Adapter binding handle
924 * Packet = Pointer to NDIS packet descriptor
927 *Status
= ProSend(NdisBindingHandle
, Packet
);
934 #undef NdisSendPackets
938 IN NDIS_HANDLE NdisBindingHandle
,
939 IN PPNDIS_PACKET PacketArray
,
940 IN UINT NumberOfPackets
)
942 ProSendPackets(NdisBindingHandle
, PacketArray
, NumberOfPackets
);
949 #undef NdisTransferData
953 OUT PNDIS_STATUS Status
,
954 IN NDIS_HANDLE NdisBindingHandle
,
955 IN NDIS_HANDLE MacReceiveContext
,
957 IN UINT BytesToTransfer
,
958 IN OUT PNDIS_PACKET Packet
,
959 OUT PUINT BytesTransferred
)
961 * FUNCTION: Forwards a request to copy received data into a protocol-supplied packet
963 * Status = Address of buffer for status information
964 * NdisBindingHandle = Adapter binding handle
965 * MacReceiveContext = MAC receive context
966 * ByteOffset = Offset in packet to place data
967 * BytesToTransfer = Number of bytes to copy into packet
968 * Packet = Pointer to NDIS packet descriptor
969 * BytesTransferred = Address of buffer to place number of bytes copied
972 *Status
= ProTransferData(NdisBindingHandle
,