4492caffe32a30ee71b99c09317545c8396a7129
[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
1782 /*
1783 * Prepare wrapper context used by HW and configuration routines.
1784 */
1785
1786 NDIS_DbgPrint(DEBUG_MINIPORT, ("Start Device %wZ\n", &Adapter->NdisMiniportBlock.MiniportName));
1787
1788 NDIS_DbgPrint(MAX_TRACE, ("Inserting adapter 0x%x into adapter list\n", Adapter));
1789
1790 /* Put adapter in global adapter list */
1791 ExInterlockedInsertTailList(&AdapterListHead, &Adapter->ListEntry, &AdapterListLock);
1792
1793 Status = IoOpenDeviceRegistryKey(
1794 Adapter->NdisMiniportBlock.PhysicalDeviceObject, PLUGPLAY_REGKEY_DRIVER,
1795 KEY_ALL_ACCESS, &WrapperContext.RegistryHandle);
1796 if (!NT_SUCCESS(Status))
1797 {
1798 NDIS_DbgPrint(MIN_TRACE,("failed to open adapter-specific reg key\n"));
1799 ExInterlockedRemoveEntryList( &Adapter->ListEntry, &AdapterListLock );
1800 return Status;
1801 }
1802
1803 NDIS_DbgPrint(MAX_TRACE, ("opened device reg key\n"));
1804
1805 WrapperContext.DeviceObject = Adapter->NdisMiniportBlock.DeviceObject;
1806
1807 /*
1808 * Store the adapter resources used by HW routines such as
1809 * NdisMQueryAdapterResources.
1810 */
1811
1812 if (Stack->Parameters.StartDevice.AllocatedResources != NULL)
1813 {
1814 ResourceCount = Stack->Parameters.StartDevice.AllocatedResources->List[0].
1815 PartialResourceList.Count;
1816 ResourceListSize =
1817 FIELD_OFFSET(CM_RESOURCE_LIST, List[0].PartialResourceList.
1818 PartialDescriptors[ResourceCount]);
1819
1820 Adapter->NdisMiniportBlock.AllocatedResources =
1821 ExAllocatePool(PagedPool, ResourceListSize);
1822 if (Adapter->NdisMiniportBlock.AllocatedResources == NULL)
1823 {
1824 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources\n"));
1825 ExInterlockedRemoveEntryList( &Adapter->ListEntry, &AdapterListLock );
1826 return STATUS_INSUFFICIENT_RESOURCES;
1827 }
1828
1829 Adapter->NdisMiniportBlock.Resources =
1830 ExAllocatePool(PagedPool, ResourceListSize);
1831 if (!Adapter->NdisMiniportBlock.Resources)
1832 {
1833 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources\n"));
1834 ExFreePool(Adapter->NdisMiniportBlock.AllocatedResources);
1835 ExInterlockedRemoveEntryList(&Adapter->ListEntry, &AdapterListLock);
1836 return STATUS_INSUFFICIENT_RESOURCES;
1837 }
1838
1839 RtlCopyMemory(Adapter->NdisMiniportBlock.Resources,
1840 Stack->Parameters.StartDevice.AllocatedResources,
1841 ResourceListSize);
1842
1843 RtlCopyMemory(Adapter->NdisMiniportBlock.AllocatedResources,
1844 Stack->Parameters.StartDevice.AllocatedResources,
1845 ResourceListSize);
1846 }
1847
1848 if (Stack->Parameters.StartDevice.AllocatedResourcesTranslated != NULL)
1849 {
1850 ResourceCount = Stack->Parameters.StartDevice.AllocatedResourcesTranslated->List[0].
1851 PartialResourceList.Count;
1852 ResourceListSize =
1853 FIELD_OFFSET(CM_RESOURCE_LIST, List[0].PartialResourceList.
1854 PartialDescriptors[ResourceCount]);
1855
1856 Adapter->NdisMiniportBlock.AllocatedResourcesTranslated =
1857 ExAllocatePool(PagedPool, ResourceListSize);
1858 if (Adapter->NdisMiniportBlock.AllocatedResourcesTranslated == NULL)
1859 {
1860 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources\n"));
1861 ExInterlockedRemoveEntryList( &Adapter->ListEntry, &AdapterListLock );
1862 return STATUS_INSUFFICIENT_RESOURCES;
1863 }
1864
1865 RtlCopyMemory(Adapter->NdisMiniportBlock.AllocatedResourcesTranslated,
1866 Stack->Parameters.StartDevice.AllocatedResourcesTranslated,
1867 ResourceListSize);
1868 }
1869
1870 /*
1871 * Store the Bus Type, Bus Number and Slot information. It's used by
1872 * the hardware routines then.
1873 */
1874
1875 NdisOpenConfiguration(&NdisStatus, &ConfigHandle, (NDIS_HANDLE)&WrapperContext);
1876 if (NdisStatus != NDIS_STATUS_SUCCESS)
1877 {
1878 NDIS_DbgPrint(MIN_TRACE, ("Failed to open configuration key\n"));
1879 ExInterlockedRemoveEntryList( &Adapter->ListEntry, &AdapterListLock );
1880 return NdisStatus;
1881 }
1882
1883 Size = sizeof(ULONG);
1884 Status = IoGetDeviceProperty(Adapter->NdisMiniportBlock.PhysicalDeviceObject,
1885 DevicePropertyLegacyBusType, Size,
1886 &Adapter->NdisMiniportBlock.BusType, &Size);
1887 if (!NT_SUCCESS(Status) || (INTERFACE_TYPE)Adapter->NdisMiniportBlock.BusType == InterfaceTypeUndefined)
1888 {
1889 NdisInitUnicodeString(&ParamName, L"BusType");
1890 NdisReadConfiguration(&NdisStatus, &ConfigParam, ConfigHandle,
1891 &ParamName, NdisParameterInteger);
1892 if (NdisStatus == NDIS_STATUS_SUCCESS)
1893 Adapter->NdisMiniportBlock.BusType = ConfigParam->ParameterData.IntegerData;
1894 else
1895 Adapter->NdisMiniportBlock.BusType = Isa;
1896 }
1897
1898 Status = IoGetDeviceProperty(Adapter->NdisMiniportBlock.PhysicalDeviceObject,
1899 DevicePropertyBusNumber, Size,
1900 &Adapter->NdisMiniportBlock.BusNumber, &Size);
1901 if (!NT_SUCCESS(Status) || Adapter->NdisMiniportBlock.BusNumber == 0xFFFFFFF0)
1902 {
1903 NdisInitUnicodeString(&ParamName, L"BusNumber");
1904 NdisReadConfiguration(&NdisStatus, &ConfigParam, ConfigHandle,
1905 &ParamName, NdisParameterInteger);
1906 if (NdisStatus == NDIS_STATUS_SUCCESS)
1907 Adapter->NdisMiniportBlock.BusNumber = ConfigParam->ParameterData.IntegerData;
1908 else
1909 Adapter->NdisMiniportBlock.BusNumber = 0;
1910 }
1911 WrapperContext.BusNumber = Adapter->NdisMiniportBlock.BusNumber;
1912
1913 Status = IoGetDeviceProperty(Adapter->NdisMiniportBlock.PhysicalDeviceObject,
1914 DevicePropertyAddress, Size,
1915 &Adapter->NdisMiniportBlock.SlotNumber, &Size);
1916 if (!NT_SUCCESS(Status) || Adapter->NdisMiniportBlock.SlotNumber == (NDIS_INTERFACE_TYPE)-1)
1917 {
1918 NdisInitUnicodeString(&ParamName, L"SlotNumber");
1919 NdisReadConfiguration(&NdisStatus, &ConfigParam, ConfigHandle,
1920 &ParamName, NdisParameterInteger);
1921 if (NdisStatus == NDIS_STATUS_SUCCESS)
1922 Adapter->NdisMiniportBlock.SlotNumber = ConfigParam->ParameterData.IntegerData;
1923 else
1924 Adapter->NdisMiniportBlock.SlotNumber = 0;
1925 }
1926 else
1927 {
1928 /* Convert slotnumber to PCI_SLOT_NUMBER */
1929 ULONG PciSlotNumber = Adapter->NdisMiniportBlock.SlotNumber;
1930 PCI_SLOT_NUMBER SlotNumber;
1931
1932 SlotNumber.u.AsULONG = 0;
1933 SlotNumber.u.bits.DeviceNumber = (PciSlotNumber >> 16) & 0xFFFF;
1934 SlotNumber.u.bits.FunctionNumber = PciSlotNumber & 0xFFFF;
1935
1936 Adapter->NdisMiniportBlock.SlotNumber = SlotNumber.u.AsULONG;
1937 }
1938 WrapperContext.SlotNumber = Adapter->NdisMiniportBlock.SlotNumber;
1939
1940 NdisCloseConfiguration(ConfigHandle);
1941
1942 /* Set handlers (some NDIS macros require these) */
1943 Adapter->NdisMiniportBlock.EthRxCompleteHandler = EthFilterDprIndicateReceiveComplete;
1944 Adapter->NdisMiniportBlock.EthRxIndicateHandler = EthFilterDprIndicateReceive;
1945 Adapter->NdisMiniportBlock.SendCompleteHandler = MiniSendComplete;
1946 Adapter->NdisMiniportBlock.SendResourcesHandler = MiniSendResourcesAvailable;
1947 Adapter->NdisMiniportBlock.ResetCompleteHandler = MiniResetComplete;
1948 Adapter->NdisMiniportBlock.TDCompleteHandler = MiniTransferDataComplete;
1949 Adapter->NdisMiniportBlock.PacketIndicateHandler= MiniIndicateReceivePacket;
1950 Adapter->NdisMiniportBlock.StatusHandler = MiniStatus;
1951 Adapter->NdisMiniportBlock.StatusCompleteHandler= MiniStatusComplete;
1952 Adapter->NdisMiniportBlock.SendPacketsHandler = ProSendPackets;
1953 Adapter->NdisMiniportBlock.QueryCompleteHandler = MiniRequestComplete;
1954 Adapter->NdisMiniportBlock.SetCompleteHandler = MiniRequestComplete;
1955
1956 /*
1957 * Call MiniportInitialize.
1958 */
1959
1960 NDIS_DbgPrint(MID_TRACE, ("calling MiniportInitialize\n"));
1961 NdisStatus = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.InitializeHandler)(
1962 &OpenErrorStatus, &SelectedMediumIndex, &MediaArray[0],
1963 MEDIA_ARRAY_SIZE, Adapter, (NDIS_HANDLE)&WrapperContext);
1964
1965 ZwClose(WrapperContext.RegistryHandle);
1966
1967 if (NdisStatus != NDIS_STATUS_SUCCESS)
1968 {
1969 NDIS_DbgPrint(MIN_TRACE, ("MiniportInitialize() failed for an adapter.\n"));
1970 ExInterlockedRemoveEntryList( &Adapter->ListEntry, &AdapterListLock );
1971 if (Adapter->NdisMiniportBlock.Interrupt)
1972 {
1973 KeBugCheckEx(BUGCODE_ID_DRIVER,
1974 (ULONG_PTR)Adapter,
1975 (ULONG_PTR)Adapter->NdisMiniportBlock.Interrupt,
1976 (ULONG_PTR)Adapter->NdisMiniportBlock.TimerQueue,
1977 1);
1978 }
1979 if (Adapter->NdisMiniportBlock.TimerQueue)
1980 {
1981 KeBugCheckEx(BUGCODE_ID_DRIVER,
1982 (ULONG_PTR)Adapter,
1983 (ULONG_PTR)Adapter->NdisMiniportBlock.Interrupt,
1984 (ULONG_PTR)Adapter->NdisMiniportBlock.TimerQueue,
1985 1);
1986 }
1987 return NdisStatus;
1988 }
1989
1990 if (SelectedMediumIndex >= MEDIA_ARRAY_SIZE)
1991 {
1992 NDIS_DbgPrint(MIN_TRACE, ("MiniportInitialize() selected a bad index\n"));
1993 ExInterlockedRemoveEntryList( &Adapter->ListEntry, &AdapterListLock );
1994 return NDIS_STATUS_UNSUPPORTED_MEDIA;
1995 }
1996
1997 Adapter->NdisMiniportBlock.MediaType = MediaArray[SelectedMediumIndex];
1998
1999 switch (Adapter->NdisMiniportBlock.MediaType)
2000 {
2001 case NdisMedium802_3:
2002 Adapter->MediumHeaderSize = 14; /* XXX figure out what to do about LLC */
2003 AddressOID = OID_802_3_CURRENT_ADDRESS;
2004 Adapter->AddressLength = ETH_LENGTH_OF_ADDRESS;
2005 NdisStatus = DoQueries(Adapter, AddressOID);
2006 if (NdisStatus == NDIS_STATUS_SUCCESS)
2007 {
2008 NdisStatus = MiniQueryInformation(Adapter, OID_802_3_MAXIMUM_LIST_SIZE, sizeof(UINT),
2009 &MaxMulticastAddresses, &BytesWritten);
2010
2011 if (NdisStatus != NDIS_STATUS_SUCCESS)
2012 {
2013 ExInterlockedRemoveEntryList( &Adapter->ListEntry, &AdapterListLock );
2014 NDIS_DbgPrint(MIN_TRACE, ("MiniQueryInformation failed (%x)\n", NdisStatus));
2015 return NdisStatus;
2016 }
2017
2018 Success = EthCreateFilter(MaxMulticastAddresses,
2019 Adapter->Address.Type.Medium802_3,
2020 &Adapter->NdisMiniportBlock.EthDB);
2021 if (Success)
2022 ((PETHI_FILTER)Adapter->NdisMiniportBlock.EthDB)->Miniport = (PNDIS_MINIPORT_BLOCK)Adapter;
2023 else
2024 NdisStatus = NDIS_STATUS_RESOURCES;
2025 }
2026 break;
2027
2028 default:
2029 /* FIXME: Support other types of media */
2030 NDIS_DbgPrint(MIN_TRACE, ("error: unsupported media\n"));
2031 ASSERT(FALSE);
2032 ExInterlockedRemoveEntryList( &Adapter->ListEntry, &AdapterListLock );
2033 return STATUS_UNSUCCESSFUL;
2034 }
2035
2036 if (NdisStatus != NDIS_STATUS_SUCCESS)
2037 {
2038 NDIS_DbgPrint(MIN_TRACE, ("couldn't create filter (%x)\n", NdisStatus));
2039 return NdisStatus;
2040 }
2041
2042 /* Check for a hang every two seconds if it wasn't set in MiniportInitialize */
2043 if (Adapter->NdisMiniportBlock.CheckForHangSeconds == 0)
2044 Adapter->NdisMiniportBlock.CheckForHangSeconds = 2;
2045
2046 Adapter->NdisMiniportBlock.OldPnPDeviceState = Adapter->NdisMiniportBlock.PnPDeviceState;
2047 Adapter->NdisMiniportBlock.PnPDeviceState = NdisPnPDeviceStarted;
2048
2049 IoSetDeviceInterfaceState(&Adapter->NdisMiniportBlock.SymbolicLinkName, TRUE);
2050
2051 Timeout.QuadPart = Int32x32To64(Adapter->NdisMiniportBlock.CheckForHangSeconds, -1000000);
2052 KeSetTimerEx(&Adapter->NdisMiniportBlock.WakeUpDpcTimer.Timer, Timeout,
2053 Adapter->NdisMiniportBlock.CheckForHangSeconds * 1000,
2054 &Adapter->NdisMiniportBlock.WakeUpDpcTimer.Dpc);
2055
2056 /* Put adapter in adapter list for this miniport */
2057 ExInterlockedInsertTailList(&Adapter->NdisMiniportBlock.DriverHandle->DeviceList, &Adapter->MiniportListEntry, &Adapter->NdisMiniportBlock.DriverHandle->Lock);
2058
2059 return STATUS_SUCCESS;
2060 }
2061
2062 \f
2063 NTSTATUS
2064 NTAPI
2065 NdisIPnPStopDevice(
2066 IN PDEVICE_OBJECT DeviceObject,
2067 PIRP Irp)
2068 /*
2069 * FUNCTION: Handle the PnP stop device event
2070 * ARGUMENTS:
2071 * DeviceObejct = Functional Device Object
2072 * Irp = IRP_MN_STOP_DEVICE I/O request packet
2073 * RETURNS:
2074 * Status of operation
2075 */
2076 {
2077 PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)DeviceObject->DeviceExtension;
2078
2079 /* Remove adapter from adapter list for this miniport */
2080 ExInterlockedRemoveEntryList(&Adapter->MiniportListEntry, &Adapter->NdisMiniportBlock.DriverHandle->Lock);
2081
2082 /* Remove adapter from global adapter list */
2083 ExInterlockedRemoveEntryList(&Adapter->ListEntry, &AdapterListLock);
2084
2085 KeCancelTimer(&Adapter->NdisMiniportBlock.WakeUpDpcTimer.Timer);
2086
2087 (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.HaltHandler)(Adapter);
2088
2089 IoSetDeviceInterfaceState(&Adapter->NdisMiniportBlock.SymbolicLinkName, FALSE);
2090
2091 if (Adapter->NdisMiniportBlock.AllocatedResources)
2092 {
2093 ExFreePool(Adapter->NdisMiniportBlock.AllocatedResources);
2094 Adapter->NdisMiniportBlock.AllocatedResources = NULL;
2095 }
2096 if (Adapter->NdisMiniportBlock.AllocatedResourcesTranslated)
2097 {
2098 ExFreePool(Adapter->NdisMiniportBlock.AllocatedResourcesTranslated);
2099 Adapter->NdisMiniportBlock.AllocatedResourcesTranslated = NULL;
2100 }
2101
2102 if (Adapter->NdisMiniportBlock.Resources)
2103 {
2104 ExFreePool(Adapter->NdisMiniportBlock.Resources);
2105 Adapter->NdisMiniportBlock.Resources = NULL;
2106 }
2107
2108 if (Adapter->NdisMiniportBlock.EthDB)
2109 {
2110 EthDeleteFilter(Adapter->NdisMiniportBlock.EthDB);
2111 Adapter->NdisMiniportBlock.EthDB = NULL;
2112 }
2113
2114 Adapter->NdisMiniportBlock.OldPnPDeviceState = Adapter->NdisMiniportBlock.PnPDeviceState;
2115 Adapter->NdisMiniportBlock.PnPDeviceState = NdisPnPDeviceStopped;
2116
2117 return STATUS_SUCCESS;
2118 }
2119
2120 NTSTATUS
2121 NTAPI
2122 NdisIShutdown(
2123 IN PDEVICE_OBJECT DeviceObject,
2124 PIRP Irp)
2125 {
2126 PLOGICAL_ADAPTER Adapter = DeviceObject->DeviceExtension;
2127 PMINIPORT_BUGCHECK_CONTEXT Context = Adapter->BugcheckContext;
2128 ADAPTER_SHUTDOWN_HANDLER ShutdownHandler = Context->ShutdownHandler;
2129
2130 ASSERT(ShutdownHandler);
2131
2132 ShutdownHandler(Context->DriverContext);
2133
2134 Irp->IoStatus.Status = STATUS_SUCCESS;
2135 Irp->IoStatus.Information = 0;
2136
2137 IoCompleteRequest(Irp, IO_NO_INCREMENT);
2138
2139 return STATUS_SUCCESS;
2140 }
2141
2142 NTSTATUS
2143 NTAPI
2144 NdisIDeviceIoControl(
2145 IN PDEVICE_OBJECT DeviceObject,
2146 PIRP Irp)
2147 {
2148 PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)DeviceObject->DeviceExtension;
2149 PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
2150 NDIS_STATUS Status = STATUS_NOT_SUPPORTED;
2151 ULONG Written;
2152
2153 Irp->IoStatus.Information = 0;
2154
2155 ASSERT(Adapter);
2156
2157 switch (Stack->Parameters.DeviceIoControl.IoControlCode)
2158 {
2159 case IOCTL_NDIS_QUERY_GLOBAL_STATS:
2160 Status = MiniQueryInformation(Adapter,
2161 *(PNDIS_OID)Irp->AssociatedIrp.SystemBuffer,
2162 Stack->Parameters.DeviceIoControl.OutputBufferLength,
2163 MmGetSystemAddressForMdl(Irp->MdlAddress),
2164 &Written);
2165 Irp->IoStatus.Information = Written;
2166 break;
2167
2168 default:
2169 ASSERT(FALSE);
2170 break;
2171 }
2172
2173 if (Status != NDIS_STATUS_PENDING)
2174 {
2175 Irp->IoStatus.Status = Status;
2176 IoCompleteRequest(Irp, IO_NO_INCREMENT);
2177 }
2178 else
2179 IoMarkIrpPending(Irp);
2180
2181 return Status;
2182 }
2183
2184 \f
2185 NTSTATUS
2186 NTAPI
2187 NdisIDispatchPnp(
2188 IN PDEVICE_OBJECT DeviceObject,
2189 PIRP Irp)
2190 {
2191 PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
2192 PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)DeviceObject->DeviceExtension;
2193 NTSTATUS Status;
2194
2195 switch (Stack->MinorFunction)
2196 {
2197 case IRP_MN_START_DEVICE:
2198 Status = NdisIForwardIrpAndWait(Adapter, Irp);
2199 if (NT_SUCCESS(Status) && NT_SUCCESS(Irp->IoStatus.Status))
2200 {
2201 Status = NdisIPnPStartDevice(DeviceObject, Irp);
2202 }
2203 else
2204 NDIS_DbgPrint(MIN_TRACE, ("Lower driver failed device start\n"));
2205 Irp->IoStatus.Status = Status;
2206 IoCompleteRequest(Irp, IO_NO_INCREMENT);
2207 break;
2208
2209 case IRP_MN_STOP_DEVICE:
2210 Status = NdisIForwardIrpAndWait(Adapter, Irp);
2211 if (NT_SUCCESS(Status) && NT_SUCCESS(Irp->IoStatus.Status))
2212 {
2213 Status = NdisIPnPStopDevice(DeviceObject, Irp);
2214 }
2215 else
2216 NDIS_DbgPrint(MIN_TRACE, ("Lower driver failed device stop\n"));
2217 Irp->IoStatus.Status = Status;
2218 IoCompleteRequest(Irp, IO_NO_INCREMENT);
2219 break;
2220
2221 case IRP_MN_QUERY_REMOVE_DEVICE:
2222 case IRP_MN_QUERY_STOP_DEVICE:
2223 Status = NdisIPnPQueryStopDevice(DeviceObject, Irp);
2224 Irp->IoStatus.Status = Status;
2225 IoCompleteRequest(Irp, IO_NO_INCREMENT);
2226 break;
2227
2228 case IRP_MN_CANCEL_REMOVE_DEVICE:
2229 case IRP_MN_CANCEL_STOP_DEVICE:
2230 Status = NdisIPnPCancelStopDevice(DeviceObject, Irp);
2231 Irp->IoStatus.Status = Status;
2232 IoCompleteRequest(Irp, IO_NO_INCREMENT);
2233 break;
2234
2235 case IRP_MN_QUERY_PNP_DEVICE_STATE:
2236 Status = NDIS_STATUS_SUCCESS;
2237 Irp->IoStatus.Status = Status;
2238 Irp->IoStatus.Information |= Adapter->NdisMiniportBlock.PnPFlags;
2239 IoCompleteRequest(Irp, IO_NO_INCREMENT);
2240 break;
2241
2242 default:
2243 IoSkipCurrentIrpStackLocation(Irp);
2244 Status = IoCallDriver(Adapter->NdisMiniportBlock.NextDeviceObject, Irp);
2245 break;
2246 }
2247
2248 return Status;
2249 }
2250
2251 \f
2252 NTSTATUS
2253 NTAPI
2254 NdisIAddDevice(
2255 IN PDRIVER_OBJECT DriverObject,
2256 IN PDEVICE_OBJECT PhysicalDeviceObject)
2257 /*
2258 * FUNCTION: Create a device for an adapter found using PnP
2259 * ARGUMENTS:
2260 * DriverObject = Pointer to the miniport driver object
2261 * PhysicalDeviceObject = Pointer to the PDO for our adapter
2262 */
2263 {
2264 static const WCHAR ClassKeyName[] = {'C','l','a','s','s','\\'};
2265 static const WCHAR LinkageKeyName[] = {'\\','L','i','n','k','a','g','e',0};
2266 PNDIS_M_DRIVER_BLOCK Miniport;
2267 PNDIS_M_DRIVER_BLOCK *MiniportPtr;
2268 WCHAR *LinkageKeyBuffer;
2269 ULONG DriverKeyLength;
2270 RTL_QUERY_REGISTRY_TABLE QueryTable[2];
2271 UNICODE_STRING ExportName;
2272 PDEVICE_OBJECT DeviceObject;
2273 PLOGICAL_ADAPTER Adapter;
2274 NTSTATUS Status;
2275
2276 /*
2277 * Gain the access to the miniport data structure first.
2278 */
2279
2280 MiniportPtr = IoGetDriverObjectExtension(DriverObject, (PVOID)'NMID');
2281 if (MiniportPtr == NULL)
2282 {
2283 NDIS_DbgPrint(MIN_TRACE, ("Can't get driver object extension.\n"));
2284 return NDIS_STATUS_FAILURE;
2285 }
2286 Miniport = *MiniportPtr;
2287
2288 /*
2289 * Get name of the Linkage registry key for our adapter. It's located under
2290 * the driver key for our driver and so we have basicly two ways to do it.
2291 * Either we can use IoOpenDriverRegistryKey or compose it using information
2292 * gathered by IoGetDeviceProperty. I choosed the second because
2293 * IoOpenDriverRegistryKey wasn't implemented at the time of writing.
2294 */
2295
2296 Status = IoGetDeviceProperty(PhysicalDeviceObject, DevicePropertyDriverKeyName,
2297 0, NULL, &DriverKeyLength);
2298 if (Status != STATUS_BUFFER_TOO_SMALL && Status != STATUS_BUFFER_OVERFLOW && Status != STATUS_SUCCESS)
2299 {
2300 NDIS_DbgPrint(MIN_TRACE, ("Can't get miniport driver key length.\n"));
2301 return Status;
2302 }
2303
2304 LinkageKeyBuffer = ExAllocatePool(PagedPool, DriverKeyLength +
2305 sizeof(ClassKeyName) + sizeof(LinkageKeyName));
2306 if (LinkageKeyBuffer == NULL)
2307 {
2308 NDIS_DbgPrint(MIN_TRACE, ("Can't allocate memory for driver key name.\n"));
2309 return STATUS_INSUFFICIENT_RESOURCES;
2310 }
2311
2312 Status = IoGetDeviceProperty(PhysicalDeviceObject, DevicePropertyDriverKeyName,
2313 DriverKeyLength, LinkageKeyBuffer +
2314 (sizeof(ClassKeyName) / sizeof(WCHAR)),
2315 &DriverKeyLength);
2316 if (!NT_SUCCESS(Status))
2317 {
2318 NDIS_DbgPrint(MIN_TRACE, ("Can't get miniport driver key.\n"));
2319 ExFreePool(LinkageKeyBuffer);
2320 return Status;
2321 }
2322
2323 /* Compose the linkage key name. */
2324 RtlCopyMemory(LinkageKeyBuffer, ClassKeyName, sizeof(ClassKeyName));
2325 RtlCopyMemory(LinkageKeyBuffer + ((sizeof(ClassKeyName) + DriverKeyLength) /
2326 sizeof(WCHAR)) - 1, LinkageKeyName, sizeof(LinkageKeyName));
2327
2328 NDIS_DbgPrint(DEBUG_MINIPORT, ("LinkageKey: %S.\n", LinkageKeyBuffer));
2329
2330 /*
2331 * Now open the linkage key and read the "Export" and "RootDevice" values
2332 * which contains device name and root service respectively.
2333 */
2334
2335 RtlZeroMemory(QueryTable, sizeof(QueryTable));
2336 RtlInitUnicodeString(&ExportName, NULL);
2337 QueryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED | RTL_QUERY_REGISTRY_DIRECT;
2338 QueryTable[0].Name = L"Export";
2339 QueryTable[0].EntryContext = &ExportName;
2340
2341 Status = RtlQueryRegistryValues(RTL_REGISTRY_CONTROL, LinkageKeyBuffer,
2342 QueryTable, NULL, NULL);
2343 ExFreePool(LinkageKeyBuffer);
2344 if (!NT_SUCCESS(Status))
2345 {
2346 NDIS_DbgPrint(MIN_TRACE, ("Can't get miniport device name. (%x)\n", Status));
2347 return Status;
2348 }
2349
2350 /*
2351 * Create the device object.
2352 */
2353
2354 NDIS_DbgPrint(MAX_TRACE, ("creating device %wZ\n", &ExportName));
2355
2356 Status = IoCreateDevice(Miniport->DriverObject, sizeof(LOGICAL_ADAPTER),
2357 &ExportName, FILE_DEVICE_PHYSICAL_NETCARD,
2358 0, FALSE, &DeviceObject);
2359 if (!NT_SUCCESS(Status))
2360 {
2361 NDIS_DbgPrint(MIN_TRACE, ("Could not create device object.\n"));
2362 RtlFreeUnicodeString(&ExportName);
2363 return Status;
2364 }
2365
2366 /*
2367 * Initialize the adapter structure.
2368 */
2369
2370 Adapter = (PLOGICAL_ADAPTER)DeviceObject->DeviceExtension;
2371 KeInitializeSpinLock(&Adapter->NdisMiniportBlock.Lock);
2372 InitializeListHead(&Adapter->ProtocolListHead);
2373
2374 Status = IoRegisterDeviceInterface(PhysicalDeviceObject,
2375 &GUID_DEVINTERFACE_NET,
2376 NULL,
2377 &Adapter->NdisMiniportBlock.SymbolicLinkName);
2378
2379 if (!NT_SUCCESS(Status))
2380 {
2381 NDIS_DbgPrint(MIN_TRACE, ("Could not create device interface.\n"));
2382 IoDeleteDevice(DeviceObject);
2383 RtlFreeUnicodeString(&ExportName);
2384 return Status;
2385 }
2386
2387 Adapter->NdisMiniportBlock.DriverHandle = Miniport;
2388 Adapter->NdisMiniportBlock.MiniportName = ExportName;
2389 Adapter->NdisMiniportBlock.DeviceObject = DeviceObject;
2390 Adapter->NdisMiniportBlock.PhysicalDeviceObject = PhysicalDeviceObject;
2391 Adapter->NdisMiniportBlock.NextDeviceObject =
2392 IoAttachDeviceToDeviceStack(Adapter->NdisMiniportBlock.DeviceObject,
2393 PhysicalDeviceObject);
2394
2395 Adapter->NdisMiniportBlock.OldPnPDeviceState = 0;
2396 Adapter->NdisMiniportBlock.PnPDeviceState = NdisPnPDeviceAdded;
2397
2398 KeInitializeTimer(&Adapter->NdisMiniportBlock.WakeUpDpcTimer.Timer);
2399 KeInitializeDpc(&Adapter->NdisMiniportBlock.WakeUpDpcTimer.Dpc, MiniportHangDpc, Adapter);
2400
2401 DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
2402
2403 return STATUS_SUCCESS;
2404 }
2405
2406 \f
2407 /*
2408 * @implemented
2409 */
2410 NDIS_STATUS
2411 EXPORT
2412 NdisMRegisterMiniport(
2413 IN NDIS_HANDLE NdisWrapperHandle,
2414 IN PNDIS_MINIPORT_CHARACTERISTICS MiniportCharacteristics,
2415 IN UINT CharacteristicsLength)
2416 /*
2417 * FUNCTION: Registers a miniport's MiniportXxx entry points with the NDIS library
2418 * ARGUMENTS:
2419 * NdisWrapperHandle = Pointer to handle returned by NdisMInitializeWrapper
2420 * MiniportCharacteristics = Pointer to a buffer with miniport characteristics
2421 * CharacteristicsLength = Number of bytes in characteristics buffer
2422 * RETURNS:
2423 * Status of operation
2424 */
2425 {
2426 UINT MinSize;
2427 PNDIS_M_DRIVER_BLOCK Miniport = GET_MINIPORT_DRIVER(NdisWrapperHandle);
2428 PNDIS_M_DRIVER_BLOCK *MiniportPtr;
2429 NTSTATUS Status;
2430
2431 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
2432
2433 switch (MiniportCharacteristics->MajorNdisVersion)
2434 {
2435 case 0x03:
2436 MinSize = sizeof(NDIS30_MINIPORT_CHARACTERISTICS);
2437 break;
2438
2439 case 0x04:
2440 MinSize = sizeof(NDIS40_MINIPORT_CHARACTERISTICS);
2441 break;
2442
2443 case 0x05:
2444 MinSize = sizeof(NDIS50_MINIPORT_CHARACTERISTICS);
2445 break;
2446
2447 default:
2448 NDIS_DbgPrint(MIN_TRACE, ("Bad miniport characteristics version.\n"));
2449 return NDIS_STATUS_BAD_VERSION;
2450 }
2451
2452 NDIS_DbgPrint(MIN_TRACE, ("Initializing an NDIS %u.%u miniport\n",
2453 MiniportCharacteristics->MajorNdisVersion,
2454 MiniportCharacteristics->MinorNdisVersion));
2455
2456 if (CharacteristicsLength < MinSize)
2457 {
2458 NDIS_DbgPrint(MIN_TRACE, ("Bad miniport characteristics length.\n"));
2459 return NDIS_STATUS_BAD_CHARACTERISTICS;
2460 }
2461
2462 /* Check if mandatory MiniportXxx functions are specified */
2463 if ((!MiniportCharacteristics->HaltHandler) ||
2464 (!MiniportCharacteristics->InitializeHandler)||
2465 (!MiniportCharacteristics->ResetHandler))
2466 {
2467 NDIS_DbgPrint(MIN_TRACE, ("Bad miniport characteristics.\n"));
2468 return NDIS_STATUS_BAD_CHARACTERISTICS;
2469 }
2470
2471 if (MiniportCharacteristics->MajorNdisVersion < 0x05)
2472 {
2473 if ((!MiniportCharacteristics->QueryInformationHandler) ||
2474 (!MiniportCharacteristics->SetInformationHandler))
2475 {
2476 NDIS_DbgPrint(MIN_TRACE, ("Bad miniport characteristics. (Set/Query)\n"));
2477 return NDIS_STATUS_BAD_CHARACTERISTICS;
2478 }
2479 }
2480 else
2481 {
2482 if (((!MiniportCharacteristics->QueryInformationHandler) ||
2483 (!MiniportCharacteristics->SetInformationHandler)) &&
2484 (!MiniportCharacteristics->CoRequestHandler))
2485 {
2486 NDIS_DbgPrint(MIN_TRACE, ("Bad miniport characteristics. (Set/Query)\n"));
2487 return NDIS_STATUS_BAD_CHARACTERISTICS;
2488 }
2489 }
2490
2491 if (MiniportCharacteristics->MajorNdisVersion == 0x03)
2492 {
2493 if (!MiniportCharacteristics->SendHandler)
2494 {
2495 NDIS_DbgPrint(MIN_TRACE, ("Bad miniport characteristics. (NDIS 3.0)\n"));
2496 return NDIS_STATUS_BAD_CHARACTERISTICS;
2497 }
2498 }
2499 else if (MiniportCharacteristics->MajorNdisVersion == 0x04)
2500 {
2501 /* NDIS 4.0 */
2502 if ((!MiniportCharacteristics->SendHandler) &&
2503 (!MiniportCharacteristics->SendPacketsHandler))
2504 {
2505 NDIS_DbgPrint(MIN_TRACE, ("Bad miniport characteristics. (NDIS 4.0)\n"));
2506 return NDIS_STATUS_BAD_CHARACTERISTICS;
2507 }
2508 }
2509 else if (MiniportCharacteristics->MajorNdisVersion == 0x05)
2510 {
2511 /* TODO: Add more checks here */
2512
2513 if ((!MiniportCharacteristics->SendHandler) &&
2514 (!MiniportCharacteristics->SendPacketsHandler) &&
2515 (!MiniportCharacteristics->CoSendPacketsHandler))
2516 {
2517 NDIS_DbgPrint(MIN_TRACE, ("Bad miniport characteristics. (NDIS 5.0)\n"));
2518 return NDIS_STATUS_BAD_CHARACTERISTICS;
2519 }
2520 }
2521
2522 /* TODO: verify NDIS5 and NDIS5.1 */
2523
2524 RtlCopyMemory(&Miniport->MiniportCharacteristics, MiniportCharacteristics, MinSize);
2525
2526 /*
2527 * NOTE: This is VERY unoptimal! Should we store the NDIS_M_DRIVER_BLOCK
2528 * structure in the driver extension or what?
2529 */
2530
2531 Status = IoAllocateDriverObjectExtension(Miniport->DriverObject, (PVOID)'NMID',
2532 sizeof(PNDIS_M_DRIVER_BLOCK), (PVOID*)&MiniportPtr);
2533 if (!NT_SUCCESS(Status))
2534 {
2535 NDIS_DbgPrint(MIN_TRACE, ("Can't allocate driver object extension.\n"));
2536 return NDIS_STATUS_RESOURCES;
2537 }
2538
2539 *MiniportPtr = Miniport;
2540
2541 Miniport->DriverObject->MajorFunction[IRP_MJ_CREATE] = NdisICreateClose;
2542 Miniport->DriverObject->MajorFunction[IRP_MJ_CLOSE] = NdisICreateClose;
2543 Miniport->DriverObject->MajorFunction[IRP_MJ_PNP] = NdisIDispatchPnp;
2544 Miniport->DriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = NdisIShutdown;
2545 Miniport->DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = NdisIDeviceIoControl;
2546 Miniport->DriverObject->DriverExtension->AddDevice = NdisIAddDevice;
2547
2548 return NDIS_STATUS_SUCCESS;
2549 }
2550
2551 \f
2552 /*
2553 * @implemented
2554 */
2555 #undef NdisMResetComplete
2556 VOID
2557 EXPORT
2558 NdisMResetComplete(
2559 IN NDIS_HANDLE MiniportAdapterHandle,
2560 IN NDIS_STATUS Status,
2561 IN BOOLEAN AddressingReset)
2562 {
2563 MiniResetComplete(MiniportAdapterHandle, Status, AddressingReset);
2564 }
2565
2566 \f
2567 /*
2568 * @implemented
2569 */
2570 #undef NdisMSendComplete
2571 VOID
2572 EXPORT
2573 NdisMSendComplete(
2574 IN NDIS_HANDLE MiniportAdapterHandle,
2575 IN PNDIS_PACKET Packet,
2576 IN NDIS_STATUS Status)
2577 /*
2578 * FUNCTION: Forwards a message to the initiating protocol saying
2579 * that a packet was handled
2580 * ARGUMENTS:
2581 * NdisAdapterHandle = Handle input to MiniportInitialize
2582 * Packet = Pointer to NDIS packet that was sent
2583 * Status = Status of send operation
2584 */
2585 {
2586 MiniSendComplete(MiniportAdapterHandle, Packet, Status);
2587 }
2588
2589 \f
2590 /*
2591 * @implemented
2592 */
2593 #undef NdisMSendResourcesAvailable
2594 VOID
2595 EXPORT
2596 NdisMSendResourcesAvailable(
2597 IN NDIS_HANDLE MiniportAdapterHandle)
2598 {
2599 MiniSendResourcesAvailable(MiniportAdapterHandle);
2600 }
2601
2602 \f
2603 /*
2604 * @implemented
2605 */
2606 #undef NdisMTransferDataComplete
2607 VOID
2608 EXPORT
2609 NdisMTransferDataComplete(
2610 IN NDIS_HANDLE MiniportAdapterHandle,
2611 IN PNDIS_PACKET Packet,
2612 IN NDIS_STATUS Status,
2613 IN UINT BytesTransferred)
2614 {
2615 MiniTransferDataComplete(MiniportAdapterHandle, Packet, Status, BytesTransferred);
2616 }
2617
2618 \f
2619 /*
2620 * @implemented
2621 */
2622 #undef NdisMSetAttributes
2623 VOID
2624 EXPORT
2625 NdisMSetAttributes(
2626 IN NDIS_HANDLE MiniportAdapterHandle,
2627 IN NDIS_HANDLE MiniportAdapterContext,
2628 IN BOOLEAN BusMaster,
2629 IN NDIS_INTERFACE_TYPE AdapterType)
2630 /*
2631 * FUNCTION: Informs the NDIS library of significant features of the caller's NIC
2632 * ARGUMENTS:
2633 * MiniportAdapterHandle = Handle input to MiniportInitialize
2634 * MiniportAdapterContext = Pointer to context information
2635 * BusMaster = Specifies TRUE if the caller's NIC is a busmaster DMA device
2636 * AdapterType = Specifies the I/O bus interface of the caller's NIC
2637 */
2638 {
2639 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
2640 NdisMSetAttributesEx(MiniportAdapterHandle, MiniportAdapterContext, 0,
2641 BusMaster ? NDIS_ATTRIBUTE_BUS_MASTER : 0,
2642 AdapterType);
2643 }
2644
2645 \f
2646 /*
2647 * @implemented
2648 */
2649 VOID
2650 EXPORT
2651 NdisMSetAttributesEx(
2652 IN NDIS_HANDLE MiniportAdapterHandle,
2653 IN NDIS_HANDLE MiniportAdapterContext,
2654 IN UINT CheckForHangTimeInSeconds OPTIONAL,
2655 IN ULONG AttributeFlags,
2656 IN NDIS_INTERFACE_TYPE AdapterType)
2657 /*
2658 * FUNCTION: Informs the NDIS library of significant features of the caller's NIC
2659 * ARGUMENTS:
2660 * MiniportAdapterHandle = Handle input to MiniportInitialize
2661 * MiniportAdapterContext = Pointer to context information
2662 * CheckForHangTimeInSeconds = Specifies interval in seconds at which
2663 * MiniportCheckForHang should be called
2664 * AttributeFlags = Bitmask that indicates specific attributes
2665 * AdapterType = Specifies the I/O bus interface of the caller's NIC
2666 */
2667 {
2668 PLOGICAL_ADAPTER Adapter = GET_LOGICAL_ADAPTER(MiniportAdapterHandle);
2669
2670 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
2671
2672 Adapter->NdisMiniportBlock.MiniportAdapterContext = MiniportAdapterContext;
2673 Adapter->NdisMiniportBlock.Flags = AttributeFlags;
2674 Adapter->NdisMiniportBlock.AdapterType = AdapterType;
2675 if (CheckForHangTimeInSeconds > 0)
2676 Adapter->NdisMiniportBlock.CheckForHangSeconds = CheckForHangTimeInSeconds;
2677 if (AttributeFlags & NDIS_ATTRIBUTE_INTERMEDIATE_DRIVER)
2678 NDIS_DbgPrint(MAX_TRACE, ("Intermediate drivers not supported yet.\n"));
2679
2680
2681 if (Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.AdapterShutdownHandler)
2682 {
2683 NDIS_DbgPrint(MAX_TRACE, ("Miniport set AdapterShutdownHandler in MiniportCharacteristics\n"));
2684 NdisMRegisterAdapterShutdownHandler(Adapter,
2685 Adapter->NdisMiniportBlock.MiniportAdapterContext,
2686 Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.AdapterShutdownHandler);
2687 }
2688 }
2689
2690 \f
2691 /*
2692 * @implemented
2693 */
2694 VOID
2695 EXPORT
2696 NdisMSleep(
2697 IN ULONG MicrosecondsToSleep)
2698 /*
2699 * FUNCTION: delay the thread's execution for MicrosecondsToSleep
2700 * ARGUMENTS:
2701 * MicrosecondsToSleep: duh...
2702 * NOTES:
2703 * - Because this is a blocking call, current IRQL must be < DISPATCH_LEVEL
2704 */
2705 {
2706 KTIMER Timer;
2707 LARGE_INTEGER DueTime;
2708
2709 PAGED_CODE();
2710
2711 DueTime.QuadPart = (-1) * 10 * MicrosecondsToSleep;
2712
2713 KeInitializeTimer(&Timer);
2714 KeSetTimer(&Timer, DueTime, 0);
2715 KeWaitForSingleObject(&Timer, Executive, KernelMode, FALSE, 0);
2716 }
2717
2718 \f
2719 /*
2720 * @implemented
2721 */
2722 BOOLEAN
2723 EXPORT
2724 NdisMSynchronizeWithInterrupt(
2725 IN PNDIS_MINIPORT_INTERRUPT Interrupt,
2726 IN PVOID SynchronizeFunction,
2727 IN PVOID SynchronizeContext)
2728 {
2729 return(KeSynchronizeExecution(Interrupt->InterruptObject,
2730 (PKSYNCHRONIZE_ROUTINE)SynchronizeFunction,
2731 SynchronizeContext));
2732 }
2733
2734 \f
2735 /*
2736 * @unimplemented
2737 */
2738 NDIS_STATUS
2739 EXPORT
2740 NdisMWriteLogData(
2741 IN NDIS_HANDLE LogHandle,
2742 IN PVOID LogBuffer,
2743 IN UINT LogBufferSize)
2744 {
2745 PUCHAR Buffer = LogBuffer;
2746 UINT i, j, idx;
2747
2748 UNIMPLEMENTED;
2749 for (i = 0; i < LogBufferSize; i += 16)
2750 {
2751 DbgPrint("%08x |", i);
2752 for (j = 0; j < 16; j++)
2753 {
2754 idx = i + j;
2755 if (idx < LogBufferSize)
2756 DbgPrint(" %02x", Buffer[idx]);
2757 else
2758 DbgPrint(" ");
2759 }
2760 DbgPrint(" | ");
2761 for (j = 0; j < 16; j++)
2762 {
2763 idx = i + j;
2764 if (idx == LogBufferSize)
2765 break;
2766 if (Buffer[idx] >= ' ') /* FIXME: not portable! replace by if (isprint(Buffer[idx])) ? */
2767 DbgPrint("%c", Buffer[idx]);
2768 else
2769 DbgPrint(".");
2770 }
2771 DbgPrint("\n");
2772 }
2773
2774 return NDIS_STATUS_FAILURE;
2775 }
2776
2777 \f
2778 /*
2779 * @implemented
2780 */
2781 VOID
2782 EXPORT
2783 NdisTerminateWrapper(
2784 IN NDIS_HANDLE NdisWrapperHandle,
2785 IN PVOID SystemSpecific)
2786 /*
2787 * FUNCTION: Releases resources allocated by a call to NdisInitializeWrapper
2788 * ARGUMENTS:
2789 * NdisWrapperHandle = Handle returned by NdisInitializeWrapper (NDIS_M_DRIVER_BLOCK)
2790 * SystemSpecific = Always NULL
2791 */
2792 {
2793 PNDIS_M_DRIVER_BLOCK Miniport = GET_MINIPORT_DRIVER(NdisWrapperHandle);
2794
2795 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
2796
2797 ExFreePool(Miniport->RegistryPath->Buffer);
2798 ExFreePool(Miniport->RegistryPath);
2799 ExInterlockedRemoveEntryList(&Miniport->ListEntry, &MiniportListLock);
2800 ExFreePool(Miniport);
2801 }
2802
2803
2804 /*
2805 * @implemented
2806 */
2807 NDIS_STATUS
2808 EXPORT
2809 NdisMQueryAdapterInstanceName(
2810 OUT PNDIS_STRING AdapterInstanceName,
2811 IN NDIS_HANDLE MiniportAdapterHandle)
2812 /*
2813 * FUNCTION:
2814 * ARGUMENTS:
2815 * NOTES:
2816 * NDIS 5.0
2817 */
2818 {
2819 PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)MiniportAdapterHandle;
2820 UNICODE_STRING AdapterName;
2821
2822 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
2823
2824 AdapterName.Length = 0;
2825 AdapterName.MaximumLength = Adapter->NdisMiniportBlock.MiniportName.MaximumLength;
2826 AdapterName.Buffer = ExAllocatePool(PagedPool, AdapterName.MaximumLength);
2827 if (!AdapterName.Buffer) {
2828 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources\n"));
2829 return NDIS_STATUS_RESOURCES;
2830 }
2831
2832 RtlCopyUnicodeString(&AdapterName, &Adapter->NdisMiniportBlock.MiniportName);
2833
2834 *AdapterInstanceName = AdapterName;
2835
2836 return NDIS_STATUS_SUCCESS;
2837 }
2838
2839 /*
2840 * @implemented
2841 */
2842 VOID
2843 EXPORT
2844 NdisDeregisterAdapterShutdownHandler(
2845 IN NDIS_HANDLE NdisAdapterHandle)
2846 /*
2847 * FUNCTION:
2848 * ARGUMENTS:
2849 * NOTES:
2850 * NDIS 4.0
2851 */
2852 {
2853 NdisMDeregisterAdapterShutdownHandler(NdisAdapterHandle);
2854 }
2855
2856
2857 /*
2858 * @implemented
2859 */
2860 VOID
2861 EXPORT
2862 NdisRegisterAdapterShutdownHandler(
2863 IN NDIS_HANDLE NdisAdapterHandle,
2864 IN PVOID ShutdownContext,
2865 IN ADAPTER_SHUTDOWN_HANDLER ShutdownHandler)
2866 /*
2867 * FUNCTION:
2868 * ARGUMENTS:
2869 * NOTES:
2870 * NDIS 4.0
2871 */
2872 {
2873 NdisMRegisterAdapterShutdownHandler(NdisAdapterHandle,
2874 ShutdownContext,
2875 ShutdownHandler);
2876 }
2877
2878 /*
2879 * @implemented
2880 */
2881 VOID
2882 EXPORT
2883 NdisMGetDeviceProperty(
2884 IN NDIS_HANDLE MiniportAdapterHandle,
2885 IN OUT PDEVICE_OBJECT *PhysicalDeviceObject OPTIONAL,
2886 IN OUT PDEVICE_OBJECT *FunctionalDeviceObject OPTIONAL,
2887 IN OUT PDEVICE_OBJECT *NextDeviceObject OPTIONAL,
2888 IN OUT PCM_RESOURCE_LIST *AllocatedResources OPTIONAL,
2889 IN OUT PCM_RESOURCE_LIST *AllocatedResourcesTranslated OPTIONAL)
2890 /*
2891 * FUNCTION:
2892 * ARGUMENTS:
2893 * NOTES:
2894 * NDIS 5.0
2895 */
2896 {
2897 PLOGICAL_ADAPTER Adapter = MiniportAdapterHandle;
2898
2899 NDIS_DbgPrint(MAX_TRACE, ("Called\n"));
2900
2901 if (PhysicalDeviceObject != NULL)
2902 *PhysicalDeviceObject = Adapter->NdisMiniportBlock.PhysicalDeviceObject;
2903
2904 if (FunctionalDeviceObject != NULL)
2905 *FunctionalDeviceObject = Adapter->NdisMiniportBlock.DeviceObject;
2906
2907 if (NextDeviceObject != NULL)
2908 *NextDeviceObject = Adapter->NdisMiniportBlock.NextDeviceObject;
2909
2910 if (AllocatedResources != NULL)
2911 *AllocatedResources = Adapter->NdisMiniportBlock.AllocatedResources;
2912
2913 if (AllocatedResourcesTranslated != NULL)
2914 *AllocatedResourcesTranslated = Adapter->NdisMiniportBlock.AllocatedResourcesTranslated;
2915 }
2916
2917 /*
2918 * @implemented
2919 */
2920 VOID
2921 EXPORT
2922 NdisMRegisterUnloadHandler(
2923 IN NDIS_HANDLE NdisWrapperHandle,
2924 IN PDRIVER_UNLOAD UnloadHandler)
2925 /*
2926 * FUNCTION:
2927 * ARGUMENTS:
2928 * NOTES:
2929 * NDIS 5.0
2930 */
2931 {
2932 PNDIS_M_DRIVER_BLOCK DriverBlock = NdisWrapperHandle;
2933
2934 NDIS_DbgPrint(MAX_TRACE, ("Miniport registered unload handler\n"));
2935
2936 DriverBlock->DriverObject->DriverUnload = UnloadHandler;
2937 }
2938
2939 /*
2940 * @implemented
2941 */
2942 NDIS_STATUS
2943 EXPORT
2944 NdisMRegisterDevice(
2945 IN NDIS_HANDLE NdisWrapperHandle,
2946 IN PNDIS_STRING DeviceName,
2947 IN PNDIS_STRING SymbolicName,
2948 IN PDRIVER_DISPATCH MajorFunctions[],
2949 OUT PDEVICE_OBJECT *pDeviceObject,
2950 OUT NDIS_HANDLE *NdisDeviceHandle)
2951 /*
2952 * FUNCTION:
2953 * ARGUMENTS:
2954 * NOTES:
2955 * NDIS 5.0
2956 */
2957 {
2958 PNDIS_M_DRIVER_BLOCK DriverBlock = NdisWrapperHandle;
2959 PNDIS_M_DEVICE_BLOCK DeviceBlock;
2960 PDEVICE_OBJECT DeviceObject;
2961 NDIS_STATUS Status;
2962 UINT i;
2963
2964 NDIS_DbgPrint(MAX_TRACE, ("Called\n"));
2965
2966 Status = IoCreateDevice(DriverBlock->DriverObject,
2967 0, /* This space is reserved for us. Should we use it? */
2968 DeviceName,
2969 FILE_DEVICE_NETWORK,
2970 0,
2971 FALSE,
2972 &DeviceObject);
2973
2974 if (!NT_SUCCESS(Status))
2975 {
2976 NDIS_DbgPrint(MIN_TRACE, ("IoCreateDevice failed (%x)\n", Status));
2977 return Status;
2978 }
2979
2980 Status = IoCreateSymbolicLink(SymbolicName, DeviceName);
2981
2982 if (!NT_SUCCESS(Status))
2983 {
2984 NDIS_DbgPrint(MIN_TRACE, ("IoCreateSymbolicLink failed (%x)\n", Status));
2985 IoDeleteDevice(DeviceObject);
2986 return Status;
2987 }
2988
2989 DeviceBlock = ExAllocatePool(NonPagedPool, sizeof(NDIS_M_DEVICE_BLOCK));
2990
2991 if (!DeviceBlock)
2992 {
2993 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources\n"));
2994 IoDeleteDevice(DeviceObject);
2995 IoDeleteSymbolicLink(SymbolicName);
2996 return NDIS_STATUS_RESOURCES;
2997 }
2998
2999 for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
3000 DriverBlock->DriverObject->MajorFunction[i] = MajorFunctions[i];
3001
3002 DriverBlock->DriverObject->MajorFunction[IRP_MJ_PNP] = NdisIDispatchPnp;
3003
3004 if (!DriverBlock->DriverObject->MajorFunction[IRP_MJ_CREATE])
3005 DriverBlock->DriverObject->MajorFunction[IRP_MJ_CREATE] = NdisICreateClose;
3006
3007 if (!DriverBlock->DriverObject->MajorFunction[IRP_MJ_CLOSE])
3008 DriverBlock->DriverObject->MajorFunction[IRP_MJ_CLOSE] = NdisICreateClose;
3009
3010 DeviceBlock->DeviceObject = DeviceObject;
3011 DeviceBlock->SymbolicName = SymbolicName;
3012
3013 *pDeviceObject = DeviceObject;
3014 *NdisDeviceHandle = DeviceBlock;
3015
3016 return NDIS_STATUS_SUCCESS;
3017 }
3018
3019 /*
3020 * @implemented
3021 */
3022 NDIS_STATUS
3023 EXPORT
3024 NdisMDeregisterDevice(
3025 IN NDIS_HANDLE NdisDeviceHandle)
3026 /*
3027 * FUNCTION:
3028 * ARGUMENTS:
3029 * NOTES:
3030 * NDIS 5.0
3031 */
3032 {
3033 PNDIS_M_DEVICE_BLOCK DeviceBlock = NdisDeviceHandle;
3034
3035 IoDeleteDevice(DeviceBlock->DeviceObject);
3036
3037 IoDeleteSymbolicLink(DeviceBlock->SymbolicName);
3038
3039 ExFreePool(DeviceBlock);
3040
3041 return NDIS_STATUS_SUCCESS;
3042 }
3043
3044 /*
3045 * @implemented
3046 */
3047 NDIS_STATUS
3048 EXPORT
3049 NdisQueryAdapterInstanceName(
3050 OUT PNDIS_STRING AdapterInstanceName,
3051 IN NDIS_HANDLE NdisBindingHandle)
3052 /*
3053 * FUNCTION:
3054 * ARGUMENTS:
3055 * NOTES:
3056 * NDIS 5.0
3057 */
3058 {
3059 PADAPTER_BINDING AdapterBinding = NdisBindingHandle;
3060 PLOGICAL_ADAPTER Adapter = AdapterBinding->Adapter;
3061
3062 return NdisMQueryAdapterInstanceName(AdapterInstanceName,
3063 Adapter);
3064 }
3065
3066 /*
3067 * @implemented
3068 */
3069 VOID
3070 EXPORT
3071 NdisCompletePnPEvent(
3072 IN NDIS_STATUS Status,
3073 IN NDIS_HANDLE NdisBindingHandle,
3074 IN PNET_PNP_EVENT NetPnPEvent)
3075 /*
3076 * FUNCTION:
3077 * ARGUMENTS:
3078 * NOTES:
3079 * NDIS 5.0
3080 */
3081 {
3082 PIRP Irp = (PIRP)NetPnPEvent->NdisReserved[0];
3083 PLIST_ENTRY CurrentEntry = (PLIST_ENTRY)NetPnPEvent->NdisReserved[1];
3084 PADAPTER_BINDING AdapterBinding = NdisBindingHandle;
3085 PLOGICAL_ADAPTER Adapter = AdapterBinding->Adapter;
3086 NDIS_STATUS NdisStatus;
3087
3088 if (Status != NDIS_STATUS_SUCCESS)
3089 {
3090 if (NetPnPEvent->Buffer) ExFreePool(NetPnPEvent->Buffer);
3091 ExFreePool(NetPnPEvent);
3092 Irp->IoStatus.Status = Status;
3093 IoCompleteRequest(Irp, IO_NO_INCREMENT);
3094 return;
3095 }
3096
3097 while (CurrentEntry != &Adapter->ProtocolListHead)
3098 {
3099 AdapterBinding = CONTAINING_RECORD(CurrentEntry, ADAPTER_BINDING, AdapterListEntry);
3100
3101 NdisStatus = (*AdapterBinding->ProtocolBinding->Chars.PnPEventHandler)(
3102 AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
3103 NetPnPEvent);
3104
3105 if (NdisStatus == NDIS_STATUS_PENDING)
3106 {
3107 NetPnPEvent->NdisReserved[1] = (ULONG_PTR)CurrentEntry->Flink;
3108 return;
3109 }
3110 else if (NdisStatus != NDIS_STATUS_SUCCESS)
3111 {
3112 if (NetPnPEvent->Buffer) ExFreePool(NetPnPEvent->Buffer);
3113 ExFreePool(NetPnPEvent);
3114 Irp->IoStatus.Status = NdisStatus;
3115 IoCompleteRequest(Irp, IO_NO_INCREMENT);
3116 return;
3117 }
3118
3119 CurrentEntry = CurrentEntry->Flink;
3120 }
3121
3122 if (NetPnPEvent->Buffer) ExFreePool(NetPnPEvent->Buffer);
3123 ExFreePool(NetPnPEvent);
3124
3125 Irp->IoStatus.Status = NDIS_STATUS_SUCCESS;
3126 IoCompleteRequest(Irp, IO_NO_INCREMENT);
3127 }
3128
3129 /*
3130 * @implemented
3131 */
3132 VOID
3133 EXPORT
3134 NdisCancelSendPackets(
3135 IN NDIS_HANDLE NdisBindingHandle,
3136 IN PVOID CancelId)
3137 {
3138 PADAPTER_BINDING AdapterBinding = NdisBindingHandle;
3139 PLOGICAL_ADAPTER Adapter = AdapterBinding->Adapter;
3140
3141 NDIS_DbgPrint(MAX_TRACE, ("Called for ID %x.\n", CancelId));
3142
3143 if (Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.CancelSendPacketsHandler)
3144 {
3145 (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.CancelSendPacketsHandler)(
3146 Adapter->NdisMiniportBlock.MiniportAdapterContext,
3147 CancelId);
3148 }
3149 }
3150
3151
3152 /*
3153 * @implemented
3154 */
3155 NDIS_HANDLE
3156 EXPORT
3157 NdisIMGetBindingContext(
3158 IN NDIS_HANDLE NdisBindingHandle)
3159 /*
3160 * FUNCTION:
3161 * ARGUMENTS:
3162 * NOTES:
3163 * NDIS 5.0
3164 */
3165 {
3166 PADAPTER_BINDING AdapterBinding = NdisBindingHandle;
3167 PLOGICAL_ADAPTER Adapter = AdapterBinding->Adapter;
3168
3169 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
3170
3171 return Adapter->NdisMiniportBlock.DeviceContext;
3172 }
3173
3174
3175 /*
3176 * @implemented
3177 */
3178 NDIS_HANDLE
3179 EXPORT
3180 NdisIMGetDeviceContext(
3181 IN NDIS_HANDLE MiniportAdapterHandle)
3182 /*
3183 * FUNCTION:
3184 * ARGUMENTS:
3185 * NOTES:
3186 * NDIS 5.0
3187 */
3188 {
3189 PLOGICAL_ADAPTER Adapter = MiniportAdapterHandle;
3190
3191 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
3192
3193 return Adapter->NdisMiniportBlock.DeviceContext;
3194 }
3195
3196 /* EOF */
3197