xref: /reactos/drivers/network/dd/e1000/ndis.c (revision 1734f297)
1 /*
2  * PROJECT:     ReactOS Intel PRO/1000 Driver
3  * LICENSE:     GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4  * PURPOSE:     Driver entrypoint
5  * COPYRIGHT:   Copyright 2013 Cameron Gutman (cameron.gutman@reactos.org)
6  *              Copyright 2018 Mark Jansen (mark.jansen@reactos.org)
7  */
8 
9 #include "nic.h"
10 
11 #include <debug.h>
12 
13 ULONG DebugTraceLevel = MIN_TRACE;
14 
15 NDIS_STATUS
16 NTAPI
17 MiniportReset(
18     OUT PBOOLEAN AddressingReset,
19     IN NDIS_HANDLE MiniportAdapterContext)
20 {
21     *AddressingReset = FALSE;
22     UNIMPLEMENTED_DBGBREAK();
23     return NDIS_STATUS_FAILURE;
24 }
25 
26 VOID
27 NTAPI
28 MiniportHalt(
29     IN NDIS_HANDLE MiniportAdapterContext)
30 {
31     PE1000_ADAPTER Adapter = (PE1000_ADAPTER)MiniportAdapterContext;
32 
33     ASSERT(Adapter != NULL);
34 
35     /* First disable sending / receiving */
36     NICDisableTxRx(Adapter);
37 
38     /* Then unregister interrupts */
39     NICUnregisterInterrupts(Adapter);
40 
41     /* Finally, free other resources (Ports, IO ranges,...) */
42     NICReleaseIoResources(Adapter);
43 
44     /* Destroy the adapter context */
45     NdisFreeMemory(Adapter, sizeof(*Adapter), 0);
46 }
47 
48 NDIS_STATUS
49 NTAPI
50 MiniportInitialize(
51     OUT PNDIS_STATUS OpenErrorStatus,
52     OUT PUINT SelectedMediumIndex,
53     IN PNDIS_MEDIUM MediumArray,
54     IN UINT MediumArraySize,
55     IN NDIS_HANDLE MiniportAdapterHandle,
56     IN NDIS_HANDLE WrapperConfigurationContext)
57 {
58     PE1000_ADAPTER Adapter;
59     NDIS_STATUS Status;
60     UINT i;
61     PNDIS_RESOURCE_LIST ResourceList;
62     UINT ResourceListSize;
63     PCI_COMMON_CONFIG PciConfig;
64 
65     /* Make sure the medium is supported */
66     for (i = 0; i < MediumArraySize; i++)
67     {
68         if (MediumArray[i] == NdisMedium802_3)
69         {
70             *SelectedMediumIndex = i;
71             break;
72         }
73     }
74 
75     if (i == MediumArraySize)
76     {
77         NDIS_DbgPrint(MIN_TRACE, ("802.3 medium was not found in the medium array\n"));
78         return NDIS_STATUS_UNSUPPORTED_MEDIA;
79     }
80 
81     ResourceList = NULL;
82     ResourceListSize = 0;
83 
84     /* Allocate our adapter context */
85     Status = NdisAllocateMemoryWithTag((PVOID*)&Adapter,
86                                        sizeof(*Adapter),
87                                        E1000_TAG);
88     if (Status != NDIS_STATUS_SUCCESS)
89     {
90         NDIS_DbgPrint(MIN_TRACE, ("Failed to allocate adapter context (0x%x)\n", Status));
91         return NDIS_STATUS_RESOURCES;
92     }
93 
94     RtlZeroMemory(Adapter, sizeof(*Adapter));
95     Adapter->AdapterHandle = MiniportAdapterHandle;
96 
97     /* Notify NDIS of some characteristics of our NIC */
98     NdisMSetAttributesEx(MiniportAdapterHandle,
99                          Adapter,
100                          0,
101                          NDIS_ATTRIBUTE_BUS_MASTER,
102                          NdisInterfacePci);
103 
104     NdisReadPciSlotInformation(Adapter->AdapterHandle,
105                                0,
106                                FIELD_OFFSET(PCI_COMMON_CONFIG, VendorID),
107                                &PciConfig, sizeof(PciConfig));
108 
109     Adapter->VendorID = PciConfig.VendorID;
110     Adapter->DeviceID = PciConfig.DeviceID;
111 
112     Adapter->SubsystemID = PciConfig.u.type0.SubSystemID;
113     Adapter->SubsystemVendorID = PciConfig.u.type0.SubVendorID;
114 
115 
116     if (!NICRecognizeHardware(Adapter))
117     {
118         NDIS_DbgPrint(MIN_TRACE, ("Hardware not recognized\n"));
119         Status = NDIS_STATUS_UNSUPPORTED_MEDIA;
120         goto Cleanup;
121     }
122 
123     /* Get our resources for IRQ and IO base information */
124     NdisMQueryAdapterResources(&Status,
125                                WrapperConfigurationContext,
126                                ResourceList,
127                                &ResourceListSize);
128     if (Status != NDIS_STATUS_RESOURCES)
129     {
130         NDIS_DbgPrint(MIN_TRACE, ("Unexpected failure of NdisMQueryAdapterResources (0x%x)\n", Status));
131         Status = NDIS_STATUS_FAILURE;
132         /* call NdisWriteErrorLogEntry */
133         goto Cleanup;
134     }
135 
136     Status = NdisAllocateMemoryWithTag((PVOID*)&ResourceList,
137                                 ResourceListSize,
138                                 E1000_TAG);
139     if (Status != NDIS_STATUS_SUCCESS)
140     {
141         NDIS_DbgPrint(MIN_TRACE, ("Failed to allocate resource list (0x%x)\n", Status));
142         /* call NdisWriteErrorLogEntry */
143         goto Cleanup;
144     }
145 
146     NdisMQueryAdapterResources(&Status,
147                                WrapperConfigurationContext,
148                                ResourceList,
149                                &ResourceListSize);
150     if (Status != NDIS_STATUS_SUCCESS)
151     {
152         NDIS_DbgPrint(MIN_TRACE, ("Unexpected failure of NdisMQueryAdapterResources (0x%x)\n", Status));
153         /* call NdisWriteErrorLogEntry */
154         goto Cleanup;
155     }
156 
157     ASSERT(ResourceList->Version == 1);
158     ASSERT(ResourceList->Revision == 1);
159 
160     Status = NICInitializeAdapterResources(Adapter, ResourceList);
161 
162     NdisFreeMemory(ResourceList, ResourceListSize, 0);
163     ResourceList = NULL;
164 
165     if (Status != NDIS_STATUS_SUCCESS)
166     {
167         NDIS_DbgPrint(MIN_TRACE, ("Adapter didn't receive enough resources\n"));
168         goto Cleanup;
169     }
170 
171     /* Allocate the DMA resources */
172     Status = NdisMInitializeScatterGatherDma(MiniportAdapterHandle,
173                                              FALSE, // 64bit is supported but can be buggy
174                                              MAXIMUM_FRAME_SIZE);
175     if (Status != NDIS_STATUS_SUCCESS)
176     {
177         NDIS_DbgPrint(MIN_TRACE, ("Unable to configure DMA\n"));
178         Status = NDIS_STATUS_RESOURCES;
179         goto Cleanup;
180     }
181 
182     Status = NICAllocateIoResources(Adapter);
183     if (Status != NDIS_STATUS_SUCCESS)
184     {
185         NDIS_DbgPrint(MIN_TRACE, ("Unable to allocate resources\n"));
186         Status = NDIS_STATUS_RESOURCES;
187         goto Cleanup;
188     }
189 
190     /* Adapter setup */
191     Status = NICPowerOn(Adapter);
192     if (Status != NDIS_STATUS_SUCCESS)
193     {
194         NDIS_DbgPrint(MIN_TRACE, ("Unable to power on NIC (0x%x)\n", Status));
195         goto Cleanup;
196     }
197 
198     Status = NICSoftReset(Adapter);
199     if (Status != NDIS_STATUS_SUCCESS)
200     {
201         NDIS_DbgPrint(MIN_TRACE, ("Unable to reset the NIC (0x%x)\n", Status));
202         goto Cleanup;
203     }
204 
205     Status = NICGetPermanentMacAddress(Adapter, Adapter->PermanentMacAddress);
206     if (Status != NDIS_STATUS_SUCCESS)
207     {
208         NDIS_DbgPrint(MIN_TRACE, ("Unable to get the fixed MAC address (0x%x)\n", Status));
209         goto Cleanup;
210     }
211 
212     RtlCopyMemory(Adapter->MulticastList[0].MacAddress, Adapter->PermanentMacAddress, IEEE_802_ADDR_LENGTH);
213 
214     NICUpdateMulticastList(Adapter);
215 
216     /* Update link state and speed */
217     NICUpdateLinkStatus(Adapter);
218 
219     /* We're ready to handle interrupts now */
220     Status = NICRegisterInterrupts(Adapter);
221     if (Status != NDIS_STATUS_SUCCESS)
222     {
223         NDIS_DbgPrint(MIN_TRACE, ("Unable to register interrupt (0x%x)\n", Status));
224         goto Cleanup;
225     }
226 
227     /* Enable interrupts on the NIC */
228     Adapter->InterruptMask = DEFAULT_INTERRUPT_MASK;
229     NICApplyInterruptMask(Adapter);
230 
231     /* Turn on TX and RX now */
232     Status = NICEnableTxRx(Adapter);
233     if (Status != NDIS_STATUS_SUCCESS)
234     {
235         NDIS_DbgPrint(MIN_TRACE, ("Unable to enable TX and RX (0x%x)\n", Status));
236         goto Cleanup;
237     }
238 
239     return NDIS_STATUS_SUCCESS;
240 
241 Cleanup:
242     if (ResourceList != NULL)
243     {
244         NdisFreeMemory(ResourceList, ResourceListSize, 0);
245     }
246 
247     MiniportHalt(Adapter);
248 
249     return Status;
250 }
251 
252 NTSTATUS
253 NTAPI
254 DriverEntry(
255     IN PDRIVER_OBJECT DriverObject,
256     IN PUNICODE_STRING RegistryPath)
257 {
258     NDIS_HANDLE WrapperHandle;
259     NDIS_MINIPORT_CHARACTERISTICS Characteristics = { 0 };
260     NDIS_STATUS Status;
261 
262     Characteristics.MajorNdisVersion = NDIS_MINIPORT_MAJOR_VERSION;
263     Characteristics.MinorNdisVersion = NDIS_MINIPORT_MINOR_VERSION;
264     Characteristics.CheckForHangHandler = NULL;
265     Characteristics.DisableInterruptHandler = NULL;
266     Characteristics.EnableInterruptHandler = NULL;
267     Characteristics.HaltHandler = MiniportHalt;
268     Characteristics.HandleInterruptHandler = MiniportHandleInterrupt;
269     Characteristics.InitializeHandler = MiniportInitialize;
270     Characteristics.ISRHandler = MiniportISR;
271     Characteristics.QueryInformationHandler = MiniportQueryInformation;
272     Characteristics.ReconfigureHandler = NULL;
273     Characteristics.ResetHandler = MiniportReset;
274     Characteristics.SendHandler = MiniportSend;
275     Characteristics.SetInformationHandler = MiniportSetInformation;
276     Characteristics.TransferDataHandler = NULL;
277     Characteristics.ReturnPacketHandler = NULL;
278     Characteristics.SendPacketsHandler = NULL;
279     Characteristics.AllocateCompleteHandler = NULL;
280 
281     NdisMInitializeWrapper(&WrapperHandle, DriverObject, RegistryPath, NULL);
282     if (!WrapperHandle)
283     {
284         return NDIS_STATUS_FAILURE;
285     }
286 
287     Status = NdisMRegisterMiniport(WrapperHandle, &Characteristics, sizeof(Characteristics));
288     if (Status != NDIS_STATUS_SUCCESS)
289     {
290         NdisTerminateWrapper(WrapperHandle, 0);
291         return NDIS_STATUS_FAILURE;
292     }
293 
294     return NDIS_STATUS_SUCCESS;
295 }
296