From 4058b79c70f5ec5c97fa7aa7c361098155c7e96c Mon Sep 17 00:00:00 2001 From: Linus Nielsen Feltzing Date: Wed, 26 Jan 2005 12:53:48 +0000 Subject: Ported ATA driver to iRiver, minor code policing git-svn-id: svn://svn.rockbox.org/rockbox/trunk@5663 a1c6a512-1295-4272-9138-f99709370657 --- firmware/drivers/ata.c | 277 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 181 insertions(+), 96 deletions(-) (limited to 'firmware/drivers') diff --git a/firmware/drivers/ata.c b/firmware/drivers/ata.c index 0983fb52ee..2385e74b4c 100644 --- a/firmware/drivers/ata.c +++ b/firmware/drivers/ata.c @@ -37,24 +37,84 @@ #define PREFER_C_WRITING #define ATA_IOBASE 0x20000000 -#define ATA_DATA (*((volatile unsigned short*)ATA_IOBASE)) -#define ATA_CONTROL (*((volatile unsigned short*)ATA_IOBASE + 0xe)) +#define ATA_DATA (*((volatile unsigned short*)(ATA_IOBASE + 0x20))) +#define ATA_CONTROL (*((volatile unsigned short*)(ATA_IOBASE + 0xe))) + +#define ATA_ERROR (*((volatile unsigned short*)(ATA_IOBASE + 0x22))) +#define ATA_NSECTOR (*((volatile unsigned short*)(ATA_IOBASE + 0x24))) +#define ATA_SECTOR (*((volatile unsigned short*)(ATA_IOBASE + 0x26))) +#define ATA_LCYL (*((volatile unsigned short*)(ATA_IOBASE + 0x28))) +#define ATA_HCYL (*((volatile unsigned short*)(ATA_IOBASE + 0x2a))) +#define ATA_SELECT (*((volatile unsigned short*)(ATA_IOBASE + 0x2c))) +#define ATA_COMMAND (*((volatile unsigned short*)(ATA_IOBASE + 0x2e))) + +#define STATUS_BSY 0x8000 +#define STATUS_RDY 0x4000 +#define STATUS_DF 0x2000 +#define STATUS_DRQ 0x0800 +#define STATUS_ERR 0x0100 + +#define ERROR_ABRT 0x0400 + +#define WRITE_PATTERN1 0xa5 +#define WRITE_PATTERN2 0x5a +#define WRITE_PATTERN3 0xaa +#define WRITE_PATTERN4 0x55 + +#define READ_PATTERN1 0xa500 +#define READ_PATTERN2 0x5a00 +#define READ_PATTERN3 0xaa00 +#define READ_PATTERN4 0x5500 + +#define SET_REG(reg,val) reg = ((val) << 8) +#define SET_16BITREG(reg,val) reg = (val) #elif CONFIG_CPU == SH7034 +#define SWAP_WORDS + #define ATA_IOBASE 0x06100100 #define ATA_DATA (*((volatile unsigned short*)0x06104100)) #define ATA_CONTROL1 ((volatile unsigned char*)0x06200206) #define ATA_CONTROL2 ((volatile unsigned char*)0x06200306) #define ATA_CONTROL (*ata_control) -#endif +#define ATA_ERROR (*((volatile unsigned char*)ATA_IOBASE + 1)) +#define ATA_NSECTOR (*((volatile unsigned char*)ATA_IOBASE + 2)) +#define ATA_SECTOR (*((volatile unsigned char*)ATA_IOBASE + 3)) +#define ATA_LCYL (*((volatile unsigned char*)ATA_IOBASE + 4)) +#define ATA_HCYL (*((volatile unsigned char*)ATA_IOBASE + 5)) +#define ATA_SELECT (*((volatile unsigned char*)ATA_IOBASE + 6)) +#define ATA_COMMAND (*((volatile unsigned char*)ATA_IOBASE + 7)) -#if CONFIG_CPU == TCC730 +#define STATUS_BSY 0x80 +#define STATUS_RDY 0x40 +#define STATUS_DF 0x20 +#define STATUS_DRQ 0x08 +#define STATUS_ERR 0x01 + +#define ERROR_ABRT 0x04 + +#define WRITE_PATTERN1 0xa5 +#define WRITE_PATTERN2 0x5a +#define WRITE_PATTERN3 0xaa +#define WRITE_PATTERN4 0x55 + +#define READ_PATTERN1 0xa5 +#define READ_PATTERN2 0x5a +#define READ_PATTERN3 0xaa +#define READ_PATTERN4 0x55 + +#define SET_REG(reg,val) reg = (val) +#define SET_16BITREG(reg,val) reg = (val) + +#elif CONFIG_CPU == TCC730 #define PREFER_C_READING #define PREFER_C_WRITING +#define SWAP_WORDS + #define ATA_DATA_IDX (0xD0) #define ATA_ERROR_IDX (0xD2) #define ATA_NSECTOR_IDX (0xD4) @@ -70,6 +130,7 @@ #define ATA_ALT_STATUS_IDX ATA_CONTROL_IDX #define SET_REG(reg, value) (ide_write_register(reg ## _IDX, value)) +#define SET_16BITREG(reg, value) (ide_write_register(reg ## _IDX, value)) #define GET_REG(reg) (ide_read_register(reg)) #define ATA_DATA (GET_REG(ATA_DATA_IDX)) @@ -85,6 +146,23 @@ #define ATA_ALT_STATUS (GET_REG(ATA_ALT_STATUS_IDX)) #define ATA_FEATURE (GET_REG(ATA_FEATURE_IDX)) +#define STATUS_BSY 0x80 +#define STATUS_RDY 0x40 +#define STATUS_DF 0x20 +#define STATUS_DRQ 0x08 +#define STATUS_ERR 0x01 + +#define ERROR_ABRT 0x04 + +#define WRITE_PATTERN1 0xa5 +#define WRITE_PATTERN2 0x5a +#define WRITE_PATTERN3 0xaa +#define WRITE_PATTERN4 0x55 + +#define READ_PATTERN1 0xa5 +#define READ_PATTERN2 0x5a +#define READ_PATTERN3 0xaa +#define READ_PATTERN4 0x55 extern int idatastart __attribute__ ((section(".idata"))); @@ -125,47 +203,15 @@ int ide_read_register(int reg) { return ide_reg_temp; } +#endif -#else - -/* generic registers */ -#define ATA_ERROR (*((volatile unsigned char*)ATA_IOBASE + 1)) -#define ATA_NSECTOR (*((volatile unsigned char*)ATA_IOBASE + 2)) -#define ATA_SECTOR (*((volatile unsigned char*)ATA_IOBASE + 3)) -#define ATA_LCYL (*((volatile unsigned char*)ATA_IOBASE + 4)) -#define ATA_HCYL (*((volatile unsigned char*)ATA_IOBASE + 5)) -#define ATA_SELECT (*((volatile unsigned char*)ATA_IOBASE + 6)) -#define ATA_COMMAND (*((volatile unsigned char*)ATA_IOBASE + 7)) #define ATA_FEATURE ATA_ERROR #define ATA_STATUS ATA_COMMAND #define ATA_ALT_STATUS ATA_CONTROL -#define SET_REG(reg, value) ((reg) = (value)) - -#endif - -#define SET_ATA_DATA(v) (SET_REG(ATA_DATA,v)) -#define SET_ATA_SELECT(v) (SET_REG(ATA_SELECT,v)) -#define SET_ATA_NSECTOR(v) (SET_REG(ATA_NSECTOR,v)) -#define SET_ATA_SECTOR(v) (SET_REG(ATA_SECTOR,v)) -#define SET_ATA_LCYL(v) (SET_REG(ATA_LCYL,v)) -#define SET_ATA_HCYL(v) (SET_REG(ATA_HCYL,v)) -#define SET_ATA_COMMAND(v) (SET_REG(ATA_COMMAND,v)) -#define SET_ATA_CONTROL(v) (SET_REG(ATA_CONTROL,v)) -#define SET_ATA_FEATURE(v) (SET_REG(ATA_FEATURE, v)) - - #define SELECT_DEVICE1 0x10 #define SELECT_LBA 0x40 -#define STATUS_BSY 0x80 -#define STATUS_RDY 0x40 -#define STATUS_DF 0x20 -#define STATUS_DRQ 0x08 -#define STATUS_ERR 0x01 - -#define ERROR_ABRT 0x04 - #define CONTROL_nIEN 0x02 #define CONTROL_SRST 0x04 @@ -190,7 +236,9 @@ int ide_read_register(int reg) { static struct mutex ata_mtx; char ata_device; /* device 0 (master) or 1 (slave) */ int ata_io_address; /* 0x300 or 0x200, only valid on recorder */ +#if CONFIG_CPU == SH7034 static volatile unsigned char* ata_control; +#endif bool old_recorder = false; int ata_spinup_time = 0; @@ -294,8 +342,13 @@ static void copy_read_sectors(unsigned char* buf, int wordcount) { /* loop compiles to 9 assembler instructions */ /* takes 14 clock cycles (2 pipeline stalls, 1 wait) */ tmp = ATA_DATA; +#ifdef SWAP_WORDS *buf++ = tmp & 0xff; /* I assume big endian */ *buf++ = tmp >> 8; /* and don't use the SWAB16 macro */ +#else + *buf++ = tmp >> 8; + *buf++ = tmp & 0xff; +#endif } while (buf < bufend); /* tail loop is faster */ } else @@ -305,7 +358,11 @@ static void copy_read_sectors(unsigned char* buf, int wordcount) do { /* loop compiles to 7 assembler instructions */ /* takes 12 clock cycles (2 pipeline stalls, 1 wait) */ +#ifdef SWAP_WORDS *wbuf = SWAB16(ATA_DATA); +#else + *wbuf = ATA_DATA; +#endif } while (++wbuf < wbufend); /* tail loop is faster */ } #else @@ -415,7 +472,7 @@ int ata_read_sectors(IF_MV2(int drive,) int timeout; int count; void* buf; - int spinup_start; + long spinup_start; #ifdef HAVE_MULTIVOLUME (void)drive; /* unused for now */ @@ -447,7 +504,7 @@ int ata_read_sectors(IF_MV2(int drive,) timeout = current_tick + READ_TIMEOUT; - SET_ATA_SELECT(ata_device); + SET_REG(ATA_SELECT, ata_device); if (!wait_for_rdy()) { mutex_unlock(&ata_mtx); @@ -463,15 +520,15 @@ int ata_read_sectors(IF_MV2(int drive,) last_disk_activity = current_tick; if ( count == 256 ) - SET_ATA_NSECTOR(0); /* 0 means 256 sectors */ + SET_REG(ATA_NSECTOR, 0); /* 0 means 256 sectors */ else - SET_ATA_NSECTOR((unsigned char)count); + SET_REG(ATA_NSECTOR, (unsigned char)count); - SET_ATA_SECTOR(start & 0xff); - SET_ATA_LCYL((start >> 8) & 0xff); - SET_ATA_HCYL((start >> 16) & 0xff); - SET_ATA_SELECT(((start >> 24) & 0xf) | SELECT_LBA | ata_device); - SET_ATA_COMMAND(CMD_READ_MULTIPLE); + SET_REG(ATA_SECTOR, start & 0xff); + SET_REG(ATA_LCYL, (start >> 8) & 0xff); + SET_REG(ATA_HCYL, (start >> 16) & 0xff); + SET_REG(ATA_SELECT, ((start >> 24) & 0xf) | SELECT_LBA | ata_device); + SET_REG(ATA_COMMAND, CMD_READ_MULTIPLE); /* wait at least 400ns between writing command and reading status */ __asm__ volatile ("nop"); @@ -572,11 +629,18 @@ static void copy_write_sectors(const unsigned char* buf, int wordcount) unsigned short tmp = 0; const unsigned char* bufend = buf + wordcount*2; do - { /* loop compiles to 9 assembler instructions */ + { +#ifdef SWAP_WORDS + /* SH1: loop compiles to 9 assembler instructions */ /* takes 13 clock cycles (2 pipeline stalls) */ tmp = (unsigned short) *buf++; tmp |= (unsigned short) *buf++ << 8; /* I assume big endian */ - SET_ATA_DATA(tmp); /* and don't use the SWAB16 macro */ + SET_16BITREG(ATA_DATA, tmp); /* and don't use the SWAB16 macro */ +#else + tmp = (unsigned short) *buf++ << 8; + tmp |= (unsigned short) *buf++; + SET_16BITREG(ATA_DATA, tmp); +#endif } while (buf < bufend); /* tail loop is faster */ } else @@ -584,9 +648,14 @@ static void copy_write_sectors(const unsigned char* buf, int wordcount) unsigned short* wbuf = (unsigned short*)buf; unsigned short* wbufend = wbuf + wordcount; do - { /* loop compiles to 6 assembler instructions */ + { +#ifdef SWAP_WORDS + /* loop compiles to 6 assembler instructions */ /* takes 10 clock cycles (2 pipeline stalls) */ - SET_ATA_DATA(SWAB16(*wbuf)); + SET_16BITREG(ATA_DATA, SWAB16(*wbuf)); +#else + SET_16BITREG(ATA_DATA, *wbuf); +#endif } while (++wbuf < wbufend); /* tail loop is faster */ } #else @@ -716,7 +785,7 @@ int ata_write_sectors(IF_MV2(int drive,) } } - SET_ATA_SELECT(ata_device); + SET_REG(ATA_SELECT, ata_device); if (!wait_for_rdy()) { mutex_unlock(&ata_mtx); @@ -725,14 +794,14 @@ int ata_write_sectors(IF_MV2(int drive,) } if ( count == 256 ) - SET_ATA_NSECTOR(0); /* 0 means 256 sectors */ + SET_REG(ATA_NSECTOR, 0); /* 0 means 256 sectors */ else - SET_ATA_NSECTOR((unsigned char)count); - SET_ATA_SECTOR(start & 0xff); - SET_ATA_LCYL((start >> 8) & 0xff); - SET_ATA_HCYL((start >> 16) & 0xff); - SET_ATA_SELECT(((start >> 24) & 0xf) | SELECT_LBA | ata_device); - SET_ATA_COMMAND(CMD_WRITE_SECTORS); + SET_REG(ATA_NSECTOR, (unsigned char)count); + SET_REG(ATA_SECTOR, start & 0xff); + SET_REG(ATA_LCYL, (start >> 8) & 0xff); + SET_REG(ATA_HCYL, (start >> 16) & 0xff); + SET_REG(ATA_SELECT, ((start >> 24) & 0xf) | SELECT_LBA | ata_device); + SET_REG(ATA_COMMAND, CMD_WRITE_SECTORS); for (i=0; i 2ms */ -#elif defined HAVE_SCF5249 +#elif defined HAVE_MCF5249 + GPIO_OUT &= ~0x00080000; + sleep(1); /* > 25us */ + + GPIO_OUT |= 0x00080000; + sleep(1); /* > 25us */ #endif /* state HRR2 */ - SET_ATA_SELECT(ata_device); /* select the right device */ + SET_REG(ATA_SELECT, ata_device); /* select the right device */ ret = wait_for_bsy(); /* Massage the return code so it is 0 on success and -1 on failure */ @@ -1014,11 +1089,11 @@ static int perform_soft_reset(void) int ret; int retry_count; - SET_ATA_SELECT ( SELECT_LBA | ata_device ); - SET_ATA_CONTROL ( CONTROL_nIEN|CONTROL_SRST ); + SET_REG(ATA_SELECT, SELECT_LBA | ata_device ); + SET_REG(ATA_CONTROL, CONTROL_nIEN|CONTROL_SRST ); sleep(1); /* >= 5us */ - SET_ATA_CONTROL (CONTROL_nIEN); + SET_REG(ATA_CONTROL, CONTROL_nIEN); sleep(1); /* >2ms */ /* This little sucker can take up to 30 seconds */ @@ -1070,14 +1145,14 @@ static int ata_power_on(void) static int master_slave_detect(void) { /* master? */ - SET_ATA_SELECT( 0 ); + SET_REG(ATA_SELECT, 0); if ( ATA_STATUS & (STATUS_RDY|STATUS_BSY) ) { ata_device = 0; DEBUGF("Found master harddisk\n"); } else { /* slave? */ - SET_ATA_SELECT( SELECT_DEVICE1 ); + SET_REG(ATA_SELECT, SELECT_DEVICE1); if ( ATA_STATUS & (STATUS_RDY|STATUS_BSY) ) { ata_device = SELECT_DEVICE1; DEBUGF("Found slave harddisk\n"); @@ -1115,7 +1190,8 @@ void ata_enable(bool on) or_b(0x80, &PADRL); /* disable ATA */ or_b(0x80, &PAIORL); -#elif defined HAVE_SCF5249 +#elif CONFIG_CPU == MCF5249 + (void)on; /* FIXME */ #endif } @@ -1123,15 +1199,14 @@ static int identify(void) { int i; - SET_ATA_SELECT ( ata_device ); + SET_REG(ATA_SELECT, ata_device); if(!wait_for_rdy()) { DEBUGF("identify() - not RDY\n"); return -1; } - - SET_ATA_COMMAND ( CMD_IDENTIFY ); + SET_REG(ATA_COMMAND, CMD_IDENTIFY); if (!wait_for_start_of_transfer()) { @@ -1139,25 +1214,30 @@ static int identify(void) return -2; } - - for (i=0; i