1- Can you post you relevant driver code?
Yes I can. But I must warn you: This is very system specific assembly. I hope you get the general idea of whats going on. Let me try and guide you through the most critical system calls being made when writing to the disk.
First system call number 0x0004000c (
fdwrsec(0x0004000c, basesid, base, sector)) is performed by the test code. Below is an example of how:
Code: Select all
push 0 ;first we push the last argument: the LBA sector to be written to.
push 0 ;then the base address of what we want to write
push eax ;then the Service ID of the base. A service is roughly the same as a segment to be selected in any segment register.
push 0x0004000c ;this is the callcode, specifying what we want the kernel to do. When CC=0x0004000c, it knows we want to do fdwrsec
int 0x30 ;this will call the kernel, and return an errorcode in eax.
add esp, 4*4 ;cleaning up the stack
Before this code, the floppy motor is started. And after this code, the floppy motors are stopped.
Now, the below code will run. This is the system call responsible for writing a sector to the disk.
Code: Select all
cc0004000c:;fdwrsec(cc, basesid, base, sector), eax=ec
;Writes one sector to floppy disk.
;Get CHS
push 3
call getarg;eax=?sector (getarg is a local function, returning argn in eax)
add esp, 4*1
push eax;sec
push 0x00040000;cc=getchs
int 0x30;eax=c, ebx=h, ecx=s
add esp, 4*2
mov edx, eax;edx=c (to free eax of the burden of storage)
;Issue command 0xC5
push 0xc5;command
push 0x00040001;cc=fdcommand
int 0x30;eax=ec
add esp, 4*2
mov rs_eax, eax;ec
test eax, eax
jnz .ret
;parameter 1: h*4+drive
shl ebx, 2
push ebx
push 0x00040002;cc=fdparameter
int 0x30
add esp, 4*2
shr ebx, 2
;parameter 2: c
push edx;parameter
push 0x00040002;cc=fdparameter
int 0x30
add esp, 4*2
;parameter 3: h
push ebx;parameter
push 0x00040002;cc=fdparameter
int 0x30
add esp, 4*2
;parameter 4: s
push ecx;parameter
push 0x00040002;cc=fdparameter
int 0x30
add esp, 4*2
;parameter 5: 2
push 2;parameter
push 0x00040002;cc=fdparameter
int 0x30
add esp, 4*2
;parameter 6: sector count (1)
push 1;parameter
push 0x00040002;cc=fdparameter
int 0x30
add esp, 4*2
;parameter 7: 0x1b
push 0x1b;parameter
push 0x00040002;cc=fdparameter
int 0x30
add esp, 4*2
;parameter 8: 0xff
push 0xff;parameter
push 0x00040002;cc=fdparameter
int 0x30
add esp, 4*2
;Transfer data
push 2
call getarg;eax=?base
add esp, 4*1
mov ebx, eax;ebx=?base
push 1
call getarg;eax=?basesid
add esp, 4*1
push ebx;base
push eax;basesid
push 0x00040004;cc=fdo (Another critical system call. This will output 512 bytes to the FIFO. Code below this.)
int 0x30;eax=ec
add esp, 4*3
mov rs_eax, eax;ec
test eax, eax
jnz .ret
;result 1: st0
push 0x00040005;cc=fdresult
int 0x30;eax=result
add esp, 4*1
;result 2: st1
push 0x00040005;cc=fdresult
int 0x30;eax=result
add esp, 4*1
mov ebx, eax;ebx=st1
;result 3: st2
push 0x00040005;cc=fdresult
int 0x30;eax=result
add esp, 4*1
;result 4: c
push 0x00040005;cc=fdresult
int 0x30;eax=result
add esp, 4*1
;result 5: h
push 0x00040005;cc=fdresult
int 0x30;eax=result
add esp, 4*1
;result 6: s
push 0x00040005;cc=fdresult
int 0x30;eax=result
add esp, 4*1
;result 7: 2
push 0x00040005;cc=fdresult
int 0x30;eax=result
add esp, 4*1
;Check st1
mov rs_eax, 0x00040001
test bl, 00010000b
jnz .ret
mov rs_eax, 0x00040002
test bl, 00000010b
jnz .ret
mov rs_eax, 0;ec
.ret:
ret
Below is the fdo system call. This system call outputs 512 bytes to the FIFO register, from a buffer.
Code: Select all
cc00040004:;fdo(cc, basesid, base), eax=ec
;Send data from base to FDC.
push 1
call getarg;eax=?basesid
add esp, 4*1
push eax;sid
push 0x00020019;cc=sidds
int 0x30;eax=ec, ds=segment (You just have to trust some functions. Including this one. This will load our base segment into ds)
add esp, 4*2
mov rs_eax, eax;ec
test eax, eax
jnz .ret
push 2
call getarg;eax=?base
add esp, 4*1
mov ebx, eax;ebx=?base
mov ecx, 512;counter
@@:
mov dx, 0x03f4;select MSR
in al, dx;get MSR
test al, 00100000b;test NDMA
jz @b;Jump if data not ready
test al, 10000000b;test RQM
jz @b;jump if data not ready
mov dx, 0x03f5;select FIFO
mov al, [ebx];get data
out dx, al;set data
inc ebx;update pointer
dec ecx;update counter
jnz @b
mov rs_eax, 0;ec
.ret:
ret
Some of this code is not the best. May be optimized in the future. Just have to get it working before moving on to that task
I should also mention the state of the floppy:
IRQs: On
Drive Polling mode: On
FIFO: On
Threshold: 8
Implied seek: On
Precompensation: 0
2- Are you running on an emulator or on bare metal?
Bare metal.
Compaq Armada 1592 DT, to be exact.
3- If running on an emulator, which one?
Nope. No emulators are allowed for me. I believe in doing it the hard way
4- Can you provide details about what exactly happens in that "mysterious" moments at bootup?
POST performs, and then it just hangs. But I don't blame the poor thing: It's executed corrupted code (This is when booting from a previously booted disk (Which is a disk that have undergone the writing-operation of the OS (which is a disk with random patches of 0's in the code.)))
It seems to me you're running on bare metal. If so, please try to use an emulator, thus making debugging easier. Also, you'll be able to use the serial ports to report output, rather than the VGA (which can easily fail).
I'm sorry, but I am not running on any emulator. Neither am I planning to, unless ABSOLUTELY necessary.
I hope this will help. If you got any questions regarding the code, please feel free to ask me
