~vojtech-horky/helenos/numa

« back to all changes in this revision

Viewing changes to uspace/drv/test/test2/test2.c

  • Committer: Vojtech Horky
  • Date: 2011-09-28 15:13:08 UTC
  • mfrom: (538.1.714 helenos-mainline)
  • Revision ID: vojtechhorky@users.sourceforge.net-20110928151308-2pz4s2w035n48o8a
Merge mainline changes

Conflicts fixed without problems (mostly caused by separating
ABI into /abi/).

Show diffs side-by-side

added added

removed removed

Lines of Context:
40
40
#define NAME "test2"
41
41
 
42
42
static int test2_add_device(ddf_dev_t *dev);
 
43
static int test2_dev_remove(ddf_dev_t *dev);
 
44
static int test2_dev_gone(ddf_dev_t *dev);
 
45
static int test2_fun_online(ddf_fun_t *fun);
 
46
static int test2_fun_offline(ddf_fun_t *fun);
43
47
 
44
48
static driver_ops_t driver_ops = {
45
 
        .add_device = &test2_add_device
 
49
        .add_device = &test2_add_device,
 
50
        .dev_remove = &test2_dev_remove,
 
51
        .dev_gone = &test2_dev_gone,
 
52
        .fun_online = &test2_fun_online,
 
53
        .fun_offline = &test2_fun_offline
46
54
};
47
55
 
48
56
static driver_t test2_driver = {
50
58
        .driver_ops = &driver_ops
51
59
};
52
60
 
 
61
/* Device soft state */
 
62
typedef struct {
 
63
        ddf_dev_t *dev;
 
64
 
 
65
        ddf_fun_t *fun_a;
 
66
        ddf_fun_t *fun_err;
 
67
        ddf_fun_t *child;
 
68
        ddf_fun_t *test1;
 
69
} test2_t;
 
70
 
53
71
/** Register child and inform user about it.
54
72
 *
55
73
 * @param parent Parent device.
59
77
 * @param score Device match score.
60
78
 */
61
79
static int register_fun_verbose(ddf_dev_t *parent, const char *message,
62
 
    const char *name, const char *match_id, int match_score)
 
80
    const char *name, const char *match_id, int match_score, ddf_fun_t **pfun)
63
81
{
64
82
        ddf_fun_t *fun;
65
83
        int rc;
88
106
                return rc;
89
107
        }
90
108
 
 
109
        *pfun = fun;
 
110
 
91
111
        ddf_msg(LVL_NOTE, "Registered child device `%s'", name);
92
112
        return EOK;
93
113
}
94
114
 
95
 
/** Add child devices after some sleep.
 
115
/** Simulate plugging and surprise unplugging.
96
116
 *
97
117
 * @param arg Parent device structure (ddf_dev_t *).
98
118
 * @return Always EOK.
99
119
 */
100
 
static int postponed_birth(void *arg)
 
120
static int plug_unplug(void *arg)
101
121
{
102
 
        ddf_dev_t *dev = (ddf_dev_t *) arg;
 
122
        test2_t *test2 = (test2_t *) arg;
103
123
        ddf_fun_t *fun_a;
104
124
        int rc;
105
125
 
106
126
        async_usleep(1000);
107
127
 
108
 
        (void) register_fun_verbose(dev, "child driven by the same task",
109
 
            "child", "virtual&test2", 10);
110
 
        (void) register_fun_verbose(dev, "child driven by test1",
111
 
            "test1", "virtual&test1", 10);
 
128
        (void) register_fun_verbose(test2->dev, "child driven by the same task",
 
129
            "child", "virtual&test2", 10, &test2->child);
 
130
        (void) register_fun_verbose(test2->dev, "child driven by test1",
 
131
            "test1", "virtual&test1", 10, &test2->test1);
112
132
 
113
 
        fun_a = ddf_fun_create(dev, fun_exposed, "a");
 
133
        fun_a = ddf_fun_create(test2->dev, fun_exposed, "a");
114
134
        if (fun_a == NULL) {
115
135
                ddf_msg(LVL_ERROR, "Failed creating function 'a'.");
116
136
                return ENOMEM;
122
142
                return rc;
123
143
        }
124
144
 
125
 
        ddf_fun_add_to_class(fun_a, "virtual");
126
 
 
 
145
        ddf_fun_add_to_category(fun_a, "virtual");
 
146
        test2->fun_a = fun_a;
 
147
 
 
148
        async_usleep(10000000);
 
149
 
 
150
        ddf_msg(LVL_NOTE, "Unbinding function test1.");
 
151
        ddf_fun_unbind(test2->test1);
 
152
        async_usleep(1000000);
 
153
        ddf_msg(LVL_NOTE, "Unbinding function child.");
 
154
        ddf_fun_unbind(test2->child);
 
155
 
 
156
        return EOK;
 
157
}
 
158
 
 
159
static int fun_remove(ddf_fun_t *fun, const char *name)
 
160
{
 
161
        int rc;
 
162
 
 
163
        ddf_msg(LVL_DEBUG, "fun_remove(%p, '%s')", fun, name);
 
164
        rc = ddf_fun_offline(fun);
 
165
        if (rc != EOK) {
 
166
                ddf_msg(LVL_ERROR, "Error offlining function '%s'.", name);
 
167
                return rc;
 
168
        }
 
169
 
 
170
        rc = ddf_fun_unbind(fun);
 
171
        if (rc != EOK) {
 
172
                ddf_msg(LVL_ERROR, "Failed unbinding function '%s'.", name);
 
173
                return rc;
 
174
        }
 
175
 
 
176
        ddf_fun_destroy(fun);
 
177
        return EOK;
 
178
}
 
