singrdk/base/boot/SingLdrArm/Omap3430/sarmboot.cpp

1993 lines
65 KiB
C++
Raw Normal View History

2008-11-17 18:29:00 -05:00
//////////////////////////////////////////////////////////////////////////////
//
// SArmBoot.cpp - Singularity ARM Boot Loader
//
// Copyright Microsoft Corporation.
//
typedef int INT;
typedef char INT8, *PINT8;
typedef short INT16, *PINT16;
typedef long INT32, *PINT32;
typedef __int64 INT64, *PINT64;
typedef long LARGEST;
typedef char CHAR, *PCHAR;
typedef unsigned int UINT;
typedef unsigned char UINT8, *PUINT8;
typedef unsigned short UINT16, *PUINT16;
typedef unsigned long UINT32, *PUINT32;
typedef unsigned __int64 UINT64, *PUINT64;
typedef unsigned long ULARGEST;
typedef unsigned short WCHAR;
typedef unsigned char UCHAR;
typedef int BOOL;
typedef void *PVOID;
typedef UINT32 ULONG_PTR;
typedef UINT32 UINTPTR;
#define NULL 0
#define arrayof(a) (sizeof(a)/sizeof(a[0]))
#define offsetof(s,m) (size_t)&(((s *)0)->m)
//#define DEBUG 1
/////////////////////////////////////////// Core types used by runtime system.
//
extern "C" ULONG_PTR _security_cookie = 0;
typedef __wchar_t bartok_char;
typedef signed char int8;
typedef signed short int16;
typedef signed int int32;
typedef __int64 int64;
typedef unsigned int uint;
typedef unsigned char uint8;
typedef unsigned short uint16;
typedef unsigned int uint32;
typedef unsigned __int64 uint64;
typedef float float32;
typedef double float64;
typedef int intptr;
typedef unsigned int uintptr;
struct uintPtr
{
uintptr value;
};
struct intPtr
{
intptr value;
};
typedef struct uintPtr *UIntPtr;
typedef struct intPtr *IntPtr;
//
// This saves the MiniDumpBase first time through since it gets
// updated by the kernel.
//
static uintptr DumpAddr32 = 0;
//////////////////////////////////////////////////////////////////////////////
//
/////////////////////////////////////////////////////////////// Static Assert.
//
// Compile-time (not run-time) assertion. Code will not compile if
// expr is false. Note: there is no non-debug version of this; we
// want this for all builds. The compiler optimizes the code away.
//
template <bool x> struct STATIC_ASSERT_FAILURE;
template <> struct STATIC_ASSERT_FAILURE<true> { };
template <int x> struct static_assert_test { };
#define STATIC_CAT_INNER(x,y) x##y
#define STATIC_CAT(x,y) STATIC_CAT_INNER(x,y)
#define STATIC_ASSERT(condition) \
typedef static_assert_test< \
sizeof(STATIC_ASSERT_FAILURE<(bool)(condition)>)> \
STATIC_CAT(__static_assert_typedef_, __COUNTER__)
//////////////////////////////////////////////////////////////////////////////
//
#define OFFSETOF(s,m) ((uintptr)&(((s *)0)->m))
//////////////////////////////////////////////////////////////////////////////
//
#pragma warning(disable: 4103)
#include "halclass.h"
//////////////////////////////////////////////////////////////////////////////
#define OMAP_CORE_CM_BASE (0x48004A00)
#define CM_CLKSEL_CORE 0x40
#define CM_CLKSEL_CORE_GPT1 0x01
#define CM_CLKSEL_CORE_GPT1_SYS32K 0x00
#define CM_CORE_EN_MMC1 (1 << 24)
#define CM_CORE_EN_MMC2 (1 << 25)
#define CM_CORE_EN_I2C1 (1 << 15)
#define CM_CORE_EN_UART2 (1 << 14)
#define CM_CORE_EN_UART1 (1 << 13)
#define CM_CORE_EN_GPT10 (1 << 11)
#define CM_FCLKEN1_CORE (0)
#define CM_ICLKEN1_CORE (0x10)
#define CM_ICLKEN2_CORE (0x14)
#define CM_IDLEST_CORE (0x20)
#define OMAP_DSS_CM_BASE (0x48004E00)
#define CM_FCLKEN_DSS (0)
#define CM_ICLKEN_DSS (0x10)
#define CM_DSS_EN_DSS1 (1 << 0)
#define CM_DSS_EN_DSS2 (1 << 1)
#define CM_DSS_EN_TV (1 << 2)
#define OMAP_WKUP_CM_BASE (0x48004C00)
#define CM_CLKSEL_WKUP 0x40
#define CM_CLKSEL_WKUP_GPT1 0x01
#define CM_CLKSEL_WKUP_GPT1_SYS32K 0x00
#define CM_WKUP_EN_GPT1 0x01
#define CM_WKUP_EN_GPIO1 (1 << 3)
#define CM_FCLKEN_WKUP (0)
#define CM_ICLKEN_WKUP (0x10)
#define CM_IDLEST_WKUP (0x20)
#define OMAP_PER_CM_BASE (0x48005000)
#define CM_CLKSEL_PER 0x40
#define CM_CLKSEL_PER_GPT2 0x01
#define CM_CLKSEL_PER_GPT2_SYS32K 0x00
#define CM_PER_EN_GPT2 0x08
#define CM_FCLKEN_PER (0)
#define CM_ICLKEN_PER (0x10)
#define CM_IDLEST_PER (0x20)
//
// Registers to configure external pins for I2C, SD/MMC1, and SD/MMC2
//
#define OMAP_SCM_BASE (0x48002000)
#define OMAP_PADCONF_MASK (0xffff)
#define OMAP_PADCONF_SHIFT 0x10
#define OMAP_PADCONF_MUXMODE_MASK (0xfff8)
#define OMAP_PADCONF_MUXMODE_0 (0x0000)
#define OMAP_PADCONF_MUXMODE_1 (0x0001)
#define OMAP_PADCONF_MUXMODE_2 (0x0002)
#define OMAP_PADCONF_MUXMODE_3 (0x0003)
#define OMAP_PADCONF_MUXMODE_4 (0x0004)
#define OMAP_PADCONF_MUXMODE_5 (0x0005)
#define OMAP_PADCONF_MUXMODE_SAFE (0x0007)
#define OMAP_PADCONF_PULLUDENABLE (0x0008)
#define OMAP_PADCONF_PULLTYPESELECT (0x0010)
#define OMAP_PADCONF_INPUTENABLE (0x0100)
#define OMAP_PADCONF_OFFENABLE (0x0200)
#define OMAP_PADCONF_OFFOUTENABLE (0x0400)
#define OMAP_PADCONF_OFFOUTVALUE (0x0800)
#define OMAP_PADCONF_OFFPULLUDENABLE (0x1000)
#define OMAP_PADCONF_OFFPULLTYPESELECT (0x2000)
#define OMAP_PADCONF_WAKEUPENABLE (0x4000)
#define OMAP_PADCONF_WAKEUPEVENT (0x8000)
#define OMAP_PADCONF_HSUSB0_DAT7 (0x1B8)
#define OMAP_PADCONF_I2C1_SDA (0x1BC)
#define OMAP_PADCONF_SYS_NIRQ (0x1E0)
#define OMAP_PADCONF_DSS_PCLK (0x0D4)
#define OMAP_PADCONF_DSS_DAT18 (0x0FC)
#define OMAP_PADCONF_ETK_D10 (0xA40)
#define OMAP_PADCONF_ETK_D14 (0xA48)
#define OMAP_GPIO1_BASE (0x48310000)
#define OMAP_GPIO_OE (0x34)
#define OMAP_GPIO_SETDATAOUT (0x94)
#define OMAP_GPIO_CLEARDATAOUT (0x90)
#define OMAP_GPIO_PIN_24 (1 << 24)
#define OMAP_GPIO_PIN_28 (1 << 28)
//////////////////////////////////////////////////////////////////////////////
inline uint32 ReadReg32(volatile void * addr)
{
return ((volatile uint32 *)addr)[0];
}
inline void WriteReg32(volatile void * addr, uint32 value)
{
((volatile uint32 *)addr)[0] = value;
}
inline void WriteReg16(volatile void * addr, uint16 value)
{
((volatile uint16 *)addr)[0] = value;
}
inline uint16 ReadReg16(volatile void * addr)
{
return ((volatile uint16 *)addr)[0];
}
inline void WriteReg8(volatile void * addr, uint8 value)
{
((volatile uint8 *)addr)[0] = value;
}
inline uint8 ReadReg8(volatile void * addr)
{
return ((volatile uint8 *)addr)[0];
}
//////////////////////////////////////////////////////////////////////////////
//
typedef unsigned int uint;
typedef unsigned int UINT;
typedef signed long LARGEST;
typedef unsigned long ULARGEST;
#include "strformat.cpp"
#include "printf.cpp"
#include "debuguart.cpp"
#include "debug.cpp"
#include "expandpe.cpp"
//////////////////////////////////////////////////////////////////////////////
//
void Halt(void);
#define ASSERT(b) if (!(b)) { AssertFailed(#b);} else
void AssertFailed(const char *string)
{
printf("Assert Failed [%s]\n", string);
Halt();
}
////////////////////////////////////////////////////////////////////// Memory.
//
// OMAP 3430 Memory Map:
//
#define ON_OMAP3430_RESERVE_ADDR 0x80000000
#define ON_OMAP3430_RESERVE_SIZE 0x00050000
#define ON_OMAP3430_LOADER_ADDR 0x80000000 // SArmBoot code.
#define ON_OMAP3430_LOADER_SIZE 0x0000fff0 // was 0x10000.
#define ON_OMAP3430_CPU_ARGS_ADDR 0x8000fff0 //
#define ON_OMAP3430_CPU_ARGS_SIZE 0x80000010 //
#define ON_OMAP3430_VIDEO_ADDR 0x80010000 // LCD Video.
#define ON_OMAP3430_VIDEO_SIZE 0x00025800
#define ON_OMAP3430_ALLOC_ADDR 0x80035800 // Boot "alloc()" heap.
#define ON_OMAP3430_ALLOC_SIZE 0x0000A800
#define ON_OMAP3430_LOGBUF_ADDR 0x80040000 // Logging record buffer.
#define ON_OMAP3430_LOGBUF_SIZE 0x00008000
#define ON_OMAP3430_LOGTXT_ADDR 0x80048000 // Logging text buffer.
#define ON_OMAP3430_LOGTXT_SIZE 0x00008000
#define ON_OMAP3430_STACK_ADDR 0x80050000 // Kernel stack.
#define ON_OMAP3430_STACK_SIZE 0x00010000
#define ON_OMAP3430_KERNEL_ADDR 0x80100000 // Base address of kernel.
//#define ON_OMAP3430_KERNEL_SIZE 0xFFFFFFFF // Determined at runtime.
#define ON_OMAP3430_MEMORY_ADDR 0x80000000 // Base general memory.
#define ON_OMAP3430_MEMORY_SIZE 0x08000000
#define ON_OMAP3430_IFLASH_ADDR 0x84000000 // Memory to scan for flash image.
#define ON_OMAP3430_IFLASH_SIZE 0x04000000
//
// These should be in a general memory layout file
// rather than buried deeply in code
//
static uintptr heapTop = ON_OMAP3430_ALLOC_ADDR;
static uintptr heapMax = ON_OMAP3430_ALLOC_ADDR + ON_OMAP3430_ALLOC_SIZE;
extern "C" void * memset(void *dest, uint8 c, uint count);
extern "C" void * memmove(void *dest, const void *src, uint count);
void * alloc(uint cbSize, uint cbPad)
{
cbPad = (cbPad != 0) ? ((cbPad + 0xf) & ~0xf) : 0x10; // 16-byte pad minimum.
uintptr newTop = (heapTop + (cbPad - 1)) & ~(cbPad - 1);
void *pvData = (void *)newTop;
cbSize = (cbSize != 0) ? ((cbSize + 0xf) & ~0xf) : 0x10; //16-byte pad minimum.
newTop += cbSize;
if (newTop > heapMax) {
// Failure, no one checks this call
printf("alloc failure req %d\n", cbSize);
Halt();
return NULL;
}
heapTop = newTop;
memset(pvData, 0, cbSize);
return pvData;
}
void * alloc(uint cbSize)
{
return alloc(cbSize, 0x10);
}
void * allocpages(uint cPages)
{
return alloc(Class_Microsoft_Singularity_Hal_Platform_PAGE_SIZE * cPages,
Class_Microsoft_Singularity_Hal_Platform_PAGE_SIZE);
}
void * operator new(uint cbSize)
{
return alloc(cbSize, 0);
}
///////////////////////////////////////////////////////////// Screen Routines.
//
#define DISPC_REVISION 0x00
#define DISPC_SYSCONFIG 0x10
#define DISPC_SYSSTATUS 0x14
#define DISPC_IRQSTATUS 0x18
#define DISPC_IRQENABLE 0x1C
#define DISPC_CONTROL 0x40
#define DISPC_CONFIG 0x44
#define DISPC_CAPABLE 0x48
#define DISPC_DEFAULT_COLOR0 0x4C
#define DISPC_DEFAULT_COLOR1 0x50
#define DISPC_TRANS_COLOR0 0x54
#define DISPC_TRANS_COLOR1 0x58
#define DISPC_LINE_STATUS 0x5C
#define DISPC_LINE_NUMBER 0x60
#define DISPC_TIMING_H 0x64
#define DISPC_TIMING_V 0x68
#define DISPC_POL_FREQ 0x6C
#define DISPC_DIVISOR 0x70
#define DISPC_SIZE_DIG 0x78
#define DISPC_SIZE_LCD 0x7C
#define DISPC_GFX_BA0 0x80
#define DISPC_GFX_BA1 0x84
#define DISPC_GFX_POSITION 0x88
#define DISPC_GFX_SIZE 0x8C
#define DISPC_GFX_ATTRIBUTES 0xA0
#define DISPC_GFX_FIFO_THRESHOLD 0xA4
#define DISPC_GFX_FIFO_SIZE_STATUS 0xA8
#define DISPC_GFX_ROW_INC 0xAC
#define DISPC_GFX_PIXEL_INC 0xB0
#define DISPC_GFX_WINDOW_SKIP 0xB4
#define DISPC_GFX_TABLE_BA 0xB8
#define DISPC_VID1_BA0 0xBC
#define DISPC_VID1_BA1 0xC0
#define DISPC_VID1_POSITION 0xC4
#define DISPC_VID1_SIZE 0xC8
#define DISPC_VID1_ATTRIBUTES 0xCC
#define DISPC_VID1_FIFO_THRESHOLD 0xD0
#define DISPC_VID1_FIFO_SIZE_STATUS 0xD4
#define DISPC_VID1_ROW_INC 0xD8
#define DISPC_VID1_PIXEL_INC 0xDC
#define DISPC_VID1_FIR 0xE0
#define DISPC_VID1_PICTURE_SIZE 0xE4
#define DISPC_VID1_ACCU0 0xE8
#define DISPC_VID1_ACCU1 0xEC
#define DISPC_VID1_CONV_COEF0 0x130
#define DISPC_VID1_CONV_COEF1 0x134
#define DISPC_VID1_CONV_COEF2 0x138
#define DISPC_VID1_CONV_COEF3 0x13C
#define DISPC_VID1_CONV_COEF4 0x140
#define DISPC_VID2_BA0 0x14C
#define DISPC_VID2_BA1 0x150
#define DISPC_VID2_POSITION 0x154
#define DISPC_VID2_SIZE 0x158
#define DISPC_VID2_ATTRIBUTES 0x15C
#define DISPC_VID2_FIFO_THRESHOLD 0x160
#define DISPC_VID2_FIFO_SIZE_STATUS 0x164
#define DISPC_VID2_ROW_INC 0x168
#define DISPC_VID2_PIXEL_INC 0x16C
#define DISPC_VID2_FIR 0x170
#define DISPC_VID2_PICTURE_SIZE 0x174
#define DISPC_VID2_ACCU0 0x178
#define DISPC_VID2_ACCU1 0x17C
#define DISPC_VID2_CONV_COEF0 0x1C0
#define DISPC_VID2_CONV_COEF1 0x1C4
#define DISPC_VID2_CONV_COEF2 0x1C8
#define DISPC_VID2_CONV_COEF3 0x1CC
#define DISPC_VID2_CONV_COEF4 0x1D0
#define DISPC_DATA_CYCLE1 0x1D4
#define DISPC_DATA_CYCLE2 0x1D8
#define DISPC_DATA_CYCLE3 0x1DC
#define DISPC_CPR_COEF_R 0x220
#define DISPC_CPR_COEF_G 0x224
#define DISPC_CPR_COEF_B 0x228
#define DISPC_GFX_PRELOAD 0x22C
#define DISPC_VID1_PRELOAD 0x230
#define DISPC_VID2_PRELOAD 0x234
#define DISPC_CONFIG_LOADMODE_FRDATLEF (2 << 1) // XXX maybe
#define DISPC_CONTROL_DIGITALENABLE (1 << 1)
#define DISPC_CONTROL_GOLCD (1 << 5)
#define DISPC_CONTROL_GPOUT0 (1 << 15)
#define DISPC_CONTROL_GPOUT1 (1 << 16)
#define DISPC_CONTROL_LCDENABLE (1 << 0)
#define DISPC_CONTROL_RFBIMODE (1 << 11)
#define DISPC_CONTROL_STNTFT (1 << 3)
#define DISPC_CONTROL_TFTDATALINES_OALSB16B (1 << 8)
#define DISPC_DIVISOR_LCD_SHIFT 16
#define DISPC_DIVISOR_PCD_SHIFT 0
#define DISPC_GFX_ATTRIBUTES_ENABLE 1
#define DISPC_GFX_ATTRIBUTES_GFXFORMAT_RGB16 (6 << 1)
#define DISPC_GFX_FIFO_THRESHOLD_HIGH_SHIFT 16
#define DISPC_GFX_FIFO_THRESHOLD_LOW_SHIFT 0
#define DISPC_SYSCONFIG_MIDLEMODE_NSTANDBY (1 << 12)
#define DISPC_SYSCONFIG_SIDLEMODE_NIDLE (1 << 3)
#define DISPC_SYSCONFIG_SOFTRESET (1 << 1)
#define DISPC_SYSSTATUS_RESETDONE (1)
#define DISPC_TIMING_H_HBP_SHIFT 20
#define DISPC_TIMING_H_HFP_SHIFT 8
#define DISPC_TIMING_H_HSW_SHIFT 0
#define DISPC_TIMING_V_VBP_SHIFT 20
#define DISPC_TIMING_V_VFP_SHIFT 8
#define DISPC_TIMING_V_VSW_SHIFT 0
#define DISPC_SIZE_LCD_QVGA_PORTRAIT (((320 - 1) << 16) | (240 - 1))
#define DISPC_SIZE_QVGA_PORTRAIT DISPC_SIZE_LCD_QVGA_PORTRAIT
#define GPIO_LCD_BACKLIGHT 24
#define GPIO_LCD_POWER 28
//////////////////////////////////////////////////////////////////////////////
//
//
// I2C interface (used here to control power to SD/MMC cards via the 4030)
//
#define OMAP_I2C1_BASE (0x48070000)
#define I2C_STAT (0x8)
#define I2C_STAT_XDR (1 << 14)
#define I2C_STAT_RDR (1 << 13)
#define I2C_STAT_BUSY (1 << 12)
#define I2C_STAT_XRDY (1 << 4)
#define I2C_STAT_RRDY (1 << 3)
#define I2C_STAT_ARDY (1 << 2)
#define I2C_STAT_NACK (1 << 1)
#define I2C_STAT_AL (1 << 0)
#define I2C_BUF (0x14)
#define I2C_CNT (0x18)
#define I2C_DATA (0x1C)
#define I2C_CON (0x24)
#define I2C_CON_EN (1 << 15)
#define I2C_CON_STB (1 << 11) // XXX REVIEW
#define I2C_CON_MASTER (1 << 10)
#define I2C_CON_DIR_MASK (1 << 9)
#define I2C_CON_XMIT I2C_CON_DIR_MASK
#define I2C_CON_RECV (0)
#define I2C_CON_STP (1 << 1) // XXX REVIEW
#define I2C_CON_STT (1 << 0) // XXX REVIEW
#define I2C_PSC (0x30)
#define I2C_SCLL (0x34)
#define I2C_SCLH (0x38)
#define I2C_OA0 (0x28)
#define I2C_SA (0x2C)
#define I2C_BUFSTAT (0x40)
#define OMAP_PM_RECEIVER (0x4B)
void HalpClocksInitialize()
{
uint32 Value;
// Clock manager domain control registers
uint8 * HalpWKUP_CM = (uint8 *)OMAP_WKUP_CM_BASE;
uint8 * HalpCORE_CM = (uint8 *)OMAP_CORE_CM_BASE;
uint8 * HalpDSS_CM = (uint8 *)OMAP_DSS_CM_BASE;
// Enable interface and function clocks for WKUP (power management)
Value = ReadReg32(HalpWKUP_CM + CM_FCLKEN_WKUP);
Value |= CM_WKUP_EN_GPIO1;
WriteReg32(HalpWKUP_CM + CM_FCLKEN_WKUP, Value);
Value = ReadReg32(HalpWKUP_CM + CM_ICLKEN_WKUP);
Value |= CM_WKUP_EN_GPIO1;
WriteReg32(HalpWKUP_CM + CM_ICLKEN_WKUP, Value);
// Enable interface and function clocks for CORE (peripherals)
Value = ReadReg32(HalpCORE_CM + CM_FCLKEN1_CORE);
Value |= CM_CORE_EN_I2C1;
WriteReg32(HalpCORE_CM + CM_FCLKEN1_CORE, Value);
Value = ReadReg32(HalpCORE_CM + CM_ICLKEN1_CORE);
Value |= CM_CORE_EN_I2C1;
WriteReg32(HalpCORE_CM + CM_ICLKEN1_CORE,Value);
// Enable interface and function clocks for DSS (display)
Value = ReadReg32(HalpDSS_CM + CM_FCLKEN_DSS);
Value |= CM_DSS_EN_DSS1 | CM_DSS_EN_DSS2 | CM_DSS_EN_TV;
WriteReg32(HalpDSS_CM + CM_FCLKEN_DSS, Value);
Value = ReadReg32(HalpDSS_CM + CM_ICLKEN_DSS);
Value |= CM_DSS_EN_DSS1;
WriteReg32(HalpDSS_CM + CM_ICLKEN_DSS, Value);
}
void HalpGpioInitialize()
{
uint32 Value;
uint8 * HalpSCM = (uint8 *)OMAP_SCM_BASE;
//
// Configure GPIO pads
//
// NB: mode 7 is 'safe' mode - GPIO as input with
// no function selected from multiplexer
//
// Enable i2c1_scl
// OMAP_PADCONF_HSUSB0_DAT7[15:0] is hsusb0_data7 (mode 0),
// OMAP_PADCONF_HSUSB0_DAT7[31:16] is i2c1_scl (mode 0)
Value = ReadReg32(HalpSCM + OMAP_PADCONF_HSUSB0_DAT7);
// i2c1_scl mux mode 7 (reset) -> mode 0
Value &= ((OMAP_PADCONF_MUXMODE_MASK << OMAP_PADCONF_SHIFT) | OMAP_PADCONF_MASK);
WriteReg32(HalpSCM + OMAP_PADCONF_HSUSB0_DAT7,Value);
// Enable i2c1_sda
// OMAP_PADCONF_I2C1_SDA[15:0] is i2c1_sda (mode 0),
// OMAP_PADCONF_I2C1_SDA[31:16] is i2c2_scl (mode 0)
Value = ReadReg32(HalpSCM + OMAP_PADCONF_I2C1_SDA);
// i2c1_sda mux mode 7 (reset) -> mode 0 */
Value &= ((OMAP_PADCONF_MASK << OMAP_PADCONF_SHIFT) | OMAP_PADCONF_MUXMODE_MASK);
WriteReg32(HalpSCM + OMAP_PADCONF_I2C1_SDA,Value);
// Enable sys_nirq
// - connected to int1_n on TWL4030
// OMAP_PADCONF_SYS_NIRQ[15:0] is sys_nirq (mode 0),
// OMAP_PADCONF_SYS_NIRQ[31:16] is sys_clkout2 (mode 0)
Value = ReadReg32(HalpSCM + OMAP_PADCONF_SYS_NIRQ);
// sys_nirq mux mode 7 (reset) -> mode 0
Value &= ((OMAP_PADCONF_MASK << OMAP_PADCONF_SHIFT) | OMAP_PADCONF_MUXMODE_MASK);
WriteReg32(HalpSCM + OMAP_PADCONF_I2C1_SDA,Value);
// Enable dss_* for LCD; configure these as:
// PULLTYPESELECT = 0, PULLUDENABLE = 0, output
uint8 * LcdGpioConfigRegister = (uint8 *)OMAP_SCM_BASE + OMAP_PADCONF_DSS_PCLK;
uint8* const LcdGpioConfigRegisterEnd = (uint8 *)OMAP_SCM_BASE + OMAP_PADCONF_DSS_DAT18;
// OMAP_PADCONF_DSS_PCLK[15:0] is dss_pclk (mode 0),
// OMAP_PADCONF_DSS_PCLK[31:16] is dss_hsync (mode 0),
// OMAP_PADCONF_DSS_VSYNC[15:0] is dss_vsync (mode 0),
// OMAP_PADCONF_DSS_VSYNC[31:16] is dss_acbias (mode 0),
// OMAP_PADCONF_DSS_DATn[15:0] is dss_data(n) (mode 0),
// OMAP_PADCONF_DSS_DATn[31:16] is dss_data(n+1) (mode 0)
for (; LcdGpioConfigRegister <= LcdGpioConfigRegisterEnd; LcdGpioConfigRegister += 4) {
WriteReg32(LcdGpioConfigRegister, (OMAP_PADCONF_MUXMODE_0 << OMAP_PADCONF_SHIFT) | OMAP_PADCONF_MUXMODE_0);
}
// [arog - Do we need to configure etk_d15/11 as well as gpio_24/28?]
// OMAP_PADCONF_ETK_D14[15:0] is gpio_28 (mode 4),
// OMAP_PADCONF_ETK_D14[31:16] is etk_d15 (mode 0) */
WriteReg32(HalpSCM + OMAP_PADCONF_ETK_D14, (OMAP_PADCONF_MUXMODE_0 << OMAP_PADCONF_SHIFT) | OMAP_PADCONF_MUXMODE_4);
// OMAP_PADCONF_ETK_D10[15:0] is gpio_24 (mode 4),
// OMAP_PADCONF_ETK_D10[31:16] is etk_d11 (mode 0)
WriteReg32(HalpSCM + OMAP_PADCONF_ETK_D10, (OMAP_PADCONF_MUXMODE_0 << OMAP_PADCONF_SHIFT) | OMAP_PADCONF_MUXMODE_4);
}
void HalpI2CMasterInitialize()
{
uint16 ShortValue;
uint8 * HalpI2C1 = (uint8 *)OMAP_I2C1_BASE;
// Setup I2C1 controller
// _ARM_WORKAROUND_ i2c code is erroring out
if ((ReadReg16(HalpI2C1 + I2C_CON) & I2C_CON_EN) != 0) {
ShortValue = ReadReg16(HalpI2C1 + I2C_CON);
ShortValue &= I2C_CON_EN;
WriteReg16(HalpI2C1 + I2C_CON, ShortValue);
ReadReg16(HalpI2C1 + I2C_CON);
}
ASSERT((ReadReg16(HalpI2C1 + I2C_CON) & I2C_CON_EN) == 0);
// We should handle the case where it was already enabled.
// Configure internal sampling frequency for 12Mhz.
WriteReg8(HalpI2C1 + I2C_PSC, 7);
// Configure for 100 kb/s
WriteReg8(HalpI2C1 + I2C_SCLL, 54);
WriteReg8(HalpI2C1 + I2C_SCLH, 56);
// Set own address address register
WriteReg16(HalpI2C1 + I2C_OA0, 0x21);
// Take I2C controller out of reset
ShortValue = ReadReg16(HalpI2C1 + I2C_CON);
ShortValue |= I2C_CON_EN;
WriteReg16(HalpI2C1 + I2C_CON,ShortValue);
}
void HalpI2CMasterSetup(
bool Xmit,
uint8 SlaveAddress,
uint16 Length,
bool GenerateStart,
bool GenerateStop
)
{
uint16 ShortValue;
uint8 * HalpI2C1 = (uint8 *)OMAP_I2C1_BASE;
WriteReg16(HalpI2C1 + I2C_CON,I2C_CON_EN);
// Set slave address
WriteReg16(HalpI2C1 + I2C_SA,SlaveAddress);
// Set transfer length
WriteReg16(HalpI2C1 + I2C_CNT,Length);
// Clear status
WriteReg16(HalpI2C1 + I2C_STAT,
I2C_STAT_ARDY | I2C_STAT_NACK | I2C_STAT_AL);
// wait for free bus?
// while ReadReg16(HalpI2C1 + I2C_STAT)) & I2C_STAT_BUSY);
ShortValue = I2C_CON_EN | I2C_CON_MASTER;
ShortValue |= Xmit ? I2C_CON_XMIT : I2C_CON_RECV;
ShortValue |= GenerateStart ? I2C_CON_STT : 0;
ShortValue |= GenerateStop ? I2C_CON_STP : 0;
WriteReg16(HalpI2C1 + I2C_CON,ShortValue);
}
bool HalpI2CMasterTransfer(bool Xmit, uint16 Length, uint8 * Data)
{
uint16 Stat;
uint16 Room;
uint8 * HalpI2C1 = (uint8 *)OMAP_I2C1_BASE;
for (;;) {
Stat = ReadReg16(HalpI2C1 + I2C_STAT);
if (Stat & (I2C_STAT_NACK|I2C_STAT_AL)) {
ASSERT(Stat == 0);
return false;
}
if (Stat & (I2C_STAT_ARDY)) {
return true;
}
if (Xmit) {
if (Stat & I2C_STAT_XDR) {
Room = ReadReg16(HalpI2C1 + I2C_BUFSTAT) & 0x3F;
while (Room--) {
WriteReg8(HalpI2C1 + I2C_DATA, *Data);
Data++;
Length--;
}
}
if (Stat & I2C_STAT_XRDY) {
Room = ReadReg16(HalpI2C1 + I2C_BUF) & 0x3F;
Room += 1;
while (Room--) {
WriteReg8(HalpI2C1 + I2C_DATA, *Data);
Data++;
Length--;
}
}
}
else {
if (Stat & I2C_STAT_RDR) {
Room = (ReadReg16(HalpI2C1 + I2C_BUFSTAT) >> 8) & 0x3F;
while (Room--) {
*Data = ReadReg8(HalpI2C1 + I2C_DATA);
Data++;
Length--;
}
}
if (Stat & I2C_STAT_RRDY) {
Room = (ReadReg16(HalpI2C1 + I2C_BUF) >> 8) & 0x3F;
Room += 1;
while (Room--) {
*Data = ReadReg8(HalpI2C1 + I2C_DATA);
Data++;
Length--;
}
}
}
WriteReg16(HalpI2C1 + I2C_STAT,Stat);
}
return true;
}
bool
HalpI2CMasterCommon(
bool Xmit,
uint8 SlaveAddress,
uint16 Length,
uint8 * Data,
bool GenerateStart,
bool GenerateStop
)
{
int retry = 10;
while (retry--) {
HalpI2CMasterSetup(Xmit, OMAP_PM_RECEIVER, Length, GenerateStart, GenerateStop);
if (HalpI2CMasterTransfer(Xmit, Length, Data)) {
return true;
}
}
return false;
}
bool
HalpI2CMasterReceive(
uint8 SlaveAddress,
uint16 Length,
uint8 * Data,
bool GenerateStart,
bool GenerateStop
)
{
return HalpI2CMasterCommon(false, OMAP_PM_RECEIVER, Length, Data,
GenerateStart, GenerateStop);
}
bool
HalpI2CMasterSend(
uint8 SlaveAddress,
uint16 Length,
uint8 * Data,
bool GenerateStart,
bool GenerateStop
)
{
return HalpI2CMasterCommon(true, OMAP_PM_RECEIVER, Length, Data,
GenerateStart, GenerateStop);
}
//////////////////////////////////////////////////////////////////////////////
//
void InitializeDisplayPowerDomains()
{
uint32 Value;
bool Good;
uint32 Count;
uint8 Data[2];
//
// Bootstrap VAUX3
//
Data[0] = 0x7A;
Data[1] = 1 << 5;
Good = HalpI2CMasterSend(OMAP_PM_RECEIVER, 2, Data, true, true);
ASSERT(Good);
Data[0] = 0x7B;
Data[1] = 4;
Good = HalpI2CMasterSend(OMAP_PM_RECEIVER, 2, Data, true, true);
ASSERT(Good);
Data[0] = 0x7d;
Data[1] = 0x3;
Good = HalpI2CMasterSend(OMAP_PM_RECEIVER, 2, Data, true, true);
ASSERT(Good);
Data[0] = 0x7d;
Good = HalpI2CMasterSend(OMAP_PM_RECEIVER, 1, Data, true, false);
ASSERT(Good);
Good = HalpI2CMasterReceive(OMAP_PM_RECEIVER, 1, Data, true, true);
ASSERT(Good);
ASSERT(Data[0] == 3);
Count = 0xFFFF;
while (Count--);
uint8 * HalpGPIO1 = (uint8 *)OMAP_GPIO1_BASE;
Value = ReadReg32(HalpGPIO1 + OMAP_GPIO_OE);
Value &= ~(OMAP_GPIO_PIN_24 | OMAP_GPIO_PIN_28);
WriteReg32(HalpGPIO1 + OMAP_GPIO_OE, Value);
WriteReg32(HalpGPIO1 + OMAP_GPIO_SETDATAOUT, OMAP_GPIO_PIN_28);
Count = 0xFFFF;
while (Count--);
WriteReg32(HalpGPIO1 + OMAP_GPIO_SETDATAOUT, OMAP_GPIO_PIN_24);
}
//////////////////////////////////////////////////////////////////////////////
uint8 Font8[] =
{
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x7e,0x81,0xa5,0x81,0xbd,0x99,0x81,0x7e,
0x7e,0xff,0xdb,0xff,0xc3,0xe7,0xff,0x7e,
0x6c,0xfe,0xfe,0xfe,0x7c,0x38,0x10,0x00,
0x10,0x38,0x7c,0xfe,0x7c,0x38,0x10,0x00,
0x38,0x7c,0x38,0xfe,0xfe,0x7c,0x38,0x7c,
0x10,0x10,0x38,0x7c,0xfe,0x7c,0x38,0x7c,
0x00,0x00,0x18,0x3c,0x3c,0x18,0x00,0x00,
0xff,0xff,0xe7,0xc3,0xc3,0xe7,0xff,0xff,
0x00,0x3c,0x66,0x42,0x42,0x66,0x3c,0x00,
0xff,0xc3,0x99,0xbd,0xbd,0x99,0xc3,0xff,
0x0f,0x07,0x0f,0x7d,0xcc,0xcc,0xcc,0x78,
0x3c,0x66,0x66,0x66,0x3c,0x18,0x7e,0x18,
0x3f,0x33,0x3f,0x30,0x30,0x70,0xf0,0xe0,
0x7f,0x63,0x7f,0x63,0x63,0x67,0xe6,0xc0,
0x99,0x5a,0x3c,0xe7,0xe7,0x3c,0x5a,0x99,
0x80,0xe0,0xf8,0xfe,0xf8,0xe0,0x80,0x00,
0x02,0x0e,0x3e,0xfe,0x3e,0x0e,0x02,0x00,
0x18,0x3c,0x7e,0x18,0x18,0x7e,0x3c,0x18,
0x66,0x66,0x66,0x66,0x66,0x00,0x66,0x00,
0x7f,0xdb,0xdb,0x7b,0x1b,0x1b,0x1b,0x00,
0x3e,0x63,0x38,0x6c,0x6c,0x38,0xcc,0x78,
0x00,0x00,0x00,0x00,0x7e,0x7e,0x7e,0x00,
0x18,0x3c,0x7e,0x18,0x7e,0x3c,0x18,0xff,
0x18,0x3c,0x7e,0x18,0x18,0x18,0x18,0x00,
0x18,0x18,0x18,0x18,0x7e,0x3c,0x18,0x00,
0x00,0x18,0x0c,0xfe,0x0c,0x18,0x00,0x00,
0x00,0x30,0x60,0xfe,0x60,0x30,0x00,0x00,
0x00,0x00,0xc0,0xc0,0xc0,0xfe,0x00,0x00,
0x00,0x24,0x66,0xff,0x66,0x24,0x00,0x00,
0x00,0x18,0x3c,0x7e,0xff,0xff,0x00,0x00,
0x00,0xff,0xff,0x7e,0x3c,0x18,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x30,0x78,0x78,0x30,0x30,0x00,0x30,0x00,
0x6c,0x6c,0x6c,0x00,0x00,0x00,0x00,0x00,
0x6c,0x6c,0xfe,0x6c,0xfe,0x6c,0x6c,0x00,
0x30,0x7c,0xc0,0x78,0x0c,0xf8,0x30,0x00,
0x00,0xc6,0xcc,0x18,0x30,0x66,0xc6,0x00,
0x38,0x6c,0x38,0x76,0xdc,0xcc,0x76,0x00,
0x60,0x60,0xc0,0x00,0x00,0x00,0x00,0x00,
0x18,0x30,0x60,0x60,0x60,0x30,0x18,0x00,
0x60,0x30,0x18,0x18,0x18,0x30,0x60,0x00,
0x00,0x66,0x3c,0xff,0x3c,0x66,0x00,0x00,
0x00,0x30,0x30,0xfc,0x30,0x30,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x60,
0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,
0x06,0x0c,0x18,0x30,0x60,0xc0,0x80,0x00,
0x7c,0xc6,0xce,0xde,0xf6,0xe6,0x7c,0x00,
0x30,0x70,0x30,0x30,0x30,0x30,0xfc,0x00,
0x78,0xcc,0x0c,0x38,0x60,0xcc,0xfc,0x00,
0x78,0xcc,0x0c,0x38,0x0c,0xcc,0x78,0x00,
0x1c,0x3c,0x6c,0xcc,0xfe,0x0c,0x1e,0x00,
0xfc,0xc0,0xf8,0x0c,0x0c,0xcc,0x78,0x00,
0x38,0x60,0xc0,0xf8,0xcc,0xcc,0x78,0x00,
0xfc,0xcc,0x0c,0x18,0x30,0x30,0x30,0x00,
0x78,0xcc,0xcc,0x78,0xcc,0xcc,0x78,0x00,
0x78,0xcc,0xcc,0x7c,0x0c,0x18,0x70,0x00,
0x00,0x30,0x30,0x00,0x00,0x30,0x30,0x00,
0x00,0x30,0x30,0x00,0x00,0x30,0x30,0x60,
0x18,0x30,0x60,0xc0,0x60,0x30,0x18,0x00,
0x00,0x00,0xfc,0x00,0x00,0xfc,0x00,0x00,
0x60,0x30,0x18,0x0c,0x18,0x30,0x60,0x00,
0x78,0xcc,0x0c,0x18,0x30,0x00,0x30,0x00,
0x7c,0xc6,0xde,0xde,0xde,0xc0,0x78,0x00,
0x30,0x78,0xcc,0xcc,0xfc,0xcc,0xcc,0x00,
0xfc,0x66,0x66,0x7c,0x66,0x66,0xfc,0x00,
0x3c,0x66,0xc0,0xc0,0xc0,0x66,0x3c,0x00,
0xf8,0x6c,0x66,0x66,0x66,0x6c,0xf8,0x00,
0xfe,0x62,0x68,0x78,0x68,0x62,0xfe,0x00,
0xfe,0x62,0x68,0x78,0x68,0x60,0xf0,0x00,
0x3c,0x66,0xc0,0xc0,0xce,0x66,0x3e,0x00,
0xcc,0xcc,0xcc,0xfc,0xcc,0xcc,0xcc,0x00,
0x78,0x30,0x30,0x30,0x30,0x30,0x78,0x00,
0x1e,0x0c,0x0c,0x0c,0xcc,0xcc,0x78,0x00,
0xe6,0x66,0x6c,0x78,0x6c,0x66,0xe6,0x00,
0xf0,0x60,0x60,0x60,0x62,0x66,0xfe,0x00,
0xc6,0xee,0xfe,0xfe,0xd6,0xc6,0xc6,0x00,
0xc6,0xe6,0xf6,0xde,0xce,0xc6,0xc6,0x00,
0x38,0x6c,0xc6,0xc6,0xc6,0x6c,0x38,0x00,
0xfc,0x66,0x66,0x7c,0x60,0x60,0xf0,0x00,
0x78,0xcc,0xcc,0xcc,0xdc,0x78,0x1c,0x00,
0xfc,0x66,0x66,0x7c,0x6c,0x66,0xe6,0x00,
0x78,0xcc,0xe0,0x70,0x1c,0xcc,0x78,0x00,
0xfc,0xb4,0x30,0x30,0x30,0x30,0x78,0x00,
0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xfc,0x00,
0xcc,0xcc,0xcc,0xcc,0xcc,0x78,0x30,0x00,
0xc6,0xc6,0xc6,0xd6,0xfe,0xee,0xc6,0x00,
0xc6,0xc6,0x6c,0x38,0x38,0x6c,0xc6,0x00,
0xcc,0xcc,0xcc,0x78,0x30,0x30,0x78,0x00,
0xfe,0xc6,0x8c,0x18,0x32,0x66,0xfe,0x00,
0x78,0x60,0x60,0x60,0x60,0x60,0x78,0x00,
0xc0,0x60,0x30,0x18,0x0c,0x06,0x02,0x00,
0x78,0x18,0x18,0x18,0x18,0x18,0x78,0x00,
0x10,0x38,0x6c,0xc6,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,
0x30,0x30,0x18,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x78,0x0c,0x7c,0xcc,0x76,0x00,
0xe0,0x60,0x60,0x7c,0x66,0x66,0xdc,0x00,
0x00,0x00,0x78,0xcc,0xc0,0xcc,0x78,0x00,
0x1c,0x0c,0x0c,0x7c,0xcc,0xcc,0x76,0x00,
0x00,0x00,0x78,0xcc,0xfc,0xc0,0x78,0x00,
0x38,0x6c,0x60,0xf0,0x60,0x60,0xf0,0x00,
0x00,0x00,0x76,0xcc,0xcc,0x7c,0x0c,0xf8,
0xe0,0x60,0x6c,0x76,0x66,0x66,0xe6,0x00,
0x30,0x00,0x70,0x30,0x30,0x30,0x78,0x00,
0x0c,0x00,0x0c,0x0c,0x0c,0xcc,0xcc,0x78,
0xe0,0x60,0x66,0x6c,0x78,0x6c,0xe6,0x00,
0x70,0x30,0x30,0x30,0x30,0x30,0x78,0x00,
0x00,0x00,0xcc,0xfe,0xfe,0xd6,0xc6,0x00,
0x00,0x00,0xf8,0xcc,0xcc,0xcc,0xcc,0x00,
0x00,0x00,0x78,0xcc,0xcc,0xcc,0x78,0x00,
0x00,0x00,0xdc,0x66,0x66,0x7c,0x60,0xf0,
0x00,0x00,0x76,0xcc,0xcc,0x7c,0x0c,0x1e,
0x00,0x00,0xdc,0x76,0x66,0x60,0xf0,0x00,
0x00,0x00,0x7c,0xc0,0x78,0x0c,0xf8,0x00,
0x10,0x30,0x7c,0x30,0x30,0x34,0x18,0x00,
0x00,0x00,0xcc,0xcc,0xcc,0xcc,0x76,0x00,
0x00,0x00,0xcc,0xcc,0xcc,0x78,0x30,0x00,
0x00,0x00,0xc6,0xd6,0xfe,0xfe,0x6c,0x00,
0x00,0x00,0xc6,0x6c,0x38,0x6c,0xc6,0x00,
0x00,0x00,0xcc,0xcc,0xcc,0x7c,0x0c,0xf8,
0x00,0x00,0xfc,0x98,0x30,0x64,0xfc,0x00,
0x1c,0x30,0x30,0xe0,0x30,0x30,0x1c,0x00,
0x18,0x18,0x18,0x00,0x18,0x18,0x18,0x00,
0xe0,0x30,0x30,0x1c,0x30,0x30,0xe0,0x00,
0x76,0xdc,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x10,0x38,0x6c,0xc6,0xc6,0xfe,0x00,
0x78,0xcc,0xc0,0xcc,0x78,0x18,0x0c,0x78,
0x00,0xcc,0x00,0xcc,0xcc,0xcc,0x7e,0x00,
0x1c,0x00,0x78,0xcc,0xfc,0xc0,0x78,0x00,
0x7e,0xc3,0x3c,0x06,0x3e,0x66,0x3f,0x00,
0xcc,0x00,0x78,0x0c,0x7c,0xcc,0x7e,0x00,
0xe0,0x00,0x78,0x0c,0x7c,0xcc,0x7e,0x00,
0x30,0x30,0x78,0x0c,0x7c,0xcc,0x7e,0x00,
0x00,0x00,0x78,0xc0,0xc0,0x78,0x0c,0x38,
0x7e,0xc3,0x3c,0x66,0x7e,0x60,0x3c,0x00,
0xcc,0x00,0x78,0xcc,0xfc,0xc0,0x78,0x00,
0xe0,0x00,0x78,0xcc,0xfc,0xc0,0x78,0x00,
0xcc,0x00,0x70,0x30,0x30,0x30,0x78,0x00,
0x7c,0xc6,0x38,0x18,0x18,0x18,0x3c,0x00,
0xe0,0x00,0x70,0x30,0x30,0x30,0x78,0x00,
0xc6,0x38,0x6c,0xc6,0xfe,0xc6,0xc6,0x00,
0x30,0x30,0x00,0x78,0xcc,0xfc,0xcc,0x00,
0x1c,0x00,0xfc,0x60,0x78,0x60,0xfc,0x00,
0x00,0x00,0x7f,0x0c,0x7f,0xcc,0x7f,0x00,
0x3e,0x6c,0xcc,0xfe,0xcc,0xcc,0xce,0x00,
0x78,0xcc,0x00,0x78,0xcc,0xcc,0x78,0x00,
0x00,0xcc,0x00,0x78,0xcc,0xcc,0x78,0x00,
0x00,0xe0,0x00,0x78,0xcc,0xcc,0x78,0x00,
0x78,0xcc,0x00,0xcc,0xcc,0xcc,0x7e,0x00,
0x00,0xe0,0x00,0xcc,0xcc,0xcc,0x7e,0x00,
0x00,0xcc,0x00,0xcc,0xcc,0x7c,0x0c,0xf8,
0xc3,0x18,0x3c,0x66,0x66,0x3c,0x18,0x00,
0xcc,0x00,0xcc,0xcc,0xcc,0xcc,0x78,0x00,
0x18,0x18,0x7e,0xc0,0xc0,0x7e,0x18,0x18,
0x38,0x6c,0x64,0xf0,0x60,0xe6,0xfc,0x00,
0xcc,0xcc,0x78,0xfc,0x30,0xfc,0x30,0x30,
0xf8,0xcc,0xcc,0xfa,0xc6,0xcf,0xc6,0xc7,
0x0e,0x1b,0x18,0x3c,0x18,0x18,0xd8,0x70,
0x1c,0x00,0x78,0x0c,0x7c,0xcc,0x7e,0x00,
0x38,0x00,0x70,0x30,0x30,0x30,0x78,0x00,
0x00,0x1c,0x00,0x78,0xcc,0xcc,0x78,0x00,
0x00,0x1c,0x00,0xcc,0xcc,0xcc,0x7e,0x00,
0x00,0xf8,0x00,0xf8,0xcc,0xcc,0xcc,0x00,
0xfc,0x00,0xcc,0xec,0xfc,0xdc,0xcc,0x00,
0x3c,0x6c,0x6c,0x3e,0x00,0x7e,0x00,0x00,
0x38,0x6c,0x6c,0x38,0x00,0x7c,0x00,0x00,
0x30,0x00,0x30,0x60,0xc0,0xcc,0x78,0x00,
0x00,0x00,0x00,0xfc,0xc0,0xc0,0x00,0x00,
0x00,0x00,0x00,0xfc,0x0c,0x0c,0x00,0x00,
0xc3,0xc6,0xcc,0xde,0x33,0x66,0xcc,0x0f,
0xc3,0xc6,0xcc,0xdb,0x37,0x6f,0xcf,0x03,
0x18,0x18,0x00,0x18,0x18,0x18,0x18,0x00,
0x00,0x33,0x66,0xcc,0x66,0x33,0x00,0x00,
0x00,0xcc,0x66,0x33,0x66,0xcc,0x00,0x00,
0x22,0x88,0x22,0x88,0x22,0x88,0x22,0x88,
0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,
0xdb,0x77,0xdb,0xee,0xdb,0x77,0xdb,0xee,
0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
0x18,0x18,0x18,0x18,0xf8,0x18,0x18,0x18,
0x18,0x18,0xf8,0x18,0xf8,0x18,0x18,0x18,
0x36,0x36,0x36,0x36,0xf6,0x36,0x36,0x36,
0x00,0x00,0x00,0x00,0xfe,0x36,0x36,0x36,
0x00,0x00,0xf8,0x18,0xf8,0x18,0x18,0x18,
0x36,0x36,0xf6,0x06,0xf6,0x36,0x36,0x36,
0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
0x00,0x00,0xfe,0x06,0xf6,0x36,0x36,0x36,
0x36,0x36,0xf6,0x06,0xfe,0x00,0x00,0x00,
0x36,0x36,0x36,0x36,0xfe,0x00,0x00,0x00,
0x18,0x18,0xf8,0x18,0xf8,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0xf8,0x18,0x18,0x18,
0x18,0x18,0x18,0x18,0x1f,0x00,0x00,0x00,
0x18,0x18,0x18,0x18,0xff,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0xff,0x18,0x18,0x18,
0x18,0x18,0x18,0x18,0x1f,0x18,0x18,0x18,
0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,
0x18,0x18,0x18,0x18,0xff,0x18,0x18,0x18,
0x18,0x18,0x1f,0x18,0x1f,0x18,0x18,0x18,
0x36,0x36,0x36,0x36,0x37,0x36,0x36,0x36,
0x36,0x36,0x37,0x30,0x3f,0x00,0x00,0x00,
0x00,0x00,0x3f,0x30,0x37,0x36,0x36,0x36,
0x36,0x36,0xf7,0x00,0xff,0x00,0x00,0x00,
0x00,0x00,0xff,0x00,0xf7,0x36,0x36,0x36,
0x36,0x36,0x37,0x30,0x37,0x36,0x36,0x36,
0x00,0x00,0xff,0x00,0xff,0x00,0x00,0x00,
0x36,0x36,0xf7,0x00,0xf7,0x36,0x36,0x36,
0x18,0x18,0xff,0x00,0xff,0x00,0x00,0x00,
0x36,0x36,0x36,0x36,0xff,0x00,0x00,0x00,
0x00,0x00,0xff,0x00,0xff,0x18,0x18,0x18,
0x00,0x00,0x00,0x00,0xff,0x36,0x36,0x36,
0x36,0x36,0x36,0x36,0x3f,0x00,0x00,0x00,
0x18,0x18,0x1f,0x18,0x1f,0x00,0x00,0x00,
0x00,0x00,0x1f,0x18,0x1f,0x18,0x18,0x18,
0x00,0x00,0x00,0x00,0x3f,0x36,0x36,0x36,
0x36,0x36,0x36,0x36,0xff,0x36,0x36,0x36,
0x18,0x18,0xff,0x18,0xff,0x18,0x18,0x18,
0x18,0x18,0x18,0x18,0xf8,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x1f,0x18,0x18,0x18,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,
0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,
0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,
0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,
0x00,0x00,0x76,0xdc,0xc8,0xdc,0x76,0x00,
0x00,0x78,0xcc,0xf8,0xcc,0xf8,0xc0,0xc0,
0x00,0xfc,0xcc,0xc0,0xc0,0xc0,0xc0,0x00,
0x00,0xfe,0x6c,0x6c,0x6c,0x6c,0x6c,0x00,
0xfc,0xcc,0x60,0x30,0x60,0xcc,0xfc,0x00,
0x00,0x00,0x7e,0xd8,0xd8,0xd8,0x70,0x00,
0x00,0x66,0x66,0x66,0x66,0x7c,0x60,0xc0,
0x00,0x76,0xdc,0x18,0x18,0x18,0x18,0x00,
0xfc,0x30,0x78,0xcc,0xcc,0x78,0x30,0xfc,
0x38,0x6c,0xc6,0xfe,0xc6,0x6c,0x38,0x00,
0x38,0x6c,0xc6,0xc6,0x6c,0x6c,0xee,0x00,
0x1c,0x30,0x18,0x7c,0xcc,0xcc,0x78,0x00,
0x00,0x00,0x7e,0xdb,0xdb,0x7e,0x00,0x00,
0x06,0x0c,0x7e,0xdb,0xdb,0x7e,0x60,0xc0,
0x38,0x60,0xc0,0xf8,0xc0,0x60,0x38,0x00,
0x78,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x00,
0x00,0xfc,0x00,0xfc,0x00,0xfc,0x00,0x00,
0x30,0x30,0xfc,0x30,0x30,0x00,0xfc,0x00,
0x60,0x30,0x18,0x30,0x60,0x00,0xfc,0x00,
0x18,0x30,0x60,0x30,0x18,0x00,0xfc,0x00,
0x0e,0x1b,0x1b,0x18,0x18,0x18,0x18,0x18,
0x18,0x18,0x18,0x18,0x18,0xd8,0xd8,0x70,
0x30,0x30,0x00,0xfc,0x00,0x30,0x30,0x00,
0x00,0x76,0xdc,0x00,0x76,0xdc,0x00,0x00,
0x38,0x6c,0x6c,0x38,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x00,
0x0f,0x0c,0x0c,0x0c,0xec,0x6c,0x3c,0x1c,
0x78,0x6c,0x6c,0x6c,0x6c,0x00,0x00,0x00,
0x70,0x18,0x30,0x60,0x78,0x00,0x00,0x00,
0x00,0x00,0x3c,0x3c,0x3c,0x3c,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
};
static uint32 videoCursor = 0;
static uint16 * videoBuffer = 0;
void InitializeDisplay(uint16 * VideoBuffer)
{
InitializeDisplayPowerDomains();
videoBuffer = VideoBuffer;
uint8 * DispCRegBase = (uint8 *)0x48050400;
//
// XXX code derived from TI diagnostic, tainted.
//
// xxx dss_clock_init
//
// disable dss
//
uint32 Value = ReadReg32(DispCRegBase + DISPC_CONTROL);
Value &= ~(DISPC_CONTROL_DIGITALENABLE | DISPC_CONTROL_LCDENABLE);
WriteReg32(DispCRegBase + DISPC_CONTROL, Value);
//
// Reset display controller
//
WriteReg32(DispCRegBase + DISPC_SYSCONFIG, DISPC_SYSCONFIG_SOFTRESET);
while((ReadReg32(DispCRegBase + DISPC_SYSSTATUS) & DISPC_SYSSTATUS_RESETDONE) == 0);
Value = ReadReg32(DispCRegBase + DISPC_SYSCONFIG);
Value &= ~DISPC_SYSCONFIG_SOFTRESET;
WriteReg32(DispCRegBase + DISPC_SYSCONFIG, Value);
//
// _ARM_WORKAROUND_ cheat and setup lcd power and backlight
// earlier in HAL. Right way to do this is with query interface
// of the stack to get a control interface.
//
// XXX do triton thing here to enable lcd power, and thena gpio that i don't understand
// xxx gpio thing to enable backlight
// configure dss
WriteReg32(DispCRegBase + DISPC_SYSCONFIG,
DISPC_SYSCONFIG_MIDLEMODE_NSTANDBY |
DISPC_SYSCONFIG_SIDLEMODE_NIDLE);
// disable interrupts
WriteReg32(DispCRegBase + DISPC_IRQENABLE, 0);
// 2:1 - Frame Data only loaded every frame (10)
WriteReg32(DispCRegBase + DISPC_CONFIG,
DISPC_CONFIG_LOADMODE_FRDATLEF);
// Default Color is white
WriteReg32(DispCRegBase + DISPC_DEFAULT_COLOR0,
0xFFFFFF);
// Default Transparency Color is black */
WriteReg32(DispCRegBase + DISPC_TRANS_COLOR0, 0);
// timing logic for HSYNC signal
uint32 bp = (3 - 1);
uint32 fp = (4 - 1);
uint32 sw = (2 - 1);
Value = (bp << DISPC_TIMING_H_HBP_SHIFT) | (fp << DISPC_TIMING_H_HFP_SHIFT) | (sw << DISPC_TIMING_H_HSW_SHIFT);
WriteReg32(DispCRegBase + DISPC_TIMING_H, Value);
// timing logic for VSYNC signal
bp = 6;
fp = 9;
sw = 1;
Value = (bp << DISPC_TIMING_V_VBP_SHIFT) | (fp << DISPC_TIMING_V_VFP_SHIFT) | (sw << DISPC_TIMING_V_VSW_SHIFT);
WriteReg32(DispCRegBase + DISPC_TIMING_V, Value);
// signal configuration
WriteReg32(DispCRegBase + DISPC_POL_FREQ, 0);
// configures the divisor
Value = (1 << DISPC_DIVISOR_LCD_SHIFT) | (17 << DISPC_DIVISOR_PCD_SHIFT);
WriteReg32(DispCRegBase + DISPC_DIVISOR, Value);
// configure panel size
WriteReg32(DispCRegBase + DISPC_SIZE_LCD,
DISPC_SIZE_LCD_QVGA_PORTRAIT);
// set lcd interface datalines
// defaults to 16
// Configure Graphics Window
WriteReg32(DispCRegBase + DISPC_GFX_BA0, (uint32)VideoBuffer);
WriteReg32(DispCRegBase + DISPC_GFX_BA1, (uint32)VideoBuffer);
// set window position
WriteReg32(DispCRegBase + DISPC_GFX_POSITION, 0);
// set window size
WriteReg32(DispCRegBase + DISPC_GFX_SIZE, DISPC_SIZE_QVGA_PORTRAIT);
Value = ReadReg32(DispCRegBase + DISPC_GFX_ATTRIBUTES);
Value |= DISPC_GFX_ATTRIBUTES_GFXFORMAT_RGB16;
WriteReg32(DispCRegBase + DISPC_GFX_ATTRIBUTES, Value);
Value= (252 << DISPC_GFX_FIFO_THRESHOLD_HIGH_SHIFT) | (192 << DISPC_GFX_FIFO_THRESHOLD_LOW_SHIFT);
WriteReg32(DispCRegBase + DISPC_GFX_FIFO_THRESHOLD, Value);
WriteReg32(DispCRegBase + DISPC_GFX_ROW_INC, 1);
WriteReg32(DispCRegBase + DISPC_GFX_PIXEL_INC, 1);
Value = ReadReg32(DispCRegBase + DISPC_GFX_ATTRIBUTES);
Value |= DISPC_GFX_ATTRIBUTES_ENABLE;
WriteReg32(DispCRegBase + DISPC_GFX_ATTRIBUTES, Value);
// LCD output enabled, active display,16-bit output.
Value = DISPC_CONTROL_GPOUT1 | DISPC_CONTROL_GPOUT0
| DISPC_CONTROL_TFTDATALINES_OALSB16B | DISPC_CONTROL_STNTFT |
DISPC_CONTROL_LCDENABLE;
Value &= ~DISPC_CONTROL_RFBIMODE; // RFBI mode disabled.
WriteReg32(DispCRegBase + DISPC_CONTROL, Value);
Value = ReadReg32(DispCRegBase + DISPC_CONTROL);
Value |= DISPC_CONTROL_GOLCD; // LCD GO command.
WriteReg32(DispCRegBase + DISPC_CONTROL, Value);
memset(VideoBuffer, 0xff, 240 * 320 * 2);
}
void Draw(uint8 c)
{
if (videoBuffer == NULL) {
return;
}
if (c == '\f') {
videoCursor = 0;
memset(videoBuffer, 0, 240 * 320 * 2);
return;
}
else if (c == '\n') {
videoCursor += 30 - (videoCursor % 30);
check_scroll:
while (videoCursor >= 30 * 40) {
memmove(videoBuffer, videoBuffer + 240 * 8, 240 * 312 * 2);
memset(videoBuffer + 312 * 240, 0, 240 * 16); // 2 bytes/pixel * 8 pixels
videoCursor -= 30;
}
return;
}
uint cy = (videoCursor / 30) * 8;
uint cx = (videoCursor % 30) * 8;
uint16 * buffer = videoBuffer + 240 * cy + cx;
if (c == '\r') {
uint toclear = 30 - (videoCursor % 30);
for (uint y = 0; y < 8; y++) {
memset(buffer, 0, toclear * 16); // 2 bytes/pixel * 8 pixels
buffer += 240;
}
videoCursor -= videoCursor % 30;
return;
}
// Find the glyph.
uint8 *pixels = Font8 + c * 8;
// Draw the pixels.
for (uint y = 0; y < 8; y++) {
uint8 line = *pixels++;
for (int x = 7; x >= 0; x--) {
buffer[x] = (line & 1) ? 0xffff : 0x0000;
line >>= 1;
}
buffer += 240;
}
videoCursor++;
goto check_scroll;
}
void Draw(const char * str)
{
for (int i = 0; i < 2048 && str[i] != '\0'; i++) {
Draw((uint8)str[i]);
}
}
//////////////////////////////////////////////////////////////////////////////
void DebugBreak();
void Halt()
{
printf("Halt.");
DebugBreak();
}
void Cls()
{
BdPrintString("-------------------------------------------------------------------------------\n", 80);
Draw('\f');
}
void __cdecl PutChar(char cOut)
{
Draw(cOut);
static CHAR szBuffer[256];
static INT nBuffer = 0;
szBuffer[nBuffer++] = cOut;
if (cOut == '\n' || nBuffer >= sizeof(szBuffer) - 1) {
BdPrintString(szBuffer, nBuffer);
nBuffer = 0;
}
}
void Probe(UINT8 * pbData, UINT cbData)
{
UINT8 b;
for (UINT i = 0; i < cbData; i++) {
b = pbData[i];
pbData[i] = b;
}
}
void Dump(UINT8 * pbData, UINT cbData)
{
for (UINT n = 0; n < cbData; n += 16) {
printf(" %08x:", pbData + n);
UINT o = n;
for (; o < n + 16; o++) {
if (o >= cbData) {
printf(" ");
}
else {
printf("%02x", pbData[o]);
}
if (o % 4 == 3) {
printf(" ");
}
}
printf(" ");
for (o = n; o < n + 16; o++) {
if (o >= cbData) {
printf(" ");
}
else {
if (pbData[o] >= ' ' && pbData[o] < 127) {
printf("%c", pbData[o]);
}
else {
printf(".");
}
}
}
printf("\n");
}
}
void Dump(UINT8 * pbData, UINT8 * pbLimit, UINT cbMax)
{
UINT cbData = (uint) (pbLimit - pbData);
if (cbData > cbMax) {
cbData = cbMax;
}
Dump(pbData, cbData);
}
static void CopyDown(UINT8 *pbDst, UINT8 *pbSrc, UINT32 cbSrc)
{
//!!! pbDst <= pbSrc
if (pbDst > pbSrc) {
printf("CopyDown(dst=%p > src=%p)\n", pbDst, pbSrc);
Halt();
}
INT32 nSrc = (cbSrc + 3) / 4;
volatile UINT32 *pDst = (UINT32*)pbDst;
volatile UINT32 *pSrc = (UINT32*)pbSrc;
while (nSrc-- > 0) {
*pDst = *pSrc;
if (*pDst != *pSrc) {
printf("CopyDown error at %p/%p : %08x != %08x\n",
pDst, pSrc, *pDst, *pSrc);
Halt();
}
pDst++;
pSrc++;
}
}
static void Zero(uint8 * pbData, uint32 cbData)
{
INT32 nDst = (cbData + 3) / 4;
volatile UINT32 *pDst = (UINT32*)pbData;
while (nDst-- > 0) {
*pDst++ = 0;
}
}
const char * SmapTypeToString(int type)
{
switch (type) {
case 1: return "RAM ";
case 2: return "Reserved";
case 3: return "ACPI RAM";
case 4: return "ACPI NVS";
default: return "Other ";
}
}
bool check(UINT8 *pbCache, UINT8 value, const char *pszDesc)
{
for (int i = 0; i < 16; i++) {
if (pbCache[i] == value) {
pbCache[i] = 0;
printf(" %s\n", pszDesc);
return 1;
}
}
return 0;
}
static bool CheckSmapForRam(const Class_Microsoft_Singularity_Hal_Platform *bi, UINT64 base, UINT64 size)
{
Struct_Microsoft_Singularity_SMAPINFO *sm = (Struct_Microsoft_Singularity_SMAPINFO *) bi->Smap32;
for (int32 i = 0; i < bi->SmapCount; i++) {
if (sm[i].type == 1 &&
sm[i].addr <= base &&
sm[i].addr + sm[i].size >= base + size) {
return true;
}
}
return false;
}
static void CheckSmap(const Class_Microsoft_Singularity_Hal_Platform *bi)
{
/////////////////////////////////////////////////////// System Memory Map.
//
printf(" BaseAddr LimtAddr Type \n");
printf(" ======== ======== ========== [%8x]\n", bi->Smap32);
Struct_Microsoft_Singularity_SMAPINFO *sm = (Struct_Microsoft_Singularity_SMAPINFO *) bi->Smap32;
for (int32 i = 0; i < bi->SmapCount; i++) {
printf(" %8x", (UINT32)(sm[i].addr));
printf(" %8x", (UINT32)(sm[i].addr + sm[i].size));
printf(" %d:%s\n",
sm[i].type,
SmapTypeToString((int)sm[i].type));
}
printf("\n");
}
void SortSmap(const Class_Microsoft_Singularity_Hal_Platform *bi)
{
Struct_Microsoft_Singularity_SMAPINFO *sm = (Struct_Microsoft_Singularity_SMAPINFO *) bi->Smap32;
// Sort the system memory map.
sortagain:
for (int i = 0; i < bi->SmapCount - 1; i++) {
if ((sm[i].addr > sm[i + 1].addr) ||
(sm[i].addr == sm[i + 1].addr &&
sm[i].addr > sm[i + 1].addr)) {
Struct_Microsoft_Singularity_SMAPINFO s = sm[i];
sm[i] = sm[i+1];
sm[i+1] = s;
goto sortagain;
}
}
}
static uintptr g_Entry = 0;
static uintptr g_Stack = 0;
static Class_Microsoft_Singularity_Hal_Platform *g_bi = 0;
static Class_Microsoft_Singularity_Hal_Cpu *g_ci = 0;
//////////////////////////////////////////////////////////////////////////////
static bool memeq(const uint8 * p1, const uint8 * p2, uint size)
{
for (; size > 0; size--) {
if (*p1++ != *p2++) {
return false;
}
}
return true;
}
struct FlashHead
{
uint8 label[18];
uint8 headSize;
uint8 fileSize;
uint32 pageSize;
uint32 majorVersion;
uint32 minorVersion;
};
struct FlashFile
{
uint32 pathOffset;
uint32 dataOffset;
uint32 size;
};
uintptr FindFlashImage(uintptr begin, uintptr limit)
{
// Round begin and limit to nearest valid addresses.
begin = (begin + 0xffff) & ~(uintptr)0xffff;
limit = (limit + 0xffff) & ~(uintptr)0xffff;
// walk through at 64KB boundaries looking for flash image.
for (; begin < limit ; begin += 0x10000) {
const FlashHead * head = (const FlashHead *)begin;
if (!memeq(head->label, (uint8*)"SingularityFlash!", sizeof(head->label))) {
continue;
}
if (head->headSize != sizeof(FlashHead)) {
continue;
}
if (head->fileSize != sizeof(FlashFile)) {
continue;
}
if (head->majorVersion != ~0u || head->minorVersion != ~0u) {
continue;
}
if (head->pageSize != 0x1000) {
continue;
}
// Header values all check out, now look at image content.
const FlashFile *file = (FlashFile*)(head + 1);
const FlashFile *fend = file + 8192;
for (; file < fend; file++) {
if ((file->dataOffset == 0xffffffff && file->size == 0xffffffff) ||
(file->dataOffset == 0 && file->size == 0)) {
continue;
}
else if (file->dataOffset == 0xffffffff && file->size == 0) {
return begin;
}
else if ((file->dataOffset & 0xfff) != 0) {
// file has unaligned offset.
printf("Unaligned offset: %x\n", file);
break;
}
}
}
return 0;
}
uintptr SizeFlashImage(uintptr begin, uint& count)
{
uintptr limit = 0;
count = 0;
const FlashHead * head = (const FlashHead *)begin;
const FlashFile *file = (FlashFile*)(head + 1);
// Assumes that there is always at least one valid file in the flash.
for (;; file++) {
if ((file->dataOffset == 0xffffffff && file->size == 0xffffffff) ||
(file->dataOffset == 0 && file->size == 0)) {
continue;
}
else if (file->dataOffset == 0xffffffff && file->size == 0) {
break;
}
if (limit < file->dataOffset + file->size) {
limit = file->dataOffset + file->size;
}
count++;
}
return ((limit + 0xfff) & ~0xfff);
}
void ProcessFlashImage(uintptr begin,
Struct_Microsoft_Singularity_Io_FileImage *files, uint count)
{
const FlashHead * head = (const FlashHead *)begin;
const FlashFile *file = (FlashFile*)(head + 1);
// Assumes that there is always at least one valid file in the flash.
for (uint item = 0;; file++) {
if ((file->dataOffset == 0xffffffff && file->size == 0xffffffff) ||
(file->dataOffset == 0 && file->size == 0)) {
continue;
}
else if (file->dataOffset == 0xffffffff && file->size == 0) {
break;
}
if (item < count) {
files[item].Address = begin + file->dataOffset;
files[item].Size = file->size;
item++;
}
}
}
//////////////////////////////////////////////////////////////////////////////
//
extern uintptr GetStack(void);
extern uintptr GetCode(void);
extern uint32 GetMidr(void);
extern uint32 GetPfr0(void);
extern uint32 GetPfr1(void);
extern uintptr GetVbar(void);
extern void SetVbar(uintptr);
extern void SetTpidrurw(uintptr);
uint MpStartupLock = 0;
int BootPhase1(void)
{
HalpClocksInitialize();
HalpGpioInitialize();
HalpI2CMasterInitialize();
BdInitDebugger(BdPortInit((uint32 *)OMAP_UART1_BASE, 115200));
printf("\f\n\rSingularity ARM Boot Loader [" __DATE__ " "__TIME__ "]\n\r");
InitializeDisplay((uint16 *)ON_OMAP3430_VIDEO_ADDR);
Draw("\fSingularity ARM Boot Loader\n[" __DATE__ " "__TIME__ "]\n\r");
uintptr base;
uintptr size = SizeOfPeImage((uintptr)ON_OMAP3430_LOADER_ADDR, base);
ASSERT(size <= ON_OMAP3430_LOADER_SIZE);
// Find out what kind of processor we're running on.
uint32 midr = GetMidr();
switch ((midr & 0xff000000) >> 24) {
case 0x41: printf("ARM Ltd "); break;
case 0x44: printf("DEC "); break;
case 0x4d: printf("Motorola "); break;
case 0x51: printf("Qualcomm "); break;
case 0x56: printf("Marvell "); break;
case 0x69: printf("Intel "); break;
default: printf("Implementor? ");
}
switch ((midr & 0xf0000) >> 16) {
case 0x01: printf("ARMv4 "); break;
case 0x02: printf("ARMv4T "); break;
case 0x03: printf("ARMv5 "); break;
case 0x04: printf("ARMv5T "); break;
case 0x05: printf("ARMv5TE "); break;
case 0x06: printf("ARMv5TEJ "); break;
case 0x07: printf("ARMv6 "); break;
case 0x0f: printf("ARMv7 "); break;
default: printf("Variant? "); break;
}
printf("%x.%x\n", (midr & 0xfff0) >> 4, midr & 0xf);
if ((midr & 0xf0000) == 0xf0000) {
// ARMv7, Used CPUID scheme.
printf("PFR: 0:%08x, 1:%08x\n", GetPfr0(), GetPfr1());
}
printf("\n");
//
// Get the BIOS info
//
g_bi = (Class_Microsoft_Singularity_Hal_Platform *)
alloc(sizeof(Class_Microsoft_Singularity_Hal_Platform));
g_bi->Size = sizeof(Class_Microsoft_Singularity_Hal_Platform);
//
// Save the debug information.
//
g_bi->DebugBasePort = OMAP_UART1_BASE;
//
// Set up Memory Map
//
Struct_Microsoft_Singularity_SMAPINFO *sm =
(Struct_Microsoft_Singularity_SMAPINFO *)
alloc(sizeof(Struct_Microsoft_Singularity_SMAPINFO) * 32);
g_bi->Smap32 = (uintptr)sm;
// Remember loader.
sm[0].type = Struct_Microsoft_Singularity_SMAPINFO_AddressTypeReserved;
sm[0].addr = ON_OMAP3430_LOADER_ADDR;
sm[0].size = SizeOfPeImage((uintptr)ON_OMAP3430_LOADER_ADDR, base);
// Remember other low reserved.
sm[1].type = Struct_Microsoft_Singularity_SMAPINFO_AddressTypeReserved;
sm[1].addr = ON_OMAP3430_RESERVE_ADDR + sm[0].size;
sm[1].size = ON_OMAP3430_RESERVE_SIZE - (sm[1].addr - ON_OMAP3430_RESERVE_ADDR);
// Remember RAM.
sm[2].type = Struct_Microsoft_Singularity_SMAPINFO_AddressTypeFree;
sm[2].addr = ON_OMAP3430_STACK_ADDR;
sm[2].size = ON_OMAP3430_MEMORY_SIZE - (ON_OMAP3430_STACK_ADDR - ON_OMAP3430_MEMORY_ADDR);
// Mark off I/O memory
sm[3].type = Struct_Microsoft_Singularity_SMAPINFO_AddressTypeUnusable;
sm[3].addr = 0;
sm[3].size = 0x80000000;
g_bi->SmapCount = 4;
//
// Register the boot memory that we use to allocated classes
// that will be converted into managed classes once the kernel
// initializes. This is so it can be properly reported to the
// GC.
//
// Record the entire boot memory range so that the kernel does
// not use it for working memory
//
g_bi->BootAllocatedMemory = 0;
g_bi->BootAllocatedMemorySize = 0x00400000; // Leave this as a guess of memory usage
g_bi->CpuRealCount = 1;
g_bi->CpuMaxCount = 1;
g_bi->BootCount = 0;
g_bi->LogRecordBuffer = ON_OMAP3430_LOGBUF_ADDR; // See Platform.cs
g_bi->LogRecordSize = ON_OMAP3430_LOGBUF_SIZE;
g_bi->LogTextBuffer = ON_OMAP3430_LOGTXT_ADDR;
g_bi->LogTextSize = ON_OMAP3430_LOGTXT_SIZE;
g_bi->KernelDllFirstPage=
g_bi->KernelDllBase = ON_OMAP3430_KERNEL_ADDR;
g_bi->PhysicalBase = 0x00010000;
//
// NOTE: The singldr should edit the SMAP to not include memory
// allocated to the kernel, its stacks, etc, similar to busying
// out the dump record.
//
// This would be a cleaner communication than the current
// combination of SMAP's, kernel base etc.
//
// There has been discussion of a modified version of SMAP that
// is communicated to the kernel that describes how memory has
// been used. SMAP describes general memory information, while
// the kernel needs to know how memory taken from the SMAP was
// used. This is important for the kernel to build its GC
// structures that track which pages contain GC objects.
//
g_bi->CpuMaxCount = 1;
g_ci = (Class_Microsoft_Singularity_Hal_Cpu *)
alloc(sizeof(Class_Microsoft_Singularity_Hal_Cpu) * 1);
g_bi->Cpus = (uintptr)g_ci;
g_ci->Size = sizeof(Class_Microsoft_Singularity_Hal_Cpu);
g_ci->Id = 0;
g_ci->KernelStackLimit = ON_OMAP3430_STACK_ADDR; // See also Platform.cs
g_ci->KernelStackBegin = ON_OMAP3430_STACK_ADDR + ON_OMAP3430_STACK_SIZE;
// Default to the Serial debugger
g_bi->DebuggerType = Class_Microsoft_Singularity_Hal_Platform_DEBUGGER_SERIAL;
g_bi->CommandLine32 = 0;
g_bi->CommandLineCount = 0;
printf("\n");
#if 0
//
// Drop SMAP entries above supported limit
//
for (int i = 0; i < g_bi->SmapCount; i++) {
if (sm[i].type != Struct_Microsoft_Singularity_SMAPINFO_AddressTypeFree) {
continue;
}
if ((sm[i].addr != 0ul) ||
(sm[i].addr >= Class_Microsoft_Singularity_Hal_Platform_MAX_VIRTUAL_ADDR)) {
sm[i] = sm[--g_bi->SmapCount];
}
else if (sm[i].addr + sm[i].size >= Class_Microsoft_Singularity_Hal_Platform_MAX_VIRTUAL_ADDR) {
sm[i].size = Class_Microsoft_Singularity_Hal_Platform_MAX_VIRTUAL_ADDR - sm[i].addr;
}
}
#endif
// Sort the system memory map.
SortSmap(g_bi);
//
// Make a reasonable guess at the size of physical memory.
//
uint32 memoryKB = 0;
for (int i = 0; i < g_bi->SmapCount; i++) {
if (sm[i].type == Struct_Microsoft_Singularity_SMAPINFO_AddressTypeFree) {
memoryKB += (uint32)(sm[i].size / 1024);
}
}
printf("Physical memory: %uMB\n", memoryKB / 1024);
CheckSmap(g_bi);
//
// Find the flash image.
//
uintptr flash = 0;
for (int i = 0; i < g_bi->SmapCount && flash == 0; i++) {
if (sm[i].type == Struct_Microsoft_Singularity_SMAPINFO_AddressTypeFree ||
sm[i].type == Struct_Microsoft_Singularity_SMAPINFO_AddressTypeReserved) {
flash = FindFlashImage((uintptr)sm[i].addr,
(uintptr)(sm[i].addr + sm[i].size));
}
}
if (flash == 0) {
printf("No valid flash image.\n");
Halt();
}
//
// Count the flash files and size the image.
//
uint nMaxImages = 0;
g_bi->DumpAddr32 = flash;
g_bi->DumpSize32 = SizeFlashImage(flash, nMaxImages);
printf("Flash: %08x..%08x.\n",
(uint32)g_bi->DumpAddr32,
(uint32)(g_bi->DumpAddr32 + g_bi->DumpSize32));
printf("Flash has %d files.\n", nMaxImages);
//
// Remember the flash files.
//
Struct_Microsoft_Singularity_Io_FileImage * files =
(Struct_Microsoft_Singularity_Io_FileImage *)
alloc(sizeof(Struct_Microsoft_Singularity_Io_FileImage) * nMaxImages);
ProcessFlashImage(flash, files, nMaxImages);
g_bi->FileImageTableBase32 = (uintptr)files;
g_bi->FileImageTableEntries = nMaxImages;
#if LIEABOUTSMAP
printf("\n");
printf("Editing the SMAP to protect the dump area...\n");
for (i = 0; i < g_bi->SmapCount; i++) {
// Does this region straddle the start of the dump area?
// if so, truncate it
if (sm[i].type == 1 &&
sm[i].addr < g_bi->DumpAddr32 &&
sm[i].addr + sm[i].size > g_bi->DumpAddr32) {
sm[i].size = g_bi->DumpAddr32 - sm[i].addr;
printf(" %08x..%08x %d (truncated)\n",
(uint32)(sm[i].addr),
(uint32)(sm[i].addr + sm[i].size),
sm[i].type);
}
if (sm[i].type == 1 &&
sm[i].addr >= g_bi->DumpAddr32) {
sm[i].type = 2; // Arbitrary non-free value
printf(" %08x..%08x %d (marked unavailable)\n",
(uint32)(sm[i].addr),
(uint32)(sm[i].addr + sm[i].size),
sm[i].type);
}
}
// Sort the system memory map.
SortSmap(g_bi);
#endif
uintptr kernelBase;
g_bi->KernelDllSize = SizeOfPeImage(files[0].Address, kernelBase);
printf("Kernel: %08x..%08x\n",
g_bi->KernelDllBase,
g_bi->KernelDllBase + g_bi->KernelDllSize);
uintptr kernelEntry = ExpandPeImage(g_bi->KernelDllBase, files[0].Address);
printf("Kernel Entry: %08x\n", kernelEntry);
//
g_bi->MpCpuCount = 0;
g_bi->MpStartupLock32 = (uintptr)&MpStartupLock;
//printf("MpStartupLock32* %x, value %x\n", g_bi->MpStartupLock32, MpStartupLock);
//
// Set the offset to the context pointers, which are the
// first two pointer words allocated in the page.
//
//
// Allocate pages for commonly referenced data
//
uint8 * cpuRecord = (uint8 *)allocpages(2);
//
// Set the offset to the context pointers, which are the
// first two pointer words allocated in the page.
//
g_bi->CpuRecordPointerOffset = 0 * sizeof(uintptr);
g_bi->ThreadRecordPointerOffset = 1 * sizeof(uintptr);
//
// Set the DS relative address to the ProcessorContext
//
// Set our base for storing our actual X86.ProcessorContext
//
SetTpidrurw((uintptr)cpuRecord);
// Align CpuRecord to 16-bytes after CpuRecord & ThreadRecord pointers.
g_ci->CpuRecordPage = (uint32)cpuRecord + 16;
g_bi->MiniDumpBase = (uintptr)g_bi->DumpAddr32;
g_bi->MiniDumpLimit = g_bi->MiniDumpBase + ((g_bi->DumpSize32 + 0xffff) & 0xffff0000);
//
// Move to next phase
//
Class_Microsoft_Singularity_Hal_Platform *bi = g_bi;
Class_Microsoft_Singularity_Hal_Cpu *ci = g_ci;
void (* pfHal)(void *, void *) = (void (*)(void *, void *))kernelEntry;
g_bi->IsaCsns = (uint32)videoBuffer;
g_bi->IsaReadPort = videoCursor;
g_bi->KillAction = 0xffff;
pfHal((void*)g_bi, (void*)g_ci);
videoCursor = g_bi->IsaReadPort;
printf("\n");
printf("Kernel exited: %04x\n", g_bi->KillAction);
g_bi->BootCount++;
Halt();
for(;;);
}
extern "C" unsigned __int64 __rt_udiv64by64( unsigned __int64 x, unsigned __int64 y)
{
unsigned __int64 q = 0;
unsigned __int64 mask = 1;
if (y == 0) {
return (unsigned __int64)-1;
}
while (y <= x) {
if (y & 0x8000000000000000) {
x -= y;
q += mask;
break;
}
mask <<= 1;
y <<= 1;
}
while (mask !=0) {
if (y <= x) {
q += mask;
x -= y;
}
y >>= 1;
mask >>= 1;
}
return q;
}