ia64/xen-unstable

view extras/mini-os/pcifront.c @ 19836:d9890e67d2b7

tools: add SHAREDIR to buildmakevars2file

c/s 19818 dropped SHAREDIR from xen/util/path.py, which broke the "xm
new" command. This patch adds SHAREDIR back to the new
buildmakevars2file-closure function.

Signed-off-by: Ryan O'Connor <rjo@cs.ubc.ca>
author Keir Fraser <keir.fraser@citrix.com>
date Thu Jun 25 13:05:10 2009 +0100 (2009-06-25)
parents 18c8270da77c
children
line source
1 /* Minimal PCI driver for Mini-OS.
2 * Copyright (c) 2007-2008 Samuel Thibault.
3 * Based on blkfront.c.
4 */
6 #include <os.h>
7 #include <xenbus.h>
8 #include <events.h>
9 #include <errno.h>
10 #include <gnttab.h>
11 #include <xmalloc.h>
12 #include <wait.h>
13 #include <pcifront.h>
15 #define PCI_DEVFN(slot, func) ((((slot) & 0x1f) << 3) | ((func) & 0x07))
17 DECLARE_WAIT_QUEUE_HEAD(pcifront_queue);
19 struct pcifront_dev {
20 domid_t dom;
22 struct xen_pci_sharedinfo *info;
23 grant_ref_t info_ref;
24 evtchn_port_t evtchn;
26 char *nodename;
27 char *backend;
29 xenbus_event_queue events;
30 };
32 void pcifront_handler(evtchn_port_t port, struct pt_regs *regs, void *data)
33 {
34 wake_up(&pcifront_queue);
35 }
37 static void free_pcifront(struct pcifront_dev *dev)
38 {
39 mask_evtchn(dev->evtchn);
41 free(dev->backend);
43 gnttab_end_access(dev->info_ref);
44 free_page(dev->info);
46 unbind_evtchn(dev->evtchn);
48 free(dev->nodename);
49 free(dev);
50 }
52 struct pcifront_dev *init_pcifront(char *_nodename)
53 {
54 xenbus_transaction_t xbt;
55 char* err;
56 char* message=NULL;
57 int retry=0;
58 char* msg;
59 char* nodename = _nodename ? _nodename : "device/pci/0";
60 int dom;
62 struct pcifront_dev *dev;
64 char path[strlen(nodename) + 1 + 10 + 1];
66 printk("******************* PCIFRONT for %s **********\n\n\n", nodename);
68 snprintf(path, sizeof(path), "%s/backend-id", nodename);
69 dom = xenbus_read_integer(path);
70 if (dom == -1) {
71 printk("no backend\n");
72 return NULL;
73 }
75 dev = malloc(sizeof(*dev));
76 memset(dev, 0, sizeof(*dev));
77 dev->nodename = strdup(nodename);
78 dev->dom = dom;
80 evtchn_alloc_unbound(dev->dom, pcifront_handler, dev, &dev->evtchn);
82 dev->info = (struct xen_pci_sharedinfo*) alloc_page();
83 memset(dev->info,0,PAGE_SIZE);
85 dev->info_ref = gnttab_grant_access(dev->dom,virt_to_mfn(dev->info),0);
87 dev->events = NULL;
89 again:
90 err = xenbus_transaction_start(&xbt);
91 if (err) {
92 printk("starting transaction\n");
93 }
95 err = xenbus_printf(xbt, nodename, "pci-op-ref","%u",
96 dev->info_ref);
97 if (err) {
98 message = "writing pci-op-ref";
99 goto abort_transaction;
100 }
101 err = xenbus_printf(xbt, nodename,
102 "event-channel", "%u", dev->evtchn);
103 if (err) {
104 message = "writing event-channel";
105 goto abort_transaction;
106 }
107 err = xenbus_printf(xbt, nodename,
108 "magic", XEN_PCI_MAGIC);
109 if (err) {
110 message = "writing magic";
111 goto abort_transaction;
112 }
114 snprintf(path, sizeof(path), "%s/state", nodename);
115 err = xenbus_switch_state(xbt, path, XenbusStateInitialised);
116 if (err) {
117 message = "switching state";
118 goto abort_transaction;
119 }
121 err = xenbus_transaction_end(xbt, 0, &retry);
122 if (retry) {
123 goto again;
124 printk("completing transaction\n");
125 }
127 goto done;
129 abort_transaction:
130 xenbus_transaction_end(xbt, 1, &retry);
131 goto error;
133 done:
135 snprintf(path, sizeof(path), "%s/backend", nodename);
136 msg = xenbus_read(XBT_NIL, path, &dev->backend);
137 if (msg) {
138 printk("Error %s when reading the backend path %s\n", msg, path);
139 goto error;
140 }
142 printk("backend at %s\n", dev->backend);
144 {
145 char path[strlen(dev->backend) + 1 + 5 + 1];
146 char frontpath[strlen(nodename) + 1 + 5 + 1];
147 XenbusState state;
148 snprintf(path, sizeof(path), "%s/state", dev->backend);
150 xenbus_watch_path_token(XBT_NIL, path, path, &dev->events);
152 err = NULL;
153 state = xenbus_read_integer(path);
154 while (err == NULL && state < XenbusStateConnected)
155 err = xenbus_wait_for_state_change(path, &state, &dev->events);
156 if (state != XenbusStateConnected) {
157 printk("backend not avalable, state=%d\n", state);
158 xenbus_unwatch_path(XBT_NIL, path);
159 goto error;
160 }
162 snprintf(frontpath, sizeof(frontpath), "%s/state", nodename);
163 if ((err = xenbus_switch_state(XBT_NIL, frontpath, XenbusStateConnected))
164 != NULL) {
165 printk("error switching state %s\n", err);
166 xenbus_unwatch_path(XBT_NIL, path);
167 goto error;
168 }
169 }
170 unmask_evtchn(dev->evtchn);
172 printk("**************************\n");
174 return dev;
176 error:
177 free_pcifront(dev);
178 return NULL;
179 }
181 void pcifront_scan(struct pcifront_dev *dev, void (*func)(unsigned int domain, unsigned int bus, unsigned slot, unsigned int fun))
182 {
183 char path[strlen(dev->backend) + 1 + 5 + 10 + 1];
184 int i, n;
185 char *s, *msg;
186 unsigned int domain, bus, slot, fun;
188 snprintf(path, sizeof(path), "%s/num_devs", dev->backend);
189 n = xenbus_read_integer(path);
191 for (i = 0; i < n; i++) {
192 snprintf(path, sizeof(path), "%s/vdev-%d", dev->backend, i);
193 msg = xenbus_read(XBT_NIL, path, &s);
194 if (msg) {
195 printk("Error %s when reading the PCI root name at %s\n", path);
196 continue;
197 }
199 if (sscanf(s, "%x:%x:%x.%x", &domain, &bus, &slot, &fun) != 4) {
200 printk("\"%s\" does not look like a PCI device address\n", s);
201 free(s);
202 continue;
203 }
204 free(s);
206 func(domain, bus, slot, fun);
207 }
208 }
210 void shutdown_pcifront(struct pcifront_dev *dev)
211 {
212 char* err = NULL;
213 XenbusState state;
215 char path[strlen(dev->backend) + 1 + 5 + 1];
216 char nodename[strlen(dev->nodename) + 1 + 5 + 1];
218 printk("close pci: backend at %s\n",dev->backend);
220 snprintf(path, sizeof(path), "%s/state", dev->backend);
221 snprintf(nodename, sizeof(nodename), "%s/state", dev->nodename);
222 if ((err = xenbus_switch_state(XBT_NIL, nodename, XenbusStateClosing)) != NULL) {
223 printk("shutdown_pcifront: error changing state to %d: %s\n",
224 XenbusStateClosing, err);
225 goto close_pcifront;
226 }
227 state = xenbus_read_integer(path);
228 while (err == NULL && state < XenbusStateClosing)
229 err = xenbus_wait_for_state_change(path, &state, &dev->events);
231 if ((err = xenbus_switch_state(XBT_NIL, nodename, XenbusStateClosed)) != NULL) {
232 printk("shutdown_pcifront: error changing state to %d: %s\n",
233 XenbusStateClosed, err);
234 goto close_pcifront;
235 }
236 state = xenbus_read_integer(path);
237 if (state < XenbusStateClosed)
238 xenbus_wait_for_state_change(path, &state, &dev->events);
240 if ((err = xenbus_switch_state(XBT_NIL, nodename, XenbusStateInitialising)) != NULL) {
241 printk("shutdown_pcifront: error changing state to %d: %s\n",
242 XenbusStateInitialising, err);
243 goto close_pcifront;
244 }
245 err = NULL;
246 state = xenbus_read_integer(path);
247 while (err == NULL && (state < XenbusStateInitWait || state >= XenbusStateClosed))
248 err = xenbus_wait_for_state_change(path, &state, &dev->events);
250 close_pcifront:
251 xenbus_unwatch_path(XBT_NIL, path);
253 snprintf(path, sizeof(path), "%s/info-ref", nodename);
254 xenbus_rm(XBT_NIL, path);
255 snprintf(path, sizeof(path), "%s/event-channel", nodename);
256 xenbus_rm(XBT_NIL, path);
258 free_pcifront(dev);
259 }
262 void pcifront_op(struct pcifront_dev *dev, struct xen_pci_op *op)
263 {
264 dev->info->op = *op;
265 /* Make sure info is written before the flag */
266 wmb();
267 set_bit(_XEN_PCIF_active, (void*) &dev->info->flags);
268 notify_remote_via_evtchn(dev->evtchn);
270 wait_event(pcifront_queue, !test_bit(_XEN_PCIF_active, (void*) &dev->info->flags));
272 /* Make sure flag is read before info */
273 rmb();
274 *op = dev->info->op;
275 }
277 int pcifront_conf_read(struct pcifront_dev *dev,
278 unsigned int dom,
279 unsigned int bus, unsigned int slot, unsigned long fun,
280 unsigned int off, unsigned int size, unsigned int *val)
281 {
282 struct xen_pci_op op;
284 memset(&op, 0, sizeof(op));
286 op.cmd = XEN_PCI_OP_conf_read;
287 op.domain = dom;
288 op.bus = bus;
289 op.devfn = PCI_DEVFN(slot, fun);
290 op.offset = off;
291 op.size = size;
293 pcifront_op(dev, &op);
295 if (op.err)
296 return op.err;
298 *val = op.value;
300 return 0;
301 }
303 int pcifront_conf_write(struct pcifront_dev *dev,
304 unsigned int dom,
305 unsigned int bus, unsigned int slot, unsigned long fun,
306 unsigned int off, unsigned int size, unsigned int val)
307 {
308 struct xen_pci_op op;
310 memset(&op, 0, sizeof(op));
312 op.cmd = XEN_PCI_OP_conf_write;
313 op.domain = dom;
314 op.bus = bus;
315 op.devfn = PCI_DEVFN(slot, fun);
316 op.offset = off;
317 op.size = size;
319 op.value = val;
321 pcifront_op(dev, &op);
323 return op.err;
324 }
326 int pcifront_enable_msi(struct pcifront_dev *dev,
327 unsigned int dom,
328 unsigned int bus, unsigned int slot, unsigned long fun)
329 {
330 struct xen_pci_op op;
332 memset(&op, 0, sizeof(op));
334 op.cmd = XEN_PCI_OP_enable_msi;
335 op.domain = dom;
336 op.bus = bus;
337 op.devfn = PCI_DEVFN(slot, fun);
339 pcifront_op(dev, &op);
341 if (op.err)
342 return op.err;
343 else
344 return op.value;
345 }
347 int pcifront_disable_msi(struct pcifront_dev *dev,
348 unsigned int dom,
349 unsigned int bus, unsigned int slot, unsigned long fun)
350 {
351 struct xen_pci_op op;
353 memset(&op, 0, sizeof(op));
355 op.cmd = XEN_PCI_OP_disable_msi;
356 op.domain = dom;
357 op.bus = bus;
358 op.devfn = PCI_DEVFN(slot, fun);
360 pcifront_op(dev, &op);
362 return op.err;
363 }
365 int pcifront_enable_msix(struct pcifront_dev *dev,
366 unsigned int dom,
367 unsigned int bus, unsigned int slot, unsigned long fun,
368 struct xen_msix_entry *entries, int n)
369 {
370 struct xen_pci_op op;
372 if (n > SH_INFO_MAX_VEC)
373 return XEN_PCI_ERR_op_failed;
375 memset(&op, 0, sizeof(op));
377 op.cmd = XEN_PCI_OP_enable_msix;
378 op.domain = dom;
379 op.bus = bus;
380 op.devfn = PCI_DEVFN(slot, fun);
381 op.value = n;
383 memcpy(op.msix_entries, entries, n * sizeof(*entries));
385 pcifront_op(dev, &op);
387 if (op.err)
388 return op.err;
390 memcpy(entries, op.msix_entries, n * sizeof(*entries));
392 return 0;
393 }
396 int pcifront_disable_msix(struct pcifront_dev *dev,
397 unsigned int dom,
398 unsigned int bus, unsigned int slot, unsigned long fun)
399 {
400 struct xen_pci_op op;
402 memset(&op, 0, sizeof(op));
404 op.cmd = XEN_PCI_OP_disable_msix;
405 op.domain = dom;
406 op.bus = bus;
407 op.devfn = PCI_DEVFN(slot, fun);
409 pcifront_op(dev, &op);
411 return op.err;
412 }