forked from Bananymous/banan-os
				
			Kernel: PCIDevice is now class with getters and constructor
This commit is contained in:
		
							parent
							
								
									b4ce438ca7
								
							
						
					
					
						commit
						a9acf1f6dc
					
				| 
						 | 
					@ -8,22 +8,35 @@ namespace Kernel
 | 
				
			||||||
	class PCIDevice
 | 
						class PCIDevice
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
	public:
 | 
						public:
 | 
				
			||||||
		const uint8_t bus;
 | 
							PCIDevice(uint8_t, uint8_t, uint8_t);
 | 
				
			||||||
		const uint8_t dev;
 | 
					 | 
				
			||||||
		const uint8_t func;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		const uint8_t class_code;
 | 
					 | 
				
			||||||
		const uint8_t subclass;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		uint32_t read_dword(uint8_t) const;
 | 
							uint32_t read_dword(uint8_t) const;
 | 
				
			||||||
		uint16_t read_word(uint8_t) const;
 | 
							uint16_t read_word(uint8_t) const;
 | 
				
			||||||
		uint8_t  read_byte(uint8_t) const;
 | 
							uint8_t  read_byte(uint8_t) const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							uint8_t bus() const { return m_bus; }
 | 
				
			||||||
 | 
							uint8_t dev() const { return m_dev; }
 | 
				
			||||||
 | 
							uint8_t func() const { return m_func; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							uint8_t class_code() const { return m_class_code; }
 | 
				
			||||||
 | 
							uint8_t subclass() const { return m_subclass; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						private:
 | 
				
			||||||
 | 
							uint8_t m_bus;
 | 
				
			||||||
 | 
							uint8_t m_dev;
 | 
				
			||||||
 | 
							uint8_t m_func;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							uint8_t m_class_code;
 | 
				
			||||||
 | 
							uint8_t m_subclass;
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	class PCI
 | 
						class PCI
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
 | 
							BAN_NON_COPYABLE(PCI);
 | 
				
			||||||
 | 
							BAN_NON_MOVABLE(PCI);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public:
 | 
						public:
 | 
				
			||||||
		static bool initialize();
 | 
							static void initialize();
 | 
				
			||||||
		static PCI& get();
 | 
							static PCI& get();
 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
		const BAN::Vector<PCIDevice>& devices() const { return m_devices; }
 | 
							const BAN::Vector<PCIDevice>& devices() const { return m_devices; }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -35,10 +35,10 @@ namespace Kernel
 | 
				
			||||||
		// Initialize all storage controllers
 | 
							// Initialize all storage controllers
 | 
				
			||||||
		for (auto& device : PCI::get().devices())
 | 
							for (auto& device : PCI::get().devices())
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			if (device.class_code != 0x01)
 | 
								if (device.class_code() != 0x01)
 | 
				
			||||||
				continue;
 | 
									continue;
 | 
				
			||||||
			
 | 
								
 | 
				
			||||||
			switch (device.subclass)
 | 
								switch (device.subclass())
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				case 0x0:
 | 
									case 0x0:
 | 
				
			||||||
					dwarnln("unsupported SCSI Bus Controller");
 | 
										dwarnln("unsupported SCSI Bus Controller");
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,4 +1,3 @@
 | 
				
			||||||
#include <kernel/Debug.h>
 | 
					 | 
				
			||||||
#include <kernel/IO.h>
 | 
					#include <kernel/IO.h>
 | 
				
			||||||
#include <kernel/PCI.h>
 | 
					#include <kernel/PCI.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -11,15 +10,14 @@
 | 
				
			||||||
namespace Kernel
 | 
					namespace Kernel
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	PCI* s_instance = nullptr;
 | 
						static PCI* s_instance = nullptr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool PCI::initialize()
 | 
						void PCI::initialize()
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		ASSERT(s_instance == nullptr);
 | 
							ASSERT(s_instance == nullptr);
 | 
				
			||||||
		s_instance = new PCI();
 | 
							s_instance = new PCI();
 | 
				
			||||||
		ASSERT(s_instance);
 | 
							ASSERT(s_instance);
 | 
				
			||||||
		s_instance->check_all_buses();
 | 
							s_instance->check_all_buses();
 | 
				
			||||||
		return !s_instance->m_devices.empty();
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	PCI& PCI::get()
 | 
						PCI& PCI::get()
 | 
				
			||||||
| 
						 | 
					@ -49,32 +47,23 @@ namespace Kernel
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void PCI::check_function(uint8_t bus, uint8_t dev, uint8_t func)
 | 
						void PCI::check_function(uint8_t bus, uint8_t dev, uint8_t func)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		uint32_t type = read_config_dword(bus, dev, func, 0x08);
 | 
							MUST(m_devices.emplace_back(bus, dev, func));
 | 
				
			||||||
		PCIDevice device {
 | 
							auto& device = m_devices.back();
 | 
				
			||||||
			bus,
 | 
							if (device.class_code() == 0x06 && device.subclass() == 0x04)
 | 
				
			||||||
			dev,
 | 
								check_bus(device.read_byte(0x19));
 | 
				
			||||||
			func,
 | 
					 | 
				
			||||||
			(uint8_t)(type >> 24),
 | 
					 | 
				
			||||||
			(uint8_t)(type >> 16),
 | 
					 | 
				
			||||||
		};
 | 
					 | 
				
			||||||
		MUST(m_devices.push_back(BAN::move(device)));
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void PCI::check_device(uint8_t bus, uint8_t dev)
 | 
						void PCI::check_device(uint8_t bus, uint8_t dev)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		if (get_vendor_id(bus, dev, 0) == INVALID)
 | 
							if (get_vendor_id(bus, dev, 0) == INVALID)
 | 
				
			||||||
			return;
 | 
								return;
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							check_function(bus, dev, 0);
 | 
				
			||||||
		if (get_header_type(bus, dev, 0) & MULTI_FUNCTION)
 | 
							if (get_header_type(bus, dev, 0) & MULTI_FUNCTION)
 | 
				
			||||||
		{
 | 
								for (uint8_t func = 1; func < 8; func++)
 | 
				
			||||||
			for (uint8_t func = 0; func < 8; func++)
 | 
					 | 
				
			||||||
				if (get_vendor_id(bus, dev, func) != INVALID)
 | 
									if (get_vendor_id(bus, dev, func) != INVALID)
 | 
				
			||||||
					check_function(bus, dev, func);
 | 
										check_function(bus, dev, func);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
		else
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			check_function(bus, dev, 0);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void PCI::check_bus(uint8_t bus)
 | 
						void PCI::check_bus(uint8_t bus)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
| 
						 | 
					@ -86,8 +75,7 @@ namespace Kernel
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		if (get_header_type(0, 0, 0) & MULTI_FUNCTION)
 | 
							if (get_header_type(0, 0, 0) & MULTI_FUNCTION)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			for (int func = 0; func < 8; func++)
 | 
								for (int func = 0; func < 8 && get_vendor_id(0, 0, func) != INVALID; func++)
 | 
				
			||||||
				if (get_vendor_id(0, 0, func) != INVALID)
 | 
					 | 
				
			||||||
				check_bus(func);
 | 
									check_bus(func);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		else
 | 
							else
 | 
				
			||||||
| 
						 | 
					@ -96,23 +84,31 @@ namespace Kernel
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						PCIDevice::PCIDevice(uint8_t bus, uint8_t dev, uint8_t func)
 | 
				
			||||||
 | 
							: m_bus(bus), m_dev(dev), m_func(func)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							uint32_t type = read_word(0x0A);
 | 
				
			||||||
 | 
							m_class_code  = (uint8_t)(type >> 8);
 | 
				
			||||||
 | 
							m_subclass    = (uint8_t)(type);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	uint32_t PCIDevice::read_dword(uint8_t offset) const
 | 
						uint32_t PCIDevice::read_dword(uint8_t offset) const
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		ASSERT((offset & 0x03) == 0);
 | 
							ASSERT((offset & 0x03) == 0);
 | 
				
			||||||
		return read_config_dword(bus, dev, func, offset);
 | 
							return read_config_dword(m_bus, m_dev, m_func, offset);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	uint16_t PCIDevice::read_word(uint8_t offset) const
 | 
						uint16_t PCIDevice::read_word(uint8_t offset) const
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		ASSERT((offset & 0x01) == 0);
 | 
							ASSERT((offset & 0x01) == 0);
 | 
				
			||||||
		uint32_t dword = read_config_dword(bus, dev, func, offset & 0xFC);
 | 
							uint32_t dword = read_config_dword(m_bus, m_dev, m_func, offset & 0xFC);
 | 
				
			||||||
		return (uint16_t)(dword >> (offset & 0x03));
 | 
							return (uint16_t)(dword >> (8 * (offset & 0x03)));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	uint8_t PCIDevice::read_byte(uint8_t offset) const
 | 
						uint8_t PCIDevice::read_byte(uint8_t offset) const
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		uint32_t dword = read_config_dword(bus, dev, func, offset & 0xFC);
 | 
							uint32_t dword = read_config_dword(m_bus, m_dev, m_func, offset & 0xFC);
 | 
				
			||||||
		return (uint8_t)(dword >> (offset & 0x03));
 | 
							return (uint8_t)(dword >> (8 * (offset & 0x03)));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -254,6 +254,13 @@ argument_done:
 | 
				
			||||||
			IO::outb(0x64, 0xFE);
 | 
								IO::outb(0x64, 0xFE);
 | 
				
			||||||
			asm volatile("cli; hlt");
 | 
								asm volatile("cli; hlt");
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							else if (arguments.front() == "lspci")
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								if (arguments.size() != 1)
 | 
				
			||||||
 | 
									return TTY_PRINTLN("'lspci' does not support command line arguments");
 | 
				
			||||||
 | 
								for (auto& device : PCI::get().devices())
 | 
				
			||||||
 | 
									TTY_PRINTLN("{2H}:{2H}.{2H} {2H}", device.bus(), device.dev(), device.func(), device.class_code());
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		else if (arguments.front() == "ls")
 | 
							else if (arguments.front() == "ls")
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			if (!VirtualFileSystem::is_initialized())
 | 
								if (!VirtualFileSystem::is_initialized())
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -86,6 +86,9 @@ extern "C" void kernel_main()
 | 
				
			||||||
	MMU::intialize();
 | 
						MMU::intialize();
 | 
				
			||||||
	dprintln("MMU initialized");
 | 
						dprintln("MMU initialized");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						PCI::initialize();
 | 
				
			||||||
 | 
						dprintln("PCI initialized");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	TerminalDriver* terminal_driver = VesaTerminalDriver::create();
 | 
						TerminalDriver* terminal_driver = VesaTerminalDriver::create();
 | 
				
			||||||
	ASSERT(terminal_driver);
 | 
						ASSERT(terminal_driver);
 | 
				
			||||||
	dprintln("VESA initialized");
 | 
						dprintln("VESA initialized");
 | 
				
			||||||
| 
						 | 
					@ -97,10 +100,6 @@ extern "C" void kernel_main()
 | 
				
			||||||
	PIT::initialize();
 | 
						PIT::initialize();
 | 
				
			||||||
	dprintln("PIT initialized");
 | 
						dprintln("PIT initialized");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!PCI::initialize())
 | 
					 | 
				
			||||||
		Kernel::panic("Could not initialize PCI");
 | 
					 | 
				
			||||||
	dprintln("PCI initialized");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (!Input::initialize())
 | 
						if (!Input::initialize())
 | 
				
			||||||
		dprintln("Could not initialize input drivers");
 | 
							dprintln("Could not initialize input drivers");
 | 
				
			||||||
	dprintln("Input initialized");
 | 
						dprintln("Input initialized");
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue