Annotation of ntddk/src/video/miniport/s3/nnclk.c, revision 1.1.1.1

1.1       root        1: /*++
                      2: 
                      3: Copyright (c) 1990-1993  Microsoft Corporation
                      4: 
                      5: Module Name:
                      6: 
                      7:     s3.c
                      8: 
                      9: Abstract:
                     10: 
                     11:     This module contains the code to set the number nine clock.
                     12: 
                     13: Environment:
                     14: 
                     15:     Kernel mode
                     16: 
                     17: Revision History:
                     18: 
                     19: --*/
                     20: 
                     21: #include "s3.h"
                     22: 
                     23: #define PROM_WRITE_INDEX        0x51
                     24: #define PROM_WRITE_BIT          0x80
                     25: #define SSW_READ_ENBL_INDEX     0x55
                     26: #define SSW_READ_ENBL_BIT       0x04
                     27: #define SSW_READ_PORT           0x03C8
                     28: #define SSW_WRITE_INDEX         0x5C
                     29: #define LOCK_INDEX              0x39
                     30: #define UNLOCK_PATTERN          0xA0
                     31: #define LOCK_INDEX2             0x38
                     32: #define UNLOCK_PATTERN2         0x48
                     33: #define BIOS_32K_INDEX          0x31
                     34: #define BIOS_32K_BIT            0x80
                     35: #define MODE_CTRL_INDEX         0x42
                     36: 
                     37: #define GOPA_FLSEL              0x40
                     38: #define GOPB_ENABLE             0x80
                     39: #define GOPB_SLED               0x40
                     40: #define GOPB_FLSEL              0x20
                     41: #define GOPB_BURN               0x10
                     42: 
                     43: 
                     44: long calc_clock(long, int);
                     45: long gcd(long, long);
                     46: VOID set_clock(
                     47:     PHW_DEVICE_EXTENSION HwDeviceExtension,
                     48:     LONG clock_value);
                     49: 
                     50: 
                     51: #undef  MIN
                     52: #define MIN(a, b)               (((a) < (b)) ? (a) : (b))
                     53: #undef  MAX
                     54: #define MAX(a, b)               (((a) > (b)) ? (a) : (b))
                     55: #define CRYSTAL_FREQUENCY       (14318180 * 2)
                     56: #define MIN_VCO_FREQUENCY       50000000
                     57: #define MAX_POST_SCALE          285000000
                     58: #define MAX_NUMERATOR           130
                     59: #define MAX_DENOMINATOR         MIN(129, CRYSTAL_FREQUENCY / 400000)
                     60: #define MIN_DENOMINATOR         MAX(3, CRYSTAL_FREQUENCY / 2000000)
                     61: 
                     62:   /* Set up the softswitch write value */
                     63: 
                     64: #define CLOCK(x) VideoPortWritePortUchar(CRT_DATA_REG, (UCHAR)(iotemp | (x)))
                     65: #define C_DATA  2
                     66: #define C_CLK   1
                     67: #define C_BOTH  3
                     68: #define C_NONE  0
                     69: 
                     70: /* Index register frequency ranges for ICD2061A chip */
                     71: 
                     72: static long     vclk_range[16] = {
                     73:                 0, /* should be MIN_VCO_FREQUENCY, but that causes problems. */
                     74:          51000000,
                     75:          53200000,
                     76:          58500000,
                     77:          60700000,
                     78:          64400000,
                     79:          66800000,
                     80:          73500000,
                     81:          75600000,
                     82:          80900000,
                     83:          83200000,
                     84:          91500000,
                     85:         100000000,
                     86:         120000000,
                     87:         MAX_POST_SCALE,
                     88:                 0,
                     89:         };
                     90: 
                     91: /****************************************************************************
                     92:  * calc_clock
                     93:  *
                     94:  * Usage: clock frequency [set]
                     95:  *      frequency is specified in MHz
                     96:  *
                     97:  ***************************************************************************/
                     98: long calc_clock(frequency, select)
                     99: 
                    100: register long   frequency;               /* in Hz */
                    101: int select;
                    102: {
                    103:   register long         index;
                    104:   long                  temp;
                    105:   long                  min_m, min_n, min_diff;
                    106:   long                  diff;
                    107: 
                    108:   int clock_m;
                    109:   int clock_n;
                    110:   int clock_p;
                    111: 
                    112:   min_diff = 0xFFFFFFF;
                    113:   min_n = 1;
                    114:   min_m = 1;
                    115: 
                    116:   /* Calculate 18 bit clock value */
                    117: 
                    118:   clock_p = 0;
                    119:   if (frequency < MIN_VCO_FREQUENCY)
                    120:     clock_p = 1;
                    121:   if (frequency < MIN_VCO_FREQUENCY / 2)
                    122:     clock_p = 2;
                    123:   if (frequency < MIN_VCO_FREQUENCY / 4)
                    124:     clock_p = 3;
                    125: 
                    126:   frequency <<= clock_p;
                    127: 
                    128:   for (clock_n = 4; clock_n <= MAX_NUMERATOR; clock_n++)
                    129:     {
                    130:       index = CRYSTAL_FREQUENCY / (frequency / clock_n);
                    131: 
                    132:       if (index > MAX_DENOMINATOR)
                    133:         index = MAX_DENOMINATOR;
                    134:       if (index < MIN_DENOMINATOR)
                    135:         index = MIN_DENOMINATOR;
                    136: 
                    137:       for (clock_m = index - 3; clock_m < index + 4; clock_m++)
                    138:         if (clock_m >= MIN_DENOMINATOR && clock_m <= MAX_DENOMINATOR)
                    139:           {
                    140:             diff = (CRYSTAL_FREQUENCY / clock_m) * clock_n - frequency;
                    141: 
                    142:             if (diff < 0)
                    143:               diff = -diff;
                    144: 
                    145:             if (min_m * gcd(clock_m, clock_n) / gcd(min_m, min_n) == clock_m &&
                    146:               min_n * gcd(clock_m, clock_n) / gcd(min_m, min_n) == clock_n)
                    147: 
                    148:             if (diff > min_diff)
                    149:               diff = min_diff;
                    150: 
                    151:             if (diff <= min_diff)
                    152:               {
                    153:                 min_diff = diff;
                    154:                 min_m = clock_m;
                    155:                 min_n = clock_n;
                    156:               }
                    157:           }
                    158:     }
                    159: 
                    160:   clock_m = min_m;
                    161:   clock_n = min_n;
                    162: 
                    163:   /* Calculate the index */
                    164: 
                    165:   temp = (((CRYSTAL_FREQUENCY / 2) * clock_n) / clock_m) << 1;
                    166:   for (index = 0; vclk_range[index + 1] < temp && index < 15; index++)
                    167:     ;
                    168: 
                    169:   /* Pack the clock value for the frequency snthesizer */
                    170: 
                    171:   temp = (((long)clock_n - 3) << 11) + ((clock_m - 2) << 1)
                    172:                 + (clock_p << 8) + (index << 18) + ((long)select << 22);
                    173: 
                    174:   return temp;
                    175: 
                    176: }
                    177: 
                    178: /******************************************************************************
                    179:  *
                    180:  *****************************************************************************/
                    181: VOID set_clock(
                    182:     PHW_DEVICE_EXTENSION HwDeviceExtension,
                    183:     LONG clock_value)                   /* 7bits M, 7bits N, 2bits P */
                    184: {
                    185:   register long         index;
                    186:   register char         iotemp;
                    187:   int select;
                    188: 
                    189:   select = (clock_value >> 22) & 3;
                    190: 
                    191:   /* Unlock the S3 registers */
                    192: 
                    193:   VideoPortWritePortUchar(CRT_ADDRESS_REG, LOCK_INDEX);
                    194:   VideoPortWritePortUchar(CRT_DATA_REG, UNLOCK_PATTERN);
                    195: 
                    196:   /* Shut off screen */
                    197: 
                    198:   VideoPortWritePortUchar(SEQ_ADDRESS_REG, 0x01);
                    199:   iotemp = VideoPortReadPortUchar(SEQ_DATA_REG);
                    200:   VideoPortWritePortUchar(SEQ_DATA_REG, (UCHAR)(iotemp | 0x20));
                    201: 
                    202:   /* set clock input to 11 binary */
                    203: 
                    204:   iotemp = VideoPortReadPortUchar(MISC_OUTPUT_REG_READ);
                    205:   VideoPortWritePortUchar(MISC_OUTPUT_REG_WRITE, (UCHAR)(iotemp | 0x0C));
                    206: 
                    207:   VideoPortWritePortUchar(CRT_ADDRESS_REG, SSW_WRITE_INDEX);
                    208:   VideoPortWritePortUchar(CRT_DATA_REG, 0);
                    209: 
                    210:   VideoPortWritePortUchar(CRT_ADDRESS_REG, MODE_CTRL_INDEX);
                    211:   iotemp = VideoPortReadPortUchar(CRT_DATA_REG) & 0xF0;
                    212: 
                    213: 
                    214:   /* Program the IC Designs 2061A frequency generator */
                    215: 
                    216:   CLOCK(C_NONE);
                    217: 
                    218:   /* Unlock sequence */
                    219: 
                    220:   CLOCK(C_DATA);
                    221:   for (index = 0; index < 6; index++)
                    222:     {
                    223:       CLOCK(C_BOTH);
                    224:       CLOCK(C_DATA);
                    225:     }
                    226:   CLOCK(C_NONE);
                    227:   CLOCK(C_CLK);
                    228:   CLOCK(C_NONE);
                    229:   CLOCK(C_CLK);
                    230: 
                    231:   /* Program the 24 bit value into REG0 */
                    232: 
                    233:   for (index = 0; index < 24; index++)
                    234:     {
                    235:       /* Clock in the next bit */
                    236:       clock_value >>= 1;
                    237:       if (clock_value & 1)
                    238:         {
                    239:           CLOCK(C_CLK);
                    240:           CLOCK(C_NONE);
                    241:           CLOCK(C_DATA);
                    242:           CLOCK(C_BOTH);
                    243:         }
                    244:       else
                    245:         {
                    246:           CLOCK(C_BOTH);
                    247:           CLOCK(C_DATA);
                    248:           CLOCK(C_NONE);
                    249:           CLOCK(C_CLK);
                    250:         }
                    251:     }
                    252: 
                    253:   CLOCK(C_BOTH);
                    254:   CLOCK(C_DATA);
                    255:   CLOCK(C_BOTH);
                    256: 
                    257:   /* If necessary, reprogram other ICD2061A registers to defaults */
                    258: 
                    259:   /* Select the CLOCK in the frequency synthesizer */
                    260: 
                    261:   CLOCK(C_NONE | select);
                    262: 
                    263:   /* Turn screen back on */
                    264: 
                    265:   VideoPortWritePortUchar(SEQ_ADDRESS_REG, 0x01);
                    266:   iotemp = VideoPortReadPortUchar(SEQ_DATA_REG);
                    267:   VideoPortWritePortUchar(SEQ_DATA_REG, (UCHAR) (iotemp & 0xDF));
                    268: 
                    269: }
                    270: 
                    271: /******************************************************************************
                    272:  * Number theoretic function - GCD (Greatest Common Divisor)
                    273:  *****************************************************************************/
                    274: long gcd(a, b)
                    275: register long a, b;
                    276: {
                    277:   register long c = a % b;
                    278:   while (c)
                    279:     a = b, b = c, c = a % b;
                    280:   return b;
                    281: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.