Update drivers management

This commit is contained in:
Yann MAGNIN 2020-05-03 23:10:49 +02:00
parent 126a619942
commit bc52765c6f
64 changed files with 1273 additions and 626 deletions

View File

@ -0,0 +1,19 @@
#ifndef __KERNEL_BITS_CONTEXT_H__
# define __KERNEL_BITS_CONTEXT_H__
#include <stddef.h>
#include <stdint.h>
// 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__*/

View File

@ -0,0 +1,24 @@
#ifndef __KERNEL_BITS_DRIVER_H__
# define __KERNEL_BITS_DRIVER_H__
#include <kernel/bits/mpu.h>
// 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__*/

View File

@ -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__*/

View File

@ -1,67 +0,0 @@
#ifndef __KERNEL_CONTEXT_H__
# define __KERNEL_CONTEXT_H__
#include <stddef.h>
#include <stdint.h>
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__*/

View File

@ -5,9 +5,11 @@
#include <stdint.h>
#include <sys/types.h>
// 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);

View File

@ -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__*/

View File

@ -6,6 +6,58 @@
#include <sys/types.h>
#include <kernel/fs/file.h>
/*******************************************/
/** **/
/** 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__*/

View File

@ -3,8 +3,8 @@
#include <stddef.h>
#include <stdint.h>
#include <kernel/def/union_types.h>
#include <kernel/def/attributes.h>
#include <kernel/bits/union_types.h>
#include <kernel/bits/attributes.h>
struct SH7305_cpg_s
{

View File

@ -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 <stdint.h>
#include <stddef.h>
#include <kernel/def/union_types.h>
#include <kernel/def/attributes.h>
#include <kernel/bits/union_types.h>
#include <kernel/bits/attributes.h>
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__*/

View File

@ -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 <stdint.h>
#include <stddef.h>
#include <kernel/def/union_types.h>
#include <kernel/def/attributes.h>
#include <kernel/bits/union_types.h>
#include <kernel/bits/attributes.h>
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__*/

View File

@ -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 <stdint.h>
#include <stddef.h>
#include <kernel/def/union_types.h>
#include <kernel/def/attributes.h>
#include <kernel/bits/union_types.h>
#include <kernel/bits/attributes.h>
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__*/

View File

@ -3,8 +3,18 @@
#include <stdint.h>
#include <stddef.h>
#include <kernel/def/union_types.h>
#include <kernel/def/attributes.h>
#include <kernel/bits/union_types.h>
#include <kernel/bits/attributes.h>
struct __sh7305_tmu_context
{
uint8_t tstr;
struct {
uint32_t tcor;
uint32_t tcnt;
uint16_t tcr;
} timer[3];
};
struct timer_s
{

View File

@ -3,8 +3,8 @@
#include <stdint.h>
#include <stddef.h>
#include <kernel/def/union_types.h>
#include <kernel/def/attributes.h>
#include <kernel/bits/union_types.h>
#include <kernel/bits/attributes.h>
struct sh7305_ubc_s
{

View File

@ -5,7 +5,7 @@
#include <stdint.h>
#include <kernel/fs/file.h>
#include <kernel/fs/filesystem.h>
#include <kernel/context.h>
#include <kernel/bits/context.h>
#include <sys/signal.h>
#include <sys/types.h>
@ -33,7 +33,7 @@ struct process
//---
// Context management
//---
common_context_t context;
struct cpu_context context;
//---

View File

@ -4,6 +4,7 @@
#include <stddef.h>
#include <stdint.h>
#include <kernel/process.h>
#include <kernel/bits/context.h>
// 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__*/

View File

@ -4,6 +4,13 @@
#include <stddef.h>
#include <stdint.h>
//---
// 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__*/

View File

@ -0,0 +1,85 @@
#include <stdint.h>
#include <kernel/util/atomic.h>
#include <kernel/devices/earlyterm.h>
#include <kernel/bits/driver.h>
#include <kernel/bits/mpu.h>
#include <sys/types.h>
// 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();
}

View File

@ -0,0 +1,39 @@
#include <kernel/devices/earlyterm.h>
#include <kernel/devices/tty.h>
#include <kernel/fs/smemfs.h>
#include <kernel/fs/gladfs.h>
#include <kernel/fs/stat.h>
#include <kernel/fs/vfs.h>
//---
// 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));
}

View File

@ -1,5 +1,8 @@
#include <stdint.h>
#include <kernel/hardware/mpu.h>
#include <kernel/bits/mpu.h>
// 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);
}

View File

@ -1,48 +1,29 @@
// Types
#include <stdint.h>
#include <stddef.h>
#include <sys/types.h>
// Hardware
#include <kernel/hardware/mpu.h>
#include <kernel/bits/mpu.h>
// Internal helpers
#include <kernel/util/atomic.h>
#include <kernel/util/casio.h>
// Modules
#include <kernel/context.h>
#include <kernel/bits/context.h>
#include <kernel/process.h>
#include <kernel/syscall.h>
#include <kernel/scheduler.h>
#include <kernel/loader.h>
// Devices
#include <kernel/devices/tty.h>
#include <kernel/devices/earlyterm.h>
// File System
#include <kernel/fs/vfs.h>
#include <kernel/fs/stat.h>
#include <kernel/fs/smemfs.h>
#include <kernel/fs/gladfs.h>
// Libs
#include <lib/display.h>
#include <lib/string.h>
// 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);

View File

@ -1,56 +0,0 @@
#include <kernel/context.h>
#include <kernel/hardware/keysc.h>
#include <kernel/hardware/intc.h>
#include <kernel/hardware/power.h>
#include <kernel/hardware/tmu.h>
#include <kernel/util/extra.h>
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;
}

