source: mainline/uspace/drv/time/cmos-rtc/cmos-rtc.c@ 8d2963d

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 8d2963d was 8d2963d, checked in by Maurizio Lombardi <m.lombardi85@…>, 14 years ago

rtc: replace time_t with the new tm structure

  • Property mode set to 100644
File size: 7.1 KB
Line 
1/*
2 * Copyright (c) 2012 Maurizio Lombardi
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/**
30 * @defgroup CMOS RTC driver.
31 * @brief HelenOS RTC driver.
32 * @{
33 */
34
35/** @file
36 */
37
38#include <errno.h>
39#include <ddi.h>
40#include <stdio.h>
41#include <ddf/driver.h>
42#include <ddf/log.h>
43#include <ops/clock.h>
44#include <fibril_synch.h>
45#include <device/hw_res.h>
46#include <devman.h>
47
48#define NAME "cmos-rtc"
49
50#define REG_COUNT 2
51
52typedef struct rtc {
53 /** DDF device node */
54 ddf_dev_t *dev;
55 /** DDF function node */
56 ddf_fun_t *fun;
57 /** The fibril mutex for synchronizing the access to the device */
58 fibril_mutex_t mutex;
59 /** The base I/O address of the device registers */
60 uint32_t io_addr;
61 /** The I/O port used to access the CMOS registers */
62 ioport8_t *port;
63} rtc_t;
64
65
66static int
67rtc_time_get(ddf_fun_t *fun, struct tm *t);
68
69static int
70rtc_time_set(ddf_fun_t *fun, struct tm *t);
71
72static int
73rtc_dev_add(ddf_dev_t *dev);
74
75static int
76rtc_dev_initialize(rtc_t *rtc);
77
78static bool
79rtc_pio_enable(rtc_t *rtc);
80
81static void
82rtc_dev_cleanup(rtc_t *rtc);
83
84
85static ddf_dev_ops_t rtc_dev_ops;
86
87/** The RTC device driver's standard operations */
88static driver_ops_t rtc_ops = {
89 .dev_add = rtc_dev_add,
90 .dev_remove = NULL, /* XXX */
91};
92
93/** The RTC device driver structure */
94static driver_t rtc_driver = {
95 .name = NAME,
96 .driver_ops = &rtc_ops,
97};
98
99/** Clock interface */
100static clock_dev_ops_t rtc_clock_dev_ops = {
101 .time_get = rtc_time_get,
102 .time_set = rtc_time_set,
103};
104
105/** Initialize the RTC driver */
106static void
107rtc_init(void)
108{
109 ddf_log_init(NAME, LVL_ERROR);
110
111 rtc_dev_ops.open = NULL; /* XXX */
112 rtc_dev_ops.close = NULL; /* XXX */
113
114 rtc_dev_ops.interfaces[CLOCK_DEV_IFACE] = &rtc_clock_dev_ops;
115 rtc_dev_ops.default_handler = NULL; /* XXX */
116}
117
118/** Clean up the RTC soft state
119 *
120 * @param rtc The RTC device
121 */
122static void
123rtc_dev_cleanup(rtc_t *rtc)
124{
125 if (rtc->dev->parent_sess) {
126 async_hangup(rtc->dev->parent_sess);
127 rtc->dev->parent_sess = NULL;
128 }
129}
130
131/** Enable the I/O ports of the device
132 *
133 * @param rtc The real time clock device
134 *
135 * @return true in case of success, false otherwise
136 */
137static bool
138rtc_pio_enable(rtc_t *rtc)
139{
140 if (pio_enable((void *)(uintptr_t) rtc->io_addr, REG_COUNT,
141 (void **) &rtc->port)) {
142
143 ddf_msg(LVL_ERROR, "Cannot map the port %#" PRIx32
144 " for device %s", rtc->io_addr, rtc->dev->name);
145 return false;
146 }
147
148 return true;
149}
150
151/** Initialize the RTC device
152 *
153 * @param rtc Pointer to the RTC device
154 *
155 * @return EOK on success or a negative error code
156 */
157static int
158rtc_dev_initialize(rtc_t *rtc)
159{
160 int rc;
161 size_t i;
162 hw_resource_t *res;
163 bool ioport = false;
164
165 ddf_msg(LVL_DEBUG, "rtc_dev_initialize %s", rtc->dev->name);
166
167 hw_resource_list_t hw_resources;
168 memset(&hw_resources, 0, sizeof(hw_resource_list_t));
169
170 /* Connect to the parent's driver */
171
172 rtc->dev->parent_sess = devman_parent_device_connect(EXCHANGE_SERIALIZE,
173 rtc->dev->handle, IPC_FLAG_BLOCKING);
174 if (!rtc->dev->parent_sess) {
175 ddf_msg(LVL_ERROR, "Failed to connect to parent driver\
176 of device %s.", rtc->dev->name);
177 rc = ENOENT;
178 goto error;
179 }
180
181 /* Get the HW resources */
182 rc = hw_res_get_resource_list(rtc->dev->parent_sess, &hw_resources);
183 if (rc != EOK) {
184 ddf_msg(LVL_ERROR, "Failed to get HW resources\
185 for device %s", rtc->dev->name);
186 goto error;
187 }
188
189 for (i = 0; i < hw_resources.count; ++i) {
190 res = &hw_resources.resources[i];
191
192 if (res->type == IO_RANGE) {
193 if (res->res.io_range.size < REG_COUNT) {
194 ddf_msg(LVL_ERROR, "I/O range assigned to \
195 device %s is too small", rtc->dev->name);
196 rc = ELIMIT;
197 goto error;
198 }
199 rtc->io_addr = res->res.io_range.address;
200 ioport = true;
201 ddf_msg(LVL_NOTE, "Device %s was assigned I/O address \
202 0x%x", rtc->dev->name, rtc->io_addr);
203 }
204 }
205
206 if (!ioport) {
207 /* No I/O address assigned to this device */
208 ddf_msg(LVL_ERROR, "Missing HW resource for device %s",
209 rtc->dev->name);
210 rc = ENOENT;
211 goto error;
212 }
213
214 hw_res_clean_resource_list(&hw_resources);
215
216 return EOK;
217
218error:
219 rtc_dev_cleanup(rtc);
220 hw_res_clean_resource_list(&hw_resources);
221
222 return rc;
223}
224
225/** Read the current time from the CMOS
226 *
227 * @param fun The RTC function
228 * @param t Pointer to the time variable
229 *
230 * @return EOK on success or a negative error code
231 */
232static int
233rtc_time_get(ddf_fun_t *fun, struct tm *t)
234{
235 return EOK;
236}
237
238/** Set the time in the RTC
239 *
240 * @param fun The RTC function
241 * @param t The time value to set
242 *
243 * @return EOK or a negative error code
244 */
245static int
246rtc_time_set(ddf_fun_t *fun, struct tm *t)
247{
248 return EOK;
249}
250
251/** The dev_add callback of the rtc driver
252 *
253 * @param dev The RTC device
254 *
255 * @return EOK on success or a negative error code
256 */
257static int
258rtc_dev_add(ddf_dev_t *dev)
259{
260 rtc_t *rtc;
261 ddf_fun_t *fun = NULL;
262 int rc;
263 bool need_cleanup = false;
264
265 ddf_msg(LVL_DEBUG, "rtc_dev_add %s (handle = %d)",
266 dev->name, (int) dev->handle);
267
268 rtc = ddf_dev_data_alloc(dev, sizeof(rtc_t));
269 if (!rtc)
270 return ENOMEM;
271
272 rtc->dev = dev;
273 fibril_mutex_initialize(&rtc->mutex);
274
275 rc = rtc_dev_initialize(rtc);
276 if (rc != EOK)
277 goto error;
278
279 need_cleanup = true;
280
281 if (!rtc_pio_enable(rtc)) {
282 rc = EADDRNOTAVAIL;
283 goto error;
284 }
285
286 fun = ddf_fun_create(dev, fun_exposed, "a");
287 if (!fun) {
288 ddf_msg(LVL_ERROR, "Failed creating function");
289 rc = ENOENT;
290 goto error;
291 }
292
293 fun->ops = &rtc_dev_ops;
294 rc = ddf_fun_bind(fun);
295 if (rc != EOK) {
296 ddf_msg(LVL_ERROR, "Failed binding function");
297 goto error;
298 }
299
300 rtc->fun = fun;
301
302 ddf_fun_add_to_category(fun, "clock");
303
304 ddf_msg(LVL_NOTE, "Device %s successfully initialized",
305 dev->name);
306
307 return rc;
308
309error:
310 if (fun)
311 ddf_fun_destroy(fun);
312 if (need_cleanup)
313 rtc_dev_cleanup(rtc);
314 return rc;
315}
316
317int
318main(int argc, char **argv)
319{
320 printf(NAME ": HelenOS RTC driver\n");
321 rtc_init();
322 return ddf_driver_main(&rtc_driver);
323}
324
325/**
326 * @}
327 */
Note: See TracBrowser for help on using the repository browser.