Commit ee0ea1d0dda935aa13e6562ee32d37d441b43490

Authored by bellard
1 parent 02a1602e

moved PCI init to BIOS - added ISA memory mapping registers and SMM support


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2174 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 1 changed file with 123 additions and 225 deletions
hw/piix_pci.c
@@ -52,7 +52,123 @@ static int pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num) @@ -52,7 +52,123 @@ static int pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num)
52 return (irq_num + slot_addend) & 3; 52 return (irq_num + slot_addend) & 3;
53 } 53 }
54 54
55 -PCIBus *i440fx_init(void) 55 +static uint32_t isa_page_descs[384 / 4];
  56 +static uint8_t smm_enabled;
  57 +
  58 +static const uint32_t mar_addresses[15] = {
  59 + 0xa0000,
  60 + 0xc0000,
  61 + 0xc4000,
  62 + 0xc8000,
  63 + 0xcc000,
  64 + 0xd0000,
  65 + 0xd4000,
  66 + 0xd8000,
  67 + 0xdc000,
  68 + 0xe0000,
  69 + 0xe4000,
  70 + 0xe8000,
  71 + 0xec000,
  72 + 0xf0000,
  73 + 0x100000,
  74 +};
  75 +
  76 +static void i440fx_update_memory_mappings(PCIDevice *d)
  77 +{
  78 + int i, r;
  79 + uint32_t start, end, addr;
  80 + uint32_t smram, smbase, smsize;
  81 +
  82 + for(i = 0; i < 14; i++) {
  83 + r = (d->config[(i >> 1) + 0x61] >> ((i & 1) * 4)) & 3;
  84 + start = mar_addresses[i];
  85 + end = mar_addresses[i + 1];
  86 + // printf("ISA mapping %08x: %d\n", start, r);
  87 + switch(r) {
  88 + case 3:
  89 + /* RAM */
  90 + cpu_register_physical_memory(start, end - start,
  91 + start);
  92 + break;
  93 + case 2:
  94 + /* ROM (XXX: not quite correct) */
  95 + cpu_register_physical_memory(start, end - start,
  96 + start | IO_MEM_ROM);
  97 + break;
  98 + case 1:
  99 + case 0:
  100 + /* XXX: should distinguish read/write cases */
  101 + for(addr = start; addr < end; addr += 4096) {
  102 + cpu_register_physical_memory(addr, 4096,
  103 + isa_page_descs[(addr - 0xa0000) >> 12]);
  104 + }
  105 + break;
  106 + }
  107 + }
  108 + smram = le32_to_cpu(*(uint32_t *)(d->config + 0x6c));
  109 + if ((smm_enabled && (smram & 0x80000000)) || (smram & (1 << 26))) {
  110 + /* Note: we assume the SMM area is in the 0xa0000-0x100000 range */
  111 + smbase = (smram & 0xffff) << 16;
  112 + smsize = (((smram >> 20) & 0xf) + 1) << 16;
  113 + if (smbase >= 0xa0000 && (smbase + smsize) <= 0x100000) {
  114 + cpu_register_physical_memory(smbase, smsize, smbase);
  115 + }
  116 + }
  117 +}
  118 +
  119 +void i440fx_set_smm(PCIDevice *d, int val)
  120 +{
  121 + val = (val != 0);
  122 + if (smm_enabled != val) {
  123 + smm_enabled = val;
  124 + i440fx_update_memory_mappings(d);
  125 + }
  126 +}
  127 +
  128 +
  129 +/* XXX: suppress when better memory API. We make the assumption that
  130 + no device (in particular the VGA) changes the memory mappings in
  131 + the 0xa0000-0x100000 range */
  132 +void i440fx_init_memory_mappings(PCIDevice *d)
  133 +{
  134 + int i;
  135 + for(i = 0; i < 96; i++) {
  136 + isa_page_descs[i] = cpu_get_physical_page_desc(0xa0000 + i * 0x1000);
  137 + }
  138 +}
  139 +
  140 +static void i440fx_write_config(PCIDevice *d,
  141 + uint32_t address, uint32_t val, int len)
  142 +{
  143 + /* XXX: implement SMRAM.D_LOCK */
  144 + pci_default_write_config(d, address, val, len);
  145 + if ((address >= 0x61 && address <= 0x67) || address == 0x6c)
  146 + i440fx_update_memory_mappings(d);
  147 +}
  148 +
  149 +static void i440fx_save(QEMUFile* f, void *opaque)
  150 +{
  151 + PCIDevice *d = opaque;
  152 + pci_device_save(d, f);
  153 + qemu_put_8s(f, &smm_enabled);
  154 +}
  155 +
  156 +static int i440fx_load(QEMUFile* f, void *opaque, int version_id)
  157 +{
  158 + PCIDevice *d = opaque;
  159 + int ret;
  160 +
  161 + if (version_id != 1)
  162 + return -EINVAL;
  163 + ret = pci_device_load(d, f);
  164 + if (ret < 0)
  165 + return ret;
  166 + i440fx_update_memory_mappings(d);
  167 + qemu_get_8s(f, &smm_enabled);
  168 + return 0;
  169 +}
  170 +
  171 +PCIBus *i440fx_init(PCIDevice **pi440fx_state)
