feat: Ability to send command to ATA device.
[lunaix-os.git] / lunaix-os / includes / hal / ahci / ahci.h
1 #ifndef __LUNAIX_AHCI_H
2 #define __LUNAIX_AHCI_H
3
4 #include <stdint.h>
5
6 /*
7  * Macro naming rule:
8  *      HBA_R[xxx]
9  *          HBA Register [xxx]
10  *          e.g. HBA_RPxCLB is Register PxCLB
11  *
12  * All registers offset are 0 based index of a DWORD array
13  */
14
15 #define AHCI_HBA_CLASS 0x10601
16
17 #define HBA_RCAP 0
18 #define HBA_RGHC 1
19 #define HBA_RIS 2
20 #define HBA_RPI 3
21 #define HBA_RVER 4
22
23 #define HBA_RPBASE (0x40)
24 #define HBA_RPSIZE (0x80 >> 2)
25 #define HBA_RPxCLB 0
26 #define HBA_RPxFB 2
27 #define HBA_RPxIS 4
28 #define HBA_RPxIE 5
29 #define HBA_RPxCMD 6
30 #define HBA_RPxTFD 8
31 #define HBA_RPxSIG 9
32 #define HBA_RPxSSTS 10
33 #define HBA_RPxSCTL 11
34 #define HBA_RPxSERR 12
35 #define HBA_RPxSACT 13
36 #define HBA_RPxCI 14
37 #define HBA_RPxSNTF 15
38 #define HBA_RPxFBS 16
39
40 #define HBA_PxCMD_FRE (1 << 4)
41 #define HBA_PxCMD_CR (1 << 15)
42 #define HBA_PxCMD_FR (1 << 14)
43 #define HBA_PxCMD_ST (1)
44 #define HBA_PxINTR_DMA (1 << 2)
45 #define HBA_PxINTR_D2HR (1)
46
47 #define HBA_RGHC_ACHI_ENABLE (1 << 31)
48 #define HBA_RGHC_INTR_ENABLE (1 << 1)
49 #define HBA_RGHC_RESET 1
50
51 #define HBA_RPxSSTS_PWR(x) (((x) >> 8) & 0xf)
52 #define HBA_RPxSSTS_IF(x) (((x) >> 4) & 0xf)
53 #define HBA_RPxSSTS_PHYSTATE(x) ((x)&0xf)
54
55 #define HBA_DEV_SIG_ATAPI 0xeb140101
56 #define HBA_DEV_SIG_ATA 0x00000101
57
58 #define __HBA_PACKED__ __attribute__((packed))
59
60 typedef unsigned int hba_reg_t;
61
62 #define HBA_CMDH_FIS_LEN(fis_bytes) (((fis_bytes) / 4) & 0x1f)
63 #define HBA_CMDH_ATAPI (1 << 5)
64 #define HBA_CMDH_WRITE (1 << 6)
65 #define HBA_CMDH_PREFETCH (1 << 7)
66 #define HBA_CMDH_R (1 << 8)
67 #define HBA_CMDH_CLR_BUSY (1 << 10)
68 #define HBA_CMDH_PRDT_LEN(entries) (((entries)&0xffff) << 16)
69
70 struct ahci_hba_cmdh
71 {
72     uint16_t options;
73     uint16_t prdt_len;
74     uint32_t transferred_size;
75     uint32_t cmd_table_base;
76     uint32_t reserved[5];
77 } __HBA_PACKED__;
78
79 #define HBA_PRDTE_BYTE_CNT(cnt) ((cnt & 0x3FFFFF) | 0x1)
80
81 struct ahci_hba_prdte
82 {
83     uint32_t data_base;
84     uint32_t reserved[2];
85     uint32_t byte_count;
86 } __HBA_PACKED__;
87
88 struct ahci_hba_cmdt
89 {
90     uint8_t command_fis[64];
91     uint8_t atapi_cmd[16];
92     uint8_t reserved[0x30];
93     struct ahci_hba_prdte entries[3];
94 } __HBA_PACKED__;
95
96 #define SATA_REG_FIS_D2H 0x34
97 #define SATA_REG_FIS_H2D 0x27
98 #define SATA_REG_FIS_COMMAND 0x80
99 #define SATA_LBA_COMPONENT(lba, offset) ((((lba_lo) >> (offset)) & 0xff))
100
101 struct sata_fis_head
102 {
103     uint8_t type;
104     uint8_t options;
105     uint8_t status_cmd;
106     uint8_t feat_err;
107 } __HBA_PACKED__;
108
109 struct sata_reg_fis
110 {
111     struct sata_fis_head head;
112
113     uint8_t lba0, lba8, lba16;
114     uint8_t dev;
115     uint8_t lba24, lba32, lba40;
116     uint8_t reserved1;
117
118     uint16_t count;
119
120     uint8_t reserved[6];
121 } __HBA_PACKED__;
122
123 struct sata_data_fis
124 {
125     struct sata_fis_head head;
126
127     uint8_t data[0];
128 } __HBA_PACKED__;
129
130 struct ahci_device_info
131 {
132     char serial_num[20];
133     char model[40];
134     uint32_t max_lba;
135     uint32_t sector_size;
136     uint8_t wwn[8];
137 };
138
139 struct ahci_port
140 {
141     volatile hba_reg_t* regs;
142     unsigned int ssts;
143     struct ahci_hba_cmdh* cmdlst;
144     struct sata_fis_head* fis;
145     struct ahci_device_info* device_info;
146 };
147
148 struct ahci_hba
149 {
150     volatile hba_reg_t* base;
151     unsigned int ports_num;
152     unsigned int cmd_slots;
153     unsigned int version;
154     struct ahci_port* ports[32];
155 };
156
157 #define ATA_IDENTIFY_DEVICE 0xec
158 #define ATA_IDENTIFY_PAKCET_DEVICE 0xa1
159
160 /**
161  * @brief 初始化AHCI与HBA
162  *
163  */
164 void
165 ahci_init();
166
167 void
168 ahci_list_device();
169
170 int
171 ahci_identify_device(struct ahci_port* port);
172
173 #endif /* __LUNAIX_AHCI_H */