예제 #1
0
bool amdgpu_read_bios(struct amdgpu_device *adev)
{
	uint8_t __iomem *bios, val1, val2;
	size_t size;

	adev->bios = NULL;
	/* XXX: some cards may return 0 for rom size? ddx has a workaround */
	bios = pci_map_rom(adev->pdev, &size);
	if (!bios) {
		return false;
	}

	val1 = readb(&bios[0]);
	val2 = readb(&bios[1]);

	if (size == 0 || val1 != 0x55 || val2 != 0xaa) {
		pci_unmap_rom(adev->pdev, bios);
		return false;
	}
	adev->bios = kzalloc(size, GFP_KERNEL);
	if (adev->bios == NULL) {
		pci_unmap_rom(adev->pdev, bios);
		return false;
	}
	memcpy_fromio(adev->bios, bios, size);
	pci_unmap_rom(adev->pdev, bios);
	return true;
}
예제 #2
0
static bool radeon_read_bios(struct radeon_device *rdev)
{
	uint8_t __iomem *bios;
	size_t size;

	rdev->bios = NULL;
	/* XXX: some cards may return 0 for rom size? ddx has a workaround */
	bios = pci_map_rom(rdev->pdev, &size);
	if (!bios) {
		return false;
	}

	if (size == 0 || bios[0] != 0x55 || bios[1] != 0xaa) {
		pci_unmap_rom(rdev->pdev, bios);
		return false;
	}
	rdev->bios = kmalloc(size, GFP_KERNEL);
	if (rdev->bios == NULL) {
		pci_unmap_rom(rdev->pdev, bios);
		return false;
	}
	memcpy(rdev->bios, bios, size);
	pci_unmap_rom(rdev->pdev, bios);
	return true;
}
예제 #3
0
bool amdgpu_read_bios(struct amdgpu_device *adev)
{
	uint8_t __iomem *bios, val[2];
	size_t size;

	adev->bios = NULL;
	/* XXX: some cards may return 0 for rom size? ddx has a workaround */
	bios = pci_map_rom(adev->pdev, &size);
	if (!bios) {
		return false;
	}

	val[0] = readb(&bios[0]);
	val[1] = readb(&bios[1]);

	if (size == 0 || !AMD_IS_VALID_VBIOS(val)) {
		pci_unmap_rom(adev->pdev, bios);
		return false;
	}
	adev->bios = kzalloc(size, GFP_KERNEL);
	if (adev->bios == NULL) {
		pci_unmap_rom(adev->pdev, bios);
		return false;
	}
	adev->bios_size = size;
	memcpy_fromio(adev->bios, bios, size);
	pci_unmap_rom(adev->pdev, bios);
	return true;
}
예제 #4
0
/**
 * psb_intel_init_bios - initialize VBIOS settings & find VBT
 * @dev: DRM device
 *
 * Loads the Video BIOS and checks that the VBT exists.  Sets scratch registers
 * to appropriate values.
 *
 * VBT existence is a sanity check that is relied on by other i830_bios.c code.
 * Note that it would be better to use a BIOS call to get the VBT, as BIOSes may
 * feed an updated VBT back through that, compared to what we'll fetch using
 * this method of groping around in the BIOS data.
 *
 * Returns 0 on success, nonzero on failure.
 */
