This Thread discussing about Port Programming.
Do you agree ?.

I want a Simple example to programming the HD Device. The Example should be like this:

1. Set Hardisk to Sec 1, Cyl 0, Head 0.
2. Save the first byte.
3. Rewrite it.
4. Load the saved byte.
5. Write it back to normal.

If this thread not match in this criteria, just delete it and send me n PM with subject, "You stupid Morron, Its not match". :grin:
Posted on 2003-04-08 08:11:04 by realvampire
sounds like wrong forum to me. It's "low level programming", not "electronics".
Posted on 2003-04-08 08:12:49 by f0dder
I dont think so. But its okay. Are we here gonna designing a Hardware device ?
Posted on 2003-04-08 08:15:09 by realvampire
As far as I can see, this forum is about messing with hardware and programming PICs. Doesn't have much to do with lowlevel access to the harddrive :)
Posted on 2003-04-08 08:18:46 by f0dder
Maybe thats what I mean, PIC programming, but what is it? the use and its definition.:tongue: :stupid:
Posted on 2003-04-08 08:21:29 by realvampire
I moved this thread to Main, so more people might get the idea of what your interested in. F0dder is right, your looking for low level access to your harddrive (probably via windows OS). This is probably a ring0 concern ~ one that im not skilled in.

Perhpas someone else might be tho...
:NaN:
Posted on 2003-04-08 17:25:35 by NaN
:o Ahum..., oke thanks. Ring0 I'll check it. Where is the good Explanation for this ?
Posted on 2003-04-08 20:46:49 by realvampire
Hello realvampire,

Check this funtion in the SDK: Int 21h Function 7305h

Maybe it is helpful.

best regards,


czDrillard
Posted on 2003-04-08 22:29:44 by czDrillard
realvampir,

seems you want to manipulate the mbr... you can find many example of this on the net. Search on google as "reading mbr".

czDrillard method is good. If you want you can do the same at bios level, check also for int 13h service 02 to read a sector, service 03 to write.
Posted on 2003-04-09 02:51:37 by Bit7
reading MBR is very easy, especially on NT. You just use a special syntax to CreateFile.

Programming the harddrive via port I/O is somewhat complex - at least you need to know what you're doing. And you will NOT be doing this under windows, not even from ring0.
Posted on 2003-04-09 03:25:29 by f0dder
:grin: I dont want to use Interupt, I must increase my skill, thats why I didnt like to use WinAPI and Interupt.
Posted on 2003-04-09 17:47:06 by realvampire
If you *really* want to work with hdd in this low level mode (i.e. with ports in and out) I could give you some advice. I am currently trying to write a hdd driver for SOL OS (see BogdanOntanu about that :) ) and I just finished the first Read_Sector procedure (one that works in LBA mode only, however).
Anyways, this works only when you are in some O.S. that allows direct access to ports (i.e. real mode MSDOS or some other O.S. like SOL OS :) )

It's written for TASM, but shouldn't make a big difference. Does not use interrupts and is not very nice written also. About interrupts.. You should set the device (HDD) not to assert INTRQ. This is done in the 'main' progam, I will also include the full source as a zip attachement.





wait_ready PROC STDCALL
push ecx
push edx

; Here we should wait 400ns, but since we don't have a timer yet... :P
mov ecx,512
@@wait1:
dec ecx
jnz @@wait1

; Then try to read status.
; 3f6h is the alternate status register. According to ATA standards
; this is the register one shall read status from
; until drive generates an interrupt or the BSY bit is clear.
; Reading 1f7h (status register) implies INTACK - drive
; clears INTRQ and also clears Status register contents.
mov dx,3f6h
@@wait2:
in al,dx
and al,80h
jnz @@wait2
mov dx,1f7h
; After BSY is clear read status register also. That is a
; required step in order for the drive to know that we
; acknowledged its request and eventually
; we are ready to read data.
in al,dx
pop edx
pop ecx
ret
ENDP

; ************* READ SECTOR ***************


LBA_Read_Sector PROC STDCALL
ARG sector_no:DWORD,lp_buff:DWORD

mov edi,[lp_buff]
mov eax,[sector_no]

mov dx,1f3h ; lba bits 0-7
out dx,al

