[Uha-devel] CVS: uha/lib HEADER, NONE, 1.1 Makefile, NONE, 1.1 bswap.h, NONE, 1.1 config.h, NONE, 1.1 config.mak, NONE, 1.1 exported.c, NONE, 1.1 iopl.c, NONE, 1.1 linux_proc.c, NONE, 1.1 mtrr.c, NONE, 1.1 pci.c, NONE, 1.1 pci.db, NONE, 1.1 pci.h, NONE, 1.1 pci_db2c.awk, NONE, 1.1 pci_helper.c, NONE, 1.1 pci_helper.h, NONE, 1.1 ports.c, NONE, 1.1 svgahelper.c, NONE, 1.1 uha.h, NONE, 1.1 uha_test.c, NONE, 1.1

Alex Beregszaszi alex at mplayerhq.hu
Thu Aug 18 14:54:02 CEST 2005


Update of /cvsroot/uha/uha/lib
In directory mail:/home/alex/uha/uha/lib

Added Files:
	HEADER Makefile bswap.h config.h config.mak exported.c iopl.c 
	linux_proc.c mtrr.c pci.c pci.db pci.h pci_db2c.awk 
	pci_helper.c pci_helper.h ports.c svgahelper.c uha.h 
	uha_test.c 
Log Message:
initial commit

--- NEW FILE: HEADER ---
/*
 * UHA exported functions
 * Copyright (c) 2005 Alex Beregszaszi
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */

/**
 * @file exported.c
 * @brief
 *     UHA exported functions
 * @author Alex Beregszaszi
 */


--- NEW FILE: Makefile ---
include config.mak

NAME = libuha
MAJOR_VERSION = 0
MINOR_VERSION = 1
VERSION = $(MAJOR_VERSION).$(MINOR_VERSION) 

ifeq ($(TARGET_OS),CYGWIN)
SHORTNAME = $(NAME).dll
else
SHORTNAME = $(NAME).so.$(MAJOR_VERSION)
SONAME_FLAGS = -Wl,-soname,$(SHORTNAME)
VSHORTNAME = $(NAME).so
endif
ifeq ($(TARGET_WIN32),yes)
LIBNAME = $(NAME).a
SHORTNAME = $(NAME).a
else
LIBNAME = $(NAME).so.$(VERSION)
endif

SRCS = pci_names.c exported.c iopl.c mtrr.c pci.c ports.c svgahelper.c linux_proc.c
OBJS = $(SRCS:.c=.o)

CFLAGS = $(OPTFLAGS) -fPIC -I. -I.. -g3
LIBS = 
ifeq ($(TARGET_OS),OpenBSD)
ifeq ($(TARGET_ARCH_X86),yes)
LIBS += -li386
endif
endif

# If you want libdha to use svgalib_helper for hardware access,
# uncomment this statement, and change the -I to the correct directory
# that includes svgalib_helper.o:
ifneq ($(wildcard svgalib_helper),)
CFLAGS += -DDEV_SVGA=\"/dev/svga\" -DCONFIG_SVGAHELPER -Isvgalib_helper/
endif

.SUFFIXES: .c .o

# .PHONY: all clean

.c.o: pci_names.c
	$(CC) -c $(CFLAGS) -o $@ $<

$(LIBNAME): $(OBJS)
ifeq ($(TARGET_WIN32),yes)
	$(AR) r $(LIBNAME) $(OBJS)
else
	#$(CC) -shared $(SONAME_FLAGS) -o $(LIBNAME) $(OBJS) $(LIBS)
	$(CC) -shared -Wl,-soname -Wl,$(LIBNAME) -o $(LIBNAME) $(OBJS) $(LIBS)
	ln -sf $(LIBNAME) $(SHORTNAME)
	ln -sf $(LIBNAME) $(VSHORTNAME)
endif

libuha.a:
	$(AR) r libuha.a $(OBJS)

uha_test: uha_test.c $(LIBNAME) libuha.a
	$(RM) libuha.a
	$(AR) r libuha.a $(OBJS)
	$(CC) -o uha_test uha_test.c $(NAME).a

all: $(LIBNAME) $(SHORTNAME) uha_test

pci_names.c:
	LC_ALL=C $(AWK) -f pci_db2c.awk pci.db

clean:
	rm -f *.o *.so *.so.* *~

distclean:
	rm -f Makefile.bak *.o *.so *.so.* test *~ .depend
	rm -f pci_dev_ids.c pci_ids.h pci_names.c pci_names.h pci_vendors.h

dep: depend

depend: pci_names.c
	$(CC) -MM $(CFLAGS) $(SRCS) 1>.depend

install:
	mkdir -p $(LIBDIR)
	install -m 755 -s -p $(LIBNAME) $(LIBDIR)/$(LIBNAME)
	rm -f $(LIBDIR)/$(NAME).so
	ln -sf $(LIBNAME) $(LIBDIR)/$(SHORTNAME)
ifeq ($(TARGET_OS),OpenBSD)
	ldconfig -R
else
	ldconfig
endif

uninstall:
	rm -f $(LIBDIR)/$(NAME).so $(LIBDIR)/$(SHORTNAME) $(LIBDIR)/$(LIBNAME)
ifeq ($(TARGET_OS),OpenBSD)
	ldconfig -R
else
	ldconfig
endif

#
# include dependency files if they exist
#
ifneq ($(wildcard .depend),)
include .depend
endif

--- NEW FILE: bswap.h ---
// FIXME
// License: GPL
// From: MPlayer

#ifndef __BSWAP_H__
#define __BSWAP_H__

#ifdef HAVE_BYTESWAP_H
#include <byteswap.h>
#else

#include <inttypes.h>

#ifdef ARCH_X86_64
#  define LEGACY_REGS "=Q"
#else
#  define LEGACY_REGS "=q"
#endif

#if defined(ARCH_X86) || defined(ARCH_X86_64)
static inline uint16_t ByteSwap16(uint16_t x)
{
  __asm("xchgb %b0,%h0"	:
        LEGACY_REGS (x)	:
        "0" (x));
    return x;
}
#define bswap_16(x) ByteSwap16(x)

