1 | /* qemu-time.c -- stubs so clock can be linked in. |
---|
2 | * |
---|
3 | * Copyright (c) 2008 Anthony Green |
---|
4 | * |
---|
5 | * The authors hereby grant permission to use, copy, modify, distribute, |
---|
6 | * and license this software and its documentation for any purpose, provided |
---|
7 | * that existing copyright notices are retained in all copies and that this |
---|
8 | * notice is included verbatim in any distributions. No written agreement, |
---|
9 | * license, or royalty fee is required for any of the authorized uses. |
---|
10 | * Modifications to this software may be copyrighted by their authors |
---|
11 | * and need not follow the licensing terms described here, provided that |
---|
12 | * the new terms are clearly indicated on the first page of each file where |
---|
13 | * they apply. |
---|
14 | */ |
---|
15 | #include <errno.h> |
---|
16 | #include <time.h> |
---|
17 | #include <sys/time.h> |
---|
18 | #include <sys/times.h> |
---|
19 | #include "glue.h" |
---|
20 | |
---|
21 | /* This is the base address of the mc146818 RTC i/o port. */ |
---|
22 | #define RTC_PORT 0x400 |
---|
23 | |
---|
24 | #define RTC_SECONDS 0x00 |
---|
25 | #define RTC_SECONDS_ALARM 0x01 |
---|
26 | #define RTC_MINUTES 0x02 |
---|
27 | #define RTC_MINUTES_ALARM 0x03 |
---|
28 | #define RTC_HOURS 0x04 |
---|
29 | #define RTC_HOURS_ALARM 0x05 |
---|
30 | #define RTC_DAY_OF_WEEK 0x06 |
---|
31 | #define RTC_DATE_OF_MONTH 0x07 |
---|
32 | #define RTC_MONTH 0x08 |
---|
33 | #define RTC_YEAR 0x09 |
---|
34 | #define RTC_CONFIG_A 0x0A |
---|
35 | #define RTC_CONFIG_B 0x0B |
---|
36 | #define RTC_CONFIG_C 0x0C |
---|
37 | #define RTC_CONFIG_D 0x0D |
---|
38 | |
---|
39 | /* |
---|
40 | * _times -- FIXME |
---|
41 | */ |
---|
42 | int |
---|
43 | _times (struct tms *buf) |
---|
44 | { |
---|
45 | errno = EINVAL; |
---|
46 | return (-1); |
---|
47 | } |
---|
48 | |
---|
49 | /* Read a value from the RTC port. */ |
---|
50 | static unsigned char |
---|
51 | rtc_read (unsigned char reg) |
---|
52 | { |
---|
53 | *(volatile unsigned char *)(RTC_PORT) = reg; |
---|
54 | return *(volatile unsigned char *)(RTC_PORT + 1); |
---|
55 | } |
---|
56 | |
---|
57 | /* Write a value to the RTC port. */ |
---|
58 | static void |
---|
59 | rtc_write (unsigned char reg, unsigned char val) |
---|
60 | { |
---|
61 | *(volatile unsigned char *)(RTC_PORT) = reg; |
---|
62 | *(volatile unsigned char *)(RTC_PORT + 1) = val; |
---|
63 | } |
---|
64 | |
---|
65 | /* Convert BCD to Decimal. */ |
---|
66 | #define BCD2DEC(BYTE) ((((BYTE >> 4) & 0xF) * 10) + (BYTE & 0xF)) |
---|
67 | |
---|
68 | /* |
---|
69 | * time -- return current time in seconds. |
---|
70 | */ |
---|
71 | time_t |
---|
72 | time (time_t *t) |
---|
73 | { |
---|
74 | struct tm tm; |
---|
75 | time_t ret; |
---|
76 | |
---|
77 | tm.tm_sec = BCD2DEC(rtc_read(RTC_SECONDS)); |
---|
78 | tm.tm_min = BCD2DEC(rtc_read(RTC_MINUTES)); |
---|
79 | tm.tm_hour = BCD2DEC(rtc_read(RTC_HOURS)); |
---|
80 | tm.tm_wday = BCD2DEC(rtc_read(RTC_DAY_OF_WEEK)) - 1; |
---|
81 | tm.tm_mday = BCD2DEC(rtc_read(RTC_DATE_OF_MONTH)); |
---|
82 | tm.tm_mon = BCD2DEC(rtc_read(RTC_MONTH)) - 1; |
---|
83 | tm.tm_year = BCD2DEC(rtc_read(RTC_YEAR)) + 100; |
---|
84 | |
---|
85 | /* FIXME. Not really sure how to handle this. */ |
---|
86 | tm.tm_isdst = 1; |
---|
87 | |
---|
88 | ret = mktime(&tm); |
---|
89 | |
---|
90 | if (t) |
---|
91 | *t = ret; |
---|
92 | |
---|
93 | return ret; |
---|
94 | } |
---|
95 | |
---|
96 | /* |
---|
97 | * _gettimeofday -- implement in terms of time, which means we can't |
---|
98 | * return the microseconds. |
---|
99 | */ |
---|
100 | int |
---|
101 | _gettimeofday (struct timeval *tv, |
---|
102 | void *tzvp) |
---|
103 | { |
---|
104 | struct timezone *tz = tzvp; |
---|
105 | struct tm tm; |
---|
106 | if (tz) |
---|
107 | tz->tz_minuteswest = tz->tz_dsttime = 0; |
---|
108 | |
---|
109 | tv->tv_usec = 0; |
---|
110 | tv->tv_sec = time(0); |
---|
111 | |
---|
112 | return 0; |
---|
113 | } |
---|