mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 10:40:03 +01:00
stubdom: Add console reading support
Signed-off-by: Samuel Thibault <samuel.thibault@eu.citrix.com>
This commit is contained in:
1 parent
9efd150651
commit
e49b738ccf
4 files changed
+77
-8
No files matched your search
@@ -49,17 +49,13 @@
|
||||
of standard dom0 handled console */
|
||||
#define USE_XEN_CONSOLE
|
||||
|
||||
/* Low level functions defined in xencons_ring.c */
|
||||
extern int xencons_ring_init(void);
|
||||
extern int xencons_ring_send(const char *data, unsigned len);
|
||||
extern int xencons_ring_send_no_notify(const char *data, unsigned len);
|
||||
|
||||
|
||||
/* If console not initialised the printk will be sent to xen serial line
|
||||
NOTE: you need to enable verbose in xen/Rules.mk for it to work. */
|
||||
static int console_initialised = 0;
|
||||
|
||||
|
||||
#ifndef HAVE_LIBC
|
||||
void xencons_rx(char *buf, unsigned len, struct pt_regs *regs)
|
||||
{
|
||||
if(len > 0)
|
||||
@@ -77,6 +73,7 @@ void xencons_tx(void)
|
||||
{
|
||||
/* Do nothing, handled by _rx */
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void console_print(char *data, int length)
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <xenbus.h>
|
||||
#include <xen/io/console.h>
|
||||
|
||||
DECLARE_WAIT_QUEUE_HEAD(console_queue);
|
||||
|
||||
static inline struct xencons_interface *xencons_interface(void)
|
||||
{
|
||||
@@ -52,6 +53,9 @@ int xencons_ring_send(const char *data, unsigned len)
|
||||
|
||||
static void handle_input(evtchn_port_t port, struct pt_regs *regs, void *ign)
|
||||
{
|
||||
#ifdef HAVE_LIBC
|
||||
wake_up(&console_queue);
|
||||
#else
|
||||
struct xencons_interface *intf = xencons_interface();
|
||||
XENCONS_RING_IDX cons, prod;
|
||||
|
||||
@@ -71,8 +75,48 @@ static void handle_input(evtchn_port_t port, struct pt_regs *regs, void *ign)
|
||||
notify_daemon();
|
||||
|
||||
xencons_tx();
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef HAVE_LIBC
|
||||
int xencons_ring_avail(void)
|
||||
{
|
||||
struct xencons_interface *intf = xencons_interface();
|
||||
XENCONS_RING_IDX cons, prod;
|
||||
|
||||
cons = intf->in_cons;
|
||||
prod = intf->in_prod;
|
||||
mb();
|
||||
BUG_ON((prod - cons) > sizeof(intf->in));
|
||||
|
||||
return prod - cons;
|
||||
}
|
||||
|
||||
int xencons_ring_recv(char *data, unsigned len)
|
||||
{
|
||||
struct xencons_interface *intf = xencons_interface();
|
||||
XENCONS_RING_IDX cons, prod;
|
||||
unsigned filled = 0;
|
||||
|
||||
cons = intf->in_cons;
|
||||
prod = intf->in_prod;
|
||||
mb();
|
||||
BUG_ON((prod - cons) > sizeof(intf->in));
|
||||
|
||||
while (filled < len && cons + filled != prod) {
|
||||
data[filled] = *(intf->in + MASK_XENCONS_IDX(cons + filled, intf->in));
|
||||
filled++;
|
||||
}
|
||||
|
||||
mb();
|
||||
intf->in_cons = cons + filled;
|
||||
|
||||
notify_daemon();
|
||||
|
||||
return filled;
|
||||
}
|
||||
#endif
|
||||
|
||||
int xencons_ring_init(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
@@ -52,4 +52,13 @@ void xencons_tx(void);
|
||||
void init_console(void);
|
||||
void console_print(char *data, int length);
|
||||
|
||||
/* Low level functions defined in xencons_ring.c */
|
||||
extern struct wait_queue_head console_queue;
|
||||
int xencons_ring_init(void);
|
||||
int xencons_ring_send(const char *data, unsigned len);
|
||||
int xencons_ring_send_no_notify(const char *data, unsigned len);
|
||||
int xencons_ring_avail(void);
|
||||
int xencons_ring_recv(char *data, unsigned len);
|
||||
|
||||
|
||||
#endif /* _LIB_CONSOLE_H_ */
|
||||
@@ -213,8 +213,19 @@ int isatty(int fd)
|
||||
int read(int fd, void *buf, size_t nbytes)
|
||||
{
|
||||
switch (files[fd].type) {
|
||||
case FTYPE_CONSOLE:
|
||||
return 0;
|
||||
case FTYPE_CONSOLE: {
|
||||
int ret;
|
||||
DEFINE_WAIT(w);
|
||||
while(1) {
|
||||
add_waiter(w, console_queue);
|
||||
ret = xencons_ring_recv(buf, nbytes);
|
||||
if (ret)
|
||||
break;
|
||||
schedule();
|
||||
}
|
||||
remove_waiter(w);
|
||||
return ret;
|
||||
}
|
||||
case FTYPE_FILE: {
|
||||
ssize_t ret;
|
||||
if (nbytes > PAGE_SIZE)
|
||||
@@ -707,7 +718,12 @@ static int select_poll(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exce
|
||||
FD_CLR(i, exceptfds);
|
||||
break;
|
||||
case FTYPE_CONSOLE:
|
||||
FD_CLR(i, readfds);
|
||||
if (FD_ISSET(i, writefds)) {
|
||||
if (xencons_ring_avail())
|
||||
n++;
|
||||
else
|
||||
FD_CLR(i, readfds);
|
||||
}
|
||||
if (FD_ISSET(i, writefds))
|
||||
n++;
|
||||
FD_CLR(i, exceptfds);
|
||||
@@ -809,6 +825,7 @@ int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
|
||||
DEFINE_WAIT(w3);
|
||||
DEFINE_WAIT(w4);
|
||||
DEFINE_WAIT(w5);
|
||||
DEFINE_WAIT(w6);
|
||||
|
||||
assert(thread == main_thread);
|
||||
|
||||
@@ -830,6 +847,7 @@ int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
|
||||
add_waiter(w3, blkfront_queue);
|
||||
add_waiter(w4, xenbus_watch_queue);
|
||||
add_waiter(w5, kbdfront_queue);
|
||||
add_waiter(w6, console_queue);
|
||||
|
||||
if (readfds)
|
||||
myread = *readfds;
|
||||
@@ -916,6 +934,7 @@ out:
|
||||
remove_waiter(w3);
|
||||
remove_waiter(w4);
|
||||
remove_waiter(w5);
|
||||
remove_waiter(w6);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||