--- freebsd_pci.c 2009-02-25 15:22:39.000000000 -0600 +++ /tmp/freebsd_pci.c 2009-02-25 15:18:13.000000000 -0600 @@ -61,8 +61,13 @@ #define PCIM_BIOS_ENABLE 0x01 #define PCIM_BIOS_ADDR_MASK 0xfffff800 +#define PCIR_BARS 0x10 +#define PCIR_BAR(x) (PCIR_BARS + (x) * 4) #define PCI_BAR_IO(x) (((x) & PCIM_BAR_SPACE) == PCIM_BAR_IO_SPACE) #define PCI_BAR_MEM(x) (((x) & PCIM_BAR_SPACE) == PCIM_BAR_MEM_SPACE) +#define PCIM_BAR_MEM_TYPE 0x00000006 +#define PCIM_BAR_MEM_64 4 +#define PCIM_BAR_MEM_PREFETCH 0x00000008 #define PCIM_BAR_SPACE 0x00000001 #define PCIM_BAR_MEM_SPACE 0 #define PCIM_BAR_IO_SPACE 1 @@ -318,7 +323,7 @@ { struct pci_device_private *priv = (struct pci_device_private *) dev; - switch (priv->header_type & 0x7f) { + switch (priv->header_type) { case 0: return 6; case 1: @@ -331,6 +336,64 @@ } } +#ifdef PCIOCGETBAR + +static int +pci_device_freebsd_probe( struct pci_device * dev ) +{ + struct pci_device_private *priv = (struct pci_device_private *) dev; + struct pci_bar_io bar; + uint8_t irq; + int err, i; + +#if HAVE_PCI_IO_PC_DOMAIN + bar.pbi_sel.pc_domain = dev->domain; +#endif + bar.pbi_sel.pc_bus = dev->bus; + bar.pbi_sel.pc_dev = dev->dev; + bar.pbi_sel.pc_func = dev->func; + + + /* Many of the fields were filled in during initial device enumeration. + * At this point, we need to fill in regions, rom_size, and irq. + */ + + err = pci_device_cfg_read_u8( dev, &irq, 60 ); + if (err) + return errno; + dev->irq = irq; + + for (i = 0; i < pci_device_freebsd_get_num_regions( dev ); i++) { + bar.pbi_reg = PCIR_BAR(i); + if ( ioctl( freebsd_pci_sys->pcidev, PCIOCGETBAR, &bar ) < 0 ) + continue; + + if (PCI_BAR_IO(bar.pbi_base)) + dev->regions[i].is_IO = 1; + + if ((bar.pbi_base & PCIM_BAR_MEM_TYPE) == PCIM_BAR_MEM_64) + dev->regions[i].is_64 = 1; + + if (bar.pbi_base & PCIM_BAR_MEM_PREFETCH) + dev->regions[i].is_prefetchable = 1; + + dev->regions[i].base_addr = bar.pbi_base & ~((uint64_t)0xf); + dev->regions[i].size = bar.pbi_length; + } + + /* If it's a VGA device, set up the rom size for read_rom using the + * 0xc0000 mapping. + */ + if ((dev->device_class & 0x00ffff00) == + ((PCIC_DISPLAY << 16) | (PCIS_DISPLAY_VGA << 8))) { + dev->rom_size = 64 * 1024; + } + + return 0; +} + +#else + /** Masks out the flag bigs of the base address register value */ static uint32_t get_map_base( uint32_t val ) @@ -450,10 +515,6 @@ return errno; dev->irq = irq; - err = pci_device_cfg_read_u8( dev, &priv->header_type, 0x0e ); - if (err) - return errno; - bar = 0x10; for (i = 0; i < pci_device_freebsd_get_num_regions( dev ); i++) { pci_device_freebsd_get_region_info( dev, i, bar ); @@ -492,6 +553,8 @@ return 0; } +#endif + static void pci_system_freebsd_destroy(void) { @@ -578,6 +641,7 @@ pci_sys->devices[ i ].base.revision = p->pc_revid; pci_sys->devices[ i ].base.device_class = (uint32_t)p->pc_class << 16 | (uint32_t)p->pc_subclass << 8 | (uint32_t)p->pc_progif; + pci_sys->devices[ i ].header_type = p->pc_hdr & 0x7f; } return 0;