Here is the ide code im not sure if it is completed at 100%:
Code: Select all
#include "../include/ide.h"
unsigned char inb (unsigned short _port)
{
unsigned char rv;
__asm__ __volatile__ ("inb %1, %0" : "=a" (rv) : "dN" (_port));
return rv;
}
void outb (unsigned short _port, unsigned char _data)
{
__asm__ __volatile__ ("outb %1, %0" : : "dN" (_port), "a" (_data));
}
#define insl(port, buffer, count) \
__asm__ ("cld; rep; insl" :: "D" (buffer), "d" (port), "c" (count))
void sleep(unsigned long ms){
int msl = 0;
while(msl != ms)msl++;
return;
}
unsigned char ide_read(unsigned char channel, unsigned char reg){
unsigned char result;
if( reg > 0x07 && reg < 0x0C)
ide_write(channel, ATA_REG_CONTROL, 0x80 | channels[channel].nIEN);
if(reg < 0x08)
result = inb(channels[channel].base + reg - 0x00);
else if ( reg < 0x0C )
result = inb(channels[channel].base + reg - 0x06);
else if ( reg < 0x0E )
result = inb(channels[channel].ctrl + reg - 0x0A);
else if ( reg < 0x16 )
result = inb(channels[channel].bmide + reg - 0x0E);
if(reg > 0x07 && reg < 0x0C)
ide_write(channel, ATA_REG_CONTROL, channels[channel].nIEN);
return result;
}
void ide_write(unsigned char channel, unsigned char reg, unsigned char data){
if(reg > 0x07 && reg < 0x0C)
ide_write(channel, ATA_REG_CONTROL, 0x80 | channels[channel].nIEN);
if ( reg < 0x08 )
outb(data, channels[channel].base + reg - 0x00);
else if( reg < 0x0C )
outb(data, channels[channel].base + reg - 0x06);
else if ( reg < 0x0E )
outb(data, channels[channel].ctrl + reg - 0x0A);
else if ( reg < 0x16 )
outb(data, channels[channel].bmide + reg - 0x0E);
if(reg > 0x07 && reg < 0x0C )
ide_write(channel, ATA_REG_CONTROL, channels[channel].nIEN);
}
void ide_read_buffer(unsigned char channel, unsigned char reg, unsigned int buffer, unsigned int quads){
if( reg > 0x07 && reg < 0x0C )
ide_write(channel, ATA_REG_CONTROL, 0x80 | channels[channel].nIEN);
asm("pushw %es; movw %ds, %ax; movw %ax, %es");
if( reg < 0x08 )
insl(channels[channel].base + reg - 0x00, buffer, quads);
else if( reg < 0x0C )
insl(channels[channel].base + reg - 0x06, buffer, quads);
else if( reg < 0x0E )
insl(channels[channel].ctrl + reg - 0x0A, buffer, quads);
else if( reg < 0x016 )
insl(channels[channel].bmide + reg - 0x0E, buffer, quads);
asm("popw %es;");
if( reg > 0x07 && reg < 0x0C )
ide_write(channel, ATA_REG_CONTROL, channels[channel].nIEN);
}
unsigned char ide_polling(unsigned char channel, unsigned int advanced_check){
//Esperamos 4 nanosegundos para BSY
int i = 0;
for( i = 0; i < 4; i++ )
ide_read(channel, ATA_REG_ALTSTATUS);
//Esperar a que BSY este limpio
while(ide_read(channel, ATA_REG_STATUS)& ATA_SR_BSY);
if( advanced_check ){
unsigned char state = ide_read(channel, ATA_REG_STATUS);
//Comprobar si hay errores
if( state & ATA_SR_ERR )
return 2;//Error!
if( state & ATA_SR_DF )
return 1; //Device Fault
if (( state & ATA_SR_DRQ) == 0 )
return 3;//DRQ debe tener valor
}
return 0;//Ningun error
}
unsigned char ide_print_error(unsigned int drive, unsigned char err){
if(err == 0)
return err;
printf("IDE:");
if( err == 1 ) { printf("- Device Fault\n "); err = 19;}
else if ( err == 2 ){
unsigned char st = ide_read(ide_devices[drive].Channel, ATA_REG_ERROR);
if( st & ATA_ER_AMNF ){printf("- No Address Mark found\n "); err = 7;}
if( st & ATA_ER_TK0NF ){printf("- No Media or Media Error\n "); err = 3;}
if( st & ATA_ER_ABRT ){printf("- Command Aborted\n "); err = 20;}
if( st & ATA_ER_MCR ){printf("- No Media or Media Error\n "); err = 3;}
if( st & ATA_ER_IDNF ){printf("- ID Mark not Found\n "); err = 21;}
if( st & ATA_ER_MC){printf("- No Media or Media Error\n "); err = 3;}
if ( st & ATA_ER_UNC){printf("- Uncorrectable Data Error\n "); err = 22;}
if ( st & ATA_ER_BBK){printf("- Bad Sectors\n "); err = 13;}
}else if( err == 3 ){printf("- Reads Nothing\n ");err = 23;}
else if( err == 4 ){printf("- Write Protected\n ");err = 8;}
printf("- [%s %s] %s\n",
(const char *[]){"Primary", "Secondary"}[ide_devices[drive].Channel],
(const char *[]){"Master", "Slave"}[ide_devices[drive].Drive],
ide_devices[drive].Model);
return err;
}
void ide_initialize(unsigned int BAR0, unsigned int BAR1, unsigned int BAR2, unsigned int BAR3, unsigned int BAR4){
int j, i, count = 0;
//1- Detecar puertos de E/S donde esta el controlador IDE:
channels[ATA_PRIMARY ].base = (BAR0 & 0xFFFFFFFC) + 0x1F0 * (!BAR0);
channels[ATA_PRIMARY ].ctrl = (BAR1 & 0xFFFFFFFC) + 0x3F4 * (!BAR1);
channels[ATA_SECONDARY].base = (BAR2 & 0xFFFFFFFC) + 0x170 * (!BAR2);
channels[ATA_SECONDARY].ctrl = (BAR3 & 0xFFFFFFFC) + 0x374 * (!BAR3);
channels[ATA_PRIMARY ].bmide = (BAR4 & 0xFFFFFFFC) + 0; // Bus Master IDE
channels[ATA_SECONDARY].bmide = (BAR4 & 0xFFFFFFFC) + 8; // Bus Master IDE
ide_write(ATA_PRIMARY, ATA_REG_CONTROL, 2);
ide_write(ATA_SECONDARY, ATA_REG_CONTROL, 2);
// 3- Detect ATA-ATAPI Devices:
for (i = 0; i < 2; i++)
for (j = 0; j < 2; j++) {
unsigned char err = 0, type = IDE_ATA, status;
ide_devices[count].Reserved = 0; // Assuming that no drive here.
// (I) Select Drive:
ide_write(i, ATA_REG_HDDEVSEL, 0xA0 | (j << 4)); // Select Drive.
sleep(1); // Wait 1ms for drive select to work.
// (II) Send ATA Identify Command:
ide_write(i, ATA_REG_COMMAND, ATA_CMD_IDENTIFY);
sleep(1); // This function should be implemented in your OS. which waits for 1 ms.
// it is based on System Timer Device Driver.
// (III) Polling:
if (ide_read(i, ATA_REG_STATUS) == 0) continue; // If Status = 0, No Device.
while(1) {
status = ide_read(i, ATA_REG_STATUS);
if ((status & ATA_SR_ERR)) {err = 1; break;} // If Err, Device is not ATA.
if (!(status & ATA_SR_BSY) && (status & ATA_SR_DRQ)) break; // Everything is right.
}
// (IV) Probe for ATAPI Devices:
if (err != 0) {
unsigned char cl = ide_read(i, ATA_REG_LBA1);
unsigned char ch = ide_read(i, ATA_REG_LBA2);
if (cl == 0x14 && ch ==0xEB)
type = IDE_ATAPI;
else if (cl == 0x69 && ch == 0x96)
type = IDE_ATAPI;
else
continue; // Unknown Type (may not be a device).
ide_write(i, ATA_REG_COMMAND, ATA_CMD_IDENTIFY_PACKET);
sleep(1);
}
// (V) Read Identification Space of the Device:
ide_read_buffer(i, ATA_REG_DATA, (unsigned int) ide_buf, 128);
// (VI) Read Device Parameters:
ide_devices[count].Reserved = 1;
ide_devices[count].Type = type;
ide_devices[count].Channel = i;
ide_devices[count].Drive = j;
ide_devices[count].Signature = ((unsigned short *)(ide_buf + ATA_IDENT_DEVICETYPE));
ide_devices[count].Capabilities = ((unsigned short *)(ide_buf + ATA_IDENT_CAPABILITIES));
ide_devices[count].CommandSets = ((unsigned int *)(ide_buf + ATA_IDENT_COMMANDSETS));
// (VII) Get Size:
if (ide_devices[count].CommandSets & (1 << 26))
// Device uses 48-Bit Addressing:
ide_devices[count].Size = ((unsigned int *)(ide_buf + ATA_IDENT_MAX_LBA_EXT));
else
// Device uses CHS or 28-bit Addressing:
ide_devices[count].Size = ((unsigned int *)(ide_buf + ATA_IDENT_MAX_LBA));
// (VIII) String indicates model of device (like Western Digital HDD and SONY DVD-RW...):
int k = 0;
for(k = 0; k < 40; k += 2) {
ide_devices[count].Model[k] = ide_buf[ATA_IDENT_MODEL + k + 1];
ide_devices[count].Model[k + 1] = ide_buf[ATA_IDENT_MODEL + k];}
ide_devices[count].Model[40] = 0; // Terminate String.
count++;
}
// 4- Print Summary:
for (i = 0; i < 4; i++)
if (ide_devices[i].Reserved == 1) {
printf(" Found %s Drive %dGB - %s\n",
(const char *[]){"ATA", "ATAPI"}[ide_devices[i].Type], /* Type */
ide_devices[i].Size / 1024 / 1024 / 2, /* Size */
ide_devices[i].Model);
}
}
Code: Select all
#ifndef __IDE_H__
#define __IDE_H__
#include "kasm.h"
#include "defs.h"
#include "klib.h"
#include "string.h"
#include "io.h"
#include "keyboard.h"
#include "kernel.h"
#include "cpuid.h"
#include "gralprotection.h"
void ide_write(unsigned char channel, unsigned char reg, unsigned char data);
unsigned char ide_read(unsigned char channel, unsigned char reg);
void ide_read_buffer(unsigned char channel, unsigned char reg, unsigned int buffer, unsigned int quads);
unsigned char ide_polling(unsigned char channel, unsigned int advanced_check);
unsigned char ide_print_error(unsigned int drive, unsigned char err);
void ide_initialize(unsigned int BAR0, unsigned int BAR1, unsigned int BAR2, unsigned int BAR3, unsigned int BAR4);
void sleep(unsigned long ms);
#define ATA_SR_BSY 0x80
#define ATA_SR_DRDY 0x40
#define ATA_SR_DF 0x20
#define ATA_SR_DSC 0x10
#define ATA_SR_DRQ 0x08
#define ATA_SR_CORR 0x04
#define ATA_SR_IDX 0x02
#define ATA_SR_ERR 0x01
#define ATA_ER_BBK 0x80
#define ATA_ER_UNC 0x40
#define ATA_ER_MC 0x20
#define ATA_ER_IDNF 0x10
#define ATA_ER_MCR 0x08
#define ATA_ER_ABRT 0x04
#define ATA_ER_TK0NF 0x02
#define ATA_ER_AMNF 0x01
#define ATA_CMD_READ_PIO 0x20
#define ATA_CMD_READ_PIO_EXT 0x24
#define ATA_CMD_READ_DMA 0xC8
#define ATA_CMD_READ_DMA_EXT 0x25
#define ATA_CMD_WRITE_PIO 0x30
#define ATA_CMD_WRITE_PIO_EXT 0x34
#define ATA_CMD_WRITE_DMA 0xCA
#define ATA_CMD_WRITE_DMA_EXT 0x34
#define ATA_CMD_CACHE_FLUSH 0xE7
#define ATA_CMD_CACHE_FLUSH_EXT 0xEA
#define ATA_CMD_PACKET 0xA0
#define ATA_CMD_IDENTIFY_PACKET 0xA1
#define ATA_CMD_IDENTIFY 0xEC
#define ATAPI_CMD_READ 0xA8
#define ATAPI_CMD_EJECT 0x1B
#define ATA_IDENT_DEVICETYPE 0
#define ATA_IDENT_CYLINDERS 2
#define ATA_IDENT_HEADS 6
#define ATA_IDENT_SECTORS 12
#define ATA_IDENT_SERIAL 20
#define ATA_IDENT_MODEL 54
#define ATA_IDENT_CAPABILITIES 98
#define ATA_IDENT_FIELDVALID 106
#define ATA_IDENT_MAX_LBA 120
#define ATA_IDENT_COMMANDSETS 164
#define ATA_IDENT_MAX_LBA_EXT 200
#define IDE_ATA 0x00
#define IDE_ATAPI 0x01
#define ATA_MASTER 0x00
#define ATA_SLAVE 0x01
#define ATA_REG_DATA 0x00
#define ATA_REG_ERROR 0x01
#define ATA_REG_FEATURES 0x01
#define ATA_REG_SECCOUNT0 0x02
#define ATA_REG_LBA0 0x03
#define ATA_REG_LBA1 0x04
#define ATA_REG_LBA2 0x05
#define ATA_REG_HDDEVSEL 0x06
#define ATA_REG_COMMAND 0x07
#define ATA_REG_STATUS 0x07
#define ATA_REG_SECCOUNT1 0x08
#define ATA_REG_LBA3 0x09
#define ATA_REG_LBA4 0x0A
#define ATA_REG_LBA5 0x0B
#define ATA_REG_CONTROL 0x0C
#define ATA_REG_ALTSTATUS 0x0C
#define ATA_REG_DEVADDRESS 0x0D
#define ATA_PRIMARY 0x00
#define ATA_SECONDARY 0x01
#define ATA_READ 0x00
#define ATA_WRITE 0x01
struct IDEChannelRegisters {
unsigned short base;
unsigned short ctrl;
unsigned short bmide;
unsigned char nIEN;
} channels[2];
unsigned char ide_buf[2048] = {0};
unsigned static char ide_irq_invoked = 0;
unsigned static char atapi_packet[12] = {0xA8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
struct ide_device {
unsigned char Reserved;
unsigned char Channel;
unsigned char Drive;
unsigned short Type;
unsigned short Signature;
unsigned short Capabilities;
unsigned int CommandSets;
unsigned int Size;
unsigned char Model[41];
} ide_devices[4];
#endif //__IDE_H__