summaryrefslogtreecommitdiffhomepage
path: root/src/hal/coreboot-ahci-driver.c
blob: 2ef20981f5f785e2498b613a80d5d8bda3eca598 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
/* -------------------------------------------

	Copyright (C) 2024, Amlal EL Mahrouss, all rights reserved.

------------------------------------------- */

/**
 * @file coreboot-ahci-driver.cc
 * @author Amlal EL Mahrouss (amlal@nekernel.org)
 * @brief SATA Disk support, via AHCI.
 * @version 0.2
 * @date 2024-01-16
 *
 * @copyright Copyright (c) 2024-2025, Amlal EL Mahrouss.
 *
 */

#include <lib/pci-tree.h>
#include <lib/boot.h>

#define CB_AHCI_DRIVER_NAME ("@sata")

/// BUGS: 0
/// @brief AHCI support for PowerPC.

/// @brief AHCI HBA port.
typedef struct cb_hba_port
{
	uint32_t clb;			// 0x00, command list base address, 1K-byte aligned
	uint32_t clbu;			// 0x04, command list base address upper 32 bits
	uint32_t fb;			// 0x08, FIS base address, 256-byte aligned
	uint32_t fbu;			// 0x0C, FIS base address upper 32 bits
	uint32_t is;			// 0x10, interrupt status
	uint32_t ie;			// 0x14, interrupt enable
	uint32_t cmd;			// 0x18, command and status
	uint32_t reserved0;		// 0x1C, Reserved
	uint32_t tfd;			// 0x20, task file data
	uint32_t sig;			// 0x24, signature
	uint32_t ssts;			// 0x28, SATA status (SCR0:SStatus)
	uint32_t sctl;			// 0x2C, SATA control (SCR2:SControl)
	uint32_t serr;			// 0x30, SATA error (SCR1:SError)
	uint32_t sact;			// 0x34, SATA active (SCR3:SActive)
	uint32_t ci;			// 0x38, command issue
	uint32_t sntf;			// 0x20, SATA notification (SCR4:SNotification)
	uint32_t fbs;			// 0x40, FIS-based switch control
	uint32_t reserved1[11]; // 0x44 ~ 0x6F, Reserved
	uint32_t vendor[4];		// 0x70 ~ 0x7F, vendor specific
} cb_hba_port_t;

/// @brief Check if port is active.
/// @param port host bus address port.
/// @return whether sact is active or not.
static boolean cb_hba_port_active(volatile cb_hba_port_t* port)
{
	if (!port)
		return false;

	return port->sact;
}

/// @brief Start HBA command processor.
/// @param port host bus address port.
/// @return whether it was successful or not.
static boolean cb_hba_start_cmd(volatile cb_hba_port_t* port)
{
	if (!port)
		return false;

	size_t timeout = 1000000;

	while ((port->cmd & 0x8000))
	{
		if (!timeout)
			return false;

		--timeout;
	}

	port->cmd |= 0x0001;
	port->cmd |= 0x0010;

	return true;
}

/// @brief Stop HBA command from processing.
/// @param port host bus address port.
/// @return whether it was successful or not.
static boolean cb_hba_stop_cmd(volatile cb_hba_port_t* port)
{
	if (!port)
		return false;

	port->cmd &= ~0x0001;
	port->cmd &= ~0x0010;

	while (yes)
	{
		if ((port->cmd & 0x8000))
			continue;

		if ((port->cmd & 0x4000))
			continue;

		break;
	}

	return true;
}