freq_adj.in revision 280849
195212Sbde#! @PATH_PERL@ -w
264880Sphk
364880Sphkdie "perl5 needed\n" unless ($] > 5);
464880Sphk
564880Sphkuse Getopt::Std;
6100206Sdduse vars qw($opt_n);
7100206Sdd
864880Sphkgetopts('d:nt:');
964880Sphk
1064880Sphk#chop($ncpu = `sysctl -n hw.ncpu`);
1164880Sphk#die "Found $ncpu CPUs; can only be run on systems with 1 CPU.\n" if ($ncpu > 1);
1264880Sphk
1364880Sphk$driftfile = "/etc/ntp.drift";
1464880Sphk$driftfile = $opt_d if defined($opt_d);
1564880Sphk
1664880Sphkchop($timer = `sysctl -n kern.timecounter.hardware 2> /dev/null`);
1764880Sphk
1864880Sphk$timer =~ tr/\U/\L/;
1964880Sphk
2064880Sphkif ($timer eq '') {
2164880Sphk  open(DM, "/var/run/dmesg.boot");
2264880Sphk  while(<DM>) {
2364880Sphk    # Timecounter "i8254"  frequency 1193182 Hz
2464880Sphk    if (/^Timecounter "(\w+)"\s+/) {
2564880Sphk      $timer = $1;
2664880Sphk      last;
2764880Sphk    }
2864880Sphk  }
2964880Sphk  close(DM);
3064880Sphk}
3164880Sphk
3264880Sphk$opt_t = $timer if !defined($opt_t);
3364880Sphk
3464880Sphkif ($timer ne '') {		# $timer found...
3564880Sphk  if ($opt_t ne  '') {		# - and $opt_t found
3664880Sphk    if ($timer ne $opt_t) {	# - - and they differ
3764880Sphk      warn "You specified a $opt_t timer but I detected a $timer timer.\n";
3864880Sphk      usage();
3965515Sphk      exit 1;
4095212Sbde    } else {			# - - and they are the same
4164880Sphk      ;
42100206Sdd    }
4364880Sphk  } else {			# - but no $opt_t specified; this is OK
4465515Sphk    ;
45100206Sdd  }
46100206Sdd} else {			# No $timer found...
47100206Sdd  if ($opt_t ne '') {		# - but $opt_t was specified
48100206Sdd    $timer = $opt_t;		# - - so use it.
49100206Sdd  } else {			# - and neither was $opt_t
50100206Sdd    warn "I can't tell what timer you have.  Please specify one.\n";
51100206Sdd    usage();
52100206Sdd    exit 1;
53100206Sdd  }
54100206Sdd}
55100206Sdd
56100206Sddopen(DF, $driftfile) || die "Can't open driftfile ($driftfile): $!\n";
57100206Sddwhile(<DF>) {
58100206Sdd    chop;
59100206Sdd    if (/^(-?\d+\.\d+)(\s\d)?$/) {
60100206Sdd	$drift = $1;
61100206Sdd    } else {
62100206Sdd	die "Bogus value in driftfile $driftfile: <$_>\n";
63100206Sdd    }
64100206Sdd}
65100206Sddclose(DF);
66100206Sdd
67100206Sddprint "NTP drift is <$drift>\n";
68100206Sdd
69100206Sdd# Convert from NTP's idea of PPM to a decimal equivalent
70100206Sdd$freq_adj = int ( $drift * ( 10 ** 6 / 2 ** 20) );
71100206Sddprint "normalized freq_adj  is <$freq_adj>\n";
72100206Sdd
73100206Sdd$freq_adj = int ( ( $freq_adj - 1 ) / 2 );
74100206Sddprint "Applying freq_adj of <".-$freq_adj.">\n";
75100206Sdd
76100206Sdd$sysctl = "machdep.".$timer."_freq";
77100206Sdd
78100206Sddchop($mach_freq = `sysctl -n $sysctl`);
79100206Sdd
80100206Sddprint "$sysctl is <$mach_freq>\n";
81100206Sdd
82100206Sdd$n_mach_freq = $mach_freq - $freq_adj;
83100206Sdd
84100206Sddif (defined($opt_n)) {
85100206Sdd  print "$sysctl $mach_freq -> $n_mach_freq\n";
86100206Sdd} else {
87100206Sdd  print "i8254: ".`sysctl -w $sysctl=$n_mach_freq`;
88100206Sdd}
89100206Sdd
90100206Sddsub usage {
91100804Sdd  print STDERR <<EOUsage
92100206SddUsage: $0 [-d drift_file] [-n] [-t timer]
93100206Sddwhere "drift_file" defaults to /etc/ntp.drift
94100206Sddand "timer" is usually "tsc" or "i8254"
95100206Sddand "-n" says "don't really change anything, just say what would happen".
96100206SddEOUsage
97100206Sdd}
98100206Sdd