#define MAKE_COLOR(Red, Green, Blue) (0xff000000 | (((Red) & 0xff) << 16) | (((Green) & 0xff) << 8) | ((Blue) & 0xff))
-BOOLEAN I2CTransmitByteGetReturn(UCHAR bPicAddressI2cFormat, UCHAR bDataToWrite, ULONG *Return);
-
static VOID
XboxVideoOutputChar(UCHAR Char, unsigned X, unsigned Y, ULONG FgColor, ULONG BgColor)
{
XboxVideoOutputChar(Ch, X, Y, FgColor, BgColor);
}
+UCHAR
+NvGetCrtc(UCHAR Index)
+{
+ *((PUCHAR) NV2A_CRTC_REGISTER_INDEX) = Index;
+ return *((PUCHAR) NV2A_CRTC_REGISTER_VALUE);
+}
+
VOID
XboxVideoInit(VOID)
{
- ULONG AvMode;
-
/* Reuse framebuffer that was set up by firmware */
- FrameBuffer = (PVOID)*((PULONG) 0xfd600800);
+ FrameBuffer = (PVOID)*((PULONG) NV2A_CRTC_FRAMEBUFFER_START);
/* Verify that framebuffer address is page-aligned */
ASSERT((ULONG_PTR)FrameBuffer % PAGE_SIZE == 0);
/* FIXME: obtain fb size from firmware somehow (Cromwell reserves high 4 MB of RAM) */
FrameBufferSize = 4 * 1024 * 1024;
- /* FIXME: don't use SMBus, obtain current video resolution directly from NV2A */
- if (I2CTransmitByteGetReturn(0x10, 0x04, &AvMode))
- {
- if (1 == AvMode) /* HDTV */
- {
- ScreenWidth = 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
- */
- ScreenWidth = 640;
- }
- }
+ ScreenWidth = *((PULONG) NV2A_RAMDAC_FP_HVALID_END) + 1;
+ ScreenHeight = *((PULONG) NV2A_RAMDAC_FP_VVALID_END) + 1;
+ /* Get BPP directly from NV2A CRTC (magic constants are from Cromwell) */
+ BytesPerPixel = 8 * (((NvGetCrtc(0x19) & 0xE0) << 3) | (NvGetCrtc(0x13) & 0xFF)) / ScreenWidth;
+ if (BytesPerPixel == 4)
+ {
+ ASSERT((NvGetCrtc(0x28) & 0xF) == BytesPerPixel - 1);
+ }
else
- {
- ScreenWidth = 640;
- }
-
- ScreenHeight = 480;
- BytesPerPixel = 4;
+ {
+ ASSERT((NvGetCrtc(0x28) & 0xF) == BytesPerPixel);
+ }
Delta = (ScreenWidth * BytesPerPixel + 3) & ~ 0x3;
+ /* Verify screen resolution */
+ ASSERT(ScreenWidth > 1);
+ ASSERT(ScreenHeight > 1);
+ ASSERT(BytesPerPixel >= 1 && BytesPerPixel <= 4);
+ /* Verify that screen fits framebuffer size */
+ ASSERT(ScreenWidth * ScreenHeight * BytesPerPixel <= FrameBufferSize);
+
XboxVideoClearScreenColor(MAKE_COLOR(0, 0, 0), TRUE);
}
#define LPC_CONFIG_DEVICE_BASE_ADDRESS_LOW 0x61
#define LPC_CONFIG_DEVICE_INTERRUPT 0x70
+#define NV2A_CONTROL_OFFSET 0xFD000000
+#define NV2A_CRTC_OFFSET (0x600000 + NV2A_CONTROL_OFFSET)
+#define NV2A_CRTC_FRAMEBUFFER_START (0x800 + NV2A_CRTC_OFFSET)
+#define NV2A_CRTC_REGISTER_INDEX (0x13D4 + NV2A_CRTC_OFFSET)
+#define NV2A_CRTC_REGISTER_VALUE (0x13D5 + NV2A_CRTC_OFFSET)
+#define NV2A_RAMDAC_OFFSET (0x680000 + NV2A_CONTROL_OFFSET)
+#define NV2A_RAMDAC_FP_HVALID_END (0x838 + NV2A_RAMDAC_OFFSET)
+#define NV2A_RAMDAC_FP_VVALID_END (0x818 + NV2A_RAMDAC_OFFSET)
+
extern UCHAR XboxFont8x16[256 * 16];
VOID XboxMachInit(const char *CmdLine);
add_subdirectory(vga)
add_subdirectory(vga_new)
add_subdirectory(vmx_svga)
-add_subdirectory(xboxvmp)
+
+if(ARCH STREQUAL "i386")
+ add_subdirectory(xboxvmp)
+endif()
list(APPEND SOURCE
- xboxi2c.c
xboxvmp.c
xboxvmp.h)
+++ /dev/null
-/*
- * PROJECT: ReactOS Xbox miniport video driver
- * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
- * PURPOSE: I2C SMBus routines
- * COPYRIGHT: Copyright 2004 Gé van Geldorp
- * Copyright 2004 Filip Navara
- * Copyright 2019 Stanislav Motylkov (x86corez@gmail.com)
- */
-
-/* INCLUDES *******************************************************************/
-
-#include "xboxvmp.h"
-
-#include <debug.h>
-#include <dpfilter.h>
-
-/* PUBLIC AND PRIVATE FUNCTIONS ***********************************************/
-
-static
-BOOLEAN
-ReadfromSMBus(
- UCHAR Address,
- UCHAR bRegister,
- UCHAR Size,
- ULONG *Data_to_smbus)
-{
- int nRetriesToLive = 50;
-
- while ((VideoPortReadPortUshort((PUSHORT) (I2C_IO_BASE + 0)) & 0x0800) != 0)
- {
- ; /* Franz's spin while bus busy with any master traffic */
- }
-
- while (nRetriesToLive-- != 0)
- {
- UCHAR b;
- int temp;
-
- VideoPortWritePortUchar((PUCHAR) (I2C_IO_BASE + 4), (Address << 1) | 1);
- VideoPortWritePortUchar((PUCHAR) (I2C_IO_BASE + 8), bRegister);
-
- temp = VideoPortReadPortUshort((PUSHORT) (I2C_IO_BASE + 0));
- VideoPortWritePortUshort((PUSHORT) (I2C_IO_BASE + 0), temp); /* clear down all preexisting errors */
-
- switch (Size)
- {
- case 4:
- {
- VideoPortWritePortUchar((PUCHAR) (I2C_IO_BASE + 2), 0x0d); /* DWORD modus ? */
- break;
- }
-
- case 2:
- {
- VideoPortWritePortUchar((PUCHAR) (I2C_IO_BASE + 2), 0x0b); /* WORD modus */
- break;
- }
-
- default:
- {
- VideoPortWritePortUchar((PUCHAR) (I2C_IO_BASE + 2), 0x0a); /* BYTE */
- }
- }
-
- b = 0;
-
- while ((b & 0x36) == 0)
- {
- b = VideoPortReadPortUchar((PUCHAR) (I2C_IO_BASE + 0));
- }
-
- if ((b & 0x24) != 0)
- {
- ERR_(IHVVIDEO, "I2CTransmitByteGetReturn error %x\n", b);
- }
-
- if ((b & 0x10) == 0)
- {
- ERR_(IHVVIDEO, "I2CTransmitByteGetReturn no complete, retry\n");
- }
- else
- {
- switch (Size)
- {
- case 4:
- {
- VideoPortReadPortUchar((PUCHAR) (I2C_IO_BASE + 6));
- VideoPortReadPortUchar((PUCHAR) (I2C_IO_BASE + 9));
- VideoPortReadPortUchar((PUCHAR) (I2C_IO_BASE + 9));
- VideoPortReadPortUchar((PUCHAR) (I2C_IO_BASE + 9));
- VideoPortReadPortUchar((PUCHAR) (I2C_IO_BASE + 9));
- break;
- }
-
- case 2:
- {
- *Data_to_smbus = VideoPortReadPortUshort((PUSHORT) (I2C_IO_BASE + 6));
- break;
- }
-
- default:
- {
- *Data_to_smbus = VideoPortReadPortUchar((PUCHAR) (I2C_IO_BASE + 6));
- }
- }
-
- return TRUE;
- }
- }
-
- return FALSE;
-}
-
-BOOLEAN
-I2CTransmitByteGetReturn(
- UCHAR bPicAddressI2cFormat,
- UCHAR bDataToWrite,
- ULONG *Return)
-{
- return ReadfromSMBus(bPicAddressI2cFormat, bDataToWrite, 1, Return);
-}
-
-/* EOF */
FrameBuffer.QuadPart += DeviceExtension->PhysFrameBufferStart.QuadPart;
MapInformation->VideoRamBase = RequestedAddress->RequestedVirtualAddress;
/* FIXME: obtain fb size from firmware somehow (Cromwell reserves high 4 MB of RAM) */
- MapInformation->VideoRamLength = 4 * 1024 * 1024;
+ MapInformation->VideoRamLength = NV2A_VIDEO_MEMORY_SIZE;
VideoPortMapMemory(
DeviceExtension,
return XboxVmpQueryCurrentMode(DeviceExtension, VideoMode, StatusBlock);
}
+UCHAR
+NvGetCrtc(
+ PXBOXVMP_DEVICE_EXTENSION DeviceExtension,
+ UCHAR Index)
+{
+ *((PUCHAR)((ULONG_PTR)DeviceExtension->VirtControlStart + NV2A_CRTC_REGISTER_INDEX)) = Index;
+ return *((PUCHAR)((ULONG_PTR)DeviceExtension->VirtControlStart + NV2A_CRTC_REGISTER_VALUE));
+}
+
+UCHAR
+NvGetBytesPerPixel(
+ PXBOXVMP_DEVICE_EXTENSION DeviceExtension,
+ ULONG ScreenWidth)
+{
+ UCHAR BytesPerPixel;
+
+ /* Get BPP directly from NV2A CRTC (magic constants are from Cromwell) */
+ BytesPerPixel = 8 * (((NvGetCrtc(DeviceExtension, 0x19) & 0xE0) << 3) | (NvGetCrtc(DeviceExtension, 0x13) & 0xFF)) / ScreenWidth;
+
+ if (BytesPerPixel == 4)
+ {
+ ASSERT((NvGetCrtc(DeviceExtension, 0x28) & 0xF) == BytesPerPixel - 1);
+ }
+ else
+ {
+ ASSERT((NvGetCrtc(DeviceExtension, 0x28) & 0xF) == BytesPerPixel);
+ }
+
+ return BytesPerPixel;
+}
+
/*
* VBEQueryCurrentMode
*
PVIDEO_MODE_INFORMATION VideoMode,
PSTATUS_BLOCK StatusBlock)
{
- ULONG AvMode = 0;
+ UCHAR BytesPerPixel;
VideoMode->Length = sizeof(VIDEO_MODE_INFORMATION);
VideoMode->ModeIndex = 0;
- /* FIXME: don't use SMBus, obtain current video resolution directly from NV2A */
- if (I2CTransmitByteGetReturn(0x10, 0x04, &AvMode))
- {
- if (AvMode == 1) /* HDTV */
- {
- VideoMode->VisScreenWidth = 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
- */
- VideoMode->VisScreenWidth = 640;
- }
- }
- else
+ VideoMode->VisScreenWidth = *((PULONG)((ULONG_PTR)DeviceExtension->VirtControlStart + NV2A_RAMDAC_FP_HVALID_END)) + 1;
+ VideoMode->VisScreenHeight = *((PULONG)((ULONG_PTR)DeviceExtension->VirtControlStart + NV2A_RAMDAC_FP_VVALID_END)) + 1;
+
+ if (VideoMode->VisScreenWidth <= 1 || VideoMode->VisScreenHeight <= 1)
{
- VideoMode->VisScreenWidth = 640;
+ ERR_(IHVVIDEO, "Cannot obtain current screen resolution!\n");
+ return FALSE;
}
- VideoMode->VisScreenHeight = 480;
- VideoMode->ScreenStride = VideoMode->VisScreenWidth * 4;
+ BytesPerPixel = NvGetBytesPerPixel(DeviceExtension, VideoMode->VisScreenWidth);
+ ASSERT(BytesPerPixel >= 1 && BytesPerPixel <= 4);
+
+ VideoMode->ScreenStride = VideoMode->VisScreenWidth * BytesPerPixel;
VideoMode->NumberOfPlanes = 1;
- VideoMode->BitsPerPlane = 32;
+ VideoMode->BitsPerPlane = BytesPerPixel * 8;
VideoMode->Frequency = 1;
VideoMode->XMillimeter = 0; /* FIXME */
VideoMode->YMillimeter = 0; /* FIXME */
- VideoMode->NumberRedBits = 8;
- VideoMode->NumberGreenBits = 8;
- VideoMode->NumberBlueBits = 8;
- VideoMode->RedMask = 0xFF0000;
- VideoMode->GreenMask = 0x00FF00;
- VideoMode->BlueMask = 0x0000FF;
+ if (BytesPerPixel >= 3)
+ {
+ VideoMode->NumberRedBits = 8;
+ VideoMode->NumberGreenBits = 8;
+ VideoMode->NumberBlueBits = 8;
+ VideoMode->RedMask = 0xFF0000;
+ VideoMode->GreenMask = 0x00FF00;
+ VideoMode->BlueMask = 0x0000FF;
+ }
+ else
+ {
+ /* FIXME: not implemented */
+ WARN_(IHVVIDEO, "BytesPerPixel %d - not implemented\n", BytesPerPixel);
+ }
VideoMode->VideoMemoryBitmapWidth = VideoMode->VisScreenWidth;
VideoMode->VideoMemoryBitmapHeight = VideoMode->VisScreenHeight;
VideoMode->AttributeFlags = VIDEO_MODE_GRAPHICS | VIDEO_MODE_COLOR |
StatusBlock->Information = sizeof(VIDEO_MODE_INFORMATION);
+ /* Verify that screen fits framebuffer size */
+ if (VideoMode->VisScreenWidth * VideoMode->VisScreenHeight * (VideoMode->BitsPerPlane / 8) > NV2A_VIDEO_MEMORY_SIZE)
+ {
+ ERR_(IHVVIDEO, "Current screen resolution exceeds video memory bounds!\n");
+ return FALSE;
+ }
+
return TRUE;
}
#include "miniport.h"
#include "video.h"
-#define I2C_IO_BASE 0xC000
-#define NV2A_CONTROL_FRAMEBUFFER_ADDRESS_OFFSET 0x600800
+#define NV2A_VIDEO_MEMORY_SIZE (4 * 1024 * 1024)
-BOOLEAN
-I2CTransmitByteGetReturn(
- UCHAR bPicAddressI2cFormat,
- UCHAR bDataToWrite,
- ULONG *Return);
+#define NV2A_CONTROL_FRAMEBUFFER_ADDRESS_OFFSET 0x600800
+#define NV2A_CRTC_REGISTER_INDEX 0x6013D4
+#define NV2A_CRTC_REGISTER_VALUE 0x6013D5
+#define NV2A_RAMDAC_FP_HVALID_END 0x680838
+#define NV2A_RAMDAC_FP_VVALID_END 0x680818
typedef struct
{