include $(ACESSDIR)/BuildConf/armv7/default.mk
-#MODULES += Display/Tegra2
+MODULES += Display/Tegra2
ASFLAGS += -D ARCHDIR_IS_$(ARCHDIR)=1 -D PLATFORM_is_$(PLATFORM)=1
CPPFLAGS += -I./include -I./arch/$(ARCHDIR)/include -D_MODULE_NAME_=\"Kernel\"
-CPPFLAGS += -D ARCH=$(ARCH) -D ARCHDIR=$(ARCHDIR) -D ARCHDIR_IS_$(ARCHDIR)=1 -D PLATFORM_is_$(PLATFORM)=1
+CPPFLAGS += -D ARCH=$(ARCH) -D ARCHDIR=$(ARCHDIR) -D PLATFORM=\"$(PLATFORM)\" -D ARCHDIR_IS_$(ARCHDIR)=1 -D PLATFORM_is_$(PLATFORM)=1
CPPFLAGS += -D KERNEL_VERSION=$(KERNEL_VERSION)
CFLAGS += -Wall -fno-stack-protector -Wstrict-prototypes -g
CFLAGS += -Wshadow -Wpointer-arith -Wcast-align -Wwrite-strings -Wmissing-prototypes -Wmissing-declarations -Wredundant-decls -Wnested-externs -Winline -Wuninitialized
; desctab.asm
[BITS 32]
-%if USE_MP
-MAX_CPUS equ 8
-%else
-MAX_CPUS equ 1
-%endif
-GDT_SIZE equ (1+2*2+1+MAX_CPUS)*8
[section .data]
-; GDT
-[global gGDT]
-gGDT:
- ; PL0 - Kernel
- ; PL3 - User
- dd 0x00000000, 0x00000000 ; 00 NULL Entry
- dd 0x0000FFFF, 0x00CF9A00 ; 08 PL0 Code
- dd 0x0000FFFF, 0x00CF9200 ; 10 PL0 Data
- dd 0x0000FFFF, 0x00CFFA00 ; 18 PL3 Code
- dd 0x0000FFFF, 0x00CFF200 ; 20 PL3 Data
- dd 26*4-1, 0x00408900 ; 28 Double Fault TSS
- times MAX_CPUS dd 26*4-1, 0x00408900 ; 30+ TSSes
-[global gGDTPtr]
-gGDTPtr:
- dw GDT_SIZE-1
- dd gGDT
; IDT
ALIGN 8
[global gIDT]
[global Desctab_Install]
Desctab_Install:
- ; Set GDT
- lgdt [gGDTPtr]
- mov ax, 0x10 ; PL0 Data
- mov ss, ax
- mov ds, ax
- mov es, ax
- mov gs, ax
- mov fs, ax
- jmp 0x08:.pl0code
-.pl0code:
-
; Set up IDT
; Helper Macros
; - Set an IDT entry to an ISR
for( i = 0; i < giNumCPUs; i ++ )
{
if(i == GetCPUNum()) continue ;
- FB[i] = BGC|'A'+i;
+ FB[i] = BGC|('A'+i);
MP_SendIPIVector(i, 0xED);
}
#endif
extern int GetCPUNum(void);
// === PROTOTYPES ==
+Uint64 __divmod64(Uint64 Num, Uint64 Den, Uint64 *Rem);
Uint64 __udivdi3(Uint64 Num, Uint64 Den);
Uint64 __umoddi3(Uint64 Num, Uint64 Den);
return Dest;
}
+#include "../helpers.h"
+
+DEF_DIVMOD(64);
+
Uint64 DivMod64U(Uint64 Num, Uint64 Div, Uint64 *Rem)
{
- Uint64 ret;
if( Div < 0x100000000ULL && Num < 0xFFFFFFFF * Div ) {
Uint32 rem, ret_32;
__asm__ __volatile__(
return ret_32;
}
- ret = __udivdi3(Num, Div);
- if(Rem) *Rem = __umoddi3(Num, Div);
- return ret;
+ return __divmod64(Num, Div, Rem);
}
/**
*/
Uint64 __udivdi3(Uint64 Num, Uint64 Den)
{
- Uint64 P[2];
- Uint64 q = 0;
- int i;
-
- if(Den == 0) __asm__ __volatile__ ("int $0x0");
+ if(Den == 0) {
+ __asm__ __volatile__ ("int $0x0");
+ return -1;
+ }
// Common speedups
if(Num <= 0xFFFFFFFF && Den <= 0xFFFFFFFF)
return (Uint32)Num / (Uint32)Den;
if(Num < Den) return 0;
if(Num < Den*2) return 1;
if(Num == Den*2) return 2;
-
- #if 1
- i = 0; // Shut up
- P[0] = Num;
- P[1] = Den;
- __asm__ __volatile__ (
- "fildq %2\n\t" // Num
- "fildq %1\n\t" // Den
- "fdivp\n\t"
- "fistpq %0"
- : "=m" (q)
- : "m" (P[0]), "m" (P[1])
- );
-
- //Log("%llx / %llx = %llx\n", Num, Den, q);
- #else
- // Restoring division, from wikipedia
- // http://en.wikipedia.org/wiki/Division_(digital)
- P[0] = Num; P[1] = 0;
- for( i = 64; i--; )
- {
- // P <<= 1;
- P[1] = (P[1] << 1) | (P[0] >> 63);
- P[0] = P[0] << 1;
-
- // P -= Den << 64
- P[1] -= Den;
-
- // P >= 0
- if( !(P[1] & (1ULL<<63)) ) {
- q |= (Uint64)1 << (63-i);
- }
- else {
- //q |= 0 << (63-i);
- P[1] += Den;
- }
- }
- #endif
-
- return q;
+
+ return __divmod64(Num, Den, NULL);
}
/**
*/
Uint64 __umoddi3(Uint64 Num, Uint64 Den)
{
- if(Den == 0) __asm__ __volatile__ ("int $0x0"); // Call Div by Zero Error
+ Uint64 ret = 0;
+ if(Den == 0) {
+ __asm__ __volatile__ ("int $0x0"); // Call Div by Zero Error
+ return -1;
+ }
if(Den == 1) return 0; // Speed Hacks
if(Den == 2) return Num & 1; // Speed Hacks
if(Den == 4) return Num & 3; // Speed Hacks
if(Num >> 32 == 0 && Den >> 32 == 0)
return (Uint32)Num % (Uint32)Den;
- return Num - __udivdi3(Num, Den) * Den;
+ __divmod64(Num, Den, &ret);
+ return ret;
}
tMBoot_Module *mods;
tMBoot_Info *mbInfo;
- LogF("Acess2 x86 v"EXPAND_STR(KERNEL_VERSION)"\n");
+ LogF("Acess2 x86-"PLATFORM" v"EXPAND_STR(KERNEL_VERSION)"\n");
LogF(" Build %i, Git Hash %s\n", BUILD_NUM, gsGitHash);
Log("MbMagic = %08x, MbInfoPtr = %p", MbMagic, MbInfoPtr);
MM_InstallVirtual(); // Clean up virtual address space
Heap_Install(); // Create initial heap
- //Log_Log("Arch", "Starting Multitasking...");
// Start Multitasking
Threads_Init();
);
}
- Log("Code at %p accessed %p", Regs->eip, Addr);
+ Log("CPU %i - Code at %p accessed %p", GetCPUNum(), Regs->eip, Addr);
// Print Stack Backtrace
Error_Backtrace(Regs->eip, Regs->ebp);
-
+
+ #if 0
Log("gaPageDir[0x%x] = 0x%x", Addr>>22, gaPageDir[Addr>>22]);
if( gaPageDir[Addr>>22] & PF_PRESENT )
Log("gaPageTable[0x%x] = 0x%x", Addr>>12, gaPageTable[Addr>>12]);
-
+ #endif
//MM_DumpTables(0, -1);
// Register Dump
; Old IP
mov eax, [esp+0x20+16]
+ test eax, eax
+ jz .nosave
mov DWORD [eax], .restore
; Old SP
mov eax, [esp+0x20+8]
mov [eax], esp
+.nosave:
mov ecx, [esp+0x20+12] ; New IP
mov eax, [esp+0x20+20] ; New CR3
mov esp, [esp+0x20+ 4] ; New SP
mov ebx, [esp+4]
int 0xAC
-; vim: ft=nasm, ts=8
+; vim: ft=nasm ts=8
#include <hal_proc.h>
// === FLAGS ===
-#define DEBUG_TRACE_SWITCH 1
+#define DEBUG_TRACE_SWITCH 0
#define DEBUG_DISABLE_DOUBLEFAULT 1
-#define DEBUG_VERY_SLOW_SWITCH 0
+#define DEBUG_VERY_SLOW_PERIOD 0
// === CONSTANTS ===
// Base is 1193182
{
int i;
tMPTable_Ent *ents;
+ #if DUMP_MP_TABLE
Log("gMPFloatPtr = %p", gMPFloatPtr);
Log("*gMPFloatPtr = {");
Log("\t.Sig = 0x%08x", gMPFloatPtr->Sig);
gMPFloatPtr->Features[4]
);
Log("}");
-
+ #endif
+
mptable = (void*)( KERNEL_BASE|gMPFloatPtr->MPConfig );
+ #if DUMP_MP_TABLE
Log("mptable = %p", mptable);
Log("*mptable = {");
Log("\t.Sig = 0x%08x", mptable->Sig);
Log("\t.ExtendedTableLen = 0x%04x", mptable->ExtendedTableLen);
Log("\t.ExtendedTableChecksum = 0x%02x", mptable->ExtendedTableChecksum);
Log("}");
+ #endif
gpMP_LocalAPIC = (void*)MM_MapHWPages(mptable->LocalAPICMemMap, 1);
{
case 0: // Processor
entSize = 20;
+ #if DUMP_MP_TABLE
Log("%i: Processor", i);
Log("\t.APICID = %i", ents->Proc.APICID);
Log("\t.APICVer = 0x%02x", ents->Proc.APICVer);
Log("\t.CPUFlags = 0x%02x", ents->Proc.CPUFlags);
Log("\t.CPUSignature = 0x%08x", ents->Proc.CPUSignature);
Log("\t.FeatureFlags = 0x%08x", ents->Proc.FeatureFlags);
-
+ #endif
if( !(ents->Proc.CPUFlags & 1) ) {
Log("DISABLED");
break;
- #if DUMP_MP_TABLES
+ #if DUMP_MP_TABLE >= 2
case 1: // Bus
entSize = 8;
Log("%i: Bus", i);
Proc_DisableSSE();
}
- SwitchTasks(
- nextthread->SavedState.ESP, &curthread->SavedState.ESP,
- nextthread->SavedState.EIP, &curthread->SavedState.EIP,
- nextthread->MemState.CR3
- );
+ if( curthread )
+ {
+ SwitchTasks(
+ nextthread->SavedState.ESP, &curthread->SavedState.ESP,
+ nextthread->SavedState.EIP, &curthread->SavedState.EIP,
+ nextthread->MemState.CR3
+ );
+ }
+ else
+ {
+ SwitchTasks(
+ nextthread->SavedState.ESP, 0,
+ nextthread->SavedState.EIP, 0,
+ nextthread->MemState.CR3
+ );
+ }
return ;
}
; Start Paging
mov ecx, gaInitPageDir - KERNEL_BASE
mov cr3, ecx
-
mov ecx, cr0
or ecx, 0x80010000 ; PG and WP
mov cr0, ecx
mov WORD [0xB8002], 0x0763 ; 'c'
- mov WORD [0xB8004], 0x0765 ; 'e'
- lea ecx, [.higherHalf]
- jmp ecx
-.higherHalf:
+ ; Set GDT
+ lgdt [gGDTPtr]
+ mov cx, 0x10 ; PL0 Data
+ mov ss, cx
+ mov ds, cx
+ mov es, cx
+ mov gs, cx
+ mov fs, cx
+ mov WORD [0xB8004], 0x0765 ; 'e'
+ jmp 0x08:.higher_half
+.higher_half:
mov WORD [0xB8006], 0x0773 ; 's'
mov WORD [0xB8008], 0x0773 ; 's'
; Multiprocessing AP Startup Code (Must be within 0 - 0x10FFF0)
;
%if USE_MP
-[extern gGDT]
-[extern gGDTPtr]
[extern gIDTPtr]
[extern gpMP_LocalAPIC]
[extern giMP_TimerCount]
[extern gaCPUs]
[extern giNumInitingCPUs]
[extern MM_NewKStack]
+[extern Proc_InitialiseSSE]
lGDTPtr: ; Local GDT Pointer
dw 3*8-1
mov DWORD [ebp+0x360], 0x000100D2 ; ##Enable LINT1 on IVT#0xD2
mov DWORD [ebp+0x370], 0x000100E1 ; ##Enable Error on IVT#0xE1
mov DWORD [ebp+0x0B0], 0 ; Send an EOI (just in case)
+
+ ; Initialise SSE support
+ call Proc_InitialiseSSE
; CPU is now marked as initialised
pop ebp
ret
+[section .data]
+; GDT
+GDT_SIZE equ (1+2*2+1+MAX_CPUS)*8
+[global gGDT]
+gGDT:
+ ; PL0 - Kernel
+ ; PL3 - User
+ dd 0x00000000, 0x00000000 ; 00 NULL Entry
+ dd 0x0000FFFF, 0x00CF9A00 ; 08 PL0 Code
+ dd 0x0000FFFF, 0x00CF9200 ; 10 PL0 Data
+ dd 0x0000FFFF, 0x00CFFA00 ; 18 PL3 Code
+ dd 0x0000FFFF, 0x00CFF200 ; 20 PL3 Data
+ dd 26*4-1, 0x00408900 ; 28 Double Fault TSS
+ times MAX_CPUS dd 26*4-1, 0x00408900 ; 30+ TSSes
+[global gGDTPtr]
+gGDTPtr:
+ dw GDT_SIZE-1
+ dd gGDT
+
[section .initpd]
[global gaInitPageDir]
[global gaInitPageTable]
int VM8086_Install(char **Arguments)
{
tPID pid;
+
+ Semaphore_Init(&gVM8086_TasksToDo, 0, 10, "VM8086", "TasksToDo");
// Lock to avoid race conditions
Mutex_Acquire( &glVM8086_Process );
// Create BIOS Call process
pid = Proc_Clone(CLONE_VM);
+ Log_Debug("VM8086", "pid = %i", pid);
if(pid == -1)
{
Log_Error("VM8086", "Unable to clone kernel into VM8086 worker");
Uint * volatile stacksetup; // Initialising Stack
Uint16 * volatile rmstack; // Real Mode Stack
int i;
-
+
+ Log_Debug("VM8086", "Initialising worker");
+
// Set Image Name
Threads_SetName("VM8086");
-// Log_Debug("VM8086", "Mapping memory");
-
// Map ROM Area
for(i=0xA0;i<0x100;i++) {
MM_Map( i * 0x1000, i * 0x1000 );
}
-// Log_Debug("VM8086", "ROM area mapped");
MM_Map( 0, 0 ); // IVT / BDA
// Map (but allow allocation) of 0x1000 - 0x9F000
// - So much hack, it isn't funny
gVM8086_WorkerPID = 0;
Threads_Exit(0, 1);
}
-// Log_Debug("VM8086", "Mapped low memory");
*(Uint8*)(0x100000) = VM8086_OP_IRET;
*(Uint8*)(0x100001) = 0x07; // POP ES
}
gVM8086_WorkerPID = pid;
-// Log_Log("VM8086", "gVM8086_WorkerPID = %i", pid);
- while( gpVM8086_State != NULL )
- Threads_Yield(); // Yield to allow the child to initialise
+
+ // It's released when the GPF fires
+ Mutex_Acquire( &glVM8086_Process );
+ Mutex_Release( &glVM8086_Process );
// Worker killed itself
if( gVM8086_WorkerPID != pid ) {
{
Uint8 opcode;
- //Log_Log("VM8086", "GPF - %04x:%04x", Regs->cs, Regs->eip);
+// Log_Log("VM8086", "GPF - %04x:%04x", Regs->cs, Regs->eip);
if(Regs->eip == VM8086_MAGIC_IP && Regs->cs == VM8086_MAGIC_CS
&& Threads_GetPID() == gVM8086_WorkerPID)
gpVM8086_State = NULL;
Mutex_Release( &glVM8086_Process ); // Release lock obtained in VM8086_Install
}
- //Log_Log("VM8086", "gpVM8086_State = %p, gVM8086_CallingThread = %i",
- // gpVM8086_State, gVM8086_CallingThread);
+// Log_Log("VM8086", "gpVM8086_State = %p, gVM8086_CallingThread = %i",
+// gpVM8086_State, gVM8086_CallingThread);
if( gpVM8086_State ) {
gpVM8086_State->AX = Regs->eax; gpVM8086_State->CX = Regs->ecx;
gpVM8086_State->DX = Regs->edx; gpVM8086_State->BX = Regs->ebx;
Semaphore_Wait(&gVM8086_TasksToDo, 1);
//Log_Log("VM8086", "We have a task (%p)", gpVM8086_State);
- Regs->esp -= 2; *(Uint16*volatile)( (Regs->ss<<4) + (Regs->esp&0xFFFF) ) = VM8086_MAGIC_CS;
- Regs->esp -= 2; *(Uint16*volatile)( (Regs->ss<<4) + (Regs->esp&0xFFFF) ) = VM8086_MAGIC_IP;
- Regs->esp -= 2; *(Uint16*volatile)( (Regs->ss<<4) + (Regs->esp&0xFFFF) ) = gpVM8086_State->CS;
- Regs->esp -= 2; *(Uint16*volatile)( (Regs->ss<<4) + (Regs->esp&0xFFFF) ) = gpVM8086_State->IP;
- Regs->esp -= 2; *(Uint16*volatile)( (Regs->ss<<4) + (Regs->esp&0xFFFF) ) = gpVM8086_State->DS;
- Regs->esp -= 2; *(Uint16*volatile)( (Regs->ss<<4) + (Regs->esp&0xFFFF) ) = gpVM8086_State->ES;
+ Regs->esp -= 2; *(Uint16*)( (Regs->ss<<4) + (Regs->esp&0xFFFF) ) = VM8086_MAGIC_CS;
+ Regs->esp -= 2; *(Uint16*)( (Regs->ss<<4) + (Regs->esp&0xFFFF) ) = VM8086_MAGIC_IP;
+ Regs->esp -= 2; *(Uint16*)( (Regs->ss<<4) + (Regs->esp&0xFFFF) ) = gpVM8086_State->CS;
+ Regs->esp -= 2; *(Uint16*)( (Regs->ss<<4) + (Regs->esp&0xFFFF) ) = gpVM8086_State->IP;
+ Regs->esp -= 2; *(Uint16*)( (Regs->ss<<4) + (Regs->esp&0xFFFF) ) = gpVM8086_State->DS;
+ Regs->esp -= 2; *(Uint16*)( (Regs->ss<<4) + (Regs->esp&0xFFFF) ) = gpVM8086_State->ES;
// Set Registers
Regs->eip = 0x11; Regs->cs = 0xFFFF;
#endif
break;
case VM8086_OP_POPF: //POPF
- Regs->eflags &= 0xFFFF0002;
- Regs->eflags |= *(Uint16*)( Regs->ss*16 + (Regs->esp&0xFFFF) ) & 0xFFFD; // Changing IF is not allowed
+ // Changing IF is not allowed
+ Regs->eflags &= 0xFFFF0202;
+ Regs->eflags |= *(Uint16*)( Regs->ss*16 + (Regs->esp&0xFFFF) );
Regs->esp += 2;
#if TRACE_EMU
Log_Debug("VM8086", "Emulated POPF");
id = *(Uint8*)( Regs->cs*16 +(Regs->eip&0xFFFF));
Regs->eip ++;
- Regs->esp -= 2; *(Uint16*volatile)( Regs->ss*16 + (Regs->esp&0xFFFF) ) = Regs->cs;
- Regs->esp -= 2; *(Uint16*volatile)( Regs->ss*16 + (Regs->esp&0xFFFF) ) = Regs->eip;
+ Regs->esp -= 2; *(Uint16*)( Regs->ss*16 + (Regs->esp&0xFFFF) ) = Regs->cs;
+ Regs->esp -= 2; *(Uint16*)( Regs->ss*16 + (Regs->esp&0xFFFF) ) = Regs->eip;
Regs->cs = *(Uint16*)(4*id + 2);
Regs->eip = *(Uint16*)(4*id);
#define DEBUG_MAX_LINE_LEN 256
-#define LOCK_DEBUG_OUTPUT 0
+#define LOCK_DEBUG_OUTPUT 1
#define TRACE_TO_KTERM 0
// Scan and get distribution
#if 1
+ if(nBlocks > 0)
{
struct {
Uint Size;
size_t pos = 0;
// Flags
int bPadLeft = 0;
+
+ auto void _putch(char ch);
- inline void _putch(char ch)
+ void _putch(char ch)
{
if(pos < __maxlen)
{
--- /dev/null
+#
+#
+
+OBJ = main.o
+NAME = Tegra2
+
+-include ../Makefile.tpl
--- /dev/null
+/**\r
+ * main.c\r
+ * - Driver core\r
+ */\r
+#define DEBUG 0\r
+#define VERSION ((0<<8)|10)\r
+#include <acess.h>\r
+#include <errno.h>\r
+#include <modules.h>\r
+#include <vfs.h>\r
+#include <fs_devfs.h>\r
+#include <drv_pci.h>\r
+#include <api_drv_video.h>\r
+#include <lib/keyvalue.h>\r
+#include <options.h> // ARM Arch\r
+#include "tegra2.h"\r
+\r
+#define ABS(a) ((a)>0?(a):-(a))\r
+\r
+// === PROTOTYPES ===\r
+// Driver\r
+ int Tegra2Vid_Install(char **Arguments);\r
+void Tegra2Vid_Uninstall();\r
+// Internal\r
+// Filesystem\r
+Uint64 Tegra2Vid_Read(tVFS_Node *node, Uint64 off, Uint64 len, void *buffer);\r
+Uint64 Tegra2Vid_Write(tVFS_Node *node, Uint64 off, Uint64 len, void *buffer);\r
+ int Tegra2Vid_IOCtl(tVFS_Node *node, int id, void *data);\r
+// -- Internals\r
+ int Tegra2Vid_int_SetMode(int Mode);\r
+\r
+// === GLOBALS ===\r
+MODULE_DEFINE(0, VERSION, Video_Tegra2, Tegra2Vid_Install, NULL, NULL);\r
+tDevFS_Driver gTegra2Vid_DriverStruct = {\r
+ NULL, "PL110",\r
+ {\r
+ .Read = Tegra2Vid_Read,\r
+ .Write = Tegra2Vid_Write,\r
+ .IOCtl = Tegra2Vid_IOCtl\r
+ }\r
+};\r
+// -- Options\r
+tPAddr gTegra2Vid_PhysBase = TEGRA2VID_BASE;\r
+ int gbTegra2Vid_IsVersatile = 1;\r
+// -- KeyVal parse rules\r
+const tKeyVal_ParseRules gTegra2Vid_KeyValueParser = {\r
+ NULL,\r
+ {\r
+ {"Base", "P", &gTegra2Vid_PhysBase},\r
+ {NULL, NULL, NULL}\r
+ }\r
+};\r
+// -- Driver state\r
+ int giTegra2Vid_CurrentMode = 0;\r
+ int giTegra2Vid_BufferMode;\r
+size_t giTegra2Vid_FramebufferSize;\r
+Uint8 *gpTegra2Vid_IOMem;\r
+tPAddr gTegra2Vid_FramebufferPhys;\r
+void *gpTegra2Vid_Framebuffer;\r
+// -- Misc\r
+tDrvUtil_Video_BufInfo gTegra2Vid_DrvUtil_BufInfo;\r
+tVideo_IOCtl_Pos gTegra2Vid_CursorPos;\r
+\r
+// === CODE ===\r
+/**\r
+ */\r
+int Tegra2Vid_Install(char **Arguments)\r
+{\r
+// KeyVal_Parse(&gTegra2Vid_KeyValueParser, Arguments);\r
+ \r
+ gpTegra2Vid_IOMem = (void*)MM_MapHWPages(gTegra2Vid_PhysBase, 256/4);\r
+\r
+ Tegra2Vid_int_SetMode(4);\r
+\r
+ DevFS_AddDevice( &gTegra2Vid_DriverStruct );\r
+\r
+ return 0;\r
+}\r
+\r
+/**\r
+ * \brief Clean up resources for driver unloading\r
+ */\r
+void Tegra2Vid_Uninstall()\r
+{\r
+}\r
+\r
+/**\r
+ * \brief Read from the framebuffer\r
+ */\r
+Uint64 Tegra2Vid_Read(tVFS_Node *node, Uint64 off, Uint64 len, void *buffer)\r
+{\r
+ return 0;\r
+}\r
+\r
+/**\r
+ * \brief Write to the framebuffer\r
+ */\r
+Uint64 Tegra2Vid_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)\r
+{\r
+ gTegra2Vid_DrvUtil_BufInfo.BufferFormat = giTegra2Vid_BufferMode;\r
+ return DrvUtil_Video_WriteLFB(&gTegra2Vid_DrvUtil_BufInfo, Offset, Length, Buffer);\r
+}\r
+\r
+const char *csaTegra2Vid_IOCtls[] = {DRV_IOCTLNAMES, DRV_VIDEO_IOCTLNAMES, NULL};\r
+\r
+/**\r
+ * \brief Handle messages to the device\r
+ */\r
+int Tegra2Vid_IOCtl(tVFS_Node *Node, int ID, void *Data)\r
+{\r
+ int ret = -2;\r
+ ENTER("pNode iID pData", Node, ID, Data);\r
+ \r
+ switch(ID)\r
+ {\r
+ BASE_IOCTLS(DRV_TYPE_VIDEO, "PL110", VERSION, csaTegra2Vid_IOCtls);\r
+\r
+ case VIDEO_IOCTL_SETBUFFORMAT:\r
+ DrvUtil_Video_RemoveCursor( &gTegra2Vid_DrvUtil_BufInfo );\r
+ ret = giTegra2Vid_BufferMode;\r
+ if(Data) giTegra2Vid_BufferMode = *(int*)Data;\r
+ if(gTegra2Vid_DrvUtil_BufInfo.BufferFormat == VIDEO_BUFFMT_TEXT)\r
+ DrvUtil_Video_SetCursor( &gTegra2Vid_DrvUtil_BufInfo, &gDrvUtil_TextModeCursor );\r
+ break;\r
+ \r
+ case VIDEO_IOCTL_GETSETMODE:\r
+ if(Data)\r
+ {\r
+ int newMode;\r
+ \r
+ if( !CheckMem(Data, sizeof(int)) )\r
+ LEAVE_RET('i', -1);\r
+ \r
+ newMode = *(int*)Data;\r
+ \r
+ if(newMode < 0 || newMode >= ciTegra2Vid_ModeCount)\r
+ LEAVE_RET('i', -1);\r
+\r
+ if(newMode != giTegra2Vid_CurrentMode)\r
+ {\r
+ giTegra2Vid_CurrentMode = newMode;\r
+ Tegra2Vid_int_SetMode( newMode );\r
+ }\r
+ }\r
+ ret = giTegra2Vid_CurrentMode;\r
+ break;\r
+ \r
+ case VIDEO_IOCTL_FINDMODE:\r
+ {\r
+ tVideo_IOCtl_Mode *mode = Data;\r
+ int closest, closestArea, reqArea = 0;\r
+ if(!Data || !CheckMem(Data, sizeof(tVideo_IOCtl_Mode)))\r
+ LEAVE_RET('i', -1);\r
+ if( mode->bpp != 32 )\r
+ LEAVE_RET('i', 0);\r
+ if( mode->flags != 0 )\r
+ LEAVE_RET('i', 0);\r
+\r
+ ret = 0;\r
+\r
+ for( int i = 0; i < ciTegra2Vid_ModeCount; i ++ )\r
+ {\r
+ int area;\r
+ if(mode->width == caTegra2Vid_Modes[i].W && mode->height == caTegra2Vid_Modes[i].H) {\r
+ mode->id = i;\r
+ ret = 1;\r
+ break;\r
+ }\r
+ \r
+ area = caTegra2Vid_Modes[i].W * caTegra2Vid_Modes[i].H;\r
+ if(!reqArea) {\r
+ reqArea = mode->width * mode->height;\r
+ closest = i;\r
+ closestArea = area;\r
+ }\r
+ else if( ABS(area - reqArea) < ABS(closestArea - reqArea) ) {\r
+ closest = i;\r
+ closestArea = area;\r
+ }\r
+ }\r
+ \r
+ if( ret == 0 )\r
+ {\r
+ mode->id = closest;\r
+ ret = 1;\r
+ }\r
+ mode->width = caTegra2Vid_Modes[mode->id].W;\r
+ mode->height = caTegra2Vid_Modes[mode->id].H;\r
+ break;\r
+ }\r
+ \r
+ case VIDEO_IOCTL_MODEINFO:\r
+ {\r
+ tVideo_IOCtl_Mode *mode = Data;\r
+ if(!Data || !CheckMem(Data, sizeof(tVideo_IOCtl_Mode)))\r
+ LEAVE_RET('i', -1);\r
+ if(mode->id < 0 || mode->id >= ciTegra2Vid_ModeCount)\r
+ LEAVE_RET('i', 0);\r
+ \r
+\r
+ mode->bpp = 32;\r
+ mode->flags = 0;\r
+ mode->width = caTegra2Vid_Modes[mode->id].W;\r
+ mode->height = caTegra2Vid_Modes[mode->id].H;\r
+\r
+ ret = 1;\r
+ break;\r
+ }\r
+ \r
+ case VIDEO_IOCTL_SETCURSOR:\r
+ if( !Data || !CheckMem(Data, sizeof(tVideo_IOCtl_Pos)) )\r
+ LEAVE_RET('i', -1);\r
+\r
+ DrvUtil_Video_RemoveCursor( &gTegra2Vid_DrvUtil_BufInfo );\r
+ \r
+ gTegra2Vid_CursorPos = *(tVideo_IOCtl_Pos*)Data;\r
+ if(gTegra2Vid_DrvUtil_BufInfo.BufferFormat == VIDEO_BUFFMT_TEXT)\r
+ DrvUtil_Video_DrawCursor(\r
+ &gTegra2Vid_DrvUtil_BufInfo,\r
+ gTegra2Vid_CursorPos.x*giVT_CharWidth,\r
+ gTegra2Vid_CursorPos.y*giVT_CharHeight\r
+ );\r
+ else\r
+ DrvUtil_Video_DrawCursor(\r
+ &gTegra2Vid_DrvUtil_BufInfo,\r
+ gTegra2Vid_CursorPos.x,\r
+ gTegra2Vid_CursorPos.y\r
+ );\r
+ break;\r
+ \r
+ default:\r
+ LEAVE('i', -2);\r
+ return -2;\r
+ }\r
+ \r
+ LEAVE('i', ret);\r
+ return ret;\r
+}\r
+\r
+//\r
+//\r
+//\r
+\r
+int Tegra2Vid_int_SetMode(int Mode)\r
+{\r
+ const struct sTegra2_Disp_Mode *mode = &caTegra2Vid_Modes[Mode];\r
+ int w = mode->W, h = mode->H; // Horizontal/Vertical Active\r
+ *(Uint32*)(gpTegra2Vid_IOMem + DC_DISP_FRONT_PORCH_0) = (mode->VFP << 16) | mode->HFP; \r
+ *(Uint32*)(gpTegra2Vid_IOMem + DC_DISP_SYNC_WIDTH_0) = (mode->HS << 16) | mode->HS;\r
+ *(Uint32*)(gpTegra2Vid_IOMem + DC_DISP_BACK_PORCH_0) = (mode->VBP << 16) | mode->HBP;\r
+ *(Uint32*)(gpTegra2Vid_IOMem + DC_DISP_DISP_ACTIVE_0) = (mode->H << 16) | mode->W;\r
+\r
+ *(Uint32*)(gpTegra2Vid_IOMem + DC_WIN_A_POSITION_0) = 0;\r
+ *(Uint32*)(gpTegra2Vid_IOMem + DC_WIN_A_SIZE_0) = (mode->H << 16) | mode->W;\r
+ *(Uint8*)(gpTegra2Vid_IOMem + DC_WIN_A_COLOR_DEPTH_0) = 12; // Could be 13 (BGR/RGB)\r
+ *(Uint32*)(gpTegra2Vid_IOMem + DC_WIN_A_PRESCALED_SIZE_0) = (mode->H << 16) | mode->W;\r
+\r
+ if( !gpTegra2Vid_Framebuffer || w*h*4 != giTegra2Vid_FramebufferSize )\r
+ {\r
+ if( gpTegra2Vid_Framebuffer )\r
+ {\r
+ // TODO: Free framebuffer for reallocation\r
+ }\r
+\r
+ giTegra2Vid_FramebufferSize = w*h*4; \r
+\r
+ gpTegra2Vid_Framebuffer = (void*)MM_AllocDMA(\r
+ (giTegra2Vid_FramebufferSize + PAGE_SIZE-1) / PAGE_SIZE,\r
+ 32,\r
+ &gTegra2Vid_FramebufferPhys\r
+ );\r
+ // TODO: Catch allocation failures\r
+ \r
+ // Tell hardware\r
+ *(Uint32*)(gpTegra2Vid_IOMem + DC_WINBUF_A_START_ADDR_0) = gTegra2Vid_FramebufferPhys;\r
+ *(Uint32*)(gpTegra2Vid_IOMem + DC_WINBUF_A_ADDR_V_OFFSET_0) = 0; // Y offset\r
+ *(Uint32*)(gpTegra2Vid_IOMem + DC_WINBUF_A_ADDR_H_OFFSET_0) = 0; // X offset\r
+ }\r
+\r
+ return 0;\r
+}\r
--- /dev/null
+/*
+ * Acess2 NVidia Tegra2 Display Driver
+ * - By John Hodge (thePowersGang)
+ *
+ * tegra2.h
+ * - Driver definitions
+ */
+#ifndef _TEGRA2_DISP_H_
+#define _TEGRA2_DISP_H_
+
+#define TEGRA2VID_BASE 0x54200000 // 0x40000 Large (256 KB)
+
+const struct sTegra2_Disp_Mode
+{
+ Uint16 W, H;
+ Uint16 HFP, VFP;
+ Uint16 HS, VS;
+ Uint16 HBP, VBP;
+} caTegra2Vid_Modes[] = {
+ // TODO: VESA timings
+ {720, 487, 16,33, 63, 33, 59, 133}, // NTSC 2
+ {720, 576, 12,33, 63, 33, 69, 193}, // PAL 2 (VFP shown as 2/33, used 33)
+ {720, 483, 16, 6, 63, 6, 59, 30}, // 480p
+ {1280, 720, 70, 5, 804, 6, 220, 20}, // 720p
+ {1920,1080, 44, 4, 884, 5, 148, 36}, // 1080p
+ // TODO: Can all but HA/VA be constant and those select the resolution?
+};
+const int ciTegra2Vid_ModeCount = sizeof(caTegra2Vid_Modes)/sizeof(caTegra2Vid_Modes[0]);
+
+enum eTegra2_Disp_Regs
+{
+ DC_DISP_DISP_SIGNAL_OPTIONS0_0 = 0x400,
+ DC_DISP_DISP_SIGNAL_OPTIONS1_0,
+ DC_DISP_DISP_WIN_OPTIONS_0,
+ DC_DISP_MEM_HIGH_PRIORITY_0,
+ DC_DISP_MEM_HIGH_PRIORITY_TIMER_0,
+ DC_DISP_DISP_TIMING_OPTIONS_0,
+ DC_DISP_REF_TO_SYNC_0,
+ DC_DISP_SYNC_WIDTH_0,
+ DC_DISP_BACK_PORCH_0,
+ DC_DISP_DISP_ACTIVE_0,
+ DC_DISP_FRONT_PORCH_0,
+
+ DC_DISP_H_PULSE0_CONTROL_0,
+
+ DC_WINC_A_COLOR_PALETTE_0 = 0x500,
+ DC_WINC_A_PALETTE_COLOR_EXT_0 = 0x600,
+ DC_WIN_A_WIN_OPTIONS_0 = 0x700,
+ DC_WIN_A_BYTE_SWAP_0,
+ DC_WIN_A_BUFFER_CONTROL_0,
+ DC_WIN_A_COLOR_DEPTH_0,
+ DC_WIN_A_POSITION_0,
+ DC_WIN_A_SIZE_0,
+ DC_WIN_A_PRESCALED_SIZE_0,
+ DC_WIN_A_H_INITIAL_DDA_0,
+ DC_WIN_A_V_INITIAL_DDA_0,
+ DC_WIN_A_DDA_INCREMENT_0,
+ DC_WIN_A_LINE_STRIDE_0,
+ DC_WIN_A_BUF_STRIDE_0,
+ DC_WIN_A_BUFFER_ADDR_MODE_0,
+ DC_WIN_A_DV_CONTROL_0,
+ DC_WIN_A_BLEND_NOKEY_0,
+
+ DC_WINBUF_A_START_ADDR_0 = 0x800,
+ DC_WINBUF_A_START_ADDR_NS_0,
+ DC_WINBUF_A_ADDR_H_OFFSET_0,
+ DC_WINBUF_A_ADDR_H_OFFSET_NS_0,
+ DC_WINBUF_A_ADDR_V_OFFSET_0,
+ DC_WINBUF_A_ADDR_V_OFFSET_NS_0,
+};
+
+#endif
+
tVesa_Mode *gVesa_Modes;\r
tVesa_Mode *gpVesaCurMode;\r
int giVesaModeCount = 0;\r
+ int gbVesaModesChecked;\r
// --- Framebuffer ---\r
char *gpVesa_Framebuffer = (void*)VESA_DEFAULT_FRAMEBUFFER;\r
int giVesaPageCount = 0; //!< Framebuffer size in pages\r
{\r
tVesa_CallInfo *info;\r
tFarPtr infoPtr;\r
- tVesa_CallModeInfo *modeinfo;\r
- tFarPtr modeinfoPtr;\r
Uint16 *modes;\r
int i;\r
\r
// Allocate Info Block\r
gpVesa_BiosState = VM8086_Init();\r
info = VM8086_Allocate(gpVesa_BiosState, 512, &infoPtr.seg, &infoPtr.ofs);\r
- modeinfo = VM8086_Allocate(gpVesa_BiosState, 512, &modeinfoPtr.seg, &modeinfoPtr.ofs);\r
// Set Requested Version\r
memcpy(info->signature, "VBE2", 4);\r
// Set Registers\r
for( i = 1; i < giVesaModeCount; i++ )\r
{\r
gVesa_Modes[i].code = modes[i];\r
- // Get Mode info\r
- gpVesa_BiosState->AX = 0x4F01;\r
- gpVesa_BiosState->CX = gVesa_Modes[i].code;\r
- gpVesa_BiosState->ES = modeinfoPtr.seg;\r
- gpVesa_BiosState->DI = modeinfoPtr.ofs;\r
- VM8086_Int(gpVesa_BiosState, 0x10);\r
- \r
- // Parse Info\r
- gVesa_Modes[i].flags = 0;\r
- if ( (modeinfo->attributes & 0x90) == 0x90 )\r
- {\r
- gVesa_Modes[i].flags |= FLAG_LFB;\r
- gVesa_Modes[i].framebuffer = modeinfo->physbase;\r
- gVesa_Modes[i].fbSize = modeinfo->Yres*modeinfo->pitch;\r
- } else {\r
- gVesa_Modes[i].framebuffer = 0;\r
- gVesa_Modes[i].fbSize = 0;\r
- }\r
- \r
- gVesa_Modes[i].pitch = modeinfo->pitch;\r
- gVesa_Modes[i].width = modeinfo->Xres;\r
- gVesa_Modes[i].height = modeinfo->Yres;\r
- gVesa_Modes[i].bpp = modeinfo->bpp;\r
- \r
- #if DEBUG\r
- Log_Log("VESA", "0x%x - %ix%ix%i",\r
- gVesa_Modes[i].code, gVesa_Modes[i].width, gVesa_Modes[i].height, gVesa_Modes[i].bpp);\r
- #endif\r
}\r
- \r
+\r
+// VM8086_Deallocate( info );\r
\r
// Install Device\r
giVesaDriverId = DevFS_AddDevice( &gVesa_DriverStruct );\r
return MODULE_ERR_OK;\r
}\r
\r
+void Vesa_int_FillModeList(void)\r
+{\r
+ if( !gbVesaModesChecked )\r
+ {\r
+ int i;\r
+ tVesa_CallModeInfo *modeinfo;\r
+ tFarPtr modeinfoPtr;\r
+ \r
+ modeinfo = VM8086_Allocate(gpVesa_BiosState, 512, &modeinfoPtr.seg, &modeinfoPtr.ofs);\r
+ for( i = 1; i < giVesaModeCount; i ++ )\r
+ {\r
+ // Get Mode info\r
+ gpVesa_BiosState->AX = 0x4F01;\r
+ gpVesa_BiosState->CX = gVesa_Modes[i].code;\r
+ gpVesa_BiosState->ES = modeinfoPtr.seg;\r
+ gpVesa_BiosState->DI = modeinfoPtr.ofs;\r
+ VM8086_Int(gpVesa_BiosState, 0x10);\r
+ \r
+ // Parse Info\r
+ gVesa_Modes[i].flags = 0;\r
+ if ( (modeinfo->attributes & 0x90) == 0x90 )\r
+ {\r
+ gVesa_Modes[i].flags |= FLAG_LFB;\r
+ gVesa_Modes[i].framebuffer = modeinfo->physbase;\r
+ gVesa_Modes[i].fbSize = modeinfo->Yres*modeinfo->pitch;\r
+ } else {\r
+ gVesa_Modes[i].framebuffer = 0;\r
+ gVesa_Modes[i].fbSize = 0;\r
+ }\r
+ \r
+ gVesa_Modes[i].pitch = modeinfo->pitch;\r
+ gVesa_Modes[i].width = modeinfo->Xres;\r
+ gVesa_Modes[i].height = modeinfo->Yres;\r
+ gVesa_Modes[i].bpp = modeinfo->bpp;\r
+ \r
+ #if DEBUG\r
+ Log_Log("VESA", "0x%x - %ix%ix%i",\r
+ gVesa_Modes[i].code, gVesa_Modes[i].width, gVesa_Modes[i].height, gVesa_Modes[i].bpp);\r
+ #endif\r
+ }\r
+ \r
+// VM8086_Deallocate( modeinfo );\r
+ \r
+ gbVesaModesChecked = 1;\r
+ }\r
+}\r
+\r
/* Read from the framebuffer\r
*/\r
Uint64 Vesa_Read(tVFS_Node *Node, Uint64 off, Uint64 len, void *buffer)\r
// Check for fast return\r
if(mode == giVesaCurrentMode) return 1;\r
\r
+ Vesa_int_FillModeList();\r
+\r
Time_RemoveTimer(giVesaCursorTimer);\r
giVesaCursorTimer = -1;\r
\r
int factor, tmp;\r
\r
ENTER("idata->width idata->height idata->bpp", data->width, data->height, data->bpp);\r
+\r
+ Vesa_int_FillModeList();\r
\r
for(i=0;i<giVesaModeCount;i++)\r
{\r
int Vesa_Int_ModeInfo(tVideo_IOCtl_Mode *data)\r
{\r
if(data->id < 0 || data->id > giVesaModeCount) return -1;\r
+\r
+ Vesa_int_FillModeList();\r
+\r
data->width = gVesa_Modes[data->id].width;\r
data->height = gVesa_Modes[data->id].height;\r
data->bpp = gVesa_Modes[data->id].bpp;\r
void USB_AsyncThread(void *Unused)
{
+ Threads_SetName("USB Async IO Thread");
for(;;)
{
tAsyncOp *op = Workqueue_GetWork(&gUSB_AsyncQueue);
}
}
+// Log_Debug("USBPoll", "giUSB_PollPosition = %i", giUSB_PollPosition);
+
// A little evil for neater code
prev = (void*)( (tVAddr)&gUSB_PollQueues[giUSB_PollPosition] - offsetof(tUSBEndpoint, Next) );