|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * The contents of this file constitute Original Code as defined in and ! 7: * are subject to the Apple Public Source License Version 1.1 (the ! 8: * "License"). You may not use this file except in compliance with the ! 9: * License. Please obtain a copy of the License at ! 10: * http://www.apple.com/publicsource and read it before using this file. ! 11: * ! 12: * This Original Code and all software distributed under the License are ! 13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 17: * License for the specific language governing rights and limitations ! 18: * under the License. ! 19: * ! 20: * @APPLE_LICENSE_HEADER_END@ ! 21: */ ! 22: /* ! 23: * clock_speed.c - Determine the best guess for the processor and bus ! 24: * speed buy using the values returned by run_clock_test. ! 25: * ! 26: * (c) Apple Computer, Inc. 1998-9 ! 27: * ! 28: * Writen by: Josh de Cesare ! 29: * ! 30: */ ! 31: ! 32: ! 33: #include <ppc/machine_routines.h> ! 34: ! 35: #include <pexpert/ppc/powermac.h> ! 36: ! 37: // prototypes ! 38: extern void pe_run_clock_test(void *tmp); ! 39: void pe_do_clock_test(unsigned int via_addr, ! 40: int num_speeds, unsigned long *speed_list); ! 41: ! 42: // Threshold for bus speed matches. ! 43: #define kMaxFreqDiff (30000) ! 44: ! 45: // This is the structure for the data that get passed to pe_run_clock_test. ! 46: struct clock_test_data { ! 47: unsigned int via_addr; ! 48: unsigned int via_ticks; ! 49: unsigned int dec_ticks; ! 50: }; ! 51: ! 52: // glocal variables to simplify some stuff. ! 53: static long bus_freq_num, bus_freq_den, cpu_pll; ! 54: ! 55: // PE_Determine_Clock_Speeds is called by the via driver in IOKit ! 56: // It uses the numbers generated by pe_do_clock_test and reports ! 57: // the cleaned up values to the rest of the OS. ! 58: void PE_Determine_Clock_Speeds(unsigned int via_addr, int num_speeds, ! 59: unsigned long *speed_list) ! 60: { ! 61: boolean_t oldLevel; ! 62: ! 63: oldLevel = ml_set_interrupts_enabled(FALSE); ! 64: pe_do_clock_test(via_addr, num_speeds, speed_list); ! 65: ml_set_interrupts_enabled(oldLevel); ! 66: ! 67: // Report the bus clock rate as is. ! 68: powermac_info.bus_clock_rate_num = bus_freq_num; ! 69: powermac_info.bus_clock_rate_den = bus_freq_den; ! 70: ! 71: // pll multipliers are in halfs so set the denominator to 2. ! 72: powermac_info.bus_to_cpu_rate_num = cpu_pll; ! 73: powermac_info.bus_to_cpu_rate_den = 2; ! 74: ! 75: // The decrementer rate is one fourth the bus rate. ! 76: powermac_info.bus_to_dec_rate_num = 1; ! 77: powermac_info.bus_to_dec_rate_den = 4; ! 78: ! 79: PE_call_timebase_callback(); ! 80: } ! 81: ! 82: // pe_do_clock_test uses the number from pe_run_clock_test to ! 83: // find a best fit guess for the bus speed. ! 84: void pe_do_clock_test(unsigned int via_addr, ! 85: int num_speeds, unsigned long *speed_list) ! 86: { ! 87: struct clock_test_data clock_test_data; ! 88: long cnt, diff, raw_cpu_freq, raw_bus_freq, tmp_bus_freq, ! 89: last_bus_freq, tries = 10; ! 90: ! 91: // Save the via addr so the asm part can use it. ! 92: clock_test_data.via_addr = via_addr; ! 93: ! 94: // Keep looping until it matches the last try. ! 95: bus_freq_num = 0; ! 96: do { ! 97: last_bus_freq = bus_freq_num; ! 98: ! 99: // The the asm part to do the real work. ! 100: pe_run_clock_test((void *)&clock_test_data); ! 101: ! 102: // First find the pll mode. Allow any integer times two. ! 103: cpu_pll = 10000000 / clock_test_data.dec_ticks; ! 104: cpu_pll = (cpu_pll / 2) + (cpu_pll & 1); ! 105: ! 106: // Using 64 bit math figure out the raw bus speed. ! 107: // 0xBF401675E5DULL is 1 / 1.27655us times 2 ^ 24. ! 108: raw_bus_freq = ((0xBF401675E5DULL * clock_test_data.dec_ticks) / ! 109: clock_test_data.via_ticks) >> 22; ! 110: ! 111: // use the pll mode and the raw bus speed to find the raw cpu speed. ! 112: raw_cpu_freq = raw_bus_freq * cpu_pll / 2; ! 113: ! 114: // Look to see if the bus speed is close to one of the ! 115: // speeds in the table. ! 116: for (cnt = 0; cnt < num_speeds; cnt++) { ! 117: bus_freq_num = speed_list[cnt * 2]; ! 118: bus_freq_den = speed_list[cnt * 2 + 1]; ! 119: diff = bus_freq_num - raw_bus_freq * bus_freq_den; ! 120: if (diff < 0) diff = -diff; ! 121: ! 122: if (diff < kMaxFreqDiff * bus_freq_den) break; ! 123: } ! 124: if (cnt != num_speeds) continue; ! 125: ! 126: // Look to see if the bus speed is close to n * 0.5 MHz ! 127: tmp_bus_freq = ((raw_bus_freq + 250000) / 500000) * 500000; ! 128: ! 129: diff = tmp_bus_freq - raw_bus_freq; ! 130: if (diff < 0) diff = -diff; ! 131: ! 132: if (diff < kMaxFreqDiff) { ! 133: bus_freq_num = tmp_bus_freq; ! 134: bus_freq_den = 1; ! 135: continue; ! 136: } ! 137: ! 138: // Look to see if the bus speed is close to n * 50/3 MHz ! 139: tmp_bus_freq = ((raw_bus_freq * 3 + 25000000) / 50000000) * 50000000; ! 140: ! 141: diff = tmp_bus_freq - raw_bus_freq * 3; ! 142: if (diff < 0) diff = -diff; ! 143: ! 144: if (diff < kMaxFreqDiff * 3) { ! 145: bus_freq_num = tmp_bus_freq; ! 146: bus_freq_den = 3; ! 147: continue; ! 148: } ! 149: ! 150: // Since all else failed return the raw bus speed ! 151: bus_freq_num = raw_bus_freq; ! 152: bus_freq_den = 1; ! 153: } while ((bus_freq_num != last_bus_freq) && tries--); ! 154: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.