Example #1
0
/**
 * Write to PCI configuration space
 *
 * @v pci		PCI device
 * @v location		Encoded offset and width
 * @v value		Value
 * @ret rc		Return status code
 */
int efipci_write ( struct pci_device *pci, unsigned long location,
		   unsigned long value ) {
	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
	EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *root;
	EFI_HANDLE handle;
	EFI_STATUS efirc;
	int rc;

	/* Identify root bridge */
	if ( ( rc = efipci_root ( pci, &handle, &root ) ) != 0 )
		goto err_root;

	/* Read from configuration space */
	if ( ( efirc = root->Pci.Write ( root, EFIPCI_WIDTH ( location ),
					 efipci_address ( pci, location ), 1,
					 &value ) ) != 0 ) {
		rc = -EEFI ( efirc );
		DBGC ( pci, "EFIPCI " PCI_FMT " config write to offset %02lx "
		       "failed: %s\n", PCI_ARGS ( pci ),
		       EFIPCI_OFFSET ( location ), strerror ( rc ) );
		goto err_write;
	}

 err_write:
	bs->CloseProtocol ( handle, &efi_pci_root_bridge_io_protocol_guid,
			    efi_image_handle, handle );
 err_root:
	return rc;
}
/**
 * Read from PCI configuration space
 *
 * @v pci		PCI device
 * @v where		Address within configuration space
 * @v value		Data buffer
 * @v len		Length to read
 * @ret rc		Return status code
 */
int linux_pci_read ( struct pci_device *pci, unsigned long where,
		     unsigned long *value, size_t len ) {
	uint32_t tmp = 0;
	int fd;
	int check_len;
	int rc;

	/* Return "missing device" in case of error */
	*value = -1UL;

	/* Open configuration space */
	fd = linux_pci_open ( pci, O_RDONLY, where );
	if ( fd < 0 ) {
		rc = fd;
		goto err_open;
	}

	/* Read value */
	check_len = linux_read ( fd, &tmp, len );
	if ( check_len < 0 ) {
		DBGC ( pci, "PCI could not read from " PCI_FMT " %#02lx+%#zx: "
		       "%s\n", PCI_ARGS ( pci ), where, len,
		       linux_strerror ( linux_errno ) );
		rc = -ELINUX ( linux_errno );
		goto err_read;
	}
	if ( ( size_t ) check_len != len ) {
		DBGC ( pci, "PCI read only %#x bytes from " PCI_FMT
		       " %#02lx+%#zx\n", check_len, PCI_ARGS ( pci ),
		       where, len );
		rc = -EIO;
		goto err_read;
	}

	/* Return value */
	*value = le32_to_cpu ( tmp );

	/* Success */
	rc = 0;

 err_read:
	linux_close ( fd );
 err_open:
	return rc;
}
/**
 * Write to PCI configuration space
 *
 * @v pci		PCI device
 * @v where		Address within configuration space
 * @v value		Value to write
 * @v len		Length of value
 * @ret rc		Return status code
 */
int linux_pci_write ( struct pci_device *pci, unsigned long where,
		      unsigned long value, size_t len ) {
	uint32_t tmp;
	int fd;
	int check_len;
	int rc;

	/* Open configuration space */
	fd = linux_pci_open ( pci, O_WRONLY, where );
	if ( fd < 0 ) {
		rc = fd;
		goto err_open;
	}

	/* Prepare value for writing */
	tmp = cpu_to_le32 ( value );
	assert ( len <= sizeof ( tmp ) );

	/* Write value */
	check_len = linux_write ( fd, &tmp, len );
	if ( check_len < 0 ) {
		DBGC ( pci, "PCI could not write to " PCI_FMT " %#02lx+%#zx: "
		       "%s\n", PCI_ARGS ( pci ), where, len,
		       linux_strerror ( linux_errno ) );
		rc = -ELINUX ( linux_errno );
		goto err_write;
	}
	if ( ( size_t ) check_len != len ) {
		DBGC ( pci, "PCI wrote only %#x bytes to " PCI_FMT
		       " %#02lx+%#zx\n", check_len, PCI_ARGS ( pci ),
		       where, len );
		rc = -EIO;
		goto err_write;
	}

	/* Success */
	rc = 0;

 err_write:
	linux_close ( fd );
 err_open:
	return rc;
}
Example #4
0
/**
 * Check to see if driver supports a device
 *
 * @v device		EFI device handle
 * @ret rc		Return status code
 */
