aboutsummaryrefslogtreecommitdiffstats
path: root/linux-2.6.9-xen-sparse/arch/xen/i386/pci/direct.c
blob: e964ae00f1d87211344888911811d851f52950a4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
/*
 * direct.c - Low-level direct PCI config space access
 */

#include <linux/pci.h>
#include <linux/init.h>
#include "pci.h"

#include <asm/xen-public/xen.h>
#include <asm/xen-public/physdev.h>

/*
 * Functions for accessing PCI configuration space with type xen accesses
 */

static int pci_conf_read (int seg, int bus, int devfn, int reg, int len, u32 *value)
{
	unsigned long flags;
	physdev_op_t op;
	int ret;

	if (!value || (bus > 255) || (devfn > 255) || (reg > 255))
		return -EINVAL;

	spin_lock_irqsave(&pci_config_lock, flags);

	op.cmd = PHYSDEVOP_PCI_CFGREG_READ;
	op.u.pci_cfgreg_read.bus  = bus;
	op.u.pci_cfgreg_read.dev  = (devfn & ~0x7) >> 3;
	op.u.pci_cfgreg_read.func = devfn & 0x7;
	op.u.pci_cfgreg_read.reg  = reg;
	op.u.pci_cfgreg_read.len  = len;

	ret = HYPERVISOR_physdev_op(&op);
	if (ret == 0)
		*value = op.u.pci_cfgreg_read.value;

	spin_unlock_irqrestore(&pci_config_lock, flags);

	return ret;
}

static int pci_conf_write (int seg, int bus, int devfn, int reg, int len, u32 value)
{
	unsigned long flags;
	physdev_op_t op;
	int ret;

	if ((bus > 255) || (devfn > 255) || (reg > 255)) 
		return -EINVAL;

	spin_lock_irqsave(&pci_config_lock, flags);

	op.cmd = PHYSDEVOP_PCI_CFGREG_WRITE;
	op.u.pci_cfgreg_write.bus   = bus;
	op.u.pci_cfgreg_write.dev   = (devfn & ~0x7) >> 3;
	op.u.pci_cfgreg_write.func  = devfn & 0x7;
	op.u.pci_cfgreg_write.reg   = reg;
	op.u.pci_cfgreg_write.len   = len;
	op.u.pci_cfgreg_write.value = value;

	ret = HYPERVISOR_physdev_op(&op);

	spin_unlock_irqrestore(&pci_config_lock, flags);

	return ret;
}

struct pci_raw_ops pci_direct_xen = {
	.read =		pci_conf_read,
	.write =	pci_conf_write,
};


static int __init pci_direct_init(void)
{

        printk(KERN_INFO "PCI: Using configuration type Xen\n");
        raw_pci_ops = &pci_direct_xen;
        return 0;
}

arch_initcall(pci_direct_init);