ATA_IDENTIFY

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
ahmedfme
Posts: 9
Joined: Wed Mar 30, 2016 7:02 am
Libera.chat IRC: ahmedfme

ATA_IDENTIFY

Post by ahmedfme »

Hi,
i am trying to use some codes from other OSes to get ATA working in my code.
i am using below code to send IDENTIFY command

Code: Select all

outportb(io + ATA_REG_SECCOUNT0, 0);
	outportb(io + ATA_REG_LBA0, 0);
	outportb(io + ATA_REG_LBA1, 0);
	outportb(io + ATA_REG_LBA2, 0);
	/* Now, send IDENTIFY */
	Printf("Sending IDENTIFY to port 0x%X\n",io);
	outportb(io + ATA_REG_COMMAND, ATA_CMD_IDENTIFY);
	Printf("Sent IDENTIFY\n");
	/* Now, read status port */
	uint8_t status = inportb(io + ATA_REG_STATUS);
	Printf("\nThe status right now is %d", status);
	if (status)
	{
		Printf("\nNow Polling... _IRQP = %d , _IRQS= %d",_IRQP,_IRQS);
		/* Now, poll untill BSY is clear. */
		while (inportb(io + ATA_REG_STATUS) & ATA_SR_BSY != 0);
		//while (!_IRQP || !_IRQS){}
		Printf("\nFinished Polling... _IRQP = %d , _IRQS= %d", _IRQP, _IRQ
when running this code it always hang up after sending the command.
some times it writes on screen "Sen" without completing the word and hang up.
there is no panic catched ..
any isea why it is hanging up?
User avatar
BrightLight
Member
Member
Posts: 901
Joined: Sat Dec 27, 2014 9:11 am
Location: Maadi, Cairo, Egypt
Contact:

Re: ATA_IDENTIFY

Post by BrightLight »

I don't see any code for selecting a device. Every ATA channel can have two devices.
You know your OS is advanced when you stop using the Intel programming guide as a reference.
ahmedfme
Posts: 9
Joined: Wed Mar 30, 2016 7:02 am
Libera.chat IRC: ahmedfme

Re: ATA_IDENTIFY

Post by ahmedfme »

here is the full function code

Code: Select all

uint8_t ide_identify(uint8_t bus, uint8_t drive)
{
	uint16_t io = 0;
	ide_select_drive(bus, drive);
	if (bus == ATA_PRIMARY) io = ATA_PRIMARY_IO;
	else io = ATA_SECONDARY_IO;
	/* ATA specs say these values must be zero before sending IDENTIFY */
	outportb(io + ATA_REG_SECCOUNT0, 0);
	outportb(io + ATA_REG_LBA0, 0);
	outportb(io + ATA_REG_LBA1, 0);
	outportb(io + ATA_REG_LBA2, 0);
	/* Now, send IDENTIFY */
	Printf("Sending IDENTIFY to port 0x%X\n",io);
	outportb(io + ATA_REG_COMMAND, ATA_CMD_IDENTIFY);
	Printf("Sent IDENTIFY\n");
	/* Now, read status port */
	uint8_t status = inportb(io + ATA_REG_STATUS);
	Printf("\nThe status right now is %d", status);
	if (status)
	{
		Printf("\nNow Polling... _IRQP = %d , _IRQS= %d",_IRQP,_IRQS);
		/* Now, poll untill BSY is clear. */
		while (inportb(io + ATA_REG_STATUS) & ATA_SR_BSY != 0);
		//while (!_IRQP || !_IRQS){}
		Printf("\nFinished Polling... _IRQP = %d , _IRQS= %d", _IRQP, _IRQS);
		if (_IRQP)	{_IRQP = false;	}
		if (_IRQS)	{ _IRQS = false; }
		
	pm_stat_read:		status = inportb(io + ATA_REG_STATUS);
		if (status & ATA_SR_ERR)
		{
			Printf("\n%s%s has ERR set. Disabled.\n", bus == ATA_PRIMARY ? "Primary" : "Secondary", drive == ATA_PRIMARY ? " master" : " slave");
			return 0;
		}
		while (!(status & ATA_SR_DRQ)) goto pm_stat_read;
		Printf("\n%s%s is online.\n", bus == ATA_PRIMARY ? "Primary" : "Secondary", drive == ATA_PRIMARY ? " master" : " slave");
		/* Now, actually read the data */
		
		for (int i = 0; i<256; i++)
		{
			*(uint16_t *)(ide_buf + i * 2) = inportw(io + ATA_REG_DATA);
		}
		
	}
}
ahmedfme
Posts: 9
Joined: Wed Mar 30, 2016 7:02 am
Libera.chat IRC: ahmedfme

Re: ATA_IDENTIFY

Post by ahmedfme »

and drive select function code is here

Code: Select all

void ide_select_drive(uint8_t bus, uint8_t i)
{
	if (bus == ATA_PRIMARY)
		if (i == ATA_MASTER)
			outportb(ATA_PRIMARY_IO + ATA_REG_HDDEVSEL, 0xA0);
		else outportb(ATA_PRIMARY_IO + ATA_REG_HDDEVSEL, 0xB0);
	else
		if (i == ATA_MASTER)
			outportb(ATA_SECONDARY_IO + ATA_REG_HDDEVSEL, 0xA0);
		else outportb(ATA_SECONDARY_IO + ATA_REG_HDDEVSEL, 0xB0);
}
User avatar
BrightLight
Member
Member
Posts: 901
Joined: Sat Dec 27, 2014 9:11 am
Location: Maadi, Cairo, Egypt
Contact:

Re: ATA_IDENTIFY

Post by BrightLight »

It doesn't really look like something is wrong. Run it in Bochs and check the log messages.
You know your OS is advanced when you stop using the Intel programming guide as a reference.
ahmedfme
Posts: 9
Joined: Wed Mar 30, 2016 7:02 am
Libera.chat IRC: ahmedfme

Re: ATA_IDENTIFY

Post by ahmedfme »

I have tried but unfortunately Bochs can't loade my bootloader "Neptune" because it doesn't support int 15h Function AX=0088
Octocontrabass
Member
Member
Posts: 5587
Joined: Mon Mar 25, 2013 7:01 pm

Re: ATA_IDENTIFY

Post by Octocontrabass »

Why are you using INT 0x15 AH=0x00? That function doesn't do anything useful on modern PCs.

Maybe what you really want is INT 0x15 AH=0x88.
User avatar
BrightLight
Member
Member
Posts: 901
Joined: Sat Dec 27, 2014 9:11 am
Location: Maadi, Cairo, Egypt
Contact:

Re: ATA_IDENTIFY

Post by BrightLight »

Octocontrabass wrote:Maybe what you really want is INT 0x15 AH=0x88.
Even so, INT 0x15 EAX = 0xE820 should be used for detecting memory. It is supported on almost all real hardware and all emulators.
You know your OS is advanced when you stop using the Intel programming guide as a reference.
alexg
Posts: 16
Joined: Sun Mar 06, 2016 11:59 am

Re: ATA_IDENTIFY

Post by alexg »

ahmedfme wrote:and drive select function code is here

Code: Select all

void ide_select_drive(uint8_t bus, uint8_t i)
{
	if (bus == ATA_PRIMARY)
		if (i == ATA_MASTER)
			outportb(ATA_PRIMARY_IO + ATA_REG_HDDEVSEL, 0xA0);
		else outportb(ATA_PRIMARY_IO + ATA_REG_HDDEVSEL, 0xB0);
	else
		if (i == ATA_MASTER)
			outportb(ATA_SECONDARY_IO + ATA_REG_HDDEVSEL, 0xA0);
		else outportb(ATA_SECONDARY_IO + ATA_REG_HDDEVSEL, 0xB0);
}
You are setting bits 7 and 5 (which are undefined => you should not touch them) besides the device select, I think you want to set bit 6 (which sets LBA addressing mode).
User avatar
BrightLight
Member
Member
Posts: 901
Joined: Sat Dec 27, 2014 9:11 am
Location: Maadi, Cairo, Egypt
Contact:

Re: ATA_IDENTIFY

Post by BrightLight »

alexg wrote:You are setting bits 7 and 5 (which are undefined => you should not touch them) besides the device select, I think you want to set bit 6 (which sets LBA addressing mode).
No. That code is correct.
OSDev Wiki wrote:To use the IDENTIFY command, select a target drive by sending 0xA0 for the master drive, or 0xB0 for the slave, to the "drive select" IO port.
You know your OS is advanced when you stop using the Intel programming guide as a reference.
alexg
Posts: 16
Joined: Sun Mar 06, 2016 11:59 am

Re: ATA_IDENTIFY

Post by alexg »

omarrx024 wrote:
alexg wrote:You are setting bits 7 and 5 (which are undefined => you should not touch them) besides the device select, I think you want to set bit 6 (which sets LBA addressing mode).
No. That code is correct.
OSDev Wiki wrote:To use the IDENTIFY command, select a target drive by sending 0xA0 for the master drive, or 0xB0 for the slave, to the "drive select" IO port.
I'm sorry, when I posted the reply I was pretty much in a hurry and I saw the fact that the ide_select_drive function specifies CHS addressing, but you're right, it's irrelevant for the IDENTIFY command. However, if LBA addressing will be used, the function should be modified to also set bit 6.

Regarding the quote from OSDev Wiki, I would appreciate you'd use an official specification when contradicting someone - http://www.t13.org/documents/uploadeddo ... lume_1.pdf ( see 6.17 IDENTIFY DEVICE bits 7 and 5 are obsolete, so it is enough to write 0x10 for the slave and 0x0 for the master ).
User avatar
BrightLight
Member
Member
Posts: 901
Joined: Sat Dec 27, 2014 9:11 am
Location: Maadi, Cairo, Egypt
Contact:

Re: ATA_IDENTIFY

Post by BrightLight »

Well, writing 0xA0 and 0xB0 for the master and slave respectively works on Bochs, QEMU, VMware, VirtualBox, one real ATA hard drive and a SATA hard drive with IDE emulation.
You know your OS is advanced when you stop using the Intel programming guide as a reference.
Octocontrabass
Member
Member
Posts: 5587
Joined: Mon Mar 25, 2013 7:01 pm

Re: ATA_IDENTIFY

Post by Octocontrabass »

alexg wrote:Regarding the quote from OSDev Wiki, I would appreciate you'd use an official specification when contradicting someone - http://www.t13.org/documents/uploadeddo ... lume_1.pdf ( see 6.17 IDENTIFY DEVICE bits 7 and 5 are obsolete, so it is enough to write 0x10 for the slave and 0x0 for the master ).
This version of the ATA specification (section 5.2.8) says bits 7 and 5 should be set for backwards compatibility.
alexg
Posts: 16
Joined: Sun Mar 06, 2016 11:59 am

Re: ATA_IDENTIFY

Post by alexg »

You said you are not running your OS on Bochs, what are you running it on?

I've just ran my OS on a real machine and the ATA registers are not exposed by the IDE controller at the standard locations and I have to read the values from the PCI IDE Controller bars (see http://wiki.osdev.org/PCI_IDE_Controller).

Edit: also make sure from your BIOS that the SATA configuration mode is set to IDE and not ACHI.
User avatar
neon
Member
Member
Posts: 1567
Joined: Sun Feb 18, 2007 7:28 pm
Contact:

Re: ATA_IDENTIFY

Post by neon »

Hello,
I have tried but unfortunately Bochs can't loade my bootloader "Neptune" because it doesn't support int 15h Function AX=0088
It should be noted that this was a copy of our old boot loader, which used int 15h function 88h to calculate the mem_lower and mem_upper fields of the multiboot information structure. The boot loader uses int 15h function e820h for the memory map fields which is what you really want. So, if you want to suppress the error, clear bit 0 of the multiboot header flags field. This will tell the boot loader to ignore the mem_* fields. In any case though, the software should still continue to run despite the error.
OS Development Series | Wiki | os | ncc
char c[2]={"\x90\xC3"};int main(){void(*f)()=(void(__cdecl*)(void))(void*)&c;f();}
Post Reply