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