1 /*
2 * The PCI Library -- Virtual Emulated Config Space Access Functions
3 *
4 * Copyright (c) 2022 Pali Rohár
5 *
6 * Can be freely distributed and used under the terms of the GNU GPL v2+.
7 *
8 * SPDX-License-Identifier: GPL-2.0-or-later
9 */
10
11 #include "internal.h"
12
13 static u32
ioflg_to_pciflg(pciaddr_t ioflg)14 ioflg_to_pciflg(pciaddr_t ioflg)
15 {
16 u32 flg = 0;
17
18 if ((ioflg & PCI_IORESOURCE_TYPE_BITS) == PCI_IORESOURCE_IO)
19 flg = PCI_BASE_ADDRESS_SPACE_IO;
20 else if ((ioflg & PCI_IORESOURCE_TYPE_BITS) == PCI_IORESOURCE_MEM)
21 {
22 flg = PCI_BASE_ADDRESS_SPACE_MEMORY;
23 if (ioflg & PCI_IORESOURCE_MEM_64)
24 flg |= PCI_BASE_ADDRESS_MEM_TYPE_64;
25 else
26 flg |= PCI_BASE_ADDRESS_MEM_TYPE_32;
27 if (ioflg & PCI_IORESOURCE_PREFETCH)
28 flg |= PCI_BASE_ADDRESS_MEM_PREFETCH;
29 }
30
31 return flg;
32 }
33
34 static u32
baseres_to_pcires(pciaddr_t addr,pciaddr_t ioflg,int * have_sec,u32 * sec_val)35 baseres_to_pcires(pciaddr_t addr, pciaddr_t ioflg, int *have_sec, u32 *sec_val)
36 {
37 u32 val = ioflg_to_pciflg(ioflg);
38
39 if (have_sec)
40 *have_sec = 0;
41
42 if ((val & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO && addr <= 0xffffffff)
43 val |= addr & PCI_BASE_ADDRESS_IO_MASK;
44 else if ((val & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_MEMORY)
45 {
46 val |= addr & PCI_BASE_ADDRESS_MEM_MASK;
47 if ((val & PCI_BASE_ADDRESS_MEM_TYPE_64) && have_sec)
48 {
49 *have_sec = 1;
50 *sec_val = addr >> 32;
51 }
52 }
53
54 return val;
55 }
56
57 static inline u32
even_baseres_to_pcires(pciaddr_t addr,pciaddr_t ioflg)58 even_baseres_to_pcires(pciaddr_t addr, pciaddr_t ioflg)
59 {
60 return baseres_to_pcires(addr, ioflg, NULL, NULL);
61 }
62
63 static inline u32
odd_baseres_to_pcires(pciaddr_t addr0,pciaddr_t ioflg0,pciaddr_t addr,pciaddr_t ioflg)64 odd_baseres_to_pcires(pciaddr_t addr0, pciaddr_t ioflg0, pciaddr_t addr, pciaddr_t ioflg)
65 {
66 int have_sec;
67 u32 val;
68 baseres_to_pcires(addr0, ioflg0, &have_sec, &val);
69 if (!have_sec)
70 val = baseres_to_pcires(addr, ioflg, NULL, NULL);
71 return val;
72 }
73
74 int
pci_emulated_read(struct pci_dev * d,int pos,byte * buf,int len)75 pci_emulated_read(struct pci_dev *d, int pos, byte *buf, int len)
76 {
77 u32 ht = PCI_HEADER_TYPE_NORMAL;
78 u32 val = 0;
79 int i;
80
81 if (pos >= 64)
82 return 0;
83
84 if (len > 4)
85 return pci_generic_block_read(d, pos, buf, len);
86
87 if (d->device_class == PCI_CLASS_BRIDGE_PCI)
88 ht = PCI_HEADER_TYPE_BRIDGE;
89 else if (d->device_class == PCI_CLASS_BRIDGE_CARDBUS)
90 ht = PCI_HEADER_TYPE_CARDBUS;
91
92 switch (pos & ~3)
93 {
94 case PCI_COMMAND:
95 for (i = 0; i < 6; i++)
96 {
97 if (!d->size[i])
98 continue;
99 if ((d->flags[i] & PCI_IORESOURCE_TYPE_BITS) == PCI_IORESOURCE_IO)
100 val |= PCI_COMMAND_IO;
101 else if ((d->flags[i] & PCI_IORESOURCE_TYPE_BITS) == PCI_IORESOURCE_MEM)
102 val |= PCI_COMMAND_MEMORY;
103 }
104 break;
105 case PCI_VENDOR_ID:
106 val = (d->device_id << 16) | d->vendor_id;
107 break;
108 case PCI_CLASS_REVISION:
109 val = (d->device_class << 16) | (d->prog_if << 8) | d->rev_id;
110 break;
111 case PCI_CACHE_LINE_SIZE:
112 val = ht << 16;
113 break;
114 case PCI_BASE_ADDRESS_0:
115 val = even_baseres_to_pcires(d->base_addr[0], d->flags[0]);
116 break;
117 case PCI_INTERRUPT_LINE:
118 val = (d->irq >= 0 && d->irq <= 0xff) ? d->irq : 0;
119 break;
120 }
121
122 if ((pos & ~3) == PCI_BASE_ADDRESS_1 && (ht == PCI_HEADER_TYPE_NORMAL || ht == PCI_HEADER_TYPE_BRIDGE))
123 val = odd_baseres_to_pcires(d->base_addr[0], d->flags[0], d->base_addr[1], d->flags[1]);
124
125 if (ht == PCI_HEADER_TYPE_NORMAL)
126 switch (pos & ~3)
127 {
128 case PCI_BASE_ADDRESS_2:
129 val = even_baseres_to_pcires(d->base_addr[2], d->flags[2]);
130 break;
131 case PCI_BASE_ADDRESS_3:
132 val = odd_baseres_to_pcires(d->base_addr[2], d->flags[2], d->base_addr[3], d->flags[3]);
133 break;
134 case PCI_BASE_ADDRESS_4:
135 val = even_baseres_to_pcires(d->base_addr[4], d->flags[4]);
136 break;
137 case PCI_BASE_ADDRESS_5:
138 val = odd_baseres_to_pcires(d->base_addr[4], d->flags[4], d->base_addr[5], d->flags[5]);
139 break;
140 case PCI_SUBSYSTEM_VENDOR_ID:
141 val = (d->subsys_id << 16) | d->subsys_vendor_id;
142 break;
143 case PCI_ROM_ADDRESS:
144 val = d->rom_base_addr & PCI_ROM_ADDRESS_MASK;
145 if (val)
146 val |= PCI_ROM_ADDRESS_ENABLE;
147 break;
148 }
149 else if (ht == PCI_HEADER_TYPE_BRIDGE)
150 switch (pos & ~3)
151 {
152 case PCI_COMMAND:
153 if (d->bridge_size[0])
154 val |= PCI_COMMAND_IO;
155 if (d->bridge_size[1] || d->bridge_size[2])
156 val |= PCI_COMMAND_MEMORY;
157 break;
158 case PCI_PRIMARY_BUS:
159 val = d->bus;
160 break;
161 case PCI_IO_BASE:
162 if (d->bridge_size[0])
163 {
164 val = (((((d->bridge_base_addr[0] + d->bridge_size[0] - 1) >> 8) & PCI_IO_RANGE_MASK) << 8) & 0xff00) |
165 (((d->bridge_base_addr[0] >> 8) & PCI_IO_RANGE_MASK) & 0x00ff);
166 if ((d->bridge_flags[0] & PCI_IORESOURCE_IO_16BIT_ADDR) &&
167 d->bridge_base_addr[0] + d->bridge_size[0] - 1 <= 0xffff)
168 val |= (PCI_IO_RANGE_TYPE_16 << 8) | PCI_IO_RANGE_TYPE_16;
169 else
170 val |= (PCI_IO_RANGE_TYPE_32 << 8) | PCI_IO_RANGE_TYPE_32;
171 }
172 else
173 val = 0xff & PCI_IO_RANGE_MASK;
174 break;
175 case PCI_MEMORY_BASE:
176 if (d->bridge_size[1])
177 val = (((((d->bridge_base_addr[1] + d->bridge_size[1] - 1) >> 16) & PCI_MEMORY_RANGE_MASK) << 16) & 0xffff0000) |
178 (((d->bridge_base_addr[1] >> 16) & PCI_MEMORY_RANGE_MASK) & 0x0000ffff);
179 else
180 val = 0xffff & PCI_MEMORY_RANGE_MASK;
181 break;
182 case PCI_PREF_MEMORY_BASE:
183 if (d->bridge_size[2])
184 {
185 val = (((((d->bridge_base_addr[2] + d->bridge_size[2] - 1) >> 16) & PCI_PREF_RANGE_MASK) << 16) & 0xffff0000) |
186 (((d->bridge_base_addr[2] >> 16) & PCI_PREF_RANGE_MASK) & 0x0000ffff);
187 if ((d->bridge_flags[2] & PCI_IORESOURCE_MEM_64) ||
188 d->bridge_base_addr[2] + d->bridge_size[2] - 1 > 0xffffffff)
189 val |= (PCI_PREF_RANGE_TYPE_64 << 16) | PCI_PREF_RANGE_TYPE_64;
190 else
191 val |= (PCI_PREF_RANGE_TYPE_32 << 16) | PCI_PREF_RANGE_TYPE_32;
192 }
193 else
194 val = 0xffff & PCI_PREF_RANGE_MASK;
195 break;
196 case PCI_PREF_BASE_UPPER32:
197 if (d->bridge_size[2])
198 val = d->bridge_base_addr[2] >> 32;
199 break;
200 case PCI_PREF_LIMIT_UPPER32:
201 if (d->bridge_size[2])
202 val = (d->bridge_base_addr[2] + d->bridge_size[2] - 1) >> 32;
203 break;
204 case PCI_IO_BASE_UPPER16:
205 if (d->bridge_size[0])
206 val = ((((d->bridge_base_addr[0] + d->bridge_size[0] - 1) >> 16) << 16) & 0xffff0000) |
207 ((d->bridge_base_addr[0] >> 16) & 0x0000ffff);
208 break;
209 case PCI_ROM_ADDRESS1:
210 val = d->rom_base_addr & PCI_ROM_ADDRESS_MASK;
211 if (val)
212 val |= PCI_ROM_ADDRESS_ENABLE;
213 break;
214 }
215 else if (ht == PCI_HEADER_TYPE_CARDBUS)
216 switch (pos & ~3)
217 {
218 case PCI_COMMAND:
219 if (d->bridge_size[0] || d->bridge_size[1])
220 val |= PCI_COMMAND_MEMORY;
221 if (d->bridge_size[2] || d->bridge_size[3])
222 val |= PCI_COMMAND_IO;
223 break;
224 case PCI_CB_PRIMARY_BUS:
225 val = d->bus;
226 break;
227 case PCI_CB_MEMORY_BASE_0:
228 if (d->bridge_size[0])
229 val = d->bridge_base_addr[0] & ~0xfff;
230 else
231 val = 0xffffffff & ~0xfff;
232 break;
233 case PCI_CB_MEMORY_LIMIT_0:
234 if (d->bridge_size[0])
235 val = (d->bridge_base_addr[0] + d->bridge_size[0] - 1) & ~0xfff;
236 break;
237 case PCI_CB_MEMORY_BASE_1:
238 if (d->bridge_size[1])
239 val = d->bridge_base_addr[1] & ~0xfff;
240 else
241 val = 0xffffffff & ~0xfff;
242 break;
243 case PCI_CB_MEMORY_LIMIT_1:
244 if (d->bridge_size[1])
245 val = (d->bridge_base_addr[1] + d->bridge_size[1] - 1) & ~0xfff;
246 break;
247 case PCI_CB_IO_BASE_0:
248 if (d->bridge_size[2])
249 {
250 val = d->bridge_base_addr[2] & PCI_CB_IO_RANGE_MASK;
251 if ((d->bridge_flags[2] & PCI_IORESOURCE_IO_16BIT_ADDR) ||
252 d->bridge_base_addr[2] + d->bridge_size[2] - 1 <= 0xffff)
253 val |= PCI_IO_RANGE_TYPE_16;
254 else
255 val |= PCI_IO_RANGE_TYPE_32;
256 }
257 else
258 val = 0x0000ffff & PCI_CB_IO_RANGE_MASK;
259 break;
260 case PCI_CB_IO_LIMIT_0:
261 if (d->bridge_size[2])
262 val = (d->bridge_base_addr[2] + d->bridge_size[2] - 1) & PCI_CB_IO_RANGE_MASK;
263 break;
264 case PCI_CB_IO_BASE_1:
265 if (d->bridge_size[3])
266 {
267 val = d->bridge_base_addr[3] & PCI_CB_IO_RANGE_MASK;
268 if ((d->bridge_flags[3] & PCI_IORESOURCE_IO_16BIT_ADDR) ||
269 d->bridge_base_addr[3] + d->bridge_size[3] - 1 <= 0xffff)
270 val |= PCI_IO_RANGE_TYPE_16;
271 else
272 val |= PCI_IO_RANGE_TYPE_32;
273 }
274 else
275 val = 0x0000ffff & PCI_CB_IO_RANGE_MASK;
276 break;
277 case PCI_CB_IO_LIMIT_1:
278 if (d->bridge_size[3])
279 val = (d->bridge_base_addr[3] + d->bridge_size[3] - 1) & PCI_CB_IO_RANGE_MASK;
280 break;
281 case PCI_CB_BRIDGE_CONTROL:
282 if (d->bridge_flags[0] & PCI_IORESOURCE_PREFETCH)
283 val |= PCI_CB_BRIDGE_CTL_PREFETCH_MEM0;
284 if (d->bridge_flags[1] & PCI_IORESOURCE_PREFETCH)
285 val |= PCI_CB_BRIDGE_CTL_PREFETCH_MEM1;
286 break;
287 case PCI_CB_SUBSYSTEM_VENDOR_ID:
288 val = (d->subsys_id << 16) | d->subsys_vendor_id;
289 break;
290 }
291
292 if (len <= 2)
293 val = (val >> (8 * (pos & 3))) & ((1 << (len * 8)) - 1);
294
295 while (len-- > 0)
296 {
297 *(buf++) = val & 0xff;
298 val >>= 8;
299 }
300 return 1;
301 }
302