patch-2.4.20 linux-2.4.20/drivers/char/ftape/lowlevel/ftape-calibr.c
Next file: linux-2.4.20/drivers/char/generic_serial.c
Previous file: linux-2.4.20/drivers/char/ftape/Config.in
Back to the patch index
Back to the overall index
- Lines: 194
- Date:
Thu Nov 28 15:53:12 2002
- Orig file:
linux-2.4.19/drivers/char/ftape/lowlevel/ftape-calibr.c
- Orig date:
Fri Sep 14 14:40:00 2001
diff -urN linux-2.4.19/drivers/char/ftape/lowlevel/ftape-calibr.c linux-2.4.20/drivers/char/ftape/lowlevel/ftape-calibr.c
@@ -31,7 +31,10 @@
#include <asm/io.h>
#if defined(__alpha__)
# include <asm/hwrpb.h>
-#elif defined(__i386__) || defined(__x86_64__)
+#elif defined(__x86_64__)
+# include <asm/msr.h>
+# include <asm/timex.h>
+#elif defined(__i386__)
# include <linux/timex.h>
#endif
#include <linux/ftape.h>
@@ -45,10 +48,14 @@
# error Ftape is not implemented for this architecture!
#endif
-#if defined(__alpha__)
+#if defined(__alpha__) || defined(__x86_64__)
static unsigned long ps_per_cycle = 0;
#endif
+#if defined(__i386__)
+extern spinlock_t i8253_lock;
+#endif
+
/*
* Note: On Intel PCs, the clock ticks at 100 Hz (HZ==100) which is
* too slow for certain timeouts (and that clock doesn't even tick
@@ -67,48 +74,58 @@
{
#if defined(__alpha__)
unsigned long r;
-
asm volatile ("rpcc %0" : "=r" (r));
return r;
-#elif defined(__i386__) || defined(__x86_64__)
+#elif defined(__x86_64__)
+ unsigned long r;
+ rdtscl(r);
+ return r;
+#elif defined(__i386__)
+
+/*
+ * Note that there is some time between counter underflowing and jiffies
+ * increasing, so the code below won't always give correct output.
+ * -Vojtech
+ */
+
unsigned long flags;
__u16 lo;
__u16 hi;
- save_flags(flags);
- cli();
+ spin_lock_irqsave(&i8253_lock, flags);
outb_p(0x00, 0x43); /* latch the count ASAP */
lo = inb_p(0x40); /* read the latched count */
lo |= inb(0x40) << 8;
hi = jiffies;
- restore_flags(flags);
+ spin_unlock_irqrestore(&i8253_lock, flags);
+
return ((hi + 1) * (unsigned int) LATCH) - lo; /* downcounter ! */
#endif
}
static unsigned int short_ftape_timestamp(void)
{
-#if defined(__alpha__)
+#if defined(__alpha__) || defined(__x86_64__)
return ftape_timestamp();
-#elif defined(__i386__) || defined(__x86_64__)
+#elif defined(__i386__)
unsigned int count;
unsigned long flags;
- save_flags(flags);
- cli();
+ spin_lock_irqsave(&i8253_lock, flags);
outb_p(0x00, 0x43); /* latch the count ASAP */
count = inb_p(0x40); /* read the latched count */
count |= inb(0x40) << 8;
- restore_flags(flags);
+ spin_unlock_irqrestore(&i8253_lock, flags);
+
return (LATCH - count); /* normal: downcounter */
#endif
}
static unsigned int diff(unsigned int t0, unsigned int t1)
{
-#if defined(__alpha__)
- return (t1 <= t0) ? t1 + (1UL << 32) - t0 : t1 - t0;
-#elif defined(__i386__) || defined(__x86_64__)
+#if defined(__alpha__) || defined(__x86_64__)
+ return (t1 - t0);
+#elif defined(__i386__)
/*
* This is tricky: to work for both short and full ftape_timestamps
* we'll have to discriminate between these.
@@ -122,9 +139,9 @@
static unsigned int usecs(unsigned int count)
{
-#if defined(__alpha__)
+#if defined(__alpha__) || defined(__x86_64__)
return (ps_per_cycle * count) / 1000000UL;
-#elif defined(__i386__) || defined(__x86_64__)
+#elif defined(__i386__)
return (10000 * count) / ((CLOCK_TICK_RATE + 50) / 100);
#endif
}
@@ -153,49 +170,24 @@
save_flags(flags);
cli();
t0 = short_ftape_timestamp();
- for (i = 0; i < 1000; ++i) {
+ for (i = 0; i < 1000; ++i)
status = inb(fdc.msr);
- }
t1 = short_ftape_timestamp();
restore_flags(flags);
+
TRACE(ft_t_info, "inb() duration: %d nsec", ftape_timediff(t0, t1));
TRACE_EXIT;
}
static void init_clock(void)
{
-#if defined(__i386__) || defined(__x86_64__)
- unsigned int t;
- int i;
TRACE_FUN(ft_t_any);
- /* Haven't studied on why, but there sometimes is a problem
- * with the tick timer readout. The two bytes get swapped.
- * This hack solves that problem by doing one extra input.
- */
- for (i = 0; i < 1000; ++i) {
- t = short_ftape_timestamp();
- if (t > LATCH) {
- inb_p(0x40); /* get in sync again */
- TRACE(ft_t_warn, "clock counter fixed");
- break;
- }
- }
+#if defined(__x86_64__)
+ ps_per_cycle = 1000000000UL / cpu_khz;
#elif defined(__alpha__)
-#if CONFIG_FT_ALPHA_CLOCK == 0
-#error You must define and set CONFIG_FT_ALPHA_CLOCK in 'make config' !
-#endif
extern struct hwrpb_struct *hwrpb;
- TRACE_FUN(ft_t_any);
-
- if (hwrpb->cycle_freq != 0) {
ps_per_cycle = (1000*1000*1000*1000UL) / hwrpb->cycle_freq;
- } else {
- /*
- * HELP: Linux 2.0.x doesn't set cycle_freq on my noname !
- */
- ps_per_cycle = (1000*1000*1000*1000UL) / CONFIG_FT_ALPHA_CLOCK;
- }
#endif
TRACE_EXIT;
}
@@ -214,7 +206,7 @@
unsigned int tc = 0;
unsigned int count;
unsigned int time;
-#if defined(__i386__) || defined(__x86_64__)
+#if defined(__i386__)
unsigned int old_tc = 0;
unsigned int old_count = 1;
unsigned int old_time = 1;
@@ -257,15 +249,14 @@
tc = (1000 * time) / (count - 1);
TRACE(ft_t_any, "once:%3d us,%6d times:%6d us, TC:%5d ns",
usecs(once), count - 1, usecs(multiple), tc);
-#if defined(__alpha__)
+#if defined(__alpha__) || defined(__x86_64__)
/*
* Increase the calibration count exponentially until the
* calibration time exceeds 100 ms.
*/
- if (time >= 100*1000) {
+ if (time >= 100*1000)
break;
- }
-#elif defined(__i386__) || defined(__x86_64__)
+#elif defined(__i386__)
/*
* increase the count until the resulting time nears 2/HZ,
* then the tc will drop sharply because we lose LATCH counts.
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)