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