From e1b6525a7e9cb6bf08ba93e45ce6515378a868a1 Mon Sep 17 00:00:00 2001 From: rami Date: Thu, 23 May 2024 00:31:32 -0500 Subject: [PATCH] ide atapi driver --- .../clangd/index/kmain.c.9B04FE5F8A3537CE.idx | Bin 1284 -> 3142 bytes Makefile | 1 - bochsrc | 3 + ide.c | 109 ++++++++++++++++++ image.img | 2 +- include/ide.h | 71 ++++++++++++ include/io.h | 2 + io.c | 10 ++ kmain.c | 13 ++- multiboot.asm | 13 ++- ps2.c | 7 ++ 11 files changed, 225 insertions(+), 6 deletions(-) create mode 100644 ide.c diff --git a/.cache/clangd/index/kmain.c.9B04FE5F8A3537CE.idx b/.cache/clangd/index/kmain.c.9B04FE5F8A3537CE.idx index d0e39c97490395a7f17e179c5dc26b88dbec633c..b59c42cc5ffadc4d113d05dfd16d14197988bd88 100644 GIT binary patch literal 3142 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 +#include +#include + +uint16_t ide_select_drive(uint8_t bus, uint8_t drive) { + if (bus == ATA_PRIMARY) { + if (drive == ATA_MASTER) + outportb(ATA_PRIMARY_IO + ATA_REG_HDDEVSEL, 0xA0); + else + outportb(ATA_PRIMARY_IO + ATA_REG_HDDEVSEL, 0xB0); + + return ATA_PRIMARY_IO; + } else { + if (drive == ATA_MASTER) + outportb(ATA_SECONDARY_IO + ATA_REG_HDDEVSEL, 0xA0); + else + outportb(ATA_SECONDARY_IO + ATA_REG_HDDEVSEL, 0xB0); + + return ATA_SECONDARY_IO; + } +} + +uint8_t ide_identify(uint8_t bus, uint8_t drive, uint16_t *ide_buf) { + asm volatile ("cli" ::); + + uint16_t io = ide_select_drive(bus, drive); + // Must zero these registers before sending IDENTIFY command + outportb(io + ATA_REG_SECCOUNT0, 0); + outportb(io + ATA_REG_LBA0, 0); + outportb(io + ATA_REG_LBA1, 0); + outportb(io + ATA_REG_LBA2, 0); + + for (int i = 0; i < 14; i++) + inportb(io + ATA_REG_STATUS); + uint8_t status = inportb(io + ATA_REG_STATUS); + + // Send IDENTIFY command + outportb(io + ATA_REG_COMMAND, ATA_CMD_IDENTIFY); + + status = inportb(io + ATA_REG_STATUS); + // Make sure there are no errors + if (!status) { + printf("Drive does not exist\n"); + asm volatile ("sti" ::); + return 0; + } + + // Poll the drive until it's not busy + while (inportb(io + ATA_REG_STATUS) & ATA_SR_BSY) + asm volatile ("pause" ::); + + if (inportb(io + ATA_REG_LBA1) || inportb(io + ATA_REG_LBA1)) { + printf("Drive is not ATA. wtf?"); + asm volatile ("sti" ::); + return 0; + } + + // Poll until drive is ready for data requests or until an error occurs + status = inportb(io + ATA_REG_STATUS); + while (!(status & ATA_SR_DRQ) && !(status & ATA_SR_ERR)) { + status = inportb(io + ATA_REG_STATUS); + } + + if (status & ATA_SR_ERR) { + printf("DRIVE ERROR\n"); + asm volatile ("sti" ::); + return 0; + } + + printf("%s %s is online. Status: %X\n", bus==ATA_PRIMARY?"Primary":"Secondary", drive==ATA_PRIMARY?"master":"slave", status); + // Read identification space of the device + for (int i = 0; i < 256; i++) { + *(ide_buf + i*2) = inportw(io + ATA_REG_DATA); + } + + asm volatile ("sti" ::); + return 0; +} + +uint8_t ata_read_sector(uint8_t bus, uint8_t drive, uint32_t lba, uint8_t *buf) { + asm volatile ("cli" ::); + uint16_t io = 0; + if (bus == ATA_PRIMARY) { + io = ATA_PRIMARY_IO; + } else { + io = ATA_SECONDARY_IO; + } + + uint8_t cmd = (drive==ATA_MASTER?0xE0:0xF0); + outportb(io + ATA_REG_HDDEVSEL, cmd | (uint8_t)(lba >> 24 & 0x0f)); + outportb(io + 1, 0x00); + outportb(io + ATA_REG_SECCOUNT0, 1); + outportb(io + ATA_REG_LBA0, (uint8_t)((lba))); + outportb(io + ATA_REG_LBA1, (uint8_t)((lba) >> 8)); + outportb(io + ATA_REG_LBA2, (uint8_t)((lba) >> 16)); + outportb(io + ATA_REG_COMMAND, ATA_CMD_READ_PIO); + + + uint8_t status = inportb(io + ATA_REG_STATUS); + while (!(status & ATA_SR_DRQ) && !(status & ATA_SR_ERR)) { + status = inportb(io + ATA_REG_STATUS); + } + + for (int i = 0; i < 256; i++) + *(uint16_t *)(buf + i*2) = inportw(io + ATA_REG_DATA); + + asm volatile ("sti" ::); + return 1; +} diff --git a/image.img b/image.img index 45b983b..0172adc 100644 --- a/image.img +++ b/image.img @@ -1 +1 @@ -hi +SKIBIDI ANDEW PINGAS BALLS ANDEW diff --git a/include/ide.h b/include/ide.h index 603c746..a9f0cad 100644 --- a/include/ide.h +++ b/include/ide.h @@ -1,6 +1,8 @@ #ifndef RK_IDE_H_ #define RK_IDE_H_ +#include + enum IDE_MODE { ISA_ONLY = 0x00, PCI_ONLY = 0x05, @@ -12,6 +14,75 @@ enum IDE_MODE { PCI_CAN_SWITCH_BUS_MASTERING = 0x8f, }; +#define ATA_PRIMARY 0 +#define ATA_SECONDARY 1 +#define ATA_MASTER 0 +#define ATA_SLAVE 1 +#define ATA_PRIMARY_IO 0x1F0 +#define ATA_SECONDARY_IO 0x170 + +#define ATA_PRIMARY_DCR_AS 0x3F6 +#define ATA_SECONDARY_DCR_AS 0x376 + +#define ATA_PRIMARY_IRQ 14 +#define ATA_SECONDARY_IRQ 15 + +#define ATA_REG_DATA 0x00 +#define ATA_REG_ERROR 0x01 +#define ATA_REG_FEATURES 0x01 +#define ATA_REG_SECCOUNT0 0x02 +#define ATA_REG_LBA0 0x03 +#define ATA_REG_LBA1 0x04 +#define ATA_REG_LBA2 0x05 +#define ATA_REG_HDDEVSEL 0x06 +#define ATA_REG_COMMAND 0x07 +#define ATA_REG_STATUS 0x07 +#define ATA_REG_SECCOUNT1 0x08 +#define ATA_REG_LBA3 0x09 +#define ATA_REG_LBA4 0x0A +#define ATA_REG_LBA5 0x0B +#define ATA_REG_CONTROL 0x0C +#define ATA_REG_ALTSTATUS 0x0C +#define ATA_REG_DEVADDRESS 0x0D + +#define ATA_CMD_READ_PIO 0x20 +#define ATA_CMD_READ_PIO_EXT 0x24 +#define ATA_CMD_READ_DMA 0xC8 +#define ATA_CMD_READ_DMA_EXT 0x25 +#define ATA_CMD_WRITE_PIO 0x30 +#define ATA_CMD_WRITE_PIO_EXT 0x34 +#define ATA_CMD_WRITE_DMA 0xCA +#define ATA_CMD_WRITE_DMA_EXT 0x35 +#define ATA_CMD_CACHE_FLUSH 0xE7 +#define ATA_CMD_CACHE_FLUSH_EXT 0xEA +#define ATA_CMD_PACKET 0xA0 +#define ATA_CMD_IDENTIFY_PACKET 0xA1 +#define ATA_CMD_IDENTIFY 0xEC + +#define ATA_SR_BSY 0x80 // Busy +#define ATA_SR_DRDY 0x40 // Drive ready +#define ATA_SR_DF 0x20 // Drive write fault +#define ATA_SR_DSC 0x10 // Drive seek complete +#define ATA_SR_DRQ 0x08 // Data request ready +#define ATA_SR_CORR 0x04 // Corrected data +#define ATA_SR_IDX 0x02 // Index +#define ATA_SR_ERR 0x01 // Error + +#define ATA_IDENT_DEVICETYPE 0 +#define ATA_IDENT_CYLINDERS 2 +#define ATA_IDENT_HEADS 6 +#define ATA_IDENT_SECTORS 12 +#define ATA_IDENT_SERIAL 20 +#define ATA_IDENT_MODEL 54 +#define ATA_IDENT_CAPABILITIES 98 +#define ATA_IDENT_FIELDVALID 106 +#define ATA_IDENT_MAX_LBA 120 +#define ATA_IDENT_COMMANDSETS 164 +#define ATA_IDENT_MAX_LBA_EXT 200 + +uint16_t ide_select_drive(uint8_t bus, uint8_t drive); +uint8_t ide_identify(uint8_t bus, uint8_t drive, uint16_t *ide_buf); +uint8_t ata_read_sector(uint8_t bus, uint8_t drive, uint32_t lba, uint8_t *buf); #endif diff --git a/include/io.h b/include/io.h index 27ac7f2..ea0e883 100644 --- a/include/io.h +++ b/include/io.h @@ -6,4 +6,6 @@ uint8_t inportb(uint16_t port); void outportb(uint16_t port, uint8_t byte); +uint16_t inportw(uint16_t port); + #endif diff --git a/io.c b/io.c index e3dc4ad..207ee25 100644 --- a/io.c +++ b/io.c @@ -15,3 +15,13 @@ void outportb(uint16_t port, uint8_t byte) { : // no output : "a" (byte), "d" (port)); } + +uint16_t inportw(uint16_t port) { + uint16_t result; + + asm volatile ("in %%dx, %%ax" + : "=a" (result) + : "d" (port)); + + return result; +} diff --git a/kmain.c b/kmain.c index 2b0a890..0340b55 100644 --- a/kmain.c +++ b/kmain.c @@ -1,3 +1,4 @@ +#include "ide.h" #include #include #include @@ -42,7 +43,6 @@ void kmain(struct multiboot_info *info) { asm volatile ("lidt %0" :: "m"(g_idtr)); - struct rsdp *found_rsdp = acpi_locate_rsdp(); if (!found_rsdp) { set_color(VGA_COLOR_RED); @@ -89,9 +89,11 @@ void kmain(struct multiboot_info *info) { if (fadt->Flags & 1) printf("Legacy devices are supported\n"); else { + /* set_color(VGA_COLOR_RED); printf("Legacy devices are not supported. I'm too lazy to support modern devices, bye bye.\n"); goto halt; + */ } pic_remap(PIC_1_START, PIC_2_START); // ACPI version 1.0 is so old that we assume that our PC supports the 8042 ps/2 controller @@ -108,11 +110,16 @@ void kmain(struct multiboot_info *info) { printf("Looks like you are using PCIe- Found MCFG at 0x%x\n", mcfg); struct pci_config_space *ide = pcie_find_device(mcfg, MASS_STORAGE_CONTROLLER, IDE_INTERFACE); - if (ide) printf("IDE controller detected. Program Interface: %X\n", ide->program_interface); + if (ide) { + printf("IDE controller detected. Program Interface: %X\n", ide->program_interface); + + uint16_t ide_buf[256] = {0}; + ide_identify(ATA_PRIMARY, ATA_MASTER, ide_buf); + } } set_color(VGA_COLOR_WHITE); - printf("You are now being dropped into a kernel shell\n$ "); + printf("\nYou are now being dropped into a kernel shell\n$ "); halt: for (;;) {} } diff --git a/multiboot.asm b/multiboot.asm index 9eb1e4f..0d9d1a3 100644 --- a/multiboot.asm +++ b/multiboot.asm @@ -1,5 +1,5 @@ %define MAGIC 0x1BADB002 -%define FLAGS 0 +%define FLAGS 0b100 ; Multiboot v1 Specification ; https://www.gnu.org/software/grub/manual/multiboot/multiboot.html @@ -9,6 +9,17 @@ dd MAGIC dd FLAGS dd -(MAGIC + FLAGS) +dd 0 +dd 0 +dd 0 +dd 0 +dd 0 + +dd 1 +dd 80 +dd 25 +dd 0 + section .text global _start _start: diff --git a/ps2.c b/ps2.c index ed62678..2f0b990 100644 --- a/ps2.c +++ b/ps2.c @@ -4,6 +4,7 @@ #include #include #include +#include #define cpu_relax asm volatile ("pause" ::); @@ -171,6 +172,12 @@ void ps2_handler() { printf("andew pingas detected"); } else if (strcmp(shell_buffer, "HELLO") == 0) { printf("hi"); + } else if (strcmp(shell_buffer, "READ") == 0) { + uint8_t sector[512] = {0}; + ata_read_sector(ATA_PRIMARY, ATA_MASTER, 0, sector); + for (int i = 0; i < 512; i++) { + _putchar(sector[i]); + } } else { printf("unknown command '%s' idiot", shell_buffer); }