xaizek / tos (License: GPLv3 only) (since 2018-12-07)
This is an alternative version of sources presented as part of Write Your Own OS video tutorial by Viktor Engelmann.
<root> / src / hwcomm / PCI.hpp (786b450c4babd410733d18ab82017e5cca994b33) (2,084B) (mode 100644) [raw]
#ifndef TOS__HWCOMM__PCI_HPP__
#define TOS__HWCOMM__PCI_HPP__

#include <cstdint>

#include "hwcomm/Port.hpp"
#include "hwcomm/interrupts.hpp"

namespace drv {
    class Driver;
    class DriverManager;
}

namespace hwcomm {

struct PCIDeviceAddr
{
    std::uint8_t bus;
    std::uint8_t device;
};

struct PCIFunctionAddr
{
    std::uint8_t bus;
    std::uint8_t device;
    std::uint8_t function;

    PCIFunctionAddr(std::uint8_t bus, std::uint8_t device,
                    std::uint8_t function);
    PCIFunctionAddr(PCIDeviceAddr deviceAddr, std::uint8_t function);

    std::uint32_t address(std::uint32_t offset) const;
};

enum class BARType
{
    None,
    MemoryMapping,
    InputOutput
};

struct BAR
{
    bool prefetchable;
    union
    {
        std::uint8_t *address;
        std::uint32_t portBase;
    };
    std::uint32_t size;
    BARType type;
};

class PCIDeviceDescr;

class PCIController
{
public:
    PCIController();

public:
    std::uint32_t read(PCIFunctionAddr functionAddr, std::uint32_t offset);
    void write(PCIFunctionAddr functionAddr, std::uint32_t offset,
               std::uint32_t value);

    void selectDrivers(drv::DriverManager &drvManager,
                       InterruptManager &interrupts);

private:
    bool deviceHasFunctions(PCIDeviceAddr deviceAddr);
    BAR readBAR(PCIFunctionAddr functionAddr, std::uint16_t barNum);
    // Can return `nullptr`.
    drv::Driver * getDriver(PCIDeviceDescr &dev, InterruptManager &interrupts);

private:
    Port32 cmdPort;
    Port32 dataPort;
};

class PCIDeviceDescr
{
public:
    PCIFunctionAddr functionAddr;

    std::uint32_t portBase;
    std::uint32_t interrupt;

    std::uint16_t vendorId;
    std::uint16_t deviceId;

    std::uint8_t classId;
    std::uint8_t subclassId;
    std::uint8_t interfaceId;

    std::uint8_t revision;

public:;
    explicit PCIDeviceDescr(PCIController &pciController,
                            PCIFunctionAddr functionAddr);

public:
    void enableBusMaster();

private:
    PCIController &pciController;
};

}

#endif // TOS__HWCOMM__PCI_HPP__
Hints

Before first commit, do not forget to setup your git environment:
git config --global user.name "your_name_here"
git config --global user.email "your@email_here"

Clone this repository using HTTP(S):
git clone https://code.reversed.top/user/xaizek/tos

Clone this repository using ssh (do not forget to upload a key first):
git clone ssh://rocketgit@code.reversed.top/user/xaizek/tos

You are allowed to anonymously push to this repository.
This means that your pushed commits will automatically be transformed into a pull request:
... clone the repository ...
... make some changes and some commits ...
git push origin master