int psb_intel_init_bios(struct drm_device *dev)
{
	struct drm_psb_private *dev_priv = dev->dev_private;
	struct pci_dev *pdev = dev->pdev;
	struct vbt_header *vbt = NULL;
	struct bdb_header *bdb = NULL;
	u8 __iomem *bios = NULL;
	size_t size;
	int i;


	dev_priv->panel_type = 0xff;

	/* XXX Should this validation be moved to intel_opregion.c? */
	if (dev_priv->opregion.vbt) {
		struct vbt_header *vbt = dev_priv->opregion.vbt;
		if (memcmp(vbt->signature, "$VBT", 4) == 0) {
			DRM_DEBUG_KMS("Using VBT from OpRegion: %20s\n",
					 vbt->signature);
			bdb = (struct bdb_header *)((char *)vbt + vbt->bdb_offset);
		} else
			dev_priv->opregion.vbt = NULL;
	}

	if (bdb == NULL) {
		bios = pci_map_rom(pdev, &size);
		if (!bios)
			return -1;

		/* Scour memory looking for the VBT signature */
		for (i = 0; i + 4 < size; i++) {
			if (!memcmp(bios + i, "$VBT", 4)) {
				vbt = (struct vbt_header *)(bios + i);
				break;
			}
		}

		if (!vbt) {
			dev_err(dev->dev, "VBT signature missing\n");
			pci_unmap_rom(pdev, bios);
			return -1;
		}
		bdb = (struct bdb_header *)(bios + i + vbt->bdb_offset);
	}

	/* Grab useful general dxefinitions */
	parse_general_features(dev_priv, bdb);
	parse_driver_features(dev_priv, bdb);
	parse_lfp_panel_data(dev_priv, bdb);
	parse_sdvo_panel_data(dev_priv, bdb);
	parse_sdvo_device_mapping(dev_priv, bdb);
	parse_device_mapping(dev_priv, bdb);
	parse_backlight_data(dev_priv, bdb);
	parse_edp(dev_priv, bdb);

	if (bios)
		pci_unmap_rom(pdev, bios);

	return 0;
}
예제 #5
0
static ssize_t pch_phub_bin_write(struct file *filp, struct kobject *kobj,
				  struct bin_attribute *attr,
				  char *buf, loff_t off, size_t count)
{
	int err;
	unsigned int addr_offset;
	int ret;
	ssize_t rom_size;
	struct pch_phub_reg *chip =
		dev_get_drvdata(container_of(kobj, struct device, kobj));

	ret = mutex_lock_interruptible(&pch_phub_mutex);
	if (ret)
		return -ERESTARTSYS;

	if (off > PCH_PHUB_OROM_SIZE) {
		addr_offset = 0;
		goto return_ok;
	}
	if (count > PCH_PHUB_OROM_SIZE) {
		addr_offset = 0;
		goto return_ok;
	}

	chip->pch_phub_extrom_base_address = pci_map_rom(chip->pdev, &rom_size);
	if (!chip->pch_phub_extrom_base_address) {
		err = -ENOMEM;
		goto exrom_map_err;
	}

	for (addr_offset = 0; addr_offset < count; addr_offset++) {
		if (PCH_PHUB_OROM_SIZE < off + addr_offset)
			goto return_ok;

		ret = pch_phub_write_serial_rom(chip,
			    chip->pch_opt_rom_start_address + addr_offset + off,
			    buf[addr_offset]);
		if (ret) {
			err = ret;
			goto return_err;
		}
	}

return_ok:
	pci_unmap_rom(chip->pdev, chip->pch_phub_extrom_base_address);
	mutex_unlock(&pch_phub_mutex);
	return addr_offset;

return_err:
	pci_unmap_rom(chip->pdev, chip->pch_phub_extrom_base_address);

exrom_map_err:
	mutex_unlock(&pch_phub_mutex);
	return err;
}
예제 #6
0
/**
 * intel_init_bios - initialize VBIOS settings & find VBT
 * @dev: DRM device
 *
 * Loads the Video BIOS and checks that the VBT exists.  Sets scratch registers
 * to appropriate values.
 *
 * VBT existence is a sanity check that is relied on by other i830_bios.c code.
 * Note that it would be better to use a BIOS call to get the VBT, as BIOSes may
 * feed an updated VBT back through that, compared to what we'll fetch using
 * this method of groping around in the BIOS data.
 *
 * Returns 0 on success, nonzero on failure.
 */