View File

@ -1,57 +0,0 @@
#include <kernel/context.h>
#include <kernel/hardware/keysc.h>
#include <kernel/hardware/power.h>
#include <kernel/hardware/intc.h>
#include <kernel/hardware/tmu.h>
#include <kernel/util/extra.h>
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();
}

View File

@ -1,10 +1,7 @@
#include <kernel/devices/tty.h>
#include <kernel/devices/earlyterm.h>
#include <kernel/drivers/keyboard.h>
#include <kernel/drivers/timer.h>
#include <kernel/util/atomic.h>
#include <kernel/context.h>
#include <kernel/syscall.h>
#include <kernel/signal.h>
#include <sys/signal.h>
#include <pthread.h>

View File

@ -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);
}

View File

@ -1,12 +1,12 @@
#include <kernel/drivers/cpg.h>
#include <kernel/hardware/cpg.h>
#include <kernel/devices/earlyterm.h>
#include <kernel/bits/driver.h>
// 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"
};

View File

@ -0,0 +1,138 @@
#include <kernel/hardware/intc.h>
#include <kernel/bits/driver.h>
// 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"
};

View File

@ -1,34 +0,0 @@
#include <kernel/drivers/keyboard.h>
/*
** 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;
}

View File

@ -1,47 +1,40 @@
#include <stdint.h>
#include <stddef.h>
#include <kernel/drivers/keyboard.h>
#include <kernel/drivers/vbr.h>
#include <kernel/hardware/keysc.h>
#include <kernel/hardware/intc.h>
#include <kernel/hardware/power.h>
#include <kernel/hardware/tmu.h>
#include <kernel/util/extra.h>
#include <kernel/bits/driver.h>
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"
};

View File

@ -1,15 +1,12 @@
#include <kernel/drivers/keyboard.h>
#include <kernel/hardware/keysc.h>
#include <kernel/hardware/intc.h>
// 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;

View File

@ -1,6 +1,38 @@
#include <kernel/drivers/keyboard.h>
#include <kernel/util/atomic.h>
/*
** 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)
{

View File

@ -0,0 +1,88 @@
#include <kernel/hardware/power.h>
#include <kernel/bits/driver.h>
#include <kernel/util/extra.h>
#include <string.h>
// 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"
};

View File

@ -1,21 +0,0 @@
#include <kernel/drivers/screen.h>
// 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;
}

View File

@ -0,0 +1,37 @@
#include <kernel/drivers/screen.h>
#include <kernel/bits/driver.h>
// 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"
};

View File

@ -1,11 +1,10 @@
#include <kernel/drivers/screen.h>
// 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);
}

View File

@ -1,5 +1,4 @@
#include <kernel/drivers/timer.h>
#include <kernel/hardware/tmu.h>
#include <kernel/util/atomic.h>
// 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();
}

View File

@ -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

View File

@ -0,0 +1,97 @@
#include <kernel/drivers/screen.h>
#include <kernel/drivers/vbr.h>
#include <kernel/hardware/intc.h>
#include <kernel/hardware/tmu.h>
#include <kernel/bits/driver.h>
// 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"
};

View File

@ -1,10 +1,9 @@
#include <kernel/hardware/tmu.h>
#include <kernel/drivers/timer.h>
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);
}

View File

@ -0,0 +1,51 @@
#include <kernel/drivers/vbr.h>
#include <kernel/bits/driver.h>
#include <string.h>
// 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"
};

View File

@ -1,35 +1,56 @@
#include <kernel/drivers/vbr.h>
#include <kernel/devices/earlyterm.h>
#include <kernel/util/atomic.h>
// 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);
}

View File

@ -3,7 +3,8 @@
#include <kernel/devices/earlyterm.h>
#include <kernel/util/atomic.h>
// 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

View File

@ -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);
}

View File

@ -2,7 +2,7 @@
#include <kernel/util/atomic.h>
/* 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;

View File

@ -1,7 +1,7 @@
#include <kernel/fs/smemfs.h>
/* casio_smem_umount() - Unmount the File System */
int smemfs_umount(void)
int smemfs_USB2_umount(void)
{
// Do nothing for now
return (0);

View File

@ -2,7 +2,7 @@
#include <kernel/util/atomic.h>
/* 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

View File

@ -2,7 +2,7 @@
#include <kernel/util/atomic.h>
/* 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();

View File

@ -2,7 +2,7 @@
#include <kernel/util/atomic.h>
/* 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

View File

@ -3,7 +3,7 @@
#include <kernel/util/atomic.h>
/* 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;

View File

@ -2,7 +2,7 @@
#include <kernel/util/atomic.h>
/* 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;

View File

@ -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;

View File

@ -0,0 +1,29 @@
#include <kernel/fs/smemfs.h>
#include <kernel/util/atomic.h>
/*
** 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);
}

View File

@ -1,11 +1,11 @@
#include <kernel/context.h>
/*#include <kernel/bits/context.h>
#include <kernel/hardware/tmu.h>
#include <kernel/devices/earlyterm.h>
// 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);
}
}*/

View File

@ -1,11 +1,12 @@
#include <kernel/scheduler.h>
#include <kernel/devices/earlyterm.h>
#include <kernel/process.h>
#include <kernel/signal.h>
//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;

View File

@ -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);

View File

@ -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] = {

View File

@ -0,0 +1,51 @@
#include <kernel/util/casio.h>
#include <kernel/util/atomic.h>
#include <kernel/bits/context.h>
#include <kernel/devices/earlyterm.h>
// 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();
}

View File

@ -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*/

View File

@ -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

View File

@ -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) ;