Page 1 of 1

Unknown Disk Read Error after Converting LBA to CHS

Posted: Wed Dec 09, 2009 3:52 am
by 54616E6E6572
EDIT: I fixed an error in convLBA2CHS.getCylinder where the shl cx, 5 should have been a shl cx, 6... I still have the same problem though

Ok so I wrote a test program that I was using to see if my LBA2CHS function worked correctly.

1. I read the disk parameters using INT 0x13, AH = 0x08
2. I convert the LBA address to CHS using the disk parameters
3. I read the sector from the disk using INT 0x13, AH = 0x02 (it fails here)
4. I search the sector for the signature (dw 0xDEAD, 0xBEEF)

The LBA Address im converting is 0x00200000 (1GB) on a 2GB disk
The conversion function does everything as expected
The function fails during the INT 0x13 call where AH = 0x02

Upon return from the Interrupt, Carry is set, AX = 0x0220; According to Ralph Brown's Interrupt List, When AH = 0x02 it means 'address mark not found'

Code: Select all

getDriveParams:
	mov si, errDisk		; precuationary load, incase we cannot get disk parameters			
	push dx			; save boot drive
	mov ah, 0x08		; get drive paramters
	xor di, di			; some BIOS crash if ES:DI is not 0000:0000
	int 0x13			; BIOS disk interrupt
	jc printMsg		; if error, print message
	
convLBA2CHS:
	and cx, 0x3F		; get Sectors Per Track
	movzx si, cl		; save Sectors Per Track
	movzx di, dh		; save Heads Per Cylinder
	.getCylinder:	; Cylinder = LBA / (SPT * HPC)
		mov ax, si	; set ax to SPT
		mul di		; multiply SPT by HPS
		mov cx, ax	; set CX to the result
		mov dx, 0x0020	; make (dx << 10) + ax = 0x00200000
		xor ax, ax	; clear ax
		div cx		; divide by (SPT * HPC)
		mov cx, ax	; set CX to the result
		shl cx, 6		; this is the cylinder, so shift left 6 bits
	.getSector:	; Sector = (LBA % SPT) + 1
		mov dx, 0x0020	; make (dx << 10) + ax = 0x00200000
		xor ax, ax	; clear AX
		div si		; divide by SPT
		add cx, dx	; add result to CX
		inc cx		; increment so we get a correct sector number
	.getHead:	; Head = (LBA / SPT) % HPC	
		xor dx, dx	; ax already holds quotient of (LBA / SPT), so clear dx
		div di		; divide by HPC
		xchg dh, dl	; set DH to Head Number
		pop ax		; get drive number into AX
		mov dl, al	; restore drive number
	
readBeef:
	mov di, 0x0005		; try at least 5 times
	mov bx, 0x9000		; into memory location 0000:9000
	.loop1:
		mov ax, 0x0201	; read 1 sector from disk
		int 0x13		; BIOS disk interrupt
		jnc findBeef	; if no error, ensure sector is valid
		xor ax, ax	; otherwise, reset disk
		int 0x13		; BIOS disk interrupt
		dec di		; remove 1 remaining attempt
		jnz .loop1	; try again
		mov si, errDisk	; otherwise, load error message and print