i2061aalt.c

来自「基于组件方式开发操作系统的OSKIT源代码」· C语言 代码 · 共 426 行

C
426
字号
/* $XFree86: xc/programs/Xserver/hw/xfree86/common_hw/I2061Aalt.c,v 3.12 1996/12/23 06:44:07 dawes Exp $ *//* * This code is derived from code available from the STB bulletin board *//* $XConsortium: I2061Aalt.c /main/12 1996/10/19 18:00:05 kaleb $ *//*#define EXTENDED_DEBUG*/#ifdef EXTENDED_DEBUG#include <stdio.h>#endif#include "Xfuncproto.h"#include "compiler.h"#define NO_OSLIB_PROTOTYPES#include "xf86_OSlib.h"#define SEQREG   0x03C4#define MISCREG  0x03C2#define MISCREAD 0x03CCdouble fref = 14.31818 * 2.0;char ascclk[] = "VIDEO CLOCK ?";unsigned short clknum;unsigned short vlbus_flag;unsigned short card;unsigned short crtcaddr;unsigned short clockreg;static double range[15] = {50.0, 51.0, 53.2, 58.5, 60.7, 64.4, 66.8, 73.5, 			   75.6, 80.9, 83.2, 91.5, 100.0, 120.0, 120.0000001};#if NeedFunctionPrototypes#if 0static void prtbinary(unsigned int size, unsigned int val);#endifstatic void wrt_clk_bit(unsigned int value);static void s3_init_clock(unsigned long setup,  unsigned short crtcport);static void et4000_init_clock(unsigned long setup);#else#if 0static void prtbinary();#endifstatic void wrt_clk_bit();static void s3_init_clock();static void et4000_init_clock();#endif#ifdef PC98_PWstatic void PWClockSet(short,unsigned long);#endif#ifdef PC98_PWLBstatic void PWLBClockSet(short,unsigned long);#endifstatic unsigned longAltICD2061CalcClock(frequency)register long   frequency;               /* in Hz */{   unsigned int m;   int i;   long dwv;   double realval;   double freq, fvco;   double dev, devx;   double delta, deltax;   double f0;   unsigned int p, q;   unsigned int bestp=0, bestq=0, bestm=0, besti=0;   unsigned char tmp;   crtcaddr=(inb(0x3CC) & 0x01) ? 0x3D4 : 0x3B4;   outb(crtcaddr, 0x11);	/* Unlock CRTC registers */   tmp = inb(crtcaddr + 1);   outb(crtcaddr + 1, tmp & ~0x80);#if !defined(PC98_PW) && !defined(PC98_PWLB)   outw(crtcaddr, 0x4838);	/* Unlock S3 register set */   outw(crtcaddr, 0xA039);#else   outw(crtcaddr, 0x4838);	/* Unlock S3 register set */   outw(crtcaddr, 0xA539);#endif   freq = ((double)frequency)/1000000.0;   if (freq > range[13])      freq = range[13];   else if (freq < 7.0)      freq = 7.0;/* *  Calculate values to load into ICD 2061A clock chip to set frequency */   delta = 999.0;   dev   = 999.0;   for (m = 0; m < 8; m++) {      fvco = freq * (1<<m);      if (fvco < 50.0 || fvco > 120.0) continue;            f0  = fvco / fref;      for (q = 14; q <= 71; q++) {     /* q={15..71}:Constraint 2 on page 14 */	 p = (int)(f0 * q + 0.5);	 if (p < 4 || p > 130)      /* p={4..130}:Constraint 5 on page 14 */	    continue; 	 deltax = (double)(p) / (double)(q) - f0;	 if (deltax < 0) deltax = -deltax;	 if (deltax <= delta) {	    for (i = 13; i >= 0; i--)	       if (fvco >= range[i])		  break;	    devx = (fvco - (range[i] + range[i+1])/2)/fvco;	    if (devx < 0)	       devx = -devx;	    if (deltax < delta || devx < dev) {	       delta = deltax;	       dev   = devx;	       bestp = p;	       bestq = q;	       bestm = m;	       besti = i;	    }	 }      }   }   fvco = fref / (1<<bestm);   realval = (fvco * bestp) /  bestq;#ifdef EXTENDED_DEBUG   fprintf(stderr, "I2061Aalt.c: from (%d,%d,%d) calculated freq %ld kHz\n", bestm, bestp, bestq,          ((((unsigned long) 4*14318lu*bestp/bestq)>>bestm)+1)>>1);#endif#if !defined(PC98_PW) && !defined(PC98_PWLB)   dwv = ((((((long)besti << 7) | (bestp-3)) << 3) | bestm) << 7) | (bestq-2);#else   bestp = (~(0x82 - bestp)) & 0x7f;   bestq = (~(0x81 - bestq)) & 0x7f;		   dwv = ((((((((long)besti << 7) | bestp) << 1) | 1) << 3) | bestm) << 7) | (bestq-2);#endif   return (dwv);}voidAltICD2061SetClock(frequency, select)register long   frequency;               /* in Hz */int select;{   unsigned char tmp;   long dwv;#ifdef EXTENDED_DEBUG   ErrorF("Setting ICD2061A compatible clock to %d\n",frequency);#endif   crtcaddr=(inb(0x3CC) & 0x01) ? 0x3D4 : 0x3B4;   outb(crtcaddr, 0x11);        /* Unlock CRTC registers */   tmp = inb(crtcaddr + 1);   outb(crtcaddr + 1, tmp & ~0x80);#if !defined(PC98_PW) && !defined(PC98_PWLB)   outw(crtcaddr, 0x4838);      /* Unlock S3 register set */   outw(crtcaddr, 0xA039);#else   outw(crtcaddr, 0x4838);      /* Unlock S3 register set */   outw(crtcaddr, 0xA539);#endif   /* Write ICD 2061A clock chip */   dwv = AltICD2061CalcClock(frequency);#if !defined(PC98_PW) && !defined(PC98_PWLB)   s3_init_clock(((unsigned long)dwv) | (((long)select) << 21), crtcaddr);   usleep(20000);      /* 20 ms delay... */#else#ifdef PC98_PW	PWClockSet(select, (unsigned long)dwv);#else#ifdef PC98_PWLB	PWLBClockSet(select, (unsigned long)dwv);#endif#endif	inb(0x3d4);	inb(0x3d4);	inb(0x3d4);	inb(0x3d4);#endif}voidEt4000AltICD2061SetClock(frequency, select)register long   frequency;               /* in Hz */int select;{   unsigned long dwv;   unsigned char tmp;   crtcaddr=(inb(0x3CC) & 0x01) ? 0x3D4 : 0x3B4;   /* Write ICD 2061A clock chip */   dwv = AltICD2061CalcClock(frequency);#ifdef EXTENDED_DEBUG   fprintf(stderr, "I2061Aalt.c: Setting (et4000)ICD2061A freq %d, select %d, dwv %ld\n",          frequency, select, dwv);#endif   et4000_init_clock(((unsigned long)dwv) | (((long)select) << 21));   /* select the clock */   tmp = inb(0x3CC);   outb(0x3C2, (tmp & 0xF3) | ((select << 2) & 0x0C));   usleep(20000);      /* 20 ms delay... */}#if 0static voidprtbinary(size, val)   unsigned int size;   unsigned int val;   {   unsigned int mask;   int k;   mask = 1;   for (k=size; --k > 0 || mask <= val/2;)      mask <<= 1;   while (mask) {      fputc((mask&val)? '1': '0' , stderr);      mask >>= 1;      }   }#endif#if NeedFunctionPrototypesstatic voids3_init_clock(unsigned long setup, unsigned short crtcport)#elsestatic voids3_init_clock(setup, crtcport)   unsigned long setup;   unsigned short crtcport;#endif   {   unsigned char nclk[2], clk[2];   unsigned short restore42;   unsigned short oldclk;   unsigned short bitval;   int i;   unsigned char c;   (void)xf86DisableInterrupts();   oldclk = inb(0x3CC);   outb(crtcport, 0x42);   restore42 = inb(crtcport+1);   outw(0x3C4, 0x0100);   outb(0x3C4, 1);   c = inb(0x3C5);   outb(0x3C5, 0x20 | c);   outb(crtcport, 0x42);   outb(crtcport+1, 0x03);   outw(0x3C4, 0x0300);   nclk[0] = oldclk & 0xF3;   nclk[1] = nclk[0] | 0x08;   clk[0] = nclk[0] | 0x04;   clk[1] = nclk[0] | 0x0C;   outb(crtcport, 0x42);   i = inw(crtcport);   outw(0x3C4, 0x0100);   wrt_clk_bit(oldclk | 0x08);   wrt_clk_bit(oldclk | 0x0C);   for (i=0; i<5; i++) {      wrt_clk_bit(nclk[1]);      wrt_clk_bit(clk[1]);      }   wrt_clk_bit(nclk[1]);   wrt_clk_bit(nclk[0]);   wrt_clk_bit(clk[0]);   wrt_clk_bit(nclk[0]);   wrt_clk_bit(clk[0]);   for (i=0; i<24; i++) {      bitval = setup & 0x01;      setup >>= 1;      wrt_clk_bit(clk[1-bitval]);      wrt_clk_bit(nclk[1-bitval]);      wrt_clk_bit(nclk[bitval]);      wrt_clk_bit(clk[bitval]);      }   wrt_clk_bit(clk[1]);   wrt_clk_bit(nclk[1]);   wrt_clk_bit(clk[1]);   outb(0x3C4, 1);   c = inb(0x3C5);   outb(0x3C5, 0xDF & c);   outb(crtcport, 0x42);   outb(crtcport+1, restore42);   outb(0x3C2, oldclk);   outw(0x3C4, 0x0300);   xf86EnableInterrupts();   }static voidwrt_clk_bit(value)   unsigned int value;   {   int j;   outb(0x3C2, value);   for (j=2; --j; )      inb(0x200);   }#ifdef PC98_PWstatic voidPWClockSet(short a, unsigned long setup){	unsigned char b, div;		unsigned short	i, bitval;	div = (a)? 0: rdinx(0x3d4, 0x41);	b = (a)? 0x20: 0x90;	for (i=0; i<22; i++) {		bitval = setup & 0x01;		setup >>= 1;		div &= 0x0f;		div |= (bitval)? 0x40: 0;		div |= b;		_outb(0x0dc|PW_PORT, div);		div |= 0x30; 		_outb(0x0dc|PW_PORT, div);	}}#endif#ifdef PC98_PWLBstatic voidPWLBClockSet(short a, unsigned long setup){	unsigned char b, div;		unsigned short	i, bitval;	div = (a)? 0: rdinx(0x3d4, 0x41);	b = (a)? 0x20: 0x90;	for (i=0; i<22; i++) {		bitval = setup & 0x01;		setup >>= 1;		div &= 0x0f;		div |= (bitval)? 0x40: 0;		div |= b;		PWLBctrl(div);		div |= 0x30; 		PWLBctrl(div);	}}#endif/* *  ET4000 ICD2061 (Diamond Stealth 32) clock setting code. *    Original by Frank Klemm *    Linux port by Ray Balister. *    various improvements by Peter Chang *    included in XFREE code base by Koen Gadeyne */static voidet4000_init_clock(unsigned long setup){    register unsigned char a=inb(0x3CC) & ~0x0C;    register unsigned i;    unsigned long m;#define S(x)   outb(0x3C2,a | 4*(x))    for (i=0; i<5; i++)      S(2), S(3);    for (i=0; i<2; i++)      S(0), S(1);    for (i=0, m=1; i<24; i++, m+=m)      if (setup & m)       S(1), S(0), S(2), S(3);      else       S(3), S(2), S(0), S(1);    S(3), S(2), S(3);    S(3);#undef S}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?