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