summaryrefslogtreecommitdiffhomepage
path: root/dev/kernel/HALKit
diff options
context:
space:
mode:
authorAmlal El Mahrouss <amlal@nekernel.org>2025-04-01 09:44:20 +0200
committerAmlal El Mahrouss <amlal@nekernel.org>2025-04-01 09:44:20 +0200
commit6965e19b184358431dd9832187e541da3af3968f (patch)
tree6c7e782ad9d66c6d1c5d55cc1031e5ef54488d9f /dev/kernel/HALKit
parent2a7a9825fd275d6d999b94614fe87c1d705c7f8f (diff)
kernel/storage, pio, ahci, dma: a lot of patches and fixes according to StorageKit specs and
cleaned up DMA driver for a future more robust implementation. Signed-off-by: Amlal El Mahrouss <amlal@nekernel.org>
Diffstat (limited to 'dev/kernel/HALKit')
-rw-r--r--dev/kernel/HALKit/AMD64/PCI/Device.cc31
-rw-r--r--dev/kernel/HALKit/AMD64/Storage/AHCI+Generic.cc19
-rw-r--r--dev/kernel/HALKit/AMD64/Storage/DMA+Generic.cc61
-rw-r--r--dev/kernel/HALKit/AMD64/Storage/PIO+Generic.cc142
4 files changed, 151 insertions, 102 deletions
diff --git a/dev/kernel/HALKit/AMD64/PCI/Device.cc b/dev/kernel/HALKit/AMD64/PCI/Device.cc
index 68bf64ea..9c27cb10 100644
--- a/dev/kernel/HALKit/AMD64/PCI/Device.cc
+++ b/dev/kernel/HALKit/AMD64/PCI/Device.cc
@@ -99,7 +99,7 @@ namespace Kernel::PCI
UShort Device::InterfaceId()
{
- return (UShort)(NE_PCIReadRaw(0x0, fBus, fDevice, fFunction) >> 16);
+ return (UShort)(NE_PCIReadRaw(0x09, fBus, fDevice, fFunction) >> 16);
}
UChar Device::Class()
@@ -122,25 +122,24 @@ namespace Kernel::PCI
return (UChar)(NE_PCIReadRaw(0xC, fBus, fDevice, fFunction) >> 16);
}
- void Device::EnableMmio(UInt32 bar_in)
+ void Device::EnableMmio()
{
- UInt32 enable = Read(bar_in, sizeof(UInt32));
- enable |= (1 << 1);
+ UInt32 command = Read(0x04, sizeof(UInt32));
+ command |= (1 << 1); // Memory Space Enable (bit 1)
- Write(bar_in, enable, sizeof(UInt32));
+ Write(0x04, command, sizeof(UInt32));
}
- void Device::BecomeBusMaster(UInt32 bar_in)
+ void Device::BecomeBusMaster()
{
- UInt32 enable = Read(bar_in, sizeof(UInt32));
- enable |= (1 << 2);
-
- Write(bar_in, enable, sizeof(UInt32));
+ UInt32 command = Read(0x04, sizeof(UInt32));
+ command |= (1 << 2); // Bus Master Enable (bit 2)
+ Write(0x04, command, sizeof(UInt32));
}
UIntPtr Device::Bar(UInt32 bar_in)
{
- UInt32 bar = NE_PCIReadRaw(bar_in & ~0x03, fBus, fDevice, fFunction);
+ UInt32 bar = NE_PCIReadRaw(bar_in, fBus, fDevice, fFunction);
if (bar & PCI_BAR_IO)
return static_cast<UIntPtr>(bar & ~0x03);
@@ -156,16 +155,12 @@ namespace Kernel::PCI
UShort Device::Vendor()
{
- UShort vendor = VendorId();
-
- if (vendor != (UShort)PciConfigKind::Invalid)
- fDevice = (UShort)Read(0x0, sizeof(UShort));
-
- return fDevice;
+ UShort vendor = this->VendorId();
+ return vendor;
}
Device::operator bool()
{
- return VendorId() != (UShort)PciConfigKind::Invalid;
+ return this->VendorId() != (UShort)PciConfigKind::Invalid;
}
} // namespace Kernel::PCI
diff --git a/dev/kernel/HALKit/AMD64/Storage/AHCI+Generic.cc b/dev/kernel/HALKit/AMD64/Storage/AHCI+Generic.cc
index e5f10db3..a02bf5e1 100644
--- a/dev/kernel/HALKit/AMD64/Storage/AHCI+Generic.cc
+++ b/dev/kernel/HALKit/AMD64/Storage/AHCI+Generic.cc
@@ -7,7 +7,7 @@
/**
* @file AHCI+Generic.cc
* @author Amlal El Mahrouss (amlal@nekernel.org)
- * @brief AHCI driver.
+ * @brief AHCI Generic driver.
* @version 0.1
* @date 2024-02-02
*
@@ -15,6 +15,7 @@
*
*/
+#include "NewKit/Defines.h"
#include <KernelKit/DeviceMgr.h>
#include <KernelKit/DriveMgr.h>
#include <KernelKit/ProcessScheduler.h>
@@ -56,7 +57,7 @@ STATIC PCI::Device kSATADev;
STATIC HbaMemRef kSATAHba;
STATIC Lba kSATASectorCount = 0UL;
STATIC UInt16 kSATAIndex = 0U;
-STATIC Char kCurrentDiskModel[50] = {"UNKNOWN AHCI DRIVE"};
+STATIC Char kCurrentDiskModel[50] = {"GENERIC SATA"};
STATIC UInt16 kSATAPortsImplemented = 0U;
template <BOOL Write, BOOL CommandOrCTRL, BOOL Identify>
@@ -74,11 +75,9 @@ STATIC Void drv_compute_disk_ahci() noexcept
const UInt16 kSzIdent = kib_cast(1);
/// Push it to the stack
- static UInt8 identify_data[kSzIdent] ATTRIBUTE(aligned(4096)) = {0};
+ UInt8* identify_data ATTRIBUTE(aligned(4096)) = (UInt8*)mib_cast(1);
- HAL::mm_map_page((void*)mib_cast(1), (void*)mib_cast(1), HAL::kMMFlagsWr);
-
- rt_set_memory(identify_data, 0, kSzIdent);
+ HAL::mm_map_page((VoidPtr)mib_cast(1), (VoidPtr)mib_cast(1), HAL::kMMFlagsWr);
/// Send AHCI command for identification.
drv_std_input_output_ahci<NO, YES, YES>(0, identify_data, kAHCISectorSize, kSzIdent);
@@ -152,7 +151,7 @@ STATIC Void drv_std_input_output_ahci(UInt64 lba, UInt8* buffer, SizeT sector_sz
MUST_PASS(command_header);
- constexpr const UInt32 kMaxPRDSize = mib_cast(4);
+ constexpr const UInt32 kMaxPRDSize = kib_cast(4);
command_header->Cfl = sizeof(FisRegH2D) / sizeof(UInt32);
command_header->Write = Write;
@@ -337,8 +336,8 @@ STATIC Bool drv_std_init_ahci(UInt16& pi, BOOL& atapi)
{
HbaMem* mem_ahci = (HbaMem*)kSATADev.Bar(kSATABar5);
- kSATADev.EnableMmio((UIntPtr)mem_ahci);
- kSATADev.BecomeBusMaster((UIntPtr)mem_ahci);
+ kSATADev.EnableMmio();
+ kSATADev.BecomeBusMaster();
UInt32 ports_implemented = mem_ahci->Pi;
UInt16 ahci_index = 0;
@@ -473,7 +472,7 @@ namespace Kernel
UInt16 sk_init_ahci_device(BOOL atapi)
{
UInt16 pi = 0;
- return drv_std_init_ahci(pi, atapi);
+ drv_std_init_ahci(pi, atapi);
kSATAPortsImplemented = pi;
diff --git a/dev/kernel/HALKit/AMD64/Storage/DMA+Generic.cc b/dev/kernel/HALKit/AMD64/Storage/DMA+Generic.cc
index cc848f64..300b959f 100644
--- a/dev/kernel/HALKit/AMD64/Storage/DMA+Generic.cc
+++ b/dev/kernel/HALKit/AMD64/Storage/DMA+Generic.cc
@@ -32,7 +32,7 @@ STATIC Boolean kATADetected = false;
STATIC Int32 kATADeviceType = kATADeviceCount;
STATIC Char kATAData[kATADataLen] = {0};
STATIC Kernel::PCI::Device kATADevice;
-STATIC Char kCurrentDiskModel[50] = {"UNKNOWN DMA DRIVE"};
+STATIC Char kCurrentDiskModel[50] = {"GENERIC DMA"};
Boolean drv_std_wait_io(UInt16 IO)
{
@@ -73,76 +73,29 @@ Boolean drv_std_init(UInt16 Bus, UInt8 Drive, UInt16& OutBus, UInt8& OutMaster)
{
kATADevice = iterator[device_index].Leak(); // And then leak the reference.
- // if SATA and then interface is AHCI...
+ /// IDE interface
if (kATADevice.Subclass() == 0x01)
{
- UInt16 IO = Bus;
-
- drv_std_select(IO);
-
- // Bus init, NEIN bit.
- rt_out8(IO + ATA_REG_NEIN, 1);
-
- // identify until it's good.
- ATAInit_Retry:
- auto status_rdy = rt_in8(IO + ATA_REG_STATUS);
-
- if (status_rdy & ATA_SR_ERR)
- {
- return false;
- }
-
- if ((status_rdy & ATA_SR_BSY))
- goto ATAInit_Retry;
-
- rt_out8(IO + ATA_REG_COMMAND, ATA_CMD_IDENTIFY);
-
- /// fetch serial info
- /// model, speed, number of sectors...
-
- drv_std_wait_io(IO);
-
- for (SizeT i = 0ul; i < kATADataLen; ++i)
- {
- drv_std_wait_io(IO);
- kATAData[i] = Kernel::HAL::rt_in16(IO + ATA_REG_DATA);
- drv_std_wait_io(IO);
- }
-
- for (SizeT i = 0; i < 40; i += 2)
- {
- kCurrentDiskModel[i * 2] = kATAData[27 + i * 2] >> 8;
- kCurrentDiskModel[i * 2 + 1] = kATAData[27 + i * 2] & 0xFF;
- }
-
- kCurrentDiskModel[40] = '\0';
-
- kout << "Drive Model: " << kCurrentDiskModel << kendl;
-
- OutBus = (Bus == ATA_PRIMARY_IO) ? ATA_PRIMARY_IO : ATA_SECONDARY_IO;
- OutMaster = (Bus == ATA_PRIMARY_IO) ? ATA_MASTER : ATA_SLAVE;
-
- return YES;
+
+ break;
}
}
- ke_panic(RUNTIME_CHECK_BOOTSTRAP, "Invalid ATA DMA driver, not detected");
-
return NO;
}
namespace Kernel::Detail
{
- struct PRDEntry
+ struct PRDEntry final
{
UInt32 mAddress;
UInt16 mByteCount;
- UInt16 mFlags;
+ UInt16 mFlags; /// @param PRD flags, set to 0x8000 to indicate end of prd.
};
} // namespace Kernel::Detail
static UIntPtr kReadAddr = mib_cast(2);
-static UIntPtr kWriteAddr = mib_cast(4);
+static UIntPtr kWriteAddr = mib_cast(2) + kib_cast(64);
Void drv_std_read(UInt64 Lba, UInt16 IO, UInt8 Master, Char* Buf, SizeT SectorSz, SizeT Size)
{
diff --git a/dev/kernel/HALKit/AMD64/Storage/PIO+Generic.cc b/dev/kernel/HALKit/AMD64/Storage/PIO+Generic.cc
index 201cdf30..c6eee7f7 100644
--- a/dev/kernel/HALKit/AMD64/Storage/PIO+Generic.cc
+++ b/dev/kernel/HALKit/AMD64/Storage/PIO+Generic.cc
@@ -15,10 +15,11 @@
*
*/
+#include "NewKit/Defines.h"
#include <modules/ATA/ATA.h>
#include <ArchKit/ArchKit.h>
-
-#ifdef __ATA_PIO__
+#include <KernelKit/DriveMgr.h>
+#include <StorageKit/ATA.h>
using namespace Kernel;
using namespace Kernel::HAL;
@@ -30,9 +31,9 @@ using namespace Kernel::HAL;
STATIC Boolean kATADetected = false;
STATIC Int32 kATADeviceType = kATADeviceCount;
STATIC Char kATAData[kATADataLen] = {0};
-STATIC Char kCurrentDiskModel[50] = {"UNKNOWN PIO DRIVE"};
+STATIC Char kCurrentDiskModel[50] = {"GENERIC PIO"};
-Boolean drv_std_wait_io(UInt16 IO)
+static Boolean drv_pio_std_wait_io(UInt16 IO)
{
for (int i = 0; i < 400; i++)
rt_in8(IO + ATA_REG_STATUS);
@@ -55,7 +56,7 @@ ATAWaitForIO_Retry2:
return true;
}
-Void drv_std_select(UInt16 Bus)
+static Void drv_pio_std_select(UInt16 Bus)
{
if (Bus == ATA_PRIMARY_IO)
rt_out8(Bus + ATA_REG_HDDEVSEL, ATA_PRIMARY_SEL);
@@ -63,11 +64,11 @@ Void drv_std_select(UInt16 Bus)
rt_out8(Bus + ATA_REG_HDDEVSEL, ATA_SECONDARY_SEL);
}
-Boolean drv_std_init(UInt16 Bus, UInt8 Drive, UInt16& OutBus, UInt8& OutMaster)
+Boolean drv_pio_std_init(UInt16 Bus, UInt8 Drive, UInt16& OutBus, UInt8& OutMaster)
{
UInt16 IO = Bus;
- drv_std_select(IO);
+ drv_pio_std_select(IO);
// Bus init, NEIN bit.
rt_out8(IO + ATA_REG_NEIN, 1);
@@ -89,7 +90,7 @@ ATAInit_Retry:
rt_out8(OutBus + ATA_REG_COMMAND, ATA_CMD_IDENTIFY);
- drv_std_wait_io(IO);
+ drv_pio_std_wait_io(IO);
/// fetch serial info
/// model, speed, number of sectors...
@@ -114,14 +115,14 @@ ATAInit_Retry:
return true;
}
-Void drv_std_read(UInt64 Lba, UInt16 IO, UInt8 Master, Char* Buf, SizeT SectorSz, SizeT Size)
+Void drv_pio_std_read(UInt64 Lba, UInt16 IO, UInt8 Master, Char* Buf, SizeT SectorSz, SizeT Size)
{
Lba /= SectorSz;
UInt8 Command = ((!Master) ? 0xE0 : 0xF0);
- drv_std_wait_io(IO);
- drv_std_select(IO);
+ drv_pio_std_wait_io(IO);
+ drv_pio_std_select(IO);
rt_out8(IO + ATA_REG_HDDEVSEL, (Command) | (((Lba) >> 24) & 0x0F));
@@ -136,19 +137,19 @@ Void drv_std_read(UInt64 Lba, UInt16 IO, UInt8 Master, Char* Buf, SizeT SectorSz
for (SizeT IndexOff = 0; IndexOff < Size; ++IndexOff)
{
- drv_std_wait_io(IO);
+ drv_pio_std_wait_io(IO);
Buf[IndexOff] = HAL::rt_in16(IO + ATA_REG_DATA);
}
}
-Void drv_std_write(UInt64 Lba, UInt16 IO, UInt8 Master, Char* Buf, SizeT SectorSz, SizeT Size)
+Void drv_pio_std_write(UInt64 Lba, UInt16 IO, UInt8 Master, Char* Buf, SizeT SectorSz, SizeT Size)
{
Lba /= SectorSz;
UInt8 Command = ((!Master) ? 0xE0 : 0xF0);
- drv_std_wait_io(IO);
- drv_std_select(IO);
+ drv_pio_std_wait_io(IO);
+ drv_pio_std_select(IO);
rt_out8(IO + ATA_REG_HDDEVSEL, (Command) | (((Lba) >> 24) & 0x0F));
@@ -163,13 +164,13 @@ Void drv_std_write(UInt64 Lba, UInt16 IO, UInt8 Master, Char* Buf, SizeT SectorS
for (SizeT IndexOff = 0; IndexOff < Size; ++IndexOff)
{
- drv_std_wait_io(IO);
+ drv_pio_std_wait_io(IO);
rt_out16(IO + ATA_REG_DATA, Buf[IndexOff]);
}
}
/// @brief is ATA detected?
-Boolean drv_std_detected(Void)
+Boolean drv_pio_std_detected(Void)
{
return kATADetected;
}
@@ -177,15 +178,116 @@ Boolean drv_std_detected(Void)
/***
@brief Getter, gets the number of sectors inside the drive.
*/
-SizeT drv_get_sector_count()
+SizeT drv_pio_get_sector_count()
{
return (kATAData[61] << 16) | kATAData[60];
}
/// @brief Get the drive size.
+SizeT drv_pio_get_size()
+{
+ return (drv_pio_get_sector_count()) * kATASectorSize;
+}
+
+namespace Kernel
+{
+ /// @brief Initialize an PIO device (StorageKit function)
+ /// @param is_master is the current PIO master?
+ /// @return [io:master] for PIO device.
+ BOOL sk_init_pio_device(BOOL is_master, UInt16& io, UInt8& master)
+ {
+ return drv_pio_std_init(ATA_SECONDARY_IO, is_master, io, master);
+ }
+
+ /// @brief Implementation details namespace.
+ namespace Detail
+ {
+ /// @brief Read PIO device.
+ /// @param self device
+ /// @param mnt mounted disk.
+ STATIC Void sk_io_read_pio(IDeviceObject<MountpointInterface*>* self, MountpointInterface* mnt)
+ {
+ ATADeviceInterface* dev = (ATADeviceInterface*)self;
+
+ err_global_get() = kErrorDisk;
+
+ if (!dev)
+ return;
+
+ auto disk = mnt->GetAddressOf(dev->GetIndex());
+
+ if (!disk)
+ return;
+
+ err_global_get() = kErrorSuccess;
+
+ drv_pio_std_read(disk->fPacket.fPacketLba, dev->GetIO(), dev->GetMaster(), (Char*)disk->fPacket.fPacketContent, kATASectorSize, disk->fPacket.fPacketSize);
+ }
+
+ /// @brief Write PIO device.
+ /// @param self device
+ /// @param mnt mounted disk.
+ STATIC Void sk_io_write_pio(IDeviceObject<MountpointInterface*>* self, MountpointInterface* mnt)
+ {
+ ATADeviceInterface* dev = (ATADeviceInterface*)self;
+
+ err_global_get() = kErrorDisk;
+
+ if (!dev)
+ return;
+
+ auto disk = mnt->GetAddressOf(dev->GetIndex());
+
+ if (!disk)
+ return;
+
+ err_global_get() = kErrorSuccess;
+
+ drv_pio_std_write(disk->fPacket.fPacketLba, dev->GetIO(), dev->GetMaster(), (Char*)disk->fPacket.fPacketContent, kATASectorSize, disk->fPacket.fPacketSize);
+ }
+ } // namespace Detail
+
+ /// @brief Acquires a new PIO device with drv_index in mind.
+ /// @param drv_index The drive index to assign.
+ /// @return A wrapped device interface if successful, or error code.
+ ErrorOr<ATADeviceInterface> sk_acquire_pio_device(Int32 drv_index)
+ {
+ /// here we don't check if we probed ATA, since we'd need to grab IO after that.
+ ATADeviceInterface device(Detail::sk_io_read_pio,
+ Detail::sk_io_write_pio,
+ nullptr);
+
+ device.SetIndex(drv_index);
+
+ return ErrorOr<ATADeviceInterface>(device);
+ }
+} // namespace Kernel
+
+#ifdef __ATA_PIO__
+
+Void drv_std_read(UInt64 Lba, UInt16 IO, UInt8 Master, Char* Buf, SizeT SectorSz, SizeT Size)
+{
+ drv_pio_std_read(Lba, IO, Master, Buf, SectorSz, Size);
+}
+
+Void drv_std_write(UInt64 Lba, UInt16 IO, UInt8 Master, Char* Buf, SizeT SectorSz, SizeT Size)
+{
+ drv_pio_std_write(Lba, IO, Master, Buf, SectorSz, Size);
+}
+
SizeT drv_get_size()
{
- return (drv_get_sector_count()) * kATASectorSize;
+ return drv_pio_get_size();
+}
+
+SizeT drv_get_sector_count()
+{
+ return drv_pio_get_sector_count();
+}
+
+Boolean drv_std_init(UInt16 Bus, UInt8 Drive, UInt16& OutBus, UInt8& OutMaster)
+{
+ return drv_pio_std_init(Bus, Drive, OutBus, OutMaster);
}
-#endif /* ifdef __ATA_PIO__ */ \ No newline at end of file
+#endif \ No newline at end of file