mirror of
https://github.com/wichtounet/thor-os.git
synced 2025-09-18 01:01:57 -04:00
Query via IRQs not polling
This commit is contained in:
parent
5d0273ca50
commit
3f15956e87
@ -5,50 +5,9 @@
|
||||
|
||||
namespace {
|
||||
|
||||
bool detected = false;
|
||||
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, 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];
|
||||
|
||||
out_byte(drive.controller + 0x6, drive.drive);
|
||||
sleep_ms(4);
|
||||
drive.present = in_byte(drive.controller + 0x7) & 0x40;
|
||||
}
|
||||
|
||||
detected = true;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t number_of_disks(){
|
||||
if(!detected){
|
||||
detect_disks();
|
||||
}
|
||||
|
||||
return 4;
|
||||
}
|
||||
|
||||
drive_descriptor& drive(uint8_t disk){
|
||||
if(!detected){
|
||||
detect_disks();
|
||||
}
|
||||
|
||||
return drives[disk];
|
||||
}
|
||||
//IDE Controllers
|
||||
#define ATA_PRIMARY 0x1F0
|
||||
#define ATA_SECONDARY 0x170
|
||||
|
||||
// I/O Controllers ports
|
||||
#define ATA_DATA 0
|
||||
@ -74,6 +33,90 @@ drive_descriptor& drive(uint8_t disk){
|
||||
#define ATA_READ_BLOCK 0x20
|
||||
#define ATA_WRITE_BLOCK 0x30
|
||||
|
||||
//Master/Slave on devices
|
||||
#define MASTER_BIT 0
|
||||
#define SLAVE_BIT 1
|
||||
|
||||
bool detected = false;
|
||||
drive_descriptor* drives;
|
||||
|
||||
volatile bool primary_invoked = false;
|
||||
volatile bool secondary_invoked = false;
|
||||
|
||||
void primary_controller_handler(){
|
||||
primary_invoked = true;
|
||||
}
|
||||
|
||||
void secondary_controller_handler(){
|
||||
secondary_invoked = true;
|
||||
}
|
||||
|
||||
void ata_wait_irq_primary(){
|
||||
while(!primary_invoked){
|
||||
__asm__ __volatile__ ("nop");
|
||||
__asm__ __volatile__ ("nop");
|
||||
__asm__ __volatile__ ("nop");
|
||||
__asm__ __volatile__ ("nop");
|
||||
__asm__ __volatile__ ("nop");
|
||||
}
|
||||
|
||||
primary_invoked = false;
|
||||
}
|
||||
|
||||
void ata_wait_irq_secondary(){
|
||||
while(!secondary_invoked){
|
||||
__asm__ __volatile__ ("nop");
|
||||
__asm__ __volatile__ ("nop");
|
||||
__asm__ __volatile__ ("nop");
|
||||
__asm__ __volatile__ ("nop");
|
||||
__asm__ __volatile__ ("nop");
|
||||
}
|
||||
|
||||
secondary_invoked = false;
|
||||
}
|
||||
|
||||
} //end of anonymous namespace
|
||||
|
||||
void detect_disks(){
|
||||
if(!detected){
|
||||
drives = reinterpret_cast<drive_descriptor*>(k_malloc(4 * sizeof(drive_descriptor)));
|
||||
|
||||
drives[0] = {ATA_PRIMARY, 0xE0, false, MASTER_BIT};
|
||||
drives[1] = {ATA_PRIMARY, 0xF0, false, SLAVE_BIT};
|
||||
drives[2] = {ATA_SECONDARY, 0xE0, false, MASTER_BIT};
|
||||
drives[3] = {ATA_SECONDARY, 0xF0, false, SLAVE_BIT};
|
||||
|
||||
for(uint8_t i = 0; i < 4; ++i){
|
||||
auto& drive = drives[i];
|
||||
|
||||
out_byte(drive.controller + 0x6, drive.drive);
|
||||
sleep_ms(4);
|
||||
drive.present = in_byte(drive.controller + 0x7) & 0x40;
|
||||
}
|
||||
|
||||
register_irq_handler<14>(primary_controller_handler);
|
||||
register_irq_handler<15>(secondary_controller_handler);
|
||||
|
||||
detected = true;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t number_of_disks(){
|
||||
if(!detected){
|
||||
detect_disks();
|
||||
}
|
||||
|
||||
return 4;
|
||||
}
|
||||
|
||||
drive_descriptor& drive(uint8_t disk){
|
||||
if(!detected){
|
||||
detect_disks();
|
||||
}
|
||||
|
||||
return drives[disk];
|
||||
}
|
||||
|
||||
//TODO MOVE to anonymous
|
||||
|
||||
static uint8_t wait_for_controller(uint16_t controller, uint8_t mask, uint8_t value, uint16_t timeout){
|
||||
@ -104,6 +147,7 @@ bool select_device(drive_descriptor& drive){
|
||||
}
|
||||
|
||||
bool ata_read_sectors(drive_descriptor& drive, std::size_t start, uint8_t count, void* destination){
|
||||
//Select the device
|
||||
if(!select_device(drive)){
|
||||
return false;
|
||||
}
|
||||
@ -115,6 +159,7 @@ bool ata_read_sectors(drive_descriptor& drive, std::size_t start, uint8_t count,
|
||||
uint8_t ch = (start >> 16) & 0xFF;
|
||||
uint8_t hd = (start >> 24) & 0x0F;
|
||||
|
||||
//Process the command
|
||||
out_byte(controller + ATA_NSECTOR, count);
|
||||
out_byte(controller + ATA_SECTOR, sc);
|
||||
out_byte(controller + ATA_LCYL, cl);
|
||||
@ -124,23 +169,32 @@ bool ata_read_sectors(drive_descriptor& drive, std::size_t start, uint8_t count,
|
||||
|
||||
sleep_ms(1);
|
||||
|
||||
//Wait at most 30 seconds for BSY flag to be cleared
|
||||
if(!wait_for_controller(controller, ATA_STATUS_BSY, 0, 30000)){
|
||||
return false;
|
||||
}
|
||||
|
||||
//Verify if there are errors
|
||||
if(in_byte(controller + ATA_STATUS) & ATA_STATUS_ERR){
|
||||
return false;
|
||||
}
|
||||
|
||||
//Wait the IRQ to happen
|
||||
if(controller == ATA_PRIMARY){
|
||||
ata_wait_irq_primary();
|
||||
} else {
|
||||
ata_wait_irq_secondary();
|
||||
}
|
||||
|
||||
//The device can report an error after the IRQ
|
||||
if(in_byte(controller + ATA_STATUS) & ATA_STATUS_ERR){
|
||||
return false;
|
||||
}
|
||||
|
||||
uint16_t* buffer = reinterpret_cast<uint16_t*>(destination);
|
||||
|
||||
//Read the disk sectors
|
||||
for(uint8_t sector = 0; sector < count; ++sector){
|
||||
sleep_ms(1);
|
||||
|
||||
while (!(in_byte(controller + ATA_STATUS) & ATA_STATUS_DRQ)) {
|
||||
__asm__ __volatile__ ("nop; nop;");
|
||||
}
|
||||
|
||||
for(int i = 0; i < 256; ++i){
|
||||
*buffer++ = in_word(controller + ATA_DATA);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user