SayoriOS 0.3.3

ata_pio.c
1 //
2 // Created by maractus on 03.01.24.
3 //
4
5 #include "drv/disk/ata.h"
6 #include "drv/disk/ata_pio.h"
7 #include "io/ports.h"
8
9 extern ata_drive_t drives[4];
10
11 uint8_t ata_pio_read_sector(uint8_t drive, uint8_t *buf, uint32_t lba) {
12 ON_NULLPTR(buf, {
13 qemu_log("Buffer is nullptr!");
14 return 0;
15 });
16
17 // Only 28-bit LBA supported!
18 lba &= 0x00FFFFFF;
19
20 uint16_t io = 0;
21
22 if(!drives[drive].online) {
23 qemu_log("Attempted read from drive that does not exist.");
24 return 0;
25 }
26
27 ata_set_params(drive, &io, &drive);
28
29 uint8_t cmd = (drive==ATA_MASTER?0xE0:0xF0);
30 uint8_t slavebit = (drive == ATA_MASTER?0x00:0x01);
31
32 outb(io + ATA_REG_HDDEVSEL, (cmd | (slavebit << 4) | (uint8_t)(lba >> 24 & 0x0F)));
33 outb(io + 1, 0x00);
34 outb(io + ATA_REG_SECCOUNT0, 1);
35 outb(io + ATA_REG_LBA0, (uint8_t)((lba)));
36 outb(io + ATA_REG_LBA1, (uint8_t)((lba) >> 8));
37 outb(io + ATA_REG_LBA2, (uint8_t)((lba) >> 16));
38 outb(io + ATA_REG_COMMAND, ATA_CMD_READ_PIO);
39
40 ide_poll(io);
41
42 uint16_t ata_data_reg = io + ATA_REG_DATA;
43
44 uint16_t* buf16 = (uint16_t*)buf;
45
46 for(int i = 0; i < 256; i++) {
47 uint16_t data = inw(ata_data_reg);
48 *(buf16 + i) = data;
49 }
50
51 ide_400ns_delay(io);
52
53 return 1;
54 }
55
56 uint8_t ata_pio_read_sectors_pre(uint8_t drive, uint8_t *buf, uint32_t lba, uint8_t sector_count) {
57 ON_NULLPTR(buf, {
58 qemu_log("Buffer is nullptr!");
59 return 0;
60 });
61
62 // Only 28-bit LBA supported!
63 lba &= 0x00FFFFFF;
64
65 uint16_t io = 0;
66
67 if(!drives[drive].online) {
68 qemu_log("Attempted read from drive that does not exist.");
69 return 0;
70 }
71
72 ata_set_params(drive, &io, &drive);
73
74 uint8_t cmd = (drive==ATA_MASTER?0xE0:0xF0);
75 uint8_t slavebit = (drive == ATA_MASTER?0x00:0x01);
76
77 outb(io + ATA_REG_HDDEVSEL, (cmd | (slavebit << 4) | (uint8_t)(lba >> 24 & 0x0F)));
78 outb(io + 1, 0x00);
79 outb(io + ATA_REG_SECCOUNT0, sector_count);
80 outb(io + ATA_REG_LBA0, (uint8_t)((lba)));
81 outb(io + ATA_REG_LBA1, (uint8_t)((lba) >> 8));
82 outb(io + ATA_REG_LBA2, (uint8_t)((lba) >> 16));
83 outb(io + ATA_REG_COMMAND, ATA_CMD_READ_PIO);
84
85 ide_poll(io);
86
87 uint16_t ata_data_reg = io + ATA_REG_DATA;
88
89 uint16_t* buf16 = (uint16_t*)buf;
90
91 for(int i = 0; i < 256 * sector_count; i++) {
92 uint16_t data = inw(ata_data_reg);
93 *(buf16 + i) = data;
94 }
95
96 ide_400ns_delay(io);
97
98 return 1;
99 }
100
108 uint8_t ata_pio_write_raw_sector(uint8_t drive, const uint8_t *buf, uint32_t lba) {
109 ON_NULLPTR(buf, {
110 qemu_log("Buffer is nullptr!");
111 return 0;
112 });
113
114 // Only 28-bit LBA supported!
115 lba &= 0x00FFFFFF;
116
117 uint16_t io = 0;
118
119 if(!drives[drive].online) {
120 qemu_log("Attempted read from drive that does not exist.");
121 return 0;
122 }
123
124 ata_set_params(drive, &io, &drive);
125
126 uint8_t cmd = (drive==ATA_MASTER?0xE0:0xF0);
127 uint8_t slavebit = (drive == ATA_MASTER?0x00:0x01);
128
129 outb(io + ATA_REG_HDDEVSEL, (cmd | (slavebit << 4) | (uint8_t)((lba >> 24 & 0x0F))));
130 outb(io + 1, 0x00);
131 outb(io + ATA_REG_SECCOUNT0, 1);
132 outb(io + ATA_REG_LBA0, (uint8_t)((lba)));
133 outb(io + ATA_REG_LBA1, (uint8_t)((lba) >> 8));
134 outb(io + ATA_REG_LBA2, (uint8_t)((lba) >> 16));
135 outb(io + ATA_REG_COMMAND, ATA_CMD_WRITE_PIO);
136
137 ide_poll_drq(io);
138
139 for(int i = 0; i < 256; i++) {
140 outw(io + ATA_REG_DATA, *(uint16_t*)(buf + i * 2));
141 }
142
143 ide_400ns_delay(io);
144
145 outb(io + ATA_REG_COMMAND, ATA_CMD_CACHE_FLUSH);
146
147 ide_poll_bsy(io);
148
149 return 1;
150 }
151
152 // UNTESTED
153 void ata_pio_write_sectors(uint8_t drive, uint8_t *buf, uint32_t lba, size_t sectors) {
154 ON_NULLPTR(buf, {
155 qemu_log("Buffer is nullptr!");
156 return;
157 });
158
159 for(size_t i = 0; i < sectors; i++) {
160 ata_pio_write_raw_sector(drive, buf + (i * drives[drive].block_size), lba + i);
161 }
162 }
163
164 // Optimize here - copy content of ata_pio_read_sector and adjust number of sectors
165 // Or modify function to accept `n` sectors
166 void ata_pio_read_sectors(uint8_t drive, uint8_t *buf, uint32_t lba, uint32_t numsects) {
167 ON_NULLPTR(buf, {
168 qemu_log("Buffer is nullptr!");
169 return;
170 });
171
172 uint8_t* rbuf = buf;
173
174 for(size_t i = 0; i < numsects; i++) {
175 ata_pio_read_sector(drive, rbuf, lba + i);
176 rbuf += drives[drive].block_size;
177 }
178 }
179
ata_drive_t
Эта структура определяет каждый ATA диск в системе
Definition: ata.h:102
ata_drive_t::block_size
uint16_t block_size
Адресация по CHS?
Definition: ata.h:111