WIP - ATA devices
This commit is contained in:
parent
4bb9021885
commit
8671007f19
2
emul
2
emul
@ -58,7 +58,7 @@ function main() {
|
|||||||
make all || exit 1
|
make all || exit 1
|
||||||
util/build_iso.sh || exit 1
|
util/build_iso.sh || exit 1
|
||||||
echo > serial.log
|
echo > serial.log
|
||||||
emulator="qemu-system-x86_64 -cdrom mittos64.iso -serial file:serial.log -smp 4 ${EMULPARAM[@]}"
|
emulator="qemu-system-x86_64 -hda image.img -cdrom mittos64.iso -boot order=d -serial file:serial.log -smp 4 ${EMULPARAM[@]}"
|
||||||
debugger=$(which x86_64-elf-linux-gdb)
|
debugger=$(which x86_64-elf-linux-gdb)
|
||||||
|
|
||||||
if [[ (-n ${EMULVNC}) ]]; then
|
if [[ (-n ${EMULVNC}) ]]; then
|
||||||
|
23
init/init.c
23
init/init.c
@ -8,29 +8,6 @@ int main(int argc, char **argv)
|
|||||||
(void) argv;
|
(void) argv;
|
||||||
|
|
||||||
|
|
||||||
int fd[2];
|
|
||||||
pipe(fd);
|
|
||||||
|
|
||||||
pid_t childpid = fork();
|
|
||||||
|
|
||||||
if(childpid)
|
|
||||||
{
|
|
||||||
printf("I am parent!\n");
|
|
||||||
close(fd[1]);
|
|
||||||
write(fd[0], "Hi, pipe!\n", 10);
|
|
||||||
close(fd[0]);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
printf("I am child!\n");
|
|
||||||
close(fd[0]);
|
|
||||||
char buffer[255];
|
|
||||||
read(fd[1], buffer, 255);
|
|
||||||
printf("Received string: %s\n", buffer);
|
|
||||||
close(fd[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
for(;;);
|
for(;;);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
#include <syscall.h>
|
#include <syscall.h>
|
||||||
#include <cpuid.h>
|
#include <cpuid.h>
|
||||||
#include <vfs.h>
|
#include <vfs.h>
|
||||||
|
#include <ata.h>
|
||||||
|
|
||||||
int kernel_execve(process_t *p, void *image, char *argv[], char *envp[]);
|
int kernel_execve(process_t *p, void *image, char *argv[], char *envp[]);
|
||||||
int kmain(uint64_t multiboot_magic, void *multiboot_data)
|
int kmain(uint64_t multiboot_magic, void *multiboot_data)
|
||||||
@ -30,10 +31,11 @@ int kmain(uint64_t multiboot_magic, void *multiboot_data)
|
|||||||
|
|
||||||
debug_info("Syscall enabled:%d\n", CPUID_FEATURE_SYSCALL);
|
debug_info("Syscall enabled:%d\n", CPUID_FEATURE_SYSCALL);
|
||||||
|
|
||||||
|
|
||||||
fs_mount(0, "/");
|
fs_mount(0, "/");
|
||||||
fs_mount(&debug_file, "/dev/debug");
|
fs_mount(&debug_file, "/dev/debug");
|
||||||
|
|
||||||
|
ata_init();
|
||||||
|
|
||||||
fs_write(&debug_file, "TESTING DEBUG FILE", 18, 0);
|
fs_write(&debug_file, "TESTING DEBUG FILE", 18, 0);
|
||||||
|
|
||||||
process_t *p1 = process_spawn(0);
|
process_t *p1 = process_spawn(0);
|
||||||
|
155
kernel/drivers/ata.c
Normal file
155
kernel/drivers/ata.c
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
#include <ata.h>
|
||||||
|
#include <ports.h>
|
||||||
|
#include <debug.h>
|
||||||
|
|
||||||
|
ata_drive drives[4] = {
|
||||||
|
{.bus=ATA_PRIMARY, .ms=ATA_MASTER},
|
||||||
|
{.bus=ATA_PRIMARY, .ms=ATA_SLAVE},
|
||||||
|
{.bus=ATA_SECONDARY, .ms=ATA_MASTER},
|
||||||
|
{.bus=ATA_SECONDARY, .ms=ATA_SLAVE}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
int ata_wait_status(int bus)
|
||||||
|
{
|
||||||
|
inb(ATA_STATUS(bus));
|
||||||
|
inb(ATA_STATUS(bus));
|
||||||
|
inb(ATA_STATUS(bus));
|
||||||
|
inb(ATA_STATUS(bus));
|
||||||
|
return inb(ATA_STATUS(bus));
|
||||||
|
}
|
||||||
|
|
||||||
|
int ata_send_command(ata_cmd_t *cmd, int wait)
|
||||||
|
{
|
||||||
|
(void)wait;
|
||||||
|
outb(ATA_DEVICE(cmd->bus), cmd->device | (cmd->lba_sep[3] & 0xF));
|
||||||
|
ata_wait_status(cmd->bus);
|
||||||
|
|
||||||
|
outb(ATA_COUNT(cmd->bus), cmd->count);
|
||||||
|
outb(ATA_LBAL(cmd->bus), cmd->lba_sep[0]);
|
||||||
|
outb(ATA_LBAM(cmd->bus), cmd->lba_sep[1]);
|
||||||
|
outb(ATA_LBAH(cmd->bus), cmd->lba_sep[2]);
|
||||||
|
while(inb(ATA_STATUS(cmd->bus)) & ATA_BSY);
|
||||||
|
outb(ATA_COMMAND(cmd->bus), cmd->command);
|
||||||
|
|
||||||
|
if(!inb(ATA_STATUS(cmd->bus)))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
cmd->status = ata_wait_status(cmd->bus);
|
||||||
|
while((cmd->status = inb(ATA_STATUS(cmd->bus))) & ATA_BSY);
|
||||||
|
if(cmd->wait_status) while(!(cmd->status = inb(ATA_STATUS(cmd->bus)) & (cmd->wait_status | ATA_ERR)));
|
||||||
|
cmd->error = inb(ATA_ERROR(cmd->bus));
|
||||||
|
cmd->count = inb(ATA_COUNT(cmd->bus));
|
||||||
|
cmd->device = inb(ATA_DEVICE(cmd->bus));
|
||||||
|
cmd->lba_sep[0] = inb(ATA_LBAL(cmd->bus));
|
||||||
|
cmd->lba_sep[1] = inb(ATA_LBAM(cmd->bus));
|
||||||
|
cmd->lba_sep[2] = inb(ATA_LBAH(cmd->bus));
|
||||||
|
cmd->lba_sep[3] = 0;
|
||||||
|
|
||||||
|
return cmd->status;
|
||||||
|
}
|
||||||
|
|
||||||
|
void init_drive(ata_drive *drive)
|
||||||
|
{
|
||||||
|
int bus = drive->bus;
|
||||||
|
// Check if the controller exists
|
||||||
|
// by writing a value to it and check
|
||||||
|
// that the same one is returned
|
||||||
|
int v1 = inb(ATA_LBAL(bus));
|
||||||
|
outb(ATA_LBAL(bus), (~v1)&0xFF);
|
||||||
|
int v2 = inb(ATA_LBAL(bus));
|
||||||
|
if(v2 != ((~v1)&0xFF))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Check if the drive exists
|
||||||
|
// by selecting the drive
|
||||||
|
outb(ATA_DEVICE(bus), 0xA0 | drive->ms);
|
||||||
|
if(!(ata_wait_status(bus) & ATA_RDY))
|
||||||
|
return;
|
||||||
|
|
||||||
|
outb(ATA_CONTROL(bus), ATA_SRST);
|
||||||
|
outb(ATA_CONTROL(bus), 0);
|
||||||
|
uint64_t lba = inb(ATA_LBAH(bus))<<16 | inb(ATA_LBAM(bus)) << 8 | inb(ATA_LBAL(bus));
|
||||||
|
|
||||||
|
ata_cmd_t command = {
|
||||||
|
.bus = bus,
|
||||||
|
.device=0xA0 | drive->ms,
|
||||||
|
.command = ATA_CMD_IDENTIFY,
|
||||||
|
.wait_status = ATA_DRQ,
|
||||||
|
};
|
||||||
|
if(lba == ATAPI_LBA_MAGIC)
|
||||||
|
{
|
||||||
|
drive->atapi = 1;
|
||||||
|
command.command = ATA_CMD_IDENTIFY_PACKET;
|
||||||
|
}
|
||||||
|
if(!ata_send_command(&command, 1))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Read IDENTIFY information
|
||||||
|
uint16_t *buf = (void *)&drive->id;
|
||||||
|
for(int i=0; i<256; i++)
|
||||||
|
{
|
||||||
|
buf[i] = inw(ATA_DATA(drive->bus));
|
||||||
|
}
|
||||||
|
|
||||||
|
drive->exists = 1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int ata_read_block(ata_drive *drive, uint64_t lba, void *buffer)
|
||||||
|
{
|
||||||
|
int retries = 5;
|
||||||
|
while(retries)
|
||||||
|
{
|
||||||
|
ata_cmd_t command = {
|
||||||
|
.bus = drive->bus,
|
||||||
|
.count = 1,
|
||||||
|
.lba = lba & 0xFFFFFF,
|
||||||
|
.device = 0xE0 | drive->ms | ((lba >> 24) & 0xF),
|
||||||
|
.command = ATA_CMD_READ_SECTORS,
|
||||||
|
};
|
||||||
|
|
||||||
|
int status = ata_send_command(&command,0);
|
||||||
|
if(status & (ATA_DF | ATA_ERR) || !(status & ATA_DRQ))
|
||||||
|
{
|
||||||
|
retries--;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t *buf = buffer;
|
||||||
|
for(int i=0; i<256; i++)
|
||||||
|
{
|
||||||
|
buf[i] = inw(ATA_DATA(drive->bus));
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
debug_error("Reading disk failed\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ata_write_block(ata_drive *drive, uint64_t lba, void *buffer)
|
||||||
|
{
|
||||||
|
ata_cmd_t command = {
|
||||||
|
.bus = drive->bus,
|
||||||
|
.count = 1,
|
||||||
|
.lba = lba & 0xFFFFFF,
|
||||||
|
.device = 0xE0 | drive->ms | ((lba >> 24) & 0xF),
|
||||||
|
.command = ATA_CMD_WRITE_SECTORS,
|
||||||
|
};
|
||||||
|
ata_send_command(&command, 0);
|
||||||
|
uint16_t *buf = buffer;
|
||||||
|
for(int i=0; i<256; i++)
|
||||||
|
{
|
||||||
|
outw(ATA_DATA(drive->bus), buf[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ata_init()
|
||||||
|
{
|
||||||
|
init_drive(&drives[0]);
|
||||||
|
init_drive(&drives[1]);
|
||||||
|
init_drive(&drives[2]);
|
||||||
|
init_drive(&drives[3]);
|
||||||
|
}
|
101
kernel/include/ata.h
Normal file
101
kernel/include/ata.h
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define ATA_PRIMARY 0x1F0
|
||||||
|
#define ATA_SECONDARY 0x170
|
||||||
|
#define ATA_MASTER 0x00
|
||||||
|
#define ATA_SLAVE 0x10
|
||||||
|
|
||||||
|
// Input to controller
|
||||||
|
#define ATA_FEATURE(x) (x + 1)
|
||||||
|
#define ATA_COUNT(x) (x + 2)
|
||||||
|
#define ATA_LBAL(x) (x + 3)
|
||||||
|
#define ATA_LBAM(x) (x + 4)
|
||||||
|
#define ATA_LBAH(x) (x + 5)
|
||||||
|
#define ATA_DEVICE(x) (x + 6)
|
||||||
|
#define ATA_COMMAND(x) (x + 7)
|
||||||
|
#define ATA_CONTROL(x) (x + 0x206)
|
||||||
|
|
||||||
|
// Output from controller
|
||||||
|
#define ATA_DATA(x) (x + 0)
|
||||||
|
#define ATA_ERROR(x) (x + 1)
|
||||||
|
// COUNT
|
||||||
|
// LBAL
|
||||||
|
// LBAM
|
||||||
|
// LBAH
|
||||||
|
// DEVICE
|
||||||
|
#define ATA_STATUS(x) (x + 7)
|
||||||
|
|
||||||
|
#define ATA_ERR (1<<0)
|
||||||
|
#define ATA_DRQ (1<<3)
|
||||||
|
#define ATA_SRV (1<<4)
|
||||||
|
#define ATA_DF (1<<5)
|
||||||
|
#define ATA_RDY (1<<6)
|
||||||
|
#define ATA_BSY (1<<7)
|
||||||
|
|
||||||
|
#define ATA_nIEN (1<<1)
|
||||||
|
#define ATA_SRST (1<<2)
|
||||||
|
|
||||||
|
#define ATA_CMD_IDENTIFY 0xEC
|
||||||
|
#define ATA_CMD_IDENTIFY_PACKET 0xA1
|
||||||
|
#define ATA_CMD_READ_SECTORS 0x20
|
||||||
|
#define ATA_CMD_WRITE_SECTORS 0x30
|
||||||
|
#define ATA_CMD_PACKET 0xA0
|
||||||
|
|
||||||
|
#define ATAPI_LBA_MAGIC 0xEB1401
|
||||||
|
|
||||||
|
typedef struct ata_drive
|
||||||
|
{
|
||||||
|
int exists;
|
||||||
|
int bus;
|
||||||
|
int ms;
|
||||||
|
int atapi;
|
||||||
|
struct {
|
||||||
|
uint16_t config;
|
||||||
|
uint16_t unused1[9];
|
||||||
|
char serial[20];
|
||||||
|
uint16_t unused2[3];
|
||||||
|
char firmware[8];
|
||||||
|
char model[40];
|
||||||
|
uint8_t unused3;
|
||||||
|
uint8_t sectors_per_interrupt;
|
||||||
|
uint16_t unused4;
|
||||||
|
uint16_t capabilities[2];
|
||||||
|
uint16_t unused5[2];
|
||||||
|
uint16_t validity;
|
||||||
|
uint16_t unused6[3];
|
||||||
|
uint32_t capacity_sectors;
|
||||||
|
uint16_t sectors_per_command;
|
||||||
|
uint32_t capacity_lba28;
|
||||||
|
uint16_t unused7[38];
|
||||||
|
uint64_t capcity_lba48;
|
||||||
|
uint16_t unused8[152];
|
||||||
|
}__attribute__((packed)) id;
|
||||||
|
} ata_drive;
|
||||||
|
|
||||||
|
ata_drive drives[4];
|
||||||
|
|
||||||
|
typedef struct ata_cmd_st
|
||||||
|
{
|
||||||
|
uint16_t bus;
|
||||||
|
union {
|
||||||
|
uint8_t feature;
|
||||||
|
uint8_t error;
|
||||||
|
};
|
||||||
|
uint8_t count;
|
||||||
|
union {
|
||||||
|
uint64_t lba;
|
||||||
|
uint8_t lba_sep[4];
|
||||||
|
};
|
||||||
|
uint8_t device;
|
||||||
|
union {
|
||||||
|
uint8_t command;
|
||||||
|
uint8_t status;
|
||||||
|
};
|
||||||
|
uint8_t wait_status;
|
||||||
|
} ata_cmd_t;
|
||||||
|
|
||||||
|
int ata_read_block(struct ata_drive *drive, uint64_t lba, void *buffer);
|
||||||
|
int ata_write_block(struct ata_drive *drive, uint64_t lba, void *buffer);
|
||||||
|
|
||||||
|
void ata_init();
|
Loading…
x
Reference in New Issue
Block a user