ATA PIO C driver need some help
Posted: Thu Feb 24, 2011 12:34 am
Thanks for the comments below. It now works on a vmware ide device reading and writing. My identify device parsing is, well, correct enough, i get the string and proper number of sectors which is all i need. I hope this helps others.
/////////////////////////assembly in and out ///////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/////////////////////////assembly in and out ///////////////////////////////////////////
Code: Select all
static inline void insw(unsigned short port, void *addr, size_t cnt)
{
__asm volatile("rep; insw"
: "+D" (addr), "+c" (cnt)
: "d" (port)
: "memory");
}
Code: Select all
static inline void outsw(unsigned short port, const void *addr, size_t cnt){
__asm volatile("rep; outsw" : "+S" (addr), "+c" (cnt) : "d" (port));
}
Code: Select all
int read_sector(int LBA) {
int count = 1; //number of sectors to read
char slavebit =0; //0 for master device 1 for slave sets bit 5 in 1f6
int stat;
outb(0x3f6, 0x02); //disable interrupts
outb(0x1F6, (0xE0 | (slavebit << 4) | (LBA >> 24 & 0x0F)));
//waste some time
outb(0x1f1, 0x00);
//set the sector count
outb(0x1f2, (unsigned char)count);
sleep(1);
stat = ide_polling(0, 0);
if(stat != 0)
return stat;
//send the low 8 bits of lbs to 1f3
outb(0x1f3, (unsigned char)LBA);
sleep(1);
stat = ide_polling(0, 0);
if(stat != 0)
return stat;
//send the middle 8 bits to 1f4
outb(0x1f4, (unsigned char)(LBA >> 8));
sleep(1);
stat = ide_polling(0, 0);
if(stat != 0)
return stat;
//send the high 8 to 1f5
outb(0x1f5, (unsigned char)(LBA >> 16));
sleep(1);
stat = ide_polling(0, 0);
if(stat != 0)
return stat;
//issue a read sectors command
outb(0x1f7, 0x20);
sleep(1);
stat = ide_polling(0, 0);
if(stat != 0)
return stat;
//eat 256 words form the buffer
insw(0x1f0, ide_buf, 256);
ide_polling(0,0);
}
Code: Select all
int write_sector(int LBA) {
int i,count = 1; //number of sectors to read
char slavebit =0; //0 for master device 1 for slave sets bit 5 in 1f6
int stat=0;
outb(0x3f6, 0x02); //disable interrupts
outb(0x1F6, (0xE0 | (slavebit << 4) | (LBA >> 24 & 0x0F)));
//waste some time
outb(0x1f1, 0x00);
//set the sector count
outb(0x1f2, (unsigned char)count);
sleep(1);
stat = ide_polling(0, 1);
if(stat == 1 || stat ==2)
printf("error after 1f2 ");
//send the low 8 bits of lbs to 1f3
outb(0x1f3, (unsigned char)LBA);
sleep(1);
stat = ide_polling(0,1);
if(stat == 1 || stat ==2)
printf("error after 1f3 ");
//send the middle 8 bits to 1f4
outb(0x1f4, (unsigned char)(LBA >> 8));
sleep(1);
stat = ide_polling(0, 1);
if(stat == 1 || stat ==2)
printf("error after 1f4 ");
//send the high 8 to 1f5
outb(0x1f5, (unsigned char)(LBA >> 16));
sleep(1);
stat = ide_polling(0, 1);
if(stat == 1 || stat ==2)
printf("error after 1f5 ");
//issue a WRITE sectors command
outb(0x1f7, 0x30);
sleep(1);
stat = ide_polling(0, 1);
if(stat == 1 || stat ==2)
printf("error after write command ");
//output 256 words form the buffer
outsw(0x1f0,outarray, 256);
stat = ide_polling(0, 1);
if(stat == 1 || stat ==2)
printf("error after write data ");
outb(0x1f7, 0xE7); //flush the cache after each write command
ide_polling(0,1);
}