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 диск в системе
Definition: ata.h:102
uint16_t block_size
Адресация по CHS?
Definition: ata.h:111