summaryrefslogtreecommitdiffhomepage
path: root/Private/HALKit/AMD64/PCI/Device.cpp
blob: f8b5f62902e133025dd4e623611a75d3914d4d11 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
/*
 *	========================================================
 *
 *	hCore
 * 	Copyright 2024 Mahrouss Logic, all rights reserved.
 *
 * 	========================================================
 */

#include <ArchKit/Arch.hpp>
#include <KernelKit/PCI/Device.hpp>


hCore::UInt LumiaPCIReadRaw(hCore::UInt bar, hCore::UShort bus, hCore::UShort dev, hCore::UShort fun)
{
    hCore::UInt target = 0x80000000 | ((hCore::UInt) bus << 16) | ((hCore::UInt) dev << 11) | ((hCore::UInt) fun << 8) |
                  (bar & 0xFC);

    hCore::HAL::out32((hCore::UShort) hCore::PCI::PciConfigKind::ConfigAddress, target);

    return hCore::HAL::in32((hCore::UShort) hCore::PCI::PciConfigKind::ConfigData);
}

void LumiaPCISetCfgTarget(hCore::UInt bar, hCore::UShort bus, hCore::UShort dev, hCore::UShort fun)
{
    hCore::UInt target =
            0x80000000 | ((hCore::UInt) bus << 16) | ((hCore::UInt) dev << 11) | ((hCore::UInt) fun << 8) | (bar & ~3);

    hCore::HAL::out32((hCore::UShort) hCore::PCI::PciConfigKind::ConfigAddress, target);
}

namespace hCore::PCI
{
    Device::Device(UShort bus, UShort device, UShort func, UShort bar)
            : m_Bus(bus), m_Device(device), m_Function(func), m_Bar(bar)
    {}

    Device::~Device() {}

    UInt Device::Read(UInt bar, Size sz)
    {
        LumiaPCISetCfgTarget(bar, m_Bus, m_Device, m_Function);

        if (sz == 4)
            return HAL::in32((UShort) PciConfigKind::ConfigData + (m_Bar & 3));
        if (sz == 2)
            return HAL::in16((UShort) PciConfigKind::ConfigData + (m_Bar & 3));
        if (sz == 1)
            return HAL::in8((UShort) PciConfigKind::ConfigData + (m_Bar & 3));

        return 0xFFFF;
    }

    void Device::Write(UInt bar, UIntPtr data, Size sz)
    {
        LumiaPCISetCfgTarget(bar, m_Bus, m_Device, m_Function);

        if (sz == 4)
            HAL::out32((UShort) PciConfigKind::ConfigData + (m_Bar & 3), (UInt) data);
        if (sz == 2)
            HAL::out16((UShort) PciConfigKind::ConfigData + (m_Bar & 3), (UShort) data);
        if (sz == 1)
            HAL::out8((UShort) PciConfigKind::ConfigData + (m_Bar & 3), (UChar) data);
    }

    UShort Device::DeviceId()
    {
        return (UShort)(LumiaPCIReadRaw(0x0 >> 16, m_Bus, m_Device, m_Function));
    }

    UShort Device::VendorId()
    {
        return (UShort) (LumiaPCIReadRaw(0x0, m_Bus, m_Device, m_Function) >> 16);
    }

    UShort Device::InterfaceId()
    {
        return (UShort)(LumiaPCIReadRaw(0x0, m_Bus, m_Device, m_Function) >> 16);
    }

    UChar Device::Class()
    {
        return (UChar)(LumiaPCIReadRaw(0x08, m_Bus, m_Device, m_Function) >> 24);
    }

    UChar Device::Subclass()
    {
        return (UChar)(LumiaPCIReadRaw(0x08, m_Bus, m_Device, m_Function) >> 16);
    }

    UChar Device::ProgIf()
    {
        return (UChar)(LumiaPCIReadRaw(0x08, m_Bus, m_Device, m_Function) >> 8);
    }

    UChar Device::HeaderType()
    {
        return (UChar)(LumiaPCIReadRaw(0xC, m_Bus, m_Device, m_Function) >> 16);
    }

    void Device::EnableMmio()
    {
        bool enable = Read(0x04, sizeof(UChar)) | (1 << 1);
        Write(0x04, enable, sizeof(UShort));
    }

    void Device::BecomeBusMaster()
    {
        bool enable = Read(0x04, sizeof(UShort)) | (1 << 2);
        Write(0x04, enable, sizeof(UShort));
    }

    UShort Device::Vendor()
    {
        UShort vendor = VendorId();

        if (vendor != (UShort) PciConfigKind::Invalid)
            m_Device = (UShort) Read(0x0, sizeof(UShort));

        return m_Device;
    }

    Device::operator bool()
    {
        return VendorId() != (UShort) PciConfigKind::Invalid;
    }
} // namespace hCore::PCI