bool
intel_init_bios(struct drm_device *dev)
{
	struct drm_i915_private *dev_priv = dev->dev_private;
	struct pci_dev *pdev = dev->pdev;
	struct vbt_header *vbt = NULL;
	struct bdb_header *bdb;
	u8 __iomem *bios;
	size_t size;
	int i;

	bios = pci_map_rom(pdev, &size);
	if (!bios)
		return -1;

	/* Scour memory looking for the VBT signature */
	for (i = 0; i + 4 < size; i++) {
		if (!memcmp(bios + i, "$VBT", 4)) {
			vbt = (struct vbt_header *)(bios + i);
			break;
		}
	}

	if (!vbt) {
		DRM_ERROR("VBT signature missing\n");
		pci_unmap_rom(pdev, bios);
		return -1;
	}

	bdb = (struct bdb_header *)(bios + i + vbt->bdb_offset);

	/* Grab useful general definitions */
	parse_general_features(dev_priv, bdb);
	parse_general_definitions(dev_priv, bdb);
	parse_lfp_panel_data(dev_priv, bdb);
	parse_sdvo_panel_data(dev_priv, bdb);
	parse_sdvo_device_mapping(dev_priv, bdb);
	parse_driver_features(dev_priv, bdb);

	pci_unmap_rom(pdev, bios);

	return 0;
}
예제 #7
0
static void __devexit pch_phub_remove(struct pci_dev *pdev)
{
	struct pch_phub_reg *chip = pci_get_drvdata(pdev);

	sysfs_remove_file(&pdev->dev.kobj, &dev_attr_pch_mac.attr);
	sysfs_remove_bin_file(&pdev->dev.kobj, &pch_bin_attr);
	pci_unmap_rom(pdev, chip->pch_phub_extrom_base_address);
	pci_iounmap(pdev, chip->pch_phub_base_address);
	pci_release_regions(pdev);
	pci_disable_device(pdev);
	kfree(chip);
}
예제 #8
0
static bool radeon_read_bios(struct radeon_device *rdev)
{
	uint8_t __iomem *bios;
	size_t size;

	rdev->bios = NULL;
	/*                                                                 */
	bios = pci_map_rom(rdev->pdev, &size);
	if (!bios) {
		return false;
	}

	if (size == 0 || bios[0] != 0x55 || bios[1] != 0xaa) {
		pci_unmap_rom(rdev->pdev, bios);
		return false;
	}
	rdev->bios = kmemdup(bios, size, GFP_KERNEL);
	if (rdev->bios == NULL) {
		pci_unmap_rom(rdev->pdev, bios);
		return false;
	}
	pci_unmap_rom(rdev->pdev, bios);
	return true;
}
예제 #9
0
static ssize_t show_pch_mac(struct device *dev, struct device_attribute *attr,
			    char *buf)
{
	u8 mac[8];
	struct pch_phub_reg *chip = dev_get_drvdata(dev);
	ssize_t rom_size;

	chip->pch_phub_extrom_base_address = pci_map_rom(chip->pdev, &rom_size);
	if (!chip->pch_phub_extrom_base_address)
		return -ENOMEM;

	pch_phub_read_gbe_mac_addr(chip, mac);
	pci_unmap_rom(chip->pdev, chip->pch_phub_extrom_base_address);

	return sprintf(buf, "%pM\n", mac);
}
예제 #10
0
static void
nouveau_bios_shadow_pci(struct nouveau_bios *bios)
{
	struct pci_dev *pdev = nv_device(bios)->pdev;
	size_t size;

	if (!pci_enable_rom(pdev)) {
		void __iomem *rom = pci_map_rom(pdev, &size);
		if (rom && size) {
			bios->data = kmalloc(size, GFP_KERNEL);
			if (bios->data) {
				memcpy_fromio(bios->data, rom, size);
				bios->size = size;
			}
		}
		if (rom)
			pci_unmap_rom(pdev, rom);

		pci_disable_rom(pdev);
	}
}
예제 #11
0
static ssize_t store_pch_mac(struct device *dev, struct device_attribute *attr,
			     const char *buf, size_t count)
{
	u8 mac[ETH_ALEN];
	ssize_t rom_size;
	struct pch_phub_reg *chip = dev_get_drvdata(dev);
	int ret;

	if (!mac_pton(buf, mac))
		return -EINVAL;

	chip->pch_phub_extrom_base_address = pci_map_rom(chip->pdev, &rom_size);
	if (!chip->pch_phub_extrom_base_address)
		return -ENOMEM;

	ret = pch_phub_write_gbe_mac_addr(chip, mac);
	pci_unmap_rom(chip->pdev, chip->pch_phub_extrom_base_address);
	if (ret)
		return ret;

	return count;
}
static ssize_t store_pch_mac(struct device *dev, struct device_attribute *attr,
			     const char *buf, size_t count)
{
	u8 mac[6];
	ssize_t rom_size;
	struct pch_phub_reg *chip = dev_get_drvdata(dev);

	if (count != 18)
		return -EINVAL;

	sscanf(buf, "%02x:%02x:%02x:%02x:%02x:%02x",
		(u32 *)&mac[0], (u32 *)&mac[1], (u32 *)&mac[2], (u32 *)&mac[3],
		(u32 *)&mac[4], (u32 *)&mac[5]);

	chip->pch_phub_extrom_base_address = pci_map_rom(chip->pdev, &rom_size);
	if (!chip->pch_phub_extrom_base_address)
		return -ENOMEM;

	pch_phub_write_gbe_mac_addr(chip, mac);
	pci_unmap_rom(chip->pdev, chip->pch_phub_extrom_base_address);

	return count;
}
예제 #13
0
/**
 * pci_map_rom_copy - map a PCI ROM to kernel space, create a copy
 * @dev: pointer to pci device struct
 * @size: pointer to receive size of pci window over ROM
 * @return: kernel virtual pointer to image of ROM
 *
 * Map a PCI ROM into kernel space. If ROM is boot video ROM,
 * the shadow BIOS copy will be returned instead of the 
 * actual ROM.
 */
