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