source: trunk/kernel/fs/devfs/devfs_file.c @ 2

Last change on this file since 2 was 1, checked in by alain, 8 years ago

First import

File size: 5.5 KB
RevLine 
[1]1/*
2 * devfs/devfs_file.c - devfs file related operations
3 *
4 * Copyright (c) 2008,2009,2010,2011,2012 Ghassan Almaless
5 * Copyright (c) 2011,2012 UPMC Sorbonne Universites
6 *
7 * This file is part of ALMOS-kernel.
8 *
9 * ALMOS-kernel is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; version 2.0 of the License.
12 *
13 * ALMOS-kernel is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with ALMOS-kernel; if not, write to the Free Software Foundation,
20 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22
23#include <config.h>
24#include <device.h>
25#include <driver.h>
26#include <kmem.h>
27#include <string.h>
28#include <vfs.h>
29#include <errno.h>
30#include <metafs.h>
31#include <thread.h>
32
33#include <devfs.h>
34#include <devfs-private.h>
35
36
37KMEM_OBJATTR_INIT(devfs_kmem_file_init)
38{
39        attr->type   = KMEM_DEVFS_FILE;
40        attr->name   = "KCM DevFs File";
41        attr->size   = sizeof(struct devfs_file_s);
42        attr->aligne = 0;
43        attr->min    = CONFIG_DEVFS_FILE_MIN;
44        attr->max    = CONFIG_DEVFS_FILE_MAX;
45        attr->ctor   = NULL;
46        attr->dtor   = NULL;
47        return 0;
48}
49
50VFS_OPEN_FILE(devfs_open)
51{
52        register error_t err;
53        register struct devfs_context_s *ctx;
54        register struct devfs_file_s *info;
55        register struct device_s *dev;
56        struct vfs_inode_s *inode;
57        dev_request_t rq;
58        kmem_req_t req;
59
60        inode = file->fr_inode;
61
62        info = file->fr_pv;
63        ctx  = (struct devfs_context_s *)&inode->i_ctx->ctx_devfs;
64
65        if(!(inode->i_attr & VFS_DIR))
66        {
67                dev = (struct device_s*)inode->i_pv;
68   
69                if(dev->type == DEV_INTERNAL)
70                        return EPERM;
71
72                if(dev->type == DEV_BLK)
73                        VFS_SET(inode->i_attr,VFS_DEV_BLK);
74                else
75                        VFS_SET(inode->i_attr,VFS_DEV_CHR);
76 
77                if(dev->op.dev.open != NULL)
78                {
79                        rq.fremote = file;
80                        if((err=dev->op.dev.open(dev, &rq)))
81                                return err;
82                }
83
84                priv->dev = (void*)dev;
85
86                return 0;
87        }
88
89        if(info == NULL)
90        {
91                req.type  = KMEM_DEVFS_FILE;
92                req.size  = sizeof(*info);
93                req.flags = AF_KERNEL;
94                info      = kmem_alloc(&req);
95        }
96
97        if(info == NULL) return ENOMEM;
98
99        metafs_iter_init(&devfs_db.root, &info->iter);
100        info->ctx  = ctx;
101        file->fr_pv = info;
102 
103        metafs_print(&devfs_db.root);
104        return 0;
105}
106
107#define TMP_BUFF_SZ 512
108//FIXME:
109//add a "while" loop for the case where the
110//buffer TMP_BUFF_SZ is smaller than
111//buffer->size
112VFS_READ_FILE(devfs_read)
113{
114        register struct device_s *dev;
115        dev_request_t rq;
116        uint_t count;
117        uint8_t buff[TMP_BUFF_SZ];
118
119        dev = (struct device_s*)file->f_private.dev;
120
121        rq.dst   = &buff[0];
122        rq.count = TMP_BUFF_SZ;
123        rq.flags = 0;
124        rq.file  = file;
125
126        if((count = dev->op.dev.read(dev, &rq)) < 0)
127                return count;
128
129        buffer->scpy_to_buff(buffer, &buff[0], count);
130        return count;
131}
132
133//FIXME: To improve this an avoid the extra copy,
134//we could set along with the buffer(src and dest)
135//the functions to manipulate them, such as in
136//do_exec.c
137VFS_WRITE_FILE(devfs_write)
138{
139        register struct device_s *dev;
140        uint8_t buff[TMP_BUFF_SZ];
141        dev_request_t rq;
142       
143        dev = (struct device_s*)file->f_private.dev;
144       
145        //FIXME avoid the extra copy ?
146        buffer->scpy_from_buff(buffer, (void*)&buff[0], TMP_BUFF_SZ);
147        rq.src   = (void*)&buff[0];
148        rq.count = buffer->size;
149        rq.flags = 0;
150        rq.file  = file;
151 
152        return dev->op.dev.write(dev, &rq);
153}
154
155VFS_LSEEK_FILE(devfs_lseek)
156{
157        register struct device_s *dev;
158        dev_request_t rq;
159
160        dev = (struct device_s*)file->fr_inode->i_pv;
161
162        if(dev->op.dev.lseek == NULL)
163                return VFS_ENOTUSED;
164 
165        rq.fremote = file;
166        return dev->op.dev.lseek(dev, &rq);
167}
168
169VFS_CLOSE_FILE(devfs_close)
170{
171        register struct device_s *dev;
172        dev_request_t rq;
173
174        if(file->fr_inode->i_attr & VFS_DIR)
175                return 0;
176
177        dev = (struct device_s*)file->fr_inode->i_pv;
178
179        if(dev->op.dev.close == NULL)
180                return 0;
181 
182        rq.fremote = file;
183        return dev->op.dev.close(dev, &rq);
184}
185
186VFS_RELEASE_FILE(devfs_release)
187{ 
188        kmem_req_t req;
189
190        if(file->fr_pv == NULL) 
191                return 0;
192 
193        req.type = KMEM_DEVFS_FILE;
194        req.ptr  = file->fr_pv;
195        kmem_free(&req);
196
197        file->fr_pv = NULL;
198        return 0;
199}
200
201VFS_READ_DIR(devfs_readdir)
202{
203        register struct devfs_file_s *info;
204        register struct metafs_s *current;
205        register struct device_s *current_dev;
206 
207        info = file->fr_pv;
208 
209        if(file->fr_pv == NULL)
210                return ENOTDIR;
211
212        if((current = metafs_lookup_next(&devfs_db.root, &info->iter)) == NULL)
213                return EEODIR;
214
215        current_dev    = metafs_container(current, struct device_s, node);
216        dirent->u_attr = (current_dev->type == DEV_BLK) ? VFS_DEV_BLK : VFS_DEV_CHR;
217
218        strcpy((char*)dirent->u_name, metafs_get_name(current));
219
220        dirent->u_ino = (uint_t) current_dev->base_paddr;
221
222        return 0;
223}
224
225VFS_MMAP_FILE(devfs_mmap)
226{
227        register struct device_s *dev;
228        dev_request_t rq;
229 
230        dev = (struct device_s*)file->f_private.dev;
231
232        if(dev->op.dev.mmap == NULL)
233                return ENODEV;
234
235        rq.flags  = 0;
236        rq.file   = file;
237        rq.region = region;
238
239        return dev->op.dev.mmap(dev, &rq);
240}
241
242VFS_MMAP_FILE(devfs_munmap)
243{
244        register struct device_s *dev;
245        dev_request_t rq;
246
247        dev = (struct device_s*)file->f_private.dev;
248
249        if(dev->op.dev.munmap == NULL)
250                return ENODEV;
251
252        rq.flags  = 0;
253        rq.file   = file;
254        rq.region = region;
255
256        return dev->op.dev.munmap(dev, &rq);
257}
258
259
260const struct vfs_file_op_s devfs_f_op = 
261{
262        .open    = devfs_open,
263        .read    = devfs_read,
264        .write   = devfs_write,
265        .lseek   = devfs_lseek,
266        .mmap    = devfs_mmap,
267        .munmap  = devfs_munmap,
268        .readdir = devfs_readdir,
269        .close   = devfs_close,
270        .release = devfs_release
271};
Note: See TracBrowser for help on using the repository browser.