/**
 * 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, &reg, 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;
}
Exemplo n.º 2
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;
}
Exemplo n.º 3
0
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;
}
Exemplo n.º 6
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;
	}