ReactOS  0.4.13-dev-551-gf37fb1f
interrupt.c
Go to the documentation of this file.
1 /*
2  * ReactOS Realtek 8139 Driver
3  *
4  * Copyright (C) 2013 Cameron Gutman
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License along
17  * with this program; if not, write to the Free Software Foundation, Inc.,
18  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19  *
20  */
21 
22 #include "nic.h"
23 
24 #define NDEBUG
25 #include <debug.h>
26 
27 VOID
28 NTAPI
30  OUT PBOOLEAN InterruptRecognized,
31  OUT PBOOLEAN QueueMiniportHandleInterrupt,
32  IN NDIS_HANDLE MiniportAdapterContext
33  )
34 {
35  PRTL_ADAPTER adapter = (PRTL_ADAPTER)MiniportAdapterContext;
36  ULONG csConfig;
37 
38  //
39  // FIXME: We need to synchronize with this ISR for changes to InterruptPending,
40  // LinkChange, MediaState, and LinkSpeedMbps. We can get away with IRQL
41  // synchronization on non-SMP machines because we run a DIRQL here.
42  //
43 
44  adapter->InterruptPending |= NICInterruptRecognized(adapter, InterruptRecognized);
45  if (!(*InterruptRecognized))
46  {
47  //
48  // This is not ours.
49  //
50  *QueueMiniportHandleInterrupt = FALSE;
51  return;
52  }
53 
54  //
55  // We have to check for a special link change interrupt before acknowledging
56  //
57  if (adapter->InterruptPending & R_I_RXUNDRUN)
58  {
59  NdisRawReadPortUlong(adapter->IoBase + R_CSCFG, &csConfig);
60  if (csConfig & R_CSCR_LINKCHNG)
61  {
62  adapter->LinkChange = TRUE;
63  NICUpdateLinkStatus(adapter);
64  }
65  }
66 
67  //
68  // Acknowledge the interrupt and mark the events pending service
69  //
70  NICAcknowledgeInterrupts(adapter);
71  *QueueMiniportHandleInterrupt = TRUE;
72 }
73 
74 VOID
75 NTAPI
77  IN NDIS_HANDLE MiniportAdapterContext
78  )
79 {
80  PRTL_ADAPTER adapter = (PRTL_ADAPTER)MiniportAdapterContext;
81  ULONG txStatus;
82  UCHAR command;
83  PPACKET_HEADER nicHeader;
84  PETH_HEADER ethHeader;
85 
86  NdisDprAcquireSpinLock(&adapter->Lock);
87 
88  NDIS_DbgPrint(MAX_TRACE, ("Interrupts pending: 0x%x\n", adapter->InterruptPending));
89 
90  //
91  // Handle a link change
92  //
93  if (adapter->LinkChange)
94  {
95  NdisDprReleaseSpinLock(&adapter->Lock);
99  NULL,
100  0);
102  NdisDprAcquireSpinLock(&adapter->Lock);
103  adapter->LinkChange = FALSE;
104  }
105 
106  //
107  // Handle a TX interrupt
108  //
109  if (adapter->InterruptPending & (R_I_TXOK | R_I_TXERR))
110  {
111  while (adapter->TxFull || adapter->DirtyTxDesc != adapter->CurrentTxDesc)
112  {
114  (adapter->DirtyTxDesc * sizeof(ULONG)), &txStatus);
115 
116  if (!(txStatus & (R_TXS_STATOK | R_TXS_UNDERRUN | R_TXS_ABORTED)))
117  {
118  //
119  // Not sent yet
120  //
121  break;
122  }
123 
124  NDIS_DbgPrint(MAX_TRACE, ("Transmission for desc %d complete: 0x%x\n",
125  adapter->DirtyTxDesc, txStatus));
126 
127  if (txStatus & R_TXS_STATOK)
128  {
129  adapter->TransmitOk++;
130  }
131  else
132  {
133  adapter->TransmitError++;
134  }
135 
136  adapter->DirtyTxDesc++;
137  adapter->DirtyTxDesc %= TX_DESC_COUNT;
138  adapter->InterruptPending &= ~(R_I_TXOK | R_I_TXERR);
139  adapter->TxFull = FALSE;
140  }
141  }
142 
143  //
144  // Handle a good RX interrupt
145  //
146  if (adapter->InterruptPending & (R_I_RXOK | R_I_RXERR))
147  {
148  for (;;)
149  {
151  if (command & R_CMD_RXEMPTY)
152  {
153  //
154  // The buffer is empty
155  //
156  adapter->InterruptPending &= ~(R_I_RXOK | R_I_RXERR);
157  break;
158  }
159 
161 
162  NDIS_DbgPrint(MAX_TRACE, ("Looking for a packet at offset 0x%x\n",
163  adapter->ReceiveOffset));
164  nicHeader = (PPACKET_HEADER)(adapter->ReceiveBuffer + adapter->ReceiveOffset);
165  if (!(nicHeader->Status & RSR_ROK))
166  {
167  //
168  // Receive failed
169  //
170  NDIS_DbgPrint(MIN_TRACE, ("Receive failed: 0x%x\n", nicHeader->Status));
171 
172  if (nicHeader->Status & RSR_FAE)
173  {
174  adapter->ReceiveAlignmentError++;
175  }
176  else if (nicHeader->Status & RSR_CRC)
177  {
178  adapter->ReceiveCrcError++;
179  }
180  adapter->ReceiveError++;
181 
182  goto NextPacket;
183  }
184 
185  NDIS_DbgPrint(MAX_TRACE, ("Indicating %d byte packet to NDIS\n",
186  nicHeader->PacketLength - RECV_CRC_LENGTH));
187 
188  ethHeader = (PETH_HEADER)(nicHeader + 1);
190  NULL,
191  (PVOID)(ethHeader),
192  sizeof(ETH_HEADER),
193  (PVOID)(ethHeader + 1),
194  nicHeader->PacketLength - sizeof(ETH_HEADER) - RECV_CRC_LENGTH,
195  nicHeader->PacketLength - sizeof(ETH_HEADER) - RECV_CRC_LENGTH);
196  adapter->ReceiveOk++;
197 
198  NextPacket:
199  adapter->ReceiveOffset += nicHeader->PacketLength + sizeof(PACKET_HEADER);
200  adapter->ReceiveOffset = (adapter->ReceiveOffset + 3) & ~3;
201  NdisRawWritePortUshort(adapter->IoBase + R_CAPR, adapter->ReceiveOffset - 0x10);
202 
203  if (adapter->InterruptPending & (R_I_RXOVRFLW | R_I_FIFOOVR))
204  {
205  //
206  // We can only clear these interrupts once CAPR has been reset
207  //
209  adapter->InterruptPending &= ~(R_I_RXOVRFLW | R_I_FIFOOVR);
210  }
211  }
212 
214  }
215 
216  NdisDprReleaseSpinLock(&adapter->Lock);
217 }
VOID NTAPI MiniportISR(OUT PBOOLEAN InterruptRecognized, OUT PBOOLEAN QueueMiniportHandleInterrupt, IN NDIS_HANDLE MiniportAdapterContext)
Definition: interrupt.c:16
#define IN
Definition: typedefs.h:38
#define RSR_CRC
Definition: 8390.h:101
ULONG MediaState
Definition: nic.h:64
#define R_IS
Definition: rtlhw.h:54
#define TRUE
Definition: types.h:120
#define R_CSCR_LINKCHNG
Definition: rtlhw.h:102
#define R_TXS_STATOK
Definition: rtlhw.h:40
ULONG TransmitError
Definition: nic.h:81
struct _PACKET_HEADER * PPACKET_HEADER
VOID EXPORT NdisDprReleaseSpinLock(IN PNDIS_SPIN_LOCK SpinLock)
Definition: control.c:187
#define NdisMEthIndicateReceiveComplete(MiniportAdapterHandle)
Definition: ndis.h:5482
#define R_CMD_RXEMPTY
Definition: rtlhw.h:46
#define RSR_FAE
Definition: 8390.h:102
ULONG NTAPI NICInterruptRecognized(IN PE1000_ADAPTER Adapter, OUT PBOOLEAN InterruptRecognized)
Definition: hardware.c:790
ULONG ReceiveError
Definition: nic.h:80
#define R_I_TXOK
Definition: rtlhw.h:59
struct _PACKET_HEADER PACKET_HEADER
USHORT ReceiveOffset
Definition: nic.h:61
#define R_TXSTS0
Definition: rtlhw.h:26
#define R_TXS_UNDERRUN
Definition: rtlhw.h:39
VOID EXPORT NdisDprAcquireSpinLock(IN PNDIS_SPIN_LOCK SpinLock)
Definition: control.c:169
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
Definition: lan.h:33
#define NdisRawWritePortUshort(Port, Data)
Definition: ndis.h:4248
ULONG TransmitOk
Definition: nic.h:79
USHORT InterruptPending
Definition: nic.h:70
#define R_CAPR
Definition: rtlhw.h:51
#define NdisRawReadPortUlong(Port, Data)
Definition: ndis.h:4182
smooth NULL
Definition: ftsmooth.c:416
VOID NTAPI NICUpdateLinkStatus(IN PE1000_ADAPTER Adapter)
Definition: hardware.c:808
UCHAR DirtyTxDesc
Definition: nic.h:72
#define RECV_CRC_LENGTH
Definition: nic.h:23
VOID EXPORT NdisMIndicateStatusComplete(IN NDIS_HANDLE MiniportAdapterHandle)
Definition: miniport.c:1579
UCHAR CurrentTxDesc
Definition: nic.h:73
#define NDIS_STATUS_MEDIA_CONNECT
Definition: ndis.h:361
BOOLEAN LinkChange
Definition: nic.h:65
BOOLEAN TxFull
Definition: nic.h:74
ULONG ReceiveOk
Definition: nic.h:78
VOID NTAPI MiniportHandleInterrupt(IN NDIS_HANDLE MiniportAdapterContext)
Definition: interrupt.c:40
struct _ETH_HEADER * PETH_HEADER
ULONG ReceiveCrcError
Definition: nic.h:83
#define NdisMEthIndicateReceive(MiniportAdapterHandle, MiniportReceiveContext, HeaderBuffer, HeaderBufferSize, LookaheadBuffer, LookaheadBufferSize, PacketSize)
Definition: ndis.h:5458
NDIS_SPIN_LOCK Lock
Definition: nic.h:38
#define R_I_RXERR
Definition: rtlhw.h:58
unsigned char UCHAR
Definition: xmlstorage.h:181
char * PBOOLEAN
Definition: retypes.h:11
PUCHAR IoBase
Definition: nic.h:48
UCHAR Status
Definition: 8390.h:140
NDIS_HANDLE MiniportAdapterHandle
Definition: nic.h:37
#define TX_DESC_COUNT
Definition: rtlhw.h:14
struct _RTL_ADAPTER * PRTL_ADAPTER
VOID NTAPI NICAcknowledgeInterrupts(IN PRTL_ADAPTER Adapter)
Definition: hardware.c:167
ULONG ReceiveAlignmentError
Definition: nic.h:84
#define MAX_TRACE
Definition: debug.h:16
#define R_I_RXOVRFLW
Definition: rtlhw.h:61
#define R_CMD
Definition: rtlhw.h:45
#define R_I_RXUNDRUN
Definition: rtlhw.h:62
#define R_TXS_ABORTED
Definition: rtlhw.h:42
#define NDIS_DbgPrint(_t_, _x_)
Definition: debug.h:40
#define RECEIVE_BUFFER_SIZE
Definition: nic.h:20
int command(const char *fmt,...)
Definition: ftp.c:266
USHORT PacketLength
Definition: 8390.h:142
#define R_CSCFG
Definition: rtlhw.h:99
#define RSR_ROK
Definition: rtlhw.h:152
#define OUT
Definition: typedefs.h:39
unsigned int ULONG
Definition: retypes.h:1
#define MIN_TRACE
Definition: debug.h:14
#define R_I_FIFOOVR
Definition: rtlhw.h:63
#define R_I_TXERR
Definition: rtlhw.h:60
#define NdisRawReadPortUchar(Port, Data)
Definition: ndis.h:4173
#define R_I_RXOK
Definition: rtlhw.h:57
VOID EXPORT NdisMIndicateStatus(IN NDIS_HANDLE MiniportAdapterHandle, IN NDIS_STATUS GeneralStatus, IN PVOID StatusBuffer, IN UINT StatusBufferSize)
Definition: miniport.c:1564
#define NDIS_STATUS_MEDIA_DISCONNECT
Definition: ndis.h:362
PUCHAR ReceiveBuffer
Definition: nic.h:59