3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: hal/halx86/xbox/display_xbox.c
6 * PURPOSE: Blue screen display
7 * PROGRAMMER: Eric Kohl (ekohl@rz-online.de)
10 * Modified for Xbox 2004/12/02 GvG
13 /* For an explanation about display ownership see generic/display.c */
20 #define I2C_IO_BASE 0xc000
22 #define CONTROL_FRAMEBUFFER_ADDRESS_OFFSET 0x600800
24 #define MAKE_COLOR(Red, Green, Blue) (0xff000000 | (((Red) & 0xff) << 16) | (((Green) & 0xff) << 8) | ((Blue) & 0xff))
26 /* Default to grey on blue */
27 #define DEFAULT_FG_COLOR MAKE_COLOR(127, 127, 127)
28 #define DEFAULT_BG_COLOR MAKE_COLOR(0, 0, 127)
30 #define TAG_HALX TAG('H', 'A', 'L', 'X')
32 /* VARIABLES ****************************************************************/
34 static ULONG CursorX
= 0; /* Cursor Position */
35 static ULONG CursorY
= 0;
36 static ULONG SizeX
; /* Display size (characters) */
39 static BOOLEAN DisplayInitialized
= FALSE
;
40 static BOOLEAN HalOwnsDisplay
= TRUE
;
42 static PHAL_RESET_DISPLAY_PARAMETERS HalResetDisplayParameters
= NULL
;
45 #define CHAR_HEIGHT 16
47 static PVOID FrameBuffer
;
48 static ULONG BytesPerPixel
;
52 * It turns out that reading from the frame buffer is a pretty expensive
53 * operation. So, we're keeping shadow arrays of the contents and use
54 * those when needed (only for scrolling) instead of reading from the fb.
55 * This cuts down boot time from about 45 sec to about 6 sec.
57 static PUCHAR CellContents
;
58 static PULONG CellFgColor
;
59 static PULONG CellBgColor
;
61 /* PRIVATE FUNCTIONS *********************************************************/
64 HalpXboxOutputChar(UCHAR Char
, unsigned X
, unsigned Y
, ULONG FgColor
, ULONG BgColor
)
72 FontPtr
= XboxFont8x16
+ Char
* 16;
73 Pixel
= (PULONG
) ((char *) FrameBuffer
+ Y
* CHAR_HEIGHT
* Delta
74 + X
* CHAR_WIDTH
* BytesPerPixel
);
75 for (Line
= 0; Line
< CHAR_HEIGHT
; Line
++)
78 for (Col
= 0; Col
< CHAR_WIDTH
; Col
++)
80 Pixel
[Col
] = (0 != (FontPtr
[Line
] & Mask
) ? FgColor
: BgColor
);
83 Pixel
= (PULONG
) ((char *) Pixel
+ Delta
);
86 if (NULL
!= CellContents
)
88 CellContents
[Y
* SizeX
+ X
] = Char
;
89 CellFgColor
[Y
* SizeX
+ X
] = FgColor
;
90 CellBgColor
[Y
* SizeX
+ X
] = BgColor
;
95 HalpXboxAttrToSingleColor(UCHAR Attr
)
99 Intensity
= (0 == (Attr
& 0x08) ? 127 : 255);
102 (0 == (Attr
& 0x04) ? 0 : (Intensity
<< 16)) |
103 (0 == (Attr
& 0x02) ? 0 : (Intensity
<< 8)) |
104 (0 == (Attr
& 0x01) ? 0 : Intensity
);
108 HalpXboxAttrToColors(UCHAR Attr
, ULONG
*FgColor
, ULONG
*BgColor
)
110 *FgColor
= HalpXboxAttrToSingleColor(Attr
& 0xf);
111 *BgColor
= HalpXboxAttrToSingleColor((Attr
>> 4) & 0xf);
115 HalpXboxClearScreenColor(ULONG Color
)
120 for (Line
= 0; Line
< SizeY
* CHAR_HEIGHT
; Line
++)
122 p
= (PULONG
) ((char *) FrameBuffer
+ Line
* Delta
);
123 for (Col
= 0; Col
< SizeX
* CHAR_WIDTH
; Col
++)
129 if (NULL
!= CellContents
)
131 for (Line
= 0; Line
< SizeY
; Line
++)
133 for (Col
= 0; Col
< SizeX
; Col
++)
135 CellContents
[Line
* SizeX
+ Col
] = ' ';
136 CellFgColor
[Line
* SizeX
+ Col
] = Color
;
137 CellBgColor
[Line
* SizeX
+ Col
] = Color
;
144 HalClearDisplay(UCHAR CharAttribute
)
146 ULONG FgColor
, BgColor
;
148 HalpXboxAttrToColors(CharAttribute
, &FgColor
, &BgColor
);
150 HalpXboxClearScreenColor(BgColor
);
157 HalScrollDisplay (VOID
)
162 if (NULL
== CellContents
)
164 p
= (PULONG
) ((char *) FrameBuffer
+ (Delta
* CHAR_HEIGHT
));
165 RtlMoveMemory(FrameBuffer
,
167 (Delta
* CHAR_HEIGHT
) * (SizeY
- 1));
169 for (Line
= 0; Line
< CHAR_HEIGHT
; Line
++)
171 p
= (PULONG
) ((char *) FrameBuffer
+ (CHAR_HEIGHT
* (SizeY
- 1 ) + Line
) * Delta
);
172 for (Col
= 0; Col
< SizeX
* CHAR_WIDTH
; Col
++)
174 *p
++ = DEFAULT_BG_COLOR
;
180 for (Line
= 0; Line
< SizeY
- 1; Line
++)
182 for (Col
= 0; Col
< SizeX
; Col
++)
184 HalpXboxOutputChar(CellContents
[(Line
+ 1) * SizeX
+ Col
], Col
, Line
,
185 CellFgColor
[(Line
+ 1) * SizeX
+ Col
],
186 CellBgColor
[(Line
+ 1) * SizeX
+ Col
]);
189 for (Col
= 0; Col
< SizeX
; Col
++)
191 HalpXboxOutputChar(' ', Col
, SizeY
- 1, DEFAULT_FG_COLOR
, DEFAULT_BG_COLOR
);
197 HalPutCharacter(UCHAR Character
)
199 HalpXboxOutputChar(Character
, CursorX
, CursorY
, DEFAULT_FG_COLOR
, DEFAULT_BG_COLOR
);
203 ReadfromSMBus(UCHAR Address
, UCHAR bRegister
, UCHAR Size
, ULONG
*Data_to_smbus
)
205 int nRetriesToLive
=50;
207 while (0 != (READ_PORT_USHORT((PUSHORT
) (I2C_IO_BASE
+ 0)) & 0x0800))
209 ; /* Franz's spin while bus busy with any master traffic */
212 while (0 != nRetriesToLive
--)
217 WRITE_PORT_UCHAR((PUCHAR
) (I2C_IO_BASE
+ 4), (Address
<< 1) | 1);
218 WRITE_PORT_UCHAR((PUCHAR
) (I2C_IO_BASE
+ 8), bRegister
);
220 temp
= READ_PORT_USHORT((PUSHORT
) (I2C_IO_BASE
+ 0));
221 WRITE_PORT_USHORT((PUSHORT
) (I2C_IO_BASE
+ 0), temp
); /* clear down all preexisting errors */
226 WRITE_PORT_UCHAR((PUCHAR
) (I2C_IO_BASE
+ 2), 0x0d); /* DWORD modus ? */
229 WRITE_PORT_UCHAR((PUCHAR
) (I2C_IO_BASE
+ 2), 0x0b); /* WORD modus */
232 WRITE_PORT_UCHAR((PUCHAR
) (I2C_IO_BASE
+ 2), 0x0a); // BYTE
238 while (0 == (b
& 0x36))
240 b
= READ_PORT_UCHAR((PUCHAR
) (I2C_IO_BASE
+ 0));
245 /* printf("I2CTransmitByteGetReturn error %x\n", b); */
250 /* printf("I2CTransmitByteGetReturn no complete, retry\n"); */
257 READ_PORT_UCHAR((PUCHAR
) (I2C_IO_BASE
+ 6));
258 READ_PORT_UCHAR((PUCHAR
) (I2C_IO_BASE
+ 9));
259 READ_PORT_UCHAR((PUCHAR
) (I2C_IO_BASE
+ 9));
260 READ_PORT_UCHAR((PUCHAR
) (I2C_IO_BASE
+ 9));
261 READ_PORT_UCHAR((PUCHAR
) (I2C_IO_BASE
+ 9));
264 *Data_to_smbus
= READ_PORT_USHORT((PUSHORT
) (I2C_IO_BASE
+ 6));
267 *Data_to_smbus
= READ_PORT_UCHAR((PUCHAR
) (I2C_IO_BASE
+ 6));
281 I2CTransmitByteGetReturn(UCHAR bPicAddressI2cFormat
, UCHAR bDataToWrite
, ULONG
*Return
)
283 return ReadfromSMBus(bPicAddressI2cFormat
, bDataToWrite
, 1, Return
);
287 HalInitializeDisplay (PROS_LOADER_PARAMETER_BLOCK LoaderBlock
)
289 * FUNCTION: Initalize the display
291 * InitParameters = Parameters setup by the boot loader
294 ULONG ScreenWidthPixels
;
295 ULONG ScreenHeightPixels
;
296 PHYSICAL_ADDRESS PhysControl
;
297 PHYSICAL_ADDRESS PhysBuffer
;
301 if (! DisplayInitialized
)
303 PhysBuffer
.u
.HighPart
= 0;
304 if (0 != (LoaderBlock
->Flags
& MB_FLAGS_MEM_INFO
))
306 PhysBuffer
.u
.LowPart
= (LoaderBlock
->MemHigher
+ 1024) * 1024;
310 /* Assume a 64Mb Xbox, last 4MB for video buf */
311 PhysBuffer
.u
.LowPart
= 60 * 1024 * 1024;
313 PhysBuffer
.u
.LowPart
|= 0xf0000000;
315 /* Tell the nVidia controller about the framebuffer */
316 PhysControl
.u
.HighPart
= 0;
317 PhysControl
.u
.LowPart
= 0xfd000000;
318 ControlBuffer
= MmMapIoSpace(PhysControl
, 0x1000000, MmNonCached
);
319 if (NULL
== ControlBuffer
)
323 *((PULONG
) ((char *) ControlBuffer
+ CONTROL_FRAMEBUFFER_ADDRESS_OFFSET
)) = (ULONG
) PhysBuffer
.u
.LowPart
;
324 MmUnmapIoSpace(ControlBuffer
, 0x1000000);
326 FrameBuffer
= MmMapIoSpace(PhysBuffer
, 4 * 1024 * 1024, MmNonCached
);
327 if (NULL
== FrameBuffer
)
332 if (I2CTransmitByteGetReturn(0x10, 0x04, &AvMode
))
334 if (1 == AvMode
) /* HDTV */
336 ScreenWidthPixels
= 720;
340 /* FIXME Other possible values of AvMode:
348 ScreenWidthPixels
= 640;
353 ScreenWidthPixels
= 640;
355 ScreenHeightPixels
= 480;
358 SizeX
= ScreenWidthPixels
/ CHAR_WIDTH
;
359 SizeY
= ScreenHeightPixels
/ CHAR_HEIGHT
;
360 Delta
= (ScreenWidthPixels
* BytesPerPixel
+ 3) & ~ 0x3;
362 CellFgColor
= (PULONG
) ExAllocatePoolWithTag(PagedPool
,
363 SizeX
* SizeY
* (sizeof(ULONG
) + sizeof(ULONG
) + sizeof(UCHAR
)),
365 if (NULL
!= CellFgColor
)
367 CellBgColor
= CellFgColor
+ SizeX
* SizeY
;
368 CellContents
= (PUCHAR
) (CellBgColor
+ SizeX
* SizeY
);
376 HalpXboxClearScreenColor(MAKE_COLOR(0, 0, 0));
378 DisplayInitialized
= TRUE
;
383 /* PUBLIC FUNCTIONS *********************************************************/
386 HalReleaseDisplayOwnership(VOID
)
388 * FUNCTION: Release ownership of display back to HAL
391 if (HalOwnsDisplay
|| NULL
== HalResetDisplayParameters
)
396 HalResetDisplayParameters(SizeX
, SizeY
);
398 HalOwnsDisplay
= TRUE
;
399 HalpXboxClearScreenColor(DEFAULT_BG_COLOR
);
407 HalAcquireDisplayOwnership(IN PHAL_RESET_DISPLAY_PARAMETERS ResetDisplayParameters
)
411 * ResetDisplayParameters = Pointer to a driver specific
415 HalOwnsDisplay
= FALSE
;
416 HalResetDisplayParameters
= ResetDisplayParameters
;
420 HalDisplayString(IN PCH String
)
422 * FUNCTION: Switches the screen to HAL console mode (BSOD) if not there
423 * already and displays a string
425 * string = ASCII string to display
426 * NOTE: Use with care because there is no support for returning from BSOD
431 static KSPIN_LOCK Lock
;
435 if (! HalOwnsDisplay
|| ! DisplayInitialized
)
442 OldIrql
= KfRaiseIrql(HIGH_LEVEL
);
443 KiAcquireSpinLock(&Lock
);
445 Ki386SaveFlags(Flags
);
446 Ki386DisableInterrupts();
455 else if (*pch
== '\b')
462 else if (*pch
!= '\r')
464 HalPutCharacter(*pch
);
467 if (SizeX
<= CursorX
)
474 if (SizeY
<= CursorY
)
483 Ki386RestoreFlags(Flags
);
485 KiReleaseSpinLock(&Lock
);
486 KfLowerIrql(OldIrql
);
490 HalQueryDisplayParameters(OUT PULONG DispSizeX
,
491 OUT PULONG DispSizeY
,
492 OUT PULONG CursorPosX
,
493 OUT PULONG CursorPosY
)
500 *CursorPosX
= CursorX
;
502 *CursorPosY
= CursorY
;
507 HalSetDisplayParameters(IN ULONG CursorPosX
,
510 CursorX
= (CursorPosX
< SizeX
) ? CursorPosX
: SizeX
- 1;
511 CursorY
= (CursorPosY
< SizeY
) ? CursorPosY
: SizeY
- 1;
516 HalQueryDisplayOwnership(VOID
)
518 return ! HalOwnsDisplay
;