ide atapi driver
This commit is contained in:
parent
216e3e59fb
commit
e1b6525a7e
Binary file not shown.
1
Makefile
1
Makefile
|
@ -15,7 +15,6 @@ KERNELIMG := $(BUILDDIR)/kernel.bin
|
|||
|
||||
QEMUFLAGS = -d int -s \
|
||||
-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 \
|
||||
|
||||
.PHONY: all kernel qemu clean docs
|
||||
|
|
3
bochsrc
3
bochsrc
|
@ -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
|
||||
magic_break: enabled=1
|
||||
boot: cdrom
|
||||
|
|
109
ide.c
Normal file
109
ide.c
Normal 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;
|
||||
}
|
|
@ -1,6 +1,8 @@
|
|||
#ifndef RK_IDE_H_
|
||||
#define RK_IDE_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
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
|
||||
|
|
|
@ -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
|
||||
|
|
10
io.c
10
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;
|
||||
}
|
||||
|
|
13
kmain.c
13
kmain.c
|
@ -1,3 +1,4 @@
|
|||
#include "ide.h"
|
||||
#include <multiboot.h>
|
||||
#include <acpi.h>
|
||||
#include <vga.h>
|
||||
|
@ -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 (;;) {}
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
|
|
7
ps2.c
7
ps2.c
|
@ -4,6 +4,7 @@
|
|||
#include <vga.h>
|
||||
#include <printf.h>
|
||||
#include <strcmp.h>
|
||||
#include <ide.h>
|
||||
|
||||
#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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user