summaryrefslogtreecommitdiffhomepage
path: root/dev/Kernel/HALKit/AMD64/PCI/Device.cc
blob: 3c3e99ecad2bd2e629fa30473ae78d3230a17934 (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
128
129
130
131
132
133
134
135
136
137
138
139
/* -------------------------------------------

	Copyright (C) 2024, Theater Quality Corp, all rights reserved.

------------------------------------------- */

#include <ArchKit/ArchKit.h>
#include <KernelKit/PCI/Device.h>

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

	Kernel::HAL::rt_out32((Kernel::UShort)Kernel::PCI::PciConfigKind::ConfigAddress,
						  target);

	return Kernel::HAL::rt_in32((Kernel::UShort)Kernel::PCI::PciConfigKind::ConfigData);
}

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

	Kernel::HAL::rt_out32((Kernel::UShort)Kernel::PCI::PciConfigKind::ConfigAddress,
						  target);
}

#define PCI_BAR_IO		 0x01
#define PCI_BAR_LOWMEM	 0x02
#define PCI_BAR_64		 0x04
#define PCI_BAR_PREFETCH 0x08

namespace Kernel::PCI
{
	Device::Device(UShort bus, UShort device, UShort func, UInt32 bar)
		: fBus(bus), fDevice(device), fFunction(func), fBar(bar)
	{
	}

	Device::~Device() = default;

	UInt Device::Read(UInt bar, Size sz)
	{
		ZKA_PCISetCfgTarget(bar, fBus, fDevice, fFunction);

		if (sz == 4)
			return HAL::rt_in32((UShort)PciConfigKind::ConfigData + (bar & 3));
		if (sz == 2)
			return HAL::rt_in16((UShort)PciConfigKind::ConfigData + (bar & 3));
		if (sz == 1)
			return HAL::rt_in8((UShort)PciConfigKind::ConfigData + (bar & 3));

		return 0xFFFF;
	}

	void Device::Write(UInt bar, UIntPtr data, Size sz)
	{
		ZKA_PCISetCfgTarget(bar, fBus, fDevice, fFunction);

		if (sz == 4)
			HAL::rt_out32((UShort)PciConfigKind::ConfigData + (fBar & 3), (UInt)data);
		if (sz == 2)
			HAL::rt_out16((UShort)PciConfigKind::ConfigData + (fBar & 3), (UShort)data);
		if (sz == 1)
			HAL::rt_out8((UShort)PciConfigKind::ConfigData + (fBar & 3), (UChar)data);
	}

	UShort Device::DeviceId()
	{
		return (UShort)(ZKA_PCIReadRaw(0x0 >> 16, fBus, fDevice, fFunction));
	}

	UShort Device::VendorId()
	{
		return (UShort)(ZKA_PCIReadRaw(0x0, fBus, fDevice, fFunction) >> 16);
	}

	UShort Device::InterfaceId()
	{
		return (UShort)(ZKA_PCIReadRaw(0x0, fBus, fDevice, fFunction) >> 16);
	}

	UChar Device::Class()
	{
		return (UChar)(ZKA_PCIReadRaw(0x08, fBus, fDevice, fFunction) >> 24);
	}

	UChar Device::Subclass()
	{
		return (UChar)(ZKA_PCIReadRaw(0x08, fBus, fDevice, fFunction) >> 16);
	}

	UChar Device::ProgIf()
	{
		return (UChar)(ZKA_PCIReadRaw(0x08, fBus, fDevice, fFunction) >> 8);
	}

	UChar Device::HeaderType()
	{
		return (UChar)(ZKA_PCIReadRaw(0xC, fBus, fDevice, fFunction) >> 16);
	}

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

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

	UIntPtr Device::Bar(UInt32 bar_in)
	{
		UInt32 bar = ZKA_PCIReadRaw(bar_in, fBus, fDevice, fFunction);
		return bar;
	}

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

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

		return fDevice;
	}

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