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