ReactOS  0.4.15-dev-4869-g35a816a
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 
14 VOID
15 NTAPI
17  OUT PBOOLEAN InterruptRecognized,
18  OUT PBOOLEAN QueueMiniportHandleInterrupt,
19  IN NDIS_HANDLE MiniportAdapterContext)
20 {
21  ULONG Value;
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 
44 VOID
45 NTAPI
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  {
61  ULONG Status;
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 
135 NextReceiveDescriptor:
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  {
191  NdisMSendComplete(Adapter->AdapterHandle, AckPackets[i], NDIS_STATUS_SUCCESS);
192  }
193  }
194  }
195 
196  ASSERT(InterruptPending == 0);
197 }
VOID NTAPI MiniportISR(OUT PBOOLEAN InterruptRecognized, OUT PBOOLEAN QueueMiniportHandleInterrupt, IN NDIS_HANDLE MiniportAdapterContext)
Definition: interrupt.c:16
#define E1000_IMS_RXT0
Definition: e1000hw.h:186
signed char * PCHAR
Definition: retypes.h:7
VOID EXPORT NdisMSendComplete(IN NDIS_HANDLE MiniportAdapterHandle, IN PNDIS_PACKET Packet, IN NDIS_STATUS Status)
Definition: miniport.c:2809
#define IN
Definition: typedefs.h:39
#define E1000_REG_RDH
Definition: e1000hw.h:132
_Interlocked_ volatile LONG InterruptPending
Definition: nic.h:70
NDIS_HANDLE AdapterHandle
Definition: nic.h:36
PE1000_RECEIVE_DESCRIPTOR ReceiveDescriptors
Definition: nic.h:85
#define TRUE
Definition: types.h:120
FORCEINLINE VOID E1000WriteUlong(_In_ PE1000_ADAPTER Adapter, _In_ ULONG Address, _In_ ULONG Value)
Definition: nic.h:219
long __cdecl _InterlockedExchange(_Interlocked_operand_ long volatile *_Target, long _Value)
volatile PUCHAR ReceiveBuffer
Definition: nic.h:89
#define NUM_RECEIVE_DESCRIPTORS
Definition: e1000hw.h:109
#define NdisMEthIndicateReceiveComplete(MiniportAdapterHandle)
Definition: ndis.h:5482
struct _E1000_ADAPTER * PE1000_ADAPTER
#define ARRAYSIZE(array)
Definition: filtermapper.c:47
#define NUM_TRANSMIT_DESCRIPTORS
Definition: e1000hw.h:108
#define E1000_IMS_TXQE
Definition: e1000hw.h:183
#define E1000_REG_RDT
Definition: e1000hw.h:133
ULONG PacketFilter
Definition: nic.h:51
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
#define FALSE
Definition: types.h:117
Definition: lan.h:33
#define E1000_RDESC_STATUS_EOP
Definition: e1000hw.h:61
#define E1000_RDESC_STATUS_DD
Definition: e1000hw.h:62
unsigned char BOOLEAN
VOID NTAPI NICUpdateLinkStatus(IN PE1000_ADAPTER Adapter)
Definition: hardware.c:738
#define E1000_RDESC_STATUS_IXSM
Definition: e1000hw.h:60
VOID EXPORT NdisMIndicateStatusComplete(IN NDIS_HANDLE MiniportAdapterHandle)
Definition: miniport.c:1580
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _Out_opt_ PUSHORT _Inout_opt_ PUNICODE_STRING Value
Definition: wdfregistry.h:406
Status
Definition: gdiplustypes.h:24
#define E1000_REG_ICR
Definition: e1000hw.h:119
ULONG MediaState
Definition: nic.h:50
#define NDIS_STATUS_MEDIA_CONNECT
Definition: ndis.h:361
#define ASSERT(a)
Definition: mode.c:44
#define E1000_IMS_LSC
Definition: e1000hw.h:184
VOID NTAPI MiniportHandleInterrupt(IN NDIS_HANDLE MiniportAdapterContext)
Definition: interrupt.c:46
#define E1000_IMS_RXDMT0
Definition: e1000hw.h:185
struct _ETH_HEADER * PETH_HEADER
ULONG LastTxDesc
Definition: nic.h:80
BOOLEAN TxFull
Definition: nic.h:81
#define NdisMEthIndicateReceive(MiniportAdapterHandle, MiniportReceiveContext, HeaderBuffer, HeaderBufferSize, LookaheadBuffer, LookaheadBufferSize, PacketSize)
Definition: ndis.h:5458
PE1000_TRANSMIT_DESCRIPTOR TransmitDescriptors
Definition: nic.h:74
#define NDIS_STATUS_SUCCESS
Definition: ndis.h:346
#define E1000_RDESC_STATUS_PIF
Definition: e1000hw.h:59
char * PBOOLEAN
Definition: retypes.h:11
ULONG CurrentTxDesc
Definition: nic.h:79
ULONG ReceiveBufferEntrySize
Definition: nic.h:91
PNDIS_PACKET TransmitPackets[NUM_TRANSMIT_DESCRIPTORS]
Definition: nic.h:77
#define E1000_IMS_TXDW
Definition: e1000hw.h:182
#define E1000_TDESC_STATUS_DD
Definition: e1000hw.h:84
#define E1000_IMS_TXD_LOW
Definition: e1000hw.h:187
FORCEINLINE VOID E1000ReadUlong(_In_ PE1000_ADAPTER Adapter, _In_ ULONG Address, _Out_ PULONG Value)
Definition: nic.h:209
#define MAX_TRACE
Definition: debug.h:16
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
#define NULL
Definition: types.h:112
#define NDIS_DbgPrint(_t_, _x_)
Definition: debug.h:40
#define OUT
Definition: typedefs.h:40
unsigned int ULONG
Definition: retypes.h:1
#define MIN_TRACE
Definition: debug.h:14
LONG InterruptMask
Definition: nic.h:67
long _InterlockedOr(_Interlocked_operand_ long volatile *_Value, long _Mask)
VOID EXPORT NdisMIndicateStatus(IN NDIS_HANDLE MiniportAdapterHandle, IN NDIS_STATUS GeneralStatus, IN PVOID StatusBuffer, IN UINT StatusBufferSize)
Definition: miniport.c:1565
#define NDIS_STATUS_MEDIA_DISCONNECT
Definition: ndis.h:362