base/arch/i386/calibration/calibrate-module.c
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
#include <linux/sched.h>
00020
#include <linux/module.h>
00021
#include <linux/irq.h>
00022
#include <asm/uaccess.h>
00023
#include <asm/io.h>
00024
#include <rtai_sched.h>
00025
#include <rtai_fifos.h>
00026
#include "calibrate.h"
00027
00028
MODULE_LICENSE(
"GPL");
00029
00030 #define COUNT 0xFFFFFFFFU
00031
00032 static struct params_t params = { 0,
SETUP_TIME_8254,
LATENCY_8254, 0,
LATENCY_APIC,
SETUP_TIME_APIC,
CALIBRATED_APIC_FREQ, 0,
CALIBRATED_CPU_FREQ, CLOCK_TICK_RATE, LATCH };
00033
00034 static int reset_count,
count;
00035 static struct times_t times;
00036
00037 static void calibrate(
void)
00038 {
00039
static RTIME cpu_tbase;
00040
static unsigned long apic_tbase;
00041
00042
times.
cpu_time = rd_CPU_ts();
00043
#ifdef CONFIG_X86_LOCAL_APIC
00044
if (
params.
mp) {
00045
times.
apic_time = apic_read(APIC_TMCCT);
00046 }
00047
#endif
00048
if (
times.
intrs < 0) {
00049 cpu_tbase =
times.
cpu_time;
00050 apic_tbase =
times.
apic_time;
00051 }
00052
times.
intrs++;
00053
if (++
count ==
reset_count) {
00054
count = 0;
00055
times.
cpu_time -= cpu_tbase;
00056
times.
apic_time = apic_tbase -
times.
apic_time;
00057
rtf_put(0, &
times,
sizeof(
times));
00058 }
00059
rt_pend_linux_irq(
TIMER_8254_IRQ);
00060
#ifdef CONFIG_X86_LOCAL_APIC
00061
if (
params.
mp) {
00062
unsigned temp = (apic_read(APIC_ICR) & (~0xCDFFF)) | (APIC_DM_FIXED | APIC_DEST_ALLINC | LOCAL_TIMER_VECTOR);
00063 apic_write(APIC_ICR, temp);
00064 }
00065
#endif
00066 }
00067
00068 static void just_ret(
void)
00069 {
00070
return;
00071 }
00072
00073 static RT_TASK rtask;
00074 static int period;
00075 static RTIME expected;
00076
00077 static void spv(
long loops)
00078 {
00079
int skip, average = 0;
00080
for (skip = 0; skip <
loops; skip++) {
00081
expected +=
period;
00082
rt_task_wait_period();
00083 average += (
int)
count2nano(
rt_get_time() -
expected);
00084 }
00085
rtf_put(0, &average,
sizeof(average));
00086
rt_task_suspend(0);
00087 }
00088
00089 static RTIME t0;
00090 static int bus_period,
bus_threshold,
use_parport,
loops,
maxj,
bit;
00091
00092 static int rt_timer_tick_ext(
int irq,
unsigned long data)
00093 {
00094
RTIME t;
00095
int jit;
00096
00097
if (
loops++ <
INILOOPS) {
00098
t0 =
rdtsc();
00099 }
else {
00100 t =
rdtsc();
00101
if (
use_parport) {
00102 outb(
bit = 1 -
bit,
PARPORT);
00103 }
00104
if ((jit = abs((
int)(t -
t0) -
bus_period)) >
maxj) {
00105
maxj = jit;
00106
if (
maxj >
bus_threshold) {
00107
int msg;
00108 msg =
imuldiv(
maxj, 1000000000,
CPU_FREQ);
00109
rtf_put(0, &msg,
sizeof(msg));
00110 }
00111 }
00112
t0 = t;
00113 }
00114
rt_times.tick_time =
rt_times.intr_time;
00115
rt_times.intr_time =
rt_times.tick_time +
rt_times.periodic_tick;
00116
rt_set_timer_delay(0);
00117
if (
rt_times.tick_time >=
rt_times.linux_time) {
00118
rt_times.linux_time +=
rt_times.linux_tick;
00119 hard_sti();
00120
rt_pend_linux_irq(
TIMER_8254_IRQ);
00121
return 0;
00122 }
00123 hard_sti();
00124
return 1;
00125 }
00126
00127 static long long user_srq(
unsigned long whatever)
00128 {
00129
extern int calibrate_8254(
void);
00130
unsigned long args[
MAXARGS];
00131
00132 copy_from_user(args, (
unsigned long *)whatever,
MAXARGS*
sizeof(
unsigned long));
00133
switch (args[0]) {
00134
case CAL_8254: {
00135
return calibrate_8254();
00136
break;
00137 }
00138
00139
case KLATENCY: {
00140
rt_set_oneshot_mode();
00141
period =
start_rt_timer(
nano2count(args[1]));
00142
rt_task_init_cpuid(&
rtask,
spv, args[2],
STACKSIZE, 0, 0, 0, hard_cpu_id());
00143
expected =
rt_get_time() + 100*
period;
00144
rt_task_make_periodic(&
rtask,
expected,
period);
00145
break;
00146 }
00147
00148
case END_KLATENCY: {
00149
stop_rt_timer();
00150
rt_task_delete(&
rtask);
00151
break;
00152 }
00153
00154
case FREQ_CAL: {
00155
times.
intrs = -1;
00156
reset_count = args[1]*HZ;
00157
count = 0;
00158
rt_assign_irq_to_cpu(
TIMER_8254_IRQ, 1 << hard_cpu_id());
00159
rt_request_timer(
just_ret,
COUNT, 1);
00160 rt_request_global_irq(
TIMER_8254_IRQ,
calibrate);
00161
break;
00162 }
00163
00164
case END_FREQ_CAL: {
00165
rt_free_timer();
00166
rt_reset_irq_to_sym_mode(
TIMER_8254_IRQ);
00167 rt_free_global_irq(
TIMER_8254_IRQ);
00168
break;
00169 }
00170
00171
case BUS_CHECK: {
00172
loops =
maxj = 0;
00173
bus_period =
imuldiv(args[1],
CPU_FREQ, 1000000000);
00174
bus_threshold =
imuldiv(args[2],
CPU_FREQ, 1000000000);
00175
use_parport = args[3];
00176
rt_assign_irq_to_cpu(
TIMER_8254_IRQ, 1 << hard_cpu_id());
00177
rt_request_timer((
void *)
rt_timer_tick_ext,
imuldiv(args[1],
FREQ_8254, 1000000000), 0);
00178 rt_set_global_irq_ext(
TIMER_8254_IRQ, 1, 0);
00179
break;
00180 }
00181
00182
case END_BUS_CHECK: {
00183
rt_free_timer();
00184
rt_reset_irq_to_sym_mode(
TIMER_8254_IRQ);
00185
break;
00186 }
00187
case GET_PARAMS: {
00188
rtf_put(0, &
params,
sizeof(
params));
00189
break;
00190 }
00191 }
00192
return 0;
00193 }
00194
00195 static int srq;
00196
00197 int init_module(
void)
00198 {
00199
#ifdef CONFIG_X86_LOCAL_APIC
00200
params.
mp = 1;
00201
#endif
00202
params.
freq_apic = RTAI_FREQ_APIC;
00203
params.
cpu_freq =
RTAI_CPU_FREQ;
00204
rtf_create(0,
FIFOBUFSIZE);
00205
if ((
srq =
rt_request_srq(
CALSRQ, (
void *)
user_srq,
user_srq)) < 0) {
00206
printk(
"No sysrq available for the calibration.\n");
00207
return srq;
00208 }
00209
return 0;
00210 }
00211
00212 void cleanup_module(
void)
00213 {
00214
rt_free_srq(
srq);
00215
rtf_destroy(0);
00216
return;
00217 }
Generated on Thu Nov 20 11:49:47 2008 for RTAI API by
1.3.8