2#ifndef PEDIGREE_CHIPSET_INTEL_PIRQ_H
3#define PEDIGREE_CHIPSET_INTEL_PIRQ_H
4#include "pedigree/kernel/processor/types.h"
9inline uint16_t routeOffset(uint8_t device) {
27inline bool decode(uint16_t routes, uint8_t pin, uint8_t& pirq) {
28 if (pin < 1 || pin > 4 || routes == 0xffff)
30 const uint8_t selector = (routes >> (4 * (pin - 1))) & 0xf;
36inline uint16_t pinOffset(uint8_t device) {
54inline bool nativePinMatches(uint32_t pins, uint8_t function, uint8_t pin) {
55 return pins != 0xffffffff && function < 8 && pin >= 1 && pin <= 4 &&
56 ((pins >> (4 * function)) & 0xf) == pin;
58inline bool chipsetExclusions(uint8_t acpiControl, uint8_t tcoControl, uint16_t& excluded) {
59 if (acpiControl == 0xff || tcoControl == 0xff || (acpiControl & 7) == 3 ||
60 ((tcoControl & 0x80) && (tcoControl & 7) == 3))
63 if ((acpiControl & 7) < 3)
64 excluded |= uint16_t{1} << (9 + (acpiControl & 7));
65 if ((tcoControl & 0x80) && (tcoControl & 7) < 3)
66 excluded |= uint16_t{1} << (9 + (tcoControl & 7));
69inline uint16_t hpetExclusion(uint32_t config, uint32_t pending,
unsigned timer,
70 bool legacyReplacement) {
71 if (config == 0xffffffff || pending == 0xffffffff)
72 return (1U << 10) | (1U << 11);
73 if ((config & (1U << 14)) || (legacyReplacement && timer < 2))
75 const unsigned irq = (config >> 9) & 31;
76 const bool active = (config & 4) || ((config & 2) && (pending & (1U << timer)));
77 return active && irq < 16 ? uint16_t{1} << irq : 0;
79inline uint16_t configOffset(uint8_t pirq) {
80 return pirq < 4 ? 0x60 + pirq : 0x68 + pirq - 4;
82inline bool validIrq(uint8_t irq) {
83 return irq < 16 && (0xdef8U & (1U << irq));
86enum class Result { Ready, ReadFailed, Unsupported, Conflict, WriteFailed, RestoreFailed };
91template <
class Config,
class Reserve>
92Result establish(Config& config, Reserve reserve, uint8_t pirq, uint16_t excluded, uint8_t& irq,
93 bool rerouteExcludedEnabled =
false) {
95 return Result::Unsupported;
96 const uint16_t offset = configOffset(pirq);
98 if (!config.read8(offset, original) || original == 0xff)
99 return Result::ReadFailed;
100 if (!(original & 0x80)) {
101 const uint8_t selected = original & 0xf;
102 if (validIrq(selected) && !(excluded & (1U << selected))) {
103 if (!reserve(selected))
104 return Result::Conflict;
106 return Result::Ready;
108 if (!rerouteExcludedEnabled)
109 return Result::Unsupported;
113 const uint8_t choices[] = {
static_cast<uint8_t
>(10 + (pirq & 1)),
114 static_cast<uint8_t
>(11 - (pirq & 1))};
115 for (uint8_t selected : choices) {
116 if ((excluded & (1U << selected)) || !reserve(selected))
118 const uint8_t desired = (original & 0x70) | selected;
120 if (config.write8(offset, desired) && config.read8(offset, actual) && actual == desired) {
122 return Result::Ready;
126 if (!config.write8(offset, original) || !config.read8(offset, actual) || actual != original)
127 return Result::RestoreFailed;
128 return Result::WriteFailed;
130 return Result::Conflict;