📄 ata.c
字号:
/*
* Copyright 2005 by Spectrum Digital Incorporated.
* All rights reserved. Property of Spectrum Digital Incorporated.
*
* Not for distribution.
*/
/*
* ATA Implementation
*
*/
/*
* Note: With the PLL set to 459 MHz and the default timing settings used
* the period in ULTRA DMA mode is about 60%-80% above spec.
* The Ultra DMA mode does work properly, but the throughput on writing
* to the harddrive will be much slower.
*/
#include "stdio.h"
#include "ata.h"
/* ------------------------------------------------------------------------ *
* *
* ATA_init( ) *
* *
* ------------------------------------------------------------------------ */
Int16 ATA_init( )
{
DAVINCIEVM_PMX_set( 0x00030000, 0 ); // Enable ATA pinmux
/*
* Configure ATA Controller for default mode ( PIO mode )
*/
ATA_IDETIMP = 0x8000; // Primary PIO mode
ATA_IDETIMS = 0x0000; // Secondary off
ATA_SIDETIM = 0x00; // Secondary IDE timing
ATA_SLEWCTL_L = 0x00; // Slew rate is 0
ATA_SLEWCTL_H = 0x00; // Slew rate is 0
ATA_IDESTATUS = 0x03; // IDE Status
ATA_UDMACTL = 0x0000; // Ultra DMA OFF
ATA_UDMATIM = 0x0000; // Ultra DMA timing
ATA_MISCCTL = 0x00000200; // Release ATA from reset
ATA_IDETIMP = 0x8000; // Primary PIO mode
PINMUX0&=0xffffffe0;
/* DAVINCIEVM_GPIO_setDirection(26,0);
DAVINCIEVM_GPIO_setOutput(26,0);
DAVINCIEVM_waitusec( 1000 );
DAVINCIEVM_GPIO_setOutput(26,1);
DAVINCIEVM_waitusec( 1000 );
DAVINCIEVM_waitusec( 1000 );
DAVINCIEVM_waitusec( 1000 );*/
DAVINCIEVM_GPIO_setDirection(40,0);
DAVINCIEVM_GPIO_setOutput(40,0);
DAVINCIEVM_GPIO_setDirection(16,0);
DAVINCIEVM_GPIO_setOutput(16,0);
return 0;
}
/* ------------------------------------------------------------------------ *
* *
* ATA_changeMode( ata_mode ) *
* *
* ------------------------------------------------------------------------ */
Int16 ATA_changeMode( Uint8 ata_mode )
{
Uint8 transfer_number = ata_mode & 0x07;
Uint8 transfer_mode = ata_mode & 0xF8;
if ( transfer_mode == ULTRA_DMA_MODE )
{
/* DMA Engine */
ATA_BMICP_PRI = 0x0000; // Primary DMA control
ATA_BMISP_PRI = 0x000E; // Primary DMA status
ATA_BMIDTP_PRI = ATA_PRD_TABLE; // Primary DMA PRD
ATA_BMICS_SEC = 0x0000; // Secondary DMA control
ATA_BMISS_SEC = 0x000E; // Secondary DMA status
ATA_BMIDTP_SEC = 0x0000; // Secondary DMA PRD
ATA_UDMACTL = 0x0003; // Ultra DMA ON
ATA_UDMATIM = 0 // Ultra DMA timing
| ( transfer_number << 4 )
| ( transfer_number << 0 )
;
}
if ( transfer_mode == MULTIWORD_DMA_MODE )
{
/* DMA Engine */
ATA_BMICP_PRI = 0x0000; // Primary DMA control
ATA_BMISP_PRI = 0x000E; // Primary DMA status
ATA_BMIDTP_PRI = ATA_PRD_TABLE; // Primary DMA PRD
ATA_BMICS_SEC = 0x0000; // Secondary DMA control
ATA_BMISS_SEC = 0x000E; // Secondary DMA status
ATA_BMIDTP_SEC = 0x0000; // Secondary DMA PRD
ATA_UDMACTL = 0x0000; // Ultra DMA OFF
ATA_UDMATIM = 0x0000; // Ultra DMA timing
}
if ( transfer_mode == PIO_MODE )
{
ATA_UDMACTL = 0x0000; // Ultra DMA OFF
ATA_UDMATIM = 0x0000; // Ultra DMA timing
}
ATA_setfeature( 0x03, ata_mode ); // Set transfer mode on harddrive
return 0;
}
/* ------------------------------------------------------------------------ *
* *
* waitWhileBSYHigh( timeout ) *
* *
* timeout: in cycles *
* *
* ------------------------------------------------------------------------ */
Int16 waitWhileBSYHigh( Uint32 timeout )
{
Uint32 timecount = 0;
while ( ( PRI_ATA_STATUS & 0x80 ) == 0x80 ) // Wait for signal to change
{
if ( ++timecount >= timeout )
{
printf( " ****BSY TIMEOUT occured****\n" );
return 1;
}
}
return 0;
}
/* ------------------------------------------------------------------------ *
* *
* waitWhileDRDYLow( timeout ) *
* *
* timeout: in cycles *
* *
* ------------------------------------------------------------------------ */
Int16 waitWhileDRDYLow( Uint32 timeout )
{
Uint32 timecount = 0;
while ( ( PRI_ATA_STATUS & 0x40 ) == 0x00 ) // Wait for signal to change
{
if ( ++timecount >= timeout )
{
printf( " ****DRDY TIMEOUT occured****\n" );
return 1;
}
}
return 0;
}
/* ------------------------------------------------------------------------ *
* *
* waitWhileIntrqLow( timeout ) *
* *
* timeout: in cycles *
* *
* ------------------------------------------------------------------------ */
Int16 waitWhileIntrqLow( Uint32 timeout )
{
Uint32 timecount = 0;
while ( ( ATA_IDESTATUS & 0x20 ) == 0x00 ) // Wait for signal to change
{
if ( ++timecount >= timeout )
{
printf( " ****Intrq TIMEOUT occured****\n" );
return 1;
}
}
return 0;
}
/* ------------------------------------------------------------------------ *
* *
* ATA_issueCommand( command, sector ) *
* *
* command: command code *
* sector: sector *
* *
* ------------------------------------------------------------------------ */
Int16 ATA_issueCommand( Uint8 command, Uint32 sector )
{
waitWhileDRDYLow( -1 ); // Wait until drive is ready
PRI_ATA_SECCNT = 0x01; // Issue command
PRI_ATA_LBA7_0 = ( sector & 0x000000ff );
PRI_ATA_LBA15_8 = ( sector & 0x0000ff00 ) >> 8;
PRI_ATA_LBA23_16 = ( sector & 0x00ff0000 ) >> 16;
PRI_ATA_LBA27_24 = ( ( sector & 0x0f000000 ) >> 24 ) | 0xe0;
PRI_ATA_CMD = command;
return 0;
}
/* ------------------------------------------------------------------------ *
* *
* ATA_setfeature( command, options ) *
* *
* command: Set Feature command *
* options: Set Feature options *
* *
* ------------------------------------------------------------------------ */
Int16 ATA_setfeature( Uint8 command, Uint8 options )
{
waitWhileDRDYLow( -1 ); // Wait until drive is ready
PRI_ATA_FEATURE = command;
PRI_ATA_SECCNT = options;
PRI_ATA_LBA7_0 = options;
PRI_ATA_LBA15_8 = options;
PRI_ATA_LBA23_16 = options;
PRI_ATA_LBA27_24 = 0;
PRI_ATA_CMD = ATA_SET_FEATURE;
waitWhileBSYHigh( -1 ); // Wait until complete
return 0;
}
/* ------------------------------------------------------------------------ *
* *
* ATA_readId( dst ) *
* Read the Harddrive ID sector *
* *
* dst: address of buffer *
* *
* ------------------------------------------------------------------------ */
Int16 ATA_readId( Uint32 dst )
{
Int16 i;
Uint16 *dst16 = ( Uint16* )dst;
for ( i = 0 ; i < ATA_SECTOR_SIZE ; i += 2 ) // Clear buffer
*dst16++ = 0;
dst16 = ( Uint16* )dst;
ATA_issueCommand( ATA_IDENTIFY_DEVICE, 0 ); // Issue ID command
waitWhileBSYHigh( -1 ); // Wait for BSY to drop low
for ( i = 0 ; i < ATA_SECTOR_SIZE ; i += 2 ) // Read data
*dst16++ = PRI_ATA_DATA16;
return 0;
}
static Int16 firstbit( Uint32 mask )
{
Int16 shiftamt;
Uint32 bit;
/* Find offset of first bit in mask */
for ( bit = 0x80000000, shiftamt = 32 ; shiftamt >= 0 ; shiftamt--, bit >>= 1 )
if ( bit & mask )
break;
/* Return location of first bit */
return shiftamt;
}
/* ------------------------------------------------------------------------ *
* *
* ATA_identify( ) *
* *
* *
* *
* ------------------------------------------------------------------------ */
Int16 ATA_identify( Uint8* buffer )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -