Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

drivers: implement memory device driver #37

Merged
merged 1 commit into from
Feb 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions mentos/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ set(KERNEL_SOURCES
${CMAKE_SOURCE_DIR}/mentos/src/devices/pci.c
${CMAKE_SOURCE_DIR}/mentos/src/devices/fpu.c
${CMAKE_SOURCE_DIR}/mentos/src/drivers/ata.c
${CMAKE_SOURCE_DIR}/mentos/src/drivers/mem.c
${CMAKE_SOURCE_DIR}/mentos/src/drivers/rtc.c
${CMAKE_SOURCE_DIR}/mentos/src/drivers/fdc.c
${CMAKE_SOURCE_DIR}/mentos/src/drivers/mouse.c
Expand Down
18 changes: 18 additions & 0 deletions mentos/inc/drivers/mem.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/// @file mem.h
/// @brief Drivers for memory devices
/// @copyright (c) 2024 This file is distributed under the MIT License.
/// See LICENSE.md for details.
/// @addtogroup drivers Device Drivers
/// @{
/// @addtogroup mem Memory devices
/// @brief Drivers for memory devices.
/// @{

#pragma once

/// @brief Initializes the memory devices.
/// @return 0 on success, 1 on error.
int mem_devs_initialize(void);

/// @}
/// @}
167 changes: 167 additions & 0 deletions mentos/src/drivers/mem.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
/// @file mem.c
/// @brief Memory devices.
/// @copyright (c) 2024 This file is distributed under the MIT License.
/// See LICENSE.md for details.

// Include the kernel log levels.
#include "sys/kernel_levels.h"
/// Change the header.
#define __DEBUG_HEADER__ "[MEMDEV ]"
/// Set the log level.
#define __DEBUG_LEVEL__ GLOBAL_LOGLEVEL

#include "assert.h"
#include "drivers/mem.h"
#include "io/debug.h"
#include "fs/vfs.h"
#include "string.h"
#include "sys/errno.h"
#include "system/syscall.h"

struct memdev;

struct memdev {
vfs_file_t *file;
struct memdev *next;
};

static struct memdev *devices;

static void add_device(struct memdev *device) {
struct memdev *dit = devices;
for (;dit != NULL; dit = dit->next);
if (dit == NULL) {
devices = device;
} else {
dit->next = device;
}
}

static vfs_file_t* find_device_file(const char *path) {
for(struct memdev *dev = devices; dev != NULL; dev = dev->next) {
if (strcmp(dev->file->name, path) == 0) {
return dev->file;
}
}
return NULL;
}

static int mem_stat(const char* path, stat_t *stat);

static vfs_sys_operations_t mem_sys_operations = {
.mkdir_f = NULL,
.rmdir_f = NULL,
.stat_f = mem_stat,
};

static vfs_file_t *null_open(const char *path, int flags, mode_t mode);
static int null_close(vfs_file_t * file);
static ssize_t null_write(vfs_file_t * file, const void *buffer, off_t offset, size_t size);
static ssize_t null_read(vfs_file_t * file, char *buffer, off_t offset, size_t size);
static int null_fstat(vfs_file_t * file, stat_t *stat);

static vfs_file_operations_t null_fs_operations = {
.open_f = null_open,
.unlink_f = NULL,
.close_f = null_close,
.read_f = null_read,
.write_f = null_write,
.lseek_f = NULL,
.stat_f = null_fstat,
.ioctl_f = NULL,
.getdents_f = NULL
};

static struct memdev *null_device_create(const char* name) {
// Create the device.
struct memdev *dev = kmalloc(sizeof(struct memdev));
dev->next = NULL;

// Create the file.
vfs_file_t *file = kmem_cache_alloc(vfs_file_cache, GFP_KERNEL);
if (file == NULL) {
pr_err("Failed to create null device.\n");
return NULL;
}
dev->file = file;

// Set the device name.
strncpy(file->name, name, NAME_MAX);
file->count = 0;
file->uid = 0;
file->gid = 0;
file->mask = 0x2000 | 0666;
file->atime = sys_time(NULL);
file->mtime = sys_time(NULL);
file->ctime = sys_time(NULL);
file->length = 0;
// Set the operations.
file->sys_operations = &mem_sys_operations;
file->fs_operations = &null_fs_operations;
return dev;
}

static vfs_file_t* null_open(const char *path, int flags, mode_t mode) {
vfs_file_t* file = find_device_file(path);
if (file) {
file->count++;
}
// TODO: check permissions
return file;
}

static int null_close(vfs_file_t * file) {
assert(file && "Received null file.");
file->count--;
return 0;
}

static ssize_t null_write(vfs_file_t * file, const void *buffer, off_t offset, size_t size) {
return size;
}

static ssize_t null_read(vfs_file_t * file, char *buffer, off_t offset, size_t size) {
return 0;
}

static int null_fstat(vfs_file_t * file, stat_t *stat)
{
pr_debug("null_fstat(%s, %p)\n", file->name, stat);
stat->st_dev = 0;
stat->st_ino = 0;
stat->st_mode = file->mask;
stat->st_uid = file->uid;
stat->st_gid = file->gid;
stat->st_atime = file->atime;
stat->st_mtime = file->mtime;
stat->st_ctime = file->ctime;
stat->st_size = file->length;
return 0;
}

static int mem_stat(const char *path, stat_t *stat) {
vfs_file_t* file = find_device_file(path);

if (file) {
return file->fs_operations->stat_f(file, stat);
}
return -ENOENT;
}

int mem_devs_initialize(void)
{
struct memdev *devnull = null_device_create("/dev/null");
if (!devnull) {
pr_err("Failed to create devnull");
return -ENODEV;
}

if (!vfs_mount("/dev/null", devnull->file)) {
pr_err("Failed to mount /dev/null");
return 1;
}

add_device(devnull);

return 0;
}
11 changes: 11 additions & 0 deletions mentos/src/kernel.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "drivers/keyboard/keymap.h"
#include "drivers/ps2.h"
#include "drivers/rtc.h"
#include "drivers/mem.h"
#include "fs/ext2.h"
#include "fs/procfs.h"
#include "fs/vfs.h"
Expand Down Expand Up @@ -238,6 +239,16 @@ int kmain(boot_info_t *boot_informations)
}
print_ok();

//==========================================================================
pr_notice(" Initialize memory devices...\n");
printf(" Initialize memory devices...");
if (mem_devs_initialize()) {
print_fail();
pr_emerg("Failed to initialize memory devices!\n");
return 1;
}
print_ok();

//==========================================================================
pr_notice(" Initialize 'procfs'...\n");
printf(" Initialize 'procfs'...");
Expand Down
Loading