fixed wrong stack address offset for "magic number"

This commit is contained in:
Markus Fröschle
2014-09-30 19:29:46 +00:00
parent 2661e9d831
commit f90cc6a8a4
4 changed files with 311 additions and 500 deletions

View File

@@ -37,7 +37,7 @@
*/ */
static struct xhdi_driver_interface xhdi_call_interface = static struct xhdi_driver_interface xhdi_call_interface =
{ {
xhdi_call xhdi_call
}; };
/* /*
@@ -47,27 +47,27 @@ static struct xhdi_driver_interface xhdi_call_interface =
*/ */
static struct dma_driver_interface dma_interface = static struct dma_driver_interface dma_interface =
{ {
.version = 0x0101, .version = 0x0101,
.magic = 0x444d4143, /* 'DMAC' */ .magic = 0x444d4143, /* 'DMAC' */
.dma_set_initiator = dma_set_initiator, .dma_set_initiator = dma_set_initiator,
.dma_get_initiator = dma_get_initiator, .dma_get_initiator = dma_get_initiator,
.dma_free_initiator = dma_free_initiator, .dma_free_initiator = dma_free_initiator,
.dma_set_channel = dma_set_channel, .dma_set_channel = dma_set_channel,
.dma_get_channel = dma_get_channel, .dma_get_channel = dma_get_channel,
.dma_free_channel = dma_free_channel, .dma_free_channel = dma_free_channel,
.dma_clear_channel = dma_clear_channel, .dma_clear_channel = dma_clear_channel,
.MCD_startDma = (int (*)(long, int8_t *, unsigned int, int8_t *, unsigned int, .MCD_startDma = (int (*)(long, int8_t *, unsigned int, int8_t *, unsigned int,
unsigned int, unsigned int, unsigned int, int, unsigned int, unsigned int, unsigned int, int,
unsigned int, unsigned int)) MCD_startDma, unsigned int, unsigned int)) MCD_startDma,
.MCD_dmaStatus = (int32_t (*)(int32_t)) MCD_dmaStatus, .MCD_dmaStatus = (int32_t (*)(int32_t)) MCD_dmaStatus,
.MCD_XferProgrQuery = (int32_t (*)(int32_t, MCD_XferProg *)) MCD_XferProgrQuery, .MCD_XferProgrQuery = (int32_t (*)(int32_t, MCD_XferProg *)) MCD_XferProgrQuery,
.MCD_killDma = (int32_t (*)(int32_t)) MCD_killDma, .MCD_killDma = (int32_t (*)(int32_t)) MCD_killDma,
.MCD_continDma = (int32_t (*)(int32_t)) MCD_continDma, .MCD_continDma = (int32_t (*)(int32_t)) MCD_continDma,
.MCD_pauseDma = (int32_t (*)(int32_t)) MCD_pauseDma, .MCD_pauseDma = (int32_t (*)(int32_t)) MCD_pauseDma,
.MCD_resumeDma = (int32_t (*)(int32_t)) MCD_resumeDma, .MCD_resumeDma = (int32_t (*)(int32_t)) MCD_resumeDma,
.MCD_csumQuery = (int32_t (*)(int32_t, uint32_t *)) MCD_csumQuery, .MCD_csumQuery = (int32_t (*)(int32_t, uint32_t *)) MCD_csumQuery,
.dma_malloc = driver_mem_alloc, .dma_malloc = driver_mem_alloc,
.dma_free = driver_mem_free .dma_free = driver_mem_free
}; };
extern struct fb_info *info_fb; extern struct fb_info *info_fb;
@@ -77,51 +77,51 @@ extern struct fb_info *info_fb;
*/ */
static struct pci_bios_interface pci_interface = static struct pci_bios_interface pci_interface =
{ {
.subjar = 0, .subjar = 0,
.version = 0x00010000, .version = 0x00010000,
.find_pci_device = wrapper_find_pci_device, .find_pci_device = wrapper_find_pci_device,
.find_pci_classcode = wrapper_find_pci_classcode, .find_pci_classcode = wrapper_find_pci_classcode,
.read_config_byte = wrapper_read_config_byte, .read_config_byte = wrapper_read_config_byte,
.read_config_word = wrapper_read_config_word, .read_config_word = wrapper_read_config_word,
.read_config_longword = wrapper_read_config_longword, .read_config_longword = wrapper_read_config_longword,
.fast_read_config_byte = wrapper_fast_read_config_byte, .fast_read_config_byte = wrapper_fast_read_config_byte,
.fast_read_config_word = wrapper_fast_read_config_word, .fast_read_config_word = wrapper_fast_read_config_word,
.fast_read_config_longword = wrapper_fast_read_config_longword, .fast_read_config_longword = wrapper_fast_read_config_longword,
.write_config_byte = wrapper_write_config_byte, .write_config_byte = wrapper_write_config_byte,
.write_config_word = wrapper_write_config_word, .write_config_word = wrapper_write_config_word,
.write_config_longword = wrapper_write_config_longword, .write_config_longword = wrapper_write_config_longword,
.hook_interrupt = wrapper_hook_interrupt, .hook_interrupt = wrapper_hook_interrupt,
.unhook_interrupt = wrapper_unhook_interrupt, .unhook_interrupt = wrapper_unhook_interrupt,
.special_cycle = wrapper_special_cycle, .special_cycle = wrapper_special_cycle,
.get_routing = wrapper_get_routing, .get_routing = wrapper_get_routing,
.set_interrupt = wrapper_set_interrupt, .set_interrupt = wrapper_set_interrupt,
.get_resource = wrapper_get_resource, .get_resource = wrapper_get_resource,
.get_card_used = wrapper_get_card_used, .get_card_used = wrapper_get_card_used,
.set_card_used = wrapper_set_card_used, .set_card_used = wrapper_set_card_used,
.read_mem_byte = wrapper_read_mem_byte, .read_mem_byte = wrapper_read_mem_byte,
.read_mem_word = wrapper_read_mem_word, .read_mem_word = wrapper_read_mem_word,
.read_mem_longword = wrapper_read_mem_longword, .read_mem_longword = wrapper_read_mem_longword,
.fast_read_mem_byte = wrapper_fast_read_mem_byte, .fast_read_mem_byte = wrapper_fast_read_mem_byte,
.fast_read_mem_word = wrapper_fast_read_mem_word, .fast_read_mem_word = wrapper_fast_read_mem_word,
.fast_read_mem_longword = wrapper_fast_read_mem_longword, .fast_read_mem_longword = wrapper_fast_read_mem_longword,
.write_mem_byte = wrapper_write_mem_byte, .write_mem_byte = wrapper_write_mem_byte,
.write_mem_word = wrapper_write_mem_word, .write_mem_word = wrapper_write_mem_word,
.write_mem_longword = wrapper_write_mem_longword, .write_mem_longword = wrapper_write_mem_longword,
.read_io_byte = wrapper_read_io_byte, .read_io_byte = wrapper_read_io_byte,
.read_io_word = wrapper_read_io_word, .read_io_word = wrapper_read_io_word,
.read_io_longword = wrapper_read_io_longword, .read_io_longword = wrapper_read_io_longword,
.fast_read_io_byte = wrapper_fast_read_io_byte, .fast_read_io_byte = wrapper_fast_read_io_byte,
.fast_read_io_word = wrapper_fast_read_io_word, .fast_read_io_word = wrapper_fast_read_io_word,
.fast_read_io_longword = wrapper_fast_read_io_longword, .fast_read_io_longword = wrapper_fast_read_io_longword,
.write_io_byte = wrapper_write_io_byte, .write_io_byte = wrapper_write_io_byte,
.write_io_word = wrapper_write_io_word, .write_io_word = wrapper_write_io_word,
.write_io_longword = wrapper_write_io_longword, .write_io_longword = wrapper_write_io_longword,
.get_machine_id = wrapper_get_machine_id, .get_machine_id = wrapper_get_machine_id,
.get_pagesize = wrapper_get_pagesize, .get_pagesize = wrapper_get_pagesize,
.virt_to_bus = wrapper_virt_to_bus, .virt_to_bus = wrapper_virt_to_bus,
.bus_to_virt = wrapper_bus_to_virt, .bus_to_virt = wrapper_bus_to_virt,
.virt_to_phys = wrapper_virt_to_phys, .virt_to_phys = wrapper_virt_to_phys,
.phys_to_virt = wrapper_phys_to_virt, .phys_to_virt = wrapper_phys_to_virt,
}; };
/* /*
@@ -129,7 +129,7 @@ static struct pci_bios_interface pci_interface =
*/ */
static struct framebuffer_driver_interface framebuffer_interface = static struct framebuffer_driver_interface framebuffer_interface =
{ {
.framebuffer_info = &info_fb .framebuffer_info = &info_fb
}; };
/* /*
@@ -137,61 +137,61 @@ static struct framebuffer_driver_interface framebuffer_interface =
*/ */
static struct mmu_driver_interface mmu_interface = static struct mmu_driver_interface mmu_interface =
{ {
.map_page_locked = &mmu_map_data_page_locked, .map_page_locked = &mmu_map_data_page_locked,
.unlock_page = &mmu_unlock_data_page, .unlock_page = &mmu_unlock_data_page,
.report_locked_pages = &mmu_report_locked_pages, .report_locked_pages = &mmu_report_locked_pages,
.report_pagesize = &mmu_report_pagesize .report_pagesize = &mmu_report_pagesize
}; };
static struct generic_interface interfaces[] = static struct generic_interface interfaces[] =
{ {
{ {
/* BaS SD-card driver interface */ /* BaS SD-card driver interface */
.type = XHDI_DRIVER, .type = XHDI_DRIVER,
.name = "SDCARD", .name = "SDCARD",
.description = "BaS SD Card driver", .description = "BaS SD Card driver",
.version = 0, .version = 0,
.revision = 1, .revision = 1,
.interface.xhdi = &xhdi_call_interface .interface.xhdi = &xhdi_call_interface
}, },
{ {
.type = MCD_DRIVER, .type = MCD_DRIVER,
.name = "MCDDMA", .name = "MCDDMA",
.description = "BaS Multichannel DMA driver", .description = "BaS Multichannel DMA driver",
.version = 0, .version = 0,
.revision = 1, .revision = 1,
.interface.dma = &dma_interface, .interface.dma = &dma_interface,
}, },
{ {
.type = VIDEO_DRIVER, .type = VIDEO_DRIVER,
.name = "RADEON", .name = "RADEON",
.description = "BaS RADEON framebuffer driver", .description = "BaS RADEON framebuffer driver",
.version = 0, .version = 0,
.revision = 1, .revision = 1,
.interface.fb = &framebuffer_interface, .interface.fb = &framebuffer_interface,
}, },
{ {
.type = PCI_DRIVER, .type = PCI_DRIVER,
.name = "PCI", .name = "PCI",
.description = "BaS PCI_BIOS driver", .description = "BaS PCI_BIOS driver",
.version = 0, .version = 0,
.revision = 1, .revision = 1,
.interface.pci = &pci_interface, .interface.pci = &pci_interface,
}, },
{ {
.type = MMU_DRIVER, .type = MMU_DRIVER,
.name = "MMU", .name = "MMU",
.description = "BaS MMU driver", .description = "BaS MMU driver",
.version = 0, .version = 0,
.revision = 1, .revision = 1,
.interface.mmu = &mmu_interface, .interface.mmu = &mmu_interface,
}, },
/* insert new drivers here */ /* insert new drivers here */
{ {
.type = END_OF_DRIVERS .type = END_OF_DRIVERS
} }
}; };
extern void remove_handler(void); /* forward declaration */ extern void remove_handler(void); /* forward declaration */
@@ -201,10 +201,10 @@ extern void remove_handler(void); /* forward declaration */
*/ */
static struct driver_table bas_drivers = static struct driver_table bas_drivers =
{ {
.bas_version = MAJOR_VERSION, .bas_version = MAJOR_VERSION,
.bas_revision = MINOR_VERSION, .bas_revision = MINOR_VERSION,
.remove_handler = remove_handler, .remove_handler = remove_handler,
.interfaces = interfaces .interfaces = interfaces
}; };
void remove_handler(void) void remove_handler(void)
@@ -217,30 +217,34 @@ void remove_handler(void)
void __attribute__((interrupt)) get_bas_drivers(void) void __attribute__((interrupt)) get_bas_drivers(void)
{ {
__asm__ __volatile( __asm__ __volatile(
/* /*
* sp should now point to the next instruction after the trap * sp should now point to the next instruction after the trap
* The trap itself is 2 bytes, the four bytes before that must * The trap itself is 2 bytes, the four bytes before that must
* read '_BAS' or we are not meant by this call * read '_BAS' or we are not meant by this call
*/ */
" move.l d0,-(sp) \n\t" // save register " move.l a0,-(sp) \n\t" // save registers
" move.l 10(sp),d0 \n\t" // get "magic word" " move.l d0,-(sp) \n\t"
" cmp.l #0x5f424153,d0 \n\t" // is it '_BAS'? " move.l 12(sp),a0 \n\t" // get return address
" beq fetch_drivers \n\t" // yes " move.l -6(a0),d0 \n\t" //
/* " cmp.l #0x5f424153,d0 \n\t" // is it '_BAS'?
* This seems indeed a "normal" trap #0. Better pass control to "normal" trap #0 processing " beq fetch_drivers \n\t" // yes
* If trap #0 isn't set to something sensible, we'll probably crash here, but this must be /*
* prevented on the caller side. * This seems indeed a "normal" trap #0. Better pass control to "normal" trap #0 processing
*/ * If trap #0 isn't set to something sensible, we'll probably crash here, but this must be
" move.l (sp)+,d0 \n\t" // restore register * prevented on the caller side.
" move.l 0x80,-(sp) \n\t" // fetch vector */
" rts \n\t" // and jump through it " move.l (sp)+,d0 \n\t" // restore registers
" move.l (sp)+,a0 \n\t"
" move.l 0x80,-(sp) \n\t" // fetch vector
" rts \n\t" // and jump through it
"fetch_drivers: \n\t" "fetch_drivers: \n\t"
" move.l #%[drivers],d0 \n\t" // return driver struct in d0 " move.l #%[drivers],d0 \n\t" // return driver struct in d0
" addq.l #4,sp \n\t" // adjust stack " addq.l #4,sp \n\t" // adjust stack
: /* no output */ " move.l (sp)+,a0 \n\t" // restore register
: [drivers] "o" (bas_drivers) /* input */ : /* no output */
: /* clobber */ : [drivers] "o" (bas_drivers) /* input */
); : /* clobber */
);
} }

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,119 +215,31 @@ 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_tlb;
void video_addr_timeout(void) void video_addr_timeout(void)
{ {
uint32_t addr = 0x0L; dbg("video address timeout\r\n");
uint32_t *src;
uint32_t *dst;
uint32_t asid;
dbg("video address timeout\r\n");
flush_and_invalidate_caches();
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;
/*
* 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 */
}
/* 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();
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;
} }
@@ -336,16 +248,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 +275,27 @@ 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 (FALCON_MFP_IPRA || FALCON_MFP_IPRB)
{ {
video_addr_timeout(); blink_led();
handled = true; }
}
/* return handled;
* 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_IPRA || FALCON_MFP_IPRB)
{
blink_led();
}
return handled;
} }
#if defined(MACHINE_FIREBEE) #if defined(MACHINE_FIREBEE)
@@ -430,112 +322,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

@@ -70,16 +70,16 @@
#elif defined(MACHINE_M54455) #elif defined(MACHINE_M54455)
#include "m54455.h" #include "m54455.h"
#else #else
#error "unknown machine!" #error "unknown machine!"x
#endif /* MACHINE_FIREBEE */ #endif /* MACHINE_FIREBEE */
//#define DBG_MMU #define DBG_MMU
#ifdef DBG_MMU #ifdef DBG_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
#define dbg(format, arg...) do {;} while (0) #define dbg(format, arg...) do {;} while (0)
#endif /* DBG_MMU */ #endif /* DBG_MMU */
#define err(format, arg...) do { xprintf("ERROR (%s()): " format, __FUNCTION__, ##arg); xprintf("system halted\r\n"); } while(0); while(1) #define err(format, arg...) do { xprintf("ERROR (%s()): " format, __FUNCTION__, ##arg); } while(0);
/* /*
* set ASID register * set ASID register
@@ -582,8 +582,6 @@ void mmu_init(void)
flags.locked = true; flags.locked = true;
mmu_map_page(0x00d00000, 0x60d00000, MMU_PAGE_SIZE_1M, SCA_PAGE_ID, &flags); mmu_map_page(0x00d00000, 0x60d00000, MMU_PAGE_SIZE_1M, SCA_PAGE_ID, &flags);
video_tlb = 0x2000; /* set page as video page */
video_sbt = 0x0; /* clear time */
#endif /* MACHINE_FIREBEE */ #endif /* MACHINE_FIREBEE */
/* /*
@@ -658,7 +656,12 @@ uint32_t mmutr_miss(uint32_t mmu_sr, uint32_t fault_address, uint32_t pc,
"PC = 0x%08x\r\n", "PC = 0x%08x\r\n",
fault_address, format_status, mmu_sr, pc); fault_address, format_status, mmu_sr, pc);
dbg("fault = 0x%08x\r\n", fault); dbg("fault = 0x%08x\r\n", fault);
mmu_map_instruction_page(pc, 0);
if (!mmu_map_instruction_page(pc, 0))
{
dbg("bus error\r\n");
return 1; /* bus error */
}
/* due to prefetch, it makes sense to map the next adjacent page also for ITLBs */ /* due to prefetch, it makes sense to map the next adjacent page also for ITLBs */
if (pc + DEFAULT_PAGE_SIZE < TARGET_ADDRESS) if (pc + DEFAULT_PAGE_SIZE < TARGET_ADDRESS)
@@ -666,7 +669,11 @@ uint32_t mmutr_miss(uint32_t mmu_sr, uint32_t fault_address, uint32_t pc,
/* /*
* only do this if the next page is still valid RAM * only do this if the next page is still valid RAM
*/ */
mmu_map_instruction_page(pc + DEFAULT_PAGE_SIZE, 0); if (!mmu_map_instruction_page(pc + DEFAULT_PAGE_SIZE, 0))
{
dbg("bus error\r\n");
return 1; /* bus error */
}
} }
break; break;
@@ -678,7 +685,12 @@ uint32_t mmutr_miss(uint32_t mmu_sr, uint32_t fault_address, uint32_t pc,
"PC = 0x%08x\r\n", "PC = 0x%08x\r\n",
fault_address, format_status, mmu_sr, pc); fault_address, format_status, mmu_sr, pc);
dbg("fault = 0x%08x\r\n", fault); dbg("fault = 0x%08x\r\n", fault);
mmu_map_data_page(fault_address, 0);
if (!mmu_map_data_page(fault_address, 0))
{
dbg("bus error\r\n");
return 1; /* bus error */
}
break; break;
/* else issue an bus error */ /* else issue an bus error */

