Page 1 of 1

ATAPI IRQ Recieving problem

Posted: Mon Jun 07, 2010 1:42 pm
by Freddy
Hi
At the moment I am trying to code an CD Driver in DMA and PIO mode. But my problem is that I do not get an IRQ from the device. But I also get no error message. :( So does anyone has an idear why I do not get an irq from the atapi deviece ??

Emulator

Code: Select all

 QEMU PC emulator version 0.12.3 (qemu-kvm-0.12.3), Copyright (c) 2003-2008 Fabrice Bellard
Source which checks for errors:

Code: Select all

bool ATA_ATAPI::check_error(unsigned short channel) {

     if((inportb(channel + 7) & 0x1) == 1){

        //Scan Error Resgister

        if((inportb(channel + 1) & 0x1) == 1) 

            error_ata_atapi = (char *)"Address Mark Not Found";

        else if((inportb(channel + 1) & 0x2) == 2)

            error_ata_atapi = (char *)"Track 0 Not Found";

        else if((inportb(channel + 1) & 0x4) == 4)

            error_ata_atapi = (char *)"command aborted";

        else if((inportb(channel + 1) & 0x8) == 8)

            error_ata_atapi = (char *)"Media Change Requested";

        else if((inportb(channel + 1) & 0x10) == 16)

            error_ata_atapi = (char *)"ID mark Not Found";

        else if((inportb(channel + 1) & 0x20) == 32)

            error_ata_atapi = (char *)"Media Changed";

        else if((inportb(channel + 1) & 0x40) == 64)

            error_ata_atapi = (char *)"Uncorrectable data error";

        else if((inportb(channel + 1) & 0x80) == 128)

            error_ata_atapi = (char *)"Bad Block";  

        return false; 

     } 

     else

        return true;

} 
Setup the Irq:

Code: Select all

void ATA_ATAPI::set_up_irq(int *channel_n)

{   

    // Paralel IDE uses IRQ 14 and 15

    if(pci_interface->results[0].pci_device->Prog_I_F == 0x8A || pci_interface->results[0].pci_device->Prog_I_F == 0x80) {	

      	if(*channel_n == 1) {

        	outportb(Prim_Device_Control_Register,0x4);

        	irq_install_handler(14, cd_handler);

      	}

      	else if(*channel_n == 2) {

         	outportb(Sec_Device_Control_Register ,0x4);  

         	irq_install_handler(15, cd_handler);

      	}

    }

    // If Serial IDE (not tested yet)

    else {

      	if(*channel_n == 1) {

        	outportb(Prim_Device_Control_Register,0x4);

        	irq_install_handler(pci_interface->results[0].pci_device->interupt_line, cd_handler);

      	}

      	else if(*channel_n == 2) {

         	outportb(Sec_Device_Control_Register ,0x4);  

         	irq_install_handler(pci_interface->results[0].pci_device->interupt_line, cd_handler);

      	}

    

   }

}
A parallel IDE drive will use IRQs 14 and 15 (http://wiki.osdev.org/IDE#Detecting_an_IDE_drive). It should be an parallel IDE drive because Prog if register is 0x80. I also set the SRST bit and cleared the nIEN bit in the Device Control Register. (http://stackoverflow.com/questions/8586 ... interrupts).

Start reading from the device:

Code: Select all

      unsigned short ide_offset; 

      ide_irq_invoked = 0;

      //Declare  unsigned char which contains the value of a ATAPI command packet ; 0xA8 Atpai read command

      uint8_t read_command[12] = { 0xA8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };

     // ide_scan();        


      outportb (0x176, 0xA0 & (1 << 4));

      timer_wait(1);


      outportb (0x171, 0x0);

      //Set Max byte count

      outportb (0x174, Atapi_Sector_Size & 0xFF);

      outportb (0x175, Atapi_Sector_Size>> 8);

      

      // Start IRQs

      set_up_irq(&IDEChannel[ide_offset].channel_n);

      outportb (0x177, 0xA0); 

      bool irq = pol_waiting(IDEChannel[ide_offset].channel);

      if(irq == false)

       {

        error_ata_atapi = (char *)"pol waiting error";      

        return false;

       }

      //Fill the ATAPI packet command

          

       read_command[9] = 1;              /* 1 sector */ 

       read_command[2] = (lba >> 0x18) & 0xFF;   /* most sig. byte of LBA */

       read_command[3] = (lba >> 0x10) & 0xFF;

       read_command[4] = (lba >> 0x08) & 0xFF;

      read_command[5] = (lba >> 0x00) & 0xFF;   /* least sig. byte of LBA */

    

      /* Send ATAPI/SCSI command */

           outportw (I0x170, ((uint16_t)read_command[0] << 8) |read_command[1]); 

     outportw (0x170, ((uint16_t)read_command[2] << 8) |read_command[3]);

     outportw (0x170, ((uint16_t)read_command[4] << 8) |read_command[5]);

     outportw (0x170, ((uint16_t)read_command[6] << 8) |read_command[7]);

     outportw (0x170, ((uint16_t)read_command[8] << 8) |read_command[9]);

     outportw (0x170, ((uint16_t)read_command[10] << 8) |read_command[11]);

      if(!check_error(2))
        return false;

      //Here I get now no IRQ
      wait_irq();
In the real code I store in a struct the channel number and if it is an ATA or ATAPi device. Therefore I know that this device is at channel 2. But to make think easier I use this time only the whole Primary CHannel ports.

Any idears :)

Re: ATAPI IRQ Recieving problem

Posted: Tue Jun 08, 2010 7:46 am
by pcmattman
The obvious things - are interrupts enabled (sti)? Have you installed proper IRQ handlers which work?

Not so obvious - check that interrupts are enabled on the ATA controller (check the control register, which is on a different port base IIRC).

Re: ATAPI IRQ Recieving problem

Posted: Tue Jun 08, 2010 10:22 am
by Freddy
Thanks for the reply :)
check that interrupts are enabled on the ATA controller
I write to the ATAPI controller follow:

Code: Select all

outportb(Sec_Device_Control_Register ,0x4);
Sec_Device_Control_Register has the value 0x376

0x4 means: SRST Bit 1; the rest 0


That should be the right setup for the Controller to allow IRQ' s or ???