/* $XFree86: xc/programs/Xserver/hw/xfree86/int10/generic.c,v 1.21 2001/05/15 10:19:41 eich Exp $ */ /* * XFree86 int10 module * execute BIOS int 10h calls in x86 real mode environment * Copyright 1999 Egbert Eich */ #define _INT10_PRIVATE #include #include #include #include "xf86int10.h" #include "xf86x86emu.h" #include "linux/io.h" #include "mod_framebuffer.h" #include "vesa.h" #define vgaram_base (VGA_BASE + 0xa0000) #define ALLOC_ENTRIES(x) ((V_RAM / x) - 1) static CARD8 read_b(xf86Int10InfoPtr pInt, int addr); static CARD16 read_w(xf86Int10InfoPtr pInt, int addr); static CARD32 read_l(xf86Int10InfoPtr pInt, int addr); static void write_b(xf86Int10InfoPtr pInt, int addr, CARD8 val); static void write_w(xf86Int10InfoPtr pInt, int addr, CARD16 val); static void write_l(xf86Int10InfoPtr pInt, int addr, CARD32 val); /* * the emulator cannot pass a pointer to the current xf86Int10InfoRec * to the memory access functions therefore store it here. */ typedef struct { int shift; int entries; void *base; void *vRam; void *sysMem; char *alloc; } genericInt10Priv; #define INTPriv(x) ((genericInt10Priv*)x->private) int10MemRec genericMem = { read_b, read_w, read_l, write_b, write_w, write_l }; static void *sysMem = NULL; #define CRT_C 24 /* 24 CRT Controller Registers */ #define ATT_C 21 /* 21 Attribute Controller Registers */ #define GRA_C 9 /* 9 Graphics Controller Registers */ #define SEQ_C 5 /* 5 Sequencer Registers */ #define MIS_C 1 /* 1 Misc Output Register */ /* VGA registers saving indexes */ #define CRT 0 /* CRT Controller Registers start */ #define ATT (CRT+CRT_C) /* Attribute Controller Registers start */ #define GRA (ATT+ATT_C) /* Graphics Controller Registers start */ #define SEQ (GRA+GRA_C) /* Sequencer Registers */ #define MIS (SEQ+SEQ_C) /* General Registers */ #define EXT (MIS+MIS_C) /* SVGA Extended Registers */ static void vgadelay(void) { int i; for (i = 0; i < 10; i++) ; } static unsigned char regs[60] = { 0x5F, 0x4F, 0x50, 0x02, 0x55, 0x81, 0xBF, 0x1F, /* CR00-CR18 */ 0x00, 0x4F, 0x0D, 0x0E, 0x0, 0x0, 0x0, 0x0, 0x9C, 0x00, 0x8F, 0x28, 0x1F, 0x96, 0xB9, 0xA3, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* AR00-AR15 */ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x0C, 0x00, 0x0F, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0E, 0x00, /* GR00-GR05 */ 0xFF, 0x03, 0x00, 0x03, 0x00, 0x02, /* SR00-SR05 */ 0x67, /* MISC_OUT */ }; static void outseq(int index, unsigned char val) { linux_outb(index, 0x3c4); linux_outb(val, 0x3c5); } static unsigned char inseq(unsigned char index) { linux_outb(index, 0x3c4); return linux_inb(0x3c5); } static void outcrtc(int index, unsigned char val) { linux_outb(index, 0x3d4); linux_outb(val, 0x3d5); } static unsigned char incrtc(int index) { linux_outb(index, 0x3d4); return linux_inb(0x3d5); } static void outgra(int index, unsigned char val) { linux_outb(index, 0x3ce); linux_outb(val, 0x3cf); } static unsigned char ingra(int index) { linux_outb(index, 0x3ce); return linux_inb(0x3cf); } static void outatt(int index, unsigned char val) { linux_inb(0x3da); vgadelay(); linux_outb(index, 0x3c0); vgadelay(); linux_outb(val, 0x3c0); vgadelay(); } static unsigned char inatt(int index) { linux_inb(0x3da); vgadelay(); linux_outb(index, 0x3c0); vgadelay(); return linux_inb(0x3c1); } static void setregs(const unsigned char *regs) { int i; unsigned char val; // misc linux_outb(regs[MIS], 0x3c2); // seq outseq(0x0, 0x1); outseq(0x01, regs[SEQ + 1] | 0x20); outseq(0x01, regs[SEQ + 1] | 0x20); for (i = 2; i < SEQ_C; i++) { outseq(i, regs[SEQ + i]); } outseq(0x0, 0x3); // crtc // write enable val = incrtc(0x11); val &= 0x7F; outcrtc(0x11, val); // crtc setting for (i = 0; i < CRT_C; i++) { outcrtc(i, regs[CRT + i]); } // gra for (i = 0; i < GRA_C; i++) { outgra(i, regs[GRA + i]); } // att for (i = 0; i < ATT_C; i++) { outatt(i, regs[ATT + i]); } outseq(0x01, regs[SEQ + 1] & 0xDF); linux_inb(0x3da); vgadelay(); linux_outb(0x20, 0x3c0); // misc readback vgadelay(); linux_outb(0x67, 0x3c2); } extern struct pci_device *vga_dev; extern int vga_available; extern int novga; extern int vesa_mode; extern struct vesamode *vesa_mode_head; int vga_bios_init(void) { xf86Int10InfoPtr pInt; int screen; void *base = 0; void *vbiosMem = 0; legacyVGARec vga; pInt = (xf86Int10InfoPtr) malloc(sizeof(xf86Int10InfoRec)); //pInt = (xf86Int10InfoPtr) calloc(1,sizeof(xf86Int10InfoRec)); memset(pInt, 0, sizeof(xf86Int10InfoRec)); if (!xf86Int10ExecSetup(pInt)) goto error0; pInt->mem = &genericMem; pInt->private = (pointer) malloc(sizeof(genericInt10Priv)); //pInt->private = (pointer) calloc(1,sizeof(genericInt10Priv)); memset(pInt->private, 0, sizeof(genericInt10Priv)); pInt->scrnIndex = 0; /* screen */ base = INTPriv(pInt)->base = malloc(0x100000); //base = INTPriv(pInt)->base = 0x80000000+memorysize-0x100000; //#if 0 #if defined(RS690) || defined(RS780E) { pcitag_t vga_bridge = _pci_make_tag(0, 1, 0); unsigned int val; /* enable VGA legacy space decode */ val = _pci_conf_read(vga_bridge, 0x3c); val |= 1 << 19; _pci_conf_write(vga_bridge, 0x3c, val); /* reallocate the prefetchable address */ #if 0 //_pci_conf_write(vga_bridge, 0x20, 0x16101600); //_pci_conf_write(vga_bridge, 0x24, 0x15f01400); printf("\n\nvga_bridge, 0x20=%x,0x24=%x\n\n\n", _pci_conf_read(vga_bridge, 0x20),_pci_conf_read(vga_bridge, 0x24)); _pci_conf_write(vga_bridge, 0x20, 0x12101200); _pci_conf_write(vga_bridge, 0x24, 0x11f01000); #else /* using the old one */ #endif } #endif /* * we need to map video RAM MMIO as some chipsets map mmio * registers into this range. */ INTPriv(pInt)->vRam = (void *)vgaram_base; if (!sysMem) { sysMem = malloc(BIOS_SIZE); setup_system_bios(sysMem); } INTPriv(pInt)->sysMem = sysMem; printf("memorysize=%x,base=%lx,sysMem=%lx,vram=%lx\n", memorysize, INTPriv(pInt)->base, sysMem, INTPriv(pInt)->vRam); setup_int_vect(pInt); set_return_trap(pInt); vbiosMem = (char *)base + V_BIOS; (void)memset(vbiosMem, 0, 2 * V_BIOS_SIZE); { struct pci_device *pdev; unsigned long romsize = 0; unsigned long romaddress = 0; unsigned char magic[2]; unsigned short ppcidata; /* pointer to pci data structure */ unsigned char pcisig[4]; /* signature of pci data structure */ unsigned char codetype; if (vga_dev != NULL) { pdev = vga_dev; printk ("Found VGA device: vendor=0x%04x, device=0x%04x\n", PCI_VENDOR(pdev->pa.pa_id), PCI_PRODUCT(pdev->pa.pa_id)); } else return -1; if (PCI_VENDOR(pdev->pa.pa_id) == 0x102b) { printk("skipping matrox cards\n"); return -1; } if (PCI_VENDOR(pdev->pa.pa_id) == 0x1002 && PCI_PRODUCT(pdev->pa.pa_id) == 0x4750) MEM_WW(pInt, 0xc015e, 0x4750); romaddress = _pci_conf_read(pdev->pa.pa_tag, 0x30); romaddress &= (~1); /* enable rom address decode */ _pci_conf_write(pdev->pa.pa_tag, 0x30, romaddress | 1); #if defined(RADEON7000) || defined(RS690) || defined(VESAFB) || defined(RS780E) { extern unsigned char vgarom[]; unsigned char *tmp; romaddress = (unsigned long)vgarom; tmp = (unsigned char *)vgarom; // printk("Here after vgarom romaddress:%x\n",tmp[4]); printk("vgarom romaddress:0x%x\n",romaddress); } #endif if (romaddress == 0) { printk("No rom address assigned,skipped\n"); return -1; } #if defined(BONITOEL) && !( defined(RADEON7000) || defined(VESAFB) || defined(RS690) || defined(RS780E)) romaddress |= 0x10000000; #endif printk("Rom base addr: %lx\n", romaddress); #ifdef LS3_HT magic[0] = *(unsigned char *)(romaddress); magic[1] = *(unsigned char *)(romaddress + 1); #else magic[0] = readb(romaddress); magic[1] = readb(romaddress + 1); #endif if (magic[0] == 0x55 && magic[1] == 0xaa) { printk("VGA bios found\n"); /* rom size is stored at offset 2,in 512 byte unit */ #ifdef LS3_HT romsize = (*(unsigned char *)(romaddress + 2)) * 512; #else romsize = (readb(romaddress + 2)) * 512; #endif printk("rom size is %ldk\n", romsize / 1024); #ifdef LS3_HT ppcidata = *(unsigned int *)(romaddress + 0x18); printk("PCI data structure at offset %x\n", ppcidata); pcisig[0] = *(unsigned char *)(romaddress + ppcidata); pcisig[1] = *(unsigned char *)(romaddress + ppcidata + 1); pcisig[2] = *(unsigned char *)(romaddress + ppcidata + 2); pcisig[3] = *(unsigned char *)(romaddress + ppcidata + 3); #else ppcidata = readw(romaddress + 0x18); printk("PCI data structure at offset %x\n", ppcidata); pcisig[0] = readb(romaddress + ppcidata); pcisig[1] = readb(romaddress + ppcidata + 1); pcisig[2] = readb(romaddress + ppcidata + 2); pcisig[3] = readb(romaddress + ppcidata + 3); #endif if (pcisig[0] != 'P' || pcisig[1] != 'C' || pcisig[2] != 'I' || pcisig[3] != 'R') { printk("PCIR expected,read %c%c%c%c\n", pcisig[0], pcisig[1], pcisig[2], pcisig[3]); printk("Invalid pci signature found,give up\n"); return -1; } #ifdef LS3_HT codetype = *(unsigned char *)(romaddress + ppcidata + 0x14); #else codetype = readb(romaddress + ppcidata + 0x14); #endif if (codetype != 0) { printk("Not x86 code in rom,give up\n"); return -1; } #if defined(RS690) || defined(RS780E) // fixup PCI ID //*((volatile unsigned int *)(0xa0000000 | (romaddress + ppcidata + 4))) = _pci_conf_read(pdev->pa.pa_tag, 0x00); *((volatile unsigned int *)((romaddress + ppcidata + 4))) = _pci_conf_read(pdev->pa.pa_tag, 0x00); #endif } else { printk("No valid bios found,magic=%x%x\n", magic[0], magic[1]); return -1; } pInt->pdev = pdev; memcpy(vbiosMem, (char *)(0x00000000 | romaddress), V_BIOS_SIZE); #if defined(RS780E) memcpy(0xc3f00000 , (char *)(0x00000000 | romaddress) , V_BIOS_SIZE); //memcpy(0xdff00000 , (char *)(0x00000000 | romaddress) , V_BIOS_SIZE); //memcpy(0xc7f00000 , (char *)(0x00000000 | romaddress) , V_BIOS_SIZE); #endif if (PCI_VENDOR(pdev->pa.pa_id) == 0x1002 && PCI_PRODUCT(pdev->pa.pa_id) == 0x4750) MEM_WW(pInt, 0xc015e, 0x4750); #if defined(RS780E) //for test MEM_WW(pInt , 0xcac90 , 0x1 | MEM_RW(pInt , 0xcac90)); #endif } #if 0 setregs(regs); #else pInt->BIOSseg = V_BIOS >> 4; pInt->num = 0xe6; printf("lock vga\n"); //LockLegacyVGA(screen, &vga); printf("starting bios emu...\n"); M.x86.debug |= /*DEBUG_STEP_F | DEBUG_DECODE_F | DEBUG_TRACE_F | DEBUG_MEM_TRACE_F */ DEBUG_IO_TRACE_F | DEBUG_DECODE_F; //X86EMU_trace_on(); // printf("end of trace ......................................\n"); printf("ax=%lx,bx=%lx,cx=%lx,dx=%lx\n", pInt->ax, pInt->bx, pInt->cx, pInt->dx); xf86ExecX86int10(pInt); printf("just before emu done ax(0x%x)\n", pInt->ax); printf("bios emu done\n"); #if 0 pInt->num = 0x10; pInt->ax = 0x03; xf86ExecX86int10(pInt); #endif //UnlockLegacyVGA(screen, &vga); setregs(regs); //linux_outb(0x67, 0x3c2); #if NMOD_FRAMEBUFFER == 0 printf("setting text mode...\n"); //X86EMU_trace_on(); pInt->BIOSseg = V_BIOS >> 4; pInt->num = 0x10; pInt->ax = 0x0003; xf86ExecX86int10(pInt); #else //printf("setting fb mode...\n"); pInt->BIOSseg = V_BIOS >> 4; pInt->num = 0x10; { char *mode; mode = getenv("vesa_mode"); if (mode != 0) vesa_mode = strtol(mode, 0, 0); else vesa_mode = 0x00; } for(vesa_mode = 0; vesa_mode <= 24; vesa_mode++){ printk("\n\nvesa_mode : 0x%x\n", vesa_mode); pInt->ax = 0x4f02; // pInt->bx = 0x4114; pInt->bx = (USE_LINEAR_FRAMEBUFFER | vesa_mode_head[vesa_mode].mode); printk("ax %x bx %x\n", pInt->ax, pInt->bx); xf86ExecX86int10(pInt); if (pInt->ax != 0x004f){ printk("set vesa mode failed,ax=%x mode(0x%x)\n", pInt->ax, pInt->bx); }else{ break; } } #ifdef DEBUG pInt->ax = 0x4f01; /* get mode information */ pInt->cx = 0x4114; pInt->di = 0; pInt->es = 0; xf86ExecX86int10(pInt); if (pInt->ax != 0x004f) printk("get vesa mode info failed,ax=%x\n", pInt->ax); printk("linelength=%x\n", MEM_RW(pInt, pInt->di + 16)); printk("width=%x\n", MEM_RW(pInt, pInt->di + 18)); printk("height=%x\n", MEM_RW(pInt, pInt->di + 20)); printk("depth=%x\n", MEM_RB(pInt, pInt->di + 25)); printk("pages=%x\n", MEM_RB(pInt, pInt->di + 29)); printk("base=%x\n", MEM_RL(pInt, pInt->di + 40)); #endif #endif #endif #if 0 radeon_init_regbase(); radeon_init_mode(); radeon_engine_init(); //radeon_dump_regs(); #endif free(pInt->private); free(pInt); free(sysMem); free(base); return 1; error0: free(pInt); return -1; } Bool MapCurrentInt10(xf86Int10InfoPtr pInt) { /* nothing to do here */ return TRUE; } #define MMIO_IN8(base, offset) \ *(volatile CARD8 *)(((CARD8*)(base)) + (offset)) #define MMIO_IN16(base, offset) \ *(volatile CARD16 *)(((CARD8*)(base)) + (offset)) #define MMIO_IN32(base, offset) \ *(volatile CARD32 *)(((CARD8*)(base)) + (offset)) #define MMIO_OUT8(base, offset, val) \ *(volatile CARD8 *)(((CARD8*)(base)) + (offset)) = (val) #define MMIO_OUT16(base, offset, val) \ *(volatile CARD16 *)(((CARD8*)(base)) + (offset)) = (val) #define MMIO_OUT32(base, offset, val) \ *(volatile CARD32 *)(((CARD8*)(base)) + (offset)) = (val) #define OFF(addr) ((addr) & 0xffff) #define SYS(addr) ((addr) >= SYS_BIOS) #define V_ADDR(addr) \ (SYS(addr) ? ((char*)INTPriv(pInt)->sysMem) + (addr - SYS_BIOS) \ : ((char*)(INTPriv(pInt)->base) + addr)) #define VRAM_ADDR(addr) (addr - V_RAM) #define VRAM_BASE (INTPriv(pInt)->vRam) #define VRAM(addr) ((addr >= V_RAM) && (addr < (V_RAM + VRAM_SIZE))) #define V_ADDR_RB(addr) \ (VRAM((addr))) ? MMIO_IN8((CARD8*)VRAM_BASE,VRAM_ADDR((addr))) \ : *(CARD8*) V_ADDR((addr)) #define V_ADDR_RW(addr) \ (VRAM((addr))) ? MMIO_IN16((CARD16*)VRAM_BASE,VRAM_ADDR((addr))) \ : (*(CARD16*)V_ADDR((addr))) #define V_ADDR_RL(addr) \ (VRAM((addr))) ? MMIO_IN32((CARD32*)VRAM_BASE,VRAM_ADDR((addr))) \ : (*(CARD32*)V_ADDR((addr))) #define V_ADDR_WB(addr,val) \ if(VRAM((addr))) { \ MMIO_OUT8((CARD8*)VRAM_BASE,VRAM_ADDR((addr)),val); \ } else \ *(CARD8*) V_ADDR((addr)) = val; #define V_ADDR_WW(addr,val) \ if(VRAM((addr))) \ MMIO_OUT16((CARD16*)VRAM_BASE,VRAM_ADDR((addr)),val); \ else \ *(CARD16*)(V_ADDR((addr))) = val; #define V_ADDR_WL(addr,val) \ if (VRAM((addr))) \ MMIO_OUT32((CARD32*)VRAM_BASE,VRAM_ADDR((addr)),val); \ else \ *(CARD32*)(V_ADDR((addr))) = val; static CARD8 read_b(xf86Int10InfoPtr pInt, int addr) { return V_ADDR_RB(addr); } static CARD16 read_w(xf86Int10InfoPtr pInt, int addr) { // return V_ADDR_RW(addr); #ifdef DEBUG_READ printf("read_w %x %x %x\n", V_ADDR_RB(addr), ((CARD16)(V_ADDR_RB((addr + 1))) << 8), (CARD16)(V_ADDR_RB(addr)) | ((CARD16)(V_ADDR_RB(addr + 1)) << 8)); #endif return (CARD16)(V_ADDR_RB(addr)) | ((CARD16)(V_ADDR_RB(addr + 1)) << 8); } static CARD32 read_l(xf86Int10InfoPtr pInt, int addr) { // return V_ADDR_RL(addr); return (CARD32)(V_ADDR_RB(addr)) | ((CARD32)(V_ADDR_RB(addr + 1)) << 8) | ((CARD32)(V_ADDR_RB(addr + 2)) << 16) | ((CARD32)(V_ADDR_RB(addr + 3)) << 24); } static void write_b(xf86Int10InfoPtr pInt, int addr, CARD8 val) { V_ADDR_WB(addr, (val & 0xff)); #ifdef DEBUG_WRITE if (VRAM(addr) && val) printf("%08x wb %x, rd %x\n", addr, val, read_b(pInt, addr)); #endif } static void write_w(xf86Int10InfoPtr pInt, int addr, CARD16 val) { V_ADDR_WB(addr, (val & 0xff)); V_ADDR_WB(addr+1, ((val >> 8) & 0xff)); #ifdef DEBUG_WRITE if (VRAM(addr) && val) printf("%08x ww %x, rd %x\n", addr, val, read_w(pInt, addr)); #endif } static void write_l(xf86Int10InfoPtr pInt, int addr, CARD32 val) { V_ADDR_WB(addr, (val & 0xff)); V_ADDR_WB(addr+1, ((val >> 8) & 0xff)); V_ADDR_WB(addr+2, ((val >> 16) & 0xff)); V_ADDR_WB(addr+3, ((val >> 24) & 0xff)); #ifdef DEBUG_WRITE if (VRAM(addr) && val) printf("%08x wl %x, rd %x\n", addr, val, read_l(pInt, addr)); #endif } pointer xf86int10Addr(xf86Int10InfoPtr pInt, CARD32 addr) { return V_ADDR(addr); }