fixed indexing into page descriptor array with wrong page size

This commit is contained in:
Markus Fröschle
2014-09-27 06:19:43 +00:00
parent 51d36b45cb
commit bb7ae911dc
6 changed files with 537 additions and 612 deletions

View File

@@ -58,19 +58,22 @@
enum mmu_page_size
{
MMU_PAGE_SIZE_1M = 0,
MMU_PAGE_SIZE_4K = 1,
MMU_PAGE_SIZE_8K = 2,
MMU_PAGE_SIZE_1K = 3
MMU_PAGE_SIZE_1M = 0,
MMU_PAGE_SIZE_4K = 1,
MMU_PAGE_SIZE_8K = 2,
MMU_PAGE_SIZE_1K = 3
};
/*
* cache modes
*/
#define CACHE_WRITETHROUGH 0
#define CACHE_COPYBACK 1
#define CACHE_NOCACHE_PRECISE 2
#define CACHE_NOCACHE_IMPRECISE 3
enum mmu_cache_modes
{
CACHE_WRITETHROUGH = 0,
CACHE_COPYBACK = 1,
CACHE_NOCACHE_PRECISE = 2,
CACHE_NOCACHE_IMPRECISE = 3
};
/*

View File

@@ -76,10 +76,10 @@ extern uint8_t _EMUTOS_SIZE[];
*/
static inline bool pic_txready(void)
{
if (MCF_PSC3_PSCSR & MCF_PSC_PSCSR_TXRDY)
return true;
if (MCF_PSC3_PSCSR & MCF_PSC_PSCSR_TXRDY)
return true;
return false;
return false;
}
/*
@@ -87,84 +87,84 @@ static inline bool pic_txready(void)
*/
static inline bool pic_rxready(void)
{
if (MCF_PSC3_PSCSR & MCF_PSC_PSCSR_RXRDY)
return true;
if (MCF_PSC3_PSCSR & MCF_PSC_PSCSR_RXRDY)
return true;
return false;
return false;
}
void write_pic_byte(uint8_t value)
{
/* Wait until the transmitter is ready or 1000us are passed */
waitfor(1000, pic_txready);
/* Wait until the transmitter is ready or 1000us are passed */
waitfor(1000, pic_txready);
/* Transmit the byte */
*(volatile uint8_t*)(&MCF_PSC3_PSCTB_8BIT) = value; // Really 8-bit
/* Transmit the byte */
*(volatile uint8_t*)(&MCF_PSC3_PSCTB_8BIT) = value; // Really 8-bit
}
uint8_t read_pic_byte(void)
{
/* Wait until a byte has been received or 1000us are passed */
waitfor(1000, pic_rxready);
/* Wait until a byte has been received or 1000us are passed */
waitfor(1000, pic_rxready);
/* Return the received byte */
return * (volatile uint8_t *) (&MCF_PSC3_PSCTB_8BIT); // Really 8-bit
/* Return the received byte */
return * (volatile uint8_t *) (&MCF_PSC3_PSCTB_8BIT); // Really 8-bit
}
void pic_init(void)
{
char answer[4] = "OLD";
char answer[4] = "OLD";
xprintf("initialize the PIC: ");
xprintf("initialize the PIC: ");
/* Send the PIC initialization string */
write_pic_byte('A');
write_pic_byte('C');
write_pic_byte('P');
write_pic_byte('F');
/* Send the PIC initialization string */
write_pic_byte('A');
write_pic_byte('C');
write_pic_byte('P');
write_pic_byte('F');
/* Read the 3-char answer string. Should be "OK!". */
answer[0] = read_pic_byte();
answer[1] = read_pic_byte();
answer[2] = read_pic_byte();
answer[3] = '\0';
/* Read the 3-char answer string. Should be "OK!". */
answer[0] = read_pic_byte();
answer[1] = read_pic_byte();
answer[2] = read_pic_byte();
answer[3] = '\0';
if (answer[0] != 'O' || answer[1] != 'K' || answer[2] != '!')
{
dbg("PIC initialization failed. Already initialized?\r\n");
}
else
{
xprintf("%s\r\n", answer);
}
if (answer[0] != 'O' || answer[1] != 'K' || answer[2] != '!')
{
dbg("PIC initialization failed. Already initialized?\r\n");
}
else
{
xprintf("%s\r\n", answer);
}
}
void nvram_init(void)
{
int i;
int i;
xprintf("Restore the NVRAM data: ");
xprintf("Restore the NVRAM data: ");
/* Request for NVRAM backup data */
write_pic_byte(0x01);
/* Request for NVRAM backup data */
write_pic_byte(0x01);
/* Check answer type */
if (read_pic_byte() != 0x81)
{
// FIXME: PIC protocol error
xprintf("FAILED\r\n");
return;
}
/* Check answer type */
if (read_pic_byte() != 0x81)
{
// FIXME: PIC protocol error
xprintf("FAILED\r\n");
return;
}
/* Restore the NVRAM backup to the FPGA */
for (i = 0; i < 64; i++)
{
uint8_t data = read_pic_byte();
*(volatile uint8_t*)0xffff8961 = i;
*(volatile uint8_t*)0xffff8963 = data;
}
/* Restore the NVRAM backup to the FPGA */
for (i = 0; i < 64; i++)
{
uint8_t data = read_pic_byte();
*(volatile uint8_t*)0xffff8961 = i;
*(volatile uint8_t*)0xffff8963 = data;
}
xprintf("finished\r\n");
xprintf("finished\r\n");
}
#define KBD_ACIA_CONTROL ((uint8_t *) 0xfffffc00)
@@ -174,24 +174,24 @@ void nvram_init(void)
void acia_init()
{
xprintf("init ACIA: ");
/* init ACIA */
* KBD_ACIA_CONTROL = 3; /* master reset */
NOP();
xprintf("init ACIA: ");
/* init ACIA */
* KBD_ACIA_CONTROL = 3; /* master reset */
NOP();
* MIDI_ACIA_CONTROL = 3; /* master reset */
NOP();
* MIDI_ACIA_CONTROL = 3; /* master reset */
NOP();
* KBD_ACIA_CONTROL = 0x96; /* clock div = 64, 8N1, RTS low, TX int disable, RX int enable */
NOP();
* KBD_ACIA_CONTROL = 0x96; /* clock div = 64, 8N1, RTS low, TX int disable, RX int enable */
NOP();
* MFP_INTR_IN_SERVICE_A = -1;
NOP();
* MFP_INTR_IN_SERVICE_A = -1;
NOP();
* MFP_INTR_IN_SERVICE_B = -1;
NOP();
* MFP_INTR_IN_SERVICE_B = -1;
NOP();
xprintf("finished\r\n");
xprintf("finished\r\n");
}
/* ACP interrupt controller */
@@ -201,43 +201,43 @@ void acia_init()
void enable_coldfire_interrupts()
{
xprintf("enable interrupts: ");
xprintf("enable interrupts: ");
#if defined(MACHINE_FIREBEE)
*FPGA_INTR_CONTRL = 0L; /* disable all interrupts */
*FPGA_INTR_CONTRL = 0L; /* disable all interrupts */
#endif /* MACHINE_FIREBEE */
MCF_EPORT_EPPAR = 0xaaa8; /* all interrupts on falling edge */
MCF_EPORT_EPPAR = 0xaaa8; /* all interrupts on falling edge */
#if defined(MACHINE_FIREBEE)
/*
* TIN0 on the Coldfire is connected to the FPGA. TIN0 triggers every write
* access to 0xff8201 (vbasehi), i.e. everytime the video base address is written
*/
MCF_GPT0_GMS = MCF_GPT_GMS_ICT(1) | /* timer 0 on, video change capture on rising edge */
MCF_GPT_GMS_IEN |
MCF_GPT_GMS_TMS(1);
/* route GPT0 interrupt on interrupt controller */
MCF_INTC_ICR62 = 0x3f; /* interrupt level 7, interrupt priority 7 */
/*
* TIN0 on the Coldfire is connected to the FPGA. TIN0 triggers every write
* access to 0xff8201 (vbasehi), i.e. everytime the video base address is written
*/
MCF_GPT0_GMS = MCF_GPT_GMS_ICT(1) | /* timer 0 on, video change capture on rising edge */
MCF_GPT_GMS_IEN |
MCF_GPT_GMS_TMS(1);
/* route GPT0 interrupt on interrupt controller */
MCF_INTC_ICR62 = 0x3f; /* interrupt level 7, interrupt priority 7 */
*FPGA_INTR_ENABLE = 0xfe; /* enable int 1-7 */
MCF_EPORT_EPIER = 0xfe; /* int 1-7 on */
MCF_EPORT_EPFR = 0xff; /* clear all pending interrupts */
MCF_INTC_IMRL = 0xffffff00; /* int 1-7 on */
MCF_INTC_IMRH = 0xbffffffe; /* psc3 and timer 0 int on */
*FPGA_INTR_ENABLE = 0xfe; /* enable int 1-7 */
MCF_EPORT_EPIER = 0xfe; /* int 1-7 on */
MCF_EPORT_EPFR = 0xff; /* clear all pending interrupts */
MCF_INTC_IMRL = 0xffffff00; /* int 1-7 on */
MCF_INTC_IMRH = 0xbffffffe; /* psc3 and timer 0 int on */
#endif
xprintf("finished\r\n");
xprintf("finished\r\n");
}
void disable_coldfire_interrupts()
{
#if defined(MACHINE_FIREBEE)
*FPGA_INTR_ENABLE = 0; /* disable all interrupts */
*FPGA_INTR_ENABLE = 0; /* disable all interrupts */
#endif /* MACHINE_FIREBEE */
MCF_EPORT_EPIER = 0x0;
MCF_EPORT_EPFR = 0x0;
MCF_INTC_IMRL = 0xfffffffe;
MCF_INTC_IMRH = 0xffffffff;
MCF_EPORT_EPIER = 0x0;
MCF_EPORT_EPFR = 0x0;
MCF_INTC_IMRL = 0xfffffffe;
MCF_INTC_IMRH = 0xffffffff;
}
@@ -252,178 +252,179 @@ NIF nif2;
*/
void init_isr(void)
{
isr_init(); /* need to call that explicitely, otherwise isr table might be full */
isr_init(); /* need to call that explicitely, otherwise isr table might be full */
/*
* register the FEC interrupt handler
*/
if (!isr_register_handler(64 + INT_SOURCE_FEC0, fec0_interrupt_handler, NULL, (void *) &nif1))
{
dbg("unable to register isr for FEC0\r\n");
return;
}
/*
* register the FEC interrupt handler
*/
if (!isr_register_handler(64 + INT_SOURCE_FEC0, fec0_interrupt_handler, NULL, (void *) &nif1))
{
dbg("unable to register isr for FEC0\r\n");
return;
}
/*
* Register the DMA interrupt handler
*/
/*
* Register the DMA interrupt handler
*/
if (!isr_register_handler(64 + INT_SOURCE_DMA, dma_interrupt_handler, NULL,NULL))
{
dbg("Error: Unable to register isr for DMA\r\n");
return;
}
if (!isr_register_handler(64 + INT_SOURCE_DMA, dma_interrupt_handler, NULL,NULL))
{
dbg("Error: Unable to register isr for DMA\r\n");
return;
}
dma_irq_enable(5, 3); /* TODO: need to match the FEC driver's specs in MiNT? */
dma_irq_enable(5, 3); /* TODO: need to match the FEC driver's specs in MiNT? */
/*
* register the PIC interrupt handler
*/
if (isr_register_handler(64 + INT_SOURCE_PSC3, pic_interrupt_handler, NULL, NULL))
{
dbg("Error: unable to register ISR for PSC3\r\n");
return;
}
/*
* register the PIC interrupt handler
*/
if (isr_register_handler(64 + INT_SOURCE_PSC3, pic_interrupt_handler, NULL, NULL))
{
dbg("Error: unable to register ISR for PSC3\r\n");
return;
}
}
void BaS(void)
{
uint8_t *src;
uint8_t *dst = (uint8_t *) TOS;
uint8_t *src;
uint8_t *dst = (uint8_t *) TOS;
#if defined(MACHINE_FIREBEE) /* LITE board has no pic and (currently) no nvram */
pic_init();
nvram_init();
pic_init();
nvram_init();
#endif /* MACHINE_FIREBEE */
xprintf("copy EmuTOS: ");
xprintf("copy EmuTOS: ");
/* copy EMUTOS */
src = (uint8_t *) EMUTOS;
dma_memcpy(dst, src, EMUTOS_SIZE);
xprintf("finished\r\n");
/* copy EMUTOS */
src = (uint8_t *) EMUTOS;
dma_memcpy(dst, src, EMUTOS_SIZE);
xprintf("finished\r\n");
xprintf("initialize MMU: ");
mmu_init();
xprintf("finished\r\n");
xprintf("initialize MMU: ");
mmu_init();
xprintf("finished\r\n");
xprintf("initialize exception vector table: ");
vec_init();
xprintf("finished\r\n");
xprintf("enable MMU: ");
MCF_MMU_MMUCR = MCF_MMU_MMUCR_EN; /* MMU on */
NOP(); /* force pipeline sync */
xprintf("finished\r\n");
xprintf("flush caches: ");
flush_and_invalidate_caches();
xprintf("finished\r\n");
xprintf("enable MMU: ");
MCF_MMU_MMUCR = MCF_MMU_MMUCR_EN; /* MMU on */
NOP(); /* force pipeline sync */
xprintf("finished\r\n");
xprintf("initialize exception vector table: ");
vec_init();
xprintf("finished\r\n");
#ifdef MACHINE_FIREBEE
xprintf("IDE reset: ");
/* IDE reset */
* (volatile uint8_t *) (0xffff8802 - 2) = 14;
* (volatile uint8_t *) (0xffff8802 - 0) = 0x80;
wait(1);
xprintf("flush caches: ");
flush_and_invalidate_caches();
xprintf("finished\r\n");
* (volatile uint8_t *) (0xffff8802 - 0) = 0;
#ifdef MACHINE_FIREBEE
xprintf("IDE reset: ");
/* IDE reset */
* (volatile uint8_t *) (0xffff8802 - 2) = 14;
* (volatile uint8_t *) (0xffff8802 - 0) = 0x80;
wait(1);
xprintf("finished\r\n");
xprintf("enable video: ");
/*
* video setup (25MHz)
*/
* (volatile uint32_t *) (0xf0000410 + 0) = 0x032002ba; /* horizontal 640x480 */
* (volatile uint32_t *) (0xf0000410 + 4) = 0x020c020a; /* vertical 640x480 */
* (volatile uint32_t *) (0xf0000410 + 8) = 0x0190015d; /* horizontal 320x240 */
* (volatile uint32_t *) (0xf0000410 + 12) = 0x020C020A; /* vertical 320x230 */
* (volatile uint8_t *) (0xffff8802 - 0) = 0;
xprintf("finished\r\n");
xprintf("enable video: ");
/*
* video setup (25MHz)
*/
* (volatile uint32_t *) (0xf0000410 + 0) = 0x032002ba; /* horizontal 640x480 */
* (volatile uint32_t *) (0xf0000410 + 4) = 0x020c020a; /* vertical 640x480 */
* (volatile uint32_t *) (0xf0000410 + 8) = 0x0190015d; /* horizontal 320x240 */
* (volatile uint32_t *) (0xf0000410 + 12) = 0x020C020A; /* vertical 320x230 */
#ifdef _NOT_USED_
// 32MHz
* (volatile uint32_t *) (0xf0000410 + 0) = 0x037002ba; /* horizontal 640x480 */
* (volatile uint32_t *) (0xf0000410 + 4) = 0x020d020a; /* vertical 640x480 */
* (volatile uint32_t *) (0xf0000410 + 8) = 0x02a001e0; /* horizontal 320x240 */
* (volatile uint32_t *) (0xf0000410 + 12) = 0x05a00160; /* vertical 320x230 */
* (volatile uint32_t *) (0xf0000410 + 0) = 0x037002ba; /* horizontal 640x480 */
* (volatile uint32_t *) (0xf0000410 + 4) = 0x020d020a; /* vertical 640x480 */
* (volatile uint32_t *) (0xf0000410 + 8) = 0x02a001e0; /* horizontal 320x240 */
* (volatile uint32_t *) (0xf0000410 + 12) = 0x05a00160; /* vertical 320x230 */
#endif /* _NOT_USED_ */
/* fifo on, refresh on, ddrcs and cke on, video dac on */
* (volatile uint32_t *) (0xf0000410 - 0x20) = 0x01070002;
/* fifo on, refresh on, ddrcs and cke on, video dac on */
* (volatile uint32_t *) (0xf0000410 - 0x20) = 0x01070002;
xprintf("finished\r\n");
xprintf("finished\r\n");
enable_coldfire_interrupts();
enable_coldfire_interrupts();
#ifdef _NOT_USED_
screen_init();
screen_init();
/* experimental */
{
int i;
uint32_t *scradr = 0xd00000;
/* experimental */
{
int i;
uint32_t *scradr = 0xd00000;
for (i = 0; i < 100; i++)
{
uint32_t *p = scradr;
for (i = 0; i < 100; i++)
{
uint32_t *p = scradr;
for (p = scradr; p < scradr + 1024 * 150L; p++)
{
*p = 0xffffffff;
}
for (p = scradr; p < scradr + 1024 * 150L; p++)
{
*p = 0xffffffff;
}
for (p = scradr; p < scradr + 1024 * 150L; p++)
{
*p = 0x0;
}
}
}
for (p = scradr; p < scradr + 1024 * 150L; p++)
{
*p = 0x0;
}
}
}
#endif /* _NOT_USED_ */
#endif /* MACHINE_FIREBEE */
sd_card_init();
sd_card_init();
/*
* memory setup
*/
memset((void *) 0x400, 0, 0x400);
/*
* memory setup
*/
memset((void *) 0x400, 0, 0x400);
#if defined(MACHINE_FIREBEE)
/* set Falcon bus control register */
/* sets bit 3 and 6. Both are undefined on an original Falcon? */
/* set Falcon bus control register */
/* sets bit 3 and 6. Both are undefined on an original Falcon? */
* (volatile uint8_t *) 0xffff8007 = 0x48;
* (volatile uint8_t *) 0xffff8007 = 0x48;
#endif /* MACHINE_FIREBEE */
/* ST RAM */
/* ST RAM */
* (uint32_t *) 0x42e = STRAM_END; /* phystop TOS system variable */
* (uint32_t *) 0x420 = 0x752019f3; /* memvalid TOS system variable */
* (uint32_t *) 0x43a = 0x237698aa; /* memval2 TOS system variable */
* (uint32_t *) 0x51a = 0x5555aaaa; /* memval3 TOS system variable */
* (uint32_t *) 0x42e = STRAM_END; /* phystop TOS system variable */
* (uint32_t *) 0x420 = 0x752019f3; /* memvalid TOS system variable */
* (uint32_t *) 0x43a = 0x237698aa; /* memval2 TOS system variable */
* (uint32_t *) 0x51a = 0x5555aaaa; /* memval3 TOS system variable */
/* TT-RAM */
/* TT-RAM */
* (uint32_t *) 0x5a4 = FASTRAM_END; /* ramtop TOS system variable */
* (uint32_t *) 0x5a8 = 0x1357bd13; /* ramvalid TOS system variable */
* (uint32_t *) 0x5a4 = FASTRAM_END; /* ramtop TOS system variable */
* (uint32_t *) 0x5a8 = 0x1357bd13; /* ramvalid TOS system variable */
#if defined(MACHINE_FIREBEE) /* m5484lite has no ACIA and no dip switch... */
acia_init();
acia_init();
#endif /* MACHINE_FIREBEE */
srec_execute("BASFLASH.S19");
srec_execute("BASFLASH.S19");
/* Jump into the OS */
typedef void void_func(void);
struct rom_header
{
void *initial_sp;
void_func *initial_pc;
};
/* Jump into the OS */
typedef void void_func(void);
struct rom_header
{
void *initial_sp;
void_func *initial_pc;
};
xprintf("BaS initialization finished, enable interrupts\r\n");
enable_coldfire_interrupts();
init_isr();
xprintf("BaS initialization finished, enable interrupts\r\n");
enable_coldfire_interrupts();
init_isr();
xprintf("call EmuTOS\r\n");
struct rom_header *os_header = (struct rom_header *) TOS;
os_header->initial_pc();
xprintf("call EmuTOS\r\n");
struct rom_header *os_header = (struct rom_header *) TOS;
os_header->initial_pc();
}

