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.

612 lines
19 KiB

  1. /**************************************************************************\
  2. $Header: $
  3. $Log: $
  4. \**************************************************************************/
  5. #include "switches.h"
  6. #if ((!defined (WINDOWS_NT)) || (USE_DDC_CODE))
  7. #ifndef WINDOWS_NT
  8. #include <dos.h>
  9. #endif
  10. #include "bind.h"
  11. #include "defbind.h"
  12. #include "edid.h"
  13. #ifdef WINDOWS_NT
  14. BOOLEAN bGetIdentifier(dword dwIdentifier, byte* romAddr, long* StartIndex);
  15. #if defined(ALLOC_PRAGMA)
  16. #pragma alloc_text(PAGE,ReportDDCcapabilities)
  17. #pragma alloc_text(PAGE,ReadEdid)
  18. #pragma alloc_text(PAGE,InDDCTable)
  19. #pragma alloc_text(PAGE,bGetIdentifier)
  20. #endif
  21. #define PCI_BIOS_BASE 0x000e0000
  22. #define PCI_BIOS_LENGTH 0x00020000
  23. extern PUCHAR setmgaselNoV(dword MgaSel, dword phyadr, dword limit);
  24. extern PVOID pMgaDeviceExtension;
  25. // I'm having trouble compiling...
  26. dword CLMFarCall[2];
  27. dword CLMCallAddress;
  28. #endif /* #ifdef WINDOWS_NT */
  29. #ifdef _WINDOWS_DLL16
  30. #include "windows.h"
  31. #endif
  32. #define DEBUG 0
  33. #define COMPAQ 0
  34. #define BIOSCOMPAQ 0xFF000
  35. byte SupportDDC = FALSE;
  36. EDID DataEdid;
  37. byte whichBios;
  38. byte BiosEntry[6];
  39. byte DataEdidFarPtr[6];
  40. dword physicalAddr;
  41. dword lenghtService;
  42. dword OffsetEntryPoint;
  43. VesaSet VesaParam[15] = {
  44. /*00*/{ 640, 480, 75, 0, 31500, 640, 16, 64, 120, 0, 480, 1, 3, 16, 0, 0, 0, 0, 0 ,
  45. 31500, 640, 16, 64, 120, 0, 480, 1, 3, 16, 0, 0, 0, 0, 0 ,
  46. 31500, 640, 16, 64, 120, 0, 480, 1, 3, 16, 0, 0, 0, 0, 0},
  47. /*01*/{ 640, 480, 72, 0, 31500, 640, 24, 40, 128, 0, 480, 9, 3, 28, 0, 0, 0, 0, 0 ,
  48. 31500, 640, 24, 40, 128, 0, 480, 9, 3, 28, 0, 0, 0, 0, 0 ,
  49. 31500, 640, 24, 40, 128, 0, 480, 9, 3, 28, 0, 0, 0, 0, 0},
  50. /*02*/{ 640, 480, 60, 0, 25175, 640, 16, 96, 48, 0, 480, 11, 2, 32, 0, 0, 0, 0, 0 ,
  51. 25175, 640, 16, 96, 48, 0, 480, 11, 2, 32, 0, 0, 0, 0, 0 ,
  52. 25175, 640, 16, 96, 48, 0, 480, 11, 2, 32, 0, 0, 0, 0, 0},
  53. /*03*/{ 800, 600, 75, 0, 49500, 800, 16, 80, 160, 1, 600, 1, 3, 21, 0, 0, 0, 1, 1 ,
  54. 49500, 800, 32, 64, 160, 1, 600, 1, 3, 21, 0, 0, 0, 1, 1 ,
  55. 49500, 800, 32, 64, 160, 1, 600, 1, 3, 21, 0, 0, 0, 1, 1},
  56. /*04*/{ 800, 600, 72, 0, 50000, 800, 56, 120, 64, 0, 600, 37, 6, 23, 0, 0, 0, 1, 1 ,
  57. 50000, 800, 56, 120, 64, 0, 600, 37, 6, 23, 0, 0, 0, 1, 1 ,
  58. 50000, 800, 56, 120, 64, 0, 600, 37, 6, 23, 0, 0, 0, 1, 1},
  59. /*05*/{ 800, 600, 60, 0, 40000, 800, 40, 128, 88, 0, 600, 1, 4, 23, 0, 0, 0, 1, 1 ,
  60. 40000, 800, 40, 128, 88, 0, 600, 1, 4, 23, 0, 0, 0, 1, 1 ,
  61. 40000, 800, 32, 128, 88, 0, 600, 1, 4, 23, 0, 0, 0, 1, 1},
  62. /*06*/{ 800, 600, 56, 0, 37800, 800, 32, 128, 128, 0, 600, 2, 4, 14, 0, 0, 0, 1, 1 ,
  63. 37800, 800, 32, 128, 128, 0, 600, 2, 4, 14, 0, 0, 0, 1, 1 ,
  64. 37800, 800, 32, 128, 128, 0, 600, 2, 4, 14, 0, 0, 0, 1, 1},
  65. /*07*/{ 1024, 768, 75, 0, 78750, 1024, 16, 96, 176, 1, 768, 1, 3, 28, 0, 0, 0, 1, 1 ,
  66. 78750, 1024, 16, 96, 176, 1, 768, 1, 3, 28, 0, 0, 0, 1, 1 ,
  67. 78750, 1024, 16, 96, 176, 1, 768, 1, 3, 28, 0, 0, 0, 1, 1},
  68. /*08*/{ 1024, 768, 70, 0, 75000, 1024, 24, 136, 144, 0, 768, 3, 6, 29, 0, 0, 0, 0, 0 ,
  69. 75000, 1024, 32, 128, 144, 0, 768, 3, 6, 29, 0, 0, 0, 0, 0 ,
  70. 75000, 1024, 40, 128, 160, 0, 768, 3, 6, 29, 0, 0, 0, 0, 0},
  71. /*09*/{ 1024, 768, 60, 0, 65000, 1024, 24, 136, 160, 0, 768, 3, 6, 29, 0, 0, 0, 0, 0 ,
  72. 65000, 1024, 24, 136, 160, 0, 768, 3, 6, 29, 0, 0, 0, 0, 0 ,
  73. 65000, 1024, 32, 136, 160, 0, 768, 3, 6, 29, 0, 0, 0, 0, 0},
  74. /*10*/{ 1024, 768, 87, 0, 44900, 1024, 32, 128, 64, 0, 384, 1, 4, 21, 0, 0, 1, 1, 1 ,
  75. 44900, 1024, 32, 128, 64, 0, 384, 1, 4, 21, 0, 0, 1, 1, 1 ,
  76. 44900, 1024, 32, 128, 64, 0, 384, 1, 4, 21, 0, 0, 1, 1, 1},
  77. /*11*/{ 1280, 1024, 75, 0, 135600, 1280, 16, 144, 248, 1, 1024, 2, 3, 37, 0, 0, 0, 1, 1 ,
  78. 135600, 1280, 32, 128, 256, 1, 1024, 2, 3, 37, 0, 0, 0, 1, 1 ,
  79. 135600, 1280, 32, 128, 256, 1, 1024, 2, 3, 37, 0, 0, 0, 1, 1},
  80. {(word)-1}
  81. };
  82. #ifdef OS2
  83. extern int pDdcInfoLen;
  84. #endif//!OS2
  85. byte ReportDDCcapabilities(void)
  86. {
  87. #ifdef OS2
  88. if(pDdcInfoLen)
  89. return (TRUE);
  90. else
  91. return (FALSE);
  92. #else//!OS2
  93. #if (USE_DDC_CODE)
  94. PUCHAR romAddr = 0;
  95. PUCHAR BiosAddr;
  96. long StartIndex;
  97. SHORT wNumPages;
  98. #else
  99. volatile byte _Far* BiosAddr;
  100. union _REGS r;
  101. #endif
  102. word i,j;
  103. byte SupportFunction,DisplayCapabilities;
  104. dword sel;
  105. char *BiosId[] = { {"COMPAQ"}, {"OTHERS"} };
  106. whichBios = 0;
  107. SupportFunction = 0;
  108. #if (USE_DDC_CODE)
  109. // getmgasel() always returns 0 on WinNT, and it does not matter.
  110. sel = getmgasel();
  111. #else
  112. if ((sel = getmgasel()) != 0)
  113. #endif
  114. {
  115. /* search for a particular BIOS */
  116. #if (USE_DDC_CODE)
  117. if ((BiosAddr = setmgaselNoV(sel, BIOSCOMPAQ, 1)) != NULL)
  118. #else
  119. if ((BiosAddr = setmgasel(sel, BIOSCOMPAQ, 1)) != NULL)
  120. #endif
  121. {
  122. for(i = 0x0FEA, j = 0; i < 0x0FF0 ; i++, j++)
  123. {
  124. if (*(BiosAddr + i) != BiosId[0][j])
  125. {
  126. whichBios = 1;
  127. break;
  128. }
  129. }
  130. }
  131. #if (USE_DDC_CODE)
  132. VideoPortFreeDeviceBase(pMgaDeviceExtension, BiosAddr);
  133. #endif
  134. /* Verify the DDC capabilities */
  135. switch (whichBios)
  136. {
  137. case COMPAQ:
  138. {
  139. #if (USE_DDC_CODE)
  140. sel = getmgasel();
  141. if ((romAddr = setmgaselNoV(sel, PCI_BIOS_BASE, 0x20)) == NULL)
  142. {
  143. return(FALSE);
  144. }
  145. StartIndex = 0;
  146. if (!bGetIdentifier('MLC$', romAddr, &StartIndex))
  147. {
  148. // We didn't find anything!
  149. VideoPortFreeDeviceBase(pMgaDeviceExtension, romAddr);
  150. return(FALSE);
  151. }
  152. else
  153. {
  154. wNumPages = (SHORT)(lenghtService / (4*1024));
  155. wNumPages = (wNumPages != 0) ? wNumPages : 1;
  156. CLMCallAddress = (dword)setmgaselNoV(sel, physicalAddr,
  157. wNumPages);
  158. if (CLMCallAddress == (dword)NULL)
  159. {
  160. DisplayCapabilities = FALSE;
  161. }
  162. else
  163. {
  164. CLMFarCall[0] = CLMCallAddress + OffsetEntryPoint;
  165. // We know this is for Compaq.
  166. _asm
  167. {
  168. xor ebx,ebx
  169. lea eax, CLMFarCall
  170. mov bx, cs
  171. mov [eax+4], ebx
  172. mov eax, 0xe813
  173. mov bx, 0x0100
  174. call fword ptr CLMFarCall
  175. jc NoCaps
  176. test ah, ah
  177. jnz NoCaps
  178. and bl, bh
  179. test bl, 0x02
  180. jz NoCaps
  181. mov DisplayCapabilities, TRUE
  182. jmp AllSet
  183. NoCaps:
  184. mov DisplayCapabilities, FALSE
  185. AllSet:
  186. }
  187. VideoPortFreeDeviceBase(pMgaDeviceExtension,
  188. (PUCHAR)CLMCallAddress);
  189. }
  190. VideoPortFreeDeviceBase(pMgaDeviceExtension, romAddr);
  191. }
  192. #else /* #if (USE_DDC_CODE) */
  193. #ifdef __WATCOMC__
  194. r.w.ax = 0xe813;
  195. #else
  196. r.x.ax = 0xe813;
  197. #endif
  198. r.h.bh = 0x01;
  199. r.h.bl = 0x00;
  200. _int86(0x15, &r, &r);
  201. /*** INT 15h function supported ***/
  202. #ifdef __WATCOMC__
  203. if (!r.w.cflag && !r.h.ah)
  204. #else
  205. if (!r.x.cflag && !r.h.ah)
  206. #endif
  207. SupportFunction = TRUE;
  208. else
  209. SupportFunction = FALSE;
  210. /*** System and monitor support DDC2 ***/
  211. if((r.h.bh & 0x02) && (r.h.bl & 0x02) && SupportFunction)
  212. DisplayCapabilities = TRUE;
  213. else
  214. DisplayCapabilities = FALSE;
  215. #endif /* #if (USE_DDC_CODE) */
  216. break;
  217. }
  218. default:
  219. {
  220. DisplayCapabilities = FALSE;
  221. break;
  222. }
  223. } /* end case */
  224. } /* end if */
  225. #if DEBUG
  226. printf ("\n SupportFunction = %d",SupportFunction);
  227. printf ("\n whichBios = %d",whichBios);
  228. getch();
  229. #endif
  230. return (DisplayCapabilities);
  231. #endif//!OS2 & else
  232. }
  233. #ifdef _WINDOWS_DLL16
  234. byte ReadEdid(void)
  235. {
  236. union REGS r;
  237. struct SREGS s = {0};
  238. RealIntStruct regReel = {0};
  239. dword lineaireDosMem;
  240. word i, sel, seg;
  241. byte _far *ddcData;
  242. EDID *DataEdidPtr;
  243. /* Allocate a dos memory bloc of 128 bytes */
  244. lineaireDosMem = GlobalDosAlloc(128);
  245. if (!lineaireDosMem)
  246. return 0;
  247. seg = lineaireDosMem >> 16;
  248. sel = lineaireDosMem & 0xffff;
  249. regReel.eax = 0xe813;
  250. regReel.ebx = 00;
  251. regReel.ds = seg;
  252. regReel.esi = 0;
  253. regReel.sp = 0;
  254. regReel.ss = 0;
  255. r.x.ax = 0x300;
  256. r.x.bx = 0x115;
  257. r.x.cx = 0x00;
  258. r.x.di = OFFSETOF(&regReel);
  259. s.es = SELECTOROF(&regReel);
  260. int86x(0x31, &r, &r, &s);
  261. if ( !r.x.cflag )
  262. {
  263. DataEdidPtr = &DataEdid;
  264. ddcData = (byte _far *)MAKELP(sel, 0);
  265. for (i = 0; i < 128; i++)
  266. *(((byte *) DataEdidPtr) + i) = ddcData[i];
  267. if( DataEdid.established_timings.est_timings_I & 0x20 )
  268. VesaParam[2].Support = TRUE; /* 640X480X60Hz */
  269. if( DataEdid.established_timings.est_timings_I & 0x08 )
  270. VesaParam[1].Support = TRUE; /* 640X480X72Hz */
  271. if( DataEdid.established_timings.est_timings_I & 0x04 )
  272. VesaParam[0].Support = TRUE; /* 640X480X75Hz */
  273. if( DataEdid.established_timings.est_timings_I & 0x02 )
  274. VesaParam[6].Support = TRUE; /* 800X600X56Hz */
  275. if( DataEdid.established_timings.est_timings_I & 0x01 )
  276. VesaParam[5].Support = TRUE; /* 800X600X60Hz */
  277. if( DataEdid.established_timings.est_timings_II & 0x80 )
  278. VesaParam[4].Support = TRUE; /* 800X600X72Hz */
  279. if( DataEdid.established_timings.est_timings_II & 0x40 )
  280. VesaParam[3].Support = TRUE; /* 800X600X75Hz */
  281. if( DataEdid.established_timings.est_timings_II & 0x10 )
  282. VesaParam[10].Support = TRUE;/* 1024X768X87Hz I */
  283. if( DataEdid.established_timings.est_timings_II & 0x08 )
  284. VesaParam[9].Support = TRUE; /* 1024X768X60Hz */
  285. if( DataEdid.established_timings.est_timings_II & 0x04 )
  286. VesaParam[8].Support = TRUE;/* 1024X768X70Hz */
  287. if( DataEdid.established_timings.est_timings_II & 0x02 )
  288. VesaParam[7].Support = TRUE; /* 1024X768X75Hz */
  289. if( DataEdid.established_timings.est_timings_II & 0x01 )
  290. VesaParam[11].Support = TRUE;/* 1280X1024X75Hz */
  291. }
  292. GlobalDosFree( sel );
  293. if (!r.x.cflag)
  294. return (1);
  295. return (0);
  296. }
  297. #else /* #ifdef _WINDOWS_DLL16 */
  298. byte ReadEdid(void)
  299. {
  300. #ifndef OS2 //[nPhung] 13-Dec-1994
  301. #ifndef WINDOWS_NT
  302. dword bios32add;
  303. volatile byte _far *romAddr = 0;
  304. int i,j,sum;
  305. #endif
  306. dword sel;
  307. /* Search for Bios32 Service Directory */
  308. byte find = 0;
  309. #if (USE_DDC_CODE)
  310. long StartIndex;
  311. SHORT wNumPages;
  312. PUCHAR romAddr = 0;
  313. StartIndex = 0;
  314. sel = getmgasel();
  315. if ((romAddr = setmgaselNoV(sel, PCI_BIOS_BASE, 0x20)) == NULL)
  316. return(FALSE);
  317. do
  318. {
  319. if (!bGetIdentifier('MLC$', romAddr, &StartIndex))
  320. {
  321. // We went through the whole region.
  322. VideoPortFreeDeviceBase(pMgaDeviceExtension, romAddr);
  323. return(FALSE);
  324. }
  325. else
  326. {
  327. wNumPages = (SHORT)(lenghtService / (4*1024));
  328. wNumPages = (wNumPages != 0) ? wNumPages : 1;
  329. CLMCallAddress = (dword)setmgaselNoV(sel, physicalAddr, wNumPages);
  330. if (CLMCallAddress != (dword)NULL)
  331. {
  332. CLMFarCall[0] = CLMCallAddress + OffsetEntryPoint;
  333. _asm
  334. {
  335. xor ebx, ebx
  336. lea eax, CLMFarCall
  337. mov bx, cs
  338. mov [eax+4], ebx
  339. mov ax, 0xe813;
  340. mov bx, 0
  341. lea esi, DataEdid
  342. call fword ptr CLMFarCall
  343. mov find, al
  344. }
  345. VideoPortFreeDeviceBase(pMgaDeviceExtension,
  346. (PUCHAR)CLMCallAddress);
  347. }
  348. }
  349. } while (find == 0);
  350. VideoPortFreeDeviceBase(pMgaDeviceExtension, romAddr);
  351. #else /* #if (USE_DDC_CODE) */
  352. if ((sel = getmgasel()) != 0)
  353. {
  354. romAddr = setmgasel(sel,0xe0000,0x20);
  355. for (i = 0; (i < 0x20000) && !find; i += 2 )
  356. {
  357. if ( (romAddr[i+0] == '_') &&
  358. (romAddr[i+1] == '3') &&
  359. (romAddr[i+2] == '2') &&
  360. (romAddr[i+3] == '_')
  361. )
  362. {
  363. sum = 0;
  364. for (j = 0; j < 16; j++)
  365. sum += romAddr[i+j];
  366. if (sum & 0xff)
  367. {
  368. find = 0;
  369. continue;
  370. }
  371. bios32add = (dword)romAddr[i+7] << 24;
  372. bios32add |= (dword)romAddr[i+6] << 16;
  373. bios32add |= (dword)romAddr[i+5] << 8;
  374. bios32add |= (dword)romAddr[i+4];
  375. if (!GetDDCIdentifier(bios32add))
  376. {
  377. switch (whichBios)
  378. {
  379. case COMPAQ:
  380. {
  381. find = GetCPQDDCDataEdid();
  382. break;
  383. }
  384. default:
  385. {
  386. find = 0;
  387. break;
  388. }
  389. } /* end switch */
  390. }
  391. }
  392. }/* end for */
  393. }
  394. #endif /* #if (USE_DDC_CODE) */
  395. if (find)
  396. #else //this is OS2 //[nPhung] 13-Dec-1994
  397. if(pDdcInfoLen) //[nPhung] 13-Dec-1994
  398. #endif // !OS2 and else //[nPhung] 13-Dec-1994
  399. {
  400. if( DataEdid.established_timings.est_timings_I & 0x20 )
  401. VesaParam[2].Support = TRUE; /* 640X480X60Hz */
  402. if( DataEdid.established_timings.est_timings_I & 0x08 )
  403. VesaParam[1].Support = TRUE; /* 640X480X72Hz */
  404. if( DataEdid.established_timings.est_timings_I & 0x04 )
  405. VesaParam[0].Support = TRUE; /* 640X480X75Hz */
  406. if( DataEdid.established_timings.est_timings_I & 0x02 )
  407. VesaParam[6].Support = TRUE; /* 800X600X56Hz */
  408. if( DataEdid.established_timings.est_timings_I & 0x01 )
  409. VesaParam[5].Support = TRUE; /* 800X600X60Hz */
  410. if( DataEdid.established_timings.est_timings_II & 0x80 )
  411. VesaParam[4].Support = TRUE; /* 800X600X72Hz */
  412. if( DataEdid.established_timings.est_timings_II & 0x40 )
  413. VesaParam[3].Support = TRUE; /* 800X600X75Hz */
  414. if( DataEdid.established_timings.est_timings_II & 0x10 )
  415. VesaParam[10].Support = TRUE;/* 1024X768X87Hz I */
  416. if( DataEdid.established_timings.est_timings_II & 0x08 )
  417. VesaParam[9].Support = TRUE; /* 1024X768X60Hz */
  418. if( DataEdid.established_timings.est_timings_II & 0x04 )
  419. VesaParam[8].Support = TRUE;/* 1024X768X70Hz */
  420. if( DataEdid.established_timings.est_timings_II & 0x02 )
  421. VesaParam[7].Support = TRUE; /* 1024X768X75Hz */
  422. if( DataEdid.established_timings.est_timings_II & 0x01 )
  423. VesaParam[11].Support = TRUE;/* 1280X1024X75Hz */
  424. #ifdef OS2
  425. return TRUE;
  426. }
  427. return FALSE;
  428. #else //!OS2
  429. }
  430. #if DEBUG
  431. printf ("\n find = %d",find);
  432. getch();
  433. #endif
  434. return (find);
  435. #endif //OS2
  436. }
  437. #endif /* #ifdef _WINDOWS_DLL16 */
  438. byte InDDCTable(dword DispWidth)
  439. {
  440. int i;
  441. for (i = 0; VesaParam[i].DispWidth != (word) -1; i++)
  442. {
  443. if (VesaParam[i].DispWidth == DispWidth)
  444. {
  445. for (; VesaParam[i].DispWidth == DispWidth; i++)
  446. {
  447. if (VesaParam[i].Support)
  448. return TRUE;
  449. }
  450. return FALSE;
  451. }
  452. }
  453. return FALSE;
  454. }
  455. #if (USE_DDC_CODE)
  456. BOOLEAN bGetIdentifier(dword dwIdentifier, UCHAR* romAddr, long* StartIndex)
  457. {
  458. dword bios32add, biosFarCall[2];
  459. long i, j, sum;
  460. byte RetValue;
  461. for (i = *StartIndex; i < PCI_BIOS_LENGTH; i += 2 )
  462. {
  463. if ((romAddr[i+0] == '_') &&
  464. (romAddr[i+1] == '3') &&
  465. (romAddr[i+2] == '2') &&
  466. (romAddr[i+3] == '_')
  467. )
  468. {
  469. sum = 0;
  470. for (j = 0; j < 16; j++)
  471. sum += romAddr[i+j];
  472. if (sum & 0xff)
  473. {
  474. continue;
  475. }
  476. bios32add = (dword)romAddr[i+7] << 24;
  477. bios32add |= (dword)romAddr[i+6] << 16;
  478. bios32add |= (dword)romAddr[i+5] << 8;
  479. bios32add |= (dword)romAddr[i+4];
  480. bios32add = (dword)setmgaselNoV( 0, bios32add, 2);
  481. if (bios32add == (dword)NULL)
  482. {
  483. RetValue = 0x80;
  484. }
  485. else
  486. {
  487. biosFarCall[0] = bios32add;
  488. // We can call bios32add directly, no need to fudge around with
  489. // selectors and access rights.
  490. _asm
  491. {
  492. // Load the registers.
  493. xor ebx,ebx
  494. lea eax, biosFarCall
  495. mov bx, cs
  496. mov [eax+4], ebx
  497. mov eax, dwIdentifier
  498. mov ebx, 0
  499. call fword ptr biosFarCall
  500. mov physicalAddr, ebx
  501. mov lenghtService, ecx
  502. mov OffsetEntryPoint, edx
  503. mov RetValue, al // 0x00, 0x80, or 0x81
  504. }
  505. VideoPortFreeDeviceBase(pMgaDeviceExtension, (PUCHAR)bios32add);
  506. }
  507. if (!RetValue)
  508. {
  509. *StartIndex = i;
  510. return(TRUE);
  511. }
  512. } // if ((romAddr[i+0] == '_') && ...
  513. } // for (i = 0; i < PCI_BIOS_LENGTH; i += 2 )
  514. *StartIndex = PCI_BIOS_LENGTH;
  515. return(FALSE);
  516. }
  517. #endif /* #if (USE_DDC_CODE) */
  518. #endif /* #if ((!defined (WINDOWS_NT)) || (USE_DDC_CODE)) */