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.

368 lines
9.2 KiB

  1. /*++
  2. Copyright (c) 1997-2000 Microsoft Corporation
  3. Module Name:
  4. agpintrf.c
  5. Abstract:
  6. This module implements the "bus handler" interfaces supported
  7. by the PCI driver.
  8. Author:
  9. Peter Johnston (peterj) 6-Jun-1997
  10. Revision History:
  11. --*/
  12. #include "pcip.h"
  13. #define AGPINTRF_VERSION 1
  14. //
  15. // Prototypes for routines exposed only thru the "interface"
  16. // mechanism.
  17. //
  18. NTSTATUS
  19. agpintrf_Constructor(
  20. PVOID DeviceExtension,
  21. PVOID PciInterface,
  22. PVOID InterfaceSpecificData,
  23. USHORT Version,
  24. USHORT Size,
  25. PINTERFACE InterfaceReturn
  26. );
  27. VOID
  28. agpintrf_Reference(
  29. IN PVOID Context
  30. );
  31. VOID
  32. agpintrf_Dereference(
  33. IN PVOID Context
  34. );
  35. NTSTATUS
  36. agpintrf_Initializer(
  37. IN PPCI_ARBITER_INSTANCE Instance
  38. );
  39. ULONG
  40. PciReadAgpConfig(
  41. IN PVOID Context,
  42. IN ULONG WhichSpace,
  43. IN PVOID Buffer,
  44. IN ULONG Offset,
  45. IN ULONG Length
  46. );
  47. ULONG
  48. PciWriteAgpConfig(
  49. IN PVOID Context,
  50. IN ULONG WhichSpace,
  51. IN PVOID Buffer,
  52. IN ULONG Offset,
  53. IN ULONG Length
  54. );
  55. //
  56. // Define the Bus Interface "Interface" structure.
  57. //
  58. PCI_INTERFACE AgpTargetInterface = {
  59. &GUID_AGP_TARGET_BUS_INTERFACE_STANDARD, // InterfaceType
  60. sizeof(AGP_TARGET_BUS_INTERFACE_STANDARD), // MinSize
  61. AGPINTRF_VERSION, // MinVersion
  62. AGPINTRF_VERSION, // MaxVersion
  63. PCIIF_PDO, // Flags
  64. 0, // ReferenceCount
  65. PciInterface_AgpTarget, // Signature
  66. agpintrf_Constructor, // Constructor
  67. agpintrf_Initializer // Instance Initializer
  68. };
  69. #ifdef ALLOC_PRAGMA
  70. #pragma alloc_text(PAGE, agpintrf_Constructor)
  71. #pragma alloc_text(PAGE, agpintrf_Dereference)
  72. #pragma alloc_text(PAGE, agpintrf_Initializer)
  73. #pragma alloc_text(PAGE, agpintrf_Reference)
  74. #endif
  75. VOID
  76. agpintrf_Reference(
  77. IN PVOID Context
  78. )
  79. {
  80. PPCI_PDO_EXTENSION targetExtension = (PPCI_PDO_EXTENSION)Context;
  81. ASSERT_PCI_PDO_EXTENSION(targetExtension);
  82. if (InterlockedIncrement(&targetExtension->AgpInterfaceReferenceCount) == 1) {
  83. ObReferenceObject(targetExtension->PhysicalDeviceObject);
  84. }
  85. }
  86. VOID
  87. agpintrf_Dereference(
  88. IN PVOID Context
  89. )
  90. {
  91. PPCI_PDO_EXTENSION targetExtension = (PPCI_PDO_EXTENSION)Context;
  92. ASSERT_PCI_PDO_EXTENSION(targetExtension);
  93. if (InterlockedDecrement(&targetExtension->AgpInterfaceReferenceCount) == 0) {
  94. ObDereferenceObject(targetExtension->PhysicalDeviceObject);
  95. }
  96. }
  97. NTSTATUS
  98. agpintrf_Constructor(
  99. PVOID DeviceExtension,
  100. PVOID PciInterface,
  101. PVOID InterfaceSpecificData,
  102. USHORT Version,
  103. USHORT Size,
  104. PINTERFACE InterfaceReturn
  105. )
  106. /*++
  107. Routine Description:
  108. Initialize the AGP_TARGET_BUS_INTERFACE fields.
  109. This interface can only be requested from the device stack of an AGP
  110. bridge. This routine looks for an AGP capability in the requester
  111. bridge and any peer host bridges. If one is found, config access
  112. to the device with the capability is granted.
  113. Arguments:
  114. PciInterface Pointer to the PciInterface record for this
  115. interface type.
  116. InterfaceSpecificData
  117. A ULONG containing the resource type for which
  118. arbitration is required.
  119. InterfaceReturn
  120. Return Value:
  121. TRUE is this device is not known to cause problems, FALSE
  122. if the device should be skipped altogether.
  123. --*/
  124. {
  125. PAGP_TARGET_BUS_INTERFACE_STANDARD targetInterface = (PAGP_TARGET_BUS_INTERFACE_STANDARD)InterfaceReturn;
  126. PPCI_PDO_EXTENSION extension = (PPCI_PDO_EXTENSION)DeviceExtension;
  127. PPCI_PDO_EXTENSION current;
  128. PPCI_PDO_EXTENSION targetExtension = NULL;
  129. PPCI_FDO_EXTENSION parentExtension;
  130. if ((extension->BaseClass != PCI_CLASS_BRIDGE_DEV) ||
  131. (extension->SubClass != PCI_SUBCLASS_BR_PCI_TO_PCI)) {
  132. //
  133. // This interface is only supported on AGP bridges,
  134. // which are PCI-PCI bridges.
  135. //
  136. return STATUS_NOT_SUPPORTED;
  137. }
  138. if (extension->TargetAgpCapabilityId == PCI_CAPABILITY_ID_AGP_TARGET) {
  139. //
  140. // The bridge has a target AGP capability itself. Give the
  141. // caller access to its config space.
  142. //
  143. targetExtension = extension;
  144. } else {
  145. //
  146. // No target AGP capability on the bridge itself. Look on the same
  147. // bus as the bridge for host bridges with the AGP capability.
  148. //
  149. parentExtension = extension->ParentFdoExtension;
  150. if (!PCI_IS_ROOT_FDO(parentExtension)) {
  151. //
  152. // Not likely to find host bridges on non-root busses.
  153. // Even if we could, constrain this interface to only support
  154. // root busses.
  155. //
  156. return STATUS_NOT_SUPPORTED;
  157. }
  158. ExAcquireFastMutex(&parentExtension->ChildListMutex);
  159. for (current = parentExtension->ChildPdoList; current != NULL; current = current->Next) {
  160. if ((current->BaseClass == PCI_CLASS_BRIDGE_DEV) &&
  161. (current->SubClass == PCI_SUBCLASS_BR_HOST) &&
  162. (current->TargetAgpCapabilityId != 0)) {
  163. //
  164. // We have a host bridge with a target AGP capability. Check to make
  165. // sure that there's only one such host bridge. If there are multiple,
  166. // we don't know which to grant access to, so fail the call.
  167. //
  168. if (targetExtension != NULL) {
  169. ExReleaseFastMutex(&parentExtension->ChildListMutex);
  170. return STATUS_NOT_SUPPORTED;
  171. }
  172. targetExtension = current;
  173. }
  174. }
  175. ExReleaseFastMutex(&parentExtension->ChildListMutex);
  176. if (targetExtension == NULL) {
  177. return STATUS_NO_SUCH_DEVICE;
  178. }
  179. }
  180. PCI_ASSERT(targetExtension != NULL);
  181. targetInterface->Size = sizeof( AGP_TARGET_BUS_INTERFACE_STANDARD );
  182. targetInterface->Version = AGPINTRF_VERSION;
  183. targetInterface->Context = targetExtension;
  184. targetInterface->InterfaceReference = agpintrf_Reference;
  185. targetInterface->InterfaceDereference = agpintrf_Dereference;
  186. targetInterface->CapabilityID = targetExtension->TargetAgpCapabilityId;
  187. targetInterface->SetBusData = PciWriteAgpConfig;
  188. targetInterface->GetBusData = PciReadAgpConfig;
  189. return STATUS_SUCCESS;
  190. }
  191. NTSTATUS
  192. agpintrf_Initializer(
  193. IN PPCI_ARBITER_INSTANCE Instance
  194. )
  195. /*++
  196. Routine Description:
  197. For bus interface, does nothing, shouldn't actually be called.
  198. Arguments:
  199. Instance Pointer to the PDO extension.
  200. Return Value:
  201. Returns the status of this operation.
  202. --*/
  203. {
  204. PCI_ASSERTMSG("PCI agpintrf_Initializer, unexpected call.", 0);
  205. return STATUS_UNSUCCESSFUL;
  206. }
  207. ULONG
  208. PciReadAgpConfig(
  209. IN PVOID Context,
  210. IN ULONG WhichSpace,
  211. IN PVOID Buffer,
  212. IN ULONG Offset,
  213. IN ULONG Length
  214. )
  215. /*++
  216. Routine Description:
  217. This function reads the PCI configuration space.
  218. Arguments:
  219. Context - Supplies a pointer to the interface context. This is actually
  220. the PDO for the root bus.
  221. Buffer - Supplies a pointer to where the data should be placed.
  222. Offset - Indicates the offset into the data where the reading should begin.
  223. Length - Indicates the count of bytes which should be read.
  224. Return Value:
  225. Returns the number of bytes read.
  226. --*/
  227. {
  228. PPCI_PDO_EXTENSION pdoExtension = (PPCI_PDO_EXTENSION)Context;
  229. ULONG lengthRead;
  230. ASSERT_PCI_PDO_EXTENSION(pdoExtension);
  231. PciReadDeviceSpace(pdoExtension,
  232. WhichSpace,
  233. Buffer,
  234. Offset,
  235. Length,
  236. &lengthRead
  237. );
  238. return lengthRead;
  239. }
  240. ULONG
  241. PciWriteAgpConfig(
  242. IN PVOID Context,
  243. IN ULONG WhichSpace,
  244. IN PVOID Buffer,
  245. IN ULONG Offset,
  246. IN ULONG Length
  247. )
  248. /*++
  249. Routine Description:
  250. This function writes the PCI configuration space.
  251. Arguments:
  252. Context - Supplies a pointer to the interface context. This is actually
  253. the PDO for the root bus.
  254. Buffer - Supplies a pointer to where the data to be written is.
  255. Offset - Indicates the offset into the data where the writing should begin.
  256. Length - Indicates the count of bytes which should be written.
  257. Return Value:
  258. Returns the number of bytes read.
  259. --*/
  260. {
  261. PPCI_PDO_EXTENSION pdoExtension = (PPCI_PDO_EXTENSION)Context;
  262. ULONG lengthWritten;
  263. ASSERT_PCI_PDO_EXTENSION(pdoExtension);
  264. PciWriteDeviceSpace(pdoExtension,
  265. WhichSpace,
  266. Buffer,
  267. Offset,
  268. Length,
  269. &lengthWritten
  270. );
  271. return lengthWritten;
  272. }