View File

@@ -310,12 +310,12 @@ init_vec_loop:
*/
vector_table_start:
std_exc_vec:
//move.w #0x2700,sr // disable interrupt
move.w #0x2700,sr // disable interrupt
subq.l #8,sp
movem.l d0/a5,(sp) // save registers
move.w 8(sp),d0 // fetch vector
and.l #0x3fc,d0 // mask out vector number
#define DBG_EXC
#ifdef DBG_EXC
// printout vector number of exception
@@ -388,12 +388,6 @@ access_mmu:
move.l MCF_MMU_MMUSR,d0 // did the last fault hit in TLB?
btst #1,d0 // yes, it did. So we already mapped that page
bne bus_error // and this must be a real bus error
btst #5,d0 // supervisor protection fault?
bne bus_error
btst #4,d0 // read access fault?
bne bus_error
btst #3,d0 // write access fault?
bne bus_error
move.l MCF_MMU_MMUAR,d0
cmp.l #__FASTRAM_END,d0 // above max User RAM area?
@@ -690,11 +684,13 @@ handler_gpt0:
link a6,#-4 * 4 // make room for
movem.l d0-d1/a0-a1,(sp) // gcc scratch registers and save them,
// other registers will be handled by gcc itself
move.w 4(a6),d0 // fetch vector number from stack
move.l d0,-(sp) // push it
jsr _gpt0_interrupt_handler // call C handler
addq.l #4,sp // adjust stack
movem.l (sp),d0-d1/a0-a1 // restore registers
unlk a6
rte
#endif /* MACHINE_FIREBEE */

