Skip to content

base: Add ATA/IDE userspace disk driver for DragonWare - #16

Draft
tseli0s wants to merge 33 commits into
masterfrom
disk-ata-support
Draft

base: Add ATA/IDE userspace disk driver for DragonWare#16
tseli0s wants to merge 33 commits into
masterfrom
disk-ata-support

Conversation

@tseli0s

@tseli0s tseli0s commented Aug 22, 2026

Copy link
Copy Markdown
Owner

About time we start tackling this, though this is just a very barebones thing and not anything useful (performs basic probing). Almost all of the code is taken verbatim from the diff of 2348fb0 and so far it appears to work well, though there's definitely some room for improvement.

There's a long road ahead actually to finish what's being started in this commit, possibly talking about months here.

Signed-off-by: Aggelos Tselios aggelostselios777@gmail.com

@tseli0s tseli0s self-assigned this Aug 22, 2026
@tseli0s tseli0s added enhancement New feature or request help wanted Extra attention is needed user-programs Userland related feature or bug performance Performance and throughput related bug or feature labels Aug 22, 2026
@tseli0s
tseli0s marked this pull request as draft August 22, 2026 19:51
@tseli0s
tseli0s force-pushed the disk-ata-support branch 2 times, most recently from 26e688c to 78e6e9d Compare August 24, 2026 11:48
@tseli0s
tseli0s force-pushed the disk-ata-support branch 3 times, most recently from 41785d9 to 13f1464 Compare August 30, 2026 06:53
@tseli0s
tseli0s force-pushed the disk-ata-support branch 2 times, most recently from 1969810 to 2ebc46c Compare August 31, 2026 18:14
@tseli0s
tseli0s force-pushed the disk-ata-support branch 3 times, most recently from 8d67407 to 19bf30f Compare September 9, 2026 08:55
Originally, when DragonWare was first being written (Not even called
DragonWare) the idea was that there would be two sets of system calls:
One for DragonWare applications, and one for POSIX applications. At the
time, it was not a microkernel, so the idea was that there would be
system calls like open(), read(), sysctl(), et al. However, as
DragonWare evolved, the stub code to eventually support POSIX system
calls became bitrot that would never happen. It was only an idea to make
porting software easier and address the fact that I was only familiar
with UNIX like operating systems.

In an effort to make the microkernel as pure as possible, remove all
POSIX-related system call stub code inside kernel space. It will never
be used because DragonWare won't implement POSIX support in kernel
space.

In the future, a POSIX server is planned instead - It will handle POSIX
system calls entirely in userspace, and the kernel will remain tiny. But
the kernel should not even know what POSIX is.

Technically this is also a performance improvement, as some checks can
now be removed entirely.

Signed-off-by: Aggelos Tselios <aggelostselios777@gmail.com>
About time we start tackling this, though this is just a very barebones
thing and not anything useful (performs basic probing). Almost all of
the code is taken verbatim from the diff of 2348fb0 and so far it
appears to work well, though there's definitely some room for
improvement.

There's a long road ahead actually to finish what's being started in
this commit, possibly talking about months here. But who the fuck cares?
YOLO

Signed-off-by: Aggelos Tselios <aggelostselios777@gmail.com>
It's still a work in progress (I mean, I'm still coding the driver :P)
but this is the first step forward.

Signed-off-by: Aggelos Tselios <aggelostselios777@gmail.com>
Instead of having everything in the main thread (and therefore being
only able to do one reading at a time at one drive at a time, which is
horribly inefficient), create listener threads instead.

You think the code is ugly, hackish and makes zero sense right? So do I.
Don't worry, this is not making it to the master branch, I just want to
add some other changes I made which need this file to be committed.
Again, sorry for the horrors you will see in this diff.

PS. Yes, I'm dead serious, I should really implement malloc in libc and
I should do so fast. Holy fuck, I want to gauge my eyes out.

