Page 1 of 1

Read Sectors 0x20

Posted: Tue Jun 14, 2011 8:46 pm
by pranjas
Hi guys,

I was trying to use READ SECTORS command with interrupts enabled. Currently NO DMA. I read on tutorial of PIO on this website that you either poll/wait for an interrupt to transfer data. However in the t13 document for ATA-7 Specification revision 4b I found this in the description of READ SECTOR(S) command
This command reads from 1 to 256 sectors as specified in the Sector Count register. A sector count of 0
requests 256 sectors. The transfer shall begin at the sector specified in the LBA Low, LBA Mid, LBA High,
and Device registers. The device shall interrupt for each DRQ block transferred.
I tried this in bochs, and the interrupt wasn't firing, however when i read data via polling, the interrupt was fired
for each block transferred as stated in the description.
My Question is then, what's the purpose of using Interrupt based data transfer mechanism? Can it only be used with DMA? I'm not sure about this please advice.

Re: Read Sectors 0x20

Posted: Wed Jun 15, 2011 4:34 am
by thepowersgang
Interrupts are best suited to DMA, yes, but it should still fire an IRQ when using PIO. Did you acknowledge the IRQ when you got it?

Re: Read Sectors 0x20

Posted: Wed Jun 15, 2011 11:59 am
by pranjas
This is my code for IDENTIFY command. Note that I don't read here, that is done by my ISR.


These are my 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)

Code: Select all

int get_drive_param(unsigned int dev_type,unsigned int bus,struct dev_geo * dev_geo_p)
{
	if(dev_type==SECONDARY_BUS) return -1;

	if(dev_geo_p == NULL) return -1;

	cmd.count=1;
	/*Send IDENTIFY COMMAND dev_type*/
	if(dev_type==PRIMARY_BUS)
	{
		dev_geo_p->heads=0;
		dev_geo_p->sectors=0;
		dev_geo_p->cylinders=0;
		while( !(inb(PRIMARY_COMMAND_PORT) & PRIMARY_STATUS_DRIVE_READY))
			;
		outb(PRIMARY_DRIVE_SELECT_PORT,COMMAND_IDENTIFY_MASTER_DRIVE); /*Primary, for slave use F0*/
		outb(PRIMARY_STATUS_PORT,0x00);/*interrupts*/


		outb(PRIMARY_SECTOR_COUNT_PORT,0);

		outb(PRIMARY_SECTOR_LBA_LOW_PORT,0);

		outb(PRIMARY_CYLLOW_LBA_MID_PORT,0);

		outb(PRIMARY_CYLHIGH_LBA_HIGH_PORT,0);

		/*send the device identify command to port*/
		outb(PRIMARY_COMMAND_PORT,COMMAND_IDENTIFY);

		while(	(inb(PRIMARY_STATUS_PORT) & PRIMARY_STATUS_DRIVE_BUSY) || ( inb(PRIMARY_STATUS_PORT)& PRIMARY_STATUS_DATA_READY));
		
			unsigned short *buff=dev_geo_p->cmd_queue->buffer;
			dev_geo_p->max_sectors=(unsigned char)(buff[47]& 0xff);
			dev_geo_p->drive_mode|=(unsigned char)(buff[59] & (1<<8));
			/*Currently only setting drive to master but check this later*/
			SET_BIT(dev_geo_p->drive_mode,5);
			if(IS_BIT_SET(buff[49],9)){/*bit 9 is set if LBA is supported*/	
			if(IS_BIT_SET(buff[83],10))
			{
				SET_BIT(dev_geo_p->drive_mode,2);
				dev_geo_p->size_48_upper=*((unsigned int*)&buff[100]);
				dev_geo_p->size_48_lower=*((unsigned int*)&buff[102]);
			}
			if(dev_geo_p->size_48==0) /*48 bit can't be used since no addressable logical sectors, but 28LBA is there*/
			{
				SET_BIT(dev_geo_p->drive_mode,1);
				dev_geo_p->size_28=*((unsigned int*)&buff[60]);
			}
			}
		//}
	}

return 0;
}
This is my ISR.

Code: Select all

void disk_handler(PushRegisters *reg)
{
//printk("%s\n",__FUNCTION__);
if(!(inb(PRIMARY_STATUS_PORT) & PRIMARY_STATUS_DATA_READY))
	return;
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");
int i=6;
inb(PRIMARY_COMMAND_PORT); 

}

Re: Read Sectors 0x20

Posted: Wed Jun 15, 2011 12:05 pm
by Combuster
No EOI to PIC seen...