Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1251 lines
42 KiB

  1. /*++
  2. Copyright (c) 1993 Weitek Corporation
  3. Module Name:
  4. pci.c
  5. Abstract:
  6. This module contains PCI code for the Weitek P9 miniport device driver.
  7. Environment:
  8. Kernel mode
  9. Revision History may be found at the end of this file.
  10. --*/
  11. #include "p9.h"
  12. #include "p9gbl.h"
  13. #include "p9000.h"
  14. #include "pci.h"
  15. #include "vga.h"
  16. #include "p91regs.h"
  17. //
  18. // OEM specific static data.
  19. //
  20. extern VOID
  21. VLSetModeP91(
  22. PHW_DEVICE_EXTENSION HwDeviceExtension
  23. );
  24. extern VOID VLEnableP91(
  25. PHW_DEVICE_EXTENSION HwDeviceExtension
  26. );
  27. VIDEO_ACCESS_RANGE Pci9001DefDACRegRange[] =
  28. {
  29. {
  30. RS_0_PCI_9001_ADDR, // Low address
  31. 0x00000000, // Hi address
  32. 0x01, // length
  33. 1, // Is range in i/o space?
  34. 1, // Range should be visible
  35. 1 // Range should be shareable
  36. },
  37. {
  38. RS_1_PCI_9001_ADDR, // Low address
  39. 0x00000000, // Hi address
  40. 0x01, // length
  41. 1, // Is range in i/o space?
  42. 1, // Range should be visible
  43. 1 // Range should be shareable
  44. },
  45. {
  46. RS_2_PCI_9001_ADDR, // Low address
  47. 0x00000000, // Hi address
  48. 0x01, // length
  49. 1, // Is range in i/o space?
  50. 1, // Range should be visible
  51. 1 // Range should be shareable
  52. },
  53. {
  54. RS_3_PCI_9001_ADDR, // Low address
  55. 0x00000000, // Hi address
  56. 0x01, // length
  57. 1, // Is range in i/o space?
  58. 1, // Range should be visible
  59. 1 // Range should be shareable
  60. },
  61. {
  62. RS_4_PCI_9001_ADDR, // Low address
  63. 0x00000000, // Hi address
  64. 0x01, // length
  65. 1, // Is range in i/o space?
  66. 1, // Range should be visible
  67. 1 // Range should be shareable
  68. },
  69. {
  70. RS_5_PCI_9001_ADDR, // Low address
  71. 0x00000000, // Hi address
  72. 0x01, // length
  73. 1, // Is range in i/o space?
  74. 1, // Range should be visible
  75. 1 // Range should be shareable
  76. },
  77. {
  78. RS_6_PCI_9001_ADDR, // Low address
  79. 0x00000000, // Hi address
  80. 0x01, // length
  81. 1, // Is range in i/o space?
  82. 1, // Range should be visible
  83. 1 // Range should be shareable
  84. },
  85. {
  86. RS_7_PCI_9001_ADDR, // Low address
  87. 0x00000000, // Hi address
  88. 0x01, // length
  89. 1, // Is range in i/o space?
  90. 1, // Range should be visible
  91. 1 // Range should be shareable
  92. },
  93. {
  94. RS_8_PCI_9001_ADDR, // Low address
  95. 0x00000000, // Hi address
  96. 0x01, // length
  97. 1, // Is range in i/o space?
  98. 1, // Range should be visible
  99. 1 // Range should be shareable
  100. },
  101. {
  102. RS_9_PCI_9001_ADDR, // Low address
  103. 0x00000000, // Hi address
  104. 0x01, // length
  105. 1, // Is range in i/o space?
  106. 1, // Range should be visible
  107. 1 // Range should be shareable
  108. },
  109. {
  110. RS_A_PCI_9001_ADDR, // Low address
  111. 0x00000000, // Hi address
  112. 0x01, // length
  113. 1, // Is range in i/o space?
  114. 1, // Range should be visible
  115. 1 // Range should be shareable
  116. },
  117. {
  118. RS_B_PCI_9001_ADDR, // Low address
  119. 0x00000000, // Hi address
  120. 0x01, // length
  121. 1, // Is range in i/o space?
  122. 1, // Range should be visible
  123. 1 // Range should be shareable
  124. },
  125. {
  126. RS_C_PCI_9001_ADDR, // Low address
  127. 0x00000000, // Hi address
  128. 0x01, // length
  129. 1, // Is range in i/o space?
  130. 1, // Range should be visible
  131. 1 // Range should be shareable
  132. },
  133. {
  134. RS_D_PCI_9001_ADDR, // Low address
  135. 0x00000000, // Hi address
  136. 0x01, // length
  137. 1, // Is range in i/o space?
  138. 1, // Range should be visible
  139. 1 // Range should be shareable
  140. },
  141. {
  142. RS_E_PCI_9001_ADDR, // Low address
  143. 0x00000000, // Hi address
  144. 0x01, // length
  145. 1, // Is range in i/o space?
  146. 1, // Range should be visible
  147. 1 // Range should be shareable
  148. },
  149. {
  150. RS_F_PCI_9001_ADDR, // Low address
  151. 0x00000000, // Hi address
  152. 0x01, // length
  153. 1, // Is range in i/o space?
  154. 1, // Range should be visible
  155. 1 // Range should be shareable
  156. }
  157. };
  158. VIDEO_ACCESS_RANGE Pci9002DefDACRegRange[] =
  159. {
  160. {
  161. RS_0_PCI_9002_ADDR, // Low address
  162. 0x00000000, // Hi address
  163. 0x01, // length
  164. 1, // Is range in i/o space?
  165. 1, // Range should be visible
  166. 1 // Range should be shareable
  167. },
  168. {
  169. RS_1_PCI_9002_ADDR, // Low address
  170. 0x00000000, // Hi address
  171. 0x01, // length
  172. 1, // Is range in i/o space?
  173. 1, // Range should be visible
  174. 1 // Range should be shareable
  175. },
  176. {
  177. RS_2_PCI_9002_ADDR, // Low address
  178. 0x00000000, // Hi address
  179. 0x01, // length
  180. 1, // Is range in i/o space?
  181. 1, // Range should be visible
  182. 1 // Range should be shareable
  183. },
  184. {
  185. RS_3_PCI_9002_ADDR, // Low address
  186. 0x00000000, // Hi address
  187. 0x01, // length
  188. 1, // Is range in i/o space?
  189. 1, // Range should be visible
  190. 1 // Range should be shareable
  191. },
  192. {
  193. RS_4_PCI_9002_ADDR, // Low address
  194. 0x00000000, // Hi address
  195. 0x01, // length
  196. 1, // Is range in i/o space?
  197. 1, // Range should be visible
  198. 1 // Range should be shareable
  199. },
  200. {
  201. RS_5_PCI_9002_ADDR, // Low address
  202. 0x00000000, // Hi address
  203. 0x01, // length
  204. 1, // Is range in i/o space?
  205. 1, // Range should be visible
  206. 1 // Range should be shareable
  207. },
  208. {
  209. RS_6_PCI_9002_ADDR, // Low address
  210. 0x00000000, // Hi address
  211. 0x01, // length
  212. 1, // Is range in i/o space?
  213. 1, // Range should be visible
  214. 1 // Range should be shareable
  215. },
  216. {
  217. RS_7_PCI_9002_ADDR, // Low address
  218. 0x00000000, // Hi address
  219. 0x01, // length
  220. 1, // Is range in i/o space?
  221. 1, // Range should be visible
  222. 1 // Range should be shareable
  223. },
  224. {
  225. RS_8_PCI_9002_ADDR, // Low address
  226. 0x00000000, // Hi address
  227. 0x01, // length
  228. 1, // Is range in i/o space?
  229. 1, // Range should be visible
  230. 1 // Range should be shareable
  231. },
  232. {
  233. RS_9_PCI_9002_ADDR, // Low address
  234. 0x00000000, // Hi address
  235. 0x01, // length
  236. 1, // Is range in i/o space?
  237. 1, // Range should be visible
  238. 1 // Range should be shareable
  239. },
  240. {
  241. RS_A_PCI_9002_ADDR, // Low address
  242. 0x00000000, // Hi address
  243. 0x01, // length
  244. 1, // Is range in i/o space?
  245. 1, // Range should be visible
  246. 1 // Range should be shareable
  247. },
  248. {
  249. RS_B_PCI_9002_ADDR, // Low address
  250. 0x00000000, // Hi address
  251. 0x01, // length
  252. 1, // Is range in i/o space?
  253. 1, // Range should be visible
  254. 1 // Range should be shareable
  255. },
  256. {
  257. RS_C_PCI_9002_ADDR, // Low address
  258. 0x00000000, // Hi address
  259. 0x01, // length
  260. 1, // Is range in i/o space?
  261. 1, // Range should be visible
  262. 1 // Range should be shareable
  263. },
  264. {
  265. RS_D_PCI_9002_ADDR, // Low address
  266. 0x00000000, // Hi address
  267. 0x01, // length
  268. 1, // Is range in i/o space?
  269. 1, // Range should be visible
  270. 1 // Range should be shareable
  271. },
  272. {
  273. RS_E_PCI_9002_ADDR, // Low address
  274. 0x00000000, // Hi address
  275. 0x01, // length
  276. 1, // Is range in i/o space?
  277. 1, // Range should be visible
  278. 1 // Range should be shareable
  279. },
  280. {
  281. RS_F_PCI_9002_ADDR, // Low address
  282. 0x00000000, // Hi address
  283. 0x01, // length
  284. 1, // Is range in i/o space?
  285. 1, // Range should be visible
  286. 1 // Range should be shareable
  287. }
  288. };
  289. /******************************************************************************
  290. ** bIntergraphBoard
  291. *
  292. * PARAMETERS: HwDeviceExtension
  293. *
  294. * DESCRIPTION: Determine if we're trying to init an Intergraph Board
  295. *
  296. * RETURNS: TRUE - if this is an Intergraph Board
  297. * FALSE - if this is not an Intergraph Board
  298. *
  299. * CREATED: 02/20/95 13:33:23
  300. *
  301. * BY: c-jeffn
  302. *
  303. * copyright (c) 1995, Newman Consulting
  304. *
  305. ******************************************************************************/
  306. BOOLEAN
  307. bIntergraphBoard(
  308. PHW_DEVICE_EXTENSION HwDeviceExtension
  309. )
  310. {
  311. ULONG ulRet;
  312. UCHAR jConfig66, jOEMId, *pjOEMId;
  313. VP_STATUS vpStatus;
  314. VIDEO_ACCESS_RANGE AccessRange;
  315. BOOLEAN bRet;
  316. VideoDebugPrint((2, "P9!bIntergraphBoard - Entry\n"));
  317. // Note that the P9100 must be in native mode before this function
  318. // is called.
  319. bRet = FALSE;
  320. // Test to see if the P9100 indicates external io device is there
  321. // If not, can't be Intergraph board
  322. if ( (HwDeviceExtension->p91State.ulPuConfig & P91_PUC_EXT_IO) == 0 )
  323. goto exit;
  324. // Set Bit 4 of Config 66. This will allow access to the Intergraph
  325. // Specific registers.
  326. jConfig66 = 0x10;
  327. ulRet = VideoPortSetBusData(HwDeviceExtension,
  328. PCIConfiguration,
  329. HwDeviceExtension->PciSlotNum,
  330. &jConfig66,
  331. 0x42,
  332. sizeof (UCHAR));
  333. if (ulRet != 1)
  334. {
  335. VideoDebugPrint((2, "P9!bIntergraphBoard - failed VideoPortSetBusData\n"));
  336. VideoDebugPrint((2, "\tulRet: %x\n", ulRet));
  337. goto exit;
  338. }
  339. // Check P9100 register 0x208 for ID in native mode
  340. ulRet = P9_RD_REG(P91_EXT_IO_ID); // Get the external io id value
  341. jOEMId = (UCHAR)(ulRet >> 16); // per Weitek programmer's manual
  342. if (jOEMId == 0xFE) // This is the id assigned to Intergraph
  343. bRet = TRUE;
  344. // Need to reset Config register 66 bit 4.
  345. jConfig66 = 0x00;
  346. ulRet = VideoPortSetBusData(HwDeviceExtension,
  347. PCIConfiguration,
  348. HwDeviceExtension->PciSlotNum,
  349. &jConfig66,
  350. 0x42,
  351. sizeof (UCHAR));
  352. exit:
  353. VideoDebugPrint((2, "P9!bIntergraphBoard - Exit: %x\n", bRet));
  354. return (bRet);
  355. }
  356. //
  357. // this thing was 0. PNP forces fix since the system now put the IO
  358. // resources at index 1 in the VIDEO_ACCESS_RANGE returned via
  359. // VideoPortGetAccessRanges().
  360. //
  361. #define IO_ACCESS_INDEX 1
  362. #define VGABIOS_ACCESS_INDEX 2
  363. BOOLEAN
  364. PciGetBaseAddr(
  365. PHW_DEVICE_EXTENSION HwDeviceExtension
  366. )
  367. /*++
  368. Routine Description:
  369. Perform board detection and if present return the P9 base address.
  370. Arguments:
  371. HwDeviceExtension - Pointer to the miniport driver's device extension.
  372. Return Value:
  373. TRUE - Board found, P9 and Frame buffer address info was placed in
  374. the device extension. PCI extended base address was placed in the
  375. device extension.
  376. FALSE - Board not found.
  377. --*/
  378. {
  379. VIDEO_ACCESS_RANGE PciAccessRange[3];
  380. PVIDEO_ACCESS_RANGE DefaultDACRegRange;
  381. ULONG ulTempAddr;
  382. PUCHAR pucBiosAddr;
  383. PUCHAR pucBoardAddr;
  384. ULONG ulTemp;
  385. LONG i;
  386. VP_STATUS status;
  387. ULONG wcpID;
  388. VideoPortZeroMemory(PciAccessRange, 3 * sizeof(VIDEO_ACCESS_RANGE));
  389. VideoDebugPrint((2, "PciGetbaseAddr() ENTRY\n"));
  390. //
  391. // Only the viper p9000 works on the Siemens boxes
  392. //
  393. if (HwDeviceExtension->MachineType == SIEMENS
  394. || HwDeviceExtension->MachineType == SIEMENS_P9100_VLB)
  395. {
  396. VideoDebugPrint((1, "PciGetbaseAddr() Failed, line %d\n", __LINE__));
  397. return FALSE;
  398. }
  399. //
  400. // See if the PCI HAL can locate a Weitek 9001 PCI Board.
  401. //
  402. //
  403. // First check for a P9100
  404. //
  405. if (PciFindDevice(HwDeviceExtension,
  406. WTK_9100_ID,
  407. WTK_VENDOR_ID,
  408. &HwDeviceExtension->PciSlotNum))
  409. {
  410. wcpID = P9100_ID;
  411. HwDeviceExtension->usBusType = PCI;
  412. // Just a hack to get things working.
  413. // NOTE: !!! WE should really do the detection.
  414. HwDeviceExtension->p91State.bVideoPowerEnabled = FALSE;
  415. // Now make sure we are looking for a P9100, if were not
  416. // then fail.
  417. if (HwDeviceExtension->P9CoprocInfo.CoprocId != P9100_ID)
  418. {
  419. VideoDebugPrint((1, "Not a 9100, even though PCIFindDevice() thinks it is\n"));
  420. return(FALSE);
  421. }
  422. #ifdef _MIPS_
  423. //
  424. // SNI platform recognition and specific stuff
  425. //
  426. {
  427. extern VP_STATUS GetCPUIdCallback(
  428. PVOID HwDeviceExtension,
  429. PVOID Context,
  430. VIDEO_DEVICE_DATA_TYPE DeviceDataType,
  431. PVOID Identifier,
  432. ULONG IdentifierLength,
  433. PVOID ConfigurationData,
  434. ULONG ConfigurationDataLength,
  435. PVOID ComponentInformation,
  436. ULONG ComponentInformationLength
  437. );
  438. if(VideoPortIsCpu(L"RM200PCI")
  439. || VideoPortIsCpu(L"RM300PCI")
  440. || VideoPortIsCpu(L"RM300PCI MP")
  441. || VideoPortIsCpu(L"RM400PCI")
  442. || VideoPortIsCpu(L"RM4x0PCI"))
  443. {
  444. // adjust the VGA physical address with the E/ISA I/O space
  445. DriverAccessRanges[1].RangeStart.LowPart += 0x14000000 ;
  446. HwDeviceExtension->MachineType = SIEMENS_P9100_PCi;
  447. }
  448. }
  449. #endif
  450. }
  451. else if (PciFindDevice(HwDeviceExtension,
  452. WTK_9001_ID,
  453. WTK_VENDOR_ID,
  454. &HwDeviceExtension->PciSlotNum))
  455. {
  456. wcpID = P9000_ID;
  457. // Now make sure we are looking for a P9000, if were not
  458. // then fail.
  459. if (HwDeviceExtension->P9CoprocInfo.CoprocId != P9000_ID)
  460. {
  461. VideoDebugPrint((1, "PciGetbaseAddr() Failed !P9000, line %d\n", __LINE__));
  462. return(FALSE);
  463. }
  464. VideoDebugPrint((2, "PciGetbaseAddr() This is a P900X\n"));
  465. //
  466. // Read the config space to determine if
  467. // this is Rev 1 or 2. This will determine at which addresses
  468. // the DAC registers are mapped.
  469. //
  470. if (!VideoPortGetBusData(HwDeviceExtension,
  471. PCIConfiguration,
  472. HwDeviceExtension->PciSlotNum,
  473. &ulTemp,
  474. P9001_REV_ID,
  475. sizeof(ulTemp)))
  476. {
  477. VideoDebugPrint((1, "PciGetbaseAddr() Failed, DAC weirdness, line %d\n", __LINE__));
  478. return(FALSE);
  479. }
  480. //
  481. // Got the 9001 rev id. Choose the appropriate table of DAC register
  482. // addresses.
  483. //
  484. switch((UCHAR) (ulTemp))
  485. {
  486. case 1 :
  487. VideoDebugPrint((2, "PciGetbaseAddr(), DAC id is 1\n"));
  488. //
  489. // This is a Rev 1 9001, which uses the standard VL DAC
  490. // Addresses. All known rev 1 implementations use the
  491. // Weitek 5286 VGA chip.
  492. //
  493. DefaultDACRegRange = VLDefDACRegRange;
  494. HwDeviceExtension->AdapterDesc.bWtk5x86 = TRUE;
  495. break;
  496. case 2 :
  497. default:
  498. VideoDebugPrint((2, "PciGetbaseAddr(), DAC id is 2 or default\n"));
  499. //
  500. // This is a Rev 2 9001. Set up the table of DAC register
  501. // offsets accordingly.
  502. //
  503. DefaultDACRegRange = Pci9001DefDACRegRange;
  504. //
  505. // A Rev 2 9001 is present. Get the BIOS ROM address from the
  506. // PCI configuration space so we can do a ROM scan to
  507. // determine if this is a Viper PCI adapter.
  508. //
  509. PciAccessRange[IO_ACCESS_INDEX].RangeStart.LowPart = 0;
  510. PciAccessRange[IO_ACCESS_INDEX].RangeStart.HighPart = 0;
  511. if (VideoPortGetBusData(HwDeviceExtension,
  512. PCIConfiguration,
  513. HwDeviceExtension->PciSlotNum,
  514. &PciAccessRange[IO_ACCESS_INDEX].RangeStart.LowPart,
  515. P9001_BIOS_BASE_ADDR,
  516. sizeof(ULONG)) == 0)
  517. {
  518. VideoDebugPrint((1, "PciGetbaseAddr() Failed. ROM bios not P9001, line %d\n", __LINE__));
  519. return FALSE;
  520. }
  521. if (PciAccessRange[IO_ACCESS_INDEX].RangeStart.LowPart)
  522. {
  523. //
  524. // We found an address for the BIOS. Verify it.
  525. //
  526. // Set up the access range so we can map out the BIOS ROM
  527. // space. This will allow us to scan the ROM and detect the
  528. // presence of a Viper PCI adapter.
  529. //
  530. PciAccessRange[IO_ACCESS_INDEX].RangeInIoSpace = FALSE;
  531. PciAccessRange[IO_ACCESS_INDEX].RangeVisible = TRUE;
  532. PciAccessRange[IO_ACCESS_INDEX].RangeShareable = TRUE;
  533. PciAccessRange[IO_ACCESS_INDEX].RangeLength = 0x1000;
  534. //
  535. // Check to see if another miniport driver has allocated the
  536. // BIOS' memory space.
  537. //
  538. if (VideoPortVerifyAccessRanges(HwDeviceExtension,
  539. 1L,
  540. PciAccessRange) != NO_ERROR)
  541. {
  542. PciAccessRange[IO_ACCESS_INDEX].RangeStart.LowPart = 0;
  543. }
  544. }
  545. if (PciAccessRange[IO_ACCESS_INDEX].RangeStart.LowPart == 0)
  546. {
  547. status = VideoPortGetAccessRanges(HwDeviceExtension,
  548. 0,
  549. NULL,
  550. 3,
  551. PciAccessRange,
  552. NULL,
  553. NULL,
  554. &HwDeviceExtension->PciSlotNum);
  555. if (status != NO_ERROR)
  556. {
  557. VideoDebugPrint((1, "PciGetbaseAddr() Failed, GetAccessRanges(), line %d, status:%x\n", __LINE__, status));
  558. return(FALSE);
  559. }
  560. }
  561. //
  562. // Map in the BIOS' memory space. If it can't be mapped,
  563. // return an error.
  564. //
  565. PciAccessRange[VGABIOS_ACCESS_INDEX].RangeStart.LowPart = 0xC0000;
  566. PciAccessRange[VGABIOS_ACCESS_INDEX].RangeStart.HighPart = 0x0000;
  567. PciAccessRange[VGABIOS_ACCESS_INDEX].RangeLength = BIOS_RANGE_LEN;
  568. PciAccessRange[VGABIOS_ACCESS_INDEX].RangeInIoSpace = FALSE;
  569. VideoDebugPrint((1, "PciGetbaseAddr() about to get BIOS address, line %d, status:%x\n", __LINE__, status));
  570. if ((pucBiosAddr =
  571. VideoPortGetDeviceBase(HwDeviceExtension,
  572. PciAccessRange[VGABIOS_ACCESS_INDEX].RangeStart,
  573. PciAccessRange[VGABIOS_ACCESS_INDEX].RangeLength,
  574. PciAccessRange[VGABIOS_ACCESS_INDEX].RangeInIoSpace)) == 0)
  575. {
  576. VideoDebugPrint((1, "PciGetbaseAddr() Failed on VGA bios, line %d\n", __LINE__));
  577. return(FALSE);
  578. }
  579. //
  580. // Enable the Adapter BIOS.
  581. //
  582. ulTemp = PciAccessRange[VGABIOS_ACCESS_INDEX].RangeStart.LowPart | PCI_BIOS_ENB;
  583. VideoDebugPrint((1, "PciGetbaseAddr() about to enable bios, line %d, status:%x\n", __LINE__, status));
  584. VideoPortSetBusData(HwDeviceExtension,
  585. PCIConfiguration,
  586. HwDeviceExtension->PciSlotNum,
  587. &ulTemp,
  588. P9001_BIOS_BASE_ADDR,
  589. sizeof(ULONG));
  590. VideoDebugPrint((1, "PciGetbaseAddr() about to scan rom, line %d, status:%x\n", __LINE__, status));
  591. if (VideoPortScanRom(HwDeviceExtension,
  592. pucBiosAddr,
  593. BIOS_RANGE_LEN,
  594. VIPER_ID_STR))
  595. {
  596. //
  597. // A Viper PCI is present, use the Viper set mode,
  598. // enable/disable video function pointers, and clk
  599. // divisor values. Also, Viper PCI does not
  600. // use a Weitek VGA.
  601. //
  602. HwDeviceExtension->AdapterDesc.OEMSetMode = ViperSetMode;
  603. HwDeviceExtension->AdapterDesc.P9EnableVideo =
  604. ViperPciP9Enable;
  605. HwDeviceExtension->AdapterDesc.P9DisableVideo =
  606. ViperPciP9Disable;
  607. HwDeviceExtension->AdapterDesc.iClkDiv = 4;
  608. HwDeviceExtension->AdapterDesc.bWtk5x86 = FALSE;
  609. }
  610. else
  611. {
  612. //
  613. // All non-Viper Rev 2 implementations use a Weitek
  614. // 5286 VGA chip.
  615. //
  616. HwDeviceExtension->AdapterDesc.bWtk5x86 = TRUE;
  617. }
  618. //
  619. // Restore the BIOS register to it's original value.
  620. //
  621. VideoDebugPrint((1, "PciGetbaseAddr() about to restore, line %d, status:%x\n", __LINE__, status));
  622. VideoPortSetBusData(HwDeviceExtension,
  623. PCIConfiguration,
  624. HwDeviceExtension->PciSlotNum,
  625. &ulTempAddr,
  626. P9001_BIOS_BASE_ADDR,
  627. sizeof(ULONG));
  628. VideoPortFreeDeviceBase(HwDeviceExtension, (PVOID) pucBiosAddr);
  629. break;
  630. }
  631. }
  632. else if (PciFindDevice(HwDeviceExtension, // Search for a Weitek 9002.
  633. WTK_9002_ID,
  634. WTK_VENDOR_ID,
  635. &HwDeviceExtension->PciSlotNum))
  636. {
  637. wcpID = P9000_ID;
  638. // Now make sure we are looking for a P9000, if were not
  639. // then fail.
  640. if (HwDeviceExtension->P9CoprocInfo.CoprocId != P9000_ID)
  641. {
  642. VideoDebugPrint((1, "PciGetbaseAddr() Failed, not a P9002, line %d\n", __LINE__));
  643. return(FALSE);
  644. }
  645. //
  646. // Found a 9002 board. Set up the table of DAC addresses
  647. // accordingly.
  648. //
  649. DefaultDACRegRange = Pci9002DefDACRegRange;
  650. }
  651. else
  652. {
  653. //
  654. // No Weitek PCI devices were found, return an error.
  655. //
  656. VideoDebugPrint((1, "PciGetbaseAddr() Failed, line %d\n", __LINE__));
  657. return(FALSE);
  658. }
  659. //
  660. // Get the base address of the adapter.
  661. // Some machines rely on the address not changing - if the address changes
  662. // the machine randomly appears to corrupt memory.
  663. // So use the pre-configured address if it is available.
  664. //
  665. HwDeviceExtension->P9PhysAddr.LowPart = 0;
  666. VideoPortGetBusData(HwDeviceExtension,
  667. PCIConfiguration,
  668. HwDeviceExtension->PciSlotNum,
  669. &HwDeviceExtension->P9PhysAddr.LowPart,
  670. P9001_BASE_ADDR,
  671. sizeof(ULONG));
  672. if (HwDeviceExtension->P9PhysAddr.LowPart == 0)
  673. {
  674. IO_RESOURCE_DESCRIPTOR ioResource = {
  675. IO_RESOURCE_PREFERRED,
  676. CmResourceTypeMemory,
  677. CmResourceShareDeviceExclusive,
  678. 0,
  679. CM_RESOURCE_MEMORY_READ_WRITE,
  680. 0,
  681. {
  682. RESERVE_PCI_ADDRESS_SPACE, // Length
  683. RESERVE_PCI_ADDRESS_SPACE, // Alignment
  684. { 0x10000000, 0 }, // Minimum start address
  685. { 0xefffffff, 0} // Maximum end address
  686. }
  687. };
  688. status = VideoPortGetAccessRanges(HwDeviceExtension,
  689. 1,
  690. &ioResource,
  691. 3,
  692. PciAccessRange,
  693. NULL,
  694. NULL,
  695. &HwDeviceExtension->PciSlotNum);
  696. if (status == NO_ERROR)
  697. {
  698. HwDeviceExtension->P9PhysAddr = PciAccessRange[IO_ACCESS_INDEX].RangeStart;
  699. //
  700. // Save the physical base address in the PCI config space.
  701. //
  702. VideoPortSetBusData(HwDeviceExtension,
  703. PCIConfiguration,
  704. HwDeviceExtension->PciSlotNum,
  705. &HwDeviceExtension->P9PhysAddr.LowPart,
  706. P9001_BASE_ADDR,
  707. sizeof(ULONG));
  708. }
  709. }
  710. if (HwDeviceExtension->P9PhysAddr.LowPart == 0)
  711. {
  712. VideoDebugPrint((1, "PciGetbaseAddr() Failed, line %d\n", __LINE__));
  713. return(FALSE);
  714. }
  715. //
  716. // The P9100 can access the DAC directly, so no I/O space needs to be
  717. // allocated for DAC access.
  718. //
  719. if (wcpID == P9000_ID)
  720. {
  721. status = VideoPortGetAccessRanges(HwDeviceExtension,
  722. 0,
  723. NULL,
  724. 3,
  725. PciAccessRange,
  726. NULL,
  727. NULL,
  728. &HwDeviceExtension->PciSlotNum);
  729. if (status == NO_ERROR)
  730. {
  731. HwDeviceExtension->P9001PhysicalAddress = PciAccessRange[IO_ACCESS_INDEX].RangeStart;
  732. }
  733. else
  734. {
  735. VideoDebugPrint((1, "VideoPortGetAccessRanges() Failed with status %x, line %d\n", status, __LINE__));
  736. return(FALSE);
  737. }
  738. //
  739. // If this is a 9002 board, map in and read the VGA id register.
  740. //
  741. if (DefaultDACRegRange == Pci9002DefDACRegRange)
  742. {
  743. //
  744. // Set up the access range so we can map out the VGA ID register.
  745. //
  746. PciAccessRange[IO_ACCESS_INDEX].RangeInIoSpace = TRUE;
  747. PciAccessRange[IO_ACCESS_INDEX].RangeVisible = TRUE;
  748. PciAccessRange[IO_ACCESS_INDEX].RangeShareable = TRUE;
  749. PciAccessRange[IO_ACCESS_INDEX].RangeLength = 1;
  750. PciAccessRange[IO_ACCESS_INDEX].RangeStart =
  751. HwDeviceExtension->P9001PhysicalAddress;
  752. PciAccessRange[IO_ACCESS_INDEX].RangeStart.LowPart += P9002_VGA_ID;
  753. //
  754. // Map in the VGA ID register. If it can't be mapped,
  755. // we can't determine the VGA type, so just use the default.
  756. //
  757. if ((pucBoardAddr =
  758. VideoPortGetDeviceBase(HwDeviceExtension,
  759. PciAccessRange[IO_ACCESS_INDEX].RangeStart,
  760. PciAccessRange[IO_ACCESS_INDEX].RangeLength,
  761. PciAccessRange[IO_ACCESS_INDEX].RangeInIoSpace)) != 0)
  762. {
  763. HwDeviceExtension->AdapterDesc.bWtk5x86 =
  764. (UCHAR)((VideoPortReadPortUchar(pucBoardAddr) & VGA_MSK) == WTK_VGA);
  765. VideoPortFreeDeviceBase(HwDeviceExtension,
  766. (PVOID) pucBoardAddr);
  767. }
  768. else
  769. {
  770. //
  771. // Assume this is a 5x86 VGA.
  772. //
  773. HwDeviceExtension->AdapterDesc.bWtk5x86 = TRUE;
  774. }
  775. }
  776. //
  777. // Compute the actual DAC register addresses relative to the PCI
  778. // base address.
  779. //
  780. for (i = 0; i < HwDeviceExtension->Dac.cDacRegs; i++)
  781. {
  782. //
  783. // If this is not a palette addr or data register, and the board
  784. // is not using the standard VL addresses, compute the register
  785. // address relative to the register base address.
  786. //
  787. if ((i > 3) && (DefaultDACRegRange != VLDefDACRegRange))
  788. {
  789. DefaultDACRegRange[i].RangeStart.LowPart +=
  790. HwDeviceExtension->P9001PhysicalAddress.LowPart;
  791. }
  792. }
  793. //
  794. // Copy the DAC register access range into the global list of access
  795. // ranges.
  796. //
  797. VideoPortMoveMemory(&DriverAccessRanges[NUM_DRIVER_ACCESS_RANGES],
  798. DefaultDACRegRange,
  799. sizeof(VIDEO_ACCESS_RANGE) *
  800. HwDeviceExtension->Dac.cDacRegs);
  801. //
  802. // This is a hack. Initialize an additional access range to map out
  803. // the entire 4K range of contiguous IO space starting at PCI_REG_BASE.
  804. // apparently the 9001 decodes accesses over this entire range rather
  805. // than the individual register offsets within this range.
  806. //
  807. //
  808. // Set up the access range so we can map the entire 4k IO range.
  809. //
  810. PciAccessRange[IO_ACCESS_INDEX].RangeInIoSpace = TRUE;
  811. PciAccessRange[IO_ACCESS_INDEX].RangeVisible = TRUE;
  812. PciAccessRange[IO_ACCESS_INDEX].RangeShareable = TRUE;
  813. PciAccessRange[IO_ACCESS_INDEX].RangeLength = P9001_IO_RANGE;
  814. PciAccessRange[IO_ACCESS_INDEX].RangeStart = HwDeviceExtension->P9001PhysicalAddress;
  815. VideoDebugPrint((1, "PciAccessRange[VGABIOS_ACCESS_INDEX].RangeStart.LowPart:%x\n",
  816. PciAccessRange[VGABIOS_ACCESS_INDEX].RangeStart.LowPart));
  817. VideoPortMoveMemory(&DriverAccessRanges[NUM_DRIVER_ACCESS_RANGES +
  818. NUM_DAC_ACCESS_RANGES],
  819. &PciAccessRange[IO_ACCESS_INDEX],
  820. sizeof(VIDEO_ACCESS_RANGE));
  821. } // end of "if (wcpID == P9000_ID)" block.
  822. return(TRUE);
  823. }
  824. BOOLEAN
  825. PciFindDevice(
  826. IN PHW_DEVICE_EXTENSION HwDeviceExtension,
  827. IN USHORT usDeviceId,
  828. IN USHORT usVendorId,
  829. IN OUT PULONG pulSlotNum
  830. )
  831. /*++
  832. Routine Description:
  833. Attempts to find a PCI device which matches the passed device id, vendor
  834. id and index.
  835. Arguments:
  836. HwDeviceExtension - Pointer to the device extension.
  837. usDeviceId - PCI Device Id.
  838. usVendorId - PCI Vendor Id.
  839. pulSlotNum - Input -> Starting Slot Number
  840. Output -> If found, the slot number of the matching device.
  841. Return Value:
  842. TRUE if device found.
  843. --*/
  844. {
  845. ULONG pciBuffer;
  846. PCI_SLOT_NUMBER slotData;
  847. PPCI_COMMON_CONFIG pciData;
  848. //
  849. //
  850. // typedef struct _PCI_SLOT_NUMBER {
  851. // union {
  852. // struct {
  853. // ULONG DeviceNumber:5;
  854. // ULONG FunctionNumber:3;
  855. // ULONG Reserved:24;
  856. // } bits;
  857. // ULONG AsULONG;
  858. // } u;
  859. // } PCI_SLOT_NUMBER, *PPCI_SLOT_NUMBER;
  860. //
  861. slotData.u.AsULONG = 0;
  862. pciData = (PPCI_COMMON_CONFIG) &pciBuffer;
  863. //
  864. // Look at each device.
  865. //
  866. *pulSlotNum = 0;
  867. slotData.u.bits.DeviceNumber = *pulSlotNum;
  868. slotData.u.bits.FunctionNumber = 0;
  869. if (VideoPortGetBusData(HwDeviceExtension,
  870. PCIConfiguration,
  871. slotData.u.AsULONG,
  872. (PVOID) pciData,
  873. 0,
  874. sizeof(ULONG)) == 0)
  875. {
  876. //
  877. // Out of functions. Go to next PCI bus.
  878. //
  879. return(FALSE);
  880. }
  881. if (pciData->VendorID == PCI_INVALID_VENDORID)
  882. {
  883. //
  884. // No PCI device, or no more functions on device
  885. // move to next PCI device.
  886. //
  887. return(FALSE);
  888. }
  889. if (pciData->VendorID == usVendorId &&
  890. pciData->DeviceID == usDeviceId)
  891. {
  892. *pulSlotNum = slotData.u.AsULONG;
  893. return(TRUE);
  894. }
  895. //
  896. // No matching PCI device was found.
  897. //
  898. return(FALSE);
  899. }
  900. BOOLEAN
  901. PciP9MemEnable(
  902. PHW_DEVICE_EXTENSION HwDeviceExtension
  903. )
  904. /*++
  905. Routine Description:
  906. Enable the physical memory and IO resources for PCI adapters.
  907. Arguments:
  908. HwDeviceExtension - Pointer to the miniport driver's device extension.
  909. Return Value:
  910. None.
  911. --*/
  912. {
  913. ULONG ulTemp;
  914. //
  915. // Read the PCI command register to determine if the memory/io
  916. // resources are enabled. If not, enable them.
  917. //
  918. if (!VideoPortGetBusData(HwDeviceExtension,
  919. PCIConfiguration,
  920. HwDeviceExtension->PciSlotNum,
  921. &ulTemp,
  922. P9001_CMD_REG,
  923. sizeof(ulTemp)))
  924. {
  925. return(FALSE);
  926. }
  927. else if (!(ulTemp & (P9001_MEM_ENB | P9001_IO_ENB)))
  928. {
  929. ulTemp |= (P9001_MEM_ENB | P9001_IO_ENB);
  930. if (!VideoPortSetBusData(HwDeviceExtension,
  931. PCIConfiguration,
  932. HwDeviceExtension->PciSlotNum,
  933. &ulTemp,
  934. P9001_CMD_REG,
  935. sizeof(ulTemp)))
  936. {
  937. return(FALSE);
  938. }
  939. }
  940. return(TRUE);
  941. }
  942. VOID
  943. ViperPciP9Enable(
  944. PHW_DEVICE_EXTENSION HwDeviceExtension
  945. )
  946. /*++
  947. Routine Description:
  948. Perform the OEM specific tasks necessary to enable the P9. These
  949. include memory mapping, setting the sync polarities, and enabling the
  950. P9 video output.
  951. Arguments:
  952. HwDeviceExtension - Pointer to the miniport driver's device extension.
  953. Return Value:
  954. None.
  955. --*/
  956. {
  957. USHORT holdit;
  958. //
  959. // Select external frequency, and clear the polarity bits.
  960. //
  961. holdit = VGA_RD_REG(MISCIN) | (MISCD | MISCC);
  962. holdit &= ~(VIPER_HSYNC_POL_MASK | VIPER_VSYNC_POL_MASK);
  963. //
  964. // Viper controls h and v sync polarities independently.
  965. //
  966. if (HwDeviceExtension->VideoData.vp == POSITIVE)
  967. {
  968. holdit |= VIPER_VSYNC_POL_MASK;
  969. }
  970. if (HwDeviceExtension->VideoData.hp == POSITIVE)
  971. {
  972. holdit |= VIPER_HSYNC_POL_MASK;
  973. }
  974. VGA_WR_REG(MISCOUT, holdit);
  975. //
  976. // If this is a Weitek VGA, unlock the VGA.
  977. //
  978. if (HwDeviceExtension->AdapterDesc.bWtk5x86)
  979. {
  980. UnlockVGARegs(HwDeviceExtension);
  981. }
  982. //
  983. // Enable P9 Video.
  984. //
  985. VGA_WR_REG(SEQ_INDEX_PORT, SEQ_OUTCNTL_INDEX);
  986. VGA_WR_REG(SEQ_DATA_PORT, (VGA_RD_REG(SEQ_DATA_PORT)) | P9_VIDEO_ENB);
  987. //
  988. // If this is a Weitek VGA, lock the VGA sequencer registers.
  989. //
  990. if (HwDeviceExtension->AdapterDesc.bWtk5x86)
  991. {
  992. LockVGARegs(HwDeviceExtension);
  993. }
  994. return;
  995. }
  996. BOOLEAN
  997. ViperPciP9Disable(
  998. PHW_DEVICE_EXTENSION HwDeviceExtension
  999. )
  1000. /*++
  1001. Routine Description:
  1002. Arguments:
  1003. HwDeviceExtension - Pointer to the miniport driver's device extension.
  1004. pPal - Pointer to the array of pallete entries.
  1005. StartIndex - Specifies the first pallete entry provided in pPal.
  1006. Count - Number of palette entries in pPal
  1007. Return Value:
  1008. TRUE, indicating no int10 is needed to complete the switch
  1009. --*/
  1010. {
  1011. //
  1012. // Unlock the VGA extended regs to disable P9 video output.
  1013. //
  1014. //
  1015. // If this is a Weitek VGA, unlock the VGA.
  1016. //
  1017. if (HwDeviceExtension->AdapterDesc.bWtk5x86)
  1018. {
  1019. UnlockVGARegs(HwDeviceExtension);
  1020. }
  1021. VGA_WR_REG(SEQ_INDEX_PORT, SEQ_OUTCNTL_INDEX);
  1022. VGA_WR_REG(SEQ_DATA_PORT, (VGA_RD_REG(SEQ_DATA_PORT)) & P9_VIDEO_DIS);
  1023. //
  1024. // Restore clock select bits.
  1025. //
  1026. VGA_WR_REG(MISCOUT, HwDeviceExtension->MiscRegState);
  1027. //
  1028. // If this is a Weitek VGA, lock the VGA sequencer registers.
  1029. //
  1030. if (HwDeviceExtension->AdapterDesc.bWtk5x86)
  1031. {
  1032. LockVGARegs(HwDeviceExtension);
  1033. }
  1034. return TRUE;
  1035. }