ReactOS 0.4.15-dev-7918-g2a2556c
interrupt.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS Intel PRO/1000 Driver
3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4 * PURPOSE: Interrupt handlers
5 * COPYRIGHT: 2013 Cameron Gutman (cameron.gutman@reactos.org)
6 * 2018 Mark Jansen (mark.jansen@reactos.org)
7 * 2019 Victor Pereertkin (victor.perevertkin@reactos.org)
8 */
9
10#include "nic.h"
11
12#include <debug.h>
13
14VOID
17 OUT PBOOLEAN InterruptRecognized,
18 OUT PBOOLEAN QueueMiniportHandleInterrupt,
19 IN NDIS_HANDLE MiniportAdapterContext)
20{
22 PE1000_ADAPTER Adapter = (PE1000_ADAPTER)MiniportAdapterContext;
23
24 /* Reading the interrupt acknowledges them */
26
27 Value &= Adapter->InterruptMask;
29
30 if (Value)
31 {
32 *InterruptRecognized = TRUE;
33 /* Mark the events pending service */
34 *QueueMiniportHandleInterrupt = TRUE;
35 }
36 else
37 {
38 /* This is not ours. */
39 *InterruptRecognized = FALSE;
40 *QueueMiniportHandleInterrupt = FALSE;
41 }
42}
43
44VOID
47 IN NDIS_HANDLE MiniportAdapterContext)
48{
49 ULONG InterruptPending;
50 PE1000_ADAPTER Adapter = (PE1000_ADAPTER)MiniportAdapterContext;
51 volatile PE1000_TRANSMIT_DESCRIPTOR TransmitDescriptor;
52
53 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
54
55 InterruptPending = _InterlockedExchange(&Adapter->InterruptPending, 0);
56
57
58 /* Link State Changed */
59 if (InterruptPending & E1000_IMS_LSC)
60 {
62
63 InterruptPending &= ~E1000_IMS_LSC;
64 NDIS_DbgPrint(MAX_TRACE, ("Link status changed!.\n"));
65
66 NICUpdateLinkStatus(Adapter);
67
69
72 }
73
74 /* Handling receive interrupts */
75 if (InterruptPending & (E1000_IMS_RXDMT0 | E1000_IMS_RXT0))
76 {
77 volatile PE1000_RECEIVE_DESCRIPTOR ReceiveDescriptor;
78 PETH_HEADER EthHeader;
79 ULONG BufferOffset;
80 BOOLEAN bGotAny = FALSE;
81 ULONG RxDescHead, RxDescTail, CurrRxDesc;
82
83 /* Clear out these interrupts */
84 InterruptPending &= ~(E1000_IMS_RXDMT0 | E1000_IMS_RXT0);
85
86 E1000ReadUlong(Adapter, E1000_REG_RDH, &RxDescHead);
87 E1000ReadUlong(Adapter, E1000_REG_RDT, &RxDescTail);
88
89 while (((RxDescTail + 1) % NUM_RECEIVE_DESCRIPTORS) != RxDescHead)
90 {
91 CurrRxDesc = (RxDescTail + 1) % NUM_RECEIVE_DESCRIPTORS;
92 BufferOffset = CurrRxDesc * Adapter->ReceiveBufferEntrySize;
93 ReceiveDescriptor = Adapter->ReceiveDescriptors + CurrRxDesc;
94
95 /* Check if the hardware have released this descriptor (DD - Descriptor Done) */
96 if (!(ReceiveDescriptor->Status & E1000_RDESC_STATUS_DD))
97 {
98 /* No need to check descriptors after the first unfinished one */
99 break;
100 }
101
102 /* Ignoring these flags for now */
103 ReceiveDescriptor->Status &= ~(E1000_RDESC_STATUS_IXSM | E1000_RDESC_STATUS_PIF);
104
105 if (ReceiveDescriptor->Status != (E1000_RDESC_STATUS_EOP | E1000_RDESC_STATUS_DD))
106 {
107 NDIS_DbgPrint(MIN_TRACE, ("Unrecognized ReceiveDescriptor status flag: %u\n", ReceiveDescriptor->Status));
108 }
109
110 /* Make sure the receive indications are enabled */
111 if (!Adapter->PacketFilter)
112 {
113 goto NextReceiveDescriptor;
114 }
115
116 if (ReceiveDescriptor->Length != 0 && ReceiveDescriptor->Address != 0)
117 {
118 EthHeader = (PETH_HEADER)(Adapter->ReceiveBuffer + BufferOffset);
119
121 NULL,
122 (PCHAR)EthHeader,
123 sizeof(ETH_HEADER),
124 (PCHAR)(EthHeader + 1),
125 ReceiveDescriptor->Length - sizeof(ETH_HEADER),
126 ReceiveDescriptor->Length - sizeof(ETH_HEADER));
127
128 bGotAny = TRUE;
129 }
130 else
131 {
132 NDIS_DbgPrint(MIN_TRACE, ("Got a NULL descriptor"));
133 }
134
135NextReceiveDescriptor:
136 /* Give the descriptor back */
137 ReceiveDescriptor->Status = 0;
138
139 RxDescTail = CurrRxDesc;
140 }
141
142 if (bGotAny)
143 {
144 /* Write back new tail value */
145 E1000WriteUlong(Adapter, E1000_REG_RDT, RxDescTail);
146
147 NDIS_DbgPrint(MAX_TRACE, ("Rx done (RDH: %u, RDT: %u)\n", RxDescHead, RxDescTail));
148
150 }
151 }
152
153 /* Handling transmit interrupts */
154 if (InterruptPending & (E1000_IMS_TXD_LOW | E1000_IMS_TXDW | E1000_IMS_TXQE))
155 {
156 PNDIS_PACKET AckPackets[40] = {0};
157 ULONG NumPackets = 0, i;
158
159 /* Clear out these interrupts */
160 InterruptPending &= ~(E1000_IMS_TXD_LOW | E1000_IMS_TXDW | E1000_IMS_TXQE);
161
162 while ((Adapter->TxFull || Adapter->LastTxDesc != Adapter->CurrentTxDesc) && NumPackets < ARRAYSIZE(AckPackets))
163 {
164 TransmitDescriptor = Adapter->TransmitDescriptors + Adapter->LastTxDesc;
165
166 if (TransmitDescriptor->Status & E1000_TDESC_STATUS_DD)
167 {
168 if (Adapter->TransmitPackets[Adapter->LastTxDesc])
169 {
170 AckPackets[NumPackets++] = Adapter->TransmitPackets[Adapter->LastTxDesc];
171 Adapter->TransmitPackets[Adapter->LastTxDesc] = NULL;
172 TransmitDescriptor->Status = 0;
173 }
174
175 Adapter->LastTxDesc = (Adapter->LastTxDesc + 1) % NUM_TRANSMIT_DESCRIPTORS;
176 Adapter->TxFull = FALSE;
177 }
178 else
179 {
180 break;
181 }
182 }
183
184 if (NumPackets)
185 {
186 NDIS_DbgPrint(MAX_TRACE, ("Tx: (TDH: %u, TDT: %u)\n", Adapter->CurrentTxDesc, Adapter->LastTxDesc));
187 NDIS_DbgPrint(MAX_TRACE, ("Tx Done: %u packets to ack\n", NumPackets));
188
189 for (i = 0; i < NumPackets; ++i)
190 {
192 }
193 }
194 }
195
196 ASSERT(InterruptPending == 0);
197}
unsigned char BOOLEAN
#define MIN_TRACE
Definition: debug.h:14
#define MAX_TRACE
Definition: debug.h:16
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define ARRAYSIZE(array)
Definition: filtermapper.c:47
struct _ETH_HEADER * PETH_HEADER
#define NDIS_DbgPrint(_t_, _x_)
Definition: debug.h:40
VOID NTAPI NICUpdateLinkStatus(IN PE1000_ADAPTER Adapter)
Definition: hardware.c:740
VOID NTAPI MiniportISR(OUT PBOOLEAN InterruptRecognized, OUT PBOOLEAN QueueMiniportHandleInterrupt, IN NDIS_HANDLE MiniportAdapterContext)
Definition: interrupt.c:16
VOID NTAPI MiniportHandleInterrupt(IN NDIS_HANDLE MiniportAdapterContext)
Definition: interrupt.c:46
struct _E1000_ADAPTER * PE1000_ADAPTER
FORCEINLINE VOID E1000ReadUlong(_In_ PE1000_ADAPTER Adapter, _In_ ULONG Address, _Out_ PULONG Value)
Definition: nic.h:209
FORCEINLINE VOID E1000WriteUlong(_In_ PE1000_ADAPTER Adapter, _In_ ULONG Address, _In_ ULONG Value)
Definition: nic.h:219
#define E1000_IMS_RXDMT0
Definition: e1000hw.h:185
#define E1000_RDESC_STATUS_PIF
Definition: e1000hw.h:59
#define E1000_RDESC_STATUS_IXSM
Definition: e1000hw.h:60
#define E1000_IMS_TXQE
Definition: e1000hw.h:183
#define E1000_REG_ICR
Definition: e1000hw.h:119
#define E1000_IMS_LSC
Definition: e1000hw.h:184
#define E1000_RDESC_STATUS_DD
Definition: e1000hw.h:62
#define E1000_IMS_TXD_LOW
Definition: e1000hw.h:187
#define E1000_IMS_TXDW
Definition: e1000hw.h:182
#define E1000_REG_RDH
Definition: e1000hw.h:132
#define E1000_TDESC_STATUS_DD
Definition: e1000hw.h:84
#define NUM_RECEIVE_DESCRIPTORS
Definition: e1000hw.h:109
#define E1000_RDESC_STATUS_EOP
Definition: e1000hw.h:61
#define NUM_TRANSMIT_DESCRIPTORS
Definition: e1000hw.h:108
#define E1000_IMS_RXT0
Definition: e1000hw.h:186
#define E1000_REG_RDT
Definition: e1000hw.h:133
Status
Definition: gdiplustypes.h:25
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
long _InterlockedOr(_Interlocked_operand_ long volatile *_Value, long _Mask)
long __cdecl _InterlockedExchange(_Interlocked_operand_ long volatile *_Target, long _Value)
#define ASSERT(a)
Definition: mode.c:44
#define NDIS_STATUS_MEDIA_CONNECT
Definition: ndis.h:361
#define NdisMEthIndicateReceiveComplete(MiniportAdapterHandle)
Definition: ndis.h:5482
#define NdisMIndicateStatusComplete(MiniportAdapterHandle)
Definition: ndis.h:5580
#define NdisMEthIndicateReceive(MiniportAdapterHandle, MiniportReceiveContext, HeaderBuffer, HeaderBufferSize, LookaheadBuffer, LookaheadBufferSize, PacketSize)
Definition: ndis.h:5458
#define NDIS_STATUS_MEDIA_DISCONNECT
Definition: ndis.h:362
#define NDIS_STATUS_SUCCESS
Definition: ndis.h:346
#define NdisMSendComplete(MiniportAdapterHandle, Packet, Status)
Definition: ndis.h:5689
#define NdisMIndicateStatus(MiniportAdapterHandle, GeneralStatus, StatusBuffer, StatusBufferSize)
Definition: ndis.h:5570
@ NdisMediaStateConnected
Definition: ntddndis.h:470
Definition: lan.h:33
PE1000_RECEIVE_DESCRIPTOR ReceiveDescriptors
Definition: nic.h:85
ULONG LastTxDesc
Definition: nic.h:80
LONG InterruptMask
Definition: nic.h:67
ULONG PacketFilter
Definition: nic.h:51
BOOLEAN TxFull
Definition: nic.h:81
ULONG ReceiveBufferEntrySize
Definition: nic.h:91
PE1000_TRANSMIT_DESCRIPTOR TransmitDescriptors
Definition: nic.h:74
ULONG MediaState
Definition: nic.h:50
PNDIS_PACKET TransmitPackets[NUM_TRANSMIT_DESCRIPTORS]
Definition: nic.h:77
NDIS_HANDLE AdapterHandle
Definition: nic.h:36
_Interlocked_ volatile LONG InterruptPending
Definition: nic.h:70
volatile PUCHAR ReceiveBuffer
Definition: nic.h:89
ULONG CurrentTxDesc
Definition: nic.h:79
unsigned char * PBOOLEAN
Definition: typedefs.h:53
#define NTAPI
Definition: typedefs.h:36
#define IN
Definition: typedefs.h:39
uint32_t ULONG
Definition: typedefs.h:59
#define OUT
Definition: typedefs.h:40
char * PCHAR
Definition: typedefs.h:51
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _Out_opt_ PUSHORT _Inout_opt_ PUNICODE_STRING Value
Definition: wdfregistry.h:413