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 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))
|
||||
|
||||
/*
|
||||
|
@ -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
|
||||
|
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