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.

636 lines
15 KiB

  1. //***************************************************************************
  2. //
  3. // Module Name:
  4. //
  5. // permmem.c
  6. //
  7. // Abstract:
  8. //
  9. // This module contains code to generate initialize table form ROM
  10. //
  11. // Environment:
  12. //
  13. // Kernel mode
  14. //
  15. //
  16. // Copyright (c) 1994-1998 3Dlabs Inc. Ltd. All rights reserved.
  17. // Copyright (c) 1995-1999 Microsoft Corporation. All Rights Reserved.
  18. //
  19. //***************************************************************************
  20. #include "permedia.h"
  21. #if defined(ALLOC_PRAGMA)
  22. #pragma alloc_text(PAGE,CopyROMInitializationTable)
  23. #pragma alloc_text(PAGE,GenerateInitializationTable)
  24. #pragma alloc_text(PAGE,ProcessInitializationTable)
  25. #pragma alloc_text(PAGE,IntergerToUnicode)
  26. #pragma alloc_text(PAGE,GetBiosVersion)
  27. #endif
  28. VOID
  29. CopyROMInitializationTable (
  30. PHW_DEVICE_EXTENSION hwDeviceExtension
  31. )
  32. /*++
  33. Routine Description:
  34. this function should be called for devices that have an expansion ROM
  35. which contains a register initialization table. The function assumes
  36. the ROM is present and enabled.
  37. Arguments:
  38. hwDeviceExtension -
  39. the device extension of the device whose ROM is to be read
  40. pvROMAddress -
  41. base address of the expansion ROM. This function assumes that
  42. the offset to the initialization table is defined at 0x1c from
  43. the beginning of ROM
  44. Return:
  45. void
  46. --*/
  47. {
  48. PULONG pulROMTable;
  49. PVOID pvROMAddress;
  50. ULONG ulTableOffset;
  51. ULONG cEntries;
  52. PULONG pul;
  53. ULONG ul;
  54. hwDeviceExtension->culTableEntries = 0;
  55. //
  56. // just use default values on NT4
  57. //
  58. if(hwDeviceExtension->NtVersion == NT4)
  59. return;
  60. //
  61. // the 2-byte offset to the initialization table is given at 0x1c
  62. // from the start of ROM
  63. //
  64. pvROMAddress = VideoPortGetRomImage( hwDeviceExtension,
  65. NULL,
  66. 0,
  67. 0x1c + 2 );
  68. if(pvROMAddress == NULL)
  69. {
  70. DEBUG_PRINT((1, "CopyROMinitializationTable: Can not access ROM\n"));
  71. return;
  72. }
  73. else if ( *(USHORT *)pvROMAddress != 0xAA55)
  74. {
  75. DEBUG_PRINT((1, "CopyROMinitializationTable: ROM Signature 0x%x is invalid\n",
  76. *(USHORT *)pvROMAddress ));
  77. return;
  78. }
  79. ulTableOffset = *((PUSHORT)(0x1c + (PCHAR)pvROMAddress));
  80. //
  81. // read the table header (32 bits)
  82. //
  83. pvROMAddress = VideoPortGetRomImage( hwDeviceExtension,
  84. NULL,
  85. 0,
  86. ulTableOffset + 4 );
  87. if(pvROMAddress == NULL)
  88. {
  89. DEBUG_PRINT((1, "CopyROMinitializationTable: Can not access ROM\n"));
  90. return;
  91. }
  92. pulROMTable = (PULONG)(ulTableOffset + (PCHAR)pvROMAddress);
  93. //
  94. // the table header (32 bits) has an identification code and a count
  95. // of the number of entries in the table
  96. //
  97. if((*pulROMTable >> 16) != 0x3d3d)
  98. {
  99. DEBUG_PRINT((1, "CopyROMinitializationTable: invalid initialization table header\n"));
  100. return;
  101. }
  102. //
  103. // number of register address & data pairs
  104. //
  105. cEntries = *pulROMTable & 0xffff;
  106. if(cEntries == 0)
  107. {
  108. DEBUG_PRINT((1, "CopyROMinitializationTable: empty initialization table\n"));
  109. return;
  110. }
  111. //
  112. // this assert, and the one after the copy should ensure we don't write
  113. // past the end of the table
  114. //
  115. P2_ASSERT(cEntries * sizeof(ULONG) * 2 <= sizeof(hwDeviceExtension->aulInitializationTable),
  116. "ERROR: too many initialization entries\n");
  117. pvROMAddress = VideoPortGetRomImage( hwDeviceExtension,
  118. NULL,
  119. 0,
  120. ulTableOffset + 4 + cEntries * sizeof(ULONG) * 2 );
  121. if(pvROMAddress == NULL)
  122. {
  123. DEBUG_PRINT((1, "CopyROMinitializationTable: Can not access ROM\n"));
  124. return;
  125. }
  126. //
  127. // each entry contains two 32-bit words
  128. //
  129. pul = hwDeviceExtension->aulInitializationTable;
  130. //
  131. // skip the 4 bype table header
  132. //
  133. pulROMTable = (PULONG)(ulTableOffset + 4 + (PCHAR)pvROMAddress);
  134. ul = cEntries << 1;
  135. while(ul--)
  136. {
  137. *pul++ = *pulROMTable;
  138. ++pulROMTable;
  139. }
  140. hwDeviceExtension->culTableEntries =
  141. (ULONG)(pul - (ULONG *)hwDeviceExtension->aulInitializationTable) >> 1;
  142. P2_ASSERT(cEntries == hwDeviceExtension->culTableEntries,
  143. "ERROR: generated different size init table to that expected\n");
  144. #if DBG
  145. //
  146. // output the initialization table
  147. //
  148. pul = hwDeviceExtension->aulInitializationTable;
  149. ul = hwDeviceExtension->culTableEntries;
  150. while(ul--)
  151. {
  152. ULONG ulReg;
  153. ULONG ulRegData;
  154. ulReg = *pul++;
  155. ulRegData = *pul++;
  156. DEBUG_PRINT((2, "CopyROMInitializationTable: initializing register %08.8Xh with %08.8Xh\n",
  157. ulReg, ulRegData));
  158. }
  159. #endif //DBG
  160. }
  161. VOID
  162. GenerateInitializationTable (
  163. PHW_DEVICE_EXTENSION hwDeviceExtension
  164. )
  165. /*++
  166. Routine Description:
  167. creates a register initialization table (called if we can't read one
  168. from ROM). If VGA is enabled the registers are already initialized so
  169. we just read them back, otherwise we have to use default values
  170. Arguments:
  171. hwDeviceExtension - the device for which we are creating the table
  172. Return:
  173. void
  174. --*/
  175. {
  176. ULONG cEntries;
  177. PULONG pul;
  178. ULONG ul;
  179. int i, j;
  180. P2_DECL;
  181. hwDeviceExtension->culTableEntries = 0;
  182. cEntries = 6;
  183. //
  184. // this assert, and the one after the copy should ensure we don't
  185. // write past the end of the table
  186. //
  187. P2_ASSERT(cEntries * sizeof(ULONG) * 2 <= sizeof(hwDeviceExtension->aulInitializationTable),
  188. "ERROR: to many initialization entries\n");
  189. //
  190. // each entry contains two 32-bit words
  191. //
  192. pul = hwDeviceExtension->aulInitializationTable;
  193. if(hwDeviceExtension->bVGAEnabled)
  194. {
  195. //
  196. // OK: no initialization table but VGA is running so our key
  197. // registers have been initialized to sensible values
  198. //
  199. DEBUG_PRINT((1, "GenerateinitializationTable: VGA enabled: reading registers\n"));
  200. //
  201. // key entries are: ROM control, Boot Address, Memory Config and
  202. // VStream Config
  203. //
  204. *pul++ = CTRL_REG_OFFSET(ROM_CONTROL);
  205. *pul++ = VideoPortReadRegisterUlong(ROM_CONTROL);
  206. *pul++ = CTRL_REG_OFFSET(BOOT_ADDRESS);
  207. *pul++ = VideoPortReadRegisterUlong(BOOT_ADDRESS);
  208. *pul++ = CTRL_REG_OFFSET(MEM_CONFIG);
  209. *pul++ = VideoPortReadRegisterUlong(MEM_CONFIG);
  210. *pul++ = CTRL_REG_OFFSET(VSTREAM_CONFIG);
  211. *pul++ = VideoPortReadRegisterUlong(VSTREAM_CONFIG);
  212. *pul++ = CTRL_REG_OFFSET(VIDEO_FIFO_CTL);
  213. *pul++ = VideoPortReadRegisterUlong(VIDEO_FIFO_CTL);
  214. *pul++ = CTRL_REG_OFFSET(V_CLK_CTL);
  215. *pul++ = VideoPortReadRegisterUlong(V_CLK_CTL);
  216. }
  217. else
  218. {
  219. //
  220. // no initialization table and no VGA. Use default values.
  221. //
  222. DEBUG_PRINT((2, "PERM2: GenerateInitializationTable() VGA disabled - using default values\n"));
  223. *pul++ = CTRL_REG_OFFSET(ROM_CONTROL);
  224. *pul++ = 0;
  225. *pul++ = CTRL_REG_OFFSET(BOOT_ADDRESS);
  226. *pul++ = 0x20;
  227. *pul++ = CTRL_REG_OFFSET(MEM_CONFIG);
  228. *pul++ = 0xe6002021;
  229. *pul++ = CTRL_REG_OFFSET(VSTREAM_CONFIG);
  230. *pul++ = 0x1f0;
  231. *pul++ = CTRL_REG_OFFSET(VIDEO_FIFO_CTL);
  232. *pul++ = 0x11008;
  233. *pul++ = CTRL_REG_OFFSET(V_CLK_CTL);
  234. if( DEVICE_FAMILY_ID(hwDeviceExtension->deviceInfo.DeviceId )
  235. == PERMEDIA_P2S_ID )
  236. {
  237. *pul++ = 0x80;
  238. }
  239. else
  240. {
  241. *pul++ = 0x40;
  242. }
  243. }
  244. hwDeviceExtension->culTableEntries =
  245. (ULONG)(pul - (ULONG *)hwDeviceExtension->aulInitializationTable) >> 1;
  246. P2_ASSERT(cEntries == hwDeviceExtension->culTableEntries,
  247. "ERROR: generated different size init table to that expected\n");
  248. #if DBG
  249. //
  250. // output the initialization table
  251. //
  252. pul = hwDeviceExtension->aulInitializationTable;
  253. ul = hwDeviceExtension->culTableEntries;
  254. while(ul--)
  255. {
  256. ULONG ulReg;
  257. ULONG ulRegData;
  258. ulReg = *pul++;
  259. ulRegData = *pul++;
  260. DEBUG_PRINT((2, "GenerateInitializationTable: initializing register %08.8Xh with %08.8Xh\n",
  261. ulReg, ulRegData));
  262. }
  263. #endif //DBG
  264. }
  265. VOID
  266. ProcessInitializationTable(
  267. PHW_DEVICE_EXTENSION hwDeviceExtension
  268. )
  269. /*++
  270. Routine Description:
  271. this function processes the register initialization table
  272. Arguments:
  273. hwDeviceExtension - a pointer to the device extension.
  274. Return:
  275. void
  276. --*/
  277. {
  278. PULONG pul;
  279. ULONG cul;
  280. ULONG ulRegAddr, ulRegData;
  281. PULONG pulReg;
  282. ULONG BaseAddrSelect;
  283. P2_DECL;
  284. pul = (PULONG)hwDeviceExtension->aulInitializationTable;
  285. cul = hwDeviceExtension->culTableEntries;
  286. while(cul--)
  287. {
  288. ulRegAddr = *pul++;
  289. ulRegData = *pul++;
  290. BaseAddrSelect = ulRegAddr >> 29;
  291. if(BaseAddrSelect == 0)
  292. {
  293. //
  294. // the offset is from the start of the control registers
  295. //
  296. pulReg = (PULONG)((ULONG_PTR)pCtrlRegs + (ulRegAddr & 0x3FFFFF));
  297. }
  298. else
  299. {
  300. DEBUG_PRINT((2, "ProcessInitializationTable: Invalid base address select %d regAddr = %d regData = %d\n",
  301. BaseAddrSelect, ulRegAddr, ulRegData));
  302. continue;
  303. }
  304. DEBUG_PRINT((2, "ProcessInitializationTable: initializing (region %d) register %08.8Xh with %08.8Xh\n",
  305. BaseAddrSelect, pulReg, ulRegData));
  306. VideoPortWriteRegisterUlong(pulReg, ulRegData);
  307. }
  308. //
  309. // We need a small delay after initializing the above registers
  310. //
  311. VideoPortStallExecution(5);
  312. }
  313. BOOLEAN
  314. VerifyBiosSettings(
  315. PHW_DEVICE_EXTENSION hwDeviceExtension
  316. )
  317. /*++
  318. Routine Description:
  319. This function validate a few register values set by bios at boot time
  320. Arguments:
  321. hwDeviceExtension - a pointer to the device extension.
  322. Return:
  323. TRUE - if the everything is all right
  324. FALSE - if some of the values don't match those in initialization table
  325. --*/
  326. {
  327. PULONG pul;
  328. ULONG cul;
  329. ULONG ulRegAddr, ulRegData;
  330. PULONG pulReg;
  331. ULONG BaseAddrSelect;
  332. P2_DECL;
  333. pul = (PULONG)hwDeviceExtension->aulInitializationTable;
  334. cul = hwDeviceExtension->culTableEntries;
  335. while(cul--)
  336. {
  337. ulRegAddr = *pul++;
  338. ulRegData = *pul++;
  339. BaseAddrSelect = ulRegAddr >> 29;
  340. if(BaseAddrSelect == 0)
  341. {
  342. //
  343. // the offset is from the start of the control registers
  344. //
  345. pulReg = (PULONG)((ULONG_PTR)pCtrlRegs + (ulRegAddr & 0x3FFFFF));
  346. //
  347. // we only care above these registers
  348. //
  349. if ( ( pulReg != BOOT_ADDRESS ) && (pulReg != MEM_CONFIG) )
  350. {
  351. continue;
  352. }
  353. }
  354. else
  355. {
  356. DEBUG_PRINT((2, "VerifyBiosSettings: Invalid base address select %d regAddr = %d regData = %d\n",
  357. BaseAddrSelect, ulRegAddr, ulRegData));
  358. continue;
  359. }
  360. if( ulRegData != VideoPortReadRegisterUlong(pulReg) )
  361. {
  362. DEBUG_PRINT((1, "VerifyBiosSettings: Bios failed to set some registers correctly. \n"));
  363. return (FALSE);
  364. }
  365. }
  366. return (TRUE);
  367. }
  368. LONG
  369. GetBiosVersion (
  370. PHW_DEVICE_EXTENSION hwDeviceExtension,
  371. OUT PWSTR BiosVersionString
  372. )
  373. /*++
  374. Routine Description:
  375. this function get the bios version and convert it to a unicode string
  376. Return:
  377. lenth of bios version string in bytes
  378. --*/
  379. {
  380. PVOID pvROMAddress;
  381. ULONG len, ulVersion;
  382. PCHAR pByte;
  383. BiosVersionString[0] = L'\0' ;
  384. //
  385. // just return on NT4
  386. //
  387. if( hwDeviceExtension->NtVersion == NT4 )
  388. {
  389. return 0;
  390. }
  391. //
  392. // bios version is stored at offset 7 and 8
  393. //
  394. pvROMAddress = VideoPortGetRomImage( hwDeviceExtension,
  395. NULL,
  396. 0,
  397. 7 + 2 );
  398. if( pvROMAddress == NULL )
  399. {
  400. DEBUG_PRINT((1, "GetBiosVersion: Can not access ROM\n"));
  401. return 0;
  402. }
  403. else if ( *(USHORT *)pvROMAddress != 0xAA55)
  404. {
  405. DEBUG_PRINT(( 2, "GetBiosVersion: ROM Signature 0x%x is invalid\n",
  406. *(USHORT *)pvROMAddress ));
  407. return 0;
  408. }
  409. pByte = ( PCHAR ) pvROMAddress;
  410. //
  411. // get major version number at offset 7
  412. //
  413. ulVersion = (ULONG) pByte[7];
  414. len = IntergerToUnicode( ulVersion, (PWSTR) (&BiosVersionString[0]));
  415. //
  416. // a dot between major and minor version number
  417. //
  418. BiosVersionString[len] = L'.' ;
  419. len++;
  420. //
  421. // get minor version number at offset 8
  422. //
  423. ulVersion = (ULONG) pByte[8];
  424. len = len + IntergerToUnicode( ulVersion, (PWSTR) (&BiosVersionString[len]) );
  425. //
  426. // len is the number of unicodes in string, we need to return
  427. // the string size in bytes
  428. //
  429. return (len * sizeof(WCHAR) );
  430. }
  431. LONG
  432. IntergerToUnicode(
  433. IN ULONG Number,
  434. OUT PWSTR UnicodeString
  435. )
  436. /*++
  437. Routine Description:
  438. this function convert an unsigned long to a unicode string
  439. Return:
  440. the number of the unicodes in UnicodeString
  441. --*/
  442. {
  443. const WCHAR digits[] = L"0123456789";
  444. LONG i, len;
  445. //
  446. // a ULONG decimal integer will not exceed 10 digits
  447. //
  448. WCHAR tmpString[10];
  449. i = 10;
  450. len = 0;
  451. do
  452. {
  453. tmpString[--i] = digits[ Number % 10 ];
  454. Number /= 10;
  455. len++;
  456. } while ( Number );
  457. VideoPortMoveMemory(UnicodeString, &tmpString[i], sizeof(WCHAR) * len );
  458. UnicodeString[len] = L'\0' ;
  459. return( len );
  460. }