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