1433d6423SLionel Sambuc #include "devman.h"
2433d6423SLionel Sambuc #include "proto.h"
3433d6423SLionel Sambuc
4433d6423SLionel Sambuc
5433d6423SLionel Sambuc static struct devman_device*devman_dev_add_child(struct devman_device
6433d6423SLionel Sambuc *parent, struct devman_device_info *devinf);
7433d6423SLionel Sambuc static struct devman_device *_find_dev(struct devman_device *dev, int
8433d6423SLionel Sambuc dev_id);
9433d6423SLionel Sambuc static int devman_dev_add_info(struct devman_device *dev, struct
10433d6423SLionel Sambuc devman_device_info_entry *entry, char *buf);
11*5eefd0feSDavid van Moolenbroek static ssize_t devman_event_read(char *ptr, size_t len, off_t offset, void
12433d6423SLionel Sambuc *data);
13433d6423SLionel Sambuc
14433d6423SLionel Sambuc static int devman_del_device(struct devman_device *dev);
15433d6423SLionel Sambuc
16433d6423SLionel Sambuc static int next_device_id = 1;
17433d6423SLionel Sambuc
18433d6423SLionel Sambuc static struct inode_stat default_dir_stat = {
19433d6423SLionel Sambuc /* .mode = */ S_IFDIR | S_IRUSR | S_IRGRP | S_IROTH,
20433d6423SLionel Sambuc /* .uid = */ 0,
21433d6423SLionel Sambuc /* .gid = */ 0,
22433d6423SLionel Sambuc /* .size = */ 0,
23433d6423SLionel Sambuc /* .dev = */ NO_DEV,
24433d6423SLionel Sambuc };
25433d6423SLionel Sambuc
26433d6423SLionel Sambuc static struct inode_stat default_file_stat = {
27433d6423SLionel Sambuc /* .mode = */ S_IFREG | S_IRUSR | S_IRGRP | S_IROTH,
28433d6423SLionel Sambuc /* .uid = */ 0,
29433d6423SLionel Sambuc /* .gid = */ 0,
30433d6423SLionel Sambuc /* .size = */ 0x1000,
31433d6423SLionel Sambuc /* .dev = */ NO_DEV,
32433d6423SLionel Sambuc };
33433d6423SLionel Sambuc
34433d6423SLionel Sambuc
35433d6423SLionel Sambuc static struct devman_device root_dev;
36433d6423SLionel Sambuc static struct devman_event_inode event_inode_data = {
37433d6423SLionel Sambuc TAILQ_HEAD_INITIALIZER(event_inode_data.event_queue),
38433d6423SLionel Sambuc };
39433d6423SLionel Sambuc static struct devman_inode event_inode;
40433d6423SLionel Sambuc
41433d6423SLionel Sambuc /*===========================================================================*
42433d6423SLionel Sambuc * devman_generate_path *
43433d6423SLionel Sambuc *===========================================================================*/
44433d6423SLionel Sambuc static int
devman_generate_path(char * buf,int len,struct devman_device * dev)45433d6423SLionel Sambuc devman_generate_path(char* buf, int len, struct devman_device *dev)
46433d6423SLionel Sambuc {
47433d6423SLionel Sambuc int res =0;
48433d6423SLionel Sambuc const char * name = ".";
49433d6423SLionel Sambuc const char * sep = "/";
50433d6423SLionel Sambuc
51433d6423SLionel Sambuc if (dev != NULL) {
52433d6423SLionel Sambuc res = devman_generate_path(buf, len, dev->parent);
53433d6423SLionel Sambuc if (res != 0) {
54433d6423SLionel Sambuc return res;
55433d6423SLionel Sambuc }
56433d6423SLionel Sambuc name = get_inode_name(dev->inode.inode);
57433d6423SLionel Sambuc } else {
58433d6423SLionel Sambuc }
59433d6423SLionel Sambuc
60433d6423SLionel Sambuc /* does it fit? */
61433d6423SLionel Sambuc if (strlen(buf) + strlen(name) + strlen(sep) + 1 > len) {
62433d6423SLionel Sambuc return ENOMEM;
63433d6423SLionel Sambuc }
64433d6423SLionel Sambuc
65433d6423SLionel Sambuc strcat(buf, name);
66433d6423SLionel Sambuc strcat(buf, sep);
67433d6423SLionel Sambuc
68433d6423SLionel Sambuc return 0;
69433d6423SLionel Sambuc }
70433d6423SLionel Sambuc
71433d6423SLionel Sambuc /*===========================================================================*
72433d6423SLionel Sambuc * devman_device_add_event *
73433d6423SLionel Sambuc *===========================================================================*/
74433d6423SLionel Sambuc static void
devman_device_add_event(struct devman_device * dev)75433d6423SLionel Sambuc devman_device_add_event(struct devman_device* dev)
76433d6423SLionel Sambuc {
77433d6423SLionel Sambuc struct devman_event * event;
78433d6423SLionel Sambuc char buf[12]; /* this fits the device ID " 0xXXXXXXXX" */
79433d6423SLionel Sambuc int res;
80433d6423SLionel Sambuc
81433d6423SLionel Sambuc event = malloc(sizeof(struct devman_event));
82433d6423SLionel Sambuc
83433d6423SLionel Sambuc if (event == NULL) {
84433d6423SLionel Sambuc panic("devman_device_remove_event: out of memory\n");
85433d6423SLionel Sambuc }
86433d6423SLionel Sambuc
87433d6423SLionel Sambuc memset(event, 0, sizeof(*event));
88433d6423SLionel Sambuc
89433d6423SLionel Sambuc strncpy(event->data, ADD_STRING, DEVMAN_STRING_LEN - 1);
90433d6423SLionel Sambuc
91433d6423SLionel Sambuc res = devman_generate_path(event->data, DEVMAN_STRING_LEN - 11 , dev);
92433d6423SLionel Sambuc
93433d6423SLionel Sambuc if (res) {
94433d6423SLionel Sambuc panic("devman_device_add_event: "
95433d6423SLionel Sambuc "devman_generate_path failed: (%d)\n", res);
96433d6423SLionel Sambuc }
97433d6423SLionel Sambuc
98433d6423SLionel Sambuc snprintf(buf, 12, " 0x%08x", dev->dev_id);
99433d6423SLionel Sambuc strcat(event->data,buf);
100433d6423SLionel Sambuc
101433d6423SLionel Sambuc TAILQ_INSERT_HEAD(&event_inode_data.event_queue, event, events);
102433d6423SLionel Sambuc }
103433d6423SLionel Sambuc
104433d6423SLionel Sambuc /*===========================================================================*
105433d6423SLionel Sambuc * devman_device_remove_event *
106433d6423SLionel Sambuc *===========================================================================*/
107433d6423SLionel Sambuc static void
devman_device_remove_event(struct devman_device * dev)108433d6423SLionel Sambuc devman_device_remove_event(struct devman_device* dev)
109433d6423SLionel Sambuc {
110433d6423SLionel Sambuc struct devman_event * event;
111433d6423SLionel Sambuc char buf[12]; /* this fits the device ID " 0xXXXXXXXX" */
112433d6423SLionel Sambuc int res;
113433d6423SLionel Sambuc
114433d6423SLionel Sambuc event = malloc(sizeof(struct devman_event));
115433d6423SLionel Sambuc
116433d6423SLionel Sambuc if (event == NULL) {
117433d6423SLionel Sambuc panic("devman_device_remove_event: out of memory\n");
118433d6423SLionel Sambuc }
119433d6423SLionel Sambuc
120433d6423SLionel Sambuc memset(event, 0, sizeof(*event));
121433d6423SLionel Sambuc
122433d6423SLionel Sambuc strncpy(event->data, REMOVE_STRING, DEVMAN_STRING_LEN - 1);
123433d6423SLionel Sambuc
124433d6423SLionel Sambuc res = devman_generate_path(event->data, DEVMAN_STRING_LEN-11, dev);
125433d6423SLionel Sambuc
126433d6423SLionel Sambuc if (res) {
127433d6423SLionel Sambuc panic("devman_device_remove_event: "
128433d6423SLionel Sambuc "devman_generate_path failed: (%d)\n", res);
129433d6423SLionel Sambuc }
130433d6423SLionel Sambuc
131433d6423SLionel Sambuc snprintf(buf, 12, " 0x%08x", dev->dev_id);
132433d6423SLionel Sambuc strcat(event->data,buf);
133433d6423SLionel Sambuc
134433d6423SLionel Sambuc
135433d6423SLionel Sambuc TAILQ_INSERT_HEAD(&event_inode_data.event_queue, event, events);
136433d6423SLionel Sambuc }
137433d6423SLionel Sambuc
138433d6423SLionel Sambuc /*===========================================================================*
139433d6423SLionel Sambuc * devman_event_read *
140433d6423SLionel Sambuc *===========================================================================*/
141*5eefd0feSDavid van Moolenbroek static ssize_t
devman_event_read(char * ptr,size_t len,off_t offset,void * data)142*5eefd0feSDavid van Moolenbroek devman_event_read(char *ptr, size_t len, off_t offset, void *data)
143433d6423SLionel Sambuc {
144433d6423SLionel Sambuc struct devman_event *ev = NULL;
145433d6423SLionel Sambuc struct devman_event_inode *n;
146*5eefd0feSDavid van Moolenbroek ssize_t r;
147433d6423SLionel Sambuc
148433d6423SLionel Sambuc n = (struct devman_event_inode *) data;
149433d6423SLionel Sambuc
150433d6423SLionel Sambuc if (!TAILQ_EMPTY(&n->event_queue)) {
151433d6423SLionel Sambuc ev = TAILQ_LAST(&n->event_queue, event_head);
152433d6423SLionel Sambuc }
153433d6423SLionel Sambuc
154*5eefd0feSDavid van Moolenbroek buf_init(ptr, len, offset);
15510b1b4eeSDavid van Moolenbroek if (ev != NULL)
156433d6423SLionel Sambuc buf_printf("%s", ev->data);
157433d6423SLionel Sambuc
158*5eefd0feSDavid van Moolenbroek r = buf_result();
159433d6423SLionel Sambuc
16010b1b4eeSDavid van Moolenbroek /* read all (EOF)? */
161*5eefd0feSDavid van Moolenbroek if (ev != NULL && r == 0) {
16210b1b4eeSDavid van Moolenbroek TAILQ_REMOVE(&n->event_queue, ev, events);
16310b1b4eeSDavid van Moolenbroek free(ev);
16410b1b4eeSDavid van Moolenbroek }
16510b1b4eeSDavid van Moolenbroek
166*5eefd0feSDavid van Moolenbroek return r;
167433d6423SLionel Sambuc }
168433d6423SLionel Sambuc
169433d6423SLionel Sambuc /*===========================================================================*
170433d6423SLionel Sambuc * devman_static_info_read *
171433d6423SLionel Sambuc *===========================================================================*/
172*5eefd0feSDavid van Moolenbroek static ssize_t
devman_static_info_read(char * ptr,size_t len,off_t offset,void * data)173*5eefd0feSDavid van Moolenbroek devman_static_info_read(char *ptr, size_t len, off_t offset, void *data)
174433d6423SLionel Sambuc {
175433d6423SLionel Sambuc struct devman_static_info_inode *n;
176433d6423SLionel Sambuc
177433d6423SLionel Sambuc n = (struct devman_static_info_inode *) data;
178433d6423SLionel Sambuc
179*5eefd0feSDavid van Moolenbroek buf_init(ptr, len, offset);
180433d6423SLionel Sambuc buf_printf("%s\n", n->data);
181*5eefd0feSDavid van Moolenbroek return buf_result();
182433d6423SLionel Sambuc }
183433d6423SLionel Sambuc
184433d6423SLionel Sambuc /*===========================================================================*
185433d6423SLionel Sambuc * devman_init_devices *
186433d6423SLionel Sambuc *===========================================================================*/
devman_init_devices()187433d6423SLionel Sambuc void devman_init_devices()
188433d6423SLionel Sambuc {
189433d6423SLionel Sambuc event_inode.data = &event_inode_data;
190433d6423SLionel Sambuc event_inode.read_fn = devman_event_read;
191433d6423SLionel Sambuc
192433d6423SLionel Sambuc root_dev.dev_id = 0;
193433d6423SLionel Sambuc root_dev.major = -1;
194433d6423SLionel Sambuc root_dev.owner = 0;
195433d6423SLionel Sambuc root_dev.parent = NULL;
196433d6423SLionel Sambuc
197433d6423SLionel Sambuc root_dev.inode.inode=
198433d6423SLionel Sambuc add_inode(get_root_inode(), "devices",
199433d6423SLionel Sambuc NO_INDEX, &default_dir_stat, 0, &root_dev.inode);
200433d6423SLionel Sambuc
201433d6423SLionel Sambuc event_inode.inode=
202433d6423SLionel Sambuc add_inode(get_root_inode(), "events",
203433d6423SLionel Sambuc NO_INDEX, &default_file_stat, 0, &event_inode);
204433d6423SLionel Sambuc
205433d6423SLionel Sambuc TAILQ_INIT(&root_dev.children);
206433d6423SLionel Sambuc TAILQ_INIT(&root_dev.infos);
207433d6423SLionel Sambuc }
208433d6423SLionel Sambuc
209433d6423SLionel Sambuc
210433d6423SLionel Sambuc /*===========================================================================*
211433d6423SLionel Sambuc * do_reply *
212433d6423SLionel Sambuc *===========================================================================*/
do_reply(message * msg,int res)213433d6423SLionel Sambuc static void do_reply(message *msg, int res)
214433d6423SLionel Sambuc {
215433d6423SLionel Sambuc msg->m_type = DEVMAN_REPLY;
216433d6423SLionel Sambuc msg->DEVMAN_RESULT = res;
217433d6423SLionel Sambuc ipc_send(msg->m_source, msg);
218433d6423SLionel Sambuc }
219433d6423SLionel Sambuc
220433d6423SLionel Sambuc /*===========================================================================*
221433d6423SLionel Sambuc * do_add_device *
222433d6423SLionel Sambuc *===========================================================================*/
do_add_device(message * msg)223433d6423SLionel Sambuc int do_add_device(message *msg)
224433d6423SLionel Sambuc {
225433d6423SLionel Sambuc endpoint_t ep = msg->m_source;
226433d6423SLionel Sambuc int res;
227433d6423SLionel Sambuc struct devman_device *dev;
228433d6423SLionel Sambuc struct devman_device *parent;
229433d6423SLionel Sambuc struct devman_device_info *devinf = NULL;
230433d6423SLionel Sambuc
231433d6423SLionel Sambuc devinf = malloc(msg->DEVMAN_GRANT_SIZE);
232433d6423SLionel Sambuc
233433d6423SLionel Sambuc if (devinf == NULL) {
234433d6423SLionel Sambuc res = ENOMEM;
235433d6423SLionel Sambuc do_reply(msg, res);
236433d6423SLionel Sambuc return 0;
237433d6423SLionel Sambuc }
238433d6423SLionel Sambuc
239433d6423SLionel Sambuc res = sys_safecopyfrom(ep, msg->DEVMAN_GRANT_ID,
240433d6423SLionel Sambuc 0, (vir_bytes) devinf, msg->DEVMAN_GRANT_SIZE);
241433d6423SLionel Sambuc
242433d6423SLionel Sambuc if (res != OK) {
243433d6423SLionel Sambuc res = EINVAL;
244433d6423SLionel Sambuc free(devinf);
245433d6423SLionel Sambuc do_reply(msg, res);
246433d6423SLionel Sambuc return 0;
247433d6423SLionel Sambuc }
248433d6423SLionel Sambuc
249433d6423SLionel Sambuc if ((parent = _find_dev(&root_dev, devinf->parent_dev_id))
250433d6423SLionel Sambuc == NULL) {
251433d6423SLionel Sambuc res = ENODEV;
252433d6423SLionel Sambuc free(devinf);
253433d6423SLionel Sambuc do_reply(msg, res);
254433d6423SLionel Sambuc return 0;
255433d6423SLionel Sambuc }
256433d6423SLionel Sambuc
257433d6423SLionel Sambuc dev = devman_dev_add_child(parent, devinf);
258433d6423SLionel Sambuc
259433d6423SLionel Sambuc if (dev == NULL) {
260433d6423SLionel Sambuc res = ENODEV;
261433d6423SLionel Sambuc free(devinf);
262433d6423SLionel Sambuc do_reply(msg, res);
263433d6423SLionel Sambuc return 0;
264433d6423SLionel Sambuc }
265433d6423SLionel Sambuc
266433d6423SLionel Sambuc dev->state = DEVMAN_DEVICE_UNBOUND;
267433d6423SLionel Sambuc
268433d6423SLionel Sambuc dev->owner = msg->m_source;
269433d6423SLionel Sambuc
270433d6423SLionel Sambuc msg->DEVMAN_DEVICE_ID = dev->dev_id;
271433d6423SLionel Sambuc
272433d6423SLionel Sambuc devman_device_add_event(dev);
273433d6423SLionel Sambuc
274433d6423SLionel Sambuc do_reply(msg, res);
275433d6423SLionel Sambuc return 0;
276433d6423SLionel Sambuc }
277433d6423SLionel Sambuc
278433d6423SLionel Sambuc
279433d6423SLionel Sambuc /*===========================================================================*
280433d6423SLionel Sambuc * _find_dev *
281433d6423SLionel Sambuc *===========================================================================*/
282433d6423SLionel Sambuc static struct devman_device *
_find_dev(struct devman_device * dev,int dev_id)283433d6423SLionel Sambuc _find_dev(struct devman_device *dev, int dev_id)
284433d6423SLionel Sambuc {
285433d6423SLionel Sambuc struct devman_device *_dev;
286433d6423SLionel Sambuc
287433d6423SLionel Sambuc if(dev->dev_id == dev_id)
288433d6423SLionel Sambuc return dev;
289433d6423SLionel Sambuc
290433d6423SLionel Sambuc TAILQ_FOREACH(_dev, &dev->children, siblings) {
291433d6423SLionel Sambuc
292433d6423SLionel Sambuc struct devman_device *t = _find_dev(_dev, dev_id);
293433d6423SLionel Sambuc
294433d6423SLionel Sambuc if (t !=NULL) {
295433d6423SLionel Sambuc return t;
296433d6423SLionel Sambuc }
297433d6423SLionel Sambuc }
298433d6423SLionel Sambuc
299433d6423SLionel Sambuc return NULL;
300433d6423SLionel Sambuc }
301433d6423SLionel Sambuc
302433d6423SLionel Sambuc /*===========================================================================*
303433d6423SLionel Sambuc * devman_find_dev *
304433d6423SLionel Sambuc *===========================================================================*/
devman_find_device(int dev_id)305433d6423SLionel Sambuc struct devman_device *devman_find_device(int dev_id)
306433d6423SLionel Sambuc {
307433d6423SLionel Sambuc return _find_dev(&root_dev, dev_id);
308433d6423SLionel Sambuc }
309433d6423SLionel Sambuc
310433d6423SLionel Sambuc /*===========================================================================*
311433d6423SLionel Sambuc * devman_dev_add_static_info *
312433d6423SLionel Sambuc *===========================================================================*/
313433d6423SLionel Sambuc static int
devman_dev_add_static_info(struct devman_device * dev,char * name,char * data)314433d6423SLionel Sambuc devman_dev_add_static_info
315433d6423SLionel Sambuc (struct devman_device *dev, char * name, char *data)
316433d6423SLionel Sambuc {
317433d6423SLionel Sambuc struct devman_inode *inode;
318433d6423SLionel Sambuc struct devman_static_info_inode *st_inode;
319433d6423SLionel Sambuc
320433d6423SLionel Sambuc
321433d6423SLionel Sambuc st_inode = malloc(sizeof(struct devman_static_info_inode));
322433d6423SLionel Sambuc st_inode->dev = dev;
323433d6423SLionel Sambuc
324433d6423SLionel Sambuc strncpy(st_inode->data, data, DEVMAN_STRING_LEN);
325433d6423SLionel Sambuc /* if string is longer it's truncated */
326433d6423SLionel Sambuc st_inode->data[DEVMAN_STRING_LEN-1] = 0;
327433d6423SLionel Sambuc
328433d6423SLionel Sambuc inode = malloc (sizeof(struct devman_inode));
329433d6423SLionel Sambuc inode->data = st_inode;
330433d6423SLionel Sambuc inode->read_fn = devman_static_info_read;
331433d6423SLionel Sambuc
332433d6423SLionel Sambuc inode->inode = add_inode(dev->inode.inode, name,
333433d6423SLionel Sambuc NO_INDEX, &default_file_stat, 0, inode);
334433d6423SLionel Sambuc
335433d6423SLionel Sambuc /* add info to info_list */
336433d6423SLionel Sambuc TAILQ_INSERT_HEAD(&dev->infos, inode, inode_list);
337433d6423SLionel Sambuc
338433d6423SLionel Sambuc return 0;
339433d6423SLionel Sambuc }
340433d6423SLionel Sambuc
341433d6423SLionel Sambuc /*===========================================================================*
342433d6423SLionel Sambuc * devman_dev_add_child *
343433d6423SLionel Sambuc *===========================================================================*/
344433d6423SLionel Sambuc static struct devman_device*
devman_dev_add_child(struct devman_device * parent,struct devman_device_info * devinf)345433d6423SLionel Sambuc devman_dev_add_child
346433d6423SLionel Sambuc (struct devman_device *parent, struct devman_device_info *devinf)
347433d6423SLionel Sambuc {
348433d6423SLionel Sambuc int i;
349433d6423SLionel Sambuc char * buffer = (char *) (devinf);
350433d6423SLionel Sambuc char tmp_buf[128];
351433d6423SLionel Sambuc struct devman_device_info_entry *entries;
352433d6423SLionel Sambuc
353433d6423SLionel Sambuc /* create device */
354433d6423SLionel Sambuc struct devman_device * dev = malloc(sizeof(struct devman_device));
355433d6423SLionel Sambuc if (dev == NULL) {
356433d6423SLionel Sambuc panic("devman_dev_add_child: out of memory\n");
357433d6423SLionel Sambuc }
358433d6423SLionel Sambuc
359433d6423SLionel Sambuc
360433d6423SLionel Sambuc if (parent == NULL) {
361433d6423SLionel Sambuc free(dev);
362433d6423SLionel Sambuc return NULL;
363433d6423SLionel Sambuc }
364433d6423SLionel Sambuc
365433d6423SLionel Sambuc dev->ref_count = 1;
366433d6423SLionel Sambuc
367433d6423SLionel Sambuc /* set dev_info */
368433d6423SLionel Sambuc dev->parent = parent;
369433d6423SLionel Sambuc dev->info = devinf;
370433d6423SLionel Sambuc
371433d6423SLionel Sambuc dev->dev_id = next_device_id++;
372433d6423SLionel Sambuc
373433d6423SLionel Sambuc dev->inode.inode =
374433d6423SLionel Sambuc add_inode(parent->inode.inode, buffer + devinf->name_offset,
375433d6423SLionel Sambuc NO_INDEX, &default_dir_stat, 0, &dev->inode);
376433d6423SLionel Sambuc
377433d6423SLionel Sambuc TAILQ_INIT(&dev->children);
378433d6423SLionel Sambuc TAILQ_INIT(&dev->infos);
379433d6423SLionel Sambuc
380433d6423SLionel Sambuc /* create information inodes */
381433d6423SLionel Sambuc entries = (struct devman_device_info_entry *)
382433d6423SLionel Sambuc (buffer + sizeof(struct devman_device_info));
383433d6423SLionel Sambuc
384433d6423SLionel Sambuc for (i = 0; i < devinf->count ; i++) {
385433d6423SLionel Sambuc devman_dev_add_info(dev, &entries[i], buffer);
386433d6423SLionel Sambuc }
387433d6423SLionel Sambuc
388433d6423SLionel Sambuc /* make device ID accessible to user land */
389433d6423SLionel Sambuc snprintf(tmp_buf, DEVMAN_STRING_LEN, "%d",dev->dev_id);
390433d6423SLionel Sambuc devman_dev_add_static_info(dev, "devman_id", tmp_buf);
391433d6423SLionel Sambuc
392433d6423SLionel Sambuc TAILQ_INSERT_HEAD(&parent->children, dev, siblings);
393433d6423SLionel Sambuc
394433d6423SLionel Sambuc devman_get_device(parent);
395433d6423SLionel Sambuc
396433d6423SLionel Sambuc /* FUTURE TODO: create links(BUS, etc) */
397433d6423SLionel Sambuc return dev;
398433d6423SLionel Sambuc }
399433d6423SLionel Sambuc
400433d6423SLionel Sambuc /*===========================================================================*
401433d6423SLionel Sambuc * devman_dev_add_info *
402433d6423SLionel Sambuc *===========================================================================*/
403433d6423SLionel Sambuc static int
devman_dev_add_info(struct devman_device * dev,struct devman_device_info_entry * entry,char * buf)404433d6423SLionel Sambuc devman_dev_add_info
405433d6423SLionel Sambuc (struct devman_device *dev, struct devman_device_info_entry *entry, char *buf)
406433d6423SLionel Sambuc {
407433d6423SLionel Sambuc switch(entry->type) {
408433d6423SLionel Sambuc
409433d6423SLionel Sambuc case DEVMAN_DEVINFO_STATIC:
410433d6423SLionel Sambuc return devman_dev_add_static_info(dev,
411433d6423SLionel Sambuc buf + entry->name_offset, buf + entry->data_offset);
412433d6423SLionel Sambuc
413433d6423SLionel Sambuc case DEVMAN_DEVINFO_DYNAMIC:
414433d6423SLionel Sambuc /* TODO */
415433d6423SLionel Sambuc /* fall through */
416433d6423SLionel Sambuc default:
417433d6423SLionel Sambuc return -1;
418433d6423SLionel Sambuc }
419433d6423SLionel Sambuc }
420433d6423SLionel Sambuc
421433d6423SLionel Sambuc /*===========================================================================*
422433d6423SLionel Sambuc * do_del_device *
423433d6423SLionel Sambuc *===========================================================================*/
do_del_device(message * msg)424433d6423SLionel Sambuc int do_del_device(message *msg)
425433d6423SLionel Sambuc {
426433d6423SLionel Sambuc int dev_id = msg->DEVMAN_DEVICE_ID;
427433d6423SLionel Sambuc
428433d6423SLionel Sambuc int res=0;
429433d6423SLionel Sambuc
430433d6423SLionel Sambuc /* only parrent is allowed to add devices */
431433d6423SLionel Sambuc struct devman_device *dev = _find_dev(&root_dev, dev_id);
432433d6423SLionel Sambuc
433433d6423SLionel Sambuc if (dev == NULL ) {
434433d6423SLionel Sambuc printf("devman: no dev with id %d\n",dev_id);
435433d6423SLionel Sambuc res = ENODEV;
436433d6423SLionel Sambuc }
437433d6423SLionel Sambuc
438433d6423SLionel Sambuc #if 0
439433d6423SLionel Sambuc if (dev->parent->owner != ep) {
440433d6423SLionel Sambuc res = EPERM;
441433d6423SLionel Sambuc }
442433d6423SLionel Sambuc #endif
443433d6423SLionel Sambuc
444433d6423SLionel Sambuc if (!res) {
445433d6423SLionel Sambuc devman_device_remove_event(dev);
446433d6423SLionel Sambuc if (dev->state == DEVMAN_DEVICE_BOUND) {
447433d6423SLionel Sambuc dev->state = DEVMAN_DEVICE_ZOMBIE;
448433d6423SLionel Sambuc }
449433d6423SLionel Sambuc devman_put_device(dev);
450433d6423SLionel Sambuc }
451433d6423SLionel Sambuc
452433d6423SLionel Sambuc do_reply(msg, res);
453433d6423SLionel Sambuc
454433d6423SLionel Sambuc return 0;
455433d6423SLionel Sambuc }
456433d6423SLionel Sambuc
457433d6423SLionel Sambuc /*===========================================================================*
458433d6423SLionel Sambuc * devman_get_device *
459433d6423SLionel Sambuc *===========================================================================*/
devman_get_device(struct devman_device * dev)460433d6423SLionel Sambuc void devman_get_device(struct devman_device *dev)
461433d6423SLionel Sambuc {
462433d6423SLionel Sambuc if (dev == NULL || dev == &root_dev) {
463433d6423SLionel Sambuc return;
464433d6423SLionel Sambuc }
465433d6423SLionel Sambuc dev->ref_count++;
466433d6423SLionel Sambuc }
467433d6423SLionel Sambuc
468433d6423SLionel Sambuc /*===========================================================================*
469433d6423SLionel Sambuc * devman_put_device *
470433d6423SLionel Sambuc *===========================================================================*/
devman_put_device(struct devman_device * dev)471433d6423SLionel Sambuc void devman_put_device(struct devman_device *dev)
472433d6423SLionel Sambuc {
473433d6423SLionel Sambuc if (dev == NULL || dev == &root_dev ) {
474433d6423SLionel Sambuc return;
475433d6423SLionel Sambuc }
476433d6423SLionel Sambuc dev->ref_count--;
477433d6423SLionel Sambuc if (dev->ref_count == 0) {
478433d6423SLionel Sambuc devman_del_device(dev);
479433d6423SLionel Sambuc }
480433d6423SLionel Sambuc }
481433d6423SLionel Sambuc
482433d6423SLionel Sambuc /*===========================================================================*
483433d6423SLionel Sambuc * devman_del_device *
484433d6423SLionel Sambuc *===========================================================================*/
devman_del_device(struct devman_device * dev)485433d6423SLionel Sambuc static int devman_del_device(struct devman_device *dev)
486433d6423SLionel Sambuc {
487433d6423SLionel Sambuc /* does device have children -> error */
488433d6423SLionel Sambuc /* evtl. remove links */
489433d6423SLionel Sambuc
490433d6423SLionel Sambuc /* free devinfo inodes */
491433d6423SLionel Sambuc struct devman_inode *inode, *_inode;
492433d6423SLionel Sambuc
493433d6423SLionel Sambuc TAILQ_FOREACH_SAFE(inode, &dev->infos, inode_list, _inode) {
494433d6423SLionel Sambuc
495433d6423SLionel Sambuc delete_inode(inode->inode);
496433d6423SLionel Sambuc
497433d6423SLionel Sambuc TAILQ_REMOVE(&dev->infos, inode, inode_list);
498433d6423SLionel Sambuc
499433d6423SLionel Sambuc if (inode->data) {
500433d6423SLionel Sambuc free(inode->data);
501433d6423SLionel Sambuc }
502433d6423SLionel Sambuc
503433d6423SLionel Sambuc free(inode);
504433d6423SLionel Sambuc }
505433d6423SLionel Sambuc
506433d6423SLionel Sambuc /* free device inode */
507433d6423SLionel Sambuc delete_inode(dev->inode.inode);
508433d6423SLionel Sambuc
509433d6423SLionel Sambuc /* remove from parent */
510433d6423SLionel Sambuc TAILQ_REMOVE(&dev->parent->children, dev, siblings);
511433d6423SLionel Sambuc
512433d6423SLionel Sambuc devman_put_device(dev->parent);
513433d6423SLionel Sambuc
514433d6423SLionel Sambuc /* free devinfo */
515433d6423SLionel Sambuc free(dev->info);
516433d6423SLionel Sambuc
517433d6423SLionel Sambuc /* free device */
518433d6423SLionel Sambuc free(dev);
519433d6423SLionel Sambuc return 0;
520433d6423SLionel Sambuc }
521