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.

1291 lines
28 KiB

  1. //
  2. // vga routines
  3. //
  4. #include "bldr.h"
  5. #include "vga.h"
  6. #include "cmdcnst.h"
  7. PUCHAR VgaBase = (PUCHAR)0xa0000;
  8. PUCHAR VgaRegisterBase = (PUCHAR)0;
  9. //
  10. // globals to track screen position
  11. //
  12. #define DELTA 80L
  13. BOOLEAN
  14. VgaInterpretCmdStream(
  15. PUSHORT pusCmdStream
  16. );
  17. UCHAR lMaskTable[8] = {0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01};
  18. UCHAR rMaskTable[8] = {0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff};
  19. UCHAR PixelMask[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
  20. //
  21. // Initialize AT registers
  22. //
  23. USHORT AT_Initialization[] = {
  24. IB, // prepare atc for writing
  25. INPUT_STATUS_1_COLOR,
  26. METAOUT+ATCOUT, // program attribute controller registers
  27. ATT_ADDRESS_PORT, // port
  28. 16, // count
  29. 0, // start index
  30. 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,
  31. IB, // prepare atc for writing
  32. INPUT_STATUS_1_COLOR,
  33. OB, // turn video on.
  34. ATT_ADDRESS_PORT,
  35. VIDEO_ENABLE,
  36. EOD
  37. };
  38. ULONG lookup[16] =
  39. {
  40. 0x00000000,
  41. 0x00000100,
  42. 0x00001000,
  43. 0x00001100,
  44. 0x00000001,
  45. 0x00000101,
  46. 0x00001001,
  47. 0x00001101,
  48. 0x00000010,
  49. 0x00000110,
  50. 0x00001010,
  51. 0x00001110,
  52. 0x00000011,
  53. 0x00000111,
  54. 0x00001011,
  55. 0x00001111
  56. };
  57. void __outpw(int p, int v)
  58. {
  59. WRITE_PORT_USHORT((PUSHORT)(p+VgaRegisterBase), (USHORT)v);
  60. }
  61. void __outpb(int p, int v)
  62. {
  63. WRITE_PORT_UCHAR((PUCHAR)(p+VgaRegisterBase), (UCHAR)v);
  64. }
  65. VOID
  66. ReadWriteMode(
  67. ULONG mode
  68. )
  69. {
  70. UCHAR value;
  71. WRITE_PORT_UCHAR((PUCHAR)(VgaRegisterBase+0x3ce), 5);
  72. value = READ_PORT_UCHAR((PUCHAR)(VgaRegisterBase+0x3cf));
  73. value &= 0xf4;
  74. value |= mode;
  75. WRITE_PORT_UCHAR((PUCHAR)(VgaRegisterBase+0x3cf), value);
  76. }
  77. VOID
  78. SetPixel(
  79. ULONG x,
  80. ULONG y,
  81. ULONG color
  82. )
  83. {
  84. PUCHAR pDst;
  85. ULONG bank;
  86. bank = x >> 3;
  87. pDst = (char *)(VgaBase + y * DELTA + bank);
  88. ReadWriteMode(0x8 | 0x2);
  89. __outpw(0x3c4, 0x0f02); // enable all write planes
  90. __outpw(0x3ce, 0x0007); // set color don't care register to zero
  91. __outpw(0x3ce, (PixelMask[x & 0x7] << 8) | 8);
  92. WRITE_REGISTER_UCHAR(pDst, (UCHAR)(READ_REGISTER_UCHAR(pDst) & ((UCHAR)color)));
  93. }
  94. VOID
  95. VidSolidColorFill(
  96. ULONG x1,
  97. ULONG y1,
  98. ULONG x2,
  99. ULONG y2,
  100. ULONG color
  101. )
  102. {
  103. PUCHAR pDst;
  104. ULONG x, y;
  105. ULONG bank1, bank2, count;
  106. ULONG lMask, rMask;
  107. lMask = (lMaskTable[x1 & 0x7] << 8) | 8;
  108. rMask = (rMaskTable[x2 & 0x7] << 8) | 8;
  109. bank1 = x1 >> 3;
  110. bank2 = x2 >> 3;
  111. count = bank2 - bank1;
  112. if (!count) {
  113. lMask = lMask & rMask;
  114. }
  115. ReadWriteMode(0x8 | 0x2);
  116. __outpw(0x3c4, 0x0f02); // enable writing to all color planes
  117. __outpw(0x3ce, 0x0007); // set color don't care register to zero
  118. //
  119. // Do the left edge
  120. //
  121. pDst = (char *)(VgaBase + y1 * DELTA + bank1);
  122. __outpw(0x3ce, lMask);
  123. for (y=y1; y<=y2; y++) {
  124. WRITE_REGISTER_UCHAR(pDst, (UCHAR)(READ_REGISTER_UCHAR(pDst) & (UCHAR) color));
  125. pDst += DELTA;
  126. }
  127. if (count) {
  128. //
  129. // Do the right edge
  130. //
  131. pDst = (char *)(VgaBase + y1 * DELTA + bank2);
  132. count--;
  133. __outpw(0x3ce, rMask);
  134. for (y=y1; y<=y2; y++) {
  135. WRITE_REGISTER_UCHAR(pDst, (UCHAR)(READ_REGISTER_UCHAR(pDst) & (UCHAR) color));
  136. pDst += DELTA;
  137. }
  138. //
  139. // Do the center section
  140. //
  141. if (count) {
  142. pDst = (char *)(VgaBase + y1 * DELTA + bank1 + 1);
  143. __outpw(0x3ce, 0xff08);
  144. for (y=y1; y<=y2; y++) {
  145. for (x=0; x<count; x++) {
  146. WRITE_REGISTER_UCHAR(pDst++, (unsigned char) color);
  147. }
  148. pDst += DELTA - count;
  149. }
  150. }
  151. }
  152. }
  153. VOID
  154. RleBitBlt(
  155. ULONG x,
  156. ULONG y,
  157. ULONG width,
  158. ULONG height,
  159. PUCHAR Buffer
  160. )
  161. /*++
  162. Routine Description:
  163. This routine displays an RLE 4 bitmap.
  164. Arguments:
  165. x, y - location at which to display the bitmap.
  166. width, height - height of the bitmap
  167. Buffer - Pointer to the compressed bitmap data.
  168. --*/
  169. {
  170. BOOLEAN Done = FALSE;
  171. PUCHAR p = Buffer;
  172. ULONG RunLength;
  173. LONG RunExtra;
  174. ULONG curr_x, curr_y;
  175. ULONG Color1, Color2;
  176. curr_x = x;
  177. curr_y = y + height - 1;
  178. while (!Done) {
  179. if (*p) {
  180. RunLength = (ULONG) *p++;
  181. //
  182. // Make sure we don't draw past end of scan.
  183. //
  184. if ((curr_x + RunLength) > (x + width))
  185. RunLength -= (curr_x + RunLength) - (width + x);
  186. Color1 = (*p & 0xf0) >> 4;
  187. Color2 = (*p++ & 0x0f);
  188. if (Color1 == Color2) {
  189. ULONG end_x = curr_x + RunLength - 1;
  190. VidSolidColorFill(curr_x,
  191. curr_y,
  192. end_x,
  193. curr_y,
  194. Color1);
  195. curr_x += RunLength;
  196. } else {
  197. while (RunLength > 1) {
  198. SetPixel(curr_x++, curr_y, Color1);
  199. SetPixel(curr_x++, curr_y, Color2);
  200. RunLength -= 2;
  201. }
  202. if (RunLength) {
  203. SetPixel(curr_x, curr_y, Color1);
  204. curr_x++;
  205. }
  206. }
  207. } else {
  208. p++;
  209. switch (*p) {
  210. case 0: curr_x = x;
  211. curr_y--;
  212. p++;
  213. break;
  214. case 1: Done = TRUE;
  215. p++;
  216. break;
  217. case 2: p++;
  218. curr_x += (ULONG) *p++;
  219. curr_y -= (ULONG) *p++;
  220. break;
  221. default: RunLength = (ULONG) *p++;
  222. //
  223. // Make sure we don't draw past end of scan.
  224. //
  225. if ((curr_x + RunLength) > (x + width)) {
  226. RunExtra = (curr_x + RunLength) - (width + x);
  227. RunLength -= RunExtra;
  228. } else {
  229. RunExtra = 0;
  230. }
  231. while (RunLength > 1) {
  232. Color1 = (*p & 0xf0) >> 4;
  233. Color2 = (*p++ & 0x0f);
  234. SetPixel(curr_x++, curr_y, Color1);
  235. SetPixel(curr_x++, curr_y, Color2);
  236. RunLength -= 2;
  237. }
  238. if (RunLength) {
  239. Color1 = (*p++ & 0xf0) >> 4;
  240. SetPixel(curr_x++, curr_y, Color1);
  241. RunExtra--;
  242. }
  243. //
  244. // Read any remaining "extra" run data.
  245. //
  246. while (RunExtra > 0) {
  247. p++;
  248. RunExtra -= 2;
  249. }
  250. if ((ULONG_PTR)p & 1) p++; // make sure we are word aligned
  251. break;
  252. }
  253. }
  254. }
  255. }
  256. VOID
  257. BitBlt(
  258. ULONG x,
  259. ULONG y,
  260. ULONG width,
  261. ULONG height,
  262. PUCHAR Buffer,
  263. ULONG bpp,
  264. LONG ScanWidth
  265. )
  266. {
  267. ULONG i, j;
  268. ULONG color=8;
  269. if (bpp == 4) {
  270. UCHAR Plane[81];
  271. ULONG lMask, rMask, count;
  272. ULONG bank1, bank2, bank;
  273. ULONG bRightEdge = FALSE, bCenterSection = FALSE;
  274. UCHAR value;
  275. ULONG plane;
  276. UCHAR Mask;
  277. ULONG toggle;
  278. PUCHAR pSrc, pSrcTemp;
  279. PUCHAR pDst, pDstTemp;
  280. UCHAR PlaneMask;
  281. lMask = lMaskTable[x & 0x7];
  282. rMask = rMaskTable[(x + width - 1) & 0x7];
  283. bank1 = x >> 3;
  284. bank2 = (x + width - 1) >> 3;
  285. count = bank2 - bank1;
  286. if (bank1 == bank2) {
  287. lMask = lMask & rMask;
  288. }
  289. if (count) {
  290. bRightEdge = TRUE;
  291. count--;
  292. if (count) {
  293. bCenterSection = TRUE;
  294. }
  295. }
  296. pDst = (PUCHAR)(VgaBase + (y * DELTA) + (x / 8));
  297. pSrc = Buffer;
  298. ReadWriteMode(0x0 | 0x0);
  299. for (j=0; j<height; j++) {
  300. for (plane=0; plane<4; plane++) {
  301. pSrcTemp = pSrc;
  302. pDstTemp = pDst;
  303. PlaneMask = 1 << plane;
  304. //
  305. // Convert the packed bitmap data into planar data
  306. // for this plane.
  307. //
  308. // BUGBUG: My guess this is going to be a hot spot, so
  309. // I need to revist this and optimize!! But for now
  310. // make it work.
  311. //
  312. bank = bank1;
  313. Plane[bank] = 0;
  314. Mask = PixelMask[x & 0x7];
  315. toggle = 0;
  316. for (i=0; i<width; i++) {
  317. if (toggle++ & 0x1) {
  318. if (*pSrcTemp & PlaneMask) {
  319. Plane[bank] |= Mask;
  320. }
  321. pSrcTemp++;
  322. } else {
  323. if (((*pSrcTemp) >> 4) & PlaneMask) {
  324. Plane[bank] |= Mask;
  325. }
  326. }
  327. Mask >>= 1;
  328. if (!Mask) {
  329. bank++;
  330. Plane[bank] = 0;
  331. Mask = 0x80;
  332. }
  333. }
  334. //
  335. // Set up the vga so that we see the correct bit plane.
  336. //
  337. __outpw(0x3c4, (1 << (plane + 8)) | 2);
  338. //
  339. // bank will go from bank1 to bank2
  340. //
  341. bank = bank1;
  342. pDstTemp = pDst;
  343. //
  344. // Set Bitmask for left edge.
  345. //
  346. __outpw(0x3ce, (lMask << 8) | 8);
  347. value = READ_REGISTER_UCHAR(pDstTemp);
  348. value &= ~lMask;
  349. value |= Plane[bank++];
  350. WRITE_REGISTER_UCHAR(pDstTemp++, value);
  351. if (bCenterSection) {
  352. __outpw(0x3ce, 0xff08); // enable writing to all bits
  353. for (i=0; i<count; i++) {
  354. WRITE_REGISTER_UCHAR(pDstTemp++, Plane[bank++]);
  355. }
  356. }
  357. if (bRightEdge) {
  358. //
  359. // Set bitmask for right edge.
  360. //
  361. __outpw(0x3ce, (rMask << 8) | 8);
  362. value = READ_REGISTER_UCHAR(pDstTemp);
  363. value &= ~rMask;
  364. value |= Plane[bank];
  365. WRITE_REGISTER_UCHAR(pDstTemp, value);
  366. }
  367. }
  368. pDst += DELTA;
  369. pSrc += ScanWidth;
  370. }
  371. } else {
  372. PUCHAR pDst, pDstTemp;
  373. PUCHAR pSrc, pSrcTemp;
  374. ULONG count;
  375. UCHAR Value;
  376. ULONG lMask, rMask;
  377. ULONG bank1, bank2;
  378. ULONG plane;
  379. UCHAR colorMask;
  380. bank1 = x >> 8;
  381. bank2 = (x + width - 1) >> 8;
  382. lMask = lMaskTable[x & 7];
  383. rMask = rMaskTable[(x + width - 1) & 7];
  384. if (bank1 == bank2) {
  385. lMask &= rMask;
  386. }
  387. lMask = ~lMask;
  388. rMask = ~rMask;
  389. pSrc = Buffer;
  390. pDst = (PUCHAR)(VgaBase + (y * DELTA) + (x / 8));
  391. ReadWriteMode(0x0 | 0x0);
  392. for (j=0; j<height; j++) {
  393. plane = 1;
  394. for (i=0; i<4; i++) {
  395. pDstTemp = pDst;
  396. pSrcTemp = pSrc;
  397. __outpw(0x3c4, (plane << 8) | 2);
  398. colorMask = (UCHAR)((color & plane) ? 0xff : 0x00);
  399. plane <<= 1; // bump up each time through loop
  400. count = width;
  401. //
  402. // non aligned case
  403. //
  404. if (x & 7) {
  405. //
  406. // Left Edge.
  407. //
  408. Value = READ_REGISTER_UCHAR(pDstTemp);
  409. Value &= lMask;
  410. Value |= (*pSrcTemp >> x) & colorMask;
  411. WRITE_REGISTER_UCHAR(pDstTemp++, Value);
  412. count -= (8 - x);
  413. //
  414. // Now do center section
  415. //
  416. while (count > 7) {
  417. Value = (*pSrcTemp << (8 - x)) | (*(pSrcTemp+1) >> x);
  418. Value &= colorMask;
  419. WRITE_REGISTER_UCHAR(pDstTemp++, Value);
  420. pSrcTemp++;
  421. count -= 8;
  422. }
  423. //
  424. // Now do the right edge.
  425. //
  426. if (count) {
  427. Value = READ_REGISTER_UCHAR(pDstTemp);
  428. Value &= rMask;
  429. Value |= *pSrcTemp << (8 - x) & colorMask;
  430. WRITE_REGISTER_UCHAR(pDstTemp++, Value);
  431. }
  432. } else {
  433. //
  434. // Aligned case.
  435. //
  436. ULONG ulColorMask = colorMask ? 0xffffffff : 0x00000000;
  437. USHORT usColorMask = colorMask ? 0xffff : 0x0000;
  438. while (count > 31) {
  439. WRITE_REGISTER_ULONG(((PULONG)pDstTemp)++, (ULONG)((*((PULONG)pSrcTemp)++) & ulColorMask));
  440. count -= 32;
  441. }
  442. while (count > 15) {
  443. WRITE_REGISTER_USHORT(((PUSHORT)pDstTemp)++, (USHORT)((*((PUSHORT)pSrcTemp)++) & usColorMask));
  444. count -= 16;
  445. }
  446. if (count > 7) {
  447. WRITE_REGISTER_UCHAR(pDstTemp++, (UCHAR)(*pSrcTemp++ & colorMask));
  448. count -= 8;
  449. }
  450. //
  451. // Now do any remaining bits.
  452. //
  453. if (count) {
  454. Value = READ_REGISTER_UCHAR(pDstTemp);
  455. Value &= rMask;
  456. Value |= *pSrcTemp & colorMask;
  457. WRITE_REGISTER_UCHAR(pDstTemp++, Value);
  458. }
  459. }
  460. }
  461. pSrc += ScanWidth;
  462. pDst += DELTA;
  463. }
  464. }
  465. }
  466. VOID
  467. VidBitBlt(
  468. PUCHAR Buffer,
  469. ULONG x,
  470. ULONG y
  471. )
  472. /*++
  473. Routine Description:
  474. This routine takes a bitmap resource and displays it at a given
  475. location.
  476. Arguments:
  477. Buffer - Pointer to the bitmap resource.
  478. x, y - The position at which to display the bitmap.
  479. --*/
  480. {
  481. PBITMAPFILEHEADER bfh;
  482. PBITMAPINFOHEADER bih;
  483. PRGBQUAD Palette;
  484. LONG lDelta;
  485. PUCHAR pBuffer;
  486. LONG cbScanLine;
  487. bih = (PBITMAPINFOHEADER) Buffer;
  488. Palette = (PRGBQUAD)(((PUCHAR)bih) + bih->biSize);
  489. //
  490. // BUGBUG: I need to add some bitmap validation code here!
  491. //
  492. cbScanLine = (((bih->biWidth * bih->biBitCount) + 31) & ~31) >> 3;
  493. pBuffer = (PUCHAR)(Buffer + sizeof(BITMAPINFOHEADER) + 64);
  494. if (bih->biCompression == BI_RLE4) {
  495. if (bih->biWidth && bih->biHeight) {
  496. RleBitBlt(x,
  497. y,
  498. bih->biWidth,
  499. bih->biHeight,
  500. pBuffer);
  501. }
  502. } else {
  503. if (bih->biHeight < 0) {
  504. // top down bitmap
  505. lDelta = cbScanLine;
  506. bih->biHeight = -bih->biHeight;
  507. } else {
  508. // bottom up bitmap
  509. pBuffer += cbScanLine * (bih->biHeight - 1);
  510. lDelta = -cbScanLine;
  511. }
  512. if (bih->biWidth && bih->biHeight) {
  513. BitBlt(x,
  514. y,
  515. bih->biWidth,
  516. bih->biHeight,
  517. pBuffer,
  518. bih->biBitCount,
  519. lDelta);
  520. }
  521. }
  522. }
  523. VOID
  524. VidScreenToBufferBlt(
  525. PUCHAR Buffer,
  526. ULONG x,
  527. ULONG y,
  528. ULONG width,
  529. ULONG height,
  530. ULONG lDelta
  531. )
  532. /*++
  533. Routine Description:
  534. This routine allows you to copy a portion of video memory into
  535. system memory.
  536. Arguments:
  537. Buffer - Points to system memory where the video image should be copied.
  538. x, y - X,Y coordinates in video memory of top-left portion of image.
  539. width, height - width and height of the image in pixels.
  540. lDelta - width of the buffer in bytes.
  541. Notes:
  542. Upon completion, the video memory image will be in system memory. Each
  543. plane of the image are stored seperately, so the first scan line of
  544. plane 0 will be followed by the first scan line of plane 1, etc. Then
  545. the second scan of plane 0, plane 1, and so on.
  546. --*/
  547. {
  548. ULONG Plane, i, j, BankStart, BankEnd;
  549. PUCHAR pSrc, pSrcTemp, pDst;
  550. PULONG pulDstTemp;
  551. UCHAR Val1, Val2;
  552. ULONG Shift1, Shift2;
  553. UCHAR ucCombined;
  554. ULONG ulCombined;
  555. BankStart = x >> 3;
  556. BankEnd = (x + width - 1) >> 3;
  557. Shift1 = x & 7;
  558. Shift2 = 8 - Shift1;
  559. //
  560. // Zero initialize the buffer so we can or in the bits later!
  561. //
  562. pDst = Buffer;
  563. memset(pDst, 0, lDelta * height);
  564. for (Plane=0; Plane<4; Plane++) {
  565. pSrc = (PUCHAR)(VgaBase + (DELTA * y) + BankStart);
  566. pDst = Buffer;
  567. ReadWriteMode(0x0 | 0x0); // set read mode 0
  568. __outpw(0x3ce, (Plane << 8) | 0x04); // read from given plane
  569. for (j=0; j<height; j++) {
  570. pSrcTemp = pSrc;
  571. pulDstTemp = (PULONG)pDst;
  572. Val1 = READ_REGISTER_UCHAR(pSrcTemp++);
  573. for (i=BankStart; i<=BankEnd; i++) {
  574. Val2 = READ_REGISTER_UCHAR(pSrcTemp++);
  575. ucCombined = (Val1 << Shift1) | (Val2 >> Shift2);
  576. ulCombined = ((lookup[(ucCombined & 0x0f) >> 0] << 16) |
  577. lookup[(ucCombined & 0xf0) >> 4]) << Plane;
  578. *pulDstTemp++ |= ulCombined;
  579. Val1 = Val2;
  580. }
  581. pSrc += DELTA; // go to next video memory scan line
  582. pDst += lDelta; // go to next scan for this plane in buffer
  583. }
  584. }
  585. }
  586. void VidBufferToScreenBlt(
  587. PUCHAR Buffer,
  588. ULONG x,
  589. ULONG y,
  590. ULONG width,
  591. ULONG height,
  592. ULONG lDelta
  593. )
  594. /*++
  595. Routine Description:
  596. This routine allows you to copy a portion of video memory into
  597. system memory.
  598. Arguments:
  599. Buffer - Points to system memory where the video image should be copied
  600. from.
  601. x, y - X,Y coordinates in video memory of top-left portion of image.
  602. width, height - width and height of the image in pixels.
  603. lDelta - width of the buffer in bytes.
  604. Notes:
  605. This routine will allow you to blt from a buffer filled by
  606. VidScreenToBufferBlt.
  607. --*/
  608. {
  609. if (width && height) {
  610. BitBlt(x,
  611. y,
  612. width,
  613. height,
  614. Buffer,
  615. 4,
  616. lDelta);
  617. }
  618. }
  619. #pragma optimize( "", off )
  620. VOID
  621. SetPaletteEntryRGB(
  622. ULONG index,
  623. RGBQUAD rgb
  624. )
  625. {
  626. __outpb(0x3c8, index);
  627. __outpb(0x3c9, rgb.rgbRed >> 2);
  628. __outpb(0x3c9, rgb.rgbGreen >> 2);
  629. __outpb(0x3c9, rgb.rgbBlue >> 2);
  630. }
  631. VOID
  632. VgaEnableVideo()
  633. {
  634. VgaInterpretCmdStream (AT_Initialization);
  635. }
  636. VOID
  637. InitPaletteConversionTable()
  638. {
  639. /*
  640. UCHAR n;
  641. READ_PORT_UCHAR((PUCHAR)(VgaRegisterBase+INPUT_STATUS_1_COLOR));
  642. for (n=0; n<16; n++) { // Initializing table of active palette entries.
  643. WRITE_PORT_UCHAR((PUCHAR)(VgaRegisterBase+ATT_ADDRESS_PORT), n);
  644. WRITE_PORT_UCHAR((PUCHAR)(VgaRegisterBase+ATT_ADDRESS_PORT), n);
  645. }
  646. */
  647. VgaEnableVideo();
  648. }
  649. VOID
  650. InitializePalette(
  651. VOID
  652. )
  653. {
  654. ULONG Palette[] =
  655. {
  656. 0x00000000,
  657. 0x00000020,
  658. 0x00002000,
  659. 0x00002020,
  660. 0x00200000,
  661. 0x00200020,
  662. 0x00202000,
  663. 0x00202020,
  664. 0x00303030,
  665. 0x0000003f,
  666. 0x00003f00,
  667. 0x00003f3f,
  668. 0x003f0000,
  669. 0x003f003f,
  670. 0x003f3f00,
  671. 0x003f3f3f,
  672. };
  673. ULONG i;
  674. for (i=0; i<16; i++) {
  675. PRGBQUAD p = (PRGBQUAD)(Palette+i);
  676. SetPaletteEntryRGB(i, *p);
  677. }
  678. }
  679. VOID
  680. InitPaletteWithTable(
  681. PRGBQUAD Palette,
  682. ULONG count
  683. )
  684. {
  685. UCHAR i;
  686. InitPaletteConversionTable();
  687. count = 16;
  688. for (i=0; i<count; i++)
  689. SetPaletteEntryRGB (i, *Palette++);
  690. }
  691. VOID
  692. InitPaletteWithBlack(
  693. VOID
  694. )
  695. {
  696. ULONG i;
  697. // RGBQUAD black = {0x3f,0x3f,0x3f,0x3f};
  698. RGBQUAD black = {0,0,0,0};
  699. InitPaletteConversionTable();
  700. //InitializePalette();
  701. for (i=0; i<16; i++)
  702. SetPaletteEntryRGB(i, black);
  703. }
  704. VOID
  705. WaitForVsync(
  706. VOID
  707. )
  708. /*++
  709. Routine Description:
  710. Wait for a v-sync
  711. --*/
  712. {
  713. //
  714. // Check to see if vsync's are being generated.
  715. //
  716. WRITE_PORT_UCHAR((VgaRegisterBase+0x3c4), 00);
  717. if (READ_PORT_UCHAR(VgaRegisterBase+0x3c5) & 0x2) {
  718. ULONG MaxDelay;
  719. //
  720. // Slight delay. Wait for one vsync.
  721. //
  722. MaxDelay = 100000;
  723. while (((READ_PORT_UCHAR(VgaRegisterBase+0x3da) & 0x08) == 0x08) && MaxDelay--);
  724. MaxDelay = 100000;
  725. while (((READ_PORT_UCHAR(VgaRegisterBase+0x3da) & 0x08) == 0x00) && MaxDelay--);
  726. }
  727. }
  728. BOOLEAN
  729. VgaInterpretCmdStream(
  730. PUSHORT pusCmdStream
  731. )
  732. /*++
  733. Routine Description:
  734. Interprets the appropriate command array to set up VGA registers for the
  735. requested mode. Typically used to set the VGA into a particular mode by
  736. programming all of the registers
  737. Arguments:
  738. pusCmdStream - array of commands to be interpreted.
  739. Return Value:
  740. The status of the operation (can only fail on a bad command); TRUE for
  741. success, FALSE for failure.
  742. --*/
  743. {
  744. ULONG ulCmd;
  745. ULONG_PTR ulPort;
  746. UCHAR jValue;
  747. USHORT usValue;
  748. ULONG culCount;
  749. ULONG ulIndex;
  750. ULONG_PTR ulBase;
  751. if (pusCmdStream == NULL) {
  752. //KdPrint(("VgaInterpretCmdStream: pusCmdStream == NULL\n"));
  753. return TRUE;
  754. }
  755. ulBase = (ULONG_PTR) VgaRegisterBase;
  756. //
  757. // Now set the adapter to the desired mode.
  758. //
  759. while ((ulCmd = *pusCmdStream++) != EOD) {
  760. WaitForVsync();
  761. //
  762. // Determine major command type
  763. //
  764. switch (ulCmd & 0xF0) {
  765. //
  766. // Basic input/output command
  767. //
  768. case INOUT:
  769. //
  770. // Determine type of inout instruction
  771. //
  772. if (!(ulCmd & IO)) {
  773. //
  774. // Out instruction. Single or multiple outs?
  775. //
  776. if (!(ulCmd & MULTI)) {
  777. //
  778. // Single out. Byte or word out?
  779. //
  780. if (!(ulCmd & BW)) {
  781. //
  782. // Single byte out
  783. //
  784. ulPort = *pusCmdStream++;
  785. jValue = (UCHAR) *pusCmdStream++;
  786. WRITE_PORT_UCHAR((PUCHAR)(ulBase+ulPort),
  787. jValue);
  788. } else {
  789. //
  790. // Single word out
  791. //
  792. ulPort = *pusCmdStream++;
  793. usValue = *pusCmdStream++;
  794. WRITE_PORT_USHORT((PUSHORT)(ulBase+ulPort),
  795. usValue);
  796. }
  797. } else {
  798. //
  799. // Output a string of values
  800. // Byte or word outs?
  801. //
  802. if (!(ulCmd & BW)) {
  803. //
  804. // String byte outs. Do in a loop; can't use
  805. // VideoPortWritePortBufferUchar because the data
  806. // is in USHORT form
  807. //
  808. ulPort = ulBase + *pusCmdStream++;
  809. culCount = *pusCmdStream++;
  810. while (culCount--) {
  811. jValue = (UCHAR) *pusCmdStream++;
  812. WRITE_PORT_UCHAR((PUCHAR)ulPort,
  813. jValue);
  814. }
  815. } else {
  816. //
  817. // String word outs
  818. //
  819. ulPort = *pusCmdStream++;
  820. culCount = *pusCmdStream++;
  821. WRITE_PORT_BUFFER_USHORT((PUSHORT)
  822. (ulBase + ulPort), pusCmdStream, culCount);
  823. pusCmdStream += culCount;
  824. }
  825. }
  826. } else {
  827. // In instruction
  828. //
  829. // Currently, string in instructions aren't supported; all
  830. // in instructions are handled as single-byte ins
  831. //
  832. // Byte or word in?
  833. //
  834. if (!(ulCmd & BW)) {
  835. //
  836. // Single byte in
  837. //
  838. ulPort = *pusCmdStream++;
  839. jValue = READ_PORT_UCHAR((PUCHAR)ulBase+ulPort);
  840. } else {
  841. //
  842. // Single word in
  843. //
  844. ulPort = *pusCmdStream++;
  845. usValue = READ_PORT_USHORT((PUSHORT)
  846. (ulBase+ulPort));
  847. }
  848. }
  849. break;
  850. //
  851. // Higher-level input/output commands
  852. //
  853. case METAOUT:
  854. //
  855. // Determine type of metaout command, based on minor
  856. // command field
  857. //
  858. switch (ulCmd & 0x0F) {
  859. //
  860. // Indexed outs
  861. //
  862. case INDXOUT:
  863. ulPort = ulBase + *pusCmdStream++;
  864. culCount = *pusCmdStream++;
  865. ulIndex = *pusCmdStream++;
  866. while (culCount--) {
  867. usValue = (USHORT) (ulIndex +
  868. (((ULONG)(*pusCmdStream++)) << 8));
  869. WRITE_PORT_USHORT((PUSHORT)ulPort, usValue);
  870. ulIndex++;
  871. }
  872. break;
  873. //
  874. // Masked out (read, AND, XOR, write)
  875. //
  876. case MASKOUT:
  877. ulPort = *pusCmdStream++;
  878. jValue = READ_PORT_UCHAR((PUCHAR)ulBase+ulPort);
  879. jValue &= *pusCmdStream++;
  880. jValue ^= *pusCmdStream++;
  881. WRITE_PORT_UCHAR((PUCHAR)ulBase + ulPort,
  882. jValue);
  883. break;
  884. //
  885. // Attribute Controller out
  886. //
  887. case ATCOUT:
  888. ulPort = ulBase + *pusCmdStream++;
  889. culCount = *pusCmdStream++;
  890. ulIndex = *pusCmdStream++;
  891. while (culCount--) {
  892. // Write Attribute Controller index
  893. WRITE_PORT_UCHAR((PUCHAR)ulPort,
  894. (UCHAR)ulIndex);
  895. // Write Attribute Controller data
  896. jValue = (UCHAR) *pusCmdStream++;
  897. WRITE_PORT_UCHAR((PUCHAR)ulPort, jValue);
  898. ulIndex++;
  899. }
  900. break;
  901. //
  902. // None of the above; error
  903. //
  904. default:
  905. return FALSE;
  906. }
  907. break;
  908. //
  909. // NOP
  910. //
  911. case NCMD:
  912. break;
  913. //
  914. // Unknown command; error
  915. //
  916. default:
  917. return FALSE;
  918. }
  919. }
  920. return TRUE;
  921. } // end VgaInterpretCmdStream()