flat assembler
Message board for the users of flat assembler.
![]() |
Author |
|
Dex4u 16 Jun 2011, 21:01
Are you acknowledging the IRQ ?.
Eg: Code: mov al,0x20 out 0xa0,al out 0x20,al |
|||
![]() |
|
Hapkidoyoka 16 Jun 2011, 22:52
Thanks Dex.
Yes, I'm clearing the APIC EOI (not using PIC), but the ISR isn't firing at all; unless I read the status register twice after sending any commands. If it helps, I'm in long mode and the problem ATA controller is operating in native mode (single IRQ 15, 2 channels). All other ISRs are running fine the IOAPIC sends all interrupts to the BSP only. I have exhausted all the ATA specs/docs/forums I can find. Now I'm hoping someone who may have came across this before can help... please???? |
|||
![]() |
|
Dex4u 16 Jun 2011, 23:21
|
|||
![]() |
|
Hapkidoyoka 17 Jun 2011, 15:49
Yes Dex, but I did read it again carefully several times again after you suggested it.
I have stripped my init code down to something that should be testable and/or readable: Code: COMMAND_PORT equ $EC00 CONTROL_PORT equ $E880 TESTME: ;select drive mov dx,COMMAND_PORT+6 ;drive/head shl al,4 mov al,$A0 ;! or $E0? out dx,al ; mov dx,CONTROL_PORT+2 ;alt status ; times 4 in al,dx ;400ns delay ;clear nIEN mov al,8 out dx,al ; times 4 in al,dx ;400ns delay ;id drive xor eax,eax mov dx,COMMAND_PORT+5 ;cyl high out dx,al dec edx ;cly low out dx,al dec edx ;sector mumber out dx,al dec edx ;sector count out dx,al add edx,5 ;back to COMMAND_PORT+7 command/status mov al,$EC ;IdentifyDrive ;debugstr "sending $EC%n" out dx,al mov dx,CONTROL_PORT+2 ;alt status times 5 in al,dx ;400ns delay + read ;debugstr 5 "waiting%n" ;check return from id xor ebx,ebx ;default HDD (atapiflag) inc al cmp al,1 ;bad if al=0 or al=1 ;debugstr be "bad id return%n" jbe .error ;wait for id to complete @@: in al,dx test al,$80 ;BSY jnz @b test al,$9 ;DRQ or ERR jz @b test al,$1 ;ERR ;debugstr z "ATA drive%n" jz @f ;if no error, ok to proceed ;could be SATA/ATAPI mov dx,COMMAND_PORT+7 ;cmd/status in al,dx ;clear interrupt that didn't fire? sub edx,2 ;cyl high in al,dx shl eax,8 dec edx ;cyl low in al,dx cmp ax,$EB14 ;is it ATAPI? cmove ebx,eax ;set something into ebx atapi flag ;debugstr e "ATAPI drive%n" je @f cmp ax,$C33C ;is it SATA? ;debugstr e "SATA drive%n" jne .error ;read data @@: ;debugstr "reading data%n" mov rdi,buff mov ecx,256 mov dx,COMMAND_PORT ;data cld rep insw mov dx,CONTROL_PORT+2 ;alt status times 4 in al,dx ;400ns ;debugstr "data read%n" ;debugstr "select drive as lba28%n" ;select drive as lba28 mov dx,COMMAND_PORT+6 ;drive/head shl al,4 mov al,$E0 ;drive0 lba28 (block bits 24-27) out dx,al ;fill in lba info to block 0 mov dx,COMMAND_PORT+1 ;write precomensation xor eax,eax out dx,al inc eax inc edx ;sector count out dx,al xor eax,eax inc edx ;sector number (block bits 0-7) out dx,al inc edx ;cyl low (block bits 8-15) out dx,al inc edx ;cyl high (block bits 16-23) out dx,al ;debugstr "wait for drive to RDY%n" mov dx,CONTROL_PORT+2 ;alt status @@: in al,dx test al,$80 ;BSY jnz @b test al,$40 ;RDY jz @b mov eax,$20 ;ReadSectorsRetry mov dx,COMMAND_PORT+7 ;cmd/status ;debugstr "sending read%n" out dx,al mov dx,CONTROL_PORT+2 ;alt status times 4 in al,dx ;400ns ;the ISR fires here, but reports status as D0 - which can't be a good thing When I send the ReadSectors the ISR fires and reports a value of 0xD0 in the status register. It seems that I'm an interrupt behind, and sending the ReadSectors is firing the interrupt that should have occured for the Identify; and the extra read status at the end is firing the interrupt for the ReadSectors? |
|||
![]() |
|
BAiC 17 Jun 2011, 18:33
this might seem off topic, but you really should get the base address from a PCI Enumerator. I test my code on multiple emulators/hardware and they all have different base addresses for their respective devices.
|
|||
![]() |
|
Hapkidoyoka 18 Jun 2011, 21:25
Agreed BAiC,
The numbers are from my systems PCI configuration space, and are correct. I merely put them in here as equs for simplicity of posting. The code posted is scratch written test code based on my current source; but it still exhibits the same behaviour. It's doing my noodle in! |
|||
![]() |
|
Cptpingu 21 Jun 2011, 14:12
Not looking good!
Until an ATA expert comes along will have to stick with polling????!!! I don't get how the controller/drive can be keeping hold of the interrupt until a status read (well two actually) occurs. That pretty much rules out (doesnt it) any possibility that the APIC or IOAPIC is in some weird state and holding back the IRQ. Anyone have any idea if perhaps the drive was in LBA48 mode (shouldn't be we only use LBA28) I've seen docs that say about writing to ports twice to set arguments... Just wonder if the "twice" bit could be related? |
|||
![]() |
|
BAiC 01 Jul 2011, 04:38
the Enumerator tells you what the interrupt vector is. I have multiple IDE controllers and my enumerator reports most of them having different IRQs.
|
|||
![]() |
|
BAiC 01 Jul 2011, 05:33
it's possible you have to add 1 to the IRQ number you find in the Enumerator. I'm pretty sure I read it in one of the IDE specs.
|
|||
![]() |
|
Hapkidoyoka 14 Jul 2011, 22:00
Sorry for the delay - been busy
![]() @BAiC: Thanks for the ideas, it always helps to reexamine the problem. @Cptpingu: Not looking good indeed, if we can't solve this, we'll have to implement full polling for now and shelf it for later. Firstly, just a point to confuse the issue... The device is on IRQ 18, I had patched the APIC to forward it as IRQ 15 on the cpu (I did this gain parity with vmware for testing, but forgot about it). Secondly, to hopefully clarify the issue... I am getting an interrupt from the device - just not anytime useful (like, after reading the status); so I don't think the IRQ number is an issue. So at the moment I have to poll until a command is complete, then read the status, and then the interrupt fires. Far from ideal, I think you'll agree. Is there any reason why this should be so? |
|||
![]() |
|
BAiC 22 Jul 2011, 12:07
I got the Interrupt Pin confused with the Interrupt Line documentation. the Pin is not valid when it's zero: INTA=1, INTB=2, etc. so nevermind that.
Code: shl al,4 mov al,$A0 ;! or $E0? I didn't spot it earlier but perhaps the code is just wrong: the first instruction in this sequence can be removed without changing the result. perhaps you meant OR al, 0xA0 rather than mov? if AL is supposed to be part of the LBA then the shift left doesn't occur at all. LBA28 bits 24..27 are the lowest order bits of the device register not the highest. I am currently entrenched in this area of development with Mathis and the driver I have for ATA does work. I'll upload my current version a little later. |
|||
![]() |
|
cod3b453 22 Jul 2011, 19:02
I only skimmed the code and don't particularly follow.
What device are you trying to access? (Note that ATAPI requires a packet to be programmed to the device) Assuming your command_port is actually the data port, I have port+2 down as the sector count register and port+0x206 as the alternate status; though this is for IDE controllers using ports 0x0170/0x01F0. |
|||
![]() |
|
BAiC 22 Jul 2011, 23:36
so how do you know where an interrupt fires in the sequence of the code?
|
|||
![]() |
|
edfed 23 Jul 2011, 12:06
irqs can be launched by many different signals.
active low, active high, active edge, etc... on apic, i don't have any idea about the possible variations, like maybe double impulse to fire one interrupt. did you try to use the PIC instead of use the APIC? it is simpler to use the pic first, and when you will have a working code around pic, you will have something ok to work with apic. |
|||
![]() |
|
< Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2025, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.