Update to 3.4-final.
[linux-flexiantxendom0-3.2.10.git] / drivers / xen / xen-pciback / conf_space_header.c
1 /*
2  * PCI Backend - Handles the virtual fields in the configuration space headers.
3  *
4  * Author: Ryan Wilson <hap9@epoch.ncsc.mil>
5  */
6
7 #include <linux/kernel.h>
8 #include <linux/pci.h>
9 #include "pciback.h"
10 #include "conf_space.h"
11
12 struct pci_bar_info {
13         u32 val;
14         u32 len_val;
15         int which;
16 };
17
18 #define is_enable_cmd(value) ((value)&(PCI_COMMAND_MEMORY|PCI_COMMAND_IO))
19 #define is_master_cmd(value) ((value)&PCI_COMMAND_MASTER)
20
21 static int command_read(struct pci_dev *dev, int offset, u16 *value, void *data)
22 {
23         int i;
24         int ret;
25
26         ret = xen_pcibk_read_config_word(dev, offset, value, data);
27         if (!pci_is_enabled(dev))
28                 return ret;
29
30         for (i = 0; i < PCI_ROM_RESOURCE; i++) {
31                 if (dev->resource[i].flags & IORESOURCE_IO)
32                         *value |= PCI_COMMAND_IO;
33                 if (dev->resource[i].flags & IORESOURCE_MEM)
34                         *value |= PCI_COMMAND_MEMORY;
35         }
36
37         return ret;
38 }
39
40 static int command_write(struct pci_dev *dev, int offset, u16 value, void *data)
41 {
42 #ifndef CONFIG_XEN
43         struct xen_pcibk_dev_data *dev_data = dev_data = pci_get_drvdata(dev);
44 #endif
45         int err;
46
47         if (!pci_is_enabled(dev) && is_enable_cmd(value)) {
48                 if (unlikely(verbose_request))
49                         printk(KERN_DEBUG DRV_NAME ": %s: enable\n",
50                                pci_name(dev));
51                 err = pci_enable_device(dev);
52                 if (err)
53                         return err;
54 #ifndef CONFIG_XEN
55                 if (dev_data)
56                         dev_data->enable_intx = 1;
57 #endif
58         } else if (pci_is_enabled(dev) && !is_enable_cmd(value)) {
59                 if (unlikely(verbose_request))
60                         printk(KERN_DEBUG DRV_NAME ": %s: disable\n",
61                                pci_name(dev));
62                 pci_disable_device(dev);
63 #ifndef CONFIG_XEN
64                 if (dev_data)
65                         dev_data->enable_intx = 0;
66 #endif
67         }
68
69         if (!dev->is_busmaster && is_master_cmd(value)) {
70                 if (unlikely(verbose_request))
71                         printk(KERN_DEBUG DRV_NAME ": %s: set bus master\n",
72                                pci_name(dev));
73                 pci_set_master(dev);
74         }
75
76         if (value & PCI_COMMAND_INVALIDATE) {
77                 if (unlikely(verbose_request))
78                         printk(KERN_DEBUG
79                                DRV_NAME ": %s: enable memory-write-invalidate\n",
80                                pci_name(dev));
81                 err = pci_set_mwi(dev);
82                 if (err) {
83                         printk(KERN_WARNING
84                                DRV_NAME ": %s: cannot enable "
85                                "memory-write-invalidate (%d)\n",
86                                pci_name(dev), err);
87                         value &= ~PCI_COMMAND_INVALIDATE;
88                 }
89         }
90
91         return pci_write_config_word(dev, offset, value);
92 }
93
94 static int rom_write(struct pci_dev *dev, int offset, u32 value, void *data)
95 {
96         struct pci_bar_info *bar = data;
97
98         if (unlikely(!bar)) {
99                 printk(KERN_WARNING DRV_NAME ": driver data not found for %s\n",
100                        pci_name(dev));
101                 return XEN_PCI_ERR_op_failed;
102         }
103
104         /* A write to obtain the length must happen as a 32-bit write.
105          * This does not (yet) support writing individual bytes
106          */
107         if (value == ~PCI_ROM_ADDRESS_ENABLE)
108                 bar->which = 1;
109         else {
110                 u32 tmpval;
111                 pci_read_config_dword(dev, offset, &tmpval);
112                 if (tmpval != bar->val && value == bar->val) {
113                         /* Allow restoration of bar value. */
114                         pci_write_config_dword(dev, offset, bar->val);
115                 }
116                 bar->which = 0;
117         }
118
119         /* Do we need to support enabling/disabling the rom address here? */
120
121         return 0;
122 }
123
124 /* For the BARs, only allow writes which write ~0 or
125  * the correct resource information
126  * (Needed for when the driver probes the resource usage)
127  */
128 static int bar_write(struct pci_dev *dev, int offset, u32 value, void *data)
129 {
130         struct pci_bar_info *bar = data;
131
132         if (unlikely(!bar)) {
133                 printk(KERN_WARNING DRV_NAME ": driver data not found for %s\n",
134                        pci_name(dev));
135                 return XEN_PCI_ERR_op_failed;
136         }
137
138         /* A write to obtain the length must happen as a 32-bit write.
139          * This does not (yet) support writing individual bytes
140          */
141         if (value == ~0)
142                 bar->which = 1;
143         else {
144                 u32 tmpval;
145                 pci_read_config_dword(dev, offset, &tmpval);
146                 if (tmpval != bar->val && value == bar->val) {
147                         /* Allow restoration of bar value. */
148                         pci_write_config_dword(dev, offset, bar->val);
149                 }
150                 bar->which = 0;
151         }
152
153         return 0;
154 }
155
156 static int bar_read(struct pci_dev *dev, int offset, u32 * value, void *data)
157 {
158         struct pci_bar_info *bar = data;
159
160         if (unlikely(!bar)) {
161                 printk(KERN_WARNING DRV_NAME ": driver data not found for %s\n",
162                        pci_name(dev));
163                 return XEN_PCI_ERR_op_failed;
164         }
165
166         *value = bar->which ? bar->len_val : bar->val;
167
168         return 0;
169 }
170
171 static inline void read_dev_bar(struct pci_dev *dev,
172                                 struct pci_bar_info *bar_info, int offset,
173                                 u32 len_mask)
174 {
175         int     pos;
176         struct resource *res = dev->resource;
177
178         if (offset == PCI_ROM_ADDRESS || offset == PCI_ROM_ADDRESS1)
179                 pos = PCI_ROM_RESOURCE;
180         else {
181                 pos = (offset - PCI_BASE_ADDRESS_0) / 4;
182                 if (pos && ((res[pos - 1].flags & (PCI_BASE_ADDRESS_SPACE |
183                                 PCI_BASE_ADDRESS_MEM_TYPE_MASK)) ==
184                            (PCI_BASE_ADDRESS_SPACE_MEMORY |
185                                 PCI_BASE_ADDRESS_MEM_TYPE_64))) {
186                         bar_info->val = res[pos - 1].start >> 32;
187                         bar_info->len_val = res[pos - 1].end >> 32;
188                         return;
189                 }
190         }
191
192         bar_info->val = res[pos].start |
193                         (res[pos].flags & PCI_REGION_FLAG_MASK);
194         bar_info->len_val = resource_size(&res[pos]);
195 }
196
197 static void *bar_init(struct pci_dev *dev, int offset)
198 {
199         struct pci_bar_info *bar = kmalloc(sizeof(*bar), GFP_KERNEL);
200
201         if (!bar)
202                 return ERR_PTR(-ENOMEM);
203
204         read_dev_bar(dev, bar, offset, ~0);
205         bar->which = 0;
206
207         return bar;
208 }
209
210 static void *rom_init(struct pci_dev *dev, int offset)
211 {
212         struct pci_bar_info *bar = kmalloc(sizeof(*bar), GFP_KERNEL);
213
214         if (!bar)
215                 return ERR_PTR(-ENOMEM);
216
217         read_dev_bar(dev, bar, offset, ~PCI_ROM_ADDRESS_ENABLE);
218         bar->which = 0;
219
220         return bar;
221 }
222
223 static void bar_reset(struct pci_dev *dev, int offset, void *data)
224 {
225         struct pci_bar_info *bar = data;
226
227         bar->which = 0;
228 }
229
230 static void bar_release(struct pci_dev *dev, int offset, void *data)
231 {
232         kfree(data);
233 }
234
235 static int xen_pcibk_read_vendor(struct pci_dev *dev, int offset,
236                                u16 *value, void *data)
237 {
238         *value = dev->vendor;
239
240         return 0;
241 }
242
243 static int xen_pcibk_read_device(struct pci_dev *dev, int offset,
244                                u16 *value, void *data)
245 {
246         *value = dev->device;
247
248         return 0;
249 }
250
251 static int interrupt_read(struct pci_dev *dev, int offset, u8 * value,
252                           void *data)
253 {
254         *value = (u8) dev->irq;
255
256         return 0;
257 }
258
259 static int bist_write(struct pci_dev *dev, int offset, u8 value, void *data)
260 {
261         u8 cur_value;
262         int err;
263
264         err = pci_read_config_byte(dev, offset, &cur_value);
265         if (err)
266                 goto out;
267
268         if ((cur_value & ~PCI_BIST_START) == (value & ~PCI_BIST_START)
269             || value == PCI_BIST_START)
270                 err = pci_write_config_byte(dev, offset, value);
271
272 out:
273         return err;
274 }
275
276 static const struct config_field header_common[] = {
277         {
278          .offset    = PCI_VENDOR_ID,
279          .size      = 2,
280          .u.w.read  = xen_pcibk_read_vendor,
281         },
282         {
283          .offset    = PCI_DEVICE_ID,
284          .size      = 2,
285          .u.w.read  = xen_pcibk_read_device,
286         },
287         {
288          .offset    = PCI_COMMAND,
289          .size      = 2,
290          .u.w.read  = command_read,
291          .u.w.write = command_write,
292         },
293         {
294          .offset    = PCI_INTERRUPT_LINE,
295          .size      = 1,
296          .u.b.read  = interrupt_read,
297         },
298         {
299          .offset    = PCI_INTERRUPT_PIN,
300          .size      = 1,
301          .u.b.read  = xen_pcibk_read_config_byte,
302         },
303         {
304          /* Any side effects of letting driver domain control cache line? */
305          .offset    = PCI_CACHE_LINE_SIZE,
306          .size      = 1,
307          .u.b.read  = xen_pcibk_read_config_byte,
308          .u.b.write = xen_pcibk_write_config_byte,
309         },
310         {
311          .offset    = PCI_LATENCY_TIMER,
312          .size      = 1,
313          .u.b.read  = xen_pcibk_read_config_byte,
314         },
315         {
316          .offset    = PCI_BIST,
317          .size      = 1,
318          .u.b.read  = xen_pcibk_read_config_byte,
319          .u.b.write = bist_write,
320         },
321         {}
322 };
323
324 #define CFG_FIELD_BAR(reg_offset)                       \
325         {                                               \
326         .offset     = reg_offset,                       \
327         .size       = 4,                                \
328         .init       = bar_init,                         \
329         .reset      = bar_reset,                        \
330         .release    = bar_release,                      \
331         .u.dw.read  = bar_read,                         \
332         .u.dw.write = bar_write,                        \
333         }
334
335 #define CFG_FIELD_ROM(reg_offset)                       \
336         {                                               \
337         .offset     = reg_offset,                       \
338         .size       = 4,                                \
339         .init       = rom_init,                         \
340         .reset      = bar_reset,                        \
341         .release    = bar_release,                      \
342         .u.dw.read  = bar_read,                         \
343         .u.dw.write = rom_write,                        \
344         }
345
346 static const struct config_field header_0[] = {
347         CFG_FIELD_BAR(PCI_BASE_ADDRESS_0),
348         CFG_FIELD_BAR(PCI_BASE_ADDRESS_1),
349         CFG_FIELD_BAR(PCI_BASE_ADDRESS_2),
350         CFG_FIELD_BAR(PCI_BASE_ADDRESS_3),
351         CFG_FIELD_BAR(PCI_BASE_ADDRESS_4),
352         CFG_FIELD_BAR(PCI_BASE_ADDRESS_5),
353         CFG_FIELD_ROM(PCI_ROM_ADDRESS),
354         {}
355 };
356
357 static const struct config_field header_1[] = {
358         CFG_FIELD_BAR(PCI_BASE_ADDRESS_0),
359         CFG_FIELD_BAR(PCI_BASE_ADDRESS_1),
360         CFG_FIELD_ROM(PCI_ROM_ADDRESS1),
361         {}
362 };
363
364 int xen_pcibk_config_header_add_fields(struct pci_dev *dev)
365 {
366         int err;
367
368         err = xen_pcibk_config_add_fields(dev, header_common);
369         if (err)
370                 goto out;
371
372         switch (dev->hdr_type) {
373         case PCI_HEADER_TYPE_NORMAL:
374                 err = xen_pcibk_config_add_fields(dev, header_0);
375                 break;
376
377         case PCI_HEADER_TYPE_BRIDGE:
378                 err = xen_pcibk_config_add_fields(dev, header_1);
379                 break;
380
381         default:
382                 err = -EINVAL;
383                 printk(KERN_ERR DRV_NAME ": %s: Unsupported header type %d!\n",
384                        pci_name(dev), dev->hdr_type);
385                 break;
386         }
387
388 out:
389         return err;
390 }