diff --git a/core/kernel.h b/core/kernel.h index 89e78c4..cdb38a8 100644 --- a/core/kernel.h +++ b/core/kernel.h @@ -11,6 +11,25 @@ #define PTR_ALIGN(p, a) ((typeof(p))ALIGN((unsigned long)(p), (a))) #define IS_ALIGNED(x, a) (((x) & ((typeof(x))(a)-1)) == 0) + +#ifdef __CHECKER__ +#define BUILD_BUG_ON_ZERO(e) (0) +#else /* __CHECKER__ */ +/* + * Force a compilation error if condition is true, but also produce a + * result (of value 0 and type int), so the expression can be used + * e.g. in a structure initializer (or where-ever else comma expressions + * aren't permitted). + */ +#define BUILD_BUG_ON_ZERO(e) ((int)(sizeof(struct { int:(-!!(e)); }))) +#endif /* __CHECKER__ */ +/* Are two types/vars the same type (ignoring qualifiers)? */ +#ifndef __same_type +# define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b)) +#endif +/* &a[0] degrades to a pointer: a different type from an array */ +#define __must_be_array(a) BUILD_BUG_ON_ZERO(__same_type((a), &(a)[0])) + #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]) + __must_be_array(arr)) /* diff --git a/core/main.c b/core/main.c index d6268be..44e99a8 100644 --- a/core/main.c +++ b/core/main.c @@ -1,5 +1,6 @@ #include "alloc.h" #include "allocArea.h" +#include "ata.h" #include "exception.h" #include "gdt.h" #include "idt.h" @@ -152,6 +153,8 @@ void kmain(unsigned long magic, unsigned long addr) kthreadCreate("idle ", idleThread, NULL); irqSetRoutine(IRQ_TIMER, pit_handler); + + ATAInit(); #ifdef RUN_TEST run_test(); #endif diff --git a/drivers/ata.c b/drivers/ata.c new file mode 100644 index 0000000..a2e7e01 --- /dev/null +++ b/drivers/ata.c @@ -0,0 +1,71 @@ +#include "ata.h" +#include "io.h" +#include "kernel.h" +#include "klibc.h" + +static struct ata_drive drives[4]; + +int ATADectectType(struct ata_drive *drive) +{ + outb(drive->base + ATA_PIO_DRIVE, 0xA0 | drive->isSlave << 4); + outb(drive->base + ATA_PIO_SEC_COUNT, 0x0); + outb(drive->base + ATA_PIO_LBALO, 0x0); + outb(drive->base + ATA_PIO_LBAMID, 0x0); + outb(drive->base + ATA_PIO_LBAHI, 0x0); + outb(drive->base + ATA_PIO_CMD, ATA_PIO_CMD_IDENTIFY); + unsigned st = inb(drive->base + ATA_PIO_STATUS); + if(st & ATA_PIO_STATUS_DRIVE_BUSY) + goto no_disk; + + inb(drive->dev_ctl); /* Drop the next 4 read to wait */ + inb(drive->dev_ctl); + inb(drive->dev_ctl); + inb(drive->dev_ctl); + unsigned cl = inb(drive->base + ATA_PIO_LBAMID); /* get the "signature bytes" */ + unsigned ch = inb(drive->base + ATA_PIO_LBAHI); + + /* differentiate ATA, ATAPI, SATA and SATAPI */ + if (cl == 0x14 && ch == 0xEB) { + drive->status = ATA_DEV_PATAPI; + return 0; + } + if (cl == 0x69 && ch == 0x96) { + drive->status = ATA_DEV_SATAPI; + return 0; + } + if (cl == 0 && ch == 0) { + drive->status = ATA_DEV_PATA; + return 0; + } + if (cl == 0x3c && ch == 0xc3) { + drive->status = ATA_DEV_SATA; + return 0; + } +no_disk: + drive->status = ATA_DEV_UNKNOWN; + return -1; +} + +int ATAInit() +{ + memset(drives, 0, sizeof(drives)); + drives[0].base = 0x1F0; + drives[0].dev_ctl = 0x3F6; + drives[0].isSlave = 0; + drives[1].base = 0x1F0; + drives[1].dev_ctl = 0x3F6; + drives[1].isSlave = 1; + drives[1].base = 0x170; + drives[1].dev_ctl = 0x376; + drives[1].isSlave = 0; + drives[2].base = 0x170; + drives[2].dev_ctl = 0x376; + drives[2].isSlave = 1; + + for(uint i = 0; i < ARRAY_SIZE(drives); i++){ + if(!ATADectectType(&drives[i])){ + printf("Driver %d detected %d\n", i, drives[i].status); + } + } + return 0; +} diff --git a/drivers/ata.h b/drivers/ata.h new file mode 100644 index 0000000..761b121 --- /dev/null +++ b/drivers/ata.h @@ -0,0 +1,52 @@ +#pragma once +#include "stdarg.h" + +#define ATA_PIO_REG_DATA 0 +#define ATA_PIO_REG_ERR 1 +#define ATA_PIO_REG_FEAT 1 +#define ATA_PIO_SEC_COUNT 2 +#define ATA_PIO_LBALO 3 +#define ATA_PIO_LBAMID 4 +#define ATA_PIO_CYL_LOW 4 +#define ATA_PIO_LBAHI 5 +#define ATA_PIO_CYL_HI 5 +#define ATA_PIO_DRIVE 6 +#define ATA_PIO_STATUS 7 +#define ATA_PIO_CMD 7 + +#define ATA_PIO_CMD_IDENTIFY 0xEC + +#define ATA_PIO_ERROR_ADDR_MARK_NOT_FOUND 0 +#define ATA_PIO_ERROR_TRACK_ZERO_NOT_FOUND 1 +#define ATA_PIO_ERROR_ABORTED 2 +#define ATA_PIO_ERROR_MEDIA_CHANGE_REQUEST 3 +#define ATA_PIO_ERROR_ID_NOT_FOUND 4 +#define ATA_PIO_ERROR_MEDIA_CHANGED 5 +#define ATA_PIO_ERROR_UNCORRECTABLE_DATA 6 +#define ATA_PIO_ERROR_BAD_BLOCK 7 + +#define ATA_PIO_STATUS_REG_ERR (1<<0) +#define ATA_PIO_STATUS_IDX (1<<1) +#define ATA_PIO_STATUS_CORP (1<<2) +#define ATA_PIO_STATUS_DRQ (1<<3) +#define ATA_PIO_STATUS_SRV (1<<4) +#define ATA_PIO_STATUS_DRIVE_FAULT (1<<5) +#define ATA_PIO_STATUS_DRIVE_RDY (1<<6) +#define ATA_PIO_STATUS_DRIVE_BUSY (1<<7) + +#define ATA_DEV_PATA 1 +#define ATA_DEV_SATA 2 +#define ATA_DEV_PATAPI 3 +#define ATA_DEV_SATAPI 4 +#define ATA_DEV_UNKNOWN 0 + +struct ata_drive { + int16_t base; + int16_t dev_ctl; + int status; + int isSlave; +}; + + +int ATADectectType(struct ata_drive* drive); +int ATAInit();