- Detect HDTV output
authorGé van Geldorp <ge@gse.nl>
Sat, 11 Dec 2004 14:45:00 +0000 (14:45 +0000)
committerGé van Geldorp <ge@gse.nl>
Sat, 11 Dec 2004 14:45:00 +0000 (14:45 +0000)
- Increase scrolling speed
- Blacklist more PCI slots

svn path=/trunk/; revision=12013

reactos/hal/halx86/xbox/display_xbox.c
reactos/hal/halx86/xbox/pci_xbox.c

index 3fce2d0..3d3b0f3 100644 (file)
@@ -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
 #include <hal.h>
 #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));
+  if (NULL == CellContents)
+    {
+      p = (PULONG) ((char *) FrameBuffer + (Delta * CHAR_HEIGHT));
+      RtlMoveMemory(FrameBuffer,
+                    p,
+                    (Delta * CHAR_HEIGHT) * (SizeY - 1));
 
-  for (Line = 0; Line < CHAR_HEIGHT; Line++)
+      for (Line = 0; Line < CHAR_HEIGHT; Line++)
+        {
+          p = (PULONG) ((char *) FrameBuffer + (CHAR_HEIGHT * (SizeY - 1 ) + Line) * Delta);
+          for (Col = 0; Col < SizeX * CHAR_WIDTH; Col++)
+            {
+              *p++ = DEFAULT_BG_COLOR;
+            }
+        }
+    }
+  else
     {
-      p = (PULONG) ((char *) FrameBuffer + (CHAR_HEIGHT * (SizeY - 1 ) + Line) * Delta);
-      for (Col = 0; Col < SizeX * CHAR_WIDTH; Col++)
+      for (Line = 0; Line < SizeY - 1; Line++)
         {
-          *p++ = DEFAULT_BG_COLOR;
+          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;
index 42c2aae..54345df 100644 (file)
@@ -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;