static inline uint32_t ByteSwap32(uint32_t x)
{
#if __CPU__ > 386
 __asm("bswap	%0":
      "=r" (x)     :
#else
 __asm("xchgb	%b0,%h0\n"
      "	rorl	$16,%0\n"
      "	xchgb	%b0,%h0":
      LEGACY_REGS (x)		:
#endif
      "0" (x));
  return x;
}
#define bswap_32(x) ByteSwap32(x)

static inline uint64_t ByteSwap64(uint64_t x)
{
#ifdef ARCH_X86_64
  __asm("bswap	%0":
        "=r" (x)     :
        "0" (x));
  return x;
#else
  register union { __extension__ uint64_t __ll;
          uint32_t __l[2]; } __x;
  asm("xchgl	%0,%1":
      "=r"(__x.__l[0]),"=r"(__x.__l[1]):
      "0"(bswap_32((unsigned long)x)),"1"(bswap_32((unsigned long)(x>>32))));
  return __x.__ll;
#endif
}
#define bswap_64(x) ByteSwap64(x)

#elif defined(ARCH_SH4)

static inline uint16_t ByteSwap16(uint16_t x) {
	__asm__("swap.b %0,%0":"=r"(x):"0"(x));
	return x;
}

static inline uint32_t ByteSwap32(uint32_t x) {
	__asm__(
	"swap.b %0,%0\n"
	"swap.w %0,%0\n"
	"swap.b %0,%0\n"
	:"=r"(x):"0"(x));
	return x;
}

#define bswap_16(x) ByteSwap16(x)
#define bswap_32(x) ByteSwap32(x)

static inline uint64_t ByteSwap64(uint64_t x)
{
    union { 
        uint64_t ll;
        struct {
           uint32_t l,h;
        } l;
    } r;
    r.l.l = bswap_32 (x);
    r.l.h = bswap_32 (x>>32);
    return r.ll;
}
#define bswap_64(x) ByteSwap64(x)

#else

#define bswap_16(x) (((x) & 0x00ff) << 8 | ((x) & 0xff00) >> 8)
			

// code from bits/byteswap.h (C) 1997, 1998 Free Software Foundation, Inc.
#define bswap_32(x) \
     ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >>  8) | \
      (((x) & 0x0000ff00) <<  8) | (((x) & 0x000000ff) << 24))

static inline uint64_t ByteSwap64(uint64_t x)
{
    union { 
        uint64_t ll;
        uint32_t l[2]; 
    } w, r;
    w.ll = x;
    r.l[0] = bswap_32 (w.l[1]);
    r.l[1] = bswap_32 (w.l[0]);
    return r.ll;
}
#define bswap_64(x) ByteSwap64(x)

#endif	/* !ARCH_X86 */

#endif	/* !HAVE_BYTESWAP_H */

// be2me ... BigEndian to MachineEndian
// le2me ... LittleEndian to MachineEndian

#ifdef WORDS_BIGENDIAN
#define be2me_16(x) (x)
#define be2me_32(x) (x)
#define be2me_64(x) (x)
#define le2me_16(x) bswap_16(x)
#define le2me_32(x) bswap_32(x)
#define le2me_64(x) bswap_64(x)
#else
#define be2me_16(x) bswap_16(x)
#define be2me_32(x) bswap_32(x)
#define be2me_64(x) bswap_64(x)
#define le2me_16(x) (x)
#define le2me_32(x) (x)
#define le2me_64(x) (x)
#endif

#endif /* __BSWAP_H__ */

--- NEW FILE: config.h ---
#ifndef _CONFIG_H
#define _CONFIG_H

#undef CONFIG_DHAHELPER

#endif /* _CONFIG_H */

--- NEW FILE: config.mak ---
AR = ar
CC = gcc
AWK = awk

TAGRET_ARCH_X86 = yes
TARGET_OS = Linux

--- NEW FILE: exported.c ---
/*
 * UHA exported functions
 * Copyright (c) 2005 Alex Beregszaszi
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */

/**
 * @file exported.c
 * @brief
 *     UHA exported functions
 * @author Alex Beregszaszi
 */

#include "uha.h"

/**
 * allocates memory for the context with malloc
 */     
uha_context *uha_allocate(void)
{
    return malloc(sizeof(uha_context));
}

/**
 * deallocates memory of the context with free
 * @param the context pointer
 */     
void uha_deallocate(uha_context *c)
{
    free(c);
}

/**
 * initializes the context
 * @param context handler, you need to allocate it
 */
static int uha_probe(uha_context *c)
{
    int fd, flags = UHA_FLAG_BASIC;

#ifdef CONFIG_UHAHELPER
    if (uha_probe_uhahelper(c) == UHA_OK)
	flags |= UHA_FLAG_UHAHELPER;
#endif
#ifdef CONFIG_SVGAHELPER
    if (uha_probe_svgahelper(c) == UHA_OK)
	flags |= UHA_FLAG_SVGAHELPER;
#endif
#ifdef CONFIG_DHAHELPER
    if (uha_probe_dhahelper(c) == UHA_OK)
	flags |= UHA_FLAG_DHAHELPER;
#endif
    if (uha_probe_iopl(c) == UHA_OK)
	flags |= UHA_FLAG_IOPL;
    return flags;
}

int uha_dummy_error()
{
    return UHA_ERROR;
}

int uha_dummy_ok()
{
    return UHA_OK;
}

int uha_init(uha_context *c)
{
    // init everything with uha_dummy_error
    c->enable_io = uha_dummy_error;

    c->flags = uha_probe(c);

    if (c->flags & UHA_FLAG_IOPL)
	uha_init_iopl(c);
    uha_init_ports(c);
    uha_linux_proc(c);
    if (uha_probe_pci(c) == UHA_OK)
	uha_init_pci(c);

#ifdef CONFIG_SVGAHELPER
    if (c->flags & UHA_FLAG_SVGAHELPER)
	uha_init_svgahelper(c);
#endif
}

/**
 * deinitializes the context
 * @param context handler, you need to free it
 */     
int uha_exit(uha_context *c)
{
}

--- NEW FILE: iopl.c ---
/*
 * iopl() support
 * Copyright (c) 2005 Alex Beregszaszi
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */

/**
 * @file iopl.c
 * @brief
 *     iopl() support
 * @author Alex Beregszaszi
 */

#include "uha.h"

#ifdef __linux__
#if defined(__i386__)
    #include <sys/perm.h>
#elif defined(__sparc__)  || defined(__powerpc__)
    #define iopl(x) (0)
#elif
    #include <sys/io.h>
#endif

#elif defined(__NetBSD__) || defined(__OpenBSD__)
    #include <machine/sysarch.h>
#endif

static int enable_io(uha_context *c)
{
#ifdef __linux__
    if (!iopl(3))
	return UHA_OK;
#elif defined(__NetBSD__) || defined(__OpenBSD__)
    if (!i386_iopl(1))
	return UHA_OK;
#endif
    return UHA_ERROR;
}

static int disable_io(uha_context *c)
{
#ifdef __linux__
    if (!iopl(0))
	return UHA_OK;
#elif defined(__NetBSD__) || defined(__OpenBSD__)
    if (!i386_iopl(0))
	return UHA_OK;
#endif
    return UHA_ERROR;
}

int uha_probe_iopl(uha_context *c)
{
    if (enable_io(c) == UHA_OK)
    {
	disable_io(c);
	return UHA_OK;
    }
    return UHA_ERROR;
}

