Floppy controller failure during real mode int 13h (ah=02h)

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.
Post Reply
OutOfTheStream
Posts: 5
Joined: Sun Aug 03, 2008 9:04 am

Floppy controller failure during real mode int 13h (ah=02h)

Post by OutOfTheStream »

Hi there,

while trying to write my own bootloader, I've failed to fix a problem reading from the floppy disk I'm booting from.

Some background info at first:
I'm using VirtualBox OSE to test my OS. But I've tried my code on Qemu, too, but it works neither on VirtualBox nor on Qemu.

My bootloader is only meant to copy data from the booting floppy disk to memory. It is using int 0x13 (with ah=0x02) for this task. But whenever I start reading from the 19th (0x13th) or any higher block inside a cylinder, the interrupt returns status code 0x20 - "controller failure".

Here is some example code

Code: Select all

[BITS 16]

global _start

_start:

mov ax,0x2000
mov ss,ax
mov ax,0xFFFF
mov sp,ax
mov bp,ax

;demo output to see how far we get
mov bx,0x0007
mov ax,0x0E76
int 0x10
mov al,0x77
int 0x10

;read first 18 blocks
mov ax,0x0212
mov bx,0x1000
mov es,bx
mov bx,0x0000
mov cx,0x0101
mov dx,0x0000
int 0x13
jc error

;another demo output
mov ax,0x0E78
mov bx,0x0007
int 0x10

;read the remaining 18 blocks from the same track
mov ax,0x0212
mov bx,0x1240
mov es,bx
mov bx,0x0000
mov cx,0x0113
mov dx,0x0000
int 0x13
jc error

;more demo output
mov ax,0x0E79
mov bx,0x0007
int 0x10
mov al,0x7A
int 0x10

;infinite loop
rpt:
nop
jmp rpt

error:
;store status code
mov cl,ah

;output a space
mov ah,0x0E
mov bx,0x0007
mov al,0x20
int 0x10

;output the error code. It is increased by 0x20 to assure that it is a printable character.
mov al,cl
add al,0x20
int 0x10
jmp rpt
This code prints

Code: Select all

vwx @
, "@" is the 0x40th ASCII character, therefore the return status code is 0x20. According to Ralf Brown's Interrupt List this indicates a controller failure (whatever that means exactly).
Some more testing later, I knew that my code failed, whenever cl (the number of the sector I start reading from) is greater than 0x12 (18).
I do not have an explanation for this. The only relevant meaning of the number 18 I know is the number of blocks per head on floppies. But no matter what I alter the head number (dh) it either returns 0x20 or 0x01 (invalid function number or invalid params).

Any help would be appreciated.

Greetings
Out Of The Stream

Edit: I'm really wondering if the block number I'm starting to read from is interpreted from the start of that cylinder or from the start of the head #-o
User avatar
xyjamepa
Member
Member
Posts: 397
Joined: Fri Sep 29, 2006 8:59 am

Re: Floppy controller failure during real mode int 13h (ah=02h)

Post by xyjamepa »

knew that my code failed, whenever cl (the number of the sector I start reading from) is greater than 0x12 (18).
There are only 18 sectors per track,
any way take a look at this
The man who follows the crowd will usually get no further than the crowd.
The man who walks alone is likely to find himself in places
no one has ever been before.
OutOfTheStream
Posts: 5
Joined: Sun Aug 03, 2008 9:04 am

Re: Floppy controller failure during real mode int 13h (ah=02h)

Post by OutOfTheStream »

Thanks a lot. I first learned about CHS from this tutorial. I guess I just misunderstood something.

After rewriting my code (and fixing some bugs that occured during rewriting), I've encountered another problem I failed to solve:

