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