1 /* 2 * PROJECT: ReactOS Intel PRO/1000 Driver 3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) 4 * PURPOSE: Driver entrypoint 5 * COPYRIGHT: Copyright 2013 Cameron Gutman (cameron.gutman@reactos.org) 6 * Copyright 2018 Mark Jansen (mark.jansen@reactos.org) 7 */ 8 9 #include "nic.h" 10 11 #include <debug.h> 12 13 ULONG DebugTraceLevel = MIN_TRACE; 14 15 NDIS_STATUS 16 NTAPI 17 MiniportReset( 18 OUT PBOOLEAN AddressingReset, 19 IN NDIS_HANDLE MiniportAdapterContext) 20 { 21 *AddressingReset = FALSE; 22 UNIMPLEMENTED_DBGBREAK(); 23 return NDIS_STATUS_FAILURE; 24 } 25 26 NDIS_STATUS 27 NTAPI 28 MiniportSend( 29 IN NDIS_HANDLE MiniportAdapterContext, 30 IN PNDIS_PACKET Packet, 31 IN UINT Flags) 32 { 33 PE1000_ADAPTER Adapter = (PE1000_ADAPTER)MiniportAdapterContext; 34 PSCATTER_GATHER_LIST sgList = NDIS_PER_PACKET_INFO_FROM_PACKET(Packet, ScatterGatherListPacketInfo); 35 ULONG TransmitLength; 36 PHYSICAL_ADDRESS TransmitBuffer; 37 NDIS_STATUS Status; 38 39 ASSERT(sgList != NULL); 40 ASSERT(sgList->NumberOfElements == 1); 41 ASSERT((sgList->Elements[0].Address.LowPart & 3) == 0); 42 ASSERT(sgList->Elements[0].Length <= MAXIMUM_FRAME_SIZE); 43 44 if (Adapter->TxFull) 45 { 46 NDIS_DbgPrint(MIN_TRACE, ("All TX descriptors are full\n")); 47 return NDIS_STATUS_RESOURCES; 48 } 49 50 TransmitLength = sgList->Elements[0].Length; 51 TransmitBuffer = sgList->Elements[0].Address; 52 Adapter->TransmitPackets[Adapter->CurrentTxDesc] = Packet; 53 54 Status = NICTransmitPacket(Adapter, TransmitBuffer, TransmitLength); 55 if (Status != NDIS_STATUS_SUCCESS) 56 { 57 NDIS_DbgPrint(MIN_TRACE, ("Transmit packet failed\n")); 58 return Status; 59 } 60 61 return NDIS_STATUS_PENDING; 62 } 63 64 VOID 65 NTAPI 66 MiniportHalt( 67 IN NDIS_HANDLE MiniportAdapterContext) 68 { 69 PE1000_ADAPTER Adapter = (PE1000_ADAPTER)MiniportAdapterContext; 70 71 ASSERT(Adapter != NULL); 72 73 /* First disable sending / receiving */ 74 NICDisableTxRx(Adapter); 75 76 /* Then unregister interrupts */ 77 NICUnregisterInterrupts(Adapter); 78 79 /* Finally, free other resources (Ports, IO ranges,...) */ 80 NICReleaseIoResources(Adapter); 81 82 /* Destroy the adapter context */ 83 NdisFreeMemory(Adapter, sizeof(*Adapter), 0); 84 } 85 86 NDIS_STATUS 87 NTAPI 88 MiniportInitialize( 89 OUT PNDIS_STATUS OpenErrorStatus, 90 OUT PUINT SelectedMediumIndex, 91 IN PNDIS_MEDIUM MediumArray, 92 IN UINT MediumArraySize, 93 IN NDIS_HANDLE MiniportAdapterHandle, 94 IN NDIS_HANDLE WrapperConfigurationContext) 95 { 96 PE1000_ADAPTER Adapter; 97 NDIS_STATUS Status; 98 UINT i; 99 PNDIS_RESOURCE_LIST ResourceList; 100 UINT ResourceListSize; 101 PCI_COMMON_CONFIG PciConfig; 102 103 /* Make sure the medium is supported */ 104 for (i = 0; i < MediumArraySize; i++) 105 { 106 if (MediumArray[i] == NdisMedium802_3) 107 { 108 *SelectedMediumIndex = i; 109 break; 110 } 111 } 112 113 if (i == MediumArraySize) 114 { 115 NDIS_DbgPrint(MIN_TRACE, ("802.3 medium was not found in the medium array\n")); 116 return NDIS_STATUS_UNSUPPORTED_MEDIA; 117 } 118 119 /* Allocate our adapter context */ 120 Status = NdisAllocateMemoryWithTag((PVOID*)&Adapter, 121 sizeof(*Adapter), 122 E1000_TAG); 123 if (Status != NDIS_STATUS_SUCCESS) 124 { 125 NDIS_DbgPrint(MIN_TRACE, ("Failed to allocate adapter context (0x%x)\n", Status)); 126 return NDIS_STATUS_RESOURCES; 127 } 128 129 RtlZeroMemory(Adapter, sizeof(*Adapter)); 130 Adapter->AdapterHandle = MiniportAdapterHandle; 131 132 /* Notify NDIS of some characteristics of our NIC */ 133 NdisMSetAttributesEx(MiniportAdapterHandle, 134 Adapter, 135 0, 136 NDIS_ATTRIBUTE_BUS_MASTER, 137 NdisInterfacePci); 138 139 NdisReadPciSlotInformation(Adapter->AdapterHandle, 140 0, 141 FIELD_OFFSET(PCI_COMMON_CONFIG, VendorID), 142 &PciConfig, sizeof(PciConfig)); 143 144 Adapter->VendorID = PciConfig.VendorID; 145 Adapter->DeviceID = PciConfig.DeviceID; 146 147 Adapter->SubsystemID = PciConfig.u.type0.SubSystemID; 148 Adapter->SubsystemVendorID = PciConfig.u.type0.SubVendorID; 149 150 151 if (!NICRecognizeHardware(Adapter)) 152 { 153 NDIS_DbgPrint(MIN_TRACE, ("Hardware not recognized\n")); 154 Status = NDIS_STATUS_UNSUPPORTED_MEDIA; 155 goto Cleanup; 156 } 157 158 159 /* Get our resources for IRQ and IO base information */ 160 ResourceList = NULL; 161 ResourceListSize = 0; 162 NdisMQueryAdapterResources(&Status, 163 WrapperConfigurationContext, 164 ResourceList, 165 &ResourceListSize); 166 if (Status != NDIS_STATUS_RESOURCES) 167 { 168 NDIS_DbgPrint(MIN_TRACE, ("Unexpected failure of NdisMQueryAdapterResources (0x%x)\n", Status)); 169 Status = NDIS_STATUS_FAILURE; 170 /* call NdisWriteErrorLogEntry */ 171 goto Cleanup; 172 } 173 174 Status = NdisAllocateMemoryWithTag((PVOID*)&ResourceList, 175 ResourceListSize, 176 E1000_TAG); 177 if (Status != NDIS_STATUS_SUCCESS) 178 { 179 NDIS_DbgPrint(MIN_TRACE, ("Failed to allocate resource list (0x%x)\n", Status)); 180 /* call NdisWriteErrorLogEntry */ 181 goto Cleanup; 182 } 183 184 NdisMQueryAdapterResources(&Status, 185 WrapperConfigurationContext, 186 ResourceList, 187 &ResourceListSize); 188 if (Status != NDIS_STATUS_SUCCESS) 189 { 190 NDIS_DbgPrint(MIN_TRACE, ("Unexpected failure of NdisMQueryAdapterResources (0x%x)\n", Status)); 191 /* call NdisWriteErrorLogEntry */ 192 goto Cleanup; 193 } 194 195 ASSERT(ResourceList->Version == 1); 196 ASSERT(ResourceList->Revision == 1); 197 198 Status = NICInitializeAdapterResources(Adapter, ResourceList); 199 200 NdisFreeMemory(ResourceList, ResourceListSize, 0); 201 ResourceList = NULL; 202 203 if (Status != NDIS_STATUS_SUCCESS) 204 { 205 NDIS_DbgPrint(MIN_TRACE, ("Adapter didn't receive enough resources\n")); 206 goto Cleanup; 207 } 208 209 /* Allocate the DMA resources */ 210 Status = NdisMInitializeScatterGatherDma(MiniportAdapterHandle, 211 FALSE, // 64bit is supported but can be buggy 212 MAXIMUM_FRAME_SIZE); 213 if (Status != NDIS_STATUS_SUCCESS) 214 { 215 NDIS_DbgPrint(MIN_TRACE, ("Unable to configure DMA\n")); 216 Status = NDIS_STATUS_RESOURCES; 217 goto Cleanup; 218 } 219 220 Status = NICAllocateIoResources(Adapter); 221 if (Status != NDIS_STATUS_SUCCESS) 222 { 223 NDIS_DbgPrint(MIN_TRACE, ("Unable to allocate resources\n")); 224 Status = NDIS_STATUS_RESOURCES; 225 goto Cleanup; 226 } 227 228 /* Adapter setup */ 229 Status = NICPowerOn(Adapter); 230 if (Status != NDIS_STATUS_SUCCESS) 231 { 232 NDIS_DbgPrint(MIN_TRACE, ("Unable to power on NIC (0x%x)\n", Status)); 233 goto Cleanup; 234 } 235 236 Status = NICSoftReset(Adapter); 237 if (Status != NDIS_STATUS_SUCCESS) 238 { 239 NDIS_DbgPrint(MIN_TRACE, ("Unable to reset the NIC (0x%x)\n", Status)); 240 goto Cleanup; 241 } 242 243 Status = NICGetPermanentMacAddress(Adapter, Adapter->PermanentMacAddress); 244 if (Status != NDIS_STATUS_SUCCESS) 245 { 246 NDIS_DbgPrint(MIN_TRACE, ("Unable to get the fixed MAC address (0x%x)\n", Status)); 247 goto Cleanup; 248 } 249 250 RtlCopyMemory(Adapter->MulticastList[0].MacAddress, Adapter->PermanentMacAddress, IEEE_802_ADDR_LENGTH); 251 252 NICUpdateMulticastList(Adapter); 253 254 /* Update link state and speed */ 255 NICUpdateLinkStatus(Adapter); 256 257 /* We're ready to handle interrupts now */ 258 Status = NICRegisterInterrupts(Adapter); 259 if (Status != NDIS_STATUS_SUCCESS) 260 { 261 NDIS_DbgPrint(MIN_TRACE, ("Unable to register interrupt (0x%x)\n", Status)); 262 goto Cleanup; 263 } 264 265 /* Enable interrupts on the NIC */ 266 Adapter->InterruptMask = DEFAULT_INTERRUPT_MASK; 267 Status = NICApplyInterruptMask(Adapter); 268 if (Status != NDIS_STATUS_SUCCESS) 269 { 270 NDIS_DbgPrint(MIN_TRACE, ("Unable to apply interrupt mask (0x%x)\n", Status)); 271 goto Cleanup; 272 } 273 274 /* Turn on TX and RX now */ 275 Status = NICEnableTxRx(Adapter); 276 if (Status != NDIS_STATUS_SUCCESS) 277 { 278 NDIS_DbgPrint(MIN_TRACE, ("Unable to enable TX and RX (0x%x)\n", Status)); 279 goto Cleanup; 280 } 281 282 return NDIS_STATUS_SUCCESS; 283 284 Cleanup: 285 if (ResourceList != NULL) 286 { 287 NdisFreeMemory(ResourceList, ResourceListSize, 0); 288 } 289 if (Adapter != NULL) 290 { 291 MiniportHalt(Adapter); 292 } 293 294 return Status; 295 } 296 297 NTSTATUS 298 NTAPI 299 DriverEntry( 300 IN PDRIVER_OBJECT DriverObject, 301 IN PUNICODE_STRING RegistryPath) 302 { 303 NDIS_HANDLE WrapperHandle; 304 NDIS_MINIPORT_CHARACTERISTICS Characteristics = { 0 }; 305 NDIS_STATUS Status; 306 307 Characteristics.MajorNdisVersion = NDIS_MINIPORT_MAJOR_VERSION; 308 Characteristics.MinorNdisVersion = NDIS_MINIPORT_MINOR_VERSION; 309 Characteristics.CheckForHangHandler = NULL; 310 Characteristics.DisableInterruptHandler = NULL; 311 Characteristics.EnableInterruptHandler = NULL; 312 Characteristics.HaltHandler = MiniportHalt; 313 Characteristics.HandleInterruptHandler = MiniportHandleInterrupt; 314 Characteristics.InitializeHandler = MiniportInitialize; 315 Characteristics.ISRHandler = MiniportISR; 316 Characteristics.QueryInformationHandler = MiniportQueryInformation; 317 Characteristics.ReconfigureHandler = NULL; 318 Characteristics.ResetHandler = MiniportReset; 319 Characteristics.SendHandler = MiniportSend; 320 Characteristics.SetInformationHandler = MiniportSetInformation; 321 Characteristics.TransferDataHandler = NULL; 322 Characteristics.ReturnPacketHandler = NULL; 323 Characteristics.SendPacketsHandler = NULL; 324 Characteristics.AllocateCompleteHandler = NULL; 325 326 NdisMInitializeWrapper(&WrapperHandle, DriverObject, RegistryPath, NULL); 327 if (!WrapperHandle) 328 { 329 return NDIS_STATUS_FAILURE; 330 } 331 332 Status = NdisMRegisterMiniport(WrapperHandle, &Characteristics, sizeof(Characteristics)); 333 if (Status != NDIS_STATUS_SUCCESS) 334 { 335 NdisTerminateWrapper(WrapperHandle, 0); 336 return NDIS_STATUS_FAILURE; 337 } 338 339 return NDIS_STATUS_SUCCESS; 340 } 341