void __iomem *pci_map_rom_copy(struct pci_dev *pdev, size_t *size)
{
	struct resource *res = &pdev->resource[PCI_ROM_RESOURCE];
	void __iomem *rom;
	
	rom = pci_map_rom(pdev, size);
	if (!rom)
		return NULL;
		
	if (res->flags & (IORESOURCE_ROM_COPY | IORESOURCE_ROM_SHADOW))
		return rom;
		
	res->start = (unsigned long)kmalloc(*size, GFP_KERNEL);
	if (!res->start) 
		return rom;

	res->end = res->start + *size; 
	memcpy_fromio((void*)res->start, rom, *size);
	pci_unmap_rom(pdev, rom);
	res->flags |= IORESOURCE_ROM_COPY;
	
	return (void __iomem *)res->start;
}
예제 #14
0
파일: pch_phub.c 프로젝트: ANFS/ANFS-kernel
static int __devinit pch_phub_probe(struct pci_dev *pdev,
				    const struct pci_device_id *id)
{
	int retval;

	int ret;
	ssize_t rom_size;
	struct pch_phub_reg *chip;

	chip = kzalloc(sizeof(struct pch_phub_reg), GFP_KERNEL);
	if (chip == NULL)
		return -ENOMEM;

	ret = pci_enable_device(pdev);
	if (ret) {
		dev_err(&pdev->dev,
		"%s : pci_enable_device FAILED(ret=%d)", __func__, ret);
		goto err_pci_enable_dev;
	}
	dev_dbg(&pdev->dev, "%s : pci_enable_device returns %d\n", __func__,
		ret);

	ret = pci_request_regions(pdev, KBUILD_MODNAME);
	if (ret) {
		dev_err(&pdev->dev,
		"%s : pci_request_regions FAILED(ret=%d)", __func__, ret);
		goto err_req_regions;
	}
	dev_dbg(&pdev->dev, "%s : "
		"pci_request_regions returns %d\n", __func__, ret);

	chip->pch_phub_base_address = pci_iomap(pdev, 1, 0);


	if (chip->pch_phub_base_address == 0) {
		dev_err(&pdev->dev, "%s : pci_iomap FAILED", __func__);
		ret = -ENOMEM;
		goto err_pci_iomap;
	}
	dev_dbg(&pdev->dev, "%s : pci_iomap SUCCESS and value "
		"in pch_phub_base_address variable is %p\n", __func__,
		chip->pch_phub_base_address);
	chip->pch_phub_extrom_base_address = pci_map_rom(pdev, &rom_size);

	if (chip->pch_phub_extrom_base_address == 0) {
		dev_err(&pdev->dev, "%s : pci_map_rom FAILED", __func__);
		ret = -ENOMEM;
		goto err_pci_map;
	}
	dev_dbg(&pdev->dev, "%s : "
		"pci_map_rom SUCCESS and value in "
		"pch_phub_extrom_base_address variable is %p\n", __func__,
		chip->pch_phub_extrom_base_address);

	pci_set_drvdata(pdev, chip);

	retval = sysfs_create_file(&pdev->dev.kobj, &dev_attr_pch_mac.attr);
	if (retval)
		goto err_sysfs_create;

	retval = sysfs_create_bin_file(&pdev->dev.kobj, &pch_bin_attr);
	if (retval)
		goto exit_bin_attr;

	pch_phub_read_modify_write_reg(chip, (unsigned int)CLKCFG_REG_OFFSET,
					CLKCFG_CAN_50MHZ, CLKCFG_CANCLK_MASK);

	/* set the prefech value */
	iowrite32(0x000affaa, chip->pch_phub_base_address + 0x14);
	/* set the interrupt delay value */
	iowrite32(0x25, chip->pch_phub_base_address + 0x44);

	return 0;
exit_bin_attr:
	sysfs_remove_file(&pdev->dev.kobj, &dev_attr_pch_mac.attr);

err_sysfs_create:
	pci_unmap_rom(pdev, chip->pch_phub_extrom_base_address);
err_pci_map:
	pci_iounmap(pdev, chip->pch_phub_base_address);
err_pci_iomap:
	pci_release_regions(pdev);
err_req_regions:
	pci_disable_device(pdev);
err_pci_enable_dev:
	kfree(chip);
	dev_err(&pdev->dev, "%s returns %d\n", __func__, ret);
	return ret;
}
예제 #15
0
/**
 * intel_parse_bios - find VBT and initialize settings from the BIOS
 * @dev: DRM device
 *
 * Loads the Video BIOS and checks that the VBT exists.  Sets scratch registers
 * to appropriate values.
 *
 * Returns 0 on success, nonzero on failure.
 */
