Skip to content

Commit

Permalink
Merge pull request #2936 from GoldenretriverYT/atapi-speed
Browse files Browse the repository at this point in the history
Make ATAPI a tiny bit faster
  • Loading branch information
valentinbreiz authored Feb 1, 2024
2 parents b5f4590 + 4e6dadf commit 89f515f
Show file tree
Hide file tree
Showing 4 changed files with 107 additions and 9 deletions.
68 changes: 66 additions & 2 deletions Tests/Kernels/Cosmos.Kernel.Tests.IO/Kernel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,17 @@
using Sys = Cosmos.System;
using System;
using Cosmos.Kernel.Tests.IO.System.IO;
using System.IO;
using Cosmos.HAL;
using Cosmos.System.FileSystem;
using XSharp.x86.Params;
using System.Collections.Generic;

namespace Cosmos.Kernel.Tests.IO
{
public class Kernel : Sys.Kernel
{
private bool ExecuteFileStreamTests = false;
private bool ExecuteFileStreamTests = true;
private Sys.FileSystem.VFS.VFSBase mVFS;

static readonly public byte[] xBytes = new byte[16]
Expand All @@ -27,6 +32,62 @@ protected override void BeforeRun()
}
}

private void DumpFolder(string aPath, string indent = "") {
var files = Directory.GetFiles(aPath);
foreach (var file in files) {
mDebugger.Send(indent + "File: " + file);
}

var dirs = Directory.GetDirectories(aPath);
foreach (var dir in dirs) {
mDebugger.Send(indent + "Dir: " + dir);
DumpFolder(aPath + "/" + dir, indent + " ");
}
}

private void TestLargeFileFromATAPI() {
// Dump all partitions
List<Disk> xDisks = mVFS.GetDisks();

foreach (var xDisk in xDisks) {
foreach (var xPart in xDisk.Partitions) {
mDebugger.Send("Partition: " + xPart.RootPath);
DumpFolder(xPart.RootPath);
}
}


float secondCounter = 0;

Global.PIT.T0Frequency = 100;
Global.PIT.RegisterTimer(new(() => {
secondCounter += 0.1f;
}, 100000000 /* 100ms */, true));
File.Copy("1:\\boot\\limine\\liminewp.bmp", "0:\\liminewp.bmp", true);

mDebugger.Send("Took " + secondCounter + " seconds to copy large file from ATAPI to hard drive!");

// check file identity
var xFile1 = File.OpenRead("1:\\boot\\limine\\liminewp.bmp");
var xFile2 = File.OpenRead("0:\\liminewp.bmp");

if (xFile1.Length != xFile2.Length) {
mDebugger.Send("File lengths do not match!");
TestController.Failed();
return;
}

for (int i = 0; i < Math.Min(128, xFile1.Length); i++) {
if (xFile1.ReadByte() != xFile2.ReadByte()) {
mDebugger.Send("File contents do not match!");
TestController.Failed();
return;
}
}

mDebugger.Send("File contents match!");
}

protected override void Run()
{
try
Expand All @@ -39,11 +100,14 @@ protected override void Run()
StringReaderTest.Execute(mDebugger);
StringWriterTest.Execute(mDebugger);

// This times out in the test runner because its still pretty slow in bochs (as to be expected cause its emulated)
//TestLargeFileFromATAPI();

TestController.Completed();
}
catch(Exception e)
{
mDebugger.Send("Exception occurred: " + e.Message);
mDebugger.Send(e.GetType().Name + " occurred: " + e.Message);

TestController.Failed();
}
Expand Down
10 changes: 4 additions & 6 deletions source/Cosmos.Core/IOPort.cs
Original file line number Diff line number Diff line change
Expand Up @@ -80,18 +80,16 @@ public static class IOPort
/// <exception cref="System.OverflowException">Thrown if aData lenght is greater than Int32.MaxValue.</exception>
[PlugMethod(PlugRequired = true)]
public static void Read8(int aPort, byte[] aData) => throw null;

/// <summary>
/// Read Word from base port.
/// Read Words from base port.
/// </summary>
/// <param name="aData">Output data array.</param>
/// <exception cref="System.OverflowException">Thrown if aData lenght is greater than Int32.MaxValue.</exception>
[PlugMethod(PlugRequired = true)]
public static void Read16(int aPort, ushort[] aData)
{
for (int i = 0; i < aData.Length; i++)
{
aData[i] = Read16(aPort);
}
throw null;
}

/// <summary>
Expand Down
27 changes: 27 additions & 0 deletions source/Cosmos.Core_Asm/IOPortImpl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,33 @@ public override void AssembleNew(Assembler aAssembler, object aMethodInfo)

#endregion

#region Read16 (many)

private class Read16ManyAssembler : AssemblerMethod {
public override void AssembleNew(Assembler aAssembler, object aMethodInfo) {
// the port index is in EBP+16
// the reference to the byte array is in EBP+12
XS.Set(XSRegisters.EDX, XSRegisters.EBP, sourceDisplacement: 16); // EDX = Port (ebp+16)
XS.Set(XSRegisters.ECX, XSRegisters.EBP, sourceDisplacement: 12); // ECX = Pointer to array (ebp+12)

XS.Lea(XSRegisters.ESI, XSRegisters.ECX, sourceDisplacement: 16); // ESI = Data* (ecx+16)
XS.Set(XSRegisters.EBX, XSRegisters.ECX, sourceDisplacement: 8); // EBX = Length (ecx+8)

XS.Label(".loop");
XS.ReadFromPortDX(XSRegisters.AX);
XS.Set(XSRegisters.ESI, XSRegisters.AX, destinationIsIndirect: true); // *esi = ax
XS.Add(XSRegisters.ESI, 2); // esi++

XS.Sub(XSRegisters.EBX, 1); // ebx--
XS.Jump(XSharp.Assembler.x86.ConditionalTestEnum.NotZero, ".loop"); // if (ebx != 0) goto .loop
}
}

[PlugMethod(Assembler = typeof(Read16ManyAssembler))]
public static void Read16(ushort aPort, ushort[] aData) => throw null;

#endregion

#region Read32

private class Read32Assembler : AssemblerMethod
Expand Down
11 changes: 10 additions & 1 deletion source/Cosmos.HAL2/BlockDevice/ATAPI.cs
Original file line number Diff line number Diff line change
Expand Up @@ -134,14 +134,23 @@ public override void ReadBlock(ulong SectorNum, ulong SectorCount, ref byte[] aD

//Convert the buffer into bytes
byte[] array = new byte[SectorSize];
int counter = 0;
/*int counter = 0;
for (int i = 0; i < SectorSize / 2; i++)
{
var item = buffer[i];
var bytes = BitConverter.GetBytes(item);
array[counter++] = bytes[0];
array[counter++] = bytes[1];
}*/

unsafe {
fixed (byte* ptr = array) {
fixed (ushort* ptr2 = buffer) {
byte* ptr3 = (byte*)ptr2;
MemoryOperations.Copy(ptr, ptr3, SectorSize);
}
}
}

//Return
Expand Down

0 comments on commit 89f515f

Please sign in to comment.