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