bool
intel_parse_bios(struct drm_device *dev)
{
	extern struct drm_device *i915;
	struct drm_i915_private *dev_priv = i915->dev_private;
	extern struct drm_device *i915;
	struct pci_dev *pdev = i915->pdev;
	struct bdb_header *bdb = NULL;
	u8 __iomem *bios = NULL;

	init_vbt_defaults(dev_priv);

	/* XXX Should this validation be moved to intel_opregion.c? */
	if (!0 && dev_priv->opregion.vbt) {
		struct vbt_header *vbt = dev_priv->opregion.vbt;
		if (memcmp(vbt->signature, "$VBT", 4) == 0) {
			fprintf(stderr, "Using VBT from OpRegion: %20s\n",
					 vbt->signature);
			bdb = (struct bdb_header *)((char *)vbt + vbt->bdb_offset);
		} else
			dev_priv->opregion.vbt = NULL;
	}

	if (bdb == NULL) {
		struct vbt_header *vbt = NULL;
		size_t size;
		int i;

		bios = pci_map_rom(pdev, &size);
		if (!bios)
			return -1;

		/* Scour memory looking for the VBT signature */
		for (i = 0; i + 4 < size; i++) {
			if (!memcmp(bios + i, "$VBT", 4)) {
				vbt = (struct vbt_header *)(bios + i);
				break;
			}
		}

		if (!vbt) {
			fprintf(stderr, "VBT signature missing\n");
			pci_unmap_rom(pdev, bios);
			return -1;
		}

		bdb = (struct bdb_header *)(bios + i + vbt->bdb_offset);
	}

	/* Grab useful general definitions */
	parse_general_features(dev_priv, bdb);
	parse_general_definitions(dev_priv, bdb);
	parse_lfp_panel_data(dev_priv, bdb);
	parse_sdvo_panel_data(dev_priv, bdb);
	parse_sdvo_device_mapping(dev_priv, bdb);
	parse_device_mapping(dev_priv, bdb);
	parse_driver_features(dev_priv, bdb);
	parse_edp(dev_priv, bdb);

	if (bios)
		pci_unmap_rom(pdev, bios);

	return 0;
}
예제 #16
0
static ssize_t pch_phub_bin_read(struct file *filp, struct kobject *kobj,
				 struct bin_attribute *attr, char *buf,
				 loff_t off, size_t count)
{
	unsigned int rom_signature;
	unsigned char rom_length;
	unsigned int tmp;
	unsigned int addr_offset;
	unsigned int orom_size;
	int ret;
	int err;
	ssize_t rom_size;

	struct pch_phub_reg *chip =
		dev_get_drvdata(container_of(kobj, struct device, kobj));

	ret = mutex_lock_interruptible(&pch_phub_mutex);
	if (ret) {
		err = -ERESTARTSYS;
		goto return_err_nomutex;
	}

	/* Get Rom signature */
	chip->pch_phub_extrom_base_address = pci_map_rom(chip->pdev, &rom_size);
	if (!chip->pch_phub_extrom_base_address)
		goto exrom_map_err;

	pch_phub_read_serial_rom(chip, chip->pch_opt_rom_start_address,
				(unsigned char *)&rom_signature);
	rom_signature &= 0xff;
	pch_phub_read_serial_rom(chip, chip->pch_opt_rom_start_address + 1,
				(unsigned char *)&tmp);
	rom_signature |= (tmp & 0xff) << 8;
	if (rom_signature == 0xAA55) {
		pch_phub_read_serial_rom(chip,
					 chip->pch_opt_rom_start_address + 2,
					 &rom_length);
		orom_size = rom_length * 512;
		if (orom_size < off) {
			addr_offset = 0;
			goto return_ok;
		}
		if (orom_size < count) {
			addr_offset = 0;
			goto return_ok;
		}

		for (addr_offset = 0; addr_offset < count; addr_offset++) {
			pch_phub_read_serial_rom(chip,
			    chip->pch_opt_rom_start_address + addr_offset + off,
			    &buf[addr_offset]);
		}
	} else {
		err = -ENODATA;
		goto return_err;
	}
return_ok:
	pci_unmap_rom(chip->pdev, chip->pch_phub_extrom_base_address);
	mutex_unlock(&pch_phub_mutex);
	return addr_offset;

return_err:
	pci_unmap_rom(chip->pdev, chip->pch_phub_extrom_base_address);
exrom_map_err:
	mutex_unlock(&pch_phub_mutex);
return_err_nomutex:
	return err;
}
예제 #17
0
/**
 * intel_parse_bios - find VBT and initialize settings from the BIOS
 * @dev: DRM device
 *
 * Loads the Video BIOS and checks that the VBT exists.  Sets scratch registers
 * to appropriate values.
 *
 * Returns 0 on success, nonzero on failure.
 */
