debuggers.hg

view xen/arch/x86/pci.c @ 0:7d21f7218375

Exact replica of unstable on 051908 + README-this
author Mukesh Rathor
date Mon May 19 15:34:57 2008 -0700 (2008-05-19)
parents
children f875aaa791f0
line source
1 /******************************************************************************
2 * pci.c
3 *
4 * PCI access functions.
5 */
7 #include <xen/config.h>
8 #include <xen/pci.h>
9 #include <xen/pci_regs.h>
10 #include <xen/spinlock.h>
11 #include <asm/io.h>
13 #define PCI_CONF_ADDRESS(bus, dev, func, reg) \
14 (0x80000000 | (bus << 16) | (dev << 11) | (func << 8) | (reg & ~3))
16 static DEFINE_SPINLOCK(pci_config_lock);
18 uint32_t pci_conf_read(uint32_t cf8, uint8_t offset, uint8_t bytes)
19 {
20 unsigned long flags;
21 uint32_t value;
23 BUG_ON((offset + bytes) > 4);
25 spin_lock_irqsave(&pci_config_lock, flags);
27 outl(cf8, 0xcf8);
29 switch ( bytes )
30 {
31 case 1:
32 value = inb(0xcfc + offset);
33 break;
34 case 2:
35 value = inw(0xcfc + offset);
36 break;
37 case 4:
38 value = inl(0xcfc + offset);
39 break;
40 default:
41 value = 0;
42 BUG();
43 }
45 spin_unlock_irqrestore(&pci_config_lock, flags);
47 return value;
48 }
50 void pci_conf_write(uint32_t cf8, uint8_t offset, uint8_t bytes, uint32_t data)
51 {
52 unsigned long flags;
54 BUG_ON((offset + bytes) > 4);
56 spin_lock_irqsave(&pci_config_lock, flags);
58 outl(cf8, 0xcf8);
60 switch ( bytes )
61 {
62 case 1:
63 outb((uint8_t)data, 0xcfc + offset);
64 break;
65 case 2:
66 outw((uint16_t)data, 0xcfc + offset);
67 break;
68 case 4:
69 outl(data, 0xcfc + offset);
70 break;
71 }
73 spin_unlock_irqrestore(&pci_config_lock, flags);
74 }
76 uint8_t pci_conf_read8(
77 unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg)
78 {
79 BUG_ON((bus > 255) || (dev > 31) || (func > 7) || (reg > 255));
80 return pci_conf_read(PCI_CONF_ADDRESS(bus, dev, func, reg), reg & 3, 1);
81 }
83 uint16_t pci_conf_read16(
84 unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg)
85 {
86 BUG_ON((bus > 255) || (dev > 31) || (func > 7) || (reg > 255));
87 return pci_conf_read(PCI_CONF_ADDRESS(bus, dev, func, reg), reg & 2, 2);
88 }
90 uint32_t pci_conf_read32(
91 unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg)
92 {
93 BUG_ON((bus > 255) || (dev > 31) || (func > 7) || (reg > 255));
94 return pci_conf_read(PCI_CONF_ADDRESS(bus, dev, func, reg), 0, 4);
95 }
97 void pci_conf_write8(
98 unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg,
99 uint8_t data)
100 {
101 BUG_ON((bus > 255) || (dev > 31) || (func > 7) || (reg > 255));
102 pci_conf_write(PCI_CONF_ADDRESS(bus, dev, func, reg), reg & 3, 1, data);
103 }
105 void pci_conf_write16(
106 unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg,
107 uint16_t data)
108 {
109 BUG_ON((bus > 255) || (dev > 31) || (func > 7) || (reg > 255));
110 pci_conf_write(PCI_CONF_ADDRESS(bus, dev, func, reg), reg & 2, 2, data);
111 }
113 void pci_conf_write32(
114 unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg,
115 uint32_t data)
116 {
117 BUG_ON((bus > 255) || (dev > 31) || (func > 7) || (reg > 255));
118 pci_conf_write(PCI_CONF_ADDRESS(bus, dev, func, reg), 0, 4, data);
119 }
121 int pci_find_cap_offset(u8 bus, u8 dev, u8 func, u8 cap)
122 {
123 u8 id;
124 int max_cap = 48;
125 u8 pos = PCI_CAPABILITY_LIST;
126 u16 status;
128 status = pci_conf_read16(bus, dev, func, PCI_STATUS);
129 if ( (status & PCI_STATUS_CAP_LIST) == 0 )
130 return 0;
132 while ( max_cap-- )
133 {
134 pos = pci_conf_read8(bus, dev, func, pos);
135 if ( pos < 0x40 )
136 break;
138 pos &= ~3;
139 id = pci_conf_read8(bus, dev, func, pos + PCI_CAP_LIST_ID);
141 if ( id == 0xff )
142 break;
143 else if ( id == cap )
144 return pos;
146 pos += PCI_CAP_LIST_NEXT;
147 }
149 return 0;
150 }
152 int pci_find_next_cap(u8 bus, unsigned int devfn, u8 pos, int cap)
153 {
154 u8 id;
155 int ttl = 48;
157 while ( ttl-- )
158 {
159 pos = pci_conf_read8(bus, PCI_SLOT(devfn), PCI_FUNC(devfn), pos);
160 if ( pos < 0x40 )
161 break;
163 pos &= ~3;
164 id = pci_conf_read8(bus, PCI_SLOT(devfn), PCI_FUNC(devfn),
165 pos + PCI_CAP_LIST_ID);
167 if ( id == 0xff )
168 break;
169 if ( id == cap )
170 return pos;
172 pos += PCI_CAP_LIST_NEXT;
173 }
174 return 0;
175 }