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