1275970Scy#! @PATH_PERL@ -w
2275970Scy
3275970Scydie "perl5 needed\n" unless ($] > 5);
4275970Scy
5275970Scyuse Getopt::Std;
6275970Scyuse vars qw($opt_n);
7275970Scy
8275970Scygetopts('d:nt:');
9275970Scy
10275970Scy#chop($ncpu = `sysctl -n hw.ncpu`);
11275970Scy#die "Found $ncpu CPUs; can only be run on systems with 1 CPU.\n" if ($ncpu > 1);
12275970Scy
13275970Scy$driftfile = "/etc/ntp.drift";
14275970Scy$driftfile = $opt_d if defined($opt_d);
15275970Scy
16275970Scychop($timer = `sysctl -n kern.timecounter.hardware 2> /dev/null`);
17275970Scy
18275970Scy$timer =~ tr/\U/\L/;
19275970Scy
20275970Scyif ($timer eq '') {
21275970Scy  open(DM, "/var/run/dmesg.boot");
22275970Scy  while(<DM>) {
23275970Scy    # Timecounter "i8254"  frequency 1193182 Hz
24275970Scy    if (/^Timecounter "(\w+)"\s+/) {
25275970Scy      $timer = $1;
26275970Scy      last;
27275970Scy    }
28275970Scy  }
29275970Scy  close(DM);
30275970Scy}
31275970Scy
32275970Scy$opt_t = $timer if !defined($opt_t);
33275970Scy
34275970Scyif ($timer ne '') {		# $timer found...
35275970Scy  if ($opt_t ne  '') {		# - and $opt_t found
36275970Scy    if ($timer ne $opt_t) {	# - - and they differ
37275970Scy      warn "You specified a $opt_t timer but I detected a $timer timer.\n";
38275970Scy      usage();
39275970Scy      exit 1;
40275970Scy    } else {			# - - and they are the same
41275970Scy      ;
42275970Scy    }
43275970Scy  } else {			# - but no $opt_t specified; this is OK
44275970Scy    ;
45275970Scy  }
46275970Scy} else {			# No $timer found...
47275970Scy  if ($opt_t ne '') {		# - but $opt_t was specified
48275970Scy    $timer = $opt_t;		# - - so use it.
49275970Scy  } else {			# - and neither was $opt_t
50275970Scy    warn "I can't tell what timer you have.  Please specify one.\n";
51275970Scy    usage();
52275970Scy    exit 1;
53275970Scy  }
54275970Scy}
55275970Scy
56275970Scyopen(DF, $driftfile) || die "Can't open driftfile ($driftfile): $!\n";
57275970Scywhile(<DF>) {
58275970Scy    chop;
59275970Scy    if (/^(-?\d+\.\d+)(\s\d)?$/) {
60275970Scy	$drift = $1;
61275970Scy    } else {
62275970Scy	die "Bogus value in driftfile $driftfile: <$_>\n";
63275970Scy    }
64275970Scy}
65275970Scyclose(DF);
66275970Scy
67275970Scyprint "NTP drift is <$drift>\n";
68275970Scy
69275970Scy# Convert from NTP's idea of PPM to a decimal equivalent
70275970Scy$freq_adj = int ( $drift * ( 10 ** 6 / 2 ** 20) );
71275970Scyprint "normalized freq_adj  is <$freq_adj>\n";
72275970Scy
73275970Scy$freq_adj = int ( ( $freq_adj - 1 ) / 2 );
74275970Scyprint "Applying freq_adj of <".-$freq_adj.">\n";
75275970Scy
76275970Scy$sysctl = "machdep.".$timer."_freq";
77275970Scy
78275970Scychop($mach_freq = `sysctl -n $sysctl`);
79275970Scy
80275970Scyprint "$sysctl is <$mach_freq>\n";
81275970Scy
82275970Scy$n_mach_freq = $mach_freq - $freq_adj;
83275970Scy
84275970Scyif (defined($opt_n)) {
85275970Scy  print "$sysctl $mach_freq -> $n_mach_freq\n";
86275970Scy} else {
87275970Scy  print "i8254: ".`sysctl -w $sysctl=$n_mach_freq`;
88275970Scy}
89275970Scy
90275970Scysub usage {
91275970Scy  print STDERR <<EOUsage
92275970ScyUsage: $0 [-d drift_file] [-n] [-t timer]
93275970Scywhere "drift_file" defaults to /etc/ntp.drift
94275970Scyand "timer" is usually "tsc" or "i8254"
95275970Scyand "-n" says "don't really change anything, just say what would happen".
96275970ScyEOUsage
97275970Scy}
98