📄 ata.c
字号:
{
Int16 i;
Uint8* id = buffer;
/* ATA specific values */
Uint16 identifier;
Uint8 model[64];
Uint8 serial[64];
Uint32 size;
Uint16 transfer_number;
ATA_readId( ( Uint32 )id );
/* Check for valid identifier */
identifier = ( id[1] << 8 ) + id[0];
printf( " HDD Identifier: 0x%x\n", identifier );
if ( ( identifier & 0x07FF ) != 0x045a )
{
printf( " Invalid HDD identifier found\n" );
return 1;
}
/* Print model number */
for ( i = 0 ; i < 40 ; i += 2 )
{
model[i] = id[i + 55];
model[i + 1] = id[i + 54];
}
model[40] = 0;
printf( " Model number: [%s]\n", model );
/* Print serial number */
for ( i = 0 ; i < 20 ; i += 2 )
{
serial[i] = id[i + 21];
serial[i + 1] = id[i + 20];
}
serial[20] = 0;
printf( " Serial number: [%s]\n", serial );
/* Print capacity */
size = id[123];
size = ( size << 8 ) + id[122];
size = ( size << 8 ) + id[121];
size = ( size << 8 ) + id[120];
size = size >> 1;
printf( " Capacity: %d Kbytes\n", size );
printf( " Capacity: %d Mbytes\n", size >> 10 );
/* Print transfer mode support */
transfer_number = ( ( id[129] << 8 ) + id[128] ) & 0x00FF;
transfer_number = firstbit( transfer_number );
printf( " PIO mode: %d supported\n", transfer_number );
transfer_number = ( ( id[127] << 8 ) + id[126] ) & 0x00FF;
transfer_number = firstbit( transfer_number );
printf( " Multi-DMA mode: %d supported\n", transfer_number );
transfer_number = ( ( id[177] << 8 ) + id[176] ) & 0x00FF;
transfer_number = firstbit( transfer_number );
printf( " Ultra DMA mode: %d supported\n", transfer_number );
return 0;
}
/* ------------------------------------------------------------------------ *
* *
* ATA_readSector( src, dst, len ) *
* *
* src: address to read from *
* dst: sector to store data *
* count: number of sectors *
* *
* ------------------------------------------------------------------------ */
Int16 ATA_readSector( Uint32 src, Uint32 dst, Uint32 count )
{
Int16 retcode = 0;
Uint32 sector;
Uint32 start = src, end = src + count;
Int32 i;
Uint16* dst16 = ( Uint16* )dst;
for ( sector = start ; sector < end ; sector++ )
{
ATA_issueCommand( ATA_READ_SECTOR, sector );// Issue Read Sector
retcode |= waitWhileIntrqLow( -1 ); // Wait on INTRQ to go high
retcode |= waitWhileBSYHigh( -1 ); // Wait on BSY to go low
for ( i = 0 ; i < ATA_SECTOR_SIZE ; i += 2 )// Read data
*dst16++ = PRI_ATA_DATA16;
}
return retcode;
}
/* ------------------------------------------------------------------------ *
* *
* ATA_readSectorDma( src, dst, len, timeout ) *
* *
* src: address to read from *
* dst: sector to store data *
* count: number of sectors *
* *
* ------------------------------------------------------------------------ */
Int16 ATA_readSectorDma( Uint32 src, Uint32 dst, Uint32 count, Uint32 timeout )
{
Int16 retcode = 0;
Uint32 sector;
Uint32 start = src, end = src + count;
for ( sector = start ; sector < end ; sector++, dst += ATA_SECTOR_SIZE )
{
*ata_prd_word0 = dst; // Setup PRD address
*ata_prd_word1 = ( 1 << 31 ) // Setup PRD size + EOT
| ( ATA_SECTOR_SIZE );
ATA_BMICP_PRI = 0x0000; // Reset DMA controls
ATA_BMISP_PRI = 0x000E; // Clear interrupts
ATA_BMIDTP_PRI = ATA_PRD_TABLE; // Set DMA PRD
ATA_issueCommand( ATA_READ_DMA, sector ); // Issue Read DMA
ATA_BMICP_PRI = ( 1 << 3 ) | ( 1 << 0 ); // Start DMA
/* Note: At this point the ATA DMA is now transfering to the
* Harddrive. When the Harddrive acknowledges the previously
* sent command, the DMARQ line will be asserted and the
* ATA DMA will get to work transferring to the harddrive.
*/
while ( ( ATA_BMISP_PRI & 0x01 ) == 0x1 ) // Wait for DMA to stop
if ( ( ATA_BMISP_PRI & 0x05 ) == 0x05 ) // Break for interrupt
break;
/*
* Note: At this point the DMA should be finished, and the
* Sector data is now in ATA FIFO. Depending on the
* location of dst, ( DDR2, Interal RAM, AEMIF, .. )
* it will take some time to transfer the data.
*/
DAVINCIEVM_wait( timeout );
switch( ATA_BMISP_PRI & 0x0005 ) // Check DMA status
{
case 4: // Transfer Over
ATA_BMICP_PRI = 0; // Stop DMA
ATA_BMISP_PRI = 0x0004; // Clear Interrupts
break;
case 5: // Interrupt recieved
ATA_BMICP_PRI = 0; // Stop DMA
ATA_BMISP_PRI = 0x0004; // Clear Interrupts
break;
case 1: // Still running ?!?
retcode = -1; // Return error
break;
case 0:
retcode = -2; // DMA error
break;
}
}
return retcode;
}
/* ------------------------------------------------------------------------ *
* *
* ATA_writeSector( src, dst, len ) *
* *
* src: address to write from *
* dst: sector to write to *
* count: number of sectors *
* *
* ------------------------------------------------------------------------ */
Int16 ATA_writeSector( Uint32 src, Uint32 dst, Uint32 count )
{
Int16 retcode = 0;
Uint32 sector;
Uint32 start = dst, end = dst + count;
Int32 i;
Uint16 *src16 = ( Uint16* )src;
for ( sector = start ; sector < end ; sector++ )
{
ATA_issueCommand( ATA_WRITE_SECTOR, sector ); // Issue Write Sector
retcode |= waitWhileBSYHigh( -1 ); // Wait for BSY to go high
for ( i = 0 ; i < ATA_SECTOR_SIZE ; i += 2 ) // Write data
PRI_ATA_DATA16 = *src16++;
retcode |= waitWhileBSYHigh( -2 ); // Wait for BSY to go high
}
return retcode;
}
/* ------------------------------------------------------------------------ *
* *
* ATA_writeSectorDma( src, dst, len, timeout ) *
* *
* src: address to write from *
* dst: sector to write to *
* count: number of sectors *
* *
* ------------------------------------------------------------------------ */
Int16 ATA_writeSectorDma( Uint32 src, Uint32 dst, Uint32 count, Uint32 timeout )
{
Int16 retcode = 0;
Uint32 sector;
Uint32 start = dst, end = dst + count;
for ( sector = start ; sector < end ; sector++, src += ATA_SECTOR_SIZE )
{
*ata_prd_word0 = src; // Setup PRD address
*ata_prd_word1 = ( 1 << 31 ) // Setup PRD size
| ( ATA_SECTOR_SIZE );
ATA_BMICP_PRI = 0x0000; // Reset DMA controls
ATA_BMISP_PRI = 0x000E; // Clear interrupts
ATA_BMIDTP_PRI = ATA_PRD_TABLE; // Set PRD
ATA_issueCommand( ATA_WRITE_DMA, sector ); // Issue Write DMA
ATA_BMICP_PRI = ( 0 << 3 ) | ( 1 << 0 ); // Start DMA
/* Note: At this point the ATA DMA is now transfering to the
* Harddrive. When the Harddrive acknowledges the previously
* sent command, the DMARQ line will be asserted and the
* ATA DMA will get to work transferring to the harddrive.
*/
while ( ( ATA_BMISP_PRI & 0x01 ) == 0x1 ) // Wait for DMA to stop
if ( ( ATA_BMISP_PRI & 0x05 ) == 0x05 ) // Break for interrupt
break;
/*
* Note: At this point the DMA should be finished, and the
* Sector data is now in Harddrive FIFO. Depending on the
* Harddrive it will take some time to write the data.
*/
waitWhileIntrqLow( -1 ); // Wait for INTRQ from disk
DAVINCIEVM_wait( timeout );
switch( ATA_BMISP_PRI & 0x0005 ) // Check DMA status
{
case 4: // Transfer Over
ATA_BMICP_PRI = 0; // Stop DMA
ATA_BMISP_PRI = 0x0004; // Clear Interrupts
break;
case 5: // Interrupt recieved
ATA_BMICP_PRI = 0; // Stop DMA
ATA_BMISP_PRI = 0x0004; // Clear Interrupts
break;
case 1: // Still running ?!?
retcode = -1; // Return error
break;
case 0:
retcode = -2; // DMA error
break;
}
}
return retcode;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -