diff options
Diffstat (limited to 'sys/fs/devfs.c')
-rw-r--r-- | sys/fs/devfs.c | 295 |
1 files changed, 0 insertions, 295 deletions
diff --git a/sys/fs/devfs.c b/sys/fs/devfs.c deleted file mode 100644 index 7fcdbad..0000000 --- a/sys/fs/devfs.c +++ /dev/null @@ -1,295 +0,0 @@ -/* - * Copyright (c) 2023-2024 Ian Marco Moffett and the Osmora Team. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Hyra nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include <fs/devfs.h> -#include <sys/vfs.h> -#include <sys/mount.h> -#include <sys/spinlock.h> -#include <sys/queue.h> -#include <sys/vnode.h> -#include <sys/errno.h> -#include <sys/cdefs.h> -#include <vm/dynalloc.h> -#include <string.h> - -struct device_node { - struct spinlock lock; - char *name; - uint8_t is_block : 1; - dev_t major, minor; - TAILQ_ENTRY(device_node) link; -}; - -static TAILQ_HEAD(, device_node) nodes; -static bool nodelist_init = false; - -static struct device_node * -node_from_name(const char *name) -{ - struct device_node *n; - - TAILQ_FOREACH(n, &nodes, link) { - if (strcmp(n->name, name) == 0) { - return n; - } - } - - return NULL; -} - -static int -cdev_read(struct device *dev, struct device_node *node, struct sio_txn *sio) -{ - size_t n_bytes; - - spinlock_acquire(&node->lock); - n_bytes = dev->read(dev, sio); - spinlock_release(&node->lock); - return n_bytes; -} - -static int -blkdev_read(struct device *dev, struct device_node *node, struct sio_txn *sio) -{ - char *buf; - struct sio_txn dev_txn = {0}; - size_t n_blocks = __DIV_ROUNDUP(sio->len, dev->blocksize); - size_t n_bytes = n_blocks * dev->blocksize; - size_t cpy_off; - - if (dev->blocksize == 0 || sio->len == 0) { - /* Sizes can't be zero! */ - return -EIO; - } - - spinlock_acquire(&node->lock); - buf = dynalloc_memalign(n_bytes, 0x1000); - - if (buf == NULL) { - spinlock_release(&node->lock); - return -ENOMEM; - } - - dev_txn.len = n_blocks; - dev_txn.buf = buf; - dev_txn.offset = sio->offset / dev->blocksize; - dev->read(dev, &dev_txn); - spinlock_release(&node->lock); - - cpy_off = sio->offset - (dev_txn.offset * dev->blocksize); - for (size_t i = 0; i < sio->len; ++i) { - ((uint8_t *)sio->buf)[i] = buf[i + cpy_off]; - } - - dynfree(buf); - return sio->len; -} - -static int -vop_vget(struct vnode *parent, const char *name, struct vnode **vp) -{ - struct device_node *dev; - struct vnode *vnode; - int status, vtype; - - if (!nodelist_init) { - return -EIO; - } - - if ((dev = node_from_name(name)) == NULL) { - return -ENOENT; - } - - vtype = dev->is_block ? VBLK : VCHR; - if ((status = vfs_alloc_vnode(&vnode, NULL, vtype)) != 0) { - return status; - } - - vnode->parent = parent; - vnode->data = dev; - vnode->vops = &g_devfs_vops; - *vp = vnode; - return 0; -} - -static int -vop_read(struct vnode *vp, struct sio_txn *sio) -{ - struct device_node *node; - struct device *dev; - - if (vp == NULL) { - return -EIO; - } - - node = vp->data; - dev = device_fetch(node->major, node->minor); - - if (dev->blocksize > 1) - return blkdev_read(dev, node, sio); - - return cdev_read(dev, node, sio); -} - -static int -vop_open(struct vnode *vp) -{ - struct device_node *node; - struct device *dev; - - if (vp == NULL) { - return -EIO; - } - - node = vp->data; - dev = device_fetch(node->major, node->minor); - - if (dev->open == NULL) { - return -EIO; - } - - return dev->open(dev); -} - -static int -vop_close(struct vnode *vp) -{ - struct device_node *node; - struct device *dev; - - if (vp == NULL) { - return -EIO; - } - - node = vp->data; - dev = device_fetch(node->major, node->minor); - - if (dev->close == NULL) { - return -EIO; - } - - return dev->close(dev); -} - -static int -devfs_init(struct fs_info *info, struct vnode *source) -{ - if (source != NULL) - return -EINVAL; - - TAILQ_INIT(&nodes); - nodelist_init = true; - return 0; -} - -static int -devfs_make_devicenode(const char *name, struct device_node **node_out) -{ - size_t name_len = 0; - const char *p = name; - struct device_node *node; - - /* - * Only one filename, no paths. - * - * TODO: Do something better here... - */ - for (; *p; ++p, ++name_len) { - if (*p == '/') - return -EINVAL; - } - - /* Ensure this filename has valid chars */ - if (!vfs_is_valid_path(name)) { - return -EINVAL; - } - - node = dynalloc(sizeof(struct device_node)); - if (node == NULL) - return -ENOMEM; - - node->name = dynalloc(sizeof(char) * name_len); - if (node->name == NULL) - return -ENOMEM; - - memcpy(node->name, name, name_len + 1); - *node_out = node; - return 0; -} - -int -devfs_add_dev(const char *name, const struct device *dev) -{ - struct device_node *node; - int status; - - if ((status = devfs_make_devicenode(name, &node)) != 0) { - return status; - } - - node->major = dev->major; - node->minor = dev->minor; - node->is_block = dev->blocksize > 1; - TAILQ_INSERT_HEAD(&nodes, node, link); - return 0; -} - -/* - * Fetch a device descriptor from a vnode. - */ -int -devfs_get_dev(struct vnode *vp, struct device **res) -{ - struct device_node *n; - struct device *dev; - - /* Is this really a device? */ - if (vp->type != VBLK && vp->type != VCHR) { - return -ENODEV; - } - - n = vp->data; - if ((dev = device_fetch(n->major, n->minor)) == NULL) { - return -ENODEV; - } - - *res = dev; - return 0; -} - -struct vfsops g_devfs_ops = { - .init = devfs_init -}; - -struct vops g_devfs_vops = { - .vget = vop_vget, - .read = vop_read, - .open = vop_open, - .close = vop_close -}; |