Detecting IDE drives, allocating memory for PRDT

This commit is contained in:
notsomeidiot123 2025-09-17 12:24:30 -04:00
parent a5af6c51da
commit c880843b6c
11 changed files with 260 additions and 70 deletions

View File

@ -47,7 +47,7 @@ kernel:
nasm src/kernel/arch_i386/idt.s -o bin/kernel/idt.o -felf32
# ld -T linker.ld bin/kernel/entry.o bin/kernel/*.o -melf_i386
ld -T linker.ld bin/kernel/*.o -melf_i386 -o kernel.elf -static
# ld -T linker.ld -o kernel_interface.elf -r -R kernel.elf -melf_i386
ld -T linker.ld -o kernel_interface.elf -r -R kernel.elf -melf_i386
ld -pie bin/modules/disk_driver.o -o idm.elf -melf_i386 -e init --no-dynamic-linker -static -nostdlib
# ld bin/modules/fs_driver.o -o ifsm.elf -melf_i386
ld -pie bin/modules/fs_driver.o -o ifsm.elf -melf_i386 -e init --no-dynamic-linker -static -nostdlib

View File

@ -24,6 +24,34 @@ uint32_t pm_alloc(){
}
}
}
uint32_t pm_alloc_index(uint32_t index){
for(uint32_t i = index; i < 2; i++){
for(int j = 0; j < 8; j++){
// if(!(pm_map[i] & (1 << j))){
pm_map[i] |= (1 << j);
// }
}
}
return (index << 3) << 12;
}
uint32_t pm_alloc_64kaligned(){
uint32_t cont = 0;
for(uint32_t i = 0; i < mmap_count; i++){
for(int j = 0; j < 8; j++){
if(!(pm_map[i] & (1 << j))){
continue;
}else{
j++;
cont = -1;
break;
}
}
if(cont == 1){
return pm_alloc_index(i);
}
cont++;
}
}
void pm_free(uint32_t address){
pm_map[address >> 15] &= ~(1 << ((address>>12) & 7));
}
@ -169,6 +197,34 @@ void *kmalloc(uint32_t size_pgs){
return (void*)(i << 12);
}
}
void *kmalloc_page_paddr(uint32_t paddr, uint32_t size_pgs){
uint32_t i = 0xc0000000 >> 12; //4mb/4096 (start search at 1mb line)
while(i < (1 << 22)){
uint8_t found = 1;
for(uint32_t j = 0; j < size_pgs; j++){
// printf("found at %x, %x\n", (i + j) << 12, get_paddr((void*)((i + j) << 12)));
if(get_pflags((void *)((i + j) << 12))){
found = 0;
break;
}
}
if(!found){
i++;
continue;
}
for(uint32_t j = 0; j < size_pgs; j++){
uint32_t flags = PT_PRESENT | PT_SYS | (PT_LINK_L * (j != 0)) | (PT_LINK_N * (j < (size_pgs - 1)));
uint32_t physaddr = paddr + j * 4096;
// if(j == 0) printf("%x", physaddr);
// printf("Mapping %x to %x\n", (i + j) << 12, physaddr);
// if(fake) return 0;
map((void *)((i + j) << 12), (void*)physaddr, flags);
}
// fake = !fake;
// for(;;);
return (void*)(i << 12);
}
}
void *kfree(void *vaddr){
uint32_t addr = (uint32_t)vaddr;
addr &= ~0xfff;

View File

@ -25,13 +25,20 @@ uint16_t pci_read_config(uint32_t bus, uint32_t slot, uint32_t func, uint8_t off
uint16_t tmp = (uint16_t)((inl(0xcfc) >> ((offset & 2) * 8)) & 0xffff);
return tmp;
}
uint16_t pci_write_config(uint32_t bus, uint32_t slot, uint32_t func, uint8_t offset, uint16_t word){
uint32_t address = (uint32_t)((bus << 16) | (slot << 11) | (func << 8) | (offset & 0xfc) | ((uint32_t)0x80000000));
outl(0xcf8, address);
outl(0xcfc, word);
return 0;
}
void pci_read_file(vfile_t *file, uint32_t *buffer, uint32_t offset, uint32_t count){
uint8_t bus = file->id >> 16;
uint8_t func = file->id>> 8 & 0xff;
uint8_t slot = file->id & 0xff;
for(uint32_t i = 0; i < count/2; i++){
buffer[i] = pci_read_config(bus, slot, func, offset + i*2) | (pci_read_config(bus, slot, func, offset + i * 2 + 2) << 16);
for(uint32_t i = 0; i < (count); i++){
buffer[i] = pci_read_config(bus, slot, func, offset + i*4) | (pci_read_config(bus, slot, func, offset + i*4 + 2) << 16);
}
return;
}
@ -45,6 +52,9 @@ void pci_make_file(uint32_t class, uint8_t bus, uint8_t slot, uint8_t func){
switch(class >> 8){
case 0x1://PCI class 0x1 is disks
strcpy("disk/", str + strlen(str));
uint32_t l = (uint32_t)pci_read_config(bus, slot, func, 0x4) | (uint32_t)pci_read_config(bus, slot, func, 0x6) << 16;
pci_write_config(bus, slot, func, 0x4, l | 2);
break;
case 0x2://PCI class 0x2 is network controllers
strcpy("net/", str + strlen(str));

View File

@ -35,8 +35,9 @@ extern void kmain(kernel_info_t *kernel_info){
vfs_init();
fcreate("/dev", VFILE_DIRECTORY, kmalloc(1), 1);
fcreate("/tmp", VFILE_DIRECTORY, kmalloc(1), 1);
fcreate("/tmp", VFILE_DIRECTORY, kmalloc(1), 1);
vfile_t *file = fopen("/dev");
printf("%x", file);
mlog("KERNEL", "Initializing Scheduler & starting PID 1\n", MLOG_PRINT);
boot_info = kernel_info;
scheduler_init();

View File

@ -71,6 +71,8 @@ uint32_t get_paddr(void *addr);
uint32_t pm_alloc();
void pm_reserve(uint32_t addr);
void pm_free(uint32_t addr);
uint32_t pm_alloc_64kaligned();
void *kmalloc_page_paddr(uint32_t paddr, uint32_t size);
inline void set_cr3(void *cr3){
asm volatile("mov %0, %%eax; mov %%eax, %%cr3":: "r"(cr3));

View File

@ -71,11 +71,14 @@ uint32_t module_api(uint32_t func, ...){
break;
case MODULE_API_OPEN:
name = va_arg(vars, char *);
file = va_arg(vars, vfile_t *);
return_value = fopen(name, file);
return_value = (uint32_t)fopen(name);
break;
case MODULE_API_MAP:
return_value = -1;
return_value = 0;
void *vaddr = va_arg(vars, void *);
void *paddr = va_arg(vars, void *);
uint32_t flags = va_arg(vars, uint32_t);
map(vaddr, paddr, flags);
break;
case MODULE_API_UNMAP:
return_value = -1;
@ -93,6 +96,14 @@ uint32_t module_api(uint32_t func, ...){
kfree(ptr);
return_value = 0;
break;
case MODULE_API_PMALLOC64K:
return_value = pm_alloc_64kaligned();
break;
case MODULE_API_KMALLOC_PADDR:
paddr = va_arg(vars, uint32_t);
uint32_t size = va_arg(vars, uint32_t);
return_value = kmalloc_page_paddr((uint32_t)paddr, size);
break;
}
va_end(vars);

View File

@ -25,6 +25,8 @@
#define MODULE_API_PADDR 13 //get physical address of memory
#define MODULE_API_MALLOC 14 //allocate memory in 4kb blocks
#define MODULE_API_FREE 15 //free memory allocated by malloc
#define MODULE_API_PMALLOC64K 16
#define MODULE_API_KMALLOC_PADDR 17
typedef struct module{
void *init_entry;

View File

@ -18,6 +18,7 @@ void add_file(vfile_t *vfile, vfile_t *current_dir){
i++;
}
dir_data[i] = vfile;
dir_data[i + 1] = 0;
}
/*
Long comment cause this one's a complicated one.
@ -77,8 +78,8 @@ vfile_t *fcreate(char *name, VFILE_TYPE type, ...){
void *ptr = va_arg(args, void*);
vfile->access.data.ptr = ptr;
vfile->access.data.size_pgs = va_arg(args, uint32_t);
*(uint32_t *)ptr = 0;
add_file(vfile, current_dir);
// printf("Created File: %s\n", vfile->name);
break;
case VFILE_FILE:
case VFILE_DEVICE:
@ -166,8 +167,16 @@ vfile_t *search_dir(char *name, vfile_t dir){
return 0;
}
int fopen(char *name, vfile_t **file){
vfile_t *fopen(char *name){
if(name[0] == '/'){
name++;
}
if(name[strlen(name) - 1] == '/'){
name[strlen(name) - 1] = 0;
}
printf("%s\n", name);
char *dir = strtok(name, '/');
printf("%s", name);
char *tmp = dir;
uint32_t filename_offset = 0;
vfile_t *current_dir = &root_dir;
@ -176,21 +185,23 @@ int fopen(char *name, vfile_t **file){
dir = tmp;
tmpfile = search_dir(tmp, *current_dir);
if(!tmpfile){
return -1;
printf("not found\n");
return 0;
}
switch(tmpfile->type){
case VFILE_DIRECTORY:
printf("found directory in %s: %s\n", current_dir->name, tmpfile->name);
current_dir = tmpfile;
break;
case VFILE_MOUNT:
return ((mount_t*)(tmpfile->access.data.ptr))->open(name + filename_offset, file);
vfile_t *file = kmalloc(1);
((mount_t*)(tmpfile->access.data.ptr))->open(name + filename_offset, file);
return file;
default:
*file = tmpfile;
return 0;
return tmpfile;
}
filename_offset += strlen(tmp) + 1;
tmp = strtok(0, '/');
}
*file = tmpfile;
return 0;
return tmpfile;
}

View File

@ -43,7 +43,7 @@ typedef enum fs_flags{
typedef struct mount_funcs{
int (*write)(vfile_t *file, void *data, uint32_t offset, uint32_t count);
int (*read)(vfile_t *file, void *data, uint32_t offset, uint32_t count);
int (*open)(char *filename, vfile_t **file);
int (*open)(char *filename, vfile_t *file);
void (*delete)(vfile_t *file);
void (*create)(char *filename, FS_FILE_FLAGS flags);
}mount_t;
@ -54,4 +54,4 @@ void fdelete();
int fwrite(vfile_t *file_entry, void *byte_array, uint32_t offset, uint32_t count);
int fread(vfile_t *file_entry, void *byte_array, uint32_t offset, uint32_t count);
vfile_t *search_dir(char *name, vfile_t dir);
int fopen(char *name, vfile_t **file);
vfile_t *fopen(char *name);

View File

@ -1,30 +1,12 @@
#include<stdint.h>
#include "modlib.h"
#include "../kernel/drivers/cpuio.h"
#include "../kernel/shared/string.h"
#define MODULE_NAME "KIDM"
KOS_MAPI_FP api;
// inline void outb(uint16_t port, uint8_t data){
// asm volatile ("outb %0, %1" :: "a"(data), "Nd"(port));
// }
// inline void outw(uint16_t port, uint16_t data){
// asm volatile ("outw %0, %1" :: "a"(data), "Nd"(port));
// }
// inline uint8_t inb(uint16_t port){
// uint8_t byte = 0;
// asm volatile ("inb %1, %0" : "=a"(byte) : "Nd"(port));
// return byte;
// }
// inline uint16_t inw(uint16_t port){
// uint16_t word = 0;
// asm volatile ("inw %1, %0" : "=a"(word) : "Nd"(port));
// return word;
// }
/*
TODO:
Register module
@ -49,11 +31,9 @@ make fini function to destroy global object, and free any remaining resources.
#define ATA_LBA_MID ATA_CYLINDER_LOW
#define ATA_LBA_HIH ATA_CYLINDER_HIGH
#define ATA_ALT_STATUS + 0x206
#define ATA_DEVICE_CONTROL + 0x206
#define ATA_DRIVE_ADDRESS + 0x207
#define ATA_IDENTIFY 0xEC
#define ATA_ALT_STATUS + 0
#define ATA_DEVICE_CONTROL + 0
#define ATA_DRIVE_ADDRESS + 1
#define ATA_PRIMARY_BUS 0x1F0
#define ATA_SECONDARY_BUS 0x170
@ -95,36 +75,103 @@ make fini function to destroy global object, and free any remaining resources.
//data address mark not found
#define ATA_AMNF(a) a & 0x1;
struct {
uint8_t pio_mode:1;
uint8_t lba48:1;
uint8_t drive:2;
}settings = {1, 0, 0};
//commands
#define ATA_CMD_READ_PIO 0x20
#define ATA_CMD_READ_PIO_EXT 0x24
#define ATA_CMD_READ_DMA 0xC8
#define ATA_CMD_READ_DMA_EXT 0x25
#define ATA_CMD_WRITE_PIO 0x30
#define ATA_CMD_WRITE_PIO_EXT 0x34
#define ATA_CMD_WRITE_DMA 0xCA
#define ATA_CMD_WRITE_DMA_EXT 0x35
#define ATA_CMD_CACHE_FLUSH 0xE7
#define ATA_CMD_CACHE_FLUSH_EXT 0xEA
#define ATA_CMD_PACKET 0xA0
#define ATA_CMD_IDENTIFY_PACKET 0xA1
#define ATA_CMD_IDENTIFY 0xEC
#define ATAPI_CMD_READ 0xA8
#define ATAPI_CMD_EJECT 0x1B
#define IDE_ATA 0x00
#define IDE_ATAPI 0x01
#define PCI_IDE_NATIVE(a) a & 1
#define PCI_IDE_CAN_SET_NATIVE(a) a & 2
#define PCI_IDE_SECONDARY_NATIVE(a) a & 4
#define PCI_IDE_SECONDARY_CAN_SET_NATIVE(a) a & 8
#define PCI_IDE_SUPPORT_DMA(a) (a & 0x80)
#define PCI_CLASS_IS_IDE(a) a == 0x0101;
typedef struct PRD{
uint32_t address;
uint16_t byte_count;
uint16_t reserved;//set msb when last;
}__attribute__((packed)) PRD_T;
void fini();
void ata_identify();
//return 1 if ready, 0 if not
enum DRIVE_TYPE{
TYPE_NULL,
TYPE_IDE,
TYPE_AHCI,
TYPE_NVME,
TYPE_USB,
TYPE_FLOPPY, //Here, Navya, just for you
};
typedef struct drive_desc{
uint32_t BARs[8];
enum DRIVE_TYPE type;
uint64_t size_sectors;
uint32_t sector_size_bytes;
struct{
uint8_t irq_dispatched:1;
uint8_t huge:1;//more than 2^28 sectors
uint8_t locked:1;//semaphores!!!!!
uint8_t slave:1;//is this drive a slave drive to another drive?
}__attribute__((packed))flags;
PRD_T *PRDT;
}drive_t;
drive_t drives[32] = {0};
uint16_t get_bus_from_drive(uint32_t drive){
return drive & 2 ? ATA_SECONDARY_BUS : ATA_PRIMARY_BUS;
}
int ata_ready(uint32_t drive){
uint16_t bus = get_bus_from_drive(drive);
if(settings.drive != drive){
if(drive & 1){
outb(bus ATA_DRIVE_HEAD, drive & 1 ? 0xB0 : 0xA0);
}
for(uint32_t i = 0; i < 15; i++){
uint8_t _ = inb(bus ATA_ALT_STATUS);
}
settings.drive = drive;
//return 1 if ready, 0 if not
int ata_ready(uint32_t BAR, uint32_t BAR2, uint8_t drive){
if(drive){
outb(BAR ATA_DRIVE_HEAD, drive ? 0xB0 : 0xA0);
}
uint8_t status = inb(bus ATA_ALT_STATUS);
for(uint32_t i = 0; i < 15; i++){
uint8_t _ = inb(BAR2 ATA_ALT_STATUS);
}
uint8_t status = inb(BAR2 ATA_ALT_STATUS);
if(!ATA_BSY(status) || ATA_DRQ(status)) return 1;
return 0;
}
//return index of first free drive descriptor
uint32_t find_free_drive(){
for(uint32_t i = 0; i < 32; i++){
if(drives[i].type == TYPE_NULL){
return i;
}
}
}
void ide_init(uint32_t BARS[5]){
uint32_t index = find_free_drive();
drives[index].type = TYPE_IDE;
for(int i = 0; i < 5; i++){
drives[index].BARs[i] = BARS[i];
}
uint32_t paddr = api(MODULE_API_PMALLOC64K);
drives[index].PRDT = api(MODULE_API_KMALLOC_PADDR, paddr, 16);
api(MODULE_API_PRINT, MODULE_NAME, "Vaddr: %x, Paddr: %x", drives[index].PRDT, paddr);
}
void init(KOS_MAPI_FP module_api, uint32_t api_version){
api = module_api;
@ -140,14 +187,35 @@ void init(KOS_MAPI_FP module_api, uint32_t api_version){
api(MODULE_API_PRINT, MODULE_NAME, "Failed to register module, exiting\n");
return;
}
ata_identify();
vfile_t *pci_drive_dir = fopen(api, "/dev/pci/disk/");
vfile_t **dir_data = (pci_drive_dir->access.data.ptr);
for(uint32_t i = 0; dir_data[i]; i++){
vfile_t *current_file = dir_data[i];
uint32_t class = 0;
fread(api, current_file, &class, 0x8, 1);
uint32_t progif = class >> 8 & 0xff;
class >>= 16;
api(MODULE_API_PRINT, MODULE_NAME, "Class: %x, %x\n", class, progif);
if(class == 0x101 && PCI_IDE_SUPPORT_DMA(progif)){ //in this house, we only support DMA.
uint32_t BARs[5] = {0};
fread(api, current_file, BARs, 0x10, 5);
if(PCI_IDE_NATIVE(progif)){
BARs[0] = ATA_PRIMARY_BUS;
BARs[1] = ATA_PRIMARY_BUS + 0x206;
}
if(PCI_IDE_SECONDARY_NATIVE(progif)){
BARs[2] = ATA_SECONDARY_BUS;
BARs[3] = ATA_SECONDARY_BUS + 0x206;
}
ide_init(BARs);
}
}
return;
}
void ata_identify(){
}
void fini(){
//destroy all objects, free memory, and
//destroy all objects, free memory, and exit
return; //nothing to do (yet)
}

View File

@ -17,6 +17,8 @@
#define MODULE_API_PADDR 13 //get physical address of memory
#define MODULE_API_MALLOC 14 //allocate memory in 4kb blocks
#define MODULE_API_FREE 15 //free memory allocated by malloc
#define MODULE_API_PMALLOC64K 16 //get 64k-aligned pages
#define MODULE_API_KMALLOC_PADDR 17
typedef uint32_t (*KOS_MAPI_FP)(unsigned int function, ...);
typedef struct module{
@ -40,15 +42,42 @@ typedef struct virtual_file{
VFILE_TYPE type;
uint32_t id;//to be assigned by driver;
uint32_t mount_id;
uint8_t lock;
uint32_t size;
struct virtual_file *parent;//should point to A: a virtual directory, or B: a mounted filesystem
union{
struct{
void (*read)(struct virtual_file *file, void *data, uint32_t offset, uint32_t count);
void (*write)(struct virtual_file *file, void *data, uint32_t offset, uint32_t count);
int (*read)(struct virtual_file *file, void *data, uint32_t offset, uint32_t count);
int (*write)(struct virtual_file *file, void *data, uint32_t offset, uint32_t count);
}funcs;
struct{
void *ptr;
uint16_t size_pgs;
uint16_t free_bytes;
uint32_t size_pgs;
}__attribute__((packed))data;
}access;
}vfile_t;
}vfile_t;
inline void *malloc(KOS_MAPI_FP api, uint32_t size_pages){
return (void *)api(MODULE_API_MALLOC, size_pages);
}
inline void *free(KOS_MAPI_FP api, void *ptr){
api(MODULE_API_FREE, ptr);
return 0;
}
inline vfile_t *fopen(KOS_MAPI_FP api, char *filename){
// vfile_t *file = malloc(api, 1);
return (void *)api(MODULE_API_OPEN, filename);
}
inline int fread(KOS_MAPI_FP api, vfile_t *file, char *buffer, uint32_t offset, uint32_t count){
return api(MODULE_API_READ, file, buffer, offset, count);
}
inline int fwrite(KOS_MAPI_FP api, vfile_t *file, char *buffer, uint32_t offset, uint32_t count){
return api(MODULE_API_WRITE, file, buffer, offset, count);
}
//read documenation for this one
inline vfile_t *fcreate(KOS_MAPI_FP api, char *filename, VFILE_TYPE type, char *pointer_write, char *size_read){
return (void *)api(MODULE_API_CREAT, filename, type, pointer_write, size_read);
}
inline void puts(KOS_MAPI_FP api, char *mname, char *str){
api(MODULE_API_PRINT, mname, str);
};