forked from KolibriOS/kolibrios
Upload uARM emulator (linux4kolibri)
git-svn-id: svn://kolibrios.org@8327 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
parent
f1979bad47
commit
a03882245a
2736
contrib/other/uarm/CPU.c
Executable file
2736
contrib/other/uarm/CPU.c
Executable file
File diff suppressed because it is too large
Load Diff
173
contrib/other/uarm/CPU.h
Executable file
173
contrib/other/uarm/CPU.h
Executable file
@ -0,0 +1,173 @@
|
||||
#ifndef _CPU_H_
|
||||
#define _CPU_H_
|
||||
|
||||
|
||||
//#define ARM_V6 //define to allow v6 instructions
|
||||
//#define THUMB_2 //define to allow Thumb2
|
||||
|
||||
#include "types.h"
|
||||
|
||||
struct ArmCpu;
|
||||
|
||||
#define ARM_SR_N 0x80000000UL
|
||||
#define ARM_SR_Z 0x40000000UL
|
||||
#define ARM_SR_C 0x20000000UL
|
||||
#define ARM_SR_V 0x10000000UL
|
||||
#define ARM_SR_Q 0x08000000UL
|
||||
#ifdef ARM_V6 //V6KT2, but without T2 to be exact (we implement things like MLS, but not Thumb2 or ThumbEE)
|
||||
#define ARM_SR_J 0x01000000UL
|
||||
#define ARM_SR_E 0x00000200UL
|
||||
#define ARM_SR_A 0x00000100UL
|
||||
#define ARM_SR_GE_0 0x00010000UL
|
||||
#define ARM_SR_GE_1 0x00020000UL
|
||||
#define ARM_SR_GE_2 0x00040000UL
|
||||
#define ARM_SR_GE_3 0x00080000UL
|
||||
#define ARM_SR_GE_MASK 0x000F0000UL
|
||||
#define ARM_SR_GE_SHIFT 16
|
||||
#endif
|
||||
#define ARM_SR_I 0x00000080UL
|
||||
#define ARM_SR_F 0x00000040UL
|
||||
#define ARM_SR_T 0x00000020UL
|
||||
#define ARM_SR_M 0x0000001FUL
|
||||
|
||||
#define ARM_SR_MODE_USR 0x00000010UL
|
||||
#define ARM_SR_MODE_FIQ 0x00000011UL
|
||||
#define ARM_SR_MODE_IRQ 0x00000012UL
|
||||
#define ARM_SR_MODE_SVC 0x00000013UL
|
||||
#define ARM_SR_MODE_ABT 0x00000017UL
|
||||
#define ARM_SR_MODE_UND 0x0000001BUL
|
||||
#define ARM_SR_MODE_SYS 0x0000001FUL
|
||||
|
||||
#define ARV_VECTOR_OFFT_RST 0x00000000UL
|
||||
#define ARM_VECTOR_OFFT_UND 0x00000004UL
|
||||
#define ARM_VECTOR_OFFT_SWI 0x00000008UL
|
||||
#define ARM_VECTOR_OFFT_P_ABT 0x0000000CUL
|
||||
#define ARM_VECTOR_OFFT_D_ABT 0x00000010UL
|
||||
#define ARM_VECTOR_OFFT_UNUSED 0x00000014UL
|
||||
#define ARM_VECTOR_OFFT_IRQ 0x00000018UL
|
||||
#define ARM_VECTOR_OFFT_FIQ 0x0000001CUL
|
||||
|
||||
#define HYPERCALL_ARM 0xF7BBBBBBUL
|
||||
#define HYPERCALL_THUMB 0xBBBBUL
|
||||
|
||||
//the following are for cpuGetRegExternal() and are generally used for debugging purposes
|
||||
#define ARM_REG_NUM_CPSR 16
|
||||
#define ARM_REG_NUM_SPSR 17
|
||||
|
||||
struct ArmCpu;
|
||||
|
||||
typedef Boolean (*ArmCoprocRegXferF) (struct ArmCpu* cpu, void* userData, Boolean two/* MCR2/MRC2 ? */, Boolean MRC, UInt8 op1, UInt8 Rx, UInt8 CRn, UInt8 CRm, UInt8 op2);
|
||||
typedef Boolean (*ArmCoprocDatProcF) (struct ArmCpu* cpu, void* userData, Boolean two/* CDP2 ? */, UInt8 op1, UInt8 CRd, UInt8 CRn, UInt8 CRm, UInt8 op2);
|
||||
typedef Boolean (*ArmCoprocMemAccsF) (struct ArmCpu* cpu, void* userData, Boolean two /* LDC2/STC2 ? */, Boolean N, Boolean store, UInt8 CRd, UInt32 addr, UInt8* option /* NULL if none */);
|
||||
typedef Boolean (*ArmCoprocTwoRegF) (struct ArmCpu* cpu, void* userData, Boolean MRRC, UInt8 op, UInt8 Rd, UInt8 Rn, UInt8 CRm);
|
||||
|
||||
typedef Boolean (*ArmCpuMemF) (struct ArmCpu* cpu, void* buf, UInt32 vaddr, UInt8 size, Boolean write, Boolean priviledged, UInt8* fsr); //read/write
|
||||
typedef Boolean (*ArmCpuHypercall) (struct ArmCpu* cpu); //return true if handled
|
||||
typedef void (*ArmCpuEmulErr) (struct ArmCpu* cpu, const char* err_str);
|
||||
|
||||
typedef void (*ArmSetFaultAdrF) (struct ArmCpu* cpu, UInt32 adr, UInt8 faultStatus);
|
||||
|
||||
#include "icache.h"
|
||||
|
||||
|
||||
/*
|
||||
|
||||
coprocessors:
|
||||
|
||||
0 - DSP (pxa only)
|
||||
0, 1 - WMMX (pxa only)
|
||||
11 - VFP (arm standard)
|
||||
15 - system control (arm standard)
|
||||
*/
|
||||
|
||||
|
||||
typedef struct{
|
||||
|
||||
ArmCoprocRegXferF regXfer;
|
||||
ArmCoprocDatProcF dataProcessing;
|
||||
ArmCoprocMemAccsF memAccess;
|
||||
ArmCoprocTwoRegF twoRegF;
|
||||
void* userData;
|
||||
|
||||
}ArmCoprocessor;
|
||||
|
||||
typedef struct{
|
||||
|
||||
UInt32 R13, R14;
|
||||
UInt32 SPSR; //usr mode doesn't have an SPSR
|
||||
}ArmBankedRegs;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
typedef struct ArmCpu{
|
||||
|
||||
UInt32 regs[16]; //current active regs as per current mode
|
||||
UInt32 CPSR, SPSR;
|
||||
|
||||
ArmBankedRegs bank_usr; //usr regs when in another mode
|
||||
ArmBankedRegs bank_svc; //svc regs when in another mode
|
||||
ArmBankedRegs bank_abt; //abt regs when in another mode
|
||||
ArmBankedRegs bank_und; //und regs when in another mode
|
||||
ArmBankedRegs bank_irq; //irq regs when in another mode
|
||||
ArmBankedRegs bank_fiq; //fiq regs when in another mode
|
||||
UInt32 extra_regs[5]; //fiq regs when not in fiq mode, usr regs when in fiq mode. R8-12
|
||||
|
||||
UInt16 waitingIrqs;
|
||||
UInt16 waitingFiqs;
|
||||
UInt16 CPAR;
|
||||
|
||||
ArmCoprocessor coproc[16]; //coprocessors
|
||||
|
||||
// various other cpu config options
|
||||
UInt32 vectorBase; //address of vector base
|
||||
|
||||
#ifdef ARM_V6
|
||||
|
||||
Boolean EEE; //endianness one exception entry
|
||||
Boolean impreciseAbtWaiting;
|
||||
#endif
|
||||
|
||||
ArmCpuMemF memF;
|
||||
ArmCpuEmulErr emulErrF;
|
||||
ArmCpuHypercall hypercallF;
|
||||
ArmSetFaultAdrF setFaultAdrF;
|
||||
|
||||
icache ic;
|
||||
|
||||
void* userData; //shared by all callbacks
|
||||
}ArmCpu;
|
||||
|
||||
|
||||
Err cpuInit(ArmCpu* cpu, UInt32 pc, ArmCpuMemF memF, ArmCpuEmulErr emulErrF, ArmCpuHypercall hypercallF, ArmSetFaultAdrF setFaultAdrF);
|
||||
Err cpuDeinit(ArmCpu* cp);
|
||||
void cpuCycle(ArmCpu* cpu);
|
||||
void cpuIrq(ArmCpu* cpu, Boolean fiq, Boolean raise); //unraise when acknowledged
|
||||
|
||||
#ifdef ARM_V6
|
||||
|
||||
void cpuSignalImpreciseAbt(ArmCpu* cpu, Boolean raise);
|
||||
|
||||
#endif
|
||||
|
||||
UInt32 cpuGetRegExternal(ArmCpu* cpu, UInt8 reg);
|
||||
void cpuSetReg(ArmCpu* cpu, UInt8 reg, UInt32 val);
|
||||
|
||||
void cpuCoprocessorRegister(ArmCpu* cpu, UInt8 cpNum, ArmCoprocessor* coproc);
|
||||
void cpuCoprocessorUnregister(ArmCpu* cpu, UInt8 cpNum);
|
||||
|
||||
void cpuSetVectorAddr(ArmCpu* cpu, UInt32 adr);
|
||||
|
||||
UInt16 cpuGetCPAR(ArmCpu* cpu);
|
||||
void cpuSetCPAR(ArmCpu* cpu, UInt16 cpar);
|
||||
|
||||
void cpuIcacheInval(ArmCpu* cpu);
|
||||
void cpuIcacheInvalAddr(ArmCpu* cpu, UInt32 addr);
|
||||
|
||||
|
||||
#endif
|
||||
|
454
contrib/other/uarm/MMU.c
Executable file
454
contrib/other/uarm/MMU.c
Executable file
@ -0,0 +1,454 @@
|
||||
#include "MMU.h"
|
||||
|
||||
|
||||
|
||||
void mmuTlbFlush(ArmMmu* mmu){
|
||||
|
||||
UInt8 i, j;
|
||||
|
||||
for(i = 0; i < MMU_TLB_BUCKET_NUM; i++){
|
||||
for(j = 0; j < MMU_TLB_BUCKET_SIZE; j++) mmu->tlb[i][j].sz = 0;
|
||||
mmu->replPos[i] = 0;
|
||||
mmu->readPos[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void mmuInit(ArmMmu* mmu, ArmMmuReadF readF, void* userData){
|
||||
|
||||
__mem_zero(mmu, sizeof(ArmMmu));
|
||||
mmu->readF = readF;
|
||||
mmu->userData = userData;
|
||||
mmu->transTablPA = MMU_DISABLED_TTP;
|
||||
mmu->domainCfg = 0;
|
||||
mmuTlbFlush(mmu);
|
||||
}
|
||||
|
||||
void muDeinit(_UNUSED_ ArmMmu* mmu){
|
||||
|
||||
//nothing here
|
||||
}
|
||||
|
||||
static _INLINE_ UInt8 mmuPrvHashAddr(UInt32 addr){ //addresses are granular on 1K
|
||||
|
||||
addr >>= 10;
|
||||
|
||||
addr = addr ^ (addr >> 5) ^ (addr >> 10);
|
||||
|
||||
return addr % MMU_TLB_BUCKET_NUM;
|
||||
}
|
||||
|
||||
Boolean mmuTranslate(ArmMmu* mmu, UInt32 adr, Boolean priviledged, Boolean write, UInt32* paP, UInt8* fsrP){
|
||||
|
||||
UInt32 va, pa = 0, sz, t;
|
||||
UInt8 i, j, dom, ap = 0;
|
||||
Boolean section = false, coarse = true, pxa_tex_page = false;
|
||||
UInt8 bucket;
|
||||
|
||||
//handle the 'MMU off' case
|
||||
|
||||
if(mmu->transTablPA == MMU_DISABLED_TTP){
|
||||
va = pa = 0;
|
||||
goto calc;
|
||||
}
|
||||
|
||||
//check the TLB
|
||||
if(MMU_TLB_BUCKET_SIZE && MMU_TLB_BUCKET_NUM){
|
||||
|
||||
bucket = mmuPrvHashAddr(adr);
|
||||
|
||||
for(j = 0, i = mmu->readPos[bucket]; j < MMU_TLB_BUCKET_SIZE; j++, i--){
|
||||
|
||||
if(i == 0xFF) i = MMU_TLB_BUCKET_SIZE - 1;
|
||||
|
||||
va = mmu->tlb[bucket][i].va;
|
||||
sz = mmu->tlb[bucket][i].sz;
|
||||
|
||||
if(va <= adr && va + sz > adr){
|
||||
|
||||
pa = mmu->tlb[bucket][i].pa;
|
||||
ap = mmu->tlb[bucket][i].ap;
|
||||
dom = mmu->tlb[bucket][i].domain;
|
||||
mmu->readPos[bucket] = i;
|
||||
|
||||
goto check;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//read first level table
|
||||
|
||||
if(mmu->transTablPA & 3){
|
||||
*fsrP = 0x01; //alignment fault
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!mmu->readF(mmu->userData, &t, mmu->transTablPA + ((adr & 0xFFF00000) >> 18))){
|
||||
|
||||
*fsrP = 0x0C; //translation external abort first level
|
||||
return false;
|
||||
}
|
||||
|
||||
dom = (t >> 5) & 0x0F;
|
||||
switch(t & 3){
|
||||
|
||||
case 0: //fault
|
||||
|
||||
*fsrP = 0x5; //section translation fault
|
||||
return false;
|
||||
|
||||
case 1: //coarse pagetable
|
||||
|
||||
t &= 0xFFFFFC00UL;
|
||||
t += (adr & 0x000FF000UL) >> 10;
|
||||
break;
|
||||
|
||||
case 2: //1MB section
|
||||
|
||||
pa = t & 0xFFF00000UL;
|
||||
va = adr & 0xFFF00000UL;
|
||||
sz = 1UL << 20;
|
||||
ap = (t >> 10) & 3;
|
||||
section = true;
|
||||
goto translated;
|
||||
|
||||
case 3: //fine page table
|
||||
|
||||
coarse = false;
|
||||
t &= 0xFFFFF000UL;
|
||||
t += (adr & 0x000FFC00UL) >> 8;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
//read second level table
|
||||
|
||||
if(!mmu->readF(mmu->userData, &t, t)){
|
||||
*fsrP = 0x0E | (dom << 4); //translation external abort second level
|
||||
return false;
|
||||
}
|
||||
|
||||
switch(t & 3){
|
||||
|
||||
case 0: //fault
|
||||
|
||||
*fsrP = 0x07 | (dom << 4); //page translation fault
|
||||
return false;
|
||||
|
||||
case 1: //64K mapping
|
||||
|
||||
pa = t & 0xFFFF0000UL;
|
||||
va = adr & 0xFFFF0000UL;
|
||||
sz = 65536UL;
|
||||
ap = (adr >> 14) & 3; //in "ap" store which AP we need [of the 4]
|
||||
break;
|
||||
|
||||
case 2: //4K mapping (1K effective thenks to having 4 AP fields)
|
||||
|
||||
page_size_4k:
|
||||
pa = t & 0xFFFFF000UL;
|
||||
va = adr & 0xFFFFF000UL;
|
||||
sz = 4096;
|
||||
ap = (adr >> 10) & 3; //in "ap" store which AP we need [of the 4]
|
||||
break;
|
||||
|
||||
case 3: //1K mapping
|
||||
|
||||
if(coarse){
|
||||
|
||||
pxa_tex_page = true;
|
||||
goto page_size_4k;
|
||||
}
|
||||
|
||||
pa = t & 0xFFFFFC00UL;
|
||||
va = adr & 0xFFFFFC00UL;
|
||||
ap = (t >> 4) & 3; //in "ap" store the actual AP [and skip quarter-page resolution later using the goto]
|
||||
sz = 1024;
|
||||
goto translated;
|
||||
}
|
||||
|
||||
|
||||
//handle 4 AP sections
|
||||
|
||||
i = (t >> 4) & 0xFF;
|
||||
if(pxa_tex_page || ((i & 0x0F) == (i >> 4) && (i & 0x03) == ((i >> 2) & 0x03))){ //if all domains are the same, add the whole thing
|
||||
|
||||
ap = (t >> 4) & 3;
|
||||
}
|
||||
else{ //take the quarter that is the one we need
|
||||
|
||||
err_str("quarter page found!\r\n");
|
||||
ap = (t >> (4 + 2 * ap)) & 3;
|
||||
sz /= 4;
|
||||
pa += ((UInt32)ap) * sz;
|
||||
va += ((UInt32)ap) * sz;
|
||||
}
|
||||
|
||||
|
||||
translated:
|
||||
|
||||
//insert tlb entry
|
||||
if(MMU_TLB_BUCKET_NUM && MMU_TLB_BUCKET_SIZE){
|
||||
|
||||
mmu->tlb[bucket][mmu->replPos[bucket]].pa = pa;
|
||||
mmu->tlb[bucket][mmu->replPos[bucket]].sz = sz;
|
||||
mmu->tlb[bucket][mmu->replPos[bucket]].va = va;
|
||||
mmu->tlb[bucket][mmu->replPos[bucket]].ap = ap;
|
||||
mmu->tlb[bucket][mmu->replPos[bucket]].domain = dom;
|
||||
mmu->readPos[bucket] = mmu->replPos[bucket];
|
||||
if(++mmu->replPos[bucket] == MMU_TLB_BUCKET_SIZE) mmu->replPos[bucket] = 0;
|
||||
}
|
||||
|
||||
check:
|
||||
|
||||
//check domain permissions
|
||||
|
||||
switch((mmu->domainCfg >> (dom * 2)) & 3){
|
||||
|
||||
case 0: //NO ACCESS:
|
||||
case 2: //RESERVED: unpredictable (treat as no access)
|
||||
|
||||
*fsrP = (section ? 0x08 : 0xB) | (dom << 4); //section or page domain fault
|
||||
return false;
|
||||
|
||||
|
||||
case 1: //CLIENT: check permissions
|
||||
|
||||
break;
|
||||
|
||||
|
||||
case 3: //MANAGER: allow all access
|
||||
|
||||
goto calc;
|
||||
|
||||
}
|
||||
|
||||
//check permissions
|
||||
|
||||
switch(ap){
|
||||
|
||||
case 0:
|
||||
|
||||
if(write || (!mmu->R && (!priviledged || !mmu->S))) break;
|
||||
goto calc;
|
||||
|
||||
case 1:
|
||||
|
||||
if(!priviledged) break;
|
||||
goto calc;
|
||||
|
||||
case 2:
|
||||
|
||||
if(!priviledged && write) break;
|
||||
goto calc;
|
||||
|
||||
case 3:
|
||||
|
||||
//all is good, allow access!
|
||||
goto calc;
|
||||
}
|
||||
|
||||
//perm_err:
|
||||
|
||||
*fsrP = (section ? 0x0D : 0x0F) | (dom << 4); //section or subpage permission fault
|
||||
return false;
|
||||
|
||||
calc:
|
||||
|
||||
*paP = adr - va + pa;
|
||||
return true;
|
||||
}
|
||||
|
||||
UInt32 mmuGetTTP(ArmMmu* mmu){
|
||||
|
||||
return mmu->transTablPA;
|
||||
}
|
||||
|
||||
void mmuSetTTP(ArmMmu* mmu, UInt32 ttp){
|
||||
|
||||
UInt8 i;
|
||||
|
||||
mmuTlbFlush(mmu);
|
||||
for(i = 0; i < MMU_TLB_BUCKET_NUM; i++){
|
||||
|
||||
mmu->replPos[i] = 0;
|
||||
mmu->readPos[i] = 0;
|
||||
}
|
||||
mmu->transTablPA = ttp;
|
||||
}
|
||||
|
||||
void mmuSetS(ArmMmu* mmu, Boolean on){
|
||||
|
||||
mmu->S = on;
|
||||
}
|
||||
|
||||
void mmuSetR(ArmMmu* mmu, Boolean on){
|
||||
|
||||
mmu->R = on;
|
||||
}
|
||||
|
||||
Boolean mmuGetS(ArmMmu* mmu){
|
||||
|
||||
return mmu->S;
|
||||
}
|
||||
|
||||
Boolean mmuGetR(ArmMmu* mmu){
|
||||
|
||||
return mmu->R;
|
||||
}
|
||||
|
||||
UInt32 mmuGetDomainCfg(ArmMmu* mmu){
|
||||
|
||||
return mmu->domainCfg;
|
||||
}
|
||||
|
||||
void mmuSetDomainCfg(ArmMmu* mmu, UInt32 val){
|
||||
|
||||
mmu->domainCfg = val;
|
||||
}
|
||||
|
||||
/////////////////////////// debugging helpers ///////////////////////////
|
||||
|
||||
|
||||
|
||||
UInt32 mmuDR(ArmMmu* mmu, UInt32 addr){
|
||||
|
||||
UInt32 t = 0;
|
||||
|
||||
if(!mmu->readF(mmu->userData, &t, addr)) t = 0xFFFFFFF0UL;
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
static void mmuDumpUpdate(UInt32 va, UInt32 pa, UInt32 len, UInt8 dom, UInt8 ap, Boolean c, Boolean b, Boolean valid){
|
||||
|
||||
UInt32 va_end;;
|
||||
|
||||
static Boolean wasValid = false;
|
||||
static UInt8 wasDom = 0;
|
||||
static UInt8 wasAp = 0;
|
||||
static Boolean wasB = 0;
|
||||
static Boolean wasC = 0;
|
||||
static UInt32 startVa = 0;
|
||||
static UInt32 startPa = 0;
|
||||
static UInt32 expectPa = 0;
|
||||
|
||||
|
||||
va_end = (va || len) ? va - 1 : 0xFFFFFFFFUL;
|
||||
|
||||
if(!wasValid && !valid) return; //no need to bother...
|
||||
|
||||
if(valid != wasValid || dom != wasDom || ap != wasAp || c != wasC || b != wasB || expectPa != pa){ //not a continuation of what we've been at...
|
||||
|
||||
if(wasValid){
|
||||
|
||||
|
||||
err_str("0x");
|
||||
err_hex(startVa);
|
||||
err_str("-0x");
|
||||
err_hex(va_end);
|
||||
err_str(" -> 0x");
|
||||
err_hex(startPa);
|
||||
err_str("-0x");
|
||||
err_hex(startPa + (va_end - startVa));
|
||||
err_str(" dom");
|
||||
err_dec(wasDom);
|
||||
err_str(" ap");
|
||||
err_dec(wasAp);
|
||||
err_str(" ");
|
||||
err_str(wasC ? "c" : " ");
|
||||
err_str(wasB ? "b" : " ");
|
||||
err_str("\r\n");
|
||||
}
|
||||
|
||||
wasValid = valid;
|
||||
if(valid){ //start of a new range
|
||||
|
||||
wasDom = dom;
|
||||
wasAp = ap;
|
||||
wasC = c;
|
||||
wasB = b;
|
||||
startVa = va;
|
||||
startPa = pa;
|
||||
expectPa = pa + len;
|
||||
}
|
||||
}
|
||||
else{ //continuation of what we've been up to...
|
||||
|
||||
expectPa += len;
|
||||
}
|
||||
}
|
||||
|
||||
static void mmuDump(ArmMmu* mmu){
|
||||
|
||||
UInt32 i, j, t, sla, va, psz;
|
||||
UInt8 dom;
|
||||
Boolean coarse = false;
|
||||
|
||||
for(i = 0; i < 0x1000; i++){
|
||||
|
||||
t = mmuDR(mmu, mmu->transTablPA + (i << 2));
|
||||
va = i << 20;
|
||||
dom = (t >> 5) & 0x0F;
|
||||
switch(t & 3){
|
||||
|
||||
case 0: //done
|
||||
mmuDumpUpdate(va, 0, 1UL << 20, 0, 0, false, false, false);
|
||||
continue;
|
||||
|
||||
case 1: //coarse page table
|
||||
coarse = true;
|
||||
t &= 0xFFFFFC00UL;
|
||||
break;
|
||||
|
||||
case 2: //section
|
||||
mmuDumpUpdate(va, t & 0xFFF00000UL, 1UL << 20, dom, (t >> 10) & 3, !!(t & 8), !!(t & 4), true);
|
||||
continue;
|
||||
|
||||
case 3: //fine page table
|
||||
t &= 0xFFFFF000UL;
|
||||
break;
|
||||
}
|
||||
|
||||
sla = t;
|
||||
psz = coarse ? 4096 : 1024;
|
||||
for(j = 0; j < ((1UL << 20) / psz); j++){
|
||||
t = mmuDR(mmu, sla + (j << 2));
|
||||
va = (i << 20) + (j * psz);
|
||||
switch(t & 3){
|
||||
|
||||
case 0: //invalid
|
||||
mmuDumpUpdate(va, 0, psz, 0, 0, false, false, false);
|
||||
break;
|
||||
|
||||
case 1: //large 64k page
|
||||
mmuDumpUpdate(va + 0 * 16384UL, (t & 0xFFFF0000UL) + 0 * 16384UL, 16384, dom, (t >> 4) & 3, !!(t & 8), !!(t & 4), true);
|
||||
mmuDumpUpdate(va + 1 * 16384UL, (t & 0xFFFF0000UL) + 1 * 16384UL, 16384, dom, (t >> 6) & 3, !!(t & 8), !!(t & 4), true);
|
||||
mmuDumpUpdate(va + 2 * 16384UL, (t & 0xFFFF0000UL) + 2 * 16384UL, 16384, dom, (t >> 8) & 3, !!(t & 8), !!(t & 4), true);
|
||||
mmuDumpUpdate(va + 3 * 16384UL, (t & 0xFFFF0000UL) + 3 * 16384UL, 16384, dom, (t >> 10) & 3, !!(t & 8), !!(t & 4), true);
|
||||
j += coarse ? 15 : 63;
|
||||
break;
|
||||
|
||||
case 2: //small 4k page
|
||||
mmuDumpUpdate(va + 0 * 1024, (t & 0xFFFFF000UL) + 0 * 1024, 1024, dom, (t >> 4) & 3, !!(t & 8), !!(t & 4), true);
|
||||
mmuDumpUpdate(va + 1 * 1024, (t & 0xFFFFF000UL) + 1 * 1024, 1024, dom, (t >> 6) & 3, !!(t & 8), !!(t & 4), true);
|
||||
mmuDumpUpdate(va + 2 * 1024, (t & 0xFFFFF000UL) + 2 * 1024, 1024, dom, (t >> 8) & 3, !!(t & 8), !!(t & 4), true);
|
||||
mmuDumpUpdate(va + 3 * 1024, (t & 0xFFFFF000UL) + 3 * 1024, 1024, dom, (t >> 10) & 3, !!(t & 8), !!(t & 4), true);
|
||||
if(!coarse) j += 3;
|
||||
break;
|
||||
|
||||
case 3: //tiny 1k page or TEX page on pxa
|
||||
if(coarse){
|
||||
|
||||
mmuDumpUpdate(va, t & 0xFFFFF000UL, 4096, dom, (t >> 4) & 3, !!(t & 8), !!(t & 4), true);
|
||||
}
|
||||
else{
|
||||
|
||||
mmuDumpUpdate(va, t & 0xFFFFFC00UL, 1024, dom, (t >> 4) & 3, !!(t & 8), !!(t & 4), true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
mmuDumpUpdate(0, 0, 0, 0, 0, false, false, false); //finish things off
|
||||
}
|
64
contrib/other/uarm/MMU.h
Executable file
64
contrib/other/uarm/MMU.h
Executable file
@ -0,0 +1,64 @@
|
||||
#ifndef _MMU_H_
|
||||
#define _MMU_H_
|
||||
|
||||
|
||||
#include "types.h"
|
||||
|
||||
|
||||
#define MMU_TLB_BUCKET_SIZE 8
|
||||
#define MMU_TLB_BUCKET_NUM 32
|
||||
#define MMU_DISABLED_TTP 0xFFFFFFFFUL
|
||||
|
||||
|
||||
typedef Err (*ArmMmuReadF)(void* userData, UInt32* buf, UInt32 pa); //read a word
|
||||
|
||||
#define errMmuTranslation (errMmu + 1)
|
||||
#define errMmuDomain (errMmu + 2)
|
||||
#define errMmuPermission (errMmu + 3)
|
||||
|
||||
typedef struct {
|
||||
|
||||
UInt32 pa, va;
|
||||
UInt32 sz;
|
||||
UInt32 ap:2;
|
||||
UInt32 domain:4;
|
||||
|
||||
}ArmPrvTlb;
|
||||
|
||||
typedef struct ArmMmu{
|
||||
|
||||
UInt32 transTablPA;
|
||||
UInt8 S:1;
|
||||
UInt8 R:1;
|
||||
UInt8 readPos[MMU_TLB_BUCKET_NUM];
|
||||
UInt8 replPos[MMU_TLB_BUCKET_NUM];
|
||||
ArmPrvTlb tlb[MMU_TLB_BUCKET_NUM][MMU_TLB_BUCKET_SIZE];
|
||||
UInt32 domainCfg;
|
||||
ArmMmuReadF readF;
|
||||
void* userData;
|
||||
|
||||
}ArmMmu;
|
||||
|
||||
|
||||
void mmuInit(ArmMmu* mmu, ArmMmuReadF readF, void* userData);
|
||||
void muDeinit(ArmMmu* mmu);
|
||||
Boolean mmuTranslate(ArmMmu* mmu, UInt32 va, Boolean priviledged, Boolean write, UInt32* paP, UInt8* fsrP);
|
||||
|
||||
UInt32 mmuGetTTP(ArmMmu* mmu);
|
||||
void mmuSetTTP(ArmMmu* mmu, UInt32 ttp);
|
||||
|
||||
void mmuSetS(ArmMmu* mmu, Boolean on);
|
||||
void mmuSetR(ArmMmu* mmu, Boolean on);
|
||||
Boolean mmuGetS(ArmMmu* mmu);
|
||||
Boolean mmuGetR(ArmMmu* mmu);
|
||||
|
||||
UInt32 mmuGetDomainCfg(ArmMmu* mmu);
|
||||
void mmuSetDomainCfg(ArmMmu* mmu, UInt32 val);
|
||||
|
||||
void mmuTlbFlush(ArmMmu* mmu);
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
20
contrib/other/uarm/Makefile
Executable file
20
contrib/other/uarm/Makefile
Executable file
@ -0,0 +1,20 @@
|
||||
CC = kos32-gcc
|
||||
LD = kos32-ld
|
||||
|
||||
SDK_DIR = $(abspath ../../sdk)
|
||||
|
||||
CFLAGS = -c -fno-ident -O2 -fomit-frame-pointer -fno-ident -U__WIN32__ -U_Win32 -U_WIN32 -U__MINGW32__ -UWIN32
|
||||
LDFLAGS = -static -S -nostdlib -T $(SDK_DIR)/sources/newlib/app.lds --image-base 0
|
||||
|
||||
INCLUDES = -I $(SDK_DIR)/sources/newlib/libc/include
|
||||
LIBPATH = -L $(SDK_DIR)/lib -L /home/autobuild/tools/win32/mingw32/lib
|
||||
|
||||
SRC := $(notdir $(wildcard *.c))
|
||||
OBJECTS = $(patsubst %.c, %.o, $(SRC))
|
||||
|
||||
default: $(patsubst %.c,%.o,$(SRC))
|
||||
kos32-ld $(LDFLAGS) $(LIBPATH) --subsystem console -o uARMk $(OBJECTS) -lgcc -lc.dll
|
||||
objcopy uARMk -O binary
|
||||
|
||||
%.o : %.c Makefile $(SRC)
|
||||
$(CC) $(CFLAGS) $(INCLUDES) -o $@ $<
|
113
contrib/other/uarm/RAM.c
Executable file
113
contrib/other/uarm/RAM.c
Executable file
@ -0,0 +1,113 @@
|
||||
#include "mem.h"
|
||||
#include "RAM.h"
|
||||
|
||||
|
||||
|
||||
static Boolean ramAccessF(void* userData, UInt32 pa, UInt8 size, Boolean write, void* bufP){
|
||||
|
||||
ArmRam* ram = userData;
|
||||
UInt8* addr = (UInt8*)ram->buf;
|
||||
|
||||
pa -= ram->adr;
|
||||
if(pa >= ram->sz) return false;
|
||||
|
||||
addr += pa;
|
||||
|
||||
if(write){
|
||||
|
||||
switch(size){
|
||||
|
||||
case 1:
|
||||
|
||||
*((UInt8*)addr) = *(UInt8*)bufP; //our memory system is little-endian
|
||||
break;
|
||||
|
||||
case 2:
|
||||
|
||||
*((UInt16*)addr) = *(UInt16*)bufP; //our memory system is little-endian
|
||||
break;
|
||||
|
||||
case 4:
|
||||
|
||||
*((UInt32*)addr) = *(UInt32*)bufP;
|
||||
break;
|
||||
|
||||
case 8:
|
||||
|
||||
*((UInt32*)(addr + 0)) = ((UInt32*)bufP)[0];
|
||||
*((UInt32*)(addr + 4)) = ((UInt32*)bufP)[1];
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else{
|
||||
|
||||
switch(size){
|
||||
|
||||
case 1:
|
||||
|
||||
*(UInt8*)bufP = *((UInt8*)addr);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
|
||||
*(UInt16*)bufP = *((UInt16*)addr);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
|
||||
*(UInt32*)bufP = *((UInt32*)addr);
|
||||
break;
|
||||
|
||||
case 64:
|
||||
((UInt32*)bufP)[ 8] = *((UInt32*)(addr + 32));
|
||||
((UInt32*)bufP)[ 9] = *((UInt32*)(addr + 36));
|
||||
((UInt32*)bufP)[10] = *((UInt32*)(addr + 40));
|
||||
((UInt32*)bufP)[11] = *((UInt32*)(addr + 44));
|
||||
((UInt32*)bufP)[12] = *((UInt32*)(addr + 48));
|
||||
((UInt32*)bufP)[13] = *((UInt32*)(addr + 52));
|
||||
((UInt32*)bufP)[14] = *((UInt32*)(addr + 56));
|
||||
((UInt32*)bufP)[15] = *((UInt32*)(addr + 60));
|
||||
//fallthrough
|
||||
case 32:
|
||||
|
||||
((UInt32*)bufP)[4] = *((UInt32*)(addr + 16));
|
||||
((UInt32*)bufP)[5] = *((UInt32*)(addr + 20));
|
||||
((UInt32*)bufP)[6] = *((UInt32*)(addr + 24));
|
||||
((UInt32*)bufP)[7] = *((UInt32*)(addr + 28));
|
||||
//fallthrough
|
||||
case 16:
|
||||
|
||||
((UInt32*)bufP)[2] = *((UInt32*)(addr + 8));
|
||||
((UInt32*)bufP)[3] = *((UInt32*)(addr + 12));
|
||||
//fallthrough
|
||||
case 8:
|
||||
((UInt32*)bufP)[0] = *((UInt32*)(addr + 0));
|
||||
((UInt32*)bufP)[1] = *((UInt32*)(addr + 4));
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Boolean ramInit(ArmRam* ram, ArmMem* mem, UInt32 adr, UInt32 sz, UInt32* buf){
|
||||
|
||||
ram->adr = adr;
|
||||
ram->sz = sz;
|
||||
ram->buf = buf;
|
||||
|
||||
return memRegionAdd(mem, adr, sz, &ramAccessF, ram);
|
||||
}
|
||||
|
||||
Boolean ramDeinit(ArmRam* ram, ArmMem* mem){
|
||||
|
||||
return memRegionDel(mem, ram->adr, ram->sz);
|
||||
}
|
24
contrib/other/uarm/RAM.h
Executable file
24
contrib/other/uarm/RAM.h
Executable file
@ -0,0 +1,24 @@
|
||||
#ifndef _RAM_H_
|
||||
#define _RAM_H_
|
||||
|
||||
|
||||
#include "types.h"
|
||||
|
||||
typedef struct{
|
||||
|
||||
UInt32 adr;
|
||||
UInt32 sz;
|
||||
UInt32* buf;
|
||||
|
||||
}ArmRam;
|
||||
|
||||
|
||||
Boolean ramInit(ArmRam* ram, ArmMem* mem, UInt32 adr, UInt32 sz, UInt32* buf);
|
||||
Boolean ramDeinit(ArmRam* ram, ArmMem* mem);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
776
contrib/other/uarm/SoC.c
Executable file
776
contrib/other/uarm/SoC.c
Executable file
@ -0,0 +1,776 @@
|
||||
#include "SoC.h"
|
||||
#include "CPU.h"
|
||||
#include "MMU.h"
|
||||
#include "mem.h"
|
||||
#include "callout_RAM.h"
|
||||
#include "RAM.h"
|
||||
#include "cp15.h"
|
||||
#include "math64.h"
|
||||
#include "pxa255_IC.h"
|
||||
#include "pxa255_TIMR.h"
|
||||
#include "pxa255_RTC.h"
|
||||
#include "pxa255_UART.h"
|
||||
#include "pxa255_PwrClk.h"
|
||||
#include "pxa255_GPIO.h"
|
||||
#include "pxa255_DMA.h"
|
||||
#include "pxa255_DSP.h"
|
||||
#include "pxa255_LCD.h"
|
||||
#ifdef EMBEDDED
|
||||
#include <avr/io.h>
|
||||
#endif
|
||||
|
||||
|
||||
#define ERR(s) do{err_str(s " Halting\r\n"); while(1); }while(0)
|
||||
|
||||
static const UInt8 embedded_boot[] = {
|
||||
0x01, 0x00, 0x8F, 0xE2, 0x10, 0xFF, 0x2F, 0xE1, 0x04, 0x27, 0x01, 0x20, 0x00, 0x21, 0x00, 0xF0,
|
||||
0x0D, 0xF8, 0x0A, 0x24, 0x24, 0x07, 0x65, 0x1C, 0x05, 0x27, 0x00, 0x22, 0x00, 0xF0, 0x06, 0xF8,
|
||||
0x20, 0x60, 0x24, 0x1D, 0x49, 0x1C, 0x80, 0x29, 0xF8, 0xD1, 0x28, 0x47, 0xBC, 0x46, 0xBB, 0xBB,
|
||||
0x70, 0x47
|
||||
};
|
||||
|
||||
#define ROM_BASE 0x00000000UL
|
||||
#define ROM_SIZE sizeof(embedded_boot)
|
||||
|
||||
#define RAM_BASE 0xA0000000UL
|
||||
#define RAM_SIZE 0x01000000UL //16M @ 0xA0000000
|
||||
|
||||
|
||||
static Boolean vMemF(ArmCpu* cpu, void* buf, UInt32 vaddr, UInt8 size, Boolean write, Boolean priviledged, UInt8* fsrP){
|
||||
|
||||
SoC* soc = cpu->userData;
|
||||
UInt32 pa;
|
||||
|
||||
if(size & (size - 1)){ //size is not a power of two
|
||||
|
||||
return false;
|
||||
}
|
||||
if(vaddr & (size - 1)){ //bad alignment
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return mmuTranslate(&soc->mmu, vaddr, priviledged, write, &pa, fsrP) && memAccess(&soc->mem, pa, size, write, buf);
|
||||
}
|
||||
|
||||
|
||||
static Boolean hyperF(ArmCpu* cpu){ //return true if handled
|
||||
|
||||
SoC* soc = cpu->userData;
|
||||
|
||||
if(cpu->regs[12] == 0){
|
||||
err_str("Hypercall 0 caught\r\n");
|
||||
soc->go = false;
|
||||
}
|
||||
else if(cpu->regs[12] == 1){
|
||||
err_dec(cpu->regs[0]);
|
||||
}
|
||||
else if(cpu->regs[12] == 2){
|
||||
char x[2];
|
||||
x[1] = 0;
|
||||
x[0] = cpu->regs[0];
|
||||
err_str(x);
|
||||
}
|
||||
else if(cpu->regs[12] == 3){ //get ram size
|
||||
cpu->regs[0] = RAM_SIZE;
|
||||
}
|
||||
else if(cpu->regs[12] == 4){ //block device access perform [do a read or write]
|
||||
|
||||
//IN:
|
||||
// R0 = op
|
||||
// R1 = sector
|
||||
|
||||
return soc->blkF(soc->blkD, cpu->regs[1], soc->blkDevBuf, cpu->regs[0]);
|
||||
}
|
||||
else if(cpu->regs[12] == 5){ //block device buffer access [read or fill emulator's buffer]
|
||||
|
||||
//IN:
|
||||
// R0 = word value
|
||||
// R1 = word offset (0, 1, 2...)
|
||||
// R2 = op (1 = write, 0 = read)
|
||||
//OUT:
|
||||
// R0 = word value
|
||||
|
||||
if(cpu->regs[1] >= BLK_DEV_BLK_SZ / sizeof(UInt32)) return false; //invalid request
|
||||
|
||||
if(cpu->regs[2] == 0){
|
||||
|
||||
cpu->regs[0] = soc->blkDevBuf[cpu->regs[1]];
|
||||
}
|
||||
else if(cpu->regs[2] == 1){
|
||||
|
||||
soc->blkDevBuf[cpu->regs[1]] = cpu->regs[0];
|
||||
}
|
||||
else return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void setFaultAdrF(ArmCpu* cpu, UInt32 adr, UInt8 faultStatus){
|
||||
|
||||
SoC* soc = cpu->userData;
|
||||
|
||||
cp15SetFaultStatus(&soc->cp15, adr, faultStatus);
|
||||
}
|
||||
|
||||
static void emulErrF(_UNUSED_ ArmCpu* cpu, const char* str){
|
||||
err_str("Emulation error: <<");
|
||||
err_str(str);
|
||||
err_str(">> halting\r\n");
|
||||
while(1);
|
||||
}
|
||||
|
||||
static Boolean pMemReadF(void* userData, UInt32* buf, UInt32 pa){ //for DMA engine and MMU pagetable walks
|
||||
|
||||
ArmMem* mem = userData;
|
||||
|
||||
return memAccess(mem, pa, 4, false, buf);
|
||||
}
|
||||
|
||||
static void dumpCpuState(ArmCpu* cpu, char* label){
|
||||
|
||||
UInt8 i;
|
||||
|
||||
if(label){
|
||||
err_str("CPU ");
|
||||
err_str(label);
|
||||
err_str("\r\n");
|
||||
}
|
||||
|
||||
for(i = 0; i < 16; i++){
|
||||
err_str("R");
|
||||
err_dec(i);
|
||||
err_str("\t= 0x");
|
||||
err_hex(cpuGetRegExternal(cpu, i));
|
||||
err_str("\r\n");
|
||||
}
|
||||
err_str("CPSR\t= 0x");
|
||||
err_hex(cpuGetRegExternal(cpu, ARM_REG_NUM_CPSR));
|
||||
err_str("\r\nSPSR\t= 0x");
|
||||
err_hex(cpuGetRegExternal(cpu, ARM_REG_NUM_SPSR));
|
||||
err_str("\r\n");
|
||||
}
|
||||
|
||||
static UInt16 socUartPrvRead(void* userData){ //these are special funcs since they always get their own userData - the uart :)
|
||||
|
||||
SoC* soc = userData;
|
||||
UInt16 v;
|
||||
int r;
|
||||
|
||||
r = soc->rcF();
|
||||
if(r == CHAR_CTL_C) v = UART_CHAR_BREAK;
|
||||
else if(r == CHAR_NONE) v = UART_CHAR_NONE;
|
||||
else if(r >= 0x100) v = UART_CHAR_NONE; //we canot send this char!!!
|
||||
else v = r;
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
static void socUartPrvWrite(UInt16 chr, void* userData){ //these are special funcs since they always get their own userData - the uart :)
|
||||
|
||||
SoC* soc = userData;
|
||||
|
||||
|
||||
if(chr == UART_CHAR_NONE) return;
|
||||
|
||||
soc->wcF(chr);
|
||||
}
|
||||
|
||||
void LinkError_SIZEOF_STRUCT_SOC_wrong();
|
||||
|
||||
|
||||
void socRamModeAlloc(SoC* soc, _UNUSED_ void* ignored){
|
||||
|
||||
UInt32* ramB = emu_alloc(RAM_SIZE);
|
||||
if(!ramB) ERR("Cannot allocate RAM buffer");
|
||||
if(!ramInit(&soc->ram.RAM, &soc->mem, RAM_BASE, RAM_SIZE, ramB)) ERR("Cannot init RAM");
|
||||
|
||||
soc->calloutMem = false;
|
||||
}
|
||||
|
||||
void socRamModeCallout(SoC* soc, void* callout){
|
||||
|
||||
if(!coRamInit(&soc->ram.coRAM, &soc->mem, RAM_BASE, RAM_SIZE, callout)) ERR("Cannot init coRAM");
|
||||
|
||||
soc->calloutMem = true;
|
||||
}
|
||||
|
||||
#define ERR_(s) ERR("error");
|
||||
|
||||
void socInit(SoC* soc, SocRamAddF raF, void*raD, readcharF rc, writecharF wc, blockOp blkF, void* blkD){
|
||||
|
||||
printf ("SoC init! \n");
|
||||
Err e;
|
||||
|
||||
soc->rcF = rc;
|
||||
soc->wcF = wc;
|
||||
|
||||
soc->blkF = blkF;
|
||||
soc->blkD = blkD;
|
||||
|
||||
soc->go = true;
|
||||
|
||||
e = cpuInit(&soc->cpu, ROM_BASE, vMemF, emulErrF, hyperF, &setFaultAdrF);
|
||||
if(e){
|
||||
err_str("Failed to init CPU: ");
|
||||
// err_dec(e);
|
||||
// err_str(". Halting\r\n");
|
||||
while(1);
|
||||
}
|
||||
printf("CPU init\n");
|
||||
soc->cpu.userData = soc;
|
||||
|
||||
memInit(&soc->mem);
|
||||
mmuInit(&soc->mmu, pMemReadF, &soc->mem);
|
||||
printf("Init complete\n");
|
||||
if(ROM_SIZE > sizeof(soc->romMem)) {
|
||||
// err_str("Failed to init CPU: ");
|
||||
err_str("ROM_SIZE to small");
|
||||
// err_str(". Halting\r\n");
|
||||
while(1);
|
||||
}
|
||||
|
||||
printf("RAF\n");
|
||||
|
||||
raF(soc, raD);
|
||||
|
||||
if(!ramInit(&soc->ROM, &soc->mem, ROM_BASE, ROM_SIZE, soc->romMem)) ERR_("Cannot init ROM");
|
||||
|
||||
cp15Init(&soc->cp15, &soc->cpu, &soc->mmu);
|
||||
|
||||
__mem_copy(soc->romMem, embedded_boot, sizeof(embedded_boot));
|
||||
|
||||
printf("Things...\n");
|
||||
|
||||
if(!pxa255icInit(&soc->ic, &soc->cpu, &soc->mem)) ERR_("Cannot init PXA255's interrupt controller");
|
||||
if(!pxa255timrInit(&soc->timr, &soc->mem, &soc->ic)) ERR_("Cannot init PXA255's OS timers");
|
||||
if(!pxa255rtcInit(&soc->rtc, &soc->mem, &soc->ic)) ERR_("Cannot init PXA255's RTC");
|
||||
if(!pxa255uartInit(&soc->ffuart, &soc->mem, &soc->ic,PXA255_FFUART_BASE, PXA255_I_FFUART)) ERR_("Cannot init PXA255's FFUART");
|
||||
if(!pxa255uartInit(&soc->btuart, &soc->mem, &soc->ic,PXA255_BTUART_BASE, PXA255_I_BTUART)) ERR_("Cannot init PXA255's BTUART");
|
||||
if(!pxa255uartInit(&soc->stuart, &soc->mem, &soc->ic,PXA255_STUART_BASE, PXA255_I_STUART)) ERR_("Cannot init PXA255's STUART");
|
||||
if(!pxa255pwrClkInit(&soc->pwrClk, &soc->cpu, &soc->mem)) ERR_("Cannot init PXA255's Power and Clock manager");
|
||||
if(!pxa255gpioInit(&soc->gpio, &soc->mem, &soc->ic)) ERR_("Cannot init PXA255's GPIO controller");
|
||||
if(!pxa255dmaInit(&soc->dma, &soc->mem, &soc->ic)) ERR_("Cannot init PXA255's DMA controller");
|
||||
if(!pxa255dspInit(&soc->dsp, &soc->cpu)) ERR_("Cannot init PXA255's cp0 DSP");
|
||||
if(!pxa255lcdInit(&soc->lcd, &soc->mem, &soc->ic)) ERR_("Cannot init PXA255's LCD controller");
|
||||
|
||||
printf("go?\n");
|
||||
|
||||
pxa255uartSetFuncs(&soc->ffuart, socUartPrvRead, socUartPrvWrite, soc);
|
||||
}
|
||||
|
||||
void gdbCmdWait(SoC* soc, unsigned gdbPort, int* ss);
|
||||
|
||||
void socRun(SoC* soc, UInt32 gdbPort){
|
||||
|
||||
|
||||
printf("go2?\n");
|
||||
|
||||
UInt32 prevRtc = 0;
|
||||
UInt32 cyclesCapt = 0;
|
||||
|
||||
UInt32 cycles = 0; //make 64 if you REALLY need it... later
|
||||
|
||||
#ifdef GDB_SUPPORT
|
||||
int ss = 1; //for gdb stub single step
|
||||
#else
|
||||
gdbPort = 0; //use the param somehow to quiet GCC
|
||||
#endif
|
||||
|
||||
printf("run !\n");
|
||||
|
||||
while(soc->go){
|
||||
//printf("Soc go...\n");
|
||||
cycles++;
|
||||
|
||||
#ifdef EMBEDDED
|
||||
if(!(PIND & 0x10)){ //btn down
|
||||
|
||||
if(!prevRtc){
|
||||
|
||||
do{
|
||||
prevRtc = gRtc;
|
||||
}while(prevRtc != gRtc);
|
||||
cyclesCapt = 0;
|
||||
}
|
||||
else{
|
||||
|
||||
UInt32 t;
|
||||
|
||||
//we only care to go on if the rtc is now different
|
||||
do{
|
||||
t = gRtc;
|
||||
}while(t != gRtc);
|
||||
|
||||
if(t != prevRtc){
|
||||
|
||||
if(!cyclesCapt){
|
||||
|
||||
//this code assumes we're called often enough that the next rtc vals we see is the NEXT second, not the one after or any other such thing
|
||||
cyclesCapt = cycles;
|
||||
prevRtc = t;
|
||||
}
|
||||
else{
|
||||
|
||||
err_dec(cycles - cyclesCapt);
|
||||
err_str(" Hz\r\n");
|
||||
|
||||
cyclesCapt = 0;
|
||||
prevRtc = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if(!(cycles & 0x00000FUL)) pxa255timrTick(&soc->timr);
|
||||
if(!(cycles & 0x0000FFUL)) pxa255uartProcess(&soc->ffuart);
|
||||
if(!(cycles & 0x000FFFUL)) pxa255rtcUpdate(&soc->rtc);
|
||||
if(!(cycles & 0x01FFFFUL)) pxa255lcdFrame(&soc->lcd);
|
||||
|
||||
#ifdef GDB_SUPPORT
|
||||
gdbCmdWait(soc, gdbPort, &ss);
|
||||
#endif
|
||||
|
||||
cpuCycle(&soc->cpu);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef GDB_SUPPORT
|
||||
|
||||
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/select.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <netinet/in.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
|
||||
static int socdBkptDel(SoC* soc, UInt32 addr, UInt8 sz){
|
||||
|
||||
UInt8 i;
|
||||
|
||||
for(i = 0; i < soc->nBkpt; i++){
|
||||
|
||||
if(soc->bkpt[i] == addr){
|
||||
|
||||
soc->nBkpt--;
|
||||
soc->bkpt[i] = soc->bkpt[soc->nBkpt];
|
||||
i--;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int socdBkptAdd(SoC* soc, UInt32 addr, UInt8 sz){ //boolean
|
||||
|
||||
socdBkptDel(soc, addr, sz);
|
||||
|
||||
if(soc->nBkpt == MAX_BKPT) return 0;
|
||||
|
||||
soc->bkpt[soc->nBkpt++] = addr;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int socdWtpDel(SoC* soc, UInt32 addr, UInt8 sz){
|
||||
|
||||
UInt8 i;
|
||||
|
||||
for(i = 0; i < soc->nWtp; i++){
|
||||
|
||||
if(soc->wtpA[i] == addr && soc->wtpS[i] == sz){
|
||||
|
||||
soc->nWtp--;
|
||||
soc->wtpA[i] = soc->wtpA[soc->nWtp];
|
||||
soc->wtpS[i] = soc->wtpS[soc->nWtp];
|
||||
i--;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int socdWtpAdd(SoC* soc, UInt32 addr, UInt8 sz){ //boolean
|
||||
|
||||
socdWtpDel(soc, addr, sz);
|
||||
|
||||
if(soc->nWtp == MAX_WTP) return 0;
|
||||
|
||||
soc->wtpA[soc->nWtp] = addr;
|
||||
soc->wtpS[soc->nWtp] = sz;
|
||||
soc->nWtp++;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
UInt32 htoi(const char** cP){
|
||||
|
||||
UInt32 i = 0;
|
||||
const char* in = *cP;
|
||||
char c;
|
||||
|
||||
while((c = *in) != 0){
|
||||
|
||||
if(c >= '0' && c <= '9') i = (i * 16) + (c - '0');
|
||||
else if(c >= 'a' && c <= 'f') i = (i * 16) + (c + 10 - 'a');
|
||||
else if(c >= 'A' && c <= 'F') i = (i * 16) + (c + 10 - 'A');
|
||||
else break;
|
||||
in++;
|
||||
}
|
||||
|
||||
*cP = in;
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
static UInt32 swap32(UInt32 x){
|
||||
|
||||
return ((x >> 24) & 0xff) | ((x >> 8) & 0xff00) | ((x & 0xff00) << 8) | ((x & 0xff) << 24);
|
||||
}
|
||||
|
||||
|
||||
int gdb_memAccess(SoC* soc, UInt32 addr, UInt8* buf, int write){
|
||||
|
||||
UInt32 pa = 0;
|
||||
UInt8 fsr = 0;
|
||||
|
||||
return mmuTranslate(&soc->mmu, addr, true, false, &pa, &fsr) && memAccess(&soc->mem, pa, 1, write | 0x80, buf);
|
||||
}
|
||||
|
||||
static int addRegToStr(SoC* soc, char* str, int reg){
|
||||
|
||||
if(reg == 0x19 || reg < 0x10){
|
||||
if(reg == 0x19) reg = ARM_REG_NUM_CPSR;
|
||||
sprintf(str + strlen(str), "%08x", swap32(cpuGetRegExternal(&soc->cpu, reg)));
|
||||
}
|
||||
else if(reg >= 0x10 && reg < 0x18){
|
||||
|
||||
strcat(str, "000000000000000000000000");
|
||||
}
|
||||
else if(reg == 0x18){ //fps
|
||||
|
||||
strcat(str, "00000000");
|
||||
}
|
||||
else return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int interpPacket(SoC* soc,const char* in, char* out, int* ss){ //return 0 if we failed to interp a command, 1 is all ok, -1 to send no reply and run
|
||||
|
||||
ArmCpu* cpu = &soc->cpu;
|
||||
unsigned char c;
|
||||
unsigned addr, len;
|
||||
unsigned char* ptr;
|
||||
int i;
|
||||
int ret = 1;
|
||||
|
||||
|
||||
|
||||
if(strcmp(in, "qSupported") == 0){
|
||||
|
||||
strcpy(out, "PacketSize=99");
|
||||
}
|
||||
else if(strcmp(in, "vCont?") == 0){
|
||||
|
||||
out[0] = 0;
|
||||
}
|
||||
else if(strcmp(in, "s") == 0){ //single step
|
||||
|
||||
*ss = 1;
|
||||
return -1;
|
||||
}
|
||||
else if(strcmp(in, "c") == 0 || in[0] == 'C'){ //continue [with signal, which we ignore]
|
||||
|
||||
return -1;
|
||||
}
|
||||
else if(in[0] == 'Z' || in[0] == 'z'){
|
||||
|
||||
char op = in[0];
|
||||
char type = in[1];
|
||||
int (*f)(SoC* soc, UInt32 addr, UInt8 sz) = NULL;
|
||||
|
||||
in += 3;
|
||||
addr = htoi(&in);
|
||||
if(*in++ != ',') goto fail; //no comma?
|
||||
len = htoi(&in);
|
||||
if(*in) goto fail; //string not over?
|
||||
|
||||
if(type == '0' || type == '1'){ //bkpt
|
||||
|
||||
f = (op == 'Z') ? socdBkptAdd : socdBkptDel;
|
||||
}
|
||||
/*
|
||||
else if(type == '2' || type == '3'){ //wtp
|
||||
|
||||
f = (op == 'Z') ? socdWtpAdd : socdWtpDel;
|
||||
}
|
||||
else goto fail;
|
||||
*/
|
||||
strcpy(out,f(soc, addr, len) ? "OK" : "e00");
|
||||
}
|
||||
else if(in[0] == 'H' && (in[1] == 'c' || in[1] == 'g')){
|
||||
strcpy(out, "OK");
|
||||
}
|
||||
else if(in[0] == 'q'){
|
||||
|
||||
if(in[1] == 'C'){
|
||||
|
||||
strcpy(out, "");
|
||||
}
|
||||
else if(strcmp(in +1, "Offsets") == 0){
|
||||
|
||||
strcpy(out, "Text=0;Data=0;Bss=0");
|
||||
}
|
||||
else goto fail;
|
||||
}
|
||||
else if(in[0] == 'p'){ //read register
|
||||
|
||||
in++;
|
||||
i = htoi(&in);
|
||||
if(*in) goto fail; //string not over?
|
||||
|
||||
out[0] = 0;
|
||||
if(!addRegToStr(soc, out, i)) goto fail;
|
||||
}
|
||||
else if(strcmp(in, "g") == 0){ //read all registers
|
||||
|
||||
out[0] = 0;
|
||||
for(i = 0; i < 0x1a; i++) if(!addRegToStr(soc, out, i)) goto fail;
|
||||
}
|
||||
else if(in[0] == 'P'){ //write register
|
||||
|
||||
in++;
|
||||
i = htoi(&in);
|
||||
if(*in++ != '=') goto fail; //string not over?
|
||||
if(i == 0x19 || i <16){
|
||||
if(i == 0x19) i = ARM_REG_NUM_CPSR;
|
||||
addr = htoi(&in);
|
||||
sprintf(out, "OK");
|
||||
cpuSetReg(cpu, i, addr);
|
||||
}
|
||||
else strcpy(out,"e00");
|
||||
}
|
||||
else if(in[0] == 'm'){ //read memory
|
||||
|
||||
in++;
|
||||
addr = htoi(&in);
|
||||
if(*in++ != ',') goto fail;
|
||||
len = htoi(&in);
|
||||
if(*in) goto fail;
|
||||
out[0] = 0;
|
||||
while(len--){
|
||||
|
||||
if(!gdb_memAccess(soc, addr++, &c, false)) break;
|
||||
sprintf(out + strlen(out), "%02x", c);
|
||||
}
|
||||
}
|
||||
else if(strcmp(in, "?") == 0){
|
||||
|
||||
strcpy(out,"S05");
|
||||
}
|
||||
else goto fail;
|
||||
|
||||
send_pkt:
|
||||
return ret;
|
||||
|
||||
fail:
|
||||
out[0] = 0;
|
||||
ret = 0;
|
||||
goto send_pkt;
|
||||
}
|
||||
|
||||
static void sendpacket(int sock, char* packet, int withAck){
|
||||
|
||||
unsigned int c;
|
||||
int i;
|
||||
|
||||
c = 0;
|
||||
for(i = 0; i < strlen(packet); i++) c += packet[i];
|
||||
memmove(packet + (withAck ? 2 : 1), packet, strlen(packet) + 1);
|
||||
if(withAck){
|
||||
packet[0] = '+';
|
||||
packet[1] = '$';
|
||||
}
|
||||
else{
|
||||
packet[0] = '$';
|
||||
}
|
||||
sprintf(packet + strlen(packet), "#%02x", c & 0xFF);
|
||||
|
||||
//printf("sending packet <<%s>>\n", packet);
|
||||
send(sock, packet, strlen(packet), 0);
|
||||
}
|
||||
|
||||
void gdbCmdWait(SoC* soc, unsigned gdbPort, int* ss){
|
||||
|
||||
ArmCpu* cpu = &soc->cpu;
|
||||
static int running = 0;
|
||||
static int sock = -1;
|
||||
char packet[4096];
|
||||
struct timeval tv = {0};
|
||||
fd_set set;
|
||||
int ret;
|
||||
|
||||
if(*ss && running){
|
||||
|
||||
strcpy(packet,"S05");
|
||||
sendpacket(sock, packet, 0);
|
||||
running = 0; //perform single step
|
||||
}
|
||||
*ss = 0;
|
||||
|
||||
if(running){ //check for breakpoints
|
||||
|
||||
UInt8 i;
|
||||
|
||||
for(i = 0; i < soc->nBkpt; i++){
|
||||
|
||||
if(soc->cpu.regs[15] == soc->bkpt[i]){
|
||||
|
||||
// printf("bkpt hit: pc=0x%08lX bk=0x%08lX i=%d\n", soc->cpu.regs[15], soc->bkpt[i], i);
|
||||
strcpy(packet,"S05");
|
||||
sendpacket(sock, packet, 0);
|
||||
running = 0; //perform breakpoint hit
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(gdbPort){
|
||||
|
||||
if(sock == -1){ //no socket yet - make one
|
||||
|
||||
struct sockaddr_in sa = {AF_INET, htons(gdbPort)};
|
||||
socklen_t sl = sizeof(sa);
|
||||
|
||||
inet_aton("127.0.0.1", &sa.sin_addr.s_addr);
|
||||
|
||||
sock = socket(PF_INET, SOCK_STREAM, 0);
|
||||
if(sock == -1){
|
||||
err_str("gdb socket creation fails: ");
|
||||
err_dec(errno);
|
||||
ERR("\n");
|
||||
}
|
||||
|
||||
ret = bind(sock, (struct sockaddr*)&sa, sizeof(sa));
|
||||
if(ret){
|
||||
err_str("gdb socket bind fails: ");
|
||||
err_dec(errno);
|
||||
ERR("\n");
|
||||
}
|
||||
|
||||
ret = listen(sock, 1);
|
||||
if(ret){
|
||||
err_str("gdb socket listen fails: ");
|
||||
err_dec(errno);
|
||||
ERR("\n");
|
||||
}
|
||||
|
||||
ret = accept(sock, (struct sockaddr*)&sa, &sl);
|
||||
if(ret == -1){
|
||||
err_str("gdb socket accept fails: ");
|
||||
err_dec(errno);
|
||||
ERR("\n");
|
||||
}
|
||||
close(sock);
|
||||
sock = ret;
|
||||
|
||||
soc->nBkpt = 0;
|
||||
soc->nWtp = 0;
|
||||
}
|
||||
}
|
||||
if(gdbPort){
|
||||
|
||||
do{
|
||||
|
||||
FD_ZERO(&set);
|
||||
FD_SET(sock, &set);
|
||||
tv.tv_sec = running ? 0 : 0x00f00000UL;
|
||||
do{
|
||||
ret = select(sock + 1, &set, NULL, NULL, &tv);
|
||||
}while(!ret && !running);
|
||||
if(ret < 0){
|
||||
err_str("select fails: ");
|
||||
err_dec(errno);
|
||||
ERR("\n");
|
||||
}
|
||||
if(ret > 0){
|
||||
char c;
|
||||
char* p;
|
||||
int i, len = 0, esc = 0, end = 0;
|
||||
|
||||
ret = recv(sock, &c, 1, 0);
|
||||
if(ret != 1) ERR("failed to receive byte (1)\n");
|
||||
|
||||
if(c == 3){
|
||||
strcpy(packet,"S11");
|
||||
sendpacket(sock, packet, 0);
|
||||
running = 0; //perform breakpoint hit
|
||||
}
|
||||
else if(c != '$'){
|
||||
//printf("unknown packet header '%c'\n", c);
|
||||
}
|
||||
else{
|
||||
do{
|
||||
if(esc){
|
||||
c = c ^ 0x20;
|
||||
esc = 0;
|
||||
}
|
||||
else if(c == 0x7d){
|
||||
esc = 1;
|
||||
}
|
||||
|
||||
if(!esc){ //we cannot be here if we're being escaped
|
||||
|
||||
packet[len++] = c;
|
||||
if(end == 0 && c == '#') end = 2;
|
||||
else if(end){
|
||||
|
||||
end--;
|
||||
if(!end) break;
|
||||
}
|
||||
|
||||
ret = recv(sock, &c, 1, 0);
|
||||
if(ret != 1) ERR("failed to receive byte (2)\n");
|
||||
}
|
||||
}while(1);
|
||||
packet[len] = 0;
|
||||
|
||||
memmove(packet, packet + 1, len);
|
||||
len -= 4;
|
||||
packet[len] = 0;
|
||||
ret = interpPacket(soc, p = strdup(packet), packet, ss);
|
||||
if(ret == 0) printf("how do i respond to packet <<%s>>\n", p);
|
||||
if(ret == -1){ //ack it anyways
|
||||
char c = '+';
|
||||
send(sock, &c, 1, 0);
|
||||
running = 1;
|
||||
}
|
||||
else sendpacket(sock, packet, 1);
|
||||
|
||||
emu_free(p);
|
||||
}
|
||||
}
|
||||
}while(!running);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
121
contrib/other/uarm/SoC.h
Executable file
121
contrib/other/uarm/SoC.h
Executable file
@ -0,0 +1,121 @@
|
||||
#ifndef _SOC_H_
|
||||
#define _SOC_H_
|
||||
|
||||
#include "types.h"
|
||||
|
||||
//#define GDB_SUPPORT
|
||||
//#define DYNAREC
|
||||
#define MAX_WTP 32
|
||||
#define MAX_BKPT 32
|
||||
|
||||
|
||||
|
||||
|
||||
#ifndef GDB_SUPPORT
|
||||
#ifdef DYNAREC
|
||||
#define _JIT
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#define CHAR_CTL_C -1L
|
||||
#define CHAR_NONE -2L
|
||||
typedef int (*readcharF)(void);
|
||||
typedef void (*writecharF)(int);
|
||||
|
||||
#define BLK_DEV_BLK_SZ 512
|
||||
|
||||
#define BLK_OP_SIZE 0
|
||||
#define BLK_OP_READ 1
|
||||
#define BLK_OP_WRITE 2
|
||||
|
||||
typedef int (*blockOp)(void* data, UInt32 sec, void* ptr, UInt8 op);
|
||||
|
||||
struct SoC;
|
||||
|
||||
typedef void (*SocRamAddF)(struct SoC* soc, void* data);
|
||||
|
||||
typedef struct{
|
||||
|
||||
UInt32 (*WordGet)(UInt32 wordAddr);
|
||||
void (*WordSet)(UInt32 wordAddr, UInt32 val);
|
||||
|
||||
}RamCallout;
|
||||
|
||||
void socRamModeAlloc(struct SoC* soc, void* ignored);
|
||||
void socRamModeCallout(struct SoC* soc, void* callout); //rally pointer to RamCallout
|
||||
|
||||
void socInit(struct SoC* soc, SocRamAddF raF, void* raD, readcharF rc, writecharF wc, blockOp blkF, void* blkD);
|
||||
void socRun(struct SoC* soc, UInt32 gdbPort);
|
||||
|
||||
|
||||
|
||||
extern volatile UInt32 gRtc; //needed by SoC
|
||||
|
||||
#include "CPU.h"
|
||||
#include "MMU.h"
|
||||
#include "mem.h"
|
||||
#include "callout_RAM.h"
|
||||
#include "RAM.h"
|
||||
#include "cp15.h"
|
||||
#include "math64.h"
|
||||
#include "pxa255_IC.h"
|
||||
#include "pxa255_TIMR.h"
|
||||
#include "pxa255_RTC.h"
|
||||
#include "pxa255_UART.h"
|
||||
#include "pxa255_PwrClk.h"
|
||||
#include "pxa255_GPIO.h"
|
||||
#include "pxa255_DMA.h"
|
||||
#include "pxa255_DSP.h"
|
||||
#include "pxa255_LCD.h"
|
||||
|
||||
typedef struct SoC{
|
||||
|
||||
readcharF rcF;
|
||||
writecharF wcF;
|
||||
|
||||
blockOp blkF;
|
||||
void* blkD;
|
||||
|
||||
UInt32 blkDevBuf[BLK_DEV_BLK_SZ / sizeof(UInt32)];
|
||||
|
||||
union{
|
||||
ArmRam RAM;
|
||||
CalloutRam coRAM;
|
||||
}ram;
|
||||
ArmRam ROM;
|
||||
ArmCpu cpu;
|
||||
ArmMmu mmu;
|
||||
ArmMem mem;
|
||||
ArmCP15 cp15;
|
||||
Pxa255ic ic;
|
||||
Pxa255timr timr;
|
||||
Pxa255rtc rtc;
|
||||
Pxa255uart ffuart;
|
||||
Pxa255uart btuart;
|
||||
Pxa255uart stuart;
|
||||
Pxa255pwrClk pwrClk;
|
||||
Pxa255gpio gpio;
|
||||
Pxa255dma dma;
|
||||
Pxa255dsp dsp;
|
||||
Pxa255lcd lcd;
|
||||
|
||||
UInt8 go :1;
|
||||
UInt8 calloutMem:1;
|
||||
|
||||
UInt32 romMem[13]; //space for embeddedBoot
|
||||
|
||||
#ifdef GDB_SUPPORT
|
||||
|
||||
UInt8 nBkpt, nWtp;
|
||||
UInt32 bkpt[MAX_BKPT];
|
||||
UInt32 wtpA[MAX_WTP];
|
||||
UInt8 wtpS[MAX_WTP];
|
||||
|
||||
#endif
|
||||
|
||||
}SoC;
|
||||
|
||||
#endif
|
||||
|
16
contrib/other/uarm/callout_RAM.c
Executable file
16
contrib/other/uarm/callout_RAM.c
Executable file
@ -0,0 +1,16 @@
|
||||
#include "mem.h"
|
||||
#include "callout_RAM.h"
|
||||
|
||||
|
||||
Boolean coRamInit(CalloutRam* ram, ArmMem* mem, UInt32 adr, UInt32 sz, ArmMemAccessF* coF){
|
||||
|
||||
ram->adr = adr;
|
||||
ram->sz = sz;
|
||||
|
||||
return memRegionAdd(mem, adr, sz, (void*)coF, ram);
|
||||
}
|
||||
|
||||
Boolean coRamDeinit(CalloutRam* ram, ArmMem* mem){
|
||||
|
||||
return memRegionDel(mem, ram->adr, ram->sz);
|
||||
}
|
24
contrib/other/uarm/callout_RAM.h
Executable file
24
contrib/other/uarm/callout_RAM.h
Executable file
@ -0,0 +1,24 @@
|
||||
#ifndef _CO_RAM_H_
|
||||
#define _CO_RAM_H_
|
||||
|
||||
|
||||
#include "types.h"
|
||||
#include "mem.h"
|
||||
|
||||
typedef struct{
|
||||
|
||||
UInt32 adr;
|
||||
UInt32 sz;
|
||||
|
||||
}CalloutRam;
|
||||
|
||||
|
||||
Boolean coRamInit(CalloutRam* ram, ArmMem* mem, UInt32 adr, UInt32 sz, ArmMemAccessF* coF);
|
||||
Boolean coRamDeinit(CalloutRam* ram, ArmMem* mem);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
141
contrib/other/uarm/console_obj.h
Executable file
141
contrib/other/uarm/console_obj.h
Executable file
@ -0,0 +1,141 @@
|
||||
// Console.obj loading for kos32-gcc
|
||||
// Writed by rgimad and maxcodehack
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifndef CONSOLE_OBJ_H
|
||||
#define CONSOLE_OBJ_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL 0
|
||||
#endif
|
||||
|
||||
#ifndef cdecl
|
||||
#define cdecl __attribute__ ((cdecl))
|
||||
#endif
|
||||
|
||||
#ifndef stdcall
|
||||
#define stdcall __attribute__ ((stdcall))
|
||||
#endif
|
||||
|
||||
typedef unsigned int dword;
|
||||
typedef unsigned short word;
|
||||
|
||||
const char* imports[] = {
|
||||
"START", "version", "con_init", "con_write_asciiz", "con_write_string",
|
||||
"con_printf", "con_exit", "con_get_flags", "con_set_flags", "con_kbhit",
|
||||
"con_getch", "con_getch2", "con_gets", "con_gets2", "con_get_font_height",
|
||||
"con_get_cursor_height", "con_set_cursor_height", "con_cls",
|
||||
"con_get_cursor_pos", "con_set_cursor_pos", "con_set_title",
|
||||
(char*)0
|
||||
};
|
||||
|
||||
dword *version;
|
||||
|
||||
typedef int (stdcall * con_gets2_callback)(int keycode, char** pstr, int* pn,
|
||||
int* ppos);
|
||||
|
||||
void stdcall (*con_init)(dword wnd_width, dword wnd_height, dword scr_width, dword scr_height, const char* title) = 0;
|
||||
void stdcall (*con_exit)(int bCloseWindow) = 0;
|
||||
void stdcall (*con_set_title)(const char* title) = 0;
|
||||
void stdcall (*con_write_asciiz)(const char* str) = 0;
|
||||
void stdcall (*con_write_string)(const char* str, dword length) = 0;
|
||||
int cdecl (*con_printf)(const char* format, ...) = 0;
|
||||
dword stdcall (*con_get_flags)(void) = 0;
|
||||
dword stdcall (*con_set_flags)(dword new_flags) = 0;
|
||||
int stdcall (*con_get_font_height)(void) = 0;
|
||||
int stdcall (*con_get_cursor_height)(void) = 0;
|
||||
int stdcall (*con_set_cursor_height)(int new_height) = 0;
|
||||
int stdcall (*con_getch)(void) = 0;
|
||||
word stdcall (*con_getch2)(void) = 0;
|
||||
int stdcall (*con_kbhit)(void) = 0;
|
||||
char* stdcall (*con_gets)(char* str, int n) = 0;
|
||||
char* stdcall (*con_gets2)(con_gets2_callback callback, char* str, int n) = 0;
|
||||
void stdcall (*con_cls)() = 0;
|
||||
void stdcall (*con_get_cursor_pos)(int* px, int* py) = 0;
|
||||
void stdcall (*con_set_cursor_pos)(int x, int y) = 0;
|
||||
|
||||
const char lib_path[] = "/sys/lib/console.obj";
|
||||
|
||||
void* load_library(const char *name)
|
||||
{
|
||||
void *table;
|
||||
__asm__ __volatile__(
|
||||
"int $0x40"
|
||||
:"=a"(table)
|
||||
:"a"(68), "b"(19), "c"(name));
|
||||
return table;
|
||||
}
|
||||
|
||||
void *load_library_procedure(void *exports, const char *name)
|
||||
{
|
||||
if (exports == NULL) { return 0; }
|
||||
while (*(dword*)exports != 0)
|
||||
{
|
||||
char *str1 = (char*)(*(dword*)exports);
|
||||
if (strcmp(str1, name) == 0)
|
||||
{
|
||||
void *ptr = (void*)*(dword*)(exports + 4);
|
||||
return ptr;
|
||||
}
|
||||
exports += 8;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void output_debug_string(const char *s)
|
||||
{
|
||||
unsigned int i = 0;
|
||||
while(*(s + i))
|
||||
{
|
||||
asm volatile ("int $0x40"::"a"(63), "b"(1), "c"(*(s + i)));
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
void load_console()
|
||||
{
|
||||
void *lib = load_library(lib_path);
|
||||
|
||||
if (!lib)
|
||||
{
|
||||
output_debug_string("Console.obj loading error\r\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
dword (*start_lib)(dword) = (dword(*)(dword))load_library_procedure(lib, imports[0]);
|
||||
|
||||
version = (dword*)load_library_procedure(lib, imports[1]);
|
||||
|
||||
con_init = (void stdcall(*)(dword,dword,dword,dword,const char*))load_library_procedure(lib, imports[2]);
|
||||
con_write_asciiz = (void stdcall(*)(const char*))load_library_procedure(lib, imports[3]);
|
||||
con_write_string = (void stdcall(*)(const char*,dword))load_library_procedure(lib, imports[4]);
|
||||
con_printf = (int cdecl(*)(const char*,...))load_library_procedure(lib, imports[5]);
|
||||
con_exit = (void stdcall(*)(int))load_library_procedure(lib, imports[6]);
|
||||
con_get_flags = (dword stdcall(*)(void))load_library_procedure(lib, imports[7]);
|
||||
con_set_flags = (dword stdcall(*)(dword))load_library_procedure(lib, imports[8]);
|
||||
con_kbhit = (int stdcall(*)(void))load_library_procedure(lib, imports[9]);
|
||||
con_getch = (int stdcall(*)(void))load_library_procedure(lib, imports[10]);
|
||||
con_getch2 = (word stdcall(*)(void))load_library_procedure(lib, imports[11]);
|
||||
con_gets = (char* stdcall(*)(char*,int))load_library_procedure(lib, imports[12]);
|
||||
con_gets2 = (char* stdcall(*)(con_gets2_callback,char*,int))load_library_procedure(lib, imports[13]);
|
||||
con_get_font_height = (int stdcall(*)(void))load_library_procedure(lib, imports[14]);
|
||||
con_get_cursor_height = (int stdcall(*)(void))load_library_procedure(lib, imports[15]);
|
||||
con_set_cursor_height = (int stdcall(*)(int))load_library_procedure(lib, imports[16]);
|
||||
con_cls = (void stdcall(*)(void))load_library_procedure(lib, imports[17]);
|
||||
con_get_cursor_pos = (void stdcall(*)(int*,int*))load_library_procedure(lib, imports[18]);
|
||||
con_set_cursor_pos = (void stdcall(*)(int,int))load_library_procedure(lib, imports[19]);
|
||||
con_set_title = (void stdcall(*)(const char*))load_library_procedure(lib, imports[20]);
|
||||
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
186
contrib/other/uarm/cp15.c
Executable file
186
contrib/other/uarm/cp15.c
Executable file
@ -0,0 +1,186 @@
|
||||
#include "cp15.h"
|
||||
|
||||
|
||||
#define CPUID_PXA255 0x69052D06UL //spepping A0
|
||||
#define CPUID_PXA270 0x69054114UL //stepping C0
|
||||
|
||||
static Boolean cp15prvCoprocRegXferFunc(struct ArmCpu* cpu, void* userData, Boolean two, Boolean read, UInt8 op1, UInt8 Rx, UInt8 CRn, UInt8 CRm, UInt8 op2){
|
||||
|
||||
ArmCP15* cp15 = userData;
|
||||
UInt32 val = 0, tmp;
|
||||
|
||||
|
||||
if(!read) val = cpuGetRegExternal(cpu, Rx);
|
||||
|
||||
if(op1 != 0 || two) goto fail; //CP15 only accessed with MCR/MRC with op1 == 0
|
||||
|
||||
switch(CRn){
|
||||
|
||||
case 0: //ID codes
|
||||
|
||||
if(!read) goto fail; //cannot write to ID codes register
|
||||
if(CRm != 0) goto fail; //CRm must be zero for this read
|
||||
if(op2 == 0){ //main ID register
|
||||
|
||||
val = CPUID_PXA255;
|
||||
goto success;
|
||||
}
|
||||
else if(op2 == 1){ //cahce type register - we lie here
|
||||
|
||||
val = 0x0B16A16AUL;
|
||||
goto success;
|
||||
}
|
||||
break;
|
||||
|
||||
case 1: //control register
|
||||
|
||||
if(op2 == 0){
|
||||
if(read){
|
||||
val = cp15->control;
|
||||
}
|
||||
else{
|
||||
tmp = val ^ cp15->control; //see what changed and mask off then chack for what we support changing of
|
||||
if(tmp & 0x84F0UL){
|
||||
err_str("cp15: unknown bits changed 0x");
|
||||
err_hex(cp15->control);
|
||||
err_str("->0x");
|
||||
err_hex(val);
|
||||
err_str(", halting\r\n");
|
||||
while(true);
|
||||
}
|
||||
|
||||
if(tmp & 0x00002000UL){ // V bit
|
||||
|
||||
cpuSetVectorAddr(cp15->cpu, (val & 0x00002000UL) ? 0xFFFF0000UL : 0x00000000UL);
|
||||
cp15->control ^= 0x00002000UL;
|
||||
}
|
||||
if(tmp & 0x00000200UL){ // R bit
|
||||
|
||||
mmuSetR(cp15->mmu, (val & 0x00000200UL) != 0);
|
||||
cp15->control ^= 0x00000200UL;
|
||||
}
|
||||
if(tmp & 0x00000100UL){ // S bit
|
||||
|
||||
mmuSetS(cp15->mmu, (val & 0x00000100UL) != 0);
|
||||
cp15->control ^= 0x00000100UL;
|
||||
}
|
||||
if(tmp & 0x00000001UL){ // M bit
|
||||
|
||||
mmuSetTTP(cp15->mmu, (val & 0x00000001UL) ? cp15->ttb : MMU_DISABLED_TTP);
|
||||
mmuTlbFlush(cp15->mmu);
|
||||
cp15->control ^= 0x00000001UL;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
else if(op2 == 1){ //PXA-specific thing
|
||||
if(read) val = cp15->ACP;
|
||||
else cp15->ACP = val;
|
||||
}
|
||||
else break;
|
||||
goto success;
|
||||
|
||||
case 2: //translation tabler base
|
||||
if(read) val = cp15->ttb;
|
||||
else{
|
||||
if(cp15->control & 0x00000001UL){ //mmu is on
|
||||
|
||||
mmuSetTTP(cp15->mmu, val);
|
||||
mmuTlbFlush(cp15->mmu);
|
||||
}
|
||||
cp15->ttb = val;
|
||||
}
|
||||
goto success;
|
||||
|
||||
case 3: //domain access control
|
||||
if(read) val = mmuGetDomainCfg(cp15->mmu);
|
||||
else mmuSetDomainCfg(cp15->mmu, val);
|
||||
goto success;
|
||||
|
||||
case 5: //FSR
|
||||
if(read) val = cp15->FSR;
|
||||
else cp15->FSR = val;
|
||||
goto success;
|
||||
|
||||
case 6: //FAR
|
||||
if(read) val = cp15->FAR;
|
||||
else cp15->FAR = val;
|
||||
goto success;
|
||||
|
||||
case 7: //cache ops
|
||||
if((CRm == 5 || CRm == 7)&& op2 == 0) cpuIcacheInval(cp15->cpu); //invalidate entire {icache(5) or both i and dcache(7)}
|
||||
if((CRm == 5 || CRm == 7) && op2 == 1) cpuIcacheInvalAddr(cp15->cpu, val); //invalidate {icache(5) or both i and dcache(7)} line, given VA
|
||||
if((CRm == 5 || CRm == 7) && op2 == 2) cpuIcacheInval(cp15->cpu); //invalidate {icache(5) or both i and dcache(7)} line, given set/index. i dont know how to do this, so flush thee whole thing
|
||||
goto success;
|
||||
|
||||
case 8: //TLB ops
|
||||
mmuTlbFlush(cp15->mmu);
|
||||
goto success;
|
||||
|
||||
case 9: //cache lockdown
|
||||
if(CRm == 1 && op2 == 0){
|
||||
err_str("Attempt to lock 0x");
|
||||
err_hex(val);
|
||||
err_str("+32 in icache\r\n");
|
||||
}
|
||||
else if(CRm == 2 && op2 == 0){
|
||||
err_str("Dcache now ");
|
||||
err_str(val ? "in" : "out of");
|
||||
err_str(" lock mode\r\n");
|
||||
}
|
||||
goto success;
|
||||
|
||||
case 10: //TLB lockdown
|
||||
goto success;
|
||||
|
||||
case 13: //FCSE
|
||||
err_str("FCSE not supported\n");
|
||||
break;
|
||||
|
||||
case 15:
|
||||
if(op2 == 0 && CRm == 1){ //CPAR
|
||||
if(read) val = cpuGetCPAR(cp15->cpu);
|
||||
else cpuSetCPAR(cp15->cpu, val & 0x3FFF);
|
||||
goto success;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
fail:
|
||||
//TODO: cause invalid instruction trap in cpu
|
||||
return false;
|
||||
|
||||
success:
|
||||
|
||||
if(read) cpuSetReg(cpu, Rx, val);
|
||||
return true;
|
||||
}
|
||||
|
||||
void cp15Init(ArmCP15* cp15, ArmCpu* cpu, ArmMmu* mmu){
|
||||
|
||||
ArmCoprocessor cp;
|
||||
|
||||
cp.regXfer = cp15prvCoprocRegXferFunc;
|
||||
cp.dataProcessing = NULL;
|
||||
cp.memAccess = NULL;
|
||||
cp.twoRegF = NULL;
|
||||
cp.userData = cp15;
|
||||
|
||||
__mem_zero(cp15, sizeof(ArmCP15));
|
||||
cp15->cpu = cpu;
|
||||
cp15->mmu = mmu;
|
||||
cp15->control = 0x00004072UL;
|
||||
|
||||
cpuCoprocessorRegister(cpu, 15, &cp);
|
||||
}
|
||||
|
||||
void cp15Deinit(ArmCP15* cp15){
|
||||
|
||||
cpuCoprocessorUnregister(cp15->cpu, 15);
|
||||
}
|
||||
|
||||
void cp15SetFaultStatus(ArmCP15* cp15, UInt32 addr, UInt8 faultStatus){
|
||||
|
||||
cp15->FAR = addr;
|
||||
cp15->FSR = faultStatus;
|
||||
}
|
27
contrib/other/uarm/cp15.h
Executable file
27
contrib/other/uarm/cp15.h
Executable file
@ -0,0 +1,27 @@
|
||||
#ifndef _CP15_H_
|
||||
#define _CP15_H_
|
||||
|
||||
|
||||
#include "types.h"
|
||||
#include "CPU.h"
|
||||
#include "MMU.h"
|
||||
|
||||
typedef struct{
|
||||
|
||||
ArmCpu* cpu;
|
||||
ArmMmu* mmu;
|
||||
|
||||
UInt32 control;
|
||||
UInt32 ttb;
|
||||
UInt32 FSR; //fault sttaus register
|
||||
UInt32 FAR; //fault address register
|
||||
UInt32 CPAR; //coprocessor access register
|
||||
UInt32 ACP; //auxilary control reg for xscale
|
||||
}ArmCP15;
|
||||
|
||||
void cp15Init(ArmCP15* cp15, ArmCpu* cpu, ArmMmu* mmu);
|
||||
void cp15Deinit(ArmCP15* cp15);
|
||||
void cp15SetFaultStatus(ArmCP15* cp15, UInt32 addr, UInt8 faultStatus);
|
||||
|
||||
#endif
|
||||
|
173
contrib/other/uarm/cpu.h
Executable file
173
contrib/other/uarm/cpu.h
Executable file
@ -0,0 +1,173 @@
|
||||
#ifndef _CPU_H_
|
||||
#define _CPU_H_
|
||||
|
||||
|
||||
//#define ARM_V6 //define to allow v6 instructions
|
||||
//#define THUMB_2 //define to allow Thumb2
|
||||
|
||||
#include "types.h"
|
||||
|
||||
struct ArmCpu;
|
||||
|
||||
#define ARM_SR_N 0x80000000UL
|
||||
#define ARM_SR_Z 0x40000000UL
|
||||
#define ARM_SR_C 0x20000000UL
|
||||
#define ARM_SR_V 0x10000000UL
|
||||
#define ARM_SR_Q 0x08000000UL
|
||||
#ifdef ARM_V6 //V6KT2, but without T2 to be exact (we implement things like MLS, but not Thumb2 or ThumbEE)
|
||||
#define ARM_SR_J 0x01000000UL
|
||||
#define ARM_SR_E 0x00000200UL
|
||||
#define ARM_SR_A 0x00000100UL
|
||||
#define ARM_SR_GE_0 0x00010000UL
|
||||
#define ARM_SR_GE_1 0x00020000UL
|
||||
#define ARM_SR_GE_2 0x00040000UL
|
||||
#define ARM_SR_GE_3 0x00080000UL
|
||||
#define ARM_SR_GE_MASK 0x000F0000UL
|
||||
#define ARM_SR_GE_SHIFT 16
|
||||
#endif
|
||||
#define ARM_SR_I 0x00000080UL
|
||||
#define ARM_SR_F 0x00000040UL
|
||||
#define ARM_SR_T 0x00000020UL
|
||||
#define ARM_SR_M 0x0000001FUL
|
||||
|
||||
#define ARM_SR_MODE_USR 0x00000010UL
|
||||
#define ARM_SR_MODE_FIQ 0x00000011UL
|
||||
#define ARM_SR_MODE_IRQ 0x00000012UL
|
||||
#define ARM_SR_MODE_SVC 0x00000013UL
|
||||
#define ARM_SR_MODE_ABT 0x00000017UL
|
||||
#define ARM_SR_MODE_UND 0x0000001BUL
|
||||
#define ARM_SR_MODE_SYS 0x0000001FUL
|
||||
|
||||
#define ARV_VECTOR_OFFT_RST 0x00000000UL
|
||||
#define ARM_VECTOR_OFFT_UND 0x00000004UL
|
||||
#define ARM_VECTOR_OFFT_SWI 0x00000008UL
|
||||
#define ARM_VECTOR_OFFT_P_ABT 0x0000000CUL
|
||||
#define ARM_VECTOR_OFFT_D_ABT 0x00000010UL
|
||||
#define ARM_VECTOR_OFFT_UNUSED 0x00000014UL
|
||||
#define ARM_VECTOR_OFFT_IRQ 0x00000018UL
|
||||
#define ARM_VECTOR_OFFT_FIQ 0x0000001CUL
|
||||
|
||||
#define HYPERCALL_ARM 0xF7BBBBBBUL
|
||||
#define HYPERCALL_THUMB 0xBBBBUL
|
||||
|
||||
//the following are for cpuGetRegExternal() and are generally used for debugging purposes
|
||||
#define ARM_REG_NUM_CPSR 16
|
||||
#define ARM_REG_NUM_SPSR 17
|
||||
|
||||
struct ArmCpu;
|
||||
|
||||
typedef Boolean (*ArmCoprocRegXferF) (struct ArmCpu* cpu, void* userData, Boolean two/* MCR2/MRC2 ? */, Boolean MRC, UInt8 op1, UInt8 Rx, UInt8 CRn, UInt8 CRm, UInt8 op2);
|
||||
typedef Boolean (*ArmCoprocDatProcF) (struct ArmCpu* cpu, void* userData, Boolean two/* CDP2 ? */, UInt8 op1, UInt8 CRd, UInt8 CRn, UInt8 CRm, UInt8 op2);
|
||||
typedef Boolean (*ArmCoprocMemAccsF) (struct ArmCpu* cpu, void* userData, Boolean two /* LDC2/STC2 ? */, Boolean N, Boolean store, UInt8 CRd, UInt32 addr, UInt8* option /* NULL if none */);
|
||||
typedef Boolean (*ArmCoprocTwoRegF) (struct ArmCpu* cpu, void* userData, Boolean MRRC, UInt8 op, UInt8 Rd, UInt8 Rn, UInt8 CRm);
|
||||
|
||||
typedef Boolean (*ArmCpuMemF) (struct ArmCpu* cpu, void* buf, UInt32 vaddr, UInt8 size, Boolean write, Boolean priviledged, UInt8* fsr); //read/write
|
||||
typedef Boolean (*ArmCpuHypercall) (struct ArmCpu* cpu); //return true if handled
|
||||
typedef void (*ArmCpuEmulErr) (struct ArmCpu* cpu, const char* err_str);
|
||||
|
||||
typedef void (*ArmSetFaultAdrF) (struct ArmCpu* cpu, UInt32 adr, UInt8 faultStatus);
|
||||
|
||||
#include "icache.h"
|
||||
|
||||
|
||||
/*
|
||||
|
||||
coprocessors:
|
||||
|
||||
0 - DSP (pxa only)
|
||||
0, 1 - WMMX (pxa only)
|
||||
11 - VFP (arm standard)
|
||||
15 - system control (arm standard)
|
||||
*/
|
||||
|
||||
|
||||
typedef struct{
|
||||
|
||||
ArmCoprocRegXferF regXfer;
|
||||
ArmCoprocDatProcF dataProcessing;
|
||||
ArmCoprocMemAccsF memAccess;
|
||||
ArmCoprocTwoRegF twoRegF;
|
||||
void* userData;
|
||||
|
||||
}ArmCoprocessor;
|
||||
|
||||
typedef struct{
|
||||
|
||||
UInt32 R13, R14;
|
||||
UInt32 SPSR; //usr mode doesn't have an SPSR
|
||||
}ArmBankedRegs;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
typedef struct ArmCpu{
|
||||
|
||||
UInt32 regs[16]; //current active regs as per current mode
|
||||
UInt32 CPSR, SPSR;
|
||||
|
||||
ArmBankedRegs bank_usr; //usr regs when in another mode
|
||||
ArmBankedRegs bank_svc; //svc regs when in another mode
|
||||
ArmBankedRegs bank_abt; //abt regs when in another mode
|
||||
ArmBankedRegs bank_und; //und regs when in another mode
|
||||
ArmBankedRegs bank_irq; //irq regs when in another mode
|
||||
ArmBankedRegs bank_fiq; //fiq regs when in another mode
|
||||
UInt32 extra_regs[5]; //fiq regs when not in fiq mode, usr regs when in fiq mode. R8-12
|
||||
|
||||
UInt16 waitingIrqs;
|
||||
UInt16 waitingFiqs;
|
||||
UInt16 CPAR;
|
||||
|
||||
ArmCoprocessor coproc[16]; //coprocessors
|
||||
|
||||
// various other cpu config options
|
||||
UInt32 vectorBase; //address of vector base
|
||||
|
||||
#ifdef ARM_V6
|
||||
|
||||
Boolean EEE; //endianness one exception entry
|
||||
Boolean impreciseAbtWaiting;
|
||||
#endif
|
||||
|
||||
ArmCpuMemF memF;
|
||||
ArmCpuEmulErr emulErrF;
|
||||
ArmCpuHypercall hypercallF;
|
||||
ArmSetFaultAdrF setFaultAdrF;
|
||||
|
||||
icache ic;
|
||||
|
||||
void* userData; //shared by all callbacks
|
||||
}ArmCpu;
|
||||
|
||||
|
||||
Err cpuInit(ArmCpu* cpu, UInt32 pc, ArmCpuMemF memF, ArmCpuEmulErr emulErrF, ArmCpuHypercall hypercallF, ArmSetFaultAdrF setFaultAdrF);
|
||||
Err cpuDeinit(ArmCpu* cp);
|
||||
void cpuCycle(ArmCpu* cpu);
|
||||
void cpuIrq(ArmCpu* cpu, Boolean fiq, Boolean raise); //unraise when acknowledged
|
||||
|
||||
#ifdef ARM_V6
|
||||
|
||||
void cpuSignalImpreciseAbt(ArmCpu* cpu, Boolean raise);
|
||||
|
||||
#endif
|
||||
|
||||
UInt32 cpuGetRegExternal(ArmCpu* cpu, UInt8 reg);
|
||||
void cpuSetReg(ArmCpu* cpu, UInt8 reg, UInt32 val);
|
||||
|
||||
void cpuCoprocessorRegister(ArmCpu* cpu, UInt8 cpNum, ArmCoprocessor* coproc);
|
||||
void cpuCoprocessorUnregister(ArmCpu* cpu, UInt8 cpNum);
|
||||
|
||||
void cpuSetVectorAddr(ArmCpu* cpu, UInt32 adr);
|
||||
|
||||
UInt16 cpuGetCPAR(ArmCpu* cpu);
|
||||
void cpuSetCPAR(ArmCpu* cpu, UInt16 cpar);
|
||||
|
||||
void cpuIcacheInval(ArmCpu* cpu);
|
||||
void cpuIcacheInvalAddr(ArmCpu* cpu, UInt32 addr);
|
||||
|
||||
|
||||
#endif
|
||||
|
155
contrib/other/uarm/dcache.c
Executable file
155
contrib/other/uarm/dcache.c
Executable file
@ -0,0 +1,155 @@
|
||||
#include "types.h"
|
||||
#include "CPU.h"
|
||||
#include "dcache.h"
|
||||
|
||||
//#define DCACHE_DEBUGGING
|
||||
|
||||
|
||||
|
||||
#ifdef DCACHE_DEBUGGING
|
||||
#define _dcache_fetch_func dcacheFetch_
|
||||
#define _dcache_test_func dcacheFetch
|
||||
#else
|
||||
#define _dcache_fetch_func dcacheFetch
|
||||
#define _dcache_test_func dcacheFetch_test
|
||||
#endif
|
||||
|
||||
void dcacheInval(dcache* dc){
|
||||
|
||||
UInt8 i, j;
|
||||
|
||||
for(i = 0; i < DCACHE_BUCKET_NUM; i++){
|
||||
for(j = 0; j < DCACHE_BUCKET_SZ; j++) dc->lines[i][j].info = 0;
|
||||
dc->ptr[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void dcacheInit(dcache* dc, ArmCpu* cpu, ArmCpuMemF memF){
|
||||
|
||||
dc->cpu = cpu;
|
||||
dc->memF = memF;
|
||||
|
||||
dcacheInval(dc);
|
||||
}
|
||||
|
||||
|
||||
static UInt8 dcachePrvHash(UInt32 addr){
|
||||
|
||||
addr >>= DCACHE_L;
|
||||
addr &= (1UL << DCACHE_S) - 1UL;
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
void dcacheInvalAddr(dcache* dc, UInt32 va){
|
||||
|
||||
UInt32 off = va % DCACHE_LINE_SZ;
|
||||
Int8 i, j, bucket;
|
||||
dcacheLine* lines;
|
||||
|
||||
va -= off;
|
||||
|
||||
bucket = dcachePrvHash(va);
|
||||
lines = dc->lines[bucket];
|
||||
|
||||
for(i = 0, j = dc->ptr[bucket]; i < DCACHE_BUCKET_SZ; i++){
|
||||
|
||||
if(--j == -1) j = DCACHE_BUCKET_SZ - 1;
|
||||
|
||||
if((lines[j].info & (DCACHE_ADDR_MASK | DCACHE_USED_MASK)) == (va | DCACHE_USED_MASK)){ //found it!
|
||||
|
||||
lines[j].info = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void dcacheFlush(dcache* dc){
|
||||
|
||||
|
||||
}
|
||||
|
||||
void dcacheFlushAddr(dcache* dc, UInt32 va){
|
||||
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
we cannot have data overlap cachelines since data is self aligned (word on 4-byte boundary, halfwords on2, etc. this is enforced elsewhere
|
||||
*/
|
||||
|
||||
Boolean dcacheWrite(dcache* dc, UInt32 va, UInt8 sz, Boolean priviledged, UInt8* fsrP, void* buf){
|
||||
|
||||
|
||||
}
|
||||
|
||||
Boolean _dcache_fetch_func(dcache* dc, UInt32 va, UInt8 sz, Boolean priviledged, UInt8* fsrP, void* buf){
|
||||
|
||||
UInt32 off = va % DCACHE_LINE_SZ;
|
||||
Int8 i, j, bucket;
|
||||
dcacheLine* lines;
|
||||
dcacheLine* line;
|
||||
|
||||
va -= off;
|
||||
|
||||
bucket = dcachePrvHash(va);
|
||||
lines = dc->lines[bucket];
|
||||
|
||||
for(i = 0, j = dc->ptr[bucket]; i < DCACHE_BUCKET_SZ; i++){
|
||||
|
||||
if(--j == -1) j = DCACHE_BUCKET_SZ - 1;
|
||||
|
||||
if((lines[j].info & (DCACHE_ADDR_MASK | DCACHE_USED_MASK)) == (va | DCACHE_USED_MASK)){ //found it!
|
||||
|
||||
if(sz == 4){
|
||||
*(UInt32*)buf = *(UInt32*)(lines[j].data + off);
|
||||
}
|
||||
else if(sz == 2){
|
||||
*(UInt16*)buf = *(UInt16*)(lines[j].data + off);
|
||||
}
|
||||
else __mem_copy(buf, lines[j].data + off, sz);
|
||||
return priviledged || !(lines[j].info & DCACHE_PRIV_MASK);
|
||||
}
|
||||
}
|
||||
//if we're here, we found nothing - time to populate the cache
|
||||
j = dc->ptr[bucket]++;
|
||||
if(dc->ptr[bucket] == DCACHE_BUCKET_SZ) dc->ptr[bucket] = 0;
|
||||
line = lines + j;
|
||||
|
||||
line->info = va | (priviledged ? DCACHE_PRIV_MASK : 0);
|
||||
if(!dc->memF(dc->cpu, line->data, va, DCACHE_LINE_SZ, false, priviledged, fsrP)){
|
||||
|
||||
return false;
|
||||
}
|
||||
line->info |= DCACHE_USED_MASK;
|
||||
|
||||
if(sz == 4){
|
||||
*(UInt32*)buf = *(UInt32*)(line->data + off);
|
||||
}
|
||||
else if(sz == 2){
|
||||
*(UInt16*)buf = *(UInt16*)(line->data + off);
|
||||
}
|
||||
else __mem_copy(buf, line->data + off, sz);
|
||||
return true;
|
||||
}
|
||||
|
||||
#include "stdio.h"
|
||||
Boolean _dcache_test_func(dcache* dc, UInt32 va, UInt8 sz, Boolean priviledged, UInt8* fsrP, void* buf){
|
||||
|
||||
UInt8 fsrO = -1, fsrT = -1;
|
||||
UInt8 dataO[4] = {0}, dataT[4] = {0};
|
||||
Boolean retO, retT;
|
||||
UInt8 i;
|
||||
|
||||
retO = _dcache_fetch_func(dc, va, sz, priviledged, &fsrO, dataO);
|
||||
retT = dc->memF(dc->cpu, dataT, va, sz, false, priviledged, &fsrT);
|
||||
|
||||
if((retT != retO) || (fsrT != fsrO) || (dataT[0] != dataO[0]) || (dataT[1] != dataO[1]) || (dataT[2] != dataO[2]) || (dataT[3] != dataO[3])){
|
||||
|
||||
fprintf(stderr, "dcache fail!");
|
||||
}
|
||||
|
||||
for(i = 0; i < sz; i++) ((UInt8*)buf)[i] = dataT[i];
|
||||
if(retT) *fsrP = fsrT;
|
||||
return retT;
|
||||
}
|
||||
|
49
contrib/other/uarm/dcache.h
Executable file
49
contrib/other/uarm/dcache.h
Executable file
@ -0,0 +1,49 @@
|
||||
#ifndef _DCACHE_H_
|
||||
#define _DCACHE_H_
|
||||
|
||||
|
||||
#include "types.h"
|
||||
#include "CPU.h"
|
||||
|
||||
|
||||
#define DCACHE_L 5UL //line size is 2^L bytes
|
||||
#define DCACHE_S 6UL //number of sets is 2^S
|
||||
#define DCACHE_A 4UL //set associativity
|
||||
|
||||
#define DCACHE_LINE_SZ (1UL << ICACHE_L)
|
||||
#define DCACHE_BUCKET_NUM (1UL << ICACHE_S)
|
||||
#define DCACHE_BUCKET_SZ (ICACHE_A)
|
||||
|
||||
|
||||
#define DCACHE_ADDR_MASK ((UInt32)-ICACHE_LINE_SZ)
|
||||
#define DCACHE_USED_MASK 1
|
||||
#define DCACHE_PRIV_MASK 2
|
||||
|
||||
typedef struct{
|
||||
|
||||
UInt32 info; //addr, masks
|
||||
UInt8 data[DCACHE_LINE_SZ];
|
||||
|
||||
}dcacheLine;
|
||||
|
||||
typedef struct{
|
||||
|
||||
struct ArmCpu* cpu;
|
||||
ArmCpuMemF memF;
|
||||
dcacheLine lines[DCACHE_BUCKET_NUM][DCACHE_BUCKET_SZ];
|
||||
UInt8 ptr[DCACHE_BUCKET_NUM];
|
||||
|
||||
}dcache;
|
||||
|
||||
|
||||
void dcacheInit(dcache* ic, struct ArmCpu* cpu, ArmCpuMemF memF);
|
||||
Boolean dcacheFetch(dcache* ic, UInt32 va, UInt8 sz, Boolean priviledged, UInt8* fsr, void* buf);
|
||||
Boolean dcacheWrite(dcache* ic, UInt32 va, UInt8 sz, Boolean priviledged, UInt8* fsr, void* buf);
|
||||
void dcacheFlush(dcache* ic);
|
||||
void dcacheFlushAddr(dcache* ic, UInt32 addr);
|
||||
void dcacheInval(dcache* ic);
|
||||
void dcacheInvalAddr(dcache* ic, UInt32 addr);
|
||||
|
||||
|
||||
|
||||
#endif
|
140
contrib/other/uarm/icache.c
Executable file
140
contrib/other/uarm/icache.c
Executable file
@ -0,0 +1,140 @@
|
||||
#include "types.h"
|
||||
#include "CPU.h"
|
||||
#include "icache.h"
|
||||
|
||||
//#define ICACHE_DEBUGGING
|
||||
|
||||
|
||||
|
||||
#ifdef ICACHE_DEBUGGING
|
||||
#define _icache_fetch_func icacheFetch_
|
||||
#define _icache_test_func icacheFetch
|
||||
#else
|
||||
#define _icache_fetch_func icacheFetch
|
||||
#define _icache_test_func icacheFetch_test
|
||||
#endif
|
||||
|
||||
void icacheInval(icache* ic){
|
||||
|
||||
UInt8 i, j;
|
||||
|
||||
for(i = 0; i < ICACHE_BUCKET_NUM; i++){
|
||||
for(j = 0; j < ICACHE_BUCKET_SZ; j++) ic->lines[i][j].info = 0;
|
||||
ic->ptr[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void icacheInit(icache* ic, ArmCpu* cpu, ArmCpuMemF memF){
|
||||
|
||||
ic->cpu = cpu;
|
||||
ic->memF = memF;
|
||||
|
||||
icacheInval(ic);
|
||||
}
|
||||
|
||||
|
||||
static UInt8 icachePrvHash(UInt32 addr){
|
||||
|
||||
addr >>= ICACHE_L;
|
||||
addr &= (1UL << ICACHE_S) - 1UL;
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
void icacheInvalAddr(icache* ic, UInt32 va){
|
||||
|
||||
UInt32 off = va % ICACHE_LINE_SZ;
|
||||
Int8 i, j, bucket;
|
||||
icacheLine* lines;
|
||||
|
||||
va -= off;
|
||||
|
||||
bucket = icachePrvHash(va);
|
||||
lines = ic->lines[bucket];
|
||||
|
||||
for(i = 0, j = ic->ptr[bucket]; (UInt8)i < ICACHE_BUCKET_SZ; i++){
|
||||
|
||||
if(--j == -1) j = ICACHE_BUCKET_SZ - 1;
|
||||
|
||||
if((lines[j].info & (ICACHE_ADDR_MASK | ICACHE_USED_MASK)) == (va | ICACHE_USED_MASK)){ //found it!
|
||||
|
||||
lines[j].info = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
we cannot have data overlap cachelines since data is self aligned (word on 4-byte boundary, halfwords on2, etc. this is enforced elsewhere
|
||||
*/
|
||||
|
||||
Boolean _icache_fetch_func(icache* ic, UInt32 va, UInt8 sz, Boolean priviledged, UInt8* fsrP, void* buf){
|
||||
|
||||
UInt32 off = va % ICACHE_LINE_SZ;
|
||||
Int8 i, j, bucket;
|
||||
icacheLine* lines;
|
||||
icacheLine* line;
|
||||
|
||||
va -= off;
|
||||
|
||||
bucket = icachePrvHash(va);
|
||||
lines = ic->lines[bucket];
|
||||
|
||||
for(i = 0, j = ic->ptr[bucket]; (UInt8)i < ICACHE_BUCKET_SZ; i++){
|
||||
|
||||
if(--j == -1) j = ICACHE_BUCKET_SZ - 1;
|
||||
|
||||
if((lines[j].info & (ICACHE_ADDR_MASK | ICACHE_USED_MASK)) == (va | ICACHE_USED_MASK)){ //found it!
|
||||
|
||||
if(sz == 4){
|
||||
*(UInt32*)buf = *(UInt32*)(lines[j].data + off);
|
||||
}
|
||||
else if(sz == 2){
|
||||
*(UInt16*)buf = *(UInt16*)(lines[j].data + off);
|
||||
}
|
||||
else __mem_copy(buf, lines[j].data + off, sz);
|
||||
return priviledged || !(lines[j].info & ICACHE_PRIV_MASK);
|
||||
}
|
||||
}
|
||||
//if we're here, we found nothing - time to populate the cache
|
||||
j = ic->ptr[bucket]++;
|
||||
if(ic->ptr[bucket] == ICACHE_BUCKET_SZ) ic->ptr[bucket] = 0;
|
||||
line = lines + j;
|
||||
|
||||
line->info = va | (priviledged ? ICACHE_PRIV_MASK : 0);
|
||||
if(!ic->memF(ic->cpu, line->data, va, ICACHE_LINE_SZ, false, priviledged, fsrP)){
|
||||
|
||||
return false;
|
||||
}
|
||||
line->info |= ICACHE_USED_MASK;
|
||||
|
||||
if(sz == 4){
|
||||
*(UInt32*)buf = *(UInt32*)(line->data + off);
|
||||
}
|
||||
else if(sz == 2){
|
||||
*(UInt16*)buf = *(UInt16*)(line->data + off);
|
||||
}
|
||||
else __mem_copy(buf, line->data + off, sz);
|
||||
return true;
|
||||
}
|
||||
|
||||
#include "stdio.h"
|
||||
Boolean _icache_test_func(icache* ic, UInt32 va, UInt8 sz, Boolean priviledged, UInt8* fsrP, void* buf){
|
||||
|
||||
UInt8 fsrO = -1, fsrT = -1;
|
||||
UInt8 dataO[4] = {0}, dataT[4] = {0};
|
||||
Boolean retO, retT;
|
||||
UInt8 i;
|
||||
|
||||
retO = _icache_fetch_func(ic, va, sz, priviledged, &fsrO, dataO);
|
||||
retT = ic->memF(ic->cpu, dataT, va, sz, false, priviledged, &fsrT);
|
||||
|
||||
if((retT != retO) || (fsrT != fsrO) || (dataT[0] != dataO[0]) || (dataT[1] != dataO[1]) || (dataT[2] != dataO[2]) || (dataT[3] != dataO[3])){
|
||||
|
||||
fprintf(stderr, "icache fail!");
|
||||
}
|
||||
|
||||
for(i = 0; i < sz; i++) ((UInt8*)buf)[i] = dataT[i];
|
||||
if(retT) *fsrP = fsrT;
|
||||
return retT;
|
||||
}
|
||||
|
47
contrib/other/uarm/icache.h
Executable file
47
contrib/other/uarm/icache.h
Executable file
@ -0,0 +1,47 @@
|
||||
#ifndef _ICACHE_H_
|
||||
#define _ICACHE_H_
|
||||
|
||||
|
||||
#include "types.h"
|
||||
#include "CPU.h"
|
||||
|
||||
|
||||
#define ICACHE_L 4UL //line size is 2^L bytes
|
||||
#define ICACHE_S 6UL //number of sets is 2^S
|
||||
#define ICACHE_A 6UL //set associativity
|
||||
|
||||
|
||||
#define ICACHE_LINE_SZ (1UL << ICACHE_L)
|
||||
#define ICACHE_BUCKET_NUM (1UL << ICACHE_S)
|
||||
#define ICACHE_BUCKET_SZ (ICACHE_A)
|
||||
|
||||
|
||||
#define ICACHE_ADDR_MASK ((UInt32)-ICACHE_LINE_SZ)
|
||||
#define ICACHE_USED_MASK 1UL
|
||||
#define ICACHE_PRIV_MASK 2UL
|
||||
|
||||
typedef struct{
|
||||
|
||||
UInt32 info; //addr, masks
|
||||
UInt8 data[ICACHE_LINE_SZ];
|
||||
|
||||
}icacheLine;
|
||||
|
||||
typedef struct{
|
||||
|
||||
struct ArmCpu* cpu;
|
||||
ArmCpuMemF memF;
|
||||
icacheLine lines[ICACHE_BUCKET_NUM][ICACHE_BUCKET_SZ];
|
||||
UInt8 ptr[ICACHE_BUCKET_NUM];
|
||||
|
||||
}icache;
|
||||
|
||||
|
||||
void icacheInit(icache* ic, struct ArmCpu* cpu, ArmCpuMemF memF);
|
||||
Boolean icacheFetch(icache* ic, UInt32 va, UInt8 sz, Boolean priviledged, UInt8* fsr, void* buf);
|
||||
void icacheInval(icache* ic);
|
||||
void icacheInvalAddr(icache* ic, UInt32 addr);
|
||||
|
||||
|
||||
|
||||
#endif
|
250
contrib/other/uarm/main_pc.c
Executable file
250
contrib/other/uarm/main_pc.c
Executable file
@ -0,0 +1,250 @@
|
||||
#include "SoC.h"
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
//#include <sys/select.h>
|
||||
#include <signal.h>
|
||||
//#include <termios.h>
|
||||
#include "console_obj.h"
|
||||
|
||||
#define getch2 con_getch
|
||||
#define cprintf printf
|
||||
|
||||
#define off64_t off_t
|
||||
unsigned char* readFile(const char* name, UInt32* lenP){
|
||||
|
||||
long len = 0;
|
||||
unsigned char *r = NULL;
|
||||
int i;
|
||||
FILE* f;
|
||||
|
||||
f = fopen(name, "r");
|
||||
if(!f){
|
||||
perror("cannot open file");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
i = fseek(f, 0, SEEK_END);
|
||||
if(i){
|
||||
return NULL;
|
||||
perror("cannot seek to end");
|
||||
}
|
||||
|
||||
len = ftell(f);
|
||||
if(len < 0){
|
||||
perror("cannot get position");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
i = fseek(f, 0, SEEK_SET);
|
||||
if(i){
|
||||
return NULL;
|
||||
perror("cannot seek to start");
|
||||
}
|
||||
|
||||
|
||||
r = malloc(len);
|
||||
if(!r){
|
||||
perror("cannot alloc memory");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(len != (long)fread(r, 1, len, f)){
|
||||
perror("canot read file");
|
||||
free(r);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*lenP = len;
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int ctlCSeen = 0;
|
||||
|
||||
static int readchar(void){
|
||||
|
||||
struct timeval tv;
|
||||
fd_set set;
|
||||
char c;
|
||||
char tmp[20];
|
||||
int ret = CHAR_NONE;
|
||||
|
||||
// if(ctlCSeen){
|
||||
//ctlCSeen = 0;
|
||||
//return 0x03;
|
||||
//}
|
||||
|
||||
//tv.tv_sec = 0;
|
||||
//tv.tv_usec = 0;
|
||||
|
||||
//FD_ZERO(&set);
|
||||
//FD_SET(0, &set);
|
||||
|
||||
//i = 1; //(1, &set, NULL, NULL, &tv);
|
||||
if(con_kbhit()){
|
||||
|
||||
ret = getch2();
|
||||
if (ret==0xD) {ret=0xA;}
|
||||
}
|
||||
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void writechar(int chr){
|
||||
|
||||
if(!(chr & 0xFF00)){
|
||||
|
||||
cprintf("%c", chr);
|
||||
}
|
||||
else{
|
||||
cprintf("<<~~ EC_0x%x ~~>>", chr);
|
||||
}
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
void ctl_cHandler(_UNUSED_ int v){ //handle SIGTERM
|
||||
|
||||
// exit(-1);
|
||||
ctlCSeen = 1;
|
||||
}
|
||||
|
||||
int rootOps(void* userData, UInt32 sector, void* buf, UInt8 op){
|
||||
|
||||
FILE* root = userData;
|
||||
int i;
|
||||
|
||||
switch(op){
|
||||
case BLK_OP_SIZE:
|
||||
|
||||
if(sector == 0){ //num blocks
|
||||
|
||||
if(root){
|
||||
|
||||
i = fseek(root, 0, SEEK_END);
|
||||
if(i) return false;
|
||||
|
||||
*(unsigned long*)buf = (off64_t)ftell(root) / (off64_t)BLK_DEV_BLK_SZ;
|
||||
}
|
||||
else{
|
||||
|
||||
*(unsigned long*)buf = 0;
|
||||
}
|
||||
}
|
||||
else if(sector == 1){ //block size
|
||||
|
||||
*(unsigned long*)buf = BLK_DEV_BLK_SZ;
|
||||
}
|
||||
else return 0;
|
||||
return 1;
|
||||
|
||||
case BLK_OP_READ:
|
||||
|
||||
i = fseek(root, (off64_t)sector * (off64_t)BLK_DEV_BLK_SZ, SEEK_SET);
|
||||
if(i) return false;
|
||||
return fread(buf, 1, BLK_DEV_BLK_SZ, root) == BLK_DEV_BLK_SZ;
|
||||
|
||||
case BLK_OP_WRITE:
|
||||
|
||||
i = fseek(root, (off64_t)sector * (off64_t)BLK_DEV_BLK_SZ, SEEK_SET);
|
||||
if(i) return false;
|
||||
return fwrite(buf, 1, BLK_DEV_BLK_SZ, root) == BLK_DEV_BLK_SZ;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
SoC soc;
|
||||
|
||||
int main(int argc, char** argv){
|
||||
load_console();
|
||||
con_set_title("uARM");
|
||||
//CONSOLE_INIT("CONSOLE");
|
||||
|
||||
/*
|
||||
struct termios cfg, old;
|
||||
*/
|
||||
FILE* root = NULL;
|
||||
int gdbPort = 0;
|
||||
|
||||
if(argc != 3 && argc != 2){
|
||||
fprintf(stderr,"usage: %s path_to_disk [gdbPort]\n", argv[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
//setup the terminal
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = 0; //tcgetattr(0, &old);
|
||||
//cfg = old;
|
||||
if(ret) perror("cannot get term attrs");
|
||||
|
||||
/* #ifndef _DARWIN_
|
||||
|
||||
cfg.c_iflag &=~ (INLCR | INPCK | ISTRIP | IUCLC | IXANY | IXOFF | IXON);
|
||||
cfg.c_oflag &=~ (OPOST | OLCUC | ONLCR | OCRNL | ONOCR | ONLRET);
|
||||
cfg.c_lflag &=~ (ECHO | ECHOE | ECHONL | ICANON | IEXTEN | XCASE);
|
||||
#else */
|
||||
// cfmakeraw(&cfg);
|
||||
//#endif
|
||||
|
||||
ret = 0; //tcsetattr(0, TCSANOW, &cfg);
|
||||
if(ret) perror("cannot set term attrs");
|
||||
}
|
||||
|
||||
root = fopen(argv[1], "r+b");
|
||||
if(!root){
|
||||
fprintf(stderr,"Failed to open root device\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
fprintf(stderr,"Stderror ready\n");
|
||||
|
||||
if(argc >= 3) gdbPort = atoi(argv[2]);
|
||||
|
||||
socInit(&soc, socRamModeAlloc, NULL, readchar, writechar, rootOps, root);
|
||||
//(SIGINT, &ctl_cHandler);
|
||||
socRun(&soc, gdbPort);
|
||||
|
||||
fclose(root);
|
||||
//tcsetattr(0, TCSANOW, &old);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//////// runtime things
|
||||
|
||||
void* emu_alloc(UInt32 size){
|
||||
|
||||
return calloc(size,1);
|
||||
}
|
||||
|
||||
void emu_free(void* ptr){
|
||||
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
UInt32 rtcCurTime(void){
|
||||
|
||||
struct timeval tv;
|
||||
|
||||
gettimeofday(&tv, NULL);
|
||||
|
||||
return tv.tv_sec;
|
||||
}
|
||||
|
||||
void err_str(const char* str){
|
||||
|
||||
printf( "%s", str);
|
||||
}
|
||||
|
197
contrib/other/uarm/math64.c
Executable file
197
contrib/other/uarm/math64.c
Executable file
@ -0,0 +1,197 @@
|
||||
#include "math64.h"
|
||||
|
||||
#ifndef COMPILER_SUPPORTS_LONG_LONG
|
||||
|
||||
|
||||
|
||||
UInt64 u64_from_halves(UInt32 hi, UInt32 lo){
|
||||
|
||||
UInt64 r;
|
||||
|
||||
r.lo = lo;
|
||||
r.hi = hi;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
UInt64 u64_32_to_64(UInt32 v){
|
||||
|
||||
UInt64 r;
|
||||
|
||||
r.hi = 0;
|
||||
r.lo = v;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
UInt32 u64_64_to_32(UInt64 v){
|
||||
|
||||
return v.lo;
|
||||
}
|
||||
|
||||
UInt32 u64_get_hi(UInt64 v){
|
||||
|
||||
return v.hi;
|
||||
}
|
||||
|
||||
UInt64 u64_add(UInt64 a, UInt64 b){
|
||||
|
||||
UInt64 r;
|
||||
|
||||
r.lo = a.lo + b.lo;
|
||||
r.hi = a.hi + b.hi;
|
||||
if(r.lo < a.lo) r.hi++;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
UInt64 u64_add32(UInt64 a, UInt32 b){
|
||||
|
||||
UInt64 r;
|
||||
|
||||
r.lo = a.lo + b;
|
||||
r.hi = a.hi;
|
||||
if(r.lo < a.lo) r.hi++;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
UInt64 u64_umul3232(UInt32 a, UInt32 b){
|
||||
|
||||
UInt64 r;
|
||||
UInt32 ah, al, bh, bl;
|
||||
|
||||
ah = a >> 16;
|
||||
al = a & 0xFFFFUL;
|
||||
bh = b >> 16;
|
||||
bl = b & 0xFFFFUL;
|
||||
|
||||
r = u64_shl(u64_32_to_64(ah * bh), 16);
|
||||
r = u64_add32(r, ah * bl);
|
||||
r = u64_add32(r, al * bh);
|
||||
r = u64_add32(u64_shl(r, 16), al * bl);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
UInt64 u64_smul3232(Int32 a, Int32 b){
|
||||
|
||||
Boolean negative = false;
|
||||
UInt64 r;
|
||||
|
||||
if(a < 0){
|
||||
a = -a;
|
||||
negative = !negative;
|
||||
}
|
||||
|
||||
if(b < 0){
|
||||
b = -b;
|
||||
negative = !negative;
|
||||
}
|
||||
|
||||
r = u64_umul3232(a, b);
|
||||
|
||||
if(negative){
|
||||
|
||||
r.hi = ~r.hi; //negate r
|
||||
r.lo = ~r.lo;
|
||||
r = u64_inc(r);
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
UInt64 u64_shr(UInt64 v, unsigned bits){
|
||||
|
||||
UInt64 a = v;
|
||||
|
||||
while(bits >= 32){
|
||||
a.lo = a.hi;
|
||||
a.hi = 0;
|
||||
bits -= 32;
|
||||
}
|
||||
|
||||
a.lo = (a.lo >> bits) + (a.hi << (32 - bits));
|
||||
a.hi >>= bits;
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
UInt64 u64_shl(UInt64 v, unsigned bits){
|
||||
|
||||
UInt64 a = v;
|
||||
|
||||
while(bits >= 32){
|
||||
a.hi = a.lo;
|
||||
a.lo = 0;
|
||||
bits -= 32;
|
||||
}
|
||||
|
||||
a.hi = (a.hi << bits) + (a.lo >> (32 - bits));
|
||||
a.lo <<= bits;
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
UInt64 u64_xtnd32(UInt64 v){
|
||||
|
||||
UInt64 a = v;
|
||||
|
||||
if(a.lo & 0x80000000UL) a.hi = 0xFFFFFFFFUL;
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
Boolean u64_isZero(UInt64 a){
|
||||
|
||||
return a.lo == 0 && a.hi == 0;
|
||||
}
|
||||
|
||||
UInt64 u64_inc(UInt64 v){
|
||||
|
||||
UInt64 a = v;
|
||||
|
||||
if(!++a.lo) a.hi++;
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
UInt64 u64_and(UInt64 a, UInt64 b){
|
||||
|
||||
UInt64 r;
|
||||
|
||||
r.lo = a.lo & b.lo;
|
||||
r.hi = a.hi & b.hi;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
UInt64 u64_zero(void){
|
||||
|
||||
UInt64 r;
|
||||
|
||||
r.lo = 0;
|
||||
r.hi = 0;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
UInt64 u64_sub(UInt64 a, UInt64 b){
|
||||
|
||||
UInt64 bn;
|
||||
|
||||
bn.lo = ~b.lo;
|
||||
bn.hi = ~b.hi;
|
||||
|
||||
bn = u64_inc(bn);
|
||||
|
||||
return u64_add(a, bn);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
64
contrib/other/uarm/math64.h
Executable file
64
contrib/other/uarm/math64.h
Executable file
@ -0,0 +1,64 @@
|
||||
#ifndef _MATH_64_H_
|
||||
#define _MATH_64_H_
|
||||
|
||||
#include "types.h"
|
||||
|
||||
#define COMPILER_SUPPORTS_LONG_LONG //undefine if compiler doe snot uspport long long
|
||||
|
||||
|
||||
#ifdef COMPILER_SUPPORTS_LONG_LONG
|
||||
|
||||
typedef unsigned long long UInt64;
|
||||
|
||||
static inline UInt64 u64_from_halves(UInt32 hi, UInt32 lo) { return (((UInt64)hi) << 32ULL) | ((UInt64)lo); }
|
||||
static inline UInt64 u64_32_to_64(UInt32 v) { return (UInt64)v; }
|
||||
static inline UInt32 u64_64_to_32(UInt64 v) { return (UInt32)v; }
|
||||
static inline UInt32 u64_get_hi(UInt64 v) { return (UInt32)(v >> 32ULL); }
|
||||
static inline UInt64 u64_add(UInt64 a, UInt64 b) { return a + b; }
|
||||
static inline UInt64 u64_add32(UInt64 a, UInt32 b) { return a + (UInt64)b; }
|
||||
static inline UInt64 u64_umul3232(UInt32 a, UInt32 b) { return ((UInt64)a) * ((UInt64)b); } //sad but true: gcc has no u32xu32->64 multiply
|
||||
static inline UInt64 u64_smul3232(Int32 a, Int32 b) { return ((signed long long)a) * ((signed long long)b); } //sad but true: gcc has no s32xs32->64 multiply
|
||||
static inline UInt64 u64_shr(UInt64 a, unsigned bits) { return a >> (UInt64)bits; }
|
||||
static inline UInt64 u64_shl(UInt64 a, unsigned bits) { return a << (UInt64)bits; }
|
||||
static inline UInt64 u64_xtnd32(UInt64 a) { if(a & 0x80000000UL) a |= (((UInt64)-1) << 32ULL); return a; }
|
||||
static inline Boolean u64_isZero(UInt64 a) { return a == 0; }
|
||||
static inline UInt64 u64_inc(UInt64 a) { return a + 1ULL; }
|
||||
static inline UInt64 u64_and(UInt64 a, UInt64 b) { return a & b; }
|
||||
static inline UInt64 u64_zero(void) { return 0; }
|
||||
static inline UInt64 u64_sub(UInt64 a, UInt64 b) { return a - b; }
|
||||
|
||||
#else
|
||||
|
||||
typedef struct{
|
||||
|
||||
UInt32 hi, lo;
|
||||
}UInt64;
|
||||
|
||||
|
||||
UInt64 u64_from_halves(UInt32 hi, UInt32 lo);
|
||||
UInt64 u64_32_to_64(UInt32 v);
|
||||
UInt32 u64_64_to_32(UInt64 v);
|
||||
UInt32 u64_get_hi(UInt64 v);
|
||||
UInt64 u64_add(UInt64 a, UInt64 b);
|
||||
UInt64 u64_umul3232(UInt32 a, UInt32 b);
|
||||
UInt64 u64_smul3232(Int32 a, Int32 b);
|
||||
UInt64 u64_shr(UInt64 a, unsigned bits);
|
||||
UInt64 u64_shl(UInt64 a, unsigned bits);
|
||||
UInt64 u64_add32(UInt64 a, UInt32 b);
|
||||
UInt64 u64_xtnd32(UInt64 a);
|
||||
Boolean u64_isZero(UInt64 a);
|
||||
UInt64 u64_inc(UInt64 a);
|
||||
UInt64 u64_zero(void);
|
||||
UInt64 u64_sub(UInt64 a, UInt64 b);
|
||||
|
||||
|
||||
|
||||
UInt64 u64_and(UInt64 a, UInt64 b);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
96
contrib/other/uarm/mem.c
Executable file
96
contrib/other/uarm/mem.c
Executable file
@ -0,0 +1,96 @@
|
||||
#include "mem.h"
|
||||
|
||||
|
||||
|
||||
void memInit(ArmMem* mem){
|
||||
|
||||
UInt8 i;
|
||||
|
||||
for(i = 0; i < MAX_MEM_REGIONS; i++){
|
||||
mem->regions[i].sz = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void memDeinit(_UNUSED_ ArmMem* mem){
|
||||
|
||||
//nothing here
|
||||
}
|
||||
|
||||
Boolean memRegionAdd(ArmMem* mem, UInt32 pa, UInt32 sz, ArmMemAccessF aF, void* uD){
|
||||
|
||||
UInt8 i;
|
||||
|
||||
//check for intersection with another region
|
||||
|
||||
for(i = 0; i < MAX_MEM_REGIONS; i++){
|
||||
|
||||
if(!mem->regions[i].sz) continue;
|
||||
if((mem->regions[i].pa <= pa && mem->regions[i].pa + mem->regions[i].sz > pa) || (pa <= mem->regions[i].pa && pa + sz > mem->regions[i].pa)){
|
||||
|
||||
return false; //intersection -> fail
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//find a free region and put it there
|
||||
|
||||
for(i = 0; i < MAX_MEM_REGIONS; i++){
|
||||
if(mem->regions[i].sz == 0){
|
||||
|
||||
mem->regions[i].pa = pa;
|
||||
mem->regions[i].sz = sz;
|
||||
mem->regions[i].aF = aF;
|
||||
mem->regions[i].uD = uD;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//fail miserably
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Boolean memRegionDel(ArmMem* mem, UInt32 pa, UInt32 sz){
|
||||
|
||||
UInt8 i;
|
||||
|
||||
for(i = 0; i < MAX_MEM_REGIONS; i++){
|
||||
if(mem->regions[i].pa == pa && mem->regions[i].sz ==sz){
|
||||
|
||||
mem->regions[i].sz = 0;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Boolean memAccess(ArmMem* mem, UInt32 addr, UInt8 size, Boolean write, void* buf){
|
||||
|
||||
UInt8 i;
|
||||
|
||||
for(i = 0; i < MAX_MEM_REGIONS; i++){
|
||||
if(mem->regions[i].pa <= addr && mem->regions[i].pa + mem->regions[i].sz > addr){
|
||||
|
||||
return mem->regions[i].aF(mem->regions[i].uD, addr, size, write & 0x7F, buf);
|
||||
}
|
||||
}
|
||||
|
||||
if(!(write & 0x80)){ //high bit in write tells us to not print this error (used by gdb stub)
|
||||
|
||||
err_str("Memory ");
|
||||
err_str(write ? "write" : "read");
|
||||
err_str(" of ");
|
||||
err_dec(size);
|
||||
err_str(" bytes at physical addr 0x");
|
||||
err_hex(addr);
|
||||
err_str(" fails, halting\r\n");
|
||||
while(1);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
38
contrib/other/uarm/mem.h
Executable file
38
contrib/other/uarm/mem.h
Executable file
@ -0,0 +1,38 @@
|
||||
#ifndef _MEM_H_
|
||||
#define _MEM_H_
|
||||
|
||||
#include "types.h"
|
||||
|
||||
#define MAX_MEM_REGIONS 16
|
||||
|
||||
#define errPhysMemNoSuchRegion (errPhysMem + 1) //this physical address is not claimed by any region
|
||||
#define errPhysMemInvalidAdr (errPhysMem + 2) //address is IN a region but access to it is not allowed (it doesn't exist really)
|
||||
#define errPhysMemInvalidSize (errPhysMem + 3) //access that is not 1, 2 or 4-byte big
|
||||
|
||||
typedef Boolean (*ArmMemAccessF)(void* userData, UInt32 pa, UInt8 size, Boolean write, void* buf);
|
||||
|
||||
typedef struct{
|
||||
|
||||
UInt32 pa;
|
||||
UInt32 sz;
|
||||
ArmMemAccessF aF;
|
||||
void* uD;
|
||||
|
||||
}ArmMemRegion;
|
||||
|
||||
typedef struct{
|
||||
|
||||
ArmMemRegion regions[MAX_MEM_REGIONS];
|
||||
|
||||
}ArmMem;
|
||||
|
||||
|
||||
void memInit(ArmMem* mem);
|
||||
void memDeinit(ArmMem* mem);
|
||||
|
||||
Boolean memRegionAdd(ArmMem* mem, UInt32 pa, UInt32 sz, ArmMemAccessF af, void* uD);
|
||||
Boolean memRegionDel(ArmMem* mem, UInt32 pa, UInt32 sz);
|
||||
|
||||
Boolean memAccess(ArmMem* mem, UInt32 addr, UInt8 size, Boolean write, void* buf);
|
||||
|
||||
#endif
|
116
contrib/other/uarm/pxa255_DMA.c
Executable file
116
contrib/other/uarm/pxa255_DMA.c
Executable file
@ -0,0 +1,116 @@
|
||||
#include "pxa255_DMA.h"
|
||||
#include "mem.h"
|
||||
|
||||
#define REG_DAR 0
|
||||
#define REG_SAR 1
|
||||
#define REG_TAR 2
|
||||
#define REG_CR 3
|
||||
#define REG_CSR 4
|
||||
|
||||
|
||||
static void pxa255dmaPrvChannelRegWrite(_UNUSED_ Pxa255dma* dma, UInt8 channel, UInt8 reg, UInt32 val){
|
||||
|
||||
if(val){ //we start with zeros, so non-zero writes are all we care about
|
||||
|
||||
const char* regs[] = {"DADDR", "SADDR", "TADDR", "CR", "CSR"};
|
||||
|
||||
err_str("dma: writes unimpl!");
|
||||
// err_str("PXA255 dma engine: writes unimpl! (writing 0x");
|
||||
// err_hex(val);
|
||||
// err_str(" to channel ");
|
||||
// err_dec(channel);
|
||||
// err_str(" reg ");
|
||||
// err_str(regs[reg]);
|
||||
// err_str(". Halting.\r\n");
|
||||
while(1);
|
||||
}
|
||||
}
|
||||
|
||||
static UInt32 pxa255dmaPrvChannelRegRead(_UNUSED_ Pxa255dma* dma, _UNUSED_ UInt8 channel, _UNUSED_ UInt8 reg){
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static Boolean pxa255dmaPrvMemAccessF(void* userData, UInt32 pa, UInt8 size, Boolean write, void* buf){
|
||||
|
||||
Pxa255dma* dma = userData;
|
||||
UInt8 reg, set;
|
||||
UInt32 val = 0;
|
||||
|
||||
if(size != 4) {
|
||||
err_str(__FILE__ ": Unexpected ");
|
||||
// err_str(write ? "write" : "read");
|
||||
// err_str(" of ");
|
||||
// err_dec(size);
|
||||
// err_str(" bytes to 0x");
|
||||
// err_hex(pa);
|
||||
// err_str("\r\n");
|
||||
return true; //we do not support non-word accesses
|
||||
}
|
||||
|
||||
pa = (pa - PXA255_DMA_BASE) >> 2;
|
||||
|
||||
if(write){
|
||||
val = *(UInt32*)buf;
|
||||
|
||||
switch(pa >> 6){ //weird, but quick way to avoide repeated if-then-elses. this is faster
|
||||
case 0:
|
||||
if(pa < 16){
|
||||
reg = REG_CSR;
|
||||
set = pa;
|
||||
pxa255dmaPrvChannelRegWrite(dma, set, reg, val);
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:
|
||||
pa -= 64;
|
||||
if(pa < 40) dma->CMR[pa] = val;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
pa -= 128;
|
||||
set = pa >> 2;
|
||||
reg = pa & 3;
|
||||
pxa255dmaPrvChannelRegWrite(dma, set, reg, val);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else{
|
||||
switch(pa >> 6){ //weird, but quick way to avoide repeated if-then-elses. this is faster
|
||||
case 0:
|
||||
if(pa < 16){
|
||||
reg = REG_CSR;
|
||||
set = pa;
|
||||
val = pxa255dmaPrvChannelRegRead(dma, set, reg);
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:
|
||||
pa -= 64;
|
||||
if(pa < 40) val = dma->CMR[pa];
|
||||
break;
|
||||
|
||||
case 2:
|
||||
pa -= 128;
|
||||
set = pa >> 2;
|
||||
reg = pa & 3;
|
||||
val = pxa255dmaPrvChannelRegRead(dma, set, reg);
|
||||
break;
|
||||
}
|
||||
|
||||
*(UInt32*)buf = val;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Boolean pxa255dmaInit(Pxa255dma* dma, ArmMem* physMem, Pxa255ic* ic){
|
||||
|
||||
__mem_zero(dma, sizeof(Pxa255dma));
|
||||
dma->ic = ic;
|
||||
dma->mem = physMem;
|
||||
|
||||
return memRegionAdd(physMem, PXA255_DMA_BASE, PXA255_DMA_SIZE, pxa255dmaPrvMemAccessF, dma);
|
||||
}
|
42
contrib/other/uarm/pxa255_DMA.h
Executable file
42
contrib/other/uarm/pxa255_DMA.h
Executable file
@ -0,0 +1,42 @@
|
||||
#ifndef _PXA255_DMA_H_
|
||||
#define _PXA255_DMA_H_
|
||||
|
||||
#include "mem.h"
|
||||
#include "cpu.h"
|
||||
#include "pxa255_IC.h"
|
||||
|
||||
/*
|
||||
PXA255 OS DMA controller
|
||||
|
||||
*/
|
||||
|
||||
#define PXA255_DMA_BASE 0x40000000UL
|
||||
#define PXA255_DMA_SIZE 0x00001000UL
|
||||
|
||||
typedef struct{
|
||||
|
||||
UInt32 DAR; //descriptor address register
|
||||
UInt32 SAR; //source address register
|
||||
UInt32 TAR; //target address register
|
||||
UInt32 CR; //command register
|
||||
UInt32 CSR; //control and status register
|
||||
|
||||
}Pxa255dmaChannel;
|
||||
|
||||
typedef struct{
|
||||
|
||||
Pxa255ic* ic;
|
||||
ArmMem* mem;
|
||||
|
||||
UInt16 DINT;
|
||||
Pxa255dmaChannel channels[16];
|
||||
UInt8 CMR[40]; //channel map registers [ we store lower 8 bits only :-) ]
|
||||
|
||||
}Pxa255dma;
|
||||
|
||||
|
||||
|
||||
Boolean pxa255dmaInit(Pxa255dma* gpio, ArmMem* physMem, Pxa255ic* ic);
|
||||
|
||||
#endif
|
||||
|
81
contrib/other/uarm/pxa255_DSP.c
Executable file
81
contrib/other/uarm/pxa255_DSP.c
Executable file
@ -0,0 +1,81 @@
|
||||
#include "math64.h"
|
||||
#include "pxa255_DSP.h"
|
||||
|
||||
|
||||
|
||||
|
||||
Boolean pxa255dspAccess(struct ArmCpu* cpu, void* userData, Boolean MRRC, UInt8 op, UInt8 RdLo, UInt8 RdHi, UInt8 acc){
|
||||
|
||||
Pxa255dsp* dsp = userData;
|
||||
|
||||
if(acc != 0 || op != 0) return false; //bad encoding
|
||||
|
||||
if(MRRC){ //MRA: read acc0
|
||||
|
||||
cpuSetReg(cpu, RdLo, u64_64_to_32(dsp->acc0));
|
||||
cpuSetReg(cpu, RdHi, (UInt8)u64_get_hi(dsp->acc0));
|
||||
}
|
||||
else{ //MAR: write acc0
|
||||
|
||||
dsp->acc0 = u64_from_halves(cpuGetRegExternal(cpu, RdHi) & 0xFF, cpuGetRegExternal(cpu, RdLo));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Boolean pxa255dspOp(struct ArmCpu* cpu, void* userData, Boolean two/* MCR2/MRC2 ? */, Boolean MRC, UInt8 op1, UInt8 Rs, UInt8 opcode_3, UInt8 Rm, UInt8 acc){
|
||||
|
||||
Pxa255dsp* dsp = userData;
|
||||
UInt64 addend = u64_zero();
|
||||
UInt32 Vs, Vm;
|
||||
|
||||
if(op1 != 1 || two || MRC || acc != 0) return false; //bad encoding
|
||||
|
||||
Vs = cpuGetRegExternal(cpu, Rs);
|
||||
Vm = cpuGetRegExternal(cpu, Rm);
|
||||
|
||||
switch(opcode_3 >> 2){
|
||||
|
||||
case 0: //MIA
|
||||
addend = u64_smul3232(Vm, Vs);
|
||||
break;
|
||||
|
||||
case 1: //invalid
|
||||
return false;
|
||||
|
||||
case 2: //MIAPH
|
||||
addend = u64_smul3232((Int32)((Int16)(Vm >> 0)), (Int32)((Int16)(Vs >> 0)));
|
||||
addend = u64_add(addend, u64_smul3232((Int32)((Int16)(Vm >> 16)), (Int32)((Int16)(Vs >> 16))));
|
||||
break;
|
||||
|
||||
case 3: //MIAxy
|
||||
if(opcode_3 & 2) Vm >>= 16; //X set
|
||||
if(opcode_3 & 1) Vs >>= 16; //Y set
|
||||
addend = u64_smul3232((Int32)((Int16)Vm), (Int32)((Int16)Vs));
|
||||
break;
|
||||
}
|
||||
|
||||
dsp->acc0 = u64_and(u64_add(dsp->acc0, addend), u64_from_halves(0xFF, 0xFFFFFFFFUL));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Boolean pxa255dspInit(Pxa255dsp* dsp, ArmCpu* cpu){
|
||||
|
||||
ArmCoprocessor cp;
|
||||
|
||||
|
||||
__mem_zero(dsp, sizeof(Pxa255dsp));
|
||||
|
||||
cp.regXfer = pxa255dspOp;
|
||||
cp.dataProcessing = NULL;
|
||||
cp.memAccess = NULL;
|
||||
cp.twoRegF = pxa255dspAccess;
|
||||
cp.userData = dsp;
|
||||
|
||||
cpuCoprocessorRegister(cpu, 0, &cp);
|
||||
|
||||
return true;
|
||||
}
|
20
contrib/other/uarm/pxa255_DSP.h
Executable file
20
contrib/other/uarm/pxa255_DSP.h
Executable file
@ -0,0 +1,20 @@
|
||||
#ifndef _PXA255_DSP_H_
|
||||
#define _PXA255_DSP_H_
|
||||
|
||||
#include "mem.h"
|
||||
#include "cpu.h"
|
||||
|
||||
|
||||
|
||||
typedef struct{
|
||||
|
||||
UInt64 acc0;
|
||||
|
||||
}Pxa255dsp;
|
||||
|
||||
|
||||
|
||||
Boolean pxa255dspInit(Pxa255dsp* dsp, ArmCpu* cpu);
|
||||
|
||||
|
||||
#endif
|
206
contrib/other/uarm/pxa255_GPIO.c
Executable file
206
contrib/other/uarm/pxa255_GPIO.c
Executable file
@ -0,0 +1,206 @@
|
||||
#include "pxa255_GPIO.h"
|
||||
#include "mem.h"
|
||||
|
||||
|
||||
static void pxa255gpioPrvRecalcValues(Pxa255gpio* gpio, UInt32 which){
|
||||
|
||||
UInt8 i;
|
||||
UInt32 val, bit;
|
||||
|
||||
val = gpio->dirs[which];
|
||||
gpio->levels[which] = (gpio->latches[which] & val) | (gpio->inputs[which] & (~val));
|
||||
|
||||
val = 3;
|
||||
bit = 1;
|
||||
for(i = 0 ; i < 16; i++, val <<= 2, bit <<= 1) if(gpio->AFRs[(which << 1) + 0] & val) gpio->levels[which] &=~ bit; //all AFRs read as zero to CPU
|
||||
for(i = 16; i < 32; i++, val <<= 2, bit <<= 1) if(gpio->AFRs[(which << 1) + 1] & val) gpio->levels[which] &=~ bit; //all AFRs read as zero to CPU
|
||||
}
|
||||
|
||||
static void pxa255gpioPrvRecalcIntrs(Pxa255gpio* gpio){
|
||||
|
||||
pxa255icInt(gpio->ic, PXA255_I_GPIO_all, gpio->levels[1] || gpio->levels[2] || (gpio->levels[0] &~ 3));
|
||||
pxa255icInt(gpio->ic, PXA255_I_GPIO_1, (gpio->levels[0] & 2) != 0);
|
||||
pxa255icInt(gpio->ic, PXA255_I_GPIO_0, (gpio->levels[0] & 1) != 0);
|
||||
}
|
||||
|
||||
static Boolean pxa255gpioPrvMemAccessF(void* userData, UInt32 pa, UInt8 size, Boolean write, void* buf){
|
||||
|
||||
Pxa255gpio* gpio = userData;
|
||||
UInt32 val = 0;
|
||||
|
||||
if(size != 4) {
|
||||
err_str(__FILE__ ": Unexpected ");
|
||||
// err_str(write ? "write" : "read");
|
||||
// err_str(" of ");
|
||||
// err_dec(size);
|
||||
// err_str(" bytes to 0x");
|
||||
// err_hex(pa);
|
||||
// err_str("\r\n");
|
||||
return true; //we do not support non-word accesses
|
||||
}
|
||||
|
||||
pa = (pa - PXA255_GPIO_BASE) >> 2;
|
||||
|
||||
if(write){
|
||||
val = *(UInt32*)buf;
|
||||
|
||||
switch(pa){
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
|
||||
break;
|
||||
|
||||
case 3:
|
||||
case 4:
|
||||
case 5:
|
||||
pa -= 3;
|
||||
gpio->dirs[pa] = val;
|
||||
goto recalc;
|
||||
|
||||
case 6:
|
||||
case 7:
|
||||
case 8:
|
||||
pa -= 6;
|
||||
gpio->levels[pa] |= val;
|
||||
goto recalc;
|
||||
|
||||
case 9:
|
||||
case 10:
|
||||
case 11:
|
||||
pa -= 9;
|
||||
gpio->levels[pa] &=~ val;
|
||||
goto recalc;
|
||||
|
||||
case 12:
|
||||
case 13:
|
||||
case 14:
|
||||
gpio->riseDet[pa - 12] = val;
|
||||
break;
|
||||
|
||||
case 15:
|
||||
case 16:
|
||||
case 17:
|
||||
gpio->fallDet[pa - 15] = val;
|
||||
break;
|
||||
|
||||
case 18:
|
||||
case 19:
|
||||
case 20:
|
||||
gpio->detStatus[pa - 18] &=~ val;
|
||||
goto trigger_intrs;
|
||||
|
||||
case 21:
|
||||
case 22:
|
||||
case 23:
|
||||
case 24:
|
||||
case 25:
|
||||
case 26:
|
||||
val = gpio->AFRs[pa - 21];
|
||||
goto recalc;
|
||||
}
|
||||
|
||||
goto done;
|
||||
|
||||
recalc:
|
||||
pxa255gpioPrvRecalcValues(gpio, pa);
|
||||
|
||||
trigger_intrs:
|
||||
pxa255gpioPrvRecalcIntrs(gpio);
|
||||
}
|
||||
else{
|
||||
switch(pa){
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
val = gpio->levels[pa - 0];
|
||||
break;
|
||||
|
||||
case 3:
|
||||
case 4:
|
||||
case 5:
|
||||
val = gpio->dirs[pa - 3];
|
||||
break;
|
||||
|
||||
case 6:
|
||||
case 7:
|
||||
case 8:
|
||||
case 9:
|
||||
case 10:
|
||||
case 11:
|
||||
val = 0;
|
||||
break;
|
||||
|
||||
case 12:
|
||||
case 13:
|
||||
case 14:
|
||||
val = gpio->riseDet[pa - 12];
|
||||
break;
|
||||
|
||||
case 15:
|
||||
case 16:
|
||||
case 17:
|
||||
val = gpio->fallDet[pa - 15];
|
||||
break;
|
||||
|
||||
case 18:
|
||||
case 19:
|
||||
case 20:
|
||||
val = gpio->detStatus[pa - 18];
|
||||
break;
|
||||
|
||||
case 21:
|
||||
case 22:
|
||||
case 23:
|
||||
case 24:
|
||||
case 25:
|
||||
case 26:
|
||||
val = gpio->AFRs[pa - 21];
|
||||
break;
|
||||
|
||||
}
|
||||
*(UInt32*)buf = val;
|
||||
}
|
||||
|
||||
done:
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Boolean pxa255gpioInit(Pxa255gpio* gpio, ArmMem* physMem, Pxa255ic* ic){
|
||||
|
||||
__mem_zero(gpio, sizeof(Pxa255gpio));
|
||||
gpio->ic = ic;
|
||||
|
||||
return memRegionAdd(physMem, PXA255_GPIO_BASE, PXA255_GPIO_SIZE, pxa255gpioPrvMemAccessF, gpio);
|
||||
}
|
||||
|
||||
void pxa255gpioSetState(Pxa255gpio* gpio, UInt8 gpioNum, Boolean on){
|
||||
|
||||
UInt32 set = gpioNum >> 5;
|
||||
UInt32 v = 1UL << (gpioNum & 0x1F);
|
||||
UInt32* p;
|
||||
|
||||
if(gpioNum >= 85) return;
|
||||
|
||||
p = gpio->inputs + set;
|
||||
if(on) *p |= v;
|
||||
else *p &=~ v;
|
||||
|
||||
pxa255gpioPrvRecalcValues(gpio, set);
|
||||
pxa255gpioPrvRecalcIntrs(gpio);
|
||||
}
|
||||
|
||||
UInt8 pxa255gpioGetState(Pxa255gpio* gpio, UInt8 gpioNum){
|
||||
|
||||
UInt32 sSet = gpioNum >> 5;
|
||||
UInt32 bSet = gpioNum >> 4;
|
||||
UInt32 sV = 1UL << (gpioNum & 0x1F);
|
||||
UInt32 bV = 3UL << (gpioNum & 0x0F);
|
||||
|
||||
|
||||
if(gpioNum >= 85) return PXA255_GPIO_NOT_PRESENT;
|
||||
if(gpio->AFRs[bSet] & bV) return ((gpio->AFRs[bSet] & bV) >> (gpioNum & 0x0F)) + PXA255_GPIO_AFR1;
|
||||
if(gpio->dirs[sSet] & sV) return (gpio->latches[sSet] & sV) ? PXA255_GPIO_HIGH : PXA255_GPIO_LOW;
|
||||
return PXA255_GPIO_HiZ;
|
||||
}
|
47
contrib/other/uarm/pxa255_GPIO.h
Executable file
47
contrib/other/uarm/pxa255_GPIO.h
Executable file
@ -0,0 +1,47 @@
|
||||
#ifndef _PXA255_GPIO_H_
|
||||
#define _PXA255_GPIO_H_
|
||||
|
||||
#include "mem.h"
|
||||
#include "cpu.h"
|
||||
#include "pxa255_IC.h"
|
||||
|
||||
/*
|
||||
PXA255 OS GPIO controller
|
||||
|
||||
*/
|
||||
|
||||
#define PXA255_GPIO_BASE 0x40E00000UL
|
||||
#define PXA255_GPIO_SIZE 0x00001000UL
|
||||
|
||||
|
||||
typedef struct{
|
||||
|
||||
Pxa255ic* ic;
|
||||
|
||||
UInt32 latches[3]; //what pxa wants to be outputting
|
||||
UInt32 inputs[3]; //what pxa is receiving [only set by the pxa255gpioSetState() API]
|
||||
UInt32 levels[3]; //what pxa sees (it differs from above for IN pins)
|
||||
UInt32 dirs[3]; //1 = output
|
||||
UInt32 riseDet[3]; //1 = rise detect
|
||||
UInt32 fallDet[3]; //1 = fall detect
|
||||
UInt32 detStatus[3]; //1 = detect happened
|
||||
UInt32 AFRs[6]; //1, 2, 3 = alt funcs
|
||||
|
||||
}Pxa255gpio;
|
||||
|
||||
#define PXA255_GPIO_LOW 0 //these values make it look like all HiZ, AFR, and nonexistent pins have pullups to those who dumbly assume gpioGEt returns a boolean
|
||||
#define PXA255_GPIO_HIGH 1
|
||||
#define PXA255_GPIO_HiZ 2
|
||||
#define PXA255_GPIO_AFR1 3
|
||||
#define PXA255_GPIO_AFR2 4
|
||||
#define PXA255_GPIO_AFR3 5
|
||||
#define PXA255_GPIO_NOT_PRESENT 6
|
||||
|
||||
Boolean pxa255gpioInit(Pxa255gpio* gpio, ArmMem* physMem, Pxa255ic* ic);
|
||||
|
||||
//for external use :)
|
||||
UInt8 pxa255gpioGetState(Pxa255gpio* gpio, UInt8 gpioNum);
|
||||
void pxa255gpioSetState(Pxa255gpio* gpio, UInt8 gpioNum, Boolean on); //we can only set value (and only of input pins), not direction
|
||||
|
||||
#endif
|
||||
|
104
contrib/other/uarm/pxa255_IC.c
Executable file
104
contrib/other/uarm/pxa255_IC.c
Executable file
@ -0,0 +1,104 @@
|
||||
#include "pxa255_IC.h"
|
||||
#include "mem.h"
|
||||
|
||||
|
||||
static void pxa255icPrvHandleChanges(Pxa255ic* ic){
|
||||
|
||||
Boolean nowIrq, nowFiq;
|
||||
UInt32 unmasked = ic->ICPR & ic->ICMR;
|
||||
|
||||
nowFiq = (unmasked & ic->ICLR) != 0;
|
||||
nowIrq = (unmasked & ~ic->ICLR) != 0;
|
||||
|
||||
if(nowFiq != ic->wasFiq) cpuIrq(ic->cpu, true, nowFiq);
|
||||
if(nowIrq != ic->wasIrq) cpuIrq(ic->cpu, false, nowIrq);
|
||||
|
||||
ic->wasFiq = nowFiq;
|
||||
ic->wasIrq = nowIrq;
|
||||
}
|
||||
|
||||
static Boolean pxa255icPrvMemAccessF(void* userData, UInt32 pa, UInt8 size, Boolean write, void* buf){
|
||||
|
||||
Pxa255ic* ic = userData;
|
||||
UInt32 val = 0;
|
||||
|
||||
if(size != 4) {
|
||||
err_str(__FILE__ ": Unexpected ");
|
||||
// err_str(write ? "write" : "read");
|
||||
// err_str(" of ");
|
||||
// err_dec(size);
|
||||
// err_str(" bytes to 0x");
|
||||
// err_hex(pa);
|
||||
// err_str("\r\n");
|
||||
return true; //we do not support non-word accesses
|
||||
}
|
||||
|
||||
pa = (pa - PXA255_IC_BASE) >> 2;
|
||||
|
||||
if(write){
|
||||
if(pa == 1) ic->ICMR = *(UInt32*)buf;
|
||||
else if(pa == 2) ic->ICLR = *(UInt32*)buf;
|
||||
else if(pa == 5) ic->ICCR = *(UInt32*)buf;
|
||||
else return true;
|
||||
pxa255icPrvHandleChanges(ic);
|
||||
}
|
||||
else{
|
||||
switch(pa){
|
||||
|
||||
case 0:
|
||||
val = ic->ICPR & ic->ICMR & ~ic->ICLR;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
val = ic->ICMR;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
val = ic->ICLR;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
val = ic->ICPR & ic->ICMR & ic->ICLR;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
val = ic->ICPR;
|
||||
break;
|
||||
|
||||
case 5:
|
||||
val = ic->ICCR;
|
||||
break;
|
||||
|
||||
}
|
||||
*(UInt32*)buf = val;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Boolean pxa255icInit(Pxa255ic* ic, ArmCpu* cpu, ArmMem* physMem){
|
||||
|
||||
__mem_zero(ic, sizeof(Pxa255ic));
|
||||
ic->cpu = cpu;
|
||||
return memRegionAdd(physMem, PXA255_IC_BASE, PXA255_IC_SIZE, pxa255icPrvMemAccessF, ic);
|
||||
}
|
||||
|
||||
|
||||
void pxa255icInt(Pxa255ic* ic, UInt8 intNum, Boolean raise){ //interrupt caused by emulated hardware
|
||||
|
||||
UInt32 old_, new_;
|
||||
|
||||
old_ = new_ = ic->ICPR;
|
||||
|
||||
if(raise) new_ |= (1UL << intNum);
|
||||
else new_ &=~ (1UL << intNum);
|
||||
|
||||
if(new_ != old_){
|
||||
ic->ICPR = new_;
|
||||
pxa255icPrvHandleChanges(ic);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
64
contrib/other/uarm/pxa255_IC.h
Executable file
64
contrib/other/uarm/pxa255_IC.h
Executable file
@ -0,0 +1,64 @@
|
||||
#ifndef _PXA255_IC_H_
|
||||
#define _PXA255_IC_H_
|
||||
|
||||
#include "mem.h"
|
||||
#include "CPU.h"
|
||||
#include <stdio.h>
|
||||
|
||||
/*
|
||||
PXA255 interrupt controller
|
||||
|
||||
PURRPOSE: raises IRQ, FIQ as needed
|
||||
|
||||
*/
|
||||
|
||||
#define PXA255_IC_BASE 0x40D00000UL
|
||||
#define PXA255_IC_SIZE 0x00010000UL
|
||||
|
||||
|
||||
#define PXA255_I_RTC_ALM 31
|
||||
#define PXA255_I_RTC_HZ 30
|
||||
#define PXA255_I_TIMR3 29
|
||||
#define PXA255_I_TIMR2 28
|
||||
#define PXA255_I_TIMR1 27
|
||||
#define PXA255_I_TIMR0 26
|
||||
#define PXA255_I_DMA 25
|
||||
#define PXA255_I_SSP 24
|
||||
#define PXA255_I_MMC 23
|
||||
#define PXA255_I_FFUART 22
|
||||
#define PXA255_I_BTUART 21
|
||||
#define PXA255_I_STUART 20
|
||||
#define PXA255_I_ICP 19
|
||||
#define PXA255_I_I2C 18
|
||||
#define PXA255_I_LCD 17
|
||||
#define PXA255_I_NET_SSP 16
|
||||
#define PXA255_I_AC97 14
|
||||
#define PXA255_I_I2S 13
|
||||
#define PXA255_I_PMU 12
|
||||
#define PXA255_I_USB 11
|
||||
#define PXA255_I_GPIO_all 10
|
||||
#define PXA255_I_GPIO_1 9
|
||||
#define PXA255_I_GPIO_0 8
|
||||
#define PXA255_I_HWUART 7
|
||||
|
||||
|
||||
typedef struct{
|
||||
|
||||
ArmCpu* cpu;
|
||||
|
||||
UInt32 ICMR; //Mask Register
|
||||
UInt32 ICLR; //Level Register
|
||||
UInt32 ICCR; //Control Register
|
||||
UInt32 ICPR; //Pending register
|
||||
|
||||
Boolean wasIrq, wasFiq;
|
||||
|
||||
}Pxa255ic;
|
||||
|
||||
Boolean pxa255icInit(Pxa255ic* ic, ArmCpu* cpu, ArmMem* physMem);
|
||||
|
||||
void pxa255icInt(Pxa255ic* ic, UInt8 intNum, Boolean raise); //interrupt caused by emulated hardware/ interrupt handled by guest
|
||||
|
||||
|
||||
#endif
|
||||
|
454
contrib/other/uarm/pxa255_LCD.c
Executable file
454
contrib/other/uarm/pxa255_LCD.c
Executable file
@ -0,0 +1,454 @@
|
||||
#include "pxa255_LCD.h"
|
||||
#include "mem.h"
|
||||
|
||||
|
||||
|
||||
#define LCD_IMAGE "LCD.bmp"
|
||||
#define UNMASKABLE_INTS 0x7C8E
|
||||
|
||||
|
||||
static void pxa255lcdPrvUpdateInts(Pxa255lcd* lcd){
|
||||
|
||||
UInt16 ints = lcd->lcsr & lcd->intMask;
|
||||
|
||||
if((ints && !lcd->intWasPending) || (!ints && lcd->intWasPending)){
|
||||
|
||||
lcd->intWasPending = !!ints;
|
||||
pxa255icInt(lcd->ic, PXA255_I_LCD, !!ints);
|
||||
}
|
||||
}
|
||||
|
||||
static Boolean pxa255lcdPrvMemAccessF(void* userData, UInt32 pa, UInt8 size, Boolean write, void* buf){
|
||||
|
||||
Pxa255lcd* lcd = userData;
|
||||
UInt32 val = 0;
|
||||
UInt16 v16;
|
||||
|
||||
if(size != 4) {
|
||||
err_str(__FILE__ ": Unexpected ");
|
||||
// err_str(write ? "write" : "read");
|
||||
// err_str(" of ");
|
||||
// err_dec(size);
|
||||
// err_str(" bytes to 0x");
|
||||
// err_hex(pa);
|
||||
// err_str("\r\n");
|
||||
return true; //we do not support non-word accesses
|
||||
}
|
||||
|
||||
pa = (pa - PXA255_LCD_BASE) >> 2;
|
||||
|
||||
if(write){
|
||||
val = *(UInt32*)buf;
|
||||
|
||||
switch(pa){
|
||||
case 0:
|
||||
if((lcd->lccr0 ^ val) & 0x0001){ //something changed about enablement - handle it
|
||||
|
||||
lcd->enbChanged = 1;
|
||||
}
|
||||
lcd->lccr0 = val;
|
||||
//recalc intMask
|
||||
v16 = UNMASKABLE_INTS;
|
||||
if(val & 0x00200000UL){ //output fifo underrun
|
||||
v16 |= 0x0040;
|
||||
}
|
||||
if(val & 0x00100000UL){ //branch int
|
||||
v16 |= 0x0200;
|
||||
}
|
||||
if(val & 0x00000400UL){ //quick disable
|
||||
v16 |= 0x0001;
|
||||
}
|
||||
if(val & 0x00000040UL){ //end of frame
|
||||
v16 |= 0x0080;
|
||||
}
|
||||
if(val & 0x00000020UL){ //input fifo underrun
|
||||
v16 |= 0x0030;
|
||||
}
|
||||
if(val & 0x00000010UL){ //start of frame
|
||||
v16 |= 0x0002;
|
||||
}
|
||||
lcd->intMask = v16;
|
||||
pxa255lcdPrvUpdateInts(lcd);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
lcd->lccr1 = val;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
lcd->lccr2 = val;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
lcd->lccr3 = val;
|
||||
break;
|
||||
|
||||
case 8:
|
||||
lcd->fbr0 = val;
|
||||
break;
|
||||
|
||||
case 9:
|
||||
lcd->fbr1 = val;
|
||||
break;
|
||||
|
||||
case 14:
|
||||
lcd->lcsr &=~ val;
|
||||
pxa255lcdPrvUpdateInts(lcd);
|
||||
break;
|
||||
|
||||
case 15:
|
||||
lcd->liicr = val;
|
||||
break;
|
||||
|
||||
case 16:
|
||||
lcd->trgbr = val;
|
||||
break;
|
||||
|
||||
case 17:
|
||||
lcd->tcr = val;
|
||||
break;
|
||||
|
||||
case 128:
|
||||
lcd->fdadr0 = val;
|
||||
break;
|
||||
|
||||
case 132:
|
||||
lcd->fdadr1 = val;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else{
|
||||
switch(pa){
|
||||
case 0:
|
||||
val = lcd->lccr0;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
val = lcd->lccr1;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
val = lcd->lccr2;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
val = lcd->lccr3;
|
||||
break;
|
||||
|
||||
case 8:
|
||||
val = lcd->fbr0;
|
||||
break;
|
||||
|
||||
case 9:
|
||||
val = lcd->fbr1;
|
||||
break;
|
||||
|
||||
case 14:
|
||||
val = lcd->lcsr;
|
||||
break;
|
||||
|
||||
case 15:
|
||||
val = lcd->liicr;
|
||||
break;
|
||||
|
||||
case 16:
|
||||
val = lcd->trgbr;
|
||||
break;
|
||||
|
||||
case 17:
|
||||
val = lcd->tcr;
|
||||
break;
|
||||
|
||||
case 128:
|
||||
val = lcd->fdadr0;
|
||||
break;
|
||||
|
||||
case 129:
|
||||
val = lcd->fsadr0;
|
||||
break;
|
||||
|
||||
case 130:
|
||||
val = lcd->fidr0;
|
||||
break;
|
||||
|
||||
case 131:
|
||||
val = lcd->ldcmd0;
|
||||
break;
|
||||
|
||||
case 132:
|
||||
val = lcd->fdadr1;
|
||||
break;
|
||||
|
||||
case 133:
|
||||
val = lcd->fsadr1;
|
||||
break;
|
||||
|
||||
case 134:
|
||||
val = lcd->fidr1;
|
||||
break;
|
||||
|
||||
case 135:
|
||||
val = lcd->ldcmd1;
|
||||
break;
|
||||
}
|
||||
*(UInt32*)buf = val;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static UInt32 pxa255PrvGetWord(Pxa255lcd* lcd, UInt32 addr){
|
||||
|
||||
UInt32 v;
|
||||
|
||||
if(!memAccess(lcd->mem, addr, 4, false, &v)) return 0;
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
static void pxa255LcdPrvDma(Pxa255lcd* lcd, void* dest, UInt32 addr, UInt32 len){
|
||||
|
||||
UInt32 t;
|
||||
UInt8* d = dest;
|
||||
|
||||
//we assume aligntment here both on part of dest and of addr
|
||||
|
||||
while(len){
|
||||
|
||||
t = pxa255PrvGetWord(lcd, addr);
|
||||
if(len--) *d++ = t;
|
||||
if(len--) *d++ = t >> 8;
|
||||
if(len--) *d++ = t >> 16;
|
||||
if(len--) *d++ = t >> 24;
|
||||
addr += 4;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef EMBEDDED
|
||||
#include <stdio.h>
|
||||
|
||||
static _INLINE_ void pxa255LcdScreenDataPixel(Pxa255lcd* lcd, UInt8* buf){
|
||||
|
||||
UInt8 r, g, b;
|
||||
const UInt32 W = 640;
|
||||
const UInt32 H = 480;
|
||||
|
||||
b = buf[0] << 3;
|
||||
r = buf[1] & 0xF8;
|
||||
g = (buf[1] << 5) | ((buf[0] >> 3) & 0x1C);
|
||||
|
||||
{
|
||||
static UInt32 pn = 0;
|
||||
static FILE* bmp = NULL;
|
||||
|
||||
if(pn == 0){
|
||||
bmp = fopen(LCD_IMAGE, "w+b");
|
||||
if(bmp){
|
||||
|
||||
const UInt32 off = 56;
|
||||
const UInt32 sz = 320 * 320 * 3 + off;
|
||||
#define LE32(x) ((int)((x) & 0xFF)), ((int)(((x) >> 8) & 0xFF)), ((int)(((x) >> 16) & 0xFF)), ((int)((x) >> 24))
|
||||
#define LE16(x) ((int)((x) & 0xFF)), ((int)(((x) >> 8) & 0xFF))
|
||||
|
||||
fprintf(bmp, "BM%c%c%c%c%c%c%c%c%c%c%c%c", LE32(sz), LE16(0), LE16(0), LE32(off)); //bitmap file header
|
||||
fprintf(bmp, "%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c", LE32(40), LE32(W), LE32(-H), LE16(1), LE16(24), LE32(0), LE32(W * H * 3), LE32(2835), LE32(2835), LE32(0), LE32(0)); //BITMAPCOREHEADER
|
||||
fprintf(bmp, "%c%c",0 ,0); //spacer to align bmp data to 4 bytes
|
||||
|
||||
#undef LE32
|
||||
}
|
||||
}
|
||||
if(bmp){
|
||||
|
||||
fprintf(bmp, "%c%c%c", b, g, r);
|
||||
}
|
||||
pn++;
|
||||
if(pn == W * H){
|
||||
pn = 0;
|
||||
if(bmp){
|
||||
|
||||
fclose(bmp);
|
||||
bmp = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef PXA255_LCD_SUPPORTS_PALLETES
|
||||
static void pxa255LcdSetFakePal(UInt8* buf, UInt8 bpp, UInt8 val){
|
||||
|
||||
while(bpp++ < 8) val = (val << 1) | (val & 1); //sign extend up (weird but works)
|
||||
|
||||
buf[1] = (val & 0xF8) | (val >> 3);
|
||||
buf[0] = ((val & 0xFC) << 5) | val >> 3;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void pxa255LcdScreenDataDma(Pxa255lcd* lcd, UInt32 addr/*PA*/, UInt32 len){
|
||||
|
||||
UInt8 data[4];
|
||||
UInt32 i, j;
|
||||
void* ptr;
|
||||
#ifndef PXA255_LCD_SUPPORTS_PALLETES
|
||||
UInt8 val[2];
|
||||
#endif
|
||||
|
||||
len /= 4;
|
||||
while(len--){
|
||||
pxa255LcdPrvDma(lcd, data, addr, 4);
|
||||
addr += 4;
|
||||
|
||||
switch((lcd->lccr3 >> 24) & 7){
|
||||
|
||||
case 0: //1BPP
|
||||
|
||||
#ifdef PXA255_LCD_SUPPORTS_PALLETES
|
||||
ptr = lcd->palette + ((data[i] >> j) & 1) * 2;
|
||||
#else
|
||||
ptr = val;
|
||||
pxa255LcdSetFakePal(val, 1, (data[i] >> j) & 1);
|
||||
#endif
|
||||
for(i = 0; i < 4; i += 1) for(j = 0; j < 8; j += 1) pxa255LcdScreenDataPixel(lcd, ptr);
|
||||
break;
|
||||
|
||||
case 1: //2BPP
|
||||
|
||||
#ifdef PXA255_LCD_SUPPORTS_PALLETES
|
||||
ptr = lcd->palette + ((data[i] >> j) & 3) * 2;
|
||||
#else
|
||||
ptr = val;
|
||||
pxa255LcdSetFakePal(val, 2, (data[i] >> j) & 3);
|
||||
#endif
|
||||
for(i = 0; i < 4; i += 1) for(j = 0; j < 8; j += 2) pxa255LcdScreenDataPixel(lcd, ptr);
|
||||
break;
|
||||
|
||||
case 2: //4BPP
|
||||
|
||||
#ifdef PXA255_LCD_SUPPORTS_PALLETES
|
||||
ptr = lcd->palette + ((data[i] >> j) & 15) * 2;
|
||||
#else
|
||||
ptr = val;
|
||||
pxa255LcdSetFakePal(val, 4, (data[i] >> j) & 15);
|
||||
#endif
|
||||
for(i = 0; i < 4; i += 1) for(j = 0; j < 8; j += 4) pxa255LcdScreenDataPixel(lcd, ptr);
|
||||
break;
|
||||
|
||||
case 3: //8BPP
|
||||
|
||||
#ifdef PXA255_LCD_SUPPORTS_PALLETES
|
||||
ptr = lcd->palette + (data[i] * 2);
|
||||
#else
|
||||
ptr = val;
|
||||
pxa255LcdSetFakePal(val, 8, data[i]);
|
||||
#endif
|
||||
for(i = 0; i < 4; i += 1) pxa255LcdScreenDataPixel(lcd, ptr);
|
||||
break;
|
||||
|
||||
case 4: //16BPP
|
||||
|
||||
for(i = 0; i < 4; i +=2 ) pxa255LcdScreenDataPixel(lcd, data + i);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
;//BAD
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
static void pxa255LcdScreenDataDma(Pxa255lcd* lcd, UInt32 addr/*PA*/, UInt32 len){
|
||||
|
||||
//nothing
|
||||
}
|
||||
#endif
|
||||
|
||||
void pxa255lcdFrame(Pxa255lcd* lcd){
|
||||
//every other call starts a frame, the others end one [this generates spacing between interrupts so as to not confuse guest OS]
|
||||
|
||||
if(lcd->enbChanged){
|
||||
|
||||
if(lcd->lccr0 & 0x0001){ //just got enabled
|
||||
|
||||
//TODO: perhaps check settings?
|
||||
}
|
||||
else{ // we just got quick disabled - kill current frame and do no more
|
||||
|
||||
lcd->lcsr |= 0x0080; //quick disable happened
|
||||
lcd->state = LCD_STATE_IDLE;
|
||||
}
|
||||
lcd->enbChanged = false;
|
||||
}
|
||||
|
||||
if(lcd->lccr0 & 0x0001){ //enabled - do a frame
|
||||
|
||||
UInt32 descrAddr, len;
|
||||
|
||||
switch(lcd->state){
|
||||
|
||||
case LCD_STATE_IDLE:
|
||||
|
||||
if(lcd->fbr0 & 1){ //branch
|
||||
|
||||
lcd->fbr0 &=~ 1UL;
|
||||
if(lcd->fbr0 & 2) lcd->lcsr |= 0x0200;
|
||||
descrAddr = lcd->fbr0 &~ 0xFUL;
|
||||
} else descrAddr = lcd->fdadr0;
|
||||
lcd->fdadr0 = pxa255PrvGetWord(lcd, descrAddr + 0);
|
||||
lcd->fsadr0 = pxa255PrvGetWord(lcd, descrAddr + 4);
|
||||
lcd->fidr0 = pxa255PrvGetWord(lcd, descrAddr + 8);
|
||||
lcd->ldcmd0 = pxa255PrvGetWord(lcd, descrAddr + 12);
|
||||
|
||||
lcd->state = LCD_STATE_DMA_0_START;
|
||||
break;
|
||||
|
||||
case LCD_STATE_DMA_0_START:
|
||||
|
||||
if(lcd->ldcmd0 & 0x00400000UL) lcd->lcsr |= 0x0002; //set SOF is DMA 0 started
|
||||
len = lcd->ldcmd0 & 0x000FFFFFUL;
|
||||
|
||||
if(lcd->ldcmd0 & 0x04000000UL){ //pallette data
|
||||
|
||||
#ifdef PXA255_LCD_SUPPORTS_PALLETES
|
||||
if(len > sizeof(lcd->palette)){
|
||||
|
||||
len = sizeof(lcd->palette);
|
||||
|
||||
pxa255LcdPrvDma(lcd, lcd->palette, lcd->fsadr0, len);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else{
|
||||
|
||||
lcd->frameNum++;
|
||||
if(!(lcd->frameNum & 63)) pxa255LcdScreenDataDma(lcd, lcd->fsadr0, len);
|
||||
}
|
||||
|
||||
lcd->state = LCD_STATE_DMA_0_END;
|
||||
break;
|
||||
|
||||
case LCD_STATE_DMA_0_END:
|
||||
|
||||
if(lcd->ldcmd0 & 0x00200000UL) lcd->lcsr |= 0x0100; //set EOF is DMA 0 finished
|
||||
lcd->state = LCD_STATE_IDLE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
pxa255lcdPrvUpdateInts(lcd);
|
||||
}
|
||||
|
||||
|
||||
Boolean pxa255lcdInit(Pxa255lcd* lcd, ArmMem* physMem, Pxa255ic* ic){
|
||||
|
||||
|
||||
__mem_zero(lcd, sizeof(Pxa255lcd));
|
||||
|
||||
lcd->ic = ic;
|
||||
lcd->mem = physMem;
|
||||
lcd->intMask = UNMASKABLE_INTS;
|
||||
|
||||
return memRegionAdd(physMem, PXA255_LCD_BASE, PXA255_LCD_SIZE, pxa255lcdPrvMemAccessF, lcd);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
63
contrib/other/uarm/pxa255_LCD.h
Executable file
63
contrib/other/uarm/pxa255_LCD.h
Executable file
@ -0,0 +1,63 @@
|
||||
#ifndef _PXA255_LCD_H_
|
||||
#define _PXA255_LCD_H_
|
||||
|
||||
#include "mem.h"
|
||||
#include "cpu.h"
|
||||
#include "pxa255_IC.h"
|
||||
|
||||
#ifndef EMBEDDED
|
||||
#define PXA255_LCD_SUPPORTS_PALLETES
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
PXA255 OS LCD controller
|
||||
|
||||
PURRPOSE: it's nice to have a framebuffer
|
||||
|
||||
*/
|
||||
|
||||
#define PXA255_LCD_BASE 0x44000000UL
|
||||
#define PXA255_LCD_SIZE 0x00001000UL
|
||||
|
||||
|
||||
|
||||
|
||||
#define LCD_STATE_IDLE 0
|
||||
#define LCD_STATE_DMA_0_START 1
|
||||
#define LCD_STATE_DMA_0_END 2
|
||||
|
||||
typedef struct{
|
||||
|
||||
Pxa255ic* ic;
|
||||
ArmMem* mem;
|
||||
|
||||
//registers
|
||||
UInt32 lccr0, lccr1, lccr2, lccr3, fbr0, fbr1, liicr, trgbr, tcr;
|
||||
UInt32 fdadr0, fsadr0, fidr0, ldcmd0;
|
||||
UInt32 fdadr1, fsadr1, fidr1, ldcmd1;
|
||||
UInt16 lcsr; //yes, 16-bit :)
|
||||
|
||||
//for our use
|
||||
UInt16 intMask;
|
||||
|
||||
UInt8 state : 6;
|
||||
UInt8 intWasPending : 1;
|
||||
UInt8 enbChanged : 1;
|
||||
|
||||
#ifdef PXA255_LCD_SUPPORTS_PALLETES
|
||||
|
||||
UInt8 palette[512];
|
||||
|
||||
#endif
|
||||
|
||||
UInt32 frameNum;
|
||||
|
||||
}Pxa255lcd;
|
||||
|
||||
Boolean pxa255lcdInit(Pxa255lcd* lcd, ArmMem* physMem, Pxa255ic* ic);
|
||||
void pxa255lcdFrame(Pxa255lcd* lcd);
|
||||
|
||||
|
||||
#endif
|
||||
|
154
contrib/other/uarm/pxa255_PwrClk.c
Executable file
154
contrib/other/uarm/pxa255_PwrClk.c
Executable file
@ -0,0 +1,154 @@
|
||||
#include "pxa255_PwrClk.h"
|
||||
|
||||
|
||||
static Boolean pxa255pwrClkPrvCoprocRegXferFunc(struct ArmCpu* cpu, void* userData, Boolean two, Boolean read, UInt8 op1, UInt8 Rx, UInt8 CRn, UInt8 CRm, UInt8 op2){
|
||||
|
||||
Pxa255pwrClk* pc = userData;
|
||||
UInt32 val = 0;
|
||||
|
||||
if(!read) val = cpuGetRegExternal(cpu, Rx);
|
||||
|
||||
if(CRm == 0 && op2 == 0 && op1 == 0 && !two){
|
||||
|
||||
switch(CRn){
|
||||
|
||||
case 6:
|
||||
if(read) val = 0;
|
||||
else{
|
||||
pc->turbo = (val & 1) != 0;
|
||||
if(val & 2){
|
||||
|
||||
err_str("Set speed mode");
|
||||
// err_str("(CCCR + cp14 reg6) to 0x");
|
||||
// err_hex(pc->CCCR);
|
||||
// err_str(", 0x");
|
||||
// err_hex(val);
|
||||
// err_str("\r\n");
|
||||
}
|
||||
}
|
||||
|
||||
case 7:
|
||||
if(read) val = pc->turbo ? 1 : 0;
|
||||
else if(val != 0){
|
||||
|
||||
// fprintf(stderr, "Someone tried to set processor power mode (cp14 reg7) to 0x%08lX\n", val);
|
||||
}
|
||||
goto success;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
success:
|
||||
|
||||
if(read) cpuSetReg(cpu, Rx, val);
|
||||
return true;
|
||||
}
|
||||
|
||||
static Boolean pxa255pwrClkPrvClockMgrMemAccessF(void* userData, UInt32 pa, UInt8 size, Boolean write, void* buf){
|
||||
|
||||
Pxa255pwrClk* pc = userData;
|
||||
UInt32 val = 0;
|
||||
|
||||
if(size != 4) {
|
||||
err_str(__FILE__ ": Unexpected ");
|
||||
// err_str(write ? "write" : "read");
|
||||
// err_str(" of ");
|
||||
// err_dec(size);
|
||||
// err_str(" bytes to 0x");
|
||||
// err_hex(pa);
|
||||
// err_str("\r\n");
|
||||
return true; //we do not support non-word accesses
|
||||
}
|
||||
|
||||
pa = (pa - PXA255_CLOCK_MANAGER_BASE) >> 2;
|
||||
|
||||
if(write) val = *(UInt32*)buf;
|
||||
|
||||
switch(pa){
|
||||
|
||||
case 0: //CCCR
|
||||
if(write) pc->CCCR = val;
|
||||
else val = pc->CCCR;
|
||||
break;
|
||||
|
||||
case 1: //CKEN
|
||||
if(write) pc->CKEN = val;
|
||||
else val = pc->CKEN;
|
||||
break;
|
||||
|
||||
case 2: //OSCR
|
||||
if(!write) val = pc->OSCR;
|
||||
//no writing to this register
|
||||
break;
|
||||
}
|
||||
|
||||
if(!write) *(UInt32*)buf = val;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static Boolean pxa255pwrClkPrvPowerMgrMemAccessF(void* userData, UInt32 pa, UInt8 size, Boolean write, void* buf){
|
||||
|
||||
Pxa255pwrClk* pc = userData;
|
||||
UInt32 val = 0;
|
||||
|
||||
if(size != 4) {
|
||||
err_str(__FILE__ ": Unexpected ");
|
||||
// err_str(write ? "write" : "read");
|
||||
// err_str(" of ");
|
||||
// err_dec(size);
|
||||
// err_str(" bytes to 0x");
|
||||
// err_hex(pa);
|
||||
// err_str("\r\n");
|
||||
return true; //we do not support non-word accesses
|
||||
}
|
||||
|
||||
pa = (pa - PXA255_POWER_MANAGER_BASE) >> 2;
|
||||
|
||||
if(write) val = *(UInt32*)buf;
|
||||
|
||||
if(pa < 13){
|
||||
|
||||
if(write) pc->pwrRegs[pa] = val;
|
||||
else val = pc->pwrRegs[pa];
|
||||
}
|
||||
|
||||
if(!write) *(UInt32*)buf = val;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Boolean pxa255pwrClkInit(Pxa255pwrClk* pc, ArmCpu* cpu, ArmMem* physMem){
|
||||
|
||||
ArmCoprocessor cp;
|
||||
Boolean ok = true;
|
||||
|
||||
__mem_zero(pc, sizeof(Pxa255pwrClk));
|
||||
|
||||
pc->cpu = cpu;
|
||||
pc->CCCR = 0x00000122UL; //set CCCR to almost default value (we use mult 32 not 27)
|
||||
pc->CKEN = 0x000179EFUL; //set CKEN to default value
|
||||
pc->OSCR = 0x00000003UL; //32KHz oscillator on and stable
|
||||
pc->pwrRegs[1] = 0x20; //set PSSR
|
||||
pc->pwrRegs[3] = 3; //set PWER
|
||||
pc->pwrRegs[4] = 3; //set PRER
|
||||
pc->pwrRegs[5] = 3; //set PFER
|
||||
pc->pwrRegs[12] = 1; //set RCSR
|
||||
|
||||
|
||||
cp.regXfer = pxa255pwrClkPrvCoprocRegXferFunc;
|
||||
cp.dataProcessing = NULL;
|
||||
cp.memAccess = NULL;
|
||||
cp.twoRegF = NULL;
|
||||
cp.userData = pc;
|
||||
|
||||
cpuCoprocessorRegister(cpu, 14, &cp);
|
||||
|
||||
ok = ok && memRegionAdd(physMem, PXA255_CLOCK_MANAGER_BASE, PXA255_CLOCK_MANAGER_SIZE, pxa255pwrClkPrvClockMgrMemAccessF, pc);
|
||||
ok = ok && memRegionAdd(physMem, PXA255_POWER_MANAGER_BASE, PXA255_POWER_MANAGER_SIZE, pxa255pwrClkPrvPowerMgrMemAccessF, pc);
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
|
32
contrib/other/uarm/pxa255_PwrClk.h
Executable file
32
contrib/other/uarm/pxa255_PwrClk.h
Executable file
@ -0,0 +1,32 @@
|
||||
#ifndef _PXA255_PWR_CLK_H_
|
||||
#define _PXA255_PWR_CLK_H_
|
||||
|
||||
#include "mem.h"
|
||||
#include "cpu.h"
|
||||
|
||||
|
||||
|
||||
typedef struct{
|
||||
|
||||
ArmCpu* cpu;
|
||||
UInt32 CCCR, CKEN, OSCR; //clocks manager regs
|
||||
UInt32 pwrRegs[13]; //we care so little about these, we don't even name them
|
||||
Boolean turbo;
|
||||
|
||||
}Pxa255pwrClk;
|
||||
|
||||
|
||||
#define PXA255_CLOCK_MANAGER_BASE 0x41300000UL
|
||||
#define PXA255_CLOCK_MANAGER_SIZE 0x00001000UL
|
||||
|
||||
#define PXA255_POWER_MANAGER_BASE 0x40F00000UL
|
||||
#define PXA255_POWER_MANAGER_SIZE 0x00001000UL
|
||||
|
||||
|
||||
Boolean pxa255pwrClkInit(Pxa255pwrClk* pc, ArmCpu* cpu, ArmMem* physMem);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
101
contrib/other/uarm/pxa255_RTC.c
Executable file
101
contrib/other/uarm/pxa255_RTC.c
Executable file
@ -0,0 +1,101 @@
|
||||
#include "pxa255_RTC.h"
|
||||
#include "mem.h"
|
||||
|
||||
|
||||
|
||||
void pxa255rtcPrvUpdate(Pxa255rtc* rtc){
|
||||
|
||||
UInt32 time = rtcCurTime();
|
||||
|
||||
if(rtc->lastSeenTime != time){ //do not triger alarm more than once per second please
|
||||
|
||||
if((rtc->RTSR & 0x4) && (time + rtc->RCNR_offset == rtc->RTAR)){ //check alarm
|
||||
rtc->RTSR |= 1;
|
||||
}
|
||||
if(rtc->RTSR & 0x8){ //send HZ interrupt
|
||||
rtc->RTSR |= 2;
|
||||
}
|
||||
}
|
||||
pxa255icInt(rtc->ic, PXA255_I_RTC_ALM, (rtc->RTSR & 1) != 0);
|
||||
pxa255icInt(rtc->ic, PXA255_I_RTC_HZ, (rtc->RTSR & 2) != 0);
|
||||
}
|
||||
|
||||
static Boolean pxa255rtcPrvMemAccessF(void* userData, UInt32 pa, UInt8 size, Boolean write, void* buf){
|
||||
|
||||
Pxa255rtc* rtc = userData;
|
||||
UInt32 val = 0;
|
||||
|
||||
if(size != 4) {
|
||||
err_str(__FILE__ ": Unexpected ");
|
||||
// err_str(write ? "write" : "read");
|
||||
// err_str(" of ");
|
||||
// err_dec(size);
|
||||
// err_str(" bytes to 0x");
|
||||
// err_hex(pa);
|
||||
// err_str("\r\n");
|
||||
return true; //we do not support non-word accesses
|
||||
}
|
||||
|
||||
pa = (pa - PXA255_RTC_BASE) >> 2;
|
||||
|
||||
if(write){
|
||||
val = *(UInt32*)buf;
|
||||
|
||||
switch(pa){
|
||||
case 0:
|
||||
rtc->RCNR_offset = rtcCurTime() - val;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
rtc->RTAR = val;
|
||||
pxa255rtcPrvUpdate(rtc);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
rtc->RTSR = (val &~ 3UL) | ((rtc->RTSR &~ val) & 3UL);
|
||||
pxa255rtcPrvUpdate(rtc);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
if(!(rtc->RTTR & 0x80000000UL)) rtc->RTTR = val;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else{
|
||||
switch(pa){
|
||||
case 0:
|
||||
val = rtcCurTime() - rtc->RCNR_offset;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
val = rtc->RTAR;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
val = rtc->RTSR;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
val = rtc->RTTR;
|
||||
break;
|
||||
}
|
||||
*(UInt32*)buf = val;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Boolean pxa255rtcInit(Pxa255rtc* rtc, ArmMem* physMem, Pxa255ic* ic){
|
||||
|
||||
__mem_zero(rtc, sizeof(Pxa255rtc));
|
||||
rtc->ic = ic;
|
||||
rtc->RCNR_offset = 0;
|
||||
rtc->RTTR = 0x7FFF; //nice default value
|
||||
rtc->lastSeenTime = rtcCurTime();
|
||||
return memRegionAdd(physMem, PXA255_RTC_BASE, PXA255_RTC_SIZE, pxa255rtcPrvMemAccessF, rtc);
|
||||
}
|
||||
|
||||
void pxa255rtcUpdate(Pxa255rtc* rtc){
|
||||
pxa255rtcPrvUpdate(rtc);
|
||||
}
|
37
contrib/other/uarm/pxa255_RTC.h
Executable file
37
contrib/other/uarm/pxa255_RTC.h
Executable file
@ -0,0 +1,37 @@
|
||||
#ifndef _PXA255_RTC_H_
|
||||
#define _PXA255_RTC_H_
|
||||
|
||||
#include "mem.h"
|
||||
#include "cpu.h"
|
||||
#include "pxa255_IC.h"
|
||||
|
||||
|
||||
/*
|
||||
PXA255 OS RTC controller
|
||||
|
||||
PURRPOSE: it's nice to know what time it is
|
||||
|
||||
*/
|
||||
|
||||
#define PXA255_RTC_BASE 0x40900000UL
|
||||
#define PXA255_RTC_SIZE 0x00001000UL
|
||||
|
||||
|
||||
typedef struct{
|
||||
|
||||
Pxa255ic* ic;
|
||||
|
||||
UInt32 RCNR_offset; //RTC counter offset from our local time
|
||||
UInt32 RTAR; //RTC alarm
|
||||
UInt32 RTSR; //RTC status
|
||||
UInt32 RTTR; //RTC trim - we ignore this alltogether
|
||||
UInt32 lastSeenTime; //for HZ interrupt
|
||||
|
||||
}Pxa255rtc;
|
||||
|
||||
Boolean pxa255rtcInit(Pxa255rtc* rtc, ArmMem* physMem, Pxa255ic* ic);
|
||||
void pxa255rtcUpdate(Pxa255rtc* rtc);
|
||||
|
||||
|
||||
#endif
|
||||
|
123
contrib/other/uarm/pxa255_TIMR.c
Executable file
123
contrib/other/uarm/pxa255_TIMR.c
Executable file
@ -0,0 +1,123 @@
|
||||
#include "pxa255_TIMR.h"
|
||||
#include "mem.h"
|
||||
|
||||
|
||||
static void pxa255timrPrvRaiseLowerInts(Pxa255timr* timr){
|
||||
|
||||
pxa255icInt(timr->ic, PXA255_I_TIMR0, (timr->OSSR & 1) != 0);
|
||||
pxa255icInt(timr->ic, PXA255_I_TIMR1, (timr->OSSR & 2) != 0);
|
||||
pxa255icInt(timr->ic, PXA255_I_TIMR2, (timr->OSSR & 4) != 0);
|
||||
pxa255icInt(timr->ic, PXA255_I_TIMR3, (timr->OSSR & 8) != 0);
|
||||
}
|
||||
|
||||
static void pxa255timrPrvCheckMatch(Pxa255timr* timr, UInt8 idx){
|
||||
|
||||
UInt8 v = 1UL << idx;
|
||||
|
||||
if((timr->OSCR == timr->OSMR[idx]) && (timr->OIER & v)){
|
||||
timr->OSSR |= v;
|
||||
}
|
||||
}
|
||||
|
||||
static void pxa255timrPrvUpdate(Pxa255timr* timr){
|
||||
|
||||
pxa255timrPrvCheckMatch(timr, 0);
|
||||
pxa255timrPrvCheckMatch(timr, 1);
|
||||
pxa255timrPrvCheckMatch(timr, 2);
|
||||
pxa255timrPrvCheckMatch(timr, 3);
|
||||
}
|
||||
|
||||
static Boolean pxa255timrPrvMemAccessF(void* userData, UInt32 pa, UInt8 size, Boolean write, void* buf){
|
||||
|
||||
Pxa255timr* timr = userData;
|
||||
UInt32 val = 0;
|
||||
|
||||
if(size != 4) {
|
||||
err_str(__FILE__ ": Unexpected ");
|
||||
// err_str(write ? "write" : "read");
|
||||
// err_str(" of ");
|
||||
// err_dec(size);
|
||||
// err_str(" bytes to 0x");
|
||||
// err_hex(pa);
|
||||
// err_str("\r\n");
|
||||
return true; //we do not support non-word accesses
|
||||
}
|
||||
|
||||
pa = (pa - PXA255_TIMR_BASE) >> 2;
|
||||
|
||||
if(write){
|
||||
val = *(UInt32*)buf;
|
||||
|
||||
switch(pa){
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
timr->OSMR[pa] = val;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
timr->OSCR = val;
|
||||
break;
|
||||
|
||||
case 5:
|
||||
timr->OSSR = timr->OSSR &~ val;
|
||||
pxa255timrPrvRaiseLowerInts(timr);
|
||||
break;
|
||||
|
||||
case 6:
|
||||
timr->OWER = val;
|
||||
break;
|
||||
|
||||
case 7:
|
||||
timr->OIER = val;
|
||||
pxa255timrPrvUpdate(timr);
|
||||
pxa255timrPrvRaiseLowerInts(timr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else{
|
||||
switch(pa){
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
val = timr->OSMR[pa];
|
||||
break;
|
||||
|
||||
case 4:
|
||||
val = timr->OSCR;
|
||||
break;
|
||||
|
||||
case 5:
|
||||
val = timr->OSSR;
|
||||
break;
|
||||
|
||||
case 6:
|
||||
val = timr->OWER;
|
||||
break;
|
||||
|
||||
case 7:
|
||||
val = timr->OIER;
|
||||
break;
|
||||
}
|
||||
*(UInt32*)buf = val;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Boolean pxa255timrInit(Pxa255timr* timr, ArmMem* physMem, Pxa255ic* ic){
|
||||
|
||||
__mem_zero(timr, sizeof(Pxa255timr));
|
||||
timr->ic = ic;
|
||||
return memRegionAdd(physMem, PXA255_TIMR_BASE, PXA255_TIMR_SIZE, pxa255timrPrvMemAccessF, timr);
|
||||
}
|
||||
|
||||
void pxa255timrTick(Pxa255timr* timr){
|
||||
|
||||
timr->OSCR++;
|
||||
pxa255timrPrvUpdate(timr);
|
||||
pxa255timrPrvRaiseLowerInts(timr);
|
||||
}
|
37
contrib/other/uarm/pxa255_TIMR.h
Executable file
37
contrib/other/uarm/pxa255_TIMR.h
Executable file
@ -0,0 +1,37 @@
|
||||
#ifndef _PXA255_TIMR_H_
|
||||
#define _PXA255_TIMR_H_
|
||||
|
||||
#include "mem.h"
|
||||
#include "cpu.h"
|
||||
#include "pxa255_IC.h"
|
||||
|
||||
|
||||
/*
|
||||
PXA255 OS timers controller
|
||||
|
||||
PURRPOSE: timers are useful for stuff :)
|
||||
|
||||
*/
|
||||
|
||||
#define PXA255_TIMR_BASE 0x40A00000UL
|
||||
#define PXA255_TIMR_SIZE 0x00010000UL
|
||||
|
||||
|
||||
typedef struct{
|
||||
|
||||
Pxa255ic* ic;
|
||||
|
||||
UInt32 OSMR[4]; //Match Register 0-3
|
||||
UInt32 OIER; //Interrupt Enable
|
||||
UInt32 OWER; //Watchdog enable
|
||||
UInt32 OSCR; //Counter Register
|
||||
UInt32 OSSR; //Status Register
|
||||
|
||||
}Pxa255timr;
|
||||
|
||||
Boolean pxa255timrInit(Pxa255timr* timr, ArmMem* physMem, Pxa255ic* ic);
|
||||
void pxa255timrTick(Pxa255timr* timr);
|
||||
|
||||
|
||||
#endif
|
||||
|
588
contrib/other/uarm/pxa255_UART.c
Executable file
588
contrib/other/uarm/pxa255_UART.c
Executable file
@ -0,0 +1,588 @@
|
||||
#include "pxa255_UART.h"
|
||||
#include "mem.h"
|
||||
|
||||
|
||||
|
||||
//TODO: signal handler for Ctl+C and send break to fifo :)
|
||||
//todo: recalc ints after eveyr write and every call to "process" from SoC
|
||||
|
||||
|
||||
#define UART_IER_DMAE 0x80 //DMA enable
|
||||
#define UART_IER_UUE 0x40 //Uart unit enable
|
||||
#define UART_IER_NRZE 0x20 //NRZI enable
|
||||
#define UART_IER_RTOIE 0x10 //transmit timeout interrupt enable
|
||||
#define UART_IER_MIE 0x08 //modem interrupt enable
|
||||
#define UART_IER_RLSE 0x04 //receiver line status interrupt enable
|
||||
#define UART_IER_TIE 0x02 //transmit data request interrupt enable
|
||||
#define UART_IER_RAVIE 0x01 //receiver data available interrupt enable
|
||||
|
||||
#define UART_IIR_FIFOES 0xC0 //fifo enable status
|
||||
#define UART_IIR_TOD 0x08 //character timout interrupt pending
|
||||
#define UART_IIR_RECV_ERR 0x06 //receive error(overrun, parity, framing, break)
|
||||
#define UART_IIR_RECV_DATA 0x04 //receive data available
|
||||
#define UART_IIR_RCV_TIMEOUT 0x0C //receive data in buffer and been a while since we've seen more
|
||||
#define UART_IIR_SEND_DATA 0x02 //transmit fifo requests data
|
||||
#define UART_IIR_MODEM_STAT 0x00 //modem lines changed state(CTS, DSR, DI, DCD)
|
||||
#define UART_IIR_NOINT 0x01 //no interrupt pending
|
||||
|
||||
|
||||
#define UART_FCR_ITL_MASK 0xC0 //mask for ITL part of FCR
|
||||
#define UART_FCR_ITL_1 0x00 //interrupt when >=1 byte in recv fifo
|
||||
#define UART_FCR_ITL_8 0x40 //interrupt when >=8 byte in recv fifo
|
||||
#define UART_FCR_ITL_16 0x80 //interrupt when >=16 byte in recv fifo
|
||||
#define UART_FCR_ITL_32 0xC0 //interrupt when >=32 byte in recv fifo
|
||||
#define UART_FCR_RESETTF 0x04 //reset tranmitter fifo
|
||||
#define UART_FCR_RESETRF 0x02 //reset receiver fifo
|
||||
#define UART_FCR_TRFIFOE 0x01 //transmit and receive fifo enable
|
||||
|
||||
#define UART_LCR_DLAB 0x80 //divisor latch access bit
|
||||
#define UART_LCR_SB 0x40 //send break
|
||||
#define UART_LCR_STKYP 0x20 //sticky parity (send parity bit but dont care what value)
|
||||
#define UART_LCR_EPS 0x10 //even parity select
|
||||
#define UART_LCR_PEN 0x08 //parity enable
|
||||
#define UART_LCR_STB 0x04 //stop bits (1 = 2, 0 = 1)
|
||||
#define UART_LCR_WLS_MASK 0x03 //mask for WLS values
|
||||
#define UART_LCR_WLS_8 0x03 //8 bit words
|
||||
#define UART_LCR_WLS_7 0x02 //7 bit words
|
||||
#define UART_LCR_WLS_6 0x01 //6 bit words
|
||||
#define UART_LCR_WLS_5 0x00 //5 bit words
|
||||
|
||||
#define UART_LSR_FIFOE 0x80 //fifo contails an error (framing, parity, or break)
|
||||
#define UART_LSR_TEMT 0x40 //tranmitter empty (shift reg is empty and no more byte sin fifo/no byte in holding reg)
|
||||
#define UART_LSR_TDRQ 0x20 //transmitter data request (see docs)
|
||||
#define UART_LSR_BI 0x10 //send when char at front of fifo (or in holding reg) was a break char (chr reads as zero by itself)
|
||||
#define UART_LSR_FE 0x08 //same as above, but for framing errors
|
||||
#define UART_LSR_PE 0x04 //dame as above, but for parity errors
|
||||
#define UART_LSR_OE 0x02 //recv fifo overran
|
||||
#define UART_LSR_DR 0x01 //byte received
|
||||
|
||||
#define UART_MCR_LOOP 0x10 //loop modem control lines (not full loopback)
|
||||
#define UART_MCR_OUT2 0x08 //when loop is 0 enables or disables UART interrupts
|
||||
#define UART_MCR_OUT1 0x04 //force RI to 1
|
||||
#define UART_MCR_RTS 0x02 //1 -> nRTS is 0
|
||||
#define UART_MCR_DTR 0x01 //0 -> nDTR is 0
|
||||
|
||||
#define UART_MSR_DCD 0x80
|
||||
#define UART_MSR_RI 0x40
|
||||
#define UART_MSR_DSR 0x20
|
||||
#define UART_MSR_CTS 0x10
|
||||
#define UART_MSR_DDCD 0x08 //dcd changed since last read
|
||||
#define UART_MSR_TERI 0x04 //ri has changed from 0 to 1 since last read
|
||||
#define UART_MSR_DDSR 0x02 //dsr changed since last read
|
||||
#define UART_MSR_DCTS 0x01 //cts changed since last read
|
||||
|
||||
|
||||
|
||||
static void pxa255uartPrvRecalc(Pxa255uart* uart);
|
||||
|
||||
|
||||
static void pxa255uartPrvIrq(Pxa255uart* uart, Boolean raise){
|
||||
|
||||
pxa255icInt(uart->ic, uart->irq, !(uart->MCR & UART_MCR_LOOP) && (uart->MCR & UART_MCR_OUT2) && raise/* only raise if ints are enabled */);
|
||||
}
|
||||
|
||||
static UInt16 pxa255uartPrvDefaultRead(_UNUSED_ void* userData){ //these are special funcs since they always get their own userData - the uart pointer :)
|
||||
|
||||
return UART_CHAR_NONE; //we read nothing..as always
|
||||
}
|
||||
|
||||
static void pxa255uartPrvDefaultWrite(_UNUSED_ UInt16 chr, _UNUSED_ void* userData){ //these are special funcs since they always get their own userData - the uart pointer :)
|
||||
|
||||
//nothing to do here
|
||||
}
|
||||
|
||||
static UInt16 pxa255uartPrvGetchar(Pxa255uart* uart){
|
||||
|
||||
Pxa255UartReadF func = uart->readF;
|
||||
void* data = (func == pxa255uartPrvDefaultRead) ? uart : uart->accessFuncsData;
|
||||
|
||||
return func(data);
|
||||
}
|
||||
|
||||
static void pxa255uartPrvPutchar(Pxa255uart* uart, UInt16 chr){
|
||||
|
||||
Pxa255UartWriteF func = uart->writeF;
|
||||
void* data = (func == pxa255uartPrvDefaultWrite) ? uart : uart->accessFuncsData;
|
||||
|
||||
func(chr, data);
|
||||
}
|
||||
|
||||
UInt8 pxa255uartPrvFifoUsed(UartFifo* fifo){ //return num spots used
|
||||
|
||||
UInt8 v;
|
||||
|
||||
if(fifo->read == UART_FIFO_EMPTY) return 0;
|
||||
v = fifo->write + UART_FIFO_DEPTH - fifo->read;
|
||||
if(v > UART_FIFO_DEPTH) v -=UART_FIFO_DEPTH;
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
void pxa255uartPrvFifoFlush(UartFifo* fifo){
|
||||
|
||||
fifo->read = UART_FIFO_EMPTY;
|
||||
fifo->write = UART_FIFO_EMPTY;
|
||||
}
|
||||
|
||||
Boolean pxa255uartPrvFifoPut(UartFifo* fifo, UInt16 val){ //return success
|
||||
|
||||
if(fifo->read == UART_FIFO_EMPTY){
|
||||
|
||||
fifo->read = 0;
|
||||
fifo->write = 1;
|
||||
fifo->buf[0] = val;
|
||||
}
|
||||
else if(fifo->read != fifo->write){ //only if not full
|
||||
|
||||
fifo->buf[fifo->write++] = val;
|
||||
if(fifo->write == UART_FIFO_DEPTH) fifo->write = 0;
|
||||
}
|
||||
else return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
UInt16 pxa255uartPrvFifoGet(UartFifo* fifo){
|
||||
|
||||
UInt16 ret;
|
||||
|
||||
if(fifo->read == UART_FIFO_EMPTY){
|
||||
|
||||
ret = 0xFFFF; //why not?
|
||||
}
|
||||
else{
|
||||
|
||||
ret = fifo->buf[fifo->read++];
|
||||
if(fifo->read == UART_FIFO_DEPTH) fifo->read = 0;
|
||||
|
||||
if(fifo->read == fifo->write){ //it is now empty
|
||||
|
||||
fifo->read = UART_FIFO_EMPTY;
|
||||
fifo->write = UART_FIFO_EMPTY;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
UInt16 pxa255uartPrvFifoPeekNth(UartFifo* fifo, UInt8 n){
|
||||
|
||||
UInt16 ret;
|
||||
|
||||
|
||||
if(fifo->read == UART_FIFO_EMPTY){
|
||||
|
||||
ret = 0xFFFF; //why not?
|
||||
}
|
||||
else{
|
||||
|
||||
n += fifo->read;
|
||||
if(n >= UART_FIFO_DEPTH) n-= UART_FIFO_DEPTH;
|
||||
ret = fifo->buf[n];
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
UInt16 pxa255uartPrvFifoPeek(UartFifo* fifo){
|
||||
|
||||
return pxa255uartPrvFifoPeekNth(fifo, 0);
|
||||
}
|
||||
|
||||
|
||||
static void sendVal(Pxa255uart* uart, UInt16 v){
|
||||
|
||||
if(uart->LSR & UART_LSR_TEMT){ //if transmit, put in shift register immediately if it's idle
|
||||
|
||||
uart->transmitShift = v;
|
||||
uart->LSR &=~ UART_LSR_TEMT;
|
||||
}
|
||||
else if(uart->FCR & UART_FCR_TRFIFOE){ //put in tx fifo if in fifo mode
|
||||
|
||||
pxa255uartPrvFifoPut(&uart->TX, v);
|
||||
if(pxa255uartPrvFifoUsed(&uart->TX) > UART_FIFO_DEPTH / 2){ //we go went below half-full buffer - set appropriate bit...
|
||||
|
||||
uart->LSR &=~ UART_LSR_TDRQ;
|
||||
}
|
||||
}
|
||||
else if(uart->LSR & UART_LSR_TDRQ){ //send without fifo if in polled mode
|
||||
|
||||
uart->transmitHolding = v;
|
||||
uart->LSR &=~ UART_LSR_TDRQ;
|
||||
}
|
||||
else{
|
||||
|
||||
//nothing to do - buffer is full so we ignore this request
|
||||
}
|
||||
}
|
||||
|
||||
static Boolean pxa255uartPrvMemAccessF(void* userData, UInt32 pa, UInt8 size, Boolean write, void* buf){
|
||||
|
||||
Pxa255uart* uart = userData;
|
||||
Boolean DLAB = (uart->LCR & UART_LCR_DLAB) != 0;
|
||||
Boolean recalcValues = false;
|
||||
UInt8 t, val = 0;
|
||||
|
||||
if(size != 4 && size != 1) {
|
||||
err_str(__FILE__ ": Unexpected ");
|
||||
// err_str(write ? "write" : "read");
|
||||
// err_str(" of ");
|
||||
// err_dec(size);
|
||||
// err_str(" bytes to 0x");
|
||||
// err_hex(pa);
|
||||
// err_str("\r\n");
|
||||
return true; //we do not support non-word accesses
|
||||
}
|
||||
|
||||
pa = (pa - uart->baseAddr) >> 2;
|
||||
|
||||
if(write){
|
||||
recalcValues = true;
|
||||
val = (size == 1) ? *(UInt8*)buf : *(UInt32*)buf;
|
||||
|
||||
switch(pa){
|
||||
case 0:
|
||||
if(DLAB){ //if DLAB - set "baudrate"...
|
||||
uart->DLL = val;
|
||||
recalcValues = false;
|
||||
}
|
||||
else{
|
||||
|
||||
sendVal(uart, val);
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:
|
||||
if(DLAB){
|
||||
|
||||
uart->DLH = val;
|
||||
recalcValues = false;
|
||||
}
|
||||
else{
|
||||
t = uart->IER ^ val;
|
||||
|
||||
if(t & UART_IER_DMAE){
|
||||
|
||||
err_str("pxa255UART: DMA mode cannot be enabled");
|
||||
t &=~ UART_IER_DMAE; //undo the change
|
||||
}
|
||||
|
||||
if(t & UART_IER_UUE){
|
||||
|
||||
if(val & UART_IER_UUE){
|
||||
|
||||
uart->LSR = UART_LSR_TEMT | UART_LSR_TDRQ;
|
||||
uart->MSR = UART_MSR_CTS;
|
||||
}
|
||||
}
|
||||
|
||||
uart->IER ^= t;
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
t = uart->FCR ^ val;
|
||||
if(t & UART_FCR_TRFIFOE){
|
||||
if(val & UART_FCR_TRFIFOE){ //fifos are now on - perform other actions as requested
|
||||
|
||||
if(val & UART_FCR_RESETRF){
|
||||
|
||||
pxa255uartPrvFifoFlush(&uart->RX); //clear the RX fifo now
|
||||
}
|
||||
if(val & UART_FCR_RESETTF){
|
||||
|
||||
pxa255uartPrvFifoFlush(&uart->TX); //clear the TX fifo now
|
||||
uart->LSR = UART_LSR_TEMT | UART_LSR_TDRQ;
|
||||
}
|
||||
uart->IIR = UART_IIR_FIFOES |UART_IIR_NOINT;
|
||||
}
|
||||
else{
|
||||
pxa255uartPrvFifoFlush(&uart->TX);
|
||||
pxa255uartPrvFifoFlush(&uart->RX);
|
||||
uart->LSR = UART_LSR_TEMT | UART_LSR_TDRQ;
|
||||
uart->IIR = UART_IIR_NOINT;
|
||||
}
|
||||
}
|
||||
uart->FCR = val;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
t = uart->LCR ^ val;
|
||||
if(t & UART_LCR_SB){
|
||||
if(val & UART_LCR_SB){ //break set (tx line pulled low)
|
||||
|
||||
|
||||
}
|
||||
else{ //break cleared (tx line released)
|
||||
|
||||
sendVal(uart, UART_CHAR_BREAK);
|
||||
}
|
||||
}
|
||||
uart->LCR = val;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
uart->MCR = val;
|
||||
break;
|
||||
|
||||
case 7:
|
||||
uart->SPR = val;
|
||||
break;
|
||||
|
||||
case 8:
|
||||
uart->ISR = val;
|
||||
if(val & 3){
|
||||
err_str("UART: IrDA mode set on UART\n");
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
else{
|
||||
switch(pa){
|
||||
case 0:
|
||||
if(DLAB) val = uart->DLL;
|
||||
else if(!(uart->LSR & UART_LSR_DR)){ //no data-> too bad
|
||||
|
||||
val = 0;
|
||||
}
|
||||
else if(uart->FCR & UART_FCR_TRFIFOE){ //fifo mode -> read fifo
|
||||
|
||||
val = pxa255uartPrvFifoGet(&uart->RX);
|
||||
if(!pxa255uartPrvFifoUsed(&uart->RX)) uart->LSR &=~ UART_LSR_DR;
|
||||
recalcValues = true; //error bits might have changed
|
||||
}
|
||||
else{ //polled mode -> read rx polled reg
|
||||
|
||||
val = uart->receiveHolding;
|
||||
uart->LSR &=~ UART_LSR_DR;
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:
|
||||
if(DLAB) val = uart->DLH;
|
||||
else val = uart->IER;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
val = uart->IIR;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
val = uart->LCR;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
val = uart->MCR;
|
||||
break;
|
||||
|
||||
case 5:
|
||||
val = uart->LSR;
|
||||
break;
|
||||
|
||||
case 6:
|
||||
val = uart->MSR;
|
||||
break;
|
||||
|
||||
case 7:
|
||||
val = uart->SPR;
|
||||
break;
|
||||
|
||||
case 8:
|
||||
val = uart->ISR;
|
||||
break;
|
||||
}
|
||||
if(size == 1) *(UInt8*)buf = val;
|
||||
else *(UInt32*)buf = val;
|
||||
}
|
||||
|
||||
if(recalcValues) pxa255uartPrvRecalc(uart);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void pxa255uartSetFuncs(Pxa255uart* uart, Pxa255UartReadF readF, Pxa255UartWriteF writeF, void* userData){
|
||||
|
||||
if(!readF) readF = pxa255uartPrvDefaultRead; //these are special funcs since they get their own private data - the uart :)
|
||||
if(!writeF) writeF = pxa255uartPrvDefaultWrite;
|
||||
|
||||
uart->readF = readF;
|
||||
uart->writeF = writeF;
|
||||
uart->accessFuncsData = userData;
|
||||
}
|
||||
|
||||
Boolean pxa255uartInit(Pxa255uart* uart, ArmMem* physMem, Pxa255ic* ic, UInt32 baseAddr, UInt8 irq){
|
||||
|
||||
__mem_zero(uart, sizeof(Pxa255uart));
|
||||
uart->ic = ic;
|
||||
uart->irq = irq;
|
||||
uart->baseAddr = baseAddr;
|
||||
uart->IIR = UART_IIR_NOINT;
|
||||
uart->IER = UART_IER_UUE | UART_IER_NRZE; //uart on
|
||||
uart->LSR = UART_LSR_TEMT | UART_LSR_TDRQ;
|
||||
uart->MSR = UART_MSR_CTS;
|
||||
pxa255uartPrvFifoFlush(&uart->TX);
|
||||
pxa255uartPrvFifoFlush(&uart->RX);
|
||||
|
||||
|
||||
pxa255uartSetFuncs(uart, NULL, NULL, NULL);
|
||||
|
||||
return memRegionAdd(physMem, baseAddr, PXA255_UART_SIZE, pxa255uartPrvMemAccessF, uart);
|
||||
}
|
||||
|
||||
void pxa255uartProcess(Pxa255uart* uart){ //send and rceive up to one character
|
||||
|
||||
UInt8 t;
|
||||
UInt16 v;
|
||||
|
||||
//first process sending (if any)
|
||||
if(!(uart->LSR & UART_LSR_TEMT)){
|
||||
|
||||
pxa255uartPrvPutchar(uart, uart->transmitShift);
|
||||
|
||||
if(uart->FCR & UART_FCR_TRFIFOE){ //fifo mode
|
||||
|
||||
t = pxa255uartPrvFifoUsed(&uart->TX);
|
||||
|
||||
if(t--){
|
||||
|
||||
uart->transmitShift = pxa255uartPrvFifoGet(&uart->TX);
|
||||
if(t <= UART_FIFO_DEPTH / 2) uart->LSR |= UART_LSR_TDRQ; //above half full - clear TDRQ bit
|
||||
}
|
||||
else{
|
||||
|
||||
uart->LSR |= UART_LSR_TEMT;
|
||||
}
|
||||
}
|
||||
else if (uart->LSR & UART_LSR_TDRQ){
|
||||
|
||||
uart->LSR |= UART_LSR_TEMT;
|
||||
}
|
||||
else{
|
||||
|
||||
uart->transmitShift = uart->transmitHolding;
|
||||
uart->LSR |= UART_LSR_TDRQ;
|
||||
}
|
||||
}
|
||||
|
||||
//now process receiving
|
||||
v = pxa255uartPrvGetchar(uart);
|
||||
if(v != UART_CHAR_NONE){
|
||||
|
||||
uart->cyclesSinceRecv = 0;
|
||||
uart->LSR |= UART_LSR_DR;
|
||||
|
||||
if(uart->FCR & UART_FCR_TRFIFOE){ //fifo mode
|
||||
|
||||
if(!pxa255uartPrvFifoPut(&uart->RX, v)){
|
||||
|
||||
uart->LSR |= UART_LSR_OE;
|
||||
}
|
||||
}
|
||||
else{
|
||||
|
||||
if(uart->LSR & UART_LSR_DR) uart->LSR |= UART_LSR_OE;
|
||||
else uart->receiveHolding = v;
|
||||
}
|
||||
}
|
||||
else if(uart->cyclesSinceRecv <= 4){
|
||||
uart->cyclesSinceRecv++;
|
||||
}
|
||||
|
||||
pxa255uartPrvRecalc(uart);
|
||||
}
|
||||
|
||||
static void pxa255uartPrvRecalcCharBits(Pxa255uart* uart, UInt16 c){
|
||||
|
||||
if(c & UART_CHAR_BREAK) uart->LSR |= UART_LSR_BI;
|
||||
if(c & UART_CHAR_FRAME_ERR) uart->LSR |= UART_LSR_FE;
|
||||
if(c & UART_CHAR_PAR_ERR) uart->LSR |= UART_LSR_PE;
|
||||
}
|
||||
|
||||
static void pxa255uartPrvRecalc(Pxa255uart* uart){
|
||||
|
||||
Boolean errorSet = false;
|
||||
UInt8 v;
|
||||
|
||||
uart->LSR &=~ UART_LSR_FIFOE;
|
||||
uart->IIR &= UART_IIR_FIFOES; //clear all other bits...
|
||||
uart->LSR &=~ (UART_LSR_BI | UART_LSR_FE | UART_LSR_PE);
|
||||
|
||||
if(uart->FCR & UART_FCR_TRFIFOE){ //fifo mode
|
||||
|
||||
|
||||
//check rx fifo for errors
|
||||
for(v = 0; v < pxa255uartPrvFifoUsed(&uart->RX); v++){
|
||||
|
||||
if((pxa255uartPrvFifoPeekNth(&uart->RX, v) >> 8) && (uart->IER & UART_IER_RLSE)){
|
||||
|
||||
uart->LSR |= UART_LSR_FIFOE;
|
||||
uart->IIR |= UART_IIR_RECV_ERR;
|
||||
errorSet = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
v = pxa255uartPrvFifoUsed(&uart->RX);
|
||||
if(v){
|
||||
pxa255uartPrvRecalcCharBits(uart, pxa255uartPrvFifoPeek(&uart->RX));
|
||||
}
|
||||
|
||||
switch(uart->FCR & UART_FCR_ITL_MASK){
|
||||
|
||||
case UART_FCR_ITL_1:
|
||||
v = v >= 1;
|
||||
break;
|
||||
|
||||
case UART_FCR_ITL_8:
|
||||
v = v >= 8;
|
||||
break;
|
||||
|
||||
case UART_FCR_ITL_16:
|
||||
v = v >= 16;
|
||||
break;
|
||||
|
||||
case UART_FCR_ITL_32:
|
||||
v = v >= 32;
|
||||
break;
|
||||
}
|
||||
if(v && (uart->IER & UART_IER_RAVIE) && !errorSet){
|
||||
|
||||
errorSet = true;
|
||||
uart->IIR |= UART_IIR_RECV_DATA;
|
||||
}
|
||||
if(pxa255uartPrvFifoUsed(&uart->RX) && uart->cyclesSinceRecv >= 4 && (uart->IER & UART_IER_RAVIE) && !errorSet){
|
||||
|
||||
errorSet = true;
|
||||
uart->IIR |= UART_IIR_RCV_TIMEOUT;
|
||||
}
|
||||
}
|
||||
else{ //polling mode
|
||||
|
||||
UInt16 c = uart->receiveHolding;
|
||||
|
||||
if(uart->LSR & UART_LSR_DR){
|
||||
|
||||
pxa255uartPrvRecalcCharBits(uart, c);
|
||||
|
||||
if((c >> 8) && !errorSet && (uart->IER & UART_IER_RLSE)){
|
||||
|
||||
uart->IIR |= UART_IIR_RECV_ERR;
|
||||
errorSet = true;
|
||||
}
|
||||
else if(!errorSet && (uart->IER & UART_IER_RAVIE)){
|
||||
|
||||
uart->IIR |= UART_IIR_RECV_DATA;
|
||||
errorSet = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(uart->LSR & UART_LSR_TDRQ && !errorSet && (uart->IER & UART_IER_TIE)){
|
||||
|
||||
errorSet = true;
|
||||
uart->IIR |= UART_IIR_SEND_DATA;
|
||||
}
|
||||
|
||||
if(!errorSet) uart->IIR |= UART_IIR_NOINT;
|
||||
pxa255uartPrvIrq(uart, errorSet);
|
||||
}
|
88
contrib/other/uarm/pxa255_UART.h
Executable file
88
contrib/other/uarm/pxa255_UART.h
Executable file
@ -0,0 +1,88 @@
|
||||
#ifndef _PXA255_UART_H_
|
||||
#define _PXA255_UART_H_
|
||||
|
||||
#include "mem.h"
|
||||
#include "cpu.h"
|
||||
#include "pxa255_IC.h"
|
||||
|
||||
|
||||
/*
|
||||
PXA255 UARTs
|
||||
|
||||
PXA255 has three. they are identical, but at diff base addresses. this implements one. instanciate more than one of this struct to make all 3 work if needed.
|
||||
PURRPOSE: this is how linux talks to us :)
|
||||
|
||||
|
||||
by default we read nothing and write nowhere (buffer drains fast into nothingness)
|
||||
this can be changed by addidng appropriate callbacks
|
||||
|
||||
*/
|
||||
|
||||
#define PXA255_FFUART_BASE 0x40100000UL
|
||||
#define PXA255_BTUART_BASE 0x40200000UL
|
||||
#define PXA255_STUART_BASE 0x40700000UL
|
||||
#define PXA255_UART_SIZE 0x00010000UL
|
||||
|
||||
#define UART_FIFO_DEPTH 64
|
||||
|
||||
|
||||
#define UART_CHAR_BREAK 0x800
|
||||
#define UART_CHAR_FRAME_ERR 0x400
|
||||
#define UART_CHAR_PAR_ERR 0x200
|
||||
#define UART_CHAR_NONE 0x100
|
||||
|
||||
typedef UInt16 (*Pxa255UartReadF)(void* userData);
|
||||
typedef void (*Pxa255UartWriteF)(UInt16 chr, void* userData);
|
||||
|
||||
#define UART_FIFO_EMPTY 0xFF
|
||||
|
||||
typedef struct{
|
||||
|
||||
UInt8 read;
|
||||
UInt8 write;
|
||||
UInt16 buf[UART_FIFO_DEPTH];
|
||||
|
||||
}UartFifo;
|
||||
|
||||
typedef struct{
|
||||
|
||||
Pxa255ic* ic;
|
||||
UInt32 baseAddr;
|
||||
|
||||
Pxa255UartReadF readF;
|
||||
Pxa255UartWriteF writeF;
|
||||
void* accessFuncsData;
|
||||
|
||||
UartFifo TX, RX;
|
||||
|
||||
UInt16 transmitShift; //char currently "sending"
|
||||
UInt16 transmitHolding; //holding register for no-fifo mode
|
||||
|
||||
UInt16 receiveHolding; //char just received
|
||||
|
||||
UInt8 irq:5;
|
||||
UInt8 cyclesSinceRecv:3;
|
||||
|
||||
UInt8 IER; //interrupt enable register
|
||||
UInt8 IIR; //interrupt information register
|
||||
UInt8 FCR; //fifo control register
|
||||
UInt8 LCR; //line control register
|
||||
UInt8 LSR; //line status register
|
||||
UInt8 MCR; //modem control register
|
||||
UInt8 MSR; //modem status register
|
||||
UInt8 SPR; //scratchpad register
|
||||
UInt8 DLL; //divisor latch low
|
||||
UInt8 DLH; //divior latch high;
|
||||
UInt8 ISR; //infrared selection register
|
||||
|
||||
|
||||
|
||||
}Pxa255uart;
|
||||
|
||||
Boolean pxa255uartInit(Pxa255uart* uart, ArmMem* physMem, Pxa255ic* ic, UInt32 baseAddr, UInt8 irq);
|
||||
void pxa255uartProcess(Pxa255uart* uart); //write out data in TX fifo and read data into RX fifo
|
||||
|
||||
void pxa255uartSetFuncs(Pxa255uart* uart, Pxa255UartReadF readF, Pxa255UartWriteF writeF, void* userData);
|
||||
|
||||
#endif
|
||||
|
12
contrib/other/uarm/readme.txt
Executable file
12
contrib/other/uarm/readme.txt
Executable file
@ -0,0 +1,12 @@
|
||||
uARM emulator.
|
||||
Port to KolibriOS - SoUrcerer
|
||||
menuetlibc -> newlibc - maxcodehack
|
||||
|
||||
Build:
|
||||
make
|
||||
|
||||
Run:
|
||||
Get image at http://xvilka.me/jaunty.rel.v2.bz2
|
||||
|
||||
And start:
|
||||
uARMk jaunty.rel.v2
|
51
contrib/other/uarm/rt.c
Executable file
51
contrib/other/uarm/rt.c
Executable file
@ -0,0 +1,51 @@
|
||||
#include "types.h"
|
||||
|
||||
void err_hex(UInt32 val){
|
||||
|
||||
char x[9];
|
||||
unsigned char i, c;
|
||||
|
||||
x[8] = 0;
|
||||
|
||||
for(i = 0; i < 8; i++){
|
||||
|
||||
c = val & 0x0F;
|
||||
val >>= 4;
|
||||
c = (c >= 10) ? (c + 'A' - 10) : (c + '0');
|
||||
x[7 - i] = c;
|
||||
}
|
||||
|
||||
err_str(x);
|
||||
}
|
||||
|
||||
void err_dec(UInt32 val){
|
||||
|
||||
char x[16];
|
||||
unsigned char i, c;
|
||||
|
||||
x[sizeof(x) - 1] = 0;
|
||||
|
||||
for(i = 0; i < sizeof(x) - 1; i++){
|
||||
|
||||
c = (val % 10) + '0';
|
||||
val /= 10;
|
||||
x[sizeof(x) - 2 - i] = c;
|
||||
if(!val) break;
|
||||
}
|
||||
err_str(x + sizeof(x) - 2 - i);
|
||||
}
|
||||
|
||||
void __mem_zero(void* ptr, UInt16 sz){
|
||||
|
||||
UInt8* p = ptr;
|
||||
|
||||
while(sz--) *p++ = 0;
|
||||
}
|
||||
|
||||
void __mem_copy(void* d_, const void* s_, UInt32 sz){
|
||||
|
||||
UInt8* d = d_;
|
||||
const UInt8* s = s_;
|
||||
|
||||
while(sz--) *d++ = *s++;
|
||||
}
|
45
contrib/other/uarm/types.h
Executable file
45
contrib/other/uarm/types.h
Executable file
@ -0,0 +1,45 @@
|
||||
#ifndef _TYPES_H_
|
||||
#define _TYPES_H_
|
||||
|
||||
|
||||
typedef unsigned long UInt32;
|
||||
typedef signed long Int32;
|
||||
typedef unsigned short UInt16;
|
||||
typedef signed short Int16;
|
||||
typedef unsigned char UInt8;
|
||||
typedef signed char Int8;
|
||||
typedef unsigned char Err;
|
||||
typedef unsigned char Boolean;
|
||||
|
||||
#define true 1
|
||||
#define false 0
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL ((void*)0)
|
||||
#endif
|
||||
|
||||
#define TYPE_CHECK ((sizeof(UInt32) == 4) && (sizeof(UInt16) == 2) && (sizeof(UInt8) == 1))
|
||||
|
||||
#define errNone 0x00
|
||||
#define errInternal 0x01
|
||||
|
||||
|
||||
#define _INLINE_ inline __attribute__ ((always_inline))
|
||||
#define _UNUSED_ __attribute__((unused))
|
||||
|
||||
|
||||
/* runtime stuffs */
|
||||
void err_str(const char* str);
|
||||
void err_hex(UInt32 val);
|
||||
void err_dec(UInt32 val);
|
||||
void __mem_zero(void* mem, UInt16 len);
|
||||
UInt32 rtcCurTime(void);
|
||||
void* emu_alloc(UInt32 size);
|
||||
void emu_free(void* ptr);
|
||||
void __mem_copy(void* d, const void* s, UInt32 sz);
|
||||
|
||||
#define memset __memset_disabled__
|
||||
#define memcpy __memcpy_disabled__
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user