int uha_init_iopl(uha_context *c)
{
    c->enable_io = enable_io;
    c->disable_io = disable_io;
    
    return UHA_OK;
}

--- NEW FILE: linux_proc.c ---
/*
 * PCI access through Linux /proc
 * Copyright (c) 2004 Colin Leroy <colino at colino.net>
 * Copyright (c) 2005 Alex Beregszaszi
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */

/**
 * @file linux_proc.c
 * @brief
 *     PCI access through Linux /proc
 * @author Colin Leroy <colino at colino.net>, Alex Beregszaszi
 */

#include <inttypes.h>
#include <fcntl.h>
#include "uha.h"
#include "bswap.h"

#ifdef __linux__
static int pci_proc_read32(uha_context *c, int bus, int dev, int func, int cmd)
{
    char path[256];
    int fd;
    uint32_t ret = 0;
    
    snprintf(path, 256, "/proc/bus/pci/%02d/%02x.0", bus, dev);
    
    if ((fd = open(path, O_RDONLY|O_SYNC)) != -1)
	if (pread(fd, &ret, 4, cmd) == 4)
	    ret = le2me_32(ret);

    if (fd > 0)
	close (fd);

    return ret;
}
#endif

int uha_linux_proc(uha_context *c)
{
#ifdef __linux__
    c->pci_config_type = 1; // assume...

    c->pci_read32 = pci_proc_read32;
    c->pci_write32 = uha_dummy_error;
#else
    c->pci_config_type = -1;
#endif
    
    return UHA_OK;
}

--- NEW FILE: mtrr.c ---
/*
 * MTRR support
 * Copyright (c) 2002 Nick Kurshev
 * Copyright (c) 2005 Alex Beregszaszi
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */

/**
 * @file mtrr.c
 * @brief
 *     MTRR support
 * @author Alex Beregszaszi
 */

#include "config.h"
#include "uha.h"

#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>

#ifdef CONFIG_DHAHELPER
#include "kernelhelper/dhahelper.h"
#include "libdha.h"
#endif

#if defined (__i386__) && defined (__NetBSD__)
#include <sys/param.h>
#if __NetBSD_Version__ > 105240000
#include <stdint.h>
#include <stdlib.h>
#include <machine/mtrr.h>
#include <machine/sysarch.h>
#endif
#endif

