Skip to content
Open
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
2 changes: 1 addition & 1 deletion hal/ia32/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

include hal/tlb/Makefile

OBJS += $(addprefix $(PREFIX_O)hal/ia32/, _init.o _exceptions.o _interrupts.o spinlock.o exceptions.o interrupts.o cpu.o pmap.o timer.o hal.o string.o pci.o init.o)
OBJS += $(addprefix $(PREFIX_O)hal/ia32/, _init.o _exceptions.o _interrupts.o spinlock.o exceptions.o interrupts.o cpu.o pmap.o timer.o hal.o string.o pci.o init.o acpi.o)
CFLAGS += -Ihal/ia32

ifeq ($(CONSOLE), vga)
Expand Down
8 changes: 8 additions & 0 deletions hal/ia32/_interrupts.S
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,14 @@ INTERRUPT(_interrupts_irq12, 12, interrupts_dispatchIRQ)
INTERRUPT(_interrupts_irq13, 13, interrupts_dispatchIRQ)
INTERRUPT(_interrupts_irq14, 14, interrupts_dispatchIRQ)
INTERRUPT(_interrupts_irq15, 15, interrupts_dispatchIRQ)
INTERRUPT(_interrupts_irq16, 16, interrupts_dispatchIRQ)
INTERRUPT(_interrupts_irq17, 17, interrupts_dispatchIRQ)
INTERRUPT(_interrupts_irq18, 18, interrupts_dispatchIRQ)
INTERRUPT(_interrupts_irq19, 19, interrupts_dispatchIRQ)
INTERRUPT(_interrupts_irq20, 20, interrupts_dispatchIRQ)
INTERRUPT(_interrupts_irq21, 21, interrupts_dispatchIRQ)
INTERRUPT(_interrupts_irq22, 22, interrupts_dispatchIRQ)
INTERRUPT(_interrupts_irq23, 23, interrupts_dispatchIRQ)
INTERRUPT(_interrupts_unexpected, 255, _interrupts_unexpected)


Expand Down
31 changes: 31 additions & 0 deletions hal/ia32/acpi.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* Phoenix-RTOS
*
* Operating system kernel
*
* ACPI kernel-userspace interface
*
* Copyright 2025 Phoenix Systems
* Author: Adam Greloch
*
* %LICENSE%
*/

#include "include/errno.h"
#include "include/arch/ia32/ia32.h"
#include "halsyspage.h"


int hal_acpiGet(acpi_var_t var, int *value)
{
switch (var) {
case acpi_rsdpAddr:
if (syspage->hs.acpi_version != ACPI_RSDP) {
return -EINVAL;
}
*value = syspage->hs.rsdp;
return EOK;
}

return -EINVAL;
}
23 changes: 23 additions & 0 deletions hal/ia32/acpi.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* Phoenix-RTOS
*
* Operating system kernel
*
* ACPI kernel-userspace interface
*
* Copyright 2025 Phoenix Systems
* Author: Adam Greloch
*
* %LICENSE%
*/

#ifndef _HAL_ACPI_H_
#define _HAL_ACPI_H_

#include "include/arch/ia32/ia32.h"


extern int hal_acpiGet(acpi_var_t var, int *value);


#endif
17 changes: 15 additions & 2 deletions hal/ia32/cpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "hal/pmap.h"
#include "hal/hal.h"
#include "hal/tlb/tlb.h"
#include "acpi.h"
#include "pci.h"
#include "ia32.h"
#include "halsyspage.h"
Expand Down Expand Up @@ -548,15 +549,27 @@ int hal_platformctl(void *ptr)
platformctl_t *data = (platformctl_t *)ptr;

