1#include <mini-os/types.h> 2#include <mini-os/wait.h> 3#include <mini-os/mm.h> 4#include <mini-os/hypervisor.h> 5#include <mini-os/events.h> 6#include <mini-os/os.h> 7#include <mini-os/lib.h> 8#include <mini-os/xenbus.h> 9#include <xen/io/console.h> 10#include <xen/io/protocols.h> 11#include <xen/io/ring.h> 12#include <mini-os/gnttab.h> 13 14#include "console.h" 15 16#include <bmk-core/memalloc.h> 17#include <bmk-core/pgalloc.h> 18#include <bmk-core/printf.h> 19#include <bmk-core/string.h> 20 21void free_consfront(struct consfront_dev *dev) 22{ 23 char* err = NULL; 24 XenbusState state; 25 26 char path[bmk_strlen(dev->backend) + 1 + 5 + 1]; 27 char nodename[bmk_strlen(dev->nodename) + 1 + 5 + 1]; 28 29 bmk_snprintf(path, sizeof(path), "%s/state", dev->backend); 30 bmk_snprintf(nodename, sizeof(nodename), "%s/state", dev->nodename); 31 32 if ((err = xenbus_switch_state(XBT_NIL, nodename, XenbusStateClosing)) != NULL) { 33 minios_printk("free_consfront: error changing state to %d: %s\n", 34 XenbusStateClosing, err); 35 goto close; 36 } 37 state = xenbus_read_integer(path); 38 while (err == NULL && state < XenbusStateClosing) 39 err = xenbus_wait_for_state_change(path, &state, &dev->events); 40 if (err) bmk_memfree(err, BMK_MEMWHO_WIREDBMK); 41 42 if ((err = xenbus_switch_state(XBT_NIL, nodename, XenbusStateClosed)) != NULL) { 43 minios_printk("free_consfront: error changing state to %d: %s\n", 44 XenbusStateClosed, err); 45 goto close; 46 } 47 48close: 49 if (err) bmk_memfree(err, BMK_MEMWHO_WIREDBMK); 50 xenbus_unwatch_path_token(XBT_NIL, path, path); 51 52 minios_mask_evtchn(dev->evtchn); 53 minios_unbind_evtchn(dev->evtchn); 54 bmk_memfree(dev->backend, BMK_MEMWHO_WIREDBMK); 55 56 gnttab_end_access(dev->ring_ref); 57 58 bmk_pgfree_one(dev->ring); 59 bmk_memfree(dev, BMK_MEMWHO_WIREDBMK); 60} 61 62struct consfront_dev *init_consfront(char *_nodename) 63{ 64 xenbus_transaction_t xbt; 65 char* err; 66 char* message=NULL; 67 int retry=0; 68 char* msg = NULL; 69 char path[64]; 70 static int consfrontends = 3; 71 struct consfront_dev *dev; 72 int res; 73 74 dev = bmk_memcalloc(1, sizeof(*dev), BMK_MEMWHO_WIREDBMK); 75 76 if (!_nodename) 77 bmk_snprintf(dev->nodename, sizeof(dev->nodename), 78 "device/console/%d", consfrontends); 79 else 80 bmk_strncpy(dev->nodename, _nodename, sizeof(dev->nodename)-1); 81 consfrontends++; 82 83 minios_printk("******************* CONSFRONT for %s **********\n\n\n", dev->nodename); 84 85 bmk_snprintf(path, sizeof(path), "%s/backend-id", dev->nodename); 86 if ((res = xenbus_read_integer(path)) < 0) 87 return NULL; 88 else 89 dev->dom = res; 90 minios_evtchn_alloc_unbound(dev->dom, console_handle_input, dev, &dev->evtchn); 91 92 dev->ring = bmk_pgalloc_one(); 93 bmk_memset(dev->ring, 0, PAGE_SIZE); 94 dev->ring_ref = gnttab_grant_access(dev->dom, virt_to_mfn(dev->ring), 0); 95 96 xenbus_event_queue_init(&dev->events); 97 98again: 99 err = xenbus_transaction_start(&xbt); 100 if (err) { 101 minios_printk("starting transaction\n"); 102 bmk_memfree(err, BMK_MEMWHO_WIREDBMK); 103 } 104 105 err = xenbus_printf(xbt, dev->nodename, "ring-ref","%u", 106 dev->ring_ref); 107 if (err) { 108 message = "writing ring-ref"; 109 goto abort_transaction; 110 } 111 err = xenbus_printf(xbt, dev->nodename, 112 "port", "%u", dev->evtchn); 113 if (err) { 114 message = "writing event-channel"; 115 goto abort_transaction; 116 } 117 err = xenbus_printf(xbt, dev->nodename, 118 "protocol", "%s", XEN_IO_PROTO_ABI_NATIVE); 119 if (err) { 120 message = "writing protocol"; 121 goto abort_transaction; 122 } 123 124 err = xenbus_printf(xbt, dev->nodename, "type", "%s", "ioemu"); 125 if (err) { 126 message = "writing type"; 127 goto abort_transaction; 128 } 129 130 bmk_snprintf(path, sizeof(path), "%s/state", dev->nodename); 131 err = xenbus_switch_state(xbt, path, XenbusStateConnected); 132 if (err) { 133 message = "switching state"; 134 goto abort_transaction; 135 } 136 137 138 err = xenbus_transaction_end(xbt, 0, &retry); 139 if (err) bmk_memfree(err, BMK_MEMWHO_WIREDBMK); 140 if (retry) { 141 goto again; 142 minios_printk("completing transaction\n"); 143 } 144 145 goto done; 146 147abort_transaction: 148 bmk_memfree(err, BMK_MEMWHO_WIREDBMK); 149 err = xenbus_transaction_end(xbt, 1, &retry); 150 minios_printk("Abort transaction %s\n", message); 151 goto error; 152 153done: 154 155 bmk_snprintf(path, sizeof(path), "%s/backend", dev->nodename); 156 msg = xenbus_read(XBT_NIL, path, &dev->backend); 157 if (msg) { 158 minios_printk("Error %s when reading the backend path %s\n", msg, path); 159 goto error; 160 } 161 162 minios_printk("backend at %s\n", dev->backend); 163 164 { 165 XenbusState state; 166 char path[bmk_strlen(dev->backend) + 1 + 19 + 1]; 167 bmk_snprintf(path, sizeof(path), "%s/state", dev->backend); 168 169 xenbus_watch_path_token(XBT_NIL, path, path, &dev->events); 170 msg = NULL; 171 state = xenbus_read_integer(path); 172 while (msg == NULL && state < XenbusStateConnected) 173 msg = xenbus_wait_for_state_change(path, &state, &dev->events); 174 if (msg != NULL || state != XenbusStateConnected) { 175 minios_printk("backend not available, state=%d\n", state); 176 xenbus_unwatch_path_token(XBT_NIL, path, path); 177 goto error; 178 } 179 } 180 minios_unmask_evtchn(dev->evtchn); 181 182 minios_printk("**************************\n"); 183 184 return dev; 185 186error: 187 bmk_memfree(msg, BMK_MEMWHO_WIREDBMK); 188 bmk_memfree(err, BMK_MEMWHO_WIREDBMK); 189 free_consfront(dev); 190 return NULL; 191} 192 193void fini_console(struct consfront_dev *dev) 194{ 195 if (dev) free_consfront(dev); 196} 197 198