ide atapi driver

This commit is contained in:
rami 2024-05-23 00:31:32 -05:00
parent 216e3e59fb
commit e1b6525a7e
11 changed files with 225 additions and 6 deletions

View File

@ -15,7 +15,6 @@ KERNELIMG := $(BUILDDIR)/kernel.bin
QEMUFLAGS = -d int -s \ QEMUFLAGS = -d int -s \
-kernel $(KERNELIMG) \ -kernel $(KERNELIMG) \
-machine q35 \
-device piix3-ide,id=ide -drive id=disk,file=image.img,format=raw,if=none -device ide-hd,drive=disk,bus=ide.0 \ -device piix3-ide,id=ide -drive id=disk,file=image.img,format=raw,if=none -device ide-hd,drive=disk,bus=ide.0 \
.PHONY: all kernel qemu clean docs .PHONY: all kernel qemu clean docs

View File

@ -1,3 +1,6 @@
ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14
ata0-master: type=disk, path="image.img"
ata0-slave: type=cdrom, path=./build/andewOS.iso, status=inserted ata0-slave: type=cdrom, path=./build/andewOS.iso, status=inserted
magic_break: enabled=1 magic_break: enabled=1
boot: cdrom boot: cdrom

109
ide.c Normal file
View File

@ -0,0 +1,109 @@
#include <ide.h>
#include <io.h>
#include <printf.h>
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;
}

View File

@ -1 +1 @@
hi SKIBIDI ANDEW PINGAS BALLS ANDEW

View File

@ -1,6 +1,8 @@
#ifndef RK_IDE_H_ #ifndef RK_IDE_H_
#define RK_IDE_H_ #define RK_IDE_H_
#include <stdint.h>
enum IDE_MODE { enum IDE_MODE {
ISA_ONLY = 0x00, ISA_ONLY = 0x00,
PCI_ONLY = 0x05, PCI_ONLY = 0x05,
@ -12,6 +14,75 @@ enum IDE_MODE {
PCI_CAN_SWITCH_BUS_MASTERING = 0x8f, 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 #endif

View File

@ -6,4 +6,6 @@
uint8_t inportb(uint16_t port); uint8_t inportb(uint16_t port);
void outportb(uint16_t port, uint8_t byte); void outportb(uint16_t port, uint8_t byte);
uint16_t inportw(uint16_t port);
#endif #endif

10
io.c
View File

@ -15,3 +15,13 @@ void outportb(uint16_t port, uint8_t byte) {
: // no output : // no output
: "a" (byte), "d" (port)); : "a" (byte), "d" (port));
} }
uint16_t inportw(uint16_t port) {
uint16_t result;
asm volatile ("in %%dx, %%ax"
: "=a" (result)
: "d" (port));
return result;
}

13
kmain.c
View File

@ -1,3 +1,4 @@
#include "ide.h"
#include <multiboot.h> #include <multiboot.h>
#include <acpi.h> #include <acpi.h>
#include <vga.h> #include <vga.h>
@ -42,7 +43,6 @@ void kmain(struct multiboot_info *info) {
asm volatile ("lidt %0" :: "m"(g_idtr)); asm volatile ("lidt %0" :: "m"(g_idtr));
struct rsdp *found_rsdp = acpi_locate_rsdp(); struct rsdp *found_rsdp = acpi_locate_rsdp();
if (!found_rsdp) { if (!found_rsdp) {
set_color(VGA_COLOR_RED); set_color(VGA_COLOR_RED);
@ -89,9 +89,11 @@ void kmain(struct multiboot_info *info) {
if (fadt->Flags & 1) if (fadt->Flags & 1)
printf("Legacy devices are supported\n"); printf("Legacy devices are supported\n");
else { else {
/*
set_color(VGA_COLOR_RED); set_color(VGA_COLOR_RED);
printf("Legacy devices are not supported. I'm too lazy to support modern devices, bye bye.\n"); printf("Legacy devices are not supported. I'm too lazy to support modern devices, bye bye.\n");
goto halt; goto halt;
*/
} }
pic_remap(PIC_1_START, PIC_2_START); 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 // 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); 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); 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); 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: halt:
for (;;) {} for (;;) {}
} }

View File

@ -1,5 +1,5 @@
%define MAGIC 0x1BADB002 %define MAGIC 0x1BADB002
%define FLAGS 0 %define FLAGS 0b100
; Multiboot v1 Specification ; Multiboot v1 Specification
; https://www.gnu.org/software/grub/manual/multiboot/multiboot.html ; https://www.gnu.org/software/grub/manual/multiboot/multiboot.html
@ -9,6 +9,17 @@ dd MAGIC
dd FLAGS dd FLAGS
dd -(MAGIC + FLAGS) dd -(MAGIC + FLAGS)
dd 0
dd 0
dd 0
dd 0
dd 0
dd 1
dd 80
dd 25
dd 0
section .text section .text
global _start global _start
_start: _start:

7
ps2.c
View File

@ -4,6 +4,7 @@
#include <vga.h> #include <vga.h>
#include <printf.h> #include <printf.h>
#include <strcmp.h> #include <strcmp.h>
#include <ide.h>
#define cpu_relax asm volatile ("pause" ::); #define cpu_relax asm volatile ("pause" ::);
@ -171,6 +172,12 @@ void ps2_handler() {
printf("andew pingas detected"); printf("andew pingas detected");
} else if (strcmp(shell_buffer, "HELLO") == 0) { } else if (strcmp(shell_buffer, "HELLO") == 0) {
printf("hi"); 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 { } else {
printf("unknown command '%s' idiot", shell_buffer); printf("unknown command '%s' idiot", shell_buffer);
} }