diff --git a/board/fxcg50/board.ini b/board/fxcg50/board.ini index b04f743..005b434 100644 --- a/board/fxcg50/board.ini +++ b/board/fxcg50/board.ini @@ -7,5 +7,5 @@ mpu=sh7305 [toolchain] prefix=sh-elf-vhex- -cflags=-DFXCG50,-m4-nofpu,-mb +cflags=-DFXCG50,-m4-nofpu,-mb,-DWIDTH=396,-DHEIGHT=224 libs=-lgcc diff --git a/board/fxcg50/fxcg50-dynamic.ld b/board/fxcg50/fxcg50-dynamic.ld new file mode 100644 index 0000000..d714a9c --- /dev/null +++ b/board/fxcg50/fxcg50-dynamic.ld @@ -0,0 +1,98 @@ +/* + Linker script for the dynamic version of Vhex (fxcg50) +*/ + +OUTPUT_FORMAT("elf32-sh", "elf32-sh", "elf32-sh") +OUTPUT_ARCH(sh4) +ENTRY(_main) + + +/* +** Linker script for user executables. +*/ +MEMORY +{ + /* virtual memory, read-write segment */ + userram (WX) : o = 0x00000000, l = 1M +} + +SECTIONS +{ /* Code */ + .text : { + *(.text); + *(.text.*); + + _bctors = . ; + *(.ctors .ctors.*) + _ectors = . ; + + _bdtors = . ; + *(.dtors .dtors.*) + _edtors = . ; + + } > userram + + /* Read-only sections */ + .rodata : { + /* Read-Only data */ + *(.rodata); + *(.rodata.*); + } > userram + + + /* The GOT section is a bit exotic. + When I generate the PIE executable, all global variables are stored + is the *(.got) section and the __GLOBAL_OFFSET_TABLE__ object is + generated and inserted in the *(.got.plt) section. + + But, neither of *(.plt*) or *(rela*) section are generated to help + me out for the "relocation" of each address stored in the GOT. The + result is that the content of the GOT is always absolute addresses, + which makes the machine crash. + + So, the idea to bypass this limitation (probably due to the custom + GCC which not provide critical information for the relocation) is to + isolate the GOT in a standalone section and, after the loading of + the image, walk thought the relocalised table and manually patch + each address. + + Moreover, the __GLOBAL_OFFSET_TABLE__ is used like a table, so, the + section ".got.plt" SHOULD be before the .got section. */ + .got.plt : { *(.got.plt) *(.igot.plt) *(.igot) } + .got : { *(.got) } + + /* readable / writable data */ + .data ALIGN(4) : { + *(.data); + *(.data.*); + *(COMMON); + } + + /* bss section included to avoid missaligned segment */ + .bss ALIGN(4) : { + *(.bss); + *(.bss.*); + + /* dynamic BSS information (move me ?) */ + *(.dynbss) + } > userram + + /* unwanted section */ + /DISCARD/ : { + *(.rela.debug*) + *(.gnu.*) + *(.debug_info) + *(.debug_abbrev) + *(.debug_loc) + *(.debug_aranges) + *(.debug_ranges) + *(.debug_line) + *(.debug_str) + *(.debug_*) + *(.jcr) + *(.eh_frame_hdr) + *(.eh_frame) + *(.comment) + *(.interp) + } +} diff --git a/board/fxcg50/hardware.c b/board/fxcg50/hardware.c index 1ef8ea6..95e343a 100644 --- a/board/fxcg50/hardware.c +++ b/board/fxcg50/hardware.c @@ -1,8 +1,8 @@ //--- // vhex:core:hardware - Platform information and hardware detection //--- -#include "vhex/drivers/mpu/sh/sh7305/pfc.h" -#include "vhex/drivers/mmu.h" +#include "vhex/driver/mpu/sh/sh7305/pfc.h" +#include "vhex/driver/mmu.h" #include "board/fxcg50/hardware.h" #include "vhex/hardware.h" diff --git a/board/fxcg50/hypervisor.c b/board/fxcg50/hypervisor.c index eb71f86..d33eb4d 100644 --- a/board/fxcg50/hypervisor.c +++ b/board/fxcg50/hypervisor.c @@ -3,15 +3,11 @@ /* hypervisor_init() : initialize the hypervisor module */ void hypervisor_init(void) { - hyp_world_t casio = hypervisor_world_new( - "casio", - HYP_WORLD_STATUS_FLAG_UNDELETABLE - ); - hyp_world_t vhex = hypervisor_world_new( - "vhex", - HYP_WORLD_STATUS_FLAG_UNDELETABLE - ); + hyp_world_t casio = hypervisor_world_new("casio"); + hyp_world_t vhex = hypervisor_world_new("vhex"); + hypervisor_world_switch(casio, vhex); + } /* hypervisor_quit() : quit the hypervisor module */ diff --git a/config b/config deleted file mode 100755 index d3713ff..0000000 --- a/config +++ /dev/null @@ -1,225 +0,0 @@ -#! /bin/python3 -import sys -import configparser -import os.path -import os -import shutil - - -help_string = f""" -usage: config [options...] - -Configuration script for the Vhex unikernel. You should build out-of-tree by -creating a build directory and configuring from there. - -Options: - -h,--help - display this message - - --verbose - display more information during the compilation step - - --format=FORMAT[,format[,...]] - select the format of the library generation. You can use two format: - <> static - generate a static library - <> dynamic - generate a dynamic library - <> all - same behaviour as "--format=static,dynamic" - By default, only "dynamic" is used. - - --board[=BOARD,board[,...]] - select boards. If no board name is given, a list of all available board - will be printed. - - --prefix=PATH - installation path for all generated libraries -""".strip() - -# -# create and apply the arguments parser -# - -def parse_arguments(): - """ - The objectif of this function is to generate the "arguments object" with - all arguments passed throuth this script correctly isolated. - """ - args = { - 'board' : [], - 'format' : [], - 'verbose': False, - 'prefix': '' - } - arg_name = [ - "-h", - "--help", - "--format", - "--verbose", - "--board", - "--prefix" - ] - for arg in sys.argv[1:]: - info = arg.split("=") - if (info[0] in arg_name) == False: - print("%s: unreconized option '%s'" % (sys.argv[0],info[0])) - print("Try '%s --help' for more information" % sys.argv[0]) - exit(84) - if (info[0] in ["-h", "--help"]) == True: - print(help_string) - exit(0) - if info[0] == "--verbose": - args["verbose"] = True - continue - if info[0] == "--prefix": - args["prefix"] = info[1] - continue - if len(info) > 1: - args[info[0][2:]] = info[1].split(",") - return args - - -# -# part handlers -# - -def board_check(file, board_list): - boards = list(os.walk('../board'))[0][1] - archs = list(os.walk('../src/drivers/mpu'))[0][1] - - if not board_list: - print('board available:') - for board in boards: - path = '../board/%s/board.ini' % board - if not os.path.exists(path): - print('board \'%s\' does not exists' % board) - continue - conf = configparser.ConfigParser() - conf.read(path) - if not ('meta' in conf) or not ('description' in conf['meta']): - print('<> %s\t\tNo description available' % board) - continue - print('<> %s\t\t%s' % (board, conf['meta']['description'])) - exit(0) - - - valid_board_list = [] - for board in board_list: - if not (board in boards): - print("board '%s' does not exist" % board) - continue - path = '../board/%s/board.ini' % board - if not os.path.exists(path): - print("board '%s' does not have INI descriptor file" % board) - continue - conf = configparser.ConfigParser() - conf.read(path) - if not ('drivers' in conf) or not ('mpu' in conf['drivers']): - print("board '%s' does not have MPU information" % board) - continue - arch = '' - mpu = conf['drivers']['mpu'] - for _arch in archs: - if not os.path.exists('../src/drivers/mpu/%s/%s' % (_arch,mpu)): - continue - arch = _arch - break - if not arch: - print("board '%s': unreconized MPU '%s'" % (board,mpu)) - continue - - pathlist = [ - '../board/%s' % board, - '../src/drivers/mpu/%s/%s' % (_arch,mpu) - ] - for driver in conf['drivers']: - if driver == 'mpu': - continue - dpath = '../src/drivers/%s' % driver - if not os.path.exists(dpath): - print("board '%s': unreconized driver \'%s\'" % (board, dpath)) - continue - for t in conf['drivers'][driver].split(','): - tpath = dpath + '/' + t - if not os.path.exists(tpath): - print("board '%s': unreconized driver \'%s\'" % (board, t)) - continue - pathlist.append(tpath) - tpath = tpath + '/target/' + arch - if os.path.exists(tpath): - pathlist.append(tpath) - for dirent in os.listdir('../src'): - if not (dirent in ['drivers', 'arch']): - pathlist.append('../src/' + dirent) - - ldflags,cflags,prefix,libs = [],[],[],[] - if 'toolchain' in conf: - if 'prefix' in conf['toolchain']: - prefix = conf['toolchain']['prefix'] - if 'cflags' in conf['toolchain']: - cflags = conf['toolchain']['cflags'].split(',') - if 'libs' in conf['toolchain']: - libs = conf['toolchain']['libs'].split(',') - - confstr = 'CONFIG.' + board; - file.write( - confstr + '.SRC-MODULE-PATH :=' + ' '.join(pathlist) + '\n' - + confstr + '.TOOLCHAIN.LDFLAGS :=' + ' '.join(ldflags) + '\n' - + confstr + '.TOOLCHAIN.CFLAGS :=' + ' '.join(cflags) + '\n' - + confstr + '.TOOLCHAIN.PREFIX :=' + prefix + '\n' - + confstr + '.LIBS :=' + ' '.join(libs) + '\n' - ) - - if not os.path.exists(board): - os.mkdir(board) - os.symlink( - '../../board/%s/%s.ld' % (board,board), - '%s/%s.ld' % (board,board) - ) - - valid_board_list.append(board) - - file.write('CONFIG.BOARD-LIST := ' + ' '.join(valid_board_list) + '\n') - -def format_check(file, format_list): - file.write('CONFIG.FORMAT-LIST :=') - for _format in format_list: - if not (_format in ["static", "dynamic", "all"]): - print("%s: unreconized format '%s'" % (sys.argv[0], _format)) - exit(84) - if _format == 'all': - file.write(' dynamic static\n') - return - file.write(' ' + _format) - if not format_list: - file.write(' dynamic') - file.write('\n') - -def prefix_check(file, prefix): - file.write('CONFIG.INSTALL-PREFIX :=' + prefix + '\n') - -def verbose_check(file, verbose): - file.write(f"CONFIG.VERBOSE := {'true' if verbose else 'false'}\n") - -# -# "real" entry of the script -# - -def main(): - args = parse_arguments() - - if os.path.exists('../src') == False: - print('error: you should configure from a build directory, like this:') - print(' mkdir build && cd build && ../configure [options..]') - exit(84) - - file = open('kernel.cfg', 'w') - - board_check(file, args['board']) - format_check(file, args['format']) - prefix_check(file, args['prefix']) - verbose_check(file, args['verbose']) - - if os.path.exists('Makefile'): - os.remove('Makefile') - os.symlink('../make/Makefile', 'Makefile') - -main() diff --git a/include/vhex/display.h b/include/vhex/display.h index 59aefbd..9f03900 100644 --- a/include/vhex/display.h +++ b/include/vhex/display.h @@ -1,24 +1,38 @@ #ifndef __VHEX_DISPLAY__ # define __VHEX_DISPLAY__ -//TODO: plate-form specific -enum { - /* Compatibility with fx9860g color names */ - C_WHITE = 0xffff, - C_LIGHT = 0xad55, - C_DARK = 0x528a, - C_BLACK = 0x0000, +#include +#include +#include +#include +//#include +//#include - /* Other colors */ - C_RED = 0xf800, - C_GREEN = 0x07e0, - C_BLUE = 0x001f, +//TODO: doc - C_NONE = -1, - C_INVERT = -2, -}; +/* dclear(): Fill the screen with a single color */ +extern did_t dclear(int color); + +/* dupdate(): Generate the display frame on the screen */ +extern void dupdate(void); + +/* dwidth(): get the screen width */ +extern size_t dwidth(void); + +/* dheight(): get the heigth of the screen */ +extern size_t dheight(void); + + + + + + +//--- +// Text render API +//--- +#if 0 /* Alignment settings for dtext_opt() and dprint_opt(). Combining a vertical and a horizontal alignment option specifies where a given point (x,y) should be relative to the rendered string. */ @@ -42,14 +56,13 @@ extern void dtext_opt( char const *str, int size ); + + + /* dpixel(): Change a pixel's color */ extern void dpixel(int x, int y, int color); -/* dupdate(): Push the video RAM to the display driver */ -extern void dupdate(void); -/* dclear(): Fill the screen with a single color */ -extern void dclear(int color); /* dascii() : display one ASCII character */ extern void dascii(int x, int y, int fg, int bg, int n); @@ -78,4 +91,6 @@ extern void dhline(int x1, int x2, int y, int color); /* dvline(): Draw vertical line */ extern void dvline(int y1, int y2, int x, int color); +#endif /* IF 0 */ + #endif /*__VHEX_DISPLAY__*/ diff --git a/include/vhex/display/color.h b/include/vhex/display/color.h new file mode 100644 index 0000000..9fcc2fc --- /dev/null +++ b/include/vhex/display/color.h @@ -0,0 +1,20 @@ +#ifndef __VHEX_DISPLAY_COLOR__ +# define __VHEX_DISPLAY_COLOR__ + + +//FIXME: this is plateform-specific :/ +enum { + C_WHITE = 0xffff, + C_LIGHT = 0xad55, + C_DARK = 0x528a, + C_BLACK = 0x0000, + + C_RED = 0xf800, + C_GREEN = 0x07e0, + C_BLUE = 0x001f, + + C_NONE = -1, + C_INVERT = -2, +}; + +#endif /* __VHEX_DISPLAY_COLOR__ */ diff --git a/include/vhex/display/draw.h b/include/vhex/display/draw.h new file mode 100644 index 0000000..df1520d --- /dev/null +++ b/include/vhex/display/draw.h @@ -0,0 +1 @@ +#include diff --git a/include/vhex/display/draw/circle.h b/include/vhex/display/draw/circle.h new file mode 100644 index 0000000..2b8e62b --- /dev/null +++ b/include/vhex/display/draw/circle.h @@ -0,0 +1,29 @@ +#ifndef __VHEX_DISPLAY_DRAW_CIRCLE__ +# define __VHEX_DISPLAY_DRAW_CIRCLE__ + +#include +#include + +/* dcircle_filled() : draw a filled circle + + This function will add a filled circle drawing in the internal "draw queue" + handled by vhex display core. The "draw ID" will be returned and shader can + be added to the circle afterward. + + Args: + ( in) x : X position (horizontal middle of the circle) + ( in) y : Y position (vertical middle of the circle) + ( in) size : diameter of the circle + ( in) color : filled color for the circle + + Return: + > the "draw ID", which can be used to apply shader afterward */ +extern did_t dcircle(int x, int y, size_t size, int mode, dshader_t *list); + +//TODO: shader +//TODO: doc +//TODO: mode + + + +#endif /* __VHEX_DISPLAY_DRAW_CIRCLE__ */ diff --git a/include/vhex/display/shader.h b/include/vhex/display/shader.h new file mode 100644 index 0000000..72a1229 --- /dev/null +++ b/include/vhex/display/shader.h @@ -0,0 +1,90 @@ +#ifndef __VHEX_DISPLAY_SHADER__ +# define __VHEX_DISPLAY_SHADER__ + +#include +#include + +/* dshader_call_arg_t: All types of arguments allowed in an indirect shader call + + Because a function call cannot be easily pieced together, there are + restrictions on what arguments can be passed. The following union lists all + of the available types. Other types can be used if casted, mainly pointers; + see the description of DSHADER*() for details. */ +typedef union dshader_call_arg { + int8_t i8; + uint8_t u8; + + int16_t i16; + uint16_t u16; + + /* 32-bit integers */ + int i; + unsigned int u; + int32_t i32; + uint32_t u32; + /* 32-bit floating-point */ + float f; + + /* Pointers to most common types, in all possible const/volatile + qualifications */ + #define POINTER(type, name) \ + type *name; \ + type const *name ## _c; \ + type volatile *name ## _v; \ + type volatile const *name ## _cv; + + POINTER(void, pv) + POINTER(char, pc) + POINTER(unsigned char, puc) + POINTER(short, ps) + POINTER(unsigned short, pus) + POINTER(int, pi) + POINTER(unsigned int, pui) + POINTER(int8_t, pi8) + POINTER(uint8_t, pu8) + POINTER(int16_t, pi16) + POINTER(uint16_t, pu16) + POINTER(int32_t, pi32) + POINTER(uint32_t, pu32) + POINTER(int64_t, pi64) + POINTER(uint64_t, pu64) + POINTER(long long int, pll) + POINTER(unsigned long long int, pull) + POINTER(float, pf) + POINTER(double, pd) + + #undef POINTER +} dshader_call_arg_t; + +/* dshader_surface - Describe the surface */ +struct dshader_surface { + void *draw; + void *frag; + size_t width; + size_t height; + unsigned int x; + unsigned int y; +}; + +/* dshader - display shader definition */ +struct dshader_call { + int (*routine)( + struct dshader_surface *surface, + dshader_call_arg_t *draw_args, + dshader_call_arg_t *shader_args + ); + dshader_call_arg_t args[8]; +}; +typedef struct dshader_call dshader_call_t; +typedef struct dshader_call dshader_t; + +/* DSHADER_LIST - helper to create a list of shader "on-the-fly" */ +#define DSHADER_LIST(shader_list) (dshader_call_t*)&{ shader_list } + +/* DSHADER - helper to create a shader object */ +#define DSHADER(fct, ...) (dshader_call_t){ \ + .routine = fct, \ + .args = { __VA_ARGS__ } \ +} + +#endif /* __VHEX_DISPLAY_SHADER__ */ diff --git a/include/vhex/display/stack.h b/include/vhex/display/stack.h new file mode 100644 index 0000000..1cebb1d --- /dev/null +++ b/include/vhex/display/stack.h @@ -0,0 +1,87 @@ +#ifndef __VHEX_DISPLAY_STACK__ +# define __VHEX_DISPLAY_STACK__ + +#include +#include + +/* dstack_call - dstack indirect call (same as dshader) */ +struct dstack_call { + int (*routine)( + struct dshader_surface *surface, + dshader_call_arg_t *draw_args + ); + dshader_call_arg_t args[12]; +}; +typedef struct dstack_call dstack_call_t; + +/* dstack_action - dstack drawing action information */ +struct dstack_action { + struct dstack_call call; + struct { + dshader_call_t *table; + int number; + int idx; + } shader; +}; + +/* DSTACK_CALL - display indirect call */ +#pragma GCC diagnostic ignored "-Wmissing-braces" + +#define DSTACK_CALL(fct, ...) (dstack_call_t){ \ + .routine = (void*)fct, \ + .args = { __VA_ARGS__ } \ +} + + +/* dstack_config - dstack configuration structure */ +struct dstack_config { + int default_icall_pool_slot; + int default_icall_args_nb; + int default_shader_per_action; +}; + +#ifndef DSTACK_DEFAULT_ICALL_SLOT +# define DSTACK_DEFAULT_ICALL_SLOT 32 +#endif + +#ifndef DSTACK_DEFAULT_ICALL_ARGS +# define DSTACK_DEFAULT_ICALL_ARGS 12 +#endif + +#ifndef DSTACK_DEFAULT_SHADER_PER_ACTION +# define DSTACK_DEFAULT_SHADER_PER_ACTION 4 +#endif + +/* dstack_drv_interface - driver interface */ +struct dstack_drv_interface { + int (*frame_start)(struct dshader_surface *); + int (*frame_frag_next)(struct dshader_surface *); + int (*frame_frag_send)(struct dshader_surface *); + int (*frame_end)(struct dshader_surface *); +}; + +//--- +// Display stack API +//--- + +/* dstack_init() : Initialise the draw stack (should not be involved) */ +extern int dstack_init(struct dstack_config *config); + +/* dstack_add_action() : add a new action in the draw stack */ +extern did_t dstack_add_action(dstack_call_t *call, dshader_call_t *shaders); + +/* dstack_get_action() : get display stack action using its ID */ +extern struct dstack_action *dstack_get_action(did_t did); + +/* dstack_render(): render a frame */ +extern void dstack_render(void); + +/* dstack_invalidate() : Invalidate the draw stack (reset) */ +extern int dstack_invalidate(void); + +/* dstack_quit() : Uninit the draw stack */ +extern int dstack_quit(void); + + + +#endif /* __VHEX_DISPLAY_STACK__ */ diff --git a/include/vhex/display/types.h b/include/vhex/display/types.h new file mode 100644 index 0000000..ef15607 --- /dev/null +++ b/include/vhex/display/types.h @@ -0,0 +1,7 @@ +#ifndef __VHEX_DISPLAY_TYPES__ +# define __VHEX_DISPLAY_TYPES__ + +/* draw ID */ +typedef int did_t; + +#endif /* __VHEX_DISPLAY_TYPES__ */ diff --git a/include/vhex/driver.h b/include/vhex/driver.h index 0d0c983..a6a318a 100644 --- a/include/vhex/driver.h +++ b/include/vhex/driver.h @@ -1,6 +1,7 @@ #ifndef __VHEX_DRIVER__ # define __VHEX_DRIVER__ +#include #include /* Device drivers */ @@ -31,7 +32,8 @@ struct vhex_driver // Standard calls /* Initialize the hardware for the driver to work in vhex. Usually - installs interrupt handlers and configures registers. May be NULL. */ + installs interrupt handlers and configures registers. Cannot be + NULL */ void (*configure)(void *state); // Internal information @@ -40,18 +42,20 @@ struct vhex_driver uint16_t state_size; /* default flags for the driver */ - int default_flag; -}; + byte_union(flags, + uint8_t :1; + uint8_t :1; + uint8_t :1; + uint8_t DISPLAY :1; -enum { - /* Driver is used by default (will be configured) */ - VHEX_DRV_USED = 0x00, + uint8_t :1; + uint8_t :1; + uint8_t SHARED :1; + uint8_t UNUSED :1; + ); - /* Driver is not used by the world */ - VHEX_DRV_UNUSED = 0x01, - - /* Driver does not require hardware state saves during world switches */ - VHEX_DRV_SHARED = 0x02, + /* module related-internal data */ + void *module_data; }; diff --git a/include/vhex/drivers/cpu.h b/include/vhex/driver/cpu.h similarity index 100% rename from include/vhex/drivers/cpu.h rename to include/vhex/driver/cpu.h diff --git a/include/vhex/drivers/mmu.h b/include/vhex/driver/mmu.h similarity index 100% rename from include/vhex/drivers/mmu.h rename to include/vhex/driver/mmu.h diff --git a/include/vhex/drivers/mpu/sh/sh7305/cpu.h b/include/vhex/driver/mpu/sh/sh7305/cpu.h similarity index 100% rename from include/vhex/drivers/mpu/sh/sh7305/cpu.h rename to include/vhex/driver/mpu/sh/sh7305/cpu.h diff --git a/include/vhex/drivers/mpu/sh/sh7305/intc.h b/include/vhex/driver/mpu/sh/sh7305/intc.h similarity index 100% rename from include/vhex/drivers/mpu/sh/sh7305/intc.h rename to include/vhex/driver/mpu/sh/sh7305/intc.h diff --git a/include/vhex/drivers/mpu/sh/sh7305/keysc.h b/include/vhex/driver/mpu/sh/sh7305/keysc.h similarity index 100% rename from include/vhex/drivers/mpu/sh/sh7305/keysc.h rename to include/vhex/driver/mpu/sh/sh7305/keysc.h diff --git a/include/vhex/drivers/mpu/sh/sh7305/mmu.h b/include/vhex/driver/mpu/sh/sh7305/mmu.h similarity index 100% rename from include/vhex/drivers/mpu/sh/sh7305/mmu.h rename to include/vhex/driver/mpu/sh/sh7305/mmu.h diff --git a/include/vhex/drivers/mpu/sh/sh7305/pfc.h b/include/vhex/driver/mpu/sh/sh7305/pfc.h similarity index 100% rename from include/vhex/drivers/mpu/sh/sh7305/pfc.h rename to include/vhex/driver/mpu/sh/sh7305/pfc.h diff --git a/include/vhex/driver/screen/r61524.h b/include/vhex/driver/screen/r61524.h new file mode 100644 index 0000000..440ea96 --- /dev/null +++ b/include/vhex/driver/screen/r61524.h @@ -0,0 +1,52 @@ +#ifndef __VHEX_DRIVER_SCREEN_R61524__ +# define __VHEX_DRIVER_SCREEN_R61524__ + +#include +#include + +/* Registers and operations */ +enum { + device_code_read = 0x000, + driver_output_control = 0x001, + entry_mode = 0x003, + display_control_2 = 0x008, + low_power_control = 0x00b, + + ram_address_horizontal = 0x200, + ram_address_vertical = 0x201, + write_data = 0x202, + + horizontal_ram_start = 0x210, + horizontal_ram_end = 0x211, + vertical_ram_start = 0x212, + vertical_ram_end = 0x213, +}; + + +VINLINE static void r61524_select(uint16_t reg) +{ + /* Clear RS and write the register number */ + *(volatile uint8_t *)0xa405013c &= ~0x10; + __asm__ volatile ("synco"::); + *(volatile uint16_t *)0xb4000000 = reg; + __asm__ volatile ("synco"::); + + /* Set RS back. We don't do this in read()/write() because the display + driver is optimized for consecutive GRAM access. LCD-transfers will + be faster when executing select() followed by several calls to + write(). (Although most applications should use the DMA instead.) */ + *(volatile uint8_t *)0xa405013c |= 0x10; + __asm__ volatile ("synco"::); +} + +VINLINE static uint16_t r61524_read(void) +{ + return *(volatile uint16_t *)0xb4000000; +} + +VINLINE static void r61524_write(uint16_t data) +{ + *(volatile uint16_t *)0xb4000000 = data; +} + +#endif /* __VHEX_DRIVER_SCREEN_R61524__ */ diff --git a/include/vhex/hypervisor.h b/include/vhex/hypervisor.h index f35bdcc..8c9b62a 100644 --- a/include/vhex/hypervisor.h +++ b/include/vhex/hypervisor.h @@ -1,10 +1,7 @@ #ifndef __VHEX_HYPERVISOR__ # define __VHEX_HYPERVISOR__ -#include -#include - -/* declare driver structure */ +#include #include /* real Vhex world with driver bitmap and meta information for the hypervisor */ @@ -12,49 +9,32 @@ struct vhex_world { /* world driver information */ struct { struct vhex_driver *context; - int flags; + byte_union(flags, + uint8_t :1; + uint8_t :1; + uint8_t :1; + uint8_t :1; + + uint8_t :1; + uint8_t SHARED :1; + uint8_t INIT :1; + uint8_t UNUSED :1; + ); } *driver; /* internal information used by the hypervisor */ char const * name; - uint8_t status; -}; + byte_union(status, + uint8_t LOCKED :1; + uint8_t ACTIVE :1; + uint8_t :1; + uint8_t :1; -/* define world status states */ -#define HYP_WORLD_STATUS_STATE_UNUSED (1 << 0) -#define HYP_WORLD_STATUS_STATE_UNINIT (1 << 1) -#define HYP_WORLD_STATUS_STATE_USED (1 << 2) - -/* define world status flags */ -#define HYP_WORLD_STATUS_FLAG_UNDELETABLE (1 << 0) - -/* hypervisor world status helper */ - -#define HYP_WORLD_STATUS_SET(flags,state) \ - (((flags & 0x0f) << 4) | ((state & 0x0f) << 0)) - -#define HYP_WORLD_STATUS_SET_STATE(status, state) \ - do { \ - status &= 0x0f; \ - status |= (state & 0x0f) << 0; \ - } while (0); - -#define HYP_WORLD_STATUS_SET_FLAGS(status, flags) \ - do { \ - status &= 0xf0; \ - status |= (state & 0x0f) << 4; \ - } while (0); - -/* hypervisor world status getter */ - -#define HYP_WORLD_STATUS_FLAGS(status) ((status & 0xf0) >> 4) -#define HYP_WORLD_STATUS_STATE(status) ((status & 0x0f) >> 0) - - -/* hypervisor driver status */ -enum { - HYP_WORLD_DRV_UNUSED = VHEX_DRV_UNUSED, - HYP_WORLD_DRV_USED = VHEX_DRV_USED, + uint8_t :1; + uint8_t :1; + uint8_t INIT :1; + uint8_t USED :1; + ); }; /* hyp_word_t : hypervisor world ID */ @@ -74,13 +54,10 @@ enum { }; /* hypervisor_world_new() : create a new world with its name */ -extern hyp_world_t hypervisor_world_new( - char const * const restrict name, - int flags -); +extern hyp_world_t hypervisor_world_new(char const * const name); /* hypervisor_world_find() : find a world ID using its name */ -extern hyp_world_t hypervisor_world_find(char const * const restrict name); +extern hyp_world_t hypervisor_world_find(char const * const name); /* hypervisor_world_get() : get a word using its ID */ extern struct vhex_world *hypervisor_world_get(hyp_world_t id); diff --git a/make/Makefile b/make/Makefile index 68de480..025dbc5 100644 --- a/make/Makefile +++ b/make/Makefile @@ -146,7 +146,7 @@ define generate-target-lib # Because we generate rule "on-the-fly" we need to create unique variable # definition because make is not a "scoped" language. (therefore, when a # variable is created, it will never be destroyed until the end of the script) -t-$1-$2-build := $(VXSDK_BUILD_PREFIX)/$1/$2 +t-$1-$2-build := $(VXSDK_PREFIX_BUILD)/$1/$2 # generate compilation flags @@ -163,20 +163,6 @@ t-$1-$2-gcc-header := $$(t-$1-$2-gcc-base)/include t-$1-$2-cflags += -I../include -I.. -I$$(t-$1-$2-gcc-header) t-$1-$2-cflags += -L../lib -L.. -L$$(t-$1-$2-gcc-base) - -# generate format-specific flags - -t-$1-$2-exec := -ifeq ($2,static) - t-$1-$2-exec := $1/libvhex-$1.a -endif -ifeq ($2,dynamic) - t-$1-$2-ldflags += -shared -T $1/$1.ld - t-$1-$2-ldflags += -soname=libvhex-$1-$(VXSDK_PKG_VERSION).so - t-$1-$2-ldflags += -Map=$$(t-$1-$2-build)/map - t-$1-$2-exec := $1/libvhex-$1.so -endif - # generate file's sources list, based on the configuration step t-$1-$2-dir := $$(foreach module,$$(CONFIG.$1.SRC-MODULE-PATH),\ @@ -186,6 +172,20 @@ t-$1-$2-src := $$(foreach path,$$(t-$1-$2-dir),\ $$(wildcard $$(path)/*.S) \ $$(wildcard $$(path)/*.s)) +# generate format-specific flags + +t-$1-$2-exec := +ifeq ($2,static) +t-$1-$2-exec := $1/libvhex-$1.a +endif +ifeq ($2,dynamic) +t-$1-$2-ldflags += -shared +t-$1-$2-ldflags += -soname=libvhex-$1-$(VXSDK_PKG_VERSION).so +t-$1-$2-ldflags += -Map=$$(t-$1-$2-build)/map +t-$1-$2-exec := $1/libvhex-$1.so +t-$1-$2-src := $(wildcard ../fake/*.c) +endif + # generate file's compilation rules and all object filename into an object # list variable, this will be used by the `main` rule @@ -208,7 +208,7 @@ $$(t-$1-$2-exec): $$(t-$1-$2-obj) @ mkdir -p $$(dir $$@) @ printf "$(blue)Create the library $(red)$$@$(nocolor)\n" ifeq ($2,dynamic) - $$(t-$1-$2-gcc) -shared $$(t-$1-$2-gcc-libs) -o $$@ $$^ + $$(t-$1-$2-gcc) -shared $$(t-$1-$2-cflags) $$(t-$1-$2-gcc-libs) -o $$@ $$^ else $$(t-$1-$2-ar) crs $$@ $$^ endif @@ -252,12 +252,12 @@ define generate-install-rule # Generate the installation rule $(basename $(notdir $1))-install: - install -d $(VXSDK_LIB_PREFIX) - install $1 -m 644 $(VXSDK_LIB_PREFIX) + install -d $(VXSDK_PREFIX_LIB) + install $1 -m 644 $(VXSDK_PREFIX_LIB) # Generate the uninstallation rule $(basename $(notdir $1))-uninstall: - rm -f $(VXSDK_LIB_PREFIX)/$(notdir $1) + rm -f $(VXSDK_PREFIX_LIB)/$(notdir $1) # Register generated rules into their appropriate list $2 += $(basename $(notdir $1))-install @@ -272,11 +272,12 @@ endef define generate-board-install-rule $1-install: - install -d $(VXSDK_LIB_PREFIX) - install ../board/$(strip $1)/$(strip $1).ld -m 644 $(VXSDK_LIB_PREFIX) + install -d $(VXSDK_PREFIX_LIB) + install ../board/$(strip $1)/*.ld -m 644 $(VXSDK_PREFIX_LIB) $1-uninstall: - rm -f $(VXSDK_LIB_PREFIX)/$(strip $1).ld + rm -f $(VXSDK_PREFIX_LIB)/$(strip $1).ld + rm -f $(VXSDK_PREFIX_LIB)/$(strip $1)-dynamic.ld $2 += $1-install $3 += $1-uninstall @@ -303,7 +304,7 @@ $(foreach board,$(CONFIG.BOARD-LIST),$(eval \ )) # Generate the path where include directory will be installed. -target-install-hdr-dir := $(VXSDK_LIB_PREFIX)/include/ +target-install-hdr-dir := $(VXSDK_PREFIX_LIB)/include/ ifeq ($(wildcard $(target-install-header-dir)vhex/.*),) target-install-hdr-dir := $(target-install-hdr-dir)vhex endif @@ -314,10 +315,11 @@ endif # Installation rules #--- install: $(target-install-rules) + mkdir -p $(dir $(target-install-hdr-dir)) cp -r ../include/vhex $(target-install-hdr-dir) unsintall: $(target-uninstall_rules) - rm -rf $(VXSDK_LIB_PREFIX)/include/vhex + rm -rf $(VXSDK_PREFIX_LIB)/include/vhex .PHONY: install uninstall diff --git a/src/drivers/mpu/sh/sh7305/cpu/atomic.c b/src/drivers/mpu/sh/sh7305/cpu/atomic.c index 4945053..55202f6 100644 --- a/src/drivers/mpu/sh/sh7305/cpu/atomic.c +++ b/src/drivers/mpu/sh/sh7305/cpu/atomic.c @@ -1,5 +1,5 @@ -#include -#include +#include +#include /* Value of IMASK when atomic mode is entered */ static int saved_IMASK = 0; diff --git a/src/drivers/mpu/sh/sh7305/cpu/cpu.c b/src/drivers/mpu/sh/sh7305/cpu/cpu.c index 9574130..56053ed 100644 --- a/src/drivers/mpu/sh/sh7305/cpu/cpu.c +++ b/src/drivers/mpu/sh/sh7305/cpu/cpu.c @@ -1,5 +1,5 @@ -#include "vhex/driver.h" -#include "vhex/drivers/mpu/sh/sh7305/cpu.h" +#include +#include #include @@ -32,12 +32,12 @@ static void __cpu_configure(struct cpu_ctx *state) /* configure the Status Register <> force the privileged mode <> enable DSP - <> allow interruptions */ + <> mask interruptions (it will be unmasked in )*/ state->sr.MD = 1; state->sr.RB = 0; state->sr.BL = 0; state->sr.DSP = 1; - state->sr.IMASK = 0b0000; + state->sr.IMASK = 0b1111; } /* hardware hypervisor call */ @@ -67,4 +67,4 @@ struct vhex_driver drv_cpu = { .configure = (void*)&__cpu_configure, .state_size = sizeof(struct cpu_ctx) }; -VHEX_DECLARE_DRIVER(16, drv_cpu); +VHEX_DECLARE_DRIVER(02, drv_cpu); diff --git a/src/drivers/mpu/sh/sh7305/intc/install.c b/src/drivers/mpu/sh/sh7305/intc/install.c index d42fcd7..0bd5b6e 100644 --- a/src/drivers/mpu/sh/sh7305/intc/install.c +++ b/src/drivers/mpu/sh/sh7305/intc/install.c @@ -1,4 +1,4 @@ -#include +#include #include #include diff --git a/src/drivers/mpu/sh/sh7305/intc/intc.c b/src/drivers/mpu/sh/sh7305/intc/intc.c index 4bdf86e..3ec28ac 100644 --- a/src/drivers/mpu/sh/sh7305/intc/intc.c +++ b/src/drivers/mpu/sh/sh7305/intc/intc.c @@ -1,5 +1,5 @@ -#include "vhex/driver.h" -#include "vhex/drivers/mpu/sh/sh7305/intc.h" +#include +#include #include diff --git a/src/drivers/mpu/sh/sh7305/keysc/handler.c b/src/drivers/mpu/sh/sh7305/keysc/handler.c index 5f99c5b..ed1964b 100644 --- a/src/drivers/mpu/sh/sh7305/keysc/handler.c +++ b/src/drivers/mpu/sh/sh7305/keysc/handler.c @@ -1,6 +1,6 @@ #include -#include -#include +#include +#include /* Internal indicator used by high-level function to notice when the key list is updated */ diff --git a/src/drivers/mpu/sh/sh7305/keysc/keysc.c b/src/drivers/mpu/sh/sh7305/keysc/keysc.c index 07c23e6..a9e780d 100644 --- a/src/drivers/mpu/sh/sh7305/keysc/keysc.c +++ b/src/drivers/mpu/sh/sh7305/keysc/keysc.c @@ -1,6 +1,6 @@ -#include "vhex/drivers/mpu/sh/sh7305/keysc.h" -#include "vhex/drivers/mpu/sh/sh7305/intc.h" -#include "vhex/driver.h" +#include +#include +#include /* define the private KeyScan context structure */ struct keysc_ctx { diff --git a/src/drivers/mpu/sh/sh7305/mmu/utlb.c b/src/drivers/mpu/sh/sh7305/mmu/utlb.c index b5c92be..638e628 100644 --- a/src/drivers/mpu/sh/sh7305/mmu/utlb.c +++ b/src/drivers/mpu/sh/sh7305/mmu/utlb.c @@ -1,8 +1,8 @@ //--- // vhex:mmu:mmu - MMU driver definition and context management //--- -#include -#include +#include +#include #include /* utlb_addr() - get the P4 address of a UTLB address entry */ diff --git a/src/drivers/screen/R61524/r61524.c b/src/drivers/screen/R61524/r61524.c index dbd7107..6cc3a00 100644 --- a/src/drivers/screen/R61524/r61524.c +++ b/src/drivers/screen/R61524/r61524.c @@ -1,15 +1,167 @@ -#if 0 +#include +#include +#include +#include + +//--- +// R61524 driver API +//--- + +/* r61524_clear_surface() - optimal way to clear the draw and render surface */ +VINLINE void r61524_clear_surface(struct dshader_surface *surface) +{ + //TODO: check cache behaviour: + // > full xram then yram + // > xram and yram + // > yram and xram + // > restrict / non-restrict + uint32_t * restrict xram = surface->draw; + uint32_t * restrict yram = surface->frag; + for (int i = 0; i < 2048; ++i) { + xram[i] = 0x00010001; + yram[i] = 0x00000000; + } +} + +/* r61524_frame_start() - prepar the screen and reset surfaces */ +int r61524_frame_start(struct dshader_surface *surface) +{ + /* Set the windows size */ + r61524_select(horizontal_ram_start); + r61524_write(0); + r61524_select(horizontal_ram_end); + r61524_write(395); + r61524_select(vertical_ram_start); + r61524_write(0); + r61524_select(vertical_ram_end); + r61524_write(223); + + /* Set the RAM position */ + r61524_select(ram_address_horizontal); + r61524_write(0); + r61524_select(ram_address_vertical); + r61524_write(0); + + /* Bind address 0xb4000000 to the data write command */ + r61524_select(write_data); + + /* initialize surface information */ + surface->draw = (void*)0xe5007000; + surface->frag = (void*)0xe5017000; + surface->width = 396; + surface->height = 10; + surface->x = 0; + surface->y = 0; + + /* reset the two surfaces */ + r61524_clear_surface(surface); + return (0); +} + +int r61524_frame_frag_next(struct dshader_surface *surface) +{ + surface->y += 10; + if (surface->y >= 224) { + surface->y -= 10; + return (-1); + } + r61524_clear_surface(surface); + return (0); +} + +int r61524_frame_frag_send(struct dshader_surface *surface) +{ + //TODO: assembly + //TODO: check cache behaviour: + // > full xram then yram + // > xram and yram + // > yram and xram + // > restrict / non-restrict + uint16_t pixel; + uint16_t * restrict xram = surface->draw; + uint16_t * restrict yram = surface->frag; + for (int i = 0; i < 4096; ++i) { + pixel = xram[i]; + if (pixel & 0x0001) { + r61524_write(yram[i]); + continue; + } + r61524_write((pixel & 0xffc0) | ((pixel & 0x003e) >> 1)); + } + return (0); +} + +int r61524_frame_end(struct dshader_surface *surface) +{ + (void)surface; + return (0); +} + +//--- +// Driver definition +//--- + +/* R61524 display (graphics RAM range) */ +struct r61524_ctx { + uint16_t HSA; + uint16_t HEA; + uint16_t VSA; + uint16_t VEA; +}; + +static void __r61524_configure(struct r61524_ctx *s) +{ + s->HSA = 0; + s->HEA = 395; + s->VSA = 0; + s->VEA = 223; +} + +static void __r61524_hsave(struct r61524_ctx *s) +{ + r61524_select(horizontal_ram_start); + s->HSA = r61524_read(); + r61524_select(horizontal_ram_end); + s->HEA = r61524_read(); + + r61524_select(vertical_ram_start); + s->VSA = r61524_read(); + r61524_select(vertical_ram_end); + s->VEA = r61524_read(); +} + +static void __r61524_hrestore(struct r61524_ctx const *s) +{ + r61524_select(horizontal_ram_start); + r61524_write(s->HSA); + r61524_select(horizontal_ram_end); + r61524_write(s->HEA); + + r61524_select(vertical_ram_start); + r61524_write(s->VSA); + r61524_select(vertical_ram_end); + r61524_write(s->VEA); +} - -/* declare the CPU driver */ +static struct dstack_drv_interface drv_r61524_dstack = { + .frame_start = &r61524_frame_start, + .frame_frag_next = &r61524_frame_frag_next, + .frame_frag_send = &r61524_frame_frag_send, + .frame_end = &r61524_frame_end +}; struct vhex_driver drv_r61524 = { .name = "R61524", .hsave = (void*)&__r61524_hsave, .hrestore = (void*)&__r61524_hrestore, .configure = (void*)&__r61524_configure, - .state_size = sizeof(struct r61524_ctx) + .state_size = sizeof(struct r61524_ctx), + .flags = { + .DISPLAY = 1, + .SHARED = 0, + .UNUSED = 0, + }, + .module_data = &drv_r61524_dstack }; VHEX_DECLARE_DRIVER(16, drv_r61524); -#endif diff --git a/src/kernel/exch.c b/src/kernel/exch.c index d8e6cfe..61c6442 100644 --- a/src/kernel/exch.c +++ b/src/kernel/exch.c @@ -4,6 +4,7 @@ //TODO: add relocation information void vhex_kernel_exch_panic(void) { +#if 0 extern uint16_t vhex_vram[]; uint32_t PC; uint32_t TEA; @@ -50,6 +51,7 @@ void vhex_kernel_exch_panic(void) dtext(6, 108, C_BLACK, "Please press the RESET button to restart the"); dtext(6, 121, C_BLACK, "calculator."); dupdate(); +#endif while (1) { __asm__ volatile ("sleep"); } } diff --git a/src/modules/display/dclear.c b/src/modules/display/dclear.c index 043884f..5cf68fb 100644 --- a/src/modules/display/dclear.c +++ b/src/modules/display/dclear.c @@ -1,13 +1,24 @@ -#include -#include #include +#include +#include -/* expose Video RAM */ -extern uint16_t vhex_vram[]; +/* dclear_draw() : real drawing algorithm */ +static void dclear_draw( + struct dshader_surface *surface, + dshader_call_arg_t *arg +) +{ + uint32_t * restrict vram; + uint32_t color; + + vram = surface->frag; + color = arg[0].u16 & 0xffff; + for (int i = 0; i < 2048; ++i) + vram[i] = (color << 16) | (color << 0); +} /* dclear(): Fill the screen with a single color */ -VWEAK void dclear(int color) +did_t dclear(int color) { - for (int i = 0; i < 396 * 224 ; ++i) - vhex_vram[i] = color; + return dstack_add_action(&DSTACK_CALL(&dclear_draw, color), NULL); } diff --git a/src/modules/display/display.c b/src/modules/display/display.c index 90816df..fc94a84 100644 --- a/src/modules/display/display.c +++ b/src/modules/display/display.c @@ -1,4 +1,4 @@ -#include "vhex/display.h" +#include "vhex/display/stack.h" #include "vhex/module.h" /* module init */ @@ -6,13 +6,18 @@ /* __display_init() : initialize the display */ static void __display_init(void) { - /* Nothing to do here ? */ + struct dstack_config conf = { + .default_icall_pool_slot = DSTACK_DEFAULT_ICALL_SLOT, + .default_icall_args_nb = DSTACK_DEFAULT_ICALL_ARGS, + .default_shader_per_action = DSTACK_DEFAULT_SHADER_PER_ACTION + }; + dstack_init(&conf); } /* __display_quit() : uninit the display */ static void __display_quit(void) { - /* Nothing to do here ? */ + dstack_quit(); } /* declare the display module */ diff --git a/src/modules/display/dhline.c b/src/modules/display/draw/dhline.c similarity index 100% rename from src/modules/display/dhline.c rename to src/modules/display/draw/dhline.c diff --git a/src/modules/display/dline.c b/src/modules/display/draw/dline.c similarity index 100% rename from src/modules/display/dline.c rename to src/modules/display/draw/dline.c diff --git a/src/modules/display/dpixel.c b/src/modules/display/draw/dpixel.c similarity index 100% rename from src/modules/display/dpixel.c rename to src/modules/display/draw/dpixel.c diff --git a/src/modules/display/drect.c b/src/modules/display/draw/drect.c similarity index 100% rename from src/modules/display/drect.c rename to src/modules/display/draw/drect.c diff --git a/src/modules/display/dstack.c b/src/modules/display/dstack.c new file mode 100644 index 0000000..425ef2f --- /dev/null +++ b/src/modules/display/dstack.c @@ -0,0 +1,148 @@ +#include +#include +#include + +#include +#include + +static struct { + struct { + struct dstack_action *action; + int slots; + int idx; + } pool; + struct dstack_drv_interface driver; +} dstack_info = { + .pool = { + .action = NULL, + .slots = 0, + .idx = 0 + }, + .driver = { + .frame_start = NULL, + .frame_frag_next = NULL, + .frame_frag_send = NULL, + .frame_end = NULL, + } +}; + +// +// Kernel API +// + +/* dstack_init() : Initialise the draw stack (should not be involved) */ +//TODO: safe +int dstack_init(struct dstack_config *config) +{ + dstack_info.pool.action = calloc( + config->default_icall_pool_slot, + sizeof(dstack_call_t) + ); + dstack_info.pool.slots = config->default_icall_pool_slot; + dstack_info.pool.idx = -1; + for (int i = 0; i < dstack_info.pool.slots; ++i) { + dstack_info.pool.action[i].shader.table = malloc( + config->default_shader_per_action + ); + dstack_info.pool.action[i].shader.number = + config->default_shader_per_action; + dstack_info.pool.action[i].shader.idx = 0; + } + + struct vhex_driver *driver = vhex_driver_table(); + for (int i = 0; i < vhex_driver_count(); ++i) { + if (driver[i].flags.DISPLAY) { + memcpy( + &dstack_info.driver, + driver[i].module_data, + sizeof(struct dstack_drv_interface) + ); + break; + } + } +} + +/* dstack_quit() : Uninit the draw stack */ +int dstack_quit(void) +{ + for (int i = 0; i < dstack_info.pool.slots; ++i) { + free(dstack_info.pool.action[i].shader.table); + dstack_info.pool.action[i].shader.number = 0; + dstack_info.pool.action[i].shader.idx = 0; + } +} + + +// +// Internal API +// + +static did_t dstack_action_alloc(dstack_call_t *call, dshader_call_t *shader) +{ + struct dstack_action *action; + int i; + + dstack_info.pool.idx += 1; + if (dstack_info.pool.idx >= dstack_info.pool.slots) { + dstack_info.pool.slots += dstack_info.pool.slots; + dstack_info.pool.action = realloc( + dstack_info.pool.action, + dstack_info.pool.slots + ); + } + action = &dstack_info.pool.action[dstack_info.pool.idx]; + memcpy(&action->call, call, sizeof(dstack_call_t)); + if (shader != NULL) { + for (i = 0; shader[i].routine != NULL; ++i) { + if (i >= action->shader.number) { + action->shader.number += action->shader.number; + action->shader.table = realloc( + action->shader.table, + action->shader.number + ); + } + memcpy( + &action->shader.table[i], + &shader[i], + sizeof(dshader_call_t) + ); + } + } + action->shader.idx = i; + return dstack_info.pool.idx; +} + +// +// Public API +// + +/* dstack_add_action() : add a new action in the draw stack */ +did_t dstack_add_action(dstack_call_t *call, dshader_call_t *shader) +{ + return dstack_action_alloc(call, shader); +} + +/* dstack_render(): render a frame */ +void dstack_render(void) +{ + struct dshader_surface surface; + struct dstack_action *action; + + action = dstack_info.pool.action; + dstack_info.driver.frame_start(&surface); + do { + for (int i = 0; i <= dstack_info.pool.idx; ++i) { + action[i].call.routine(&surface, action[i].call.args); + for (int j = 0; j < action[i].shader.idx; j++) { + action[i].shader.table[j].routine( + &surface, + action[i].call.args, + action[i].shader.table[i].args + ); + } + } + dstack_info.driver.frame_frag_send(&surface); + } while (dstack_info.driver.frame_frag_next(&surface) == 0); + dstack_info.driver.frame_end(&surface); + dstack_info.pool.idx = 0; +} diff --git a/src/modules/display/dupdate.c b/src/modules/display/dupdate.c index be91bad..dac2838 100644 --- a/src/modules/display/dupdate.c +++ b/src/modules/display/dupdate.c @@ -1,76 +1,8 @@ #include "vhex/display.h" -#include "vhex/defs/attributes.h" -#include "vhex/defs/types.h" - -/* Registers and operations */ -enum { - device_code_read = 0x000, - driver_output_control = 0x001, - entry_mode = 0x003, - display_control_2 = 0x008, - low_power_control = 0x00b, - - ram_address_horizontal = 0x200, - ram_address_vertical = 0x201, - write_data = 0x202, - - horizontal_ram_start = 0x210, - horizontal_ram_end = 0x211, - vertical_ram_start = 0x212, - vertical_ram_end = 0x213, -}; - -/* Interface with the controller */ -static volatile uint16_t *intf = (void *)0xb4000000; -/* Bit 4 of Port R controls the RS bit of the display driver */ -static volatile uint8_t *PRDR = (void *)0xa405013c; - -static void select(uint16_t reg) -{ - /* Clear RS and write the register number */ - *PRDR &= ~0x10; - __asm__ volatile ("synco"::); - *intf = reg; - __asm__ volatile ("synco"::); - - /* Set RS back. We don't do this in read()/write() because the display - driver is optimized for consecutive GRAM access. LCD-transfers will - be faster when executing select() followed by several calls to - write(). (Although most applications should use the DMA instead.) */ - *PRDR |= 0x10; - __asm__ volatile ("synco"::); -} - -static void write(uint16_t data) -{ - *intf = data; -} +#include "vhex/display/stack.h" /* dupdate(): Push the video RAM to the display driver */ -VWEAK void dupdate(void) +void dupdate(void) { - extern uint16_t vhex_vram[]; - - /* Set the windows size */ - select(horizontal_ram_start); - write(0); - select(horizontal_ram_end); - write(395); - select(vertical_ram_start); - write(0); - select(vertical_ram_end); - write(223); - - /* Set the RAM position */ - select(ram_address_horizontal); - write(0); - select(ram_address_vertical); - write(0); - - /* Bind address 0xb4000000 to the data write command */ - select(write_data); - - /* force-fill manualy the screen */ - for (int i = 0; i < 396 * 224; ++i) - write(vhex_vram[i]); + dstack_render(); } diff --git a/src/modules/display/dascii.c b/src/modules/display/text/dascii.c similarity index 98% rename from src/modules/display/dascii.c rename to src/modules/display/text/dascii.c index 5b7d547..071e8c6 100644 --- a/src/modules/display/dascii.c +++ b/src/modules/display/text/dascii.c @@ -1,3 +1,4 @@ +#if 0 #include "vhex/display.h" #include "vhex/defs/types.h" @@ -38,3 +39,4 @@ void dascii(int x, int y, int fg, int bg, int n) } } } +#endif diff --git a/src/modules/display/dtext.c b/src/modules/display/text/dtext.c similarity index 98% rename from src/modules/display/dtext.c rename to src/modules/display/text/dtext.c index 35ce30d..90be2d1 100644 --- a/src/modules/display/dtext.c +++ b/src/modules/display/text/dtext.c @@ -1,3 +1,4 @@ +#if 0 #include "vhex/display.h" #include "vhex/defs/types.h" @@ -55,3 +56,4 @@ void dprint(int x, int y, int fg, char const * const text, ...) dtext_opt(x, y, fg, C_NONE, DTEXT_LEFT, DTEXT_TOP, buff, -1); } +#endif diff --git a/src/modules/display/dsize.c b/src/modules/display/text/dtext_size.c similarity index 98% rename from src/modules/display/dsize.c rename to src/modules/display/text/dtext_size.c index a01de3b..a84dbea 100644 --- a/src/modules/display/dsize.c +++ b/src/modules/display/text/dtext_size.c @@ -1,3 +1,4 @@ +#if 0 #include #include @@ -28,3 +29,4 @@ void dnsize(char const *str, int n, int *w, int *h) if (w != NULL) *w = strnlen(str, n) * (font8x9.width + 1); if (h != NULL) *h = font8x9.height; } +#endif diff --git a/src/modules/hypervisor/switch.c b/src/modules/hypervisor/switch.c index ec83296..1775a12 100644 --- a/src/modules/hypervisor/switch.c +++ b/src/modules/hypervisor/switch.c @@ -1,6 +1,5 @@ #include -#include - +#include #include /* hypervisor_world_switch() : perform a world switch */ @@ -11,7 +10,6 @@ int hypervisor_world_switch(hyp_world_t out, hyp_world_t in) struct vhex_world *wout; struct vhex_driver *dtable; - wout = hypervisor_world_get(out); win = hypervisor_world_get(in); if (wout == NULL || win == NULL) @@ -24,29 +22,33 @@ int hypervisor_world_switch(hyp_world_t out, hyp_world_t in) for (int i = 0; i < vhex_driver_count(); ++i) { if (dtable[i].hpowered != NULL && dtable[i].hpowered() == false) { - wout->driver[i].flags = HYP_WORLD_DRV_UNUSED; + wout->driver[i].flags.UNUSED = 1; continue; } dtable[i].hsave(wout->driver[i].context); - wout->driver[i].flags = HYP_WORLD_DRV_USED; + wout->driver[i].flags.UNUSED = 0; } for (int i = 0; i < vhex_driver_count(); ++i) { - if (HYP_WORLD_STATUS_STATE(win->status) - == HYP_WORLD_STATUS_STATE_UNINIT) { - if (dtable[i].configure != NULL) - dtable[i].configure(win->driver[i].context); - win->driver[i].flags = dtable[i].default_flag; + if (win->status.INIT == 0) { + dtable[i].configure(win->driver[i].context); + win->driver[i].flags.UNUSED = dtable[i].flags.UNUSED; + win->driver[i].flags.SHARED = dtable[i].flags.SHARED; } - if (win->driver[i].flags == HYP_WORLD_DRV_UNUSED) { + //FIXME : check shared driver + if (win->driver[i].flags.UNUSED == 1) { if (dtable[i].hpowered() == true) dtable[i].hpoweroff(); continue; } + //FIXME : check if the driver is unused if (dtable[i].hpowered != NULL && dtable[i].hpowered() == false) dtable[i].hpoweron(); dtable[i].hrestore(win->driver[i].context); + } - HYP_WORLD_STATUS_SET_STATE(win->status, HYP_WORLD_STATUS_STATE_USED); - HYP_WORLD_STATUS_SET_STATE(wout->status, HYP_WORLD_STATUS_STATE_USED); + win->status.INIT = 1; + win->status.ACTIVE = 1; + wout->status.ACTIVE = 0; + wout->status.INIT = 1; cpu_atomic_end(); } diff --git a/src/modules/hypervisor/table.c b/src/modules/hypervisor/table.c index 5f983c8..2dda775 100644 --- a/src/modules/hypervisor/table.c +++ b/src/modules/hypervisor/table.c @@ -8,68 +8,73 @@ /* internal world table */ static struct { - struct vhex_world *table; - size_t table_slot; + struct { + struct vhex_world *table; + int number; + } world; } hyp = { - .table = NULL, - .table_slot = 0 + .world = { + .table = NULL, + .number = 0 + } }; /* hypervisor_world_new() : create a new world with its name */ -hyp_world_t hypervisor_world_new(char const * const restrict name, int flags) +hyp_world_t hypervisor_world_new(char const * const restrict name) { struct vhex_driver *dtable; hyp_world_t id; /* try to find free world */ - id = 0xb0cad0; - if (hyp.table != NULL) { - for (size_t i = 0; i < hyp.table_slot; ++i) { - if (HYP_WORLD_STATUS_STATE(hyp.table[i].status) - == HYP_WORLD_STATUS_STATE_UNUSED) { - id = i; - continue; - } - if (strcmp(hyp.table[i].name, name) == 0) - return (hyp_world_already_exists); - + id = -1; + for (int i = 0; i < hyp.world.number; ++i) { + if (hyp.world.table[i].status.USED == 0) { + id = i; + continue; } + if (strcmp(hyp.world.table[i].name, name) == 0) + return (hyp_world_already_exists); } /* if no world is found, update the table */ - if (id == 0xb0cad0) { - id = hyp.table_slot; + if (id == -1) { + id = hyp.world.number; - if (hyp.table_slot == 0) - hyp.table_slot = 1; + hyp.world.number += hyp.world.number; + if (hyp.world.number == 0) + hyp.world.number = 2; - hyp.table = reallocarray( - hyp.table, - hyp.table_slot * 2, + hyp.world.table = reallocarray( + hyp.world.table, + hyp.world.number, sizeof(struct vhex_world) ); - for (size_t i = hyp.table_slot; i < hyp.table_slot * 2; ++i) { - hyp.table[i].status = HYP_WORLD_STATUS_STATE_UNUSED; - hyp.table[i].driver = NULL; - hyp.table[i].name = NULL; - } - hyp.table_slot = hyp.table_slot * 2; + for (int i = id; i < hyp.world.number; ++i) { + hyp.world.table[i].driver = NULL; + hyp.world.table[i].name = NULL; + hyp.world.table[id].status.LOCKED = 0; + hyp.world.table[id].status.ACTIVE = 0; + hyp.world.table[id].status.INIT = 0; + hyp.world.table[id].status.USED = 0; + } } /* initialize the world */ - hyp.table[id].name = strdup(name); - hyp.table[id].status = HYP_WORLD_STATUS_SET( - flags, - HYP_WORLD_STATUS_STATE_UNINIT - ); - if (hyp.table[id].driver == NULL) { - hyp.table[id].driver = malloc( - vhex_driver_count() * sizeof(*hyp.table[id].driver) + hyp.world.table[id].name = strdup(name); + hyp.world.table[id].status.LOCKED = 0; + hyp.world.table[id].status.ACTIVE = 0; + hyp.world.table[id].status.INIT = 0; + hyp.world.table[id].status.USED = 1; + + if (hyp.world.table[id].driver == NULL) { + hyp.world.table[id].driver = calloc( + vhex_driver_count(), + sizeof(*hyp.world.table[id].driver) ); dtable = vhex_driver_table(); for (int i = 0; i < vhex_driver_count(); ++i) { - hyp.table[id].driver[i].context = malloc( + hyp.world.table[id].driver[i].context = malloc( dtable[i].state_size ); } @@ -82,9 +87,9 @@ hyp_world_t hypervisor_world_new(char const * const restrict name, int flags) /* hypervisor_world_find() : find a world using its name */ hyp_world_t hypervisor_world_find(char const * const restrict name) { - if (hyp.table != NULL) { - for (size_t i = 0; i < hyp.table_slot; ++i) { - if (strcmp(hyp.table[i].name, name) == 0) + if (hyp.world.table != NULL) { + for (int i = 0; i < hyp.world.number; ++i) { + if (strcmp(hyp.world.table[i].name, name) == 0) return (i); } } @@ -94,26 +99,23 @@ hyp_world_t hypervisor_world_find(char const * const restrict name) /* hypervisor_world_get() : get a word using its ID */ struct vhex_world *hypervisor_world_get(hyp_world_t id) { - if (id < 0 || (size_t)id >= hyp.table_slot) + if (id < 0 || id >= hyp.world.number) return (NULL); - if (HYP_WORLD_STATUS_STATE(hyp.table[id].status) - == HYP_WORLD_STATUS_STATE_UNUSED) { + if (hyp.world.table[id].status.USED == 0) { return (NULL); } - return (&hyp.table[id]); + return (&hyp.world.table[id]); } /* hypervisor_world_delete() : remove world */ hyp_world_t hypervisor_world_delete(hyp_world_t id) { - if (id < 0 || (size_t)id >= hyp.table_slot) + if (id < 0 || id >= hyp.world.number) return (hyp_world_bad_id); - if (HYP_WORLD_STATUS_FLAGS(hyp.table[id].status) - == HYP_WORLD_STATUS_FLAG_UNDELETABLE) { + if (hyp.world.table[id].status.LOCKED == 1) return (hyp_world_undeletable); - } - hyp.table[id].status = HYP_WORLD_STATUS_STATE_UNUSED; + hyp.world.table[id].status.USED = 0; } diff --git a/src/modules/keyboard/keyboard.c b/src/modules/keyboard/keyboard.c index 85f5aea..02bac79 100644 --- a/src/modules/keyboard/keyboard.c +++ b/src/modules/keyboard/keyboard.c @@ -1,5 +1,5 @@ -#include "vhex/keyboard.h" -#include "vhex/module.h" +#include +#include /* module init */ @@ -23,4 +23,4 @@ struct vhex_module mod_keyboard = { .init = &__keyboard_init, .quit = &__keyboard_quit, }; -VHEX_DECLARE_MODULE(03, mod_keyboard); +VHEX_DECLARE_MODULE(04, mod_keyboard); diff --git a/src/modules/keyboard/keycache.c b/src/modules/keyboard/keycache.c index 665dfa1..550ae07 100644 --- a/src/modules/keyboard/keycache.c +++ b/src/modules/keyboard/keycache.c @@ -1,5 +1,5 @@ #include -#include +#include /* Internal cache, used like chained list. @note: diff --git a/vxsdk.toml b/vxsdk.toml index 7f1c03c..049dd3c 100644 --- a/vxsdk.toml +++ b/vxsdk.toml @@ -1,9 +1,13 @@ -[package] +[project] name = 'vxkernel' version = '0.5.0' [build] -configure = 'mkdir -p build && cd build && ../config --board=fxcg50 --format=static --verbose' +configure = 'mkdir -p build && cd build && ../configure --board=fxcg50' build = 'cd build && make' install = 'cd build && make install' uninstall = 'cd build && make uninstall' + +[dependencies] +sh-elf-vhex = 'master' +