[PATCH:libpciaccess 3/3] Support more pci functions on NetBSD.

Matthieu Herrb matthieu.herrb at laas.fr
Wed Jun 12 15:28:05 PDT 2013


On Wed, Jun 12, 2013 at 01:43:33PM +0200, Thomas Klausner wrote:
> From Chuck Silvers <chuq at chuq.com> based on openbsd_pci.c.
> 
> Signed-off-by: Thomas Klausner <wiz at NetBSD.org>
> ---
>  src/netbsd_pci.c | 335 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 335 insertions(+)
> 
> diff --git a/src/netbsd_pci.c b/src/netbsd_pci.c
> index 2d99680..ab49272 100644
> --- a/src/netbsd_pci.c
> +++ b/src/netbsd_pci.c
> @@ -523,6 +523,332 @@ pci_device_netbsd_read_rom(struct pci_device *dev, void *buffer)
>      return 0;
>  }
>  
> +#if defined(__i386__) || defined(__amd64__)
> +#include <machine/sysarch.h>
> +//#include <machine/pio.h>
   ^^
Please Remove the commented out line above
> +
> +/*
> + * Functions to provide access to x86 programmed I/O instructions.
> + *
> + * The in[bwl]() and out[bwl]() functions are split into two varieties: one to
> + * use a small, constant, 8-bit port number, and another to use a large or
> + * variable port number.  The former can be compiled as a smaller instruction.
> + */
> +
> +
> +#ifdef __OPTIMIZE__
> +
> +#define	__use_immediate_port(port) \
> +	(__builtin_constant_p((port)) && (port) < 0x100)
> +
> +#else
> +
> +#define	__use_immediate_port(port)	0
> +
> +#endif
> +
> +
> +#define	inb(port) \
> +    (/* CONSTCOND */ __use_immediate_port(port) ? __inbc(port) : __inb(port))
> +
> +static __inline u_int8_t
> +__inbc(unsigned port)
> +{
> +	u_int8_t data;
> +	__asm __volatile("inb %w1,%0" : "=a" (data) : "id" (port));
> +	return data;
> +}
> +
> +static __inline u_int8_t
> +__inb(unsigned port)
> +{
> +	u_int8_t data;
> +	__asm __volatile("inb %w1,%0" : "=a" (data) : "d" (port));
> +	return data;
> +}
> +
> +static __inline void
> +insb(unsigned port, void *addr, int cnt)
> +{
> +	void *dummy1;
> +	int dummy2;
> +	__asm __volatile("cld\n\trepne\n\tinsb"			:
> +			 "=D" (dummy1), "=c" (dummy2) 		:
> +			 "d" (port), "0" (addr), "1" (cnt)	:
> +			 "memory");
> +}
> +
> +#define	inw(port) \
> +    (/* CONSTCOND */ __use_immediate_port(port) ? __inwc(port) : __inw(port))
> +
> +static __inline u_int16_t
> +__inwc(unsigned port)
> +{
> +	u_int16_t data;
> +	__asm __volatile("inw %w1,%0" : "=a" (data) : "id" (port));
> +	return data;
> +}
> +
> +static __inline u_int16_t
> +__inw(unsigned port)
> +{
> +	u_int16_t data;
> +	__asm __volatile("inw %w1,%0" : "=a" (data) : "d" (port));
> +	return data;
> +}
> +
> +static __inline void
> +insw(unsigned port, void *addr, int cnt)
> +{
> +	void *dummy1;
> +	int dummy2;
> +	__asm __volatile("cld\n\trepne\n\tinsw"			:
> +			 "=D" (dummy1), "=c" (dummy2)		:
> +			 "d" (port), "0" (addr), "1" (cnt)	:
> +			 "memory");
> +}
> +
> +#define	inl(port) \
> +    (/* CONSTCOND */ __use_immediate_port(port) ? __inlc(port) : __inl(port))
> +
> +static __inline u_int32_t
> +__inlc(unsigned port)
> +{
> +	u_int32_t data;
> +	__asm __volatile("inl %w1,%0" : "=a" (data) : "id" (port));
> +	return data;
> +}
> +
> +static __inline u_int32_t
> +__inl(unsigned port)
> +{
> +	u_int32_t data;
> +	__asm __volatile("inl %w1,%0" : "=a" (data) : "d" (port));
> +	return data;
> +}
> +
> +static __inline void
> +insl(unsigned port, void *addr, int cnt)
> +{
> +	void *dummy1;
> +	int dummy2;
> +	__asm __volatile("cld\n\trepne\n\tinsl"			:
> +			 "=D" (dummy1), "=c" (dummy2)		:
> +			 "d" (port), "0" (addr), "1" (cnt)	:
> +			 "memory");
> +}
> +
> +#define	outb(port, data) \
> +    (/* CONSTCOND */__use_immediate_port(port) ? __outbc(port, data) : \
> +						__outb(port, data))
> +
> +static __inline void
> +__outbc(unsigned port, u_int8_t data)
> +{
> +	__asm __volatile("outb %0,%w1" : : "a" (data), "id" (port));
> +}
> +
> +static __inline void
> +__outb(unsigned port, u_int8_t data)
> +{
> +	__asm __volatile("outb %0,%w1" : : "a" (data), "d" (port));
> +}
> +
> +static __inline void
> +outsb(unsigned port, const void *addr, int cnt)
> +{
> +	void *dummy1;
> +	int dummy2;
> +	__asm __volatile("cld\n\trepne\n\toutsb"		:
> +			 "=S" (dummy1), "=c" (dummy2)		:
> +			 "d" (port), "0" (addr), "1" (cnt));
> +}
> +
> +#define	outw(port, data) \
> +    (/* CONSTCOND */ __use_immediate_port(port) ? __outwc(port, data) : \
> +						__outw(port, data))
> +
> +static __inline void
> +__outwc(unsigned port, u_int16_t data)
> +{
> +	__asm __volatile("outw %0,%w1" : : "a" (data), "id" (port));
> +}
> +
> +static __inline void
> +__outw(unsigned port, u_int16_t data)
> +{
> +	__asm __volatile("outw %0,%w1" : : "a" (data), "d" (port));
> +}
> +
> +static __inline void
> +outsw(unsigned port, const void *addr, int cnt)
> +{
> +	void *dummy1;
> +	int dummy2;
> +	__asm __volatile("cld\n\trepne\n\toutsw"		:
> +			 "=S" (dummy1), "=c" (dummy2)		:
> +			 "d" (port), "0" (addr), "1" (cnt));
> +}
> +
> +#define	outl(port, data) \
> +    (/* CONSTCOND */ __use_immediate_port(port) ? __outlc(port, data) : \
> +						__outl(port, data))
> +
> +static __inline void
> +__outlc(unsigned port, u_int32_t data)
> +{
> +	__asm __volatile("outl %0,%w1" : : "a" (data), "id" (port));
> +}
> +
> +static __inline void
> +__outl(unsigned port, u_int32_t data)
> +{
> +	__asm __volatile("outl %0,%w1" : : "a" (data), "d" (port));
> +}
> +
> +static __inline void
> +outsl(unsigned port, const void *addr, int cnt)
> +{
> +	void *dummy1;
> +	int dummy2;
> +	__asm __volatile("cld\n\trepne\n\toutsl"		:
> +			 "=S" (dummy1), "=c" (dummy2)		:
> +			 "d" (port), "0" (addr), "1" (cnt));
> +}
> +
> +#endif
> +
> +
> +static struct pci_io_handle *
> +pci_device_netbsd_open_legacy_io(struct pci_io_handle *ret,
> +    struct pci_device *dev, pciaddr_t base, pciaddr_t size)
> +{
> +#if defined(__i386__)
> +	struct i386_iopl_args ia;
> +
> +	ia.iopl = 1;
> +	if (sysarch(I386_IOPL, &ia))
> +		return NULL;
> +
> +	ret->base = base;
> +	ret->size = size;
> +	return ret;
> +#elif defined(__amd64__)
> +	struct x86_64_iopl_args ia;
> +
> +	ia.iopl = 1;
> +	if (sysarch(X86_64_IOPL, &ia))
> +		return NULL;
> +
> +	ret->base = base;
> +	ret->size = size;
> +	return ret;
> +#elif defined(PCI_MAGIC_IO_RANGE)
> +	ret->memory = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED,
> +	    aperturefd, PCI_MAGIC_IO_RANGE + base);

