Fixed the ATA read driver. now exposing the Block device interface to the kernel

This commit is contained in:
Morten Delenk 2016-03-18 16:28:00 +01:00
parent 81e223fc8a
commit 2104685d55
6 changed files with 132 additions and 80 deletions

View file

@ -6,7 +6,7 @@ CPP = $(PREFIX)g++
CC = $(PREFIX)gcc
ASFLAGS = -m32
CFLAGS = -m32 -Wall -fno-stack-protector -nostdinc -Ic_include/ -ffreestanding -std=c11 -fno-builtin -Werror -nostdlib -g -fpie
CPPFLAGS = -m32 -Wall -fno-stack-protector -nostdinc -std=c++14 -Iinclude/ -Ic_include/ -fno-rtti -fno-exceptions -ffreestanding -fno-builtin -Werror -nostdlib -fno-use-cxa-atexit -Wextra -Wno-unused -g -fno-pie
CPPFLAGS = -m32 -Wall -fno-stack-protector -nostdinc -std=c++14 -Iinclude/ -Ic_include/ -fno-rtti -fno-exceptions -ffreestanding -fno-builtin -Werror -nostdlib -fno-use-cxa-atexit -Wextra -Wno-unused -g -fno-pie -Wno-reorder
LDFLAGS = -r -melf_i386

View file

