Add ATA
This commit is contained in:
parent
92b4f4af3a
commit
f2e32cc0fd
@ -11,6 +11,25 @@
|
|||||||
#define PTR_ALIGN(p, a) ((typeof(p))ALIGN((unsigned long)(p), (a)))
|
#define PTR_ALIGN(p, a) ((typeof(p))ALIGN((unsigned long)(p), (a)))
|
||||||
#define IS_ALIGNED(x, a) (((x) & ((typeof(x))(a)-1)) == 0)
|
#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))
|
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]) + __must_be_array(arr))
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#include "alloc.h"
|
#include "alloc.h"
|
||||||
#include "allocArea.h"
|
#include "allocArea.h"
|
||||||
|
#include "ata.h"
|
||||||
#include "exception.h"
|
#include "exception.h"
|
||||||
#include "gdt.h"
|
#include "gdt.h"
|
||||||
#include "idt.h"
|
#include "idt.h"
|
||||||
@ -152,6 +153,8 @@ void kmain(unsigned long magic, unsigned long addr)
|
|||||||
kthreadCreate("idle ", idleThread, NULL);
|
kthreadCreate("idle ", idleThread, NULL);
|
||||||
|
|
||||||
irqSetRoutine(IRQ_TIMER, pit_handler);
|
irqSetRoutine(IRQ_TIMER, pit_handler);
|
||||||
|
|
||||||
|
ATAInit();
|
||||||
#ifdef RUN_TEST
|
#ifdef RUN_TEST
|
||||||
run_test();
|
run_test();
|
||||||
#endif
|
#endif
|
||||||
|
71
drivers/ata.c
Normal file
71
drivers/ata.c
Normal file
@ -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;
|
||||||
|
}
|
52
drivers/ata.h
Normal file
52
drivers/ata.h
Normal file
@ -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();
|
Loading…
Reference in New Issue
Block a user