xref: /minix3/minix/drivers/clock/readclock/forward.c (revision 433d6423c39e34ec4b79c950597bb2d236f886be)
1*433d6423SLionel Sambuc /*
2*433d6423SLionel Sambuc  * Some real time clocks are embedded within other multi-function chips.
3*433d6423SLionel Sambuc  * Drivers for such chips will implement the RTCDEV protocol and the
4*433d6423SLionel Sambuc  * readclock driver will simply forward on the message to the driver.
5*433d6423SLionel Sambuc  * This keeps things simple for any other services that need to access
6*433d6423SLionel Sambuc  * the RTC as they only have to know / care about the readclock driver.
7*433d6423SLionel Sambuc  */
8*433d6423SLionel Sambuc 
9*433d6423SLionel Sambuc #include <minix/syslib.h>
10*433d6423SLionel Sambuc #include <minix/drvlib.h>
11*433d6423SLionel Sambuc #include <minix/sysutil.h>
12*433d6423SLionel Sambuc #include <minix/log.h>
13*433d6423SLionel Sambuc #include <minix/rs.h>
14*433d6423SLionel Sambuc #include <minix/ds.h>
15*433d6423SLionel Sambuc #include <minix/safecopies.h>
16*433d6423SLionel Sambuc 
17*433d6423SLionel Sambuc #include <sys/mman.h>
18*433d6423SLionel Sambuc #include <sys/types.h>
19*433d6423SLionel Sambuc 
20*433d6423SLionel Sambuc #include <stdio.h>
21*433d6423SLionel Sambuc #include <stdlib.h>
22*433d6423SLionel Sambuc #include <stdarg.h>
23*433d6423SLionel Sambuc #include <string.h>
24*433d6423SLionel Sambuc #include <errno.h>
25*433d6423SLionel Sambuc #include <assert.h>
26*433d6423SLionel Sambuc #include <time.h>
27*433d6423SLionel Sambuc #include <lib.h>
28*433d6423SLionel Sambuc 
29*433d6423SLionel Sambuc #include "forward.h"
30*433d6423SLionel Sambuc #include "readclock.h"
31*433d6423SLionel Sambuc 
32*433d6423SLionel Sambuc static int fwd_msg(int type, struct tm *t, int t_access, int flags);
33*433d6423SLionel Sambuc 
34*433d6423SLionel Sambuc static struct log log = {
35*433d6423SLionel Sambuc 	.name = "readclock.fwd",
36*433d6423SLionel Sambuc 	.log_level = LEVEL_INFO,
37*433d6423SLionel Sambuc 	.log_func = default_log
38*433d6423SLionel Sambuc };
39*433d6423SLionel Sambuc 
40*433d6423SLionel Sambuc /*
41*433d6423SLionel Sambuc  * Label of the driver that messages should be forwarded to.
42*433d6423SLionel Sambuc  */
43*433d6423SLionel Sambuc static char *target_label;
44*433d6423SLionel Sambuc 
45*433d6423SLionel Sambuc int
fwd_set_label(char * label)46*433d6423SLionel Sambuc fwd_set_label(char *label)
47*433d6423SLionel Sambuc {
48*433d6423SLionel Sambuc 	target_label = label;
49*433d6423SLionel Sambuc 	return OK;
50*433d6423SLionel Sambuc }
51*433d6423SLionel Sambuc 
52*433d6423SLionel Sambuc int
fwd_init(void)53*433d6423SLionel Sambuc fwd_init(void)
54*433d6423SLionel Sambuc {
55*433d6423SLionel Sambuc 	if (target_label == NULL) {
56*433d6423SLionel Sambuc 		return EINVAL;
57*433d6423SLionel Sambuc 	}
58*433d6423SLionel Sambuc 	return OK;
59*433d6423SLionel Sambuc }
60*433d6423SLionel Sambuc 
61*433d6423SLionel Sambuc static int
fwd_msg(int type,struct tm * t,int t_access,int flags)62*433d6423SLionel Sambuc fwd_msg(int type, struct tm *t, int t_access, int flags)
63*433d6423SLionel Sambuc {
64*433d6423SLionel Sambuc 	int r;
65*433d6423SLionel Sambuc 	message m;
66*433d6423SLionel Sambuc 	endpoint_t ep;
67*433d6423SLionel Sambuc 	cp_grant_id_t gid;
68*433d6423SLionel Sambuc 
69*433d6423SLionel Sambuc 	r = ds_retrieve_label_endpt(target_label, &ep);
70*433d6423SLionel Sambuc 	if (r != 0) {
71*433d6423SLionel Sambuc 		return -1;
72*433d6423SLionel Sambuc 	}
73*433d6423SLionel Sambuc 
74*433d6423SLionel Sambuc 	if (type == RTCDEV_PWR_OFF) {
75*433d6423SLionel Sambuc 		/* RTCDEV_PWR_OFF messages don't contain any data/flags. */
76*433d6423SLionel Sambuc 		return _syscall(ep, RTCDEV_PWR_OFF, &m);
77*433d6423SLionel Sambuc 	}
78*433d6423SLionel Sambuc 
79*433d6423SLionel Sambuc 	gid = cpf_grant_direct(ep, (vir_bytes) t, sizeof(struct tm), t_access);
80*433d6423SLionel Sambuc 	if (!GRANT_VALID(gid)) {
81*433d6423SLionel Sambuc 		log_warn(&log, "Could not create grant.\n");
82*433d6423SLionel Sambuc 		return -1;
83*433d6423SLionel Sambuc 	}
84*433d6423SLionel Sambuc 
85*433d6423SLionel Sambuc 	m.m_lc_readclock_rtcdev.grant = gid;
86*433d6423SLionel Sambuc 	m.m_lc_readclock_rtcdev.flags = flags;
87*433d6423SLionel Sambuc 
88*433d6423SLionel Sambuc 	r = _syscall(ep, type, &m);
89*433d6423SLionel Sambuc 	cpf_revoke(gid);
90*433d6423SLionel Sambuc 	if (r != RTCDEV_REPLY || m.m_readclock_lc_rtcdev.status != 0) {
91*433d6423SLionel Sambuc 		log_warn(&log, "Call to '%s' failed.\n", target_label);
92*433d6423SLionel Sambuc 		return -1;
93*433d6423SLionel Sambuc 	}
94*433d6423SLionel Sambuc 
95*433d6423SLionel Sambuc 	return OK;
96*433d6423SLionel Sambuc }
97*433d6423SLionel Sambuc 
98*433d6423SLionel Sambuc int
fwd_get_time(struct tm * t,int flags)99*433d6423SLionel Sambuc fwd_get_time(struct tm *t, int flags)
100*433d6423SLionel Sambuc {
101*433d6423SLionel Sambuc 	return fwd_msg(RTCDEV_GET_TIME_G, t, CPF_WRITE, flags);
102*433d6423SLionel Sambuc }
103*433d6423SLionel Sambuc 
104*433d6423SLionel Sambuc int
fwd_set_time(struct tm * t,int flags)105*433d6423SLionel Sambuc fwd_set_time(struct tm *t, int flags)
106*433d6423SLionel Sambuc {
107*433d6423SLionel Sambuc 	return fwd_msg(RTCDEV_SET_TIME_G, t, CPF_READ, flags);
108*433d6423SLionel Sambuc }
109*433d6423SLionel Sambuc 
110*433d6423SLionel Sambuc int
fwd_pwr_off(void)111*433d6423SLionel Sambuc fwd_pwr_off(void)
112*433d6423SLionel Sambuc {
113*433d6423SLionel Sambuc 	return fwd_msg(RTCDEV_PWR_OFF, NULL, 0, RTCDEV_NOFLAGS);
114*433d6423SLionel Sambuc }
115*433d6423SLionel Sambuc 
116*433d6423SLionel Sambuc void
fwd_exit(void)117*433d6423SLionel Sambuc fwd_exit(void)
118*433d6423SLionel Sambuc {
119*433d6423SLionel Sambuc 	target_label = NULL;
120*433d6423SLionel Sambuc }
121