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.

1224 lines
30 KiB

  1. /*++
  2. Copyright (c) 1999-2000 Microsoft Corporation
  3. Module Name:
  4. device.c
  5. Abstract:
  6. This module contains functions for handling Read/Write to Config Space.
  7. Author:
  8. Nicholas Owens (Nichow)
  9. Revision History:
  10. BrandonA - Feb. 2000 - Updated to support Read/Write from PCI_COMMON_CONFIG instead of private headers.
  11. --*/
  12. #include "pch.h"
  13. BOOLEAN
  14. SoftPCIValidSlot(
  15. IN PSOFTPCI_DEVICE FirstDevice,
  16. IN PSOFTPCI_SLOT Slot
  17. );
  18. VOID
  19. WriteByte(
  20. IN PSOFTPCI_DEVICE device,
  21. IN ULONG Register,
  22. IN UCHAR Data
  23. );
  24. VOID
  25. WriteByte(
  26. IN PSOFTPCI_DEVICE Device,
  27. IN ULONG Register,
  28. IN UCHAR Data
  29. )
  30. {
  31. PSOFTPCI_DEVICE child;
  32. PUCHAR config;
  33. PUCHAR mask;
  34. ASSERT(Register < sizeof(PCI_COMMON_CONFIG));
  35. config = (PUCHAR)&Device->Config.Current;
  36. mask = (PUCHAR)&Device->Config.Mask;
  37. if (Register < sizeof(PCI_COMMON_CONFIG)) {
  38. config += Register;
  39. mask += Register;
  40. //
  41. // If we are writing to a SoftPCI-PCI Bridge lets check and see it
  42. // it happens to be the SecondaryBusNumber Register.
  43. //
  44. if (IS_BRIDGE(Device)) {
  45. if (Register == (UCHAR) FIELD_OFFSET(PCI_COMMON_CONFIG, u.type1.SecondaryBus)) {
  46. SoftPCIDbgPrint(
  47. SOFTPCI_BUS_NUM,
  48. "SOFTPCI: Assigning DEV_%02x&FUN_%02x Bus #%02x\n",
  49. Device->Slot.Device,
  50. Device->Slot.Function,
  51. Data
  52. );
  53. //
  54. // If we have children update thier bus numbers as well.
  55. //
  56. child = Device->Child;
  57. while(child){
  58. child->Bus = Data;
  59. child = child->Sibling;
  60. }
  61. }
  62. }
  63. //
  64. // Preserve the read-only bits first
  65. //
  66. *config &= ~(*mask);
  67. //
  68. // Verify the bits trying to be written are allowed.
  69. //
  70. Data &= *mask;
  71. //
  72. // Update the register with the new value if any
  73. //
  74. *config |= Data;
  75. }
  76. }
  77. NTSTATUS
  78. SoftPCIAddNewDevice(
  79. IN PSOFTPCI_DEVICE NewDevice
  80. )
  81. /*++
  82. Routine Description:
  83. This function is called by SoftPciAddDeviceIoctl when and ADDDEVICE IOCTL is send
  84. from our user mode app. Here we create a new SoftPCI device and attach it to our
  85. tree.
  86. Arguments:
  87. DeviceExtension - Device Extension for our BUS 0 (or first root bus) Filter DO.
  88. NewDevice - SoftPCI device to create
  89. Return Value:
  90. NT status.
  91. --*/
  92. {
  93. NTSTATUS status;
  94. PSOFTPCI_DEVICE device;
  95. PSOFTPCI_DEVICE currentDevice;
  96. KIRQL irql;
  97. status = STATUS_UNSUCCESSFUL;
  98. //
  99. // Allocate some NonPagedPool for our new device
  100. //
  101. device = ExAllocatePool(NonPagedPool, sizeof(SOFTPCI_DEVICE));
  102. if (device) {
  103. RtlZeroMemory(device, sizeof(SOFTPCI_DEVICE));
  104. RtlCopyMemory(device, NewDevice, sizeof(SOFTPCI_DEVICE));
  105. SoftPCIDbgPrint(
  106. SOFTPCI_INFO,
  107. "SOFTPCI: AddNewDevice - New Device! BUS_%02x&DEV_%02x&FUN_%02x (%p)\n",
  108. device->Bus,
  109. device->Slot.Device,
  110. device->Slot.Function,
  111. device
  112. );
  113. //
  114. // Grab our lock
  115. //
  116. SoftPCILockDeviceTree(&irql);
  117. currentDevice = SoftPciTree.RootDevice;
  118. if (currentDevice == NULL) {
  119. //
  120. // We found our first root bus
  121. //
  122. SoftPciTree.RootDevice = device;
  123. SoftPciTree.DeviceCount++;
  124. status = STATUS_SUCCESS;
  125. } else {
  126. //
  127. // Not on bus zero (or fist root bus) so lets see if we can find it.
  128. //
  129. while(currentDevice){
  130. if (IS_ROOTBUS(device)) {
  131. SoftPCIDbgPrint(
  132. SOFTPCI_INFO,
  133. "SOFTPCI: AddNewDevice - New Device is a PlaceHolder device\n"
  134. );
  135. //
  136. // A root bus.
  137. //
  138. while (currentDevice->Sibling) {
  139. currentDevice = currentDevice->Sibling;
  140. }
  141. currentDevice->Sibling = device;
  142. SoftPciTree.DeviceCount++;
  143. status = STATUS_SUCCESS;
  144. break;
  145. }
  146. //
  147. // Don't forget that we pretend that each root bus we have are bridges....
  148. //
  149. if (IS_BRIDGE(currentDevice) &&
  150. currentDevice->Config.Current.u.type1.SecondaryBus == device->Bus) {
  151. SoftPCIDbgPrint(
  152. SOFTPCI_INFO,
  153. "SOFTPCI: AddNewDevice - New Device is on bus 0x%02x\n",
  154. currentDevice->Config.Current.u.type1.SecondaryBus
  155. );
  156. //
  157. // Found it. Update the tree.
  158. //
  159. device->Sibling = currentDevice->Child;
  160. currentDevice->Child = device;
  161. device->Parent = currentDevice;
  162. device->Child = NULL;
  163. SoftPciTree.DeviceCount++;
  164. status = STATUS_SUCCESS;
  165. break;
  166. }else if (IS_BRIDGE(currentDevice) &&
  167. device->Bus >= currentDevice->Config.Current.u.type1.SecondaryBus &&
  168. device->Bus <= currentDevice->Config.Current.u.type1.SubordinateBus) {
  169. if (currentDevice->Child) {
  170. currentDevice = currentDevice->Child;
  171. } else {
  172. //
  173. // There is no device to attach too.
  174. //
  175. SoftPCIDbgPrint(
  176. SOFTPCI_ERROR,
  177. "SOFTPCI: AddNewDevice - Failed to find a device to attach to!\n"
  178. );
  179. }
  180. } else {
  181. currentDevice = currentDevice->Sibling;
  182. }
  183. }
  184. }
  185. SoftPCIUnlockDeviceTree(irql);
  186. } else {
  187. status = STATUS_INSUFFICIENT_RESOURCES;
  188. }
  189. if (!NT_SUCCESS(status)) {
  190. SoftPCIDbgPrint(
  191. SOFTPCI_ERROR,
  192. "SOFTPCI: AddNewDevice - Failed to attach device! status = (0x%x)\n",
  193. status
  194. );
  195. ExFreePool(device);
  196. }else{
  197. //
  198. // Cause a rescan of PCI if this is a new fake device
  199. //
  200. if (!device->Config.PlaceHolder) {
  201. SoftPCIEnumerateTree();
  202. }
  203. }
  204. return status;
  205. }
  206. NTSTATUS
  207. SoftPCIAddNewDeviceByPath(
  208. IN PSOFTPCI_SCRIPT_DEVICE ScriptDevice
  209. )
  210. /*++
  211. Routine Description:
  212. This function is called by SoftPciAddDeviceIoctl when to add a device via
  213. a specified PCI device path. Here we create a new SoftPCI device and attach
  214. it to our tree.
  215. Arguments:
  216. ScriptDevice - Contains the device and path used for installing the device
  217. Return Value:
  218. NT status.
  219. --*/
  220. {
  221. PSOFTPCI_DEVICE parentDevice;
  222. PSOFTPCI_DEVICE currentDevice;
  223. PSOFTPCI_DEVICE newDevice;
  224. parentDevice = SoftPCIFindDeviceByPath((PWCHAR)&ScriptDevice->ParentPath);
  225. if (parentDevice) {
  226. SoftPCIDbgPrint(
  227. SOFTPCI_ADD_DEVICE,
  228. "SOFTPCI: AddNewDeviceByPath - Found parent device! (%p)\n",
  229. parentDevice
  230. );
  231. //
  232. // Found our parent. Allocate a new child
  233. //
  234. newDevice = ExAllocatePool(NonPagedPool, sizeof(SOFTPCI_DEVICE));
  235. if (!newDevice) {
  236. return STATUS_INSUFFICIENT_RESOURCES;
  237. }
  238. RtlCopyMemory(newDevice, &ScriptDevice->SoftPciDevice, sizeof(SOFTPCI_DEVICE));
  239. newDevice->Parent = parentDevice;
  240. newDevice->Bus = parentDevice->Config.Current.u.type1.SecondaryBus;
  241. if (parentDevice->Child) {
  242. currentDevice = parentDevice->Child;
  243. if (SoftPCIRealHardwarePresent(newDevice) ||
  244. !SoftPCIValidSlot(currentDevice, &newDevice->Slot)) {
  245. //
  246. // Either real hardware is present or we already have a fake one.
  247. //
  248. SoftPCIDbgPrint(
  249. SOFTPCI_ADD_DEVICE,
  250. "SOFTPCI: AddNewDeviceByPath - Cannot add device at specified Slot (%04x)!\n",
  251. newDevice->Slot.AsUSHORT
  252. );
  253. ExFreePool(newDevice);
  254. return STATUS_ACCESS_DENIED;
  255. }
  256. while (currentDevice->Sibling) {
  257. currentDevice = currentDevice->Sibling;
  258. }
  259. currentDevice->Sibling = newDevice;
  260. }else{
  261. parentDevice->Child = newDevice;
  262. }
  263. SoftPciTree.DeviceCount++;
  264. //
  265. // New device is in our tree, re-enum
  266. //
  267. SoftPCIEnumerateTree();
  268. }else{
  269. return STATUS_NO_SUCH_DEVICE;
  270. }
  271. return STATUS_SUCCESS;
  272. }
  273. PSOFTPCI_DEVICE
  274. SoftPCIFindDevice(
  275. IN UCHAR Bus,
  276. IN USHORT Slot,
  277. OUT PSOFTPCI_DEVICE *PreviousSibling OPTIONAL,
  278. IN BOOLEAN ReturnAll
  279. )
  280. /*++
  281. Routine Description:
  282. This routine searches our tree of SoftPci devices looking for the specified device.
  283. It requires that SoftPCILockDeviceTree() has been previously called to
  284. lock the device tree.
  285. Arguments:
  286. Bus - Bus number of device we are searching for
  287. Device - Device number of device we are searching for
  288. Function - Function of device we are searching for
  289. Return Value:
  290. Returns the softpci device we are looking for. NULL otherwise.
  291. --*/
  292. {
  293. PSOFTPCI_DEVICE currentDevice;
  294. PSOFTPCI_DEVICE previousDevice;
  295. PSOFTPCI_DEVICE deviceFound;
  296. SOFTPCI_SLOT slot;
  297. currentDevice = SoftPciTree.RootDevice;
  298. previousDevice = SoftPciTree.RootDevice;;
  299. deviceFound = NULL;
  300. slot.AsUSHORT = Slot;
  301. SoftPCIDbgPrint(
  302. SOFTPCI_FIND_DEVICE,
  303. "SOFTPCI: FindDevice - Searching for BUS_%02x&DEV_%02x&FUN_%02x\n",
  304. Bus,
  305. slot.Device,
  306. slot.Function
  307. );
  308. while (currentDevice) {
  309. SoftPCIDbgPrint(
  310. SOFTPCI_FIND_DEVICE,
  311. "SOFTPCI: FindDevice - Does %02x.%02x.%02x = %02x.%02x.%02x ?\n",
  312. Bus, slot.Device, slot.Function,
  313. currentDevice->Bus,
  314. currentDevice->Slot.Device,
  315. currentDevice->Slot.Function
  316. );
  317. if (currentDevice->Bus == Bus &&
  318. currentDevice->Slot.AsUSHORT == Slot) {
  319. //
  320. // Found it! Only return it if caller specified ReturnAll
  321. //
  322. if (!currentDevice->Config.PlaceHolder || ReturnAll) {
  323. if (PreviousSibling) {
  324. *PreviousSibling = previousDevice;
  325. }
  326. SoftPCIDbgPrint(
  327. SOFTPCI_FIND_DEVICE,
  328. "SOFTPCI: FindDevice - Found Device! (0x%p)\n",
  329. currentDevice);
  330. deviceFound = currentDevice;
  331. }
  332. break;
  333. }else if ((IS_BRIDGE(currentDevice)) &&
  334. (Bus >= currentDevice->Config.Current.u.type1.SecondaryBus) &&
  335. (Bus <= currentDevice->Config.Current.u.type1.SubordinateBus)) {
  336. SoftPCIDbgPrint(
  337. SOFTPCI_FIND_DEVICE,
  338. "SOFTPCI: FindDevice - 0x%p exposes bus %02x-%02x\n",
  339. currentDevice,
  340. currentDevice->Config.Current.u.type1.SecondaryBus,
  341. currentDevice->Config.Current.u.type1.SubordinateBus
  342. );
  343. if (!(currentDevice->Config.PlaceHolder) &&
  344. !(currentDevice->Config.Current.u.type1.SecondaryBus) &&
  345. !(currentDevice->Config.Current.u.type1.SubordinateBus)){
  346. //
  347. // We have a bridge but it hasnt been given its bus numbers
  348. // yet. Therefore cant have children.
  349. //
  350. SoftPCIDbgPrint(
  351. SOFTPCI_FIND_DEVICE,
  352. "SOFTPCI: FindDevice - Skipping unconfigured bridge (0x%p)\n",
  353. currentDevice
  354. );
  355. previousDevice = currentDevice;
  356. currentDevice = currentDevice->Sibling;
  357. }else{
  358. //
  359. // Our bus is behind this bridge. Keep looking
  360. //
  361. previousDevice = NULL;
  362. currentDevice = currentDevice->Child;
  363. }
  364. }else{
  365. //
  366. // Not a bridge, check our sibling
  367. //
  368. previousDevice = currentDevice;
  369. currentDevice = currentDevice->Sibling;
  370. }
  371. }
  372. return deviceFound;
  373. }
  374. PSOFTPCI_DEVICE
  375. SoftPCIFindDeviceByPath(
  376. IN PWCHAR PciPath
  377. )
  378. /*++
  379. Routine Description:
  380. This function will take a given PCIPATH and return the device located at that path.
  381. Arguments:
  382. PciPath - Path to device. Syntax is FFXX\DEVFUNC\DEVFUNC\....
  383. Return Value:
  384. SoftPCI device located at path
  385. --*/
  386. {
  387. PWCHAR nextSlotStart;
  388. SOFTPCI_SLOT currentSlot;
  389. PSOFTPCI_DEVICE currentDevice;
  390. currentSlot.AsUSHORT = 0;
  391. currentDevice = SoftPciTree.RootDevice;
  392. nextSlotStart = PciPath;
  393. while (nextSlotStart) {
  394. nextSlotStart = SoftPCIGetNextSlotFromPath(nextSlotStart, &currentSlot);
  395. SoftPCIDbgPrint(
  396. SOFTPCI_FIND_DEVICE,
  397. "SOFTPCI: FindDeviceByPath - nextSlotStart = %ws\n",
  398. nextSlotStart
  399. );
  400. while(currentDevice){
  401. SoftPCIDbgPrint(
  402. SOFTPCI_FIND_DEVICE,
  403. "SOFTPCI: FindDeviceByPath - currentDevice.Slot = %04x, currentSlot.Slot = %04x\n",
  404. currentDevice->Slot.AsUSHORT,
  405. currentSlot.AsUSHORT
  406. );
  407. if (currentDevice->Slot.AsUSHORT == currentSlot.AsUSHORT) {
  408. //
  409. // This device is in our path
  410. //
  411. if (nextSlotStart &&
  412. (!(IS_BRIDGE(currentDevice)))){
  413. //
  414. // This device is in our path but since it isnt a bridge it
  415. // cannot have children!
  416. //
  417. SoftPCIDbgPrint(
  418. SOFTPCI_FIND_DEVICE,
  419. "SOFTPCI: FindDeviceByPath - ERROR! Path contains a parent that isnt a bridge!\n"
  420. );
  421. return NULL;
  422. }
  423. if (currentDevice->Child && nextSlotStart) {
  424. currentDevice = currentDevice->Child;
  425. }
  426. break;
  427. }else{
  428. //
  429. // Not in our path, look at our next sibling
  430. //
  431. currentDevice = currentDevice->Sibling;
  432. }
  433. }
  434. }
  435. #if 0
  436. if (currentDevice) {
  437. //
  438. // looks like we found it
  439. //
  440. *TargetDevice = currentDevice;
  441. return STATUS_SUCCESS;
  442. }
  443. #endif
  444. return currentDevice;
  445. }
  446. BOOLEAN
  447. SoftPCIRealHardwarePresent(
  448. IN PSOFTPCI_DEVICE Device
  449. )
  450. /*++
  451. Routine Description:
  452. This function does a quick check to see if real hardware exists at the bus/slot
  453. specified in the provided SOFTPCI_DEVICE
  454. Arguments:
  455. Device - Contains the Bus / Slot we want to check for
  456. Return Value:
  457. TRUE if real hardware is present
  458. --*/
  459. {
  460. ULONG bytesRead;
  461. USHORT vendorID;
  462. PCI_SLOT_NUMBER slot;
  463. PSOFTPCI_PCIBUS_INTERFACE busInterface;
  464. busInterface = SoftPciTree.BusInterface;
  465. ASSERT((busInterface->ReadConfig != NULL) ||
  466. (busInterface->WriteConfig != NULL));
  467. slot.u.AsULONG = 0;
  468. slot.u.bits.DeviceNumber = ((ULONG)Device->Slot.Device & 0xff);
  469. slot.u.bits.FunctionNumber = ((ULONG)Device->Slot.Function & 0xff);
  470. vendorID = 0;
  471. bytesRead = busInterface->ReadConfig(
  472. busInterface->Context,
  473. Device->Bus,
  474. slot.u.AsULONG,
  475. &vendorID,
  476. 0,
  477. sizeof(USHORT)
  478. );
  479. if (bytesRead == sizeof(USHORT)) {
  480. if (vendorID == 0xFFFF || vendorID == 0) {
  481. return FALSE;
  482. }
  483. }else{
  484. ASSERT(FALSE);
  485. }
  486. //
  487. // Play it safe and assume there is hardware present
  488. //
  489. return TRUE;
  490. }
  491. NTSTATUS
  492. SoftPCIRemoveDevice(
  493. IN PSOFTPCI_DEVICE Device
  494. )
  495. /*++
  496. Routine Description:
  497. This routine is called to remove/delete a specified SoftPCI device
  498. Arguments:
  499. DeviceExtension -
  500. Return Value:
  501. Returns a count of bytes written.
  502. --*/
  503. {
  504. NTSTATUS status = STATUS_SUCCESS;
  505. PSOFTPCI_DEVICE device;
  506. PSOFTPCI_DEVICE previous;
  507. PSOFTPCI_DEVICE current;
  508. PSOFTPCI_DEVICE end;
  509. KIRQL irql;
  510. //
  511. // Lock the tree while we remove our device from the tree
  512. //
  513. SoftPCILockDeviceTree(&irql);
  514. previous = NULL;
  515. device = SoftPCIFindDevice(
  516. Device->Bus,
  517. Device->Slot.AsUSHORT,
  518. &previous,
  519. FALSE
  520. );
  521. //
  522. // We should never get back our root node
  523. //
  524. ASSERT(device != SoftPciTree.RootDevice);
  525. if (device) {
  526. //
  527. // We found the device we want to delete.
  528. //
  529. SoftPCIDbgPrint(
  530. SOFTPCI_REMOVE_DEVICE,
  531. "SOFTPCI: RemoveDevice - Removing BUS_%02x&DEV_%02x&FUN_%02x and all its children\n",
  532. device->Bus,
  533. device->Slot.Device,
  534. device->Slot.Function
  535. );
  536. if (previous){
  537. //
  538. // Patch the link between our previous and next if any
  539. //
  540. previous->Sibling = device->Sibling;
  541. }else{
  542. //
  543. // Update our parent
  544. //
  545. device->Parent->Child = device->Sibling;
  546. }
  547. //
  548. // Release the tree lock now that we have severed the link
  549. // between the device and the tree
  550. //
  551. SoftPCIUnlockDeviceTree(irql);
  552. if (device->Child) {
  553. //
  554. // We have at least one child. Traverse and free everything.
  555. //
  556. current = device;
  557. while (current) {
  558. //
  559. // Find the last Child.
  560. //
  561. while (current->Child) {
  562. previous = current;
  563. current=current->Child;
  564. }
  565. //
  566. // We have a sibling. Free our current node and
  567. // set the previous parent node's child to our
  568. // sibling (if any) and restart the list.
  569. //
  570. end = current;
  571. previous->Child = current->Sibling;
  572. current = device;
  573. SoftPCIDbgPrint(
  574. SOFTPCI_REMOVE_DEVICE,
  575. "SOFTPCI: RemoveDevice - Freeing BUS_%02x&DEV_%02x&FUN_%02x\n",
  576. end->Bus,
  577. end->Slot.Device,
  578. end->Slot.Function
  579. );
  580. ExFreePool(end);
  581. if (device->Child == NULL) {
  582. //
  583. // All our children are now gone. Free the requested device.
  584. //
  585. SoftPCIDbgPrint(
  586. SOFTPCI_REMOVE_DEVICE,
  587. "SOFTPCI: RemoveDevice - Freeing BUS_%02x&DEV_%02x&FUN_%02x\n",
  588. device->Bus,
  589. device->Slot.Device,
  590. device->Slot.Function
  591. );
  592. ExFreePool(device);
  593. break;
  594. }
  595. }
  596. }else{
  597. //
  598. // Cool, no children. Free the device.
  599. //
  600. SoftPCIDbgPrint(
  601. SOFTPCI_REMOVE_DEVICE,
  602. "SOFTPCI: RemoveDevice - Freeing BUS_%02x&DEV_%02x&FUN_%02x\n",
  603. device->Bus, device->Slot.Device, device->Slot.Function
  604. );
  605. ExFreePool(device);
  606. }
  607. }else{
  608. //
  609. // We cant delete one if we dont have one.
  610. //
  611. SoftPCIDbgPrint(
  612. SOFTPCI_REMOVE_DEVICE,
  613. "SOFTPCI: RemoveDevice - No device at BUS_%02x&DEV_%02x&FUN_%02x\n",
  614. Device->Bus,
  615. Device->Slot.Device,
  616. Device->Slot.Function
  617. );
  618. SoftPCIUnlockDeviceTree(irql);
  619. }
  620. if (NT_SUCCESS(status)) {
  621. SoftPciTree.DeviceCount--;
  622. ASSERT(SoftPciTree.DeviceCount != 0);
  623. //
  624. // If we changed the tree, queue an enum
  625. //
  626. SoftPCIEnumerateTree();
  627. }
  628. return status;
  629. }
  630. ULONG
  631. SoftPCIReadConfigSpace(
  632. IN PSOFTPCI_PCIBUS_INTERFACE BusInterface,
  633. IN UCHAR BusOffset,
  634. IN ULONG Slot,
  635. OUT PVOID Buffer,
  636. IN ULONG Offset,
  637. IN ULONG Length
  638. )
  639. /*++
  640. Routine Description:
  641. This routine is called by the PCI driver in place of the normal interface call to
  642. the HAL.
  643. Arguments:
  644. BusInterface - Interface contexts we gave PCI during the query
  645. for PCI_BUS_INTERFACE_STANDARD.
  646. BusOffset - BusOffset provided by PCI
  647. Slot - Slot provided by PCI
  648. Buffer - Buffer for returned data
  649. Offset - Configspace Offset to Read from
  650. Length - Length of requested read.
  651. Return Value:
  652. Returns a count of bytes read..
  653. --*/
  654. {
  655. PCI_SLOT_NUMBER slotNum;
  656. SOFTPCI_SLOT softSlot;
  657. PSOFTPCI_DEVICE device;
  658. PSOFTPCI_CONFIG config;
  659. ULONG count;
  660. PUCHAR softConfig = NULL;
  661. KIRQL irql;
  662. slotNum.u.AsULONG = Slot;
  663. softSlot.Device = (UCHAR) slotNum.u.bits.DeviceNumber;
  664. softSlot.Function = (UCHAR) slotNum.u.bits.FunctionNumber;
  665. SoftPCILockDeviceTree(&irql);
  666. //
  667. // First look for a matching fake device
  668. //
  669. device = SoftPCIFindDevice(
  670. BusOffset,
  671. softSlot.AsUSHORT,
  672. NULL,
  673. FALSE
  674. );
  675. SoftPCIUnlockDeviceTree(irql);
  676. //
  677. // If we found a device, then read it's config space.
  678. //
  679. if (device) {
  680. config = &device->Config;
  681. SoftPCIDbgPrint(SOFTPCI_INFO, "SOFTPCI: ReadConfig - SoftConfigSpace for VEN_%04x&DEV_%04x, HeaderType = 0x%02x\n",
  682. config->Current.VendorID, config->Current.DeviceID, config->Current.HeaderType);
  683. ASSERT(Offset <= sizeof(PCI_COMMON_CONFIG));
  684. ASSERT(Length <= (sizeof(PCI_COMMON_CONFIG) - Offset));
  685. softConfig = (PUCHAR) &config->Current;
  686. softConfig += (UCHAR)Offset;
  687. RtlCopyMemory((PUCHAR)Buffer, softConfig, Length);
  688. //
  689. // We assume everything copied ok. Set count to Length.
  690. //
  691. count = Length;
  692. } else {
  693. //
  694. // We don't have a softdevice so see if we have a real one.
  695. //
  696. count = BusInterface->ReadConfig(
  697. BusInterface->Context,
  698. BusOffset,
  699. Slot,
  700. Buffer,
  701. Offset,
  702. Length
  703. );
  704. //
  705. // Here we snoop the config space header reads
  706. // and if we find a bridge we make sure we have
  707. // it in our tree.
  708. //
  709. if ((Offset == 0) &&
  710. (Length == PCI_COMMON_HDR_LENGTH) &&
  711. ((PCI_CONFIGURATION_TYPE((PPCI_COMMON_CONFIG)Buffer)) == PCI_BRIDGE_TYPE)) {
  712. //
  713. // OK, look one more time, only this time we want placeholders as well
  714. //
  715. SoftPCILockDeviceTree(&irql);
  716. device = SoftPCIFindDevice(
  717. BusOffset,
  718. softSlot.AsUSHORT,
  719. NULL,
  720. TRUE
  721. );
  722. SoftPCIUnlockDeviceTree(irql);
  723. if (!device) {
  724. //
  725. // This real bridge doesnt exist in our tree, add it.
  726. //
  727. device = (PSOFTPCI_DEVICE) ExAllocatePool(NonPagedPool,
  728. sizeof(SOFTPCI_DEVICE));
  729. if (device) {
  730. RtlZeroMemory(device, sizeof(SOFTPCI_DEVICE));
  731. device->Bus = BusOffset;
  732. device->Slot.AsUSHORT = softSlot.AsUSHORT;
  733. device->Config.PlaceHolder = TRUE;
  734. RtlCopyMemory(&device->Config.Current, Buffer, Length);
  735. if (!NT_SUCCESS(SoftPCIAddNewDevice(device))){
  736. SoftPCIDbgPrint(
  737. SOFTPCI_INFO,
  738. "SOFTPCI: ReadConfig - Failed to add new PlaceHolder Device! VEN_%04x&DEV_%04x",
  739. device->Config.Current.VendorID,
  740. device->Config.Current.DeviceID
  741. );
  742. }
  743. }else{
  744. SoftPCIDbgPrint(
  745. SOFTPCI_INFO,
  746. "SOFTPCI: ReadConfig - Failed to allocate memory for new placeholder!\n"
  747. );
  748. }
  749. }
  750. }
  751. }
  752. return count;
  753. }
  754. ULONG
  755. SoftPCIWriteConfigSpace(
  756. IN PSOFTPCI_PCIBUS_INTERFACE BusInterface,
  757. IN UCHAR BusOffset,
  758. IN ULONG Slot,
  759. IN PVOID Buffer,
  760. IN ULONG Offset,
  761. IN ULONG Length
  762. )
  763. /*++
  764. Routine Description:
  765. This routine is called by the PCI driver in place of the normal interface call to
  766. the HAL.
  767. Arguments:
  768. Context - Interface contexts we gave PCI during the query
  769. for PCI_BUS_INTERFACE_STANDARD.
  770. BusOffset - BusOffset provided by PCI
  771. Slot - Slot provided by PCI
  772. Buffer - Data to be written to configspace
  773. Offset - Configspace Offset to start writting
  774. Length - Length of requested write.
  775. Return Value:
  776. Returns a count of bytes written.
  777. --*/
  778. {
  779. PCI_SLOT_NUMBER slotNum;
  780. SOFTPCI_SLOT softSlot;
  781. PSOFTPCI_DEVICE device;
  782. ULONG count = 0;
  783. KIRQL irql;
  784. PPCI_COMMON_CONFIG bridgeConfig;
  785. PUCHAR bridgeOffset;
  786. slotNum.u.AsULONG = Slot;
  787. softSlot.Device = (UCHAR) slotNum.u.bits.DeviceNumber;
  788. softSlot.Function = (UCHAR) slotNum.u.bits.FunctionNumber;
  789. SoftPCILockDeviceTree(&irql);
  790. //
  791. // First look for a matching fake or placeholder device
  792. //
  793. device = SoftPCIFindDevice(
  794. BusOffset,
  795. softSlot.AsUSHORT,
  796. NULL,
  797. TRUE
  798. );
  799. //
  800. // If we found a device, then write to it's config space.
  801. //
  802. if (device && (!device->Config.PlaceHolder)) {
  803. ULONG reg;
  804. PUCHAR value = (PUCHAR) Buffer;
  805. for (reg = Offset; reg < Offset + Length; reg ++) {
  806. WriteByte(device, reg, *value);
  807. value++;
  808. count++;
  809. }
  810. } else {
  811. if (device && (IS_BRIDGE(device))) {
  812. ASSERT(device->Config.PlaceHolder == TRUE);
  813. //
  814. // We have a place holder to update as well as real hardware
  815. //
  816. bridgeConfig = &device->Config.Current;
  817. bridgeOffset = (PUCHAR) bridgeConfig;
  818. bridgeOffset += Offset;
  819. RtlCopyMemory(bridgeOffset, Buffer, Length);
  820. }
  821. //
  822. // We don't have a softdevice so write to the real one.
  823. //
  824. count = BusInterface->WriteConfig(
  825. BusInterface->Context,
  826. BusOffset,
  827. Slot,
  828. Buffer,
  829. Offset,
  830. Length
  831. );
  832. }
  833. SoftPCIUnlockDeviceTree(irql);
  834. return count;
  835. }
  836. BOOLEAN
  837. SoftPCIValidSlot(
  838. IN PSOFTPCI_DEVICE FirstDevice,
  839. IN PSOFTPCI_SLOT Slot
  840. )
  841. /*++
  842. Routine Description:
  843. This function makes sure that there isnt already a device at the specified Slot
  844. Arguments:
  845. FirstDevice - First device we will compare against. We will then only check siblings.
  846. Return Value:
  847. TRUE if the Slot is valid
  848. --*/
  849. {
  850. PSOFTPCI_DEVICE currentDevice;
  851. SOFTPCI_SLOT mfSlot;
  852. BOOLEAN mfSlotRequired;
  853. BOOLEAN mfSlotFound;
  854. RtlZeroMemory(&mfSlot, sizeof(SOFTPCI_SLOT));
  855. mfSlotRequired = FALSE;
  856. mfSlotFound = FALSE;
  857. if (Slot->Function) {
  858. //
  859. // We have a multi-function slot. Make sure function 0
  860. // is present or we must fail
  861. //
  862. mfSlot.AsUSHORT = 0;
  863. mfSlot.Device = Slot->Device;
  864. mfSlotRequired = TRUE;
  865. }
  866. currentDevice = FirstDevice;
  867. while (currentDevice) {
  868. if (currentDevice->Slot.AsUSHORT == mfSlot.AsUSHORT) {
  869. mfSlotFound = TRUE;
  870. }
  871. if (currentDevice->Slot.AsUSHORT == Slot->AsUSHORT) {
  872. return FALSE;
  873. }
  874. currentDevice = currentDevice->Sibling;
  875. }
  876. if (mfSlotRequired && !mfSlotFound) {
  877. //
  878. // Didnt find function 0
  879. //
  880. SoftPCIDbgPrint(
  881. SOFTPCI_ERROR,
  882. "SOFTPCI: VerifyValidSlot - Multi-function slot (%04x) without function 0 !\n",
  883. Slot->AsUSHORT
  884. );
  885. return FALSE;
  886. }
  887. return TRUE;
  888. }
  889. VOID
  890. SoftPCILockDeviceTree(
  891. IN PKIRQL OldIrql
  892. )
  893. {
  894. KeRaiseIrql(HIGH_LEVEL,
  895. OldIrql
  896. );
  897. KeAcquireSpinLockAtDpcLevel(&SoftPciTree.TreeLock);
  898. }
  899. VOID
  900. SoftPCIUnlockDeviceTree(
  901. IN KIRQL NewIrql
  902. )
  903. {
  904. KeReleaseSpinLockFromDpcLevel(&SoftPciTree.TreeLock);
  905. KeLowerIrql(NewIrql);
  906. }