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