mov dx,1f4h
xchg al,ah
out dx,al ; lba bits 8-15

shr eax,16

mov dx,1f5h ; lba bits 16-23
out dx,al

mov dx,1f6h
; and bits 24-27, along with drive/head register
; and LBA mode bit :) are here
xchg al,ah
or al,11100000b
and al,11101111b ; lowest bits are lba 24-27, the 0 bit is the drive no.
out dx,al

mov dx,1f2h
mov al,1 ; no. of sectors to read; one for now
out dx,al

mov dx,01f7h
mov al,20h ; read sectors command
out dx,al

call wait_ready STDCALL

and al,00001000b ; check DRQ - if ON then we have to read data, else... something is wrong.
jz @@err
mov ecx,256

mov dx,01f0h
@@hdloop:
in ax,dx
mov WORD PTR [edi],ax
inc edi
inc edi
dec ecx
jnz @@hdloop
xor eax,eax
ret

@@err:
mov eax,1
ret
ENDP


Hope this will help.. You could check the SOL OS site here for more information. Unfortunatelly the version with this HDD app. isn't released yet.

Good luck! :alright:
Posted on 2003-04-09 19:10:58 by Hawkuletz
you shouldn't even program harddrive with port I/O from DOS. Only if you're messing around with os-dev.
"Increase your skill" ... there isn't really much skill to programming ATA through port I/O, the only "skill" involved would be googling for specifications and port commands.
Posted on 2003-04-10 02:14:02 by f0dder

you shouldn't even program harddrive with port I/O from DOS. Only if you're messing around with os-dev.
"Increase your skill" ... there isn't really much skill to programming ATA through port I/O, the only "skill" involved would be googling for specifications and port commands.


agreed :grin:

and if you have an enough time, make a PIC project to connect to ATA HD, so it can read/write it, the easy way is to use avaiable super i/o controller chip. i did once in my thesis, but its not hd, it simpler, its floppy :grin: that what you want to talk i though, if you place this thread in electronic.
Posted on 2003-04-10 06:19:03 by dion
Here is small program I did for using io/ports and read master boot record of drive c on win9x.



; use a dirty hack to get to ring 0 and read mbr with i/o-ports, on win 9x

.486
.model flat, stdcall
option casemap:none

include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
include \masm32\include\user32.inc
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\user32.lib

ReadMbr PROTO

.data?

Idtr df ?
hFile dd ?
bytesRet dd ?
bootSector db 512 dup (?)

.data

szApp db "bootsector2",0
szOk db "master boot record of drive c:",13,10
db "saved to "
szFileName db "mbr.txt",0
szFileFail db "Error saving file.",0

ioports dw 1f7h,1f5h,1f4h,1f3h,1f2h,1f6h
outbytes db 20h ,00h , 00h, 01h, 01h,0a0h

.code

; read mbr from drive c:

ReadMbr PROC
mov ecx, 6
mov esi, OFFSET ioports
mov edi, OFFSET outbytes

@@: mov dx, word ptr [esi-2+ecx*2]
mov al, byte ptr [edi-1+ecx]
out dx, al
dec ecx
jnz SHORT @B

@@: in al, dx
test al, 08h
jz SHORT @B

mov ecx, 128
mov esi, OFFSET bootSector
mov dx, 1f0h
rep insd
iretd
ReadMbr ENDP

start:

; Redirect int 3h in Interupt Descriptor Table

sidt fword ptr Idtr ; get far pointer to Interupt Descriptor Table
mov ebx, dword ptr Idtr+2 ; get the offset part of the far pointer
push [ebx+24] ; save the descriptor for int 3h (3*8=24)
push [ebx+28]
lea eax, ReadMbr ; Redirect int 3h to Our ReadMbr-procedure
mov word ptr [ebx+24], ax
shr eax, 16
mov word ptr [ebx+30], ax
pushad ; save registers
int 3h ; invoke ReadMbr
popad ; restore registers
pop [ebx+28] ; restore original int 3h-descriptor
pop [ebx+24]

; save the mbr to disk

