diff --git a/reactos/hal/halx86/xbox/display_xbox.c b/reactos/hal/halx86/xbox/display_xbox.c index 3fce2d0e18f..3d3b0f3499f 100644 --- a/reactos/hal/halx86/xbox/display_xbox.c +++ b/reactos/hal/halx86/xbox/display_xbox.c @@ -1,4 +1,4 @@ -/* $Id: display_xbox.c,v 1.2 2004/12/08 11:42:28 gvg Exp $ +/* $Id: display_xbox.c,v 1.3 2004/12/11 14:45:00 gvg Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -16,12 +16,18 @@ #include #include "halxbox.h" +#define I2C_IO_BASE 0xc000 + +#define CONTROL_FRAMEBUFFER_ADDRESS_OFFSET 0x600800 + #define MAKE_COLOR(Red, Green, Blue) (0xff000000 | (((Red) & 0xff) << 16) | (((Green) & 0xff) << 8) | ((Blue) & 0xff)) /* Default to grey on blue */ #define DEFAULT_FG_COLOR MAKE_COLOR(127, 127, 127) #define DEFAULT_BG_COLOR MAKE_COLOR(0, 0, 127) +#define TAG_HALX TAG('H', 'A', 'L', 'X') + /* VARIABLES ****************************************************************/ static ULONG CursorX = 0; /* Cursor Position */ @@ -41,6 +47,16 @@ static PVOID FrameBuffer; static ULONG BytesPerPixel; static ULONG Delta; +/* + * It turns out that reading from the frame buffer is a pretty expensive + * operation. So, we're keeping shadow arrays of the contents and use + * those when needed (only for scrolling) instead of reading from the fb. + * This cuts down boot time from about 45 sec to about 6 sec. + */ +static PUCHAR CellContents; +static PULONG CellFgColor; +static PULONG CellBgColor; + /* PRIVATE FUNCTIONS *********************************************************/ static VOID FASTCALL @@ -65,6 +81,13 @@ HalpXboxOutputChar(UCHAR Char, unsigned X, unsigned Y, ULONG FgColor, ULONG BgCo } Pixel = (PULONG) ((char *) Pixel + Delta); } + + if (NULL != CellContents) + { + CellContents[Y * SizeX + X] = Char; + CellFgColor[Y * SizeX + X] = FgColor; + CellBgColor[Y * SizeX + X] = BgColor; + } } static ULONG FASTCALL @@ -101,6 +124,19 @@ HalpXboxClearScreenColor(ULONG Color) *p++ = Color; } } + + if (NULL != CellContents) + { + for (Line = 0; Line < SizeY; Line++) + { + for (Col = 0; Col < SizeX; Col++) + { + CellContents[Line * SizeX + Col] = ' '; + CellFgColor[Line * SizeX + Col] = Color; + CellBgColor[Line * SizeX + Col] = Color; + } + } + } } VOID FASTCALL @@ -122,17 +158,36 @@ HalScrollDisplay (VOID) ULONG Line, Col; PULONG p; - p = (PULONG) ((char *) FrameBuffer + (Delta * CHAR_HEIGHT)); - RtlMoveMemory(FrameBuffer, - p, - (Delta * CHAR_HEIGHT) * (SizeY - 1)); - - for (Line = 0; Line < CHAR_HEIGHT; Line++) + if (NULL == CellContents) { - p = (PULONG) ((char *) FrameBuffer + (CHAR_HEIGHT * (SizeY - 1 ) + Line) * Delta); - for (Col = 0; Col < SizeX * CHAR_WIDTH; Col++) + p = (PULONG) ((char *) FrameBuffer + (Delta * CHAR_HEIGHT)); + RtlMoveMemory(FrameBuffer, + p, + (Delta * CHAR_HEIGHT) * (SizeY - 1)); + + for (Line = 0; Line < CHAR_HEIGHT; Line++) { - *p++ = DEFAULT_BG_COLOR; + p = (PULONG) ((char *) FrameBuffer + (CHAR_HEIGHT * (SizeY - 1 ) + Line) * Delta); + for (Col = 0; Col < SizeX * CHAR_WIDTH; Col++) + { + *p++ = DEFAULT_BG_COLOR; + } + } + } + else + { + for (Line = 0; Line < SizeY - 1; Line++) + { + for (Col = 0; Col < SizeX; Col++) + { + HalpXboxOutputChar(CellContents[(Line + 1) * SizeX + Col], Col, Line, + CellFgColor[(Line + 1) * SizeX + Col], + CellBgColor[(Line + 1) * SizeX + Col]); + } + } + for (Col = 0; Col < SizeX; Col++) + { + HalpXboxOutputChar(' ', Col, SizeY - 1, DEFAULT_FG_COLOR, DEFAULT_BG_COLOR); } } } @@ -143,6 +198,90 @@ HalPutCharacter(UCHAR Character) HalpXboxOutputChar(Character, CursorX, CursorY, DEFAULT_FG_COLOR, DEFAULT_BG_COLOR); } +static BOOL +ReadfromSMBus(UCHAR Address, UCHAR bRegister, UCHAR Size, ULONG *Data_to_smbus) +{ + int nRetriesToLive=50; + + while (0 != (READ_PORT_USHORT((PUSHORT) (I2C_IO_BASE + 0)) & 0x0800)) + { + ; /* Franz's spin while bus busy with any master traffic */ + } + + while (0 != nRetriesToLive--) + { + UCHAR b; + int temp; + + WRITE_PORT_UCHAR((PUCHAR) (I2C_IO_BASE + 4), (Address << 1) | 1); + WRITE_PORT_UCHAR((PUCHAR) (I2C_IO_BASE + 8), bRegister); + + temp = READ_PORT_USHORT((PUSHORT) (I2C_IO_BASE + 0)); + WRITE_PORT_USHORT((PUSHORT) (I2C_IO_BASE + 0), temp); /* clear down all preexisting errors */ + + switch (Size) + { + case 4: + WRITE_PORT_UCHAR((PUCHAR) (I2C_IO_BASE + 2), 0x0d); /* DWORD modus ? */ + break; + case 2: + WRITE_PORT_UCHAR((PUCHAR) (I2C_IO_BASE + 2), 0x0b); /* WORD modus */ + break; + default: + WRITE_PORT_UCHAR((PUCHAR) (I2C_IO_BASE + 2), 0x0a); // BYTE + break; + } + + b = 0; + + while (0 == (b & 0x36)) + { + b = READ_PORT_UCHAR((PUCHAR) (I2C_IO_BASE + 0)); + } + + if (0 != (b & 0x24)) + { + /* printf("I2CTransmitByteGetReturn error %x\n", b); */ + } + + if(0 == (b & 0x10)) + { + /* printf("I2CTransmitByteGetReturn no complete, retry\n"); */ + } + else + { + switch (Size) + { + case 4: + READ_PORT_UCHAR((PUCHAR) (I2C_IO_BASE + 6)); + READ_PORT_UCHAR((PUCHAR) (I2C_IO_BASE + 9)); + READ_PORT_UCHAR((PUCHAR) (I2C_IO_BASE + 9)); + READ_PORT_UCHAR((PUCHAR) (I2C_IO_BASE + 9)); + READ_PORT_UCHAR((PUCHAR) (I2C_IO_BASE + 9)); + break; + case 2: + *Data_to_smbus = READ_PORT_USHORT((PUSHORT) (I2C_IO_BASE + 6)); + break; + default: + *Data_to_smbus = READ_PORT_UCHAR((PUCHAR) (I2C_IO_BASE + 6)); + break; + } + + + return TRUE; + } + } + + return FALSE; +} + + +static BOOL +I2CTransmitByteGetReturn(UCHAR bPicAddressI2cFormat, UCHAR bDataToWrite, ULONG *Return) +{ + return ReadfromSMBus(bPicAddressI2cFormat, bDataToWrite, 1, Return); +} + VOID FASTCALL HalInitializeDisplay (PLOADER_PARAMETER_BLOCK LoaderBlock) /* @@ -153,7 +292,10 @@ HalInitializeDisplay (PLOADER_PARAMETER_BLOCK LoaderBlock) { ULONG ScreenWidthPixels; ULONG ScreenHeightPixels; + PHYSICAL_ADDRESS PhysControl; PHYSICAL_ADDRESS PhysBuffer; + ULONG AvMode; + PVOID ControlBuffer; if (! DisplayInitialized) { @@ -164,16 +306,51 @@ HalInitializeDisplay (PLOADER_PARAMETER_BLOCK LoaderBlock) } else { - /* Assume a 64Mb Xbox */ - PhysBuffer.u.LowPart = 0x03c00000; + /* Assume a 64Mb Xbox, last 4MB for video buf */ + PhysBuffer.u.LowPart = 60 * 1024 * 1024; } PhysBuffer.u.LowPart |= 0xf0000000; - FrameBuffer = MmMapIoSpace(PhysBuffer, 0x400000, MmNonCached); + + /* Tell the nVidia controller about the framebuffer */ + PhysControl.u.HighPart = 0; + PhysControl.u.LowPart = 0xfd000000; + ControlBuffer = MmMapIoSpace(PhysControl, 0x1000000, MmNonCached); + if (NULL == ControlBuffer) + { + return; + } + *((PULONG) ((char *) ControlBuffer + CONTROL_FRAMEBUFFER_ADDRESS_OFFSET)) = (ULONG) PhysBuffer.u.LowPart; + MmUnmapIoSpace(ControlBuffer, 0x1000000); + + FrameBuffer = MmMapIoSpace(PhysBuffer, 4 * 1024 * 1024, MmNonCached); if (NULL == FrameBuffer) { return; } - ScreenWidthPixels = 720; + + if (I2CTransmitByteGetReturn(0x10, 0x04, &AvMode)) + { + if (1 == AvMode) /* HDTV */ + { + ScreenWidthPixels = 720; + } + else + { + /* FIXME Other possible values of AvMode: + * 0 - AV_SCART_RGB + * 2 - AV_VGA_SOG + * 4 - AV_SVIDEO + * 6 - AV_COMPOSITE + * 7 - AV_VGA + * other AV_COMPOSITE + */ + ScreenWidthPixels = 640; + } + } + else + { + ScreenWidthPixels = 640; + } ScreenHeightPixels = 480; BytesPerPixel = 4; @@ -181,6 +358,20 @@ HalInitializeDisplay (PLOADER_PARAMETER_BLOCK LoaderBlock) SizeY = ScreenHeightPixels / CHAR_HEIGHT; Delta = (ScreenWidthPixels * BytesPerPixel + 3) & ~ 0x3; + CellFgColor = (PULONG) ExAllocatePoolWithTag(PagedPool, + SizeX * SizeY * (sizeof(ULONG) + sizeof(ULONG) + sizeof(UCHAR)), + TAG_HALX); + if (NULL != CellFgColor) + { + CellBgColor = CellFgColor + SizeX * SizeY; + CellContents = (PUCHAR) (CellBgColor + SizeX * SizeY); + } + else + { + CellBgColor = NULL; + CellContents = NULL; + } + HalpXboxClearScreenColor(MAKE_COLOR(0, 0, 0)); DisplayInitialized = TRUE; diff --git a/reactos/hal/halx86/xbox/pci_xbox.c b/reactos/hal/halx86/xbox/pci_xbox.c index 42c2aaec38e..54345df23b8 100644 --- a/reactos/hal/halx86/xbox/pci_xbox.c +++ b/reactos/hal/halx86/xbox/pci_xbox.c @@ -1,4 +1,4 @@ -/* $Id: pci_xbox.c,v 1.2 2004/12/08 21:53:24 gvg Exp $ +/* $Id: pci_xbox.c,v 1.3 2004/12/11 14:45:00 gvg Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -7,6 +7,12 @@ * PROGRAMMER: Ge van Geldorp (gvg@reactos.com) * UPDATE HISTORY: * 2004/12/04: Created + * + * Trying to get PCI config data from devices 0:0:1 and 0:0:2 will completely + * hang the Xbox. Also, the device number doesn't seem to be decoded for the + * video card, so it appears to be present on 1:0:0 - 1:31:0. + * We hack around these problems by indicating "device not present" for devices + * 0:0:1, 0:0:2, 1:1:0, 1:2:0, 1:3:0, ...., 1:31:0 */ /* INCLUDES *****************************************************************/ @@ -50,7 +56,9 @@ HalpXboxGetPciData(PBUS_HANDLER BusHandler, DPRINT(" Offset 0x%lx\n", Offset); DPRINT(" Length 0x%lx\n", Length); - if (0 == BusNumber && (1 == ((SlotNumber >> 5) & 0x07) || 2 == ((SlotNumber >> 5) & 0x07))) + if ((0 == BusNumber && 0 == (SlotNumber & 0x1f) && + (1 == ((SlotNumber >> 5) & 0x07) || 2 == ((SlotNumber >> 5) & 0x07))) || + (1 == BusNumber && 0 != (SlotNumber & 0x1f))) { DPRINT("Blacklisted PCI slot\n"); if (0 == Offset && 2 <= Length) @@ -78,7 +86,9 @@ HalpXboxSetPciData(PBUS_HANDLER BusHandler, DPRINT(" Offset 0x%lx\n", Offset); DPRINT(" Length 0x%lx\n", Length); - if (0 == BusNumber && (1 == ((SlotNumber >> 5) & 0x07) || 2 == ((SlotNumber >> 5) & 0x07))) + if ((0 == BusNumber && 0 == (SlotNumber & 0x1f) && + (1 == ((SlotNumber >> 5) & 0x07) || 2 == ((SlotNumber >> 5) & 0x07))) || + (1 == BusNumber && 0 != (SlotNumber & 0x1f))) { DPRINT1("Trying to set data on blacklisted PCI slot\n"); return 0; @@ -90,7 +100,7 @@ HalpXboxSetPciData(PBUS_HANDLER BusHandler, void HalpXboxInitPciBus(ULONG BusNumber, PBUS_HANDLER BusHandler) { - if (0 == BusNumber) + if (0 == BusNumber || 1 == BusNumber) { GenericGetPciData = BusHandler->GetBusData; BusHandler->GetBusData = HalpXboxGetPciData;