Kernel: Implement MSI, MSI-X and interrupt reservation
This commit is contained in:
		
							parent
							
								
									56a29dc176
								
							
						
					
					
						commit
						c6130f33d7
					
				|  | @ -14,6 +14,9 @@ namespace Kernel | |||
| 		virtual void enable_irq(uint8_t) override; | ||||
| 		virtual bool is_in_service(uint8_t) override; | ||||
| 
 | ||||
| 		virtual BAN::ErrorOr<void> reserve_irq(uint8_t irq) override; | ||||
| 		virtual BAN::Optional<uint8_t> get_free_irq() override; | ||||
| 
 | ||||
| 	private: | ||||
| 		uint32_t read_from_local_apic(ptrdiff_t); | ||||
| 		void write_to_local_apic(ptrdiff_t, uint32_t); | ||||
|  | @ -54,6 +57,7 @@ namespace Kernel | |||
| 		Kernel::vaddr_t			m_local_apic_vaddr = 0; | ||||
| 		BAN::Vector<IOAPIC>		m_io_apics;	 | ||||
| 		uint8_t					m_irq_overrides[0x100] {}; | ||||
| 		uint8_t					m_reserved_gsis[0x100 / 8] {}; | ||||
| 	}; | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -1,5 +1,8 @@ | |||
| #pragma once | ||||
| 
 | ||||
| #include <BAN/Optional.h> | ||||
| #include <BAN/Errors.h> | ||||
| 
 | ||||
| #include <stdint.h> | ||||
| 
 | ||||
| #define DISABLE_INTERRUPTS() asm volatile("cli") | ||||
|  | @ -37,6 +40,9 @@ namespace Kernel | |||
| 		static void initialize(bool force_pic); | ||||
| 		static InterruptController& get(); | ||||
| 
 | ||||
| 		virtual BAN::ErrorOr<void> reserve_irq(uint8_t irq) = 0; | ||||
| 		virtual BAN::Optional<uint8_t> get_free_irq() = 0; | ||||
| 
 | ||||
| 		bool is_using_apic() const { return m_using_apic; } | ||||
| 
 | ||||
| 		void enter_acpi_mode(); | ||||
|  |  | |||
|  | @ -79,7 +79,8 @@ namespace Kernel::PCI | |||
| 		uint16_t vendor_id() const { return m_vendor_id; } | ||||
| 		uint16_t device_id() const { return m_device_id; } | ||||
| 
 | ||||
| 		BAN::ErrorOr<uint8_t> get_irq(); | ||||
| 		BAN::ErrorOr<void> reserve_irqs(uint8_t count); | ||||
| 		uint8_t get_irq(uint8_t index); | ||||
| 
 | ||||
| 		BAN::ErrorOr<BAN::UniqPtr<BarRegion>> allocate_bar_region(uint8_t bar_num); | ||||
| 
 | ||||
|  | @ -92,15 +93,15 @@ namespace Kernel::PCI | |||
| 		void enable_io_space(); | ||||
| 		void disable_io_space(); | ||||
| 
 | ||||
| 		void enable_pin_interrupts(); | ||||
| 		void disable_pin_interrupts(); | ||||
| 
 | ||||
| 	private: | ||||
| 		void enumerate_capabilites(); | ||||
| 
 | ||||
| 		void set_command_bits(uint16_t mask); | ||||
| 		void unset_command_bits(uint16_t mask); | ||||
| 
 | ||||
| 		void enable_pin_interrupts(); | ||||
| 		void disable_pin_interrupts(); | ||||
| 
 | ||||
| 	private: | ||||
| 		const uint8_t m_bus; | ||||
| 		const uint8_t m_dev; | ||||
|  | @ -114,6 +115,9 @@ namespace Kernel::PCI | |||
| 		uint16_t m_vendor_id; | ||||
| 		uint16_t m_device_id; | ||||
| 
 | ||||
| 		uint32_t m_reserved_irqs { 0 }; | ||||
| 		uint8_t m_reserved_irq_count { 0 }; | ||||
| 
 | ||||
