Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
6dc51b6f
Commit
6dc51b6f
authored
Apr 17, 2003
by
Alan Cox
Committed by
Linus Torvalds
Apr 17, 2003
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[PATCH] now we have the time logic in Mach_* use it
parent
1ffee2cd
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
30 additions
and
109 deletions
+30
-109
arch/i386/kernel/time.c
arch/i386/kernel/time.c
+30
-109
No files found.
arch/i386/kernel/time.c
View file @
6dc51b6f
...
@@ -55,12 +55,15 @@
...
@@ -55,12 +55,15 @@
#include <asm/processor.h>
#include <asm/processor.h>
#include <asm/timer.h>
#include <asm/timer.h>
#include <linux/mc146818rtc.h>
#include "mach_time.h"
#include <linux/timex.h>
#include <linux/timex.h>
#include <linux/config.h>
#include <linux/config.h>
#include <asm/arch_hooks.h>
#include <asm/arch_hooks.h>
#include "io_ports.h"
extern
spinlock_t
i8259A_lock
;
extern
spinlock_t
i8259A_lock
;
int
pit_latch_buggy
;
/* extern */
int
pit_latch_buggy
;
/* extern */
...
@@ -138,80 +141,13 @@ void do_settimeofday(struct timeval *tv)
...
@@ -138,80 +141,13 @@ void do_settimeofday(struct timeval *tv)
clock_was_set
();
clock_was_set
();
}
}
/* monotonic_clock(): returns # of nanoseconds passed since time_init()
* Note: This function is required to return accurate
* time even in the absence of multiple timer ticks.
*/
unsigned
long
long
monotonic_clock
(
void
)
{
return
timer
->
monotonic_clock
();
}
EXPORT_SYMBOL
(
monotonic_clock
);
/*
* In order to set the CMOS clock precisely, set_rtc_mmss has to be
* called 500 ms after the second nowtime has started, because when
* nowtime is written into the registers of the CMOS clock, it will
* jump to the next second precisely 500 ms later. Check the Motorola
* MC146818A or Dallas DS12887 data sheet for details.
*
* BUG: This routine does not handle hour overflow properly; it just
* sets the minutes. Usually you'll only notice that after reboot!
*/
static
int
set_rtc_mmss
(
unsigned
long
nowtime
)
static
int
set_rtc_mmss
(
unsigned
long
nowtime
)
{
{
int
retval
=
0
;
int
retval
;
int
real_seconds
,
real_minutes
,
cmos_minutes
;
unsigned
char
save_control
,
save_freq_select
;
/* gets recalled with irq locally disabled */
/* gets recalled with irq locally disabled */
spin_lock
(
&
rtc_lock
);
spin_lock
(
&
rtc_lock
);
save_control
=
CMOS_READ
(
RTC_CONTROL
);
/* tell the clock it's being set */
retval
=
mach_set_rtc_mmss
(
nowtime
);
CMOS_WRITE
((
save_control
|
RTC_SET
),
RTC_CONTROL
);
save_freq_select
=
CMOS_READ
(
RTC_FREQ_SELECT
);
/* stop and reset prescaler */
CMOS_WRITE
((
save_freq_select
|
RTC_DIV_RESET2
),
RTC_FREQ_SELECT
);
cmos_minutes
=
CMOS_READ
(
RTC_MINUTES
);
if
(
!
(
save_control
&
RTC_DM_BINARY
)
||
RTC_ALWAYS_BCD
)
BCD_TO_BIN
(
cmos_minutes
);
/*
* since we're only adjusting minutes and seconds,
* don't interfere with hour overflow. This avoids
* messing with unknown time zones but requires your
* RTC not to be off by more than 15 minutes
*/
real_seconds
=
nowtime
%
60
;
real_minutes
=
nowtime
/
60
;
if
(((
abs
(
real_minutes
-
cmos_minutes
)
+
15
)
/
30
)
&
1
)
real_minutes
+=
30
;
/* correct for half hour time zone */
real_minutes
%=
60
;
if
(
abs
(
real_minutes
-
cmos_minutes
)
<
30
)
{
if
(
!
(
save_control
&
RTC_DM_BINARY
)
||
RTC_ALWAYS_BCD
)
{
BIN_TO_BCD
(
real_seconds
);
BIN_TO_BCD
(
real_minutes
);
}
CMOS_WRITE
(
real_seconds
,
RTC_SECONDS
);
CMOS_WRITE
(
real_minutes
,
RTC_MINUTES
);
}
else
{
printk
(
KERN_WARNING
"set_rtc_mmss: can't update from %d to %d
\n
"
,
cmos_minutes
,
real_minutes
);
retval
=
-
1
;
}
/* The following flags have to be released exactly in this order,
* otherwise the DS12887 (popular MC146818A clone with integrated
* battery and quartz) will not reset the oscillator and will not
* update precisely 500 ms later. You won't find this mentioned in
* the Dallas Semiconductor data sheets, but who believes data
* sheets anyway ... -- Markus Kuhn
*/
CMOS_WRITE
(
save_control
,
RTC_CONTROL
);
CMOS_WRITE
(
save_freq_select
,
RTC_FREQ_SELECT
);
spin_unlock
(
&
rtc_lock
);
spin_unlock
(
&
rtc_lock
);
return
retval
;
return
retval
;
...
@@ -222,6 +158,17 @@ static long last_rtc_update;
...
@@ -222,6 +158,17 @@ static long last_rtc_update;
int
timer_ack
;
int
timer_ack
;
/* monotonic_clock(): returns # of nanoseconds passed since time_init()
* Note: This function is required to return accurate
* time even in the absence of multiple timer ticks.
*/
unsigned
long
long
monotonic_clock
(
void
)
{
return
timer
->
monotonic_clock
();
}
EXPORT_SYMBOL
(
monotonic_clock
);
/*
/*
* timer_interrupt() needs to keep up the real-time clock,
* timer_interrupt() needs to keep up the real-time clock,
* as well as call the "do_timer()" routine every clocktick
* as well as call the "do_timer()" routine every clocktick
...
@@ -237,9 +184,9 @@ static inline void do_timer_interrupt(int irq, void *dev_id, struct pt_regs *reg
...
@@ -237,9 +184,9 @@ static inline void do_timer_interrupt(int irq, void *dev_id, struct pt_regs *reg
* on an 82489DX-based system.
* on an 82489DX-based system.
*/
*/
spin_lock
(
&
i8259A_lock
);
spin_lock
(
&
i8259A_lock
);
outb
(
0x0c
,
0x20
);
outb
(
0x0c
,
PIC_MASTER_OCW3
);
/* Ack the IRQ; AEOI will end it automatically. */
/* Ack the IRQ; AEOI will end it automatically. */
inb
(
0x20
);
inb
(
PIC_MASTER_POLL
);
spin_unlock
(
&
i8259A_lock
);
spin_unlock
(
&
i8259A_lock
);
}
}
#endif
#endif
...
@@ -253,14 +200,16 @@ static inline void do_timer_interrupt(int irq, void *dev_id, struct pt_regs *reg
...
@@ -253,14 +200,16 @@ static inline void do_timer_interrupt(int irq, void *dev_id, struct pt_regs *reg
*/
*/
if
((
time_status
&
STA_UNSYNC
)
==
0
&&
if
((
time_status
&
STA_UNSYNC
)
==
0
&&
xtime
.
tv_sec
>
last_rtc_update
+
660
&&
xtime
.
tv_sec
>
last_rtc_update
+
660
&&
(
xtime
.
tv_nsec
/
1000
)
>=
500000
-
((
unsigned
)
TICK_SIZE
)
/
2
&&
(
xtime
.
tv_nsec
/
1000
)
(
xtime
.
tv_nsec
/
1000
)
<=
500000
+
((
unsigned
)
TICK_SIZE
)
/
2
)
{
>=
USEC_AFTER
-
((
unsigned
)
TICK_SIZE
)
/
2
&&
(
xtime
.
tv_nsec
/
1000
)
<=
USEC_BEFORE
+
((
unsigned
)
TICK_SIZE
)
/
2
)
{
if
(
set_rtc_mmss
(
xtime
.
tv_sec
)
==
0
)
if
(
set_rtc_mmss
(
xtime
.
tv_sec
)
==
0
)
last_rtc_update
=
xtime
.
tv_sec
;
last_rtc_update
=
xtime
.
tv_sec
;
else
else
last_rtc_update
=
xtime
.
tv_sec
-
600
;
/* do it again in 60 s */
last_rtc_update
=
xtime
.
tv_sec
-
600
;
/* do it again in 60 s */
}
}
#ifdef CONFIG_MCA
#ifdef CONFIG_MCA
if
(
MCA_bus
)
{
if
(
MCA_bus
)
{
/* The PS/2 uses level-triggered interrupts. You can't
/* The PS/2 uses level-triggered interrupts. You can't
...
@@ -341,43 +290,15 @@ void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
...
@@ -341,43 +290,15 @@ void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
/* not static: needed by APM */
/* not static: needed by APM */
unsigned
long
get_cmos_time
(
void
)
unsigned
long
get_cmos_time
(
void
)
{
{
unsigned
int
year
,
mon
,
day
,
hour
,
min
,
sec
;
unsigned
long
retval
;
int
i
;
spin_lock
(
&
rtc_lock
);
spin_lock
(
&
rtc_lock
);
/* The Linux interpretation of the CMOS clock register contents:
* When the Update-In-Progress (UIP) flag goes from 1 to 0, the
retval
=
mach_get_cmos_time
();
* RTC registers show the second which has precisely just started.
* Let's hope other operating systems interpret the RTC the same way.
*/
/* read RTC exactly on falling edge of update flag */
for
(
i
=
0
;
i
<
1000000
;
i
++
)
/* may take up to 1 second... */
if
(
CMOS_READ
(
RTC_FREQ_SELECT
)
&
RTC_UIP
)
break
;
for
(
i
=
0
;
i
<
1000000
;
i
++
)
/* must try at least 2.228 ms */
if
(
!
(
CMOS_READ
(
RTC_FREQ_SELECT
)
&
RTC_UIP
))
break
;
do
{
/* Isn't this overkill ? UIP above should guarantee consistency */
sec
=
CMOS_READ
(
RTC_SECONDS
);
min
=
CMOS_READ
(
RTC_MINUTES
);
hour
=
CMOS_READ
(
RTC_HOURS
);
day
=
CMOS_READ
(
RTC_DAY_OF_MONTH
);
mon
=
CMOS_READ
(
RTC_MONTH
);
year
=
CMOS_READ
(
RTC_YEAR
);
}
while
(
sec
!=
CMOS_READ
(
RTC_SECONDS
));
if
(
!
(
CMOS_READ
(
RTC_CONTROL
)
&
RTC_DM_BINARY
)
||
RTC_ALWAYS_BCD
)
{
BCD_TO_BIN
(
sec
);
BCD_TO_BIN
(
min
);
BCD_TO_BIN
(
hour
);
BCD_TO_BIN
(
day
);
BCD_TO_BIN
(
mon
);
BCD_TO_BIN
(
year
);
}
spin_unlock
(
&
rtc_lock
);
spin_unlock
(
&
rtc_lock
);
if
((
year
+=
1900
)
<
1970
)
year
+=
100
;
return
retval
;
return
mktime
(
year
,
mon
,
day
,
hour
,
min
,
sec
);
}
}
/* XXX this driverfs stuff should probably go elsewhere later -john */
/* XXX this driverfs stuff should probably go elsewhere later -john */
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment