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.

1289 lines
27 KiB

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