Signed-off-by: Aggelos Tselios <aggelostselios777@gmail.com>
Not needed, because there are separate ports for each bus, so each
message will be directly dispatched to the correct listener. Or maybe
not, I don't know, I'll test it out later.

Signed-off-by: Aggelos Tselios <aggelostselios777@gmail.com>
I have no idea why I did it like this last night, I was probably too
tired. There's no reason to create those listener and IRQ ports on the
main thread, they should be in the listener threads.

Signed-off-by: Aggelos Tselios <aggelostselios777@gmail.com>
Writing the bytes one by one will be a pain in the ass and will look
ugly as shit (Let's not even get on the technical aspect of this with
all the ABI breakages that could occur and so on). Better to have
structs instead that we copy directly on the payload.

In the future, I will add some macro wizardry to do this automatically
for any amount of (sufficiently fitting) structs instead of calling
memcpy() on each and every one of them, and manually calculating the
offsets of each, but for now, I want to get something working.

Signed-off-by: Aggelos Tselios <aggelostselios777@gmail.com>
Part 1/2 (The actual disk read isn't implemented yet, but this is the
skeleton of it). I already tested it with shared memory and everything,
appears to work well, which means we're in good direction.

Signed-off-by: Aggelos Tselios <aggelostselios777@gmail.com>
Will be needed for a tiny part in the ATA/IDE driver to make our lifes
easier in PIO mode, so time to implement them now.

Signed-off-by: Aggelos Tselios <aggelostselios777@gmail.com>
Why limit ourselves to 28 bits when we can immediately lay the future
ahead with 48 bit support? (Or whatever the saying is). We can just
force LBA28 for the time being, of course.

Signed-off-by: Aggelos Tselios <aggelostselios777@gmail.com>
Needed to implement waiting on DRQs, checking ERR/DF and the rest. Maybe
in the future they will go in another header, but for now, they just
need to be available to the driver.

Signed-off-by: Aggelos Tselios <aggelostselios777@gmail.com>
Fixes BSY never being cleared when attempting a READ command (the driver
was testing the wrong bit). In preparation to push an early prototype of
a readonly ATA/IDE driver.

Signed-off-by: Aggelos Tselios <aggelostselios777@gmail.com>
An attempt to fix a bug I am running into (And I am unable to even
pinpoint right now). These functions may also come in handy in the
future, and having them in a separate header is because I want to add
more control function helpers in the future.

Signed-off-by: Aggelos Tselios <aggelostselios777@gmail.com>
* Define the macros ATA_ALTSTATUS_PRIMARY and ATA_ALTSTATUS_SECONDARY to
  be able to read without affecting interrupts the status of the current
  operation.

* Fix the definitions of ATA_STATUS_* macros, otherwise checking or DRQ
  or RDY is actually incorrect when using these definitions to mask out
  the bits (In a test function that is not pushed here yet, which is
  where I discovered the bug).

Signed-off-by: Aggelos Tselios <aggelostselios777@gmail.com>
Will be shared by many parts of the driver because of how ATA/IDE works
and the specification is structured, so time to share it. identify.c
already has ATASoftResetDelay() (Which I have no idea why I named as
such).

Documentation is a bit generalizations and blah blah blah, don't worry,
I'll fix it.

Signed-off-by: Aggelos Tselios <aggelostselios777@gmail.com>
IdentifyDrive() will disable ATA interrupts (nIEN bit) during the
identify call, since there's no handler for this interrupt and the INTRQ
line remains high (or something like that). Preparation to convert the
driver into an interrupt-driven model.

