1706f2543Smrg/* 2706f2543Smrg * XFree86 int10 module 3706f2543Smrg * execute BIOS int 10h calls in x86 real mode environment 4706f2543Smrg * Copyright 1999 Egbert Eich 5706f2543Smrg * 6706f2543Smrg * Part of this code was inspired by the VBIOS POSTing code in DOSEMU 7706f2543Smrg * developed by the "DOSEMU-Development-Team" 8706f2543Smrg */ 9706f2543Smrg 10706f2543Smrg/* 11706f2543Smrg * To debug port accesses define PRINT_PORT to 1. 12706f2543Smrg * Note! You also have to comment out ioperm() 13706f2543Smrg * in xf86EnableIO(). Otherwise we won't trap 14706f2543Smrg * on PIO. 15706f2543Smrg */ 16706f2543Smrg 17706f2543Smrg#ifdef HAVE_XORG_CONFIG_H 18706f2543Smrg#include <xorg-config.h> 19706f2543Smrg#endif 20706f2543Smrg 21706f2543Smrg#define PRINT_PORT 0 22706f2543Smrg 23706f2543Smrg#include <unistd.h> 24706f2543Smrg 25706f2543Smrg#include <X11/Xos.h> 26706f2543Smrg#include "xf86.h" 27706f2543Smrg#include "xf86_OSproc.h" 28706f2543Smrg#include "compiler.h" 29706f2543Smrg#define _INT10_PRIVATE 30706f2543Smrg#include "int10Defines.h" 31706f2543Smrg#include "xf86int10.h" 32706f2543Smrg#include "Pci.h" 33706f2543Smrg#ifdef _X86EMU 34706f2543Smrg#include "x86emu/x86emui.h" 35706f2543Smrg#else 36706f2543Smrg#define DEBUG_IO_TRACE() 0 37706f2543Smrg#endif 38706f2543Smrg#include <pciaccess.h> 39706f2543Smrg 40706f2543Smrgstatic int pciCfg1in(CARD16 addr, CARD32 *val); 41706f2543Smrgstatic int pciCfg1out(CARD16 addr, CARD32 val); 42706f2543Smrgstatic int pciCfg1inw(CARD16 addr, CARD16 *val); 43706f2543Smrgstatic int pciCfg1outw(CARD16 addr, CARD16 val); 44706f2543Smrgstatic int pciCfg1inb(CARD16 addr, CARD8 *val); 45706f2543Smrgstatic int pciCfg1outb(CARD16 addr, CARD8 val); 46706f2543Smrg#if defined (_PC) 47706f2543Smrgstatic void SetResetBIOSVars(xf86Int10InfoPtr pInt, Bool set); 48706f2543Smrg#endif 49706f2543Smrg 50706f2543Smrg#define REG pInt 51706f2543Smrg 52706f2543Smrgint 53706f2543Smrgsetup_int(xf86Int10InfoPtr pInt) 54706f2543Smrg{ 55706f2543Smrg if (pInt != Int10Current) { 56706f2543Smrg if (!MapCurrentInt10(pInt)) 57706f2543Smrg return -1; 58706f2543Smrg Int10Current = pInt; 59706f2543Smrg } 60706f2543Smrg X86_EAX = (CARD32) pInt->ax; 61706f2543Smrg X86_EBX = (CARD32) pInt->bx; 62706f2543Smrg X86_ECX = (CARD32) pInt->cx; 63706f2543Smrg X86_EDX = (CARD32) pInt->dx; 64706f2543Smrg X86_ESI = (CARD32) pInt->si; 65706f2543Smrg X86_EDI = (CARD32) pInt->di; 66706f2543Smrg X86_EBP = (CARD32) pInt->bp; 67706f2543Smrg X86_ESP = 0x1000; X86_SS = pInt->stackseg >> 4; 68706f2543Smrg X86_EIP = 0x0600; X86_CS = 0x0; /* address of 'hlt' */ 69706f2543Smrg X86_DS = 0x40; /* standard pc ds */ 70706f2543Smrg X86_ES = pInt->es; 71706f2543Smrg X86_FS = 0; 72706f2543Smrg X86_GS = 0; 73706f2543Smrg X86_EFLAGS = X86_IF_MASK | X86_IOPL_MASK; 74706f2543Smrg#if defined (_PC) 75706f2543Smrg if (pInt->Flags & SET_BIOS_SCRATCH) 76706f2543Smrg SetResetBIOSVars(pInt, TRUE); 77706f2543Smrg#endif 78706f2543Smrg OsBlockSignals(); 79706f2543Smrg return 0; 80706f2543Smrg} 81706f2543Smrg 82706f2543Smrgvoid 83706f2543Smrgfinish_int(xf86Int10InfoPtr pInt, int sig) 84706f2543Smrg{ 85706f2543Smrg OsReleaseSignals(); 86706f2543Smrg pInt->ax = (CARD32) X86_EAX; 87706f2543Smrg pInt->bx = (CARD32) X86_EBX; 88706f2543Smrg pInt->cx = (CARD32) X86_ECX; 89706f2543Smrg pInt->dx = (CARD32) X86_EDX; 90706f2543Smrg pInt->si = (CARD32) X86_ESI; 91706f2543Smrg pInt->di = (CARD32) X86_EDI; 92706f2543Smrg pInt->es = (CARD16) X86_ES; 93706f2543Smrg pInt->bp = (CARD32) X86_EBP; 94706f2543Smrg pInt->flags = (CARD32) X86_FLAGS; 95706f2543Smrg#if defined (_PC) 96706f2543Smrg if (pInt->Flags & RESTORE_BIOS_SCRATCH) 97706f2543Smrg SetResetBIOSVars(pInt, FALSE); 98706f2543Smrg#endif 99706f2543Smrg} 100706f2543Smrg 101706f2543Smrg/* general software interrupt handler */ 102706f2543SmrgCARD32 103706f2543SmrggetIntVect(xf86Int10InfoPtr pInt,int num) 104706f2543Smrg{ 105706f2543Smrg return MEM_RW(pInt, num << 2) + (MEM_RW(pInt, (num << 2) + 2) << 4); 106706f2543Smrg} 107706f2543Smrg 108706f2543Smrgvoid 109706f2543Smrgpushw(xf86Int10InfoPtr pInt, CARD16 val) 110706f2543Smrg{ 111706f2543Smrg X86_ESP -= 2; 112706f2543Smrg MEM_WW(pInt, ((CARD32) X86_SS << 4) + X86_SP, val); 113706f2543Smrg} 114706f2543Smrg 115706f2543Smrgint 116706f2543Smrgrun_bios_int(int num, xf86Int10InfoPtr pInt) 117706f2543Smrg{ 118706f2543Smrg CARD32 eflags; 119706f2543Smrg#ifndef _PC 120706f2543Smrg /* check if bios vector is initialized */ 121706f2543Smrg if (MEM_RW(pInt, (num << 2) + 2) == (SYS_BIOS >> 4)) { /* SYS_BIOS_SEG ?*/ 122706f2543Smrg 123706f2543Smrg if (num == 21 && X86_AH == 0x4e) { 124706f2543Smrg xf86DrvMsg(pInt->scrnIndex, X_NOTICE, 125706f2543Smrg "Failing Find-Matching-File on non-PC" 126706f2543Smrg " (int 21, func 4e)\n"); 127706f2543Smrg X86_AX = 2; 128706f2543Smrg SET_FLAG(F_CF); 129706f2543Smrg return 1; 130706f2543Smrg } else { 131706f2543Smrg xf86DrvMsgVerb(pInt->scrnIndex, X_NOT_IMPLEMENTED, 2, 132706f2543Smrg "Ignoring int 0x%02x call\n", num); 133706f2543Smrg if (xf86GetVerbosity() > 3) { 134706f2543Smrg dump_registers(pInt); 135706f2543Smrg stack_trace(pInt); 136706f2543Smrg } 137706f2543Smrg return 1; 138706f2543Smrg } 139706f2543Smrg } 140706f2543Smrg#endif 141706f2543Smrg#ifdef PRINT_INT 142706f2543Smrg ErrorF("calling card BIOS at: "); 143706f2543Smrg#endif 144706f2543Smrg eflags = X86_EFLAGS; 145706f2543Smrg#if 0 146706f2543Smrg eflags = eflags | IF_MASK; 147706f2543Smrg X86_EFLAGS = X86_EFLAGS & ~(VIF_MASK | TF_MASK | IF_MASK | NT_MASK); 148706f2543Smrg#endif 149706f2543Smrg pushw(pInt, eflags); 150706f2543Smrg pushw(pInt, X86_CS); 151706f2543Smrg pushw(pInt, X86_IP); 152706f2543Smrg X86_CS = MEM_RW(pInt, (num << 2) + 2); 153706f2543Smrg X86_IP = MEM_RW(pInt, num << 2); 154706f2543Smrg#ifdef PRINT_INT 155706f2543Smrg ErrorF("0x%x:%lx\n", X86_CS, X86_EIP); 156706f2543Smrg#endif 157706f2543Smrg return 1; 158706f2543Smrg} 159706f2543Smrg 160706f2543Smrg/* Debugging stuff */ 161706f2543Smrgvoid 162706f2543Smrgdump_code(xf86Int10InfoPtr pInt) 163706f2543Smrg{ 164706f2543Smrg int i; 165706f2543Smrg unsigned long lina = SEG_ADR((CARD32), X86_CS, IP); 166706f2543Smrg 167706f2543Smrg xf86DrvMsgVerb(pInt->scrnIndex, X_INFO, 3, "code at 0x%8.8lx:\n", lina); 168706f2543Smrg for (i=0; i<0x10; i++) 169706f2543Smrg xf86ErrorFVerb(3, " %2.2x", MEM_RB(pInt, lina + i)); 170706f2543Smrg xf86ErrorFVerb(3, "\n"); 171706f2543Smrg for (; i<0x20; i++) 172706f2543Smrg xf86ErrorFVerb(3, " %2.2x", MEM_RB(pInt, lina + i)); 173706f2543Smrg xf86ErrorFVerb(3, "\n"); 174706f2543Smrg} 175706f2543Smrg 176706f2543Smrgvoid 177706f2543Smrgdump_registers(xf86Int10InfoPtr pInt) 178706f2543Smrg{ 179706f2543Smrg xf86DrvMsgVerb(pInt->scrnIndex, X_INFO, 3, 180706f2543Smrg "EAX=0x%8.8lx, EBX=0x%8.8lx, ECX=0x%8.8lx, EDX=0x%8.8lx\n", 181706f2543Smrg (unsigned long)X86_EAX, (unsigned long)X86_EBX, 182706f2543Smrg (unsigned long)X86_ECX, (unsigned long)X86_EDX); 183706f2543Smrg xf86DrvMsgVerb(pInt->scrnIndex, X_INFO, 3, 184706f2543Smrg "ESP=0x%8.8lx, EBP=0x%8.8lx, ESI=0x%8.8lx, EDI=0x%8.8lx\n", 185706f2543Smrg (unsigned long)X86_ESP, (unsigned long)X86_EBP, 186706f2543Smrg (unsigned long)X86_ESI, (unsigned long)X86_EDI); 187706f2543Smrg xf86DrvMsgVerb(pInt->scrnIndex, X_INFO, 3, 188706f2543Smrg "CS=0x%4.4x, SS=0x%4.4x," 189706f2543Smrg " DS=0x%4.4x, ES=0x%4.4x, FS=0x%4.4x, GS=0x%4.4x\n", 190706f2543Smrg X86_CS, X86_SS, X86_DS, X86_ES, X86_FS, X86_GS); 191706f2543Smrg xf86DrvMsgVerb(pInt->scrnIndex, X_INFO, 3, 192706f2543Smrg "EIP=0x%8.8lx, EFLAGS=0x%8.8lx\n", 193706f2543Smrg (unsigned long)X86_EIP, (unsigned long)X86_EFLAGS); 194706f2543Smrg} 195706f2543Smrg 196706f2543Smrgvoid 197706f2543Smrgstack_trace(xf86Int10InfoPtr pInt) 198706f2543Smrg{ 199706f2543Smrg int i = 0; 200706f2543Smrg unsigned long stack = SEG_ADR((CARD32), X86_SS, SP); 201706f2543Smrg unsigned long tail = (CARD32)((X86_SS << 4) + 0x1000); 202706f2543Smrg 203706f2543Smrg if (stack >= tail) return; 204706f2543Smrg 205706f2543Smrg xf86MsgVerb(X_INFO, 3, "stack at 0x%8.8lx:\n", stack); 206706f2543Smrg for (; stack < tail; stack++) { 207706f2543Smrg xf86ErrorFVerb(3, " %2.2x", MEM_RB(pInt, stack)); 208706f2543Smrg i = (i + 1) % 0x10; 209706f2543Smrg if (!i) 210706f2543Smrg xf86ErrorFVerb(3, "\n"); 211706f2543Smrg } 212706f2543Smrg if (i) 213706f2543Smrg xf86ErrorFVerb(3, "\n"); 214706f2543Smrg} 215706f2543Smrg 216706f2543Smrgint 217706f2543Smrgport_rep_inb(xf86Int10InfoPtr pInt, 218706f2543Smrg CARD16 port, CARD32 base, int d_f, CARD32 count) 219706f2543Smrg{ 220706f2543Smrg register int inc = d_f ? -1 : 1; 221706f2543Smrg CARD32 dst = base; 222706f2543Smrg if (PRINT_PORT && DEBUG_IO_TRACE()) 223706f2543Smrg ErrorF(" rep_insb(%#x) %ld bytes at %8.8lx %s\n", 224706f2543Smrg port, count, base, d_f ? "up" : "down"); 225706f2543Smrg while (count--) { 226706f2543Smrg MEM_WB(pInt, dst, x_inb(port)); 227706f2543Smrg dst += inc; 228706f2543Smrg } 229706f2543Smrg return dst - base; 230706f2543Smrg} 231706f2543Smrg 232706f2543Smrgint 233706f2543Smrgport_rep_inw(xf86Int10InfoPtr pInt, 234706f2543Smrg CARD16 port, CARD32 base, int d_f, CARD32 count) 235706f2543Smrg{ 236706f2543Smrg register int inc = d_f ? -2 : 2; 237706f2543Smrg CARD32 dst = base; 238706f2543Smrg if (PRINT_PORT && DEBUG_IO_TRACE()) 239706f2543Smrg ErrorF(" rep_insw(%#x) %ld bytes at %8.8lx %s\n", 240706f2543Smrg port, count, base, d_f ? "up" : "down"); 241706f2543Smrg while (count--) { 242706f2543Smrg MEM_WW(pInt, dst, x_inw(port)); 243706f2543Smrg dst += inc; 244706f2543Smrg } 245706f2543Smrg return dst - base; 246706f2543Smrg} 247706f2543Smrg 248706f2543Smrgint 249706f2543Smrgport_rep_inl(xf86Int10InfoPtr pInt, 250706f2543Smrg CARD16 port, CARD32 base, int d_f, CARD32 count) 251706f2543Smrg{ 252706f2543Smrg register int inc = d_f ? -4 : 4; 253706f2543Smrg CARD32 dst = base; 254706f2543Smrg if (PRINT_PORT && DEBUG_IO_TRACE()) 255706f2543Smrg ErrorF(" rep_insl(%#x) %ld bytes at %8.8lx %s\n", 256706f2543Smrg port, count, base, d_f ? "up" : "down"); 257706f2543Smrg while (count--) { 258706f2543Smrg MEM_WL(pInt, dst, x_inl(port)); 259706f2543Smrg dst += inc; 260706f2543Smrg } 261706f2543Smrg return dst - base; 262706f2543Smrg} 263706f2543Smrg 264706f2543Smrgint 265706f2543Smrgport_rep_outb(xf86Int10InfoPtr pInt, 266706f2543Smrg CARD16 port, CARD32 base, int d_f, CARD32 count) 267706f2543Smrg{ 268706f2543Smrg register int inc = d_f ? -1 : 1; 269706f2543Smrg CARD32 dst = base; 270706f2543Smrg if (PRINT_PORT && DEBUG_IO_TRACE()) 271706f2543Smrg ErrorF(" rep_outb(%#x) %ld bytes at %8.8lx %s\n", 272706f2543Smrg port, count, base, d_f ? "up" : "down"); 273706f2543Smrg while (count--) { 274706f2543Smrg x_outb(port, MEM_RB(pInt, dst)); 275706f2543Smrg dst += inc; 276706f2543Smrg } 277706f2543Smrg return dst - base; 278706f2543Smrg} 279706f2543Smrg 280706f2543Smrgint 281706f2543Smrgport_rep_outw(xf86Int10InfoPtr pInt, 282706f2543Smrg CARD16 port, CARD32 base, int d_f, CARD32 count) 283706f2543Smrg{ 284706f2543Smrg register int inc = d_f ? -2 : 2; 285706f2543Smrg CARD32 dst = base; 286706f2543Smrg if (PRINT_PORT && DEBUG_IO_TRACE()) 287706f2543Smrg ErrorF(" rep_outw(%#x) %ld bytes at %8.8lx %s\n", 288706f2543Smrg port, count, base, d_f ? "up" : "down"); 289706f2543Smrg while (count--) { 290706f2543Smrg x_outw(port, MEM_RW(pInt, dst)); 291706f2543Smrg dst += inc; 292706f2543Smrg } 293706f2543Smrg return dst - base; 294706f2543Smrg} 295706f2543Smrg 296706f2543Smrgint 297706f2543Smrgport_rep_outl(xf86Int10InfoPtr pInt, 298706f2543Smrg CARD16 port, CARD32 base, int d_f, CARD32 count) 299706f2543Smrg{ 300706f2543Smrg register int inc = d_f ? -4 : 4; 301706f2543Smrg CARD32 dst = base; 302706f2543Smrg if (PRINT_PORT && DEBUG_IO_TRACE()) 303706f2543Smrg ErrorF(" rep_outl(%#x) %ld bytes at %8.8lx %s\n", 304706f2543Smrg port, count, base, d_f ? "up" : "down"); 305706f2543Smrg while (count--) { 306706f2543Smrg x_outl(port, MEM_RL(pInt, dst)); 307706f2543Smrg dst += inc; 308706f2543Smrg } 309706f2543Smrg return dst - base; 310706f2543Smrg} 311706f2543Smrg 312706f2543SmrgCARD8 313706f2543Smrgx_inb(CARD16 port) 314706f2543Smrg{ 315706f2543Smrg CARD8 val; 316706f2543Smrg 317706f2543Smrg if (port == 0x40) { 318706f2543Smrg Int10Current->inb40time++; 319706f2543Smrg val = (CARD8)(Int10Current->inb40time >> 320706f2543Smrg ((Int10Current->inb40time & 1) << 3)); 321706f2543Smrg if (PRINT_PORT && DEBUG_IO_TRACE()) 322706f2543Smrg ErrorF(" inb(%#x) = %2.2x\n", port, val); 323706f2543Smrg#ifdef __NOT_YET__ 324706f2543Smrg } else if (port < 0x0100) { /* Don't interfere with mainboard */ 325706f2543Smrg val = 0; 326706f2543Smrg xf86DrvMsgVerb(Int10Current->scrnIndex, X_NOT_IMPLEMENTED, 2, 327706f2543Smrg "inb 0x%4.4x\n", port); 328706f2543Smrg if (xf86GetVerbosity() > 3) { 329706f2543Smrg dump_registers(Int10Current); 330706f2543Smrg stack_trace(Int10Current); 331706f2543Smrg } 332706f2543Smrg#endif /* __NOT_YET__ */ 333706f2543Smrg } else if (!pciCfg1inb(port, &val)) { 334706f2543Smrg val = inb(Int10Current->ioBase + port); 335706f2543Smrg if (PRINT_PORT && DEBUG_IO_TRACE()) 336706f2543Smrg ErrorF(" inb(%#x) = %2.2x\n", port, val); 337706f2543Smrg } 338706f2543Smrg return val; 339706f2543Smrg} 340706f2543Smrg 341706f2543SmrgCARD16 342706f2543Smrgx_inw(CARD16 port) 343706f2543Smrg{ 344706f2543Smrg CARD16 val; 345706f2543Smrg 346706f2543Smrg if (port == 0x5c) { 347706f2543Smrg struct timeval tv; 348706f2543Smrg 349706f2543Smrg /* 350706f2543Smrg * Emulate a PC98's timer. Typical resolution is 3.26 usec. 351706f2543Smrg * Approximate this by dividing by 3. 352706f2543Smrg */ 353706f2543Smrg X_GETTIMEOFDAY(&tv); 354706f2543Smrg val = (CARD16)(tv.tv_usec / 3); 355706f2543Smrg } else if (!pciCfg1inw(port, &val)) { 356706f2543Smrg val = inw(Int10Current->ioBase + port); 357706f2543Smrg if (PRINT_PORT && DEBUG_IO_TRACE()) 358706f2543Smrg ErrorF(" inw(%#x) = %4.4x\n", port, val); 359706f2543Smrg } 360706f2543Smrg return val; 361706f2543Smrg} 362706f2543Smrg 363706f2543Smrgvoid 364706f2543Smrgx_outb(CARD16 port, CARD8 val) 365706f2543Smrg{ 366706f2543Smrg if ((port == 0x43) && (val == 0)) { 367706f2543Smrg struct timeval tv; 368706f2543Smrg /* 369706f2543Smrg * Emulate a PC's timer 0. Such timers typically have a resolution of 370706f2543Smrg * some .838 usec per tick, but this can only provide 1 usec per tick. 371706f2543Smrg * (Not that this matters much, given inherent emulation delays.) Use 372706f2543Smrg * the bottom bit as a byte select. See inb(0x40) above. 373706f2543Smrg */ 374706f2543Smrg X_GETTIMEOFDAY(&tv); 375706f2543Smrg Int10Current->inb40time = (CARD16)(tv.tv_usec | 1); 376706f2543Smrg if (PRINT_PORT && DEBUG_IO_TRACE()) 377706f2543Smrg ErrorF(" outb(%#x, %2.2x)\n", port, val); 378706f2543Smrg#ifdef __NOT_YET__ 379706f2543Smrg } else if (port < 0x0100) { /* Don't interfere with mainboard */ 380706f2543Smrg xf86DrvMsgVerb(Int10Current->scrnIndex, X_NOT_IMPLEMENTED, 2, 381706f2543Smrg "outb 0x%4.4x,0x%2.2x\n", port, val); 382706f2543Smrg if (xf86GetVerbosity() > 3) { 383706f2543Smrg dump_registers(Int10Current); 384706f2543Smrg stack_trace(Int10Current); 385706f2543Smrg } 386706f2543Smrg#endif /* __NOT_YET__ */ 387706f2543Smrg } else if (!pciCfg1outb(port, val)) { 388706f2543Smrg if (PRINT_PORT && DEBUG_IO_TRACE()) 389706f2543Smrg ErrorF(" outb(%#x, %2.2x)\n", port, val); 390706f2543Smrg outb(Int10Current->ioBase + port, val); 391706f2543Smrg } 392706f2543Smrg} 393706f2543Smrg 394706f2543Smrgvoid 395706f2543Smrgx_outw(CARD16 port, CARD16 val) 396706f2543Smrg{ 397706f2543Smrg 398706f2543Smrg if (!pciCfg1outw(port, val)) { 399706f2543Smrg if (PRINT_PORT && DEBUG_IO_TRACE()) 400706f2543Smrg ErrorF(" outw(%#x, %4.4x)\n", port, val); 401706f2543Smrg outw(Int10Current->ioBase + port, val); 402706f2543Smrg } 403706f2543Smrg} 404706f2543Smrg 405706f2543SmrgCARD32 406706f2543Smrgx_inl(CARD16 port) 407706f2543Smrg{ 408706f2543Smrg CARD32 val; 409706f2543Smrg 410706f2543Smrg if (!pciCfg1in(port, &val)) { 411706f2543Smrg val = inl(Int10Current->ioBase + port); 412706f2543Smrg if (PRINT_PORT && DEBUG_IO_TRACE()) 413706f2543Smrg ErrorF(" inl(%#x) = %8.8lx\n", port, val); 414706f2543Smrg } 415706f2543Smrg return val; 416706f2543Smrg} 417706f2543Smrg 418706f2543Smrgvoid 419706f2543Smrgx_outl(CARD16 port, CARD32 val) 420706f2543Smrg{ 421706f2543Smrg if (!pciCfg1out(port, val)) { 422706f2543Smrg if (PRINT_PORT && DEBUG_IO_TRACE()) 423706f2543Smrg ErrorF(" outl(%#x, %8.8lx)\n", port, val); 424706f2543Smrg outl(Int10Current->ioBase + port, val); 425706f2543Smrg } 426706f2543Smrg} 427706f2543Smrg 428706f2543SmrgCARD8 429706f2543SmrgMem_rb(CARD32 addr) 430706f2543Smrg{ 431706f2543Smrg return (*Int10Current->mem->rb)(Int10Current, addr); 432706f2543Smrg} 433706f2543Smrg 434706f2543SmrgCARD16 435706f2543SmrgMem_rw(CARD32 addr) 436706f2543Smrg{ 437706f2543Smrg return (*Int10Current->mem->rw)(Int10Current, addr); 438706f2543Smrg} 439706f2543Smrg 440706f2543SmrgCARD32 441706f2543SmrgMem_rl(CARD32 addr) 442706f2543Smrg{ 443706f2543Smrg return (*Int10Current->mem->rl)(Int10Current, addr); 444706f2543Smrg} 445706f2543Smrg 446706f2543Smrgvoid 447706f2543SmrgMem_wb(CARD32 addr, CARD8 val) 448706f2543Smrg{ 449706f2543Smrg (*Int10Current->mem->wb)(Int10Current, addr, val); 450706f2543Smrg} 451706f2543Smrg 452706f2543Smrgvoid 453706f2543SmrgMem_ww(CARD32 addr, CARD16 val) 454706f2543Smrg{ 455706f2543Smrg (*Int10Current->mem->ww)(Int10Current, addr, val); 456706f2543Smrg} 457706f2543Smrg 458706f2543Smrgvoid 459706f2543SmrgMem_wl(CARD32 addr, CARD32 val) 460706f2543Smrg{ 461706f2543Smrg (*Int10Current->mem->wl)(Int10Current, addr, val); 462706f2543Smrg} 463706f2543Smrg 464706f2543Smrgstatic CARD32 PciCfg1Addr = 0; 465706f2543Smrg 466706f2543Smrg#define PCI_DOM_FROM_TAG(tag) (((tag) >> 24) & (PCI_DOM_MASK)) 467706f2543Smrg#define PCI_BUS_FROM_TAG(tag) (((tag) >> 16) & (PCI_DOMBUS_MASK)) 468706f2543Smrg#define PCI_DEV_FROM_TAG(tag) (((tag) & 0x0000f800u) >> 11) 469706f2543Smrg#define PCI_FUNC_FROM_TAG(tag) (((tag) & 0x00000700u) >> 8) 470706f2543Smrg 471706f2543Smrg#define PCI_OFFSET(x) ((x) & 0x000000ff) 472706f2543Smrg#define PCI_TAG(x) ((x) & 0x7fffff00) 473706f2543Smrg 474706f2543Smrgstatic struct pci_device* 475706f2543Smrgpci_device_for_cfg_address (CARD32 addr) 476706f2543Smrg{ 477706f2543Smrg struct pci_device *dev = NULL; 478706f2543Smrg PCITAG tag = PCI_TAG(addr); 479706f2543Smrg struct pci_slot_match slot_match = { 480706f2543Smrg .domain = PCI_DOM_FROM_TAG(tag), 481706f2543Smrg .bus = PCI_BUS_NO_DOMAIN(PCI_BUS_FROM_TAG(tag)), 482706f2543Smrg .dev = PCI_DEV_FROM_TAG(tag), 483706f2543Smrg .func = PCI_FUNC_FROM_TAG(tag), 484706f2543Smrg .match_data = 0 485706f2543Smrg }; 486706f2543Smrg 487706f2543Smrg struct pci_device_iterator *iter = 488706f2543Smrg pci_slot_match_iterator_create (&slot_match); 489706f2543Smrg 490706f2543Smrg if (iter) 491706f2543Smrg dev = pci_device_next(iter); 492706f2543Smrg 493706f2543Smrg pci_iterator_destroy(iter); 494706f2543Smrg 495706f2543Smrg return dev; 496706f2543Smrg} 497706f2543Smrg 498706f2543Smrgstatic int 499706f2543SmrgpciCfg1in(CARD16 addr, CARD32 *val) 500706f2543Smrg{ 501706f2543Smrg if (addr == 0xCF8) { 502706f2543Smrg *val = PciCfg1Addr; 503706f2543Smrg return 1; 504706f2543Smrg } 505706f2543Smrg if (addr == 0xCFC) { 506706f2543Smrg pci_device_cfg_read_u32(pci_device_for_cfg_address(PciCfg1Addr), 507706f2543Smrg /* 508706f2543Smrg * XXXMRG 509706f2543Smrg * this one is OK - CARD32 is "long" for 32 bit 510706f2543Smrg * and "int" for 64 bit 511706f2543Smrg */ 512706f2543Smrg (uint32_t *)val, PCI_OFFSET(PciCfg1Addr)); 513706f2543Smrg if (PRINT_PORT && DEBUG_IO_TRACE()) 514706f2543Smrg ErrorF(" cfg_inl(%#lx) = %8.8lx\n", PciCfg1Addr, *val); 515706f2543Smrg return 1; 516706f2543Smrg } 517706f2543Smrg return 0; 518706f2543Smrg} 519706f2543Smrg 520706f2543Smrgstatic int 521706f2543SmrgpciCfg1out(CARD16 addr, CARD32 val) 522706f2543Smrg{ 523706f2543Smrg if (addr == 0xCF8) { 524706f2543Smrg PciCfg1Addr = val; 525706f2543Smrg return 1; 526706f2543Smrg } 527706f2543Smrg if (addr == 0xCFC) { 528706f2543Smrg if (PRINT_PORT && DEBUG_IO_TRACE()) 529706f2543Smrg ErrorF(" cfg_outl(%#lx, %8.8lx)\n", PciCfg1Addr, val); 530706f2543Smrg pci_device_cfg_write_u32(pci_device_for_cfg_address(PciCfg1Addr), 531706f2543Smrg val, PCI_OFFSET(PciCfg1Addr)); 532706f2543Smrg return 1; 533706f2543Smrg } 534706f2543Smrg return 0; 535706f2543Smrg} 536706f2543Smrg 537706f2543Smrgstatic int 538706f2543SmrgpciCfg1inw(CARD16 addr, CARD16 *val) 539706f2543Smrg{ 540706f2543Smrg int shift; 541706f2543Smrg 542706f2543Smrg if ((addr >= 0xCF8) && (addr <= 0xCFB)) { 543706f2543Smrg shift = (addr - 0xCF8) * 8; 544706f2543Smrg *val = (PciCfg1Addr >> shift) & 0xffff; 545706f2543Smrg return 1; 546706f2543Smrg } 547706f2543Smrg if ((addr >= 0xCFC) && (addr <= 0xCFF)) { 548706f2543Smrg const unsigned offset = addr - 0xCFC; 549706f2543Smrg 550706f2543Smrg pci_device_cfg_read_u16(pci_device_for_cfg_address(PciCfg1Addr), 551706f2543Smrg val, PCI_OFFSET(PciCfg1Addr) + offset); 552706f2543Smrg if (PRINT_PORT && DEBUG_IO_TRACE()) 553706f2543Smrg ErrorF(" cfg_inw(%#lx) = %4.4x\n", PciCfg1Addr + offset, *val); 554706f2543Smrg return 1; 555706f2543Smrg } 556706f2543Smrg return 0; 557706f2543Smrg} 558706f2543Smrg 559706f2543Smrgstatic int 560706f2543SmrgpciCfg1outw(CARD16 addr, CARD16 val) 561706f2543Smrg{ 562706f2543Smrg int shift; 563706f2543Smrg 564706f2543Smrg if ((addr >= 0xCF8) && (addr <= 0xCFB)) { 565706f2543Smrg shift = (addr - 0xCF8) * 8; 566706f2543Smrg PciCfg1Addr &= ~(0xffff << shift); 567706f2543Smrg PciCfg1Addr |= ((CARD32) val) << shift; 568706f2543Smrg return 1; 569706f2543Smrg } 570706f2543Smrg if ((addr >= 0xCFC) && (addr <= 0xCFF)) { 571706f2543Smrg const unsigned offset = addr - 0xCFC; 572706f2543Smrg 573706f2543Smrg if (PRINT_PORT && DEBUG_IO_TRACE()) 574706f2543Smrg ErrorF(" cfg_outw(%#lx, %4.4x)\n", PciCfg1Addr + offset, val); 575706f2543Smrg pci_device_cfg_write_u16(pci_device_for_cfg_address(PciCfg1Addr), 576706f2543Smrg val, PCI_OFFSET(PciCfg1Addr) + offset); 577706f2543Smrg return 1; 578706f2543Smrg } 579706f2543Smrg return 0; 580706f2543Smrg} 581706f2543Smrg 582706f2543Smrgstatic int 583706f2543SmrgpciCfg1inb(CARD16 addr, CARD8 *val) 584706f2543Smrg{ 585706f2543Smrg int shift; 586706f2543Smrg 587706f2543Smrg if ((addr >= 0xCF8) && (addr <= 0xCFB)) { 588706f2543Smrg shift = (addr - 0xCF8) * 8; 589706f2543Smrg *val = (PciCfg1Addr >> shift) & 0xff; 590706f2543Smrg return 1; 591706f2543Smrg } 592706f2543Smrg if ((addr >= 0xCFC) && (addr <= 0xCFF)) { 593706f2543Smrg const unsigned offset = addr - 0xCFC; 594706f2543Smrg 595706f2543Smrg pci_device_cfg_read_u8(pci_device_for_cfg_address(PciCfg1Addr), 596706f2543Smrg val, PCI_OFFSET(PciCfg1Addr) + offset); 597706f2543Smrg if (PRINT_PORT && DEBUG_IO_TRACE()) 598706f2543Smrg ErrorF(" cfg_inb(%#lx) = %2.2x\n", PciCfg1Addr + offset, *val); 599706f2543Smrg return 1; 600706f2543Smrg } 601706f2543Smrg return 0; 602706f2543Smrg} 603706f2543Smrg 604706f2543Smrgstatic int 605706f2543SmrgpciCfg1outb(CARD16 addr, CARD8 val) 606706f2543Smrg{ 607706f2543Smrg int shift; 608706f2543Smrg 609706f2543Smrg if ((addr >= 0xCF8) && (addr <= 0xCFB)) { 610706f2543Smrg shift = (addr - 0xCF8) * 8; 611706f2543Smrg PciCfg1Addr &= ~(0xff << shift); 612706f2543Smrg PciCfg1Addr |= ((CARD32) val) << shift; 613706f2543Smrg return 1; 614706f2543Smrg } 615706f2543Smrg if ((addr >= 0xCFC) && (addr <= 0xCFF)) { 616706f2543Smrg const unsigned offset = addr - 0xCFC; 617706f2543Smrg 618706f2543Smrg if (PRINT_PORT && DEBUG_IO_TRACE()) 619706f2543Smrg ErrorF(" cfg_outb(%#lx, %2.2x)\n", PciCfg1Addr + offset, val); 620706f2543Smrg pci_device_cfg_write_u8(pci_device_for_cfg_address(PciCfg1Addr), 621706f2543Smrg val, PCI_OFFSET(PciCfg1Addr) + offset); 622706f2543Smrg return 1; 623706f2543Smrg } 624706f2543Smrg return 0; 625706f2543Smrg} 626706f2543Smrg 627706f2543SmrgCARD8 628706f2543Smrgbios_checksum(const CARD8 *start, int size) 629706f2543Smrg{ 630706f2543Smrg CARD8 sum = 0; 631706f2543Smrg 632706f2543Smrg while (size-- > 0) 633706f2543Smrg sum += *start++; 634706f2543Smrg return sum; 635706f2543Smrg} 636706f2543Smrg 637706f2543Smrg/* 638706f2543Smrg * Lock/Unlock legacy VGA. Some Bioses try to be very clever and make 639706f2543Smrg * an attempt to detect a legacy ISA card. If they find one they might 640706f2543Smrg * act very strange: for example they might configure the card as a 641706f2543Smrg * monochrome card. This might cause some drivers to choke. 642706f2543Smrg * To avoid this we attempt legacy VGA by writing to all know VGA 643706f2543Smrg * disable registers before we call the BIOS initialization and 644706f2543Smrg * restore the original values afterwards. In beween we hold our 645706f2543Smrg * breath. To get to a (possibly exising) ISA card need to disable 646706f2543Smrg * our current PCI card. 647706f2543Smrg */ 648706f2543Smrg/* 649706f2543Smrg * This is just for booting: we just want to catch pure 650706f2543Smrg * legacy vga therefore we don't worry about mmio etc. 651706f2543Smrg * This stuff should really go into vgaHW.c. However then 652706f2543Smrg * the driver would have to load the vga-module prior to 653706f2543Smrg * doing int10. 654706f2543Smrg */ 655706f2543Smrgvoid 656706f2543SmrgLockLegacyVGA(xf86Int10InfoPtr pInt, legacyVGAPtr vga) 657706f2543Smrg{ 658706f2543Smrg#ifndef NO_LEGACY_VGA 659706f2543Smrg vga->save_msr = inb(pInt->ioBase + 0x03CC); 660706f2543Smrg vga->save_vse = inb(pInt->ioBase + 0x03C3); 661706f2543Smrg#ifndef __ia64__ 662706f2543Smrg vga->save_46e8 = inb(pInt->ioBase + 0x46E8); 663706f2543Smrg#endif 664706f2543Smrg vga->save_pos102 = inb(pInt->ioBase + 0x0102); 665706f2543Smrg outb(pInt->ioBase + 0x03C2, ~(CARD8)0x03 & vga->save_msr); 666706f2543Smrg outb(pInt->ioBase + 0x03C3, ~(CARD8)0x01 & vga->save_vse); 667706f2543Smrg#ifndef __ia64__ 668706f2543Smrg outb(pInt->ioBase + 0x46E8, ~(CARD8)0x08 & vga->save_46e8); 669706f2543Smrg#endif 670706f2543Smrg outb(pInt->ioBase + 0x0102, ~(CARD8)0x01 & vga->save_pos102); 671706f2543Smrg#endif 672706f2543Smrg} 673706f2543Smrg 674706f2543Smrgvoid 675706f2543SmrgUnlockLegacyVGA(xf86Int10InfoPtr pInt, legacyVGAPtr vga) 676706f2543Smrg{ 677706f2543Smrg#ifndef NO_LEGACY_VGA 678706f2543Smrg outb(pInt->ioBase + 0x0102, vga->save_pos102); 679706f2543Smrg#ifndef __ia64__ 680706f2543Smrg outb(pInt->ioBase + 0x46E8, vga->save_46e8); 681706f2543Smrg#endif 682706f2543Smrg outb(pInt->ioBase + 0x03C3, vga->save_vse); 683706f2543Smrg outb(pInt->ioBase + 0x03C2, vga->save_msr); 684706f2543Smrg#endif 685706f2543Smrg} 686706f2543Smrg 687706f2543Smrg#if defined (_PC) 688706f2543Smrgstatic void 689706f2543SmrgSetResetBIOSVars(xf86Int10InfoPtr pInt, Bool set) 690706f2543Smrg{ 691706f2543Smrg int pagesize = getpagesize(); 692706f2543Smrg unsigned char* base = xf86MapVidMem(pInt->scrnIndex, 693706f2543Smrg VIDMEM_MMIO, 0, pagesize); 694706f2543Smrg int i; 695706f2543Smrg 696706f2543Smrg if (set) { 697706f2543Smrg for (i = BIOS_SCRATCH_OFF; i < BIOS_SCRATCH_END; i++) 698706f2543Smrg MEM_WW(pInt, i, *(base + i)); 699706f2543Smrg } else { 700706f2543Smrg for (i = BIOS_SCRATCH_OFF; i < BIOS_SCRATCH_END; i++) 701706f2543Smrg *(base + i) = MEM_RW(pInt, i); 702706f2543Smrg } 703706f2543Smrg 704706f2543Smrg xf86UnMapVidMem(pInt->scrnIndex,base,pagesize); 705706f2543Smrg} 706706f2543Smrg 707706f2543Smrgvoid 708706f2543Smrgxf86Int10SaveRestoreBIOSVars(xf86Int10InfoPtr pInt, Bool save) 709706f2543Smrg{ 710706f2543Smrg int pagesize = getpagesize(); 711706f2543Smrg unsigned char* base; 712706f2543Smrg int i; 713706f2543Smrg 714706f2543Smrg if (!xf86IsEntityPrimary(pInt->entityIndex) 715706f2543Smrg || (!save && !pInt->BIOSScratch)) 716706f2543Smrg return; 717706f2543Smrg 718706f2543Smrg base = xf86MapVidMem(pInt->scrnIndex, VIDMEM_MMIO, 0, pagesize); 719706f2543Smrg base += BIOS_SCRATCH_OFF; 720706f2543Smrg if (save) { 721706f2543Smrg if ((pInt->BIOSScratch 722706f2543Smrg = xnfalloc(BIOS_SCRATCH_LEN))) 723706f2543Smrg for (i = 0; i < BIOS_SCRATCH_LEN; i++) 724706f2543Smrg *(((char*)pInt->BIOSScratch + i)) = *(base + i); 725706f2543Smrg } else { 726706f2543Smrg if (pInt->BIOSScratch) { 727706f2543Smrg for (i = 0; i < BIOS_SCRATCH_LEN; i++) 728706f2543Smrg *(base + i) = *(pInt->BIOSScratch + i); 729706f2543Smrg free(pInt->BIOSScratch); 730706f2543Smrg pInt->BIOSScratch = NULL; 731706f2543Smrg } 732706f2543Smrg } 733706f2543Smrg 734706f2543Smrg xf86UnMapVidMem(pInt->scrnIndex,base - BIOS_SCRATCH_OFF ,pagesize); 735706f2543Smrg} 736706f2543Smrg#endif 737706f2543Smrg 738706f2543Smrgxf86Int10InfoPtr 739706f2543Smrgxf86InitInt10(int entityIndex) 740706f2543Smrg{ 741706f2543Smrg return xf86ExtendedInitInt10(entityIndex, 0); 742706f2543Smrg} 743