Vystem 0.2

This commit is contained in:
2026-05-27 19:34:54 +02:00
parent a43c08b893
commit d238606b75
372 changed files with 51320 additions and 83217 deletions

View File

@@ -0,0 +1,175 @@
// SPDX-License-Identifier: MPL-2.0
#include "devs/apic/ioapic.h"
#include "memory/memory.h"
#include "kernel/log.h"
typedef struct {
sh_ioapic_DEVICE **by_ioapic_id;
sh_uint64 max_ioapic_id;
sh_uint64 ioapic_count;
} ioapic_devs_template;
ioapic_devs_template ioapic_devs={0};
static inline sh_uint32 sh_ioapic_read(sh_ioapic_DEVICE *ioapic,sh_uint32 reg) {
*(volatile sh_uint32*)((sh_uint8*)ioapic->base+SH_IOAPIC_OFFSET_IOREGSEL)=reg;
return *(volatile sh_uint32*)((sh_uint8*)ioapic->base+SH_IOAPIC_OFFSET_IOWIN);
}
static inline void sh_ioapic_write(sh_ioapic_DEVICE *ioapic,sh_uint32 reg,sh_uint32 value) {
*(volatile sh_uint32*)((sh_uint8*)ioapic->base+SH_IOAPIC_OFFSET_IOREGSEL)=reg;
*(volatile sh_uint32*)((sh_uint8*)ioapic->base+SH_IOAPIC_OFFSET_IOWIN)=value;
}
SH_STATUS sh_ioapic_init(sh_uint32 base,sh_uint8 ioapic_id,sh_uint32 gsi_base,sh_ioapic_DEVICE *ioapic) {
if (ioapic==SH_NULLPTR || base==0) return SH_STATUS_INVALID_PARAMETER;
sh_uint64 page=base& ~0xfffull;
SH_STATUS status=sh_memory_identity_map(page,1,SH_PAGE_RW | SH_PAGE_PRESENT | SH_PAGE_NX | SH_PAGE_PCD);
if (sh_status_error(status) && status!=SH_STATUS_ERROR_VA_FULLY_MAPPED) return status;
ioapic->base=(volatile sh_uint32*)(sh_uint64)base;
ioapic->ioapic_id=ioapic_id;
ioapic->gsi_base=gsi_base;
ioapic->gsi_count=0;
ioapic->lock=SH_LOCK_LOCAL();
sh_uint32 ver=sh_ioapic_read(ioapic,SH_IOAPIC_REGISTER_IOAPICVER);
sh_uint32 max_redir=(ver>>16)&0xFF;
ioapic->gsi_count=max_redir+1;
sh_log_fdebug(SH_LOG_SOURCE_ACPI,"IOAPIC with id %1u: [%4u - %4u]\n",ioapic->ioapic_id,ioapic->gsi_base,ioapic->gsi_base+ioapic->gsi_count-1);
sh_uint32 id_reg=sh_ioapic_read(ioapic,SH_IOAPIC_REGISTER_IOAPICID);
sh_uint8 hw_id=(id_reg>>24)&0x0F;
if (hw_id!=ioapic_id) {
sh_log_fwarning(SH_LOG_SOURCE_ACPI,"IOAPIC of IOAPIC id %1u doesn't provide the same id in his hardware register: %4u.\n",ioapic_id,hw_id);
}
return SH_STATUS_SUCCESS;
}
SH_STATUS sh_ioapic_init_devs(sh_uint8 max_ioapic_id) {
sh_ioapic_DEVICE **ioapic_ptr_by_ioapic_id=sh_malloc((max_ioapic_id+1)*sizeof(sh_ioapic_DEVICE*));
if (!ioapic_ptr_by_ioapic_id) return SH_STATUS_ERROR_NULLPTR_RETURNED;
sh_mem_set_8((sh_uint8*)ioapic_ptr_by_ioapic_id,0x0,(max_ioapic_id+1)*sizeof(sh_ioapic_DEVICE*));
ioapic_devs.by_ioapic_id=ioapic_ptr_by_ioapic_id;
ioapic_devs.max_ioapic_id=max_ioapic_id;
return SH_STATUS_SUCCESS;
}
SH_STATUS sh_ioapic_bind(sh_ioapic_DEVICE *ioapic_dev) {
if (ioapic_dev==SH_NULLPTR) return SH_STATUS_INVALID_PARAMETER;
if (ioapic_devs.by_ioapic_id==SH_NULLPTR) return SH_STATUS_DEVS_NOT_INITIALIZED;
ioapic_devs.by_ioapic_id[ioapic_dev->ioapic_id]=ioapic_dev;
ioapic_devs.ioapic_count++;
return SH_STATUS_SUCCESS;
}
sh_ioapic_DEVICE *sh_ioapic_get_dev_ioapic_id(sh_uint64 ioapic_id) {
if (ioapic_id>ioapic_devs.max_ioapic_id) return SH_NULLPTR;
return ioapic_devs.by_ioapic_id[ioapic_id];
}
SH_STATUS sh_ioapic_read_ioredtbl_entry(sh_ioapic_DEVICE *ioapic_dev,sh_uint32 gsi,sh_ioapic_IOREDTBL_ENTRY *entry) {
if (!ioapic_dev || !entry) return SH_STATUS_INVALID_PARAMETER;
if (gsi<ioapic_dev->gsi_base) return SH_STATUS_INVALID_PARAMETER;
sh_uint32 index=gsi-ioapic_dev->gsi_base;
if (index>=ioapic_dev->gsi_count) return SH_STATUS_INVALID_PARAMETER;
sh_uint32 low_reg=SH_IOAPIC_REGISTER_IOREDTBL_BASE+(index*2);
sh_uint32 high_reg=low_reg+1;
sh_spin_lock(&ioapic_dev->lock);
entry->low=sh_ioapic_read(ioapic_dev,low_reg);
entry->high=sh_ioapic_read(ioapic_dev,high_reg);
sh_spin_unlock(&ioapic_dev->lock);
return SH_STATUS_SUCCESS;
}
SH_STATUS sh_ioapic_mask_gsi(sh_ioapic_DEVICE *dev,sh_uint32 gsi) {
if (!dev) return SH_STATUS_INVALID_PARAMETER;
sh_ioapic_IOREDTBL_ENTRY e;
SH_STATUS status=sh_ioapic_read_ioredtbl_entry(dev,gsi,&e);
if (status!=SH_STATUS_SUCCESS) return status;
e.low|=(1<<16);
return sh_ioapic_write_ioredtbl_entry(dev,gsi,&e);
}
SH_STATUS sh_ioapic_unmask_gsi(sh_ioapic_DEVICE *dev,sh_uint32 gsi) {
if (!dev) return SH_STATUS_INVALID_PARAMETER;
sh_ioapic_IOREDTBL_ENTRY e;
SH_STATUS status=sh_ioapic_read_ioredtbl_entry(dev,gsi,&e);
if (status!=SH_STATUS_SUCCESS) return status;
e.low&= ~(1U<<16);
return sh_ioapic_write_ioredtbl_entry(dev,gsi,&e);
}
SH_STATUS sh_ioapic_write_ioredtbl_entry(sh_ioapic_DEVICE *ioapic_dev,sh_uint32 gsi,sh_ioapic_IOREDTBL_ENTRY *entry) {
if (!ioapic_dev || !entry) return SH_STATUS_INVALID_PARAMETER;
if (gsi<ioapic_dev->gsi_base) return SH_STATUS_INVALID_PARAMETER;
sh_uint32 index=gsi-ioapic_dev->gsi_base;
if (index>=ioapic_dev->gsi_count) return SH_STATUS_INVALID_PARAMETER;
sh_uint32 low_reg=SH_IOAPIC_REGISTER_IOREDTBL_BASE+(index*2);
sh_uint32 high_reg=low_reg+1;
sh_spin_lock(&ioapic_dev->lock);
sh_ioapic_write(ioapic_dev,high_reg,entry->high);
sh_ioapic_write(ioapic_dev,low_reg,entry->low);
sh_spin_unlock(&ioapic_dev->lock);
return SH_STATUS_SUCCESS;
}
sh_ioapic_DEVICE *sh_ioapic_get_dev_by_gsi(sh_uint32 gsi) {
if (ioapic_devs.by_ioapic_id==SH_NULLPTR) return SH_NULLPTR;
for (sh_uint64 i=0;i<=ioapic_devs.max_ioapic_id;i++) {
sh_ioapic_DEVICE *dev=ioapic_devs.by_ioapic_id[i];
if (!dev) continue;
if (gsi>=dev->gsi_base && gsi<(dev->gsi_base+dev->gsi_count)) {
return dev;
}
}
return SH_NULLPTR;
}
SH_STATUS sh_ioapic_mask_all() {
if (ioapic_devs.by_ioapic_id==SH_NULLPTR) return SH_STATUS_DEVS_NOT_INITIALIZED;
for (sh_uint64 i=0;i<=ioapic_devs.max_ioapic_id;i++) {
sh_ioapic_DEVICE *dev=ioapic_devs.by_ioapic_id[i];
if (!dev) continue;
for (sh_uint32 j=0;j<dev->gsi_count;j++) {
sh_uint32 gsi=dev->gsi_base+j;
SH_STATUS status=sh_ioapic_mask_gsi(dev,gsi);
if (sh_status_error(status)) return status;
}
}
return SH_STATUS_SUCCESS;
}
SH_STATUS sh_ioapic_devs_query(char *sub_path,sh_devs_RESULT *result) {
if (sub_path==SH_NULLPTR || result==SH_NULLPTR) return SH_STATUS_INVALID_PARAMETER;
sh_uint64 path_len=sh_string_len(sub_path);
if (path_len==0 || path_len>256) return SH_STATUS_INVALID_PARAMETER;
if (ioapic_devs.by_ioapic_id==SH_NULLPTR) return SH_STATUS_DEVS_NOT_INITIALIZED;
if (sh_string_compare(sub_path,"/count",6)) {
if (path_len==6) {
result->type=SH_DEVS_VALUE;
result->value=ioapic_devs.ioapic_count;
return SH_STATUS_SUCCESS;
} else {
return SH_STATUS_NOT_FOUND;
}
} else if (sh_string_compare(sub_path,"/max-ioapic-id",14)) {
if (path_len==14) {
result->type=SH_DEVS_VALUE;
result->value=ioapic_devs.max_ioapic_id;
return SH_STATUS_SUCCESS;
} else {
return SH_STATUS_NOT_FOUND;
}
} else if (sh_string_compare(sub_path,"/by-ioapic-id/",14)) {
if (path_len>14 && path_len<=34) {
sh_uint64 remaining_text=sh_string_len(sub_path)-sh_string_len("/by-ioapic-id/");
char ioapic_id_str[22];
sh_string_substring(sub_path,sh_string_len("/by-ioapic-id/"),remaining_text,ioapic_id_str);
sh_uint64 ioapic_id=sh_string_to_uint64(ioapic_id_str);
if (ioapic_id>ioapic_devs.max_ioapic_id) return SH_STATUS_NOT_FOUND;
result->type=SH_DEVS_IOAPIC;
result->value=(sh_uint64)ioapic_devs.by_ioapic_id[ioapic_id];
return SH_STATUS_SUCCESS;
} else {
return SH_STATUS_NOT_FOUND;
}
} else if (sh_string_compare(sub_path,"/by-gsi/",8)) {
if (path_len>8 && path_len<=28) {
sh_uint64 remaining_text=sh_string_len(sub_path)-sh_string_len("/by-gsi/");
char gsi_str[22];
sh_string_substring(sub_path,sh_string_len("/by-gsi/"),remaining_text,gsi_str);
sh_uint64 gsi=sh_string_to_uint64(gsi_str);
result->type=SH_DEVS_IOAPIC;
result->value=(sh_uint64)sh_ioapic_get_dev_by_gsi((sh_uint32)gsi);
return SH_STATUS_SUCCESS;
} else {
return SH_STATUS_NOT_FOUND;
}
} else {
return SH_STATUS_NOT_FOUND;
}
return SH_STATUS_SUCCESS;
}