#ifndef __LUNAIX_CONSTANTS_H
#define __LUNAIX_CONSTANTS_H
+#define PG_SIZE_BITS 12
+#define PG_SIZE (1 << PG_SIZE_BITS)
+#define PG_INDEX_BITS 10
+
#define MEM_1MB 0x100000
#define MEM_4MB 0x400000
void* underlay;
int (*read)(struct device* dev, void* buf, size_t offset, size_t len);
int (*write)(struct device* dev, void* buf, size_t offset, size_t len);
+ int (*read_page)(struct device* dev, void* buf, size_t offset);
+ int (*write_page)(struct device* dev, void* buf, size_t offset);
int (*exec_cmd)(struct device* dev, uint32_t req, va_list args);
};
{
int (*write)(struct v_inode* inode, void* buffer, size_t len, size_t fpos);
int (*read)(struct v_inode* inode, void* buffer, size_t len, size_t fpos);
+
+ // for operatiosn {write|read}_page, following are true:
+ // + `len` always equals to PG_SIZE
+ // + `fpos` always PG_SIZE aligned.
+ // These additional operations allow underlying fs to use more specialized
+ // and optimized code.
+
+ int (*write_page)(struct v_inode* inode, void* pg, size_t len, size_t fpos);
+ int (*read_page)(struct v_inode* inode, void* pg, size_t len, size_t fpos);
+
int (*readdir)(struct v_file* file, struct dir_context* dctx);
int (*seek)(struct v_inode* inode, size_t offset); // optional
int (*close)(struct v_file* file);
#include <lunaix/common.h>
#include <stdint.h>
-#define PG_SIZE_BITS 12
-#define PG_SIZE (1 << PG_SIZE_BITS)
-#define PG_INDEX_BITS 10
-
#define PG_MAX_ENTRIES 1024U
#define PG_LAST_TABLE PG_MAX_ENTRIES - 1
#define PG_FIRST_TABLE 0
return errno;
}
+int
+__block_read_page(struct device* dev, void* buf, size_t offset)
+{
+ struct vecbuf* vbuf = NULL;
+ struct block_dev* bdev = (struct block_dev*)dev->underlay;
+
+ u32_t lba = offset / bdev->blk_size + bdev->start_lba;
+ u32_t rd_lba = MIN(lba + PG_SIZE / bdev->blk_size, bdev->end_lba);
+
+ if (rd_lba <= lba) {
+ return 0;
+ }
+
+ rd_lba -= lba;
+
+ vbuf_alloc(&vbuf, buf, rd_lba * bdev->blk_size);
+
+ struct blkio_req* req = blkio_vrd(vbuf, lba, NULL, NULL, 0);
+
+ blkio_commit(bdev->blkio, req, BLKIO_WAIT);
+
+ int errno = req->errcode;
+ if (!errno) {
+ errno = rd_lba * bdev->blk_size;
+ } else {
+ errno = -errno;
+ }
+
+ blkio_free_req(req);
+ vbuf_free(vbuf);
+ return errno;
+}
+
+int
+__block_write_page(struct device* dev, void* buf, size_t offset)
+{
+ struct vecbuf* vbuf = NULL;
+ struct block_dev* bdev = (struct block_dev*)dev->underlay;
+
+ u32_t lba = offset / bdev->blk_size + bdev->start_lba;
+ u32_t rd_lba = MIN(lba + PG_SIZE / bdev->blk_size, bdev->end_lba);
+
+ if (rd_lba <= lba) {
+ return 0;
+ }
+
+ rd_lba -= lba;
+
+ vbuf_alloc(&vbuf, buf, rd_lba * bdev->blk_size);
+
+ struct blkio_req* req = blkio_vwr(vbuf, lba, NULL, NULL, 0);
+
+ blkio_commit(bdev->blkio, req, BLKIO_WAIT);
+
+ int errno = req->errcode;
+ if (!errno) {
+ errno = rd_lba * bdev->blk_size;
+ } else {
+ errno = -errno;
+ }
+
+ blkio_free_req(req);
+ vbuf_free(vbuf);
+ return errno;
+}
+
int
__block_rd_lb(struct block_dev* bdev, void* buf, u64_t start, size_t count)
{
struct device* dev = device_addvol(NULL, bdev, "sd%c", 'a' + free_slot);
dev->write = __block_write;
+ dev->write_page = __block_write_page;
dev->read = __block_read;
+ dev->read_page = __block_read_page;
bdev->dev = dev;
strcpy(bdev->bdev_id, dev->name_val);
struct device* dev =
device_addvol(NULL, pbdev, "%sp%d", bdev->bdev_id, index + 1);
dev->write = __block_write;
+ dev->write_page = __block_write_page;
dev->read = __block_read;
+ dev->read_page = __block_read_page;
pbdev->start_lba = start_lba;
pbdev->end_lba = end_lba;
return dev->write(dev, buffer, fpos, len);
}
+int
+devfs_read_page(struct v_inode* inode, void* buffer, size_t len, size_t fpos)
+{
+ assert(inode->data);
+
+ struct device* dev = (struct device*)inode->data;
+
+ if (!dev->read_page) {
+ return ENOTSUP;
+ }
+
+ return dev->read_page(dev, buffer, fpos);
+}
+
+int
+devfs_write_page(struct v_inode* inode, void* buffer, size_t len, size_t fpos)
+{
+ assert(inode->data);
+
+ struct device* dev = (struct device*)inode->data;
+
+ if (!dev->read_page) {
+ return ENOTSUP;
+ }
+
+ return dev->read_page(dev, buffer, fpos);
+}
+
int
devfs_get_itype(struct device* dev)
{
struct v_file_ops devfs_file_ops = { .close = default_file_close,
.read = devfs_read,
+ .read_page = devfs_read_page,
.write = devfs_write,
+ .write_page = devfs_write_page,
.seek = default_file_seek,
.readdir = devfs_readdir };
\ No newline at end of file
return sizeof(struct input_evt_pkt);
}
+int
+__input_dev_read_pg(struct device* dev, void* buf, size_t offset)
+{
+ return __input_dev_read(dev, buf, offset, PG_SIZE);
+}
+
struct input_device*
input_add_device(char* name_fmt, ...)
{
idev->dev_if = dev;
dev->read = __input_dev_read;
+ dev->read_page = __input_dev_read_pg;
va_end(args);
u32_t l = drec->name.len;
while (l < (u32_t)-1 && drec->name.content[l--] != ';')
;
- l = (l + 1) ? l : drec->name.len;
- l = MIN(l, ISO9660_IDLEN);
+ l++;
+ l = l ? l : drec->name.len;
+ l = MIN(l, ISO9660_IDLEN - 1);
+
strncpy(cache->name_val, drec->name.content, l);
cache->name = HSTR(cache->name_val, l);
hstr_rehash(&cache->name, HSTR_FULL_HASH);
static struct v_file_ops iso_file_ops = { .close = iso9660_close,
.read = iso9660_read,
+ .read_page = iso9660_read,
.write = iso9660_write,
+ .write_page = iso9660_write,
.seek = iso9660_seek,
.readdir = iso9660_readdir };
struct device* dev = vsb->dev;
struct iso_vol* vdesc = (struct iso_vol*)valloc(ISO9660_BLKSZ);
struct iso_vol_primary* vprim = NULL;
+ u32_t lba = 16;
int errno = 0;
do {
- errno = dev->read(dev, vdesc, ISO9660_BLKSZ * 16, ISO9660_BLKSZ);
+ errno = dev->read(dev, vdesc, ISO9660_BLKSZ * lba, ISO9660_BLKSZ);
if (errno < 0) {
errno = EIO;
goto done;
vprim = (struct iso_vol_primary*)vdesc;
break;
}
-
+ lba++;
} while (vdesc->type != ISO_VOLTERM);
if (!vprim) {
}
vfs_i_addhash(rootino);
+ return 0;
done:
vfree(vdesc);
- return 0;
+ return errno;
}
int
{
struct pcache_pg* pg = btrie_get(&pcache->tree, index);
int is_new = 0;
- *offset = index & ((1 << pcache->tree.truncated) - 1);
+ u32_t mask = ((1 << pcache->tree.truncated) - 1);
+ *offset = index & mask;
if (!pg && (pg = pcache_new_page(pcache, index))) {
- pg->fpos = index - *offset;
+ pg->fpos = index & ~mask;
pcache->n_pages++;
is_new = 1;
}
}
// Filling up the page
- errno = inode->default_fops->read(inode, pg->pg, PG_SIZE, pg->fpos);
+ errno =
+ inode->default_fops->read_page(inode, pg->pg, PG_SIZE, pg->fpos);
if (errno >= 0 && errno < PG_SIZE) {
// EOF
len = MIN(len, buf_off + errno);
}
int errno =
- inode->default_fops->write(inode, page->pg, PG_SIZE, page->fpos);
+ inode->default_fops->write_page(inode, page->pg, PG_SIZE, page->fpos);
if (!errno) {
page->flags &= ~PCACHE_DIRTY;
const struct v_file_ops ramfs_file_ops = { .readdir = ramfs_readdir,
.close = default_file_close,
.read = default_file_read,
+ .read_page = default_file_read,
.write = default_file_write,
+ .write_page = default_file_write,
.seek = default_file_seek };
\ No newline at end of file
const struct v_file_ops twifs_file_ops = { .close = default_file_close,
.read = __twifs_fread,
+ .read_page = __twifs_fread,
.write = __twifs_fwrite,
+ .write_page = __twifs_fwrite,
.readdir = __twifs_iterate_dir };
const struct v_inode_ops twifs_inode_ops = { .dir_lookup = __twifs_dirlookup,
static struct v_file_ops taskfs_file_ops = { .close = default_file_close,
.read = default_file_read,
+ .read_page = default_file_read,
.write = default_file_write,
+ .write_page = default_file_write,
.readdir = taskfs_readdir,
.seek = default_file_seek };
static struct v_inode_ops taskfs_inode_ops = { .dir_lookup = taskfs_dirlookup,
lx_console.flush_timer = NULL;
}
+int
+__tty_write_pg(struct device* dev, void* buf, size_t offset)
+{
+ return __tty_write(dev, buf, offset, PG_SIZE);
+}
+
+int
+__tty_read_pg(struct device* dev, void* buf, size_t offset)
+{
+ return __tty_read(dev, buf, offset, PG_SIZE);
+}
+
void
lxconsole_spawn_ttydev()
{
struct device* tty_dev = device_addseq(NULL, &lx_console, "tty");
tty_dev->write = __tty_write;
+ tty_dev->write_page = __tty_write_pg;
tty_dev->read = __tty_read;
+ tty_dev->read_page = __tty_read_pg;
tty_dev->exec_cmd = __tty_exec_cmd;
waitq_init(&lx_reader);