feature (drive manager): implemented a manager for drives/storage media

This commit is contained in:
antifallobst 2023-05-15 18:13:58 +02:00
parent 7e5fee1437
commit 0bed26ff26
5 changed files with 236 additions and 4 deletions

View File

@ -5,6 +5,7 @@
#include "utils/stdtypes.h"
#include "drivers/pci.h"
#include "drivers/drive_manager.h"
#define SATA_SIG_ATA 0x00000101
#define SATA_SIG_ATAPI 0xEB140101
@ -209,23 +210,26 @@ typedef struct{
} ahci_hba_command_table_T;
typedef struct ahci_controller_T ahci_controller_T;
typedef struct {
ahci_hba_port_T* hba_port;
ahci_device_type_E type;
uint8_t* buffer;
ahci_controller_T* controller;
uint8_t id;
drive_T* drive;
void* cmd_list_base;
void* fis_base;
void* command_tables [32];
} ahci_port_T;
typedef struct {
struct ahci_controller_T {
ahci_port_T ports [32];
int num_ports;
pci_device_T* pci_device;
ahci_hba_memory_T* abar;
} ahci_controller_T;
};
ahci_controller_T* ahci_controller_alloc (pci_device_T* pci_device);
void ahci_controller_destruct (ahci_controller_T* controller);

View File

@ -0,0 +1,71 @@
// This file is part of noxos and licensed under the MIT open source license
#ifndef NOXOS_DRIVE_MANAGER_H
#define NOXOS_DRIVE_MANAGER_H
#include "drivers/fs/vfs.h"
#include "utils/stdtypes.h"
#include "utils/bitmap.h"
#define DRIVE_CHUNK_SIZE 16
#define DRIVE_PARTITION_CHUNK_SIZE 16
typedef enum {
DRIVE_CONTROLLER_AHCI
} drive_controller_types_E;
typedef struct drive_chunk_T drive_chunk_T;
typedef struct drive_partition_chunk_T drive_partition_chunk_T;
typedef struct drive_partition_T drive_partition_T;
typedef struct drive_T drive_T;
struct drive_partition_T{
drive_partition_chunk_T* chunk;
uint32_t id_in_chunk;
uint32_t id;
drive_T* drive;
fs_T filesystem;
uint32_t start_sector;
uint32_t end_sector;
};
struct drive_T {
drive_chunk_T* chunk;
uint32_t id_in_chunk;
uint32_t id;
drive_partition_chunk_T* partitions_chunks;
drive_controller_types_E controller_type;
void* controller;
};
struct drive_chunk_T {
drive_T drives [DRIVE_CHUNK_SIZE];
bitmap_T drives_bitmap;
uint32_t num_drives;
drive_chunk_T* prev;
drive_chunk_T* next;
};
struct drive_partition_chunk_T {
drive_partition_T partitions [DRIVE_PARTITION_CHUNK_SIZE];
bitmap_T partitions_bitmap;
uint32_t num_partitions;
drive_partition_chunk_T* prev;
drive_partition_chunk_T* next;
};
typedef struct {
drive_chunk_T* chunks;
} drive_manager_T;
drive_chunk_T* drive_chunk_alloc (drive_chunk_T* prev);
drive_partition_chunk_T* drive_partition_chunk_alloc (drive_partition_chunk_T* prev);
void drive_partition_chunk_destruct (drive_partition_chunk_T* chunk);
void drive_manager_init ();
drive_T* drive_manager_add_drive (drive_controller_types_E controller_type, void* controller, void* device);
void drive_manager_remove_drive (drive_T* drive);
drive_partition_T* drive_manager_add_partition (drive_T* drive, uint32_t start_sector, uint32_t end_sector);
void drive_manager_remove_partition (drive_partition_T* partition);
#endif //NOXOS_DRIVE_MANAGER_H

View File