#ifdef CONFIG_DHAHELPER
int dhahelper_mtrr_set(unsigned base,unsigned size,int type)
{
    int dhahelper_fd;
    dhahelper_fd = open("/dev/dhahelper",O_RDWR);
    if(dhahelper_fd > 0)
    {
	int retval;
	dhahelper_mtrr_t mtrrs;
	mtrrs.operation = MTRR_OP_ADD;
	mtrrs.start = base;
	mtrrs.size = size;
	mtrrs.type = type;
	retval = ioctl(dhahelper_fd, DHAHELPER_ACK_IRQ, &mtrrs);
	close(dhahelper_fd);
	return retval;
    }
#endif

#if defined (__NetBSD__) && (__NetBSD_Version__) > 105240000
static int mtrr_set(uha_context *c, int base, int size, int type)
{
    struct mtrr *mtrrp;
    int n;

    mtrrp = malloc(sizeof (struct mtrr));
    mtrrp->base = base;
    mtrrp->len = size;
    mtrrp->type = type;  
    mtrrp->flags = MTRR_VALID | MTRR_PRIVATE;
    n = 1;

    if (i386_set_mtrr(mtrrp, &n) < 0) {
	free(mtrrp);
	return errno;
    }
    free(mtrrp);
    return 0;
}
#elif defined(__linux__)
static int mtrr_set(uha_context *c, int base, int size, int type)
{
    FILE * mtrr_fd;
    char * stype;
    switch(type)
    {
	case MTRR_TYPE_UNCACHABLE: stype = "uncachable"; break;
	case MTRR_TYPE_WRCOMB:	   stype = "write-combining"; break;
	case MTRR_TYPE_WRTHROUGH:  stype = "write-through"; break;
	case MTRR_TYPE_WRPROT:	   stype = "write-protect"; break;
	case MTRR_TYPE_WRBACK:	   stype = "write-back"; break;
	default:		   return EINVAL;
    }
    mtrr_fd = fopen("/proc/mtrr","wt");
    if(mtrr_fd)
    {
	char sout[256];
	unsigned wr_len;
	sprintf(sout,"base=0x%08X size=0x%08X type=%s\n",base,size,stype);
	wr_len = fprintf(mtrr_fd,sout);
	/*printf("MTRR: %s\n",sout);*/
	fclose(mtrr_fd);
	return wr_len == strlen(sout) ? 0 : EPERM;
    }
}
#else
static int mtrr_set(uha_context *c)
{
    return UHA_ERROR;
}
#endif

int uha_init_mtrr(uha_context *c)
{
    c->mtrr_set = mtrr_set;
    return UHA_OK;
}

--- NEW FILE: pci.c ---
/*
 * PCI access through standard ports
 * Copyright (c) 2005 Alex Beregszaszi
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */

/**
 * @file pci.c
 * @brief
 *     PCI access through standard ports
 * @author Alex Beregszaszi
 */

#include <inttypes.h>
#include "uha.h"
#include "pci.h"

static int pci_detect(uha_context *c)
{
    uint8_t tmp1, tmp2;

    uha_port_write8(c, PCI_MODE2_ENABLE_REG, 0x00);
    uha_port_write8(c, PCI_MODE2_FORWARD_REG, 0x00);
    tmp1 = uha_port_read8(c, PCI_MODE2_ENABLE_REG);
    tmp2 = uha_port_read8(c, PCI_MODE2_FORWARD_REG);
    if ((tmp1 == 0x00) && (tmp2 == 0x00))
	return 2; //< conf type 2
    else
    {
	uint32_t tmpl1, tmpl2;
	
	tmpl1 = uha_port_read32(c, PCI_MODE1_ADDRESS_REG);
	uha_port_write32(c, PCI_MODE1_ADDRESS_REG, PCI_EN);
	tmpl2 = uha_port_read32(c, PCI_MODE1_ADDRESS_REG);
	uha_port_write32(c, PCI_MODE1_ADDRESS_REG, tmpl1);
	if (tmpl2 == PCI_EN)
	    return 1; //< conf type 1
    }
    
    return -1; //< no pci
}

#define pci_mode1_select(c, bus, dev, func, cmd) \
    uha_port_write32(c, PCI_MODE1_ADDRESS_REG, \
		    PCI_EN | (bus<<16) | (dev<<11) | (func<<8) | cmd)

static int pci_mode1_read32(uha_context *c, int bus, int dev, int func, int cmd)
{
    pci_mode1_select(c, bus, dev, func, cmd);
    return uha_port_read32(c,  PCI_MODE1_DATA_REG);
}

static int pci_mode1_write32(uha_context *c, int bus, int dev, int func, int cmd, int value)
{
    pci_mode1_select(c, bus, dev, func, cmd);
    return uha_port_write32(c,  PCI_MODE1_DATA_REG, value);
}

// FIXME: untested!
static int pci_mode2_read32(uha_context *c, int bus, int dev, int func, int cmd)
{
    uint32_t ret;
    
    uha_port_write8(c, PCI_MODE2_ENABLE_REG, 0xF1);
    uha_port_write8(c, PCI_MODE2_FORWARD_REG, bus);
    
    ret = uha_port_read32(c, 0xc000+(dev*0x100));

    uha_port_write8(c, PCI_MODE2_ENABLE_REG, 0x00);

    return ret;
}

static int pci_mode2_write32(uha_context *c, int bus, int dev, int func, int cmd, int value)
{
    uint32_t ret;
    
    uha_port_write8(c, PCI_MODE2_ENABLE_REG, 0xF1);
    uha_port_write8(c, PCI_MODE2_FORWARD_REG, bus);
    
    ret = uha_port_write32(c, 0xc000+(dev*0x100), value);

    uha_port_write8(c, PCI_MODE2_ENABLE_REG, 0x00);

    return ret;
}

int uha_probe_pci(uha_context *c)
{
    if (!uha_is_port(c) || !uha_is_io(c))
	return UHA_ERROR;
    uha_enable_io(c);
    if (pci_detect(c) < 0)
	return UHA_ERROR;
    return UHA_OK;
}

int uha_init_pci(uha_context *c)
{
    c->pci_config_type = pci_detect(c);

    if (c->pci_config_type == 1)
    {
	c->pci_read32 = pci_mode1_read32;
	c->pci_write32 = pci_mode1_write32;
    } else if (c->pci_config_type == 2)
    {
//	uha_log("PCI Mode2 support untested, take care!\n");
	c->pci_read32 = pci_mode2_read32;
	c->pci_write32 = pci_mode2_write32;
    }    
    
    return UHA_OK;
}

--- NEW FILE: pci.db ---
v	0000	Gammagraphx, Inc.	0	
v	001a	Ascend Communications, Inc.	0	
v	0033	Paradyne corp.	0	
v	003d	Lockheed Martin-Marietta Corp	0	
v	0059	Tiger Jet Network Inc. (Wrong ID)	0	Real TJN ID is e159, but they got it wrong several times --mj
v	0070	Hauppauge computer works Inc.	0	
d	00704000	WinTV PVR-350	0	
d	00704001	WinTV PVR-250 (v1)	0	
d	00704009	WinTV PVR-250	0	
d	00704801	WinTV PVR-250 MCE	0	
v	0071	Nebula Electronics Ltd.	0	
v	0095	Silicon Image, Inc. (Wrong ID)	0	
d	00950680	Ultra ATA/133 IDE RAID CONTROLLER CARD	0	
v	0100	Ncipher Corp Ltd	0	
v	018a	LevelOne	0	018a is not LevelOne but there is a board misprogrammed
d	018a0106	FPC-0106TX misprogrammed [RTL81xx]	0	
v	021b	Compaq Computer Corporation	0	021b is not Compaq but there is a board misprogrammed
d	021b8139	HNE-300 (RealTek RTL8139c) [iPaq Networking]	0	
v	0280		1	Unknown. Found as an subsystem vendor for Tvia Cyberpro on the Fujitsu-Siemens Activy 3xx
[...10234 lines suppressed...]
d	f1d0cafe	Kona SD	1	Updated - Kona and Xena have different PCI IDs
d	f1d0cfee	Xena LS/SD-22-DA/SD-DA	1	
d	f1d0dcaf	Kona HD	1	Updated - Kona and Xena have different PCI IDs
d	f1d0dfee	Xena HD-DA	1	
d	f1d0efac	KONA SD SMPTE 259M I/O	0	
d	f1d0efac	Xena SD-MM/SD-22-MM	1	
d	f1d0facd	KONA HD SMPTE 292M I/O	0	
d	f1d0facd	Xena HD-MM	1	Updated - Kona and Xena have different PCI IDs
v	fa57	Interagon AS	0	
d	fa570001	PMC [Pattern Matching Chip]	0	
v	febd	Ultraview Corp.	0	
v	feda	Broadcom Inc (nee Epigram)	0	
d	fedaa0fa	BCM4210 iLine10 HomePNA 2.0	0	
d	fedaa10e	BCM4230 iLine10 HomePNA 2.0	0	
v	fede	Fedetec Inc.	0	IT & Telecom company, develops PCI Trunk cards <www.fedetec.es>
d	fede0003	TABIC PCI v3	0	
v	fffe	VMWare Inc	0	
d	fffe0405	Virtual SVGA 4.0	0	
d	fffe0710	Virtual SVGA	0	
v	ffff	Illegal Vendor ID	0	

--- NEW FILE: pci.h ---
#ifndef _UHA_PCI_H
#define _UHA_PCI_H 1

#ifdef __alpha__
#define PCI_EN 0x00000000
#else
#define PCI_EN 0x80000000
#endif

#define PCI_MODE1_ADDRESS_REG 0xcf8
#define PCI_MODE1_DATA_REG 0xcfc

#define PCI_MODE2_ENABLE_REG 0xcf8
#define PCI_MODE2_FORWARD_REG 0xcfa

#endif

--- NEW FILE: pci_db2c.awk ---
# This file converts given pci.db to "C" source and header files
# For latest version of pci ids see: http://pciids.sf.net
# Copyright 2002 Nick Kurshev
#
# Usage: awk -f pci_db2c.awk pci.db
#
# Tested with Gawk v 3.0.x and Mawk 1.3.3
# But it should work with standard Awk implementations (hopefully).
# (Nobody tested it with Nawk, but it should work, too).
#

BEGIN {

    if(ARGC != 2) {
# check for arguments:
	print "Usage awk -f pci_db2c.awk pci.db (and make sure pci.db file exists first)";
	exit(1);
    }
    in_file = ARGV[1];
    vendor_file = "pci_vendors.h";
    ids_file = "pci_ids.h"
    name_file = "pci_names.c"
    name_h_file = "pci_names.h"
    dev_ids_file = "pci_dev_ids.c"
    line=0;
# print out head lines
    print_head(vendor_file);
    print_head(ids_file);
    print_head(name_file);
    print_head(name_h_file);
    print_head(dev_ids_file);
    print "#ifndef PCI_VENDORS_INCLUDED" >vendor_file
    print "#define PCI_VENDORS_INCLUDED 1">vendor_file
    print "" >vendor_file
    print "#ifndef PCI_IDS_INCLUDED" >ids_file
    print "#define PCI_IDS_INCLUDED 1">ids_file
    print "" >ids_file
    print "#include \"pci_vendors.h\"">ids_file
    print "" >ids_file

    print "#ifndef PCI_NAMES_INCLUDED" >name_h_file
    print "#define PCI_NAMES_INCLUDED 1">name_h_file
    print "" >name_h_file
    print_name_struct(name_h_file);
    print "#include <stddef.h>">name_file
    print "#include \"pci_names.h\"">name_file
    print "#include \"pci_dev_ids.c\"">name_file
    print "">name_file
    print "static struct vendor_id_s vendor_ids[] = {">name_file
    first_pass=1;
    init_name_db();
    while(getline <in_file) 
    {
# count up lines
	line++;
	n=split($0, field, "[\t]");
	name_field = kill_double_quoting(field[3])
	if(field[1] == "v" && length(field[3])>0 && field[4] == "0")
	{
		init_device_db()
		svend_name = get_short_vendor_name(field[3])
		printf("#define VENDOR_%s\t", svend_name) >vendor_file;
		if(length(svend_name) < 9) printf("\t") >vendor_file;
		printf("0x%s /*%s*/\n",field[2], name_field) >vendor_file;
		printf("{ 0x%s, \"%s\", dev_lst_%s },\n",field[2], name_field, field[2]) >name_file;
		printf("/* Vendor: %s: %s */\n", field[2], name_field) > ids_file
		if(first_pass == 1) { first_pass=0; }
		else	{ print "{ 0xFFFF,  NULL }\n};" >dev_ids_file; }
		printf("static const struct device_id_s dev_lst_%s[]={\n", field[2])>dev_ids_file
	}
	if(field[1] == "d" && length(field[3])>0 && field[4] == "0")
	{
		sdev_name = get_short_device_name(field[3])
		full_name = sprintf("#define DEVICE_%s_%s", svend_name, sdev_name);
		printf("%s\t", full_name) >ids_file
		if(length(full_name) < 9) printf("\t") >ids_file;
		if(length(full_name) < 17) printf("\t") >ids_file;
		if(length(full_name) < 25) printf("\t") >ids_file;
		if(length(full_name) < 32) printf("\t") >ids_file;
		if(length(full_name) < 40) printf("\t") >ids_file;
		if(length(full_name) < 48) printf("\t") >ids_file;
		printf("0x%s /*%s*/\n", substr(field[2], 5), name_field) >ids_file
		printf("{ 0x%s, \"%s\" },\n", substr(field[2], 5), name_field) >dev_ids_file
	}
	if(field[1] == "s" && length(field[3])>0 && field[4] == "0")
	{
		subdev_name = get_short_subdevice_name(field[3])
		full_name = sprintf("#define SUBDEVICE_%s_%s", svend_name, subdev_name)
		printf("\t%s\t", full_name) >ids_file
		if(length(full_name) < 9) printf("\t") >ids_file;
		if(length(full_name) < 17) printf("\t") >ids_file;
		if(length(full_name) < 25) printf("\t") >ids_file;
		if(length(full_name) < 32) printf("\t") >ids_file;
		if(length(full_name) < 40) printf("\t") >ids_file;
		printf("0x%s /*%s*/\n", substr(field[2], 9), name_field) >ids_file
	}
    }
    print "Total lines parsed:", line;
    print "">vendor_file
    print "#endif/*PCI_VENDORS_INCLUDED*/">vendor_file
    print "">ids_file
    print "#endif/*PCI_IDS_INCLUDED*/">ids_file
    print "">name_h_file
    print "#endif/*PCI_NAMES_INCLUDED*/">name_h_file
    print "};">name_file
    print "{ 0xFFFF,  NULL }" >dev_ids_file;
    print "};">dev_ids_file
    print_func_bodies(name_file);
}

function print_head( out_file)
{
    print "/*" >out_file;
    printf(" * File: %s\n", out_file) >out_file;
    printf(" * This file was generated automatically. Don't modify it.\n") >out_file;
    print "*/" >out_file;
    return;
}

function print_name_struct(out_file)
{
   print "#ifdef __cplusplus" >out_file
   print "extern \"C\" {" >out_file
   print "#endif" >out_file
   print "">out_file
   print "struct device_id_s" >out_file
   print "{" >out_file
   print "\tunsigned short\tid;" >out_file
   print "\tconst char *\tname;" >out_file
   print "};" >out_file
   print "">out_file
   print "struct vendor_id_s" >out_file
   print "{" >out_file
   print "\tunsigned short\tid;" >out_file
   print "\tconst char *\tname;" >out_file
   print "\tconst struct device_id_s *\tdev_list;" >out_file
   print "};" >out_file
   print "extern const char *pci_vendor_name(unsigned short id);">out_file
   print "extern const char *pci_device_name(unsigned short vendor_id, unsigned short device_id);">out_file
   print "">out_file
   print "#ifdef __cplusplus" >out_file
   print "}" >out_file
   print "#endif" >out_file
   return
}

function print_func_bodies(out_file)
{
   print "">out_file
   print "const char *pci_vendor_name(unsigned short id)" >out_file
   print "{" >out_file
   print "  unsigned i;" >out_file
   print "  for(i=0;i<sizeof(vendor_ids)/sizeof(struct vendor_id_s);i++)">out_file
   print "  {" >out_file
   print "\tif(vendor_ids[i].id == id) return vendor_ids[i].name;" >out_file
   print "  }" >out_file
   print "  return NULL;" >out_file
   print "}">out_file
   print "" >out_file
   print "const char *pci_device_name(unsigned short vendor_id, unsigned short device_id)" >out_file
   print "{" >out_file
   print "  unsigned i, j;" >out_file
   print "  for(i=0;i<sizeof(vendor_ids)/sizeof(struct vendor_id_s);i++)">out_file
   print "  {" >out_file
   print "\tif(vendor_ids[i].id == vendor_id)" >out_file
   print "\t{" >out_file
   print "\t  j=0;" >out_file
   print "\t  while(vendor_ids[i].dev_list[j].id != 0xFFFF)" >out_file
   print "\t  {">out_file
   print "\t\tif(vendor_ids[i].dev_list[j].id == device_id) return vendor_ids[i].dev_list[j].name;">out_file
   print "\t\tj++;">out_file
   print "\t  };">out_file
   print "\t  break;" >out_file
   print "\t}" >out_file
   print "  }" >out_file
   print "  return NULL;">out_file
   print "}">out_file
   return
}

function kill_double_quoting(fld)
{
  n=split(fld,phrases, "[\"]");
  new_fld = phrases[1]
  for(i=2;i<=n;i++) new_fld = sprintf("%s\\\"%s", new_fld, phrases[i])
  return new_fld
}

function init_name_db()
{
  vendor_names[1]=""
}

function init_device_db()
{
#  delete device_names
  for( i in device_names ) delete device_names[i];
  device_names[1]=""
#  delete subdevice_names
  for( i in subdevice_names ) delete subdevice_names[i];
  subdevice_names[1] = ""
}

function get_short_vendor_name(from)
{
  n=split(from, name, "[ ]");
  new_name = toupper(name[1]);
  if(length(new_name)<3) new_name = sprintf("%s_%s", new_name, toupper(name[2]));
  n=split(new_name, name, "[^0-9A-Za-z]");
  svendor = name[1];
  for(i=2;i<=n;i++) svendor=sprintf("%s%s%s", svendor, length(name[i])?"_":"", name[i]);
  new_name = svendor;
  vend_suffix = 2;
# check for unique 
  while(new_name in vendor_names) 
  {
    new_name = sprintf("%s%u", svendor, vend_suffix)
    vend_suffix = vend_suffix + 1;
  }
# Add new name in array of vendor's names
  vendor_names[new_name] = new_name
  return new_name;
}

function get_short_device_name(from_name)
{
  n=split(from_name, name, "[ ]");
  new_name = toupper(name[1]);
  if(length(name[2])) new_name = sprintf("%s_%s", new_name, toupper(name[2]));
  if(length(name[3])) new_name = sprintf("%s_%s", new_name, toupper(name[3]));
  n=split(new_name, name, "[^0-9A-Za-z]");
  sdevice = name[1];
  for(i=2;i<=n;i++) sdevice=sprintf("%s%s%s", sdevice, length(name[i])?"_":"", name[i]);
  new_name = sdevice;
  dev_suffix = 2;
# check for unique 
  while(new_name in device_names) 
  {
    new_name = sprintf("%s%u", sdevice, dev_suffix)
    dev_suffix = dev_suffix + 1;
  }
# Add new name in array of device names
  device_names[new_name] = new_name
  return new_name;
}

function get_short_subdevice_name(from_name)
{
  n=split(from_name, name, "[ ]");
  new_name = toupper(name[1]);
  if(length(name[2])) new_name = sprintf("%s_%s", new_name, toupper(name[2]));
  if(length(name[3])) new_name = sprintf("%s_%s", new_name, toupper(name[3]));
  n=split(new_name, name, "[^0-9A-Za-z]");
  ssdevice = name[1];
  for(i=2;i<=n;i++) ssdevice=sprintf("%s%s%s", ssdevice, length(name[i])?"_":"", name[i]);
  new_name = ssdevice;
  sdev_suffix = 2;
# check for unique 
  while(new_name in subdevice_names) 
  {
    new_name = sprintf("%s%u", ssdevice, sdev_suffix)
    sdev_suffix = sdev_suffix + 1;
  }
# Add new name in array of subdevice names
  subdevice_names[new_name] = new_name
  return new_name;
}

--- NEW FILE: pci_helper.c ---
#include "uha.h"

pci_find_device(uha_context *c, int device, int vendor)
{
    uha_context *c = uha_allocate();
    
    uha_init(c);
    uha_enable_io(c);
    
    if (uha_is_pci(c))
    {
	int bus, card, func;

	for (bus = 0; bus < 4; bus++)
	    for (card = 0; card < 32; card++)
		for (func = 0; func < 8; func++)
		{
		    int ret = uha_pci_read32(c, bus, card, func, 0);
		    int vendor = ret & 0xffff, device = (ret >> 16) & 0xffff;

		    if (!vendor && !device) // subfunction not present
			break;

		    if (vendor != 0xffff && device != 0xffff)
			printf("device %02x:%02x.%1x: vendor=%x device=%x\n",
			    bus, card, func, vendor, device);
		}
    }
    else
    {
	printf("No pci support present - not testing\n");
    }
    uha_exit(c);
    uha_deallocate(c);
}

--- NEW FILE: pci_helper.h ---
#include <inttypes.h>

typedef struct uha_pci_config_table {
    union {
	uint32_t device_vendor;
	struct {
#ifdef WORDS_BIGENDIAN
	    uint16_t device;
	    uint16_t vendor;
#else
	    uint16_t vendor;
	    uint16_t device;
#endif
	} u.
    } a;
#define device_vendor a.device_vendor
#define vendor a.u.vendor
#define device a.u.device

    union {
	uint32_t status_command;
	struct {
#ifdef WORDS_BIGENDIAN
	    uint16_t command;
	    uint16_t status;
#else
	    uint16_t status;
	    uint16_t command;
#endif
	} u;
    } b;
#define status_command b.status_command
#define command b.u.command
#define status b.u.status

    union {
	uint32_t class_revision;
	struct {
#ifdef WORDS_BIGENDIAN
	    uint8_t base_class;
	    uint8_t sub_class;
	    uint8_t prog_if;
	    uint8_t rev_id;
#else
	    uint8_t rev_id;
	    uint8_t prog_if;
	    uint8_t sub_class;
	    uint8_t base_class;
#endif
	} u;
    } c;
#define status_command c.class_revision
#define base_class c.u.base_class
#define sub_class c.u.sub_class
#define prog_if c.u.prog_if
#define rev_id c.u.rev_id

    union {
	uint32_t header_latency;
	struct {
#ifdef WORDS_BIGENDIAN
	    uint8_t bist;
	    uint8_t header_type;
	    uint8_t latency;
	    uint8_t cl_size;
#else
	    uint8_t cl_size;
	    uint8_t latency;
	    uint8_t header_type;
	    uint8_t bist;
#endif
	} u;
    } d;
#define header_latency d.header_latency
#define bist d.u.bist
#define header_type d.u.header_type
#define latency d.u.latency
#define cl_size d.u.cl_size

    //// MISSING
    
    uint32_t reserved1;
    uint32_t reserved2;
    uint32_t baserom;
    uint32_t reserved3;
    uint32_t reserved4;
};

--- NEW FILE: ports.c ---
/*
 * Port I/O support
 * Copyright (c) 2005 Alex Beregszaszi
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */

/**
 * @file ports.c
 * @brief
 *     Port I/O support
 * @author Alex Beregszaszi
 */

#include "uha.h"

#if defined(__sparc__) && !defined(ASI_PL)
#define ASI_PL 0x88
#endif

#if !defined(__i386__) && !defined(__sparc__)
#warning "your system is not supported"
#endif

static int port_write8(uha_context *c, int port, int value)
{
#if defined(__i386__)
    __asm__ __volatile__("outb %0, %1" : : "a" ((char)value), "d" ((short)port));
#elif defined(__sparc__)
    __asm__ __volatile__("stba %0, [%1] %2" : : "r" (value), "r" (port), "i" (ASI_PL));
#endif
}

static int port_write16(uha_context *c, int port, int value)
{
#if defined(__i386__)
    __asm__ __volatile__("outw %0, %1" : : "a" ((short)value), "d" ((short)port));
#elif defined(__sparc__)
    __asm__ __volatile__("stha %0, [%1] %2" : : "r" (value), "r" (port), "i" (ASI_PL));
#endif
}

static int port_write32(uha_context *c, int port, int value)
{
#if defined(__i386__)
    __asm__ __volatile__("outl %0, %1" : : "a" (value), "d" ((short)port));
#elif defined(__sparc__)
    __asm__ __volatile__("sta %0, [%1] %2" : : "r" (value), "r" (port), "i" (ASI_PL));
#endif
}

static int port_read8(uha_context *c, int port)
{
    int ret = 0;
#if defined(__i386__)
    __asm__ __volatile__("inb %1, %0" : "=a" (ret) : "d" ((short)port));
#elif defined(__sparc__)
    __asm__ __volatile__("lduba [%1] %2, %0" : "=r" (ret) : "r" (port), "i" (ASI_PL));
#endif
    return ret;
}

static int port_read16(uha_context *c, int port)
{
    int ret = 0;
#if defined(__i386__)
    __asm__ __volatile__("inw %1, %0" : "=a" (ret) : "d" ((short)port));
#elif defined(__sparc__)
    __asm__ __volatile__("lduha [%1] %2, %0" : "=r" (ret) : "r" (port), "i" (ASI_PL));
#endif
    return ret;
}

static int port_read32(uha_context *c, int port)
{
    int ret = 0;
#if defined(__i386__)
    __asm__ __volatile__("inl %1, %0" : "=a" (ret) : "d" ((short)port));
#elif defined(__sparc__)
    __asm__ __volatile__("lda [%1] %2, %0" : "=r" (ret) : "r" (port), "i" (ASI_PL));
#endif
    return ret;
}

// FIXME uha_probe

int uha_init_ports(uha_context *c)
{
#if !defined(__i386__) && !defined(__sparc__)
    return UHA_ERROR;
#endif

    c->port_write8 = port_write8;
    c->port_write16 = port_write16;
    c->port_write32 = port_write32;
    c->port_read8 = port_read8;
    c->port_read16 = port_read16;
    c->port_read32 = port_read32;
    
    return UHA_OK;
}

--- NEW FILE: svgahelper.c ---
/*
 * svgahelper support
 * Copyright (c) 2005 Alex Beregszaszi
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */

/**
 * @file svgahelper.c
 * @brief
 *     svgahelper support
 * @author Alex Beregszaszi
 */

#include "uha.h"

#ifdef CONFIG_SVGAHELPER
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <svgalib_helper.h>

#ifndef SVGALIB_HELPER_IOC_MAGIC
/* svgalib 1.9.18+ compatibility ::atmos */
#define SVGALIB_HELPER_IOCSOUTB SVGAHELPER_OUTB
#define SVGALIB_HELPER_IOCSOUTW SVGAHELPER_OUTW
#define SVGALIB_HELPER_IOCSOUTL SVGAHELPER_OUTL
#define SVGALIB_HELPER_IOCGINB  SVGAHELPER_INB
#define SVGALIB_HELPER_IOCGINW  SVGAHELPER_INW
#define SVGALIB_HELPER_IOCGINL  SVGAHELPER_INL
#define SVGALIB_HELPER_IOCGPCIINB SVGAHELPER_PCIINB
#define SVGALIB_HELPER_IOCGPCIINW SVGAHELPER_PCIINW
#define SVGALIB_HELPER_IOCGPCIINL SVGAHELPER_PCIINL
#endif

#define svgahelper_fd c->reserved[0]

static int port_write8(uha_context *c, int port, int value)
{
    io_t iov;
    
    iov.val = value;
    iov.port = port;
    ioctl(svgahelper_fd, SVGALIB_HELPER_IOCSOUTB, &iov);
}

static int port_write16(uha_context *c, int port, int value)
{
    io_t iov;
    
    iov.val = value;
    iov.port = port;
    ioctl(svgahelper_fd, SVGALIB_HELPER_IOCSOUTW, &iov);
}

static int port_write32(uha_context *c, int port, int value)
{
    io_t iov;
    
    iov.val = value;
    iov.port = port;
    ioctl(svgahelper_fd, SVGALIB_HELPER_IOCSOUTL, &iov);
}

static int port_read8(uha_context *c, int port)
{
    io_t iov;
    
    iov.port = port;
    ioctl(svgahelper_fd, SVGALIB_HELPER_IOCGINB, &iov);
    
    return iov.val;
}

static int port_read16(uha_context *c, int port)
{
    io_t iov;
    
    iov.port = port;
    ioctl(svgahelper_fd, SVGALIB_HELPER_IOCGINW, &iov);
    
    return iov.val;
}

static int port_read32(uha_context *c, int port)
{
    io_t iov;
    
    iov.port = port;
    ioctl(svgahelper_fd, SVGALIB_HELPER_IOCGINL, &iov);
    
    return iov.val;
}

static int pci_read8(uha_context *c, int bus, int dev, int func, int cmd)
{
    pcic_t p;
    
    p.address = cmd;
    p.pcipos = (bus << 8) | (func << 5) | dev;
    
    ioctl(svgahelper_fd, SVGALIB_HELPER_IOCGPCIINB, &p);
    
    return p.val;
}

static int pci_read16(uha_context *c, int bus, int dev, int func, int cmd)
{
    pcic_t p;
    
    p.address = cmd;
    p.pcipos = (bus << 8) | (func << 5) | dev;
    
    ioctl(svgahelper_fd, SVGALIB_HELPER_IOCGPCIINW, &p);
    
    return p.val;
}
static int pci_read32(uha_context *c, int bus, int dev, int func, int cmd)
{
    pcic_t p;
    
    p.address = cmd;
    p.pcipos = (bus << 8) | (func << 5) | dev;
    
    ioctl(svgahelper_fd, SVGALIB_HELPER_IOCGPCIINL, &p);
    
    return p.val;
}

static void *mem_map(uha_context *c, int base, int size, int write)
{
#ifdef ARCH_ALPHA
    base += bus_base();
#endif

    return mmap(0, size, PROT_READ|(write?PROT_WRITE:0), MAP_SHARED, svgahelper_fd, base);
}

static void mem_unmap(uha_context *c, void *mem, int size)
{
    munmap(mem, size);
}

int uha_probe_svgahelper(uha_context *c)
{
    if ((svgahelper_fd = open(DEV_SVGA, O_RDWR)) < 0)
	return UHA_ERROR;
    
    close(svgahelper_fd);
    return UHA_OK;
}

int uha_init_svgahelper(uha_context *c)
{
    if ((svgahelper_fd = open(DEV_SVGA, O_RDWR)) < 0)
	return UHA_ERROR;
    uha_log("opened svgahelper\n");
    
    c->enable_io = c->disable_io = uha_dummy_ok;

    c->port_write8 = port_write8;
    c->port_write16 = port_write16;
    c->port_write32 = port_write32;
    c->port_read8 = port_read8;
    c->port_read16 = port_read16;
    c->port_read32 = port_read32;

    c->pci_read8 = pci_read8;
    c->pci_read16 = pci_read16;
    c->pci_read32 = pci_read32;

    c->mem_map = mem_map;
    c->mem_unmap = mem_unmap;
    
    return UHA_OK;
}
#endif /* CONFIG_SVGAHELPER */

--- NEW FILE: uha.h ---
/*
 * UHA header
 * Copyright (c) 2005 Alex Beregszaszi
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */

/**
 * @file uha.h
 * @brief
 *     UHA header
 * @author Alex Beregszaszi
 */

#ifndef _UHA_H
#define _UHA_H 1

#include "config.h"

#define uha_log printf // FIXME

#define UHA_ERROR	-1
#define UHA_OK		0

#define UHA_FLAG_BASIC		0x0 //< dummy/default
#define UHA_FLAG_IOPL		0x1 //< iopl() support
#define UHA_FLAG_SVGAHELPER	0x2
#define UHA_FLAG_DHAHELPER	0x4
#define UHA_FLAG_UHAHELPER	0x8

typedef struct uha_context {
    int flags;

    // for internal use
    // slot0: svgahelper
    // slot1: dhahelper
    // slot2: uhahelper
    int reserved[7];
    
    // exported funcs
    // iopl.c
    int (*enable_io)(struct uha_context *c);
    int (*disable_io)(struct uha_context *c);

    // mtrr.c    
    //< FIXME: mtrr_get ?
    int (*mtrr_set)(struct uha_context *c, int base, int size, int type);

    // ports.c
    int (*port_read8)(struct uha_context *c, int port);
    int (*port_read16)(struct uha_context *c, int port);
    int (*port_read32)(struct uha_context *c, int port);
    int (*port_write8)(struct uha_context *c, int port, int value);
    int (*port_write16)(struct uha_context *c, int port, int value);
    int (*port_write32)(struct uha_context *c, int port, int value);
    
    // pci.c
    int (*pci_read8)(struct uha_context *c, int bus, int dev, int func, int cmd);
    int (*pci_read16)(struct uha_context *c, int bus, int dev, int func, int cmd);
    int (*pci_read32)(struct uha_context *c, int bus, int dev, int func, int cmd);
    int (*pci_write8)(struct uha_context *c, int bus, int dev, int func, int cmd, int value);
    int (*pci_write16)(struct uha_context *c, int bus, int dev, int func, int cmd, int value);
    int (*pci_write32)(struct uha_context *c, int bus, int dev, int func, int cmd, int value);
    int pci_config_type;

    // mem.c
    // user->kernel, virtual->physical translations
    int (*mem_map)(struct uha_context *c, int base, int size, int write);
    int (*mem_unmap)(struct uha_context *c, void *mem, int size);
    
    // interrupt.c
    // irq disable/enable, irq install/wait/uninstall
} uha_context;

int uha_dummy_ok();
int uha_dummy_error();

int uha_init(uha_context *c);
int uha_exit(uha_context *c);

#define uha_is_io(c) (c->enable_io && c->disable_io)
#define uha_is_mtrr(c) (c->mtrr_set)
#define uha_is_port(c) (c->port_read8 && c->port_read16 && c->port_read32 && \
			c->port_write8 && c->port_write16 && c->port_write32)