int
intel_parse_bios(struct drm_device *dev)
{
	struct drm_i915_private *dev_priv = dev->dev_private;
	struct pci_dev *pdev = dev->pdev;
	struct bdb_header *bdb = NULL;
	u8 __iomem *bios = NULL;

	if (HAS_PCH_NOP(dev))
		return -ENODEV;

	init_vbt_defaults(dev_priv);

	/* XXX Should this validation be moved to intel_opregion.c? */
	if (!dmi_check_system(intel_no_opregion_vbt) && dev_priv->opregion.vbt) {
		struct vbt_header *vbt = dev_priv->opregion.vbt;
		if (memcmp(vbt->signature, "$VBT", 4) == 0) {
			DRM_DEBUG_KMS("Using VBT from OpRegion: %20s\n",
					 vbt->signature);
			bdb = (struct bdb_header *)((char *)vbt + vbt->bdb_offset);
		} else
			dev_priv->opregion.vbt = NULL;
	}

	if (bdb == NULL) {
		struct vbt_header *vbt = NULL;
		size_t size;
		int i;

		bios = pci_map_rom(pdev, &size);
		if (!bios)
			return -1;

		/* Scour memory looking for the VBT signature */
		for (i = 0; i + 4 < size; i++) {
			if (!memcmp(bios + i, "$VBT", 4)) {
				vbt = (struct vbt_header *)(bios + i);
				break;
			}
		}

		if (!vbt) {
			DRM_DEBUG_DRIVER("VBT signature missing\n");
			pci_unmap_rom(pdev, bios);
			return -1;
		}

		bdb = (struct bdb_header *)(bios + i + vbt->bdb_offset);
	}

	/* Grab useful general definitions */
	parse_general_features(dev_priv, bdb);
	parse_general_definitions(dev_priv, bdb);
	parse_lfp_panel_data(dev_priv, bdb);
	parse_lfp_backlight(dev_priv, bdb);
	parse_sdvo_panel_data(dev_priv, bdb);
	parse_sdvo_device_mapping(dev_priv, bdb);
	parse_device_mapping(dev_priv, bdb);
	parse_driver_features(dev_priv, bdb);
	parse_edp(dev_priv, bdb);
	parse_mipi(dev_priv, bdb);
	parse_ddi_ports(dev_priv, bdb);

	if (bios)
		pci_unmap_rom(pdev, bios);

	return 0;
}
예제 #18
0
/*
 * MMIO BAR access
 * We handle two excluded ranges here as well, if the user tries to read
 * the ROM beyond what PCI tells us is available or the MSI-X table region,
 * we return 0xFF and writes are dropped.
 */
