SayoriOS 0.3.3

atapi.c
1
9 // Super-duper original ATAPI driver by NDRAEY (c) 2023
10 // for SayoriOS
11
12 #include "drv/atapi.h"
13 #include "net/endianess.h"
14 #include "debug/hexview.h"
15
16 // FIXME: Add REQUEST_SENSE command to handle errors.
17
23 bool ata_scsi_status_wait(uint8_t bus) {
24 while (1) {
25 uint8_t status = inb(ATA_PORT(bus) + ATA_REG_COMMAND);
26
27 if ((status & 0x01) == 1)
28 return true; // error
29
30 if (!(status & 0x80) && (status & 0x08))
31 break;
32
33 ide_400ns_delay(ATA_PORT(bus));
34 }
35
36 return false;
37 }
38
47 bool ata_scsi_send(uint16_t bus, bool slave, uint16_t lba_mid_hi, uint8_t command[12]) {
48 // qemu_log("ATAPI SCSI send [%s %s], LBA (MID AND HI): %d",
49 // PRIM_SEC(bus), MAST_SLV(slave), lba_mid_hi);
50
51 ide_select_drive(bus, slave);
52
53 ide_400ns_delay(ATA_PORT(bus));
54
55 outb(ATA_PORT(bus) + ATA_REG_ERROR, 0x00);
56 outb(ATA_PORT(bus) + ATA_REG_LBA1, lba_mid_hi & 0xFF);
57 outb(ATA_PORT(bus) + ATA_REG_LBA2, (lba_mid_hi >> 8) & 0xFF);
58 outb(ATA_PORT(bus) + ATA_REG_COMMAND, ATA_CMD_PACKET);
59
60 ide_400ns_delay(ATA_PORT(bus));
61
62 bool error = ata_scsi_status_wait(bus);
63
64 if(error) {
65 qemu_log("Error");
66 return error;
67 }
68
69 outsw(ATA_PORT(bus) + ATA_REG_DATA, (uint16_t *)command, 6);
70
71 // That's all folks!
72
73 return false;
74 }
75
81 size_t ata_scsi_receive_size_of_transfer(uint16_t bus) {
82 bool error = ata_scsi_status_wait(bus);
83
84 if(error) {
85 qemu_log("ATAPI size receive error");
86 return 0;
87 }
88
89 return (inb(ATA_PORT(bus) + ATA_REG_LBA2) << 8)
90 | inb(ATA_PORT(bus) + ATA_REG_LBA1);
91 }
92
99 void ata_scsi_read_result(uint16_t bus, size_t size, uint16_t* buffer) {
100 insw(ATA_PORT(bus) + ATA_REG_DATA, (uint16_t*)((uint8_t *)buffer), size);
101 }
102
109 size_t atapi_read_size(uint16_t bus, bool slave) {
110 // qemu_log("SIZE REQUEST ON (ints): %d %d", bus, slave);
111 // qemu_log("SIZE REQUEST ON: %s %s", PRIM_SEC(bus), MAST_SLV(slave));
112
113 uint8_t command[12] = {
114 ATAPI_READ_CAPACITY,
115 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
116 };
117
118 ata_scsi_send(bus, slave, 0x0008, command);
119
120 size_t transf_size = ata_scsi_receive_size_of_transfer(bus);
121
122 // qemu_log("Size of transfer is: %d", transf_size);
123
124 if(!transf_size)
125 return 0;
126
127 uint16_t* data = kcalloc(transf_size, 1);
128
129 ata_scsi_read_result(bus, transf_size, data);
130
131 uint32_t* data2 = (uint32_t*)data;
132
133 uint32_t maxlba = data2[0];
134 // uint32_t blocksize = ntohl(data2[1]);
135
136 maxlba = ntohl(maxlba);
137
138 // qemu_log("Blocks: %x; Block size: %x", maxlba, blocksize);
139
140 kfree(data);
141
142 return maxlba;
143 }
144
151 size_t atapi_read_block_size(uint16_t bus, bool slave) {
152 uint8_t command[12] = {
153 ATAPI_READ_CAPACITY,
154 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
155 };
156
157 ata_scsi_send(bus, slave, 0x0008, command);
158
159 size_t transf_size = ata_scsi_receive_size_of_transfer(bus);
160
161 uint16_t* data = (uint16_t*)kcalloc(transf_size, 1);
162
163 ata_scsi_read_result(bus, transf_size, data);
164
165 uint32_t blocksize = ntohl(*((uint32_t*)(data) + 1));
166
167 // qemu_log("Block size is: %d", blocksize);
168
169 kfree(data);
170
171 return blocksize;
172 }
173
182 bool atapi_read_sectors(uint16_t drive, uint8_t *buf, uint32_t lba, size_t sector_count) {
183 uint8_t bus = (drive >> 1) & 1;
184 bool slave = (bool)((drive >> 0) & 1);
185
186 uint8_t command[12] = {
187 ATAPI_CMD_READ, // Command
188 0, // ?
189 (lba >> 0x18) & 0xFF, // LBA
190 (lba >> 0x10) & 0xFF,
191 (lba >> 0x08) & 0xFF,
192 (lba >> 0x00) & 0xFF,
193 (sector_count >> 0x18) & 0xFF, // Sector count
194 (sector_count >> 0x10) & 0xFF,
195 (sector_count >> 0x08) & 0xFF,
196 (sector_count >> 0x00) & 0xFF,
197 0, // ?
198 0 // ?
199 };
200
201 size_t block_size = atapi_read_block_size(bus, slave);
202 bool error = ata_scsi_send(bus, slave, block_size, command);
203
204 if(error) {
205 qemu_log("Error");
206 return error;
207 }
208
209 size_t transf_size = ata_scsi_receive_size_of_transfer(bus);
210
211 if(!transf_size) {
212 qemu_log("Error: Transfer size can't be 0!");
213 return true;
214 }
215
216 for (uint32_t i = 0; i < sector_count; i++) {
217 error = ata_scsi_status_wait(bus);
218
219 if(error)
220 return true;
221
222 size_t size = ata_scsi_receive_size_of_transfer(bus);
223
224 insw(ATA_PORT(bus) + ATA_REG_DATA, (uint16_t*)((uint8_t*)buf + i * block_size), size / 2); // Read it
225 }
226
227 return false;
228 }
229
236 bool atapi_eject(uint8_t bus, bool slave) {
237 // Byte 4:
238 // Bit 0: Start
239 // Bit 1: LoEj
240
241 // LoEj Start Result
242 // 0 0 Stop the Disc
243 // 0 1 Start the Disc
244 // 1 0 Eject Disc
245 // 1 1 Close the Tray (Load the Disc)
246
247 uint8_t command[12] = {
248 ATAPI_CMD_START_STOP, // Command
249 0, 0, 0, // Reserved
250 0, // Stop disc
251 0, 0, 0, 0, 0, 0, 0 // Reserved
252 };
253
254 bool error = ata_scsi_send(bus, slave, 0, command);
255
256 if(error) {
257 qemu_log("Error");
258 }
259
260 command[4] = (1 << 1); // Byte 4: LoEj: Eject disc if possible
261
262 error = ata_scsi_send(bus, slave, 0, command);
263
264 if(error) {
265 qemu_log("Error");
266 }
267
268 return error;
269 }
270
278 atapi_error_code atapi_request_sense(uint8_t bus, bool slave, uint8_t out[18]) {
279 uint8_t command[12] = {
280 ATAPI_CMD_RQ_SENSE, 0, 0, 0,
281 18, // Allocation Length: We need only 18 bytes (mininal respose length)
282 0, 0, 0, 0, 0, 0, 0
283 };
284
285 ata_scsi_send(bus, slave, 18, command);
286
287 ata_scsi_receive_size_of_transfer(bus);
288
289 ata_scsi_read_result(bus, 18, (uint16_t*)out);
290
291 // First byte should be 0xf0
292
293 hexview_advanced(out, 18, 10, false, new_qemu_printf);
294
295 return (atapi_error_code){(out[0] >> 7) & 1, out[2] & 0b00001111, out[12], out[13]};
296 }
297
304 bool atapi_check_media_presence(uint8_t bus, bool slave) {
305 uint8_t command[12] = {
306 ATAPI_CMD_READY, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
307 };
308
309 bool error = ata_scsi_send(bus, slave, 0, command);
310
311 if(error) {
312 qemu_log("Error");
313 return false;
314 }
315
316 uint8_t errorcode[18];
317
318 atapi_error_code error_code = atapi_request_sense(1, 0, errorcode);
319
320 return !(error_code.valid && error_code.sense_key == 0x02 && error_code.sense_code == 0x3A);
321 }
atapi_error_code
Definition: atapi.h:14