feature (drive manager): implemented a manager for drives/storage media
This commit is contained in:
parent
7e5fee1437
commit
0bed26ff26
|
@ -5,6 +5,7 @@
|
||||||
|
|
||||||
#include "utils/stdtypes.h"
|
#include "utils/stdtypes.h"
|
||||||
#include "drivers/pci.h"
|
#include "drivers/pci.h"
|
||||||
|
#include "drivers/drive_manager.h"
|
||||||
|
|
||||||
#define SATA_SIG_ATA 0x00000101
|
#define SATA_SIG_ATA 0x00000101
|
||||||
#define SATA_SIG_ATAPI 0xEB140101
|
#define SATA_SIG_ATAPI 0xEB140101
|
||||||
|
@ -209,23 +210,26 @@ typedef struct{
|
||||||
} ahci_hba_command_table_T;
|
} ahci_hba_command_table_T;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct ahci_controller_T ahci_controller_T;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
ahci_hba_port_T* hba_port;
|
ahci_hba_port_T* hba_port;
|
||||||
ahci_device_type_E type;
|
ahci_device_type_E type;
|
||||||
uint8_t* buffer;
|
ahci_controller_T* controller;
|
||||||
uint8_t id;
|
uint8_t id;
|
||||||
|
drive_T* drive;
|
||||||
|
|
||||||
void* cmd_list_base;
|
void* cmd_list_base;
|
||||||
void* fis_base;
|
void* fis_base;
|
||||||
void* command_tables [32];
|
void* command_tables [32];
|
||||||
} ahci_port_T;
|
} ahci_port_T;
|
||||||
|
|
||||||
typedef struct {
|
struct ahci_controller_T {
|
||||||
ahci_port_T ports [32];
|
ahci_port_T ports [32];
|
||||||
int num_ports;
|
int num_ports;
|
||||||
pci_device_T* pci_device;
|
pci_device_T* pci_device;
|
||||||
ahci_hba_memory_T* abar;
|
ahci_hba_memory_T* abar;
|
||||||
} ahci_controller_T;
|
};
|
||||||
|
|
||||||
ahci_controller_T* ahci_controller_alloc (pci_device_T* pci_device);
|
ahci_controller_T* ahci_controller_alloc (pci_device_T* pci_device);
|
||||||
void ahci_controller_destruct (ahci_controller_T* controller);
|
void ahci_controller_destruct (ahci_controller_T* controller);
|
||||||
|
|
|
@ -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
|
|
@ -15,6 +15,7 @@
|
||||||
#include "drivers/graphics/renderer.h"
|
#include "drivers/graphics/renderer.h"
|
||||||
#include "drivers/fs/vfs.h"
|
#include "drivers/fs/vfs.h"
|
||||||
#include "drivers/acpi/acpi.h"
|
#include "drivers/acpi/acpi.h"
|
||||||
|
#include "drivers/drive_manager.h"
|
||||||
#include "drivers/pci.h"
|
#include "drivers/pci.h"
|
||||||
#include "drivers/ps2/controller.h"
|
#include "drivers/ps2/controller.h"
|
||||||
#include "drivers/tty.h"
|
#include "drivers/tty.h"
|
||||||
|
@ -49,6 +50,8 @@ void kernel_init(boot_info_T* boot_info) {
|
||||||
|
|
||||||
acpi_init(boot_info);
|
acpi_init(boot_info);
|
||||||
|
|
||||||
|
drive_manager_init();
|
||||||
|
|
||||||
pci_init();
|
pci_init();
|
||||||
|
|
||||||
tty_init();
|
tty_init();
|
||||||
|
|
|
@ -40,6 +40,7 @@ ahci_controller_T* ahci_controller_alloc(pci_device_T* pci_device) {
|
||||||
port->type = type;
|
port->type = type;
|
||||||
port->hba_port = &controller->abar->ports[i];
|
port->hba_port = &controller->abar->ports[i];
|
||||||
port->id = controller->num_ports;
|
port->id = controller->num_ports;
|
||||||
|
port->controller = controller;
|
||||||
|
|
||||||
controller->num_ports += 1;
|
controller->num_ports += 1;
|
||||||
break;
|
break;
|
||||||
|
@ -94,6 +95,8 @@ void ahci_port_init(ahci_port_T* port) {
|
||||||
|
|
||||||
ahci_port_command_start(port);
|
ahci_port_command_start(port);
|
||||||
|
|
||||||
|
port->drive = drive_manager_add_drive(DRIVE_CONTROLLER_AHCI, port->controller, port);
|
||||||
|
|
||||||
ahci_port_init_partitions_mbr(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;
|
mbr_partition_types_E type = mbr->partitions[i].partition_type;
|
||||||
if (type == MBR_PARTITION_TYPE_UNUSED) continue;
|
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) {
|
if (type == MBR_PARTITION_TYPE_GPT) {
|
||||||
ahci_port_init_partitions_gpt(port);
|
ahci_port_init_partitions_gpt(port);
|
||||||
break;
|
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 {
|
} else {
|
||||||
log(LOG_INFO, " p%d: (%d)<--LBA-->(%d) %s", i, entry->starting_lba, entry->ending_lba, gpt_partition_type_to_string(type));
|
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) {
|
void ahci_port_destruct(ahci_port_T* port) {
|
||||||
|
|
||||||
|
drive_manager_remove_drive(port->drive);
|
||||||
|
|
||||||
for (uint32_t i = 0; i < 32; i++) {
|
for (uint32_t i = 0; i < 32; i++) {
|
||||||
pframe_free(port->command_tables[i]);
|
pframe_free(port->command_tables[i]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
Loading…
Reference in New Issue