flat assembler
Message board for the users of flat assembler.
Index
> OS Construction > ATA Port IO |
Author |
|
ManOfSteel 15 Apr 2010, 09:44
First of all, you are using C/H/S.
Now for the code... In the 2nd and 3rd out operations, you send the sector and cylinder. Does the first word in current_sector (also bl and bh) contain these two? In the 4th operation, you send the rest of the cylinder. Does the high part of current_sector (also ebx) - which becomes the low part after bswap - contain that? In the 5th operation, you send the drive (bit 4) and head (bits 0-3) to be read. Bits 5-7 should always be 101b (they're reserved as such), but you have 111b. So it should be 0xa0 instead of 0xe0. As for the add dx,1, is there any reason you're not just doing inc dx? And please next time, add a comment for everyone of these lines to show the current port used for the out operation. It'd be much easier to read. And finally, even if the buffer is successfully filled with a sector, it may contain no printable characters at all. |
|||
15 Apr 2010, 09:44 |
|
edfed 15 Apr 2010, 10:37
maybe, i just say maybe... we need a function that will do the ATA disk read/writes.
something in fasm, simple to use, and that works great. then, nobody will have to rewrite the ATA driver. something like this code that dosin gave to me some mounth ago. Code: org 0x0600 use16 start: mov [DriveNo],dl xor ax,ax mov ds,ax mov es,ax mov ss,ax mov sp,0x7c00 sti cld mov si,sp mov di,0600h mov cx,438;512/2 rep movsw jmp 0000:main main: mov dx,0x3F2 mov al,0 out dx,al mov [hdbase],0x1F0 mov [hdid],0x00 mov eax,0x0 call hdd_read mov si,buffer ;move MBR to SI add si,446 ;add si 446 to start of portion find_portion: cmp byte[si],00h ;00h only one portion can be set bootable at a time jne boot_portion1 ;cmp until we find match. add si,16 ;if not set bootable check next portion p2: cmp byte[si],00h jne boot_portion2 add si,16 ;if not set bootable check next portion p3: cmp byte[si],00h jne boot_portion3 add si,16 ;if not set bootable check next portion p4: cmp byte[si],00h jne boot_portion4 jmp fin boot_portion1: jmp p11 boot_portion2: jmp p21 boot_portion3: jmp p31 boot_portion4: jmp p41 p11: add si,16 ;This is the were we get our lba info jmp nxt ;it tells us the location of the bootable p21: add si,16+16 ;portion jmp nxt p31: add si,16+16+16 jmp nxt p41: add si,16+16+16+16 nxt: mov di,lba ;copy it to LBA add si,8 mov bx,word[si] mov word[di],bx add si,2 mov bx,word[si] mov word[di+2],bx mov eax,dword[lba] ;load the lba sector call hdd_read mov sp,buffer ;our buffer now has the LBA bootable portion! sti cld mov si,sp mov di,0x7c00 mov cx,512/2 rep movsw mov dl,[DriveNo] xor ecx,ecx xor ebx,ebx xor eax,eax jmp 0000:7C00h ;here we jmp to it! fin: ;if no bootable portion ;you may want to put an error msg here! jmp $ lba dd 0x00000000 hdid db 0x00 hdbase dd 0x00 DriveNo: db 0 default: db 0 newln: db 13,10,0 hdd_read: pushad push eax newhd_read: mov edx,[hdbase] inc edx mov al,0 out dx,al inc edx mov al,1 out dx,al inc edx pop ax out dx,al inc edx shr ax,8 out dx,al inc edx pop ax out dx,al inc edx shr ax,8 and al,1+2+4+8 add al,[hdid] add al,128+64+32 out dx,al inc edx mov al,20h out dx,al hddwait: in al,dx test al,128 jnz hddwait mov edi,buffer mov ecx,256 mov edx,[hdbase] cld rep insw popad ret print: mov ah,0Eh ; Request display again1: lodsb ; load a byte into AL from DS:SI or al,al ; Or AL jz done1 ; Jump 0, to label done1 int 10h ; Call interrupt service jmp again1 ; Jump to label again1 done1: ret times 510 - ($-start) db 0 dw 0xaa55 buffer rb 512 i tried to convert it as a simple function, but some testing bored me until i gave up. maybe it is time to restart this project. |
|||
15 Apr 2010, 10:37 |
|
sinsi 15 Apr 2010, 11:02
Remember that INSW will write to [es:edi], not ds.
The code works for me in virtualpc - reading lba 0 gets me an mbr. |
|||
15 Apr 2010, 11:02 |
|
XanClic 15 Apr 2010, 13:59
ManOfSteel wrote: As for the add dx,1, is there any reason you're not just doing inc dx? Because it's at least equal when comparing speed if not faster. There's a reason why GCC compiles “i++” to something like “add ...,1” instead of “inc ...”. |
|||
15 Apr 2010, 13:59 |
|
revolution 15 Apr 2010, 14:08
Any code executing INSW is hardly a candidate for trying to optimise for speed. You're doing it wrong if you think add reg,1 will give any speed boost, the INSW will completely dominate the runtime.
If you want performance for that code then forget about 'add reg,1' vs 'inc reg'. Instead change to whole procedure to use DMA. |
|||
15 Apr 2010, 14:08 |
|
ManOfSteel 15 Apr 2010, 17:32
Exactly. The whole reason I proposed inc instead of add is that it's more readable (IMO, at least).
|
|||
15 Apr 2010, 17:32 |
|
cod3b453 15 Apr 2010, 18:25
Could be your wait loop - I have this for my CD driver:
Code: mov dx,ATA_REG_COMMAND @@: in al,dx test al,0x80 jnz @b @@: in al,dx test al,0x08 jnz @f Also you might need to assert es is correct and put cld before rep insw |
|||
15 Apr 2010, 18:25 |
|
XanClic 15 Apr 2010, 20:50
ManOfSteel wrote: Exactly. The whole reason I proposed inc instead of add is that it's more readable (IMO, at least). Well, you asked for “any” reason. |
|||
15 Apr 2010, 20:50 |
|
score_under 15 Apr 2010, 22:09
XanClic wrote:
Tested on my processor (AMD Athlon X2 64, running in 32bit mode) under Windows (none of my optical drives or floppy drives are working, I can't boot off anything), they take exactly the same amount of time. Looped 10000 times. Last edited by score_under on 20 Apr 2010, 20:04; edited 1 time in total |
|||
15 Apr 2010, 22:09 |
|
Tyler 15 Apr 2010, 22:30
I didn't use DMA because this is for my bootloader, DMA, from what little I read, seems like overkill for a bootloader. Then again, so was add *,1.
|
|||
15 Apr 2010, 22:30 |
|
ManOfSteel 15 Apr 2010, 23:12
Talking directly to the controller in your bootloader is overkill. Keep all the fun stuff for your PM device drivers, and use the BIOS for anything RM instead.
|
|||
15 Apr 2010, 23:12 |
|
Tyler 15 Apr 2010, 23:47
I'm trying to avoid using the bios, for no other reason than to learn how to do things on the small scale to make doing it in the kernel slightly easier. I guess I'll use the bios for this though. Thanks for the suggestions and I'll keep in mind how trivial add *,1 can be.
|
|||
15 Apr 2010, 23:47 |
|
< Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.