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: Copyright 2013 Cameron Gutman (cameron.gutman@reactos.org)
6 * Copyright 2018 Mark Jansen (mark.jansen@reactos.org)
16 OUT PBOOLEAN InterruptRecognized
,
17 OUT PBOOLEAN QueueMiniportHandleInterrupt
,
18 IN NDIS_HANDLE MiniportAdapterContext
)
21 PE1000_ADAPTER Adapter
= (PE1000_ADAPTER
)MiniportAdapterContext
;
23 Value
= NICInterruptRecognized(Adapter
, InterruptRecognized
);
24 InterlockedOr(&Adapter
->InterruptPending
, Value
);
26 if (!(*InterruptRecognized
))
28 /* This is not ours. */
29 *QueueMiniportHandleInterrupt
= FALSE
;
33 /* Mark the events pending service */
34 *QueueMiniportHandleInterrupt
= TRUE
;
39 MiniportHandleInterrupt(
40 IN NDIS_HANDLE MiniportAdapterContext
)
43 PE1000_ADAPTER Adapter
= (PE1000_ADAPTER
)MiniportAdapterContext
;
44 volatile PE1000_TRANSMIT_DESCRIPTOR TransmitDescriptor
;
46 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
48 Value
= InterlockedExchange(&Adapter
->InterruptPending
, 0);
50 NdisDprAcquireSpinLock(&Adapter
->Lock
);
52 if (Value
& E1000_IMS_LSC
)
56 NdisDprReleaseSpinLock(&Adapter
->Lock
);
57 Value
&= ~E1000_IMS_LSC
;
58 NDIS_DbgPrint(MIN_TRACE
, ("Link status changed!.\n"));
60 NICUpdateLinkStatus(Adapter
);
62 Status
= Adapter
->MediaState
== NdisMediaStateConnected
? NDIS_STATUS_MEDIA_CONNECT
: NDIS_STATUS_MEDIA_DISCONNECT
;
63 NdisMIndicateStatus(Adapter
->AdapterHandle
, Status
, NULL
, 0);
64 NdisMIndicateStatusComplete(Adapter
->AdapterHandle
);
66 NdisDprAcquireSpinLock(&Adapter
->Lock
);
69 if (Value
& E1000_IMS_TXDW
)
71 while (Adapter
->TxFull
|| Adapter
->LastTxDesc
!= Adapter
->CurrentTxDesc
)
73 TransmitDescriptor
= Adapter
->TransmitDescriptors
+ Adapter
->LastTxDesc
;
75 if (!(TransmitDescriptor
->Status
& E1000_TDESC_STATUS_DD
))
77 /* Not processed yet */
81 Adapter
->LastTxDesc
= (Adapter
->LastTxDesc
+ 1) % NUM_TRANSMIT_DESCRIPTORS
;
82 Value
&= ~E1000_IMS_TXDW
;
83 Adapter
->TxFull
= FALSE
;
84 NDIS_DbgPrint(MAX_TRACE
, ("CurrentTxDesc:%u, LastTxDesc:%u\n", Adapter
->CurrentTxDesc
, Adapter
->LastTxDesc
));
88 if (Value
& (E1000_IMS_RXDMT0
| E1000_IMS_RXT0
))
90 volatile PE1000_RECEIVE_DESCRIPTOR ReceiveDescriptor
;
91 PETH_HEADER EthHeader
;
94 /* Clear out these interrupts */
95 Value
&= ~(E1000_IMS_RXDMT0
| E1000_IMS_RXT0
);
99 BufferOffset
= Adapter
->CurrentRxDesc
* Adapter
->ReceiveBufferEntrySize
;
100 ReceiveDescriptor
= Adapter
->ReceiveDescriptors
+ Adapter
->CurrentRxDesc
;
102 if (!(ReceiveDescriptor
->Status
& E1000_RDESC_STATUS_DD
))
104 /* Not received yet */
108 if (ReceiveDescriptor
->Length
!= 0)
110 EthHeader
= Adapter
->ReceiveBuffer
+ BufferOffset
;
112 NdisMEthIndicateReceive(Adapter
->AdapterHandle
,
117 ReceiveDescriptor
->Length
- sizeof(ETH_HEADER
),
118 ReceiveDescriptor
->Length
- sizeof(ETH_HEADER
));
120 if (ReceiveDescriptor
->Status
& E1000_RDESC_STATUS_EOP
)
122 NdisMEthIndicateReceiveComplete(Adapter
->AdapterHandle
);
130 /* Restore the descriptor Address, incase we received a NULL descriptor */
131 ReceiveDescriptor
->Address
= Adapter
->ReceiveBufferPa
.QuadPart
+ BufferOffset
;
132 /* Give the descriptor back */
133 ReceiveDescriptor
->Status
= 0;
134 E1000WriteUlong(Adapter
, E1000_REG_RDT
, Adapter
->CurrentRxDesc
);
135 Adapter
->CurrentRxDesc
= (Adapter
->CurrentRxDesc
+ 1) % NUM_RECEIVE_DESCRIPTORS
;