Page 1 of 1

ports,harddisk....

Posted: Mon Sep 02, 2002 9:32 am
by frank
Hi,

I'm trying to read sector 64 at cylinder 1 , head 0 of the harddisk.
That works fine if I first read sector 63 at cylinder 0, head 0.
But if I don't read sector 63 at cy l 0, head 0 then
sector 64 (cyl 1,head 0) doesn't get the right info...
Any ideas why?

I thought it was something with seek... so I tried to do a seek...
I setted the same variables then outputed 0x70,
and then setted the same variables again and outputed a read, but that didn't change a thing...
So how di I fix this?


Also I output the sector number using my outportdd function which sends 2 bytes which is 66536 bytes big... but my disk has more sectors than 66536, so should I make a function called outportw (which sends 4 bytes) instead?

Best,
Frank

Re:ports,harddisk....

Posted: Mon Sep 02, 2002 10:20 am
by Tim
frank wrote:I'm trying to read sector 64 at cylinder 1 , head 0 of the harddisk.
That works fine if I first read sector 63 at cylinder 0, head 0.
But if I don't read sector 63 at cy l 0, head 0 then
sector 64 (cyl 1,head 0) doesn't get the right info...
Any ideas why?
What do you expect to see? How do you know it's not the right info? You should be seeing the boot sector of the first partition. Any code?
Also I output the sector number using my outportdd function which sends 2 bytes which is 66536 bytes big... but my disk has more sectors than 66536, so should I make a function called outportw (which sends 4 bytes) instead?
Look up LBA in the ATA reference you're using; the sector number gets split across the cylinder and sector registers. Alternatively, write a simple sector number to cylinder-head-sector function and program the CHS values into the drive.

BTW: outportw sounds like it outputs a word, which is 2 bytes and ranges from 0 to 65535. outportd sounds like it outputs a doubleword, which is 4 bytes and ranges from 0 to 2[sup]32[/sup] - 1 (about 4 billion).

Re:ports,harddisk....

Posted: Mon Sep 02, 2002 10:26 am
by frank
Tim Robinson wrote:
frank wrote:I'm trying to read sector 64 at cylinder 1 , head 0 of the harddisk.
That works fine if I first read sector 63 at cylinder 0, head 0.
But if I don't read sector 63 at cy l 0, head 0 then
sector 64 (cyl 1,head 0) doesn't get the right info...
Any ideas why?
What do you expect to see? How do you know it's not the right info? You should be seeing the boot sector of the first partition. Any code?
Also I output the sector number using my outportdd function which sends 2 bytes which is 66536 bytes big... but my disk has more sectors than 66536, so should I make a function called outportw (which sends 4 bytes) instead?
Look up LBA in the ATA reference you're using; the sector number gets split across the cylinder and sector registers. Alternatively, write a simple sector number to cylinder-head-sector function and program the CHS values into the drive.