56 { 172 {
57 PCIBus *b; 173 PCIBus *b;
58 PCIDevice *d; 174 PCIDevice *d;
@@ -73,7 +189,7 @@ PCIBus *i440fx_init(void) @@ -73,7 +189,7 @@ PCIBus *i440fx_init(void)
73 register_ioport_read(0xcfc, 4, 4, pci_host_data_readl, s); 189 register_ioport_read(0xcfc, 4, 4, pci_host_data_readl, s);
74 190
75 d = pci_register_device(b, "i440FX", sizeof(PCIDevice), 0, 191 d = pci_register_device(b, "i440FX", sizeof(PCIDevice), 0,
76 - NULL, NULL); 192 + NULL, i440fx_write_config);
77 193
78 d->config[0x00] = 0x86; // vendor_id 194 d->config[0x00] = 0x86; // vendor_id
79 d->config[0x01] = 0x80; 195 d->config[0x01] = 0x80;
@@ -83,6 +199,11 @@ PCIBus *i440fx_init(void) @@ -83,6 +199,11 @@ PCIBus *i440fx_init(void)
83 d->config[0x0a] = 0x00; // class_sub = host2pci 199 d->config[0x0a] = 0x00; // class_sub = host2pci
84 d->config[0x0b] = 0x06; // class_base = PCI_bridge 200 d->config[0x0b] = 0x06; // class_base = PCI_bridge
85 d->config[0x0e] = 0x00; // header_type 201 d->config[0x0e] = 0x00; // header_type
  202 +
  203 + d->config[0x6c] = 0x0a; /* SMRAM */
  204 +
  205 + register_savevm("I440FX", 0, 1, i440fx_save, i440fx_load, d);
  206 + *pi440fx_state = d;
86 return b; 207 return b;
87 } 208 }
88 209
@@ -188,226 +309,3 @@ int piix3_init(PCIBus *bus) @@ -188,226 +309,3 @@ int piix3_init(PCIBus *bus)
188 piix3_reset(d); 309 piix3_reset(d);
189 return d->devfn; 310 return d->devfn;
190 } 311 }
191 -  
192 -/***********************************************************/  
193 -/* XXX: the following should be moved to the PC BIOS */  
194 -  
195 -static __attribute__((unused)) uint32_t isa_inb(uint32_t addr)  
196 -{  
197 - return cpu_inb(NULL, addr);  
198 -}  
199 -  
200 -static void isa_outb(uint32_t val, uint32_t addr)  
201 -{  
202 - cpu_outb(NULL, addr, val);  
203 -}  
204 -  
205 -static __attribute__((unused)) uint32_t isa_inw(uint32_t addr)  
206 -{  
207 - return cpu_inw(NULL, addr);  
208 -}  
209 -  
210 -static __attribute__((unused)) void isa_outw(uint32_t val, uint32_t addr)  
211 -{  
212 - cpu_outw(NULL, addr, val);  
213 -}  
214 -  
215 -static __attribute__((unused)) uint32_t isa_inl(uint32_t addr)  
216 -{  
217 - return cpu_inl(NULL, addr);  
218 -}  
219 -  
220 -static __attribute__((unused)) void isa_outl(uint32_t val, uint32_t addr)  
221 -{  
222 - cpu_outl(NULL, addr, val);  
223 -}  
224 -  
225 -static uint32_t pci_bios_io_addr;  
226 -static uint32_t pci_bios_mem_addr;  
227 -/* host irqs corresponding to PCI irqs A-D */  
228 -static uint8_t pci_irqs[4] = { 11, 9, 11, 9 };  
229 -static int pci_bios_next_bus;  
230 -  
231 -static void pci_config_writel(PCIDevice *d, uint32_t addr, uint32_t val)  
232 -{  
233 - PCIBus *s = d->bus;  
234 - addr |= (pci_bus_num(s) << 16) | (d->devfn << 8);  
235 - pci_data_write(s, addr, val, 4);  
236 -}  
237 -  
238 -static void pci_config_writew(PCIDevice *d, uint32_t addr, uint32_t val)  
239 -{  
240 - PCIBus *s = d->bus;  
241 - addr |= (pci_bus_num(s) << 16) | (d->devfn << 8);  
242 - pci_data_write(s, addr, val, 2);  
243 -}  
244 -  
245 -static void pci_config_writeb(PCIDevice *d, uint32_t addr, uint32_t val)  
246 -{  
247 - PCIBus *s = d->bus;  
248 - addr |= (pci_bus_num(s) << 16) | (d->devfn << 8);  
249 - pci_data_write(s, addr, val, 1);  
250 -}  
251 -  
252 -static __attribute__((unused)) uint32_t pci_config_readl(PCIDevice *d, uint32_t addr)  
253 -{  
254 - PCIBus *s = d->bus;  
255 - addr |= (pci_bus_num(s) << 16) | (d->devfn << 8);  
256 - return pci_data_read(s, addr, 4);  
257 -}  
258 -  
259 -static uint32_t pci_config_readw(PCIDevice *d, uint32_t addr)  
260 -{  
261 - PCIBus *s = d->bus;  
262 - addr |= (pci_bus_num(s) << 16) | (d->devfn << 8);  
263 - return pci_data_read(s, addr, 2);  
264 -}  
265 -  
266 -static uint32_t pci_config_readb(PCIDevice *d, uint32_t addr)  
267 -{  
268 - PCIBus *s = d->bus;  
269 - addr |= (pci_bus_num(s) << 16) | (d->devfn << 8);  
270 - return pci_data_read(s, addr, 1);  
271 -}  
272 -  
273 -static void pci_set_io_region_addr(PCIDevice *d, int region_num, uint32_t addr)  
274 -{  
275 - PCIIORegion *r;  
276 - uint16_t cmd;  
277 - uint32_t ofs;  
278 -  
279 - if ( region_num == PCI_ROM_SLOT ) {  
280 - ofs = 0x30;  
281 - }else{  
282 - ofs = 0x10 + region_num * 4;  
283 - }  
284 -  
285 - pci_config_writel(d, ofs, addr);  
286 - r = &d->io_regions[region_num];  
287 -  
288 - /* enable memory mappings */  
289 - cmd = pci_config_readw(d, PCI_COMMAND);  
290 - if ( region_num == PCI_ROM_SLOT )  
291 - cmd |= 2;  
292 - else if (r->type & PCI_ADDRESS_SPACE_IO)  
293 - cmd |= 1;  
294 - else  
295 - cmd |= 2;  
296 - pci_config_writew(d, PCI_COMMAND, cmd);  
297 -}  
298 -  
299 -static void pci_bios_init_device(PCIDevice *d)  
300 -{  
301 - int class;  
302 - PCIIORegion *r;  
303 - uint32_t *paddr;  
304 - int i, pin, pic_irq, vendor_id, device_id;  
305 -  
306 - class = pci_config_readw(d, PCI_CLASS_DEVICE);  
307 - vendor_id = pci_config_readw(d, PCI_VENDOR_ID);  
308 - device_id = pci_config_readw(d, PCI_DEVICE_ID);  
309 - switch(class) {  
310 - case 0x0101:  
311 - if (vendor_id == 0x8086 && device_id == 0x7010) {  
312 - /* PIIX3 IDE */  
313 - pci_config_writew(d, 0x40, 0x8000); // enable IDE0  
314 - pci_config_writew(d, 0x42, 0x8000); // enable IDE1  
315 - goto default_map;  
316 - } else {  
317 - /* IDE: we map it as in ISA mode */  
318 - pci_set_io_region_addr(d, 0, 0x1f0);  
319 - pci_set_io_region_addr(d, 1, 0x3f4);  
320 - pci_set_io_region_addr(d, 2, 0x170);  
321 - pci_set_io_region_addr(d, 3, 0x374);  
322 - }  
323 - break;  
324 - case 0x0604:  
325 - /* PCI to PCI bridge. Assign bus ID and recurse to configure  
326 - devices on the secondary bus. */  
327 - i = pci_bios_next_bus++;  
328 - pci_config_writeb(d, 0x18, pci_bus_num(d->bus));  
329 - pci_config_writeb(d, 0x19, i);  
330 - pci_for_each_device(i, pci_bios_init_device);  
331 - break;  
332 - case 0x0300:  
333 - if (vendor_id != 0x1234)  
334 - goto default_map;  
335 - /* VGA: map frame buffer to default Bochs VBE address */  
336 - pci_set_io_region_addr(d, 0, 0xE0000000);  
337 - break;  
338 - case 0x0800:  
339 - /* PIC */  
340 - vendor_id = pci_config_readw(d, PCI_VENDOR_ID);  
341 - device_id = pci_config_readw(d, PCI_DEVICE_ID);  
342 - if (vendor_id == 0x1014) {  
343 - /* IBM */  
344 - if (device_id == 0x0046 || device_id == 0xFFFF) {  
345 - /* MPIC & MPIC2 */  
346 - pci_set_io_region_addr(d, 0, 0x80800000 + 0x00040000);  
347 - }  
348 - }  
349 - break;  
350 - case 0xff00:  
351 - if (vendor_id == 0x0106b &&  
352 - (device_id == 0x0017 || device_id == 0x0022)) {  
353 - /* macio bridge */  
354 - pci_set_io_region_addr(d, 0, 0x80800000);  
355 - }  
356 - break;  
357 - default:  
358 - default_map:  
359 - /* default memory mappings */  
360 - for(i = 0; i < PCI_NUM_REGIONS; i++) {  
361 - r = &d->io_regions[i];  
362 - if (r->size) {  
363 - if (r->type & PCI_ADDRESS_SPACE_IO)  
364 - paddr = &pci_bios_io_addr;  
365 - else  
366 - paddr = &pci_bios_mem_addr;  
367 - *paddr = (*paddr + r->size - 1) & ~(r->size - 1);  
368 - pci_set_io_region_addr(d, i, *paddr);  
369 - *paddr += r->size;  
370 - }  
371 - }  
372 - break;  
373 - }  
374 -  
375 - /* map the interrupt */  
376 - pin = pci_config_readb(d, PCI_INTERRUPT_PIN);  
377 - if (pin != 0) {  
378 - pin = pci_slot_get_pirq(d, pin - 1);  
379 - pic_irq = pci_irqs[pin];  
380 - pci_config_writeb(d, PCI_INTERRUPT_LINE, pic_irq);  
381 - }  
382 -}  
383 -  
384 -/*  
385 - * This function initializes the PCI devices as a normal PCI BIOS  
386 - * would do. It is provided just in case the BIOS has no support for  
387 - * PCI.  
388 - */  
389 -void pci_bios_init(void)  
390 -{  
391 - int i, irq;  
392 - uint8_t elcr[2];  
393 -  
394 - pci_bios_io_addr = 0xc000;  
395 - pci_bios_mem_addr = 0xf0000000;  
396 -  
397 - /* activate IRQ mappings */  
398 - elcr[0] = 0x00;  
399 - elcr[1] = 0x00;  
400 - for(i = 0; i < 4; i++) {  
401 - irq = pci_irqs[i];  
402 - /* set to trigger level */  
403 - elcr[irq >> 3] |= (1 << (irq & 7));  
404 - /* activate irq remapping in PIIX */  
405 - pci_config_writeb(piix3_dev, 0x60 + i, irq);  
406 - }  
407 - isa_outb(elcr[0], 0x4d0);  
408 - isa_outb(elcr[1], 0x4d1);  
409 -  
410 - pci_bios_next_bus = 1;  
411 - pci_for_each_device(0, pci_bios_init_device);  
412 -}  
413 -