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.

1478 lines
44 KiB

  1. #include "pch.h"
  2. BOOL
  3. SoftPCI_GetSlotPathList(
  4. IN PPCI_DN Pdn,
  5. OUT PULONG SlotCount,
  6. OUT PLIST_ENTRY SlotPathList
  7. )
  8. {
  9. PPCI_DN currentPdn = Pdn;
  10. PSLOT_PATH_ENTRY currentSlot;
  11. while (currentPdn) {
  12. currentSlot = calloc(1, sizeof(SLOT_PATH_ENTRY));
  13. if (currentSlot == NULL) {
  14. return FALSE;
  15. }
  16. currentSlot->Slot.AsUSHORT = currentPdn->Slot.AsUSHORT;
  17. InsertHeadList(SlotPathList, &currentSlot->ListEntry);
  18. (*SlotCount)++;
  19. currentPdn = currentPdn->Parent;
  20. }
  21. return TRUE;
  22. }
  23. VOID
  24. SoftPCI_DestroySlotPathList(
  25. PLIST_ENTRY SlotPathList
  26. )
  27. {
  28. PLIST_ENTRY listEntry;
  29. PLIST_ENTRY nextEntry;
  30. PSLOT_PATH_ENTRY currentSlotEntry;
  31. listEntry = SlotPathList->Flink;
  32. while (listEntry != SlotPathList) {
  33. nextEntry = listEntry->Flink;
  34. currentSlotEntry = CONTAINING_RECORD(listEntry,
  35. SLOT_PATH_ENTRY,
  36. ListEntry
  37. );
  38. free(currentSlotEntry);
  39. listEntry = nextEntry;
  40. }
  41. InitializeListHead(SlotPathList);
  42. }
  43. BOOL
  44. SoftPCI_GetDevicePathList(
  45. IN PPCI_DN Pdn,
  46. OUT PLIST_ENTRY DevicePathList
  47. )
  48. {
  49. PPCI_DN currentPdn = Pdn;
  50. while (currentPdn) {
  51. InsertHeadList(DevicePathList, &currentPdn->ListEntry);
  52. currentPdn = currentPdn->Parent;
  53. }
  54. return TRUE;
  55. }
  56. PWCHAR
  57. SoftPCI_GetPciPathFromDn(
  58. IN PPCI_DN Pdn
  59. )
  60. {
  61. PWCHAR pciPath;
  62. WCHAR currentSlot[25];
  63. ULONG pathCount, bufferSize;
  64. PSLOT_PATH_ENTRY currentSlotEntry;
  65. LIST_ENTRY slotList;
  66. PLIST_ENTRY listEntry = NULL;
  67. InitializeListHead(&slotList);
  68. //
  69. // First figure out how many parents we have and tag them
  70. //
  71. pathCount = 0;
  72. if (!SoftPCI_GetSlotPathList(Pdn, &pathCount, &slotList)){
  73. return NULL;
  74. }
  75. //
  76. // Add in the size of each slot path + size for each "\" and
  77. // one NULL terminator
  78. //
  79. bufferSize = (wcslen(L"XXXX") * pathCount) + pathCount + 1;;
  80. //
  81. // Now convert it to WCHARs
  82. //
  83. bufferSize *= sizeof(WCHAR);
  84. //
  85. // Now allocate our path
  86. //
  87. pciPath = (PWCHAR) calloc(1, bufferSize);
  88. if (pciPath == NULL) {
  89. return NULL;
  90. }
  91. //
  92. // We now have a list that starts with our root. Build out pcipath
  93. //
  94. for (listEntry = slotList.Flink;
  95. listEntry != &slotList;
  96. listEntry = listEntry->Flink) {
  97. currentSlotEntry = CONTAINING_RECORD(listEntry,
  98. SLOT_PATH_ENTRY,
  99. ListEntry
  100. );
  101. wsprintf(currentSlot, L"%04x", currentSlotEntry->Slot.AsUSHORT);
  102. #if 0
  103. {
  104. USHORT testValue = 0;
  105. testValue = SoftPCIStringToUSHORT(currentSlot);
  106. SoftPCI_Debug(SoftPciAlways, L"testValue = %04x\n", testValue);
  107. }
  108. #endif
  109. wcscat(pciPath, currentSlot);
  110. if (listEntry->Flink != &slotList) {
  111. wcscat(pciPath, L"\\");
  112. }
  113. }
  114. SoftPCI_DestroySlotPathList(&slotList);
  115. return pciPath;
  116. }
  117. VOID
  118. SoftPCI_EnumerateDevices(
  119. IN PPCI_TREE PciTree,
  120. IN PPCI_DN *Pdn,
  121. IN DEVNODE Dn,
  122. IN PPCI_DN Parent
  123. )
  124. {
  125. PPCI_DN pdn = NULL;
  126. DEVNODE dnNew = Dn;
  127. BOOL isValid = FALSE;
  128. BOOL skipChildEnum;
  129. HPS_HWINIT_DESCRIPTOR hpData;
  130. isValid = SoftPCI_IsDevnodePCIRoot(Dn, TRUE);
  131. skipChildEnum = FALSE;
  132. if (isValid) {
  133. SoftPCI_Debug(SoftPciDevice, L"SoftPCI_EnumerateDevices() - Found valid PCI Device!\n");
  134. pdn = (PPCI_DN) calloc(1, sizeof(PCI_DN));
  135. if (!pdn) return;
  136. *Pdn = pdn;
  137. pdn->PciTree = PciTree;
  138. pdn->Parent = Parent;
  139. pdn->DevNode = Dn;
  140. SoftPCI_CompletePciDevNode(pdn);
  141. //
  142. // We have special enumeration for hotplug bridges.
  143. // See if this device supports this special enumeration. If this device
  144. // doesn't support the required WMI goop to do this, it'll return FALSE
  145. // and we will fall back to the default enumeration mechanism.
  146. //
  147. skipChildEnum = SoftPCI_EnumerateHotplugDevices(PciTree,
  148. pdn
  149. );
  150. }
  151. if (!skipChildEnum) {
  152. if ((CM_Get_Child(&dnNew, Dn, 0) == CR_SUCCESS)){
  153. //
  154. // Get the next child
  155. //
  156. SoftPCI_EnumerateDevices(PciTree,
  157. (isValid ? &(pdn->Child) : Pdn),
  158. dnNew,
  159. pdn
  160. );
  161. }
  162. }
  163. if ((CM_Get_Sibling(&dnNew, Dn, 0) == CR_SUCCESS)){
  164. //
  165. // Get the next sibling
  166. //
  167. SoftPCI_EnumerateDevices(PciTree,
  168. (isValid ? &(pdn->Sibling) : Pdn),
  169. dnNew,
  170. Parent
  171. );
  172. }
  173. }
  174. VOID
  175. SoftPCI_CompletePciDevNode(
  176. IN PPCI_DN Pdn
  177. )
  178. {
  179. ULONG bytesReturned = 0;
  180. DEVNODE childNode = 0;
  181. PSOFTPCI_DEVICE device = NULL;
  182. SP_DEVINFO_DATA devInfoData;
  183. Pdn->Child = NULL;
  184. Pdn->Sibling = NULL;
  185. if ((CM_Get_Device_ID(Pdn->DevNode, Pdn->DevId, MAX_PATH, 0)) != CR_SUCCESS) {
  186. wcscpy(Pdn->DevId, L"Failed to get DevID...");
  187. SoftPCI_Debug(SoftPciDevice, L"CompletePciDevNode - Failed to retrieve DevID\n");
  188. }
  189. SoftPCI_Debug(SoftPciDevice, L"CompletePciDevNode - DevID - %s\n", Pdn->DevId);
  190. SOFTPCI_ASSERT(Pdn->PciTree->DevInfoSet != INVALID_HANDLE_VALUE);
  191. devInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
  192. if (SetupDiOpenDeviceInfo(Pdn->PciTree->DevInfoSet, Pdn->DevId, NULL, 0, &devInfoData)){
  193. if (Pdn->DevNode == devInfoData.DevInst){
  194. Pdn->DevInfoData = devInfoData;
  195. }
  196. }
  197. SoftPCI_AllocWmiInstanceName(Pdn->WmiId,
  198. Pdn->DevId
  199. );
  200. SoftPCI_Debug(SoftPciHotPlug, L"CompletePciDevNode - WmiID - %s\n", Pdn->WmiId);
  201. //
  202. // Now we need to see if this is a root bus as getting its bus number
  203. // is not quite as easy as a PCI device
  204. //
  205. if (SoftPCI_IsDevnodePCIRoot(Pdn->DevNode, FALSE)) {
  206. if (!SoftPCI_GetPciRootBusNumber(Pdn->DevNode, &Pdn->Bus)){
  207. //
  208. // Not sure what I should do in this case.....should probably disable this device (if a bridge)
  209. // from allowing devices behind it.....
  210. //
  211. }
  212. //
  213. // Setup our root Slot info
  214. //
  215. Pdn->Slot.Device = 0xff;
  216. Pdn->Slot.Function = (UCHAR)Pdn->Bus;
  217. }else{
  218. if (!SoftPCI_GetBusDevFuncFromDevnode(Pdn->DevNode, &Pdn->Bus, &Pdn->Slot)) {
  219. //
  220. // Not sure what I should do in this case.....should probably disable this device (if a bridge)
  221. // from allowing devices behind it.....
  222. //
  223. }
  224. }
  225. if (!SoftPCI_GetFriendlyNameFromDevNode(Pdn->DevNode, Pdn->FriendlyName)) {
  226. //
  227. // Not sure what I should do in this case.....
  228. //
  229. wcscpy(Pdn->FriendlyName, L"Failed to get friendly name...");
  230. }
  231. if ((Pdn->Parent) &&
  232. ((Pdn->Parent->Bus == Pdn->Bus) &&
  233. (Pdn->Parent->Slot.AsUSHORT == Pdn->Slot.AsUSHORT))){
  234. //
  235. // Our parent (probably a root bus) matches us. We dont want dupes.
  236. //
  237. return;
  238. }
  239. if (g_DriverHandle){
  240. //
  241. // Grab any softPCI device information there may be
  242. //
  243. device = (PSOFTPCI_DEVICE) calloc(1, sizeof(SOFTPCI_DEVICE));
  244. if (device) {
  245. device->Bus = (UCHAR)Pdn->Bus;
  246. device->Slot.AsUSHORT = Pdn->Slot.AsUSHORT;
  247. if (!DeviceIoControl(g_DriverHandle,
  248. (DWORD) SOFTPCI_IOCTL_GET_DEVICE,
  249. device,
  250. sizeof(SOFTPCI_DEVICE),
  251. device,
  252. sizeof(SOFTPCI_DEVICE),
  253. &bytesReturned,
  254. NULL
  255. )){
  256. SoftPCI_Debug(SoftPciDeviceVerbose,
  257. L"CompletePciDevNode - Failed to get SoftPCI device info (bus %02x dev %02x func %02x)\n",
  258. Pdn->Bus, Pdn->Slot.Device, Pdn->Slot.Function);
  259. free(device);
  260. }else{
  261. Pdn->SoftDev = device;
  262. }
  263. }
  264. }
  265. }
  266. BOOL
  267. SoftPCI_EnumerateHotplugDevices(
  268. IN PPCI_TREE PciTree,
  269. IN PPCI_DN Pdn
  270. )
  271. {
  272. HPS_HWINIT_DESCRIPTOR hpData;
  273. PPCI_DN deviceTable[PCI_MAX_DEVICES];
  274. PPCI_DN newPdn, currentPdn, slotHeadPdn;
  275. DEVNODE devNode, childDn;
  276. UCHAR slotNum, devNum;
  277. ULONG slotLabelNum, slotsMask;
  278. CONFIGRET configRet;
  279. BOOL status, skipChildEnum;
  280. PSOFTPCI_DEVICE softDevice;
  281. if (!SoftPCI_SetEventContext(Pdn)) {
  282. return FALSE;
  283. }
  284. if (!SoftPCI_GetHotplugData(Pdn,
  285. &hpData
  286. )) {
  287. return FALSE;
  288. }
  289. //
  290. // This device is actually a hotplug controller. Mark it as such for the future.
  291. //
  292. Pdn->Flags |= SOFTPCI_HOTPLUG_CONTROLLER;
  293. SoftPCI_Debug(SoftPciDevice, L"SoftPCI_EnumerateDevices() - Found HOTPLUG PCI Bridge!\n");
  294. //SoftPCI_CompleteCommand(Pdn);
  295. currentPdn = NULL;
  296. slotLabelNum = hpData.FirstSlotLabelNumber;
  297. RtlZeroMemory(deviceTable,sizeof(deviceTable));
  298. //
  299. // First create slot objects for each slot and add them
  300. // to the tree.
  301. //
  302. for (slotNum=0; slotNum < hpData.NumSlots; slotNum++) {
  303. devNum = slotNum + hpData.FirstDeviceID;
  304. newPdn = (PPCI_DN) calloc(1, sizeof(PCI_DN));
  305. if (!newPdn) {
  306. break;
  307. }
  308. //
  309. // For slots, we co-opt the Function field to be
  310. // the slot number.
  311. //
  312. newPdn->Slot.Device = devNum;
  313. newPdn->Slot.Function = slotNum;
  314. newPdn->PciTree = PciTree;
  315. newPdn->Parent = Pdn;
  316. newPdn->Flags = SOFTPCI_HOTPLUG_SLOT;
  317. if (currentPdn) {
  318. currentPdn->Sibling = newPdn;
  319. } else {
  320. slotHeadPdn = newPdn;
  321. }
  322. wsprintf(newPdn->FriendlyName,L"Slot %d",slotLabelNum);
  323. RtlZeroMemory(newPdn->WmiId,MAX_PATH);
  324. SOFTPCI_ASSERT(devNum < PCI_MAX_DEVICES);
  325. //
  326. // Add this slot to the table that maps slot objects to the
  327. // PCI device numbers that they correspond to.
  328. //
  329. if (devNum < PCI_MAX_DEVICES) {
  330. deviceTable[devNum] = newPdn;
  331. } else {
  332. free(newPdn);
  333. break;
  334. }
  335. currentPdn = newPdn;
  336. if (hpData.UpDown) {
  337. slotLabelNum++;
  338. } else {
  339. slotLabelNum--;
  340. }
  341. }
  342. //
  343. // Now enumerate all the devices and put them underneath the
  344. // appropriate slots.
  345. //
  346. configRet = CM_Get_Child(&devNode, Pdn->DevNode, 0);
  347. while (configRet == CR_SUCCESS){
  348. //
  349. // The controller has a child. Create the PCI_DN for it.
  350. //
  351. newPdn = (PPCI_DN) calloc(1, sizeof(PCI_DN));
  352. if (!newPdn) {
  353. break;
  354. }
  355. newPdn->PciTree = PciTree;
  356. newPdn->DevNode = devNode;
  357. SoftPCI_CompletePciDevNode(newPdn);
  358. SOFTPCI_ASSERT(newPdn->Slot.Device < PCI_MAX_DEVICES);
  359. if (newPdn->Slot.Device < PCI_MAX_DEVICES) {
  360. //
  361. // Add this PCI_DN to the tree underneath the
  362. // slot object for the appropriate slot.
  363. // If there is no corresponding slot, add it
  364. // directly underneat the controller.
  365. //
  366. if (deviceTable[newPdn->Slot.Device]) {
  367. SoftPCI_AddChild(deviceTable[newPdn->Slot.Device],
  368. newPdn
  369. );
  370. } else {
  371. SoftPCI_AddChild(Pdn,
  372. newPdn
  373. );
  374. }
  375. skipChildEnum = SoftPCI_EnumerateHotplugDevices(PciTree,
  376. newPdn
  377. );
  378. //
  379. // We've done the hotplug specific enumeration.
  380. // If there are more devices underneath this one
  381. // (there is a bridge in the hotplug slot), return
  382. // to the default enumeration
  383. //
  384. if (!skipChildEnum &&
  385. (CM_Get_Child(&childDn,devNode,0) == CR_SUCCESS)) {
  386. SoftPCI_EnumerateDevices(PciTree,
  387. &newPdn->Child,
  388. childDn,
  389. newPdn
  390. );
  391. }
  392. } else {
  393. free(newPdn);
  394. }
  395. //
  396. // After enumerating the first child of the controller, get the
  397. // rest of the devices by getting the first child's sibling.
  398. //
  399. configRet = CM_Get_Sibling(&devNode, devNode, 0);
  400. }
  401. //
  402. // Next run through all the slots again and if they don't have real
  403. // children, call GetDevice to get the unenumerated device from hpsim.
  404. //
  405. for (slotNum=0; slotNum < hpData.NumSlots; slotNum++) {
  406. devNum = slotNum + hpData.FirstDeviceID;
  407. if (deviceTable[devNum] && !deviceTable[devNum]->Child) {
  408. softDevice = (PSOFTPCI_DEVICE)malloc(sizeof(SOFTPCI_DEVICE));
  409. if (!softDevice) {
  410. break;
  411. }
  412. status = SoftPCI_GetHotplugDevice(Pdn,
  413. slotNum,
  414. softDevice
  415. );
  416. if (status == FALSE) {
  417. SoftPCI_Debug(SoftPciHotPlug, L"EnumerateHotplugDevices - Couldn't get device for slot %d\n", slotNum);
  418. free(softDevice);
  419. continue;
  420. }
  421. newPdn = (PPCI_DN) calloc(1, sizeof(PCI_DN));
  422. if (!newPdn) {
  423. free(softDevice);
  424. break;
  425. }
  426. newPdn->PciTree = PciTree;
  427. newPdn->Parent = deviceTable[devNum];
  428. newPdn->Bus = newPdn->Parent->Bus;
  429. newPdn->Slot.AsUSHORT = softDevice->Slot.AsUSHORT;
  430. newPdn->SoftDev = softDevice;
  431. newPdn->Flags = SOFTPCI_UNENUMERATED_DEVICE;
  432. wcscpy(newPdn->FriendlyName, L"Unpowered Device");
  433. RtlZeroMemory(newPdn->WmiId,MAX_PATH);
  434. deviceTable[devNum]->Child = newPdn;
  435. }
  436. }
  437. //
  438. // Now add the slot objects to the tree, along with whatever's been added
  439. // beneath them. Do this now so that they show up at the end of the list
  440. // rather than at the top.
  441. //
  442. currentPdn = Pdn->Child;
  443. if (currentPdn == NULL) {
  444. Pdn->Child = slotHeadPdn;
  445. } else {
  446. while (currentPdn->Sibling != NULL) {
  447. currentPdn = currentPdn->Sibling;
  448. }
  449. currentPdn->Sibling = slotHeadPdn;
  450. }
  451. return TRUE;
  452. }
  453. VOID
  454. SoftPCI_BringHotplugDeviceOnline(
  455. IN PPCI_DN PciDn,
  456. IN UCHAR SlotNumber
  457. )
  458. {
  459. BOOL status;
  460. SOFTPCI_DEVICE softDevice;
  461. SoftPCI_Debug(SoftPciHotPlug, L"Bringing slot %d online\n", SlotNumber);
  462. status = SoftPCI_GetHotplugDevice(PciDn,
  463. SlotNumber,
  464. &softDevice
  465. );
  466. if (status == FALSE) {
  467. SoftPCI_Debug(SoftPciHotPlug, L"Couldn't get device for slot\n");
  468. return;
  469. }
  470. if (!SoftPCI_CreateDevice(&softDevice,
  471. 1<<softDevice.Slot.Device,
  472. FALSE
  473. )){
  474. SoftPCI_Debug(SoftPciHotPlug, L"Failed to bring device at slot %d online\n", SlotNumber);
  475. }
  476. }
  477. VOID
  478. SoftPCI_TakeHotplugDeviceOffline(
  479. IN PPCI_DN PciDn,
  480. IN UCHAR SlotNumber
  481. )
  482. {
  483. SOFTPCI_DEVICE softDevice;
  484. BOOL status;
  485. SoftPCI_Debug(SoftPciHotPlug, L"Taking slot %d offline\n", SlotNumber);
  486. status = SoftPCI_GetHotplugDevice(PciDn,
  487. SlotNumber,
  488. &softDevice
  489. );
  490. if (status == FALSE) {
  491. SoftPCI_Debug(SoftPciHotPlug, L"Couldn't get device for slot\n");
  492. return;
  493. }
  494. status = SoftPCI_DeleteDevice(&softDevice);
  495. if (status == FALSE) {
  496. SoftPCI_Debug(SoftPciHotPlug, L"Couldn't delete device\n");
  497. } else {
  498. SoftPCI_Debug(SoftPciHotPlug, L"Slot %d offline\n", SlotNumber);
  499. }
  500. }
  501. VOID
  502. SoftPCI_AddChild(
  503. IN PPCI_DN Parent,
  504. IN PPCI_DN Child
  505. )
  506. {
  507. PPCI_DN sibling;
  508. Child->Parent = Parent;
  509. if (Parent->Child == NULL) {
  510. Parent->Child = Child;
  511. } else {
  512. sibling = Parent->Child;
  513. while (sibling->Sibling != NULL) {
  514. sibling = sibling->Sibling;
  515. }
  516. sibling->Sibling = Child;
  517. }
  518. }
  519. BOOL
  520. SoftPCI_IsBridgeDevice(
  521. IN PPCI_DN Pdn
  522. )
  523. {
  524. // ISSUE: BrandonA - This should probably just be a macro
  525. if ((Pdn->SoftDev != NULL) &&
  526. (IS_BRIDGE(Pdn->SoftDev))) {
  527. return TRUE;
  528. }
  529. return FALSE;
  530. }
  531. BOOL
  532. SoftPCI_IsSoftPCIDevice(
  533. IN PPCI_DN Pdn
  534. )
  535. {
  536. // ISSUE: BrandonA - This should probably just be a macro
  537. if ((Pdn->SoftDev) &&
  538. !(Pdn->SoftDev->Config.PlaceHolder)) {
  539. return TRUE;
  540. }
  541. return FALSE;
  542. }
  543. BOOL
  544. SoftPCI_IsDevnodePCIRoot(
  545. IN DEVNODE Dn,
  546. IN BOOL ValidateAll
  547. )
  548. {
  549. WCHAR devId[MAX_PATH];
  550. ULONG size = 0;
  551. PWCHAR p = NULL, idList = NULL, id = NULL;
  552. if ((CM_Get_Device_ID(Dn, devId, MAX_PATH, 0))==CR_SUCCESS){
  553. if (ValidateAll &&
  554. ((p = wcsstr(devId, L"PCI\\VEN")) != NULL)){
  555. return TRUE;
  556. }
  557. if ((p = wcsstr(devId, L"PNP0A03")) != NULL){
  558. return TRUE;
  559. }
  560. }
  561. //
  562. // Check our compat ids as well
  563. //
  564. if ((CM_Get_DevNode_Registry_Property(Dn, CM_DRP_COMPATIBLEIDS, NULL, NULL, &size, 0)) == CR_BUFFER_SMALL){
  565. idList = (PWCHAR) calloc(1, size);
  566. if (!idList) {
  567. return FALSE;
  568. }
  569. if ((CM_Get_DevNode_Registry_Property(Dn,
  570. CM_DRP_COMPATIBLEIDS,
  571. NULL,
  572. idList,
  573. &size,
  574. 0)) == CR_SUCCESS){
  575. for (id = idList; *id; id+=wcslen(id)+1) {
  576. if ((p = wcsstr(id, L"PNP0A03")) != NULL){
  577. free(idList);
  578. return TRUE;
  579. }
  580. }
  581. }
  582. }
  583. return FALSE;
  584. }
  585. BOOL
  586. SoftPCI_UpdateDeviceFriendlyName(
  587. IN DEVNODE DeviceNode,
  588. IN PWCHAR NewName
  589. )
  590. {
  591. WCHAR friendlyName[MAX_PATH];
  592. ULONG length = 0;
  593. //
  594. // If we are updating a root bus we append to the current name
  595. //
  596. if (wcscmp(NewName, SOFTPCI_BUS_DESC) == 0) {
  597. if (!SoftPCI_GetFriendlyNameFromDevNode(DeviceNode, friendlyName)){
  598. return FALSE;
  599. }
  600. length = (wcslen(friendlyName) + 1) + (wcslen(NewName) + 1);
  601. //
  602. // Make sure there is enough room
  603. //
  604. if (length < MAX_PATH) {
  605. wcscat(friendlyName, NewName);
  606. }
  607. }else{
  608. //
  609. // Otherwise, we replace the name entirely
  610. //
  611. wcscpy(friendlyName, NewName);
  612. length = wcslen(friendlyName) + 1;
  613. }
  614. length *= sizeof(WCHAR);
  615. if ((CM_Set_DevNode_Registry_Property(DeviceNode,
  616. CM_DRP_DEVICEDESC,
  617. (PVOID)friendlyName,
  618. length,
  619. 0
  620. )) != CR_SUCCESS){
  621. return FALSE;
  622. }
  623. return TRUE;
  624. }
  625. HANDLE
  626. SoftPCI_OpenHandleToDriver(VOID)
  627. {
  628. HANDLE hFile = NULL;
  629. BOOL success = TRUE;
  630. ULONG requiredSize, error;
  631. HDEVINFO deviceInfoSet;
  632. SP_DEVICE_INTERFACE_DATA deviceInterfaceData;
  633. PSP_DEVICE_INTERFACE_DETAIL_DATA deviceInterfaceDetailData;
  634. deviceInfoSet = SetupDiGetClassDevs((LPGUID)&GUID_SOFTPCI_INTERFACE,
  635. NULL,
  636. NULL,
  637. DIGCF_PRESENT | DIGCF_DEVICEINTERFACE
  638. );
  639. if (deviceInfoSet == INVALID_HANDLE_VALUE) {
  640. SoftPCI_Debug(SoftPciAlways,
  641. L"OpenHandleToDriver() - SetupDiGetClassDevs failed! Error - \"%s\"\n",
  642. SoftPCI_GetLastError());
  643. return NULL;
  644. }
  645. deviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
  646. success = SetupDiEnumDeviceInterfaces(deviceInfoSet,
  647. NULL,
  648. (LPGUID)&GUID_SOFTPCI_INTERFACE,
  649. 0,
  650. &deviceInterfaceData
  651. );
  652. if (success) {
  653. //
  654. // Call it once to find out how big the buffer needs to be.
  655. //
  656. SetupDiGetDeviceInterfaceDetail(deviceInfoSet,
  657. &deviceInterfaceData,
  658. NULL,
  659. 0,
  660. &requiredSize,
  661. NULL
  662. );
  663. //
  664. // Allocate the required size for the buffer
  665. // and initialize the buffer.
  666. //
  667. deviceInterfaceDetailData = malloc(requiredSize);
  668. if (deviceInterfaceDetailData) {
  669. deviceInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
  670. success = SetupDiGetDeviceInterfaceDetail(deviceInfoSet,
  671. &deviceInterfaceData,
  672. deviceInterfaceDetailData,
  673. requiredSize,
  674. NULL,
  675. NULL
  676. );
  677. if (success) {
  678. hFile = CreateFile(deviceInterfaceDetailData->DevicePath,
  679. 0,
  680. FILE_SHARE_READ | FILE_SHARE_WRITE,
  681. NULL,
  682. OPEN_EXISTING,
  683. 0,
  684. NULL
  685. );
  686. if (hFile == INVALID_HANDLE_VALUE) {
  687. SoftPCI_Debug(SoftPciAlways,
  688. L"OpenHandleToDriver() - CreateFile failed! Error - \"%s\"\n",
  689. SoftPCI_GetLastError());
  690. SOFTPCI_ASSERT(FALSE);
  691. hFile = NULL;
  692. }
  693. } else {
  694. SoftPCI_Debug(SoftPciAlways,
  695. L"OpenHandleToDriver() - SetupDiGetDeviceInterfaceDetail() failed! Error - \"%s\"\n",
  696. SoftPCI_GetLastError());
  697. SOFTPCI_ASSERT(FALSE);
  698. }
  699. free(deviceInterfaceDetailData);
  700. }
  701. } else {
  702. SoftPCI_Debug(SoftPciAlways,
  703. L"OpenHandleToDriver() - SetupDiEnumDeviceInterfaces() failed! Error - \"%s\"\n",
  704. SoftPCI_GetLastError());
  705. }
  706. SetupDiDestroyDeviceInfoList(deviceInfoSet);
  707. return hFile;
  708. }
  709. VOID
  710. SoftPCI_InstallScriptDevices(
  711. VOID
  712. )
  713. {
  714. ULONG deviceMask;
  715. PSINGLE_LIST_ENTRY listEntry;
  716. PSOFTPCI_SCRIPT_DEVICE installDevice;
  717. if (g_DriverHandle) {
  718. //
  719. // We have a handle to our driver. Drain our script queue if we have one.
  720. //
  721. listEntry = g_NewDeviceList.Next;
  722. while (listEntry) {
  723. installDevice = NULL;
  724. installDevice = CONTAINING_RECORD(listEntry, SOFTPCI_SCRIPT_DEVICE, ListEntry);
  725. listEntry = listEntry->Next;
  726. deviceMask = (ULONG) -1;
  727. if (installDevice->SlotSpecified) {
  728. deviceMask = (1 << installDevice->SoftPciDevice.Slot.Device);
  729. }
  730. if (!SoftPCI_CreateDevice(installDevice,
  731. deviceMask,
  732. TRUE)){
  733. SoftPCI_Debug(SoftPciAlways, L"Failed to install scriptdevice");
  734. }
  735. //
  736. // We no longer need this memory so free it
  737. //
  738. free(installDevice);
  739. }
  740. g_NewDeviceList.Next = NULL;
  741. }
  742. }
  743. BOOL
  744. SoftPCI_CreateDevice(
  745. IN PVOID CreateDevice,
  746. IN ULONG PossibleDeviceMask,
  747. IN BOOL ScriptDevice
  748. )
  749. {
  750. BOOL success = FALSE, status = FALSE;
  751. ULONG error, bytesReturned, type;
  752. ULONG newDeviceSize;
  753. PVOID newDevice;
  754. PSOFTPCI_SCRIPT_DEVICE scriptDevice;
  755. PSOFTPCI_SLOT softPciSlot;
  756. newDevice = CreateDevice;
  757. newDeviceSize = sizeof(SOFTPCI_DEVICE);
  758. scriptDevice = NULL;
  759. softPciSlot = NULL;
  760. if (ScriptDevice) {
  761. scriptDevice = (PSOFTPCI_SCRIPT_DEVICE) CreateDevice;
  762. softPciSlot = &scriptDevice->SoftPciDevice.Slot;
  763. if (scriptDevice->ParentPathLength) {
  764. SOFTPCI_ASSERT(scriptDevice->ParentPath != NULL);
  765. newDeviceSize = sizeof(SOFTPCI_SCRIPT_DEVICE) + scriptDevice->ParentPathLength;
  766. }else{
  767. newDevice = (PVOID)&scriptDevice->SoftPciDevice;
  768. }
  769. }else{
  770. softPciSlot = &((PSOFTPCI_DEVICE)CreateDevice)->Slot;
  771. }
  772. softPciSlot->Device = 0;
  773. bytesReturned = 0;
  774. while (PossibleDeviceMask != 0) {
  775. if (PossibleDeviceMask & 0x1) {
  776. status = DeviceIoControl(g_DriverHandle,
  777. (DWORD) SOFTPCI_IOCTL_CREATE_DEVICE,
  778. newDevice,
  779. newDeviceSize,
  780. &success,
  781. sizeof (BOOLEAN),
  782. &bytesReturned,
  783. NULL
  784. );
  785. if ((status == TRUE) ||
  786. (softPciSlot->Device == PCI_MAX_DEVICES)) {
  787. break;
  788. }
  789. }
  790. softPciSlot->Device++;
  791. PossibleDeviceMask >>= 1;
  792. }
  793. if ((bytesReturned < sizeof(BOOLEAN)) || !status){
  794. if (GetLastError() == ERROR_ACCESS_DENIED) {
  795. MessageBox(NULL, L"A device exists at the location (slot) specified!", NULL, MB_OK);
  796. }else{
  797. SoftPCI_Debug(SoftPciAlways, L"CreateDevice - Failed! (%d) - \"%s\"\n",
  798. GetLastError(),
  799. SoftPCI_GetLastError());
  800. }
  801. return FALSE;
  802. }
  803. return TRUE;
  804. }
  805. BOOL
  806. SoftPCI_DeleteDevice(
  807. IN PSOFTPCI_DEVICE Device
  808. )
  809. {
  810. BOOL success, status = TRUE;
  811. ULONG error, bytesReturned;
  812. SOFTPCI_ASSERT((g_DriverHandle != NULL) &&
  813. (g_DriverHandle != INVALID_HANDLE_VALUE));
  814. //
  815. // Tell our driver to delete the device.
  816. //
  817. status = DeviceIoControl(g_DriverHandle,
  818. (DWORD) SOFTPCI_IOCTL_DELETE_DEVICE,
  819. Device,
  820. sizeof(SOFTPCI_DEVICE),
  821. &success, //ISSUE do I need a result here?
  822. sizeof (BOOLEAN),
  823. &bytesReturned,
  824. NULL
  825. );
  826. if (!success || !status){
  827. MessageBox(NULL, L"Failed to delete specified device or one of its children", NULL, MB_OK);
  828. SoftPCI_Debug(SoftPciAlways, L"DeleteDevice - IOCTL failed! Error - \"%s\"\n",
  829. SoftPCI_GetLastError());
  830. return FALSE;
  831. }
  832. return TRUE;
  833. }
  834. VOID
  835. SoftPCI_InitializeDevice(
  836. IN PSOFTPCI_DEVICE Device,
  837. IN SOFTPCI_DEV_TYPE Type
  838. )
  839. {
  840. PSOFTPCI_CONFIG config;
  841. PPCI_COMMON_CONFIG commonConfig;
  842. //
  843. // Set the type of the device
  844. //
  845. Device->DevType = Type;
  846. config = &Device->Config;
  847. commonConfig = &config->Current;
  848. switch (Type) {
  849. case TYPE_DEVICE:
  850. commonConfig->VendorID = 0xABCD;
  851. commonConfig->DeviceID = 0xDCBA;
  852. //commonConfig->Command = 0;
  853. commonConfig->Status = 0x0200;
  854. commonConfig->RevisionID = 0x0;
  855. //commonConfig->ProgIf = 0x00;
  856. commonConfig->SubClass = 0x80;
  857. commonConfig->BaseClass = 0x04;
  858. commonConfig->CacheLineSize = 0x11;
  859. commonConfig->LatencyTimer = 0x99;
  860. commonConfig->HeaderType= 0x80;
  861. //commonConfig->BIST = 0x0;
  862. //commonConfig->u.type0.BaseAddresses[0] = 0;
  863. //commonConfig->u.type0.BaseAddresses[1] = 0;
  864. //commonConfig->u.type0.BaseAddresses[2] = 0;
  865. //commonConfig->u.type0.BaseAddresses[3] = 0;
  866. //commonConfig->u.type0.BaseAddresses[4] = 0;
  867. //commonConfig->u.type0.BaseAddresses[5] = 0;
  868. //commonConfig->u.type0.CIS = 0x0;
  869. commonConfig->u.type0.SubVendorID = 0xABCD;
  870. commonConfig->u.type0.SubSystemID = 0xDCBA;
  871. //commonConfig->u.type0.ROMBaseAddress = 0;
  872. //commonConfig->u.type0.CapabilitiesPtr = 0x0;
  873. //commonConfig->u.type0.Reserved1[0] = 0x0;
  874. //commonConfig->u.type0.Reserved1[1] = 0x0;
  875. //commonConfig->u.type0.Reserved1[2] = 0x0;
  876. //commonConfig->u.type0.Reserved2 = 0x0;
  877. //commonConfig->u.type0.InterruptLine = 0xFF;
  878. //commonConfig->u.type0.InterruptPin = 0;
  879. //commonConfig->u.type0.MinimumGrant = 0x0;
  880. //commonConfig->u.type0.MaximumLatency = 0x0;
  881. //
  882. // Now set the Mask
  883. //
  884. commonConfig = &config->Mask;
  885. //commonConfig->VendorID = 0;
  886. //commonConfig->DeviceID = 0;
  887. commonConfig->Command = 0x143;
  888. commonConfig->Status = 0x0200;
  889. //commonConfig->RevisionID = 0x0;
  890. //commonConfig->ProgIf = 0x00;
  891. commonConfig->SubClass = 0x80;
  892. commonConfig->BaseClass = 0x04;
  893. commonConfig->CacheLineSize = 0xff;
  894. commonConfig->LatencyTimer = 0xff;
  895. //commonConfig->HeaderType= 0x80;
  896. //commonConfig->BIST = 0x0;
  897. //commonConfig->u.type0.BaseAddresses[0] = 0;//0xffff0000;
  898. //commonConfig->u.type0.BaseAddresses[1] = 0;
  899. //commonConfig->u.type0.BaseAddresses[2] = 0;
  900. //commonConfig->u.type0.BaseAddresses[3] = 0;
  901. //commonConfig->u.type0.BaseAddresses[4] = 0;
  902. //commonConfig->u.type0.BaseAddresses[5] = 0;
  903. //commonConfig->u.type0.CIS = 0x0;
  904. //commonConfig->u.type0.SubVendorID = 0xABCD;
  905. //commonConfig->u.type0.SubSystemID = 0xDCBA;
  906. //commonConfig->u.type0.ROMBaseAddress = 0;
  907. //commonConfig->u.type0.CapabilitiesPtr = 0x0;
  908. //commonConfig->u.type0.Reserved1[0] = 0x0;
  909. //commonConfig->u.type0.Reserved1[1] = 0x0;
  910. //commonConfig->u.type0.Reserved1[2] = 0x0;
  911. //commonConfig->u.type0.Reserved2 = 0x0;
  912. commonConfig->u.type0.InterruptLine = 0xFF;
  913. //commonConfig->u.type0.InterruptPin = 0;
  914. //commonConfig->u.type0.MinimumGrant = 0x0;
  915. //commonConfig->u.type0.MaximumLatency = 0x0;
  916. break;
  917. case TYPE_PCI_BRIDGE:
  918. case TYPE_HOTPLUG_BRIDGE:
  919. if (Type == TYPE_PCI_BRIDGE) {
  920. commonConfig->VendorID = 0xABCD;
  921. commonConfig->DeviceID = 0xDCBB;
  922. commonConfig->Status = 0x0400;
  923. }else{
  924. commonConfig->VendorID = 0xABCD;
  925. commonConfig->DeviceID = 0xDCBC;
  926. commonConfig->Status = 0x0410;
  927. commonConfig->u.type1.CapabilitiesPtr = 0x40;
  928. commonConfig->DeviceSpecific[0] = 0xc; //CapID
  929. commonConfig->DeviceSpecific[1] = 0x48; //Next Cap
  930. commonConfig->DeviceSpecific[8] = 0xd; //CapID for hwinit
  931. commonConfig->DeviceSpecific[9] = 0; //Next Cap
  932. }
  933. commonConfig->Command = 0x80;
  934. //commonConfig->RevisionhpsinitOffsetID = 0x0;
  935. commonConfig->ProgIf = 0x80;
  936. commonConfig->SubClass = 0x04;
  937. commonConfig->BaseClass = 0x06;
  938. commonConfig->CacheLineSize = 0x8;
  939. //commonConfig->LatencyTimer = 0x00;
  940. commonConfig->HeaderType= 0x81;
  941. //commonConfig->BIST = 0x0;
  942. //commonConfig->u.type1.BaseAddresses[0] = 0;
  943. //commonConfig->u.type1.BaseAddresses[1] = 0;
  944. //commonConfig->u.type1.PrimaryBus = 0x0;
  945. //commonConfig->u.type1.SecondaryBus = 0x0;
  946. //commonConfig->u.type1.SubordinateBus = 0x0;
  947. //commonConfig->u.type1.SecondaryLatency = 0;
  948. //commonConfig->u.type1.CapabilitiesPtr = 0;
  949. //commonConfig->u.type1.IOBase = 0;
  950. //commonConfig->u.type1.IOLimit = 0;
  951. //commonConfig->u.type1.SecondaryStatus = 0x0;
  952. //commonConfig->u.type1.MemoryBase = 0x0;
  953. //commonConfig->u.type1.MemoryLimit = 0;
  954. //commonConfig->u.type1.PrefetchBase = 0;
  955. //commonConfig->u.type1.MemoryLimit = 0x0;
  956. //commonConfig->u.type1.PrefetchBaseUpper32 = 0x0;
  957. //commonConfig->u.type1.IOBaseUpper16 = 0x0;
  958. //commonConfig->u.type1.IOLimitUpper16 = 0x0;
  959. //commonConfig->u.type1.CapabilitiesPtr = 0x0;
  960. //commonConfig->u.type1.Reserved1[0] = 0x0;
  961. //commonConfig->u.type1.Reserved1[1] = 0x0;
  962. //commonConfig->u.type1.Reserved1[2] = 0x0;
  963. //commonConfig->u.type1.ROMBaseAddress = 0x0;
  964. //commonConfig->u.type1.InterruptLine = 0x0;
  965. //commonConfig->u.type1.InterruptPin = 0x0;
  966. //commonConfig->u.type1.BridgeControl = 0x0;
  967. //
  968. // Now set the Mask
  969. //
  970. commonConfig = &config->Mask;
  971. //commonConfig->VendorID = 0x0;
  972. //commonConfig->DeviceID = 0x0;
  973. commonConfig->Command = 0xff;
  974. //commonConfig->Status = 0x0;
  975. //commonConfig->RevisionID = 0x0;
  976. //commonConfig->ProgIf = 0x0;
  977. //commonConfig->SubClass = 0x0;
  978. //commonConfig->BaseClass = 0x0;
  979. //commonConfig->CacheLineSize = 0;
  980. //commonConfig->LatencyTimer = 0;
  981. //commonConfig->HeaderType= 0;
  982. //commonConfig->BIST = 0x0;
  983. //commonConfig->u.type1.BaseAddresses[0] = 0;
  984. //commonConfig->u.type1.BaseAddresses[1] = 0;
  985. commonConfig->u.type1.PrimaryBus = 0xff;
  986. commonConfig->u.type1.SecondaryBus = 0xff;
  987. commonConfig->u.type1.SubordinateBus = 0xff;
  988. //commonConfig->u.type1.SecondaryLatency = 0;
  989. //commonConfig->u.type1.CapabilitiesPtr = 0;
  990. commonConfig->u.type1.IOBase = 0xf0;
  991. commonConfig->u.type1.IOLimit = 0xf0;
  992. //commonConfig->u.type1.SecondaryStatus = 0x0;
  993. commonConfig->u.type1.MemoryBase = 0xfff0;
  994. commonConfig->u.type1.MemoryLimit = 0xfff0;
  995. commonConfig->u.type1.PrefetchBase = 0xfff0;
  996. commonConfig->u.type1.PrefetchLimit = 0xfff0;
  997. //commonConfig->u.type1.PrefetchBaseUpper32 = 0xffffffff;
  998. //commonConfig->u.type1.PrefetchLimitUpper32 = 0xffffffff;
  999. //commonConfig->u.type1.IOBaseUpper16 = 0;
  1000. //commonConfig->u.type1.IOLimitUpper16 = 0;
  1001. //commonConfig->u.type1.CapabilitiesPtr = 0x0;
  1002. //commonConfig->u.type1.Reserved1[0] = 0x0;
  1003. //commonConfig->u.type1.Reserved1[1] = 0x0;
  1004. //commonConfig->u.type1.Reserved1[2] = 0x0;
  1005. //commonConfig->u.type1.ROMBaseAddress = 0x0;
  1006. //commonConfig->u.type1.InterruptLine = 0x0;
  1007. //commonConfig->u.type1.InterruptPin = 0x0;
  1008. //commonConfig->u.type1.BridgeControl = 0x0;
  1009. //
  1010. // For a hotplug bridge, the pending byte is not a read/write
  1011. // register, but it has to be in softpci because the hotplug
  1012. // simulator needs to write to it.
  1013. //
  1014. if (Type == TYPE_HOTPLUG_BRIDGE) {
  1015. commonConfig->DeviceSpecific[2] = 0xff; // DWORD Select
  1016. commonConfig->DeviceSpecific[3] = 0xff; // Pending
  1017. commonConfig->DeviceSpecific[4] = 0xff; // Data
  1018. commonConfig->DeviceSpecific[5] = 0xff;
  1019. commonConfig->DeviceSpecific[6] = 0xff;
  1020. commonConfig->DeviceSpecific[7] = 0xff;
  1021. }
  1022. break;
  1023. }
  1024. //
  1025. // Now set our default config
  1026. //
  1027. RtlCopyMemory(&config->Default, &config->Current, sizeof(PCI_COMMON_CONFIG));
  1028. }
  1029. ULONGLONG
  1030. SoftPCI_GetLengthFromBar(
  1031. ULONGLONG BaseAddressRegister
  1032. )
  1033. /*++
  1034. Routine Description:
  1035. STOLEN FROM PCI.SYS and modified to support 64 bit bars
  1036. Given the contents of a PCI Base Address Register, after it
  1037. has been written with all ones, this routine calculates the
  1038. length (and alignment) requirement for this BAR.
  1039. This method for determining requirements is described in
  1040. section 6.2.5.1 of the PCI Specification (Rev 2.1).
  1041. Arguments:
  1042. BaseAddressRegister contains something.
  1043. Return Value:
  1044. Returns the length of the resource requirement. This will be a number
  1045. in the range 0 thru 0x80000000 (0 thru 0x8000000000000000 on 64bit bar).
  1046. --*/
  1047. {
  1048. ULONGLONG Length;
  1049. //
  1050. // A number of least significant bits should be ignored in the
  1051. // determination of the length. These are flag bits, the number
  1052. // of bits is dependent on the type of the resource.
  1053. //
  1054. if (BaseAddressRegister & PCI_ADDRESS_IO_SPACE) {
  1055. //
  1056. // PCI IO space.
  1057. //
  1058. BaseAddressRegister &= PCI_ADDRESS_IO_ADDRESS_MASK;
  1059. } else {
  1060. //
  1061. // PCI Memory space.
  1062. //
  1063. //BaseAddressRegister &= PCI_ADDRESS_MEMORY_ADDRESS_MASK;
  1064. BaseAddressRegister &= 0xfffffffffffffff0;
  1065. }
  1066. //
  1067. // BaseAddressRegister now contains the maximum base address
  1068. // this device can reside at and still exist below the top of
  1069. // memory.
  1070. //
  1071. // The value 0xffffffff was written to the BAR. The device will
  1072. // have adjusted this value to the maximum it can really use.
  1073. //
  1074. // Length MUST be a power of 2.
  1075. //
  1076. // For most devices, h/w will simply have cleared bits from the
  1077. // least significant bit positions so that the address 0xffffffff
  1078. // is adjusted to accomodate the length. eg: if the new value is
  1079. // 0xffffff00, the device requires 256 bytes.
  1080. //
  1081. // The difference between the original and new values is the length (-1).
  1082. //
  1083. // For example, if the value fead back from the BAR is 0xffff0000,
  1084. // the length of this resource is
  1085. //
  1086. // 0xffffffff - 0xffff0000 + 1
  1087. // = 0x0000ffff + 1
  1088. // = 0x00010000
  1089. //
  1090. // ie 64KB.
  1091. //
  1092. // Some devices cannot reside at the top of PCI address space. These
  1093. // devices will have adjusted the value such that length bytes are
  1094. // accomodated below the highest address. For example, if a device
  1095. // must reside below 1MB, and occupies 256 bytes, the value will now
  1096. // be 0x000fff00.
  1097. //
  1098. // In the first case, length can be calculated as-
  1099. //
  1100. Length = (0xffffffffffffffff - BaseAddressRegister) + 1;
  1101. if (((Length - 1) & Length) != 0) {
  1102. //
  1103. // We didn't end up with a power of two, must be the latter
  1104. // case, we will have to scan for it.
  1105. //
  1106. Length = 4; // start with minimum possible
  1107. while ((Length | BaseAddressRegister) != BaseAddressRegister) {
  1108. //
  1109. // Length *= 2, note we will eventually drop out of this
  1110. // loop for one of two reasons (a) because we found the
  1111. // length, or (b) because Length left shifted off the end
  1112. // and became 0.
  1113. //
  1114. Length <<= 1;
  1115. }
  1116. }
  1117. //
  1118. // Check that we got something.
  1119. //
  1120. return Length;
  1121. }
  1122. BOOL
  1123. SoftPCI_ReadWriteConfigSpace(
  1124. IN PPCI_DN Device,
  1125. IN ULONG Offset,
  1126. IN ULONG Length,
  1127. IN OUT PVOID Buffer,
  1128. IN BOOL WriteConfig
  1129. )
  1130. {
  1131. /*++
  1132. Abstract:
  1133. This is the function used to send an IOCTL telling the PCIDRV driver to read or write config space.
  1134. Arguments:
  1135. Device - device we are going to mess with
  1136. Offset - offset in config space to start at
  1137. Length - length of the read or write
  1138. Buffer - pointer to data to be written, or location to store value read
  1139. WriteConfig - boolean value indicating write if true, or read if false
  1140. Return Value:
  1141. TRUE if success
  1142. FALSE if not
  1143. --*/
  1144. BOOL status = FALSE, success = FALSE;
  1145. ULONG bytesReturned = 0;
  1146. SOFTPCI_RW_CONTEXT context;
  1147. context.WriteConfig = ((WriteConfig == TRUE) ? SoftPciWriteConfig : SoftPciReadConfig);
  1148. context.Bus = Device->Bus;
  1149. context.Slot.AsUSHORT = Device->Slot.AsUSHORT;
  1150. context.Offset = Offset;
  1151. context.Data = Buffer;
  1152. //
  1153. // Call our driver
  1154. //
  1155. status = DeviceIoControl(g_DriverHandle,
  1156. (DWORD) SOFTPCI_IOCTL_RW_CONFIG,
  1157. &context,
  1158. sizeof(SOFTPCI_RW_CONTEXT),
  1159. Buffer,
  1160. Length,
  1161. &bytesReturned,
  1162. NULL
  1163. );
  1164. if (!status) {
  1165. //
  1166. // Something failed
  1167. //
  1168. wprintf(TEXT("DeviceIoControl() Failed! 0x%x\n"), GetLastError());
  1169. }
  1170. return status;
  1171. }