Leaked source code of windows server 2003
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.

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