MS DDK compatibility fixes.
[reactos.git] / reactos / drivers / net / ndis / ndis / miniport.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS NDIS library
4 * FILE: ndis/miniport.c
5 * PURPOSE: Routines used by NDIS miniport drivers
6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
7 * Vizzini (vizzini@plasmic.com)
8 * REVISIONS:
9 * CSH 01/08-2000 Created
10 * 20 Aug 2003 vizzini - DMA support
11 * 3 Oct 2003 vizzini - SendPackets support
12 */
13
14 #include "ndissys.h"
15 #include "efilter.h"
16
17 #ifdef DBG
18 #include <buffer.h>
19 #endif /* DBG */
20
21 #undef NdisMSendComplete
22 VOID
23 EXPORT
24 NdisMSendComplete(
25 IN NDIS_HANDLE MiniportAdapterHandle,
26 IN PNDIS_PACKET Packet,
27 IN NDIS_STATUS Status);
28
29 /* Root of the scm database */
30 #define SERVICES_ROOT L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\"
31
32 /*
33 * Define to 1 to get a debugger breakpoint at the end of NdisInitializeWrapper
34 * for each new miniport starting up
35 */
36 #define BREAK_ON_MINIPORT_INIT 0
37
38 /*
39 * This has to be big enough to hold the results of querying the Route value
40 * from the Linkage key. Please re-code me to determine this dynamically.
41 */
42 #define ROUTE_DATA_SIZE 256
43
44 /* Number of media we know */
45 #define MEDIA_ARRAY_SIZE 15
46
47 static NDIS_MEDIUM MediaArray[MEDIA_ARRAY_SIZE] =
48 {
49 NdisMedium802_3,
50 NdisMedium802_5,
51 NdisMediumFddi,
52 NdisMediumWan,
53 NdisMediumLocalTalk,
54 NdisMediumDix,
55 NdisMediumArcnetRaw,
56 NdisMediumArcnet878_2,
57 NdisMediumAtm,
58 NdisMediumWirelessWan,
59 NdisMediumIrda,
60 NdisMediumBpc,
61 NdisMediumCoWan,
62 NdisMedium1394,
63 NdisMediumMax
64 };
65
66 /* global list and lock of Miniports NDIS has registered */
67 LIST_ENTRY MiniportListHead;
68 KSPIN_LOCK MiniportListLock;
69
70 /* global list and lock of adapters NDIS has registered */
71 LIST_ENTRY AdapterListHead;
72 KSPIN_LOCK AdapterListLock;
73
74 VOID
75 MiniDisplayPacket(
76 PNDIS_PACKET Packet)
77 {
78 #ifdef DBG
79 ULONG i, Length;
80 UCHAR Buffer[64];
81 if ((DebugTraceLevel & DEBUG_PACKET) > 0) {
82 Length = CopyPacketToBuffer(
83 (PUCHAR)&Buffer,
84 Packet,
85 0,
86 64);
87
88 DbgPrint("*** PACKET START ***");
89
90 for (i = 0; i < Length; i++) {
91 if (i % 12 == 0)
92 DbgPrint("\n%04X ", i);
93 DbgPrint("%02X ", Buffer[i]);
94 }
95
96 DbgPrint("*** PACKET STOP ***\n");
97 }
98 #endif /* DBG */
99 }
100
101 VOID
102 MiniDisplayPacket2(
103 PVOID HeaderBuffer,
104 UINT HeaderBufferSize,
105 PVOID LookaheadBuffer,
106 UINT LookaheadBufferSize)
107 {
108 #ifdef DBG
109 if ((DebugTraceLevel & DEBUG_PACKET) > 0) {
110 ULONG i, Length;
111 PUCHAR p;
112
113 DbgPrint("*** RECEIVE PACKET START ***\n");
114 DbgPrint("HEADER:");
115 p = HeaderBuffer;
116 for (i = 0; i < HeaderBufferSize; i++) {
117 if (i % 16 == 0)
118 DbgPrint("\n%04X ", i);
119 DbgPrint("%02X ", *p++);
120 }
121
122 DbgPrint("\nFRAME:");
123
124 p = LookaheadBuffer;
125 Length = (LookaheadBufferSize < 64)? LookaheadBufferSize : 64;
126 for (i = 0; i < Length; i++) {
127 if (i % 16 == 0)
128 DbgPrint("\n%04X ", i);
129 DbgPrint("%02X ", *p++);
130 }
131
132 DbgPrint("\n*** RECEIVE PACKET STOP ***\n");
133 }
134 #endif /* DBG */
135 }
136
137 \f
138 VOID
139 MiniIndicateData(
140 PLOGICAL_ADAPTER Adapter,
141 NDIS_HANDLE MacReceiveContext,
142 PVOID HeaderBuffer,
143 UINT HeaderBufferSize,
144 PVOID LookaheadBuffer,
145 UINT LookaheadBufferSize,
146 UINT PacketSize)
147 /*
148 * FUNCTION: Indicate received data to bound protocols
149 * ARGUMENTS:
150 * Adapter = Pointer to logical adapter
151 * MacReceiveContext = MAC receive context handle
152 * HeaderBuffer = Pointer to header buffer
153 * HeaderBufferSize = Size of header buffer
154 * LookaheadBuffer = Pointer to lookahead buffer
155 * LookaheadBufferSize = Size of lookahead buffer
156 * PacketSize = Total size of received packet
157 */
158 {
159 /* KIRQL OldIrql; */
160 PLIST_ENTRY CurrentEntry;
161 PADAPTER_BINDING AdapterBinding;
162
163 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called. Adapter (0x%X) HeaderBuffer (0x%X) "
164 "HeaderBufferSize (0x%X) LookaheadBuffer (0x%X) LookaheadBufferSize (0x%X).\n",
165 Adapter, HeaderBuffer, HeaderBufferSize, LookaheadBuffer, LookaheadBufferSize));
166
167 MiniDisplayPacket2(HeaderBuffer, HeaderBufferSize, LookaheadBuffer, LookaheadBufferSize);
168
169 /*
170 * XXX Think about this. This is probably broken. Spinlocks are
171 * taken out for now until i comprehend the Right Way to do this.
172 *
173 * This used to acquire the MiniportBlock spinlock and hold it until
174 * just before the call to ReceiveHandler. It would then release and
175 * subsequently re-acquire the lock.
176 *
177 * I don't see how this does any good, as it would seem he's just
178 * trying to protect the packet list. If somebody else dequeues
179 * a packet, we are in fact in bad shape, but we don't want to
180 * necessarily call the receive handler at elevated irql either.
181 *
182 * therefore: We *are* going to call the receive handler at high irql
183 * (due to holding the lock) for now, and eventually we have to
184 * figure out another way to protect this packet list.
185 *
186 * UPDATE: this is busted; this results in a recursive lock acquisition.
187 */
188 //NDIS_DbgPrint(MAX_TRACE, ("acquiring miniport block lock\n"));
189 //KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
190 {
191 CurrentEntry = Adapter->ProtocolListHead.Flink;
192 NDIS_DbgPrint(DEBUG_MINIPORT, ("CurrentEntry = %x\n", CurrentEntry));
193
194 if (CurrentEntry == &Adapter->ProtocolListHead)
195 {
196 NDIS_DbgPrint(DEBUG_MINIPORT, ("WARNING: No upper protocol layer.\n"));
197 }
198
199 while (CurrentEntry != &Adapter->ProtocolListHead)
200 {
201 AdapterBinding = CONTAINING_RECORD(CurrentEntry, ADAPTER_BINDING, AdapterListEntry);
202 NDIS_DbgPrint(DEBUG_MINIPORT, ("AdapterBinding = %x\n", AdapterBinding));
203
204 /* see above */
205 /* KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql); */
206
207 #ifdef DBG
208 if(!AdapterBinding)
209 {
210 NDIS_DbgPrint(MIN_TRACE, ("AdapterBinding was null\n"));
211 break;
212 }
213
214 if(!AdapterBinding->ProtocolBinding)
215 {
216 NDIS_DbgPrint(MIN_TRACE, ("AdapterBinding->ProtocolBinding was null\n"));
217 break;
218 }
219
220 if(!AdapterBinding->ProtocolBinding->Chars.ReceiveHandler)
221 {
222 NDIS_DbgPrint(MIN_TRACE, ("AdapterBinding->ProtocolBinding->Chars.ReceiveHandler was null\n"));
223 break;
224 }
225 #endif
226
227 NDIS_DbgPrint
228 (MID_TRACE,
229 ("XXX (%x) %x %x %x %x %x %x %x XXX\n",
230 *AdapterBinding->ProtocolBinding->Chars.ReceiveHandler,
231 AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
232 MacReceiveContext,
233 HeaderBuffer,
234 HeaderBufferSize,
235 LookaheadBuffer,
236 LookaheadBufferSize,
237 PacketSize));
238
239 /* call the receive handler */
240 (*AdapterBinding->ProtocolBinding->Chars.ReceiveHandler)(
241 AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
242 MacReceiveContext,
243 HeaderBuffer,
244 HeaderBufferSize,
245 LookaheadBuffer,
246 LookaheadBufferSize,
247 PacketSize);
248
249 /* see above */
250 /* KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql); */
251
252 CurrentEntry = CurrentEntry->Flink;
253 }
254 }
255 //KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
256
257 NDIS_DbgPrint(MAX_TRACE, ("Leaving.\n"));
258 }
259
260 \f
261 VOID NTAPI
262 MiniIndicateReceivePacket(
263 IN NDIS_HANDLE Miniport,
264 IN PPNDIS_PACKET PacketArray,
265 IN UINT NumberOfPackets)
266 /*
267 * FUNCTION: receives miniport packet array indications
268 * ARGUMENTS:
269 * Miniport: Miniport handle for the adapter
270 * PacketArray: pointer to a list of packet pointers to indicate
271 * NumberOfPackets: number of packets to indicate
272 * NOTES:
273 * - This currently is a big temporary hack. In the future this should
274 * call ProtocolReceivePacket() on each bound protocol if it exists.
275 * For now it just mimics NdisMEthIndicateReceive.
276 */
277 {
278 UINT i;
279
280 for(i = 0; i < NumberOfPackets; i++)
281 {
282 PCHAR PacketBuffer = 0;
283 UINT PacketLength = 0;
284 PNDIS_BUFFER NdisBuffer = 0;
285
286 #define PACKET_TAG (('k' << 24) + ('P' << 16) + ('D' << 8) + 'N')
287
288 NdisAllocateMemoryWithTag((PVOID)&PacketBuffer, 1518, PACKET_TAG);
289 if(!PacketBuffer)
290 {
291 NDIS_DbgPrint(MIN_TRACE, ("insufficient resources\n"));
292 return;
293 }
294
295 NdisQueryPacket(PacketArray[i], NULL, NULL, &NdisBuffer, NULL);
296
297 while(NdisBuffer)
298 {
299 PNDIS_BUFFER CurrentBuffer;
300 PVOID BufferVa;
301 UINT BufferLen;
302
303 NdisQueryBuffer(NdisBuffer, &BufferVa, &BufferLen);
304 memcpy(PacketBuffer + PacketLength, BufferVa, BufferLen);
305 PacketLength += BufferLen;
306
307 CurrentBuffer = NdisBuffer;
308 NdisGetNextBuffer(CurrentBuffer, &NdisBuffer);
309 }
310
311 NDIS_DbgPrint(MID_TRACE, ("indicating a %d-byte packet\n", PacketLength));
312
313 MiniIndicateData(Miniport, NULL, PacketBuffer, 14, PacketBuffer+14, PacketLength-14, PacketLength-14);
314
315 NdisFreeMemory(PacketBuffer, 0, 0);
316 }
317 }
318
319 \f
320 VOID NTAPI
321 MiniResetComplete(
322 IN NDIS_HANDLE MiniportAdapterHandle,
323 IN NDIS_STATUS Status,
324 IN BOOLEAN AddressingReset)
325 {
326 UNIMPLEMENTED
327 }
328
329
330 \f
331 VOID NTAPI
332 MiniRequestComplete(
333 IN PADAPTER_BINDING AdapterBinding,
334 IN PNDIS_REQUEST Request,
335 IN NDIS_STATUS Status)
336 {
337 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
338
339 if( AdapterBinding->ProtocolBinding->Chars.RequestCompleteHandler ) {
340 (*AdapterBinding->ProtocolBinding->Chars.RequestCompleteHandler)(
341 AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
342 Request,
343 Status);
344 }
345 }
346
347 VOID NTAPI
348 MiniSendComplete(
349 IN NDIS_HANDLE MiniportAdapterHandle,
350 IN PNDIS_PACKET Packet,
351 IN NDIS_STATUS Status)
352 /*
353 * FUNCTION: Forwards a message to the initiating protocol saying
354 * that a packet was handled
355 * ARGUMENTS:
356 * NdisAdapterHandle = Handle input to MiniportInitialize
357 * Packet = Pointer to NDIS packet that was sent
358 * Status = Status of send operation
359 */
360 {
361 PADAPTER_BINDING AdapterBinding;
362
363 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
364
365 AdapterBinding = (PADAPTER_BINDING)Packet->Reserved[0];
366
367 (*AdapterBinding->ProtocolBinding->Chars.SendCompleteHandler)(
368 AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
369 Packet,
370 Status);
371 }
372
373
374 VOID NTAPI
375 MiniSendResourcesAvailable(
376 IN NDIS_HANDLE MiniportAdapterHandle)
377 {
378 UNIMPLEMENTED
379 }
380
381
382 VOID NTAPI
383 MiniTransferDataComplete(
384 IN NDIS_HANDLE MiniportAdapterHandle,
385 IN PNDIS_PACKET Packet,
386 IN NDIS_STATUS Status,
387 IN UINT BytesTransferred)
388 {
389 PADAPTER_BINDING AdapterBinding;
390
391 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
392
393 AdapterBinding = (PADAPTER_BINDING)Packet->Reserved[0];
394
395 (*AdapterBinding->ProtocolBinding->Chars.SendCompleteHandler)(
396 AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
397 Packet,
398 Status);
399 }
400
401 \f
402 BOOLEAN
403 MiniAdapterHasAddress(
404 PLOGICAL_ADAPTER Adapter,
405 PNDIS_PACKET Packet)
406 /*
407 * FUNCTION: Determines whether a packet has the same destination address as an adapter
408 * ARGUMENTS:
409 * Adapter = Pointer to logical adapter object
410 * Packet = Pointer to NDIS packet
411 * RETURNS:
412 * TRUE if the destination address is that of the adapter, FALSE if not
413 */
414 {
415 UINT Length;
416 PUCHAR Start1;
417 PUCHAR Start2;
418 PNDIS_BUFFER NdisBuffer;
419 UINT BufferLength;
420
421 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
422
423 #ifdef DBG
424 if(!Adapter)
425 {
426 NDIS_DbgPrint(MID_TRACE, ("Adapter object was null\n"));
427 return FALSE;
428 }
429
430 if(!Packet)
431 {
432 NDIS_DbgPrint(MID_TRACE, ("Packet was null\n"));
433 return FALSE;
434 }
435 #endif
436
437 NdisQueryPacket(Packet, NULL, NULL, &NdisBuffer, NULL);
438
439 if (!NdisBuffer)
440 {
441 NDIS_DbgPrint(MID_TRACE, ("Packet contains no buffers.\n"));
442 return FALSE;
443 }
444
445 NdisQueryBuffer(NdisBuffer, (PVOID)&Start2, &BufferLength);
446
447 /* FIXME: Should handle fragmented packets */
448
449 switch (Adapter->NdisMiniportBlock.MediaType)
450 {
451 case NdisMedium802_3:
452 Length = ETH_LENGTH_OF_ADDRESS;
453 /* Destination address is the first field */
454 break;
455
456 default:
457 NDIS_DbgPrint(MIN_TRACE, ("Adapter has unsupported media type (0x%X).\n", Adapter->NdisMiniportBlock.MediaType));
458 return FALSE;
459 }
460
461 if (BufferLength < Length)
462 {
463 NDIS_DbgPrint(MID_TRACE, ("Buffer is too small.\n"));
464 return FALSE;
465 }
466
467 Start1 = (PUCHAR)&Adapter->Address;
468 NDIS_DbgPrint(MAX_TRACE, ("packet address: %x:%x:%x:%x:%x:%x adapter address: %x:%x:%x:%x:%x:%x\n",
469 *((char *)Start1), *(((char *)Start1)+1), *(((char *)Start1)+2), *(((char *)Start1)+3), *(((char *)Start1)+4), *(((char *)Start1)+5),
470 *((char *)Start2), *(((char *)Start2)+1), *(((char *)Start2)+2), *(((char *)Start2)+3), *(((char *)Start2)+4), *(((char *)Start2)+5))
471 );
472
473 return (RtlCompareMemory((PVOID)Start1, (PVOID)Start2, Length) == Length);
474 }
475
476 \f
477 PLOGICAL_ADAPTER
478 MiniLocateDevice(
479 PNDIS_STRING AdapterName)
480 /*
481 * FUNCTION: Finds an adapter object by name
482 * ARGUMENTS:
483 * AdapterName = Pointer to name of adapter
484 * RETURNS:
485 * Pointer to logical adapter object, or NULL if none was found.
486 * If found, the adapter is referenced for the caller. The caller
487 * is responsible for dereferencing after use
488 */
489 {
490 KIRQL OldIrql;
491 PLIST_ENTRY CurrentEntry;
492 PLOGICAL_ADAPTER Adapter = 0;
493
494 ASSERT(AdapterName);
495
496 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
497
498 if(IsListEmpty(&AdapterListHead))
499 {
500 NDIS_DbgPrint(DEBUG_MINIPORT, ("No registered miniports for protocol to bind to\n"));
501 return NULL;
502 }
503
504 KeAcquireSpinLock(&AdapterListLock, &OldIrql);
505 {
506 do
507 {
508 CurrentEntry = AdapterListHead.Flink;
509
510 while (CurrentEntry != &AdapterListHead)
511 {
512 Adapter = CONTAINING_RECORD(CurrentEntry, LOGICAL_ADAPTER, ListEntry);
513
514 ASSERT(Adapter);
515
516 NDIS_DbgPrint(DEBUG_MINIPORT, ("AdapterName = %wZ\n", AdapterName));
517 NDIS_DbgPrint(DEBUG_MINIPORT, ("DeviceName = %wZ\n", &Adapter->NdisMiniportBlock.MiniportName));
518
519 if (RtlCompareUnicodeString(AdapterName, &Adapter->NdisMiniportBlock.MiniportName, TRUE) == 0)
520 {
521 ReferenceObject(Adapter);
522 break;
523 }
524
525 Adapter = NULL;
526 CurrentEntry = CurrentEntry->Flink;
527 }
528 } while (0);
529 }
530 KeReleaseSpinLock(&AdapterListLock, OldIrql);
531
532 if(Adapter)
533 {
534 NDIS_DbgPrint(DEBUG_MINIPORT, ("Leaving. Adapter found at 0x%x\n", Adapter));
535 }
536 else
537 {
538 NDIS_DbgPrint(DEBUG_MINIPORT, ("Leaving (adapter not found).\n"));
539 }
540
541 return Adapter;
542 }
543
544 \f
545 NDIS_STATUS
546 MiniQueryInformation(
547 PLOGICAL_ADAPTER Adapter,
548 NDIS_OID Oid,
549 ULONG Size,
550 PULONG BytesWritten)
551 /*
552 * FUNCTION: Queries a logical adapter for properties
553 * ARGUMENTS:
554 * Adapter = Pointer to the logical adapter object to query
555 * Oid = Specifies the Object ID to query for
556 * Size = If non-zero overrides the length in the adapter object
557 * BytesWritten = Address of buffer to place number of bytes written
558 * NOTES:
559 * If the specified buffer is too small, a new buffer is allocated,
560 * and the query is attempted again
561 * RETURNS:
562 * Status of operation
563 * TODO:
564 * Is there any way to use the buffer provided by the protocol?
565 */
566 {
567 NDIS_STATUS NdisStatus;
568 ULONG BytesNeeded;
569
570 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
571
572 if (Adapter->QueryBufferLength == 0)
573 {
574 /* XXX is 32 the right number? */
575 Adapter->QueryBuffer = ExAllocatePool(NonPagedPool, (Size == 0)? 32 : Size);
576
577 if (!Adapter->QueryBuffer)
578 {
579 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
580 return NDIS_STATUS_RESOURCES;
581 }
582
583 /* ditto */
584 Adapter->QueryBufferLength = (Size == 0)? 32 : Size;
585 }
586
587 /* this is the third time i've seen this conditional */
588 BytesNeeded = (Size == 0)? Adapter->QueryBufferLength : Size;
589
590 /* call the miniport's queryinfo handler */
591 NdisStatus = (*Adapter->Miniport->Chars.QueryInformationHandler)(
592 Adapter->NdisMiniportBlock.MiniportAdapterContext,
593 Oid,
594 Adapter->QueryBuffer,
595 BytesNeeded,
596 BytesWritten,
597 &BytesNeeded);
598
599 /* XXX is status_pending part of success macro? */
600 if ((NT_SUCCESS(NdisStatus)) || (NdisStatus == NDIS_STATUS_PENDING))
601 {
602 NDIS_DbgPrint(DEBUG_MINIPORT, ("Miniport returned status (0x%X).\n", NdisStatus));
603 return NdisStatus;
604 }
605
606 if (NdisStatus == NDIS_STATUS_INVALID_LENGTH)
607 {
608 ExFreePool(Adapter->QueryBuffer);
609
610 Adapter->QueryBufferLength += BytesNeeded;
611 Adapter->QueryBuffer = ExAllocatePool(NonPagedPool, Adapter->QueryBufferLength);
612
613 if (!Adapter->QueryBuffer)
614 {
615 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
616 return NDIS_STATUS_RESOURCES;
617 }
618
619 NdisStatus = (*Adapter->Miniport->Chars.QueryInformationHandler)(
620 Adapter->NdisMiniportBlock.MiniportAdapterContext,
621 Oid,
622 Adapter->QueryBuffer,
623 Adapter->QueryBufferLength,
624 BytesWritten,
625 &BytesNeeded);
626 }
627
628 return NdisStatus;
629 }
630
631 \f
632 NDIS_STATUS
633 FASTCALL
634 MiniQueueWorkItem(
635 PADAPTER_BINDING AdapterBinding,
636 NDIS_WORK_ITEM_TYPE WorkItemType,
637 PVOID WorkItemContext)
638 /*
639 * FUNCTION: Queues a work item for execution at a later time
640 * ARGUMENTS:
641 * Adapter = Pointer to the logical adapter object to queue work item on
642 * WorkItemType = Type of work item to queue
643 * WorkItemContext = Pointer to context information for work item
644 * NOTES:
645 * Adapter lock must be held when called
646 * RETURNS:
647 * Status of operation
648 */
649 {
650 PINTERNAL_NDIS_MINIPORT_WORK_ITEM Item;
651 PLOGICAL_ADAPTER Adapter = AdapterBinding->Adapter;
652
653 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
654
655 ASSERT(Adapter);
656 ASSERT(KeGetCurrentIrql() >= DISPATCH_LEVEL);
657
658 #if 0
659 if (Adapter->WorkQueueLevel < NDIS_MINIPORT_WORK_QUEUE_SIZE - 1)
660 {
661 Item = &Adapter->WorkQueue[Adapter->WorkQueueLevel];
662 Adapter->WorkQueueLevel++;
663 }
664 else
665 #endif
666 {
667 Item = ExAllocatePool(NonPagedPool, sizeof(INTERNAL_NDIS_MINIPORT_WORK_ITEM));
668 if (Item == NULL)
669 {
670 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
671 return NDIS_STATUS_RESOURCES;
672 }
673 }
674
675 Item->AdapterBinding = AdapterBinding;
676 Item->RealWorkItem.WorkItemType = WorkItemType;
677 Item->RealWorkItem.WorkItemContext = WorkItemContext;
678
679 /* safe due to adapter lock held */
680 Item->Link.Next = NULL;
681 if (!Adapter->WorkQueueHead)
682 {
683 Adapter->WorkQueueHead = Item;
684 Adapter->WorkQueueTail = Item;
685 }
686 else
687 {
688 Adapter->WorkQueueTail->Link.Next = (PSINGLE_LIST_ENTRY)Item;
689 Adapter->WorkQueueTail = Item;
690 }
691
692 KeInsertQueueDpc(&Adapter->MiniportDpc, NULL, NULL);
693
694 return NDIS_STATUS_SUCCESS;
695 }
696
697 \f
698 NDIS_STATUS
699 FASTCALL
700 MiniDequeueWorkItem(
701 PLOGICAL_ADAPTER Adapter,
702 PADAPTER_BINDING *AdapterBinding,
703 NDIS_WORK_ITEM_TYPE *WorkItemType,
704 PVOID *WorkItemContext)
705 /*
706 * FUNCTION: Dequeues a work item from the work queue of a logical adapter
707 * ARGUMENTS:
708 * Adapter = Pointer to the logical adapter object to dequeue work item from
709 * AdapterBinding = Address of buffer for adapter binding for this request
710 * WorkItemType = Address of buffer for work item type
711 * WorkItemContext = Address of buffer for pointer to context information
712 * NOTES:
713 * Adapter lock must be held when called
714 * RETURNS:
715 * Status of operation
716 */
717 {
718 PINTERNAL_NDIS_MINIPORT_WORK_ITEM Item;
719
720 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
721
722 Item = Adapter->WorkQueueHead;
723
724 if (Item)
725 {
726 /* safe due to adapter lock held */
727 Adapter->WorkQueueHead = (PINTERNAL_NDIS_MINIPORT_WORK_ITEM)Item->Link.Next;
728
729 if (Item == Adapter->WorkQueueTail)
730 Adapter->WorkQueueTail = NULL;
731
732 *AdapterBinding = Item->AdapterBinding;
733 *WorkItemType = Item->RealWorkItem.WorkItemType;
734 *WorkItemContext = Item->RealWorkItem.WorkItemContext;
735
736 ExFreePool(Item);
737
738 return NDIS_STATUS_SUCCESS;
739 }
740
741 return NDIS_STATUS_FAILURE;
742 }
743
744 \f
745 NDIS_STATUS
746 MiniDoRequest(
747 PADAPTER_BINDING AdapterBinding,
748 PNDIS_REQUEST NdisRequest)
749 /*
750 * FUNCTION: Sends a request to a miniport
751 * ARGUMENTS:
752 * AdapterBinding = Pointer to binding used in the request
753 * NdisRequest = Pointer to NDIS request structure describing request
754 * RETURNS:
755 * Status of operation
756 */
757 {
758 PLOGICAL_ADAPTER Adapter = AdapterBinding->Adapter;
759
760 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
761
762 Adapter->NdisMiniportBlock.MediaRequest = NdisRequest;
763
764 switch (NdisRequest->RequestType)
765 {
766 case NdisRequestQueryInformation:
767 return (*Adapter->Miniport->Chars.QueryInformationHandler)(
768 Adapter->NdisMiniportBlock.MiniportAdapterContext,
769 NdisRequest->DATA.QUERY_INFORMATION.Oid,
770 NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer,
771 NdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength,
772 (PULONG)&NdisRequest->DATA.QUERY_INFORMATION.BytesWritten,
773 (PULONG)&NdisRequest->DATA.QUERY_INFORMATION.BytesNeeded);
774 break;
775
776 case NdisRequestSetInformation:
777 return (*Adapter->Miniport->Chars.SetInformationHandler)(
778 Adapter->NdisMiniportBlock.MiniportAdapterContext,
779 NdisRequest->DATA.SET_INFORMATION.Oid,
780 NdisRequest->DATA.SET_INFORMATION.InformationBuffer,
781 NdisRequest->DATA.SET_INFORMATION.InformationBufferLength,
782 (PULONG)&NdisRequest->DATA.SET_INFORMATION.BytesRead,
783 (PULONG)&NdisRequest->DATA.SET_INFORMATION.BytesNeeded);
784 break;
785
786 default:
787 return NDIS_STATUS_FAILURE;
788 }
789 }
790
791 \f
792 #undef NdisMQueryInformationComplete
793 /*
794 * @implemented
795 */
796 VOID
797 EXPORT
798 NdisMQueryInformationComplete(
799 IN NDIS_HANDLE MiniportAdapterHandle,
800 IN NDIS_STATUS Status)
801 {
802 PNDIS_MINIPORT_BLOCK MiniportBlock =
803 (PNDIS_MINIPORT_BLOCK)MiniportAdapterHandle;
804 ASSERT(MiniportBlock);
805 if( MiniportBlock->QueryCompleteHandler )
806 (MiniportBlock->QueryCompleteHandler)(MiniportAdapterHandle, Status);
807 }
808
809 \f
810 VOID NTAPI MiniportDpc(
811 IN PKDPC Dpc,
812 IN PVOID DeferredContext,
813 IN PVOID SystemArgument1,
814 IN PVOID SystemArgument2)
815 /*
816 * FUNCTION: Deferred routine to handle serialization
817 * ARGUMENTS:
818 * Dpc = Pointer to DPC object
819 * DeferredContext = Pointer to context information (LOGICAL_ADAPTER)
820 * SystemArgument1 = Unused
821 * SystemArgument2 = Unused
822 */
823 {
824 NDIS_STATUS NdisStatus;
825 PVOID WorkItemContext;
826 NDIS_WORK_ITEM_TYPE WorkItemType;
827 PADAPTER_BINDING AdapterBinding;
828 PLOGICAL_ADAPTER Adapter = GET_LOGICAL_ADAPTER(DeferredContext);
829
830 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
831
832 NdisStatus =
833 MiniDequeueWorkItem
834 (Adapter, &AdapterBinding, &WorkItemType, &WorkItemContext);
835
836 if (NdisStatus == NDIS_STATUS_SUCCESS)
837 {
838 switch (WorkItemType)
839 {
840 case NdisWorkItemSend:
841 /*
842 * called by ProSend when protocols want to send packets to the miniport
843 */
844 #ifdef DBG
845 MiniDisplayPacket((PNDIS_PACKET)WorkItemContext);
846 #endif
847 if(Adapter->Miniport->Chars.SendPacketsHandler)
848 {
849 NDIS_DbgPrint(MAX_TRACE, ("Calling miniport's SendPackets handler\n"));
850
851 /*
852 * XXX assumes single-packet - prolly OK since we'll call something
853 * different on multi-packet sends
854 */
855 (*Adapter->Miniport->Chars.SendPacketsHandler)(
856 Adapter->NdisMiniportBlock.MiniportAdapterContext, (PPNDIS_PACKET)&WorkItemContext, 1);
857 NdisStatus =
858 NDIS_GET_PACKET_STATUS((PNDIS_PACKET)WorkItemContext);
859
860 NDIS_DbgPrint(MAX_TRACE, ("back from miniport's SendPackets handler\n"));
861 }
862 else
863 {
864 NDIS_DbgPrint(MAX_TRACE, ("Calling miniport's Send handler\n"));
865
866 NdisStatus = (*Adapter->Miniport->Chars.SendHandler)(
867 Adapter->NdisMiniportBlock.MiniportAdapterContext, (PNDIS_PACKET)WorkItemContext, 0);
868
869 NDIS_DbgPrint(MAX_TRACE, ("back from miniport's Send handler\n"));
870 }
871 if( NdisStatus != NDIS_STATUS_PENDING ) {
872 NdisMSendComplete
873 ( Adapter, (PNDIS_PACKET)WorkItemContext, NdisStatus );
874 Adapter->MiniportBusy = FALSE;
875 }
876 break;
877
878 case NdisWorkItemSendLoopback:
879 /*
880 * called by ProSend when protocols want to send loopback packets
881 */
882 /* XXX atm ProIndicatePacket sends a packet up via the loopback adapter only */
883 NdisStatus = ProIndicatePacket(Adapter, (PNDIS_PACKET)WorkItemContext);
884 MiniSendComplete((NDIS_HANDLE)Adapter, (PNDIS_PACKET)WorkItemContext, NdisStatus);
885 break;
886
887 case NdisWorkItemReturnPackets:
888 break;
889
890 case NdisWorkItemResetRequested:
891 break;
892
893 case NdisWorkItemResetInProgress:
894 break;
895
896 case NdisWorkItemHalt:
897 break;
898
899 case NdisWorkItemMiniportCallback:
900 break;
901
902 case NdisWorkItemRequest:
903 NdisStatus = MiniDoRequest(AdapterBinding, (PNDIS_REQUEST)WorkItemContext);
904
905 if (NdisStatus == NDIS_STATUS_PENDING)
906 break;
907
908 switch (((PNDIS_REQUEST)WorkItemContext)->RequestType)
909 {
910 case NdisRequestQueryInformation:
911 NdisMQueryInformationComplete((NDIS_HANDLE)Adapter, NdisStatus);
912 MiniRequestComplete( AdapterBinding, (PNDIS_REQUEST)WorkItemContext, NdisStatus );
913 break;
914
915 case NdisRequestSetInformation:
916 NdisMSetInformationComplete((NDIS_HANDLE)Adapter, NdisStatus);
917 MiniRequestComplete( AdapterBinding, (PNDIS_REQUEST)WorkItemContext, NdisStatus );
918 break;
919
920 default:
921 NDIS_DbgPrint(MIN_TRACE, ("Unknown NDIS request type.\n"));
922 break;
923 }
924 break;
925
926 default:
927 NDIS_DbgPrint(MIN_TRACE, ("Unknown NDIS work item type (%d).\n", WorkItemType));
928 break;
929 }
930 }
931 }
932
933 \f
934 /*
935 * @unimplemented
936 */
937 VOID
938 EXPORT
939 NdisMCloseLog(
940 IN NDIS_HANDLE LogHandle)
941 {
942 UNIMPLEMENTED
943 }
944
945 \f
946 /*
947 * @unimplemented
948 */
949 NDIS_STATUS
950 EXPORT
951 NdisMCreateLog(
952 IN NDIS_HANDLE MiniportAdapterHandle,
953 IN UINT Size,
954 OUT PNDIS_HANDLE LogHandle)
955 {
956 UNIMPLEMENTED
957
958 return NDIS_STATUS_FAILURE;
959 }
960
961 \f
962 /*
963 * @implemented
964 */
965 VOID
966 EXPORT
967 NdisMDeregisterAdapterShutdownHandler(
968 IN NDIS_HANDLE MiniportHandle)
969 /*
970 * FUNCTION: de-registers a shutdown handler
971 * ARGUMENTS: MiniportHandle: Handle passed into MiniportInitialize
972 */
973 {
974 PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)MiniportHandle;
975
976 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
977
978 if(Adapter->BugcheckContext->ShutdownHandler)
979 KeDeregisterBugCheckCallback(Adapter->BugcheckContext->CallbackRecord);
980 }
981
982 \f
983 /*
984 * @unimplemented
985 */
986 VOID
987 EXPORT
988 NdisMFlushLog(
989 IN NDIS_HANDLE LogHandle)
990 {
991 UNIMPLEMENTED
992 }
993
994 #undef NdisMIndicateStatus
995
996 /*
997 * @unimplemented
998 */
999 VOID
1000 EXPORT
1001 NdisMIndicateStatus(
1002 IN NDIS_HANDLE MiniportAdapterHandle,
1003 IN NDIS_STATUS GeneralStatus,
1004 IN PVOID StatusBuffer,
1005 IN UINT StatusBufferSize)
1006 {
1007 UNIMPLEMENTED
1008 }
1009
1010 #undef NdisMIndicateStatusComplete
1011
1012 /*
1013 * @unimplemented
1014 */
1015 VOID
1016 EXPORT
1017 NdisMIndicateStatusComplete(
1018 IN NDIS_HANDLE MiniportAdapterHandle)
1019 {
1020 UNIMPLEMENTED
1021 }
1022
1023 \f
1024 /*
1025 * @implemented
1026 */
1027 VOID
1028 EXPORT
1029 NdisInitializeWrapper(
1030 OUT PNDIS_HANDLE NdisWrapperHandle,
1031 IN PVOID SystemSpecific1,
1032 IN PVOID SystemSpecific2,
1033 IN PVOID SystemSpecific3)
1034 /*
1035 * FUNCTION: Notifies the NDIS library that a new miniport is initializing
1036 * ARGUMENTS:
1037 * NdisWrapperHandle = Address of buffer to place NDIS wrapper handle
1038 * SystemSpecific1 = Pointer to the driver's driver object
1039 * SystemSpecific2 = Pointer to the driver's registry path
1040 * SystemSpecific3 = Always NULL
1041 * NOTES:
1042 * - SystemSpecific2 goes invalid so we copy it
1043 */
1044 {
1045 PMINIPORT_DRIVER Miniport;
1046 PUNICODE_STRING RegistryPath;
1047 WCHAR *RegistryBuffer;
1048
1049 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
1050
1051 ASSERT(NdisWrapperHandle);
1052
1053 *NdisWrapperHandle = NULL;
1054
1055 #if BREAK_ON_MINIPORT_INIT
1056 __asm__ ("int $3\n");
1057 #endif
1058
1059 Miniport = ExAllocatePool(NonPagedPool, sizeof(MINIPORT_DRIVER));
1060
1061 if (!Miniport)
1062 {
1063 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
1064 return;
1065 }
1066
1067 RtlZeroMemory(Miniport, sizeof(MINIPORT_DRIVER));
1068
1069 KeInitializeSpinLock(&Miniport->Lock);
1070
1071 Miniport->RefCount = 1;
1072
1073 Miniport->DriverObject = (PDRIVER_OBJECT)SystemSpecific1;
1074
1075 /* set the miniport's driver registry path */
1076 RegistryPath = ExAllocatePool(PagedPool, sizeof(UNICODE_STRING));
1077 if(!RegistryPath)
1078 {
1079 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
1080 return;
1081 }
1082
1083 RegistryPath->Length = ((PUNICODE_STRING)SystemSpecific2)->Length;
1084 RegistryPath->MaximumLength = RegistryPath->Length + sizeof(WCHAR); /* room for 0-term */
1085
1086 RegistryBuffer = ExAllocatePool(PagedPool, RegistryPath->MaximumLength);
1087 if(!RegistryBuffer)
1088 {
1089 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
1090 return;
1091 }
1092
1093 RtlCopyMemory(RegistryBuffer, ((PUNICODE_STRING)SystemSpecific2)->Buffer, RegistryPath->Length);
1094 RegistryBuffer[RegistryPath->Length/sizeof(WCHAR)] = 0;
1095
1096 RegistryPath->Buffer = RegistryBuffer;
1097 Miniport->RegistryPath = RegistryPath;
1098
1099 InitializeListHead(&Miniport->AdapterListHead);
1100
1101 /* Put miniport in global miniport list */
1102 ExInterlockedInsertTailList(&MiniportListHead, &Miniport->ListEntry, &MiniportListLock);
1103
1104 *NdisWrapperHandle = Miniport;
1105 }
1106
1107 \f
1108 VOID NTAPI NdisIBugcheckCallback(
1109 IN PVOID Buffer,
1110 IN ULONG Length)
1111 /*
1112 * FUNCTION: Internal callback for handling bugchecks - calls adapter's shutdown handler
1113 * ARGUMENTS:
1114 * Buffer: Pointer to a bugcheck callback context
1115 * Length: Unused
1116 */
1117 {
1118 PMINIPORT_BUGCHECK_CONTEXT Context = (PMINIPORT_BUGCHECK_CONTEXT)Buffer;
1119 ADAPTER_SHUTDOWN_HANDLER sh = (ADAPTER_SHUTDOWN_HANDLER)Context->ShutdownHandler;
1120
1121 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
1122
1123 if(sh)
1124 sh(Context->DriverContext);
1125 }
1126
1127 \f
1128 /*
1129 * @implemented
1130 */
1131 VOID
1132 EXPORT
1133 NdisMRegisterAdapterShutdownHandler(
1134 IN NDIS_HANDLE MiniportHandle,
1135 IN PVOID ShutdownContext,
1136 IN ADAPTER_SHUTDOWN_HANDLER ShutdownHandler)
1137 /*
1138 * FUNCTION: Register a shutdown handler for an adapter
1139 * ARGUMENTS:
1140 * MiniportHandle: Handle originally passed into MiniportInitialize
1141 * ShutdownContext: Pre-initialized bugcheck context
1142 * ShutdownHandler: Function to call to handle the bugcheck
1143 * NOTES:
1144 * - I'm not sure about ShutdownContext
1145 * - FIXME - memory leak below
1146 */
1147 {
1148 PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)MiniportHandle;
1149 PMINIPORT_BUGCHECK_CONTEXT BugcheckContext = Adapter->BugcheckContext;
1150
1151 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
1152
1153 if(BugcheckContext)
1154 return;
1155
1156 BugcheckContext = ExAllocatePool(NonPagedPool, sizeof(MINIPORT_BUGCHECK_CONTEXT));
1157 if(!BugcheckContext)
1158 {
1159 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
1160 return;
1161 }
1162
1163 BugcheckContext->ShutdownHandler = ShutdownHandler;
1164 BugcheckContext->DriverContext = ShutdownContext;
1165
1166 /* not sure if this needs to be initialized or not... oh well, it's a leak. */
1167 BugcheckContext->CallbackRecord = ExAllocatePool(NonPagedPool, sizeof(KBUGCHECK_CALLBACK_RECORD));
1168
1169 KeRegisterBugCheckCallback(BugcheckContext->CallbackRecord, NdisIBugcheckCallback,
1170 BugcheckContext, sizeof(BugcheckContext), (PUCHAR)"Ndis Miniport");
1171 }
1172
1173 \f
1174 NDIS_STATUS
1175 DoQueries(
1176 PLOGICAL_ADAPTER Adapter,
1177 NDIS_OID AddressOID)
1178 /*
1179 * FUNCTION: Queries miniport for information
1180 * ARGUMENTS:
1181 * Adapter = Pointer to logical adapter
1182 * AddressOID = OID to use to query for current address
1183 * RETURNS:
1184 * Status of operation
1185 */
1186 {
1187 ULONG BytesWritten;
1188 NDIS_STATUS NdisStatus;
1189
1190 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
1191
1192 /* Get MAC options for adapter */
1193 NdisStatus = MiniQueryInformation(Adapter, OID_GEN_MAC_OPTIONS, 0, &BytesWritten);
1194
1195 if (NdisStatus != NDIS_STATUS_SUCCESS)
1196 {
1197 NDIS_DbgPrint(MIN_TRACE, ("OID_GEN_MAC_OPTIONS failed. NdisStatus (0x%X).\n", NdisStatus));
1198 return NdisStatus;
1199 }
1200
1201 RtlCopyMemory(&Adapter->NdisMiniportBlock.MacOptions, Adapter->QueryBuffer, sizeof(UINT));
1202
1203 NDIS_DbgPrint(DEBUG_MINIPORT, ("MacOptions (0x%X).\n", Adapter->NdisMiniportBlock.MacOptions));
1204
1205 /* Get current hardware address of adapter */
1206 NdisStatus = MiniQueryInformation(Adapter, AddressOID, 0, &BytesWritten);
1207
1208 if (NdisStatus != NDIS_STATUS_SUCCESS)
1209 {
1210 NDIS_DbgPrint(MIN_TRACE, ("Address OID (0x%X) failed. NdisStatus (0x%X).\n", AddressOID, NdisStatus));
1211 return NdisStatus;
1212 }
1213
1214 RtlCopyMemory(&Adapter->Address, Adapter->QueryBuffer, Adapter->AddressLength);
1215 #ifdef DBG
1216 {
1217 /* 802.3 only */
1218
1219 PUCHAR A = (PUCHAR)&Adapter->Address.Type.Medium802_3;
1220
1221 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]));
1222 }
1223 #endif /* DBG */
1224
1225 /* Get maximum lookahead buffer size of adapter */
1226 NdisStatus = MiniQueryInformation(Adapter, OID_GEN_MAXIMUM_LOOKAHEAD, 0, &BytesWritten);
1227
1228 if (NdisStatus != NDIS_STATUS_SUCCESS)
1229 {
1230 NDIS_DbgPrint(MIN_TRACE, ("OID_GEN_MAXIMUM_LOOKAHEAD failed. NdisStatus (0x%X).\n", NdisStatus));
1231 return NdisStatus;
1232 }
1233
1234 Adapter->NdisMiniportBlock.MaximumLookahead = *((PULONG)Adapter->QueryBuffer);
1235
1236 NDIS_DbgPrint(DEBUG_MINIPORT, ("MaxLookaheadLength (0x%X).\n", Adapter->NdisMiniportBlock.MaximumLookahead));
1237
1238 /* Get current lookahead buffer size of adapter */
1239 NdisStatus = MiniQueryInformation(Adapter, OID_GEN_CURRENT_LOOKAHEAD, 0, &BytesWritten);
1240
1241 if (NdisStatus != NDIS_STATUS_SUCCESS)
1242 {
1243 NDIS_DbgPrint(MIN_TRACE, ("OID_GEN_CURRENT_LOOKAHEAD failed. NdisStatus (0x%X).\n", NdisStatus));
1244 return NdisStatus;
1245 }
1246
1247 Adapter->NdisMiniportBlock.CurrentLookahead = *((PULONG)Adapter->QueryBuffer);
1248
1249 NDIS_DbgPrint(DEBUG_MINIPORT, ("CurLookaheadLength (0x%X).\n", Adapter->NdisMiniportBlock.CurrentLookahead));
1250
1251 if (Adapter->NdisMiniportBlock.MaximumLookahead != 0)
1252 {
1253 Adapter->LookaheadLength = Adapter->NdisMiniportBlock.MaximumLookahead + Adapter->MediumHeaderSize;
1254 Adapter->LookaheadBuffer = ExAllocatePool(NonPagedPool, Adapter->LookaheadLength);
1255
1256 if (!Adapter->LookaheadBuffer)
1257 return NDIS_STATUS_RESOURCES;
1258 }
1259
1260 return STATUS_SUCCESS;
1261 }
1262
1263 \f
1264 NTSTATUS
1265 NTAPI
1266 NdisIForwardIrpAndWaitCompletionRoutine(
1267 PDEVICE_OBJECT Fdo,
1268 PIRP Irp,
1269 PVOID Context)
1270 {
1271 PKEVENT Event = Context;
1272
1273 if (Irp->PendingReturned)
1274 KeSetEvent(Event, IO_NO_INCREMENT, FALSE);
1275
1276 return STATUS_MORE_PROCESSING_REQUIRED;
1277 }
1278
1279 \f
1280 NTSTATUS
1281 NTAPI
1282 NdisIForwardIrpAndWait(PLOGICAL_ADAPTER Adapter, PIRP Irp)
1283 {
1284 KEVENT Event;
1285 NTSTATUS Status;
1286
1287 KeInitializeEvent(&Event, NotificationEvent, FALSE);
1288 IoCopyCurrentIrpStackLocationToNext(Irp);
1289 IoSetCompletionRoutine(Irp, NdisIForwardIrpAndWaitCompletionRoutine, &Event,
1290 TRUE, TRUE, TRUE);
1291 Status = IoCallDriver(Adapter->NdisMiniportBlock.NextDeviceObject, Irp);
1292 if (Status == STATUS_PENDING)
1293 {
1294 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
1295 Status = Irp->IoStatus.Status;
1296 }
1297 return Status;
1298 }
1299
1300 \f
1301 NTSTATUS
1302 NTAPI
1303 NdisIPnPStartDevice(
1304 IN PDEVICE_OBJECT DeviceObject,
1305 PIRP Irp)
1306 /*
1307 * FUNCTION: Handle the PnP start device event
1308 * ARGUMENTS:
1309 * DeviceObejct = Functional Device Object
1310 * Irp = IRP_MN_START_DEVICE I/O request packet
1311 * RETURNS:
1312 * Status of operation
1313 */
1314 {
1315 PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
1316 PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)DeviceObject->DeviceExtension;
1317 NDIS_WRAPPER_CONTEXT WrapperContext;
1318 NDIS_STATUS NdisStatus;
1319 NDIS_STATUS OpenErrorStatus;
1320 NTSTATUS Status;
1321 UINT SelectedMediumIndex = 0;
1322 NDIS_OID AddressOID;
1323 BOOLEAN Success = FALSE;
1324 ULONG ResourceCount;
1325 ULONG ResourceListSize;
1326 UNICODE_STRING ParamName;
1327 PNDIS_CONFIGURATION_PARAMETER ConfigParam;
1328 NDIS_HANDLE ConfigHandle;
1329 ULONG Size;
1330 /* FIXME - KIRQL OldIrql; */
1331
1332 /*
1333 * Prepare wrapper context used by HW and configuration routines.
1334 */
1335
1336 Status = IoOpenDeviceRegistryKey(
1337 Adapter->NdisMiniportBlock.PhysicalDeviceObject, PLUGPLAY_REGKEY_DRIVER,
1338 KEY_ALL_ACCESS, &WrapperContext.RegistryHandle);
1339 if (!NT_SUCCESS(Status))
1340 {
1341 NDIS_DbgPrint(MIN_TRACE,("failed to open adapter-specific reg key\n"));
1342 return Status;
1343 }
1344
1345 NDIS_DbgPrint(MAX_TRACE, ("opened device reg key\n"));
1346
1347 WrapperContext.DeviceObject = Adapter->NdisMiniportBlock.DeviceObject;
1348
1349 /*
1350 * Store the adapter resources used by HW routines such as
1351 * NdisMQueryAdapterResources.
1352 */
1353
1354 if (Stack->Parameters.StartDevice.AllocatedResources != NULL &&
1355 Stack->Parameters.StartDevice.AllocatedResourcesTranslated != NULL)
1356 {
1357 ResourceCount = Stack->Parameters.StartDevice.AllocatedResources->List[0].
1358 PartialResourceList.Count;
1359 ResourceListSize =
1360 FIELD_OFFSET(CM_RESOURCE_LIST, List[0].PartialResourceList.
1361 PartialDescriptors[ResourceCount]);
1362
1363 Adapter->NdisMiniportBlock.AllocatedResources =
1364 ExAllocatePool(PagedPool, ResourceListSize);
1365 if (Adapter->NdisMiniportBlock.AllocatedResources == NULL)
1366 {
1367 return STATUS_INSUFFICIENT_RESOURCES;
1368 }
1369
1370 Adapter->NdisMiniportBlock.AllocatedResourcesTranslated =
1371 ExAllocatePool(PagedPool, ResourceListSize);
1372 if (Adapter->NdisMiniportBlock.AllocatedResourcesTranslated == NULL)
1373 {
1374 ExFreePool(Adapter->NdisMiniportBlock.AllocatedResources);
1375 Adapter->NdisMiniportBlock.AllocatedResources = NULL;
1376 return STATUS_INSUFFICIENT_RESOURCES;
1377 }
1378
1379 RtlCopyMemory(Adapter->NdisMiniportBlock.AllocatedResources,
1380 Stack->Parameters.StartDevice.AllocatedResources,
1381 ResourceListSize);
1382
1383 RtlCopyMemory(Adapter->NdisMiniportBlock.AllocatedResourcesTranslated,
1384 Stack->Parameters.StartDevice.AllocatedResourcesTranslated,
1385 ResourceListSize);
1386 }
1387
1388 /*
1389 * Store the Bus Type, Bus Number and Slot information. It's used by
1390 * the hardware routines then.
1391 */
1392
1393 NdisOpenConfiguration(&NdisStatus, &ConfigHandle, (NDIS_HANDLE)&WrapperContext);
1394
1395 Size = sizeof(ULONG);
1396 Status = IoGetDeviceProperty(Adapter->NdisMiniportBlock.PhysicalDeviceObject,
1397 DevicePropertyLegacyBusType, Size,
1398 &Adapter->NdisMiniportBlock.BusType, &Size);
1399 if (!NT_SUCCESS(Status) || Adapter->NdisMiniportBlock.BusType == (NDIS_INTERFACE_TYPE)-1)
1400 {
1401 NdisInitUnicodeString(&ParamName, L"BusType");
1402 NdisReadConfiguration(&NdisStatus, &ConfigParam, ConfigHandle,
1403 &ParamName, NdisParameterInteger);
1404 if (NdisStatus == NDIS_STATUS_SUCCESS)
1405 Adapter->NdisMiniportBlock.BusType = ConfigParam->ParameterData.IntegerData;
1406 else
1407 Adapter->NdisMiniportBlock.BusType = Isa;
1408 }
1409
1410 Status = IoGetDeviceProperty(Adapter->NdisMiniportBlock.PhysicalDeviceObject,
1411 DevicePropertyBusNumber, Size,
1412 &Adapter->NdisMiniportBlock.BusNumber, &Size);
1413 if (!NT_SUCCESS(Status) || Adapter->NdisMiniportBlock.BusNumber == (NDIS_INTERFACE_TYPE)-1)
1414 {
1415 NdisInitUnicodeString(&ParamName, L"BusNumber");
1416 NdisReadConfiguration(&NdisStatus, &ConfigParam, ConfigHandle,
1417 &ParamName, NdisParameterInteger);
1418 if (NdisStatus == NDIS_STATUS_SUCCESS)
1419 Adapter->NdisMiniportBlock.BusNumber = ConfigParam->ParameterData.IntegerData;
1420 else
1421 Adapter->NdisMiniportBlock.BusNumber = 0;
1422 }
1423 WrapperContext.BusNumber = Adapter->NdisMiniportBlock.BusNumber;
1424
1425 Status = IoGetDeviceProperty(Adapter->NdisMiniportBlock.PhysicalDeviceObject,
1426 DevicePropertyAddress, Size,
1427 &Adapter->NdisMiniportBlock.SlotNumber, &Size);
1428 if (!NT_SUCCESS(Status) || Adapter->NdisMiniportBlock.SlotNumber == (NDIS_INTERFACE_TYPE)-1)
1429 {
1430 NdisInitUnicodeString(&ParamName, L"SlotNumber");
1431 NdisReadConfiguration(&NdisStatus, &ConfigParam, ConfigHandle,
1432 &ParamName, NdisParameterInteger);
1433 if (NdisStatus == NDIS_STATUS_SUCCESS)
1434 Adapter->NdisMiniportBlock.SlotNumber = ConfigParam->ParameterData.IntegerData;
1435 else
1436 Adapter->NdisMiniportBlock.SlotNumber = 0;
1437 }
1438
1439 NdisCloseConfiguration(ConfigHandle);
1440
1441 /*
1442 * Call MiniportInitialize.
1443 */
1444
1445 NDIS_DbgPrint(MID_TRACE, ("calling MiniportInitialize\n"));
1446 NdisStatus = (*Adapter->Miniport->Chars.InitializeHandler)(
1447 &OpenErrorStatus, &SelectedMediumIndex, &MediaArray[0],
1448 MEDIA_ARRAY_SIZE, Adapter, (NDIS_HANDLE)&WrapperContext);
1449
1450 ZwClose(WrapperContext.RegistryHandle);
1451
1452 if (NdisStatus != NDIS_STATUS_SUCCESS ||
1453 SelectedMediumIndex >= MEDIA_ARRAY_SIZE)
1454 {
1455 NDIS_DbgPrint(MIN_TRACE, ("MiniportInitialize() failed for an adapter.\n"));
1456 return (NTSTATUS)NdisStatus;
1457 }
1458
1459 /* Set handlers (some NDIS macros require these) */
1460
1461 Adapter->NdisMiniportBlock.EthRxCompleteHandler = EthFilterDprIndicateReceiveComplete;
1462 Adapter->NdisMiniportBlock.EthRxIndicateHandler = EthFilterDprIndicateReceive;
1463 Adapter->NdisMiniportBlock.SendCompleteHandler = MiniSendComplete;
1464 Adapter->NdisMiniportBlock.SendResourcesHandler = MiniSendResourcesAvailable;
1465 Adapter->NdisMiniportBlock.ResetCompleteHandler = MiniResetComplete;
1466 Adapter->NdisMiniportBlock.TDCompleteHandler = MiniTransferDataComplete;
1467 Adapter->NdisMiniportBlock.PacketIndicateHandler= MiniIndicateReceivePacket;
1468
1469 Adapter->NdisMiniportBlock.MediaType = MediaArray[SelectedMediumIndex];
1470
1471 switch (Adapter->NdisMiniportBlock.MediaType)
1472 {
1473 case NdisMedium802_3:
1474 Adapter->MediumHeaderSize = 14; /* XXX figure out what to do about LLC */
1475 AddressOID = OID_802_3_CURRENT_ADDRESS;
1476 Adapter->AddressLength = ETH_LENGTH_OF_ADDRESS;
1477 NdisStatus = DoQueries(Adapter, AddressOID);
1478 if (NdisStatus == NDIS_STATUS_SUCCESS)
1479 {
1480 Success = EthCreateFilter(32, /* FIXME: Query this from miniport. */
1481 Adapter->Address.Type.Medium802_3,
1482 &Adapter->NdisMiniportBlock.EthDB);
1483 if (Success)
1484 ((PETHI_FILTER)Adapter->NdisMiniportBlock.EthDB)->Miniport = (PNDIS_MINIPORT_BLOCK)Adapter;
1485 else
1486 NdisStatus = NDIS_STATUS_RESOURCES;
1487 }
1488 break;
1489
1490 default:
1491 /* FIXME: Support other types of media */
1492 NDIS_DbgPrint(MIN_TRACE, ("error: unsupported media\n"));
1493 ASSERT(FALSE);
1494 /* FIXME - KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql); */
1495 return STATUS_UNSUCCESSFUL;
1496 }
1497
1498 if (!Success || NdisStatus != NDIS_STATUS_SUCCESS)
1499 {
1500 NDIS_DbgPrint(MAX_TRACE, ("couldn't create filter (%x)\n", NdisStatus));
1501 if (Adapter->LookaheadBuffer)
1502 {
1503 ExFreePool(Adapter->LookaheadBuffer);
1504 Adapter->LookaheadBuffer = NULL;
1505 }
1506 return (NTSTATUS)NdisStatus;
1507 }
1508
1509 Adapter->NdisMiniportBlock.OldPnPDeviceState = Adapter->NdisMiniportBlock.PnPDeviceState;
1510 Adapter->NdisMiniportBlock.PnPDeviceState = NdisPnPDeviceStarted;
1511
1512 /* Put adapter in adapter list for this miniport */
1513 ExInterlockedInsertTailList(&Adapter->Miniport->AdapterListHead, &Adapter->MiniportListEntry, &Adapter->Miniport->Lock);
1514
1515 /* Put adapter in global adapter list */
1516 ExInterlockedInsertTailList(&AdapterListHead, &Adapter->ListEntry, &AdapterListLock);
1517
1518 return STATUS_SUCCESS;
1519 }
1520
1521 \f
1522 NTSTATUS
1523 NTAPI
1524 NdisIPnPStopDevice(
1525 IN PDEVICE_OBJECT DeviceObject,
1526 PIRP Irp)
1527 /*
1528 * FUNCTION: Handle the PnP stop device event
1529 * ARGUMENTS:
1530 * DeviceObejct = Functional Device Object
1531 * Irp = IRP_MN_STOP_DEVICE I/O request packet
1532 * RETURNS:
1533 * Status of operation
1534 */
1535 {
1536 PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)DeviceObject->DeviceExtension;
1537 KIRQL OldIrql;
1538
1539 /* Remove adapter from adapter list for this miniport */
1540 KeAcquireSpinLock(&Adapter->Miniport->Lock, &OldIrql);
1541 RemoveEntryList(&Adapter->MiniportListEntry);
1542 KeReleaseSpinLock(&Adapter->Miniport->Lock, OldIrql);
1543
1544 /* Remove adapter from global adapter list */
1545 KeAcquireSpinLock(&AdapterListLock, &OldIrql);
1546 RemoveEntryList(&Adapter->ListEntry);
1547 KeReleaseSpinLock(&AdapterListLock, OldIrql);
1548
1549 (*Adapter->Miniport->Chars.HaltHandler)(Adapter);
1550
1551 if (Adapter->LookaheadBuffer)
1552 {
1553 ExFreePool(Adapter->LookaheadBuffer);
1554 Adapter->LookaheadBuffer = NULL;
1555 }
1556 if (Adapter->NdisMiniportBlock.AllocatedResources)
1557 {
1558 ExFreePool(Adapter->NdisMiniportBlock.AllocatedResources);
1559 Adapter->NdisMiniportBlock.AllocatedResources = NULL;
1560 }
1561 if (Adapter->NdisMiniportBlock.AllocatedResourcesTranslated)
1562 {
1563 ExFreePool(Adapter->NdisMiniportBlock.AllocatedResourcesTranslated);
1564 Adapter->NdisMiniportBlock.AllocatedResourcesTranslated = NULL;
1565 }
1566
1567 Adapter->NdisMiniportBlock.OldPnPDeviceState = Adapter->NdisMiniportBlock.PnPDeviceState;
1568 Adapter->NdisMiniportBlock.PnPDeviceState = NdisPnPDeviceStopped;
1569
1570 return STATUS_SUCCESS;
1571 }
1572
1573 \f
1574 NTSTATUS
1575 NTAPI
1576 NdisIDispatchPnp(
1577 IN PDEVICE_OBJECT DeviceObject,
1578 PIRP Irp)
1579 {
1580 PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
1581 PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)DeviceObject->DeviceExtension;
1582 NTSTATUS Status;
1583
1584 switch (Stack->MinorFunction)
1585 {
1586 case IRP_MN_START_DEVICE:
1587 Status = NdisIForwardIrpAndWait(Adapter, Irp);
1588 if (NT_SUCCESS(Status) && NT_SUCCESS(Irp->IoStatus.Status))
1589 {
1590 Status = NdisIPnPStartDevice(DeviceObject, Irp);
1591 }
1592 Irp->IoStatus.Status = Status;
1593 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1594 break;
1595
1596 case IRP_MN_STOP_DEVICE:
1597 /* FIXME */
1598 Status = STATUS_UNSUCCESSFUL;
1599 break;
1600 Status = NdisIForwardIrpAndWait(Adapter, Irp);
1601 if (NT_SUCCESS(Status) && NT_SUCCESS(Irp->IoStatus.Status))
1602 {
1603 Status = NdisIPnPStopDevice(DeviceObject, Irp);
1604 }
1605 Irp->IoStatus.Status = Status;
1606 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1607 break;
1608
1609 default:
1610 IoSkipCurrentIrpStackLocation(Irp);
1611 Status = IoCallDriver(Adapter->NdisMiniportBlock.NextDeviceObject, Irp);
1612 break;
1613 }
1614
1615 return Status;
1616 }
1617
1618 \f
1619 NTSTATUS
1620 NTAPI
1621 NdisIAddDevice(
1622 IN PDRIVER_OBJECT DriverObject,
1623 IN PDEVICE_OBJECT PhysicalDeviceObject)
1624 /*
1625 * FUNCTION: Create a device for an adapter found using PnP
1626 * ARGUMENTS:
1627 * DriverObject = Pointer to the miniport driver object
1628 * PhysicalDeviceObject = Pointer to the PDO for our adapter
1629 */
1630 {
1631 static const WCHAR ClassKeyName[] = {'C','l','a','s','s','\\'};
1632 static const WCHAR LinkageKeyName[] = {'\\','L','i','n','k','a','g','e',0};
1633 PMINIPORT_DRIVER Miniport;
1634 PMINIPORT_DRIVER *MiniportPtr;
1635 WCHAR *LinkageKeyBuffer;
1636 ULONG DriverKeyLength;
1637 RTL_QUERY_REGISTRY_TABLE QueryTable[2];
1638 UNICODE_STRING ExportName;
1639 PDEVICE_OBJECT DeviceObject;
1640 PLOGICAL_ADAPTER Adapter;
1641 NTSTATUS Status;
1642
1643 /*
1644 * Gain the access to the miniport data structure first.
1645 */
1646
1647 MiniportPtr = IoGetDriverObjectExtension(DriverObject, (PVOID)TAG('D','I','M','N'));
1648 if (MiniportPtr == NULL)
1649 {
1650 NDIS_DbgPrint(DEBUG_MINIPORT, ("Can't get driver object extension.\n"));
1651 return STATUS_UNSUCCESSFUL;
1652 }
1653 Miniport = *MiniportPtr;
1654
1655 /*
1656 * Get name of the Linkage registry key for our adapter. It's located under
1657 * the driver key for our driver and so we have basicly two ways to do it.
1658 * Either we can use IoOpenDriverRegistryKey or compose it using information
1659 * gathered by IoGetDeviceProperty. I choosed the second because
1660 * IoOpenDriverRegistryKey wasn't implemented at the time of writing.
1661 */
1662
1663 Status = IoGetDeviceProperty(PhysicalDeviceObject, DevicePropertyDriverKeyName,
1664 0, NULL, &DriverKeyLength);
1665 if (Status != STATUS_BUFFER_TOO_SMALL)
1666 {
1667 NDIS_DbgPrint(DEBUG_MINIPORT, ("Can't get miniport driver key length.\n"));
1668 return Status;
1669 }
1670
1671 LinkageKeyBuffer = ExAllocatePool(PagedPool, DriverKeyLength +
1672 sizeof(ClassKeyName) + sizeof(LinkageKeyName));
1673 if (LinkageKeyBuffer == NULL)
1674 {
1675 NDIS_DbgPrint(DEBUG_MINIPORT, ("Can't allocate memory for driver key name.\n"));
1676 return STATUS_INSUFFICIENT_RESOURCES;
1677 }
1678
1679 Status = IoGetDeviceProperty(PhysicalDeviceObject, DevicePropertyDriverKeyName,
1680 DriverKeyLength, LinkageKeyBuffer +
1681 (sizeof(ClassKeyName) / sizeof(WCHAR)),
1682 &DriverKeyLength);
1683 if (!NT_SUCCESS(Status))
1684 {
1685 NDIS_DbgPrint(DEBUG_MINIPORT, ("Can't get miniport driver key.\n"));
1686 ExFreePool(LinkageKeyBuffer);
1687 return Status;
1688 }
1689
1690 /* Compose the linkage key name. */
1691 RtlCopyMemory(LinkageKeyBuffer, ClassKeyName, sizeof(ClassKeyName));
1692 RtlCopyMemory(LinkageKeyBuffer + ((sizeof(ClassKeyName) + DriverKeyLength) /
1693 sizeof(WCHAR)) - 1, LinkageKeyName, sizeof(LinkageKeyName));
1694
1695 NDIS_DbgPrint(DEBUG_MINIPORT, ("LinkageKey: %S.\n", LinkageKeyBuffer));
1696
1697 /*
1698 * Now open the linkage key and read the "Export" and "RootDevice" values
1699 * which contains device name and root service respectively.
1700 */
1701
1702 RtlZeroMemory(QueryTable, sizeof(QueryTable));
1703 RtlInitUnicodeString(&ExportName, NULL);
1704 QueryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED | RTL_QUERY_REGISTRY_DIRECT;
1705 QueryTable[0].Name = L"Export";
1706 QueryTable[0].EntryContext = &ExportName;
1707
1708 Status = RtlQueryRegistryValues(RTL_REGISTRY_CONTROL, LinkageKeyBuffer,
1709 QueryTable, NULL, NULL);
1710 ExFreePool(LinkageKeyBuffer);
1711 if (!NT_SUCCESS(Status))
1712 {
1713 NDIS_DbgPrint(DEBUG_MINIPORT, ("Can't get miniport device name. (%x)\n", Status));
1714 return Status;
1715 }
1716
1717 /*
1718 * Create the device object.
1719 */
1720
1721 NDIS_DbgPrint(MAX_TRACE, ("creating device %wZ\n", &ExportName));
1722
1723 Status = IoCreateDevice(Miniport->DriverObject, sizeof(LOGICAL_ADAPTER),
1724 &ExportName, FILE_DEVICE_PHYSICAL_NETCARD,
1725 0, FALSE, &DeviceObject);
1726 if (!NT_SUCCESS(Status))
1727 {
1728 NDIS_DbgPrint(MIN_TRACE, ("Could not create device object.\n"));
1729 RtlFreeUnicodeString(&ExportName);
1730 return Status;
1731 }
1732
1733 /*
1734 * Initialize the adapter structure.
1735 */
1736
1737 Adapter = (PLOGICAL_ADAPTER)DeviceObject->DeviceExtension;
1738 KeInitializeSpinLock(&Adapter->NdisMiniportBlock.Lock);
1739 InitializeListHead(&Adapter->ProtocolListHead);
1740 Adapter->RefCount = 1;
1741 Adapter->Miniport = Miniport;
1742
1743 Adapter->NdisMiniportBlock.MiniportName = ExportName;
1744
1745 Adapter->NdisMiniportBlock.DeviceObject = DeviceObject;
1746 Adapter->NdisMiniportBlock.PhysicalDeviceObject = PhysicalDeviceObject;
1747 Adapter->NdisMiniportBlock.NextDeviceObject =
1748 IoAttachDeviceToDeviceStack(Adapter->NdisMiniportBlock.DeviceObject,
1749 PhysicalDeviceObject);
1750
1751 Adapter->NdisMiniportBlock.OldPnPDeviceState = 0;
1752 Adapter->NdisMiniportBlock.PnPDeviceState = NdisPnPDeviceAdded;
1753
1754 KeInitializeDpc(&Adapter->MiniportDpc, MiniportDpc, (PVOID)Adapter);
1755
1756 DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
1757
1758 return STATUS_SUCCESS;
1759 }
1760
1761 \f
1762 /*
1763 * @implemented
1764 */
1765 NDIS_STATUS
1766 EXPORT
1767 NdisMRegisterMiniport(
1768 IN NDIS_HANDLE NdisWrapperHandle,
1769 IN PNDIS_MINIPORT_CHARACTERISTICS MiniportCharacteristics,
1770 IN UINT CharacteristicsLength)
1771 /*
1772 * FUNCTION: Registers a miniport's MiniportXxx entry points with the NDIS library
1773 * ARGUMENTS:
1774 * NdisWrapperHandle = Pointer to handle returned by NdisMInitializeWrapper
1775 * MiniportCharacteristics = Pointer to a buffer with miniport characteristics
1776 * CharacteristicsLength = Number of bytes in characteristics buffer
1777 * RETURNS:
1778 * Status of operation
1779 */
1780 {
1781 UINT MinSize;
1782 PMINIPORT_DRIVER Miniport = GET_MINIPORT_DRIVER(NdisWrapperHandle);
1783 PMINIPORT_DRIVER *MiniportPtr;
1784 NTSTATUS Status;
1785
1786 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
1787
1788 switch (MiniportCharacteristics->MajorNdisVersion)
1789 {
1790 case 0x03:
1791 MinSize = sizeof(NDIS30_MINIPORT_CHARACTERISTICS);
1792 break;
1793
1794 case 0x04:
1795 MinSize = sizeof(NDIS40_MINIPORT_CHARACTERISTICS);
1796 break;
1797
1798 case 0x05:
1799 MinSize = sizeof(NDIS50_MINIPORT_CHARACTERISTICS);
1800 break;
1801
1802 default:
1803 NDIS_DbgPrint(DEBUG_MINIPORT, ("Bad miniport characteristics version.\n"));
1804 return NDIS_STATUS_BAD_VERSION;
1805 }
1806
1807 if (CharacteristicsLength < MinSize)
1808 {
1809 NDIS_DbgPrint(DEBUG_MINIPORT, ("Bad miniport characteristics.\n"));
1810 return NDIS_STATUS_BAD_CHARACTERISTICS;
1811 }
1812
1813 /* Check if mandatory MiniportXxx functions are specified */
1814 if ((!MiniportCharacteristics->HaltHandler) ||
1815 (!MiniportCharacteristics->InitializeHandler)||
1816 (!MiniportCharacteristics->QueryInformationHandler) ||
1817 (!MiniportCharacteristics->ResetHandler) ||
1818 (!MiniportCharacteristics->SetInformationHandler))
1819 {
1820 NDIS_DbgPrint(DEBUG_MINIPORT, ("Bad miniport characteristics.\n"));
1821 return NDIS_STATUS_BAD_CHARACTERISTICS;
1822 }
1823
1824 if (MiniportCharacteristics->MajorNdisVersion == 0x03)
1825 {
1826 if (!MiniportCharacteristics->SendHandler)
1827 {
1828 NDIS_DbgPrint(DEBUG_MINIPORT, ("Bad miniport characteristics.\n"));
1829 return NDIS_STATUS_BAD_CHARACTERISTICS;
1830 }
1831 }
1832 else if (MiniportCharacteristics->MajorNdisVersion >= 0x04)
1833 {
1834 /* NDIS 4.0+ */
1835 if ((!MiniportCharacteristics->SendHandler) &&
1836 (!MiniportCharacteristics->SendPacketsHandler))
1837 {
1838 NDIS_DbgPrint(DEBUG_MINIPORT, ("Bad miniport characteristics.\n"));
1839 return NDIS_STATUS_BAD_CHARACTERISTICS;
1840 }
1841 }
1842
1843 /* TODO: verify NDIS5 and NDIS5.1 */
1844
1845 RtlCopyMemory(&Miniport->Chars, MiniportCharacteristics, MinSize);
1846
1847 /*
1848 * NOTE: This is VERY unoptimal! Should we store the MINIPORT_DRIVER
1849 * struture in the driver extension or what?
1850 */
1851
1852 Status = IoAllocateDriverObjectExtension(Miniport->DriverObject, (PVOID)TAG('D','I','M','N'),
1853 sizeof(PMINIPORT_DRIVER), (PVOID*)&MiniportPtr);
1854 if (!NT_SUCCESS(Status))
1855 {
1856 NDIS_DbgPrint(DEBUG_MINIPORT, ("Can't allocate driver object extension.\n"));
1857 return NDIS_STATUS_RESOURCES;
1858 }
1859
1860 *MiniportPtr = Miniport;
1861
1862 Miniport->DriverObject->MajorFunction[IRP_MJ_PNP] = NdisIDispatchPnp;
1863 Miniport->DriverObject->DriverExtension->AddDevice = NdisIAddDevice;
1864
1865 return NDIS_STATUS_SUCCESS;
1866 }
1867
1868 \f
1869 /*
1870 * @implemented
1871 */
1872 #undef NdisMResetComplete
1873 VOID
1874 EXPORT
1875 NdisMResetComplete(
1876 IN NDIS_HANDLE MiniportAdapterHandle,
1877 IN NDIS_STATUS Status,
1878 IN BOOLEAN AddressingReset)
1879 {
1880 MiniResetComplete(MiniportAdapterHandle, Status, AddressingReset);
1881 }
1882
1883 \f
1884 /*
1885 * @implemented
1886 */
1887 #undef NdisMSendComplete
1888 VOID
1889 EXPORT
1890 NdisMSendComplete(
1891 IN NDIS_HANDLE MiniportAdapterHandle,
1892 IN PNDIS_PACKET Packet,
1893 IN NDIS_STATUS Status)
1894 /*
1895 * FUNCTION: Forwards a message to the initiating protocol saying
1896 * that a packet was handled
1897 * ARGUMENTS:
1898 * NdisAdapterHandle = Handle input to MiniportInitialize
1899 * Packet = Pointer to NDIS packet that was sent
1900 * Status = Status of send operation
1901 */
1902 {
1903 MiniSendComplete(MiniportAdapterHandle, Packet, Status);
1904 }
1905
1906 \f
1907 /*
1908 * @implemented
1909 */
1910 #undef NdisMSendResourcesAvailable
1911 VOID
1912 EXPORT
1913 NdisMSendResourcesAvailable(
1914 IN NDIS_HANDLE MiniportAdapterHandle)
1915 {
1916 MiniSendResourcesAvailable(MiniportAdapterHandle);
1917 }
1918
1919 \f
1920 /*
1921 * @implemented
1922 */
1923 #undef NdisMTransferDataComplete
1924 VOID
1925 EXPORT
1926 NdisMTransferDataComplete(
1927 IN NDIS_HANDLE MiniportAdapterHandle,
1928 IN PNDIS_PACKET Packet,
1929 IN NDIS_STATUS Status,
1930 IN UINT BytesTransferred)
1931 {
1932 MiniTransferDataComplete(MiniportAdapterHandle, Packet, Status, BytesTransferred);
1933 }
1934
1935 #undef NdisMSetInformationComplete
1936
1937 \f
1938 /*
1939 * @implemented
1940 */
1941 VOID
1942 EXPORT
1943 NdisMSetInformationComplete(
1944 IN NDIS_HANDLE MiniportAdapterHandle,
1945 IN NDIS_STATUS Status)
1946 {
1947 (*((PNDIS_MINIPORT_BLOCK)(MiniportAdapterHandle))->SetCompleteHandler)(MiniportAdapterHandle, Status);
1948 }
1949
1950 #undef NdisMSetAttributes
1951
1952 \f
1953 /*
1954 * @implemented
1955 */
1956 VOID
1957 EXPORT
1958 NdisMSetAttributes(
1959 IN NDIS_HANDLE MiniportAdapterHandle,
1960 IN NDIS_HANDLE MiniportAdapterContext,
1961 IN BOOLEAN BusMaster,
1962 IN NDIS_INTERFACE_TYPE AdapterType)
1963 /*
1964 * FUNCTION: Informs the NDIS library of significant features of the caller's NIC
1965 * ARGUMENTS:
1966 * MiniportAdapterHandle = Handle input to MiniportInitialize
1967 * MiniportAdapterContext = Pointer to context information
1968 * BusMaster = Specifies TRUE if the caller's NIC is a busmaster DMA device
1969 * AdapterType = Specifies the I/O bus interface of the caller's NIC
1970 */
1971 {
1972 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
1973 NdisMSetAttributesEx(MiniportAdapterHandle, MiniportAdapterContext, 0,
1974 BusMaster ? NDIS_ATTRIBUTE_BUS_MASTER : 0,
1975 AdapterType);
1976 }
1977
1978 \f
1979 /*
1980 * @implemented
1981 */
1982 VOID
1983 EXPORT
1984 NdisMSetAttributesEx(
1985 IN NDIS_HANDLE MiniportAdapterHandle,
1986 IN NDIS_HANDLE MiniportAdapterContext,
1987 IN UINT CheckForHangTimeInSeconds OPTIONAL,
1988 IN ULONG AttributeFlags,
1989 IN NDIS_INTERFACE_TYPE AdapterType)
1990 /*
1991 * FUNCTION: Informs the NDIS library of significant features of the caller's NIC
1992 * ARGUMENTS:
1993 * MiniportAdapterHandle = Handle input to MiniportInitialize
1994 * MiniportAdapterContext = Pointer to context information
1995 * CheckForHangTimeInSeconds = Specifies interval in seconds at which
1996 * MiniportCheckForHang should be called
1997 * AttributeFlags = Bitmask that indicates specific attributes
1998 * AdapterType = Specifies the I/O bus interface of the caller's NIC
1999 */
2000 {
2001 /* TODO: Take CheckForHandTimeInSeconds into account! */
2002
2003 PLOGICAL_ADAPTER Adapter = GET_LOGICAL_ADAPTER(MiniportAdapterHandle);
2004
2005 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
2006
2007 Adapter->NdisMiniportBlock.MiniportAdapterContext = MiniportAdapterContext;
2008 Adapter->NdisMiniportBlock.Flags = AttributeFlags;
2009 Adapter->NdisMiniportBlock.AdapterType = AdapterType;
2010 Adapter->AttributesSet = TRUE;
2011 if (AttributeFlags & NDIS_ATTRIBUTE_INTERMEDIATE_DRIVER)
2012 NDIS_DbgPrint(MAX_TRACE, ("Intermediate drivers not supported yet.\n"));
2013 }
2014
2015 \f
2016 /*
2017 * @implemented
2018 */
2019 VOID
2020 EXPORT
2021 NdisMSleep(
2022 IN ULONG MicrosecondsToSleep)
2023 /*
2024 * FUNCTION: delay the thread's execution for MicrosecondsToSleep
2025 * ARGUMENTS:
2026 * MicrosecondsToSleep: duh...
2027 * NOTES:
2028 * - Because this is a blocking call, current IRQL must be < DISPATCH_LEVEL
2029 */
2030 {
2031 KTIMER Timer;
2032 LARGE_INTEGER DueTime;
2033
2034 PAGED_CODE();
2035
2036 DueTime.QuadPart = (-1) * 10 * MicrosecondsToSleep;
2037
2038 KeInitializeTimer(&Timer);
2039 KeSetTimer(&Timer, DueTime, 0);
2040 KeWaitForSingleObject(&Timer, Executive, KernelMode, FALSE, 0);
2041 }
2042
2043 \f
2044 /*
2045 * @implemented
2046 */
2047 BOOLEAN
2048 EXPORT
2049 NdisMSynchronizeWithInterrupt(
2050 IN PNDIS_MINIPORT_INTERRUPT Interrupt,
2051 IN PVOID SynchronizeFunction,
2052 IN PVOID SynchronizeContext)
2053 {
2054 return(KeSynchronizeExecution(Interrupt->InterruptObject,
2055 (PKSYNCHRONIZE_ROUTINE)SynchronizeFunction,
2056 SynchronizeContext));
2057 }
2058
2059 \f
2060 /*
2061 * @unimplemented
2062 */
2063 NDIS_STATUS
2064 EXPORT
2065 NdisMWriteLogData(
2066 IN NDIS_HANDLE LogHandle,
2067 IN PVOID LogBuffer,
2068 IN UINT LogBufferSize)
2069 {
2070 UNIMPLEMENTED
2071
2072 return NDIS_STATUS_FAILURE;
2073 }
2074
2075 \f
2076 /*
2077 * @implemented
2078 */
2079 VOID
2080 EXPORT
2081 NdisTerminateWrapper(
2082 IN NDIS_HANDLE NdisWrapperHandle,
2083 IN PVOID SystemSpecific)
2084 /*
2085 * FUNCTION: Releases resources allocated by a call to NdisInitializeWrapper
2086 * ARGUMENTS:
2087 * NdisWrapperHandle = Handle returned by NdisInitializeWrapper (MINIPORT_DRIVER)
2088 * SystemSpecific = Always NULL
2089 */
2090 {
2091 PMINIPORT_DRIVER Miniport = GET_MINIPORT_DRIVER(NdisWrapperHandle);
2092
2093 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
2094
2095 ExFreePool(Miniport->RegistryPath->Buffer);
2096 ExFreePool(Miniport->RegistryPath);
2097 ExFreePool(Miniport);
2098 }
2099
2100 /* EOF */
2101