Initial revision
[linux-2.6.git] / drivers / xen / xenbus / xenbus_backend_client.c
1 /******************************************************************************
2  * Backend-client-facing interface for the Xenbus driver.  In other words, the
3  * interface between the Xenbus and the device-specific code in the backend
4  * driver.
5  *
6  * Copyright (C) 2005-2006 XenSource Ltd
7  * 
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License version 2
10  * as published by the Free Software Foundation; or, when distributed
11  * separately from the Linux kernel or incorporated into other
12  * software packages, subject to the following license:
13  * 
14  * Permission is hereby granted, free of charge, to any person obtaining a copy
15  * of this source file (the "Software"), to deal in the Software without
16  * restriction, including without limitation the rights to use, copy, modify,
17  * merge, publish, distribute, sublicense, and/or sell copies of the Software,
18  * and to permit persons to whom the Software is furnished to do so, subject to
19  * the following conditions:
20  * 
21  * The above copyright notice and this permission notice shall be included in
22  * all copies or substantial portions of the Software.
23  * 
24  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
27  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
29  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
30  * IN THE SOFTWARE.
31  */
32
33 #include <linux/err.h>
34 #include <xen/gnttab.h>
35 #include <xen/xenbus.h>
36 #include <xen/driver_util.h>
37
38 /* Based on Rusty Russell's skeleton driver's map_page */
39 struct vm_struct *xenbus_map_ring_valloc(struct xenbus_device *dev, int gnt_ref)
40 {
41         struct gnttab_map_grant_ref op;
42         struct vm_struct *area;
43
44         area = alloc_vm_area(PAGE_SIZE);
45         if (!area)
46                 return ERR_PTR(-ENOMEM);
47
48         gnttab_set_map_op(&op, (unsigned long)area->addr, GNTMAP_host_map,
49                           gnt_ref, dev->otherend_id);
50         
51         lock_vm_area(area);
52         BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1));
53         unlock_vm_area(area);
54
55         if (op.status != GNTST_okay) {
56                 free_vm_area(area);
57                 xenbus_dev_fatal(dev, op.status,
58                                  "mapping in shared page %d from domain %d",
59                                  gnt_ref, dev->otherend_id);
60                 BUG_ON(!IS_ERR(ERR_PTR(op.status)));
61                 return ERR_PTR(op.status);
62         }
63
64         /* Stuff the handle in an unused field */
65         area->phys_addr = (unsigned long)op.handle;
66
67         return area;
68 }
69 EXPORT_SYMBOL_GPL(xenbus_map_ring_valloc);
70
71
72 int xenbus_map_ring(struct xenbus_device *dev, int gnt_ref,
73                    grant_handle_t *handle, void *vaddr)
74 {
75         struct gnttab_map_grant_ref op;
76         
77         gnttab_set_map_op(&op, (unsigned long)vaddr, GNTMAP_host_map,
78                           gnt_ref, dev->otherend_id);
79         BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1));
80
81         if (op.status != GNTST_okay) {
82                 xenbus_dev_fatal(dev, op.status,
83                                  "mapping in shared page %d from domain %d",
84                                  gnt_ref, dev->otherend_id);
85         } else
86                 *handle = op.handle;
87
88         return op.status;
89 }
90 EXPORT_SYMBOL_GPL(xenbus_map_ring);
91
92
93 /* Based on Rusty Russell's skeleton driver's unmap_page */
94 int xenbus_unmap_ring_vfree(struct xenbus_device *dev, struct vm_struct *area)
95 {
96         struct gnttab_unmap_grant_ref op;
97
98         gnttab_set_unmap_op(&op, (unsigned long)area->addr, GNTMAP_host_map,
99                             (grant_handle_t)area->phys_addr);
100
101         lock_vm_area(area);
102         BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1));
103         unlock_vm_area(area);
104
105         if (op.status == GNTST_okay)
106                 free_vm_area(area);
107         else
108                 xenbus_dev_error(dev, op.status,
109                                  "unmapping page at handle %d error %d",
110                                  (int16_t)area->phys_addr, op.status);
111
112         return op.status;
113 }
114 EXPORT_SYMBOL_GPL(xenbus_unmap_ring_vfree);
115
116
117 int xenbus_unmap_ring(struct xenbus_device *dev,
118                      grant_handle_t handle, void *vaddr)
119 {
120         struct gnttab_unmap_grant_ref op;
121
122         gnttab_set_unmap_op(&op, (unsigned long)vaddr, GNTMAP_host_map,
123                             handle);
124         BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1));
125
126         if (op.status != GNTST_okay)
127                 xenbus_dev_error(dev, op.status,
128                                  "unmapping page at handle %d error %d",
129                                  handle, op.status);
130
131         return op.status;
132 }
133 EXPORT_SYMBOL_GPL(xenbus_unmap_ring);
134
135 MODULE_LICENSE("Dual BSD/GPL");