#define uha_is_pci_read(c) (c->pci_config_type != -1 && c->pci_read32)
#define uha_is_pci_write(c) (c->pci_config_type != -1 && c->pci_write32)
#define uha_is_pci(c) (c->pci_config_type != -1 && c->pci_read32 && c->pci_write32)
#define uha_is_mem(c) (c->mem_map && c->mem_unmap)

#define uha_enable_io(c) c->enable_io(c)
#define uha_disable_io(c) c->disable_io(c)

#define uha_mtrr_set(c, base, size, type) c->mtrr_set(c, base, size, type)

#define uha_port_read8(c, port) c->port_read8(c, port)
#define uha_port_read16(c, port) c->port_read16(c, port)
#define uha_port_read32(c, port) c->port_read32(c, port)
#define uha_port_write8(c, port, value) c->port_write8(c, port, value)
#define uha_port_write16(c, port, value) c->port_write16(c, port, value)
#define uha_port_write32(c, port, value) c->port_write32(c, port, value)

#define uha_pci_read32(c, bus, dev, func, cmd) c->pci_read32(c, bus, dev, func, cmd)
#define uha_pci_write32(c, bus, dev, func, cmd, value) c->pci_write32(c, bus, dev, func, cmd, value)
#define uha_pci_get_vendor(c, bus, dev, func) c->pci_read32(c, bus, dev, func, 0)
#define uha_pci_config_type(c) c->pci_config_type