| 		BAN::Optional<uint8_t> m_offset_msi; | ||||
| 		BAN::Optional<uint8_t> m_offset_msi_x; | ||||
| 	}; | ||||
|  |  | |||
|  | @ -12,12 +12,16 @@ namespace Kernel | |||
| 		virtual void enable_irq(uint8_t) override; | ||||
| 		virtual bool is_in_service(uint8_t) override; | ||||
| 
 | ||||
| 		virtual BAN::ErrorOr<void> reserve_irq(uint8_t irq) override; | ||||
| 		virtual BAN::Optional<uint8_t> get_free_irq() override; | ||||
| 
 | ||||
| 		static void remap(); | ||||
| 		static void mask_all(); | ||||
| 
 | ||||
| 	private: | ||||
| 		static PIC* create(); | ||||
| 		friend class InterruptController; | ||||
| 		uint16_t m_reserved_irqs { 0 }; | ||||
| 	}; | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -223,8 +223,16 @@ namespace Kernel | |||
| 
 | ||||
| 	void APIC::enable_irq(uint8_t irq) | ||||
| 	{ | ||||
| 		CriticalScope _; | ||||
| 
 | ||||
| 		uint32_t gsi = m_irq_overrides[irq]; | ||||
| 
 | ||||
| 		{ | ||||
| 			int byte = gsi / 8; | ||||
| 			int bit  = gsi % 8; | ||||
| 			ASSERT(m_reserved_gsis[byte] & (1 << bit)); | ||||
| 		} | ||||
| 
 | ||||
| 		IOAPIC* ioapic = nullptr; | ||||
| 		for (IOAPIC& io : m_io_apics) | ||||
| 		{ | ||||
|  | @ -258,4 +266,67 @@ namespace Kernel | |||
| 		return isr & (1 << bit); | ||||
| 	} | ||||
| 
 | ||||
| 	BAN::ErrorOr<void> APIC::reserve_irq(uint8_t irq) | ||||
| 	{ | ||||
| 		CriticalScope _; | ||||
| 
 | ||||
| 		uint32_t gsi = m_irq_overrides[irq]; | ||||
| 
 | ||||
| 		IOAPIC* ioapic = nullptr; | ||||
| 		for (IOAPIC& io : m_io_apics) | ||||
| 		{ | ||||
| 			if (io.gsi_base <= gsi && gsi <= io.gsi_base + io.max_redirs) | ||||
| 			{ | ||||
| 				ioapic = &io; | ||||
| 				break; | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		if (!ioapic) | ||||
| 		{ | ||||
| 			dwarnln("Cannot enable irq {} for APIC", irq); | ||||
| 			return BAN::Error::from_errno(EFAULT); | ||||
| 		} | ||||
| 
 | ||||
| 		int byte = gsi / 8; | ||||
| 		int bit  = gsi % 8; | ||||
| 		if (m_reserved_gsis[byte] & (1 << bit)) | ||||
| 		{ | ||||
| 			dwarnln("irq {} is already reserved", irq); | ||||
| 			return BAN::Error::from_errno(EFAULT); | ||||
| 		} | ||||
| 		m_reserved_gsis[byte] |= 1 << bit; | ||||
| 		return {}; | ||||
| 	} | ||||
| 
 | ||||
| 	BAN::Optional<uint8_t> APIC::get_free_irq() | ||||
| 	{ | ||||
| 		CriticalScope _; | ||||
| 		for (int irq = 0; irq <= 0xFF; irq++) | ||||
| 		{ | ||||
| 			uint32_t gsi = m_irq_overrides[irq]; | ||||
| 		 | ||||
| 			IOAPIC* ioapic = nullptr; | ||||
| 			for (IOAPIC& io : m_io_apics) | ||||
| 			{ | ||||
| 				if (io.gsi_base <= gsi && gsi <= io.gsi_base + io.max_redirs) | ||||
| 				{ | ||||
| 					ioapic = &io; | ||||
| 					break; | ||||
| 				} | ||||
| 			} | ||||
| 
 | ||||
| 			if (!ioapic) | ||||
| 				continue; | ||||
| 
 | ||||
| 			int byte = gsi / 8; | ||||
| 			int bit  = gsi % 8; | ||||
| 			if (m_reserved_gsis[byte] & (1 << bit)) | ||||
| 				continue; | ||||
| 			m_reserved_gsis[byte] |= 1 << bit; | ||||
| 			return irq; | ||||
| 		} | ||||
| 		return {}; | ||||
| 	} | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -329,6 +329,18 @@ namespace Kernel::Input | |||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		// Reserve IRQs
 | ||||
| 		if (m_devices[0] && InterruptController::get().reserve_irq(PS2::IRQ::DEVICE0).is_error()) | ||||
| 		{ | ||||
| 			dwarnln("Could not reserve irq for PS/2 port 1"); | ||||
| 			m_devices[0].clear(); | ||||
| 		} | ||||
| 		if (m_devices[1] && InterruptController::get().reserve_irq(PS2::IRQ::DEVICE1).is_error()) | ||||
| 		{ | ||||
| 			dwarnln("Could not reserve irq for PS/2 port 2"); | ||||
| 			m_devices[1].clear(); | ||||
| 		} | ||||
| 		 | ||||
| 		if (!m_devices[0] && !m_devices[1]) | ||||
| 			return {}; | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,3 +1,4 @@ | |||
| #include <kernel/IDT.h> | ||||
| #include <kernel/IO.h> | ||||
| #include <kernel/Memory/PageTable.h> | ||||
| #include <kernel/MMIO.h> | ||||
|  | @ -6,8 +7,6 @@ | |||
| #include <kernel/Storage/ATA/AHCI/Controller.h> | ||||
| #include <kernel/Storage/ATA/ATAController.h> | ||||
| 
 | ||||
| #include <lai/helpers/pci.h> | ||||
| 
 | ||||
| #define INVALID_VENDOR 0xFFFF | ||||
| #define MULTI_FUNCTION 0x80 | ||||
| 
 | ||||
|  | @ -25,13 +24,22 @@ | |||
| #define PCI_CMD_BUS_MASTER (1 << 2) | ||||
| #define PCI_CMD_INTERRUPT_DISABLE (1 << 10) | ||||
| 
 | ||||
| #define DEBUG_PCI 1 | ||||
| #define DEBUG_PCI 0 | ||||
| 
 | ||||
| namespace Kernel::PCI | ||||
| { | ||||
| 
 | ||||
| 	static PCIManager* s_instance = nullptr; | ||||
| 
 | ||||
| 	struct MSIXEntry | ||||
| 	{ | ||||
| 		uint32_t msg_addr_low; | ||||
| 		uint32_t msg_addr_high; | ||||
| 		uint32_t msg_data; | ||||
| 		uint32_t vector_ctrl; | ||||
| 	}; | ||||
| 	static_assert(sizeof(MSIXEntry) == 16); | ||||
| 
 | ||||
| 	uint32_t PCIManager::read_config_dword(uint8_t bus, uint8_t dev, uint8_t func, uint8_t offset) | ||||
| 	{ | ||||
| 		ASSERT(offset % 4 == 0); | ||||
|  | @ -421,38 +429,147 @@ namespace Kernel::PCI | |||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	BAN::ErrorOr<uint8_t> PCI::Device::get_irq() | ||||
| 	BAN::ErrorOr<void> PCI::Device::reserve_irqs(uint8_t count) | ||||
| 	{ | ||||
| 		if (m_offset_msi_x.has_value()) | ||||
| 		{ | ||||
| 			uint16_t msg_ctrl = read_word(*m_offset_msi_x + 0x02); | ||||
| 			if (count > (msg_ctrl & 0x7FF) + 1) | ||||
| 			{ | ||||
| 				dwarnln("MSI-X: could not allocate {} interrupts, only {} supported", count, (msg_ctrl & 0x7FF) + 1); | ||||
| 				return BAN::Error::from_errno(EFAULT); | ||||
| 			} | ||||
| 			msg_ctrl |= 1 << 15; // Enable
 | ||||
| 			write_word(*m_offset_msi_x + 0x02, msg_ctrl); | ||||
| 			disable_pin_interrupts(); | ||||
| 		} | ||||
| 		else if (m_offset_msi.has_value()) | ||||
| 		{ | ||||
| 			if (count > 1) | ||||
| 			{ | ||||
| 				dwarnln("MSI: could not allocate {} interrupts, (currently) only {} supported", count, 1); | ||||
| 				return BAN::Error::from_errno(EFAULT); | ||||
| 			} | ||||
| 			uint16_t msg_ctrl = read_word(*m_offset_msi + 0x02); | ||||
| 			msg_ctrl &= ~(0x07 << 4);	// Only one interrupt
 | ||||
| 			msg_ctrl |= 1u << 0;		// Enable
 | ||||
| 			write_word(*m_offset_msi + 0x02, msg_ctrl); | ||||
| 			disable_pin_interrupts(); | ||||
| 		} | ||||
| 		else if (!InterruptController::get().is_using_apic()) | ||||
| 		{ | ||||
| 			if (count > 1) | ||||
| 			{ | ||||
| 				dwarnln("PIC: could not allocate {} interrupts, (currently) only {} supported", count, 1); | ||||
| 				return BAN::Error::from_errno(EFAULT); | ||||
| 			} | ||||
| 			enable_pin_interrupts(); | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			ASSERT_NOT_REACHED(); | ||||
| 		} | ||||
| 
 | ||||
| 		for (; m_reserved_irq_count < count; m_reserved_irq_count++) | ||||
| 		{ | ||||
| 			auto irq = InterruptController::get().get_free_irq(); | ||||
| 			if (!irq.has_value()) | ||||
| 			{ | ||||
| 				dwarnln("Could not reserve interrupt for PCI {}:{}.{}", m_bus, m_dev, m_func); | ||||
| 				return BAN::Error::from_errno(EFAULT); | ||||
| 			} | ||||
| 
 | ||||
| 			ASSERT(*irq < 32); | ||||
| 			ASSERT(!(m_reserved_irqs & (1 << *irq))); | ||||
| 			m_reserved_irqs |= 1 << *irq; | ||||
| 		} | ||||
| 
 | ||||
| 		return {}; | ||||
| 	} | ||||
| 
 | ||||
| 	static uint64_t msi_message_address() | ||||
| 	{ | ||||
| 		return 0xFEE00000; | ||||
| 	} | ||||
| 
 | ||||
| 	static uint32_t msi_message_data(uint8_t irq) | ||||
| 	{ | ||||
| 		return (IRQ_VECTOR_BASE + irq) & 0xFF; | ||||
| 	} | ||||
| 
 | ||||
| 	uint8_t PCI::Device::get_irq(uint8_t index) | ||||
| 	{ | ||||
| 		ASSERT(m_offset_msi.has_value() || m_offset_msi_x.has_value() || !InterruptController::get().is_using_apic()); | ||||
| 		ASSERT(index < m_reserved_irq_count); | ||||
| 
 | ||||
| 		uint8_t count_found = 0; | ||||
| 		uint8_t irq = 0xFF; | ||||
| 		for (uint8_t i = 0; i < 32; i++) | ||||
| 		{ | ||||
| 			if (m_reserved_irqs & (1 << i)) | ||||
| 				count_found++; | ||||
| 			if (count_found > index) | ||||
| 			{ | ||||
| 				irq = i; | ||||
| 				break; | ||||
| 			} | ||||
| 		} | ||||
| 		ASSERT(irq != 0xFF); | ||||
| 
 | ||||
| 		// Legacy PIC just uses the interrupt line field
 | ||||
| 		if (!InterruptController::get().is_using_apic()) | ||||
| 			return read_byte(PCI_REG_IRQ_LINE); | ||||
| 		 | ||||
| 		// TODO: use MSI and MSI-X if supported
 | ||||
| 
 | ||||
| 		if (m_offset_msi.has_value()) | ||||
| 		{ | ||||
| 			write_byte(PCI_REG_IRQ_LINE, irq); | ||||
| 			return irq; | ||||
| 		} | ||||
| 
 | ||||
| 		if (m_offset_msi_x.has_value()) | ||||
| 		{ | ||||
| 			uint32_t dword0 = read_dword(*m_offset_msi_x); | ||||
| 			ASSERT((dword0 & 0xFF) == 0x11); | ||||
| 
 | ||||
| 			uint32_t dword1 = read_dword(*m_offset_msi_x + 0x04); | ||||
| 			uint32_t offset = dword1 & ~3u; | ||||
| 			uint8_t  bir    = dword1 &  3u; | ||||
| 
 | ||||
| 			uint64_t msg_addr = msi_message_address(); | ||||
| 			uint32_t msg_data = msi_message_data(irq); | ||||
| 
 | ||||
| 			auto bar = MUST(allocate_bar_region(bir)); | ||||
| 			ASSERT(bar->type() == BarType::MEM); | ||||
| 			auto& msi_x_entry = reinterpret_cast<volatile MSIXEntry*>(bar->vaddr() + offset)[index]; | ||||
| 			msi_x_entry.msg_addr_low  = msg_addr & 0xFFFFFFFF; | ||||
| 			msi_x_entry.msg_addr_high = msg_addr >> 32;; | ||||
| 			msi_x_entry.msg_data      = msg_data; | ||||
| 			msi_x_entry.vector_ctrl   = msi_x_entry.vector_ctrl & ~1u; | ||||
| 
 | ||||
| 			return irq; | ||||
| 		} | ||||
| 
 | ||||
| 		for (uint8_t irq_pin = 1; irq_pin <= 4; irq_pin++) | ||||
| 		if (m_offset_msi.has_value()) | ||||
| 		{ | ||||
| 			acpi_resource_t dest; | ||||
| 			auto err = lai_pci_route_pin(&dest, 0, m_bus, m_dev, m_func, irq_pin); | ||||
| 			if (err != LAI_ERROR_NONE) | ||||
| 			uint32_t dword0 = read_dword(*m_offset_msi); | ||||
| 			ASSERT((dword0 & 0xFF) == 0x05); | ||||
| 
 | ||||
| 			uint64_t msg_addr = msi_message_address(); | ||||
| 			uint32_t msg_data = msi_message_data(irq); | ||||
| 
 | ||||
| 			if (dword0 & (1 << 23)) | ||||
| 			{ | ||||
| 				dprintln("{}", lai_api_error_to_string(err)); | ||||
| 				continue; | ||||
| 				write_dword(*m_offset_msi + 0x04, msg_addr & 0xFFFFFFFF); | ||||
| 				write_dword(*m_offset_msi + 0x08, msg_addr >> 32); | ||||
| 				write_word(*m_offset_msi  + 0x12, msg_data); | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				write_dword(*m_offset_msi + 0x04, msg_addr & 0xFFFFFFFF); | ||||
| 				write_word(*m_offset_msi  + 0x08, msg_data); | ||||
| 			} | ||||
| 
 | ||||
| 			write_byte(PCI_REG_IRQ_PIN, irq_pin); | ||||
| 			return dest.base; | ||||
| 			return irq; | ||||
| 		} | ||||
| 
 | ||||
| 		dwarnln("Could not allocate interrupt for PCI {}:{}.{}", m_bus, m_dev, m_func); | ||||
| 		return BAN::Error::from_errno(ENOTSUP); | ||||
| 		ASSERT_NOT_REACHED(); | ||||
| 	} | ||||
| 
 | ||||
| 	void PCI::Device::set_command_bits(uint16_t mask) | ||||
|  |  | |||
|  | @ -1,3 +1,4 @@ | |||
| #include <kernel/CriticalScope.h> | ||||
| #include <kernel/IDT.h> | ||||
| #include <kernel/IO.h> | ||||
| #include <kernel/PIC.h> | ||||
|  | @ -70,6 +71,7 @@ namespace Kernel | |||
| 
 | ||||
| 	void PIC::eoi(uint8_t irq) | ||||
| 	{ | ||||
| 		ASSERT(!interrupts_enabled()); | ||||
| 		if (irq >= 8) | ||||
| 			IO::outb(PIC2_CMD, PIC_EOI); | ||||
| 		IO::outb(PIC1_CMD, PIC_EOI); | ||||
|  | @ -77,6 +79,10 @@ namespace Kernel | |||
| 
 | ||||
| 	void PIC::enable_irq(uint8_t irq) | ||||
| 	{ | ||||
| 		CriticalScope _; | ||||
| 		ASSERT(irq < 16); | ||||
| 		ASSERT(m_reserved_irqs & (1 << irq)); | ||||
| 
 | ||||
| 		uint16_t port = PIC1_DATA; | ||||
| 		if(irq >= 8) | ||||
| 		{ | ||||
|  | @ -86,6 +92,37 @@ namespace Kernel | |||
| 		IO::outb(port, IO::inb(port) & ~(1 << irq)); | ||||
| 	} | ||||
| 
 | ||||
| 	BAN::ErrorOr<void> PIC::reserve_irq(uint8_t irq) | ||||
| 	{ | ||||
| 		if (irq >= 16) | ||||
| 		{ | ||||
| 			dwarnln("PIC only supports 16 irqs"); | ||||
| 			return BAN::Error::from_errno(EFAULT); | ||||
| 		} | ||||
| 		CriticalScope _; | ||||
| 		if (m_reserved_irqs & (1 << irq)) | ||||
| 		{ | ||||
| 			dwarnln("irq {} is already reserved", irq); | ||||
| 			return BAN::Error::from_errno(EFAULT); | ||||
| 		} | ||||
| 		m_reserved_irqs |= 1 << irq; | ||||
| 		return {}; | ||||
| 	} | ||||
| 
 | ||||
| 	BAN::Optional<uint8_t> PIC::get_free_irq() | ||||
| 	{ | ||||
| 		CriticalScope _; | ||||
| 		for (int irq = 0; irq < 16; irq++) | ||||
| 		{ | ||||
| 			if (m_reserved_irqs & (1 << irq)) | ||||
| 				continue; | ||||
| 			m_reserved_irqs |= 1 << irq; | ||||
| 			return irq; | ||||
| 		} | ||||
| 		 | ||||
| 		return {}; | ||||
| 	} | ||||
| 
 | ||||
| 	bool PIC::is_in_service(uint8_t irq) | ||||
| 	{ | ||||
| 		uint16_t port = PIC1_CMD; | ||||
|  |  | |||
|  | @ -25,8 +25,8 @@ namespace Kernel | |||
| 
 | ||||
| 		// Enable interrupts and bus mastering
 | ||||
| 		m_pci_device.enable_bus_mastering(); | ||||
| 		m_pci_device.enable_pin_interrupts(); | ||||
| 		set_irq(TRY(m_pci_device.get_irq())); | ||||
| 		TRY(m_pci_device.reserve_irqs(1)); | ||||
| 		set_irq(m_pci_device.get_irq(0)); | ||||
| 		enable_interrupt(); | ||||
| 		abar_mem.ghc = abar_mem.ghc | SATA_GHC_INTERRUPT_ENABLE; | ||||
| 
 | ||||
|  |  | |||
|  | @ -21,8 +21,6 @@ namespace Kernel | |||
| 		auto bus = BAN::RefPtr<ATABus>::adopt(bus_ptr); | ||||
| 		bus->set_irq(irq); | ||||
| 		TRY(bus->initialize()); | ||||
| 		if (bus->m_devices.empty()) | ||||
| 			return BAN::Error::from_errno(ENODEV); | ||||
| 		return bus; | ||||
| 	} | ||||
| 
 | ||||
|  |  | |||
|  | @ -41,6 +41,8 @@ namespace Kernel | |||
| 
 | ||||
| 		uint8_t prog_if = m_pci_device.read_byte(0x09); | ||||
| 
 | ||||
| 		// FIXME: support native mode
 | ||||
| 
 | ||||
| 		if ((prog_if & ATA_PROGIF_CAN_MODIFY_PRIMARY_NATIVE) && (prog_if & ATA_PROGIF_PRIMARY_NATIVE)) | ||||
| 		{ | ||||
| 			prog_if &= ~ATA_PROGIF_PRIMARY_NATIVE; | ||||
|  | @ -57,11 +59,16 @@ namespace Kernel | |||
| 
 | ||||
| 		if (!(prog_if & ATA_PROGIF_PRIMARY_NATIVE)) | ||||
| 		{ | ||||
| 			auto bus_or_error = ATABus::create(0x1F0, 0x3F6, 14); | ||||
| 			if (bus_or_error.is_error()) | ||||
| 				dprintln("IDE ATABus: {}", bus_or_error.error()); | ||||
| 			if (InterruptController::get().reserve_irq(14).is_error()) | ||||
| 				dwarnln("Could not reserve interrupt {} for ATA device", 14); | ||||
| 			else | ||||
| 				TRY(buses.push_back(bus_or_error.release_value())); | ||||
| 			{ | ||||
| 				auto bus_or_error = ATABus::create(0x1F0, 0x3F6, 14); | ||||
| 				if (bus_or_error.is_error()) | ||||
| 					dprintln("IDE ATABus: {}", bus_or_error.error()); | ||||
| 				else | ||||
| 					TRY(buses.push_back(bus_or_error.release_value())); | ||||
| 			} | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
|  | @ -70,11 +77,16 @@ namespace Kernel | |||
| 
 | ||||
| 		if (!(prog_if & ATA_PROGIF_SECONDARY_NATIVE)) | ||||
| 		{ | ||||
| 			auto bus_or_error = ATABus::create(0x170, 0x376, 15); | ||||
| 			if (bus_or_error.is_error()) | ||||
| 				dprintln("IDE ATABus: {}", bus_or_error.error()); | ||||
| 			if (InterruptController::get().reserve_irq(15).is_error()) | ||||
| 				dwarnln("Could not reserver interrupt {} for ATA device", 15); | ||||
| 			else | ||||
| 				TRY(buses.push_back(bus_or_error.release_value())); | ||||
| 			{ | ||||
| 				auto bus_or_error = ATABus::create(0x170, 0x376, 15); | ||||
| 				if (bus_or_error.is_error()) | ||||
| 					dprintln("IDE ATABus: {}", bus_or_error.error()); | ||||
| 				else | ||||
| 					TRY(buses.push_back(bus_or_error.release_value())); | ||||
| 			} | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
|  |  | |||
|  | @ -195,12 +195,14 @@ namespace Kernel | |||
| 		if (serial.port() == COM1_PORT) | ||||
| 		{ | ||||
| 			IO::outb(COM1_PORT + 1, 1); | ||||
| 			TRY(InterruptController::get().reserve_irq(COM1_IRQ)); | ||||
| 			tty->set_irq(COM1_IRQ); | ||||
| 			tty->enable_interrupt(); | ||||
| 		} | ||||
| 		else if (serial.port() == COM2_PORT) | ||||
| 		{ | ||||
| 			IO::outb(COM2_PORT + 1, 1); | ||||
| 			TRY(InterruptController::get().reserve_irq(COM2_IRQ)); | ||||
| 			tty->set_irq(COM2_IRQ); | ||||
| 			tty->enable_interrupt(); | ||||
| 		} | ||||
|  |  | |||
|  | @ -105,6 +105,7 @@ namespace Kernel | |||
| 				if (irq_cap & (1 << irq)) | ||||
| 					break; | ||||
| 		} | ||||
| 		TRY(InterruptController::get().reserve_irq(irq)); | ||||
| 
 | ||||
| 		unmapper.disable(); | ||||
| 
 | ||||
|  |  | |||
|  | @ -182,17 +182,19 @@ static void init2(void*) | |||
| 	SystemTimer::get().sleep(5000); | ||||
| #endif | ||||
| 
 | ||||
| 	// Initialize empty keymap
 | ||||
| 	MUST(Input::KeyboardLayout::initialize()); | ||||
| 	if (auto res = PS2Controller::initialize(); res.is_error()) | ||||
| 		dprintln("{}", res.error()); | ||||
| 
 | ||||
| 	// NOTE: PCI devices are the last ones to be initialized
 | ||||
| 	//       so other devices can reserve predefined interrupts
 | ||||
| 	PCI::PCIManager::initialize(); | ||||
| 	dprintln("PCI initialized"); | ||||
| 
 | ||||
| 	VirtualFileSystem::initialize(cmdline.root); | ||||
| 	dprintln("VFS initialized"); | ||||
| 
 | ||||
| 	// Initialize empty keymap
 | ||||
| 	MUST(Input::KeyboardLayout::initialize()); | ||||
| 	if (auto res = PS2Controller::initialize(); res.is_error()) | ||||
| 		dprintln("{}", res.error()); | ||||
| 
 | ||||
| 	TTY::initialize_devices(); | ||||
| 
 | ||||
| 	MUST(Process::create_userspace({ 0, 0, 0, 0 }, "/usr/bin/init"sv)); | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue