1 /* Xenbus code for tpmif backend
2 Copyright (C) 2005 IBM Corporation
3 Copyright (C) 2005 Rusty Russell <rusty@rustcorp.com.au>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 #include <linux/module.h>
21 #include <xen/xenbus.h>
26 struct xenbus_device *dev;
28 /* our communications channel */
32 long int instance; // instance of TPM
33 u8 is_instance_set;// whether instance number has been set
35 /* watch front end for changes */
36 struct xenbus_watch backend_watch;
39 static void maybe_connect(struct backend_info *be);
40 static void connect(struct backend_info *be);
41 static int connect_ring(struct backend_info *be);
42 static void backend_changed(struct xenbus_watch *watch,
43 const char **vec, unsigned int len);
44 static void frontend_changed(struct xenbus_device *dev,
45 enum xenbus_state frontend_state);
47 long int tpmback_get_instance(struct backend_info *bi)
50 if (bi && bi->is_instance_set)
55 static int tpmback_remove(struct xenbus_device *dev)
57 struct backend_info *be = dev->dev.driver_data;
61 if (be->backend_watch.node) {
62 unregister_xenbus_watch(&be->backend_watch);
63 kfree(be->backend_watch.node);
64 be->backend_watch.node = NULL;
68 vtpm_release_packets(be->tpmif, 0);
73 dev->dev.driver_data = NULL;
77 static int tpmback_probe(struct xenbus_device *dev,
78 const struct xenbus_device_id *id)
81 struct backend_info *be = kzalloc(sizeof(struct backend_info),
85 xenbus_dev_fatal(dev, -ENOMEM,
86 "allocating backend structure");
90 be->is_instance_set = 0;
92 dev->dev.driver_data = be;
94 err = xenbus_watch_path2(dev, dev->nodename,
95 "instance", &be->backend_watch,
101 err = xenbus_switch_state(dev, XenbusStateInitWait);
112 static void backend_changed(struct xenbus_watch *watch,
113 const char **vec, unsigned int len)
117 struct backend_info *be
118 = container_of(watch, struct backend_info, backend_watch);
119 struct xenbus_device *dev = be->dev;
121 err = xenbus_scanf(XBT_NIL, dev->nodename,
122 "instance","%li", &instance);
123 if (XENBUS_EXIST_ERR(err)) {
128 xenbus_dev_fatal(dev, err, "reading instance");
132 if (be->is_instance_set == 0) {
133 be->instance = instance;
134 be->is_instance_set = 1;
139 static void frontend_changed(struct xenbus_device *dev,
140 enum xenbus_state frontend_state)
142 struct backend_info *be = dev->dev.driver_data;
145 switch (frontend_state) {
146 case XenbusStateInitialising:
147 case XenbusStateInitialised:
150 case XenbusStateConnected:
151 err = connect_ring(be);
158 case XenbusStateClosing:
162 case XenbusStateUnknown:
163 case XenbusStateClosed:
164 device_unregister(&be->dev->dev);
169 xenbus_dev_fatal(dev, -EINVAL,
170 "saw state %d at frontend",
178 static void maybe_connect(struct backend_info *be)
180 if (be->tpmif == NULL || be->tpmif->status == CONNECTED)
187 static void connect(struct backend_info *be)
189 struct xenbus_transaction xbt;
191 struct xenbus_device *dev = be->dev;
192 unsigned long ready = 1;
195 err = xenbus_transaction_start(&xbt);
197 xenbus_dev_fatal(be->dev, err, "starting transaction");
201 err = xenbus_printf(xbt, be->dev->nodename,
202 "ready", "%lu", ready);
204 xenbus_dev_fatal(be->dev, err, "writing 'ready'");
208 err = xenbus_transaction_end(xbt, 0);
212 xenbus_dev_fatal(be->dev, err, "end of transaction");
214 err = xenbus_switch_state(dev, XenbusStateConnected);
216 be->tpmif->status = CONNECTED;
219 xenbus_transaction_end(xbt, 1);
223 static int connect_ring(struct backend_info *be)
225 struct xenbus_device *dev = be->dev;
226 unsigned long ring_ref;
230 err = xenbus_gather(XBT_NIL, dev->otherend,
231 "ring-ref", "%lu", &ring_ref,
232 "event-channel", "%u", &evtchn, NULL);
234 xenbus_dev_error(dev, err,
235 "reading %s/ring-ref and event-channel",
241 be->tpmif = tpmif_find(dev->otherend_id, be);
242 if (IS_ERR(be->tpmif)) {
243 err = PTR_ERR(be->tpmif);
245 xenbus_dev_fatal(dev,err,"creating vtpm interface");
250 if (be->tpmif != NULL) {
251 err = tpmif_map(be->tpmif, ring_ref, evtchn);
253 xenbus_dev_error(dev, err,
254 "mapping shared-frame %lu port %u",
263 static struct xenbus_device_id tpmback_ids[] = {
269 static struct xenbus_driver tpmback = {
271 .owner = THIS_MODULE,
273 .probe = tpmback_probe,
274 .remove = tpmback_remove,
275 .otherend_changed = frontend_changed,
279 void tpmif_xenbus_init(void)
281 xenbus_register_backend(&tpmback);
284 void tpmif_xenbus_exit(void)
286 xenbus_unregister_driver(&tpmback);