Annotation of XNU/pexpert/ppc/pe_clock_speed.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

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