Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3964 lines
119 KiB

  1. /*++
  2. Copyright (c) 1990-1995 Microsoft Corporation
  3. Module Name:
  4. configm.c
  5. Abstract:
  6. NDIS wrapper functions for miniport configuration/initialization
  7. Author:
  8. Sean Selitrennikoff (SeanSe) 05-Oct-93
  9. Jameel Hyder (JameelH) 01-Jun-95
  10. Environment:
  11. Kernel mode, FSD
  12. Revision History:
  13. --*/
  14. #include <precomp.h>
  15. #pragma hdrstop
  16. //
  17. // Define the module number for debug code.
  18. //
  19. #define MODULE_NUMBER MODULE_CONFIGM
  20. NDIS_STATUS
  21. NdisMRegisterMiniport(
  22. IN NDIS_HANDLE NdisWrapperHandle,
  23. IN PNDIS_MINIPORT_CHARACTERISTICS MiniportCharacteristics,
  24. IN UINT CharacteristicsLength
  25. )
  26. /*++
  27. Routine Description:
  28. Used to register a Miniport driver with the wrapper.
  29. Arguments:
  30. Status - Status of the operation.
  31. NdisWrapperHandle - Handle returned by NdisWInitializeWrapper.
  32. MiniportCharacteritics - The NDIS_MINIPORT_CHARACTERISTICS table.
  33. CharacteristicsLength - The length of MiniportCharacteristics.
  34. Return Value:
  35. None.
  36. --*/
  37. {
  38. NDIS_STATUS Status;
  39. PNDIS_M_DRIVER_BLOCK MiniBlock;
  40. DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO,
  41. ("==>NdisMRegisterMiniport: NdisWrapperHandle %p\n", NdisWrapperHandle));
  42. Status = ndisRegisterMiniportDriver(NdisWrapperHandle,
  43. MiniportCharacteristics,
  44. CharacteristicsLength,
  45. &MiniBlock);
  46. DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO,
  47. ("NdisMRegisterMiniport: MiniBlock %p\n", MiniBlock));
  48. ASSERT (CURRENT_IRQL < DISPATCH_LEVEL);
  49. DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO,
  50. ("<==NdisMRegisterMiniport: MiniBlock %p, Status %lx\n", MiniBlock, Status));
  51. return Status;
  52. }
  53. NDIS_STATUS
  54. NdisIMRegisterLayeredMiniport(
  55. IN NDIS_HANDLE NdisWrapperHandle,
  56. IN PNDIS_MINIPORT_CHARACTERISTICS MiniportCharacteristics,
  57. IN UINT CharacteristicsLength,
  58. OUT PNDIS_HANDLE DriverHandle
  59. )
  60. /*++
  61. Routine Description:
  62. Used to register a layered Miniport driver with the wrapper.
  63. Arguments:
  64. Status - Status of the operation.
  65. NdisWrapperHandle - Handle returned by NdisInitializeWrapper.
  66. MiniportCharacteritics - The NDIS_MINIPORT_CHARACTERISTICS table.
  67. CharacteristicsLength - The length of MiniportCharacteristics.
  68. DriverHandle - Returns a handle which can be used to call NdisMInitializeDeviceInstance.
  69. Return Value:
  70. None.
  71. --*/
  72. {
  73. NDIS_STATUS Status;
  74. DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO,
  75. ("==>NdisIMRegisterLayeredMiniport: NdisWrapperHandle %p\n", NdisWrapperHandle));
  76. Status = ndisRegisterMiniportDriver(NdisWrapperHandle,
  77. MiniportCharacteristics,
  78. CharacteristicsLength,
  79. DriverHandle);
  80. if (Status == NDIS_STATUS_SUCCESS)
  81. {
  82. PNDIS_M_DRIVER_BLOCK MiniBlock = (PNDIS_M_DRIVER_BLOCK)(*DriverHandle);
  83. MiniBlock->Flags |= fMINIBLOCK_INTERMEDIATE_DRIVER;
  84. INITIALIZE_MUTEX(&MiniBlock->IMStartRemoveMutex);
  85. }
  86. DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO,
  87. ("<==NdisIMRegisterLayeredMiniport: MiniBlock %p, Status %lx\n", *DriverHandle, Status));
  88. return Status;
  89. }
  90. VOID
  91. NdisIMDeregisterLayeredMiniport(
  92. IN NDIS_HANDLE DriverHandle
  93. )
  94. {
  95. //
  96. // Do nothing for now
  97. //
  98. }
  99. VOID
  100. NdisIMAssociateMiniport(
  101. IN NDIS_HANDLE DriverHandle,
  102. IN NDIS_HANDLE ProtocolHandle
  103. )
  104. {
  105. PNDIS_M_DRIVER_BLOCK MiniDriver = (PNDIS_M_DRIVER_BLOCK)DriverHandle;
  106. PNDIS_PROTOCOL_BLOCK Protocol = (PNDIS_PROTOCOL_BLOCK)ProtocolHandle;
  107. MiniDriver->AssociatedProtocol = Protocol;
  108. Protocol->AssociatedMiniDriver = MiniDriver;
  109. }
  110. NDIS_STATUS
  111. ndisRegisterMiniportDriver(
  112. IN NDIS_HANDLE NdisWrapperHandle,
  113. IN PNDIS_MINIPORT_CHARACTERISTICS MiniportCharacteristics,
  114. IN UINT CharacteristicsLength,
  115. OUT PNDIS_HANDLE DriverHandle
  116. )
  117. /*++
  118. Routine Description:
  119. Used to register a layered Miniport driver with the wrapper.
  120. Arguments:
  121. Status - Status of the operation.
  122. NdisWrapperHandle - Handle returned by NdisWInitializeWrapper.
  123. MiniportCharacteritics - The NDIS_MINIPORT_CHARACTERISTICS table.
  124. CharacteristicsLength - The length of MiniportCharacteristics.
  125. DriverHandle - Returns a handle which can be used to call NdisMInitializeDeviceInstance.
  126. Return Value:
  127. None.
  128. --*/
  129. {
  130. PNDIS_M_DRIVER_BLOCK MiniBlock;
  131. PNDIS_WRAPPER_HANDLE DriverInfo = (PNDIS_WRAPPER_HANDLE)NdisWrapperHandle;
  132. UNICODE_STRING Us;
  133. PWSTR pWch;
  134. USHORT i, size;
  135. NDIS_STATUS Status;
  136. KIRQL OldIrql;
  137. DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO,
  138. ("==>ndisRegisterMiniportDriver: NdisWrapperHandle %p\n", NdisWrapperHandle));
  139. do
  140. {
  141. if (DriverInfo == NULL)
  142. {
  143. Status = NDIS_STATUS_FAILURE;
  144. break;
  145. }
  146. //
  147. // Check version numbers and CharacteristicsLength.
  148. //
  149. size = 0; // Used to indicate bad version below
  150. if (MiniportCharacteristics->MinorNdisVersion == 0)
  151. {
  152. if (MiniportCharacteristics->MajorNdisVersion == 3)
  153. {
  154. size = sizeof(NDIS30_MINIPORT_CHARACTERISTICS);
  155. }
  156. else if (MiniportCharacteristics->MajorNdisVersion == 4)
  157. {
  158. size = sizeof(NDIS40_MINIPORT_CHARACTERISTICS);
  159. }
  160. else if (MiniportCharacteristics->MajorNdisVersion == 5)
  161. {
  162. size = sizeof(NDIS50_MINIPORT_CHARACTERISTICS);
  163. }
  164. }
  165. else if (MiniportCharacteristics->MinorNdisVersion == 1)
  166. {
  167. if (MiniportCharacteristics->MajorNdisVersion == 5)
  168. {
  169. size = sizeof(NDIS51_MINIPORT_CHARACTERISTICS);
  170. }
  171. }
  172. //
  173. // Check that this is an NDIS 3.0/4.0/5.0 miniport.
  174. //
  175. if (size == 0)
  176. {
  177. Status = NDIS_STATUS_BAD_VERSION;
  178. break;
  179. }
  180. //
  181. // Check that CharacteristicsLength is enough.
  182. //
  183. if (CharacteristicsLength < size)
  184. {
  185. Status = NDIS_STATUS_BAD_CHARACTERISTICS;
  186. break;
  187. }
  188. //
  189. // Validate some stuff for NDIS 5.0
  190. //
  191. if (MiniportCharacteristics->MajorNdisVersion == 5)
  192. {
  193. if (MiniportCharacteristics->CoSendPacketsHandler != NULL)
  194. {
  195. if (MiniportCharacteristics->CoRequestHandler == NULL)
  196. {
  197. Status = NDIS_STATUS_BAD_CHARACTERISTICS;
  198. break;
  199. }
  200. }
  201. if (MiniportCharacteristics->MinorNdisVersion >= 1)
  202. {
  203. //
  204. // for 5.1 miniports, having an AdapterShutdownHandler is mandatory
  205. //
  206. if (MiniportCharacteristics->AdapterShutdownHandler == NULL)
  207. {
  208. Status = NDIS_STATUS_BAD_CHARACTERISTICS;
  209. break;
  210. }
  211. }
  212. }
  213. //
  214. // Allocate memory for the NDIS MINIPORT block.
  215. //
  216. Status = IoAllocateDriverObjectExtension(DriverInfo->DriverObject, // DriverObject
  217. (PVOID)NDIS_PNP_MINIPORT_DRIVER_ID,// MiniDriver magic number
  218. sizeof(NDIS_M_DRIVER_BLOCK),
  219. (PVOID)&MiniBlock);
  220. if (!NT_SUCCESS(Status))
  221. {
  222. Status = NDIS_STATUS_RESOURCES;
  223. break;
  224. }
  225. ZeroMemory(MiniBlock, sizeof(NDIS_M_DRIVER_BLOCK));
  226. //
  227. // Copy over the characteristics table.
  228. //
  229. CopyMemory(&MiniBlock->MiniportCharacteristics,
  230. MiniportCharacteristics,
  231. size);
  232. //
  233. // Check if the Driver is verifying
  234. //
  235. if (MmIsDriverVerifying(DriverInfo->DriverObject))
  236. {
  237. MiniBlock->Flags |= fMINIBLOCK_VERIFYING;
  238. if (ndisFlags & NDIS_GFLAG_TRACK_MEM_ALLOCATION)
  239. {
  240. if (ndisDriverTrackAlloc == NULL)
  241. {
  242. ndisDriverTrackAlloc = MiniBlock;
  243. }
  244. else
  245. {
  246. //
  247. // tracking memory alocation is allowed
  248. // for one driver only. otherwise null out the
  249. // global ndisDriverTrackAlloc to avoid confusion
  250. // memory allocations will continue to get tracked
  251. // but the result will not be very useful
  252. //
  253. ndisDriverTrackAlloc = NULL;
  254. }
  255. }
  256. }
  257. //
  258. // No adapters yet registered for this Miniport.
  259. //
  260. MiniBlock->MiniportQueue = (PNDIS_MINIPORT_BLOCK)NULL;
  261. //
  262. // Set up the handlers for this driver. First setup Dummy handlers and then specific ones
  263. //
  264. for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++)
  265. {
  266. DriverInfo->DriverObject->MajorFunction[i] = ndisDummyIrpHandler;
  267. }
  268. //
  269. // set up AddDevice handler for this miniport
  270. //
  271. DriverInfo->DriverObject->DriverExtension->AddDevice = ndisPnPAddDevice;
  272. //
  273. // Set up unload handler
  274. //
  275. DriverInfo->DriverObject->DriverUnload = ndisMUnload;
  276. DriverInfo->DriverObject->MajorFunction[IRP_MJ_CREATE] = ndisCreateIrpHandler;
  277. DriverInfo->DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ndisDeviceControlIrpHandler;
  278. DriverInfo->DriverObject->MajorFunction[IRP_MJ_CLOSE] = ndisCloseIrpHandler;
  279. //
  280. // setup a handler for PnP messages
  281. //
  282. DriverInfo->DriverObject->MajorFunction[IRP_MJ_PNP] = ndisPnPDispatch;
  283. DriverInfo->DriverObject->MajorFunction[IRP_MJ_POWER] = ndisPowerDispatch;
  284. DriverInfo->DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = ndisWMIDispatch;
  285. //
  286. // Use this event to tell us when all adapters are removed from the mac
  287. // during an unload
  288. //
  289. INITIALIZE_EVENT(&MiniBlock->MiniportsRemovedEvent);
  290. // let the initial state stay reset, because the ref count
  291. // going to zero is going to signal the event
  292. MiniBlock->NdisDriverInfo = DriverInfo;
  293. InitializeListHead(&MiniBlock->DeviceList);
  294. ndisInitializeRef(&MiniBlock->Ref);
  295. //
  296. // Put Driver on global list.
  297. //
  298. PnPReferencePackage();
  299. ACQUIRE_SPIN_LOCK(&ndisMiniDriverListLock, &OldIrql);
  300. MiniBlock->NextDriver = ndisMiniDriverList;
  301. ndisMiniDriverList = MiniBlock;
  302. REF_NDIS_DRIVER_OBJECT();
  303. RELEASE_SPIN_LOCK(&ndisMiniDriverListLock, OldIrql);
  304. PnPDereferencePackage();
  305. *DriverHandle = MiniBlock;
  306. Status = NDIS_STATUS_SUCCESS;
  307. } while (FALSE);
  308. DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO,
  309. ("<==ndisRegisterMiniportDriver: MiniBlock %p\n", MiniBlock));
  310. return Status;
  311. }
  312. NDIS_STATUS
  313. NdisMRegisterDevice(
  314. IN NDIS_HANDLE NdisWrapperHandle,
  315. IN PNDIS_STRING DeviceName,
  316. IN PNDIS_STRING SymbolicName,
  317. IN PDRIVER_DISPATCH * MajorFunctions,
  318. OUT PDEVICE_OBJECT * pDeviceObject,
  319. OUT NDIS_HANDLE * NdisDeviceHandle
  320. )
  321. /*++
  322. Routine Description:
  323. Arguments:
  324. Return Value:
  325. --*/
  326. {
  327. PNDIS_WRAPPER_HANDLE DriverInfo = (PNDIS_WRAPPER_HANDLE)NdisWrapperHandle;
  328. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  329. PDRIVER_OBJECT DriverObject;
  330. PDEVICE_OBJECT DeviceObject;
  331. PNDIS_M_DRIVER_BLOCK MiniBlock;
  332. PNDIS_MINIPORT_BLOCK Miniport;
  333. PNDIS_DEVICE_LIST DeviceList = NULL;
  334. KIRQL OldIrql;
  335. *pDeviceObject = NULL;
  336. *NdisDeviceHandle = NULL;
  337. //
  338. // Check if the passed parameter is a NdisWrapperHandle or NdisMiniportHandle
  339. //
  340. if (DriverInfo->DriverObject == NULL)
  341. {
  342. Miniport = (PNDIS_MINIPORT_BLOCK)NdisWrapperHandle;
  343. MiniBlock = Miniport->DriverHandle;
  344. }
  345. else
  346. {
  347. MiniBlock = (PNDIS_M_DRIVER_BLOCK)IoGetDriverObjectExtension(DriverInfo->DriverObject,
  348. (PVOID)NDIS_PNP_MINIPORT_DRIVER_ID);
  349. }
  350. if (MiniBlock != NULL)
  351. {
  352. DriverObject = MiniBlock->NdisDriverInfo->DriverObject;
  353. Status = IoCreateDevice(DriverObject, // DriverObject
  354. sizeof(NDIS_WRAPPER_CONTEXT) +
  355. sizeof(NDIS_DEVICE_LIST) + // DeviceExtension
  356. DeviceName->Length + sizeof(WCHAR) +
  357. SymbolicName->Length + sizeof(WCHAR),
  358. DeviceName, // DeviceName
  359. FILE_DEVICE_NETWORK, // DeviceType
  360. FILE_DEVICE_SECURE_OPEN, // DeviceCharacteristics
  361. FALSE, // Exclusive
  362. &DeviceObject); // DeviceObject
  363. if (NT_SUCCESS(Status))
  364. {
  365. DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
  366. Status = IoCreateSymbolicLink(SymbolicName, DeviceName);
  367. if (!NT_SUCCESS(Status))
  368. {
  369. IoDeleteDevice(DeviceObject);
  370. }
  371. else
  372. {
  373. DeviceList = (PNDIS_DEVICE_LIST)((PNDIS_WRAPPER_CONTEXT)DeviceObject->DeviceExtension + 1);
  374. RtlZeroMemory(DeviceList, sizeof(NDIS_DEVICE_LIST) +
  375. DeviceName->Length + sizeof(WCHAR) +
  376. SymbolicName->Length + sizeof(WCHAR));
  377. DeviceList->Signature = (PVOID)CUSTOM_DEVICE_MAGIC_VALUE;
  378. InitializeListHead(&DeviceList->List);
  379. DeviceList->MiniBlock = MiniBlock;
  380. DeviceList->DeviceObject = DeviceObject;
  381. RtlCopyMemory(DeviceList->MajorFunctions,
  382. MajorFunctions,
  383. (IRP_MJ_MAXIMUM_FUNCTION+1)*sizeof(PDRIVER_DISPATCH));
  384. DeviceList->DeviceName.Buffer = (PWCHAR)(DeviceList + 1);
  385. DeviceList->DeviceName.Length = DeviceName->Length;
  386. DeviceList->DeviceName.MaximumLength = DeviceName->Length + sizeof(WCHAR);
  387. RtlCopyMemory(DeviceList->DeviceName.Buffer,
  388. DeviceName->Buffer,
  389. DeviceName->Length);
  390. DeviceList->SymbolicLinkName.Buffer = (PWCHAR)((PUCHAR)DeviceList->DeviceName.Buffer + DeviceList->DeviceName.MaximumLength);
  391. DeviceList->SymbolicLinkName.Length = SymbolicName->Length;
  392. DeviceList->SymbolicLinkName.MaximumLength = SymbolicName->Length + sizeof(WCHAR);
  393. RtlCopyMemory(DeviceList->SymbolicLinkName.Buffer,
  394. SymbolicName->Buffer,
  395. SymbolicName->Length);
  396. PnPReferencePackage();
  397. ACQUIRE_SPIN_LOCK(&MiniBlock->Ref.SpinLock, &OldIrql);
  398. InsertHeadList(&MiniBlock->DeviceList, &DeviceList->List);
  399. RELEASE_SPIN_LOCK(&MiniBlock->Ref.SpinLock, OldIrql);
  400. PnPDereferencePackage();
  401. *pDeviceObject = DeviceObject;
  402. *NdisDeviceHandle = DeviceList;
  403. }
  404. }
  405. }
  406. else
  407. {
  408. Status = NDIS_STATUS_NOT_SUPPORTED;
  409. }
  410. return Status;
  411. }
  412. NDIS_STATUS
  413. NdisMDeregisterDevice(
  414. IN NDIS_HANDLE NdisDeviceHandle
  415. )
  416. /*++
  417. Routine Description:
  418. Arguments:
  419. Return Value:
  420. --*/
  421. {
  422. PNDIS_DEVICE_LIST DeviceList = (PNDIS_DEVICE_LIST)NdisDeviceHandle;
  423. PNDIS_M_DRIVER_BLOCK MiniBlock;
  424. KIRQL OldIrql;
  425. MiniBlock = DeviceList->MiniBlock;
  426. PnPReferencePackage();
  427. ACQUIRE_SPIN_LOCK(&MiniBlock->Ref.SpinLock, &OldIrql);
  428. RemoveEntryList(&DeviceList->List);
  429. RELEASE_SPIN_LOCK(&MiniBlock->Ref.SpinLock, OldIrql);
  430. PnPDereferencePackage();
  431. IoDeleteSymbolicLink(&DeviceList->SymbolicLinkName);
  432. IoDeleteDevice(DeviceList->DeviceObject);
  433. return NDIS_STATUS_SUCCESS;
  434. }
  435. VOID
  436. NdisMRegisterUnloadHandler(
  437. IN NDIS_HANDLE NdisWrapperHandle,
  438. IN PDRIVER_UNLOAD UnloadHandler
  439. )
  440. {
  441. PNDIS_WRAPPER_HANDLE DriverInfo = (PNDIS_WRAPPER_HANDLE)NdisWrapperHandle;
  442. PNDIS_M_DRIVER_BLOCK MiniBlock;
  443. if (DriverInfo->DriverObject == NULL)
  444. {
  445. MiniBlock = (PNDIS_M_DRIVER_BLOCK)NdisWrapperHandle;
  446. }
  447. else
  448. {
  449. MiniBlock = (PNDIS_M_DRIVER_BLOCK)IoGetDriverObjectExtension(DriverInfo->DriverObject,
  450. (PVOID)NDIS_PNP_MINIPORT_DRIVER_ID);
  451. }
  452. if (MiniBlock != NULL)
  453. {
  454. MiniBlock->UnloadHandler = UnloadHandler;
  455. }
  456. }
  457. NDIS_STATUS
  458. NdisIMDeInitializeDeviceInstance(
  459. IN NDIS_HANDLE NdisMiniportHandle
  460. )
  461. /*++
  462. Routine Description:
  463. Arguments:
  464. Return Value:
  465. --*/
  466. {
  467. PNDIS_MINIPORT_BLOCK Miniport;
  468. PNDIS_M_DRIVER_BLOCK MiniBlock;
  469. NDIS_STATUS Status = NDIS_STATUS_FAILURE;
  470. DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO,
  471. ("==>NdisIMDeInitializeDeviceInstance: Miniport %p\n", NdisMiniportHandle));
  472. ASSERT (KeGetCurrentIrql() < DISPATCH_LEVEL);
  473. Miniport = (PNDIS_MINIPORT_BLOCK)NdisMiniportHandle;
  474. MiniBlock = Miniport->DriverHandle;
  475. if (MINIPORT_INCREMENT_REF(Miniport))
  476. {
  477. ndisReferenceDriver(MiniBlock);
  478. //
  479. // for all practical purposes we want the same thing happens as in
  480. // stopping the device, i.e. device objects remain and some certain fields that
  481. // get initialized during AddDevice to be preserved.
  482. //
  483. Miniport->PnPDeviceState = NdisPnPDeviceStopped;
  484. ndisPnPRemoveDevice(Miniport->DeviceObject, NULL);
  485. Miniport->CurrentDevicePowerState = PowerDeviceUnspecified;
  486. MINIPORT_DECREMENT_REF(Miniport);
  487. ndisDereferenceDriver(MiniBlock, FALSE);
  488. Status = NDIS_STATUS_SUCCESS;
  489. }
  490. DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO,
  491. ("<==NdisIMDeInitializeDeviceInstance: Miniport %p, Status %lx\n", NdisMiniportHandle, Status));
  492. return Status;
  493. }
  494. VOID
  495. ndisMFinishQueuedPendingOpen(
  496. IN PNDIS_POST_OPEN_PROCESSING PostOpen
  497. )
  498. /*++
  499. Routine Description:
  500. Handles any pending NdisOpenAdapter() calls for miniports.
  501. Arguments:
  502. PostOpen: a tempoary structure to carry the open information around
  503. Return Value:
  504. Returns the status code of the open.
  505. --*/
  506. {
  507. PNDIS_OPEN_BLOCK Open = PostOpen->Open;
  508. PNDIS_MINIPORT_BLOCK Miniport = Open->MiniportHandle;
  509. PNDIS_AF_NOTIFY AfNotify = NULL;
  510. NDIS_STATUS Status;
  511. UINT OpenRef;
  512. KIRQL OldIrql;
  513. DBGPRINT_RAW(DBG_COMP_BIND, DBG_LEVEL_INFO,
  514. ("==>ndisMFinishQueuedPendingOpen: PostOpen %p\n", PostOpen));
  515. PnPReferencePackage();
  516. NDIS_ACQUIRE_MINIPORT_SPIN_LOCK(Miniport, &OldIrql);
  517. //
  518. // If this is a binding that involves registration/open of address families, notify
  519. //
  520. ASSERT (MINIPORT_TEST_FLAG(Miniport, fMINIPORT_IS_CO) &&
  521. (Open->ProtocolHandle->ProtocolCharacteristics.CoAfRegisterNotifyHandler != NULL));
  522. Status = ndisCreateNotifyQueue(Miniport,
  523. Open,
  524. NULL,
  525. &AfNotify);
  526. NDIS_RELEASE_MINIPORT_SPIN_LOCK(Miniport, OldIrql);
  527. if (AfNotify != NULL)
  528. {
  529. //
  530. // Notify existing clients of this registration
  531. //
  532. ndisNotifyAfRegistration(AfNotify);
  533. }
  534. FREE_POOL(PostOpen);
  535. ndisDereferenceAfNotification(Open);
  536. NDIS_ACQUIRE_MINIPORT_SPIN_LOCK(Miniport, &OldIrql);
  537. ndisMDereferenceOpen(Open);
  538. NDIS_RELEASE_MINIPORT_SPIN_LOCK(Miniport, OldIrql);
  539. PnPDereferencePackage();
  540. DBGPRINT_RAW(DBG_COMP_BIND, DBG_LEVEL_INFO,
  541. ("<==ndisMFinishQueuedPendingOpen: Open %p\n", Open));
  542. }
  543. NDIS_STATUS
  544. NdisMRegisterIoPortRange(
  545. OUT PVOID * PortOffset,
  546. IN NDIS_HANDLE MiniportAdapterHandle,
  547. IN UINT InitialPort,
  548. IN UINT NumberOfPorts
  549. )
  550. /*++
  551. Routine Description:
  552. Sets up an IO port for operations.
  553. Arguments:
  554. PortOffset - The mapped port address the Miniport uses for NdisRaw functions.
  555. MiniportAdapterHandle - Handle passed to Miniport Initialize.
  556. InitialPort - Physical address of the starting port number.
  557. NumberOfPorts - Number of ports to map.
  558. Return Value:
  559. None.
  560. --*/
  561. {
  562. PNDIS_MINIPORT_BLOCK Miniport = (PNDIS_MINIPORT_BLOCK)(MiniportAdapterHandle);
  563. PHYSICAL_ADDRESS PortAddress;
  564. PHYSICAL_ADDRESS InitialPortAddress;
  565. ULONG addressSpace;
  566. NDIS_STATUS Status;
  567. PCM_PARTIAL_RESOURCE_DESCRIPTOR pResourceDescriptor = NULL;
  568. DBGPRINT_RAW(DBG_COMP_CONFIG, DBG_LEVEL_INFO,
  569. ("==>NdisMRegisterIoPortRange: Miniport %p\n", Miniport));
  570. // Miniport->InfoFlags |= NDIS_MINIPORT_USES_IO;
  571. do
  572. {
  573. if (MINIPORT_VERIFY_TEST_FLAG(Miniport, fMINIPORT_VERIFY_FAIL_REGISTER_IO))
  574. {
  575. #if DBG
  576. DbgPrint("NdisMRegisterIoPortRange failed to verify miniport %p\n", Miniport);
  577. #endif
  578. Status = NDIS_STATUS_RESOURCES;
  579. break;
  580. }
  581. InitialPortAddress.QuadPart = InitialPort;
  582. #if !defined(_M_IX86)
  583. Status = ndisTranslateResources(Miniport,
  584. CmResourceTypePort,
  585. InitialPortAddress,
  586. &PortAddress,
  587. &pResourceDescriptor);
  588. if (Status != NDIS_STATUS_SUCCESS)
  589. {
  590. Status = NDIS_STATUS_FAILURE;
  591. break;
  592. }
  593. if (pResourceDescriptor->Type == CmResourceTypeMemory)
  594. addressSpace = 0;
  595. else
  596. addressSpace = -1;
  597. if (addressSpace == 0)
  598. {
  599. //
  600. // memory space
  601. //
  602. *(PortOffset) = (PULONG)MmMapIoSpace(PortAddress,
  603. NumberOfPorts,
  604. FALSE);
  605. if (*(PortOffset) == (PULONG)NULL)
  606. {
  607. Status = NDIS_STATUS_RESOURCES;
  608. break;
  609. }
  610. }
  611. else
  612. {
  613. //
  614. // I/O space
  615. //
  616. *(PortOffset) = ULongToPtr(PortAddress.LowPart);
  617. }
  618. #else // x86 platform
  619. //
  620. // make sure the port belongs to the device
  621. //
  622. Status = ndisTranslateResources(Miniport,
  623. CmResourceTypePort,
  624. InitialPortAddress,
  625. &PortAddress,
  626. &pResourceDescriptor);
  627. if (Status != NDIS_STATUS_SUCCESS)
  628. {
  629. Status = NDIS_STATUS_FAILURE;
  630. break;
  631. }
  632. if (pResourceDescriptor->Type == CmResourceTypeMemory)
  633. {
  634. //
  635. // memory space
  636. //
  637. *(PortOffset) = (PULONG)MmMapIoSpace(PortAddress,
  638. NumberOfPorts,
  639. FALSE);
  640. if (*(PortOffset) == (PULONG)NULL)
  641. {
  642. Status = NDIS_STATUS_RESOURCES;
  643. break;
  644. }
  645. }
  646. else
  647. {
  648. //
  649. // I/O space
  650. //
  651. *(PortOffset) = (PULONG)PortAddress.LowPart;
  652. }
  653. #endif
  654. Status = NDIS_STATUS_SUCCESS;
  655. } while (FALSE);
  656. DBGPRINT_RAW(DBG_COMP_CONFIG, DBG_LEVEL_INFO,
  657. ("<==NdisMRegisterIoPortRange: Miniport %p, Status %lx\n", Miniport, Status));
  658. return Status;
  659. }
  660. VOID
  661. NdisMDeregisterIoPortRange(
  662. IN NDIS_HANDLE MiniportAdapterHandle,
  663. IN UINT InitialPort,
  664. IN UINT NumberOfPorts,
  665. IN PVOID PortOffset
  666. )
  667. /*++
  668. Routine Description:
  669. Sets up an IO port for operations.
  670. Arguments:
  671. MiniportAdapterHandle - Handle passed to Miniport Initialize.
  672. InitialPort - Physical address of the starting port number.
  673. NumberOfPorts - Number of ports to map.
  674. PortOffset - The mapped port address the Miniport uses for NdisRaw functions.
  675. Return Value:
  676. None.
  677. --*/
  678. {
  679. PNDIS_MINIPORT_BLOCK Miniport = (PNDIS_MINIPORT_BLOCK)(MiniportAdapterHandle);
  680. PHYSICAL_ADDRESS PortAddress;
  681. PHYSICAL_ADDRESS InitialPortAddress;
  682. ULONG addressSpace;
  683. CM_PARTIAL_RESOURCE_DESCRIPTOR Resource;
  684. NDIS_STATUS Status;
  685. DBGPRINT_RAW(DBG_COMP_CONFIG, DBG_LEVEL_INFO,
  686. ("==>NdisMDeregisterIoPortRange: Miniport %p\n", Miniport));
  687. DBGPRINT_RAW(DBG_COMP_CONFIG, DBG_LEVEL_INFO,
  688. ("<==NdisMDeregisterIoPortRange: Miniport %p\n", Miniport));
  689. return;
  690. }
  691. NDIS_STATUS
  692. NdisMMapIoSpace(
  693. OUT PVOID * VirtualAddress,
  694. IN NDIS_HANDLE MiniportAdapterHandle,
  695. IN NDIS_PHYSICAL_ADDRESS PhysicalAddress,
  696. IN UINT Length
  697. )
  698. {
  699. NDIS_STATUS Status;
  700. ULONG addressSpace = 0;
  701. PHYSICAL_ADDRESS PhysicalTemp;
  702. PNDIS_MINIPORT_BLOCK Miniport = (PNDIS_MINIPORT_BLOCK)(MiniportAdapterHandle);
  703. PCM_PARTIAL_RESOURCE_DESCRIPTOR pResourceDescriptor = NULL;
  704. DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO,
  705. ("==>NdisMMapIoSpace\n"));
  706. // Miniport->InfoFlags |= NDIS_MINIPORT_USES_MEMORY;
  707. if (MINIPORT_VERIFY_TEST_FLAG(Miniport, fMINIPORT_VERIFY_FAIL_MAP_IO_SPACE))
  708. {
  709. #if DBG
  710. DbgPrint("NdisMMapIoSpace failed to verify miniport %p\n", Miniport);
  711. #endif
  712. *VirtualAddress = NULL;
  713. return NDIS_STATUS_RESOURCES;
  714. }
  715. do
  716. {
  717. #if !defined(_M_IX86)
  718. PhysicalTemp.HighPart = 0;
  719. Status = ndisTranslateResources(Miniport,
  720. CmResourceTypeMemory,
  721. PhysicalAddress,
  722. &PhysicalTemp,
  723. &pResourceDescriptor);
  724. if (Status != NDIS_STATUS_SUCCESS)
  725. {
  726. Status = NDIS_STATUS_FAILURE;
  727. break;
  728. }
  729. if (pResourceDescriptor->Type == CmResourceTypeMemory)
  730. addressSpace = 0;
  731. else
  732. addressSpace = -1;
  733. #else
  734. addressSpace = 0; // need to do MmMapIoSpace
  735. Status = ndisTranslateResources(Miniport,
  736. CmResourceTypeMemory,
  737. PhysicalAddress,
  738. &PhysicalTemp,
  739. &pResourceDescriptor);
  740. if (Status != NDIS_STATUS_SUCCESS)
  741. {
  742. Status = NDIS_STATUS_FAILURE;
  743. break;
  744. }
  745. #endif
  746. if (addressSpace == 0)
  747. {
  748. *VirtualAddress = MmMapIoSpace(PhysicalTemp, (Length), FALSE);
  749. }
  750. else
  751. {
  752. *VirtualAddress = ULongToPtr(PhysicalTemp.LowPart);
  753. }
  754. Status = NDIS_STATUS_SUCCESS;
  755. if (*VirtualAddress == NULL)
  756. {
  757. Status = NDIS_STATUS_RESOURCES;
  758. }
  759. } while (FALSE);
  760. DBGPRINT_RAW(DBG_COMP_CONFIG, DBG_LEVEL_INFO,
  761. ("<==NdisMMapIoSpace: Miniport %p, Status %lx\n", MiniportAdapterHandle, Status));
  762. return Status;
  763. }
  764. VOID
  765. NdisMUnmapIoSpace(
  766. IN NDIS_HANDLE MiniportAdapterHandle,
  767. IN PVOID VirtualAddress,
  768. IN UINT Length
  769. )
  770. {
  771. DBGPRINT_RAW(DBG_COMP_CONFIG, DBG_LEVEL_INFO,
  772. ("==>NdisMUnmapIoSpace: Miniport %p\n", MiniportAdapterHandle));
  773. #ifndef _ALPHA_
  774. MmUnmapIoSpace(VirtualAddress, Length);
  775. #endif
  776. DBGPRINT_RAW(DBG_COMP_CONFIG, DBG_LEVEL_INFO,
  777. ("<==NdisMUnmapIoSpace: Miniport %p\n", MiniportAdapterHandle));
  778. }
  779. VOID
  780. NdisMAllocateSharedMemory(
  781. IN NDIS_HANDLE MiniportAdapterHandle,
  782. IN ULONG Length,
  783. IN BOOLEAN Cached,
  784. OUT PVOID * VirtualAddress,
  785. OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress
  786. )
  787. {
  788. PNDIS_MINIPORT_BLOCK Miniport = (PNDIS_MINIPORT_BLOCK)MiniportAdapterHandle;
  789. PDMA_ADAPTER SystemAdapterObject;
  790. PNDIS_WRAPPER_CONTEXT WrapperContext;
  791. PULONG Page;
  792. ULONG Type;
  793. PNDIS_SHARED_MEM_SIGNATURE pSharedMemSignature = NULL;
  794. // Miniport->InfoFlags |= NDIS_MINIPORT_USES_SHARED_MEMORY;
  795. SystemAdapterObject = Miniport->SystemAdapterObject;
  796. WrapperContext = Miniport->WrapperContext;
  797. DBGPRINT_RAW(DBG_COMP_CONFIG, DBG_LEVEL_INFO,
  798. ("==>NdisMAllocateSharedMemory: Miniport %p, Length %lx\n", Miniport, Length));
  799. PhysicalAddress->HighPart = PhysicalAddress->LowPart = 0;
  800. if (MINIPORT_VERIFY_TEST_FLAG(Miniport, fMINIPORT_VERIFY_FAIL_SHARED_MEM_ALLOC))
  801. {
  802. #if DBG
  803. DbgPrint("NdisMAllocateSharedMemory failed to verify miniport %p\n", Miniport);
  804. #endif
  805. *VirtualAddress = NULL;
  806. DBGPRINT_RAW(DBG_COMP_CONFIG, DBG_LEVEL_INFO,
  807. ("<==NdisMAllocateSharedMemory: Miniport %p, Length %lx\n", Miniport, Length));
  808. return;
  809. }
  810. if (Miniport->SystemAdapterObject == NULL)
  811. {
  812. *VirtualAddress = NULL;
  813. return;
  814. }
  815. if (CURRENT_IRQL >= DISPATCH_LEVEL)
  816. {
  817. BAD_MINIPORT(Miniport, "Allocating Shared Memory at raised IRQL");
  818. KeBugCheckEx(BUGCODE_ID_DRIVER,
  819. (ULONG_PTR)Miniport,
  820. Length,
  821. 0,
  822. 1);
  823. }
  824. //
  825. // Compute allocation size by aligning to the proper boundary.
  826. //
  827. ASSERT(Length != 0);
  828. Length = (Length + ndisDmaAlignment - 1) & ~(ndisDmaAlignment - 1);
  829. //
  830. // Check to determine is there is enough room left in the current page
  831. // to satisfy the allocation.
  832. //
  833. Type = Cached ? 1 : 0;
  834. ExAcquireResourceExclusiveLite(&SharedMemoryResource, TRUE);
  835. do
  836. {
  837. PALLOCATE_COMMON_BUFFER allocateCommonBuffer;
  838. allocateCommonBuffer = *SystemAdapterObject->DmaOperations->AllocateCommonBuffer;
  839. if (WrapperContext->SharedMemoryLeft[Type] < Length)
  840. {
  841. if ((Length + sizeof(NDIS_SHARED_MEM_SIGNATURE)) >= PAGE_SIZE)
  842. {
  843. //
  844. // The allocation is greater than a page.
  845. //
  846. *VirtualAddress = allocateCommonBuffer(SystemAdapterObject,
  847. Length,
  848. PhysicalAddress,
  849. Cached);
  850. break;
  851. }
  852. //
  853. // Allocate a new page for shared alocation.
  854. //
  855. WrapperContext->SharedMemoryPage[Type] =
  856. allocateCommonBuffer(SystemAdapterObject,
  857. PAGE_SIZE,
  858. &WrapperContext->SharedMemoryAddress[Type],
  859. Cached);
  860. if (WrapperContext->SharedMemoryPage[Type] == NULL)
  861. {
  862. WrapperContext->SharedMemoryLeft[Type] = 0;
  863. *VirtualAddress = NULL;
  864. break;
  865. }
  866. //
  867. // Initialize the reference count in the last ULONG of the page.
  868. // Initialize the Tag in the second last ulong of the page
  869. //
  870. Page = (PULONG)WrapperContext->SharedMemoryPage[Type];
  871. pSharedMemSignature = (PNDIS_SHARED_MEM_SIGNATURE) ((PUCHAR)Page+ (PAGE_SIZE - sizeof(NDIS_SHARED_MEM_SIGNATURE)));
  872. pSharedMemSignature->Tag = NDIS_TAG_SHARED_MEMORY;
  873. pSharedMemSignature->PageRef = 0;
  874. WrapperContext->SharedMemoryLeft[Type] = PAGE_SIZE - sizeof(NDIS_SHARED_MEM_SIGNATURE);
  875. }
  876. //
  877. // Increment the reference count, set the address of the allocation,
  878. // compute the physical address, and reduce the space remaining.
  879. //
  880. Page = (PULONG)WrapperContext->SharedMemoryPage[Type];
  881. //
  882. // First check whether Page is pointing to shared memory. Bugcheck to catch the driver
  883. //
  884. pSharedMemSignature = (PNDIS_SHARED_MEM_SIGNATURE) ((PUCHAR)Page+ (PAGE_SIZE - sizeof(NDIS_SHARED_MEM_SIGNATURE)));
  885. if (pSharedMemSignature->Tag != NDIS_TAG_SHARED_MEMORY)
  886. {
  887. ASSERT (pSharedMemSignature->Tag == NDIS_TAG_SHARED_MEMORY);
  888. BAD_MINIPORT(Miniport, "Overwrote past allocated shared memory");
  889. KeBugCheckEx(BUGCODE_ID_DRIVER,
  890. (ULONG_PTR)Miniport,
  891. (ULONG_PTR)Page,
  892. (ULONG_PTR)WrapperContext,
  893. (ULONG_PTR)pSharedMemSignature);
  894. }
  895. pSharedMemSignature->PageRef += 1;
  896. *VirtualAddress = (PVOID)((PUCHAR)Page +
  897. (PAGE_SIZE - sizeof(NDIS_SHARED_MEM_SIGNATURE) - WrapperContext->SharedMemoryLeft[Type]));
  898. PhysicalAddress->QuadPart = WrapperContext->SharedMemoryAddress[Type].QuadPart +
  899. ((ULONG_PTR)(*VirtualAddress) & (PAGE_SIZE - 1));
  900. WrapperContext->SharedMemoryLeft[Type] -= Length;
  901. } while (FALSE);
  902. if (*VirtualAddress)
  903. {
  904. InterlockedIncrement(&Miniport->DmaAdapterRefCount);
  905. }
  906. ExReleaseResourceLite(&SharedMemoryResource);
  907. #if DBG
  908. if (*VirtualAddress == NULL)
  909. {
  910. DBGPRINT_RAW(DBG_COMP_ALL, DBG_LEVEL_ERR,
  911. ("NdisMAllocateSharedMemory: Miniport %p, allocateCommonBuffer failed for %lx bytes\n", Miniport, Length));
  912. }
  913. #endif
  914. if (!MINIPORT_TEST_FLAG(Miniport, fMINIPORT_64BITS_DMA) &&
  915. (PhysicalAddress->HighPart > 0))
  916. {
  917. #if DBG
  918. DbgPrint("NdisMAllocateSharedMemory: Miniport %p, allocateCommonBuffer returned a physical address > 4G for a"
  919. " non-64bit DMA adapter. PhysAddress->HighPart = %p", Miniport, PhysicalAddress->HighPart);
  920. #endif
  921. ASSERT(PhysicalAddress->HighPart == 0);
  922. }
  923. DBGPRINT_RAW(DBG_COMP_CONFIG, DBG_LEVEL_INFO,
  924. ("<==NdisMAllocateSharedMemory: Miniport %p, Length %lx, Virtual Address %p\n", Miniport, Length, *VirtualAddress));
  925. }
  926. NDIS_STATUS
  927. NdisMAllocateSharedMemoryAsync(
  928. IN NDIS_HANDLE MiniportAdapterHandle,
  929. IN ULONG Length,
  930. IN BOOLEAN Cached,
  931. IN PVOID Context
  932. )
  933. {
  934. //
  935. // Convert the handle to our internal structure.
  936. //
  937. PNDIS_MINIPORT_BLOCK Miniport = (PNDIS_MINIPORT_BLOCK) MiniportAdapterHandle;
  938. PASYNC_WORKITEM pWorkItem = NULL;
  939. // Miniport->InfoFlags |= NDIS_MINIPORT_USES_SHARED_MEMORY;
  940. // Allocate a workitem
  941. if ((Miniport->SystemAdapterObject != NULL) &&
  942. (Miniport->DriverHandle->MiniportCharacteristics.AllocateCompleteHandler != NULL))
  943. {
  944. pWorkItem = ALLOC_FROM_POOL(sizeof(ASYNC_WORKITEM), NDIS_TAG_ALLOC_SHARED_MEM_ASYNC);
  945. }
  946. if ((pWorkItem == NULL) ||
  947. !MINIPORT_INCREMENT_REF(Miniport))
  948. {
  949. if (pWorkItem != NULL)
  950. FREE_POOL(pWorkItem);
  951. return NDIS_STATUS_FAILURE;
  952. }
  953. InterlockedIncrement(&Miniport->DmaAdapterRefCount);
  954. // Initialize the workitem and queue it up to a worker thread
  955. pWorkItem->Miniport = Miniport;
  956. pWorkItem->Length = Length;
  957. pWorkItem->Cached = Cached;
  958. pWorkItem->Context = Context;
  959. INITIALIZE_WORK_ITEM(&pWorkItem->ExWorkItem, ndisMQueuedAllocateSharedHandler, pWorkItem);
  960. QUEUE_WORK_ITEM(&pWorkItem->ExWorkItem, CriticalWorkQueue);
  961. return NDIS_STATUS_PENDING;
  962. }
  963. VOID
  964. ndisMQueuedAllocateSharedHandler(
  965. IN PASYNC_WORKITEM pWorkItem
  966. )
  967. {
  968. KIRQL OldIrql;
  969. // Allocate the memory
  970. NdisMAllocateSharedMemory(pWorkItem->Miniport,
  971. pWorkItem->Length,
  972. pWorkItem->Cached,
  973. &pWorkItem->VAddr,
  974. &pWorkItem->PhyAddr);
  975. //
  976. // we shouldn't need to reference package here
  977. //
  978. ASSERT(ndisPkgs[NDSM_PKG].ReferenceCount > 0);
  979. if (MINIPORT_TEST_FLAG(pWorkItem->Miniport, fMINIPORT_DESERIALIZE))
  980. {
  981. KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
  982. }
  983. else
  984. {
  985. NDIS_ACQUIRE_MINIPORT_SPIN_LOCK(pWorkItem->Miniport, &OldIrql);
  986. }
  987. // Call the miniport back
  988. (*pWorkItem->Miniport->DriverHandle->MiniportCharacteristics.AllocateCompleteHandler)(
  989. pWorkItem->Miniport->MiniportAdapterContext,
  990. pWorkItem->VAddr,
  991. &pWorkItem->PhyAddr,
  992. pWorkItem->Length,
  993. pWorkItem->Context);
  994. if (MINIPORT_TEST_FLAG(pWorkItem->Miniport, fMINIPORT_DESERIALIZE))
  995. {
  996. KeLowerIrql(OldIrql);
  997. }
  998. else
  999. {
  1000. NDIS_RELEASE_MINIPORT_SPIN_LOCK(pWorkItem->Miniport, OldIrql);
  1001. }
  1002. ndisDereferenceDmaAdapter(pWorkItem->Miniport);
  1003. // Dereference the miniport
  1004. MINIPORT_DECREMENT_REF(pWorkItem->Miniport);
  1005. // And finally free the work-item
  1006. FREE_POOL(pWorkItem);
  1007. }
  1008. VOID
  1009. ndisFreeSharedMemory(
  1010. IN NDIS_HANDLE MiniportAdapterHandle,
  1011. IN ULONG Length,
  1012. IN BOOLEAN Cached,
  1013. IN PVOID VirtualAddress,
  1014. IN NDIS_PHYSICAL_ADDRESS PhysicalAddress
  1015. )
  1016. {
  1017. PNDIS_MINIPORT_BLOCK Miniport = (PNDIS_MINIPORT_BLOCK)MiniportAdapterHandle;
  1018. PDMA_ADAPTER SystemAdapterObject;
  1019. PNDIS_WRAPPER_CONTEXT WrapperContext;
  1020. PULONG Page;
  1021. ULONG Type;
  1022. PNDIS_SHARED_MEM_SIGNATURE pSharedMemSignature = NULL;
  1023. PFREE_COMMON_BUFFER freeCommonBuffer;
  1024. //
  1025. // Get interesting information from the miniport.
  1026. //
  1027. SystemAdapterObject = Miniport->SystemAdapterObject;
  1028. WrapperContext = Miniport->WrapperContext;
  1029. if (SystemAdapterObject == NULL)
  1030. {
  1031. if (Miniport->SavedSystemAdapterObject)
  1032. SystemAdapterObject = Miniport->SavedSystemAdapterObject;
  1033. //
  1034. // Non-busmasters shouldn't call this routine.
  1035. //
  1036. ASSERT(SystemAdapterObject != NULL);
  1037. #if DBG
  1038. DbgPrint("Ndis: WARNING... Miniport %p freeing shared memory -after- freeing map registers.\n", Miniport);
  1039. if (MINIPORT_PNP_TEST_FLAG(Miniport, fMINIPORT_VERIFYING) && (ndisFlags & NDIS_GFLAG_BREAK_ON_WARNING))
  1040. DbgBreakPoint();
  1041. #endif
  1042. Miniport->SystemAdapterObject = Miniport->SavedSystemAdapterObject;
  1043. }
  1044. freeCommonBuffer = *SystemAdapterObject->DmaOperations->FreeCommonBuffer;
  1045. //
  1046. // Compute allocation size by aligning to the proper boundary.
  1047. //
  1048. ASSERT(Length != 0);
  1049. Length = (Length + ndisDmaAlignment - 1) & ~(ndisDmaAlignment - 1);
  1050. //
  1051. // Free the specified memory.
  1052. //
  1053. ExAcquireResourceExclusiveLite(&SharedMemoryResource, TRUE);
  1054. if ((Length + sizeof(NDIS_SHARED_MEM_SIGNATURE)) >= PAGE_SIZE)
  1055. {
  1056. //
  1057. // The allocation is greater than a page free the page directly.
  1058. //
  1059. freeCommonBuffer(SystemAdapterObject,
  1060. Length,
  1061. PhysicalAddress,
  1062. VirtualAddress,
  1063. Cached);
  1064. }
  1065. else
  1066. {
  1067. //
  1068. // Decrement the reference count and if the result is zero, then free
  1069. // the page.
  1070. //
  1071. Page = (PULONG)((ULONG_PTR)VirtualAddress & ~(PAGE_SIZE - 1));
  1072. //
  1073. // First check whether Page is pointing to shared memory. Bugcheck to catch the driver
  1074. //
  1075. pSharedMemSignature = (PNDIS_SHARED_MEM_SIGNATURE) ((PUCHAR)Page + (PAGE_SIZE - sizeof(NDIS_SHARED_MEM_SIGNATURE)));
  1076. if (pSharedMemSignature->Tag != NDIS_TAG_SHARED_MEMORY)
  1077. {
  1078. ASSERT (pSharedMemSignature->Tag == NDIS_TAG_SHARED_MEMORY);
  1079. BAD_MINIPORT(Miniport, "Freeing shared memory not allocated");
  1080. KeBugCheckEx(BUGCODE_ID_DRIVER,
  1081. (ULONG_PTR)Miniport,
  1082. (ULONG_PTR)Page,
  1083. (ULONG_PTR)pSharedMemSignature,
  1084. (ULONG_PTR)VirtualAddress );
  1085. }
  1086. pSharedMemSignature->PageRef -= 1;
  1087. //
  1088. // If the references on the page have gone to zero then free the page
  1089. //
  1090. if (pSharedMemSignature->PageRef == 0)
  1091. {
  1092. //
  1093. // Compute the physical address of the page and free it.
  1094. //
  1095. PhysicalAddress.LowPart &= ~(PAGE_SIZE - 1);
  1096. freeCommonBuffer(SystemAdapterObject,
  1097. PAGE_SIZE,
  1098. PhysicalAddress,
  1099. Page,
  1100. Cached);
  1101. Type = Cached ? 1 : 0;
  1102. if ((PVOID)Page == WrapperContext->SharedMemoryPage[Type])
  1103. {
  1104. WrapperContext->SharedMemoryLeft[Type] = 0;
  1105. WrapperContext->SharedMemoryPage[Type] = NULL;
  1106. }
  1107. }
  1108. }
  1109. ndisDereferenceDmaAdapter(Miniport);
  1110. ExReleaseResourceLite(&SharedMemoryResource);
  1111. }
  1112. VOID
  1113. NdisMFreeSharedMemory(
  1114. IN NDIS_HANDLE MiniportAdapterHandle,
  1115. IN ULONG Length,
  1116. IN BOOLEAN Cached,
  1117. IN PVOID VirtualAddress,
  1118. IN NDIS_PHYSICAL_ADDRESS PhysicalAddress
  1119. )
  1120. {
  1121. PNDIS_MINIPORT_BLOCK Miniport = (PNDIS_MINIPORT_BLOCK)MiniportAdapterHandle;
  1122. if (CURRENT_IRQL < DISPATCH_LEVEL)
  1123. {
  1124. ndisFreeSharedMemory(MiniportAdapterHandle,
  1125. Length,
  1126. Cached,
  1127. VirtualAddress,
  1128. PhysicalAddress);
  1129. }
  1130. else if (MINIPORT_INCREMENT_REF(Miniport))
  1131. {
  1132. PASYNC_WORKITEM pWorkItem = NULL;
  1133. // Allocate a work-item and queue it up to a worker thread
  1134. pWorkItem = ALLOC_FROM_POOL(sizeof(ASYNC_WORKITEM), NDIS_TAG_FREE_SHARED_MEM_ASYNC);
  1135. if (pWorkItem != NULL)
  1136. {
  1137. // Initialize the workitem and queue it up to a worker thread
  1138. pWorkItem->Miniport = Miniport;
  1139. pWorkItem->Length = Length;
  1140. pWorkItem->Cached = Cached;
  1141. pWorkItem->VAddr = VirtualAddress;
  1142. pWorkItem->PhyAddr = PhysicalAddress;
  1143. INITIALIZE_WORK_ITEM(&pWorkItem->ExWorkItem, ndisMQueuedFreeSharedHandler, pWorkItem);
  1144. QUEUE_WORK_ITEM(&pWorkItem->ExWorkItem, CriticalWorkQueue);
  1145. }
  1146. // What do we do now ?
  1147. }
  1148. }
  1149. VOID
  1150. ndisMQueuedFreeSharedHandler(
  1151. IN PASYNC_WORKITEM pWorkItem
  1152. )
  1153. {
  1154. // Free the memory
  1155. ndisFreeSharedMemory(pWorkItem->Miniport,
  1156. pWorkItem->Length,
  1157. pWorkItem->Cached,
  1158. pWorkItem->VAddr,
  1159. pWorkItem->PhyAddr);
  1160. // Dereference the miniport
  1161. MINIPORT_DECREMENT_REF(pWorkItem->Miniport);
  1162. // And finally free the work-item
  1163. FREE_POOL(pWorkItem);
  1164. }
  1165. NDIS_STATUS
  1166. NdisMRegisterDmaChannel(
  1167. OUT PNDIS_HANDLE MiniportDmaHandle,
  1168. IN NDIS_HANDLE MiniportAdapterHandle,
  1169. IN UINT DmaChannel,
  1170. IN BOOLEAN Dma32BitAddresses,
  1171. IN PNDIS_DMA_DESCRIPTION DmaDescription,
  1172. IN ULONG MaximumLength
  1173. )
  1174. {
  1175. PNDIS_MINIPORT_BLOCK Miniport = (PNDIS_MINIPORT_BLOCK)(MiniportAdapterHandle);
  1176. NDIS_STATUS Status;
  1177. NDIS_INTERFACE_TYPE BusType;
  1178. ULONG BusNumber;
  1179. DEVICE_DESCRIPTION DeviceDescription;
  1180. PDMA_ADAPTER AdapterObject;
  1181. ULONG MapRegistersNeeded;
  1182. ULONG MapRegistersAllowed;
  1183. PNDIS_DMA_BLOCK DmaBlock;
  1184. KIRQL OldIrql;
  1185. NTSTATUS NtStatus;
  1186. DBGPRINT_RAW(DBG_COMP_CONFIG, DBG_LEVEL_INFO,
  1187. ("==>NdisMRegisterDmaChannel: Miniport %p\n", Miniport));
  1188. BusType = Miniport->BusType;
  1189. BusNumber = Miniport->BusNumber;
  1190. do
  1191. {
  1192. //
  1193. // Set up the device description; zero it out in case its
  1194. // size changes.
  1195. //
  1196. ZeroMemory(&DeviceDescription, sizeof(DEVICE_DESCRIPTION));
  1197. DeviceDescription.Version = DEVICE_DESCRIPTION_VERSION;
  1198. DeviceDescription.Master = MINIPORT_TEST_FLAG(Miniport, fMINIPORT_BUS_MASTER);
  1199. DeviceDescription.ScatterGather = MINIPORT_TEST_FLAG(Miniport, fMINIPORT_BUS_MASTER);
  1200. DeviceDescription.DemandMode = DmaDescription->DemandMode;
  1201. DeviceDescription.AutoInitialize = DmaDescription->AutoInitialize;
  1202. DeviceDescription.Dma32BitAddresses = Dma32BitAddresses;
  1203. DeviceDescription.BusNumber = Miniport->BusNumber;
  1204. DeviceDescription.DmaChannel = DmaChannel;
  1205. DeviceDescription.InterfaceType = BusType;
  1206. DeviceDescription.DmaWidth = DmaDescription->DmaWidth;
  1207. DeviceDescription.DmaSpeed = DmaDescription->DmaSpeed;
  1208. DeviceDescription.MaximumLength = MaximumLength;
  1209. DeviceDescription.DmaPort = DmaDescription->DmaPort;
  1210. MapRegistersNeeded = ((MaximumLength - 2) / PAGE_SIZE) + 2;
  1211. //
  1212. // Get the adapter object.
  1213. //
  1214. AdapterObject =
  1215. IoGetDmaAdapter(Miniport->PhysicalDeviceObject,
  1216. &DeviceDescription,
  1217. &MapRegistersAllowed);
  1218. if ((AdapterObject == NULL) || (MapRegistersAllowed < MapRegistersNeeded))
  1219. {
  1220. Status = NDIS_STATUS_RESOURCES;
  1221. break;
  1222. }
  1223. //
  1224. // Allocate storage for our DMA block.
  1225. //
  1226. DmaBlock = (PNDIS_DMA_BLOCK)ALLOC_FROM_POOL(sizeof(NDIS_DMA_BLOCK), NDIS_TAG_DMA);
  1227. if (DmaBlock == (PNDIS_DMA_BLOCK)NULL)
  1228. {
  1229. Status = NDIS_STATUS_RESOURCES;
  1230. break;
  1231. }
  1232. //
  1233. // Use this event to tell us when ndisAllocationExecutionRoutine
  1234. // has been called.
  1235. //
  1236. INITIALIZE_EVENT(&DmaBlock->AllocationEvent);
  1237. //
  1238. // We save this to call IoFreeAdapterChannel later.
  1239. //
  1240. (PDMA_ADAPTER)DmaBlock->SystemAdapterObject = AdapterObject;
  1241. ASSERT(ndisPkgs[NPNP_PKG].ReferenceCount > 0);
  1242. PnPReferencePackage();
  1243. //
  1244. // Now allocate the adapter channel.
  1245. //
  1246. RAISE_IRQL_TO_DISPATCH(&OldIrql);
  1247. NtStatus = AdapterObject->DmaOperations->AllocateAdapterChannel(AdapterObject,
  1248. Miniport->DeviceObject,
  1249. MapRegistersNeeded,
  1250. ndisDmaExecutionRoutine,
  1251. (PVOID)DmaBlock);
  1252. LOWER_IRQL(OldIrql, DISPATCH_LEVEL);
  1253. PnPDereferencePackage();
  1254. if (!NT_SUCCESS(NtStatus))
  1255. {
  1256. DBGPRINT_RAW(DBG_COMP_ALL, DBG_LEVEL_ERR,
  1257. ("NDIS DMA AllocateAdapterChannel: %lx\n", NtStatus));
  1258. FREE_POOL(DmaBlock);
  1259. Status = NDIS_STATUS_RESOURCES;
  1260. break;
  1261. }
  1262. //
  1263. // ndisDmaExecutionRoutine will set this event
  1264. // when it has been called.
  1265. //
  1266. NtStatus = WAIT_FOR_OBJECT(&DmaBlock->AllocationEvent, 0);
  1267. if (!NT_SUCCESS(NtStatus))
  1268. {
  1269. DBGPRINT_RAW(DBG_COMP_ALL, DBG_LEVEL_ERR,
  1270. ("NDIS DMA AllocateAdapterChannel: %lx\n", NtStatus));
  1271. FREE_POOL(DmaBlock);
  1272. Status = NDIS_STATUS_RESOURCES;
  1273. break;
  1274. }
  1275. RESET_EVENT(&DmaBlock->AllocationEvent);
  1276. //
  1277. // We now have the DMA channel allocated, we are done.
  1278. //
  1279. DmaBlock->InProgress = FALSE;
  1280. *MiniportDmaHandle = (NDIS_HANDLE)DmaBlock;
  1281. Status = NDIS_STATUS_SUCCESS;
  1282. } while (FALSE);
  1283. DBGPRINT_RAW(DBG_COMP_CONFIG, DBG_LEVEL_INFO,
  1284. ("<==NdisMRegisterDmaChannel: Miniport %p, Status %lx\n", Miniport, Status));
  1285. return Status;
  1286. }
  1287. VOID
  1288. NdisMDeregisterDmaChannel(
  1289. IN NDIS_HANDLE MiniportDmaHandle
  1290. )
  1291. {
  1292. KIRQL OldIrql;
  1293. PNDIS_DMA_BLOCK DmaBlock = (PNDIS_DMA_BLOCK)MiniportDmaHandle;
  1294. PPUT_DMA_ADAPTER putDmaAdapter;
  1295. DBGPRINT_RAW(DBG_COMP_CONFIG, DBG_LEVEL_INFO,
  1296. ("==>NdisMDeregisterDmaChannel\n"));
  1297. ASSERT(ndisPkgs[NPNP_PKG].ReferenceCount > 0);
  1298. PnPReferencePackage();
  1299. RAISE_IRQL_TO_DISPATCH(&OldIrql);
  1300. ((PDMA_ADAPTER)DmaBlock->SystemAdapterObject)->DmaOperations->FreeAdapterChannel(DmaBlock->SystemAdapterObject);
  1301. LOWER_IRQL(OldIrql, DISPATCH_LEVEL);
  1302. putDmaAdapter = ((PDMA_ADAPTER)DmaBlock->SystemAdapterObject)->DmaOperations->PutDmaAdapter;
  1303. putDmaAdapter((PDMA_ADAPTER)DmaBlock->SystemAdapterObject);
  1304. PnPDereferencePackage();
  1305. FREE_POOL(DmaBlock);
  1306. DBGPRINT_RAW(DBG_COMP_CONFIG, DBG_LEVEL_INFO,
  1307. ("<==NdisMDeregisterDmaChannel\n"));
  1308. }
  1309. NDIS_STATUS
  1310. NdisMAllocateMapRegisters(
  1311. IN NDIS_HANDLE MiniportAdapterHandle,
  1312. IN UINT DmaChannel,
  1313. IN NDIS_DMA_SIZE DmaSize,
  1314. IN ULONG BaseMapRegistersNeeded,
  1315. IN ULONG MaximumPhysicalMapping
  1316. )
  1317. /*++
  1318. Routine Description:
  1319. Allocates map registers for bus mastering devices.
  1320. Arguments:
  1321. MiniportAdapterHandle - Handle passed to MiniportInitialize.
  1322. BaseMapRegistersNeeded - The maximum number of base map registers needed
  1323. by the Miniport at any one time.
  1324. MaximumPhysicalMapping - Maximum length of a buffer that will have to be mapped.
  1325. Return Value:
  1326. None.
  1327. --*/
  1328. {
  1329. //
  1330. // Convert the handle to our internal structure.
  1331. //
  1332. PNDIS_MINIPORT_BLOCK Miniport = (PNDIS_MINIPORT_BLOCK) MiniportAdapterHandle;
  1333. //
  1334. // This is needed by HalGetAdapter.
  1335. //
  1336. DEVICE_DESCRIPTION DeviceDescription;
  1337. //
  1338. // Returned by HalGetAdapter.
  1339. //
  1340. ULONG MapRegistersAllowed;
  1341. //
  1342. // Returned by IoGetDmaAdapter.
  1343. //
  1344. PDMA_ADAPTER AdapterObject;
  1345. PALLOCATE_ADAPTER_CHANNEL allocateAdapterChannel;
  1346. PFREE_MAP_REGISTERS freeMapRegisters;
  1347. //
  1348. // Map registers needed per channel.
  1349. //
  1350. ULONG MapRegistersPerChannel;
  1351. NTSTATUS NtStatus;
  1352. KIRQL OldIrql;
  1353. USHORT i;
  1354. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  1355. BOOLEAN AllocationFailed;
  1356. KEVENT AllocationEvent;
  1357. DBGPRINT_RAW(DBG_COMP_CONFIG, DBG_LEVEL_INFO,
  1358. ("==>NdisMAllocateMapRegisters: Miniport %p, BaseMapRegistersNeeded %lx\n", Miniport, BaseMapRegistersNeeded));
  1359. ASSERT(ndisPkgs[NPNP_PKG].ReferenceCount > 0);
  1360. PnPReferencePackage();
  1361. // Miniport->InfoFlags |= NDIS_MINIPORT_USES_MAP_REGISTERS;
  1362. do
  1363. {
  1364. if (MINIPORT_VERIFY_TEST_FLAG(Miniport, fMINIPORT_VERIFY_FAIL_MAP_REG_ALLOC))
  1365. {
  1366. #if DBG
  1367. DbgPrint("NdisMAllocateMapRegisters failed to verify miniport %p\n", Miniport);
  1368. #endif
  1369. Status = NDIS_STATUS_RESOURCES;
  1370. break;
  1371. }
  1372. //
  1373. // If the device is a busmaster, we get an adapter
  1374. // object for it.
  1375. // If map registers are needed, we loop, allocating an
  1376. // adapter channel for each map register needed.
  1377. //
  1378. if (MINIPORT_TEST_FLAG(Miniport, fMINIPORT_BUS_MASTER))
  1379. {
  1380. Miniport->BaseMapRegistersNeeded = (USHORT)BaseMapRegistersNeeded;
  1381. Miniport->MaximumPhysicalMapping = MaximumPhysicalMapping;
  1382. //
  1383. // Allocate storage for holding the appropriate
  1384. // information for each map register.
  1385. //
  1386. Miniport->MapRegisters = NULL;
  1387. if (BaseMapRegistersNeeded > 0)
  1388. {
  1389. Miniport->MapRegisters = (PMAP_REGISTER_ENTRY)
  1390. ALLOC_FROM_POOL(sizeof(MAP_REGISTER_ENTRY) * BaseMapRegistersNeeded,
  1391. NDIS_TAG_MAP_REG);
  1392. if (Miniport->MapRegisters == (PMAP_REGISTER_ENTRY)NULL)
  1393. {
  1394. //
  1395. // Error out
  1396. //
  1397. NdisWriteErrorLogEntry((NDIS_HANDLE)Miniport,
  1398. NDIS_ERROR_CODE_OUT_OF_RESOURCES,
  1399. 1,
  1400. 0xFFFFFFFF);
  1401. Status = NDIS_STATUS_RESOURCES;
  1402. break;
  1403. }
  1404. }
  1405. //
  1406. // Use this event to tell us when ndisAllocationExecutionRoutine
  1407. // has been called.
  1408. //
  1409. Miniport->AllocationEvent = &AllocationEvent;
  1410. INITIALIZE_EVENT(&AllocationEvent);
  1411. //
  1412. // Set up the device description; zero it out in case its
  1413. // size changes.
  1414. //
  1415. ZeroMemory(&DeviceDescription, sizeof(DEVICE_DESCRIPTION));
  1416. DeviceDescription.Version = DEVICE_DESCRIPTION_VERSION;
  1417. DeviceDescription.Master = TRUE;
  1418. DeviceDescription.ScatterGather = TRUE;
  1419. DeviceDescription.BusNumber = Miniport->BusNumber;
  1420. DeviceDescription.DmaChannel = DmaChannel;
  1421. DeviceDescription.InterfaceType = Miniport->AdapterType;
  1422. if (DeviceDescription.InterfaceType == NdisInterfaceIsa)
  1423. {
  1424. //
  1425. // For ISA devices, the width is based on the DMA channel:
  1426. // 0-3 == 8 bits, 5-7 == 16 bits. Timing is compatibility
  1427. // mode.
  1428. //
  1429. if (DmaChannel > 4)
  1430. {
  1431. DeviceDescription.DmaWidth = Width16Bits;
  1432. }
  1433. else
  1434. {
  1435. DeviceDescription.DmaWidth = Width8Bits;
  1436. }
  1437. DeviceDescription.DmaSpeed = Compatible;
  1438. }
  1439. else if (DeviceDescription.InterfaceType == NdisInterfacePci)
  1440. {
  1441. if (DmaSize == NDIS_DMA_32BITS)
  1442. {
  1443. DeviceDescription.Dma32BitAddresses = TRUE;
  1444. }
  1445. else if (DmaSize == NDIS_DMA_64BITS)
  1446. {
  1447. DeviceDescription.Dma64BitAddresses = TRUE;
  1448. MINIPORT_SET_FLAG(Miniport, fMINIPORT_64BITS_DMA);
  1449. }
  1450. }
  1451. DeviceDescription.MaximumLength = MaximumPhysicalMapping;
  1452. //
  1453. // Determine how many map registers we need per channel.
  1454. //
  1455. MapRegistersPerChannel = ((MaximumPhysicalMapping - 2) / PAGE_SIZE) + 2;
  1456. #if DBG
  1457. if (MapRegistersPerChannel > 16)
  1458. {
  1459. DBGPRINT_RAW(DBG_COMP_CONFIG, DBG_LEVEL_WARN,
  1460. ("NdisMAllocateMapRegisters: Miniport %p, MaximumPhysicalMapping of 0x%lx\nwould require more than 16 MAP registers per channel, the call may fail\n",
  1461. Miniport, MaximumPhysicalMapping));
  1462. }
  1463. #endif
  1464. NDIS_WARN((Miniport->BaseMapRegistersNeeded * MapRegistersPerChannel > 0x40),
  1465. Miniport,
  1466. NDIS_GFLAG_WARN_LEVEL_0,
  1467. ("ndisMInitializeAdapter: Miniport %p is asking for too many %ld > 64 map registers.\n",
  1468. Miniport, Miniport->BaseMapRegistersNeeded * MapRegistersPerChannel
  1469. ));
  1470. //
  1471. // Get the adapter object.
  1472. //
  1473. AdapterObject =
  1474. IoGetDmaAdapter(Miniport->PhysicalDeviceObject, &DeviceDescription, &MapRegistersAllowed);
  1475. if ((AdapterObject == NULL) || (MapRegistersAllowed < MapRegistersPerChannel))
  1476. {
  1477. NdisWriteErrorLogEntry((NDIS_HANDLE)Miniport,
  1478. NDIS_ERROR_CODE_OUT_OF_RESOURCES,
  1479. 1,
  1480. 0xFFFFFFFF);
  1481. FREE_POOL(Miniport->MapRegisters);
  1482. Miniport->MapRegisters = NULL;
  1483. Status = NDIS_STATUS_RESOURCES;
  1484. if (AdapterObject != NULL)
  1485. {
  1486. RAISE_IRQL_TO_DISPATCH(&OldIrql);
  1487. ((PDMA_ADAPTER)AdapterObject)->DmaOperations->PutDmaAdapter((PDMA_ADAPTER)AdapterObject);
  1488. LOWER_IRQL(OldIrql, DISPATCH_LEVEL);
  1489. }
  1490. break;
  1491. }
  1492. //
  1493. // We save this to call IoFreeMapRegisters later.
  1494. //
  1495. Miniport->SystemAdapterObject = AdapterObject;
  1496. Miniport->SavedSystemAdapterObject = NULL;
  1497. ASSERT(Miniport->DmaAdapterRefCount == 0);
  1498. InterlockedIncrement(&Miniport->DmaAdapterRefCount);
  1499. allocateAdapterChannel = *AdapterObject->DmaOperations->AllocateAdapterChannel;
  1500. freeMapRegisters = *AdapterObject->DmaOperations->FreeMapRegisters;
  1501. //
  1502. // Now loop, allocating an adapter channel each time, then
  1503. // freeing everything but the map registers.
  1504. //
  1505. AllocationFailed = FALSE;
  1506. for (i=0; i<Miniport->BaseMapRegistersNeeded; i++)
  1507. {
  1508. Miniport->CurrentMapRegister = i;
  1509. RAISE_IRQL_TO_DISPATCH(&OldIrql);
  1510. NtStatus = allocateAdapterChannel(AdapterObject,
  1511. Miniport->DeviceObject,
  1512. MapRegistersPerChannel,
  1513. ndisAllocationExecutionRoutine,
  1514. Miniport);
  1515. if (!NT_SUCCESS(NtStatus))
  1516. {
  1517. DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR,
  1518. ("AllocateAdapterChannel: %lx\n", NtStatus));
  1519. for (; i != 0; i--)
  1520. {
  1521. freeMapRegisters(Miniport->SystemAdapterObject,
  1522. Miniport->MapRegisters[i-1].MapRegister,
  1523. MapRegistersPerChannel);
  1524. }
  1525. LOWER_IRQL(OldIrql, DISPATCH_LEVEL);
  1526. NdisWriteErrorLogEntry((NDIS_HANDLE)Miniport,
  1527. NDIS_ERROR_CODE_OUT_OF_RESOURCES,
  1528. 1,
  1529. 0xFFFFFFFF);
  1530. FREE_POOL(Miniport->MapRegisters);
  1531. Miniport->MapRegisters = NULL;
  1532. ndisDereferenceDmaAdapter(Miniport);
  1533. AllocationFailed = TRUE;
  1534. break;
  1535. }
  1536. LOWER_IRQL(OldIrql, DISPATCH_LEVEL);
  1537. //
  1538. // wait indefinitely for allocation routine to be called
  1539. //
  1540. NtStatus = WAIT_FOR_OBJECT(&AllocationEvent, 0);
  1541. if (!NT_SUCCESS(NtStatus))
  1542. {
  1543. DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR,
  1544. (" NDIS DMA AllocateAdapterChannel: %lx\n", NtStatus));
  1545. RAISE_IRQL_TO_DISPATCH(&OldIrql);
  1546. for (; i != 0; i--)
  1547. {
  1548. freeMapRegisters(Miniport->SystemAdapterObject,
  1549. Miniport->MapRegisters[i-1].MapRegister,
  1550. MapRegistersPerChannel);
  1551. }
  1552. LOWER_IRQL(OldIrql, DISPATCH_LEVEL);
  1553. NdisWriteErrorLogEntry((NDIS_HANDLE)Miniport,
  1554. NDIS_ERROR_CODE_OUT_OF_RESOURCES,
  1555. 1,
  1556. 0xFFFFFFFF);
  1557. FREE_POOL(Miniport->MapRegisters);
  1558. Miniport->MapRegisters = NULL;
  1559. ndisDereferenceDmaAdapter(Miniport);
  1560. AllocationFailed = TRUE;
  1561. break;
  1562. }
  1563. RESET_EVENT(&AllocationEvent);
  1564. }
  1565. if (AllocationFailed)
  1566. {
  1567. Status = NDIS_STATUS_RESOURCES;
  1568. break;
  1569. }
  1570. }
  1571. } while (FALSE);
  1572. PnPDereferencePackage();
  1573. DBGPRINT_RAW(DBG_COMP_CONFIG, DBG_LEVEL_INFO,
  1574. ("<==NdisMAllocateMapRegisters: Miniport %p, Status %lx\n", Miniport, Status));
  1575. return Status;
  1576. }
  1577. VOID
  1578. NdisMFreeMapRegisters(
  1579. IN NDIS_HANDLE MiniportAdapterHandle
  1580. )
  1581. /*++
  1582. Routine Description:
  1583. Releases allocated map registers
  1584. Arguments:
  1585. MiniportAdapterHandle - Handle passed to MiniportInitialize.
  1586. Return Value:
  1587. None.
  1588. --*/
  1589. {
  1590. //
  1591. // Convert the handle to our internal structure.
  1592. //
  1593. PNDIS_MINIPORT_BLOCK Miniport = (PNDIS_MINIPORT_BLOCK) MiniportAdapterHandle;
  1594. PFREE_MAP_REGISTERS freeMapRegisters;
  1595. KIRQL OldIrql;
  1596. ULONG i;
  1597. DBGPRINT_RAW(DBG_COMP_CONFIG, DBG_LEVEL_INFO,
  1598. ("==>NdisMFreeMapRegisters: Miniport %p\n", Miniport));
  1599. ASSERT(ndisPkgs[NPNP_PKG].ReferenceCount > 0);
  1600. PnPReferencePackage();
  1601. ASSERT(MINIPORT_TEST_FLAG(Miniport, fMINIPORT_BUS_MASTER));
  1602. ASSERT(Miniport->MapRegisters != NULL);
  1603. ASSERT(Miniport->SystemAdapterObject != NULL);
  1604. if (MINIPORT_TEST_FLAG(Miniport, fMINIPORT_BUS_MASTER) &&
  1605. (Miniport->MapRegisters != NULL))
  1606. {
  1607. ULONG MapRegistersPerChannel =
  1608. ((Miniport->MaximumPhysicalMapping - 2) / PAGE_SIZE) + 2;
  1609. freeMapRegisters = *Miniport->SystemAdapterObject->DmaOperations->FreeMapRegisters;
  1610. RAISE_IRQL_TO_DISPATCH(&OldIrql);
  1611. for (i = 0; i < Miniport->BaseMapRegistersNeeded; i++)
  1612. {
  1613. freeMapRegisters(Miniport->SystemAdapterObject,
  1614. Miniport->MapRegisters[i].MapRegister,
  1615. MapRegistersPerChannel);
  1616. }
  1617. LOWER_IRQL(OldIrql, DISPATCH_LEVEL);
  1618. //
  1619. // Map registers are allocated from non-paged pool.
  1620. // So this memory can be freed at DISPATCH
  1621. //
  1622. FREE_POOL(Miniport->MapRegisters);
  1623. Miniport->MapRegisters = NULL;
  1624. ndisDereferenceDmaAdapter(Miniport);
  1625. }
  1626. PnPDereferencePackage();
  1627. DBGPRINT_RAW(DBG_COMP_CONFIG, DBG_LEVEL_INFO,
  1628. ("<==NdisMFreeMapRegisters: Miniport %p\n", Miniport));
  1629. }
  1630. ULONG
  1631. NdisMReadDmaCounter(
  1632. IN NDIS_HANDLE MiniportDmaHandle
  1633. )
  1634. /*++
  1635. Routine Description:
  1636. Reads the current value of the dma counter
  1637. Arguments:
  1638. MiniportDmaHandle - Handle for the DMA transfer.
  1639. Return Value:
  1640. current value of a DMA counter
  1641. --*/
  1642. {
  1643. return ((PDMA_ADAPTER)((PNDIS_DMA_BLOCK)(MiniportDmaHandle))->SystemAdapterObject)->DmaOperations->ReadDmaCounter(((PNDIS_DMA_BLOCK)(MiniportDmaHandle))->SystemAdapterObject);
  1644. }
  1645. VOID
  1646. ndisBugcheckHandler(
  1647. IN PNDIS_WRAPPER_CONTEXT WrapperContext,
  1648. IN ULONG Size
  1649. )
  1650. /*++
  1651. Routine Description:
  1652. This routine is called when a bugcheck occurs in the system.
  1653. Arguments:
  1654. Buffer -- Ndis wrapper context.
  1655. Size -- Size of wrapper context
  1656. Return Value:
  1657. Void.
  1658. --*/
  1659. {
  1660. PNDIS_MINIPORT_BLOCK Miniport;
  1661. if (Size == sizeof(NDIS_WRAPPER_CONTEXT))
  1662. {
  1663. Miniport = (PNDIS_MINIPORT_BLOCK)(WrapperContext + 1);
  1664. MINIPORT_PNP_SET_FLAG(Miniport, fMINIPORT_SHUTTING_DOWN);
  1665. if (WrapperContext->ShutdownHandler != NULL)
  1666. {
  1667. WrapperContext->ShutdownHandler(WrapperContext->ShutdownContext);
  1668. }
  1669. }
  1670. }
  1671. VOID
  1672. NdisMRegisterAdapterShutdownHandler(
  1673. IN NDIS_HANDLE MiniportHandle,
  1674. IN PVOID ShutdownContext,
  1675. IN ADAPTER_SHUTDOWN_HANDLER ShutdownHandler
  1676. )
  1677. /*++
  1678. Routine Description:
  1679. Deregisters an NDIS adapter.
  1680. Arguments:
  1681. MiniportHandle - The miniport.
  1682. ShutdownHandler - The Handler for the Adapter, to be called on shutdown.
  1683. Return Value:
  1684. none.
  1685. --*/
  1686. {
  1687. PNDIS_MINIPORT_BLOCK Miniport = (PNDIS_MINIPORT_BLOCK) MiniportHandle;
  1688. PNDIS_WRAPPER_CONTEXT WrapperContext = Miniport->WrapperContext;
  1689. DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO,
  1690. ("==>NdisMRegisterAdapterShutdownHandler: Miniport %p\n", Miniport));
  1691. if (WrapperContext->ShutdownHandler == NULL)
  1692. {
  1693. //
  1694. // Store information
  1695. //
  1696. WrapperContext->ShutdownHandler = ShutdownHandler;
  1697. WrapperContext->ShutdownContext = ShutdownContext;
  1698. //
  1699. // Register our shutdown handler for a bugcheck. (Note that we are
  1700. // already registered for shutdown notification.)
  1701. //
  1702. KeInitializeCallbackRecord(&WrapperContext->BugcheckCallbackRecord);
  1703. KeRegisterBugCheckCallback(&WrapperContext->BugcheckCallbackRecord, // callback record.
  1704. ndisBugcheckHandler, // callback routine.
  1705. WrapperContext, // free form buffer.
  1706. sizeof(NDIS_WRAPPER_CONTEXT), // buffer size.
  1707. "Ndis miniport"); // component id.
  1708. }
  1709. DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO,
  1710. ("<==NdisMRegisterAdapterShutdownHandler: Miniport %p\n", Miniport));
  1711. }
  1712. VOID
  1713. NdisMDeregisterAdapterShutdownHandler(
  1714. IN NDIS_HANDLE MiniportHandle
  1715. )
  1716. /*++
  1717. Routine Description:
  1718. Arguments:
  1719. MiniportHandle - The miniport.
  1720. Return Value:
  1721. None.
  1722. --*/
  1723. {
  1724. PNDIS_MINIPORT_BLOCK Miniport = (PNDIS_MINIPORT_BLOCK) MiniportHandle;
  1725. PNDIS_WRAPPER_CONTEXT WrapperContext = Miniport->WrapperContext;
  1726. DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO,
  1727. ("==>NdisMDeregisterAdapterShutdownHandler: Miniport %p\n", Miniport));
  1728. //
  1729. // Clear information
  1730. //
  1731. if (WrapperContext->ShutdownHandler != NULL)
  1732. {
  1733. KeDeregisterBugCheckCallback(&WrapperContext->BugcheckCallbackRecord);
  1734. WrapperContext->ShutdownHandler = NULL;
  1735. }
  1736. DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO,
  1737. ("<==NdisMDeregisterAdapterShutdownHandler: Miniport %p\n", Miniport));
  1738. }
  1739. NDIS_STATUS
  1740. NdisMPciAssignResources(
  1741. IN NDIS_HANDLE MiniportHandle,
  1742. IN ULONG SlotNumber,
  1743. OUT PNDIS_RESOURCE_LIST * AssignedResources
  1744. )
  1745. /*++
  1746. Routine Description:
  1747. This routine uses the Hal to assign a set of resources to a PCI
  1748. device.
  1749. Arguments:
  1750. MiniportHandle - The miniport.
  1751. SlotNumber - Slot number of the device.
  1752. AssignedResources - The returned resources.
  1753. Return Value:
  1754. Status of the operation
  1755. --*/
  1756. {
  1757. PNDIS_MINIPORT_BLOCK Miniport = (PNDIS_MINIPORT_BLOCK) MiniportHandle;
  1758. DBGPRINT_RAW(DBG_COMP_CONFIG, DBG_LEVEL_INFO,
  1759. ("==>NdisMPciAssignResources: Miniport %p\n", Miniport));
  1760. NDIS_WARN(TRUE, Miniport, NDIS_GFLAG_WARN_LEVEL_3,
  1761. ("NdisMPciAssignResources: Miniport %p should use NdisMQueryAdapterResources to get resources.\n", Miniport));
  1762. if ((Miniport->BusType != NdisInterfacePci) || (Miniport->AllocatedResources == NULL))
  1763. {
  1764. *AssignedResources = NULL;
  1765. DBGPRINT(DBG_COMP_CONFIG, DBG_LEVEL_INFO,
  1766. ("<==NdisMPciAssignResources: Miniport %p\n", Miniport));
  1767. return NDIS_STATUS_FAILURE;
  1768. }
  1769. *AssignedResources = &Miniport->AllocatedResources->List[0].PartialResourceList;
  1770. DBGPRINT_RAW(DBG_COMP_CONFIG, DBG_LEVEL_INFO,
  1771. ("<==NdisMPciAssignResources: Miniport %p\n", Miniport));
  1772. return NDIS_STATUS_SUCCESS;
  1773. }
  1774. VOID
  1775. NdisMQueryAdapterResources(
  1776. OUT PNDIS_STATUS Status,
  1777. IN NDIS_HANDLE WrapperConfigurationContext,
  1778. OUT PNDIS_RESOURCE_LIST ResourceList,
  1779. IN IN PUINT BufferSize
  1780. )
  1781. {
  1782. PDEVICE_OBJECT DeviceObject;
  1783. PNDIS_MINIPORT_BLOCK Miniport;
  1784. ULONG MemNeeded;
  1785. DBGPRINT_RAW(DBG_COMP_CONFIG, DBG_LEVEL_INFO,
  1786. ("==>NdisMQueryAdapterResources: WrapperConfigurationContext %p\n", WrapperConfigurationContext));
  1787. DeviceObject = ((PNDIS_WRAPPER_CONFIGURATION_HANDLE)WrapperConfigurationContext)->DeviceObject;
  1788. Miniport = (PNDIS_MINIPORT_BLOCK)((PNDIS_WRAPPER_CONTEXT)DeviceObject->DeviceExtension + 1);
  1789. DBGPRINT_RAW(DBG_COMP_CONFIG, DBG_LEVEL_INFO,
  1790. ("NdisMQueryAdapterResources: Miniport %p\n", Miniport));
  1791. if (Miniport->AllocatedResources == NULL)
  1792. {
  1793. *Status = NDIS_STATUS_FAILURE;
  1794. }
  1795. else
  1796. {
  1797. MemNeeded = sizeof(CM_PARTIAL_RESOURCE_LIST) - sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR)
  1798. + Miniport->AllocatedResources->List[0].PartialResourceList.Count *
  1799. sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
  1800. if (*BufferSize < MemNeeded)
  1801. {
  1802. *BufferSize = MemNeeded;
  1803. *Status = NDIS_STATUS_RESOURCES;
  1804. }
  1805. else
  1806. {
  1807. NdisMoveMemory(
  1808. ResourceList,
  1809. &Miniport->AllocatedResources->List[0].PartialResourceList,
  1810. MemNeeded
  1811. );
  1812. *Status = NDIS_STATUS_SUCCESS;
  1813. }
  1814. }
  1815. DBGPRINT_RAW(DBG_COMP_CONFIG, DBG_LEVEL_INFO,
  1816. ("<==NdisMQueryAdapterResources: Miniport %p, Status %lx\n", Miniport, *Status));
  1817. return;
  1818. }
  1819. NTSTATUS
  1820. ndisPnPAddDevice(
  1821. IN PDRIVER_OBJECT DriverObject,
  1822. IN PDEVICE_OBJECT PhysicalDeviceObject
  1823. )
  1824. /*++
  1825. Routine Description:
  1826. The AddDevice entry point is called by the Plug & Play manager
  1827. to inform the driver when a new device instance arrives that this
  1828. driver must control.
  1829. Arguments:
  1830. Return Value:
  1831. --*/
  1832. {
  1833. NTSTATUS NtStatus, Status;
  1834. PWSTR ExportData = NULL;
  1835. UNICODE_STRING ExportName, BusStr;
  1836. HANDLE Handle = NULL;
  1837. PUINT BusTypeData = NULL, CharacteristicsData = NULL;
  1838. ULONG ValueType;
  1839. RTL_QUERY_REGISTRY_TABLE LQueryTable[3];
  1840. DBGPRINT_RAW(DBG_COMP_PNP, DBG_LEVEL_INFO,
  1841. ("==>ndisPnPAddDevice: DriverObject %p, PDO %p\n", DriverObject, PhysicalDeviceObject));
  1842. Status = STATUS_UNSUCCESSFUL;
  1843. do
  1844. {
  1845. #if NDIS_TEST_REG_FAILURE
  1846. NtStatus = STATUS_UNSUCCESSFUL;
  1847. #else
  1848. NtStatus = IoOpenDeviceRegistryKey(PhysicalDeviceObject,
  1849. PLUGPLAY_REGKEY_DRIVER,
  1850. GENERIC_READ | MAXIMUM_ALLOWED,
  1851. &Handle);
  1852. #endif
  1853. #if !NDIS_NO_REGISTRY
  1854. if (!NT_SUCCESS(NtStatus))
  1855. break;
  1856. //
  1857. // 1.
  1858. // Switch to the Linkage key below this driver instance key
  1859. //
  1860. LQueryTable[0].QueryRoutine = NULL;
  1861. LQueryTable[0].Flags = RTL_QUERY_REGISTRY_SUBKEY;
  1862. LQueryTable[0].Name = L"Linkage";
  1863. //
  1864. // 2.
  1865. // Read the export and rootdevice keywords
  1866. //
  1867. LQueryTable[1].QueryRoutine = ndisReadParameter;
  1868. LQueryTable[1].Flags = RTL_QUERY_REGISTRY_REQUIRED | RTL_QUERY_REGISTRY_NOEXPAND;
  1869. LQueryTable[1].Name = L"Export";
  1870. LQueryTable[1].EntryContext = (PVOID)&ExportData;
  1871. LQueryTable[1].DefaultType = REG_NONE;
  1872. LQueryTable[2].QueryRoutine = NULL;
  1873. LQueryTable[2].Flags = 0;
  1874. LQueryTable[2].Name = NULL;
  1875. NtStatus = RtlQueryRegistryValues(RTL_REGISTRY_HANDLE,
  1876. Handle,
  1877. LQueryTable,
  1878. NULL,
  1879. NULL);
  1880. if (!NT_SUCCESS(NtStatus) || (ExportData == NULL))
  1881. break;
  1882. RtlInitUnicodeString(&ExportName, ExportData);
  1883. //
  1884. // 3.
  1885. // Read the bus-type and characteristics keywords
  1886. //
  1887. LQueryTable[0].QueryRoutine = ndisReadParameter;
  1888. LQueryTable[0].Flags = RTL_QUERY_REGISTRY_NOEXPAND;
  1889. LQueryTable[0].Name = L"Characteristics";
  1890. LQueryTable[0].EntryContext = (PVOID)&CharacteristicsData;
  1891. LQueryTable[0].DefaultType = REG_NONE;
  1892. LQueryTable[1].QueryRoutine = NULL;
  1893. LQueryTable[1].Flags = 0;
  1894. LQueryTable[1].Name = NULL;
  1895. NtStatus = RtlQueryRegistryValues(RTL_REGISTRY_HANDLE,
  1896. Handle,
  1897. LQueryTable,
  1898. &ValueType,
  1899. NULL);
  1900. #else
  1901. if (NT_SUCCESS(NtStatus))
  1902. {
  1903. //
  1904. // 1.
  1905. // Switch to the Linkage key below this driver instance key
  1906. //
  1907. LQueryTable[0].QueryRoutine = NULL;
  1908. LQueryTable[0].Flags = RTL_QUERY_REGISTRY_SUBKEY;
  1909. LQueryTable[0].Name = L"Linkage";
  1910. //
  1911. // 2.
  1912. // Read the export and rootdevice keywords
  1913. //
  1914. LQueryTable[1].QueryRoutine = ndisReadParameter;
  1915. LQueryTable[1].Flags = RTL_QUERY_REGISTRY_REQUIRED | RTL_QUERY_REGISTRY_NOEXPAND;
  1916. LQueryTable[1].Name = L"Export";
  1917. LQueryTable[1].EntryContext = (PVOID)&ExportData;
  1918. LQueryTable[1].DefaultType = REG_NONE;
  1919. LQueryTable[2].QueryRoutine = NULL;
  1920. LQueryTable[2].Flags = 0;
  1921. LQueryTable[2].Name = NULL;
  1922. NtStatus = RtlQueryRegistryValues(RTL_REGISTRY_HANDLE,
  1923. Handle,
  1924. LQueryTable,
  1925. NULL,
  1926. NULL);
  1927. if (!NT_SUCCESS(NtStatus) || (ExportData == NULL))
  1928. break;
  1929. RtlInitUnicodeString(&ExportName, ExportData);
  1930. //
  1931. // 3.
  1932. // Read the bus-type and characteristics keywords
  1933. //
  1934. LQueryTable[0].QueryRoutine = ndisReadParameter;
  1935. LQueryTable[0].Flags = RTL_QUERY_REGISTRY_NOEXPAND;
  1936. LQueryTable[0].Name = L"Characteristics";
  1937. LQueryTable[0].EntryContext = (PVOID)&CharacteristicsData;
  1938. LQueryTable[0].DefaultType = REG_NONE;
  1939. LQueryTable[1].QueryRoutine = NULL;
  1940. LQueryTable[1].Flags = 0;
  1941. LQueryTable[1].Name = NULL;
  1942. NtStatus = RtlQueryRegistryValues(RTL_REGISTRY_HANDLE,
  1943. Handle,
  1944. LQueryTable,
  1945. &ValueType,
  1946. NULL);
  1947. }
  1948. else
  1949. {
  1950. ExportData = (PWSTR)ALLOC_FROM_POOL(sizeof(NDIS_DEFAULT_EXPORT_NAME),
  1951. NDIS_TAG_NAME_BUF);
  1952. if (ExportData == NULL)
  1953. {
  1954. Status = STATUS_INSUFFICIENT_RESOURCES;
  1955. break;
  1956. }
  1957. RtlCopyMemory(ExportData, ndisDefaultExportName, sizeof(NDIS_DEFAULT_EXPORT_NAME));
  1958. RtlInitUnicodeString(&ExportName, ExportData);
  1959. }
  1960. #endif
  1961. DBGPRINT_RAW(DBG_COMP_PNP, DBG_LEVEL_INFO,
  1962. ("ndisPnPAddDevice: Device: "));
  1963. DBGPRINT_UNICODE(DBG_COMP_PNP, DBG_LEVEL_INFO,
  1964. &ExportName);
  1965. DBGPRINT_RAW(DBG_COMP_PNP, DBG_LEVEL_INFO,
  1966. ("\n"));
  1967. Status = ndisAddDevice(DriverObject,
  1968. &ExportName,
  1969. PhysicalDeviceObject,
  1970. (CharacteristicsData != NULL) ? *CharacteristicsData : 0);
  1971. } while (FALSE);
  1972. if (Handle)
  1973. ZwClose(Handle);
  1974. if (ExportData != NULL)
  1975. FREE_POOL(ExportData);
  1976. if (CharacteristicsData != NULL)
  1977. FREE_POOL(CharacteristicsData);
  1978. DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO,
  1979. (" ndisPnPAddDevice returning %lx\n", Status));
  1980. DBGPRINT_RAW(DBG_COMP_PNP, DBG_LEVEL_INFO,
  1981. ("<==ndisPnPAddDevice: PDO %p\n", PhysicalDeviceObject));
  1982. return Status;
  1983. }
  1984. NDIS_STATUS
  1985. FASTCALL
  1986. ndisPnPStartDevice(
  1987. IN PDEVICE_OBJECT DeviceObject,
  1988. IN PIRP Irp OPTIONAL
  1989. )
  1990. /*+++
  1991. Routine Description:
  1992. The handler for IRP_MN_START_DEVICE.
  1993. Arguments:
  1994. DeviceObject - The adapter's device object.
  1995. Irp - The IRP.
  1996. Adapter - a pointer to either AdapterBlock or MiniportBlock
  1997. Return Value:
  1998. NDIS_STATUS_SUCCESS if intializing the device was successful
  1999. Note: This routine can also be called from NdisImInitializeDeviceInstanceEx in which case
  2000. the Irp woud be NULL
  2001. ---*/
  2002. {
  2003. PNDIS_MINIPORT_BLOCK Miniport;
  2004. PCM_RESOURCE_LIST AllocatedResources, AllocatedResourcesTranslated, pTempResources = NULL;
  2005. NDIS_STATUS Status;
  2006. PIO_STACK_LOCATION IrpSp;
  2007. NTSTATUS NtStatus;
  2008. ULONG MemNeeded = 0;
  2009. DBGPRINT_RAW(DBG_COMP_PNP, DBG_LEVEL_INFO,
  2010. ("==>ndisPnPStartDevice: DeviceObject\n", DeviceObject));
  2011. Miniport = (PNDIS_MINIPORT_BLOCK)((PNDIS_WRAPPER_CONTEXT)DeviceObject->DeviceExtension + 1);
  2012. DBGPRINT_RAW(DBG_COMP_PNP, DBG_LEVEL_INFO,
  2013. ("ndisPnPStartDevice: Miniport %p, ", Miniport));
  2014. DBGPRINT_UNICODE(DBG_COMP_PNP, DBG_LEVEL_INFO, Miniport->pAdapterInstanceName);
  2015. DBGPRINT_RAW(DBG_COMP_PNP, DBG_LEVEL_INFO, ("\n"));
  2016. DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO, ("\n"));
  2017. if (Miniport->PnPDeviceState == NdisPnPDeviceStopped)
  2018. {
  2019. //
  2020. // re-initialize the miniport block structure without destroying what
  2021. // we set during AddDevice
  2022. //
  2023. ndisReinitializeMiniportBlock(Miniport);
  2024. MINIPORT_PNP_SET_FLAG(Miniport, fMINIPORT_RECEIVED_START);
  2025. }
  2026. do
  2027. {
  2028. if (Irp != NULL)
  2029. {
  2030. IrpSp = IoGetCurrentIrpStackLocation (Irp);
  2031. //
  2032. // save allocated resources with miniport/adapter structure
  2033. //
  2034. AllocatedResources = IrpSp->Parameters.StartDevice.AllocatedResources;
  2035. AllocatedResourcesTranslated = IrpSp->Parameters.StartDevice.AllocatedResourcesTranslated;
  2036. if (AllocatedResources)
  2037. {
  2038. MINIPORT_PNP_SET_FLAG(Miniport, fMINIPORT_HARDWARE_DEVICE);
  2039. MemNeeded = sizeof(CM_RESOURCE_LIST) - sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) +
  2040. AllocatedResources->List[0].PartialResourceList.Count *
  2041. sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
  2042. pTempResources = (PCM_RESOURCE_LIST)ALLOC_FROM_POOL(2 * MemNeeded, NDIS_TAG_ALLOCATED_RESOURCES);
  2043. if (pTempResources == NULL)
  2044. {
  2045. Status = NDIS_STATUS_RESOURCES;
  2046. break;
  2047. }
  2048. NdisMoveMemory(pTempResources, AllocatedResources, MemNeeded);
  2049. NdisMoveMemory((PUCHAR)pTempResources + MemNeeded,
  2050. IrpSp->Parameters.StartDevice.AllocatedResourcesTranslated, MemNeeded);
  2051. #if DBG
  2052. if ((ndisDebugLevel == DBG_LEVEL_INFO) &&
  2053. (ndisDebugSystems & DBG_COMP_PNP))
  2054. {
  2055. UINT j;
  2056. PCM_PARTIAL_RESOURCE_LIST pResourceList;
  2057. DbgPrint("ndisPnPStartDevice: Miniport %p, Non-Translated allocated resources\n", Miniport);
  2058. pResourceList = &(AllocatedResources->List[0].PartialResourceList);
  2059. for (j = 0; j < pResourceList->Count; j++)
  2060. {
  2061. switch (pResourceList->PartialDescriptors[j].Type)
  2062. {
  2063. case CmResourceTypePort:
  2064. DbgPrint("IO Port: %p, Length: %lx\n",
  2065. pResourceList->PartialDescriptors[j].u.Port.Start.LowPart,
  2066. pResourceList->PartialDescriptors[j].u.Port.Length);
  2067. break;
  2068. case CmResourceTypeMemory:
  2069. DbgPrint("Memory: %p, Length: %lx\n",
  2070. pResourceList->PartialDescriptors[j].u.Memory.Start.LowPart,
  2071. pResourceList->PartialDescriptors[j].u.Memory.Length);
  2072. break;
  2073. case CmResourceTypeInterrupt:
  2074. DbgPrint("Interrupt Level: %lx, Vector: %lx\n",
  2075. pResourceList->PartialDescriptors[j].u.Interrupt.Level,
  2076. pResourceList->PartialDescriptors[j].u.Interrupt.Vector);
  2077. break;
  2078. case CmResourceTypeDma:
  2079. DbgPrint("DMA Channel: %lx\n", pResourceList->PartialDescriptors[j].u.Dma.Channel);
  2080. break;
  2081. }
  2082. }
  2083. DbgPrint("ndisPnPStartDevice: Miniport %p, Translated allocated resources\n", Miniport);
  2084. pResourceList = &(AllocatedResourcesTranslated->List[0].PartialResourceList);
  2085. for (j = 0; j < pResourceList->Count; j++)
  2086. {
  2087. switch (pResourceList->PartialDescriptors[j].Type)
  2088. {
  2089. case CmResourceTypePort:
  2090. DbgPrint("IO Port: %p, Length: %lx\n",
  2091. pResourceList->PartialDescriptors[j].u.Port.Start.LowPart,
  2092. pResourceList->PartialDescriptors[j].u.Port.Length);
  2093. break;
  2094. case CmResourceTypeMemory:
  2095. DbgPrint("Memory: %p, Length: %lx\n",
  2096. pResourceList->PartialDescriptors[j].u.Memory.Start.LowPart,
  2097. pResourceList->PartialDescriptors[j].u.Memory.Length);
  2098. break;
  2099. case CmResourceTypeInterrupt:
  2100. DbgPrint("Interrupt Level: %lx, Vector: %lx\n",
  2101. pResourceList->PartialDescriptors[j].u.Interrupt.Level,
  2102. pResourceList->PartialDescriptors[j].u.Interrupt.Vector);
  2103. break;
  2104. case CmResourceTypeDma:
  2105. DbgPrint("DMA Channel: %lx\n", pResourceList->PartialDescriptors[j].u.Dma.Channel);
  2106. break;
  2107. }
  2108. }
  2109. }
  2110. #endif
  2111. } // end of if AllocatedResources != NULL
  2112. }
  2113. Miniport->AllocatedResources = pTempResources;
  2114. Miniport->AllocatedResourcesTranslated = (PCM_RESOURCE_LIST)((PUCHAR)pTempResources + MemNeeded);
  2115. Status = ndisInitializeAdapter(Miniport->DriverHandle,
  2116. DeviceObject,
  2117. Miniport->pAdapterInstanceName,
  2118. Miniport->DeviceContext);
  2119. if (Status == NDIS_STATUS_SUCCESS)
  2120. {
  2121. Miniport->PnPDeviceState = NdisPnPDeviceStarted;
  2122. NdisSetEvent(&Miniport->OpenReadyEvent);
  2123. KeQueryTickCount(&Miniport->NdisStats.StartTicks);
  2124. }
  2125. } while (FALSE);
  2126. DBGPRINT_RAW(DBG_COMP_PNP, DBG_LEVEL_INFO,
  2127. ("<==ndisPnPStartDevice: Miniport %p\n", Miniport));
  2128. return Status;
  2129. }
  2130. NTSTATUS
  2131. ndisQueryReferenceBusInterface(
  2132. IN PDEVICE_OBJECT PnpDeviceObject,
  2133. OUT PBUS_INTERFACE_REFERENCE* pBusInterface
  2134. )
  2135. /*++
  2136. Routine Description:
  2137. Queries the bus for the standard information interface.
  2138. Arguments:
  2139. PnpDeviceObject -
  2140. Contains the next device object on the Pnp stack.
  2141. PhysicalDeviceObject -
  2142. Contains the physical device object which was passed to the FDO during
  2143. the Add Device.
  2144. BusInterface -
  2145. The place in which to return the pointer to the Reference interface.
  2146. Return Value:
  2147. Returns STATUS_SUCCESS if the interface was retrieved, else an error.
  2148. --*/
  2149. {
  2150. NTSTATUS Status;
  2151. KEVENT Event;
  2152. IO_STATUS_BLOCK IoStatusBlock;
  2153. PIRP Irp;
  2154. PIO_STACK_LOCATION IrpStackNext;
  2155. PAGED_CODE();
  2156. *pBusInterface = (PBUS_INTERFACE_REFERENCE)ALLOC_FROM_POOL(sizeof(BUS_INTERFACE_REFERENCE), NDIS_TAG_BUS_INTERFACE);
  2157. if (*pBusInterface == NULL)
  2158. {
  2159. return STATUS_INSUFFICIENT_RESOURCES;
  2160. }
  2161. //
  2162. // There is no file object associated with this Irp, so the event may be located
  2163. // on the stack as a non-object manager object.
  2164. //
  2165. INITIALIZE_EVENT(&Event);
  2166. Irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP,
  2167. PnpDeviceObject,
  2168. NULL,
  2169. 0,
  2170. NULL,
  2171. &Event,
  2172. &IoStatusBlock);
  2173. if (Irp != NULL)
  2174. {
  2175. Irp->RequestorMode = KernelMode;
  2176. Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
  2177. IrpStackNext = IoGetNextIrpStackLocation(Irp);
  2178. //
  2179. // Create an interface query out of the Irp.
  2180. //
  2181. IrpStackNext->MinorFunction = IRP_MN_QUERY_INTERFACE;
  2182. IrpStackNext->Parameters.QueryInterface.InterfaceType = (GUID*)&REFERENCE_BUS_INTERFACE;
  2183. IrpStackNext->Parameters.QueryInterface.Size = sizeof(**pBusInterface);
  2184. IrpStackNext->Parameters.QueryInterface.Version = BUS_INTERFACE_REFERENCE_VERSION;
  2185. IrpStackNext->Parameters.QueryInterface.Interface = (PINTERFACE)*pBusInterface;
  2186. IrpStackNext->Parameters.QueryInterface.InterfaceSpecificData = NULL;
  2187. Status = IoCallDriver(PnpDeviceObject, Irp);
  2188. if (Status == STATUS_PENDING)
  2189. {
  2190. //
  2191. // This waits using KernelMode, so that the stack, and therefore the
  2192. // event on that stack, is not paged out.
  2193. //
  2194. WAIT_FOR_OBJECT(&Event, NULL);
  2195. Status = IoStatusBlock.Status;
  2196. }
  2197. }
  2198. else
  2199. {
  2200. Status = STATUS_INSUFFICIENT_RESOURCES;
  2201. }
  2202. if (!NT_SUCCESS(Status))
  2203. {
  2204. FREE_POOL(*pBusInterface);
  2205. *pBusInterface = NULL;
  2206. }
  2207. return Status;
  2208. }
  2209. NTSTATUS
  2210. ndisAddDevice(
  2211. IN PDRIVER_OBJECT DriverObject,
  2212. IN PUNICODE_STRING pExportName,
  2213. IN PDEVICE_OBJECT PhysicalDeviceObject,
  2214. IN ULONG Characteristics
  2215. )
  2216. /*++
  2217. Routine Description:
  2218. The AddDevice entry point is called by the Plug & Play manager
  2219. to inform the driver when a new device instance arrives that this
  2220. driver must control.
  2221. Arguments:
  2222. Return Value:
  2223. --*/
  2224. {
  2225. PDEVICE_OBJECT NextDeviceObject = NULL;
  2226. NTSTATUS NtStatus, Status = STATUS_UNSUCCESSFUL;
  2227. PDEVICE_OBJECT DevicePtr = NULL;
  2228. PNDIS_MINIPORT_BLOCK Miniport;
  2229. UNICODE_STRING us;
  2230. PWCHAR pPath;
  2231. PNDIS_M_DRIVER_BLOCK MiniBlock, TmpMiniBlock;
  2232. UINT NumComponents;
  2233. LONG Size;
  2234. BOOLEAN FreeDevice = FALSE;
  2235. PCM_RESOURCE_LIST pResourceList;
  2236. KIRQL OldIrql;
  2237. DBGPRINT_RAW(DBG_COMP_PNP, DBG_LEVEL_INFO,
  2238. ("==>ndisAddDevice: PDO %p\n", PhysicalDeviceObject));
  2239. PnPReferencePackage();
  2240. do
  2241. {
  2242. MiniBlock = (PNDIS_M_DRIVER_BLOCK)IoGetDriverObjectExtension(DriverObject,
  2243. (PVOID)NDIS_PNP_MINIPORT_DRIVER_ID);
  2244. {
  2245. //
  2246. // check to make sure the mini block is on our queue
  2247. //
  2248. ACQUIRE_SPIN_LOCK(&ndisMiniDriverListLock, &OldIrql);
  2249. TmpMiniBlock = ndisMiniDriverList;
  2250. while (TmpMiniBlock)
  2251. {
  2252. if (TmpMiniBlock == MiniBlock)
  2253. break;
  2254. TmpMiniBlock = TmpMiniBlock->NextDriver;
  2255. }
  2256. RELEASE_SPIN_LOCK(&ndisMiniDriverListLock, OldIrql);
  2257. ASSERT(TmpMiniBlock == MiniBlock);
  2258. if (TmpMiniBlock != MiniBlock)
  2259. {
  2260. #if TRACK_UNLOAD
  2261. DbgPrint("ndisAddDevice: AddDevice called with a MiniBlock that is not on ndisMiniDriverList\n");
  2262. KeBugCheckEx(BUGCODE_ID_DRIVER,
  2263. (ULONG_PTR)MiniBlock,
  2264. (ULONG_PTR)DriverObject,
  2265. 0,
  2266. 0);
  2267. #endif
  2268. break;
  2269. }
  2270. }
  2271. //
  2272. // create DeviceObject and Miniport/Adapter structure now,
  2273. // we will set a few field here and the rest will be set during
  2274. // processing IRP_MN_START_DEVICE and InitializeAdapter call.
  2275. //
  2276. // Note: We need the device-name field double null terminated.
  2277. //
  2278. Size = sizeof(NDIS_MINIPORT_BLOCK) +
  2279. sizeof(NDIS_WRAPPER_CONTEXT) +
  2280. pExportName->Length + sizeof(WCHAR) + sizeof(WCHAR);
  2281. NtStatus = IoCreateDevice(DriverObject,
  2282. Size,
  2283. pExportName,
  2284. FILE_DEVICE_PHYSICAL_NETCARD,
  2285. FILE_DEVICE_SECURE_OPEN,
  2286. FALSE, // exclusive flag
  2287. &DevicePtr);
  2288. if(!NT_SUCCESS(NtStatus))
  2289. break;
  2290. DevicePtr->Flags &= ~DO_DEVICE_INITIALIZING;
  2291. DevicePtr->Flags |= DO_DIRECT_IO;
  2292. PhysicalDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
  2293. FreeDevice = TRUE;
  2294. //
  2295. // Mark the device as being pageable.
  2296. //
  2297. DevicePtr->Flags |= DO_POWER_PAGABLE;
  2298. //
  2299. // Attach our FDO to the PDO. This routine will return the top most
  2300. // device that is attached to the PDO or the PDO itself if no other
  2301. // device objects have attached to it.
  2302. //
  2303. NextDeviceObject = IoAttachDeviceToDeviceStack(DevicePtr, PhysicalDeviceObject);
  2304. ZeroMemory(DevicePtr->DeviceExtension, Size);
  2305. Miniport = (PNDIS_MINIPORT_BLOCK)((PNDIS_WRAPPER_CONTEXT)DevicePtr->DeviceExtension + 1);
  2306. Miniport->Signature = (PVOID)MINIPORT_DEVICE_MAGIC_VALUE;
  2307. Miniport->DriverHandle = MiniBlock;
  2308. //
  2309. // initialize OpenReady event in case we get an open request before start IRP
  2310. //
  2311. NdisInitializeEvent(&Miniport->OpenReadyEvent);
  2312. INITIALIZE_SPIN_LOCK(&Miniport->Lock);
  2313. #if CHECK_TIMER
  2314. if (Miniport->DriverHandle->Flags & fMINIBLOCK_VERIFYING)
  2315. INITIALIZE_SPIN_LOCK(&Miniport->TimerQueueLock);
  2316. #endif
  2317. Miniport->PrimaryMiniport = Miniport;
  2318. Miniport->PnPDeviceState = NdisPnPDeviceAdded;
  2319. Miniport->PhysicalDeviceObject = PhysicalDeviceObject;
  2320. Miniport->DeviceObject = DevicePtr;
  2321. Miniport->NextDeviceObject = NextDeviceObject;
  2322. Miniport->WrapperContext = DevicePtr->DeviceExtension;
  2323. InitializeListHead(&Miniport->PacketList);
  2324. //
  2325. // intialize the reference and set it to 0; we will increment it
  2326. // in ndisMinitializeAdapter
  2327. //
  2328. ndisInitializeULongRef(&Miniport->Ref);
  2329. Miniport->Ref.ReferenceCount = 0;
  2330. #ifdef TRACK_MINIPORT_REFCOUNTS
  2331. M_LOG_MINIPORT_SET_REF(Miniport, 0);
  2332. #endif
  2333. //
  2334. // Read the characteristics. This determines if the device is hidden or not (from device-manager)
  2335. //
  2336. if (Characteristics & 0x08)
  2337. {
  2338. //
  2339. // Bit 0x08 is NCF_HIDDEN
  2340. //
  2341. MINIPORT_PNP_SET_FLAG(Miniport, fMINIPORT_HIDDEN);
  2342. }
  2343. if (Characteristics & 0x02)
  2344. {
  2345. //
  2346. // Bit 0x02 is NCF_SOFTWARE_ENUMERATED
  2347. //
  2348. MINIPORT_PNP_SET_FLAG(Miniport, fMINIPORT_SWENUM);
  2349. }
  2350. //
  2351. // MiniportName must follow the MINIPORT_BLOCK.
  2352. //
  2353. ndisSetDeviceNames(pExportName,
  2354. &Miniport->MiniportName,
  2355. &Miniport->BaseName,
  2356. (PUCHAR)Miniport + sizeof(NDIS_MINIPORT_BLOCK));
  2357. NtStatus = ndisCreateAdapterInstanceName(&Miniport->pAdapterInstanceName,
  2358. PhysicalDeviceObject);
  2359. if (!NT_SUCCESS(NtStatus))
  2360. {
  2361. break;
  2362. }
  2363. Miniport->InstanceNumber = (USHORT)InterlockedIncrement(&ndisInstanceNumber);
  2364. DBGPRINT_RAW(DBG_COMP_PNP, DBG_LEVEL_INFO,
  2365. ("ndisAddDevice: Miniport %p, ", Miniport));
  2366. DBGPRINT_UNICODE(DBG_COMP_PNP, DBG_LEVEL_INFO,
  2367. Miniport->pAdapterInstanceName);
  2368. DBGPRINT_RAW(DBG_COMP_PNP, DBG_LEVEL_INFO, ("\n"));
  2369. if (Characteristics & 0x02)
  2370. {
  2371. PBUS_INTERFACE_REFERENCE BusInterface = NULL;
  2372. Status = ndisQueryReferenceBusInterface(PhysicalDeviceObject, &BusInterface);
  2373. if (NT_SUCCESS(Status))
  2374. {
  2375. Miniport->BusInterface = BusInterface;
  2376. }
  2377. else
  2378. {
  2379. ASSERT(BusInterface == NULL);
  2380. break;
  2381. }
  2382. }
  2383. //
  2384. // create a security descriptor for the device
  2385. //
  2386. Status = ndisCreateSecurityDescriptor(Miniport->DeviceObject,
  2387. &Miniport->SecurityDescriptor,
  2388. TRUE);
  2389. if (!NT_SUCCESS(Status))
  2390. {
  2391. FREE_POOL(Miniport->pAdapterInstanceName);
  2392. Status = STATUS_UNSUCCESSFUL;
  2393. break;
  2394. }
  2395. Status = STATUS_SUCCESS;
  2396. //
  2397. // Don't want to free up the device object.
  2398. //
  2399. FreeDevice = FALSE;
  2400. } while (FALSE);
  2401. if (FreeDevice)
  2402. {
  2403. //
  2404. // if device is created it is also attached
  2405. //
  2406. if (NextDeviceObject)
  2407. IoDetachDevice(NextDeviceObject);
  2408. IoDeleteDevice(DevicePtr);
  2409. DevicePtr = NULL;
  2410. }
  2411. if (DevicePtr && (NT_SUCCESS(Status)))
  2412. {
  2413. //
  2414. // if DevicePtr is not NULL, we do have a valid
  2415. // miniport. queue the miniport on global miniport queue
  2416. //
  2417. ACQUIRE_SPIN_LOCK(&ndisMiniportListLock, &OldIrql);
  2418. Miniport->NextGlobalMiniport = ndisMiniportList;
  2419. ndisMiniportList = Miniport;
  2420. RELEASE_SPIN_LOCK(&ndisMiniportListLock, OldIrql);
  2421. }
  2422. PnPDereferencePackage();
  2423. DBGPRINT_RAW(DBG_COMP_PNP, DBG_LEVEL_INFO,
  2424. ("<==ndisAddDevice: Miniport %p\n", Miniport));
  2425. return Status;
  2426. }
  2427. VOID
  2428. ndisSetDeviceNames(
  2429. IN PNDIS_STRING ExportName,
  2430. OUT PNDIS_STRING DeviceName,
  2431. OUT PNDIS_STRING BaseName,
  2432. IN PUCHAR Buffer
  2433. )
  2434. {
  2435. PNDIS_STRING BindPath;
  2436. PWSTR pComp, p;
  2437. USHORT i;
  2438. NDIS_STRING Str, SubStr;
  2439. DeviceName->Buffer = (PWSTR)Buffer;
  2440. DeviceName->Length = ExportName->Length;
  2441. DeviceName->MaximumLength = DeviceName->Length + sizeof(WCHAR);
  2442. RtlUpcaseUnicodeString(DeviceName,
  2443. ExportName,
  2444. FALSE);
  2445. //
  2446. // ExportName is in the form of \Device\<AdapterName>
  2447. // Extract BaseName which is the name w/o the "\Device\"
  2448. //
  2449. BaseName->Buffer = DeviceName->Buffer + (ndisDeviceStr.Length/sizeof(WCHAR));
  2450. BaseName->Length = DeviceName->Length - ndisDeviceStr.Length;
  2451. BaseName->MaximumLength = BaseName->Length + sizeof(WCHAR);
  2452. }
  2453. NTSTATUS
  2454. FASTCALL
  2455. ndisPnPQueryStopDevice(
  2456. IN PDEVICE_OBJECT DeviceObject,
  2457. IN PIRP Irp
  2458. )
  2459. {
  2460. NTSTATUS Status;
  2461. PNDIS_MINIPORT_BLOCK Miniport = (PNDIS_MINIPORT_BLOCK)((PNDIS_WRAPPER_CONTEXT)DeviceObject->DeviceExtension + 1);
  2462. KIRQL OldIrql;
  2463. DBGPRINT_RAW(DBG_COMP_PNP, DBG_LEVEL_INFO,
  2464. ("==>ndisPnPQueryStopDevice: Miniport %p\n", Miniport));
  2465. do
  2466. {
  2467. if (Miniport->PnPCapabilities & NDIS_DEVICE_NOT_STOPPABLE)
  2468. {
  2469. Status = STATUS_UNSUCCESSFUL;
  2470. break;
  2471. }
  2472. //
  2473. // query_stop and stop are not reported to the user mode
  2474. // so we have to protect ourselves against cases that apps
  2475. // may have pending IO against the miniport
  2476. //
  2477. NDIS_ACQUIRE_MINIPORT_SPIN_LOCK(Miniport, &OldIrql);
  2478. if (Miniport->UserModeOpenReferences != 0)
  2479. {
  2480. Status = STATUS_UNSUCCESSFUL;
  2481. NDIS_RELEASE_MINIPORT_SPIN_LOCK(Miniport, OldIrql);
  2482. break;
  2483. }
  2484. NDIS_RELEASE_MINIPORT_SPIN_LOCK(Miniport, OldIrql);
  2485. //
  2486. // for now do the same as query remove
  2487. //
  2488. Status = ndisPnPQueryRemoveDevice(DeviceObject, Irp);
  2489. } while (FALSE);
  2490. DBGPRINT_RAW(DBG_COMP_PNP, DBG_LEVEL_INFO,
  2491. ("<==ndisPnPQueryStopDevice: Miniport %p\n", Miniport));
  2492. return Status;
  2493. }
  2494. NTSTATUS
  2495. FASTCALL
  2496. ndisPnPCancelStopDevice(
  2497. IN PDEVICE_OBJECT DeviceObject,
  2498. IN PIRP Irp
  2499. )
  2500. {
  2501. NTSTATUS Status;
  2502. DBGPRINT_RAW(DBG_COMP_PNP, DBG_LEVEL_INFO,
  2503. ("==>ndisPnPCancelStopDevice\n"));
  2504. //
  2505. // for now do the same as cancel remove
  2506. //
  2507. Status = ndisPnPCancelRemoveDevice(DeviceObject, Irp);
  2508. DBGPRINT_RAW(DBG_COMP_PNP, DBG_LEVEL_INFO,
  2509. ("<==ndisPnPCancelStopDevice\n"));
  2510. return Status;
  2511. }
  2512. NTSTATUS
  2513. FASTCALL
  2514. ndisPnPStopDevice(
  2515. IN PDEVICE_OBJECT DeviceObject,
  2516. IN PIRP Irp
  2517. )
  2518. {
  2519. NTSTATUS Status;
  2520. DBGPRINT_RAW(DBG_COMP_PNP, DBG_LEVEL_INFO,
  2521. ("==>ndisPnPStopDevice\n"));
  2522. //
  2523. // do the same as remove
  2524. //
  2525. Status = ndisPnPRemoveDevice(DeviceObject, Irp);
  2526. DBGPRINT_RAW(DBG_COMP_PNP, DBG_LEVEL_INFO,
  2527. ("<==ndisPnPStopDevice\n"));
  2528. return Status;
  2529. }
  2530. NTSTATUS
  2531. FASTCALL
  2532. ndisPnPQueryRemoveDevice(
  2533. IN PDEVICE_OBJECT DeviceObject,
  2534. IN PIRP Irp
  2535. )
  2536. {
  2537. PNDIS_MINIPORT_BLOCK Miniport = (PNDIS_MINIPORT_BLOCK)((PNDIS_WRAPPER_CONTEXT)DeviceObject->DeviceExtension + 1);
  2538. NTSTATUS Status = STATUS_SUCCESS;
  2539. DBGPRINT_RAW(DBG_COMP_PNP, DBG_LEVEL_INFO,
  2540. ("==>ndisPnPQueryRemoveDevice: Miniport %p, UserModeOpenReferences %lx\n", Miniport, Miniport->UserModeOpenReferences));
  2541. do
  2542. {
  2543. //
  2544. // If this was the network card used in a remote boot, then we
  2545. // can't remove it.
  2546. //
  2547. if (MINIPORT_TEST_FLAG(Miniport, fMINIPORT_NETBOOT_CARD))
  2548. {
  2549. Status = STATUS_UNSUCCESSFUL;
  2550. break;
  2551. }
  2552. Status = ndisPnPNotifyAllTransports(Miniport,
  2553. NetEventQueryRemoveDevice,
  2554. NULL,
  2555. 0);
  2556. } while (FALSE);
  2557. DBGPRINT_RAW(DBG_COMP_PNP, DBG_LEVEL_INFO,
  2558. ("<==ndisPnPQueryRemoveDevice: Miniport %p, Status 0x%x\n", Miniport, Status));
  2559. return Status;
  2560. }
  2561. NTSTATUS
  2562. FASTCALL
  2563. ndisPnPCancelRemoveDevice(
  2564. IN PDEVICE_OBJECT DeviceObject,
  2565. IN PIRP Irp
  2566. )
  2567. {
  2568. PNDIS_MINIPORT_BLOCK Miniport = (PNDIS_MINIPORT_BLOCK)((PNDIS_WRAPPER_CONTEXT)DeviceObject->DeviceExtension + 1);
  2569. NTSTATUS Status = NDIS_STATUS_SUCCESS;
  2570. DBGPRINT_RAW(DBG_COMP_PNP, DBG_LEVEL_INFO,
  2571. ("==>ndisPnPCancelRemoveDevice: Miniport %p\n", Miniport));
  2572. Status = ndisPnPNotifyAllTransports(Miniport,
  2573. NetEventCancelRemoveDevice,
  2574. NULL,
  2575. 0);
  2576. DBGPRINT_RAW(DBG_COMP_PNP, DBG_LEVEL_INFO,
  2577. ("<==ndisPnPCancelRemoveDevice: Miniport %p\n", Miniport));
  2578. return STATUS_SUCCESS;
  2579. }
  2580. NTSTATUS
  2581. FASTCALL
  2582. ndisPnPRemoveDevice(
  2583. IN PDEVICE_OBJECT DeviceObject,
  2584. IN PIRP Irp OPTIONAL
  2585. )
  2586. {
  2587. PNDIS_MINIPORT_BLOCK Miniport = (PNDIS_MINIPORT_BLOCK)((PNDIS_WRAPPER_CONTEXT)DeviceObject->DeviceExtension + 1);
  2588. NTSTATUS Status = NDIS_STATUS_SUCCESS;
  2589. PNDIS_OPEN_BLOCK Open, NextOpen;
  2590. NDIS_BIND_CONTEXT UnbindContext;
  2591. KIRQL OldIrql;
  2592. BOOLEAN fAcquiredImMutex = FALSE;
  2593. PKMUTEX pIMStartRemoveMutex = NULL;
  2594. DBGPRINT_RAW(DBG_COMP_PNP, DBG_LEVEL_INFO,
  2595. ("==>ndisPnPRemoveDevice: Miniport %p\n", Miniport));
  2596. PnPReferencePackage();
  2597. //
  2598. // there are three different cases that we can get a remove request
  2599. // a: the request is coming from PnP manager in response to a user mode
  2600. // app. In this case, the remove has been proceeded by a query remove
  2601. // which we happily failed if there was any legacy protocol bound to
  2602. // the adapter
  2603. //
  2604. // b. the request is coming from PnP manager because Starting the device failed
  2605. // in this case (hopefully) there is no binding at all. in this case it is not
  2606. // proceeded by query_remove and neet not be. we don't have any protocol bound
  2607. // to the adapter to worry about
  2608. //
  2609. // c. or it can come in response to a surprise style removal in which case we are
  2610. // hosed anyway. sending query_remove to protocols does not do any good
  2611. //
  2612. do
  2613. {
  2614. PNDIS_M_DRIVER_BLOCK MiniBlock;
  2615. PNDIS_MINIPORT_BLOCK TmpMiniport;
  2616. //
  2617. // find the miniport on driver queue
  2618. //
  2619. MiniBlock = Miniport->DriverHandle;
  2620. if (MiniBlock == NULL)
  2621. break;
  2622. //
  2623. // Intermediate drivers could be in the middle of initialization through the
  2624. // NdisIMInitializeDeviceInstance Code path. We need to synchronize
  2625. //
  2626. if (MiniBlock->Flags & fMINIBLOCK_INTERMEDIATE_DRIVER)
  2627. {
  2628. pIMStartRemoveMutex = &MiniBlock->IMStartRemoveMutex;
  2629. WAIT_FOR_OBJECT(pIMStartRemoveMutex, NULL);
  2630. fAcquiredImMutex = TRUE;
  2631. }
  2632. ACQUIRE_SPIN_LOCK(&MiniBlock->Ref.SpinLock, &OldIrql);
  2633. for (TmpMiniport = MiniBlock->MiniportQueue;
  2634. TmpMiniport != NULL;
  2635. TmpMiniport = TmpMiniport->NextMiniport)
  2636. {
  2637. if (TmpMiniport == Miniport)
  2638. {
  2639. break;
  2640. }
  2641. }
  2642. RELEASE_SPIN_LOCK(&MiniBlock->Ref.SpinLock, OldIrql);
  2643. if ((TmpMiniport != Miniport) || (Miniport->Ref.Closing == TRUE))
  2644. {
  2645. break;
  2646. }
  2647. ndisReferenceDriver(MiniBlock);
  2648. NdisResetEvent(&Miniport->OpenReadyEvent);
  2649. //
  2650. // Notify WMI of adapter removal.
  2651. //
  2652. if (Miniport->pAdapterInstanceName != NULL)
  2653. {
  2654. PWNODE_SINGLE_INSTANCE wnode;
  2655. PUCHAR ptmp;
  2656. NTSTATUS NtStatus;
  2657. ndisSetupWmiNode(Miniport,
  2658. Miniport->pAdapterInstanceName,
  2659. Miniport->MiniportName.Length + sizeof(USHORT),
  2660. (PVOID)&GUID_NDIS_NOTIFY_ADAPTER_REMOVAL,
  2661. &wnode);
  2662. if (wnode != NULL)
  2663. {
  2664. //
  2665. // Save the number of elements in the first ULONG.
  2666. //
  2667. ptmp = (PUCHAR)wnode + wnode->DataBlockOffset;
  2668. *((PUSHORT)ptmp) = Miniport->MiniportName.Length;
  2669. //
  2670. // Copy the data after the number of elements.
  2671. //
  2672. RtlCopyMemory(ptmp + sizeof(USHORT),
  2673. Miniport->MiniportName.Buffer,
  2674. Miniport->MiniportName.Length);
  2675. //
  2676. // Indicate the event to WMI. WMI will take care of freeing
  2677. // the WMI struct back to pool.
  2678. //
  2679. NtStatus = IoWMIWriteEvent(wnode);
  2680. if (!NT_SUCCESS(NtStatus))
  2681. {
  2682. DBGPRINT(DBG_COMP_WMI, DBG_LEVEL_ERR,
  2683. ("ndisPnPRemoveDevice: Failed to indicate adapter removal\n"));
  2684. FREE_POOL(wnode);
  2685. }
  2686. }
  2687. }
  2688. //
  2689. // this will take care of closing all the bindings
  2690. //
  2691. ndisCloseMiniportBindings(Miniport);
  2692. if (Miniport->pIrpWaitWake)
  2693. {
  2694. if (IoCancelIrp(Miniport->pIrpWaitWake))
  2695. {
  2696. DBGPRINT_RAW(DBG_COMP_PM, DBG_LEVEL_INFO,
  2697. ("ndisPnPRemoveDevice: Miniport %p, Successfully canceled wake irp\n", Miniport));
  2698. }
  2699. }
  2700. //
  2701. // get rid of wakeup patterns set on the miniport
  2702. //
  2703. {
  2704. PSINGLE_LIST_ENTRY Link;
  2705. PNDIS_PACKET_PATTERN_ENTRY pPatternEntry;
  2706. while (Miniport->PatternList.Next != NULL)
  2707. {
  2708. Link = PopEntryList(&Miniport->PatternList);
  2709. pPatternEntry = CONTAINING_RECORD(Link, NDIS_PACKET_PATTERN_ENTRY, Link);
  2710. //
  2711. // Free the memory taken by the pattern.
  2712. //
  2713. FREE_POOL(pPatternEntry);
  2714. }
  2715. }
  2716. //
  2717. // and this one will take care of the rest!
  2718. // we call this function even if the device has already been halted by
  2719. // ndisPMHaltMiniport. because that functions does not clean up everything.
  2720. // ndisMHaltMiniport will check for PM_HALTED flag and avoid re-doing what PMHalt
  2721. // has already done.
  2722. //
  2723. ndisMHaltMiniport(Miniport);
  2724. //
  2725. // Free the media-request structure, if present
  2726. //
  2727. if (Miniport->MediaRequest != NULL)
  2728. {
  2729. FREE_POOL(Miniport->MediaRequest);
  2730. Miniport->MediaRequest = NULL;
  2731. }
  2732. ndisDereferenceDriver(MiniBlock, FALSE);
  2733. {
  2734. UNICODE_STRING DeviceName, UpcaseDeviceName;
  2735. UNICODE_STRING SymbolicLink;
  2736. NTSTATUS NtStatus;
  2737. WCHAR SymLnkBuf[128];
  2738. SymbolicLink.Buffer = SymLnkBuf;
  2739. SymbolicLink.Length = 0;
  2740. SymbolicLink.MaximumLength = sizeof(SymLnkBuf);
  2741. RtlCopyUnicodeString(&SymbolicLink, &ndisDosDevicesStr);
  2742. RtlAppendUnicodeStringToString(&SymbolicLink,
  2743. &Miniport->BaseName);
  2744. NtStatus = IoDeleteSymbolicLink(&SymbolicLink);
  2745. if (!NT_SUCCESS(NtStatus))
  2746. {
  2747. #if DBG
  2748. DbgPrint("ndisPnPRemoveDevice: deleting symbolic link name failed for miniport %p, SymbolicLinkName %p, NtStatus %lx\n",
  2749. Miniport, &SymbolicLink, NtStatus);
  2750. #endif
  2751. }
  2752. }
  2753. } while (FALSE);
  2754. if(fAcquiredImMutex == TRUE)
  2755. {
  2756. RELEASE_MUTEX(pIMStartRemoveMutex);
  2757. }
  2758. PnPDereferencePackage();
  2759. DBGPRINT_RAW(DBG_COMP_PNP, DBG_LEVEL_INFO,
  2760. ("<==ndisPnPRemoveDevice: Miniport %p\n", Miniport));
  2761. return Status;
  2762. }
  2763. VOID
  2764. FASTCALL
  2765. ndisReinitializeMiniportBlock(
  2766. IN PNDIS_MINIPORT_BLOCK Miniport
  2767. )
  2768. {
  2769. PDEVICE_OBJECT PhysicalDeviceObject, DeviceObject, NextDeviceObject;
  2770. PNDIS_M_DRIVER_BLOCK MiniBlock;
  2771. PNDIS_MINIPORT_BLOCK NextGlobalMiniport;
  2772. PNDIS_MINIPORT_BLOCK PrimaryMiniport;
  2773. UNICODE_STRING BaseName, MiniportName;
  2774. PUNICODE_STRING InstanceName;
  2775. PNDIS_BIND_PATHS BindPaths;
  2776. PVOID WrapperContext;
  2777. NDIS_HANDLE DeviceContext;
  2778. ULONG PnPCapabilities;
  2779. ULONG FlagsToSave = 0;
  2780. ULONG PnPFlagsToSave = 0;
  2781. DEVICE_POWER_STATE CurrentDevicePowerState;
  2782. PVOID BusInterface;
  2783. USHORT InstanceNumber;
  2784. PSECURITY_DESCRIPTOR SecurityDescriptor;
  2785. DBGPRINT_RAW(DBG_COMP_PNP, DBG_LEVEL_INFO,
  2786. ("==>ndisReinitializeMiniportBlock: Miniport %p\n", Miniport));
  2787. PhysicalDeviceObject = Miniport->PhysicalDeviceObject;
  2788. DeviceObject= Miniport->DeviceObject;
  2789. NextDeviceObject = Miniport->NextDeviceObject;
  2790. MiniBlock = Miniport->DriverHandle;
  2791. WrapperContext = Miniport->WrapperContext;
  2792. BaseName = Miniport->BaseName;
  2793. MiniportName = Miniport->MiniportName;
  2794. InstanceName = Miniport->pAdapterInstanceName;
  2795. DeviceContext = Miniport->DeviceContext;
  2796. BindPaths = Miniport->BindPaths;
  2797. PnPCapabilities = Miniport->PnPCapabilities;
  2798. PnPFlagsToSave = Miniport->PnPFlags & (fMINIPORT_RECEIVED_START |
  2799. fMINIPORT_SWENUM |
  2800. fMINIPORT_HIDDEN |
  2801. fMINIPORT_HARDWARE_DEVICE |
  2802. fMINIPORT_NDIS_WDM_DRIVER |
  2803. fMINIPORT_FILTER_IM
  2804. );
  2805. FlagsToSave = Miniport->Flags & fMINIPORT_REQUIRES_MEDIA_POLLING;
  2806. CurrentDevicePowerState = Miniport->CurrentDevicePowerState;
  2807. NextGlobalMiniport = Miniport->NextGlobalMiniport;
  2808. PrimaryMiniport = Miniport->PrimaryMiniport;
  2809. InstanceNumber = Miniport->InstanceNumber;
  2810. BusInterface = Miniport->BusInterface;
  2811. SecurityDescriptor = Miniport->SecurityDescriptor;
  2812. ZeroMemory(Miniport, FIELD_OFFSET(NDIS_MINIPORT_BLOCK, OpenReadyEvent));
  2813. ZeroMemory((PUCHAR)Miniport +
  2814. FIELD_OFFSET(NDIS_MINIPORT_BLOCK, OpenReadyEvent) +
  2815. sizeof(Miniport->OpenReadyEvent),
  2816. sizeof(NDIS_MINIPORT_BLOCK) -
  2817. FIELD_OFFSET(NDIS_MINIPORT_BLOCK, OpenReadyEvent) -
  2818. sizeof(Miniport->OpenReadyEvent));
  2819. //
  2820. // restore what we saved
  2821. //
  2822. Miniport->PnPDeviceState = NdisPnPDeviceAdded;
  2823. Miniport->Signature = (PVOID)MINIPORT_DEVICE_MAGIC_VALUE;
  2824. Miniport->DriverHandle = MiniBlock;
  2825. INITIALIZE_SPIN_LOCK(&Miniport->Lock);
  2826. #if CHECK_TIMER
  2827. if (Miniport->DriverHandle->Flags & fMINIBLOCK_VERIFYING)
  2828. INITIALIZE_SPIN_LOCK(&Miniport->TimerQueueLock);
  2829. #endif
  2830. Miniport->PhysicalDeviceObject = PhysicalDeviceObject;
  2831. Miniport->DeviceObject = DeviceObject;
  2832. Miniport->NextDeviceObject = NextDeviceObject;
  2833. Miniport->WrapperContext = WrapperContext;
  2834. Miniport->BaseName = BaseName;
  2835. Miniport->MiniportName = MiniportName;
  2836. Miniport->pAdapterInstanceName = InstanceName;
  2837. Miniport->DeviceContext = DeviceContext;
  2838. Miniport->BindPaths = BindPaths;
  2839. Miniport->PnPCapabilities = PnPCapabilities;
  2840. Miniport->Flags = FlagsToSave;
  2841. Miniport->PnPFlags = PnPFlagsToSave;
  2842. Miniport->CurrentDevicePowerState = CurrentDevicePowerState;
  2843. Miniport->NextGlobalMiniport = NextGlobalMiniport;
  2844. Miniport->PrimaryMiniport = PrimaryMiniport;
  2845. Miniport->InstanceNumber = InstanceNumber;
  2846. Miniport->BusInterface = BusInterface;
  2847. InitializeListHead(&Miniport->PacketList);
  2848. Miniport->FirstPendingPacket = NULL;
  2849. if (MiniBlock->Flags & fMINIBLOCK_INTERMEDIATE_DRIVER)
  2850. {
  2851. MINIPORT_SET_FLAG(Miniport, fMINIPORT_INTERMEDIATE_DRIVER);
  2852. }
  2853. Miniport->SecurityDescriptor = SecurityDescriptor;
  2854. DBGPRINT_RAW(DBG_COMP_PNP, DBG_LEVEL_INFO,
  2855. ("<==ndisReinitializeMiniportBlock: Miniport %p\n", Miniport));
  2856. }
  2857. EXPORT
  2858. VOID
  2859. NdisMGetDeviceProperty(
  2860. IN NDIS_HANDLE MiniportAdapterHandle,
  2861. IN OUT PDEVICE_OBJECT * PhysicalDeviceObject OPTIONAL,
  2862. IN OUT PDEVICE_OBJECT * FunctionalDeviceObject OPTIONAL,
  2863. IN OUT PDEVICE_OBJECT * NextDeviceObject OPTIONAL,
  2864. IN OUT PCM_RESOURCE_LIST * AllocatedResources OPTIONAL,
  2865. IN OUT PCM_RESOURCE_LIST * AllocatedResourcesTranslated OPTIONAL
  2866. )
  2867. {
  2868. PNDIS_MINIPORT_BLOCK Miniport = (PNDIS_MINIPORT_BLOCK)MiniportAdapterHandle;
  2869. //
  2870. // very likely this is a NDIS_WDM driver.
  2871. //
  2872. if (!MINIPORT_PNP_TEST_FLAG(Miniport, fMINIPORT_HARDWARE_DEVICE))
  2873. {
  2874. MINIPORT_PNP_SET_FLAG(Miniport, fMINIPORT_NDIS_WDM_DRIVER);
  2875. }
  2876. if (ARGUMENT_PRESENT(PhysicalDeviceObject))
  2877. {
  2878. *PhysicalDeviceObject = Miniport->PhysicalDeviceObject;
  2879. }
  2880. if (ARGUMENT_PRESENT(FunctionalDeviceObject))
  2881. {
  2882. *FunctionalDeviceObject = Miniport->DeviceObject;
  2883. }
  2884. if (ARGUMENT_PRESENT(NextDeviceObject))
  2885. {
  2886. *NextDeviceObject = Miniport->NextDeviceObject;
  2887. }
  2888. if (ARGUMENT_PRESENT(AllocatedResources))
  2889. {
  2890. *AllocatedResources = Miniport->AllocatedResources;
  2891. }
  2892. if (ARGUMENT_PRESENT(AllocatedResourcesTranslated))
  2893. {
  2894. *AllocatedResourcesTranslated = Miniport->AllocatedResourcesTranslated;
  2895. }
  2896. return;
  2897. }
  2898. NTSTATUS
  2899. ndisWritePnPCapabilities(
  2900. IN PNDIS_MINIPORT_BLOCK Miniport,
  2901. IN ULONG PnPCapabilities
  2902. )
  2903. {
  2904. NTSTATUS RegistryStatus;
  2905. HANDLE Handle, RootHandle;
  2906. OBJECT_ATTRIBUTES ObjAttr;
  2907. UNICODE_STRING Root={0, 0, NULL};
  2908. do
  2909. {
  2910. #if NDIS_TEST_REG_FAILURE
  2911. RegistryStatus = STATUS_UNSUCCESSFUL;
  2912. RootHandle = NULL;
  2913. #else
  2914. RegistryStatus = IoOpenDeviceRegistryKey(Miniport->PhysicalDeviceObject,
  2915. PLUGPLAY_REGKEY_DRIVER,
  2916. GENERIC_WRITE | MAXIMUM_ALLOWED,
  2917. &RootHandle);
  2918. #endif
  2919. if (!NT_SUCCESS(RegistryStatus))
  2920. {
  2921. break;
  2922. }
  2923. InitializeObjectAttributes(&ObjAttr,
  2924. &Root,
  2925. OBJ_CASE_INSENSITIVE,
  2926. RootHandle,
  2927. NULL);
  2928. RegistryStatus = ZwOpenKey(&Handle,
  2929. GENERIC_READ | MAXIMUM_ALLOWED,
  2930. &ObjAttr);
  2931. if (NT_SUCCESS(RegistryStatus))
  2932. {
  2933. RegistryStatus = RtlWriteRegistryValue(RTL_REGISTRY_HANDLE,
  2934. Handle,
  2935. L"PnPCapabilities",
  2936. REG_DWORD,
  2937. &PnPCapabilities,
  2938. sizeof(ULONG));
  2939. ZwClose(Handle);
  2940. }
  2941. ZwClose(RootHandle);
  2942. } while (FALSE);
  2943. return RegistryStatus;
  2944. }
  2945. NDIS_STATUS
  2946. NdisMRemoveMiniport(
  2947. IN NDIS_HANDLE MiniportHandle
  2948. )
  2949. /*++
  2950. Routine Description:
  2951. Miniports call this routine to signal a device failure.
  2952. in response, ndis will ask PnP to send a REMOVE IRP for this device
  2953. Arguments:
  2954. MiniportHandle - Miniport
  2955. Return Value:
  2956. always successful
  2957. --*/
  2958. {
  2959. PNDIS_MINIPORT_BLOCK Miniport = (PNDIS_MINIPORT_BLOCK)MiniportHandle;
  2960. MINIPORT_PNP_SET_FLAG(Miniport, fMINIPORT_DEVICE_FAILED);
  2961. IoInvalidateDeviceState(Miniport->PhysicalDeviceObject);
  2962. return(NDIS_STATUS_SUCCESS);
  2963. }
  2964. PNDIS_MINIPORT_BLOCK
  2965. ndisFindMiniportOnGlobalList(
  2966. IN PNDIS_STRING DeviceName
  2967. )
  2968. /*++
  2969. Routine Description:
  2970. Find the Miniport with a matching device name on ndisMiniportList.
  2971. Arguments:
  2972. Return Value:
  2973. a pointer to MiniportBlock if found. NULL otherwise
  2974. --*/
  2975. {
  2976. KIRQL OldIrql;
  2977. PNDIS_MINIPORT_BLOCK Miniport;
  2978. NDIS_STRING UpcaseDevice;
  2979. PWSTR pwch;
  2980. DBGPRINT(DBG_COMP_PNP, DBG_LEVEL_INFO,
  2981. ("==>ndisFindMiniportOnGlobalList: DeviceName %p\n", DeviceName));
  2982. //
  2983. // First we need to upcase the device-name before checking
  2984. //
  2985. UpcaseDevice.Length = DeviceName->Length;
  2986. UpcaseDevice.MaximumLength = DeviceName->Length + sizeof(WCHAR);
  2987. UpcaseDevice.Buffer = ALLOC_FROM_POOL(UpcaseDevice.MaximumLength, NDIS_TAG_STRING);
  2988. if ((pwch = UpcaseDevice.Buffer) == NULL)
  2989. {
  2990. return NULL;
  2991. }
  2992. RtlUpcaseUnicodeString(&UpcaseDevice, DeviceName, FALSE);
  2993. ASSERT(ndisPkgs[NPNP_PKG].ReferenceCount > 0);
  2994. PnPReferencePackage();
  2995. ACQUIRE_SPIN_LOCK(&ndisMiniportListLock, &OldIrql);
  2996. for (Miniport = ndisMiniportList;
  2997. Miniport != NULL;
  2998. Miniport = Miniport->NextGlobalMiniport)
  2999. {
  3000. if (NDIS_EQUAL_UNICODE_STRING(&UpcaseDevice, &Miniport->MiniportName))
  3001. {
  3002. break;
  3003. }
  3004. }
  3005. RELEASE_SPIN_LOCK(&ndisMiniportListLock, OldIrql);
  3006. PnPDereferencePackage();
  3007. FREE_POOL(pwch);
  3008. DBGPRINT(DBG_COMP_PNP, DBG_LEVEL_INFO,
  3009. ("<==ndisFindMiniportOnGlobalList: Miniport %p\n", Miniport));
  3010. return Miniport;
  3011. }
  3012. ULONG
  3013. NdisMGetDmaAlignment(
  3014. IN NDIS_HANDLE MiniportAdapterHandle
  3015. )
  3016. {
  3017. PNDIS_MINIPORT_BLOCK Miniport = (PNDIS_MINIPORT_BLOCK)MiniportAdapterHandle;
  3018. ASSERT(CURRENT_IRQL < DISPATCH_LEVEL);
  3019. ASSERT(Miniport->SystemAdapterObject != NULL);
  3020. if (Miniport->SystemAdapterObject)
  3021. {
  3022. return (Miniport->SystemAdapterObject->DmaOperations->GetDmaAlignment(Miniport->SystemAdapterObject));
  3023. }
  3024. else
  3025. {
  3026. return 0;
  3027. }
  3028. }
  3029. ULONG
  3030. NdisGetSharedDataAlignment(
  3031. VOID
  3032. )
  3033. {
  3034. return KeGetRecommendedSharedDataAlignment();
  3035. }
  3036. VOID
  3037. ndisDereferenceDmaAdapter(
  3038. IN PNDIS_MINIPORT_BLOCK Miniport
  3039. )
  3040. {
  3041. PDMA_ADAPTER DmaAdapter;
  3042. PPUT_DMA_ADAPTER putDmaAdapter;
  3043. LONG DmaAdapterRefCount;
  3044. KIRQL OldIrql;
  3045. NDIS_ACQUIRE_MINIPORT_SPIN_LOCK(Miniport, &OldIrql);
  3046. DmaAdapterRefCount = InterlockedDecrement(&Miniport->DmaAdapterRefCount);
  3047. ASSERT(DmaAdapterRefCount >= 0);
  3048. if (DmaAdapterRefCount == 0)
  3049. {
  3050. //
  3051. // free the dma adapter
  3052. //
  3053. DmaAdapter = Miniport->SystemAdapterObject;
  3054. ASSERT(DmaAdapter != NULL);
  3055. if (DmaAdapter != NULL)
  3056. {
  3057. Miniport->SavedSystemAdapterObject = Miniport->SystemAdapterObject;
  3058. putDmaAdapter = *DmaAdapter->DmaOperations->PutDmaAdapter;
  3059. putDmaAdapter(DmaAdapter);
  3060. Miniport->SystemAdapterObject = NULL;
  3061. }
  3062. if (Miniport->SGListLookasideList)
  3063. {
  3064. ExDeleteNPagedLookasideList(Miniport->SGListLookasideList);
  3065. FREE_POOL(Miniport->SGListLookasideList);
  3066. Miniport->SGListLookasideList = NULL;
  3067. }
  3068. if (Miniport->DmaResourcesReleasedEvent != NULL)
  3069. {
  3070. SET_EVENT(Miniport->DmaResourcesReleasedEvent);
  3071. }
  3072. }
  3073. NDIS_RELEASE_MINIPORT_SPIN_LOCK(Miniport, OldIrql);
  3074. }