xref: /reactos/drivers/network/dd/e1000/ndis.c (revision 58588b76)
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     ResourceList = NULL;
120     ResourceListSize = 0;
121 
122     /* Allocate our adapter context */
123     Status = NdisAllocateMemoryWithTag((PVOID*)&Adapter,
124                                        sizeof(*Adapter),
125                                        E1000_TAG);
126     if (Status != NDIS_STATUS_SUCCESS)
127     {
128         NDIS_DbgPrint(MIN_TRACE, ("Failed to allocate adapter context (0x%x)\n", Status));
129         return NDIS_STATUS_RESOURCES;
130     }
131 
132     RtlZeroMemory(Adapter, sizeof(*Adapter));
133     Adapter->AdapterHandle = MiniportAdapterHandle;
134 
135     /* Notify NDIS of some characteristics of our NIC */
136     NdisMSetAttributesEx(MiniportAdapterHandle,
137                          Adapter,
138                          0,
139                          NDIS_ATTRIBUTE_BUS_MASTER,
140                          NdisInterfacePci);
141 
142     NdisReadPciSlotInformation(Adapter->AdapterHandle,
143                                0,
144                                FIELD_OFFSET(PCI_COMMON_CONFIG, VendorID),
145                                &PciConfig, sizeof(PciConfig));
146 
147     Adapter->VendorID = PciConfig.VendorID;
148     Adapter->DeviceID = PciConfig.DeviceID;
149 
150     Adapter->SubsystemID = PciConfig.u.type0.SubSystemID;
151     Adapter->SubsystemVendorID = PciConfig.u.type0.SubVendorID;
152 
153 
154     if (!NICRecognizeHardware(Adapter))
155     {
156         NDIS_DbgPrint(MIN_TRACE, ("Hardware not recognized\n"));
157         Status = NDIS_STATUS_UNSUPPORTED_MEDIA;
158         goto Cleanup;
159     }
160 
161     /* Get our resources for IRQ and IO base information */
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 
290     MiniportHalt(Adapter);
291 
292     return Status;
293 }
294 
295 NTSTATUS
296 NTAPI
297 DriverEntry(
298     IN PDRIVER_OBJECT DriverObject,
299     IN PUNICODE_STRING RegistryPath)
300 {
301     NDIS_HANDLE WrapperHandle;
302     NDIS_MINIPORT_CHARACTERISTICS Characteristics = { 0 };
303     NDIS_STATUS Status;
304 
305     Characteristics.MajorNdisVersion = NDIS_MINIPORT_MAJOR_VERSION;
306     Characteristics.MinorNdisVersion = NDIS_MINIPORT_MINOR_VERSION;
307     Characteristics.CheckForHangHandler = NULL;
308     Characteristics.DisableInterruptHandler = NULL;
309     Characteristics.EnableInterruptHandler = NULL;
310     Characteristics.HaltHandler = MiniportHalt;
311     Characteristics.HandleInterruptHandler = MiniportHandleInterrupt;
312     Characteristics.InitializeHandler = MiniportInitialize;
313     Characteristics.ISRHandler = MiniportISR;
314     Characteristics.QueryInformationHandler = MiniportQueryInformation;
315     Characteristics.ReconfigureHandler = NULL;
316     Characteristics.ResetHandler = MiniportReset;
317     Characteristics.SendHandler = MiniportSend;
318     Characteristics.SetInformationHandler = MiniportSetInformation;
319     Characteristics.TransferDataHandler = NULL;
320     Characteristics.ReturnPacketHandler = NULL;
321     Characteristics.SendPacketsHandler = NULL;
322     Characteristics.AllocateCompleteHandler = NULL;
323 
324     NdisMInitializeWrapper(&WrapperHandle, DriverObject, RegistryPath, NULL);
325     if (!WrapperHandle)
326     {
327         return NDIS_STATUS_FAILURE;
328     }
329 
330     Status = NdisMRegisterMiniport(WrapperHandle, &Characteristics, sizeof(Characteristics));
331     if (Status != NDIS_STATUS_SUCCESS)
332     {
333         NdisTerminateWrapper(WrapperHandle, 0);
334         return NDIS_STATUS_FAILURE;
335     }
336 
337     return NDIS_STATUS_SUCCESS;
338 }
339