- Restore a value that is lost in MiniportReset when AddressingReset is TRUE
[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
345 NDIS_STATUS NTAPI
346 ProReset(
347 IN NDIS_HANDLE MacBindingHandle)
348 {
349 PADAPTER_BINDING AdapterBinding = MacBindingHandle;
350
351 /* FIXME: Wait for all packets to be sent */
352
353 return MiniReset(AdapterBinding->Adapter);
354 }
355
356 VOID NTAPI
357 ScatterGatherSendPacket(
358 IN PDEVICE_OBJECT DeviceObject,
359 IN PIRP Irp,
360 IN PSCATTER_GATHER_LIST ScatterGather,
361 IN PVOID Context)
362 {
363 PDMA_CONTEXT DmaContext = Context;
364 PLOGICAL_ADAPTER Adapter = DmaContext->Adapter;
365 PNDIS_PACKET Packet = DmaContext->Packet;
366 NDIS_STATUS Status;
367
368 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
369
370 NDIS_PER_PACKET_INFO_FROM_PACKET(Packet,
371 ScatterGatherListPacketInfo) = ScatterGather;
372
373 Status = proSendPacketToMiniport(Adapter, Packet);
374
375 if (Status != NDIS_STATUS_PENDING) {
376 NDIS_DbgPrint(MAX_TRACE, ("Completing packet.\n"));
377 MiniSendComplete(Adapter,
378 Packet,
379 Status);
380 }
381
382 ExFreePool(DmaContext);
383 }
384
385 NDIS_STATUS
386 proSendPacketToMiniport(PLOGICAL_ADAPTER Adapter, PNDIS_PACKET Packet)
387 {
388 #if WORKER_TEST
389 MiniQueueWorkItem(Adapter, NdisWorkItemSend, Packet, FALSE);
390 return NDIS_STATUS_PENDING;
391 #else
392 KIRQL RaiseOldIrql;
393 NDIS_STATUS NdisStatus;
394
395 if(MiniIsBusy(Adapter, NdisWorkItemSend)) {
396 MiniQueueWorkItem(Adapter, NdisWorkItemSend, Packet, FALSE);
397 return NDIS_STATUS_PENDING;
398 }
399
400 if(Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendPacketsHandler)
401 {
402 if(Adapter->NdisMiniportBlock.Flags & NDIS_ATTRIBUTE_DESERIALIZE)
403 {
404 NDIS_DbgPrint(MAX_TRACE, ("Calling miniport's SendPackets handler\n"));
405 (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendPacketsHandler)(
406 Adapter->NdisMiniportBlock.MiniportAdapterContext, &Packet, 1);
407 NdisStatus = NDIS_STATUS_PENDING;
408 } else {
409 /* SendPackets is called at DISPATCH_LEVEL for all serialized miniports */
410 KeRaiseIrql(DISPATCH_LEVEL, &RaiseOldIrql);
411 {
412 NDIS_DbgPrint(MAX_TRACE, ("Calling miniport's SendPackets handler\n"));
413 (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendPacketsHandler)(
414 Adapter->NdisMiniportBlock.MiniportAdapterContext, &Packet, 1);
415 }
416 KeLowerIrql(RaiseOldIrql);
417
418 NdisStatus = NDIS_GET_PACKET_STATUS(Packet);
419 if (NdisStatus == NDIS_STATUS_RESOURCES) {
420 MiniQueueWorkItem(Adapter, NdisWorkItemSend, Packet, TRUE);
421 NdisStatus = NDIS_STATUS_PENDING;
422 }
423 }
424
425 return NdisStatus;
426 } else {
427 if(Adapter->NdisMiniportBlock.Flags & NDIS_ATTRIBUTE_DESERIALIZE)
428 {
429 NDIS_DbgPrint(MAX_TRACE, ("Calling miniport's Send handler\n"));
430 NdisStatus = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendHandler)(
431 Adapter->NdisMiniportBlock.MiniportAdapterContext, Packet, Packet->Private.Flags);
432 NDIS_DbgPrint(MAX_TRACE, ("back from miniport's send handler\n"));
433 } else {
434 /* Send is called at DISPATCH_LEVEL for all serialized miniports */
435 KeRaiseIrql(DISPATCH_LEVEL, &RaiseOldIrql);
436 NDIS_DbgPrint(MAX_TRACE, ("Calling miniport's Send handler\n"));
437 NdisStatus = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendHandler)(
438 Adapter->NdisMiniportBlock.MiniportAdapterContext, Packet, Packet->Private.Flags);
439 NDIS_DbgPrint(MAX_TRACE, ("back from miniport's send handler\n"));
440 KeLowerIrql(RaiseOldIrql);
441
442 if (NdisStatus == NDIS_STATUS_RESOURCES) {
443 MiniQueueWorkItem(Adapter, NdisWorkItemSend, Packet, TRUE);
444 NdisStatus = NDIS_STATUS_PENDING;
445 }
446 }
447
448 return NdisStatus;
449 }
450 #endif
451 }
452
453 \f
454 NDIS_STATUS NTAPI
455 ProSend(
456 IN NDIS_HANDLE MacBindingHandle,
457 IN PNDIS_PACKET Packet)
458 /*
459 * FUNCTION: Forwards a request to send a packet to an NDIS miniport
460 * ARGUMENTS:
461 * MacBindingHandle = Adapter binding handle
462 * Packet = Pointer to NDIS packet descriptor
463 * RETURNS:
464 * NDIS_STATUS_SUCCESS if the packet was successfully sent
465 * NDIS_STATUS_PENDING if the miniport was busy or a serialized miniport returned NDIS_STATUS_RESOURCES
466 */
467 {
468 PADAPTER_BINDING AdapterBinding;
469 PLOGICAL_ADAPTER Adapter;
470 PNDIS_BUFFER NdisBuffer;
471 PDMA_CONTEXT Context;
472 NDIS_STATUS NdisStatus;
473 UINT PacketLength;
474 KIRQL OldIrql;
475
476 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
477
478 ASSERT(MacBindingHandle);
479 AdapterBinding = GET_ADAPTER_BINDING(MacBindingHandle);
480
481 ASSERT(AdapterBinding);
482 Adapter = AdapterBinding->Adapter;
483
484 ASSERT(Adapter);
485
486 /* if the following is not true, KeRaiseIrql() below will break */
487 ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
488
489 /* XXX what is this crazy black magic? */
490 Packet->Reserved[1] = (ULONG_PTR)MacBindingHandle;
491
492 /*
493 * Test the packet to see if it is a MAC loopback.
494 *
495 * We may have to loop this packet if miniport cannot.
496 * If dest MAC address of packet == MAC address of adapter,
497 * this is a loopback frame.
498 */
499
500 if ((Adapter->NdisMiniportBlock.MacOptions & NDIS_MAC_OPTION_NO_LOOPBACK) &&
501 MiniAdapterHasAddress(Adapter, Packet))
502 {
503 #if WORKER_TEST
504 MiniQueueWorkItem(Adapter, NdisWorkItemSendLoopback, Packet, FALSE);
505 return NDIS_STATUS_PENDING;
506 #else
507 return ProIndicatePacket(Adapter, Packet);
508 #endif
509 } else {
510 if (Adapter->NdisMiniportBlock.ScatterGatherListSize != 0)
511 {
512 NDIS_DbgPrint(MAX_TRACE, ("Using Scatter/Gather DMA\n"));
513
514 NdisQueryPacket(Packet,
515 NULL,
516 NULL,
517 &NdisBuffer,
518 &PacketLength);
519
520 Context = ExAllocatePool(NonPagedPool, sizeof(DMA_CONTEXT));
521 if (!Context) {
522 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources\n"));
523 return NDIS_STATUS_RESOURCES;
524 }
525
526 Context->Adapter = Adapter;
527 Context->Packet = Packet;
528
529 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
530
531 KeFlushIoBuffers(NdisBuffer, FALSE, TRUE);
532
533 NdisStatus = Adapter->NdisMiniportBlock.SystemAdapterObject->DmaOperations->GetScatterGatherList(
534 Adapter->NdisMiniportBlock.SystemAdapterObject,
535 Adapter->NdisMiniportBlock.PhysicalDeviceObject,
536 NdisBuffer,
537 MmGetMdlVirtualAddress(NdisBuffer),
538 PacketLength,
539 ScatterGatherSendPacket,
540 Context,
541 TRUE);
542
543 KeLowerIrql(OldIrql);
544
545 if (!NT_SUCCESS(NdisStatus)) {
546 NDIS_DbgPrint(MIN_TRACE, ("GetScatterGatherList failed! (%x)\n", NdisStatus));
547 return NdisStatus;
548 }
549
550 return NDIS_STATUS_PENDING;
551 }
552
553
554 return proSendPacketToMiniport(Adapter, Packet);
555 }
556 }
557
558 \f
559 VOID NTAPI
560 ProSendPackets(
561 IN NDIS_HANDLE NdisBindingHandle,
562 IN PPNDIS_PACKET PacketArray,
563 IN UINT NumberOfPackets)
564 {
565 PADAPTER_BINDING AdapterBinding = NdisBindingHandle;
566 PLOGICAL_ADAPTER Adapter = AdapterBinding->Adapter;
567 KIRQL RaiseOldIrql;
568 NDIS_STATUS NdisStatus;
569 UINT i;
570
571 if(Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendPacketsHandler)
572 {
573 if(Adapter->NdisMiniportBlock.Flags & NDIS_ATTRIBUTE_DESERIALIZE)
574 {
575 (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendPacketsHandler)(
576 Adapter->NdisMiniportBlock.MiniportAdapterContext, PacketArray, NumberOfPackets);
577 }
578 else
579 {
580 /* SendPackets is called at DISPATCH_LEVEL for all serialized miniports */
581 KeRaiseIrql(DISPATCH_LEVEL, &RaiseOldIrql);
582 (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendPacketsHandler)(
583 Adapter->NdisMiniportBlock.MiniportAdapterContext, PacketArray, NumberOfPackets);
584 KeLowerIrql(RaiseOldIrql);
585 for (i = 0; i < NumberOfPackets; i++)
586 {
587 NdisStatus = NDIS_GET_PACKET_STATUS(PacketArray[i]);
588 if (NdisStatus != NDIS_STATUS_PENDING)
589 MiniSendComplete(Adapter, PacketArray[i], NdisStatus);
590 }
591 }
592 }
593 else
594 {
595 if(Adapter->NdisMiniportBlock.Flags & NDIS_ATTRIBUTE_DESERIALIZE)
596 {
597 for (i = 0; i < NumberOfPackets; i++)
598 {
599 NdisStatus = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendHandler)(
600 Adapter->NdisMiniportBlock.MiniportAdapterContext, PacketArray[i], PacketArray[i]->Private.Flags);
601 if (NdisStatus != NDIS_STATUS_PENDING)
602 MiniSendComplete(Adapter, PacketArray[i], NdisStatus);
603 }
604 }
605 else
606 {
607 /* Send is called at DISPATCH_LEVEL for all serialized miniports */
608 KeRaiseIrql(DISPATCH_LEVEL, &RaiseOldIrql);
609 for (i = 0; i < NumberOfPackets; i++)
610 {
611 NdisStatus = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendHandler)(
612 Adapter->NdisMiniportBlock.MiniportAdapterContext, PacketArray[i], PacketArray[i]->Private.Flags);
613 if (NdisStatus != NDIS_STATUS_PENDING)
614 MiniSendComplete(Adapter, PacketArray[i], NdisStatus);
615 }
616 KeLowerIrql(RaiseOldIrql);
617 }
618 }
619 }
620
621 \f
622 NDIS_STATUS NTAPI
623 ProTransferData(
624 IN NDIS_HANDLE MacBindingHandle,
625 IN NDIS_HANDLE MacReceiveContext,
626 IN UINT ByteOffset,
627 IN UINT BytesToTransfer,
628 IN OUT PNDIS_PACKET Packet,
629 OUT PUINT BytesTransferred)
630 /*
631 * FUNCTION: Forwards a request to copy received data into a protocol-supplied packet
632 * ARGUMENTS:
633 * MacBindingHandle = Adapter binding handle
634 * MacReceiveContext = MAC receive context
635 * ByteOffset = Offset in packet to place data
636 * BytesToTransfer = Number of bytes to copy into packet
637 * Packet = Pointer to NDIS packet descriptor
638 * BytesTransferred = Address of buffer to place number of bytes copied
639 */
640 {
641 PADAPTER_BINDING AdapterBinding = GET_ADAPTER_BINDING(MacBindingHandle);
642 PLOGICAL_ADAPTER Adapter = AdapterBinding->Adapter;
643 NDIS_STATUS Status;
644 KIRQL OldIrql;
645
646 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
647
648 /* FIXME: Interrupts must be disabled for adapter */
649 /* XXX sd - why is that true? */
650
651 if (Packet == Adapter->NdisMiniportBlock.IndicatedPacket[KeGetCurrentProcessorNumber()]) {
652 NDIS_DbgPrint(MAX_TRACE, ("LoopPacket\n"));
653 /* NDIS is responsible for looping this packet */
654 NdisCopyFromPacketToPacket(Packet,
655 ByteOffset,
656 BytesToTransfer,
657 Adapter->NdisMiniportBlock.IndicatedPacket[KeGetCurrentProcessorNumber()],
658 0,
659 BytesTransferred);
660 return NDIS_STATUS_SUCCESS;
661 }
662
663 ASSERT(Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.TransferDataHandler);
664
665 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
666
667 Status = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.TransferDataHandler)(
668 Packet,
669 BytesTransferred,
670 Adapter->NdisMiniportBlock.MiniportAdapterContext,
671 MacReceiveContext,
672 ByteOffset,
673 BytesToTransfer);
674
675 KeLowerIrql(OldIrql);
676
677 return Status;
678 }
679
680
681
682 /*
683 * @implemented
684 */
685 VOID
686 EXPORT
687 NdisCloseAdapter(
688 OUT PNDIS_STATUS Status,
689 IN NDIS_HANDLE NdisBindingHandle)
690 /*
691 * FUNCTION: Closes an adapter opened with NdisOpenAdapter
692 * ARGUMENTS:
693 * Status = Address of buffer for status information
694 * NdisBindingHandle = Handle returned by NdisOpenAdapter
695 */
696 {
697 PADAPTER_BINDING AdapterBinding = GET_ADAPTER_BINDING(NdisBindingHandle);
698
699 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
700
701 /* Remove from protocol's bound adapters list */
702 ExInterlockedRemoveEntryList(&AdapterBinding->ProtocolListEntry, &AdapterBinding->ProtocolBinding->Lock);
703
704 /* Remove protocol from adapter's bound protocols list */
705 ExInterlockedRemoveEntryList(&AdapterBinding->AdapterListEntry, &AdapterBinding->Adapter->NdisMiniportBlock.Lock);
706
707 ExFreePool(AdapterBinding);
708
709 *Status = NDIS_STATUS_SUCCESS;
710 }
711
712
713 /*
714 * @implemented
715 */
716 VOID
717 EXPORT
718 NdisDeregisterProtocol(
719 OUT PNDIS_STATUS Status,
720 IN NDIS_HANDLE NdisProtocolHandle)
721 /*
722 * FUNCTION: Releases the resources allocated by NdisRegisterProtocol
723 * ARGUMENTS:
724 * Status = Address of buffer for status information
725 * NdisProtocolHandle = Handle returned by NdisRegisterProtocol
726 */
727 {
728 PPROTOCOL_BINDING Protocol = GET_PROTOCOL_BINDING(NdisProtocolHandle);
729
730 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
731
732 /* FIXME: Make sure no adapter bindings exist */
733
734 /* Remove protocol from global list */
735 ExInterlockedRemoveEntryList(&Protocol->ListEntry, &ProtocolListLock);
736
737 ExFreePool(Protocol);
738
739 *Status = NDIS_STATUS_SUCCESS;
740 }
741
742
743 /*
744 * @implemented
745 */
746 VOID
747 EXPORT
748 NdisOpenAdapter(
749 OUT PNDIS_STATUS Status,
750 OUT PNDIS_STATUS OpenErrorStatus,
751 OUT PNDIS_HANDLE NdisBindingHandle,
752 OUT PUINT SelectedMediumIndex,
753 IN PNDIS_MEDIUM MediumArray,
754 IN UINT MediumArraySize,
755 IN NDIS_HANDLE NdisProtocolHandle,
756 IN NDIS_HANDLE ProtocolBindingContext,
757 IN PNDIS_STRING AdapterName,
758 IN UINT OpenOptions,
759 IN PSTRING AddressingInformation OPTIONAL)
760 /*
761 * FUNCTION: Opens an adapter for communication
762 * ARGUMENTS:
763 * Status = Address of buffer for status information
764 * OpenErrorStatus = Address of buffer for secondary error code
765 * NdisBindingHandle = Address of buffer for adapter binding handle
766 * SelectedMediumIndex = Address of buffer for selected medium
767 * MediumArray = Pointer to an array of NDIS_MEDIUMs called can support
768 * MediumArraySize = Number of elements in MediumArray
769 * NdisProtocolHandle = Handle returned by NdisRegisterProtocol
770 * ProtocolBindingContext = Pointer to caller suplied context area
771 * AdapterName = Pointer to buffer with name of adapter
772 * OpenOptions = Bitmask with flags passed to next-lower driver
773 * AddressingInformation = Optional pointer to buffer with NIC specific information
774 */
775 {
776 UINT i;
777 BOOLEAN Found;
778 PLOGICAL_ADAPTER Adapter;
779 PADAPTER_BINDING AdapterBinding;
780 PPROTOCOL_BINDING Protocol = GET_PROTOCOL_BINDING(NdisProtocolHandle);
781
782 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
783
784 if(!NdisProtocolHandle)
785 {
786 NDIS_DbgPrint(MIN_TRACE, ("NdisProtocolHandle is NULL\n"));
787 *OpenErrorStatus = *Status = NDIS_STATUS_FAILURE;
788 return;
789 }
790
791 Adapter = MiniLocateDevice(AdapterName);
792 if (!Adapter)
793 {
794 NDIS_DbgPrint(MIN_TRACE, ("Adapter not found.\n"));
795 *Status = NDIS_STATUS_ADAPTER_NOT_FOUND;
796 return;
797 }
798
799 /* Find the media type in the list provided by the protocol driver */
800 Found = FALSE;
801 for (i = 0; i < MediumArraySize; i++)
802 {
803 if (Adapter->NdisMiniportBlock.MediaType == MediumArray[i])
804 {
805 *SelectedMediumIndex = i;
806 Found = TRUE;
807 break;
808 }
809 }
810
811 if (!Found)
812 {
813 NDIS_DbgPrint(MIN_TRACE, ("Medium is not supported.\n"));
814 *Status = NDIS_STATUS_UNSUPPORTED_MEDIA;
815 return;
816 }
817
818 /* Now that we have confirmed that the adapter can be opened, create a binding */
819
820 AdapterBinding = ExAllocatePool(NonPagedPool, sizeof(ADAPTER_BINDING));
821 if (!AdapterBinding)
822 {
823 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
824 *Status = NDIS_STATUS_RESOURCES;
825 return;
826 }
827
828 RtlZeroMemory(AdapterBinding, sizeof(ADAPTER_BINDING));
829
830 AdapterBinding->ProtocolBinding = Protocol;
831 AdapterBinding->Adapter = Adapter;
832 AdapterBinding->NdisOpenBlock.ProtocolBindingContext = ProtocolBindingContext;
833
834 /* Set fields required by some NDIS macros */
835 AdapterBinding->NdisOpenBlock.BindingHandle = (NDIS_HANDLE)AdapterBinding;
836
837 /* Set handlers (some NDIS macros require these) */
838
839 AdapterBinding->NdisOpenBlock.RequestHandler = ProRequest;
840 AdapterBinding->NdisOpenBlock.ResetHandler = ProReset;
841 AdapterBinding->NdisOpenBlock.SendHandler = ProSend;
842 AdapterBinding->NdisOpenBlock.SendPacketsHandler = ProSendPackets;
843 AdapterBinding->NdisOpenBlock.TransferDataHandler = ProTransferData;
844
845 AdapterBinding->NdisOpenBlock.RequestCompleteHandler =
846 Protocol->Chars.RequestCompleteHandler;
847
848 /* Put on protocol's bound adapters list */
849 ExInterlockedInsertTailList(&Protocol->AdapterListHead, &AdapterBinding->ProtocolListEntry, &Protocol->Lock);
850
851 /* Put protocol on adapter's bound protocols list */
852 NDIS_DbgPrint(MAX_TRACE, ("acquiring miniport block lock\n"));
853 ExInterlockedInsertTailList(&Adapter->ProtocolListHead, &AdapterBinding->AdapterListEntry, &Adapter->NdisMiniportBlock.Lock);
854
855 *NdisBindingHandle = (NDIS_HANDLE)AdapterBinding;
856
857 *Status = NDIS_STATUS_SUCCESS;
858 }
859
860 VOID
861 NTAPI
862 ndisBindMiniportsToProtocol(OUT PNDIS_STATUS Status, IN PNDIS_PROTOCOL_CHARACTERISTICS ProtocolCharacteristics)
863 {
864 /*
865 * bind the protocol to all of its miniports
866 *
867 * open registry path
868 * get list of devices from Bind key
869 * call BindAdapterHandler for each
870 */
871 OBJECT_ATTRIBUTES ObjectAttributes;
872 UNICODE_STRING RegistryPath;
873 WCHAR *RegistryPathStr;
874 NTSTATUS NtStatus;
875 WCHAR *DataPtr;
876 HANDLE DriverKeyHandle = NULL;
877 PKEY_VALUE_PARTIAL_INFORMATION KeyInformation = NULL;
878
879 RegistryPathStr = ExAllocatePoolWithTag(PagedPool, sizeof(SERVICES_KEY) + ProtocolCharacteristics->Name.Length + sizeof(LINKAGE_KEY), NDIS_TAG + __LINE__);
880 if(!RegistryPathStr)
881 {
882 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
883 *Status = NDIS_STATUS_RESOURCES;
884 return;
885 }
886
887 wcscpy(RegistryPathStr, SERVICES_KEY);
888 wcsncat(RegistryPathStr, ((WCHAR *)ProtocolCharacteristics->Name.Buffer), ProtocolCharacteristics->Name.Length / sizeof(WCHAR));
889 RegistryPathStr[wcslen(SERVICES_KEY)+ProtocolCharacteristics->Name.Length/sizeof(WCHAR)] = 0;
890 wcscat(RegistryPathStr, LINKAGE_KEY);
891
892 RtlInitUnicodeString(&RegistryPath, RegistryPathStr);
893 NDIS_DbgPrint(MAX_TRACE, ("Opening configuration key: %wZ\n", &RegistryPath));
894
895 InitializeObjectAttributes(&ObjectAttributes, &RegistryPath, OBJ_CASE_INSENSITIVE, NULL, NULL);
896 NtStatus = ZwOpenKey(&DriverKeyHandle, KEY_READ, &ObjectAttributes);
897
898 ExFreePool(RegistryPathStr);
899
900 if(!NT_SUCCESS(NtStatus))
901 {
902 NDIS_DbgPrint(MIN_TRACE, ("Unable to open protocol configuration\n"));
903 *Status = NDIS_STATUS_FAILURE;
904 return;
905 }
906
907 NDIS_DbgPrint(MAX_TRACE, ("Successfully opened the registry configuration\n"));
908
909 {
910 UNICODE_STRING ValueName;
911 ULONG ResultLength;
912
913 RtlInitUnicodeString(&ValueName, L"Bind");
914
915 NtStatus = ZwQueryValueKey(DriverKeyHandle, &ValueName, KeyValuePartialInformation, NULL, 0, &ResultLength);
916 if(NtStatus != STATUS_BUFFER_OVERFLOW && NtStatus != STATUS_BUFFER_TOO_SMALL && NtStatus != STATUS_SUCCESS)
917 {
918 NDIS_DbgPrint(MIN_TRACE, ("Unable to query the Bind value for size\n"));
919 ZwClose(DriverKeyHandle);
920 *Status = NDIS_STATUS_FAILURE;
921 return;
922 }
923
924 KeyInformation = ExAllocatePoolWithTag(PagedPool, sizeof(KEY_VALUE_PARTIAL_INFORMATION) + ResultLength, NDIS_TAG + __LINE__);
925 if(!KeyInformation)
926 {
927 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
928 ZwClose(DriverKeyHandle);
929 *Status = NDIS_STATUS_FAILURE;
930 return;
931 }
932
933 NtStatus = ZwQueryValueKey(DriverKeyHandle, &ValueName, KeyValuePartialInformation, KeyInformation,
934 sizeof(KEY_VALUE_PARTIAL_INFORMATION) + ResultLength, &ResultLength);
935
936 ZwClose(DriverKeyHandle);
937
938 if(!NT_SUCCESS(NtStatus))
939 {
940 NDIS_DbgPrint(MIN_TRACE, ("Unable to query the Bind value\n"));
941 ExFreePool(KeyInformation);
942 *Status = NDIS_STATUS_FAILURE;
943 return;
944 }
945 }
946
947 for (DataPtr = (WCHAR *)KeyInformation->Data;
948 *DataPtr != 0;
949 DataPtr += wcslen(DataPtr) + 1)
950 {
951 /* BindContext is for tracking pending binding operations */
952 VOID *BindContext = 0;
953 NDIS_STRING DeviceName;
954 NDIS_STRING RegistryPath;
955 WCHAR *RegistryPathStr = NULL;
956 ULONG PathLength = 0;
957
958 RtlInitUnicodeString(&DeviceName, DataPtr); /* we know this is 0-term */
959
960 /*
961 * RegistryPath should be:
962 * \Registry\Machine\System\CurrentControlSet\Services\Nic1\Parameters\Tcpip
963 *
964 * This is constructed as follows:
965 * SERVICES_KEY + extracted device name + Protocol name from characteristics
966 */
967
968 PathLength = sizeof(SERVICES_KEY) + /* \Registry\Machine\System\CurrentControlSet\Services\ */
969 wcslen( DataPtr + 8 ) * sizeof(WCHAR) + /* Adapter1 (extracted from \Device\Adapter1) */
970 sizeof(PARAMETERS_KEY) + /* \Parameters\ */
971 ProtocolCharacteristics->Name.Length + sizeof(WCHAR); /* Tcpip */
972
973 RegistryPathStr = ExAllocatePool(PagedPool, PathLength);
974 if(!RegistryPathStr)
975 {
976 NDIS_DbgPrint(MIN_TRACE, ("insufficient resources.\n"));
977 ExFreePool(KeyInformation);
978 *Status = NDIS_STATUS_RESOURCES;
979 return;
980 }
981
982 wcscpy(RegistryPathStr, SERVICES_KEY);
983 wcscat(RegistryPathStr, DataPtr + 8 );
984 wcscat(RegistryPathStr, PARAMETERS_KEY);
985 wcsncat(RegistryPathStr, ProtocolCharacteristics->Name.Buffer, ProtocolCharacteristics->Name.Length / sizeof(WCHAR) );
986
987 RegistryPathStr[PathLength/sizeof(WCHAR) - 1] = 0;
988
989 RtlInitUnicodeString(&RegistryPath, RegistryPathStr);
990
991 NDIS_DbgPrint(MAX_TRACE, ("Calling protocol's BindAdapter handler with DeviceName %wZ and RegistryPath %wZ\n",
992 &DeviceName, &RegistryPath));
993
994 {
995 BIND_HANDLER BindHandler = ProtocolCharacteristics->BindAdapterHandler;
996 if(BindHandler)
997 BindHandler(Status, BindContext, &DeviceName, &RegistryPath, 0);
998 else
999 NDIS_DbgPrint(MIN_TRACE, ("No protocol bind handler specified\n"));
1000 }
1001 }
1002
1003 *Status = NDIS_STATUS_SUCCESS;
1004 ExFreePool(KeyInformation);
1005 }
1006
1007 /*
1008 * @implemented
1009 */
1010 VOID
1011 EXPORT
1012 NdisRegisterProtocol(
1013 OUT PNDIS_STATUS Status,
1014 OUT PNDIS_HANDLE NdisProtocolHandle,
1015 IN PNDIS_PROTOCOL_CHARACTERISTICS ProtocolCharacteristics,
1016 IN UINT CharacteristicsLength)
1017 /*
1018 * FUNCTION: Registers an NDIS driver's ProtocolXxx entry points
1019 * ARGUMENTS:
1020 * Status = Address of buffer for status information
1021 * NdisProtocolHandle = Address of buffer for handle used to identify the driver
1022 * ProtocolCharacteristics = Pointer to NDIS_PROTOCOL_CHARACTERISTICS structure
1023 * CharacteristicsLength = Size of structure which ProtocolCharacteristics targets
1024 * NOTES:
1025 * - you *must* set NdisProtocolHandle before doing anything that could wind up
1026 * getting BindAdapterHandler, as it will probably call OpenAdapter with this handle
1027 * - the above implies that the initialization of the protocol block must be complete
1028 * by then
1029 * TODO:
1030 * - break this function up - probably do a 'ndisRefreshProtocolBindings' function
1031 * - make this thing able to handle >1 protocol
1032 */
1033 {
1034 PPROTOCOL_BINDING Protocol;
1035 NTSTATUS NtStatus;
1036 UINT MinSize;
1037
1038 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
1039
1040 *NdisProtocolHandle = NULL;
1041
1042 /* first validate the PROTOCOL_CHARACTERISTICS */
1043 switch (ProtocolCharacteristics->MajorNdisVersion)
1044 {
1045 case 0x03:
1046 /* we don't really want to support ndis3 drivers - so we complain for now */
1047 NDIS_DbgPrint(MID_TRACE, ("NDIS 3 protocol attempting to register\n"));
1048 MinSize = sizeof(NDIS30_PROTOCOL_CHARACTERISTICS);
1049 break;
1050
1051 case 0x04:
1052 MinSize = sizeof(NDIS40_PROTOCOL_CHARACTERISTICS);
1053 break;
1054
1055 case 0x05:
1056 MinSize = sizeof(NDIS50_PROTOCOL_CHARACTERISTICS);
1057 break;
1058
1059 default:
1060 *Status = NDIS_STATUS_BAD_VERSION;
1061 NDIS_DbgPrint(MIN_TRACE, ("Incorrect characteristics size\n"));
1062 return;
1063 }
1064
1065 if (CharacteristicsLength < MinSize)
1066 {
1067 NDIS_DbgPrint(MIN_TRACE, ("Bad protocol characteristics.\n"));
1068 *Status = NDIS_STATUS_BAD_CHARACTERISTICS;
1069 return;
1070 }
1071
1072 /* set up the protocol block */
1073 Protocol = ExAllocatePool(NonPagedPool, sizeof(PROTOCOL_BINDING));
1074 if (!Protocol)
1075 {
1076 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
1077 *Status = NDIS_STATUS_RESOURCES;
1078 return;
1079 }
1080
1081 RtlZeroMemory(Protocol, sizeof(PROTOCOL_BINDING));
1082 RtlCopyMemory(&Protocol->Chars, ProtocolCharacteristics, MinSize);
1083
1084 NtStatus = RtlUpcaseUnicodeString(&Protocol->Chars.Name, &ProtocolCharacteristics->Name, TRUE);
1085 if (!NT_SUCCESS(NtStatus))
1086 {
1087 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
1088 ExFreePool(Protocol);
1089 *Status = NDIS_STATUS_RESOURCES;
1090 return;
1091 }
1092
1093 KeInitializeSpinLock(&Protocol->Lock);
1094
1095 InitializeListHead(&Protocol->AdapterListHead);
1096
1097 /* We must set this before the call to ndisBindMiniportsToProtocol because the protocol's
1098 * BindAdapter handler might need it */
1099
1100 *NdisProtocolHandle = Protocol;
1101
1102 ndisBindMiniportsToProtocol(Status, &Protocol->Chars);
1103
1104 if (*Status == NDIS_STATUS_SUCCESS) {
1105 ExInterlockedInsertTailList(&ProtocolListHead, &Protocol->ListEntry, &ProtocolListLock);
1106 } else {
1107 NDIS_DbgPrint(MIN_TRACE, ("Binding failed (%x)\n", *Status));
1108 ExFreePool(Protocol);
1109 *NdisProtocolHandle = NULL;
1110 }
1111 }
1112
1113 \f
1114 /*
1115 * @implemented
1116 */
1117 VOID
1118 EXPORT
1119 NdisRequest(
1120 OUT PNDIS_STATUS Status,
1121 IN NDIS_HANDLE NdisBindingHandle,
1122 IN PNDIS_REQUEST NdisRequest)
1123 /*
1124 * FUNCTION: Forwards a request to an NDIS driver
1125 * ARGUMENTS:
1126 * Status = Address of buffer for status information
1127 * NdisBindingHandle = Adapter binding handle
1128 * NdisRequest = Pointer to request to perform
1129 */
1130 {
1131 *Status = ProRequest(NdisBindingHandle, NdisRequest);
1132 }
1133
1134 \f
1135 /*
1136 * @implemented
1137 */
1138 VOID
1139 EXPORT
1140 NdisReset(
1141 OUT PNDIS_STATUS Status,
1142 IN NDIS_HANDLE NdisBindingHandle)
1143 {
1144 *Status = ProReset(NdisBindingHandle);
1145 }
1146
1147 \f
1148 /*
1149 * @implemented
1150 */
1151 #undef NdisSend
1152 VOID
1153 EXPORT
1154 NdisSend(
1155 OUT PNDIS_STATUS Status,
1156 IN NDIS_HANDLE NdisBindingHandle,
1157 IN PNDIS_PACKET Packet)
1158 /*
1159 * FUNCTION: Forwards a request to send a packet
1160 * ARGUMENTS:
1161 * Status = Address of buffer for status information
1162 * NdisBindingHandle = Adapter binding handle
1163 * Packet = Pointer to NDIS packet descriptor
1164 */
1165 {
1166 *Status = ProSend(NdisBindingHandle, Packet);
1167 }
1168
1169 \f
1170 /*
1171 * @implemented
1172 */
1173 #undef NdisSendPackets
1174 VOID
1175 EXPORT
1176 NdisSendPackets(
1177 IN NDIS_HANDLE NdisBindingHandle,
1178 IN PPNDIS_PACKET PacketArray,
1179 IN UINT NumberOfPackets)
1180 {
1181 ProSendPackets(NdisBindingHandle, PacketArray, NumberOfPackets);
1182 }
1183
1184 \f
1185 /*
1186 * @implemented
1187 */
1188 #undef NdisTransferData
1189 VOID
1190 EXPORT
1191 NdisTransferData(
1192 OUT PNDIS_STATUS Status,
1193 IN NDIS_HANDLE NdisBindingHandle,
1194 IN NDIS_HANDLE MacReceiveContext,
1195 IN UINT ByteOffset,
1196 IN UINT BytesToTransfer,
1197 IN OUT PNDIS_PACKET Packet,
1198 OUT PUINT BytesTransferred)
1199 /*
1200 * FUNCTION: Forwards a request to copy received data into a protocol-supplied packet
1201 * ARGUMENTS:
1202 * Status = Address of buffer for status information
1203 * NdisBindingHandle = Adapter binding handle
1204 * MacReceiveContext = MAC receive context
1205 * ByteOffset = Offset in packet to place data
1206 * BytesToTransfer = Number of bytes to copy into packet
1207 * Packet = Pointer to NDIS packet descriptor
1208 * BytesTransferred = Address of buffer to place number of bytes copied
1209 */
1210 {
1211 *Status = ProTransferData(NdisBindingHandle,
1212 MacReceiveContext,
1213 ByteOffset,
1214 BytesToTransfer,
1215 Packet,
1216 BytesTransferred);
1217 }
1218
1219 /*
1220 * @implemented
1221 */
1222 VOID
1223 NTAPI
1224 NdisReEnumerateProtocolBindings(IN NDIS_HANDLE NdisProtocolHandle)
1225 {
1226 PPROTOCOL_BINDING Protocol = NdisProtocolHandle;
1227 NDIS_STATUS NdisStatus;
1228
1229 ndisBindMiniportsToProtocol(&NdisStatus, &Protocol->Chars);
1230 }
1231
1232
1233 /*
1234 * @implemented
1235 */
1236 VOID
1237 EXPORT
1238 NdisGetDriverHandle(
1239 IN PNDIS_HANDLE NdisBindingHandle,
1240 OUT PNDIS_HANDLE NdisDriverHandle)
1241 /*
1242 * FUNCTION:
1243 * ARGUMENTS:
1244 * NOTES:
1245 * NDIS 5.0
1246 */
1247 {
1248 PADAPTER_BINDING Binding = (PADAPTER_BINDING)NdisBindingHandle;
1249
1250 if (!Binding)
1251 {
1252 NDIS_DbgPrint(MIN_TRACE, ("Bad binding handle\n"));
1253 *NdisDriverHandle = NULL;
1254 return;
1255 }
1256
1257 *NdisDriverHandle = Binding->Adapter->NdisMiniportBlock.DriverHandle;
1258 }
1259
1260 /* EOF */