xref: /reactos/drivers/network/dd/rtl8139/hardware.c (revision 9393fc32)
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 NDIS_STATUS
28 NTAPI
29 NICPowerOn (
30     IN PRTL_ADAPTER Adapter
31     )
32 {
33     //
34     // Send 0x00 to the CONFIG_1 register (0x52) to set the LWAKE + LWPTN to active high.
35     // This should essentially *power on* the device.
36     // -- OSDev Wiki
37     //
38     NdisRawWritePortUchar(Adapter->IoBase + R_CFG1, 0x00);
39     return NDIS_STATUS_SUCCESS;
40 }
41 
42 NDIS_STATUS
43 NTAPI
44 NICSoftReset (
45     IN PRTL_ADAPTER Adapter
46     )
47 {
48     UCHAR commandReg;
49     UINT resetAttempts;
50 
51     //
52     // Sending 0x10 to the Command register (0x37) will send the RTL8139 into a software reset.
53     // Once that byte is sent, the RST bit must be checked to make sure that the chip has finished the reset.
54     // If the RST bit is high (1), then the reset is still in operation.
55     // -- OSDev Wiki
56     NdisRawWritePortUchar(Adapter->IoBase + R_CMD, B_CMD_RST);
57 
58     for (resetAttempts = 0; resetAttempts < MAX_RESET_ATTEMPTS; resetAttempts++)
59     {
60         NdisRawReadPortUchar(Adapter->IoBase + R_CMD, &commandReg);
61 
62         if (!(commandReg & B_CMD_RST))
63         {
64             return NDIS_STATUS_SUCCESS;
65         }
66 
67         NdisMSleep(100);
68     }
69 
70     return NDIS_STATUS_FAILURE;
71 }
72 
73 NDIS_STATUS
74 NTAPI
75 NICRegisterReceiveBuffer (
76     IN PRTL_ADAPTER Adapter
77     )
78 {
79     ASSERT(NdisGetPhysicalAddressHigh(Adapter->ReceiveBufferPa) == 0);
80 
81     NdisRawWritePortUlong(Adapter->IoBase + R_RXSA, Adapter->ReceiveBufferPa.LowPart);
82 
83     return NDIS_STATUS_SUCCESS;
84 }
85 
86 NDIS_STATUS
87 NTAPI
88 NICRemoveReceiveBuffer (
89     IN PRTL_ADAPTER Adapter
90     )
91 {
92     NdisRawWritePortUlong(Adapter->IoBase + R_RXSA, 0);
93     return NDIS_STATUS_SUCCESS;
94 }
95 
96 NDIS_STATUS
97 NTAPI
98 NICEnableTxRx (
99     IN PRTL_ADAPTER Adapter
100     )
101 {
102     NdisRawWritePortUchar(Adapter->IoBase + R_CMD, B_CMD_TXE | B_CMD_RXE);
103 
104     //
105     // TX and RX must be enabled before setting these
106     //
107     NdisRawWritePortUlong(Adapter->IoBase + R_RC, RC_VAL);
108     NdisRawWritePortUlong(Adapter->IoBase + R_TC, TC_VAL);
109     return NDIS_STATUS_SUCCESS;
110 }
111 
112 NDIS_STATUS
113 NTAPI
114 NICGetPermanentMacAddress (
115     IN PRTL_ADAPTER Adapter,
116     OUT PUCHAR MacAddress
117     )
118 {
119     UINT i;
120 
121     for (i = 0; i < IEEE_802_ADDR_LENGTH; i++)
122     {
123         NdisRawReadPortUchar(Adapter->IoBase + R_MAC + i, &MacAddress[i]);
124     }
125 
126     return NDIS_STATUS_SUCCESS;
127 }
128 
129 NDIS_STATUS
130 NTAPI
131 NICApplyInterruptMask (
132     IN PRTL_ADAPTER Adapter
133     )
134 {
135     NdisRawWritePortUshort(Adapter->IoBase + R_IM, Adapter->InterruptMask);
136     return NDIS_STATUS_SUCCESS;
137 }
138 
139 NDIS_STATUS
140 NTAPI
141 NICDisableInterrupts (
142     IN PRTL_ADAPTER Adapter
143     )
144 {
145     NdisRawWritePortUshort(Adapter->IoBase + R_IM, 0);
146     return NDIS_STATUS_SUCCESS;
147 }
148 
149 USHORT
150 NTAPI
151 NICInterruptRecognized (
152     IN PRTL_ADAPTER Adapter,
153     OUT PBOOLEAN InterruptRecognized
154     )
155 {
156     USHORT interruptStatus;
157 
158     NdisRawReadPortUshort(Adapter->IoBase + R_IS, &interruptStatus);
159 
160     *InterruptRecognized = (interruptStatus & Adapter->InterruptMask) != 0;
161 
162     return (interruptStatus & Adapter->InterruptMask);
163 }
164 
165 VOID
166 NTAPI
167 NICAcknowledgeInterrupts (
168     IN PRTL_ADAPTER Adapter
169     )
170 {
171     NdisRawWritePortUshort(Adapter->IoBase + R_IS, Adapter->InterruptPending);
172 }
173 
174 VOID
175 NTAPI
176 NICUpdateLinkStatus (
177     IN PRTL_ADAPTER Adapter
178     )
179 {
180     UCHAR mediaState;
181 
182     NdisRawReadPortUchar(Adapter->IoBase + R_MS, &mediaState);
183     Adapter->MediaState = (mediaState & R_MS_LINKDWN) ? NdisMediaStateDisconnected :
184                                                         NdisMediaStateConnected;
185     Adapter->LinkSpeedMbps = (mediaState & R_MS_SPEED_10) ? 10 : 100;
186 }
187 
188 NDIS_STATUS
189 NTAPI
190 NICApplyPacketFilter (
191     IN PRTL_ADAPTER Adapter
192     )
193 {
194     ULONG filterMask;
195 
196     filterMask = RC_VAL;
197 
198     if (Adapter->PacketFilter & NDIS_PACKET_TYPE_DIRECTED)
199     {
200         filterMask |= B_RC_APM;
201     }
202 
203     if (Adapter->PacketFilter & NDIS_PACKET_TYPE_MULTICAST)
204     {
205         filterMask |= B_RC_AM;
206     }
207 
208     if (Adapter->PacketFilter & NDIS_PACKET_TYPE_BROADCAST)
209     {
210         filterMask |= B_RC_AB;
211     }
212 
213     if (Adapter->PacketFilter & NDIS_PACKET_TYPE_PROMISCUOUS)
214     {
215         filterMask |= B_RC_AAP;
216     }
217 
218     NdisRawWritePortUlong(Adapter->IoBase + R_RC, filterMask);
219 
220     return NDIS_STATUS_SUCCESS;
221 }
222 
223 NDIS_STATUS
224 NTAPI
225 NICTransmitPacket (
226     IN PRTL_ADAPTER Adapter,
227     IN UCHAR TxDesc,
228     IN ULONG PhysicalAddress,
229     IN ULONG Length
230     )
231 {
232     NdisRawWritePortUlong(Adapter->IoBase + R_TXSAD0 + (TxDesc * sizeof(ULONG)), PhysicalAddress);
233     NdisRawWritePortUlong(Adapter->IoBase + R_TXSTS0 + (TxDesc * sizeof(ULONG)), Length);
234     return NDIS_STATUS_SUCCESS;
235 }
236