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