/* This library is free software; you can redistribute it and/or */ /* modify it without any restrictions. This library is distributed */ /* in the hope that it will be useful, but without any warranty. */ /* * Matrox Driver - Michal Lindner */ #define DEBUG 1 #define MEMORY_SIZE 4 // size of card memory #include #include #include #include #include #include "vga.h" #include "libvga.h" #include "driver.h" #include "timing.h" #include "vgaregs.h" #include "interface.h" #include "accel.h" #include "vgapci.h" #include "matrox_reg.h" #define PCI_VENDOR_MATROX 0x102b #define PCI_CHIP_MGA_MILLENIUM 0x519 #define PCI_CHIP_MGA1064 0x51a // mystique #define PCI_CHIP_MGA_MILLENIUM_2 0x51b #define PCI_CHIP_MGA_MILLENIUM_2_AGP 0x51f #define PCI_CHIP_MGAG100_MM 0x1000 #define PCI_CHIP_MGAG100_AGP 0x1001 #define PCI_CHIP_MGAG200_PCI 0x520 #define PCI_CHIP_MGAG200_AGP 0x521 #define PCI_CHIP_MGAG400 0x525 #define MGAREG_SAVE(i) (VGA_TOTAL_REGS+i) #define MGA_TOTAL_REGS (VGA_TOTAL_REGS + 100) /* * Read/write to the DAC via MMIO */ /* * These were functions. Use macros instead to avoid the need to * pass pMga to them. */ #define INREG8(addr) *(volatile unsigned char*)(MMIO_POINTER + (addr)) #define OUTREG8(addr,val) *(volatile unsigned char*)(MMIO_POINTER + (addr))=(val) #define inMGAdreg(reg) INREG8(RAMDAC_OFFSET + (reg)) #define outMGAdreg(reg, val) OUTREG8(RAMDAC_OFFSET + (reg), val) #define inMGAdac(reg) \ (outMGAdreg(MGA1064_INDEX, reg), inMGAdreg(MGA1064_DATA)) #define outMGAdac(reg, val) \ (outMGAdreg(MGA1064_INDEX, reg), outMGAdreg(MGA1064_DATA, val)) #define outMGAdacmsk(reg, mask, val) \ do { /* note: mask and reg may get evaluated twice */ \ unsigned char tmp = (mask) ? (inMGAdac(reg) & (mask)) : 0; \ outMGAdreg(MGA1064_INDEX, reg); \ outMGAdreg(MGA1064_DATA, tmp | (val)); \ } while (0) #define DACREGSIZE 0x50 /* current hardware status */ typedef struct { u_int32_t MXoptionReg; unsigned char DACclk[6]; unsigned char DACreg[DACREGSIZE]; unsigned char MiscOutReg; unsigned char DACpal[768]; unsigned char CRTC[25]; unsigned char CRTCEXT[6]; unsigned char _SEQ[5]; /* unused for MGA mode, but who knows... */ unsigned char GCTL[9]; /* unused for MGA mode, but who knows... */ unsigned char ATTR[21]; }matrox_hw_state; typedef struct { u_int32_t DEVID; u_int32_t DEVCTRL; u_int32_t CLASS; u_int32_t HEADER; u_int32_t MGABASE2; u_int32_t MGABASE1; u_int32_t MGABASE3; u_int32_t reserved_1[4]; u_int32_t SUBSYSID_READ; u_int32_t ROMBASE; u_int32_t CAP_PTR; u_int32_t reserved_2; u_int32_t INTCRTL; u_int32_t OPTION; u_int32_t MGA_INDEX; u_int32_t MGA_DATA; u_int32_t SUBSYSID_WRITE; u_int32_t OPTION2; u_int32_t OPTION3; u_int32_t reserved_3[33]; u_int32_t PM_IDENT; u_int32_t PM_CSR; u_int32_t reserved_4[3]; u_int32_t AGP_IDENT; u_int32_t AGP_STS; u_int32_t AGP_CMD; u_int32_t reserved_5; }matrox_pci_configuration_space; static int matrox_init(int, int, int); static void matrox_unlock(void); static void matrox_lock(void); static void matrox_soft_reset(void); void __svgalib_skaccel_init(AccelSpecs * accelspecs, int bpp, int width_in_pixels); static int matrox_chipset; static int matrox_memory; static int matrox_is_linear, matrox_linear_base, matrox_control_base, matrox_ILOAD_base, matrox_chiptype; static int matrox_hasSDRAM; static CardSpecs *cardspecs; //static struct pci_dev *matrox_pci_dev; static void matrox_setpage(int page) { } static int __svgalib_matrox_inlinearmode(void) { return matrox_is_linear; } /* Fill in chipset specific mode information */ static void matrox_getmodeinfo(int mode, vga_modeinfo *modeinfo) { if(modeinfo->colors==16)return; modeinfo->maxpixels = matrox_memory*1024/modeinfo->bytesperpixel; modeinfo->maxlogicalwidth = 4088; modeinfo->startaddressrange = matrox_memory * 1024 - 1; modeinfo->haveblit = 0; modeinfo->flags &= ~HAVE_RWPAGE; if (modeinfo->bytesperpixel >= 1) { if(matrox_linear_base)modeinfo->flags |= CAPABLE_LINEAR; if (__svgalib_matrox_inlinearmode()) modeinfo->flags |= IS_LINEAR; } } /* Read and save chipset-specific registers */ static int matrox_saveregs(unsigned char regs[]) { // int i; matrox_unlock(); return MGA_TOTAL_REGS - VGA_TOTAL_REGS; } /* Set chipset-specific registers */ static void matrox_setregs(const unsigned char regs[], int mode) { // int i; matrox_unlock(); } /* Return nonzero if mode is available */ static int matrox_modeavailable(int mode) { struct info *info; ModeTiming *modetiming; ModeInfo *modeinfo; modeinfo = __svgalib_createModeInfoStructureForSvgalibMode(mode); if ((mode < G640x480x256 ) || mode == G720x348x2) return __svgalib_vga_driverspecs.modeavailable(mode); info = &__svgalib_infotable[mode]; if (matrox_memory * 1024 < info->ydim * info->xbytes) return 0; modeinfo = __svgalib_createModeInfoStructureForSvgalibMode(mode); modetiming = malloc(sizeof(ModeTiming)); if (__svgalib_getmodetiming(modetiming, modeinfo, cardspecs)) { free(modetiming); free(modeinfo); return 0; } free(modetiming); free(modeinfo); return SVGADRV; } /* The following values are in kHz */ #define MGA_MIN_VCO_FREQ 50000 #define MGA_MAX_VCO_FREQ 310000 static double MGAGCalcClock (long f_out, int *best_m, int *best_n, int *p, int *s ) { int m, n; double f_pll, f_vco; double m_err, calc_f; double ref_freq; int feed_div_min, feed_div_max; int in_div_min, in_div_max; int post_div_max; switch( matrox_chipset ) { case PCI_CHIP_MGA1064: ref_freq = 14318.18; feed_div_min = 100; feed_div_max = 127; in_div_min = 1; in_div_max = 31; post_div_max = 7; break; case PCI_CHIP_MGAG400: ref_freq = 27050.5; feed_div_min = 7; feed_div_max = 127; in_div_min = 1; in_div_max = 31; post_div_max = 7; break; case PCI_CHIP_MGAG100_MM: case PCI_CHIP_MGAG100_AGP: case PCI_CHIP_MGAG200_AGP: case PCI_CHIP_MGAG200_PCI: default: /* if (pMga->Bios2.PinID && (pMga->Bios2.VidCtrl & 0x20)) ref_freq = 14318.18; else */ ref_freq = 27050.5; feed_div_min = 7; feed_div_max = 127; in_div_min = 1; in_div_max = 6; post_div_max = 7; break; } /* Make sure that f_min <= f_out */ if ( f_out < ( MGA_MIN_VCO_FREQ / 8)) f_out = MGA_MIN_VCO_FREQ / 8; /* * f_pll = f_vco / (p+1) * Choose p so that MGA_MIN_VCO_FREQ <= f_vco <= MGA_MAX_VCO_FREQ * we don't have to bother checking for this maximum limit. */ f_vco = ( double ) f_out; for ( *p = 0; *p <= post_div_max && f_vco < MGA_MIN_VCO_FREQ; *p = *p * 2 + 1, f_vco *= 2.0); /* Initial amount of error for frequency maximum */ m_err = f_out; /* Search for the different values of ( m ) */ for ( m = in_div_min ; m <= in_div_max ; m++ ) { /* see values of ( n ) which we can't use */ for ( n = feed_div_min; n <= feed_div_max; n++ ) { calc_f = ref_freq * (n + 1) / (m + 1) ; /* * Pick the closest frequency. */ if ( abs(calc_f - f_vco) < m_err ) { m_err = abs(calc_f - f_vco); *best_m = m; *best_n = n; } } } /* Now all the calculations can be completed */ f_vco = ref_freq * (*best_n + 1) / (*best_m + 1); /* Adjustments for filtering pll feed back */ if ( (50000.0 <= f_vco) && (f_vco < 100000.0) ) *s = 0; if ( (100000.0 <= f_vco) && (f_vco < 140000.0) ) *s = 1; if ( (140000.0 <= f_vco) && (f_vco < 180000.0) ) *s = 2; if ( (180000.0 <= f_vco) ) *s = 3; f_pll = f_vco / ( *p + 1 ); #if 0 //#ifdef DEBUG ErrorF( "f_out_requ =%ld f_pll_real=%.1f f_vco=%.1f n=0x%x m=0x%x p=0x%x s=0x%x\n", f_out, f_pll, f_vco, *best_n, *best_m, *p, *s ); #endif return f_pll; } /* * MGAGSetPCLK - Set the pixel (PCLK) clock. MGAGSetPCLK( ScrnInfoPtr pScrn, long f_out ) */ static void MGAGSetPCLK( matrox_hw_state *state, long f_out ) { /* MGAPtr pMga = MGAPTR(pScrn); MGARegPtr pReg = &pMga->ModeReg; */ /* Pixel clock values */ int m, n, p, s; /* The actual frequency output by the clock */ double f_pll; /* Do the calculations for m, n, p and s */ f_pll = MGAGCalcClock( f_out, &m, &n, &p, &s ); /* Values for the pixel clock PLL registers */ state->DACreg[ MGA1064_PIX_PLLC_M ] = m & 0x1F; state->DACreg[ MGA1064_PIX_PLLC_N ] = n & 0x7F; state->DACreg[ MGA1064_PIX_PLLC_P ] = (p & 0x07) | ((s & 0x03) << 3); } /* * MGASoftReset -- reset drawing engine */ void matrox_soft_reset() { (unsigned long)MMIO_POINTER[ MGAREG_Reset ]=1; usleep(200); (unsigned long)MMIO_POINTER[ MGAREG_Reset ]=0; (unsigned long)MMIO_POINTER[ MGAREG_MACCESS ]=1<<15; usleep(10); } /* Local, called by matrox_setmode(). */ static void matrox_initializemode(unsigned char *moderegs, ModeTiming * modetiming, ModeInfo * modeinfo, int mode) { int i,hd,hs,he,ht,vd,vs,ve,vt,wd; int maccess,mopmode; int BppShift; matrox_hw_state state; /* * initial values of the DAC registers */ const static unsigned char initDAC[] = { /* 0x00: */ 0, 0, 0, 0, 0, 0, 0x00, 0, /* 0x08: */ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10: */ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x18: */ 0x00, 0, 0xC9, 0xFF, 0xBF, 0x20, 0x1F, 0x20, /* 0x20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28: */ 0x00, 0x00, 0x00, 0x00, 0, 0, 0, 0x40, /* 0x30: */ 0x00, 0xB0, 0x00, 0xC2, 0x34, 0x14, 0x02, 0x83, /* 0x38: */ 0x00, 0x93, 0x00, 0x77, 0x00, 0x00, 0x00, 0x3A, /* 0x40: */ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x48: */ 0, 0, 0, 0, 0, 0, 0, 0 }; __svgalib_setup_VGA_registers(moderegs, modetiming, modeinfo); for(i=0;iOverclockMem) { /* 220 Mhz */ // state.DACreg[ MGA1064_SYS_PLL_M ] = 0x06; // state.DACreg[ MGA1064_SYS_PLL_N ] = 0x38; // state.DACreg[ MGA1064_SYS_PLL_P ] = 0x18; // } else { /* 203 Mhz */ state.DACreg[ MGA1064_SYS_PLL_M ] = 0x01; state.DACreg[ MGA1064_SYS_PLL_N ] = 0x0E; state.DACreg[ MGA1064_SYS_PLL_P ] = 0x18; // } proc_pci_write_dword(VGAPCI_CS_OPTION,0x404991a9); // pReg->Option = 0x404991a9; } else { // if(pMga->OverclockMem) { /* 143 Mhz */ // state.DACreg[ MGA1064_SYS_PLL_M ] = 0x06; // state.DACreg[ MGA1064_SYS_PLL_N ] = 0x24; // state.DACreg[ MGA1064_SYS_PLL_P ] = 0x10; // } else { /* 124 Mhz */ state.DACreg[ MGA1064_SYS_PLL_M ] = 0x04; state.DACreg[ MGA1064_SYS_PLL_N ] = 0x16; state.DACreg[ MGA1064_SYS_PLL_P ] = 0x08; // } proc_pci_write_dword(VGAPCI_CS_OPTION,0x4049d121); } proc_pci_write_dword(VGAPCI_CS_OPTION2,0x0000007); break; case PCI_CHIP_MGAG400: /* we don't have a good overclock value yet */ /* 165 Mhz */ state.DACreg[ MGA1064_SYS_PLL_M ] = 0x09; state.DACreg[ MGA1064_SYS_PLL_N ] = 0x3C; state.DACreg[ MGA1064_SYS_PLL_P ] = 0x10; proc_pci_write_dword(VGAPCI_CS_OPTION2,0x01003000); proc_pci_write_dword(VGAPCI_CS_OPTION3,0x0190a419); if(matrox_hasSDRAM) proc_pci_write_dword(VGAPCI_CS_OPTION,0x50040120); else proc_pci_write_dword(VGAPCI_CS_OPTION,0x50044120); break; case PCI_CHIP_MGAG200_AGP: case PCI_CHIP_MGAG200_PCI: default: state.MiscOutReg = 0xEF; // if(pMga->OverclockMem) { /* 143 Mhz */ // state.DACreg[ MGA1064_SYS_PLL_M ] = 0x06; // state.DACreg[ MGA1064_SYS_PLL_N ] = 0x24; // state.DACreg[ MGA1064_SYS_PLL_P ] = 0x10; // } else { /* 124 Mhz */ state.DACreg[ MGA1064_SYS_PLL_M ] = 0x04; state.DACreg[ MGA1064_SYS_PLL_N ] = 0x2D; state.DACreg[ MGA1064_SYS_PLL_P ] = 0x19; // } proc_pci_write_dword(VGAPCI_CS_OPTION2,0x00008000); if(matrox_hasSDRAM) proc_pci_write_dword(VGAPCI_CS_OPTION,0x40499121); else proc_pci_write_dword(VGAPCI_CS_OPTION,0x4049cd21); break; } if(modeinfo->height>400){ state.MiscOutReg &= ~0x40; }else{ state.MiscOutReg &= ~0x80; } // if(pMga->UsePCIRetry) // pReg->Option &= ~0x20000000; // else // pReg->Option |= 0x20000000; #endif mopmode=MGAOPM_DMA_BLIT; switch(modeinfo->bitsPerPixel) { case 8: BppShift=0; /* set pwidth bits 0,1 to 00 - 8 bits per pixel*/ maccess=0x00000000; state.DACreg[ MGA1064_MUL_CTL ] = MGA1064_MUL_CTL_8bits; break; case 15: BppShift=1; /* set pwidth bits 0,1 to 01 - 16 bits per pixel*/ maccess=0xC0000001; state.DACreg[ MGA1064_MUL_CTL ] = MGA1064_MUL_CTL_15bits; break; case 16: BppShift=1; /* set pwidth bits 0,1 to 01 - 16 bits per pixel*/ /* dit555 mode - bit 31 - 0 - 5:6:5 dithering mode */ maccess=0x40000001; state.DACreg[ MGA1064_MUL_CTL ] = MGA1064_MUL_CTL_16bits; break; case 24: BppShift=0; /* set pwidth bits 0,1 to 11 - 24 bits per pixel*/ maccess=0x00000003; state.DACreg[ MGA1064_MUL_CTL ] = MGA1064_MUL_CTL_24bits; break; case 32: BppShift=2; /* set pwidth bits 0,1 to 01 - 16 bits per pixel*/ maccess=0x00000002; // if(pMga->Overlay8Plus24) { // alpha canal // state.DACreg[ MGA1064_MUL_CTL ] = MGA1064_MUL_CTL_32bits; // state.DACreg[ MGA1064_COL_KEY_MSK_LSB ] = 0xFF; // state.DACreg[ MGA1064_COL_KEY_LSB ] = pMga->colorKey; // } else state.DACreg[ MGA1064_MUL_CTL ] = MGA1064_MUL_CTL_32_24bits; break; default: BppShift=0; maccess=0x00000000; mopmode=0; // FatalError("MGA: unsupported depth\n"); } matrox_soft_reset(); (unsigned long)MMIO_POINTER[ MGAREG_PITCH ] = modeinfo->lineWidth; (unsigned long)MMIO_POINTER[ MGAREG_YDSTORG ] = 0; // if (ACCESS_FBINFO(capable.plnwt)) (unsigned long)MMIO_POINTER[ MGAREG_PLNWT ] = 0xFFFFFFFF; // MMIO_POINTER[ MGAREG_CXBNDRY ] = 0xFFFF0000; // !!!! overit! (unsigned long)MMIO_POINTER[ MGAREG_CXBNDRY ] = 0x0FFF0000; (unsigned long)MMIO_POINTER[ MGAREG_OPMODE ]=mopmode; (unsigned long)MMIO_POINTER[ MGAREG_YTOP ] = 0x007FFFFF; (unsigned long)MMIO_POINTER[ MGAREG_YBOT ] = 0x00000000; (unsigned long)MMIO_POINTER[ MGAREG_MACCESS ]=maccess; /* set zwidth bits 0,1 to 00 - 16bit Z buffer - no stencil bufer */ // MMIO_POINTER[ MGAREG_MACCESS ]&=0xFFFFFFF3; /* disable dithering */ // MMIO_POINTER[ MGAREG_MACCESS ]|=1<<30; /* reset memory */ // MMIO_POINTER[ MGAREG_MACCESS ]|=1<<15; // matrox_soft_reset(); /* * Here all of the MGA registers get filled in. */ hd = (modetiming->CrtcHDisplay >> 3) - 1; hs = (modetiming->CrtcHSyncStart>> 3) - 1; he = (modetiming->CrtcHSyncEnd >> 3) - 1; ht = (modetiming->CrtcHTotal >> 3) - 1; vd = modetiming->CrtcVDisplay - 1; vs = modetiming->CrtcVSyncStart - 1; ve = modetiming->CrtcVSyncEnd - 1; vt = modetiming->CrtcVTotal - 2; /* HTOTAL & 0x7 equal to 0x6 in 8bpp or 0x4 in 24bpp causes strange * vertical stripes */ if((ht & 0x07) == 0x06 || (ht & 0x07) == 0x04) ht++; if(modeinfo->bitsPerPixel==24) wd = (modeinfo->lineWidth * 3) >> BppShift; else wd = modeinfo->lineWidth >> BppShift; state.CRTCEXT[0] = 0; state.CRTCEXT[5] = 0; if (modetiming->flags & INTERLACED) { state.CRTCEXT[0] = 0x80; state.CRTCEXT[5] = (hs + he - ht) >> 1; wd <<= 1; vt &= 0xFFFE; } state.CRTCEXT[0] |= (wd & 0x300) >> 4; state.CRTCEXT[1] = (((ht - 4) & 0x100) >> 8) | ((hd & 0x100) >> 7) | ((hs & 0x100) >> 6) | (ht & 0x40); state.CRTCEXT[2] = ((vt & 0xc00) >> 10) | ((vd & 0x400) >> 8) | ((vd & 0xc00) >> 7) | ((vs & 0xc00) >> 5); if(modeinfo->bitsPerPixel==24) state.CRTCEXT[3] = (((1 << BppShift)*3 ) - 1) | 0x80; else state.CRTCEXT[3] = ((1 << BppShift) - 1) | 0x80; #if 0 // !!!! - nastavit CRTCEXT[3] na 0x80 ! /* Set viddelay (CRTCEXT3 Bits 3-4). */ pReg->ExtVga[3] |= (pScrn->videoRam == 8192 ? 0x10 : pScrn->videoRam == 2048 ? 0x08 : 0x00); #endif // state.CRTCEXT[3] = 0x80; state.CRTCEXT[4] = 0; for(i=0;i> 8 ) | ((vd & 0x100) >> 7 ) | ((vs & 0x100) >> 6 ) | ((vd & 0x100) >> 5 ) | 0x10 | ((vt & 0x200) >> 4 ) | ((vd & 0x200) >> 3 ) | ((vs & 0x200) >> 2 ); state.CRTC[9] = ((vd & 0x200) >> 4) | 0x40; state.CRTC[16] = vs & 0xFF; state.CRTC[13] = (modeinfo->lineWidth*modeinfo->bitsPerPixel)/128; state.CRTC[17] = (ve & 0x0F) | 0x20; state.CRTC[18] = vd & 0xFF; state.CRTC[19] = wd & 0xFF; state.CRTC[21] = vd & 0xFF; state.CRTC[22] = (vt + 1) & 0xFF; if (modetiming->flags & DOUBLESCAN) state.CRTC[9] |= 0x80; for(i=0;iFbCursorOffset >> 10; state.DacReg[ MGA1064_CURSOR_BASE_ADR_HI ] = pMga->FbCursorOffset >> 18; #endif #if 0 if (pMga->SyncOnGreen) { pReg->DacRegs[ MGA1064_GEN_CTL ] &= ~0x20; pReg->ExtVga[3] |= 0x40; } #endif /* select external clock */ state.MiscOutReg |= 0x0C; MGAGSetPCLK(&state, modetiming->pixelClock ); /* This disables the VGA memory aperture */ state.MiscOutReg &= ~0x02; /* restore DAC registers * according to the docs we shouldn't write to reserved regs*/ for (i = 0; i < DACREGSIZE; i++) { if( (i <= 0x03) || (i == 0x07) || (i == 0x0b) || (i == 0x0f) || ((i >= 0x13) && (i <= 0x17)) || (i == 0x1b) || (i == 0x1c) || ((i >= 0x1f) && (i <= 0x29)) || ((i >= 0x30) && (i <= 0x37)) ) continue; outMGAdac(i, state.DACreg[i]); } OUTREG8(0x1fcc,state.MiscOutReg); // MISC WRITE return ; } static int matrox_setmode(int mode, int prv_mode) { unsigned char *moderegs; ModeTiming *modetiming; ModeInfo *modeinfo; int i; if ((mode < G640x480x256)||(mode==G720x348x2)) { return __svgalib_vga_driverspecs.setmode(mode, prv_mode); } if (!matrox_modeavailable(mode)) return 1; modeinfo = __svgalib_createModeInfoStructureForSvgalibMode(mode); modetiming = malloc(sizeof(ModeTiming)); if (__svgalib_getmodetiming(modetiming, modeinfo, cardspecs)) { free(modetiming); free(modeinfo); return 1; } moderegs = malloc(MGA_TOTAL_REGS); matrox_initializemode(moderegs, modetiming, modeinfo, mode); free(modetiming); __svgalib_setregs(moderegs); /* Set standard regs. */ matrox_setregs(moderegs, mode); /* Set extended regs. */ free(moderegs); __svgalib_InitializeAcceleratorInterface(modeinfo); free(modeinfo); // memset(LINEAR_MEM_POINTER,0x3f,__svgalib_linear_mem_size); for(i=0;i<__svgalib_linear_mem_size;i++) LINEAR_MEM_POINTER[i]=(i&0xc0)+((i&0x3f)*((i>>8)&0xfc)>>8); // LINEAR_MEM_POINTER[i]=(i%640)&0xff; return 0; } /* Unlock chipset-specific registers */ static void matrox_unlock(void) { int vgaIOBase, temp; vgaIOBase = (inb(0x3CC) & 0x01) ? 0x3D0 : 0x3B0; outb(vgaIOBase + 4, 0x11); temp = inb(vgaIOBase + 5); outb(vgaIOBase + 5, temp & 0x7F); } static void matrox_lock(void) { int vgaIOBase, temp; vgaIOBase = (inb(0x3CC) & 0x01) ? 0x3D0 : 0x3B0; outb(vgaIOBase + 4, 0x11); temp = inb(vgaIOBase + 5); outb(vgaIOBase + 5, temp & 0x7F); } /* Indentify chipset, initialize and return non-zero if detected */ static int matrox_test(void) { int _ioperm=0,found; matrox_pci_configuration_space buf; #ifdef DEBUG printf("svgalib: probing matrox driver\n"); #endif if (getenv("IOPERM") == NULL) { _ioperm=1; if (iopl(3) < 0) { printf("svgalib: cannot get I/O permissions\n"); exit(1); } } found=__svgalib_pci_find_vendor_vga(PCI_VENDOR_MATROX,(long*)&buf,0); if (_ioperm) iopl(0); if(found){// I don't know why, but in vgapci.c 0 in on success #ifdef DEBUG printf("svgalib: fatal error (no matrox card found)\n"); #endif return(0); } matrox_chipset=(buf.DEVID>>16)&0xffff; switch(matrox_chipset){ case PCI_CHIP_MGA_MILLENIUM: printf("svgalib: Matrox millenium card found\n"); break; case PCI_CHIP_MGA1064: printf("svgalib: Matrox mystique card found\n"); break; case PCI_CHIP_MGA_MILLENIUM_2: printf("svgalib: Matrox MIL2PCI card found\n"); break; case PCI_CHIP_MGA_MILLENIUM_2_AGP: printf("svgalib: Matrox MIL2AGP card found\n"); break; case PCI_CHIP_MGAG100_MM: printf("svgalib: Matrox G100_MM card found\n"); break; case PCI_CHIP_MGAG100_AGP: printf("svgalib: Matrox G100AGP card found\n"); break; case PCI_CHIP_MGAG200_PCI: printf("svgalib: Matrox G200PCI card found\n"); break; case PCI_CHIP_MGAG200_AGP: printf("svgalib: Matrox G200AGP card found\n"); break; case PCI_CHIP_MGAG400: printf("svgalib: Matrox G400AGP card found\n"); break; default: printf("svgalib: unsupported Matrox card\n"); return 0; } matrox_hasSDRAM = buf.OPTION&0x4000; matrox_init(0,0,(buf.DEVID>>16)&0xffff); return 1; } /* Set display start address (not for 16 color modes) */ /* Cirrus supports any address in video memory (up to 2Mb) */ static void matrox_setdisplaystart(int address) { address=address >> 2; outw(CRT_IC, (address & 0x00FF00) | 0x0C); outw(CRT_IC, ((address & 0x00FF) << 8) | 0x0D); } /* Set logical scanline length (usually multiple of 8) */ /* Cirrus supports multiples of 8, up to 4088 */ static void matrox_setlogicalwidth(int width) { int offset = width >> 3; __svgalib_outCR(0x13,offset&0xff); } static int matrox_linear(int op, int param) { if (op==LINEAR_ENABLE){matrox_is_linear=1; return 0;}; if (op==LINEAR_DISABLE){matrox_is_linear=0; return 0;}; if (op==LINEAR_QUERY_BASE) return matrox_linear_base; if (op == LINEAR_QUERY_RANGE || op == LINEAR_QUERY_GRANULARITY) return 0; /* No granularity or range. */ else return -1; /* Unknown function. */ } static int matrox_match_programmable_clock(int clock) { return clock ; } static int matrox_map_clock(int bpp, int clock) { return clock ; } static int matrox_map_horizontal_crtc(int bpp, int pixelclock, int htiming) { return htiming; } /* Function table (exported) */ DriverSpecs __svgalib_matrox_driverspecs = { matrox_saveregs, // ulozenie obsahu registrov karty - pri prepinani n ainu konzolu a pod matrox_setregs, // obnovenie stavu registrov "zo zalohy" matrox_unlock, // odomknutie karty - malo by fungovat matrox_lock, // zamknutie karty - malo by fungovat matrox_test, // detakcia karty - funguje matrox_init, // inicializacia karty - mozno funguje matrox_setpage, // prepnutie stranky - zatial nie je, ale malo by to byt jednoduche NULL, NULL, matrox_setmode, // nastavenie grafickeho rezimu matrox_modeavailable, // zistenie, ci je tento graficky mod na tejto karte pristupny matrox_setdisplaystart, matrox_setlogicalwidth, matrox_getmodeinfo, // ??? - mozno funguje 0, /* old blit funcs */ 0, 0, 0, 0, 0, /* ext_set */ 0, /* accel */ matrox_linear, 0, /* accelspecs, filled in during init. */ NULL, /* Emulation */ }; /* Initialize chipset (called after detection) */ static int matrox_init(int force, int par1, int par2) { matrox_pci_configuration_space buf; int found=0; int _ioperm=0; matrox_unlock(); if (force) { matrox_memory = par1; matrox_chiptype = par2; } else { }; matrox_memory=MEMORY_SIZE*1024; /* hard limit - detection must be done */ matrox_is_linear=1; // let's be linear if (getenv("IOPERM") == NULL) { _ioperm=1; if (iopl(3) < 0) { printf("svgalib: cannot get I/O permissions\n"); exit(1); } } found=__svgalib_pci_find_vendor_vga(PCI_VENDOR_MATROX,(long*)&buf,0); // matrox_pci_dev=pci_find_device(PCI_VENDOR_MATROX,(buf.DEVID>>16)&0xffff,pci_devices); if (_ioperm) iopl(0); matrox_linear_base=0; if (!found){ matrox_linear_base=buf.MGABASE2&0xffffff00; matrox_control_base=buf.MGABASE1&0xffffff00; matrox_ILOAD_base=buf.MGABASE3&0xffffff00; if(__svgalib_mem_fd<0){ printf("svgalib: __svgalib_mem_fd is not opened\n"); exit(1); } }; if (__svgalib_driver_report) { printf("Using MGA driver, %iKB. ",matrox_memory); }; cardspecs = malloc(sizeof(CardSpecs)); cardspecs->videoMemory = matrox_memory; cardspecs->maxPixelClock4bpp = 75000; cardspecs->maxPixelClock8bpp = 160000; cardspecs->maxPixelClock16bpp = 160000; cardspecs->maxPixelClock24bpp = 160000; cardspecs->maxPixelClock32bpp = 160000; cardspecs->flags = INTERLACE_DIVIDE_VERT | CLOCK_PROGRAMMABLE; cardspecs->maxHorizontalCrtc = 2040; cardspecs->maxPixelClock4bpp = 0; cardspecs->nClocks =0; cardspecs->mapClock = matrox_map_clock; cardspecs->mapHorizontalCrtc = matrox_map_horizontal_crtc; cardspecs->matchProgrammableClock=matrox_match_programmable_clock; __svgalib_driverspecs = &__svgalib_matrox_driverspecs; __svgalib_banked_mem_base=0xa0000; __svgalib_banked_mem_size=0x10000; __svgalib_linear_mem_base=matrox_linear_base; __svgalib_linear_mem_size=matrox_memory*1024; __svgalib_mmio_base=buf.MGABASE1; __svgalib_mmio_size=0x4000; return 0; } /* Bear's motes: valid mode check - xfree 3.9.15 mga_driver.c lace = 1 + ((mode->Flags&V_INTERLACE)!=0) HDisplay <= 2048 - rozlisenie x HSyncStart <= 4096 - start sync impulzu (HDisplay < HSyncStart) HSyncEnd <= 4096 - koniec sync impulzu (HsyncStart < HSyncEnd < HTotal) HTotal <= 4096 - sirka VDisplay <= 2048*lace - detto VSyncStart <= 4096*lace HSyncEnd <= 4096*lace HTotal <= 4096*lace */