int 0x13 now gives me status code 09h - data boundary error. But I'm not using DMA (I guess BIOS uses it internally), I'm not trying to read more than 64KB at once (I'm just reading 7 blocks), and I'm far below the 1 MiB border. What other reason might cause such an error?
User avatar
xyjamepa
Member
Member
Posts: 397
Joined: Fri Sep 29, 2006 8:59 am

Re: Floppy controller failure during real mode int 13h (ah=02h)

Post by xyjamepa »

why don't you try to read less than 128 sectors,and see if it works.
The man who follows the crowd will usually get no further than the crowd.
The man who walks alone is likely to find himself in places
no one has ever been before.
thooot
Member
Member
Posts: 30
Joined: Sun Jun 01, 2008 11:20 am

Re: Floppy controller failure during real mode int 13h (ah=02h)

Post by thooot »

Are you crossing a 64KB boundary? I don't think that's allowed. Try changing your code to only read one sector at a time. This is the safest method.
OutOfTheStream
Posts: 5
Joined: Sun Aug 03, 2008 9:04 am

Re: Floppy controller failure during real mode int 13h (ah=02h)

Post by OutOfTheStream »

As I stated in my previous post, I'm trying to read 7 (in letters: seven) blocks at once (which is less than 128). That is 3584 Bytes, which is less than 64KiB.

Edit:
Here is some demo code again. It fails reproducably with errorcode 0x09.

Code: Select all

[BITS 16]

global _start

_start:

mov ax,0x2000
mov ss,ax
mov ax,0xFFFF
mov sp,ax
mov bp,ax

;demo output to see how far we get
mov bx,0x0007
mov ax,0x0E76
int 0x10
mov al,0x77
int 0x10

;demo read
mov ax,0x5FA0
mov es,ax
mov ax,0x0207
mov bx,0x0000
mov cx,0x0A01
mov dx,0x0100
int 0x13
jc error

;more demo output
mov ax,0x0E78
mov bx,0x0007
int 0x10
mov al,0x79
int 0x10


;infinite loop
rpt:
nop
jmp rpt

error:
  ;store status code
  mov cl,ah

  ;output a space
  mov ah,0x0E
  mov bx,0x0007
  mov al,0x20
  int 0x10

  ;output the error code
  xor eax,eax
  mov ah,cl
  call writeHexDword
  jmp rpt
Some more testing returned the knowledge, that this code fails, whenever al is greater than three.
If you wish to see the "writeHexDword" routine, I'll of course show it to you. But it is tested and working correctly.
OutOfTheStream
Posts: 5
Joined: Sun Aug 03, 2008 9:04 am

Re: Floppy controller failure during real mode int 13h (ah=02h)

Post by OutOfTheStream »

I'm sorry for being that rude in my last post. I was upset about those (with all due respect and all due thankfulness) useless answers (especially as my post was not even read completely) and forgot my manners for a moment. I will try not to be that rude again.

I ask you to excuse my misbehaviour and I hope that I will be granted further help.
User avatar
AJ
Member
Member
Posts: 2646
Joined: Sun Oct 22, 2006 7:01 am
Location: Devon, UK
Contact:

Re: Floppy controller failure during real mode int 13h (ah=02h)

Post by AJ »

Hi,

I find that the safest way with the (tempromental) FDC is to read one sector at a time. With the slowness of the FDD, you really won't notice any performance loss. I originally got this function from Christoffer Bubach's "BOS" and it has served me very well:

Code: Select all

;-----------------------------------------------;
;   read a number of sectors (one at a time)    ;
;	this function taken from Bubach's 'BOS'		;
;-----------------------------------------------;
;  in:                                          ;
;    di = segment to save at                    ;
;    ax = sector to read                        ;
;    cx = number of sectors                     ;
;  out:                                         ;
;    di = updated (added for next read)         ;
;    ax = updated (added for next read)         ;
;-----------------------------------------------;
[BITS 16]
ReadSectors:
	pusha
	mov		bl, byte [bpbTrackSect]		; bl = number of sectors per track
	div		bl							; al = ax / bl
	mov		cl, ah						; cl = real sector number
	add		cl, 1
	xor		ah, ah						; del the rest of the div before
	mov		bl, byte [bpbHeads]			; bl = number of heads
	div		bl							; ah = rest of ( ax / bx ), al = ax / bx
	mov		ch, al						; ch = number of track
	mov		dh, ah						; dh = the head number
	mov		ax, cx						; save cx in ax
	mov		cx, 6						; try it 6 times
	
	.next_try:
		push	es
		push	cx
		mov		cx, ax			      		; restore cx
		push	cx
		xor		ax, ax
		mov		dl, [bpbDriveNumber]		; reset drive
		push	dx
		int		0x13
	jc	.failed
	
		pop	  dx
		pop	  cx
		xor	  bx, bx
		mov	  es, di
		mov	  ax, 0x0201				; function 2, 1 sector
		int	  0x13
	jnc	  .ok							; if it was ok, check next..
	
	 .failed:
		pop	  dx
		pop	  ax
		
		pop	  cx
		pop	  es
	loop	  .next_try					; else try once again if there is an error
	
		jmp	  Error						; if cx = 0 and the read operation failed, halt
	.ok:
		pop	  cx						; from the next_try loop
		pop	  es
		popa
		add	  di, 32					; add 32 (512/16) to segment (automatic seg incrementing)
		inc	  ax						; add sector counter
	loop	  ReadSectors
ret
HTH,
Adam
thooot
Member
Member
Posts: 30
Joined: Sun Jun 01, 2008 11:20 am

Re: Floppy controller failure during real mode int 13h (ah=02h)

Post by thooot »

OutOfTheStream wrote:As I stated in my previous post, I'm trying to read 7 (in letters: seven) blocks at once (which is less than 128). That is 3584 Bytes, which is less than 64KiB.

Some more testing returned the knowledge, that this code fails, whenever al is greater than three.
If you wish to see the "writeHexDword" routine, I'll of course show it to you. But it is tested and working correctly.
Like I said you can't cross a 64KB boundary, that will cause an error. You start at 0x5FA00 and it fails if you read 4 or more sectors which takes you across 0x60000 (a 64KB boundary). That is why your code is failing.
OutOfTheStream
Posts: 5
Joined: Sun Aug 03, 2008 9:04 am

Re: Floppy controller failure during real mode int 13h (ah=02h)

Post by OutOfTheStream »

Ah, so the 64 kiB boundary is not meant relative to the destination address. Thanks a lot for that hint. I guess this problem is solved then.
Post Reply