]> xenbits.xensource.com Git - people/liuw/libxenctrl-split/mini-os.git/commitdiff
stubdom: Add console reading support
authorKeir Fraser <keir.fraser@citrix.com>
Tue, 3 Jun 2008 08:32:50 +0000 (09:32 +0100)
committerKeir Fraser <keir.fraser@citrix.com>
Tue, 3 Jun 2008 08:32:50 +0000 (09:32 +0100)
Signed-off-by: Samuel Thibault <samuel.thibault@eu.citrix.com>
console/console.c
console/xencons_ring.c
include/console.h
lib/sys.c

index 29fdd99f3b0baf2fda801e311506737f19b14e72..94379ddb335af4de14629895f3a80b73d05914f7 100644 (file)
    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)
index 583e4bcb920b6fba6082a913ed946843c20c3d7e..251a4f95f19fe5b26d5703238cae76c79ef596ce 100644 (file)
@@ -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;
index 9ace8dfcb11f00602791f97d6f081ec16eadf9b1..ac9cb53e7b6a88650a9f2a70cdb228616a8ac153 100644 (file)
@@ -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_ */
index 004e300728b13802e43b7ecb7fa150138c8c9201..7b171b66d59ab4e45e1d9f1c1a192c4e2d8478a5 100644 (file)
--- a/lib/sys.c
+++ b/lib/sys.c
@@ -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;
 }