-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathata.c
More file actions
72 lines (61 loc) · 2.32 KB
/
Copy pathata.c
File metadata and controls
72 lines (61 loc) · 2.32 KB
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
#include "types.h"
#define ATA_PRIMARY_DATA 0x1F0
#define ATA_PRIMARY_ERR 0x1F1
#define ATA_PRIMARY_SECCOUNT 0x1F2
#define ATA_PRIMARY_LBA_LO 0x1F3
#define ATA_PRIMARY_LBA_MID 0x1F4
#define ATA_PRIMARY_LBA_HI 0x1F5
#define ATA_PRIMARY_DRIVE_HEAD 0x1F6
#define ATA_PRIMARY_COMM_REGSTAT 0x1F7
static inline uint8_t inb(uint16_t port) {
uint8_t ret;
__asm__ __volatile__ ("inb %1, %0" : "=a"(ret) : "Nd"(port));
return ret;
}
static inline void outb(uint16_t port, uint8_t val) {
__asm__ __volatile__ ("outb %0, %1" : : "a"(val), "Nd"(port));
}
static inline uint16_t inw(uint16_t port) {
uint16_t ret;
__asm__ __volatile__ ("inw %1, %0" : "=a"(ret) : "Nd"(port));
return ret;
}
static inline void outw(uint16_t port, uint16_t val) {
__asm__ __volatile__ ("outw %0, %1" : : "a"(val), "Nd"(port));
}
/**
* @brief Reads a 512-byte sector from disk into memory buffer
* @param lba Logical Block Address (Sector number on disk)
* @param buffer Output memory array (at least 512 bytes)
*/
void ata_read_sector(uint32_t lba, uint8_t* buffer) {
outb(ATA_PRIMARY_DRIVE_HEAD, 0xE0 | ((lba >> 24) & 0x0F));
outb(ATA_PRIMARY_SECCOUNT, 1);
outb(ATA_PRIMARY_LBA_LO, (uint8_t)lba);
outb(ATA_PRIMARY_LBA_MID, (uint8_t)(lba >> 8));
outb(ATA_PRIMARY_LBA_HI, (uint8_t)(lba >> 16));
outb(ATA_PRIMARY_COMM_REGSTAT, 0x20); // 0x20 = Read Sectors Command
// Wait until disk controller is ready (DRQ bit set, BUSY bit clear)
while ((inb(ATA_PRIMARY_COMM_REGSTAT) & 0x88) != 0x08);
// Read 256 16-bit words (512 bytes total)
uint16_t* ptr = (uint16_t*)buffer;
for (int i = 0; i < 256; i++) {
ptr[i] = inw(ATA_PRIMARY_DATA);
}
}
/**
* @brief Writes a 512-byte sector from memory buffer to disk
*/
void ata_write_sector(uint32_t lba, uint8_t* buffer) {
outb(ATA_PRIMARY_DRIVE_HEAD, 0xE0 | ((lba >> 24) & 0x0F));
outb(ATA_PRIMARY_SECCOUNT, 1);
outb(ATA_PRIMARY_LBA_LO, (uint8_t)lba);
outb(ATA_PRIMARY_LBA_MID, (uint8_t)(lba >> 8));
outb(ATA_PRIMARY_LBA_HI, (uint8_t)(lba >> 16));
outb(ATA_PRIMARY_COMM_REGSTAT, 0x30); // 0x30 = Write Sectors Command
while ((inb(ATA_PRIMARY_COMM_REGSTAT) & 0x88) != 0x08);
uint16_t* ptr = (uint16_t*)buffer;
for (int i = 0; i < 256; i++) {
outw(ATA_PRIMARY_DATA, ptr[i]);
}
}