N-sim
Emulation and simulation of
Wireless Sensor Networks



   Home


   Project Page


   Download


   CVS



   Installation


   Configuration


   Plug-ins




 Hosted by
SourceForge.net Logo

/home/brennan/n-sim/OrbisQuartus/server/xen/backend/sdev_bus.c

Go to the documentation of this file.
00001 
00012 /*  
00013  * Copyright (C) 2005 Rusty Russell <rusty@rustcorp.com.au>
00014  * Copyright (C) 2005 XenSource Ltd
00015  *
00016  * Copyright 2006. Los Alamos National Security, LLC. This material
00017  * was produced under U.S. Government contract DE-AC52-06NA25396 for
00018  * Los Alamos National Laboratory (LANL), which is operated by Los
00019  * Alamos National Security, LLC, for the Department of Energy. The
00020  * U.S. Government has rights to use, reproduce, and distribute this
00021  * software. NEITHER THE GOVERNMENT NOR LOS ALAMOS NATIONAL SECURITY,
00022  * LLC, MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR ASSUMES ANY LEGAL
00023  * LIABILITY FOR THE USE OF THIS SOFTWARE. If software is modified to
00024  * produce derivative works, such modified software should be clearly
00025  * marked, so as not to confuse it with the version available from LANL.
00026  * Additionally, this program is free software; you can redistribute it
00027  * and/or modify it under the terms of the GNU General Public License as
00028  * published by the Free Software Foundation; either version 2 of the
00029  * License, or (at your option) any later version. Accordingly, this
00030  * program is distributed in the hope it will be useful, but WITHOUT ANY
00031  * WARRANTY; without even the implied warranty of MERCHANTABILITY or
00032  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
00033  * for more details.
00034  ******************************
00035  *
00036  * This program is free software; you can redistribute it and/or
00037  * modify it under the terms of the GNU General Public License version 2
00038  * as published by the Free Software Foundation; or, when distributed
00039  * separately from the Linux kernel or incorporated into other
00040  * software packages, subject to the following license:
00041  * 
00042  * Permission is hereby granted, free of charge, to any person obtaining a copy
00043  * of this source file (the "Software"), to deal in the Software without
00044  * restriction, including without limitation the rights to use, copy, modify,
00045  * merge, publish, distribute, sublicense, and/or sell copies of the Software,
00046  * and to permit persons to whom the Software is furnished to do so, subject to
00047  * the following conditions:
00048  * 
00049  * The above copyright notice and this permission notice shall be included in
00050  * all copies or substantial portions of the Software.
00051  * 
00052  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00053  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00054  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00055  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00056  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
00057  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
00058  * IN THE SOFTWARE.
00059  *
00060  * You should have received a copy of the GNU General Public License
00061  * along with this program; if not, write to the Free Software
00062  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00063  */
00064 
00065 
00066 
00067 #include <stdarg.h>
00068 #include <linux/module.h>
00069 #include <xen/xenbus.h>
00070 #include <xen/net_driver_util.h>
00071 #include "sdev.h"
00072 
00073 
00074 
00075 struct backend_info
00076 {
00077         struct xenbus_device *dev;
00078         sdev_t *sdev;
00079         struct xenbus_watch backend_watch;
00080         XenbusState frontend_state;
00081 };
00082 
00083 
00084 static int connect_rings(struct backend_info *);
00085 static void connect(struct backend_info *);
00086 static void maybe_connect(struct backend_info *);
00087 static void backend_changed(struct xenbus_watch *, const char **,
00088                             unsigned int);
00089 
00090 
00091 static int sdevback_remove(struct xenbus_device *dev)
00092 {
00093         struct backend_info *be = dev->data;
00094 
00095         if (be->backend_watch.node) {
00096                 unregister_xenbus_watch(&be->backend_watch);
00097                 kfree(be->backend_watch.node);
00098                 be->backend_watch.node = NULL;
00099         }
00100         if (be->sdev) {
00101                 sdev_disconnect(be->sdev);
00102                 be->sdev = NULL;
00103         }
00104         kfree(be);
00105         dev->data = NULL;
00106         return 0;
00107 }
00108 
00109 
00115 static int sdevback_probe(struct xenbus_device *dev,
00116                          const struct xenbus_device_id *id)
00117 {
00118         int err;
00119         struct backend_info *be = kzalloc(sizeof(struct backend_info), 
00120                                           GFP_KERNEL);
00121 
00122         if (!be) {
00123                 xenbus_dev_fatal(dev, -ENOMEM,
00124                                  "allocating backend structure");
00125                 return -ENOMEM;
00126         }
00127 
00128         be->dev = dev;
00129         dev->data = be;
00130 
00131         err = xenbus_watch_path2(dev, dev->nodename, "handle",
00132                                  &be->backend_watch, backend_changed);
00133         if (err)
00134                 goto fail;
00135 
00136         err = xenbus_switch_state(dev, XenbusStateInitWait);
00137         if (err) {
00138                 goto fail;
00139         }
00140 
00141         return 0;
00142 
00143 fail:
00144         DPRINTK("failed");
00145         sdevback_remove(dev);
00146         return err;
00147 }
00148 
00149 
00155 static int sdevback_uevent(struct xenbus_device *xdev, char **envp,
00156                             int num_envp, char *buffer, int buffer_size)
00157 {
00158         struct backend_info *be = xdev->data;
00159         sdev_t *sdev = be->sdev;
00160         int i = 0, length = 0;
00161         char *val;
00162 
00163         DPRINTK("sdevback_uevent");
00164 
00165         val = xenbus_read(XBT_NULL, xdev->nodename, "script", NULL);
00166         if (IS_ERR(val)) {
00167                 int err = PTR_ERR(val);
00168                 xenbus_dev_fatal(xdev, err, "reading script");
00169                 return err;
00170         }
00171         else {
00172                 add_uevent_var(envp, num_envp, &i, buffer, buffer_size,
00173                                &length, "script=%s", val);
00174                 kfree(val);
00175         }
00176 
00177         add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length,
00178                        "vwif=%s", sdev->dev->name);
00179 
00180         envp[i] = NULL;
00181 
00182         return 0;
00183 }
00184 
00185 
00190 static void backend_changed(struct xenbus_watch *watch,
00191                             const char **vec, unsigned int len)
00192 {
00193         int err;
00194         long handle;
00195         struct backend_info *be
00196                 = container_of(watch, struct backend_info, backend_watch);
00197         struct xenbus_device *dev = be->dev;
00198 
00199         DPRINTK("");
00200 
00201         err = xenbus_scanf(XBT_NULL, dev->nodename, "handle", "%li", &handle);
00202         if (XENBUS_EXIST_ERR(err)) {
00203                 /* Since this watch will fire once immediately after it is
00204                    registered, we expect this.  Ignore it, and wait for the
00205                    hotplug scripts. */
00206                 return;
00207         }
00208         if (err != 1) {
00209                 xenbus_dev_fatal(dev, err, "reading handle");
00210                 return;
00211         }
00212 
00213         if (be->sdev == NULL) {
00214                 u8 be_mac[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 };
00215 
00216                 be->sdev = alloc_sdev(dev->otherend_id, handle, be_mac);
00217                 if (IS_ERR(be->sdev)) {
00218                         err = PTR_ERR(be->sdev);
00219                         be->sdev = NULL;
00220                         xenbus_dev_fatal(dev, err, "creating interface");
00221                         return;
00222                 }
00223 
00224                 kobject_uevent(&dev->dev.kobj, KOBJ_ONLINE);
00225                 maybe_connect(be);
00226         }
00227 }
00228 
00229 
00233 static void frontend_changed(struct xenbus_device *dev,
00234                              XenbusState frontend_state)
00235 {
00236         struct backend_info *be = dev->data;
00237 
00238         DPRINTK("");
00239 
00240         be->frontend_state = frontend_state;
00241 
00242         switch (frontend_state) {
00243         case XenbusStateInitialising:
00244         case XenbusStateInitialised:
00245                 break;
00246 
00247         case XenbusStateConnected:
00248                 maybe_connect(be);
00249                 break;
00250 
00251         case XenbusStateClosing:
00252                 xenbus_switch_state(dev, XenbusStateClosing);
00253                 break;
00254 
00255         case XenbusStateClosed:
00256                 if (be->sdev != NULL)
00257                         kobject_uevent(&dev->dev.kobj, KOBJ_OFFLINE);
00258                 device_unregister(&dev->dev);
00259                 break;
00260 
00261         case XenbusStateUnknown:
00262         case XenbusStateInitWait:
00263         default:
00264                 xenbus_dev_fatal(dev, -EINVAL, "saw state %d at frontend",
00265                                  frontend_state);
00266                 break;
00267         }
00268 }
00269 
00270 
00271 /* ** Connection ** */
00272 
00273 
00274 static void maybe_connect(struct backend_info *be)
00275 {
00276         if (be->sdev != NULL && be->frontend_state == XenbusStateConnected) {
00277                 connect(be);
00278         }
00279 }
00280 
00281 
00282 static void connect(struct backend_info *be)
00283 {
00284         int err;
00285         struct xenbus_device *dev = be->dev;
00286 
00287         err = connect_rings(be);
00288         if (err)
00289                 return;
00290 
00291         err = xen_net_read_mac(dev, be->sdev->fe_dev_addr);
00292         if (err) {
00293                 xenbus_dev_fatal(dev, err, "parsing %s/mac", dev->nodename);
00294                 return;
00295         }
00296 
00297         xenbus_switch_state(dev, XenbusStateConnected);
00298 }
00299 
00300 
00301 static int connect_rings(struct backend_info *be)
00302 {
00303         struct xenbus_device *dev = be->dev;
00304         unsigned long tx_ring_ref, rx_ring_ref;
00305         unsigned int evtchn;
00306         int err;
00307 
00308         DPRINTK("");
00309 
00310         err = xenbus_gather(XBT_NULL, dev->otherend,
00311                             "tx-ring-ref", "%lu", &tx_ring_ref,
00312                             "rx-ring-ref", "%lu", &rx_ring_ref,
00313                             "event-channel", "%u", &evtchn, NULL);
00314         if (err) {
00315                 xenbus_dev_fatal(dev, err,
00316                                  "reading %s/ring-ref and event-channel",
00317                                  dev->otherend);
00318                 return err;
00319         }
00320 
00321         /* Map the shared frame, irq etc. */
00322         err = sdev_map(be->sdev, tx_ring_ref, rx_ring_ref, evtchn);
00323         if (err) {
00324                 xenbus_dev_fatal(dev, err,
00325                                  "mapping shared-frames %lu/%lu port %u",
00326                                  tx_ring_ref, rx_ring_ref, evtchn);
00327                 return err;
00328         }
00329         return 0;
00330 }
00331 
00332 
00333 /* ** Driver Registration ** */
00334 
00335 
00336 static struct xenbus_device_id sdevback_ids[] = {
00337         { "vwif" },
00338         { "" }
00339 };
00340 
00341 
00342 static struct xenbus_driver sdevback = {
00343         .name = "vwif",
00344         .owner = THIS_MODULE,
00345         .ids = sdevback_ids,
00346         .probe = sdevback_probe,
00347         .remove = sdevback_remove,
00348         .uevent = sdevback_uevent,
00349         .otherend_changed = frontend_changed,
00350 };
00351 
00352 
00353 void sdev_xenbus_init(void)
00354 {
00355         char *err1 = "failed to register vwif device due to ";
00356         char * err2 = "faulty de-registration upon module unload";
00357 
00358         if (xenbus_register_backend(&sdevback) < 0)
00359                 printk(KERN_ERR 
00360                        "orbisquartus: %s%s\n", err1, err2);
00361 }
00362 
00363 
00364 void sdev_xenbus_exit(void)
00365 {
00366         xenbus_unregister_driver(&sdevback);
00367 }


© 2007, Los Alamos National Security, LLC.