1 /*
2 * PROJECT: ReactOS nVidia nForce Ethernet Controller Driver
3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4 * PURPOSE: Miniport initialization helper routines
5 * COPYRIGHT: Copyright 2021-2022 Dmitry Borisov <di.sean@protonmail.com>
6 */
7
8 /* INCLUDES *******************************************************************/
9
10 #include "nvnet.h"
11
12 #define NDEBUG
13 #include "debug.h"
14
15 /* FUNCTIONS ******************************************************************/
16
17 static
18 CODE_SEG("PAGE")
19 VOID
QueryInteger(_In_ NDIS_HANDLE ConfigurationHandle,_In_ PCWSTR EntryName,_Out_ PULONG EntryContext,_In_ ULONG DefaultValue,_In_ ULONG Minimum,_In_ ULONG Maximum)20 QueryInteger(
21 _In_ NDIS_HANDLE ConfigurationHandle,
22 _In_ PCWSTR EntryName,
23 _Out_ PULONG EntryContext,
24 _In_ ULONG DefaultValue,
25 _In_ ULONG Minimum,
26 _In_ ULONG Maximum)
27 {
28 NDIS_STATUS Status;
29 UNICODE_STRING Keyword;
30 PNDIS_CONFIGURATION_PARAMETER ConfigurationParameter;
31
32 PAGED_CODE();
33
34 NdisInitUnicodeString(&Keyword, EntryName);
35 NdisReadConfiguration(&Status,
36 &ConfigurationParameter,
37 ConfigurationHandle,
38 &Keyword,
39 NdisParameterInteger);
40 if (Status != NDIS_STATUS_SUCCESS)
41 {
42 NDIS_DbgPrint(MIN_TRACE, ("'%S' request failed\n", EntryName));
43
44 *EntryContext = DefaultValue;
45 }
46 else
47 {
48 if (ConfigurationParameter->ParameterData.IntegerData >= Minimum &&
49 ConfigurationParameter->ParameterData.IntegerData <= Maximum)
50 {
51 *EntryContext = ConfigurationParameter->ParameterData.IntegerData;
52 }
53 else
54 {
55 NDIS_DbgPrint(MAX_TRACE, ("'%S' value out of range\n", EntryName));
56
57 *EntryContext = DefaultValue;
58 }
59 }
60
61 NDIS_DbgPrint(MIN_TRACE, ("Set '%S' to %d\n", EntryName, *EntryContext));
62 }
63
64 static
65 CODE_SEG("PAGE")
66 NDIS_STATUS
NvNetReadConfiguration(_Inout_ PNVNET_ADAPTER Adapter)67 NvNetReadConfiguration(
68 _Inout_ PNVNET_ADAPTER Adapter)
69 {
70 NDIS_STATUS Status;
71 NDIS_HANDLE ConfigurationHandle;
72 PUCHAR NetworkAddress;
73 UINT Length;
74 ULONG GenericUlong;
75
76 PAGED_CODE();
77
78 NDIS_DbgPrint(MIN_TRACE, ("()\n"));
79
80 NdisOpenConfiguration(&Status,
81 &ConfigurationHandle,
82 Adapter->WrapperConfigurationHandle);
83 if (Status != NDIS_STATUS_SUCCESS)
84 return Status;
85
86 QueryInteger(ConfigurationHandle,
87 L"OptimizationMode",
88 &GenericUlong,
89 NV_OPTIMIZATION_MODE_DYNAMIC,
90 NV_OPTIMIZATION_MODE_THROUGHPUT,
91 NV_OPTIMIZATION_MODE_DYNAMIC);
92 Adapter->OptimizationMode = GenericUlong;
93
94 QueryInteger(ConfigurationHandle,
95 L"FlowControl",
96 &GenericUlong,
97 NV_FLOW_CONTROL_AUTO,
98 NV_FLOW_CONTROL_DISABLE,
99 NV_FLOW_CONTROL_RX_TX);
100 Adapter->FlowControlMode = GenericUlong;
101
102 QueryInteger(ConfigurationHandle,
103 L"SpeedDuplex",
104 &GenericUlong,
105 0,
106 0,
107 4);
108 switch (GenericUlong)
109 {
110 case 1:
111 Adapter->Flags |= NV_FORCE_SPEED_AND_DUPLEX;
112 break;
113 case 2:
114 Adapter->Flags |= (NV_FORCE_SPEED_AND_DUPLEX | NV_FORCE_FULL_DUPLEX);
115 break;
116 case 3:
117 Adapter->Flags |= (NV_FORCE_SPEED_AND_DUPLEX | NV_USER_SPEED_100);
118 break;
119 case 4:
120 Adapter->Flags |= (NV_FORCE_SPEED_AND_DUPLEX | NV_FORCE_FULL_DUPLEX |
121 NV_USER_SPEED_100);
122 break;
123
124 default:
125 break;
126 }
127
128 QueryInteger(ConfigurationHandle,
129 L"ChecksumOffload",
130 &GenericUlong,
131 0,
132 0,
133 1);
134 if (GenericUlong)
135 Adapter->Flags |= NV_SEND_CHECKSUM;
136
137 QueryInteger(ConfigurationHandle,
138 L"LargeSendOffload",
139 &GenericUlong,
140 0,
141 0,
142 1);
143 if (GenericUlong)
144 Adapter->Flags |= NV_SEND_LARGE_SEND;
145
146 QueryInteger(ConfigurationHandle,
147 L"JumboSize",
148 &GenericUlong,
149 NVNET_MAXIMUM_FRAME_SIZE,
150 NVNET_MAXIMUM_FRAME_SIZE,
151 NVNET_MAXIMUM_FRAME_SIZE_JUMBO);
152 Adapter->MaximumFrameSize = GenericUlong;
153
154 QueryInteger(ConfigurationHandle,
155 L"Priority",
156 &GenericUlong,
157 0,
158 0,
159 1);
160 if (GenericUlong)
161 Adapter->Flags |= NV_PACKET_PRIORITY;
162
163 QueryInteger(ConfigurationHandle,
164 L"VlanTag",
165 &GenericUlong,
166 0,
167 0,
168 1);
169 if (GenericUlong)
170 Adapter->Flags |= NV_VLAN_TAGGING;
171
172 QueryInteger(ConfigurationHandle,
173 L"VlanID",
174 &GenericUlong,
175 0,
176 0,
177 NVNET_MAXIMUM_VLAN_ID);
178
179 NdisReadNetworkAddress(&Status,
180 (PVOID*)&NetworkAddress,
181 &Length,
182 ConfigurationHandle);
183 if ((Status == NDIS_STATUS_SUCCESS) && (Length == ETH_LENGTH_OF_ADDRESS))
184 {
185 if ((ETH_IS_MULTICAST(NetworkAddress) || ETH_IS_BROADCAST(NetworkAddress)) ||
186 !ETH_IS_LOCALLY_ADMINISTERED(NetworkAddress))
187 {
188 NDIS_DbgPrint(MAX_TRACE, ("Invalid software MAC: %02x:%02x:%02x:%02x:%02x:%02x\n",
189 NetworkAddress[0],
190 NetworkAddress[1],
191 NetworkAddress[2],
192 NetworkAddress[3],
193 NetworkAddress[4],
194 NetworkAddress[5]));
195 }
196 else
197 {
198 NDIS_DbgPrint(MIN_TRACE, ("Using software MAC\n"));
199
200 ETH_COPY_NETWORK_ADDRESS(Adapter->CurrentMacAddress, NetworkAddress);
201
202 Adapter->Flags |= NV_USE_SOFT_MAC_ADDRESS;
203 }
204 }
205 Status = NDIS_STATUS_SUCCESS;
206
207 NdisCloseConfiguration(ConfigurationHandle);
208
209 return Status;
210 }
211
212 static
213 CODE_SEG("PAGE")
214 NDIS_STATUS
NvNetInitializeAdapterResources(_Inout_ PNVNET_ADAPTER Adapter)215 NvNetInitializeAdapterResources(
216 _Inout_ PNVNET_ADAPTER Adapter)
217 {
218 NDIS_STATUS Status;
219 PNDIS_RESOURCE_LIST AssignedResources = NULL;
220 UINT i, ResourceListSize = 0;
221
222 PAGED_CODE();
223
224 NDIS_DbgPrint(MIN_TRACE, ("()\n"));
225
226 NdisMQueryAdapterResources(&Status,
227 Adapter->WrapperConfigurationHandle,
228 AssignedResources,
229 &ResourceListSize);
230 if (Status != NDIS_STATUS_RESOURCES)
231 {
232 NvNetLogError(Adapter, NDIS_ERROR_CODE_RESOURCE_CONFLICT);
233 return NDIS_STATUS_FAILURE;
234 }
235
236 Status = NdisAllocateMemoryWithTag((PVOID*)&AssignedResources,
237 ResourceListSize,
238 NVNET_TAG);
239 if (Status != NDIS_STATUS_SUCCESS)
240 {
241 NvNetLogError(Adapter, NDIS_ERROR_CODE_OUT_OF_RESOURCES);
242 return Status;
243 }
244
245 NdisMQueryAdapterResources(&Status,
246 Adapter->WrapperConfigurationHandle,
247 AssignedResources,
248 &ResourceListSize);
249 if (Status != NDIS_STATUS_SUCCESS)
250 {
251 NvNetLogError(Adapter, NDIS_ERROR_CODE_RESOURCE_CONFLICT);
252 goto Cleanup;
253 }
254
255 for (i = 0; i < AssignedResources->Count; ++i)
256 {
257 PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor = &AssignedResources->PartialDescriptors[i];
258
259 switch (Descriptor->Type)
260 {
261 case CmResourceTypeMemory:
262 {
263 Adapter->IoAddress = Descriptor->u.Memory.Start;
264 Adapter->IoLength = Descriptor->u.Memory.Length;
265 break;
266 }
267
268 case CmResourceTypeInterrupt:
269 {
270 Adapter->InterruptVector = Descriptor->u.Interrupt.Vector;
271 Adapter->InterruptLevel = Descriptor->u.Interrupt.Level;
272 Adapter->InterruptShared = (Descriptor->ShareDisposition == CmResourceShareShared);
273 Adapter->InterruptFlags = Descriptor->Flags;
274 break;
275 }
276
277 default:
278 break;
279 }
280 }
281
282 if (!Adapter->IoAddress.QuadPart || !Adapter->InterruptVector)
283 {
284 Status = NDIS_STATUS_RESOURCES;
285 NvNetLogError(Adapter, NDIS_ERROR_CODE_RESOURCE_CONFLICT);
286 goto Cleanup;
287 }
288
289 NDIS_DbgPrint(MIN_TRACE, ("MEM at [%I64X-%I64X]\n",
290 Adapter->IoAddress.QuadPart,
291 Adapter->IoAddress.QuadPart + Adapter->IoLength));
292 NDIS_DbgPrint(MIN_TRACE, ("IRQ Vector %d Level %d\n",
293 Adapter->InterruptVector,
294 Adapter->InterruptLevel));
295
296 Status = NdisMMapIoSpace((PVOID*)&Adapter->IoBase,
297 Adapter->AdapterHandle,
298 Adapter->IoAddress,
299 Adapter->IoLength);
300 if (Status != NDIS_STATUS_SUCCESS)
301 {
302 NvNetLogError(Adapter, NDIS_ERROR_CODE_RESOURCE_CONFLICT);
303 goto Cleanup;
304 }
305
306 Cleanup:
307 NdisFreeMemory(AssignedResources, ResourceListSize, 0);
308
309 return Status;
310 }
311
312 static
313 CODE_SEG("PAGE")
314 NDIS_STATUS
AllocateTransmitBuffers(_In_ PNVNET_ADAPTER Adapter)315 AllocateTransmitBuffers(
316 _In_ PNVNET_ADAPTER Adapter)
317 {
318 ULONG i;
319 BOOLEAN HasBuffer = FALSE;
320 PNVNET_TX_BUFFER CoalesceBuffer;
321 NDIS_STATUS Status;
322
323 PAGED_CODE();
324
325 Status = NdisAllocateMemoryWithTag((PVOID*)&CoalesceBuffer,
326 NVNET_TRANSMIT_BUFFERS * sizeof(NVNET_TX_BUFFER),
327 NVNET_TAG);
328 if (Status != NDIS_STATUS_SUCCESS)
329 return Status;
330
331 NdisZeroMemory(CoalesceBuffer, NVNET_TRANSMIT_BUFFERS * sizeof(NVNET_TX_BUFFER));
332
333 Adapter->SendBuffer = CoalesceBuffer;
334
335 for (i = 0; i < NVNET_TRANSMIT_BUFFERS; ++i)
336 {
337 PVOID VirtualAddress;
338 NDIS_PHYSICAL_ADDRESS PhysicalAddress;
339
340 NdisMAllocateSharedMemory(Adapter->AdapterHandle,
341 Adapter->MaximumFrameSize + NVNET_ALIGNMENT,
342 TRUE, /* Cached */
343 &VirtualAddress,
344 &PhysicalAddress);
345 if (!VirtualAddress)
346 continue;
347
348 CoalesceBuffer->VirtualAddress = ALIGN_UP_POINTER_BY(VirtualAddress, NVNET_ALIGNMENT);
349 CoalesceBuffer->PhysicalAddress.QuadPart =
350 ALIGN_UP_BY(PhysicalAddress.QuadPart, NVNET_ALIGNMENT);
351
352 Adapter->SendBufferAllocationData[i].PhysicalAddress.QuadPart = PhysicalAddress.QuadPart;
353 Adapter->SendBufferAllocationData[i].VirtualAddress = VirtualAddress;
354
355 PushEntryList(&Adapter->Send.BufferList, &CoalesceBuffer->Link);
356 ++CoalesceBuffer;
357
358 HasBuffer = TRUE;
359 }
360 if (!HasBuffer)
361 {
362 return NDIS_STATUS_RESOURCES;
363 }
364
365 return NDIS_STATUS_SUCCESS;
366 }
367
368 static
369 CODE_SEG("PAGE")
370 NDIS_STATUS
AllocateTransmitBlocks(_In_ PNVNET_ADAPTER Adapter)371 AllocateTransmitBlocks(
372 _In_ PNVNET_ADAPTER Adapter)
373 {
374 PNVNET_TCB Tcb;
375 NDIS_STATUS Status;
376
377 PAGED_CODE();
378
379 Status = NdisAllocateMemoryWithTag((PVOID*)&Tcb,
380 NVNET_TRANSMIT_BLOCKS * sizeof(NVNET_TCB),
381 NVNET_TAG);
382 if (Status != NDIS_STATUS_SUCCESS)
383 return Status;
384
385 NdisZeroMemory(Tcb, NVNET_TRANSMIT_BLOCKS * sizeof(NVNET_TCB));
386
387 Adapter->Send.TailTcb = Tcb + (NVNET_TRANSMIT_BLOCKS - 1);
388 Adapter->Send.HeadTcb = Tcb;
389 Adapter->Send.CurrentTcb = Tcb;
390 Adapter->Send.LastTcb = Tcb;
391
392 return NDIS_STATUS_SUCCESS;
393 }
394
395 static
396 CODE_SEG("PAGE")
397 NDIS_STATUS
AllocateTransmitDescriptors(_In_ PNVNET_ADAPTER Adapter)398 AllocateTransmitDescriptors(
399 _In_ PNVNET_ADAPTER Adapter)
400 {
401 NVNET_TBD Tbd;
402 ULONG Size;
403
404 PAGED_CODE();
405
406 if (Adapter->Features & DEV_HAS_HIGH_DMA)
407 {
408 Size = sizeof(NVNET_DESCRIPTOR_64);
409 }
410 else
411 {
412 Size = sizeof(NVNET_DESCRIPTOR_32);
413 }
414 NdisMAllocateSharedMemory(Adapter->AdapterHandle,
415 Size * NVNET_TRANSMIT_DESCRIPTORS + NVNET_ALIGNMENT,
416 TRUE, /* Cached */
417 &Adapter->TbdOriginal,
418 &Adapter->TbdPhysOriginal);
419 if (!Adapter->TbdOriginal)
420 return NDIS_STATUS_RESOURCES;
421
422 Tbd.Memory = ALIGN_UP_POINTER_BY(Adapter->TbdOriginal, NVNET_ALIGNMENT);
423 Adapter->TbdPhys.QuadPart = ALIGN_UP_BY(Adapter->TbdPhysOriginal.QuadPart, NVNET_ALIGNMENT);
424
425 Adapter->Send.HeadTbd = Tbd;
426 Adapter->Send.CurrentTbd = Tbd;
427
428 if (Adapter->Features & DEV_HAS_HIGH_DMA)
429 {
430 Adapter->Send.TailTbd.x64 = Tbd.x64 + (NVNET_TRANSMIT_DESCRIPTORS - 1);
431 }
432 else
433 {
434 Adapter->Send.TailTbd.x32 = Tbd.x32 + (NVNET_TRANSMIT_DESCRIPTORS - 1);
435 }
436
437 return NDIS_STATUS_SUCCESS;
438 }
439
440 static
441 CODE_SEG("PAGE")
442 NDIS_STATUS
AllocateReceiveDescriptors(_In_ PNVNET_ADAPTER Adapter)443 AllocateReceiveDescriptors(
444 _In_ PNVNET_ADAPTER Adapter)
445 {
446 ULONG Size;
447
448 PAGED_CODE();
449
450 if (Adapter->Features & DEV_HAS_HIGH_DMA)
451 {
452 Size = sizeof(NVNET_DESCRIPTOR_64);
453 }
454 else
455 {
456 Size = sizeof(NVNET_DESCRIPTOR_32);
457 }
458 NdisMAllocateSharedMemory(Adapter->AdapterHandle,
459 Size * NVNET_RECEIVE_DESCRIPTORS + NVNET_ALIGNMENT,
460 TRUE, /* Cached */
461 &Adapter->RbdOriginal,
462 &Adapter->RbdPhysOriginal);
463 if (!Adapter->RbdOriginal)
464 return NDIS_STATUS_RESOURCES;
465
466 Adapter->Receive.NvRbd.Memory = ALIGN_UP_POINTER_BY(Adapter->RbdOriginal, NVNET_ALIGNMENT);
467 Adapter->RbdPhys.QuadPart = ALIGN_UP_BY(Adapter->RbdPhysOriginal.QuadPart, NVNET_ALIGNMENT);
468
469 return NDIS_STATUS_SUCCESS;
470 }
471
472 static
473 CODE_SEG("PAGE")
474 NDIS_STATUS
AllocateReceiveBuffers(_In_ PNVNET_ADAPTER Adapter)475 AllocateReceiveBuffers(
476 _In_ PNVNET_ADAPTER Adapter)
477 {
478 PAGED_CODE();
479
480 NdisMAllocateSharedMemory(Adapter->AdapterHandle,
481 NVNET_RECEIVE_BUFFER_SIZE * NVNET_RECEIVE_DESCRIPTORS,
482 TRUE, /* Cached */
483 (PVOID*)&Adapter->ReceiveBuffer,
484 &Adapter->ReceiveBufferPhys);
485 if (!Adapter->ReceiveBuffer)
486 {
487 return NDIS_STATUS_RESOURCES;
488 }
489
490 return NDIS_STATUS_SUCCESS;
491 }
492
493 static
494 CODE_SEG("PAGE")
495 NDIS_STATUS
AllocateAdapterMemory(_In_ PNVNET_ADAPTER Adapter)496 AllocateAdapterMemory(
497 _In_ PNVNET_ADAPTER Adapter)
498 {
499 NDIS_STATUS Status;
500
501 PAGED_CODE();
502
503 Status = AllocateTransmitBuffers(Adapter);
504 if (Status != NDIS_STATUS_SUCCESS)
505 return Status;
506
507 Status = AllocateTransmitBlocks(Adapter);
508 if (Status != NDIS_STATUS_SUCCESS)
509 return Status;
510
511 Status = AllocateTransmitDescriptors(Adapter);
512 if (Status != NDIS_STATUS_SUCCESS)
513 return Status;
514
515 Status = AllocateReceiveDescriptors(Adapter);
516 if (Status != NDIS_STATUS_SUCCESS)
517 return Status;
518
519 Status = AllocateReceiveBuffers(Adapter);
520 if (Status != NDIS_STATUS_SUCCESS)
521 return Status;
522
523 NdisAllocateSpinLock(&Adapter->Send.Lock);
524 NdisAllocateSpinLock(&Adapter->Receive.Lock);
525 NdisAllocateSpinLock(&Adapter->Lock);
526
527 return NDIS_STATUS_SUCCESS;
528 }
529
530 CODE_SEG("PAGE")
531 VOID
NvNetInitTransmitMemory(_In_ PNVNET_ADAPTER Adapter)532 NvNetInitTransmitMemory(
533 _In_ PNVNET_ADAPTER Adapter)
534 {
535 PAGED_CODE();
536
537 Adapter->Send.TcbSlots = NVNET_TRANSMIT_BLOCKS;
538 Adapter->Send.TbdSlots = NVNET_TRANSMIT_DESCRIPTORS;
539
540 if (Adapter->Features & DEV_HAS_HIGH_DMA)
541 {
542 NdisZeroMemory(Adapter->Send.HeadTbd.x64,
543 sizeof(NVNET_DESCRIPTOR_64) * NVNET_TRANSMIT_DESCRIPTORS);
544 }
545 else
546 {
547 NdisZeroMemory(Adapter->Send.HeadTbd.x32,
548 sizeof(NVNET_DESCRIPTOR_32) * NVNET_TRANSMIT_DESCRIPTORS);
549 }
550 }
551
552 static
553 CODE_SEG("PAGE")
554 VOID
NvNetInitReceiveMemory(_In_ PNVNET_ADAPTER Adapter)555 NvNetInitReceiveMemory(
556 _In_ PNVNET_ADAPTER Adapter)
557 {
558 NV_RBD NvRbd;
559 ULONG i;
560
561 PAGED_CODE();
562
563 Adapter->CurrentRx = 0;
564
565 if (Adapter->Features & DEV_HAS_HIGH_DMA)
566 {
567 for (i = 0; i < NVNET_RECEIVE_DESCRIPTORS; ++i)
568 {
569 NvRbd.x64 = &Adapter->Receive.NvRbd.x64[i];
570
571 NvRbd.x64->AddressHigh = NdisGetPhysicalAddressHigh(Adapter->ReceiveBufferPhys)
572 + i * NVNET_RECEIVE_BUFFER_SIZE;
573 NvRbd.x64->AddressLow = NdisGetPhysicalAddressLow(Adapter->ReceiveBufferPhys)
574 + i * NVNET_RECEIVE_BUFFER_SIZE;
575 NvRbd.x64->VlanTag = 0;
576 NvRbd.x64->FlagsLength = NV_RX2_AVAIL | NVNET_RECEIVE_BUFFER_SIZE;
577 }
578 }
579 else
580 {
581 for (i = 0; i < NVNET_RECEIVE_DESCRIPTORS; ++i)
582 {
583 NvRbd.x32 = &Adapter->Receive.NvRbd.x32[i];
584
585 NvRbd.x32->Address = NdisGetPhysicalAddressLow(Adapter->ReceiveBufferPhys)
586 + i * NVNET_RECEIVE_BUFFER_SIZE;
587 NvRbd.x32->FlagsLength = NV_RX_AVAIL | NVNET_RECEIVE_BUFFER_SIZE;
588 }
589 }
590 }
591
592
593 CODE_SEG("PAGE")
594 VOID
NvNetFreeAdapter(_In_ PNVNET_ADAPTER Adapter)595 NvNetFreeAdapter(
596 _In_ PNVNET_ADAPTER Adapter)
597 {
598 ULONG i;
599 ULONG DescriptorSize;
600
601 PAGED_CODE();
602
603 NDIS_DbgPrint(MIN_TRACE, ("()\n"));
604
605 for (i = 0; i < RTL_NUMBER_OF(Adapter->WakeFrames); ++i)
606 {
607 PNVNET_WAKE_FRAME WakeFrame = Adapter->WakeFrames[i];
608
609 if (!WakeFrame)
610 continue;
611
612 NdisFreeMemory(WakeFrame, sizeof(*WakeFrame), 0);
613 }
614
615 if (Adapter->Interrupt.InterruptObject)
616 {
617 NdisMDeregisterInterrupt(&Adapter->Interrupt);
618 Adapter->Interrupt.InterruptObject = NULL;
619 }
620
621 if (Adapter->Features & DEV_HAS_HIGH_DMA)
622 {
623 DescriptorSize = sizeof(NVNET_DESCRIPTOR_64);
624 }
625 else
626 {
627 DescriptorSize = sizeof(NVNET_DESCRIPTOR_32);
628 }
629 if (Adapter->TbdOriginal)
630 {
631 NdisMFreeSharedMemory(Adapter->AdapterHandle,
632 DescriptorSize * NVNET_TRANSMIT_DESCRIPTORS,
633 FALSE,
634 Adapter->TbdOriginal,
635 Adapter->TbdPhysOriginal);
636 Adapter->TbdOriginal = NULL;
637 }
638 if (Adapter->RbdOriginal)
639 {
640 NdisMFreeSharedMemory(Adapter->AdapterHandle,
641 DescriptorSize * NVNET_RECEIVE_DESCRIPTORS,
642 FALSE,
643 Adapter->RbdOriginal,
644 Adapter->RbdPhysOriginal);
645 Adapter->RbdOriginal = NULL;
646 }
647 if (Adapter->SendBuffer)
648 {
649 ULONG Length = ALIGN_UP_BY(Adapter->MaximumFrameSize, NVNET_ALIGNMENT);
650
651 for (i = 0; i < NVNET_TRANSMIT_BUFFERS; ++i)
652 {
653 PNVNET_TX_BUFFER_DATA SendBufferData = &Adapter->SendBufferAllocationData[i];
654
655 if (!SendBufferData->VirtualAddress)
656 continue;
657
658 NdisMFreeSharedMemory(Adapter->AdapterHandle,
659 Length,
660 TRUE,
661 SendBufferData->VirtualAddress,
662 SendBufferData->PhysicalAddress);
663 }
664
665 NdisFreeMemory(Adapter->SendBuffer, NVNET_TRANSMIT_BUFFERS * sizeof(NVNET_TX_BUFFER), 0);
666 Adapter->SendBuffer = NULL;
667 }
668
669 if (Adapter->ReceiveBuffer)
670 {
671 NdisMFreeSharedMemory(Adapter->AdapterHandle,
672 NVNET_RECEIVE_BUFFER_SIZE * NVNET_RECEIVE_DESCRIPTORS,
673 FALSE,
674 Adapter->ReceiveBuffer,
675 Adapter->ReceiveBufferPhys);
676 Adapter->ReceiveBuffer = NULL;
677 }
678
679 if (Adapter->IoBase)
680 {
681 NdisMUnmapIoSpace(Adapter->AdapterHandle,
682 Adapter->IoBase,
683 Adapter->IoLength);
684 Adapter->IoBase = NULL;
685 }
686
687 if (Adapter->Lock.SpinLock)
688 NdisFreeSpinLock(&Adapter->Lock);
689 if (Adapter->Send.Lock.SpinLock)
690 NdisFreeSpinLock(&Adapter->Send.Lock);
691 if (Adapter->Receive.Lock.SpinLock)
692 NdisFreeSpinLock(&Adapter->Receive.Lock);
693
694 NdisFreeMemory(Adapter->AdapterOriginal, sizeof(NVNET_ADAPTER), 0);
695 }
696
697 CODE_SEG("PAGE")
698 NDIS_STATUS
699 NTAPI
MiniportInitialize(_Out_ PNDIS_STATUS OpenErrorStatus,_Out_ PUINT SelectedMediumIndex,_In_ PNDIS_MEDIUM MediumArray,_In_ UINT MediumArraySize,_In_ NDIS_HANDLE MiniportAdapterHandle,_In_ NDIS_HANDLE WrapperConfigurationContext)700 MiniportInitialize(
701 _Out_ PNDIS_STATUS OpenErrorStatus,
702 _Out_ PUINT SelectedMediumIndex,
703 _In_ PNDIS_MEDIUM MediumArray,
704 _In_ UINT MediumArraySize,
705 _In_ NDIS_HANDLE MiniportAdapterHandle,
706 _In_ NDIS_HANDLE WrapperConfigurationContext)
707 {
708 UINT i;
709 ULONG Size;
710 PVOID UnalignedAdapter;
711 PNVNET_ADAPTER Adapter;
712 NDIS_STATUS Status;
713
714 PAGED_CODE();
715
716 NDIS_DbgPrint(MIN_TRACE, ("()\n"));
717
718 for (i = 0; i < MediumArraySize; ++i)
719 {
720 if (MediumArray[i] == NdisMedium802_3)
721 {
722 *SelectedMediumIndex = i;
723 break;
724 }
725 }
726 if (i == MediumArraySize)
727 {
728 NDIS_DbgPrint(MAX_TRACE, ("No supported media\n"));
729 return NDIS_STATUS_UNSUPPORTED_MEDIA;
730 }
731
732 Size = sizeof(NVNET_ADAPTER) + NdisGetSharedDataAlignment();
733
734 Status = NdisAllocateMemoryWithTag((PVOID*)&UnalignedAdapter,
735 Size,
736 NVNET_TAG);
737 if (Status != NDIS_STATUS_SUCCESS)
738 {
739 NDIS_DbgPrint(MAX_TRACE, ("Failed to allocate adapter\n"));
740 return NDIS_STATUS_RESOURCES;
741 }
742
743 NdisZeroMemory(UnalignedAdapter, Size);
744 Adapter = ALIGN_UP_POINTER_BY(UnalignedAdapter, NdisGetSharedDataAlignment());
745 Adapter->AdapterOriginal = UnalignedAdapter;
746 Adapter->AdapterHandle = MiniportAdapterHandle;
747 Adapter->WrapperConfigurationHandle = WrapperConfigurationContext;
748
749 Status = NvNetReadConfiguration(Adapter);
750 if (Status != NDIS_STATUS_SUCCESS)
751 {
752 goto Failure;
753 }
754
755 NdisMSetAttributesEx(MiniportAdapterHandle,
756 Adapter,
757 0,
758 NDIS_ATTRIBUTE_USES_SAFE_BUFFER_APIS |
759 // NDIS_ATTRIBUTE_DESERIALIZE | TODO
760 NDIS_ATTRIBUTE_BUS_MASTER,
761 NdisInterfacePci);
762
763 Status = NvNetRecognizeHardware(Adapter);
764 if (Status != NDIS_STATUS_SUCCESS)
765 {
766 if (Status == NDIS_STATUS_ADAPTER_NOT_FOUND)
767 {
768 NvNetLogError(Adapter, NDIS_ERROR_CODE_ADAPTER_NOT_FOUND);
769 }
770 else if (Status == NDIS_STATUS_NOT_RECOGNIZED)
771 {
772 NvNetLogError(Adapter, NDIS_ERROR_CODE_UNSUPPORTED_CONFIGURATION);
773 }
774
775 goto Failure;
776 }
777
778 Status = NvNetInitializeAdapterResources(Adapter);
779 if (Status != NDIS_STATUS_SUCCESS)
780 {
781 goto Failure;
782 }
783
784 Status = NdisMInitializeScatterGatherDma(Adapter->AdapterHandle,
785 !!(Adapter->Features & DEV_HAS_HIGH_DMA),
786 NVNET_MAXIMUM_FRAME_SIZE);
787 // ^TODO: NVNET_MAX_DMA_TRANSFER);
788 if (Status != NDIS_STATUS_SUCCESS)
789 {
790 NvNetLogError(Adapter, NDIS_ERROR_CODE_OUT_OF_RESOURCES);
791 goto Failure;
792 }
793
794 Status = AllocateAdapterMemory(Adapter);
795 if (Status != NDIS_STATUS_SUCCESS)
796 {
797 NDIS_DbgPrint(MAX_TRACE, ("Failed to allocate adapter memory\n"));
798
799 NvNetLogError(Adapter, NDIS_ERROR_CODE_OUT_OF_RESOURCES);
800 goto Failure;
801 }
802
803 NvNetInitTransmitMemory(Adapter);
804 NvNetInitReceiveMemory(Adapter);
805
806 if (Adapter->Features & DEV_HAS_HIGH_DMA)
807 {
808 Adapter->TransmitPacket = NvNetTransmitPacket64;
809 Adapter->ProcessTransmit = ProcessTransmitDescriptors64;
810 }
811 else
812 {
813 Adapter->TransmitPacket = NvNetTransmitPacket32;
814
815 if (Adapter->Features & DEV_HAS_LARGEDESC)
816 {
817 Adapter->ProcessTransmit = ProcessTransmitDescriptors32;
818 }
819 else
820 {
821 Adapter->ProcessTransmit = ProcessTransmitDescriptorsLegacy;
822 }
823 }
824
825 Status = NvNetGetPermanentMacAddress(Adapter, Adapter->PermanentMacAddress);
826 if (Status != NDIS_STATUS_SUCCESS)
827 {
828 NvNetLogError(Adapter, NDIS_ERROR_CODE_NETWORK_ADDRESS);
829 goto Failure;
830 }
831
832 if (!(Adapter->Flags & NV_USE_SOFT_MAC_ADDRESS))
833 {
834 ETH_COPY_NETWORK_ADDRESS(Adapter->CurrentMacAddress,
835 Adapter->PermanentMacAddress);
836 }
837
838 NvNetSetupMacAddress(Adapter, Adapter->CurrentMacAddress);
839
840 Status = NvNetInitNIC(Adapter, TRUE);
841 if (Status != NDIS_STATUS_SUCCESS)
842 {
843 NDIS_DbgPrint(MAX_TRACE, ("Failed to initialize the NIC\n"));
844
845 NvNetLogError(Adapter, NDIS_ERROR_CODE_HARDWARE_FAILURE);
846 goto Failure;
847 }
848
849 NvNetDisableInterrupts(Adapter);
850 NV_WRITE(Adapter, NvRegMIIStatus, NVREG_MIISTAT_MASK_ALL);
851 NV_WRITE(Adapter, NvRegIrqStatus, NVREG_IRQSTAT_MASK);
852
853 /* FIXME: Bug in the PIC HAL? */
854 #if defined(SARCH_XBOX)
855 Status = NdisMRegisterInterrupt(&Adapter->Interrupt,
856 Adapter->AdapterHandle,
857 Adapter->InterruptVector,
858 Adapter->InterruptLevel,
859 TRUE, /* Request ISR calls */
860 FALSE,
861 NdisInterruptLatched);
862 #else
863 Status = NdisMRegisterInterrupt(&Adapter->Interrupt,
864 Adapter->AdapterHandle,
865 Adapter->InterruptVector,
866 Adapter->InterruptLevel,
867 TRUE, /* Request ISR calls */
868 TRUE, /* Shared */
869 NdisInterruptLevelSensitive);
870 #endif
871 if (Status != NDIS_STATUS_SUCCESS)
872 {
873 NvNetLogError(Adapter, NDIS_ERROR_CODE_INTERRUPT_CONNECT);
874 goto Failure;
875 }
876
877 NvNetStartAdapter(Adapter);
878
879 return NDIS_STATUS_SUCCESS;
880
881 Failure:
882 NvNetFreeAdapter(Adapter);
883
884 return Status;
885 }
886