static int efipci_supported ( EFI_HANDLE device ) {
	struct pci_device pci;
	int rc;

	/* Get PCI device information */
	if ( ( rc = efipci_info ( device, &pci ) ) != 0 )
		return rc;

	/* Look for a driver */
	if ( ( rc = pci_find_driver ( &pci ) ) != 0 ) {
		DBGC ( device, "EFIPCI " PCI_FMT " (%04x:%04x class %06x) "
		       "has no driver\n", PCI_ARGS ( &pci ), pci.vendor,
		       pci.device, pci.class );
		return rc;
	}
Example #5
0
File: efi_pci.c Project: grze/ipxe
int efipci_write ( struct pci_device *pci, unsigned long location,
		   unsigned long value ) {
	EFI_STATUS efirc;
	int rc;

	if ( ( efirc = efipci->Pci.Write ( efipci, EFIPCI_WIDTH ( location ),
					   efipci_address ( pci, location ), 1,
					   &value ) ) != 0 ) {
		rc = -EEFI ( efirc );
		DBG ( "EFIPCI config write to " PCI_FMT " offset %02lx "
		      "failed: %s\n", PCI_ARGS ( pci ),
		      EFIPCI_OFFSET ( location ), strerror ( rc ) );
		return -EIO;
	}

	return 0;
}
Example #6
0
/**
 * Open EFI PCI device
 *
 * @v device		EFI device handle
 * @v attributes	Protocol opening attributes
 * @v pci		PCI device to fill in
 * @ret rc		Return status code
 */
int efipci_open ( EFI_HANDLE device, UINT32 attributes,
		  struct pci_device *pci ) {
	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
	union {
		EFI_PCI_IO_PROTOCOL *pci_io;
		void *interface;
	} pci_io;
	UINTN pci_segment, pci_bus, pci_dev, pci_fn;
	unsigned int busdevfn;
	EFI_STATUS efirc;
	int rc;

	/* See if device is a PCI device */
	if ( ( efirc = bs->OpenProtocol ( device, &efi_pci_io_protocol_guid,
					  &pci_io.interface, efi_image_handle,
					  device, attributes ) ) != 0 ) {
		rc = -EEFI_PCI ( efirc );
		DBGCP ( device, "EFIPCI %s cannot open PCI protocols: %s\n",
			efi_handle_name ( device ), strerror ( rc ) );
		goto err_open_protocol;
	}

	/* Get PCI bus:dev.fn address */
	if ( ( efirc = pci_io.pci_io->GetLocation ( pci_io.pci_io, &pci_segment,
						    &pci_bus, &pci_dev,
						    &pci_fn ) ) != 0 ) {
		rc = -EEFI ( efirc );
		DBGC ( device, "EFIPCI %s could not get PCI location: %s\n",
		       efi_handle_name ( device ), strerror ( rc ) );
		goto err_get_location;
	}
	busdevfn = PCI_BUSDEVFN ( pci_segment, pci_bus, pci_dev, pci_fn );
	pci_init ( pci, busdevfn );
	DBGCP ( device, "EFIPCI " PCI_FMT " is %s\n",
		PCI_ARGS ( pci ), efi_handle_name ( device ) );

	/* Try to enable I/O cycles, memory cycles, and bus mastering.
	 * Some platforms will 'helpfully' report errors if these bits
	 * can't be enabled (for example, if the card doesn't actually
	 * support I/O cycles).  Work around any such platforms by
	 * enabling bits individually and simply ignoring any errors.
	 */
	pci_io.pci_io->Attributes ( pci_io.pci_io,
				    EfiPciIoAttributeOperationEnable,
				    EFI_PCI_IO_ATTRIBUTE_IO, NULL );
	pci_io.pci_io->Attributes ( pci_io.pci_io,
				    EfiPciIoAttributeOperationEnable,
				    EFI_PCI_IO_ATTRIBUTE_MEMORY, NULL );
	pci_io.pci_io->Attributes ( pci_io.pci_io,
				    EfiPciIoAttributeOperationEnable,
				    EFI_PCI_IO_ATTRIBUTE_BUS_MASTER, NULL );

	/* Populate PCI device */
	if ( ( rc = pci_read_config ( pci ) ) != 0 ) {
		DBGC ( device, "EFIPCI " PCI_FMT " cannot read PCI "
		       "configuration: %s\n",
		       PCI_ARGS ( pci ), strerror ( rc ) );
		goto err_pci_read_config;
	}

	return 0;

 err_pci_read_config:
 err_get_location:
	bs->CloseProtocol ( device, &efi_pci_io_protocol_guid,
			    efi_image_handle, device );
 err_open_protocol:
	return rc;
}
Example #7
0
	struct pci_device pci;
	int rc;

	/* Get PCI device information */
	if ( ( rc = efipci_info ( device, &pci ) ) != 0 )
		return rc;

	/* Look for a driver */
	if ( ( rc = pci_find_driver ( &pci ) ) != 0 ) {
		DBGC ( device, "EFIPCI " PCI_FMT " (%04x:%04x class %06x) "
		       "has no driver\n", PCI_ARGS ( &pci ), pci.vendor,
		       pci.device, pci.class );
		return rc;
	}
	DBGC ( device, "EFIPCI " PCI_FMT " (%04x:%04x class %06x) has driver "
	       "\"%s\"\n", PCI_ARGS ( &pci ), pci.vendor, pci.device,
	       pci.class, pci.id->name );

	return 0;
}

