Create new branch for PCI development
This commit is contained in:
458
pci_BaS_gcc/sys/BaS.c
Normal file
458
pci_BaS_gcc/sys/BaS.c
Normal file
@@ -0,0 +1,458 @@
|
||||
/*
|
||||
* BaS
|
||||
*
|
||||
* This file is part of BaS_gcc.
|
||||
*
|
||||
* BaS_gcc is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* BaS_gcc is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with BaS_gcc. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Copyright 2010 - 2012 F. Aschwanden
|
||||
* Copyright 2011 - 2012 V. Riviere
|
||||
* Copyright 2012 M. Froeschle
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "MCF5475.h"
|
||||
#include "startcf.h"
|
||||
#include "sysinit.h"
|
||||
#include "util.h"
|
||||
#include "cache.h"
|
||||
#include "bas_printf.h"
|
||||
#include "bas_string.h"
|
||||
#include "bas_types.h"
|
||||
#include "sd_card.h"
|
||||
#include "wait.h"
|
||||
|
||||
#include "diskio.h"
|
||||
#include "ff.h"
|
||||
#include "s19reader.h"
|
||||
#include "mmu.h"
|
||||
#include "dma.h"
|
||||
#include "net.h"
|
||||
#include "eth.h"
|
||||
#include "nbuf.h"
|
||||
#include "nif.h"
|
||||
#include "fec.h"
|
||||
#include "bootp.h"
|
||||
#include "interrupts.h"
|
||||
#include "exceptions.h"
|
||||
|
||||
//#define BAS_DEBUG
|
||||
#if defined(BAS_DEBUG)
|
||||
#define dbg(format, arg...) do { xprintf("DEBUG: " format "\r\n", ##arg); } while (0)
|
||||
#else
|
||||
#define dbg(format, arg...) do { ; } while (0)
|
||||
#endif
|
||||
|
||||
/* imported routines */
|
||||
extern int vec_init();
|
||||
|
||||
/* Symbols from the linker script */
|
||||
extern uint8_t _STRAM_END[];
|
||||
#define STRAM_END ((uint32_t)_STRAM_END)
|
||||
extern uint8_t _TOS[];
|
||||
#define TOS ((uint32_t)_TOS) /* final TOS location */
|
||||
extern uint8_t _FASTRAM_END[];
|
||||
#define FASTRAM_END ((uint32_t)_FASTRAM_END)
|
||||
extern uint8_t _EMUTOS[];
|
||||
#define EMUTOS ((uint32_t)_EMUTOS) /* where EmuTOS is stored in flash */
|
||||
extern uint8_t _EMUTOS_SIZE[];
|
||||
#define EMUTOS_SIZE ((uint32_t)_EMUTOS_SIZE) /* size of EmuTOS, in bytes */
|
||||
|
||||
/*
|
||||
* check if it is possible to transfer data to PIC
|
||||
*/
|
||||
static inline bool pic_txready(void)
|
||||
{
|
||||
if (MCF_PSC3_PSCSR & MCF_PSC_PSCSR_TXRDY)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* check if it is possible to receive data from PIC
|
||||
*/
|
||||
static inline bool pic_rxready(void)
|
||||
{
|
||||
if (MCF_PSC3_PSCSR & MCF_PSC_PSCSR_RXRDY)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void write_pic_byte(uint8_t value)
|
||||
{
|
||||
/* 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
|
||||
}
|
||||
|
||||
uint8_t read_pic_byte(void)
|
||||
{
|
||||
/* 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
|
||||
}
|
||||
|
||||
void pic_init(void)
|
||||
{
|
||||
char answer[4] = "OLD";
|
||||
|
||||
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');
|
||||
|
||||
/* 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("%s: PIC initialization failed. Already initialized?\r\n", __FUNCTION__);
|
||||
}
|
||||
else
|
||||
{
|
||||
xprintf("%s\r\n", answer);
|
||||
}
|
||||
}
|
||||
|
||||
void nvram_init(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
xprintf("Restore the NVRAM data: ");
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/* 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");
|
||||
}
|
||||
|
||||
#define KBD_ACIA_CONTROL ((uint8_t *) 0xfffffc00)
|
||||
#define MIDI_ACIA_CONTROL ((uint8_t *) 0xfffffc04)
|
||||
#define MFP_INTR_IN_SERVICE_A ((uint8_t *) 0xfffffa0f)
|
||||
#define MFP_INTR_IN_SERVICE_B ((uint8_t *) 0xfffffa11)
|
||||
|
||||
void acia_init()
|
||||
{
|
||||
xprintf("init ACIA: ");
|
||||
/* init ACIA */
|
||||
* KBD_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();
|
||||
|
||||
* MFP_INTR_IN_SERVICE_A = -1;
|
||||
NOP();
|
||||
|
||||
* MFP_INTR_IN_SERVICE_B = -1;
|
||||
NOP();
|
||||
|
||||
xprintf("finished\r\n");
|
||||
}
|
||||
|
||||
/* ACP interrupt controller */
|
||||
#define FPGA_INTR_CONTRL (volatile uint32_t *) 0xf0010000
|
||||
#define FPGA_INTR_ENABLE (volatile uint8_t *) 0xf0010004
|
||||
#define FPGA_INTR_PENDIN (volatile uint32_t *) 0xf0010008
|
||||
|
||||
void enable_coldfire_interrupts()
|
||||
{
|
||||
xprintf("enable interrupts: ");
|
||||
#if MACHINE_FIREBEE
|
||||
*FPGA_INTR_CONTRL = 0L; /* disable all interrupts */
|
||||
#endif /* MACHINE_FIREBEE */
|
||||
MCF_EPORT_EPPAR = 0xaaa8; /* all interrupts on falling edge */
|
||||
|
||||
#if 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 */
|
||||
|
||||
*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");
|
||||
}
|
||||
|
||||
void disable_coldfire_interrupts()
|
||||
{
|
||||
#ifdef MACHINE_FIREBEE
|
||||
*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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
NIF nif1;
|
||||
#ifdef MACHINE_M5484LITE
|
||||
NIF nif2;
|
||||
#endif
|
||||
static IP_INFO ip_info;
|
||||
static ARP_INFO arp_info;
|
||||
|
||||
|
||||
void network_init(void)
|
||||
{
|
||||
uint8_t mac[6] = {0x00, 0xcf, 0x54, 0x12, 0x34, 0x56};
|
||||
uint8_t bc[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; /* this is our broadcast MAC address */
|
||||
IP_ADDR myip = {192, 168, 1, 100};
|
||||
IP_ADDR gateway = {192, 168, 1, 1};
|
||||
IP_ADDR netmask = {255, 255, 255, 0};
|
||||
int vector;
|
||||
int (*handler)(void *, void *);
|
||||
|
||||
handler = fec0_interrupt_handler;
|
||||
vector = 103;
|
||||
|
||||
isr_init(); /* need to call that explicitely, otherwise isr table might be full */
|
||||
|
||||
if (!isr_register_handler(ISR_DBUG_ISR, vector, handler, NULL, (void *) &nif1))
|
||||
{
|
||||
dbg("%s: unable to register handler for vector %d\r\n", __FUNCTION__, vector);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Register the DMA interrupt handler
|
||||
*/
|
||||
handler = dma_interrupt_handler;
|
||||
vector = 112;
|
||||
|
||||
if (!isr_register_handler(ISR_DBUG_ISR, vector, handler, NULL,NULL))
|
||||
{
|
||||
dbg("%s: Error: Unable to register handler for vector %s\r\n", __FUNCTION__, vector);
|
||||
return;
|
||||
}
|
||||
|
||||
nif_init(&nif1);
|
||||
nif1.mtu = ETH_MTU;
|
||||
nif1.send = fec0_send;
|
||||
fec_eth_setup(0, FEC_MODE_MII, FEC_MII_100BASE_TX, FEC_MII_FULL_DUPLEX, mac);
|
||||
// fec_eth_setup(1, FEC_MODE_MII, FEC_MII_100BASE_TX, FEC_MII_FULL_DUPLEX, mac);
|
||||
memcpy(nif1.hwa, mac, 6);
|
||||
memcpy(nif1.broadcast, bc, 6);
|
||||
|
||||
dbg("%s: ethernet address is %02X:%02X:%02X:%02X:%02X:%02X\r\n", __FUNCTION__,
|
||||
nif1.hwa[0], nif1.hwa[1], nif1.hwa[2],
|
||||
nif1.hwa[3], nif1.hwa[4], nif1.hwa[5]);
|
||||
|
||||
timer_init(TIMER_NETWORK, TMR_INTC_LVL, TMR_INTC_PRI);
|
||||
|
||||
arp_init(&arp_info);
|
||||
nif_bind_protocol(&nif1, ETH_FRM_ARP, arp_handler, (void *) &arp_info);
|
||||
|
||||
ip_init(&ip_info, myip, gateway, netmask);
|
||||
nif_bind_protocol(&nif1, ETH_FRM_IP, ip_handler, (void *) &ip_info);
|
||||
|
||||
udp_init();
|
||||
|
||||
dma_irq_enable(6, 6);
|
||||
|
||||
set_ipl(0);
|
||||
|
||||
bootp_request(&nif1, 0);
|
||||
|
||||
fec_eth_stop(0);
|
||||
}
|
||||
|
||||
void BaS(void)
|
||||
{
|
||||
uint8_t *src;
|
||||
uint8_t *dst = (uint8_t *) TOS;
|
||||
|
||||
#if MACHINE_FIREBEE /* LITE board has no pic and (currently) no nvram */
|
||||
pic_init();
|
||||
nvram_init();
|
||||
#endif /* MACHINE_FIREBEE */
|
||||
|
||||
xprintf("copy EmuTOS: ");
|
||||
|
||||
/* 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 exception vector table: ");
|
||||
vec_init();
|
||||
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");
|
||||
|
||||
#ifdef MACHINE_FIREBEE
|
||||
xprintf("IDE reset: ");
|
||||
/* IDE reset */
|
||||
* (volatile uint8_t *) (0xffff8802 - 2) = 14;
|
||||
* (volatile uint8_t *) (0xffff8802 - 0) = 0x80;
|
||||
wait(1);
|
||||
|
||||
* (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 */
|
||||
#endif /* _NOT_USED_ */
|
||||
|
||||
/* fifo on, refresh on, ddrcs and cke on, video dac on */
|
||||
* (volatile uint32_t *) (0xf0000410 - 0x20) = 0x01070002;
|
||||
|
||||
xprintf("finished\r\n");
|
||||
|
||||
enable_coldfire_interrupts();
|
||||
|
||||
#ifdef _NOT_USED_
|
||||
screen_init();
|
||||
|
||||
/* experimental */
|
||||
{
|
||||
int i;
|
||||
uint32_t *scradr = 0xd00000;
|
||||
|
||||
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 = 0x0;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* _NOT_USED_ */
|
||||
|
||||
#endif /* MACHINE_FIREBEE */
|
||||
|
||||
sd_card_init();
|
||||
|
||||
/*
|
||||
* memory setup
|
||||
*/
|
||||
memset((void *) 0x400, 0, 0x400);
|
||||
|
||||
#ifdef MACHINE_FIREBEE
|
||||
/* set Falcon bus control register */
|
||||
/* sets bit 3 and 6. Both are undefined on an original Falcon? */
|
||||
|
||||
* (volatile uint8_t *) 0xffff8007 = 0x48;
|
||||
#endif /* MACHINE_FIREBEE */
|
||||
|
||||
/* 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 */
|
||||
|
||||
/* TT-RAM */
|
||||
|
||||
* (uint32_t *) 0x5a4 = FASTRAM_END; /* ramtop TOS system variable */
|
||||
* (uint32_t *) 0x5a8 = 0x1357bd13; /* ramvalid TOS system variable */
|
||||
|
||||
#ifdef MACHINE_FIREBEE /* m5484lite has no ACIA and no dip switch... */
|
||||
acia_init();
|
||||
#endif /* MACHINE_FIREBEE */
|
||||
|
||||
srec_execute("BASFLASH.S19");
|
||||
|
||||
/* Jump into the OS */
|
||||
typedef void void_func(void);
|
||||
typedef struct {
|
||||
void *initial_sp;
|
||||
void_func *initial_pc;
|
||||
} ROM_HEADER;
|
||||
|
||||
xprintf("BaS initialization finished, enable interrupts\r\n");
|
||||
enable_coldfire_interrupts();
|
||||
|
||||
//set_ipl(0);
|
||||
network_init();
|
||||
|
||||
xprintf("call EmuTOS\r\n");
|
||||
ROM_HEADER* os_header = (ROM_HEADER*)TOS;
|
||||
os_header->initial_pc();
|
||||
}
|
||||
145
pci_BaS_gcc/sys/cache.c
Normal file
145
pci_BaS_gcc/sys/cache.c
Normal file
@@ -0,0 +1,145 @@
|
||||
/*
|
||||
* cache handling
|
||||
*
|
||||
* This file is part of BaS_gcc.
|
||||
*
|
||||
* BaS_gcc is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* BaS_gcc is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with BaS_gcc. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Copyright 2010 - 2012 F. Aschwanden
|
||||
* Copyright 2011 - 2012 V. Riviere
|
||||
* Copyright 2012 M. Froeschle
|
||||
*
|
||||
*/
|
||||
|
||||
#include "cache.h"
|
||||
|
||||
void cacr_set(uint32_t value)
|
||||
{
|
||||
extern uint32_t rt_cacr;
|
||||
|
||||
rt_cacr = value;
|
||||
__asm__ __volatile__("movec %0, cacr\n\t"
|
||||
: /* output */
|
||||
: "r" (rt_cacr)
|
||||
: /* clobbers */);
|
||||
}
|
||||
|
||||
uint32_t cacr_get(void)
|
||||
{
|
||||
extern uint32_t rt_cacr;
|
||||
|
||||
return rt_cacr;
|
||||
}
|
||||
|
||||
void flush_and_invalidate_caches(void)
|
||||
{
|
||||
__asm__ (
|
||||
" clr.l d0\n\t"
|
||||
" clr.l d1\n\t"
|
||||
" move.l d0,a0\n\t"
|
||||
"cfa_setloop:\n\t"
|
||||
" cpushl bc,(a0) | flush\n\t"
|
||||
" lea 0x10(a0),a0 | index+1\n\t"
|
||||
" addq.l #1,d1 | index+1\n\t"
|
||||
" cmpi.w #512,d1 | all sets?\n\t"
|
||||
" bne.s cfa_setloop | no->\n\t"
|
||||
" clr.l d1\n\t"
|
||||
" addq.l #1,d0\n\t"
|
||||
" move.l d0,a0\n\t"
|
||||
" cmpi.w #4,d0 | all ways?\n\t"
|
||||
" bne.s cfa_setloop | no->\n\t"
|
||||
/* input */ :
|
||||
/* output */ :
|
||||
/* clobber */ : "d0", "d1", "a0"
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
* flush and invalidate a specific memory region from the instruction cache
|
||||
*/
|
||||
void flush_icache_range(void *address, size_t size)
|
||||
{
|
||||
uint32_t set;
|
||||
uint32_t start_set;
|
||||
uint32_t end_set;
|
||||
void *endaddr = address + size;
|
||||
|
||||
start_set = (uint32_t) address & _ICACHE_SET_MASK;
|
||||
end_set = (uint32_t) endaddr & _ICACHE_SET_MASK;
|
||||
|
||||
if (start_set > end_set) {
|
||||
/* from the begining to the lowest address */
|
||||
for (set = 0; set <= end_set; set += (0x10 - 3)) {
|
||||
asm volatile("cpushl ic,(%0)\n\t"
|
||||
"addq.l #1,%0\n\t"
|
||||
"cpushl ic,(%0)\n\t"
|
||||
"addq.l #1,%0\n\t"
|
||||
"cpushl ic,(%0)\n\t"
|
||||
"addq.l #1,%0\n\t"
|
||||
"cpushl ic,(%0)" : "=a" (set) : "a" (set));
|
||||
}
|
||||
/* next loop will finish the cache ie pass the hole */
|
||||
end_set = LAST_ICACHE_ADDR;
|
||||
}
|
||||
for (set = start_set; set <= end_set; set += (0x10 - 3)) {
|
||||
asm volatile("cpushl ic,(%0)\n\t"
|
||||
"addq.l #1,%0\n\t"
|
||||
"cpushl ic,(%0)\n\t"
|
||||
"addq%.l #1,%0\n\t"
|
||||
"cpushl ic,(%0)\n\t"
|
||||
"addq.l #1,%0\n\t"
|
||||
"cpushl ic,(%0)" : "=a" (set) : "a" (set));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* flush and invalidate a specific region from the data cache
|
||||
*/
|
||||
void flush_dcache_range(void *address, size_t size)
|
||||
{
|
||||
unsigned long set;
|
||||
unsigned long start_set;
|
||||
unsigned long end_set;
|
||||
void *endaddr;
|
||||
|
||||
endaddr = address + size;
|
||||
start_set = (uint32_t) address & _DCACHE_SET_MASK;
|
||||
end_set = (uint32_t) endaddr & _DCACHE_SET_MASK;
|
||||
|
||||
if (start_set > end_set) {
|
||||
/* from the begining to the lowest address */
|
||||
for (set = 0; set <= end_set; set += (0x10 - 3)) {
|
||||
asm volatile("cpushl dc,(%0)\n\t"
|
||||
"addq.l #1,%0\n\t"
|
||||
"cpushl dc,(%0)\n\t"
|
||||
"addq.l #1,%0\n\t"
|
||||
"cpushl dc,(%0)\n\t"
|
||||
"addq.l #1,%0\n\t"
|
||||
"cpushl dc,(%0)" : "=a" (set) : "a" (set));
|
||||
}
|
||||
/* next loop will finish the cache ie pass the hole */
|
||||
end_set = LAST_DCACHE_ADDR;
|
||||
}
|
||||
for (set = start_set; set <= end_set; set += (0x10 - 3)) {
|
||||
asm volatile("cpushl dc,(%0)\n\t"
|
||||
"addq.l #1,%0\n\t"
|
||||
"cpushl dc,(%0)\n\t"
|
||||
"addq%.l #1,%0\n\t"
|
||||
"cpushl dc,(%0)\n\t"
|
||||
"addq.l #1,%0\n\t"
|
||||
"cpushl dc,(%0)" : "=a" (set) : "a" (set));
|
||||
}
|
||||
}
|
||||
338
pci_BaS_gcc/sys/driver_mem.c
Normal file
338
pci_BaS_gcc/sys/driver_mem.c
Normal file
@@ -0,0 +1,338 @@
|
||||
/*
|
||||
* driver_mem.c
|
||||
*
|
||||
* based from Emutos / BDOS
|
||||
*
|
||||
* Copyright (c) 2001 Lineo, Inc.
|
||||
*
|
||||
* Authors: Karl T. Braun, Martin Doering, Laurent Vogel
|
||||
*
|
||||
* This file is distributed under the GPL, version 2 or at your
|
||||
* option any later version.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "bas_string.h"
|
||||
#include "bas_printf.h"
|
||||
#include "usb.h"
|
||||
#include "exceptions.h" /* set_ipl() */
|
||||
|
||||
#if MACHINE_FIREBEE
|
||||
#include "firebee.h"
|
||||
#elif MACHINE_M5484LITE
|
||||
#include "m5484l.h"
|
||||
#endif
|
||||
|
||||
//#define DBG_DM
|
||||
|
||||
#ifdef DBG_DM
|
||||
#define dbg(fmt, args...) xprintf(fmt, ##args)
|
||||
#else
|
||||
#define dbg(fmt, args...)
|
||||
#endif
|
||||
|
||||
extern long offscren_reserved(void);
|
||||
|
||||
extern uint8_t driver_mem_buffer[DRIVER_MEM_BUFFER_SIZE]; /* defined in linker control file */
|
||||
|
||||
/* MD - Memory Descriptor */
|
||||
|
||||
#define MD struct _md_
|
||||
|
||||
MD
|
||||
{
|
||||
MD *m_link;
|
||||
long m_start;
|
||||
long m_length;
|
||||
void *m_own;
|
||||
};
|
||||
|
||||
/* MPB - Memory Partition Block */
|
||||
|
||||
#define MPB struct _mpb
|
||||
|
||||
MPB
|
||||
{
|
||||
MD *mp_mfl;
|
||||
MD *mp_mal;
|
||||
MD *mp_rover;
|
||||
};
|
||||
|
||||
#define MAXMD 256
|
||||
|
||||
static MD tab_md[MAXMD];
|
||||
static MPB pmd;
|
||||
|
||||
static void *xmgetblk(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAXMD; i++)
|
||||
{
|
||||
if (tab_md[i].m_own == NULL)
|
||||
{
|
||||
tab_md[i].m_own = (void*)1L;
|
||||
return(&tab_md[i]);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void xmfreblk(void *m)
|
||||
{
|
||||
int i = (int)(((long) m - (long) tab_md) / sizeof(MD));
|
||||
if ((i > 0) && (i < MAXMD))
|
||||
{
|
||||
tab_md[i].m_own = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static MD *ffit(long amount, MPB *mp)
|
||||
{
|
||||
MD *p, *q, *p1; /* free list is composed of MD's */
|
||||
int maxflg;
|
||||
long maxval;
|
||||
|
||||
if (amount != -1)
|
||||
{
|
||||
amount += 15; /* 16 bytes alignment */
|
||||
amount &= 0xFFFFFFF0;
|
||||
}
|
||||
|
||||
if ((q = mp->mp_rover) == 0) /* get rotating pointer */
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
maxval = 0;
|
||||
maxflg = ((amount == -1) ? true : false) ;
|
||||
p = q->m_link; /* start with next MD */
|
||||
do /* search the list for an MD with enough space */
|
||||
{
|
||||
if (p == 0)
|
||||
{
|
||||
/* at end of list, wrap back to start */
|
||||
q = (MD *) &mp->mp_mfl; /* q => mfl field */
|
||||
p = q->m_link; /* p => 1st MD */
|
||||
}
|
||||
if ((!maxflg) && (p->m_length >= amount))
|
||||
{
|
||||
/* big enough */
|
||||
if (p->m_length == amount)
|
||||
{
|
||||
q->m_link = p->m_link; /* take the whole thing */
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* break it up - 1st allocate a new
|
||||
* MD to describe the remainder
|
||||
*/
|
||||
p1 = xmgetblk();
|
||||
if (p1 == NULL)
|
||||
{
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/* init new MD */
|
||||
p1->m_length = p->m_length - amount;
|
||||
p1->m_start = p->m_start + amount;
|
||||
p1->m_link = p->m_link;
|
||||
p->m_length = amount; /* adjust allocated block */
|
||||
q->m_link = p1;
|
||||
}
|
||||
/* link allocate block into allocated list,
|
||||
mark owner of block, & adjust rover */
|
||||
p->m_link = mp->mp_mal;
|
||||
mp->mp_mal = p;
|
||||
mp->mp_rover = (q == (MD *) &mp->mp_mfl ? q->m_link : q);
|
||||
return(p); /* got some */
|
||||
}
|
||||
else if (p->m_length > maxval)
|
||||
maxval = p->m_length;
|
||||
p = ( q=p )->m_link;
|
||||
} while(q != mp->mp_rover);
|
||||
|
||||
/*
|
||||
* return either the max, or 0 (error)
|
||||
*/
|
||||
if (maxflg)
|
||||
{
|
||||
maxval -= 15; /* 16 bytes alignment */
|
||||
if (maxval < 0)
|
||||
{
|
||||
maxval = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
maxval &= 0xFFFFFFF0;
|
||||
}
|
||||
}
|
||||
return(maxflg ? (MD *) maxval : 0);
|
||||
}
|
||||
|
||||
static void freeit(MD *m, MPB *mp)
|
||||
{
|
||||
MD *p, *q;
|
||||
|
||||
q = 0;
|
||||
for (p = mp->mp_mfl; p ; p = (q = p) -> m_link)
|
||||
{
|
||||
if (m->m_start <= p->m_start)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
m->m_link = p;
|
||||
|
||||
if (q)
|
||||
{
|
||||
q->m_link = m;
|
||||
}
|
||||
else
|
||||
{
|
||||
mp->mp_mfl = m;
|
||||
}
|
||||
|
||||
if (!mp->mp_rover)
|
||||
{
|
||||
mp->mp_rover = m;
|
||||
}
|
||||
|
||||
if (p)
|
||||
{
|
||||
if (m->m_start + m->m_length == p->m_start)
|
||||
{
|
||||
/* join to higher neighbor */
|
||||
m->m_length += p->m_length;
|
||||
m->m_link = p->m_link;
|
||||
if (p == mp->mp_rover)
|
||||
{
|
||||
mp->mp_rover = m;
|
||||
}
|
||||
xmfreblk(p);
|
||||
}
|
||||
}
|
||||
if (q)
|
||||
{
|
||||
if (q->m_start + q->m_length == m->m_start)
|
||||
{
|
||||
/* join to lower neighbor */
|
||||
q->m_length += m->m_length;
|
||||
q->m_link = m->m_link;
|
||||
if (m == mp->mp_rover)
|
||||
{
|
||||
mp->mp_rover = q;
|
||||
}
|
||||
xmfreblk(m);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int32_t driver_mem_free(void *addr)
|
||||
{
|
||||
int level;
|
||||
MD *p, **q;
|
||||
MPB *mpb;
|
||||
mpb = &pmd;
|
||||
level = set_ipl(7);
|
||||
|
||||
for(p = *(q = &mpb->mp_mal); p; p = *(q = &p->m_link))
|
||||
{
|
||||
if ((long) addr == p->m_start)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!p)
|
||||
{
|
||||
set_ipl(level);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
*q = p->m_link;
|
||||
freeit(p, mpb);
|
||||
set_ipl(level);
|
||||
|
||||
dbg("%s: driver_mem_free(0x%08X)\r\n", __FUNCTION__, addr);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
void *driver_mem_alloc(uint32_t amount)
|
||||
{
|
||||
void *ret = NULL;
|
||||
int level;
|
||||
MD *m;
|
||||
|
||||
if (amount == -1L)
|
||||
{
|
||||
return((void *)ffit(-1L, &pmd));
|
||||
}
|
||||
|
||||
if (amount <= 0 )
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
|
||||
if ((amount & 1))
|
||||
{
|
||||
amount++;
|
||||
}
|
||||
|
||||
level = set_ipl(7);
|
||||
m = ffit(amount, &pmd);
|
||||
|
||||
if (m != NULL)
|
||||
{
|
||||
ret = (void *)m->m_start;
|
||||
}
|
||||
set_ipl(level);
|
||||
dbg("%s: driver_mem_alloc(%d) = 0x%08X\r\n", __FUNCTION__, amount, ret);
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
static int use_count = 0;
|
||||
|
||||
int driver_mem_init(void)
|
||||
{
|
||||
if (use_count == 0)
|
||||
{
|
||||
dbg("%s: initialise driver_mem_buffer[] at %p, size 0x%x\r\n", __FUNCTION__, driver_mem_buffer, DRIVER_MEM_BUFFER_SIZE);
|
||||
memset(driver_mem_buffer, 0, DRIVER_MEM_BUFFER_SIZE);
|
||||
|
||||
pmd.mp_mfl = pmd.mp_rover = &tab_md[0];
|
||||
tab_md[0].m_link = (MD *) NULL;
|
||||
tab_md[0].m_start = ((long) driver_mem_buffer + 15) & ~15;
|
||||
tab_md[0].m_length = DRIVER_MEM_BUFFER_SIZE;
|
||||
tab_md[0].m_own = (void *) 1L;
|
||||
pmd.mp_mal = (MD *) NULL;
|
||||
memset(driver_mem_buffer, 0, tab_md[0].m_length);
|
||||
|
||||
dbg("%s: uncached driver memory buffer at 0x%08X size %d\r\n", __FUNCTION__, tab_md[0].m_start, tab_md[0].m_length);
|
||||
}
|
||||
use_count++;
|
||||
dbg("%s: driver_mem now has a use count of %d\r\n", __FUNCTION__, use_count);
|
||||
return(0);
|
||||
}
|
||||
|
||||
void driver_mem_release(void)
|
||||
{
|
||||
if (use_count-- == 0)
|
||||
{
|
||||
#ifndef CONFIG_USB_MEM_NO_CACHE
|
||||
#ifdef USE_RADEON_MEMORY
|
||||
if (driver_mem_buffer == (void *) offscren_reserved())
|
||||
return;
|
||||
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
dbg("%s: driver_mem use count now %d\r\n", __FUNCTION__, use_count);
|
||||
}
|
||||
|
||||
|
||||
|
||||
1010
pci_BaS_gcc/sys/exceptions.S
Normal file
1010
pci_BaS_gcc/sys/exceptions.S
Normal file
File diff suppressed because it is too large
Load Diff
198
pci_BaS_gcc/sys/fault_vectors.c
Normal file
198
pci_BaS_gcc/sys/fault_vectors.c
Normal file
@@ -0,0 +1,198 @@
|
||||
/*
|
||||
* This file is part of BaS_gcc.
|
||||
*
|
||||
* BaS_gcc is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* BaS_gcc is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with BaS_gcc. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* provide an early exception vector branch table to catch exceptions _before_ VBR has been setup eventually
|
||||
* (to RAMBAR0, in exceptions.S)
|
||||
*/
|
||||
|
||||
#include "MCF5475.h"
|
||||
#include "bas_types.h"
|
||||
#include "bas_printf.h"
|
||||
|
||||
typedef void (*exception_handler)(void);
|
||||
extern exception_handler SDRAM_VECTOR_TABLE[];
|
||||
|
||||
/*
|
||||
* decipher Coldfire exception stack frame and print it out in cleartext
|
||||
*/
|
||||
void fault_handler(uint32_t pc, uint32_t format_status)
|
||||
{
|
||||
int format;
|
||||
int fault_status;
|
||||
int vector;
|
||||
int sr;
|
||||
|
||||
xprintf("\007\007exception! Processor halted.\r\n");
|
||||
xprintf("format_status: %lx\r\n", format_status);
|
||||
xprintf("pc: %lx\r\n", pc);
|
||||
|
||||
/*
|
||||
* extract info from format-/status word
|
||||
*/
|
||||
format = (format_status & 0b11110000000000000000000000000000) >> 28;
|
||||
fault_status = ((format_status & 0b00001100000000000000000000000000) >> 26) |
|
||||
((format_status & 0b00000000000000110000000000000000) >> 16);
|
||||
vector = (format_status & 0b00000011111111000000000000000000) >> 18;
|
||||
sr = (format_status & 0b00000000000000001111111111111111);
|
||||
|
||||
xprintf("format: %x\r\n", format);
|
||||
xprintf("fault_status: %x (", fault_status);
|
||||
switch (fault_status)
|
||||
{
|
||||
case 0:
|
||||
xprintf("not an access or address error nor an interrupted debug service routine");
|
||||
break;
|
||||
case 1:
|
||||
case 3:
|
||||
case 11:
|
||||
xprintf("reserved");
|
||||
break;
|
||||
case 2:
|
||||
xprintf("interrupt during a debug service routine for faults other than access errors");
|
||||
break;
|
||||
case 4:
|
||||
xprintf("error (for example, protection fault) on instruction fetch");
|
||||
break;
|
||||
case 5:
|
||||
xprintf("TLB miss on opword or instruction fetch");
|
||||
break;
|
||||
case 6:
|
||||
xprintf("TLB miss on extension word of instruction fetch");
|
||||
break;
|
||||
case 7:
|
||||
xprintf("IFP access error while executing in emulator mode");
|
||||
break;
|
||||
case 8:
|
||||
xprintf("error on data write");
|
||||
break;
|
||||
case 9:
|
||||
xprintf("error on attempted write to write-protected space");
|
||||
break;
|
||||
case 10:
|
||||
xprintf("TLB miss on data write");
|
||||
break;
|
||||
case 12:
|
||||
xprintf("error on data read");
|
||||
break;
|
||||
case 13:
|
||||
xprintf("attempted read, read-modify-write of protected space");
|
||||
break;
|
||||
case 14:
|
||||
xprintf("TLB miss on data read or read-modify-write");
|
||||
break;
|
||||
case 15:
|
||||
xprintf("OEP access error while executing in emulator mode");
|
||||
}
|
||||
xprintf(")\r\n");
|
||||
|
||||
xprintf("vector = %02x (", vector);
|
||||
switch (vector)
|
||||
{
|
||||
case 2:
|
||||
xprintf("access error");
|
||||
break;
|
||||
case 3:
|
||||
xprintf("address error");
|
||||
break;
|
||||
case 4:
|
||||
xprintf("illegal instruction");
|
||||
break;
|
||||
case 5:
|
||||
xprintf("divide by zero");
|
||||
break;
|
||||
case 8:
|
||||
xprintf("privilege violation");
|
||||
break;
|
||||
case 9:
|
||||
xprintf("trace");
|
||||
break;
|
||||
case 10:
|
||||
xprintf("unimplemented line-a opcode");
|
||||
break;
|
||||
case 11:
|
||||
xprintf("unimplemented line-f opcode");
|
||||
break;
|
||||
case 12:
|
||||
xprintf("non-PC breakpoint debug interrupt");
|
||||
break;
|
||||
case 13:
|
||||
xprintf("PC breakpoint debug interrupt");
|
||||
break;
|
||||
case 14:
|
||||
xprintf("format error");
|
||||
break;
|
||||
case 24:
|
||||
xprintf("spurious interrupt");
|
||||
break;
|
||||
default:
|
||||
if ( ((fault_status >= 6) && (fault_status <= 7)) ||
|
||||
((fault_status >= 16) && (fault_status <= 23)))
|
||||
{
|
||||
xprintf("reserved");
|
||||
}
|
||||
else if ((fault_status >= 25) && (fault_status <= 31))
|
||||
{
|
||||
xprintf("level %d autovectored interrupt", fault_status - 24);
|
||||
}
|
||||
else if ((fault_status >= 32) && (fault_status <= 47))
|
||||
{
|
||||
xprintf("trap #%d", fault_status - 32);
|
||||
}
|
||||
else
|
||||
{
|
||||
xprintf("unknown fault status");
|
||||
}
|
||||
}
|
||||
xprintf(")\r\n");
|
||||
xprintf("sr=%4x\r\n", sr);
|
||||
}
|
||||
|
||||
void __attribute__((interrupt)) handler(void)
|
||||
{
|
||||
/*
|
||||
* Prepare exception stack contents so it can be handled by a C routine.
|
||||
*
|
||||
* For standard routines, we'd have to save registers here.
|
||||
* Since we do not intend to return anyway, we just ignore that requirement.
|
||||
*/
|
||||
__asm__ __volatile__("move.l (sp),-(sp)\n\t"\
|
||||
"move.l 8(sp),-(sp)\n\t"\
|
||||
"bsr _fault_handler\n\t"\
|
||||
"halt\n\t"\
|
||||
: : : "memory");
|
||||
}
|
||||
|
||||
void setup_vectors(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
xprintf("\r\ninstall early exception vector table:");
|
||||
|
||||
for (i = 8; i < 256; i++)
|
||||
{
|
||||
SDRAM_VECTOR_TABLE[i] = &handler;
|
||||
}
|
||||
|
||||
/*
|
||||
* make sure VBR points to our table
|
||||
*/
|
||||
__asm__ __volatile__("clr.l d0\n\t"\
|
||||
"movec.l d0,VBR\n\t"\
|
||||
"nop\n\t"\
|
||||
"move.l d0,_rt_vbr" ::: "d0", "memory");
|
||||
|
||||
xprintf("finished.\r\n");
|
||||
}
|
||||
169
pci_BaS_gcc/sys/init_fpga.c
Normal file
169
pci_BaS_gcc/sys/init_fpga.c
Normal file
@@ -0,0 +1,169 @@
|
||||
/*
|
||||
* init_fpga.c
|
||||
*
|
||||
* This file is part of BaS_gcc.
|
||||
*
|
||||
* BaS_gcc is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* BaS_gcc is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with BaS_gcc. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Copyright 2010 - 2012 F. Aschwanden
|
||||
* Copyright 2011 - 2012 V. Riviere
|
||||
* Copyright 2012 M. Froeschle
|
||||
*
|
||||
*/
|
||||
|
||||
#include "MCF5475.h"
|
||||
#include "sysinit.h"
|
||||
#include "bas_printf.h"
|
||||
#include "wait.h"
|
||||
|
||||
#define FPGA_STATUS (1 << 0)
|
||||
#define FPGA_CLOCK (1 << 1)
|
||||
#define FPGA_CONFIG (1 << 2)
|
||||
#define FPGA_DATA0 (1 << 3)
|
||||
#define FPGA_CONF_DONE (1 << 5)
|
||||
|
||||
extern uint8_t _FPGA_FLASH_DATA[];
|
||||
#define FPGA_FLASH_DATA &_FPGA_FLASH_DATA[0]
|
||||
extern uint8_t _FPGA_FLASH_DATA_SIZE[];
|
||||
#define FPGA_FLASH_DATA_SIZE ((uint32_t) &_FPGA_FLASH_DATA_SIZE[0])
|
||||
|
||||
|
||||
#ifdef _NOT_USED_
|
||||
void test_longword(void)
|
||||
{
|
||||
uint32_t *fpga_data = (uint32_t *) FPGA_FLASH_DATA;
|
||||
const uint32_t *fpga_flash_data_end = (uint32_t *) FPGA_FLASH_DATA + FPGA_FLASH_DATA_SIZE;
|
||||
do
|
||||
{
|
||||
uint32_t value = *fpga_data++;
|
||||
xprintf("LONGWORDS: addr=%p, value=%08x\r", fpga_data, value);
|
||||
} while (fpga_data < fpga_flash_data_end);
|
||||
xprintf("finished. \r\n");
|
||||
}
|
||||
|
||||
void test_word(void)
|
||||
{
|
||||
uint16_t *fpga_data = (uint16_t *) FPGA_FLASH_DATA;
|
||||
const uint16_t *fpga_flash_data_end = (uint16_t *) FPGA_FLASH_DATA + FPGA_FLASH_DATA_SIZE;
|
||||
|
||||
do
|
||||
{
|
||||
uint16_t value = *fpga_data++;
|
||||
xprintf("WORDS: addr=%p, value=%04x\r", fpga_data, value);
|
||||
} while (fpga_data < fpga_flash_data_end);
|
||||
xprintf("finished. \r\n");
|
||||
}
|
||||
|
||||
void test_byte(void)
|
||||
{
|
||||
uint8_t *fpga_data = (uint8_t *) FPGA_FLASH_DATA;
|
||||
const uint8_t *fpga_flash_data_end = (uint8_t *) FPGA_FLASH_DATA + FPGA_FLASH_DATA_SIZE;
|
||||
|
||||
do
|
||||
{
|
||||
uint8_t value = *fpga_data++;
|
||||
xprintf("LONGWORDS: addr=%p, value=%08x\r", fpga_data, value);
|
||||
} while (fpga_data < fpga_flash_data_end);
|
||||
xprintf("finished. \r\n");
|
||||
}
|
||||
#endif /* _NOT_USED_ */
|
||||
|
||||
/*
|
||||
* load FPGA
|
||||
*/
|
||||
void init_fpga(void)
|
||||
{
|
||||
uint8_t *fpga_data;
|
||||
volatile int32_t time, start, end;
|
||||
int i;
|
||||
|
||||
xprintf("FPGA load config... ");
|
||||
start = MCF_SLT0_SCNT;
|
||||
|
||||
MCF_GPIO_PODR_FEC1L &= ~FPGA_CLOCK; /* FPGA clock => low */
|
||||
|
||||
/* pulling FPGA_CONFIG to low resets the FPGA */
|
||||
MCF_GPIO_PODR_FEC1L &= ~FPGA_CONFIG; /* FPGA config => low */
|
||||
wait(10); /* give it some time to do its reset stuff */
|
||||
|
||||
while ((MCF_GPIO_PPDSDR_FEC1L & FPGA_STATUS) && (MCF_GPIO_PPDSDR_FEC1L & FPGA_CONF_DONE));
|
||||
|
||||
MCF_GPIO_PODR_FEC1L |= FPGA_CONFIG; /* pull FPGA_CONFIG high to start config cycle */
|
||||
while (!(MCF_GPIO_PPDSDR_FEC1L & FPGA_STATUS)); /* wait until status becomes high */
|
||||
|
||||
/*
|
||||
* excerpt from an Altera configuration manual:
|
||||
*
|
||||
* The low-to-high transition of nCONFIG on the FPGA begins the configuration cycle. The
|
||||
* configuration cycle consists of 3 stages<65>reset, configuration, and initialization.
|
||||
* While nCONFIG is low, the device is in reset. When the device comes out of reset,
|
||||
* nCONFIG must be at a logic high level in order for the device to release the open-drain
|
||||
* nSTATUS pin. After nSTATUS is released, it is pulled high by a pull-up resistor and the FPGA
|
||||
* is ready to receive configuration data. Before and during configuration, all user I/O pins
|
||||
* are tri-stated. Stratix series, Arria series, and Cyclone series have weak pull-up resistors
|
||||
* on the I/O pins which are on, before and during configuration.
|
||||
*
|
||||
* To begin configuration, nCONFIG and nSTATUS must be at a logic high level. You can delay
|
||||
* configuration by holding the nCONFIG low. The device receives configuration data on its
|
||||
* DATA0 pins. Configuration data is latched into the FPGA on the rising edge of DCLK. After
|
||||
* the FPGA has received all configuration data successfully, it releases the CONF_DONE pin,
|
||||
* which is pulled high by a pull-up resistor. A low to high transition on CONF_DONE indicates
|
||||
* configuration is complete and initialization of the device can begin.
|
||||
*/
|
||||
|
||||
const uint8_t *fpga_flash_data_end = FPGA_FLASH_DATA + FPGA_FLASH_DATA_SIZE;
|
||||
|
||||
fpga_data = (uint8_t *) FPGA_FLASH_DATA;
|
||||
do
|
||||
{
|
||||
uint8_t value = *fpga_data++;
|
||||
for (i = 0; i < 8; i++, value >>= 1)
|
||||
{
|
||||
|
||||
if (value & 1)
|
||||
{
|
||||
/* bit set -> toggle DATA0 to high */
|
||||
MCF_GPIO_PODR_FEC1L |= FPGA_DATA0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* bit is cleared -> toggle DATA0 to low */
|
||||
MCF_GPIO_PODR_FEC1L &= ~FPGA_DATA0;
|
||||
}
|
||||
/* toggle DCLK -> FPGA reads the bit */
|
||||
MCF_GPIO_PODR_FEC1L |= FPGA_CLOCK;
|
||||
MCF_GPIO_PODR_FEC1L &= ~FPGA_CLOCK;
|
||||
}
|
||||
} while ((!(MCF_GPIO_PPDSDR_FEC1L & FPGA_CONF_DONE)) && (fpga_data < fpga_flash_data_end));
|
||||
|
||||
if (fpga_data < fpga_flash_data_end)
|
||||
{
|
||||
#ifdef _NOT_USED_
|
||||
while (fpga_data++ < fpga_flash_data_end)
|
||||
{
|
||||
/* toggle a little more since it's fun ;) */
|
||||
MCF_GPIO_PODR_FEC1L |= FPGA_CLOCK;
|
||||
MCF_GPIO_PODR_FEC1L &= ~FPGA_CLOCK;
|
||||
}
|
||||
#endif /* _NOT_USED_ */
|
||||
end = MCF_SLT0_SCNT;
|
||||
time = (start - end) / (SYSCLK / 1000) / 1000;
|
||||
|
||||
xprintf("finished (took %f seconds).\r\n", time / 1000.0);
|
||||
}
|
||||
else
|
||||
{
|
||||
xprintf("FAILED!\r\n");
|
||||
}
|
||||
}
|
||||
224
pci_BaS_gcc/sys/interrupts.c
Normal file
224
pci_BaS_gcc/sys/interrupts.c
Normal file
@@ -0,0 +1,224 @@
|
||||
/*
|
||||
* Interrupts
|
||||
*
|
||||
* Handle interrupts, the levels.
|
||||
*
|
||||
* This file is part of BaS_gcc.
|
||||
*
|
||||
* BaS_gcc is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* BaS_gcc is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with BaS_gcc. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Created on: 26.02.2013
|
||||
* Author: Markus Fröschle
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "MCF5475.h"
|
||||
#include "bas_utils.h"
|
||||
#include "bas_printf.h"
|
||||
#include "exceptions.h"
|
||||
#include "interrupts.h"
|
||||
#include "bas_printf.h"
|
||||
|
||||
extern void (*rt_vbr[])(void);
|
||||
#define VBR rt_vbr
|
||||
|
||||
#define IRQ_DEBUG
|
||||
#if defined(IRQ_DEBUG)
|
||||
#define dbg(format, arg...) do { xprintf("DEBUG: " format, ##arg); } while (0)
|
||||
#else
|
||||
#define dbg(format, arg...) do { ; } while (0)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* register an interrupt handler at the Coldfire interrupt controller and add the handler to
|
||||
* the interrupt vector table
|
||||
*/
|
||||
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;
|
||||
|
||||
source &= 63;
|
||||
priority &= 7;
|
||||
|
||||
if (source < 1 || source > 63)
|
||||
{
|
||||
dbg("%s: interrupt source %d not defined\r\n", __FUNCTION__, source);
|
||||
return -1;
|
||||
}
|
||||
|
||||
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("%s: level %d and priority %d already used for interrupt source %d!\r\n", __FUNCTION__,
|
||||
level, priority, i);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* disable interrupts */
|
||||
ipl = set_ipl(7);
|
||||
|
||||
VBR[64 + source] = handler; /* first 64 vectors are system exceptions */
|
||||
|
||||
/* set level and priority in interrupt controller */
|
||||
ICR[source] = lp;
|
||||
|
||||
/* set interrupt mask to where it was before */
|
||||
set_ipl(ipl);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef UIF_MAX_ISR_ENTRY
|
||||
#define UIF_MAX_ISR_ENTRY (20)
|
||||
#endif
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int vector;
|
||||
int type;
|
||||
int (*handler)(void *, void *);
|
||||
void *hdev;
|
||||
void *harg;
|
||||
} ISRENTRY;
|
||||
|
||||
ISRENTRY isrtab[UIF_MAX_ISR_ENTRY];
|
||||
|
||||
|
||||
void isr_init(void)
|
||||
{
|
||||
int index;
|
||||
|
||||
for (index = 0; index < UIF_MAX_ISR_ENTRY; index++)
|
||||
{
|
||||
isrtab[index].vector = 0;
|
||||
isrtab[index].type = 0;
|
||||
isrtab[index].handler = 0;
|
||||
isrtab[index].hdev = 0;
|
||||
isrtab[index].harg = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int isr_register_handler(int type, int vector,
|
||||
int (*handler)(void *, void *), void *hdev, void *harg)
|
||||
{
|
||||
/*
|
||||
* This function places an interrupt handler in the ISR table,
|
||||
* thereby registering it so that the low-level handler may call it.
|
||||
*
|
||||
* The two parameters are intended for the first arg to be a
|
||||
* pointer to the device itself, and the second a pointer to a data
|
||||
* structure used by the device driver for that particular device.
|
||||
*/
|
||||
int index;
|
||||
|
||||
if ((vector == 0) ||
|
||||
((type != ISR_DBUG_ISR) && (type != ISR_USER_ISR)) ||
|
||||
(handler == NULL))
|
||||
{
|
||||
dbg("%s: illegal type, vector or handler!\r\n", __FUNCTION__);
|
||||
return false;
|
||||
}
|
||||
|
||||
for (index = 0; index < UIF_MAX_ISR_ENTRY; index++)
|
||||
{
|
||||
if ((isrtab[index].vector == vector) &&
|
||||
(isrtab[index].type == type))
|
||||
{
|
||||
/* only one entry of each type per vector */
|
||||
dbg("%s: already set handler with this type and vector (%d, %d)\r\n", __FUNCTION__, type, vector);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isrtab[index].vector == 0)
|
||||
{
|
||||
isrtab[index].vector = vector;
|
||||
isrtab[index].type = type;
|
||||
isrtab[index].handler = handler;
|
||||
isrtab[index].hdev = hdev;
|
||||
isrtab[index].harg = harg;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
dbg("%s: no available slots to register handler for vector %d\n\r", __FUNCTION__, vector);
|
||||
|
||||
return false; /* no available slots */
|
||||
}
|
||||
|
||||
void isr_remove_handler(int type, int (*handler)(void *, void *))
|
||||
{
|
||||
/*
|
||||
* This routine removes from the ISR table all
|
||||
* entries that matches 'type' and 'handler'.
|
||||
*/
|
||||
int index;
|
||||
|
||||
for (index = 0; index < UIF_MAX_ISR_ENTRY; index++)
|
||||
{
|
||||
if ((isrtab[index].handler == handler) &&
|
||||
(isrtab[index].type == type))
|
||||
{
|
||||
isrtab[index].vector = 0;
|
||||
isrtab[index].type = 0;
|
||||
isrtab[index].handler = 0;
|
||||
isrtab[index].hdev = 0;
|
||||
isrtab[index].harg = 0;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
dbg("%s: no such handler registered (type=%d, handler=%p\r\n", __FUNCTION__, type, handler);
|
||||
}
|
||||
|
||||
|
||||
bool isr_execute_handler(int vector)
|
||||
{
|
||||
/*
|
||||
* This routine searches the ISR table for an entry that matches
|
||||
* 'vector'. If one is found, then 'handler' is executed.
|
||||
*/
|
||||
int index;
|
||||
bool retval = false;
|
||||
|
||||
/*
|
||||
* First locate a BaS Interrupt Service Routine handler.
|
||||
*/
|
||||
for (index = 0; index < UIF_MAX_ISR_ENTRY; index++)
|
||||
{
|
||||
if ((isrtab[index].vector == vector) &&
|
||||
(isrtab[index].type == ISR_DBUG_ISR))
|
||||
{
|
||||
retval = true;
|
||||
|
||||
if (isrtab[index].handler(isrtab[index].hdev, isrtab[index].harg))
|
||||
{
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
}
|
||||
dbg("%s: no BaS isr handler for vector %d found\r\n", __FUNCTION__, vector);
|
||||
return retval;
|
||||
}
|
||||
|
||||
439
pci_BaS_gcc/sys/mmu.c
Normal file
439
pci_BaS_gcc/sys/mmu.c
Normal file
@@ -0,0 +1,439 @@
|
||||
#include "mmu.h"
|
||||
#include "acia.h"
|
||||
|
||||
/*
|
||||
* mmu.c
|
||||
*
|
||||
* This file is part of BaS_gcc.
|
||||
*
|
||||
* BaS_gcc is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* BaS_gcc is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with BaS_gcc. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* derived from original assembler sources:
|
||||
* Copyright 2010 - 2012 F. Aschwanden
|
||||
* Copyright 2013 M. Froeschle
|
||||
*/
|
||||
|
||||
#define ACR_BA(x) ((x) & 0xffff0000)
|
||||
#define ACR_ADMSK(x) (((x) & 0xffff) << 16)
|
||||
#define ACR_E(x) (((x) & 1) << 15)
|
||||
|
||||
#define ACR_S(x) (((x) & 3) << 13)
|
||||
#define ACR_S_USERMODE 0
|
||||
#define ACR_S_SUPERVISOR_MODE 1
|
||||
#define ACR_S_ALL 2
|
||||
|
||||
#define ACR_AMM(x) (((x) & 1) << 10)
|
||||
|
||||
#define ACR_CM(x) (((x) & 3) << 5)
|
||||
#define ACR_CM_CACHEABLE_WT 0x0
|
||||
#define ACR_CM_CACHEABLE_CB 0x1
|
||||
#define ACR_CM_CACHE_INH_PRECISE 0x2
|
||||
#define ACR_CM_CACHE_INH_IMPRECISE 0x3
|
||||
|
||||
#define ACR_SP(x) (((x) & 1) << 3)
|
||||
#define ACR_W(x) (((x) & 1) << 2)
|
||||
|
||||
#include <stdint.h>
|
||||
#include "bas_printf.h"
|
||||
#include "bas_types.h"
|
||||
#include "MCF5475.h"
|
||||
#include "pci.h"
|
||||
#include "cache.h"
|
||||
#include "util.h"
|
||||
|
||||
#if defined(MACHINE_FIREBEE)
|
||||
#include "firebee.h"
|
||||
#elif defined(MACHINE_M5484LITE)
|
||||
#include "m5484l.h"
|
||||
#else
|
||||
#error "unknown machine!"
|
||||
#endif /* MACHINE_FIREBEE */
|
||||
|
||||
//#define DEBUG_MMU
|
||||
#ifdef DEBUG_MMU
|
||||
#define dbg(format, arg...) do { xprintf("DEBUG: " format, ##arg);} while(0)
|
||||
#else
|
||||
#define dbg(format, arg...) do {;} while (0)
|
||||
#endif /* DEBUG_MMU */
|
||||
|
||||
/*
|
||||
* set ASID register
|
||||
* saves new value to rt_asid and returns former value
|
||||
*/
|
||||
inline uint32_t set_asid(uint32_t value)
|
||||
{
|
||||
extern long rt_asid;
|
||||
uint32_t ret = rt_asid;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"movec %[value],ASID\n\t"
|
||||
: /* no output */
|
||||
: [value] "r" (value)
|
||||
:
|
||||
);
|
||||
|
||||
rt_asid = value;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* set ACRx register
|
||||
* saves new value to rt_acrx and returns former value
|
||||
*/
|
||||
inline uint32_t set_acr0(uint32_t value)
|
||||
{
|
||||
extern uint32_t rt_acr0;
|
||||
uint32_t ret = rt_acr0;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"movec %[value],ACR0\n\t"
|
||||
: /* not output */
|
||||
: [value] "r" (value)
|
||||
:
|
||||
);
|
||||
rt_acr0 = value;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* set ACRx register
|
||||
* saves new value to rt_acrx and returns former value
|
||||
*/
|
||||
inline uint32_t set_acr1(uint32_t value)
|
||||
{
|
||||
extern uint32_t rt_acr1;
|
||||
uint32_t ret = rt_acr1;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"movec %[value],ACR1\n\t"
|
||||
: /* not output */
|
||||
: [value] "r" (value)
|
||||
:
|
||||
);
|
||||
rt_acr1 = value;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* set ACRx register
|
||||
* saves new value to rt_acrx and returns former value
|
||||
*/
|
||||
inline uint32_t set_acr2(uint32_t value)
|
||||
{
|
||||
extern uint32_t rt_acr2;
|
||||
uint32_t ret = rt_acr2;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"movec %[value],ACR2\n\t"
|
||||
: /* not output */
|
||||
: [value] "r" (value)
|
||||
:
|
||||
);
|
||||
rt_acr2 = value;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* set ACRx register
|
||||
* saves new value to rt_acrx and returns former value
|
||||
*/
|
||||
inline uint32_t set_acr3(uint32_t value)
|
||||
{
|
||||
extern uint32_t rt_acr3;
|
||||
uint32_t ret = rt_acr3;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"movec %[value],ACR3\n\t"
|
||||
: /* not output */
|
||||
: [value] "r" (value)
|
||||
:
|
||||
);
|
||||
rt_acr3 = value;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline uint32_t set_mmubar(uint32_t value)
|
||||
{
|
||||
extern uint32_t rt_mmubar;
|
||||
uint32_t ret = rt_mmubar;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"movec %[value],MMUBAR\n\t"
|
||||
: /* no output */
|
||||
: [value] "r" (value)
|
||||
: /* no clobber */
|
||||
);
|
||||
rt_mmubar = value;
|
||||
NOP();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void mmu_init(void)
|
||||
{
|
||||
extern uint8_t _MMUBAR[];
|
||||
uint32_t MMUBAR = (uint32_t) &_MMUBAR[0];
|
||||
extern uint8_t _TOS[];
|
||||
uint32_t TOS = (uint32_t) &_TOS[0];
|
||||
|
||||
set_asid(0); /* do not use address extension (ASID provides virtual 48 bit addresses */
|
||||
|
||||
/* 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 */
|
||||
ACR_AMM(0) | /* control region > 16 MB */
|
||||
ACR_S(ACR_S_ALL) | /* match addresses in user and supervisor mode */
|
||||
ACR_E(1) | /* enable ACR */
|
||||
#if MACHINE_FIREBEE
|
||||
ACR_ADMSK(0x3f) | /* cover 1GB area from 0xc0000000 to 0xffffffff */
|
||||
ACR_BA(0xc0000000)); /* (equals area from 3 to 4 GB */
|
||||
#elif MACHINE_M5484LITE
|
||||
ACR_ADMSK(0x7f) | /* cover 2 GB area from 0x80000000 to 0xffffffff */
|
||||
ACR_BA(0x80000000));
|
||||
#endif /* MACHINE_FIREBEE */
|
||||
|
||||
// set_acr1(0x601fc000);
|
||||
set_acr1(ACR_W(0) |
|
||||
ACR_SP(0) |
|
||||
ACR_CM(0) |
|
||||
#if MACHINE_FIREBEE
|
||||
ACR_CM(ACR_CM_CACHEABLE_WT) | /* video RAM on the Firebee */
|
||||
#elif MACHINE_M5484LITE
|
||||
ACR_CM(ACR_CM_CACHE_INH_PRECISE) | /* Compact Flash on the M548xLITE */
|
||||
#endif /* MACHINE_FIREBEE */
|
||||
ACR_AMM(0) |
|
||||
ACR_S(ACR_S_ALL) |
|
||||
ACR_E(1) |
|
||||
ACR_ADMSK(0x1f) |
|
||||
ACR_BA(0x60000000));
|
||||
|
||||
/* set instruction access attributes in ACR2 and ACR3 */
|
||||
|
||||
//set_acr2(0xe007c400);
|
||||
set_acr2(ACR_W(0) |
|
||||
ACR_SP(0) |
|
||||
ACR_CM(0) |
|
||||
ACR_CM(ACR_CM_CACHEABLE_WT) |
|
||||
ACR_AMM(1) |
|
||||
ACR_S(ACR_S_ALL) |
|
||||
ACR_E(1) |
|
||||
ACR_ADMSK(0x7) |
|
||||
ACR_BA(0xe0000000));
|
||||
|
||||
/* disable ACR3 */
|
||||
set_acr3(0x0);
|
||||
|
||||
set_mmubar(MMUBAR + 1); /* set and enable MMUBAR */
|
||||
|
||||
/* clear all MMU TLB entries */
|
||||
MCF_MMU_MMUOR = MCF_MMU_MMUOR_CA;
|
||||
|
||||
/* create locked TLB entries */
|
||||
|
||||
/*
|
||||
* 0x0000'0000 - 0x000F'FFFF (first MB of physical memory) locked virtual = physical
|
||||
*/
|
||||
MCF_MMU_MMUTR = 0x0 | /* virtual address */
|
||||
MCF_MMU_MMUTR_SG | /* shared global */
|
||||
MCF_MMU_MMUTR_V; /* valid */
|
||||
MCF_MMU_MMUDR = 0x0 | /* physical address */
|
||||
MCF_MMU_MMUDR_SZ(0) | /* 1 MB page size */
|
||||
MCF_MMU_MMUDR_CM(0x1) | /* cacheable, copyback */
|
||||
MCF_MMU_MMUDR_R | /* read access enable */
|
||||
MCF_MMU_MMUDR_W | /* write access enable */
|
||||
MCF_MMU_MMUDR_X | /* execute access enable */
|
||||
MCF_MMU_MMUDR_LK; /* lock entry */
|
||||
MCF_MMU_MMUOR = MCF_MMU_MMUOR_ACC | /* access TLB, data */
|
||||
MCF_MMU_MMUOR_UAA; /* update allocation address field */
|
||||
MCF_MMU_MMUOR = MCF_MMU_MMUOR_ITLB | /* instruction */
|
||||
MCF_MMU_MMUOR_ACC | /* access TLB */
|
||||
MCF_MMU_MMUOR_UAA; /* update allocation address field */
|
||||
|
||||
/*
|
||||
* 0x00d0'0000 - 0x00df'ffff (last megabyte of ST RAM = Falcon video memory) locked ID = 6
|
||||
* mapped to physical address 0x60d0'0000 (FPGA video memory)
|
||||
* video RAM: read write execute normal write true
|
||||
*/
|
||||
|
||||
MCF_MMU_MMUTR = 0x00d00000 | /* virtual address */
|
||||
#if defined(MACHINE_FIREBEE)
|
||||
MCF_MMU_MMUTR_ID(SCA_PAGE_ID) |
|
||||
#endif /* MACHINE_FIREBEE */
|
||||
MCF_MMU_MMUTR_SG | /* shared global */
|
||||
MCF_MMU_MMUTR_V; /* valid */
|
||||
#if defined(MACHINE_FIREBEE)
|
||||
/* map FPGA video memory for FireBee only */
|
||||
MCF_MMU_MMUDR = 0x60d00000 | /* physical address */
|
||||
#elif defined(MACHINE_M5484LITE)
|
||||
MCF_MMU_MMUDR = 0x00d00000 | /* physical address */
|
||||
#endif /* MACHINE_FIREBEE */
|
||||
MCF_MMU_MMUDR_SZ(0) | /* 1 MB page size */
|
||||
MCF_MMU_MMUDR_CM(0x0) | /* cachable writethrough */
|
||||
/* caveat: can't be supervisor protected since TOS puts the application stack there! */
|
||||
//MCF_MMU_MMUDR_SP | /* supervisor protect */
|
||||
MCF_MMU_MMUDR_R | /* read access enable */
|
||||
MCF_MMU_MMUDR_W | /* write access enable */
|
||||
MCF_MMU_MMUDR_X | /* execute access enable */
|
||||
MCF_MMU_MMUDR_LK; /* lock entry */
|
||||
MCF_MMU_MMUOR = MCF_MMU_MMUOR_ACC | /* access TLB, data */
|
||||
MCF_MMU_MMUOR_UAA; /* update allocation address field */
|
||||
MCF_MMU_MMUOR = MCF_MMU_MMUOR_ITLB | /* instruction */
|
||||
MCF_MMU_MMUOR_ACC | /* access TLB */
|
||||
MCF_MMU_MMUOR_UAA; /* update allocation address field */
|
||||
|
||||
#if defined(MACHINE_FIREBEE)
|
||||
video_tlb = 0x2000; /* set page as video page */
|
||||
video_sbt = 0x0; /* clear time */
|
||||
#endif /* MACHINE_FIREBEE */
|
||||
|
||||
/*
|
||||
* Make the TOS (in SDRAM) read-only
|
||||
* This maps virtual 0x00e0'0000 - 0x00ef'ffff to the same virtual address
|
||||
*/
|
||||
MCF_MMU_MMUTR = TOS | /* virtual address */
|
||||
MCF_MMU_MMUTR_SG | /* shared global */
|
||||
MCF_MMU_MMUTR_V; /* valid */
|
||||
MCF_MMU_MMUDR = TOS | /* physical address */
|
||||
MCF_MMU_MMUDR_SZ(0) | /* 1 MB page size */
|
||||
MCF_MMU_MMUDR_CM(0x1) | /* cachable copyback */
|
||||
MCF_MMU_MMUDR_R | /* read access enable */
|
||||
//MCF_MMU_MMUDR_W | /* write access enable (FIXME: for now) */
|
||||
MCF_MMU_MMUDR_X | /* execute access enable */
|
||||
MCF_MMU_MMUDR_LK; /* lock entry */
|
||||
MCF_MMU_MMUOR = MCF_MMU_MMUOR_ACC | /* access TLB, data */
|
||||
MCF_MMU_MMUOR_UAA; /* update allocation address field */
|
||||
MCF_MMU_MMUOR = MCF_MMU_MMUOR_ITLB | /* instruction */
|
||||
MCF_MMU_MMUOR_ACC | /* access TLB */
|
||||
MCF_MMU_MMUOR_UAA; /* update allocation address field */
|
||||
|
||||
#if MACHINE_FIREBEE
|
||||
/*
|
||||
* Map FireBee I/O area (0xfff0'0000 - 0xffff'ffff physical) to the Falcon-compatible I/O
|
||||
* area (0x00f0'0000 - 0x00ff'ffff virtual) for the FireBee
|
||||
*/
|
||||
|
||||
MCF_MMU_MMUTR = 0x00f00000 | /* virtual address */
|
||||
MCF_MMU_MMUTR_SG | /* shared global */
|
||||
MCF_MMU_MMUTR_V; /* valid */
|
||||
MCF_MMU_MMUDR = 0xfff00000 | /* physical address */
|
||||
MCF_MMU_MMUDR_SZ(0) | /* 1 MB page size */
|
||||
MCF_MMU_MMUDR_CM(0x2) | /* nocache precise */
|
||||
MCF_MMU_MMUDR_SP | /* supervisor protect */
|
||||
MCF_MMU_MMUDR_R | /* read access enable */
|
||||
MCF_MMU_MMUDR_W | /* write access enable */
|
||||
MCF_MMU_MMUDR_X | /* execute access enable */
|
||||
MCF_MMU_MMUDR_LK; /* lock entry */
|
||||
MCF_MMU_MMUOR = MCF_MMU_MMUOR_ACC | /* access TLB, data */
|
||||
MCF_MMU_MMUOR_UAA; /* update allocation address field */
|
||||
MCF_MMU_MMUOR = MCF_MMU_MMUOR_ITLB | /* instruction */
|
||||
MCF_MMU_MMUOR_ACC | /* access TLB */
|
||||
MCF_MMU_MMUOR_UAA; /* update allocation address field */
|
||||
#endif /* MACHINE_FIREBEE */
|
||||
|
||||
/*
|
||||
* Map (locked) the second last MB of physical SDRAM (this is where BaS .data and .bss reside) to the same
|
||||
* virtual address. This is also used when BaS is in RAM
|
||||
*/
|
||||
|
||||
MCF_MMU_MMUTR = (SDRAM_START + SDRAM_SIZE - 0x00200000) | /* virtual address */
|
||||
MCF_MMU_MMUTR_SG | /* shared global */
|
||||
MCF_MMU_MMUTR_V; /* valid */
|
||||
MCF_MMU_MMUDR = (SDRAM_START + SDRAM_SIZE - 0x00200000) | /* physical address */
|
||||
MCF_MMU_MMUDR_SZ(0) | /* 1 MB page size */
|
||||
MCF_MMU_MMUDR_CM(0x0) | /* cacheable writethrough */
|
||||
MCF_MMU_MMUDR_SP | /* supervisor protect */
|
||||
MCF_MMU_MMUDR_R | /* read access enable */
|
||||
MCF_MMU_MMUDR_W | /* write access enable */
|
||||
MCF_MMU_MMUDR_X | /* execute access enable */
|
||||
MCF_MMU_MMUDR_LK; /* lock entry */
|
||||
MCF_MMU_MMUOR = MCF_MMU_MMUOR_ACC | /* access TLB, data */
|
||||
MCF_MMU_MMUOR_UAA; /* update allocation address field */
|
||||
MCF_MMU_MMUOR = MCF_MMU_MMUOR_ITLB | /* instruction */
|
||||
MCF_MMU_MMUOR_ACC | /* access TLB */
|
||||
MCF_MMU_MMUOR_UAA; /* update allocation address field */
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
MCF_MMU_MMUTR = (SDRAM_START + SDRAM_SIZE - 0x00100000) | /* virtual address */
|
||||
MCF_MMU_MMUTR_SG | /* shared global */
|
||||
MCF_MMU_MMUTR_V; /* valid */
|
||||
MCF_MMU_MMUDR = (SDRAM_START + SDRAM_SIZE - 0x00100000) | /* physical address */
|
||||
MCF_MMU_MMUDR_SZ(0) | /* 1 MB page size */
|
||||
MCF_MMU_MMUDR_CM(0x2) | /* nocache precise */
|
||||
MCF_MMU_MMUDR_SP | /* supervisor protect */
|
||||
MCF_MMU_MMUDR_R | /* read access enable */
|
||||
MCF_MMU_MMUDR_W | /* write access enable */
|
||||
//MCF_MMU_MMUDR_X | /* execute access enable */
|
||||
MCF_MMU_MMUDR_LK; /* lock entry */
|
||||
MCF_MMU_MMUOR = MCF_MMU_MMUOR_ACC | /* access TLB, data */
|
||||
MCF_MMU_MMUOR_UAA; /* update allocation address field */
|
||||
MCF_MMU_MMUOR = MCF_MMU_MMUOR_ITLB | /* instruction */
|
||||
MCF_MMU_MMUOR_ACC | /* access TLB */
|
||||
MCF_MMU_MMUOR_UAA; /* update allocation address field */
|
||||
}
|
||||
|
||||
void mmutr_miss(uint32_t address)
|
||||
{
|
||||
dbg("MMU TLB MISS at 0x%08x\r\n", address);
|
||||
flush_and_invalidate_caches();
|
||||
|
||||
switch (address)
|
||||
{
|
||||
case keyctl:
|
||||
case keybd:
|
||||
/* do something to emulate the IKBD access */
|
||||
dbg("IKBD access\r\n");
|
||||
break;
|
||||
|
||||
case midictl:
|
||||
case midi:
|
||||
/* do something to emulate MIDI access */
|
||||
dbg("MIDI ACIA access\r\n");
|
||||
break;
|
||||
|
||||
default:
|
||||
/* add missed page to TLB */
|
||||
MCF_MMU_MMUTR = (address & 0xfff00000) | /* virtual aligned to 1M */
|
||||
MCF_MMU_MMUTR_SG | /* shared global */
|
||||
MCF_MMU_MMUTR_V; /* valid */
|
||||
|
||||
MCF_MMU_MMUDR = (address & 0xfff00000) | /* physical aligned to 1M */
|
||||
MCF_MMU_MMUDR_SZ(0) | /* 1 MB page size */
|
||||
MCF_MMU_MMUDR_CM(0x1) | /* cacheable copyback */
|
||||
MCF_MMU_MMUDR_R | /* read access enable */
|
||||
MCF_MMU_MMUDR_W | /* write access enable */
|
||||
MCF_MMU_MMUDR_X; /* execute access enable */
|
||||
|
||||
MCF_MMU_MMUOR = MCF_MMU_MMUOR_ACC | /* access TLB, data */
|
||||
MCF_MMU_MMUOR_UAA; /* update allocation address field */
|
||||
|
||||
MCF_MMU_MMUOR = MCF_MMU_MMUOR_ITLB | /* instruction */
|
||||
MCF_MMU_MMUOR_ACC | /* access TLB */
|
||||
MCF_MMU_MMUOR_UAA; /* update allocation address field */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
65
pci_BaS_gcc/sys/startcf.S
Normal file
65
pci_BaS_gcc/sys/startcf.S
Normal file
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* This object file must be the first to be linked,
|
||||
* so it will be placed at the very beginning of the ROM.
|
||||
*/
|
||||
|
||||
.equ MCF_MMU_MMUCR, __MMUBAR + 0
|
||||
|
||||
.global _rom_header
|
||||
.global _rom_entry
|
||||
|
||||
.extern _initialize_hardware
|
||||
.extern _rt_mbar
|
||||
|
||||
/* ROM header */
|
||||
_rom_header:
|
||||
/* The first long is supposed to be the initial SP.
|
||||
* We replace it by bra.s to allow running the ROM from the first byte.
|
||||
* Then we add a fake jmp instruction for pretty disassembly.
|
||||
*/
|
||||
bra.s _rom_entry // Short jump to the real entry point
|
||||
.short 0x4ef9 // Fake jmp instruction
|
||||
/* The second long is the initial PC */
|
||||
.long _rom_entry // Real entry point
|
||||
|
||||
/* ROM entry point */
|
||||
_rom_entry:
|
||||
/* disable interrupts */
|
||||
move.w #0x2700,SR
|
||||
|
||||
/* Initialize MBAR */
|
||||
move.l #__MBAR,d0
|
||||
movec d0,MBAR
|
||||
move.l d0,_rt_mbar
|
||||
|
||||
/* mmu off */
|
||||
move.l #__MMUBAR+1,d0
|
||||
movec d0,MMUBAR
|
||||
|
||||
clr.l d0
|
||||
move.l d0,MCF_MMU_MMUCR
|
||||
|
||||
/* Initialize RAMBARs: locate SRAM and validate it */
|
||||
move.l #__RAMBAR0 + 0x7,d0 /* supervisor only */
|
||||
movec d0,RAMBAR0
|
||||
move.l #__RAMBAR1 + 0x1,d0
|
||||
movec d0,RAMBAR1
|
||||
|
||||
/* set stack pointer to end of SRAM */
|
||||
lea __SUP_SP,a7
|
||||
move.l #0,(sp)
|
||||
|
||||
/* Initialize the processor caches.
|
||||
* The instruction cache is fully enabled.
|
||||
* The data cache is enabled, but cache-inhibited by default.
|
||||
* Later, the MMU will fully activate the data cache for specific areas.
|
||||
* It is important to enable both caches now, otherwise cpushl would hang.
|
||||
*/
|
||||
|
||||
move.l #0xa50c8120,d0
|
||||
movec d0,cacr
|
||||
andi.l #0xfefbfeff,d0 // Clear invalidate bits
|
||||
move.l d0,_rt_cacr
|
||||
|
||||
/* initialize any hardware specific issues */
|
||||
bra _initialize_hardware
|
||||
1152
pci_BaS_gcc/sys/sysinit.c
Normal file
1152
pci_BaS_gcc/sys/sysinit.c
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user