110,20 → 110,41 |
*/ |
SPINLOCK_INITIALIZE(sgcn_output_lock); |
|
/* |
* Ensures that reading from the buffer and consequent update of the read |
* pointer are together one atomic operation. |
*/ |
SPINLOCK_INITIALIZE(sgcn_input_lock); |
|
static void sgcn_putchar(struct chardev * cd, const char c); |
|
/** character device operations */ |
static chardev_operations_t sgcn_ops = { |
.suspend = NULL, |
.resume = NULL, |
/* functions referenced from definitions of I/O operations structures */ |
static void sgcn_noop(chardev_t *); |
static void sgcn_putchar(chardev_t *, const char); |
static char sgcn_key_read(chardev_t *); |
|
/** character device output operations */ |
static chardev_operations_t sgcn_output_ops = { |
.suspend = sgcn_noop, |
.resume = sgcn_noop, |
.write = sgcn_putchar, |
.read = NULL |
}; |
|
/** SGCN character device */ |
/** character device input operations */ |
static chardev_operations_t sgcn_input_ops = { |
.suspend = sgcn_noop, |
.resume = sgcn_noop, |
.read = sgcn_key_read |
}; |
|
|
/** SGCN character output device */ |
chardev_t sgcn_stdout; |
|
/** SGCN character input device */ |
chardev_t sgcn_input; |
|
|
/** |
* Initializes the starting address of SRAM. |
* |
180,6 → 201,13 |
} |
|
/** |
* Default suspend/resume operation for the input device. |
*/ |
static void sgcn_noop(chardev_t *d) |
{ |
} |
|
/** |
* Writes a single character to the SGCN (circular) output buffer |
* and updates the output write pointer so that SGCN gets to know |
* that the character has been written. |
235,6 → 263,47 |
} |
|
/** |
* Called when actively reading the character. Not implemented yet. |
*/ |
static char sgcn_key_read(chardev_t *d) |
{ |
return (char) 0; |
} |
|
/** |
* Function regularly called by the keyboard polling thread. Finds out whether |
* there are some unread characters in the input queue. If so, it picks them up |
* and sends them to the upper layers of HelenOS. |
*/ |
void sgcn_poll(void) |
{ |
spinlock_lock(&sgcn_input_lock); |
|
char c; |
uint32_t begin = SGCN_BUFFER_HEADER->in_begin; |
uint32_t end = SGCN_BUFFER_HEADER->in_end; |
uint32_t size = end - begin; |
|
/* we need pointers to volatile variables */ |
volatile char *buf_ptr = (volatile char *) |
SGCN_BUFFER(char, SGCN_BUFFER_HEADER->in_rdptr); |
volatile uint32_t *in_wrptr_ptr = &(SGCN_BUFFER_HEADER->in_wrptr); |
volatile uint32_t *in_rdptr_ptr = &(SGCN_BUFFER_HEADER->in_rdptr); |
|
while (*in_rdptr_ptr != *in_wrptr_ptr) { |
c = *buf_ptr; |
*in_rdptr_ptr = (((*in_rdptr_ptr) - begin + 1) % size) + begin; |
buf_ptr = (volatile char *) |
SGCN_BUFFER(char, SGCN_BUFFER_HEADER->in_rdptr); |
chardev_push_character(&sgcn_input, c); |
if (c == '\r') |
chardev_push_character(&sgcn_input, '\n'); |
} |
|
spinlock_unlock(&sgcn_input_lock); |
} |
|
/** |
* A public function which initializes I/O from/to Serengeti console |
* and sets it as a default input/output. |
*/ |
242,11 → 311,11 |
{ |
sgcn_buffer_begin_init(); |
|
chardev_initialize("sgcn_output", &sgcn_stdout, &sgcn_ops); |
chardev_initialize("sgcn_output", &sgcn_stdout, &sgcn_output_ops); |
stdout = &sgcn_stdout; |
|
|
printf("SGCN buffer begin = %d, in read ptr = %" PRIu32 ".", sgcn_buffer_begin, SGCN_BUFFER_HEADER->in_wrptr); |
chardev_initialize("sgcn_input", &sgcn_input, &sgcn_input_ops); |
stdin = &sgcn_input; |
} |
|
/** @} |