Vhex-kernel/src/kernel/devices/tty/utils/screen/buffer.c

94 lines
2.3 KiB
C

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