From e0fbcfe868b509f256fcdc239178d32f617bb129 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gwenol=C3=A9=20Beauchesne?= Date: Wed, 25 Aug 2004 05:45:29 +0000 Subject: VGA softbootloader for Linux, uses an x86 CPU emulator on non x86 arches. --- tools/ddcprobe/int10/AsmMacros.h | 458 ++++++++++++++++++++ tools/ddcprobe/int10/Makefile | 19 + tools/ddcprobe/int10/README | 35 ++ tools/ddcprobe/int10/emu_vm86.c | 154 +++++++ tools/ddcprobe/int10/i10_int.c | 195 +++++++++ tools/ddcprobe/int10/i10_io.c | 108 +++++ tools/ddcprobe/int10/i10_pci.c | 866 +++++++++++++++++++++++++++++++++++++ tools/ddcprobe/int10/i10_v86.c | 515 ++++++++++++++++++++++ tools/ddcprobe/int10/i10_vbios.c | 571 ++++++++++++++++++++++++ tools/ddcprobe/int10/pci.h | 127 ++++++ tools/ddcprobe/int10/v86bios.h | 215 +++++++++ tools/ddcprobe/int10/vbios.h | 4 + tools/ddcprobe/int10/vm86_struct.h | 135 ++++++ 13 files changed, 3402 insertions(+) create mode 100644 tools/ddcprobe/int10/AsmMacros.h create mode 100644 tools/ddcprobe/int10/Makefile create mode 100644 tools/ddcprobe/int10/README create mode 100644 tools/ddcprobe/int10/emu_vm86.c create mode 100644 tools/ddcprobe/int10/i10_int.c create mode 100644 tools/ddcprobe/int10/i10_io.c create mode 100644 tools/ddcprobe/int10/i10_pci.c create mode 100644 tools/ddcprobe/int10/i10_v86.c create mode 100644 tools/ddcprobe/int10/i10_vbios.c create mode 100644 tools/ddcprobe/int10/pci.h create mode 100644 tools/ddcprobe/int10/v86bios.h create mode 100644 tools/ddcprobe/int10/vbios.h create mode 100644 tools/ddcprobe/int10/vm86_struct.h (limited to 'tools/ddcprobe') diff --git a/tools/ddcprobe/int10/AsmMacros.h b/tools/ddcprobe/int10/AsmMacros.h new file mode 100644 index 000000000..68f955872 --- /dev/null +++ b/tools/ddcprobe/int10/AsmMacros.h @@ -0,0 +1,458 @@ +/* $XConsortium: AsmMacros.h /main/13 1996/10/25 11:33:12 kaleb $ */ +/* + * (c) Copyright 1993,1994 by David Wexelblat + * + * 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.14 1999/09/25 14:36:58 dawes Exp $ */ + + +#if defined(__GNUC__) + +#if defined(linux) && (defined(__alpha__) || defined(__ia64__)) + +#include + +#undef inb +#undef inw +#undef inl +#undef outb +#undef outw +#undef outl + +static __inline__ unsigned int inb(unsigned long int p) { return _inb(p); }; +static __inline__ unsigned int inw(unsigned long int p) { return _inw(p); }; +static __inline__ unsigned int inl(unsigned long int p) { return _inl(p); }; +static __inline__ void outb(unsigned long int p, unsigned char v) { _outb(v,p); }; +static __inline__ void outw(unsigned long int p, unsigned short v) { _outw(v,p); }; +static __inline__ void outl(unsigned long int p, unsigned int 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 +#if defined(__FreeBSD__) && defined(__alpha__) + +#include + +extern void outb(u_int32_t port, u_int8_t val); +extern void outw(u_int32_t port, u_int16_t val); +extern void outl(u_int32_t port, u_int32_t val); +extern u_int8_t inb(u_int32_t port); +extern u_int16_t inw(u_int32_t port); +extern u_int32_t inl(u_int32_t port); + +#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__ */ +#endif /* __FreeBSD__ && __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 +# ifndef __USLC__ +# define __USLC__ +# endif +# endif +#ifndef SCO325 +# include +#else +# include "../common/scoasm.h" +#endif +#define intr_disable() asm("cli") +#define intr_enable() asm("sti") + +#endif /* _MINIX and _ACK */ +#endif /* __GNUC__ */ diff --git a/tools/ddcprobe/int10/Makefile b/tools/ddcprobe/int10/Makefile new file mode 100644 index 000000000..b2a559140 --- /dev/null +++ b/tools/ddcprobe/int10/Makefile @@ -0,0 +1,19 @@ +CC = gcc +INCS = +CFLAGS = -O -Wall +SRCS = emu_vm86.c i10_int.c i10_io.c i10_pci.c i10_v86.c i10_vbios.c +OBJS = $(SRCS:%.c=%.o) + +TARGETLIB = ../libint10.a + +all: $(TARGETLIB) + +$(TARGETLIB): $(OBJS) + @ar rv $(TARGETLIB) $(OBJS) + +%.o: %.c + $(CC) $(CFLAGS) $(INCS) -c $< -o $@ + +clean: + @rm -f $(TARGETLIB) + @rm -f $(OBJS) validate.o diff --git a/tools/ddcprobe/int10/README b/tools/ddcprobe/int10/README new file mode 100644 index 000000000..4b7d0fa02 --- /dev/null +++ b/tools/ddcprobe/int10/README @@ -0,0 +1,35 @@ + +This is a preliminary version of a VGA softbooter for LINUX. + +It makes use of the of the vm86() call and is therefore only +usable on ix86 systems. +There are plans to port this program to use a x86 emulator +like x86emu. Also it may be ported to other operating systems. + +So far it has been tested on a small number of cards. It might +well be that it will fail on your card. + +If you need to make modifications to the programs to be able +to boot your card please let the author know. + +So far there is no command line interface. All options need +to be hardcoded. You can do this by editing debug.h. You can +turn on a bunch of debug output. Other options allow you to +boot the primary card (CONFIG_ACTIVE_DEVICE), save the bios +to a file (SAVE_BIOS), and map the original system bios +(MAP_SYS_BIOS). + +The author wants to thank + Hans Lermen (dosemu) + and + Kendall Bennett (x86emu) +for their support. + +Parts of the code - especially in v86.c and io.c - are based on code +taken from dosemu. Parts of the code in int.c are based on code taken +from x86emu + +Egbert Eich. + + + diff --git a/tools/ddcprobe/int10/emu_vm86.c b/tools/ddcprobe/int10/emu_vm86.c new file mode 100644 index 000000000..2603a5aeb --- /dev/null +++ b/tools/ddcprobe/int10/emu_vm86.c @@ -0,0 +1,154 @@ +#include +#include +#ifdef __i386__ +#include +#else +#include "vm86_struct.h" +#endif + +#define INT2PTR(a) ((a) + (unsigned char *) 0) + +#include "../x86emu/include/x86emu.h" +#include "AsmMacros.h" + +int emu_vm86_ret; + +static u8 Mem_rb(u32 addr) { + return *(u8 *)(INT2PTR(addr)); +} +static void Mem_wb(u32 addr, u8 val) { + *(u8 *)INT2PTR(addr) = val; +} +#ifdef __ia64__ + +static u16 Mem_rw(u32 addr) { + return *(u8 *)INT2PTR(addr) | *(u8 *)INT2PTR(addr + 1) << 8; +} +static u32 Mem_rl(u32 addr) { + return *(u8 *)INT2PTR(addr) | *(u8 *)INT2PTR(addr + 1) << 8 | + *(u8 *)INT2PTR(addr + 2) << 16 | *(u8 *)INT2PTR(addr + 3) << 24; +} +static void Mem_ww(u32 addr, u16 val) { + *(u8 *)INT2PTR(addr) = val; + *(u8 *)INT2PTR(addr + 1) = val >> 8; +} +static void Mem_wl(u32 addr, u32 val) { + *(u8 *)INT2PTR(addr) = val; + *(u8 *)INT2PTR(addr + 1) = val >> 8; + *(u8 *)INT2PTR(addr + 2) = val >> 16; + *(u8 *)INT2PTR(addr + 3) = val >> 24; +} + +#else + +static u16 Mem_rw(u32 addr) { + return *(u16 *)INT2PTR(addr); +} +static u32 Mem_rl(u32 addr) { + return *(u32 *)INT2PTR(addr); +} +static void Mem_ww(u32 addr, u16 val) { + *(u16 *)INT2PTR(addr) = val; +} +static void Mem_wl(u32 addr, u32 val) { + *(u32 *)INT2PTR(addr) = val; +} + +#endif + +static void do_int(int num) { + emu_vm86_ret = VM86_INTx | (num << 8); + M.x86.intr = INTR_HALTED; +} + + +int +emu_vm86(struct vm86_struct *vm) +{ + int i; + + X86EMU_memFuncs memFuncs; + X86EMU_intrFuncs intFuncs[256]; + X86EMU_pioFuncs pioFuncs; + + memFuncs.rdb = Mem_rb; + memFuncs.rdw = Mem_rw; + memFuncs.rdl = Mem_rl; + memFuncs.wrb = Mem_wb; + memFuncs.wrw = Mem_ww; + memFuncs.wrl = Mem_wl; + X86EMU_setupMemFuncs(&memFuncs); + + pioFuncs.inb = (u8(*)(u16))inb; + pioFuncs.inw = (u16(*)(u16))inw; + pioFuncs.inl = (u32(*)(u16))inl; + pioFuncs.outb = (void(*)(u16, u8))outb; + pioFuncs.outw = (void(*)(u16, u16))outw; + pioFuncs.outl = (void(*)(u16, u32))outl; + X86EMU_setupPioFuncs(&pioFuncs); + + for (i=0;i<256;i++) + intFuncs[i] = do_int; + X86EMU_setupIntrFuncs(intFuncs); + + M.mem_base = 0; + M.mem_size = 1024*1024 + 1024; + + M.x86.R_EAX = vm->regs.eax; + M.x86.R_EBX = vm->regs.ebx; + M.x86.R_ECX = vm->regs.ecx; + M.x86.R_EDX = vm->regs.edx; + + M.x86.R_ESP = vm->regs.esp; + M.x86.R_EBP = vm->regs.ebp; + M.x86.R_ESI = vm->regs.esi; + M.x86.R_EDI = vm->regs.edi; + M.x86.R_EIP = vm->regs.eip; + M.x86.R_EFLG = vm->regs.eflags; + + M.x86.R_CS = vm->regs.cs; + M.x86.R_DS = vm->regs.ds; + M.x86.R_SS = vm->regs.ss; + M.x86.R_ES = vm->regs.es; + M.x86.R_FS = vm->regs.fs; + M.x86.R_GS = vm->regs.gs; + + emu_vm86_ret = 0; + X86EMU_exec(); + + vm->regs.eax = M.x86.R_EAX; + vm->regs.ebx = M.x86.R_EBX; + vm->regs.ecx = M.x86.R_ECX; + vm->regs.edx = M.x86.R_EDX; + + vm->regs.esp = M.x86.R_ESP; + vm->regs.ebp = M.x86.R_EBP; + vm->regs.esi = M.x86.R_ESI; + vm->regs.edi = M.x86.R_EDI; + vm->regs.eip = M.x86.R_EIP; + vm->regs.eflags = M.x86.R_EFLG; + + vm->regs.cs = M.x86.R_CS; + vm->regs.ds = M.x86.R_DS; + vm->regs.ss = M.x86.R_SS; + vm->regs.es = M.x86.R_ES; + vm->regs.fs = M.x86.R_FS; + vm->regs.gs = M.x86.R_GS; + + if (emu_vm86_ret == 0 && *(unsigned char *)INT2PTR(((u32)M.x86.R_CS << 4) + (M.x86.R_IP - 1)) == 0xf4) + { + vm->regs.eip--; + return VM86_UNKNOWN; + } + return emu_vm86_ret ? emu_vm86_ret : -1; +} + +void +printk(const char *fmt, ...) +{ + va_list argptr; + va_start(argptr, fmt); + vfprintf(stderr, fmt, argptr); + va_end(argptr); +} + diff --git a/tools/ddcprobe/int10/i10_int.c b/tools/ddcprobe/int10/i10_int.c new file mode 100644 index 000000000..99a009d0a --- /dev/null +++ b/tools/ddcprobe/int10/i10_int.c @@ -0,0 +1,195 @@ +/* + * Copyright 1999 Egbert Eich + * + * 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 name of the authors not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. The authors makes no representations + * about the suitability of this software for any purpose. It is provided + * "as is" without express or implied warranty. + * + * THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE AUTHORS 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(__alpha__) || defined (__ia64__) +#include +#endif + +#include "v86bios.h" +#include "AsmMacros.h" +#include "pci.h" + +static int int1A_handler(struct regs86 *regs); +static int int42_handler(int num, struct regs86 *regs); + +int +int_handler(int num, struct regs86 *regs) +{ + switch (num) { + case 0x10: + case 0x42: + return (int42_handler(num,regs)); + case 0x1A: + return (int1A_handler(regs)); + default: + return 0; + } + return 0; +} + +static int +int42_handler(int num,struct regs86 *regs) +{ + unsigned char c; + CARD32 val; + + /* + * video bios has modified these - + * leave it to the video bios to do this + */ + + val = getIntVect(num); + if (val != 0xF000F065) + return 0; + + if ((regs->ebx & 0xff) == 0x32) { + switch (regs->eax & 0xFFFF) { + case 0x1200: + c = inb(0x3cc); + c |= 0x02; + outb(0x3c2,c); + return 1; + case 0x1201: + c = inb(0x3cc); + c &= ~0x02; + outb(0x3c2,c); + return 1; + } + } + if (num == 0x42) + return 1; + else + return 0; +} + +#define SUCCESSFUL 0x00 +#define DEVICE_NOT_FOUND 0x86 +#define BAD_REGISTER_NUMBER 0x87 + +static int +int1A_handler(struct regs86 *regs) +{ + CARD32 Slot; +// PciStructPtr pPci; + + if (! CurrentPci) return 0; /* oops */ + + switch (regs->eax & 0xFFFF) { + case 0xb101: + regs->eax &= 0xFF00; /* no config space/special cycle support */ + regs->edx = 0x20494350; /* " ICP" */ + regs->ebx = 0x0210; /* Version 2.10 */ + regs->ecx &= 0xFF00; + regs->ecx |= (pciMaxBus & 0xFF); /* Max bus number in system */ + regs->eflags &= ~((unsigned long)0x01); /* clear carry flag */ + return 1; + case 0xb102: + if (((regs->edx & 0xFFFF) == CurrentPci->VendorID) && + ((regs->ecx & 0xFFFF) == CurrentPci->DeviceID) && + (regs->esi == 0)) { + regs->eax = (regs->eax & 0x00FF) | (SUCCESSFUL << 8); + regs->eflags &= ~((unsigned long)0x01); /* clear carry flag */ + regs->ebx = pciSlotBX(CurrentPci); + } else { + regs->eax = (regs->eax & 0x00FF) | (DEVICE_NOT_FOUND << 8); + regs->eflags |= ((unsigned long)0x01); /* set carry flag */ + } + return 1; + case 0xb103: + if (((regs->ecx & 0xFF) == CurrentPci->Interface) && + (((regs->ecx & 0xFF00) >> 8) == CurrentPci->SubClass) && + (((regs->ecx & 0xFFFF0000) >> 16) == CurrentPci->BaseClass) && + ((regs->esi & 0xff) == 0)) { + regs->eax = (regs->eax & 0x00FF) | (SUCCESSFUL << 8); + regs->ebx = pciSlotBX(CurrentPci); + regs->eflags &= ~((unsigned long)0x01); /* clear carry flag */ + } else { + regs->eax = (regs->eax & 0x00FF) | (DEVICE_NOT_FOUND << 8); + regs->eflags |= ((unsigned long)0x01); /* set carry flag */ + } + return 1; + case 0xb108: + if ((Slot = findPci(regs->ebx))) { + regs->ecx &= 0xFFFFFF00; + regs->ecx |= PciRead8(regs->edi,Slot); + regs->eax = (regs->eax & 0x00FF) | (SUCCESSFUL << 8); + regs->eflags &= ~((unsigned long)0x01); /* clear carry flag */ + } else { + regs->eax = (regs->eax & 0x00FF) | (BAD_REGISTER_NUMBER << 8); + regs->eflags |= ((unsigned long)0x01); /* set carry flag */ + } + return 1; + case 0xb109: + if ((Slot = findPci(regs->ebx))) { + regs->ecx &= 0xFFFF0000; + regs->ecx |= PciRead16(regs->edi,Slot); + regs->eax = (regs->eax & 0x00FF) | (SUCCESSFUL << 8); + regs->eflags &= ~((unsigned long)0x01); /* clear carry flag */ + } else { + regs->eax = (regs->eax & 0x00FF) | (BAD_REGISTER_NUMBER << 8); + regs->eflags |= ((unsigned long)0x01); /* set carry flag */ + } + return 1; + case 0xb10a: + if ((Slot = findPci(regs->ebx))) { + regs->ecx &= 0; + regs->ecx |= PciRead32(regs->edi,Slot); + regs->eax = (regs->eax & 0x00FF) | (SUCCESSFUL << 8); + regs->eflags &= ~((unsigned long)0x01); /* clear carry flag */ + } else { + regs->eax = (regs->eax & 0x00FF) | (BAD_REGISTER_NUMBER << 8); + regs->eflags |= ((unsigned long)0x01); /* set carry flag */ + } + return 1; + case 0xb10b: + if ((Slot = findPci(regs->ebx))) { + PciWrite8(regs->edi,(CARD8)regs->ecx,Slot); + regs->eax = (regs->eax & 0x00FF) | (SUCCESSFUL << 8); + regs->eflags &= ~((unsigned long)0x01); /* clear carry flag */ + } else { + regs->eax = (regs->eax & 0x00FF) | (BAD_REGISTER_NUMBER << 8); + regs->eflags |= ((unsigned long)0x01); /* set carry flag */ + } + return 1; + case 0xb10c: + if ((Slot = findPci(regs->ebx))) { + PciWrite16(regs->edi,(CARD16)regs->ecx,Slot); + regs->eax = (regs->eax & 0x00FF) | (SUCCESSFUL << 8); + regs->eflags &= ~((unsigned long)0x01); /* clear carry flag */ + } else { + regs->eax = (regs->eax & 0x00FF) | (BAD_REGISTER_NUMBER << 8); + regs->eflags |= ((unsigned long)0x01); /* set carry flag */ + } + return 1; + case 0xb10d: + if ((Slot = findPci(regs->ebx))) { + PciWrite32(regs->edi,(CARD32)regs->ecx,Slot); + regs->eax = (regs->eax & 0x00FF) | (SUCCESSFUL << 8); + regs->eflags &= ~((unsigned long)0x01); /* clear carry flag */ + } else { + regs->eax = (regs->eax & 0x00FF) | (BAD_REGISTER_NUMBER << 8); + regs->eflags |= ((unsigned long)0x01); /* set carry flag */ + } + return 1; + default: + return 0; + } +} diff --git a/tools/ddcprobe/int10/i10_io.c b/tools/ddcprobe/int10/i10_io.c new file mode 100644 index 000000000..717356f47 --- /dev/null +++ b/tools/ddcprobe/int10/i10_io.c @@ -0,0 +1,108 @@ +/* + * Copyright 1999 Egbert Eich + * + * 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 name of the authors not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. The authors makes no representations + * about the suitability of this software for any purpose. It is provided + * "as is" without express or implied warranty. + * + * THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE AUTHORS 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. + */ + +#include +#if defined(__alpha__) || defined (__ia64__) +#include +#endif +#include "AsmMacros.h" +#include "v86bios.h" +#include "pci.h" + + +int +port_rep_inb(CARD16 port, CARD8 *base, int d_f, CARD32 count) +{ + register int inc = d_f ? -1 : 1; + CARD8 *dst = base; + + while (count--) { + *dst = inb(port); + dst += inc; + } + return (dst-base); +} + +int +port_rep_inw(CARD16 port, CARD16 *base, int d_f, CARD32 count) +{ + register int inc = d_f ? -1 : 1; + CARD16 *dst = base; + + while (count--) { + *dst = inw(port); + dst += inc; + } + return (dst-base); +} + +int +port_rep_inl(CARD16 port, CARD32 *base, int d_f, CARD32 count) +{ + register int inc = d_f ? -1 : 1; + CARD32 *dst = base; + + while (count--) { + *dst = inl(port); + dst += inc; + } + return (dst-base); +} + +int +port_rep_outb(CARD16 port, CARD8 *base, int d_f, CARD32 count) +{ + register int inc = d_f ? -1 : 1; + CARD8 *dst = base; + + while (count--) { + outb(port,*dst); + dst += inc; + } + return (dst-base); +} + +int +port_rep_outw(CARD16 port, CARD16 *base, int d_f, CARD32 count) +{ + register int inc = d_f ? -1 : 1; + CARD16 *dst = base; + + while (count--) { + outw(port,*dst); + dst += inc; + } + return (dst-base); +} + +int +port_rep_outl(CARD16 port, CARD32 *base, int d_f, CARD32 count) +{ + register int inc = d_f ? -1 : 1; + CARD32 *dst = base; + + while (count--) { + outl(port,*dst); + dst += inc; + } + return (dst-base); +} diff --git a/tools/ddcprobe/int10/i10_pci.c b/tools/ddcprobe/int10/i10_pci.c new file mode 100644 index 000000000..387cebb65 --- /dev/null +++ b/tools/ddcprobe/int10/i10_pci.c @@ -0,0 +1,866 @@ +/* + * Copyright 1999 Egbert Eich + * + * 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 name of the authors not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. The authors makes no representations + * about the suitability of this software for any purpose. It is provided + * "as is" without express or implied warranty. + * + * THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE AUTHORS 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. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#if defined (__alpha__) || defined (__ia64__) +#include +#endif +#include "AsmMacros.h" + +#include "pci.h" + +#define RESORT 1 +#define FIX_ROM 0 + +/* + * I'm rather simple mindend - therefore I do a poor man's + * pci scan without all the fancy stuff that is done in + * scanpci. However that's all we need. + */ + +PciStructPtr PciStruct = NULL; +PciBusPtr PciBuses = NULL; +PciStructPtr CurrentPci = NULL; +PciStructPtr PciList = NULL; +int pciMaxBus = 0; + +static CARD32 PciCfg1Addr; + +static void readConfigSpaceCfg1(CARD32 bus, CARD32 dev, CARD32 func, + CARD32 *reg); +static int checkSlotCfg1(CARD32 bus, CARD32 dev, CARD32 func); +static int checkSlotCfg2(CARD32 bus, int dev); +static void readConfigSpaceCfg2(CARD32 bus, int dev, CARD32 *reg); +static CARD8 interpretConfigSpace(CARD32 *reg, int busidx, + CARD8 dev, CARD8 func); +static CARD32 findBIOSMap(PciStructPtr pciP, CARD32 *biosSize); +static void restoreMem(PciStructPtr pciP); + + +#ifdef __alpha__ +#define PCI_BUS_FROM_TAG(tag) (((tag) & 0x00ff0000) >> 16) +#define PCI_DFN_FROM_TAG(tag) (((tag) & 0x0000ff00) >> 8) + +#include + +CARD32 +axpPciCfgRead(CARD32 tag) +{ + int bus, dfn; + CARD32 val = 0xffffffff; + + bus = PCI_BUS_FROM_TAG(tag); + dfn = PCI_DFN_FROM_TAG(tag); + + syscall(__NR_pciconfig_read, bus, dfn, tag & 0xff, 4, &val); + return(val); +} + +void +axpPciCfgWrite(CARD32 tag, CARD32 val) +{ + int bus, dfn; + + bus = PCI_BUS_FROM_TAG(tag); + dfn = PCI_DFN_FROM_TAG(tag); + + syscall(__NR_pciconfig_write, bus, dfn, tag & 0xff, 4, &val); +} + +static CARD32 (*readPci)(CARD32 reg) = axpPciCfgRead; +static void (*writePci)(CARD32 reg, CARD32 val) = axpPciCfgWrite; +#else +static CARD32 readPciCfg1(CARD32 reg); +static void writePciCfg1(CARD32 reg, CARD32 val); +#ifndef __ia64__ +static CARD32 readPciCfg2(CARD32 reg); +static void writePciCfg2(CARD32 reg, CARD32 val); +#endif + +static CARD32 (*readPci)(CARD32 reg) = readPciCfg1; +static void (*writePci)(CARD32 reg, CARD32 val) = writePciCfg1; +#endif + +#if defined(__alpha__) || defined(__sparc__) +#define PCI_EN 0x00000000 +#else +#define PCI_EN 0x80000000 +#endif + + +static int numbus; +static int hostbridges = 1; +static unsigned long pciMinMemReg = ~0; + + + +void +scan_pci(int pci_cfg_method) +{ + unsigned short configtype; + + CARD32 reg[64]; + int busidx; + CARD8 cardnum; + CARD8 func; + int idx; + + PciStructPtr pci1; + PciBusPtr pci_b1,pci_b2; + + if(pci_cfg_method) { + configtype = pci_cfg_method; + } + else { +#if defined(__alpha__) || defined(__powerpc__) || defined(__sparc__) || defined(__ia64__) + configtype = 1; +#else + CARD8 tmp1, tmp2; + CARD32 tmp32_1, tmp32_2; + 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)) { + configtype = 2; + readPci = readPciCfg2; + writePci = writePciCfg2; + } else { + tmp32_1 = inl(PCI_MODE1_ADDRESS_REG); + outl(PCI_MODE1_ADDRESS_REG, PCI_EN); + tmp32_2 = inl(PCI_MODE1_ADDRESS_REG); + outl(PCI_MODE1_ADDRESS_REG, tmp32_1); + if (tmp32_2 == PCI_EN) { + configtype = 1; + } else { + return; + } + } +#endif + } + + if (configtype == 1) { + busidx = 0; + numbus = 1; + idx = 0; + do { + for (cardnum = 0; cardnum < MAX_DEV_PER_VENDOR_CFG1; cardnum++) { + func = 0; + do { + /* loop over the different functions, if present */ + if (!checkSlotCfg1(busidx,cardnum,func)) { + if (!func) + break; + else { + func++; + continue; + } + } + readConfigSpaceCfg1(busidx,cardnum,func,reg); + + func = interpretConfigSpace(reg,busidx, + cardnum,func); + + if (++idx >= MAX_PCI_DEVICES) + break; + } while (func < 8); + if (idx >= MAX_PCI_DEVICES) + break; + } + if (idx >= MAX_PCI_DEVICES) + break; + } while (++busidx < PCI_MAXBUS); +#if defined(__alpha__) || defined(__powerpc__) || defined(__sparc__) || defined(__ia64__) + /* don't use outl() ;-) */ +#else + outl(PCI_MODE1_ADDRESS_REG, 0); +#endif + } else { + int slot; + + busidx = 0; + numbus = 1; + idx = 0; + do { + for (slot=0xc0; slot<0xd0; slot++) { + if (!checkSlotCfg2(busidx,slot)) + break; + readConfigSpaceCfg2(busidx,slot,reg); + + interpretConfigSpace(reg,busidx, + slot,0); + if (++idx >= MAX_PCI_DEVICES) + break; + } + if (idx >= MAX_PCI_DEVICES) + break; + } while (++busidx < PCI_MAXBUS); + } + + + pciMaxBus = numbus - 1; + + /* link buses */ + pci_b1 = PciBuses; + while (pci_b1) { + pci_b2 = PciBuses; + pci_b1->pBus = NULL; + while (pci_b2) { + if (pci_b1->primary == pci_b2->secondary) + pci_b1->pBus = pci_b2; + pci_b2 = pci_b2->next; + } + pci_b1 = pci_b1->next; + } + pci1 = PciStruct; + while (pci1) { + pci_b2 = PciBuses; + pci1->pBus = NULL; + while (pci_b2) { + if (pci1->bus == pci_b2->secondary) + pci1->pBus = pci_b2; + pci_b2 = pci_b2->next; + } + pci1 = pci1->next; + } + if (RESORT) { + PciStructPtr tmp = PciStruct, tmp1; + PciStruct = NULL; + while (tmp) { + tmp1 = tmp->next; + tmp->next = PciStruct; + PciStruct = tmp; + tmp = tmp1; + } + } + PciList = CurrentPci = PciStruct; +} + +#ifndef __alpha__ +static CARD32 +readPciCfg1(CARD32 reg) +{ + CARD32 val; + + outl(PCI_MODE1_ADDRESS_REG, reg); + val = inl(PCI_MODE1_DATA_REG); + outl(PCI_MODE1_ADDRESS_REG, 0); + return val; +} + +static void +writePciCfg1(CARD32 reg, CARD32 val) +{ + outl(PCI_MODE1_ADDRESS_REG, reg); + outl(PCI_MODE1_DATA_REG,val); + outl(PCI_MODE1_ADDRESS_REG, 0); +} + +#ifndef __ia64__ +static CARD32 +readPciCfg2(CARD32 reg) +{ + CARD32 val; + CARD8 bus = (reg >> 16) & 0xff; + CARD8 dev = (reg >> 11) & 0x1f; + CARD8 num = reg & 0xff; + + outb(PCI_MODE2_ENABLE_REG, 0xF1); + outb(PCI_MODE2_FORWARD_REG, bus); + val = inl((dev << 8) + num); + outb(PCI_MODE2_ENABLE_REG, 0x00); + return val; +} + +static void +writePciCfg2(CARD32 reg, CARD32 val) +{ + CARD8 bus = (reg >> 16) & 0xff; + CARD8 dev = (reg >> 11) & 0x1f; + CARD8 num = reg & 0xff; + + outb(PCI_MODE2_ENABLE_REG, 0xF1); + outb(PCI_MODE2_FORWARD_REG, bus); + outl((dev << 8) + num,val); + outb(PCI_MODE2_ENABLE_REG, 0x00); +} +#endif +#endif + +void +pciVideoDisable(void) +{ + /* disable VGA routing on bridges */ + PciBusPtr pbp = PciBuses; + PciStructPtr pcp = PciStruct; + + while (pbp) { + writePci(pbp->Slot.l | 0x3c, pbp->bctl & ~(CARD32)(8<<16)); + pbp = pbp->next; + } + /* disable display devices */ + while (pcp) { + writePci(pcp->Slot.l | 0x04, pcp->cmd_st & ~(CARD32)3); + writePci(pcp->Slot.l | 0x30, pcp->RomBase & ~(CARD32)1); + pcp = pcp->next; + } +} + +void +pciVideoRestore(void) +{ + /* disable VGA routing on bridges */ + PciBusPtr pbp = PciBuses; + PciStructPtr pcp = PciStruct; + + while (pbp) { + writePci(pbp->Slot.l | 0x3c, pbp->bctl); + pbp = pbp->next; + } + /* disable display devices */ + while (pcp) { + writePci(pcp->Slot.l | 0x04, pcp->cmd_st); + writePci(pcp->Slot.l | 0x30, pcp->RomBase); + pcp = pcp->next; + } +} + +void +EnableCurrent() +{ + PciBusPtr pbp; + PciStructPtr pcp = CurrentPci; + + pciVideoDisable(); + + pbp = pcp->pBus; + while (pbp) { /* enable bridges */ + writePci(pbp->Slot.l | 0x3c, pbp->bctl | (CARD32)(8<<16)); + pbp = pbp->pBus; + } + writePci(pcp->Slot.l | 0x04, pcp->cmd_st | (CARD32)3); + writePci(pcp->Slot.l | 0x30, pcp->RomBase | (CARD32)1); +} + +CARD8 +PciRead8(int offset, CARD32 Slot) +{ + int shift = offset & 0x3; + offset = offset & 0xFC; + return ((readPci(Slot | offset) >> (shift << 3)) & 0xff); +} + +CARD16 +PciRead16(int offset, CARD32 Slot) +{ + int shift = offset & 0x2; + offset = offset & 0xFC; + return ((readPci(Slot | offset) >> (shift << 3)) & 0xffff); +} + +CARD32 +PciRead32(int offset, CARD32 Slot) +{ + offset = offset & 0xFC; + return (readPci(Slot | offset)); +} + +void +PciWrite8(int offset, CARD8 byte, CARD32 Slot) +{ + CARD32 val; + int shift = offset & 0x3; + offset = offset & 0xFC; + val = readPci(Slot | offset); + val &= ~(CARD32)(0xff << (shift << 3)); + val |= byte << (shift << 3); + writePci(Slot | offset, val); +} + +void +PciWrite16(int offset, CARD16 word, CARD32 Slot) +{ + CARD32 val; + int shift = offset & 0x2; + offset = offset & 0xFC; + val = readPci(Slot | offset); + val &= ~(CARD32)(0xffff << (shift << 3)); + val |= word << (shift << 3); + writePci(Slot | offset, val); +} + +void +PciWrite32(int offset, CARD32 lg, CARD32 Slot) +{ + offset = offset & 0xFC; + writePci(Slot | offset, lg); +} + +int +mapPciRom(PciStructPtr pciP) +{ + unsigned long RomBase = 0; + int mem_fd; + unsigned char *mem, *ptr; + unsigned char *scratch = NULL; + int length = 0; + CARD32 biosSize = 0x1000000; + CARD32 enablePci = 0; /* to keep gcc happy */ + + if (!pciP) + pciP = CurrentPci; + + if (FIX_ROM) { + RomBase = findBIOSMap(pciP, &biosSize); + if (!RomBase) { + RomBase = pciP->RomBase & ~(CARD32)0xFF; + } + } else { + RomBase = pciP->RomBase & ~(CARD32)0xFF; + if (~RomBase + 1 < biosSize || !RomBase) + RomBase = findBIOSMap(pciP, &biosSize); + } + + if ((mem_fd = open(MEM_FILE,O_RDONLY))<0) { + perror("opening memory"); + restoreMem(pciP); + return (0); + } + + PciWrite32(0x30,RomBase | 1,pciP->Slot.l); + +#ifdef __alpha__ + mem = ptr = (unsigned char *)mmap(0, biosSize, PROT_READ, + MAP_SHARED, mem_fd, RomBase | _bus_base()); +#else + mem = ptr = (unsigned char *)mmap(0, biosSize, PROT_READ, + MAP_SHARED, mem_fd, RomBase); +#endif + if (pciP != CurrentPci) { + enablePci = PciRead32(0x4,pciP->Slot.l); + PciWrite32(0x4,enablePci | 0x2,pciP->Slot.l); + } + + while ( *ptr == 0x55 && *(ptr+1) == 0xAA) { + unsigned short data_off = *(ptr+0x18) | (*(ptr+0x19)<< 8); + unsigned char *data = ptr + data_off; + unsigned char type; + int i; + + if (*data!='P' || *(data+1)!='C' || *(data+2)!='I' || *(data+3)!='R') { + break; + } + type = *(data + 0x14); + + if (type != 0) { /* not PC-AT image: find next one */ + unsigned int image_length; + unsigned char indicator = *(data + 0x15); + if (indicator & 0x80) /* last image */ + break; + image_length = (*(data + 0x10) + | (*(data + 0x11) << 8)) << 9; + ptr = ptr + image_length; + continue; + } + /* OK, we have a PC Image */ + length = (*(ptr + 2) << 9); + scratch = (unsigned char *)malloc(length); + /* don't use memcpy() here: Reading from bus! */ + for (i=0;iSlot.l); + + /* unmap/close/disable PCI bios mem */ + munmap(mem, biosSize); + close(mem_fd); + /* disable and restore mapping */ + writePci(pciP->Slot.l | 0x30, pciP->RomBase & ~(CARD32)1); + + if (scratch && length) { + memcpy((unsigned char *)V_BIOS, scratch, length); + free(scratch); + } + + restoreMem(pciP); + return length; +} + +CARD32 +findPci(CARD16 slotBX) +{ + CARD32 slot = slotBX << 8; + + if (slot == (CurrentPci->Slot.l & ~PCI_EN)) + return (CurrentPci->Slot.l | PCI_EN); + else { +#if !SHOW_ALL_DEV + PciBusPtr pBus = CurrentPci->pBus; + while (pBus) { + if (slot == (pBus->Slot.l & ~PCI_EN)) + return pBus->Slot.l | PCI_EN; + pBus = pBus->next; + } +#else + PciStructPtr pPci = PciStruct; + while (pPci) { + if (slot == (pPci->Slot.l & ~PCI_EN)) + return pPci->Slot.l | PCI_EN; + pPci = pPci->next; + } +#endif + } + return 0; +} + +CARD16 +pciSlotBX(PciStructPtr pPci) +{ + return (CARD16)((pPci->Slot.l >> 8) & 0xFFFF); +} + +PciStructPtr +findPciDevice(CARD16 vendorID, CARD16 deviceID, char n) +{ + PciStructPtr pPci = CurrentPci; + n++; + + while (pPci) { + if ((pPci->VendorID == vendorID) && (pPci->DeviceID == deviceID)) { + if (!(--n)) break; + } + pPci = pPci->next; + } + return pPci; +} + +PciStructPtr +findPciClass(CARD8 intf, CARD8 subClass, CARD16 class, char n) +{ + PciStructPtr pPci = CurrentPci; + n++; + + while (pPci) { + if ((pPci->Interface == intf) && (pPci->SubClass == subClass) + && (pPci->BaseClass == class)) { + if (!(--n)) break; + } + pPci = pPci->next; + } + return pPci; +} + +static void +readConfigSpaceCfg1(CARD32 bus, CARD32 dev, CARD32 func, CARD32 *reg) +{ + CARD32 config_cmd = PCI_EN | (bus<<16) | + (dev<<11) | (func<<8); + int i; + + for (i = 0; i<64;i+=4) { +#ifdef __alpha__ + reg[i] = axpPciCfgRead(config_cmd | i); +#else + outl(PCI_MODE1_ADDRESS_REG, config_cmd | i); + reg[i] = inl(PCI_MODE1_DATA_REG); +#endif + + } +} + +static int +checkSlotCfg1(CARD32 bus, CARD32 dev, CARD32 func) +{ + CARD32 config_cmd = PCI_EN | (bus<<16) | + (dev<<11) | (func<<8); + CARD32 reg; +#ifdef __alpha__ + reg = axpPciCfgRead(config_cmd); +#else + outl(PCI_MODE1_ADDRESS_REG, config_cmd); + reg = inl(PCI_MODE1_DATA_REG); +#endif + if (reg != 0xFFFFFFFF) + return 1; + else + return 0; +} + +static int +checkSlotCfg2(CARD32 bus, int dev) +{ + CARD32 val; + + outb(PCI_MODE2_ENABLE_REG, 0xF1); + outb(PCI_MODE2_FORWARD_REG, bus); + val = inl(dev << 8); + outb(PCI_MODE2_FORWARD_REG, 0x00); + outb(PCI_MODE2_ENABLE_REG, 0x00); + if (val == 0xFFFFFFFF) + return 0; + if (val == 0xF0F0F0F0) + return 0; + return 1; +} + +static void +readConfigSpaceCfg2(CARD32 bus, int dev, CARD32 *reg) +{ + int i; + + outb(PCI_MODE2_ENABLE_REG, 0xF1); + outb(PCI_MODE2_FORWARD_REG, bus); + for (i = 0; i<64;i+=4) { + reg[i] = inl((dev << 8) + i); + } + outb(PCI_MODE2_ENABLE_REG, 0x00); +} + +static CARD8 +interpretConfigSpace(CARD32 *reg, int busidx, CARD8 dev, CARD8 func) +{ + CARD32 config_cmd; + CARD16 vendor, device; + CARD8 baseclass, subclass; + CARD8 primary, secondary; + CARD8 header, interface; + int i; + + config_cmd = PCI_EN | busidx<<16 | + (dev<<11) | (func<<8); + + for (i = 0x10; i < 0x28; i+=4) { + if (IS_MEM32(reg[i])) + if ((reg[i] & 0xFFFFFFF0) < pciMinMemReg) + pciMinMemReg = (reg[i] & 0xFFFFFFF0); +#ifdef __alpha__ + if (IS_MEM64(reg[i])) { + unsigned long addr = reg[i] | + (unsigned long)(reg[i+4]) << 32; + if ((addr & ~0xfL) < pciMinMemReg) + pciMinMemReg = (addr & ~0xfL); + i+=4; + } +#endif + } + vendor = reg[0] & 0xFFFF; + device = reg[0] >> 16; + baseclass = reg[8] >> 24; + subclass = (reg[8] >> 16) & 0xFF; + interface = (reg[8] >> 8) & 0xFF; + + header = (reg[0x0c] >> 16) & 0xff; + if (BRIDGE_CLASS(baseclass)) { + if (BRIDGE_PCI_CLASS(subclass)) { + PciBusPtr pbp = malloc(sizeof(PciBusRec)); + primary = reg[0x18] & 0xFF; + secondary = (reg[0x18] >> 8) & 0xFF; + pbp->bctl = reg[0x3c]; + pbp->primary = primary; + pbp->secondary = secondary; + pbp->Slot.l = config_cmd; + pbp->next = PciBuses; + PciBuses = pbp; + numbus++; + } else if (BRIDGE_HOST_CLASS(subclass) + && (hostbridges++ > 1)) { + numbus++; + } + } else if (VIDEO_CLASS(baseclass,subclass)) { + PciStructPtr pcp = malloc(sizeof(PciStructRec)); + pcp->RomBase = reg[0x30]; + pcp->cmd_st = reg[4]; + pcp->active = (reg[4] & 0x03) == 3 ? 1 : 0; + pcp->VendorID = vendor; + pcp->DeviceID = device; + pcp->Interface = interface; + pcp->BaseClass = baseclass; + pcp->SubClass = subclass; + pcp->Slot.l = config_cmd; + pcp->bus = busidx; + pcp->dev = dev; + pcp->func = func; + pcp->next = PciStruct; + PciStruct = pcp; + } + if ((func == 0) + && ((header & PCI_MULTIFUNC_DEV) == 0)) + func = 8; + else + func++; + return func; +} + +static CARD32 remapMEM_val; +static int remapMEM_num; + +static int /* map it on some other video device */ +remapMem(PciStructPtr pciP, int num, CARD32 size) +{ + PciStructPtr pciPtr = PciStruct; + int i; + CARD32 org; + CARD32 val; + CARD32 size_n; + + org = PciRead32(num + 0x10,pciP->Slot.l); + + while (pciPtr) { + for (i = 0; i < 20; i=i+4) { + + val = PciRead32(i + 0x10,pciPtr->Slot.l); + /* don't map it on itself */ + if ((org & 0xfffffff0) == (val & 0xfffffff0)) + continue; + if (val && !(val & 1)) + PciWrite32(i + 0x10,0xffffffff,pciPtr->Slot.l); + else + continue; + size_n = PciRead32(i + 0x10,pciPtr->Slot.l); + PciWrite32(i + 0x10,val,pciPtr->Slot.l); + size_n = ~(CARD32)(size_n & 0xfffffff0) + 1; + + if (size_n >= size) { + PciWrite32(num + 0x10,val,pciP->Slot.l); + return 1; + } + } + pciPtr = pciPtr->next; + } + /* last resort: try to go below lowest PCI mem address */ + val = ((pciMinMemReg & ~(CARD32)(size - 1)) - size); + if (val > 0x7fffffff) { + PciWrite32(num + 0x10,val, pciP->Slot.l); + return 1; + } + + return 0; +} + +static void +restoreMem(PciStructPtr pciP) +{ + if (remapMEM_val == 0) return; + PciWrite32(remapMEM_num + 0x10,remapMEM_val,pciP->Slot.l); + return; +} + +static CARD32 +findBIOSMap(PciStructPtr pciP, CARD32 *biosSize) +{ + PciStructPtr pciPtr = PciStruct; + int i; + CARD32 val; + CARD32 size = 4*1024; /* should be fixed: size seems _really_ to be undefined below */ + + PciWrite32(0x30,0xffffffff,pciP->Slot.l); + *biosSize = PciRead32(0x30,pciP->Slot.l); + PciWrite32(0x30,pciP->RomBase,pciP->Slot.l); + *biosSize = ~(*biosSize & 0xFFFFFF00) + 1; + if (*biosSize > (1024 * 1024 * 16)) { + *biosSize = 1024 * 1024 * 16; + } + while (pciPtr) { + if (pciPtr->bus != pciP->bus) { + pciPtr = pciPtr->next; + continue; + } + for (i = 0; i < 20; i=i+4) { + + val = PciRead32(i + 0x10,pciPtr->Slot.l); + if (!(val & 1)) + + PciWrite32(i + 0x10,0xffffffff,pciPtr->Slot.l); + else + continue; + size = PciRead32(i + 0x10,pciPtr->Slot.l); + PciWrite32(i + 0x10,val,pciPtr->Slot.l); + size = ~(CARD32)(size & 0xFFFFFFF0) + 1; + if (size >= *biosSize) { + if (pciP == pciPtr) { /* if same device remap ram*/ + if (!(remapMem(pciP,i,size))) + continue; + remapMEM_val = val; + remapMEM_num = i; + } else { + remapMEM_val = 0; + } + return val & 0xFFFFFF00; + } + } + pciPtr = pciPtr->next; + } + remapMEM_val = 0; + /* very last resort */ + if (pciP->bus == 0 && (pciMinMemReg > *biosSize)) + return (pciMinMemReg - size) & ~(size - 1); + + return 0; +} + +int +cfg1out(CARD16 addr, CARD32 val) +{ + if (addr == 0xCF8) { + PciCfg1Addr = val; + return 1; + } else if (addr == 0xCFC) { + writePci(PciCfg1Addr, val); + return 1; + } + return 0; +} + +int +cfg1in(CARD16 addr, CARD32 *val) +{ + if (addr == 0xCF8) { + *val = PciCfg1Addr; + return 1; + } else if (addr == 0xCFC) { + *val = readPci(PciCfg1Addr); + return 1; + } + return 0; +} + +PciStructPtr +findPciByIDs(int bus, int dev, int func) +{ + PciStructPtr pciP = PciList; + + while (pciP) { + if (pciP->bus == (unsigned) bus && pciP->dev == (unsigned) dev && pciP->func == (unsigned) func) + return pciP; + pciP = pciP->next; + } + return NULL; +} diff --git a/tools/ddcprobe/int10/i10_v86.c b/tools/ddcprobe/int10/i10_v86.c new file mode 100644 index 000000000..0e50b1576 --- /dev/null +++ b/tools/ddcprobe/int10/i10_v86.c @@ -0,0 +1,515 @@ +/* + * Copyright 1999 Egbert Eich + * + * 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 name of the authors not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. The authors makes no representations + * about the suitability of this software for any purpose. It is provided + * "as is" without express or implied warranty. + * + * THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE AUTHORS 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. + */ + +#include +#include +#include +#include +#include +#ifdef __i386__ +#include +#else +#include "vm86_struct.h" +#endif +#include +#include "v86bios.h" +#include "AsmMacros.h" + +extern int emu_vm86(struct vm86_struct *vm); + +#define INT2PTR(a) ((a) + (unsigned char *) 0) + +void log_err(char *format, ...) __attribute__ ((format (printf, 1, 2))); + +struct vm86_struct vm86s; + +static int vm86_GP_fault(void); +static int vm86_do_int(int num); +#ifdef __i386__ +static int vm86_rep(struct vm86_struct *ptr); +#endif +void log_registers(void); + +#define CPU_REG(x) (vm86s.regs.x) +#define CPU_REG_LW(reg) (*((CARD16 *)&CPU_REG(reg))) +#define CPU_REG_HW(reg) (*((CARD16 *)&CPU_REG(reg) + 1)) +#define CPU_REG_LB(reg) (*(CARD8 *)&CPU_REG(e##reg)) +#define SEG_ADR(type, seg, reg) type((CPU_REG_LW(seg) << 4) + CPU_REG_LW(e##reg) + (unsigned char *) 0) +#define DF (1 << 10) + +struct pio P; + +void +setup_io(void) +{ + P.inb = (CARD8(*)(CARD16))inb; + P.inw = (CARD16(*)(CARD16))inw; + P.inl = (CARD32(*)(CARD16))inl; + P.outb = (void(*)(CARD16,CARD8))outb; + P.outw = (void(*)(CARD16,CARD16))outw; + P.outl = (void(*)(CARD16,CARD32))outl; +} + + +static void +setup_vm86(unsigned long bios_start, i86biosRegsPtr regs) +{ + CARD32 eip; + CARD16 cs; + + vm86s.flags = VM86_SCREEN_BITMAP; + vm86s.flags = 0; + vm86s.screen_bitmap = 0; + vm86s.cpu_type = CPU_586; + memset(&vm86s.int_revectored, 0xff,sizeof(vm86s.int_revectored)) ; + memset(&vm86s.int21_revectored, 0xff,sizeof(vm86s.int21_revectored)) ; + + eip = bios_start & 0xFFFF; + cs = (bios_start & 0xFF0000) >> 4; + + CPU_REG(eax) = regs->ax; + CPU_REG(ebx) = regs->bx; + CPU_REG(ecx) = regs->cx; + CPU_REG(edx) = regs->dx; + CPU_REG(esi) = 0; + CPU_REG(edi) = regs->di; + CPU_REG(ebp) = 0; + CPU_REG(eip) = eip; + CPU_REG(cs) = cs; + CPU_REG(esp) = 0x100; + CPU_REG(ss) = 0x30; /* This is the standard pc bios stack */ + CPU_REG(es) = regs->es; + CPU_REG(ds) = 0x40; /* standard pc ds */ + CPU_REG(fs) = 0; + CPU_REG(gs) = 0; + CPU_REG(eflags) |= (VIF_MASK | VIP_MASK); +} + +void +collect_bios_regs(i86biosRegsPtr regs) +{ + regs->ax = CPU_REG(eax); + regs->bx = CPU_REG(ebx); + regs->cx = CPU_REG(ecx); + regs->dx = CPU_REG(edx); + regs->es = CPU_REG(es); + regs->ds = CPU_REG(ds); + regs->di = CPU_REG(edi); + regs->si = CPU_REG(esi); +} + +static int do_vm86(int cpuemu) +{ + int retval; + +#ifdef V86BIOS_DEBUG + dump_registers(); +#endif + +#ifdef __i386__ + if(cpuemu) { + retval = emu_vm86(&vm86s); + } + else { + retval = vm86_rep(&vm86s); + } +#else + retval = emu_vm86(&vm86s); +#endif + + switch (VM86_TYPE(retval)) { + case VM86_UNKNOWN: + if (!vm86_GP_fault()) + return 0; + break; + case VM86_STI: + log_err("vm86_sti :-((\n"); + log_registers(); + return 0; + case VM86_INTx: + if (!vm86_do_int(VM86_ARG(retval))) { + log_err("Unknown vm86_int: %X\n",VM86_ARG(retval)); + log_registers(); + return 0; + } + /* I'm not sure yet what to do if we can handle ints */ + break; + case VM86_SIGNAL: + log_err("VBE: received a signal!\n"); + log_registers(); + return 0; + default: + log_err("unknown type(0x%x)=0x%x\n", + VM86_ARG(retval),VM86_TYPE(retval)); + log_registers(); + return 0; + } + + return 1; +} + +void +do_x86(unsigned long bios_start, i86biosRegsPtr regs, int cpuemu) +{ + setup_vm86(bios_start, regs); + while(do_vm86(cpuemu)) {}; + collect_bios_regs(regs); +} + +/* get the linear address */ +#define LIN_PREF_SI ((pref_seg << 4) + CPU_REG_LW(esi)) + +#define LWECX (prefix66 ^ prefix67 ? CPU_REG(ecx) : CPU_REG_LW(ecx)) + +static int +vm86_GP_fault(void) +{ + unsigned char *csp, *lina; + CARD32 org_eip; + int pref_seg; + int done,is_rep,prefix66,prefix67; + + + csp = lina = SEG_ADR((unsigned char *), cs, ip); +#ifdef V86BIOS_DEBUG + printf("exception: \n"); + dump_code(); +#endif + + is_rep = 0; + prefix66 = prefix67 = 0; + pref_seg = -1; + + /* eat up prefixes */ + done = 0; + do { + switch (*(csp++)) { + case 0x66: /* operand prefix */ prefix66=1; break; + case 0x67: /* address prefix */ prefix67=1; break; + case 0x2e: /* CS */ pref_seg=CPU_REG(cs); break; + case 0x3e: /* DS */ pref_seg=CPU_REG(ds); break; + case 0x26: /* ES */ pref_seg=CPU_REG(es); break; + case 0x36: /* SS */ pref_seg=CPU_REG(ss); break; + case 0x65: /* GS */ pref_seg=CPU_REG(gs); break; + case 0x64: /* FS */ pref_seg=CPU_REG(fs); break; + case 0xf2: /* repnz */ + case 0xf3: /* rep */ is_rep=1; break; + default: done=1; + } + } while (!done); + csp--; /* oops one too many */ + org_eip = CPU_REG(eip); + CPU_REG_LW(eip) += (csp - lina); + + switch (*csp) { + + case 0x6c: /* insb */ + /* NOTE: ES can't be overwritten; prefixes 66,67 should use esi,edi,ecx + * but is anyone using extended regs in real mode? */ + /* WARNING: no test for DI wrapping! */ + CPU_REG_LW(edi) += port_rep_inb(CPU_REG_LW(edx), + SEG_ADR((CARD8 *),es,di), + CPU_REG_LW(eflags)&DF, + (is_rep? LWECX:1)); + if (is_rep) LWECX = 0; + CPU_REG_LW(eip)++; + break; + + case 0x6d: /* (rep) insw / insd */ + /* NOTE: ES can't be overwritten */ + /* WARNING: no test for _DI wrapping! */ + if (prefix66) { + CPU_REG_LW(edi) += port_rep_inl(CPU_REG_LW(edx), + SEG_ADR((CARD32 *),es,di), + CPU_REG_LW(eflags)&DF, + (is_rep? LWECX:1)); + } + else { + CPU_REG_LW(edi) += port_rep_inw(CPU_REG_LW(edx), + SEG_ADR((CARD16 *),es,di), + CPU_REG_LW(eflags)&DF, + (is_rep? LWECX:1)); + } + if (is_rep) LWECX = 0; + CPU_REG_LW(eip)++; + break; + + case 0x6e: /* (rep) outsb */ + if (pref_seg < 0) pref_seg = CPU_REG_LW(ds); + /* WARNING: no test for _SI wrapping! */ + CPU_REG_LW(esi) += port_rep_outb(CPU_REG_LW(edx),(CARD8*)INT2PTR(LIN_PREF_SI), + CPU_REG_LW(eflags)&DF, + (is_rep? LWECX:1)); + if (is_rep) LWECX = 0; + CPU_REG_LW(eip)++; + break; + + case 0x6f: /* (rep) outsw / outsd */ + if (pref_seg < 0) pref_seg = CPU_REG_LW(ds); + /* WARNING: no test for _SI wrapping! */ + if (prefix66) { + CPU_REG_LW(esi) += port_rep_outl(CPU_REG_LW(edx), + (CARD32 *)INT2PTR(LIN_PREF_SI), + CPU_REG_LW(eflags)&DF, + (is_rep? LWECX:1)); + } + else { + CPU_REG_LW(esi) += port_rep_outw(CPU_REG_LW(edx), + (CARD16 *)INT2PTR(LIN_PREF_SI), + CPU_REG_LW(eflags)&DF, + (is_rep? LWECX:1)); + } + if (is_rep) LWECX = 0; + CPU_REG_LW(eip)++; + break; + + case 0xe5: /* inw xx, inl xx */ + if (prefix66) CPU_REG(eax) = P.inl((int) csp[1]); + else CPU_REG_LW(eax) = P.inw((int) csp[1]); + CPU_REG_LW(eip) += 2; + break; + case 0xe4: /* inb xx */ + CPU_REG_LW(eax) &= ~(CARD32)0xff; + CPU_REG_LB(ax) |= P.inb((int) csp[1]); + CPU_REG_LW(eip) += 2; + break; + case 0xed: /* inw dx, inl dx */ + if (prefix66) CPU_REG(eax) = P.inl(CPU_REG_LW(edx)); + else CPU_REG_LW(eax) = P.inw(CPU_REG_LW(edx)); + CPU_REG_LW(eip) += 1; + break; + case 0xec: /* inb dx */ + CPU_REG_LW(eax) &= ~(CARD32)0xff; + CPU_REG_LB(ax) |= P.inb(CPU_REG_LW(edx)); + CPU_REG_LW(eip) += 1; + break; + + case 0xe7: /* outw xx */ + if (prefix66) P.outl((int)csp[1], CPU_REG(eax)); + else P.outw((int)csp[1], CPU_REG_LW(eax)); + CPU_REG_LW(eip) += 2; + break; + case 0xe6: /* outb xx */ + P.outb((int) csp[1], CPU_REG_LB(ax)); + CPU_REG_LW(eip) += 2; + break; + case 0xef: /* outw dx */ + if (prefix66) P.outl(CPU_REG_LW(edx), CPU_REG(eax)); + else P.outw(CPU_REG_LW(edx), CPU_REG_LW(eax)); + CPU_REG_LW(eip) += 1; + break; + case 0xee: /* outb dx */ + P.outb(CPU_REG_LW(edx), CPU_REG_LB(ax)); + CPU_REG_LW(eip) += 1; + break; + + case 0xf4: +#ifdef V86BIOS_DEBUG + printf("hlt at %p\n", lina); +#endif + return 0; + + case 0x0f: + log_err("CPU 0x0f Trap at eip=0x%lx\n",CPU_REG(eip)); + goto op0ferr; + break; + + case 0xf0: /* lock */ + default: + log_err("unknown reason for exception\n"); + log_registers(); + op0ferr: + log_err("cannot continue\n"); + return 0; + } /* end of switch() */ + return 1; +} + +static int +vm86_do_int(int num) +{ + int val; + struct regs86 regs; + + /* try to run bios interrupt */ + + /* if not installed fall back */ +#define COPY(x) regs.x = CPU_REG(x) +#define COPY_R(x) CPU_REG(x) = regs.x + + COPY(eax); + COPY(ebx); + COPY(ecx); + COPY(edx); + COPY(esi); + COPY(edi); + COPY(ebp); + COPY(eip); + COPY(esp); + COPY(cs); + COPY(ss); + COPY(ds); + COPY(es); + COPY(fs); + COPY(gs); + COPY(eflags); + + if (!(val = int_handler(num,®s))) + if (!(val = run_bios_int(num,®s))) + return val; + + COPY_R(eax); + COPY_R(ebx); + COPY_R(ecx); + COPY_R(edx); + COPY_R(esi); + COPY_R(edi); + COPY_R(ebp); + COPY_R(eip); + COPY_R(esp); + COPY_R(cs); + COPY_R(ss); + COPY_R(ds); + COPY_R(es); + COPY_R(fs); + COPY_R(gs); + COPY_R(eflags); + + return val; +#undef COPY +#undef COPY_R +} + +#ifdef __i386__ + +static int +vm86_rep(struct vm86_struct *ptr) +{ + + int __res; + + /* stay away from %ebx */ + __asm__ __volatile__("push %%ebx\n\tmov %%ecx,%%ebx\n\tpush %%gs\n\tint $0x80\n\tpop %%gs\n\tpop %%ebx\n" + :"=a" (__res):"a" ((int)113), + "c" ((struct vm86_struct *)ptr)); + + if ((__res) < 0) { + errno = -__res; + __res=-1; + } + else errno = 0; + return __res; +} + +#endif + +#ifdef __i386__ + +#define pushw(base, ptr, val) \ +__asm__ __volatile__( \ + "decw %w0\n\t" \ + "movb %h2,(%1,%0)\n\t" \ + "decw %w0\n\t" \ + "movb %b2,(%1,%0)" \ + : "=r" (ptr) \ + : "r" (base), "q" (val), "0" (ptr)) + +#else + +#define pushw(base, ptr, val) { \ + ptr = ((ptr) - 1) & 0xffff; \ + *((unsigned char *)(base) + (ptr)) = (val) >> 8; \ + ptr = ((ptr) - 1) & 0xffff; \ + *((unsigned char *)(base) + (ptr)) = (val); \ + } + +#endif + +int +run_bios_int(int num, struct regs86 *regs) +{ + CARD16 *ssp; + CARD32 sp; + CARD32 eflags; + +#ifdef V86BIOS_DEBUG + static int firsttime = 1; +#endif + /* check if bios vector is initialized */ + if (((CARD16*)0)[(num<<1)+1] == 0x0000) { /* SYS_BIOS_SEG ?*/ + return 0; + } + +#ifdef V86BIOS_DEBUG + if (firsttime) { + dprint(0,0x3D0); + firsttime = 0; + } +#endif + + ssp = (CARD16*)INT2PTR(CPU_REG(ss)<<4); + sp = (CARD32) CPU_REG_LW(esp); + + eflags = regs->eflags; + eflags = ((eflags & VIF_MASK) != 0) + ? (eflags | IF_MASK) : (eflags & ~(CARD32) IF_MASK); + pushw(ssp, sp, eflags); + pushw(ssp, sp, regs->cs); + pushw(ssp, sp, (CARD16)regs->eip); + regs->esp -= 6; + regs->cs = ((CARD16 *) 0)[(num << 1) + 1]; + regs->eip = (regs->eip & 0xFFFF0000) | ((CARD16 *) 0)[num << 1]; +#ifdef V86BIOS_DEBUG + dump_code(); +#endif + regs->eflags = regs->eflags + & ~(VIF_MASK | TF_MASK | IF_MASK | NT_MASK); + return 1; +} + +CARD32 +getIntVect(int num) +{ + return ((CARD32*)0)[num]; +} + +CARD32 +getIP(void) +{ + return (CPU_REG(cs) << 4) + CPU_REG(eip); +} + +void log_registers() +{ + log_err( + " eax %08x, ebx %08x, ecx %08x, edx %08x\n" + " esi %08x, edi %08x, ebp %08x, esp %08x\n" + " ds %04x, es %04x, fs %04x, gs %04x, ss %04x\n" + " cs:eip %04x:%08x\n", + (unsigned) CPU_REG(eax), (unsigned) CPU_REG(ebx), (unsigned) CPU_REG(ecx), (unsigned) CPU_REG(edx), + (unsigned) CPU_REG(esi), (unsigned) CPU_REG(edi), (unsigned) CPU_REG(ebp), (unsigned) CPU_REG(esp), + (unsigned) CPU_REG(ds), (unsigned) CPU_REG(es), + (unsigned) CPU_REG(fs), (unsigned) CPU_REG(gs), (unsigned) CPU_REG(ss), + (unsigned) CPU_REG(cs), (unsigned) CPU_REG(eip) + ); +} + diff --git a/tools/ddcprobe/int10/i10_vbios.c b/tools/ddcprobe/int10/i10_vbios.c new file mode 100644 index 000000000..89c6b7c5a --- /dev/null +++ b/tools/ddcprobe/int10/i10_vbios.c @@ -0,0 +1,571 @@ +/* + * Copyright 1999 Egbert Eich + * + * 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 name of the authors not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. The authors makes no representations + * about the suitability of this software for any purpose. It is provided + * "as is" without express or implied warranty. + * + * THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE AUTHORS 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. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if defined(__alpha__) || defined (__ia64__) +#include +//#elif defined(HAVE_SYS_PERM) +#else +#include +#endif +#include "v86bios.h" +#include "pci.h" +#include "AsmMacros.h" +#include "vbios.h" + +void log_err(char *format, ...) __attribute__ ((format (printf, 1, 2))); + +#define SIZE 0x100000 +#define VRAM_START 0xA0000 +#define VRAM_SIZE 0x1FFFF +#define V_BIOS_SIZE 0x1FFFF +#define BIOS_START 0x7C00 /* default BIOS entry */ + +static CARD8 code[] = { 0xcd, 0x10, 0xf4 }; /* int 0x10, hlt */ +// static CARD8 code13[] = { 0xcd, 0x13, 0xf4 }; /* int 0x13, hlt */ + +static int map(void); +static void unmap(void); +static int map_vram(void); +static void unmap_vram(void); +static int copy_vbios(void); +// static int copy_sbios(void); +#if MAP_SYS_BIOS +static int copy_sys_bios(void); +#endif +static int copy_bios_ram(); +static int setup_system_bios(void); +static void setup_int_vect(void); +static int chksum(CARD8 *start); + +void loadCodeToMem(unsigned char *ptr, CARD8 *code); + +static int vram_mapped = 0; +static int int10inited = 0; + +static sigjmp_buf longjmp_buf; + +static void sigsegv_handler(int); + +int InitInt10(int pci_cfg_method) +{ + if(geteuid()) return -1; + + if(!map()) return -1; + + if(!setup_system_bios()) { + unmap(); + return -1; + } + + setup_io(); + + if(iopl(3) < 0) { + unmap(); + return -1; + } + + scan_pci(pci_cfg_method); + + for(; CurrentPci; CurrentPci = CurrentPci->next) { + if(CurrentPci->active) break; + } + + iopl(0); + + setup_int_vect(); + + if(!copy_vbios()) { + unmap(); + return -1; + } + +#if 0 + if(!copy_sbios()) { + unmap(); + return -1; + } +#endif + + if(!map_vram() || !copy_bios_ram()) { + unmap(); + return -1; + } + + int10inited = 1; + +#if 0 + /* int 13 default location (fdd) */ + ((CARD16*)0)[(0x13<<1)+1] = 0xf000; + ((CARD16*)0)[0x13<<1] = 0xec59; +#endif + + return 0; +} + + +void FreeInt10() +{ + if(!int10inited) return; + + unmap_vram(); + unmap(); + + int10inited = 0; +} + + +void sigsegv_handler(int num) +{ + siglongjmp(longjmp_buf, num + 1000); +} + + +int CallInt10(int *ax, int *bx, int *cx, unsigned char *buf, int len, int cpuemu) +{ + i86biosRegs bRegs; + void (*old_sigsegv_handler)(int) = SIG_DFL; + void (*old_sigill_handler)(int) = SIG_DFL; + void (*old_sigtrap_handler)(int) = SIG_DFL; + int jmp; + + if(!int10inited) return -1; + memset(&bRegs, 0, sizeof bRegs); + bRegs.ax = *ax; + bRegs.bx = *bx; + bRegs.cx = *cx; + bRegs.dx = 0; + bRegs.es = 0x7e0; + bRegs.di = 0x0; + if(buf) memcpy((unsigned char *) 0x7e00, buf, len); + + iopl(3); + + jmp = sigsetjmp(longjmp_buf, 1); + + if(!jmp) { + old_sigsegv_handler = signal(SIGSEGV, sigsegv_handler); + old_sigill_handler = signal(SIGILL, sigsegv_handler); + old_sigtrap_handler = signal(SIGTRAP, sigsegv_handler); + + loadCodeToMem((unsigned char *) BIOS_START, code); + do_x86(BIOS_START, &bRegs, cpuemu); + } + else { + int10inited = 0; + log_err("oops: got signal %d in vm86() code\n", jmp - 1000); + } + + signal(SIGTRAP, old_sigtrap_handler); + signal(SIGILL, old_sigill_handler); + signal(SIGSEGV, old_sigsegv_handler); + + iopl(0); + + if(buf) memcpy(buf, (unsigned char *) 0x7e00, len); + + *ax = bRegs.ax; + *bx = bRegs.bx; + *cx = bRegs.cx; + + return bRegs.ax; +} + + +#if 0 +int CallInt13(int *ax, int *bx, int *cx, int *dx, unsigned char *buf, int len, int cpuemu) +{ + i86biosRegs bRegs; + + if(!int10inited) return -1; + memset(&bRegs, 0, sizeof bRegs); + bRegs.ax = *ax; + bRegs.bx = *bx; + bRegs.cx = *cx; + bRegs.dx = *dx; + bRegs.es = 0x7e0; + bRegs.ds = 0x7e0; + bRegs.di = 0x0; + bRegs.si = 0x0; + if(buf) memcpy((unsigned char *) 0x7e00, buf, len); + + iopl(3); + + loadCodeToMem((unsigned char *) BIOS_START, code13); + do_x86(BIOS_START, &bRegs, cpuemu); + + iopl(0); + + if(buf) memcpy(buf, (unsigned char *) 0x7e00, len); + + *ax = bRegs.ax; + *bx = bRegs.bx; + *cx = bRegs.cx; + *dx = bRegs.dx; + + return bRegs.ax; +} +#endif + + +int map() +{ + void* mem; + + mem = mmap(0, (size_t) SIZE, PROT_EXEC | PROT_READ | PROT_WRITE, MAP_FIXED | MAP_PRIVATE | MAP_ANON, -1, 0); + + if(mem) { + perror("anonymous map"); + return 0; + } + + memset(mem, 0, SIZE); + + loadCodeToMem((unsigned char *) BIOS_START, code); + + return 1; +} + + +void unmap() +{ + munmap(0, SIZE); +} + + +static int +map_vram(void) +{ + int mem_fd; + +#ifdef __ia64__ + if ((mem_fd = open(MEM_FILE,O_RDWR | O_SYNC))<0) +#else + if ((mem_fd = open(MEM_FILE,O_RDWR))<0) +#endif + { + perror("opening memory"); + return 0; + } + +#ifndef __alpha__ + if (mmap((void *) VRAM_START, (size_t) VRAM_SIZE, + PROT_EXEC | PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, + mem_fd, VRAM_START) == (void *) -1) +#else + if (!_bus_base()) sparse_shift = 7; /* Uh, oh, JENSEN... */ + if (!_bus_base_sparse()) sparse_shift = 0; + if ((vram_map = mmap(0,(size_t) (VRAM_SIZE << sparse_shift), + PROT_READ | PROT_WRITE, + MAP_SHARED, + mem_fd, (VRAM_START << sparse_shift) + | _bus_base_sparse())) == (void *) -1) +#endif + { + perror("mmap error in map_hardware_ram"); + close(mem_fd); + return (0); + } + vram_mapped = 1; + close(mem_fd); + return (1); +} + + +void unmap_vram() +{ + if(!vram_mapped) return; + + munmap((void*) VRAM_START, VRAM_SIZE); + + vram_mapped = 0; +} + + +/* + * Read video BIOS from /dev/mem. + * + * Return: + * 0: failed + * 1: ok + */ +int copy_vbios() +{ + int mem_fd, size, ok = 0; + unsigned char tmp[3]; + + if((mem_fd = open(MEM_FILE, O_RDONLY)) == -1) { + log_err("vbe: failed to open BIOS memory, errno = %d", errno); + + return 0; + } + + if(lseek(mem_fd, (off_t) V_BIOS, SEEK_SET) != (off_t) V_BIOS) { + log_err("vbe: lseek failed, errno = %d\n", errno); + } + else { + if(read(mem_fd, tmp, sizeof tmp) != sizeof tmp) { + log_err("vbe: failed to read %u bytes at 0x%x, errno = %d\n", (unsigned) sizeof tmp, V_BIOS, errno); + } + else { + if(lseek(mem_fd, V_BIOS, SEEK_SET) != V_BIOS) { + log_err("vbe: lseek failed, errno = %d\n", errno); + } + else { + if(tmp[0] != 0x55 || tmp[1] != 0xAA ) { + log_err("vbe: no bios found at: 0x%x\n", V_BIOS); + } + else { + size = tmp[2] * 0x200; + + if(read(mem_fd, (char *) V_BIOS, size) != size) { + log_err("vbe: failed to read %d bytes at 0x%x, errno = %d\n", size, V_BIOS, errno); + } + else { + if(chksum((CARD8 *) V_BIOS)) ok = 1; + } + } + } + } + } + + close(mem_fd); + + return ok; +} + + +#if 0 +#define SYS_BIOS 0xe0000 +#define SYS_BIOS_SIZE 0x20000 +int copy_sbios() +{ + int fd; + + if((fd = open(MEM_FILE, O_RDONLY)) < 0) { + perror("opening memory"); + return 0; + } + + if(lseek(fd,(off_t) SYS_BIOS, SEEK_SET) == (off_t) SYS_BIOS) { + read(fd, (void *) SYS_BIOS, SYS_BIOS_SIZE); + } + + close(fd); + + return 1; +} +#endif + + +#if MAP_SYS_BIOS +static int +copy_sys_bios(void) +{ +#define SYS_BIOS 0xF0000 + int mem_fd; + + if ((mem_fd = open(MEM_FILE,O_RDONLY))<0) { + perror("opening memory"); + return (0); + } + + if (lseek(mem_fd,(off_t) SYS_BIOS,SEEK_SET) != (off_t) SYS_BIOS) + goto Error; + if (read(mem_fd, (char *)SYS_BIOS, (size_t) 0xFFFF) != (size_t) 0xFFFF) + goto Error; + + close(mem_fd); + return (1); + +Error: + perror("sys_bios"); + close(mem_fd); + return (0); +} +#endif + + +static int +copy_bios_ram(void) +{ +#define BIOS_RAM 0 + int mem_fd; + + if ((mem_fd = open(MEM_FILE,O_RDONLY))<0) { + perror("opening memory"); + return (0); + } + + if (lseek(mem_fd,(off_t) BIOS_RAM,SEEK_SET) != (off_t) BIOS_RAM) + goto Error; + if (read(mem_fd, (char *)BIOS_RAM, (size_t) 0x1000) != (size_t) 0x1000) + goto Error; + + close(mem_fd); + return (1); + +Error: + perror("bios_ram"); + close(mem_fd); + return (0); +} + + +void loadCodeToMem(unsigned char *ptr, CARD8 *code) +{ + while((*ptr++ = *code++) != 0xf4 /* hlt */); + + return; +} + + +/* + * here we are really paranoid about faking a "real" + * BIOS. Most of this information was pulled from + * dosem. + */ +static void +setup_int_vect(void) +{ + const CARD16 cs = 0x0000; + const CARD16 ip = 0x0; + int i; + + /* let the int vects point to the SYS_BIOS seg */ + for (i=0; i<0x80; i++) { + ((CARD16*)0)[i<<1] = ip; + ((CARD16*)0)[(i<<1)+1] = cs; + } + /* video interrupts default location */ + ((CARD16*)0)[(0x42<<1)+1] = 0xf000; + ((CARD16*)0)[0x42<<1] = 0xf065; + ((CARD16*)0)[(0x10<<1)+1] = 0xf000; + ((CARD16*)0)[0x10<<1] = 0xf065; + /* video param table default location (int 1d) */ + ((CARD16*)0)[(0x1d<<1)+1] = 0xf000; + ((CARD16*)0)[0x1d<<1] = 0xf0A4; + /* font tables default location (int 1F) */ + ((CARD16*)0)[(0x1f<<1)+1] = 0xf000; + ((CARD16*)0)[0x1f<<1] = 0xfa6e; + + /* int 11 default location */ + ((CARD16*)0)[(0x11<1)+1] = 0xf000; + ((CARD16*)0)[0x11<<1] = 0xf84d; + /* int 12 default location */ + ((CARD16*)0)[(0x12<<1)+1] = 0xf000; + ((CARD16*)0)[0x12<<1] = 0xf841; + /* int 15 default location */ + ((CARD16*)0)[(0x15<<1)+1] = 0xf000; + ((CARD16*)0)[0x15<<1] = 0xf859; + /* int 1A default location */ + ((CARD16*)0)[(0x1a<<1)+1] = 0xf000; + ((CARD16*)0)[0x1a<<1] = 0xff6e; + /* int 05 default location */ + ((CARD16*)0)[(0x05<<1)+1] = 0xf000; + ((CARD16*)0)[0x05<<1] = 0xff54; + /* int 08 default location */ + ((CARD16*)0)[(0x8<<1)+1] = 0xf000; + ((CARD16*)0)[0x8<<1] = 0xfea5; + /* int 13 default location (fdd) */ + ((CARD16*)0)[(0x13<<1)+1] = 0xf000; + ((CARD16*)0)[0x13<<1] = 0xec59; + /* int 0E default location */ + ((CARD16*)0)[(0xe<<1)+1] = 0xf000; + ((CARD16*)0)[0xe<<1] = 0xef57; + /* int 17 default location */ + ((CARD16*)0)[(0x17<<1)+1] = 0xf000; + ((CARD16*)0)[0x17<<1] = 0xefd2; + /* fdd table default location (int 1e) */ + ((CARD16*)0)[(0x1e<<1)+1] = 0xf000; + ((CARD16*)0)[0x1e<<1] = 0xefc7; +} + +static int +setup_system_bios(void) +{ + char *date = "06/01/99"; + char *eisa_ident = "PCI/ISA"; + +#if MAP_SYS_BIOS + if (!copy_sys_bios()) return 0; + return 1; +#endif +// memset((void *)0xF0000,0xf4,0xfff7); + + /* + * we trap the "industry standard entry points" to the BIOS + * and all other locations by filling them with "hlt" + * TODO: implement hlt-handler for these + */ + memset((void *)0xF0000,0xf4,0x10000); + + /* + * TODO: we should copy the fdd table (0xfec59-0xfec5b) + * the video parameter table (0xf0ac-0xf0fb) + * and the font tables (0xfa6e-0xfe6d) + * from the original bios here + */ + + /* set bios date */ + strcpy((char *)0xFFFF5,date); + /* set up eisa ident string */ + strcpy((char *)0xFFFD9,eisa_ident); + /* write system model id for IBM-AT */ + ((char *)0)[0xFFFFE] = 0xfc; + + return 1; +} + + +/* + * Check BIOS CRC. + * + * Return: + * 0: failed + * 1: ok + */ +int chksum(CARD8 *start) +{ + CARD16 size; + CARD8 val = 0; + int i; + + size = start[2] * 0x200; + for(i = 0; i < size; i++) val += start[i]; + + if(!val) return 1; + + log_err("vbe: BIOS chksum wrong\n"); + + return 0; +} + diff --git a/tools/ddcprobe/int10/pci.h b/tools/ddcprobe/int10/pci.h new file mode 100644 index 000000000..840f9d4ae --- /dev/null +++ b/tools/ddcprobe/int10/pci.h @@ -0,0 +1,127 @@ +/* + * Copyright 1999 Egbert Eich + * + * 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 name of the authors not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. The authors makes no representations + * about the suitability of this software for any purpose. It is provided + * "as is" without express or implied warranty. + * + * THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE AUTHORS 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. + */ +#include "v86bios.h" + +#ifndef V86_PCI_H +#define V86_PCI_H + +typedef union { + struct { + unsigned int zero:2; + unsigned int reg:6; + unsigned int func:3; + unsigned int dev:5; + unsigned int bus:8; + unsigned int reserved:7; + unsigned int enable:1; + } pci; + CARD32 l; +} PciSlot; + +typedef struct pciBusRec { + CARD8 primary; + CARD8 secondary; + CARD32 bctl; + PciSlot Slot; + struct pciBusRec *next; + struct pciBusRec *pBus; +} PciBusRec, *PciBusPtr; + +typedef struct pciStructRec { + CARD16 VendorID; + CARD16 DeviceID; + CARD8 Interface; + CARD8 BaseClass; + CARD8 SubClass; + CARD32 RomBase; + CARD32 bus; + CARD8 dev; + CARD8 func; + CARD32 cmd_st; + int active; + PciSlot Slot; + struct pciStructRec *next; + PciBusPtr pBus; +} PciStructRec , *PciStructPtr; + + +extern PciStructPtr CurrentPci; +extern PciStructPtr PciList; +extern PciStructPtr BootBios; +extern int pciMaxBus; + +extern CARD32 findPci(CARD16 slotBX); +extern CARD16 pciSlotBX(PciStructPtr); +PciStructPtr findPciDevice(CARD16 vendorID, CARD16 deviceID, char n); +PciStructPtr findPciClass(CARD8 intf, CARD8 subClass, CARD16 class, char n); + +extern CARD8 PciRead8(int offset, CARD32 slot); +extern CARD16 PciRead16(int offset, CARD32 slot); +extern CARD32 PciRead32(int offset, CARD32 slot); + +extern void PciWrite8(int offset,CARD8 byte, CARD32 slot); +extern void PciWrite16(int offset,CARD16 word, CARD32 slot); +extern void PciWrite32(int offset,CARD32 lg, CARD32 slot); + +extern void scan_pci(int); +extern void pciVideoDisable(void); +extern void pciVideoRestore(void); +extern void EnableCurrent(void); +extern int mapPciRom(PciStructPtr pciP); +extern int cfg1out(CARD16 addr, CARD32 val); +extern int cfg1in(CARD16 addr, CARD32 *val); +extern void list_pci(void); +extern PciStructPtr findPciByIDs(int bus, int dev, int func); + +#define PCI_MODE2_ENABLE_REG 0xCF8 +#define PCI_MODE2_FORWARD_REG 0xCFA +#define PCI_MODE1_ADDRESS_REG 0xCF8 +#define PCI_MODE1_DATA_REG 0xCFC +#if defined(__alpha__) || defined(__sparc__) +#define PCI_EN 0x00000000 +#else +#define PCI_EN 0x80000000 +#endif +#define MAX_DEV_PER_VENDOR_CFG1 32 +#define BRIDGE_CLASS(x) (x == 0x06) +#define BRIDGE_PCI_CLASS(x) (x == 0x04) +#define BRIDGE_HOST_CLASS(x) (x == 0x00) +#define PCI_CLASS_PREHISTORIC 0x00 +#define PCI_SUBCLASS_PREHISTORIC_VGA 0x01 +#define PCI_CLASS_DISPLAY 0x03 +#define PCI_SUBCLASS_DISPLAY_VGA 0x00 +#define PCI_SUBCLASS_DISPLAY_XGA 0x01 +#define PCI_SUBCLASS_DISPLAY_MISC 0x80 +#define VIDEO_CLASS(b,s) \ + (((b) == PCI_CLASS_PREHISTORIC && (s) == PCI_SUBCLASS_PREHISTORIC_VGA) || \ + ((b) == PCI_CLASS_DISPLAY && (s) == PCI_SUBCLASS_DISPLAY_VGA) ||\ + ((b) == PCI_CLASS_DISPLAY && (s) == PCI_SUBCLASS_DISPLAY_XGA) ||\ + ((b) == PCI_CLASS_DISPLAY && (s) == PCI_SUBCLASS_DISPLAY_MISC)) +#define PCI_MULTIFUNC_DEV 0x80 +#define MAX_PCI_DEVICES 64 +#define PCI_MAXBUS 16 +#define PCI_IS_MEM 0x00000001 +#define MAX_PCI_ROM_SIZE (1024 * 1024 * 16) + +#define IS_MEM32(x) ((x & 0x7) == 0 && x != 0) +#define IS_MEM64(x) ((x & 0x7) == 0x4) +#endif diff --git a/tools/ddcprobe/int10/v86bios.h b/tools/ddcprobe/int10/v86bios.h new file mode 100644 index 000000000..c0c8acca6 --- /dev/null +++ b/tools/ddcprobe/int10/v86bios.h @@ -0,0 +1,215 @@ +/* + * Copyright 1999 Egbert Eich + * + * 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 name of the authors not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. The authors makes no representations + * about the suitability of this software for any purpose. It is provided + * "as is" without express or implied warranty. + * + * THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE AUTHORS 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. + */ +#ifndef V86_BIOS_H +#define V86_BIOS_H + +#if defined (__i386__) || defined (__i486__) || defined (__i586__) || defined (__i686__) || defined (__k6__) +# ifndef __ia32__ +# define __ia32__ +# endif +#endif + +#include + +#define p_printf(f,a...) do {if (Config.PrintPort) lprintf(f,##a);} \ + while(0) +#define i_printf(f,a...) do {if (Config.PrintIrq) lprintf(f,##a);} \ + while(0) +#define P_printf(f,a...) do {if (Config.PrintPci) lprintf(f,##a);} \ + while(0) + +typedef unsigned char CARD8; +typedef unsigned short CARD16; +typedef unsigned int CARD32; +#if defined (__alpha__) || defined (__ia64__) +typedef unsigned long memType; +#else +typedef unsigned int memType; +#endif + +typedef int Bool; + +#define FALSE 0 +#define TRUE 1 + +struct config { + Bool PrintPort; + Bool IoStatistics; + Bool PrintIrq; + Bool PrintPci; + Bool ShowAllDev; + Bool PrintIp; + Bool SaveBios; + Bool Trace; + Bool ConfigActiveOnly; + Bool ConfigActiveDevice; + Bool MapSysBios; + Bool Resort; + Bool FixRom; + Bool NoConsole; + Bool BootOnly; + int Verbose; +}; + +struct pio { + CARD8 (*inb)(CARD16); + CARD16 (*inw)(CARD16); + CARD32 (*inl)(CARD16); + void (*outb)(CARD16,CARD8); + void (*outw)(CARD16,CARD16); + void (*outl)(CARD16,CARD32); +}; + +struct regs86 { + long ebx; + long ecx; + long edx; + long esi; + long edi; + long ebp; + long eax; + long eip; + long esp; + unsigned short cs; + unsigned short ss; + unsigned short es; + unsigned short ds; + unsigned short fs; + unsigned short gs; + long eflags; +}; + +typedef struct { + CARD32 ax; + CARD32 bx; + CARD32 cx; + CARD32 dx; + CARD32 cs; + CARD32 es; + CARD32 ds; + CARD32 si; + CARD32 di; +} i86biosRegs, *i86biosRegsPtr; + +typedef struct { + int fd; + int vt; +} console; + +typedef struct { + void* address; + CARD8 orgval; +} haltpoints; + +enum dev_type { NONE, ISA, PCI }; +struct device { + Bool booted; + enum dev_type type; + union { + int none; + struct pci { + int bus; + int dev; + int func; + } pci; + } loc; +}; + +extern struct device Device; + +#ifdef __alpha__ +unsigned long _bus_base(void); +extern void* vram_map; +extern int sparse_shift; +#endif + +extern struct pio P; +extern struct config Config; +#define IOPERM_BITS 1024 +extern int ioperm_list[IOPERM_BITS]; + +extern void setup_io(void); +extern void do_x86(unsigned long bios_start,i86biosRegsPtr regs, int cpuemu); +extern int run_bios_int(int num, struct regs86 *regs); +extern CARD32 getIntVect(int num); +CARD32 getIP(void); + +extern void call_boot(struct device *dev); +extern void runINT(int num,i86biosRegsPtr Regs); +extern void add_hlt(unsigned long addr); +extern void del_hlt(int addr); +extern void list_hlt(); + +extern int port_rep_inb(CARD16 port, CARD8 *base, int d_f, CARD32 count); +extern int port_rep_inw(CARD16 port, CARD16 *base, int d_f, CARD32 count); +extern int port_rep_inl(CARD16 port, CARD32 *base, int d_f, CARD32 count); +extern int port_rep_outb(CARD16 port, CARD8 *base, int d_f, CARD32 count); +extern int port_rep_outw(CARD16 port, CARD16 *base, int d_f, CARD32 count); +extern int port_rep_outl(CARD16 port, CARD32 *base, int d_f, CARD32 count); +extern CARD8 p_inb(CARD16 port); +extern CARD16 p_inw(CARD16 port); +extern CARD32 p_inl(CARD16 port); +extern void p_outb(CARD16 port, CARD8 val); +extern void p_outw(CARD16 port, CARD16 val); +extern void p_outl(CARD16 port, CARD32 val); +#ifdef __alpha__ +extern CARD8 a_inb(CARD16 port); +extern CARD16 a_inw(CARD16 port); +extern void a_outb(CARD16 port, CARD8 val); +extern void a_outw(CARD16 port, CARD16 val); +#endif +#ifdef __alpha__ +CARD8 mem_rb(CARD32 addr); +CARD16 mem_rw(CARD32 addr); +CARD32 mem_rl(CARD32 addr); +void mem_wb(CARD32 addr, CARD8 val); +void mem_ww(CARD32 addr, CARD16 val); +void mem_wl(CARD32 addr, CARD32 val); +#endif +extern void io_statistics(void); +extern void clear_stat(void); +extern int int_handler(int num, struct regs86 *regs); + +extern console open_console(void); +extern void close_console(console); + +extern void dprint(unsigned long start, unsigned long size); + +extern Bool logging; +extern Bool nostdout; +extern char* logfile; +extern void logon(void* ptr); +extern void logoff(); +extern void lprintf(const char *f, ...); + +#define MEM_FILE "/dev/mem" +#define DEFAULT_V_BIOS 0xc0000 +#ifndef V_BIOS +#define V_BIOS DEFAULT_V_BIOS +#endif + +#ifdef __alpha__ +#define NEED_PCI_IO +#endif + +#endif + diff --git a/tools/ddcprobe/int10/vbios.h b/tools/ddcprobe/int10/vbios.h new file mode 100644 index 000000000..6bd5e8043 --- /dev/null +++ b/tools/ddcprobe/int10/vbios.h @@ -0,0 +1,4 @@ +int InitInt10(int); +int CallInt10(int *ax, int *bx, int *cx, unsigned char *buf, int len, int cpuemu); +int CallInt13(int *ax, int *bx, int *cx, int *dx, unsigned char *buf, int len, int cpuemu); +void FreeInt10(void); diff --git a/tools/ddcprobe/int10/vm86_struct.h b/tools/ddcprobe/int10/vm86_struct.h new file mode 100644 index 000000000..772e6cab2 --- /dev/null +++ b/tools/ddcprobe/int10/vm86_struct.h @@ -0,0 +1,135 @@ +#ifndef _LINUX_VM86_H +#define _LINUX_VM86_H + +/* + * I'm guessing at the VIF/VIP flag usage, but hope that this is how + * the Pentium uses them. Linux will return from vm86 mode when both + * VIF and VIP is set. + * + * On a Pentium, we could probably optimize the virtual flags directly + * in the eflags register instead of doing it "by hand" in vflags... + * + * Linus + */ + +#define TF_MASK 0x00000100 +#define IF_MASK 0x00000200 +#define IOPL_MASK 0x00003000 +#define NT_MASK 0x00004000 +#define VM_MASK 0x00020000 +#define AC_MASK 0x00040000 +#define VIF_MASK 0x00080000 /* virtual interrupt flag */ +#define VIP_MASK 0x00100000 /* virtual interrupt pending */ +#define ID_MASK 0x00200000 + +#define BIOSSEG 0x0f000 + +#define CPU_086 0 +#define CPU_186 1 +#define CPU_286 2 +#define CPU_386 3 +#define CPU_486 4 +#define CPU_586 5 + +/* + * Return values for the 'vm86()' system call + */ +#define VM86_TYPE(retval) ((retval) & 0xff) +#define VM86_ARG(retval) ((retval) >> 8) + +#define VM86_SIGNAL 0 /* return due to signal */ +#define VM86_UNKNOWN 1 /* unhandled GP fault - IO-instruction or similar */ +#define VM86_INTx 2 /* int3/int x instruction (ARG = x) */ +#define VM86_STI 3 /* sti/popf/iret instruction enabled virtual interrupts */ + +/* + * Additional return values when invoking new vm86() + */ +#define VM86_PICRETURN 4 /* return due to pending PIC request */ +#define VM86_TRAP 6 /* return due to DOS-debugger request */ + +/* + * function codes when invoking new vm86() + */ +#define VM86_PLUS_INSTALL_CHECK 0 +#define VM86_ENTER 1 +#define VM86_ENTER_NO_BYPASS 2 +#define VM86_REQUEST_IRQ 3 +#define VM86_FREE_IRQ 4 +#define VM86_GET_IRQ_BITS 5 +#define VM86_GET_AND_RESET_IRQ 6 + +/* + * This is the stack-layout seen by the user space program when we have + * done a translation of "SAVE_ALL" from vm86 mode. The real kernel layout + * is 'kernel_vm86_regs' (see below). + */ + +struct vm86_regs { +/* + * normal regs, with special meaning for the segment descriptors.. + */ + long ebx; + long ecx; + long edx; + long esi; + long edi; + long ebp; + long eax; + long __null_ds; + long __null_es; + long __null_fs; + long __null_gs; + long orig_eax; + long eip; + unsigned short cs, __csh; + long eflags; + long esp; + unsigned short ss, __ssh; +/* + * these are specific to v86 mode: + */ + unsigned short es, __esh; + unsigned short ds, __dsh; + unsigned short fs, __fsh; + unsigned short gs, __gsh; +}; + +struct revectored_struct { + unsigned long __map[8]; /* 256 bits */ +}; + +struct vm86_struct { + struct vm86_regs regs; + unsigned long flags; + unsigned long screen_bitmap; + unsigned long cpu_type; + struct revectored_struct int_revectored; + struct revectored_struct int21_revectored; +}; + +/* + * flags masks + */ +#define VM86_SCREEN_BITMAP 0x0001 + +struct vm86plus_info_struct { + unsigned long force_return_for_pic:1; + unsigned long vm86dbg_active:1; /* for debugger */ + unsigned long vm86dbg_TFpendig:1; /* for debugger */ + unsigned long unused:28; + unsigned long is_vm86pus:1; /* for vm86 internal use */ + unsigned char vm86dbg_intxxtab[32]; /* for debugger */ +}; + +struct vm86plus_struct { + struct vm86_regs regs; + unsigned long flags; + unsigned long screen_bitmap; + unsigned long cpu_type; + struct revectored_struct int_revectored; + struct revectored_struct int21_revectored; + struct vm86plus_info_struct vm86plus; +}; + +#endif -- cgit v1.2.1