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

660 lines
20 KiB

  1. /*++
  2. Copyright (c) 1990-1995 Microsoft Corporation
  3. Module Name:
  4. bus.c
  5. Abstract:
  6. NDIS wrapper functions to handle specific buses
  7. Author:
  8. Adam Barr (adamba) 11-Jul-1990
  9. Environment:
  10. Kernel mode, FSD
  11. Revision History:
  12. 26-Feb-1991 JohnsonA Added Debugging Code
  13. 10-Jul-1991 JohnsonA Implement revised Ndis Specs
  14. 01-Jun-1995 JameelH Re-organization/optimization
  15. --*/
  16. #include <precomp.h>
  17. #pragma hdrstop
  18. #include <stdarg.h>
  19. //
  20. // Define the module number for debug code.
  21. //
  22. #define MODULE_NUMBER MODULE_BUS
  23. VOID
  24. NdisReadEisaSlotInformation(
  25. OUT PNDIS_STATUS Status,
  26. IN NDIS_HANDLE WrapperConfigurationContext,
  27. OUT PUINT SlotNumber,
  28. OUT PNDIS_EISA_FUNCTION_INFORMATION EisaData
  29. )
  30. /*++
  31. Routine Description:
  32. This routine reads the EISA data from the slot given.
  33. Arguments:
  34. Status - Status of request to be returned to the user.
  35. WrapperConfigurationContext - Context passed to MacAddAdapter.
  36. SlotNumber - the EISA Slot where the card is at.
  37. EisaData - pointer to a buffer where the EISA configuration is to be returned.
  38. Return Value:
  39. None.
  40. --*/
  41. {
  42. DBGPRINT_RAW(DBG_COMP_BUSINFO, DBG_LEVEL_INFO,
  43. ("==>NdisReadEisaSlotInformation: WrapperConfigurationContext %p\n", WrapperConfigurationContext));
  44. *Status = NDIS_STATUS_NOT_SUPPORTED;
  45. DBGPRINT_RAW(DBG_COMP_BUSINFO, DBG_LEVEL_INFO,
  46. ("<==NdisReadEisaSlotInformation: WrapperConfigurationContext %p, Status %lx\n", WrapperConfigurationContext, *Status));
  47. return;
  48. }
  49. VOID
  50. NdisReadEisaSlotInformationEx(
  51. OUT PNDIS_STATUS Status,
  52. IN NDIS_HANDLE WrapperConfigurationContext,
  53. OUT PUINT SlotNumber,
  54. OUT PNDIS_EISA_FUNCTION_INFORMATION *EisaData,
  55. OUT PUINT NumberOfFunctions
  56. )
  57. /*++
  58. Routine Description:
  59. This routine reads the EISA data from the slot given.
  60. Arguments:
  61. Status - Status of request to be returned to the user.
  62. WrapperConfigurationContext - Context passed to MacAddAdapter.
  63. SlotNumber - the EISA Slot where the card is at.
  64. EisaData - pointer to a buffer where the EISA configuration is to be returned.
  65. NumberOfFunctions - Returns the number of function structures in the EisaData.
  66. Return Value:
  67. None.
  68. --*/
  69. {
  70. DBGPRINT_RAW(DBG_COMP_BUSINFO, DBG_LEVEL_INFO,
  71. ("==>NdisReadEisaSlotInformationEx: WrapperConfigurationContext %p\n", WrapperConfigurationContext));
  72. *Status = NDIS_STATUS_NOT_SUPPORTED;
  73. DBGPRINT_RAW(DBG_COMP_BUSINFO, DBG_LEVEL_INFO,
  74. ("<==NdisReadEisaSlotInformationEx: WrapperConfigurationContext %p, Status %lx\n", WrapperConfigurationContext, *Status));
  75. return;
  76. }
  77. ULONG
  78. NdisImmediateReadPciSlotInformation(
  79. IN NDIS_HANDLE WrapperConfigurationContext,
  80. IN ULONG SlotNumber,
  81. IN ULONG Offset,
  82. IN PVOID Buffer,
  83. IN ULONG Length
  84. )
  85. /*++
  86. Routine Description:
  87. This routine reads from the PCI configuration space a specified
  88. length of bytes at a certain offset.
  89. Arguments:
  90. WrapperConfigurationContext - Context passed to MacAddAdapter.
  91. SlotNumber - The slot number of the device.
  92. Offset - Offset to read from
  93. Buffer - Place to store the bytes
  94. Length - Number of bytes to read
  95. Return Value:
  96. Returns the number of bytes read.
  97. --*/
  98. {
  99. PRTL_QUERY_REGISTRY_TABLE KeyQueryTable = (PRTL_QUERY_REGISTRY_TABLE)WrapperConfigurationContext;
  100. PNDIS_MINIPORT_BLOCK Miniport = (PNDIS_MINIPORT_BLOCK)KeyQueryTable[3].QueryRoutine;
  101. ULONG BytesRead;
  102. DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO,
  103. ("==>NdisImmediateReadPciSlotInformation: Miniport %p\n", Miniport));
  104. ASSERT(Miniport != NULL);
  105. NDIS_WARN(TRUE, Miniport, NDIS_GFLAG_WARN_LEVEL_3,
  106. ("NdisImmediateReadPciSlotInformation: this API is going away. Use NdisReadPciSlotInformation\n", Miniport));
  107. NDIS_WARN((SlotNumber != 0), Miniport, NDIS_GFLAG_WARN_LEVEL_2,
  108. ("NdisImmediateReadPciSlotInformation: Miniport %p passes a non-zero SlotNumber to the function\n", Miniport));
  109. BytesRead = ndisGetSetBusConfigSpace(Miniport,
  110. Offset,
  111. Buffer,
  112. Length,
  113. PCI_WHICHSPACE_CONFIG,
  114. TRUE);
  115. DBGPRINT_RAW(DBG_COMP_BUSINFO, DBG_LEVEL_INFO,
  116. ("<==NdisImmediateReadPciSlotInformation: Miniport %p\n", Miniport));
  117. return BytesRead;
  118. }
  119. ULONG
  120. NdisImmediateWritePciSlotInformation(
  121. IN NDIS_HANDLE WrapperConfigurationContext,
  122. IN ULONG SlotNumber,
  123. IN ULONG Offset,
  124. IN PVOID Buffer,
  125. IN ULONG Length
  126. )
  127. /*++
  128. Routine Description:
  129. This routine writes to the PCI configuration space a specified
  130. length of bytes at a certain offset.
  131. Arguments:
  132. WrapperConfigurationContext - Context passed to MacAddAdapter.
  133. SlotNumber - The slot number of the device.
  134. Offset - Offset to read from
  135. Buffer - Place to store the bytes
  136. Length - Number of bytes to read
  137. Return Value:
  138. Returns the number of bytes written.
  139. --*/
  140. {
  141. PRTL_QUERY_REGISTRY_TABLE KeyQueryTable = (PRTL_QUERY_REGISTRY_TABLE)WrapperConfigurationContext;
  142. PNDIS_MINIPORT_BLOCK Miniport = (PNDIS_MINIPORT_BLOCK)KeyQueryTable[3].QueryRoutine;
  143. ULONG BytesWritten;
  144. DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO,
  145. ("==>NdisImmediateWritePciSlotInformation: Miniport %p\n", Miniport));
  146. ASSERT(Miniport != NULL);
  147. NDIS_WARN(TRUE, Miniport, NDIS_GFLAG_WARN_LEVEL_3,
  148. ("NdisImmediateWritePciSlotInformation: this API is going away. Use NdisWritePciSlotInformation\n", Miniport));
  149. NDIS_WARN((SlotNumber != 0), Miniport, NDIS_GFLAG_WARN_LEVEL_2,
  150. ("NdisImmediateWritePciSlotInformation: Miniport %p passes a non-zero SlotNumber to the function\n", Miniport));
  151. BytesWritten = ndisGetSetBusConfigSpace(Miniport,
  152. Offset,
  153. Buffer,
  154. Length,
  155. PCI_WHICHSPACE_CONFIG,
  156. FALSE);
  157. DBGPRINT_RAW(DBG_COMP_BUSINFO, DBG_LEVEL_INFO,
  158. ("<==NdisImmediateWritePciSlotInformation: Miniport %p\n", Miniport));
  159. return BytesWritten;
  160. }
  161. ULONG
  162. NdisReadPciSlotInformation(
  163. IN NDIS_HANDLE NdisAdapterHandle,
  164. IN ULONG SlotNumber,
  165. IN ULONG Offset,
  166. IN PVOID Buffer,
  167. IN ULONG Length
  168. )
  169. /*++
  170. Routine Description:
  171. This routine reads from the PCI configuration space a specified
  172. length of bytes at a certain offset.
  173. Arguments:
  174. NdisAdapterHandle - Adapter we are talking about.
  175. SlotNumber - The slot number of the device.
  176. Offset - Offset to read from
  177. Buffer - Place to store the bytes
  178. Length - Number of bytes to read
  179. Return Value:
  180. Returns the number of bytes read.
  181. --*/
  182. {
  183. PNDIS_MINIPORT_BLOCK Miniport = (PNDIS_MINIPORT_BLOCK)NdisAdapterHandle;
  184. ULONG BytesRead;
  185. DBGPRINT_RAW(DBG_COMP_BUSINFO, DBG_LEVEL_INFO,
  186. ("==>NdisReadPciSlotInformation: Miniport %p\n", Miniport));
  187. NDIS_WARN((SlotNumber != 0), Miniport, NDIS_GFLAG_WARN_LEVEL_2,
  188. ("NdisReadPciSlotInformation: Miniport %p passes a non-zero SlotNumber to the function\n", Miniport));
  189. BytesRead = ndisGetSetBusConfigSpace(Miniport,
  190. Offset,
  191. Buffer,
  192. Length,
  193. PCI_WHICHSPACE_CONFIG,
  194. TRUE);
  195. DBGPRINT_RAW(DBG_COMP_BUSINFO, DBG_LEVEL_INFO,
  196. ("<==NdisReadPciSlotInformation: Miniport %p\n", Miniport));
  197. return BytesRead;
  198. }
  199. ULONG
  200. NdisWritePciSlotInformation(
  201. IN NDIS_HANDLE NdisAdapterHandle,
  202. IN ULONG SlotNumber,
  203. IN ULONG Offset,
  204. IN PVOID Buffer,
  205. IN ULONG Length
  206. )
  207. /*++
  208. Routine Description:
  209. This routine writes to the PCI configuration space a specified
  210. length of bytes at a certain offset.
  211. Arguments:
  212. NdisAdapterHandle - Adapter we are talking about.
  213. SlotNumber - The slot number of the device.
  214. Offset - Offset to read from
  215. Buffer - Place to store the bytes
  216. Length - Number of bytes to read
  217. Return Value:
  218. Returns the number of bytes written.
  219. --*/
  220. {
  221. PNDIS_MINIPORT_BLOCK Miniport = (PNDIS_MINIPORT_BLOCK)NdisAdapterHandle;
  222. ULONG BytesWritten;
  223. DBGPRINT_RAW(DBG_COMP_BUSINFO, DBG_LEVEL_INFO,
  224. ("==>NdisWritePciSlotInformation: Miniport %p\n", Miniport));
  225. NDIS_WARN((SlotNumber != 0), Miniport, NDIS_GFLAG_WARN_LEVEL_2,
  226. ("NdisWritePciSlotInformation: Miniport %p passes a non-zero SlotNumber to the function\n", Miniport));
  227. BytesWritten = ndisGetSetBusConfigSpace(Miniport,
  228. Offset,
  229. Buffer,
  230. Length,
  231. PCI_WHICHSPACE_CONFIG,
  232. FALSE);
  233. DBGPRINT_RAW(DBG_COMP_BUSINFO, DBG_LEVEL_INFO,
  234. ("<==NdisWritePciSlotInformation: Miniport %p\n", Miniport));
  235. return BytesWritten;
  236. }
  237. NTSTATUS
  238. FASTCALL
  239. ndisQueryBusInterface(
  240. IN PNDIS_MINIPORT_BLOCK Miniport
  241. )
  242. {
  243. PIRP Irp;
  244. PIO_STACK_LOCATION IrpSp;
  245. NTSTATUS Status;
  246. PDEVICE_OBJECT NextDeviceObject;
  247. BUS_INTERFACE_STANDARD BusInterfaceStandard = {0};
  248. DBGPRINT_RAW(DBG_COMP_PNP, DBG_LEVEL_INFO,
  249. ("==>ndisQueryBusInterface: Miniport %p\n", Miniport));
  250. do {
  251. NextDeviceObject = Miniport->NextDeviceObject;
  252. //
  253. // Allocate an irp to send to PCI bus device driver.
  254. //
  255. Irp = IoAllocateIrp((CCHAR)(NextDeviceObject->StackSize + 1),
  256. FALSE);
  257. if (Irp == NULL)
  258. {
  259. ASSERT(FALSE);
  260. Status = STATUS_INSUFFICIENT_RESOURCES;
  261. break;
  262. }
  263. //
  264. // Get the stack location for the next device.
  265. //
  266. IrpSp = IoGetNextIrpStackLocation(Irp);
  267. ASSERT(IrpSp != NULL);
  268. IrpSp->MajorFunction = IRP_MJ_PNP;
  269. IrpSp->MinorFunction = IRP_MN_QUERY_INTERFACE;
  270. IrpSp->DeviceObject = NextDeviceObject;
  271. Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
  272. IrpSp->Parameters.QueryInterface.InterfaceType = &GUID_BUS_INTERFACE_STANDARD;
  273. IrpSp->Parameters.QueryInterface.Size = sizeof (BUS_INTERFACE_STANDARD);
  274. IrpSp->Parameters.QueryInterface.Version = 1;
  275. IrpSp->Parameters.QueryInterface.Interface = (PINTERFACE)&BusInterfaceStandard;
  276. ASSERT(KeGetCurrentIrql() == 0);
  277. Status = ndisPassIrpDownTheStack(Irp, NextDeviceObject);
  278. if (NT_SUCCESS(Status))
  279. {
  280. Miniport->SetBusData = BusInterfaceStandard.SetBusData;
  281. Miniport->GetBusData = BusInterfaceStandard.GetBusData;
  282. Miniport->BusDataContext = BusInterfaceStandard.Context;
  283. Status = NDIS_STATUS_SUCCESS;
  284. }
  285. IoFreeIrp(Irp);
  286. } while (FALSE);
  287. DBGPRINT_RAW(DBG_COMP_PNP, DBG_LEVEL_INFO,
  288. ("<==ndisQueryBusInterface: Miniport %p\n", Miniport));
  289. return Status;
  290. }
  291. ULONG
  292. ndisGetSetBusConfigSpace(
  293. IN PNDIS_MINIPORT_BLOCK Miniport,
  294. IN ULONG Offset,
  295. IN PVOID Buffer,
  296. IN ULONG Length,
  297. IN ULONG WhichSpace,
  298. IN BOOLEAN Read
  299. )
  300. {
  301. ULONG ActualLength = 0;
  302. DBGPRINT_RAW(DBG_COMP_BUSINFO, DBG_LEVEL_INFO,
  303. ("==>ndisGetSetBusConfigSpace: Miniport %p\n", Miniport));
  304. if ((Read && MINIPORT_VERIFY_TEST_FLAG(Miniport, fMINIPORT_VERIFY_FAIL_READ_CONFIG_SPACE)) ||
  305. MINIPORT_VERIFY_TEST_FLAG(Miniport, fMINIPORT_VERIFY_FAIL_WRITE_CONFIG_SPACE))
  306. {
  307. #if DBG
  308. DbgPrint("ndisGetSetBusConfigSpace failed to verify miniport %p\n", Miniport);
  309. #endif
  310. return 0;
  311. }
  312. do
  313. {
  314. if ((Miniport->SetBusData == NULL) || (Miniport->BusDataContext == NULL))
  315. break;
  316. ActualLength = (Read ? Miniport->GetBusData : Miniport->SetBusData)(
  317. Miniport->BusDataContext,
  318. WhichSpace,
  319. Buffer,
  320. Offset,
  321. Length);
  322. } while (FALSE);
  323. DBGPRINT_RAW(DBG_COMP_BUSINFO, DBG_LEVEL_INFO,
  324. ("<==ndisGetSetBusConfigSpace: Miniport %p\n", Miniport));
  325. return ActualLength;
  326. }
  327. NDIS_STATUS
  328. ndisTranslateResources(
  329. IN PNDIS_MINIPORT_BLOCK Miniport,
  330. IN CM_RESOURCE_TYPE ResourceType,
  331. IN PHYSICAL_ADDRESS Resource,
  332. OUT PPHYSICAL_ADDRESS pTranslatedResource,
  333. OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR * pResourceDescriptor OPTIONAL
  334. )
  335. {
  336. UINT j;
  337. PCM_RESOURCE_LIST AllocatedResources, AllocatedResourcesTranslated;
  338. PHYSICAL_ADDRESS Offset;
  339. PCM_PARTIAL_RESOURCE_LIST pResourceList, pResourceListTranslated;
  340. NDIS_STATUS Status = NDIS_STATUS_FAILURE;
  341. DBGPRINT_RAW(DBG_COMP_CONFIG, DBG_LEVEL_INFO,
  342. ("==>ndisTranslateResources: Miniport %p\n", Miniport));
  343. DBGPRINT_RAW(DBG_COMP_CONFIG, DBG_LEVEL_INFO,
  344. (" translating resource type: %lx, value: %I64x\n", ResourceType, Resource));
  345. do
  346. {
  347. AllocatedResources = Miniport->AllocatedResources;
  348. AllocatedResourcesTranslated = Miniport->AllocatedResourcesTranslated;
  349. if ((AllocatedResources == NULL) || (AllocatedResourcesTranslated == NULL))
  350. {
  351. Status = NDIS_STATUS_FAILURE;
  352. break;
  353. }
  354. pResourceList = &(AllocatedResources->List[0].PartialResourceList);
  355. pResourceListTranslated = &(AllocatedResourcesTranslated->List[0].PartialResourceList);
  356. for (j = 0; j < pResourceList->Count; j++)
  357. {
  358. if (pResourceList->PartialDescriptors[j].Type != ResourceType)
  359. continue;
  360. switch (ResourceType)
  361. {
  362. case CmResourceTypePort:
  363. case CmResourceTypeMemory:
  364. Offset.QuadPart = Resource.QuadPart - pResourceList->PartialDescriptors[j].u.Port.Start.QuadPart;
  365. if ((Offset.QuadPart >= 0) && (Offset.u.HighPart == 0) &&
  366. (((ULONG)(Offset.u.LowPart)) < pResourceList->PartialDescriptors[j].u.Port.Length))
  367. {
  368. pTranslatedResource->QuadPart = pResourceListTranslated->PartialDescriptors[j].u.Memory.Start.QuadPart +
  369. Offset.QuadPart;
  370. Status = NDIS_STATUS_SUCCESS;
  371. }
  372. break;
  373. case CmResourceTypeInterrupt:
  374. if (Resource.QuadPart == pResourceList->PartialDescriptors[j].u.Interrupt.Level)
  375. {
  376. pTranslatedResource->QuadPart = (LONGLONG)pResourceListTranslated->PartialDescriptors[j].u.Interrupt.Level;
  377. Status = NDIS_STATUS_SUCCESS;
  378. }
  379. break;
  380. case CmResourceTypeDma:
  381. if (Resource.QuadPart == pResourceList->PartialDescriptors[j].u.Dma.Channel)
  382. {
  383. pTranslatedResource->QuadPart = (LONGLONG)pResourceListTranslated->PartialDescriptors[j].u.Dma.Channel;
  384. Status = NDIS_STATUS_SUCCESS;
  385. }
  386. break;
  387. }
  388. if (Status == NDIS_STATUS_SUCCESS)
  389. {
  390. DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO,
  391. (" ndisTranslateResources translated %I64x to %I64x\n", Resource, *pTranslatedResource));
  392. if (pResourceDescriptor != NULL)
  393. {
  394. *pResourceDescriptor = &pResourceListTranslated->PartialDescriptors[j];
  395. }
  396. break;
  397. }
  398. }
  399. } while (FALSE);
  400. DBGPRINT_RAW(DBG_COMP_CONFIG, DBG_LEVEL_INFO,
  401. ("<==ndisTranslateResources: Miniport %p, Status %lx\n", Miniport, Status));
  402. return Status;
  403. }
  404. ULONG
  405. NdisReadPcmciaAttributeMemory(
  406. IN NDIS_HANDLE NdisAdapterHandle,
  407. IN ULONG Offset,
  408. IN PVOID Buffer,
  409. IN ULONG Length
  410. )
  411. {
  412. PNDIS_MINIPORT_BLOCK Miniport = (PNDIS_MINIPORT_BLOCK)NdisAdapterHandle;
  413. PDEVICE_OBJECT NextDeviceObject;
  414. ULONG BytesRead;
  415. DBGPRINT_RAW(DBG_COMP_BUSINFO, DBG_LEVEL_INFO,
  416. ("==>NdisReadPcmciaAttributeMemory: Miniport %p\n", Miniport));
  417. NextDeviceObject = Miniport->NextDeviceObject;
  418. ASSERT(NextDeviceObject != NULL);
  419. //
  420. // use direct entry points in bus driver to get/set bus data
  421. //
  422. BytesRead = ndisGetSetBusConfigSpace(Miniport,
  423. Offset,
  424. Buffer,
  425. Length,
  426. PCCARD_ATTRIBUTE_MEMORY,
  427. TRUE);
  428. DBGPRINT_RAW(DBG_COMP_BUSINFO, DBG_LEVEL_INFO,
  429. ("<==NdisReadPcmciaAttributeMemory: Miniport %p, Bytes Read %lx\n", Miniport, BytesRead));
  430. return BytesRead;
  431. }
  432. ULONG
  433. NdisWritePcmciaAttributeMemory(
  434. IN NDIS_HANDLE NdisAdapterHandle,
  435. IN ULONG Offset,
  436. IN PVOID Buffer,
  437. IN ULONG Length
  438. )
  439. {
  440. PNDIS_MINIPORT_BLOCK Miniport = (PNDIS_MINIPORT_BLOCK)NdisAdapterHandle;
  441. PDEVICE_OBJECT NextDeviceObject;
  442. ULONG BytesWritten;
  443. DBGPRINT_RAW(DBG_COMP_BUSINFO, DBG_LEVEL_INFO,
  444. ("==>NdisWritePcmciaAttributeMemory: Miniport %p\n", Miniport));
  445. NextDeviceObject = Miniport->NextDeviceObject;
  446. ASSERT(NextDeviceObject != NULL);
  447. BytesWritten = ndisGetSetBusConfigSpace(Miniport,
  448. Offset,
  449. Buffer,
  450. Length,
  451. PCCARD_ATTRIBUTE_MEMORY,
  452. FALSE);
  453. DBGPRINT_RAW(DBG_COMP_BUSINFO, DBG_LEVEL_INFO,
  454. ("<==NdisWritePcmciaAttributeMemory: Miniport %p, Bytes Written %.8x\n", Miniport, BytesWritten));
  455. return BytesWritten;
  456. }
  457. VOID
  458. NdisOverrideBusNumber(
  459. IN NDIS_HANDLE WrapperConfigurationContext,
  460. IN NDIS_HANDLE MiniportAdapterHandle OPTIONAL,
  461. IN ULONG BusNumber
  462. )
  463. {
  464. #if DBG
  465. PRTL_QUERY_REGISTRY_TABLE KeyQueryTable = (PRTL_QUERY_REGISTRY_TABLE)WrapperConfigurationContext;
  466. PNDIS_MINIPORT_BLOCK Miniport = (PNDIS_MINIPORT_BLOCK)KeyQueryTable[3].QueryRoutine;
  467. NDIS_WARN(TRUE, Miniport, NDIS_GFLAG_WARN_LEVEL_1,
  468. ("NdisOverrideBusNumber: This API is going away.\n", Miniport));
  469. #endif
  470. }
  471. VOID
  472. NdisReadMcaPosInformation(
  473. OUT PNDIS_STATUS Status,
  474. IN NDIS_HANDLE WrapperConfigurationContext,
  475. OUT PUINT ChannelNumber,
  476. OUT PNDIS_MCA_POS_DATA McaData
  477. )
  478. {
  479. *Status = NDIS_STATUS_NOT_SUPPORTED;
  480. return;
  481. }