xref: /reactos/drivers/network/dd/e1000/ndis.c (revision 5bfe6a53)
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 NDIS_STATUS
27 NTAPI
28 MiniportSend(
29     IN NDIS_HANDLE MiniportAdapterContext,
30     IN PNDIS_PACKET Packet,
31     IN UINT Flags)
32 {
33     PE1000_ADAPTER Adapter = (PE1000_ADAPTER)MiniportAdapterContext;
34     PSCATTER_GATHER_LIST sgList = NDIS_PER_PACKET_INFO_FROM_PACKET(Packet, ScatterGatherListPacketInfo);
35     ULONG TransmitLength;
36     PHYSICAL_ADDRESS TransmitBuffer;
37     NDIS_STATUS Status;
38 
39     ASSERT(sgList != NULL);
40     ASSERT(sgList->NumberOfElements == 1);
41     ASSERT((sgList->Elements[0].Address.LowPart & 3) == 0);
42     ASSERT(sgList->Elements[0].Length <= MAXIMUM_FRAME_SIZE);
43 
44     if (Adapter->TxFull)
45     {
46         NDIS_DbgPrint(MIN_TRACE, ("All TX descriptors are full\n"));
47         return NDIS_STATUS_RESOURCES;
48     }
49 
50     TransmitLength = sgList->Elements[0].Length;
51     TransmitBuffer = sgList->Elements[0].Address;
52     Adapter->TransmitPackets[Adapter->CurrentTxDesc] = Packet;
53 
54     Status = NICTransmitPacket(Adapter, TransmitBuffer, TransmitLength);
55     if (Status != NDIS_STATUS_SUCCESS)
56     {
57         NDIS_DbgPrint(MIN_TRACE, ("Transmit packet failed\n"));
58         return Status;
59     }
60 
61     return NDIS_STATUS_PENDING;
62 }
63 
64 VOID
65 NTAPI
66 MiniportHalt(
67     IN NDIS_HANDLE MiniportAdapterContext)
68 {
69     PE1000_ADAPTER Adapter = (PE1000_ADAPTER)MiniportAdapterContext;
70 
71     ASSERT(Adapter != NULL);
72 
73     /* First disable sending / receiving */
74     NICDisableTxRx(Adapter);
75 
76     /* Then unregister interrupts */
77     NICUnregisterInterrupts(Adapter);
78 
79     /* Finally, free other resources (Ports, IO ranges,...) */
80     NICReleaseIoResources(Adapter);
81 
82     /* Destroy the adapter context */
83     NdisFreeMemory(Adapter, sizeof(*Adapter), 0);
84 }
85 
86 NDIS_STATUS
87 NTAPI
88 MiniportInitialize(
89     OUT PNDIS_STATUS OpenErrorStatus,
90     OUT PUINT SelectedMediumIndex,
91     IN PNDIS_MEDIUM MediumArray,
92     IN UINT MediumArraySize,
93     IN NDIS_HANDLE MiniportAdapterHandle,
94     IN NDIS_HANDLE WrapperConfigurationContext)
95 {
96     PE1000_ADAPTER Adapter;
97     NDIS_STATUS Status;
98     UINT i;
99     PNDIS_RESOURCE_LIST ResourceList;
100     UINT ResourceListSize;
101     PCI_COMMON_CONFIG PciConfig;
102 
103     /* Make sure the medium is supported */
104     for (i = 0; i < MediumArraySize; i++)
105     {
106         if (MediumArray[i] == NdisMedium802_3)
107         {
108             *SelectedMediumIndex = i;
109             break;
110         }
111     }
112 
113     if (i == MediumArraySize)
114     {
115         NDIS_DbgPrint(MIN_TRACE, ("802.3 medium was not found in the medium array\n"));
116         return NDIS_STATUS_UNSUPPORTED_MEDIA;
117     }
118 
119     /* Allocate our adapter context */
120     Status = NdisAllocateMemoryWithTag((PVOID*)&Adapter,
121                                        sizeof(*Adapter),
122                                        E1000_TAG);
123     if (Status != NDIS_STATUS_SUCCESS)
124     {
125         NDIS_DbgPrint(MIN_TRACE, ("Failed to allocate adapter context (0x%x)\n", Status));
126         return NDIS_STATUS_RESOURCES;
127     }
128 
129     RtlZeroMemory(Adapter, sizeof(*Adapter));
130     Adapter->AdapterHandle = MiniportAdapterHandle;
131 
132     /* Notify NDIS of some characteristics of our NIC */
133     NdisMSetAttributesEx(MiniportAdapterHandle,
134                          Adapter,
135                          0,
136                          NDIS_ATTRIBUTE_BUS_MASTER,
137                          NdisInterfacePci);
138 
139     NdisReadPciSlotInformation(Adapter->AdapterHandle,
140                                0,
141                                FIELD_OFFSET(PCI_COMMON_CONFIG, VendorID),
142                                &PciConfig, sizeof(PciConfig));
143 
144     Adapter->VendorID = PciConfig.VendorID;
145     Adapter->DeviceID = PciConfig.DeviceID;
146 
147     Adapter->SubsystemID = PciConfig.u.type0.SubSystemID;
148     Adapter->SubsystemVendorID = PciConfig.u.type0.SubVendorID;
149 
150 
151     if (!NICRecognizeHardware(Adapter))
152     {
153         NDIS_DbgPrint(MIN_TRACE, ("Hardware not recognized\n"));
154         Status = NDIS_STATUS_UNSUPPORTED_MEDIA;
155         goto Cleanup;
156     }
157 
158 
159     /* Get our resources for IRQ and IO base information */
160     ResourceList = NULL;
161     ResourceListSize = 0;
162     NdisMQueryAdapterResources(&Status,
163                                WrapperConfigurationContext,
164                                ResourceList,
165                                &ResourceListSize);
166     if (Status != NDIS_STATUS_RESOURCES)
167     {
168         NDIS_DbgPrint(MIN_TRACE, ("Unexpected failure of NdisMQueryAdapterResources (0x%x)\n", Status));
169         Status = NDIS_STATUS_FAILURE;
170         /* call NdisWriteErrorLogEntry */
171         goto Cleanup;
172     }
173 
174     Status = NdisAllocateMemoryWithTag((PVOID*)&ResourceList,
175                                 ResourceListSize,
176                                 E1000_TAG);
177     if (Status != NDIS_STATUS_SUCCESS)
178     {
179         NDIS_DbgPrint(MIN_TRACE, ("Failed to allocate resource list (0x%x)\n", Status));
180         /* call NdisWriteErrorLogEntry */
181         goto Cleanup;
182     }
183 
184     NdisMQueryAdapterResources(&Status,
185                                WrapperConfigurationContext,
186                                ResourceList,
187                                &ResourceListSize);
188     if (Status != NDIS_STATUS_SUCCESS)
189     {
190         NDIS_DbgPrint(MIN_TRACE, ("Unexpected failure of NdisMQueryAdapterResources (0x%x)\n", Status));
191         /* call NdisWriteErrorLogEntry */
192         goto Cleanup;
193     }
194 
195     ASSERT(ResourceList->Version == 1);
196     ASSERT(ResourceList->Revision == 1);
197 
198     Status = NICInitializeAdapterResources(Adapter, ResourceList);
199 
200     NdisFreeMemory(ResourceList, ResourceListSize, 0);
201     ResourceList = NULL;
202 
203     if (Status != NDIS_STATUS_SUCCESS)
204     {
205         NDIS_DbgPrint(MIN_TRACE, ("Adapter didn't receive enough resources\n"));
206         goto Cleanup;
207     }
208 
209     /* Allocate the DMA resources */
210     Status = NdisMInitializeScatterGatherDma(MiniportAdapterHandle,
211                                              FALSE, // 64bit is supported but can be buggy
212                                              MAXIMUM_FRAME_SIZE);
213     if (Status != NDIS_STATUS_SUCCESS)
214     {
215         NDIS_DbgPrint(MIN_TRACE, ("Unable to configure DMA\n"));
216         Status = NDIS_STATUS_RESOURCES;
217         goto Cleanup;
218     }
219 
220     Status = NICAllocateIoResources(Adapter);
221     if (Status != NDIS_STATUS_SUCCESS)
222     {
223         NDIS_DbgPrint(MIN_TRACE, ("Unable to allocate resources\n"));
224         Status = NDIS_STATUS_RESOURCES;
225         goto Cleanup;
226     }
227 
228     /* Adapter setup */
229     Status = NICPowerOn(Adapter);
230     if (Status != NDIS_STATUS_SUCCESS)
231     {
232         NDIS_DbgPrint(MIN_TRACE, ("Unable to power on NIC (0x%x)\n", Status));
233         goto Cleanup;
234     }
235 
236     Status = NICSoftReset(Adapter);
237     if (Status != NDIS_STATUS_SUCCESS)
238     {
239         NDIS_DbgPrint(MIN_TRACE, ("Unable to reset the NIC (0x%x)\n", Status));
240         goto Cleanup;
241     }
242 
243     Status = NICGetPermanentMacAddress(Adapter, Adapter->PermanentMacAddress);
244     if (Status != NDIS_STATUS_SUCCESS)
245     {
246         NDIS_DbgPrint(MIN_TRACE, ("Unable to get the fixed MAC address (0x%x)\n", Status));
247         goto Cleanup;
248     }
249 
250     RtlCopyMemory(Adapter->MulticastList[0].MacAddress, Adapter->PermanentMacAddress, IEEE_802_ADDR_LENGTH);
251 
252     NICUpdateMulticastList(Adapter);
253 
254     /* Update link state and speed */
255     NICUpdateLinkStatus(Adapter);
256 
257     /* We're ready to handle interrupts now */
258     Status = NICRegisterInterrupts(Adapter);
259     if (Status != NDIS_STATUS_SUCCESS)
260     {
261         NDIS_DbgPrint(MIN_TRACE, ("Unable to register interrupt (0x%x)\n", Status));
262         goto Cleanup;
263     }
264 
265     /* Enable interrupts on the NIC */
266     Adapter->InterruptMask = DEFAULT_INTERRUPT_MASK;
267     Status = NICApplyInterruptMask(Adapter);
268     if (Status != NDIS_STATUS_SUCCESS)
269     {
270         NDIS_DbgPrint(MIN_TRACE, ("Unable to apply interrupt mask (0x%x)\n", Status));
271         goto Cleanup;
272     }
273 
274     /* Turn on TX and RX now */
275     Status = NICEnableTxRx(Adapter);
276     if (Status != NDIS_STATUS_SUCCESS)
277     {
278         NDIS_DbgPrint(MIN_TRACE, ("Unable to enable TX and RX (0x%x)\n", Status));
279         goto Cleanup;
280     }
281 
282     return NDIS_STATUS_SUCCESS;
283 
284 Cleanup:
285     if (ResourceList != NULL)
286     {
287         NdisFreeMemory(ResourceList, ResourceListSize, 0);
288     }
289     if (Adapter != NULL)
290     {
291         MiniportHalt(Adapter);
292     }
293 
294     return Status;
295 }
296 
297 NTSTATUS
298 NTAPI
299 DriverEntry(
300     IN PDRIVER_OBJECT DriverObject,
301     IN PUNICODE_STRING RegistryPath)
302 {
303     NDIS_HANDLE WrapperHandle;
304     NDIS_MINIPORT_CHARACTERISTICS Characteristics = { 0 };
305     NDIS_STATUS Status;
306 
307     Characteristics.MajorNdisVersion = NDIS_MINIPORT_MAJOR_VERSION;
308     Characteristics.MinorNdisVersion = NDIS_MINIPORT_MINOR_VERSION;
309     Characteristics.CheckForHangHandler = NULL;
310     Characteristics.DisableInterruptHandler = NULL;
311     Characteristics.EnableInterruptHandler = NULL;
312     Characteristics.HaltHandler = MiniportHalt;
313     Characteristics.HandleInterruptHandler = MiniportHandleInterrupt;
314     Characteristics.InitializeHandler = MiniportInitialize;
315     Characteristics.ISRHandler = MiniportISR;
316     Characteristics.QueryInformationHandler = MiniportQueryInformation;
317     Characteristics.ReconfigureHandler = NULL;
318     Characteristics.ResetHandler = MiniportReset;
319     Characteristics.SendHandler = MiniportSend;
320     Characteristics.SetInformationHandler = MiniportSetInformation;
321     Characteristics.TransferDataHandler = NULL;
322     Characteristics.ReturnPacketHandler = NULL;
323     Characteristics.SendPacketsHandler = NULL;
324     Characteristics.AllocateCompleteHandler = NULL;
325 
326     NdisMInitializeWrapper(&WrapperHandle, DriverObject, RegistryPath, NULL);
327     if (!WrapperHandle)
328     {
329         return NDIS_STATUS_FAILURE;
330     }
331 
332     Status = NdisMRegisterMiniport(WrapperHandle, &Characteristics, sizeof(Characteristics));
333     if (Status != NDIS_STATUS_SUCCESS)
334     {
335         NdisTerminateWrapper(WrapperHandle, 0);
336         return NDIS_STATUS_FAILURE;
337     }
338 
339     return NDIS_STATUS_SUCCESS;
340 }
341