Detect Bad graphic Bios, Some graphice card report VBE 2.0 when the are VBE 1.2....
[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 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 PNDIS_MINIPORT_BLOCK Adapter,
334 IN PNDIS_REQUEST Request,
335 IN NDIS_STATUS Status)
336 {
337 PNDIS_REQUEST_MAC_BLOCK MacBlock = (PNDIS_REQUEST_MAC_BLOCK)Request->MacReserved;
338
339 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
340
341 if( MacBlock->Binding->RequestCompleteHandler ) {
342 (*MacBlock->Binding->RequestCompleteHandler)(
343 MacBlock->Binding->ProtocolBindingContext,
344 Request,
345 Status);
346 }
347 }
348
349 VOID NTAPI
350 MiniSendComplete(
351 IN NDIS_HANDLE MiniportAdapterHandle,
352 IN PNDIS_PACKET Packet,
353 IN NDIS_STATUS Status)
354 /*
355 * FUNCTION: Forwards a message to the initiating protocol saying
356 * that a packet was handled
357 * ARGUMENTS:
358 * NdisAdapterHandle = Handle input to MiniportInitialize
359 * Packet = Pointer to NDIS packet that was sent
360 * Status = Status of send operation
361 */
362 {
363 PADAPTER_BINDING AdapterBinding;
364
365 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
366
367 AdapterBinding = (PADAPTER_BINDING)Packet->Reserved[0];
368
369 (*AdapterBinding->ProtocolBinding->Chars.SendCompleteHandler)(
370 AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
371 Packet,
372 Status);
373 }
374
375
376 VOID NTAPI
377 MiniSendResourcesAvailable(
378 IN NDIS_HANDLE MiniportAdapterHandle)
379 {
380 UNIMPLEMENTED
381 }
382
383
384 VOID NTAPI
385 MiniTransferDataComplete(
386 IN NDIS_HANDLE MiniportAdapterHandle,
387 IN PNDIS_PACKET Packet,
388 IN NDIS_STATUS Status,
389 IN UINT BytesTransferred)
390 {
391 PADAPTER_BINDING AdapterBinding;
392
393 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
394
395 AdapterBinding = (PADAPTER_BINDING)Packet->Reserved[0];
396
397 (*AdapterBinding->ProtocolBinding->Chars.SendCompleteHandler)(
398 AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
399 Packet,
400 Status);
401 }
402
403 \f
404 BOOLEAN
405 MiniAdapterHasAddress(
406 PLOGICAL_ADAPTER Adapter,
407 PNDIS_PACKET Packet)
408 /*
409 * FUNCTION: Determines whether a packet has the same destination address as an adapter
410 * ARGUMENTS:
411 * Adapter = Pointer to logical adapter object
412 * Packet = Pointer to NDIS packet
413 * RETURNS:
414 * TRUE if the destination address is that of the adapter, FALSE if not
415 */
416 {
417 UINT Length;
418 PUCHAR Start1;
419 PUCHAR Start2;
420 PNDIS_BUFFER NdisBuffer;
421 UINT BufferLength;
422
423 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
424
425 #ifdef DBG
426 if(!Adapter)
427 {
428 NDIS_DbgPrint(MID_TRACE, ("Adapter object was null\n"));
429 return FALSE;
430 }
431
432 if(!Packet)
433 {
434 NDIS_DbgPrint(MID_TRACE, ("Packet was null\n"));
435 return FALSE;
436 }
437 #endif
438
439 NdisQueryPacket(Packet, NULL, NULL, &NdisBuffer, NULL);
440
441 if (!NdisBuffer)
442 {
443 NDIS_DbgPrint(MID_TRACE, ("Packet contains no buffers.\n"));
444 return FALSE;
445 }
446
447 NdisQueryBuffer(NdisBuffer, (PVOID)&Start2, &BufferLength);
448
449 /* FIXME: Should handle fragmented packets */
450
451 switch (Adapter->NdisMiniportBlock.MediaType)
452 {
453 case NdisMedium802_3:
454 Length = ETH_LENGTH_OF_ADDRESS;
455 /* Destination address is the first field */
456 break;
457
458 default:
459 NDIS_DbgPrint(MIN_TRACE, ("Adapter has unsupported media type (0x%X).\n", Adapter->NdisMiniportBlock.MediaType));
460 return FALSE;
461 }
462
463 if (BufferLength < Length)
464 {
465 NDIS_DbgPrint(MID_TRACE, ("Buffer is too small.\n"));
466 return FALSE;
467 }
468
469 Start1 = (PUCHAR)&Adapter->Address;
470 NDIS_DbgPrint(MAX_TRACE, ("packet address: %x:%x:%x:%x:%x:%x adapter address: %x:%x:%x:%x:%x:%x\n",
471 *((char *)Start1), *(((char *)Start1)+1), *(((char *)Start1)+2), *(((char *)Start1)+3), *(((char *)Start1)+4), *(((char *)Start1)+5),
472 *((char *)Start2), *(((char *)Start2)+1), *(((char *)Start2)+2), *(((char *)Start2)+3), *(((char *)Start2)+4), *(((char *)Start2)+5))
473 );
474
475 return (RtlCompareMemory((PVOID)Start1, (PVOID)Start2, Length) == Length);
476 }
477
478 \f
479 PLOGICAL_ADAPTER
480 MiniLocateDevice(
481 PNDIS_STRING AdapterName)
482 /*
483 * FUNCTION: Finds an adapter object by name
484 * ARGUMENTS:
485 * AdapterName = Pointer to name of adapter
486 * RETURNS:
487 * Pointer to logical adapter object, or NULL if none was found.
488 * If found, the adapter is referenced for the caller. The caller
489 * is responsible for dereferencing after use
490 */
491 {
492 KIRQL OldIrql;
493 PLIST_ENTRY CurrentEntry;
494 PLOGICAL_ADAPTER Adapter = 0;
495
496 ASSERT(AdapterName);
497
498 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
499
500 if(IsListEmpty(&AdapterListHead))
501 {
502 NDIS_DbgPrint(DEBUG_MINIPORT, ("No registered miniports for protocol to bind to\n"));
503 return NULL;
504 }
505
506 KeAcquireSpinLock(&AdapterListLock, &OldIrql);
507 {
508 do
509 {
510 CurrentEntry = AdapterListHead.Flink;
511
512 while (CurrentEntry != &AdapterListHead)
513 {
514 Adapter = CONTAINING_RECORD(CurrentEntry, LOGICAL_ADAPTER, ListEntry);
515
516 ASSERT(Adapter);
517
518 NDIS_DbgPrint(DEBUG_MINIPORT, ("AdapterName = %wZ\n", AdapterName));
519 NDIS_DbgPrint(DEBUG_MINIPORT, ("DeviceName = %wZ\n", &Adapter->NdisMiniportBlock.MiniportName));
520
521 if (RtlCompareUnicodeString(AdapterName, &Adapter->NdisMiniportBlock.MiniportName, TRUE) == 0)
522 {
523 break;
524 }
525
526 Adapter = NULL;
527 CurrentEntry = CurrentEntry->Flink;
528 }
529 } while (0);
530 }
531 KeReleaseSpinLock(&AdapterListLock, OldIrql);
532
533 if(Adapter)
534 {
535 NDIS_DbgPrint(DEBUG_MINIPORT, ("Leaving. Adapter found at 0x%x\n", Adapter));
536 }
537 else
538 {
539 NDIS_DbgPrint(DEBUG_MINIPORT, ("Leaving (adapter not found).\n"));
540 }
541
542 return Adapter;
543 }
544
545 \f
546 NDIS_STATUS
547 MiniQueryInformation(
548 PLOGICAL_ADAPTER Adapter,
549 NDIS_OID Oid,
550 ULONG Size,
551 PVOID Buffer,
552 PULONG BytesWritten)
553 /*
554 * FUNCTION: Queries a logical adapter for properties
555 * ARGUMENTS:
556 * Adapter = Pointer to the logical adapter object to query
557 * Oid = Specifies the Object ID to query for
558 * Size = Size of the passed buffer
559 * Buffer = Buffer for the output
560 * BytesWritten = Address of buffer to place number of bytes written
561 * NOTES:
562 * If the specified buffer is too small, a new buffer is allocated,
563 * and the query is attempted again
564 * RETURNS:
565 * Status of operation
566 * TODO:
567 * Is there any way to use the buffer provided by the protocol?
568 */
569 {
570 NDIS_STATUS NdisStatus;
571 ULONG BytesNeeded;
572
573 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
574
575 /* call the miniport's queryinfo handler */
576 NdisStatus = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.QueryInformationHandler)(
577 Adapter->NdisMiniportBlock.MiniportAdapterContext,
578 Oid,
579 Buffer,
580 Size,
581 BytesWritten,
582 &BytesNeeded);
583
584 /* FIXME: Wait in pending case! */
585
586 /* XXX is status_pending part of success macro? */
587 if ((NT_SUCCESS(NdisStatus)) || (NdisStatus == NDIS_STATUS_PENDING))
588 {
589 NDIS_DbgPrint(DEBUG_MINIPORT, ("Miniport returned status (0x%X).\n", NdisStatus));
590 return NdisStatus;
591 }
592
593 return NdisStatus;
594 }
595
596 \f
597 NDIS_STATUS
598 FASTCALL
599 MiniQueueWorkItem(
600 PLOGICAL_ADAPTER Adapter,
601 NDIS_WORK_ITEM_TYPE WorkItemType,
602 PVOID WorkItemContext)
603 /*
604 * FUNCTION: Queues a work item for execution at a later time
605 * ARGUMENTS:
606 * Adapter = Pointer to the logical adapter object to queue work item on
607 * WorkItemType = Type of work item to queue
608 * WorkItemContext = Pointer to context information for work item
609 * NOTES:
610 * Adapter lock must be held when called
611 * RETURNS:
612 * Status of operation
613 */
614 {
615 PNDIS_MINIPORT_WORK_ITEM Item;
616
617 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
618
619 ASSERT(Adapter);
620 ASSERT(KeGetCurrentIrql() >= DISPATCH_LEVEL);
621
622 Item = ExAllocatePool(NonPagedPool, sizeof(NDIS_MINIPORT_WORK_ITEM));
623 if (Item == NULL)
624 {
625 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
626 return NDIS_STATUS_RESOURCES;
627 }
628
629 Item->WorkItemType = WorkItemType;
630 Item->WorkItemContext = WorkItemContext;
631
632 /* safe due to adapter lock held */
633 Item->Link.Next = NULL;
634 if (!Adapter->WorkQueueHead)
635 {
636 Adapter->WorkQueueHead = Item;
637 Adapter->WorkQueueTail = Item;
638 }
639 else
640 {
641 Adapter->WorkQueueTail->Link.Next = (PSINGLE_LIST_ENTRY)Item;
642 Adapter->WorkQueueTail = Item;
643 }
644
645 KeInsertQueueDpc(&Adapter->NdisMiniportBlock.DeferredDpc, NULL, NULL);
646
647 return NDIS_STATUS_SUCCESS;
648 }
649
650 \f
651 NDIS_STATUS
652 FASTCALL
653 MiniDequeueWorkItem(
654 PLOGICAL_ADAPTER Adapter,
655 NDIS_WORK_ITEM_TYPE *WorkItemType,
656 PVOID *WorkItemContext)
657 /*
658 * FUNCTION: Dequeues a work item from the work queue of a logical adapter
659 * ARGUMENTS:
660 * Adapter = Pointer to the logical adapter object to dequeue work item from
661 * AdapterBinding = Address of buffer for adapter binding for this request
662 * WorkItemType = Address of buffer for work item type
663 * WorkItemContext = Address of buffer for pointer to context information
664 * NOTES:
665 * Adapter lock must be held when called
666 * RETURNS:
667 * Status of operation
668 */
669 {
670 PNDIS_MINIPORT_WORK_ITEM Item;
671
672 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
673
674 Item = Adapter->WorkQueueHead;
675
676 if (Item)
677 {
678 /* safe due to adapter lock held */
679 Adapter->WorkQueueHead = (PNDIS_MINIPORT_WORK_ITEM)Item->Link.Next;
680
681 if (Item == Adapter->WorkQueueTail)
682 Adapter->WorkQueueTail = NULL;
683
684 *WorkItemType = Item->WorkItemType;
685 *WorkItemContext = Item->WorkItemContext;
686
687 ExFreePool(Item);
688
689 return NDIS_STATUS_SUCCESS;
690 }
691
692 return NDIS_STATUS_FAILURE;
693 }
694
695 \f
696 NDIS_STATUS
697 MiniDoRequest(
698 PNDIS_MINIPORT_BLOCK Adapter,
699 PNDIS_REQUEST NdisRequest)
700 /*
701 * FUNCTION: Sends a request to a miniport
702 * ARGUMENTS:
703 * AdapterBinding = Pointer to binding used in the request
704 * NdisRequest = Pointer to NDIS request structure describing request
705 * RETURNS:
706 * Status of operation
707 */
708 {
709 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
710
711 Adapter->MediaRequest = NdisRequest;
712
713 switch (NdisRequest->RequestType)
714 {
715 case NdisRequestQueryInformation:
716 return (*Adapter->DriverHandle->MiniportCharacteristics.QueryInformationHandler)(
717 Adapter->MiniportAdapterContext,
718 NdisRequest->DATA.QUERY_INFORMATION.Oid,
719 NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer,
720 NdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength,
721 (PULONG)&NdisRequest->DATA.QUERY_INFORMATION.BytesWritten,
722 (PULONG)&NdisRequest->DATA.QUERY_INFORMATION.BytesNeeded);
723 break;
724
725 case NdisRequestSetInformation:
726 return (*Adapter->DriverHandle->MiniportCharacteristics.SetInformationHandler)(
727 Adapter->MiniportAdapterContext,
728 NdisRequest->DATA.SET_INFORMATION.Oid,
729 NdisRequest->DATA.SET_INFORMATION.InformationBuffer,
730 NdisRequest->DATA.SET_INFORMATION.InformationBufferLength,
731 (PULONG)&NdisRequest->DATA.SET_INFORMATION.BytesRead,
732 (PULONG)&NdisRequest->DATA.SET_INFORMATION.BytesNeeded);
733 break;
734
735 default:
736 return NDIS_STATUS_FAILURE;
737 }
738 }
739
740 \f
741 /*
742 * @implemented
743 */
744 #undef NdisMQueryInformationComplete
745 VOID
746 EXPORT
747 NdisMQueryInformationComplete(
748 IN NDIS_HANDLE MiniportAdapterHandle,
749 IN NDIS_STATUS Status)
750 {
751 PNDIS_MINIPORT_BLOCK MiniportBlock =
752 (PNDIS_MINIPORT_BLOCK)MiniportAdapterHandle;
753 ASSERT(MiniportBlock);
754 if( MiniportBlock->QueryCompleteHandler )
755 (MiniportBlock->QueryCompleteHandler)(MiniportAdapterHandle, Status);
756 }
757
758 \f
759 VOID NTAPI MiniportDpc(
760 IN PKDPC Dpc,
761 IN PVOID DeferredContext,
762 IN PVOID SystemArgument1,
763 IN PVOID SystemArgument2)
764 /*
765 * FUNCTION: Deferred routine to handle serialization
766 * ARGUMENTS:
767 * Dpc = Pointer to DPC object
768 * DeferredContext = Pointer to context information (LOGICAL_ADAPTER)
769 * SystemArgument1 = Unused
770 * SystemArgument2 = Unused
771 */
772 {
773 NDIS_STATUS NdisStatus;
774 PVOID WorkItemContext;
775 NDIS_WORK_ITEM_TYPE WorkItemType;
776 PLOGICAL_ADAPTER Adapter = GET_LOGICAL_ADAPTER(DeferredContext);
777
778 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
779
780 NdisStatus =
781 MiniDequeueWorkItem
782 (Adapter, &WorkItemType, &WorkItemContext);
783
784 if (NdisStatus == NDIS_STATUS_SUCCESS)
785 {
786 switch (WorkItemType)
787 {
788 case NdisWorkItemSend:
789 /*
790 * called by ProSend when protocols want to send packets to the miniport
791 */
792 #ifdef DBG
793 MiniDisplayPacket((PNDIS_PACKET)WorkItemContext);
794 #endif
795 if(Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendPacketsHandler)
796 {
797 NDIS_DbgPrint(MAX_TRACE, ("Calling miniport's SendPackets handler\n"));
798
799 /*
800 * XXX assumes single-packet - prolly OK since we'll call something
801 * different on multi-packet sends
802 */
803 (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendPacketsHandler)(
804 Adapter->NdisMiniportBlock.MiniportAdapterContext, (PPNDIS_PACKET)&WorkItemContext, 1);
805 NdisStatus =
806 NDIS_GET_PACKET_STATUS((PNDIS_PACKET)WorkItemContext);
807
808 NDIS_DbgPrint(MAX_TRACE, ("back from miniport's SendPackets handler\n"));
809 }
810 else
811 {
812 NDIS_DbgPrint(MAX_TRACE, ("Calling miniport's Send handler\n"));
813
814 NdisStatus = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendHandler)(
815 Adapter->NdisMiniportBlock.MiniportAdapterContext, (PNDIS_PACKET)WorkItemContext, 0);
816
817 NDIS_DbgPrint(MAX_TRACE, ("back from miniport's Send handler\n"));
818 }
819 if( NdisStatus != NDIS_STATUS_PENDING ) {
820 NdisMSendComplete
821 ( Adapter, (PNDIS_PACKET)WorkItemContext, NdisStatus );
822 Adapter->MiniportBusy = FALSE;
823 }
824 break;
825
826 case NdisWorkItemSendLoopback:
827 /*
828 * called by ProSend when protocols want to send loopback packets
829 */
830 /* XXX atm ProIndicatePacket sends a packet up via the loopback adapter only */
831 NdisStatus = ProIndicatePacket(Adapter, (PNDIS_PACKET)WorkItemContext);
832 MiniSendComplete((NDIS_HANDLE)Adapter, (PNDIS_PACKET)WorkItemContext, NdisStatus);
833 break;
834
835 case NdisWorkItemReturnPackets:
836 break;
837
838 case NdisWorkItemResetRequested:
839 break;
840
841 case NdisWorkItemResetInProgress:
842 break;
843
844 case NdisWorkItemMiniportCallback:
845 break;
846
847 case NdisWorkItemRequest:
848 NdisStatus = MiniDoRequest(&Adapter->NdisMiniportBlock, (PNDIS_REQUEST)WorkItemContext);
849
850 if (NdisStatus == NDIS_STATUS_PENDING)
851 break;
852
853 switch (((PNDIS_REQUEST)WorkItemContext)->RequestType)
854 {
855 case NdisRequestQueryInformation:
856 NdisMQueryInformationComplete((NDIS_HANDLE)Adapter, NdisStatus);
857 MiniRequestComplete( &Adapter->NdisMiniportBlock, (PNDIS_REQUEST)WorkItemContext, NdisStatus );
858 break;
859
860 case NdisRequestSetInformation:
861 NdisMSetInformationComplete((NDIS_HANDLE)Adapter, NdisStatus);
862 MiniRequestComplete( &Adapter->NdisMiniportBlock, (PNDIS_REQUEST)WorkItemContext, NdisStatus );
863 break;
864
865 default:
866 NDIS_DbgPrint(MIN_TRACE, ("Unknown NDIS request type.\n"));
867 break;
868 }
869 break;
870
871 default:
872 NDIS_DbgPrint(MIN_TRACE, ("Unknown NDIS work item type (%d).\n", WorkItemType));
873 break;
874 }
875 }
876 }
877
878 \f
879 /*
880 * @unimplemented
881 */
882 VOID
883 EXPORT
884 NdisMCloseLog(
885 IN NDIS_HANDLE LogHandle)
886 {
887 UNIMPLEMENTED
888 }
889
890 \f
891 /*
892 * @unimplemented
893 */
894 NDIS_STATUS
895 EXPORT
896 NdisMCreateLog(
897 IN NDIS_HANDLE MiniportAdapterHandle,
898 IN UINT Size,
899 OUT PNDIS_HANDLE LogHandle)
900 {
901 UNIMPLEMENTED
902
903 return NDIS_STATUS_FAILURE;
904 }
905
906 \f
907 /*
908 * @implemented
909 */
910 VOID
911 EXPORT
912 NdisMDeregisterAdapterShutdownHandler(
913 IN NDIS_HANDLE MiniportHandle)
914 /*
915 * FUNCTION: de-registers a shutdown handler
916 * ARGUMENTS: MiniportHandle: Handle passed into MiniportInitialize
917 */
918 {
919 PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)MiniportHandle;
920
921 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
922
923 if(Adapter->BugcheckContext->ShutdownHandler)
924 KeDeregisterBugCheckCallback(Adapter->BugcheckContext->CallbackRecord);
925 }
926
927 \f
928 /*
929 * @unimplemented
930 */
931 VOID
932 EXPORT
933 NdisMFlushLog(
934 IN NDIS_HANDLE LogHandle)
935 {
936 UNIMPLEMENTED
937 }
938
939 /*
940 * @unimplemented
941 */
942 #undef NdisMIndicateStatus
943 VOID
944 EXPORT
945 NdisMIndicateStatus(
946 IN NDIS_HANDLE MiniportAdapterHandle,
947 IN NDIS_STATUS GeneralStatus,
948 IN PVOID StatusBuffer,
949 IN UINT StatusBufferSize)
950 {
951 UNIMPLEMENTED
952 }
953
954 /*
955 * @unimplemented
956 */
957 #undef NdisMIndicateStatusComplete
958 VOID
959 EXPORT
960 NdisMIndicateStatusComplete(
961 IN NDIS_HANDLE MiniportAdapterHandle)
962 {
963 UNIMPLEMENTED
964 }
965
966 \f
967 /*
968 * @implemented
969 */
970 VOID
971 EXPORT
972 NdisInitializeWrapper(
973 OUT PNDIS_HANDLE NdisWrapperHandle,
974 IN PVOID SystemSpecific1,
975 IN PVOID SystemSpecific2,
976 IN PVOID SystemSpecific3)
977 /*
978 * FUNCTION: Notifies the NDIS library that a new miniport is initializing
979 * ARGUMENTS:
980 * NdisWrapperHandle = Address of buffer to place NDIS wrapper handle
981 * SystemSpecific1 = Pointer to the driver's driver object
982 * SystemSpecific2 = Pointer to the driver's registry path
983 * SystemSpecific3 = Always NULL
984 * NOTES:
985 * - SystemSpecific2 goes invalid so we copy it
986 */
987 {
988 PNDIS_M_DRIVER_BLOCK Miniport;
989 PUNICODE_STRING RegistryPath;
990 WCHAR *RegistryBuffer;
991
992 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
993
994 ASSERT(NdisWrapperHandle);
995
996 *NdisWrapperHandle = NULL;
997
998 #if BREAK_ON_MINIPORT_INIT
999 __asm__ ("int $3\n");
1000 #endif
1001
1002 Miniport = ExAllocatePool(NonPagedPool, sizeof(NDIS_M_DRIVER_BLOCK));
1003
1004 if (!Miniport)
1005 {
1006 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
1007 return;
1008 }
1009
1010 RtlZeroMemory(Miniport, sizeof(NDIS_M_DRIVER_BLOCK));
1011
1012 KeInitializeSpinLock(&Miniport->Lock);
1013
1014 Miniport->DriverObject = (PDRIVER_OBJECT)SystemSpecific1;
1015
1016 /* set the miniport's driver registry path */
1017 RegistryPath = ExAllocatePool(PagedPool, sizeof(UNICODE_STRING));
1018 if(!RegistryPath)
1019 {
1020 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
1021 return;
1022 }
1023
1024 RegistryPath->Length = ((PUNICODE_STRING)SystemSpecific2)->Length;
1025 RegistryPath->MaximumLength = RegistryPath->Length + sizeof(WCHAR); /* room for 0-term */
1026
1027 RegistryBuffer = ExAllocatePool(PagedPool, RegistryPath->MaximumLength);
1028 if(!RegistryBuffer)
1029 {
1030 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
1031 return;
1032 }
1033
1034 RtlCopyMemory(RegistryBuffer, ((PUNICODE_STRING)SystemSpecific2)->Buffer, RegistryPath->Length);
1035 RegistryBuffer[RegistryPath->Length/sizeof(WCHAR)] = 0;
1036
1037 RegistryPath->Buffer = RegistryBuffer;
1038 Miniport->RegistryPath = RegistryPath;
1039
1040 InitializeListHead(&Miniport->DeviceList);
1041
1042 /* Put miniport in global miniport list */
1043 ExInterlockedInsertTailList(&MiniportListHead, &Miniport->ListEntry, &MiniportListLock);
1044
1045 *NdisWrapperHandle = Miniport;
1046 }
1047
1048 \f
1049 VOID NTAPI NdisIBugcheckCallback(
1050 IN PVOID Buffer,
1051 IN ULONG Length)
1052 /*
1053 * FUNCTION: Internal callback for handling bugchecks - calls adapter's shutdown handler
1054 * ARGUMENTS:
1055 * Buffer: Pointer to a bugcheck callback context
1056 * Length: Unused
1057 */
1058 {
1059 PMINIPORT_BUGCHECK_CONTEXT Context = (PMINIPORT_BUGCHECK_CONTEXT)Buffer;
1060 ADAPTER_SHUTDOWN_HANDLER sh = (ADAPTER_SHUTDOWN_HANDLER)Context->ShutdownHandler;
1061
1062 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
1063
1064 if(sh)
1065 sh(Context->DriverContext);
1066 }
1067
1068 \f
1069 /*
1070 * @implemented
1071 */
1072 VOID
1073 EXPORT
1074 NdisMRegisterAdapterShutdownHandler(
1075 IN NDIS_HANDLE MiniportHandle,
1076 IN PVOID ShutdownContext,
1077 IN ADAPTER_SHUTDOWN_HANDLER ShutdownHandler)
1078 /*
1079 * FUNCTION: Register a shutdown handler for an adapter
1080 * ARGUMENTS:
1081 * MiniportHandle: Handle originally passed into MiniportInitialize
1082 * ShutdownContext: Pre-initialized bugcheck context
1083 * ShutdownHandler: Function to call to handle the bugcheck
1084 * NOTES:
1085 * - I'm not sure about ShutdownContext
1086 * - FIXME - memory leak below
1087 */
1088 {
1089 PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)MiniportHandle;
1090 PMINIPORT_BUGCHECK_CONTEXT BugcheckContext = Adapter->BugcheckContext;
1091
1092 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
1093
1094 if(BugcheckContext)
1095 return;
1096
1097 BugcheckContext = ExAllocatePool(NonPagedPool, sizeof(MINIPORT_BUGCHECK_CONTEXT));
1098 if(!BugcheckContext)
1099 {
1100 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
1101 return;
1102 }
1103
1104 BugcheckContext->ShutdownHandler = ShutdownHandler;
1105 BugcheckContext->DriverContext = ShutdownContext;
1106
1107 /* not sure if this needs to be initialized or not... oh well, it's a leak. */
1108 BugcheckContext->CallbackRecord = ExAllocatePool(NonPagedPool, sizeof(KBUGCHECK_CALLBACK_RECORD));
1109
1110 KeRegisterBugCheckCallback(BugcheckContext->CallbackRecord, NdisIBugcheckCallback,
1111 BugcheckContext, sizeof(BugcheckContext), (PUCHAR)"Ndis Miniport");
1112 }
1113
1114 \f
1115 NDIS_STATUS
1116 DoQueries(
1117 PLOGICAL_ADAPTER Adapter,
1118 NDIS_OID AddressOID)
1119 /*
1120 * FUNCTION: Queries miniport for information
1121 * ARGUMENTS:
1122 * Adapter = Pointer to logical adapter
1123 * AddressOID = OID to use to query for current address
1124 * RETURNS:
1125 * Status of operation
1126 */
1127 {
1128 ULONG BytesWritten;
1129 NDIS_STATUS NdisStatus;
1130
1131 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
1132
1133 /* Get MAC options for adapter */
1134 NdisStatus = MiniQueryInformation(Adapter, OID_GEN_MAC_OPTIONS, sizeof(UINT),
1135 &Adapter->NdisMiniportBlock.MacOptions,
1136 &BytesWritten);
1137
1138 if (NdisStatus != NDIS_STATUS_SUCCESS)
1139 {
1140 NDIS_DbgPrint(MIN_TRACE, ("OID_GEN_MAC_OPTIONS failed. NdisStatus (0x%X).\n", NdisStatus));
1141 return NdisStatus;
1142 }
1143
1144 NDIS_DbgPrint(DEBUG_MINIPORT, ("MacOptions (0x%X).\n", Adapter->NdisMiniportBlock.MacOptions));
1145
1146 /* Get current hardware address of adapter */
1147 NdisStatus = MiniQueryInformation(Adapter, AddressOID, Adapter->AddressLength,
1148 &Adapter->Address, &BytesWritten);
1149
1150 if (NdisStatus != NDIS_STATUS_SUCCESS)
1151 {
1152 NDIS_DbgPrint(MIN_TRACE, ("Address OID (0x%X) failed. NdisStatus (0x%X).\n", AddressOID, NdisStatus));
1153 return NdisStatus;
1154 }
1155
1156 #ifdef DBG
1157 {
1158 /* 802.3 only */
1159
1160 PUCHAR A = (PUCHAR)&Adapter->Address.Type.Medium802_3;
1161
1162 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]));
1163 }
1164 #endif /* DBG */
1165
1166 /* Get maximum lookahead buffer size of adapter */
1167 NdisStatus = MiniQueryInformation(Adapter, OID_GEN_MAXIMUM_LOOKAHEAD, sizeof(ULONG),
1168 &Adapter->NdisMiniportBlock.MaximumLookahead, &BytesWritten);
1169
1170 if (NdisStatus != NDIS_STATUS_SUCCESS)
1171 {
1172 NDIS_DbgPrint(MIN_TRACE, ("OID_GEN_MAXIMUM_LOOKAHEAD failed. NdisStatus (0x%X).\n", NdisStatus));
1173 return NdisStatus;
1174 }
1175
1176 NDIS_DbgPrint(DEBUG_MINIPORT, ("MaxLookaheadLength (0x%X).\n", Adapter->NdisMiniportBlock.MaximumLookahead));
1177
1178 /* Get current lookahead buffer size of adapter */
1179 NdisStatus = MiniQueryInformation(Adapter, OID_GEN_CURRENT_LOOKAHEAD, sizeof(ULONG),
1180 &Adapter->NdisMiniportBlock.CurrentLookahead, &BytesWritten);
1181
1182 if (NdisStatus != NDIS_STATUS_SUCCESS)
1183 {
1184 NDIS_DbgPrint(MIN_TRACE, ("OID_GEN_CURRENT_LOOKAHEAD failed. NdisStatus (0x%X).\n", NdisStatus));
1185 return NdisStatus;
1186 }
1187
1188 NDIS_DbgPrint(DEBUG_MINIPORT, ("CurLookaheadLength (0x%X).\n", Adapter->NdisMiniportBlock.CurrentLookahead));
1189
1190 if (Adapter->NdisMiniportBlock.MaximumLookahead != 0)
1191 {
1192 Adapter->LookaheadLength = Adapter->NdisMiniportBlock.MaximumLookahead + Adapter->MediumHeaderSize;
1193 Adapter->LookaheadBuffer = ExAllocatePool(NonPagedPool, Adapter->LookaheadLength);
1194
1195 if (!Adapter->LookaheadBuffer)
1196 return NDIS_STATUS_RESOURCES;
1197 }
1198
1199 return STATUS_SUCCESS;
1200 }
1201
1202 \f
1203 NTSTATUS
1204 NTAPI
1205 NdisIForwardIrpAndWaitCompletionRoutine(
1206 PDEVICE_OBJECT Fdo,
1207 PIRP Irp,
1208 PVOID Context)
1209 {
1210 PKEVENT Event = Context;
1211
1212 if (Irp->PendingReturned)
1213 KeSetEvent(Event, IO_NO_INCREMENT, FALSE);
1214
1215 return STATUS_MORE_PROCESSING_REQUIRED;
1216 }
1217
1218 \f
1219 NTSTATUS
1220 NTAPI
1221 NdisIForwardIrpAndWait(PLOGICAL_ADAPTER Adapter, PIRP Irp)
1222 {
1223 KEVENT Event;
1224 NTSTATUS Status;
1225
1226 KeInitializeEvent(&Event, NotificationEvent, FALSE);
1227 IoCopyCurrentIrpStackLocationToNext(Irp);
1228 IoSetCompletionRoutine(Irp, NdisIForwardIrpAndWaitCompletionRoutine, &Event,
1229 TRUE, TRUE, TRUE);
1230 Status = IoCallDriver(Adapter->NdisMiniportBlock.NextDeviceObject, Irp);
1231 if (Status == STATUS_PENDING)
1232 {
1233 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
1234 Status = Irp->IoStatus.Status;
1235 }
1236 return Status;
1237 }
1238
1239 \f
1240 NTSTATUS
1241 NTAPI
1242 NdisIPnPStartDevice(
1243 IN PDEVICE_OBJECT DeviceObject,
1244 PIRP Irp)
1245 /*
1246 * FUNCTION: Handle the PnP start device event
1247 * ARGUMENTS:
1248 * DeviceObejct = Functional Device Object
1249 * Irp = IRP_MN_START_DEVICE I/O request packet
1250 * RETURNS:
1251 * Status of operation
1252 */
1253 {
1254 PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
1255 PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)DeviceObject->DeviceExtension;
1256 NDIS_WRAPPER_CONTEXT WrapperContext;
1257 NDIS_STATUS NdisStatus;
1258 NDIS_STATUS OpenErrorStatus;
1259 NTSTATUS Status;
1260 UINT SelectedMediumIndex = 0;
1261 NDIS_OID AddressOID;
1262 BOOLEAN Success = FALSE;
1263 ULONG ResourceCount;
1264 ULONG ResourceListSize;
1265 UNICODE_STRING ParamName;
1266 PNDIS_CONFIGURATION_PARAMETER ConfigParam;
1267 NDIS_HANDLE ConfigHandle;
1268 ULONG Size;
1269 /* FIXME - KIRQL OldIrql; */
1270
1271 /*
1272 * Prepare wrapper context used by HW and configuration routines.
1273 */
1274
1275 Status = IoOpenDeviceRegistryKey(
1276 Adapter->NdisMiniportBlock.PhysicalDeviceObject, PLUGPLAY_REGKEY_DRIVER,
1277 KEY_ALL_ACCESS, &WrapperContext.RegistryHandle);
1278 if (!NT_SUCCESS(Status))
1279 {
1280 NDIS_DbgPrint(MIN_TRACE,("failed to open adapter-specific reg key\n"));
1281 return Status;
1282 }
1283
1284 NDIS_DbgPrint(MAX_TRACE, ("opened device reg key\n"));
1285
1286 WrapperContext.DeviceObject = Adapter->NdisMiniportBlock.DeviceObject;
1287
1288 /*
1289 * Store the adapter resources used by HW routines such as
1290 * NdisMQueryAdapterResources.
1291 */
1292
1293 if (Stack->Parameters.StartDevice.AllocatedResources != NULL &&
1294 Stack->Parameters.StartDevice.AllocatedResourcesTranslated != NULL)
1295 {
1296 ResourceCount = Stack->Parameters.StartDevice.AllocatedResources->List[0].
1297 PartialResourceList.Count;
1298 ResourceListSize =
1299 FIELD_OFFSET(CM_RESOURCE_LIST, List[0].PartialResourceList.
1300 PartialDescriptors[ResourceCount]);
1301
1302 Adapter->NdisMiniportBlock.AllocatedResources =
1303 ExAllocatePool(PagedPool, ResourceListSize);
1304 if (Adapter->NdisMiniportBlock.AllocatedResources == NULL)
1305 {
1306 return STATUS_INSUFFICIENT_RESOURCES;
1307 }
1308
1309 Adapter->NdisMiniportBlock.AllocatedResourcesTranslated =
1310 ExAllocatePool(PagedPool, ResourceListSize);
1311 if (Adapter->NdisMiniportBlock.AllocatedResourcesTranslated == NULL)
1312 {
1313 ExFreePool(Adapter->NdisMiniportBlock.AllocatedResources);
1314 Adapter->NdisMiniportBlock.AllocatedResources = NULL;
1315 return STATUS_INSUFFICIENT_RESOURCES;
1316 }
1317
1318 RtlCopyMemory(Adapter->NdisMiniportBlock.AllocatedResources,
1319 Stack->Parameters.StartDevice.AllocatedResources,
1320 ResourceListSize);
1321
1322 RtlCopyMemory(Adapter->NdisMiniportBlock.AllocatedResourcesTranslated,
1323 Stack->Parameters.StartDevice.AllocatedResourcesTranslated,
1324 ResourceListSize);
1325 }
1326
1327 /*
1328 * Store the Bus Type, Bus Number and Slot information. It's used by
1329 * the hardware routines then.
1330 */
1331
1332 NdisOpenConfiguration(&NdisStatus, &ConfigHandle, (NDIS_HANDLE)&WrapperContext);
1333
1334 Size = sizeof(ULONG);
1335 Status = IoGetDeviceProperty(Adapter->NdisMiniportBlock.PhysicalDeviceObject,
1336 DevicePropertyLegacyBusType, Size,
1337 &Adapter->NdisMiniportBlock.BusType, &Size);
1338 if (!NT_SUCCESS(Status) || (INTERFACE_TYPE)Adapter->NdisMiniportBlock.BusType == InterfaceTypeUndefined)
1339 {
1340 NdisInitUnicodeString(&ParamName, L"BusType");
1341 NdisReadConfiguration(&NdisStatus, &ConfigParam, ConfigHandle,
1342 &ParamName, NdisParameterInteger);
1343 if (NdisStatus == NDIS_STATUS_SUCCESS)
1344 Adapter->NdisMiniportBlock.BusType = ConfigParam->ParameterData.IntegerData;
1345 else
1346 Adapter->NdisMiniportBlock.BusType = Isa;
1347 }
1348
1349 Status = IoGetDeviceProperty(Adapter->NdisMiniportBlock.PhysicalDeviceObject,
1350 DevicePropertyBusNumber, Size,
1351 &Adapter->NdisMiniportBlock.BusNumber, &Size);
1352 if (!NT_SUCCESS(Status) || Adapter->NdisMiniportBlock.BusNumber == 0xFFFFFFF0)
1353 {
1354 NdisInitUnicodeString(&ParamName, L"BusNumber");
1355 NdisReadConfiguration(&NdisStatus, &ConfigParam, ConfigHandle,
1356 &ParamName, NdisParameterInteger);
1357 if (NdisStatus == NDIS_STATUS_SUCCESS)
1358 Adapter->NdisMiniportBlock.BusNumber = ConfigParam->ParameterData.IntegerData;
1359 else
1360 Adapter->NdisMiniportBlock.BusNumber = 0;
1361 }
1362 WrapperContext.BusNumber = Adapter->NdisMiniportBlock.BusNumber;
1363
1364 Status = IoGetDeviceProperty(Adapter->NdisMiniportBlock.PhysicalDeviceObject,
1365 DevicePropertyAddress, Size,
1366 &Adapter->NdisMiniportBlock.SlotNumber, &Size);
1367 if (!NT_SUCCESS(Status) || Adapter->NdisMiniportBlock.SlotNumber == (NDIS_INTERFACE_TYPE)-1)
1368 {
1369 NdisInitUnicodeString(&ParamName, L"SlotNumber");
1370 NdisReadConfiguration(&NdisStatus, &ConfigParam, ConfigHandle,
1371 &ParamName, NdisParameterInteger);
1372 if (NdisStatus == NDIS_STATUS_SUCCESS)
1373 Adapter->NdisMiniportBlock.SlotNumber = ConfigParam->ParameterData.IntegerData;
1374 else
1375 Adapter->NdisMiniportBlock.SlotNumber = 0;
1376 }
1377
1378 NdisCloseConfiguration(ConfigHandle);
1379
1380 /*
1381 * Call MiniportInitialize.
1382 */
1383
1384 NDIS_DbgPrint(MID_TRACE, ("calling MiniportInitialize\n"));
1385 NdisStatus = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.InitializeHandler)(
1386 &OpenErrorStatus, &SelectedMediumIndex, &MediaArray[0],
1387 MEDIA_ARRAY_SIZE, Adapter, (NDIS_HANDLE)&WrapperContext);
1388
1389 ZwClose(WrapperContext.RegistryHandle);
1390
1391 if (NdisStatus != NDIS_STATUS_SUCCESS ||
1392 SelectedMediumIndex >= MEDIA_ARRAY_SIZE)
1393 {
1394 NDIS_DbgPrint(MIN_TRACE, ("MiniportInitialize() failed for an adapter.\n"));
1395 return (NTSTATUS)NdisStatus;
1396 }
1397
1398 /* Set handlers (some NDIS macros require these) */
1399
1400 Adapter->NdisMiniportBlock.EthRxCompleteHandler = EthFilterDprIndicateReceiveComplete;
1401 Adapter->NdisMiniportBlock.EthRxIndicateHandler = EthFilterDprIndicateReceive;
1402 Adapter->NdisMiniportBlock.SendCompleteHandler = MiniSendComplete;
1403 Adapter->NdisMiniportBlock.SendResourcesHandler = MiniSendResourcesAvailable;
1404 Adapter->NdisMiniportBlock.ResetCompleteHandler = MiniResetComplete;
1405 Adapter->NdisMiniportBlock.TDCompleteHandler = MiniTransferDataComplete;
1406 Adapter->NdisMiniportBlock.PacketIndicateHandler= MiniIndicateReceivePacket;
1407
1408 Adapter->NdisMiniportBlock.MediaType = MediaArray[SelectedMediumIndex];
1409
1410 switch (Adapter->NdisMiniportBlock.MediaType)
1411 {
1412 case NdisMedium802_3:
1413 Adapter->MediumHeaderSize = 14; /* XXX figure out what to do about LLC */
1414 AddressOID = OID_802_3_CURRENT_ADDRESS;
1415 Adapter->AddressLength = ETH_LENGTH_OF_ADDRESS;
1416 NdisStatus = DoQueries(Adapter, AddressOID);
1417 if (NdisStatus == NDIS_STATUS_SUCCESS)
1418 {
1419 Success = EthCreateFilter(32, /* FIXME: Query this from miniport. */
1420 Adapter->Address.Type.Medium802_3,
1421 &Adapter->NdisMiniportBlock.EthDB);
1422 if (Success)
1423 ((PETHI_FILTER)Adapter->NdisMiniportBlock.EthDB)->Miniport = (PNDIS_MINIPORT_BLOCK)Adapter;
1424 else
1425 NdisStatus = NDIS_STATUS_RESOURCES;
1426 }
1427 break;
1428
1429 default:
1430 /* FIXME: Support other types of media */
1431 NDIS_DbgPrint(MIN_TRACE, ("error: unsupported media\n"));
1432 ASSERT(FALSE);
1433 /* FIXME - KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql); */
1434 return STATUS_UNSUCCESSFUL;
1435 }
1436
1437 if (!Success || NdisStatus != NDIS_STATUS_SUCCESS)
1438 {
1439 NDIS_DbgPrint(MAX_TRACE, ("couldn't create filter (%x)\n", NdisStatus));
1440 if (Adapter->LookaheadBuffer)
1441 {
1442 ExFreePool(Adapter->LookaheadBuffer);
1443 Adapter->LookaheadBuffer = NULL;
1444 }
1445 return (NTSTATUS)NdisStatus;
1446 }
1447
1448 Adapter->NdisMiniportBlock.OldPnPDeviceState = Adapter->NdisMiniportBlock.PnPDeviceState;
1449 Adapter->NdisMiniportBlock.PnPDeviceState = NdisPnPDeviceStarted;
1450
1451 /* Put adapter in adapter list for this miniport */
1452 ExInterlockedInsertTailList(&Adapter->NdisMiniportBlock.DriverHandle->DeviceList, &Adapter->MiniportListEntry, &Adapter->NdisMiniportBlock.DriverHandle->Lock);
1453
1454 /* Put adapter in global adapter list */
1455 ExInterlockedInsertTailList(&AdapterListHead, &Adapter->ListEntry, &AdapterListLock);
1456
1457 return STATUS_SUCCESS;
1458 }
1459
1460 \f
1461 NTSTATUS
1462 NTAPI
1463 NdisIPnPStopDevice(
1464 IN PDEVICE_OBJECT DeviceObject,
1465 PIRP Irp)
1466 /*
1467 * FUNCTION: Handle the PnP stop device event
1468 * ARGUMENTS:
1469 * DeviceObejct = Functional Device Object
1470 * Irp = IRP_MN_STOP_DEVICE I/O request packet
1471 * RETURNS:
1472 * Status of operation
1473 */
1474 {
1475 PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)DeviceObject->DeviceExtension;
1476 KIRQL OldIrql;
1477
1478 /* Remove adapter from adapter list for this miniport */
1479 KeAcquireSpinLock(&Adapter->NdisMiniportBlock.DriverHandle->Lock, &OldIrql);
1480 RemoveEntryList(&Adapter->MiniportListEntry);
1481 KeReleaseSpinLock(&Adapter->NdisMiniportBlock.DriverHandle->Lock, OldIrql);
1482
1483 /* Remove adapter from global adapter list */
1484 KeAcquireSpinLock(&AdapterListLock, &OldIrql);
1485 RemoveEntryList(&Adapter->ListEntry);
1486 KeReleaseSpinLock(&AdapterListLock, OldIrql);
1487
1488 (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.HaltHandler)(Adapter);
1489
1490 if (Adapter->LookaheadBuffer)
1491 {
1492 ExFreePool(Adapter->LookaheadBuffer);
1493 Adapter->LookaheadBuffer = NULL;
1494 }
1495 if (Adapter->NdisMiniportBlock.AllocatedResources)
1496 {
1497 ExFreePool(Adapter->NdisMiniportBlock.AllocatedResources);
1498 Adapter->NdisMiniportBlock.AllocatedResources = NULL;
1499 }
1500 if (Adapter->NdisMiniportBlock.AllocatedResourcesTranslated)
1501 {
1502 ExFreePool(Adapter->NdisMiniportBlock.AllocatedResourcesTranslated);
1503 Adapter->NdisMiniportBlock.AllocatedResourcesTranslated = NULL;
1504 }
1505
1506 Adapter->NdisMiniportBlock.OldPnPDeviceState = Adapter->NdisMiniportBlock.PnPDeviceState;
1507 Adapter->NdisMiniportBlock.PnPDeviceState = NdisPnPDeviceStopped;
1508
1509 return STATUS_SUCCESS;
1510 }
1511
1512 \f
1513 NTSTATUS
1514 NTAPI
1515 NdisIDispatchPnp(
1516 IN PDEVICE_OBJECT DeviceObject,
1517 PIRP Irp)
1518 {
1519 PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
1520 PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)DeviceObject->DeviceExtension;
1521 NTSTATUS Status;
1522
1523 switch (Stack->MinorFunction)
1524 {
1525 case IRP_MN_START_DEVICE:
1526 Status = NdisIForwardIrpAndWait(Adapter, Irp);
1527 if (NT_SUCCESS(Status) && NT_SUCCESS(Irp->IoStatus.Status))
1528 {
1529 Status = NdisIPnPStartDevice(DeviceObject, Irp);
1530 }
1531 Irp->IoStatus.Status = Status;
1532 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1533 break;
1534
1535 case IRP_MN_STOP_DEVICE:
1536 /* FIXME */
1537 Status = STATUS_UNSUCCESSFUL;
1538 break;
1539 Status = NdisIForwardIrpAndWait(Adapter, Irp);
1540 if (NT_SUCCESS(Status) && NT_SUCCESS(Irp->IoStatus.Status))
1541 {
1542 Status = NdisIPnPStopDevice(DeviceObject, Irp);
1543 }
1544 Irp->IoStatus.Status = Status;
1545 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1546 break;
1547
1548 default:
1549 IoSkipCurrentIrpStackLocation(Irp);
1550 Status = IoCallDriver(Adapter->NdisMiniportBlock.NextDeviceObject, Irp);
1551 break;
1552 }
1553
1554 return Status;
1555 }
1556
1557 \f
1558 NTSTATUS
1559 NTAPI
1560 NdisIAddDevice(
1561 IN PDRIVER_OBJECT DriverObject,
1562 IN PDEVICE_OBJECT PhysicalDeviceObject)
1563 /*
1564 * FUNCTION: Create a device for an adapter found using PnP
1565 * ARGUMENTS:
1566 * DriverObject = Pointer to the miniport driver object
1567 * PhysicalDeviceObject = Pointer to the PDO for our adapter
1568 */
1569 {
1570 static const WCHAR ClassKeyName[] = {'C','l','a','s','s','\\'};
1571 static const WCHAR LinkageKeyName[] = {'\\','L','i','n','k','a','g','e',0};
1572 PNDIS_M_DRIVER_BLOCK Miniport;
1573 PNDIS_M_DRIVER_BLOCK *MiniportPtr;
1574 WCHAR *LinkageKeyBuffer;
1575 ULONG DriverKeyLength;
1576 RTL_QUERY_REGISTRY_TABLE QueryTable[2];
1577 UNICODE_STRING ExportName;
1578 PDEVICE_OBJECT DeviceObject;
1579 PLOGICAL_ADAPTER Adapter;
1580 NTSTATUS Status;
1581
1582 /*
1583 * Gain the access to the miniport data structure first.
1584 */
1585
1586 MiniportPtr = IoGetDriverObjectExtension(DriverObject, (PVOID)TAG('D','I','M','N'));
1587 if (MiniportPtr == NULL)
1588 {
1589 NDIS_DbgPrint(DEBUG_MINIPORT, ("Can't get driver object extension.\n"));
1590 return STATUS_UNSUCCESSFUL;
1591 }
1592 Miniport = *MiniportPtr;
1593
1594 /*
1595 * Get name of the Linkage registry key for our adapter. It's located under
1596 * the driver key for our driver and so we have basicly two ways to do it.
1597 * Either we can use IoOpenDriverRegistryKey or compose it using information
1598 * gathered by IoGetDeviceProperty. I choosed the second because
1599 * IoOpenDriverRegistryKey wasn't implemented at the time of writing.
1600 */
1601
1602 Status = IoGetDeviceProperty(PhysicalDeviceObject, DevicePropertyDriverKeyName,
1603 0, NULL, &DriverKeyLength);
1604 if (Status != STATUS_BUFFER_TOO_SMALL)
1605 {
1606 NDIS_DbgPrint(DEBUG_MINIPORT, ("Can't get miniport driver key length.\n"));
1607 return Status;
1608 }
1609
1610 LinkageKeyBuffer = ExAllocatePool(PagedPool, DriverKeyLength +
1611 sizeof(ClassKeyName) + sizeof(LinkageKeyName));
1612 if (LinkageKeyBuffer == NULL)
1613 {
1614 NDIS_DbgPrint(DEBUG_MINIPORT, ("Can't allocate memory for driver key name.\n"));
1615 return STATUS_INSUFFICIENT_RESOURCES;
1616 }
1617
1618 Status = IoGetDeviceProperty(PhysicalDeviceObject, DevicePropertyDriverKeyName,
1619 DriverKeyLength, LinkageKeyBuffer +
1620 (sizeof(ClassKeyName) / sizeof(WCHAR)),
1621 &DriverKeyLength);
1622 if (!NT_SUCCESS(Status))
1623 {
1624 NDIS_DbgPrint(DEBUG_MINIPORT, ("Can't get miniport driver key.\n"));
1625 ExFreePool(LinkageKeyBuffer);
1626 return Status;
1627 }
1628
1629 /* Compose the linkage key name. */
1630 RtlCopyMemory(LinkageKeyBuffer, ClassKeyName, sizeof(ClassKeyName));
1631 RtlCopyMemory(LinkageKeyBuffer + ((sizeof(ClassKeyName) + DriverKeyLength) /
1632 sizeof(WCHAR)) - 1, LinkageKeyName, sizeof(LinkageKeyName));
1633
1634 NDIS_DbgPrint(DEBUG_MINIPORT, ("LinkageKey: %S.\n", LinkageKeyBuffer));
1635
1636 /*
1637 * Now open the linkage key and read the "Export" and "RootDevice" values
1638 * which contains device name and root service respectively.
1639 */
1640
1641 RtlZeroMemory(QueryTable, sizeof(QueryTable));
1642 RtlInitUnicodeString(&ExportName, NULL);
1643 QueryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED | RTL_QUERY_REGISTRY_DIRECT;
1644 QueryTable[0].Name = L"Export";
1645 QueryTable[0].EntryContext = &ExportName;
1646
1647 Status = RtlQueryRegistryValues(RTL_REGISTRY_CONTROL, LinkageKeyBuffer,
1648 QueryTable, NULL, NULL);
1649 ExFreePool(LinkageKeyBuffer);
1650 if (!NT_SUCCESS(Status))
1651 {
1652 NDIS_DbgPrint(DEBUG_MINIPORT, ("Can't get miniport device name. (%x)\n", Status));
1653 return Status;
1654 }
1655
1656 /*
1657 * Create the device object.
1658 */
1659
1660 NDIS_DbgPrint(MAX_TRACE, ("creating device %wZ\n", &ExportName));
1661
1662 Status = IoCreateDevice(Miniport->DriverObject, sizeof(LOGICAL_ADAPTER),
1663 &ExportName, FILE_DEVICE_PHYSICAL_NETCARD,
1664 0, FALSE, &DeviceObject);
1665 if (!NT_SUCCESS(Status))
1666 {
1667 NDIS_DbgPrint(MIN_TRACE, ("Could not create device object.\n"));
1668 RtlFreeUnicodeString(&ExportName);
1669 return Status;
1670 }
1671
1672 /*
1673 * Initialize the adapter structure.
1674 */
1675
1676 Adapter = (PLOGICAL_ADAPTER)DeviceObject->DeviceExtension;
1677 KeInitializeSpinLock(&Adapter->NdisMiniportBlock.Lock);
1678 InitializeListHead(&Adapter->ProtocolListHead);
1679 Adapter->NdisMiniportBlock.DriverHandle = Miniport;
1680
1681 Adapter->NdisMiniportBlock.MiniportName = ExportName;
1682
1683 Adapter->NdisMiniportBlock.DeviceObject = DeviceObject;
1684 Adapter->NdisMiniportBlock.PhysicalDeviceObject = PhysicalDeviceObject;
1685 Adapter->NdisMiniportBlock.NextDeviceObject =
1686 IoAttachDeviceToDeviceStack(Adapter->NdisMiniportBlock.DeviceObject,
1687 PhysicalDeviceObject);
1688
1689 Adapter->NdisMiniportBlock.OldPnPDeviceState = 0;
1690 Adapter->NdisMiniportBlock.PnPDeviceState = NdisPnPDeviceAdded;
1691
1692 KeInitializeDpc(&Adapter->NdisMiniportBlock.DeferredDpc, MiniportDpc, (PVOID)Adapter);
1693
1694 DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
1695
1696 return STATUS_SUCCESS;
1697 }
1698
1699 \f
1700 /*
1701 * @implemented
1702 */
1703 NDIS_STATUS
1704 EXPORT
1705 NdisMRegisterMiniport(
1706 IN NDIS_HANDLE NdisWrapperHandle,
1707 IN PNDIS_MINIPORT_CHARACTERISTICS MiniportCharacteristics,
1708 IN UINT CharacteristicsLength)
1709 /*
1710 * FUNCTION: Registers a miniport's MiniportXxx entry points with the NDIS library
1711 * ARGUMENTS:
1712 * NdisWrapperHandle = Pointer to handle returned by NdisMInitializeWrapper
1713 * MiniportCharacteristics = Pointer to a buffer with miniport characteristics
1714 * CharacteristicsLength = Number of bytes in characteristics buffer
1715 * RETURNS:
1716 * Status of operation
1717 */
1718 {
1719 UINT MinSize;
1720 PNDIS_M_DRIVER_BLOCK Miniport = GET_MINIPORT_DRIVER(NdisWrapperHandle);
1721 PNDIS_M_DRIVER_BLOCK *MiniportPtr;
1722 NTSTATUS Status;
1723
1724 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
1725
1726 switch (MiniportCharacteristics->MajorNdisVersion)
1727 {
1728 case 0x03:
1729 MinSize = sizeof(NDIS30_MINIPORT_CHARACTERISTICS);
1730 break;
1731
1732 case 0x04:
1733 MinSize = sizeof(NDIS40_MINIPORT_CHARACTERISTICS);
1734 break;
1735
1736 case 0x05:
1737 MinSize = sizeof(NDIS50_MINIPORT_CHARACTERISTICS);
1738 break;
1739
1740 default:
1741 NDIS_DbgPrint(DEBUG_MINIPORT, ("Bad miniport characteristics version.\n"));
1742 return NDIS_STATUS_BAD_VERSION;
1743 }
1744
1745 if (CharacteristicsLength < MinSize)
1746 {
1747 NDIS_DbgPrint(DEBUG_MINIPORT, ("Bad miniport characteristics.\n"));
1748 return NDIS_STATUS_BAD_CHARACTERISTICS;
1749 }
1750
1751 /* Check if mandatory MiniportXxx functions are specified */
1752 if ((!MiniportCharacteristics->HaltHandler) ||
1753 (!MiniportCharacteristics->InitializeHandler)||
1754 (!MiniportCharacteristics->QueryInformationHandler) ||
1755 (!MiniportCharacteristics->ResetHandler) ||
1756 (!MiniportCharacteristics->SetInformationHandler))
1757 {
1758 NDIS_DbgPrint(DEBUG_MINIPORT, ("Bad miniport characteristics.\n"));
1759 return NDIS_STATUS_BAD_CHARACTERISTICS;
1760 }
1761
1762 if (MiniportCharacteristics->MajorNdisVersion == 0x03)
1763 {
1764 if (!MiniportCharacteristics->SendHandler)
1765 {
1766 NDIS_DbgPrint(DEBUG_MINIPORT, ("Bad miniport characteristics.\n"));
1767 return NDIS_STATUS_BAD_CHARACTERISTICS;
1768 }
1769 }
1770 else if (MiniportCharacteristics->MajorNdisVersion >= 0x04)
1771 {
1772 /* NDIS 4.0+ */
1773 if ((!MiniportCharacteristics->SendHandler) &&
1774 (!MiniportCharacteristics->SendPacketsHandler))
1775 {
1776 NDIS_DbgPrint(DEBUG_MINIPORT, ("Bad miniport characteristics.\n"));
1777 return NDIS_STATUS_BAD_CHARACTERISTICS;
1778 }
1779 }
1780
1781 /* TODO: verify NDIS5 and NDIS5.1 */
1782
1783 RtlCopyMemory(&Miniport->MiniportCharacteristics, MiniportCharacteristics, MinSize);
1784
1785 /*
1786 * NOTE: This is VERY unoptimal! Should we store the NDIS_M_DRIVER_BLOCK
1787 * structure in the driver extension or what?
1788 */
1789
1790 Status = IoAllocateDriverObjectExtension(Miniport->DriverObject, (PVOID)TAG('D','I','M','N'),
1791 sizeof(PNDIS_M_DRIVER_BLOCK), (PVOID*)&MiniportPtr);
1792 if (!NT_SUCCESS(Status))
1793 {
1794 NDIS_DbgPrint(DEBUG_MINIPORT, ("Can't allocate driver object extension.\n"));
1795 return NDIS_STATUS_RESOURCES;
1796 }
1797
1798 *MiniportPtr = Miniport;
1799
1800 Miniport->DriverObject->MajorFunction[IRP_MJ_PNP] = NdisIDispatchPnp;
1801 Miniport->DriverObject->DriverExtension->AddDevice = NdisIAddDevice;
1802
1803 return NDIS_STATUS_SUCCESS;
1804 }
1805
1806 \f
1807 /*
1808 * @implemented
1809 */
1810 #undef NdisMResetComplete
1811 VOID
1812 EXPORT
1813 NdisMResetComplete(
1814 IN NDIS_HANDLE MiniportAdapterHandle,
1815 IN NDIS_STATUS Status,
1816 IN BOOLEAN AddressingReset)
1817 {
1818 MiniResetComplete(MiniportAdapterHandle, Status, AddressingReset);
1819 }
1820
1821 \f
1822 /*
1823 * @implemented
1824 */
1825 #undef NdisMSendComplete
1826 VOID
1827 EXPORT
1828 NdisMSendComplete(
1829 IN NDIS_HANDLE MiniportAdapterHandle,
1830 IN PNDIS_PACKET Packet,
1831 IN NDIS_STATUS Status)
1832 /*
1833 * FUNCTION: Forwards a message to the initiating protocol saying
1834 * that a packet was handled
1835 * ARGUMENTS:
1836 * NdisAdapterHandle = Handle input to MiniportInitialize
1837 * Packet = Pointer to NDIS packet that was sent
1838 * Status = Status of send operation
1839 */
1840 {
1841 MiniSendComplete(MiniportAdapterHandle, Packet, Status);
1842 }
1843
1844 \f
1845 /*
1846 * @implemented
1847 */
1848 #undef NdisMSendResourcesAvailable
1849 VOID
1850 EXPORT
1851 NdisMSendResourcesAvailable(
1852 IN NDIS_HANDLE MiniportAdapterHandle)
1853 {
1854 MiniSendResourcesAvailable(MiniportAdapterHandle);
1855 }
1856
1857 \f
1858 /*
1859 * @implemented
1860 */
1861 #undef NdisMTransferDataComplete
1862 VOID
1863 EXPORT
1864 NdisMTransferDataComplete(
1865 IN NDIS_HANDLE MiniportAdapterHandle,
1866 IN PNDIS_PACKET Packet,
1867 IN NDIS_STATUS Status,
1868 IN UINT BytesTransferred)
1869 {
1870 MiniTransferDataComplete(MiniportAdapterHandle, Packet, Status, BytesTransferred);
1871 }
1872
1873 \f
1874 /*
1875 * @implemented
1876 */
1877 #undef NdisMSetInformationComplete
1878 VOID
1879 EXPORT
1880 NdisMSetInformationComplete(
1881 IN NDIS_HANDLE MiniportAdapterHandle,
1882 IN NDIS_STATUS Status)
1883 {
1884 (*((PNDIS_MINIPORT_BLOCK)(MiniportAdapterHandle))->SetCompleteHandler)(MiniportAdapterHandle, Status);
1885 }
1886
1887 \f
1888 /*
1889 * @implemented
1890 */
1891 #undef NdisMSetAttributes
1892 VOID
1893 EXPORT
1894 NdisMSetAttributes(
1895 IN NDIS_HANDLE MiniportAdapterHandle,
1896 IN NDIS_HANDLE MiniportAdapterContext,
1897 IN BOOLEAN BusMaster,
1898 IN NDIS_INTERFACE_TYPE AdapterType)
1899 /*
1900 * FUNCTION: Informs the NDIS library of significant features of the caller's NIC
1901 * ARGUMENTS:
1902 * MiniportAdapterHandle = Handle input to MiniportInitialize
1903 * MiniportAdapterContext = Pointer to context information
1904 * BusMaster = Specifies TRUE if the caller's NIC is a busmaster DMA device
1905 * AdapterType = Specifies the I/O bus interface of the caller's NIC
1906 */
1907 {
1908 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
1909 NdisMSetAttributesEx(MiniportAdapterHandle, MiniportAdapterContext, 0,
1910 BusMaster ? NDIS_ATTRIBUTE_BUS_MASTER : 0,
1911 AdapterType);
1912 }
1913
1914 \f
1915 /*
1916 * @implemented
1917 */
1918 VOID
1919 EXPORT
1920 NdisMSetAttributesEx(
1921 IN NDIS_HANDLE MiniportAdapterHandle,
1922 IN NDIS_HANDLE MiniportAdapterContext,
1923 IN UINT CheckForHangTimeInSeconds OPTIONAL,
1924 IN ULONG AttributeFlags,
1925 IN NDIS_INTERFACE_TYPE AdapterType)
1926 /*
1927 * FUNCTION: Informs the NDIS library of significant features of the caller's NIC
1928 * ARGUMENTS:
1929 * MiniportAdapterHandle = Handle input to MiniportInitialize
1930 * MiniportAdapterContext = Pointer to context information
1931 * CheckForHangTimeInSeconds = Specifies interval in seconds at which
1932 * MiniportCheckForHang should be called
1933 * AttributeFlags = Bitmask that indicates specific attributes
1934 * AdapterType = Specifies the I/O bus interface of the caller's NIC
1935 */
1936 {
1937 /* TODO: Take CheckForHandTimeInSeconds into account! */
1938
1939 PLOGICAL_ADAPTER Adapter = GET_LOGICAL_ADAPTER(MiniportAdapterHandle);
1940
1941 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
1942
1943 Adapter->NdisMiniportBlock.MiniportAdapterContext = MiniportAdapterContext;
1944 Adapter->NdisMiniportBlock.Flags = AttributeFlags;
1945 Adapter->NdisMiniportBlock.AdapterType = AdapterType;
1946 if (AttributeFlags & NDIS_ATTRIBUTE_INTERMEDIATE_DRIVER)
1947 NDIS_DbgPrint(MAX_TRACE, ("Intermediate drivers not supported yet.\n"));
1948 }
1949
1950 \f
1951 /*
1952 * @implemented
1953 */
1954 VOID
1955 EXPORT
1956 NdisMSleep(
1957 IN ULONG MicrosecondsToSleep)
1958 /*
1959 * FUNCTION: delay the thread's execution for MicrosecondsToSleep
1960 * ARGUMENTS:
1961 * MicrosecondsToSleep: duh...
1962 * NOTES:
1963 * - Because this is a blocking call, current IRQL must be < DISPATCH_LEVEL
1964 */
1965 {
1966 KTIMER Timer;
1967 LARGE_INTEGER DueTime;
1968
1969 PAGED_CODE();
1970
1971 DueTime.QuadPart = (-1) * 10 * MicrosecondsToSleep;
1972
1973 KeInitializeTimer(&Timer);
1974 KeSetTimer(&Timer, DueTime, 0);
1975 KeWaitForSingleObject(&Timer, Executive, KernelMode, FALSE, 0);
1976 }
1977
1978 \f
1979 /*
1980 * @implemented
1981 */
1982 BOOLEAN
1983 EXPORT
1984 NdisMSynchronizeWithInterrupt(
1985 IN PNDIS_MINIPORT_INTERRUPT Interrupt,
1986 IN PVOID SynchronizeFunction,
1987 IN PVOID SynchronizeContext)
1988 {
1989 return(KeSynchronizeExecution(Interrupt->InterruptObject,
1990 (PKSYNCHRONIZE_ROUTINE)SynchronizeFunction,
1991 SynchronizeContext));
1992 }
1993
1994 \f
1995 /*
1996 * @unimplemented
1997 */
1998 NDIS_STATUS
1999 EXPORT
2000 NdisMWriteLogData(
2001 IN NDIS_HANDLE LogHandle,
2002 IN PVOID LogBuffer,
2003 IN UINT LogBufferSize)
2004 {
2005 UNIMPLEMENTED
2006
2007 return NDIS_STATUS_FAILURE;
2008 }
2009
2010 \f
2011 /*
2012 * @implemented
2013 */
2014 VOID
2015 EXPORT
2016 NdisTerminateWrapper(
2017 IN NDIS_HANDLE NdisWrapperHandle,
2018 IN PVOID SystemSpecific)
2019 /*
2020 * FUNCTION: Releases resources allocated by a call to NdisInitializeWrapper
2021 * ARGUMENTS:
2022 * NdisWrapperHandle = Handle returned by NdisInitializeWrapper (NDIS_M_DRIVER_BLOCK)
2023 * SystemSpecific = Always NULL
2024 */
2025 {
2026 PNDIS_M_DRIVER_BLOCK Miniport = GET_MINIPORT_DRIVER(NdisWrapperHandle);
2027
2028 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
2029
2030 ExFreePool(Miniport->RegistryPath->Buffer);
2031 ExFreePool(Miniport->RegistryPath);
2032 ExFreePool(Miniport);
2033 }
2034
2035 /* EOF */
2036