/**
 * Attach driver to device
 *
 * @v efidev		EFI device
 * @ret rc		Return status code
 */
static int efipci_start ( struct efi_device *efidev ) {
	EFI_HANDLE device = efidev->device;
	struct pci_device *pci;
	int rc;
Example #8
-5
/**
 * Locate EFI PCI root bridge I/O protocol
 *
 * @v pci		PCI device
 * @ret handle		EFI PCI root bridge handle
 * @ret root		EFI PCI root bridge I/O protocol, or NULL if not found
 * @ret rc		Return status code
 */
static int efipci_root ( struct pci_device *pci, EFI_HANDLE *handle,
			 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL **root ) {
	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
	EFI_HANDLE *handles;
	UINTN num_handles;
	union {
		void *interface;
		EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *root;
	} u;
	EFI_STATUS efirc;
	UINTN i;
	int rc;

	/* Enumerate all handles */
	if ( ( efirc = bs->LocateHandleBuffer ( ByProtocol,
			&efi_pci_root_bridge_io_protocol_guid,
			NULL, &num_handles, &handles ) ) != 0 ) {
		rc = -EEFI ( efirc );
		DBGC ( pci, "EFIPCI " PCI_FMT " cannot locate root bridges: "
		       "%s\n", PCI_ARGS ( pci ), strerror ( rc ) );
		goto err_locate;
	}

	/* Look for matching root bridge I/O protocol */
	for ( i = 0 ; i < num_handles ; i++ ) {
		*handle = handles[i];
		if ( ( efirc = bs->OpenProtocol ( *handle,
				&efi_pci_root_bridge_io_protocol_guid,
				&u.interface, efi_image_handle, *handle,
				EFI_OPEN_PROTOCOL_GET_PROTOCOL ) ) != 0 ) {
			rc = -EEFI ( efirc );
			DBGC ( pci, "EFIPCI " PCI_FMT " cannot open %s: %s\n",
			       PCI_ARGS ( pci ), efi_handle_name ( *handle ),
			       strerror ( rc ) );
			continue;
		}
		if ( u.root->SegmentNumber == PCI_SEG ( pci->busdevfn ) ) {
			*root = u.root;
			bs->FreePool ( handles );
			return 0;
		}
		bs->CloseProtocol ( *handle,
				    &efi_pci_root_bridge_io_protocol_guid,
				    efi_image_handle, *handle );
	}
	DBGC ( pci, "EFIPCI " PCI_FMT " found no root bridge\n",
	       PCI_ARGS ( pci ) );
	rc = -ENOENT;

	bs->FreePool ( handles );
 err_locate:
	return rc;
}