ATA interrupts confuse me ...

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

ATA interrupts confuse me ...

Post by Pype.Clicker »

this is more targetted at Tim, as i'm using his ATA driver as a source of inspiration for mine, but help is accepted from any Wizard of OS ...

So far, i figured out that each of the IDE controller (primary and secondary) had its own interrupt line: IRQ14 was for primary (based at I/O port 0x1F0) and IRQ15 was for secondary (based at I/O port 0x170).

but then why do i find

Code: Select all

    ...
    AtaReset(ctrl);
    r = in(ctrl->base + REG_CYL_LO);
    out(ctrl->base + REG_CYL_LO, ~r);
    if (in(ctrl->base + REG_CYL_LO) == r)
    {
        wprintf(L"Controller at %x not found: %x\n", base, r);
        /*return false;*/
    }

    DevRegisterIrq(AT_IRQ0, &ctrl->dev);
    ArchMaskIrq(1 << AT_IRQ0, 0);
    ...
maybe i should consider updating my CVS copy ...
or is there a reason i'm missing ? ...
RicoSanchez

Re:ATA interrupts confuse me ...

Post by RicoSanchez »

I don't know. What do you think that is missing?

I'm not working on an ATA device driver yet (not by far), but it seems to me that this code isn't complete yet. It checks for a controller and if it can't find one, it prints a message, the return is commented out, but the code below goes on with the fact that the controller is found. It seems not logical to me and thus it seems not complete to me for this reason.

Doesn't Tim comment somewhere if this code is operational or not?
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

Re:ATA interrupts confuse me ...

Post by Pype.Clicker »

what troubled me was the "IRQ0" regardless of the controller we used, but it seems that's a bug Tim fixed in a later version ...
Tim

Re:ATA interrupts confuse me ...

Post by Tim »

It seems you do have an old version of the source. The version on my hard disk has:

Code: Select all

    /* Check for controller */
    AtaReset(ctrl);
    r = in(ctrl->base + REG_CYL_LO);
    out(ctrl->base + REG_CYL_LO, ~r);
    if (in(ctrl->base + REG_CYL_LO) == r)
    {
        wprintf(L"Controller at %x not found: %x\n", base, r);
        /*return false;*/
    }

    DevRegisterIrq(irq, &ctrl->dev);
    ArchMaskIrq(1 << irq, 0);
    DevAddDevice(&ctrl->dev, name, cfg);
where [tt]irq[/tt] is a parameter to the [tt]AtaInitController[/tt] function where this code comes from. If you look at this file you'll see it's fairly recent.
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

Re:ATA interrupts confuse me ...

Post by Pype.Clicker »

Back online ...
I've been pushing my tests with ATA further and here are the (possible) useful hints i can provide you:

1. When unmasking hardware interrupt for ATA device (IRQ 14 and 15), don't forget to unmask the cascade IRQ aswell (IRQ2).

2. Some commands (and among them ATA_IDENTIFY 0xEC) respond very quickly, especially under BOCHS. So most of the other stuff (like preparing memory structure, or installing time-outs) should be performed either *before* the command is set or in a code section where interrupts are disable (yes, even if what you wanna do is receiving an interrupt 8) )

For instance,

Code: Select all

 kSemWait(ctrl->lock);
  // warning: prototype is outb(<value>, <port>) in Clicker !
  outb(ATA_IDENTIFY,ctrl->base+REG_COMMAND);
  ctrl->command=ATA_IDENTIFY;
  ctrl->status=STATUS_BSY;
  ctrl->requestor=getSysGlocals()->thread;
kSemSignal(ctrl->lock);
  
  log(KLOG_DEBUG,0,"sent ATA_IDENTIFY command to %s %s(%i)",ctrl->pname, drive_name[drive],drive);


  notifier=ti_setAfter(5000,ataTimeOutEvent);
  
  sign("waiting for event");
  e=eWait(ataTimeOutEvent,ataCtrlCompleteEvent,NULL);
   // code for analysis of the event received come here
didn't work:
  • if the disk is very fast (and BOCHS disk *is*), an IRQ signalling the end of the IDENTIFY command could be received before ctrl->requestor and ctrl->command are set, which will make the Interrupt Service Routine behave very weirdly.
  • nothing prevents ataCtrlCompleteEvent (generated by the ISR) to be sent before a receiver is planned with eWait( ... ), so the success of the command is likely to be lost.
The working code looks more like

Code: Select all

  kSysLock(&(ctrl->lock));
  ctrl->command=ATA_IDENTIFY;
  ctrl->status=STATUS_BSY;
  ctrl->requestor=getSysGlocals()->thread;
  outb(ATA_IDENTIFY,ctrl->base+REG_COMMAND);
  
  log(KLOG_DEBUG,0,"sent ATA_IDENTIFY command to %s %s(%i)",ctrl->pname,
      drive_name[drive],drive);

  notifier=ti_setAfter(5000,ataTimeOutEvent);
  
  sign("waiting for event");
  e=eWait(ataTimeOutEvent,ataCtrlCompleteEvent,NULL);
  kSysUnlock(&(ctrl->lock));
Note that the semaphore has been replaced by a mutex that disables interrupts while locked. This guarantees us we will not receive IRQ14 before we told the handler how it should understand it.
The call to eWait() will setup handler for both ataTimeOut and ataCtrlComplete events and then schedule to another thread (the current thread is put asleep). Once we enter one of those thread that will have its IF flag set, we can receive the interrupt from the drive.

This makes me wondering whether a busy-waiting loop would have been better ...
Tim

Re:ATA interrupts confuse me ...

Post by Tim »

On the subject of interrupts finishing quickly: whenever issuing a command which will result in an interrupt, I assume that the interrupt will occur immediately after issuing the command. That is, given:

Code: Select all

IssueCommandToDevice();
DoSomeOtherStuff();
...I assume that all interrupt handling might have completed before DoSomeOtherStuff() is called. This affects e.g. allocating something before the command is issued and freeing it inside the interrupt handler.
Post Reply