BTW: outportw sounds like it outputs a word, which is 2 bytes and ranges from 0 to 65535. outportd sounds like it outputs a doubleword, which is 4 bytes and ranges from 0 to 2[sup]32[/sup] - 1 (about 4 billion).
well, I wrote it to sector 64... I've also written it to 63,15,14 (all work fine) except for 64...
(i'm using dd for it at the moment)
Normally, yes, I should see the start of the partition...
the thing is, I'm not using partitions right now.. (I boot my os the windows way now)
so I should see the data... it works fine with sector 63,15,14 (at head 0, cyl 0)
but when I read sector 64 (without reading 63 before) it outputs the wrong data...
if I do read sec 63 before it outputs the right data..

Code: Select all

int ATAreadsec(int drive,char head,char sec,int cylinder,unsigned char * buf)
{
unsigned char c=0x0,c2=0x00;
unsigned short int b;
int cylinderlow,cylinderhigh;
int i=0;
int dh=0;

cylinderlow = (cylinder & 255);
cylinderhigh = (cylinder >> 8 & 255);

dh = dh+(prisec & 255); 
dh = dh+(head >> 8 & 255);

if (ATA[drive]){

ATAsetdrive(drive);                   /* set drive ports. */   
outportdd(diskport,dh);
outportdd(nrsecport,1);
outportdd(secport,sec);
outportdd(lcylport,cylinderlow);
outportdd(hcylport,cylinderhigh);
outportdd(commandport,0x20);            /* Read with retry */
ATAdiskready();  

while (i<512)
{
b = inportdd(dataport); 
asm volatile("movw %%ax,%%bx"::"b" (b));    
asm volatile("mov %%al,%%bh":"=b" (c));
asm volatile("mov %%ah,%%bl":"=b" (c2));
buf[i] = c;
buf[i+1] = c2;
i = i+2;
}
ATAdiskready();

} else {
printf("\nTrying to read an non ATA disk");  
}

return * buf;
}


Just found out that it does not matter wheter I read sector 64 or 65...
I have to read sector 63 for some reason, else it doesn't put the sector..
(sectors before 63 don't work)...
yes reading does, but when I want to read 64,65 only 63 works..
I don't know what I did wrong, reading sectors lower than 63 work directly...
( I have 63 sec per track, new cylinder starts at 64 )
I didn't do a seek, should I? (also, how?)
Any examples/codes of the disk from other os-es? (language doesn't really matter, I prefer C)

Re:ports,harddisk....

Posted: Mon Sep 02, 2002 3:48 pm
by Warmaster199
When you write to the 64th sector, it is actually Cyl1, Sec0, Hd0... Not Cyl1, Sec 64... You only have 64(0-63) Sectors per cylinder.

Re:ports,harddisk....

Posted: Mon Sep 02, 2002 5:23 pm
by Tim
Warmaster199 is right... LBA sector 64 is actually head 0 cylinder 1 sector 0. Sector 65 is C/H/S = 1/0/1, etc.

By the way, you should probably learn some boolean algebra.

AND operator (& in C): masks bits.
value & mask clears the 1 bits in value that are 0 in mask, and leaves the bits in value that are 1 in mask alone.

OR operator (| in C): combines bits
value | bits combines the bits in mask with the bits in value, so that the 1's in mask become 1's in value, and the 0s in mask are ignored.

Left and right shift operators (<< and >> in C): move bits
value << count moves the bits in value count bits to the left. The bottom bits are cleared.
value >> count moves the bits in value count bits to the right. The top bits are cleared.

To obtain the high and low bytes of a 16-bit number:

Code: Select all

bh = (bx >> 8) & 0xff; /* shift right 8 bits and mask bottom 8 bits */
bl = (bx >> 0) & 0xff; /* don't shift at all; mask bottom 8 bits */
When working with sets of bits, you should use OR and shifts instead of + and *. If you add together two bit patterns, and some bits that are set in one pattern are set in the other, you won't get the right result. If you OR them, everything will be fine.

That was just a quick reference; see pretty much any computer science text for more detail.

Re:ports,harddisk....

Posted: Tue Sep 03, 2002 12:58 am
by frank
cylinder 1, head 0, sec 0 works :),
but I still have to read cylinder 0-head 0-sector 63 (end of cylinder 0) before I can read cylinder 1-head 0-sec 0.
(else it outputs data from another sector)
Any ideas why?

Re:ports,harddisk....

Posted: Tue Sep 03, 2002 12:59 am
by Pype.Clicker
Tim Robinson wrote: Warmaster199 is right... LBA sector 64 is actually head 0 cylinder 1 sector 0. Sector 65 is C/H/S = 1/0/1, etc.

That was just a quick reference; see pretty much any computer science text for more detail.
what a fool am i to fight the legendary Tim Robinson on the block addressing battle field ... Grand Gods of Assembly, i pray for mercy ...

this been said, i remembered the sector after C=0/H=0/S=63 was C=0/H=1/S=1 rather than C=1/H=0/S=1. This mainly make sense because moving to the next head requires absolutely no rw heads moves (the slowest part of disk IO) and thus contiguous sectors can be read far quickly than if it has to change the heads position every single track.

Assuming (as tim said) sector 64 is 1/0/1 (remember: no sector #0) would mean that you need nb_heads*nb_cylinders heads moves to sweep your entire disk while assuming it is 0/1/1 does only require nb_cylinders moves ...

now, i leave my fate in the hands of BIOS ...

Re:ports,harddisk....

Posted: Tue Sep 03, 2002 6:40 am
by frank
Tried it using assembly, doesn't work :(
I still have to read sec 63-head 0-cyl 0 before I can read sec 0-head 0-cyl 1...
(else it outputs wrong sector data, probably sector data of another sector)
But it doesn't work without reading sec 63 (end of cyl 0) before reading sec 0... (Cyl 1)

code:

Code: Select all

bits 32
jmp t

t: mov ebx,0xb8000
mov byte[es:ebx],'f'
jmp set

set: mov dx,0x1f6
mov ax,176      ; head+drive, second drive
out dx,al

mov dx,0x1f2
mov ax,1       ; 1 sector
out dx,al       

mov dx,0x1f3
mov ax,63        ; sector 63
out dx,al

mov dx,0x1f4
mov ax,0        ; cylinder 0
out dx,ax 

mov dx,0x1f5
mov ax,0        ; high cylinder = 0
out dx,ax

mov dx,0x1f7
mov ax,0x20     ; read with retry :]
out dx,ax

f:  in al,dx
test al,8        ; are we still busy?
jz f
mov cx,0
mov ebx,0xB8000
jmp re

re: mov dx,0x1f0 
in ax,dx

mov dl,al
mov dh,ah

mov byte[es:ebx],dl
inc ebx
mov byte[es:ebx],0x1F
inc ebx

mov byte[es:ebx],dh
inc ebx
mov byte[es:ebx],0x1F
inc ebx

inc cx
cmp cx,512
jne re
jmp k

;
; do the same stuff again... 
;

k:   mov dx,0x1f6
mov ax,176      ; head+drive, second drive
out dx,al

mov dx,0x1f2
mov ax,1        ; 1 sector
out dx,al       

mov dx,0x1f3
mov ax,0        ; sector 1
out dx,al

mov dx,0x1f4
mov ax,1        ; cylinder 1
out dx,ax 

mov dx,0x1f5
mov ax,0        ; high cylinder = 0
out dx,ax

mov dx,0x1f7
mov ax,0x20     ; read with retry :]
out dx,ax

f2:  in al,dx
test al,8        ; are we still busy?
jz f2
mov cx,0
jmp re2


re2: mov dx,0x1f0 
in ax,dx

mov dl,al
mov dh,ah

mov byte[es:ebx],dl
inc ebx
mov byte[es:ebx],0x1F
inc ebx

mov byte[es:ebx],dh
inc ebx
mov byte[es:ebx],0x1F
inc ebx

inc cx
cmp cx,512
jne re2


hang: jmp hang          ; hang   

Re:ports,harddisk....

Posted: Tue Sep 03, 2002 8:30 am
by Pype.Clicker
as long as i remember, there is *no* sector #0 on any track: sectors are numbered from 1 to 63, not from 0 to 63 !!

Re:ports,harddisk....

Posted: Tue Sep 03, 2002 8:47 am
by frank
doesn't change much...
outputs no data at all...

Code: Select all

bits 32
jmp k

;============================
; do the stuff again... 
;============================

k:   mov dx,0x1f6
mov ax,176      ; head+drive, second drive
out dx,al

mov dx,0x1f2
mov ax,1        ; 1 sector
out dx,al       

mov dx,0x1f3
mov ax,1        ; sector 1
out dx,al

mov dx,0x1f4
mov ax,1        ; cylinder 1
out dx,ax 

mov dx,0x1f5
mov ax,0        ; high cylinder = 0
out dx,ax

mov dx,0x1f7
mov ax,0x20     ; read with retry :]
out dx,ax

