Page 1 of 1
Cannot read data from hard disk
Posted: Thu Sep 22, 2011 12:39 pm
by ElasticRaven
I am trying to load a file (my kernel) from disk. I think I've followed the instructions at
http://wiki.osdev.org/ATA_PIO_Mode correctly, but my data is never loaded. Instead, the destination memory space is filled with zeros. I am checking the error bit, etc. but they are always clear.
I am using the 28-bit LBA address method. My file begins at byte 2048 on the drive. I am just reading one sector for now. Am I correct in thinking that my LBA address should be 5 [EDIT: should have been 4 because LBA addresses start with 0 instead of 1] and my sectorcount should be 1?
I am confused by the statement "A sectorcount of 0 means 256 sectors = 128K," to the point that I don't really trust it. 128K seems like a huge amount of data for what appears to be the smallest possible read size. Is there any way that I can read just a few sectors?
Any help would be appreciated.
Re: Cannot read data from hard disk
Posted: Thu Sep 22, 2011 1:29 pm
by intx13
ElasticRaven wrote:I am confused by the statement "A sectorcount of 0 means 256 sectors = 128K," to the point that I don't really trust it. 128K seems like a huge amount of data for what appears to be the smallest possible read size. Is there any way that I can read just a few sectors?
A read of 0 sectors wouldn't be very useful, so 0 is reused as the
largest read size. So instead of being able to read up to 255 sectors at a time you can read up to 256 sectors at a time. This is common for a lot of IO on a lot of different devices where 0 doesn't make much sense.
Re: Cannot read data from hard disk
Posted: Thu Sep 22, 2011 2:57 pm
by gerryg400
ElasticRaven wrote:I am confused by the statement "A sectorcount of 0 means 256 sectors = 128K," to the point that I don't really trust it. 128K seems like a huge amount of data for what appears to be the smallest possible read size. Is there any way that I can read just a few sectors?
Any help would be appreciated.
It goes like this
Code: Select all
int read_sectors(uint8_t sectorcount) {
if (sectorcount == 0) {
read 256 sectors
}
else {
read sectorcount sectors
}
}
Re: Cannot read data from hard disk
Posted: Fri Sep 23, 2011 2:04 am
by Combuster
Actually the BIOS would do things more like the following:
Code: Select all
do
{
read_sector();
sector_count--;
} while (sector_count)
Now see what happens if you pass in sector_count=0 at the start
Re: Cannot read data from hard disk
Posted: Fri Sep 23, 2011 6:39 am
by ElasticRaven
Ok, thanks. So sectorcount makes sense, but what about the LBA address? It's just the sector number from the beginning of the disk, right? I'm still getting a bunch of zeros.
Code: Select all
ATARead:
;read bl sectors from primary ATA controller master into [edi]
;starting at LBA [esi]
push edi
push eax
push ecx
push edx
mov dx,0x1F7 ;status register
.busy_loop:
in al,dx ;set AL to status register
and al,10000000b ;check MSB of al (BSY)
jnz .busy_loop ;poll again if BSY=1
mov dx,0x1F7 ;status register
.drdy_loop:
in al,dx ;set al to status register
and al,01000000b ;check 2nd bit of al (DRDY)
jz .drdy_loop ;poll again if DRDY=0
mov dx,0x1F6 ;device/head register
mov ecx,esi ;copy lba address
shr ecx,24
and ecx,0x0F ;highest 4 bits of LBA
mov al,0xE0 ;device 0 (master)
or al,cl ;ORed with highest 4 bits of LBA
out dx,al ;select device
mov dx,0x1F1 ;features/error info register
mov al,0
out dx,al ;clear features/error info register (ignored anyway)
mov dx,0x1F2 ;sector count register
mov al,bl ;sector count
out dx,al ;set sector sount
mov eax,esi ;load lba
mov dx,0x1F3 ;low lba register
out dx,al ;set low lba address
shr eax,8 ;al becomes middle lba address
mov dx,0x1F4 ;middle lba register
out dx,al ;set middle lba address
shr eax,8 ;al becomes high lba address
mov dx,0x1F5 ;high lba register
out dx,al ;set high lba address
mov dx,0x1F7 ;command register
mov al,0x20 ;read sectors command
out dx,al ;send read sectors command
mov dx,0x3F6 ;alternate status register
in al,dx ;wait 100ns
mov dx,0x3F6 ;alternate status register
in al,dx ;wait 100ns
mov dx,0x3F6 ;alternate status register
in al,dx ;wait 100ns
mov dx,0x3F6 ;alternate status register
in al,dx ;wait 100ns
mov dx,0x1F7 ;status register
.bsy_loop2:
in al,dx ;set al to status register
and al,10000000b ;check BSY bit
jnz .bsy_loop2 ;poll again if BSY=1
mov dx,0x1F7 ;status register
.drq_loop:
in al,dx ;set al to status register
and al,00000001b ;check ERR bit
jnz .err ;error
in al,dx ;set al to status register
and al,00001000b ;check DRQ bit
jz .drq_loop ;poll again if DRQ=0
mov dx,0x1F0 ;data register
mov ecx,256d ;number of words to read
cld ;clear direction flag so insw increments edi
rep insw ;read words from data register
jmp .end
.err:
push esi
mov esi,ReadErrorString
call PrintStringVideo32
pop esi
jmp .end
.end:
pop edx
pop ecx
pop eax
pop edi
ret
I'm calling it with
Code: Select all
mov esi,5 ;sector number
mov edi,0x00010000 ;destination address
mov bl,1 ;sector count
mov byte [edi+1],'X'
call ATARead ;read from disk
mov al,[edi+1]
call PrintCharVideo32
But 'X' gets replaced by 0x0, when it should be replaced by 'E' (since I'm reading an ELF file).
Re: Cannot read data from hard disk
Posted: Fri Sep 23, 2011 11:49 am
by guyfawkes
Should this not be 0xA0
Code: Select all
mov al,0xE0 ;device 0 (master)
or al,cl ;ORed with highest 4 bits of LBA
out dx,al ;select device
Re: Cannot read data from hard disk
Posted: Fri Sep 23, 2011 1:40 pm
by ElasticRaven
guyfawkes wrote:Should this not be 0xA0
Code: Select all
mov al,0xE0 ;device 0 (master)
or al,cl ;ORed with highest 4 bits of LBA
out dx,al ;select device
I tried both 0xE0 and 0xA0. The wiki page I linked to says use 0xE0 (it says use 0xA0 for IDENTIFY, though).
EDIT: Figured it out.
Re: Cannot read data from hard disk
Posted: Sun Feb 01, 2015 5:30 pm
by danielbj
First of all: I am sorry to bump a four year old thread, but this is the only one I could find, that matches my problem.
The good thing about a forum, is that answers and knowledge is not lost. Not even years after that knowledge has been revealed.
The bad thing is when the answers and solutions are never posted. This is, in my opinion, against the purpose of a forum.
Now I'm reading this thread, knowing that the dear Mr(s). ElasticRaven has the solution to my problem. Unfortunately that very same user is no longer active on this forum, making it rather difficult for me to find him. The last time he paid us a visit was Fri Oct 07, 2011 11:37 am. He might as well be gone forever.
And the worst part?
I WILL NEVER KNOW HIS SECRET.
Re: Cannot read data from hard disk
Posted: Mon Feb 02, 2015 5:16 am
by zhiayang
There was truly never any more appropriate time for this xkcd to appear.