initial version, corresponding to ipfw3-2012
[ipfw-google.git] / original_passthru / protocol.c
1 /*++\r
2 \r
3 Copyright(c) 1992-2000  Microsoft Corporation\r
4 \r
5 Module Name:\r
6 \r
7     protocol.c\r
8 \r
9 Abstract:\r
10 \r
11     Ndis Intermediate Miniport driver sample. This is a passthru driver.\r
12 \r
13 Author:\r
14 \r
15 Environment:\r
16 \r
17 \r
18 Revision History:\r
19 \r
20 \r
21 --*/\r
22 \r
23 \r
24 #include "precomp.h"\r
25 #pragma hdrstop\r
26 \r
27 #define MAX_PACKET_POOL_SIZE 0x0000FFFF\r
28 #define MIN_PACKET_POOL_SIZE 0x000000FF\r
29 \r
30 //\r
31 // NDIS version as 0xMMMMmmmm, where M=Major/m=minor (0x00050001 = 5.1); \r
32 // initially unknown (0)\r
33 // \r
34 ULONG       NdisDotSysVersion =  0x0;\r
35 \r
36 \r
37 #define NDIS_SYS_VERSION_51       0x00050001\r
38 \r
39 \r
40 VOID\r
41 PtBindAdapter(\r
42     OUT PNDIS_STATUS            Status,\r
43     IN  NDIS_HANDLE             BindContext,\r
44     IN  PNDIS_STRING            DeviceName,\r
45     IN  PVOID                   SystemSpecific1,\r
46     IN  PVOID                   SystemSpecific2\r
47     )\r
48 /*++\r
49 \r
50 Routine Description:\r
51 \r
52     Called by NDIS to bind to a miniport below.\r
53 \r
54 Arguments:\r
55 \r
56     Status            - Return status of bind here.\r
57     BindContext        - Can be passed to NdisCompleteBindAdapter if this call is pended.\r
58     DeviceName         - Device name to bind to. This is passed to NdisOpenAdapter.\r
59     SystemSpecific1    - Can be passed to NdisOpenProtocolConfiguration to read per-binding information\r
60     SystemSpecific2    - Unused\r
61 \r
62 Return Value:\r
63 \r
64     NDIS_STATUS_PENDING    if this call is pended. In this case call NdisCompleteBindAdapter\r
65     to complete.\r
66     Anything else          Completes this call synchronously\r
67 \r
68 --*/\r
69 {\r
70     NDIS_HANDLE                     ConfigHandle = NULL;\r
71     PNDIS_CONFIGURATION_PARAMETER   Param;\r
72     NDIS_STRING                     DeviceStr = NDIS_STRING_CONST("UpperBindings");\r
73     NDIS_STRING                     NdisVersionStr = NDIS_STRING_CONST("NdisVersion");\r
74     PADAPT                          pAdapt = NULL;\r
75     NDIS_STATUS                     Sts;\r
76     UINT                            MediumIndex;\r
77     ULONG                           TotalSize;\r
78     BOOLEAN                         NoCleanUpNeeded = FALSE;\r
79 \r
80 \r
81     UNREFERENCED_PARAMETER(BindContext);\r
82     UNREFERENCED_PARAMETER(SystemSpecific2);\r
83     \r
84     DBGPRINT(("==> Protocol BindAdapter\n"));\r
85 \r
86     do\r
87     {\r
88         //\r
89         // Access the configuration section for our binding-specific\r
90         // parameters.\r
91         //\r
92         NdisOpenProtocolConfiguration(Status,\r
93                                        &ConfigHandle,\r
94                                        SystemSpecific1);\r
95 \r
96         if (*Status != NDIS_STATUS_SUCCESS)\r
97         {\r
98             break;\r
99         }\r
100         if (NdisDotSysVersion == 0)\r
101         {\r
102             NdisReadConfiguration(Status,\r
103                                   &Param,\r
104                                   ConfigHandle,\r
105                                   &NdisVersionStr,        // "NdisVersion"\r
106                                   NdisParameterInteger);\r
107             if (*Status != NDIS_STATUS_SUCCESS)\r
108             {\r
109                 break;\r
110             }\r
111             \r
112             NdisDotSysVersion = Param->ParameterData.IntegerData;\r
113         }\r
114                         \r
115 \r
116         //\r
117         // Read the "UpperBindings" reserved key that contains a list\r
118         // of device names representing our miniport instances corresponding\r
119         // to this lower binding. Since this is a 1:1 IM driver, this key\r
120         // contains exactly one name.\r
121         //\r
122         // If we want to implement a N:1 mux driver (N adapter instances\r
123         // over a single lower binding), then UpperBindings will be a\r
124         // MULTI_SZ containing a list of device names - we would loop through\r
125         // this list, calling NdisIMInitializeDeviceInstanceEx once for\r
126         // each name in it.\r
127         //\r
128         NdisReadConfiguration(Status,\r
129                               &Param,\r
130                               ConfigHandle,\r
131                               &DeviceStr,\r
132                               NdisParameterString);\r
133         if (*Status != NDIS_STATUS_SUCCESS)\r
134         {\r
135             break;\r
136         }\r
137 \r
138         //\r
139         // Allocate memory for the Adapter structure. This represents both the\r
140         // protocol context as well as the adapter structure when the miniport\r
141         // is initialized.\r
142         //\r
143         // In addition to the base structure, allocate space for the device\r
144         // instance string.\r
145         //\r
146         TotalSize = sizeof(ADAPT) + Param->ParameterData.StringData.MaximumLength;\r
147 \r
148         NdisAllocateMemoryWithTag(&pAdapt, TotalSize, TAG);\r
149 \r
150         if (pAdapt == NULL)\r
151         {\r
152             *Status = NDIS_STATUS_RESOURCES;\r
153             break;\r
154         }\r
155 \r
156         //\r
157         // Initialize the adapter structure. We copy in the IM device\r
158         // name as well, because we may need to use it in a call to\r
159         // NdisIMCancelInitializeDeviceInstance. The string returned\r
160         // by NdisReadConfiguration is active (i.e. available) only\r
161         // for the duration of this call to our BindAdapter handler.\r
162         //\r
163         NdisZeroMemory(pAdapt, TotalSize);\r
164         pAdapt->DeviceName.MaximumLength = Param->ParameterData.StringData.MaximumLength;\r
165         pAdapt->DeviceName.Length = Param->ParameterData.StringData.Length;\r
166         pAdapt->DeviceName.Buffer = (PWCHAR)((ULONG_PTR)pAdapt + sizeof(ADAPT));\r
167         NdisMoveMemory(pAdapt->DeviceName.Buffer,\r
168                        Param->ParameterData.StringData.Buffer,\r
169                        Param->ParameterData.StringData.MaximumLength);\r
170 \r
171 \r
172 \r
173         NdisInitializeEvent(&pAdapt->Event);\r
174         NdisAllocateSpinLock(&pAdapt->Lock);\r
175 \r
176         //\r
177         // Allocate a packet pool for sends. We need this to pass sends down.\r
178         // We cannot use the same packet descriptor that came down to our send\r
179         // handler (see also NDIS 5.1 packet stacking).\r
180         //\r
181         NdisAllocatePacketPoolEx(Status,\r
182                                    &pAdapt->SendPacketPoolHandle,\r
183                                    MIN_PACKET_POOL_SIZE,\r
184                                    MAX_PACKET_POOL_SIZE - MIN_PACKET_POOL_SIZE,\r
185                                    sizeof(SEND_RSVD));\r
186 \r
187         if (*Status != NDIS_STATUS_SUCCESS)\r
188         {\r
189             break;\r
190         }\r
191 \r
192         //\r
193         // Allocate a packet pool for receives. We need this to indicate receives.\r
194         // Same consideration as sends (see also NDIS 5.1 packet stacking).\r
195         //\r
196         NdisAllocatePacketPoolEx(Status,\r
197                                    &pAdapt->RecvPacketPoolHandle,\r
198                                    MIN_PACKET_POOL_SIZE,\r
199                                    MAX_PACKET_POOL_SIZE - MIN_PACKET_POOL_SIZE,\r
200                                    PROTOCOL_RESERVED_SIZE_IN_PACKET);\r
201 \r
202         if (*Status != NDIS_STATUS_SUCCESS)\r
203         {\r
204             break;\r
205         }\r
206 \r
207         //\r
208         // Now open the adapter below and complete the initialization\r
209         //\r
210         NdisOpenAdapter(Status,\r
211                           &Sts,\r
212                           &pAdapt->BindingHandle,\r
213                           &MediumIndex,\r
214                           MediumArray,\r
215                           sizeof(MediumArray)/sizeof(NDIS_MEDIUM),\r
216                           ProtHandle,\r
217                           pAdapt,\r
218                           DeviceName,\r
219                           0,\r
220                           NULL);\r
221 \r
222         if (*Status == NDIS_STATUS_PENDING)\r
223         {\r
224             NdisWaitEvent(&pAdapt->Event, 0);\r
225             *Status = pAdapt->Status;\r
226         }\r
227 \r
228         if (*Status != NDIS_STATUS_SUCCESS)\r
229         {\r
230             break;\r
231         }\r
232         PtReferenceAdapt(pAdapt);\r
233 \r
234 #pragma prefast(suppress: __WARNING_POTENTIAL_BUFFER_OVERFLOW, "Ndis guarantees MediumIndex to be within bounds");\r
235         pAdapt->Medium = MediumArray[MediumIndex];\r
236 \r
237         //\r
238         // Now ask NDIS to initialize our miniport (upper) edge.\r
239         // Set the flag below to synchronize with a possible call\r
240         // to our protocol Unbind handler that may come in before\r
241         // our miniport initialization happens.\r
242         //\r
243         pAdapt->MiniportInitPending = TRUE;\r
244         NdisInitializeEvent(&pAdapt->MiniportInitEvent);\r
245 \r
246         PtReferenceAdapt(pAdapt);\r
247 \r
248         *Status = NdisIMInitializeDeviceInstanceEx(DriverHandle,\r
249                                            &pAdapt->DeviceName,\r
250                                            pAdapt);\r
251 \r
252         if (*Status != NDIS_STATUS_SUCCESS)\r
253         {\r
254             if (pAdapt->MiniportIsHalted == TRUE)\r
255             {\r
256                 NoCleanUpNeeded = TRUE;\r
257             }\r
258             \r
259             DBGPRINT(("BindAdapter: Adapt %p, IMInitializeDeviceInstance error %x\n",\r
260                 pAdapt, *Status));\r
261             \r
262             if (PtDereferenceAdapt(pAdapt))\r
263             {\r
264                 pAdapt = NULL;\r
265             }\r
266             \r
267             break;\r
268         }\r
269         \r
270         PtDereferenceAdapt(pAdapt);\r
271 \r
272     } while(FALSE);\r
273 \r
274     //\r
275     // Close the configuration handle now - see comments above with\r
276     // the call to NdisIMInitializeDeviceInstanceEx.\r
277     //\r
278     if (ConfigHandle != NULL)\r
279     {\r
280         NdisCloseConfiguration(ConfigHandle);\r
281     }\r
282 \r
283     if ((*Status != NDIS_STATUS_SUCCESS) && (NoCleanUpNeeded == FALSE))\r
284     {\r
285         if (pAdapt != NULL)\r
286         {\r
287             if (pAdapt->BindingHandle != NULL)\r
288             {\r
289                 NDIS_STATUS    LocalStatus;\r
290 \r
291                 //\r
292                 // Close the binding we opened above.\r
293                 //\r
294 \r
295                 NdisResetEvent(&pAdapt->Event);\r
296                 \r
297                 NdisCloseAdapter(&LocalStatus, pAdapt->BindingHandle);\r
298                 pAdapt->BindingHandle = NULL;\r
299 \r
300                 if (LocalStatus == NDIS_STATUS_PENDING)\r
301                 {\r
302                      NdisWaitEvent(&pAdapt->Event, 0);\r
303                      LocalStatus = pAdapt->Status;\r
304 \r
305                      \r
306                 }\r
307                 if (PtDereferenceAdapt(pAdapt))\r
308                 {\r
309                      pAdapt = NULL;\r
310                 }\r
311             }\r
312         }\r
313     }\r
314 \r
315 \r
316     DBGPRINT(("<== Protocol BindAdapter: pAdapt %p, Status %x\n", pAdapt, *Status));\r
317 }\r
318 \r
319 \r
320 VOID\r
321 PtOpenAdapterComplete(\r
322     IN  NDIS_HANDLE             ProtocolBindingContext,\r
323     IN  NDIS_STATUS             Status,\r
324     IN  NDIS_STATUS             OpenErrorStatus\r
325     )\r
326 /*++\r
327 \r
328 Routine Description:\r
329 \r
330     Completion routine for NdisOpenAdapter issued from within the PtBindAdapter. Simply\r
331     unblock the caller.\r
332 \r
333 Arguments:\r
334 \r
335     ProtocolBindingContext    Pointer to the adapter\r
336     Status                    Status of the NdisOpenAdapter call\r
337     OpenErrorStatus            Secondary status(ignored by us).\r
338 \r
339 Return Value:\r
340 \r
341     None\r
342 \r
343 --*/\r
344 {\r
345     PADAPT      pAdapt =(PADAPT)ProtocolBindingContext;\r
346     \r
347     UNREFERENCED_PARAMETER(OpenErrorStatus);\r
348     \r
349     DBGPRINT(("==> PtOpenAdapterComplete: Adapt %p, Status %x\n", pAdapt, Status));\r
350     pAdapt->Status = Status;\r
351     NdisSetEvent(&pAdapt->Event);\r
352 }\r
353 \r
354 \r
355 VOID\r
356 PtUnbindAdapter(\r
357     OUT PNDIS_STATUS           Status,\r
358     IN  NDIS_HANDLE            ProtocolBindingContext,\r
359     IN  NDIS_HANDLE            UnbindContext\r
360     )\r
361 /*++\r
362 \r
363 Routine Description:\r
364 \r
365     Called by NDIS when we are required to unbind to the adapter below.\r
366     This functions shares functionality with the miniport's HaltHandler.\r
367     The code should ensure that NdisCloseAdapter and NdisFreeMemory is called\r
368     only once between the two functions\r
369 \r
370 Arguments:\r
371 \r
372     Status                    Placeholder for return status\r
373     ProtocolBindingContext    Pointer to the adapter structure\r
374     UnbindContext            Context for NdisUnbindComplete() if this pends\r
375 \r
376 Return Value:\r
377 \r
378     Status for NdisIMDeinitializeDeviceContext\r
379 \r
380 --*/\r
381 {\r
382     PADAPT         pAdapt =(PADAPT)ProtocolBindingContext;\r
383     NDIS_STATUS    LocalStatus;\r
384 \r
385     UNREFERENCED_PARAMETER(UnbindContext);\r
386     \r
387     DBGPRINT(("==> PtUnbindAdapter: Adapt %p\n", pAdapt));\r
388 \r
389     //\r
390     // Set the flag that the miniport below is unbinding, so the request handlers will\r
391     // fail any request comming later\r
392     // \r
393     NdisAcquireSpinLock(&pAdapt->Lock);\r
394     pAdapt->UnbindingInProcess = TRUE;\r
395     if (pAdapt->QueuedRequest == TRUE)\r
396     {\r
397         pAdapt->QueuedRequest = FALSE;\r
398         NdisReleaseSpinLock(&pAdapt->Lock);\r
399 \r
400         PtRequestComplete(pAdapt,\r
401                          &pAdapt->Request,\r
402                          NDIS_STATUS_FAILURE );\r
403 \r
404     }\r
405     else\r
406     {\r
407         NdisReleaseSpinLock(&pAdapt->Lock);\r
408     }\r
409 #ifndef WIN9X\r
410     //\r
411     // Check if we had called NdisIMInitializeDeviceInstanceEx and\r
412     // we are awaiting a call to MiniportInitialize.\r
413     //\r
414     if (pAdapt->MiniportInitPending == TRUE)\r
415     {\r
416         //\r
417         // Try to cancel the pending IMInit process.\r
418         //\r
419         LocalStatus = NdisIMCancelInitializeDeviceInstance(\r
420                         DriverHandle,\r
421                         &pAdapt->DeviceName);\r
422 \r
423         if (LocalStatus == NDIS_STATUS_SUCCESS)\r
424         {\r
425             //\r
426             // Successfully cancelled IM Initialization; our\r
427             // Miniport Initialize routine will not be called\r
428             // for this device.\r
429             //\r
430             pAdapt->MiniportInitPending = FALSE;\r
431             ASSERT(pAdapt->MiniportHandle == NULL);\r
432         }\r
433         else\r
434         {\r
435             //\r
436             // Our Miniport Initialize routine will be called\r
437             // (may be running on another thread at this time).\r
438             // Wait for it to finish.\r
439             //\r
440             NdisWaitEvent(&pAdapt->MiniportInitEvent, 0);\r
441             ASSERT(pAdapt->MiniportInitPending == FALSE);\r
442         }\r
443 \r
444     }\r
445 #endif // !WIN9X\r
446 \r
447     //\r
448     // Call NDIS to remove our device-instance. We do most of the work\r
449     // inside the HaltHandler.\r
450     //\r
451     // The Handle will be NULL if our miniport Halt Handler has been called or\r
452     // if the IM device was never initialized\r
453     //\r
454     \r
455     if (pAdapt->MiniportHandle != NULL)\r
456     {\r
457         *Status = NdisIMDeInitializeDeviceInstance(pAdapt->MiniportHandle);\r
458 \r
459         if (*Status != NDIS_STATUS_SUCCESS)\r
460         {\r
461             *Status = NDIS_STATUS_FAILURE;\r
462         }\r
463     }\r
464     else\r
465     {\r
466         //\r
467         // We need to do some work here. \r
468         // Close the binding below us \r
469         // and release the memory allocated.\r
470         //\r
471         \r
472         if(pAdapt->BindingHandle != NULL)\r
473         {\r
474             NdisResetEvent(&pAdapt->Event);\r
475 \r
476             NdisCloseAdapter(Status, pAdapt->BindingHandle);\r
477 \r
478             //\r
479             // Wait for it to complete\r
480             //\r
481             if(*Status == NDIS_STATUS_PENDING)\r
482             {\r
483                  NdisWaitEvent(&pAdapt->Event, 0);\r
484                  *Status = pAdapt->Status;\r
485             }\r
486             pAdapt->BindingHandle = NULL;\r
487         }\r
488         else\r
489         {\r
490             //\r
491             // Both Our MiniportHandle and Binding Handle  should not be NULL.\r
492             //\r
493             *Status = NDIS_STATUS_FAILURE;\r
494             ASSERT(0);\r
495         }\r
496 \r
497         //\r
498         //    Free the memory here, if was not released earlier(by calling the HaltHandler)\r
499         //\r
500         MPFreeAllPacketPools(pAdapt);\r
501         NdisFreeSpinLock(&pAdapt->Lock);\r
502         NdisFreeMemory(pAdapt, 0, 0);\r
503     }\r
504 \r
505     DBGPRINT(("<== PtUnbindAdapter: Adapt %p\n", pAdapt));\r
506 }\r
507 \r
508 VOID\r
509 PtUnloadProtocol(\r
510     VOID\r
511 )\r
512 {\r
513     NDIS_STATUS Status;\r
514 \r
515     if (ProtHandle != NULL)\r
516     {\r
517         NdisDeregisterProtocol(&Status, ProtHandle);\r
518         ProtHandle = NULL;\r
519     }\r
520 \r
521     DBGPRINT(("PtUnloadProtocol: done!\n"));\r
522 }\r
523 \r
524 \r
525 \r
526 VOID\r
527 PtCloseAdapterComplete(\r
528     IN    NDIS_HANDLE            ProtocolBindingContext,\r
529     IN    NDIS_STATUS            Status\r
530     )\r
531 /*++\r
532 \r
533 Routine Description:\r
534 \r
535     Completion for the CloseAdapter call.\r
536 \r
537 Arguments:\r
538 \r
539     ProtocolBindingContext    Pointer to the adapter structure\r
540     Status                    Completion status\r
541 \r
542 Return Value:\r
543 \r
544     None.\r
545 \r
546 --*/\r
547 {\r
548     PADAPT      pAdapt =(PADAPT)ProtocolBindingContext;\r
549 \r
550     DBGPRINT(("CloseAdapterComplete: Adapt %p, Status %x\n", pAdapt, Status));\r
551     pAdapt->Status = Status;\r
552     NdisSetEvent(&pAdapt->Event);\r
553 }\r
554 \r
555 \r
556 VOID\r
557 PtResetComplete(\r
558     IN  NDIS_HANDLE            ProtocolBindingContext,\r
559     IN  NDIS_STATUS            Status\r
560     )\r
561 /*++\r
562 \r
563 Routine Description:\r
564 \r
565     Completion for the reset.\r
566 \r
567 Arguments:\r
568 \r
569     ProtocolBindingContext    Pointer to the adapter structure\r
570     Status                    Completion status\r
571 \r
572 Return Value:\r
573 \r
574     None.\r
575 \r
576 --*/\r
577 {\r
578 \r
579     UNREFERENCED_PARAMETER(ProtocolBindingContext);\r
580     UNREFERENCED_PARAMETER(Status);\r
581     //\r
582     // We never issue a reset, so we should not be here.\r
583     //\r
584     ASSERT(0);\r
585 }\r
586 \r
587 \r
588 VOID\r
589 PtRequestComplete(\r
590     IN  NDIS_HANDLE            ProtocolBindingContext,\r
591     IN  PNDIS_REQUEST          NdisRequest,\r
592     IN  NDIS_STATUS            Status\r
593     )\r
594 /*++\r
595 \r
596 Routine Description:\r
597 \r
598     Completion handler for the previously posted request. All OIDS\r
599     are completed by and sent to the same miniport that they were requested for.\r
600     If Oid == OID_PNP_QUERY_POWER then the data structure needs to returned with all entries =\r
601     NdisDeviceStateUnspecified\r
602 \r
603 Arguments:\r
604 \r
605     ProtocolBindingContext    Pointer to the adapter structure\r
606     NdisRequest                The posted request\r
607     Status                    Completion status\r
608 \r
609 Return Value:\r
610 \r
611     None\r
612 \r
613 --*/\r
614 {\r
615     PADAPT        pAdapt = (PADAPT)ProtocolBindingContext;\r
616     NDIS_OID      Oid = pAdapt->Request.DATA.SET_INFORMATION.Oid ;\r
617 \r
618     //\r
619     // Since our request is not outstanding anymore\r
620     //\r
621     ASSERT(pAdapt->OutstandingRequests == TRUE);\r
622 \r
623     pAdapt->OutstandingRequests = FALSE;\r
624 \r
625     //\r
626     // Complete the Set or Query, and fill in the buffer for OID_PNP_CAPABILITIES, if need be.\r
627     //\r
628     switch (NdisRequest->RequestType)\r
629     {\r
630       case NdisRequestQueryInformation:\r
631 \r
632         //\r
633         // We never pass OID_PNP_QUERY_POWER down.\r
634         //\r
635         ASSERT(Oid != OID_PNP_QUERY_POWER);\r
636 \r
637         if ((Oid == OID_PNP_CAPABILITIES) && (Status == NDIS_STATUS_SUCCESS))\r
638         {\r
639             MPQueryPNPCapabilities(pAdapt, &Status);\r
640         }\r
641         *pAdapt->BytesReadOrWritten = NdisRequest->DATA.QUERY_INFORMATION.BytesWritten;\r
642         *pAdapt->BytesNeeded = NdisRequest->DATA.QUERY_INFORMATION.BytesNeeded;\r
643 \r
644         if (((Oid == OID_GEN_MAC_OPTIONS) \r
645               && (Status == NDIS_STATUS_SUCCESS))\r
646               && (NdisDotSysVersion >= NDIS_SYS_VERSION_51))\r
647         {\r
648             //\r
649             // Only do this on Windows XP or greater (NDIS.SYS v 5.1); \r
650             // do not do in Windows 2000 (NDIS.SYS v 5.0))\r
651             //\r
652                 \r
653             //\r
654             // Remove the no-loopback bit from mac-options. In essence we are\r
655             // telling NDIS that we can handle loopback. We don't, but the\r
656             // interface below us does. If we do not do this, then loopback\r
657             // processing happens both below us and above us. This is wasteful\r
658             // at best and if Netmon is running, it will see multiple copies\r
659             // of loopback packets when sniffing above us.\r
660             //\r
661             // Only the lowest miniport is a stack of layered miniports should\r
662             // ever report this bit set to NDIS.\r
663             //\r
664             *(PULONG)NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer &= ~NDIS_MAC_OPTION_NO_LOOPBACK;\r
665         }\r
666 \r
667         NdisMQueryInformationComplete(pAdapt->MiniportHandle,\r
668                                       Status);\r
669         break;\r
670 \r
671       case NdisRequestSetInformation:\r
672 \r
673         ASSERT( Oid != OID_PNP_SET_POWER);\r
674 \r
675         *pAdapt->BytesReadOrWritten = NdisRequest->DATA.SET_INFORMATION.BytesRead;\r
676         *pAdapt->BytesNeeded = NdisRequest->DATA.SET_INFORMATION.BytesNeeded;\r
677         NdisMSetInformationComplete(pAdapt->MiniportHandle,\r
678                                     Status);\r
679         break;\r
680 \r
681       default:\r
682         ASSERT(0);\r
683         break;\r
684     }\r
685     \r
686 }\r
687 \r
688 \r
689 VOID\r
690 PtStatus(\r
691     IN  NDIS_HANDLE         ProtocolBindingContext,\r
692     IN  NDIS_STATUS         GeneralStatus,\r
693     IN  PVOID               StatusBuffer,\r
694     IN  UINT                StatusBufferSize\r
695     )\r
696 /*++\r
697 \r
698 Routine Description:\r
699 \r
700     Status handler for the lower-edge(protocol).\r
701 \r
702 Arguments:\r
703 \r
704     ProtocolBindingContext    Pointer to the adapter structure\r
705     GeneralStatus             Status code\r
706     StatusBuffer              Status buffer\r
707     StatusBufferSize          Size of the status buffer\r
708 \r
709 Return Value:\r
710 \r
711     None\r
712 \r
713 --*/\r
714 {\r
715     PADAPT      pAdapt = (PADAPT)ProtocolBindingContext;\r
716 \r
717     //\r
718     // Pass up this indication only if the upper edge miniport is initialized\r
719     // and powered on. Also ignore indications that might be sent by the lower\r
720     // miniport when it isn't at D0.\r
721     //\r
722     if ((pAdapt->MiniportHandle != NULL)  &&\r
723         (pAdapt->MPDeviceState == NdisDeviceStateD0) &&\r
724         (pAdapt->PTDeviceState == NdisDeviceStateD0))    \r
725     {\r
726         if ((GeneralStatus == NDIS_STATUS_MEDIA_CONNECT) || \r
727             (GeneralStatus == NDIS_STATUS_MEDIA_DISCONNECT))\r
728         {\r
729             \r
730             pAdapt->LastIndicatedStatus = GeneralStatus;\r
731         }\r
732         NdisMIndicateStatus(pAdapt->MiniportHandle,\r
733                             GeneralStatus,\r
734                             StatusBuffer,\r
735                             StatusBufferSize);\r
736     }\r
737     //\r
738     // Save the last indicated media status \r
739     //\r
740     else\r
741     {\r
742         if ((pAdapt->MiniportHandle != NULL) && \r
743         ((GeneralStatus == NDIS_STATUS_MEDIA_CONNECT) || \r
744             (GeneralStatus == NDIS_STATUS_MEDIA_DISCONNECT)))\r
745         {\r
746             pAdapt->LatestUnIndicateStatus = GeneralStatus;\r
747         }\r
748     }\r
749     \r
750 }\r
751 \r
752 \r
753 VOID\r
754 PtStatusComplete(\r
755     IN NDIS_HANDLE            ProtocolBindingContext\r
756     )\r
757 /*++\r
758 \r
759 Routine Description:\r
760 \r
761 \r
762 Arguments:\r
763 \r
764 \r
765 Return Value:\r
766 \r
767 \r
768 --*/\r
769 {\r
770     PADAPT      pAdapt = (PADAPT)ProtocolBindingContext;\r
771 \r
772     //\r
773     // Pass up this indication only if the upper edge miniport is initialized\r
774     // and powered on. Also ignore indications that might be sent by the lower\r
775     // miniport when it isn't at D0.\r
776     //\r
777     if ((pAdapt->MiniportHandle != NULL)  &&\r
778         (pAdapt->MPDeviceState == NdisDeviceStateD0) &&\r
779         (pAdapt->PTDeviceState == NdisDeviceStateD0))    \r
780     {\r
781         NdisMIndicateStatusComplete(pAdapt->MiniportHandle);\r
782     }\r
783 }\r
784 \r
785 \r
786 VOID\r
787 PtSendComplete(\r
788     IN  NDIS_HANDLE            ProtocolBindingContext,\r
789     IN  PNDIS_PACKET           Packet,\r
790     IN  NDIS_STATUS            Status\r
791     )\r
792 /*++\r
793 \r
794 Routine Description:\r
795 \r
796     Called by NDIS when the miniport below had completed a send. We should\r
797     complete the corresponding upper-edge send this represents.\r
798 \r
799 Arguments:\r
800 \r
801     ProtocolBindingContext - Points to ADAPT structure\r
802     Packet - Low level packet being completed\r
803     Status - status of send\r
804 \r
805 Return Value:\r
806 \r
807     None\r
808 \r
809 --*/\r
810 {\r
811     PADAPT            pAdapt = (PADAPT)ProtocolBindingContext;\r
812     PNDIS_PACKET      Pkt; \r
813     NDIS_HANDLE       PoolHandle;\r
814 \r
815 #ifdef NDIS51\r
816     //\r
817     // Packet stacking:\r
818     //\r
819     // Determine if the packet we are completing is the one we allocated. If so, then\r
820     // get the original packet from the reserved area and completed it and free the\r
821     // allocated packet. If this is the packet that was sent down to us, then just\r
822     // complete it\r
823     //\r
824     PoolHandle = NdisGetPoolFromPacket(Packet);\r
825     if (PoolHandle != pAdapt->SendPacketPoolHandle)\r
826     {\r
827         //\r
828         // We had passed down a packet belonging to the protocol above us.\r
829         //\r
830         // DBGPRINT(("PtSendComp: Adapt %p, Stacked Packet %p\n", pAdapt, Packet));\r
831 \r
832         NdisMSendComplete(pAdapt->MiniportHandle,\r
833                           Packet,\r
834                           Status);\r
835     }\r
836     else\r
837 #endif // NDIS51\r
838     {\r
839         PSEND_RSVD        SendRsvd;\r
840 \r
841         SendRsvd = (PSEND_RSVD)(Packet->ProtocolReserved);\r
842         Pkt = SendRsvd->OriginalPkt;\r
843     \r
844 #ifndef WIN9X\r
845         NdisIMCopySendCompletePerPacketInfo (Pkt, Packet);\r
846 #endif\r
847     \r
848         NdisDprFreePacket(Packet);\r
849 \r
850         NdisMSendComplete(pAdapt->MiniportHandle,\r
851                                  Pkt,\r
852                                  Status);\r
853     }\r
854     //\r
855     // Decrease the outstanding send count\r
856     //\r
857     ADAPT_DECR_PENDING_SENDS(pAdapt);\r
858 }       \r
859 \r
860 \r
861 VOID\r
862 PtTransferDataComplete(\r
863     IN  NDIS_HANDLE         ProtocolBindingContext,\r
864     IN  PNDIS_PACKET        Packet,\r
865     IN  NDIS_STATUS         Status,\r
866     IN  UINT                BytesTransferred\r
867     )\r
868 /*++\r
869 \r
870 Routine Description:\r
871 \r
872     Entry point called by NDIS to indicate completion of a call by us\r
873     to NdisTransferData.\r
874 \r
875     See notes under SendComplete.\r
876 \r
877 Arguments:\r
878 \r
879 Return Value:\r
880 \r
881 --*/\r
882 {\r
883     PADAPT      pAdapt =(PADAPT)ProtocolBindingContext;\r
884 \r
885     if(pAdapt->MiniportHandle)\r
886     {\r
887         NdisMTransferDataComplete(pAdapt->MiniportHandle,\r
888                                   Packet,\r
889                                   Status,\r
890                                   BytesTransferred);\r
891     }\r
892 }\r
893 \r
894 \r
895 NDIS_STATUS\r
896 PtReceive(\r
897     IN  NDIS_HANDLE         ProtocolBindingContext,\r
898     IN  NDIS_HANDLE         MacReceiveContext,\r
899     IN  PVOID               HeaderBuffer,\r
900     IN  UINT                HeaderBufferSize,\r
901     IN  PVOID               LookAheadBuffer,\r
902     IN  UINT                LookAheadBufferSize,\r
903     IN  UINT                PacketSize\r
904     )\r
905 /*++\r
906 \r
907 Routine Description:\r
908 \r
909     Handle receive data indicated up by the miniport below. We pass\r
910     it along to the protocol above us.\r
911 \r
912     If the miniport below indicates packets, NDIS would more\r
913     likely call us at our ReceivePacket handler. However we\r
914     might be called here in certain situations even though\r
915     the miniport below has indicated a receive packet, e.g.\r
916     if the miniport had set packet status to NDIS_STATUS_RESOURCES.\r
917         \r
918 Arguments:\r
919 \r
920     <see DDK ref page for ProtocolReceive>\r
921 \r
922 Return Value:\r
923 \r
924     NDIS_STATUS_SUCCESS if we processed the receive successfully,\r
925     NDIS_STATUS_XXX error code if we discarded it.\r
926 \r
927 --*/\r
928 {\r
929     PADAPT            pAdapt = (PADAPT)ProtocolBindingContext;\r
930     PNDIS_PACKET      MyPacket, Packet = NULL;\r
931     NDIS_STATUS       Status = NDIS_STATUS_SUCCESS;\r
932     ULONG             Proc = KeGetCurrentProcessorNumber();      \r
933     \r
934     if ((!pAdapt->MiniportHandle) || (pAdapt->MPDeviceState > NdisDeviceStateD0))\r
935     {\r
936         Status = NDIS_STATUS_FAILURE;\r
937     }\r
938     else do\r
939     {\r
940         //\r
941         // Get at the packet, if any, indicated up by the miniport below.\r
942         //\r
943         Packet = NdisGetReceivedPacket(pAdapt->BindingHandle, MacReceiveContext);\r
944         if (Packet != NULL)\r
945         {\r
946             //\r
947             // The miniport below did indicate up a packet. Use information\r
948             // from that packet to construct a new packet to indicate up.\r
949             //\r
950 \r
951 #ifdef NDIS51\r
952             //\r
953             // NDIS 5.1 NOTE: Do not reuse the original packet in indicating\r
954             // up a receive, even if there is sufficient packet stack space.\r
955             // If we had to do so, we would have had to overwrite the\r
956             // status field in the original packet to NDIS_STATUS_RESOURCES,\r
957             // and it is not allowed for protocols to overwrite this field\r
958             // in received packets.\r
959             //\r
960 #endif // NDIS51\r
961 \r
962             //\r
963             // Get a packet off the pool and indicate that up\r
964             //\r
965             NdisDprAllocatePacket(&Status,\r
966                                 &MyPacket,\r
967                                 pAdapt->RecvPacketPoolHandle);\r
968 \r
969             if (Status == NDIS_STATUS_SUCCESS)\r
970             {\r
971                 //\r
972                 // Make our packet point to data from the original\r
973                 // packet. NOTE: this works only because we are\r
974                 // indicating a receive directly from the context of\r
975                 // our receive indication. If we need to queue this\r
976                 // packet and indicate it from another thread context,\r
977                 // we will also have to allocate a new buffer and copy\r
978                 // over the packet contents, OOB data and per-packet\r
979                 // information. This is because the packet data\r
980                 // is available only for the duration of this\r
981                 // receive indication call.\r
982                 //\r
983                 NDIS_PACKET_FIRST_NDIS_BUFFER(MyPacket) = NDIS_PACKET_FIRST_NDIS_BUFFER(Packet);\r
984                 NDIS_PACKET_LAST_NDIS_BUFFER(MyPacket) = NDIS_PACKET_LAST_NDIS_BUFFER(Packet);\r
985 \r
986                 //\r
987                 // Get the original packet (it could be the same packet as the\r
988                 // one received or a different one based on the number of layered\r
989                 // miniports below) and set it on the indicated packet so the OOB\r
990                 // data is visible correctly at protocols above.  If the IM driver \r
991                 // modifies the packet in any way it should not set the new packet's\r
992                 // original packet equal to the original packet of the packet that \r
993                 // was indicated to it from the underlying driver, in this case, the \r
994                 // IM driver should also ensure that the related per packet info should\r
995                 // be copied to the new packet.\r
996                 // we can set the original packet to the original packet of the packet\r
997                 // indicated from the underlying driver because the driver doesn't modify\r
998                 // the data content in the packet.\r
999                 //\r
1000                 NDIS_SET_ORIGINAL_PACKET(MyPacket, NDIS_GET_ORIGINAL_PACKET(Packet));\r
1001                 NDIS_SET_PACKET_HEADER_SIZE(MyPacket, HeaderBufferSize);\r
1002 \r
1003                 //\r
1004                 // Copy packet flags.\r
1005                 //\r
1006                 NdisGetPacketFlags(MyPacket) = NdisGetPacketFlags(Packet);\r
1007 \r
1008                 //\r
1009                 // Force protocols above to make a copy if they want to hang\r
1010                 // on to data in this packet. This is because we are in our\r
1011                 // Receive handler (not ReceivePacket) and we can't return a\r
1012                 // ref count from here.\r
1013                 //\r
1014                 NDIS_SET_PACKET_STATUS(MyPacket, NDIS_STATUS_RESOURCES);\r
1015 \r
1016                 //\r
1017                 // By setting NDIS_STATUS_RESOURCES, we also know that we can reclaim\r
1018                 // this packet as soon as the call to NdisMIndicateReceivePacket\r
1019                 // returns.\r
1020                 //\r
1021 \r
1022                 if (pAdapt->MiniportHandle != NULL)\r
1023                 {\r
1024                     NdisMIndicateReceivePacket(pAdapt->MiniportHandle, &MyPacket, 1);\r
1025                 }\r
1026 \r
1027                 //\r
1028                 // Reclaim the indicated packet. Since we had set its status\r
1029                 // to NDIS_STATUS_RESOURCES, we are guaranteed that protocols\r
1030                 // above are done with it.\r
1031                 //\r
1032                 NdisDprFreePacket(MyPacket);\r
1033 \r
1034                 break;\r
1035             }\r
1036         }\r
1037         else\r
1038         {\r
1039             //\r
1040             // The miniport below us uses the old-style (not packet)\r
1041             // receive indication. Fall through.\r
1042             //\r
1043         }\r
1044 \r
1045         //\r
1046         // Fall through if the miniport below us has either not\r
1047         // indicated a packet or we could not allocate one\r
1048         //\r
1049         pAdapt->ReceivedIndicationFlags[Proc] = TRUE;\r
1050         if (pAdapt->MiniportHandle == NULL)\r
1051         {\r
1052             break;\r
1053         }\r
1054         switch (pAdapt->Medium)\r
1055         {\r
1056             case NdisMedium802_3:\r
1057             case NdisMediumWan:\r
1058                 NdisMEthIndicateReceive(pAdapt->MiniportHandle,\r
1059                                              MacReceiveContext,\r
1060                                              HeaderBuffer,\r
1061                                              HeaderBufferSize,\r
1062                                              LookAheadBuffer,\r
1063                                              LookAheadBufferSize,\r
1064                                              PacketSize);\r
1065                 break;\r
1066 \r
1067             case NdisMedium802_5:\r
1068                 NdisMTrIndicateReceive(pAdapt->MiniportHandle,\r
1069                                             MacReceiveContext,\r
1070                                             HeaderBuffer,\r
1071                                             HeaderBufferSize,\r
1072                                             LookAheadBuffer,\r
1073                                             LookAheadBufferSize,\r
1074                                             PacketSize);\r
1075                 break;\r
1076 \r
1077 #if FDDI\r
1078                   case NdisMediumFddi:\r
1079                          NdisMFddiIndicateReceive(pAdapt->MiniportHandle,\r
1080                                                                                           MacReceiveContext,\r
1081                                                                                           HeaderBuffer,\r
1082                                                                                           HeaderBufferSize,\r
1083                                                                                           LookAheadBuffer,\r
1084                                                                                           LookAheadBufferSize,\r
1085                                                                                           PacketSize);\r
1086                          break;\r
1087 #endif\r
1088                   default:\r
1089                          ASSERT(FALSE);\r
1090                          break;\r
1091                 }\r
1092 \r
1093     } while(FALSE);\r
1094 \r
1095     return Status;\r
1096 }\r
1097 \r
1098 \r
1099 VOID\r
1100 PtReceiveComplete(\r
1101     IN NDIS_HANDLE        ProtocolBindingContext\r
1102     )\r
1103 /*++\r
1104 \r
1105 Routine Description:\r
1106 \r
1107     Called by the adapter below us when it is done indicating a batch of\r
1108     received packets.\r
1109 \r
1110 Arguments:\r
1111 \r
1112     ProtocolBindingContext    Pointer to our adapter structure.\r
1113 \r
1114 Return Value:\r
1115 \r
1116     None\r
1117 \r
1118 --*/\r
1119 {\r
1120     PADAPT        pAdapt =(PADAPT)ProtocolBindingContext;\r
1121     ULONG         Proc = KeGetCurrentProcessorNumber();      \r
1122 \r
1123     if (((pAdapt->MiniportHandle != NULL)\r
1124                 && (pAdapt->MPDeviceState == NdisDeviceStateD0))\r
1125                 && (pAdapt->ReceivedIndicationFlags[Proc]))\r
1126     {\r
1127         switch (pAdapt->Medium)\r
1128         {\r
1129             case NdisMedium802_3:\r
1130             case NdisMediumWan:\r
1131                 NdisMEthIndicateReceiveComplete(pAdapt->MiniportHandle);\r
1132                 break;\r
1133 \r
1134                   case NdisMedium802_5:\r
1135                         NdisMTrIndicateReceiveComplete(pAdapt->MiniportHandle);\r
1136                         break;\r
1137 #if FDDI\r
1138                   case NdisMediumFddi:\r
1139                         NdisMFddiIndicateReceiveComplete(pAdapt->MiniportHandle);\r
1140                         break;\r
1141 #endif\r
1142                   default:\r
1143                         ASSERT(FALSE);\r
1144                         break;\r
1145                 }\r
1146         }\r
1147 \r
1148     pAdapt->ReceivedIndicationFlags[Proc] = FALSE;\r
1149 }\r
1150 \r
1151 \r
1152 INT\r
1153 PtReceivePacket(\r
1154     IN NDIS_HANDLE            ProtocolBindingContext,\r
1155     IN PNDIS_PACKET           Packet\r
1156     )\r
1157 /*++\r
1158 \r
1159 Routine Description:\r
1160 \r
1161     ReceivePacket handler. Called by NDIS if the miniport below supports\r
1162     NDIS 4.0 style receives. Re-package the buffer chain in a new packet\r
1163     and indicate the new packet to protocols above us. Any context for\r
1164     packets indicated up must be kept in the MiniportReserved field.\r
1165 \r
1166     NDIS 5.1 - packet stacking - if there is sufficient "stack space" in\r
1167     the packet passed to us, we can use the same packet in a receive\r
1168     indication.\r
1169 \r
1170 Arguments:\r
1171 \r
1172     ProtocolBindingContext - Pointer to our adapter structure.\r
1173     Packet - Pointer to the packet\r
1174 \r
1175 Return Value:\r
1176 \r
1177     == 0 -> We are done with the packet\r
1178     != 0 -> We will keep the packet and call NdisReturnPackets() this\r
1179             many times when done.\r
1180 --*/\r
1181 {\r
1182     PADAPT              pAdapt =(PADAPT)ProtocolBindingContext;\r
1183     NDIS_STATUS         Status;\r
1184     PNDIS_PACKET        MyPacket;\r
1185     BOOLEAN             Remaining;\r
1186 \r
1187     //\r
1188     // Drop the packet silently if the upper miniport edge isn't initialized or\r
1189     // the miniport edge is in low power state\r
1190     //\r
1191     if ((!pAdapt->MiniportHandle) || (pAdapt->MPDeviceState > NdisDeviceStateD0))\r
1192     {\r
1193           return 0;\r
1194     }\r
1195 \r
1196 #ifdef NDIS51\r
1197     //\r
1198     // Check if we can reuse the same packet for indicating up.\r
1199     // See also: PtReceive(). \r
1200     //\r
1201     (VOID)NdisIMGetCurrentPacketStack(Packet, &Remaining);\r
1202     if (Remaining)\r
1203     {\r
1204         //\r
1205         // We can reuse "Packet". Indicate it up and be done with it.\r
1206         //\r
1207         Status = NDIS_GET_PACKET_STATUS(Packet);\r
1208         NdisMIndicateReceivePacket(pAdapt->MiniportHandle, &Packet, 1);\r
1209         return((Status != NDIS_STATUS_RESOURCES) ? 1 : 0);\r
1210     }\r
1211 #endif // NDIS51\r
1212 \r
1213     //\r
1214     // Get a packet off the pool and indicate that up\r
1215     //\r
1216     NdisDprAllocatePacket(&Status,\r
1217                            &MyPacket,\r
1218                            pAdapt->RecvPacketPoolHandle);\r
1219 \r
1220     if (Status == NDIS_STATUS_SUCCESS)\r
1221     {\r
1222         PRECV_RSVD            RecvRsvd;\r
1223 \r
1224         RecvRsvd = (PRECV_RSVD)(MyPacket->MiniportReserved);\r
1225         RecvRsvd->OriginalPkt = Packet;\r
1226 \r
1227         NDIS_PACKET_FIRST_NDIS_BUFFER(MyPacket) = NDIS_PACKET_FIRST_NDIS_BUFFER(Packet);\r
1228         NDIS_PACKET_LAST_NDIS_BUFFER(MyPacket) = NDIS_PACKET_LAST_NDIS_BUFFER(Packet);\r
1229 \r
1230         //\r
1231         // Get the original packet (it could be the same packet as the one\r
1232         // received or a different one based on the number of layered miniports\r
1233         // below) and set it on the indicated packet so the OOB data is visible\r
1234         // correctly to protocols above us.\r
1235         //\r
1236         NDIS_SET_ORIGINAL_PACKET(MyPacket, NDIS_GET_ORIGINAL_PACKET(Packet));\r
1237 \r
1238         //\r
1239         // Set Packet Flags\r
1240         //\r
1241         NdisGetPacketFlags(MyPacket) = NdisGetPacketFlags(Packet);\r
1242 \r
1243         Status = NDIS_GET_PACKET_STATUS(Packet);\r
1244 \r
1245         NDIS_SET_PACKET_STATUS(MyPacket, Status);\r
1246         NDIS_SET_PACKET_HEADER_SIZE(MyPacket, NDIS_GET_PACKET_HEADER_SIZE(Packet));\r
1247 \r
1248         if (pAdapt->MiniportHandle != NULL)\r
1249         {\r
1250             NdisMIndicateReceivePacket(pAdapt->MiniportHandle, &MyPacket, 1);\r
1251         }\r
1252 \r
1253         //\r
1254         // Check if we had indicated up the packet with NDIS_STATUS_RESOURCES\r
1255         // NOTE -- do not use NDIS_GET_PACKET_STATUS(MyPacket) for this since\r
1256         // it might have changed! Use the value saved in the local variable.\r
1257         //\r
1258         if (Status == NDIS_STATUS_RESOURCES)\r
1259         {\r
1260             //\r
1261             // Our ReturnPackets handler will not be called for this packet.\r
1262             // We should reclaim it right here.\r
1263             //\r
1264             NdisDprFreePacket(MyPacket);\r
1265         }\r
1266 \r
1267         return((Status != NDIS_STATUS_RESOURCES) ? 1 : 0);\r
1268     }\r
1269     else\r
1270     {\r
1271         //\r
1272         // We are out of packets. Silently drop it.\r
1273         //\r
1274         return(0);\r
1275     }\r
1276 }\r
1277 \r
1278 \r
1279 NDIS_STATUS\r
1280 PtPNPHandler(\r
1281     IN NDIS_HANDLE        ProtocolBindingContext,\r
1282     IN PNET_PNP_EVENT     pNetPnPEvent\r
1283     )\r
1284 \r
1285 /*++\r
1286 Routine Description:\r
1287 \r
1288     This is called by NDIS to notify us of a PNP event related to a lower\r
1289     binding. Based on the event, this dispatches to other helper routines.\r
1290 \r
1291     NDIS 5.1: forward this event to the upper protocol(s) by calling\r
1292     NdisIMNotifyPnPEvent.\r
1293 \r
1294 Arguments:\r
1295 \r
1296     ProtocolBindingContext - Pointer to our adapter structure. Can be NULL\r
1297                 for "global" notifications\r
1298 \r
1299     pNetPnPEvent - Pointer to the PNP event to be processed.\r
1300 \r
1301 Return Value:\r
1302 \r
1303     NDIS_STATUS code indicating status of event processing.\r
1304 \r
1305 --*/\r
1306 {\r
1307     PADAPT            pAdapt  =(PADAPT)ProtocolBindingContext;\r
1308     NDIS_STATUS       Status  = NDIS_STATUS_SUCCESS;\r
1309 \r
1310     DBGPRINT(("PtPnPHandler: Adapt %p, Event %d\n", pAdapt, pNetPnPEvent->NetEvent));\r
1311 \r
1312     switch (pNetPnPEvent->NetEvent)\r
1313     {\r
1314         case NetEventSetPower:\r
1315             Status = PtPnPNetEventSetPower(pAdapt, pNetPnPEvent);\r
1316             break;\r
1317 \r
1318          case NetEventReconfigure:\r
1319             Status = PtPnPNetEventReconfigure(pAdapt, pNetPnPEvent);\r
1320             break;\r
1321 \r
1322          default:\r
1323 #ifdef NDIS51\r
1324             //\r
1325             // Pass on this notification to protocol(s) above, before\r
1326             // doing anything else with it.\r
1327             //\r
1328             if (pAdapt && pAdapt->MiniportHandle)\r
1329             {\r
1330                 Status = NdisIMNotifyPnPEvent(pAdapt->MiniportHandle, pNetPnPEvent);\r
1331             }\r
1332 #else\r
1333             Status = NDIS_STATUS_SUCCESS;\r
1334 \r
1335 #endif // NDIS51\r
1336 \r
1337             break;\r
1338     }\r
1339 \r
1340     return Status;\r
1341 }\r
1342 \r
1343 \r
1344 NDIS_STATUS\r
1345 PtPnPNetEventReconfigure(\r
1346     IN PADAPT            pAdapt,\r
1347     IN PNET_PNP_EVENT    pNetPnPEvent\r
1348     )\r
1349 /*++\r
1350 Routine Description:\r
1351 \r
1352     This routine is called from NDIS to notify our protocol edge of a\r
1353     reconfiguration of parameters for either a specific binding (pAdapt\r
1354     is not NULL), or global parameters if any (pAdapt is NULL).\r
1355 \r
1356 Arguments:\r
1357 \r
1358     pAdapt - Pointer to our adapter structure.\r
1359     pNetPnPEvent - the reconfigure event\r
1360 \r
1361 Return Value:\r
1362 \r
1363     NDIS_STATUS_SUCCESS\r
1364 \r
1365 --*/\r
1366 {\r
1367     NDIS_STATUS    ReconfigStatus = NDIS_STATUS_SUCCESS;\r
1368     NDIS_STATUS    ReturnStatus = NDIS_STATUS_SUCCESS;\r
1369 \r
1370     do\r
1371     {\r
1372         //\r
1373         // Is this is a global reconfiguration notification ?\r
1374         //\r
1375         if (pAdapt == NULL)\r
1376         {\r
1377             //\r
1378             // An important event that causes this notification to us is if\r
1379             // one of our upper-edge miniport instances was enabled after being\r
1380             // disabled earlier, e.g. from Device Manager in Win2000. Note that\r
1381             // NDIS calls this because we had set up an association between our\r
1382             // miniport and protocol entities by calling NdisIMAssociateMiniport.\r
1383             //\r
1384             // Since we would have torn down the lower binding for that miniport,\r
1385             // we need NDIS' assistance to re-bind to the lower miniport. The\r
1386             // call to NdisReEnumerateProtocolBindings does exactly that.\r
1387             //\r
1388             NdisReEnumerateProtocolBindings (ProtHandle);        \r
1389             \r
1390             break;\r
1391         }\r
1392 \r
1393 #ifdef NDIS51\r
1394         //\r
1395         // Pass on this notification to protocol(s) above before doing anything\r
1396         // with it.\r
1397         //\r
1398         if (pAdapt->MiniportHandle)\r
1399         {\r
1400             ReturnStatus = NdisIMNotifyPnPEvent(pAdapt->MiniportHandle, pNetPnPEvent);\r
1401         }\r
1402 #endif // NDIS51\r
1403 \r
1404         ReconfigStatus = NDIS_STATUS_SUCCESS;\r
1405 \r
1406     } while(FALSE);\r
1407 \r
1408     DBGPRINT(("<==PtPNPNetEventReconfigure: pAdapt %p\n", pAdapt));\r
1409 \r
1410 #ifdef NDIS51\r
1411     //\r
1412     // Overwrite status with what upper-layer protocol(s) returned.\r
1413     //\r
1414     ReconfigStatus = ReturnStatus;\r
1415 #endif\r
1416 \r
1417     return ReconfigStatus;\r
1418 }\r
1419 \r
1420 \r
1421 NDIS_STATUS\r
1422 PtPnPNetEventSetPower(\r
1423     IN PADAPT            pAdapt,\r
1424     IN PNET_PNP_EVENT    pNetPnPEvent\r
1425     )\r
1426 /*++\r
1427 Routine Description:\r
1428 \r
1429     This is a notification to our protocol edge of the power state\r
1430     of the lower miniport. If it is going to a low-power state, we must\r
1431     wait here for all outstanding sends and requests to complete.\r
1432 \r
1433     NDIS 5.1:  Since we use packet stacking, it is not sufficient to\r
1434     check usage of our local send packet pool to detect whether or not\r
1435     all outstanding sends have completed. For this, use the new API\r
1436     NdisQueryPendingIOCount.\r
1437 \r
1438     NDIS 5.1: Use the 5.1 API NdisIMNotifyPnPEvent to pass on PnP\r
1439     notifications to upper protocol(s).\r
1440 \r
1441 Arguments:\r
1442 \r
1443     pAdapt            -    Pointer to the adpater structure\r
1444     pNetPnPEvent    -    The Net Pnp Event. this contains the new device state\r
1445 \r
1446 Return Value:\r
1447 \r
1448     NDIS_STATUS_SUCCESS or the status returned by upper-layer protocols.\r
1449 \r
1450 --*/\r
1451 {\r
1452     PNDIS_DEVICE_POWER_STATE       pDeviceState  =(PNDIS_DEVICE_POWER_STATE)(pNetPnPEvent->Buffer);\r
1453     NDIS_DEVICE_POWER_STATE        PrevDeviceState = pAdapt->PTDeviceState;  \r
1454     NDIS_STATUS                    Status;\r
1455     NDIS_STATUS                    ReturnStatus;\r
1456 \r
1457     ReturnStatus = NDIS_STATUS_SUCCESS;\r
1458 \r
1459     //\r
1460     // Set the Internal Device State, this blocks all new sends or receives\r
1461     //\r
1462     NdisAcquireSpinLock(&pAdapt->Lock);\r
1463     pAdapt->PTDeviceState = *pDeviceState;\r
1464 \r
1465     //\r
1466     // Check if the miniport below is going to a low power state.\r
1467     //\r
1468     if (pAdapt->PTDeviceState > NdisDeviceStateD0)\r
1469     {\r
1470         //\r
1471         // If the miniport below is going to standby, fail all incoming requests\r
1472         //\r
1473         if (PrevDeviceState == NdisDeviceStateD0)\r
1474         {\r
1475             pAdapt->StandingBy = TRUE;\r
1476         }\r
1477 \r
1478         NdisReleaseSpinLock(&pAdapt->Lock);\r
1479 \r
1480 #ifdef NDIS51\r
1481         //\r
1482         // Notify upper layer protocol(s) first.\r
1483         //\r
1484         if (pAdapt->MiniportHandle != NULL)\r
1485         {\r
1486             ReturnStatus = NdisIMNotifyPnPEvent(pAdapt->MiniportHandle, pNetPnPEvent);\r
1487         }\r
1488 #endif // NDIS51\r
1489 \r
1490         //\r
1491         // Wait for outstanding sends and requests to complete.\r
1492         //\r
1493         while (pAdapt->OutstandingSends != 0)\r
1494         {\r
1495             NdisMSleep(2);\r
1496         }\r
1497 \r
1498         while (pAdapt->OutstandingRequests == TRUE)\r
1499         {\r
1500             //\r
1501             // sleep till outstanding requests complete\r
1502             //\r
1503             NdisMSleep(2);\r
1504         }\r
1505 \r
1506         //\r
1507         // If the below miniport is going to low power state, complete the queued request\r
1508         //\r
1509         NdisAcquireSpinLock(&pAdapt->Lock);\r
1510         if (pAdapt->QueuedRequest)\r
1511         {\r
1512             pAdapt->QueuedRequest = FALSE;\r
1513             NdisReleaseSpinLock(&pAdapt->Lock);\r
1514             PtRequestComplete(pAdapt, &pAdapt->Request, NDIS_STATUS_FAILURE);\r
1515         }\r
1516         else\r
1517         {\r
1518             NdisReleaseSpinLock(&pAdapt->Lock);\r
1519         }\r
1520             \r
1521 \r
1522         ASSERT(NdisPacketPoolUsage(pAdapt->SendPacketPoolHandle) == 0);\r
1523         ASSERT(pAdapt->OutstandingRequests == FALSE);\r
1524     }\r
1525     else\r
1526     {\r
1527         //\r
1528         // If the physical miniport is powering up (from Low power state to D0), \r
1529         // clear the flag\r
1530         //\r
1531         if (PrevDeviceState > NdisDeviceStateD0)\r
1532         {\r
1533             pAdapt->StandingBy = FALSE;\r
1534         }\r
1535         //\r
1536         // The device below is being turned on. If we had a request\r
1537         // pending, send it down now.\r
1538         //\r
1539         if (pAdapt->QueuedRequest == TRUE)\r
1540         {\r
1541             pAdapt->QueuedRequest = FALSE;\r
1542         \r
1543             pAdapt->OutstandingRequests = TRUE;\r
1544             NdisReleaseSpinLock(&pAdapt->Lock);\r
1545 \r
1546             NdisRequest(&Status,\r
1547                         pAdapt->BindingHandle,\r
1548                         &pAdapt->Request);\r
1549 \r
1550             if (Status != NDIS_STATUS_PENDING)\r
1551             {\r
1552                 PtRequestComplete(pAdapt,\r
1553                                   &pAdapt->Request,\r
1554                                   Status);\r
1555                 \r
1556             }\r
1557         }\r
1558         else\r
1559         {\r
1560             NdisReleaseSpinLock(&pAdapt->Lock);\r
1561         }\r
1562 \r
1563 \r
1564 #ifdef NDIS51\r
1565         //\r
1566         // Pass on this notification to protocol(s) above\r
1567         //\r
1568         if (pAdapt->MiniportHandle)\r
1569         {\r
1570             ReturnStatus = NdisIMNotifyPnPEvent(pAdapt->MiniportHandle, pNetPnPEvent);\r
1571         }\r
1572 #endif // NDIS51\r
1573 \r
1574     }\r
1575 \r
1576     return ReturnStatus;\r
1577 }\r
1578 \r
1579 VOID\r
1580 PtReferenceAdapt(\r
1581     IN PADAPT     pAdapt\r
1582     )\r
1583 {\r
1584     NdisAcquireSpinLock(&pAdapt->Lock);\r
1585     \r
1586     ASSERT(pAdapt->RefCount >= 0);\r
1587 \r
1588     pAdapt->RefCount ++;\r
1589     NdisReleaseSpinLock(&pAdapt->Lock);\r
1590 }\r
1591 \r
1592 \r
1593 BOOLEAN\r
1594 PtDereferenceAdapt(\r
1595     IN PADAPT     pAdapt\r
1596     )\r
1597 {\r
1598     NdisAcquireSpinLock(&pAdapt->Lock);\r
1599 \r
1600     ASSERT(pAdapt->RefCount > 0);\r
1601 \r
1602     pAdapt->RefCount--;\r
1603 \r
1604     if (pAdapt->RefCount == 0)\r
1605     {\r
1606         NdisReleaseSpinLock(&pAdapt->Lock);\r
1607         \r
1608         //\r
1609         // Free all resources on this adapter structure.\r
1610         //\r
1611         MPFreeAllPacketPools (pAdapt);;\r
1612         NdisFreeSpinLock(&pAdapt->Lock);\r
1613         NdisFreeMemory(pAdapt, 0 , 0);\r
1614         \r
1615         return TRUE;\r
1616         \r
1617     }\r
1618     else\r
1619     {\r
1620         NdisReleaseSpinLock(&pAdapt->Lock);\r
1621 \r
1622         return FALSE;\r
1623     }\r
1624 }\r
1625 \r
1626 \r