1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
|
#include <minix/drivers.h>
#include <minix/chardriver.h>
#include <stdio.h>
#include <stdlib.h>
#include <minix/ds.h>
#include "hello.h"
/*
* Function prototypes for the hello driver.
*/
static int hello_open(devminor_t minor, int access, endpoint_t user_endpt);
static int hello_close(devminor_t minor);
static ssize_t hello_read(devminor_t minor, u64_t position, endpoint_t endpt,
cp_grant_id_t grant, size_t size, int flags, cdev_id_t id);
/* SEF functions and variables. */
static void sef_local_startup(void);
static int sef_cb_init(int type, sef_init_info_t *info);
static int sef_cb_lu_state_save(int, int);
static int lu_state_restore(void);
/* Entry points to the hello driver. */
static struct chardriver hello_tab =
{
.cdr_open = hello_open,
.cdr_close = hello_close,
.cdr_read = hello_read,
};
/** State variable to count the number of times the device has been opened.
* Note that this is not the regular type of open counter: it never decreases.
*/
static int open_counter;
static int hello_open(devminor_t UNUSED(minor), int UNUSED(access),
endpoint_t UNUSED(user_endpt))
{
printf("hello_open(). Called %d time(s).\n", ++open_counter);
return OK;
}
static int hello_close(devminor_t UNUSED(minor))
{
printf("hello_close()\n");
return OK;
}
static ssize_t hello_read(devminor_t UNUSED(minor), u64_t position,
endpoint_t endpt, cp_grant_id_t grant, size_t size, int UNUSED(flags),
cdev_id_t UNUSED(id))
{
u64_t dev_size;
char *ptr;
int ret;
char *buf = HELLO_MESSAGE;
printf("hello_read()\n");
/* This is the total size of our device. */
dev_size = (u64_t) strlen(buf);
/* Check for EOF, and possibly limit the read size. */
if (position >= dev_size) return 0; /* EOF */
if (position + size > dev_size)
size = (size_t)(dev_size - position); /* limit size */
/* Copy the requested part to the caller. */
ptr = buf + (size_t)position;
if ((ret = sys_safecopyto(endpt, grant, 0, (vir_bytes) ptr, size)) != OK)
return ret;
/* Return the number of bytes read. */
return size;
}
static int sef_cb_lu_state_save(int UNUSED(state), int UNUSED(flags)) {
/* Save the state. */
ds_publish_u32("open_counter", open_counter, DSF_OVERWRITE);
return OK;
}
static int lu_state_restore() {
/* Restore the state. */
u32_t value;
ds_retrieve_u32("open_counter", &value);
ds_delete_u32("open_counter");
open_counter = (int) value;
return OK;
}
static void sef_local_startup()
{
/*
* Register init callbacks. Use the same function for all event types
*/
sef_setcb_init_fresh(sef_cb_init);
sef_setcb_init_lu(sef_cb_init);
sef_setcb_init_restart(sef_cb_init);
/*
* Register live update callbacks.
*/
sef_setcb_lu_state_save(sef_cb_lu_state_save);
/* Let SEF perform startup. */
sef_startup();
}
static int sef_cb_init(int type, sef_init_info_t *UNUSED(info))
{
/* Initialize the hello driver. */
int do_announce_driver = TRUE;
open_counter = 0;
switch(type) {
case SEF_INIT_FRESH:
printf("%s", HELLO_MESSAGE);
break;
case SEF_INIT_LU:
/* Restore the state. */
lu_state_restore();
do_announce_driver = FALSE;
printf("%sHey, I'm a new version!\n", HELLO_MESSAGE);
break;
case SEF_INIT_RESTART:
printf("%sHey, I've just been restarted!\n", HELLO_MESSAGE);
break;
}
/* Announce we are up when necessary. */
if (do_announce_driver) {
chardriver_announce();
}
/* Initialization completed successfully. */
return OK;
}
int main(void)
{
/*
* Perform initialization.
*/
sef_local_startup();
/*
* Run the main loop.
*/
chardriver_task(&hello_tab);
return OK;
}
|