ReactOS 0.4.15-dev-7924-g5949c20
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
27VOID
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;
64 }
65 }
66
67 //
68 // Acknowledge the interrupt and mark the events pending service
69 //
71 *QueueMiniportHandleInterrupt = TRUE;
72}
73
74VOID
77 IN NDIS_HANDLE MiniportAdapterContext
78 )
79{
80 PRTL_ADAPTER adapter = (PRTL_ADAPTER)MiniportAdapterContext;
81 ULONG txStatus;
83 PPACKET_HEADER nicHeader;
84 PETH_HEADER ethHeader;
85
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 {
96 NdisMIndicateStatus(adapter->MiniportAdapterHandle,
97 adapter->MediaState == NdisMediaStateConnected ?
99 NULL,
100 0);
101 NdisMIndicateStatusComplete(adapter->MiniportAdapterHandle);
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 {
152 {
153 //
154 // The buffer is empty
155 //
156 adapter->InterruptPending &= ~(R_I_RXOK | R_I_RXERR);
157 break;
158 }
159
160 adapter->ReceiveOffset %= RECEIVE_BUFFER_SIZE;
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);
189 NdisMEthIndicateReceive(adapter->MiniportAdapterHandle,
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
213 NdisMEthIndicateReceiveComplete(adapter->MiniportAdapterHandle);
214 }
215
217}
#define RSR_CRC
Definition: 8390.h:101
#define RSR_FAE
Definition: 8390.h:102
struct _PACKET_HEADER PACKET_HEADER
struct _PACKET_HEADER * PPACKET_HEADER
#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
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
VOID NTAPI NICAcknowledgeInterrupts(IN PRTL_ADAPTER Adapter)
Definition: hardware.c:167
USHORT NTAPI NICInterruptRecognized(IN PRTL_ADAPTER Adapter, OUT PBOOLEAN InterruptRecognized)
Definition: hardware.c:151
#define RECEIVE_BUFFER_SIZE
Definition: nic.h:20
return adapter
#define NdisRawReadPortUlong(Port, Data)
Definition: ndis.h:4182
#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 NdisDprReleaseSpinLock(_SpinLock)
Definition: ndis.h:4133
#define NDIS_STATUS_MEDIA_DISCONNECT
Definition: ndis.h:362
#define NdisRawReadPortUchar(Port, Data)
Definition: ndis.h:4173
#define NdisDprAcquireSpinLock(_SpinLock)
Definition: ndis.h:4124
#define NdisRawWritePortUshort(Port, Data)
Definition: ndis.h:4248
#define NdisMIndicateStatus(MiniportAdapterHandle, GeneralStatus, StatusBuffer, StatusBufferSize)
Definition: ndis.h:5570
@ NdisMediaStateConnected
Definition: ntddndis.h:470
#define RECV_CRC_LENGTH
Definition: nic.h:23
struct _RTL_ADAPTER * PRTL_ADAPTER
#define R_I_TXERR
Definition: rtlhw.h:60
#define R_CMD_RXEMPTY
Definition: rtlhw.h:46
#define R_IS
Definition: rtlhw.h:54
#define R_I_RXUNDRUN
Definition: rtlhw.h:62
#define R_I_RXOVRFLW
Definition: rtlhw.h:61
#define R_TXS_ABORTED
Definition: rtlhw.h:42
#define R_TXSTS0
Definition: rtlhw.h:26
#define R_I_RXOK
Definition: rtlhw.h:57
#define R_CSCR_LINKCHNG
Definition: rtlhw.h:102
#define R_I_TXOK
Definition: rtlhw.h:59
#define R_I_FIFOOVR
Definition: rtlhw.h:63
#define TX_DESC_COUNT
Definition: rtlhw.h:14
#define R_I_RXERR
Definition: rtlhw.h:58
#define RSR_ROK
Definition: rtlhw.h:152
#define R_CAPR
Definition: rtlhw.h:51
#define R_CMD
Definition: rtlhw.h:45
#define R_TXS_STATOK
Definition: rtlhw.h:40
#define R_CSCFG
Definition: rtlhw.h:99
#define R_TXS_UNDERRUN
Definition: rtlhw.h:39
Definition: lan.h:33
USHORT PacketLength
Definition: 8390.h:142
UCHAR Status
Definition: 8390.h:140
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
unsigned char UCHAR
Definition: xmlstorage.h:181