2 * The PCI Library -- Virtual Emulated Config Space Access Functions
4 * Copyright (c) 2022 Pali Rohár
6 * Can be freely distributed and used under the terms of the GNU GPL.
12 ioflg_to_pciflg(pciaddr_t ioflg)
16 if ((ioflg & PCI_IORESOURCE_TYPE_BITS) == PCI_IORESOURCE_IO)
17 flg = PCI_BASE_ADDRESS_SPACE_IO;
18 else if ((ioflg & PCI_IORESOURCE_TYPE_BITS) == PCI_IORESOURCE_MEM)
20 flg = PCI_BASE_ADDRESS_SPACE_MEMORY;
21 if (ioflg & PCI_IORESOURCE_MEM_64)
22 flg |= PCI_BASE_ADDRESS_MEM_TYPE_64;
24 flg |= PCI_BASE_ADDRESS_MEM_TYPE_32;
25 if (ioflg & PCI_IORESOURCE_PREFETCH)
26 flg |= PCI_BASE_ADDRESS_MEM_PREFETCH;
33 baseres_to_pcires(pciaddr_t addr, pciaddr_t ioflg, int *have_sec, u32 *sec_val)
35 u32 val = ioflg_to_pciflg(ioflg);
40 if ((val & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO && addr <= 0xffffffff)
41 val |= addr & PCI_BASE_ADDRESS_IO_MASK;
42 else if ((val & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_MEMORY)
44 val |= addr & PCI_BASE_ADDRESS_MEM_MASK;
45 if ((val & PCI_BASE_ADDRESS_MEM_TYPE_64) && have_sec)
48 *sec_val = addr >> 32;
56 even_baseres_to_pcires(pciaddr_t addr, pciaddr_t ioflg)
58 return baseres_to_pcires(addr, ioflg, NULL, NULL);
62 odd_baseres_to_pcires(pciaddr_t addr0, pciaddr_t ioflg0, pciaddr_t addr, pciaddr_t ioflg)
66 baseres_to_pcires(addr0, ioflg0, &have_sec, &val);
68 val = baseres_to_pcires(addr, ioflg, NULL, NULL);
73 pci_emulated_read(struct pci_dev *d, int pos, byte *buf, int len)
75 u32 ht = PCI_HEADER_TYPE_NORMAL;
83 return pci_generic_block_read(d, pos, buf, len);
85 if (d->device_class == PCI_CLASS_BRIDGE_PCI)
86 ht = PCI_HEADER_TYPE_BRIDGE;
87 else if (d->device_class == PCI_CLASS_BRIDGE_CARDBUS)
88 ht = PCI_HEADER_TYPE_CARDBUS;
93 for (i = 0; i < 6; i++)
97 if ((d->flags[i] & PCI_IORESOURCE_TYPE_BITS) == PCI_IORESOURCE_IO)
98 val |= PCI_COMMAND_IO;
99 else if ((d->flags[i] & PCI_IORESOURCE_TYPE_BITS) == PCI_IORESOURCE_MEM)
100 val |= PCI_COMMAND_MEMORY;
104 val = (d->device_id << 16) | d->vendor_id;
106 case PCI_CLASS_REVISION:
107 val = (d->device_class << 16) | (d->prog_if << 8) | d->rev_id;
109 case PCI_CACHE_LINE_SIZE:
112 case PCI_BASE_ADDRESS_0:
113 val = even_baseres_to_pcires(d->base_addr[0], d->flags[0]);
115 case PCI_INTERRUPT_LINE:
116 val = (d->irq >= 0 && d->irq <= 0xff) ? d->irq : 0;
120 if ((pos & ~3) == PCI_BASE_ADDRESS_1 && (ht == PCI_HEADER_TYPE_NORMAL || ht == PCI_HEADER_TYPE_BRIDGE))
121 val = odd_baseres_to_pcires(d->base_addr[0], d->flags[0], d->base_addr[1], d->flags[1]);
123 if (ht == PCI_HEADER_TYPE_NORMAL)
126 case PCI_BASE_ADDRESS_2:
127 val = even_baseres_to_pcires(d->base_addr[2], d->flags[2]);
129 case PCI_BASE_ADDRESS_3:
130 val = odd_baseres_to_pcires(d->base_addr[2], d->flags[2], d->base_addr[3], d->flags[3]);
132 case PCI_BASE_ADDRESS_4:
133 val = even_baseres_to_pcires(d->base_addr[4], d->flags[4]);
135 case PCI_BASE_ADDRESS_5:
136 val = odd_baseres_to_pcires(d->base_addr[4], d->flags[4], d->base_addr[5], d->flags[5]);
138 case PCI_SUBSYSTEM_VENDOR_ID:
139 val = (d->subsys_id << 16) | d->subsys_vendor_id;
141 case PCI_ROM_ADDRESS:
142 val = d->rom_base_addr & PCI_ROM_ADDRESS_MASK;
144 val |= PCI_ROM_ADDRESS_ENABLE;
147 else if (ht == PCI_HEADER_TYPE_BRIDGE)
151 if (d->bridge_size[0])
152 val |= PCI_COMMAND_IO;
153 if (d->bridge_size[1] || d->bridge_size[2])
154 val |= PCI_COMMAND_MEMORY;
156 case PCI_PRIMARY_BUS:
160 if (d->bridge_size[0])
162 val = (((((d->bridge_base_addr[0] + d->bridge_size[0] - 1) >> 8) & PCI_IO_RANGE_MASK) << 8) & 0xff00) |
163 (((d->bridge_base_addr[0] >> 8) & PCI_IO_RANGE_MASK) & 0x00ff);
164 if ((d->bridge_flags[0] & PCI_IORESOURCE_IO_16BIT_ADDR) &&
165 d->bridge_base_addr[0] + d->bridge_size[0] - 1 <= 0xffff)
166 val |= (PCI_IO_RANGE_TYPE_16 << 8) | PCI_IO_RANGE_TYPE_16;
168 val |= (PCI_IO_RANGE_TYPE_32 << 8) | PCI_IO_RANGE_TYPE_32;
171 val = 0xff & PCI_IO_RANGE_MASK;
173 case PCI_MEMORY_BASE:
174 if (d->bridge_size[1])
175 val = (((((d->bridge_base_addr[1] + d->bridge_size[1] - 1) >> 16) & PCI_MEMORY_RANGE_MASK) << 16) & 0xffff0000) |
176 (((d->bridge_base_addr[1] >> 16) & PCI_MEMORY_RANGE_MASK) & 0x0000ffff);
178 val = 0xffff & PCI_MEMORY_RANGE_MASK;
180 case PCI_PREF_MEMORY_BASE:
181 if (d->bridge_size[2])
183 val = (((((d->bridge_base_addr[2] + d->bridge_size[2] - 1) >> 16) & PCI_PREF_RANGE_MASK) << 16) & 0xffff0000) |
184 (((d->bridge_base_addr[2] >> 16) & PCI_PREF_RANGE_MASK) & 0x0000ffff);
185 if ((d->bridge_flags[2] & PCI_IORESOURCE_MEM_64) ||
186 d->bridge_base_addr[2] + d->bridge_size[2] - 1 > 0xffffffff)
187 val |= (PCI_PREF_RANGE_TYPE_64 << 16) | PCI_PREF_RANGE_TYPE_64;
189 val |= (PCI_PREF_RANGE_TYPE_32 << 16) | PCI_PREF_RANGE_TYPE_32;
192 val = 0xffff & PCI_PREF_RANGE_MASK;
194 case PCI_PREF_BASE_UPPER32:
195 if (d->bridge_size[2])
196 val = d->bridge_base_addr[2] >> 32;
198 case PCI_PREF_LIMIT_UPPER32:
199 if (d->bridge_size[2])
200 val = (d->bridge_base_addr[2] + d->bridge_size[2] - 1) >> 32;
202 case PCI_IO_BASE_UPPER16:
203 if (d->bridge_size[0])
204 val = ((((d->bridge_base_addr[0] + d->bridge_size[0] - 1) >> 16) << 16) & 0xffff0000) |
205 ((d->bridge_base_addr[0] >> 16) & 0x0000ffff);
207 case PCI_ROM_ADDRESS1:
208 val = d->rom_base_addr & PCI_ROM_ADDRESS_MASK;
210 val |= PCI_ROM_ADDRESS_ENABLE;
213 else if (ht == PCI_HEADER_TYPE_CARDBUS)
217 if (d->bridge_size[0] || d->bridge_size[1])
218 val |= PCI_COMMAND_MEMORY;
219 if (d->bridge_size[2] || d->bridge_size[3])
220 val |= PCI_COMMAND_IO;
222 case PCI_CB_PRIMARY_BUS:
225 case PCI_CB_MEMORY_BASE_0:
226 if (d->bridge_size[0])
227 val = d->bridge_base_addr[0] & ~0xfff;
229 val = 0xffffffff & ~0xfff;
231 case PCI_CB_MEMORY_LIMIT_0:
232 if (d->bridge_size[0])
233 val = (d->bridge_base_addr[0] + d->bridge_size[0] - 1) & ~0xfff;
235 case PCI_CB_MEMORY_BASE_1:
236 if (d->bridge_size[1])
237 val = d->bridge_base_addr[1] & ~0xfff;
239 val = 0xffffffff & ~0xfff;
241 case PCI_CB_MEMORY_LIMIT_1:
242 if (d->bridge_size[1])
243 val = (d->bridge_base_addr[1] + d->bridge_size[1] - 1) & ~0xfff;
245 case PCI_CB_IO_BASE_0:
246 if (d->bridge_size[2])
248 val = d->bridge_base_addr[2] & PCI_CB_IO_RANGE_MASK;
249 if ((d->bridge_flags[2] & PCI_IORESOURCE_IO_16BIT_ADDR) ||
250 d->bridge_base_addr[2] + d->bridge_size[2] - 1 <= 0xffff)
251 val |= PCI_IO_RANGE_TYPE_16;
253 val |= PCI_IO_RANGE_TYPE_32;
256 val = 0x0000ffff & PCI_CB_IO_RANGE_MASK;
258 case PCI_CB_IO_LIMIT_0:
259 if (d->bridge_size[2])
260 val = (d->bridge_base_addr[2] + d->bridge_size[2] - 1) & PCI_CB_IO_RANGE_MASK;
262 case PCI_CB_IO_BASE_1:
263 if (d->bridge_size[3])
265 val = d->bridge_base_addr[3] & PCI_CB_IO_RANGE_MASK;
266 if ((d->bridge_flags[3] & PCI_IORESOURCE_IO_16BIT_ADDR) ||
267 d->bridge_base_addr[3] + d->bridge_size[3] - 1 <= 0xffff)
268 val |= PCI_IO_RANGE_TYPE_16;
270 val |= PCI_IO_RANGE_TYPE_32;
273 val = 0x0000ffff & PCI_CB_IO_RANGE_MASK;
275 case PCI_CB_IO_LIMIT_1:
276 if (d->bridge_size[3])
277 val = (d->bridge_base_addr[3] + d->bridge_size[3] - 1) & PCI_CB_IO_RANGE_MASK;
279 case PCI_CB_BRIDGE_CONTROL:
280 if (d->bridge_flags[0] & PCI_IORESOURCE_PREFETCH)
281 val |= PCI_CB_BRIDGE_CTL_PREFETCH_MEM0;
282 if (d->bridge_flags[1] & PCI_IORESOURCE_PREFETCH)
283 val |= PCI_CB_BRIDGE_CTL_PREFETCH_MEM1;
285 case PCI_CB_SUBSYSTEM_VENDOR_ID:
286 val = (d->subsys_id << 16) | d->subsys_vendor_id;
291 val = (val >> (8 * (pos & 3))) & ((1 << (len * 8)) - 1);
295 *(buf++) = val & 0xff;