reading from block devices is done using the block cache (bcache). This cache stores sectors from a block device in pages of memory marked as 'cached', which will allow them to be reclaimed when memory pressure is high (TODO). while block device drivers implement callbacks allowing reading/writing at block-granularity, the device subsystem uses the block cache to implement reading/writing at byte-granularity in a driver-agnostic way. block drivers can disable the block cache for their devices, but this will require that any clients communicate with the devices at block-granularity. also added an offset parameter to device and object read/write functions/callbacks.
49 lines
1.1 KiB
C
49 lines
1.1 KiB
C
#include <socks/device.h>
|
|
|
|
struct char_device *char_device_create(void)
|
|
{
|
|
struct device *dev = device_alloc();
|
|
if (!dev) {
|
|
return NULL;
|
|
}
|
|
|
|
dev->dev_type = DEV_TYPE_CHAR;
|
|
|
|
return CHAR_DEVICE(dev);
|
|
}
|
|
|
|
struct char_device *char_device_from_generic(struct device *dev)
|
|
{
|
|
dev->dev_type = DEV_TYPE_CHAR;
|
|
return CHAR_DEVICE(dev);
|
|
}
|
|
|
|
static kern_status_t char_device_read(struct device *dev, void *buf, size_t offset, size_t size, size_t *bytes_read, socks_flags_t flags)
|
|
{
|
|
kern_status_t status = KERN_UNSUPPORTED;
|
|
struct char_device *cdev = CHAR_DEVICE(dev);
|
|
|
|
if (cdev->c_ops && cdev->c_ops->read) {
|
|
status = cdev->c_ops->read(dev, buf, offset, size, bytes_read, flags);
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
static kern_status_t char_device_write(struct device *dev, const void *buf, size_t offset, size_t size, size_t *bytes_read, socks_flags_t flags)
|
|
{
|
|
kern_status_t status = KERN_UNSUPPORTED;
|
|
struct char_device *cdev = CHAR_DEVICE(dev);
|
|
|
|
if (cdev->c_ops && cdev->c_ops->write) {
|
|
status = cdev->c_ops->write(dev, buf, offset, size, bytes_read, flags);
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
struct device_type_ops char_type_ops = {
|
|
.read = char_device_read,
|
|
.write = char_device_write,
|
|
};
|