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