ata.c

Commit: cf5aa961 Author: jokerz Raw Copy
1
/* ============================================================================
2
 * Pactor64 — ATA PIO (Programmed I/O) Block Device Driver
3
 * Primary ATA controller: ports 0x1F0-0x1F7, 0x3F6
4
 * ============================================================================ */
5
#include "../include/pactor64.h"
6
7
/* === ATA I/O Ports (Primary Bus) === */
8
#define ATA_DATA        0x1F0   /* Data register (R/W, 16-bit) */
9
#define ATA_ERROR       0x1F1   /* Error register (R) */
10
#define ATA_FEATURES    0x1F1   /* Features register (W) */
11
#define ATA_SECCOUNT    0x1F2   /* Sector count register */
12
#define ATA_LBA_LO      0x1F3   /* LBA low byte */
13
#define ATA_LBA_MID     0x1F4   /* LBA mid byte */
14
#define ATA_LBA_HI      0x1F5   /* LBA high byte */
15
#define ATA_DRIVE_HEAD  0x1F6   /* Drive/Head register */
16
#define ATA_STATUS      0x1F7   /* Status register (R) */
17
#define ATA_COMMAND     0x1F7   /* Command register (W) */
18
#define ATA_ALT_STATUS  0x3F6   /* Alternate status (R) */
19
#define ATA_DEV_CTRL    0x3F6   /* Device control (W) */
20
21
/* === ATA Status Bits === */
22
#define ATA_SR_BSY      0x80    /* Busy */
23
#define ATA_SR_DRDY     0x40    /* Drive ready */
24
#define ATA_SR_DF       0x20    /* Drive write fault */
25
#define ATA_SR_DSC      0x10    /* Drive seek complete */
26
#define ATA_SR_DRQ      0x08    /* Data request ready */
27
#define ATA_SR_CORR     0x04    /* Corrected data */
28
#define ATA_SR_IDX      0x02    /* Index */
29
#define ATA_SR_ERR      0x01    /* Error */
30
31
/* === ATA Commands === */
32
#define ATA_CMD_IDENTIFY    0xEC
33
#define ATA_CMD_READ        0x20
34
#define ATA_CMD_WRITE       0x30
35
36
/* === Global State === */
37
static int ata_drive_exists = 0;
38
static char ata_model[41];
39
static char ata_serial[21];
40
static uint32_t ata_sectors = 0;
41
42
/* === Helper: Wait for drive to be not busy === */
43
static void ata_wait_bsy(void) {
44
    while (inb(ATA_STATUS) & ATA_SR_BSY)
45
        ;
46
}
47
48
/* === Helper: Wait for DRQ (data ready) === */
49
static int ata_wait_drq(void) {
50
    uint8_t status;
51
    /* Wait up to ~1 second (poll ~1M times) */
52
    for (int i = 0; i < 1000000; i++) {
53
        status = inb(ATA_STATUS);
54
        if (status & ATA_SR_ERR) return -1;
55
        if (status & ATA_SR_DF)  return -1;
56
        if (status & ATA_SR_DRQ) return 0;
57
    }
58
    return -1; /* timeout */
59
}
60
61
/* === Helper: 400ns delay via reading alternate status === */
62
static void ata_delay_400ns(void) {
63
    inb(ATA_ALT_STATUS);
64
    inb(ATA_ALT_STATUS);
65
    inb(ATA_ALT_STATUS);
66
    inb(ATA_ALT_STATUS);
67
}
68
69
/* === Initialize ATA controller and detect drive === */
70
void ata_init(void) {
71
    kprintf("[ata] Initializing primary ATA controller...\n");
72
73
    /* Select drive 0 (master) on primary bus */
74
    outb(ATA_DRIVE_HEAD, 0xA0);   /* LBA mode, drive 0 */
75
    ata_delay_400ns();
76
77
    /* Soft reset */
78
    outb(ATA_DEV_CTRL, 0x04);     /* Set SRST bit */
79
    ata_delay_400ns();
80
    outb(ATA_DEV_CTRL, 0x00);     /* Clear SRST */
81
    ata_delay_400ns();
82
83
    /* Wait for drive to be ready */
84
    ata_wait_bsy();
85
86
    /* Check if drive exists by reading status */
87
    uint8_t status = inb(ATA_STATUS);
88
    if (status == 0x00 || status == 0xFF) {
89
        kprintf("[ata] No drive detected (status=0x%x)\n", status);
90
        return;
91
    }
92
93
    kprintf("[ata] Drive detected, status=0x%x\n", status);
94
95
    /* Send IDENTIFY command */
96
    outb(ATA_DRIVE_HEAD, 0xA0);   /* Drive 0, LBA */
97
    outb(ATA_SECCOUNT, 0);
98
    outb(ATA_LBA_LO, 0);
99
    outb(ATA_LBA_MID, 0);
100
    outb(ATA_LBA_HI, 0);
101
    outb(ATA_COMMAND, ATA_CMD_IDENTIFY);
102
103
    /* Wait for response */
104
    ata_delay_400ns();
105
    status = inb(ATA_STATUS);
106
107
    if (status == 0x00) {
108
        kprintf("[ata] Drive does not support IDENTIFY\n");
109
        return;
110
    }
111
112
    /* Wait for BSY to clear */
113
    ata_wait_bsy();
114
115
    /* Check LBA mid/high for ATAPI detection */
116
    if (inb(ATA_LBA_MID) != 0 || inb(ATA_LBA_HI) != 0) {
117
        kprintf("[ata] Not an ATA drive (ATAPI?)\n");
118
        return;
119
    }
120
121
    /* Wait for DRQ */
122
    if (ata_wait_drq() != 0) {
123
        kprintf("[ata] IDENTIFY timeout\n");
124
        return;
125
    }
126
127
    /* Read 256 words (512 bytes) of IDENTIFY data */
128
    uint16_t identify_data[256];
129
    for (int i = 0; i < 256; i++) {
130
        identify_data[i] = inw(ATA_DATA);
131
    }
132
133
    /* Extract model string (words 27-46, 40 bytes) */
134
    for (int i = 0; i < 20; i++) {
135
        ata_model[i * 2]     = (char)(identify_data[27 + i] >> 8);
136
        ata_model[i * 2 + 1] = (char)(identify_data[27 + i] & 0xFF);
137
    }
138
    ata_model[40] = '\0';
139
140
    /* Trim trailing spaces from model */
141
    for (int i = 39; i >= 0 && ata_model[i] == ' '; i--)
142
        ata_model[i] = '\0';
143
144
    /* Extract serial string (words 10-19, 20 bytes) */
145
    for (int i = 0; i < 10; i++) {
146
        ata_serial[i * 2]     = (char)(identify_data[10 + i] >> 8);
147
        ata_serial[i * 2 + 1] = (char)(identify_data[10 + i] & 0xFF);
148
    }
149
    ata_serial[20] = '\0';
150
151
    /* Trim trailing spaces from serial */
152
    for (int i = 19; i >= 0 && ata_serial[i] == ' '; i--)
153
        ata_serial[i] = '\0';
154
155
    /* Capacity: words 60-61 contain total LBA28 sectors */
156
    ata_sectors = ((uint32_t)identify_data[61] << 16) | identify_data[60];
157
    uint32_t capacity_mb = (ata_sectors * 512) / (1024 * 1024);
158
159
    ata_drive_exists = 1;
160
161
    kprintf("[ata] Model:    %s\n", ata_model);
162
    kprintf("[ata] Serial:   %s\n", ata_serial);
163
    kprintf("[ata] Sectors:  %d (%d MB)\n", ata_sectors, capacity_mb);
164
    kprintf("[ata] ATA PIO driver ready.\n");
165
}
166
167
/* === Read sectors using LBA28 PIO === */
168
int ata_read_sectors(uint32_t lba, uint32_t count, void *buf) {
169
    if (!ata_drive_exists) return -1;
170
171
    uint16_t *ptr = (uint16_t *)buf;
172
173
    for (uint32_t i = 0; i < count; i++) {
174
        uint32_t cur_lba = lba + i;
175
176
        ata_wait_bsy();
177
178
        /* Select drive + upper 4 bits of LBA */
179
        outb(ATA_DRIVE_HEAD, 0xE0 | ((cur_lba >> 24) & 0x0F));
180
        ata_delay_400ns();
181
182
        /* Set parameters */
183
        outb(ATA_SECCOUNT, 1);                      /* 1 sector at a time */
184
        outb(ATA_LBA_LO,  (uint8_t)(cur_lba & 0xFF));
185
        outb(ATA_LBA_MID, (uint8_t)((cur_lba >> 8) & 0xFF));
186
        outb(ATA_LBA_HI,  (uint8_t)((cur_lba >> 16) & 0xFF));
187
188
        /* Send READ SECTORS command */
189
        outb(ATA_COMMAND, ATA_CMD_READ);
190
191
        /* Wait for data */
192
        if (ata_wait_drq() != 0) {
193
            kprintf("[ata] Read error at LBA %d\n", cur_lba);
194
            return -1;
195
        }
196
197
        /* Read 256 words (512 bytes) */
198
        for (int w = 0; w < 256; w++) {
199
            ptr[w] = inw(ATA_DATA);
200
        }
201
        ptr += 256;
202
    }
203
204
    return 0;
205
}
206
207
/* === Write sectors using LBA28 PIO === */
208
int ata_write_sectors(uint32_t lba, uint32_t count, const void *buf) {
209
    if (!ata_drive_exists) return -1;
210
211
    const uint16_t *ptr = (const uint16_t *)buf;
212
213
    for (uint32_t i = 0; i < count; i++) {
214
        uint32_t cur_lba = lba + i;
215
216
        ata_wait_bsy();
217
218
        /* Select drive + upper 4 bits of LBA */
219
        outb(ATA_DRIVE_HEAD, 0xE0 | ((cur_lba >> 24) & 0x0F));
220
        ata_delay_400ns();
221
222
        /* Set parameters */
223
        outb(ATA_SECCOUNT, 1);
224
        outb(ATA_LBA_LO,  (uint8_t)(cur_lba & 0xFF));
225
        outb(ATA_LBA_MID, (uint8_t)((cur_lba >> 8) & 0xFF));
226
        outb(ATA_LBA_HI,  (uint8_t)((cur_lba >> 16) & 0xFF));
227
228
        /* Send WRITE SECTORS command */
229
        outb(ATA_COMMAND, ATA_CMD_WRITE);
230
231
        /* Wait for DRQ */
232
        if (ata_wait_drq() != 0) {
233
            kprintf("[ata] Write error at LBA %d\n", cur_lba);
234
            return -1;
235
        }
236
237
        /* Write 256 words (512 bytes) */
238
        for (int w = 0; w < 256; w++) {
239
            outw(ATA_DATA, ptr[w]);
240
        }
241
        ptr += 256;
242
243
        /* Flush: send CACHE FLUSH command */
244
        ata_wait_bsy();
245
        outb(ATA_COMMAND, 0xE7);  /* CACHE FLUSH */
246
        ata_wait_bsy();
247
    }
248
249
    return 0;
250
}
251
252
/* === Check if drive exists === */
253
int ata_is_present(void) {
254
    return ata_drive_exists;
255
}
256
257
/* === Get drive info === */
258
uint32_t ata_get_sector_count(void) {
259
    return ata_sectors;
260
}
261
262
const char *ata_get_model(void) {
263
    return ata_model;
264
}
265
266
const char *ata_get_serial(void) {
267
    return ata_serial;
268
}
269
270
/* === Raw sector read (for ext2 block device callback) === */
271
/* Note: This wraps ata_read_sectors with LBA/sector conversion */
272
int ata_block_read(uint64_t lba, uint32_t count, void *buf) {
273
    return ata_read_sectors((uint32_t)lba, count, buf);
274
}
275