switch (data->type) {
case pctl_acpi:
if (data->action == pctl_get) {
return hal_acpiGet(data->acpi.var, &data->acpi.value);
}
break;

case pctl_pci:
if (data->action == pctl_get) {
return hal_pciGetDevice(&data->pci.id, &data->pci.dev, data->pci.caps);
}
break;

case pctl_busmaster:
case pctl_pcicfg:
if (data->action == pctl_set) {
return hal_pciSetConfigOption(&data->pcicfg.dev, data->pcicfg.cfg, data->pcicfg.enable);
}
break;

case pctl_usbownership:
if (data->action == pctl_set) {
return hal_pciSetBusmaster(&data->busmaster.dev, data->busmaster.enable);
return hal_pciSetUsbOwnership(&data->usbownership.dev, data->usbownership.eecp, data->usbownership.osOwned);
}
break;

Expand Down
41 changes: 38 additions & 3 deletions hal/ia32/interrupts.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,14 @@ extern void _interrupts_irq12(void);
extern void _interrupts_irq13(void);
extern void _interrupts_irq14(void);
extern void _interrupts_irq15(void);
extern void _interrupts_irq16(void);
extern void _interrupts_irq17(void);
extern void _interrupts_irq18(void);
extern void _interrupts_irq19(void);
extern void _interrupts_irq20(void);
extern void _interrupts_irq21(void);
extern void _interrupts_irq22(void);
extern void _interrupts_irq23(void);

extern void _interrupts_unexpected(void);

Expand All @@ -55,7 +63,8 @@ extern void _interrupts_syscall(void);
extern void _interrupts_TLBShootdown(void);


#define SIZE_INTERRUPTS 16
#define ISA_INTERRUPTS 16
#define SIZE_INTERRUPTS 24


struct {
Expand Down Expand Up @@ -209,6 +218,20 @@ int interrupts_dispatchIRQ(unsigned int n, cpu_context_t *ctx)
}


static inline void _hal_ioapicUnmaskPCI(unsigned int n)
{
u32 high, low;

_hal_ioapicReadIRQ(interrupts_common.irqs[n].ioapic, n, &high, &low);

if ((low & IOAPIC_IRQ_MASK) != 0) {
/* PCI interrupts are active low level triggered */
low |= (IOAPIC_INTPOL | IOAPIC_TRIGGER);
_hal_ioapicWriteIRQ(interrupts_common.irqs[n].ioapic, n, high, low & ~IOAPIC_IRQ_MASK);
}
}


int hal_interruptsSetHandler(intr_handler_t *h)
{
spinlock_ctx_t sc;
Expand All @@ -219,6 +242,10 @@ int hal_interruptsSetHandler(intr_handler_t *h)

hal_spinlockSet(&interrupts_common.interrupts[h->n].spinlock, &sc);
HAL_LIST_ADD(&interrupts_common.interrupts[h->n].handler, h);
if (h->n >= ISA_INTERRUPTS) {
/* Assume IRQs above ISA_INTERRUPTS are PCI interrupts */
_hal_ioapicUnmaskPCI(h->n);
}
hal_spinlockClear(&interrupts_common.interrupts[h->n].spinlock, &sc);

return EOK;
Expand Down Expand Up @@ -429,8 +456,8 @@ static int _hal_ioapicInit(void)
}
}

