svn commit: r186767 - user/dfr/xenhvm/6/sys/dev/xen/xenpci
Doug Rabson
dfr at FreeBSD.org
Mon Jan 5 02:43:49 PST 2009
Author: dfr
Date: Mon Jan 5 10:43:48 2009
New Revision: 186767
URL: http://svn.freebsd.org/changeset/base/186767
Log:
Tidy this up a lot and improve the comments somewhat.
Modified:
user/dfr/xenhvm/6/sys/dev/xen/xenpci/xenpci.c
user/dfr/xenhvm/6/sys/dev/xen/xenpci/xenpcivar.h
Modified: user/dfr/xenhvm/6/sys/dev/xen/xenpci/xenpci.c
==============================================================================
--- user/dfr/xenhvm/6/sys/dev/xen/xenpci/xenpci.c Mon Jan 5 10:41:54 2009 (r186766)
+++ user/dfr/xenhvm/6/sys/dev/xen/xenpci/xenpci.c Mon Jan 5 10:43:48 2009 (r186767)
@@ -1,5 +1,5 @@
/*
- * Copyright (c) [year] [your name]
+ * Copyright (c) 2008 Citrix Systems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -68,101 +68,12 @@ shared_info_t *HYPERVISOR_shared_info;
static vm_paddr_t shared_info_pa;
/*
- * The softc is automatically allocated by the parent bus using the
- * size specified in the driver_t declaration below.
+ * This is used to find our platform device instance.
*/
-#define DEVICE2SOFTC(dev) ((struct xenpci_softc *) device_get_softc(dev))
-
-/* Function prototypes (these should all be static). */
-static int xenpci_deallocate_resources(device_t device);
-static int xenpci_allocate_resources(device_t device);
-static int xenpci_attach(device_t device, struct xenpci_softc *scp);
-static int xenpci_detach(device_t device, struct xenpci_softc *scp);
-
-static int xenpci_alloc_space_int(struct xenpci_softc *scp, size_t sz,
- u_long *pa);
-
static devclass_t xenpci_devclass;
-static int xenpci_pci_probe(device_t);
-static int xenpci_pci_attach(device_t);
-static int xenpci_pci_detach(device_t);
-static int xenpci_pci_resume(device_t);
-
-static device_method_t xenpci_pci_methods[] = {
- /* Device interface */
- DEVMETHOD(device_probe, xenpci_pci_probe),
- DEVMETHOD(device_attach, xenpci_pci_attach),
- DEVMETHOD(device_detach, xenpci_pci_detach),
- DEVMETHOD(device_resume, xenpci_pci_resume),
-
- /* Bus interface */
- DEVMETHOD(bus_add_child, bus_generic_add_child),
-
- { 0, 0 }
-};
-
-static driver_t xenpci_pci_driver = {
- "xenpci",
- xenpci_pci_methods,
- sizeof(struct xenpci_softc),
-};
-
-DRIVER_MODULE(xenpci, pci, xenpci_pci_driver, xenpci_devclass, 0, 0);
-
-static struct _pcsid
-{
- u_int32_t type;
- const char *desc;
-} pci_ids[] = {
- { 0x00015853, "Xen Platform Device" },
- { 0x00000000, NULL }
-};
-
-static int
-xenpci_pci_probe (device_t device)
-{
- u_int32_t type = pci_get_devid(device);
- struct _pcsid *ep = pci_ids;
-
- while (ep->type && ep->type != type)
- ++ep;
- if (ep->desc) {
- device_set_desc(device, ep->desc);
- return (bus_generic_probe(device));
- } else
- return (ENXIO);
-}
-
-static int
-xenpci_pci_attach(device_t device)
-{
- int error;
- struct xenpci_softc *scp = DEVICE2SOFTC(device);
-
- error = xenpci_attach(device, scp);
- if (error)
- xenpci_pci_detach(device);
- return (error);
-}
-
-static int
-xenpci_pci_detach (device_t device)
-{
- struct xenpci_softc *scp = DEVICE2SOFTC(device);
-
- return (xenpci_detach(device, scp));
-}
-
-static int
-xenpci_pci_resume(device_t device)
-{
-
- return (bus_generic_resume(device));
-}
-
/*
- * Common Attachment sub-functions
+ * Return the CPUID base address for Xen functions.
*/
static uint32_t
xenpci_cpuid_base(void)
@@ -178,21 +89,24 @@ xenpci_cpuid_base(void)
return (0);
}
+/*
+ * Allocate and fill in the hypcall page.
+ */
static int
-xenpci_init_hypercall_stubs(device_t device, struct xenpci_softc * scp)
+xenpci_init_hypercall_stubs(device_t dev, struct xenpci_softc * scp)
{
uint32_t base, regs[4];
int i;
base = xenpci_cpuid_base();
if (!base) {
- device_printf(device, "Xen platform device but not Xen VMM\n");
+ device_printf(dev, "Xen platform device but not Xen VMM\n");
return (EINVAL);
}
if (bootverbose) {
do_cpuid(base + 1, regs);
- device_printf(device, "Xen version %d.%d.\n",
+ device_printf(dev, "Xen version %d.%d.\n",
regs[0] >> 16, regs[0] & 0xffff);
}
@@ -210,8 +124,11 @@ xenpci_init_hypercall_stubs(device_t dev
return (0);
}
+/*
+ * After a resume, re-initialise the hypercall page.
+ */
static void
-xenpci_resume_hypercall_stubs(device_t device, struct xenpci_softc * scp)
+xenpci_resume_hypercall_stubs(device_t dev, struct xenpci_softc * scp)
{
uint32_t base, regs[4];
int i;
@@ -224,19 +141,22 @@ xenpci_resume_hypercall_stubs(device_t d
}
}
+/*
+ * Tell the hypervisor how to contact us for event channel callbacks.
+ */
static void
-xenpci_set_callback(device_t device)
+xenpci_set_callback(device_t dev)
{
int irq;
uint64_t callback;
struct xen_hvm_param xhp;
- irq = pci_get_irq(device);
+ irq = pci_get_irq(dev);
if (irq < 16) {
callback = irq;
} else {
- callback = (pci_get_intpin(device) - 1) & 3;
- callback |= pci_get_slot(device) << 11;
+ callback = (pci_get_intpin(dev) - 1) & 3;
+ callback |= pci_get_slot(dev) << 11;
callback |= 1ull << 56;
}
@@ -247,135 +167,62 @@ xenpci_set_callback(device_t device)
panic("Can't set evtchn callback");
}
-static int
-xenpci_attach(device_t device, struct xenpci_softc * scp)
-{
- struct xen_add_to_physmap xatp;
- vm_offset_t shared_va;
-
- if (xenpci_allocate_resources(device))
- goto errexit;
-
- scp->phys_next = rman_get_start(scp->res_memory);
-
- if (xenpci_init_hypercall_stubs(device, scp))
- goto errexit;
-
- setup_xen_features();
-
- xenpci_alloc_space_int(scp, PAGE_SIZE, &shared_info_pa);
-
- xatp.domid = DOMID_SELF;
- xatp.idx = 0;
- xatp.space = XENMAPSPACE_shared_info;
- xatp.gpfn = shared_info_pa >> PAGE_SHIFT;
- if (HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp))
- panic("HYPERVISOR_memory_op failed");
-
- shared_va = kmem_alloc_nofault(kernel_map, PAGE_SIZE);
- pmap_kenter(shared_va, shared_info_pa);
- HYPERVISOR_shared_info = (void *) shared_va;
-
- /*
- * Hook the irq up to evtchn
- */
- xenpci_irq_init(device, scp);
- xenpci_set_callback(device);
-
- return (bus_generic_attach(device));
-
-errexit:
- /*
- * Undo anything we may have done.
- */
- xenpci_detach(device, scp);
- return (ENXIO);
-}
+/*
+ * Deallocate anything allocated by xenpci_allocate_resources.
+ */
static int
-xenpci_detach(device_t device, struct xenpci_softc *scp)
+xenpci_deallocate_resources(device_t dev)
{
- device_t parent = device_get_parent(device);
+ struct xenpci_softc *scp = device_get_softc(dev);
- /*
- * Take our interrupt handler out of the list of handlers
- * that can handle this irq.
- */
- if (scp->intr_cookie != NULL) {
- if (BUS_TEARDOWN_INTR(parent, device,
- scp->res_irq, scp->intr_cookie) != 0)
- printf("intr teardown failed.. continuing\n");
- scp->intr_cookie = NULL;
+ if (scp->res_irq != 0) {
+ bus_deactivate_resource(dev, SYS_RES_IRQ,
+ scp->rid_irq, scp->res_irq);
+ bus_release_resource(dev, SYS_RES_IRQ,
+ scp->rid_irq, scp->res_irq);
+ scp->res_irq = 0;
+ }
+ if (scp->res_memory != 0) {
+ bus_deactivate_resource(dev, SYS_RES_MEMORY,
+ scp->rid_memory, scp->res_memory);
+ bus_release_resource(dev, SYS_RES_MEMORY,
+ scp->rid_memory, scp->res_memory);
+ scp->res_memory = 0;
}
- /*
- * Deallocate any system resources we may have
- * allocated on behalf of this driver.
- */
- return xenpci_deallocate_resources(device);
+ return (0);
}
+/*
+ * Allocate irq and memory resources.
+ */
static int
-xenpci_allocate_resources(device_t device)
+xenpci_allocate_resources(device_t dev)
{
- int error;
- struct xenpci_softc *scp = DEVICE2SOFTC(device);
+ struct xenpci_softc *scp = device_get_softc(dev);
- scp->res_irq = bus_alloc_resource_any(device, SYS_RES_IRQ,
+ scp->res_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ,
&scp->rid_irq, RF_SHAREABLE|RF_ACTIVE);
if (scp->res_irq == NULL)
goto errexit;
- scp->rid_ioport = PCIR_BAR(0);
- scp->res_ioport = bus_alloc_resource_any(device, SYS_RES_IOPORT,
- &scp->rid_ioport, RF_ACTIVE);
- if (scp->res_ioport == NULL)
- goto errexit;
-
scp->rid_memory = PCIR_BAR(1);
- scp->res_memory = bus_alloc_resource_any(device, SYS_RES_MEMORY,
+ scp->res_memory = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
&scp->rid_memory, RF_ACTIVE);
if (scp->res_memory == NULL)
goto errexit;
return (0);
errexit:
- error = ENXIO;
/* Cleanup anything we may have assigned. */
- xenpci_deallocate_resources(device);
+ xenpci_deallocate_resources(dev);
return (ENXIO); /* For want of a better idea. */
}
-static int
-xenpci_deallocate_resources(device_t device)
-{
- struct xenpci_softc *scp = DEVICE2SOFTC(device);
-
- if (scp->res_irq != 0) {
- bus_deactivate_resource(device, SYS_RES_IRQ,
- scp->rid_irq, scp->res_irq);
- bus_release_resource(device, SYS_RES_IRQ,
- scp->rid_irq, scp->res_irq);
- scp->res_irq = 0;
- }
- if (scp->res_ioport != 0) {
- bus_deactivate_resource(device, SYS_RES_IOPORT,
- scp->rid_ioport, scp->res_ioport);
- bus_release_resource(device, SYS_RES_IOPORT,
- scp->rid_ioport, scp->res_ioport);
- scp->res_ioport = 0;
- }
- if (scp->res_memory != 0) {
- bus_deactivate_resource(device, SYS_RES_MEMORY,
- scp->rid_memory, scp->res_memory);
- bus_release_resource(device, SYS_RES_MEMORY,
- scp->rid_memory, scp->res_memory);
- scp->res_memory = 0;
- }
-
- return (0);
-}
-
+/*
+ * Allocate a physical address range from our mmio region.
+ */
static int
xenpci_alloc_space_int(struct xenpci_softc *scp, size_t sz,
vm_paddr_t *pa)
@@ -391,27 +238,35 @@ xenpci_alloc_space_int(struct xenpci_sof
return (0);
}
+/*
+ * Allocate a physical address range from our mmio region.
+ */
int
xenpci_alloc_space(size_t sz, vm_paddr_t *pa)
{
- device_t device = devclass_get_device(xenpci_devclass, 0);
+ device_t dev = devclass_get_device(xenpci_devclass, 0);
- if (device) {
- return (xenpci_alloc_space_int(DEVICE2SOFTC(device),
+ if (dev) {
+ return (xenpci_alloc_space_int(device_get_softc(dev),
sz, pa));
} else {
return (ENOMEM);
}
}
+/*
+ * Called very early in the resume sequence - reinitialise the various
+ * bits of Xen machinery including the hypercall page and the shared
+ * info page.
+ */
void
xenpci_resume()
{
- device_t device = devclass_get_device(xenpci_devclass, 0);
- struct xenpci_softc *scp = DEVICE2SOFTC(device);
+ device_t dev = devclass_get_device(xenpci_devclass, 0);
+ struct xenpci_softc *scp = device_get_softc(dev);
struct xen_add_to_physmap xatp;
- xenpci_resume_hypercall_stubs(device, scp);
+ xenpci_resume_hypercall_stubs(dev, scp);
xatp.domid = DOMID_SELF;
xatp.idx = 0;
@@ -422,9 +277,123 @@ xenpci_resume()
pmap_kenter((vm_offset_t) HYPERVISOR_shared_info, shared_info_pa);
- xenpci_set_callback(device);
+ xenpci_set_callback(dev);
gnttab_resume();
irq_resume();
}
+/*
+ * Probe - just check device ID.
+ */
+static int
+xenpci_probe(device_t dev)
+{
+
+ if (pci_get_devid(dev) != 0x00015853)
+ return (ENXIO);
+
+ device_set_desc(dev, "Xen Platform Device");
+ return (bus_generic_probe(dev));
+}
+
+/*
+ * Attach - find resources and talk to Xen.
+ */
+static int
+xenpci_attach(device_t dev)
+{
+ int error;
+ struct xenpci_softc *scp = device_get_softc(dev);
+ struct xen_add_to_physmap xatp;
+ vm_offset_t shared_va;
+
+ error = xenpci_allocate_resources(dev);
+ if (error)
+ goto errexit;
+
+ scp->phys_next = rman_get_start(scp->res_memory);
+
+ error = xenpci_init_hypercall_stubs(dev, scp);
+ if (error)
+ goto errexit;
+
+ setup_xen_features();
+
+ xenpci_alloc_space_int(scp, PAGE_SIZE, &shared_info_pa);
+
+ xatp.domid = DOMID_SELF;
+ xatp.idx = 0;
+ xatp.space = XENMAPSPACE_shared_info;
+ xatp.gpfn = shared_info_pa >> PAGE_SHIFT;
+ if (HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp))
+ panic("HYPERVISOR_memory_op failed");
+
+ shared_va = kmem_alloc_nofault(kernel_map, PAGE_SIZE);
+ pmap_kenter(shared_va, shared_info_pa);
+ HYPERVISOR_shared_info = (void *) shared_va;
+
+ /*
+ * Hook the irq up to evtchn
+ */
+ xenpci_irq_init(dev, scp);
+ xenpci_set_callback(dev);
+
+ return (bus_generic_attach(dev));
+
+errexit:
+ /*
+ * Undo anything we may have done.
+ */
+ xenpci_deallocate_resources(dev);
+ return (error);
+}
+
+/*
+ * Detach - reverse anything done by attach.
+ */
+static int
+xenpci_detach(device_t dev)
+{
+ struct xenpci_softc *scp = device_get_softc(dev);
+ device_t parent = device_get_parent(dev);
+
+ /*
+ * Take our interrupt handler out of the list of handlers
+ * that can handle this irq.
+ */
+ if (scp->intr_cookie != NULL) {
+ if (BUS_TEARDOWN_INTR(parent, dev,
+ scp->res_irq, scp->intr_cookie) != 0)
+ printf("intr teardown failed.. continuing\n");
+ scp->intr_cookie = NULL;
+ }
+
+ /*
+ * Deallocate any system resources we may have
+ * allocated on behalf of this driver.
+ */
+ return (xenpci_deallocate_resources(dev));
+}
+
+static device_method_t xenpci_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, xenpci_probe),
+ DEVMETHOD(device_attach, xenpci_attach),
+ DEVMETHOD(device_detach, xenpci_detach),
+ DEVMETHOD(device_suspend, bus_generic_suspend),
+ DEVMETHOD(device_resume, bus_generic_resume),
+
+ /* Bus interface */
+ DEVMETHOD(bus_add_child, bus_generic_add_child),
+
+ { 0, 0 }
+};
+
+static driver_t xenpci_driver = {
+ "xenpci",
+ xenpci_methods,
+ sizeof(struct xenpci_softc),
+};
+
+DRIVER_MODULE(xenpci, pci, xenpci_driver, xenpci_devclass, 0, 0);
Modified: user/dfr/xenhvm/6/sys/dev/xen/xenpci/xenpcivar.h
==============================================================================
--- user/dfr/xenhvm/6/sys/dev/xen/xenpci/xenpcivar.h Mon Jan 5 10:41:54 2009 (r186766)
+++ user/dfr/xenhvm/6/sys/dev/xen/xenpci/xenpcivar.h Mon Jan 5 10:43:48 2009 (r186767)
@@ -1,5 +1,5 @@
/*
- * Copyright (c) [year] [your name]
+ * Copyright (c) 2008 Citrix Systems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -31,7 +31,6 @@ struct xenpci_softc {
int rid_ioport;
int rid_memory;
int rid_irq;
- struct resource* res_ioport; /* Resource for port range. */
struct resource* res_memory; /* Resource for mem range. */
struct resource* res_irq; /* Resource for irq range. */
void *intr_cookie;
More information about the svn-src-user
mailing list