changeset 3973:138800dfbe22

preliminary support of direct hardware access
author nick
date Fri, 04 Jan 2002 10:32:26 +0000
parents f021941d26c9
children 90e7917f945f
files libdha/AsmMacros.h libdha/Makefile libdha/README libdha/libdha.c libdha/libdha.h libdha/pci.c libdha/test.c
diffstat 7 files changed, 1907 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libdha/AsmMacros.h	Fri Jan 04 10:32:26 2002 +0000
@@ -0,0 +1,434 @@
+/* $XConsortium: AsmMacros.h /main/13 1996/10/25 11:33:12 kaleb $ */
+/*
+ * (c) Copyright 1993,1994 by David Wexelblat <dwex@xfree86.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a 
+ * copy of this software and associated documentation files (the "Software"), 
+ * to deal in the Software without restriction, including without limitation 
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, 
+ * and/or sell copies of the Software, and to permit persons to whom the 
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL 
+ * DAVID WEXELBLAT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF 
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 
+ * SOFTWARE.
+ * 
+ * Except as contained in this notice, the name of David Wexelblat shall not be
+ * used in advertising or otherwise to promote the sale, use or other dealings
+ * in this Software without prior written authorization from David Wexelblat.
+ *
+ */
+/*
+ * Copyright 1997
+ * Digital Equipment Corporation. All rights reserved.
+ * This software is furnished under license and may be used and copied only in 
+ * accordance with the following terms and conditions.  Subject to these 
+ * conditions, you may download, copy, install, use, modify and distribute 
+ * this software in source and/or binary form. No title or ownership is 
+ * transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce and retain 
+ *    this copyright notice and list of conditions as they appear in the source
+ *    file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or logo of Digital 
+ *    Equipment Corporation. Neither the "Digital Equipment Corporation" name 
+ *    nor any trademark or logo of Digital Equipment Corporation may be used 
+ *    to endorse or promote products derived from this software without the 
+ *    prior written permission of Digital Equipment Corporation.
+ *
+ * 3) This software is provided "AS-IS" and any express or implied warranties, 
+ *    including but not limited to, any implied warranties of merchantability, 
+ *    fitness for a particular purpose, or non-infringement are disclaimed. In 
+ *    no event shall DIGITAL be liable for any damages whatsoever, and in 
+ *    particular, DIGITAL shall not be liable for special, indirect, 
+ *    consequential, or incidental damages or damages for 
+ *    lost profits, loss of revenue or loss of use, whether such damages arise 
+ *    in contract, 
+ *    negligence, tort, under statute, in equity, at law or otherwise, even if 
+ *    advised of the possibility of such damage. 
+ *
+ */
+
+
+
+
+/* $XFree86: xc/programs/Xserver/hw/xfree86/SuperProbe/AsmMacros.h,v 3.13 1999/03/28 15:32:21 dawes Exp $ */
+
+#if defined(__GNUC__)
+#if defined(linux) && defined(__alpha__)
+#define inb _inb
+#define inw _inw
+#define inl _inl
+#define outb(p,v) _outb((v),(p))
+#define outw(p,v) _outw((v),(p))
+#define outl(p,v) _outl((v),(p))
+#else
+#if defined(__sparc__)
+#ifndef ASI_PL
+#define ASI_PL 0x88
+#endif
+
+static __inline__ void
+outb(port, val)
+unsigned long port;
+char val;
+{
+  __asm__ __volatile__("stba %0, [%1] %2" : : "r" (val), "r" (port), "i" (ASI_PL));
+}
+
+static __inline__ void
+outw(port, val)
+unsigned long port;
+char val;
+{
+  __asm__ __volatile__("stha %0, [%1] %2" : : "r" (val), "r" (port), "i" (ASI_PL));
+}
+
+static __inline__ void
+outl(port, val)
+unsigned long port;
+char val;
+{
+  __asm__ __volatile__("sta %0, [%1] %2" : : "r" (val), "r" (port), "i" (ASI_PL));
+}
+
+static __inline__ unsigned int
+inb(port)
+unsigned long port;
+{
+   unsigned char ret;
+   __asm__ __volatile__("lduba [%1] %2, %0" : "=r" (ret) : "r" (port), "i" (ASI_PL));
+   return ret;
+}
+
+static __inline__ unsigned int
+inw(port)
+unsigned long port;
+{
+   unsigned char ret;
+   __asm__ __volatile__("lduha [%1] %2, %0" : "=r" (ret) : "r" (port), "i" (ASI_PL));
+   return ret;
+}
+
+static __inline__ unsigned int
+inl(port)
+unsigned long port;
+{
+   unsigned char ret;
+   __asm__ __volatile__("lda [%1] %2, %0" : "=r" (ret) : "r" (port), "i" (ASI_PL));
+   return ret;
+}
+#else
+#ifdef __arm32__
+unsigned int IOPortBase;  /* Memory mapped I/O port area */
+
+static __inline__ void
+outb(port, val)
+     short port;
+     char val;
+{
+	 if ((unsigned short)port >= 0x400) return;
+
+	*(volatile unsigned char*)(((unsigned short)(port))+IOPortBase) = val;
+}
+
+static __inline__ void
+outw(port, val)
+     short port;
+     short val;
+{
+	 if ((unsigned short)port >= 0x400) return;
+
+	*(volatile unsigned short*)(((unsigned short)(port))+IOPortBase) = val;
+}
+
+static __inline__ void
+outl(port, val)
+     short port;
+     int val;
+{
+	 if ((unsigned short)port >= 0x400) return;
+
+	*(volatile unsigned long*)(((unsigned short)(port))+IOPortBase) = val;
+}
+
+static __inline__ unsigned int
+inb(port)
+     short port;
+{
+	 if ((unsigned short)port >= 0x400) return((unsigned int)-1);
+
+	return(*(volatile unsigned char*)(((unsigned short)(port))+IOPortBase));
+}
+
+static __inline__ unsigned int
+inw(port)
+     short port;
+{
+	 if ((unsigned short)port >= 0x400) return((unsigned int)-1);
+
+	return(*(volatile unsigned short*)(((unsigned short)(port))+IOPortBase));
+}
+
+static __inline__ unsigned int
+inl(port)
+     short port;
+{
+	 if ((unsigned short)port >= 0x400) return((unsigned int)-1);
+
+	return(*(volatile unsigned long*)(((unsigned short)(port))+IOPortBase));
+}
+#else /* __arm32__ */
+#if defined(Lynx) && defined(__powerpc__)
+extern unsigned char *ioBase;
+
+static volatile void
+eieio()
+{
+	__asm__ __volatile__ ("eieio");
+}
+
+static void
+outb(port, value)
+short port;
+unsigned char value;
+{
+	*(uchar *)(ioBase + port) = value; eieio();
+}
+
+static void
+outw(port, value)
+short port;
+unsigned short value;
+{
+	*(unsigned short *)(ioBase + port) = value; eieio();
+}
+
+static void
+outl(port, value)
+short port;
+unsigned long value;
+{
+	*(unsigned long *)(ioBase + port) = value; eieio();
+}
+
+static unsigned char
+inb(port)
+short port;
+{
+	unsigned char val;
+
+	val = *((unsigned char *)(ioBase + port)); eieio();
+	return(val);
+}
+
+static unsigned short
+inw(port)
+short port;
+{
+	unsigned short val;
+
+	val = *((unsigned short *)(ioBase + port)); eieio();
+	return(val);
+}
+
+static unsigned long
+inl(port)
+short port;
+{
+	unsigned long val;
+
+	val = *((unsigned long *)(ioBase + port)); eieio();
+	return(val);
+}
+
+#else
+#ifdef GCCUSESGAS
+static __inline__ void
+outb(port, val)
+short port;
+char val;
+{
+   __asm__ __volatile__("outb %0,%1" : :"a" (val), "d" (port));
+}
+
+static __inline__ void
+outw(port, val)
+short port;
+short val;
+{
+   __asm__ __volatile__("outw %0,%1" : :"a" (val), "d" (port));
+}
+
+static __inline__ void
+outl(port, val)
+short port;
+unsigned int val;
+{
+   __asm__ __volatile__("outl %0,%1" : :"a" (val), "d" (port));
+}
+
+static __inline__ unsigned int
+inb(port)
+short port;
+{
+   unsigned char ret;
+   __asm__ __volatile__("inb %1,%0" :
+       "=a" (ret) :
+       "d" (port));
+   return ret;
+}
+
+static __inline__ unsigned int
+inw(port)
+short port;
+{
+   unsigned short ret;
+   __asm__ __volatile__("inw %1,%0" :
+       "=a" (ret) :
+       "d" (port));
+   return ret;
+}
+
+static __inline__ unsigned int
+inl(port)
+short port;
+{
+   unsigned int ret;
+   __asm__ __volatile__("inl %1,%0" :
+       "=a" (ret) :
+       "d" (port));
+   return ret;
+}
+
+#else /* GCCUSESGAS */
+
+static __inline__ void
+outb(port, val)
+     short port;
+     char val;
+{
+  __asm__ __volatile__("out%B0 (%1)" : :"a" (val), "d" (port));
+}
+
+static __inline__ void
+outw(port, val)
+     short port;
+     short val;
+{
+  __asm__ __volatile__("out%W0 (%1)" : :"a" (val), "d" (port));
+}
+
+static __inline__ void
+outl(port, val)
+     short port;
+     unsigned int val;
+{
+  __asm__ __volatile__("out%L0 (%1)" : :"a" (val), "d" (port));
+}
+
+static __inline__ unsigned int
+inb(port)
+     short port;
+{
+  unsigned int ret;
+  __asm__ __volatile__("in%B0 (%1)" :
+                   "=a" (ret) :
+                   "d" (port));
+  return ret;
+}
+
+static __inline__ unsigned int
+inw(port)
+     short port;
+{
+  unsigned int ret;
+  __asm__ __volatile__("in%W0 (%1)" :
+                   "=a" (ret) :
+                   "d" (port));
+  return ret;
+}
+
+static __inline__ unsigned int
+inl(port)
+     short port;
+{
+  unsigned int ret;
+  __asm__ __volatile__("in%L0 (%1)" :
+                   "=a" (ret) :
+                   "d" (port));
+  return ret;
+}
+
+#endif /* GCCUSESGAS */
+#endif /* Lynx && __powerpc__ */
+#endif /* arm32 */
+#endif /* linux && __sparc__ */
+#endif /* linux && __alpha__ */
+
+#if defined(linux) || defined(__arm32__) || (defined(Lynx) && defined(__powerpc__))
+
+#define intr_disable()
+#define intr_enable()
+
+#else 
+
+static __inline__ void
+intr_disable()
+{
+  __asm__ __volatile__("cli");
+}
+
+static __inline__ void
+intr_enable()
+{
+  __asm__ __volatile__("sti");
+}
+
+#endif /* else !linux && !__arm32__ */
+
+#else /* __GNUC__ */
+
+#if defined(_MINIX) && defined(_ACK)
+
+/* inb, outb, inw and outw are defined in the library */
+/* ... but I've no idea if the same is true for inl & outl */
+
+u8_t inb(U16_t);
+void outb(U16_t, U8_t);
+u16_t inw(U16_t);
+void outw(U16_t, U16_t);
+u32_t inl(U16_t);
+void outl(U16_t, U32_t);
+
+#else /* not _MINIX and _ACK */
+
+# if defined(__STDC__) && (__STDC__ == 1)
+#  ifndef NCR
+#  define asm __asm
+#  endif
+# endif
+# ifdef SVR4
+#  include <sys/types.h>
+#  ifndef __USLC__
+#   define __USLC__
+#  endif
+# endif
+#ifndef SCO325
+# include <sys/inline.h>
+#else
+# include "../common/scoasm.h"
+#endif
+#define intr_disable() asm("cli")
+#define intr_enable()  asm("sti")
+
+#endif /* _MINIX and _ACK */
+#endif /* __GNUC__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libdha/Makefile	Fri Jan 04 10:32:26 2002 +0000
@@ -0,0 +1,53 @@
+# makefile
+
+include ../config.mak
+
+VERSION = 0.1
+
+SHORTNAME = libdha.so
+LIBNAME = libdha-$(VERSION).so
+
+SRCS=libdha.c pci.c
+OBJS=$(SRCS:.c=.o)
+
+CFLAGS  = $(OPTFLAGS) -fPIC -I. -I.. -Wall -W
+
+.SUFFIXES: .c .o
+
+# .PHONY: all clean
+
+.c.o:
+	$(CC) -c $(CFLAGS) -o $@ $<
+
+$(LIBNAME):     $(OBJS)
+	$(CC) -shared -o $(LIBNAME) $(OBJS)
+	ln -sf $(LIBNAME) $(SHORTNAME)
+
+all:    $(LIBNAME) $(SHORTNAME)
+
+test:
+	$(CC) test.c -o test $(SHORTNAME)
+
+clean:
+	rm -f *.o *.so *~
+
+distclean:
+	rm -f Makefile.bak *.o *.so test *~ .depend
+
+dep:    depend
+
+depend:
+	$(CC) -MM $(CFLAGS) $(SRCS) 1>.depend
+
+install:
+	cp $(LIBNAME) $(prefix)/lib/$(LIBNAME)
+	rm $(prefix)/lib/libdha.so
+	ln -sf $(LIBNAME) $(prefix)/lib/libdha.so
+	ldconfig
+
+#
+# include dependency files if they exist
+#
+ifneq ($(wildcard .depend),)
+include .depend
+endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libdha/README	Fri Jan 04 10:32:26 2002 +0000
@@ -0,0 +1,11 @@
+libdha - Library of Direct Hardware Access.
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+This library was designed for direct hardware access under different
+OS and architectures. It's not linux specific only (like harddrake
+and other).
+
+This library is based on gfxdump utility from GATOS project.
+Full list of supported OS'es see in libdha.h
+
+Note: This library requires ROOT privileges or SUID'ed executable
+file (same as XServer).
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libdha/libdha.c	Fri Jan 04 10:32:26 2002 +0000
@@ -0,0 +1,148 @@
+/*
+    libgha.c - Library for direct hardware access
+    Copyrights:
+    1996/10/27	- Robin Cutshaw (robin@xfree86.org)
+		  XFree86 3.3.3 implementation
+    1999	- Øyvind Aabling.
+    		  Modified for GATOS/win/gfxdump.
+		  
+    2002	- library implementation by Nick Kurshev
+    
+    supported O/S's:	SVR4, UnixWare, SCO, Solaris,
+			FreeBSD, NetBSD, 386BSD, BSDI BSD/386,
+			Linux, Mach/386, ISC
+			DOS (WATCOM 9.5 compiler), Win9x (with mapdev.vxd)
+    Licence: GPL
+    Original location: www.linuxvideo.org/gatos
+*/
+
+#include "libdha.h"
+#include "AsmMacros.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#ifdef _WIN32
+// MAPDEV.h - include file for VxD MAPDEV
+// Copyright (c) 1996 Vireo Software, Inc.
+
+#include <windows.h>
+
+// This is the request structure that applications use
+// to request services from the MAPDEV VxD.
+
+typedef struct _MapDevRequest
+{
+	DWORD	mdr_ServiceID;			// supplied by caller
+	LPVOID	mdr_PhysicalAddress;	// supplied by caller
+	DWORD	mdr_SizeInBytes;		// supplied by caller
+	LPVOID	mdr_LinearAddress;		// returned by VxD
+	WORD	mdr_Selector;			// returned if 16-bit caller
+	WORD	mdr_Status;				// MDR_xxxx code below
+} MAPDEVREQUEST, *PMAPDEVREQUEST;
+
+#define MDR_SERVICE_MAP		CTL_CODE(FILE_DEVICE_UNKNOWN, 1, METHOD_NEITHER, FILE_ANY_ACCESS)
+#define MDR_SERVICE_UNMAP	CTL_CODE(FILE_DEVICE_UNKNOWN, 2, METHOD_NEITHER, FILE_ANY_ACCESS)
+
+#define MDR_STATUS_SUCCESS	1
+#define MDR_STATUS_ERROR	0
+/*#include "winioctl.h"*/
+#define FILE_DEVICE_UNKNOWN             0x00000022
+#define METHOD_NEITHER                  3
+#define FILE_ANY_ACCESS                 0
+#define CTL_CODE( DeviceType, Function, Method, Access ) ( \
+    ((DeviceType)<<16) | ((Access)<<14) | ((Function)<<2) | (Method) )
+
+/* Memory Map a piece of Real Memory */
+void *map_phys_mem(unsigned base, unsigned size) {
+
+  HANDLE hDevice ;
+  PVOID inBuf[1] ;		/* buffer for struct pointer to VxD */
+  DWORD RetInfo[2] ;		/* buffer to receive data from VxD */
+  DWORD cbBytesReturned ;	/* count of bytes returned from VxD */
+  MAPDEVREQUEST req ;		/* map device request structure */
+  DWORD *pNicstar, Status, Time ; int i ; char *endptr ;
+  const PCHAR VxDName = "\\\\.\\MAPDEV.VXD" ;
+  const PCHAR VxDNameAlreadyLoaded = "\\\\.\\MAPDEV" ;
+
+  hDevice = CreateFile(VxDName, 0,0,0,
+                       CREATE_NEW, FILE_FLAG_DELETE_ON_CLOSE, 0) ;
+  if (hDevice == INVALID_HANDLE_VALUE)
+    hDevice = CreateFile(VxDNameAlreadyLoaded, 0,0,0,
+                         CREATE_NEW, FILE_FLAG_DELETE_ON_CLOSE, 0) ;
+  if (hDevice == INVALID_HANDLE_VALUE) {
+    fprintf(stderr, "Cannot open driver, error=%08lx\n", GetLastError()) ;
+    exit(1) ; }
+
+  req.mdr_ServiceID = MDR_SERVICE_MAP ;
+  req.mdr_PhysicalAddress = (PVOID)base ;
+  req.mdr_SizeInBytes = size ;
+  inBuf[0] = &req ;
+
+  if ( ! DeviceIoControl(hDevice, MDR_SERVICE_MAP, inBuf, sizeof(PVOID),
+         NULL, 0, &cbBytesReturned, NULL) ) {
+    fprintf(stderr, "Failed to map device\n") ; exit(1) ; }
+
+  return (void*)req.mdr_LinearAddress ;
+}
+
+void unmap_phys_mem(void *ptr, unsigned size) { }
+
+#else
+#include <sys/mman.h>
+
+static int mem=-1;
+void *map_phys_mem(unsigned base, unsigned size)
+{
+  void *ptr;
+  if ( (mem = open("/dev/mem",O_RDWR)) == -1) {
+    perror("libdha: open(/dev/mem) failed") ; exit(1) ;
+  }
+  ptr=mmap(0,size,PROT_READ|PROT_WRITE,MAP_SHARED,mem,base) ;
+  if ((int)ptr == -1) {
+    perror("libdha: mmap() failed") ; exit(1) ;
+  }
+  return ptr;
+}
+
+void unmap_phys_mem(void *ptr, unsigned size)
+{
+  int res=munmap(ptr,size) ;
+  if (res == -1) { perror("libdha: munmap() failed") ; exit(1) ; }
+  close(mem);
+}
+#endif
+
+unsigned char  INREG8(unsigned idx)
+{
+  return inb(idx);
+}
+
+unsigned short INREG16(unsigned idx)
+{
+  return inw(idx);
+}
+
+unsigned       INREG32(unsigned idx)
+{
+  return inl(idx);
+}
+
+void          OUTREG8(unsigned idx,unsigned char val)
+{
+  outb(idx,val);
+}
+
+void          OUTREG16(unsigned idx,unsigned short val)
+{
+  outw(idx,val);
+}
+
+void          OUTREG32(unsigned idx,unsigned val)
+{
+  outl(idx,val);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libdha/libdha.h	Fri Jan 04 10:32:26 2002 +0000
@@ -0,0 +1,57 @@
+/*
+    libgha.h - Library for direct hardware access
+    Copyrights:
+    1996/10/27	- Robin Cutshaw (robin@xfree86.org)
+		  XFree86 3.3.3 implementation
+    1999	- Øyvind Aabling.
+    		  Modified for GATOS/win/gfxdump.
+    2002	- library implementation by Nick Kurshev
+    
+    supported O/S's:	SVR4, UnixWare, SCO, Solaris,
+			FreeBSD, NetBSD, 386BSD, BSDI BSD/386,
+			Linux, Mach/386, ISC
+			DOS (WATCOM 9.5 compiler), Win9x (with mapdev.vxd)
+    Licence: GPL
+*/
+#ifndef LIBDHA_H
+#define LIBDHA_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define MAX_DEV_PER_VENDOR_CFG1 64
+#define MAX_PCI_DEVICES_PER_BUS 32
+#define MAX_PCI_DEVICES         64
+#define PCI_MULTIFUNC_DEV	0x80
+
+typedef struct pciinfo_s
+{
+  int	bus,card,func ;			/* PCI/AGP bus:card:func */
+  unsigned short vendor,device ;			/* Card vendor+device ID */
+  unsigned	base0,base1,base2,baserom ;	/* Memory and I/O base addresses */
+}pciinfo_t;
+
+			/* Fill array pci_list which must have size MAX_PCI_DEVICES
+			   and return 0 if sucessful */
+extern int  pci_scan(pciinfo_t *pci_list,unsigned *num_card);
+
+
+
+extern unsigned char  INREG8(unsigned idx);
+extern unsigned short INREG16(unsigned idx);
+extern unsigned       INREG32(unsigned idx);
+#define INREG(idx) INREG32(idx)
+extern void          OUTREG8(unsigned idx,unsigned char val);
+extern void          OUTREG16(unsigned idx,unsigned short val);
+extern void          OUTREG32(unsigned idx,unsigned val);
+#define OUTREG(idx,val) OUTREG32(idx,val)
+
+extern void *  map_phys_mem(unsigned base, unsigned size);
+extern void    unmap_phys_mem(void *ptr, unsigned size);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libdha/pci.c	Fri Jan 04 10:32:26 2002 +0000
@@ -0,0 +1,1177 @@
+/*
+   (C) 2002 - library implementation by Nick Kyrshev
+   XFree86 3.3.3 scanpci.c, modified for GATOS/win/gfxdump by Øyvind Aabling.
+ */
+ 
+#include "libdha.h"
+ 
+#include <errno.h>
+#include <string.h>
+#include "AsmMacros.h"
+#ifdef __unix__
+#include <unistd.h>
+#include <sys/mman.h>
+#elif defined ( _WIN32 )
+#include <windows.h>
+#else
+#include <dos.h>
+#endif
+ 
+#define outb	pcioutb
+#define outl	pcioutl
+#define inb	pciinb
+#define inl	pciinl
+ 
+/* $XConsortium: scanpci.c /main/25 1996/10/27 11:48:40 kaleb $ */
+/*
+ *  name:             scanpci.c
+ *
+ *  purpose:          This program will scan for and print details of
+ *                    devices on the PCI bus.
+ 
+ *  author:           Robin Cutshaw (robin@xfree86.org)
+ *
+ *  supported O/S's:  SVR4, UnixWare, SCO, Solaris,
+ *                    FreeBSD, NetBSD, 386BSD, BSDI BSD/386,
+ *                    Linux, Mach/386, ISC
+ *                    DOS (WATCOM 9.5 compiler)
+ *
+ *  compiling:        [g]cc scanpci.c -o scanpci
+ *                    for SVR4 (not Solaris), UnixWare use:
+ *                        [g]cc -DSVR4 scanpci.c -o scanpci
+ *                    for DOS, watcom 9.5:
+ *                        wcc386p -zq -omaxet -7 -4s -s -w3 -d2 name.c
+ *                        and link with PharLap or other dos extender for exe
+ *
+ */
+ 
+/* $XFree86: xc/programs/Xserver/hw/xfree86/etc/scanpci.c,v 3.34.2.17 1998/11/10 11:55:40 dawes Exp $ */
+ 
+/*
+ * Copyright 1995 by Robin Cutshaw <robin@XFree86.Org>
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the names of the above listed copyright holder(s)
+ * not be used in advertising or publicity pertaining to distribution of
+ * the software without specific, written prior permission.  The above listed
+ * copyright holder(s) make(s) no representations about the suitability of this
+ * software for any purpose.  It is provided "as is" without express or
+ * implied warranty.
+ *
+ * THE ABOVE LISTED COPYRIGHT HOLDER(S) DISCLAIM(S) ALL WARRANTIES WITH REGARD
+ * TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS, IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE
+ * LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
+ * DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+ 
+#if defined(__SVR4)
+#if !defined(SVR4)
+#define SVR4
+#endif
+#endif
+ 
+#ifdef __EMX__
+#define INCL_DOSFILEMGR
+#include <os2.h>
+#endif
+ 
+#include <stdio.h>
+#include <sys/types.h>
+#if defined(SVR4)
+#if defined(sun)
+#ifndef __EXTENSIONS__
+#define __EXTENSIONS__
+#endif
+#endif
+#include <sys/proc.h>
+#include <sys/tss.h>
+#if defined(NCR)
+#define __STDC
+#include <sys/sysi86.h>
+#undef __STDC
+#else
+#include <sys/sysi86.h>
+#endif
+#if defined(__SUNPRO_C) || defined(sun) || defined(__sun)
+#include <sys/psw.h>
+#else
+#include <sys/seg.h>
+#endif
+#include <sys/v86.h>
+#endif
+#if defined(__FreeBSD__) || defined(__386BSD__)
+#include <sys/file.h>
+#include <machine/console.h>
+#ifndef GCCUSESGAS
+#define GCCUSESGAS
+#endif
+#endif
+#if defined(__NetBSD__)
+#include <sys/param.h>
+#include <sys/file.h>
+#include <machine/sysarch.h>
+#ifndef GCCUSESGAS
+#define GCCUSESGAS
+#endif
+#endif
+#if defined(__bsdi__)
+#include <sys/file.h>
+#include <sys/ioctl.h>
+#include <i386/isa/pcconsioctl.h>
+#ifndef GCCUSESGAS
+#define GCCUSESGAS
+#endif
+#endif
+#if defined(SCO) || defined(ISC)
+#ifndef ISC
+#include <sys/console.h>
+#endif
+#include <sys/param.h>
+#include <sys/immu.h>
+#include <sys/region.h>
+#include <sys/proc.h>
+#include <sys/tss.h>
+#include <sys/sysi86.h>
+#include <sys/v86.h>
+#endif
+#if defined(Lynx_22)
+#ifndef GCCUSESGAS
+#define GCCUSESGAS
+#endif
+#endif
+ 
+ 
+#if defined(__WATCOMC__)
+ 
+#include <stdlib.h>
+static void outl(unsigned port, unsigned data);
+#pragma aux outl =  "out    dx, eax" parm [dx] [eax];
+static void outb(unsigned port, unsigned data);
+#pragma aux outb = "out    dx, al" parm [dx] [eax];
+static unsigned inl(unsigned port);
+#pragma aux inl = "in     eax, dx" parm [dx];
+static unsigned inb(unsigned port);
+#pragma aux inb = "xor    eax,eax" "in     al, dx" parm [dx];
+ 
+#else /* __WATCOMC__ */
+ 
+#if defined(__GNUC__)
+ 
+#if !defined(__alpha__) && !defined(__powerpc__)
+#if defined(GCCUSESGAS)
+#define OUTB_GCC "outb %0,%1"
+#define OUTL_GCC "outl %0,%1"
+#define INB_GCC  "inb %1,%0"
+#define INL_GCC  "inl %1,%0"
+#else
+#define OUTB_GCC "out%B0 (%1)"
+#define OUTL_GCC "out%L0 (%1)"
+#define INB_GCC "in%B0 (%1)"
+#define INL_GCC "in%L0 (%1)"
+#endif /* GCCUSESGAS */
+ 
+static void outb(unsigned short port, unsigned char val) {
+     __asm__ __volatile__(OUTB_GCC : :"a" (val), "d" (port)); }
+static void outl(unsigned short port, unsigned long val) {
+     __asm__ __volatile__(OUTL_GCC : :"a" (val), "d" (port)); }
+static unsigned char inb(unsigned short port) { unsigned char ret;
+     __asm__ __volatile__(INB_GCC : "=a" (ret) : "d" (port)); return ret; }
+static unsigned long inl(unsigned short port) { unsigned long ret;
+     __asm__ __volatile__(INL_GCC : "=a" (ret) : "d" (port)); return ret; }
+ 
+#endif /* !defined(__alpha__) && !defined(__powerpc__) */
+#else  /* __GNUC__ */
+ 
+#if defined(__STDC__) && (__STDC__ == 1)
+# if !defined(NCR)
+#  define asm __asm
+# endif
+#endif
+ 
+#if defined(__SUNPRO_C)
+/*
+ * This section is a gross hack in if you tell anyone that I wrote it,
+ * I'll deny it.  :-)
+ * The leave/ret instructions are the big hack to leave %eax alone on return.
+ */
+static unsigned char inb(int port) {
+		asm("	movl 8(%esp),%edx");
+		asm("	subl %eax,%eax");
+		asm("	inb  (%dx)");
+		asm("	leave");
+		asm("	ret");
+	}
+ 
+static unsigned short inw(int port) {
+		asm("	movl 8(%esp),%edx");
+		asm("	subl %eax,%eax");
+		asm("	inw  (%dx)");
+		asm("	leave");
+		asm("	ret");
+	}
+ 
+static unsigned long inl(int port) {
+		asm("	movl 8(%esp),%edx");
+		asm("	inl  (%dx)");
+		asm("	leave");
+		asm("	ret");
+	}
+ 
+static void outb(int port, unsigned char value) {
+		asm("	movl 8(%esp),%edx");
+		asm("	movl 12(%esp),%eax");
+		asm("	outb (%dx)");
+	}
+ 
+static void outw(int port, unsigned short value) {
+		asm("	movl 8(%esp),%edx");
+		asm("	movl 12(%esp),%eax");
+		asm("	outw (%dx)");
+	}
+ 
+static void outl(int port, unsigned long value) {
+		asm("	movl 8(%esp),%edx");
+		asm("	movl 12(%esp),%eax");
+		asm("	outl (%dx)");
+	}
+#else
+ 
+#if defined(SVR4)
+# if !defined(__USLC__)
+#  define __USLC__
+# endif
+#endif
+ 
+#ifdef __unix__
+#ifndef SCO325
+# include <sys/inline.h>
+#else
+# include "scoasm.h"
+#endif
+#endif
+ 
+#endif /* SUNPRO_C */
+ 
+#endif /* __GNUC__ */
+#endif /* __WATCOMC__ */
+ 
+#undef outb
+#undef outl
+#undef inb
+#undef inl
+ 
+#if defined(__GLIBC__) && __GLIBC__ >= 2
+#if defined(linux)
+#include <sys/perm.h>
+#endif
+#endif
+ 
+#if defined(__alpha__)
+#if defined(linux)
+#include <asm/unistd.h>
+#define BUS(tag) (((tag)>>16)&0xff)
+#define DFN(tag) (((tag)>>8)&0xff)
+static int pciconfig_read(
+          unsigned char bus,
+          unsigned char dfn,
+          unsigned char off,
+          unsigned char len,
+          void * buf)
+{
+  return syscall(__NR_pciconfig_read, bus, dfn, off, len, buf);
+}
+
+static int pciconfig_write(
+          unsigned char bus,
+          unsigned char dfn,
+          unsigned char off,
+          unsigned char len,
+          void * buf)
+{
+  return syscall(__NR_pciconfig_write, bus, dfn, off, len, buf);
+}
+#else
+Generate compiler error - scanpci unsupported on non-linux alpha platforms
+#endif /* linux */
+#endif /* __alpha__ */
+#if defined(Lynx) && defined(__powerpc__)
+/* let's mimick the Linux Alpha stuff for LynxOS so we don't have
+ * to change too much code
+ */
+#include <smem.h>
+ 
+static unsigned char *pciConfBase;
+ 
+static __inline__ unsigned long
+static swapl(unsigned long val)
+{
+	unsigned char *p = (unsigned char *)&val;
+	return ((p[3] << 24) | (p[2] << 16) | (p[1] << 8) | (p[0] << 0));
+}
+ 
+ 
+#define BUS(tag) (((tag)>>16)&0xff)
+#define DFN(tag) (((tag)>>8)&0xff)
+ 
+#define PCIBIOS_DEVICE_NOT_FOUND	0x86
+#define PCIBIOS_SUCCESSFUL		0x00
+ 
+static int pciconfig_read(
+          unsigned char bus,
+          unsigned char dev,
+          unsigned char offset,
+          int len,		/* unused, alway 4 */
+          unsigned long *val)
+{
+	unsigned long _val;
+	unsigned long *ptr;
+ 
+	dev >>= 3;
+	if (bus || dev >= 16) {
+		*val = 0xFFFFFFFF;
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	} else {
+		ptr = (unsigned long *)(pciConfBase + ((1<<dev) | offset));
+		_val = swapl(*ptr);
+	}
+	*val = _val;
+	return PCIBIOS_SUCCESSFUL;
+}
+ 
+static int pciconfig_write(
+          unsigned char bus,
+          unsigned char dev,
+          unsigned char offset,
+          int len,		/* unused, alway 4 */
+          unsigned long val)
+{
+	unsigned long _val;
+	unsigned long *ptr;
+ 
+	dev >>= 3;
+	_val = swapl(val);
+	if (bus || dev >= 16) {
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	} else {
+		ptr = (unsigned long *)(pciConfBase + ((1<<dev) | offset));
+		*ptr = _val;
+	}
+	return PCIBIOS_SUCCESSFUL;
+}
+#endif
+ 
+#if !defined(__powerpc__)
+struct pci_config_reg {
+    /* start of official PCI config space header */
+    union {
+        unsigned long device_vendor;
+	struct {
+	    unsigned short vendor;
+	    unsigned short device;
+	} dv;
+    } dv_id;
+#define _device_vendor dv_id.device_vendor
+#define _vendor dv_id.dv.vendor
+#define _device dv_id.dv.device
+    union {
+        unsigned long status_command;
+	struct {
+	    unsigned short command;
+	    unsigned short status;
+	} sc;
+    } stat_cmd;
+#define _status_command stat_cmd.status_command
+#define _command stat_cmd.sc.command
+#define _status  stat_cmd.sc.status
+    union {
+        unsigned long class_revision;
+	struct {
+	    unsigned char rev_id;
+	    unsigned char prog_if;
+	    unsigned char sub_class;
+	    unsigned char base_class;
+	} cr;
+    } class_rev;
+#define _class_revision class_rev.class_revision
+#define _rev_id     class_rev.cr.rev_id
+#define _prog_if    class_rev.cr.prog_if
+#define _sub_class  class_rev.cr.sub_class
+#define _base_class class_rev.cr.base_class
+    union {
+        unsigned long bist_header_latency_cache;
+	struct {
+	    unsigned char cache_line_size;
+	    unsigned char latency_timer;
+	    unsigned char header_type;
+	    unsigned char bist;
+	} bhlc;
+    } bhlc;
+#define _bist_header_latency_cache bhlc.bist_header_latency_cache
+#define _cache_line_size bhlc.bhlc.cache_line_size
+#define _latency_timer   bhlc.bhlc.latency_timer
+#define _header_type     bhlc.bhlc.header_type
+#define _bist            bhlc.bhlc.bist
+    union {
+	struct {
+	    unsigned long dv_base0;
+	    unsigned long dv_base1;
+	    unsigned long dv_base2;
+	    unsigned long dv_base3;
+	    unsigned long dv_base4;
+	    unsigned long dv_base5;
+	} dv;
+	struct {
+	    unsigned long bg_rsrvd[2];
+	    unsigned char primary_bus_number;
+	    unsigned char secondary_bus_number;
+	    unsigned char subordinate_bus_number;
+	    unsigned char secondary_latency_timer;
+	    unsigned char io_base;
+	    unsigned char io_limit;
+	    unsigned short secondary_status;
+	    unsigned short mem_base;
+	    unsigned short mem_limit;
+	    unsigned short prefetch_mem_base;
+	    unsigned short prefetch_mem_limit;
+	} bg;
+    } bc;
+#define	_base0				bc.dv.dv_base0
+#define	_base1				bc.dv.dv_base1
+#define	_base2				bc.dv.dv_base2
+#define	_base3				bc.dv.dv_base3
+#define	_base4				bc.dv.dv_base4
+#define	_base5				bc.dv.dv_base5
+#define	_primary_bus_number		bc.bg.primary_bus_number
+#define	_secondary_bus_number		bc.bg.secondary_bus_number
+#define	_subordinate_bus_number		bc.bg.subordinate_bus_number
+#define	_secondary_latency_timer	bc.bg.secondary_latency_timer
+#define _io_base			bc.bg.io_base
+#define _io_limit			bc.bg.io_limit
+#define _secondary_status		bc.bg.secondary_status
+#define _mem_base			bc.bg.mem_base
+#define _mem_limit			bc.bg.mem_limit
+#define _prefetch_mem_base		bc.bg.prefetch_mem_base
+#define _prefetch_mem_limit		bc.bg.prefetch_mem_limit
+    unsigned long rsvd1;
+    unsigned long rsvd2;
+    unsigned long _baserom;
+    unsigned long rsvd3;
+    unsigned long rsvd4;
+    union {
+        unsigned long max_min_ipin_iline;
+	struct {
+	    unsigned char int_line;
+	    unsigned char int_pin;
+	    unsigned char min_gnt;
+	    unsigned char max_lat;
+	} mmii;
+    } mmii;
+#define _max_min_ipin_iline mmii.max_min_ipin_iline
+#define _int_line mmii.mmii.int_line
+#define _int_pin  mmii.mmii.int_pin
+#define _min_gnt  mmii.mmii.min_gnt
+#define _max_lat  mmii.mmii.max_lat
+    /* I don't know how accurate or standard this is (DHD) */
+    union {
+	unsigned long user_config;
+	struct {
+	    unsigned char user_config_0;
+	    unsigned char user_config_1;
+	    unsigned char user_config_2;
+	    unsigned char user_config_3;
+	} uc;
+    } uc;
+#define _user_config uc.user_config
+#define _user_config_0 uc.uc.user_config_0
+#define _user_config_1 uc.uc.user_config_1
+#define _user_config_2 uc.uc.user_config_2
+#define _user_config_3 uc.uc.user_config_3
+    /* end of official PCI config space header */
+    unsigned long _pcibusidx;
+    unsigned long _pcinumbus;
+    unsigned long _pcibuses[16];
+    unsigned short _configtype;   /* config type found                   */
+    unsigned short _ioaddr;       /* config type 1 - private I/O addr    */
+    unsigned long _cardnum;       /* config type 2 - private card number */
+};
+#else
+/* ppc is big endian, swapping bytes is not quite enough
+ * to interpret the PCI config registers...
+ */
+struct pci_config_reg {
+    /* start of official PCI config space header */
+    union {
+        unsigned long device_vendor;
+	struct {
+	    unsigned short device;
+	    unsigned short vendor;
+	} dv;
+    } dv_id;
+#define _device_vendor dv_id.device_vendor
+#define _vendor dv_id.dv.vendor
+#define _device dv_id.dv.device
+    union {
+        unsigned long status_command;
+	struct {
+	    unsigned short status;
+	    unsigned short command;
+	} sc;
+    } stat_cmd;
+#define _status_command stat_cmd.status_command
+#define _command stat_cmd.sc.command
+#define _status  stat_cmd.sc.status
+    union {
+        unsigned long class_revision;
+	struct {
+	    unsigned char base_class;
+	    unsigned char sub_class;
+	    unsigned char prog_if;
+	    unsigned char rev_id;
+	} cr;
+    } class_rev;
+#define _class_revision class_rev.class_revision
+#define _rev_id     class_rev.cr.rev_id
+#define _prog_if    class_rev.cr.prog_if
+#define _sub_class  class_rev.cr.sub_class
+#define _base_class class_rev.cr.base_class
+    union {
+        unsigned long bist_header_latency_cache;
+	struct {
+	    unsigned char bist;
+	    unsigned char header_type;
+	    unsigned char latency_timer;
+	    unsigned char cache_line_size;
+	} bhlc;
+    } bhlc;
+#define _bist_header_latency_cache bhlc.bist_header_latency_cache
+#define _cache_line_size bhlc.bhlc.cache_line_size
+#define _latency_timer   bhlc.bhlc.latency_timer
+#define _header_type     bhlc.bhlc.header_type
+#define _bist            bhlc.bhlc.bist
+    union {
+	struct {
+	    unsigned long dv_base0;
+	    unsigned long dv_base1;
+	    unsigned long dv_base2;
+	    unsigned long dv_base3;
+	    unsigned long dv_base4;
+	    unsigned long dv_base5;
+	} dv;
+/* ?? */
+	struct {
+	    unsigned long bg_rsrvd[2];
+ 
+	    unsigned char secondary_latency_timer;
+	    unsigned char subordinate_bus_number;
+	    unsigned char secondary_bus_number;
+	    unsigned char primary_bus_number;
+ 
+	    unsigned short secondary_status;
+	    unsigned char io_limit;
+	    unsigned char io_base;
+ 
+	    unsigned short mem_limit;
+	    unsigned short mem_base;
+ 
+	    unsigned short prefetch_mem_limit;
+	    unsigned short prefetch_mem_base;
+	} bg;
+    } bc;
+#define	_base0				bc.dv.dv_base0
+#define	_base1				bc.dv.dv_base1
+#define	_base2				bc.dv.dv_base2
+#define	_base3				bc.dv.dv_base3
+#define	_base4				bc.dv.dv_base4
+#define	_base5				bc.dv.dv_base5
+#define	_primary_bus_number		bc.bg.primary_bus_number
+#define	_secondary_bus_number		bc.bg.secondary_bus_number
+#define	_subordinate_bus_number		bc.bg.subordinate_bus_number
+#define	_secondary_latency_timer	bc.bg.secondary_latency_timer
+#define _io_base			bc.bg.io_base
+#define _io_limit			bc.bg.io_limit
+#define _secondary_status		bc.bg.secondary_status
+#define _mem_base			bc.bg.mem_base
+#define _mem_limit			bc.bg.mem_limit
+#define _prefetch_mem_base		bc.bg.prefetch_mem_base
+#define _prefetch_mem_limit		bc.bg.prefetch_mem_limit
+    unsigned long rsvd1;
+    unsigned long rsvd2;
+    unsigned long _baserom;
+    unsigned long rsvd3;
+    unsigned long rsvd4;
+    union {
+        unsigned long max_min_ipin_iline;
+	struct {
+	    unsigned char max_lat;
+	    unsigned char min_gnt;
+	    unsigned char int_pin;
+	    unsigned char int_line;
+	} mmii;
+    } mmii;
+#define _max_min_ipin_iline mmii.max_min_ipin_iline
+#define _int_line mmii.mmii.int_line
+#define _int_pin  mmii.mmii.int_pin
+#define _min_gnt  mmii.mmii.min_gnt
+#define _max_lat  mmii.mmii.max_lat
+    /* I don't know how accurate or standard this is (DHD) */
+    union {
+	unsigned long user_config;
+	struct {
+	    unsigned char user_config_3;
+	    unsigned char user_config_2;
+	    unsigned char user_config_1;
+	    unsigned char user_config_0;
+	} uc;
+    } uc;
+#define _user_config uc.user_config
+#define _user_config_0 uc.uc.user_config_0
+#define _user_config_1 uc.uc.user_config_1
+#define _user_config_2 uc.uc.user_config_2
+#define _user_config_3 uc.uc.user_config_3
+    /* end of official PCI config space header */
+    unsigned long _pcibusidx;
+    unsigned long _pcinumbus;
+    unsigned long _pcibuses[16];
+    unsigned short _ioaddr;       /* config type 1 - private I/O addr    */
+    unsigned short _configtype;   /* config type found                   */
+    unsigned long _cardnum;       /* config type 2 - private card number */
+};
+#endif
+
+#define MAX_DEV_PER_VENDOR_CFG1 64
+#define MAX_PCI_DEVICES_PER_BUS 32
+#define MAX_PCI_DEVICES         64
+#define NF ((void (*)())NULL), { 0.0, 0, 0, NULL }
+#define PCI_MULTIFUNC_DEV	0x80
+#if defined(__alpha__) || defined(__powerpc__)
+#define PCI_ID_REG              0x00
+#define PCI_CMD_STAT_REG        0x04
+#define PCI_CLASS_REG           0x08
+#define PCI_HEADER_MISC         0x0C
+#define PCI_MAP_REG_START       0x10
+#define PCI_MAP_ROM_REG         0x30
+#define PCI_INTERRUPT_REG       0x3C
+#define PCI_REG_USERCONFIG      0x40
+#endif
+ 
+static int pcibus=-1, pcicard=-1, pcifunc=-1 ;
+/*static struct pci_device *pcidev=NULL ;*/
+ 
+#if defined(__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
+#ifdef PC98
+#define	PCI_MODE2_FORWARD_REG		0xCF9
+#else
+#define	PCI_MODE2_FORWARD_REG		0xCFA
+#endif
+ 
+static int pcicards=0 ;
+static pciinfo_t *pci_lst;
+ 
+static void identify_card(struct pci_config_reg *pcr)
+{
+ 
+  if (pcicards>=MAX_PCI_DEVICES) return ;
+ 
+  pci_lst[pcicards].bus     = pcibus ;
+  pci_lst[pcicards].card    = pcicard ;
+  pci_lst[pcicards].func    = pcifunc ;
+  pci_lst[pcicards].vendor  = pcr->_vendor ;
+  pci_lst[pcicards].device  = pcr->_device ;
+  pci_lst[pcicards].base0   = 0xFFFFFFFF ;
+  pci_lst[pcicards].base1   = 0xFFFFFFFF ;
+  pci_lst[pcicards].base2   = 0xFFFFFFFF ;
+  pci_lst[pcicards].baserom = 0x000C0000 ;
+  if (pcr->_base0) pci_lst[pcicards].base0 = pcr->_base0 &
+                     ((pcr->_base0&0x1) ? 0xFFFFFFFC : 0xFFFFFFF0) ;
+  if (pcr->_base1) pci_lst[pcicards].base1 = pcr->_base1 &
+                     ((pcr->_base1&0x1) ? 0xFFFFFFFC : 0xFFFFFFF0) ;
+  if (pcr->_base2) pci_lst[pcicards].base2 = pcr->_base2 &
+                     ((pcr->_base2&0x1) ? 0xFFFFFFFC : 0xFFFFFFF0) ;
+  if (pcr->_baserom) pci_lst[pcicards].baserom = pcr->_baserom ;
+ 
+  pcicards++;
+}
+
+static int io_fd;
+#ifdef __EMX__
+static USHORT callgate[3] = {0,0,0};
+#endif
+ 
+static void enable_os_io(void)
+{
+    io_fd = -1 ;
+#if defined(SVR4) || defined(SCO) || defined(ISC)
+#if defined(SI86IOPL)
+    sysi86(SI86IOPL, 3);
+#else
+    sysi86(SI86V86, V86SC_IOPL, PS_IOPL);
+#endif
+#endif
+#if defined(linux)
+    iopl(3);
+#endif
+#if defined(__FreeBSD__)  || defined(__386BSD__) || defined(__bsdi__)
+    if ((io_fd = open("/dev/console", O_RDWR, 0)) < 0) {
+        perror("/dev/console");
+        exit(1);
+    }
+#if defined(__FreeBSD__)  || defined(__386BSD__)
+    if (ioctl(io_fd, KDENABIO, 0) < 0) {
+        perror("ioctl(KDENABIO)");
+        exit(1);
+    }
+#endif
+#if defined(__bsdi__)
+    if (ioctl(io_fd, PCCONENABIOPL, 0) < 0) {
+        perror("ioctl(PCCONENABIOPL)");
+        exit(1);
+    }
+#endif
+#endif
+#if defined(__NetBSD__)
+#if !defined(USE_I386_IOPL)
+    if ((io_fd = open("/dev/io", O_RDWR, 0)) < 0) {
+	perror("/dev/io");
+	exit(1);
+    }
+#else
+    if (i386_iopl(1) < 0) {
+	perror("i386_iopl");
+	exit(1);
+    }
+#endif /* USE_I386_IOPL */
+#endif /* __NetBSD__ */
+#if defined(__OpenBSD__)
+    if (i386_iopl(1) < 0) {
+	perror("i386_iopl");
+	exit(1);
+    }
+#endif /* __OpenBSD__ */
+#if defined(MACH386)
+    if ((io_fd = open("/dev/iopl", O_RDWR, 0)) < 0) {
+        perror("/dev/iopl");
+        exit(1);
+    }
+#endif
+#ifdef __EMX__
+    {
+	HFILE hfd;
+	ULONG dlen,action;
+	APIRET rc;
+	static char *ioDrvPath = "/dev/fastio$";
+ 
+	if (DosOpen((PSZ)ioDrvPath, (PHFILE)&hfd, (PULONG)&action,
+	   (ULONG)0, FILE_SYSTEM, FILE_OPEN,
+	   OPEN_SHARE_DENYNONE|OPEN_FLAGS_NOINHERIT|OPEN_ACCESS_READONLY,
+	   (ULONG)0) != 0) {
+		fprintf(stderr,"Error opening fastio$ driver...\n");
+		fprintf(stderr,"Please install xf86sup.sys in config.sys!\n");
+		exit(42);
+	}
+	callgate[0] = callgate[1] = 0;
+ 
+/* Get callgate from driver for fast io to ports and other stuff */
+ 
+	rc = DosDevIOCtl(hfd, (ULONG)0x76, (ULONG)0x64,
+		NULL, 0, NULL,
+		(ULONG*)&callgate[2], sizeof(USHORT), &dlen);
+	if (rc) {
+		fprintf(stderr,"xf86-OS/2: EnableIOPorts failed, rc=%d, dlen=%d; emergency exit\n",
+			rc,dlen);
+		DosClose(hfd);
+		exit(42);
+	}
+ 
+/* Calling callgate with function 13 sets IOPL for the program */
+ 
+	asm volatile ("movl $13,%%ebx;.byte 0xff,0x1d;.long _callgate"
+			: /*no outputs */
+			: /*no inputs */
+			: "eax","ebx","ecx","edx","cc");
+ 
+        DosClose(hfd);
+   }
+#endif
+#if defined(Lynx) && defined(__powerpc__)
+    pciConfBase = (unsigned char *) smem_create("PCI-CONF",
+    	    (char *)0x80800000, 64*1024, SM_READ|SM_WRITE);
+    if (pciConfBase == (void *) -1)
+        exit(1);
+#endif
+}
+ 
+ 
+static void disable_os_io(void)
+{
+#if defined(SVR4) || defined(SCO) || defined(ISC)
+#if defined(SI86IOPL)
+    sysi86(SI86IOPL, 0);
+#else
+    sysi86(SI86V86, V86SC_IOPL, 0);
+#endif
+#endif
+#if defined(linux)
+    iopl(0);
+#endif
+#if defined(__FreeBSD__)  || defined(__386BSD__)
+    if (ioctl(io_fd, KDDISABIO, 0) < 0) {
+        perror("ioctl(KDDISABIO)");
+	close(io_fd);
+        exit(1);
+    }
+    close(io_fd);
+#endif
+#if defined(__NetBSD__)
+#if !defined(USE_I386_IOPL)
+    close(io_fd);
+#else
+    if (i386_iopl(0) < 0) {
+	perror("i386_iopl");
+	exit(1);
+    }
+#endif /* NetBSD1_1 */
+#endif /* __NetBSD__ */
+#if defined(__bsdi__)
+    if (ioctl(io_fd, PCCONDISABIOPL, 0) < 0) {
+        perror("ioctl(PCCONDISABIOPL)");
+	close(io_fd);
+        exit(1);
+    }
+    close(io_fd);
+#endif
+#if defined(MACH386)
+    close(io_fd);
+#endif
+#if defined(Lynx) && defined(__powerpc__)
+    smem_create(NULL, (char *) pciConfBase, 0, SM_DETACH);
+    smem_remove("PCI-CONF");
+    pciConfBase = NULL;
+#endif
+}
+ 
+/*main(int argc, char *argv[])*/
+int pci_scan(pciinfo_t *pci_list,unsigned *num_pci)
+{
+    unsigned long tmplong1, tmplong2, config_cmd;
+    unsigned char tmp1, tmp2;
+    unsigned int idx;
+    struct pci_config_reg pcr;
+    int do_mode1_scan = 0, do_mode2_scan = 0;
+    int func, hostbridges=0;
+    
+    pci_lst = pci_list;
+ 
+    enable_os_io();
+ 
+#if !defined(__alpha__) && !defined(__powerpc__)
+    pcr._configtype = 0;
+ 
+    outb(PCI_MODE2_ENABLE_REG, 0x00);
+    outb(PCI_MODE2_FORWARD_REG, 0x00);
+    tmp1 = inb(PCI_MODE2_ENABLE_REG);
+    tmp2 = inb(PCI_MODE2_FORWARD_REG);
+    if ((tmp1 == 0x00) && (tmp2 == 0x00)) {
+	pcr._configtype = 2;
+        /*printf("PCI says configuration type 2\n");*/
+    } else {
+        tmplong1 = inl(PCI_MODE1_ADDRESS_REG);
+        outl(PCI_MODE1_ADDRESS_REG, PCI_EN);
+        tmplong2 = inl(PCI_MODE1_ADDRESS_REG);
+        outl(PCI_MODE1_ADDRESS_REG, tmplong1);
+        if (tmplong2 == PCI_EN) {
+	    pcr._configtype = 1;
+            /*printf("PCI says configuration type 1\n");*/
+	} else {
+            /*printf("No PCI !\n");*/
+	    disable_os_io();
+	    /*exit(1);*/
+	    return ENODEV ;
+	}
+    }
+#else
+    pcr._configtype = 1;
+#endif
+ 
+    /* Try pci config 1 probe first */
+ 
+    if ((pcr._configtype == 1) || do_mode1_scan) {
+    /*printf("\nPCI probing configuration type 1\n");*/
+ 
+    pcr._ioaddr = 0xFFFF;
+ 
+    pcr._pcibuses[0] = 0;
+    pcr._pcinumbus = 1;
+    pcr._pcibusidx = 0;
+    idx = 0;
+ 
+    do {
+        /*printf("Probing for devices on PCI bus %d:\n\n", pcr._pcibusidx);*/
+ 
+        for (pcr._cardnum = 0x0; pcr._cardnum < MAX_PCI_DEVICES_PER_BUS;
+		pcr._cardnum += 0x1) {
+	  func = 0;
+	  do { /* loop over the different functions, if present */
+#if !defined(__alpha__) && !defined(__powerpc__)
+	    config_cmd = PCI_EN | (pcr._pcibuses[pcr._pcibusidx]<<16) |
+                                  (pcr._cardnum<<11) | (func<<8);
+ 
+            outl(PCI_MODE1_ADDRESS_REG, config_cmd);         /* ioreg 0 */
+            pcr._device_vendor = inl(PCI_MODE1_DATA_REG);
+#else
+	    pciconfig_read(pcr._pcibuses[pcr._pcibusidx], pcr._cardnum<<3,
+		PCI_ID_REG, 4, &pcr._device_vendor);
+#endif
+ 
+            if ((pcr._vendor == 0xFFFF) || (pcr._device == 0xFFFF))
+                break;   /* nothing there */
+ 
+	    /*printf("\npci bus 0x%x cardnum 0x%02x function 0x%04x: vendor 0x%04x device 0x%04x\n",
+	        pcr._pcibuses[pcr._pcibusidx], pcr._cardnum, func,
+		pcr._vendor, pcr._device);*/
+	    pcibus = pcr._pcibuses[pcr._pcibusidx] ;
+	    pcicard = pcr._cardnum ; pcifunc = func ;
+ 
+#if !defined(__alpha__) && !defined(__powerpc__)
+            outl(PCI_MODE1_ADDRESS_REG, config_cmd | 0x04);
+	    pcr._status_command  = inl(PCI_MODE1_DATA_REG);
+            outl(PCI_MODE1_ADDRESS_REG, config_cmd | 0x08);
+	    pcr._class_revision  = inl(PCI_MODE1_DATA_REG);
+            outl(PCI_MODE1_ADDRESS_REG, config_cmd | 0x0C);
+	    pcr._bist_header_latency_cache = inl(PCI_MODE1_DATA_REG);
+            outl(PCI_MODE1_ADDRESS_REG, config_cmd | 0x10);
+	    pcr._base0  = inl(PCI_MODE1_DATA_REG);
+            outl(PCI_MODE1_ADDRESS_REG, config_cmd | 0x14);
+	    pcr._base1  = inl(PCI_MODE1_DATA_REG);
+            outl(PCI_MODE1_ADDRESS_REG, config_cmd | 0x18);
+	    pcr._base2  = inl(PCI_MODE1_DATA_REG);
+            outl(PCI_MODE1_ADDRESS_REG, config_cmd | 0x1C);
+	    pcr._base3  = inl(PCI_MODE1_DATA_REG);
+            outl(PCI_MODE1_ADDRESS_REG, config_cmd | 0x20);
+	    pcr._base4  = inl(PCI_MODE1_DATA_REG);
+            outl(PCI_MODE1_ADDRESS_REG, config_cmd | 0x24);
+	    pcr._base5  = inl(PCI_MODE1_DATA_REG);
+            outl(PCI_MODE1_ADDRESS_REG, config_cmd | 0x30);
+	    pcr._baserom = inl(PCI_MODE1_DATA_REG);
+            outl(PCI_MODE1_ADDRESS_REG, config_cmd | 0x3C);
+	    pcr._max_min_ipin_iline = inl(PCI_MODE1_DATA_REG);
+            outl(PCI_MODE1_ADDRESS_REG, config_cmd | 0x40);
+	    pcr._user_config = inl(PCI_MODE1_DATA_REG);
+#else
+	    pciconfig_read(pcr._pcibuses[pcr._pcibusidx], pcr._cardnum<<3,
+			PCI_CMD_STAT_REG, 4, &pcr._status_command);
+	    pciconfig_read(pcr._pcibuses[pcr._pcibusidx], pcr._cardnum<<3,
+			PCI_CLASS_REG, 4, &pcr._class_revision);
+	    pciconfig_read(pcr._pcibuses[pcr._pcibusidx], pcr._cardnum<<3,
+			PCI_HEADER_MISC, 4, &pcr._bist_header_latency_cache);
+	    pciconfig_read(pcr._pcibuses[pcr._pcibusidx], pcr._cardnum<<3,
+			PCI_MAP_REG_START, 4, &pcr._base0);
+	    pciconfig_read(pcr._pcibuses[pcr._pcibusidx], pcr._cardnum<<3,
+			PCI_MAP_REG_START + 0x04, 4, &pcr._base1);
+	    pciconfig_read(pcr._pcibuses[pcr._pcibusidx], pcr._cardnum<<3,
+			PCI_MAP_REG_START + 0x08, 4, &pcr._base2);
+	    pciconfig_read(pcr._pcibuses[pcr._pcibusidx], pcr._cardnum<<3,
+			PCI_MAP_REG_START + 0x0C, 4, &pcr._base3);
+	    pciconfig_read(pcr._pcibuses[pcr._pcibusidx], pcr._cardnum<<3,
+			PCI_MAP_REG_START + 0x10, 4, &pcr._base4);
+	    pciconfig_read(pcr._pcibuses[pcr._pcibusidx], pcr._cardnum<<3,
+			PCI_MAP_REG_START + 0x14, 4, &pcr._base5);
+	    pciconfig_read(pcr._pcibuses[pcr._pcibusidx], pcr._cardnum<<3,
+			PCI_MAP_ROM_REG, 4, &pcr._baserom);
+	    pciconfig_read(pcr._pcibuses[pcr._pcibusidx], pcr._cardnum<<3,
+			PCI_INTERRUPT_REG, 4, &pcr._max_min_ipin_iline);
+	    pciconfig_read(pcr._pcibuses[pcr._pcibusidx], pcr._cardnum<<3,
+			PCI_REG_USERCONFIG, 4, &pcr._user_config);
+#endif
+ 
+            /* check for pci-pci bridges */
+#define PCI_CLASS_MASK 		0xff000000
+#define PCI_SUBCLASS_MASK 	0x00ff0000
+#define PCI_CLASS_BRIDGE 	0x06000000
+#define PCI_SUBCLASS_BRIDGE_PCI	0x00040000
+	    switch(pcr._class_revision & (PCI_CLASS_MASK|PCI_SUBCLASS_MASK)) {
+		case PCI_CLASS_BRIDGE|PCI_SUBCLASS_BRIDGE_PCI:
+		    if (pcr._secondary_bus_number > 0) {
+		        pcr._pcibuses[pcr._pcinumbus++] = pcr._secondary_bus_number;
+		    }
+			break;
+		case PCI_CLASS_BRIDGE:
+		    if ( ++hostbridges > 1) {
+			pcr._pcibuses[pcr._pcinumbus] = pcr._pcinumbus;
+			pcr._pcinumbus++;
+		    }
+			break;
+		default:
+			break;
+	    }
+	    if((func==0) && ((pcr._header_type & PCI_MULTIFUNC_DEV) == 0)) {
+	        /* not a multi function device */
+		func = 8;
+	    } else {
+	        func++;
+	    }
+ 
+	    if (idx++ >= MAX_PCI_DEVICES)
+	        continue;
+ 
+	    identify_card(&pcr);
+	  } while( func < 8 );
+        }
+    } while (++pcr._pcibusidx < pcr._pcinumbus);
+    }
+ 
+#if !defined(__alpha__) && !defined(__powerpc__)
+    /* Now try pci config 2 probe (deprecated) */
+ 
+    if ((pcr._configtype == 2) || do_mode2_scan) {
+    outb(PCI_MODE2_ENABLE_REG, 0xF1);
+    outb(PCI_MODE2_FORWARD_REG, 0x00); /* bus 0 for now */
+ 
+    /*printf("\nPCI probing configuration type 2\n");*/
+ 
+    pcr._pcibuses[0] = 0;
+    pcr._pcinumbus = 1;
+    pcr._pcibusidx = 0;
+    idx = 0;
+ 
+    do {
+        for (pcr._ioaddr = 0xC000; pcr._ioaddr < 0xD000; pcr._ioaddr += 0x0100){
+	    outb(PCI_MODE2_FORWARD_REG, pcr._pcibuses[pcr._pcibusidx]); /* bus 0 for now */
+            pcr._device_vendor = inl(pcr._ioaddr);
+	    outb(PCI_MODE2_FORWARD_REG, 0x00); /* bus 0 for now */
+ 
+            if ((pcr._vendor == 0xFFFF) || (pcr._device == 0xFFFF))
+                continue;
+            if ((pcr._vendor == 0xF0F0) || (pcr._device == 0xF0F0))
+                continue;  /* catch ASUS P55TP4XE motherboards */
+ 
+	    /*printf("\npci bus 0x%x slot at 0x%04x, vendor 0x%04x device 0x%04x\n",
+	        pcr._pcibuses[pcr._pcibusidx], pcr._ioaddr, pcr._vendor,
+                pcr._device);*/
+	    pcibus = pcr._pcibuses[pcr._pcibusidx] ;
+	    pcicard = pcr._ioaddr ; pcifunc = 0 ;
+ 
+	    outb(PCI_MODE2_FORWARD_REG, pcr._pcibuses[pcr._pcibusidx]); /* bus 0 for now */
+            pcr._status_command = inl(pcr._ioaddr + 0x04);
+            pcr._class_revision = inl(pcr._ioaddr + 0x08);
+            pcr._bist_header_latency_cache = inl(pcr._ioaddr + 0x0C);
+            pcr._base0 = inl(pcr._ioaddr + 0x10);
+            pcr._base1 = inl(pcr._ioaddr + 0x14);
+            pcr._base2 = inl(pcr._ioaddr + 0x18);
+            pcr._base3 = inl(pcr._ioaddr + 0x1C);
+            pcr._base4 = inl(pcr._ioaddr + 0x20);
+            pcr._base5 = inl(pcr._ioaddr + 0x24);
+            pcr._baserom = inl(pcr._ioaddr + 0x30);
+            pcr._max_min_ipin_iline = inl(pcr._ioaddr + 0x3C);
+            pcr._user_config = inl(pcr._ioaddr + 0x40);
+	    outb(PCI_MODE2_FORWARD_REG, 0x00); /* bus 0 for now */
+ 
+            /* check for pci-pci bridges (currently we only know Digital) */
+            if ((pcr._vendor == 0x1011) && (pcr._device == 0x0001))
+                if (pcr._secondary_bus_number > 0)
+                    pcr._pcibuses[pcr._pcinumbus++] = pcr._secondary_bus_number;
+ 
+	    if (idx++ >= MAX_PCI_DEVICES)
+	        continue;
+ 
+	    identify_card(&pcr);
+	}
+    } while (++pcr._pcibusidx < pcr._pcinumbus);
+ 
+    outb(PCI_MODE2_ENABLE_REG, 0x00);
+    }
+ 
+#endif /* __alpha__ */
+ 
+    disable_os_io();
+    *num_pci = pcicards;
+ 
+    return 0 ;
+ 
+}
+
+#if 0 
+void
+print_i128(struct pci_config_reg *pcr)
+{
+    /*
+    if (pcr->_status_command)
+        printf("  STATUS    0x%04x  COMMAND 0x%04x\n",
+            pcr->_status, pcr->_command);
+    if (pcr->_class_revision)
+        printf("  CLASS     0x%02x 0x%02x 0x%02x  REVISION 0x%02x\n",
+            pcr->_base_class, pcr->_sub_class, pcr->_prog_if, pcr->_rev_id);
+    if (pcr->_bist_header_latency_cache)
+        printf("  BIST      0x%02x  HEADER 0x%02x  LATENCY 0x%02x  CACHE 0x%02x\n",
+            pcr->_bist, pcr->_header_type, pcr->_latency_timer,
+            pcr->_cache_line_size);
+    printf("  MW0_AD    0x%08x  addr 0x%08x  %spre-fetchable\n",
+        pcr->_base0, pcr->_base0 & 0xFFC00000,
+        pcr->_base0 & 0x8 ? "" : "not-");
+    printf("  MW1_AD    0x%08x  addr 0x%08x  %spre-fetchable\n",
+        pcr->_base1, pcr->_base1 & 0xFFC00000,
+        pcr->_base1 & 0x8 ? "" : "not-");
+    printf("  XYW_AD(A) 0x%08x  addr 0x%08x\n",
+        pcr->_base2, pcr->_base2 & 0xFFC00000);
+    printf("  XYW_AD(B) 0x%08x  addr 0x%08x\n",
+        pcr->_base3, pcr->_base3 & 0xFFC00000);
+    printf("  RBASE_G   0x%08x  addr 0x%08x\n",
+        pcr->_base4, pcr->_base4 & 0xFFFF0000);
+    printf("  IO        0x%08x  addr 0x%08x\n",
+        pcr->_base5, pcr->_base5 & 0xFFFFFF00);
+    printf("  RBASE_E   0x%08x  addr 0x%08x  %sdecode-enabled\n",
+        pcr->_baserom, pcr->_baserom & 0xFFFF8000,
+        pcr->_baserom & 0x1 ? "" : "not-");
+    if (pcr->_max_min_ipin_iline)
+        printf("  MAX_LAT   0x%02x  MIN_GNT 0x%02x  INT_PIN 0x%02x  INT_LINE 0x%02x\n",
+            pcr->_max_lat, pcr->_min_gnt, pcr->_int_pin, pcr->_int_line);
+    */
+}
+ 
+void
+print_pcibridge(struct pci_config_reg *pcr)
+{
+    /*
+    if (pcr->_status_command)
+        printf("  STATUS    0x%04x  COMMAND 0x%04x\n",
+            pcr->_status, pcr->_command);
+    if (pcr->_class_revision)
+        printf("  CLASS     0x%02x 0x%02x 0x%02x  REVISION 0x%02x\n",
+            pcr->_base_class, pcr->_sub_class, pcr->_prog_if, pcr->_rev_id);
+    if (pcr->_bist_header_latency_cache)
+        printf("  BIST      0x%02x  HEADER 0x%02x  LATENCY 0x%02x  CACHE 0x%02x\n",
+            pcr->_bist, pcr->_header_type, pcr->_latency_timer,
+            pcr->_cache_line_size);
+    printf("  PRIBUS 0x%02x SECBUS 0x%02x SUBBUS 0x%02x SECLT 0x%02x\n",
+           pcr->_primary_bus_number, pcr->_secondary_bus_number,
+	   pcr->_subordinate_bus_number, pcr->_secondary_latency_timer);
+    printf("  IOBASE: 0x%02x00 IOLIM 0x%02x00 SECSTATUS 0x%04x\n",
+	pcr->_io_base, pcr->_io_limit, pcr->_secondary_status);
+    printf("  NOPREFETCH MEMBASE: 0x%08x MEMLIM 0x%08x\n",
+	pcr->_mem_base, pcr->_mem_limit);
+    printf("  PREFETCH MEMBASE: 0x%08x MEMLIM 0x%08x\n",
+	pcr->_prefetch_mem_base, pcr->_prefetch_mem_limit);
+    printf("  RBASE_E   0x%08x  addr 0x%08x  %sdecode-enabled\n",
+        pcr->_baserom, pcr->_baserom & 0xFFFF8000,
+        pcr->_baserom & 0x1 ? "" : "not-");
+    if (pcr->_max_min_ipin_iline)
+        printf("  MAX_LAT   0x%02x  MIN_GNT 0x%02x  INT_PIN 0x%02x  INT_LINE 0x%02x\n",
+            pcr->_max_lat, pcr->_min_gnt, pcr->_int_pin, pcr->_int_line);
+    */
+}
+#endif 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libdha/test.c	Fri Jan 04 10:32:26 2002 +0000
@@ -0,0 +1,27 @@
+#include "libdha.h"
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+int main( void )
+{
+  pciinfo_t lst[MAX_PCI_DEVICES];
+  unsigned i,num_pci;
+  int err;
+  err = pci_scan(lst,&num_pci);
+  if(err)
+  {
+    printf("Error occured during pci scan: %s\n",strerror(err));
+    return EXIT_FAILURE;
+  }
+  else
+  {
+    printf(" Bus:card:func vend:dev  base0   :base1   :base2   :baserom\n");
+    for(i=0;i<num_pci;i++)
+      printf("%04X:%04X:%04X %04X:%04X %08X:%08X:%08X:%08X\n"
+    	    ,lst[i].bus,lst[i].card,lst[i].func
+	    ,lst[i].vendor,lst[i].device
+	    ,lst[i].base0,lst[i].base1,lst[i].base2,lst[i].baserom);
+  }
+  return EXIT_SUCCESS;
+}