ssize_t vfio_pci_mem_readwrite(struct vfio_pci_device *vdev, char __user *buf,
                               size_t count, loff_t *ppos, bool iswrite)
{
    struct pci_dev *pdev = vdev->pdev;
    loff_t pos = *ppos & VFIO_PCI_OFFSET_MASK;
    int bar = VFIO_PCI_OFFSET_TO_INDEX(*ppos);
    void __iomem *io;
    resource_size_t end;
    size_t done = 0;
    size_t x_start = 0, x_end = 0; /* excluded range */

    if (!pci_resource_start(pdev, bar))
        return -EINVAL;

    end = pci_resource_len(pdev, bar);

    if (pos > end)
        return -EINVAL;

    if (pos == end)
        return 0;

    if (pos + count > end)
        count = end - pos;

    if (bar == PCI_ROM_RESOURCE) {
        io = pci_map_rom(pdev, &x_start);
        x_end = end;
    } else {
        if (!vdev->barmap[bar]) {
            int ret;

            ret = pci_request_selected_regions(pdev, 1 << bar,
                                               "vfio");
            if (ret)
                return ret;

            vdev->barmap[bar] = pci_iomap(pdev, bar, 0);

            if (!vdev->barmap[bar]) {
                pci_release_selected_regions(pdev, 1 << bar);
                return -EINVAL;
            }
        }

        io = vdev->barmap[bar];

        if (bar == vdev->msix_bar) {
            x_start = vdev->msix_offset;
            x_end = vdev->msix_offset + vdev->msix_size;
        }
    }

    if (!io)
        return -EINVAL;

    while (count) {
        size_t fillable, filled;

        if (pos < x_start)
            fillable = x_start - pos;
        else if (pos >= x_end)
            fillable = end - pos;
        else
            fillable = 0;

        if (fillable >= 4 && !(pos % 4) && (count >= 4)) {
            __le32 val;

            if (iswrite) {
                if (copy_from_user(&val, buf, 4))
                    goto out;

                iowrite32(le32_to_cpu(val), io + pos);
            } else {
                val = cpu_to_le32(ioread32(io + pos));

                if (copy_to_user(buf, &val, 4))
                    goto out;
            }

            filled = 4;
        } else if (fillable >= 2 && !(pos % 2) && (count >= 2)) {
            __le16 val;

            if (iswrite) {
                if (copy_from_user(&val, buf, 2))
                    goto out;

                iowrite16(le16_to_cpu(val), io + pos);
            } else {
                val = cpu_to_le16(ioread16(io + pos));

                if (copy_to_user(buf, &val, 2))
                    goto out;
            }

            filled = 2;
        } else if (fillable) {
            u8 val;

            if (iswrite) {
                if (copy_from_user(&val, buf, 1))
                    goto out;

                iowrite8(val, io + pos);
            } else {
                val = ioread8(io + pos);

                if (copy_to_user(buf, &val, 1))
                    goto out;
            }

            filled = 1;
        } else {
            /* Drop writes, fill reads with FF */
            if (!iswrite) {
                char val = 0xFF;
                size_t i;

                for (i = 0; i < x_end - pos; i++) {
                    if (put_user(val, buf + i))
                        goto out;
                }
            }

            filled = x_end - pos;
        }

        count -= filled;
        done += filled;
        buf += filled;
        pos += filled;
    }

    *ppos += done;

out:
    if (bar == PCI_ROM_RESOURCE)
        pci_unmap_rom(pdev, io);

    return count ? -EFAULT : done;
}
예제 #19
0
static int __devinit pch_phub_probe(struct pci_dev *pdev,
				    const struct pci_device_id *id)
{
	int retval;

	int ret;
	ssize_t rom_size;
	struct pch_phub_reg *chip;

	chip = kzalloc(sizeof(struct pch_phub_reg), GFP_KERNEL);
	if (chip == NULL)
		return -ENOMEM;

	ret = pci_enable_device(pdev);
	if (ret) {
		dev_err(&pdev->dev,
		"%s : pci_enable_device FAILED(ret=%d)", __func__, ret);
		goto err_pci_enable_dev;
	}
	dev_dbg(&pdev->dev, "%s : pci_enable_device returns %d\n", __func__,
		ret);

	ret = pci_request_regions(pdev, KBUILD_MODNAME);
	if (ret) {
		dev_err(&pdev->dev,
		"%s : pci_request_regions FAILED(ret=%d)", __func__, ret);
		goto err_req_regions;
	}
	dev_dbg(&pdev->dev, "%s : "
		"pci_request_regions returns %d\n", __func__, ret);

	chip->pch_phub_base_address = pci_iomap(pdev, 1, 0);


	if (chip->pch_phub_base_address == 0) {
		dev_err(&pdev->dev, "%s : pci_iomap FAILED", __func__);
		ret = -ENOMEM;
		goto err_pci_iomap;
	}
	dev_dbg(&pdev->dev, "%s : pci_iomap SUCCESS and value "
		"in pch_phub_base_address variable is %p\n", __func__,
		chip->pch_phub_base_address);
	chip->pch_phub_extrom_base_address = pci_map_rom(pdev, &rom_size);

	if (chip->pch_phub_extrom_base_address == 0) {
		dev_err(&pdev->dev, "%s : pci_map_rom FAILED", __func__);
		ret = -ENOMEM;
		goto err_pci_map;
	}
	dev_dbg(&pdev->dev, "%s : "
		"pci_map_rom SUCCESS and value in "
		"pch_phub_extrom_base_address variable is %p\n", __func__,
		chip->pch_phub_extrom_base_address);

	if (id->driver_data == 1) {
		retval = sysfs_create_file(&pdev->dev.kobj,
					   &dev_attr_pch_mac.attr);
		if (retval)
			goto err_sysfs_create;

		retval = sysfs_create_bin_file(&pdev->dev.kobj, &pch_bin_attr);
		if (retval)
			goto exit_bin_attr;

		pch_phub_read_modify_write_reg(chip,
					       (unsigned int)CLKCFG_REG_OFFSET,
					       CLKCFG_CAN_50MHZ,
					       CLKCFG_CANCLK_MASK);

		/* quirk for CM-iTC board */
		if (strstr(dmi_get_system_info(DMI_BOARD_NAME), "CM-iTC"))
			pch_phub_read_modify_write_reg(chip,
						(unsigned int)CLKCFG_REG_OFFSET,
						CLKCFG_UART_48MHZ | CLKCFG_BAUDDIV |
						CLKCFG_PLL2VCO | CLKCFG_UARTCLKSEL,
						CLKCFG_UART_MASK);

		/* set the prefech value */
		iowrite32(0x000affaa, chip->pch_phub_base_address + 0x14);
		/* set the interrupt delay value */
		iowrite32(0x25, chip->pch_phub_base_address + 0x44);
	} else if (id->driver_data == 2) {
		retval = sysfs_create_bin_file(&pdev->dev.kobj, &pch_bin_attr);
		if (retval)
			goto err_sysfs_create;
		/* set the prefech value
		 * Device2(USB OHCI #1/ USB EHCI #1/ USB Device):a
		 * Device4(SDIO #0,1,2):f
		 * Device6(SATA 2):f
		 * Device8(USB OHCI #0/ USB EHCI #0):a
		 */
		iowrite32(0x000affa0, chip->pch_phub_base_address + 0x14);
	}
	pci_set_drvdata(pdev, chip);

	return 0;
exit_bin_attr:
	sysfs_remove_file(&pdev->dev.kobj, &dev_attr_pch_mac.attr);

err_sysfs_create:
	pci_unmap_rom(pdev, chip->pch_phub_extrom_base_address);
err_pci_map:
	pci_iounmap(pdev, chip->pch_phub_base_address);
err_pci_iomap:
	pci_release_regions(pdev);
err_req_regions:
	pci_disable_device(pdev);
err_pci_enable_dev:
	kfree(chip);
	dev_err(&pdev->dev, "%s returns %d\n", __func__, ret);
	return ret;
}
bool
intel_parse_bios(struct drm_device *dev)
{
	struct drm_i915_private *dev_priv = dev->dev_private;
	struct pci_dev *pdev = dev->pdev;
	struct bdb_header *bdb = NULL;
	u8 __iomem *bios = NULL;

	init_vbt_defaults(dev_priv);

	
	if (!dmi_check_system(intel_no_opregion_vbt) && dev_priv->opregion.vbt) {
		struct vbt_header *vbt = dev_priv->opregion.vbt;
		if (memcmp(vbt->signature, "$VBT", 4) == 0) {
			DRM_DEBUG_KMS("Using VBT from OpRegion: %20s\n",
					 vbt->signature);
			bdb = (struct bdb_header *)((char *)vbt + vbt->bdb_offset);
		} else
			dev_priv->opregion.vbt = NULL;
	}

	if (bdb == NULL) {
		struct vbt_header *vbt = NULL;
		size_t size;
		int i;

		bios = pci_map_rom(pdev, &size);
		if (!bios)
			return -1;

		
		for (i = 0; i + 4 < size; i++) {
			if (!memcmp(bios + i, "$VBT", 4)) {
				vbt = (struct vbt_header *)(bios + i);
				break;
			}
		}

		if (!vbt) {
			DRM_DEBUG_DRIVER("VBT signature missing\n");
			pci_unmap_rom(pdev, bios);
			return -1;
		}

		bdb = (struct bdb_header *)(bios + i + vbt->bdb_offset);
	}

	
	parse_general_features(dev_priv, bdb);
	parse_general_definitions(dev_priv, bdb);
	parse_lfp_panel_data(dev_priv, bdb);
	parse_sdvo_panel_data(dev_priv, bdb);
	parse_sdvo_device_mapping(dev_priv, bdb);
	parse_device_mapping(dev_priv, bdb);
	parse_driver_features(dev_priv, bdb);
	parse_edp(dev_priv, bdb);

	if (bios)
		pci_unmap_rom(pdev, bios);

	return 0;
}