コード例 #1
0
ファイル: spi_bit.c プロジェクト: 42wim/ipxe
/**
 * Transfer bits over SPI bit-bashing bus
 *
 * @v bus		SPI bus
 * @v data_out		TX data buffer (or NULL)
 * @v data_in		RX data buffer (or NULL)
 * @v len		Length of transfer (in @b bits)
 * @v endianness	Endianness of this data transfer
 *
 * This issues @c len clock cycles on the SPI bus, shifting out data
 * from the @c data_out buffer to the MOSI line and shifting in data
 * from the MISO line to the @c data_in buffer.  If @c data_out is
 * NULL, then the data sent will be all zeroes.  If @c data_in is
 * NULL, then the incoming data will be discarded.
 */
static void spi_bit_transfer ( struct spi_bit_basher *spibit,
			       const void *data_out, void *data_in,
			       unsigned int len, int endianness ) {
	struct spi_bus *bus = &spibit->bus;
	struct bit_basher *basher = &spibit->basher;
	unsigned int sclk = ( ( bus->mode & SPI_MODE_CPOL ) ? 1 : 0 );
	unsigned int cpha = ( ( bus->mode & SPI_MODE_CPHA ) ? 1 : 0 );
	unsigned int bit_offset;
	unsigned int byte_offset;
	unsigned int byte_mask;
	unsigned int bit;
	unsigned int step;

	DBGC2 ( spibit, "SPIBIT %p transferring %d bits in mode %#x\n",
		spibit, len, bus->mode );

	for ( step = 0 ; step < ( len * 2 ) ; step++ ) {
		/* Calculate byte offset and byte mask */
		bit_offset = ( ( endianness == SPI_BIT_BIG_ENDIAN ) ?
			       ( len - ( step / 2 ) - 1 ) : ( step / 2 ) );
		byte_offset = ( bit_offset / 8 );
		byte_mask = ( 1 << ( bit_offset % 8 ) );

		/* Shift data in or out */
		if ( sclk == cpha ) {
			const uint8_t *byte;

			/* Shift data out */
			if ( data_out ) {
				byte = ( data_out + byte_offset );
				bit = ( *byte & byte_mask );
				DBGCP ( spibit, "SPIBIT %p wrote bit %d\n",
					spibit, ( bit ? 1 : 0 ) );
			} else {
				bit = 0;
			}
			write_bit ( basher, SPI_BIT_MOSI, bit );
		} else {
			uint8_t *byte;

			/* Shift data in */
			bit = read_bit ( basher, SPI_BIT_MISO );
			if ( data_in ) {
				DBGCP ( spibit, "SPIBIT %p read bit %d\n",
					spibit, ( bit ? 1 : 0 ) );
				byte = ( data_in + byte_offset );
				*byte &= ~byte_mask;
				*byte |= ( bit & byte_mask );
			}
		}

		/* Toggle clock line */
		spi_bit_delay();
		sclk ^= 1;
		write_bit ( basher, SPI_BIT_SCLK, sclk );
	}
}
コード例 #2
0
ファイル: efi_pci.c プロジェクト: andrewrothstein/ipxe
/**
 * 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 ) {
		DBGCP ( device, "EFIPCI %s has no driver\n",
			efi_handle_name ( device ) );
		return rc;
	}
	DBGC ( device, "EFIPCI %s has driver \"%s\"\n",
	       efi_handle_name ( device ), pci.id->name );

	return 0;
}
コード例 #3
0
ファイル: xenstore.c プロジェクト: liangdong-xjtu/ipxe
/**
 * Receive XenStore response raw data
 *
 * @v xen		Xen hypervisor
 * @v data		Data buffer, or NULL to discard data
 * @v len		Length of data
 */
static void xenstore_recv ( struct xen_hypervisor *xen, void *data,
			    size_t len ) {
	struct xenstore_domain_interface *intf = xen->store.intf;
	XENSTORE_RING_IDX cons = readl ( &intf->rsp_cons );
	XENSTORE_RING_IDX prod;
	XENSTORE_RING_IDX idx;
	char *bytes = data;
	size_t offset = 0;
	size_t fill;

	DBGCP ( intf, "XENSTORE raw response:\n" );

	/* Read one byte at a time */
	while ( offset < len ) {

		/* Wait for data to be ready */
		while ( 1 ) {
			prod = readl ( &intf->rsp_prod );
			fill = ( prod - cons );
			if ( fill > 0 )
				break;
			DBGC2 ( xen, "." );
			cpu_nap();
			rmb();
		}

		/* Read byte */
		idx = MASK_XENSTORE_IDX ( cons++ );
		if ( data )
			bytes[offset++] = readb ( &intf->rsp[idx] );
	}
	if ( data )
		DBGCP_HDA ( intf, MASK_XENSTORE_IDX ( cons - len ), data, len );

	/* Update consumer counter */
	writel ( cons, &intf->rsp_cons );
	wmb();
}
コード例 #4
0
ファイル: xenstore.c プロジェクト: liangdong-xjtu/ipxe
/**
 * Send XenStore request raw data
 *
 * @v xen		Xen hypervisor
 * @v data		Data buffer
 * @v len		Length of data
 */
static void xenstore_send ( struct xen_hypervisor *xen, const void *data,
			    size_t len ) {
	struct xenstore_domain_interface *intf = xen->store.intf;
	XENSTORE_RING_IDX prod = readl ( &intf->req_prod );
	XENSTORE_RING_IDX cons;
	XENSTORE_RING_IDX idx;
	const char *bytes = data;
	size_t offset = 0;
	size_t fill;

	DBGCP ( intf, "XENSTORE raw request:\n" );
	DBGCP_HDA ( intf, MASK_XENSTORE_IDX ( prod ), data, len );

	/* Write one byte at a time */
	while ( offset < len ) {

		/* Wait for space to become available */
		while ( 1 ) {
			cons = readl ( &intf->req_cons );
			fill = ( prod - cons );
			if ( fill < XENSTORE_RING_SIZE )
				break;
			DBGC2 ( xen, "." );
			cpu_nap();
			rmb();
		}

		/* Write byte */
		idx = MASK_XENSTORE_IDX ( prod++ );
		writeb ( bytes[offset++], &intf->req[idx] );
	}

	/* Update producer counter */
	wmb();
	writel ( prod, &intf->req_prod );
	wmb();
}
コード例 #5
0
ファイル: efi_pci.c プロジェクト: antoinemiquel/ipxe
/**
 * 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;
}