From 126a61994270f5e338d485476f16f93b817cf4b6 Mon Sep 17 00:00:00 2001 From: Yann MAGNIN Date: Fri, 1 May 2020 11:23:56 +0200 Subject: [PATCH] Update TTY device + Fix signals error + Change process TTY management --- include/kernel/devices/tty.h | 185 ++++--- include/kernel/drivers/cpg.h | 28 + include/kernel/drivers/keyboard.h | 13 +- include/kernel/drivers/screen.h | 2 +- include/kernel/drivers/timer.h | 10 +- include/kernel/fs/filesystem.h | 4 +- include/kernel/fs/vfs.h | 1 + include/kernel/loader.h | 2 +- include/kernel/process.h | 2 - include/lib/display.h | 3 +- include/{kernel/util => lib}/elf.h | 0 include/lib/pthread.h | 30 ++ src/kernel/bootstrap/start.c | 2 +- src/kernel/devices/earlyterm/write.c | 21 +- src/kernel/devices/tty/operations/close.c | 25 +- src/kernel/devices/tty/operations/open.c | 81 +-- src/kernel/devices/tty/operations/read.c | 485 ++++-------------- src/kernel/devices/tty/operations/write.c | 193 +------ .../devices/tty/utils/keyboard/buffer.c | 179 +++++++ .../devices/tty/utils/keyboard/callback.c | 55 ++ src/kernel/devices/tty/utils/keyboard/check.c | 135 +++++ .../devices/tty/utils/keyboard/constructor.c | 37 ++ .../devices/tty/utils/keyboard/destructor.c | 12 + src/kernel/devices/tty/utils/screen/buffer.c | 93 ++++ .../devices/tty/utils/screen/constructor.c | 36 ++ .../devices/tty/utils/screen/destructor.c | 12 + .../devices/tty/utils/screen/discipline.c | 84 +++ src/kernel/devices/tty/utils/screen/display.c | 39 ++ src/kernel/drivers/cpg/constructor.c | 44 ++ src/kernel/drivers/cpg/get_frequency.c | 16 + src/kernel/drivers/keyboard/wait_event.c | 33 +- src/kernel/drivers/screen/constructor.c | 6 +- src/kernel/drivers/screen/update.c | 11 + .../drivers/{timers => timer}/constructor.c | 0 .../drivers/{timers => timer}/handler.c | 0 src/kernel/drivers/timer/install.c | 63 +++ src/kernel/drivers/timer/set_callback.c | 22 + src/kernel/drivers/timer/set_ticks.c | 31 ++ src/kernel/drivers/{timers => timer}/start.c | 0 src/kernel/drivers/{timers => timer}/stop.c | 0 .../drivers/{timers => timer}/uninstall.c | 0 src/kernel/drivers/timers/install.c | 54 -- src/kernel/fs/syscall/close.c | 8 +- src/kernel/fs/syscall/lseek.c | 8 +- src/kernel/fs/syscall/open.c | 9 +- src/kernel/fs/syscall/pread.c | 12 +- src/kernel/fs/syscall/pwrite.c | 10 +- src/kernel/fs/syscall/read.c | 12 +- src/kernel/fs/syscall/write.c | 10 +- src/kernel/fs/vfs/dentry/alloc.c | 4 + src/kernel/fs/vfs/file/close.c | 27 +- src/kernel/fs/vfs/file/open.c | 42 +- src/kernel/fs/vfs/file/read.c | 14 +- src/kernel/fs/vfs/file/write.c | 12 +- src/kernel/fs/vfs/inode/mknod.c | 15 +- src/kernel/loader/entry.c | 2 +- src/kernel/scheduler/process/create.c | 17 +- src/kernel/scheduler/process/terminate.c | 15 + src/kernel/scheduler/schedule.c | 12 +- src/kernel/scheduler/start.c | 103 +--- src/kernel/scheduler/syscall/sys_fexecve.c | 8 +- src/kernel/util/mutex.c | 54 ++ src/lib/display/dascii.c | 10 +- src/lib/display/drect.c | 57 ++ src/user/shell/main.c | 6 +- src/user/shell/shell.ld | 3 +- src/user/shell/util/manual_proc_call.c | 45 +- src/user/shell/util/wait_child.c | 3 - src/user/test/test.c | 7 +- 69 files changed, 1607 insertions(+), 967 deletions(-) create mode 100644 include/kernel/drivers/cpg.h rename include/{kernel/util => lib}/elf.h (100%) create mode 100644 include/lib/pthread.h create mode 100644 src/kernel/devices/tty/utils/keyboard/buffer.c create mode 100644 src/kernel/devices/tty/utils/keyboard/callback.c create mode 100644 src/kernel/devices/tty/utils/keyboard/check.c create mode 100644 src/kernel/devices/tty/utils/keyboard/constructor.c create mode 100644 src/kernel/devices/tty/utils/keyboard/destructor.c create mode 100644 src/kernel/devices/tty/utils/screen/buffer.c create mode 100644 src/kernel/devices/tty/utils/screen/constructor.c create mode 100644 src/kernel/devices/tty/utils/screen/destructor.c create mode 100644 src/kernel/devices/tty/utils/screen/discipline.c create mode 100644 src/kernel/devices/tty/utils/screen/display.c create mode 100644 src/kernel/drivers/cpg/constructor.c create mode 100644 src/kernel/drivers/cpg/get_frequency.c create mode 100644 src/kernel/drivers/screen/update.c rename src/kernel/drivers/{timers => timer}/constructor.c (100%) rename src/kernel/drivers/{timers => timer}/handler.c (100%) create mode 100644 src/kernel/drivers/timer/install.c create mode 100644 src/kernel/drivers/timer/set_callback.c create mode 100644 src/kernel/drivers/timer/set_ticks.c rename src/kernel/drivers/{timers => timer}/start.c (100%) rename src/kernel/drivers/{timers => timer}/stop.c (100%) rename src/kernel/drivers/{timers => timer}/uninstall.c (100%) delete mode 100644 src/kernel/drivers/timers/install.c create mode 100644 src/kernel/util/mutex.c create mode 100644 src/lib/display/drect.c diff --git a/include/kernel/devices/tty.h b/include/kernel/devices/tty.h index a687bbe..32e4441 100644 --- a/include/kernel/devices/tty.h +++ b/include/kernel/devices/tty.h @@ -4,82 +4,130 @@ #include #include #include -#include +#include #include - -// Define default buffer size. -// TODO: remove me ? -//#define TTY_BUFFER_LINES (DISPLAY_VCHAR_MAX * 3) -//#define TTY_BUFFER_COLUMNS (DISPLAY_HCHAR_MAX) +#include // Define TTY major #define TTY_DEV_MAJOR (4) -struct tty_s +// Internal TTY informations +#define TTY_INPUT_BUFFSIZE (256) +#define TTY_OUTPUT_BUFFSIZE (1024) + +struct tty { // Internal buffers + // TODO: move me ? struct { - char input[256]; - char **output; + char input[TTY_INPUT_BUFFSIZE]; + char output[TTY_OUTPUT_BUFFSIZE]; } buffers; - // Window size informations used by the write primitive + // Screen abstraction part struct { - unsigned short ws_col; - unsigned short ws_row; - unsigned short ws_xpixel; - unsigned short ws_ypixel; - } winsize; - - // Cursor informations - struct { - int16_t x; - int16_t y; + // Window size informations used by the write primitive struct { - int16_t x; - int16_t y; - } max; - } cursor; + unsigned short ws_col; + unsigned short ws_row; + unsigned short ws_xpixel; + unsigned short ws_ypixel; + } winsize; - // Object used by the drawing library. - // It's store video ram and font informations - display_t disp; -}; - -// internal strct used by the TTY read primitives -// TODO: Move me ? -// TODO: Add internal keyboard buffer !!! -struct keyboard_obj_s -{ - struct { - uint8_t *addr; - size_t size; - size_t clen; - off_t cursor; - } buffer; - struct { - uint8_t enter : 1; - uint8_t maj : 1; - uint8_t special : 1; - uint8_t ctrl : 1; - uint8_t const : 4; - } mode; - uint8_t cvisible; - struct { + // Cursor informations struct { + // Drawing cursors struct { int16_t x; int16_t y; - } cursor; - } tty; - struct { - uint8_t keycode; - off_t cursor; - } signal; - } saved; + } disp; - // FIXME Dirty place, remove / move me ! - struct tty_s *tty; + // Internal output buffer cursor + int write; + int flush; + } cursor; + + // Private data + struct { + // Object used by the drawing library. + // It's store video ram and font informations + display_t disp; + + // The timer is used to flush the internal + // output buffer + struct { + // Timer ID used to flush the output + // buffer on the screen + int id; + + // Used to indicate that the output flush timer + // is currently used + int status; + } timer; + + // used to indicate if we want to not use the cache + int nocache; + + // screen abstraction mutex + pthread_mutex_t mutex; + } private; + } screen; + + + // Internal keyboard informations + struct { + // Internal keyboard mode for cannonical (cooked) + // keyboard configurations + struct { + uint8_t enter : 1; + uint8_t maj : 1; + uint8_t special : 1; + uint8_t ctrl : 1; + uint8_t const : 4; + } mode; + + // Internal saved values, used for the echoing + // mecanism + struct { + struct { + struct { + int16_t x; + int16_t y; + } cursor; + } tty; + struct { + uint8_t keycode; + off_t cursor; + } signal; + } saved; + + // Private data + // TODO: keyboard configuration ? (raw / cannonical) + struct { + // Internal cursor informations for the input + // buffer + off_t cursor; + off_t cursor_max; + + // The timer is used to blink the currsor position + struct { + // Timer ID + int id; + + // Used to count the number of "timer_start()" + // and known if we can stop the timer. + int used; + } timer; + + // Internal mutex to avoid atomic operation + pthread_mutex_t mutex; + } private; + } keyboard; + + // Internal device data + struct { + int open_cnt; + } private; }; // primitives. @@ -88,7 +136,26 @@ extern ssize_t tty_write(void *inode, const void *buffer, size_t count); extern ssize_t tty_read(void *inode, void *buffer, size_t count); extern int tty_close(void *inode); -// IOCTL. +// Internal utilities (keyboard abstraction) +extern int tty_keyboard_constructor(struct tty *tty); +extern int tty_keyboard_buffer_insert(struct tty *tty, char n); +extern int tty_keyboard_buffer_update(struct tty *tty, key_t key); +extern int tty_keyboard_check_special(struct tty *tty, key_t key); +extern void tty_keyboard_check_signal(struct tty *tty); +extern void tty_keyboard_buffer_remove(struct tty *tty, off_t cursor); +extern void tty_keyboard_buffer_flush(struct tty *tty); +extern void tty_keyboard_buffer_echoing(struct tty *tty); +extern void tty_keyboard_destructor(struct tty *tty); + +// Internal utilities (screen abstraction) +extern int tty_screen_constructor(struct tty *tty); +extern ssize_t tty_screen_buffer_update(struct tty *tty, const uint8_t *buffer, size_t count); +extern void tty_screen_buffer_flush(struct tty *tty); +extern void tty_screen_display_callback(struct tty *tty); +extern int tty_screen_discipline_char(struct tty *tty, char n, int action); +extern void tty_screen_destructor(struct tty *tty); + +// IOCTL (remove me ?) #define TTY_IOCTL_GETDX (0x00) #define TTY_IOCTL_GETDY (0x01) extern void tty_ioctl(void *inode, uint32_t cmd, ...); diff --git a/include/kernel/drivers/cpg.h b/include/kernel/drivers/cpg.h new file mode 100644 index 0000000..4c59ec3 --- /dev/null +++ b/include/kernel/drivers/cpg.h @@ -0,0 +1,28 @@ +#ifndef __KERNEL_DRIVERS_CPG_H__ +# define __KERNEL_DRIVERS_CPG_H__ + +#include +#include + +struct cpg +{ + uint32_t fll_freq; + uint32_t pll_freq; + uint32_t cpu_freq; + uint32_t bus_freq; + uint32_t per_freq; +}; + +enum cpg_module +{ + CPG_FLL, + CPG_PLL, + CPG_CPU, + CPG_BUS, + CPG_PERIPHERAL +}; + +// Getter +extern uint32_t cpg_get_frequency(enum cpg_module module); + +#endif /*__KERNEL_DRIVERS_CPG_H__*/ diff --git a/include/kernel/drivers/keyboard.h b/include/kernel/drivers/keyboard.h index ea1b926..f282c12 100644 --- a/include/kernel/drivers/keyboard.h +++ b/include/kernel/drivers/keyboard.h @@ -16,6 +16,17 @@ struct keycache_s struct keycache_s *next; }; +// Structure used by the keybaord abstraction +// FIXME: this macros is hardware specific !! +#define KEYBOARD_NB_KEYS (96) +struct keyscan_s +{ + uint8_t keycode; + uint32_t counter; +}; +typedef struct keyscan_s keyscan_t; + + typedef enum key_e { KEY_F1 = 0x41, @@ -85,6 +96,6 @@ extern ssize_t keyboard_read(void *buffer, size_t count); extern int keyboard_close(void); // Helpers -extern void keyboard_wait_event(void); +extern void keyboard_wait_event(keyscan_t *list); #endif /*__KERNEL_DEVICES_KEYBOARD_H__*/ diff --git a/include/kernel/drivers/screen.h b/include/kernel/drivers/screen.h index 607df59..4876cd3 100644 --- a/include/kernel/drivers/screen.h +++ b/include/kernel/drivers/screen.h @@ -13,6 +13,6 @@ typedef enum { // Internal hardware abstract extern size_t screen_get(screen_getter_t getter); -extern void (*screen_update)(void *vram); +extern void screen_update(void *vram); #endif /*__KERNEL_DRIVERS_SCREEN_H__*/ diff --git a/include/kernel/drivers/timer.h b/include/kernel/drivers/timer.h index 959ed44..ab19168 100644 --- a/include/kernel/drivers/timer.h +++ b/include/kernel/drivers/timer.h @@ -23,9 +23,11 @@ typedef enum { } tmode_t; // Prototypes -extern int timer_uninstall(int timer_ID); -extern int timer_install(void *callback, void *arg, uint32_t ticks, tmode_t mode); -extern int timer_start(int timer_ID); -extern int timer_stop(int timer_ID); +extern int timer_uninstall(int timerID); +extern int timer_install(void *callback, void *arg, int hertz, tmode_t mode); +extern int timer_set_callback(int timerID, void *callback, void *arg); +extern int timer_set_ticks(int timerID, uint32_t ticks); +extern int timer_start(int timerID); +extern int timer_stop(int timerID); #endif /*__KERNEL_UTIL_TIMER_H__*/ diff --git a/include/kernel/fs/filesystem.h b/include/kernel/fs/filesystem.h index 5d36e09..793e28f 100644 --- a/include/kernel/fs/filesystem.h +++ b/include/kernel/fs/filesystem.h @@ -76,8 +76,10 @@ struct dentry // File name. char name[VFS_DENTRY_NAME_LENGHT]; - // Internal inode + // Internal inode OR device address / informations void *inode; + struct device *device; + dev_t dev_id; // Internal counter used by opne() and close() uint32_t counter; diff --git a/include/kernel/fs/vfs.h b/include/kernel/fs/vfs.h index 9526e28..bf1f8dd 100644 --- a/include/kernel/fs/vfs.h +++ b/include/kernel/fs/vfs.h @@ -7,6 +7,7 @@ #include #include #include +#include // Internal VFS macros #define VFS_MOUNT_ROOT (-1) diff --git a/include/kernel/loader.h b/include/kernel/loader.h index ce8d80b..cb63a7a 100644 --- a/include/kernel/loader.h +++ b/include/kernel/loader.h @@ -5,7 +5,7 @@ #include #include #include -#include +#include // Function extern int loader(struct process *process, const char *path); diff --git a/include/kernel/process.h b/include/kernel/process.h index 6ac6841..84ebadb 100644 --- a/include/kernel/process.h +++ b/include/kernel/process.h @@ -19,7 +19,6 @@ struct sched_task; // define process struct. -//TODO: signal ! struct process { //--- @@ -48,7 +47,6 @@ struct process FILE file; } opfile[PROCESS_NB_OPEN_FILE]; struct dentry *working_dir; - FILE tty; //--- diff --git a/include/lib/display.h b/include/lib/display.h index b276d07..7a0ec52 100644 --- a/include/lib/display.h +++ b/include/lib/display.h @@ -55,10 +55,11 @@ struct font_block_s // Draw primitives extern int dopen(display_t *disp, const char *fontname); extern void dclear(display_t *disp); -extern void dascii(display_t *disp, int row, int colomn, char const c); +extern void dascii(display_t *disp, int row, int colomn, char const c, int mode); extern size_t dprint(display_t *disp, int x, int y, char const *str, ...); extern void dscroll(display_t *disp, int line); extern void dreverse(display_t *disp, int x, int y, int width, int height); +extern void drect(display_t *disp, int x, int y, int width, int height); extern void dupdate(display_t *disp); #endif /*__LIB_DISPLAY_H__*/ diff --git a/include/kernel/util/elf.h b/include/lib/elf.h similarity index 100% rename from include/kernel/util/elf.h rename to include/lib/elf.h diff --git a/include/lib/pthread.h b/include/lib/pthread.h new file mode 100644 index 0000000..884899a --- /dev/null +++ b/include/lib/pthread.h @@ -0,0 +1,30 @@ +#ifndef __LIB_PTHREAD_H__ +# define __LIB_PTHREAD_H__ + +#include +#include +#include + +// Define internal Posix thread mutex +// FIXME: this is a custom implemetation +struct __pthread_mutex_s +{ + pid_t owner; + int lock; +}; +typedef struct __pthread_mutex_s pthread_mutex_t; + + +// Define internal Posix thread mutex attributes +struct __pthread_mutexattr_s +{ + int attr; +}; + +/* Mutex part */ +extern int pthread_mutex_init(struct __pthread_mutex_s *mutex, const struct __pthread_mutexattr_s *attr); +extern int pthread_mutex_lock(struct __pthread_mutex_s *mutex); +extern int pthread_mutex_unlock(struct __pthread_mutex_s *mutex); +extern int pthread_mutex_destroy(struct __pthread_mutex_s *mutex); + +#endif /*__LIB_PTHREAD_H__*/ diff --git a/src/kernel/bootstrap/start.c b/src/kernel/bootstrap/start.c index 43d3e96..f276fac 100644 --- a/src/kernel/bootstrap/start.c +++ b/src/kernel/bootstrap/start.c @@ -230,6 +230,6 @@ int start(void) sched_start(); // normally the kernel SHOULD / CAN not arrive here. - earlyterm_write("Kernel job fini !"); + earlyterm_write("Kernel job fini !\n"); while (1) { __asm__ volatile ("sleep"); } } diff --git a/src/kernel/devices/earlyterm/write.c b/src/kernel/devices/earlyterm/write.c index 4aa763a..ca1a7a1 100644 --- a/src/kernel/devices/earlyterm/write.c +++ b/src/kernel/devices/earlyterm/write.c @@ -49,7 +49,7 @@ static void print_base(struct earlyterm *earlyterm, uint32_t nb, while (--digits >= 0) { dascii(&earlyterm->display, earlyterm->cursor.x, - earlyterm->cursor.y, buffer[digits]); + earlyterm->cursor.y, buffer[digits], 0); earlyterm_horizontal_update(earlyterm); } } @@ -93,6 +93,13 @@ void earlyterm_write(const char *format, ...) // String format "simple" if (format[i] == '%') { + if (format[i + 1] == 'c') { + nb = (char)va_arg(ap, int); + dascii(&earlyterm.display, earlyterm.cursor.x, earlyterm.cursor.y, nb, 0); + earlyterm_horizontal_update(&earlyterm); + i = i + 1; + continue; + } if (format[i + 1] == 'd' || format[i + 1] == 'x') { // Check negative value @@ -101,7 +108,7 @@ void earlyterm_write(const char *format, ...) if (nb < 0 && format[i + 1] == 'd') { nb = 0 - nb; - dascii(&earlyterm.display, earlyterm.cursor.x, earlyterm.cursor.y, '-'); + dascii(&earlyterm.display, earlyterm.cursor.x, earlyterm.cursor.y, '-', 0); earlyterm_horizontal_update(&earlyterm); } print_base(&earlyterm, nb, (format[i + 1] == 'd') ? 10 : 16, 1); @@ -113,14 +120,14 @@ void earlyterm_write(const char *format, ...) // add @ if 'p' (pointer) if (format[i + 1] == 'p') { - dascii(&earlyterm.display, earlyterm.cursor.x, earlyterm.cursor.y, '@'); + dascii(&earlyterm.display, earlyterm.cursor.x, earlyterm.cursor.y, '@', 0); earlyterm_horizontal_update(&earlyterm); } // Add "0x" - dascii(&earlyterm.display, earlyterm.cursor.x, earlyterm.cursor.y, '0'); + dascii(&earlyterm.display, earlyterm.cursor.x, earlyterm.cursor.y, '0', 0); earlyterm_horizontal_update(&earlyterm); - dascii(&earlyterm.display, earlyterm.cursor.x, earlyterm.cursor.y, 'x'); + dascii(&earlyterm.display, earlyterm.cursor.x, earlyterm.cursor.y, 'x', 0); earlyterm_horizontal_update(&earlyterm); // Get value @@ -138,7 +145,7 @@ void earlyterm_write(const char *format, ...) { if (line_discipline(&earlyterm, *(char*)nb) != 0) continue; - dascii(&earlyterm.display, earlyterm.cursor.x, earlyterm.cursor.y, *(char*)nb); + dascii(&earlyterm.display, earlyterm.cursor.x, earlyterm.cursor.y, *(char*)nb, 0); earlyterm_horizontal_update(&earlyterm); } i = i + 1; @@ -147,7 +154,7 @@ void earlyterm_write(const char *format, ...) } // Default, display character - dascii(&earlyterm.display, earlyterm.cursor.x, earlyterm.cursor.y, format[i]); + dascii(&earlyterm.display, earlyterm.cursor.x, earlyterm.cursor.y, format[i], 0); earlyterm_horizontal_update(&earlyterm); } diff --git a/src/kernel/devices/tty/operations/close.c b/src/kernel/devices/tty/operations/close.c index b63e358..14ed72f 100644 --- a/src/kernel/devices/tty/operations/close.c +++ b/src/kernel/devices/tty/operations/close.c @@ -1,22 +1,27 @@ #include +#include +#include #include int tty_close(void *inode) { - struct tty_s *tty; - int line; + struct tty *tty; // Get tty object tty = inode; - // Free'd all allocated memory for the - // output buffer - line = tty->cursor.max.y; - while (line >= 0) - kmem_free(tty->buffers.output[line]); - kmem_free(tty->buffers.output); + // Force flush internal buffers + tty_keyboard_buffer_flush(tty); + tty_screen_buffer_flush(tty); - // Free'd tty object - kmem_free(tty); + // Start atomic operations + atomic_start(); + + // Call each module destructors + tty_keyboard_destructor(tty); + tty_screen_destructor(tty); + + // Stop atomic operations + atomic_stop(); return (0); } diff --git a/src/kernel/devices/tty/operations/open.c b/src/kernel/devices/tty/operations/open.c index 1c8e73e..5de3c85 100644 --- a/src/kernel/devices/tty/operations/open.c +++ b/src/kernel/devices/tty/operations/open.c @@ -1,70 +1,43 @@ #include #include -#include +#include #include -#include -#include +#include + +// TTY device +struct tty tty; + +static void tty_default_init(struct tty *tty) +{ + // Wipe all object data + memset(tty, 0x00, sizeof(struct tty)); + + // Force default value + // TODO: move to "./utils/" appropriate part ? + tty->keyboard.private.timer.id = -1; + tty->screen.private.timer.id = -1; +} void *tty_open(dev_t major, dev_t minor) { - struct tty_s *tty; - int line; - // TODO: handle major / minor !! (void)major; (void)minor; - // Try to allocate tty object - tty = (struct tty_s*)kmem_alloc(sizeof(struct tty_s)); - if (tty == NULL) - return (NULL); + // Start atomic operations + atomic_start(); - // Get the font used by the tty. - if (dopen(&tty->disp, "default") != 0) + // Initialize TTY + tty_default_init(&tty); + if (tty_screen_constructor(&tty) != 0 + || tty_keyboard_constructor(&tty) != 0) { - kmem_free(tty); + tty_close(&tty); + atomic_stop(); return (NULL); } - // Generate "visible" informations for the write primitive - tty->winsize.ws_xpixel = screen_get(SCREEN_WIDTH); - tty->winsize.ws_ypixel = screen_get(SCREEN_HEIGHT); - tty->winsize.ws_col = tty->winsize.ws_xpixel / (tty->disp.font->font.width + 1); - tty->winsize.ws_row = tty->winsize.ws_ypixel / (tty->disp.font->font.height + 1); - - // Generate formated output buffer indicator - tty->cursor.max.x = screen_get(SCREEN_WIDTH) / (tty->disp.font->font.width + 1); - tty->cursor.max.y = screen_get(SCREEN_HEIGHT) / (tty->disp.font->font.height + 1); - tty->cursor.max.y = tty->cursor.max.y * 4; - - // Try to alloc new tty output buffer - tty->buffers.output = (char **)kmem_alloc(sizeof(char *) * tty->cursor.max.y); - if (tty->buffers.output == NULL) - { - kmem_free(tty); - return (NULL); - } - - // Try to alloc each line of the output buffer - line = tty->cursor.max.y; - while (--line >= 0) - { - // Try to alloc the line - tty->buffers.output[line] = (char*)kmem_alloc(tty->cursor.max.x); - if (tty->buffers.output[line] != NULL) { - memset(tty->buffers.output[line], '\0', tty->cursor.max.x); - continue; - } - // Release all allocated space and return NULL - while (++line < tty->cursor.max.y) - kmem_free(tty->buffers.output[line]); - kmem_free(tty->buffers.output); - kmem_free(tty); - return (NULL); - } - - // Initialize default TTY cursor position. - tty->cursor.x = 0; - tty->cursor.y = 0; - return (tty); + // Stop atomic operations and return the device + atomic_stop(); + return (&tty); } diff --git a/src/kernel/devices/tty/operations/read.c b/src/kernel/devices/tty/operations/read.c index ead47ec..bee9a39 100644 --- a/src/kernel/devices/tty/operations/read.c +++ b/src/kernel/devices/tty/operations/read.c @@ -3,408 +3,129 @@ #include #include #include -#include #include #include #include -#include #include +#include +#include -// Intenral functions -static void check_signal(struct keyboard_obj_s *keyboard); -static int check_special(struct keyboard_obj_s *keyboard, key_t key); -static int update_buffer(struct keyboard_obj_s *keyboard, key_t key); -static int buffer_insert(struct keyboard_obj_s *keyboard, char n); -static void tty_buffer_display(struct keyboard_obj_s *keyboard); -static void cursor_callback(struct keyboard_obj_s *keyboard); - -//FIXME: this function is device-specifique !! -//FIXME: shared device error !!! -ssize_t tty_read(void *inode, void *buffer, size_t count) +static void tty_init_internal(struct tty *tty) { - extern struct keycache_s *keylist; - struct keyboard_obj_s keyboard; - struct keycache_s *keynode; - int first_key; - //int timer_fd; + // Wait TTY keyboard availability + pthread_mutex_lock(&tty->keyboard.private.mutex); - // Check potential error. - if (count < 2) - return (0); - - // Initialize internal struc. - memset(buffer, '\0', count); - keyboard.buffer.addr = buffer; - keyboard.buffer.size = count; - keyboard.buffer.cursor = 0; - keyboard.buffer.clen = 0; - keyboard.mode.enter = 0; - keyboard.mode.maj = 0; - keyboard.mode.special = 0; - keyboard.cvisible = 0; - keyboard.tty = inode; + // Wait TTY screen availability + pthread_mutex_lock(&tty->screen.private.mutex); // save TTY informations. - keyboard.saved.tty.cursor.x = keyboard.tty->cursor.x; - keyboard.saved.tty.cursor.y = keyboard.tty->cursor.y; + tty->keyboard.saved.tty.cursor.x = tty->screen.cursor.disp.x; + tty->keyboard.saved.tty.cursor.y = tty->screen.cursor.disp.y; - // Initialize timer for cursor. - // FIXME: find real ticks value !! - //timer_fd = timer_install(&cursor_callback, &keyboard, 500 * 500 * 2, TIMER_START); - //if (timer_fd == -1) - // return (0); + // Unlock the TTY screen + pthread_mutex_unlock(&tty->screen.private.mutex); + + // Start timer (if needed) for cursor blink. + if (tty->keyboard.private.timer.used == 0) + timer_start(tty->keyboard.private.timer.id); + tty->keyboard.private.timer.used += 1; + + // Unlock device + pthread_mutex_unlock(&tty->keyboard.private.mutex); +} + +//FIXME: user mutex and remove atomic_* !! +//FIXME: with mutex use DMA transfert insted of memset() ! +static ssize_t tty_uninit_internal(struct tty *tty, void *buffer, size_t count) +{ + // Wait device availability + pthread_mutex_lock(&tty->keyboard.private.mutex); + + // Get the real size to dump + if (count > tty->keyboard.private.cursor_max) + count = tty->keyboard.private.cursor_max; + + // Dump internal buffer + memcpy(buffer, tty->buffers.input, count); + + // Update the input buffer if needed + if (count < tty->keyboard.private.cursor_max) { + memcpy(tty->buffers.input, &tty->buffers.input[count], + tty->keyboard.private.cursor_max - count); + } + + // Update internal cursor + tty->keyboard.private.cursor_max = 0; + tty->keyboard.private.cursor = 0; + + // Stop the cursor timer if needed. + tty->keyboard.private.timer.used -= 1; + if (tty->keyboard.private.timer.used == 0) + timer_stop(tty->keyboard.private.timer.id); + + // Unlock device + pthread_mutex_unlock(&tty->keyboard.private.mutex); + + // Return the number of input char. + return (count); +} + +//FIXME: user mutex and remove atomic_* !! +ssize_t tty_read(void *inode, void *buffer, size_t count) +{ + keyscan_t keylist[KEYBOARD_NB_KEYS]; + struct tty *tty; + + // Check potential error. + if (count == 0) + return (0); + + // Get tty devie + tty = inode; + + // Intialize internal struct + tty_init_internal(tty); // Main Loop, wait [EXE] key. - while (keyboard.mode.enter == 0) - { - // Wait user interruption. - keyboard_wait_event(); + // TODO: use thread !!! + do { + // Wait user interactions + keyboard_wait_event(keylist); - // Start atomic operations and check - // signal, special key then update - // the buffer. - atomic_start(); - keynode = keylist; - first_key = 0; - keyboard.mode.ctrl = 0; - keyboard.saved.signal.keycode = KEY_UNUSED; - while (keynode != NULL && - (keynode->counter == 1 || keynode->keycode == KEY_OPTN || - (first_key == 0 && keynode->counter > 10 && (keynode->counter & 1) == 0))) + // Wait device availability + pthread_mutex_lock(&tty->keyboard.private.mutex); + + // Check the keys list + tty->keyboard.mode.ctrl = 0; + tty->keyboard.mode.enter = 0; + tty->keyboard.saved.signal.keycode = KEY_UNUSED; + for (int i = 0 ; keylist[i].keycode != KEY_UNUSED && i < KEYBOARD_NB_KEYS ; ++i) { + // Check key validity + if (!(keylist[i].keycode == KEY_OPTN || keylist[i].counter == 1 + || (i == 0 && keylist[i].counter > 10 && (keylist[i].counter & 1) == 0))) + continue; + // Handle current key - if (check_special(&keyboard, keynode->keycode) == 0) - update_buffer(&keyboard, keynode->keycode); + if (tty_keyboard_check_special(tty, keylist[i].keycode) == 0) + tty_keyboard_buffer_update(tty, keylist[i].keycode); // Dump the the fist pressed key - if (first_key == 0) { - keyboard.saved.signal.keycode = keynode->keycode; - keyboard.saved.signal.cursor = keyboard.buffer.cursor; + // @note: this is a workaround for the signal management + if (i == 0) { + tty->keyboard.saved.signal.keycode = keylist[i].keycode; + tty->keyboard.saved.signal.cursor = tty->keyboard.private.cursor; } - first_key = 1; - - // Get next key. - keynode = keynode->next; } + // Unlock device + pthread_mutex_unlock(&tty->keyboard.private.mutex); + // Check signal - check_signal(&keyboard); + tty_keyboard_check_signal(tty); - // Stop atomic operations - atomic_stop(); - - // Display buffer on TTY. - tty_buffer_display(&keyboard); - } - - // uninstall cursor timer. - //timer_uninstall(timer_fd); - - // Return the number of input char. - return (keyboard.buffer.clen); -} - -//TODO: move me -static void check_signal(struct keyboard_obj_s *keyboard) -{ - extern struct process *process_current; - struct { uint8_t keycode; int signal; } echapment[3] = { - {.keycode = KEY_LN, .signal = SIGINT}, - {.keycode = KEY_DIV, .signal = SIGQUIT}, - {.keycode = KEY_0, .signal = SIGTSTP} - }; - int signal; - - // Check signal sending request - if (keyboard->mode.ctrl == 0) - return; - - // Try to find the signal to send - signal = -1; - for (int i = 0 ; i < 3 ; ++i) { - if (echapment[i].keycode != keyboard->saved.signal.keycode) - continue; - signal = echapment[i].signal; - break; - } - if (signal == -1) - return; - - // Remove the cheracter - if (keyboard->saved.signal.cursor > 0) - { - // Move seconde part. - memcpy( - &keyboard->buffer.addr[keyboard->buffer.cursor - 1], - &keyboard->buffer.addr[keyboard->buffer.cursor], - keyboard->buffer.clen - keyboard->buffer.cursor - ); - - // Add null char and update clen. - keyboard->buffer.clen = keyboard->buffer.clen - 1; - keyboard->buffer.addr[keyboard->buffer.clen] = '\0'; - keyboard->buffer.cursor = keyboard->buffer.cursor - 1; - } - - // Send signal - signal_raise(process_current, signal); -} - -// TODO: move me -// TODO: update me -static int check_special(struct keyboard_obj_s *keyboard, key_t key) -{ - extern fx9860_context_t casio_context; - extern fx9860_context_t vhex_context; - - // Check CTRL key (KEY_OPT) - if (key == KEY_OPTN) { - keyboard->mode.ctrl = 1; - return (1); - } - - // Check MAJ. - if (key == KEY_ALPHA) { - keyboard->mode.maj ^= 1; - return (1); - } - - // Check Alpha / num mode. (special) - if (key == KEY_SHIFT) { - keyboard->mode.special ^= 0x01; - return (1); - } - - // Check space key (workaround) - if (key == KEY_DOT && keyboard->mode.special == 0) { - buffer_insert(keyboard, ' '); - return (1); - } - - // Check DEL key. - if (key == KEY_DEL) - { - // Check potential error. - if (keyboard->buffer.cursor <= 0) - return (1); - // Move seconde part. - memcpy( - &keyboard->buffer.addr[keyboard->buffer.cursor - 1], - &keyboard->buffer.addr[keyboard->buffer.cursor], - keyboard->buffer.clen - keyboard->buffer.cursor - ); - - // Add null char and update clen. - keyboard->buffer.clen = keyboard->buffer.clen - 1; - keyboard->buffer.addr[keyboard->buffer.clen] = '\0'; - keyboard->buffer.cursor = keyboard->buffer.cursor - 1; - return (1); - } - - // Check MENU key. - // TODO: fix me ! - if (key == KEY_MENU) - { - // Save current Vhex context and restore Casio's context. - atomic_start(); - fx9860_context_save(&vhex_context); - fx9860_context_restore(&casio_context); - atomic_stop(); - - // Inject MENU key and call GetKey(). - // TODO !!! - //casio_GetKeyWait(&row, &column, 0, 0, 0, &key); - casio_GetKey(&key); - - // Save current Casio's context and restore Vhex's context. - atomic_start(); - fx9860_context_save(&casio_context); - fx9860_context_restore(&vhex_context); - atomic_stop(); - return (1); - } - - // Check EXE key. - if (key == KEY_EXE) - { - // Add new line character. - keyboard->buffer.addr[keyboard->buffer.clen] = '\n'; - keyboard->buffer.clen = keyboard->buffer.clen + 1; - keyboard->buffer.addr[keyboard->buffer.clen] = '\0'; - - // indicate that the EXE has been pressed. - keyboard->mode.enter = 1; - return (1); - } - - // Check LEFT key. - if (key == KEY_LEFT) - { - // Check potential error. - if (keyboard->buffer.cursor <= 0) - return (1); - - // Move cursor. - keyboard->buffer.cursor = keyboard->buffer.cursor - 1; - return (1); - } - - // Check RIGHT key. - if (key == KEY_RIGHT) - { - // Check limit - if (keyboard->buffer.cursor >= keyboard->buffer.clen) - return (1); - - // Move cursor. - keyboard->buffer.cursor = keyboard->buffer.cursor + 1; - return (1); - } - return (0); -} - -static void tty_buffer_display(struct keyboard_obj_s *keyboard) -{ - size_t size; - - // Restore TTY X/Y axis positions. - keyboard->tty->cursor.x = keyboard->saved.tty.cursor.x; - keyboard->tty->cursor.y = keyboard->saved.tty.cursor.y; - - // Workaround for [EXE] key. - size = keyboard->buffer.clen; - if (keyboard->mode.enter == 0) - size = keyboard->buffer.clen + 1; - - // Write buffer. - tty_write(keyboard->tty, keyboard->buffer.addr, size); -} - -static int update_buffer(struct keyboard_obj_s *keyboard, key_t key) -{ - static const uint8_t keylist_alpha[] = { - KEY_XOT, KEY_LOG, KEY_LN, KEY_SIN, KEY_COS, KEY_TAN, - KEY_FRAC, KEY_FD, KEY_LEFTP, KEY_RIGHTP, KEY_COMMA, KEY_ARROW, - KEY_7, KEY_8, KEY_9, - KEY_4, KEY_5, KEY_6, KEY_MUL, KEY_DIV, - KEY_1, KEY_2, KEY_3, KEY_PLUS, KEY_MINUS, - KEY_0, KEY_UNUSED - }; - static const uint8_t keylist_num[] = { - KEY_0, KEY_1, KEY_2, KEY_3, KEY_4, - KEY_5, KEY_6, KEY_7, KEY_8, KEY_9, - KEY_PLUS, KEY_MINUS, KEY_MUL, KEY_DIV, - KEY_LEFTP, KEY_RIGHTP, KEY_COMMA, KEY_POWER, - KEY_DOT, KEY_FD, KEY_ARROW, KEY_UNUSED - }; - static const char keylist_num_char[] = "0123456789+-x/(),^.|_"; - const uint8_t *keycode_list; - char character; - int i; - - // Get the appropriate key list. - keycode_list = keylist_alpha; - if (keyboard->mode.special == 1) - keycode_list = keylist_num; - - // Try to find the pressed key. - i = -1; - while (keycode_list[++i] != KEY_UNUSED && keycode_list[i] != key); - if (keycode_list[i] != key) - return (0); - - // If the key match, update buffer and get the - // character to be written - character = keylist_num_char[i]; - if (keyboard->mode.special == 0) { - character = 'a' + i; - if (keyboard->mode.maj == 1) - character = 'A' + i;; - } - - // Insert new character if possible. - buffer_insert(keyboard, character); - return (1); -} - -static int buffer_insert(struct keyboard_obj_s *keyboard, char n) -{ - // Check if the buffer is full. - if (keyboard->buffer.clen + 1 >= keyboard->buffer.size) - return (1); - - // Move the seconds par of the buffer is needed - if (keyboard->buffer.cursor < keyboard->buffer.clen) - { - int i = keyboard->buffer.clen + 1; - while (--i >= (int)keyboard->buffer.cursor) - keyboard->buffer.addr[i] = keyboard->buffer.addr[i - 1]; - } - - // Add the new character. - keyboard->buffer.addr[keyboard->buffer.cursor] = n; - - // Update cursor and character len. - keyboard->buffer.cursor = keyboard->buffer.cursor + 1; - keyboard->buffer.clen = keyboard->buffer.clen + 1; - return (0); -} - -static void cursor_callback(struct keyboard_obj_s *keyboard) -{ -// static int test = 0; - - // Draw cursor if needed - if (keyboard->cvisible == 0) - { - // Force atomic operation - atomic_start(); - - // Geneate TTY buffer cursor position. - int x = keyboard->buffer.cursor + keyboard->saved.tty.cursor.x; - int y = x / keyboard->tty->cursor.max.x; - x = x - (y * keyboard->tty->cursor.max.x); - y = y + keyboard->saved.tty.cursor.y; - - // Check circular limit - if (y >= keyboard->tty->cursor.max.y) - y = y - keyboard->tty->cursor.max.y; - - // Get window row - int line = -1; - while (++line < keyboard->tty->winsize.ws_row - 1) - { - // Update row cursor. - if (--y < 0) - y = keyboard->tty->cursor.max.y - 1; - - // Check if the line existe. - if (keyboard->tty->buffers.output[y][0] == '\0') - break; - } - - //if (line != test) { - // earlyterm_write("line = %d - %d\n", line, keyboard->tty->winsize.ws_row); - // test = line; - // DBG_WAIT; - //} - - // Get "real" X and Y position (pixel) - x = x * (keyboard->tty->disp.font->font.width + 1); - y = line * (keyboard->tty->disp.font->font.height + 1); - - // Display cursor. - dreverse( - &keyboard->tty->disp, x, y, - (keyboard->tty->disp.font->font.width + 1), - (keyboard->tty->disp.font->font.height + 1) - ); - (*screen_update)(keyboard->tty->disp.vram); - - - // Stop atomic operations - atomic_stop(); - } - // Update cursor status. - keyboard->cvisible = keyboard->cvisible ^ 1; + // Display intput buffer on TTY. + tty_keyboard_buffer_echoing(tty); + } while (tty->keyboard.mode.enter == 0); + return (tty_uninit_internal(tty, buffer, count)); } diff --git a/src/kernel/devices/tty/operations/write.c b/src/kernel/devices/tty/operations/write.c index ecb3f61..5d4f582 100644 --- a/src/kernel/devices/tty/operations/write.c +++ b/src/kernel/devices/tty/operations/write.c @@ -1,186 +1,35 @@ #include -#include +#include #include -#include - -/* tty_vertical_update() - Check / update TTY vertical cursor */ -static void tty_vertical_update(struct tty_s *tty) -{ - // Get next line. - tty->cursor.y = tty->cursor.y + 1; - if (tty->cursor.y >= tty->cursor.max.y) - tty->cursor.y = 0; - - // Wipe new line. - memset(tty->buffers.output[tty->cursor.y], '\0', tty->cursor.max.x); -} - -/* tty_horizontal_update() - Check / update TTY horizotal cursor */ -static int tty_horizontal_update(struct tty_s *tty) -{ - tty->cursor.x = tty->cursor.x + 1; - if (tty->cursor.x >= tty->cursor.max.x) - { - tty_vertical_update(tty); - tty->cursor.x = 0; - return (1); - } - return (0); -} - -/* tty_buffer_update() - Line discipline */ -static ssize_t tty_buffer_update(struct tty_s *tty, const uint8_t *buffer, size_t count) -{ - int16_t offset; - ssize_t i; - - i = -1; - while (++i < (ssize_t)count) - { - // Check bell char. - if (buffer[i] == '\a') - { - // TODO - continue; - } - // Check backspace. - if (buffer[i] == '\b') - { - if (tty->cursor.x > 0) - tty->cursor.x = tty->cursor.x - 1; - tty->buffers.output[tty->cursor.y][tty->cursor.x] = '\0'; - continue; - } - - // Check horizotal tab. - if (buffer[i] == '\t') - { - // Check if we need a new line or not. - offset = 5 - (tty->cursor.x - ((tty->cursor.x / 5) * 5)); - if (tty->cursor.x + offset < tty->cursor.max.x) - { - memset(&tty->buffers.output[tty->cursor.y][tty->cursor.x], ' ', offset); - tty->cursor.x = tty->cursor.x + offset; - continue; - } - - // If a new line is required char. - // Generate a new line. - tty->cursor.x = 0; - tty_vertical_update(tty); - continue; - } - - // Check new line char. - if (buffer[i] == '\n') - { - tty->buffers.output[tty->cursor.y][tty->cursor.x] = '\n'; - tty->cursor.x = 0; - tty_vertical_update(tty); - continue; - } - - - // Check 'form feed' and 'vertical tab' char. - // @note: for now this character is interpreted like '\v' - if (buffer[i] == '\f' || buffer[i] == '\v') - { - tty_vertical_update(tty); - memset(tty->buffers.output[tty->cursor.y], ' ', tty->cursor.x); - continue; - } - - // Check carriage return. - if (buffer[i] == '\r') { tty->cursor.x = 0; continue;} - - // Update TTY buffer char. - tty->buffers.output[tty->cursor.y][tty->cursor.x] = buffer[i]; - tty_horizontal_update(tty); - } - - tty->buffers.output[tty->cursor.y][tty->cursor.x] = '\0'; - return (i); -} - -// FIXME: this function is device-specific ! -// TODO: Update me ? -static void tty_display(struct tty_s *tty) -{ - int test_row; - int line_len; - int start; - int line; - int y; - - // Start atomic operation. - atomic_start(); - - // Get the "first" line and number of line. - // @note: circular buffer. - line = -1; - test_row = tty->cursor.y; - while (++line < tty->winsize.ws_row) - { - // Update check line. - start = test_row; - if (--test_row < 0) - test_row = tty->cursor.max.y - 1; - - // Check if the line existe. - if (tty->buffers.output[test_row][0] == '\0') - break; - } - - //TODO - //TODO Display only the new char ! - //TODO Use scroll drawing function to avoid draw time ! - //TODO - - // clear screen - dclear(&tty->disp); - - // Display "on-screen" string lines. - y = -1; - while (++y <= line && y < tty->winsize.ws_row) - { - // Display line - line_len = -1; - while (tty->buffers.output[start][++line_len] != '\0') { - if (tty->buffers.output[start][line_len] != '\n') - dascii(&tty->disp, line_len, y, tty->buffers.output[start][line_len]); - } - - // Update row index - if (++start >= tty->cursor.max.y) - start = 0; - } - - // Display on screen. - (*screen_update)(tty->disp.vram); - - // Stop atomic operation - atomic_stop(); -} /* tty_write() - TTY write primitive ! */ ssize_t tty_write(void *inode, const void *buffer, size_t count) { - ssize_t written; + struct tty *tty; - // Start atomic operation. + // Get tty device + tty = inode; + + // Start atomic operation atomic_start(); - // Update internal buffer and display - // TTY on the screen. - written = tty_buffer_update(inode, buffer, count); - - // TODO: Monotonic display ? - tty_display(inode); + // Check STDERR ouput mode (force print) + // FIXME: move me !!!! + if (tty->screen.private.nocache == 1) { + size_t i = -1; + while (++i < count) + tty_screen_discipline_char(tty, ((char*)buffer)[i], 1); + screen_update(tty->screen.private.disp.vram); + tty->screen.private.nocache = 0; + atomic_stop(); + return (i); + } // Stop atomic operation atomic_stop(); - // Return the number of char written into - // TTY's internal buffer. - return (written); + // Update internal output buffer + // @note: it will be displayed monotoinically using + // hardware timer (~16hz) + return (tty_screen_buffer_update(inode, buffer, count)); } diff --git a/src/kernel/devices/tty/utils/keyboard/buffer.c b/src/kernel/devices/tty/utils/keyboard/buffer.c new file mode 100644 index 0000000..d910bf5 --- /dev/null +++ b/src/kernel/devices/tty/utils/keyboard/buffer.c @@ -0,0 +1,179 @@ +#include +#include +#include +#include +#include +#include +#include + +/* tty_keyboard_buffer_flush() - force flush the internal buffer */ +void tty_keyboard_buffer_flush(struct tty *tty) +{ + // Start atomic operation + atomic_start(); + + // Force echo the internal buffer + tty_keyboard_buffer_echoing(tty); + + tty->keyboard.private.cursor = 0; + tty->keyboard.private.cursor_max = 0; + + // Stop atomic operations + atomic_stop(); +} + +/* +** tty_buffer_remove() - Remove the character based on current +** cursor position +** @note: this function should be called ONLY if the device +** is locked +*/ +// TODO: use DMA ? +void tty_keyboard_buffer_remove(struct tty *tty, off_t cursor) +{ + if (cursor <= 0 || cursor > tty->keyboard.private.cursor_max) { + pthread_mutex_unlock(&tty->keyboard.private.mutex); + return; + } + + // Remove target char using areas overlaps (if needed) + if (cursor < tty->keyboard.private.cursor_max) + { + memcpy( + &tty->buffers.input[cursor - 1], + &tty->buffers.input[cursor], + tty->keyboard.private.cursor_max - cursor + ); + } + + // Update keyboard cu + tty->keyboard.private.cursor_max = tty->keyboard.private.cursor_max - 1; + tty->keyboard.private.cursor = tty->keyboard.private.cursor - 1; +} + +/* +** tty_buffer_insert() - Insert new character based on current +** cursor position +** @note: this function should be called ONLY if the device +** is locked +*/ +int tty_keyboard_buffer_insert(struct tty *tty, char n) +{ + // Check if the buffer is full. + if (tty->keyboard.private.cursor_max + 1 >= TTY_INPUT_BUFFSIZE) + return (1); + + // Move the seconds par of the buffer is needed + // TODO: use DMA ? + if (tty->keyboard.private.cursor < tty->keyboard.private.cursor_max) + { + int i = tty->keyboard.private.cursor_max + 1; + while (--i >= (int)tty->keyboard.private.cursor) + tty->buffers.input[i] = tty->buffers.input[i - 1]; + } + + // Add the new character. + tty->buffers.input[tty->keyboard.private.cursor] = n; + + // Update cursor and character len. + tty->keyboard.private.cursor = tty->keyboard.private.cursor + 1; + tty->keyboard.private.cursor_max = tty->keyboard.private.cursor_max + 1; + return (0); +} + +/* tty_keyboard_buffer_echoing() - Display the internal buffer */ +void tty_keyboard_buffer_echoing(struct tty *tty) +{ + // Start atomic operation + atomic_start(); + + // Save current TTY cursor positions + //saved_tty_x = tty->screen.cursor.disp.x; + //saved_tty_y = tty->screen.cursor.disp.y; + + // Set "real" position + tty->screen.cursor.disp.x = tty->keyboard.saved.tty.cursor.x; + tty->screen.cursor.disp.y = tty->keyboard.saved.tty.cursor.y; + + // Walk into input buffer and simulate the character + // echoing to force the internal line discipline to + // update TTY cursor position + for (off_t i = 0 ; i < tty->keyboard.private.cursor_max ; ++i) + { + // Clear the area + drect(&tty->screen.private.disp, + tty->screen.cursor.disp.x * (tty->screen.private.disp.font->font.width + 1), + tty->screen.cursor.disp.y * (tty->screen.private.disp.font->font.height + 1), + tty->screen.private.disp.font->font.width + 1, + tty->screen.private.disp.font->font.height + 1); + + // Update cursor and display char if needed + tty_screen_discipline_char((void*)tty, tty->buffers.input[i], 1); + } + + // workaround for the DEL actions + drect(&tty->screen.private.disp, + tty->screen.cursor.disp.x * (tty->screen.private.disp.font->font.width + 1), + tty->screen.cursor.disp.y * (tty->screen.private.disp.font->font.height + 1), + tty->screen.private.disp.font->font.width + 1, + tty->screen.private.disp.font->font.height + 1); + + // Update screen + screen_update((void *)tty->screen.private.disp.vram); + + // Stop atomic operation + atomic_stop(); +} + +/* +** tty_keyboard_buffer_update() - Udate the internal buffer +** with the given key code +** @note: this function should be called ONLY if the device +** is locked +*/ +int tty_keyboard_buffer_update(struct tty *tty, key_t key) +{ + static const uint8_t keylist_alpha[] = { + KEY_XOT, KEY_LOG, KEY_LN, KEY_SIN, KEY_COS, KEY_TAN, + KEY_FRAC, KEY_FD, KEY_LEFTP, KEY_RIGHTP, KEY_COMMA, KEY_ARROW, + KEY_7, KEY_8, KEY_9, + KEY_4, KEY_5, KEY_6, KEY_MUL, KEY_DIV, + KEY_1, KEY_2, KEY_3, KEY_PLUS, KEY_MINUS, + KEY_0, KEY_UNUSED + }; + static const uint8_t keylist_num[] = { + KEY_0, KEY_1, KEY_2, KEY_3, KEY_4, + KEY_5, KEY_6, KEY_7, KEY_8, KEY_9, + KEY_PLUS, KEY_MINUS, KEY_MUL, KEY_DIV, + KEY_LEFTP, KEY_RIGHTP, KEY_COMMA, KEY_POWER, + KEY_DOT, KEY_FD, KEY_ARROW, KEY_UNUSED + }; + static const char keylist_num_char[] = "0123456789+-x/(),^.|_"; + const uint8_t *keycode_list; + char character; + int i; + + // Get the appropriate key list. + keycode_list = keylist_alpha; + if (tty->keyboard.mode.special == 1) + keycode_list = keylist_num; + + // Try to find the pressed key. + i = -1; + while (keycode_list[++i] != KEY_UNUSED && keycode_list[i] != key); + if (keycode_list[i] != key) + return (0); + + // If the key match, update buffer and get the + // character to be written + character = keylist_num_char[i]; + if (tty->keyboard.mode.special == 0) { + character = 'a' + i; + if (tty->keyboard.mode.maj == 1) + character = 'A' + i;; + } + + // Insert new character if possible. + tty_keyboard_buffer_insert(tty, character); + return (1); +} diff --git a/src/kernel/devices/tty/utils/keyboard/callback.c b/src/kernel/devices/tty/utils/keyboard/callback.c new file mode 100644 index 0000000..e2fc57f --- /dev/null +++ b/src/kernel/devices/tty/utils/keyboard/callback.c @@ -0,0 +1,55 @@ +#include +#include +#include + +void tty_cursor_callback(volatile struct tty *tty) +{ + static int cursor_visible = 0; + int saved_tty_x; + int saved_tty_y; + int x; + int y; + + // Force atomic operation + atomic_start(); + + // Draw cursor if needed + if (cursor_visible == 0) + { + // Save current TTY cursor positions + saved_tty_x = tty->screen.cursor.disp.x; + saved_tty_y = tty->screen.cursor.disp.y; + + // Set "real" position + tty->screen.cursor.disp.x = tty->keyboard.saved.tty.cursor.x; + tty->screen.cursor.disp.y = tty->keyboard.saved.tty.cursor.y; + + // Walk into input buffer and simulate the character + // echoing to force the internal line discipline to + // update TTY cursor position + for (off_t i = 0 ; i < tty->keyboard.private.cursor ; ++i) + tty_screen_discipline_char((void*)tty, tty->buffers.input[i], 0); + + // Get "real" X and Y position (pixel) + x = tty->screen.cursor.disp.x * (tty->screen.private.disp.font->font.width + 1); + y = tty->screen.cursor.disp.y * (tty->screen.private.disp.font->font.height + 1); + + // Draw and display cursor. + dreverse( + (void *)&tty->screen.private.disp, x, y, + (tty->screen.private.disp.font->font.width + 1), + (tty->screen.private.disp.font->font.height + 1) + ); + screen_update((void *)tty->screen.private.disp.vram); + + // Restore old TTY position + tty->screen.cursor.disp.x = saved_tty_x; + tty->screen.cursor.disp.y = saved_tty_y; + } + + // Update cursor status. + cursor_visible ^= 1; + + // Stop atomic operations + atomic_stop(); +} diff --git a/src/kernel/devices/tty/utils/keyboard/check.c b/src/kernel/devices/tty/utils/keyboard/check.c new file mode 100644 index 0000000..64baad4 --- /dev/null +++ b/src/kernel/devices/tty/utils/keyboard/check.c @@ -0,0 +1,135 @@ +#include +#include +#include +#include +#include + +//FIXME: SIGINT and SIGQUIT is send by the hardware driver ?! +void tty_keyboard_check_signal(struct tty *tty) +{ + extern struct process *process_current; + struct { uint8_t keycode; int signal; } echapment[3] = { + {.keycode = KEY_LN, .signal = SIGINT}, + {.keycode = KEY_DIV, .signal = SIGQUIT}, + {.keycode = KEY_0, .signal = SIGTSTP} + }; + int signal; + + // Check signal sending request + if (tty->keyboard.mode.ctrl == 0) { + pthread_mutex_unlock(&tty->keyboard.private.mutex); + return; + } + + // Try to find the signal to send + signal = -1; + for (int i = 0 ; i < 3 ; ++i) { + if (echapment[i].keycode != tty->keyboard.saved.signal.keycode) + continue; + signal = echapment[i].signal; + break; + } + if (signal == -1) { + pthread_mutex_unlock(&tty->keyboard.private.mutex); + return; + } + + // Remove first saved character + tty_keyboard_buffer_remove(tty, tty->keyboard.saved.signal.cursor); + + // Send signal + // TODO: display signal ? + signal_raise(process_current, signal); +} + + +//TODO update ? +//@note: Call this function ONLY if the device is locked !! +int tty_keyboard_check_special(struct tty *tty, key_t key) +{ + extern fx9860_context_t casio_context; + extern fx9860_context_t vhex_context; + + // Check CTRL key (KEY_OPT) + if (key == KEY_OPTN) { + tty->keyboard.mode.ctrl = 1; + return (1); + } + + // Check MAJ. + if (key == KEY_ALPHA) { + tty->keyboard.mode.maj ^= 1; + return (1); + } + + // Check Alpha / num mode. (special) + if (key == KEY_SHIFT) { + tty->keyboard.mode.special ^= 0x01; + return (1); + } + + // Check space key (workaround) + if (key == KEY_DOT && tty->keyboard.mode.special == 0) { + tty_keyboard_buffer_insert(tty, ' '); + return (1); + } + + // Check DEL key. + if (key == KEY_DEL){ + tty_keyboard_buffer_remove(tty, tty->keyboard.private.cursor); + return (1); + } + + // Check MENU key. + // TODO: fix me ! + if (key == KEY_MENU) + { + // Save current Vhex context and restore Casio's context. + atomic_start(); + fx9860_context_save(&vhex_context); + fx9860_context_restore(&casio_context); + atomic_stop(); + + // Inject MENU key and call GetKey(). + // FIXME !!! + //casio_GetKeyWait(&row, &column, 0, 0, 0, &key); + casio_GetKey(&key); + + // Save current Casio's context and restore Vhex's context. + atomic_start(); + fx9860_context_save(&casio_context); + fx9860_context_restore(&vhex_context); + atomic_stop(); + return (1); + } + + // Check EXE key. + if (key == KEY_EXE) + { + // Add new line character. + tty->buffers.input[tty->keyboard.private.cursor_max] = '\n'; + tty->keyboard.private.cursor_max += 1; + tty->buffers.input[tty->keyboard.private.cursor_max] = '\0'; + + // indicate that the EXE has been pressed. + tty->keyboard.mode.enter = 1; + return (1); + } + + // Check LEFT key. + if (key == KEY_LEFT) + { + if (tty->keyboard.private.cursor > 0) + tty->keyboard.private.cursor -= 1; + return (1); + } + + // Check RIGHT key. + if (key == KEY_RIGHT) + { + if (tty->keyboard.private.cursor < tty->keyboard.private.cursor_max) + tty->keyboard.private.cursor += 1; + return (1); + } + return (0); +} diff --git a/src/kernel/devices/tty/utils/keyboard/constructor.c b/src/kernel/devices/tty/utils/keyboard/constructor.c new file mode 100644 index 0000000..bdfe06f --- /dev/null +++ b/src/kernel/devices/tty/utils/keyboard/constructor.c @@ -0,0 +1,37 @@ +#include +#include +#include +#include +#include + +int tty_keyboard_constructor(struct tty *tty) +{ + extern void tty_cursor_callback(volatile struct tty *tty); + + // Start atomic + atomic_start(); + + // Try to get hardware timer slot + tty->keyboard.private.timer.id = timer_install(&tty_cursor_callback, tty, 2, TIMER_STOP); + if (tty->keyboard.private.timer.id < 0) { + earlyterm_write("TTY: keyboard cursor's timer error\n"); + return (0); + } + + // Intitialise internal data used by the + // abstraction primitive + tty->keyboard.private.cursor = 0; + tty->keyboard.private.cursor_max = 0; + + // Initialize internal mutex + pthread_mutex_init(&tty->keyboard.private.mutex, NULL); + + // Intialize internal keyboard mode + tty->keyboard.mode.enter = 0; + tty->keyboard.mode.maj = 0; + tty->keyboard.mode.special = 0; + + // Start atomic + atomic_stop(); + return (0); +} diff --git a/src/kernel/devices/tty/utils/keyboard/destructor.c b/src/kernel/devices/tty/utils/keyboard/destructor.c new file mode 100644 index 0000000..7b48184 --- /dev/null +++ b/src/kernel/devices/tty/utils/keyboard/destructor.c @@ -0,0 +1,12 @@ +#include +#include + +void tty_keyboard_destructor(struct tty *tty) +{ + // Uninstall hardware timer + if (tty->keyboard.private.timer.id != -1) + timer_uninstall(tty->keyboard.private.timer.id); + + // Destroy internal mutex + pthread_mutex_destroy(&tty->keyboard.private.mutex); +} diff --git a/src/kernel/devices/tty/utils/screen/buffer.c b/src/kernel/devices/tty/utils/screen/buffer.c new file mode 100644 index 0000000..b7004f7 --- /dev/null +++ b/src/kernel/devices/tty/utils/screen/buffer.c @@ -0,0 +1,93 @@ +#include +#include +#include +#include +#include + +/* +** tty_screen_buffer_flush() - Force display all character +** currently in the output buffer +*/ +void tty_screen_buffer_flush(struct tty *tty) +{ + // start atomic operations + atomic_start(); + + // Force flush + while (tty->screen.cursor.flush != tty->screen.cursor.write) + tty_screen_display_callback(tty); + + // Stop atomic operations + atomic_stop(); +} + +/* Wait flush syncronisation (wait flush timer) */ +static void wait_sync_flush(struct tty *tty) +{ + // Wait syncro + while (1) { + // Check syncro + if (tty->screen.cursor.flush == tty->screen.cursor.write) + return; + + // Wait schedule + // FIXME: force schedule and preemptive !! + __asm__ volatile ("sleep"); + } +} + +// TODO: use DMA !!!!!! +ssize_t tty_screen_buffer_update(struct tty *tty, const uint8_t *buffer, size_t count) +{ + size_t transaction_size; + size_t size; + int counter; + int again; + + // Check useless action + if (count == 0) + return (0); + + // Wait TTY screen part + pthread_mutex_lock(&tty->screen.private.mutex); + + // Start flush timer + again = tty->screen.private.timer.status; + tty->screen.private.timer.status += 1; + if (again == 0) + timer_start(tty->screen.private.timer.id); + + // Send buffer data in the output buffer + size = 0; + counter = 0; + transaction_size = 0; + while (size < count) + { + // Get the transaction size + transaction_size = (count - size) / (TTY_OUTPUT_BUFFSIZE / 2); + if (transaction_size == 0) + transaction_size = count - size; + else + transaction_size = TTY_OUTPUT_BUFFSIZE / 2; + + // Check output buffer limit + if (tty->screen.cursor.write + transaction_size >= TTY_OUTPUT_BUFFSIZE) + transaction_size = TTY_OUTPUT_BUFFSIZE - tty->screen.cursor.write; + + // Wait output buffer syncro and send data + wait_sync_flush(tty); + memcpy(&tty->buffers.output[tty->screen.cursor.write], &buffer[size], transaction_size); + + // Update current written size + size = size + transaction_size; + + // Update buffer write cursor + tty->screen.cursor.write += transaction_size; + if (tty->screen.cursor.write >= TTY_OUTPUT_BUFFSIZE) + tty->screen.cursor.write -= TTY_OUTPUT_BUFFSIZE; + } + + // Indicate that we have finish to write + tty->screen.private.timer.status -= 1; + return (count); +} diff --git a/src/kernel/devices/tty/utils/screen/constructor.c b/src/kernel/devices/tty/utils/screen/constructor.c new file mode 100644 index 0000000..b6ccfce --- /dev/null +++ b/src/kernel/devices/tty/utils/screen/constructor.c @@ -0,0 +1,36 @@ +#include +#include +#include +#include +#include +#include + +int tty_screen_constructor(struct tty *tty) +{ + // Try to get the font used by the tty. + // @note: we use drawing lib primitives + if (dopen(&tty->screen.private.disp, "default") != 0) + return (-1); + + // Try to get hardware timer slot + tty->screen.private.timer.id = timer_install(&tty_screen_display_callback, tty, 16, TIMER_STOP); + if (tty->screen.private.timer.id < 0) { + earlyterm_write("TTY: screen flush timer error\n"); + return (-1); + } + + // Generate "visible" informations for the write primitive + tty->screen.winsize.ws_xpixel = screen_get(SCREEN_WIDTH); + tty->screen.winsize.ws_ypixel = screen_get(SCREEN_HEIGHT); + tty->screen.winsize.ws_col = tty->screen.winsize.ws_xpixel / (tty->screen.private.disp.font->font.width + 1); + tty->screen.winsize.ws_row = tty->screen.winsize.ws_ypixel / (tty->screen.private.disp.font->font.height + 1); + + // Initialize default TTY screen abstraction cursor position. + tty->screen.cursor.disp.x = 0; + tty->screen.cursor.disp.y = 0; + + // Intializei buffer cursor + tty->screen.cursor.flush = 0; + tty->screen.cursor.write = 0; + return (0); +} diff --git a/src/kernel/devices/tty/utils/screen/destructor.c b/src/kernel/devices/tty/utils/screen/destructor.c new file mode 100644 index 0000000..0f2f224 --- /dev/null +++ b/src/kernel/devices/tty/utils/screen/destructor.c @@ -0,0 +1,12 @@ +#include +#include + +void tty_screen_destructor(struct tty *tty) +{ + // Uninstall hardware timer + if (tty->screen.private.timer.id != -1) + timer_uninstall(tty->screen.private.timer.id); + + // Destroy internal mutex + pthread_mutex_destroy(&tty->screen.private.mutex); +} diff --git a/src/kernel/devices/tty/utils/screen/discipline.c b/src/kernel/devices/tty/utils/screen/discipline.c new file mode 100644 index 0000000..224d14d --- /dev/null +++ b/src/kernel/devices/tty/utils/screen/discipline.c @@ -0,0 +1,84 @@ +#include + +/* tty_vertical_update() - Check / update TTY vertical cursor */ +static void tty_vertical_update(struct tty *tty) +{ + tty->screen.cursor.disp.y = tty->screen.cursor.disp.y + 1; + if (tty->screen.cursor.disp.y >= tty->screen.winsize.ws_row) + { + dscroll(&tty->screen.private.disp, tty->screen.private.disp.font->font.height + 1); + tty->screen.cursor.disp.y = tty->screen.winsize.ws_row - 1; + } +} + +/* tty_horizontal_update() - Check / update TTY horizotal cursor */ +static int tty_horizontal_update(struct tty *tty) +{ + tty->screen.cursor.disp.x = tty->screen.cursor.disp.x + 1; + if (tty->screen.cursor.disp.x >= tty->screen.winsize.ws_col) + { + tty->screen.cursor.disp.x = 0; + tty_vertical_update(tty); + return (1); + } + return (0); +} + +/* tty_vertical_clear() - Form feed emulation */ +static void tty_vertical_clear(struct tty *tty) +{ + dscroll( + &tty->screen.private.disp, + tty->screen.private.disp.font->font.height * tty->screen.winsize.ws_row + ); +} + +int tty_screen_discipline_char(struct tty *tty, char n, int action) +{ + int offset; + + switch (n) + { + // Check bell char (TODO) + case '\a': break; + + // Check backspace. + case '\b': + if (tty->screen.cursor.disp.x > 0) + tty->screen.cursor.disp.x -= 1; + break; + + // Check tabulation + case '\t': + // Check if we need a new line or not. + offset = 5 - (tty->screen.cursor.disp.x - ((tty->screen.cursor.disp.x / 5) * 5)); + if (tty->screen.cursor.disp.x + offset < tty->screen.winsize.ws_col) { + tty->screen.cursor.disp.x = tty->screen.cursor.disp.x + offset; + break; + } + + // If a new line is required char. + // Generate a new line. + tty->screen.cursor.disp.x = 0; + tty_vertical_update(tty); + break; + + // Check 'form feed' + // Check 'vertical tab' + // Check 'new line' + // Check 'cariage return' + case '\f': tty->screen.cursor.disp.y = 0; tty_vertical_clear(tty); break; + case '\v': tty_vertical_update(tty); break; + case '\n': tty->screen.cursor.disp.x = 0; tty_vertical_update(tty); break; + case '\r': tty->screen.cursor.disp.x = 0; break; + default: + if (action != 0) { + dascii(&tty->screen.private.disp, + tty->screen.cursor.disp.x, tty->screen.cursor.disp.y, + n, 0); + } + tty_horizontal_update(tty); + return (0); + } + return (0); +} diff --git a/src/kernel/devices/tty/utils/screen/display.c b/src/kernel/devices/tty/utils/screen/display.c new file mode 100644 index 0000000..537128d --- /dev/null +++ b/src/kernel/devices/tty/utils/screen/display.c @@ -0,0 +1,39 @@ +#include +#include +#include +#include +#include +#include + +/* tty_screen_display_callback() - flush ony characte of the output buffer */ +void tty_screen_display_callback(struct tty *tty) +{ + int update; + + // Force atomic operation + atomic_start(); + + // Check useless action + update = 0; + while (tty->screen.cursor.flush != tty->screen.cursor.write) + { + tty_screen_discipline_char(tty, tty->buffers.output[tty->screen.cursor.flush], 1); + tty->screen.cursor.flush = tty->screen.cursor.flush + 1; + if (tty->screen.cursor.flush >= TTY_OUTPUT_BUFFSIZE) + tty->screen.cursor.flush = 0; + update = 1; + } + + // Update screen if needed + if (update == 1) + screen_update(tty->screen.private.disp.vram); + + // Stop timer if needed + if (tty->screen.private.timer.status == 0) { + timer_stop(tty->screen.private.timer.id); + pthread_mutex_unlock(&tty->screen.private.mutex); + } + + // Stop atomic operation + atomic_stop(); +} diff --git a/src/kernel/drivers/cpg/constructor.c b/src/kernel/drivers/cpg/constructor.c new file mode 100644 index 0000000..203da42 --- /dev/null +++ b/src/kernel/drivers/cpg/constructor.c @@ -0,0 +1,44 @@ +#include +#include +#include + +// Internal struct +struct cpg cpg_info; + +__attribute__((constructor)) +static void cpg_init(void) +{ + // Calculate FLL frequency (Khz) + // @note: RCLK = 32 768 Hz + cpg_info.fll_freq = SH7305_CPG.FLLFRQ.FLF * 32768; // Hz + cpg_info.fll_freq /= (1 << SH7305_CPG.FLLFRQ.SELXM); // Check FLL output division + + // Calculate PLL frequency (Khz) + cpg_info.pll_freq = cpg_info.fll_freq * (SH7305_CPG.FRQCRA.STC + 1); + + // Calculate CPU clock frequency ! + cpg_info.cpu_freq = cpg_info.pll_freq / (1 << (SH7305_CPG.FRQCRA.IFC + 1)); + + // Calculate BUS clock frequency ! + cpg_info.bus_freq = cpg_info.pll_freq / (1 << (SH7305_CPG.FRQCRA.BFC + 1)); + + // Calculate Peripheral clock frequency ! + cpg_info.per_freq = cpg_info.pll_freq / (1 << (SH7305_CPG.FRQCRA.PFC + 1)); + + + // Debug + earlyterm_write("Calibrate frequencies...\n"); + earlyterm_write( + "* FLL freq: %d.%d Mhz\n" + "* PLL freq: %d.%d Mhz\n" + "* CPU freq: %d.%d Mhz\n" + "* BUS freq: %d.%d Mhz\n" + "* Per freq: %d.%d Mhz\n", + cpg_info.fll_freq / 1000000, (((cpg_info.fll_freq - ((cpg_info.fll_freq / 1000000)) * 1000000)) + 999) / 1000, + cpg_info.pll_freq / 1000000, (((cpg_info.pll_freq - ((cpg_info.pll_freq / 1000000)) * 1000000)) + 999) / 1000, + cpg_info.cpu_freq / 1000000, (((cpg_info.cpu_freq - ((cpg_info.cpu_freq / 1000000)) * 1000000)) + 999) / 1000, + cpg_info.bus_freq / 1000000, (((cpg_info.bus_freq - ((cpg_info.bus_freq / 1000000)) * 1000000)) + 999) / 1000, + cpg_info.per_freq / 1000000, (((cpg_info.per_freq - ((cpg_info.per_freq / 1000000)) * 1000000)) + 999) / 1000 + ); + DBG_WAIT; +} diff --git a/src/kernel/drivers/cpg/get_frequency.c b/src/kernel/drivers/cpg/get_frequency.c new file mode 100644 index 0000000..bd3c183 --- /dev/null +++ b/src/kernel/drivers/cpg/get_frequency.c @@ -0,0 +1,16 @@ +#include + +uint32_t cpg_get_frequency(enum cpg_module module) +{ + extern struct cpg cpg_info; + + switch (module) + { + case CPG_FLL: return (cpg_info.fll_freq); + case CPG_PLL: return (cpg_info.pll_freq); + case CPG_CPU: return (cpg_info.cpu_freq); + case CPG_BUS: return (cpg_info.bus_freq); + case CPG_PERIPHERAL: return (cpg_info.per_freq); + } + return (0); +} diff --git a/src/kernel/drivers/keyboard/wait_event.c b/src/kernel/drivers/keyboard/wait_event.c index 9388929..bd84eec 100644 --- a/src/kernel/drivers/keyboard/wait_event.c +++ b/src/kernel/drivers/keyboard/wait_event.c @@ -1,18 +1,41 @@ #include +#include /*keyboard_wait_event() - Wait keys events (press or release) */ -void keyboard_wait_event(void) +void keyboard_wait_event(keyscan_t *list) { extern volatile uint8_t keylist_isUpdate; + extern struct keycache_s *keylist; + struct keycache_s *keynode; + int i; // Wait key list update. - // @note: - // To ensure reentrace and avoid data corruption - // we should wait kernel indication. - // TODO: explain correctly x) + // @note : each tim the user press or relase key(s) + // the hardware driver will set the "keylist_isUpdate" to 1. + // TODO: schedule !! while (keylist_isUpdate == 0) { __asm__ volatile ("sleep"); } + + // Start atomic operations + atomic_start(); + + // Dump all keys + i = 0; + keynode = keylist; + while (keynode != NULL) + { + list[i].counter = keynode->counter; + list[i].keycode = keynode->keycode; + keynode = keynode->next; + i = i + 1; + } + list[i].keycode = KEY_UNUSED; + + // Indicate that the key buffer has been readed keylist_isUpdate = 0; + + // Stop atomic operations + atomic_stop(); } diff --git a/src/kernel/drivers/screen/constructor.c b/src/kernel/drivers/screen/constructor.c index 02d6611..afc7c87 100644 --- a/src/kernel/drivers/screen/constructor.c +++ b/src/kernel/drivers/screen/constructor.c @@ -5,7 +5,7 @@ extern void t6k11_variant_lcd_driver(void *vram); extern void t6k11_lcd_driver(void *vram); // Primitives -void (*screen_update)(void *vram); +void (*screen_driver)(void *vram); __attribute__((constructor)) void screen_driver_load(void) @@ -13,9 +13,9 @@ void screen_driver_load(void) // Check T6K11 variant which appear during // the OS >= 03.00.0000 if (*(uint8_t*)0xa0010021 == '3') { - screen_update = (void*)&t6k11_variant_lcd_driver; + screen_driver = (void*)&t6k11_variant_lcd_driver; return; } // Default driver - screen_update = &t6k11_lcd_driver; + screen_driver = &t6k11_lcd_driver; } diff --git a/src/kernel/drivers/screen/update.c b/src/kernel/drivers/screen/update.c new file mode 100644 index 0000000..1bedc50 --- /dev/null +++ b/src/kernel/drivers/screen/update.c @@ -0,0 +1,11 @@ +#include + +void screen_update(void *vram) +{ + extern void (*screen_driver)(void *vram); + + // Check driver validity + if (screen_driver == NULL) + return; + screen_driver(vram); +} diff --git a/src/kernel/drivers/timers/constructor.c b/src/kernel/drivers/timer/constructor.c similarity index 100% rename from src/kernel/drivers/timers/constructor.c rename to src/kernel/drivers/timer/constructor.c diff --git a/src/kernel/drivers/timers/handler.c b/src/kernel/drivers/timer/handler.c similarity index 100% rename from src/kernel/drivers/timers/handler.c rename to src/kernel/drivers/timer/handler.c diff --git a/src/kernel/drivers/timer/install.c b/src/kernel/drivers/timer/install.c new file mode 100644 index 0000000..078ae6f --- /dev/null +++ b/src/kernel/drivers/timer/install.c @@ -0,0 +1,63 @@ +#include +#include +#include +#include + +/* +** int timer_instal(void*, void*, tmode_t) +** +** @info +** This function will try to setup an hardware timer. +*/ +int timer_install(void *callback, void *arg, int hertz, tmode_t mode) +{ + extern struct timer_cache_s timercache[TIMER_NUMBER]; + int prescaler[8] = {4, 16, 64, 256, 1024, 4, 4, 4}; + uint32_t ticks; + int timerID; + + // Do atomic operation because of + // sheared timer cache and I/O access. + atomic_start(); + + // Find free timer. + timerID = -1; + while (++timerID < TIMER_NUMBER && + timercache[timerID].status != TIMER_UNUSED); + if (timerID >= TIMER_NUMBER) + { + atomic_stop(); + return (-1); + } + + // Initialise internal timer data. + timercache[timerID].callback = callback; + timercache[timerID].status = mode; + timercache[timerID].arg = arg; + + // Initialise hardware module. + SH7305_TMU.TSTR.BYTE &= ~(1 << timerID); // Stop timer. + + // Calculate real ticks needed + // FIXME: correct ticks calculation (remove / 2 ?) + ticks = cpg_get_frequency(CPG_PERIPHERAL) / 2; + ticks = ticks / prescaler[SH7305_TMU.TIMER[timerID].TCR.TPSC]; + ticks = ticks / hertz; + + // Setup Timer + SH7305_TMU.TIMER[timerID].TCOR = ticks; + SH7305_TMU.TIMER[timerID].TCNT = ticks; + + // Configure timer + SH7305_TMU.TIMER[timerID].TCR.UNF = 0; // Clear interrupt flag. + SH7305_TMU.TIMER[timerID].TCR.UNIE = 1; // Enable interrupt. + + // Start timer if needed. + if (mode == TIMER_START) + SH7305_TMU.TSTR.BYTE |= 1 << timerID; + + // End of atomic operations. + // and return the timer ID. + atomic_stop(); + return (timerID); +} diff --git a/src/kernel/drivers/timer/set_callback.c b/src/kernel/drivers/timer/set_callback.c new file mode 100644 index 0000000..34ef566 --- /dev/null +++ b/src/kernel/drivers/timer/set_callback.c @@ -0,0 +1,22 @@ +#include +#include + +int timer_set_callback(int timerID, void *callback, void *arg) +{ + extern struct timer_cache_s timercache[TIMER_NUMBER]; + + // Check bad ID + if (timerID < 0 || timerID >= TIMER_NUMBER) + return (-1); + + // Start Atomic operation. + atomic_start(); + + // Set new callback and arg + timercache[timerID].callback = callback; + timercache[timerID].arg = arg; + + // Stop atomic operation and return. + atomic_stop(); + return (0); +} diff --git a/src/kernel/drivers/timer/set_ticks.c b/src/kernel/drivers/timer/set_ticks.c new file mode 100644 index 0000000..c18b6b2 --- /dev/null +++ b/src/kernel/drivers/timer/set_ticks.c @@ -0,0 +1,31 @@ +#include +#include +#include + +int timer_set_ticks(int timerID, uint32_t ticks) +{ + extern struct timer_cache_s timercache[TIMER_NUMBER]; + uint8_t status; + + // Check bad ID + if (timerID < 0 || timerID >= TIMER_NUMBER) + return (-1); + + // Start Atomic operation. + atomic_start(); + + // Save current timer status (start / stop) + status = SH7305_TMU.TSTR.BYTE &= 1 << timerID; // save + SH7305_TMU.TSTR.BYTE &= ~(1 << timerID); // stop + + // Setup Timer timer + SH7305_TMU.TIMER[timerID].TCOR = ticks; + SH7305_TMU.TIMER[timerID].TCNT = ticks; + + // Start hardware timer. + SH7305_TMU.TSTR.BYTE |= status; + + // Stop atomic operation and return. + atomic_stop(); + return (0); +} diff --git a/src/kernel/drivers/timers/start.c b/src/kernel/drivers/timer/start.c similarity index 100% rename from src/kernel/drivers/timers/start.c rename to src/kernel/drivers/timer/start.c diff --git a/src/kernel/drivers/timers/stop.c b/src/kernel/drivers/timer/stop.c similarity index 100% rename from src/kernel/drivers/timers/stop.c rename to src/kernel/drivers/timer/stop.c diff --git a/src/kernel/drivers/timers/uninstall.c b/src/kernel/drivers/timer/uninstall.c similarity index 100% rename from src/kernel/drivers/timers/uninstall.c rename to src/kernel/drivers/timer/uninstall.c diff --git a/src/kernel/drivers/timers/install.c b/src/kernel/drivers/timers/install.c deleted file mode 100644 index e7dbc5c..0000000 --- a/src/kernel/drivers/timers/install.c +++ /dev/null @@ -1,54 +0,0 @@ -#include -#include -#include - -/* -** int timer_instal(void*, void*, tmode_t) -** -** @info -** This function will try to setup an hardware timer. -*/ -int timer_install(void *callback, void *arg, uint32_t ticks, tmode_t mode) -{ - extern struct timer_cache_s timercache[TIMER_NUMBER]; - int timer_ID; - - // Do atomic operation because of - // sheared timer cache and I/O access. - atomic_start(); - - // Find free timer. - timer_ID = -1; - while (++timer_ID < TIMER_NUMBER && - timercache[timer_ID].status != TIMER_UNUSED); - if (timer_ID >= TIMER_NUMBER) - { - atomic_stop(); - return (-1); - } - - // Initialise internal timer data. - timercache[timer_ID].callback = callback; - timercache[timer_ID].status = mode; - timercache[timer_ID].arg = arg; - - // Initialise hardware module. - SH7305_TMU.TSTR.BYTE &= ~(1 << timer_ID); // Stop timer. - - // Setup Timer - SH7305_TMU.TIMER[timer_ID].TCOR = ticks; - SH7305_TMU.TIMER[timer_ID].TCNT = ticks; - - // Configure timer - SH7305_TMU.TIMER[timer_ID].TCR.UNF = 0; // Clear interrupt flag. - SH7305_TMU.TIMER[timer_ID].TCR.UNIE = 1; // Enable interrupt. - - // Start timer if needed. - if (mode == TIMER_START) - SH7305_TMU.TSTR.BYTE |= 1 << timer_ID; - - // End of atomic operations. - // and return the timer ID. - atomic_stop(); - return (timer_ID); -} diff --git a/src/kernel/fs/syscall/close.c b/src/kernel/fs/syscall/close.c index 3049446..c822ace 100644 --- a/src/kernel/fs/syscall/close.c +++ b/src/kernel/fs/syscall/close.c @@ -6,13 +6,9 @@ int sys_close(int fd) extern struct process *process_current; // Check fd validity - if (fd < 0 || fd - 3 >= PROCESS_NB_OPEN_FILE) + if (fd < 0 || fd >= PROCESS_NB_OPEN_FILE) return (-1); - // Check virtual file (TTY) - if (fd < 3) - return (0); - // Call VFS close primitive - return (vfs_close(&process_current->opfile[fd - 3].file)); + return (vfs_close(&process_current->opfile[fd].file)); } diff --git a/src/kernel/fs/syscall/lseek.c b/src/kernel/fs/syscall/lseek.c index ae5599e..b1d0319 100644 --- a/src/kernel/fs/syscall/lseek.c +++ b/src/kernel/fs/syscall/lseek.c @@ -6,13 +6,9 @@ off_t sys_lseek(int fd, off_t offset, int whence) extern struct process *process_current; // Check fd - if (fd < 0 || fd - 3 >= PROCESS_NB_OPEN_FILE) + if (fd < 0 || fd >= PROCESS_NB_OPEN_FILE) return (-1); - // Check virtual file (TTY) - if (fd < 3) - return (0); - // Call VFS lseek primitive - return (vfs_lseek(&process_current->opfile[fd - 3].file, offset, whence)); + return (vfs_lseek(&process_current->opfile[fd].file, offset, whence)); } diff --git a/src/kernel/fs/syscall/open.c b/src/kernel/fs/syscall/open.c index 627ece7..6b44023 100644 --- a/src/kernel/fs/syscall/open.c +++ b/src/kernel/fs/syscall/open.c @@ -4,13 +4,14 @@ int sys_open(const char *pathname, int flags, ...) { extern struct process *process_current; + int fd; // Get current process if (process_current == NULL) return (-1); // Try to find free file slot - int fd = -1; + fd = -1; while (++fd < PROCESS_NB_OPEN_FILE && process_current->opfile[fd].status == PROCESS_FILE_SLOT_USED); if (fd >= PROCESS_NB_OPEN_FILE) @@ -24,9 +25,5 @@ int sys_open(const char *pathname, int flags, ...) return (-1); // Return the file descriptor - // @note: - // * fd = 0 -> STDOUT_FILENO - // * fd = 1 -> STDERR_FILENO - // * fd = 2 -> STDIN_FILENO - return (fd + 3); + return (fd); } diff --git a/src/kernel/fs/syscall/pread.c b/src/kernel/fs/syscall/pread.c index 924a657..18d722f 100644 --- a/src/kernel/fs/syscall/pread.c +++ b/src/kernel/fs/syscall/pread.c @@ -7,17 +7,9 @@ ssize_t sys_pread(int fd, void *buf, size_t count, off_t offset) extern struct process *process_current; // Check fd - if (fd < 0 || fd - 3 >= PROCESS_NB_OPEN_FILE) + if (fd < 0 || fd >= PROCESS_NB_OPEN_FILE) return (-1); - // Check virtual file (TTY) and open it if needed - if (fd < 3) { - if (process_current->tty.private == NULL && - vfs_open(&process_current->tty, "/dev/tty", O_RDWR) != 0) - return (-1); - return (vfs_pread(&process_current->tty, buf, count, offset)); - } - // call VFS read primitive - return (vfs_pread(&process_current->opfile[fd - 3].file, buf, count, offset)); + return (vfs_pread(&process_current->opfile[fd].file, buf, count, offset)); } diff --git a/src/kernel/fs/syscall/pwrite.c b/src/kernel/fs/syscall/pwrite.c index f4c8908..a53b0a3 100644 --- a/src/kernel/fs/syscall/pwrite.c +++ b/src/kernel/fs/syscall/pwrite.c @@ -7,17 +7,9 @@ ssize_t sys_pwrite(int fd, const void *buf, size_t count, off_t offset) extern struct process *process_current; // Check fd - if (fd < 0 || fd - 3 >= PROCESS_NB_OPEN_FILE) + if (fd < 0 || fd >= PROCESS_NB_OPEN_FILE) return (-1); - // Check virtual file (TTY) and open it if needed - if (fd < 3) { - if (process_current->tty.private == NULL && - vfs_open(&process_current->tty, "/dev/tty", O_RDWR) != 0) - return (-1); - return (vfs_pwrite(&process_current->tty, buf, count, offset)); - } - // call VFS read primitive return (vfs_pwrite(&process_current->opfile[fd].file, buf, count, offset)); } diff --git a/src/kernel/fs/syscall/read.c b/src/kernel/fs/syscall/read.c index f451464..a7c3c17 100644 --- a/src/kernel/fs/syscall/read.c +++ b/src/kernel/fs/syscall/read.c @@ -7,17 +7,9 @@ ssize_t sys_read(int fd, void *buf, size_t count) extern struct process *process_current; // Check fd - if (fd < 0 || fd - 3 >= PROCESS_NB_OPEN_FILE) + if (fd < 0 || fd >= PROCESS_NB_OPEN_FILE) return (-1); - // Check virtual file (TTY) and open it if needed - if (fd < 3) { - if (process_current->tty.private == NULL && - vfs_open(&process_current->tty, "/dev/tty", O_RDWR) != 0) - return (-1); - return (vfs_read(&process_current->tty, buf, count)); - } - // call VFS read primitive - return (vfs_read(&process_current->opfile[fd - 3].file, buf, count)); + return (vfs_read(&process_current->opfile[fd].file, buf, count)); } diff --git a/src/kernel/fs/syscall/write.c b/src/kernel/fs/syscall/write.c index e1a3bf7..77c464a 100644 --- a/src/kernel/fs/syscall/write.c +++ b/src/kernel/fs/syscall/write.c @@ -7,17 +7,9 @@ ssize_t sys_write(int fd, const void *buf, size_t count) extern struct process *process_current; // Check fd - if (fd < 0 || fd - 3 >= PROCESS_NB_OPEN_FILE) + if (fd < 0 || fd >= PROCESS_NB_OPEN_FILE) return (-1); - // Check virtual file (TTY) and open it if needed - if (fd < 3) { - if (process_current->tty.private == NULL && - vfs_open(&process_current->tty, "/dev/tty", O_RDWR) != 0) - return (-1); - return (vfs_write(&process_current->tty, buf, count)); - } - // call VFS write primitive return (vfs_write(&process_current->opfile[fd].file, buf, count)); } diff --git a/src/kernel/fs/vfs/dentry/alloc.c b/src/kernel/fs/vfs/dentry/alloc.c index ff09031..f0c74ee 100644 --- a/src/kernel/fs/vfs/dentry/alloc.c +++ b/src/kernel/fs/vfs/dentry/alloc.c @@ -12,6 +12,9 @@ struct dentry *vfs_dentry_alloc(const char *name, mode_t mode) if (node == NULL) return (NULL); + // Wipe all informations + memset(node, 0x00, sizeof(struct dentry)); + // Initialize dentry memset(node->name, 0x00, VFS_DENTRY_NAME_LENGHT); @@ -24,6 +27,7 @@ struct dentry *vfs_dentry_alloc(const char *name, mode_t mode) // Set default value node->inode = NULL; + node->device = NULL; node->parent = NULL; node->child = NULL; node->next = NULL; diff --git a/src/kernel/fs/vfs/file/close.c b/src/kernel/fs/vfs/file/close.c index f4981b8..58e4e88 100644 --- a/src/kernel/fs/vfs/file/close.c +++ b/src/kernel/fs/vfs/file/close.c @@ -1,14 +1,37 @@ #include +#include +#include int vfs_close(FILE *file) { + struct dentry *dentry; + // Check error if (file == NULL) return (-1); - //TODO: call close primitive for device ! + // Get the dentry + dentry = file->private; + + // Start atomic operations + atomic_start(); // Update internal dentry counter - ((struct dentry*)file->private)->counter -= 1; + dentry->counter = dentry->counter - 1; + + // Call close primitive for the device if needed + if ((dentry->mode & __S_IFCHR) != 0 && dentry->counter == 0) { + dentry->device->close(dentry->inode); + dentry->inode = NULL; + } + + // Wipe all inforations + file->cursor = 0; + file->file_op = NULL; + file->permission = 0; + file->private = NULL; + + // Stop atomic operations + atomic_stop(); return (0); } diff --git a/src/kernel/fs/vfs/file/open.c b/src/kernel/fs/vfs/file/open.c index 0c87065..ab404da 100644 --- a/src/kernel/fs/vfs/file/open.c +++ b/src/kernel/fs/vfs/file/open.c @@ -1,6 +1,7 @@ #include #include #include +#include /* vfs_open() - Open file named pathname */ int vfs_open(FILE *file, char const *pathname, int flags) @@ -14,30 +15,44 @@ int vfs_open(FILE *file, char const *pathname, int flags) dentry = vfs_dentry_resolve(pathname, 0); if (dentry == NULL) { - earlyterm_write("VFS_open() error !\n"); - earlyterm_write("* path error '%s'\n", pathname); + earlyterm_write("VFS_open() path error !\n"); DBG_WAIT; return (-1); } + // Start atomic operations + atomic_start(); + // Check directory. if ((dentry->mode & __S_IFDIR) != 0) { earlyterm_write("VFS_open(): file type error '%s'\n", pathname); DBG_WAIT; + atomic_stop(); return (-2); } - //TODO: call FS specific open() primitive ? - - // Debug -/* earlyterm_write("vfs_open(): inode found !"); - earlyterm_write("* path: %s", pathname); - earlyterm_write("* name: %s", dentry->name); - earlyterm_write("* inode: %p", dentry->inode); - earlyterm_write("* file_op: %p", dentry->dentry_op.file_op); - DBG_WAIT;*/ - + // Call device specific open() primitive if needed + if ((dentry->mode & __S_IFCHR) != 0 && dentry->counter == 0) + { + // Check potential error + if (dentry->device == NULL) { + earlyterm_write("VFS_open: device does not exist\n"); + DBG_WAIT; + atomic_stop(); + return (-3); + } + + // Open the device + dentry->inode = dentry->device->open(dev_get_major(dentry->dev_id), dev_get_minor(dentry->dev_id)); + if (dentry->inode == NULL) { + earlyterm_write("VFS_open: device open error !!\n"); + DBG_WAIT; + atomic_stop(); + return (-4); + } + } + // Update interne dentry counter dentry->counter = dentry->counter + 1; @@ -46,5 +61,8 @@ int vfs_open(FILE *file, char const *pathname, int flags) file->permission = dentry->mode & (~__S_IFMT); file->file_op = dentry->dentry_op.file_op; file->cursor = 0; + + // Stop atomic operations + atomic_stop(); return (0); } diff --git a/src/kernel/fs/vfs/file/read.c b/src/kernel/fs/vfs/file/read.c index cf1ca57..20a3aeb 100644 --- a/src/kernel/fs/vfs/file/read.c +++ b/src/kernel/fs/vfs/file/read.c @@ -10,15 +10,13 @@ ssize_t vfs_read(FILE *file, void *buf, size_t count) return (-1); // Get / check file's informations - if (file->private == NULL || - file->file_op == NULL || - file->file_op->read == NULL) - return (-1); + if (file->private == NULL) + return (-2); + if (file->file_op == NULL) + return (-3); + if (file->file_op->read == NULL) + return (-4); - // Check error - if (file->cursor == 0xffffffff) - earlyterm_write("pos = %#x\n", file->cursor); - // Read with FS specifique primitive and return the numbe of reading bytes. ssize_t read = file->file_op->read(((struct dentry*)file->private)->inode, buf, count, file->cursor); if (read > 0) diff --git a/src/kernel/fs/vfs/file/write.c b/src/kernel/fs/vfs/file/write.c index d6e3059..e78817c 100644 --- a/src/kernel/fs/vfs/file/write.c +++ b/src/kernel/fs/vfs/file/write.c @@ -9,14 +9,16 @@ ssize_t vfs_write(FILE *file, const void *buf, size_t count) return (-1); // Get / check file's informations - if (file->private == NULL || - file->file_op == NULL || - file->file_op->write == NULL) - return (-1); + if (file->private == NULL) + return (-2); + if (file->file_op == NULL) + return (-3); + if (file->file_op->write == NULL) + return (-4); // Writa with FS specifique primitive and return the numbe of reading bytes. ssize_t write = file->file_op->write(((struct dentry*)file->private)->inode, buf, count, file->cursor); - if (write != -1) + if (write > 0) file->cursor = file->cursor + write; return (write); } diff --git a/src/kernel/fs/vfs/inode/mknod.c b/src/kernel/fs/vfs/inode/mknod.c index a3c9db7..3131745 100644 --- a/src/kernel/fs/vfs/inode/mknod.c +++ b/src/kernel/fs/vfs/inode/mknod.c @@ -50,27 +50,24 @@ int vfs_mknod(const char *pathname, mode_t mode, dev_t dev) name = (name == NULL) ? (void *)pathname : &name[1]; // Try to find the device - // TODO: handle othe file (mode) !!! + // TODO: handle other file (mode) !!! device = device_get(dev_get_major(dev)); if (device == NULL) { atomic_stop(); return (-2); } - // Tru to create empty node + // Try to create empty node file = vfs_dentry_alloc(name, mode | __S_IFCHR); if (file == NULL) { atomic_stop(); return (-3); } - - // Try to open device - file->inode = device->open(dev_get_major(dev), dev_get_minor(dev)); - if (file->inode == NULL) { - atomic_stop(); - return (-4); - } + // Indicate device file + file->inode = NULL; + file->device = device; + file->dev_id = dev; // Set file operations file->dentry_op.file_op = &device->file_op; diff --git a/src/kernel/loader/entry.c b/src/kernel/loader/entry.c index a79059e..a9c294c 100644 --- a/src/kernel/loader/entry.c +++ b/src/kernel/loader/entry.c @@ -1,9 +1,9 @@ #include #include #include -#include #include #include +#include // // TODO: write doc diff --git a/src/kernel/scheduler/process/create.c b/src/kernel/scheduler/process/create.c index f5d8e74..ab46556 100644 --- a/src/kernel/scheduler/process/create.c +++ b/src/kernel/scheduler/process/create.c @@ -2,8 +2,10 @@ #include #include #include -#include +#include #include +#include +#include /* proc_stacks_create() - create user and kernel stack */ static int proc_stacks_create(struct process *proc) @@ -81,9 +83,18 @@ static void proc_file_init(struct process *proc) proc->opfile[i].file.cursor = 0; } - // Initialize "special" file + // Initialize working directory path proc->working_dir = vfs_root_node; - proc->tty.private = NULL; + + // Open TTY for stdin, stdout, stderr + // TODO: add correct stderr configurations + // TODO: do not open TTY each time ? + vfs_open(&proc->opfile[STDIN_FILENO].file, "/dev/tty", O_RDWR); + vfs_open(&proc->opfile[STDOUT_FILENO].file, "/dev/tty", O_RDWR); + vfs_open(&proc->opfile[STDERR_FILENO].file, "/dev/tty", O_RDWR); + proc->opfile[STDIN_FILENO].status = PROCESS_FILE_SLOT_USED; + proc->opfile[STDOUT_FILENO].status = PROCESS_FILE_SLOT_USED; + proc->opfile[STDERR_FILENO].status = PROCESS_FILE_SLOT_USED; } /* proc_signal_init() - Initialize signal management */ diff --git a/src/kernel/scheduler/process/terminate.c b/src/kernel/scheduler/process/terminate.c index b6b7ad3..847f909 100644 --- a/src/kernel/scheduler/process/terminate.c +++ b/src/kernel/scheduler/process/terminate.c @@ -1,14 +1,29 @@ #include #include +#include #include #include #include +static void first_proc_term(int __stat_lock) +{ + earlyterm_write("Kernel PANIK !!\n"); + earlyterm_write("First process terminate [%d]\n", __stat_lock); + + // TODO: restore Casio context / environnement + earlyterm_write("Wait manual reset..."); + while (1); +} + void process_terminate(struct process *proc, int __stat_lock) { struct pm_heap_page **page; void *tmp; + // Check first process termination + if (proc->parent == NULL) + first_proc_term(__stat_lock); + // Start atomic operation atomic_start(); diff --git a/src/kernel/scheduler/schedule.c b/src/kernel/scheduler/schedule.c index ad52dbf..35a3658 100644 --- a/src/kernel/scheduler/schedule.c +++ b/src/kernel/scheduler/schedule.c @@ -1,7 +1,9 @@ #include +#include #include -//TODO: assembly ! +//TODO: assembly ? +//TODO: preemptive handling !! // @note: This part *SHOULD* be exeption safe ! int sched_schedule(common_context_t **context_current, common_context_t **context_next) { @@ -20,7 +22,7 @@ int sched_schedule(common_context_t **context_current, common_context_t **contex { // Check process validity if (task_next->status == SCHED_TASK_RUNNING - && signal_deliver_pending(task_next->process) == 0) + && signal_deliver_pending((void*)task_next->process) == 0) break; // Get next task @@ -30,8 +32,12 @@ int sched_schedule(common_context_t **context_current, common_context_t **contex } // Check error - if (task_next == sched_task_current) + // FIXME: check terminate signal ?! + if (task_next == sched_task_current) { + if (task_next != NULL) + signal_deliver_pending((void*)task_next->process); return (-1); + } // Get contexts *context_current = NULL; diff --git a/src/kernel/scheduler/start.c b/src/kernel/scheduler/start.c index f97d244..d924e83 100644 --- a/src/kernel/scheduler/start.c +++ b/src/kernel/scheduler/start.c @@ -3,107 +3,48 @@ #include #include #include +#include // Internal data used by the scheduler handler -uint32_t sched_timer_id = 0; +int sched_timer_id = 0; uint32_t sched_timer_address = 0; uint32_t sched_timer_intevt = 0; uint32_t sched_timer_tstr_bit = 0; -// Internal private function -//void sched_handler(void); - -//FIXME: remove me and wrap timer interrupt when occur !! -/*static void scheduler_timer_callback(void) -{ - common_context_t *context_current; - common_context_t *context_next; - - //TODO: quantum handling !! - //TODO: scheduler block / unblock options !! - //FIXME: Get SPC, SSR, ... !! - - // Get current context and - if (sched_schedule(&context_current, &context_next) != 0) - return; - - // Debug - //dclear(&kdisplay); - //earlyterm_write(&kdisplay, 0, 0, "Scheduler_schudele !"); - //earlyterm_write(&kdisplay, 0, 1, "context current = %p", context_current); - //earlyterm_write(&kdisplay, 0, 2, "context next = %p", context_next); - //(*screen_update)(kdisplay.vram); - //earlyterm_write(&kdisplay, 0, 3, "context switch !"); - //(*screen_update)(kdisplay.vram); - //DBG_WAIT; - - // Context switch - sched_context_switch(context_current, context_next); -}*/ - +// TODO: generate quantum and quantum counter for preemption ! void sched_start(void) { extern struct sched_task *sched_task_queue; extern struct process *process_current; - uint32_t fll_freq; - uint32_t pll_freq; - uint32_t cpu_freq; - uint32_t bus_freq; - uint32_t per_freq; - - - // Calculate FLL frequency (Khz) - // @note: RCLK = 32 768 Hz - fll_freq = SH7305_CPG.FLLFRQ.FLF * 32768; // Hz - fll_freq = fll_freq / (1 << SH7305_CPG.FLLFRQ.SELXM); // Check FLL output division - - // Calculate PLL frequency (Khz) - pll_freq = fll_freq * (SH7305_CPG.FRQCRA.STC + 1); - - // Calculate CPU clock frequency ! - cpu_freq = pll_freq / (1 << (SH7305_CPG.FRQCRA.IFC + 1)); - - // Calculate BUS clock frequency ! - bus_freq = pll_freq / (1 << (SH7305_CPG.FRQCRA.BFC + 1)); - - // Calculate Peripheral clock frequency ! - per_freq = pll_freq / (1 << (SH7305_CPG.FRQCRA.PFC + 1)); - - - // Debug - earlyterm_write( - "* FLL freq: %d.%d Mhz\n" - "* PLL freq: %d.%d Mhz\n" - "* CPU freq: %d.%d Mhz\n" - "* BUS freq: %d.%d Mhz\n" - "* Per freq: %d.%d Mhz\n", - fll_freq / 1000000, (((fll_freq - ((fll_freq / 1000000)) * 1000000)) + 999) / 1000, - pll_freq / 1000000, (((pll_freq - ((pll_freq / 1000000)) * 1000000)) + 999) / 1000, - cpu_freq / 1000000, (((cpu_freq - ((cpu_freq / 1000000)) * 1000000)) + 999) / 1000, - bus_freq / 1000000, (((bus_freq - ((bus_freq / 1000000)) * 1000000)) + 999) / 1000, - per_freq / 1000000, (((per_freq - ((per_freq / 1000000)) * 1000000)) + 999) / 1000 - ); - DBG_WAIT; // Register first process ! process_current = sched_task_queue->process; // Setup TMU0 (scheduler) interrupt ! - // @note: I use Po/4 on TMU prescaler - // TODO: generate quantum and quantum counter for preemption ! - uint32_t ticks = (per_freq / 4) / 32; - sched_timer_id = timer_install(NULL, NULL, ticks, 0); + sched_timer_id = timer_install(NULL, NULL, 32, TIMER_STOP); + if (sched_timer_id < 0) { + earlyterm_write("scheduler FATAL error (timer)\n"); + earlyterm_write("wait manuall reset..."); + while (1); + } + + // Setup appropriate ticks timing fior the timer + // @note: I use Po/4 on TMU prescaler and I want 32 process switch per second + //timer_set_ticks(sched_timer_id, (cpg_get_frequency(CPG_PERIPHERAL) / 4) / 32); + + + // Initialize internal precalculated data wich will be used + // when scheduler timer interrupt occur. sched_timer_address = (uint32_t)&SH7305_TMU.TIMER[sched_timer_id].TCR; sched_timer_intevt = 0x400 + (0x20 * sched_timer_id); sched_timer_tstr_bit = 1 << sched_timer_id; // Debug - earlyterm_write("* timer ID: %d\n", sched_timer_id); - earlyterm_write("* timer addr: %#x\n", sched_timer_address); - earlyterm_write("* timer event: %#x\n", sched_timer_intevt); - earlyterm_write("* timer TSTR: %#x\n", sched_timer_tstr_bit); - DBG_WAIT; - + //earlyterm_write("* timer ID: %d\n", sched_timer_id); + //earlyterm_write("* timer addr: %#x\n", sched_timer_address); + //earlyterm_write("* timer event: %#x\n", sched_timer_intevt); + //earlyterm_write("* timer TSTR: %#x\n", sched_timer_tstr_bit); + //DBG_WAIT; // Start scheduler timer timer_start(sched_timer_id); diff --git a/src/kernel/scheduler/syscall/sys_fexecve.c b/src/kernel/scheduler/syscall/sys_fexecve.c index fa2d855..22937e0 100644 --- a/src/kernel/scheduler/syscall/sys_fexecve.c +++ b/src/kernel/scheduler/syscall/sys_fexecve.c @@ -11,15 +11,11 @@ //TODO static void proc_dump_shared(struct process *child, struct process *parent) { - // Dump all opened file for (int i = 0 ; i < PROCESS_NB_OPEN_FILE ; ++i) { memcpy(&child->opfile[i].file, &parent->opfile[i].file, sizeof(FILE)); child->opfile[i].status = parent->opfile[i].status; } - - // Dump specific - memcpy(&child->tty, &parent->tty, sizeof(FILE)); } static int generate_arguments(struct process *proc, char **argv, char **envp) @@ -80,7 +76,7 @@ pid_t sys_fexecve(const char *pathname, char **argv, char **envp) // Try to load binary into physical memory if (loader(proc, pathname) != 0) { - earlyterm_write("sys_fexecve: loader error !"); + earlyterm_write("sys_fexecve: loader error !\n"); DBG_WAIT; process_free(proc); atomic_stop(); @@ -104,7 +100,7 @@ pid_t sys_fexecve(const char *pathname, char **argv, char **envp) // Add new process into task queue if (sched_task_add(proc)) { - earlyterm_write("sys_fexecve: scheduler error !"); + earlyterm_write("sys_fexecve: scheduler error !\n"); DBG_WAIT; process_free(proc); atomic_stop(); diff --git a/src/kernel/util/mutex.c b/src/kernel/util/mutex.c new file mode 100644 index 0000000..7dabe7d --- /dev/null +++ b/src/kernel/util/mutex.c @@ -0,0 +1,54 @@ +#include +#include +#include +#include + +int pthread_mutex_init(struct __pthread_mutex_s *mutex, + const struct __pthread_mutexattr_s *attr) +{ + // FIXME: handle attribute + (void)attr; + + // Initialize mutex + mutex->lock = 0; + return (0); +} + +int pthread_mutex_lock(struct __pthread_mutex_s *mutex) +{ + // Wait util the mutex is unlocked + while (1) + { + // Check if the mutex is unlock + atomic_start(); + if (mutex->lock == 0) + break; + atomic_stop(); + + // TODO: schedule + __asm__ volatile ("sleep"); + } + + // Lock the mutex + mutex->lock = 1; + + // Stop atomic operations + atomic_stop(); + return (0); +} + +int pthread_mutex_unlock(struct __pthread_mutex_s *mutex) +{ + // Check validity and unlock mutex if possible + atomic_start(); + mutex->lock = 0; + atomic_stop(); + return (0); +} + +//TODO +int pthread_mutex_destroy(struct __pthread_mutex_s *mutex) +{ + (void)mutex; + return (-1); +} diff --git a/src/lib/display/dascii.c b/src/lib/display/dascii.c index 8b4b3c6..8f39523 100644 --- a/src/lib/display/dascii.c +++ b/src/lib/display/dascii.c @@ -1,6 +1,7 @@ #include -static void font_draw_core(uint32_t *vram, struct font_s *font, struct font_block_s *fblock) +static void font_draw_core(uint32_t *vram, struct font_s *font, + struct font_block_s *fblock, int mode) { uint8_t vram_offset_y; uint32_t pixel_cursor; @@ -34,6 +35,9 @@ static void font_draw_core(uint32_t *vram, struct font_s *font, struct font_bloc { vram[((fblock->x + x) >> 5) + vram_offset_y] |= 0x80000000 >> ((fblock->x + x) & 31); + } else if (mode == 1) { + vram[((fblock->x + x) >> 5) + vram_offset_y] &= + ~(0x80000000 >> ((fblock->x + x) & 31)); } } @@ -45,7 +49,7 @@ static void font_draw_core(uint32_t *vram, struct font_s *font, struct font_bloc /* dascii() - Draw ASCII character into Video RAM */ -void dascii(display_t *disp, int x, int y, char const c) +void dascii(display_t *disp, int x, int y, char const c, int mode) { struct font_block_s fblock; @@ -94,5 +98,5 @@ void dascii(display_t *disp, int x, int y, char const c) return; // Draw ASCII character. - font_draw_core(disp->vram, disp->font, &fblock); + font_draw_core(disp->vram, disp->font, &fblock, mode); } diff --git a/src/lib/display/drect.c b/src/lib/display/drect.c new file mode 100644 index 0000000..1dfb729 --- /dev/null +++ b/src/lib/display/drect.c @@ -0,0 +1,57 @@ +#include + +void drect(display_t *disp, int x, int y, int width, int height) +{ + int vram_offset_y; + int j; + + // Check error. + if (width < 0 || height < 0) + return; + + // Get "real" X position and area width. + if (x < 0) + { + width = width + x; + x = 0; + } else { + if (x + width >= (int)disp->display.width) + width = disp->display.width - x; + } + + // Get "real" Y position and area height. + if (y < 0) + { + height = height + x; + y = 0; + } else { + if (y + height >= (int)disp->display.height) + height = disp->display.height - x; + } + + // Check potential error. + // @note we do not check height because the while() + // while do the job for us. + if (width < 0) + return; + + // Generate VRAM offset for Y axis. + // @note: + // The screen width size is always 128 and we + // use 4-aligned Video RAM so 32 pixels per "slot" + // and 128 / 32 = 4. + // y * 4 can be optimised by used shift operator, + // this is why we use y << 2 because 2^2 = 4. + vram_offset_y = (y + height - 1) << 2; + + // Reverse area + while (--height >= 0) + { + j = width + x; + while (--j >= x) + { + disp->vram[(j >> 5) + vram_offset_y] &= ~(0x80000000 >> (j & 31)); + } + vram_offset_y = vram_offset_y - 4; + } +} diff --git a/src/user/shell/main.c b/src/user/shell/main.c index b14f04b..5dd4ab6 100644 --- a/src/user/shell/main.c +++ b/src/user/shell/main.c @@ -13,7 +13,7 @@ int main(void) int argc; // Shell main loop. - write(STDOUT_FILENO, "Boot Complete !\n", 16); + printf("Boot Complete !\n"); // Ignore internal signals (keyboard) //signal(SIGINT, SIG_IGN); @@ -29,12 +29,12 @@ int main(void) cmd_size = read(STDIN_FILENO, input, 12); // Check no char - if (cmd_size == 1) + if (cmd_size < 1) continue; // Generate argc / argv. if (strtotab(&argc, &argv, input) != 0) { - printf("parser: internal error\n"); + write(STDOUT_FILENO, "\n", 1); continue; } diff --git a/src/user/shell/shell.ld b/src/user/shell/shell.ld index 9e95154..30062f2 100644 --- a/src/user/shell/shell.ld +++ b/src/user/shell/shell.ld @@ -33,7 +33,8 @@ SECTIONS /* Procedure Linkage Table */ *(.plt) - /* GLobal Offset Table */ + /* Global Offset Table */ + /* TODO: move me into .data section ? */ *(.got.plt) *(.got.*) *(.got) diff --git a/src/user/shell/util/manual_proc_call.c b/src/user/shell/util/manual_proc_call.c index d14831d..8830cb4 100644 --- a/src/user/shell/util/manual_proc_call.c +++ b/src/user/shell/util/manual_proc_call.c @@ -4,25 +4,48 @@ #include #include #include +#include int manual_proc_call(char **argv) { - char pathname[32]; - pid_t child; + char c[1024]; + int ret; + int fd; + + // Try to open test file + (void)argv; + fd = open("/mnt/casio/VHEX/text.txt", O_RDONLY); + if (fd < 0) { + dprintf(STDERR_FILENO, "unable to open test file\n"); + return (84); + } + + // Display file + while (1) + { + ret = read(fd, c, 1020); + if (ret <= 0) + break; + write(STDOUT_FILENO, c, ret); + } + return (0); + +// char pathname[32]; +// pid_t child; // Generate pathname // TODO: handle PATH - strcpy(pathname, "/mnt/casio/VHEX/"); - strcat(pathname, argv[0]); + //strcpy(pathname, "/mnt/casio/VHEX/"); + //strcat(pathname, argv[0]); // Try to call binary from eeprom - printf("try to call '%s'\n", pathname); - for(int i = 0 ; i < 3000000 ; ++i); - child = fexecve(pathname, argv, NULL); - if (child != 0) - return (-1); +// printf("try to call '%s'\n", pathname); +// for(int i = 0 ; i < 3000000 ; ++i); +// child = fexecve(pathname, argv, NULL); +// if (child != 0) + // return (-1); // Wait child process - wait_child(child); - return (0); +// wait_child(child); +// return (0); } diff --git a/src/user/shell/util/wait_child.c b/src/user/shell/util/wait_child.c index 66e3847..399f485 100644 --- a/src/user/shell/util/wait_child.c +++ b/src/user/shell/util/wait_child.c @@ -43,9 +43,6 @@ void wait_child(pid_t pid) // Wait child death waitpid(pid, &wstatus, 0); - // FIXME: workaround dto display - printf("\n"); - // Check exit() return if (WIFEXITED(wstatus)) { diff --git a/src/user/test/test.c b/src/user/test/test.c index 3c97830..be74c19 100644 --- a/src/user/test/test.c +++ b/src/user/test/test.c @@ -28,10 +28,13 @@ int main(int argc, char **argv) break; write(STDOUT_FILENO, c, ret); } + printf("test oui:"); // Wait signal // TODO: better signal management (kernel) - printf("wait signal....\n"); - while (read(STDIN_FILENO, c, 3) != 4); + if (argc != 1) { + printf("wait signal....\n"); + while (read(STDIN_FILENO, c, 3) != 4); + } return (0); }