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#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
8
9#include <linux/kernel.h>
10#include <linux/pci.h>
11#include "pciback.h"
12#include "conf_space.h"
13
14struct pci_bar_info {
15	u32 val;
16	u32 len_val;
17	int which;
18};
19
20#define is_enable_cmd(value) ((value)&(PCI_COMMAND_MEMORY|PCI_COMMAND_IO))
21#define is_master_cmd(value) ((value)&PCI_COMMAND_MASTER)
22
23static int command_read(struct pci_dev *dev, int offset, u16 *value, void *data)
24{
25	int i;
26	int ret;
27
28	ret = xen_pcibk_read_config_word(dev, offset, value, data);
29	if (!pci_is_enabled(dev))
30		return ret;
31
32	for (i = 0; i < PCI_ROM_RESOURCE; i++) {
33		if (dev->resource[i].flags & IORESOURCE_IO)
34			*value |= PCI_COMMAND_IO;
35		if (dev->resource[i].flags & IORESOURCE_MEM)
36			*value |= PCI_COMMAND_MEMORY;
37	}
38
39	return ret;
40}
41
42static int command_write(struct pci_dev *dev, int offset, u16 value, void *data)
43{
44	struct xen_pcibk_dev_data *dev_data;
45	int err;
46
47	dev_data = pci_get_drvdata(dev);
48	if (!pci_is_enabled(dev) && is_enable_cmd(value)) {
49		if (unlikely(verbose_request))
50			printk(KERN_DEBUG DRV_NAME ": %s: enable\n",
51			       pci_name(dev));
52		err = pci_enable_device(dev);
53		if (err)
54			return err;
55		if (dev_data)
56			dev_data->enable_intx = 1;
57	} else if (pci_is_enabled(dev) && !is_enable_cmd(value)) {
58		if (unlikely(verbose_request))
59			printk(KERN_DEBUG DRV_NAME ": %s: disable\n",
60			       pci_name(dev));
61		pci_disable_device(dev);
62		if (dev_data)
63			dev_data->enable_intx = 0;
64	}
65
66	if (!dev->is_busmaster && is_master_cmd(value)) {
67		if (unlikely(verbose_request))
68			printk(KERN_DEBUG DRV_NAME ": %s: set bus master\n",
69			       pci_name(dev));
70		pci_set_master(dev);
71	}
72
73	if (value & PCI_COMMAND_INVALIDATE) {
74		if (unlikely(verbose_request))
75			printk(KERN_DEBUG
76			       DRV_NAME ": %s: enable memory-write-invalidate\n",
77			       pci_name(dev));
78		err = pci_set_mwi(dev);
79		if (err) {
80			pr_warn("%s: cannot enable 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
89static 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		pr_warn(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 */
123static 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		pr_warn(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
151static 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		pr_warn(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
166static 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
192static 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
205static 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
218static 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
225static void bar_release(struct pci_dev *dev, int offset, void *data)
226{
227	kfree(data);
228}
229
230static 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
238static 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
246static 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
254static 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
267out:
268	return err;
269}
270
271static 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
341static 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
352static 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
359int 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		pr_err("%s: Unsupported header type %d!\n",
379		       pci_name(dev), dev->hdr_type);
380		break;
381	}
382
383out:
384	return err;
385}
386