Max OS 0.3
Loading...
Searching...
No Matches
ata.cpp
Go to the documentation of this file.
1
9#include <drivers/disk/ata.h>
10
11using namespace MaxOS;
12using namespace MaxOS::common;
13using namespace MaxOS::hardwarecommunication;
14using namespace MaxOS::drivers;
15using namespace MaxOS::drivers::disk;
16
24 : m_data_port(port_base),
25 m_error_port(port_base + 1),
26 m_sector_count_port(port_base + 2),
27 m_LBA_low_port(port_base + 3),
28 m_LBA_mid_port(port_base + 4),
29 m_LBA_high_Port(port_base + 5),
30 m_device_port(port_base + 6),
31 m_command_port(port_base + 7),
32 m_control_port(port_base + 0x206),
33 m_is_master(master) {
34
35}
36
37AdvancedTechnologyAttachment::~AdvancedTechnologyAttachment() = default;
38
45
46 // Select the device (master or slave)
47 m_device_port.write(m_is_master ? 0xA0 : 0xB0);
48
49 // Reset the High Order Byte
50 m_control_port.write(0);
51
52 // Check if the master is present
53 m_device_port.write(0xA0);
54 uint8_t status = m_command_port.read();
55 if (status == 0xFF) {
56 Logger::WARNING() << "ATA Device: Invalid status";
57 return false;
58 }
59
60 // Select the device (master or slave)
61 m_device_port.write(m_is_master ? 0xA0 : 0xB0);
62
63 // Clear the ports
64 m_sector_count_port.write(0);
65 m_LBA_low_port.write(0);
66 m_LBA_mid_port.write(0);
67 m_LBA_high_Port.write(0);
68
69 // Check if the device is present
70 m_command_port.write(0x0EC);
71 status = m_command_port.read();
72 if (status == 0x00)
73 return false;
74
75 // Wait for the device to be ready or for an error to occur
76 while (((status & 0x80) == 0x80) && ((status & 0x01) != 0x01))
77 status = m_command_port.read();
78
79 //Check for any errors
80 if (status & 0x01) {
81 Logger::WARNING() << "ATA Device: Error reading status\n";
82 return false;
83 }
84
85 // Read the rest of the data as a whole sector needs to be read (force the compiler to do so)
86 for (uint16_t i = 0; i < 256; ++i) {
87 volatile uint16_t data = m_data_port.read();
88 (void) data;
89 }
90
91
92 // Device is present and ready
93 return true;
94}
95
104
105 // Don't allow reading more than a sector
106 if (sector & 0xF0000000 || amount > m_bytes_per_sector)
107 return;
108
109 // Select the device (master or slave)
110 m_device_port.write((m_is_master ? 0xE0 : 0xF0) | ((sector & 0x0F000000) >> 24));
111
112 // Device is busy @todo yield
113 while ((m_command_port.read() & 0x80) != 0);
114
115 // Reset the device
116 m_error_port.write(0);
117 m_sector_count_port.write(1);
118
119 // Split the sector into the ports
120 m_LBA_low_port.write(sector & 0x000000FF);
121 m_LBA_mid_port.write((sector & 0x0000FF00) >> 8);
122 m_LBA_high_Port.write((sector & 0x00FF0000) >> 16);
123
124 // Tell the device to prepare for reading
125 m_command_port.write(0x20);
126
127 // Make sure the device is there
128 uint8_t status = m_command_port.read();
129 if (status == 0x00)
130 return;
131
132 // Wait for the device to be ready or for an error to occur @todo Userspace block here
133 while (((status & 0x80) == 0x80) && ((status & 0x01) != 0x01))
134 status = m_command_port.read();
135
136 //Check for any errors
137 if (status & 0x01)
138 return;
139
140 for (size_t i = 0; i < amount; i += 2) {
141
142 // Read from the disk (2 bytes) and store the first byte
143 uint16_t read_data = m_data_port.read();
144 data_buffer->write(read_data & 0x00FF);
145
146 // Place the second byte in the array if there is one
147 if (i + 1 < amount)
148 data_buffer->write((read_data >> 8) & 0x00FF);
149 }
150
151 // Read the remaining bytes as a full sector has to be read
152 for (uint16_t i = amount + (amount % 2); i < m_bytes_per_sector; i += 2)
153 m_data_port.read();
154}
155
164
165 // Don't allow writing more than a sector
166 if (sector > 0x0FFFFFFF || count > m_bytes_per_sector)
167 return;
168
169 // Select the device (master or slave)
170 m_device_port.write(m_is_master ? 0xE0 : 0xF0 | ((sector & 0x0F000000) >> 24));
171
172 // Device is busy @todo YIELD
173 while ((m_command_port.read() & 0x80) != 0);
174
175 // Reset the device
176 m_error_port.write(0);
177 m_sector_count_port.write(1);
178
179 // Split the sector into the ports
180 m_LBA_low_port.write(sector & 0x000000FF);
181 m_LBA_mid_port.write((sector & 0x0000FF00) >> 8);
182 m_LBA_high_Port.write((sector & 0x00FF0000) >> 16);
183
184 // Send the write command
185 m_command_port.write(0x30);
186
187 // Wait for the device be ready writing @todo YIELD
188 uint8_t status = m_command_port.read();
189 while ((status & 0x80) != 0 || (status & 0x08) == 0)
190 status = m_command_port.read();
191
192 // Write the data to the device
193 for (size_t i = 0; i < m_bytes_per_sector; i += 2) {
194
195 uint16_t write_data = data->read();
196
197 // Place the next byte in the array if there is one
198 if (i + 1 < count)
199 write_data |= (uint16_t) (data->read()) << 8;
200
201 m_data_port.write(write_data);
202 }
203
204 // Write the remaining bytes as a full sector has to be written
205 for (size_t i = count + (count % 2); i < m_bytes_per_sector; i += 2)
206 m_data_port.write(0x0000);
207
208 // Wait for the device to finish writing @todo YIELD
209 status = m_command_port.read();
210 while ((status & 0x80) != 0 || (status & 0x08) != 0)
211 status = m_command_port.read();
212
213 flush();
214}
215
220
221 // Select the device (master or slave)
222 m_device_port.write(m_is_master ? 0xE0 : 0xF0);
223
224 // Send the flush command
225 m_command_port.write(0xE7);
226
227 // Make sure the device is there
228 uint8_t status = m_command_port.read();
229 if (status == 0x00)
230 return;
231
232 // Wait for the device to be ready or for an error to occur
233 while (((status & 0x80) == 0x80) && ((status & 0x01) != 0x01))
234 status = m_command_port.read();
235
236 // Check for an error
237 if (status & 0x01)
238 return;
239
240 // ...
241}
242
249 return "Advanced Technology Attachment";
250}
251
258 return "IDE";
259}
Driver for the ATA controller, handles the reading and writing of data to the hard drive.
static Logger WARNING()
Gets active logger set to WARNING level.
Definition logger.cpp:205
Wrapper class for a region of bytes in memor in an attempt to add some memory safety....
Definition buffer.h:25
uint8_t read()
Safely reads a byte from the buffer at the current offset.
Definition buffer.cpp:168
Stores the left, top, width and height of a rectangle.
Definition rectangle.h:22
AdvancedTechnologyAttachment(uint16_t port_base, bool master)
Constructor for the AdvancedTechnologyAttachment class.
Definition ata.cpp:23
bool identify()
Identify the ATA device.
Definition ata.cpp:44
string device_name() final
Get the device name.
Definition ata.cpp:248
void flush() final
Flush the cache of the ATA device.
Definition ata.cpp:219
void read(uint32_t sector, common::buffer_t *data_buffer, size_t amount) final
read a sector from the ATA device
Definition ata.cpp:103
string vendor_name() final
Get the vendor name.
Definition ata.cpp:257
void write(uint32_t sector, common::buffer_t *data, size_t count) final
write to a sector on the ATA device
Definition ata.cpp:163
virtual void write(uint16_t data)
write a word to the port
Definition port.cpp:95
virtual uint16_t read()
read a word from the port
Definition port.cpp:105
virtual uint8_t read()
read a byte from the port
Definition port.cpp:51
virtual void write(uint8_t data)
write a byte to the port
Definition port.cpp:41