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 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 173 PCIBus *b;
58 174 PCIDevice *d;
... ... @@ -73,7 +189,7 @@ PCIBus *i440fx_init(void)
73 189 register_ioport_read(0xcfc, 4, 4, pci_host_data_readl, s);
74 190  
75 191 d = pci_register_device(b, "i440FX", sizeof(PCIDevice), 0,
76   - NULL, NULL);
  192 + NULL, i440fx_write_config);
77 193  
78 194 d->config[0x00] = 0x86; // vendor_id
79 195 d->config[0x01] = 0x80;
... ... @@ -83,6 +199,11 @@ PCIBus *i440fx_init(void)
83 199 d->config[0x0a] = 0x00; // class_sub = host2pci
84 200 d->config[0x0b] = 0x06; // class_base = PCI_bridge
85 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 207 return b;
87 208 }
88 209  
... ... @@ -188,226 +309,3 @@ int piix3_init(PCIBus *bus)
188 309 piix3_reset(d);
189 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   -
... ...