ATAPI IRQ Recieving problem
Posted: Mon Jun 07, 2010 1:42 pm
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
Source which checks for errors:
Setup the Irq:
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:
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
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
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;
}
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);
}
}
}
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();
Any idears