ia64/xen-unstable

view extras/mini-os/pcifront.c @ 18811:390ef36eb596

Remove Xen-private definitions from kexec public header.

Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Wed Nov 19 13:13:39 2008 +0000 (2008-11-19)
parents 1f338c90d60f
children 18c8270da77c
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 err = xenbus_printf(xbt, nodename, "state", "%u",
115 3); /* initialised */
118 err = xenbus_transaction_end(xbt, 0, &retry);
119 if (retry) {
120 goto again;
121 printk("completing transaction\n");
122 }
124 goto done;
126 abort_transaction:
127 xenbus_transaction_end(xbt, 1, &retry);
128 goto error;
130 done:
132 snprintf(path, sizeof(path), "%s/backend", nodename);
133 msg = xenbus_read(XBT_NIL, path, &dev->backend);
134 if (msg) {
135 printk("Error %s when reading the backend path %s\n", msg, path);
136 goto error;
137 }
139 printk("backend at %s\n", dev->backend);
141 {
142 char path[strlen(dev->backend) + 1 + 5 + 1];
143 snprintf(path, sizeof(path), "%s/state", dev->backend);
145 xenbus_watch_path_token(XBT_NIL, path, path, &dev->events);
147 xenbus_wait_for_value(path, "4", &dev->events);
149 xenbus_printf(xbt, nodename, "state", "%u", 4); /* connected */
150 }
151 unmask_evtchn(dev->evtchn);
153 printk("**************************\n");
155 return dev;
157 error:
158 free_pcifront(dev);
159 return NULL;
160 }
162 void pcifront_scan(struct pcifront_dev *dev, void (*func)(unsigned int domain, unsigned int bus, unsigned slot, unsigned int fun))
163 {
164 char path[strlen(dev->backend) + 1 + 5 + 10 + 1];
165 int i, n;
166 char *s, *msg;
167 unsigned int domain, bus, slot, fun;
169 snprintf(path, sizeof(path), "%s/num_devs", dev->backend);
170 n = xenbus_read_integer(path);
172 for (i = 0; i < n; i++) {
173 snprintf(path, sizeof(path), "%s/vdev-%d", dev->backend, i);
174 msg = xenbus_read(XBT_NIL, path, &s);
175 if (msg) {
176 printk("Error %s when reading the PCI root name at %s\n", path);
177 continue;
178 }
180 if (sscanf(s, "%x:%x:%x.%x", &domain, &bus, &slot, &fun) != 4) {
181 printk("\"%s\" does not look like a PCI device address\n", s);
182 free(s);
183 continue;
184 }
185 free(s);
187 func(domain, bus, slot, fun);
188 }
189 }
191 void shutdown_pcifront(struct pcifront_dev *dev)
192 {
193 char* err;
194 char *nodename = dev->nodename;
196 char path[strlen(dev->backend) + 1 + 5 + 1];
198 printk("close pci: backend at %s\n",dev->backend);
200 snprintf(path, sizeof(path), "%s/state", dev->backend);
201 err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 5); /* closing */
202 xenbus_wait_for_value(path, "5", &dev->events);
204 err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 6);
205 xenbus_wait_for_value(path, "6", &dev->events);
207 err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 1);
208 xenbus_wait_for_value(path, "2", &dev->events);
210 xenbus_unwatch_path(XBT_NIL, path);
212 snprintf(path, sizeof(path), "%s/info-ref", nodename);
213 xenbus_rm(XBT_NIL, path);
214 snprintf(path, sizeof(path), "%s/event-channel", nodename);
215 xenbus_rm(XBT_NIL, path);
217 free_pcifront(dev);
218 }
221 void pcifront_op(struct pcifront_dev *dev, struct xen_pci_op *op)
222 {
223 dev->info->op = *op;
224 /* Make sure info is written before the flag */
225 wmb();
226 set_bit(_XEN_PCIF_active, (void*) &dev->info->flags);
227 notify_remote_via_evtchn(dev->evtchn);
229 wait_event(pcifront_queue, !test_bit(_XEN_PCIF_active, (void*) &dev->info->flags));
231 /* Make sure flag is read before info */
232 rmb();
233 *op = dev->info->op;
234 }
236 int pcifront_conf_read(struct pcifront_dev *dev,
237 unsigned int dom,
238 unsigned int bus, unsigned int slot, unsigned long fun,
239 unsigned int off, unsigned int size, unsigned int *val)
240 {
241 struct xen_pci_op op;
243 memset(&op, 0, sizeof(op));
245 op.cmd = XEN_PCI_OP_conf_read;
246 op.domain = dom;
247 op.bus = bus;
248 op.devfn = PCI_DEVFN(slot, fun);
249 op.offset = off;
250 op.size = size;
252 pcifront_op(dev, &op);
254 if (op.err)
255 return op.err;
257 *val = op.value;
259 return 0;
260 }
262 int pcifront_conf_write(struct pcifront_dev *dev,
263 unsigned int dom,
264 unsigned int bus, unsigned int slot, unsigned long fun,
265 unsigned int off, unsigned int size, unsigned int val)
266 {
267 struct xen_pci_op op;
269 memset(&op, 0, sizeof(op));
271 op.cmd = XEN_PCI_OP_conf_write;
272 op.domain = dom;
273 op.bus = bus;
274 op.devfn = PCI_DEVFN(slot, fun);
275 op.offset = off;
276 op.size = size;
278 op.value = val;
280 pcifront_op(dev, &op);
282 return op.err;
283 }
285 int pcifront_enable_msi(struct pcifront_dev *dev,
286 unsigned int dom,
287 unsigned int bus, unsigned int slot, unsigned long fun)
288 {
289 struct xen_pci_op op;
291 memset(&op, 0, sizeof(op));
293 op.cmd = XEN_PCI_OP_enable_msi;
294 op.domain = dom;
295 op.bus = bus;
296 op.devfn = PCI_DEVFN(slot, fun);
298 pcifront_op(dev, &op);
300 if (op.err)
301 return op.err;
302 else
303 return op.value;
304 }
306 int pcifront_disable_msi(struct pcifront_dev *dev,
307 unsigned int dom,
308 unsigned int bus, unsigned int slot, unsigned long fun)
309 {
310 struct xen_pci_op op;
312 memset(&op, 0, sizeof(op));
314 op.cmd = XEN_PCI_OP_disable_msi;
315 op.domain = dom;
316 op.bus = bus;
317 op.devfn = PCI_DEVFN(slot, fun);
319 pcifront_op(dev, &op);
321 return op.err;
322 }
324 int pcifront_enable_msix(struct pcifront_dev *dev,
325 unsigned int dom,
326 unsigned int bus, unsigned int slot, unsigned long fun,
327 struct xen_msix_entry *entries, int n)
328 {
329 struct xen_pci_op op;
331 if (n > SH_INFO_MAX_VEC)
332 return XEN_PCI_ERR_op_failed;
334 memset(&op, 0, sizeof(op));
336 op.cmd = XEN_PCI_OP_enable_msix;
337 op.domain = dom;
338 op.bus = bus;
339 op.devfn = PCI_DEVFN(slot, fun);
340 op.value = n;
342 memcpy(op.msix_entries, entries, n * sizeof(*entries));
344 pcifront_op(dev, &op);
346 if (op.err)
347 return op.err;
349 memcpy(entries, op.msix_entries, n * sizeof(*entries));
351 return 0;
352 }
355 int pcifront_disable_msix(struct pcifront_dev *dev,
356 unsigned int dom,
357 unsigned int bus, unsigned int slot, unsigned long fun)
358 {
359 struct xen_pci_op op;
361 memset(&op, 0, sizeof(op));
363 op.cmd = XEN_PCI_OP_disable_msix;
364 op.domain = dom;
365 op.bus = bus;
366 op.devfn = PCI_DEVFN(slot, fun);
368 pcifront_op(dev, &op);
370 return op.err;
371 }