invoke CreateFile, ADDR szFileName, GENERIC_WRITE, FILE_SHARE_WRITE, 0, CREATE_ALWAYS,\
FILE_ATTRIBUTE_NORMAL, 0
cmp eax, INVALID_HANDLE_VALUE
jnz @F
_fileFail:
invoke MessageBox, NULL, ADDR szFileFail, ADDR szApp, MB_ICONERROR
jmp _quit
@@: mov hFile, eax
invoke WriteFile, eax, ADDR bootSector, 512, ADDR bytesRet, 0
test eax, eax
jz _fileFail
invoke MessageBox, NULL, ADDR szOk, ADDR szApp, MB_ICONASTERISK
_quit:
invoke CloseHandle, hFile
invoke ExitProcess, 0

end start


http://www.nondot.org/sabre/os/articles/DiskandDiscDrives/ this site has description of io ports to drives and other low level stuff
Posted on 2003-04-10 06:57:45 by david
Thats why you keep telling me dont subscibe this thread :confused: .

Thanks David, int 31h is at Es=0 and DI=31*4, so....
es*16+DI*4
<==> 0+C4h
<==>C4h

It's located at C4. I try to call it like this...


mov eax,c4
call eax


But..., where I should put the Parameter.
Note: Please tell me if I done something wrong.:confused:
Posted on 2003-04-10 09:39:02 by realvampire
For a serious stuff you should code a .vxd for ring0 on win9x, but there is this trick to do it too.

The interupt descriptor table is an array of addresses for each of the interupts.
(You can't call these addresses directly, only by making an int-opcode, so you see you cannot pass any argument as you ask)
So you can choose one interupt that is not likely to be called by the operating system, like int 3h,
and substitue the address of that interrupt with the address of YOUR ROUTINE.
Then naturally, after doing that, if you call
int 3h
Your Routine will be called instead, but in ring0.
After returning you have to restore the original address of int3h in the IDT of course.
It is possible on win9x, because of some weird reason, they didn't protect memory area the interupt descriptor table resides in at all
from ring3 when designing the operating system. It works on WinMe too.

Most people in this forum will tell to code a vxd I'm sure, but it's a pretty cool little snippet to play with.
Posted on 2003-04-10 10:16:05 by david
ring0 hacks == bugs. But I guess that since microsoft have retired the 9x product line, they wont be fixed for this ugly abomination of a operating system ("exnteded dos extender" :grin: ).

realvampire, before you even consider messing with port I/O, especially harddrive related, you need a more thorough understanding of IA32. Even in realmode, you can NOT call an interrupt like that. A far call "might" work, but you'd have trouble when the interrupt code returns.

In protected mode, the IDT isn't located at base address 0 - it can be located anywhere. Windows will typically have it at some fixed address, but of course you shouldn't depend on this, and rather get it with sidt. And you shouldn't even mess with the IDT directly, but use the OS services for this. And on top of that, you can't really call dos interrupts from windows, they need to be executed in vm86 - and are totally unexistant on NT. BIOS interrupts will be available on NT too, since they're BIOS interrupts after all - but here you shouldn't even _think_ of calling them, unless you very much know what you're doing. And, honestly speaking, you don't.
Posted on 2003-04-10 10:25:04 by f0dder
Originally posted by f0dder
... unless you very much know what you're doing. And, honestly speaking, you don't.


...And, Honestly speaking. You're Right. :grin:

What is IA32?, Im hoping Dion translate a good resource about this. Now it be a Bit *Lazzy*. :stupid:
Posted on 2003-04-10 10:37:30 by realvampire
IA32 = Intel Architecture, 32bit processors.
You'll want to get yourself a copy of the intel pentium4 processor manuals from http://developer.intel.com (if you can't find them, let me know and I'll track down the PDFs for you - it's not like it's hard). Then you'll have to concentrate on volume 3, systems programming.

When you understand concepts like privileged instructions, paging, task switching (etc), you need to familiarize yourself with how windows uses that, and what restrictions it puts on you.

The conclusion you end up with, should be that direct harddrive programming just isn't done from "user" code - you only do this if you're writing a driver for the hardware. Or messing around with osdev :) (and you really should only do programming of this kind from a clean boot with your own bootsector code, I would recommend against it even from something as "clean" as DOS).
Posted on 2003-04-10 10:46:19 by f0dder