#define uha_mem_map(c, base, size) c->mem_map(c, base, size)
#define uha_mem_unmap(c, mem, size) c->mem_unmap(c, mem, size)

// FIXME
#define MTRR_TYPE_UNCACHABLE 1
#define MTRR_TYPE_WRCOMB 2
#define MTRR_TYPE_WRTHROUGH 3
#define MTRR_TYPE_WRPROT 4
#define MTRR_TYPE_WRBACK 5

#endif /* _UHA_H */

--- NEW FILE: uha_test.c ---
#include "uha.h"

main()
{
    uha_context *c = uha_allocate();
    
    uha_init(c);
    uha_enable_io(c);
    
    if (uha_is_pci_read(c))
    {
	int bus, card, func = 0;
	
	int ret = uha_pci_read32(c, 0, 0, 0, 0);
	int ret2 = ret|1;
	
	uha_pci_write32(c, 0, 0, 0, 0, ret2);
	int ret3 = uha_pci_read32(c, 0, 0, 0, 0);

	printf("%x %x -> %x\n", ret, ret2, ret3);

	for (bus = 0; bus < 4; bus++)
	    for (card = 0; card < 32; card++)
//		for (func = 0; func < 8; func++)
		{
		    int ret = uha_pci_read32(c, bus, card, func, 0);
		    int vendor = ret & 0xffff, device = (ret >> 16) & 0xffff;

		    if (!vendor && !device) // subfunction not present
			break;

		    if (vendor != 0xffff && device != 0xffff)
			printf("device %02x:%02x.%1x: vendor=%x device=%x\n",
			    bus, card, func, vendor, device);
		}
    }
    else
    {
	printf("No pci support present - not testing\n");
    }
    uha_exit(c);
    uha_deallocate(c);
}




More information about the uha-devel mailing list