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