/** * Read a VGA rom using the 0xc0000 mapping. * * This function should be extended to handle access through PCI resources, * which should be more reliable when available. */ static int pci_device_freebsd_read_rom( struct pci_device * dev, void * buffer ) { struct pci_device_private *priv = (struct pci_device_private *) dev; void *bios; pciaddr_t rom_base; uint32_t rom; uint16_t reg; int pci_rom, memfd; if ( ( dev->device_class & 0x00ffff00 ) != ( ( PCIC_DISPLAY << 16 ) | ( PCIS_DISPLAY_VGA << 8 ) ) ) { return ENOSYS; } if (priv->rom_base == 0) { #if defined(__amd64__) || defined(__i386__) rom_base = 0xc0000; pci_rom = 0; #else return ENOSYS; #endif } else { rom_base = priv->rom_base; pci_rom = 1; pci_device_cfg_read_u16( dev, ®, PCIR_COMMAND ); pci_device_cfg_write_u16( dev, reg | PCIM_CMD_MEMEN, PCIR_COMMAND ); pci_device_cfg_read_u32( dev, &rom, PCIR_BIOS ); pci_device_cfg_write_u32( dev, rom | PCIM_BIOS_ENABLE, PCIR_BIOS ); } printf("Using rom_base = 0x%lx\n", (long)rom_base); memfd = open( "/dev/mem", O_RDONLY | O_CLOEXEC ); if ( memfd == -1 ) return errno; bios = mmap( NULL, dev->rom_size, PROT_READ, 0, memfd, rom_base ); if ( bios == MAP_FAILED ) { close( memfd ); return errno; } memcpy( buffer, bios, dev->rom_size ); munmap( bios, dev->rom_size ); close( memfd ); if (pci_rom) { pci_device_cfg_write_u32( dev, PCIR_BIOS, rom ); pci_device_cfg_write_u16( dev, PCIR_COMMAND, reg ); } return 0; }
int isNc10( struct pci_device * dev ) { char * p; uint16_t id; if( dev == NULL ) return 0; p = (char *) pci_device_get_device_name( dev ); if( p == NULL ) return 0; if( strcmp( p, "Mobile 945GM/GMS/GME, 943/940GML Express Integrated Graphics Controller" ) ) return 0; p = (char *) pci_device_get_subvendor_name( dev ); if( p == NULL ) return 0; if( strcmp( p, "Samsung Electronics Co Ltd" ) ) return 0; if( pci_device_cfg_read_u16( dev, &id, 0x2e ) ) return 0; if( id != 0xca00 ) return 0; return 1; }
void xf86PciProbe(void) { int i = 0, k; int num = 0; struct pci_device *info; struct pci_device_iterator *iter; struct pci_device **xf86PciVideoInfo = NULL; if (!xf86scanpci()) { xf86PciVideoInfo = NULL; return; } iter = pci_slot_match_iterator_create(&xf86IsolateDevice); while ((info = pci_device_next(iter)) != NULL) { if (PCIINFOCLASSES(info->device_class)) { num++; xf86PciVideoInfo = xnfreallocarray(xf86PciVideoInfo, num + 1, sizeof(struct pci_device *)); xf86PciVideoInfo[num] = NULL; xf86PciVideoInfo[num - 1] = info; pci_device_probe(info); if (primaryBus.type == BUS_NONE && pci_device_is_boot_vga(info)) { primaryBus.type = BUS_PCI; primaryBus.id.pci = info; } info->user_data = 0; } } free(iter); /* If we haven't found a primary device try a different heuristic */ if (primaryBus.type == BUS_NONE && num) { for (i = 0; i < num; i++) { uint16_t command; info = xf86PciVideoInfo[i]; pci_device_cfg_read_u16(info, &command, 4); if ((command & PCI_CMD_MEM_ENABLE) && ((num == 1) || IS_VGA(info->device_class))) { if (primaryBus.type == BUS_NONE) { primaryBus.type = BUS_PCI; primaryBus.id.pci = info; } else { xf86Msg(X_NOTICE, "More than one possible primary device found\n"); primaryBus.type ^= (BusType) (-1); } } } } /* Print a summary of the video devices found */ for (k = 0; k < num; k++) { const char *prim = " "; Bool memdone = FALSE, iodone = FALSE; info = xf86PciVideoInfo[k]; if (!PCIALWAYSPRINTCLASSES(info->device_class)) continue; if (xf86IsPrimaryPci(info)) prim = "*"; xf86Msg(X_PROBED, "PCI:%s(%u:%u:%u:%u) %04x:%04x:%04x:%04x ", prim, info->domain, info->bus, info->dev, info->func, info->vendor_id, info->device_id, info->subvendor_id, info->subdevice_id); xf86ErrorF("rev %d", info->revision); for (i = 0; i < 6; i++) { struct pci_mem_region *r = &info->regions[i]; if (r->size && !r->is_IO) { if (!memdone) { xf86ErrorF(", Mem @ "); memdone = TRUE; } else xf86ErrorF(", "); xf86ErrorF("0x%08lx/%ld", (long) r->base_addr, (long) r->size); } } for (i = 0; i < 6; i++) { struct pci_mem_region *r = &info->regions[i]; if (r->size && r->is_IO) { if (!iodone) { xf86ErrorF(", I/O @ "); iodone = TRUE; } else xf86ErrorF(", "); xf86ErrorF("0x%08lx/%ld", (long) r->base_addr, (long) r->size); } } if (info->rom_size) { xf86ErrorF(", BIOS @ 0x\?\?\?\?\?\?\?\?/%ld", (long) info->rom_size); } xf86ErrorF("\n"); } free(xf86PciVideoInfo); }
static int print_clock_info(struct pci_device *pci_dev) { uint32_t devid = pci_dev->device_id; uint16_t gcfgc; if (IS_GM45(devid)) { int core_clock = -1; pci_device_cfg_read_u16(pci_dev, &gcfgc, I915_GCFGC); switch (gcfgc & 0xf) { case 8: core_clock = 266; break; case 9: core_clock = 320; break; case 11: core_clock = 400; break; case 13: core_clock = 533; break; } print_clock("core", core_clock); } else if (IS_965(devid) && IS_MOBILE(devid)) { int render_clock = -1, sampler_clock = -1; pci_device_cfg_read_u16(pci_dev, &gcfgc, I915_GCFGC); switch (gcfgc & 0xf) { case 2: render_clock = 250; sampler_clock = 267; break; case 3: render_clock = 320; sampler_clock = 333; break; case 4: render_clock = 400; sampler_clock = 444; break; case 5: render_clock = 500; sampler_clock = 533; break; } print_clock("render", render_clock); printf(" "); print_clock("sampler", sampler_clock); } else if (IS_945(devid) && IS_MOBILE(devid)) { int render_clock = -1, display_clock = -1; pci_device_cfg_read_u16(pci_dev, &gcfgc, I915_GCFGC); switch (gcfgc & 0x7) { case 0: render_clock = 166; break; case 1: render_clock = 200; break; case 3: render_clock = 250; break; case 5: render_clock = 400; break; } switch (gcfgc & 0x70) { case 0: display_clock = 200; break; case 4: display_clock = 320; break; } if (gcfgc & (1 << 7)) display_clock = 133; print_clock("render", render_clock); printf(" "); print_clock("display", display_clock); } else if (IS_915(devid) && IS_MOBILE(devid)) { int render_clock = -1, display_clock = -1; pci_device_cfg_read_u16(pci_dev, &gcfgc, I915_GCFGC); switch (gcfgc & 0x7) { case 0: render_clock = 160; break; case 1: render_clock = 190; break; case 4: render_clock = 333; break; } if (gcfgc & (1 << 13)) render_clock = 133; switch (gcfgc & 0x70) { case 0: display_clock = 190; break; case 4: display_clock = 333; break; } if (gcfgc & (1 << 7)) display_clock = 133; print_clock("render", render_clock); printf(" "); print_clock("display", display_clock); } printf("\n"); return -1; }
/** * Sets the address and size information for the region from config space * registers. * * This would be much better provided by a kernel interface. * * \return 0 on success, or an errno value. */ static int pci_device_freebsd_get_region_info( struct pci_device * dev, int region, int bar ) { uint32_t addr, testval; uint16_t cmd; int err; /* Get the base address */ err = pci_device_cfg_read_u32( dev, &addr, bar ); if (err != 0) return err; /* * We are going to be doing evil things to the registers here * so disable them via the command register first. */ err = pci_device_cfg_read_u16( dev, &cmd, PCIR_COMMAND ); if (err != 0) return err; err = pci_device_cfg_write_u16( dev, cmd & ~(PCI_BAR_MEM(addr) ? PCIM_CMD_MEMEN : PCIM_CMD_PORTEN), PCIR_COMMAND ); if (err != 0) return err; /* Test write all ones to the register, then restore it. */ err = pci_device_cfg_write_u32( dev, 0xffffffff, bar ); if (err != 0) return err; err = pci_device_cfg_read_u32( dev, &testval, bar ); if (err != 0) return err; err = pci_device_cfg_write_u32( dev, addr, bar ); if (err != 0) return err; /* Restore the command register */ err = pci_device_cfg_write_u16( dev, cmd, PCIR_COMMAND ); if (err != 0) return err; if (addr & 0x01) dev->regions[region].is_IO = 1; if (addr & 0x04) dev->regions[region].is_64 = 1; if (addr & 0x08) dev->regions[region].is_prefetchable = 1; /* Set the size */ dev->regions[region].size = get_test_val_size( testval ); printf("size = 0x%lx\n", (long)dev->regions[region].size); /* Set the base address value */ if (dev->regions[region].is_64) { uint32_t top; err = pci_device_cfg_read_u32( dev, &top, bar + 4 ); if (err != 0) return err; dev->regions[region].base_addr = ((uint64_t)top << 32) | get_map_base(addr); } else { dev->regions[region].base_addr = get_map_base(addr); } return 0; }
static void get_device_serial_number(struct pci_device *dev, struct hba_info *info) { uint32_t pcie_cap_header; uint32_t dword_high = 0; uint32_t dword_low = 0; uint16_t pcie_cap_id; pciaddr_t offset; uint16_t status; uint8_t cap_ptr; int rc; /* Default */ snprintf(info->serial_number, sizeof(info->serial_number), "Unknown"); /* * Read the Status Regiser in the PCIe configuration * header space to see if the PCI Capability List is * supported by this device. */ rc = pci_device_cfg_read_u16(dev, &status, PCI_STATUS); if (rc) { fprintf(stderr, "Failed reading PCI status register\n"); return; } if (!(status & PCI_STATUS_CAP_LIST)) { fprintf(stderr, "PCI capabilities are not supported\n"); return; } /* * Read the offset (cap_ptr) of first entry in the capability list in * the PCI configuration space. */ rc = pci_device_cfg_read_u8(dev, &cap_ptr, PCI_CAPABILITY_LIST); if (rc) { fprintf(stderr, "Failed reading PCI Capability List Register\n"); return; } offset = cap_ptr; /* Search for the PCIe capability */ while (offset) { uint8_t next_cap; uint8_t cap_id; rc = pci_device_cfg_read_u8(dev, &cap_id, offset + PCI_CAP_LIST_ID); if (rc) { fprintf(stderr, "Failed reading capability ID at 0x%"PRIx64"\n", offset + PCI_CAP_LIST_ID); return; } if (cap_id != PCI_CAP_ID_EXP) { rc = pci_device_cfg_read_u8(dev, &next_cap, offset + PCI_CAP_LIST_NEXT); if (rc) { fprintf(stderr, "Failed reading next capability ID at 0x%"PRIx64"\n", offset + PCI_CAP_LIST_NEXT); return; } offset = (pciaddr_t) next_cap; continue; } /* * PCIe Capability Structure exists! */ /* * The first PCIe extended capability is located at * offset 0x100 in the device configuration space. */ offset = 0x100; do { rc = pci_device_cfg_read_u32(dev, &pcie_cap_header, offset); if (rc) { fprintf(stderr, "Failed reading PCIe config header\n"); return; } /* Get the PCIe Extended Capability ID */ pcie_cap_id = pcie_cap_header & 0xffff; if (pcie_cap_id != PCI_EXT_CAP_ID_DSN) { /* Get the offset of the next capability */ offset = (pciaddr_t) pcie_cap_header >> 20; continue; } /* * Found the serial number register! */ (void) pci_device_cfg_read_u32(dev, &dword_low, offset + 4); (void) pci_device_cfg_read_u32(dev, &dword_high, offset + 8); snprintf(info->serial_number, sizeof(info->serial_number), "%02X%02X%02X%02X%02X%02X\n", dword_high >> 24, (dword_high >> 16) & 0xff, (dword_high >> 8) & 0xff, (dword_low >> 16) & 0xff, (dword_low >> 8) & 0xff, dword_low & 0xff); break; } while (offset); break; }