summaryrefslogtreecommitdiffhomepage
path: root/dev/kernel/KernelKit/PCI
diff options
context:
space:
mode:
Diffstat (limited to 'dev/kernel/KernelKit/PCI')
-rw-r--r--dev/kernel/KernelKit/PCI/DMA.h81
-rw-r--r--dev/kernel/KernelKit/PCI/DMA.inl20
-rw-r--r--dev/kernel/KernelKit/PCI/Database.h58
-rw-r--r--dev/kernel/KernelKit/PCI/Device.h81
-rw-r--r--dev/kernel/KernelKit/PCI/Express.h12
-rw-r--r--dev/kernel/KernelKit/PCI/IO.h75
-rw-r--r--dev/kernel/KernelKit/PCI/IOArray+AMD64.inl54
-rw-r--r--dev/kernel/KernelKit/PCI/Iterator.h43
-rw-r--r--dev/kernel/KernelKit/PCI/PCI.h59
9 files changed, 483 insertions, 0 deletions
diff --git a/dev/kernel/KernelKit/PCI/DMA.h b/dev/kernel/KernelKit/PCI/DMA.h
new file mode 100644
index 00000000..68f3fa37
--- /dev/null
+++ b/dev/kernel/KernelKit/PCI/DMA.h
@@ -0,0 +1,81 @@
+/* -------------------------------------------
+
+ Copyright (C) 2024-2025, Amlal EL Mahrouss, all rights reserved.
+
+------------------------------------------- */
+
+#pragma once
+
+#include <KernelKit/DeviceMgr.h>
+#include <KernelKit/PCI/Device.h>
+#include <NewKit/Array.h>
+#include <NewKit/OwnPtr.h>
+#include <NewKit/Ref.h>
+
+namespace NeOS
+{
+ enum class DmaKind
+ {
+ PCI, // Bus mastering is required to be turned on. Basiaclly a request
+ // control system. 64-Bit access depends on the PAE bit and the device
+ // (if Double Address Cycle is available)
+ ISA, // Four DMA channels 0-3; 8 bit transfers and only a megabyte of RAM.
+ Invalid,
+ };
+
+ class DMAWrapper final
+ {
+ public:
+ explicit DMAWrapper() = delete;
+
+ public:
+ explicit DMAWrapper(nullPtr) = delete;
+ explicit DMAWrapper(voidPtr Ptr, DmaKind Kind = DmaKind::PCI)
+ : fAddress(Ptr), fKind(Kind)
+ {
+ }
+
+ public:
+ DMAWrapper& operator=(voidPtr Ptr);
+
+ public:
+ DMAWrapper& operator=(const DMAWrapper&) = default;
+ DMAWrapper(const DMAWrapper&) = default;
+
+ public:
+ ~DMAWrapper() = default;
+
+ template <class T>
+ T* operator->();
+
+ template <class T>
+ T* Get(const UIntPtr off = 0);
+
+ public:
+ operator bool();
+ bool operator!();
+
+ public:
+ bool Write(const UIntPtr& bit, const UInt32& offset);
+ UIntPtr Read(const UInt32& offset);
+ Boolean Check(UIntPtr offset) const;
+
+ public:
+ UIntPtr operator[](const UIntPtr& offset);
+
+ private:
+ voidPtr fAddress{nullptr};
+ DmaKind fKind{DmaKind::Invalid};
+
+ private:
+ friend class DMAFactory;
+ };
+
+ class DMAFactory final
+ {
+ public:
+ static OwnPtr<IOBuf<Char*>> Construct(OwnPtr<DMAWrapper>& dma);
+ };
+} // namespace NeOS
+
+#include <KernelKit/PCI/DMA.inl>
diff --git a/dev/kernel/KernelKit/PCI/DMA.inl b/dev/kernel/KernelKit/PCI/DMA.inl
new file mode 100644
index 00000000..d9c6e551
--- /dev/null
+++ b/dev/kernel/KernelKit/PCI/DMA.inl
@@ -0,0 +1,20 @@
+/* -------------------------------------------
+
+ Copyright (C) 2024-2025, Amlal EL Mahrouss, all rights reserved.
+
+------------------------------------------- */
+
+namespace NeOS
+{
+ template <class T>
+ T* DMAWrapper::operator->()
+ {
+ return this->fAddress;
+ }
+
+ template <class T>
+ T* DMAWrapper::Get(const UIntPtr offset)
+ {
+ return reinterpret_cast<T*>((UIntPtr)this->fAddress + offset);
+ }
+} // namespace NeOS
diff --git a/dev/kernel/KernelKit/PCI/Database.h b/dev/kernel/KernelKit/PCI/Database.h
new file mode 100644
index 00000000..cb12a731
--- /dev/null
+++ b/dev/kernel/KernelKit/PCI/Database.h
@@ -0,0 +1,58 @@
+/* -------------------------------------------
+
+ Copyright (C) 2024-2025, Amlal EL Mahrouss, all rights reserved.
+
+------------------------------------------- */
+#pragma once
+
+#include <KernelKit/PCI/Device.h>
+#include <NewKit/Defines.h>
+
+namespace NeOS
+{
+ namespace Types
+ {
+ // https://wiki.osdev.org/PCI
+ enum class PciDeviceKind : UChar
+ {
+ MassStorageController = 0x1,
+ NetworkController = 0x2,
+ DisplayController = 0x3,
+ MultimediaController = 0x4,
+ MemoryController = 0x5,
+ Bridge = 0x6,
+ CommunicationController = 0x7,
+ GenericSystemPeripheral = 0x8,
+ InputDeviceController = 0x9,
+ DockingStation = 0xa,
+ Processor = 0xb,
+ SerialBusController = 0xc,
+ WirelessController = 0xd,
+ IntelligentController = 0xe,
+ SatelliteCommunicationsController = 0xf,
+ CoProcessor = 0x40,
+ Unassgined = 0xf,
+ Invalid = Unassgined,
+ };
+ } // namespace Types
+} // namespace NeOS
+
+inline BOOL operator!=(const NeOS::Types::PciDeviceKind& lhs, NeOS::UChar rhs)
+{
+ return rhs != (NeOS::UChar)lhs;
+}
+
+inline BOOL operator==(const NeOS::Types::PciDeviceKind& lhs, NeOS::UChar rhs)
+{
+ return rhs == (NeOS::UChar)lhs;
+}
+
+inline BOOL operator!=(NeOS::UChar lhs, const NeOS::Types::PciDeviceKind& rhs)
+{
+ return lhs != (NeOS::UChar)rhs;
+}
+
+inline BOOL operator==(NeOS::UChar lhs, const NeOS::Types::PciDeviceKind& rhs)
+{
+ return lhs == (NeOS::UChar)rhs;
+} \ No newline at end of file
diff --git a/dev/kernel/KernelKit/PCI/Device.h b/dev/kernel/KernelKit/PCI/Device.h
new file mode 100644
index 00000000..9870f618
--- /dev/null
+++ b/dev/kernel/KernelKit/PCI/Device.h
@@ -0,0 +1,81 @@
+/* -------------------------------------------
+
+ Copyright (C) 2024-2025, Amlal EL Mahrouss, all rights reserved.
+
+------------------------------------------- */
+#pragma once
+
+#include <NewKit/Defines.h>
+
+namespace NeOS::PCI
+{
+ enum class PciConfigKind : UShort
+ {
+ ConfigAddress = 0xCF8,
+ ConfigData = 0xCFC,
+ CommandReg = 0x0004,
+ Invalid = 0xFFFF,
+ };
+
+ class Device final
+ {
+ public:
+ Device() = default;
+
+ public:
+ explicit Device(UShort bus, UShort device, UShort function, UInt32 bar);
+
+ Device& operator=(const Device&) = default;
+
+ Device(const Device&) = default;
+
+ ~Device();
+
+ public:
+ UInt Read(UInt bar, Size szData);
+ void Write(UInt bar, UIntPtr data, Size szData);
+
+ public:
+ operator bool();
+
+ public:
+ template <typename T>
+ UInt Read(UInt bar)
+ {
+ static_assert(sizeof(T) <= 4, "64-bit PCI addressing is unsupported");
+ return Read(bar, sizeof(T));
+ }
+
+ template <typename T>
+ void Write(UInt bar, UIntPtr data)
+ {
+ static_assert(sizeof(T) <= 4, "64-bit PCI addressing is unsupported");
+ Write(bar, data, sizeof(T));
+ }
+
+ public:
+ UShort DeviceId();
+ UShort VendorId();
+ UShort InterfaceId();
+ UChar Class();
+ UChar Subclass();
+ UChar ProgIf();
+ UChar HeaderType();
+ UIntPtr Bar(UInt32 bar_in);
+
+ public:
+ void EnableMmio(UInt32 bar_in);
+ void BecomeBusMaster(UInt32 bar_in); // for PCI-DMA, PC-DMA does not need that.
+
+ UShort Vendor();
+
+ private:
+ UShort fBus;
+ UShort fDevice;
+ UShort fFunction;
+ UInt32 fBar;
+ };
+} // namespace NeOS::PCI
+
+EXTERN_C void NewOSPCISetCfgTarget(NeOS::UInt bar);
+EXTERN_C NeOS::UInt NewOSPCIReadRaw(NeOS::UInt bar);
diff --git a/dev/kernel/KernelKit/PCI/Express.h b/dev/kernel/KernelKit/PCI/Express.h
new file mode 100644
index 00000000..c437a1cb
--- /dev/null
+++ b/dev/kernel/KernelKit/PCI/Express.h
@@ -0,0 +1,12 @@
+/* -------------------------------------------
+
+ Copyright (C) 2024-2025, Amlal EL Mahrouss, all rights reserved.
+
+------------------------------------------- */
+
+#pragma once
+
+#include <NewKit/Defines.h>
+#include <KernelKit/PCI/PCI.h>
+
+#define PCI_EXPRESS_BUS_COUNT (4096)
diff --git a/dev/kernel/KernelKit/PCI/IO.h b/dev/kernel/KernelKit/PCI/IO.h
new file mode 100644
index 00000000..1d60df8e
--- /dev/null
+++ b/dev/kernel/KernelKit/PCI/IO.h
@@ -0,0 +1,75 @@
+/* -------------------------------------------
+
+ Copyright (C) 2024-2025, Amlal EL Mahrouss, all rights reserved.
+
+------------------------------------------- */
+
+#pragma once
+
+#include <ArchKit/ArchKit.h>
+#include <NewKit/Array.h>
+#include <NewKit/Defines.h>
+#include <NewKit/Ref.h>
+
+namespace NeOS
+{
+ template <SizeT Sz>
+ class IOArray final
+ {
+ public:
+ IOArray() = delete;
+
+ IOArray(nullPtr) = delete;
+
+ explicit IOArray(Array<UShort, Sz>& ports)
+ : fPorts(ports)
+ {
+ }
+
+ ~IOArray()
+ {
+ }
+
+ IOArray& operator=(const IOArray&) = default;
+
+ IOArray(const IOArray&) = default;
+
+ operator bool()
+ {
+ return !fPorts.Empty();
+ }
+
+ public:
+ template <typename T>
+ T In(SizeT index);
+
+ template <typename T>
+ void Out(SizeT index, T value);
+
+ private:
+ Array<UShort, Sz> fPorts;
+ };
+
+ inline constexpr UInt16 kMaxPorts = 16;
+
+ using IOArray16 = IOArray<kMaxPorts>;
+
+ template <SizeT Sz>
+ inline Array<UShort, Sz> make_ports(UShort base)
+ {
+ Array<UShort, Sz> ports;
+
+ for (UShort i = 0; i < Sz; ++i)
+ {
+ ports[i] = base + i;
+ }
+
+ return ports;
+ }
+} // namespace NeOS
+
+#ifdef __x86_64__
+#include <KernelKit/PCI/IOArray+AMD64.inl>
+#else
+#error Please provide platform specific code for the I/O
+#endif // ifdef __x86_64__
diff --git a/dev/kernel/KernelKit/PCI/IOArray+AMD64.inl b/dev/kernel/KernelKit/PCI/IOArray+AMD64.inl
new file mode 100644
index 00000000..2630fa98
--- /dev/null
+++ b/dev/kernel/KernelKit/PCI/IOArray+AMD64.inl
@@ -0,0 +1,54 @@
+/* -------------------------------------------
+
+ Copyright (C) 2024-2025, Amlal EL Mahrouss, all rights reserved.
+
+ File: IO-Impl-AMD64.h
+ Purpose: I/O for AMD64.
+
+ Revision History:
+
+ 30/01/24: Add file. (amlel)
+ 02/02/24: Update I/O routines. (amlel)
+
+------------------------------------------- */
+
+namespace NeOS
+{
+ template <SizeT Sz>
+ template <typename T>
+ T IOArray<Sz>::In(SizeT index)
+ {
+ switch (sizeof(T))
+ {
+#ifdef __NE_AMD64__
+ case 4:
+ return HAL::rt_in32(fPorts[index].Leak());
+ case 2:
+ return HAL::rt_in16(fPorts[index].Leak());
+ case 1:
+ return HAL::rt_in8(fPorts[index].Leak());
+#endif
+ default:
+ return 0xFFFF;
+ }
+ }
+
+ template <SizeT Sz>
+ template <typename T>
+ void IOArray<Sz>::Out(SizeT index, T value)
+ {
+ switch (sizeof(T))
+ {
+#ifdef __NE_AMD64__
+ case 4:
+ HAL::rt_out32(fPorts[index].Leak(), value);
+ case 2:
+ HAL::rt_out16(fPorts[index].Leak(), value);
+ case 1:
+ HAL::rt_out8(fPorts[index].Leak(), value);
+#endif
+ default:
+ break;
+ }
+ }
+} // namespace NeOS \ No newline at end of file
diff --git a/dev/kernel/KernelKit/PCI/Iterator.h b/dev/kernel/KernelKit/PCI/Iterator.h
new file mode 100644
index 00000000..2a788450
--- /dev/null
+++ b/dev/kernel/KernelKit/PCI/Iterator.h
@@ -0,0 +1,43 @@
+/* -------------------------------------------
+
+ Copyright (C) 2024-2025, Amlal EL Mahrouss, all rights reserved.
+
+------------------------------------------- */
+
+#ifndef __PCI_ITERATOR_H__
+#define __PCI_ITERATOR_H__
+
+#include <KernelKit/PCI/Database.h>
+#include <KernelKit/PCI/Device.h>
+#include <NewKit/Array.h>
+#include <NewKit/Defines.h>
+#include <NewKit/Ref.h>
+
+#define NE_BUS_COUNT (256)
+#define NE_DEVICE_COUNT (33)
+#define NE_FUNCTION_COUNT (8)
+
+namespace NeOS::PCI
+{
+ class Iterator final
+ {
+ public:
+ Iterator() = delete;
+
+ public:
+ explicit Iterator(const Types::PciDeviceKind& deviceType);
+
+ Iterator& operator=(const Iterator&) = default;
+ Iterator(const Iterator&) = default;
+
+ ~Iterator();
+
+ public:
+ Ref<PCI::Device> operator[](const Size& sz);
+
+ private:
+ Array<PCI::Device, NE_BUS_COUNT> fDevices;
+ };
+} // namespace NeOS::PCI
+
+#endif // __PCI_ITERATOR_H__
diff --git a/dev/kernel/KernelKit/PCI/PCI.h b/dev/kernel/KernelKit/PCI/PCI.h
new file mode 100644
index 00000000..7eec9ec1
--- /dev/null
+++ b/dev/kernel/KernelKit/PCI/PCI.h
@@ -0,0 +1,59 @@
+/* -------------------------------------------
+
+ Copyright (C) 2024-2025, Amlal EL Mahrouss, all rights reserved.
+
+------------------------------------------- */
+
+#pragma once
+
+#include <NewKit/Defines.h>
+
+#define kPCIConfigAddressPort (0xCF8)
+#define kPCIConfigDataPort (0xCFC)
+
+#define kPCIDeviceCount (32)
+#define kPCIFuncCount (8)
+#define kPCIBusCount (256U)
+
+namespace NeOS::PCI
+{
+ // model
+ struct DeviceHeader
+ {
+ UInt16 VendorId;
+ UInt16 DeviceId;
+ UInt8 Command;
+ UInt8 Status;
+ UInt8 RevisionId;
+ UInt8 ProgIf;
+ UInt8 SubClass;
+ UInt8 Class;
+ UInt8 CacheLineSz;
+ UInt8 LatencyTimer;
+ UInt8 HeaderType;
+ UInt8 Bist;
+ UInt8 Bus;
+ UInt8 Device;
+ UInt8 Function;
+ };
+
+ namespace Detail
+ {
+ class BAR
+ {
+ public:
+ UIntPtr BAR;
+ SizeT Size;
+ };
+ } // namespace Detail
+
+ class BAR
+ {
+ public:
+ Detail::BAR BAR1;
+ Detail::BAR BAR2;
+ Detail::BAR BAR3;
+ Detail::BAR BAR4;
+ Detail::BAR BAR5;
+ };
+} // namespace NeOS::PCI