ATA/ATAPI using DMA problem with the PRD Table
Posted: Sat May 15, 2010 9:56 am
Hi
I am trying to program an cd Driver who uses Dma to recieve datas from the CD. Therefore I tried to set up the prdt table with that code:
This is for the second ATA Channel
That code I used to set up the ptrd table
The function which return false;
Does anyone know why the transfer fail ??
I am trying to program an cd Driver who uses Dma to recieve datas from the CD. Therefore I tried to set up the prdt table with that code:
This is for the second ATA Channel
Code: Select all
..........
unsigned long addrr_bar4 = results[0].pci_device->bar4;
................
else if((addrr_bar4 & 0x1) == 1)
{
//Save start port in an var and add the offset (Secondary ATA bus)
int port = (addrr_bar4 & 0xFFFFFFFC) + 8;
//Go to the port to which we have to send the ptr table address
port+=7;
//make sure it is an DWORD and store the address into the var address
unsigned long address_of_ptr = (int)ptr_table & 0xFFFFFFFF;
//Send the first byte of the address
outportb(port, address_of_ptr & 0xFF);
port--;
//Send the second byte of the address
outportb(port, (address_of_ptr >> 8)& 0xFF);
port--;
outportb(port, (address_of_ptr >> 16)& 0xFF);
port--;
//Send the last byte
outportb(port,(address_of_ptr >>24) & 0xFF);
//Set Command byte. To start and write
outportb((addrr_bar4 & 0xFFFFFFFC) + 8, 0x81 & 0xFF);
}
Code: Select all
void DMA::setup_ptr_table(uint8_t count, unsigned long memory_space)
{
//set the value of the ptr table. Memory Space is the first DWORD. Count the next Word. Next word Reservt for MSB
//I was not sure if an unsigned char pointer can store an unsigned long var. So I wrote this. If he can only
*(ptr_table+3) = (unsigned char)(memory_space & 0xFF);
*(ptr_table+2) = (unsigned char)(memory_space >> 8);
*(ptr_table+1) = (unsigned char) (memory_space >> 16);
*ptr_table = (unsigned char) (memory_space >> 24);
//Set the next DWORD. First 16 bit are 0 (reserver MSB). The next is the count. A count of 0 means 64 k
//I was not sure if an unsigned char pointer can store an unsigned long var. So I wrote this. If he can only
*(ptr_table+5) = (unsigned char) (count & 0xff);
*(ptr_table +4) = (unsigned char)(count >> 8);
//Set MSB
*(ptr_table+6) = 0x00;
*(ptr_table+7) = 0x00;
*(ptr_table+8) = '\0';
}
Code: Select all
bool DMA::check_fail(int ata_bus)
{
//Read the two words of the BAR4 register
unsigned long addrr_bar4 = results[0].pci_device->bar4;
unsigned char* status_address;
unsigned long base_port;
if((addrr_bar4 & 0x1 ) == 0) {
status_address = (unsigned char *)(addrr_bar4 & 0xFFFFFFF0);
if(ata_bus == 1) {
if(status_address[2] & 0x2 == 2)
return false;
}
else {
if(status_address[10] & 0x2 == 2)
return false;
}
}
else {
base_port = (addrr_bar4 & 0xFFFFFFFC);
if (ata_bus == 1)
base_port += 2;
else
base_port += 10;
unsigned char staus_register = inportb(base_port);
if(staus_register & 0x2 == 2)
return false;
}
return true;
}