9
0
Fork 0

- introduce ioctl call

- pass open/close/lseek through to drivers
This commit is contained in:
Sascha Hauer 2008-06-06 09:25:13 +02:00
parent 3f73e61600
commit ee6d36a540
10 changed files with 194 additions and 10 deletions

View File

@ -120,6 +120,9 @@ int open_and_lseek(const char *filename, int mode, ulong pos)
return fd;
}
if (!pos)
return fd;
ret = lseek(fd, pos, SEEK_SET);
if (ret < 0) {
perror("lseek");
@ -525,22 +528,31 @@ static struct device_d mem_dev = {
static struct driver_d mem_drv = {
.name = "mem",
.probe = dummy_probe,
.open = dev_open_default,
.close = dev_close_default,
.read = mem_read,
.write = mem_write,
.lseek = dev_lseek_default,
};
static struct driver_d ram_drv = {
.name = "ram",
.probe = dummy_probe,
.open = dev_open_default,
.close = dev_close_default,
.read = mem_read,
.write = mem_write,
.lseek = dev_lseek_default,
.type = DEVICE_TYPE_DRAM,
};
static struct driver_d rom_drv = {
.name = "rom",
.probe = dummy_probe,
.open = dev_open_default,
.close = dev_close_default,
.read = mem_read,
.lseek = dev_lseek_default,
};
static int mem_init(void)

View File

@ -32,6 +32,9 @@
#include <errno.h>
#include <partition.h>
#include <xfuncs.h>
#include <ioctl.h>
#include <nand.h>
#include <linux/mtd/mtd-abi.h>
/**
* Add one partition on top of a device, as a device.
@ -168,6 +171,43 @@ static ssize_t part_write(struct device_d *dev, const void *buf, size_t count,
return dev_write(part->physdev, buf, count, offset + part->offset, flags);
}
static off_t part_lseek(struct device_d *dev, off_t ofs)
{
struct partition *part = dev->type_data;
return dev_lseek(part->physdev, ofs);
}
static int part_open(struct device_d *dev, struct filep *f)
{
struct partition *part = dev->type_data;
return dev_open(part->physdev, f);
}
static int part_close(struct device_d *dev, struct filep *f)
{
struct partition *part = dev->type_data;
return dev_close(part->physdev, f);
}
static int part_ioctl(struct device_d *dev, int request,
void *buf)
{
struct partition *part = dev->type_data;
off_t offset;
switch (request) {
case MEMGETBADBLOCK:
offset = (off_t)buf;
offset += part->offset;
return dev_ioctl(part->physdev, request, (void *)offset);
}
return -ENOSYS;
}
/**
* FIXME.
* @param[in] dev The partition info as a device
@ -201,8 +241,12 @@ struct driver_d part_driver = {
.name = "partition",
.probe = part_probe,
.remove = part_remove,
.open = part_open,
.close = part_close,
.ioctl = part_ioctl,
.read = part_read,
.write = part_write,
.lseek = part_lseek,
.erase = part_erase,
.protect= part_protect,
.memmap = part_memmap,

View File

@ -524,6 +524,9 @@ static struct driver_d cfi_driver = {
.probe = cfi_probe,
.read = mem_read,
.write = cfi_write,
.lseek = dev_lseek_default,
.open = dev_open_default,
.close = dev_close_default,
.erase = cfi_erase,
.protect= cfi_protect,
.memmap = generic_memmap_ro,

View File

@ -352,6 +352,12 @@ static int cramfs_read(struct device_d *_dev, FILE *f, void *buf, size_t size)
return outsize;
}
static off_t cramfs_lseek(struct device_d *dev, FILE *f, off_t pos)
{
f->pos = pos;
return f->pos;
}
static int cramfs_stat(struct device_d *_dev, const char *filename, struct stat *stat)
{
struct cramfs_priv *priv = _dev->priv;
@ -443,6 +449,7 @@ static struct fs_driver_d cramfs_driver = {
.open = cramfs_open,
.close = cramfs_close,
.read = cramfs_read,
.lseek = cramfs_lseek,
.opendir = cramfs_opendir,
.readdir = cramfs_readdir,
.closedir = cramfs_closedir,

View File

@ -44,6 +44,19 @@ static int devfs_write(struct device_d *_dev, FILE *f, const void *buf, size_t s
return dev_write(dev, buf, size, f->pos, f->flags);
}
static off_t devfs_lseek(struct device_d *_dev, FILE *f, off_t pos)
{
struct device_d *dev = f->inode;
int ret;
ret = dev_lseek(dev, pos);
if (ret >= 0)
f->pos = pos;
return ret;
}
static int devfs_erase(struct device_d *_dev, FILE *f, size_t count, unsigned long offset)
{
struct device_d *dev = f->inode;
@ -65,21 +78,30 @@ static int devfs_memmap(struct device_d *_dev, FILE *f, void **map, int flags)
return dev_memmap(dev, map, flags);
}
static int devfs_open(struct device_d *_dev, FILE *file, const char *filename)
static int devfs_open(struct device_d *_dev, FILE *f, const char *filename)
{
struct device_d *dev = get_device_by_id(filename + 1);
if (!dev)
return -ENOENT;
file->size = dev->size;
file->inode = dev;
return 0;
f->size = dev->size;
f->inode = dev;
return dev_open(dev, f);
}
static int devfs_close(struct device_d *dev, FILE *f)
static int devfs_close(struct device_d *_dev, FILE *f)
{
return 0;
struct device_d *dev = f->inode;
return dev_close(dev, f);
}
static int devfs_ioctl(struct device_d *_dev, FILE *f, int request, void *buf)
{
struct device_d *dev = f->inode;
return dev_ioctl(dev, request, buf);
}
static int devfs_truncate(struct device_d *dev, FILE *f, ulong size)
@ -156,8 +178,10 @@ static struct fs_driver_d devfs_driver = {
.type = FS_TYPE_DEVFS,
.read = devfs_read,
.write = devfs_write,
.lseek = devfs_lseek,
.open = devfs_open,
.close = devfs_close,
.ioctl = devfs_ioctl,
.opendir = devfs_opendir,
.readdir = devfs_readdir,
.truncate = devfs_truncate,

34
fs/fs.c
View File

@ -451,6 +451,22 @@ int creat(const char *pathname, mode_t mode)
}
EXPORT_SYMBOL(creat);
int ioctl(int fd, int request, void *buf)
{
struct device_d *dev;
struct fs_driver_d *fsdrv;
FILE *f = &files[fd];
dev = f->dev;
fsdrv = (struct fs_driver_d *)dev->driver->type_data;
if (fsdrv->ioctl)
return fsdrv->ioctl(dev, f, request, buf);
return -ENOSYS;
}
int read(int fd, void *buf, size_t count)
{
struct device_d *dev;
@ -496,30 +512,40 @@ EXPORT_SYMBOL(write);
off_t lseek(int fildes, off_t offset, int whence)
{
struct device_d *dev;
struct fs_driver_d *fsdrv;
FILE *f = &files[fildes];
ulong pos;
errno = 0;
dev = f->dev;
fsdrv = (struct fs_driver_d *)dev->driver->type_data;
if (!fsdrv->lseek)
return -ENOSYS;
switch(whence) {
case SEEK_SET:
if (offset > f->size)
goto out;
f->pos = offset;
pos = offset;
break;
case SEEK_CUR:
if (offset + f->pos > f->size)
goto out;
f->pos += offset;
pos = f->pos + offset;
break;
case SEEK_END:
if (offset)
goto out;
f->pos = f->size;
pos = f->size;
break;
default:
goto out;
}
return 0;
return fsdrv->lseek(dev, f, pos);
out:
errno = -EINVAL;
return errno;

View File

@ -403,6 +403,12 @@ static int ramfs_write(struct device_d *_dev, FILE *f, const void *buf, size_t i
return insize;
}
static off_t ramfs_lseek(struct device_d *dev, FILE *f, off_t pos)
{
f->pos = pos;
return f->pos;
}
static int ramfs_truncate(struct device_d *dev, FILE *f, ulong size)
{
struct ramfs_inode *node = (struct ramfs_inode *)f->inode;
@ -540,6 +546,7 @@ static struct fs_driver_d ramfs_driver = {
.truncate = ramfs_truncate,
.read = ramfs_read,
.write = ramfs_write,
.lseek = ramfs_lseek,
.mkdir = ramfs_mkdir,
.rmdir = ramfs_rmdir,
.opendir = ramfs_opendir,

View File

@ -64,6 +64,8 @@
/*@{*/ /* do not delete, doxygen relevant */
struct filep;
/** @brief Describes a particular device present in the system */
struct device_d {
/*! This member (and 'type' described below) is used to match with a
@ -131,6 +133,11 @@ struct driver_d {
/*! Called in response of write to this device. Required */
ssize_t (*write) (struct device_d*, const void* buf, size_t count, ulong offset, ulong flags);
int (*ioctl) (struct device_d*, int, void *);
off_t (*lseek) (struct device_d*, off_t);
int (*open) (struct device_d*, struct filep*);
int (*close) (struct device_d*, struct filep*);
int (*erase) (struct device_d*, size_t count, unsigned long offset);
int (*protect)(struct device_d*, size_t count, unsigned long offset, int prot);
@ -219,6 +226,10 @@ struct driver_d *get_driver_by_name(const char *name);
ssize_t dev_read(struct device_d *dev, void *buf, size_t count, ulong offset, ulong flags);
ssize_t dev_write(struct device_d *dev, const void *buf, size_t count, ulong offset, ulong flags);
int dev_open(struct device_d *dev, struct filep *);
int dev_close(struct device_d *dev, struct filep *);
int dev_ioctl(struct device_d *dev, int, void *);
off_t dev_lseek(struct device_d *dev, off_t offset);
int dev_erase(struct device_d *dev, size_t count, unsigned long offset);
int dev_protect(struct device_d *dev, size_t count, unsigned long offset, int prot);
int dev_memmap(struct device_d *dev, void **map, int flags);
@ -233,5 +244,20 @@ int dummy_probe(struct device_d *);
int generic_memmap_ro(struct device_d *dev, void **map, int flags);
int generic_memmap_rw(struct device_d *dev, void **map, int flags);
static inline off_t dev_lseek_default(struct device_d *dev, off_t ofs)
{
return ofs;
}
static inline int dev_open_default(struct device_d *dev, struct filep *f)
{
return 0;
}
static inline int dev_close_default(struct device_d *dev, struct filep *f)
{
return 0;
}
#endif /* DRIVER_H */

View File

@ -58,12 +58,14 @@ struct fs_driver_d {
int (*close)(struct device_d *dev, FILE *f);
int (*read)(struct device_d *dev, FILE *f, void *buf, size_t size);
int (*write)(struct device_d *dev, FILE *f, const void *buf, size_t size);
off_t (*lseek)(struct device_d *dev, FILE *f, off_t pos);
struct dir* (*opendir)(struct device_d *dev, const char *pathname);
struct dirent* (*readdir)(struct device_d *dev, struct dir *dir);
int (*closedir)(struct device_d *dev, DIR *dir);
int (*stat)(struct device_d *dev, const char *file, struct stat *stat);
int (*ioctl)(struct device_d *dev, FILE *f, int request, void *buf);
int (*erase)(struct device_d *dev, FILE *f, size_t count,
unsigned long offset);
int (*protect)(struct device_d *dev, FILE *f, size_t count,
@ -101,6 +103,7 @@ int unlink(const char *pathname);
int close(int fd);
int stat(const char *filename, struct stat *s);
int read(int fd, void *buf, size_t count);
int ioctl(int fd, int request, void *buf);
ssize_t write(int fd, const void *buf, size_t count);
#define SEEK_SET 1

View File

@ -212,6 +212,38 @@ ssize_t dev_write(struct device_d *dev, const void *buf, size_t count, unsigned
return -ENOSYS;
}
off_t dev_lseek(struct device_d *dev, off_t offset)
{
if (dev->driver->lseek)
return dev->driver->lseek(dev, offset);
errno = -ENOSYS;
return -ENOSYS;
}
int dev_open(struct device_d *dev, struct filep *f)
{
if (dev->driver->open)
return dev->driver->open(dev, f);
errno = -ENOSYS;
return -ENOSYS;
}
int dev_close(struct device_d *dev, struct filep *f)
{
if (dev->driver->close)
return dev->driver->close(dev, f);
errno = -ENOSYS;
return -ENOSYS;
}
int dev_ioctl(struct device_d *dev, int request, void *buf)
{
if (dev->driver->ioctl)
return dev->driver->ioctl(dev, request, buf);
errno = -ENOSYS;
return -ENOSYS;
}
int dev_erase(struct device_d *dev, size_t count, unsigned long offset)
{
if (dev->driver->erase)