1
0
Fork 0
forked from len0rd/rockbox

Now uses READ MULTIPLE command. Also corrected some return values.

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@2186 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Björn Stenberg 2002-09-05 15:25:08 +00:00
parent e4d35f6170
commit 8ccbc766a4

View file

@ -70,8 +70,12 @@
#define CMD_READ_SECTORS 0x20
#define CMD_WRITE_SECTORS 0x30
#define CMD_READ_MULTIPLE 0xC4
#define CMD_WRITE_MULTIPLE 0xC5
#define CMD_SET_MULTIPLE_MODE 0xC6
#define CMD_STANDBY_IMMEDIATE 0xE0
#define CMD_STANDBY 0xE2
#define CMD_IDENTIFY 0xEC
#define CMD_SLEEP 0xE6
#define CMD_SECURITY_FREEZE_LOCK 0xF5
@ -96,6 +100,9 @@ static int delayed_sector_num;
static long last_user_activity = -1;
static long last_disk_activity = -1;
static int multisectors; /* number of supported multisectors */
static unsigned short identify_info[SECTOR_SIZE];
#ifdef USE_POWEROFF
static int ata_power_on(void);
#endif
@ -110,13 +117,9 @@ static int wait_for_bsy(void)
yield();
if (TIME_BEFORE(current_tick, timeout))
{
return 1;
}
else
{
return 0; /* timeout */
}
}
static int wait_for_rdy(void) __attribute__ ((section (".icode")));
@ -134,13 +137,9 @@ static int wait_for_rdy(void)
yield();
if (TIME_BEFORE(current_tick, timeout))
{
return STATUS_RDY;
}
else
{
return 0; /* timeout */
}
}
static int wait_for_start_of_transfer(void) __attribute__ ((section (".icode")));
@ -166,7 +165,6 @@ int ata_read_sectors(unsigned long start,
int count,
void* buf)
{
int i;
int ret = 0;
last_disk_activity = current_tick;
@ -193,7 +191,7 @@ int ata_read_sectors(unsigned long start,
if (!wait_for_rdy())
{
mutex_unlock(&ata_mtx);
return -1;
return -2;
}
led(true);
@ -207,27 +205,36 @@ int ata_read_sectors(unsigned long start,
ATA_LCYL = (start >> 8) & 0xff;
ATA_HCYL = (start >> 16) & 0xff;
ATA_SELECT = ((start >> 24) & 0xf) | SELECT_LBA | ata_device;
ATA_COMMAND = CMD_READ_SECTORS;
ATA_COMMAND = CMD_READ_MULTIPLE;
for (i=0; i<count; i++) {
while (count) {
int j;
int sectors;
if (!wait_for_start_of_transfer())
{
led(false);
mutex_unlock(&ata_mtx);
return -1;
}
/* if destination address is odd, use byte copying,
otherwise use word copying */
if (count >= multisectors )
sectors = multisectors;
else
sectors = count;
if ( (unsigned int)buf & 1 ) {
for (j=0; j<SECTOR_SIZE/2; j++) {
for (j=0; j < sectors * SECTOR_SIZE / 2; j++) {
unsigned short tmp = SWAB16(ATA_DATA);
((unsigned char*)buf)[j*2] = tmp >> 8;
((unsigned char*)buf)[j*2+1] = tmp & 0xff;
}
}
else {
for (j=0; j<SECTOR_SIZE/2; j++)
for (j=0; j < sectors * SECTOR_SIZE / 2; j++)
((unsigned short*)buf)[j] = SWAB16(ATA_DATA);
}
@ -235,13 +242,14 @@ int ata_read_sectors(unsigned long start,
/* reading the status register clears the interrupt */
j = ATA_STATUS;
#endif
buf += SECTOR_SIZE; /* Advance one sector */
buf += sectors * SECTOR_SIZE; /* Advance one sector */
count -= sectors;
}
led(false);
if(!wait_for_end_of_transfer())
ret = -1;
ret = -3;
led(false);
mutex_unlock(&ata_mtx);
@ -283,7 +291,7 @@ int ata_write_sectors(unsigned long start,
if (!wait_for_rdy())
{
mutex_unlock(&ata_mtx);
return 0;
return -2;
}
led(true);
@ -318,7 +326,8 @@ int ata_write_sectors(unsigned long start,
led(false);
i = wait_for_end_of_transfer();
if(!wait_for_end_of_transfer())
i = -3;
mutex_unlock(&ata_mtx);
@ -375,7 +384,7 @@ static int freeze_lock(void)
ATA_COMMAND = CMD_SECURITY_FREEZE_LOCK;
if (!wait_for_rdy())
return -1;
return -2;
return 0;
}
@ -415,7 +424,7 @@ static int ata_perform_sleep(void)
if (!wait_for_rdy())
{
DEBUGF("ata_perform_sleep() - CMD failed\n");
ret = -1;
ret = -2;
}
#endif
sleeping = true;
@ -479,7 +488,7 @@ int ata_hard_reset(void)
PADR |= 0x0200;
ret = wait_for_rdy();
ret = wait_for_rdy();
/* Massage the return code so it is 0 on success and -1 on failure */
ret = ret?0:-1;
@ -624,6 +633,31 @@ void ata_enable(bool on)
PAIOR |= 0x80;
}
static int identify(void)
{
int i;
if(!wait_for_rdy()) {
DEBUGF("identify() - not RDY\n");
return -1;
}
ATA_SELECT = ata_device;
ATA_COMMAND = CMD_IDENTIFY;
if (!wait_for_start_of_transfer())
{
DEBUGF("identify() - CMD failed\n");
return -2;
}
for (i=0; i<SECTOR_SIZE/2; i++)
/* the IDENTIFY words are already swapped */
identify_info[i] = ATA_DATA;
return 0;
}
int ata_init(void)
{
mutex_init(&ata_mtx);
@ -644,6 +678,11 @@ int ata_init(void)
if (freeze_lock())
return -4;
if (identify())
return -5;
multisectors = identify_info[47] & 0xff;
DEBUGF("ata: %d sectors per ata request\n",multisectors);
queue_init(&ata_queue);
create_thread(ata_thread, ata_stack,