#include "../include/disk.h" #include "../include/utils.h" #include "../include/stdio.h" // Define the IDE registers #define IDE_CMD 0x1F7 #define IDE_DATA 0x1F0 #define IDE_SEC_COUNT 0x1F2 #define IDE_SEC_NUM 0x1F3 #define IDE_CYL_LOW 0x1F4 #define IDE_CYL_HIGH 0x1F5 #define IDE_HEAD 0x1F6 #define IDE_STATUS 0x1F7 #define IDE_COMMAND 0x1F7 #define STATUS_ERR 0x01 #define STATUS_BUSY 0x80 #define STATUS_DRQ 0x08 // Define the IDE commands #define IDE_CMD_IDENTIFY 0xEC void ide_send_command(unsigned char command) { __asm__ __volatile__("outb %0, %1" : : "a" (command), "d" (IDE_COMMAND)); } unsigned short ide_read_data() { unsigned short data; //__asm__ __volatile__("inw %1, %0" : "=a" (data) : "d" (IDE_DATA)); __asm__ __volatile__("inw %w1, %0" : "=a" (data) : "Nd" (IDE_DATA)); return data; } unsigned char ide_read_status() { unsigned char status; __asm__ __volatile__("inb %1, %0" : "=a" (status) : "d" (IDE_STATUS)); return status; } uint16_t inw(uint16_t port) { uint16_t value; __asm__ __volatile__("inw %w1, %w0" : "=a" (value) : "Nd" (port)); return value; } //https://wiki.osdev.org/ATA_PIO_Mode#IDENTIFY_command void get_disk_info(disk_info *info) { outportb(0x1F6, 0xA0);//select master drive, 0xA0 - master, 0xB0 - slave //set sectorcount, LBAlo, LBAmid, LBAhi IO ports to 0 outportb(0x1F2, 0x0); outportb(0x1F3, 0x0); outportb(0x1F4, 0x0); outportb(0x1F5, 0x0); // Send the identify command ide_send_command(IDE_CMD_IDENTIFY);//0xEC uint8_t status = inportb(0x1F7); printf("status is %X\n", status); if(!status) { printf("!status\n"); return; } while((inportb(0x1F7) & STATUS_BUSY) != 0); while(1){ status = inportb(0x1F7); if(status & STATUS_ERR) { printf("ERROR! drive has err set. returning...\n"); return; } if(status & STATUS_DRQ) break; } printf("disk is online\n"); uint8_t lbaMID, lbaHI; lbaMID = inportb(0x1F4); lbaHI = inportb(0x1F5); if(lbaMID != 0 || lbaHI != 0) { printf("ERROR! lbaMID: %X, lbaHI: %X\n", lbaMID, lbaHI); printf("The drive is not ATA\n"); return; } // Read the data unsigned short data[256]; for (int i = 0; i < 256; i++) { data[i] = ide_read_data(); } // Extract the disk information info->cylinders = (data[1] >> 8) | (data[2] << 8); // Cylinder count info->heads = data[6]; // Heads per cylinder info->sectors = data[3]; // Sectors per track } // Function to check if a disk is present int ide_check_disk_present() { // Send the identify command ide_send_command(IDE_CMD_IDENTIFY); // Wait for 1 second for (int i = 0; i < 1000000; i++); // Check the status register unsigned char status; __asm__ __volatile__("inb %1, %0" : "=a" (status) : "d" (IDE_STATUS)); // If the device is not busy and there's no error, it's likely a disk is present if ((status & 0x80) == 0 && (status & 0x01) == 0) { return 1; // Disk present } // If the device is busy, it might be a disk, so let's try again if (status & 0x80) { // Wait for the device to become ready while ((ide_read_status() & 0x80)!= 0); // Check the status register again __asm__ __volatile__("inb %1, %0" : "=a" (status) : "d" (IDE_STATUS)); // If the device is not busy and there's no error, it's likely a disk is present if ((status & 0x80) == 0 && (status & 0x01) == 0) { return 1; // Disk present } } return 0; // No disk present }