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