@ -15,6 +15,7 @@
#include "drivers/graphics/renderer.h"
#include "drivers/fs/vfs.h"
#include "drivers/acpi/acpi.h"
#include "drivers/drive_manager.h"
#include "drivers/pci.h"
#include "drivers/ps2/controller.h"
#include "drivers/tty.h"
@ -49,6 +50,8 @@ void kernel_init(boot_info_T* boot_info) {
acpi_init(boot_info);
drive_manager_init();
pci_init();
tty_init();

View File

@ -40,6 +40,7 @@ ahci_controller_T* ahci_controller_alloc(pci_device_T* pci_device) {
port->type = type;
port->hba_port = &controller->abar->ports[i];
port->id = controller->num_ports;
port->controller = controller;
controller->num_ports += 1;
break;
@ -94,6 +95,8 @@ void ahci_port_init(ahci_port_T* port) {
ahci_port_command_start(port);
port->drive = drive_manager_add_drive(DRIVE_CONTROLLER_AHCI, port->controller, port);
ahci_port_init_partitions_mbr(port);
}
@ -109,12 +112,15 @@ void ahci_port_init_partitions_mbr(ahci_port_T* port) {
mbr_partition_types_E type = mbr->partitions[i].partition_type;
if (type == MBR_PARTITION_TYPE_UNUSED) continue;
log(LOG_INFO, " p%d: 0x%xb - %d - %s", i, type, mbr->partitions[i].start_lba, mbr_partition_type_to_string(type));
mbr_partition_header_T* partition = &mbr->partitions[i];
log(LOG_INFO, " p%d: 0x%xb - (LBA: %d) - %s", i, type, partition->start_lba, mbr_partition_type_to_string(type));
if (type == MBR_PARTITION_TYPE_GPT) {
ahci_port_init_partitions_gpt(port);
break;
}
drive_manager_add_partition(port->drive, partition->start_lba, partition->start_lba + partition->num_sectors);
}
}
@ -156,6 +162,8 @@ void ahci_port_init_partitions_gpt(ahci_port_T* port) {
} else {
log(LOG_INFO, " p%d: (%d)<--LBA-->(%d) %s", i, entry->starting_lba, entry->ending_lba, gpt_partition_type_to_string(type));
}
drive_manager_add_partition(port->drive, entry->starting_lba, entry->ending_lba);
}
}
@ -167,6 +175,8 @@ void ahci_port_init_partitions_gpt(ahci_port_T* port) {
void ahci_port_destruct(ahci_port_T* port) {
drive_manager_remove_drive(port->drive);
for (uint32_t i = 0; i < 32; i++) {
pframe_free(port->command_tables[i]);
}

144
src/drivers/drive_manager.c Normal file
View File

@ -0,0 +1,144 @@
// This file is part of noxos and licensed under the MIT open source license
#include "drivers/drive_manager.h"
#include "utils/memory.h"
#include "utils/logger.h"
drive_manager_T g_drive_manager;
drive_chunk_T* drive_chunk_alloc(drive_chunk_T* prev) {
drive_chunk_T* chunk = memory_allocate(sizeof(drive_chunk_T));
chunk->drives_bitmap = bitmap_init(DRIVE_CHUNK_SIZE);
chunk->num_drives = 0;
chunk->next = NULL;
chunk->prev = prev;
if (prev != NULL) {
prev->next = chunk;
}
return chunk;
}
drive_partition_chunk_T* drive_partition_chunk_alloc(drive_partition_chunk_T* prev) {
drive_partition_chunk_T* chunk = memory_allocate(sizeof(drive_partition_chunk_T));
chunk->partitions_bitmap = bitmap_init(DRIVE_PARTITION_CHUNK_SIZE);
chunk->num_partitions = 0;
chunk->next = NULL;
chunk->prev = prev;
if (prev != NULL) {
prev->next = chunk;
}
return chunk;
}
void drive_partition_chunk_destruct(drive_partition_chunk_T* chunk) {
bitmap_destruct(&chunk->partitions_bitmap);
memory_free(chunk);
}
void drive_manager_init(void) {
g_drive_manager.chunks = drive_chunk_alloc(NULL);
}
drive_T* drive_manager_add_drive(drive_controller_types_E controller_type, void* controller, void* device) {
uint32_t num_chunks = 0;
drive_chunk_T* chunk = g_drive_manager.chunks;
while (chunk->num_drives == DRIVE_CHUNK_SIZE) {
if (chunk->next == NULL) {
drive_chunk_alloc(chunk);
}
chunk = chunk->next;
num_chunks++;
}
for (int i = 0; i < DRIVE_CHUNK_SIZE; i++) {
if (bitmap_get(&chunk->drives_bitmap, i)) continue;
bitmap_set(&chunk->drives_bitmap, i, true);
drive_T* drive = &chunk->drives[i];
drive->id_in_chunk = i;
drive->id = (num_chunks * DRIVE_CHUNK_SIZE) + i;
drive->partitions_chunks = drive_partition_chunk_alloc(NULL);
drive->controller_type = controller_type;
drive->controller = controller;
drive->chunk = chunk;
chunk->num_drives += 1;
log(LOG_INFO, "Registered drive %d", drive->id);
return drive;
}
// this should never happen
return NULL;
}
void drive_manager_remove_drive(drive_T* drive) {
if (drive == NULL) return;
drive_chunk_T* chunk = drive->chunk;
if (!bitmap_get(&chunk->drives_bitmap, drive->id_in_chunk)) return;
drive_partition_chunk_T* partition_chunk = drive->partitions_chunks;
while (partition_chunk != NULL) {
drive_partition_chunk_T* next = partition_chunk->next;
drive_partition_chunk_destruct(partition_chunk);
partition_chunk = next;
}
chunk->num_drives -= 1;
bitmap_set(&chunk->drives_bitmap, drive->id_in_chunk, false);
}
drive_partition_T* drive_manager_add_partition(drive_T* drive, uint32_t start_sector, uint32_t end_sector) {
uint32_t num_chunks = 0;
drive_partition_chunk_T* chunk = drive->partitions_chunks;
while (chunk->num_partitions == DRIVE_PARTITION_CHUNK_SIZE) {
if (chunk->next == NULL) {
drive_partition_chunk_alloc(chunk);
}
chunk = chunk->next;
num_chunks++;
}
for (int i = 0; i < DRIVE_PARTITION_CHUNK_SIZE; i++) {
if (bitmap_get(&chunk->partitions_bitmap, i)) continue;
bitmap_set(&chunk->partitions_bitmap, i, true);
drive_partition_T* partition = &chunk->partitions[i];
partition->id_in_chunk = i;
partition->id = (num_chunks * DRIVE_CHUNK_SIZE) + i;
partition->drive = drive;
partition->chunk = chunk;
partition->start_sector = start_sector;
partition->end_sector = end_sector;
// TODO: set partition filesystem
chunk->num_partitions += 1;
log(LOG_INFO, "Registered partition %d in drive %d", partition->id, drive->id);
return partition;
}
// this should never happen
return NULL;
}
void drive_manager_remove_partition(drive_partition_T* partition) {
if (partition == NULL) return;
drive_partition_chunk_T* chunk = partition->chunk;
if (!bitmap_get(&chunk->partitions_bitmap, partition->id_in_chunk)) return;
chunk->num_partitions -= 1;
bitmap_set(&chunk->partitions_bitmap, partition->id_in_chunk, false);
}