View File

@@ -68,7 +68,9 @@ void setcookie(uint32_t cookie, uint32_t value)
* work from TSRs) * work from TSRs)
*/ */
if (cookiejar[-1]) if (cookiejar[-1])
{
max_slots = cookiejar[-1]; max_slots = cookiejar[-1];
}
if (max_slots > num_slots) if (max_slots > num_slots)
{ {
@@ -83,7 +85,7 @@ void setcookie(uint32_t cookie, uint32_t value)
printf("cannot set cookie, cookie jar is full!\r\n"); printf("cannot set cookie, cookie jar is full!\r\n");
} }
# define COOKIE_DMAC 0x444D4143L /* FireTOS DMA API */ #define COOKIE_DMAC 0x444d4143L /* FireTOS DMA API */
static char *dt_to_str(enum driver_type dt) static char *dt_to_str(enum driver_type dt)
{ {
@@ -118,7 +120,7 @@ int main(int argc, char *argv[])
if (sig == 0x45544f53) if (sig == 0x45544f53)
{ {
old_vector = Setexc(0x20, my_own_trap0_handler); /* set our own temporarily */ old_vector = Setexc(0x20, my_own_trap0_handler); /* set our own temporarily */
dt = get_bas_drivers(); /* trap #1 */ dt = get_bas_drivers(); /* trap #0 */
(void) Setexc(0x20, old_vector); /* restore original vector */ (void) Setexc(0x20, old_vector); /* restore original vector */
if (dt) if (dt)
@@ -143,17 +145,20 @@ int main(int argc, char *argv[])
ifc++; ifc++;
} }
} }
else
{
printf("driver table not found.\r\n");
}
} }
else else
{ {
printf("not running on EmuTOS,\r\n(signature 0x%04x instead of 0x%04x),\r\n\r\nexiting\r\n", printf("not running on EmuTOS,\r\n(signature 0x%04x instead of 0x%04x\r\n",
(uint32_t) sig, 0x45544f53); (uint32_t) sig, 0x45544f53);
} }
Super(ssp); Super(ssp);
while (Cconis()) Cconin(); /* eat keys */ while (Cconis()) Cconin(); /* eat keys */
// printf("press any key to continue\n\r");
// while (! Cconis());
return 0; return 0;
} }