You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
riscv-pke/kernel/ramdev.c

107 lines
3.1 KiB

/*
* Utility functions operating the devices. support only RAM disk device. added @lab4_1.
*/
#include "ramdev.h"
#include "vfs.h"
#include "pmm.h"
#include "riscv.h"
#include "util/types.h"
#include "util/string.h"
#include "spike_interface/spike_utils.h"
#include "rfs.h"
struct rfs_device *rfs_device_list[MAX_RAMDISK_COUNT];
//
// write the content stored in "buff" to the "blkno"^th block of disk.
//
int ramdisk_write(struct rfs_device *rfs_device, int blkno){
if ( blkno < 0 || blkno >= RAMDISK_BLOCK_COUNT )
panic("ramdisk_write: write block No %d out of range!\n", blkno);
void * dst = (void *)((uint64)rfs_device->d_address + blkno * RAMDISK_BLOCK_SIZE);
memcpy(dst, rfs_device->iobuffer, RAMDISK_BLOCK_SIZE);
return 0;
}
//
// read the "blkno"^th block from the RAM disk and store its content into buffer.
//
int ramdisk_read(struct rfs_device *rfs_device, int blkno){
if ( blkno < 0 || blkno >= RAMDISK_BLOCK_COUNT )
panic("ramdisk_read: read block No out of range!\n");
void * src = (void *)((uint64)rfs_device->d_address + blkno * RAMDISK_BLOCK_SIZE);
memcpy(rfs_device->iobuffer, src, RAMDISK_BLOCK_SIZE);
return 0;
}
//
// alloc RAMDISK_BLOCK_COUNT continuous pages (blocks) for the RAM Disk
// setup an vfs node, initialize RAM disk device, and attach the device with the vfs node.
//
struct device *init_rfs_device(const char *dev_name) {
// find rfs in registered fs list
struct file_system_type *fs_type = NULL;
for (int i = 0; i < MAX_SUPPORTED_FS; i++) {
if (fs_list[i] != NULL && fs_list[i]->type_num == RFS_TYPE) {
fs_type = fs_list[i];
break;
}
}
if (!fs_type) {
panic("No RFS file system found!\n");
}
// alloc blocks for the RAM Disk
void *curr_addr = NULL;
void *last_addr = NULL;
void *ramdisk_addr = NULL;
for ( int i = 0; i < RAMDISK_BLOCK_COUNT; ++ i ){
last_addr = curr_addr;
curr_addr = alloc_page();
if ( last_addr != NULL && last_addr - curr_addr != PGSIZE ){
panic("RAM Disk0: address is discontinuous!\n");
}
}
ramdisk_addr = curr_addr;
// find a free rfs device
struct rfs_device **rfs_device = NULL;
int device_id = 0;
for (int i = 0; i < MAX_RAMDISK_COUNT; i++) {
if (rfs_device_list[i] == NULL) {
rfs_device = &rfs_device_list[i];
device_id = i;
break;
}
}
if (!rfs_device) {
panic("RAM Disk0: no free device!\n");
}
*rfs_device = (struct rfs_device *)alloc_page();
(*rfs_device)->d_blocks = RAMDISK_BLOCK_COUNT;
(*rfs_device)->d_blocksize = RAMDISK_BLOCK_SIZE;
(*rfs_device)->d_write = ramdisk_write;
(*rfs_device)->d_read = ramdisk_read;
(*rfs_device)->d_address = ramdisk_addr;
(*rfs_device)->iobuffer = alloc_page();
// allocate a vfs device
struct device * device = (struct device *)alloc_page();
// set the device name and index
strcpy(device->dev_name, dev_name);
device->dev_id = device_id;
device->fs_type = fs_type;
// add the device to the vfs device list
for(int i = 0; i < MAX_VFS_DEV; i++) {
if (vfs_dev_list[i] == NULL) {
vfs_dev_list[i] = device;
break;
}
}
sprint("%s: base address of %s is: %p\n",dev_name, dev_name, ramdisk_addr);
return device;
}