1 /*
2 * PROJECT: ReactOS DC21x4 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 2023 Dmitry Borisov <di.sean@protonmail.com>
6 */
7
8 /* INCLUDES *******************************************************************/
9
10 #include "dc21x4.h"
11
12 #include <debug.h>
13
14 /* GLOBALS ********************************************************************/
15
16 /*
17 * The driver must align the buffers on a 4 byte boundary to meet the hardware requirement.
18 * We stick with cache alignment to get better performance.
19 */
20 C_ASSERT((SYSTEM_CACHE_ALIGNMENT_SIZE % DC_RECEIVE_BUFFER_ALIGNMENT) == 0);
21 C_ASSERT((SYSTEM_CACHE_ALIGNMENT_SIZE % DC_DESCRIPTOR_ALIGNMENT) == 0);
22 C_ASSERT((SYSTEM_CACHE_ALIGNMENT_SIZE % DC_SETUP_FRAME_ALIGNMENT) == 0);
23
24 /* Errata: The end of receive buffer must not fall on a cache boundary */
25 #define DC_RECEIVE_BUFFER_SIZE (DC_RECEIVE_BLOCK_SIZE - 4)
26 C_ASSERT((DC_RECEIVE_BUFFER_SIZE % 32) != 0);
27
28 #define DC_MEM_BLOCK_SIZE_RCB \
29 (DC_RECEIVE_BLOCK_SIZE + SYSTEM_CACHE_ALIGNMENT_SIZE - 1)
30
31 #define DC_MEM_BLOCK_SIZE_RBD \
32 (sizeof(DC_RBD) * DC_RECEIVE_BUFFERS_DEFAULT + SYSTEM_CACHE_ALIGNMENT_SIZE - 1)
33
34 #define DC_MEM_BLOCK_SIZE_TBD_AUX \
35 (sizeof(DC_TBD) * DC_TRANSMIT_DESCRIPTORS + SYSTEM_CACHE_ALIGNMENT_SIZE - 1 + \
36 DC_SETUP_FRAME_SIZE + SYSTEM_CACHE_ALIGNMENT_SIZE - 1 + \
37 DC_LOOPBACK_FRAME_SIZE * DC_LOOPBACK_FRAMES + SYSTEM_CACHE_ALIGNMENT_SIZE - 1)
38
39 #define DC_MEM_BLOCK_SIZE_TX_BUFFER \
40 (DC_TRANSMIT_BLOCK_SIZE + SYSTEM_CACHE_ALIGNMENT_SIZE - 1)
41
42 /* FUNCTIONS ******************************************************************/
43
44 static
45 CODE_SEG("PAGE")
46 VOID
DcConfigQueryInteger(_In_ NDIS_HANDLE ConfigurationHandle,_In_ PCWSTR EntryName,_Out_ PULONG EntryContext,_In_ ULONG DefaultValue,_In_ ULONG Minimum,_In_ ULONG Maximum)47 DcConfigQueryInteger(
48 _In_ NDIS_HANDLE ConfigurationHandle,
49 _In_ PCWSTR EntryName,
50 _Out_ PULONG EntryContext,
51 _In_ ULONG DefaultValue,
52 _In_ ULONG Minimum,
53 _In_ ULONG Maximum)
54 {
55 NDIS_STATUS Status;
56 UNICODE_STRING Keyword;
57 PNDIS_CONFIGURATION_PARAMETER ConfigurationParameter;
58
59 PAGED_CODE();
60
61 NdisInitUnicodeString(&Keyword, EntryName);
62 NdisReadConfiguration(&Status,
63 &ConfigurationParameter,
64 ConfigurationHandle,
65 &Keyword,
66 NdisParameterInteger);
67 if (Status != NDIS_STATUS_SUCCESS)
68 {
69 TRACE("'%S' request failed, default value %u\n", EntryName, DefaultValue);
70
71 *EntryContext = DefaultValue;
72 return;
73 }
74
75 if (ConfigurationParameter->ParameterData.IntegerData >= Minimum &&
76 ConfigurationParameter->ParameterData.IntegerData <= Maximum)
77 {
78 *EntryContext = ConfigurationParameter->ParameterData.IntegerData;
79 }
80 else
81 {
82 WARN("'%S' value out of range\n", EntryName);
83
84 *EntryContext = DefaultValue;
85 }
86
87 TRACE("Set '%S' to %u\n", EntryName, *EntryContext);
88 }
89
90 static
91 CODE_SEG("PAGE")
92 NDIS_STATUS
DcReadConfiguration(_In_ PDC21X4_ADAPTER Adapter)93 DcReadConfiguration(
94 _In_ PDC21X4_ADAPTER Adapter)
95 {
96 NDIS_STATUS Status;
97 NDIS_HANDLE ConfigurationHandle;
98 PUCHAR NetworkAddress;
99 UINT Length;
100 ULONG GenericUlong;
101
102 PAGED_CODE();
103
104 NdisOpenConfiguration(&Status,
105 &ConfigurationHandle,
106 Adapter->WrapperConfigurationHandle);
107 if (Status != NDIS_STATUS_SUCCESS)
108 return Status;
109
110 DcConfigQueryInteger(ConfigurationHandle,
111 L"SpeedDuplex",
112 &GenericUlong,
113 MEDIA_AUTO,
114 MEDIA_10T,
115 MEDIA_HMR);
116 Adapter->DefaultMedia = GenericUlong;
117
118 NdisReadNetworkAddress(&Status,
119 (PVOID*)&NetworkAddress,
120 &Length,
121 ConfigurationHandle);
122 if ((Status == NDIS_STATUS_SUCCESS) && (Length == ETH_LENGTH_OF_ADDRESS))
123 {
124 if (ETH_IS_MULTICAST(NetworkAddress) ||
125 ETH_IS_EMPTY(NetworkAddress) ||
126 ETH_IS_BROADCAST(NetworkAddress) ||
127 !ETH_IS_LOCALLY_ADMINISTERED(NetworkAddress))
128 {
129 ERR("Invalid software MAC address: %02x:%02x:%02x:%02x:%02x:%02x\n",
130 NetworkAddress[0],
131 NetworkAddress[1],
132 NetworkAddress[2],
133 NetworkAddress[3],
134 NetworkAddress[4],
135 NetworkAddress[5]);
136 }
137 else
138 {
139 INFO("Using software MAC address\n");
140
141 /* Override the MAC address */
142 NdisMoveMemory(Adapter->CurrentMacAddress, NetworkAddress, ETH_LENGTH_OF_ADDRESS);
143 }
144 }
145
146 NdisCloseConfiguration(ConfigurationHandle);
147
148 return NDIS_STATUS_SUCCESS;
149 }
150
151 static
152 CODE_SEG("PAGE")
153 VOID
DcFreeRcb(_In_ PDC21X4_ADAPTER Adapter,_In_ __drv_freesMem (Mem)PDC_RCB Rcb)154 DcFreeRcb(
155 _In_ PDC21X4_ADAPTER Adapter,
156 _In_ __drv_freesMem(Mem) PDC_RCB Rcb)
157 {
158 PAGED_CODE();
159
160 if (Rcb->VirtualAddressOriginal)
161 {
162 NdisMFreeSharedMemory(Adapter->AdapterHandle,
163 DC_MEM_BLOCK_SIZE_RCB,
164 TRUE, /* Cached */
165 Rcb->VirtualAddressOriginal,
166 Rcb->PhysicalAddressOriginal);
167 }
168
169 if (Rcb->NdisBuffer)
170 NdisFreeBuffer(Rcb->NdisBuffer);
171 if (Rcb->Packet)
172 NdisFreePacket(Rcb->Packet);
173
174 NdisFreeMemory(Rcb, sizeof(*Rcb), 0);
175 }
176
177 static
178 CODE_SEG("PAGE")
179 PDC_RCB
DcAllocateRcb(_In_ PDC21X4_ADAPTER Adapter)180 DcAllocateRcb(
181 _In_ PDC21X4_ADAPTER Adapter)
182 {
183 NDIS_STATUS Status;
184 PDC_RCB Rcb;
185 PVOID VirtualAddress;
186 NDIS_PHYSICAL_ADDRESS PhysicalAddress;
187
188 PAGED_CODE();
189
190 Status = NdisAllocateMemoryWithTag((PVOID*)&Rcb, sizeof(*Rcb), DC21X4_TAG);
191 if (Status != NDIS_STATUS_SUCCESS)
192 return NULL;
193 NdisZeroMemory(Rcb, sizeof(*Rcb));
194
195 NdisMAllocateSharedMemory(Adapter->AdapterHandle,
196 DC_MEM_BLOCK_SIZE_RCB,
197 TRUE, /* Cached */
198 &VirtualAddress,
199 &PhysicalAddress);
200 if (!VirtualAddress)
201 goto Failure;
202
203 /* 32-bit DMA */
204 ASSERT(PhysicalAddress.HighPart == 0);
205
206 Rcb->VirtualAddress = ALIGN_UP_POINTER_BY(VirtualAddress, SYSTEM_CACHE_ALIGNMENT_SIZE);
207 Rcb->PhysicalAddress = ALIGN_UP_BY(PhysicalAddress.LowPart, SYSTEM_CACHE_ALIGNMENT_SIZE);
208
209 ASSERT((Rcb->PhysicalAddress % DC_RECEIVE_BUFFER_ALIGNMENT) == 0);
210
211 Rcb->VirtualAddressOriginal = VirtualAddress;
212 Rcb->PhysicalAddressOriginal.QuadPart = PhysicalAddress.QuadPart;
213
214 NdisAllocatePacket(&Status, &Rcb->Packet, Adapter->PacketPool);
215 if (Status != NDIS_STATUS_SUCCESS)
216 goto Failure;
217
218 *DC_RCB_FROM_PACKET(Rcb->Packet) = Rcb;
219
220 NdisAllocateBuffer(&Status,
221 &Rcb->NdisBuffer,
222 Adapter->BufferPool,
223 Rcb->VirtualAddress,
224 DC_RECEIVE_BLOCK_SIZE);
225 if (Status != NDIS_STATUS_SUCCESS)
226 goto Failure;
227
228 NDIS_SET_PACKET_HEADER_SIZE(Rcb->Packet, DC_ETHERNET_HEADER_SIZE);
229 NdisChainBufferAtFront(Rcb->Packet, Rcb->NdisBuffer);
230
231 PushEntryList(&Adapter->AllocRcbList, &Rcb->AllocListEntry);
232
233 return Rcb;
234
235 Failure:
236 DcFreeRcb(Adapter, Rcb);
237
238 return NULL;
239 }
240
241 static
242 CODE_SEG("PAGE")
243 NDIS_STATUS
DcAllocateReceiveBuffers(_In_ PDC21X4_ADAPTER Adapter)244 DcAllocateReceiveBuffers(
245 _In_ PDC21X4_ADAPTER Adapter)
246 {
247 ULONG i;
248 NDIS_STATUS Status;
249 PDC_RCB Rcb;
250
251 PAGED_CODE();
252
253 NdisAllocatePacketPool(&Status,
254 &Adapter->PacketPool,
255 DC_RECEIVE_BUFFERS_DEFAULT + DC_RECEIVE_BUFFERS_EXTRA,
256 PROTOCOL_RESERVED_SIZE_IN_PACKET);
257 if (Status != NDIS_STATUS_SUCCESS)
258 return Status;
259
260 NdisAllocateBufferPool(&Status,
261 &Adapter->BufferPool,
262 DC_RECEIVE_BUFFERS_DEFAULT + DC_RECEIVE_BUFFERS_EXTRA);
263 if (Status != NDIS_STATUS_SUCCESS)
264 return Status;
265
266 /* Allocate RCBs */
267 for (i = 0; i < DC_RECEIVE_BUFFERS_DEFAULT; ++i)
268 {
269 Rcb = DcAllocateRcb(Adapter);
270 if (!Rcb)
271 {
272 WARN("RCB allocation failed, total buffers %u\n", Adapter->RcbCount);
273 break;
274 }
275
276 PushEntryList(&Adapter->UsedRcbList, &Rcb->ListEntry);
277
278 ++Adapter->RcbCount;
279 }
280
281 if (Adapter->RcbCount < DC_RECEIVE_BUFFERS_MIN)
282 return NDIS_STATUS_RESOURCES;
283
284 Adapter->RcbFree = Adapter->RcbCount;
285
286 /* Fix up the ring size */
287 Adapter->TailRbd = Adapter->HeadRbd + Adapter->RcbCount - 1;
288
289 /* Allocate extra RCBs for receive indication */
290 for (i = 0; i < DC_RECEIVE_BUFFERS_EXTRA; ++i)
291 {
292 Rcb = DcAllocateRcb(Adapter);
293 if (!Rcb)
294 {
295 WARN("Extra RCB allocation failed\n");
296 break;
297 }
298
299 PushEntryList(&Adapter->FreeRcbList, &Rcb->ListEntry);
300 }
301
302 Status = NdisAllocateMemoryWithTag((PVOID*)&Adapter->RcbArray,
303 sizeof(PVOID) * Adapter->RcbCount,
304 DC21X4_TAG);
305 if (Status != NDIS_STATUS_SUCCESS)
306 return Status;
307
308 return NDIS_STATUS_SUCCESS;
309 }
310
311 static
312 CODE_SEG("PAGE")
313 NDIS_STATUS
DcAllocateReceiveDescriptors(_In_ PDC21X4_ADAPTER Adapter)314 DcAllocateReceiveDescriptors(
315 _In_ PDC21X4_ADAPTER Adapter)
316 {
317 PDC_RBD Rbd;
318
319 PAGED_CODE();
320
321 NdisMAllocateSharedMemory(Adapter->AdapterHandle,
322 DC_MEM_BLOCK_SIZE_RBD,
323 FALSE, /* Non-cached */
324 &Adapter->RbdOriginal,
325 &Adapter->RbdPhysOriginal);
326 if (!Adapter->RbdOriginal)
327 return NDIS_STATUS_RESOURCES;
328
329 /* 32-bit DMA */
330 ASSERT(Adapter->RbdPhysOriginal.HighPart == 0);
331
332 Adapter->RbdPhys = ALIGN_UP_BY(Adapter->RbdPhysOriginal.LowPart, SYSTEM_CACHE_ALIGNMENT_SIZE);
333
334 ASSERT((Adapter->RbdPhys % DC_DESCRIPTOR_ALIGNMENT) == 0);
335
336 Rbd = ALIGN_UP_POINTER_BY(Adapter->RbdOriginal, SYSTEM_CACHE_ALIGNMENT_SIZE);
337
338 Adapter->HeadRbd = Rbd;
339
340 return NDIS_STATUS_SUCCESS;
341 }
342
343 static
344 CODE_SEG("PAGE")
345 NDIS_STATUS
DcAllocateTransmitBlocks(_In_ PDC21X4_ADAPTER Adapter)346 DcAllocateTransmitBlocks(
347 _In_ PDC21X4_ADAPTER Adapter)
348 {
349 PDC_TCB Tcb;
350 NDIS_STATUS Status;
351
352 PAGED_CODE();
353
354 Status = NdisAllocateMemoryWithTag((PVOID*)&Tcb,
355 DC_TRANSMIT_BLOCKS * sizeof(*Tcb),
356 DC21X4_TAG);
357 if (Status != NDIS_STATUS_SUCCESS)
358 return Status;
359
360 NdisZeroMemory(Tcb, DC_TRANSMIT_BLOCKS * sizeof(*Tcb));
361
362 Adapter->HeadTcb = Tcb;
363 Adapter->TailTcb = Tcb + (DC_TRANSMIT_BLOCKS - 1);
364
365 return NDIS_STATUS_SUCCESS;
366 }
367
368 static
369 CODE_SEG("PAGE")
370 NDIS_STATUS
DcAllocateTransmitDescriptorsAndBuffers(_In_ PDC21X4_ADAPTER Adapter)371 DcAllocateTransmitDescriptorsAndBuffers(
372 _In_ PDC21X4_ADAPTER Adapter)
373 {
374 ULONG_PTR BufferVa, BufferPa;
375 NDIS_STATUS Status;
376 ULONG i;
377
378 PAGED_CODE();
379
380 NdisMAllocateSharedMemory(Adapter->AdapterHandle,
381 DC_MEM_BLOCK_SIZE_TBD_AUX,
382 FALSE, /* Non-cached */
383 &Adapter->TbdOriginal,
384 &Adapter->TbdPhysOriginal);
385 if (!Adapter->TbdOriginal)
386 return NDIS_STATUS_RESOURCES;
387
388 /* 32-bit DMA */
389 ASSERT(Adapter->TbdPhysOriginal.HighPart == 0);
390
391 BufferVa = (ULONG_PTR)Adapter->TbdOriginal;
392 BufferPa = Adapter->TbdPhysOriginal.LowPart;
393
394 BufferVa = ALIGN_UP_BY(BufferVa, SYSTEM_CACHE_ALIGNMENT_SIZE);
395 BufferPa = ALIGN_UP_BY(BufferPa, SYSTEM_CACHE_ALIGNMENT_SIZE);
396
397 ASSERT((BufferPa % DC_DESCRIPTOR_ALIGNMENT) == 0);
398
399 Adapter->TbdPhys = (ULONG)BufferPa;
400 Adapter->HeadTbd = (PDC_TBD)BufferVa;
401 Adapter->TailTbd = (PDC_TBD)BufferVa + DC_TRANSMIT_DESCRIPTORS - 1;
402
403 BufferVa += sizeof(DC_TBD) * DC_TRANSMIT_DESCRIPTORS;
404 BufferPa += sizeof(DC_TBD) * DC_TRANSMIT_DESCRIPTORS;
405
406 BufferVa = ALIGN_UP_BY(BufferVa, SYSTEM_CACHE_ALIGNMENT_SIZE);
407 BufferPa = ALIGN_UP_BY(BufferPa, SYSTEM_CACHE_ALIGNMENT_SIZE);
408
409 ASSERT((BufferPa % DC_SETUP_FRAME_ALIGNMENT) == 0);
410
411 Adapter->SetupFrame = (PVOID)BufferVa;
412 Adapter->SetupFramePhys = BufferPa;
413
414 BufferVa += DC_SETUP_FRAME_SIZE;
415 BufferPa += DC_SETUP_FRAME_SIZE;
416
417 BufferVa = ALIGN_UP_BY(BufferVa, SYSTEM_CACHE_ALIGNMENT_SIZE);
418 BufferPa = ALIGN_UP_BY(BufferPa, SYSTEM_CACHE_ALIGNMENT_SIZE);
419
420 for (i = 0; i < DC_LOOPBACK_FRAMES; ++i)
421 {
422 Adapter->LoopbackFrame[i] = (PVOID)BufferVa;
423 Adapter->LoopbackFramePhys[i] = BufferPa;
424
425 BufferVa += DC_LOOPBACK_FRAME_SIZE;
426 BufferPa += DC_LOOPBACK_FRAME_SIZE;
427 }
428
429 if (Adapter->Features & DC_HAS_POWER_MANAGEMENT)
430 {
431 Status = NdisAllocateMemoryWithTag((PVOID*)&Adapter->SetupFrameSaved,
432 DC_SETUP_FRAME_SIZE,
433 DC21X4_TAG);
434 if (Status != NDIS_STATUS_SUCCESS)
435 return Status;
436 }
437
438 return NDIS_STATUS_SUCCESS;
439 }
440
441 static
442 CODE_SEG("PAGE")
443 NDIS_STATUS
DcAllocateTransmitBuffers(_In_ PDC21X4_ADAPTER Adapter)444 DcAllocateTransmitBuffers(
445 _In_ PDC21X4_ADAPTER Adapter)
446 {
447 PDC_COALESCE_BUFFER CoalesceBuffer;
448 NDIS_STATUS Status;
449 ULONG i;
450
451 PAGED_CODE();
452
453 Status = NdisAllocateMemoryWithTag((PVOID*)&CoalesceBuffer,
454 DC_TRANSMIT_BUFFERS * sizeof(*CoalesceBuffer),
455 DC21X4_TAG);
456 if (Status != NDIS_STATUS_SUCCESS)
457 return Status;
458
459 NdisZeroMemory(CoalesceBuffer, DC_TRANSMIT_BUFFERS * sizeof(*CoalesceBuffer));
460
461 Adapter->CoalesceBuffer = CoalesceBuffer;
462
463 for (i = 0; i < DC_TRANSMIT_BUFFERS; ++i)
464 {
465 PVOID VirtualAddress;
466 NDIS_PHYSICAL_ADDRESS PhysicalAddress;
467
468 NdisMAllocateSharedMemory(Adapter->AdapterHandle,
469 DC_MEM_BLOCK_SIZE_TX_BUFFER,
470 FALSE, /* Non-cached */
471 &VirtualAddress,
472 &PhysicalAddress);
473 if (!VirtualAddress)
474 continue;
475
476 ASSERT(PhysicalAddress.HighPart == 0);
477
478 CoalesceBuffer->VirtualAddress =
479 ALIGN_UP_POINTER_BY(VirtualAddress, SYSTEM_CACHE_ALIGNMENT_SIZE);
480 CoalesceBuffer->PhysicalAddress =
481 ALIGN_UP_BY(PhysicalAddress.LowPart, SYSTEM_CACHE_ALIGNMENT_SIZE);
482
483 Adapter->SendBufferData[i].PhysicalAddress.QuadPart = PhysicalAddress.QuadPart;
484 Adapter->SendBufferData[i].VirtualAddress = VirtualAddress;
485
486 PushEntryList(&Adapter->SendBufferList, &CoalesceBuffer->ListEntry);
487
488 ++CoalesceBuffer;
489 }
490
491 if (!Adapter->SendBufferList.Next)
492 return NDIS_STATUS_RESOURCES;
493
494 return NDIS_STATUS_SUCCESS;
495 }
496
497 CODE_SEG("PAGE")
498 VOID
DcInitTxRing(_In_ PDC21X4_ADAPTER Adapter)499 DcInitTxRing(
500 _In_ PDC21X4_ADAPTER Adapter)
501 {
502 PDC_TCB Tcb;
503 PDC_TBD Tbd;
504
505 PAGED_CODE();
506
507 InitializeListHead(&Adapter->SendQueueList);
508
509 Tcb = Adapter->HeadTcb;
510
511 Adapter->CurrentTcb = Tcb;
512 Adapter->LastTcb = Tcb;
513
514 Adapter->TcbSlots = DC_TRANSMIT_BLOCKS - DC_TCB_RESERVE;
515 Adapter->TbdSlots = DC_TRANSMIT_DESCRIPTORS - DC_TBD_RESERVE;
516 Adapter->LoopbackFrameSlots = DC_LOOPBACK_FRAMES;
517 Adapter->TcbCompleted = 0;
518
519 Tbd = Adapter->HeadTbd;
520 Adapter->CurrentTbd = Tbd;
521
522 NdisZeroMemory(Tbd, sizeof(*Tbd) * DC_TRANSMIT_DESCRIPTORS);
523
524 Adapter->TailTbd->Control |= DC_TBD_CONTROL_END_OF_RING;
525 }
526
527 static
528 CODE_SEG("PAGE")
529 VOID
DcCreateRxRing(_In_ PDC21X4_ADAPTER Adapter)530 DcCreateRxRing(
531 _In_ PDC21X4_ADAPTER Adapter)
532 {
533 PDC_RCB* RcbSlot;
534 PDC_RCB Rcb;
535 PDC_RBD Rbd;
536 PSINGLE_LIST_ENTRY Entry;
537
538 PAGED_CODE();
539
540 Rbd = Adapter->HeadRbd;
541 Adapter->CurrentRbd = Rbd;
542
543 RcbSlot = DC_GET_RCB_SLOT(Adapter, Rbd);
544 Rcb = (PDC_RCB)Adapter->UsedRcbList.Next;
545
546 for (Entry = Adapter->UsedRcbList.Next;
547 Entry != NULL;
548 Entry = Entry->Next)
549 {
550 Rcb = (PDC_RCB)Entry;
551
552 C_ASSERT((DC_RECEIVE_BUFFER_SIZE % DC_RECEIVE_BUFFER_SIZE_MULTIPLE) == 0);
553
554 Rbd->Address1 = Rcb->PhysicalAddress;
555 Rbd->Address2 = 0;
556 Rbd->Control = DC_RECEIVE_BUFFER_SIZE;
557 Rbd->Status = DC_RBD_STATUS_OWNED;
558
559 *RcbSlot = Rcb;
560
561 ++RcbSlot;
562 ++Rbd;
563 Rcb = (PDC_RCB)Rcb->ListEntry.Next;
564 }
565 Rbd = Rbd - 1;
566 Rbd->Control |= DC_RBD_CONTROL_CHAINED;
567 Rbd->Address2 = Adapter->RbdPhys;
568
569 ASSERT(Rbd == Adapter->TailRbd);
570 }
571
572 CODE_SEG("PAGE")
573 VOID
DcInitRxRing(_In_ PDC21X4_ADAPTER Adapter)574 DcInitRxRing(
575 _In_ PDC21X4_ADAPTER Adapter)
576 {
577 PDC_RBD Rbd;
578 ULONG i;
579
580 PAGED_CODE();
581
582 Rbd = Adapter->HeadRbd;
583 Adapter->CurrentRbd = Rbd;
584
585 for (i = 0; i < Adapter->RcbCount; ++i)
586 {
587 Rbd->Control = DC_RECEIVE_BUFFER_SIZE;
588 Rbd->Status = DC_RBD_STATUS_OWNED;
589
590 ++Rbd;
591 }
592 Rbd = Rbd - 1;
593 Rbd->Control |= DC_RBD_CONTROL_CHAINED;
594
595 ASSERT(Rbd == Adapter->TailRbd);
596 }
597
598 static
599 CODE_SEG("PAGE")
600 NDIS_STATUS
DcAllocateMemory(_In_ PDC21X4_ADAPTER Adapter)601 DcAllocateMemory(
602 _In_ PDC21X4_ADAPTER Adapter)
603 {
604 NDIS_STATUS Status;
605
606 PAGED_CODE();
607
608 Status = NdisMInitializeScatterGatherDma(Adapter->AdapterHandle,
609 FALSE, /* 32-bit DMA */
610 DC_TRANSMIT_BLOCK_SIZE);
611 if (Status != NDIS_STATUS_SUCCESS)
612 return Status;
613
614 Status = DcAllocateReceiveDescriptors(Adapter);
615 if (Status != NDIS_STATUS_SUCCESS)
616 return Status;
617
618 Status = DcAllocateTransmitBlocks(Adapter);
619 if (Status != NDIS_STATUS_SUCCESS)
620 return Status;
621
622 Status = DcAllocateTransmitBuffers(Adapter);
623 if (Status != NDIS_STATUS_SUCCESS)
624 return Status;
625
626 Status = DcAllocateTransmitDescriptorsAndBuffers(Adapter);
627 if (Status != NDIS_STATUS_SUCCESS)
628 return Status;
629
630 Status = DcAllocateReceiveBuffers(Adapter);
631 if (Status != NDIS_STATUS_SUCCESS)
632 return Status;
633
634 NdisAllocateSpinLock(&Adapter->SendLock);
635 NdisAllocateSpinLock(&Adapter->ReceiveLock);
636 NdisAllocateSpinLock(&Adapter->ModeLock);
637
638 return NDIS_STATUS_SUCCESS;
639 }
640
641 static
642 CODE_SEG("PAGE")
643 VOID
DcInitTestPacket(_In_ PDC21X4_ADAPTER Adapter)644 DcInitTestPacket(
645 _In_ PDC21X4_ADAPTER Adapter)
646 {
647 ULONG i;
648
649 PAGED_CODE();
650
651 for (i = 0; i < DC_LOOPBACK_FRAMES; ++i)
652 {
653 PETH_HEADER PacketBuffer = Adapter->LoopbackFrame[i];
654
655 NdisZeroMemory(PacketBuffer, DC_LOOPBACK_FRAME_SIZE);
656
657 /* Destination MAC address */
658 NdisMoveMemory(PacketBuffer->Destination,
659 Adapter->CurrentMacAddress,
660 ETH_LENGTH_OF_ADDRESS);
661
662 /* Source MAC address */
663 NdisMoveMemory(PacketBuffer->Source,
664 Adapter->CurrentMacAddress,
665 ETH_LENGTH_OF_ADDRESS);
666
667 ++PacketBuffer;
668 }
669 }
670
671 static
672 CODE_SEG("PAGE")
673 NDIS_STATUS
DcInitializeAdapterResources(_In_ PDC21X4_ADAPTER Adapter)674 DcInitializeAdapterResources(
675 _In_ PDC21X4_ADAPTER Adapter)
676 {
677 NDIS_STATUS Status;
678 PNDIS_RESOURCE_LIST AssignedResources = NULL;
679 PCM_PARTIAL_RESOURCE_DESCRIPTOR IoDescriptor = NULL;
680 PCM_PARTIAL_RESOURCE_DESCRIPTOR InterruptDescriptor = NULL;
681 UINT i, ResourceListSize = 0;
682
683 PAGED_CODE();
684
685 NdisMQueryAdapterResources(&Status,
686 Adapter->WrapperConfigurationHandle,
687 AssignedResources,
688 &ResourceListSize);
689 if (Status != NDIS_STATUS_RESOURCES)
690 return NDIS_STATUS_FAILURE;
691
692 Status = NdisAllocateMemoryWithTag((PVOID*)&AssignedResources,
693 ResourceListSize,
694 DC21X4_TAG);
695 if (Status != NDIS_STATUS_SUCCESS)
696 return Status;
697
698 NdisMQueryAdapterResources(&Status,
699 Adapter->WrapperConfigurationHandle,
700 AssignedResources,
701 &ResourceListSize);
702 if (Status != NDIS_STATUS_SUCCESS)
703 goto Cleanup;
704
705 for (i = 0; i < AssignedResources->Count; ++i)
706 {
707 PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor;
708
709 Descriptor = &AssignedResources->PartialDescriptors[i];
710 switch (Descriptor->Type)
711 {
712 case CmResourceTypePort:
713 case CmResourceTypeMemory:
714 {
715 if (!IoDescriptor && (Descriptor->u.Port.Length == DC_IO_LENGTH))
716 IoDescriptor = Descriptor;
717 break;
718 }
719
720 case CmResourceTypeInterrupt:
721 {
722 if (!InterruptDescriptor)
723 InterruptDescriptor = Descriptor;
724 break;
725 }
726
727 default:
728 break;
729 }
730 }
731
732 if (!IoDescriptor || !InterruptDescriptor)
733 {
734 Status = NDIS_STATUS_RESOURCES;
735 goto Cleanup;
736 }
737
738 Adapter->InterruptVector = InterruptDescriptor->u.Interrupt.Vector;
739 Adapter->InterruptLevel = InterruptDescriptor->u.Interrupt.Level;
740 Adapter->InterruptFlags = InterruptDescriptor->Flags;
741 if (InterruptDescriptor->ShareDisposition == CmResourceShareShared)
742 Adapter->Flags |= DC_IRQ_SHARED;
743
744 Adapter->IoBaseAddress = IoDescriptor->u.Port.Start;
745
746 if ((IoDescriptor->Type == CmResourceTypePort) &&
747 (IoDescriptor->Flags & CM_RESOURCE_PORT_IO))
748 {
749 Status = NdisMRegisterIoPortRange((PVOID*)&Adapter->IoBase,
750 Adapter->AdapterHandle,
751 Adapter->IoBaseAddress.LowPart,
752 DC_IO_LENGTH);
753 }
754 else
755 {
756 Status = NdisMMapIoSpace((PVOID*)&Adapter->IoBase,
757 Adapter->AdapterHandle,
758 Adapter->IoBaseAddress,
759 DC_IO_LENGTH);
760
761 Adapter->Flags |= DC_IO_MAPPED;
762 }
763 if (Status != NDIS_STATUS_SUCCESS)
764 goto Cleanup;
765
766 INFO("IO Base %p\n", Adapter->IoBase);
767 INFO("IRQ Level %u, Vector %u\n",
768 Adapter->InterruptLevel,
769 Adapter->InterruptVector);
770 INFO("IRQ ShareDisposition %u, InterruptFlags %lx\n",
771 InterruptDescriptor->ShareDisposition,
772 InterruptDescriptor->Flags);
773
774 Cleanup:
775 NdisFreeMemory(AssignedResources, ResourceListSize, 0);
776
777 return Status;
778 }
779
780 static
781 CODE_SEG("PAGE")
782 NDIS_STATUS
DcInitializeAdapterLocation(_In_ PDC21X4_ADAPTER Adapter)783 DcInitializeAdapterLocation(
784 _In_ PDC21X4_ADAPTER Adapter)
785 {
786 PDEVICE_OBJECT Pdo;
787 NTSTATUS Status;
788 ULONG PropertyValue, Length;
789
790 PAGED_CODE();
791
792 NdisMGetDeviceProperty(Adapter->AdapterHandle,
793 &Pdo,
794 NULL,
795 NULL,
796 NULL,
797 NULL);
798
799 Status = IoGetDeviceProperty(Pdo,
800 DevicePropertyAddress,
801 sizeof(PropertyValue),
802 &PropertyValue,
803 &Length);
804 if (!NT_SUCCESS(Status))
805 return NDIS_STATUS_FAILURE;
806
807 /* We need this for PCI devices only ((DeviceNumber << 16) | Function) */
808 Adapter->DeviceNumber = (PropertyValue >> 16) & 0x000000FF;
809
810 Status = IoGetDeviceProperty(Pdo,
811 DevicePropertyBusNumber,
812 sizeof(PropertyValue),
813 &Adapter->BusNumber,
814 &Length);
815 if (!NT_SUCCESS(Status))
816 return NDIS_STATUS_FAILURE;
817
818 return NDIS_STATUS_SUCCESS;
819 }
820
821 static
822 CODE_SEG("PAGE")
823 ULONG
DcGetBusModeParameters(_In_ PDC21X4_ADAPTER Adapter,_In_ PPCI_COMMON_CONFIG PciData)824 DcGetBusModeParameters(
825 _In_ PDC21X4_ADAPTER Adapter,
826 _In_ PPCI_COMMON_CONFIG PciData)
827 {
828 ULONG DefaultMode, NewMode;
829
830 PAGED_CODE();
831
832 /* TODO: Other architectures than x86 */
833 DefaultMode = DC_BUS_MODE_CACHE_ALIGNMENT_16 | DC_BUS_MODE_BURST_LENGTH_NO_LIMIT;
834
835 if (!(Adapter->Features & DC_ENABLE_PCI_COMMANDS))
836 return DefaultMode;
837
838 INFO("PCI Cache Line Size %u\n", PciData->CacheLineSize * 4);
839 INFO("PCI Command %04lx\n", PciData->Command);
840
841 /* Use the cache line size if it was set up by firmware */
842 switch (PciData->CacheLineSize)
843 {
844 case 8:
845 NewMode = DC_BUS_MODE_CACHE_ALIGNMENT_8 | DC_BUS_MODE_BURST_LENGTH_8;
846 break;
847 case 16:
848 NewMode = DC_BUS_MODE_CACHE_ALIGNMENT_16 | DC_BUS_MODE_BURST_LENGTH_16;
849 break;
850 case 32:
851 NewMode = DC_BUS_MODE_CACHE_ALIGNMENT_32 | DC_BUS_MODE_BURST_LENGTH_32;
852 break;
853
854 default:
855 return DefaultMode;
856 }
857
858 /* Enable one of those commands */
859 if (PciData->Command & PCI_ENABLE_WRITE_AND_INVALIDATE)
860 {
861 NewMode |= DC_BUS_MODE_WRITE_INVALIDATE;
862 }
863 else
864 {
865 NewMode |= DC_BUS_MODE_READ_LINE;
866 }
867
868 return NewMode;
869 }
870
871 static
872 CODE_SEG("PAGE")
873 NDIS_STATUS
DcRecognizeHardware(_In_ PDC21X4_ADAPTER Adapter)874 DcRecognizeHardware(
875 _In_ PDC21X4_ADAPTER Adapter)
876 {
877 UCHAR Buffer[RTL_SIZEOF_THROUGH_FIELD(PCI_COMMON_CONFIG, CacheLineSize)];
878 PPCI_COMMON_CONFIG PciConfig = (PPCI_COMMON_CONFIG)Buffer; // Partial PCI header
879 PNDIS_TIMER_FUNCTION MediaMonitorRoutine;
880 ULONG Bytes;
881
882 PAGED_CODE();
883
884 Bytes = NdisReadPciSlotInformation(Adapter->AdapterHandle,
885 0,
886 FIELD_OFFSET(PCI_COMMON_CONFIG, VendorID),
887 Buffer,
888 sizeof(Buffer));
889 if (Bytes != sizeof(Buffer))
890 return NDIS_STATUS_FAILURE;
891
892 Adapter->DeviceId = PciConfig->DeviceID;
893 Adapter->RevisionId = PciConfig->RevisionID;
894
895 switch ((PciConfig->DeviceID << 16) | PciConfig->VendorID)
896 {
897 case DC_DEV_DECCHIP_21040:
898 {
899 Adapter->ChipType = DC21040;
900 Adapter->InterruptMask = DC_GENERIC_IRQ_MASK | DC_IRQ_LINK_FAIL;
901 Adapter->LinkStateChangeMask = DC_IRQ_LINK_FAIL;
902 Adapter->HandleLinkStateChange = MediaLinkStateChange21040;
903 MediaMonitorRoutine = MediaMonitor21040Dpc;
904 break;
905 }
906
907 case DC_DEV_DECCHIP_21041:
908 {
909 Adapter->ChipType = DC21041;
910 Adapter->Features |= DC_HAS_POWER_SAVING | DC_HAS_TIMER;
911 Adapter->InterruptMask = DC_GENERIC_IRQ_MASK | DC_IRQ_LINK_PASS | DC_IRQ_LINK_FAIL;
912 Adapter->LinkStateChangeMask = DC_IRQ_LINK_PASS | DC_IRQ_LINK_FAIL;
913 Adapter->HandleLinkStateChange = MediaLinkStateChange21041;
914 MediaMonitorRoutine = MediaMonitor21041Dpc;
915 break;
916 }
917
918 case DC_DEV_DECCHIP_21140:
919 {
920 Adapter->ChipType = DC21140;
921 Adapter->Features |= DC_HAS_TIMER;
922
923 if ((PciConfig->RevisionID & 0xF0) < 0x20)
924 {
925 /* 21140 */
926 Adapter->Features |= DC_PERFECT_FILTERING_ONLY;
927 }
928 else
929 {
930 /* 21140A */
931 Adapter->Features |= DC_NEED_RX_OVERFLOW_WORKAROUND | DC_ENABLE_PCI_COMMANDS |
932 DC_HAS_POWER_SAVING;
933 }
934
935 Adapter->OpMode |= DC_OPMODE_PORT_ALWAYS;
936 Adapter->InterruptMask = DC_GENERIC_IRQ_MASK;
937 MediaMonitorRoutine = MediaMonitor21140Dpc;
938 break;
939 }
940
941 case DC_DEV_INTEL_21143:
942 {
943 Adapter->Features |= DC_NEED_RX_OVERFLOW_WORKAROUND | DC_SIA_GPIO |
944 DC_HAS_POWER_SAVING | DC_MII_AUTOSENSE | DC_HAS_TIMER;
945
946 Adapter->InterruptMask = DC_GENERIC_IRQ_MASK | DC_IRQ_LINK_PASS | DC_IRQ_LINK_FAIL;
947 Adapter->LinkStateChangeMask = DC_IRQ_LINK_PASS | DC_IRQ_LINK_FAIL;
948
949 Adapter->ChipType = DC21143;
950
951 if ((PciConfig->RevisionID & 0xF0) < 0x20)
952 {
953 /* 21142 */
954 }
955 else
956 {
957 /* 21143 */
958 Adapter->Features |= DC_ENABLE_PCI_COMMANDS;
959 Adapter->OpMode |= DC_OPMODE_PORT_ALWAYS;
960 Adapter->InterruptMask |= DC_IRQ_LINK_CHANGED;
961 Adapter->LinkStateChangeMask |= DC_IRQ_LINK_CHANGED;
962 }
963
964 /* 21143 -PD and -TD */
965 if ((PciConfig->RevisionID & 0xF0) > 0x30)
966 Adapter->Features |= DC_HAS_POWER_MANAGEMENT;
967
968 Adapter->HandleLinkStateChange = MediaLinkStateChange21143;
969 MediaMonitorRoutine = MediaMonitor21143Dpc;
970 break;
971 }
972
973 case DC_DEV_INTEL_21145:
974 {
975 Adapter->ChipType = DC21145;
976
977 Adapter->Features |= DC_NEED_RX_OVERFLOW_WORKAROUND | DC_SIA_GPIO |
978 DC_HAS_POWER_MANAGEMENT | DC_HAS_POWER_SAVING |
979 DC_SIA_ANALOG_CONTROL | DC_ENABLE_PCI_COMMANDS |
980 DC_MII_AUTOSENSE | DC_HAS_TIMER;
981
982 Adapter->OpMode |= DC_OPMODE_PORT_ALWAYS;
983 Adapter->InterruptMask = DC_GENERIC_IRQ_MASK | DC_IRQ_LINK_CHANGED |
984 DC_IRQ_LINK_PASS | DC_IRQ_LINK_FAIL;
985 Adapter->LinkStateChangeMask = DC_IRQ_LINK_CHANGED |
986 DC_IRQ_LINK_PASS | DC_IRQ_LINK_FAIL;
987 Adapter->HandleLinkStateChange = MediaLinkStateChange21143;
988 MediaMonitorRoutine = MediaMonitor21143Dpc;
989
990 Adapter->AnalogControl = DC_HPNA_ANALOG_CTRL;
991
992 /* Workaround for internal RX errata */
993 Adapter->HpnaRegister[HPNA_NOISE_FLOOR] = 0x10;
994 Adapter->HpnaInitBitmap = (1 << HPNA_NOISE_FLOOR);
995 break;
996 }
997
998 default:
999 return NDIS_STATUS_NOT_RECOGNIZED;
1000 }
1001
1002 Adapter->BusMode = DcGetBusModeParameters(Adapter, PciConfig);
1003
1004 INFO("Bus Mode %08lx\n", Adapter->BusMode);
1005
1006 /* Errata: hash filtering is broken on some chips */
1007 if (Adapter->Features & DC_PERFECT_FILTERING_ONLY)
1008 Adapter->MulticastMaxEntries = DC_SETUP_FRAME_ADDRESSES;
1009 else
1010 Adapter->MulticastMaxEntries = DC_MULTICAST_LIST_SIZE;
1011
1012 NdisMInitializeTimer(&Adapter->MediaMonitorTimer,
1013 Adapter->AdapterHandle,
1014 MediaMonitorRoutine,
1015 Adapter);
1016
1017 return NDIS_STATUS_SUCCESS;
1018 }
1019
1020 CODE_SEG("PAGE")
1021 VOID
DcFreeAdapter(_In_ __drv_freesMem (Mem)PDC21X4_ADAPTER Adapter)1022 DcFreeAdapter(
1023 _In_ __drv_freesMem(Mem) PDC21X4_ADAPTER Adapter)
1024 {
1025 ULONG i;
1026
1027 PAGED_CODE();
1028
1029 DcFreeEeprom(Adapter);
1030
1031 if (Adapter->Interrupt.InterruptObject)
1032 {
1033 NdisMDeregisterInterrupt(&Adapter->Interrupt);
1034 }
1035
1036 if (Adapter->IoBase)
1037 {
1038 if (Adapter->Flags & DC_IO_MAPPED)
1039 {
1040 NdisMUnmapIoSpace(Adapter->AdapterHandle,
1041 Adapter->IoBase,
1042 DC_IO_LENGTH);
1043 }
1044 else
1045 {
1046 NdisMDeregisterIoPortRange(Adapter->AdapterHandle,
1047 Adapter->IoBaseAddress.LowPart,
1048 DC_IO_LENGTH,
1049 Adapter->IoBase);
1050 }
1051 }
1052
1053 if (Adapter->HeadTcb)
1054 {
1055 NdisFreeMemory(Adapter->HeadTcb, sizeof(DC_TCB) * DC_TRANSMIT_BLOCKS, 0);
1056 }
1057 if (Adapter->RcbArray)
1058 {
1059 NdisFreeMemory(Adapter->RcbArray, sizeof(PVOID) * Adapter->RcbCount, 0);
1060 }
1061 if (Adapter->SetupFrameSaved)
1062 {
1063 NdisFreeMemory(Adapter->SetupFrameSaved, DC_SETUP_FRAME_SIZE, 0);
1064 }
1065
1066 while (Adapter->AllocRcbList.Next)
1067 {
1068 PSINGLE_LIST_ENTRY Entry = PopEntryList(&Adapter->AllocRcbList);
1069 PDC_RCB Rcb = CONTAINING_RECORD(Entry, DC_RCB, AllocListEntry);
1070
1071 DcFreeRcb(Adapter, Rcb);
1072 }
1073
1074 if (Adapter->RbdOriginal)
1075 {
1076 NdisMFreeSharedMemory(Adapter->AdapterHandle,
1077 DC_MEM_BLOCK_SIZE_RBD,
1078 FALSE, /* Non-cached */
1079 Adapter->RbdOriginal,
1080 Adapter->RbdPhysOriginal);
1081 }
1082 if (Adapter->TbdOriginal)
1083 {
1084 NdisMFreeSharedMemory(Adapter->AdapterHandle,
1085 DC_MEM_BLOCK_SIZE_TBD_AUX,
1086 FALSE, /* Non-cached */
1087 Adapter->TbdOriginal,
1088 Adapter->TbdPhysOriginal);
1089 }
1090 if (Adapter->CoalesceBuffer)
1091 {
1092 for (i = 0; i < DC_TRANSMIT_BUFFERS; ++i)
1093 {
1094 PDC_TX_BUFFER_DATA SendBufferData = &Adapter->SendBufferData[i];
1095
1096 if (!SendBufferData->VirtualAddress)
1097 continue;
1098
1099 NdisMFreeSharedMemory(Adapter->AdapterHandle,
1100 DC_MEM_BLOCK_SIZE_TX_BUFFER,
1101 FALSE, /* Non-cached */
1102 SendBufferData->VirtualAddress,
1103 SendBufferData->PhysicalAddress);
1104 }
1105 }
1106
1107 if (Adapter->PacketPool)
1108 NdisFreePacketPool(Adapter->PacketPool);
1109 if (Adapter->BufferPool)
1110 NdisFreeBufferPool(Adapter->BufferPool);
1111
1112 if (Adapter->SendLock.SpinLock)
1113 NdisFreeSpinLock(&Adapter->SendLock);
1114 if (Adapter->ReceiveLock.SpinLock)
1115 NdisFreeSpinLock(&Adapter->ReceiveLock);
1116 if (Adapter->ModeLock.SpinLock)
1117 NdisFreeSpinLock(&Adapter->ModeLock);
1118
1119 NdisFreeMemory(Adapter->AdapterOriginal, sizeof(*Adapter), 0);
1120 }
1121
1122 CODE_SEG("PAGE")
1123 NDIS_STATUS
1124 NTAPI
DcInitialize(_Out_ PNDIS_STATUS OpenErrorStatus,_Out_ PUINT SelectedMediumIndex,_In_ PNDIS_MEDIUM MediumArray,_In_ UINT MediumArraySize,_In_ NDIS_HANDLE MiniportAdapterHandle,_In_ NDIS_HANDLE WrapperConfigurationContext)1125 DcInitialize(
1126 _Out_ PNDIS_STATUS OpenErrorStatus,
1127 _Out_ PUINT SelectedMediumIndex,
1128 _In_ PNDIS_MEDIUM MediumArray,
1129 _In_ UINT MediumArraySize,
1130 _In_ NDIS_HANDLE MiniportAdapterHandle,
1131 _In_ NDIS_HANDLE WrapperConfigurationContext)
1132 {
1133 PDC21X4_ADAPTER Adapter;
1134 PVOID UnalignedAdapter;
1135 NDIS_STATUS Status;
1136 ULONG Alignment, AdapterSize, OpMode;
1137 BOOLEAN Success;
1138 UINT i;
1139
1140 INFO("Called\n");
1141
1142 PAGED_CODE();
1143
1144 for (i = 0; i < MediumArraySize; ++i)
1145 {
1146 if (MediumArray[i] == NdisMedium802_3)
1147 {
1148 *SelectedMediumIndex = i;
1149 break;
1150 }
1151 }
1152 if (i == MediumArraySize)
1153 {
1154 ERR("No supported media\n");
1155 return NDIS_STATUS_UNSUPPORTED_MEDIA;
1156 }
1157
1158 Alignment = NdisGetSharedDataAlignment();
1159 AdapterSize = sizeof(*Adapter) + Alignment;
1160
1161 Status = NdisAllocateMemoryWithTag((PVOID*)&UnalignedAdapter, AdapterSize, DC21X4_TAG);
1162 if (Status != NDIS_STATUS_SUCCESS)
1163 {
1164 ERR("Failed to allocate adapter context\n");
1165 return NDIS_STATUS_RESOURCES;
1166 }
1167 NdisZeroMemory(UnalignedAdapter, AdapterSize);
1168
1169 Adapter = ALIGN_UP_POINTER_BY(UnalignedAdapter, Alignment);
1170 Adapter->AdapterOriginal = UnalignedAdapter;
1171 Adapter->AdapterSize = AdapterSize;
1172 Adapter->AdapterHandle = MiniportAdapterHandle;
1173 Adapter->WrapperConfigurationHandle = WrapperConfigurationContext;
1174
1175 NdisInitializeWorkItem(&Adapter->ResetWorkItem, DcResetWorker, Adapter);
1176 NdisInitializeWorkItem(&Adapter->PowerWorkItem, DcPowerWorker, Adapter);
1177 NdisInitializeWorkItem(&Adapter->TxRecoveryWorkItem, DcTransmitTimeoutRecoveryWorker, Adapter);
1178
1179 NdisMSetAttributesEx(MiniportAdapterHandle,
1180 Adapter,
1181 2, /* CheckForHangTimeInSeconds */
1182 NDIS_ATTRIBUTE_BUS_MASTER |
1183 NDIS_ATTRIBUTE_DESERIALIZE |
1184 NDIS_ATTRIBUTE_USES_SAFE_BUFFER_APIS,
1185 NdisInterfacePci);
1186
1187 Status = DcRecognizeHardware(Adapter);
1188 if (Status != NDIS_STATUS_SUCCESS)
1189 {
1190 return Status;
1191 }
1192
1193 Status = DcInitializeAdapterResources(Adapter);
1194 if (Status != NDIS_STATUS_SUCCESS)
1195 {
1196 goto Failure;
1197 }
1198
1199 Status = DcInitializeAdapterLocation(Adapter);
1200 if (Status != NDIS_STATUS_SUCCESS)
1201 {
1202 goto Failure;
1203 }
1204
1205 /* Bring the chip out of sleep mode */
1206 DcPowerSave(Adapter, FALSE);
1207
1208 OpMode = DC_READ(Adapter, DcCsr6_OpMode);
1209 OpMode &= ~(DC_OPMODE_RX_ENABLE | DC_OPMODE_TX_ENABLE);
1210 DC_WRITE(Adapter, DcCsr6_OpMode, OpMode);
1211
1212 MediaInitMediaList(Adapter);
1213
1214 Status = DcReadEeprom(Adapter);
1215 if (Status != NDIS_STATUS_SUCCESS)
1216 {
1217 goto Failure;
1218 }
1219
1220 NdisMoveMemory(Adapter->CurrentMacAddress, Adapter->PermanentMacAddress, ETH_LENGTH_OF_ADDRESS);
1221
1222 Status = DcReadConfiguration(Adapter);
1223 if (Status != NDIS_STATUS_SUCCESS)
1224 {
1225 goto Failure;
1226 }
1227
1228 Status = DcAllocateMemory(Adapter);
1229 if (Status != NDIS_STATUS_SUCCESS)
1230 {
1231 goto Failure;
1232 }
1233
1234 DcInitTestPacket(Adapter);
1235
1236 DcCreateRxRing(Adapter);
1237
1238 /* Execute the reset sequence */
1239 if (Adapter->ResetStreamLength)
1240 {
1241 for (i = 0; i < Adapter->ResetStreamLength; ++i)
1242 {
1243 DcWriteGpio(Adapter, Adapter->ResetStream[i]);
1244 NdisMSleep(100);
1245 }
1246
1247 /* Give the PHY some time to reset */
1248 NdisMSleep(5000);
1249 }
1250
1251 /* Perform a software reset */
1252 DC_WRITE(Adapter, DcCsr0_BusMode, DC_BUS_MODE_SOFT_RESET);
1253 NdisMSleep(100);
1254 DC_WRITE(Adapter, DcCsr0_BusMode, Adapter->BusMode);
1255
1256 /* Try to detect a MII PHY */
1257 if (Adapter->Features & DC_HAS_MII)
1258 {
1259 MediaSelectMiiPort(Adapter, TRUE);
1260
1261 Success = DcFindMiiPhy(Adapter);
1262 if (Success)
1263 {
1264 /* Disable all link interrupts when the MII PHY media is found */
1265 Adapter->InterruptMask &= ~(DC_IRQ_LINK_CHANGED | DC_IRQ_LINK_FAIL | DC_IRQ_LINK_PASS);
1266 Adapter->LinkStateChangeMask = 0;
1267 }
1268 else
1269 {
1270 /* Incorrect EEPROM table or PHY is not connected, switch to a serial transceiver */
1271 WARN("No PHY devices found\n");
1272 Adapter->Features &= ~DC_HAS_MII;
1273 }
1274 }
1275
1276 MediaInitDefaultMedia(Adapter, Adapter->DefaultMedia);
1277
1278 /* Set the MAC address */
1279 DcSetupFrameInitialize(Adapter);
1280
1281 /* Clear statistics */
1282 DC_READ(Adapter, DcCsr8_RxCounters);
1283
1284 Adapter->Flags |= DC_FIRST_SETUP;
1285
1286 Status = DcSetupAdapter(Adapter);
1287 if (Status != NDIS_STATUS_SUCCESS)
1288 {
1289 ERR("Failed to initialize the NIC\n");
1290 goto Disable;
1291 }
1292
1293 Adapter->Flags &= ~DC_FIRST_SETUP;
1294
1295 Status = NdisMRegisterInterrupt(&Adapter->Interrupt,
1296 Adapter->AdapterHandle,
1297 Adapter->InterruptVector,
1298 Adapter->InterruptLevel,
1299 TRUE, /* Request ISR calls */
1300 !!(Adapter->Flags & DC_IRQ_SHARED),
1301 (Adapter->InterruptFlags & CM_RESOURCE_INTERRUPT_LATCHED) ?
1302 NdisInterruptLatched : NdisInterruptLevelSensitive);
1303 if (Status != NDIS_STATUS_SUCCESS)
1304 {
1305 ERR("Unable to register interrupt\n");
1306 goto Disable;
1307 }
1308
1309 DcStartAdapter(Adapter);
1310
1311 return NDIS_STATUS_SUCCESS;
1312
1313 Disable:
1314 DcDisableHw(Adapter);
1315 Failure:
1316 ERR("Initialization failed with status %08lx\n", Status);
1317
1318 DcFreeAdapter(Adapter);
1319
1320 return Status;
1321 }
1322