Skip to content

Commit c55db10

Browse files
committed
Map identified AHCI controller and check ports
1 parent 0f5ba39 commit c55db10

File tree

3 files changed

+188
-7
lines changed

3 files changed

+188
-7
lines changed
Lines changed: 126 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,145 @@
1-
#include <libpci/driver.hpp>
1+
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2+
* *
3+
* Ghost, a micro-kernel based operating system for the x86 architecture *
4+
* Copyright (C) 2025, Max Schlüssel <lokoxe@gmail.com> *
5+
* *
6+
* This program is free software: you can redistribute it and/or modify *
7+
* it under the terms of the GNU General Public License as published by *
8+
* the Free Software Foundation, either version 3 of the License, or *
9+
* (at your option) any later version. *
10+
* *
11+
* This program is distributed in the hope that it will be useful, *
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14+
* GNU General Public License for more details. *
15+
* *
16+
* You should have received a copy of the GNU General Public License *
17+
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
18+
* *
19+
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
20+
21+
#include "ahcidriver.hpp"
222
#include <cstdio>
23+
#include <libahci/ahci.hpp>
24+
#include <libahci/driver.hpp>
325

426
int main()
527
{
28+
g_task_register_id(G_AHCI_DRIVER_IDENTIFIER);
29+
30+
g_pci_identify_ahci_controller_entry* entries;
31+
if((entries = ahciDriverIdentifyController()) == nullptr)
32+
return -1;
33+
34+
auto ahciController = entries[0];
35+
g_irq_create_redirect(ahciController.interruptLine, 2);
36+
37+
auto ahciControllerVirt = g_map_mmio((void*) ahciController.baseAddress, 0x1000);
38+
klog("mapped AHCI controller at %x to virtual %x", ahciController.baseAddress, ahciControllerVirt);
39+
40+
auto ahciGhc = (volatile g_ahci_hba_ghc*) ahciControllerVirt;
41+
ahciGhc->ghc.ahciEnable = 1;
42+
ahciGhc->ghc.interruptEnable = 1;
43+
klog("AHCI ports implemented: %i", ahciGhc->pi);
44+
45+
auto ahciPorts = (volatile g_ahci_hba_port*) (ahciControllerVirt + G_AHCI_HBA_PORT_OFFSET);
46+
for(uint8_t portNumber = 0; portNumber < 32; portNumber++)
47+
{
48+
if(!(ahciGhc->pi & (1 << portNumber)))
49+
continue;
50+
ahciIdentifyDevice(portNumber, &ahciPorts[portNumber]);
51+
}
52+
53+
g_sleep(999999);
54+
}
55+
56+
g_pci_identify_ahci_controller_entry* ahciDriverIdentifyController()
57+
{
58+
g_pci_identify_ahci_controller_entry* entries = nullptr;
659
while(true)
760
{
8-
g_pci_identify_ahci_controller_entry* entries;
961
int count;
62+
// TODO avoid this loop
1063
if(pciDriverIdentifyAhciController(&entries, &count))
1164
{
12-
klog("Successfully identified %i AHCI controllers", count);
13-
14-
for(int i = 0; i < count; i++)
65+
if(count < 1)
1566
{
16-
klog("AHCI controller: %x, INTR line: %i", entries[i].baseAddress, entries[i].interruptLine);
67+
klog("no AHCI controllers were reported by PCI driver, exiting");
68+
return nullptr;
1769
}
70+
1871
break;
1972
}
2073
else
2174
{
22-
klog("Failed to identify AHCI controller, retrying soon...");
75+
klog("failed to identify AHCI controller, retrying soon...");
2376
}
2477
g_sleep(5000);
2578
}
79+
return entries;
80+
}
81+
82+
void ahciIdentifyDevice(uint8_t portNumber, volatile g_ahci_hba_port* port)
83+
{
84+
if(!(port->ssts.det == G_AHCI_HBA_PORT_SSTS_DET_READY))
85+
{
86+
klog("device on port %i not present or ready: %i", portNumber, port->ssts.det);
87+
return;
88+
}
89+
90+
if(port->sig != G_SATA_SIGNATURE_ATA)
91+
{
92+
klog("port %i does not have an ATA device: %x", portNumber, port->sig);
93+
return;
94+
}
95+
96+
if(!ahciPortStopCommands(port))
97+
{
98+
klog("timed out when trying to stop commands on port %i", portNumber);
99+
return;
100+
}
101+
102+
// ...
103+
klog("ready to initialize device on port %i", portNumber);
104+
}
105+
106+
bool ahciPortStartCommands(volatile g_ahci_hba_port* port)
107+
{
108+
uint32_t timeout = 1000000;
109+
while(port->cmd.cr && --timeout)
110+
{
111+
}
112+
113+
if(timeout > 0)
114+
{
115+
port->cmd.fre = 1;
116+
port->cmd.st = 1;
117+
return true;
118+
}
119+
return false;
120+
}
121+
122+
bool ahciPortStopCommands(volatile g_ahci_hba_port* port)
123+
{
124+
port->cmd.st = 0;
125+
port->cmd.fre = 0;
126+
127+
uint32_t timeout = 1000000;
128+
while((port->cmd.fr || port->cmd.cr) && --timeout)
129+
{
130+
}
131+
return timeout > 0;
132+
}
133+
134+
int ahciFindFreeCommandSlot(volatile g_ahci_hba_port* port)
135+
{
136+
// If not set in SACT and CI, the slot is free
137+
uint32_t slots = (port->sact | port->ci);
138+
for(int i = 0; i < 32; i++)
139+
{
140+
if((slots & 1) == 0)
141+
return i;
142+
slots >>= 1;
143+
}
144+
return -1;
26145
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2+
* *
3+
* Ghost, a micro-kernel based operating system for the x86 architecture *
4+
* Copyright (C) 2025, Max Schlüssel <lokoxe@gmail.com> *
5+
* *
6+
* This program is free software: you can redistribute it and/or modify *
7+
* it under the terms of the GNU General Public License as published by *
8+
* the Free Software Foundation, either version 3 of the License, or *
9+
* (at your option) any later version. *
10+
* *
11+
* This program is distributed in the hope that it will be useful, *
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14+
* GNU General Public License for more details. *
15+
* *
16+
* You should have received a copy of the GNU General Public License *
17+
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
18+
* *
19+
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
20+
21+
#ifndef __AHCIDRIVER__
22+
#define __AHCIDRIVER__
23+
24+
#include <stdint.h>
25+
#include <ghost.h>
26+
#include <libahci/ahci.hpp>
27+
#include <libpci/driver.hpp>
28+
29+
g_pci_identify_ahci_controller_entry* ahciDriverIdentifyController();
30+
bool ahciPortStartCommands(volatile g_ahci_hba_port* port);
31+
bool ahciPortStopCommands(volatile g_ahci_hba_port* port);
32+
int ahciFindFreeCommandSlot(volatile g_ahci_hba_port* port);
33+
void ahciIdentifyDevice(uint8_t portNumber, volatile g_ahci_hba_port* port);
34+
35+
#endif
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2+
* *
3+
* Ghost, a micro-kernel based operating system for the x86 architecture *
4+
* Copyright (C) 2025, Max Schlüssel <lokoxe@gmail.com> *
5+
* *
6+
* This program is free software: you can redistribute it and/or modify *
7+
* it under the terms of the GNU General Public License as published by *
8+
* the Free Software Foundation, either version 3 of the License, or *
9+
* (at your option) any later version. *
10+
* *
11+
* This program is distributed in the hope that it will be useful, *
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14+
* GNU General Public License for more details. *
15+
* *
16+
* You should have received a copy of the GNU General Public License *
17+
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
18+
* *
19+
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
20+
21+
#ifndef __LIBAHCI_AHCIDRIVER__
22+
#define __LIBAHCI_AHCIDRIVER__
23+
24+
#define G_AHCI_DRIVER_IDENTIFIER "ahcidriver"
25+
26+
27+
#endif

0 commit comments

Comments
 (0)