ATAPI (again)
Posted: Sun Mar 09, 2008 11:13 am
Hey
I'm having a spot of bother getting ATAPI to work, and the OSDev Wiki page on the subject is, unfortunately, less than helpful (starting with the fact that the ATA page starts with the section "What is ATAPI?", eh?)
I have a test machine, with an ATAPI CD-ROM connected as the Primary Slave of the standard IDE controller on the system (i.e. Device 1 of the ATA controller at I/O port 0x1F0).
I can send an atapi command to the device as the six words of data, but as soon as I receive the interrupt, the ERR bit is set with an Error register sense key of 6 (no idea what this means in it's context).
I have tried sending PLAY AUDIO [10], TEST UNIT READY and various other commands (including six words of garbage) with exactly the same result each time. I think I may be dealing with a duff device, but I haven't been able to find any succint examples of code for SendAtapiPacket().
My version of SendAtapiPacket is as follows:
I have the ATAPI-6 document, the MMC-4 document and the SPC-4 document, and if there were any more cross-references between them, I think my head would explode.
I have looked at the code from Dex's CDPod (didn't work ) and from the http://www.ata-atapi.com site (can't see what I'm doing differently / wrong).
If I can get this fixed and working, I'm going to post it up to the Wiki with some other information that the page lacks (unless someone wants to beat me to it) to improve that page and help others looking into this.
(PS: Any pointing out of silly mistakes will be humbly received)
I'm having a spot of bother getting ATAPI to work, and the OSDev Wiki page on the subject is, unfortunately, less than helpful (starting with the fact that the ATA page starts with the section "What is ATAPI?", eh?)
I have a test machine, with an ATAPI CD-ROM connected as the Primary Slave of the standard IDE controller on the system (i.e. Device 1 of the ATA controller at I/O port 0x1F0).
I can send an atapi command to the device as the six words of data, but as soon as I receive the interrupt, the ERR bit is set with an Error register sense key of 6 (no idea what this means in it's context).
I have tried sending PLAY AUDIO [10], TEST UNIT READY and various other commands (including six words of garbage) with exactly the same result each time. I think I may be dealing with a duff device, but I haven't been able to find any succint examples of code for SendAtapiPacket().
My version of SendAtapiPacket is as follows:
Code: Select all
void AtaPI_SendPacket( unsigned char* pPacket, int pLength )
{
// Sends an ATAPI packet command
// Based on ATA-ATAPI-6, PACKET command (section 8.24) and PACKET Command Protocol (section 9.8)
short lPortBase = 0x1F0;
char lOverlap = 0;
char lDMA = 0;
char lTag = 0;
unsigned short lByteCount = 0xFFFF;
char lDevice = 1;
unsigned char lCount;
unsigned short lCommand;
lOverlap &= 0x01;
lDMA &= 0x01;
lTag &= 0x1F;
lDevice &= 0x01;
// Initial status is 0x50 (DRDY set, bit 4 set)
Ata_ShowStatus( lPortBase );
// Set initial imput conditions
Ports_OutB( lPortBase + ATA_ERROR_FEATURES, (lOverlap << 1) | lDMA ); // Sets OVERLAP and DMA
Ports_OutB( lPortBase + ATA_SECTORCOUNT, lTag << 3 ); // Sets TAG
Ports_OutB( lPortBase + ATA_LBA_LOW, 0x00 ); // Does nothing
Ports_OutB( lPortBase + ATA_LBA_MID, (lByteCount & 0xFF) ); // Sets the Byte Count Low
Ports_OutB( lPortBase + ATA_LBA_HIGH, (lByteCount & 0xFF00) >> 8 ); // Sets the Byte Count High
Ports_OutB( lPortBase + ATA_DEVICE, lDevice << 4 ); // Set the Device
mWaitingForInterrupt = 1;
Ports_OutB( lPortBase + ATA_STATUS_COMMAND, 0xA0 ); // Send PACKET command
Ata_WaitForInterrupt();
// Now in "HP0: Check_Status_A" state
// If BSY is set, continue to wait
Timer_Delay( 10 );
while ( Ports_InB( lPortBase + ATA_STATUS_COMMAND ) & 0x80 )
{
Timer_Delay( 10 );
}
// Status is now 0x58 (DRQ now set)
Ata_ShowStatus( lPortBase );
// If BSY is clear and DRQ is clear, return to Idle
if ( Ports_InB( lPortBase + ATA_STATUS_COMMAND ) & 0x88 == 0x00 )
{
// Doesn't come in here
return;
}
// Now in "HP1: Send_Packet" state
// Send Command Packet to the Data port
mWaitingForInterrupt = 1;
for ( lCount = 0 ; lCount < pLength ; lCount += 2 )
{
lCommand = *((unsigned short*)&pPacket[lCount]);
String_kprintf( "0x%04X\n", lCommand );
Ports_OutS( lPortBase + ATA_DATA, lCommand );
}
Ata_WaitForInterrupt();
// Status is now 0x51 (DRQ clear, CHK set)
Ata_ShowStatus( lPortBase );
// Error Register now contains 0x60
Ata_ShowError( lPortBase );
}
I have the ATAPI-6 document, the MMC-4 document and the SPC-4 document, and if there were any more cross-references between them, I think my head would explode.
I have looked at the code from Dex's CDPod (didn't work ) and from the http://www.ata-atapi.com site (can't see what I'm doing differently / wrong).
If I can get this fixed and working, I'm going to post it up to the Wiki with some other information that the page lacks (unless someone wants to beat me to it) to improve that page and help others looking into this.
(PS: Any pointing out of silly mistakes will be humbly received)