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.

800 lines
18 KiB

  1. /************************************************************************/
  2. /* */
  3. /* EEVGA.C */
  4. /* */
  5. /* Copyright (c) 1992 ATI Technologies Inc. */
  6. /************************************************************************/
  7. /* */
  8. /********************** PolyTron RCS Utilities
  9. $Revision: 1.3 $
  10. $Date: 23 Jan 1996 11:46:08 $
  11. $Author: RWolff $
  12. $Log: S:/source/wnt/ms11/miniport/archive/eevga.c_v $
  13. *
  14. * Rev 1.3 23 Jan 1996 11:46:08 RWolff
  15. * Eliminated level 3 warnings.
  16. *
  17. * Rev 1.2 23 Dec 1994 10:47:10 ASHANMUG
  18. * ALPHA/Chrontel-DAC
  19. *
  20. * Rev 1.1 07 Feb 1994 14:07:44 RWOLFF
  21. * Added alloc_text() pragmas to allow miniport to be swapped out when
  22. * not needed.
  23. *
  24. * Rev 1.0 31 Jan 1994 11:08:26 RWOLFF
  25. * Initial revision.
  26. Rev 1.2 08 Oct 1993 15:17:28 RWOLFF
  27. No longer includes VIDFIND.H.
  28. Rev 1.1 03 Sep 1993 14:23:18 RWOLFF
  29. Partway through CX isolation.
  30. Rev 1.0 16 Aug 1993 13:26:32 Robert_Wolff
  31. Initial revision.
  32. Rev 1.11 24 Jun 1993 14:32:48 RWOLFF
  33. Microsoft-originated change: now uses VideoPortSynchronizeExecution()
  34. instead of _disable()/_enable() pairs.
  35. Rev 1.10 10 May 1993 10:54:08 RWOLFF
  36. Fixed uninitialized variable in Read_ee().
  37. Rev 1.9 27 Apr 1993 20:19:40 BRADES
  38. change extern ati_reg toa long, is a virtual IO address now.
  39. Rev 1.8 21 Apr 1993 17:31:10 RWOLFF
  40. Now uses AMACH.H instead of 68800.H/68801.H.
  41. Rev 1.7 08 Mar 1993 19:28:36 BRADES
  42. submit to MS NT
  43. Rev 1.5 06 Jan 1993 11:05:22 Robert_Wolff
  44. Cleaned up compile warnings.
  45. Rev 1.4 27 Nov 1992 15:19:30 STEPHEN
  46. No change.
  47. Rev 1.3 13 Nov 1992 16:32:32 Robert_Wolff
  48. Now includes 68801.H, which consists of the now-obsolete MACH8.H
  49. and elements moved from VIDFIND.H.
  50. Rev 1.2 12 Nov 1992 16:56:56 Robert_Wolff
  51. Same source file can now be used for both Windows NT driver and
  52. VIDEO.EXE test program.
  53. Rev 1.1 06 Nov 1992 19:02:34 Robert_Wolff
  54. Moved I/O port defines to VIDFIND.H.
  55. Rev 1.0 05 Nov 1992 14:01:06 Robert_Wolff
  56. Initial revision.
  57. Rev 1.1 01 Oct 1992 15:29:08 Robert_Wolff
  58. Can now handle both Mach32 and Mach8 cards.
  59. Rev 1.0 14 Sep 1992 09:44:30 Robert_Wolff
  60. Initial revision.
  61. End of PolyTron RCS section *****************/
  62. #if defined(DOC)
  63. EEVGA.C - EEPROM read and write routines
  64. DESCRIPTION:
  65. VGA EEPROM read and write routines
  66. September 4 1992 - R. Wolff
  67. Translated from assembler into C.
  68. August 28 1992 - C. Brady.
  69. This has been adapted from the VGA$EEC.ASM software by Steve Stefanidis
  70. The original code used externs to long_delay() and short_delay(), these
  71. where changed to use local function delay.
  72. The original used compile time options to work with various VGA revisions,
  73. it is required to be run time determinate since we need to access
  74. eeprom VGA style (how archaic) for the Graphics Ultra (38800) and the
  75. 68800 family of graphics controllers.
  76. OLD_EEPROM_MAP equ 1 ; enables the Old EEPROM Handling routines
  77. REMOVED, the DETECT.C routine assigns the eeprom address size used
  78. in EE_addr(). I do not know of a Graphics Ultra using 7 bit address
  79. since they ONLY had a 1k eeprom == 64 words.
  80. #endif
  81. #include <conio.h>
  82. #include <dos.h>
  83. #include "miniport.h"
  84. #include "ntddvdeo.h"
  85. #include "video.h"
  86. #include "stdtyp.h"
  87. #include "amach.h"
  88. #include "amach1.h"
  89. #include "atimp.h"
  90. #include "cvtvga.h" /* For SplitWord data type */
  91. #include "eeprom.h"
  92. #include "services.h"
  93. #define OFF 0
  94. #define ON 1
  95. #define IND_OFFSET 0x00B0
  96. #define SYNC_I 0x008 ^ IND_OFFSET
  97. #define L_ALL 0x004
  98. #define MISC3_I 0x010 ^ IND_OFFSET
  99. #define EEPROM 0x020 /* EEPROM Enable bit */
  100. #define EE_WREG 0x003 ^ IND_OFFSET
  101. #define EE_CS 0x008 /* Chip Select bit */
  102. #define EE_ENABLE 0x004
  103. #define EE_CLK 0x002
  104. #define EE_DI 0x001
  105. #define EE_RREG 0x007 ^ IND_OFFSET
  106. #define EE_DO 0x008
  107. /*
  108. * Definitions for reading and writing the VGA sequencer registers.
  109. */
  110. #define SD_CLOCK 0x0001 /* Index for clock mode register */
  111. /*
  112. * Bit to set in clock mode register to blank the screen and disable
  113. * video-generation logic access to video memory.
  114. */
  115. #define SD_CLK_OFF 0x020
  116. ULONG ati_reg; // Base register for ATI extended VGA registers
  117. char vga_chip; // VGA chip revision as ascii
  118. /*
  119. * Storage for register where EEPROM read/write happens.
  120. */
  121. static union SplitWord zEepromIOPort;
  122. /*
  123. * Storage for original status which is determined in Sel_EE() and
  124. * which must be restored in DeSel_EE().
  125. */
  126. static union SplitWord zOrigStat;
  127. /*
  128. * EEPROM word to be read/written/erased/etc.
  129. */
  130. static unsigned char ucEepromWord;
  131. static void setscrn(int iSetting);
  132. static unsigned short Read_ee(void);
  133. static void ee_sel_vga(void);
  134. static void ee_clock_vga(void);
  135. static void EE_control(unsigned char ucEepromStatus);
  136. static void ee_deselect_vga(void);
  137. static void Write_ee(unsigned short uiData);
  138. static void Enabl_ee(void);
  139. static void Disab_ee(void);
  140. static void Erase_ee(void);
  141. extern void ee_wait(void);
  142. /*
  143. * Allow miniport to be swapped out when not needed.
  144. *
  145. * The following routines are called through function pointers
  146. * rather than an explicit call to the routine, and may run into
  147. * trouble if paged out. If problems develop, make them un-pageable:
  148. * ee_read_vga()
  149. * ee_cmd_vga()
  150. */
  151. #if defined (ALLOC_PRAGMA)
  152. #pragma alloc_text(PAGE_M, ee_read_vga)
  153. #pragma alloc_text(PAGE_M, ee_write_vga)
  154. #pragma alloc_text(PAGE_M, ee_erase_vga)
  155. #pragma alloc_text(PAGE_M, ee_enab_vga)
  156. #pragma alloc_text(PAGE_M, ee_disab_vga)
  157. #pragma alloc_text(PAGE_M, setscrn)
  158. #pragma alloc_text(PAGE_M, Read_ee)
  159. #pragma alloc_text(PAGE_M, ee_sel_vga)
  160. #pragma alloc_text(PAGE_M, ee_cmd_vga)
  161. #pragma alloc_text(PAGE_M, ee_sel_eeprom)
  162. #pragma alloc_text(PAGE_M, ee_clock_vga)
  163. #pragma alloc_text(PAGE_M, EE_control)
  164. #pragma alloc_text(PAGE_M, ee_deselect_vga)
  165. #pragma alloc_text(PAGE_M, Write_ee)
  166. #pragma alloc_text(PAGE_M, Enabl_ee)
  167. #pragma alloc_text(PAGE_M, Disab_ee)
  168. #pragma alloc_text(PAGE_M, Erase_ee)
  169. #endif
  170. /*
  171. * WORD ee_read_vga(iIndex);
  172. *
  173. * short iIndex; Which word of EEPROM should be read
  174. *
  175. * Read the specified word from the EEPROM.
  176. */
  177. WORD ee_read_vga(short iIndex)
  178. {
  179. unsigned short uiRetVal; /* Value returned by Read_ee() */
  180. setscrn(OFF); /* Disable the video card */
  181. /*
  182. * Set up the word index within the EEPROM and the chip identifier.
  183. */
  184. ucEepromWord = iIndex & 0x00ff;
  185. uiRetVal = Read_ee(); /* Get the word */
  186. setscrn(ON); /* Re-enable the video card */
  187. return uiRetVal;
  188. }
  189. /*
  190. * void ee_write_vga(uiIndex, uiData);
  191. *
  192. * unsigned short uiIndex;
  193. * unsigned short uiData;
  194. *
  195. * Routine to write a word to the EEPROM.
  196. */
  197. void ee_write_vga(unsigned short uiIndex, unsigned short uiData)
  198. {
  199. setscrn(OFF);
  200. ucEepromWord = uiIndex & 0x00ff;
  201. Write_ee(uiData);
  202. ee_wait();
  203. setscrn(ON);
  204. return;
  205. }
  206. /*
  207. * void ee_erase_vga(uiIndex);
  208. *
  209. * unsigned short uiIndex;
  210. *
  211. * Routine to erase a word in the EEPROM.
  212. */
  213. void ee_erase_vga(unsigned short uiIndex)
  214. {
  215. setscrn(OFF);
  216. ucEepromWord = uiIndex & 0x00ff;
  217. Erase_ee();
  218. setscrn(ON);
  219. ee_wait();
  220. return;
  221. }
  222. /*
  223. * void ee_enab_vga(void);
  224. *
  225. * Routine to enable the EEPROM.
  226. */
  227. void ee_enab_vga()
  228. {
  229. setscrn(OFF);
  230. Enabl_ee();
  231. setscrn(ON);
  232. return;
  233. }
  234. /*
  235. * void ee_disab_vga(void);
  236. *
  237. * Routine to disable the EEPROM.
  238. */
  239. void ee_disab_vga(void)
  240. {
  241. setscrn(OFF);
  242. Disab_ee();
  243. setscrn(ON);
  244. ee_wait();
  245. return;
  246. }
  247. /*
  248. * static void setscrn(iSetting);
  249. *
  250. * int iSetting; Should the video card be enabled (ON) or disabled (OFF)
  251. *
  252. * Enable or disable the video card, as selected by the caller.
  253. */
  254. static void setscrn(int iSetting)
  255. {
  256. static unsigned char ucSavedMode; /* Saved value of clock mode register */
  257. if (iSetting)
  258. {
  259. /*
  260. * Caller wants to unblank the screen.
  261. *
  262. * Point the sequencer index register to the clock mode register.
  263. */
  264. OUTP(SEQ_IND, SD_CLOCK);
  265. /*
  266. * Set the clock mode register to the value it had before we
  267. * blanked the screen.
  268. */
  269. OUTP(SEQ_DATA, ucSavedMode);
  270. }
  271. else{
  272. /*
  273. * Caller wants to blank the screen.
  274. *
  275. * Point the sequencer index register to the clock mode register.
  276. */
  277. OUTP(SEQ_IND, SD_CLOCK);
  278. /*
  279. * Read and save the current contents of the clock mode register.
  280. */
  281. ucSavedMode = INP(SEQ_DATA);
  282. /*
  283. * Blank the screen without changing the other contents
  284. * of the clock mode register.
  285. */
  286. OUTP(SEQ_DATA, (BYTE)(ucSavedMode | SD_CLK_OFF));
  287. }
  288. return;
  289. }
  290. /*
  291. * static unsigned short Read_ee(void);
  292. *
  293. * A lower-level way of getting a word out of the EEPROM.
  294. */
  295. static unsigned short Read_ee(void)
  296. {
  297. int iCount; /* Loop counter */
  298. unsigned short uiValueRead = 0; /* Value read from the EEPROM */
  299. union SplitWord zStateSet; /* Used in setting the video state */
  300. ee_sel_vga();
  301. if (vga_chip >= '4') /* ASIC revision level */
  302. {
  303. /*
  304. * Set read/write bit of ATI register 26 to read.
  305. */
  306. zStateSet.byte.low = 0x0a6;
  307. OUTP(ati_reg, zStateSet.byte.low);
  308. zStateSet.byte.high = INP(ati_reg+1);
  309. OUTPW(ati_reg, (WORD)((zStateSet.word & 0x0FBFF)));
  310. }
  311. ee_cmd_vga((unsigned short) (EE_READ | ucEepromWord));
  312. zEepromIOPort.byte.high &= (~EE_DI);
  313. OUTPW(ati_reg, zEepromIOPort.word);
  314. ee_clock_vga();
  315. /*
  316. * Read in the word, one bit at a time.
  317. */
  318. for (iCount = 0; iCount < 16; iCount++)
  319. {
  320. uiValueRead = uiValueRead << 1;
  321. OUTP(ati_reg, EE_RREG);
  322. if (INP(ati_reg+1) & EE_DO)
  323. uiValueRead |= 1;
  324. ee_clock_vga();
  325. }
  326. ee_deselect_vga();
  327. /*
  328. * Undo the state setting which was done on entry.
  329. */
  330. if (vga_chip >= '4')
  331. OUTPW(ati_reg, zStateSet.word);
  332. return uiValueRead;
  333. }
  334. /*
  335. * static void ee_sel_vga(void);
  336. *
  337. * This routine selects the EEPROM.
  338. */
  339. static void ee_sel_vga(void)
  340. {
  341. if (vga_chip <= '2')
  342. {
  343. /*
  344. * Get the video card's status.
  345. */
  346. VideoPortSynchronizeExecution(phwDeviceExtension,
  347. VpHighPriority,
  348. (PMINIPORT_SYNCHRONIZE_ROUTINE)
  349. ee_sel_eeprom,
  350. phwDeviceExtension);
  351. OUTPW(HI_SEQ_ADDR, 0x0100);
  352. }
  353. else{
  354. EE_control(EEPROM);
  355. }
  356. return;
  357. }
  358. /*
  359. * void ee_cmd_vga(uiInstruct);
  360. *
  361. * unsigned short uiInstruct; Opcode and address to send
  362. *
  363. * Sends EEPROM opcode and address to the EEPROM. The uiInstruct
  364. * parameter holds the 5 bit opcode and 6 bit index in the
  365. * format xxxx xOOO OOII IIII, where:
  366. * x is an unused bit
  367. * O is an opcode bit
  368. * I is an index bit
  369. */
  370. void ee_cmd_vga(unsigned short uiInstruct)
  371. {
  372. struct st_eeprom_data *ee = phwDeviceExtension->ee;
  373. int iCount; /* Loop counter */
  374. /*
  375. * Mask showing which bit to test when sending the opcode or the address.
  376. */
  377. unsigned short uiBitTest;
  378. /*
  379. * Get the initial value for the I/O register which
  380. * will have its bits forced to specific values.
  381. */
  382. VideoPortSynchronizeExecution(phwDeviceExtension,
  383. VpHighPriority,
  384. (PMINIPORT_SYNCHRONIZE_ROUTINE) ee_init_io,
  385. phwDeviceExtension);
  386. ee_clock_vga();
  387. zEepromIOPort.byte.high &= (~EE_DI);
  388. zEepromIOPort.byte.high |= (EE_ENABLE | EE_CS); /* Enable the EEPROM and select the chip */
  389. OUTPW(ati_reg, zEepromIOPort.word);
  390. ee_clock_vga();
  391. /*
  392. * Send the opcode.
  393. */
  394. uiBitTest = 0x400;
  395. for (iCount = 0; iCount < 3; iCount++)
  396. {
  397. if (uiInstruct & uiBitTest)
  398. zEepromIOPort.byte.high |= EE_DI;
  399. else
  400. zEepromIOPort.byte.high &= (~EE_DI);
  401. OUTPW(ati_reg, zEepromIOPort.word);
  402. ee_clock_vga();
  403. uiBitTest >>= 1;
  404. }
  405. /*
  406. * We have finished with the opcode, now send the address.
  407. * Assume the EEPROM address is no longer than 8 bits
  408. * (256 word capacity). The Graphics Ultra series use
  409. * a 6 bit address (64 words), while the G.U. Plus and
  410. * Pro use 8 bits (but the EEPROM is only 128 words long).
  411. * Assume a 6 bit EEPROM address (64 word capacity).
  412. */
  413. uiBitTest = 0x01 << (ee->addr_size - 1);
  414. for (iCount = 0; iCount < ee->addr_size; iCount++)
  415. {
  416. if (uiBitTest & uiInstruct)
  417. zEepromIOPort.byte.high |= EE_DI;
  418. else
  419. zEepromIOPort.byte.high &= (~EE_DI);
  420. OUTPW(ati_reg, zEepromIOPort.word);
  421. ee_clock_vga();
  422. uiBitTest >>= 1;
  423. }
  424. return;
  425. }
  426. BOOLEAN
  427. ee_sel_eeprom (
  428. PVOID Context
  429. )
  430. /*++
  431. Routine Description:
  432. Selects the eeprom within the context of interrupts being disabled.
  433. This function must be called via a call to VideoPortSynchronizeRoutine.
  434. Arguments:
  435. Context - Context parameter passed to the synchronized routine.
  436. Must be a pointer to the miniport driver's device extension.
  437. Return Value:
  438. TRUE.
  439. --*/
  440. {
  441. union SplitWord zStatus; /* Status of the video card. */
  442. PHW_DEVICE_EXTENSION phwDeviceExtension = Context;
  443. OUTP(ati_reg, SYNC_I);
  444. zStatus.byte.high = INP(ati_reg + 1);
  445. zStatus.byte.low = SYNC_I;
  446. /*
  447. * Preserve the status so ee_deselect_vga() can restore it.
  448. */
  449. zOrigStat.word = zStatus.word;
  450. /*
  451. * Unlock the EEPROM to allow reading/writing.
  452. */
  453. zStatus.byte.high &= ~L_ALL;
  454. OUTPW(ati_reg, zStatus.word);
  455. return TRUE;
  456. }
  457. BOOLEAN
  458. ee_init_io (
  459. PVOID Context
  460. )
  461. /*++
  462. Routine Description:
  463. Gets the initial value for the I/O register which
  464. will have its bits forced to specific values.
  465. This function must be called via a call to VideoPortSynchronizeRoutine.
  466. Arguments:
  467. Context - Context parameter passed to the synchronized routine.
  468. Must be a pointer to the miniport driver's device extension.
  469. Return Value:
  470. TRUE.
  471. --*/
  472. {
  473. PHW_DEVICE_EXTENSION phwDeviceExtension = Context;
  474. zEepromIOPort.byte.low = EE_WREG;
  475. OUTP(ati_reg, zEepromIOPort.byte.low);
  476. zEepromIOPort.byte.high = INP(ati_reg + 1);
  477. return TRUE;
  478. }
  479. /*
  480. * static void ee_clock_vga(void);
  481. *
  482. * Toggle the EEPROM CLK line high then low.
  483. */
  484. static void ee_clock_vga(void)
  485. {
  486. ee_wait();
  487. zEepromIOPort.byte.high |= EE_CLK;
  488. OUTPW(ati_reg, zEepromIOPort.word);
  489. ee_wait();
  490. zEepromIOPort.byte.high &= ~EE_CLK;
  491. OUTPW(ati_reg, zEepromIOPort.word);
  492. return;
  493. }
  494. /*
  495. * static void EE_control(ucEepromStatus);
  496. *
  497. * unsigned char ucEepromStatus; Sets whether or not we should access the EEPROM
  498. *
  499. * Sets/resets the EEPROM bit of the data register at index MISC3_I.
  500. * This enables/disables EEPROM access.
  501. */
  502. static void EE_control(unsigned char ucEepromStatus)
  503. {
  504. union SplitWord zCtrlData; /* Data read/written at specified control port */
  505. /*
  506. * Set up to write to the MISC3_I index register, and initialize
  507. * the data field to the EEPROM status we want.
  508. */
  509. zCtrlData.byte.high = ucEepromStatus;
  510. zCtrlData.byte.low = MISC3_I;
  511. OUTP(ati_reg, zCtrlData.byte.low);
  512. /*
  513. * Read in the data which is stored at the index MISC3_I, and combine
  514. * its contents (other than the EEPROM enable/disable bit)
  515. * with the desired EEPROM status we received as a parameter.
  516. */
  517. zCtrlData.byte.high |= (INP(ati_reg + 1) & ~EEPROM);
  518. /*
  519. * Write the result back. All bits other than the EEPROM enable/disable
  520. * bit will be unmodified.
  521. */
  522. OUTPW(ati_reg, zCtrlData.word);
  523. return;
  524. }
  525. /*
  526. * static void ee_deselect_vga(void);
  527. *
  528. * Purpose: Disable EEPROM read/write
  529. */
  530. static void ee_deselect_vga(void)
  531. {
  532. zEepromIOPort.byte.high &= (~EE_CS);
  533. OUTPW(ati_reg, zEepromIOPort.word);
  534. ee_clock_vga();
  535. zEepromIOPort.byte.high &= (~EE_ENABLE);
  536. OUTPW(ati_reg, zEepromIOPort.word);
  537. if (vga_chip <= '2')
  538. {
  539. OUTPW(HI_SEQ_ADDR, 0x0300);
  540. OUTPW(ati_reg, zOrigStat.word);
  541. }
  542. else{
  543. EE_control(0);
  544. }
  545. ee_wait();
  546. return;
  547. }
  548. /*
  549. * static void Write_ee(uiData);
  550. *
  551. * unsigned short uiData; Value to write to the EEPROM.
  552. *
  553. * Lower-level routine to write a word to the EEPROM.
  554. */
  555. static void Write_ee(unsigned short uiData)
  556. {
  557. int iCount; /* Loop counter */
  558. ee_sel_vga();
  559. ee_cmd_vga((unsigned short) (EE_WRITE | ucEepromWord));
  560. /*
  561. * Write out the word, one bit at a time.
  562. */
  563. for (iCount = 0; iCount < 16; iCount++)
  564. {
  565. if (uiData & 0x8000)
  566. zEepromIOPort.byte.high |= EE_DI;
  567. else
  568. zEepromIOPort.byte.high &= (~EE_DI);
  569. OUTPW(ati_reg, zEepromIOPort.word);
  570. ee_clock_vga();
  571. uiData = uiData << 1;
  572. }
  573. ee_deselect_vga();
  574. return;
  575. }
  576. /*
  577. * Static void Enabl_ee(void);
  578. *
  579. * This is a lower-level routine to enable the EEPROM.
  580. */
  581. static void Enabl_ee()
  582. {
  583. ee_sel_vga();
  584. ee_cmd_vga((EE_ENAB | 0x3f));
  585. ee_deselect_vga();
  586. return;
  587. }
  588. /*
  589. * Static void Disab_ee(void);
  590. *
  591. * This is a lower-level routine to disable the EEPROM.
  592. */
  593. static void Disab_ee(void)
  594. {
  595. ee_sel_vga();
  596. ee_cmd_vga((EE_DISAB | 0x00));
  597. ee_deselect_vga();
  598. return;
  599. }
  600. /*
  601. * Static void Erase_ee(void);
  602. *
  603. * This is a lower-level routine to erase the EEPROM.
  604. */
  605. static void Erase_ee(void)
  606. {
  607. ee_sel_vga();
  608. ee_cmd_vga((unsigned short) (EE_ERASE | ucEepromWord));
  609. ee_deselect_vga();
  610. return;
  611. }