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