// SPDX-License-Identifier: MPL-2.0 #ifndef SH_LIB_GSI_H #define SH_LIB_GSI_H #include "std/stdlib.h" #include "devs/apic/ioapic.h" // GSI polarity enum enum sh_gsi_POLARITY { SH_GSI_POLARITY_NOT_SET=0, SH_GSI_POLARITY_BUS_DEFAULT, SH_GSI_POLARITY_ACTIVE_HIGH, SH_GSI_POLARITY_ACTIVE_LOW }; // GSI trigger mode enum enum sh_gsi_TRIGGER_MODE { SH_GSI_TRIGGER_MODE_NOT_SET=0, SH_GSI_TRIGGER_MODE_BUS_DEFAULT, SH_GSI_TRIGGER_MODE_EDGE, SH_GSI_TRIGGER_MODE_LEVEL }; // Interrupt source override (ISO) structure typedef struct { sh_uint32 gsi; // must default to SH_FALSE sh_bool valid; // when ISOs array is initialized, this field must default to 0 sh_uint8 source_irq; // these two fields are determined by the flags field in the MADT entry. Bus-default value are resolved when writing IOREDTBL enum sh_gsi_POLARITY polarity; enum sh_gsi_TRIGGER_MODE trigger_mode; // when ISOs array is initialized, this field must default to 0 sh_uint8 bus; } sh_gsi_ISO; // Initialize a 256 elements array of sh_gsi_ISO structs SH_STATUS sh_gsi_iso_array_init(); // Register an ISO, this function is supposed to be used during MADT parsing when encountering an ISO. It expect the field as they are provided into the MADT entry SH_STATUS sh_gsi_iso_register(sh_uint8 bus,sh_uint8 source,sh_uint32 gsi,sh_uint16 flags); // Return an ISO structure for the given interrupt sh_gsi_ISO *sh_gsi_get_iso_by_irq(sh_uint8 irq); // Return an ISO structure for the given GSI sh_gsi_ISO *sh_gsi_get_iso_by_gsi(sh_uint32 gsi); // These two functions provide a thread-safe and "interrupt-storm" safe way to get and set IOREDTBL entries // Read the IOREDTBL entry associated with the provided GSI SH_STATUS sh_gsi_get(sh_uint32 gsi,sh_ioapic_IOREDTBL_ENTRY *entry); // Set the provided GSI to the corresponding IOREDTBL entry, mask the IOOREDTBL entry and doesn't unmask it SH_STATUS sh_gsi_set(sh_uint32 gsi,sh_ioapic_IOREDTBL_ENTRY *entry); // Set the provided IRQ to IOREDTBL entry, calculate the expected GSI using sh_gsi_get_iso_by_irq SH_STATUS sh_gsi_irq_set(sh_uint8 irq,sh_ioapic_IOREDTBL_ENTRY *entry); // Mask the IOREDTBL entry corresponding to the provided GSI inline SH_STATUS sh_gsi_mask(sh_uint32 gsi) { return sh_ioapic_mask_gsi(sh_ioapic_get_dev_by_gsi(gsi),gsi); } // Unmask the IOREDTBL entry corresponding to the provided GSI inline SH_STATUS sh_gsi_unmask(sh_uint32 gsi) { return sh_ioapic_unmask_gsi(sh_ioapic_get_dev_by_gsi(gsi),gsi); } // Mask the IOREDTBL entry corresponding to the provided IRQ SH_STATUS sh_gsi_irq_mask(sh_uint8 irq); // Unmask the IOREDTBL entry corresponding to the provided IRQ SH_STATUS sh_gsi_irq_unmask(sh_uint8 irq); // Load all legacy IRQ to IOREDTBL entries, intented to be called only one time SH_STATUS sh_gsi_irq_switch(); #endif