@ -18,78 +18,29 @@
#define DRV 6
#define CMD 7
namespace MTGosHAL {
uint16_t ataports[4]={0x1F0,0x170,0x1E8,0x168};
uint16_t commports[4]={0x3F6,0x376,0x3E6,0x366};
BlockDevice::BlockDevice(): numDevices(0), existent(0) {
for(int i=0;i<4;i++) {
if(inb(ataports[i]+CMD)!=0xFF) {
outb(ataports[i]+DRV, 0xE0);
outb(ataports[i]+LBAlo,0x55);
if(inb(ataports[i]+LBAlo)==0x55) {
existent|=1<<(i<<1);
numDevices++;
}
outb(ataports[i]+DRV, 0xF0);
outb(ataports[i]+LBAlo,0x55);
if(inb(ataports[i]+LBAlo)==0x55) {
existent|=1<<((i<<1)+1);
numDevices++;
}
}
}
if(numDevices==0) {
BlockDevice::BlockDevice(): numDevices(0), ata0(0x1F0,0), ata1(0x170,1), ata2(0x1E8,2), ata3(0x168,3) {
if(getDriveCnt()==0) {
err<<"Not a single device was found!\n";
}
for(int i=0;i<8;i++) {
if(!(existent&(1<<i)))
continue;
outb(commports[i>>1],0x40);
inb(ataports[i>>1]+CMD);
inb(ataports[i>>1]+CMD);
inb(ataports[i>>1]+CMD);
inb(ataports[i>>1]+CMD);
outb(commports[i>>1],0x00);
}
}
auto BlockDevice::getDriveCnt() -> uint8_t {return numDevices;}
auto BlockDevice::getDriveNumByName(const char * name) -> uint8_t {
if(strlen(name)!=5)
return -1; //Format is ATA[0-3][sm] (regex)
if((name[0]!=name[2])||(name[2]!='A'))
return -1;
if(name[1]!='T')
return -1;
uint8_t drivenum=name[3]-0x30;
if(drivenum>3)
return -1;
if((name[4]!='s')&&(name[4]!='m'))
return -1;
drivenum<<=1;
drivenum+=(name[4]=='s')?1:0;
if(!(existent&(1<<drivenum)))
return -1;
return drivenum;
auto BlockDevice::getDriveCnt() -> int32_t {return ata0.getDriveCnt()+ata1.getDriveCnt()+ata2.getDriveCnt()+ata3.getDriveCnt();}
auto BlockDevice::getDriveNumByName(const char * name) -> int32_t {
int32_t tmp;
if((tmp=ata0.getDriveNumByName(name))!=-1)
return tmp;
else if((tmp=ata1.getDriveNumByName(name))!=-1)
return tmp+ata0.getDriveCnt();
else if((tmp=ata2.getDriveNumByName(name))!=-1)
return tmp+ata0.getDriveCnt()+ata1.getDriveCnt();
else if((tmp=ata3.getDriveNumByName(name))!=-1)
return tmp+ata0.getDriveCnt()+ata1.getDriveCnt()+ata2.getDriveCnt();
else return -1;
}
BlockDevice::~BlockDevice() {};
auto BlockDevice::readSector(uint8_t drv, uint64_t sectorNum, uint8_t *buf) -> void {
if(!(existent&(1<<drv)))
return;
outb(ataports[drv>>1]+DRV, 0x40 | (drv&1)<<4);
outb(ataports[drv>>1]+SECTOR_CNT, 0);
outb(ataports[drv>>1]+LBAlo, (uint8_t)(sectorNum>>24));
outb(ataports[drv>>1]+LBAmid, (uint8_t)(sectorNum>>32));
outb(ataports[drv>>1]+LBAhi, (uint8_t)(sectorNum>>40));
outb(ataports[drv>>1]+SECTOR_CNT, 1);
outb(ataports[drv>>1]+LBAlo, (uint8_t)(sectorNum));
outb(ataports[drv>>1]+LBAmid, (uint8_t)(sectorNum>>8));
outb(ataports[drv>>1]+LBAhi, (uint8_t)(sectorNum>>16));
outb(ataports[drv>>1]+CMD, 0x24);
inb(ataports[drv>>1]+CMD);
inb(ataports[drv>>1]+CMD);
inb(ataports[drv>>1]+CMD);
while(inb(ataports[drv>>1]+CMD)&0x80);
uint16_t *bufw=(uint16_t *)buf;
for(int i=0;i<256;i++)
bufw[i]=inb(ataports[drv>>1]);
auto BlockDevice::readSector(int32_t drv, uint64_t sectorNum, uint8_t *buf) -> void {
ata0.readSector(drv, sectorNum, buf);
ata1.readSector(drv, sectorNum, buf);
ata2.readSector(drv, sectorNum, buf);
ata3.readSector(drv, sectorNum, buf);
}
}

View file

@ -0,0 +1,88 @@
#include <base.hpp>
#include <blockdev.hpp>
#include <io.h>
#include <textDISP.hpp>
#include <string.h>
#define ATAPIO_ERR 0x01
#define ATAPIO_DRQ 0x08
#define ATAPIO_SRV 0x10
#define ATAPIO_DF 0x20
#define ATAPIO_RDY 0x40
#define ATAPIO_BSY 0x80
#define DATA 0
#define ATAPI_RESV 1
#define SECTOR_CNT 2
#define LBAlo 3
#define LBAmid 4
#define LBAhi 5
#define DRV 6
#define CMD 7
#define ALTCMD 0x206
namespace MTGosHAL {
IDE::IDE(uint16_t baseport, uint8_t num): baseport(baseport), num(num), existent(0), numDevices(0) {
if(inb(baseport+CMD)!=0xFF) { //Does the ATA controller return floating bus?
// Checking existence of the master
outb(baseport+DRV, 0xE0);
outb(baseport+LBAlo,0x55);
if(inb(baseport+LBAlo)==0x55) {
existent|=1;
numDevices++;
}
// Checking existence of the slave
outb(baseport+DRV, 0xF0);
outb(baseport+LBAlo,0x55);
if(inb(baseport+LBAlo)==0x55) {
existent|=2;
numDevices++;
}
} else {
err << "ATA device could not be found!\n";
}
outb(baseport+ALTCMD,0x40);
inb(baseport+CMD);
inb(baseport+CMD);
inb(baseport+CMD);
outb(baseport+ALTCMD,0x00);
}
auto IDE::getDriveCnt() -> int32_t {return numDevices;}
auto IDE::getDriveNumByName(const char* name) -> int32_t {
if(strlen(name)!=5)
return -1; //Format is ATA[0-3][sm] (regex)
if((name[0]!=name[2])||(name[2]!='A'))
return -1;
if(name[1]!='T')
return -1;
int32_t drivenum=name[3]-0x30;
if(drivenum!=num)
return -1;
if((name[4]!='s')&&(name[4]!='m'))
return -1;
drivenum<<=1;
drivenum+=(name[4]=='s')?1:0;
if(!(existent&(1<<drivenum)))
return -1;
return drivenum;
}
auto IDE::readSector(int32_t drive, uint64_t sectorNum, uint8_t *buf) -> void {
if(drive<(num*2)||drive>(num*2+1))
return;
if(!(existent&(1<<(drive-num*2))))
return;
outb(baseport+DRV, 0x40 | (drive&1)<<4);
outb(baseport+SECTOR_CNT, 0);
outb(baseport+LBAlo, (uint8_t)(sectorNum>>24));
outb(baseport+LBAmid, (uint8_t)(sectorNum>>32));
outb(baseport+LBAhi, (uint8_t)(sectorNum>>40));
outb(baseport+SECTOR_CNT, 1);
outb(baseport+LBAlo, (uint8_t)(sectorNum));
outb(baseport+LBAmid, (uint8_t)(sectorNum>>8));
outb(baseport+LBAhi, (uint8_t)(sectorNum>>16));
outb(baseport+CMD, 0x24);
inb(baseport+CMD);
inb(baseport+CMD);
inb(baseport+CMD);
while(inb(baseport+CMD)&0x80);
uint16_t *bufw=(uint16_t *)buf;
asm volatile ("rep insw" : : "D"((int)bufw),"d"(baseport),"c"(256));
}
}

View file

@ -2,17 +2,34 @@
#define __HAL_BLOCKDEV_HPP
#include <stdint.h>
namespace MTGosHAL {
class IDE {
private:
uint8_t existent; //Bitmap showing which of the up to 2 drives are actually existent.
uint8_t num;
int32_t numDevices;
uint16_t baseport;
IDE() {}
public:
IDE(uint16_t baseport, uint8_t num);
auto getDriveCnt() -> int32_t;
auto getDriveNumByName(const char *) -> int32_t;
auto readSector(int32_t drv, uint64_t sectorNum, uint8_t *buf) -> void; //Has to be at least 512 bytes big!
auto readSectors(int32_t drv, uint64_t sectorNum, uint32_t num, uint8_t *buf) -> void; //Has to be at least num*512 bytes big!
};
class BlockDevice {
private:
uint8_t numDevices;
uint8_t existent; //Bitmap showing which of the up to 8 drives are actually existent.
IDE ata0;
IDE ata1;
IDE ata2;
IDE ata3;
public:
BlockDevice();
~BlockDevice();
auto getDriveCnt() -> uint8_t;
auto getDriveNumByName(const char *) -> uint8_t; //Returns -1 if device is not existent
auto readSector(uint8_t drv, uint64_t sectorNum, uint8_t *buf) -> void; //Has to be at least 512 bytes big!
auto readSectors(uint8_t drv, uint64_t sectorNum, uint32_t num, uint8_t *buf) -> void; //Has to be at least num*512 bytes big!
auto getDriveCnt() -> int32_t;
auto getDriveNumByName(const char *) -> int32_t; //Returns -1 if device is not existent
auto readSector(int32_t drv, uint64_t sectorNum, uint8_t *buf) -> void; //Has to be at least 512 bytes big!
auto readSectors(int32_t drv, uint64_t sectorNum, uint32_t num, uint8_t *buf) -> void; //Has to be at least num*512 bytes big!
};
}

View file

@ -48,7 +48,7 @@ namespace MTGosHAL {
uint16_t* vmem=(uint16_t*)0xB8000;
auto putChar(char c) -> void;
public:
Screen() {
Screen(): fg(FG_color::WHITE), bg(BG_color::BLACK) {
clrscr();
}
template <typename T>

View file

@ -40,11 +40,7 @@ namespace MTGosHAL {
idt.setEntry(48, (void *)((uint32_t)&intr_stub_0+768), SEG_KERNEL, IDT_TRAP_GATE | IDT_SEG_32_BIT | IDT_RING_0 | IDT_USED);
idt.setEntry(8, (void *)((uint32_t)&intr_stub_0+128), SEG_DBL_FAULT, IDT_TASK_GATE | IDT_SEG_32_BIT | IDT_RING_0 | IDT_USED);
idt.apply();
char sec[513];
sec[512]='\0';
disk.readSector(disk.getDriveNumByName("ATA0m"),1,(uint8_t *)sec);
out << sec;
//sti();
sti();
::main();
for(;;);
}