mirror of
https://github.com/wichtounet/thor-os.git
synced 2025-09-19 09:35:15 -04:00
Fix ata_read
This commit is contained in:
parent
c5afd61093
commit
5d0273ca50
@ -7,12 +7,13 @@ struct drive_descriptor {
|
||||
uint16_t controller;
|
||||
uint8_t drive;
|
||||
bool present;
|
||||
uint8_t slave;
|
||||
};
|
||||
|
||||
void detect_disks();
|
||||
uint8_t number_of_disks();
|
||||
drive_descriptor& drive(uint8_t disk);
|
||||
|
||||
void ata_read_sectors(drive_descriptor& drive, std::size_t start, uint8_t count, void* destination);
|
||||
bool ata_read_sectors(drive_descriptor& drive, std::size_t start, uint8_t count, void* destination);
|
||||
|
||||
#endif
|
||||
|
@ -10,14 +10,17 @@ drive_descriptor* drives;
|
||||
|
||||
} //end of anonymous namespace
|
||||
|
||||
#define MASTER_BIT 0
|
||||
#define SLAVE_BIT 1
|
||||
|
||||
void detect_disks(){
|
||||
if(!detected){
|
||||
drives = reinterpret_cast<drive_descriptor*>(k_malloc(4 * sizeof(drive_descriptor)));
|
||||
|
||||
drives[0] = {0x1F0, 0xE0, false};
|
||||
drives[1] = {0x1F0, 0xF0, false};
|
||||
drives[2] = {0x170, 0xE0, false};
|
||||
drives[3] = {0x170, 0xF0, false};
|
||||
drives[0] = {0x1F0, 0xE0, false, MASTER_BIT};
|
||||
drives[1] = {0x1F0, 0xF0, false, SLAVE_BIT};
|
||||
drives[2] = {0x170, 0xE0, false, MASTER_BIT};
|
||||
drives[3] = {0x170, 0xF0, false, SLAVE_BIT};
|
||||
|
||||
for(uint8_t i = 0; i < 4; ++i){
|
||||
auto& drive = drives[i];
|
||||
@ -26,6 +29,8 @@ void detect_disks(){
|
||||
sleep_ms(4);
|
||||
drive.present = in_byte(drive.controller + 0x7) & 0x40;
|
||||
}
|
||||
|
||||
detected = true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -45,34 +50,101 @@ drive_descriptor& drive(uint8_t disk){
|
||||
return drives[disk];
|
||||
}
|
||||
|
||||
void ata_read_sectors(drive_descriptor& drive, std::size_t start, uint8_t count, void* destination){
|
||||
// I/O Controllers ports
|
||||
#define ATA_DATA 0
|
||||
#define ATA_ERROR 1
|
||||
#define ATA_NSECTOR 2
|
||||
#define ATA_SECTOR 3
|
||||
#define ATA_LCYL 4
|
||||
#define ATA_HCYL 5
|
||||
#define ATA_DRV_HEAD 6
|
||||
#define ATA_STATUS 7
|
||||
#define ATA_COMMAND 7
|
||||
#define ATA_DEV_CTL 0x206
|
||||
|
||||
// Status bits
|
||||
#define ATA_STATUS_BSY 0x80
|
||||
#define ATA_STATUS_DRDY 0x40
|
||||
#define ATA_STATUS_DRQ 0x08
|
||||
#define ATA_STATUS_ERR 0x01
|
||||
|
||||
// Commands
|
||||
#define ATA_IDENTIFY 0xEC
|
||||
#define ATAPI_IDENTIFY 0xA1
|
||||
#define ATA_READ_BLOCK 0x20
|
||||
#define ATA_WRITE_BLOCK 0x30
|
||||
|
||||
//TODO MOVE to anonymous
|
||||
|
||||
static uint8_t wait_for_controller(uint16_t controller, uint8_t mask, uint8_t value, uint16_t timeout){
|
||||
uint8_t status;
|
||||
do {
|
||||
status = in_byte(controller + ATA_STATUS);
|
||||
sleep_ms(1);
|
||||
} while ((status & mask) != value && --timeout);
|
||||
|
||||
return timeout;
|
||||
}
|
||||
|
||||
bool select_device(drive_descriptor& drive){
|
||||
auto controller = drive.controller;
|
||||
|
||||
out_byte(controller + 0x6, drive.drive | ((start >> 24) & 0x0F)); //TODO CHECK THIS
|
||||
if(in_byte(controller + ATA_STATUS) & (ATA_STATUS_BSY | ATA_STATUS_DRQ)){
|
||||
return false;
|
||||
}
|
||||
|
||||
out_byte(controller + 0x1, 0x00);
|
||||
out_byte(controller + 0x2, count);
|
||||
out_byte(controller + ATA_DRV_HEAD, 0xA0 | (drive.slave << 4));
|
||||
sleep_ms(1);
|
||||
|
||||
//Send the LBA28 value
|
||||
out_byte(controller + 0x3, static_cast<uint8_t>(start));
|
||||
out_byte(controller + 0x4, static_cast<uint8_t>(start >> 8));
|
||||
out_byte(controller + 0x5, static_cast<uint8_t>(start >> 16));
|
||||
//out_byte(controller + 0x6, drive | ((start >> 24) & 0x0F)); //TODO CHECK THIS
|
||||
if(in_byte(controller + ATA_STATUS) & (ATA_STATUS_BSY | ATA_STATUS_DRQ)){
|
||||
return false;
|
||||
}
|
||||
|
||||
//Send the read sectors command
|
||||
out_byte(controller + 0x7, 0x20);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ata_read_sectors(drive_descriptor& drive, std::size_t start, uint8_t count, void* destination){
|
||||
if(!select_device(drive)){
|
||||
return false;
|
||||
}
|
||||
|
||||
auto controller = drive.controller;
|
||||
|
||||
uint8_t sc = start & 0xFF;
|
||||
uint8_t cl = (start >> 8) & 0xFF;
|
||||
uint8_t ch = (start >> 16) & 0xFF;
|
||||
uint8_t hd = (start >> 24) & 0x0F;
|
||||
|
||||
out_byte(controller + ATA_NSECTOR, count);
|
||||
out_byte(controller + ATA_SECTOR, sc);
|
||||
out_byte(controller + ATA_LCYL, cl);
|
||||
out_byte(controller + ATA_HCYL, ch);
|
||||
out_byte(controller + ATA_DRV_HEAD, (1 << 6) | (drive.slave << 4) | hd);
|
||||
out_byte(controller + ATA_COMMAND, ATA_READ_BLOCK);
|
||||
|
||||
sleep_ms(1);
|
||||
|
||||
if(!wait_for_controller(controller, ATA_STATUS_BSY, 0, 30000)){
|
||||
return false;
|
||||
}
|
||||
|
||||
if(in_byte(controller + ATA_STATUS) & ATA_STATUS_ERR){
|
||||
return false;
|
||||
}
|
||||
|
||||
uint16_t* buffer = reinterpret_cast<uint16_t*>(destination);
|
||||
|
||||
for(uint8_t sector = 0; sector < count; ++sector){
|
||||
sleep_ms(1);
|
||||
|
||||
while (!(in_byte(0x1F7) & 0x08)) {
|
||||
while (!(in_byte(controller + ATA_STATUS) & ATA_STATUS_DRQ)) {
|
||||
__asm__ __volatile__ ("nop; nop;");
|
||||
}
|
||||
|
||||
for(int i = 0; i < 256; ++i){
|
||||
(*buffer++) = in_word(controller + 0x0);
|
||||
*buffer++ = in_word(controller + ATA_DATA);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -259,6 +259,20 @@ void memory_command(const char*){
|
||||
k_printf("Total used memory: %m\n", used_memory());
|
||||
k_printf("Total free memory: %m\n", free_memory());
|
||||
}
|
||||
|
||||
uint16_t* buffer = reinterpret_cast<uint16_t*>(k_malloc(512));
|
||||
|
||||
if(!ata_read_sectors(drive(0), 2048, 1, buffer)){
|
||||
k_print_line("Read failed");
|
||||
} else {
|
||||
for(int i = 0; i < 80; i += 8){
|
||||
k_printf("%h %h %h %h %h %h %h %h\n",
|
||||
buffer[i+0], buffer[i+1], buffer[i+2], buffer[i+3],
|
||||
buffer[i+4], buffer[i+5], buffer[i+6], buffer[i+7]);
|
||||
}
|
||||
|
||||
k_free(reinterpret_cast<std::size_t*>(buffer));
|
||||
}
|
||||
}
|
||||
|
||||
void disks_command(const char*){
|
||||
|
Loading…
x
Reference in New Issue
Block a user