1 /*
2 * PROJECT: ReactOS DC21x4 Driver
3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4 * PURPOSE: Main header file
5 * COPYRIGHT: Copyright 2023 Dmitry Borisov <di.sean@protonmail.com>
6 */
7
8 #pragma once
9
10 #if !DBG
11 #define NO_KERNEL_LIST_ENTRY_CHECKS
12 #endif
13 #include <ndis.h>
14 #include <section_attribs.h>
15
16 #include "dc21x4hw.h"
17 #include "eeprom.h"
18 #include "media.h"
19 #include "util.h"
20
21 #define DC21X4_TAG '4x12'
22
23 #define DC_TRANSMIT_DESCRIPTORS 64
24 #define DC_TRANSMIT_BLOCKS 48
25 #define DC_TRANSMIT_BUFFERS 4
26 #define DC_LOOPBACK_FRAMES 4
27
28 #define DC_RECEIVE_BUFFERS_DEFAULT 64
29 #define DC_RECEIVE_BUFFERS_MIN 8
30 #define DC_RECEIVE_BUFFERS_EXTRA 16
31
32 #define DC_RECEIVE_ARRAY_SIZE 16
33
34 #define DC_MULTICAST_LIST_SIZE 36
35
36 #define DC_MAXIMUM_FRAME_SIZE 1514
37 #define DC_TRANSMIT_BLOCK_SIZE 1536
38 #define DC_RECEIVE_BLOCK_SIZE 1536
39 #define DC_ETHERNET_HEADER_SIZE 14
40
41 #define DC_TX_UNDERRUN_LIMIT 5
42 #define DC_INTERRUPT_PROCESSING_LIMIT 8
43
44 #define DC_FRAGMENTATION_THRESHOLD 32
45
46 #define DC_PACKET_FILTERS ( \
47 NDIS_PACKET_TYPE_DIRECTED | \
48 NDIS_PACKET_TYPE_MULTICAST | \
49 NDIS_PACKET_TYPE_BROADCAST | \
50 NDIS_PACKET_TYPE_PROMISCUOUS | \
51 NDIS_PACKET_TYPE_ALL_MULTICAST)
52
53 #define DC_LOOPBACK_FRAME_SIZE 64
54
55 /* Transmit descriptors reserved for internal use */
56 #define DC_TBD_RESERVE (2 + DC_LOOPBACK_FRAMES) /* (+2 for setup frame) */
57 #define DC_TCB_RESERVE (1 + DC_LOOPBACK_FRAMES) /* (+1 for setup frame) */
58
59 #define DC_EVENT_SETUP_FRAME_COMPLETED 0x00000001
60
61 typedef struct _DC21X4_ADAPTER DC21X4_ADAPTER, *PDC21X4_ADAPTER;
62 typedef struct _DC_TCB DC_TCB, *PDC_TCB;
63 typedef struct _DC_RCB DC_RCB, *PDC_RCB;
64 typedef struct _DC_COALESCE_BUFFER DC_COALESCE_BUFFER, *PDC_COALESCE_BUFFER;
65
66 typedef VOID
67 (MEDIA_HANDLE_LINK_STATE_CHANGE)(
68 _In_ PDC21X4_ADAPTER Adapter,
69 _In_ ULONG InterruptStatus);
70 typedef MEDIA_HANDLE_LINK_STATE_CHANGE *PMEDIA_HANDLE_LINK_STATE_CHANGE;
71
72 typedef struct _DC_TX_BUFFER_DATA
73 {
74 PVOID VirtualAddress;
75 NDIS_PHYSICAL_ADDRESS PhysicalAddress;
76 } DC_TX_BUFFER_DATA, *PDC_TX_BUFFER_DATA;
77
78 typedef struct _DC_STATISTICS
79 {
80 ULONG64 TransmitOk;
81 ULONG64 TransmitDeferred;
82 ULONG64 TransmitHeartbeatErrors;
83 ULONG64 TransmitOneRetry;
84 ULONG64 TransmitMoreCollisions;
85 ULONG64 TransmitErrors;
86 ULONG64 TransmitExcessiveCollisions;
87 ULONG64 TransmitUnderrunErrors;
88 ULONG64 TransmitLostCarrierSense;
89 ULONG64 TransmitLateCollisions;
90 ULONG64 ReceiveOk;
91 ULONG64 ReceiveBroadcast;
92 ULONG64 ReceiveMulticast;
93 ULONG64 ReceiveUnicast;
94 ULONG64 ReceiveErrors;
95 ULONG64 ReceiveOverrunErrors;
96 ULONG64 ReceiveNoBuffers;
97 ULONG64 ReceiveCrcErrors;
98 ULONG64 ReceiveAlignmentErrors;
99 } DC_STATISTICS, *PDC_STATISTICS;
100
101 typedef struct _DC21X4_ADAPTER
102 {
103 PUCHAR IoBase;
104 ULONG InterruptMask;
105 ULONG CurrentInterruptMask;
106
107 ULONG Features;
108 #define DC_NEED_RX_OVERFLOW_WORKAROUND 0x80000000
109 #define DC_SIA_GPIO 0x00000001
110 #define DC_SIA_ANALOG_CONTROL 0x00000002
111 #define DC_HAS_POWER_MANAGEMENT 0x00000004
112 #define DC_HAS_POWER_SAVING 0x00000008
113 #define DC_HAS_MII 0x00000010
114 #define DC_PERFECT_FILTERING_ONLY 0x00000020
115 #define DC_ENABLE_PCI_COMMANDS 0x00000040
116 #define DC_MII_AUTOSENSE 0x00000080
117 #define DC_HAS_TIMER 0x00000100
118
119 ULONG Flags;
120 #define DC_ACTIVE 0x80000000
121 #define DC_IO_MAPPED 0x00000001
122 #define DC_IRQ_SHARED 0x00000002
123 #define DC_FIRST_SETUP 0x00000004
124 #define DC_AUTOSENSE 0x00000008
125
126 ULONG InterruptStatus;
127 PMEDIA_HANDLE_LINK_STATE_CHANGE HandleLinkStateChange;
128
129 DECLSPEC_CACHEALIGN NDIS_SPIN_LOCK SendLock;
130 PDC_TCB TailTcb;
131 PDC_TCB LastTcb;
132 PDC_TCB CurrentTcb;
133 PDC_TBD CurrentTbd;
134 PDC_TBD HeadTbd;
135 PDC_TBD TailTbd;
136 LIST_ENTRY SendQueueList;
137 ULONG TcbSlots;
138 ULONG TbdSlots;
139 ULONG TcbCompleted;
140 ULONG LastTcbCompleted;
141 PDC_TCB HeadTcb;
142 SINGLE_LIST_ENTRY SendBufferList;
143 SCATTER_GATHER_LIST LocalSgList;
144
145 DECLSPEC_CACHEALIGN NDIS_SPIN_LOCK ReceiveLock;
146 PDC_RCB* RcbArray;
147 PDC_RBD CurrentRbd;
148 PDC_RBD HeadRbd;
149 PDC_RBD TailRbd;
150 SINGLE_LIST_ENTRY FreeRcbList;
151 ULONG RcbFree;
152
153 ULONG TransmitUnderruns;
154 ULONG PacketFilter;
155
156 DC_STATISTICS Statistics;
157
158 NDIS_HANDLE AdapterHandle;
159 NDIS_HANDLE WrapperConfigurationHandle;
160
161 DECLSPEC_CACHEALIGN NDIS_SPIN_LOCK ModeLock;
162 ULONG ModeFlags;
163 #define DC_MODE_AUTONEG_MASK 0x0000000F
164 #define DC_MODE_PORT_AUTOSENSE 0x00000010
165 #define DC_MODE_TEST_PACKET 0x00000020
166 #define DC_MODE_AUI_FAILED 0x00000040
167 #define DC_MODE_BNC_FAILED 0x00000080
168
169 #define DC_MODE_AUTONEG_NONE 0x00000000
170 #define DC_MODE_AUTONEG_WAIT_INTERRUPT 0x00000001
171 #define DC_MODE_AUTONEG_LINK_STATUS_CHECK 0x00000002
172
173 ULONG OpMode;
174 ULONG MediaNumber;
175 ULONG MediaBitmap;
176 BOOLEAN LinkUp;
177 ULONG PhyAddress;
178 ULONG SiaSetting;
179 ULONG LastReceiveActivity;
180 volatile LONG MediaTestStatus;
181 NDIS_MINIPORT_TIMER MediaMonitorTimer;
182 DC_MII_MEDIA MiiMedia;
183 DC_MEDIA Media[MEDIA_LIST_MAX];
184
185 ULONG AnalogControl;
186 ULONG SymAdvertising;
187 ULONG MiiAdvertising;
188 ULONG MiiControl;
189 DC_CHIP_TYPE ChipType;
190 ULONG LinkStateChangeMask;
191
192 ULONG WakeUpFlags;
193 NDIS_DEVICE_POWER_STATE PowerState;
194 NDIS_DEVICE_POWER_STATE PrevPowerState;
195
196 ULONG HpnaInitBitmap;
197 UCHAR HpnaRegister[32];
198
199 UCHAR PermanentMacAddress[ETH_LENGTH_OF_ADDRESS];
200 UCHAR CurrentMacAddress[ETH_LENGTH_OF_ADDRESS];
201
202 ULONG MulticastMaxEntries;
203 _Field_range_(0, MulticastMaxEntries)
204 ULONG MulticastCount;
205 struct
206 {
207 UCHAR MacAddress[ETH_LENGTH_OF_ADDRESS];
208 } MulticastList[DC_MULTICAST_LIST_SIZE];
209
210 ULONG LinkSpeedMbps;
211 ULONG BusMode;
212 ULONG DefaultMedia;
213 ULONG RcbCount;
214 BOOLEAN OidPending;
215 BOOLEAN ProgramHashPerfectFilter;
216 PULONG SetupFrame;
217 PULONG SetupFrameSaved;
218 ULONG SetupFramePhys;
219 ULONG LoopbackFrameSlots;
220 ULONG LoopbackFrameNumber;
221 ULONG LoopbackFramePhys[DC_LOOPBACK_FRAMES];
222 ULONG BusNumber;
223 UCHAR DeviceNumber;
224 UCHAR RevisionId;
225 UCHAR ControllerIndex;
226 UCHAR ResetStreamLength;
227 USHORT ResetStream[SROM_MAX_STREAM_REGS];
228 USHORT DeviceId;
229 SINGLE_LIST_ENTRY AllocRcbList;
230 SINGLE_LIST_ENTRY UsedRcbList;
231 NDIS_MINIPORT_INTERRUPT Interrupt;
232 ULONG InterruptVector;
233 ULONG InterruptLevel;
234 ULONG InterruptFlags;
235 ULONG AdapterSize;
236 NDIS_WORK_ITEM PowerWorkItem;
237 NDIS_WORK_ITEM ResetWorkItem;
238 NDIS_WORK_ITEM TxRecoveryWorkItem;
239 _Interlocked_ volatile LONG ResetLock;
240 NDIS_PHYSICAL_ADDRESS IoBaseAddress;
241 PDC_SROM_ENTRY SRomEntry;
242 PVOID AdapterOriginal;
243 PVOID TbdOriginal;
244 PVOID RbdOriginal;
245 ULONG TbdPhys;
246 ULONG RbdPhys;
247 NDIS_HANDLE BufferPool;
248 NDIS_HANDLE PacketPool;
249 NDIS_PHYSICAL_ADDRESS TbdPhysOriginal;
250 NDIS_PHYSICAL_ADDRESS RbdPhysOriginal;
251 PVOID LoopbackFrame[DC_LOOPBACK_FRAMES];
252 PDC_COALESCE_BUFFER CoalesceBuffer;
253 DC_TX_BUFFER_DATA SendBufferData[DC_TRANSMIT_BUFFERS];
254 } DC21X4_ADAPTER, *PDC21X4_ADAPTER;
255
256 #include "sendrcv.h"
257
258 extern LIST_ENTRY SRompAdapterList;
259
260 FORCEINLINE
261 ULONG
DC_READ(_In_ PDC21X4_ADAPTER Adapter,_In_ DC_CSR Register)262 DC_READ(
263 _In_ PDC21X4_ADAPTER Adapter,
264 _In_ DC_CSR Register)
265 {
266 ULONG Value;
267
268 NdisRawReadPortUlong((PULONG)(Adapter->IoBase + Register), &Value);
269 return Value;
270 }
271
272 #define DC_WRITE(Adapter, Register, Value) \
273 NdisRawWritePortUlong((PULONG)((Adapter)->IoBase + (Register)), (Value));
274
275 CODE_SEG("INIT")
276 DRIVER_INITIALIZE DriverEntry;
277
278 CODE_SEG("PAGE")
279 NDIS_STATUS
280 NTAPI
281 DcInitialize(
282 _Out_ PNDIS_STATUS OpenErrorStatus,
283 _Out_ PUINT SelectedMediumIndex,
284 _In_ PNDIS_MEDIUM MediumArray,
285 _In_ UINT MediumArraySize,
286 _In_ NDIS_HANDLE MiniportAdapterHandle,
287 _In_ NDIS_HANDLE WrapperConfigurationContext);
288
289 VOID
290 NTAPI
291 DcSendPackets(
292 _In_ NDIS_HANDLE MiniportAdapterContext,
293 _In_ PPNDIS_PACKET PacketArray,
294 _In_ UINT NumberOfPackets);
295
296 VOID
297 NTAPI
298 DcCancelSendPackets(
299 _In_ NDIS_HANDLE MiniportAdapterContext,
300 _In_ PVOID CancelId);
301
302 VOID
303 DcProcessPendingPackets(
304 _In_ PDC21X4_ADAPTER Adapter);
305
306 VOID
307 NTAPI
308 DcReturnPacket(
309 _In_ NDIS_HANDLE MiniportAdapterContext,
310 _In_ PNDIS_PACKET Packet);
311
312 NDIS_STATUS
313 NTAPI
314 DcQueryInformation(
315 _In_ NDIS_HANDLE MiniportAdapterContext,
316 _In_ NDIS_OID Oid,
317 _In_ PVOID InformationBuffer,
318 _In_ ULONG InformationBufferLength,
319 _Out_ PULONG BytesWritten,
320 _Out_ PULONG BytesNeeded);
321
322 NDIS_STATUS
323 NTAPI
324 DcSetInformation(
325 _In_ NDIS_HANDLE MiniportAdapterContext,
326 _In_ NDIS_OID Oid,
327 _In_ PVOID InformationBuffer,
328 _In_ ULONG InformationBufferLength,
329 _Out_ PULONG BytesRead,
330 _Out_ PULONG BytesNeeded);
331
332 VOID
333 NTAPI
334 DcIsr(
335 _Out_ PBOOLEAN InterruptRecognized,
336 _Out_ PBOOLEAN QueueMiniportHandleInterrupt,
337 _In_ NDIS_HANDLE MiniportAdapterContext);
338
339 VOID
340 NTAPI
341 DcHandleInterrupt(
342 _In_ NDIS_HANDLE MiniportAdapterContext);
343
344 CODE_SEG("PAGE")
345 VOID
346 NTAPI
347 DcPowerWorker(
348 _In_ PNDIS_WORK_ITEM WorkItem,
349 _In_opt_ PVOID Context);
350
351 NDIS_STATUS
352 DcSetPower(
353 _In_ PDC21X4_ADAPTER Adapter,
354 _In_ NDIS_DEVICE_POWER_STATE PowerState);
355
356 NDIS_STATUS
357 DcAddWakeUpPattern(
358 _In_ PDC21X4_ADAPTER Adapter,
359 _In_ PNDIS_PM_PACKET_PATTERN PmPattern);
360
361 NDIS_STATUS
362 DcRemoveWakeUpPattern(
363 _In_ PDC21X4_ADAPTER Adapter,
364 _In_ PNDIS_PM_PACKET_PATTERN PmPattern);
365
366 CODE_SEG("PAGE")
367 VOID
368 DcFreeAdapter(
369 _In_ __drv_freesMem(Mem) PDC21X4_ADAPTER Adapter);
370
371 CODE_SEG("PAGE")
372 VOID
373 NTAPI
374 DcResetWorker(
375 _In_ PNDIS_WORK_ITEM WorkItem,
376 _In_opt_ PVOID Context);
377
378 DECLSPEC_NOINLINE
379 VOID
380 DcStopAdapter(
381 _In_ PDC21X4_ADAPTER Adapter,
382 _In_ BOOLEAN WaitForPackets);
383
384 CODE_SEG("PAGE")
385 VOID
386 DcStartAdapter(
387 _In_ PDC21X4_ADAPTER Adapter);
388
389 CODE_SEG("PAGE")
390 NDIS_STATUS
391 DcSetupAdapter(
392 _In_ PDC21X4_ADAPTER Adapter);
393
394 CODE_SEG("PAGE")
395 NDIS_STATUS
396 DcReadEeprom(
397 _In_ PDC21X4_ADAPTER Adapter);
398
399 CODE_SEG("PAGE")
400 VOID
401 DcFreeEeprom(
402 _In_ PDC21X4_ADAPTER Adapter);
403
404 CODE_SEG("PAGE")
405 VOID
406 DcInitTxRing(
407 _In_ PDC21X4_ADAPTER Adapter);
408
409 CODE_SEG("PAGE")
410 VOID
411 DcInitRxRing(
412 _In_ PDC21X4_ADAPTER Adapter);
413
414 ULONG
415 DcEthernetCrc(
416 _In_reads_bytes_(Size) const VOID* Buffer,
417 _In_ ULONG Size);
418
419 VOID
420 DcDisableHw(
421 _In_ PDC21X4_ADAPTER Adapter);
422
423 VOID
424 DcStopTxRxProcess(
425 _In_ PDC21X4_ADAPTER Adapter);
426
427 VOID
428 DcWriteGpio(
429 _In_ PDC21X4_ADAPTER Adapter,
430 _In_ ULONG Value);
431
432 VOID
433 DcWriteSia(
434 _In_ PDC21X4_ADAPTER Adapter,
435 _In_ ULONG Csr13,
436 _In_ ULONG Csr14,
437 _In_ ULONG Csr15);
438
439 VOID
440 DcTestPacket(
441 _In_ PDC21X4_ADAPTER Adapter);
442
443 CODE_SEG("PAGE")
444 VOID
445 DcSetupFrameInitialize(
446 _In_ PDC21X4_ADAPTER Adapter);
447
448 BOOLEAN
449 DcSetupFrameDownload(
450 _In_ PDC21X4_ADAPTER Adapter,
451 _In_ BOOLEAN WaitForCompletion);
452
453 NDIS_STATUS
454 DcApplyPacketFilter(
455 _In_ PDC21X4_ADAPTER Adapter,
456 _In_ ULONG PacketFilter);
457
458 NDIS_STATUS
459 DcUpdateMulticastList(
460 _In_ PDC21X4_ADAPTER Adapter);
461
462 VOID
463 DcPowerSave(
464 _In_ PDC21X4_ADAPTER Adapter,
465 _In_ BOOLEAN Enable);
466
467 CODE_SEG("PAGE")
468 BOOLEAN
469 DcFindMiiPhy(
470 _In_ PDC21X4_ADAPTER Adapter);
471
472 BOOLEAN
473 MiiWrite(
474 _In_ PDC21X4_ADAPTER Adapter,
475 _In_ ULONG PhyAddress,
476 _In_ ULONG RegAddress,
477 _In_ ULONG Data);
478
479 BOOLEAN
480 MiiRead(
481 _In_ PDC21X4_ADAPTER Adapter,
482 _In_ ULONG PhyAddress,
483 _In_ ULONG RegAddress,
484 _Out_ PULONG Data);
485
486 CODE_SEG("PAGE")
487 VOID
488 HpnaPhyInit(
489 _In_ PDC21X4_ADAPTER Adapter);
490
491 VOID
492 NTAPI
493 DcTransmitTimeoutRecoveryWorker(
494 _In_ PNDIS_WORK_ITEM WorkItem,
495 _In_opt_ PVOID Context);
496
497 NDIS_TIMER_FUNCTION MediaMonitor21040Dpc;
498 NDIS_TIMER_FUNCTION MediaMonitor21041Dpc;
499 NDIS_TIMER_FUNCTION MediaMonitor21140Dpc;
500 NDIS_TIMER_FUNCTION MediaMonitor21143Dpc;
501
502 MEDIA_HANDLE_LINK_STATE_CHANGE MediaLinkStateChange21040;
503 MEDIA_HANDLE_LINK_STATE_CHANGE MediaLinkStateChange21041;
504 MEDIA_HANDLE_LINK_STATE_CHANGE MediaLinkStateChange21143;
505
506 CODE_SEG("PAGE")
507 VOID
508 MediaInitMediaList(
509 _In_ PDC21X4_ADAPTER Adapter);
510
511 CODE_SEG("PAGE")
512 VOID
513 MediaInitDefaultMedia(
514 _In_ PDC21X4_ADAPTER Adapter,
515 _In_ ULONG MediaNumber);
516
517 VOID
518 MediaIndicateConnect(
519 _In_ PDC21X4_ADAPTER Adapter,
520 _In_ BOOLEAN LinkUp);
521
522 VOID
523 MediaSelectMiiPort(
524 _In_ PDC21X4_ADAPTER Adapter,
525 _In_ BOOLEAN ResetPhy);
526
527 VOID
528 MediaMiiSelect(
529 _In_ PDC21X4_ADAPTER Adapter);
530
531 BOOLEAN
532 MediaMiiCheckLink(
533 _In_ PDC21X4_ADAPTER Adapter);
534
535 VOID
536 MediaSiaSelect(
537 _In_ PDC21X4_ADAPTER Adapter);
538
539 VOID
540 MediaGprSelect(
541 _In_ PDC21X4_ADAPTER Adapter);
542