diff --git a/apps/debug_menu.c b/apps/debug_menu.c index 6cc65c83a4..427df27e3e 100644 --- a/apps/debug_menu.c +++ b/apps/debug_menu.c @@ -1430,11 +1430,13 @@ static int disk_callback(int btn, struct gui_synclist *lists) simplelist_addline( "Firmware: %s", buf); - uint64_t total_sectors = identify_info[60] | ((uint32_t)identify_info[61] << 16); + uint64_t total_sectors = (identify_info[61] << 16) | identify_info[60]; #ifdef HAVE_LBA48 - if (identify_info[83] & 0x0400 - && total_sectors == 0x0FFFFFFF) - total_sectors = identify_info[100] | ((uint64_t)identify_info[101] << 16) | ((uint64_t)identify_info[102] << 32) | ((uint64_t)identify_info[103] << 48); + if (identify_info[83] & 0x0400 && total_sectors == 0x0FFFFFFF) + total_sectors = ((uint64_t)identify_info[103] << 48) | + ((uint64_t)identify_info[102] << 32) | + ((uint64_t)identify_info[101] << 16) | + identify_info[100]; #endif uint32_t sector_size; @@ -1555,6 +1557,9 @@ static int disk_callback(int btn, struct gui_synclist *lists) if (i == 0) { simplelist_addline( "DMA not enabled"); + } else if (i == 0xff) { + simplelist_addline( + "CE-ATA mode"); } else { simplelist_addline( "DMA mode: %s %c", diff --git a/firmware/drivers/ata.c b/firmware/drivers/ata.c index 525451ff1c..5331e7f589 100644 --- a/firmware/drivers/ata.c +++ b/firmware/drivers/ata.c @@ -114,7 +114,6 @@ static int multisectors; /* number of supported multisectors */ static unsigned short identify_info[ATA_IDENTIFY_WORDS]; #ifdef MAX_PHYS_SECTOR_SIZE - struct sector_cache_entry { bool inuse; sector_t sectornum; /* logical sector */ @@ -1068,7 +1067,7 @@ static int set_multiple_mode(int sectors) } #ifdef HAVE_ATA_DMA -static int get_best_mode(unsigned short identword, int max, int modetype) +static int ata_get_best_mode(unsigned short identword, int max, int modetype) { unsigned short testbit = BIT_N(max); @@ -1118,12 +1117,12 @@ static int set_features(void) #ifdef HAVE_ATA_DMA if (identify_info[53] & (1<<2)) { /* Ultra DMA mode info present, find a mode */ - dma_mode = get_best_mode(identify_info[88], ATA_MAX_UDMA, 0x40); + dma_mode = ata_get_best_mode(identify_info[88], ATA_MAX_UDMA, 0x40); } if (!dma_mode) { /* No UDMA mode found, try to find a multi-word DMA mode */ - dma_mode = get_best_mode(identify_info[63], ATA_MAX_MWDMA, 0x20); + dma_mode = ata_get_best_mode(identify_info[63], ATA_MAX_MWDMA, 0x20); features[1].id_word = 63; } else { features[1].id_word = 88; @@ -1263,14 +1262,14 @@ int STORAGE_INIT_ATTR ata_init(void) DEBUGF("ata: %d sectors per ata request\n",multisectors); - total_sectors = identify_info[60] | (identify_info[61] << 16); + total_sectors = (identify_info[61] << 16) | identify_info[60]; #ifdef HAVE_LBA48 - if (identify_info[83] & 0x0400 /* 48 bit address support */ - && total_sectors == 0x0FFFFFFF) /* and disk size >= 128 GiB */ - { /* (needs BigLBA addressing) */ - total_sectors = identify_info[100] | (identify_info[101] << 16) | ((uint64_t)identify_info[102] << 32) | ((uint64_t)identify_info[103] << 48); - + if (identify_info[83] & 0x0400 && total_sectors == 0x0FFFFFFF) { + total_sectors = ((uint64_t)identify_info[103] << 48) | + ((uint64_t)identify_info[102] << 32) | + ((uint64_t)identify_info[101] << 16) | + identify_info[100]; lba48 = true; /* use BigLBA */ } #endif /* HAVE_LBA48 */ diff --git a/firmware/export/config/ipod6g.h b/firmware/export/config/ipod6g.h index 50aa5d8e8c..58c91b29c6 100644 --- a/firmware/export/config/ipod6g.h +++ b/firmware/export/config/ipod6g.h @@ -12,7 +12,7 @@ /* define this if you use an ATA controller */ #define CONFIG_STORAGE STORAGE_ATA -#define HAVE_ATA_DMA +#define HAVE_ATA_DMA #define ATA_MAX_UDMA 4 #define ATA_MAX_MWDMA 2 @@ -139,7 +139,7 @@ /* 6g has a standard battery of 550mAh, except for the thick 6g (2007 160gb) * which has a standard battery of 850mAh. - * + * * It's possible to buy 3rd party batteries up to 3000mAh. */ #define BATTERY_CAPACITY_DEFAULT 550 /* default battery capacity */ @@ -189,17 +189,12 @@ /* Define this if you can read an absolute wheel position */ #define HAVE_WHEEL_POSITION -#define SECTOR_SIZE 4096 - #define HAVE_ATA_SMART +#define SECTOR_SIZE 512 /* define this if the device has larger sectors when accessed via USB */ -/* (only relevant in disk.c, fat.c now always supports large virtual sectors) */ -//#define MAX_LOG_SECTOR_SIZE 4096 - -/* define this if the hard drive uses large physical sectors (ATA-7 feature) */ -/* and doesn't handle them in the drive firmware */ -//#define MAX_PHYS_SECTOR_SIZE 4096 +#define MAX_LOG_SECTOR_SIZE 4096 +//#define MAX_PHYS_SECTOR_SIZE 4096 // Only if we have various physical sector sizes #define HAVE_HARDWARE_CLICK diff --git a/firmware/export/config/vibe500.h b/firmware/export/config/vibe500.h index b6d2e5082a..48140e7a4a 100644 --- a/firmware/export/config/vibe500.h +++ b/firmware/export/config/vibe500.h @@ -170,14 +170,6 @@ /* Define this if you have adjustable CPU frequency */ #define HAVE_ADJUSTABLE_CPU_FREQ -/* define this if the device has larger sectors when accessed via USB */ -/* (only relevant in disk.c, fat.c now always supports large virtual sectors) */ -/* #define MAX_LOG_SECTOR_SIZE 2048 */ - -/* define this if the hard drive uses large physical sectors (ATA-7 feature) */ -/* and doesn't handle them in the drive firmware */ -/* #define MAX_PHYS_SECTOR_SIZE 1024 */ - #define MI4_FORMAT #define BOOTFILE_EXT "mi4" #define BOOTFILE "rockbox." BOOTFILE_EXT @@ -185,9 +177,6 @@ #define ICODE_ATTR_TREMOR_NOT_MDCT -/* DMA is used only for reading on PP502x because although reads are ~8x faster - * writes appear to be ~25% slower. - */ #ifndef BOOTLOADER #define HAVE_ATA_DMA #endif diff --git a/firmware/target/arm/s5l8702/ipod6g/storage_ata-6g.c b/firmware/target/arm/s5l8702/ipod6g/storage_ata-6g.c index ee192ae3d1..97a55eba10 100644 --- a/firmware/target/arm/s5l8702/ipod6g/storage_ata-6g.c +++ b/firmware/target/arm/s5l8702/ipod6g/storage_ata-6g.c @@ -58,6 +58,18 @@ #define CEATA_DAT_NONBUSY_TIMEOUT 5000000 #define CEATA_MMC_RCA 1 +#if SECTOR_SIZE == 4096 +#define SIZE_SHIFT 3 /* ie 4096 >> 3 == 512 */ +#elif SECTOR_SIZE == 512 +#define SIZE_SHIFT 0 +#else +#error "Need to define SIZE_SHIFT for SECTOR_SIZE" +#endif + +#ifdef MAX_PHYS_SECTOR_SIZE +#error "Driver does not work with MAX_PHYS_SECTOR_SIZE" +#endif + /** static, private data **/ static uint8_t ceata_taskfile[16] STORAGE_ALIGN_ATTR; static uint16_t ata_identify_data[ATA_IDENTIFY_WORDS] STORAGE_ALIGN_ATTR; @@ -69,19 +81,22 @@ static struct mutex ata_mutex; static struct semaphore ata_wakeup; static uint32_t ata_dma_flags; static long ata_last_activity_value = -1; -static long ata_sleep_timeout = 20 * HZ; +static long ata_sleep_timeout = 7 * HZ; static bool ata_powered; -static const int ata_retries = ATA_RETRIES; -static const bool ata_error_srst = true; static struct semaphore mmc_wakeup; static struct semaphore mmc_comp_wakeup; static int spinup_time = 0; static int dma_mode = 0; + +#if SECTOR_SIZE > 512 static char aligned_buffer[SECTOR_SIZE] STORAGE_ALIGN_ATTR; +#endif + +static const int ata_retries = ATA_RETRIES; +static const bool ata_error_srst = true; static int ata_reset(void); - static uint16_t ata_read_cbr(uint32_t volatile* reg) { while (!(ATA_PIO_READY & 2)); @@ -102,8 +117,10 @@ static int ata_wait_for_not_bsy(long timeout) while (true) { uint8_t csd = ata_read_cbr(&ATA_PIO_CSD); - if (!(csd & BIT(7))) return 0; - if (TIMEOUT_EXPIRED(startusec, timeout)) RET_ERR(0); + if (!(csd & BIT(7))) + return 0; + if (TIMEOUT_EXPIRED(startusec, timeout)) + RET_ERR(0); yield(); } } @@ -115,8 +132,10 @@ static int ata_wait_for_rdy(long timeout) while (true) { uint8_t dad = ata_read_cbr(&ATA_PIO_DAD); - if (dad & BIT(6)) return 0; - if (TIMEOUT_EXPIRED(startusec, timeout)) RET_ERR(1); + if (dad & BIT(6)) + return 0; + if (TIMEOUT_EXPIRED(startusec, timeout)) + RET_ERR(1); yield(); } } @@ -128,9 +147,12 @@ static int ata_wait_for_start_of_transfer(long timeout) while (true) { uint8_t dad = ata_read_cbr(&ATA_PIO_DAD); - if (dad & BIT(0)) RET_ERR(1); - if ((dad & (BIT(7) | BIT(3))) == BIT(3)) return 0; - if (TIMEOUT_EXPIRED(startusec, timeout)) RET_ERR(2); + if (dad & BIT(0)) + RET_ERR(1); + if ((dad & (BIT(7) | BIT(3))) == BIT(3)) + return 0; + if (TIMEOUT_EXPIRED(startusec, timeout)) + RET_ERR(2); yield(); } } @@ -139,8 +161,10 @@ static int ata_wait_for_end_of_transfer(long timeout) { PASS_RC(ata_wait_for_not_bsy(timeout), 2, 0); uint8_t dad = ata_read_cbr(&ATA_PIO_DAD); - if (dad & BIT(0)) RET_ERR(1); - if ((dad & (BIT(3) | BITRANGE(5, 7))) == BIT(6)) return 0; + if (dad & BIT(0)) + RET_ERR(1); + if ((dad & (BIT(3) | BITRANGE(5, 7))) == BIT(6)) + return 0; RET_ERR(2); } @@ -148,13 +172,17 @@ static int mmc_dsta_check_command_success(bool disable_crc) { int rc = 0; uint32_t dsta = SDCI_DSTA; - if (dsta & SDCI_DSTA_RESTOUTE) rc |= 1; - if (dsta & SDCI_DSTA_RESENDE) rc |= 2; - if (dsta & SDCI_DSTA_RESINDE) rc |= 4; + if (dsta & SDCI_DSTA_RESTOUTE) + rc |= 1; + if (dsta & SDCI_DSTA_RESENDE) + rc |= 2; + if (dsta & SDCI_DSTA_RESINDE) + rc |= 4; if (!disable_crc) if (dsta & SDCI_DSTA_RESCRCE) rc |= 8; - if (rc) RET_ERR(rc); + if (rc) + RET_ERR(rc); return 0; } @@ -163,7 +191,8 @@ static bool mmc_send_command(uint32_t cmd, uint32_t arg, uint32_t* result, int t long starttime = USEC_TIMER; while ((SDCI_STATE & SDCI_STATE_CMD_STATE_MASK) != SDCI_STATE_CMD_STATE_CMD_IDLE) { - if (TIMEOUT_EXPIRED(starttime, timeout)) RET_ERR(0); + if (TIMEOUT_EXPIRED(starttime, timeout)) + RET_ERR(0); yield(); } SDCI_STAC = SDCI_STAC_CLR_CMDEND | SDCI_STAC_CLR_BIT_3 @@ -178,32 +207,38 @@ static bool mmc_send_command(uint32_t cmd, uint32_t arg, uint32_t* result, int t | SDCI_STAC_CLR_RD_DATENDE6 | SDCI_STAC_CLR_RD_DATENDE7; SDCI_ARGU = arg; SDCI_CMD = cmd; - if (!(SDCI_DSTA & SDCI_DSTA_CMDRDY)) RET_ERR(1); + if (!(SDCI_DSTA & SDCI_DSTA_CMDRDY)) + RET_ERR(1); SDCI_CMD = cmd | SDCI_CMD_CMDSTR; long sleepbase = USEC_TIMER; - while (TIMEOUT_EXPIRED(sleepbase, 1000)) yield(); + while (TIMEOUT_EXPIRED(sleepbase, 1000)) + yield(); while (!(SDCI_DSTA & SDCI_DSTA_CMDEND)) { - if (TIMEOUT_EXPIRED(starttime, timeout)) RET_ERR(2); + if (TIMEOUT_EXPIRED(starttime, timeout)) + RET_ERR(2); yield(); } if ((cmd & SDCI_CMD_RES_TYPE_MASK) != SDCI_CMD_RES_TYPE_NONE) { while (!(SDCI_DSTA & SDCI_DSTA_RESEND)) { - if (TIMEOUT_EXPIRED(starttime, timeout)) RET_ERR(3); + if (TIMEOUT_EXPIRED(starttime, timeout)) + RET_ERR(3); yield(); } if (cmd & SDCI_CMD_RES_BUSY) while (SDCI_DSTA & SDCI_DSTA_DAT_BUSY) { - if (TIMEOUT_EXPIRED(starttime, CEATA_DAT_NONBUSY_TIMEOUT)) RET_ERR(4); + if (TIMEOUT_EXPIRED(starttime, CEATA_DAT_NONBUSY_TIMEOUT)) + RET_ERR(4); yield(); } } bool nocrc = (cmd & SDCI_CMD_RES_SIZE_MASK) == SDCI_CMD_RES_SIZE_136; PASS_RC(mmc_dsta_check_command_success(nocrc), 3, 5); - if (result) *result = SDCI_RESP0; + if (result) + *result = SDCI_RESP0; return 0; } @@ -226,7 +261,8 @@ static int mmc_init(void) uint32_t result; do { - if (TIMEOUT_EXPIRED(startusec, CEATA_POWERUP_TIMEOUT)) RET_ERR(1); + if (TIMEOUT_EXPIRED(startusec, CEATA_POWERUP_TIMEOUT)) + RET_ERR(1); sleep(HZ / 100); PASS_RC(mmc_send_command(SDCI_CMD_CMD_NUM(MMC_CMD_SEND_OP_COND) | SDCI_CMD_CMD_TYPE_BCR | SDCI_CMD_RES_TYPE_R3 @@ -251,7 +287,8 @@ static int mmc_init(void) MMC_CMD_SELECT_CARD_RCA(CEATA_MMC_RCA), NULL, CEATA_COMMAND_TIMEOUT), 3, 5); PASS_RC(mmc_get_card_status(&result), 3, 6); - if ((result & MMC_STATUS_CURRENT_STATE_MASK) != MMC_STATUS_CURRENT_STATE_TRAN) RET_ERR(7); + if ((result & MMC_STATUS_CURRENT_STATE_MASK) != MMC_STATUS_CURRENT_STATE_TRAN) + RET_ERR(7); return 0; } @@ -285,7 +322,8 @@ static int ceata_soft_reset(void) do { PASS_RC(mmc_fastio_read(0xf, &status), 2, 2); - if (TIMEOUT_EXPIRED(startusec, CEATA_POWERUP_TIMEOUT)) RET_ERR(3); + if (TIMEOUT_EXPIRED(startusec, CEATA_POWERUP_TIMEOUT)) + RET_ERR(3); sleep(HZ / 100); } while (status & 0x80); @@ -298,16 +336,21 @@ static int mmc_dsta_check_data_success(void) uint32_t dsta = SDCI_DSTA; if (dsta & (SDCI_DSTA_WR_DATCRCE | SDCI_DSTA_RD_DATCRCE)) { - if (dsta & SDCI_DSTA_WR_DATCRCE) rc |= 1; - if (dsta & SDCI_DSTA_RD_DATCRCE) rc |= 2; - if ((dsta & SDCI_DSTA_WR_CRC_STATUS_MASK) == SDCI_DSTA_WR_CRC_STATUS_TXERR) rc |= 4; - else if ((dsta & SDCI_DSTA_WR_CRC_STATUS_MASK) == SDCI_DSTA_WR_CRC_STATUS_CARDERR) rc |= 8; + if (dsta & SDCI_DSTA_WR_DATCRCE) + rc |= 1; + if (dsta & SDCI_DSTA_RD_DATCRCE) + rc |= 2; + if ((dsta & SDCI_DSTA_WR_CRC_STATUS_MASK) == SDCI_DSTA_WR_CRC_STATUS_TXERR) + rc |= 4; + else if ((dsta & SDCI_DSTA_WR_CRC_STATUS_MASK) == SDCI_DSTA_WR_CRC_STATUS_CARDERR) + rc |= 8; } if (dsta & (SDCI_DSTA_RD_DATENDE0 | SDCI_DSTA_RD_DATENDE1 | SDCI_DSTA_RD_DATENDE2 | SDCI_DSTA_RD_DATENDE3 | SDCI_DSTA_RD_DATENDE4 | SDCI_DSTA_RD_DATENDE5 | SDCI_DSTA_RD_DATENDE6 | SDCI_DSTA_RD_DATENDE7)) rc |= 16; - if (rc) RET_ERR(rc); + if (rc) + RET_ERR(rc); return 0; } @@ -320,7 +363,8 @@ static void mmc_discard_irq(void) static int ceata_read_multiple_register(uint32_t addr, void* dest, uint32_t size) { - if (size > 0x10) RET_ERR(0); + if (size > 0x10) + RET_ERR(0); mmc_discard_irq(); SDCI_DMASIZE = size; SDCI_DMACOUNT = 1; @@ -334,8 +378,8 @@ static int ceata_read_multiple_register(uint32_t addr, void* dest, uint32_t size | MMC_CMD_CEATA_RW_MULTIPLE_REG_ADDRESS(addr & 0xfc) | MMC_CMD_CEATA_RW_MULTIPLE_REG_COUNT(size & 0xfc), NULL, CEATA_COMMAND_TIMEOUT), 2, 1); - if (semaphore_wait(&mmc_wakeup, CEATA_COMMAND_TIMEOUT * HZ / 1000000) - == OBJ_WAIT_TIMEDOUT) RET_ERR(2); + if (semaphore_wait(&mmc_wakeup, CEATA_COMMAND_TIMEOUT * HZ / 1000000) == OBJ_WAIT_TIMEDOUT) + RET_ERR(2); PASS_RC(mmc_dsta_check_data_success(), 2, 3); return 0; } @@ -343,7 +387,8 @@ static int ceata_read_multiple_register(uint32_t addr, void* dest, uint32_t size static int ceata_write_multiple_register(uint32_t addr, void* dest, uint32_t size) { uint32_t i; - if (size > 0x10) RET_ERR(0); + if (size > 0x10) + RET_ERR(0); mmc_discard_irq(); SDCI_DMASIZE = size; SDCI_DMACOUNT = 0; @@ -357,13 +402,15 @@ static int ceata_write_multiple_register(uint32_t addr, void* dest, uint32_t siz | MMC_CMD_CEATA_RW_MULTIPLE_REG_COUNT(size & 0xfc), NULL, CEATA_COMMAND_TIMEOUT), 3, 1); SDCI_DCTRL = SDCI_DCTRL_TRCONT_TX; - for (i = 0; i < size / 4; i++) SDCI_DATA = ((uint32_t*)dest)[i]; + for (i = 0; i < size / 4; i++) + SDCI_DATA = ((uint32_t*)dest)[i]; long startusec = USEC_TIMER; - if (semaphore_wait(&mmc_wakeup, CEATA_COMMAND_TIMEOUT * HZ / 1000000) - == OBJ_WAIT_TIMEDOUT) RET_ERR(2); + if (semaphore_wait(&mmc_wakeup, CEATA_COMMAND_TIMEOUT * HZ / 1000000) == OBJ_WAIT_TIMEDOUT) + RET_ERR(2); while ((SDCI_STATE & SDCI_STATE_DAT_STATE_MASK) != SDCI_STATE_DAT_STATE_IDLE) { - if (TIMEOUT_EXPIRED(startusec, CEATA_COMMAND_TIMEOUT)) RET_ERR(3); + if (TIMEOUT_EXPIRED(startusec, CEATA_COMMAND_TIMEOUT)) + RET_ERR(3); yield(); } PASS_RC(mmc_dsta_check_data_success(), 3, 4); @@ -380,13 +427,17 @@ static int ceata_init(int buswidth) | MMC_CMD_SWITCH_INDEX(MMC_CMD_SWITCH_FIELD_HS_TIMING) | MMC_CMD_SWITCH_VALUE(MMC_CMD_SWITCH_FIELD_HS_TIMING_HIGH_SPEED), &result, CEATA_COMMAND_TIMEOUT), 3, 0); - if (result & MMC_STATUS_SWITCH_ERROR) RET_ERR(1); + if (result & MMC_STATUS_SWITCH_ERROR) + RET_ERR(1); if (buswidth > 1) { int setting; - if (buswidth == 4) setting = MMC_CMD_SWITCH_FIELD_BUS_WIDTH_4BIT; - else if (buswidth == 8) setting = MMC_CMD_SWITCH_FIELD_BUS_WIDTH_8BIT; - else setting = MMC_CMD_SWITCH_FIELD_BUS_WIDTH_1BIT; + if (buswidth == 4) + setting = MMC_CMD_SWITCH_FIELD_BUS_WIDTH_4BIT; + else if (buswidth == 8) + setting = MMC_CMD_SWITCH_FIELD_BUS_WIDTH_8BIT; + else + setting = MMC_CMD_SWITCH_FIELD_BUS_WIDTH_1BIT; PASS_RC(mmc_send_command(SDCI_CMD_CMD_NUM(MMC_CMD_SWITCH) | SDCI_CMD_RES_BUSY | SDCI_CMD_CMD_TYPE_AC | SDCI_CMD_RES_TYPE_R1 | SDCI_CMD_RES_SIZE_48 | SDCI_CMD_NCR_NID_NCR, @@ -394,7 +445,8 @@ static int ceata_init(int buswidth) | MMC_CMD_SWITCH_INDEX(MMC_CMD_SWITCH_FIELD_BUS_WIDTH) | MMC_CMD_SWITCH_VALUE(setting), &result, CEATA_COMMAND_TIMEOUT), 3, 2); - if (result & MMC_STATUS_SWITCH_ERROR) RET_ERR(3); + if (result & MMC_STATUS_SWITCH_ERROR) + RET_ERR(3); if (buswidth == 4) SDCI_CTRL = (SDCI_CTRL & ~SDCI_CTRL_BUS_WIDTH_MASK) | SDCI_CTRL_BUS_WIDTH_4BIT; else if (buswidth == 8) @@ -402,7 +454,8 @@ static int ceata_init(int buswidth) } PASS_RC(ceata_soft_reset(), 3, 4); PASS_RC(ceata_read_multiple_register(0, ceata_taskfile, 0x10), 3, 5); - if (ceata_taskfile[0xc] != 0xce || ceata_taskfile[0xd] != 0xaa) RET_ERR(6); + if (ceata_taskfile[0xc] != 0xce || ceata_taskfile[0xd] != 0xaa) + RET_ERR(6); PASS_RC(mmc_fastio_write(6, 0), 3, 7); return 0; } @@ -426,8 +479,10 @@ static int ceata_wait_idle(void) { uint32_t status; PASS_RC(mmc_fastio_read(0xf, &status), 1, 0); - if (!(status & 0x88)) return 0; - if (TIMEOUT_EXPIRED(startusec, CEATA_DAT_NONBUSY_TIMEOUT)) RET_ERR(1); + if (!(status & 0x88)) + return 0; + if (TIMEOUT_EXPIRED(startusec, CEATA_DAT_NONBUSY_TIMEOUT)) + RET_ERR(1); sleep(HZ / 20); } } @@ -476,7 +531,8 @@ static int ceata_rw_multiple_block(bool write, void* buf, uint32_t count, long t | SDCI_CMD_RES_SIZE_48 | SDCI_CMD_NCR_NID_NCR, direction | MMC_CMD_CEATA_RW_MULTIPLE_BLOCK_COUNT(count), NULL, CEATA_COMMAND_TIMEOUT), 3, 0); - if (write) SDCI_DCTRL = SDCI_DCTRL_TRCONT_TX; + if (write) + SDCI_DCTRL = SDCI_DCTRL_TRCONT_TX; if (semaphore_wait(&mmc_wakeup, timeout) == OBJ_WAIT_TIMEDOUT) { PASS_RC(ceata_cancel_command(), 3, 1); @@ -509,7 +565,8 @@ static int ata_identify(uint16_t* buf) ata_write_cbr(&ATA_PIO_DVR, 0); ata_write_cbr(&ATA_PIO_CSD, CMD_IDENTIFY); PASS_RC(ata_wait_for_start_of_transfer(10000000), 1, 1); - for (i = 0; i < ATA_IDENTIFY_WORDS; i++) buf[i] = ata_read_cbr(&ATA_PIO_DTR); + for (i = 0; i < ATA_IDENTIFY_WORDS; i++) + buf[i] = ata_read_cbr(&ATA_PIO_DTR); } return 0; } @@ -548,6 +605,34 @@ static int ata_set_feature(uint32_t feature, uint32_t param) return 0; } +#ifdef HAVE_ATA_DMA +static int udmatimes[ATA_MAX_UDMA + 1] = { + 0x4071152, + 0x2050d52, + 0x2030a52, + 0x1020a52, + 0x1010a52 +}; +static int mwdmatimes[ATA_MAX_MWDMA + 1] = { + 0x1c175, + 0x7083, + 0x5072 +}; +static int ata_get_best_mode(unsigned short identword, int max, int modetype) +{ + unsigned short testbit = BIT_N(max); + + while (1) { + if (identword & testbit) + return max | modetype; + testbit >>= 1; + if (!testbit) + return 0; + max--; + } +} +#endif + /* * ATA_UDMA_TIME register is documented on s3c6400 datasheet, information * included in s5l8700 datasheet is wrong or not valid for s5l8702. @@ -572,10 +657,10 @@ static int ata_power_up(void) ata_set_active(); ide_power_enable(true); long spinup_start = current_tick; - if (ceata) - { + if (ceata) { ata_lba48 = true; ata_dma = true; + dma_mode = 0xff; /* Canary */ PCON(8) = 0x33333333; PCON(9) = 0x00000033; PCON(11) |= 0xf; @@ -596,10 +681,7 @@ static int ata_power_up(void) sleep(HZ / 100); PASS_RC(ceata_init(8), 3, 1); PASS_RC(ata_identify(ata_identify_data), 3, 2); - dma_mode = 0x44; - } - else - { + } else { PCON(7) = 0x44444444; PCON(8) = 0x44444444; PCON(9) = 0x44444444; @@ -619,64 +701,35 @@ static int ata_power_up(void) ATA_PIO_LHR = 0; ATA_CFG = BIT(6); while (!(ATA_PIO_READY & BIT(1))) yield(); + PASS_RC(ata_identify(ata_identify_data), 3, 3); - uint32_t piotime = 0x11f3; - uint32_t mdmatime = 0x1c175; - uint32_t udmatime = 0x4071152; + + uint32_t piotime = 0x11f3; /* PIO0-2? */ + if (ata_identify_data[53] & BIT(1)) /* Word 64..70 valid */ + { + if (ata_identify_data[64] & BIT(1)) + piotime = 0x2072; /* PIO mode 4 */ + else if (ata_identify_data[64] & BIT(0)) + piotime = 0x7083; /* PIO mode 3 */ + } + ATA_PIO_TIME = piotime; + uint32_t param = 0; ata_dma_flags = 0; - ata_lba48 = ata_identify_data[83] & BIT(10) ? true : false; - if (ata_identify_data[53] & BIT(1)) +#ifdef HAVE_ATA_DMA + if ((ata_identify_data[53] & BIT(2)) && (ata_identify_data[88] & BITRANGE(0, 4))) /* Any UDMA */ { - if (ata_identify_data[64] & BIT(1)) piotime = 0x2072; - else if (ata_identify_data[64] & BIT(0)) piotime = 0x7083; + param = ata_get_best_mode(ata_identify_data[88], ATA_MAX_UDMA, 0x40); + ATA_UDMA_TIME = udmatimes[param & 0xf]; + ata_dma_flags = BIT(2) | BIT(3) | BIT(9) | BIT(10); } - if (ata_identify_data[63] & BIT(2)) - { - mdmatime = 0x5072; - param = 0x22; - } - else if (ata_identify_data[63] & BIT(1)) - { - mdmatime = 0x7083; - param = 0x21; - } - if (ata_identify_data[63] & BITRANGE(0, 2)) + if (!param && ata_identify_data[63] & BITRANGE(0, 2)) /* Fall back to any MWDMA */ { + param = ata_get_best_mode(ata_identify_data[63], ATA_MAX_MWDMA, 0x20); + ATA_MDMA_TIME = mwdmatimes[param & 0xf]; ata_dma_flags = BIT(3) | BIT(10); - param |= 0x20; - } - if (ata_identify_data[53] & BIT(2)) - { - if (ata_identify_data[88] & BIT(4)) - { - udmatime = 0x1010a52; - param = 0x44; - } - else if (ata_identify_data[88] & BIT(3)) - { - udmatime = 0x1020a52; - param = 0x43; - } - else if (ata_identify_data[88] & BIT(2)) - { - udmatime = 0x2030a52; - param = 0x42; - } - else if (ata_identify_data[88] & BIT(1)) - { - udmatime = 0x2050d52; - param = 0x41; - } - else if (ata_identify_data[88] & BIT(0)) - { - param = 0x40; - } - if (ata_identify_data[88] & BITRANGE(0, 4)) - { - ata_dma_flags = BIT(2) | BIT(3) | BIT(9) | BIT(10); - } } +#endif /* HAVE_ATA_DMA */ ata_dma = param ? true : false; dma_mode = param; PASS_RC(ata_set_feature(0x03, param), 3, 4); /* Transfer mode */ @@ -688,19 +741,22 @@ static int ata_power_up(void) PASS_RC(ata_set_feature(0x05, 0x80), 3, 7); /* Enable lowest power mode w/o standby */ if (ata_identify_data[83] & BIT(9)) PASS_RC(ata_set_feature(0x42, 0x80), 3, 8); /* Enable lowest noise mode */ - ATA_PIO_TIME = piotime; - ATA_MDMA_TIME = mdmatime; - ATA_UDMA_TIME = udmatime; } spinup_time = current_tick - spinup_start; - if (ata_lba48) - ata_total_sectors = ata_identify_data[100] - | (((uint64_t)ata_identify_data[101]) << 16) - | (((uint64_t)ata_identify_data[102]) << 32) - | (((uint64_t)ata_identify_data[103]) << 48); - else - ata_total_sectors = ata_identify_data[60] | (((uint32_t)ata_identify_data[61]) << 16); - ata_total_sectors >>= 3; /* ie SECTOR_SIZE/512. */ + + ata_total_sectors = (ata_identify_data[61] << 16) | ata_identify_data[60]; + if ( ata_identify_data[83] & BIT(10) && ata_total_sectors == 0x0FFFFFFF) + { + ata_total_sectors = ((uint64_t)ata_identify_data[103] << 48) | + ((uint64_t)ata_identify_data[102] << 32) | + ((uint64_t)ata_identify_data[101] << 16) | + ata_identify_data[100]; + ata_lba48 = true; + } else { + ata_lba48 = false; + } + + ata_total_sectors >>= SIZE_SHIFT; ata_powered = true; ata_set_active(); return 0; @@ -708,7 +764,8 @@ static int ata_power_up(void) static void ata_power_down(void) { - if (!ata_powered) return; + if (!ata_powered) + return; if (ceata) { memset(ceata_taskfile, 0, 16); @@ -727,7 +784,8 @@ static void ata_power_down(void) ata_wait_for_rdy(1000000); sleep(HZ / 30); ATA_CONTROL = 0; - while (!(ATA_CONTROL & BIT(1))) yield(); + while (!(ATA_CONTROL & BIT(1))) + yield(); PWRCON(0) |= (1 << 5); } PCON(7) = 0; @@ -744,18 +802,18 @@ static int ata_rw_chunk_internal(uint64_t sector, uint32_t cnt, void* buffer, bo if (ceata) { memset(ceata_taskfile, 0, 16); - ceata_taskfile[0x2] = cnt >> 5; - ceata_taskfile[0x3] = sector >> 21; - ceata_taskfile[0x4] = sector >> 29; - ceata_taskfile[0x5] = sector >> 37; - ceata_taskfile[0xa] = cnt << 3; - ceata_taskfile[0xb] = sector << 3; - ceata_taskfile[0xc] = sector >> 5; - ceata_taskfile[0xd] = sector >> 13; + ceata_taskfile[0x2] = cnt >> (8-SIZE_SHIFT); + ceata_taskfile[0x3] = sector >> (24-SIZE_SHIFT); + ceata_taskfile[0x4] = sector >> (32-SIZE_SHIFT); + ceata_taskfile[0x5] = sector >> (40-SIZE_SHIFT); + ceata_taskfile[0xa] = cnt << SIZE_SHIFT; + ceata_taskfile[0xb] = sector << SIZE_SHIFT; + ceata_taskfile[0xc] = sector >> (8-SIZE_SHIFT); + ceata_taskfile[0xd] = sector >> (16-SIZE_SHIFT); ceata_taskfile[0xf] = write ? CMD_WRITE_DMA_EXT : CMD_READ_DMA_EXT; PASS_RC(ceata_wait_idle(), 2, 0); PASS_RC(ceata_write_multiple_register(0, ceata_taskfile, 16), 2, 1); - PASS_RC(ceata_rw_multiple_block(write, buffer, cnt << 3, CEATA_COMMAND_TIMEOUT * HZ / 1000000), 2, 2); + PASS_RC(ceata_rw_multiple_block(write, buffer, cnt << SIZE_SHIFT, CEATA_COMMAND_TIMEOUT * HZ / 1000000), 2, 2); } else { @@ -763,14 +821,14 @@ static int ata_rw_chunk_internal(uint64_t sector, uint32_t cnt, void* buffer, bo ata_write_cbr(&ATA_PIO_DVR, 0); if (ata_lba48) { - ata_write_cbr(&ATA_PIO_SCR, cnt >> 5); - ata_write_cbr(&ATA_PIO_SCR, (cnt << 3) & 0xff); - ata_write_cbr(&ATA_PIO_LHR, (sector >> 37) & 0xff); - ata_write_cbr(&ATA_PIO_LMR, (sector >> 29) & 0xff); - ata_write_cbr(&ATA_PIO_LLR, (sector >> 21) & 0xff); - ata_write_cbr(&ATA_PIO_LHR, (sector >> 13) & 0xff); - ata_write_cbr(&ATA_PIO_LMR, (sector >> 5) & 0xff); - ata_write_cbr(&ATA_PIO_LLR, (sector << 3) & 0xff); + ata_write_cbr(&ATA_PIO_SCR, (cnt >> (8-SIZE_SHIFT)) & 0xff); + ata_write_cbr(&ATA_PIO_SCR, (cnt << SIZE_SHIFT) & 0xff); + ata_write_cbr(&ATA_PIO_LHR, (sector >> (40-SIZE_SHIFT)) & 0xff); + ata_write_cbr(&ATA_PIO_LMR, (sector >> (32-SIZE_SHIFT)) & 0xff); + ata_write_cbr(&ATA_PIO_LLR, (sector >> (24-SIZE_SHIFT)) & 0xff); + ata_write_cbr(&ATA_PIO_LHR, (sector >> (16-SIZE_SHIFT)) & 0xff); + ata_write_cbr(&ATA_PIO_LMR, (sector >> (8-SIZE_SHIFT)) & 0xff); + ata_write_cbr(&ATA_PIO_LLR, (sector << SIZE_SHIFT) & 0xff); ata_write_cbr(&ATA_PIO_DVR, BIT(6)); if (write) ata_write_cbr(&ATA_PIO_CSD, ata_dma ? CMD_WRITE_DMA_EXT : CMD_WRITE_MULTIPLE_EXT); @@ -779,16 +837,17 @@ static int ata_rw_chunk_internal(uint64_t sector, uint32_t cnt, void* buffer, bo } else { - ata_write_cbr(&ATA_PIO_SCR, (cnt << 3) & 0xff); - ata_write_cbr(&ATA_PIO_LHR, (sector >> 13) & 0xff); - ata_write_cbr(&ATA_PIO_LMR, (sector >> 5) & 0xff); - ata_write_cbr(&ATA_PIO_LLR, (sector << 3) & 0xff); - ata_write_cbr(&ATA_PIO_DVR, BIT(6) | ((sector >> 21) & 0xf)); + ata_write_cbr(&ATA_PIO_SCR, (cnt << SIZE_SHIFT) & 0xff); + ata_write_cbr(&ATA_PIO_LHR, (sector >> (16-SIZE_SHIFT)) & 0xff); + ata_write_cbr(&ATA_PIO_LMR, (sector >> (8-SIZE_SHIFT)) & 0xff); + ata_write_cbr(&ATA_PIO_LLR, (sector << SIZE_SHIFT) & 0xff); + ata_write_cbr(&ATA_PIO_DVR, BIT(6) | ((sector >> (24-SIZE_SHIFT)) & 0xf)); if (write) ata_write_cbr(&ATA_PIO_CSD, ata_dma ? CMD_WRITE_DMA : CMD_WRITE_SECTORS); else ata_write_cbr(&ATA_PIO_CSD, ata_dma ? CMD_READ_DMA : CMD_READ_MULTIPLE); } +#ifdef HAVE_ATA_DMA if (ata_dma) { PASS_RC(ata_wait_for_start_of_transfer(500000), 2, 1); @@ -811,8 +870,7 @@ static int ata_rw_chunk_internal(uint64_t sector, uint32_t cnt, void* buffer, bo ATA_IRQ = BITRANGE(0, 4); ATA_IRQ_MASK = BIT(0); ATA_COMMAND = BIT(0); - if (semaphore_wait(&ata_wakeup, 500000 * HZ / 1000000) - == OBJ_WAIT_TIMEDOUT) + if (semaphore_wait(&ata_wakeup, 500000 * HZ / 1000000) == OBJ_WAIT_TIMEDOUT) { ATA_COMMAND = BIT(1); ATA_CFG &= ~(BITRANGE(2, 3) | BIT(12)); @@ -822,8 +880,9 @@ static int ata_rw_chunk_internal(uint64_t sector, uint32_t cnt, void* buffer, bo ATA_CFG &= ~(BITRANGE(2, 3) | BIT(12)); } else +#endif // HAVE_ATA_DMA { - cnt *= SECTOR_SIZE / 512; + cnt <<= SIZE_SHIFT; while (cnt--) { int i; @@ -834,7 +893,7 @@ static int ata_rw_chunk_internal(uint64_t sector, uint32_t cnt, void* buffer, bo else for (i = 0; i < 256; i++) ((uint16_t*)buffer)[i] = ata_read_cbr(&ATA_PIO_DTR); - buffer += 512; + buffer += (SECTOR_SIZE >> SIZE_SHIFT); } } PASS_RC(ata_wait_for_end_of_transfer(100000), 2, 3); @@ -852,6 +911,7 @@ static int ata_rw_chunk(uint64_t sector, uint32_t cnt, void* buffer, bool write) static int ata_rw_sectors(uint64_t sector, uint32_t count, void* buffer, bool write) { +#if SECTOR_SIZE > 512 if (STORAGE_OVERLAP((uint32_t)buffer)) { while (count) @@ -871,19 +931,27 @@ static int ata_rw_sectors(uint64_t sector, uint32_t count, void* buffer, bool wr return 0; } +#endif - if (!ata_powered) ata_power_up(); - if (sector + count > ata_total_sectors) RET_ERR(0); + if (!ata_powered) + ata_power_up(); + if (sector + count > ata_total_sectors) + RET_ERR(0); ata_set_active(); - if (ata_dma && write) commit_dcache(); - else if (ata_dma) commit_discard_dcache(); - if (!ceata) ATA_COMMAND = BIT(1); + if (ata_dma && write) + commit_dcache(); + else if (ata_dma) + commit_discard_dcache(); + if (!ceata) + ATA_COMMAND = BIT(1); + while (count) { - uint32_t cnt = MIN(ata_lba48 ? 8192 : 32, count); + uint32_t cnt = MIN(ata_lba48 ? (65536 >> SIZE_SHIFT) : (256 >> SIZE_SHIFT), count); int rc = -1; rc = ata_rw_chunk(sector, cnt, buffer, write); - if (rc && ata_error_srst) ata_reset(); + if (rc && ata_error_srst) + ata_reset(); if (rc && ata_retries) { void* buf = buffer; @@ -895,9 +963,11 @@ static int ata_rw_sectors(uint64_t sector, uint32_t count, void* buffer, bool wr while (tries-- && rc) { rc = ata_rw_chunk(sect, 1, buf, write); - if (rc && ata_error_srst) ata_reset(); + if (rc && ata_error_srst) + ata_reset(); } - if (rc) break; + if (rc) + break; buf += SECTOR_SIZE; } } @@ -915,9 +985,13 @@ int ata_soft_reset(void) { int rc; mutex_lock(&ata_mutex); - if (!ata_powered) PASS_RC(ata_power_up(), 1, 0); + if (!ata_powered) + PASS_RC(ata_power_up(), 1, 0); ata_set_active(); - if (ceata) rc = ceata_soft_reset(); + if (ceata) + { + rc = ceata_soft_reset(); + } else { ata_write_cbr(&ATA_PIO_DAD, BIT(1) | BIT(2)); @@ -944,7 +1018,8 @@ static int ata_reset(void) { int rc; mutex_lock(&ata_mutex); - if (!ata_powered) PASS_RC(ata_power_up(), 2, 0); + if (!ata_powered) + PASS_RC(ata_power_up(), 2, 0); ata_set_active(); rc = ata_soft_reset(); if (IS_ERR(rc)) @@ -956,7 +1031,8 @@ static int ata_reset(void) ata_power_down(); sleep(HZ * 3); int rc2 = ata_power_up(); - if (IS_ERR(rc2)) rc = ERR_RC((rc << 2) | 2); + if (IS_ERR(rc2)) + rc = ERR_RC((rc << 2) | 2); } else rc = 1; } @@ -1036,14 +1112,21 @@ void ata_spin(void) ata_set_active(); } +#ifdef STORAGE_GET_INFO void ata_get_info(IF_MD(int drive,) struct storage_info *info) { - (*info).sector_size = SECTOR_SIZE; + /* Logical sector size */ + if ((ata_identify_data[106] & 0xd000) == 0x5000) + info->sector_size = ata_identify_data[117] | (ata_identify_data[118] << 16); + else + info->sector_size = SECTOR_SIZE; + (*info).num_sectors = ata_total_sectors; (*info).vendor = "Apple"; (*info).product = "iPod Classic"; (*info).revision = "1.0"; } +#endif long ata_last_disk_activity(void) { @@ -1064,7 +1147,8 @@ int ata_init(void) mutex_lock(&ata_mutex); int rc = ata_power_up(); mutex_unlock(&ata_mutex); - if (IS_ERR(rc)) return rc; + if (IS_ERR(rc)) + return rc; return 0; } @@ -1101,7 +1185,8 @@ static int ata_smart(uint16_t* buf) ata_write_cbr(&ATA_PIO_DVR, BIT(6)); ata_write_cbr(&ATA_PIO_CSD, CMD_SMART); PASS_RC(ata_wait_for_start_of_transfer(10000000), 3, 7); - for (i = 0; i < 0x100; i++) buf[i] = ata_read_cbr(&ATA_PIO_DTR); + for (i = 0; i < 0x100; i++) + buf[i] = ata_read_cbr(&ATA_PIO_DTR); } ata_set_active(); return 0; @@ -1136,24 +1221,29 @@ int ata_spinup_time(void) return spinup_time; } +#ifdef HAVE_ATA_DMA int ata_get_dma_mode(void) { return dma_mode; } +#endif void INT_ATA(void) { uint32_t ata_irq = ATA_IRQ; ATA_IRQ = ata_irq; - if (ata_irq & ATA_IRQ_MASK) semaphore_release(&ata_wakeup); + if (ata_irq & ATA_IRQ_MASK) + semaphore_release(&ata_wakeup); ATA_IRQ_MASK = 0; } void INT_MMC(void) { uint32_t irq = SDCI_IRQ; - if (irq & SDCI_IRQ_DAT_DONE_INT) semaphore_release(&mmc_wakeup); - if (irq & SDCI_IRQ_IOCARD_IRQ_INT) semaphore_release(&mmc_comp_wakeup); + if (irq & SDCI_IRQ_DAT_DONE_INT) + semaphore_release(&mmc_wakeup); + if (irq & SDCI_IRQ_IOCARD_IRQ_INT) + semaphore_release(&mmc_comp_wakeup); SDCI_IRQ = irq; }