Files
KatauOS/src/disk.c
T

139 lines
3.6 KiB
C

#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
}