- In Win32 DBG is defined to 0 for a non-debug build and to 1 for a debug build....
[reactos.git] / reactos / drivers / network / ndis / ndis / protocol.c
1 /*
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)
8 * REVISIONS:
9 * CSH 01/08-2000 Created
10 * 09-13-2003 Vizzini Updates for SendPackets support
11 */
12
13 #include "ndissys.h"
14 #include <buffer.h>
15
16 #define SERVICES_KEY L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\"
17 #define LINKAGE_KEY L"\\Linkage"
18 #define PARAMETERS_KEY L"\\Parameters\\"
19
20 LIST_ENTRY ProtocolListHead;
21 KSPIN_LOCK ProtocolListLock;
22
23 #define WORKER_TEST 0
24
25 typedef struct _DMA_CONTEXT {
26 PLOGICAL_ADAPTER Adapter;
27 PNDIS_PACKET Packet;
28 } DMA_CONTEXT, *PDMA_CONTEXT;
29
30 PNET_PNP_EVENT
31 ProSetupPnPEvent(
32 NET_PNP_EVENT_CODE EventCode,
33 PVOID EventBuffer,
34 ULONG EventBufferLength)
35 {
36 PNET_PNP_EVENT PnPEvent;
37
38 PnPEvent = ExAllocatePool(PagedPool, sizeof(NET_PNP_EVENT));
39 if (!PnPEvent)
40 return NULL;
41
42 RtlZeroMemory(PnPEvent, sizeof(NET_PNP_EVENT));
43
44 PnPEvent->NetEvent = EventCode;
45
46 if (EventBuffer != NULL)
47 {
48 PnPEvent->Buffer = ExAllocatePool(PagedPool, EventBufferLength);
49 if (!PnPEvent->Buffer)
50 {
51 ExFreePool(PnPEvent);
52 return NULL;
53 }
54
55 PnPEvent->BufferLength = EventBufferLength;
56
57 RtlCopyMemory(PnPEvent->Buffer, EventBuffer, PnPEvent->BufferLength);
58 }
59
60 return PnPEvent;
61 }
62
63 NDIS_STATUS
64 ProSendAndFreePnPEvent(
65 PLOGICAL_ADAPTER Adapter,
66 PNET_PNP_EVENT PnPEvent,
67 PIRP Irp)
68 {
69 PLIST_ENTRY CurrentEntry;
70 NDIS_STATUS Status;
71 PADAPTER_BINDING AdapterBinding;
72
73 CurrentEntry = Adapter->ProtocolListHead.Flink;
74
75 while (CurrentEntry != &Adapter->ProtocolListHead)
76 {
77 AdapterBinding = CONTAINING_RECORD(CurrentEntry, ADAPTER_BINDING, AdapterListEntry);
78
79 Status = (*AdapterBinding->ProtocolBinding->Chars.PnPEventHandler)(
80 AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
81 PnPEvent);
82
83 if (Status == NDIS_STATUS_PENDING)
84 {
85 IoMarkIrpPending(Irp);
86 /* Yes, I know this is stupid */
87 PnPEvent->NdisReserved[0] = (ULONG_PTR)Irp;
88 PnPEvent->NdisReserved[1] = (ULONG_PTR)CurrentEntry->Flink;
89 return NDIS_STATUS_PENDING;
90 }
91 else if (Status != NDIS_STATUS_SUCCESS)
92 {
93 if (PnPEvent->Buffer) ExFreePool(PnPEvent->Buffer);
94 ExFreePool(PnPEvent);
95 return Status;
96 }
97
98 CurrentEntry = CurrentEntry->Flink;
99 }
100
101 if (PnPEvent->Buffer) ExFreePool(PnPEvent->Buffer);
102 ExFreePool(PnPEvent);
103
104 return NDIS_STATUS_SUCCESS;
105 }
106
107 NTSTATUS
108 NTAPI
109 NdisIPwrSetPower(
110 IN PDEVICE_OBJECT DeviceObject,
111 PIRP Irp)
112 {
113 PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)DeviceObject->DeviceExtension;
114 PNET_PNP_EVENT PnPEvent;
115 PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
116
117 ASSERT(Stack->Parameters.Power.Type == DevicePowerState);
118
119 PnPEvent = ProSetupPnPEvent(NetEventSetPower, &Stack->Parameters.Power.State, sizeof(NDIS_DEVICE_POWER_STATE));
120 if (!PnPEvent)
121 return NDIS_STATUS_RESOURCES;
122
123 return ProSendAndFreePnPEvent(Adapter, PnPEvent, Irp);
124 }
125
126 NTSTATUS
127 NTAPI
128 NdisIPwrQueryPower(
129 IN PDEVICE_OBJECT DeviceObject,
130 PIRP Irp)
131 {
132 PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)DeviceObject->DeviceExtension;
133 PNET_PNP_EVENT PnPEvent;
134 PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
135
136 ASSERT(Stack->Parameters.Power.Type == DevicePowerState);
137
138 PnPEvent = ProSetupPnPEvent(NetEventQueryPower, &Stack->Parameters.Power.State, sizeof(NDIS_DEVICE_POWER_STATE));
139 if (!PnPEvent)
140 return NDIS_STATUS_RESOURCES;
141
142 return ProSendAndFreePnPEvent(Adapter, PnPEvent, Irp);
143 }
144
145
146 NTSTATUS
147 NTAPI
148 NdisIPnPQueryStopDevice(
149 IN PDEVICE_OBJECT DeviceObject,
150 PIRP Irp)
151 {
152 PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)DeviceObject->DeviceExtension;
153 PNET_PNP_EVENT PnPEvent;
154
155 PnPEvent = ProSetupPnPEvent(NetEventQueryRemoveDevice, NULL, 0);
156 if (!PnPEvent)
157 return NDIS_STATUS_RESOURCES;
158
159 return ProSendAndFreePnPEvent(Adapter, PnPEvent, Irp);
160 }
161
162 NTSTATUS
163 NTAPI
164 NdisIPnPCancelStopDevice(
165 IN PDEVICE_OBJECT DeviceObject,
166 PIRP Irp)
167 {
168 PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)DeviceObject->DeviceExtension;
169 PNET_PNP_EVENT PnPEvent;
170
171 PnPEvent = ProSetupPnPEvent(NetEventCancelRemoveDevice, NULL, 0);
172 if (!PnPEvent)
173 return NDIS_STATUS_RESOURCES;
174
175 return ProSendAndFreePnPEvent(Adapter, PnPEvent, Irp);
176 }
177
178 \f
179 /*
180 * @implemented
181 */
182 VOID
183 EXPORT
184 NdisCompleteBindAdapter(
185 IN NDIS_HANDLE BindAdapterContext,
186 IN NDIS_STATUS Status,
187 IN NDIS_STATUS OpenStatus)
188 /*
189 * FUNCTION: Indicates a packet to bound protocols
190 * ARGUMENTS:
191 * Adapter = Pointer to logical adapter
192 * Packet = Pointer to packet to indicate
193 * RETURNS:
194 * Status of operation
195 * NOTES:
196 * - FIXME: partially-implemented
197 */
198 {
199 PROTOCOL_BINDING *Protocol = (PROTOCOL_BINDING *)BindAdapterContext;
200
201 if (!NT_SUCCESS(Status)) return;
202
203 /* Put protocol binding struct on global list */
204 ExInterlockedInsertTailList(&ProtocolListHead, &Protocol->ListEntry, &ProtocolListLock);
205 }
206
207 /*
208 * @implemented
209 */
210 VOID
211 EXPORT
212 NdisCompleteUnbindAdapter(
213 IN NDIS_HANDLE UnbindAdapterContext,
214 IN NDIS_STATUS Status)
215 {
216 /* We probably need to do more here but for now we just do
217 * the opposite of what NdisCompleteBindAdapter does
218 */
219
220 PROTOCOL_BINDING *Protocol = (PROTOCOL_BINDING *)UnbindAdapterContext;
221
222 if (!NT_SUCCESS(Status)) return;
223
224 ExInterlockedRemoveEntryList(&Protocol->ListEntry, &ProtocolListLock);
225 }
226
227 \f
228 NDIS_STATUS
229 ProIndicatePacket(
230 PLOGICAL_ADAPTER Adapter,
231 PNDIS_PACKET Packet)
232 /*
233 * FUNCTION: Indicates a packet to bound protocols
234 * ARGUMENTS:
235 * Adapter = Pointer to logical adapter
236 * Packet = Pointer to packet to indicate
237 * RETURNS:
238 * STATUS_SUCCESS in all cases
239 * NOTES:
240 * - XXX ATM, this only handles loopback packets - is that its designed function?
241 */
242 {
243 UINT BufferedLength;
244 UINT PacketLength;
245 KIRQL OldIrql;
246 PUCHAR LookaheadBuffer;
247
248 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
249
250 #if DBG
251 MiniDisplayPacket(Packet);
252 #endif
253
254 LookaheadBuffer = ExAllocatePool(NonPagedPool, Adapter->NdisMiniportBlock.CurrentLookahead + Adapter->MediumHeaderSize);
255 if (!LookaheadBuffer)
256 return NDIS_STATUS_RESOURCES;
257
258 NdisQueryPacket(Packet, NULL, NULL, NULL, &PacketLength);
259
260 NDIS_DbgPrint(MAX_TRACE, ("acquiring miniport block lock\n"));
261 KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
262 {
263 BufferedLength = CopyPacketToBuffer(LookaheadBuffer, Packet, 0, Adapter->NdisMiniportBlock.CurrentLookahead);
264 }
265 KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
266
267 if (BufferedLength > Adapter->MediumHeaderSize)
268 {
269 /* XXX Change this to call SendPackets so we don't have to duplicate this wacky logic */
270 MiniIndicateData(Adapter, NULL, LookaheadBuffer, Adapter->MediumHeaderSize,
271 &LookaheadBuffer[Adapter->MediumHeaderSize], BufferedLength - Adapter->MediumHeaderSize,
272 PacketLength - Adapter->MediumHeaderSize);
273 }
274 else
275 {
276 MiniIndicateData(Adapter, NULL, LookaheadBuffer, Adapter->MediumHeaderSize, NULL, 0, 0);
277 }
278
279 ExFreePool(LookaheadBuffer);
280
281 return NDIS_STATUS_SUCCESS;
282 }
283
284 \f
285 NDIS_STATUS NTAPI
286 ProRequest(
287 IN NDIS_HANDLE MacBindingHandle,
288 IN PNDIS_REQUEST NdisRequest)
289 /*
290 * FUNCTION: Forwards a request to an NDIS miniport
291 * ARGUMENTS:
292 * MacBindingHandle = Adapter binding handle
293 * NdisRequest = Pointer to request to perform
294 * RETURNS:
295 * Status of operation
296 */
297 {
298 PADAPTER_BINDING AdapterBinding;
299 PLOGICAL_ADAPTER Adapter;
300 PNDIS_REQUEST_MAC_BLOCK MacBlock = (PNDIS_REQUEST_MAC_BLOCK)NdisRequest->MacReserved;
301
302 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
303
304 ASSERT(MacBindingHandle);
305 AdapterBinding = GET_ADAPTER_BINDING(MacBindingHandle);
306
307 ASSERT(AdapterBinding->Adapter);
308 Adapter = AdapterBinding->Adapter;
309
310 MacBlock->Binding = &AdapterBinding->NdisOpenBlock;
311
312 #if WORKER_TEST
313 MiniQueueWorkItem(Adapter, NdisWorkItemRequest, NdisRequest, FALSE);
314 return NDIS_STATUS_PENDING;
315 #else
316 if (MiniIsBusy(Adapter, NdisWorkItemRequest)) {
317 MiniQueueWorkItem(Adapter, NdisWorkItemRequest, NdisRequest, FALSE);
318 return NDIS_STATUS_PENDING;
319 }
320
321 return MiniDoRequest(Adapter, NdisRequest);
322 #endif
323 }
324
325 \f
326 NDIS_STATUS NTAPI
327 ProReset(
328 IN NDIS_HANDLE MacBindingHandle)
329 {
330 UNIMPLEMENTED
331
332 return NDIS_STATUS_FAILURE;
333 }
334
335 VOID NTAPI
336 ScatterGatherSendPacket(
337 IN PDEVICE_OBJECT DeviceObject,
338 IN PIRP Irp,
339 IN PSCATTER_GATHER_LIST ScatterGather,
340 IN PVOID Context)
341 {
342 PDMA_CONTEXT DmaContext = Context;
343 PLOGICAL_ADAPTER Adapter = DmaContext->Adapter;
344 PNDIS_PACKET Packet = DmaContext->Packet;
345 NDIS_STATUS Status;
346
347 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
348
349 NDIS_PER_PACKET_INFO_FROM_PACKET(Packet,
350 ScatterGatherListPacketInfo) = ScatterGather;
351
352 Status = proSendPacketToMiniport(Adapter, Packet);
353
354 if (Status != NDIS_STATUS_PENDING) {
355 NDIS_DbgPrint(MAX_TRACE, ("Completing packet.\n"));
356 MiniSendComplete(Adapter,
357 Packet,
358 Status);
359 }
360
361 ExFreePool(DmaContext);
362 }
363
364 NDIS_STATUS
365 proSendPacketToMiniport(PLOGICAL_ADAPTER Adapter, PNDIS_PACKET Packet)
366 {
367 #if WORKER_TEST
368 MiniQueueWorkItem(Adapter, NdisWorkItemSend, Packet, FALSE);
369 return NDIS_STATUS_PENDING;
370 #else
371 KIRQL RaiseOldIrql;
372 NDIS_STATUS NdisStatus;
373
374 if(MiniIsBusy(Adapter, NdisWorkItemSend)) {
375 MiniQueueWorkItem(Adapter, NdisWorkItemSend, Packet, FALSE);
376 return NDIS_STATUS_PENDING;
377 }
378
379 if(Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendPacketsHandler)
380 {
381 if(Adapter->NdisMiniportBlock.Flags & NDIS_ATTRIBUTE_DESERIALIZE)
382 {
383 NDIS_DbgPrint(MAX_TRACE, ("Calling miniport's SendPackets handler\n"));
384 (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendPacketsHandler)(
385 Adapter->NdisMiniportBlock.MiniportAdapterContext, &Packet, 1);
386 NdisStatus = NDIS_STATUS_PENDING;
387 } else {
388 /* SendPackets is called at DISPATCH_LEVEL for all serialized miniports */
389 KeRaiseIrql(DISPATCH_LEVEL, &RaiseOldIrql);
390 {
391 NDIS_DbgPrint(MAX_TRACE, ("Calling miniport's SendPackets handler\n"));
392 (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendPacketsHandler)(
393 Adapter->NdisMiniportBlock.MiniportAdapterContext, &Packet, 1);
394 }
395 KeLowerIrql(RaiseOldIrql);
396
397 NdisStatus = NDIS_GET_PACKET_STATUS(Packet);
398 if (NdisStatus == NDIS_STATUS_RESOURCES) {
399 MiniQueueWorkItem(Adapter, NdisWorkItemSend, Packet, TRUE);
400 NdisStatus = NDIS_STATUS_PENDING;
401 }
402 }
403
404 return NdisStatus;
405 } else {
406 if(Adapter->NdisMiniportBlock.Flags & NDIS_ATTRIBUTE_DESERIALIZE)
407 {
408 NDIS_DbgPrint(MAX_TRACE, ("Calling miniport's Send handler\n"));
409 NdisStatus = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendHandler)(
410 Adapter->NdisMiniportBlock.MiniportAdapterContext, Packet, Packet->Private.Flags);
411 NDIS_DbgPrint(MAX_TRACE, ("back from miniport's send handler\n"));
412 } else {
413 /* Send is called at DISPATCH_LEVEL for all serialized miniports */
414 KeRaiseIrql(DISPATCH_LEVEL, &RaiseOldIrql);
415 NDIS_DbgPrint(MAX_TRACE, ("Calling miniport's Send handler\n"));
416 NdisStatus = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendHandler)(
417 Adapter->NdisMiniportBlock.MiniportAdapterContext, Packet, Packet->Private.Flags);
418 NDIS_DbgPrint(MAX_TRACE, ("back from miniport's send handler\n"));
419 KeLowerIrql(RaiseOldIrql);
420
421 if (NdisStatus == NDIS_STATUS_RESOURCES) {
422 MiniQueueWorkItem(Adapter, NdisWorkItemSend, Packet, TRUE);
423 NdisStatus = NDIS_STATUS_PENDING;
424 }
425 }
426
427 return NdisStatus;
428 }
429 #endif
430 }
431
432 \f
433 NDIS_STATUS NTAPI
434 ProSend(
435 IN NDIS_HANDLE MacBindingHandle,
436 IN PNDIS_PACKET Packet)
437 /*
438 * FUNCTION: Forwards a request to send a packet to an NDIS miniport
439 * ARGUMENTS:
440 * MacBindingHandle = Adapter binding handle
441 * Packet = Pointer to NDIS packet descriptor
442 * RETURNS:
443 * NDIS_STATUS_SUCCESS if the packet was successfully sent
444 * NDIS_STATUS_PENDING if the miniport was busy or a serialized miniport returned NDIS_STATUS_RESOURCES
445 */
446 {
447 PADAPTER_BINDING AdapterBinding;
448 PLOGICAL_ADAPTER Adapter;
449 PNDIS_BUFFER NdisBuffer;
450 PDMA_CONTEXT Context;
451 NDIS_STATUS NdisStatus;
452 UINT PacketLength;
453 KIRQL OldIrql;
454
455 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
456
457 ASSERT(MacBindingHandle);
458 AdapterBinding = GET_ADAPTER_BINDING(MacBindingHandle);
459
460 ASSERT(AdapterBinding);
461 Adapter = AdapterBinding->Adapter;
462
463 ASSERT(Adapter);
464
465 /* if the following is not true, KeRaiseIrql() below will break */
466 ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
467
468 /* XXX what is this crazy black magic? */
469 Packet->Reserved[1] = (ULONG_PTR)MacBindingHandle;
470
471 /*
472 * Test the packet to see if it is a MAC loopback.
473 *
474 * We may have to loop this packet if miniport cannot.
475 * If dest MAC address of packet == MAC address of adapter,
476 * this is a loopback frame.
477 */
478
479 if ((Adapter->NdisMiniportBlock.MacOptions & NDIS_MAC_OPTION_NO_LOOPBACK) &&
480 MiniAdapterHasAddress(Adapter, Packet))
481 {
482 #if WORKER_TEST
483 MiniQueueWorkItem(Adapter, NdisWorkItemSendLoopback, Packet, FALSE);
484 return NDIS_STATUS_PENDING;
485 #else
486 return ProIndicatePacket(Adapter, Packet);
487 #endif
488 } else {
489 if (Adapter->NdisMiniportBlock.ScatterGatherListSize != 0)
490 {
491 NDIS_DbgPrint(MAX_TRACE, ("Using Scatter/Gather DMA\n"));
492
493 NdisQueryPacket(Packet,
494 NULL,
495 NULL,
496 &NdisBuffer,
497 &PacketLength);
498
499 Context = ExAllocatePool(NonPagedPool, sizeof(DMA_CONTEXT));
500 if (!Context)
501 return NDIS_STATUS_RESOURCES;
502
503 Context->Adapter = Adapter;
504 Context->Packet = Packet;
505
506 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
507
508 KeFlushIoBuffers(NdisBuffer, FALSE, TRUE);
509
510 NdisStatus = Adapter->NdisMiniportBlock.SystemAdapterObject->DmaOperations->GetScatterGatherList(
511 Adapter->NdisMiniportBlock.SystemAdapterObject,
512 Adapter->NdisMiniportBlock.PhysicalDeviceObject,
513 NdisBuffer,
514 MmGetMdlVirtualAddress(NdisBuffer),
515 PacketLength,
516 ScatterGatherSendPacket,
517 Context,
518 TRUE);
519
520 KeLowerIrql(OldIrql);
521
522 if (!NT_SUCCESS(NdisStatus)) {
523 NDIS_DbgPrint(MIN_TRACE, ("GetScatterGatherList failed!\n"));
524 return NdisStatus;
525 }
526
527 return NDIS_STATUS_PENDING;
528 }
529
530
531 return proSendPacketToMiniport(Adapter, Packet);
532 }
533 }
534
535 \f
536 VOID NTAPI
537 ProSendPackets(
538 IN NDIS_HANDLE NdisBindingHandle,
539 IN PPNDIS_PACKET PacketArray,
540 IN UINT NumberOfPackets)
541 {
542 PADAPTER_BINDING AdapterBinding = NdisBindingHandle;
543 PLOGICAL_ADAPTER Adapter = AdapterBinding->Adapter;
544 KIRQL RaiseOldIrql;
545 NDIS_STATUS NdisStatus;
546 UINT i;
547
548 if(Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendPacketsHandler)
549 {
550 if(Adapter->NdisMiniportBlock.Flags & NDIS_ATTRIBUTE_DESERIALIZE)
551 {
552 (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendPacketsHandler)(
553 Adapter->NdisMiniportBlock.MiniportAdapterContext, PacketArray, NumberOfPackets);
554 }
555 else
556 {
557 /* SendPackets is called at DISPATCH_LEVEL for all serialized miniports */
558 KeRaiseIrql(DISPATCH_LEVEL, &RaiseOldIrql);
559 (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendPacketsHandler)(
560 Adapter->NdisMiniportBlock.MiniportAdapterContext, PacketArray, NumberOfPackets);
561 KeLowerIrql(RaiseOldIrql);
562 for (i = 0; i < NumberOfPackets; i++)
563 {
564 NdisStatus = NDIS_GET_PACKET_STATUS(PacketArray[i]);
565 if (NdisStatus != NDIS_STATUS_PENDING)
566 MiniSendComplete(Adapter, PacketArray[i], NdisStatus);
567 }
568 }
569 }
570 else
571 {
572 if(Adapter->NdisMiniportBlock.Flags & NDIS_ATTRIBUTE_DESERIALIZE)
573 {
574 for (i = 0; i < NumberOfPackets; i++)
575 {
576 NdisStatus = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendHandler)(
577 Adapter->NdisMiniportBlock.MiniportAdapterContext, PacketArray[i], PacketArray[i]->Private.Flags);
578 if (NdisStatus != NDIS_STATUS_PENDING)
579 MiniSendComplete(Adapter, PacketArray[i], NdisStatus);
580 }
581 }
582 else
583 {
584 /* Send is called at DISPATCH_LEVEL for all serialized miniports */
585 KeRaiseIrql(DISPATCH_LEVEL, &RaiseOldIrql);
586 for (i = 0; i < NumberOfPackets; i++)
587 {
588 NdisStatus = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendHandler)(
589 Adapter->NdisMiniportBlock.MiniportAdapterContext, PacketArray[i], PacketArray[i]->Private.Flags);
590 if (NdisStatus != NDIS_STATUS_PENDING)
591 MiniSendComplete(Adapter, PacketArray[i], NdisStatus);
592 }
593 KeLowerIrql(RaiseOldIrql);
594 }
595 }
596 }
597
598 \f
599 NDIS_STATUS NTAPI
600 ProTransferData(
601 IN NDIS_HANDLE MacBindingHandle,
602 IN NDIS_HANDLE MacReceiveContext,
603 IN UINT ByteOffset,
604 IN UINT BytesToTransfer,
605 IN OUT PNDIS_PACKET Packet,
606 OUT PUINT BytesTransferred)
607 /*
608 * FUNCTION: Forwards a request to copy received data into a protocol-supplied packet
609 * ARGUMENTS:
610 * MacBindingHandle = Adapter binding handle
611 * MacReceiveContext = MAC receive context
612 * ByteOffset = Offset in packet to place data
613 * BytesToTransfer = Number of bytes to copy into packet
614 * Packet = Pointer to NDIS packet descriptor
615 * BytesTransferred = Address of buffer to place number of bytes copied
616 */
617 {
618 PADAPTER_BINDING AdapterBinding = GET_ADAPTER_BINDING(MacBindingHandle);
619 PLOGICAL_ADAPTER Adapter = AdapterBinding->Adapter;
620 NDIS_STATUS Status;
621 KIRQL OldIrql;
622
623 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
624
625 /* FIXME: Interrupts must be disabled for adapter */
626 /* XXX sd - why is that true? */
627
628 if (Packet == Adapter->NdisMiniportBlock.IndicatedPacket[KeGetCurrentProcessorNumber()]) {
629 NDIS_DbgPrint(MAX_TRACE, ("LoopPacket\n"));
630 /* NDIS is responsible for looping this packet */
631 NdisCopyFromPacketToPacket(Packet,
632 ByteOffset,
633 BytesToTransfer,
634 Adapter->NdisMiniportBlock.IndicatedPacket[KeGetCurrentProcessorNumber()],
635 0,
636 BytesTransferred);
637 return NDIS_STATUS_SUCCESS;
638 }
639
640 ASSERT(Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.TransferDataHandler);
641
642 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
643
644 Status = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.TransferDataHandler)(
645 Packet,
646 BytesTransferred,
647 Adapter->NdisMiniportBlock.MiniportAdapterContext,
648 MacReceiveContext,
649 ByteOffset,
650 BytesToTransfer);
651
652 KeLowerIrql(OldIrql);
653
654 return Status;
655 }
656
657
658
659 /*
660 * @implemented
661 */
662 VOID
663 EXPORT
664 NdisCloseAdapter(
665 OUT PNDIS_STATUS Status,
666 IN NDIS_HANDLE NdisBindingHandle)
667 /*
668 * FUNCTION: Closes an adapter opened with NdisOpenAdapter
669 * ARGUMENTS:
670 * Status = Address of buffer for status information
671 * NdisBindingHandle = Handle returned by NdisOpenAdapter
672 */
673 {
674 PADAPTER_BINDING AdapterBinding = GET_ADAPTER_BINDING(NdisBindingHandle);
675
676 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
677
678 /* Remove from protocol's bound adapters list */
679 ExInterlockedRemoveEntryList(&AdapterBinding->ProtocolListEntry, &AdapterBinding->ProtocolBinding->Lock);
680
681 /* Remove protocol from adapter's bound protocols list */
682 ExInterlockedRemoveEntryList(&AdapterBinding->AdapterListEntry, &AdapterBinding->Adapter->NdisMiniportBlock.Lock);
683
684 ExFreePool(AdapterBinding);
685
686 *Status = NDIS_STATUS_SUCCESS;
687 }
688
689
690 /*
691 * @implemented
692 */
693 VOID
694 EXPORT
695 NdisDeregisterProtocol(
696 OUT PNDIS_STATUS Status,
697 IN NDIS_HANDLE NdisProtocolHandle)
698 /*
699 * FUNCTION: Releases the resources allocated by NdisRegisterProtocol
700 * ARGUMENTS:
701 * Status = Address of buffer for status information
702 * NdisProtocolHandle = Handle returned by NdisRegisterProtocol
703 */
704 {
705 PPROTOCOL_BINDING Protocol = GET_PROTOCOL_BINDING(NdisProtocolHandle);
706
707 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
708
709 /* FIXME: Make sure no adapter bindings exist */
710
711 /* Remove protocol from global list */
712 ExInterlockedRemoveEntryList(&Protocol->ListEntry, &ProtocolListLock);
713
714 ExFreePool(Protocol);
715
716 *Status = NDIS_STATUS_SUCCESS;
717 }
718
719
720 /*
721 * @implemented
722 */
723 VOID
724 EXPORT
725 NdisOpenAdapter(
726 OUT PNDIS_STATUS Status,
727 OUT PNDIS_STATUS OpenErrorStatus,
728 OUT PNDIS_HANDLE NdisBindingHandle,
729 OUT PUINT SelectedMediumIndex,
730 IN PNDIS_MEDIUM MediumArray,
731 IN UINT MediumArraySize,
732 IN NDIS_HANDLE NdisProtocolHandle,
733 IN NDIS_HANDLE ProtocolBindingContext,
734 IN PNDIS_STRING AdapterName,
735 IN UINT OpenOptions,
736 IN PSTRING AddressingInformation OPTIONAL)
737 /*
738 * FUNCTION: Opens an adapter for communication
739 * ARGUMENTS:
740 * Status = Address of buffer for status information
741 * OpenErrorStatus = Address of buffer for secondary error code
742 * NdisBindingHandle = Address of buffer for adapter binding handle
743 * SelectedMediumIndex = Address of buffer for selected medium
744 * MediumArray = Pointer to an array of NDIS_MEDIUMs called can support
745 * MediumArraySize = Number of elements in MediumArray
746 * NdisProtocolHandle = Handle returned by NdisRegisterProtocol
747 * ProtocolBindingContext = Pointer to caller suplied context area
748 * AdapterName = Pointer to buffer with name of adapter
749 * OpenOptions = Bitmask with flags passed to next-lower driver
750 * AddressingInformation = Optional pointer to buffer with NIC specific information
751 */
752 {
753 UINT i;
754 BOOLEAN Found;
755 PLOGICAL_ADAPTER Adapter;
756 PADAPTER_BINDING AdapterBinding;
757 PPROTOCOL_BINDING Protocol = GET_PROTOCOL_BINDING(NdisProtocolHandle);
758
759 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
760
761 if(!NdisProtocolHandle)
762 {
763 NDIS_DbgPrint(MAX_TRACE, ("NdisProtocolHandle is NULL\n"));
764 *OpenErrorStatus = *Status = NDIS_STATUS_FAILURE;
765 return;
766 }
767
768 Adapter = MiniLocateDevice(AdapterName);
769 if (!Adapter)
770 {
771 NDIS_DbgPrint(MIN_TRACE, ("Adapter not found.\n"));
772 *Status = NDIS_STATUS_ADAPTER_NOT_FOUND;
773 return;
774 }
775
776 /* Find the media type in the list provided by the protocol driver */
777 Found = FALSE;
778 for (i = 0; i < MediumArraySize; i++)
779 {
780 if (Adapter->NdisMiniportBlock.MediaType == MediumArray[i])
781 {
782 *SelectedMediumIndex = i;
783 Found = TRUE;
784 break;
785 }
786 }
787
788 if (!Found)
789 {
790 NDIS_DbgPrint(MIN_TRACE, ("Medium is not supported.\n"));
791 *Status = NDIS_STATUS_UNSUPPORTED_MEDIA;
792 return;
793 }
794
795 /* Now that we have confirmed that the adapter can be opened, create a binding */
796
797 AdapterBinding = ExAllocatePool(NonPagedPool, sizeof(ADAPTER_BINDING));
798 if (!AdapterBinding)
799 {
800 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
801 *Status = NDIS_STATUS_RESOURCES;
802 return;
803 }
804
805 RtlZeroMemory(AdapterBinding, sizeof(ADAPTER_BINDING));
806
807 AdapterBinding->ProtocolBinding = Protocol;
808 AdapterBinding->Adapter = Adapter;
809 AdapterBinding->NdisOpenBlock.ProtocolBindingContext = ProtocolBindingContext;
810
811 /* Set fields required by some NDIS macros */
812 AdapterBinding->NdisOpenBlock.BindingHandle = (NDIS_HANDLE)AdapterBinding;
813
814 /* Set handlers (some NDIS macros require these) */
815
816 AdapterBinding->NdisOpenBlock.RequestHandler = ProRequest;
817 AdapterBinding->NdisOpenBlock.ResetHandler = ProReset;
818 AdapterBinding->NdisOpenBlock.SendHandler = ProSend;
819 AdapterBinding->NdisOpenBlock.SendPacketsHandler = ProSendPackets;
820 AdapterBinding->NdisOpenBlock.TransferDataHandler = ProTransferData;
821
822 AdapterBinding->NdisOpenBlock.RequestCompleteHandler =
823 Protocol->Chars.RequestCompleteHandler;
824
825 /* Put on protocol's bound adapters list */
826 ExInterlockedInsertTailList(&Protocol->AdapterListHead, &AdapterBinding->ProtocolListEntry, &Protocol->Lock);
827
828 /* Put protocol on adapter's bound protocols list */
829 NDIS_DbgPrint(MAX_TRACE, ("acquiring miniport block lock\n"));
830 ExInterlockedInsertTailList(&Adapter->ProtocolListHead, &AdapterBinding->AdapterListEntry, &Adapter->NdisMiniportBlock.Lock);
831
832 *NdisBindingHandle = (NDIS_HANDLE)AdapterBinding;
833
834 *Status = NDIS_STATUS_SUCCESS;
835 }
836
837 VOID
838 NTAPI
839 ndisBindMiniportsToProtocol(OUT PNDIS_STATUS Status, IN PNDIS_PROTOCOL_CHARACTERISTICS ProtocolCharacteristics)
840 {
841 /*
842 * bind the protocol to all of its miniports
843 *
844 * open registry path
845 * get list of devices from Bind key
846 * call BindAdapterHandler for each
847 */
848 OBJECT_ATTRIBUTES ObjectAttributes;
849 UNICODE_STRING RegistryPath;
850 WCHAR *RegistryPathStr;
851 NTSTATUS NtStatus;
852 WCHAR *DataPtr;
853 HANDLE DriverKeyHandle = NULL;
854 PKEY_VALUE_PARTIAL_INFORMATION KeyInformation = NULL;
855
856 RegistryPathStr = ExAllocatePoolWithTag(PagedPool, sizeof(SERVICES_KEY) + ProtocolCharacteristics->Name.Length + sizeof(LINKAGE_KEY), NDIS_TAG + __LINE__);
857 if(!RegistryPathStr)
858 {
859 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
860 *Status = NDIS_STATUS_RESOURCES;
861 return;
862 }
863
864 wcscpy(RegistryPathStr, SERVICES_KEY);
865 wcsncat(RegistryPathStr, ((WCHAR *)ProtocolCharacteristics->Name.Buffer), ProtocolCharacteristics->Name.Length / sizeof(WCHAR));
866 RegistryPathStr[wcslen(SERVICES_KEY)+ProtocolCharacteristics->Name.Length/sizeof(WCHAR)] = 0;
867 wcscat(RegistryPathStr, LINKAGE_KEY);
868
869 RtlInitUnicodeString(&RegistryPath, RegistryPathStr);
870 NDIS_DbgPrint(MAX_TRACE, ("Opening configuration key: %wZ\n", &RegistryPath));
871
872 InitializeObjectAttributes(&ObjectAttributes, &RegistryPath, OBJ_CASE_INSENSITIVE, NULL, NULL);
873 NtStatus = ZwOpenKey(&DriverKeyHandle, KEY_READ, &ObjectAttributes);
874
875 ExFreePool(RegistryPathStr);
876
877 if(!NT_SUCCESS(NtStatus))
878 {
879 NDIS_DbgPrint(MIN_TRACE, ("Unable to open protocol configuration\n"));
880 *Status = NDIS_STATUS_FAILURE;
881 return;
882 }
883
884 NDIS_DbgPrint(MAX_TRACE, ("Successfully opened the registry configuration\n"));
885
886 {
887 UNICODE_STRING ValueName;
888 ULONG ResultLength;
889
890 RtlInitUnicodeString(&ValueName, L"Bind");
891
892 NtStatus = ZwQueryValueKey(DriverKeyHandle, &ValueName, KeyValuePartialInformation, NULL, 0, &ResultLength);
893 if(NtStatus != STATUS_BUFFER_OVERFLOW && NtStatus != STATUS_BUFFER_TOO_SMALL && NtStatus != STATUS_SUCCESS)
894 {
895 NDIS_DbgPrint(MIN_TRACE, ("Unable to query the Bind value for size\n"));
896 ZwClose(DriverKeyHandle);
897 *Status = NDIS_STATUS_FAILURE;
898 return;
899 }
900
901 KeyInformation = ExAllocatePoolWithTag(PagedPool, sizeof(KEY_VALUE_PARTIAL_INFORMATION) + ResultLength, NDIS_TAG + __LINE__);
902 if(!KeyInformation)
903 {
904 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
905 ZwClose(DriverKeyHandle);
906 *Status = NDIS_STATUS_FAILURE;
907 return;
908 }
909
910 NtStatus = ZwQueryValueKey(DriverKeyHandle, &ValueName, KeyValuePartialInformation, KeyInformation,
911 sizeof(KEY_VALUE_PARTIAL_INFORMATION) + ResultLength, &ResultLength);
912
913 ZwClose(DriverKeyHandle);
914
915 if(!NT_SUCCESS(NtStatus))
916 {
917 NDIS_DbgPrint(MIN_TRACE, ("Unable to query the Bind value\n"));
918 ExFreePool(KeyInformation);
919 *Status = NDIS_STATUS_FAILURE;
920 return;
921 }
922 }
923
924 for (DataPtr = (WCHAR *)KeyInformation->Data;
925 *DataPtr != 0;
926 DataPtr += wcslen(DataPtr) + 1)
927 {
928 /* BindContext is for tracking pending binding operations */
929 VOID *BindContext = 0;
930 NDIS_STRING DeviceName;
931 NDIS_STRING RegistryPath;
932 WCHAR *RegistryPathStr = NULL;
933 ULONG PathLength = 0;
934
935 RtlInitUnicodeString(&DeviceName, DataPtr); /* we know this is 0-term */
936
937 /*
938 * RegistryPath should be:
939 * \Registry\Machine\System\CurrentControlSet\Services\Nic1\Parameters\Tcpip
940 *
941 * This is constructed as follows:
942 * SERVICES_KEY + extracted device name + Protocol name from characteristics
943 */
944
945 PathLength = sizeof(SERVICES_KEY) + /* \Registry\Machine\System\CurrentControlSet\Services\ */
946 wcslen( DataPtr + 8 ) * sizeof(WCHAR) + /* Adapter1 (extracted from \Device\Adapter1) */
947 sizeof(PARAMETERS_KEY) + /* \Parameters\ */
948 ProtocolCharacteristics->Name.Length + sizeof(WCHAR); /* Tcpip */
949
950 RegistryPathStr = ExAllocatePool(PagedPool, PathLength);
951 if(!RegistryPathStr)
952 {
953 NDIS_DbgPrint(MIN_TRACE, ("insufficient resources.\n"));
954 ExFreePool(KeyInformation);
955 *Status = NDIS_STATUS_RESOURCES;
956 return;
957 }
958
959 wcscpy(RegistryPathStr, SERVICES_KEY);
960 wcscat(RegistryPathStr, DataPtr + 8 );
961 wcscat(RegistryPathStr, PARAMETERS_KEY);
962 wcsncat(RegistryPathStr, ProtocolCharacteristics->Name.Buffer, ProtocolCharacteristics->Name.Length / sizeof(WCHAR) );
963
964 RegistryPathStr[PathLength/sizeof(WCHAR) - 1] = 0;
965
966 RtlInitUnicodeString(&RegistryPath, RegistryPathStr);
967
968 NDIS_DbgPrint(MAX_TRACE, ("Calling protocol's BindAdapter handler with DeviceName %wZ and RegistryPath %wZ\n",
969 &DeviceName, &RegistryPath));
970
971 {
972 BIND_HANDLER BindHandler = ProtocolCharacteristics->BindAdapterHandler;
973 if(BindHandler)
974 BindHandler(Status, BindContext, &DeviceName, &RegistryPath, 0);
975 else
976 NDIS_DbgPrint(MID_TRACE, ("No protocol bind handler specified\n"));
977 }
978 }
979
980 *Status = NDIS_STATUS_SUCCESS;
981 ExFreePool(KeyInformation);
982 }
983
984 /*
985 * @implemented
986 */
987 VOID
988 EXPORT
989 NdisRegisterProtocol(
990 OUT PNDIS_STATUS Status,
991 OUT PNDIS_HANDLE NdisProtocolHandle,
992 IN PNDIS_PROTOCOL_CHARACTERISTICS ProtocolCharacteristics,
993 IN UINT CharacteristicsLength)
994 /*
995 * FUNCTION: Registers an NDIS driver's ProtocolXxx entry points
996 * ARGUMENTS:
997 * Status = Address of buffer for status information
998 * NdisProtocolHandle = Address of buffer for handle used to identify the driver
999 * ProtocolCharacteristics = Pointer to NDIS_PROTOCOL_CHARACTERISTICS structure
1000 * CharacteristicsLength = Size of structure which ProtocolCharacteristics targets
1001 * NOTES:
1002 * - you *must* set NdisProtocolHandle before doing anything that could wind up
1003 * getting BindAdapterHandler, as it will probably call OpenAdapter with this handle
1004 * - the above implies that the initialization of the protocol block must be complete
1005 * by then
1006 * TODO:
1007 * - break this function up - probably do a 'ndisRefreshProtocolBindings' function
1008 * - make this thing able to handle >1 protocol
1009 */
1010 {
1011 PPROTOCOL_BINDING Protocol;
1012 NTSTATUS NtStatus;
1013 UINT MinSize;
1014
1015 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
1016
1017 *NdisProtocolHandle = NULL;
1018
1019 /* first validate the PROTOCOL_CHARACTERISTICS */
1020 switch (ProtocolCharacteristics->MajorNdisVersion)
1021 {
1022 case 0x03:
1023 /* we don't really want to support ndis3 drivers - so we complain for now */
1024 NDIS_DbgPrint(MID_TRACE, ("NDIS 3 protocol attempting to register\n"));
1025 MinSize = sizeof(NDIS30_PROTOCOL_CHARACTERISTICS);
1026 break;
1027
1028 case 0x04:
1029 MinSize = sizeof(NDIS40_PROTOCOL_CHARACTERISTICS);
1030 break;
1031
1032 case 0x05:
1033 MinSize = sizeof(NDIS50_PROTOCOL_CHARACTERISTICS);
1034 break;
1035
1036 default:
1037 *Status = NDIS_STATUS_BAD_VERSION;
1038 NDIS_DbgPrint(MIN_TRACE, ("Incorrect characteristics size\n"));
1039 return;
1040 }
1041
1042 if (CharacteristicsLength < MinSize)
1043 {
1044 NDIS_DbgPrint(MIN_TRACE, ("Bad protocol characteristics.\n"));
1045 *Status = NDIS_STATUS_BAD_CHARACTERISTICS;
1046 return;
1047 }
1048
1049 /* set up the protocol block */
1050 Protocol = ExAllocatePool(NonPagedPool, sizeof(PROTOCOL_BINDING));
1051 if (!Protocol)
1052 {
1053 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
1054 *Status = NDIS_STATUS_RESOURCES;
1055 return;
1056 }
1057
1058 RtlZeroMemory(Protocol, sizeof(PROTOCOL_BINDING));
1059 RtlCopyMemory(&Protocol->Chars, ProtocolCharacteristics, MinSize);
1060
1061 NtStatus = RtlUpcaseUnicodeString(&Protocol->Chars.Name, &ProtocolCharacteristics->Name, TRUE);
1062 if (!NT_SUCCESS(NtStatus))
1063 {
1064 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
1065 ExFreePool(Protocol);
1066 *Status = NDIS_STATUS_RESOURCES;
1067 return;
1068 }
1069
1070 KeInitializeSpinLock(&Protocol->Lock);
1071
1072 InitializeListHead(&Protocol->AdapterListHead);
1073
1074 /* We must set this before the call to ndisBindMiniportsToProtocol because the protocol's
1075 * BindAdapter handler might need it */
1076
1077 *NdisProtocolHandle = Protocol;
1078
1079 ndisBindMiniportsToProtocol(Status, &Protocol->Chars);
1080
1081 if (*Status == NDIS_STATUS_SUCCESS) {
1082 ExInterlockedInsertTailList(&ProtocolListHead, &Protocol->ListEntry, &ProtocolListLock);
1083 } else {
1084 ExFreePool(Protocol);
1085 *NdisProtocolHandle = NULL;
1086 }
1087 }
1088
1089 \f
1090 /*
1091 * @implemented
1092 */
1093 VOID
1094 EXPORT
1095 NdisRequest(
1096 OUT PNDIS_STATUS Status,
1097 IN NDIS_HANDLE NdisBindingHandle,
1098 IN PNDIS_REQUEST NdisRequest)
1099 /*
1100 * FUNCTION: Forwards a request to an NDIS driver
1101 * ARGUMENTS:
1102 * Status = Address of buffer for status information
1103 * NdisBindingHandle = Adapter binding handle
1104 * NdisRequest = Pointer to request to perform
1105 */
1106 {
1107 *Status = ProRequest(NdisBindingHandle, NdisRequest);
1108 }
1109
1110 \f
1111 /*
1112 * @implemented
1113 */
1114 VOID
1115 EXPORT
1116 NdisReset(
1117 OUT PNDIS_STATUS Status,
1118 IN NDIS_HANDLE NdisBindingHandle)
1119 {
1120 *Status = ProReset(NdisBindingHandle);
1121 }
1122
1123 \f
1124 /*
1125 * @implemented
1126 */
1127 #undef NdisSend
1128 VOID
1129 EXPORT
1130 NdisSend(
1131 OUT PNDIS_STATUS Status,
1132 IN NDIS_HANDLE NdisBindingHandle,
1133 IN PNDIS_PACKET Packet)
1134 /*
1135 * FUNCTION: Forwards a request to send a packet
1136 * ARGUMENTS:
1137 * Status = Address of buffer for status information
1138 * NdisBindingHandle = Adapter binding handle
1139 * Packet = Pointer to NDIS packet descriptor
1140 */
1141 {
1142 *Status = ProSend(NdisBindingHandle, Packet);
1143 }
1144
1145 \f
1146 /*
1147 * @implemented
1148 */
1149 #undef NdisSendPackets
1150 VOID
1151 EXPORT
1152 NdisSendPackets(
1153 IN NDIS_HANDLE NdisBindingHandle,
1154 IN PPNDIS_PACKET PacketArray,
1155 IN UINT NumberOfPackets)
1156 {
1157 ProSendPackets(NdisBindingHandle, PacketArray, NumberOfPackets);
1158 }
1159
1160 \f
1161 /*
1162 * @implemented
1163 */
1164 #undef NdisTransferData
1165 VOID
1166 EXPORT
1167 NdisTransferData(
1168 OUT PNDIS_STATUS Status,
1169 IN NDIS_HANDLE NdisBindingHandle,
1170 IN NDIS_HANDLE MacReceiveContext,
1171 IN UINT ByteOffset,
1172 IN UINT BytesToTransfer,
1173 IN OUT PNDIS_PACKET Packet,
1174 OUT PUINT BytesTransferred)
1175 /*
1176 * FUNCTION: Forwards a request to copy received data into a protocol-supplied packet
1177 * ARGUMENTS:
1178 * Status = Address of buffer for status information
1179 * NdisBindingHandle = Adapter binding handle
1180 * MacReceiveContext = MAC receive context
1181 * ByteOffset = Offset in packet to place data
1182 * BytesToTransfer = Number of bytes to copy into packet
1183 * Packet = Pointer to NDIS packet descriptor
1184 * BytesTransferred = Address of buffer to place number of bytes copied
1185 */
1186 {
1187 *Status = ProTransferData(NdisBindingHandle,
1188 MacReceiveContext,
1189 ByteOffset,
1190 BytesToTransfer,
1191 Packet,
1192 BytesTransferred);
1193 }
1194
1195 /*
1196 * @implemented
1197 */
1198 VOID
1199 NTAPI
1200 NdisReEnumerateProtocolBindings(IN NDIS_HANDLE NdisProtocolHandle)
1201 {
1202 PPROTOCOL_BINDING Protocol = NdisProtocolHandle;
1203 NDIS_STATUS NdisStatus;
1204
1205 ndisBindMiniportsToProtocol(&NdisStatus, &Protocol->Chars);
1206 }
1207
1208
1209 /*
1210 * @implemented
1211 */
1212 VOID
1213 EXPORT
1214 NdisGetDriverHandle(
1215 IN PNDIS_HANDLE NdisBindingHandle,
1216 OUT PNDIS_HANDLE NdisDriverHandle)
1217 /*
1218 * FUNCTION:
1219 * ARGUMENTS:
1220 * NOTES:
1221 * NDIS 5.0
1222 */
1223 {
1224 PADAPTER_BINDING Binding = (PADAPTER_BINDING)NdisBindingHandle;
1225
1226 if (!Binding)
1227 {
1228 *NdisDriverHandle = NULL;
1229 return;
1230 }
1231
1232 *NdisDriverHandle = Binding->Adapter->NdisMiniportBlock.DriverHandle;
1233 }
1234
1235 /* EOF */