View File

@@ -52,45 +52,45 @@ extern void (*rt_vbr[])(void);
*/
int register_interrupt_handler(uint8_t source, uint8_t level, uint8_t priority, uint8_t intr, void (*handler)(void))
{
int ipl;
int i;
volatile uint8_t *ICR = &MCF_INTC_ICR01 - 1;
uint8_t lp;
int ipl;
int i;
volatile uint8_t *ICR = &MCF_INTC_ICR01 - 1;
uint8_t lp;
source &= 63;
priority &= 7;
source &= 63;
priority &= 7;
if (source < 1 || source > 63)
{
dbg("interrupt source %d not defined\r\n", source);
return -1;
}
if (source < 1 || source > 63)
{
dbg("interrupt source %d not defined\r\n", source);
return -1;
}
lp = MCF_INTC_ICR_IL(level) | MCF_INTC_ICR_IP(priority);
lp = MCF_INTC_ICR_IL(level) | MCF_INTC_ICR_IP(priority);
/* check if this combination is already set somewhere */
for (i = 1; i < 64; i++)
{
if (ICR[i] == lp)
{
dbg("level %d and priority %d already used for interrupt source %d!\r\n",
level, priority, i);
return -1;
}
}
/* check if this combination is already set somewhere */
for (i = 1; i < 64; i++)
{
if (ICR[i] == lp)
{
dbg("level %d and priority %d already used for interrupt source %d!\r\n",
level, priority, i);
return -1;
}
}
/* disable interrupts */
ipl = set_ipl(7);
/* disable interrupts */
ipl = set_ipl(7);
VBR[64 + source] = handler; /* first 64 vectors are system exceptions */
VBR[64 + source] = handler; /* first 64 vectors are system exceptions */
/* set level and priority in interrupt controller */
ICR[source] = lp;
/* set level and priority in interrupt controller */
ICR[source] = lp;
/* set interrupt mask to where it was before */
set_ipl(ipl);
/* set interrupt mask to where it was before */
set_ipl(ipl);
return 0;
return 0;
}
#ifndef MAX_ISR_ENTRY
@@ -100,10 +100,10 @@ int register_interrupt_handler(uint8_t source, uint8_t level, uint8_t priority,
struct isrentry
{
int vector;
int (*handler)(void *, void *);
void *hdev;
void *harg;
int vector;
int (*handler)(void *, void *);
void *hdev;
void *harg;
};
static struct isrentry isrtab[MAX_ISR_ENTRY]; /* list of interrupt service routines */
@@ -113,7 +113,7 @@ static struct isrentry isrtab[MAX_ISR_ENTRY]; /* list of interrupt service
*/
void isr_init(void)
{
memset(isrtab, 0, sizeof(isrtab));
memset(isrtab, 0, sizeof(isrtab));
}
/*
@@ -126,56 +126,56 @@ void isr_init(void)
*/
int isr_register_handler(int vector, int (*handler)(void *, void *), void *hdev, void *harg)
{
int index;
int index;
if ((vector == 0) || (handler == NULL))
{
dbg("illegal vector or handler!\r\n");
return false;
}
if ((vector == 0) || (handler == NULL))
{
dbg("illegal vector or handler!\r\n");
return false;
}
for (index = 0; index < MAX_ISR_ENTRY; index++)
{
if (isrtab[index].vector == vector)
{
/* one cross each, only! */
dbg("already set handler with this vector (%d, %d)\r\n", vector);
return false;
}
for (index = 0; index < MAX_ISR_ENTRY; index++)
{
if (isrtab[index].vector == vector)
{
/* one cross each, only! */
dbg("already set handler with this vector (%d, %d)\r\n", vector);
return false;
}
if (isrtab[index].vector == 0)
{
isrtab[index].vector = vector;
isrtab[index].handler = handler;
isrtab[index].hdev = hdev;
isrtab[index].harg = harg;
if (isrtab[index].vector == 0)
{
isrtab[index].vector = vector;
isrtab[index].handler = handler;
isrtab[index].hdev = hdev;
isrtab[index].harg = harg;
return true;
}
}
dbg("no available slots to register handler for vector %d\n\r", vector);
return true;
}
}
dbg("no available slots to register handler for vector %d\n\r", vector);
return false; /* no available slots */
return false; /* no available slots */
}
void isr_remove_handler(int (*handler)(void *, void *))
{
/*
* This routine removes from the ISR table all
* entries that matches 'handler'.
*/
int index;
/*
* This routine removes from the ISR table all
* entries that matches 'handler'.
*/
int index;
for (index = 0; index < MAX_ISR_ENTRY; index++)
{
if (isrtab[index].handler == handler)
{
memset(&isrtab[index], 0, sizeof(struct isrentry));
for (index = 0; index < MAX_ISR_ENTRY; index++)
{
if (isrtab[index].handler == handler)
{
memset(&isrtab[index], 0, sizeof(struct isrentry));
return;
}
}
dbg("no such handler registered (handler=%p\r\n", handler);
return;
}
}
dbg("no such handler registered (handler=%p\r\n", handler);
}
/*
@@ -184,27 +184,27 @@ void isr_remove_handler(int (*handler)(void *, void *))
*/
bool isr_execute_handler(int vector)
{
int index;
bool retval = false;
int index;
bool retval = false;
/*
* locate a BaS Interrupt Service Routine handler.
*/
for (index = 0; index < MAX_ISR_ENTRY; index++)
{
if (isrtab[index].vector == vector)
{
retval = true;
/*
* locate a BaS Interrupt Service Routine handler.
*/
for (index = 0; index < MAX_ISR_ENTRY; index++)
{
if (isrtab[index].vector == vector)
{
retval = true;
if (isrtab[index].handler(isrtab[index].hdev, isrtab[index].harg))
{
return retval;
}
}
}
dbg("no BaS isr handler for vector %d found\r\n", vector);
if (isrtab[index].handler(isrtab[index].hdev, isrtab[index].harg))
{
return retval;
}
}
}
dbg("no BaS isr handler for vector %d found\r\n", vector);
return retval;
return retval;
}
/*
@@ -215,25 +215,25 @@ bool isr_execute_handler(int vector)
*/
int pic_interrupt_handler(void *arg1, void *arg2)
{
uint8_t rcv_byte;
uint8_t rcv_byte;
rcv_byte = MCF_PSC3_PSCRB_8BIT;
if (rcv_byte == 2) // PIC requests RTC data
{
uint8_t *rtc_reg = (uint8_t *) 0xffff8961;
uint8_t *rtc_data = (uint8_t *) 0xffff8963;
int index = 0;
rcv_byte = MCF_PSC3_PSCRB_8BIT;
if (rcv_byte == 2) // PIC requests RTC data
{
uint8_t *rtc_reg = (uint8_t *) 0xffff8961;
uint8_t *rtc_data = (uint8_t *) 0xffff8963;
int index = 0;
xprintf("PIC interrupt: requesting RTC data\r\n");
xprintf("PIC interrupt: requesting RTC data\r\n");
MCF_PSC3_PSCTB_8BIT = 0x82; // header byte to PIC
do
{
*rtc_reg = 0;
MCF_PSC3_PSCTB_8BIT = *rtc_data;
} while (index++ < 64);
}
return 1;
MCF_PSC3_PSCTB_8BIT = 0x82; // header byte to PIC
do
{
*rtc_reg = 0;
MCF_PSC3_PSCTB_8BIT = *rtc_data;
} while (index++ < 64);
}
return 1;
}
extern int32_t video_sbt;
@@ -241,93 +241,93 @@ extern int32_t video_tlb;
void video_addr_timeout(void)
{
uint32_t addr = 0x0L;
uint32_t *src;
uint32_t *dst;
uint32_t asid;
uint32_t addr = 0x0L;
uint32_t *src;
uint32_t *dst;
uint32_t asid;
dbg("video address timeout\r\n");
flush_and_invalidate_caches();
dbg("video address timeout\r\n");
flush_and_invalidate_caches();
do
{
uint32_t tlb;
uint32_t page_attr;
do
{
uint32_t tlb;
uint32_t page_attr;
/*
* search tlb entry id for addr (if not available, the MMU
* will provide a new one based on its LRU algorithm)
*/
MCF_MMU_MMUAR = addr;
MCF_MMU_MMUOR =
MCF_MMU_MMUOR_STLB |
MCF_MMU_MMUOR_RW |
MCF_MMU_MMUOR_ACC;
NOP();
tlb = (MCF_MMU_MMUOR >> 16) & 0xffff;
/*
* search tlb entry id for addr (if not available, the MMU
* will provide a new one based on its LRU algorithm)
*/
MCF_MMU_MMUAR = addr;
MCF_MMU_MMUOR =
MCF_MMU_MMUOR_STLB |
MCF_MMU_MMUOR_RW |
MCF_MMU_MMUOR_ACC;
NOP();
tlb = (MCF_MMU_MMUOR >> 16) & 0xffff;
/*
* retrieve tlb entry with the found TLB entry id
*/
MCF_MMU_MMUAR = tlb;
MCF_MMU_MMUOR =
MCF_MMU_MMUOR_STLB |
MCF_MMU_MMUOR_ADR |
MCF_MMU_MMUOR_RW |
MCF_MMU_MMUOR_ACC;
NOP();
/*
* retrieve tlb entry with the found TLB entry id
*/
MCF_MMU_MMUAR = tlb;
MCF_MMU_MMUOR =
MCF_MMU_MMUOR_STLB |
MCF_MMU_MMUOR_ADR |
MCF_MMU_MMUOR_RW |
MCF_MMU_MMUOR_ACC;
NOP();
asid = (MCF_MMU_MMUTR >> 2) & 0x1fff; /* fetch ASID of page */;
if (asid != sca_page_ID) /* check if screen area */
{
addr += 0x100000;
continue; /* next page */
}
asid = (MCF_MMU_MMUTR >> 2) & 0x1fff; /* fetch ASID of page */;
if (asid != sca_page_ID) /* check if screen area */
{
addr += 0x100000;
continue; /* next page */
}
/* modify found TLB entry */
if (addr == 0x0)
{
page_attr =
MCF_MMU_MMUDR_LK |
MCF_MMU_MMUDR_SZ(0) |
MCF_MMU_MMUDR_CM(0) |
MCF_MMU_MMUDR_R |
MCF_MMU_MMUDR_W |
MCF_MMU_MMUDR_X;
}
else
{
page_attr =
MCF_MMU_MMUTR_SG |
MCF_MMU_MMUTR_V;
}
/* modify found TLB entry */
if (addr == 0x0)
{
page_attr =
MCF_MMU_MMUDR_LK |
MCF_MMU_MMUDR_SZ(0) |
MCF_MMU_MMUDR_CM(0) |
MCF_MMU_MMUDR_R |
MCF_MMU_MMUDR_W |
MCF_MMU_MMUDR_X;
}
else
{
page_attr =
MCF_MMU_MMUTR_SG |
MCF_MMU_MMUTR_V;
}
MCF_MMU_MMUTR = addr;
MCF_MMU_MMUDR = page_attr;
MCF_MMU_MMUOR =
MCF_MMU_MMUOR_STLB |
MCF_MMU_MMUOR_ADR |
MCF_MMU_MMUOR_ACC |
MCF_MMU_MMUOR_UAA;
NOP();
MCF_MMU_MMUTR = addr;
MCF_MMU_MMUDR = page_attr;
MCF_MMU_MMUOR =
MCF_MMU_MMUOR_STLB |
MCF_MMU_MMUOR_ADR |
MCF_MMU_MMUOR_ACC |
MCF_MMU_MMUOR_UAA;
NOP();
dst = (uint32_t *) 0x60000000 + addr;
src = (uint32_t *) addr;
while (dst < (uint32_t *) 0x60000000 + addr + 0x10000)
{
*dst++ = *src++;
*dst++ = *src++;
*dst++ = *src++;
*dst++ = *src++;
}
dst = (uint32_t *) 0x60000000 + addr;
src = (uint32_t *) addr;
while (dst < (uint32_t *) 0x60000000 + addr + 0x10000)
{
*dst++ = *src++;
*dst++ = *src++;
*dst++ = *src++;
*dst++ = *src++;
}
addr += 0x100000;
} while (addr < 0xd00000);
video_tlb = 0x2000;
video_sbt = 0;
addr += 0x100000;
} while (addr < 0xd00000);
video_tlb = 0x2000;
video_sbt = 0;
}
@@ -336,16 +336,16 @@ void video_addr_timeout(void)
*/
void blink_led(void)
{
static uint16_t blinker = 0;
static uint16_t blinker = 0;
if ((blinker++ & 0x80) > 0)
{
MCF_GPIO_PODR_FEC1L |= (1 << 4); /* LED off */
}
else
{
MCF_GPIO_PODR_FEC1L &= ~(1 << 4); /* LED on */
}
if ((blinker++ & 0x80) > 0)
{
MCF_GPIO_PODR_FEC1L |= (1 << 4); /* LED off */
}
else
{
MCF_GPIO_PODR_FEC1L &= ~(1 << 4); /* LED on */
}
}
/*
@@ -363,47 +363,47 @@ void blink_led(void)
bool irq6_acsi_dma_interrupt(void)
{
dbg("ACSI DMA interrupt\r\n");
dbg("ACSI DMA interrupt\r\n");
/*
* TODO: implement handler
*/
/*
* TODO: implement handler
*/
return false;
return false;
}
bool irq6_interrupt_handler(uint32_t sf1, uint32_t sf2)
{
bool handled = false;
bool handled = false;
MCF_EPORT_EPFR |= (1 << 6); /* clear int6 from edge port */
MCF_EPORT_EPFR |= (1 << 6); /* clear int6 from edge port */
if (video_sbt != 0 && (video_sbt - 0x70000000) > MCF_SLT0_SCNT)
{
video_addr_timeout();
handled = true;
}
if (video_sbt != 0 && (video_sbt - 0x70000000) > MCF_SLT0_SCNT)
{
video_addr_timeout();
handled = true;
}
/*
* check if ACSI DMA interrupt
*/
/*
* check if ACSI DMA interrupt
*/
if (FALCON_MFP_IERA & (1 << 7))
{
/* ACSI interrupt is enabled */
if (FALCON_MFP_IPRA & (1 << 7))
{
irq6_acsi_dma_interrupt();
handled = true;
}
}
if (FALCON_MFP_IERA & (1 << 7))
{
/* ACSI interrupt is enabled */
if (FALCON_MFP_IPRA & (1 << 7))
{
irq6_acsi_dma_interrupt();
handled = true;
}
}
if (FALCON_MFP_IPRA || FALCON_MFP_IPRB)
{
blink_led();
}
if (FALCON_MFP_IPRA || FALCON_MFP_IPRB)
{
blink_led();
}
return handled;
return handled;
}
#if defined(MACHINE_FIREBEE)
@@ -430,112 +430,10 @@ bool irq6_interrupt_handler(uint32_t sf1, uint32_t sf2)
*/
void gpt0_interrupt_handler(void)
{
uint32_t video_address;
uint32_t video_end_address;
int page_number;
bool already_set;
extern uint32_t _STRAM_END;
dbg("screen base = 0x%x\r\n", vbasehi);
dbg("screen base = 0x%x\r\n", vbasehi);
if (vbasehi < 2) /* screen base lower than 0x20000? */
{
goto rearm_trigger; /* do nothing */
}
else if (vbasehi >= 0xd0) /* higher than 0xd00000 (normal Falcon address)? */
{
video_sbt = MCF_SLT0_SCNT; /* FIXME: no idea why we need to save the time here */
}
video_address = (vbasehi << 16) | (vbasemid << 8) | vbaselow;
page_number = video_address >> 20; /* calculate a page number */
already_set = (video_tlb & (1 << page_number)); /* already in bitset? */
video_tlb |= page_number; /* set it */
if (! already_set) /* newly set page, need to copy contents */
{
flush_and_invalidate_caches();
dma_memcpy((uint8_t *) video_address + 0x60000000, (uint8_t *) video_address, 0x100000);
/*
* create an MMU TLB entry for the new video page
*/
/*
* first search for an existing entry with our address. If none is found,
* the MMU will propose a new one
*/
MCF_MMU_MMUAR = video_address;
MCF_MMU_MMUOR = 0x106;
NOP();
/*
* take this MMU TLB entry and set it to our video address and page mapping
*/
MCF_MMU_MMUAR = (MCF_MMU_MMUOR >> 16) & 0xffff; /* set TLB id */
MCF_MMU_MMUTR = video_address |
MCF_MMU_MMUTR_ID(sca_page_ID) | /* set video page ID */
MCF_MMU_MMUTR_SG | /* shared global */
MCF_MMU_MMUTR_V; /* valid */
MCF_MMU_MMUDR = (video_address + 0x60000000) | /* physical address */
MCF_MMU_MMUDR_SZ(0) | /* 1 MB page size */
MCF_MMU_MMUDR_CM(0) | /* writethrough */
MCF_MMU_MMUDR_R | /* readable */
MCF_MMU_MMUDR_W | /* writeable */
MCF_MMU_MMUDR_X; /* executable */
MCF_MMU_MMUOR = 0x10b; /* update TLB entry */
}
/*
* Calculate the effective screen memory size to see if we need to map another page
* in case the new screen spans more than one single page
*/
video_end_address = video_address + (vde - vdb) * vwrap;
if (video_end_address < _STRAM_END)
{
page_number = video_end_address >> 20; /* calculate a page number */
already_set = (video_tlb & (1 << page_number)); /* already in bitset? */
video_tlb |= page_number; /* set it */
if (! already_set) /* newly set page, need to copy contents */
{
flush_and_invalidate_caches();
dma_memcpy((uint8_t *) video_end_address + 0x60000000, (uint8_t *) video_end_address, 0x100000);
/*
* create an MMU TLB entry for the new video page
*/
/*
* first search for an existing entry with our address. If none is found,
* the MMU will propose a new one
*/
MCF_MMU_MMUAR = video_end_address;
MCF_MMU_MMUOR = 0x106;
NOP();
/*
* take this MMU TLB entry and set it to our video address and page mapping
*/
MCF_MMU_MMUAR = (MCF_MMU_MMUOR >> 16) & 0xffff; /* set TLB id */
MCF_MMU_MMUTR = video_end_address |
MCF_MMU_MMUTR_ID(sca_page_ID) | /* set video page ID */
MCF_MMU_MMUTR_SG | /* shared global */
MCF_MMU_MMUTR_V; /* valid */
MCF_MMU_MMUDR = (video_end_address + 0x60000000) | /* physical address */
MCF_MMU_MMUDR_SZ(0) | /* 1 MB page size */
MCF_MMU_MMUDR_CM(0) | /* writethrough */
MCF_MMU_MMUDR_R | /* readable */
MCF_MMU_MMUDR_W | /* writeable */
MCF_MMU_MMUDR_X; /* executable */
MCF_MMU_MMUOR = 0x10b; /* update TLB entry */
}
}
rearm_trigger:
MCF_GPT0_GMS &= ~1; /* rearm trigger */
NOP();
MCF_GPT0_GMS |= 1;
MCF_GPT0_GMS &= ~1; /* rearm trigger */
NOP();
MCF_GPT0_GMS |= 1;
}
#endif /* MACHINE_FIREBEE */

