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