CirrusLogic5430UgaDraw.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418
  1. /** @file
  2. This file produces the graphics abstration of UGA Draw. It is called by
  3. CirrusLogic5430.c file which deals with the EFI 1.1 driver model.
  4. This file just does graphics.
  5. Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
  6. This program and the accompanying materials
  7. are licensed and made available under the terms and conditions of the BSD License
  8. which accompanies this distribution. The full text of the license may be found at
  9. http://opensource.org/licenses/bsd-license.php
  10. THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
  11. WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
  12. **/
  13. #include "CirrusLogic5430.h"
  14. //
  15. // UGA Draw Protocol Member Functions
  16. //
  17. EFI_STATUS
  18. EFIAPI
  19. CirrusLogic5430UgaDrawGetMode (
  20. IN EFI_UGA_DRAW_PROTOCOL *This,
  21. OUT UINT32 *HorizontalResolution,
  22. OUT UINT32 *VerticalResolution,
  23. OUT UINT32 *ColorDepth,
  24. OUT UINT32 *RefreshRate
  25. )
  26. {
  27. CIRRUS_LOGIC_5430_PRIVATE_DATA *Private;
  28. Private = CIRRUS_LOGIC_5430_PRIVATE_DATA_FROM_UGA_DRAW_THIS (This);
  29. if (Private->HardwareNeedsStarting) {
  30. return EFI_NOT_STARTED;
  31. }
  32. if ((HorizontalResolution == NULL) ||
  33. (VerticalResolution == NULL) ||
  34. (ColorDepth == NULL) ||
  35. (RefreshRate == NULL)) {
  36. return EFI_INVALID_PARAMETER;
  37. }
  38. *HorizontalResolution = Private->ModeData[Private->CurrentMode].HorizontalResolution;
  39. *VerticalResolution = Private->ModeData[Private->CurrentMode].VerticalResolution;
  40. *ColorDepth = Private->ModeData[Private->CurrentMode].ColorDepth;
  41. *RefreshRate = Private->ModeData[Private->CurrentMode].RefreshRate;
  42. return EFI_SUCCESS;
  43. }
  44. EFI_STATUS
  45. EFIAPI
  46. CirrusLogic5430UgaDrawSetMode (
  47. IN EFI_UGA_DRAW_PROTOCOL *This,
  48. IN UINT32 HorizontalResolution,
  49. IN UINT32 VerticalResolution,
  50. IN UINT32 ColorDepth,
  51. IN UINT32 RefreshRate
  52. )
  53. {
  54. CIRRUS_LOGIC_5430_PRIVATE_DATA *Private;
  55. UINTN Index;
  56. Private = CIRRUS_LOGIC_5430_PRIVATE_DATA_FROM_UGA_DRAW_THIS (This);
  57. for (Index = 0; Index < Private->MaxMode; Index++) {
  58. if (HorizontalResolution != Private->ModeData[Index].HorizontalResolution) {
  59. continue;
  60. }
  61. if (VerticalResolution != Private->ModeData[Index].VerticalResolution) {
  62. continue;
  63. }
  64. if (ColorDepth != Private->ModeData[Index].ColorDepth) {
  65. continue;
  66. }
  67. if (RefreshRate != Private->ModeData[Index].RefreshRate) {
  68. continue;
  69. }
  70. if (Private->LineBuffer) {
  71. gBS->FreePool (Private->LineBuffer);
  72. }
  73. Private->LineBuffer = NULL;
  74. Private->LineBuffer = AllocatePool (HorizontalResolution);
  75. if (Private->LineBuffer == NULL) {
  76. return EFI_OUT_OF_RESOURCES;
  77. }
  78. InitializeGraphicsMode (Private, &CirrusLogic5430VideoModes[Private->ModeData[Index].ModeNumber]);
  79. Private->CurrentMode = Index;
  80. Private->HardwareNeedsStarting = FALSE;
  81. return EFI_SUCCESS;
  82. }
  83. return EFI_NOT_FOUND;
  84. }
  85. EFI_STATUS
  86. EFIAPI
  87. CirrusLogic5430UgaDrawBlt (
  88. IN EFI_UGA_DRAW_PROTOCOL *This,
  89. IN EFI_UGA_PIXEL *BltBuffer, OPTIONAL
  90. IN EFI_UGA_BLT_OPERATION BltOperation,
  91. IN UINTN SourceX,
  92. IN UINTN SourceY,
  93. IN UINTN DestinationX,
  94. IN UINTN DestinationY,
  95. IN UINTN Width,
  96. IN UINTN Height,
  97. IN UINTN Delta
  98. )
  99. {
  100. CIRRUS_LOGIC_5430_PRIVATE_DATA *Private;
  101. EFI_TPL OriginalTPL;
  102. UINTN DstY;
  103. UINTN SrcY;
  104. EFI_UGA_PIXEL *Blt;
  105. UINTN X;
  106. UINT8 Pixel;
  107. UINT32 WidePixel;
  108. UINTN ScreenWidth;
  109. UINTN Offset;
  110. UINTN SourceOffset;
  111. Private = CIRRUS_LOGIC_5430_PRIVATE_DATA_FROM_UGA_DRAW_THIS (This);
  112. if ((UINT32)BltOperation >= EfiUgaBltMax) {
  113. return EFI_INVALID_PARAMETER;
  114. }
  115. if (Width == 0 || Height == 0) {
  116. return EFI_INVALID_PARAMETER;
  117. }
  118. //
  119. // If Delta is zero, then the entire BltBuffer is being used, so Delta
  120. // is the number of bytes in each row of BltBuffer. Since BltBuffer is Width pixels size,
  121. // the number of bytes in each row can be computed.
  122. //
  123. if (Delta == 0) {
  124. Delta = Width * sizeof (EFI_UGA_PIXEL);
  125. }
  126. //
  127. // We need to fill the Virtual Screen buffer with the blt data.
  128. // The virtual screen is upside down, as the first row is the bootom row of
  129. // the image.
  130. //
  131. //
  132. // Make sure the SourceX, SourceY, DestinationX, DestinationY, Width, and Height parameters
  133. // are valid for the operation and the current screen geometry.
  134. //
  135. if (BltOperation == EfiUgaVideoToBltBuffer) {
  136. //
  137. // Video to BltBuffer: Source is Video, destination is BltBuffer
  138. //
  139. if (SourceY + Height > Private->ModeData[Private->CurrentMode].VerticalResolution) {
  140. return EFI_INVALID_PARAMETER;
  141. }
  142. if (SourceX + Width > Private->ModeData[Private->CurrentMode].HorizontalResolution) {
  143. return EFI_INVALID_PARAMETER;
  144. }
  145. } else {
  146. //
  147. // BltBuffer to Video: Source is BltBuffer, destination is Video
  148. //
  149. if (DestinationY + Height > Private->ModeData[Private->CurrentMode].VerticalResolution) {
  150. return EFI_INVALID_PARAMETER;
  151. }
  152. if (DestinationX + Width > Private->ModeData[Private->CurrentMode].HorizontalResolution) {
  153. return EFI_INVALID_PARAMETER;
  154. }
  155. }
  156. //
  157. // We have to raise to TPL Notify, so we make an atomic write the frame buffer.
  158. // We would not want a timer based event (Cursor, ...) to come in while we are
  159. // doing this operation.
  160. //
  161. OriginalTPL = gBS->RaiseTPL (TPL_NOTIFY);
  162. switch (BltOperation) {
  163. case EfiUgaVideoToBltBuffer:
  164. //
  165. // Video to BltBuffer: Source is Video, destination is BltBuffer
  166. //
  167. for (SrcY = SourceY, DstY = DestinationY; DstY < (Height + DestinationY); SrcY++, DstY++) {
  168. Offset = (SrcY * Private->ModeData[Private->CurrentMode].HorizontalResolution) + SourceX;
  169. if (((Offset & 0x03) == 0) && ((Width & 0x03) == 0)) {
  170. Private->PciIo->Mem.Read (
  171. Private->PciIo,
  172. EfiPciIoWidthUint32,
  173. 0,
  174. Offset,
  175. Width >> 2,
  176. Private->LineBuffer
  177. );
  178. } else {
  179. Private->PciIo->Mem.Read (
  180. Private->PciIo,
  181. EfiPciIoWidthUint8,
  182. 0,
  183. Offset,
  184. Width,
  185. Private->LineBuffer
  186. );
  187. }
  188. for (X = 0; X < Width; X++) {
  189. Blt = (EFI_UGA_PIXEL *) ((UINT8 *) BltBuffer + (DstY * Delta) + (DestinationX + X) * sizeof (EFI_UGA_PIXEL));
  190. Blt->Red = (UINT8) (Private->LineBuffer[X] & 0xe0);
  191. Blt->Green = (UINT8) ((Private->LineBuffer[X] & 0x1c) << 3);
  192. Blt->Blue = (UINT8) ((Private->LineBuffer[X] & 0x03) << 6);
  193. }
  194. }
  195. break;
  196. case EfiUgaVideoToVideo:
  197. //
  198. // Perform hardware acceleration for Video to Video operations
  199. //
  200. ScreenWidth = Private->ModeData[Private->CurrentMode].HorizontalResolution;
  201. SourceOffset = (SourceY * Private->ModeData[Private->CurrentMode].HorizontalResolution) + (SourceX);
  202. Offset = (DestinationY * Private->ModeData[Private->CurrentMode].HorizontalResolution) + (DestinationX);
  203. outw (Private, GRAPH_ADDRESS_REGISTER, 0x0000);
  204. outw (Private, GRAPH_ADDRESS_REGISTER, 0x0010);
  205. outw (Private, GRAPH_ADDRESS_REGISTER, 0x0012);
  206. outw (Private, GRAPH_ADDRESS_REGISTER, 0x0014);
  207. outw (Private, GRAPH_ADDRESS_REGISTER, 0x0001);
  208. outw (Private, GRAPH_ADDRESS_REGISTER, 0x0011);
  209. outw (Private, GRAPH_ADDRESS_REGISTER, 0x0013);
  210. outw (Private, GRAPH_ADDRESS_REGISTER, 0x0015);
  211. outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) (((Width << 8) & 0xff00) | 0x20));
  212. outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) ((Width & 0xff00) | 0x21));
  213. outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) (((Height << 8) & 0xff00) | 0x22));
  214. outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) ((Height & 0xff00) | 0x23));
  215. outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) (((ScreenWidth << 8) & 0xff00) | 0x24));
  216. outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) ((ScreenWidth & 0xff00) | 0x25));
  217. outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) (((ScreenWidth << 8) & 0xff00) | 0x26));
  218. outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) ((ScreenWidth & 0xff00) | 0x27));
  219. outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) ((((Offset) << 8) & 0xff00) | 0x28));
  220. outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) ((((Offset) >> 0) & 0xff00) | 0x29));
  221. outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) ((((Offset) >> 8) & 0xff00) | 0x2a));
  222. outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) ((((SourceOffset) << 8) & 0xff00) | 0x2c));
  223. outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) ((((SourceOffset) >> 0) & 0xff00) | 0x2d));
  224. outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) ((((SourceOffset) >> 8) & 0xff00) | 0x2e));
  225. outw (Private, GRAPH_ADDRESS_REGISTER, 0x002f);
  226. outw (Private, GRAPH_ADDRESS_REGISTER, 0x0030);
  227. outw (Private, GRAPH_ADDRESS_REGISTER, 0x0d32);
  228. outw (Private, GRAPH_ADDRESS_REGISTER, 0x0033);
  229. outw (Private, GRAPH_ADDRESS_REGISTER, 0x0034);
  230. outw (Private, GRAPH_ADDRESS_REGISTER, 0x0035);
  231. outw (Private, GRAPH_ADDRESS_REGISTER, 0x0231);
  232. outb (Private, GRAPH_ADDRESS_REGISTER, 0x31);
  233. while ((inb (Private, GRAPH_DATA_REGISTER) & 0x01) == 0x01)
  234. ;
  235. break;
  236. case EfiUgaVideoFill:
  237. Blt = BltBuffer;
  238. Pixel = (UINT8) ((Blt->Red & 0xe0) | ((Blt->Green >> 3) & 0x1c) | ((Blt->Blue >> 6) & 0x03));
  239. WidePixel = (Pixel << 8) | Pixel;
  240. WidePixel = (WidePixel << 16) | WidePixel;
  241. if (DestinationX == 0 && Width == Private->ModeData[Private->CurrentMode].HorizontalResolution) {
  242. Offset = DestinationY * Private->ModeData[Private->CurrentMode].HorizontalResolution;
  243. if (((Offset & 0x03) == 0) && (((Width * Height) & 0x03) == 0)) {
  244. Private->PciIo->Mem.Write (
  245. Private->PciIo,
  246. EfiPciIoWidthFillUint32,
  247. 0,
  248. Offset,
  249. (Width * Height) >> 2,
  250. &WidePixel
  251. );
  252. } else {
  253. Private->PciIo->Mem.Write (
  254. Private->PciIo,
  255. EfiPciIoWidthFillUint8,
  256. 0,
  257. Offset,
  258. Width * Height,
  259. &Pixel
  260. );
  261. }
  262. } else {
  263. for (SrcY = SourceY, DstY = DestinationY; SrcY < (Height + SourceY); SrcY++, DstY++) {
  264. Offset = (DstY * Private->ModeData[Private->CurrentMode].HorizontalResolution) + DestinationX;
  265. if (((Offset & 0x03) == 0) && ((Width & 0x03) == 0)) {
  266. Private->PciIo->Mem.Write (
  267. Private->PciIo,
  268. EfiPciIoWidthFillUint32,
  269. 0,
  270. Offset,
  271. Width >> 2,
  272. &WidePixel
  273. );
  274. } else {
  275. Private->PciIo->Mem.Write (
  276. Private->PciIo,
  277. EfiPciIoWidthFillUint8,
  278. 0,
  279. Offset,
  280. Width,
  281. &Pixel
  282. );
  283. }
  284. }
  285. }
  286. break;
  287. case EfiUgaBltBufferToVideo:
  288. for (SrcY = SourceY, DstY = DestinationY; SrcY < (Height + SourceY); SrcY++, DstY++) {
  289. for (X = 0; X < Width; X++) {
  290. Blt = (EFI_UGA_PIXEL *) ((UINT8 *) BltBuffer + (SrcY * Delta) + (SourceX + X) * sizeof (EFI_UGA_PIXEL));
  291. Private->LineBuffer[X] = (UINT8) ((Blt->Red & 0xe0) | ((Blt->Green >> 3) & 0x1c) | ((Blt->Blue >> 6) & 0x03));
  292. }
  293. Offset = (DstY * Private->ModeData[Private->CurrentMode].HorizontalResolution) + DestinationX;
  294. if (((Offset & 0x03) == 0) && ((Width & 0x03) == 0)) {
  295. Private->PciIo->Mem.Write (
  296. Private->PciIo,
  297. EfiPciIoWidthUint32,
  298. 0,
  299. Offset,
  300. Width >> 2,
  301. Private->LineBuffer
  302. );
  303. } else {
  304. Private->PciIo->Mem.Write (
  305. Private->PciIo,
  306. EfiPciIoWidthUint8,
  307. 0,
  308. Offset,
  309. Width,
  310. Private->LineBuffer
  311. );
  312. }
  313. }
  314. break;
  315. default:
  316. break;
  317. }
  318. gBS->RestoreTPL (OriginalTPL);
  319. return EFI_SUCCESS;
  320. }
  321. //
  322. // Construction and Destruction functions
  323. //
  324. EFI_STATUS
  325. CirrusLogic5430UgaDrawConstructor (
  326. CIRRUS_LOGIC_5430_PRIVATE_DATA *Private
  327. )
  328. {
  329. EFI_UGA_DRAW_PROTOCOL *UgaDraw;
  330. //
  331. // Fill in Private->UgaDraw protocol
  332. //
  333. UgaDraw = &Private->UgaDraw;
  334. UgaDraw->GetMode = CirrusLogic5430UgaDrawGetMode;
  335. UgaDraw->SetMode = CirrusLogic5430UgaDrawSetMode;
  336. UgaDraw->Blt = CirrusLogic5430UgaDrawBlt;
  337. //
  338. // Initialize the private data
  339. //
  340. Private->CurrentMode = 0;
  341. Private->HardwareNeedsStarting = TRUE;
  342. Private->LineBuffer = NULL;
  343. //
  344. // Initialize the hardware
  345. //
  346. UgaDraw->SetMode (
  347. UgaDraw,
  348. Private->ModeData[Private->CurrentMode].HorizontalResolution,
  349. Private->ModeData[Private->CurrentMode].VerticalResolution,
  350. Private->ModeData[Private->CurrentMode].ColorDepth,
  351. Private->ModeData[Private->CurrentMode].RefreshRate
  352. );
  353. DrawLogo (
  354. Private,
  355. Private->ModeData[Private->CurrentMode].HorizontalResolution,
  356. Private->ModeData[Private->CurrentMode].VerticalResolution
  357. );
  358. return EFI_SUCCESS;
  359. }