| 237 | |
| 238 | |
| 239 | uint8_t PCIDevice::AllocateVector(PCIVectors type){ |
| 240 | if(type & PCIVectorMSI){ |
| 241 | if(!msiCapable){ |
| 242 | Log::Error("[PCIDevice] AllocateVector: Device not MSI capable!"); |
| 243 | } else { |
| 244 | uint8_t interrupt = IDT::ReserveUnusedInterrupt(); |
| 245 | if(interrupt == 0xFF){ |
| 246 | Log::Error("[PCIDevice] AllocateVector: Could not reserve unused interrupt (no free interrupts?)!"); |
| 247 | return interrupt; |
| 248 | } |
| 249 | |
| 250 | msiCap.msiControl = (msiCap.msiControl & ~(PCI_CAP_MSI_CONTROL_MME_MASK | PCI_CAP_MSI_CONTROL_VECTOR_MASKING)) | PCI_CAP_MSI_CONTROL_SET_MME(0); // We only support one message at the moment, disable masking |
| 251 | msiCap.msiControl |= 1; // Enable MSIs |
| 252 | |
| 253 | msiCap.SetData(ICR_VECTOR(interrupt) | ICR_MESSAGE_TYPE_FIXED); |
| 254 | |
| 255 | msiCap.SetAddress(GetCPULocal()->id); |
| 256 | |
| 257 | if(msiCap.msiControl & PCI_CAP_MSI_CONTROL_64){ |
| 258 | PCI::ConfigWriteDword(bus, slot, func, msiPtr + sizeof(uint32_t) * 3, msiCap.register3); |
| 259 | } |
| 260 | PCI::ConfigWriteDword(bus, slot, func, msiPtr + sizeof(uint32_t) * 2, msiCap.register2); |
| 261 | PCI::ConfigWriteDword(bus, slot, func, msiPtr + sizeof(uint32_t), msiCap.register1); |
| 262 | |
| 263 | PCI::ConfigWriteWord(bus, slot, func, msiPtr + sizeof(uint16_t), msiCap.msiControl); |
| 264 | |
| 265 | return interrupt; |
| 266 | } |
| 267 | } |
| 268 | |
| 269 | if(type & PCIVectorLegacy){ |
| 270 | uint8_t irq = GetInterruptLine(); |
| 271 | if(irq == 0xFF){ |
| 272 | Log::Error("[PCIDevice] AllocateVector: Legacy interrupts not supported by device."); |
| 273 | return 0xFF; |
| 274 | } else { |
| 275 | APIC::IO::MapLegacyIRQ(irq); |
| 276 | } |
| 277 | |
| 278 | return IRQ0 | irq; |
| 279 | } |
| 280 | |
| 281 | Log::Error("[PCIDevice] AllocateVector: Could not allocate interrupt (type %i)!", static_cast<int>(type)); |
| 282 | return 0xFF; |
| 283 | } |
no test coverage detected