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.

1173 lines
29 KiB

  1. /*++
  2. Copyright (c) 1997-2000 Microsoft Corporation
  3. Module Name:
  4. cardbus.c
  5. Abstract:
  6. This module contains functions associated with enumerating
  7. PCI to Cardbus bridges (PCI Header Type 2).
  8. This module also contain Cardbus/Pci Private interface functions.
  9. Author:
  10. Peter Johnston (peterj) 09-Mar-1997
  11. Revision History:
  12. --*/
  13. #include "pcip.h"
  14. //
  15. // Prototypes for routines exposed only thru the "interface"
  16. // mechanism.
  17. //
  18. NTSTATUS
  19. pcicbintrf_AddCardBus(
  20. IN PDEVICE_OBJECT DeviceObject,
  21. IN OUT PVOID * DeviceContext
  22. );
  23. NTSTATUS
  24. pcicbintrf_DeleteCardBus(
  25. IN PVOID DeviceContext
  26. );
  27. NTSTATUS
  28. pcicbintrf_DispatchPnp(
  29. IN PVOID DeviceContext,
  30. IN PIRP Irp
  31. );
  32. NTSTATUS
  33. pcicbintrf_GetLocation(
  34. IN PDEVICE_OBJECT Pdo,
  35. OUT UCHAR *Bus,
  36. OUT UCHAR *DeviceNumber,
  37. OUT UCHAR *FunctionNumber,
  38. OUT BOOLEAN *OnDebugPath
  39. );
  40. NTSTATUS
  41. pcicbintrf_Constructor(
  42. PVOID DeviceExtension,
  43. PVOID PciInterface,
  44. PVOID InterfaceSpecificData,
  45. USHORT Version,
  46. USHORT Size,
  47. PINTERFACE InterfaceReturn
  48. );
  49. VOID
  50. pcicbintrf_Reference(
  51. IN PVOID Context
  52. );
  53. VOID
  54. pcicbintrf_Dereference(
  55. IN PVOID Context
  56. );
  57. NTSTATUS
  58. pcicbintrf_Initializer(
  59. IN PPCI_ARBITER_INSTANCE Instance
  60. );
  61. //
  62. // Define the PCI-Cardbus private interface.
  63. //
  64. PCI_INTERFACE PciCardbusPrivateInterface = {
  65. &GUID_PCI_CARDBUS_INTERFACE_PRIVATE, // InterfaceType
  66. sizeof(PCI_CARDBUS_INTERFACE_PRIVATE), // MinSize
  67. PCI_CB_INTRF_VERSION, // MinVersion
  68. PCI_CB_INTRF_VERSION, // MaxVersion
  69. PCIIF_PDO, // Flags
  70. 0, // ReferenceCount
  71. PciInterface_PciCb, // Signature
  72. pcicbintrf_Constructor, // Constructor
  73. pcicbintrf_Initializer // Instance Initializer
  74. };
  75. #ifdef ALLOC_PRAGMA
  76. //
  77. // Query Interface routines
  78. //
  79. #pragma alloc_text(PAGE, pcicbintrf_AddCardBus)
  80. #pragma alloc_text(PAGE, pcicbintrf_DeleteCardBus)
  81. #pragma alloc_text(PAGE, pcicbintrf_DispatchPnp)
  82. #pragma alloc_text(PAGE, pcicbintrf_Constructor)
  83. #pragma alloc_text(PAGE, pcicbintrf_Dereference)
  84. #pragma alloc_text(PAGE, pcicbintrf_Initializer)
  85. #pragma alloc_text(PAGE, pcicbintrf_Reference)
  86. //
  87. // Standard PCI enumeration routines
  88. //
  89. #pragma alloc_text(PAGE, Cardbus_MassageHeaderForLimitsDetermination)
  90. #pragma alloc_text(PAGE, Cardbus_RestoreCurrent)
  91. #pragma alloc_text(PAGE, Cardbus_SaveLimits)
  92. #pragma alloc_text(PAGE, Cardbus_SaveCurrentSettings)
  93. #pragma alloc_text(PAGE, Cardbus_GetAdditionalResourceDescriptors)
  94. #endif
  95. NTSTATUS
  96. pcicbintrf_AddCardBus(
  97. IN PDEVICE_OBJECT ControllerPdo,
  98. IN OUT PVOID *DeviceContext
  99. )
  100. {
  101. PPCI_PDO_EXTENSION controllerPdoExtension;
  102. PPCI_FDO_EXTENSION fdoExtension = NULL;
  103. PPCI_FDO_EXTENSION parent;
  104. NTSTATUS status;
  105. PciDebugPrint(
  106. PciDbgCardBus,
  107. "PCI - AddCardBus FDO for PDO %08x\n",
  108. ControllerPdo
  109. );
  110. //
  111. // DeviceObject is the PDO for this CardBus controller. Ensure
  112. // the PCI driver created it and knows what it is.
  113. //
  114. controllerPdoExtension = (PPCI_PDO_EXTENSION)ControllerPdo->DeviceExtension;
  115. ASSERT_PCI_PDO_EXTENSION(controllerPdoExtension);
  116. if ((controllerPdoExtension->BaseClass != PCI_CLASS_BRIDGE_DEV) ||
  117. (controllerPdoExtension->SubClass != PCI_SUBCLASS_BR_CARDBUS)) {
  118. ASSERT(controllerPdoExtension->BaseClass == PCI_CLASS_BRIDGE_DEV);
  119. ASSERT(controllerPdoExtension->SubClass == PCI_SUBCLASS_BR_CARDBUS);
  120. status = STATUS_INVALID_DEVICE_REQUEST;
  121. goto cleanup;
  122. }
  123. //
  124. // Sanity check.
  125. //
  126. parent = PCI_PARENT_FDOX(controllerPdoExtension);
  127. if ( (controllerPdoExtension->Dependent.type2.PrimaryBus !=
  128. parent->BaseBus)
  129. || (controllerPdoExtension->Dependent.type2.SecondaryBus <=
  130. parent->BaseBus)
  131. || (controllerPdoExtension->Dependent.type2.SubordinateBus <
  132. controllerPdoExtension->Dependent.type2.SecondaryBus)
  133. ) {
  134. PciDebugPrint(
  135. PciDbgAlways,
  136. "PCI Cardbus Bus Number configuration error (%02x>=%02x>%02x=%02x)\n",
  137. controllerPdoExtension->Dependent.type2.SubordinateBus,
  138. controllerPdoExtension->Dependent.type2.SecondaryBus,
  139. controllerPdoExtension->Dependent.type2.PrimaryBus,
  140. parent->BaseBus
  141. );
  142. ASSERT(controllerPdoExtension->Dependent.type2.PrimaryBus == parent->BaseBus);
  143. ASSERT(controllerPdoExtension->Dependent.type2.SecondaryBus > parent->BaseBus);
  144. ASSERT(controllerPdoExtension->Dependent.type2.SubordinateBus >=
  145. controllerPdoExtension->Dependent.type2.SecondaryBus);
  146. status = STATUS_INVALID_DEVICE_REQUEST;
  147. goto cleanup;
  148. }
  149. fdoExtension = ExAllocatePool(NonPagedPool, sizeof(PCI_FDO_EXTENSION));
  150. if (fdoExtension == NULL) {
  151. status = STATUS_INSUFFICIENT_RESOURCES;
  152. goto cleanup;
  153. }
  154. PciInitializeFdoExtensionCommonFields(
  155. fdoExtension,
  156. parent->FunctionalDeviceObject, // borrow parent's fdo
  157. ControllerPdo
  158. );
  159. //
  160. // We are probably only going to see QUERY_DEVICE_RELATIONS
  161. // Irps so initialize the FDO extension to a working state.
  162. //
  163. fdoExtension->PowerState.CurrentSystemState = PowerSystemWorking;
  164. fdoExtension->PowerState.CurrentDeviceState = PowerDeviceD0;
  165. fdoExtension->DeviceState = PciStarted;
  166. fdoExtension->TentativeNextState = PciStarted;
  167. fdoExtension->BaseBus = controllerPdoExtension->Dependent.type2.SecondaryBus;
  168. //
  169. // Copy the access methods from the root fdo and set
  170. // the root fdo back pointer.
  171. //
  172. fdoExtension->BusRootFdoExtension = parent->BusRootFdoExtension;
  173. //
  174. // Initialize arbiters for this FDO.
  175. //
  176. status = PciInitializeArbiters(fdoExtension);
  177. if (!NT_SUCCESS(status)) {
  178. goto cleanup;
  179. }
  180. //
  181. // Point the PDOextension to the new FDOextension (also indicates
  182. // the object is a bridge) and vice versa.
  183. //
  184. controllerPdoExtension->BridgeFdoExtension = fdoExtension;
  185. fdoExtension->ParentFdoExtension = parent;
  186. //
  187. // Flag that this FDO extension doesn't have a REAL FDO
  188. // associated with it.
  189. //
  190. fdoExtension->Fake = TRUE;
  191. //
  192. // Normaly we set the arbiter's ranges on a START_DEVICE IRP
  193. // but this has happened long before we get here so we must
  194. // regenerate the resource list.
  195. //
  196. {
  197. PCM_RESOURCE_LIST allocatedResources;
  198. status = PciQueryResources(
  199. controllerPdoExtension,
  200. &allocatedResources
  201. );
  202. if (NT_SUCCESS(status)) {
  203. //
  204. // Note: there's really not much that can be done if
  205. // the above failed,...
  206. //
  207. // Note: Find the first memory range, it should be length
  208. // 0x1000, we really don't want the arbiter using this so
  209. // nullify it.
  210. //
  211. PCM_FULL_RESOURCE_DESCRIPTOR full;
  212. PCM_PARTIAL_RESOURCE_LIST partial;
  213. PCM_PARTIAL_RESOURCE_DESCRIPTOR descriptor;
  214. ULONG count;
  215. ASSERT(allocatedResources != NULL);
  216. ASSERT(allocatedResources->Count == 1);
  217. full = allocatedResources->List; ASSERT(full);
  218. partial = &full->PartialResourceList; ASSERT(partial);
  219. descriptor = partial->PartialDescriptors; ASSERT(descriptor);
  220. count = partial->Count; ASSERT(count);
  221. while (count--) {
  222. if (descriptor->Type == CmResourceTypeMemory) {
  223. ASSERT(descriptor->u.Generic.Length == 4096);
  224. descriptor->Type = CmResourceTypeNull;
  225. break;
  226. }
  227. }
  228. status = PciInitializeArbiterRanges(fdoExtension, allocatedResources);
  229. ASSERT(NT_SUCCESS(status));
  230. ExFreePool(allocatedResources);
  231. }
  232. }
  233. //
  234. // If the PDO has resource requirements squirreled away somewhere,
  235. // cause them to be reevaluated.
  236. //
  237. PciInvalidateResourceInfoCache(controllerPdoExtension);
  238. //
  239. // Insert this Fdo in the list of PCI parent Fdos.
  240. //
  241. PciInsertEntryAtTail(&PciFdoExtensionListHead,
  242. &fdoExtension->List,
  243. &PciGlobalLock);
  244. //
  245. // Return the device context (really a pointer to our fake
  246. // FDO extension) that will be used on all subsequent calls
  247. // for this device.
  248. //
  249. *DeviceContext = fdoExtension;
  250. return STATUS_SUCCESS;
  251. cleanup:
  252. if (fdoExtension) {
  253. ExFreePool(fdoExtension);
  254. }
  255. return status;
  256. }
  257. NTSTATUS
  258. pcicbintrf_DeleteCardBus(
  259. IN PVOID DeviceContext
  260. )
  261. {
  262. PPCI_FDO_EXTENSION fdoExtension;
  263. PPCI_PDO_EXTENSION pdoExtension;
  264. fdoExtension = (PPCI_FDO_EXTENSION)DeviceContext;
  265. ASSERT_PCI_FDO_EXTENSION(fdoExtension);
  266. pdoExtension = fdoExtension->PhysicalDeviceObject->DeviceExtension;
  267. ASSERT_PCI_PDO_EXTENSION(pdoExtension);
  268. ASSERT(pdoExtension->BridgeFdoExtension == fdoExtension);
  269. pdoExtension->BridgeFdoExtension = NULL;
  270. PciDebugPrint(
  271. PciDbgCardBus,
  272. "PCI - DeleteCardBus (fake) FDO %08x for PDO %08x\n",
  273. fdoExtension,
  274. pdoExtension
  275. );
  276. //
  277. // Free the (fake) FDO extension we created to run this
  278. // bus with.
  279. //
  280. ASSERT(fdoExtension->ChildPdoList == NULL);
  281. PciRemoveEntryFromList(&PciFdoExtensionListHead,
  282. &fdoExtension->List,
  283. &PciGlobalLock);
  284. ExFreePool(fdoExtension);
  285. return STATUS_SUCCESS;
  286. }
  287. NTSTATUS
  288. pcicbintrf_DispatchPnp(
  289. IN PVOID DeviceContext,
  290. IN PIRP Irp
  291. )
  292. {
  293. PIO_STACK_LOCATION irpSp;
  294. NTSTATUS status;
  295. PPCI_FDO_EXTENSION fdoExtension;
  296. PVOID irpReturnVal;
  297. PAGED_CODE();
  298. fdoExtension = (PPCI_FDO_EXTENSION)DeviceContext;
  299. ASSERT_PCI_FDO_EXTENSION(fdoExtension);
  300. ASSERT(fdoExtension->Fake == TRUE);
  301. //
  302. // Get the stack location and take appropriate action based
  303. // on the minor function.
  304. //
  305. irpSp = IoGetCurrentIrpStackLocation(Irp);
  306. ASSERT(irpSp->MajorFunction == IRP_MJ_PNP);
  307. #if DBG
  308. PciDebugPrint(
  309. PciDbgCardBus,
  310. "PCI CardBus Dispatch PNP: FDO(%x, bus 0x%02x)<-%s\n",
  311. fdoExtension,
  312. fdoExtension->BaseBus,
  313. PciDebugPnpIrpTypeToText(irpSp->MinorFunction)
  314. );
  315. #endif
  316. return PciFdoIrpQueryDeviceRelations(
  317. Irp,
  318. irpSp,
  319. (PPCI_COMMON_EXTENSION) fdoExtension
  320. );
  321. }
  322. NTSTATUS
  323. pcicbintrf_GetLocation(
  324. IN PDEVICE_OBJECT Pdo,
  325. OUT UCHAR *Bus,
  326. OUT UCHAR *DeviceNumber,
  327. OUT UCHAR *FunctionNumber,
  328. OUT BOOLEAN *OnDebugPath
  329. )
  330. {
  331. PPCI_PDO_EXTENSION PdoExt = (PPCI_PDO_EXTENSION)Pdo->DeviceExtension;
  332. ASSERT(Bus);
  333. ASSERT(DeviceNumber);
  334. ASSERT(FunctionNumber);
  335. //
  336. // Verify that this PDO actually belongs to us.
  337. //
  338. if (!PdoExt) {
  339. return STATUS_NOT_FOUND;
  340. }
  341. //
  342. // Verify that it is actually a PDO.
  343. //
  344. if (PdoExt->ExtensionType != PciPdoExtensionType) {
  345. return STATUS_NOT_FOUND;
  346. }
  347. *Bus = (UCHAR) PCI_PARENT_FDOX(PdoExt)->BaseBus;
  348. *DeviceNumber = (UCHAR) PdoExt->Slot.u.bits.DeviceNumber;
  349. *FunctionNumber = (UCHAR) PdoExt->Slot.u.bits.FunctionNumber;
  350. *OnDebugPath = PdoExt->OnDebugPath;
  351. return STATUS_SUCCESS;
  352. }
  353. VOID
  354. pcicbintrf_Reference(
  355. IN PVOID Context
  356. )
  357. {
  358. }
  359. VOID
  360. pcicbintrf_Dereference(
  361. IN PVOID Context
  362. )
  363. {
  364. }
  365. NTSTATUS
  366. pcicbintrf_Constructor(
  367. PVOID DeviceExtension,
  368. PVOID PciInterface,
  369. PVOID InterfaceSpecificData,
  370. USHORT Version,
  371. USHORT Size,
  372. PINTERFACE InterfaceReturn
  373. )
  374. /*++
  375. Routine Description:
  376. Initialize the PCI_CARDBUS_INTERFACE_PRIVATE fields.
  377. Arguments:
  378. PciInterface Pointer to the PciInterface record for this
  379. interface type.
  380. InterfaceSpecificData
  381. A ULONG containing the resource type for which
  382. arbitration is required.
  383. InterfaceReturn
  384. Return Value:
  385. Status of this operation.
  386. --*/
  387. {
  388. PPCI_CARDBUS_INTERFACE_PRIVATE interface;
  389. interface = (PPCI_CARDBUS_INTERFACE_PRIVATE)InterfaceReturn;
  390. //
  391. // Standard interface stuff
  392. //
  393. interface->Size = sizeof(PCI_CARDBUS_INTERFACE_PRIVATE);
  394. interface->Version = PCI_CB_INTRF_VERSION;
  395. interface->Context = DeviceExtension;
  396. interface->InterfaceReference = pcicbintrf_Reference;
  397. interface->InterfaceDereference = pcicbintrf_Dereference;
  398. //
  399. // PCI-CardBus private
  400. //
  401. interface->DriverObject = PciDriverObject;
  402. interface->AddCardBus = pcicbintrf_AddCardBus;
  403. interface->DeleteCardBus = pcicbintrf_DeleteCardBus;
  404. interface->DispatchPnp = pcicbintrf_DispatchPnp;
  405. interface->GetLocation = pcicbintrf_GetLocation;
  406. return STATUS_SUCCESS;
  407. }
  408. NTSTATUS
  409. pcicbintrf_Initializer(
  410. IN PPCI_ARBITER_INSTANCE Instance
  411. )
  412. /*++
  413. Routine Description:
  414. For pci-cardbus interface, does nothing, shouldn't actually be called.
  415. Arguments:
  416. Instance Pointer to the PDO extension.
  417. Return Value:
  418. Returns the status of this operation.
  419. --*/
  420. {
  421. ASSERTMSG("PCI pcicbintrf_Initializer, unexpected call.", 0);
  422. return STATUS_UNSUCCESSFUL;
  423. }
  424. VOID
  425. Cardbus_MassageHeaderForLimitsDetermination(
  426. IN PPCI_CONFIGURABLE_OBJECT This
  427. )
  428. /*++
  429. Description:
  430. The configuration header for a cardbus bridge has one BAR, the
  431. SocketRegistersBaseAddress (which is handled in the same way as
  432. a normal device BAR (see device.c)) and four range descriptions,
  433. two for I/O and two for memory. Either or both of the memory
  434. ranges can be prefetchable.
  435. Arguments:
  436. This - Pointer to a PCI driver "configurable" object. This
  437. object contains configuration data for the function
  438. currently being configured.
  439. Return Value:
  440. The Working configuration has been modified so that all range
  441. fields have been set to their maximum possible values.
  442. The Current configuration has been modified such that writing it
  443. to the hardware will restore the hardware to it's current (disabled)
  444. state.
  445. --*/
  446. {
  447. PPCI_COMMON_CONFIG working = This->Working;
  448. PPCI_COMMON_CONFIG current = This->Current;
  449. ULONG index;
  450. ULONG mask;
  451. working->u.type2.SocketRegistersBaseAddress = 0xffffffff;
  452. for (index = 0; index < (PCI_TYPE2_ADDRESSES-1); index++) {
  453. working->u.type2.Range[index].Base = 0xffffffff;
  454. working->u.type2.Range[index].Limit = 0xffffffff;
  455. }
  456. This->PrivateData = This->Current->u.type2.SecondaryStatus;
  457. This->Current->u.type2.SecondaryStatus = 0;
  458. This->Working->u.type2.SecondaryStatus = 0;
  459. //
  460. // For cardbus, disregard whatever the BIOS set as resource
  461. // windows, PnP will assign new windows as appropriate.
  462. //
  463. if (!This->PdoExtension->OnDebugPath) {
  464. mask = 0xfffff000;
  465. for (index = 0; index < (PCI_TYPE2_ADDRESSES-1); index++) {
  466. current->u.type2.Range[index].Base = mask;
  467. current->u.type2.Range[index].Limit = 0;
  468. if (index == 2) {
  469. //
  470. // Switch to IO (first two are memory).
  471. //
  472. mask = 0xfffffffc;
  473. }
  474. }
  475. }
  476. }
  477. VOID
  478. Cardbus_RestoreCurrent(
  479. IN PPCI_CONFIGURABLE_OBJECT This
  480. )
  481. /*++
  482. Description:
  483. Restore any type specific fields in the original copy of config
  484. space. In the case of Cardbus bridges, the secondary status field.
  485. Arguments:
  486. This - Pointer to a PCI driver "configurable" object. This
  487. object contains configuration data for the function
  488. currently being configured.
  489. Return Value:
  490. None.
  491. --*/
  492. {
  493. This->Current->u.type2.SecondaryStatus = (USHORT)(This->PrivateData);
  494. }
  495. VOID
  496. Cardbus_SaveLimits(
  497. IN PPCI_CONFIGURABLE_OBJECT This
  498. )
  499. /*++
  500. Description:
  501. Fill in the Limit structure with a IO_RESOURCE_REQUIREMENT
  502. for each implemented BAR.
  503. Arguments:
  504. This - Pointer to a PCI driver "configurable" object. This
  505. object contains configuration data for the function
  506. currently being configured.
  507. Return Value:
  508. None.
  509. --*/
  510. {
  511. BOOLEAN DbgChk64Bit;
  512. ULONG index;
  513. PIO_RESOURCE_DESCRIPTOR descriptor;
  514. PPCI_COMMON_CONFIG working = This->Working;
  515. ULONG endOffset;
  516. ULONG base;
  517. ULONG limit;
  518. TYPE2EXTRAS type2extras;
  519. ULONG tempLegacyModeBaseAddress;
  520. NTSTATUS status;
  521. descriptor = This->PdoExtension->Resources->Limit;
  522. DbgChk64Bit = PciCreateIoDescriptorFromBarLimit(
  523. descriptor,
  524. &working->u.type2.SocketRegistersBaseAddress,
  525. FALSE);
  526. ASSERT(!DbgChk64Bit);
  527. descriptor++;
  528. for (index = 0;
  529. index < (PCI_TYPE2_ADDRESSES-1);
  530. index++, descriptor++) {
  531. if (index < 2) {
  532. //
  533. // First two are Memory
  534. //
  535. endOffset = 0xfff;
  536. descriptor->Type = CmResourceTypeMemory;
  537. descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
  538. } else {
  539. //
  540. // Next two are IO
  541. //
  542. if ((working->u.type2.Range[index].Base & 0x3) == 0x0) {
  543. //
  544. // Only the lower 16 bits are implemented.
  545. //
  546. ASSERT((working->u.type2.Range[index].Limit & 0x3) == 0x0);
  547. working->u.type2.Range[index].Base &= 0xffff;
  548. working->u.type2.Range[index].Limit &= 0xffff;
  549. }
  550. endOffset = 0x3;
  551. descriptor->Type = CmResourceTypePort;
  552. descriptor->Flags = CM_RESOURCE_PORT_IO
  553. | CM_RESOURCE_PORT_POSITIVE_DECODE
  554. | CM_RESOURCE_PORT_WINDOW_DECODE;
  555. }
  556. base = working->u.type2.Range[index].Base & ~endOffset;
  557. limit = working->u.type2.Range[index].Limit | endOffset;
  558. //
  559. // Is this range in use?
  560. //
  561. if ((base != 0) && (base < limit)) {
  562. //
  563. // Yep.
  564. //
  565. descriptor->u.Generic.MinimumAddress.QuadPart = 0;
  566. descriptor->u.Generic.MaximumAddress.QuadPart = limit;
  567. descriptor->u.Generic.Alignment = endOffset + 1;
  568. //
  569. // Length is meaningless here, report zero.
  570. //
  571. descriptor->u.Generic.Length = 0;
  572. } else {
  573. //
  574. // Not in use, don't report it.
  575. //
  576. descriptor->Type = CmResourceTypeNull;
  577. }
  578. }
  579. //
  580. // Cardbus has an additional base address register in config
  581. // space beyond the common header. Also there are the subsystem
  582. // ID and subsystem vendor ID so get those while we're there.
  583. //
  584. PciReadDeviceConfig(This->PdoExtension,
  585. &type2extras,
  586. FIELD_OFFSET(PCI_COMMON_CONFIG,
  587. DeviceSpecific),
  588. sizeof(type2extras));
  589. This->PdoExtension->SubsystemVendorId = type2extras.SubVendorID;
  590. This->PdoExtension->SubsystemId = type2extras.SubSystemID;
  591. //
  592. // CardBus always wants a 4K apperture in the first memory BAR.
  593. // Note that when saving the original settings we discarded
  594. // whatever was there already.
  595. //
  596. ASSERT(This->PdoExtension->Resources->Limit[1].u.Generic.Length == 0);
  597. This->PdoExtension->Resources->Limit[1].u.Generic.Length = 4096;
  598. }
  599. VOID
  600. Cardbus_SaveCurrentSettings(
  601. IN PPCI_CONFIGURABLE_OBJECT This
  602. )
  603. /*++
  604. Description:
  605. Fill in the Current array in the PDO extension with the current
  606. settings for each implemented BAR.
  607. Also, fill in the PDO Extension's Dependent structure.
  608. Arguments:
  609. This - Pointer to a PCI driver "configurable" object. This
  610. object contains configuration data for the function
  611. currently being configured.
  612. Return Value:
  613. None.
  614. --*/
  615. {
  616. ULONG index;
  617. PCM_PARTIAL_RESOURCE_DESCRIPTOR partial;
  618. PIO_RESOURCE_DESCRIPTOR ioResourceDescriptor;
  619. PPCI_COMMON_CONFIG current = This->Current;
  620. ULONG endOffset;
  621. ULONG base;
  622. ULONG limit;
  623. partial = This->PdoExtension->Resources->Current;
  624. ioResourceDescriptor = This->PdoExtension->Resources->Limit;
  625. for (index = 0;
  626. index < PCI_TYPE2_RANGE_COUNT;
  627. index++, partial++, ioResourceDescriptor++) {
  628. partial->Type = ioResourceDescriptor->Type;
  629. if (partial->Type == CmResourceTypeNull) {
  630. //
  631. // This entry is not implemented (or permanently disabled)
  632. // no further processing required.
  633. //
  634. continue;
  635. }
  636. partial->Flags = ioResourceDescriptor->Flags;
  637. partial->ShareDisposition = ioResourceDescriptor->ShareDisposition;
  638. //
  639. // The first and last entries are in PCI Base Address Register
  640. // form.
  641. //
  642. if (index == 0) {
  643. partial->u.Generic.Length = ioResourceDescriptor->u.Generic.Length;
  644. base = current->u.type2.SocketRegistersBaseAddress;
  645. base &= ~(partial->u.Generic.Length - 1);
  646. partial->u.Generic.Start.QuadPart = base;
  647. continue;
  648. } else if (index == (PCI_TYPE2_RANGE_COUNT - 1)) {
  649. //
  650. // We don't use LegacyModeBaseAddress any more its always set to 0
  651. //
  652. continue;
  653. }
  654. //
  655. // Following entries are in the form of ranges.
  656. //
  657. base = current->u.type2.Range[index-1].Base;
  658. limit = current->u.type2.Range[index-1].Limit;
  659. if (index < 3) {
  660. //
  661. // after the BAR come two memory ranges.
  662. //
  663. endOffset = 0xfff;
  664. } else {
  665. //
  666. // Next two are IO
  667. //
  668. if ((current->u.type2.Range[index].Base & 0x3) == 0x0) {
  669. //
  670. // Only the lower 16 bits are implemented.
  671. //
  672. base &= 0xffff;
  673. limit &= 0xffff;
  674. }
  675. endOffset = 0x3;
  676. }
  677. base &= ~endOffset;
  678. limit |= endOffset;
  679. //
  680. // Is this range in use?
  681. //
  682. if (base && (base < limit)) {
  683. //
  684. // Yep.
  685. //
  686. partial->u.Generic.Start.QuadPart = base;
  687. partial->u.Generic.Length = limit - base + 1;
  688. } else {
  689. //
  690. // Not in use, don't report it.
  691. //
  692. partial->Type = CmResourceTypeNull;
  693. }
  694. }
  695. //
  696. // Always clear the ISA bit on a cardbus bridge
  697. //
  698. This->PdoExtension->Dependent.type2.IsaBitSet = FALSE;
  699. //
  700. // If any of the MEM0_PREFETCH, MEM1_PREFETCH or ISA bits are set in brigde
  701. // control register force us to update the hardware so we will clear them
  702. // in ChangeResourceSettings
  703. //
  704. if (current->u.type2.BridgeControl & (PCI_ENABLE_CARDBUS_MEM0_PREFETCH
  705. | PCI_ENABLE_CARDBUS_MEM1_PREFETCH
  706. | PCI_ENABLE_BRIDGE_ISA)) {
  707. This->PdoExtension->UpdateHardware = TRUE;
  708. }
  709. //
  710. // Save the bridge's PCI bus #'s
  711. //
  712. This->PdoExtension->Dependent.type2.PrimaryBus =
  713. current->u.type2.PrimaryBus;
  714. This->PdoExtension->Dependent.type2.SecondaryBus =
  715. current->u.type2.SecondaryBus;
  716. This->PdoExtension->Dependent.type2.SubordinateBus =
  717. current->u.type2.SubordinateBus;
  718. }
  719. VOID
  720. Cardbus_ChangeResourceSettings(
  721. IN PPCI_PDO_EXTENSION PdoExtension,
  722. IN PPCI_COMMON_CONFIG CommonConfig
  723. )
  724. {
  725. ULONG index;
  726. PCM_PARTIAL_RESOURCE_DESCRIPTOR partial;
  727. PIO_RESOURCE_DESCRIPTOR ioResourceDescriptor;
  728. ULONG lowPart;
  729. ULONG length;
  730. struct _type2_range {
  731. ULONG Base;
  732. ULONG Limit;
  733. } *range;
  734. #if DBG
  735. PHYSICAL_ADDRESS upperBound;
  736. ULONG align;
  737. #endif
  738. //
  739. // Close the bridge windows and only open them is appropriate resources
  740. // have been assigned
  741. //
  742. for (index = 0; index < PCI_TYPE2_ADDRESSES-1; index++) {
  743. CommonConfig->u.type2.Range[index].Base = 0xffffffff;
  744. CommonConfig->u.type2.Range[index].Limit = 0x0;
  745. }
  746. if (PdoExtension->Resources) {
  747. partial = PdoExtension->Resources->Current;
  748. ioResourceDescriptor = PdoExtension->Resources->Limit;
  749. for (index = 0;
  750. index < PCI_TYPE2_RANGE_COUNT;
  751. index++, partial++, ioResourceDescriptor++) {
  752. //
  753. // If this entry is not implemented, skip.
  754. //
  755. if (partial->Type == CmResourceTypeNull) {
  756. continue;
  757. }
  758. ASSERT(partial->Type == ioResourceDescriptor->Type);
  759. //
  760. // Cardbus supports 32 (or 16) bit addresses only.
  761. //
  762. lowPart = partial->u.Generic.Start.LowPart;
  763. ASSERT(partial->u.Generic.Start.HighPart == 0);
  764. //
  765. // Type 2 headers
  766. //
  767. // entry cfg offset size what
  768. //
  769. // 0 10 4 CB Socket reg/EXCA BAR
  770. // 1 1c 8 Mem base/limit (32 bits each)
  771. // 2 24 8 "" "" 2nd aperture
  772. // 3 2c 8(*) IO base/limit
  773. // 4 34 8(*) "" "" 2nd aperture
  774. // 5 40 4(**) 16 bit PC card legacy mode BAR
  775. //
  776. // * Optionally 16 or 32 bits.
  777. // ** Optional. Not supported at present (Memphis says they don't
  778. // support it at all). Peterj 11/5/97.
  779. //
  780. if (index == 0) {
  781. ASSERT(partial->Type == CmResourceTypeMemory);
  782. CommonConfig->u.type2.SocketRegistersBaseAddress = lowPart;
  783. } else if (index == (PCI_TYPE2_RANGE_COUNT-1)) {
  784. //
  785. // We don't use LegacyModeBaseAddress any more its always set to 0
  786. //
  787. ASSERT(partial->Type = CmResourceTypeNull);
  788. continue;
  789. } else {
  790. //
  791. // It's one of the range/limit pairs.
  792. //
  793. range =
  794. (struct _type2_range *)&CommonConfig->u.type2.Range[index-1];
  795. length = partial->u.Generic.Length;
  796. #if DBG
  797. //
  798. // Verify type and upper bound.
  799. //
  800. upperBound.QuadPart = lowPart + (partial->u.Generic.Length - 1);
  801. ASSERT(upperBound.HighPart == 0);
  802. if (index < 3) {
  803. //
  804. // Memory ranges, 4KB alignment.
  805. //
  806. align = 0xfff;
  807. } else {
  808. //
  809. // IO ranges, verify type, 4 Byte alignment and
  810. // upperbound if 16 bit only.
  811. //
  812. align = 0x3;
  813. if ((range->Base & 0x3) == 0) {
  814. //
  815. // 16 bit
  816. //
  817. ASSERT((upperBound.LowPart & 0xffff0000) == 0);
  818. }
  819. }
  820. ASSERT((lowPart & align) == 0);
  821. ASSERT(((length & align) == 0) && (length > align));
  822. #endif
  823. range->Base = lowPart;
  824. range->Limit = lowPart + (length - 1);
  825. continue;
  826. }
  827. }
  828. }
  829. //
  830. // Restore the bridge's PCI bus #'s
  831. //
  832. CommonConfig->u.type2.PrimaryBus = PdoExtension->Dependent.type2.PrimaryBus;
  833. CommonConfig->u.type2.SecondaryBus = PdoExtension->Dependent.type2.SecondaryBus;
  834. CommonConfig->u.type2.SubordinateBus = PdoExtension->Dependent.type2.SubordinateBus;
  835. //
  836. // Always clear the MEM0_PREFETCH, MEM1_PREFETCH and ISA enables
  837. // for a cardbus contoller as we don't support these.
  838. //
  839. ASSERT(!PdoExtension->Dependent.type2.IsaBitSet);
  840. CommonConfig->u.type2.BridgeControl &= ~(PCI_ENABLE_CARDBUS_MEM0_PREFETCH
  841. | PCI_ENABLE_CARDBUS_MEM1_PREFETCH
  842. | PCI_ENABLE_BRIDGE_ISA);
  843. //
  844. // Set the bridge control register bits we might have changes
  845. //
  846. if (PdoExtension->Dependent.type2.VgaBitSet) {
  847. CommonConfig->u.type2.BridgeControl |= PCI_ENABLE_BRIDGE_VGA;
  848. }
  849. }
  850. VOID
  851. Cardbus_GetAdditionalResourceDescriptors(
  852. IN PPCI_PDO_EXTENSION PdoExtension,
  853. IN PPCI_COMMON_CONFIG CommonConfig,
  854. IN PIO_RESOURCE_DESCRIPTOR Resource
  855. )
  856. {
  857. //
  858. // For the moment, do nothing, need to add the same sort of
  859. // support as is in pci-pci bridges.
  860. //
  861. return;
  862. }
  863. NTSTATUS
  864. Cardbus_ResetDevice(
  865. IN PPCI_PDO_EXTENSION PdoExtension,
  866. IN PPCI_COMMON_CONFIG CommonConfig
  867. )
  868. {
  869. //
  870. // While you might logically expect to find code in this
  871. // function, RavisP assures me that the cardbus driver
  872. // handles resets correctly and the PCI driver doesn't
  873. // need to touch it.
  874. //
  875. return STATUS_SUCCESS;
  876. }