|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.