Struggling with IDE driver (PIO with interrupts enabled)
Posted: Sun Jun 26, 2011 10:44 am
Hi
I'm struggling with writing an IDE driver. Tried everything but this thing just doesn't work. I'm using bochs, Please see what the hell i'm doing wrong... this is very frustrating i'm stuck on this.
#defines
The read_sectors function, cmd is the command variable, first_block is the address of the first block.
The following is my ISR, this is being called by an assembly generic ISR handler. This doesn't have any IRET cuz after this ISR handler is over, the control moves back in assembler code which generates the IRET for both primary and slave. So no problem regarding IRET for sure.
The function disk_handler returns early and the status port value i get is 0x51. I'm not sure about the error nor is command aborted so idk what the error is. Please help or let me see any of your code which is working so i can test on bochs if it works.
This is driving me into desperation, would do anything for correct code!
I'm struggling with writing an IDE driver. Tried everything but this thing just doesn't work. I'm using bochs, Please see what the hell i'm doing wrong... this is very frustrating i'm stuck on this.
#defines
Code: Select all
#define PRIMARY_DATA_PORT 0x1F0
#define PRIMARY_ERROR_PORT PRIMARY_DATA_PORT+1
#define PRIMARY_SECTOR_COUNT_PORT PRIMARY_DATA_PORT+2 /*Number of sectors to read/write*/
#define PRIMARY_SECTOR_LBA_LOW_PORT PRIMARY_DATA_PORT+3 /*LBA28/CHS/LBA48 specific.*/
#define PRIMARY_CYLLOW_LBA_MID_PORT PRIMARY_DATA_PORT+4 /*Either Cylinder low for CHS or LBA mid bits*/
#define PRIMARY_CYLHIGH_LBA_HIGH_PORT PRIMARY_DATA_PORT+5 /*High bits for cylinder/lba address*/
#define PRIMARY_DRIVE_SELECT_PORT PRIMARY_DATA_PORT+6 /*drive/head select*/
#define PRIMARY_COMMAND_PORT PRIMARY_DATA_PORT+7 /*May also be used to read in status*/
#define PRIMARY_STATUS_PORT 0x3F6 /*Will read Alternate status register instead.Good for us.*/
#define PRIMARY_STATUS_ERROR (1<<0)
#define PRIMARY_STATUS_DATA_READY (1<<3)
#define PRIMARY_STATUS_MODE_SRV 1<<4 /*Don't really know what this is*/
#define PRIMARY_STATUS_DRIVE_FAULT 1<<5
#define PRIMARY_STATUS_DRIVE_READY 1<<6
#define PRIMARY_STATUS_DRIVE_BUSY (1<<7)
#define PRIMARY_COMMAND_INTR_ENABLE 1<<1/*Disable interrupts when set*/
#define PRIMARY_COMMAND_SOFT_RST 1<<2/*Software reset, helpful if device hangs*/
#define PRIMARY_COMMAND_HOB 1<<7/*Read the last High order byte sent to device in LBA48*/
Code: Select all
int read_sectors (struct dev_geo* dev,unsigned int first_block,unsigned char howmany,void *buffer)
{
cmd.lba_address=first_block;
cmd.count=howmany;
cmd.buffer=buffer;
unsigned short* buff=(unsigned short*)cmd.buffer;
unsigned char drive_select=0xa0;
if(IS_BIT_SET(dev->drive_mode,5))
{
drive_select=0xf0;
}
volatile unsigned char status;
drive_select|=(unsigned char)(first_block>>24 & 0x0f);
printk("drive is %x\n",drive_select);
/*while( !(inb(PRIMARY_COMMAND_PORT) & PRIMARY_STATUS_DRIVE_READY))
;
outb(PRIMARY_DRIVE_SELECT_PORT,COMMAND_IDENTIFY_MASTER_DRIVE); Primary, for slave use F0*/
read_again:
while( !(inb(PRIMARY_STATUS_PORT) & PRIMARY_STATUS_DRIVE_READY))
;
outb(PRIMARY_DRIVE_SELECT_PORT,drive_select);
outb(PRIMARY_SECTOR_COUNT_PORT,howmany);
outb(PRIMARY_SECTOR_LBA_LOW_PORT,(unsigned char)first_block);
outb(PRIMARY_CYLLOW_LBA_MID_PORT,(unsigned char)(first_block>>8 & 0xff));
outb(PRIMARY_CYLHIGH_LBA_HIGH_PORT,(unsigned char)(first_block>>16 &0xff));
// printk("%s, %x\n",__FUNCTION__,inb(PRIMARY_STATUS_PORT));
outb(PRIMARY_COMMAND_PORT,COMMAND_READ_SECTORS);
int buff_index=0;
while( cmd.count>0);
return howmany;
Code: Select all
void disk_handler(PushRegisters *reg)
{
if(!(inb(PRIMARY_STATUS_PORT) & PRIMARY_STATUS_DATA_READY)){
printk("[1]%s ,%x\n",__FUNCTION__,inb(PRIMARY_COMMAND_PORT));
return;}
printk("[2]%s %x\n",__FUNCTION__,inb(PRIMARY_COMMAND_PORT));
unsigned short* buff=(unsigned short*)cmd.buffer;
//printk("reading sectors[PKS]\n");
int j=0;
for(;j<256;j++)
{
buff[256*cmd.sectors_served+j]=ins(PRIMARY_DATA_PORT);
}
cmd.count--;
cmd.sectors_served++;
//printk("done\n");
inb(PRIMARY_COMMAND_PORT);
printk("%s %x\n",__FUNCTION__,inb(PRIMARY_COMMAND_PORT));
}
This is driving me into desperation, would do anything for correct code!