#include /* Needed by all modules */ #include /* Needed for KERN_ALERT */ #include /* We are doing something with Xen */ #include #include "xen_buf.h" struct vdevbfrnt_info { struct xenbus_device *dev; unsigned int evtchn; unsigned int irq; grant_ref_t ring_ref; }; // The function is called on activation of the device static int xen_vdevb_fe_probe(struct xenbus_device *dev, const struct xenbus_device_id *id) { struct vdevbfrnt_info *info = NULL; pr_log("Probe called. We are good to go.\n"); pr_log(" %p %d\n", dev, dev->otherend_id); /* Allocating memory for private structure */ info = kzalloc(sizeof(struct vdevbfrnt_info), GFP_KERNEL); if (!info) { xenbus_dev_fatal(dev, -ENOMEM, "allocating frontend structure"); return -ENOMEM; } info->dev = dev; dev_set_drvdata(&dev->dev, info); // info->domid = dev->otherend_id; pr_log("info->domid: %d\n", dev->otherend_id); pr_log("devicetype: %s, nodename: %s, otherend: %s\n", dev->devicetype, dev->nodename, dev->otherend); // xenbus_switch_state(dev, XenbusStateInitialised); return 0; } static int xen_vdevb_fe_remove(struct xenbus_device *dev) { pr_log("\n"); return 0; } // This is where we set up xenstore files and event channels static int frontend_connect(struct xenbus_device *dev) { pr_log("Connecting the frontend now\n"); return 0; } // The function is called on a state change of the backend driver static void xen_vdevb_fe_backend_changed(struct xenbus_device *dev, enum xenbus_state backend_state) { struct vdevbfrnt_info *info = dev_get_drvdata(&dev->dev); //pr_log("info: %p\n", info); pr_log("dev->state: %s-%d, backend_state: %s-%d\n", xenbus_state_array[dev->state], dev->state, xenbus_state_array[backend_state], backend_state); switch (backend_state) { case XenbusStateInitialising: xenbus_switch_state(dev, XenbusStateInitialising); break; case XenbusStateInitialised: case XenbusStateReconfiguring: case XenbusStateReconfigured: case XenbusStateUnknown: break; case XenbusStateInitWait: if (dev->state != XenbusStateInitialising) break; if (frontend_connect(dev) != 0) break; xenbus_switch_state(dev, XenbusStateConnected); break; case XenbusStateConnected: pr_log("Other side says it is connected as well.\n"); break; case XenbusStateClosed: if (dev->state == XenbusStateClosed) break; /* Missed the backend's CLOSING state -- fallthrough */ case XenbusStateClosing: xenbus_frontend_closed(dev); } } // This defines the name of the devices the driver reacts to static const struct xenbus_device_id xen_vdevb_fe_ids[] = { { "vdevb" }, { "" } }; // We set up the callback functions static struct xenbus_driver xen_vdevb_fe_driver = { .ids = xen_vdevb_fe_ids, .probe = xen_vdevb_fe_probe, .remove = xen_vdevb_fe_remove, .otherend_changed = xen_vdevb_fe_backend_changed, }; // On loading this kernel module, we register as a frontend driver static int __init xen_vdevb_fe_init(void) { pr_log("xen_domain_type: %d, xen_domain: %d\n", xen_domain_type,xen_domain()); pr_log("Hello World!\n"); return xenbus_register_frontend(&xen_vdevb_fe_driver); } module_init(xen_vdevb_fe_init); // ...and on unload we unregister static void __exit xen_vdevb_fe_exit(void) { xenbus_unregister_driver(&xen_vdevb_fe_driver); pr_log( "Goodbye world.\n"); } module_exit(xen_vdevb_fe_exit); MODULE_LICENSE("GPL"); MODULE_ALIAS("xen-clk: vdevb");