1 /* Copyright (c) 2012 The Regents of the University of California
2 * Barret Rhoden <brho@cs.berkeley.edu>
3 * See LICENSE for details.
5 * Console (Keyboard/serial/whatever) related functions. */
8 #include <ros/ring_buffer.h>
12 struct kb_buffer cons_buf;
14 void kb_buf_init(struct kb_buffer *kb)
18 spinlock_init(&kb->buf_lock);
19 sem_init(&kb->buf_sem, 0);
20 /* no need to memset the buffer - we only read something that is written */
23 /* Producers don't block - their input is dropped. Should be rare for now; if
24 * it happens, it's probably a bug. */
25 void kb_add_to_buf(struct kb_buffer *kb, char c)
27 /* make sure we're a power of 2 */
28 static_assert(KB_BUF_SIZE == __RD32(KB_BUF_SIZE));
29 bool was_empty = FALSE;
30 spin_lock(&kb->buf_lock);
31 if (!__ring_full(KB_BUF_SIZE, kb->prod_idx, kb->cons_idx)) {
32 if (__ring_empty(kb->prod_idx, kb->cons_idx))
34 kb->buf[kb->prod_idx % KB_BUF_SIZE] = c; // compiler should shift
37 /* else drop the char */
38 printk("[kernel] KB buffer overflowed %c\n", c);
40 spin_unlock(&kb->buf_lock);
41 /* up the sem when it goes from empty->non_empty. rule for syncing with
42 * blockers: if there are any items in the buffer, either the sem is upped,
43 * or there is an active consumer. consumers immediately down (to become an
44 * active consumer). */
47 /* also note that multiple readers on the console/serial are going to fight
48 * for input and it is going to get interleaved - broader issue */
51 /* Will read cnt chars from the KB buf into dst. Will block until complete. */
52 void kb_get_from_buf(struct kb_buffer *kb, char *dst, size_t cnt)
54 unsigned int dst_idx = 0; /* aka, amt copied so far */
55 bool need_an_up = FALSE;
57 /* so long as we still need items, we'll sleep til there is activity, then
58 * grab everything we can til the kb buf is empty (or we're done). If we
59 * didn't empty the buf, we'll need to up the sem later. */
60 while (dst_idx < cnt) {
61 /* this will return immediately if some data is already there, o/w we
62 * block til there is some activity */
63 sem_down(&kb->buf_sem);
64 spin_lock(&kb->buf_lock);
65 /* under the current scheme, we should only have one active consumer at
66 * a time, so if we woke up, the ring must not be empty. */
67 assert(!__ring_empty(kb->prod_idx, kb->cons_idx));
68 while (!__ring_empty(kb->prod_idx, kb->cons_idx)) {
70 /* we're done, and it's not empty yet */
74 dst[dst_idx] = kb->buf[kb->cons_idx % KB_BUF_SIZE];
78 spin_unlock(&kb->buf_lock);
80 /* Remember: if the buf is non empty, there is either an active consumer or
81 * the sem is upped. */
86 /* Kernel messages associated with the console. Arch-specific interrupt
87 * handlers need to call these. For add char, a0 = &cons_buf and a1 = the char
88 * you read. Call __run_mon on your 'magic' input. */
89 void __cons_add_char(uint32_t srcid, long a0, long a1, long a2)
91 kb_add_to_buf((struct kb_buffer*)a0, (char)a1);
94 void __run_mon(uint32_t srcid, long a0, long a1, long a2)