Upload Tizen:Base source
[framework/base/util-linux-ng.git] / hwclock / kd.c
1 /* kd.c - KDGHWCLK stuff, possibly m68k only - deprecated */
2
3 #include "clock.h"
4
5 #ifndef __m68k__
6
7 struct clock_ops *
8 probe_for_kd_clock() {
9         return NULL;
10 }
11
12 #else /* __m68k__ */
13
14 #include <unistd.h>             /* for close() */
15 #include <fcntl.h>              /* for O_RDONLY */
16 #include <sysexits.h>
17 #include <sys/ioctl.h>
18
19 #include "nls.h"
20
21 static int con_fd = -1;         /* opened by probe_for_kd_clock() */
22                                 /* never closed */
23 static char *con_fd_filename;   /* usually "/dev/tty1" */
24
25 /* Get defines for KDGHWCLK and KDSHWCLK (m68k) */
26 #include <linux/kd.h>
27 #ifndef KDGHWCLK
28 #define KDGHWCLK        0x4B50     /* get hardware clock */
29 #define KDSHWCLK        0x4B51     /* set hardware clock */
30 struct hwclk_time {
31         unsigned        sec;    /* 0..59 */
32         unsigned        min;    /* 0..59 */
33         unsigned        hour;   /* 0..23 */
34         unsigned        day;    /* 1..31 */
35         unsigned        mon;    /* 0..11 */
36         unsigned        year;   /* 70... */
37         int             wday;   /* 0..6, 0 is Sunday, -1 means unknown/don't set */
38 };
39 #endif
40
41 static int
42 synchronize_to_clock_tick_kd(void) {
43 /*----------------------------------------------------------------------------
44    Wait for the top of a clock tick by calling KDGHWCLK in a busy loop until
45    we see it.
46 -----------------------------------------------------------------------------*/
47   int i;
48
49   /* The time when we were called (and started waiting) */
50   struct hwclk_time start_time, nowtime;
51
52   if (debug)
53     printf(_("Waiting in loop for time from KDGHWCLK to change\n"));
54
55   if (ioctl(con_fd, KDGHWCLK, &start_time) == -1) {
56     outsyserr(_("KDGHWCLK ioctl to read time failed"));
57     return 3;
58   }
59
60   i = 0;
61   do {
62     /* Added by Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de> */
63     /* "The culprit is the fast loop with KDGHWCLK ioctls. It seems
64        the kernel gets confused by those on Amigas with A2000 RTCs
65        and simply hangs after some time. Inserting a nanosleep helps." */
66     /* Christian T. Steigies: 1 instead of 1000000 is still sufficient
67        to keep the machine from freezing. */
68
69 #ifdef HAVE_NANOSLEEP
70     struct timespec xsleep = { 0, 1 };
71     nanosleep( &xsleep, NULL );
72 #else
73     usleep(1);
74 #endif
75
76     if (i++ >= 1000000) {
77       fprintf(stderr, _("Timed out waiting for time change.\n"));
78       return 2;
79     }
80     if (ioctl(con_fd, KDGHWCLK, &nowtime) == -1) {
81       outsyserr(_("KDGHWCLK ioctl to read time failed in loop"));
82       return 3;
83     }
84   } while (start_time.sec == nowtime.sec);
85
86   return 0;
87 }
88
89
90 static int
91 read_hardware_clock_kd(struct tm *tm) {
92 /*----------------------------------------------------------------------------
93   Read the hardware clock and return the current time via <tm>
94   argument.  Use ioctls to /dev/tty1 on what we assume is an m68k
95   machine.
96
97   Note that we don't use /dev/console here.  That might be a serial
98   console.
99 -----------------------------------------------------------------------------*/
100   struct hwclk_time t;
101
102   if (ioctl(con_fd, KDGHWCLK, &t) == -1) {
103     outsyserr(_("ioctl() failed to read time from %s"), con_fd_filename);
104     hwclock_exit(EX_IOERR);
105   }
106
107   tm->tm_sec  = t.sec;
108   tm->tm_min  = t.min;
109   tm->tm_hour = t.hour;
110   tm->tm_mday = t.day;
111   tm->tm_mon  = t.mon;
112   tm->tm_year = t.year;
113   tm->tm_wday = t.wday;
114   tm->tm_isdst = -1;     /* Don't know if it's Daylight Savings Time */
115
116   return 0;
117 }
118
119
120 static int
121 set_hardware_clock_kd(const struct tm *new_broken_time) {
122 /*----------------------------------------------------------------------------
123   Set the Hardware Clock to the time <new_broken_time>.  Use ioctls to
124   /dev/tty1 on what we assume is an m68k machine.
125
126   Note that we don't use /dev/console here.  That might be a serial console.
127 ----------------------------------------------------------------------------*/
128   struct hwclk_time t;
129
130   t.sec  = new_broken_time->tm_sec;
131   t.min  = new_broken_time->tm_min;
132   t.hour = new_broken_time->tm_hour;
133   t.day  = new_broken_time->tm_mday;
134   t.mon  = new_broken_time->tm_mon;
135   t.year = new_broken_time->tm_year;
136   t.wday = new_broken_time->tm_wday;
137
138   if (ioctl(con_fd, KDSHWCLK, &t ) == -1) {
139     outsyserr(_("ioctl KDSHWCLK failed"));
140     hwclock_exit(1);
141   }
142   return 0;
143 }
144
145 static int
146 get_permissions_kd(void) {
147   return 0;
148 }
149
150 static struct clock_ops kd = {
151         "KDGHWCLK interface to m68k clock",
152         get_permissions_kd,
153         read_hardware_clock_kd,
154         set_hardware_clock_kd,
155         synchronize_to_clock_tick_kd,
156 };
157
158 /* return &kd if KDGHWCLK works, NULL otherwise */
159 struct clock_ops *
160 probe_for_kd_clock() {
161         struct clock_ops *ret = NULL;
162         struct hwclk_time t;
163
164         if (con_fd < 0) {       /* first time here */
165                 con_fd_filename = "/dev/tty1";
166                 con_fd = open(con_fd_filename, O_RDONLY);
167         }
168         if (con_fd < 0) {
169                 /* perhaps they are using devfs? */
170                 con_fd_filename = "/dev/vc/1";
171                 con_fd = open(con_fd_filename, O_RDONLY);
172         }
173         if (con_fd < 0) {
174                 /* probably KDGHWCLK exists on m68k only */
175                 outsyserr(_("Can't open /dev/tty1 or /dev/vc/1"));
176         } else {
177                 if (ioctl(con_fd, KDGHWCLK, &t) == -1) {
178                         if (errno != EINVAL)
179                                 outsyserr(_("KDGHWCLK ioctl failed"));
180                 } else
181                         ret = &kd;
182         }
183         return ret;
184 }
185 #endif /* __m68k__ */