[NDIS]
[reactos.git] / drivers / network / ndis / ndis / miniport.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS NDIS library
4 * FILE: ndis/miniport.c
5 * PURPOSE: Routines used by NDIS miniport drivers
6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
7 * Vizzini (vizzini@plasmic.com)
8 * REVISIONS:
9 * CSH 01/08-2000 Created
10 * 20 Aug 2003 vizzini - DMA support
11 * 3 Oct 2003 vizzini - SendPackets support
12 */
13
14 #include "ndissys.h"
15 #include "efilter.h"
16
17 #include <buffer.h>
18
19 /*
20 * Define to 1 to get a debugger breakpoint at the end of NdisInitializeWrapper
21 * for each new miniport starting up
22 */
23 #define BREAK_ON_MINIPORT_INIT 0
24
25 /*
26 * This has to be big enough to hold the results of querying the Route value
27 * from the Linkage key. Please re-code me to determine this dynamically.
28 */
29 #define ROUTE_DATA_SIZE 256
30
31 /* Number of media we know */
32 #define MEDIA_ARRAY_SIZE 15
33
34 static NDIS_MEDIUM MediaArray[MEDIA_ARRAY_SIZE] =
35 {
36 NdisMedium802_3,
37 NdisMedium802_5,
38 NdisMediumFddi,
39 NdisMediumWan,
40 NdisMediumLocalTalk,
41 NdisMediumDix,
42 NdisMediumArcnetRaw,
43 NdisMediumArcnet878_2,
44 NdisMediumAtm,
45 NdisMediumWirelessWan,
46 NdisMediumIrda,
47 NdisMediumBpc,
48 NdisMediumCoWan,
49 NdisMedium1394,
50 NdisMediumMax
51 };
52
53 /* global list and lock of Miniports NDIS has registered */
54 LIST_ENTRY MiniportListHead;
55 KSPIN_LOCK MiniportListLock;
56
57 /* global list and lock of adapters NDIS has registered */
58 LIST_ENTRY AdapterListHead;
59 KSPIN_LOCK AdapterListLock;
60
61 VOID
62 MiniDisplayPacket(
63 PNDIS_PACKET Packet)
64 {
65 #if DBG
66 ULONG i, Length;
67 UCHAR Buffer[64];
68 if ((DebugTraceLevel & DEBUG_PACKET) > 0) {
69 Length = CopyPacketToBuffer(
70 Buffer,
71 Packet,
72 0,
73 64);
74
75 DbgPrint("*** PACKET START ***");
76
77 for (i = 0; i < Length; i++) {
78 if (i % 12 == 0)
79 DbgPrint("\n%04X ", i);
80 DbgPrint("%02X ", Buffer[i]);
81 }
82
83 DbgPrint("*** PACKET STOP ***\n");
84 }
85 #endif /* DBG */
86 }
87
88 VOID
89 MiniDisplayPacket2(
90 PVOID HeaderBuffer,
91 UINT HeaderBufferSize,
92 PVOID LookaheadBuffer,
93 UINT LookaheadBufferSize)
94 {
95 #if DBG
96 if ((DebugTraceLevel & DEBUG_PACKET) > 0) {
97 ULONG i, Length;
98 PUCHAR p;
99
100 DbgPrint("*** RECEIVE PACKET START ***\n");
101 DbgPrint("HEADER:");
102 p = HeaderBuffer;
103 for (i = 0; i < HeaderBufferSize; i++) {
104 if (i % 16 == 0)
105 DbgPrint("\n%04X ", i);
106 DbgPrint("%02X ", *p++);
107 }
108
109 DbgPrint("\nFRAME:");
110
111 p = LookaheadBuffer;
112 Length = (LookaheadBufferSize < 64)? LookaheadBufferSize : 64;
113 for (i = 0; i < Length; i++) {
114 if (i % 16 == 0)
115 DbgPrint("\n%04X ", i);
116 DbgPrint("%02X ", *p++);
117 }
118
119 DbgPrint("\n*** RECEIVE PACKET STOP ***\n");
120 }
121 #endif /* DBG */
122 }
123
124 \f
125 VOID
126 MiniIndicateData(
127 PLOGICAL_ADAPTER Adapter,
128 NDIS_HANDLE MacReceiveContext,
129 PVOID HeaderBuffer,
130 UINT HeaderBufferSize,
131 PVOID LookaheadBuffer,
132 UINT LookaheadBufferSize,
133 UINT PacketSize)
134 /*
135 * FUNCTION: Indicate received data to bound protocols
136 * ARGUMENTS:
137 * Adapter = Pointer to logical adapter
138 * MacReceiveContext = MAC receive context handle
139 * HeaderBuffer = Pointer to header buffer
140 * HeaderBufferSize = Size of header buffer
141 * LookaheadBuffer = Pointer to lookahead buffer
142 * LookaheadBufferSize = Size of lookahead buffer
143 * PacketSize = Total size of received packet
144 */
145 {
146 KIRQL OldIrql;
147 PLIST_ENTRY CurrentEntry;
148 PADAPTER_BINDING AdapterBinding;
149
150 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called. Adapter (0x%X) HeaderBuffer (0x%X) "
151 "HeaderBufferSize (0x%X) LookaheadBuffer (0x%X) LookaheadBufferSize (0x%X).\n",
152 Adapter, HeaderBuffer, HeaderBufferSize, LookaheadBuffer, LookaheadBufferSize));
153
154 MiniDisplayPacket2(HeaderBuffer, HeaderBufferSize, LookaheadBuffer, LookaheadBufferSize);
155
156 NDIS_DbgPrint(MAX_TRACE, ("acquiring miniport block lock\n"));
157 KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
158 {
159 CurrentEntry = Adapter->ProtocolListHead.Flink;
160 NDIS_DbgPrint(DEBUG_MINIPORT, ("CurrentEntry = %x\n", CurrentEntry));
161
162 if (CurrentEntry == &Adapter->ProtocolListHead)
163 {
164 NDIS_DbgPrint(MIN_TRACE, ("WARNING: No upper protocol layer.\n"));
165 }
166
167 while (CurrentEntry != &Adapter->ProtocolListHead)
168 {
169 AdapterBinding = CONTAINING_RECORD(CurrentEntry, ADAPTER_BINDING, AdapterListEntry);
170 NDIS_DbgPrint(DEBUG_MINIPORT, ("AdapterBinding = %x\n", AdapterBinding));
171
172 NDIS_DbgPrint
173 (MID_TRACE,
174 ("XXX (%x) %x %x %x %x %x %x %x XXX\n",
175 *AdapterBinding->ProtocolBinding->Chars.ReceiveHandler,
176 AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
177 MacReceiveContext,
178 HeaderBuffer,
179 HeaderBufferSize,
180 LookaheadBuffer,
181 LookaheadBufferSize,
182 PacketSize));
183
184 /* call the receive handler */
185 (*AdapterBinding->ProtocolBinding->Chars.ReceiveHandler)(
186 AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
187 MacReceiveContext,
188 HeaderBuffer,
189 HeaderBufferSize,
190 LookaheadBuffer,
191 LookaheadBufferSize,
192 PacketSize);
193
194 CurrentEntry = CurrentEntry->Flink;
195 }
196 }
197 KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
198
199 NDIS_DbgPrint(MAX_TRACE, ("Leaving.\n"));
200 }
201
202 \f
203 VOID NTAPI
204 MiniIndicateReceivePacket(
205 IN NDIS_HANDLE MiniportAdapterHandle,
206 IN PPNDIS_PACKET PacketArray,
207 IN UINT NumberOfPackets)
208 /*
209 * FUNCTION: receives miniport packet array indications
210 * ARGUMENTS:
211 * MiniportAdapterHandle: Miniport handle for the adapter
212 * PacketArray: pointer to a list of packet pointers to indicate
213 * NumberOfPackets: number of packets to indicate
214 *
215 */
216 {
217 PLOGICAL_ADAPTER Adapter = MiniportAdapterHandle;
218 PLIST_ENTRY CurrentEntry;
219 PADAPTER_BINDING AdapterBinding;
220 KIRQL OldIrql;
221 UINT i;
222
223 KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
224
225 CurrentEntry = Adapter->ProtocolListHead.Flink;
226
227 while (CurrentEntry != &Adapter->ProtocolListHead)
228 {
229 AdapterBinding = CONTAINING_RECORD(CurrentEntry, ADAPTER_BINDING, AdapterListEntry);
230
231 for (i = 0; i < NumberOfPackets; i++)
232 {
233 if (AdapterBinding->ProtocolBinding->Chars.ReceivePacketHandler &&
234 NDIS_GET_PACKET_STATUS(PacketArray[i]) != NDIS_STATUS_RESOURCES)
235 {
236 (*AdapterBinding->ProtocolBinding->Chars.ReceivePacketHandler)(
237 AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
238 PacketArray[i]);
239 }
240 else
241 {
242 UINT FirstBufferLength, TotalBufferLength, LookAheadSize, HeaderSize;
243 PNDIS_BUFFER NdisBuffer;
244 PVOID NdisBufferVA, LookAheadBuffer;
245 NDIS_STATUS NdisStatus;
246
247
248 NdisGetFirstBufferFromPacket(PacketArray[i],
249 &NdisBuffer,
250 &NdisBufferVA,
251 &FirstBufferLength,
252 &TotalBufferLength);
253
254 HeaderSize = NDIS_GET_PACKET_HEADER_SIZE(PacketArray[i]);
255
256 if (Adapter->NdisMiniportBlock.CurrentLookahead < (TotalBufferLength - HeaderSize))
257 {
258 LookAheadSize = Adapter->NdisMiniportBlock.CurrentLookahead;
259 }
260 else
261 {
262 LookAheadSize = TotalBufferLength - HeaderSize;
263 }
264
265
266 LookAheadBuffer = ExAllocatePool(NonPagedPool, LookAheadSize);
267 if (!LookAheadBuffer)
268 {
269 NDIS_DbgPrint(MIN_TRACE, ("Failed to allocate lookahead buffer!\n"));
270 KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
271 return;
272 }
273
274 CopyBufferChainToBuffer(LookAheadBuffer,
275 NdisBuffer,
276 HeaderSize,
277 LookAheadSize);
278
279 NdisStatus = (*AdapterBinding->ProtocolBinding->Chars.ReceiveHandler)(
280 AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
281 AdapterBinding->NdisOpenBlock.MacHandle,
282 NdisBufferVA,
283 HeaderSize,
284 LookAheadBuffer,
285 LookAheadSize,
286 TotalBufferLength - HeaderSize);
287
288 NDIS_SET_PACKET_STATUS(PacketArray[i], NdisStatus);
289
290 ExFreePool(LookAheadBuffer);
291 }
292 }
293
294 CurrentEntry = CurrentEntry->Flink;
295 }
296
297 KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
298 }
299
300 \f
301 VOID NTAPI
302 MiniResetComplete(
303 IN NDIS_HANDLE MiniportAdapterHandle,
304 IN NDIS_STATUS Status,
305 IN BOOLEAN AddressingReset)
306 {
307 PLOGICAL_ADAPTER Adapter = MiniportAdapterHandle;
308 PLIST_ENTRY CurrentEntry;
309 PADAPTER_BINDING AdapterBinding;
310 KIRQL OldIrql;
311
312 MiniEndRequest(Adapter, NdisWorkItemResetRequested);
313
314 if (AddressingReset)
315 MiniDoAddressingReset(Adapter);
316
317 NdisMIndicateStatus(Adapter, NDIS_STATUS_RESET_END, NULL, 0);
318 NdisMIndicateStatusComplete(Adapter);
319
320 KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
321
322 CurrentEntry = Adapter->ProtocolListHead.Flink;
323
324 while (CurrentEntry != &Adapter->ProtocolListHead)
325 {
326 AdapterBinding = CONTAINING_RECORD(CurrentEntry, ADAPTER_BINDING, AdapterListEntry);
327
328 (*AdapterBinding->ProtocolBinding->Chars.ResetCompleteHandler)(
329 AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
330 Status);
331
332 CurrentEntry = CurrentEntry->Flink;
333 }
334
335 KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
336 }
337
338 VOID NTAPI
339 MiniRequestComplete(
340 IN NDIS_HANDLE MiniportAdapterHandle,
341 IN NDIS_STATUS Status)
342 {
343 PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)MiniportAdapterHandle;
344 PNDIS_REQUEST Request;
345 PNDIS_REQUEST_MAC_BLOCK MacBlock;
346 KIRQL OldIrql;
347
348 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
349
350 KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
351 Request = Adapter->NdisMiniportBlock.PendingRequest;
352 KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
353
354 MiniEndRequest(Adapter, NdisWorkItemRequest);
355
356 MacBlock = (PNDIS_REQUEST_MAC_BLOCK)Request->MacReserved;
357
358 if( MacBlock->Binding->RequestCompleteHandler ) {
359 (*MacBlock->Binding->RequestCompleteHandler)(
360 MacBlock->Binding->ProtocolBindingContext,
361 Request,
362 Status);
363 }
364 }
365
366 VOID NTAPI
367 MiniIndicateComplete(
368 IN NDIS_HANDLE MiniportAdapterHandle,
369 IN PNDIS_PACKET Packet,
370 IN NDIS_STATUS Status)
371 {
372 PADAPTER_BINDING AdapterBinding = (PADAPTER_BINDING)Packet->Reserved[1];
373
374 MiniEndRequest(MiniportAdapterHandle, NdisWorkItemSendLoopback);
375
376 (*AdapterBinding->ProtocolBinding->Chars.SendCompleteHandler)(
377 AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
378 Packet,
379 Status);
380 }
381
382 VOID NTAPI
383 MiniSendComplete(
384 IN NDIS_HANDLE MiniportAdapterHandle,
385 IN PNDIS_PACKET Packet,
386 IN NDIS_STATUS Status)
387 /*
388 * FUNCTION: Forwards a message to the initiating protocol saying
389 * that a packet was handled
390 * ARGUMENTS:
391 * NdisAdapterHandle = Handle input to MiniportInitialize
392 * Packet = Pointer to NDIS packet that was sent
393 * Status = Status of send operation
394 */
395 {
396 PLOGICAL_ADAPTER Adapter = MiniportAdapterHandle;
397 PADAPTER_BINDING AdapterBinding;
398 KIRQL OldIrql;
399 PSCATTER_GATHER_LIST SGList;
400
401 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
402
403 AdapterBinding = (PADAPTER_BINDING)Packet->Reserved[1];
404
405 if (Adapter->NdisMiniportBlock.ScatterGatherListSize != 0)
406 {
407 NDIS_DbgPrint(MAX_TRACE, ("Freeing Scatter/Gather list\n"));
408
409 SGList = NDIS_PER_PACKET_INFO_FROM_PACKET(Packet,
410 ScatterGatherListPacketInfo);
411
412 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
413
414 Adapter->NdisMiniportBlock.SystemAdapterObject->
415 DmaOperations->PutScatterGatherList(
416 Adapter->NdisMiniportBlock.SystemAdapterObject,
417 SGList,
418 TRUE);
419
420 KeLowerIrql(OldIrql);
421
422 NDIS_PER_PACKET_INFO_FROM_PACKET(Packet,
423 ScatterGatherListPacketInfo) = NULL;
424 }
425
426 MiniEndRequest(Adapter, NdisWorkItemSend);
427
428 (*AdapterBinding->ProtocolBinding->Chars.SendCompleteHandler)(
429 AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
430 Packet,
431 Status);
432 }
433
434 NDIS_STATUS
435 SignalQueue(PLOGICAL_ADAPTER Adapter)
436 {
437 PIO_WORKITEM WorkItem = IoAllocateWorkItem(Adapter->NdisMiniportBlock.DeviceObject);
438
439 ASSERT(WorkItem);
440 if (!WorkItem) return NDIS_STATUS_RESOURCES;
441
442 IoQueueWorkItem(WorkItem,
443 MiniportWorker,
444 DelayedWorkQueue,
445 WorkItem);
446
447 return NDIS_STATUS_SUCCESS;
448 }
449
450 VOID NTAPI
451 MiniSendResourcesAvailable(
452 IN NDIS_HANDLE MiniportAdapterHandle)
453 {
454 SignalQueue(MiniportAdapterHandle);
455 }
456
457 VOID NTAPI
458 MiniTransferDataComplete(
459 IN NDIS_HANDLE MiniportAdapterHandle,
460 IN PNDIS_PACKET Packet,
461 IN NDIS_STATUS Status,
462 IN UINT BytesTransferred)
463 {
464 PADAPTER_BINDING AdapterBinding;
465
466 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
467
468 AdapterBinding = (PADAPTER_BINDING)Packet->Reserved[1];
469
470 (*AdapterBinding->ProtocolBinding->Chars.TransferDataCompleteHandler)(
471 AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
472 Packet,
473 Status,
474 BytesTransferred);
475 }
476
477 \f
478 BOOLEAN
479 MiniAdapterHasAddress(
480 PLOGICAL_ADAPTER Adapter,
481 PNDIS_PACKET Packet)
482 /*
483 * FUNCTION: Determines whether a packet has the same destination address as an adapter
484 * ARGUMENTS:
485 * Adapter = Pointer to logical adapter object
486 * Packet = Pointer to NDIS packet
487 * RETURNS:
488 * TRUE if the destination address is that of the adapter, FALSE if not
489 */
490 {
491 UINT Length;
492 PUCHAR Start1;
493 PUCHAR Start2;
494 PNDIS_BUFFER NdisBuffer;
495 UINT BufferLength;
496
497 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
498
499 #if DBG
500 if(!Adapter)
501 {
502 NDIS_DbgPrint(MIN_TRACE, ("Adapter object was null\n"));
503 return FALSE;
504 }
505
506 if(!Packet)
507 {
508 NDIS_DbgPrint(MIN_TRACE, ("Packet was null\n"));
509 return FALSE;
510 }
511 #endif
512
513 NdisQueryPacket(Packet, NULL, NULL, &NdisBuffer, NULL);
514
515 if (!NdisBuffer)
516 {
517 NDIS_DbgPrint(MIN_TRACE, ("Packet contains no buffers.\n"));
518 return FALSE;
519 }
520
521 NdisQueryBuffer(NdisBuffer, (PVOID)&Start2, &BufferLength);
522
523 /* FIXME: Should handle fragmented packets */
524
525 switch (Adapter->NdisMiniportBlock.MediaType)
526 {
527 case NdisMedium802_3:
528 Length = ETH_LENGTH_OF_ADDRESS;
529 /* Destination address is the first field */
530 break;
531
532 default:
533 NDIS_DbgPrint(MIN_TRACE, ("Adapter has unsupported media type (0x%X).\n", Adapter->NdisMiniportBlock.MediaType));
534 return FALSE;
535 }
536
537 if (BufferLength < Length)
538 {
539 NDIS_DbgPrint(MIN_TRACE, ("Buffer is too small.\n"));
540 return FALSE;
541 }
542
543 Start1 = (PUCHAR)&Adapter->Address;
544 NDIS_DbgPrint(MAX_TRACE, ("packet address: %x:%x:%x:%x:%x:%x adapter address: %x:%x:%x:%x:%x:%x\n",
545 *((char *)Start1), *(((char *)Start1)+1), *(((char *)Start1)+2), *(((char *)Start1)+3), *(((char *)Start1)+4), *(((char *)Start1)+5),
546 *((char *)Start2), *(((char *)Start2)+1), *(((char *)Start2)+2), *(((char *)Start2)+3), *(((char *)Start2)+4), *(((char *)Start2)+5))
547 );
548
549 return (RtlCompareMemory((PVOID)Start1, (PVOID)Start2, Length) == Length);
550 }
551
552 \f
553 PLOGICAL_ADAPTER
554 MiniLocateDevice(
555 PNDIS_STRING AdapterName)
556 /*
557 * FUNCTION: Finds an adapter object by name
558 * ARGUMENTS:
559 * AdapterName = Pointer to name of adapter
560 * RETURNS:
561 * Pointer to logical adapter object, or NULL if none was found.
562 * If found, the adapter is referenced for the caller. The caller
563 * is responsible for dereferencing after use
564 */
565 {
566 KIRQL OldIrql;
567 PLIST_ENTRY CurrentEntry;
568 PLOGICAL_ADAPTER Adapter = 0;
569
570 ASSERT(AdapterName);
571
572 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
573
574 KeAcquireSpinLock(&AdapterListLock, &OldIrql);
575 {
576 CurrentEntry = AdapterListHead.Flink;
577
578 while (CurrentEntry != &AdapterListHead)
579 {
580 Adapter = CONTAINING_RECORD(CurrentEntry, LOGICAL_ADAPTER, ListEntry);
581
582 ASSERT(Adapter);
583
584 NDIS_DbgPrint(DEBUG_MINIPORT, ("Examining adapter 0x%lx\n", Adapter));
585 NDIS_DbgPrint(DEBUG_MINIPORT, ("AdapterName = %wZ\n", AdapterName));
586 NDIS_DbgPrint(DEBUG_MINIPORT, ("DeviceName = %wZ\n", &Adapter->NdisMiniportBlock.MiniportName));
587
588 if (RtlCompareUnicodeString(AdapterName, &Adapter->NdisMiniportBlock.MiniportName, TRUE) == 0)
589 {
590 break;
591 }
592
593 Adapter = NULL;
594 CurrentEntry = CurrentEntry->Flink;
595 }
596 }
597 KeReleaseSpinLock(&AdapterListLock, OldIrql);
598
599 if(Adapter)
600 {
601 NDIS_DbgPrint(DEBUG_MINIPORT, ("Leaving. Adapter found at 0x%x\n", Adapter));
602 }
603 else
604 {
605 NDIS_DbgPrint(MIN_TRACE, ("Leaving (adapter not found for %wZ).\n", AdapterName));
606 }
607
608 return Adapter;
609 }
610
611 NDIS_STATUS
612 MiniSetInformation(
613 PLOGICAL_ADAPTER Adapter,
614 NDIS_OID Oid,
615 ULONG Size,
616 PVOID Buffer,
617 PULONG BytesRead)
618 {
619 NDIS_STATUS NdisStatus;
620 PNDIS_REQUEST NdisRequest;
621
622 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
623
624 NdisRequest = ExAllocatePool(NonPagedPool, sizeof(NDIS_REQUEST));
625 if (!NdisRequest) {
626 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources\n"));
627 return NDIS_STATUS_RESOURCES;
628 }
629
630 RtlZeroMemory(NdisRequest, sizeof(NDIS_REQUEST));
631
632 NdisRequest->RequestType = NdisRequestSetInformation;
633 NdisRequest->DATA.SET_INFORMATION.Oid = Oid;
634 NdisRequest->DATA.SET_INFORMATION.InformationBuffer = Buffer;
635 NdisRequest->DATA.SET_INFORMATION.InformationBufferLength = Size;
636
637 NdisStatus = MiniBeginRequest(Adapter, NdisWorkItemRequest, NdisRequest);
638 if (!NT_SUCCESS(NdisStatus))
639 return NdisStatus;
640
641 NdisStatus = MiniDoRequest(Adapter, NdisRequest);
642
643 /* FIXME: Wait in pending case! */
644 if (NdisStatus != NDIS_STATUS_PENDING)
645 MiniEndRequest(Adapter, NdisWorkItemRequest);
646
647 ASSERT(NdisStatus != NDIS_STATUS_PENDING);
648
649 *BytesRead = NdisRequest->DATA.SET_INFORMATION.BytesRead;
650
651 ExFreePool(NdisRequest);
652
653 return NdisStatus;
654 }
655
656 NDIS_STATUS
657 MiniQueryInformation(
658 PLOGICAL_ADAPTER Adapter,
659 NDIS_OID Oid,
660 ULONG Size,
661 PVOID Buffer,
662 PULONG BytesWritten)
663 /*
664 * FUNCTION: Queries a logical adapter for properties
665 * ARGUMENTS:
666 * Adapter = Pointer to the logical adapter object to query
667 * Oid = Specifies the Object ID to query for
668 * Size = Size of the passed buffer
669 * Buffer = Buffer for the output
670 * BytesWritten = Address of buffer to place number of bytes written
671 * RETURNS:
672 * Status of operation
673 */
674 {
675 NDIS_STATUS NdisStatus;
676 PNDIS_REQUEST NdisRequest;
677
678 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
679
680 NdisRequest = ExAllocatePool(NonPagedPool, sizeof(NDIS_REQUEST));
681 if (!NdisRequest) {
682 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources\n"));
683 return NDIS_STATUS_RESOURCES;
684 }
685
686 RtlZeroMemory(NdisRequest, sizeof(NDIS_REQUEST));
687
688 NdisRequest->RequestType = NdisRequestQueryInformation;
689 NdisRequest->DATA.QUERY_INFORMATION.Oid = Oid;
690 NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer = Buffer;
691 NdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength = Size;
692
693 NdisStatus = MiniBeginRequest(Adapter, NdisWorkItemRequest, NdisRequest);
694 if (!NT_SUCCESS(NdisStatus))
695 return NdisStatus;
696
697 NdisStatus = MiniDoRequest(Adapter, NdisRequest);
698
699 /* FIXME: Wait in pending case! */
700 if (NdisStatus != NDIS_STATUS_PENDING)
701 MiniEndRequest(Adapter, NdisWorkItemRequest);
702
703 ASSERT(NdisStatus != NDIS_STATUS_PENDING);
704
705 *BytesWritten = NdisRequest->DATA.QUERY_INFORMATION.BytesWritten;
706
707 ExFreePool(NdisRequest);
708
709 return NdisStatus;
710 }
711
712 BOOLEAN
713 MiniCheckForHang( PLOGICAL_ADAPTER Adapter )
714 /*
715 * FUNCTION: Checks to see if the miniport is hung
716 * ARGUMENTS:
717 * Adapter = Pointer to the logical adapter object
718 * RETURNS:
719 * TRUE if the miniport is hung
720 * FALSE if the miniport is not hung
721 */
722 {
723 BOOLEAN Ret = FALSE;
724
725 if (Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.CheckForHangHandler)
726 Ret = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.CheckForHangHandler)(
727 Adapter->NdisMiniportBlock.MiniportAdapterContext);
728
729 return Ret;
730 }
731
732 VOID
733 MiniDoAddressingReset(PLOGICAL_ADAPTER Adapter)
734 {
735 ULONG BytesRead;
736
737 MiniSetInformation(Adapter,
738 OID_GEN_CURRENT_LOOKAHEAD,
739 sizeof(ULONG),
740 &Adapter->NdisMiniportBlock.CurrentLookahead,
741 &BytesRead);
742
743 /* FIXME: Set more stuff */
744 }
745
746 NDIS_STATUS
747 MiniReset(
748 PLOGICAL_ADAPTER Adapter)
749 /*
750 * FUNCTION: Resets the miniport
751 * ARGUMENTS:
752 * Adapter = Pointer to the logical adapter object
753 * RETURNS:
754 * Status of the operation
755 */
756 {
757 NDIS_STATUS Status;
758 BOOLEAN AddressingReset = TRUE;
759
760 Status = MiniBeginRequest(Adapter, NdisWorkItemResetRequested, NULL);
761 if (!NT_SUCCESS(Status))
762 return Status;
763
764 NdisMIndicateStatus(Adapter, NDIS_STATUS_RESET_START, NULL, 0);
765 NdisMIndicateStatusComplete(Adapter);
766
767 Status = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.ResetHandler)(
768 Adapter->NdisMiniportBlock.MiniportAdapterContext,
769 &AddressingReset);
770
771 if (Status != NDIS_STATUS_PENDING) {
772 if (AddressingReset)
773 MiniDoAddressingReset(Adapter);
774
775 MiniEndRequest(Adapter, NdisWorkItemResetRequested);
776
777 NdisMIndicateStatus(Adapter, NDIS_STATUS_RESET_END, NULL, 0);
778 NdisMIndicateStatusComplete(Adapter);
779 }
780
781 return Status;
782 }
783
784 VOID NTAPI
785 MiniportHangDpc(
786 PKDPC Dpc,
787 PVOID DeferredContext,
788 PVOID SystemArgument1,
789 PVOID SystemArgument2)
790 {
791 PLOGICAL_ADAPTER Adapter = DeferredContext;
792
793 if (MiniCheckForHang(Adapter)) {
794 NDIS_DbgPrint(MIN_TRACE, ("Miniport detected adapter hang\n"));
795 MiniReset(Adapter);
796 }
797 }
798
799 NDIS_STATUS
800 MiniBeginRequest(
801 PLOGICAL_ADAPTER Adapter,
802 NDIS_WORK_ITEM_TYPE WorkItemType,
803 PVOID WorkItemContext)
804 {
805 KIRQL OldIrql;
806 BOOLEAN QueueBusy;
807 PNDIS_MINIPORT_WORK_ITEM MiniportWorkItem;
808 PSINGLE_LIST_ENTRY CurrentEntry;
809
810 KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
811
812 QueueBusy = (Adapter->NdisMiniportBlock.WorkQueue[WorkItemType].Next != NULL);
813
814 MiniportWorkItem = ExAllocatePool(NonPagedPool, sizeof(NDIS_MINIPORT_WORK_ITEM));
815 if (!MiniportWorkItem)
816 {
817 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
818 KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
819 return NDIS_STATUS_RESOURCES;
820 }
821
822 MiniportWorkItem->WorkItemType = WorkItemType;
823 MiniportWorkItem->WorkItemContext = WorkItemContext;
824 MiniportWorkItem->Link.Next = NULL;
825
826 CurrentEntry = &Adapter->NdisMiniportBlock.WorkQueue[WorkItemType];
827 while (CurrentEntry->Next)
828 CurrentEntry = CurrentEntry->Next;
829
830 CurrentEntry->Next = (PSINGLE_LIST_ENTRY)MiniportWorkItem;
831
832 KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
833
834 if (QueueBusy)
835 NDIS_DbgPrint(MIN_TRACE, ("Queue %d busy!\n", WorkItemType));
836
837 return (QueueBusy ? NDIS_STATUS_PENDING : NDIS_STATUS_SUCCESS);
838 }
839
840 \f
841 NDIS_STATUS
842 FASTCALL
843 MiniDequeueWorkItem(
844 PLOGICAL_ADAPTER Adapter,
845 NDIS_WORK_ITEM_TYPE WorkItemType,
846 PVOID *WorkItemContext)
847 /*
848 * FUNCTION: Dequeues a work item from the work queue of a logical adapter
849 * ARGUMENTS:
850 * Adapter = Pointer to the logical adapter object to dequeue work item from
851 * AdapterBinding = Address of buffer for adapter binding for this request
852 * WorkItemType = Address of buffer for work item type
853 * WorkItemContext = Address of buffer for pointer to context information
854 * NOTES:
855 * Adapter lock must be held when called
856 * RETURNS:
857 * Status of operation
858 */
859 {
860 PNDIS_MINIPORT_WORK_ITEM MiniportWorkItem;
861 KIRQL OldIrql;
862
863 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
864
865 KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
866 MiniportWorkItem = (PNDIS_MINIPORT_WORK_ITEM)Adapter->NdisMiniportBlock.WorkQueue[WorkItemType].Next;
867 KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
868
869 if (MiniportWorkItem)
870 {
871 /* This is VERY IMPORTANT! We dequeue the work item AFTER completion */
872
873 *WorkItemContext = MiniportWorkItem->WorkItemContext;
874
875 return NDIS_STATUS_SUCCESS;
876 }
877 else
878 {
879 return NDIS_STATUS_FAILURE;
880 }
881 }
882
883 VOID
884 MiniEndRequest(
885 PLOGICAL_ADAPTER Adapter,
886 NDIS_WORK_ITEM_TYPE WorkItemType)
887 {
888 KIRQL OldIrql;
889 BOOLEAN QueueBusy;
890 PNDIS_MINIPORT_WORK_ITEM MiniportWorkItem;
891
892 KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
893
894 MiniportWorkItem = (PNDIS_MINIPORT_WORK_ITEM)Adapter->NdisMiniportBlock.WorkQueue[WorkItemType].Next;
895 ASSERT(MiniportWorkItem);
896 Adapter->NdisMiniportBlock.WorkQueue[WorkItemType].Next = MiniportWorkItem->Link.Next;
897 ExFreePool(MiniportWorkItem);
898
899 QueueBusy = (Adapter->NdisMiniportBlock.WorkQueue[WorkItemType].Next != NULL);
900 KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
901
902 if (QueueBusy)
903 SignalQueue(Adapter);
904 }
905
906 \f
907 NDIS_STATUS
908 MiniDoRequest(
909 PLOGICAL_ADAPTER Adapter,
910 PNDIS_REQUEST NdisRequest)
911 /*
912 * FUNCTION: Sends a request to a miniport
913 * ARGUMENTS:
914 * AdapterBinding = Pointer to binding used in the request
915 * NdisRequest = Pointer to NDIS request structure describing request
916 * RETURNS:
917 * Status of operation
918 */
919 {
920 NDIS_STATUS Status;
921 KIRQL OldIrql;
922
923 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
924
925 KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
926 Adapter->NdisMiniportBlock.PendingRequest = NdisRequest;
927 KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
928
929 if (!Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.CoRequestHandler)
930 {
931 switch (NdisRequest->RequestType)
932 {
933 case NdisRequestQueryInformation:
934 Status = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.QueryInformationHandler)(
935 Adapter->NdisMiniportBlock.MiniportAdapterContext,
936 NdisRequest->DATA.QUERY_INFORMATION.Oid,
937 NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer,
938 NdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength,
939 (PULONG)&NdisRequest->DATA.QUERY_INFORMATION.BytesWritten,
940 (PULONG)&NdisRequest->DATA.QUERY_INFORMATION.BytesNeeded);
941 break;
942
943 case NdisRequestSetInformation:
944 Status = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SetInformationHandler)(
945 Adapter->NdisMiniportBlock.MiniportAdapterContext,
946 NdisRequest->DATA.SET_INFORMATION.Oid,
947 NdisRequest->DATA.SET_INFORMATION.InformationBuffer,
948 NdisRequest->DATA.SET_INFORMATION.InformationBufferLength,
949 (PULONG)&NdisRequest->DATA.SET_INFORMATION.BytesRead,
950 (PULONG)&NdisRequest->DATA.SET_INFORMATION.BytesNeeded);
951 break;
952
953 default:
954 NDIS_DbgPrint(MIN_TRACE, ("Bad request type\n"));
955 Status = NDIS_STATUS_FAILURE;
956 }
957 }
958 else
959 {
960 Status = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.CoRequestHandler)(
961 Adapter->NdisMiniportBlock.MiniportAdapterContext,
962 NULL, /* FIXME */
963 NdisRequest);
964 }
965
966 return Status;
967 }
968
969 \f
970 /*
971 * @implemented
972 */
973 #undef NdisMSetInformationComplete
974 VOID
975 EXPORT
976 NdisMSetInformationComplete(
977 IN NDIS_HANDLE MiniportAdapterHandle,
978 IN NDIS_STATUS Status)
979 {
980 PLOGICAL_ADAPTER Adapter =
981 (PLOGICAL_ADAPTER)MiniportAdapterHandle;
982
983 (Adapter->NdisMiniportBlock.SetCompleteHandler)(MiniportAdapterHandle, Status);
984
985 MiniEndRequest(Adapter, NdisWorkItemRequest);
986 }
987
988 \f
989 /*
990 * @implemented
991 */
992 #undef NdisMQueryInformationComplete
993 VOID
994 EXPORT
995 NdisMQueryInformationComplete(
996 IN NDIS_HANDLE MiniportAdapterHandle,
997 IN NDIS_STATUS Status)
998 {
999 PLOGICAL_ADAPTER Adapter =
1000 (PLOGICAL_ADAPTER)MiniportAdapterHandle;
1001
1002 (Adapter->NdisMiniportBlock.QueryCompleteHandler)(MiniportAdapterHandle, Status);
1003
1004 MiniEndRequest(Adapter, NdisWorkItemRequest);
1005 }
1006
1007 VOID
1008 NTAPI
1009 MiniportWorker(IN PDEVICE_OBJECT DeviceObject, IN PVOID Context)
1010 {
1011 PLOGICAL_ADAPTER Adapter = DeviceObject->DeviceExtension;
1012 KIRQL RaiseOldIrql;
1013 NDIS_STATUS NdisStatus;
1014 PVOID WorkItemContext;
1015 NDIS_WORK_ITEM_TYPE WorkItemType;
1016 BOOLEAN AddressingReset, NextQueue;
1017
1018 IoFreeWorkItem((PIO_WORKITEM)Context);
1019
1020 for (WorkItemType = 0; WorkItemType < NUMBER_OF_WORK_ITEM_TYPES; WorkItemType++)
1021 {
1022 NextQueue = FALSE;
1023 while (!NextQueue && MiniDequeueWorkItem(Adapter, WorkItemType, &WorkItemContext) == NDIS_STATUS_SUCCESS)
1024 {
1025 switch (WorkItemType)
1026 {
1027 case NdisWorkItemSend:
1028 /*
1029 * called by ProSend when protocols want to send packets to the miniport
1030 */
1031
1032 if(Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendPacketsHandler)
1033 {
1034 if(Adapter->NdisMiniportBlock.Flags & NDIS_ATTRIBUTE_DESERIALIZE)
1035 {
1036 NDIS_DbgPrint(MAX_TRACE, ("Calling miniport's SendPackets handler\n"));
1037 (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendPacketsHandler)(
1038 Adapter->NdisMiniportBlock.MiniportAdapterContext, (PPNDIS_PACKET)&WorkItemContext, 1);
1039 NdisStatus = NDIS_STATUS_PENDING;
1040 }
1041 else
1042 {
1043 /* SendPackets is called at DISPATCH_LEVEL for all serialized miniports */
1044 KeRaiseIrql(DISPATCH_LEVEL, &RaiseOldIrql);
1045 {
1046 NDIS_DbgPrint(MAX_TRACE, ("Calling miniport's SendPackets handler\n"));
1047 (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendPacketsHandler)(
1048 Adapter->NdisMiniportBlock.MiniportAdapterContext, (PPNDIS_PACKET)&WorkItemContext, 1);
1049 }
1050 KeLowerIrql(RaiseOldIrql);
1051
1052 NdisStatus = NDIS_GET_PACKET_STATUS((PNDIS_PACKET)WorkItemContext);
1053 if( NdisStatus == NDIS_STATUS_RESOURCES ) {
1054 NextQueue = TRUE;
1055 break;
1056 }
1057 }
1058 }
1059 else
1060 {
1061 if(Adapter->NdisMiniportBlock.Flags & NDIS_ATTRIBUTE_DESERIALIZE)
1062 {
1063 NDIS_DbgPrint(MAX_TRACE, ("Calling miniport's Send handler\n"));
1064 NdisStatus = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendHandler)(
1065 Adapter->NdisMiniportBlock.MiniportAdapterContext, (PNDIS_PACKET)WorkItemContext,
1066 ((PNDIS_PACKET)WorkItemContext)->Private.Flags);
1067 NDIS_DbgPrint(MAX_TRACE, ("back from miniport's send handler\n"));
1068 }
1069 else
1070 {
1071 /* Send is called at DISPATCH_LEVEL for all serialized miniports */
1072 KeRaiseIrql(DISPATCH_LEVEL, &RaiseOldIrql);
1073 NDIS_DbgPrint(MAX_TRACE, ("Calling miniport's Send handler\n"));
1074 NdisStatus = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendHandler)(
1075 Adapter->NdisMiniportBlock.MiniportAdapterContext, (PNDIS_PACKET)WorkItemContext,
1076 ((PNDIS_PACKET)WorkItemContext)->Private.Flags);
1077 NDIS_DbgPrint(MAX_TRACE, ("back from miniport's send handler\n"));
1078 KeLowerIrql(RaiseOldIrql);
1079 if( NdisStatus == NDIS_STATUS_RESOURCES ) {
1080 NextQueue = TRUE;
1081 break;
1082 }
1083 }
1084 }
1085
1086 if( NdisStatus != NDIS_STATUS_PENDING ) {
1087 MiniSendComplete
1088 ( Adapter, (PNDIS_PACKET)WorkItemContext, NdisStatus );
1089 }
1090 break;
1091
1092 case NdisWorkItemSendLoopback:
1093 /*
1094 * called by ProSend when protocols want to send loopback packets
1095 */
1096 /* XXX atm ProIndicatePacket sends a packet up via the loopback adapter only */
1097 NdisStatus = ProIndicatePacket(Adapter, (PNDIS_PACKET)WorkItemContext);
1098
1099 if( NdisStatus != NDIS_STATUS_PENDING )
1100 MiniIndicateComplete((NDIS_HANDLE)Adapter, (PNDIS_PACKET)WorkItemContext, NdisStatus);
1101 break;
1102
1103 case NdisWorkItemReturnPackets:
1104 break;
1105
1106 case NdisWorkItemResetRequested:
1107 NdisStatus = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.ResetHandler)(
1108 Adapter->NdisMiniportBlock.MiniportAdapterContext,
1109 &AddressingReset);
1110
1111 if (NdisStatus != NDIS_STATUS_PENDING)
1112 MiniResetComplete(Adapter, NdisStatus, AddressingReset);
1113 break;
1114
1115 case NdisWorkItemResetInProgress:
1116 break;
1117
1118 case NdisWorkItemMiniportCallback:
1119 break;
1120
1121 case NdisWorkItemRequest:
1122 NdisStatus = MiniDoRequest(Adapter, (PNDIS_REQUEST)WorkItemContext);
1123
1124 if (NdisStatus == NDIS_STATUS_PENDING)
1125 break;
1126
1127 switch (((PNDIS_REQUEST)WorkItemContext)->RequestType)
1128 {
1129 case NdisRequestQueryInformation:
1130 NdisMQueryInformationComplete((NDIS_HANDLE)Adapter, NdisStatus);
1131 break;
1132
1133 case NdisRequestSetInformation:
1134 NdisMSetInformationComplete((NDIS_HANDLE)Adapter, NdisStatus);
1135 break;
1136
1137 default:
1138 NDIS_DbgPrint(MIN_TRACE, ("Unknown NDIS request type.\n"));
1139 MiniEndRequest(Adapter, NdisWorkItemRequest);
1140 break;
1141 }
1142 break;
1143
1144 default:
1145 MiniEndRequest(Adapter, WorkItemType);
1146 NDIS_DbgPrint(MIN_TRACE, ("Unknown NDIS work item type (%d).\n", WorkItemType));
1147 break;
1148 }
1149 }
1150 }
1151 }
1152
1153
1154 \f
1155 VOID
1156 NTAPI
1157 MiniStatus(
1158 IN NDIS_HANDLE MiniportHandle,
1159 IN NDIS_STATUS GeneralStatus,
1160 IN PVOID StatusBuffer,
1161 IN UINT StatusBufferSize)
1162 {
1163 PLOGICAL_ADAPTER Adapter = MiniportHandle;
1164 PLIST_ENTRY CurrentEntry;
1165 PADAPTER_BINDING AdapterBinding;
1166 KIRQL OldIrql;
1167
1168 KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
1169
1170 CurrentEntry = Adapter->ProtocolListHead.Flink;
1171
1172 while (CurrentEntry != &Adapter->ProtocolListHead)
1173 {
1174 AdapterBinding = CONTAINING_RECORD(CurrentEntry, ADAPTER_BINDING, AdapterListEntry);
1175
1176 (*AdapterBinding->ProtocolBinding->Chars.StatusHandler)(
1177 AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
1178 GeneralStatus,
1179 StatusBuffer,
1180 StatusBufferSize);
1181
1182 CurrentEntry = CurrentEntry->Flink;
1183 }
1184
1185 KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
1186 }
1187
1188 \f
1189 VOID
1190 NTAPI
1191 MiniStatusComplete(
1192 IN NDIS_HANDLE MiniportAdapterHandle)
1193 {
1194 PLOGICAL_ADAPTER Adapter = MiniportAdapterHandle;
1195 PLIST_ENTRY CurrentEntry;
1196 PADAPTER_BINDING AdapterBinding;
1197 KIRQL OldIrql;
1198
1199 KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
1200
1201 CurrentEntry = Adapter->ProtocolListHead.Flink;
1202
1203 while (CurrentEntry != &Adapter->ProtocolListHead)
1204 {
1205 AdapterBinding = CONTAINING_RECORD(CurrentEntry, ADAPTER_BINDING, AdapterListEntry);
1206
1207 (*AdapterBinding->ProtocolBinding->Chars.StatusCompleteHandler)(
1208 AdapterBinding->NdisOpenBlock.ProtocolBindingContext);
1209
1210 CurrentEntry = CurrentEntry->Flink;
1211 }
1212
1213 KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
1214 }
1215
1216 \f
1217 /*
1218 * @implemented
1219 */
1220 VOID
1221 EXPORT
1222 NdisMCloseLog(
1223 IN NDIS_HANDLE LogHandle)
1224 {
1225 PNDIS_LOG Log = (PNDIS_LOG)LogHandle;
1226 PNDIS_MINIPORT_BLOCK Miniport = Log->Miniport;
1227 KIRQL OldIrql;
1228
1229 NDIS_DbgPrint(MAX_TRACE, ("called: LogHandle 0x%x\n", LogHandle));
1230
1231 KeAcquireSpinLock(&(Miniport)->Lock, &OldIrql);
1232 Miniport->Log = NULL;
1233 KeReleaseSpinLock(&(Miniport)->Lock, OldIrql);
1234
1235 ExFreePool(Log);
1236 }
1237
1238 /*
1239 * @implemented
1240 */
1241 NDIS_STATUS
1242 EXPORT
1243 NdisMCreateLog(
1244 IN NDIS_HANDLE MiniportAdapterHandle,
1245 IN UINT Size,
1246 OUT PNDIS_HANDLE LogHandle)
1247 {
1248 PLOGICAL_ADAPTER Adapter = MiniportAdapterHandle;
1249 PNDIS_LOG Log;
1250 KIRQL OldIrql;
1251
1252 NDIS_DbgPrint(MAX_TRACE, ("called: MiniportAdapterHandle 0x%x, Size %ld\n", MiniportAdapterHandle, Size));
1253
1254 KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
1255
1256 if (Adapter->NdisMiniportBlock.Log)
1257 {
1258 *LogHandle = NULL;
1259 KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
1260 return NDIS_STATUS_FAILURE;
1261 }
1262
1263 Log = ExAllocatePool(NonPagedPool, Size + sizeof(NDIS_LOG));
1264 if (!Log)
1265 {
1266 *LogHandle = NULL;
1267 KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
1268 return NDIS_STATUS_RESOURCES;
1269 }
1270
1271 Adapter->NdisMiniportBlock.Log = Log;
1272
1273 KeInitializeSpinLock(&Log->LogLock);
1274
1275 Log->Miniport = &Adapter->NdisMiniportBlock;
1276 Log->TotalSize = Size;
1277 Log->CurrentSize = 0;
1278 Log->OutPtr = 0;
1279 Log->InPtr = 0;
1280 Log->Irp = NULL;
1281
1282 *LogHandle = Log;
1283
1284 KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
1285
1286 return NDIS_STATUS_SUCCESS;
1287 }
1288
1289 /*
1290 * @implemented
1291 */
1292 VOID
1293 EXPORT
1294 NdisMDeregisterAdapterShutdownHandler(
1295 IN NDIS_HANDLE MiniportHandle)
1296 /*
1297 * FUNCTION: de-registers a shutdown handler
1298 * ARGUMENTS: MiniportHandle: Handle passed into MiniportInitialize
1299 */
1300 {
1301 PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)MiniportHandle;
1302
1303 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
1304
1305 if(Adapter->BugcheckContext->ShutdownHandler) {
1306 KeDeregisterBugCheckCallback(Adapter->BugcheckContext->CallbackRecord);
1307 IoUnregisterShutdownNotification(Adapter->NdisMiniportBlock.DeviceObject);
1308 }
1309 }
1310
1311 /*
1312 * @implemented
1313 */
1314 VOID
1315 EXPORT
1316 NdisMFlushLog(
1317 IN NDIS_HANDLE LogHandle)
1318 {
1319 PNDIS_LOG Log = (PNDIS_LOG) LogHandle;
1320 KIRQL OldIrql;
1321
1322 NDIS_DbgPrint(MAX_TRACE, ("called: LogHandle 0x%x\n", LogHandle));
1323
1324 /* Lock object */
1325 KeAcquireSpinLock(&Log->LogLock, &OldIrql);
1326
1327 /* Set buffers size */
1328 Log->CurrentSize = 0;
1329 Log->OutPtr = 0;
1330 Log->InPtr = 0;
1331
1332 /* Unlock object */
1333 KeReleaseSpinLock(&Log->LogLock, OldIrql);
1334 }
1335
1336 /*
1337 * @implemented
1338 */
1339 #undef NdisMIndicateStatus
1340 VOID
1341 EXPORT
1342 NdisMIndicateStatus(
1343 IN NDIS_HANDLE MiniportAdapterHandle,
1344 IN NDIS_STATUS GeneralStatus,
1345 IN PVOID StatusBuffer,
1346 IN UINT StatusBufferSize)
1347 {
1348 MiniStatus(MiniportAdapterHandle, GeneralStatus, StatusBuffer, StatusBufferSize);
1349 }
1350
1351 /*
1352 * @implemented
1353 */
1354 #undef NdisMIndicateStatusComplete
1355 VOID
1356 EXPORT
1357 NdisMIndicateStatusComplete(
1358 IN NDIS_HANDLE MiniportAdapterHandle)
1359 {
1360 MiniStatusComplete(MiniportAdapterHandle);
1361 }
1362
1363 \f
1364 /*
1365 * @implemented
1366 */
1367 VOID
1368 EXPORT
1369 NdisInitializeWrapper(
1370 OUT PNDIS_HANDLE NdisWrapperHandle,
1371 IN PVOID SystemSpecific1,
1372 IN PVOID SystemSpecific2,
1373 IN PVOID SystemSpecific3)
1374 /*
1375 * FUNCTION: Notifies the NDIS library that a new miniport is initializing
1376 * ARGUMENTS:
1377 * NdisWrapperHandle = Address of buffer to place NDIS wrapper handle
1378 * SystemSpecific1 = Pointer to the driver's driver object
1379 * SystemSpecific2 = Pointer to the driver's registry path
1380 * SystemSpecific3 = Always NULL
1381 * NOTES:
1382 * - SystemSpecific2 goes invalid so we copy it
1383 */
1384 {
1385 PNDIS_M_DRIVER_BLOCK Miniport;
1386 PUNICODE_STRING RegistryPath;
1387 WCHAR *RegistryBuffer;
1388
1389 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
1390
1391 ASSERT(NdisWrapperHandle);
1392
1393 *NdisWrapperHandle = NULL;
1394
1395 #if BREAK_ON_MINIPORT_INIT
1396 DbgBreakPoint();
1397 #endif
1398
1399 Miniport = ExAllocatePool(NonPagedPool, sizeof(NDIS_M_DRIVER_BLOCK));
1400
1401 if (!Miniport)
1402 {
1403 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
1404 return;
1405 }
1406
1407 RtlZeroMemory(Miniport, sizeof(NDIS_M_DRIVER_BLOCK));
1408
1409 KeInitializeSpinLock(&Miniport->Lock);
1410
1411 Miniport->DriverObject = (PDRIVER_OBJECT)SystemSpecific1;
1412
1413 /* set the miniport's driver registry path */
1414 RegistryPath = ExAllocatePool(PagedPool, sizeof(UNICODE_STRING));
1415 if(!RegistryPath)
1416 {
1417 ExFreePool(Miniport);
1418 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
1419 return;
1420 }
1421
1422 RegistryPath->Length = ((PUNICODE_STRING)SystemSpecific2)->Length;
1423 RegistryPath->MaximumLength = RegistryPath->Length + sizeof(WCHAR); /* room for 0-term */
1424
1425 RegistryBuffer = ExAllocatePool(PagedPool, RegistryPath->MaximumLength);
1426 if(!RegistryBuffer)
1427 {
1428 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
1429 ExFreePool(Miniport);
1430 ExFreePool(RegistryPath);
1431 return;
1432 }
1433
1434 RtlCopyMemory(RegistryBuffer, ((PUNICODE_STRING)SystemSpecific2)->Buffer, RegistryPath->Length);
1435 RegistryBuffer[RegistryPath->Length/sizeof(WCHAR)] = 0;
1436
1437 RegistryPath->Buffer = RegistryBuffer;
1438 Miniport->RegistryPath = RegistryPath;
1439
1440 InitializeListHead(&Miniport->DeviceList);
1441
1442 /* Put miniport in global miniport list */
1443 ExInterlockedInsertTailList(&MiniportListHead, &Miniport->ListEntry, &MiniportListLock);
1444
1445 *NdisWrapperHandle = Miniport;
1446 }
1447
1448 \f
1449 VOID NTAPI NdisIBugcheckCallback(
1450 IN PVOID Buffer,
1451 IN ULONG Length)
1452 /*
1453 * FUNCTION: Internal callback for handling bugchecks - calls adapter's shutdown handler
1454 * ARGUMENTS:
1455 * Buffer: Pointer to a bugcheck callback context
1456 * Length: Unused
1457 */
1458 {
1459 PMINIPORT_BUGCHECK_CONTEXT Context = (PMINIPORT_BUGCHECK_CONTEXT)Buffer;
1460 ADAPTER_SHUTDOWN_HANDLER sh = (ADAPTER_SHUTDOWN_HANDLER)Context->ShutdownHandler;
1461
1462 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
1463
1464 if(sh)
1465 sh(Context->DriverContext);
1466 }
1467
1468 \f
1469 /*
1470 * @implemented
1471 */
1472 VOID
1473 EXPORT
1474 NdisMRegisterAdapterShutdownHandler(
1475 IN NDIS_HANDLE MiniportHandle,
1476 IN PVOID ShutdownContext,
1477 IN ADAPTER_SHUTDOWN_HANDLER ShutdownHandler)
1478 /*
1479 * FUNCTION: Register a shutdown handler for an adapter
1480 * ARGUMENTS:
1481 * MiniportHandle: Handle originally passed into MiniportInitialize
1482 * ShutdownContext: Pre-initialized bugcheck context
1483 * ShutdownHandler: Function to call to handle the bugcheck
1484 * NOTES:
1485 * - I'm not sure about ShutdownContext
1486 */
1487 {
1488 PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)MiniportHandle;
1489 PMINIPORT_BUGCHECK_CONTEXT BugcheckContext;
1490
1491 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
1492
1493 BugcheckContext = ExAllocatePool(NonPagedPool, sizeof(MINIPORT_BUGCHECK_CONTEXT));
1494 if(!BugcheckContext)
1495 {
1496 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
1497 return;
1498 }
1499
1500 BugcheckContext->ShutdownHandler = ShutdownHandler;
1501 BugcheckContext->DriverContext = ShutdownContext;
1502
1503 BugcheckContext->CallbackRecord = ExAllocatePool(NonPagedPool, sizeof(KBUGCHECK_CALLBACK_RECORD));
1504 if (!BugcheckContext->CallbackRecord) {
1505 ExFreePool(BugcheckContext);
1506 return;
1507 }
1508
1509 Adapter->BugcheckContext = BugcheckContext;
1510
1511 KeInitializeCallbackRecord(BugcheckContext->CallbackRecord);
1512
1513 KeRegisterBugCheckCallback(BugcheckContext->CallbackRecord, NdisIBugcheckCallback,
1514 BugcheckContext, sizeof(*BugcheckContext), (PUCHAR)"Ndis Miniport");
1515
1516 IoRegisterShutdownNotification(Adapter->NdisMiniportBlock.DeviceObject);
1517 }
1518
1519 \f
1520 NDIS_STATUS
1521 DoQueries(
1522 PLOGICAL_ADAPTER Adapter,
1523 NDIS_OID AddressOID)
1524 /*
1525 * FUNCTION: Queries miniport for information
1526 * ARGUMENTS:
1527 * Adapter = Pointer to logical adapter
1528 * AddressOID = OID to use to query for current address
1529 * RETURNS:
1530 * Status of operation
1531 */
1532 {
1533 ULONG BytesWritten;
1534 NDIS_STATUS NdisStatus;
1535
1536 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
1537
1538 /* Get MAC options for adapter */
1539 NdisStatus = MiniQueryInformation(Adapter, OID_GEN_MAC_OPTIONS, sizeof(UINT),
1540 &Adapter->NdisMiniportBlock.MacOptions,
1541 &BytesWritten);
1542
1543 if (NdisStatus != NDIS_STATUS_SUCCESS)
1544 {
1545 NDIS_DbgPrint(MIN_TRACE, ("OID_GEN_MAC_OPTIONS failed. NdisStatus (0x%X).\n", NdisStatus));
1546 return NdisStatus;
1547 }
1548
1549 NDIS_DbgPrint(DEBUG_MINIPORT, ("MacOptions (0x%X).\n", Adapter->NdisMiniportBlock.MacOptions));
1550
1551 /* Get current hardware address of adapter */
1552 NdisStatus = MiniQueryInformation(Adapter, AddressOID, Adapter->AddressLength,
1553 &Adapter->Address, &BytesWritten);
1554
1555 if (NdisStatus != NDIS_STATUS_SUCCESS)
1556 {
1557 NDIS_DbgPrint(MIN_TRACE, ("Address OID (0x%X) failed. NdisStatus (0x%X).\n", AddressOID, NdisStatus));
1558 return NdisStatus;
1559 }
1560
1561 #if DBG
1562 {
1563 /* 802.3 only */
1564
1565 PUCHAR A = (PUCHAR)&Adapter->Address.Type.Medium802_3;
1566
1567 NDIS_DbgPrint(MAX_TRACE, ("Adapter address is (%02X %02X %02X %02X %02X %02X).\n", A[0], A[1], A[2], A[3], A[4], A[5]));
1568 }
1569 #endif /* DBG */
1570
1571 /* Get maximum lookahead buffer size of adapter */
1572 NdisStatus = MiniQueryInformation(Adapter, OID_GEN_MAXIMUM_LOOKAHEAD, sizeof(ULONG),
1573 &Adapter->NdisMiniportBlock.MaximumLookahead, &BytesWritten);
1574
1575 if (NdisStatus != NDIS_STATUS_SUCCESS)
1576 {
1577 NDIS_DbgPrint(MIN_TRACE, ("OID_GEN_MAXIMUM_LOOKAHEAD failed. NdisStatus (0x%X).\n", NdisStatus));
1578 return NdisStatus;
1579 }
1580
1581 NDIS_DbgPrint(DEBUG_MINIPORT, ("MaxLookaheadLength (0x%X).\n", Adapter->NdisMiniportBlock.MaximumLookahead));
1582
1583 /* Get current lookahead buffer size of adapter */
1584 NdisStatus = MiniQueryInformation(Adapter, OID_GEN_CURRENT_LOOKAHEAD, sizeof(ULONG),
1585 &Adapter->NdisMiniportBlock.CurrentLookahead, &BytesWritten);
1586
1587 if (NdisStatus != NDIS_STATUS_SUCCESS)
1588 {
1589 NDIS_DbgPrint(MIN_TRACE, ("OID_GEN_CURRENT_LOOKAHEAD failed. NdisStatus (0x%X).\n", NdisStatus));
1590 return NdisStatus;
1591 }
1592
1593 NdisStatus = MiniQueryInformation(Adapter, OID_GEN_MAXIMUM_SEND_PACKETS, sizeof(ULONG),
1594 &Adapter->NdisMiniportBlock.MaxSendPackets, &BytesWritten);
1595
1596 if (NdisStatus != NDIS_STATUS_SUCCESS)
1597 {
1598 NDIS_DbgPrint(MIN_TRACE, ("OID_GEN_MAXIMUM_SEND_PACKETS failed. NdisStatus (0x%X).\n", NdisStatus));
1599
1600 /* Set it to 1 if it fails because some drivers don't support this (?)*/
1601 Adapter->NdisMiniportBlock.MaxSendPackets = 1;
1602 }
1603
1604 NDIS_DbgPrint(DEBUG_MINIPORT, ("CurLookaheadLength (0x%X).\n", Adapter->NdisMiniportBlock.CurrentLookahead));
1605
1606 return STATUS_SUCCESS;
1607 }
1608
1609 \f
1610 NTSTATUS
1611 NTAPI
1612 NdisIForwardIrpAndWaitCompletionRoutine(
1613 PDEVICE_OBJECT Fdo,
1614 PIRP Irp,
1615 PVOID Context)
1616 {
1617 PKEVENT Event = Context;
1618
1619 if (Irp->PendingReturned)
1620 KeSetEvent(Event, IO_NO_INCREMENT, FALSE);
1621
1622 return STATUS_MORE_PROCESSING_REQUIRED;
1623 }
1624
1625 \f
1626 NTSTATUS
1627 NTAPI
1628 NdisIForwardIrpAndWait(PLOGICAL_ADAPTER Adapter, PIRP Irp)
1629 {
1630 KEVENT Event;
1631 NTSTATUS Status;
1632
1633 KeInitializeEvent(&Event, NotificationEvent, FALSE);
1634 IoCopyCurrentIrpStackLocationToNext(Irp);
1635 IoSetCompletionRoutine(Irp, NdisIForwardIrpAndWaitCompletionRoutine, &Event,
1636 TRUE, TRUE, TRUE);
1637 Status = IoCallDriver(Adapter->NdisMiniportBlock.NextDeviceObject, Irp);
1638 if (Status == STATUS_PENDING)
1639 {
1640 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
1641 Status = Irp->IoStatus.Status;
1642 }
1643 return Status;
1644 }
1645
1646 \f
1647 NTSTATUS
1648 NTAPI
1649 NdisIPnPStartDevice(
1650 IN PDEVICE_OBJECT DeviceObject,
1651 PIRP Irp)
1652 /*
1653 * FUNCTION: Handle the PnP start device event
1654 * ARGUMENTS:
1655 * DeviceObejct = Functional Device Object
1656 * Irp = IRP_MN_START_DEVICE I/O request packet
1657 * RETURNS:
1658 * Status of operation
1659 */
1660 {
1661 PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
1662 PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)DeviceObject->DeviceExtension;
1663 NDIS_WRAPPER_CONTEXT WrapperContext;
1664 NDIS_STATUS NdisStatus;
1665 NDIS_STATUS OpenErrorStatus;
1666 NTSTATUS Status;
1667 UINT SelectedMediumIndex = 0;
1668 NDIS_OID AddressOID;
1669 BOOLEAN Success = FALSE;
1670 ULONG ResourceCount;
1671 ULONG ResourceListSize;
1672 UNICODE_STRING ParamName;
1673 PNDIS_CONFIGURATION_PARAMETER ConfigParam;
1674 NDIS_HANDLE ConfigHandle;
1675 ULONG Size;
1676 LARGE_INTEGER Timeout;
1677 UINT MaxMulticastAddresses;
1678 ULONG BytesWritten;
1679
1680 /*
1681 * Prepare wrapper context used by HW and configuration routines.
1682 */
1683
1684 NDIS_DbgPrint(DEBUG_MINIPORT, ("Start Device %wZ\n", &Adapter->NdisMiniportBlock.MiniportName));
1685
1686 NDIS_DbgPrint(MAX_TRACE, ("Inserting adapter 0x%x into adapter list\n", Adapter));
1687
1688 /* Put adapter in global adapter list */
1689 ExInterlockedInsertTailList(&AdapterListHead, &Adapter->ListEntry, &AdapterListLock);
1690
1691 Status = IoOpenDeviceRegistryKey(
1692 Adapter->NdisMiniportBlock.PhysicalDeviceObject, PLUGPLAY_REGKEY_DRIVER,
1693 KEY_ALL_ACCESS, &WrapperContext.RegistryHandle);
1694 if (!NT_SUCCESS(Status))
1695 {
1696 NDIS_DbgPrint(MIN_TRACE,("failed to open adapter-specific reg key\n"));
1697 ExInterlockedRemoveEntryList( &Adapter->ListEntry, &AdapterListLock );
1698 return Status;
1699 }
1700
1701 NDIS_DbgPrint(MAX_TRACE, ("opened device reg key\n"));
1702
1703 WrapperContext.DeviceObject = Adapter->NdisMiniportBlock.DeviceObject;
1704
1705 /*
1706 * Store the adapter resources used by HW routines such as
1707 * NdisMQueryAdapterResources.
1708 */
1709
1710 if (Stack->Parameters.StartDevice.AllocatedResources != NULL)
1711 {
1712 ResourceCount = Stack->Parameters.StartDevice.AllocatedResources->List[0].
1713 PartialResourceList.Count;
1714 ResourceListSize =
1715 FIELD_OFFSET(CM_RESOURCE_LIST, List[0].PartialResourceList.
1716 PartialDescriptors[ResourceCount]);
1717
1718 Adapter->NdisMiniportBlock.AllocatedResources =
1719 ExAllocatePool(PagedPool, ResourceListSize);
1720 if (Adapter->NdisMiniportBlock.AllocatedResources == NULL)
1721 {
1722 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources\n"));
1723 ExInterlockedRemoveEntryList( &Adapter->ListEntry, &AdapterListLock );
1724 return STATUS_INSUFFICIENT_RESOURCES;
1725 }
1726
1727 Adapter->NdisMiniportBlock.Resources =
1728 ExAllocatePool(PagedPool, ResourceListSize);
1729 if (!Adapter->NdisMiniportBlock.Resources)
1730 {
1731 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources\n"));
1732 ExFreePool(Adapter->NdisMiniportBlock.AllocatedResources);
1733 ExInterlockedRemoveEntryList(&Adapter->ListEntry, &AdapterListLock);
1734 return STATUS_INSUFFICIENT_RESOURCES;
1735 }
1736
1737 RtlCopyMemory(Adapter->NdisMiniportBlock.Resources,
1738 Stack->Parameters.StartDevice.AllocatedResources,
1739 ResourceListSize);
1740
1741 RtlCopyMemory(Adapter->NdisMiniportBlock.AllocatedResources,
1742 Stack->Parameters.StartDevice.AllocatedResources,
1743 ResourceListSize);
1744 }
1745
1746 if (Stack->Parameters.StartDevice.AllocatedResourcesTranslated != NULL)
1747 {
1748 ResourceCount = Stack->Parameters.StartDevice.AllocatedResourcesTranslated->List[0].
1749 PartialResourceList.Count;
1750 ResourceListSize =
1751 FIELD_OFFSET(CM_RESOURCE_LIST, List[0].PartialResourceList.
1752 PartialDescriptors[ResourceCount]);
1753
1754 Adapter->NdisMiniportBlock.AllocatedResourcesTranslated =
1755 ExAllocatePool(PagedPool, ResourceListSize);
1756 if (Adapter->NdisMiniportBlock.AllocatedResourcesTranslated == NULL)
1757 {
1758 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources\n"));
1759 ExInterlockedRemoveEntryList( &Adapter->ListEntry, &AdapterListLock );
1760 return STATUS_INSUFFICIENT_RESOURCES;
1761 }
1762
1763 RtlCopyMemory(Adapter->NdisMiniportBlock.AllocatedResourcesTranslated,
1764 Stack->Parameters.StartDevice.AllocatedResourcesTranslated,
1765 ResourceListSize);
1766 }
1767
1768 /*
1769 * Store the Bus Type, Bus Number and Slot information. It's used by
1770 * the hardware routines then.
1771 */
1772
1773 NdisOpenConfiguration(&NdisStatus, &ConfigHandle, (NDIS_HANDLE)&WrapperContext);
1774 if (NdisStatus != NDIS_STATUS_SUCCESS)
1775 {
1776 NDIS_DbgPrint(MIN_TRACE, ("Failed to open configuration key\n"));
1777 ExInterlockedRemoveEntryList( &Adapter->ListEntry, &AdapterListLock );
1778 return NdisStatus;
1779 }
1780
1781 Size = sizeof(ULONG);
1782 Status = IoGetDeviceProperty(Adapter->NdisMiniportBlock.PhysicalDeviceObject,
1783 DevicePropertyLegacyBusType, Size,
1784 &Adapter->NdisMiniportBlock.BusType, &Size);
1785 if (!NT_SUCCESS(Status) || (INTERFACE_TYPE)Adapter->NdisMiniportBlock.BusType == InterfaceTypeUndefined)
1786 {
1787 NdisInitUnicodeString(&ParamName, L"BusType");
1788 NdisReadConfiguration(&NdisStatus, &ConfigParam, ConfigHandle,
1789 &ParamName, NdisParameterInteger);
1790 if (NdisStatus == NDIS_STATUS_SUCCESS)
1791 Adapter->NdisMiniportBlock.BusType = ConfigParam->ParameterData.IntegerData;
1792 else
1793 Adapter->NdisMiniportBlock.BusType = Isa;
1794 }
1795
1796 Status = IoGetDeviceProperty(Adapter->NdisMiniportBlock.PhysicalDeviceObject,
1797 DevicePropertyBusNumber, Size,
1798 &Adapter->NdisMiniportBlock.BusNumber, &Size);
1799 if (!NT_SUCCESS(Status) || Adapter->NdisMiniportBlock.BusNumber == 0xFFFFFFF0)
1800 {
1801 NdisInitUnicodeString(&ParamName, L"BusNumber");
1802 NdisReadConfiguration(&NdisStatus, &ConfigParam, ConfigHandle,
1803 &ParamName, NdisParameterInteger);
1804 if (NdisStatus == NDIS_STATUS_SUCCESS)
1805 Adapter->NdisMiniportBlock.BusNumber = ConfigParam->ParameterData.IntegerData;
1806 else
1807 Adapter->NdisMiniportBlock.BusNumber = 0;
1808 }
1809 WrapperContext.BusNumber = Adapter->NdisMiniportBlock.BusNumber;
1810
1811 Status = IoGetDeviceProperty(Adapter->NdisMiniportBlock.PhysicalDeviceObject,
1812 DevicePropertyAddress, Size,
1813 &Adapter->NdisMiniportBlock.SlotNumber, &Size);
1814 if (!NT_SUCCESS(Status) || Adapter->NdisMiniportBlock.SlotNumber == (NDIS_INTERFACE_TYPE)-1)
1815 {
1816 NdisInitUnicodeString(&ParamName, L"SlotNumber");
1817 NdisReadConfiguration(&NdisStatus, &ConfigParam, ConfigHandle,
1818 &ParamName, NdisParameterInteger);
1819 if (NdisStatus == NDIS_STATUS_SUCCESS)
1820 Adapter->NdisMiniportBlock.SlotNumber = ConfigParam->ParameterData.IntegerData;
1821 else
1822 Adapter->NdisMiniportBlock.SlotNumber = 0;
1823 }
1824 else
1825 {
1826 /* Convert slotnumber to PCI_SLOT_NUMBER */
1827 ULONG PciSlotNumber = Adapter->NdisMiniportBlock.SlotNumber;
1828 PCI_SLOT_NUMBER SlotNumber;
1829
1830 SlotNumber.u.AsULONG = 0;
1831 SlotNumber.u.bits.DeviceNumber = (PciSlotNumber >> 16) & 0xFFFF;
1832 SlotNumber.u.bits.FunctionNumber = PciSlotNumber & 0xFFFF;
1833
1834 Adapter->NdisMiniportBlock.SlotNumber = SlotNumber.u.AsULONG;
1835 }
1836 WrapperContext.SlotNumber = Adapter->NdisMiniportBlock.SlotNumber;
1837
1838 NdisCloseConfiguration(ConfigHandle);
1839
1840 /* Set handlers (some NDIS macros require these) */
1841 Adapter->NdisMiniportBlock.EthRxCompleteHandler = EthFilterDprIndicateReceiveComplete;
1842 Adapter->NdisMiniportBlock.EthRxIndicateHandler = EthFilterDprIndicateReceive;
1843 Adapter->NdisMiniportBlock.SendCompleteHandler = MiniSendComplete;
1844 Adapter->NdisMiniportBlock.SendResourcesHandler = MiniSendResourcesAvailable;
1845 Adapter->NdisMiniportBlock.ResetCompleteHandler = MiniResetComplete;
1846 Adapter->NdisMiniportBlock.TDCompleteHandler = MiniTransferDataComplete;
1847 Adapter->NdisMiniportBlock.PacketIndicateHandler= MiniIndicateReceivePacket;
1848 Adapter->NdisMiniportBlock.StatusHandler = MiniStatus;
1849 Adapter->NdisMiniportBlock.StatusCompleteHandler= MiniStatusComplete;
1850 Adapter->NdisMiniportBlock.SendPacketsHandler = ProSendPackets;
1851 Adapter->NdisMiniportBlock.QueryCompleteHandler = MiniRequestComplete;
1852 Adapter->NdisMiniportBlock.SetCompleteHandler = MiniRequestComplete;
1853
1854 /*
1855 * Call MiniportInitialize.
1856 */
1857
1858 NDIS_DbgPrint(MID_TRACE, ("calling MiniportInitialize\n"));
1859 NdisStatus = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.InitializeHandler)(
1860 &OpenErrorStatus, &SelectedMediumIndex, &MediaArray[0],
1861 MEDIA_ARRAY_SIZE, Adapter, (NDIS_HANDLE)&WrapperContext);
1862
1863 ZwClose(WrapperContext.RegistryHandle);
1864
1865 if (NdisStatus != NDIS_STATUS_SUCCESS)
1866 {
1867 NDIS_DbgPrint(MIN_TRACE, ("MiniportInitialize() failed for an adapter.\n"));
1868 ExInterlockedRemoveEntryList( &Adapter->ListEntry, &AdapterListLock );
1869 return NdisStatus;
1870 }
1871
1872 if (SelectedMediumIndex >= MEDIA_ARRAY_SIZE)
1873 {
1874 NDIS_DbgPrint(MIN_TRACE, ("MiniportInitialize() selected a bad index\n"));
1875 ExInterlockedRemoveEntryList( &Adapter->ListEntry, &AdapterListLock );
1876 return NDIS_STATUS_UNSUPPORTED_MEDIA;
1877 }
1878
1879 Adapter->NdisMiniportBlock.MediaType = MediaArray[SelectedMediumIndex];
1880
1881 switch (Adapter->NdisMiniportBlock.MediaType)
1882 {
1883 case NdisMedium802_3:
1884 Adapter->MediumHeaderSize = 14; /* XXX figure out what to do about LLC */
1885 AddressOID = OID_802_3_CURRENT_ADDRESS;
1886 Adapter->AddressLength = ETH_LENGTH_OF_ADDRESS;
1887 NdisStatus = DoQueries(Adapter, AddressOID);
1888 if (NdisStatus == NDIS_STATUS_SUCCESS)
1889 {
1890 NdisStatus = MiniQueryInformation(Adapter, OID_802_3_MAXIMUM_LIST_SIZE, sizeof(UINT),
1891 &MaxMulticastAddresses, &BytesWritten);
1892
1893 if (NdisStatus != NDIS_STATUS_SUCCESS)
1894 {
1895 ExInterlockedRemoveEntryList( &Adapter->ListEntry, &AdapterListLock );
1896 NDIS_DbgPrint(MIN_TRACE, ("MiniQueryInformation failed (%x)\n", NdisStatus));
1897 return NdisStatus;
1898 }
1899
1900 Success = EthCreateFilter(MaxMulticastAddresses,
1901 Adapter->Address.Type.Medium802_3,
1902 &Adapter->NdisMiniportBlock.EthDB);
1903 if (Success)
1904 ((PETHI_FILTER)Adapter->NdisMiniportBlock.EthDB)->Miniport = (PNDIS_MINIPORT_BLOCK)Adapter;
1905 else
1906 NdisStatus = NDIS_STATUS_RESOURCES;
1907 }
1908 break;
1909
1910 default:
1911 /* FIXME: Support other types of media */
1912 NDIS_DbgPrint(MIN_TRACE, ("error: unsupported media\n"));
1913 ASSERT(FALSE);
1914 ExInterlockedRemoveEntryList( &Adapter->ListEntry, &AdapterListLock );
1915 return STATUS_UNSUCCESSFUL;
1916 }
1917
1918 if (NdisStatus != NDIS_STATUS_SUCCESS)
1919 {
1920 NDIS_DbgPrint(MIN_TRACE, ("couldn't create filter (%x)\n", NdisStatus));
1921 return NdisStatus;
1922 }
1923
1924 /* Check for a hang every two seconds if it wasn't set in MiniportInitialize */
1925 if (Adapter->NdisMiniportBlock.CheckForHangSeconds == 0)
1926 Adapter->NdisMiniportBlock.CheckForHangSeconds = 2;
1927
1928 Adapter->NdisMiniportBlock.OldPnPDeviceState = Adapter->NdisMiniportBlock.PnPDeviceState;
1929 Adapter->NdisMiniportBlock.PnPDeviceState = NdisPnPDeviceStarted;
1930
1931 IoSetDeviceInterfaceState(&Adapter->NdisMiniportBlock.SymbolicLinkName, TRUE);
1932
1933 Timeout.QuadPart = Int32x32To64(Adapter->NdisMiniportBlock.CheckForHangSeconds, -1000000);
1934 KeSetTimerEx(&Adapter->NdisMiniportBlock.WakeUpDpcTimer.Timer, Timeout,
1935 Adapter->NdisMiniportBlock.CheckForHangSeconds * 1000,
1936 &Adapter->NdisMiniportBlock.WakeUpDpcTimer.Dpc);
1937
1938 /* Put adapter in adapter list for this miniport */
1939 ExInterlockedInsertTailList(&Adapter->NdisMiniportBlock.DriverHandle->DeviceList, &Adapter->MiniportListEntry, &Adapter->NdisMiniportBlock.DriverHandle->Lock);
1940
1941 return STATUS_SUCCESS;
1942 }
1943
1944 \f
1945 NTSTATUS
1946 NTAPI
1947 NdisIPnPStopDevice(
1948 IN PDEVICE_OBJECT DeviceObject,
1949 PIRP Irp)
1950 /*
1951 * FUNCTION: Handle the PnP stop device event
1952 * ARGUMENTS:
1953 * DeviceObejct = Functional Device Object
1954 * Irp = IRP_MN_STOP_DEVICE I/O request packet
1955 * RETURNS:
1956 * Status of operation
1957 */
1958 {
1959 PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)DeviceObject->DeviceExtension;
1960
1961 /* Remove adapter from adapter list for this miniport */
1962 ExInterlockedRemoveEntryList(&Adapter->MiniportListEntry, &Adapter->NdisMiniportBlock.DriverHandle->Lock);
1963
1964 /* Remove adapter from global adapter list */
1965 ExInterlockedRemoveEntryList(&Adapter->ListEntry, &AdapterListLock);
1966
1967 KeCancelTimer(&Adapter->NdisMiniportBlock.WakeUpDpcTimer.Timer);
1968
1969 (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.HaltHandler)(Adapter);
1970
1971 IoSetDeviceInterfaceState(&Adapter->NdisMiniportBlock.SymbolicLinkName, FALSE);
1972
1973 if (Adapter->NdisMiniportBlock.AllocatedResources)
1974 {
1975 ExFreePool(Adapter->NdisMiniportBlock.AllocatedResources);
1976 Adapter->NdisMiniportBlock.AllocatedResources = NULL;
1977 }
1978 if (Adapter->NdisMiniportBlock.AllocatedResourcesTranslated)
1979 {
1980 ExFreePool(Adapter->NdisMiniportBlock.AllocatedResourcesTranslated);
1981 Adapter->NdisMiniportBlock.AllocatedResourcesTranslated = NULL;
1982 }
1983
1984 if (Adapter->NdisMiniportBlock.Resources)
1985 {
1986 ExFreePool(Adapter->NdisMiniportBlock.Resources);
1987 Adapter->NdisMiniportBlock.Resources = NULL;
1988 }
1989
1990 if (Adapter->NdisMiniportBlock.EthDB)
1991 {
1992 EthDeleteFilter(Adapter->NdisMiniportBlock.EthDB);
1993 Adapter->NdisMiniportBlock.EthDB = NULL;
1994 }
1995
1996 Adapter->NdisMiniportBlock.OldPnPDeviceState = Adapter->NdisMiniportBlock.PnPDeviceState;
1997 Adapter->NdisMiniportBlock.PnPDeviceState = NdisPnPDeviceStopped;
1998
1999 return STATUS_SUCCESS;
2000 }
2001
2002 NTSTATUS
2003 NTAPI
2004 NdisIShutdown(
2005 IN PDEVICE_OBJECT DeviceObject,
2006 PIRP Irp)
2007 {
2008 PLOGICAL_ADAPTER Adapter = DeviceObject->DeviceExtension;
2009 PMINIPORT_BUGCHECK_CONTEXT Context = Adapter->BugcheckContext;
2010 ADAPTER_SHUTDOWN_HANDLER ShutdownHandler = Context->ShutdownHandler;
2011
2012 ASSERT(ShutdownHandler);
2013
2014 ShutdownHandler(Context->DriverContext);
2015
2016 Irp->IoStatus.Status = STATUS_SUCCESS;
2017 Irp->IoStatus.Information = 0;
2018
2019 IoCompleteRequest(Irp, IO_NO_INCREMENT);
2020
2021 return STATUS_SUCCESS;
2022 }
2023
2024 NTSTATUS
2025 NTAPI
2026 NdisIDeviceIoControl(
2027 IN PDEVICE_OBJECT DeviceObject,
2028 PIRP Irp)
2029 {
2030 PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)DeviceObject->DeviceExtension;
2031 PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
2032 NDIS_STATUS Status = STATUS_NOT_SUPPORTED;
2033
2034 Irp->IoStatus.Information = 0;
2035
2036 ASSERT(Adapter);
2037
2038 switch (Stack->Parameters.DeviceIoControl.IoControlCode)
2039 {
2040 case IOCTL_NDIS_QUERY_GLOBAL_STATS:
2041 Status = MiniQueryInformation(Adapter,
2042 *(PNDIS_OID)Irp->AssociatedIrp.SystemBuffer,
2043 Stack->Parameters.DeviceIoControl.OutputBufferLength,
2044 MmGetSystemAddressForMdl(Irp->MdlAddress),
2045 &Irp->IoStatus.Information);
2046 break;
2047
2048 default:
2049 ASSERT(FALSE);
2050 break;
2051 }
2052
2053 if (Status != NDIS_STATUS_PENDING)
2054 {
2055 Irp->IoStatus.Status = Status;
2056 IoCompleteRequest(Irp, IO_NO_INCREMENT);
2057 }
2058 else
2059 IoMarkIrpPending(Irp);
2060
2061 return Status;
2062 }
2063
2064 \f
2065 NTSTATUS
2066 NTAPI
2067 NdisIDispatchPnp(
2068 IN PDEVICE_OBJECT DeviceObject,
2069 PIRP Irp)
2070 {
2071 PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
2072 PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)DeviceObject->DeviceExtension;
2073 NTSTATUS Status;
2074
2075 switch (Stack->MinorFunction)
2076 {
2077 case IRP_MN_START_DEVICE:
2078 Status = NdisIForwardIrpAndWait(Adapter, Irp);
2079 if (NT_SUCCESS(Status) && NT_SUCCESS(Irp->IoStatus.Status))
2080 {
2081 Status = NdisIPnPStartDevice(DeviceObject, Irp);
2082 }
2083 else
2084 NDIS_DbgPrint(MIN_TRACE, ("Lower driver failed device start\n"));
2085 Irp->IoStatus.Status = Status;
2086 IoCompleteRequest(Irp, IO_NO_INCREMENT);
2087 break;
2088
2089 case IRP_MN_STOP_DEVICE:
2090 Status = NdisIForwardIrpAndWait(Adapter, Irp);
2091 if (NT_SUCCESS(Status) && NT_SUCCESS(Irp->IoStatus.Status))
2092 {
2093 Status = NdisIPnPStopDevice(DeviceObject, Irp);
2094 }
2095 else
2096 NDIS_DbgPrint(MIN_TRACE, ("Lower driver failed device stop\n"));
2097 Irp->IoStatus.Status = Status;
2098 IoCompleteRequest(Irp, IO_NO_INCREMENT);
2099 break;
2100
2101 case IRP_MN_QUERY_REMOVE_DEVICE:
2102 case IRP_MN_QUERY_STOP_DEVICE:
2103 Status = NdisIPnPQueryStopDevice(DeviceObject, Irp);
2104 Irp->IoStatus.Status = Status;
2105 IoCompleteRequest(Irp, IO_NO_INCREMENT);
2106 break;
2107
2108 case IRP_MN_CANCEL_REMOVE_DEVICE:
2109 case IRP_MN_CANCEL_STOP_DEVICE:
2110 Status = NdisIPnPCancelStopDevice(DeviceObject, Irp);
2111 Irp->IoStatus.Status = Status;
2112 IoCompleteRequest(Irp, IO_NO_INCREMENT);
2113 break;
2114
2115 case IRP_MN_QUERY_PNP_DEVICE_STATE:
2116 Status = NDIS_STATUS_SUCCESS;
2117 Irp->IoStatus.Status = Status;
2118 Irp->IoStatus.Information |= Adapter->NdisMiniportBlock.PnPFlags;
2119 IoCompleteRequest(Irp, IO_NO_INCREMENT);
2120 break;
2121
2122 default:
2123 IoSkipCurrentIrpStackLocation(Irp);
2124 Status = IoCallDriver(Adapter->NdisMiniportBlock.NextDeviceObject, Irp);
2125 break;
2126 }
2127
2128 return Status;
2129 }
2130
2131 \f
2132 NTSTATUS
2133 NTAPI
2134 NdisIAddDevice(
2135 IN PDRIVER_OBJECT DriverObject,
2136 IN PDEVICE_OBJECT PhysicalDeviceObject)
2137 /*
2138 * FUNCTION: Create a device for an adapter found using PnP
2139 * ARGUMENTS:
2140 * DriverObject = Pointer to the miniport driver object
2141 * PhysicalDeviceObject = Pointer to the PDO for our adapter
2142 */
2143 {
2144 static const WCHAR ClassKeyName[] = {'C','l','a','s','s','\\'};
2145 static const WCHAR LinkageKeyName[] = {'\\','L','i','n','k','a','g','e',0};
2146 PNDIS_M_DRIVER_BLOCK Miniport;
2147 PNDIS_M_DRIVER_BLOCK *MiniportPtr;
2148 WCHAR *LinkageKeyBuffer;
2149 ULONG DriverKeyLength;
2150 RTL_QUERY_REGISTRY_TABLE QueryTable[2];
2151 UNICODE_STRING ExportName;
2152 PDEVICE_OBJECT DeviceObject;
2153 PLOGICAL_ADAPTER Adapter;
2154 NTSTATUS Status;
2155 UINT i;
2156
2157 /*
2158 * Gain the access to the miniport data structure first.
2159 */
2160
2161 MiniportPtr = IoGetDriverObjectExtension(DriverObject, (PVOID)'NMID');
2162 if (MiniportPtr == NULL)
2163 {
2164 NDIS_DbgPrint(MIN_TRACE, ("Can't get driver object extension.\n"));
2165 return NDIS_STATUS_FAILURE;
2166 }
2167 Miniport = *MiniportPtr;
2168
2169 /*
2170 * Get name of the Linkage registry key for our adapter. It's located under
2171 * the driver key for our driver and so we have basicly two ways to do it.
2172 * Either we can use IoOpenDriverRegistryKey or compose it using information
2173 * gathered by IoGetDeviceProperty. I choosed the second because
2174 * IoOpenDriverRegistryKey wasn't implemented at the time of writing.
2175 */
2176
2177 Status = IoGetDeviceProperty(PhysicalDeviceObject, DevicePropertyDriverKeyName,
2178 0, NULL, &DriverKeyLength);
2179 if (Status != STATUS_BUFFER_TOO_SMALL && Status != STATUS_BUFFER_OVERFLOW && Status != STATUS_SUCCESS)
2180 {
2181 NDIS_DbgPrint(MIN_TRACE, ("Can't get miniport driver key length.\n"));
2182 return Status;
2183 }
2184
2185 LinkageKeyBuffer = ExAllocatePool(PagedPool, DriverKeyLength +
2186 sizeof(ClassKeyName) + sizeof(LinkageKeyName));
2187 if (LinkageKeyBuffer == NULL)
2188 {
2189 NDIS_DbgPrint(MIN_TRACE, ("Can't allocate memory for driver key name.\n"));
2190 return STATUS_INSUFFICIENT_RESOURCES;
2191 }
2192
2193 Status = IoGetDeviceProperty(PhysicalDeviceObject, DevicePropertyDriverKeyName,
2194 DriverKeyLength, LinkageKeyBuffer +
2195 (sizeof(ClassKeyName) / sizeof(WCHAR)),
2196 &DriverKeyLength);
2197 if (!NT_SUCCESS(Status))
2198 {
2199 NDIS_DbgPrint(MIN_TRACE, ("Can't get miniport driver key.\n"));
2200 ExFreePool(LinkageKeyBuffer);
2201 return Status;
2202 }
2203
2204 /* Compose the linkage key name. */
2205 RtlCopyMemory(LinkageKeyBuffer, ClassKeyName, sizeof(ClassKeyName));
2206 RtlCopyMemory(LinkageKeyBuffer + ((sizeof(ClassKeyName) + DriverKeyLength) /
2207 sizeof(WCHAR)) - 1, LinkageKeyName, sizeof(LinkageKeyName));
2208
2209 NDIS_DbgPrint(DEBUG_MINIPORT, ("LinkageKey: %S.\n", LinkageKeyBuffer));
2210
2211 /*
2212 * Now open the linkage key and read the "Export" and "RootDevice" values
2213 * which contains device name and root service respectively.
2214 */
2215
2216 RtlZeroMemory(QueryTable, sizeof(QueryTable));
2217 RtlInitUnicodeString(&ExportName, NULL);
2218 QueryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED | RTL_QUERY_REGISTRY_DIRECT;
2219 QueryTable[0].Name = L"Export";
2220 QueryTable[0].EntryContext = &ExportName;
2221
2222 Status = RtlQueryRegistryValues(RTL_REGISTRY_CONTROL, LinkageKeyBuffer,
2223 QueryTable, NULL, NULL);
2224 ExFreePool(LinkageKeyBuffer);
2225 if (!NT_SUCCESS(Status))
2226 {
2227 NDIS_DbgPrint(MIN_TRACE, ("Can't get miniport device name. (%x)\n", Status));
2228 return Status;
2229 }
2230
2231 /*
2232 * Create the device object.
2233 */
2234
2235 NDIS_DbgPrint(MAX_TRACE, ("creating device %wZ\n", &ExportName));
2236
2237 Status = IoCreateDevice(Miniport->DriverObject, sizeof(LOGICAL_ADAPTER),
2238 &ExportName, FILE_DEVICE_PHYSICAL_NETCARD,
2239 0, FALSE, &DeviceObject);
2240 if (!NT_SUCCESS(Status))
2241 {
2242 NDIS_DbgPrint(MIN_TRACE, ("Could not create device object.\n"));
2243 RtlFreeUnicodeString(&ExportName);
2244 return Status;
2245 }
2246
2247 /*
2248 * Initialize the adapter structure.
2249 */
2250
2251 Adapter = (PLOGICAL_ADAPTER)DeviceObject->DeviceExtension;
2252 KeInitializeSpinLock(&Adapter->NdisMiniportBlock.Lock);
2253 InitializeListHead(&Adapter->ProtocolListHead);
2254
2255 Status = IoRegisterDeviceInterface(PhysicalDeviceObject,
2256 &GUID_DEVINTERFACE_NET,
2257 NULL,
2258 &Adapter->NdisMiniportBlock.SymbolicLinkName);
2259
2260 if (!NT_SUCCESS(Status))
2261 {
2262 NDIS_DbgPrint(MIN_TRACE, ("Could not create device interface.\n"));
2263 IoDeleteDevice(DeviceObject);
2264 RtlFreeUnicodeString(&ExportName);
2265 return Status;
2266 }
2267
2268 Adapter->NdisMiniportBlock.DriverHandle = Miniport;
2269 Adapter->NdisMiniportBlock.MiniportName = ExportName;
2270 Adapter->NdisMiniportBlock.DeviceObject = DeviceObject;
2271 Adapter->NdisMiniportBlock.PhysicalDeviceObject = PhysicalDeviceObject;
2272 Adapter->NdisMiniportBlock.NextDeviceObject =
2273 IoAttachDeviceToDeviceStack(Adapter->NdisMiniportBlock.DeviceObject,
2274 PhysicalDeviceObject);
2275
2276 Adapter->NdisMiniportBlock.OldPnPDeviceState = 0;
2277 Adapter->NdisMiniportBlock.PnPDeviceState = NdisPnPDeviceAdded;
2278
2279 for (i = 0; i < NUMBER_OF_WORK_ITEM_TYPES; i++)
2280 Adapter->NdisMiniportBlock.WorkQueue[i].Next = NULL;
2281
2282 KeInitializeTimer(&Adapter->NdisMiniportBlock.WakeUpDpcTimer.Timer);
2283 KeInitializeDpc(&Adapter->NdisMiniportBlock.WakeUpDpcTimer.Dpc, MiniportHangDpc, Adapter);
2284
2285 DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
2286
2287 return STATUS_SUCCESS;
2288 }
2289
2290 \f
2291 /*
2292 * @implemented
2293 */
2294 NDIS_STATUS
2295 EXPORT
2296 NdisMRegisterMiniport(
2297 IN NDIS_HANDLE NdisWrapperHandle,
2298 IN PNDIS_MINIPORT_CHARACTERISTICS MiniportCharacteristics,
2299 IN UINT CharacteristicsLength)
2300 /*
2301 * FUNCTION: Registers a miniport's MiniportXxx entry points with the NDIS library
2302 * ARGUMENTS:
2303 * NdisWrapperHandle = Pointer to handle returned by NdisMInitializeWrapper
2304 * MiniportCharacteristics = Pointer to a buffer with miniport characteristics
2305 * CharacteristicsLength = Number of bytes in characteristics buffer
2306 * RETURNS:
2307 * Status of operation
2308 */
2309 {
2310 UINT MinSize;
2311 PNDIS_M_DRIVER_BLOCK Miniport = GET_MINIPORT_DRIVER(NdisWrapperHandle);
2312 PNDIS_M_DRIVER_BLOCK *MiniportPtr;
2313 NTSTATUS Status;
2314
2315 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
2316
2317 switch (MiniportCharacteristics->MajorNdisVersion)
2318 {
2319 case 0x03:
2320 MinSize = sizeof(NDIS30_MINIPORT_CHARACTERISTICS);
2321 break;
2322
2323 case 0x04:
2324 MinSize = sizeof(NDIS40_MINIPORT_CHARACTERISTICS);
2325 break;
2326
2327 case 0x05:
2328 MinSize = sizeof(NDIS50_MINIPORT_CHARACTERISTICS);
2329 break;
2330
2331 default:
2332 NDIS_DbgPrint(MIN_TRACE, ("Bad miniport characteristics version.\n"));
2333 return NDIS_STATUS_BAD_VERSION;
2334 }
2335
2336 NDIS_DbgPrint(MIN_TRACE, ("Initializing an NDIS %u.%u miniport\n",
2337 MiniportCharacteristics->MajorNdisVersion,
2338 MiniportCharacteristics->MinorNdisVersion));
2339
2340 if (CharacteristicsLength < MinSize)
2341 {
2342 NDIS_DbgPrint(MIN_TRACE, ("Bad miniport characteristics length.\n"));
2343 return NDIS_STATUS_BAD_CHARACTERISTICS;
2344 }
2345
2346 /* Check if mandatory MiniportXxx functions are specified */
2347 if ((!MiniportCharacteristics->HaltHandler) ||
2348 (!MiniportCharacteristics->InitializeHandler)||
2349 (!MiniportCharacteristics->ResetHandler))
2350 {
2351 NDIS_DbgPrint(MIN_TRACE, ("Bad miniport characteristics.\n"));
2352 return NDIS_STATUS_BAD_CHARACTERISTICS;
2353 }
2354
2355 if (MiniportCharacteristics->MajorNdisVersion < 0x05)
2356 {
2357 if ((!MiniportCharacteristics->QueryInformationHandler) ||
2358 (!MiniportCharacteristics->SetInformationHandler))
2359 {
2360 NDIS_DbgPrint(MIN_TRACE, ("Bad miniport characteristics. (Set/Query)\n"));
2361 return NDIS_STATUS_BAD_CHARACTERISTICS;
2362 }
2363 }
2364 else
2365 {
2366 if (((!MiniportCharacteristics->QueryInformationHandler) ||
2367 (!MiniportCharacteristics->SetInformationHandler)) &&
2368 (!MiniportCharacteristics->CoRequestHandler))
2369 {
2370 NDIS_DbgPrint(MIN_TRACE, ("Bad miniport characteristics. (Set/Query)\n"));
2371 return NDIS_STATUS_BAD_CHARACTERISTICS;
2372 }
2373 }
2374
2375 if (MiniportCharacteristics->MajorNdisVersion == 0x03)
2376 {
2377 if (!MiniportCharacteristics->SendHandler)
2378 {
2379 NDIS_DbgPrint(MIN_TRACE, ("Bad miniport characteristics. (NDIS 3.0)\n"));
2380 return NDIS_STATUS_BAD_CHARACTERISTICS;
2381 }
2382 }
2383 else if (MiniportCharacteristics->MajorNdisVersion == 0x04)
2384 {
2385 /* NDIS 4.0 */
2386 if ((!MiniportCharacteristics->SendHandler) &&
2387 (!MiniportCharacteristics->SendPacketsHandler))
2388 {
2389 NDIS_DbgPrint(MIN_TRACE, ("Bad miniport characteristics. (NDIS 4.0)\n"));
2390 return NDIS_STATUS_BAD_CHARACTERISTICS;
2391 }
2392 }
2393 else if (MiniportCharacteristics->MajorNdisVersion == 0x05)
2394 {
2395 /* TODO: Add more checks here */
2396
2397 if ((!MiniportCharacteristics->SendHandler) &&
2398 (!MiniportCharacteristics->SendPacketsHandler) &&
2399 (!MiniportCharacteristics->CoSendPacketsHandler))
2400 {
2401 NDIS_DbgPrint(MIN_TRACE, ("Bad miniport characteristics. (NDIS 5.0)\n"));
2402 return NDIS_STATUS_BAD_CHARACTERISTICS;
2403 }
2404 }
2405
2406 /* TODO: verify NDIS5 and NDIS5.1 */
2407
2408 RtlCopyMemory(&Miniport->MiniportCharacteristics, MiniportCharacteristics, MinSize);
2409
2410 /*
2411 * NOTE: This is VERY unoptimal! Should we store the NDIS_M_DRIVER_BLOCK
2412 * structure in the driver extension or what?
2413 */
2414
2415 Status = IoAllocateDriverObjectExtension(Miniport->DriverObject, (PVOID)'NMID',
2416 sizeof(PNDIS_M_DRIVER_BLOCK), (PVOID*)&MiniportPtr);
2417 if (!NT_SUCCESS(Status))
2418 {
2419 NDIS_DbgPrint(MIN_TRACE, ("Can't allocate driver object extension.\n"));
2420 return NDIS_STATUS_RESOURCES;
2421 }
2422
2423 *MiniportPtr = Miniport;
2424
2425 Miniport->DriverObject->MajorFunction[IRP_MJ_PNP] = NdisIDispatchPnp;
2426 Miniport->DriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = NdisIShutdown;
2427 Miniport->DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = NdisIDeviceIoControl;
2428 Miniport->DriverObject->DriverExtension->AddDevice = NdisIAddDevice;
2429
2430 return NDIS_STATUS_SUCCESS;
2431 }
2432
2433 \f
2434 /*
2435 * @implemented
2436 */
2437 #undef NdisMResetComplete
2438 VOID
2439 EXPORT
2440 NdisMResetComplete(
2441 IN NDIS_HANDLE MiniportAdapterHandle,
2442 IN NDIS_STATUS Status,
2443 IN BOOLEAN AddressingReset)
2444 {
2445 MiniResetComplete(MiniportAdapterHandle, Status, AddressingReset);
2446 }
2447
2448 \f
2449 /*
2450 * @implemented
2451 */
2452 #undef NdisMSendComplete
2453 VOID
2454 EXPORT
2455 NdisMSendComplete(
2456 IN NDIS_HANDLE MiniportAdapterHandle,
2457 IN PNDIS_PACKET Packet,
2458 IN NDIS_STATUS Status)
2459 /*
2460 * FUNCTION: Forwards a message to the initiating protocol saying
2461 * that a packet was handled
2462 * ARGUMENTS:
2463 * NdisAdapterHandle = Handle input to MiniportInitialize
2464 * Packet = Pointer to NDIS packet that was sent
2465 * Status = Status of send operation
2466 */
2467 {
2468 MiniSendComplete(MiniportAdapterHandle, Packet, Status);
2469 }
2470
2471 \f
2472 /*
2473 * @implemented
2474 */
2475 #undef NdisMSendResourcesAvailable
2476 VOID
2477 EXPORT
2478 NdisMSendResourcesAvailable(
2479 IN NDIS_HANDLE MiniportAdapterHandle)
2480 {
2481 MiniSendResourcesAvailable(MiniportAdapterHandle);
2482 }
2483
2484 \f
2485 /*
2486 * @implemented
2487 */
2488 #undef NdisMTransferDataComplete
2489 VOID
2490 EXPORT
2491 NdisMTransferDataComplete(
2492 IN NDIS_HANDLE MiniportAdapterHandle,
2493 IN PNDIS_PACKET Packet,
2494 IN NDIS_STATUS Status,
2495 IN UINT BytesTransferred)
2496 {
2497 MiniTransferDataComplete(MiniportAdapterHandle, Packet, Status, BytesTransferred);
2498 }
2499
2500 \f
2501 /*
2502 * @implemented
2503 */
2504 #undef NdisMSetAttributes
2505 VOID
2506 EXPORT
2507 NdisMSetAttributes(
2508 IN NDIS_HANDLE MiniportAdapterHandle,
2509 IN NDIS_HANDLE MiniportAdapterContext,
2510 IN BOOLEAN BusMaster,
2511 IN NDIS_INTERFACE_TYPE AdapterType)
2512 /*
2513 * FUNCTION: Informs the NDIS library of significant features of the caller's NIC
2514 * ARGUMENTS:
2515 * MiniportAdapterHandle = Handle input to MiniportInitialize
2516 * MiniportAdapterContext = Pointer to context information
2517 * BusMaster = Specifies TRUE if the caller's NIC is a busmaster DMA device
2518 * AdapterType = Specifies the I/O bus interface of the caller's NIC
2519 */
2520 {
2521 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
2522 NdisMSetAttributesEx(MiniportAdapterHandle, MiniportAdapterContext, 0,
2523 BusMaster ? NDIS_ATTRIBUTE_BUS_MASTER : 0,
2524 AdapterType);
2525 }
2526
2527 \f
2528 /*
2529 * @implemented
2530 */
2531 VOID
2532 EXPORT
2533 NdisMSetAttributesEx(
2534 IN NDIS_HANDLE MiniportAdapterHandle,
2535 IN NDIS_HANDLE MiniportAdapterContext,
2536 IN UINT CheckForHangTimeInSeconds OPTIONAL,
2537 IN ULONG AttributeFlags,
2538 IN NDIS_INTERFACE_TYPE AdapterType)
2539 /*
2540 * FUNCTION: Informs the NDIS library of significant features of the caller's NIC
2541 * ARGUMENTS:
2542 * MiniportAdapterHandle = Handle input to MiniportInitialize
2543 * MiniportAdapterContext = Pointer to context information
2544 * CheckForHangTimeInSeconds = Specifies interval in seconds at which
2545 * MiniportCheckForHang should be called
2546 * AttributeFlags = Bitmask that indicates specific attributes
2547 * AdapterType = Specifies the I/O bus interface of the caller's NIC
2548 */
2549 {
2550 PLOGICAL_ADAPTER Adapter = GET_LOGICAL_ADAPTER(MiniportAdapterHandle);
2551
2552 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
2553
2554 Adapter->NdisMiniportBlock.MiniportAdapterContext = MiniportAdapterContext;
2555 Adapter->NdisMiniportBlock.Flags = AttributeFlags;
2556 Adapter->NdisMiniportBlock.AdapterType = AdapterType;
2557 if (CheckForHangTimeInSeconds > 0)
2558 Adapter->NdisMiniportBlock.CheckForHangSeconds = CheckForHangTimeInSeconds;
2559 if (AttributeFlags & NDIS_ATTRIBUTE_INTERMEDIATE_DRIVER)
2560 NDIS_DbgPrint(MAX_TRACE, ("Intermediate drivers not supported yet.\n"));
2561
2562
2563 if (Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.AdapterShutdownHandler)
2564 {
2565 NDIS_DbgPrint(MAX_TRACE, ("Miniport set AdapterShutdownHandler in MiniportCharacteristics\n"));
2566 NdisMRegisterAdapterShutdownHandler(Adapter,
2567 Adapter->NdisMiniportBlock.MiniportAdapterContext,
2568 Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.AdapterShutdownHandler);
2569 }
2570 }
2571
2572 \f
2573 /*
2574 * @implemented
2575 */
2576 VOID
2577 EXPORT
2578 NdisMSleep(
2579 IN ULONG MicrosecondsToSleep)
2580 /*
2581 * FUNCTION: delay the thread's execution for MicrosecondsToSleep
2582 * ARGUMENTS:
2583 * MicrosecondsToSleep: duh...
2584 * NOTES:
2585 * - Because this is a blocking call, current IRQL must be < DISPATCH_LEVEL
2586 */
2587 {
2588 KTIMER Timer;
2589 LARGE_INTEGER DueTime;
2590
2591 PAGED_CODE();
2592
2593 DueTime.QuadPart = (-1) * 10 * MicrosecondsToSleep;
2594
2595 KeInitializeTimer(&Timer);
2596 KeSetTimer(&Timer, DueTime, 0);
2597 KeWaitForSingleObject(&Timer, Executive, KernelMode, FALSE, 0);
2598 }
2599
2600 \f
2601 /*
2602 * @implemented
2603 */
2604 BOOLEAN
2605 EXPORT
2606 NdisMSynchronizeWithInterrupt(
2607 IN PNDIS_MINIPORT_INTERRUPT Interrupt,
2608 IN PVOID SynchronizeFunction,
2609 IN PVOID SynchronizeContext)
2610 {
2611 return(KeSynchronizeExecution(Interrupt->InterruptObject,
2612 (PKSYNCHRONIZE_ROUTINE)SynchronizeFunction,
2613 SynchronizeContext));
2614 }
2615
2616 \f
2617 /*
2618 * @unimplemented
2619 */
2620 NDIS_STATUS
2621 EXPORT
2622 NdisMWriteLogData(
2623 IN NDIS_HANDLE LogHandle,
2624 IN PVOID LogBuffer,
2625 IN UINT LogBufferSize)
2626 {
2627 PUCHAR Buffer = LogBuffer;
2628 UINT i, j, idx;
2629
2630 UNIMPLEMENTED;
2631 for (i = 0; i < LogBufferSize; i += 16)
2632 {
2633 DbgPrint("%08x |", i);
2634 for (j = 0; j < 16; j++)
2635 {
2636 idx = i + j;
2637 if (idx < LogBufferSize)
2638 DbgPrint(" %02x", Buffer[idx]);
2639 else
2640 DbgPrint(" ");
2641 }
2642 DbgPrint(" | ");
2643 for (j = 0; j < 16; j++)
2644 {
2645 idx = i + j;
2646 if (idx == LogBufferSize)
2647 break;
2648 if (Buffer[idx] >= ' ') /* FIXME: not portable! replace by if (isprint(Buffer[idx])) ? */
2649 DbgPrint("%c", Buffer[idx]);
2650 else
2651 DbgPrint(".");
2652 }
2653 DbgPrint("\n");
2654 }
2655
2656 return NDIS_STATUS_FAILURE;
2657 }
2658
2659 \f
2660 /*
2661 * @implemented
2662 */
2663 VOID
2664 EXPORT
2665 NdisTerminateWrapper(
2666 IN NDIS_HANDLE NdisWrapperHandle,
2667 IN PVOID SystemSpecific)
2668 /*
2669 * FUNCTION: Releases resources allocated by a call to NdisInitializeWrapper
2670 * ARGUMENTS:
2671 * NdisWrapperHandle = Handle returned by NdisInitializeWrapper (NDIS_M_DRIVER_BLOCK)
2672 * SystemSpecific = Always NULL
2673 */
2674 {
2675 PNDIS_M_DRIVER_BLOCK Miniport = GET_MINIPORT_DRIVER(NdisWrapperHandle);
2676
2677 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
2678
2679 ExFreePool(Miniport->RegistryPath->Buffer);
2680 ExFreePool(Miniport->RegistryPath);
2681 ExInterlockedRemoveEntryList(&Miniport->ListEntry, &MiniportListLock);
2682 ExFreePool(Miniport);
2683 }
2684
2685
2686 /*
2687 * @implemented
2688 */
2689 NDIS_STATUS
2690 EXPORT
2691 NdisMQueryAdapterInstanceName(
2692 OUT PNDIS_STRING AdapterInstanceName,
2693 IN NDIS_HANDLE MiniportAdapterHandle)
2694 /*
2695 * FUNCTION:
2696 * ARGUMENTS:
2697 * NOTES:
2698 * NDIS 5.0
2699 */
2700 {
2701 PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)MiniportAdapterHandle;
2702 UNICODE_STRING AdapterName;
2703
2704 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
2705
2706 AdapterName.Length = 0;
2707 AdapterName.MaximumLength = Adapter->NdisMiniportBlock.MiniportName.MaximumLength;
2708 AdapterName.Buffer = ExAllocatePool(PagedPool, AdapterName.MaximumLength);
2709 if (!AdapterName.Buffer) {
2710 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources\n"));
2711 return NDIS_STATUS_RESOURCES;
2712 }
2713
2714 RtlCopyUnicodeString(&AdapterName, &Adapter->NdisMiniportBlock.MiniportName);
2715
2716 *AdapterInstanceName = AdapterName;
2717
2718 return NDIS_STATUS_SUCCESS;
2719 }
2720
2721 /*
2722 * @implemented
2723 */
2724 VOID
2725 EXPORT
2726 NdisDeregisterAdapterShutdownHandler(
2727 IN NDIS_HANDLE NdisAdapterHandle)
2728 /*
2729 * FUNCTION:
2730 * ARGUMENTS:
2731 * NOTES:
2732 * NDIS 4.0
2733 */
2734 {
2735 NdisMDeregisterAdapterShutdownHandler(NdisAdapterHandle);
2736 }
2737
2738
2739 /*
2740 * @implemented
2741 */
2742 VOID
2743 EXPORT
2744 NdisRegisterAdapterShutdownHandler(
2745 IN NDIS_HANDLE NdisAdapterHandle,
2746 IN PVOID ShutdownContext,
2747 IN ADAPTER_SHUTDOWN_HANDLER ShutdownHandler)
2748 /*
2749 * FUNCTION:
2750 * ARGUMENTS:
2751 * NOTES:
2752 * NDIS 4.0
2753 */
2754 {
2755 NdisMRegisterAdapterShutdownHandler(NdisAdapterHandle,
2756 ShutdownContext,
2757 ShutdownHandler);
2758 }
2759
2760 /*
2761 * @implemented
2762 */
2763 VOID
2764 EXPORT
2765 NdisMGetDeviceProperty(
2766 IN NDIS_HANDLE MiniportAdapterHandle,
2767 IN OUT PDEVICE_OBJECT *PhysicalDeviceObject OPTIONAL,
2768 IN OUT PDEVICE_OBJECT *FunctionalDeviceObject OPTIONAL,
2769 IN OUT PDEVICE_OBJECT *NextDeviceObject OPTIONAL,
2770 IN OUT PCM_RESOURCE_LIST *AllocatedResources OPTIONAL,
2771 IN OUT PCM_RESOURCE_LIST *AllocatedResourcesTranslated OPTIONAL)
2772 /*
2773 * FUNCTION:
2774 * ARGUMENTS:
2775 * NOTES:
2776 * NDIS 5.0
2777 */
2778 {
2779 PLOGICAL_ADAPTER Adapter = MiniportAdapterHandle;
2780
2781 NDIS_DbgPrint(MAX_TRACE, ("Called\n"));
2782
2783 if (PhysicalDeviceObject != NULL)
2784 *PhysicalDeviceObject = Adapter->NdisMiniportBlock.PhysicalDeviceObject;
2785
2786 if (FunctionalDeviceObject != NULL)
2787 *FunctionalDeviceObject = Adapter->NdisMiniportBlock.DeviceObject;
2788
2789 if (NextDeviceObject != NULL)
2790 *NextDeviceObject = Adapter->NdisMiniportBlock.NextDeviceObject;
2791
2792 if (AllocatedResources != NULL)
2793 *AllocatedResources = Adapter->NdisMiniportBlock.AllocatedResources;
2794
2795 if (AllocatedResourcesTranslated != NULL)
2796 *AllocatedResourcesTranslated = Adapter->NdisMiniportBlock.AllocatedResourcesTranslated;
2797 }
2798
2799 /*
2800 * @implemented
2801 */
2802 VOID
2803 EXPORT
2804 NdisMRegisterUnloadHandler(
2805 IN NDIS_HANDLE NdisWrapperHandle,
2806 IN PDRIVER_UNLOAD UnloadHandler)
2807 /*
2808 * FUNCTION:
2809 * ARGUMENTS:
2810 * NOTES:
2811 * NDIS 5.0
2812 */
2813 {
2814 PNDIS_M_DRIVER_BLOCK DriverBlock = NdisWrapperHandle;
2815
2816 NDIS_DbgPrint(MAX_TRACE, ("Miniport registered unload handler\n"));
2817
2818 DriverBlock->DriverObject->DriverUnload = UnloadHandler;
2819 }
2820
2821 /*
2822 * @implemented
2823 */
2824 NDIS_STATUS
2825 EXPORT
2826 NdisMRegisterDevice(
2827 IN NDIS_HANDLE NdisWrapperHandle,
2828 IN PNDIS_STRING DeviceName,
2829 IN PNDIS_STRING SymbolicName,
2830 IN PDRIVER_DISPATCH MajorFunctions[],
2831 OUT PDEVICE_OBJECT *pDeviceObject,
2832 OUT NDIS_HANDLE *NdisDeviceHandle)
2833 /*
2834 * FUNCTION:
2835 * ARGUMENTS:
2836 * NOTES:
2837 * NDIS 5.0
2838 */
2839 {
2840 PNDIS_M_DRIVER_BLOCK DriverBlock = NdisWrapperHandle;
2841 PNDIS_M_DEVICE_BLOCK DeviceBlock;
2842 PDEVICE_OBJECT DeviceObject;
2843 NDIS_STATUS Status;
2844 UINT i;
2845
2846 NDIS_DbgPrint(MAX_TRACE, ("Called\n"));
2847
2848 Status = IoCreateDevice(DriverBlock->DriverObject,
2849 0, /* This space is reserved for us. Should we use it? */
2850 DeviceName,
2851 FILE_DEVICE_NETWORK,
2852 0,
2853 FALSE,
2854 &DeviceObject);
2855
2856 if (!NT_SUCCESS(Status))
2857 {
2858 NDIS_DbgPrint(MIN_TRACE, ("IoCreateDevice failed (%x)\n", Status));
2859 return Status;
2860 }
2861
2862 Status = IoCreateSymbolicLink(SymbolicName, DeviceName);
2863
2864 if (!NT_SUCCESS(Status))
2865 {
2866 NDIS_DbgPrint(MIN_TRACE, ("IoCreateSymbolicLink failed (%x)\n", Status));
2867 IoDeleteDevice(DeviceObject);
2868 return Status;
2869 }
2870
2871 DeviceBlock = ExAllocatePool(NonPagedPool, sizeof(NDIS_M_DEVICE_BLOCK));
2872
2873 if (!DeviceBlock)
2874 {
2875 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources\n"));
2876 IoDeleteDevice(DeviceObject);
2877 IoDeleteSymbolicLink(SymbolicName);
2878 return NDIS_STATUS_RESOURCES;
2879 }
2880
2881 for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
2882 DriverBlock->DriverObject->MajorFunction[i] = MajorFunctions[i];
2883
2884 DriverBlock->DriverObject->MajorFunction[IRP_MJ_PNP] = NdisIDispatchPnp;
2885
2886 DeviceBlock->DeviceObject = DeviceObject;
2887 DeviceBlock->SymbolicName = SymbolicName;
2888
2889 *pDeviceObject = DeviceObject;
2890 *NdisDeviceHandle = DeviceBlock;
2891
2892 return NDIS_STATUS_SUCCESS;
2893 }
2894
2895 /*
2896 * @implemented
2897 */
2898 NDIS_STATUS
2899 EXPORT
2900 NdisMDeregisterDevice(
2901 IN NDIS_HANDLE NdisDeviceHandle)
2902 /*
2903 * FUNCTION:
2904 * ARGUMENTS:
2905 * NOTES:
2906 * NDIS 5.0
2907 */
2908 {
2909 PNDIS_M_DEVICE_BLOCK DeviceBlock = NdisDeviceHandle;
2910
2911 IoDeleteDevice(DeviceBlock->DeviceObject);
2912
2913 IoDeleteSymbolicLink(DeviceBlock->SymbolicName);
2914
2915 ExFreePool(DeviceBlock);
2916
2917 return NDIS_STATUS_SUCCESS;
2918 }
2919
2920 /*
2921 * @implemented
2922 */
2923 NDIS_STATUS
2924 EXPORT
2925 NdisQueryAdapterInstanceName(
2926 OUT PNDIS_STRING AdapterInstanceName,
2927 IN NDIS_HANDLE NdisBindingHandle)
2928 /*
2929 * FUNCTION:
2930 * ARGUMENTS:
2931 * NOTES:
2932 * NDIS 5.0
2933 */
2934 {
2935 PADAPTER_BINDING AdapterBinding = NdisBindingHandle;
2936 PLOGICAL_ADAPTER Adapter = AdapterBinding->Adapter;
2937
2938 return NdisMQueryAdapterInstanceName(AdapterInstanceName,
2939 Adapter);
2940 }
2941
2942 /*
2943 * @implemented
2944 */
2945 VOID
2946 EXPORT
2947 NdisCompletePnPEvent(
2948 IN NDIS_STATUS Status,
2949 IN NDIS_HANDLE NdisBindingHandle,
2950 IN PNET_PNP_EVENT NetPnPEvent)
2951 /*
2952 * FUNCTION:
2953 * ARGUMENTS:
2954 * NOTES:
2955 * NDIS 5.0
2956 */
2957 {
2958 PIRP Irp = (PIRP)NetPnPEvent->NdisReserved[0];
2959 PLIST_ENTRY CurrentEntry = (PLIST_ENTRY)NetPnPEvent->NdisReserved[1];
2960 PADAPTER_BINDING AdapterBinding = NdisBindingHandle;
2961 PLOGICAL_ADAPTER Adapter = AdapterBinding->Adapter;
2962 NDIS_STATUS NdisStatus;
2963
2964 if (Status != NDIS_STATUS_SUCCESS)
2965 {
2966 if (NetPnPEvent->Buffer) ExFreePool(NetPnPEvent->Buffer);
2967 ExFreePool(NetPnPEvent);
2968 Irp->IoStatus.Status = Status;
2969 IoCompleteRequest(Irp, IO_NO_INCREMENT);
2970 return;
2971 }
2972
2973 while (CurrentEntry != &Adapter->ProtocolListHead)
2974 {
2975 AdapterBinding = CONTAINING_RECORD(CurrentEntry, ADAPTER_BINDING, AdapterListEntry);
2976
2977 NdisStatus = (*AdapterBinding->ProtocolBinding->Chars.PnPEventHandler)(
2978 AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
2979 NetPnPEvent);
2980
2981 if (NdisStatus == NDIS_STATUS_PENDING)
2982 {
2983 NetPnPEvent->NdisReserved[1] = (ULONG_PTR)CurrentEntry->Flink;
2984 return;
2985 }
2986 else if (NdisStatus != NDIS_STATUS_SUCCESS)
2987 {
2988 if (NetPnPEvent->Buffer) ExFreePool(NetPnPEvent->Buffer);
2989 ExFreePool(NetPnPEvent);
2990 Irp->IoStatus.Status = NdisStatus;
2991 IoCompleteRequest(Irp, IO_NO_INCREMENT);
2992 return;
2993 }
2994
2995 CurrentEntry = CurrentEntry->Flink;
2996 }
2997
2998 if (NetPnPEvent->Buffer) ExFreePool(NetPnPEvent->Buffer);
2999 ExFreePool(NetPnPEvent);
3000
3001 Irp->IoStatus.Status = NDIS_STATUS_SUCCESS;
3002 IoCompleteRequest(Irp, IO_NO_INCREMENT);
3003 }
3004
3005 /*
3006 * @implemented
3007 */
3008 VOID
3009 EXPORT
3010 NdisCancelSendPackets(
3011 IN NDIS_HANDLE NdisBindingHandle,
3012 IN PVOID CancelId)
3013 {
3014 PADAPTER_BINDING AdapterBinding = NdisBindingHandle;
3015 PLOGICAL_ADAPTER Adapter = AdapterBinding->Adapter;
3016
3017 NDIS_DbgPrint(MAX_TRACE, ("Called for ID %x.\n", CancelId));
3018
3019 if (Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.CancelSendPacketsHandler)
3020 {
3021 (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.CancelSendPacketsHandler)(
3022 Adapter->NdisMiniportBlock.MiniportAdapterContext,
3023 CancelId);
3024 }
3025 }
3026
3027
3028 /*
3029 * @implemented
3030 */
3031 NDIS_HANDLE
3032 EXPORT
3033 NdisIMGetBindingContext(
3034 IN NDIS_HANDLE NdisBindingHandle)
3035 /*
3036 * FUNCTION:
3037 * ARGUMENTS:
3038 * NOTES:
3039 * NDIS 5.0
3040 */
3041 {
3042 PADAPTER_BINDING AdapterBinding = NdisBindingHandle;
3043 PLOGICAL_ADAPTER Adapter = AdapterBinding->Adapter;
3044
3045 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
3046
3047 return Adapter->NdisMiniportBlock.DeviceContext;
3048 }
3049
3050
3051 /*
3052 * @implemented
3053 */
3054 NDIS_HANDLE
3055 EXPORT
3056 NdisIMGetDeviceContext(
3057 IN NDIS_HANDLE MiniportAdapterHandle)
3058 /*
3059 * FUNCTION:
3060 * ARGUMENTS:
3061 * NOTES:
3062 * NDIS 5.0
3063 */
3064 {
3065 PLOGICAL_ADAPTER Adapter = MiniportAdapterHandle;
3066
3067 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
3068
3069 return Adapter->NdisMiniportBlock.DeviceContext;
3070 }
3071
3072 /* EOF */
3073