View File

@@ -62,7 +62,7 @@
#error "unknown machine!"
#endif /* MACHINE_FIREBEE */
#define DEBUG_MMU
//#define DEBUG_MMU
#ifdef DEBUG_MMU
#define dbg(format, arg...) do { xprintf("DEBUG (%s()): " format, __FUNCTION__, ##arg);} while(0)
#else
@@ -199,14 +199,14 @@ struct virt_to_phys
{
uint32_t start_address;
uint32_t length;
uint32_t physical_offset;
uint32_t physical_offset;
};
static struct virt_to_phys translation[] =
{
/* virtual , length , offset */
{ 0x00000000, 0x00e00000, 0x60000000 }, /* map first 14 MByte to first 14 Mb of video ram */
{ 0x00e00000, 0x00100000, 0x00000000 }, /* map TOS to SDRAM */
/* virtual , length , offset */
{ 0x00000000, 0x00e00000, 0x60000000 }, /* map first 14 MByte to first 14 Mb of video ram */
//{ 0x00e00000, 0x00100000, 0x00000000 }, /* map TOS to SDRAM */
{ 0x00f00000, 0x00100000, 0xff000000 }, /* map Falcon I/O area to FPGA */
{ 0x01000000, 0x10000000, 0x00000000 }, /* map rest of ram virt = phys */
{ 0x1fd00000, 0x01000000, 0x00000000 }, /* accessed by EmuTOS? */
@@ -219,12 +219,12 @@ static inline uint32_t lookup_phys(uint32_t virt)
for (i = 0; i < num_translations; i++)
{
if (virt >= translation[i].start_address && virt < translation[i].start_address + translation[i].length)
if (virt >= translation[i].start_address && virt < translation[i].start_address + translation[i].length)
{
return virt + translation[i].physical_offset;
return virt + translation[i].physical_offset;
}
}
err("virtual address 0x%lx not found in translation table!\r\n", virt);
err("virtual address 0x%lx not found in translation table!\r\n", virt);
}
struct page_descriptor
@@ -254,11 +254,11 @@ static struct page_descriptor pages[65536]; /* 512 Mb RAM */
*/
int mmu_map_8k_page(uint32_t virt)
{
const int size_mask = 0xffffe000; /* 8k pagesize */
int page_index = (virt & size_mask) / 4096; /* index into page_descriptor array */
struct page_descriptor *page = &pages[page_index]; /* attributes of page to map */
const int size_mask = 0xffffe000; /* 8k pagesize */
int page_index = (virt & size_mask) / DEFAULT_PAGE_SIZE; /* index into page_descriptor array */
struct page_descriptor *page = &pages[page_index]; /* attributes of page to map */
uint32_t addr = lookup_phys(virt); /* virtual to physical translation of page */
uint32_t phys = lookup_phys(virt); /* virtual to physical translation of page */
/*
* add page to TLB
@@ -269,7 +269,7 @@ int mmu_map_8k_page(uint32_t virt)
MCF_MMU_MMUTR_V; /* valid */
NOP();
MCF_MMU_MMUDR = (addr & size_mask) | /* physical address */
MCF_MMU_MMUDR = (phys & size_mask) | /* physical address */
MCF_MMU_MMUDR_SZ(MMU_PAGE_SIZE_8K) | /* page size */
MCF_MMU_MMUDR_CM(page->cache_mode) |
(page->read ? MCF_MMU_MMUDR_R : 0) | /* read access enable */
@@ -282,24 +282,19 @@ int mmu_map_8k_page(uint32_t virt)
MCF_MMU_MMUOR_UAA; /* update allocation address field */
NOP();
dbg("mapped virt=0x%08x to phys=0x%08x\r\n", virt & size_mask, phys & size_mask);
dbg("DTLB: MCF_MMU_MMUOR = %08x\r\n", MCF_MMU_MMUOR);
MCF_MMU_MMUOR = MCF_MMU_MMUOR_ITLB | /* instruction */
MCF_MMU_MMUOR_ACC | /* access TLB */
MCF_MMU_MMUOR_UAA; /* update allocation address field */
dbg("mapped virt=0x%08x to phys=0x%08x\r\n", virt, addr);
dbg("ITLB: MCF_MMU_MMUOR = %08x\r\n\r\n", MCF_MMU_MMUOR);
return 1;
}
struct mmu_map_flags
{
unsigned cache_mode:2;
unsigned protection:1;
unsigned page_id:8;
unsigned access:3;
unsigned locked:1;
unsigned unused:17;
};
/*
* map a page of memory using virt and phys as addresses with the Coldfire MMU.
*
@@ -312,7 +307,7 @@ struct mmu_map_flags
*
*
*/
int mmu_map_page(uint32_t virt, uint32_t phys, enum mmu_page_size sz, const struct mmu_map_flags *flags)
int mmu_map_page(uint32_t virt, uint32_t phys, enum mmu_page_size sz, uint8_t page_id, const struct page_descriptor *flags)
{
int size_mask;
@@ -335,24 +330,24 @@ int mmu_map_page(uint32_t virt, uint32_t phys, enum mmu_page_size sz, const stru
break;
default:
err("illegal map size %d\r\n", sz);
err("illegal map size %d\r\n", sz);
}
/*
* add page to TLB
*/
MCF_MMU_MMUTR = ((int) virt & size_mask) | /* virtual address */
MCF_MMU_MMUTR_ID(flags->page_id) | /* address space id (ASID) */
MCF_MMU_MMUTR_SG | /* shared global */
MCF_MMU_MMUTR = ((uint32_t) virt & size_mask) | /* virtual address */
MCF_MMU_MMUTR_ID(page_id) | /* address space id (ASID) */
(flags->global ? MCF_MMU_MMUTR_SG : 0) | /* shared global */
MCF_MMU_MMUTR_V; /* valid */
NOP();
MCF_MMU_MMUDR = ((int) phys & size_mask) | /* physical address */
MCF_MMU_MMUDR = ((uint32_t) phys & size_mask) | /* physical address */
MCF_MMU_MMUDR_SZ(sz) | /* page size */
MCF_MMU_MMUDR_CM(flags->cache_mode) |
(flags->access & ACCESS_READ ? MCF_MMU_MMUDR_R : 0) | /* read access enable */
(flags->access & ACCESS_WRITE ? MCF_MMU_MMUDR_W : 0) | /* write access enable */
(flags->access & ACCESS_EXECUTE ? MCF_MMU_MMUDR_X : 0) | /* execute access enable */
(flags->read ? MCF_MMU_MMUDR_R : 0) | /* read access enable */
(flags->write ? MCF_MMU_MMUDR_W : 0) | /* write access enable */
(flags->execute ? MCF_MMU_MMUDR_X : 0) | /* execute access enable */
(flags->locked ? MCF_MMU_MMUDR_LK : 0);
NOP();
@@ -372,38 +367,52 @@ void mmu_init(void)
{
extern uint8_t _MMUBAR[];
uint32_t MMUBAR = (uint32_t) &_MMUBAR[0];
struct mmu_map_flags flags;
struct page_descriptor flags;
int i;
/*
* prelaminary initialization of page descriptor 0 (root) table
* clear all MMU TLB entries first
*/
MCF_MMU_MMUOR = MCF_MMU_MMUOR_CA;
NOP();
/*
* prelaminary initialization of page descriptor 0 (root) table
*/
for (i = 0; i < sizeof(pages); i++)
{
uint32_t addr = i * DEFAULT_PAGE_SIZE;
uint32_t addr = i * DEFAULT_PAGE_SIZE;
if (addr >= 0x00f00000 && addr < 0x00ffffff)
if (addr >= 0x00f00000 && addr < 0x00ffffff)
{
pages[i].cache_mode = CACHE_NOCACHE_PRECISE;
pages[i].execute = 0;
pages[i].supervisor_protect = 1;
}
else if (addr >= 0x0 && addr < 0x00f00000) /* ST-RAM, potential video memory */
{
pages[i].cache_mode = CACHE_WRITETHROUGH;
pages[i].execute = 1;
pages[i].supervisor_protect = 0;
}
else
{
pages[i].cache_mode = CACHE_COPYBACK;
pages[i].execute = 1;
pages[i].supervisor_protect = 0;
}
pages[i].global = 1; /* all pages global by default */
pages[i].locked = 0; /* not locked */
pages[i].read = 1; /* readable, writable, executable */
pages[i].global = 1; /* all pages global by default */
pages[i].locked = 0; /* not locked */
pages[i].read = 1; /* readable, writable, executable */
pages[i].write = 1;
pages[i].execute = 1;
pages[i].supervisor_protect = 0; /* not supervisor protected */
}
set_asid(0); /* do not use address extension (ASID provides virtual 48 bit addresses) yet */
set_asid(0); /* do not use address extension (ASID provides virtual 48 bit addresses) yet */
/* set data access attributes in ACR0 and ACR1 */
set_acr0(ACR_W(0) | /* read and write accesses permitted */
ACR_SP(0) | /* supervisor and user mode access permitted */
ACR_CM(ACR_CM_CACHE_INH_PRECISE) | /* cache inhibit, precise (i/o area!) */
ACR_CM(ACR_CM_CACHE_INH_PRECISE) | /* cache inhibit, precise (i/o area!) */
ACR_AMM(0) | /* control region > 16 MB */
ACR_S(ACR_S_ALL) | /* match addresses in user and supervisor mode */
ACR_E(1) | /* enable ACR */
@@ -425,7 +434,7 @@ void mmu_init(void)
ACR_SP(0) |
ACR_CM(0) |
#if defined(MACHINE_FIREBEE)
ACR_CM(ACR_CM_CACHEABLE_WT) | /* ST RAM on the Firebee */
ACR_CM(ACR_CM_CACHEABLE_WT) | /* ST RAM on the Firebee */
#elif defined(MACHINE_M5484LITE)
ACR_CM(ACR_CM_CACHE_INH_PRECISE) | /* Compact Flash on the M548xLITE */
#elif defined(MACHINE_M54455)
@@ -441,7 +450,7 @@ void mmu_init(void)
/* set instruction access attributes in ACR2 and ACR3 */
//set_acr2(0xe007c400); /* flash area */
//set_acr2(0xe007c400); /* flash area */
set_acr2(ACR_W(0) |
ACR_SP(0) |
ACR_CM(0) |
@@ -467,18 +476,33 @@ void mmu_init(void)
* virtual address. This is also used (completely) when BaS is in RAM
*/
flags.cache_mode = CACHE_COPYBACK;
flags.access = ACCESS_READ | ACCESS_WRITE | ACCESS_EXECUTE;
flags.protection = SV_PROTECT; /* supervisor access only */
mmu_map_page(SDRAM_START + SDRAM_SIZE - 0X00200000, SDRAM_START + SDRAM_SIZE - 0X00200000, MMU_PAGE_SIZE_1M, &flags);
flags.read = 1;
flags.write = 1;
flags.execute = 1;
flags.supervisor_protect = 1; /* supervisor access only */
flags.locked = 1;
mmu_map_page(SDRAM_START + SDRAM_SIZE - 0x00200000, SDRAM_START + SDRAM_SIZE - 0x00200000, 0, MMU_PAGE_SIZE_1M, &flags);
/*
* map EmuTOS (locked for now)
*/
flags.read = 1;
flags.write = 1;
flags.execute = 1;
flags.locked = 1;
mmu_map_page(0xe00000, 0xe00000, MMU_PAGE_SIZE_1M, 0, &flags);
/*
* Map (locked) the very last MB of physical SDRAM (this is where the driver buffers reside) to the same
* virtual address. Used uncached for drivers.
*/
flags.cache_mode = CACHE_NOCACHE_PRECISE;
flags.access = ACCESS_READ | ACCESS_WRITE;
flags.protection = SV_PROTECT;
mmu_map_page(SDRAM_START + SDRAM_SIZE - 0x00100000, SDRAM_START + SDRAM_SIZE - 0x00100000, MMU_PAGE_SIZE_1M, &flags);
flags.read = 1;
flags.write = 1;
flags.execute = 0;
flags.supervisor_protect = 1;
flags.locked = 1;
mmu_map_page(SDRAM_START + SDRAM_SIZE - 0x00100000, SDRAM_START + SDRAM_SIZE - 0x00100000, 0, MMU_PAGE_SIZE_1M, &flags);
}
@@ -489,12 +513,16 @@ void mmutr_miss(uint32_t address, uint32_t pc, uint32_t format_status)
#ifdef _NOT_USED_
// experimental; try to ensure that supervisor stack area stays in mmu TLBs
// guess what: doesn't work...
// guess what: doesn't work...
register uint32_t sp asm("sp");
dbg("stack is at %p\r\n", sp);
if (sp < 0x02000000)
{
dbg("mapped stack at 0x%08x\r\n");
mmu_map_8k_page(sp);
flush_and_invalidate_caches();
#endif /* _NOT_USED_ */
//flush_and_invalidate_caches();
}
#endif /* _NOT_USED */
switch (address)
{
@@ -513,9 +541,6 @@ void mmutr_miss(uint32_t address, uint32_t pc, uint32_t format_status)
default:
/* add missed page to TLB */
mmu_map_8k_page(address);
dbg("DTLB: MCF_MMU_MMUOR = %08x\r\n", MCF_MMU_MMUOR);
dbg("ITLB: MCF_MMU_MMUOR = %08x\r\n\r\n", MCF_MMU_MMUOR);
}
}

View File

@@ -49,6 +49,8 @@ _rom_entry:
/* set stack pointer to end of SRAM */
lea __SUP_SP,a7
move.l #0,(sp)
subq.l #4,sp
move.l #0,(sp)
/*
* Initialize the processor caches.