179
 
 
180
static int fun_unbind(ddf_fun_t *fun, const char *name)
 
181
{
 
182
        int rc;
 
183
 
 
184
        ddf_msg(LVL_DEBUG, "fun_unbind(%p, '%s')", fun, name);
 
185
        rc = ddf_fun_unbind(fun);
 
186
        if (rc != EOK) {
 
187
                ddf_msg(LVL_ERROR, "Failed unbinding function '%s'.", name);
 
188
                return rc;
 
189
        }
 
190
 
 
191
        ddf_fun_destroy(fun);
127
192
        return EOK;
128
193
}
129
194
 
130
195
static int test2_add_device(ddf_dev_t *dev)
131
196
{
 
197
        test2_t *test2;
 
198
 
132
199
        ddf_msg(LVL_DEBUG, "test2_add_device(name=\"%s\", handle=%d)",
133
200
            dev->name, (int) dev->handle);
134
201
 
 
202
        test2 = ddf_dev_data_alloc(dev, sizeof(test2_t));
 
203
        if (test2 == NULL) {
 
204
                ddf_msg(LVL_ERROR, "Failed allocating soft state.");
 
205
                return ENOMEM;
 
206
        }
 
207
 
 
208
        test2->dev = dev;
 
209
 
135
210
        if (str_cmp(dev->name, "child") != 0) {
136
 
                fid_t postpone = fibril_create(postponed_birth, dev);
 
211
                fid_t postpone = fibril_create(plug_unplug, test2);
137
212
                if (postpone == 0) {
138
213
                        ddf_msg(LVL_ERROR, "fibril_create() failed.");
139
214
                        return ENOMEM;
141
216
                fibril_add_ready(postpone);
142
217
        } else {
143
218
                (void) register_fun_verbose(dev, "child without available driver",
144
 
                    "ERROR", "non-existent.match.id", 10);
145
 
        }
146
 
 
147
 
        return EOK;
 
219
                    "ERROR", "non-existent.match.id", 10, &test2->fun_err);
 
220
        }
 
221
 
 
222
        return EOK;
 
223
}
 
224
 
 
225
static int test2_dev_remove(ddf_dev_t *dev)
 
226
{
 
227
        test2_t *test2 = (test2_t *)dev->driver_data;
 
228
        int rc;
 
229
 
 
230
        ddf_msg(LVL_DEBUG, "test2_dev_remove(%p)", dev);
 
231
 
 
232
        if (test2->fun_a != NULL) {
 
233
                rc = fun_remove(test2->fun_a, "a");
 
234
                if (rc != EOK)
 
235
                        return rc;
 
236
        }
 
237
 
 
238
        if (test2->fun_err != NULL) {
 
239
                rc = fun_remove(test2->fun_err, "ERROR");
 
240
                if (rc != EOK)
 
241
                        return rc;
 
242
        }
 
243
 
 
244
        if (test2->child != NULL) {
 
245
                rc = fun_remove(test2->child, "child");
 
246
                if (rc != EOK)
 
247
                        return rc;
 
248
        }
 
249
 
 
250
        if (test2->test1 != NULL) {
 
251
                rc = fun_remove(test2->test1, "test1");
 
252
                if (rc != EOK)
 
253
                        return rc;
 
254
        }
 
255
 
 
256
        return EOK;
 
257
}
 
258
 
 
259
static int test2_dev_gone(ddf_dev_t *dev)
 
260
{
 
261
        test2_t *test2 = (test2_t *)dev->driver_data;
 
262
        int rc;
 
263
 
 
264
        ddf_msg(LVL_DEBUG, "test2_dev_gone(%p)", dev);
 
265
 
 
266
        if (test2->fun_a != NULL) {
 
267
                rc = fun_unbind(test2->fun_a, "a");
 
268
                if (rc != EOK)
 
269
                        return rc;
 
270
        }
 
271
 
 
272
        if (test2->fun_err != NULL) {
 
273
                rc = fun_unbind(test2->fun_err, "ERROR");
 
274
                if (rc != EOK)
 
275
                        return rc;
 
276
        }
 
277
 
 
278
        if (test2->child != NULL) {
 
279
                rc = fun_unbind(test2->child, "child");
 
280
                if (rc != EOK)
 
281
                        return rc;
 
282
        }
 
283
 
 
284
        if (test2->test1 != NULL) {
 
285
                rc = fun_unbind(test2->test1, "test1");
 
286
                if (rc != EOK)
 
287
                        return rc;
 
288
        }
 
289
 
 
290
        return EOK;
 
291
}
 
292
 
 
293
 
 
294
static int test2_fun_online(ddf_fun_t *fun)
 
295
{
 
296
        ddf_msg(LVL_DEBUG, "test2_fun_online()");
 
297
        return ddf_fun_online(fun);
 
298
}
 
299
 
 
300
static int test2_fun_offline(ddf_fun_t *fun)
 
301
{
 
302
        ddf_msg(LVL_DEBUG, "test2_fun_offline()");
 
303
        return ddf_fun_offline(fun);
148
304
}
149
305
 
150
306
int main(int argc, char *argv[])
151
307
{
152
308
        printf(NAME ": HelenOS test2 virtual device driver\n");
153
 
        ddf_log_init(NAME, LVL_ERROR);
 
309
        ddf_log_init(NAME, LVL_NOTE);
154
310
        return ddf_driver_main(&test2_driver);
155
311
}
156
312