diff --git a/include/kernel/def/attributes.h b/include/kernel/bits/attributes.h similarity index 100% rename from include/kernel/def/attributes.h rename to include/kernel/bits/attributes.h diff --git a/include/kernel/bits/context.h b/include/kernel/bits/context.h new file mode 100644 index 0000000..11dfbce --- /dev/null +++ b/include/kernel/bits/context.h @@ -0,0 +1,19 @@ +#ifndef __KERNEL_BITS_CONTEXT_H__ +# define __KERNEL_BITS_CONTEXT_H__ + +#include +#include + +// Define the SuperH CPU hardware context +struct cpu_context +{ + uint32_t reg[16]; + uint32_t gbr; + uint32_t macl; + uint32_t mach; + uint32_t ssr; + uint32_t spc; + uint32_t pr; +}; + +#endif /*__KERNEL_BITS_CONTEXT_H__*/ diff --git a/include/kernel/bits/driver.h b/include/kernel/bits/driver.h new file mode 100644 index 0000000..c9e75a0 --- /dev/null +++ b/include/kernel/bits/driver.h @@ -0,0 +1,24 @@ +#ifndef __KERNEL_BITS_DRIVER_H__ +# define __KERNEL_BITS_DRIVER_H__ + +#include + +// Macros used to declare new driver object +// @note: +// Level 1: Should be installed first (power management) +// Level 2: Higher priority (clock and bus control) +// Level 3: High priority (timer, rtc, ...) +// Level 4: General drivers +#define VHEX_DRIVER(level, name) \ + __attribute__((section(".driver." #level))) struct driver name + +// Define driver object +struct driver +{ + mpu_t arch; + void (*install)(void); + void (*uninstall)(void); + const char *name; +}; + +#endif /*__KERNEL_BITS_DRIVER_H__*/ diff --git a/include/kernel/hardware/mpu.h b/include/kernel/bits/mpu.h similarity index 52% rename from include/kernel/hardware/mpu.h rename to include/kernel/bits/mpu.h index 138a611..9b3ec10 100644 --- a/include/kernel/hardware/mpu.h +++ b/include/kernel/bits/mpu.h @@ -1,5 +1,5 @@ -#ifndef __KERNEL_HARDWARE_MPU_H__ -# define __KERNEL_HARDWARE_MPU_H__ +#ifndef __KERNEL_BITS_MPU_H__ +# define __KERNEL_BITS_MPU_H__ // Define MPU arch. typedef enum mpu_e @@ -11,4 +11,4 @@ typedef enum mpu_e MPU_UNKNOWN, } mpu_t; -#endif /*__KERNEL_HARDWARE_MPU_H__*/ +#endif /*__KERNEL_BITS_MPU_H__*/ diff --git a/include/kernel/def/union_types.h b/include/kernel/bits/union_types.h similarity index 100% rename from include/kernel/def/union_types.h rename to include/kernel/bits/union_types.h diff --git a/include/kernel/context.h b/include/kernel/context.h deleted file mode 100644 index a6d7c99..0000000 --- a/include/kernel/context.h +++ /dev/null @@ -1,67 +0,0 @@ -#ifndef __KERNEL_CONTEXT_H__ -# define __KERNEL_CONTEXT_H__ - -#include -#include - -typedef struct fx9860_context_s -{ - struct { - uint16_t control; - uint16_t autofix; - uint16_t scan_mode; - uint16_t scan_state; - uint16_t interrupt; - uint16_t scan_wait; - uint16_t scan_interval; - uint16_t kyoutdr; - uint16_t kyindr; - } keyboard; - struct { - uint16_t ipra; - uint16_t iprb; - uint16_t iprc; - uint16_t iprd; - uint16_t ipre; - uint16_t iprf; - uint16_t iprg; - uint16_t iprh; - uint16_t ipri; - uint16_t iprj; - uint16_t iprk; - uint16_t iprl; - } intc; - struct { - uint32_t stbcr; - uint32_t mstpcr0; - uint32_t mstpcr1; - uint32_t mstpcr2; - } power; - struct { - uint8_t tstr; - struct { - uint32_t tcor; - uint32_t tcnt; - uint16_t tcr; - } timer[3]; - } tmu; - uint32_t vbr; - //TODO: SR SSR SPC GBR MACL MACH -} fx9860_context_t; - -typedef struct common_context_s -{ - uint32_t reg[16]; - uint32_t gbr; - uint32_t macl; - uint32_t mach; - uint32_t ssr; - uint32_t spc; - uint32_t pr; -} common_context_t; - -// Context primitive. -extern void fx9860_context_save(fx9860_context_t *context); -extern void fx9860_context_restore(fx9860_context_t *context); - -#endif /*__KERNEL_CONTEXT_H__*/ diff --git a/include/kernel/drivers/keyboard.h b/include/kernel/drivers/keyboard.h index f282c12..92237b3 100644 --- a/include/kernel/drivers/keyboard.h +++ b/include/kernel/drivers/keyboard.h @@ -5,9 +5,11 @@ #include #include +// Macros which generate keycode #define KEYCODE_GEN(row, column) \ (((row & 0x0f) << 4) | ((column & 0x0f) << 0)) +// Internal struct used by the keyboard abstraction struct keycache_s { uint8_t keycode; @@ -26,7 +28,7 @@ struct keyscan_s }; typedef struct keyscan_s keyscan_t; - +// Define all keycode typedef enum key_e { KEY_F1 = 0x41, @@ -90,10 +92,11 @@ typedef enum key_e KEY_UNUSED = 0xff } key_t; -// Primitives -extern int keyboard_open(void); -extern ssize_t keyboard_read(void *buffer, size_t count); -extern int keyboard_close(void); + +// key cache abstrations functions +extern void keycache_initialize(void); +extern void keycache_clean(int key_frame); +extern void keycache_update(int row, int column, uint8_t key_frame); // Helpers extern void keyboard_wait_event(keyscan_t *list); diff --git a/include/kernel/drivers/vbr.h b/include/kernel/drivers/vbr.h index df612d0..23d3e3d 100644 --- a/include/kernel/drivers/vbr.h +++ b/include/kernel/drivers/vbr.h @@ -19,7 +19,23 @@ //--- // Interruption code //--- -//TODO +//TODO: chech SH7724 code validity (?) +#define INT_CODE_TMU0_TUNI0 0x400 +#define INT_CODE_TMU0_TUNI1 0x420 +#define INT_CODE_TMU0_TUNI2 0x440 +#define INT_CODE_KEYSC 0xbe0 +// Macros helpers +// @note: +// First interrupt code start at 0x400 (TLB miss are redirect) +// and the last interrupt code is 0xfe0 (undocumented) +// Each interrupt code are gapped by 0x20 +#define VBR_GET_INTERRUPT_CODE(id, code) (id = ((code - 0x400) / 0x20)) +#define VBR_INTERRUPT_NB ((0xfe0 - 0x400) / 0x20) + +// Driver primitives +extern void *vbr_interrupt_set(int intcode, void (*handler)(void)); +extern void *vbr_set(void *vbr); +extern void *vbr_get(void); #endif /*__KERNEL_DRIVERS_VBR_H__*/ diff --git a/include/kernel/fs/smemfs.h b/include/kernel/fs/smemfs.h index 5a85687..a8568a1 100644 --- a/include/kernel/fs/smemfs.h +++ b/include/kernel/fs/smemfs.h @@ -6,6 +6,58 @@ #include #include + + +/*******************************************/ +/** **/ +/** Common SMEM driver part **/ +/** **/ +/*******************************************/ +extern void smemfs_initialize(void); +extern void smemfd_uninitialize(void); + + + + +/*******************************************/ +/** **/ +/** USB Power Graphic II SMEM driver part **/ +/** **/ +/*******************************************/ +// Internal Casio's structure to dump file's informations +struct smem_USB3_file_info +{ + uint16_t id; // File index + uint16_t type; // File type + struct { + uint32_t file; // File size (data + header) + uint32_t data; // Data size (without header) + } size; + uint32_t address; // Data address ? +}; + +// Superblock primitives +extern void * smemfs_USB3_mount(void); +extern int smemfs_USB3_umount(void); + +// File primitives +extern ssize_t smemfs_USB3_read(void *inode, void *buf, size_t count, off_t pos); + +// Inode primitive +extern void * smemfs_USB3_find_parent(void *inode); +extern void * smemfs_USB3_find_first_child(void *inode); +extern void * smemfs_USB3_find_next_sibling(void *inode); +extern int smemfs_USB3_get_name(void *inode, char *name, size_t count); +extern mode_t smemfs_USB3_get_mode(void *inode); + + +/*******************************************/ +/** **/ +/** USB Power Graphic II SMEM driver part **/ +/** **/ +/*******************************************/ + +// Define internal SMEM informations /flags #define CASIO_SMEM_NAME_LENGHT 12 #define CASIO_SMEM_ROOT_ID 0xffff #define CASIO_SMEM_BLOCK_ENTRY_MAGIC 0x4200 @@ -18,7 +70,6 @@ #define CASIO_SMEM_FRAGMENT_MAGIC 0x0120 #define CASIO_SMEM_ROOT_ID 0xffff - // Define block data. struct casio_smem_block_s { @@ -86,28 +137,26 @@ struct smemfs_superblock_s smemfs_sector_t *sector_table; }; -// Constructor -extern void smemfs_initialize(); // Superblock primitives -extern void *smemfs_mount(void); -extern int smemfs_umount(void); +extern void * smemfs_USB2_mount(void); +extern int smemfs_USB2_umount(void); // File primitives -extern ssize_t smemfs_read(void *inode, void *buf, size_t count, off_t pos); +extern ssize_t smemfs_USB2_read(void *inode, void *buf, size_t count, off_t pos); // Inode primitive -extern void *smemfs_find_next_sibling(void *inode); -extern void *smemfs_find_first_child(void *inode); -extern void *smemfs_find_parent(void *inode); -extern int smemfs_get_name(void *inode, char *name, size_t count); -extern mode_t smemfs_get_mode(void *inode); +extern void * smemfs_USB2_find_parent(void *inode); +extern void * smemfs_USB2_find_first_child(void *inode); +extern void * smemfs_USB2_find_next_sibling(void *inode); +extern int smemfs_USB2_get_name(void *inode, char *name, size_t count); +extern mode_t smemfs_USB2_get_mode(void *inode); // Internal helper ! #define WALK_FLAG_ID_CHECK_PARENT (1 << 0) #define WALK_FLAG_ID_CHECK_DIRECTORY (0 << 0) -extern smemfs_inode_t *smemfs_walk(smemfs_inode_t *current, - smemfs_inode_t *entry, uint16_t folder_id, int flags); +extern smemfs_inode_t *smemfs_USB2_walk(smemfs_inode_t *current, + smemfs_inode_t *entry, uint16_t folder_id, int flags); #endif /*_CASIO_SMEM_H__*/ diff --git a/include/kernel/hardware/cpg.h b/include/kernel/hardware/cpg.h index 13363e2..e0ffe1e 100644 --- a/include/kernel/hardware/cpg.h +++ b/include/kernel/hardware/cpg.h @@ -3,8 +3,8 @@ #include #include -#include -#include +#include +#include struct SH7305_cpg_s { diff --git a/include/kernel/hardware/intc.h b/include/kernel/hardware/intc.h index f96c1b3..c630da1 100644 --- a/include/kernel/hardware/intc.h +++ b/include/kernel/hardware/intc.h @@ -1,12 +1,12 @@ -#ifndef __KERNEL_MODULES_SH7724_INTC_H__ -# define __KERNEL_MODULES_SH7724_INTC_H__ +#ifndef __KERNEL_HARDWARE_INTC_H__ +# define __KERNEL_HARDWARE_INTC_H__ #include #include -#include -#include +#include +#include -struct SH7305_intc_s +struct __sh7305_intc_s { //--- // Interrupt priority register. @@ -510,5 +510,29 @@ struct SH7305_intc_s ); }; -#define SH7305_INTC (*(volatile struct SH7305_intc_s *)0xa4080000) -#endif /*__KERNEL_MODULES_SH7724_INTC_H__*/ +struct __sh7305_intc_context +{ + uint16_t ipra; + uint16_t iprb; + uint16_t iprc; + uint16_t iprd; + uint16_t ipre; + uint16_t iprf; + uint16_t iprg; + uint16_t iprh; + uint16_t ipri; + uint16_t iprj; + uint16_t iprk; + uint16_t iprl; + uint8_t imr[12]; + uint16_t icr[2]; + uint32_t intpri00; + uint8_t intreq00; + uint8_t intmsk00; + uint8_t intmskclr00; + uint16_t nmifcr; + uint32_t usermsk; +} __attribute__((packed, aligned(2))); + +#define SH7305_INTC (*(volatile struct __sh7305_intc_s *)0xa4080000) +#endif /*__KERNEL_HARDWARE_INTC_H__*/ diff --git a/include/kernel/hardware/keysc.h b/include/kernel/hardware/keysc.h index 92dc9f9..037886c 100644 --- a/include/kernel/hardware/keysc.h +++ b/include/kernel/hardware/keysc.h @@ -1,12 +1,12 @@ -#ifndef __KERNEL_MODULES_SH7724_KEYSC_H__ -# define __KERNEL_MODULES_SH7724_KEYSC_H__ +#ifndef __KERNEL_HARDWARE_KEYSC_H__ +# define __KERNEL_HARDWARE_KEYSC_H__ #include #include -#include -#include +#include +#include -struct sh7305_keysc_s +struct __sh7305_keysc_s { volatile const uint16_t KIUDATA[6]; volatile word_union(CONTROL, @@ -61,6 +61,19 @@ struct sh7305_keysc_s ); }; -#define SH7305_KEYSC (*(volatile struct sh7305_keysc_s *)0xa44b0000) +struct __sh7305_keysc_context +{ + uint16_t control; + uint16_t autofix; + uint16_t scan_mode; + uint16_t scan_state; + uint16_t interrupt; + uint16_t scan_wait; + uint16_t scan_interval; + uint16_t kyoutdr; + uint16_t kyindr; +}; -#endif /*__KERNEL_MODULES_SH7724_KEYSC_H__*/ +#define SH7305_KEYSC (*(volatile struct __sh7305_keysc_s *)0xa44b0000) + +#endif /*__KERNEL_HARDWARE_KEYSC_H__*/ diff --git a/include/kernel/hardware/power.h b/include/kernel/hardware/power.h index e766d11..b9ca322 100644 --- a/include/kernel/hardware/power.h +++ b/include/kernel/hardware/power.h @@ -1,12 +1,12 @@ -#ifndef __KERNEL_MODULES_SH7724_STANDBY_H__ -# define __KERNEL_MODULES_SH7724_STANDBY_H__ +#ifndef __KERNEL_HARDWARE_POWER_H__ +# define __KERNEL_HARDWARE_POWER_H__ #include #include -#include -#include +#include +#include -struct power_s +struct __sh7305_power_s { volatile long_union(STBCR, /* Standby Control Register */ uint32_t const : 24; @@ -63,39 +63,46 @@ struct power_s volatile long_union(MSTPCR2, /* Module Stop Register 2 */ uint32_t const : 2; /* All 0 */ uint32_t MMC : 1; /* Multi Media Card Interface (?) */ - uint32_t EMAC : 1; /* Ether Controller */ + uint32_t const : 1; /* unknwon */ uint32_t const : 1; /* All 0 */ - uint32_t ATAPI : 1; /* ATAPI */ + uint32_t const : 1; /* unknown */ uint32_t TPU : 1; /* Timer Pulse Unit */ - uint32_t IrDA : 1; /* IrDA interface */ + uint32_t IrDA : 1; /* IrDA interface ? */ uint32_t const : 1; /* All 0 */ - uint32_t TSIF : 1; /* TS interface */ - uint32_t USB1 : 1; /* USB 1 */ + uint32_t const : 1; /* unknown */ + uint32_t const : 1; /* unknown */ uint32_t USB0 : 1; /* USB 0 */ - uint32_t _2DG : 1; /* 2D graphics accelerator */ - uint32_t SDHI0 : 1; /* SD card host */ - uint32_t SDHI1 : 1; /* IrDA interface */ + uint32_t const : 1; /* unknown */ + uint32_t SDHI0 : 1; /* SD card host 0 ? */ + uint32_t SDHI1 : 1; /* SD card host 1 ? */ uint32_t const : 1; /* All 0 */ - uint32_t VEU1 : 1; /* */ + uint32_t const : 1; /* unknown */ uint32_t const : 1; /* All 0 */ - uint32_t CEU1 : 1; /* */ - uint32_t BEU1 : 1; /* */ + uint32_t const : 1; /* unknown */ + uint32_t const : 1; /* unknown */ uint32_t const : 1; /* All 0 */ - uint32_t _2DDMAC: 1; /* */ - uint32_t SPU : 1; /* Sound Processing Unit */ - uint32_t const : 1; /* All 0 */ - uint32_t GCU : 1; /* */ - uint32_t JPU : 1; /* JPEG processing Unit */ - uint32_t VOU : 1; /* Video Output Unit */ - uint32_t BEU0 : 1; /* */ - uint32_t CEU0 : 1; /* */ - uint32_t VPU : 1; /* Video Processing Unit */ - uint32_t LCDC : 1; /* LCD controller */ + uint32_t const : 1; /* unknown */ + uint32_t SPU : 1; /* Sound Processing Unit ? */ + uint32_t const : 1; /* all 0 */ + uint32_t const : 1; /* unknown */ + uint32_t LCD : 1; /* LCD driver */ + uint32_t const : 1; /* unknown */ + uint32_t const : 1; /* unknown */ + uint32_t const : 1; /* unknown */ + uint32_t const : 1; /* unknown */ + uint32_t LCDC : 1; /* LCD controller ? */ ); GAPS(4); - volatile uint32_t const BAR; /* Boot Address Register */ + volatile uint32_t BAR; /* Boot Address Register */ }; -#define SH7305_POWER (*(volatile struct power_s *)0xa4150020) +struct __sh7305_power_context +{ + uint32_t stbcr; + uint32_t mstpcr[3]; + uint32_t bar; +}; -#endif /*__KERNEL_MODULES_SH7724_STANDBY_H__*/ +#define SH7305_POWER (*(volatile struct __sh7305_power_s *)0xa4150020) + +#endif /*__KERNEL_HARDWARE_POWER_H__*/ diff --git a/include/kernel/hardware/tmu.h b/include/kernel/hardware/tmu.h index 7a36b6c..834105a 100644 --- a/include/kernel/hardware/tmu.h +++ b/include/kernel/hardware/tmu.h @@ -3,8 +3,18 @@ #include #include -#include -#include +#include +#include + +struct __sh7305_tmu_context +{ + uint8_t tstr; + struct { + uint32_t tcor; + uint32_t tcnt; + uint16_t tcr; + } timer[3]; +}; struct timer_s { diff --git a/include/kernel/hardware/ubc.h b/include/kernel/hardware/ubc.h index 7d05e70..0614f4b 100644 --- a/include/kernel/hardware/ubc.h +++ b/include/kernel/hardware/ubc.h @@ -3,8 +3,8 @@ #include #include -#include -#include +#include +#include struct sh7305_ubc_s { diff --git a/include/kernel/process.h b/include/kernel/process.h index 84ebadb..214109e 100644 --- a/include/kernel/process.h +++ b/include/kernel/process.h @@ -5,7 +5,7 @@ #include #include #include -#include +#include #include #include @@ -33,7 +33,7 @@ struct process //--- // Context management //--- - common_context_t context; + struct cpu_context context; //--- diff --git a/include/kernel/scheduler.h b/include/kernel/scheduler.h index 48f252d..92205ca 100644 --- a/include/kernel/scheduler.h +++ b/include/kernel/scheduler.h @@ -4,6 +4,7 @@ #include #include #include +#include // Define the number of task #define SCHED_TASK_NB_MAX PROCESS_MAX @@ -78,12 +79,12 @@ extern void sched_start(void); ** Get the current task context and the next one ** based on internal task priority / status. */ -extern int sched_schedule(common_context_t **current, common_context_t **next); +extern int sched_schedule(struct cpu_context **current, struct cpu_context **next); /* ** Internal function wich will switch current process ** context with the next context */ -extern void sched_context_switch(common_context_t *current, common_context_t *next); +extern void sched_context_switch(struct cpu_context *current, struct cpu_context *next); #endif /*__KERNEL_SHEDULER_H__*/ diff --git a/include/kernel/util/casio.h b/include/kernel/util/casio.h index 73c1f16..e783c50 100644 --- a/include/kernel/util/casio.h +++ b/include/kernel/util/casio.h @@ -4,6 +4,13 @@ #include #include +//--- +// Casio's wrapper +//--- +extern void casio_return_menu(int mode); + + + // Internal Casio datat structure struct rect { @@ -13,6 +20,11 @@ struct rect int bottom; }; +// GetKeyWait macros +#define KEYWAIT_HALTON_TIMEROFF 0 +#define KEYWAIT_HALTOFF_TIMEROFF 1 +#define KEYWAIT_HALTON_TIMERON 2 + // // Casio prototypes. // @@ -60,6 +72,12 @@ static inline void dclear_area(int x1, int y1, int x2, int y2) casio_Bdisp_AreaClr_VRAM(&area); } +// Timer syscalls +extern int casio_TimerInstall(int id, void (*handler)(void), int delay_ms); +extern int casio_TimerUninstall(int id); +extern int casio_TimerStart(int id); +extern int casio_TimerStop(int id); + #endif /*__KERNEL_UTIL_CASIO_H__*/ diff --git a/src/kernel/bootstrap/driver.c b/src/kernel/bootstrap/driver.c new file mode 100644 index 0000000..f7bd946 --- /dev/null +++ b/src/kernel/bootstrap/driver.c @@ -0,0 +1,85 @@ +#include +#include +#include +#include +#include +#include + +// Internal bootstrap funtions +extern mpu_t mpu_get(void); + +//TODO: secure if no driver is found !! +void bootstrap_drivers_install(void) +{ + extern uint32_t bdrivers_section; + extern uint32_t edrivers_section; + struct driver *driver; + mpu_t mpu; + int i; + + // Start atomic operations + earlyterm_write("Load drivers...\n"); + atomic_start(); + + i = -1; + mpu = mpu_get(); + driver = (void *)&bdrivers_section; + while ((uint32_t)&driver[++i] < (uint32_t)&edrivers_section) + { + // Check driver + if (driver[i].arch != mpu) + continue; + + // Check driver integrity + if (driver[i].install == NULL || driver[i].uninstall == NULL) { + earlyterm_write("* WARNING - driver integrity [%s]\n", driver[i].name); + continue; + } + + // Try to install the driver + // TODO: check driver error ? + earlyterm_write("* install driver [%s]\n", driver[i].name); + (*driver[i].install)(); + } + + // Stop atomic operations + atomic_stop(); +} + +void bootstrap_drivers_uninstall(void) +{ + extern uint32_t bdrivers_section; + extern uint32_t edrivers_section; + struct driver *driver; + mpu_t mpu; + int i; + + // Start atomic operations + earlyterm_write("Unload drivers...\n"); + atomic_start(); + + // Uninstall driver (fifo style) + mpu = mpu_get(); + driver = (void *)&bdrivers_section; + i = ((uint32_t)&edrivers_section - (uint32_t)&bdrivers_section) / sizeof(struct driver); + while (--i >= 0) + { + // Check driver + if (driver[i].arch != mpu) + continue; + + // Check driver integrity + if (driver[i].install == NULL || driver[i].uninstall == NULL) { + earlyterm_write("* WARNING - driver integrity [%s]\n", driver[i].name); + continue; + } + + // Try to uninstall the driver + // TODO: check driver error ? + earlyterm_write("* uninstall driver [%s]\n", driver[i].name); + (*driver[i].uninstall)(); + } + + // Stop atomic operations + atomic_stop(); +} diff --git a/src/kernel/bootstrap/filesystem.c b/src/kernel/bootstrap/filesystem.c new file mode 100644 index 0000000..8f13006 --- /dev/null +++ b/src/kernel/bootstrap/filesystem.c @@ -0,0 +1,39 @@ +#include +#include +#include +#include +#include +#include + +//--- +// Initialize File System and Virtual File System ! +//--- +void bootstrap_filesystem_init(void) +{ + extern struct file_system_type gladfs_filesystem; + extern struct file_system_type smemfs_filesystem; + + // Internal FS init ! + earlyterm_write("Initialize File System...\n"); + gladfs_initialize(); + smemfs_initialize(); + + // Initialize Virtual File System + earlyterm_write("Init. Virtual File System...\n"); + vfs_register_filesystem(&gladfs_filesystem); + vfs_register_filesystem(&smemfs_filesystem); + + // Creat initial FileSystem Hierarchy + earlyterm_write("Create Filesystem Hierarchy...\n"); + vfs_mount(NULL, NULL, "gladfs", VFS_MOUNT_ROOT, NULL); + vfs_mkdir("/dev", S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); + vfs_mkdir("/home", S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); + vfs_mkdir("/mnt", S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); + vfs_mkdir("/mnt/casio", S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); + vfs_mount(NULL, "/mnt/casio", "smemfs", /*MS_RDONLY*/0, NULL); + + // Add devices + earlyterm_write("Add devices...\n"); + vfs_mknod("/dev/tty", S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, + dev_make_major(TTY_DEV_MAJOR)); +} diff --git a/src/kernel/bootstrap/mpu.c b/src/kernel/bootstrap/mpu.c index 67a685d..abafc8c 100644 --- a/src/kernel/bootstrap/mpu.c +++ b/src/kernel/bootstrap/mpu.c @@ -1,5 +1,8 @@ #include -#include +#include + +// Internal symbols +mpu_t current_mpu = MPU_UNKNOWN; /* check_sh3 - Detecting sh3-based MPU */ static mpu_t check_sh3(uint16_t tplcr) @@ -50,7 +53,10 @@ mpu_t mpu_get(void) volatile uint16_t *plcr = (void *)0xa4000114; uint16_t splcr; uint16_t tplcr; - mpu_t mpu; + + // Check if the MPU is already find + if (current_mpu != MPU_UNKNOWN) + return (current_mpu); // Check port L control register. splcr = *plcr; @@ -58,8 +64,9 @@ mpu_t mpu_get(void) tplcr = *plcr; *plcr = splcr; - mpu = check_sh3(tplcr); - if (mpu != MPU_UNKNOWN) - return (mpu); - return (check_sh4()); + // Check MPU arch + current_mpu = check_sh3(tplcr); + if (current_mpu == MPU_UNKNOWN) + current_mpu = check_sh4(); + return (current_mpu); } diff --git a/src/kernel/bootstrap/start.c b/src/kernel/bootstrap/start.c index f276fac..011b0a1 100644 --- a/src/kernel/bootstrap/start.c +++ b/src/kernel/bootstrap/start.c @@ -1,48 +1,29 @@ +// Types #include #include #include -// Hardware -#include +#include // Internal helpers #include #include // Modules -#include +#include #include #include #include #include // Devices -#include #include -// File System -#include -#include -#include -#include // Libs #include #include -// Internal symbols -mpu_t current_mpu = MPU_UNKNOWN; - -// Internal hardware context. -fx9860_context_t casio_context; -fx9860_context_t vhex_context; - // Symbols defined by the linker extern uint32_t bbss; extern uint32_t sbss; extern uint32_t bdata_ram; extern uint32_t bdata_rom; extern uint32_t sdata; -extern uint32_t bvhex_ram; -extern uint32_t bvhex_rom; -extern uint32_t svhex; -extern uint32_t bubc_ram; -extern uint32_t bubc_rom; -extern uint32_t subc; extern uint32_t brom; extern uint32_t srom; extern uint32_t bctors; @@ -50,16 +31,10 @@ extern uint32_t ectors; extern uint32_t bdtors; extern uint32_t edtors; -// Internal functions. -extern void vhex_context_set(void); -extern void kernel_switch(common_context_t *context); +// Internal bootstrap funtions extern mpu_t mpu_get(void); -extern int main(void); - -// Internal object -extern struct file_system_type gladfs_filesystem; -extern struct file_system_type smemfs_filesystem; - +extern void bootstrap_drivers_install(void); +extern void bootstrap_filesystem_init(void); // // rom_explore() - explore all add-in ROM part. @@ -93,37 +68,19 @@ static void section_execute(void *bsection, void *esection) } } - /* start() - Kernel entry point */ __attribute__((section(".pretext"))) int start(void) { - //-- - // Bootstrap part ! - //-- + // Casio do not load all add-in page and we can not use the MMU. + // So we need to "force" update TLB before switching the VBR to + // avoid TLB miss exception that we can not handle for now. + rom_explore(&brom, (int32_t)&srom); // Wipe .bss section and dump .data / Vhex sections memset(&bbss, 0x00, (size_t)&sbss); memcpy(&bdata_ram, &bdata_rom, (size_t)&sdata); - // Check MPU hardware. - current_mpu = mpu_get(); - if (current_mpu != MPU_SH7305) - return (0); - - // Load UBC / VBR space. - memcpy(&bubc_ram, &bubc_rom, (size_t)&subc); - memcpy(&bvhex_ram, &bvhex_rom, (size_t)&svhex); - - // Casio do not load all add-in - // page. So we need to "force" update TLB - // before switching the VBR. - rom_explore(&brom, (int32_t)&srom); - - // TODO: load driver on-the-fly - extern void screen_driver_load(void); - screen_driver_load(); - // Start early terminal device // This device is used by the kernel to display // some logs on screen @@ -132,59 +89,23 @@ int start(void) earlyterm_clear(); earlyterm_write("Kernel initialisation...\n"); + // Load all drivers on-the-fly + bootstrap_drivers_install(); + // Execute constructor. + // FIXME: remove me ? section_execute(&bctors, &ectors); - - // Save Casio's hardware context and set - // Vhex hardware context. - // @note: - // This operation should be atomic - // because if an interruption or exception - // occur during the hardware context change - // the calculator will crash. - // And this is why between each `atomic_start` - // and `atomic_end()` the code *SHOULD* be - // exception safe. - earlyterm_write("Environment switch...\n"); - atomic_start(); - fx9860_context_save(&casio_context); - vhex_context_set(); - atomic_stop(); - - //--- - // File System part ! - //--- - - // Internal FS init ! - earlyterm_write("Initialize File System...\n"); - gladfs_initialize(); - smemfs_initialize(); - - // Initilize Virtual File System - earlyterm_write("Init. Virtual File System...\n"); - vfs_register_filesystem(&gladfs_filesystem); - vfs_register_filesystem(&smemfs_filesystem); - - // Creat initial file tree - earlyterm_write("Create Filesystem Hierarchy...\n"); - vfs_mount(NULL, NULL, "gladfs", VFS_MOUNT_ROOT, NULL); - vfs_mkdir("/dev", S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); - vfs_mkdir("/home", S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); - vfs_mkdir("/mnt", S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); - vfs_mkdir("/mnt/casio", S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); - vfs_mount(NULL, "/mnt/casio", "smemfs", /*MS_RDONLY*/0, NULL); - - // Add devices - earlyterm_write("Add devices...\n"); - vfs_mknod("/dev/tty", S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, - dev_make_major(TTY_DEV_MAJOR)); + // Initialize all File Systems and Virtual File System + // TODO: rename into initramfs ? + bootstrap_filesystem_init(); //--- // Start first process ! //--- + //TODO: move me !! // Load programe. earlyterm_write("Create first process...\n"); @@ -201,29 +122,15 @@ int start(void) earlyterm_write("File \"VHEX/shell.elf\" not found !\n"); earlyterm_write("Press [MENU key]...\n"); - // Restore Casio context. - fx9860_context_restore(&casio_context); - atomic_stop(); - - // Casio VRAM workaround - // @note: GetKey will call Bdisp_PutDD_VRAM(), - // so save the current internal Video RAM data into - // Casio's VRAM. - extern struct earlyterm earlyterm; - memcpy(casio_Bdisp_GetVRAM(), earlyterm.display.vram, 1024); - - // Wait MENU key. - unsigned int key; - while (1) - { - casio_GetKey(&key); - } + // Restore Casio's context and wait MENU key + casio_return_menu(1); } //--- // Initialize sheduler !! //--- + //TODO: move me ? earlyterm_write("Initialize scheduler...\n"); sched_initialize(); sched_task_add(vhex_process); diff --git a/src/kernel/context/fx9860/restore.c b/src/kernel/context/fx9860/restore.c deleted file mode 100644 index aa449f9..0000000 --- a/src/kernel/context/fx9860/restore.c +++ /dev/null @@ -1,56 +0,0 @@ -#include -#include -#include -#include -#include -#include - -void fx9860_context_restore(fx9860_context_t *context) -{ - // Restore VBR. - vbr_set((void*)context->vbr); - - // Restore TMU context. - SH7305_TMU.TSTR.BYTE = 0x00; // stop all timer. - SH7305_TMU.TIMER[0].TCOR = context->tmu.timer[0].tcor; - SH7305_TMU.TIMER[0].TCNT = context->tmu.timer[0].tcnt; - SH7305_TMU.TIMER[0].TCR.WORD = context->tmu.timer[0].tcr; - SH7305_TMU.TIMER[1].TCOR = context->tmu.timer[1].tcor; - SH7305_TMU.TIMER[1].TCNT = context->tmu.timer[1].tcnt; - SH7305_TMU.TIMER[1].TCR.WORD = context->tmu.timer[1].tcr; - SH7305_TMU.TIMER[2].TCOR = context->tmu.timer[2].tcor; - SH7305_TMU.TIMER[2].TCNT = context->tmu.timer[2].tcnt; - SH7305_TMU.TIMER[2].TCR.WORD = context->tmu.timer[2].tcr; - SH7305_TMU.TSTR.BYTE = context->tmu.tstr; - - // Restore power context. - SH7305_POWER.STBCR.LONG_WORD = context->power.stbcr; - SH7305_POWER.MSTPCR0.LONG_WORD = context->power.mstpcr0; - SH7305_POWER.MSTPCR1.LONG_WORD = context->power.mstpcr1; - SH7305_POWER.MSTPCR2.LONG_WORD = context->power.mstpcr2; - - // Restore Key Scan (KEYSC) context. - SH7305_KEYSC.CONTROL.WORD = context->keyboard.control; - SH7305_KEYSC.AUTOFIX.WORD = context->keyboard.autofix; - SH7305_KEYSC.SCAN_MODE.WORD = context->keyboard.scan_mode; - SH7305_KEYSC.SCAN_STATE.WORD = context->keyboard.scan_state; - SH7305_KEYSC.INTERRUPT.WORD = context->keyboard.interrupt; - SH7305_KEYSC.SCAN_WAIT.WORD = context->keyboard.scan_wait; - SH7305_KEYSC.SCAN_INTERVAL = context->keyboard.scan_interval; - SH7305_KEYSC.KYOUTDR.WORD = context->keyboard.kyoutdr; - SH7305_KEYSC.KYINDR.WORD = context->keyboard.kyindr; - - // Restore Interrupt Controller (INTC) - SH7305_INTC.IPRA.WORD = context->intc.ipra; - SH7305_INTC.IPRB.WORD = context->intc.iprb; - SH7305_INTC.IPRC.WORD = context->intc.iprc; - SH7305_INTC.IPRD.WORD = context->intc.iprd; - SH7305_INTC.IPRE.WORD = context->intc.ipre; - SH7305_INTC.IPRF.WORD = context->intc.iprf; - SH7305_INTC.IPRG.WORD = context->intc.iprg; - SH7305_INTC.IPRH.WORD = context->intc.iprh; - SH7305_INTC.IPRI.WORD = context->intc.ipri; - SH7305_INTC.IPRJ.WORD = context->intc.iprj; - SH7305_INTC.IPRK.WORD = context->intc.iprk; - SH7305_INTC.IPRL.WORD = context->intc.iprl; -} diff --git a/src/kernel/context/fx9860/save.c b/src/kernel/context/fx9860/save.c deleted file mode 100644 index aba7cfe..0000000 --- a/src/kernel/context/fx9860/save.c +++ /dev/null @@ -1,57 +0,0 @@ -#include -#include -#include -#include -#include -#include - -void fx9860_context_save(fx9860_context_t *context) -{ - // Save Interrupt Controller (INTC) - context->intc.ipra = SH7305_INTC.IPRA.WORD; - context->intc.iprb = SH7305_INTC.IPRB.WORD; - context->intc.iprc = SH7305_INTC.IPRC.WORD; - context->intc.iprd = SH7305_INTC.IPRD.WORD; - context->intc.ipre = SH7305_INTC.IPRE.WORD; - context->intc.iprf = SH7305_INTC.IPRF.WORD; - context->intc.iprg = SH7305_INTC.IPRG.WORD; - context->intc.iprh = SH7305_INTC.IPRH.WORD; - context->intc.ipri = SH7305_INTC.IPRI.WORD; - context->intc.iprj = SH7305_INTC.IPRJ.WORD; - context->intc.iprk = SH7305_INTC.IPRK.WORD; - context->intc.iprl = SH7305_INTC.IPRL.WORD; - - // Save Key Scan (KEYSC) context. - context->keyboard.control = SH7305_KEYSC.CONTROL.WORD; - context->keyboard.autofix = SH7305_KEYSC.AUTOFIX.WORD; - context->keyboard.scan_mode = SH7305_KEYSC.SCAN_MODE.WORD; - context->keyboard.scan_state = SH7305_KEYSC.SCAN_STATE.WORD; - context->keyboard.interrupt = SH7305_KEYSC.INTERRUPT.WORD; - context->keyboard.scan_wait = SH7305_KEYSC.SCAN_WAIT.WORD; - context->keyboard.scan_interval = SH7305_KEYSC.SCAN_INTERVAL; - context->keyboard.kyoutdr = SH7305_KEYSC.KYOUTDR.WORD; - context->keyboard.kyindr = SH7305_KEYSC.KYINDR.WORD; - - // Save power context. - context->power.stbcr = SH7305_POWER.STBCR.LONG_WORD; - context->power.mstpcr0 = SH7305_POWER.MSTPCR0.LONG_WORD; - context->power.mstpcr1 = SH7305_POWER.MSTPCR1.LONG_WORD; - context->power.mstpcr2 = SH7305_POWER.MSTPCR2.LONG_WORD; - - // Save TMU context. - context->tmu.tstr = SH7305_TMU.TSTR.BYTE; - SH7305_TMU.TSTR.BYTE = 0x00; // stop all timer. - context->tmu.timer[0].tcor = SH7305_TMU.TIMER[0].TCOR; - context->tmu.timer[0].tcnt = SH7305_TMU.TIMER[0].TCNT; - context->tmu.timer[0].tcr = SH7305_TMU.TIMER[0].TCR.WORD; - context->tmu.timer[1].tcor = SH7305_TMU.TIMER[1].TCOR; - context->tmu.timer[1].tcnt = SH7305_TMU.TIMER[1].TCNT; - context->tmu.timer[1].tcr = SH7305_TMU.TIMER[1].TCR.WORD; - context->tmu.timer[2].tcor = SH7305_TMU.TIMER[2].TCOR; - context->tmu.timer[2].tcnt = SH7305_TMU.TIMER[2].TCNT; - context->tmu.timer[2].tcr = SH7305_TMU.TIMER[2].TCR.WORD; - - // Save current VBR. - context->vbr = (uint32_t)vbr_get(); -} - diff --git a/src/kernel/devices/tty/operations/read.c b/src/kernel/devices/tty/operations/read.c index bee9a39..5d7e113 100644 --- a/src/kernel/devices/tty/operations/read.c +++ b/src/kernel/devices/tty/operations/read.c @@ -1,10 +1,7 @@ #include -#include #include #include #include -#include -#include #include #include #include diff --git a/src/kernel/devices/tty/utils/keyboard/check.c b/src/kernel/devices/tty/utils/keyboard/check.c index 64baad4..8df9210 100644 --- a/src/kernel/devices/tty/utils/keyboard/check.c +++ b/src/kernel/devices/tty/utils/keyboard/check.c @@ -43,13 +43,10 @@ void tty_keyboard_check_signal(struct tty *tty) } -//TODO update ? +//TODO update me //@note: Call this function ONLY if the device is locked !! int tty_keyboard_check_special(struct tty *tty, key_t key) { - extern fx9860_context_t casio_context; - extern fx9860_context_t vhex_context; - // Check CTRL key (KEY_OPT) if (key == KEY_OPTN) { tty->keyboard.mode.ctrl = 1; @@ -81,25 +78,8 @@ int tty_keyboard_check_special(struct tty *tty, key_t key) } // Check MENU key. - // TODO: fix me ! - if (key == KEY_MENU) - { - // Save current Vhex context and restore Casio's context. - atomic_start(); - fx9860_context_save(&vhex_context); - fx9860_context_restore(&casio_context); - atomic_stop(); - - // Inject MENU key and call GetKey(). - // FIXME !!! - //casio_GetKeyWait(&row, &column, 0, 0, 0, &key); - casio_GetKey(&key); - - // Save current Casio's context and restore Vhex's context. - atomic_start(); - fx9860_context_save(&casio_context); - fx9860_context_restore(&vhex_context); - atomic_stop(); + if (key == KEY_MENU) { + casio_return_menu(0); return (1); } diff --git a/src/kernel/drivers/cpg/constructor.c b/src/kernel/drivers/cpg/driver.c similarity index 77% rename from src/kernel/drivers/cpg/constructor.c rename to src/kernel/drivers/cpg/driver.c index 203da42..4ef1ddb 100644 --- a/src/kernel/drivers/cpg/constructor.c +++ b/src/kernel/drivers/cpg/driver.c @@ -1,12 +1,12 @@ #include #include -#include +#include // Internal struct struct cpg cpg_info; -__attribute__((constructor)) -static void cpg_init(void) +// @note: we just get the frequencies +static void sh7305_cpg_driver_install(void) { // Calculate FLL frequency (Khz) // @note: RCLK = 32 768 Hz @@ -27,7 +27,8 @@ static void cpg_init(void) // Debug - earlyterm_write("Calibrate frequencies...\n"); + // TODO: device + /*earlyterm_write("Calibrate frequencies...\n"); earlyterm_write( "* FLL freq: %d.%d Mhz\n" "* PLL freq: %d.%d Mhz\n" @@ -39,6 +40,18 @@ static void cpg_init(void) cpg_info.cpu_freq / 1000000, (((cpg_info.cpu_freq - ((cpg_info.cpu_freq / 1000000)) * 1000000)) + 999) / 1000, cpg_info.bus_freq / 1000000, (((cpg_info.bus_freq - ((cpg_info.bus_freq / 1000000)) * 1000000)) + 999) / 1000, cpg_info.per_freq / 1000000, (((cpg_info.per_freq - ((cpg_info.per_freq / 1000000)) * 1000000)) + 999) / 1000 - ); - DBG_WAIT; + );*/ } + +static void sh7305_cpg_driver_uninstall(void) +{ + // Nothing for now +} + +// Create driver object +VHEX_DRIVER(2, driver_cpg_sh7305) = { + .arch = MPU_SH7305, + .install = &sh7305_cpg_driver_install, + .uninstall = &sh7305_cpg_driver_uninstall, + .name = "cpg" +}; diff --git a/src/kernel/drivers/intc/driver.c b/src/kernel/drivers/intc/driver.c new file mode 100644 index 0000000..2528a1c --- /dev/null +++ b/src/kernel/drivers/intc/driver.c @@ -0,0 +1,138 @@ +#include +#include + +// Internal hardware context +struct __sh7305_intc_context intc_context; + +static void sh7305_intc_driver_install(void) +{ + // Dump current context + intc_context.ipra = SH7305_INTC.IPRA.WORD; + intc_context.iprb = SH7305_INTC.IPRB.WORD; + intc_context.iprc = SH7305_INTC.IPRC.WORD; + intc_context.iprd = SH7305_INTC.IPRD.WORD; + intc_context.ipre = SH7305_INTC.IPRE.WORD; + intc_context.iprf = SH7305_INTC.IPRF.WORD; + intc_context.iprg = SH7305_INTC.IPRG.WORD; + intc_context.iprh = SH7305_INTC.IPRH.WORD; + intc_context.ipri = SH7305_INTC.IPRI.WORD; + intc_context.iprj = SH7305_INTC.IPRJ.WORD; + intc_context.iprk = SH7305_INTC.IPRK.WORD; + intc_context.iprl = SH7305_INTC.IPRL.WORD; + intc_context.imr[0] = SH7305_INTC.IMR0.BYTE; + intc_context.imr[1] = SH7305_INTC.IMR1.BYTE; + intc_context.imr[2] = SH7305_INTC.IMR2.BYTE; + intc_context.imr[3] = SH7305_INTC.IMR3.BYTE; + intc_context.imr[4] = SH7305_INTC.IMR4.BYTE; + intc_context.imr[5] = SH7305_INTC.IMR5.BYTE; + intc_context.imr[6] = SH7305_INTC.IMR6.BYTE; + intc_context.imr[7] = SH7305_INTC.IMR7.BYTE; + intc_context.imr[8] = SH7305_INTC.IMR8.BYTE; + intc_context.imr[9] = SH7305_INTC.IMR9.BYTE; + intc_context.imr[10] = SH7305_INTC.IMR10.BYTE; + intc_context.imr[11] = SH7305_INTC.IMR11.BYTE; + intc_context.icr[0] = SH7305_INTC.ICR0.WORD; + intc_context.icr[1] = SH7305_INTC.ICR1.WORD; + intc_context.intpri00 = SH7305_INTC.INTPRI00.LONG_WORD; + intc_context.intreq00 = SH7305_INTC.INTREQ00.BYTE; + intc_context.intmsk00 = SH7305_INTC.INTMSK00.BYTE; + intc_context.intmskclr00 = SH7305_INTC.INTMSKCLR00.BYTE; + intc_context.nmifcr = SH7305_INTC.NMIFCR.WORD; + intc_context.usermsk = SH7305_INTC.USERMSK.LONG_WORD; + + // Initialize Interrupt Controller (INTC). + SH7305_INTC.IPRA.WORD = 0x0000; + SH7305_INTC.IPRB.WORD = 0x0000; + SH7305_INTC.IPRC.WORD = 0x0000; + SH7305_INTC.IPRD.WORD = 0x0000; + SH7305_INTC.IPRE.WORD = 0x0000; + SH7305_INTC.IPRF.WORD = 0x0000; + SH7305_INTC.IPRG.WORD = 0x0000; + SH7305_INTC.IPRH.WORD = 0x0000; + SH7305_INTC.IPRI.WORD = 0x0000; + SH7305_INTC.IPRJ.WORD = 0x0000; + SH7305_INTC.IPRK.WORD = 0x0000; + SH7305_INTC.IPRL.WORD = 0x0000; + + SH7305_INTC.IMR0.BYTE = 0xff; + SH7305_INTC.IMR1.BYTE = 0xff; + SH7305_INTC.IMR2.BYTE = 0xff; + SH7305_INTC.IMR3.BYTE = 0xff; + SH7305_INTC.IMR4.BYTE = 0xff; + SH7305_INTC.IMR5.BYTE = 0xff; + SH7305_INTC.IMR6.BYTE = 0xff; + SH7305_INTC.IMR7.BYTE = 0xff; + SH7305_INTC.IMR8.BYTE = 0xff; + SH7305_INTC.IMR9.BYTE = 0xff; + SH7305_INTC.IMR10.BYTE = 0xff; + SH7305_INTC.IMR11.BYTE = 0xff; + + SH7305_INTC.ICR0.NMIL = 0; // NMI input level to low + SH7305_INTC.ICR0.MAI = 1; // disable NMI interrupt when input is low + SH7305_INTC.ICR0.NMIB = 0; // keep NMI interrupt pending when BL bit is set + SH7305_INTC.ICR0.NMIE = 0; // select faling edge interrupt + SH7305_INTC.ICR0.LVLMODE = 1; // retain interrupt request + SH7305_INTC.ICR1.WORD = 0x0000; // select (all) interrupt request on falling edge + SH7305_INTC.INTPRI00.LONG_WORD = 0x00000000; // disable all interrupt request + SH7305_INTC.INTMSK00.BYTE = 0x00; // mask all interrupt request + SH7305_INTC.NMIFCR.NMIFL = 0; // clear NMI flags + + SH7305_INTC.USERMSK.SECRET = 0xa5; // secret + SH7305_INTC.USERMSK.UIMASK = 0b0000; // enable all interrupt in user mode (not used here) +} + +static void sh7305_intc_driver_uninstall(void) +{ + SH7305_INTC.IPRA.WORD = intc_context.ipra; + SH7305_INTC.IPRB.WORD = intc_context.iprb; + SH7305_INTC.IPRC.WORD = intc_context.iprc; + SH7305_INTC.IPRD.WORD = intc_context.iprd; + SH7305_INTC.IPRE.WORD = intc_context.ipre; + SH7305_INTC.IPRF.WORD = intc_context.iprf; + SH7305_INTC.IPRG.WORD = intc_context.iprg; + SH7305_INTC.IPRH.WORD = intc_context.iprh; + SH7305_INTC.IPRI.WORD = intc_context.ipri; + SH7305_INTC.IPRJ.WORD = intc_context.iprj; + SH7305_INTC.IPRK.WORD = intc_context.iprk; + SH7305_INTC.IPRL.WORD = intc_context.iprl; + SH7305_INTC.IMR0.BYTE = intc_context.imr[0]; + SH7305_INTC.IMR1.BYTE = intc_context.imr[1]; + SH7305_INTC.IMR2.BYTE = intc_context.imr[2]; + SH7305_INTC.IMR3.BYTE = intc_context.imr[3]; + SH7305_INTC.IMR4.BYTE = intc_context.imr[4]; + SH7305_INTC.IMR5.BYTE = intc_context.imr[5]; + SH7305_INTC.IMR6.BYTE = intc_context.imr[6]; + SH7305_INTC.IMR7.BYTE = intc_context.imr[7]; + SH7305_INTC.IMR8.BYTE = intc_context.imr[8]; + SH7305_INTC.IMR9.BYTE = intc_context.imr[9]; + SH7305_INTC.IMR10.BYTE = intc_context.imr[10]; + SH7305_INTC.IMR11.BYTE = intc_context.imr[11]; + SH7305_INTC.IMCR0.BYTE = ~intc_context.imr[0]; + SH7305_INTC.IMCR1.BYTE = ~intc_context.imr[1]; + SH7305_INTC.IMCR2.BYTE = ~intc_context.imr[2]; + SH7305_INTC.IMCR3.BYTE = ~intc_context.imr[3]; + SH7305_INTC.IMCR4.BYTE = ~intc_context.imr[4]; + SH7305_INTC.IMCR5.BYTE = ~intc_context.imr[5]; + SH7305_INTC.IMCR6.BYTE = ~intc_context.imr[6]; + SH7305_INTC.IMCR7.BYTE = ~intc_context.imr[7]; + SH7305_INTC.IMCR8.BYTE = ~intc_context.imr[8]; + SH7305_INTC.IMCR9.BYTE = ~intc_context.imr[9]; + SH7305_INTC.IMCR10.BYTE = intc_context.imr[10]; + SH7305_INTC.IMCR11.BYTE = intc_context.imr[11]; + SH7305_INTC.ICR0.WORD = intc_context.icr[0]; + SH7305_INTC.ICR1.WORD = intc_context.icr[1]; + SH7305_INTC.INTPRI00.LONG_WORD = intc_context.intpri00; + SH7305_INTC.INTREQ00.BYTE = intc_context.intreq00; + SH7305_INTC.INTMSK00.BYTE = intc_context.intmsk00; + SH7305_INTC.INTMSKCLR00.BYTE = intc_context.intmskclr00; + SH7305_INTC.NMIFCR.WORD = intc_context.nmifcr; + SH7305_INTC.USERMSK.LONG_WORD = intc_context.usermsk; +} + +// Create driver object +VHEX_DRIVER(2, driver_intc_sh7305) = { + .arch = MPU_SH7305, + .install = &sh7305_intc_driver_install, + .uninstall = &sh7305_intc_driver_uninstall, + .name = "cpg" +}; diff --git a/src/kernel/drivers/keyboard/contructor.c b/src/kernel/drivers/keyboard/contructor.c deleted file mode 100644 index 5f832cd..0000000 --- a/src/kernel/drivers/keyboard/contructor.c +++ /dev/null @@ -1,34 +0,0 @@ -#include - -/* -** Internal cache, used like chained list. -** -** @note: -** The KEYSC have 6 key data 16-bits registers -** this is why we used 6 * 16 = 96 cache slot. -*/ -struct keycache_s keycache[96]; -struct keycache_s *keylist; - -/* -** keycache_init() -** -** @info -** Constructor used by the kernel during the -** bootstrap part. It will initialize keycache -** and the chained list. -** This function sould not be called anymore. -*/ -__attribute__((constructor)) -static void keycache_init(void) -{ - int i; - - i = 96; - while (--i >= 0) - { - keycache[i].keycode = KEY_UNUSED; - keycache[i].next = NULL; - } - keylist = NULL; -} diff --git a/src/kernel/bootstrap/vhex.c b/src/kernel/drivers/keyboard/hardware/sh7305/driver.c similarity index 50% rename from src/kernel/bootstrap/vhex.c rename to src/kernel/drivers/keyboard/hardware/sh7305/driver.c index 033c0e3..188f371 100644 --- a/src/kernel/bootstrap/vhex.c +++ b/src/kernel/drivers/keyboard/hardware/sh7305/driver.c @@ -1,47 +1,40 @@ -#include -#include +#include +#include #include #include -#include -#include -#include +#include -void vhex_context_set(void) +// Internal module functions +extern void sh7305_keysc_int_handler(void); + +// Internal hardware context +struct __sh7305_keysc_context keysc_context; + +// Configure Key Scan (KEYSC) +static void sh7305_keysc_driver_install(void) { - extern uint32_t vhex_vbr; - - // Initialize Interrupt Controller (INTC). - SH7305_INTC.IPRA.WORD = 0x0000; - SH7305_INTC.IPRB.WORD = 0x0000; - SH7305_INTC.IPRC.WORD = 0x0000; - SH7305_INTC.IPRD.WORD = 0x0000; - SH7305_INTC.IPRE.WORD = 0x0000; - SH7305_INTC.IPRF.WORD = 0x0000; - SH7305_INTC.IPRG.WORD = 0x0000; - SH7305_INTC.IPRH.WORD = 0x0000; - SH7305_INTC.IPRI.WORD = 0x0000; - SH7305_INTC.IPRJ.WORD = 0x0000; - SH7305_INTC.IPRK.WORD = 0x0000; - SH7305_INTC.IPRL.WORD = 0x0000; - - // Switch VBR - // @note: - // The VBR swtich *SHOULD* be atomic - // because one exepction / interrupt will - // crash the calculator. - vbr_set(&vhex_vbr); - - // Configure Key Scan (KEYSC) + // Mask interrupt (requered) SH7305_INTC.IMR5.KEYI = 1; // Mask KEYSC interrupt. SH7305_INTC.IPRF.KEYSC = 0; // Disable KEYSC interrupt. - SH7305_TMU.TIMER[0].TCOR = 0xffffffff; // Disable Timer 2 + + // Save current keysc context + keysc_context.control = SH7305_KEYSC.CONTROL.WORD; + keysc_context.autofix = SH7305_KEYSC.AUTOFIX.WORD; + keysc_context.scan_mode = SH7305_KEYSC.SCAN_MODE.WORD; + keysc_context.scan_state = SH7305_KEYSC.SCAN_STATE.WORD; + keysc_context.interrupt = SH7305_KEYSC.INTERRUPT.WORD; + keysc_context.scan_wait = SH7305_KEYSC.SCAN_WAIT.WORD; + keysc_context.scan_interval = SH7305_KEYSC.SCAN_INTERVAL; + keysc_context.kyoutdr = SH7305_KEYSC.KYOUTDR.WORD; + keysc_context.kyindr = SH7305_KEYSC.KYINDR.WORD; + + // Intialize key scan interface SH7305_KEYSC.CONTROL.KEYIE = 1; // Enable KEYSC interrupt. SH7305_KEYSC.CONTROL.INTMODE = 0b00; // Use default (?) interrupt mode. SH7305_KEYSC.AUTOFIX.ENABLE = 1; // Enable key bounce fix (?) SH7305_KEYSC.AUTOFIX.UNKNOWN0 = 0b100; // Unknown, use Casio's value. (autofix) SH7305_KEYSC.AUTOFIX.UNKNOWN1 = 0b10; // Unknown, use Casio's value. (autofix) SH7305_KEYSC.SCAN_MODE.UNKNOWN = 0b001; // Unknown, use Casio's value. (scan mode) - //SH7305_KEYSC.INTERRUPT.KYCPU_IE = 0b0000100; // Interrupt when keys are pressed or released. SH7305_KEYSC.INTERRUPT.KYCPU_IE = 0b0000010; // Falling + pressed + rising. SH7305_KEYSC.SCAN_WAIT.TIME = 0x05; // No time between each interrupt. SH7305_KEYSC.SCAN_INTERVAL = 0x98; // Unknown, use Casio's value. (scan interval) @@ -57,28 +50,42 @@ void vhex_context_set(void) SH7305_KEYSC.KYINDR.KYDIR3 = 1; // Scan [F4],[MENU],[EXIT],[sin],[)],[DEL],[x],[+],[(-)] SH7305_KEYSC.KYINDR.KYDIR2 = 1; // Scan [F5],[left],[down],[cos],[,],[%],[-],[EXE] SH7305_KEYSC.KYINDR.KYDIR1 = 1; // Scan [F6],[up],[right],[tan],[->] + + // Install the interrupt handler + vbr_interrupt_set(INT_CODE_KEYSC, &sh7305_keysc_int_handler); + + // Initialize high level abstractions + keycache_initialize(); + + // Enable interrupt SH7305_INTC.IPRF.KEYSC = 10; // Set KEYSC interrupt priority (max). SH7305_INTC.IMCR5.KEYI = 1; // Clear KEYSC interrupt mask. - - // Configure power / sleep mode. - SH7305_POWER.STBCR.LONG_WORD = 0x00000000; - //SH7305_POWER.STBCR.STBY = 1; - //TODO: handle real-power on. - - // Configure TMU. - SH7305_TMU.TSTR.BYTE = 0x00; // Stop all timer - for (int i = 0 ; i < 3 ; i = i + 1) - { - SH7305_TMU.TIMER[i].TCOR = 0xffffffff; // Reset Timer - SH7305_TMU.TIMER[i].TCOR = 0xffffffff; // Reset Timer - SH7305_TMU.TIMER[i].TCR.UNF = 0; // Clear interrupt flag. - SH7305_TMU.TIMER[i].TCR.UNIE = 0; // Disable interrupt. - SH7305_TMU.TIMER[i].TCR.TPSC = 0b0000; // Select clock deviser. - } - SH7305_INTC.IPRA.TMU0_0 = 12; - SH7305_INTC.IPRA.TMU0_1 = 12; - SH7305_INTC.IPRA.TMU0_2 = 12; - SH7305_INTC.IMCR4.TUNI2 = 1; - SH7305_INTC.IMCR4.TUNI1 = 1; - SH7305_INTC.IMCR4.TUNI0 = 1; } + +// Restore old context +// @note: the interrupt priority will be restored by the INTC driver +static void sh7305_keysc_driver_uninstall(void) +{ + // Mask interrupt (requered) + SH7305_INTC.IMR5.KEYI = 1; + SH7305_INTC.IPRF.KEYSC = 0; + + // Restore keysc context + SH7305_KEYSC.CONTROL.WORD = keysc_context.control; + SH7305_KEYSC.AUTOFIX.WORD = keysc_context.autofix; + SH7305_KEYSC.SCAN_MODE.WORD = keysc_context.scan_mode; + SH7305_KEYSC.SCAN_STATE.WORD = keysc_context.scan_state; + SH7305_KEYSC.INTERRUPT.WORD = keysc_context.interrupt; + SH7305_KEYSC.SCAN_WAIT.WORD = keysc_context.scan_wait; + SH7305_KEYSC.SCAN_INTERVAL = keysc_context.scan_interval; + SH7305_KEYSC.KYOUTDR.WORD = keysc_context.kyoutdr; + SH7305_KEYSC.KYINDR.WORD = keysc_context.kyindr; +} + +// Create driver object +VHEX_DRIVER(4, driver_keyboard_sh7305) = { + .arch = MPU_SH7305, + .install = &sh7305_keysc_driver_install, + .uninstall = &sh7305_keysc_driver_uninstall, + .name = "keysc" +}; diff --git a/src/kernel/drivers/keyboard/handler.c b/src/kernel/drivers/keyboard/hardware/sh7305/handler.c similarity index 85% rename from src/kernel/drivers/keyboard/handler.c rename to src/kernel/drivers/keyboard/hardware/sh7305/handler.c index 10505b2..96c06dc 100644 --- a/src/kernel/drivers/keyboard/handler.c +++ b/src/kernel/drivers/keyboard/hardware/sh7305/handler.c @@ -1,15 +1,12 @@ +#include #include #include -// Internal functions -extern void keycache_update(int row, int column, uint8_t key_frame); -extern void keycache_clean(uint8_t key_frame); - // Device internal indicator to // avoid reentrace with the key list. volatile uint8_t keylist_isUpdate = 0; -void keysc_handler(void) +void sh7305_keysc_int_handler(void) { static uint8_t key_frame = 0; int column; diff --git a/src/kernel/drivers/keyboard/keycache.c b/src/kernel/drivers/keyboard/keycache.c index 45613a6..e1f7046 100644 --- a/src/kernel/drivers/keyboard/keycache.c +++ b/src/kernel/drivers/keyboard/keycache.c @@ -1,6 +1,38 @@ #include #include +/* +** Internal cache, used like chained list. +** +** @note: +** The KEYSC have 6 key data 16-bits registers +** this is why we used 6 * 16 = 96 cache slot. +*/ +struct keycache_s keycache[96]; +struct keycache_s *keylist; + +/* +** keycache_init() +** +** @info +** Constructor used by the kernel during the +** bootstrap part. It will initialize keycache +** and the chained list. +** This function sould not be called anymore. +*/ +void keycache_initialize(void) +{ + int i; + + i = 96; + while (--i >= 0) + { + keycache[i].keycode = KEY_UNUSED; + keycache[i].next = NULL; + } + keylist = NULL; +} + /* keycache_alloc() - Try to alloc a new keycache node */ static struct keycache_s *keycache_alloc(void) { diff --git a/src/kernel/drivers/power/driver.c b/src/kernel/drivers/power/driver.c new file mode 100644 index 0000000..a9b571d --- /dev/null +++ b/src/kernel/drivers/power/driver.c @@ -0,0 +1,88 @@ +#include +#include +#include +#include + +// Internal globals for abstractions +struct __sh7305_power_context vhex_power_context; +struct __sh7305_power_context casio_power_context; +int power_driver_is_installed = 0; + +// TODO: save area before dump ? +static void power_driver_install(void) +{ + // Save current context (Casio) + casio_power_context.stbcr = SH7305_POWER.STBCR.LONG_WORD; + casio_power_context.mstpcr[0] = SH7305_POWER.MSTPCR0.LONG_WORD; + casio_power_context.mstpcr[1] = SH7305_POWER.MSTPCR1.LONG_WORD; + casio_power_context.mstpcr[2] = SH7305_POWER.MSTPCR2.LONG_WORD; + casio_power_context.bar = SH7305_POWER.BAR; + + // Check if we need to install the default Vhex context + if (power_driver_is_installed != 0) + { + SH7305_POWER.STBCR.LONG_WORD = vhex_power_context.stbcr; + SH7305_POWER.MSTPCR0.LONG_WORD = vhex_power_context.mstpcr[0]; + SH7305_POWER.MSTPCR1.LONG_WORD = vhex_power_context.mstpcr[1]; + SH7305_POWER.MSTPCR2.LONG_WORD = vhex_power_context.mstpcr[2]; + SH7305_POWER.BAR = vhex_power_context.bar; + icbi((void*)0xa0000000); + return; + } + + // Setup new power context + // Selecte SLEEP mode (the CPU is stopped but all + // peripheral continue to operates) + SH7305_POWER.STBCR.RSTBY = 0; + SH7305_POWER.STBCR.STBY = 0; + SH7305_POWER.STBCR.USTBY = 0; + + // Start Vhex peripheral + // @note: We can't stop peripherals that we don't + // use because we don't known if Casio use them >_< + SH7305_POWER.MSTPCR0.TLB = 0; // start TLB + SH7305_POWER.MSTPCR0.IC = 0; // start instruction cache + SH7305_POWER.MSTPCR0.OC = 0; // start operand cache + SH7305_POWER.MSTPCR0.RS = 0; // start RS memory + SH7305_POWER.MSTPCR0.IL = 0; // start IL memroy + SH7305_POWER.MSTPCR0.SC = 0; // start secondary cache + SH7305_POWER.MSTPCR0.INTC = 0; // start interrupt controller + SH7305_POWER.MSTPCR0.TMU0 = 0; // start Timer Unit 0 + SH7305_POWER.MSTPCR1.KEYSC = 0; // start Key Scan Interface + SH7305_POWER.MSTPCR1.RTC = 0; // start Real Time Clock + SH7305_POWER.MSTPCR2.LCD = 0; // start LCD module + + // Force CPU update + icbi((void*)0xa0000000); + + // Indicate that the driver is installed + power_driver_is_installed = 1; +} + +static void power_driver_uninstall(void) +{ + // Save current context (Vhex) + vhex_power_context.stbcr = SH7305_POWER.STBCR.LONG_WORD; + vhex_power_context.mstpcr[0] = SH7305_POWER.MSTPCR0.LONG_WORD; + vhex_power_context.mstpcr[1] = SH7305_POWER.MSTPCR1.LONG_WORD; + vhex_power_context.mstpcr[2] = SH7305_POWER.MSTPCR2.LONG_WORD; + vhex_power_context.bar = SH7305_POWER.BAR; + + // Restore Casio context + SH7305_POWER.STBCR.LONG_WORD = casio_power_context.stbcr; + SH7305_POWER.MSTPCR0.LONG_WORD = casio_power_context.mstpcr[0]; + SH7305_POWER.MSTPCR1.LONG_WORD = casio_power_context.mstpcr[1]; + SH7305_POWER.MSTPCR2.LONG_WORD = casio_power_context.mstpcr[2]; + SH7305_POWER.BAR = casio_power_context.bar; + + // Force CPU update + icbi((void*)0xa0000000); +} + +// Create driver object +VHEX_DRIVER(1, driver_power) = { + .arch = MPU_SH7305, + .install = &power_driver_install, + .uninstall = &power_driver_uninstall, + .name = "power" +}; diff --git a/src/kernel/drivers/screen/constructor.c b/src/kernel/drivers/screen/constructor.c deleted file mode 100644 index afc7c87..0000000 --- a/src/kernel/drivers/screen/constructor.c +++ /dev/null @@ -1,21 +0,0 @@ -#include - -// Internal drivers -extern void t6k11_variant_lcd_driver(void *vram); -extern void t6k11_lcd_driver(void *vram); - -// Primitives -void (*screen_driver)(void *vram); - -__attribute__((constructor)) -void screen_driver_load(void) -{ - // Check T6K11 variant which appear during - // the OS >= 03.00.0000 - if (*(uint8_t*)0xa0010021 == '3') { - screen_driver = (void*)&t6k11_variant_lcd_driver; - return; - } - // Default driver - screen_driver = &t6k11_lcd_driver; -} diff --git a/src/kernel/drivers/screen/hardware/t6k11/driver.c b/src/kernel/drivers/screen/hardware/t6k11/driver.c new file mode 100644 index 0000000..93b4408 --- /dev/null +++ b/src/kernel/drivers/screen/hardware/t6k11/driver.c @@ -0,0 +1,37 @@ +#include +#include + +// Internal drivers +extern void t6k11_variant_lcd_driver(void *vram); +extern void t6k11_lcd_driver(void *vram); + +//TODO: save screen context !! +static void t6k11_driver_install(void) +{ + extern void (*screen_driver)(void *vram); + + // The T6K11 variant which appear during + // the OS >= 03.00.0000, so check it + // @note: The OS version is stored at 0xa0010021 + // TODO: get the OS version properly !! + if (*(uint8_t*)0xa0010021 == '3') { + screen_driver = (void*)&t6k11_variant_lcd_driver; + return; + } + + // Default driver + screen_driver = &t6k11_lcd_driver; +} + +static void t6k11_driver_uninstall(void) +{ + //FIXME: restore screen context !!! +} + +// Create driver object +VHEX_DRIVER(4, driver_screen_t6k11) = { + .arch = MPU_SH7305, + .install = &t6k11_driver_install, + .uninstall = &t6k11_driver_uninstall, + .name = "t6k11" +}; diff --git a/src/kernel/drivers/screen/t6k11.s b/src/kernel/drivers/screen/hardware/t6k11/t6k11.s similarity index 100% rename from src/kernel/drivers/screen/t6k11.s rename to src/kernel/drivers/screen/hardware/t6k11/t6k11.s diff --git a/src/kernel/drivers/screen/t6h11_variant.c b/src/kernel/drivers/screen/hardware/t6k11/t6k11_variant.c similarity index 100% rename from src/kernel/drivers/screen/t6h11_variant.c rename to src/kernel/drivers/screen/hardware/t6k11/t6k11_variant.c diff --git a/src/kernel/drivers/screen/update.c b/src/kernel/drivers/screen/update.c index 1bedc50..5b242a0 100644 --- a/src/kernel/drivers/screen/update.c +++ b/src/kernel/drivers/screen/update.c @@ -1,11 +1,10 @@ #include +// Driver install indicator +void (*screen_driver)(void *vram) = NULL; + void screen_update(void *vram) { - extern void (*screen_driver)(void *vram); - - // Check driver validity - if (screen_driver == NULL) - return; - screen_driver(vram); + if (screen_driver != NULL) + screen_driver(vram); } diff --git a/src/kernel/drivers/timer/constructor.c b/src/kernel/drivers/timer/constructor.c index b82020f..9981939 100644 --- a/src/kernel/drivers/timer/constructor.c +++ b/src/kernel/drivers/timer/constructor.c @@ -1,5 +1,4 @@ #include -#include #include // Internal timer "cache". @@ -26,22 +25,6 @@ void timer_constructor(void) timercache[i].arg = NULL; } - // Configure TMU - SH7305_TMU.TSTR.STR0 = 0; // Stop timer 0 - SH7305_TMU.TSTR.STR1 = 0; // Stop timer 1 - SH7305_TMU.TSTR.STR2 = 0; // Stop timer 2 - - // Configure TMU timers - for (int i = 0 ; i < 3 ; ++i) - { - SH7305_TMU.TIMER[i].TCOR = 0xffffffff; // Reset timer constant register - SH7305_TMU.TIMER[i].TCNT = 0xffffffff; // Reset timer counter - SH7305_TMU.TIMER[i].TCR.UNF = 0; // Clear interrupt flags - SH7305_TMU.TIMER[i].TCR.UNIE = 0; // Disable timerinterrupt - SH7305_TMU.TIMER[i].TCR.CKREG = 0b00; // Count on rising edge - SH7305_TMU.TIMER[i].TCR.TPSC = 0b000; // Select P/4 prescaler - } - // Stop atomic operations atomic_stop(); } diff --git a/src/kernel/drivers/timer/install.c b/src/kernel/drivers/timer/install.c index 078ae6f..9e61042 100644 --- a/src/kernel/drivers/timer/install.c +++ b/src/kernel/drivers/timer/install.c @@ -41,7 +41,7 @@ int timer_install(void *callback, void *arg, int hertz, tmode_t mode) // Calculate real ticks needed // FIXME: correct ticks calculation (remove / 2 ?) ticks = cpg_get_frequency(CPG_PERIPHERAL) / 2; - ticks = ticks / prescaler[SH7305_TMU.TIMER[timerID].TCR.TPSC]; + ticks = ticks / prescaler[SH7305_TMU.TIMER[timerID].TCR.TPSC]; ticks = ticks / hertz; // Setup Timer diff --git a/src/kernel/drivers/timer/tmu/driver.c b/src/kernel/drivers/timer/tmu/driver.c new file mode 100644 index 0000000..6ec3a04 --- /dev/null +++ b/src/kernel/drivers/timer/tmu/driver.c @@ -0,0 +1,97 @@ +#include +#include +#include +#include +#include + +// Internal handlers +extern void sh7305_tmu_handler(void); + +// Internal hardware context +struct __sh7305_tmu_context casio_tmu_context; +struct __sh7305_tmu_context vhex_tmu_context; +int tmu_driver_is_installed = 0; + +static void tmu_driver_install(void) +{ + // Save current TMU timer's status and stop all + casio_tmu_context.tstr = SH7305_TMU.TSTR.BYTE; + SH7305_TMU.TSTR.BYTE = 0x00; // Stop all timer + + // Configure TMU. + for (int i = 0 ; i < 3 ; ++i) + { + // Save timmer context + casio_tmu_context.timer[i].tcor = SH7305_TMU.TIMER[i].TCOR; + casio_tmu_context.timer[i].tcnt = SH7305_TMU.TIMER[i].TCNT; + casio_tmu_context.timer[i].tcr = SH7305_TMU.TIMER[i].TCR.WORD; + + // Re-install driver if possible + if (tmu_driver_is_installed != 0) + { + SH7305_TMU.TIMER[i].TCOR = vhex_tmu_context.timer[i].tcor; + SH7305_TMU.TIMER[i].TCNT = vhex_tmu_context.timer[i].tcnt; + SH7305_TMU.TIMER[i].TCR.WORD = vhex_tmu_context.timer[i].tcr; + } else { + SH7305_TMU.TIMER[i].TCOR = 0xffffffff; // Reset Timer + SH7305_TMU.TIMER[i].TCOR = 0xffffffff; // Reset Timer + SH7305_TMU.TIMER[i].TCR.UNF = 0; // Clear interrupt flag. + SH7305_TMU.TIMER[i].TCR.UNIE = 0; // Disable interrupt. + SH7305_TMU.TIMER[i].TCR.TPSC = 0b0000; // Select clock deviser. + } + } + + // Install interrupt handlers for each timer + vbr_interrupt_set(INT_CODE_TMU0_TUNI0, &sh7305_tmu_handler); + vbr_interrupt_set(INT_CODE_TMU0_TUNI1, &sh7305_tmu_handler); + vbr_interrupt_set(INT_CODE_TMU0_TUNI2, &sh7305_tmu_handler); + + // Set interruptions priority + SH7305_INTC.IPRA.TMU0_0 = 12; + SH7305_INTC.IPRA.TMU0_1 = 12; + SH7305_INTC.IPRA.TMU0_2 = 12; + + // Enable interruptions + SH7305_INTC.IMCR4.TUNI2 = 1; + SH7305_INTC.IMCR4.TUNI1 = 1; + SH7305_INTC.IMCR4.TUNI0 = 1; + + // Restart timer if possible + if (tmu_driver_is_installed != 0) + SH7305_TMU.TSTR.BYTE = vhex_tmu_context.tstr; + + // Indicate that the driver has been installed + tmu_driver_is_installed = 1; +} + +// Restore context +static void tmu_driver_uninstall(void) +{ + // Save Vhex TMU timer's status and stop all + vhex_tmu_context.tstr = SH7305_TMU.TSTR.BYTE; + SH7305_TMU.TSTR.BYTE = 0x00; + + for (int i = 0; i < 3 ; ++i) + { + // Save timer context (Vhex) + vhex_tmu_context.timer[i].tcor = SH7305_TMU.TIMER[i].TCOR; + vhex_tmu_context.timer[i].tcnt = SH7305_TMU.TIMER[i].TCNT; + vhex_tmu_context.timer[i].tcr = SH7305_TMU.TIMER[i].TCR.WORD; + + // Restore Casio's TMU context + SH7305_TMU.TIMER[i].TCOR = casio_tmu_context.timer[i].tcor; + SH7305_TMU.TIMER[i].TCNT = casio_tmu_context.timer[i].tcnt; + SH7305_TMU.TIMER[i].TCR.WORD = casio_tmu_context.timer[i].tcr; + } + + // Restart timer + SH7305_TMU.TSTR.BYTE = casio_tmu_context.tstr; +} + +// Create driver object +VHEX_DRIVER(3, driver_tmu) = { + .arch = MPU_SH7305, + .install = &tmu_driver_install, + .uninstall = &tmu_driver_uninstall, + .name = "tmu" +}; diff --git a/src/kernel/drivers/timer/handler.c b/src/kernel/drivers/timer/tmu/handler.c similarity index 65% rename from src/kernel/drivers/timer/handler.c rename to src/kernel/drivers/timer/tmu/handler.c index e5d3b12..2deffac 100644 --- a/src/kernel/drivers/timer/handler.c +++ b/src/kernel/drivers/timer/tmu/handler.c @@ -1,10 +1,9 @@ #include #include -void timer_handler(void) +void sh7305_tmu_handler(void) { extern struct timer_cache_s timercache[TIMER_NUMBER]; - //static uint32_t counter = 0; uint32_t intevt; int timer_ID; @@ -14,22 +13,12 @@ void timer_handler(void) intevt = *(uint32_t*)0xff000028; timer_ID = (intevt - 0x400) / 0x20; - /*if (intevt != 0x400) - { - kvram_clear(); - printk(0, 0, "Timer ID: %d\n", timer_ID); - printk(0, 1, "Interrupt: %#x\n", intevt); - printk(0, 2, "counter: %d\n", counter++); - kvram_display(); - }*/ - // Clear interrupt flags. SH7305_TMU.TIMER[timer_ID].TCR.UNF = 0; // Execute callback if possible. if (timercache[timer_ID].status != TIMER_UNUSED && - timercache[timer_ID].callback != NULL) - { + timercache[timer_ID].callback != NULL) { ((void (*)(volatile void *))timercache[timer_ID].callback)(timercache[timer_ID].arg); } diff --git a/src/kernel/drivers/vbr/driver.c b/src/kernel/drivers/vbr/driver.c new file mode 100644 index 0000000..1c5bb4d --- /dev/null +++ b/src/kernel/drivers/vbr/driver.c @@ -0,0 +1,51 @@ +#include +#include +#include + +// Internal globals for abstractions +void (*int_handler[VBR_INTERRUPT_NB])(void); +int vbr_driver_is_installed = 0; +void *old_vbr; + +// TODO: save area before dump ? +static void vbr_driver_install(void) +{ + extern uint32_t vhex_vbr; + extern uint32_t bvhex_ram; + extern uint32_t bvhex_rom; + extern uint32_t svhex; + + // Save and switch the VBR + // @note: The VBR swtich *SHOULD* be atomic because + // one exepction / interrupt will crash the calculator. + old_vbr = vbr_set(&vhex_vbr); + + // Check if the VBR driver is already installed + if (vbr_driver_is_installed != 0) + return; + + // Dump VBR handlers (interrupt and exception) + memcpy(&bvhex_ram, &bvhex_rom, (size_t)&svhex); + + // Initialize pseudo-abtraction + // TODO: Find better way to do the job + for (int i = 0 ; i < VBR_INTERRUPT_NB ; ++i) + int_handler[i] = NULL; + + // Indicate that the driver is installed + vbr_driver_is_installed = 1; +} + +static void vbr_driver_uninstall(void) +{ + // restore old VBR + vbr_set(old_vbr); +} + +// Create driver object +VHEX_DRIVER(3, driver_vbr) = { + .arch = MPU_SH7305, + .install = &vbr_driver_install, + .uninstall = &vbr_driver_uninstall, + .name = "vbr" +}; diff --git a/src/kernel/drivers/vbr/interrupt.c b/src/kernel/drivers/vbr/interrupt.c index 6d7c8d1..d45c9ac 100644 --- a/src/kernel/drivers/vbr/interrupt.c +++ b/src/kernel/drivers/vbr/interrupt.c @@ -1,35 +1,56 @@ +#include #include +#include -// Handler prototype. -extern void keysc_handler(void); -extern void timer_handler(void); - +// TODO: update me void interrupt_handler(void) { + extern void (*int_handler[VBR_INTERRUPT_NB])(void); uint32_t intevt = *(uint32_t*)0xff000028; + int id; + // Get the interrupt ID + VBR_GET_INTERRUPT_CODE(id, intevt); - // Check KEYSC interrupt. - if (intevt == 0xbe0) + // Check id validity and handler error + if (id < 0 || id >= VBR_INTERRUPT_NB || int_handler[id] == NULL) { - keysc_handler(); - return; - } - if (intevt == 0x400 || - intevt == 0x410 || - intevt == 0x420) - { - timer_handler(); - return; + earlyterm_write( + "Ho crap ! Interrupt error !\n" + "Interrupt ID (%#x)\n" + "Error: handler not foud !\n", + intevt + ); + while (1); } - // Display error. - earlyterm_clear(); - earlyterm_write( - "Ho crap ! Interrupt error !\n" - "Interrupt ID (%#x)\n" - "Error: handler not foud !\n", - intevt - ); - while (1); + // Call handler and exit + (*int_handler[id])(); +} + +void *vbr_interrupt_set(int intcode, void (*handler)(void)) +{ + extern void (*int_handler[VBR_INTERRUPT_NB])(void); + void *old; + int id; + + // Get the interrupt ID + VBR_GET_INTERRUPT_CODE(id, intcode); + + // Check id validity + if (id < 0 || id >= VBR_INTERRUPT_NB) + return (NULL); + + // Start atomic operations + atomic_start(); + + // Switch interupt handler + old = int_handler[id]; + int_handler[id] = handler; + + // Stop atomic operations + atomic_stop(); + + // Return old interrupt handler + return (old); } diff --git a/src/kernel/util/extra/vbr.s b/src/kernel/drivers/vbr/utils.s similarity index 100% rename from src/kernel/util/extra/vbr.s rename to src/kernel/drivers/vbr/utils.s diff --git a/src/kernel/fs/smemfs/initialize.c b/src/kernel/fs/smemfs/initialize.c index 7662ab8..7b53863 100644 --- a/src/kernel/fs/smemfs/initialize.c +++ b/src/kernel/fs/smemfs/initialize.c @@ -3,7 +3,8 @@ #include #include -// Kernel FS block +// Casio SMEM FileSystem primitives +// @note: We use USB PowerGraphic 2 primitives struct file_system_type smemfs_filesystem = { // internal informations @@ -12,22 +13,23 @@ struct file_system_type smemfs_filesystem = // FS specific openrations .filesystem_operations = { - .mount = &smemfs_mount, - .umount = &smemfs_umount + .mount = &smemfs_USB2_mount, + .umount = &smemfs_USB2_umount }, // File operations .file_operations = { - .read = &smemfs_read, - .write = NULL + .read = &smemfs_USB2_read, + .write = NULL, + .ioctl = NULL }, // Inode operations .inode_operations = { // Walk - .find_next_sibling = &smemfs_find_next_sibling, - .find_first_child = &smemfs_find_first_child, - .find_parent = &smemfs_find_parent, + .find_next_sibling = &smemfs_USB2_find_next_sibling, + .find_first_child = &smemfs_USB2_find_first_child, + .find_parent = &smemfs_USB2_find_parent, // Memory .create = NULL, @@ -36,13 +38,32 @@ struct file_system_type smemfs_filesystem = .rename = NULL, // Informations - .get_name = &smemfs_get_name, - .get_mode = &smemfs_get_mode + .get_name = &smemfs_USB2_get_name, + .get_mode = &smemfs_USB2_get_mode } }; +// Internal superblock informations struct smemfs_superblock_s smemfs_superblock; + +// switch USB Power Graphic II driver to +// USB Power Graphic III (Casio syscall wrapper) +static void use_dump_smem_driver(void) +{ +/* smemfs_filesystem.filesystem_operations.mount = &smemfs_USB3_mount; + smemfs_filesystem.filesystem_operations.umount = &smemfs_USB3_umount; + smemfs_filesystem.file_operations.read = &smemfs_USB3_read; + smemfs_filesystem.inode_operations.find_next_sibling = &smemfs_USB3_find_next_sibling; + smemfs_filesystem.inode_operations.find_first_child = &smemfs_USB3_find_first_child; + smemfs_filesystem.inode_operations.find_parent = &smemfs_USB3_find_parent; + smemfs_filesystem.inode_operations.get_name = &smemfs_USB3_get_name; + smemfs_filesystem.inode_operations.get_mode = &smemfs_USB3_get_mode; + smemfs_superblock.sector_table = NULL; + smemfs_superblock.inode_table = NULL;*/ + while (1); +} + void smemfs_initialize(void) { // Start atomic operations @@ -56,11 +77,8 @@ void smemfs_initialize(void) smemfs_superblock.sector_table = (void *)0xa0270000; if (smemfs_superblock.sector_table->magic_start != CASIO_SMEM_BLOCK_ENTRY_MAGIC) { - earlyterm_clear(); earlyterm_write("SMEMFS: Casio sector table error !"); - earlyterm_write("Wait manual reset..."); - atomic_stop(); - while (1){ __asm__ volatile ("sleep"); } + return (use_dump_smem_driver()); } // Try to find Casio SMEM inode table start always at the end of @@ -76,11 +94,8 @@ void smemfs_initialize(void) smemfs_superblock.inode_table->parent.id != 0xffff || smemfs_superblock.inode_table->parent.type != 0xffff) { - earlyterm_clear(); earlyterm_write("SMEMFS: Casio inode table error !"); - earlyterm_write("Wait manual reset..."); - atomic_stop(); - while (1){ __asm__ volatile ("sleep"); } + return (use_dump_smem_driver()); } // Stop atomic operations diff --git a/src/kernel/fs/smemfs/file/read.c b/src/kernel/fs/smemfs/power_graphic_2/file/read.c similarity index 96% rename from src/kernel/fs/smemfs/file/read.c rename to src/kernel/fs/smemfs/power_graphic_2/file/read.c index 47b00b9..27536f1 100644 --- a/src/kernel/fs/smemfs/file/read.c +++ b/src/kernel/fs/smemfs/power_graphic_2/file/read.c @@ -24,7 +24,7 @@ static void *casio_smem_get_data_base_address(smemfs_fragdata_t *fragment) } /* casio_smem_read() - Read the file data (based on internal cursor) */ -ssize_t smemfs_read(void *inode, void *buf, size_t count, off_t pos) +ssize_t smemfs_USB2_read(void *inode, void *buf, size_t count, off_t pos) { smemfs_fragdata_t *fragment; smemfs_header_t *header; @@ -33,9 +33,6 @@ ssize_t smemfs_read(void *inode, void *buf, size_t count, off_t pos) size_t current_size; size_t real_size; - //earlyterm_write("pos = %#x\n", pos); - //DBG_WAIT; - // Get Check obvious error. if (inode == NULL || buf == NULL) return (-1); @@ -66,7 +63,6 @@ ssize_t smemfs_read(void *inode, void *buf, size_t count, off_t pos) if (fragment->magic != CASIO_SMEM_FRAGMENT_MAGIC || fragment->info != CASIO_SMEM_FRAGMENT_INFO_EXIST) { - atomic_stop(); earlyterm_write("smemfs: fragment error !\n"); earlyterm_write("* current_size = %d\n", current_size); earlyterm_write("* pos = %#x\n", pos); @@ -75,6 +71,7 @@ ssize_t smemfs_read(void *inode, void *buf, size_t count, off_t pos) DBG_WAIT; DBG_WAIT; DBG_WAIT; + atomic_stop(); return (-1); } diff --git a/src/kernel/fs/smemfs/filesystem/mount.c b/src/kernel/fs/smemfs/power_graphic_2/filesystem/mount.c similarity index 93% rename from src/kernel/fs/smemfs/filesystem/mount.c rename to src/kernel/fs/smemfs/power_graphic_2/filesystem/mount.c index c72889d..792cbbd 100644 --- a/src/kernel/fs/smemfs/filesystem/mount.c +++ b/src/kernel/fs/smemfs/power_graphic_2/filesystem/mount.c @@ -2,7 +2,7 @@ #include /* casio_smem_mount() - Mount the file system (sync) */ -void *smemfs_mount(void) +void *smemfs_USB2_mount(void) { extern struct smemfs_superblock_s smemfs_superblock; void *root_inode; diff --git a/src/kernel/fs/smemfs/filesystem/umount.c b/src/kernel/fs/smemfs/power_graphic_2/filesystem/umount.c similarity index 80% rename from src/kernel/fs/smemfs/filesystem/umount.c rename to src/kernel/fs/smemfs/power_graphic_2/filesystem/umount.c index e5a58c2..66eda09 100644 --- a/src/kernel/fs/smemfs/filesystem/umount.c +++ b/src/kernel/fs/smemfs/power_graphic_2/filesystem/umount.c @@ -1,7 +1,7 @@ #include /* casio_smem_umount() - Unmount the File System */ -int smemfs_umount(void) +int smemfs_USB2_umount(void) { // Do nothing for now return (0); diff --git a/src/kernel/fs/smemfs/inode/find_first_child.c b/src/kernel/fs/smemfs/power_graphic_2/inode/find_first_child.c similarity index 88% rename from src/kernel/fs/smemfs/inode/find_first_child.c rename to src/kernel/fs/smemfs/power_graphic_2/inode/find_first_child.c index 7aee1c4..2afd265 100644 --- a/src/kernel/fs/smemfs/inode/find_first_child.c +++ b/src/kernel/fs/smemfs/power_graphic_2/inode/find_first_child.c @@ -2,7 +2,7 @@ #include /* smemfs_find_first_child() - Find the fist file in the (folder) inode (sync) */ -void *smemfs_find_first_child(void *inode) +void *smemfs_USB2_find_first_child(void *inode) { extern struct smemfs_superblock_s smemfs_superblock; uint16_t folder_id; @@ -33,7 +33,7 @@ void *smemfs_find_first_child(void *inode) } // Return the first child of the file. - child_inode = smemfs_walk(inode, smemfs_superblock.inode_table, + child_inode = smemfs_USB2_walk(inode, smemfs_superblock.inode_table, folder_id, WALK_FLAG_ID_CHECK_PARENT); // Stop atomic operation diff --git a/src/kernel/fs/smemfs/inode/find_next_sibling.c b/src/kernel/fs/smemfs/power_graphic_2/inode/find_next_sibling.c similarity index 84% rename from src/kernel/fs/smemfs/inode/find_next_sibling.c rename to src/kernel/fs/smemfs/power_graphic_2/inode/find_next_sibling.c index 3016949..0452f57 100644 --- a/src/kernel/fs/smemfs/inode/find_next_sibling.c +++ b/src/kernel/fs/smemfs/power_graphic_2/inode/find_next_sibling.c @@ -2,7 +2,7 @@ #include /* smemfs_find_next_sibling() - Find the next file from the same parent (sync) */ -void *smemfs_find_next_sibling(void *inode) +void *smemfs_USB2_find_next_sibling(void *inode) { extern struct smemfs_superblock_s smemfs_superblock; void *sibling_inode; @@ -27,7 +27,7 @@ void *smemfs_find_next_sibling(void *inode) folder_id = ((struct casio_smem_header_s *)inode)->parent.id; // Return the next file of the directory. - sibling_inode = smemfs_walk(inode, inode, folder_id, WALK_FLAG_ID_CHECK_PARENT); + sibling_inode = smemfs_USB2_walk(inode, inode, folder_id, WALK_FLAG_ID_CHECK_PARENT); // Stop atomic operation atomic_stop(); diff --git a/src/kernel/fs/smemfs/inode/find_parent.c b/src/kernel/fs/smemfs/power_graphic_2/inode/find_parent.c similarity index 85% rename from src/kernel/fs/smemfs/inode/find_parent.c rename to src/kernel/fs/smemfs/power_graphic_2/inode/find_parent.c index 8d37754..3adc48b 100644 --- a/src/kernel/fs/smemfs/inode/find_parent.c +++ b/src/kernel/fs/smemfs/power_graphic_2/inode/find_parent.c @@ -2,7 +2,7 @@ #include /* smemfs_find_parent() - Return the parent inode */ -void *smemfs_find_parent(void *inode) +void *smemfs_USB2_find_parent(void *inode) { extern struct smemfs_superblock_s smemfs_superblock; void *parent_inode; @@ -27,7 +27,7 @@ void *smemfs_find_parent(void *inode) folder_id = ((struct casio_smem_header_s *)inode)->parent.id; // Return first inode find - parent_inode = smemfs_walk(inode, smemfs_superblock.inode_table, folder_id, + parent_inode = smemfs_USB2_walk(inode, smemfs_superblock.inode_table, folder_id, WALK_FLAG_ID_CHECK_DIRECTORY); // Stop atomic operation diff --git a/src/kernel/fs/smemfs/inode/get_mode.c b/src/kernel/fs/smemfs/power_graphic_2/inode/get_mode.c similarity index 96% rename from src/kernel/fs/smemfs/inode/get_mode.c rename to src/kernel/fs/smemfs/power_graphic_2/inode/get_mode.c index c8391ee..6d646bd 100644 --- a/src/kernel/fs/smemfs/inode/get_mode.c +++ b/src/kernel/fs/smemfs/power_graphic_2/inode/get_mode.c @@ -3,7 +3,7 @@ #include /* smemfs_get_mode() - Return the permission dans the type of a file (sync) */ -mode_t smemfs_get_mode(void *inode) +mode_t smemfs_USB2_get_mode(void *inode) { extern struct smemfs_superblock_s smemfs_superblock; struct casio_smem_header_s *header; diff --git a/src/kernel/fs/smemfs/inode/get_name.c b/src/kernel/fs/smemfs/power_graphic_2/inode/get_name.c similarity index 93% rename from src/kernel/fs/smemfs/inode/get_name.c rename to src/kernel/fs/smemfs/power_graphic_2/inode/get_name.c index a20b31c..af15034 100644 --- a/src/kernel/fs/smemfs/inode/get_name.c +++ b/src/kernel/fs/smemfs/power_graphic_2/inode/get_name.c @@ -2,7 +2,7 @@ #include /* smemfs_get_name() - Dump the name of a file (sync) */ -int smemfs_get_name(void *inode, char *buf, size_t count) +int smemfs_USB2_get_name(void *inode, char *buf, size_t count) { extern struct smemfs_superblock_s smemfs_superblock; struct casio_smem_header_s *header; diff --git a/src/kernel/fs/smemfs/inode/walk.c b/src/kernel/fs/smemfs/power_graphic_2/inode/walk.c similarity index 94% rename from src/kernel/fs/smemfs/inode/walk.c rename to src/kernel/fs/smemfs/power_graphic_2/inode/walk.c index 58ea75e..d8e3758 100644 --- a/src/kernel/fs/smemfs/inode/walk.c +++ b/src/kernel/fs/smemfs/power_graphic_2/inode/walk.c @@ -2,7 +2,7 @@ /* smemfs_walk() - Find inode based on directory ID and flags */ /* @note: This function is internal of smemFS, do not call it ! */ -smemfs_inode_t *smemfs_walk(smemfs_inode_t *current, +smemfs_inode_t *smemfs_USB2_walk(smemfs_inode_t *current, smemfs_inode_t *file, uint16_t folder_id, int flags) { smemfs_fragdata_t *fragdata; diff --git a/src/kernel/fs/smemfs/power_graphic_3/filesystem/mount.c b/src/kernel/fs/smemfs/power_graphic_3/filesystem/mount.c new file mode 100644 index 0000000..832f12c --- /dev/null +++ b/src/kernel/fs/smemfs/power_graphic_3/filesystem/mount.c @@ -0,0 +1,29 @@ +#include +#include + +/* +** smemfs_USB3_mount() - Mount the file system (sync) +** @note: +** We don't known how the file system work, so we should use +** Casio's "Bfile_*" sycalls to dump all internal informations +** to avoid OS switch (Vhex -> Casio -> Vhex) +*/ +void *smemfs_USB3_mount(void) +{ + extern struct smemfs_superblock_s smemfs_superblock; + void *root_inode = NULL; + + // Start atomic operation + atomic_start(); + + //TODO + //TODO Use Bfile_FindFirst and Bfile_Find_Next to dump + //TODO All internal FS informations + //TODO + + // Stop atomic operation + atomic_stop(); + + // Return the sector table to simulate the root inode. + return (root_inode); +} diff --git a/src/kernel/scheduler/debug.c b/src/kernel/scheduler/debug.c index 7a57dc5..59af684 100644 --- a/src/kernel/scheduler/debug.c +++ b/src/kernel/scheduler/debug.c @@ -1,11 +1,11 @@ -#include +/*#include #include #include // Test uint32_t counter = 0; -void sched_debug(common_context_t *context_current, common_context_t *context_next) +void sched_debug(struct cpu_context *context_current, struct cpu_context *context_next) { extern uint32_t sched_timer_id; extern uint32_t sched_timer_address; @@ -33,4 +33,4 @@ void sched_debug(common_context_t *context_current, common_context_t *context_ne earlyterm_write("TCOR: %#x", tcor); earlyterm_write("TCNT: %#x", tcnt); earlyterm_write("TCR: %#x", tcr); -} +}*/ diff --git a/src/kernel/scheduler/schedule.c b/src/kernel/scheduler/schedule.c index 35a3658..f6532f4 100644 --- a/src/kernel/scheduler/schedule.c +++ b/src/kernel/scheduler/schedule.c @@ -1,11 +1,12 @@ #include +#include #include #include //TODO: assembly ? //TODO: preemptive handling !! // @note: This part *SHOULD* be exeption safe ! -int sched_schedule(common_context_t **context_current, common_context_t **context_next) +int sched_schedule(struct cpu_context **context_current, struct cpu_context **context_next) { extern struct sched_task *sched_task_current; extern struct sched_task *sched_task_queue; diff --git a/src/kernel/scheduler/start.c b/src/kernel/scheduler/start.c index d924e83..6874952 100644 --- a/src/kernel/scheduler/start.c +++ b/src/kernel/scheduler/start.c @@ -40,11 +40,12 @@ void sched_start(void) sched_timer_tstr_bit = 1 << sched_timer_id; // Debug - //earlyterm_write("* timer ID: %d\n", sched_timer_id); - //earlyterm_write("* timer addr: %#x\n", sched_timer_address); - //earlyterm_write("* timer event: %#x\n", sched_timer_intevt); - //earlyterm_write("* timer TSTR: %#x\n", sched_timer_tstr_bit); - //DBG_WAIT; + /*earlyterm_write("* timer ID: %d\n", sched_timer_id); + earlyterm_write("* timer addr: %#x\n", sched_timer_address); + earlyterm_write("* timer event: %#x\n", sched_timer_intevt); + earlyterm_write("* timer TSTR: %#x\n", sched_timer_tstr_bit); + DBG_WAIT; + while (1);*/ // Start scheduler timer timer_start(sched_timer_id); diff --git a/src/kernel/syscall/handler.c b/src/kernel/syscall/handler.c index 3af6487..d611701 100644 --- a/src/kernel/syscall/handler.c +++ b/src/kernel/syscall/handler.c @@ -10,7 +10,7 @@ static void sys_test(uint32_t a, uint32_t b, uint32_t c, uint32_t d) earlyterm_write("* b = %#x\n", b); earlyterm_write("* c = %#x\n", c); earlyterm_write("* d = %#x\n", d); - DBG_WAIT; + while (1); } static const void *sys_handler[__NR_MAX] = { diff --git a/src/kernel/util/casio/menu.c b/src/kernel/util/casio/menu.c new file mode 100644 index 0000000..e79c403 --- /dev/null +++ b/src/kernel/util/casio/menu.c @@ -0,0 +1,51 @@ +#include +#include +#include +#include + +// Internal bootstrap primitives +extern void bootstrap_drivers_install(void); +extern void bootstrap_drivers_uninstall(void); + +// Internal informations +int casio_timer_id; + +static void casio_keycode_inject(void) +{ + uint16_t keycode; + + keycode = 0x308; + casio_Bkey_PutKeymatrix(&keycode); + casio_TimerUninstall(casio_timer_id); +} + +//@note: +// * mode 0 - Involve menu manually +// * mode 1 - Use GetKey_wait +// FIXME: WAIT DMA transfert !! +void casio_return_menu(int mode) +{ + unsigned int keycode; + int row; + int col; + + // unistall / restore all drivers + bootstrap_drivers_uninstall(); + + // If we should involve main menu manually + // we need to setup one timer which will inject + // Casio's [MENU] keycode to force the GetKey_wait syscall + // to return in main menu + if (mode == 0) { + casio_timer_id = casio_TimerInstall(0, &casio_keycode_inject, 25); + casio_TimerStart(casio_timer_id); + } + + // Use GetKeyWait to wait key event (or keycode inject) + do { + casio_GetKeyWait(&row, &col, KEYWAIT_HALTON_TIMERON, 25, 0, &keycode); + } while (mode == 1); + + // Re-install Vhex drivers + bootstrap_drivers_install(); +} diff --git a/src/kernel/util/casio/menu_test_asm.s b/src/kernel/util/casio/menu_test_asm.s new file mode 100644 index 0000000..6357ce1 --- /dev/null +++ b/src/kernel/util/casio/menu_test_asm.s @@ -0,0 +1,100 @@ +/*.text +.global _casio_return_menu +.type _casio_return_menu, @function + +;; +;; casio_return_menu(int mode) - return to the Casio menu +;; mode 0 - involve menu manually +;; mode 1 - use GetKeyWait and inf. loop +;; +_casio_return_menu: + mov.l r8, @-r15 + sts.l pr, @-r15 + + ! save the mode + mov r4, r8 + + ! Uninstall all drivers + mov.l .bootstrap_drivers_uninstall, r0 + jsr @r0 + nop + + ! TODO + ! TODO Handle mode !! + ! TODO + + ! Save critical register + sts.l mach, @-r15 ! get mach regsiter + sts.l macl, @-r15 ! get macl regsiter + stc.l gbr, @-r15 ! get gbr regsiter + mov.l r14, @-r15 ! get r14 regsiter + mov.l r13, @-r15 ! get r13 regsiter + mov.l r12, @-r15 ! get r12 regsiter + mov.l r11, @-r15 ! get r11 regsiter + mov.l r10, @-r15 ! get r10 regsiter + mov.l r9, @-r15 ! get r9 regsiter + mov.l r8, @-r15 ! get r8 regsiter + + ! Save current stack + mov.l .test_stack, r0 + mov.l r15, @r0 + + + ! Call GetKeyWait(int *row, int *col, int mode, + ! int timeout, int menu, int *keycode) + add #-4, r15 ! get space + mov r15,r7 ! r7 = &keycode + add #-4, r15 ! get space + mov r15,r5 ! r5 = &col + add #-4, r15 ! get space + mov r15,r4 ! r4 = &row + mov #0,r2 ! r2 = menu = 0 (press [MENU] return to the menu) + mov.l r7,@-r15 ! place the keycode address into the seventh aguments position + mov.l r2,@-r15 ! place the menu option into the sixth arguments position + mov #0,r6 ! r6 = mode = 0 (KEYWAIT_HALTON_TIMEROFF) + mov #0,r7 ! r7 = timeout = 0 + +GetKeyWait: + mov.l .casio_GetKeyWait, r0 ! get GetKeyWait syscall + jsr @r0 ! GetKeyWait(int*col, int*row, int waittype, int timeout, int menu,u16*key) + nop + + + !add #20, r15 ! restore stack + mov.l .test_stack, r0 + mov.l @r0, r15 + + ! Restore critical register + mov.l @r15+, r8 ! set r8 regsiter + mov.l @r15+, r9 ! set r9 regsiter + mov.l @r15+, r10 ! set r10 regsiter + mov.l @r15+, r11 ! set r11 regsiter + mov.l @r15+, r12 ! set r12 regsiter + mov.l @r15+, r13 ! set r13 regsiter + mov.l @r15+, r14 ! set r14 regsiter + ldc.l @r15+, gbr ! set gbr regsiter + lds.l @r15+, macl ! set macl regsiter + lds.l @r15+, mach ! set mach regsiter + + ! re-install all drivers + mov.l .bootstrap_drivers_install, r0 + jsr @r0 + nop + + ! epilogue + lds.l @r15+, pr + rts + nop + +.align 4 +.bootstrap_drivers_install: .long _bootstrap_drivers_install +.bootstrap_drivers_uninstall: .long _bootstrap_drivers_uninstall +.casio_GetKeyWait: .long _casio_GetKeyWait +.test_stack: .long _test_stack + +.data +.align 4 +.global _test_stack +.type _test_stack, @object +_test_stack: .long 0 +.end*/ diff --git a/src/kernel/util/casio/syscall.s b/src/kernel/util/casio/syscall.s index 4d92217..ea6e089 100644 --- a/src/kernel/util/casio/syscall.s +++ b/src/kernel/util/casio/syscall.s @@ -23,6 +23,10 @@ .global _casio_WriteFile .global _casio_CloseFile +.global _casio_TimerInstall +.global _casio_TimerUninstall +.global _casio_TimerStart +.global _casio_TimerStop @@ -51,6 +55,9 @@ .type _casio_CloseFile, @function +.type _casio_SetTimer, @function +.type _casio_KillTimer, @function + @@ -174,8 +181,29 @@ _casio_CloseFile: nop +_casio_TimerInstall: + mov.l .syscall_entry, r1 + mov.l .sys_TimerInstall, r0 + jmp @r1 + nop +_casio_TimerStart: + mov.l .syscall_entry, r1 + mov.l .sys_TimerStart, r0 + jmp @r1 + nop +_casio_TimerUninstall: + mov.l .syscall_entry, r1 + mov.l .sys_TimerUninstall, r0 + jmp @r1 + nop + +_casio_TimerStop: + mov.l .syscall_entry, r1 + mov.l .sys_TimerStop, r0 + jmp @r1 + nop .align 4 .syscall_entry: .long 0x80010070 @@ -198,4 +226,8 @@ _casio_CloseFile: .sys_closeFile: .long 0x0000042d .sys_getkeywait: .long 0x00000247 .sys_putKeycode: .long 0x0000024f +.sys_TimerInstall: .long 0x00000118 +.sys_TimerUninstall: .long 0x00000119 +.sys_TimerStart: .long 0x0000011a +.sys_TimerStop: .long 0x0000011b .end diff --git a/src/kernel/vhex.ld b/src/kernel/vhex.ld index ddd264a..42a1da9 100644 --- a/src/kernel/vhex.ld +++ b/src/kernel/vhex.ld @@ -47,6 +47,11 @@ SECTIONS . = ALIGN(4); *(.rodata) *(.rodata.*) + + /* Drivers */ + _bdrivers_section = ALIGN(4); + *(SORT_BY_NAME(.driver.*)); + _edrivers_section = . ; /* Constructors, destructors */ _bctors = ALIGN(4) ;