mirror of
https://github.com/Mathewnd/Astral.git
synced 2026-11-01 06:58:22 +00:00
devfs: use iovec_iterator internally
This commit is contained in:
@@ -18,12 +18,10 @@ void arch_e9_puts(char *c) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef X86_64_ENABLE_E9
|
#ifdef X86_64_ENABLE_E9
|
||||||
static int devwrite(int minor, void *bufferp, size_t count, uintmax_t offset, int flags, size_t *wcount) {
|
static int devwrite(int minor, iovec_iterator_t *iovec_iterator, size_t count, uintmax_t offset, int flags, size_t *wcount) {
|
||||||
uint8_t *buffer = bufferp;
|
|
||||||
|
|
||||||
for (uintmax_t i = 0; i < count; ++i) {
|
for (uintmax_t i = 0; i < count; ++i) {
|
||||||
char c;
|
char c;
|
||||||
int error = USERCOPY_POSSIBLY_FROM_USER(&c, &buffer[i], 1);
|
int error = iovec_iterator_copy_to_buffer(iovec_iterator, &c, 1);
|
||||||
if (error)
|
if (error)
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
|
|||||||
+20
-2
@@ -85,7 +85,16 @@ int devfs_read(vnode_t *node, void *buffer, size_t size, uintmax_t offset, int f
|
|||||||
if (devnode->devops->read == NULL)
|
if (devnode->devops->read == NULL)
|
||||||
return ENODEV;
|
return ENODEV;
|
||||||
|
|
||||||
return devnode->devops->read(devnode->attr.rdevminor, buffer, size, offset, flags, readc);
|
// TODO remove this once the whole fs uses iovec
|
||||||
|
iovec_iterator_t iovec_iterator;
|
||||||
|
iovec_t iovec = {
|
||||||
|
.addr = buffer,
|
||||||
|
.len = size
|
||||||
|
};
|
||||||
|
|
||||||
|
iovec_iterator_init(&iovec_iterator, &iovec, 1);
|
||||||
|
|
||||||
|
return devnode->devops->read(devnode->attr.rdevminor, &iovec_iterator, size, offset, flags, readc);
|
||||||
}
|
}
|
||||||
|
|
||||||
int devfs_write(vnode_t *node, void *buffer, size_t size, uintmax_t offset, int flags, size_t *writec, cred_t *cred) {
|
int devfs_write(vnode_t *node, void *buffer, size_t size, uintmax_t offset, int flags, size_t *writec, cred_t *cred) {
|
||||||
@@ -102,7 +111,16 @@ int devfs_write(vnode_t *node, void *buffer, size_t size, uintmax_t offset, int
|
|||||||
if (devnode->devops->write == NULL)
|
if (devnode->devops->write == NULL)
|
||||||
return ENODEV;
|
return ENODEV;
|
||||||
|
|
||||||
return devnode->devops->write(devnode->attr.rdevminor, buffer, size, offset, flags, writec);
|
// TODO remove this once the whole fs uses iovec
|
||||||
|
iovec_iterator_t iovec_iterator;
|
||||||
|
iovec_t iovec = {
|
||||||
|
.addr = buffer,
|
||||||
|
.len = size
|
||||||
|
};
|
||||||
|
|
||||||
|
iovec_iterator_init(&iovec_iterator, &iovec, 1);
|
||||||
|
|
||||||
|
return devnode->devops->write(devnode->attr.rdevminor, &iovec_iterator, size, offset, flags, writec);
|
||||||
}
|
}
|
||||||
|
|
||||||
int devfs_lookup(vnode_t *node, char *name, vnode_t **result, cred_t *cred) {
|
int devfs_lookup(vnode_t *node, char *name, vnode_t **result, cred_t *cred) {
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <kernel/iovec.h>
|
||||||
|
|
||||||
#define BLOCK_TYPE_DISK 0
|
#define BLOCK_TYPE_DISK 0
|
||||||
#define BLOCK_TYPE_PART 1
|
#define BLOCK_TYPE_PART 1
|
||||||
@@ -15,8 +16,8 @@ typedef struct {
|
|||||||
uintmax_t lbaoffset;
|
uintmax_t lbaoffset;
|
||||||
size_t blockcapacity;
|
size_t blockcapacity;
|
||||||
size_t blocksize;
|
size_t blocksize;
|
||||||
int (*write)(void *private, void *buffer, uintmax_t lba, size_t count);
|
int (*write)(void *private, iovec_iterator_t *buffer, uintmax_t lba, size_t count);
|
||||||
int (*read)(void *private, void *buffer, uintmax_t lba, size_t count);
|
int (*read)(void *private, iovec_iterator_t *buffer, uintmax_t lba, size_t count);
|
||||||
} blockdesc_t;
|
} blockdesc_t;
|
||||||
|
|
||||||
void block_register(blockdesc_t *desc, char *name);
|
void block_register(blockdesc_t *desc, char *name);
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
#include <kernel/poll.h>
|
#include <kernel/poll.h>
|
||||||
#include <hashtable.h>
|
#include <hashtable.h>
|
||||||
|
#include <kernel/iovec.h>
|
||||||
|
|
||||||
#define DEV_MAJOR_NULL 1
|
#define DEV_MAJOR_NULL 1
|
||||||
#define DEV_MAJOR_FULL 2
|
#define DEV_MAJOR_FULL 2
|
||||||
@@ -23,8 +24,8 @@
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
int (*open)(int minor, vnode_t **vnode, int flags);
|
int (*open)(int minor, vnode_t **vnode, int flags);
|
||||||
int (*close)(int minor, int flags);
|
int (*close)(int minor, int flags);
|
||||||
int (*read)(int minor, void *buffer, size_t size, uintmax_t offset, int flags, size_t *readc);
|
int (*read)(int minor, iovec_iterator_t *iovec_iterator, size_t size, uintmax_t offset, int flags, size_t *readc);
|
||||||
int (*write)(int minor, void *buffer, size_t size, uintmax_t offset, int flags, size_t *writec);
|
int (*write)(int minor, iovec_iterator_t *iovec_iterator, size_t size, uintmax_t offset, int flags, size_t *writec);
|
||||||
int (*poll)(int minor, polldata_t *data, int events);
|
int (*poll)(int minor, polldata_t *data, int events);
|
||||||
int (*mmap)(int minor, void *addr, uintmax_t offset, int flags);
|
int (*mmap)(int minor, void *addr, uintmax_t offset, int flags);
|
||||||
int (*munmap)(int minor, void *addr, uintmax_t offset, int flags);
|
int (*munmap)(int minor, void *addr, uintmax_t offset, int flags);
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ static int internalpoll(polldata_t *data, int events) {
|
|||||||
return revents;
|
return revents;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int read(int minor, void *buffer, size_t size, uintmax_t offset, int flags, size_t *readc) {
|
static int read(int minor, iovec_iterator_t *iovec_iterator, size_t size, uintmax_t offset, int flags, size_t *readc) {
|
||||||
*readc = 0;
|
*readc = 0;
|
||||||
|
|
||||||
if (size < 1)
|
if (size < 1)
|
||||||
@@ -62,7 +62,7 @@ static int read(int minor, void *buffer, size_t size, uintmax_t offset, int flag
|
|||||||
|
|
||||||
// this abuses a behavior of how the ringbuffer works to not need a lock for reading
|
// this abuses a behavior of how the ringbuffer works to not need a lock for reading
|
||||||
// (as it would need interrupts to be off)
|
// (as it would need interrupts to be off)
|
||||||
*readc = ringbuffer_read(&ringbuffer, buffer, size);
|
*readc = iovec_iterator_read_from_ringbuffer(iovec_iterator, &ringbuffer, size);
|
||||||
if (*readc == RINGBUFFER_USER_COPY_FAILED)
|
if (*readc == RINGBUFFER_USER_COPY_FAILED)
|
||||||
error = EFAULT;
|
error = EFAULT;
|
||||||
|
|
||||||
@@ -73,14 +73,18 @@ static int read(int minor, void *buffer, size_t size, uintmax_t offset, int flag
|
|||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int write(int minor, void *buffer, size_t size, uintmax_t offset, int flags, size_t *writec) {
|
static int write(int minor, iovec_iterator_t *iovec_iterator, size_t size, uintmax_t offset, int flags, size_t *writec) {
|
||||||
if (size < 1) {
|
if (size < 1) {
|
||||||
*writec = 0;
|
*writec = 0;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *c = buffer;
|
char c;
|
||||||
switch (*c) {
|
int error = iovec_iterator_copy_to_buffer(iovec_iterator, &c, 1);
|
||||||
|
if (error)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
switch (c) {
|
||||||
case 'p':
|
case 'p':
|
||||||
acpi_poweroff();
|
acpi_poweroff();
|
||||||
break;
|
break;
|
||||||
@@ -89,7 +93,7 @@ static int write(int minor, void *buffer, size_t size, uintmax_t offset, int fla
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return EIO;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int poll(int minor, polldata_t *data, int events) {
|
static int poll(int minor, polldata_t *data, int events) {
|
||||||
|
|||||||
+37
-14
@@ -8,8 +8,8 @@
|
|||||||
#include <kernel/vmm.h>
|
#include <kernel/vmm.h>
|
||||||
#include <kernel/usercopy.h>
|
#include <kernel/usercopy.h>
|
||||||
|
|
||||||
#define DISK_READ(desc, buf, lba, size) (desc)->read(desc->private, buf, lba, size)
|
#define DISK_READ(desc, it, lba, size) (desc)->read(desc->private, it, lba, size)
|
||||||
#define DISK_WRITE(desc, buf, lba, size) (desc)->write(desc->private, buf, lba, size)
|
#define DISK_WRITE(desc, it, lba, size) (desc)->write(desc->private, it, lba, size)
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
char signature[8];
|
char signature[8];
|
||||||
@@ -72,10 +72,34 @@ static void bytestolba(blockdesc_t *desc, uintmax_t offset, size_t size, uintmax
|
|||||||
*lbacount = toplba - *lbaoffset;
|
*lbacount = toplba - *lbaoffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int disk_read_direct(blockdesc_t *desc, void *buffer, size_t lba_offset, size_t block_count) {
|
||||||
|
iovec_t iovec = {
|
||||||
|
.addr = buffer,
|
||||||
|
.len = block_count * desc->blocksize
|
||||||
|
};
|
||||||
|
|
||||||
|
iovec_iterator_t iovec_iterator;
|
||||||
|
iovec_iterator_init(&iovec_iterator, &iovec, 1);
|
||||||
|
|
||||||
|
return DISK_READ(desc, &iovec_iterator, lba_offset, block_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int disk_write_direct(blockdesc_t *desc, void *buffer, size_t lba_offset, size_t block_count) {
|
||||||
|
iovec_t iovec = {
|
||||||
|
.addr = buffer,
|
||||||
|
.len = block_count * desc->blocksize
|
||||||
|
};
|
||||||
|
|
||||||
|
iovec_iterator_t iovec_iterator;
|
||||||
|
iovec_iterator_init(&iovec_iterator, &iovec, 1);
|
||||||
|
|
||||||
|
return DISK_WRITE(desc, &iovec_iterator, lba_offset, block_count);
|
||||||
|
}
|
||||||
|
|
||||||
#define MAP_FLAGS (ARCH_MMU_FLAGS_READ | ARCH_MMU_FLAGS_WRITE | ARCH_MMU_FLAGS_NOEXEC)
|
#define MAP_FLAGS (ARCH_MMU_FLAGS_READ | ARCH_MMU_FLAGS_WRITE | ARCH_MMU_FLAGS_NOEXEC)
|
||||||
|
|
||||||
// this is only really called by the page cache VOP_GETPAGE and VOP_PUTPAGE functions, so we can make a few assumptions
|
// this is only really called by the page cache VOP_GETPAGE and VOP_PUTPAGE functions, so we can make a few assumptions
|
||||||
static int rwblock(int minor, void *buffer, size_t size, uintmax_t offset, int flags, bool write, size_t *done) {
|
static int rwblock(int minor, iovec_iterator_t *iovec_iterator, size_t size, uintmax_t offset, int flags, bool write, size_t *done) {
|
||||||
blockdesc_t *desc = getdesc(minor);
|
blockdesc_t *desc = getdesc(minor);
|
||||||
if (desc == NULL)
|
if (desc == NULL)
|
||||||
return ENODEV;
|
return ENODEV;
|
||||||
@@ -104,28 +128,27 @@ static int rwblock(int minor, void *buffer, size_t size, uintmax_t offset, int f
|
|||||||
|
|
||||||
int error = 0;
|
int error = 0;
|
||||||
if (write) {
|
if (write) {
|
||||||
error = DISK_WRITE(desc, buffer, lbaoffset + desc->lbaoffset, lbacount);
|
error = DISK_WRITE(desc, iovec_iterator, lbaoffset + desc->lbaoffset, lbacount);
|
||||||
if (error)
|
if (error)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
} else {
|
} else {
|
||||||
error = DISK_READ(desc, buffer, lbaoffset + desc->lbaoffset, lbacount);
|
error = DISK_READ(desc, iovec_iterator, lbaoffset + desc->lbaoffset, lbacount);
|
||||||
if (error)
|
if (error)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
*done = size;
|
*done = size;
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int read(int minor, void *buffer, size_t size, uintmax_t offset, int flags, size_t *readc) {
|
static int read(int minor, iovec_iterator_t *iovec_iterator, size_t size, uintmax_t offset, int flags, size_t *readc) {
|
||||||
return rwblock(minor, buffer, size, offset, flags, false, readc);
|
return rwblock(minor, iovec_iterator, size, offset, flags, false, readc);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int write(int minor, void *buffer, size_t size, uintmax_t offset, int flags, size_t *writec) {
|
static int write(int minor, iovec_iterator_t *iovec_iterator, size_t size, uintmax_t offset, int flags, size_t *writec) {
|
||||||
return rwblock(minor, buffer, size, offset, flags, true, writec);
|
return rwblock(minor, iovec_iterator, size, offset, flags, true, writec);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ioctl(int minor, unsigned long request, void *arg, int *result, cred_t *cred) {
|
static int ioctl(int minor, unsigned long request, void *arg, int *result, cred_t *cred) {
|
||||||
@@ -177,7 +200,7 @@ static int detectpart(blockdesc_t *desc) {
|
|||||||
// read first two sectors
|
// read first two sectors
|
||||||
void *sects = vmm_map(NULL, desc->blocksize * 2, VMM_FLAGS_ALLOCATE, MAP_FLAGS, NULL);
|
void *sects = vmm_map(NULL, desc->blocksize * 2, VMM_FLAGS_ALLOCATE, MAP_FLAGS, NULL);
|
||||||
__assert(sects);
|
__assert(sects);
|
||||||
__assert(DISK_READ(desc, sects, 0, 2) == 0);
|
__assert(disk_read_direct(desc, sects, 0, 2) == 0);
|
||||||
|
|
||||||
void *lba0 = sects;
|
void *lba0 = sects;
|
||||||
void *lba1 = (void *)((uintptr_t)lba0 + desc->blocksize);
|
void *lba1 = (void *)((uintptr_t)lba0 + desc->blocksize);
|
||||||
@@ -199,7 +222,7 @@ static void dogpt(blockdesc_t *desc, char *name) {
|
|||||||
// get header
|
// get header
|
||||||
void *lba1 = vmm_map(NULL, desc->blocksize, VMM_FLAGS_ALLOCATE, MAP_FLAGS, NULL);
|
void *lba1 = vmm_map(NULL, desc->blocksize, VMM_FLAGS_ALLOCATE, MAP_FLAGS, NULL);
|
||||||
__assert(lba1);
|
__assert(lba1);
|
||||||
__assert(DISK_READ(desc, lba1, 1, 1) == 0);
|
__assert(disk_read_direct(desc, lba1, 1, 1) == 0);
|
||||||
gptheader_t *header = lba1;
|
gptheader_t *header = lba1;
|
||||||
|
|
||||||
// get partition table
|
// get partition table
|
||||||
@@ -207,7 +230,7 @@ static void dogpt(blockdesc_t *desc, char *name) {
|
|||||||
size_t tablelbasize = ROUND_UP(tablebytesize, desc->blocksize) / desc->blocksize;
|
size_t tablelbasize = ROUND_UP(tablebytesize, desc->blocksize) / desc->blocksize;
|
||||||
void *tablebuffer = vmm_map(NULL, tablelbasize * desc->blocksize, VMM_FLAGS_ALLOCATE, MAP_FLAGS, NULL);
|
void *tablebuffer = vmm_map(NULL, tablelbasize * desc->blocksize, VMM_FLAGS_ALLOCATE, MAP_FLAGS, NULL);
|
||||||
__assert(tablebuffer);
|
__assert(tablebuffer);
|
||||||
__assert(DISK_READ(desc, tablebuffer, header->entryarraylbastart, tablelbasize) == 0);
|
__assert(disk_read_direct(desc, tablebuffer, header->entryarraylbastart, tablelbasize) == 0);
|
||||||
|
|
||||||
// name + 'p' + 3 digits (max gpt partition count is 128) + '\0'
|
// name + 'p' + 3 digits (max gpt partition count is 128) + '\0'
|
||||||
size_t namebuflen = strlen(name) + 5;
|
size_t namebuflen = strlen(name) + 5;
|
||||||
@@ -241,7 +264,7 @@ static void dombr(blockdesc_t *desc, char *name) {
|
|||||||
// get entries
|
// get entries
|
||||||
void *lba0 = vmm_map(NULL, desc->blocksize, VMM_FLAGS_ALLOCATE, MAP_FLAGS, NULL);
|
void *lba0 = vmm_map(NULL, desc->blocksize, VMM_FLAGS_ALLOCATE, MAP_FLAGS, NULL);
|
||||||
__assert(lba0);
|
__assert(lba0);
|
||||||
__assert(DISK_READ(desc, lba0, 0, 1) == 0);
|
__assert(disk_read_direct(desc, lba0, 0, 1) == 0);
|
||||||
mbrentry_t *mbrents = (mbrentry_t *)((uintptr_t)lba0 + MBR_ENTRIES_OFFSET);
|
mbrentry_t *mbrents = (mbrentry_t *)((uintptr_t)lba0 + MBR_ENTRIES_OFFSET);
|
||||||
|
|
||||||
// name + 'p' + single digit (max mbr partition count is 4) + '\0'
|
// name + 'p' + single digit (max mbr partition count is 4) + '\0'
|
||||||
|
|||||||
+23
-10
@@ -503,22 +503,35 @@ static int iowrite(nvmenamespace_t *namespace, uint64_t prp[2], uint64_t lba, ui
|
|||||||
|
|
||||||
#define PAGES_FLAGS (ARCH_MMU_FLAGS_READ | ARCH_MMU_FLAGS_WRITE | ARCH_MMU_FLAGS_NOEXEC)
|
#define PAGES_FLAGS (ARCH_MMU_FLAGS_READ | ARCH_MMU_FLAGS_WRITE | ARCH_MMU_FLAGS_NOEXEC)
|
||||||
|
|
||||||
static int rwblocks(nvmenamespace_t *namespace, void *buffer, uintmax_t lba, size_t count, bool write) {
|
static int rwblocks(nvmenamespace_t *namespace, iovec_iterator_t *iovec_iterator, uintmax_t lba, size_t count, bool write) {
|
||||||
__assert(namespace->blocksize <= PAGE_SIZE);
|
__assert(namespace->blocksize <= PAGE_SIZE);
|
||||||
|
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
uint64_t prp[2] = {0, 0};
|
uint64_t prp[2] = {0, 0};
|
||||||
__assert(((uintptr_t)buffer % namespace->blocksize) == 0);
|
|
||||||
uintmax_t pageoffset = (uintptr_t)buffer - ROUND_DOWN((uintptr_t)buffer, PAGE_SIZE);
|
|
||||||
|
|
||||||
int done = 0;
|
int done = 0;
|
||||||
while (done < count) {
|
while (done < count) {
|
||||||
size_t docount = (done == 0) ? (PAGE_SIZE - pageoffset) / namespace->blocksize : PAGE_SIZE / namespace->blocksize;
|
void *page;
|
||||||
|
size_t page_offset, page_remaining;
|
||||||
|
// XXX this takes an entire page from the iovec, though it may not be used fully.
|
||||||
|
// ATM this does not really matter but it could at one point in the future
|
||||||
|
err = iovec_iterator_next_page(iovec_iterator, &page_offset, &page_remaining, &page);
|
||||||
|
|
||||||
|
if (err)
|
||||||
|
break;
|
||||||
|
|
||||||
|
// check that there is enough space to complete the write of this page
|
||||||
|
__assert(page);
|
||||||
|
__assert(page_remaining >= min((count - done) * namespace->blocksize, PAGE_SIZE));
|
||||||
|
|
||||||
|
// and that the space is aligned to the block size
|
||||||
|
__assert((page_remaining % namespace->blocksize) == 0);
|
||||||
|
|
||||||
|
size_t docount = page_remaining / namespace->blocksize;
|
||||||
docount = min(docount, count - done);
|
docount = min(docount, count - done);
|
||||||
|
|
||||||
prp[0] = (uint64_t)vmm_getphysical((void *)((uintptr_t)buffer + done * namespace->blocksize), true);
|
prp[0] = (uint64_t)page + page_offset;
|
||||||
__assert(prp[0]);
|
|
||||||
|
|
||||||
err = write ? iowrite(namespace, prp, lba + done, docount) : ioread(namespace, prp, lba + done, docount);
|
err = write ? iowrite(namespace, prp, lba + done, docount) : ioread(namespace, prp, lba + done, docount);
|
||||||
|
|
||||||
@@ -533,12 +546,12 @@ static int rwblocks(nvmenamespace_t *namespace, void *buffer, uintmax_t lba, siz
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int read(void *private, void *buffer, uintmax_t lba, size_t count) {
|
static int read(void *private, iovec_iterator_t *iovec_iterator, uintmax_t lba, size_t count) {
|
||||||
return rwblocks(private, buffer, lba, count, false);
|
return rwblocks(private, iovec_iterator, lba, count, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int write(void *private, void *buffer, uintmax_t lba, size_t count) {
|
static int write(void *private, iovec_iterator_t *iovec_iterator, uintmax_t lba, size_t count) {
|
||||||
return rwblocks(private, buffer, lba, count, true);
|
return rwblocks(private, iovec_iterator, lba, count, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void initnamespace(nvmecontroller_t *controller, int id) {
|
static void initnamespace(nvmecontroller_t *controller, int id) {
|
||||||
|
|||||||
@@ -99,7 +99,7 @@ static void vioblk_enqueue(vioblkdev_t *blkdev, requestheader_t *headerphys, voi
|
|||||||
interrupt_set(intstatus);
|
interrupt_set(intstatus);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int vioblk_rw(vioblkdev_t *blkdev, void *buffer, uintmax_t lba, size_t count, bool write) {
|
static int vioblk_rw(vioblkdev_t *blkdev, iovec_iterator_t *iovec_iterator, uintmax_t lba, size_t count, bool write) {
|
||||||
void *physpage = pmm_allocpage(PMM_SECTION_DEFAULT);
|
void *physpage = pmm_allocpage(PMM_SECTION_DEFAULT);
|
||||||
if (physpage == NULL)
|
if (physpage == NULL)
|
||||||
return ENOMEM;
|
return ENOMEM;
|
||||||
@@ -112,21 +112,28 @@ static int vioblk_rw(vioblkdev_t *blkdev, void *buffer, uintmax_t lba, size_t co
|
|||||||
|
|
||||||
headerhhdm->type = write ? HEADER_TYPE_WRITE : HEADER_TYPE_READ;
|
headerhhdm->type = write ? HEADER_TYPE_WRITE : HEADER_TYPE_READ;
|
||||||
|
|
||||||
__assert(((uintptr_t)buffer % 512) == 0);
|
|
||||||
uintmax_t pageoffset = (uintptr_t)buffer - ROUND_DOWN((uintptr_t)buffer, PAGE_SIZE);
|
|
||||||
|
|
||||||
int done = 0;
|
int done = 0;
|
||||||
while (done < count) {
|
while (done < count) {
|
||||||
|
void *page;
|
||||||
|
size_t page_offset, page_remaining;
|
||||||
|
err = iovec_iterator_next_page(iovec_iterator, &page_offset, &page_remaining, &page);
|
||||||
|
if (err)
|
||||||
|
break;
|
||||||
|
|
||||||
|
// check that there is enough space to complete the write of this page
|
||||||
|
__assert(page);
|
||||||
|
__assert(page_remaining >= min((count - done) * 512, PAGE_SIZE));
|
||||||
|
|
||||||
|
// and that the space is aligned to the block size
|
||||||
|
__assert((page_remaining % 512) == 0);
|
||||||
|
|
||||||
headerhhdm->sector = lba + done;
|
headerhhdm->sector = lba + done;
|
||||||
size_t docount = (done == 0) ? (PAGE_SIZE - pageoffset) / 512 : PAGE_SIZE / 512;
|
size_t docount = page_remaining / 512;
|
||||||
docount = min(docount, count - done);
|
docount = min(docount, count - done);
|
||||||
|
|
||||||
void *bufferphys = vmm_getphysical((void *)((uintptr_t)buffer + done * 512), true);
|
vioblk_enqueue(blkdev, header, (void *)((uintptr_t)page + page_offset), PAGE_SIZE, status, write);
|
||||||
__assert(bufferphys);
|
|
||||||
|
|
||||||
vioblk_enqueue(blkdev, header, bufferphys, docount * 512, status, write);
|
pmm_release(page);
|
||||||
|
|
||||||
pmm_release(bufferphys);
|
|
||||||
|
|
||||||
if (*statushhdm) {
|
if (*statushhdm) {
|
||||||
err = EIO;
|
err = EIO;
|
||||||
@@ -140,12 +147,12 @@ static int vioblk_rw(vioblkdev_t *blkdev, void *buffer, uintmax_t lba, size_t co
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int vioblk_write(void *private, void *buffer, uintmax_t lba, size_t count) {
|
static int vioblk_write(void *private, iovec_iterator_t *iovec_iterator, uintmax_t lba, size_t count) {
|
||||||
return vioblk_rw(private, buffer, lba, count, true);
|
return vioblk_rw(private, iovec_iterator, lba, count, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int vioblk_read(void *private, void *buffer, uintmax_t lba, size_t count) {
|
static int vioblk_read(void *private, iovec_iterator_t *iovec_iterator, uintmax_t lba, size_t count) {
|
||||||
return vioblk_rw(private, buffer, lba, count, false);
|
return vioblk_rw(private, iovec_iterator, lba, count, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
int vioblk_newdevice(viodevice_t *viodevice) {
|
int vioblk_newdevice(viodevice_t *viodevice) {
|
||||||
|
|||||||
+4
-4
@@ -86,7 +86,7 @@ static int maxseek(int minor, size_t *max) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int read(int minor, void *buffer, size_t size, uintmax_t offset, int flags, size_t *readc) {
|
static int read(int minor, iovec_iterator_t *iovec_iterator, size_t size, uintmax_t offset, int flags, size_t *readc) {
|
||||||
if (minor >= count)
|
if (minor >= count)
|
||||||
return ENODEV;
|
return ENODEV;
|
||||||
|
|
||||||
@@ -99,7 +99,7 @@ static int read(int minor, void *buffer, size_t size, uintmax_t offset, int flag
|
|||||||
if(size + offset > end)
|
if(size + offset > end)
|
||||||
size = end - offset;
|
size = end - offset;
|
||||||
|
|
||||||
int error = USERCOPY_POSSIBLY_TO_USER(buffer, (void *)((uintptr_t)fbs[minor]->address + offset), size);
|
int error = iovec_iterator_copy_from_buffer(iovec_iterator, (void *)((uintptr_t)fbs[minor]->address + offset), size);
|
||||||
if (error)
|
if (error)
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
@@ -108,7 +108,7 @@ static int read(int minor, void *buffer, size_t size, uintmax_t offset, int flag
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int write(int minor, void *buffer, size_t size, uintmax_t offset, int flags, size_t *writec) {
|
static int write(int minor, iovec_iterator_t *iovec_iterator, size_t size, uintmax_t offset, int flags, size_t *writec) {
|
||||||
if (minor >= count)
|
if (minor >= count)
|
||||||
return ENODEV;
|
return ENODEV;
|
||||||
|
|
||||||
@@ -121,7 +121,7 @@ static int write(int minor, void *buffer, size_t size, uintmax_t offset, int fla
|
|||||||
if(size + offset > end)
|
if(size + offset > end)
|
||||||
size = end - offset;
|
size = end - offset;
|
||||||
|
|
||||||
int error = USERCOPY_POSSIBLY_FROM_USER((void *)((uintptr_t)fbs[minor]->address + offset), buffer, size);
|
int error = iovec_iterator_copy_to_buffer(iovec_iterator, (void *)((uintptr_t)fbs[minor]->address + offset), size);
|
||||||
if (error)
|
if (error)
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
|
|||||||
@@ -154,7 +154,7 @@ static keyboard_t* getkb(int kb) {
|
|||||||
return kbp;
|
return kbp;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int read(int minor, void *buffer, size_t size, uintmax_t offset, int flags, size_t *readc) {
|
static int read(int minor, iovec_iterator_t *iovec_iterator, size_t size, uintmax_t offset, int flags, size_t *readc) {
|
||||||
keyboard_t *kb = getkb(minor);
|
keyboard_t *kb = getkb(minor);
|
||||||
if (kb == NULL)
|
if (kb == NULL)
|
||||||
return ENODEV;
|
return ENODEV;
|
||||||
@@ -165,7 +165,6 @@ static int read(int minor, void *buffer, size_t size, uintmax_t offset, int flag
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
for (int i = 0; i < count; ++i) {
|
for (int i = 0; i < count; ++i) {
|
||||||
kbpacket_t *buff = (kbpacket_t *)((uintptr_t)buffer + i * sizeof(kbpacket_t));
|
|
||||||
kbpacket_t packet;
|
kbpacket_t packet;
|
||||||
|
|
||||||
bool ok = keyboard_get(kb, &packet);
|
bool ok = keyboard_get(kb, &packet);
|
||||||
@@ -175,7 +174,7 @@ static int read(int minor, void *buffer, size_t size, uintmax_t offset, int flag
|
|||||||
if (error)
|
if (error)
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
error = USERCOPY_POSSIBLY_TO_USER(buff, &packet, sizeof(kbpacket_t));
|
error = iovec_iterator_copy_from_buffer(iovec_iterator, &packet, sizeof(kbpacket_t));
|
||||||
|
|
||||||
*readc += error ? 0 : sizeof(kbpacket_t);
|
*readc += error ? 0 : sizeof(kbpacket_t);
|
||||||
return error;
|
return error;
|
||||||
@@ -184,7 +183,7 @@ static int read(int minor, void *buffer, size_t size, uintmax_t offset, int flag
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
int error = USERCOPY_POSSIBLY_TO_USER(buff, &packet, sizeof(kbpacket_t));
|
int error = iovec_iterator_copy_from_buffer(iovec_iterator, &packet, sizeof(kbpacket_t));
|
||||||
if (error)
|
if (error)
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ static int internalpoll(mouse_t *mouse, polldata_t *data, int events) {
|
|||||||
return revents;
|
return revents;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int read(int minor, void *buffer, size_t size, uintmax_t offset, int flags, size_t *readc) {
|
static int read(int minor, iovec_iterator_t *iovec_iterator, size_t size, uintmax_t offset, int flags, size_t *readc) {
|
||||||
mouse_t *mouse = getmouse(minor);
|
mouse_t *mouse = getmouse(minor);
|
||||||
if (mouse == NULL)
|
if (mouse == NULL)
|
||||||
return ENODEV;
|
return ENODEV;
|
||||||
@@ -121,7 +121,7 @@ static int read(int minor, void *buffer, size_t size, uintmax_t offset, int flag
|
|||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
*readc = ringbuffer_read(&mouse->packetbuffer, buffer, sizeof(mousepacket_t) * packetcount);
|
*readc = iovec_iterator_read_from_ringbuffer(iovec_iterator, &mouse->packetbuffer, sizeof(mousepacket_t) * packetcount);
|
||||||
if (*readc == RINGBUFFER_USER_COPY_FAILED) {
|
if (*readc == RINGBUFFER_USER_COPY_FAILED) {
|
||||||
error = EFAULT;
|
error = EFAULT;
|
||||||
goto leave;
|
goto leave;
|
||||||
|
|||||||
@@ -4,22 +4,21 @@
|
|||||||
#include <logging.h>
|
#include <logging.h>
|
||||||
#include <kernel/timekeeper.h>
|
#include <kernel/timekeeper.h>
|
||||||
|
|
||||||
static int null_write(int minor, void *buffer, size_t count, uintmax_t offset, int flags, size_t *wcount) {
|
static int null_write(int minor, iovec_iterator_t *iovec_iterator, size_t count, uintmax_t offset, int flags, size_t *wcount) {
|
||||||
*wcount = count;
|
*wcount = count;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int full_write(int minor, void *buffer, size_t count, uintmax_t offset, int flags, size_t *wcount) {
|
static int full_write(int minor, iovec_iterator_t *iovec_iterator, size_t count, uintmax_t offset, int flags, size_t *wcount) {
|
||||||
return ENOSPC;
|
return ENOSPC;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int zero_read(int minor, void *buffer, size_t count, uintmax_t offset, int flags, size_t *rcount) {
|
static int zero_read(int minor, iovec_iterator_t *iovec_iterator, size_t count, uintmax_t offset, int flags, size_t *rcount) {
|
||||||
*rcount = count;
|
*rcount = count;
|
||||||
memset(buffer, 0, count);
|
return iovec_iterator_memset(iovec_iterator, 0, count);
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int null_read(int minor, void *buffer, size_t count, uintmax_t offset, int flags, size_t *rcount) {
|
static int null_read(int minor, iovec_iterator_t *iovec_iterator, size_t count, uintmax_t offset, int flags, size_t *rcount) {
|
||||||
*rcount = 0;
|
*rcount = 0;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -36,10 +35,13 @@ static uint8_t getrand8() {
|
|||||||
return current & 0xff;
|
return current & 0xff;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int urandom_read(int minor, void *_buffer, size_t count, uintmax_t offset, int flags, size_t *rcount) {
|
static int urandom_read(int minor, iovec_iterator_t *iovec_iterator, size_t count, uintmax_t offset, int flags, size_t *rcount) {
|
||||||
uint8_t *buffer = _buffer;
|
for (int i = 0; i < count; ++i) {
|
||||||
for (int i = 0; i < count; ++i)
|
uint8_t byte = getrand8();
|
||||||
buffer[i] = getrand8();
|
int error = iovec_iterator_copy_from_buffer(iovec_iterator, &byte, sizeof(byte));
|
||||||
|
if (error)
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
*rcount = count;
|
*rcount = count;
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
+4
-16
@@ -127,7 +127,7 @@ static int internalpoll(pty_t *pty, polldata_t *data, int events) {
|
|||||||
return revents;
|
return revents;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int read(int minor, void *buffer, size_t size, uintmax_t offset, int flags, size_t *readc) {
|
static int read(int minor, iovec_iterator_t *iovec_iterator, size_t size, uintmax_t offset, int flags, size_t *readc) {
|
||||||
pty_t *pty = ptyget(minor);
|
pty_t *pty = ptyget(minor);
|
||||||
if (pty == NULL)
|
if (pty == NULL)
|
||||||
return ENODEV;
|
return ENODEV;
|
||||||
@@ -139,27 +139,18 @@ static int read(int minor, void *buffer, size_t size, uintmax_t offset, int flag
|
|||||||
if (e)
|
if (e)
|
||||||
return e;
|
return e;
|
||||||
|
|
||||||
bool intstatus = interrupt_set(false);
|
|
||||||
spinlock_acquire(&pty->lock);
|
|
||||||
|
|
||||||
int revents = internalpoll(pty, &desc.data[0], POLLIN);
|
int revents = internalpoll(pty, &desc.data[0], POLLIN);
|
||||||
|
|
||||||
if (revents) {
|
if (revents) {
|
||||||
*readc = ringbuffer_read(&pty->ringbuffer, buffer, size);
|
*readc = iovec_iterator_read_from_ringbuffer(iovec_iterator, &pty->ringbuffer, size);
|
||||||
if (*readc == RINGBUFFER_USER_COPY_FAILED)
|
if (*readc == RINGBUFFER_USER_COPY_FAILED)
|
||||||
e = EFAULT;
|
e = EFAULT;
|
||||||
|
|
||||||
spinlock_release(&pty->lock);
|
|
||||||
interrupt_set(intstatus);
|
|
||||||
|
|
||||||
poll_leave(&desc);
|
poll_leave(&desc);
|
||||||
poll_destroydesc(&desc);
|
poll_destroydesc(&desc);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
spinlock_release(&pty->lock);
|
|
||||||
interrupt_set(intstatus);
|
|
||||||
|
|
||||||
if (flags & V_FFLAGS_NONBLOCKING) {
|
if (flags & V_FFLAGS_NONBLOCKING) {
|
||||||
poll_leave(&desc);
|
poll_leave(&desc);
|
||||||
poll_destroydesc(&desc);
|
poll_destroydesc(&desc);
|
||||||
@@ -210,17 +201,14 @@ static int ioctl(int minor, unsigned long request, void *_arg, int *result, cred
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int write(int minor, void *buffer, size_t size, uintmax_t offset, int flags, size_t *writec) {
|
static int write(int minor, iovec_iterator_t *iovec_iterator, size_t size, uintmax_t offset, int flags, size_t *writec) {
|
||||||
pty_t *pty = ptyget(minor);
|
pty_t *pty = ptyget(minor);
|
||||||
if (pty == NULL)
|
if (pty == NULL)
|
||||||
return ENODEV;
|
return ENODEV;
|
||||||
|
|
||||||
char *str = buffer;
|
|
||||||
|
|
||||||
for (int i = 0; i < size; ++i) {
|
for (int i = 0; i < size; ++i) {
|
||||||
// bruh
|
|
||||||
char c;
|
char c;
|
||||||
int error = USERCOPY_POSSIBLY_FROM_USER(&c, &str[i], sizeof(char));
|
int error = iovec_iterator_copy_to_buffer(iovec_iterator, &c, sizeof(char));
|
||||||
if (error)
|
if (error)
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
|
|||||||
+5
-7
@@ -170,7 +170,7 @@ static int internalpoll(tty_t *tty, polldata_t *data, int events) {
|
|||||||
return revents;
|
return revents;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int read(int minor, void *buffer, size_t size, uintmax_t offset, int flags, size_t *readc) {
|
static int read(int minor, iovec_iterator_t *iovec_iterator, size_t size, uintmax_t offset, int flags, size_t *readc) {
|
||||||
tty_t *tty = ttyget(minor);
|
tty_t *tty = ttyget(minor);
|
||||||
if (tty == NULL)
|
if (tty == NULL)
|
||||||
return ENODEV;
|
return ENODEV;
|
||||||
@@ -194,7 +194,7 @@ static int read(int minor, void *buffer, size_t size, uintmax_t offset, int flag
|
|||||||
// read data and if theres nothing just return
|
// read data and if theres nothing just return
|
||||||
if (min == 0 && time == 0) {
|
if (min == 0 && time == 0) {
|
||||||
MUTEX_ACQUIRE(&tty->readmutex, false);
|
MUTEX_ACQUIRE(&tty->readmutex, false);
|
||||||
*readc = ringbuffer_read(&tty->readbuffer, buffer, size);
|
*readc = iovec_iterator_read_from_ringbuffer(iovec_iterator, &tty->readbuffer, size);
|
||||||
|
|
||||||
int error = 0;
|
int error = 0;
|
||||||
if (*readc == RINGBUFFER_USER_COPY_FAILED)
|
if (*readc == RINGBUFFER_USER_COPY_FAILED)
|
||||||
@@ -227,7 +227,7 @@ static int read(int minor, void *buffer, size_t size, uintmax_t offset, int flag
|
|||||||
// theres data to read
|
// theres data to read
|
||||||
MUTEX_ACQUIRE(&tty->readmutex, false);
|
MUTEX_ACQUIRE(&tty->readmutex, false);
|
||||||
|
|
||||||
size_t actuallyread = ringbuffer_read(&tty->readbuffer, (void *)((uintptr_t)buffer + readcount), spaceleft);
|
size_t actuallyread = iovec_iterator_read_from_ringbuffer(iovec_iterator, &tty->readbuffer, spaceleft);
|
||||||
|
|
||||||
MUTEX_RELEASE(&tty->readmutex);
|
MUTEX_RELEASE(&tty->readmutex);
|
||||||
|
|
||||||
@@ -274,20 +274,18 @@ static int read(int minor, void *buffer, size_t size, uintmax_t offset, int flag
|
|||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int write(int minor, void *_buffer, size_t size, uintmax_t offset, int flags, size_t *writec) {
|
static int write(int minor, iovec_iterator_t *iovec_iterator, size_t size, uintmax_t offset, int flags, size_t *writec) {
|
||||||
tty_t *tty = ttyget(minor);
|
tty_t *tty = ttyget(minor);
|
||||||
if (tty == NULL)
|
if (tty == NULL)
|
||||||
return ENODEV;
|
return ENODEV;
|
||||||
|
|
||||||
// TODO background process stuff etc
|
// TODO background process stuff etc
|
||||||
|
|
||||||
char *buffer = _buffer;
|
|
||||||
|
|
||||||
*writec = size;
|
*writec = size;
|
||||||
for (int i = 0; i < size; ++i) {
|
for (int i = 0; i < size; ++i) {
|
||||||
// bruh
|
// bruh
|
||||||
char c;
|
char c;
|
||||||
int error = USERCOPY_POSSIBLY_FROM_USER(&c, &buffer[i], sizeof(char));
|
int error = iovec_iterator_copy_to_buffer(iovec_iterator, &c, sizeof(char));
|
||||||
if (error)
|
if (error)
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user