diff --git a/BaS_gcc.files b/BaS_gcc.files index e63751a..6ae34cd 100644 --- a/BaS_gcc.files +++ b/BaS_gcc.files @@ -204,6 +204,7 @@ sys/cache.c sys/driver_mem.c sys/exceptions.S sys/fault_vectors.c +sys/ide.c sys/init_fpga.c sys/interrupts.c sys/mmu.c diff --git a/Makefile b/Makefile index 3ab89df..3b313eb 100644 --- a/Makefile +++ b/Makefile @@ -110,6 +110,7 @@ CSRCS= \ dspi.c \ driver_vec.c \ driver_mem.c \ + ide.c \ \ MCD_dmaApi.c \ MCD_tasks.c \ diff --git a/bas.lk.in b/bas.lk.in index 9092496..4fcf620 100644 --- a/bas.lk.in +++ b/bas.lk.in @@ -83,6 +83,7 @@ SECTIONS OBJDIR/bas_printf.o(.text) OBJDIR/bas_string.o(.text) OBJDIR/conout.o(.text) + OBJDIR/ide.o(.text) #if (FORMAT_ELF == 1) OBJDIR/libgcc_helper.o(.text) #endif diff --git a/sys/BaS.c b/sys/BaS.c index 22accd1..3923d5e 100644 --- a/sys/BaS.c +++ b/sys/BaS.c @@ -56,6 +56,7 @@ /* imported routines */ extern int vec_init(); +extern void set_ide_access_mode(void); /* Symbols from the linker script */ extern uint8_t _STRAM_END[]; @@ -387,6 +388,19 @@ void init_isr(void) } } +void ide_init(void) +{ + /* IDE reset */ + * (volatile uint8_t *) (0xffff8802 - 2) = 14; + * (volatile uint8_t *) (0xffff8802 - 0) = 0x80; + wait(1); + + * (volatile uint8_t *) (0xffff8802 - 0) = 0; + + set_ide_access_mode(); +} + + /* Jump into the OS */ typedef void void_func(void); struct rom_header @@ -450,14 +464,8 @@ void BaS(void) memset((void *) 0x0200, 0x0, 0x0400); #if defined(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("IDE reset: \r\n"); + ide_init(); xprintf("finished\r\n"); xprintf("enable video: "); diff --git a/sys/ide.c b/sys/ide.c new file mode 100644 index 0000000..6664018 --- /dev/null +++ b/sys/ide.c @@ -0,0 +1,168 @@ +/* + * ide.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 . + * + * derived from original assembler sources: + * Copyright 2010 - 2018 F. Aschwanden + * Copyright 2018 D. Gálvez + */ + +#include "bas_printf.h" + +#define FALCON_IO 0xFFF00000 +#define IDE_1ST_INTERFACE 0x00 +#define IDE_2ND_INTERFACE 0x40 + +#define IDE_REG_DATA *(volatile long*)(FALCON_IO + ide_addr_offset + (0x00)) +#define IDE_REG_ERROR *(volatile char*)(FALCON_IO + ide_addr_offset + (0x05)) +#define IDE_REG_SECCNT *(volatile char*)(FALCON_IO + ide_addr_offset + (0x09)) +#define IDE_REG_STASEC *(volatile char*)(FALCON_IO + ide_addr_offset + (0x0D)) +#define IDE_REG_DRVHEAD *(volatile char*)(FALCON_IO + ide_addr_offset + (0x19)) +#define IDE_REG_CMD *(volatile char*)(FALCON_IO + ide_addr_offset + (0x1D)) +#define IDE_REG_STATUS *(volatile char*)(FALCON_IO + ide_addr_offset + (0x1D)) + +#define IDE_REG_STATUS_DRQ (1 << 3) +#define IDE_REG_STATUS_BSY (1 << 7) + +#define IDE_CMD_RESET 0x08 +#define IDE_CMD_IDENTIFY 0xEC + +/* IDENTIFY INFO OFFSETS IN BYTES */ +#define IDENTIFY_MODEL 27 * 2 +#define IDENTIFY_PIO_CYCLE_TIME_NS 68 * 2 + +#define ACP_CONFIG_REG *(volatile long*)(0xF0040000) + +#define ACP_CONFIG_REG_SPEED_U0 (3 << 16) /* Slow (3), Middle (2), Fast (1), No drive (NEG) */ +#define ACP_CONFIG_REG_SPEED_U1 (3 << 20) /* Slow (3), Middle (2), Fast (1), No drive (NEG) */ +#define ACP_CONFIG_REG_RST (1 << 25) +#define ACP_CONFIG_REG_SCSI_INT (1 << 27) +#define ACP_CONFIG_REG_IDE_INT (1 << 28) +#define ACP_CONFIG_REG_IDE_ADDR (1 << 30) /* 0: 0x40 1: 0x00 */ +#define ACP_CONFIG_REG_CF_ADDR (1 << 31) /* 0: 0x00 1: 0x40 */ + +extern void wait_ms(long); + + +int32_t get_speed(short pio_cycle_time) +{ + int32_t speed; + + /* From BaS CW sources: + * 0 - 63 ns fast + * 64 - 128 ns middle + * > 128 ns slow + */ + if (pio_cycle_time <= 0) + speed = -1; /* drive or card not present */ + else if (pio_cycle_time <= 63) + speed = 0; + else if (pio_cycle_time <= 96) + speed = 1; + else if (pio_cycle_time <= 128) + speed = 2; + else speed = 3; + + return speed; +} + +int wait_ready(short ide_addr_offset) +{ + int i = 0; + + do { + wait_ms(1); + i++; + if (i == 2000) /* 2 sec */ + return -1; + } while (IDE_REG_STATUS & IDE_REG_STATUS_BSY); + + return 0; +} + +short test_drive(short ide_addr_offset) +{ + uint32_t buff[128]; /* 512 bytes */ + int8_t *buff2 = (int8_t *)buff; + int16_t pio_cycle_time; + int i; + + /* IDE reset */ + + IDE_REG_DRVHEAD = 0x00; + IDE_REG_CMD = IDE_CMD_RESET; + + if (wait_ready(ide_addr_offset)) + return 0; /* Time-Out */ + + /* Identify device */ + + i = 0; + do { + IDE_REG_DRVHEAD = 0x00; + IDE_REG_CMD = IDE_CMD_IDENTIFY; + + wait_ready(ide_addr_offset); + if (++i > 3) /* 3 attempts */ + return 0; + } while (!(IDE_REG_STATUS & IDE_REG_STATUS_DRQ)); + + for (i = 0; i < 128; i++) { + buff[i] = IDE_REG_DATA; + } + + if (!buff[0]) + return 0; /* There is no data */ + + /* Print drive info */ + + for (i = 0; i < 20; i++) { + xprintf("%c", *(buff2 + IDENTIFY_MODEL + i)); + } + + pio_cycle_time = (short) *(short *)(buff2 + IDENTIFY_PIO_CYCLE_TIME_NS); + + xprintf("PIO cycle time: %d ns\n\r", *(short *)(buff2 + IDENTIFY_PIO_CYCLE_TIME_NS)); + + return pio_cycle_time; +}; + + +void set_ide_access_mode(void) +{ + uint16_t pio_cycle_time; + int32_t speed; + + ACP_CONFIG_REG |= ACP_CONFIG_REG_RST; + wait_ms(10); + + /* CF 0xFFF00000, IDE 0xFFF00040, IDE INT ON, SCSI INT OFF, SPEED SLOW */ + ACP_CONFIG_REG |= (ACP_CONFIG_REG_IDE_INT | ACP_CONFIG_REG_SPEED_U1 | ACP_CONFIG_REG_SPEED_U0); + wait_ms(10); + + pio_cycle_time = test_drive(IDE_1ST_INTERFACE); + speed = get_speed(pio_cycle_time); + ACP_CONFIG_REG = (ACP_CONFIG_REG & 0xfff0ffff) | (speed << 16); + + /* For now we only support the built-in CF interface */ +#if 0 + pio_cycle_time = test_drive(IDE_2ND_INTERFACE); + speed = get_speed(pio_cycle_time); +#endif + speed = 0x0f; /* -1 (drive or card not present) */ + ACP_CONFIG_REG = (ACP_CONFIG_REG & 0xff0fffff) | (speed << 20); +}; diff --git a/sys/sysinit.c b/sys/sysinit.c index 0b4ec56..a24e3bd 100644 --- a/sys/sysinit.c +++ b/sys/sysinit.c @@ -415,13 +415,13 @@ static void init_fbcs() #if defined(MACHINE_FIREBEE) /* FBC setup for FireBee */ - MCF_FBCS1_CSAR = MCF_FBCS_CSAR_BA(0xFFF00000); /* ATARI I/O address range */ + MCF_FBCS1_CSAR = MCF_FBCS_CSAR_BA(0xFFF80000); /* ATARI I/O address range */ MCF_FBCS1_CSCR = MCF_FBCS_CSCR_PS_16 /* 16BIT PORT */ | MCF_FBCS_CSCR_WS(32) /* 32 wait states */ // | MCF_FBCS_CSCR_BSTR /* burst read enable */ // | MCF_FBCS_CSCR_BSTW /* burst write enable */ | MCF_FBCS_CSCR_AA; /* auto /TA acknowledge */ - MCF_FBCS1_CSMR = MCF_FBCS_CSMR_BAM_1M | MCF_FBCS_CSMR_V; + MCF_FBCS1_CSMR = MCF_FBCS_CSMR_BAM_512K | MCF_FBCS_CSMR_V; MCF_FBCS2_CSAR = MCF_FBCS_CSAR_BA(0xF0000000); /* Firebee new I/O address range */ MCF_FBCS2_CSCR = MCF_FBCS_CSCR_PS_32 /* 32BIT PORT */ @@ -430,12 +430,14 @@ static void init_fbcs() MCF_FBCS2_CSMR = (MCF_FBCS_CSMR_BAM_128M /* F000'0000-F7FF'FFFF */ | MCF_FBCS_CSMR_V); - MCF_FBCS3_CSAR = MCF_FBCS_CSAR_BA(0xF8000000); /* Firebee SRAM */ - MCF_FBCS3_CSCR = MCF_FBCS_CSCR_PS_16 /* 16 bit port */ - | MCF_FBCS_CSCR_WS(32) /* 0 wait states */ - | MCF_FBCS_CSCR_AA; /* auto /TA acknowledge */ - MCF_FBCS3_CSMR = (MCF_FBCS_CSMR_BAM_64M /* F800'0000-FBFF'FFFF */ - | MCF_FBCS_CSMR_V); + MCF_FBCS3_CSAR = MCF_FBCS_CSAR_BA(0xFFF00000); /* IDE I/O address BURST! */ + MCF_FBCS3_CSCR = MCF_FBCS_CSCR_PS_16 /* 16BIT PORT */ + | MCF_FBCS_CSCR_WS(16) /* 16 wait states */ + | MCF_FBCS_CSCR_BSTR /* Burst read enable */ + | MCF_FBCS_CSCR_BSTW /* Burst write enable */ + | MCF_FBCS_CSCR_AA; /* auto /TA acknowledge */ + MCF_FBCS3_CSMR = (MCF_FBCS_CSMR_BAM_512K /* FFF0'0000-FFF7'FFFF */ + | MCF_FBCS_CSMR_V); /* * Note: burst read/write settings of the following FBCS are purely "cosmetical".