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.

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