/* Enable all IRQS */
for (i = 0; i < SIZE_INTERRUPTS; ++i) {
/* Enable all ISA IRQs */
for (i = 0; i < ISA_INTERRUPTS; ++i) {
_hal_ioapicReadIRQ(interrupts_common.irqs[i].ioapic, i, &high, &low);
_hal_ioapicWriteIRQ(interrupts_common.irqs[i].ioapic, i, high, low & ~IOAPIC_IRQ_MASK);
}
Expand Down Expand Up @@ -480,6 +507,14 @@ void _hal_interruptsInit(void)
_interrupts_setIDTEntry(INTERRUPTS_VECTOR_OFFSET + 13, _interrupts_irq13, flags);
_interrupts_setIDTEntry(INTERRUPTS_VECTOR_OFFSET + 14, _interrupts_irq14, flags);
_interrupts_setIDTEntry(INTERRUPTS_VECTOR_OFFSET + 15, _interrupts_irq15, flags);
_interrupts_setIDTEntry(INTERRUPTS_VECTOR_OFFSET + 16, _interrupts_irq16, flags);
_interrupts_setIDTEntry(INTERRUPTS_VECTOR_OFFSET + 17, _interrupts_irq17, flags);
_interrupts_setIDTEntry(INTERRUPTS_VECTOR_OFFSET + 18, _interrupts_irq18, flags);
_interrupts_setIDTEntry(INTERRUPTS_VECTOR_OFFSET + 19, _interrupts_irq19, flags);
_interrupts_setIDTEntry(INTERRUPTS_VECTOR_OFFSET + 20, _interrupts_irq20, flags);
_interrupts_setIDTEntry(INTERRUPTS_VECTOR_OFFSET + 21, _interrupts_irq21, flags);
_interrupts_setIDTEntry(INTERRUPTS_VECTOR_OFFSET + 22, _interrupts_irq22, flags);
_interrupts_setIDTEntry(INTERRUPTS_VECTOR_OFFSET + 23, _interrupts_irq23, flags);

for (k = 0; k < SIZE_INTERRUPTS; k++) {
hal_spinlockCreate(&interrupts_common.interrupts[k].spinlock, "interrupts_common.interrupts[].spinlock");
Expand Down
125 changes: 94 additions & 31 deletions hal/ia32/pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
*
* PCI driver
*
* Copyright 2018, 2019, 2020 Phoenix Systems
* Author: Aleksander Kaminski, Kamil Amanowicz, Lukasz Kosinski
* Copyright 2018, 2019, 2020, 2024 Phoenix Systems
* Author: Aleksander Kaminski, Kamil Amanowicz, Lukasz Kosinski, Adam Greloch
*
* This file is part of Phoenix-RTOS.
*
Expand Down Expand Up @@ -84,19 +84,24 @@ static int _hal_pciGetCaps(pci_dev_t *dev, void *caps)
}


int hal_pciSetBusmaster(pci_dev_t *dev, u8 enable)
/* Sets a bit in PCI configuration command register */
int _hal_pciSetCmdRegBit(pci_dev_t *dev, u8 bit, u8 enable)
{
spinlock_ctx_t sc;
u32 dv;

if (dev == NULL)
if (dev == NULL) {
return -EINVAL;
}

hal_spinlockSet(&pci_common.spinlock, &sc);
dv = _hal_pciGet(dev->bus, dev->dev, dev->func, 1);
dv &= ~(1 << 2);
if (enable)
dv |= (1 << 2);
if (enable != 0) {
dv |= (1 << bit);
}
else {
dv &= ~(1 << bit);
}
_hal_pciSet(dev->bus, dev->dev, dev->func, 1, dv);
hal_spinlockClear(&pci_common.spinlock, &sc);

Expand All @@ -106,11 +111,64 @@ int hal_pciSetBusmaster(pci_dev_t *dev, u8 enable)
}


int hal_pciSetUsbOwnership(pci_dev_t *dev, u8 eecp, u8 osOwned)
{
spinlock_ctx_t sc;
u32 dv;
u8 reg = eecp >> 2U; /* eecp is a pci config offset */

if (dev == NULL) {
return -EINVAL;
}

hal_spinlockSet(&pci_common.spinlock, &sc);
dv = _hal_pciGet(dev->bus, dev->dev, dev->func, reg);
if (osOwned != 0) {
dv |= (1 << 24);
}
else {
dv &= ~(1 << 24);
}
_hal_pciSet(dev->bus, dev->dev, dev->func, reg, dv);

for (;;) {
dv = _hal_pciGet(dev->bus, dev->dev, dev->func, reg);
if ((osOwned != 0) && ((dv & (1 << 24)) != 0) && ((dv & (1 << 16)) == 0)) {
break;
}

if ((osOwned == 0) && ((dv & (1 << 24)) == 0) && ((dv & (1 << 16)) != 0)) {
break;
}
}
hal_spinlockClear(&pci_common.spinlock, &sc);

dev->command = dv & 0xffff;

return EOK;
}


int hal_pciSetConfigOption(pci_dev_t *dev, pci_cfg_t cfg, u8 enable)
{
switch (cfg) {
case pci_cfg_interruptdisable:
return _hal_pciSetCmdRegBit(dev, 10, enable);
case pci_cfg_memoryspace:
return _hal_pciSetCmdRegBit(dev, 1, enable);
case pci_cfg_busmaster:
return _hal_pciSetCmdRegBit(dev, 2, enable);
default:
return -EINVAL;
}
}


int hal_pciGetDevice(pci_id_t *id, pci_dev_t *dev, void *caps)
{
spinlock_ctx_t sc;
unsigned char b, d, f, i;
u32 dv, cl, mask, val;
u32 val0, cl, progif, mask, valB, val2;
int res = EOK;

if ((id == NULL) || (dev == NULL))
Expand All @@ -122,57 +180,62 @@ int hal_pciGetDevice(pci_id_t *id, pci_dev_t *dev, void *caps)
hal_spinlockSet(&pci_common.spinlock, &sc);

do {
if ((dv = _hal_pciGet(b, d, f, 0)) == 0xffffffff)
if ((val0 = _hal_pciGet(b, d, f, 0)) == 0xffffffff)
break;

if ((id->vendor != PCI_ANY) && (id->vendor != (dv & 0xffff)))
if ((id->vendor != PCI_ANY) && (id->vendor != (val0 & 0xffff)))
break;

if ((id->device != PCI_ANY) && (id->device != (dv >> 16)))
if ((id->device != PCI_ANY) && (id->device != (val0 >> 16)))
break;

cl = _hal_pciGet(b, d, f, 2) >> 16;
val2 = _hal_pciGet(b, d, f, 0x2);

cl = val2 >> 16;
progif = (val2 >> 8) & 0xff;

if ((id->cl != PCI_ANY) && (id->cl != cl))
break;

val = _hal_pciGet(b, d, f, 0xb);
if ((id->progif != PCI_ANY) && (id->progif != progif))
break;

valB = _hal_pciGet(b, d, f, 0xb);

if ((id->subdevice != PCI_ANY) && (id->subdevice != (val >> 16)))
if ((id->subdevice != PCI_ANY) && (id->subdevice != (valB >> 16)))
break;

if ((id->subvendor != PCI_ANY) && (id->subvendor != (val & 0xffff)))
if ((id->subvendor != PCI_ANY) && (id->subvendor != (valB & 0xffff)))
break;

dev->bus = b;
dev->dev = d;
dev->func = f;
dev->vendor = dv & 0xffff;
dev->device = dv >> 16;
dev->vendor = val0 & 0xffff;
dev->device = val0 >> 16;
dev->cl = cl;
dev->subvendor = val & 0xffff;
dev->subdevice = val >> 16;
dev->subvendor = valB & 0xffff;
dev->subdevice = valB >> 16;

dv = _hal_pciGet(b, d, f, 1);
dev->status = dv >> 16;
dev->command = dv & 0xffff;
val0 = _hal_pciGet(b, d, f, 0x1);
dev->status = val0 >> 16;
dev->command = val0 & 0xffff;

val = _hal_pciGet(b, d, f, 2);
dev->progif = (val >> 8) & 0xff;
dev->revision = val & 0xff;
dev->type = (_hal_pciGet(b, d, f, 3) >> 16) & 0xff;
dev->irq = _hal_pciGet(b, d, f, 15) & 0xff;
dev->progif = progif;
dev->revision = val2 & 0xff;
dev->type = (_hal_pciGet(b, d, f, 0x3) >> 16) & 0xff;
dev->irq = _hal_pciGet(b, d, f, 0xf) & 0xff;

/* Get resources */
for (i = 0; i < 6; i++) {
dev->resources[i].base = _hal_pciGet(b, d, f, 4 + i);
dev->resources[i].base = _hal_pciGet(b, d, f, 0x4 + i);

/* Get resource flags and size */
_hal_pciSet(b, d, f, 4 + i, 0xffffffff);
dev->resources[i].limit = _hal_pciGet(b, d, f, 4 + i);
_hal_pciSet(b, d, f, 0x4 + i, 0xffffffff);
dev->resources[i].limit = _hal_pciGet(b, d, f, 0x4 + i);
mask = (dev->resources[i].base & 0x1) ? ~0x3 : ~0xf;
dev->resources[i].limit = (~(dev->resources[i].limit & mask)) + 1;
_hal_pciSet(b, d, f, 4 + i, dev->resources[i].base);
_hal_pciSet(b, d, f, 0x4 + i, dev->resources[i].base);
dev->resources[i].flags = dev->resources[i].base & ~mask;
dev->resources[i].base &= mask;
}
Expand Down
Loading