summaryrefslogtreecommitdiffhomepage
path: root/Private/HALKit/AMD64/PCI/Device.cpp
blob: 9fdcda433b742c8a36c42cf208dbc049503dca27 (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
/*
 *	========================================================
 *
 *	HCore
 * 	Copyright 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