[E1000] Finished an implementation of the driver.
[reactos.git] / drivers / network / dd / e1000 / ndis.c
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 }