98 if (!(bbuf =
kmalloc(bs, &M_KDEV_BLK, 0)))
101 size_t start =
MIN(bs - offset % bs, size);
103 if ((r =
dev->
bread(dd, offset/bs, 1, bbuf)) < 1)
106 memcpy(cbuf, bbuf + (offset % bs), start);
118 size_t count = size/bs;
121 if ((r =
dev->
bread(dd, offset/bs, count, cbuf)) < 0)
129 if (!size || (
size_t) r < count)
133 size_t end = size % bs;
136 if (!bbuf && !(bbuf =
kmalloc(bs, &M_KDEV_BLK, 0)))
137 return ret ? ret : -ENOMEM;
139 if ((r =
dev->
bread(dd, offset/bs, 1, bbuf)) < 1)
150 return r < 0 && !ret ? r : ret;
182 if (!(bbuf =
kmalloc(bs, &M_KDEV_BLK, 0)))
186 size_t start =
MIN(bs - offset % bs, size);
188 if ((r =
dev->
bread(dd, offset/bs, 1, bbuf)) < 1)
191 memcpy(bbuf + (offset % bs), cbuf, start);
193 if ((r =
dev->
bwrite(dd, offset/bs, 1, bbuf)) < 1)
206 size_t count = size/bs;
209 if ((r =
dev->
bwrite(dd, offset/bs, count, cbuf)) < 0)
217 if (!size || (
size_t) r < count)
221 size_t end = size % bs;
224 if (!bbuf && !(bbuf =
kmalloc(bs, &M_KDEV_BLK, 0)))
225 return ret ? ret : -ENOMEM;
227 if ((r =
dev->
bread(dd, offset/bs, 1, bbuf)) < 1)
232 if ((r =
dev->
bwrite(dd, offset/bs, 1, bbuf)) < 1)
246 return ret || !size ? ret : -ENOSPC;
260 size_t size = io->
resid, done = 0;
263 while (done < size) {
267 if ((r =
iobuf_in(io, buf, len)) > 0)
270 if ((r =
kdev_bread(dd, offset + done, len, buf)) > 0)
280 if ((
size_t) r < len)
285 return done ? (
ssize_t) done : r;
304 if (S_ISCHR(dd->
type))
326 if (S_ISCHR(dd->
type))
350 return dev->
ioctl(dd, request, argp);
578 printk(
"kdev: registered chrdev %d: %s\n", major,
dev->
name);
591 for (
int i = 0; i < 256; ++i)
608 printk(
"kdev: registered blkdev %d: %s\n", major,
dev->
name);
617 printk(
"kdev: initializing\n");
int blkcache_flush(void)
Writes every dirty block of the cache to its disk.
ssize_t iobuf_out(struct iobuf *io, const void *src, size_t n)
Copies bytes from the kernel into the iobuf's buffer, and moves past them.
ssize_t iobuf_in(struct iobuf *io, void *dst, size_t n)
Copies bytes from the iobuf's buffer into the kernel, and moves past them.
int kdev_map(struct devid *dd, struct vm_space *vm_space, struct vm_entry *vm_entry)
Maps a device into an address space (mmap() of a framebuffer).
ssize_t kdev_file_close(struct devid *dd, struct file *file)
Closes an open device file, through its driver's file operations.
off_t kdev_file_lseek(struct devid *dd, struct file *file, off_t offset, int whence)
Moves an open device file's offset, through its driver's file operations.
void kdev_blkdev_register(devid_t major, struct dev *dev)
Registers a driver as the block device of a major number.
struct fops * kdev_fops(struct devid *dd)
Returns the file operations of a device.
int kdev_file_can_write(struct devid *dd, struct file *file, size_t size)
Asks a device's driver whether a write wouldn't have to wait.
int kdev_file_eof(struct devid *dd, struct file *file)
Asks a device's driver whether a read that found no data is at the end of the file.
ssize_t kdev_file_write(struct devid *dd, struct file *file, struct iobuf *io)
Writes to an open device file, through its driver's file operations.
ssize_t kdev_file_read(struct devid *dd, struct file *file, struct iobuf *io)
Reads an open device file, through its driver's file operations.
int kdev_file_ioctl(struct devid *dd, struct file *file, int request, void *argp)
Passes an ioctl() on an open device file to its driver's file operations.
ssize_t kdev_read(struct devid *dd, off_t offset, struct iobuf *io)
Reads from a device: a character device through its driver, a block device in blocks.
ssize_t kdev_bread(struct devid *dd, off_t offset, size_t size, void *buf)
Reads bytes from a block device, at any offset: the driver reads whole blocks, and the partial blocks...
void kdev_chrdev_register(devid_t major, struct dev *dev)
Registers a driver as the character device of a major number.
int kdev_close(struct devid *dev)
Closes a device: there is nothing to do.
int kdev_file_open(struct devid *dd, struct file *file)
Opens a device, through its driver's file operations.
static ssize_t kdev_blk_io(struct devid *dd, off_t offset, struct iobuf *io, int write)
Reads or writes a block device's bytes from or to an iobuf (user memory), a page at a time through a ...
int kdev_sync(void)
Writes what the block cache holds that was written, and what the block devices hold in their write ca...
static struct dev * kdev_get(struct devid *dd)
Returns the driver of a device number, picked by minor if the major's driver multiplexes several devi...
int kdev_ioctl(struct devid *dd, int request, void *argp)
Passes an ioctl() to a device's driver.
int kdev_file_can_read(struct devid *dd, struct file *file, size_t size)
Asks a device's driver whether a read wouldn't have to wait.
ssize_t kdev_write(struct devid *dd, off_t offset, struct iobuf *io)
Writes to a device: a character device through its driver, a block device in blocks.
void kdev_init()
Starts the device layer, at boot.
ssize_t kdev_bwrite(struct devid *dd, off_t offset, size_t size, void *buf)
Writes bytes to a block device, at any offset: the driver writes whole blocks, and the partial blocks...
#define MALLOC_DEFINE(type, _name, _desc)
void * kmalloc(size_t size, struct malloc_type *type, int flags)
Allocates memory for one of the kernel's structures.
void kfree(void *)
Frees an object that kmalloc() gave.
void * memcpy(void *dst, const void *src, size_t n)
Copies n bytes; dst and src must not overlap.
int posix_file_close(struct file *file)
Closes an open file by dropping its reference to its vnode.
int printk(const char *fmt,...)
Writes a kernel message, to the message buffer and the consoles.
A device driver: its operations, any of which may be NULL.
struct dev *(*) mux(struct devid *dev)
ssize_t(*) read(struct devid *dev, off_t offset, struct iobuf *io)
int(*) map(struct devid *dev, struct vm_space *vm_space, struct vm_entry *vm_entry)
ssize_t(*) write(struct devid *dev, off_t offset, struct iobuf *io)
size_t(*) getbs(struct devid *dev)
int(*) ioctl(struct devid *dev, int request, void *argp)
ssize_t(*) bread(struct devid *dev, off_t lba, size_t count, void *buf)
ssize_t(*) bwrite(struct devid *dev, off_t lba, size_t count, void *buf)
Which device: its kind (S_IFCHR or S_IFBLK) and numbers.
An open file (POSIX's "open file description", fs/file.c).
An open file's operations.
int(*) ioctl(struct file *file, int request, void *argp)
int(*) close(struct file *file)
int(*) can_read(struct file *file, size_t size)
ssize_t(*) read(struct file *file, struct iobuf *io)
off_t(*) lseek(struct file *file, off_t offset, int whence)
ssize_t(*) write(struct file *file, struct iobuf *io)
int(*) open(struct file *file)
int(*) eof(struct file *)
int(*) can_write(struct file *file, size_t size)
A mapping (map entry): a range of an address space, its permissions, and where its pages come from.
An address space: its mappings, and its page tables.