f2:  in al,dx
test al,8        ; are we still busy?
jz f2
mov cx,0
mov ebx,0xB8000
jmp re2


re2: mov dx,0x1f0 
in ax,dx

mov dl,al
mov dh,ah

mov byte[es:ebx],dl
inc ebx
mov byte[es:ebx],0x1F
inc ebx

mov byte[es:ebx],dh
inc ebx
mov byte[es:ebx],0x1F
inc ebx

inc cx
cmp cx,512
jne re2
jmp hang    

hang: jmp hang          ; hang  

hmmm, no errors at all...
head 0, cyl 1,sector 0, = sec 64, 65 is the sec 1...

Code: Select all

bits 32
jmp set

err: mov ebx,0xb8000
mov byte[es:ebx],'E'
inc ebx
mov byte[es:ebx],0x1F
jmp hang

set: mov dx,0x1f7
in al,dx       
or al,1
je err
or al,7      ; ready to accept commands ? :)
jz set

mov dx,0x1f6
mov ax,176      ; head+drive, second drive
out dx,al

mov dx,0x1f2
mov ax,1       ; 1 sector
out dx,al       

mov dx,0x1f3
mov ax,0        ; sector 1
out dx,al

mov dx,0x1f4
mov ax,1        ; cylinder 1
out dx,ax 

mov dx,0x1f5
mov ax,0        ; high cylinder = 0
out dx,ax

mov dx,0x1f7
mov ax,0x20     ; read with retry :]
out dx,ax

