462 lines
11 KiB
C
462 lines
11 KiB
C
/*
|
|
* 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"
|
|
#include "net_timer.h"
|
|
|
|
//#define BAS_DEBUG
|
|
#if defined(BAS_DEBUG)
|
|
#define dbg(format, arg...) do { xprintf("DEBUG: %s(): " format, __FUNCTION__, ##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("PIC initialization failed. Already initialized?\r\n");
|
|
}
|
|
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 defined(MACHINE_FIREBEE)
|
|
*FPGA_INTR_CONTRL = 0L; /* disable all interrupts */
|
|
#endif /* MACHINE_FIREBEE */
|
|
MCF_EPORT_EPPAR = 0xaaa8; /* all interrupts on falling edge */
|
|
|
|
#if defined(MACHINE_FIREBEE)
|
|
/*
|
|
* TIN0 on the Coldfire is connected to the FPGA. TIN0 triggers every write
|
|
* access to 0xff8201 (vbasehi), i.e. everytime the video base address is written
|
|
*/
|
|
MCF_GPT0_GMS = MCF_GPT_GMS_ICT(1) | /* timer 0 on, video change capture on rising edge */
|
|
MCF_GPT_GMS_IEN |
|
|
MCF_GPT_GMS_TMS(1);
|
|
/* route GPT0 interrupt on interrupt controller */
|
|
MCF_INTC_ICR62 = 0x3f; /* interrupt level 7, interrupt priority 7 */
|
|
|
|
*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()
|
|
{
|
|
#if defined(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;
|
|
#if defined(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, 0x85, 0xcf, 0x01}; /* this is the original MAC address dbug assigns */
|
|
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(vector, handler, NULL, (void *) &nif1))
|
|
{
|
|
dbg("unable to register handler for vector %d\r\n", vector);
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* Register the DMA interrupt handler
|
|
*/
|
|
handler = dma_interrupt_handler;
|
|
vector = 112;
|
|
|
|
if (!isr_register_handler(vector, handler, NULL,NULL))
|
|
{
|
|
dbg("Error: Unable to register handler for vector %s\r\n", 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("ethernet address is %02X:%02X:%02X:%02X:%02X:%02X\r\n",
|
|
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 defined(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);
|
|
|
|
#if defined(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 */
|
|
|
|
#if defined(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);
|
|
struct rom_header
|
|
{
|
|
void *initial_sp;
|
|
void_func *initial_pc;
|
|
};
|
|
|
|
xprintf("BaS initialization finished, enable interrupts\r\n");
|
|
enable_coldfire_interrupts();
|
|
|
|
//set_ipl(0);
|
|
network_init();
|
|
|
|
xprintf("call EmuTOS\r\n");
|
|
struct rom_header *os_header = (struct rom_header *) TOS;
|
|
os_header->initial_pc();
|
|
}
|