diff --git a/board/fxcg50/board.toml b/board/fxcg50/board.toml index cac7ed8..977f770 100644 --- a/board/fxcg50/board.toml +++ b/board/fxcg50/board.toml @@ -9,7 +9,8 @@ modules = [ 'hypervisor', 'keyboard', 'kmalloc', - 'timer' + 'timer', + 'rtc', ] [drivers] diff --git a/board/fxcg50/fxcg50.ld b/board/fxcg50/fxcg50.ld index 28fb00c..1f6c1ea 100644 --- a/board/fxcg50/fxcg50.ld +++ b/board/fxcg50/fxcg50.ld @@ -60,6 +60,13 @@ SECTIONS _vhex_modules_end = . ; } > userram + /* Exposed device interfaces (.vhex.device) */ + .vhex.device : { + _vhex_devices_start = . ; + KEEP(*(.vhex.device)); + _vhex_devices_end = . ; + } > userram + /* Read-only sections */ .rodata : { /* Read-Only data */ diff --git a/include/vhex/device.h b/include/vhex/device.h new file mode 100644 index 0000000..b39fb68 --- /dev/null +++ b/include/vhex/device.h @@ -0,0 +1,68 @@ +#ifndef __VHEX_DEVICE__ +# define __VHEX_DEVICE__ + +#include +#include + +struct vhex_device +{ + /* device name */ + const char * const name; + + /* device flags */ + byte_union(flags, + uint8_t :1; + uint8_t :1; + uint8_t :1; + uint8_t :1; + + uint8_t :1; + uint8_t :1; + uint8_t :1; + uint8_t FS :1; + ); + + /* device primitives */ + struct { + int (*init)(void); + int (*open)(void **data, const char *pathname, int flags, int mode); + ssize_t (*write)(void *data, const void *buf, size_t size); + ssize_t (*read)(void *data, void *buf, size_t size); + off_t (*lseek)(void *data, off_t offset, int whence); + int (*close)(void *data); + int (*quit)(void); + } primitives; +}; + +/* VHEX_DECLARE_DEVICE(): Declare a device for the kernel + + Use this macro to declare a device by passing it the name of a + vhex_device structure. This macro moves the structure to the + `.vhex.device` sections, which are automatically traversed at startup. */ +#define VHEX_DECLARE_DEVICE(name) \ + VSECTION(".vhex.device") extern struct vhex_device name; + + +//--- +// Internal driver control +// +// The following data is exposed for introspection and debugging purposes; it +// is not part of the vhex API. There is *no stability guarantee* that the +// following types and functions will remain unchanged in future minor and +// patch versions. +//--- + +/* Number of drivers in the (vhex_drivers) array */ +#define vhex_device_count() \ + ((struct vhex_device *)&vhex_devices_end \ + - (struct vhex_device *)&vhex_devices_start) + +/* driver table */ +#define vhex_device_table() \ + ((struct vhex_device *)&vhex_devices_start) + +/* provided by the linker script */ +extern uintptr_t vhex_devices_start; +extern uintptr_t vhex_devices_end; + +#endif /* __VHEX_DEVICE__ */ diff --git a/include/vhex/driver.h b/include/vhex/driver.h index b31557b..fdce071 100644 --- a/include/vhex/driver.h +++ b/include/vhex/driver.h @@ -43,7 +43,7 @@ struct vhex_driver /* default flags for the driver */ byte_union(flags, - uint8_t :1; + uint8_t RTC :1; uint8_t KEYBOARD :1; uint8_t TIMER :1; uint8_t DISPLAY :1; diff --git a/include/vhex/driver/mpu/sh/sh7305/cpg.h b/include/vhex/driver/mpu/sh/sh7305/cpg.h index 7a22302..b15b7ac 100644 --- a/include/vhex/driver/mpu/sh/sh7305/cpg.h +++ b/include/vhex/driver/mpu/sh/sh7305/cpg.h @@ -14,7 +14,7 @@ /* sh7305_cpg - Clock Pulse Generator registers Fields marked with [*] don't have the meaning described in the SH7724 documentation. */ -struct sh7305_cpg +struct __sh7305_cpg { lword_union(FRQCR, uint32_t KICK :1; /* Flush FRQCRA modifications */ @@ -25,7 +25,7 @@ struct sh7305_cpg uint32_t SFC :4; /* Sphi divider 1 [*] */ uint32_t BFC :4; /* Bphi divider 1 [*] */ uint32_t :4; - uint32_t P1FC :4; /* Pphi divider 1 [*] */ + uint32_t PFC :4; /* Pphi divider 1 [*] */ ); pad(0x4); @@ -83,7 +83,8 @@ struct sh7305_cpg lword_union(SSCGCR, uint32_t SSEN :1; /* Spread Spectrum Enable */ - uint32_t :31; + uint32_t :30; + uint32_t SSEN_EMU:1; /* Emulateur enable */ ); pad(0x8); @@ -95,11 +96,14 @@ struct sh7305_cpg ); pad(0x0c); - uint32_t LSTATS; + lword_union(LSTATS, + uint32_t :31; + uint32_t FRQF : 1; /* frequency changing status */ + ); } VPACKED(4); -#define SH7305_CPG (*((volatile struct sh7305_cpg *)0xa4150000)) +#define SH7305_CPG (*((volatile struct __sh7305_cpg *)0xa4150000)) //--- // kernel-level API diff --git a/include/vhex/driver/mpu/sh/sh7305/intc.h b/include/vhex/driver/mpu/sh/sh7305/intc.h index 847d626..c8a7d90 100644 --- a/include/vhex/driver/mpu/sh/sh7305/intc.h +++ b/include/vhex/driver/mpu/sh/sh7305/intc.h @@ -465,4 +465,7 @@ extern void *sh7305_intc_install_inth(int blockid, void *gate, size_t size); /* sh7305_intc_priority() : set the interrupt name priority */ extern int sh7305_intc_priority(int intname, int level); +/* sh7305_intc_generic_handler() : install generic interrupt handler */ +extern void *sh7305_intc_generic_handler(int event_code, void *user_inth); + #endif /* __VHEX_ARCH_SH7305_INTC__ */ diff --git a/include/vhex/driver/mpu/sh/sh7305/rtc.h b/include/vhex/driver/mpu/sh/sh7305/rtc.h new file mode 100644 index 0000000..245a602 --- /dev/null +++ b/include/vhex/driver/mpu/sh/sh7305/rtc.h @@ -0,0 +1,135 @@ +#ifndef __VHEX_DRIVER_MPU_SH_SH7305_RTC__ +# define __VHEX_DRIVER_MPU_SH_SH7305_RTC__ + +#include +#include + +//--- +// Hybrid SH7705-SH7305 Real-Time Clock. Refer to: +// "Renesas SH7705 Group Hardware Manual" +// Section 15: "Real-Time Clock (RTC)" +// "Renesas SH7724 User's Manual: Hardware" +// Section 28: "Real-Time Clock (RTC)" +//--- + +/* rtc_BCD2_t - a 2-digit BCD counter with a 1-byte gap */ +typedef struct +{ + byte_union(, + uint8_t TENS :4; + uint8_t ONES :4; + ); + pad(1); + +} VPACKED(2) rtc_BCD2_t; + +/* sh7305_rtc - Date and time access, RTC control */ +struct __sh7305_rtc_s +{ + uint8_t const R64CNT; /* A 64-Hz counter */ + pad(1); + + rtc_BCD2_t RSECCNT; /* Second count */ + rtc_BCD2_t RMINCNT; /* Minute count */ + rtc_BCD2_t RHRCNT; /* Hour count */ + + uint8_t RWKCNT; /* Day of week, must be in [0..6] */ + pad(1); + + rtc_BCD2_t RDAYCNT; /* Day count */ + rtc_BCD2_t RMONCNT; /* Month count */ + + word_union(RYRCNT, /* Year count */ + uint THOUSANDS :4; + uint HUNDREDS :4; + uint TENS :4; + uint ONES :4; + ); + pad(12); /* Alarm registers... */ + + byte_union(RCR1, + uint8_t CF :1; /* Carry flag */ + uint8_t :2; + uint8_t CIE :1; /* Carry interrupt enable */ + uint8_t AIE :1; /* Alarm interrupt enable */ + uint8_t :2; + uint8_t AF :1; /* Alarm flag */ + ); + pad(1); + + byte_union(RCR2, + uint8_t PEF :1; /* Periodic interrupt flag */ + uint8_t PES :3; /* Periodic interrupt interval */ + uint8_t :1; + uint8_t ADJ :1; /* 30-second adjustment */ + uint8_t RESET :1; /* Reset trigger */ + uint8_t START :1; /* Start bit */ + ); + pad(1); + + byte_union(RCR3, + uint8_t BEN :1; /* Periodic interrupt flag */ + uint8_t :7; + ); + pad(1); +} VPACKED(4); + + +#define SH7305_RTC (*((volatile struct __sh7305_rtc_s *)0xa413fec0)) + +//--- +// RTC periodic interrupt +// The real-time clock produces a regular interrupt which may be used as a +// timer with a maximum frequency of 256 Hz. It is also useful to check +// that the clock settings (see ) are properly detected, by +// comparing the detected frequencies with the RTC. +//--- + +/* Possible frequency settings for the RTC's interrupt */ +enum +{ + RTC_500mHz = 7, + RTC_1Hz = 6, + RTC_2Hz = 5, + RTC_4Hz = 4, + RTC_16Hz = 3, + RTC_64Hz = 2, + RTC_256Hz = 1, + RTC_NONE = 0, +}; + +/* rtc_call: Indirect call with up to 4 register arguments */ +struct rtc_call { + void *function; + uint32_t args[4]; +}; + +/* RTC_CALL(): Build an callback from function and arguments */ +#define RTC_CALL(fct, ...) \ + (struct rtc_call){ \ + .function = (void*)fct, \ + .args = { __VA_ARGS__ } \ + } + +/* rtc_periodic_enable(): Enable the periodic interrupt + + This function sets up the periodic interrupt to invoke the provided callback + regularly. As with timers, the callback must return either TIMER_CONTINUE or + TIMER_STOP. + + Note that the timing of the first callback is always uncertain. A 1 Hz timer + set up when half of the current second is already elapsed will be called for + the first time after only 500 ms, for instance. + + @frequency Periodic interrupt frequency + @callback Function to call back at the specified frequency + Returns true on success, false if the interrupt is already in use. */ +extern bool sh7305_rtc_periodic_enable(int frequency, struct rtc_call callback); + +/* rtc_periodic_disable(): Stop the periodic interrupt + + This has the same effect as returning TIMER_STOP from the callback, or + setting RTC_NONE as the parameter for rtc_periodic_enable(). */ +extern void sh7305_rtc_periodic_disable(void); + +#endif /* __VHEX_DRIVER_MPU_SH_SH7305_RTC__ */ diff --git a/include/vhex/fs.h b/include/vhex/fs.h new file mode 100644 index 0000000..4f642e2 --- /dev/null +++ b/include/vhex/fs.h @@ -0,0 +1,34 @@ +#ifndef __VHEX_FS_INFORMATION__ +# define __VHEX_FS_INFORMATION__ + +#include +#include +#include + +/* define the default number of file that can be oppened in the same time */ +#ifndef VHEX_NB_FILE +# define VHEX_NB_FILE 8 +#endif /* VHEX_NB_FILE */ + +/* internal file system information */ +struct __fs_info { + struct vhex_device fs; + void *table[VHEX_NB_FILE]; +}; + +extern struct __fs_info fs_info; + +//--- +// Internal API +//--- + +/* fs_table_reserve() : reserve file descriptor */ +extern int fs_table_reserve(void **data); + +/* fs_table_find() : find device-specific data */ +extern int fs_table_find(void **data, int fd); + +/* fs_table_remove() : remove file descriptor */ +extern int fs_table_remove(int fd); + +#endif /* __VHEX_FS_INFORMATION__ */ diff --git a/include/vhex/fs/fugue.h b/include/vhex/fs/fugue.h new file mode 100644 index 0000000..2d7a377 --- /dev/null +++ b/include/vhex/fs/fugue.h @@ -0,0 +1,12 @@ +#ifndef __VHEX_FS_FUGUE__ +# define __VHEX_FS_FUGUE__ + +#include + +extern int fugue_open(void **data, const char *pathname, int flags, int mode); +extern ssize_t fugue_write(void *data, const void *buf, size_t size); +extern ssize_t fugue_read(void *data, void *buf, size_t size); +extern off_t fugue_lseek(void *data, off_t offset, int whence); +extern int fugue_close(void *data); + +#endif /* __VHEX_FS_FUGUE__ */ diff --git a/include/vhex/rtc.h b/include/vhex/rtc.h new file mode 100644 index 0000000..db5ab18 --- /dev/null +++ b/include/vhex/rtc.h @@ -0,0 +1,16 @@ +#ifndef __VHEX_DRIVER_RTC__ +# define __VHEX_DRIVER_RTC__ + +#include + +/* rtc_get_time(): Read the current time from the RTC + @time Pointer to rtc_time_t structure (needs not be initialized) */ +extern int rtc_get_time(rtc_time_t *time); + +/* rtc_set_time(): Set current time in the RTC + If [time->week_day] is not in the valid range, it is set to 0. Other fields + are not checked. R64CNT cannot be set to [time->ticks] is ignored. + @time Pointer to new time */ +extern int rtc_set_time(rtc_time_t const *time); + +#endif /* __VHEX_DRIVER_RTC__ */ diff --git a/include/vhex/rtc/interface.h b/include/vhex/rtc/interface.h new file mode 100644 index 0000000..bd67fc3 --- /dev/null +++ b/include/vhex/rtc/interface.h @@ -0,0 +1,13 @@ +#ifndef __VHEX_TIMER_INTERFACE__ +# define __VHEX_TIMER_INTERFACE__ + +#include + +/* rtc_drv_interface - driver interface */ +struct rtc_drv_interface +{ + int (*rtc_get_time)(rtc_time_t *time); + int (*rtc_set_time)(rtc_time_t const *time); +}; + +#endif /* __VHEX_TIMER_INTERFACE__ */ diff --git a/include/vhex/rtc/types.h b/include/vhex/rtc/types.h new file mode 100644 index 0000000..7d458e8 --- /dev/null +++ b/include/vhex/rtc/types.h @@ -0,0 +1,24 @@ +#ifndef __VHEX_RTC_TYPES__ +# define __VHEX_RTC_TYPES__ + +#include + +/* rtc_time_t: A point in time, representable in the RTC registers + + WARNING: A copy of this definition is used in fxlibc, make sure to keep it + in sync. (We don't install kernel headers before compiling the fxlibc, it's + kind of a nightmare for the modest build system.) */ +typedef struct +{ + uint16_t year; /* Years (exact value, e.g. 2018) */ + uint8_t week_day; /* Day of week, (0=Sunday, 6=Saturday) */ + uint8_t month; /* Month (0..11) */ + uint8_t month_day; /* Day of month (1..31) */ + uint8_t hours; /* Hour (0..23) */ + uint8_t minutes; /* Minute (0..59) */ + uint8_t seconds; /* Second (0..59) */ + uint8_t ticks; /* 128-Hz sub-second counter (0...127) */ + +} rtc_time_t; + +#endif /* __VHEX_RTC_TYPES__ */ diff --git a/src/display/dclear.c b/src/display/dclear.c index f701fb2..4da2575 100644 --- a/src/display/dclear.c +++ b/src/display/dclear.c @@ -9,12 +9,17 @@ /* dclear_draw() : real drawing algorithm */ void dclear_render(dsurface_t *surface, uint32_t color) { + uint32_t *vram = surface->vram; + for (size_t i = 0; i < surface->width * (surface->height/2); ++i) + vram[i] = color; +#if 0 uint32_t *vram; int size = (surface->y1 == 220) ? 792 : 1980; vram = surface->vram; for (int i = 0; i < size; ++i) vram[i] = color; +#endif } //--- diff --git a/src/driver/mpu/sh/sh7305/cpg/cpg.c b/src/driver/mpu/sh/sh7305/cpg/cpg.c index 5d328a2..dcc668a 100644 --- a/src/driver/mpu/sh/sh7305/cpg/cpg.c +++ b/src/driver/mpu/sh/sh7305/cpg/cpg.c @@ -21,7 +21,7 @@ void cpg_clock_freq(struct cpg_clock_frequency *freq) int divb = CPG.FRQCR.BFC; int divi = CPG.FRQCR.IFC; int divs = CPG.FRQCR.SFC; - int divp = CPG.FRQCR.P1FC; + int divp = CPG.FRQCR.PFC; freq->Bphi_div = 1 << (divb + 1); freq->Iphi_div = 1 << (divi + 1); @@ -47,25 +47,143 @@ void cpg_clock_freq(struct cpg_clock_frequency *freq) //--- struct cpg_ctx { - uint32_t SSCGCR; + struct __sh7305_cpg hw; }; /* __cpg_configure() : configure the CPG */ static void __cpg_configure(struct cpg_ctx *state) { - (void)state; + /* Configure the all bus divier and multiplicator + <> PLL : 232.31Mhz (x16) + <> Iphi (CPU) : 116.15Mhz (/2) + <> Sphi (SuperH) : 58.07Mhz (/4) + <> Bphi (BSC) : 58.07Mhz (/4) + <> Pphi (peripheral) : 29.03Mhz (/8) + */ + state->hw.FRQCR.STC = 15; + state->hw.FRQCR.IFC = 0; + state->hw.FRQCR.SFC = 1; + state->hw.FRQCR.BFC = 1; + state->hw.FRQCR.PFC = 2; + + /* Configure FSI clock (disable by default) */ + state->hw.FSICLKCR.CLKSTP = 1; + + /* Configure DD clock (disable by default) */ + state->hw.DDCLKCR.CLKSTP = 1; + + /* Configure USB clock (disable by default) */ + state->hw.USBCLKCR.CLKSTP = 1; + + /* Configure PLL and FLL multiplier + <> enable PLL + <> enable FLL + <> disable CKO output stop + */ + state->hw.PLLCR.PLLE = 1; + state->hw.PLLCR.FLLE = 1; + state->hw.PLLCR.CKOFF = 0; + + /* Configure PLL multiplication ratio (disable by default) */ + state->hw.PLL2CR.MUL = 0; + + /* Configure SPU (disable by default) */ + state->hw.SPUCLKCR.CLKSTP = 1; + + /* Configure Spread Spectrum (force disable) */ + state->hw.SSCGCR.SSEN_EMU = 0; + state->hw.SSCGCR.SSEN = 0; + + /* Configure FLL division/multiplicator + <> force FLL multiplication Ratio with x(1/2) + <> use 1017 (default value of the module) as multiplicator wich will + give us ~16Mhz (Casio use 900 instead of 1017 wich is ~14Mhz): + + ( 32768 * 1017 ) / 2 = 16 662 528 Hz + ( 32768 * 900 ) / 2 = 14 745 600 Hz + */ + state->hw.FLLFRQ.SELXM = 1; + state->hw.FLLFRQ.FLF = 1017; } /* __cpg_hsave() : save hardware information */ static void __cpg_hsave(struct cpg_ctx *state) { - (void)state; + state->hw.FRQCR.STC = SH7305_CPG.FRQCR.STC; + state->hw.FRQCR.IFC = SH7305_CPG.FRQCR.IFC; + state->hw.FRQCR.SFC = SH7305_CPG.FRQCR.SFC; + state->hw.FRQCR.BFC = SH7305_CPG.FRQCR.BFC; + state->hw.FRQCR.PFC = SH7305_CPG.FRQCR.PFC; + + state->hw.FSICLKCR.DIVB = SH7305_CPG.FSICLKCR.DIVB; + state->hw.FSICLKCR.CLKSTP = SH7305_CPG.FSICLKCR.CLKSTP; + state->hw.FSICLKCR.SRC = SH7305_CPG.FSICLKCR.SRC; + state->hw.FSICLKCR.DIVA = SH7305_CPG.FSICLKCR.DIVA; + + state->hw.DDCLKCR.CLKSTP = SH7305_CPG.DDCLKCR.CLKSTP; + state->hw.DDCLKCR.SRC = SH7305_CPG.DDCLKCR.SRC; + state->hw.DDCLKCR.DIV = SH7305_CPG.DDCLKCR.DIV; + + state->hw.USBCLKCR.CLKSTP = SH7305_CPG.USBCLKCR.CLKSTP; + + state->hw.PLLCR.PLLE = SH7305_CPG.PLLCR.PLLE; + state->hw.PLLCR.FLLE = SH7305_CPG.PLLCR.FLLE; + state->hw.PLLCR.CKOFF = SH7305_CPG.PLLCR.CKOFF; + + state->hw.PLL2CR.MUL = SH7305_CPG.PLL2CR.MUL; + + state->hw.SPUCLKCR.CLKSTP = SH7305_CPG.SPUCLKCR.CLKSTP; + state->hw.SPUCLKCR.SRC = SH7305_CPG.SPUCLKCR.SRC; + state->hw.SPUCLKCR.DIV = SH7305_CPG.SPUCLKCR.DIV; + + state->hw.SSCGCR.SSEN = SH7305_CPG.SSCGCR.SSEN; + state->hw.SSCGCR.SSEN_EMU = SH7305_CPG.SSCGCR.SSEN_EMU; + + state->hw.FLLFRQ.SELXM = SH7305_CPG.FLLFRQ.SELXM; + state->hw.FLLFRQ.FLF = SH7305_CPG.FLLFRQ.FLF; } /* __cpg_hrestore() : restore hardware information */ static void __cpg_hrestore(struct cpg_ctx *state) { - (void)state; + SH7305_CPG.FRQCR.STC = state->hw.FRQCR.STC; + SH7305_CPG.FRQCR.IFC = state->hw.FRQCR.IFC; + SH7305_CPG.FRQCR.SFC = state->hw.FRQCR.SFC; + SH7305_CPG.FRQCR.BFC = state->hw.FRQCR.BFC; + SH7305_CPG.FRQCR.PFC = state->hw.FRQCR.PFC; + + SH7305_CPG.FSICLKCR.DIVB = state->hw.FSICLKCR.DIVB; + SH7305_CPG.FSICLKCR.CLKSTP = state->hw.FSICLKCR.CLKSTP; + SH7305_CPG.FSICLKCR.SRC = state->hw.FSICLKCR.SRC; + SH7305_CPG.FSICLKCR.DIVA = state->hw.FSICLKCR.DIVA; + + SH7305_CPG.DDCLKCR.CLKSTP = state->hw.DDCLKCR.CLKSTP; + SH7305_CPG.DDCLKCR.SRC = state->hw.DDCLKCR.SRC; + SH7305_CPG.DDCLKCR.DIV = state->hw.DDCLKCR.DIV; + + SH7305_CPG.USBCLKCR.CLKSTP = state->hw.USBCLKCR.CLKSTP; + + SH7305_CPG.PLLCR.PLLE = state->hw.PLLCR.PLLE; + SH7305_CPG.PLLCR.FLLE = state->hw.PLLCR.FLLE; + SH7305_CPG.PLLCR.CKOFF = state->hw.PLLCR.CKOFF; + + SH7305_CPG.PLL2CR.MUL = state->hw.PLL2CR.MUL; + + SH7305_CPG.SPUCLKCR.CLKSTP = state->hw.SPUCLKCR.CLKSTP; + SH7305_CPG.SPUCLKCR.SRC = state->hw.SPUCLKCR.SRC; + SH7305_CPG.SPUCLKCR.DIV = state->hw.SPUCLKCR.DIV; + + SH7305_CPG.SSCGCR.SSEN = state->hw.SSCGCR.SSEN; + SH7305_CPG.SSCGCR.SSEN_EMU = state->hw.SSCGCR.SSEN_EMU; + + SH7305_CPG.FLLFRQ.SELXM = state->hw.FLLFRQ.SELXM; + SH7305_CPG.FLLFRQ.FLF = state->hw.FLLFRQ.FLF; + + SH7305_CPG.FRQCR.KICK = 1; + while (SH7305_CPG.LSTATS.FRQF != 0) { __asm__ volatile ("nop"); } + + SH7305_CPG.PLL2CR.KICK = 1; + while (SH7305_CPG.LSTATS.FRQF != 0) { __asm__ volatile ("nop"); } } struct vhex_driver drv_cpg = { @@ -75,4 +193,4 @@ struct vhex_driver drv_cpg = { .configure = (void*)&__cpg_configure, .state_size = sizeof(struct cpg_ctx) }; -VHEX_DECLARE_DRIVER(03, drv_cpu); +VHEX_DECLARE_DRIVER(03, drv_cpg); diff --git a/src/driver/mpu/sh/sh7305/intc/install.c b/src/driver/mpu/sh/sh7305/intc/install.c deleted file mode 100644 index 9eea85f..0000000 --- a/src/driver/mpu/sh/sh7305/intc/install.c +++ /dev/null @@ -1,5 +0,0 @@ -#include -#include -#include - - diff --git a/src/driver/mpu/sh/sh7305/intc/intc.c b/src/driver/mpu/sh/sh7305/intc/intc.c index 23b1c16..1e48fc3 100644 --- a/src/driver/mpu/sh/sh7305/intc/intc.c +++ b/src/driver/mpu/sh/sh7305/intc/intc.c @@ -120,6 +120,24 @@ void *sh7305_intc_install_inth(int event_code, void *gate, size_t size) ); } +/* sh7305_intc_generic_handler() : install generic interrupt handler */ +void *sh7305_intc_generic_handler(int event_code, void *user_inth) +{ + extern void vhex_sh7305_intc_generic_handler(void); + + void *h = sh7305_intc_install_inth( + event_code, + sh7305_intc_generic_handler, + 32 + ); + if(!h) return false; + + *(void **)(h + 28) = user_inth; + + return h; +} + + //--- // hardware configuration call //--- diff --git a/src/driver/mpu/sh/sh7305/intc/inth.S b/src/driver/mpu/sh/sh7305/intc/inth.S index e32778f..2893e23 100644 --- a/src/driver/mpu/sh/sh7305/intc/inth.S +++ b/src/driver/mpu/sh/sh7305/intc/inth.S @@ -66,3 +66,21 @@ _vhex_inth_sh7305: .first_entry: +/* _vhex_sh7305_intc_generic_handler: Standard interrupt handler + + This is a generic interrupt handler that calls back into a C function, + useful for complex handling or simple drivers that benefit more from + simplicity than razor-sharp performance. */ + +.section .vhex.blocks, "ax" +.align 4 + +.global _vhex_sh7305_intc_generic_handler /* 32 bytes */ + +_vhex_sh7305_intc_generic_handler: + mov.l 1f, r1 + jmp @r1 + mov r0, r4 + + .zero 22 /* Indirect call to be made */ +1: .long 0 /* Address of the runtime */ diff --git a/src/driver/mpu/sh/sh7305/keysc/keysc.c b/src/driver/mpu/sh/sh7305/keysc/keysc.c index 72d22f5..d593cad 100644 --- a/src/driver/mpu/sh/sh7305/keysc/keysc.c +++ b/src/driver/mpu/sh/sh7305/keysc/keysc.c @@ -6,7 +6,6 @@ /* define the private KeyScan context structure */ struct keysc_ctx { struct __sh7305_keysc_s keysc; - uint16_t iprf; }; /* hardware configuration call */ diff --git a/src/driver/mpu/sh/sh7305/rtc/rtc.c b/src/driver/mpu/sh/sh7305/rtc/rtc.c new file mode 100644 index 0000000..05a8d61 --- /dev/null +++ b/src/driver/mpu/sh/sh7305/rtc/rtc.c @@ -0,0 +1,231 @@ +#include +#include +#include +#include + +#include + +//--- +// RTC periodic interrupt +//--- + +static struct rtc_call rtc_call; + +/* rtc_periodic interrupt() : internal interrupt handler */ +static void sh7305_rtc_periodic_inth(void) +{ + int (*routine)( + uintptr_t, + uintptr_t, + uintptr_t, + uintptr_t + ) = rtc_call.function; + + int rc = routine( + rtc_call.args[0], + rtc_call.args[1], + rtc_call.args[2], + rtc_call.args[3] + ); + + /* Clear the interrupt flag */ + do SH7305_RTC.RCR2.PEF = 0; + while(SH7305_RTC.RCR2.PEF); + + /* Stop the interrupt if the callback returns non-zero */ + if(rc) sh7305_rtc_periodic_disable(); +} + +/* rtc_periodic_enable(): Enable the periodic interrupt */ +bool sh7305_rtc_periodic_enable(int frequency, struct rtc_call callback) +{ + /* Refuse to override an existing interrupt */ + if(SH7305_RTC.RCR2.PES != RTC_NONE) return false; + if(frequency == RTC_NONE) + { + sh7305_rtc_periodic_disable(); + return true; + } + + /* Temporarily disable the interrupt and set up the callback */ + SH7305_RTC.RCR2.PES = RTC_NONE; + memcpy(&rtc_call, &callback, sizeof(struct rtc_call)); + + /* Clear the interrupt flag */ + do SH7305_RTC.RCR2.PEF = 0; + while(SH7305_RTC.RCR2.PEF); + + /* Enable the interrupt */ + SH7305_RTC.RCR2.PES = frequency; + return true; +} + +/* rtc_periodic_disable(): Stop the periodic interrupt */ +void sh7305_rtc_periodic_disable(void) +{ + SH7305_RTC.RCR2.PES = RTC_NONE; +} + +//--- +// Define driver information +//--- + +struct rtc_ctx { + struct __sh7305_rtc_s rtc; +}; + +/* __rtc_configure() : configure the RTC */ +static void __rtc_configure(struct rtc_ctx *state) +{ + /* Clear and disable the carry and alamr interrupts */ + state->rtc.RCR1.CF = 0; + state->rtc.RCR1.CIE = 0; + state->rtc.RCR1.AIE = 0; + state->rtc.RCR1.AF = 0; + + /* Disable the periodic interrupt flag */ + state->rtc.RCR2.PEF = 0; + state->rtc.RCR2.PES = RTC_NONE; + state->rtc.RCR2.ADJ = 0; + state->rtc.RCR2.RESET = 1; + state->rtc.RCR2.START = 1; + + /* Disable year alarm check */ + state->rtc.RCR3.BEN = 0; + + /* set the interrupt level (max) */ + sh7305_intc_priority(INTC_RTC_ATI, 0); + sh7305_intc_priority(INTC_RTC_CUI, 0); + sh7305_intc_priority(INTC_RTC_PRI, 1); + + /* intall the RTC interupt handler */ + sh7305_intc_generic_handler(0xaa0, &sh7305_rtc_periodic_inth); +} + +/* __rtc_hsave() : save hardware information */ +static void __rtc_hsave(struct rtc_ctx *state) +{ + /* stop as soon as possible RTC counters */ + state->rtc.RCR2.START = SH7305_RTC.RCR2.START; + SH7305_RTC.RCR2.START = 0; + + state->rtc.RCR1.CF = SH7305_RTC.RCR1.CF; + state->rtc.RCR1.CIE = SH7305_RTC.RCR1.CIE; + state->rtc.RCR1.AIE = SH7305_RTC.RCR1.AIE; + state->rtc.RCR1.AF = SH7305_RTC.RCR1.AF; + + state->rtc.RCR2.PEF = SH7305_RTC.RCR2.PEF; + state->rtc.RCR2.PES = SH7305_RTC.RCR2.PES; + state->rtc.RCR2.ADJ = SH7305_RTC.RCR2.ADJ; + + state->rtc.RCR3.BEN = SH7305_RTC.RCR3.BEN; +} + +/* __rtc_hrestore() : restore hardware information */ +static void __rtc_hrestore(struct rtc_ctx *state) +{ + /* stop as soon as possible RTC counters */ + SH7305_RTC.RCR2.START = 0; + + SH7305_RTC.RCR1.CF = state->rtc.RCR1.CF; + SH7305_RTC.RCR1.CIE = state->rtc.RCR1.CIE; + SH7305_RTC.RCR1.AIE = state->rtc.RCR1.AIE; + SH7305_RTC.RCR1.AF = state->rtc.RCR1.AF; + + SH7305_RTC.RCR2.PEF = state->rtc.RCR2.PEF; + SH7305_RTC.RCR2.PES = state->rtc.RCR2.PES; + SH7305_RTC.RCR2.ADJ = state->rtc.RCR2.ADJ; + + SH7305_RTC.RCR3.BEN = state->rtc.RCR3.BEN; + + SH7305_RTC.RCR2.START = state->rtc.RCR2.START; +} + +//--- +// User API +//--- + +/* int8(), int16(): Convert BCD to integer */ +static int int8(uint8_t bcd) +{ + return (bcd & 0x0f) + 10 * (bcd >> 4); +} +static int int16(uint16_t bcd) +{ + return (bcd & 0xf) + 10 * ((bcd >> 4) & 0xf) + 100 * ((bcd >> 8) & 0xf) + + 1000 * (bcd >> 12); +} + +/* bcd8(), bcd16(): Convert integer to BCD */ +static uint8_t bcd8(int integer) +{ + integer %= 100; + return ((integer / 10) << 4) | (integer % 10); +} +static uint16_t bcd16(int integer) +{ + integer %= 10000; + return (bcd8(integer / 100) << 8) | bcd8(integer % 100); +} + +/* sh7305_rtc_get_time(): Read the current time from the RTC */ +int sh7305_rtc_get_time(rtc_time_t *time) +{ + do { + SH7305_RTC.RCR1.CF = 0; + + time->ticks = SH7305_RTC.R64CNT; + time->seconds = int8(SH7305_RTC.RSECCNT.byte); + time->minutes = int8(SH7305_RTC.RMINCNT.byte); + time->hours = int8(SH7305_RTC.RHRCNT.byte); + time->month_day = int8(SH7305_RTC.RDAYCNT.byte); + time->month = int8(SH7305_RTC.RMONCNT.byte); + time->year = int16(SH7305_RTC.RYRCNT.word); + time->week_day = SH7305_RTC.RWKCNT; + + } while(SH7305_RTC.RCR1.CF != 0); + return 0; +} + +/* sh7305_rtc_set_time(): Set current time in the RTC */ +int sh7305_rtc_set_time(rtc_time_t const *time) +{ + int wday = time->week_day; + if(wday >= 7) wday = 0; + + do { + SH7305_RTC.RCR1.CF = 0; + + SH7305_RTC.RSECCNT.byte = bcd8(time->seconds); + SH7305_RTC.RMINCNT.byte = bcd8(time->minutes); + SH7305_RTC.RHRCNT.byte = bcd8(time->hours); + SH7305_RTC.RDAYCNT.byte = bcd8(time->month_day); + SH7305_RTC.RMONCNT.byte = bcd8(time->month); + SH7305_RTC.RYRCNT.word = bcd16(time->year); + SH7305_RTC.RWKCNT = wday; + + } while(SH7305_RTC.RCR1.CF != 0); + return 0; +} + +//--- +// Declare driver +//--- + +struct vhex_driver drv_rtc = { + .name = "RTC", + .hsave = (void*)&__rtc_hsave, + .hrestore = (void*)&__rtc_hrestore, + .configure = (void*)&__rtc_configure, + .state_size = sizeof(struct rtc_ctx), + .flags = { + .RTC = 1, + .SHARED = 0, + .UNUSED = 0, + }, + .module_data = &(struct rtc_drv_interface){ + .rtc_get_time = &sh7305_rtc_get_time, + .rtc_set_time = &sh7305_rtc_set_time, + } +}; +VHEX_DECLARE_DRIVER(06, drv_rtc); diff --git a/src/driver/mpu/sh/sh7305/tmu/tmu.c b/src/driver/mpu/sh/sh7305/tmu/tmu.c index a4a2c09..09bd32c 100644 --- a/src/driver/mpu/sh/sh7305/tmu/tmu.c +++ b/src/driver/mpu/sh/sh7305/tmu/tmu.c @@ -381,27 +381,29 @@ int sh7305_tmu_prof_init(timer_prof_t *prof) /* sh7305_tmu_prof_enter(): Start counting time for a function */ void sh7305_tmu_prof_enter(timer_prof_t *prof) { - prof->elapsed += *tmu_prof_tcnt; + if (tmu_prof_tcnt != NULL) + prof->elapsed += *tmu_prof_tcnt; } /* sh7305_tmu_prof_enter_rec(): Start counting time for a recursive function */ void sh7305_tmu_prof_enter_rec(timer_prof_t *prof) { - if (!prof->rec++) + if (!prof->rec++ && tmu_prof_tcnt != NULL) prof->elapsed += *tmu_prof_tcnt; } /* sh7305_tmu_prof_leave_rec(): Start counting time for a recursive function */ void sh7305_tmu_prof_leave_rec(timer_prof_t *prof) { - if (!--prof->rec) + if (!--prof->rec && tmu_prof_tcnt != NULL) prof->elapsed -= *tmu_prof_tcnt; } /* sh7305_tmu_prof_leave(): Stop counting time for a function */ void sh7305_tmu_prof_leave(timer_prof_t *prof) { - prof->elapsed -= *tmu_prof_tcnt; + if (tmu_prof_tcnt != NULL) + prof->elapsed -= *tmu_prof_tcnt; } diff --git a/src/driver/screen/R61524/r61524.c b/src/driver/screen/R61524/r61524.c index 3a666a2..e898a6d 100644 --- a/src/driver/screen/R61524/r61524.c +++ b/src/driver/screen/R61524/r61524.c @@ -7,6 +7,8 @@ // R61524 driver API //--- +uint32_t vhex_vram[396*(224/2)]; + /* r61524_frame_start() - prepar the screen and reset surfaces */ VALIGNED(4) int r61524_frame_start(dsurface_t *surface) { @@ -30,18 +32,24 @@ VALIGNED(4) int r61524_frame_start(dsurface_t *surface) r61524_select(write_data); /* initialize surface information */ - surface->vram = (void*)0xe5017000; +// surface->vram = (void*)0xe5017000; +// surface->width = 396; +// surface->height = 10; + surface->vram = (void*)vhex_vram; surface->width = 396; - surface->height = 10; + surface->height = 224; surface->x1 = 0; surface->y1 = 0; surface->x2 = 395; - surface->y2 = 9; + surface->y2 = 223; return (0); } VALIGNED(4) int r61524_frame_frag_next(dsurface_t *surface) { + (void)surface; + return -1; +#if 0 surface->y1 += 10; if (surface->y1 >= 224) { surface->y1 -= 10; @@ -52,10 +60,16 @@ VALIGNED(4) int r61524_frame_frag_next(dsurface_t *surface) surface->height = 4; surface->y2 += surface->height; return (0); +#endif } VALIGNED(4) VWEAK int r61524_frame_frag_send(dsurface_t *surface) { + uint16_t *vram = surface->vram; + for (int i = 0; i < 396*224; ++i) { + r61524_write(vram[i]); + } +#if 0 uint16_t * restrict yram = surface->vram; int size = (surface->y1 == 220) ? 1584 : 3960; @@ -63,6 +77,7 @@ VALIGNED(4) VWEAK int r61524_frame_frag_send(dsurface_t *surface) r61524_write(yram[i]); } return (0); +#endif } VALIGNED(4) int r61524_frame_end(dsurface_t *surface) diff --git a/src/fs/_table.c b/src/fs/_table.c new file mode 100644 index 0000000..7b15c51 --- /dev/null +++ b/src/fs/_table.c @@ -0,0 +1,42 @@ +#if 0 +#include + +#include + +/* fs_table_reserve() : reserve file descriptor */ +int fs_table_reserve(void **data) +{ + *data = NULL; + for (int i = 3 ; i < VHEX_NB_FILE; ++i) { + if (fs_info.table[i] == NULL) { + fs_info.table[i] = (void*)0xdeadbeef; + *data = &fs_info.table[i]; + return 0; + } + } + return ENFILE; +} + +/* fs_table_find() : find device-specific data */ +int fs_table_find(void **data, int fd) +{ + *data = NULL; + if (fd < 0 || fd >= VHEX_NB_FILE) + return EBADF; + if (fs_info.table[fd] == NULL) + return EBADF; + *data = fs_info.table[fd]; + return 0; +} + +/* fs_table_remove() : remove file descriptor */ +int fs_table_remove(int fd) +{ + if (fd < 0 || fd >= VHEX_NB_FILE) + return EBADF; + if (fs_info.table[fd] == NULL) + return EBADF; + fs_info.table[fd] = NULL; + return 0; +} +#endif diff --git a/src/fs/close.c b/src/fs/close.c new file mode 100644 index 0000000..21ceb4b --- /dev/null +++ b/src/fs/close.c @@ -0,0 +1,32 @@ +#include + +#include + +int close(int fd) +{ + (void)fd; +#if 0 + void *data; + + errno = fs_table_find(&data, fd); + if (errno != 0) + return -1; + + if (fd >= 0 && fd <= 2) { + //TODO:support keyboard + //TODO:support display + errno = ENODEV; + return -1; + } + + if (fs_info.fs.primitives.write == NULL) { + errno = EIO; + return -1; + } + errno = fs_info.fs.primitives.close(data); + if (errno != 0) + return -1; + + return fs_table_remove(fd); +#endif +} diff --git a/src/fs/fs.c b/src/fs/fs.c index 7d3e37f..81ce846 100644 --- a/src/fs/fs.c +++ b/src/fs/fs.c @@ -1,28 +1,46 @@ -#include -#include +#if 0 +#include +#include +#include -ssize_t write(int fd, const void *buf, size_t size) +#include + +/* module init */ + +/* internal file system information */ +struct __fs_info fs_info; + +/* __fs_init() : initialize the fs module */ +static void __fs_init(void) { - (void)fd; - (void)buf; - (void)size; + struct vhex_device *device = vhex_device_table(); + for (int i = 0; i < vhex_device_count(); ++i) { + if (device[i].flags.FS) { + memcpy( + &fs_info.fs, + &device[i], + sizeof(struct vhex_device) + ); + break; + } + } + //TODO: initialise STDIN_FILENO + //TODO: initialise STDOUT_FILENO + //TODO: initialise STDERR_FILENO } -ssize_t read(int fd, void *buf, size_t size) +/* __display_quit() : uninit the fs module */ +static void __fs_quit(void) { - (void)fd; - (void)buf; - (void)size; + //Nothing to do } -off_t lseek(int fd, off_t offset, int whence) -{ - (void)fd; - (void)offset; - (void)whence; -} +/* declare the fs module */ -int close(int fd) -{ - (void)fd; -} +struct vhex_module mod_fs = { + .name = "fs", + .init = &__fs_init, + .quit = &__fs_quit, +}; +VHEX_DECLARE_MODULE(03, mod_fs); +#endif diff --git a/src/fs/fugue/close.c b/src/fs/fugue/close.c new file mode 100644 index 0000000..7602aa6 --- /dev/null +++ b/src/fs/fugue/close.c @@ -0,0 +1,6 @@ +#include + +int fugue_close(void *data) +{ + (void)data; +} diff --git a/src/fs/fugue/fugue.c b/src/fs/fugue/fugue.c new file mode 100644 index 0000000..5b52f0a --- /dev/null +++ b/src/fs/fugue/fugue.c @@ -0,0 +1,23 @@ +#if 0 +#include +#include + +/* declare device */ + +struct vhex_device dev_fugue = { + .name = "Fugue", + .flags = { + .FS = 1 + }, + .primitives = { + .init = NULL, + .open = &fugue_open, + .write = &fugue_write, + .read = &fugue_read, + .lseek = &fugue_lseek, + .close = &fugue_close, + .quit = NULL + } +}; +VHEX_DECLARE_DEVICE(dev_fugue); +#endif diff --git a/src/fs/fugue/lseek.c b/src/fs/fugue/lseek.c new file mode 100644 index 0000000..9fdd25a --- /dev/null +++ b/src/fs/fugue/lseek.c @@ -0,0 +1,8 @@ +#include + +off_t fugue_lseek(void *data, off_t offset, int whence) +{ + (void)data; + (void)offset; + (void)whence; +} diff --git a/src/fs/fugue/open.c b/src/fs/fugue/open.c new file mode 100644 index 0000000..d8440ec --- /dev/null +++ b/src/fs/fugue/open.c @@ -0,0 +1,146 @@ +#if 0 +#include + +#include +#include +#include + +/* fugue_open() : try to open file */ +int fugue_open(void **data, const char *pathname, int flags, int mode) +{ + (void)mode; + if (data == NULL || pathname == NULL) { + errno = EFAULT; + return -1; + } + + /* we need to convert the pathname into FONTCHARACTER format with meta + information inside (mainly the device) */ + uint16_t *fcpath = fs_path_normalize_fc(pathname); + if (fcpath == NULL) { + errno = ENOMEM; + return -1; + } + + /* handle open mode */ + int bfile_mode = BFile_ReadOnly; + if(flags & O_WRONLY) + bfile_mode = BFile_WriteOnly; + else if(flags & O_RDWR) + bfile_mode = BFile_ReadWrite; + + /* Exclusive open means no sense unless creation is also requested */ + bool excl = (flags & O_EXCL) && (flags & O_CREAT); + /* Truncation requires the file to be removed/recreated */ + bool trunc = (flags & O_TRUNC) && (flags & O_CREAT); + + /* Stat the entry. A special case is needed for the root, which doesn't + respond well. fs_path_normalize_fc() normalizes the path so we just + have to check for the fixed string "\\fls0\". */ + bool exists; + if(!memcmp(fcpath, u"\\\\fls0\\", 16)) { + exists = true; + type = BFile_Type_Directory; + } else { + exists = (BFile_Ext_Stat(fcpath, &type, NULL) == 0); + if(!exists) type = -1; + } + + /* If the entry exists and O_EXCL was requested, fail. */ + if(exists && excl) { + errno = EEXIST; + rc = -1; + goto end; + } + + /* If the entry is not a directory but O_DIRECTORY is set, fail. If the + directory doesn't exist, we fail regardless of O_CREAT. */ + if((flags & O_DIRECTORY) && type != BFile_Type_Directory) { + errno = (exists ? ENOTDIR : ENOENT); + rc = -1; + goto end; + } + + /* If the entry is a directory, open it as such */ + if(type == BFile_Type_Directory) { + void *dp = fugue_dir_explore(path); + fugue_descriptor_t data = { + .type = &fugue_dir_descriptor_type, + .data = dp, + }; + fd = fugue_create_descriptor(&data); + rc = fd; + goto end; + } + + /* Try and open the file normally, unless O_TRUNC is specified without + O_EXCL, in which case we simply delete and recreate the file. */ + fugue_fd = BFile_EntryNotFound; + if(trunc == 0) + fugue_fd = BFile_Open(fcpath, bfile_mode); + + /* If O_TRUNC is requested and either the file exists or we can create + it, remove it. (If fugue_fd < 0 an opening error might still have + occurred so we delete it just in case.) */ + if((flags & O_TRUNC) && (fugue_fd >= 0 || (flags & O_CREAT))) { + if(fugue_fd >= 0) + BFile_Close(fugue_fd); + BFile_Remove(fcpath); + fugue_fd = BFile_EntryNotFound; + } + + /* If the file does not exist and O_CREAT is set, create it */ + if((flags & O_CREAT) && ((flags & O_TRUNC) || fugue_fd < 0)) { + new_file_size = 0; + err = BFile_Create(fcpath, BFile_File, &new_file_size); + if(err < 0) { + errno = bfile_error_to_errno(err); + rc = -1; + goto end; + } + fugue_fd = BFile_Open(fcpath, bfile_mode); + } + + /* check error during hadling */ + if(fugue_fd < 0) { + errno = bfile_error_to_errno(fugue_fd); + rc = fugue_fd; + goto end; + } + + /* If O_APPEND is set, move to the end of the file */ + // TODO: O_APPEND should move the cursor before *each* write + int pos = 0; + if((flags & O_APPEND)) { + pos = BFile_Size(fugue_fd); + BFile_Seek(fugue_fd, pos); + } + + /* Return the now-open file descriptor */ + fugue_fd_t *data = malloc(sizeof(fugue_fs_t)); + if(data == NULL) { + BFile_Close(fugue_fd); + goto end; + } + data->fd = fugue_fd; + data->pos = pos; + + /* generate file descriptor information */ + fugue_descriptor_t fd_data = { + .type = &fugue_descriptor_type, + .data = data, + }; + rc = fd = fugue_create_descriptor(&fd_data); + + if(fd == -1) { + BFile_Close(fugue_fd); + free(data); + errno = ENFILE; + goto end; + } + +end: + free(fcpath); + return rc; +} +#endif diff --git a/src/fs/fugue/read.c b/src/fs/fugue/read.c new file mode 100644 index 0000000..33c41be --- /dev/null +++ b/src/fs/fugue/read.c @@ -0,0 +1,8 @@ +#include + +ssize_t fugue_write(void *data, const void *buf, size_t size) +{ + (void)data; + (void)buf; + (void)size; +} diff --git a/src/fs/fugue/write.c b/src/fs/fugue/write.c new file mode 100644 index 0000000..2d3a70b --- /dev/null +++ b/src/fs/fugue/write.c @@ -0,0 +1,8 @@ +#include + +ssize_t fugue_read(void *data, void *buf, size_t size) +{ + (void)data; + (void)buf; + (void)size; +} diff --git a/src/fs/lseek.c b/src/fs/lseek.c new file mode 100644 index 0000000..36279f6 --- /dev/null +++ b/src/fs/lseek.c @@ -0,0 +1,30 @@ +#include + +#include + +off_t lseek(int fd, off_t offset, int whence) +{ + (void)fd; + (void)offset; + (void)whence; +#if 0 + void *data; + + errno = fs_table_find(&data, fd); + if (errno != 0) + return -1; + + if (fd >= 0 && fd <= 2) { + //TODO:support keyboard + //TODO:support display + errno = ENODEV; + return -1; + } + + if (fs_info.fs.primitives.lseek == NULL) { + errno = EIO; + return -1; + } + return fs_info.fs.primitives.lseek(data, offset, whence); +#endif +} diff --git a/src/fs/open.c b/src/fs/open.c new file mode 100644 index 0000000..4babb1e --- /dev/null +++ b/src/fs/open.c @@ -0,0 +1,36 @@ +#include + +#include +#include + +/* open() : try to open file */ +int open(const char *pathname, int flags, ...) +{ + (void)pathname; + (void)flags; +#if 0 + va_list ap; + void *data; + int mode; + + va_start(ap, flags); + mode = va_arg(ap, int); + va_end(ap); + + if (fs_info.fs.primitives.open == NULL) { + errno = ENOMEDIUM; + return -1; + } + + errno = fs_table_reserve(&data); + if (errno != 0) + return -1; + + return fs_info.fs.primitives.open( + data, + pathname, + flags, + mode + ); +#endif +} diff --git a/src/fs/read.c b/src/fs/read.c new file mode 100644 index 0000000..9346720 --- /dev/null +++ b/src/fs/read.c @@ -0,0 +1,31 @@ +#include + +#include + +ssize_t read(int fd, void *buf, size_t size) +{ + (void)fd; + (void)buf; + (void)size; + return -1; +#if 0 + void *data; + + errno = fs_table_find(&data, fd); + if (errno != 0) + return -1; + + if (fd >= 0 && fd <= 2) { + //TODO:support keyboard + //TODO:support display + errno = ENODEV; + return -1; + } + + if (fs_info.fs.primitives.read == NULL) { + errno = EIO; + return -1; + } + return fs_info.fs.primitives.read(data, buf, size); +#endif +} diff --git a/src/fs/write.c b/src/fs/write.c new file mode 100644 index 0000000..2be62ce --- /dev/null +++ b/src/fs/write.c @@ -0,0 +1,31 @@ +#include + +#include + +ssize_t write(int fd, const void *buf, size_t size) +{ + (void)fd; + (void)buf; + (void)size; + return -1; +#if 0 + void *data; + + errno = fs_table_find(&data, fd); + if (errno != 0) + return -1; + + if (fd >= 0 && fd <= 2) { + //TODO:support keyboard + //TODO:support display + errno = ENODEV; + return -1; + } + + if (fs_info.fs.primitives.write == NULL) { + errno = EIO; + return -1; + } + return fs_info.fs.primitives.write(data, buf, size); +#endif +} diff --git a/src/rtc/rtc.c b/src/rtc/rtc.c new file mode 100644 index 0000000..1ee08f9 --- /dev/null +++ b/src/rtc/rtc.c @@ -0,0 +1,68 @@ +#include +#include +#include +#include + +#include + +/* internal timer information */ +struct { + struct rtc_drv_interface driver; +} rtc_info; + +//--- +// user-level timer API +//--- + +/* rtc_get_time(): Read the current time from the RTC */ +int rtc_get_time(rtc_time_t *time) +{ + if (rtc_info.driver.rtc_get_time != NULL) + return rtc_info.driver.rtc_get_time(time); + return -1; +} + +/* rtc_set_time(): Set current time in the RTC */ +int rtc_set_time(rtc_time_t const *time) +{ + if (rtc_info.driver.rtc_set_time != NULL) + return rtc_info.driver.rtc_set_time(time); + return -1; +} + +//--- +// Kernel module information +//--- + +/* __rtc_init() : initialize the RTC module */ +static void __rtc_init(void) +{ + memset(&rtc_info, 0x00, sizeof(rtc_info)); + + struct vhex_driver *driver = vhex_driver_table(); + for (int i = 0; i < vhex_driver_count(); ++i) { + if (driver[i].flags.RTC) { + memcpy( + &rtc_info.driver, + driver[i].module_data, + sizeof(struct rtc_drv_interface) + ); + break; + } + } +} + +/* __rtc_quit() : uninitialize the RTC module */ +static void __rtc_quit(void) +{ + ; +} + +/* declare the timer module */ + +struct vhex_module mod_rtc = { + .name = "RTC", + .init = &__rtc_init, + .quit = &__rtc_quit, +}; +VHEX_DECLARE_MODULE(06, mod_rtc);