Signed-off-by: Aggelos Tselios <aggelostselios777@gmail.com>
Fixes some compiler warnings because the return value of inb() is being
discarded (This is intentional, those are dummy reads to delay the CPU
as the function name says, we don't care about the returned value)

Signed-off-by: Aggelos Tselios <aggelostselios777@gmail.com>
* Replace calls to ATASoftResetDelay with the now exported Wait400ns()
  function instead to avoid code duplication.

* Flush data returned by the IDENTIFY command (Read it but don't store
  it anywhere) to fix a soft lock on drive requests in QEMU (Better
  detailed in the comment left there)

* Small other code cleanups.

Signed-off-by: Aggelos Tselios <aggelostselios777@gmail.com>
Just following along with the DragonWare coding style where magic
numbers are forbidden, while I am writing a basic read only ATA driver
:P

Signed-off-by: Aggelos Tselios <aggelostselios777@gmail.com>
Found out I need it while developing a read function, because a driver
bug may appear as hardware failure by accident without it to the caller
programs.

Signed-off-by: Aggelos Tselios <aggelostselios777@gmail.com>
About time. The code here took about a week of debugging and ironing
out, and yes, it's not perfect. I've tested it with a small utility
function (Yes, from another process) and it does work however, so this
is a great milestone to hit.

Write support isn't implemented yet, and there are some optimizations I
would like to do, but at the very least, there's a disk driver in
DragonWare now.

Signed-off-by: Aggelos Tselios <aggelostselios777@gmail.com>
Fixes a bug where listener threads were created for buses without any
drives, causing programs to be able to see drives that weren't connected
in the system at all.

Signed-off-by: Aggelos Tselios <aggelostselios777@gmail.com>
… attached

idedrv is fundamentally an interrupt-driven driver, so we NEED
interrupts to be able to issue further requests without polling.
IdentifyDrive() disables them, so we need to reenable them manually.

Signed-off-by: Aggelos Tselios <aggelostselios777@gmail.com>
…`0x1000`

Technically has no effect here (and never will) except trapping into the
kernel to be 100% sure the number is correct. On x86, all page sizes
will be 4KBs for the foreseeable future, but if this driver is to ever
become portable to other architectures, we will need to know what page
size we have, to allocate the correct stack size.

Signed-off-by: Aggelos Tselios <aggelostselios777@gmail.com>
Will be needed to implement write support in the idedrv driver.

Signed-off-by: Aggelos Tselios <aggelostselios777@gmail.com>
Both commands will be needed now that I am working on a prototype write
implementation for the ATA driver.

Signed-off-by: Aggelos Tselios <aggelostselios777@gmail.com>
Not implemented as of this commit, just a simple declaration while I am
working on implementing it.

Signed-off-by: Aggelos Tselios <aggelostselios777@gmail.com>
After a long week of battling it out, I finally did it. It appears to
work when running it through a basic test. To be honest, it's actually
not that perfect, but as far as "get something written on a disk image"
goes, we're finally here.

Unfortunately, this write support is purely polling-based. I can't find
how to replace it with interrupts instead. I also haven't implemented
any error checking and I am not even sure this code is 100% standards
compliant.

Signed-off-by: Aggelos Tselios <aggelostselios777@gmail.com>
With commit e1d590f now implementing some basic write support, it's time
to handle this protocol request as well.

Signed-off-by: Aggelos Tselios <aggelostselios777@gmail.com>
There is a lot of ugly code because there's no malloc() in DragonWare as
it stands in this file. About time we start cleaning it up, now that
dwuser also has some nice wrappers to create a thread, for example.

Signed-off-by: Aggelos Tselios <aggelostselios777@gmail.com>
Should speed up I/O performance since we don't have to wait for the disk
to fetch the data physically, it's all in memory and we just copy it
back into buf.

Signed-off-by: Aggelos Tselios <aggelostselios777@gmail.com>
Signed-off-by: Aggelos Tselios <aggelostselios777@gmail.com>
Fixes a bug in real hardware where the write call would fail as we
didn't wait for the drive to "spin up".

Signed-off-by: Aggelos Tselios <aggelostselios777@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request help wanted Extra attention is needed performance Performance and throughput related bug or feature user-programs Userland related feature or bug

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant