static int tpmfront_connect(struct tpmfront_dev* dev) { char* err; /* Create shared page */ dev->page = (vtpm_shared_page_t*) alloc_page(); if(dev->page == NULL) { TPMFRONT_ERR("Unable to allocate page for shared memory\n"); goto error; } memset(dev->page, 0, PAGE_SIZE); dev->ring_ref = gnttab_grant_access(dev->bedomid, virt_to_mfn(dev->page), 0); TPMFRONT_DEBUG("grant ref is %lu\n", (unsigned long) dev->ring_ref); /*Create event channel */ if(evtchn_alloc_unbound(dev->bedomid, tpmfront_handler, dev, &dev->evtchn)) { TPMFRONT_ERR("Unable to allocate event channel\n"); goto error_postmap; } unmask_evtchn(dev->evtchn); TPMFRONT_DEBUG("event channel is %lu\n", (unsigned long) dev->evtchn); /* Write the entries to xenstore */ if(publish_xenbus(dev)) { goto error_postevtchn; } /* Change state to connected */ dev->state = XenbusStateConnected; /* Tell the backend that we are ready */ if((err = xenbus_printf(XBT_NIL, dev->nodename, "state", "%u", dev->state))) { TPMFRONT_ERR("Unable to write to xenstore %s/state, value=%u", dev->nodename, XenbusStateConnected); free(err); goto error; } return 0; error_postevtchn: mask_evtchn(dev->evtchn); unbind_evtchn(dev->evtchn); error_postmap: gnttab_end_access(dev->ring_ref); free_page(dev->page); error: return -1; }
evtchn_port_or_error_t xc_evtchn_bind_unbound_port(int xce_handle, int domid) { int ret, i; evtchn_port_t port; assert(get_current() == main_thread); i = port_alloc(xce_handle); if (i == -1) return -1; printf("xc_evtchn_bind_unbound_port(%d)", domid); ret = evtchn_alloc_unbound(domid, evtchn_handler, (void*)(intptr_t)xce_handle, &port); printf(" = %d\n", ret); if (ret < 0) { errno = -ret; return -1; } files[xce_handle].evtchn.ports[i].bound = 1; files[xce_handle].evtchn.ports[i].port = port; unmask_evtchn(port); return port; }
struct kbdfront_dev *init_kbdfront(char *_nodename, int abs_pointer) { xenbus_transaction_t xbt; char* err; char* message=NULL; struct xenkbd_page *s; int retry=0; char* msg = NULL; char* nodename = _nodename ? _nodename : "device/vkbd/0"; struct kbdfront_dev *dev; char path[strlen(nodename) + strlen("/backend-id") + 1]; printk("******************* KBDFRONT for %s **********\n\n\n", nodename); dev = malloc(sizeof(*dev)); memset(dev, 0, sizeof(*dev)); dev->nodename = strdup(nodename); #ifdef HAVE_LIBC dev->fd = -1; #endif snprintf(path, sizeof(path), "%s/backend-id", nodename); dev->dom = xenbus_read_integer(path); evtchn_alloc_unbound(dev->dom, kbdfront_handler, dev, &dev->evtchn); dev->page = s = (struct xenkbd_page*) alloc_page(); memset(s,0,PAGE_SIZE); dev->events = NULL; s->in_cons = s->in_prod = 0; s->out_cons = s->out_prod = 0; again: err = xenbus_transaction_start(&xbt); if (err) { printk("starting transaction\n"); free(err); } err = xenbus_printf(xbt, nodename, "page-ref","%lu", virt_to_mfn(s)); if (err) { message = "writing page-ref"; goto abort_transaction; } err = xenbus_printf(xbt, nodename, "event-channel", "%u", dev->evtchn); if (err) { message = "writing event-channel"; goto abort_transaction; } if (abs_pointer) { err = xenbus_printf(xbt, nodename, "request-abs-pointer", "1"); if (err) { message = "writing event-channel"; goto abort_transaction; } } snprintf(path, sizeof(path), "%s/state", nodename); err = xenbus_switch_state(xbt, path, XenbusStateInitialised); if (err) { printk("error writing initialized: %s\n", err); free(err); } err = xenbus_transaction_end(xbt, 0, &retry); free(err); if (retry) { goto again; printk("completing transaction\n"); } goto done; abort_transaction: free(err); err = xenbus_transaction_end(xbt, 1, &retry); printk("Abort transaction %s\n", message); goto error; done: snprintf(path, sizeof(path), "%s/backend", nodename); msg = xenbus_read(XBT_NIL, path, &dev->backend); if (msg) { printk("Error %s when reading the backend path %s\n", msg, path); goto error; } printk("backend at %s\n", dev->backend); { XenbusState state; char path[strlen(dev->backend) + strlen("/state") + 1]; char frontpath[strlen(nodename) + strlen("/state") + 1]; snprintf(path, sizeof(path), "%s/state", dev->backend); xenbus_watch_path_token(XBT_NIL, path, path, &dev->events); err = NULL; state = xenbus_read_integer(path); while (err == NULL && state < XenbusStateConnected) err = xenbus_wait_for_state_change(path, &state, &dev->events); if (state != XenbusStateConnected) { printk("backend not available, state=%d\n", state); free(err); err = xenbus_unwatch_path_token(XBT_NIL, path, path); goto error; } printk("%s connected\n", dev->backend); snprintf(frontpath, sizeof(frontpath), "%s/state", nodename); if((err = xenbus_switch_state(XBT_NIL, frontpath, XenbusStateConnected)) != NULL) { printk("error switching state: %s\n", err); free(err); err = xenbus_unwatch_path_token(XBT_NIL, path, path); goto error; } } unmask_evtchn(dev->evtchn); printk("************************** KBDFRONT\n"); return dev; error: free(msg); free(err); free_kbdfront(dev); return NULL; }
struct fbfront_dev *init_fbfront(char *_nodename, unsigned long *mfns, int width, int height, int depth, int stride, int n) { xenbus_transaction_t xbt; char* err; char* message=NULL; struct xenfb_page *s; int retry=0; char* msg=NULL; int i, j; struct fbfront_dev *dev; int max_pd; unsigned long mapped; char* nodename = _nodename ? _nodename : "device/vfb/0"; char path[strlen(nodename) + 1 + 10 + 1]; printk("******************* FBFRONT for %s **********\n\n\n", nodename); dev = malloc(sizeof(*dev)); memset(dev, 0, sizeof(*dev)); dev->nodename = strdup(nodename); #ifdef HAVE_LIBC dev->fd = -1; #endif snprintf(path, sizeof(path), "%s/backend-id", nodename); dev->dom = xenbus_read_integer(path); evtchn_alloc_unbound(dev->dom, fbfront_handler, dev, &dev->evtchn); dev->page = s = (struct xenfb_page*) alloc_page(); memset(s,0,PAGE_SIZE); s->in_cons = s->in_prod = 0; s->out_cons = s->out_prod = 0; dev->width = s->width = width; dev->height = s->height = height; dev->depth = s->depth = depth; dev->stride = s->line_length = stride; dev->mem_length = s->mem_length = n * PAGE_SIZE; dev->offset = 0; dev->events = NULL; max_pd = sizeof(s->pd) / sizeof(s->pd[0]); mapped = 0; for (i = 0; mapped < n && i < max_pd; i++) { unsigned long *pd = (unsigned long *) alloc_page(); for (j = 0; mapped < n && j < PAGE_SIZE / sizeof(unsigned long); j++) pd[j] = mfns[mapped++]; for ( ; j < PAGE_SIZE / sizeof(unsigned long); j++) pd[j] = 0; s->pd[i] = virt_to_mfn(pd); } for ( ; i < max_pd; i++) s->pd[i] = 0; again: err = xenbus_transaction_start(&xbt); if (err) { printk("starting transaction\n"); free(err); } err = xenbus_printf(xbt, nodename, "page-ref","%lu", virt_to_mfn(s)); if (err) { message = "writing page-ref"; goto abort_transaction; } err = xenbus_printf(xbt, nodename, "event-channel", "%u", dev->evtchn); if (err) { message = "writing event-channel"; goto abort_transaction; } err = xenbus_printf(xbt, nodename, "protocol", "%s", XEN_IO_PROTO_ABI_NATIVE); if (err) { message = "writing event-channel"; goto abort_transaction; } err = xenbus_printf(xbt, nodename, "feature-update", "1"); if (err) { message = "writing event-channel"; goto abort_transaction; } snprintf(path, sizeof(path), "%s/state", nodename); err = xenbus_switch_state(xbt, path, XenbusStateInitialised); if (err) { message = "switching state"; goto abort_transaction; } err = xenbus_transaction_end(xbt, 0, &retry); free(err); if (retry) { goto again; printk("completing transaction\n"); } goto done; abort_transaction: free(err); err = xenbus_transaction_end(xbt, 1, &retry); printk("Abort transaction %s\n", message); goto error; done: snprintf(path, sizeof(path), "%s/backend", nodename); msg = xenbus_read(XBT_NIL, path, &dev->backend); if (msg) { printk("Error %s when reading the backend path %s\n", msg, path); goto error; } printk("backend at %s\n", dev->backend); { XenbusState state; char path[strlen(dev->backend) + strlen("/request-update") + 1]; char frontpath[strlen(nodename) + strlen("/state") + 1]; snprintf(path, sizeof(path), "%s/state", dev->backend); xenbus_watch_path_token(XBT_NIL, path, path, &dev->events); err = NULL; state = xenbus_read_integer(path); while (err == NULL && state < XenbusStateConnected) err = xenbus_wait_for_state_change(path, &state, &dev->events); if (state != XenbusStateConnected) { printk("backend not available, state=%d\n", state); free(err); err = xenbus_unwatch_path_token(XBT_NIL, path, path); goto error; } printk("%s connected\n", dev->backend); snprintf(path, sizeof(path), "%s/request-update", dev->backend); dev->request_update = xenbus_read_integer(path); snprintf(frontpath, sizeof(frontpath), "%s/state", nodename); if ((err = xenbus_switch_state(XBT_NIL, frontpath, XenbusStateConnected)) != NULL) { printk("error switching state: %s\n", err); free(err); err = xenbus_unwatch_path_token(XBT_NIL, path, path); goto error; } } unmask_evtchn(dev->evtchn); printk("************************** FBFRONT\n"); return dev; error: free(msg); free(err); free_fbfront(dev); return NULL; }
struct kbdfront_dev *init_kbdfront(char *_nodename, int abs_pointer) { xenbus_transaction_t xbt; char* err; char* message=NULL; struct xenkbd_page *s; int retry=0; char* msg; char* nodename = _nodename ? _nodename : "device/vkbd/0"; struct kbdfront_dev *dev; char path[strlen(nodename) + 1 + 10 + 1]; printk("******************* KBDFRONT for %s **********\n\n\n", nodename); dev = malloc(sizeof(*dev)); dev->nodename = strdup(nodename); #ifdef HAVE_LIBC dev->fd = -1; #endif snprintf(path, sizeof(path), "%s/backend-id", nodename); dev->dom = xenbus_read_integer(path); evtchn_alloc_unbound(dev->dom, kbdfront_handler, dev, &dev->evtchn); dev->page = s = (struct xenkbd_page*) alloc_page(); memset(s,0,PAGE_SIZE); dev->events = NULL; s->in_cons = s->in_prod = 0; s->out_cons = s->out_prod = 0; again: err = xenbus_transaction_start(&xbt); if (err) { printk("starting transaction\n"); } err = xenbus_printf(xbt, nodename, "page-ref","%u", virt_to_mfn(s)); if (err) { message = "writing page-ref"; goto abort_transaction; } err = xenbus_printf(xbt, nodename, "event-channel", "%u", dev->evtchn); if (err) { message = "writing event-channel"; goto abort_transaction; } if (abs_pointer) { err = xenbus_printf(xbt, nodename, "request-abs-pointer", "1"); if (err) { message = "writing event-channel"; goto abort_transaction; } } err = xenbus_printf(xbt, nodename, "state", "%u", 3); /* initialized */ if (err) printk("error writing initialized: %s\n", err); err = xenbus_transaction_end(xbt, 0, &retry); if (retry) { goto again; printk("completing transaction\n"); } goto done; abort_transaction: xenbus_transaction_end(xbt, 1, &retry); goto error; done: snprintf(path, sizeof(path), "%s/backend", nodename); msg = xenbus_read(XBT_NIL, path, &dev->backend); if (msg) { printk("Error %s when reading the backend path %s\n", msg, path); goto error; } printk("backend at %s\n", dev->backend); { char path[strlen(dev->backend) + 1 + 6 + 1]; snprintf(path, sizeof(path), "%s/state", dev->backend); xenbus_watch_path_token(XBT_NIL, path, path, &dev->events); xenbus_wait_for_value(path, "4", &dev->events); printk("%s connected\n", dev->backend); err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 4); /* connected */ } unmask_evtchn(dev->evtchn); printk("************************** KBDFRONT\n"); return dev; error: free_kbdfront(dev); return NULL; }
struct netfront_dev *init_netfront(char *_nodename, void (*thenetif_rx)(unsigned char* data, int len), unsigned char rawmac[6], char **ip) { xenbus_transaction_t xbt; char* err; char* message=NULL; struct netif_tx_sring *txs; struct netif_rx_sring *rxs; int retry=0; int i; char* msg; char nodename[256]; char path[256]; struct netfront_dev *dev; static int netfrontends = 0; if (!_nodename) snprintf(nodename, sizeof(nodename), "device/vif/%d", netfrontends); else strncpy(nodename, _nodename, strlen(nodename)); netfrontends++; if (!thenetif_rx) thenetif_rx = netif_rx; printk("************************ NETFRONT for %s **********\n\n\n", nodename); dev = malloc(sizeof(*dev)); memset(dev, 0, sizeof(*dev)); dev->nodename = strdup(nodename); #ifdef HAVE_LIBC dev->fd = -1; #endif printk("net TX ring size %d\n", NET_TX_RING_SIZE); printk("net RX ring size %d\n", NET_RX_RING_SIZE); init_SEMAPHORE(&dev->tx_sem, NET_TX_RING_SIZE); for(i=0;i<NET_TX_RING_SIZE;i++) { add_id_to_freelist(i,dev->tx_freelist); dev->tx_buffers[i].page = NULL; } for(i=0;i<NET_RX_RING_SIZE;i++) { /* TODO: that's a lot of memory */ dev->rx_buffers[i].page = (char*)alloc_page(); } snprintf(path, sizeof(path), "%s/backend-id", nodename); dev->dom = xenbus_read_integer(path); #ifdef HAVE_LIBC if (thenetif_rx == NETIF_SELECT_RX) evtchn_alloc_unbound(dev->dom, netfront_select_handler, dev, &dev->evtchn); else #endif evtchn_alloc_unbound(dev->dom, netfront_handler, dev, &dev->evtchn); txs = (struct netif_tx_sring *) alloc_page(); rxs = (struct netif_rx_sring *) alloc_page(); memset(txs,0,PAGE_SIZE); memset(rxs,0,PAGE_SIZE); SHARED_RING_INIT(txs); SHARED_RING_INIT(rxs); FRONT_RING_INIT(&dev->tx, txs, PAGE_SIZE); FRONT_RING_INIT(&dev->rx, rxs, PAGE_SIZE); dev->tx_ring_ref = gnttab_grant_access(dev->dom,virt_to_mfn(txs),0); dev->rx_ring_ref = gnttab_grant_access(dev->dom,virt_to_mfn(rxs),0); init_rx_buffers(dev); dev->netif_rx = thenetif_rx; dev->events = NULL; again: err = xenbus_transaction_start(&xbt); if (err) { printk("starting transaction\n"); } err = xenbus_printf(xbt, nodename, "tx-ring-ref","%u", dev->tx_ring_ref); if (err) { message = "writing tx ring-ref"; goto abort_transaction; } err = xenbus_printf(xbt, nodename, "rx-ring-ref","%u", dev->rx_ring_ref); if (err) { message = "writing rx ring-ref"; goto abort_transaction; } err = xenbus_printf(xbt, nodename, "event-channel", "%u", dev->evtchn); if (err) { message = "writing event-channel"; goto abort_transaction; } err = xenbus_printf(xbt, nodename, "request-rx-copy", "%u", 1); if (err) { message = "writing request-rx-copy"; goto abort_transaction; } snprintf(path, sizeof(path), "%s/state", nodename); err = xenbus_switch_state(xbt, path, XenbusStateConnected); if (err) { message = "switching state"; goto abort_transaction; } err = xenbus_transaction_end(xbt, 0, &retry); if (retry) { goto again; printk("completing transaction\n"); } goto done; abort_transaction: xenbus_transaction_end(xbt, 1, &retry); goto error; done: snprintf(path, sizeof(path), "%s/backend", nodename); msg = xenbus_read(XBT_NIL, path, &dev->backend); snprintf(path, sizeof(path), "%s/mac", nodename); msg = xenbus_read(XBT_NIL, path, &dev->mac); if ((dev->backend == NULL) || (dev->mac == NULL)) { printk("%s: backend/mac failed\n", __func__); goto error; } printk("backend at %s\n",dev->backend); printk("mac is %s\n",dev->mac); { XenbusState state; char path[strlen(dev->backend) + 1 + 5 + 1]; snprintf(path, sizeof(path), "%s/state", dev->backend); xenbus_watch_path_token(XBT_NIL, path, path, &dev->events); err = NULL; state = xenbus_read_integer(path); while (err == NULL && state < XenbusStateConnected) err = xenbus_wait_for_state_change(path, &state, &dev->events); if (state != XenbusStateConnected) { printk("backend not avalable, state=%d\n", state); xenbus_unwatch_path(XBT_NIL, path); goto error; } if (ip) { snprintf(path, sizeof(path), "%s/ip", dev->backend); xenbus_read(XBT_NIL, path, ip); } } printk("**************************\n"); unmask_evtchn(dev->evtchn); /* Special conversion specifier 'hh' needed for __ia64__. Without this mini-os panics with 'Unaligned reference'. */ if (rawmac) sscanf(dev->mac,"%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &rawmac[0], &rawmac[1], &rawmac[2], &rawmac[3], &rawmac[4], &rawmac[5]); return dev; error: free_netfront(dev); return NULL; }
struct consfront_dev *init_consfront(char *_nodename) { xenbus_transaction_t xbt; char* err; char* message=NULL; int retry=0; char* msg = NULL; char nodename[256]; char path[256]; static int consfrontends = 3; struct consfront_dev *dev; int res; if (!_nodename) snprintf(nodename, sizeof(nodename), "device/console/%d", consfrontends); else strncpy(nodename, _nodename, sizeof(nodename)); printk("******************* CONSFRONT for %s **********\n\n\n", nodename); consfrontends++; dev = malloc(sizeof(*dev)); memset(dev, 0, sizeof(*dev)); dev->nodename = strdup(nodename); #ifdef HAVE_LIBC dev->fd = -1; #endif snprintf(path, sizeof(path), "%s/backend-id", nodename); if ((res = xenbus_read_integer(path)) < 0) return NULL; else dev->dom = res; evtchn_alloc_unbound(dev->dom, handle_input, dev, &dev->evtchn); dev->ring = (struct xencons_interface *) alloc_page(); memset(dev->ring, 0, PAGE_SIZE); dev->ring_ref = gnttab_grant_access(dev->dom, virt_to_mfn(dev->ring), 0); dev->events = NULL; again: err = xenbus_transaction_start(&xbt); if (err) { printk("starting transaction\n"); free(err); } err = xenbus_printf(xbt, nodename, "ring-ref","%u", dev->ring_ref); if (err) { message = "writing ring-ref"; goto abort_transaction; } err = xenbus_printf(xbt, nodename, "port", "%u", dev->evtchn); if (err) { message = "writing event-channel"; goto abort_transaction; } err = xenbus_printf(xbt, nodename, "protocol", "%s", XEN_IO_PROTO_ABI_NATIVE); if (err) { message = "writing protocol"; goto abort_transaction; } err = xenbus_printf(xbt, nodename, "type", "%s", "ioemu"); if (err) { message = "writing type"; goto abort_transaction; } snprintf(path, sizeof(path), "%s/state", nodename); err = xenbus_switch_state(xbt, path, XenbusStateConnected); if (err) { message = "switching state"; goto abort_transaction; } err = xenbus_transaction_end(xbt, 0, &retry); if (err) free(err); if (retry) { goto again; printk("completing transaction\n"); } goto done; abort_transaction: free(err); err = xenbus_transaction_end(xbt, 1, &retry); goto error; done: snprintf(path, sizeof(path), "%s/backend", nodename); msg = xenbus_read(XBT_NIL, path, &dev->backend); if (msg) { printk("Error %s when reading the backend path %s\n", msg, path); goto error; } printk("backend at %s\n", dev->backend); { XenbusState state; char path[strlen(dev->backend) + 1 + 19 + 1]; snprintf(path, sizeof(path), "%s/state", dev->backend); xenbus_watch_path_token(XBT_NIL, path, path, &dev->events); msg = NULL; state = xenbus_read_integer(path); while (msg == NULL && state < XenbusStateConnected) msg = xenbus_wait_for_state_change(path, &state, &dev->events); if (msg != NULL || state != XenbusStateConnected) { printk("backend not available, state=%d\n", state); xenbus_unwatch_path_token(XBT_NIL, path, path); goto error; } } unmask_evtchn(dev->evtchn); printk("**************************\n"); return dev; error: free(msg); free(err); free_consfront(dev); return NULL; }
struct blkfront_dev *init_blkfront(char *_nodename, struct blkfront_info *info) { xenbus_transaction_t xbt; char* err; char* message=NULL; struct blkif_sring *s; int retry=0; char* msg = NULL; char* c; char* nodename = _nodename ? _nodename : "device/vbd/768"; struct blkfront_dev *dev; char path[strlen(nodename) + strlen("/backend-id") + 1]; printk("******************* BLKFRONT for %s **********\n\n\n", nodename); dev = malloc(sizeof(*dev)); memset(dev, 0, sizeof(*dev)); dev->nodename = strdup(nodename); #ifdef HAVE_LIBC dev->fd = -1; #endif snprintf(path, sizeof(path), "%s/backend-id", nodename); dev->dom = xenbus_read_integer(path); evtchn_alloc_unbound(dev->dom, blkfront_handler, dev, &dev->evtchn); s = (struct blkif_sring*) alloc_page(); memset(s,0,PAGE_SIZE); SHARED_RING_INIT(s); FRONT_RING_INIT(&dev->ring, s, PAGE_SIZE); dev->ring_ref = gnttab_grant_access(dev->dom,virt_to_mfn(s),0); dev->events = NULL; again: err = xenbus_transaction_start(&xbt); if (err) { printk("starting transaction\n"); free(err); } err = xenbus_printf(xbt, nodename, "ring-ref","%u", dev->ring_ref); if (err) { message = "writing ring-ref"; goto abort_transaction; } err = xenbus_printf(xbt, nodename, "event-channel", "%u", dev->evtchn); if (err) { message = "writing event-channel"; goto abort_transaction; } err = xenbus_printf(xbt, nodename, "protocol", "%s", XEN_IO_PROTO_ABI_NATIVE); if (err) { message = "writing protocol"; goto abort_transaction; } snprintf(path, sizeof(path), "%s/state", nodename); err = xenbus_switch_state(xbt, path, XenbusStateConnected); if (err) { message = "switching state"; goto abort_transaction; } err = xenbus_transaction_end(xbt, 0, &retry); free(err); if (retry) { goto again; printk("completing transaction\n"); } goto done; abort_transaction: free(err); err = xenbus_transaction_end(xbt, 1, &retry); printk("Abort transaction %s\n", message); goto error; done: snprintf(path, sizeof(path), "%s/backend", nodename); msg = xenbus_read(XBT_NIL, path, &dev->backend); if (msg) { printk("Error %s when reading the backend path %s\n", msg, path); goto error; } printk("backend at %s\n", dev->backend); dev->handle = strtoul(strrchr(nodename, '/')+1, NULL, 0); { XenbusState state; char path[strlen(dev->backend) + strlen("/feature-flush-cache") + 1]; snprintf(path, sizeof(path), "%s/mode", dev->backend); msg = xenbus_read(XBT_NIL, path, &c); if (msg) { printk("Error %s when reading the mode\n", msg); goto error; } if (*c == 'w') dev->info.mode = O_RDWR; else dev->info.mode = O_RDONLY; free(c); snprintf(path, sizeof(path), "%s/state", dev->backend); xenbus_watch_path_token(XBT_NIL, path, path, &dev->events); msg = NULL; state = xenbus_read_integer(path); while (msg == NULL && state < XenbusStateConnected) msg = xenbus_wait_for_state_change(path, &state, &dev->events); if (msg != NULL || state != XenbusStateConnected) { printk("backend not available, state=%d\n", state); xenbus_unwatch_path_token(XBT_NIL, path, path); goto error; } snprintf(path, sizeof(path), "%s/info", dev->backend); dev->info.info = xenbus_read_integer(path); snprintf(path, sizeof(path), "%s/sectors", dev->backend); // FIXME: read_integer returns an int, so disk size limited to 1TB for now dev->info.sectors = xenbus_read_integer(path); snprintf(path, sizeof(path), "%s/sector-size", dev->backend); dev->info.sector_size = xenbus_read_integer(path); snprintf(path, sizeof(path), "%s/feature-barrier", dev->backend); dev->info.barrier = xenbus_read_integer(path); snprintf(path, sizeof(path), "%s/feature-flush-cache", dev->backend); dev->info.flush = xenbus_read_integer(path); *info = dev->info; } unmask_evtchn(dev->evtchn); printk("%lu sectors of %u bytes\n", (unsigned long) dev->info.sectors, dev->info.sector_size); printk("**************************\n"); return dev; error: free(msg); free(err); free_blkfront(dev); return NULL; }
static struct netfront_dev *_init_netfront(struct netfront_dev *dev, unsigned char rawmac[6], char **ip) { xenbus_transaction_t xbt; char* err = NULL; const char* message=NULL; struct netif_tx_sring *txs; struct netif_rx_sring *rxs; int feature_split_evtchn; int retry=0; int i; char* msg = NULL; char path[256]; snprintf(path, sizeof(path), "%s/backend-id", dev->nodename); dev->dom = xenbus_read_integer(path); snprintf(path, sizeof(path), "%s/backend", dev->nodename); msg = xenbus_read(XBT_NIL, path, &dev->backend); snprintf(path, sizeof(path), "%s/mac", dev->nodename); msg = xenbus_read(XBT_NIL, path, &dev->mac); if ((dev->backend == NULL) || (dev->mac == NULL)) { printk("%s: backend/mac failed\n", __func__); goto error; } #ifdef CONFIG_NETMAP snprintf(path, sizeof(path), "%s/feature-netmap", dev->backend); dev->netmap = xenbus_read_integer(path) > 0 ? 1 : 0; if (dev->netmap) { dev->na = init_netfront_netmap(dev, dev->netif_rx); goto skip; } #endif /* Check feature-split-event-channels */ snprintf(path, sizeof(path), "%s/feature-split-event-channels", dev->backend); feature_split_evtchn = xenbus_read_integer(path) > 0 ? 1 : 0; #ifdef HAVE_LIBC /* Force the use of a single event channel */ if (dev->netif_rx == NETIF_SELECT_RX) feature_split_evtchn = 0; #endif printk("************************ NETFRONT for %s **********\n\n\n", dev->nodename); init_SEMAPHORE(&dev->tx_sem, NET_TX_RING_SIZE); for(i=0;i<NET_TX_RING_SIZE;i++) { add_id_to_freelist(i,dev->tx_freelist); #if defined CONFIG_NETFRONT_PERSISTENT_GRANTS || !defined CONFIG_NETFRONT_LWIP_ONLY dev->tx_buffers[i].page = (void*)alloc_page(); BUG_ON(dev->tx_buffers[i].page == NULL); #ifdef CONFIG_NETFRONT_PERSISTENT_GRANTS dev->tx_buffers[i].gref = gnttab_grant_access(dev->dom, virt_to_mfn(dev->tx_buffers[i].page), 0); BUG_ON(dev->tx_buffers[i].gref == GRANT_INVALID_REF); dprintk("tx[%d]: page = %p, gref=0x%x\n", i, dev->tx_buffers[i].page, dev->tx_buffers[i].gref); #endif #endif } #if defined CONFIG_NETFRONT_PERSISTENT_GRANTS || !defined CONFIG_NETFRONT_LWIP_ONLY printk("net TX ring size %d, %lu KB\n", NET_TX_RING_SIZE, (unsigned long)(NET_TX_RING_SIZE * PAGE_SIZE)/1024); #else printk("net TX ring size %d\n", NET_TX_RING_SIZE); #endif #ifdef CONFIG_NETFRONT_PERSISTENT_GRANTS for(i=0;i<NET_RX_RING_SIZE;i++) { /* TODO: that's a lot of memory */ dev->rx_buffers[i].page = (void*)alloc_page(); BUG_ON(dev->rx_buffers[i].page == NULL); dprintk("rx[%d]: page = %p\n", i, dev->rx_buffers[i].page); } printk("net RX ring size %d, %lu KB\n", NET_RX_RING_SIZE, (unsigned long)(NET_RX_RING_SIZE * PAGE_SIZE)/1024); #else for(i=0;i<NET_RX_RING_SIZE;i++) dev->rx_buffers[i] = NULL; for(i=0;i<NET_RX_BUFFERS;i++) { /* allocate rx buffer pool */ dev->rx_buffer_pool[i].page = (void*)alloc_page(); BUG_ON(dev->rx_buffer_pool[i].page == NULL); dprintk("rx[%d]: page = %p\n", i, dev->rx_buffer_pool[i].page); add_id_to_freelist(i,dev->rx_freelist); } dev->rx_avail = NET_RX_BUFFERS; printk("net RX ring size %d, %lu KB buffer space\n", NET_RX_RING_SIZE, (unsigned long)(NET_RX_BUFFERS * PAGE_SIZE)/1024); #endif if (feature_split_evtchn) { evtchn_alloc_unbound(dev->dom, netfront_tx_handler, dev, &dev->tx_evtchn); evtchn_alloc_unbound(dev->dom, netfront_rx_handler, dev, &dev->rx_evtchn); printk("split event channels enabled\n"); } else { #ifdef HAVE_LIBC if (dev->netif_rx == NETIF_SELECT_RX) evtchn_alloc_unbound(dev->dom, netfront_select_handler, dev, &dev->tx_evtchn); else #endif evtchn_alloc_unbound(dev->dom, netfront_handler, dev, &dev->tx_evtchn); dev->rx_evtchn = dev->tx_evtchn; } #ifdef CONFIG_NETFRONT_PERSISTENT_GRANTS printk("persistent grants enabled\n"); #endif txs = (struct netif_tx_sring *) alloc_page(); rxs = (struct netif_rx_sring *) alloc_page(); memset(txs,0,PAGE_SIZE); memset(rxs,0,PAGE_SIZE); SHARED_RING_INIT(txs); SHARED_RING_INIT(rxs); FRONT_RING_INIT(&dev->tx, txs, PAGE_SIZE); FRONT_RING_INIT(&dev->rx, rxs, PAGE_SIZE); dev->tx_ring_ref = gnttab_grant_access(dev->dom,virt_to_mfn(txs),0); BUG_ON(dev->tx_ring_ref == GRANT_INVALID_REF); dev->rx_ring_ref = gnttab_grant_access(dev->dom,virt_to_mfn(rxs),0); BUG_ON(dev->rx_ring_ref == GRANT_INVALID_REF); init_rx_buffers(dev); dev->events = NULL; again: err = xenbus_transaction_start(&xbt); if (err) { printk("starting transaction\n"); free(err); } err = xenbus_printf(xbt, dev->nodename, "tx-ring-ref","%u", dev->tx_ring_ref); if (err) { message = "writing tx ring-ref"; goto abort_transaction; } err = xenbus_printf(xbt, dev->nodename, "rx-ring-ref","%u", dev->rx_ring_ref); if (err) { message = "writing rx ring-ref"; goto abort_transaction; } if (feature_split_evtchn) { err = xenbus_printf(xbt, dev->nodename, "event-channel-tx", "%u", dev->tx_evtchn); if (err) { message = "writing event-channel-tx"; goto abort_transaction; } err = xenbus_printf(xbt, dev->nodename, "event-channel-rx", "%u", dev->rx_evtchn); if (err) { message = "writing event-channel-rx"; goto abort_transaction; } } else { err = xenbus_printf(xbt, dev->nodename, "event-channel", "%u", dev->tx_evtchn); if (err) { message = "writing event-channel"; goto abort_transaction; } } err = xenbus_printf(xbt, dev->nodename, "feature-rx-notify", "%u", 1); if (err) { message = "writing feature-rx-notify"; goto abort_transaction; } #ifdef CONFIG_NETFRONT_PERSISTENT_GRANTS err = xenbus_printf(xbt, dev->nodename, "feature-persistent", "%u", 1); if (err) { message = "writing feature-persistent"; goto abort_transaction; } #endif err = xenbus_printf(xbt, dev->nodename, "request-rx-copy", "%u", 1); if (err) { message = "writing request-rx-copy"; goto abort_transaction; } #if defined(CONFIG_NETFRONT_GSO) && defined(HAVE_LWIP) err = xenbus_printf(xbt, dev->nodename, "feature-sg", "%u", 1); if (err) { message = "writing feature-sg"; goto abort_transaction; } err = xenbus_printf(xbt, dev->nodename, "feature-gso-tcpv4", "%u", 1); if (err) { message = "writing feature-gso-tcpv4"; goto abort_transaction; } err = xenbus_printf(xbt, dev->nodename, "feature-gso-tcpv6", "%u", 1); if (err) { message = "writing feature-gso-tcpv6"; goto abort_transaction; } #endif snprintf(path, sizeof(path), "%s/state", dev->nodename); err = xenbus_switch_state(xbt, path, XenbusStateConnected); if (err) { message = "switching state"; goto abort_transaction; } err = xenbus_transaction_end(xbt, 0, &retry); free(err); if (retry) { goto again; printk("completing transaction\n"); } goto done; abort_transaction: free(err); err = xenbus_transaction_end(xbt, 1, &retry); printk("Abort transaction %s\n", message); goto error; done: snprintf(path, sizeof(path), "%s/mac", dev->nodename); msg = xenbus_read(XBT_NIL, path, &dev->mac); if (dev->mac == NULL) { printk("%s: backend/mac failed\n", __func__); goto error; } printk("backend at %s\n",dev->backend); printk("mac is %s\n",dev->mac); { XenbusState state; char path[strlen(dev->backend) + strlen("/state") + 1]; snprintf(path, sizeof(path), "%s/state", dev->backend); xenbus_watch_path_token(XBT_NIL, path, path, &dev->events); err = NULL; state = xenbus_read_integer(path); while (err == NULL && state < XenbusStateConnected) err = xenbus_wait_for_state_change(path, &state, &dev->events); if (state != XenbusStateConnected) { printk("backend not avalable, state=%d\n", state); xenbus_unwatch_path_token(XBT_NIL, path, path); goto error; } if (ip) { snprintf(path, sizeof(path), "%s/ip", dev->backend); xenbus_read(XBT_NIL, path, ip); } } printk("**************************\n"); unmask_evtchn(dev->tx_evtchn); if (feature_split_evtchn) unmask_evtchn(dev->rx_evtchn); #ifdef CONFIG_NETMAP skip: if (dev->netmap) connect_netfront(dev); #endif /* Special conversion specifier 'hh' needed for __ia64__. Without this mini-os panics with 'Unaligned reference'. */ if (rawmac) sscanf(dev->mac,"%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &rawmac[0], &rawmac[1], &rawmac[2], &rawmac[3], &rawmac[4], &rawmac[5]); #ifdef CONFIG_SELECT_POLL dev->fd = alloc_fd(FTYPE_TAP); files[dev->fd].read = 0; #endif #ifdef CONFIG_NETFRONT_STATS netfront_reset_txcounters(dev); #endif return dev; error: free(msg); free(err); free_netfront(dev); return NULL; }
struct pcifront_dev *init_pcifront(char *_nodename) { xenbus_transaction_t xbt; char* err; char* message=NULL; int retry=0; char* msg = NULL; char* nodename = _nodename ? _nodename : "device/pci/0"; int dom; struct pcifront_dev *dev; char path[strlen(nodename) + strlen("/backend-id") + 1]; if (!_nodename && pcidev) return pcidev; printk("******************* PCIFRONT for %s **********\n\n\n", nodename); snprintf(path, sizeof(path), "%s/backend-id", nodename); dom = xenbus_read_integer(path); if (dom == -1) { printk("no backend\n"); return NULL; } dev = malloc(sizeof(*dev)); memset(dev, 0, sizeof(*dev)); dev->nodename = strdup(nodename); dev->dom = dom; evtchn_alloc_unbound(dev->dom, pcifront_handler, dev, &dev->evtchn); dev->info = (struct xen_pci_sharedinfo*) alloc_page(); memset(dev->info,0,PAGE_SIZE); dev->info_ref = gnttab_grant_access(dev->dom,virt_to_mfn(dev->info),0); dev->events = NULL; again: err = xenbus_transaction_start(&xbt); if (err) { printk("starting transaction\n"); free(err); } err = xenbus_printf(xbt, nodename, "pci-op-ref","%u", dev->info_ref); if (err) { message = "writing pci-op-ref"; goto abort_transaction; } err = xenbus_printf(xbt, nodename, "event-channel", "%u", dev->evtchn); if (err) { message = "writing event-channel"; goto abort_transaction; } err = xenbus_printf(xbt, nodename, "magic", XEN_PCI_MAGIC); if (err) { message = "writing magic"; goto abort_transaction; } snprintf(path, sizeof(path), "%s/state", nodename); err = xenbus_switch_state(xbt, path, XenbusStateInitialised); if (err) { message = "switching state"; goto abort_transaction; } err = xenbus_transaction_end(xbt, 0, &retry); free(err); if (retry) { goto again; printk("completing transaction\n"); } goto done; abort_transaction: free(err); err = xenbus_transaction_end(xbt, 1, &retry); printk("Abort transaction %s\n", message); goto error; done: snprintf(path, sizeof(path), "%s/backend", nodename); msg = xenbus_read(XBT_NIL, path, &dev->backend); if (msg) { printk("Error %s when reading the backend path %s\n", msg, path); goto error; } printk("backend at %s\n", dev->backend); { char path[strlen(dev->backend) + strlen("/state") + 1]; char frontpath[strlen(nodename) + strlen("/state") + 1]; XenbusState state; snprintf(path, sizeof(path), "%s/state", dev->backend); xenbus_watch_path_token(XBT_NIL, path, path, &dev->events); err = NULL; state = xenbus_read_integer(path); while (err == NULL && state < XenbusStateConnected) err = xenbus_wait_for_state_change(path, &state, &dev->events); if (state != XenbusStateConnected) { printk("backend not avalable, state=%d\n", state); free(err); err = xenbus_unwatch_path_token(XBT_NIL, path, path); goto error; } snprintf(frontpath, sizeof(frontpath), "%s/state", nodename); if ((err = xenbus_switch_state(XBT_NIL, frontpath, XenbusStateConnected)) != NULL) { printk("error switching state %s\n", err); free(err); err = xenbus_unwatch_path_token(XBT_NIL, path, path); goto error; } } unmask_evtchn(dev->evtchn); printk("**************************\n"); if (!_nodename) pcidev = dev; return dev; error: free(msg); free(err); free_pcifront(dev); return NULL; }