: PCI ROM support.
PATCH 1/1 : PCI ROM support.
Attached is a preliminary patch which adds support for ROM resources to the PCI subsystem as a 7th resource. It's fairly self explanatory, but for some reason in my guest Linux OS, ROM resources are all sized to 2KB (but unassigned and disabled) even if the ROM base address register (@0x30) is all zeros... Not sure if it's just the version of lspci I'm using...
There is probably an obvious bug that Fabrice can spot ;)
Signature · 3 lines
// Gianni Tedesco (gianni at scaramanga dot co dot uk) lynx --source www.scaramanga.co.uk/scaramanga.asc | gpg --import 8646BE7D: 6D9F 2287 870E A2C9 8F60 3A3C 91B5 7669 8646 BE7D
hw/pci.c +30 -12
@@ -100,7 +100,7 @@ {PCIIORegion *r; -if ((unsigned int )region_num >=6 ) +if ((unsigned int )region_num >=PCI_NUM_REGIONS )return ; r = &pci_dev->io_regions[region_num]; r->addr =-1 ;
@@ -125,16 +125,21 @@ {PCIIORegion *r;int cmd, i; -uint32_t last_addr, new_addr; +uint32_t last_addr, new_addr, config_ofs; cmd =le16_to_cpu (*(uint16_t *)(d->config +PCI_COMMAND )); -for (i =0 ; i <6 ; i++) { +for (i =0 ; i <PCI_NUM_REGIONS ; i++) { r = &d->io_regions[i]; +if ( i ==PCI_ROM_SLOT ) { + config_ofs =0x30 ; + }else { + config_ofs =0x10 + i *4 ; + }if (r->size !=0 ) {if (r->type &PCI_ADDRESS_SPACE_IO ) {if (cmd &PCI_COMMAND_IO ) { new_addr =le32_to_cpu (*(uint32_t *)(d->config + -0x10 + i *4 )); + config_ofs)); new_addr = new_addr & ~(r->size -1 ); last_addr = new_addr + r->size -1 ;/* NOTE: we have only 64K ioports on PC */
@@ -148,7 +153,7 @@ }else {if (cmd &PCI_COMMAND_MEMORY ) { new_addr =le32_to_cpu (*(uint32_t *)(d->config + -0x10 + i *4 )); + config_ofs)); new_addr = new_addr & ~(r->size -1 ); last_addr = new_addr + r->size -1 ;/* NOTE: we do not support wrapping */
@@ -216,18 +221,22 @@int can_write, i;uint32_t end, addr; -if (len ==4 && (address >=0x10 && address <0x10 +4 *6 )) { +if (len ==4 && ((address >=0x10 && address <0x10 +4 *6 ) || address ==0x30 ) ) {PCIIORegion *r;int reg; - reg = (address -0x10 ) >>2 ; +if ( address ==0x30 ) { + reg =PCI_ROM_SLOT ; + }else { + reg = (address -0x10 ) >>2 ; + } r = &d->io_regions[reg];if (r->size ==0 ) goto default_config;/* compute the stored value */ val &= ~(r->size -1 ); val |= r->type; - *(uint32_t *)(d->config +0x10 + reg *4 ) =cpu_to_le32 (val); + *(uint32_t *)(d->config + address) =cpu_to_le32 (val);pci_update_mappings (d);return ; }
@@ -812,7 +821,7 @@if (d->config[PCI_INTERRUPT_PIN ] !=0 ) {printf (" IRQ %d.\n" , d->config[PCI_INTERRUPT_LINE ]); } -for (i =0 ;i <6 ; i++) { +for (i =0 ;i <PCI_NUM_REGIONS ; i++) { r = &d->io_regions[i];if (r->size !=0 ) {printf (" BAR%d: " , i);
@@ -934,13 +943,22 @@ {PCIIORegion *r;uint16_t cmd; +uint32_t ofs; -pci_config_writel (d,0x10 + region_num *4 , addr); +if ( region_num ==PCI_ROM_SLOT ) { + ofs =0x30 ; + }else { + ofs =0x10 + region_num *4 ; + } + +pci_config_writel (d, ofs, addr); r = &d->io_regions[region_num];/* enable memory mappings */ cmd =pci_config_readw (d,PCI_COMMAND ); -if (r->type &PCI_ADDRESS_SPACE_IO ) +if ( region_num ==PCI_ROM_SLOT ) + cmd |=2 ; +else if (r->type &PCI_ADDRESS_SPACE_IO ) cmd |=1 ;else cmd |=2 ;
@@ -977,7 +995,7 @@break ;default :/* default memory mappings */ -for (i =0 ; i <6 ; i++) { +for (i =0 ; i <PCI_NUM_REGIONS ; i++) { r = &d->io_regions[i];if (r->size) {if (r->type &PCI_ADDRESS_SPACE_IO )
vl.h +4 -1
@@ -381,6 +381,7 @@#define PCI_ADDRESS_SPACE_MEM 0x00#define PCI_ADDRESS_SPACE_IO 0x01 +#define PCI_ADDRESS_SPACE_ROM 0x02/* not a real flag */ #define PCI_ADDRESS_SPACE_MEM_PREFETCH 0x08 typedef struct PCIIORegion {
@@ -390,6 +391,8 @@PCIMapIORegionFunc *map_func; } PCIIORegion; +#define PCI_ROM_SLOT 6 +#define PCI_NUM_REGIONS 7struct PCIDevice {/* PCI config space */ uint8_t config[256 ];
@@ -398,7 +401,7 @@int bus_num;int devfn;char name[64 ]; -PCIIORegion io_regions[6 ]; +PCIIORegion io_regions[PCI_NUM_REGIONS ];/* do not access the following fields */ PCIConfigReadFunc *config_read;
Hi,
I commited a variant of your patch - try it. I also added support for opaque data on all memory I/Os.
Fabrice.
Quoted 8 lines · Gianni Tedesco
Attached is a preliminary patch which adds support for ROM resources to the PCI subsystem as a 7th resource. It's fairly self explanatory, but for some reason in my guest Linux OS, ROM resources are all sized to 2KB (but unassigned and disabled) even if the ROM base address register (@0x30) is all zeros... Not sure if it's just the version of lspci I'm using...
There is probably an obvious bug that Fabrice can spot ;)
Quoted 4 lines · Fabrice Bellard
Hi,
I commited a variant of your patch - try it. I also added support for opaque data on all memory I/Os.
Thanks Fabrice, that does everything I need now and the opaque data on memory I/Os is very neat. I shall be ready to post a more complete version of my pciproxy patch soon. Just one minor niggle regarding the ROM code.
I notice you preserve the ROM enable bit, thats useful :)
However this still isn't solving my wierd problem with lspci on Linux showing all devices as having a 2KB unassigned, disabled ROM chip where normally it wouldnt print anything. In the config space the ROM bar is 0x00000000...
How are the BARs sized, by writing 0xffffffff over them then re-reading once? It doesn't mention anything in the i440FX manual... Just waffles on about the PMC extended register space.
Signature · 3 lines
// Gianni Tedesco (gianni at scaramanga dot co dot uk) lynx --source www.scaramanga.co.uk/scaramanga.asc | gpg --import 8646BE7D: 6D9F 2287 870E A2C9 8F60 3A3C 91B5 7669 8646 BE7D
Quoted 4 lines · Gianni Tedesco
However this still isn't solving my wierd problem with lspci on Linux showing all devices as having a 2KB unassigned, disabled ROM chip where normally it wouldnt print anything. In the config space the ROM bar is
0x00000000...
It is fixed now (an unassigned BAR/ROM should be hardwired to zero).
Quoted 2 lines
How are the BARs sized, by writing
0xffffffffover them then re-reading once?
Yes.
Fabrice.
Quoted 8 lines · Fabrice Bellard
Quoted 4 lines · Gianni Tedesco
However this still isn't solving my wierd problem with lspci on Linux showing all devices as having a 2KB unassigned, disabled ROM chip where normally it wouldnt print anything. In the config space the ROM bar is
0x00000000...It is fixed now (an unassigned BAR/ROM should be hardwired to zero).
Cool, yes, that fixes it for me.
Thanks.
Signature · 3 lines
// Gianni Tedesco (gianni at scaramanga dot co dot uk) lynx --source www.scaramanga.co.uk/scaramanga.asc | gpg --import 8646BE7D: 6D9F 2287 870E A2C9 8F60 3A3C 91B5 7669 8646 BE7D