f:  in al,dx
or al,1          ; error?
je err      
test al,8        ; are we still busy?
jz f
mov cx,0
mov ebx,0xB8000
jmp re

re: mov dx,0x1f0 
in ax,dx

mov dl,al
mov dh,ah

mov byte[es:ebx],dl
inc ebx
mov byte[es:ebx],0x1F
inc ebx

mov byte[es:ebx],dh
inc ebx
mov byte[es:ebx],0x1F
inc ebx

inc cx
cmp cx,512
jne re
jmp hang

hang: jmp hang          ; hang   

Re:ports,harddisk....

Posted: Tue Sep 03, 2002 9:36 am
by Pype.Clicker
maybe displaying the status result on screen might help ... maybe it says "ready" but its seek is not yet complete or maybe an error occured ...

Re:ports,harddisk....

Posted: Wed Sep 04, 2002 9:17 am
by frank
hmmmm... it outputs 1e00 when I read sec 0 - head 0 - cyl 1...
(checked that in vi, I've put a part of the disk in a file :P)

1e00 is sector 6 at head 0 - cylinder 0

Re:ports,harddisk....

Posted: Thu Sep 05, 2002 2:45 am
by Pype.Clicker
i think we're not talking about the same thing: i was suggesting that you display the disk status port on screen with something like

Code: Select all


hexs db '0123456789abcdef'
mov [0xb8000],0x073e073e ; displays ..
xor ebx,ebx
f2:  in al,dx
mov bl,al
shr bl,4
mov ah,[hexs+ebx]
mov [0xb8000],ah    ; display higher nible
mov bl,al
and bl,0x0f
mov ah,[hexs+ebx]
mov [0xb8002],ah    ; display lower nible

test al,0x20     ; is there a flaw
err:
   jne err  ; if there is, stops working

test al,0x8       ; are we still busy?
jz f2

...

Re:ports,harddisk....

Posted: Thu Sep 05, 2002 7:50 am
by frank
What do you mean?
I read the status port (see f: in ax,dx)...
dx still contains the status port,
I see no errors at all, only the output of the wrong sector.
(just checked the error register (0x1f1), doesn't output errors either.
I checked if the are bits using: or al,number)

[edit]
It always outputs that sector, no matter if I change the sector.
So cylinder 1021 outputs the same as 567...
see source:

Code: Select all

bits 32
jmp s

err: mov ebx,0xb8000
     mov byte[es:ebx],'E'
     inc ebx
     mov byte[es:ebx],0x1F
     jmp hang
 
s:    mov dx,0x1f7    ; recalibrate
      mov al,0x10
      out dx,al

f2:   in al,dx
      test al,7
      jz f2
      

     ;===============================================
     ; read
     ;===============================================
     mov dx,0x1f6
     mov ax,176      ; head+drive, second drive
     out dx,ax
     
     mov dx,0x1f2
     mov ax,1        ; 1 sector
     out dx,ax       
     
     mov dx,0x1f3
     mov ax,0        ;0        ; sector 0
     out dx,ax
     
     mov dx,0x1f4
     mov ax,1007        ; cylinder 1
     out dx,ax 
     
     mov dx,0x1f5
     mov ax,5343       ; high cylinder = 0
     out dx,ax
     
     mov dx,0x1f7
     mov ax,0x20     ; read with retry :] 
     out dx,ax
                  
           ; Check for errors
     mov dx,0x1f1
     in al,dx  
     or al,1
     je err
     or al,2
     je err
     or al,3
     je err
     or al,5
     je err
     or al,7
     je err
     or al,8
     je err

f:  mov dx,0x1f7
    in ax,dx
    or ax,1          ; error?
    je err      
    test ax,8        ; are we still busy?
    jz f
    mov cx,0
    mov ebx,0xB8000
    jmp re
    
re: mov dx,0x1f0 
    in ax,dx
    
    mov dl,al
    mov dh,ah
    
    mov byte[es:ebx],dl
    inc ebx
    mov byte[es:ebx],0x1F
    inc ebx
    
    mov byte[es:ebx],dh
    inc ebx
    mov byte[es:ebx],0x1F
    inc ebx
 
    inc cx
    cmp cx,512
    jne re
    jmp hang

hang: jmp hang          ; hang   
   
changing the cylinder to 0 (or any other number) does no matter, it doesn't output the right output...
but when I select cylinder 0 and a number < 63 for the sector it works fine...

[/edi]