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

View File

@@ -310,12 +310,12 @@ init_vec_loop:
*/ */
vector_table_start: vector_table_start:
std_exc_vec: std_exc_vec:
//move.w #0x2700,sr // disable interrupt move.w #0x2700,sr // disable interrupt
subq.l #8,sp subq.l #8,sp
movem.l d0/a5,(sp) // save registers movem.l d0/a5,(sp) // save registers
move.w 8(sp),d0 // fetch vector move.w 8(sp),d0 // fetch vector
and.l #0x3fc,d0 // mask out vector number and.l #0x3fc,d0 // mask out vector number
#define DBG_EXC
#ifdef DBG_EXC #ifdef DBG_EXC
// printout vector number of exception // printout vector number of exception
@@ -388,12 +388,6 @@ access_mmu:
move.l MCF_MMU_MMUSR,d0 // did the last fault hit in TLB? 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 btst #1,d0 // yes, it did. So we already mapped that page
bne bus_error // and this must be a real bus error 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 move.l MCF_MMU_MMUAR,d0
cmp.l #__FASTRAM_END,d0 // above max User RAM area? cmp.l #__FASTRAM_END,d0 // above max User RAM area?
@@ -690,11 +684,13 @@ handler_gpt0:
link a6,#-4 * 4 // make room for link a6,#-4 * 4 // make room for
movem.l d0-d1/a0-a1,(sp) // gcc scratch registers and save them, movem.l d0-d1/a0-a1,(sp) // gcc scratch registers and save them,
// other registers will be handled by gcc itself // other registers will be handled by gcc itself
move.w 4(a6),d0 // fetch vector number from stack move.w 4(a6),d0 // fetch vector number from stack
move.l d0,-(sp) // push it move.l d0,-(sp) // push it
jsr _gpt0_interrupt_handler // call C handler jsr _gpt0_interrupt_handler // call C handler
addq.l #4,sp // adjust stack addq.l #4,sp // adjust stack
movem.l (sp),d0-d1/a0-a1 // restore registers
unlk a6 unlk a6
rte rte
#endif /* MACHINE_FIREBEE */ #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 register_interrupt_handler(uint8_t source, uint8_t level, uint8_t priority, uint8_t intr, void (*handler)(void))
{ {
int ipl; int ipl;
int i; int i;
volatile uint8_t *ICR = &MCF_INTC_ICR01 - 1; volatile uint8_t *ICR = &MCF_INTC_ICR01 - 1;
uint8_t lp; uint8_t lp;
source &= 63; source &= 63;
priority &= 7; priority &= 7;
if (source < 1 || source > 63) if (source < 1 || source > 63)
{ {
dbg("interrupt source %d not defined\r\n", source); dbg("interrupt source %d not defined\r\n", source);
return -1; 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 */ /* check if this combination is already set somewhere */
for (i = 1; i < 64; i++) for (i = 1; i < 64; i++)
{ {
if (ICR[i] == lp) if (ICR[i] == lp)
{ {
dbg("level %d and priority %d already used for interrupt source %d!\r\n", dbg("level %d and priority %d already used for interrupt source %d!\r\n",
level, priority, i); level, priority, i);
return -1; return -1;
} }
} }
/* disable interrupts */ /* disable interrupts */
ipl = set_ipl(7); 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 */ /* set level and priority in interrupt controller */
ICR[source] = lp; ICR[source] = lp;
/* set interrupt mask to where it was before */ /* set interrupt mask to where it was before */
set_ipl(ipl); set_ipl(ipl);
return 0; return 0;
} }
#ifndef MAX_ISR_ENTRY #ifndef MAX_ISR_ENTRY
@@ -100,10 +100,10 @@ int register_interrupt_handler(uint8_t source, uint8_t level, uint8_t priority,
struct isrentry struct isrentry
{ {
int vector; int vector;
int (*handler)(void *, void *); int (*handler)(void *, void *);
void *hdev; void *hdev;
void *harg; void *harg;
}; };
static struct isrentry isrtab[MAX_ISR_ENTRY]; /* list of interrupt service routines */ 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) 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 isr_register_handler(int vector, int (*handler)(void *, void *), void *hdev, void *harg)
{ {
int index; int index;
if ((vector == 0) || (handler == NULL)) if ((vector == 0) || (handler == NULL))
{ {
dbg("illegal vector or handler!\r\n"); dbg("illegal vector or handler!\r\n");
return false; return false;
} }
for (index = 0; index < MAX_ISR_ENTRY; index++) for (index = 0; index < MAX_ISR_ENTRY; index++)
{ {
if (isrtab[index].vector == vector) if (isrtab[index].vector == vector)
{ {
/* one cross each, only! */ /* one cross each, only! */
dbg("already set handler with this vector (%d, %d)\r\n", vector); dbg("already set handler with this vector (%d, %d)\r\n", vector);
return false; return false;
} }
if (isrtab[index].vector == 0) if (isrtab[index].vector == 0)
{ {
isrtab[index].vector = vector; isrtab[index].vector = vector;
isrtab[index].handler = handler; isrtab[index].handler = handler;
isrtab[index].hdev = hdev; isrtab[index].hdev = hdev;
isrtab[index].harg = harg; isrtab[index].harg = harg;
return true; return true;
} }
} }
dbg("no available slots to register handler for vector %d\n\r", vector); 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 *)) void isr_remove_handler(int (*handler)(void *, void *))
{ {
/* /*
* This routine removes from the ISR table all * This routine removes from the ISR table all
* entries that matches 'handler'. * entries that matches 'handler'.
*/ */
int index; int index;
for (index = 0; index < MAX_ISR_ENTRY; index++) for (index = 0; index < MAX_ISR_ENTRY; index++)
{ {
if (isrtab[index].handler == handler) if (isrtab[index].handler == handler)
{ {
memset(&isrtab[index], 0, sizeof(struct isrentry)); memset(&isrtab[index], 0, sizeof(struct isrentry));
return; return;
} }
} }
dbg("no such handler registered (handler=%p\r\n", handler); 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) bool isr_execute_handler(int vector)
{ {
int index; int index;
bool retval = false; bool retval = false;
/* /*
* locate a BaS Interrupt Service Routine handler. * locate a BaS Interrupt Service Routine handler.
*/ */
for (index = 0; index < MAX_ISR_ENTRY; index++) for (index = 0; index < MAX_ISR_ENTRY; index++)
{ {
if (isrtab[index].vector == vector) if (isrtab[index].vector == vector)
{ {
retval = true; retval = true;
if (isrtab[index].handler(isrtab[index].hdev, isrtab[index].harg)) if (isrtab[index].handler(isrtab[index].hdev, isrtab[index].harg))
{ {
return retval; return retval;
} }
} }
} }
dbg("no BaS isr handler for vector %d found\r\n", vector); 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) int pic_interrupt_handler(void *arg1, void *arg2)
{ {
uint8_t rcv_byte; uint8_t rcv_byte;
rcv_byte = MCF_PSC3_PSCRB_8BIT; rcv_byte = MCF_PSC3_PSCRB_8BIT;
if (rcv_byte == 2) // PIC requests RTC data if (rcv_byte == 2) // PIC requests RTC data
{ {
uint8_t *rtc_reg = (uint8_t *) 0xffff8961; uint8_t *rtc_reg = (uint8_t *) 0xffff8961;
uint8_t *rtc_data = (uint8_t *) 0xffff8963; uint8_t *rtc_data = (uint8_t *) 0xffff8963;
int index = 0; 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 MCF_PSC3_PSCTB_8BIT = 0x82; // header byte to PIC
do do
{ {
*rtc_reg = 0; *rtc_reg = 0;
MCF_PSC3_PSCTB_8BIT = *rtc_data; MCF_PSC3_PSCTB_8BIT = *rtc_data;
} while (index++ < 64); } while (index++ < 64);
} }
return 1; return 1;
} }
extern int32_t video_sbt; extern int32_t video_sbt;
@@ -241,93 +241,93 @@ extern int32_t video_tlb;
void video_addr_timeout(void) void video_addr_timeout(void)
{ {
uint32_t addr = 0x0L; uint32_t addr = 0x0L;
uint32_t *src; uint32_t *src;
uint32_t *dst; uint32_t *dst;
uint32_t asid; uint32_t asid;
dbg("video address timeout\r\n"); dbg("video address timeout\r\n");
flush_and_invalidate_caches(); flush_and_invalidate_caches();
do do
{ {
uint32_t tlb; uint32_t tlb;
uint32_t page_attr; uint32_t page_attr;
/* /*
* search tlb entry id for addr (if not available, the MMU * search tlb entry id for addr (if not available, the MMU
* will provide a new one based on its LRU algorithm) * will provide a new one based on its LRU algorithm)
*/ */
MCF_MMU_MMUAR = addr; MCF_MMU_MMUAR = addr;
MCF_MMU_MMUOR = MCF_MMU_MMUOR =
MCF_MMU_MMUOR_STLB | MCF_MMU_MMUOR_STLB |
MCF_MMU_MMUOR_RW | MCF_MMU_MMUOR_RW |
MCF_MMU_MMUOR_ACC; MCF_MMU_MMUOR_ACC;
NOP(); NOP();
tlb = (MCF_MMU_MMUOR >> 16) & 0xffff; tlb = (MCF_MMU_MMUOR >> 16) & 0xffff;
/* /*
* retrieve tlb entry with the found TLB entry id * retrieve tlb entry with the found TLB entry id
*/ */
MCF_MMU_MMUAR = tlb; MCF_MMU_MMUAR = tlb;
MCF_MMU_MMUOR = MCF_MMU_MMUOR =
MCF_MMU_MMUOR_STLB | MCF_MMU_MMUOR_STLB |
MCF_MMU_MMUOR_ADR | MCF_MMU_MMUOR_ADR |
MCF_MMU_MMUOR_RW | MCF_MMU_MMUOR_RW |
MCF_MMU_MMUOR_ACC; MCF_MMU_MMUOR_ACC;
NOP(); NOP();
asid = (MCF_MMU_MMUTR >> 2) & 0x1fff; /* fetch ASID of page */; asid = (MCF_MMU_MMUTR >> 2) & 0x1fff; /* fetch ASID of page */;
if (asid != sca_page_ID) /* check if screen area */ if (asid != sca_page_ID) /* check if screen area */
{ {
addr += 0x100000; addr += 0x100000;
continue; /* next page */ continue; /* next page */
} }
/* modify found TLB entry */ /* modify found TLB entry */
if (addr == 0x0) if (addr == 0x0)
{ {
page_attr = page_attr =
MCF_MMU_MMUDR_LK | MCF_MMU_MMUDR_LK |
MCF_MMU_MMUDR_SZ(0) | MCF_MMU_MMUDR_SZ(0) |
MCF_MMU_MMUDR_CM(0) | MCF_MMU_MMUDR_CM(0) |
MCF_MMU_MMUDR_R | MCF_MMU_MMUDR_R |
MCF_MMU_MMUDR_W | MCF_MMU_MMUDR_W |
MCF_MMU_MMUDR_X; MCF_MMU_MMUDR_X;
} }
else else
{ {
page_attr = page_attr =
MCF_MMU_MMUTR_SG | MCF_MMU_MMUTR_SG |
MCF_MMU_MMUTR_V; MCF_MMU_MMUTR_V;
} }
MCF_MMU_MMUTR = addr; MCF_MMU_MMUTR = addr;
MCF_MMU_MMUDR = page_attr; MCF_MMU_MMUDR = page_attr;
MCF_MMU_MMUOR = MCF_MMU_MMUOR =
MCF_MMU_MMUOR_STLB | MCF_MMU_MMUOR_STLB |
MCF_MMU_MMUOR_ADR | MCF_MMU_MMUOR_ADR |
MCF_MMU_MMUOR_ACC | MCF_MMU_MMUOR_ACC |
MCF_MMU_MMUOR_UAA; MCF_MMU_MMUOR_UAA;
NOP(); NOP();
dst = (uint32_t *) 0x60000000 + addr; dst = (uint32_t *) 0x60000000 + addr;
src = (uint32_t *) addr; src = (uint32_t *) addr;
while (dst < (uint32_t *) 0x60000000 + addr + 0x10000) while (dst < (uint32_t *) 0x60000000 + addr + 0x10000)
{ {
*dst++ = *src++; *dst++ = *src++;
*dst++ = *src++; *dst++ = *src++;
*dst++ = *src++; *dst++ = *src++;
*dst++ = *src++; *dst++ = *src++;
} }
addr += 0x100000; addr += 0x100000;
} while (addr < 0xd00000); } while (addr < 0xd00000);
video_tlb = 0x2000; video_tlb = 0x2000;
video_sbt = 0; video_sbt = 0;
} }
@@ -336,16 +336,16 @@ void video_addr_timeout(void)
*/ */
void blink_led(void) void blink_led(void)
{ {
static uint16_t blinker = 0; static uint16_t blinker = 0;
if ((blinker++ & 0x80) > 0) if ((blinker++ & 0x80) > 0)
{ {
MCF_GPIO_PODR_FEC1L |= (1 << 4); /* LED off */ MCF_GPIO_PODR_FEC1L |= (1 << 4); /* LED off */
} }
else else
{ {
MCF_GPIO_PODR_FEC1L &= ~(1 << 4); /* LED on */ MCF_GPIO_PODR_FEC1L &= ~(1 << 4); /* LED on */
} }
} }
/* /*
@@ -363,47 +363,47 @@ void blink_led(void)
bool irq6_acsi_dma_interrupt(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 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) if (video_sbt != 0 && (video_sbt - 0x70000000) > MCF_SLT0_SCNT)
{ {
video_addr_timeout(); video_addr_timeout();
handled = true; handled = true;
} }
/* /*
* check if ACSI DMA interrupt * check if ACSI DMA interrupt
*/ */
if (FALCON_MFP_IERA & (1 << 7)) if (FALCON_MFP_IERA & (1 << 7))
{ {
/* ACSI interrupt is enabled */ /* ACSI interrupt is enabled */
if (FALCON_MFP_IPRA & (1 << 7)) if (FALCON_MFP_IPRA & (1 << 7))
{ {
irq6_acsi_dma_interrupt(); irq6_acsi_dma_interrupt();
handled = true; handled = true;
} }
} }
if (FALCON_MFP_IPRA || FALCON_MFP_IPRB) if (FALCON_MFP_IPRA || FALCON_MFP_IPRB)
{ {
blink_led(); blink_led();
} }
return handled; return handled;
} }
#if defined(MACHINE_FIREBEE) #if defined(MACHINE_FIREBEE)
@@ -430,112 +430,10 @@ bool irq6_interrupt_handler(uint32_t sf1, uint32_t sf2)
*/ */
void gpt0_interrupt_handler(void) void gpt0_interrupt_handler(void)
{ {
uint32_t video_address; dbg("screen base = 0x%x\r\n", vbasehi);
uint32_t video_end_address;
int page_number;
bool already_set;
extern uint32_t _STRAM_END;
dbg("screen base = 0x%x\r\n", vbasehi); MCF_GPT0_GMS &= ~1; /* rearm trigger */
NOP();
if (vbasehi < 2) /* screen base lower than 0x20000? */ MCF_GPT0_GMS |= 1;
{
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;
} }
#endif /* MACHINE_FIREBEE */ #endif /* MACHINE_FIREBEE */

View File

@@ -62,7 +62,7 @@
#error "unknown machine!" #error "unknown machine!"
#endif /* MACHINE_FIREBEE */ #endif /* MACHINE_FIREBEE */
#define DEBUG_MMU //#define DEBUG_MMU
#ifdef DEBUG_MMU #ifdef DEBUG_MMU
#define dbg(format, arg...) do { xprintf("DEBUG (%s()): " format, __FUNCTION__, ##arg);} while(0) #define dbg(format, arg...) do { xprintf("DEBUG (%s()): " format, __FUNCTION__, ##arg);} while(0)
#else #else
@@ -199,14 +199,14 @@ struct virt_to_phys
{ {
uint32_t start_address; uint32_t start_address;
uint32_t length; uint32_t length;
uint32_t physical_offset; uint32_t physical_offset;
}; };
static struct virt_to_phys translation[] = static struct virt_to_phys translation[] =
{ {
/* virtual , length , offset */ /* virtual , length , offset */
{ 0x00000000, 0x00e00000, 0x60000000 }, /* map first 14 MByte to first 14 Mb of video ram */ { 0x00000000, 0x00e00000, 0x60000000 }, /* map first 14 MByte to first 14 Mb of video ram */
{ 0x00e00000, 0x00100000, 0x00000000 }, /* map TOS to SDRAM */ //{ 0x00e00000, 0x00100000, 0x00000000 }, /* map TOS to SDRAM */
{ 0x00f00000, 0x00100000, 0xff000000 }, /* map Falcon I/O area to FPGA */ { 0x00f00000, 0x00100000, 0xff000000 }, /* map Falcon I/O area to FPGA */
{ 0x01000000, 0x10000000, 0x00000000 }, /* map rest of ram virt = phys */ { 0x01000000, 0x10000000, 0x00000000 }, /* map rest of ram virt = phys */
{ 0x1fd00000, 0x01000000, 0x00000000 }, /* accessed by EmuTOS? */ { 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++) 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 struct page_descriptor
@@ -254,11 +254,11 @@ static struct page_descriptor pages[65536]; /* 512 Mb RAM */
*/ */
int mmu_map_8k_page(uint32_t virt) int mmu_map_8k_page(uint32_t virt)
{ {
const int size_mask = 0xffffe000; /* 8k pagesize */ const int size_mask = 0xffffe000; /* 8k pagesize */
int page_index = (virt & size_mask) / 4096; /* index into page_descriptor array */ 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 */ 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 * add page to TLB
@@ -269,7 +269,7 @@ int mmu_map_8k_page(uint32_t virt)
MCF_MMU_MMUTR_V; /* valid */ MCF_MMU_MMUTR_V; /* valid */
NOP(); 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_SZ(MMU_PAGE_SIZE_8K) | /* page size */
MCF_MMU_MMUDR_CM(page->cache_mode) | MCF_MMU_MMUDR_CM(page->cache_mode) |
(page->read ? MCF_MMU_MMUDR_R : 0) | /* read access enable */ (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 */ MCF_MMU_MMUOR_UAA; /* update allocation address field */
NOP(); 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 = MCF_MMU_MMUOR_ITLB | /* instruction */
MCF_MMU_MMUOR_ACC | /* access TLB */ MCF_MMU_MMUOR_ACC | /* access TLB */
MCF_MMU_MMUOR_UAA; /* update allocation address field */ 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; 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. * 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; 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; break;
default: default:
err("illegal map size %d\r\n", sz); err("illegal map size %d\r\n", sz);
} }
/* /*
* add page to TLB * add page to TLB
*/ */
MCF_MMU_MMUTR = ((int) virt & size_mask) | /* virtual address */ MCF_MMU_MMUTR = ((uint32_t) virt & size_mask) | /* virtual address */
MCF_MMU_MMUTR_ID(flags->page_id) | /* address space id (ASID) */ MCF_MMU_MMUTR_ID(page_id) | /* address space id (ASID) */
MCF_MMU_MMUTR_SG | /* shared global */ (flags->global ? MCF_MMU_MMUTR_SG : 0) | /* shared global */
MCF_MMU_MMUTR_V; /* valid */ MCF_MMU_MMUTR_V; /* valid */
NOP(); 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_SZ(sz) | /* page size */
MCF_MMU_MMUDR_CM(flags->cache_mode) | MCF_MMU_MMUDR_CM(flags->cache_mode) |
(flags->access & ACCESS_READ ? MCF_MMU_MMUDR_R : 0) | /* read access enable */ (flags->read ? MCF_MMU_MMUDR_R : 0) | /* read access enable */
(flags->access & ACCESS_WRITE ? MCF_MMU_MMUDR_W : 0) | /* write access enable */ (flags->write ? MCF_MMU_MMUDR_W : 0) | /* write access enable */
(flags->access & ACCESS_EXECUTE ? MCF_MMU_MMUDR_X : 0) | /* execute access enable */ (flags->execute ? MCF_MMU_MMUDR_X : 0) | /* execute access enable */
(flags->locked ? MCF_MMU_MMUDR_LK : 0); (flags->locked ? MCF_MMU_MMUDR_LK : 0);
NOP(); NOP();
@@ -372,38 +367,52 @@ void mmu_init(void)
{ {
extern uint8_t _MMUBAR[]; extern uint8_t _MMUBAR[];
uint32_t MMUBAR = (uint32_t) &_MMUBAR[0]; uint32_t MMUBAR = (uint32_t) &_MMUBAR[0];
struct mmu_map_flags flags; struct page_descriptor flags;
int i; 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++) 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].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 else
{ {
pages[i].cache_mode = CACHE_COPYBACK; 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].global = 1; /* all pages global by default */
pages[i].locked = 0; /* not locked */ pages[i].locked = 0; /* not locked */
pages[i].read = 1; /* readable, writable, executable */ pages[i].read = 1; /* readable, writable, executable */
pages[i].write = 1; 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 data access attributes in ACR0 and ACR1 */
set_acr0(ACR_W(0) | /* read and write accesses permitted */ set_acr0(ACR_W(0) | /* read and write accesses permitted */
ACR_SP(0) | /* supervisor and user mode access 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_AMM(0) | /* control region > 16 MB */
ACR_S(ACR_S_ALL) | /* match addresses in user and supervisor mode */ ACR_S(ACR_S_ALL) | /* match addresses in user and supervisor mode */
ACR_E(1) | /* enable ACR */ ACR_E(1) | /* enable ACR */
@@ -425,7 +434,7 @@ void mmu_init(void)
ACR_SP(0) | ACR_SP(0) |
ACR_CM(0) | ACR_CM(0) |
#if defined(MACHINE_FIREBEE) #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) #elif defined(MACHINE_M5484LITE)
ACR_CM(ACR_CM_CACHE_INH_PRECISE) | /* Compact Flash on the M548xLITE */ ACR_CM(ACR_CM_CACHE_INH_PRECISE) | /* Compact Flash on the M548xLITE */
#elif defined(MACHINE_M54455) #elif defined(MACHINE_M54455)
@@ -441,7 +450,7 @@ void mmu_init(void)
/* set instruction access attributes in ACR2 and ACR3 */ /* set instruction access attributes in ACR2 and ACR3 */
//set_acr2(0xe007c400); /* flash area */ //set_acr2(0xe007c400); /* flash area */
set_acr2(ACR_W(0) | set_acr2(ACR_W(0) |
ACR_SP(0) | ACR_SP(0) |
ACR_CM(0) | ACR_CM(0) |
@@ -467,18 +476,33 @@ void mmu_init(void)
* virtual address. This is also used (completely) when BaS is in RAM * virtual address. This is also used (completely) when BaS is in RAM
*/ */
flags.cache_mode = CACHE_COPYBACK; flags.cache_mode = CACHE_COPYBACK;
flags.access = ACCESS_READ | ACCESS_WRITE | ACCESS_EXECUTE; flags.read = 1;
flags.protection = SV_PROTECT; /* supervisor access only */ flags.write = 1;
mmu_map_page(SDRAM_START + SDRAM_SIZE - 0X00200000, SDRAM_START + SDRAM_SIZE - 0X00200000, MMU_PAGE_SIZE_1M, &flags); 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 * 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. * virtual address. Used uncached for drivers.
*/ */
flags.cache_mode = CACHE_NOCACHE_PRECISE; flags.cache_mode = CACHE_NOCACHE_PRECISE;
flags.access = ACCESS_READ | ACCESS_WRITE; flags.read = 1;
flags.protection = SV_PROTECT; flags.write = 1;
mmu_map_page(SDRAM_START + SDRAM_SIZE - 0x00100000, SDRAM_START + SDRAM_SIZE - 0x00100000, MMU_PAGE_SIZE_1M, &flags); 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_ #ifdef _NOT_USED_
// experimental; try to ensure that supervisor stack area stays in mmu TLBs // 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"); register uint32_t sp asm("sp");
dbg("stack is at %p\r\n", sp);
if (sp < 0x02000000) if (sp < 0x02000000)
{
dbg("mapped stack at 0x%08x\r\n");
mmu_map_8k_page(sp); mmu_map_8k_page(sp);
flush_and_invalidate_caches(); //flush_and_invalidate_caches();
#endif /* _NOT_USED_ */ }
#endif /* _NOT_USED */
switch (address) switch (address)
{ {
@@ -513,9 +541,6 @@ void mmutr_miss(uint32_t address, uint32_t pc, uint32_t format_status)
default: default:
/* add missed page to TLB */ /* add missed page to TLB */
mmu_map_8k_page(address); 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 */ /* set stack pointer to end of SRAM */
lea __SUP_SP,a7 lea __SUP_SP,a7
move.l #0,(sp) move.l #0,(sp)
subq.l #4,sp
move.l #0,(sp)
/* /*
* Initialize the processor caches. * Initialize the processor caches.