2016-03-18 15:28:00 +00:00
# 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 {
2016-07-24 10:21:12 +00:00
IDE : : IDE ( uint16_t baseport , uint8_t num ) : baseport ( baseport ) , num ( num ) , existent ( 0 ) , numDevices ( 0 ) {
2016-03-18 15:28:00 +00:00
if ( inb ( baseport + CMD ) ! = 0xFF ) { //Does the ATA controller return floating bus?
2016-07-24 10:21:12 +00:00
// 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 + + ;
}
2016-03-18 15:28:00 +00:00
} else {
2016-05-29 06:30:53 +00:00
//err << "ATA device could not be found!\n";
2016-03-18 15:28:00 +00:00
}
outb ( baseport + ALTCMD , 0x40 ) ;
inb ( baseport + CMD ) ;
inb ( baseport + CMD ) ;
inb ( baseport + CMD ) ;
outb ( baseport + ALTCMD , 0x00 ) ;
2016-07-24 10:21:12 +00:00
}
auto IDE : : getDriveCnt ( ) - > int32_t { return numDevices ; }
auto IDE : : getDriveNumByName ( const char * name ) - > int32_t {
2016-03-18 15:28:00 +00:00
if ( strlen ( name ) ! = 5 )
2016-07-24 10:21:12 +00:00
return - 1 ; //Format is ATA[0-3][sm] (regex)
2016-03-18 15:28:00 +00:00
if ( ( name [ 0 ] ! = name [ 2 ] ) | | ( name [ 2 ] ! = ' A ' ) )
2016-07-24 10:21:12 +00:00
return - 1 ;
2016-03-18 15:28:00 +00:00
if ( name [ 1 ] ! = ' T ' )
2016-07-24 10:21:12 +00:00
return - 1 ;
2016-03-18 15:28:00 +00:00
int32_t drivenum = name [ 3 ] - 0x30 ;
if ( drivenum ! = num )
2016-07-24 10:21:12 +00:00
return - 1 ;
2016-03-18 15:28:00 +00:00
if ( ( name [ 4 ] ! = ' s ' ) & & ( name [ 4 ] ! = ' m ' ) )
2016-07-24 10:21:12 +00:00
return - 1 ;
2016-03-18 15:28:00 +00:00
drivenum < < = 1 ;
drivenum + = ( name [ 4 ] = = ' s ' ) ? 1 : 0 ;
if ( ! ( existent & ( 1 < < drivenum ) ) )
2016-07-24 10:21:12 +00:00
return - 1 ;
2016-03-18 15:28:00 +00:00
return drivenum ;
2016-07-24 10:21:12 +00:00
}
auto IDE : : readSector ( int32_t drive , uint64_t sectorNum , uint8_t * buf ) - > void {
2016-03-18 15:28:00 +00:00
if ( drive < ( num * 2 ) | | drive > ( num * 2 + 1 ) )
2016-07-24 10:21:12 +00:00
return ;
2016-03-18 15:28:00 +00:00
if ( ! ( existent & ( 1 < < ( drive - num * 2 ) ) ) )
2016-07-24 10:21:12 +00:00
return ;
2016-07-24 10:48:17 +00:00
while ( inb ( baseport + ALTCMD ) & ATAPIO_BSY ) ;
2016-03-18 15:28:00 +00:00
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 ) ) ;
2016-07-24 10:21:12 +00:00
}
auto IDE : : readSector ( int32_t drive , uint64_t sectorNum , uint32_t num , uint8_t * buf ) - > void {
2016-07-24 10:48:17 +00:00
if ( drive < ( this - > num * 2 ) | | drive > ( this - > num * 2 + 1 ) )
2016-07-24 10:21:12 +00:00
return ;
2016-07-24 10:48:17 +00:00
if ( ! ( existent & ( 1 < < ( drive - this - > num * 2 ) ) ) )
2016-07-24 10:21:12 +00:00
return ;
2016-07-24 10:48:17 +00:00
if ( num = = 0 )
return ;
if ( num > 65536 )
return ;
if ( num = = 65536 )
num = 0 ;
while ( inb ( baseport + ALTCMD ) & ATAPIO_BSY ) ;
outb ( baseport + DRV , 0x40 | ( drive & 1 ) < < 4 ) ;
outb ( baseport + SECTOR_CNT , ( uint8_t ) ( num > > 8 ) ) ;
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 , ( uint8_t ) num ) ;
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 * num ) ) ;
2016-07-24 10:21:12 +00:00
}
auto IDE : : writeSector ( int32_t drive , uint64_t sectorNum , uint8_t * buf ) - > void {
2016-07-24 10:48:17 +00:00
if ( drive < ( this - > num * 2 ) | | drive > ( this - > num * 2 + 1 ) )
2016-07-24 10:21:12 +00:00
return ;
2016-07-24 10:48:17 +00:00
if ( ! ( existent & ( 1 < < ( drive - this - > num * 2 ) ) ) )
2016-07-24 10:21:12 +00:00
return ;
2016-07-24 10:48:17 +00:00
while ( inb ( baseport + ALTCMD ) & ATAPIO_BSY ) ;
outb ( baseport + SECTOR_CNT , ( uint8_t ) ( 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 , ( uint8_t ) 1 ) ;
outb ( baseport + LBAlo , ( uint8_t ) ( sectorNum ) ) ;
outb ( baseport + LBAmid , ( uint8_t ) ( sectorNum > > 8 ) ) ;
outb ( baseport + LBAhi , ( uint8_t ) ( sectorNum > > 16 ) ) ;
outb ( baseport + CMD , 0x34 ) ;
inb ( baseport + CMD ) ;
inb ( baseport + CMD ) ;
inb ( baseport + CMD ) ;
while ( inb ( baseport + CMD ) & ATAPIO_BSY ) ;
for ( int i = 0 ; i < 256 ; i + + ) {
asm volatile ( " outsw; aad " : : " S " ( ( int ) buf ) , " d " ( baseport ) , " a " ( 8787 ) ) ; //The AAD is for creating a short delay between writes, as the compiler might unroll this loop.
}
}
2016-07-24 10:21:12 +00:00
auto IDE : : writeSector ( int32_t drive , uint64_t sectorNum , uint32_t num , uint8_t * buf ) - > void {
2016-07-24 10:48:17 +00:00
if ( drive < ( this - > num * 2 ) | | drive > ( this - > num * 2 + 1 ) )
2016-07-24 10:21:12 +00:00
return ;
2016-07-24 10:48:17 +00:00
if ( ! ( existent & ( 1 < < ( drive - this - > num * 2 ) ) ) )
2016-07-24 10:21:12 +00:00
return ;
2016-07-24 10:48:17 +00:00
if ( num = = 0 )
return ;
if ( num > 65536 )
return ;
if ( num = = 65536 )
num = 0 ;
while ( inb ( baseport + ALTCMD ) & ATAPIO_BSY ) ;
outb ( baseport + SECTOR_CNT , ( uint8_t ) ( num > > 8 ) ) ;
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 , ( uint8_t ) num ) ;
outb ( baseport + LBAlo , ( uint8_t ) ( sectorNum ) ) ;
outb ( baseport + LBAmid , ( uint8_t ) ( sectorNum > > 8 ) ) ;
outb ( baseport + LBAhi , ( uint8_t ) ( sectorNum > > 16 ) ) ;
outb ( baseport + CMD , 0x34 ) ;
inb ( baseport + CMD ) ;
inb ( baseport + CMD ) ;
inb ( baseport + CMD ) ;
while ( inb ( baseport + CMD ) & ATAPIO_BSY ) ;
for ( uint32_t i = 0 ; i < ( num < < 8 ) ; i + + ) {
asm volatile ( " outsw; aad " : : " S " ( ( int ) buf ) , " d " ( baseport ) , " a " ( 8787 ) ) ; //The AAD is for creating a short delay between writes, as the compiler might partially unroll this loop.
}
}
2016-03-18 15:28:00 +00:00
}