Update TTY device + Fix signals error + Change process TTY management
This commit is contained in:
parent
7140bb1631
commit
126a619942
|
@ -4,82 +4,130 @@
|
|||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#include <kernel/drivers/screen.h>
|
||||
#include <kernel/drivers/keyboard.h>
|
||||
#include <display.h>
|
||||
|
||||
// Define default buffer size.
|
||||
// TODO: remove me ?
|
||||
//#define TTY_BUFFER_LINES (DISPLAY_VCHAR_MAX * 3)
|
||||
//#define TTY_BUFFER_COLUMNS (DISPLAY_HCHAR_MAX)
|
||||
#include <pthread.h>
|
||||
|
||||
// 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, ...);
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
#ifndef __KERNEL_DRIVERS_CPG_H__
|
||||
# define __KERNEL_DRIVERS_CPG_H__
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
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__*/
|
|
@ -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__*/
|
||||
|
|
|
@ -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__*/
|
||||
|
|
|
@ -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__*/
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include <kernel/fs/file.h>
|
||||
#include <kernel/fs/filesystem.h>
|
||||
#include <kernel/devices/device.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
// Internal VFS macros
|
||||
#define VFS_MOUNT_ROOT (-1)
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
#include <stdint.h>
|
||||
#include <kernel/fs/file.h>
|
||||
#include <kernel/process.h>
|
||||
#include <kernel/util/elf.h>
|
||||
#include <elf.h>
|
||||
|
||||
// Function
|
||||
extern int loader(struct process *process, const char *path);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
||||
//---
|
||||
|
|
|
@ -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__*/
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
#ifndef __LIB_PTHREAD_H__
|
||||
# define __LIB_PTHREAD_H__
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
// 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__*/
|
|
@ -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"); }
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,22 +1,27 @@
|
|||
#include <kernel/devices/tty.h>
|
||||
#include <kernel/drivers/timer.h>
|
||||
#include <kernel/util/atomic.h>
|
||||
#include <kernel/util/kmem.h>
|
||||
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -1,70 +1,43 @@
|
|||
#include <kernel/devices/tty.h>
|
||||
#include <kernel/devices/earlyterm.h>
|
||||
#include <kernel/drivers/screen.h>
|
||||
#include <kernel/util/atomic.h>
|
||||
#include <kernel/util/kmem.h>
|
||||
#include <lib/display.h>
|
||||
#include <lib/string.h>
|
||||
#include <string.h>
|
||||
|
||||
// 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/<module>" 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);
|
||||
}
|
||||
|
|
|
@ -3,408 +3,129 @@
|
|||
#include <kernel/drivers/keyboard.h>
|
||||
#include <kernel/drivers/timer.h>
|
||||
#include <kernel/util/atomic.h>
|
||||
#include <kernel/util/casio.h>
|
||||
#include <kernel/context.h>
|
||||
#include <kernel/syscall.h>
|
||||
#include <kernel/signal.h>
|
||||
#include <lib/string.h>
|
||||
#include <sys/signal.h>
|
||||
#include <pthread.h>
|
||||
#include <string.h>
|
||||
|
||||
// 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));
|
||||
}
|
||||
|
|
|
@ -1,186 +1,35 @@
|
|||
#include <kernel/devices/tty.h>
|
||||
#include <kernel/devices/earlyterm.h>
|
||||
#include <kernel/drivers/screen.h>
|
||||
#include <kernel/util/atomic.h>
|
||||
#include <lib/string.h>
|
||||
|
||||
/* 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));
|
||||
}
|
||||
|
|
|
@ -0,0 +1,179 @@
|
|||
#include <kernel/devices/tty.h>
|
||||
#include <kernel/devices/earlyterm.h>
|
||||
#include <kernel/drivers/screen.h>
|
||||
#include <kernel/util/atomic.h>
|
||||
#include <lib/pthread.h>
|
||||
#include <lib/display.h>
|
||||
#include <lib/string.h>
|
||||
|
||||
/* 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);
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
#include <kernel/devices/tty.h>
|
||||
#include <kernel/drivers/screen.h>
|
||||
#include <kernel/util/atomic.h>
|
||||
|
||||
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();
|
||||
}
|
|
@ -0,0 +1,135 @@
|
|||
#include <kernel/devices/tty.h>
|
||||
#include <kernel/drivers/keyboard.h>
|
||||
#include <kernel/util/casio.h>
|
||||
#include <kernel/util/atomic.h>
|
||||
#include <kernel/signal.h>
|
||||
|
||||
//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);
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
#include <kernel/devices/tty.h>
|
||||
#include <kernel/drivers/timer.h>
|
||||
#include <kernel/devices/earlyterm.h>
|
||||
#include <kernel/util/atomic.h>
|
||||
#include <pthread.h>
|
||||
|
||||
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);
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
#include <kernel/devices/tty.h>
|
||||
#include <kernel/drivers/timer.h>
|
||||
|
||||
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);
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
#include <kernel/devices/tty.h>
|
||||
#include <kernel/devices/earlyterm.h>
|
||||
#include <kernel/drivers/timer.h>
|
||||
#include <kernel/util/atomic.h>
|
||||
#include <string.h>
|
||||
|
||||
/*
|
||||
** 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);
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
#include <kernel/devices/tty.h>
|
||||
#include <kernel/devices/earlyterm.h>
|
||||
#include <kernel/drivers/screen.h>
|
||||
#include <kernel/drivers/timer.h>
|
||||
#include <kernel/util/kmem.h>
|
||||
#include <string.h>
|
||||
|
||||
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);
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
#include <kernel/devices/tty.h>
|
||||
#include <kernel/drivers/timer.h>
|
||||
|
||||
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);
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
#include <kernel/devices/tty.h>
|
||||
|
||||
/* 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);
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
#include <kernel/devices/tty.h>
|
||||
#include <kernel/devices/earlyterm.h>
|
||||
#include <kernel/drivers/screen.h>
|
||||
#include <kernel/drivers/timer.h>
|
||||
#include <kernel/util/atomic.h>
|
||||
#include <display.h>
|
||||
|
||||
/* 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();
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
#include <kernel/drivers/cpg.h>
|
||||
#include <kernel/hardware/cpg.h>
|
||||
#include <kernel/devices/earlyterm.h>
|
||||
|
||||
// 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;
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
#include <kernel/drivers/cpg.h>
|
||||
|
||||
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);
|
||||
}
|
|
@ -1,18 +1,41 @@
|
|||
#include <kernel/drivers/keyboard.h>
|
||||
#include <kernel/util/atomic.h>
|
||||
|
||||
/*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();
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
#include <kernel/drivers/screen.h>
|
||||
|
||||
void screen_update(void *vram)
|
||||
{
|
||||
extern void (*screen_driver)(void *vram);
|
||||
|
||||
// Check driver validity
|
||||
if (screen_driver == NULL)
|
||||
return;
|
||||
screen_driver(vram);
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
#include <kernel/drivers/timer.h>
|
||||
#include <kernel/drivers/cpg.h>
|
||||
#include <kernel/hardware/tmu.h>
|
||||
#include <kernel/util/atomic.h>
|
||||
|
||||
/*
|
||||
** 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);
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
#include <kernel/drivers/timer.h>
|
||||
#include <kernel/util/atomic.h>
|
||||
|
||||
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);
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
#include <kernel/drivers/timer.h>
|
||||
#include <kernel/hardware/tmu.h>
|
||||
#include <kernel/util/atomic.h>
|
||||
|
||||
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);
|
||||
}
|
|
@ -1,54 +0,0 @@
|
|||
#include <kernel/drivers/timer.h>
|
||||
#include <kernel/hardware/tmu.h>
|
||||
#include <kernel/util/atomic.h>
|
||||
|
||||
/*
|
||||
** 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);
|
||||
}
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -1,14 +1,37 @@
|
|||
#include <kernel/fs/vfs.h>
|
||||
#include <kernel/fs/stat.h>
|
||||
#include <kernel/util/atomic.h>
|
||||
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include <kernel/fs/vfs.h>
|
||||
#include <kernel/fs/stat.h>
|
||||
#include <kernel/devices/earlyterm.h>
|
||||
#include <kernel/util/atomic.h>
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
#include <kernel/loader.h>
|
||||
#include <kernel/fs/vfs.h>
|
||||
#include <kernel/fs/file.h>
|
||||
#include <kernel/util/elf.h>
|
||||
#include <kernel/devices/earlyterm.h>
|
||||
#include <fcntl.h>
|
||||
#include <elf.h>
|
||||
|
||||
//
|
||||
// TODO: write doc
|
||||
|
|
|
@ -2,8 +2,10 @@
|
|||
#include <asm/unistd_32.h>
|
||||
#include <kernel/memory.h>
|
||||
#include <kernel/devices/earlyterm.h>
|
||||
#include <lib/string.h>
|
||||
#include <kernel/fs/vfs.h>
|
||||
#include <sys/signal.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/* 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 */
|
||||
|
|
|
@ -1,14 +1,29 @@
|
|||
#include <kernel/process.h>
|
||||
#include <kernel/scheduler.h>
|
||||
#include <kernel/devices/earlyterm.h>
|
||||
#include <kernel/util/atomic.h>
|
||||
#include <kernel/fs/vfs.h>
|
||||
#include <kernel/memory.h>
|
||||
|
||||
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();
|
||||
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
#include <kernel/scheduler.h>
|
||||
#include <kernel/process.h>
|
||||
#include <kernel/signal.h>
|
||||
|
||||
//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;
|
||||
|
|
|
@ -3,107 +3,48 @@
|
|||
#include <kernel/hardware/tmu.h>
|
||||
#include <kernel/devices/earlyterm.h>
|
||||
#include <kernel/drivers/timer.h>
|
||||
#include <kernel/drivers/cpg.h>
|
||||
|
||||
// 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);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
#include <kernel/process.h>
|
||||
#include <kernel/util/atomic.h>
|
||||
#include <lib/pthread.h>
|
||||
#include <lib/unistd.h>
|
||||
|
||||
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);
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
#include <display.h>
|
||||
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
#include <display.h>
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -4,25 +4,48 @@
|
|||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -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))
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue