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