Hmm where is aperturefd defined in the NetBSD case ? (I know it's is
defined as static in  openbsd_pci.c, but I can't find the similar hack
for NetBSD -- and it should not be needed in NetBSD's case where all
memory can be be mapped through the /dev/pci* entry).

BTW the same issue is apparently found in freebsd_pci.c, so I may be
missing something...

> +	if (ret->memory == MAP_FAILED)
> +		return NULL;
> +
> +	ret->base = base;
> +	ret->size = size;
> +	return ret;
> +#else
> +	return NULL;
> +#endif
> +}
> +
> +static uint32_t
> +pci_device_netbsd_read32(struct pci_io_handle *handle, uint32_t reg)
> +{
> +#if defined(__i386__) || defined(__amd64__)
> +	return inl(handle->base + reg);
> +#else
> +	return *(uint32_t *)((uintptr_t)handle->memory + reg);
> +#endif
> +}
> +
> +static uint16_t
> +pci_device_netbsd_read16(struct pci_io_handle *handle, uint32_t reg)
> +{
> +#if defined(__i386__) || defined(__amd64__)
> +	return inw(handle->base + reg);
> +#else
> +	return *(uint16_t *)((uintptr_t)handle->memory + reg);
> +#endif
> +}
> +
> +static uint8_t
> +pci_device_netbsd_read8(struct pci_io_handle *handle, uint32_t reg)
> +{
> +#if defined(__i386__) || defined(__amd64__)
> +	return inb(handle->base + reg);
> +#else
> +	return *(uint8_t *)((uintptr_t)handle->memory + reg);
> +#endif
> +}
> +
> +static void
> +pci_device_netbsd_write32(struct pci_io_handle *handle, uint32_t reg,
> +    uint32_t data)
> +{
> +#if defined(__i386__) || defined(__amd64__)
> +	outl(handle->base + reg, data);
> +#else
> +	*(uint16_t *)((uintptr_t)handle->memory + reg) = data;
> +#endif
> +}
> +
> +static void
> +pci_device_netbsd_write16(struct pci_io_handle *handle, uint32_t reg,
> +    uint16_t data)
> +{
> +#if defined(__i386__) || defined(__amd64__)
> +	outw(handle->base + reg, data);
> +#else
> +	*(uint8_t *)((uintptr_t)handle->memory + reg) = data;
> +#endif
> +}
> +
> +static void
> +pci_device_netbsd_write8(struct pci_io_handle *handle, uint32_t reg,
> +    uint8_t data)
> +{
> +#if defined(__i386__) || defined(__amd64__)
> +	outb(handle->base + reg, data);
> +#else
> +	*(uint32_t *)((uintptr_t)handle->memory + reg) = data;
> +#endif
> +}
> +
> +static int
> +pci_device_netbsd_map_legacy(struct pci_device *dev, pciaddr_t base,
> +    pciaddr_t size, unsigned map_flags, void **addr)
> +{
> +	struct pci_device_mapping map;
> +	int err;
> +
> +	map.base = base;
> +	map.size = size;
> +	map.flags = map_flags;
> +	map.memory = NULL;
> +	err = pci_device_netbsd_map_range(dev, &map);
> +	*addr = map.memory;
> +
> +	return err;
> +}
> +
> +static int
> +pci_device_netbsd_unmap_legacy(struct pci_device *dev, void *addr,
> +    pciaddr_t size)
> +{
> +	struct pci_device_mapping map;
> +
> +	map.memory = addr;
> +	map.size = size;
> +	map.flags = 0;
> +	return pci_device_netbsd_unmap_range(dev, &map);
> +}
> +
>  static const struct pci_system_methods netbsd_pci_methods = {
>  	.destroy = pci_system_netbsd_destroy,
>  	.destroy_device = NULL,
> @@ -538,6 +864,15 @@ static const struct pci_system_methods netbsd_pci_methods = {
>  #else
>  	.boot_vga = NULL,
>  #endif
> +	.open_legacy_io = pci_device_netbsd_open_legacy_io,
> +	.read32 = pci_device_netbsd_read32,
> +	.read16 = pci_device_netbsd_read16,
> +	.read8 = pci_device_netbsd_read8,
> +	.write32 = pci_device_netbsd_write32,
> +	.write16 = pci_device_netbsd_write16,
> +	.write8 = pci_device_netbsd_write8,
> +	.map_legacy = pci_device_netbsd_map_legacy,
> +	.unmap_legacy = pci_device_netbsd_unmap_legacy,
>  };
>  
>  int
> -- 
> 1.8.2.3
> 
> _______________________________________________
> xorg-devel at lists.x.org: X.Org development
> Archives: http://lists.x.org/archives/xorg-devel
> Info: http://lists.x.org/mailman/listinfo/xorg-devel

-- 
Matthieu Herrb


More information about the xorg-devel mailing list