| Index: emcore/trunk/target/ipodclassic/storage_ata.c | 
| — | — | @@ -92,6 +92,10 @@ | 
| 93 | 93 | .bbt_reload = ata_bbt_reload, | 
| 94 | 94 | .bbt_disable = ata_bbt_disable, | 
| 95 | 95 | #endif | 
|  | 96 | +    .soft_reset = ata_soft_reset, | 
|  | 97 | +    .hard_reset = ata_hard_reset, | 
|  | 98 | +    .read_taskfile = ata_read_taskfile, | 
|  | 99 | +    .raw_cmd = ata_raw_cmd, | 
| 96 | 100 | }; | 
| 97 | 101 |  | 
| 98 | 102 |  | 
| — | — | @@ -465,7 +469,7 @@ | 
| 466 | 470 | return 0; | 
| 467 | 471 | } | 
| 468 | 472 |  | 
| 469 |  | -int ceata_rw_multiple_block(bool write, void* buf, uint32_t count, long timeout) | 
|  | 473 | +int ceata_rw_multiple_block(bool write, void* buf, uint32_t count, uint32_t blksize, long timeout) | 
| 470 | 474 | { | 
| 471 | 475 | mmc_discard_irq(); | 
| 472 | 476 | uint32_t responsetype; | 
| — | — | @@ -485,7 +489,7 @@ | 
| 486 | 490 | direction = MMC_CMD_CEATA_RW_MULTIPLE_BLOCK_DIRECTION_READ; | 
| 487 | 491 | invalidate_dcache(); | 
| 488 | 492 | } | 
| 489 |  | -    SDCI_DMASIZE = 0x200; | 
|  | 493 | +    SDCI_DMASIZE = blksize; | 
| 490 | 494 | SDCI_DMAADDR = buf; | 
| 491 | 495 | SDCI_DMACOUNT = count; | 
| 492 | 496 | SDCI_DCTRL = SDCI_DCTRL_TXFIFORST | SDCI_DCTRL_RXFIFORST; | 
| — | — | @@ -519,15 +523,16 @@ | 
| 520 | 524 | ceata_taskfile[0xf] = 0xec; | 
| 521 | 525 | PASS_RC(ceata_wait_idle(), 2, 0); | 
| 522 | 526 | PASS_RC(ceata_write_multiple_register(0, ceata_taskfile, 16), 2, 1); | 
| 523 |  | -        PASS_RC(ceata_rw_multiple_block(false, buf, 1, CEATA_COMMAND_TIMEOUT), 2, 2); | 
|  | 527 | +        PASS_RC(ceata_rw_multiple_block(false, buf, 1, 256, CEATA_COMMAND_TIMEOUT), 2, 2); | 
| 524 | 528 | } | 
| 525 | 529 | else | 
| 526 | 530 | { | 
| 527 |  | -        PASS_RC(ata_wait_for_not_bsy(10000000), 1, 0); | 
|  | 531 | +        PASS_RC(ata_wait_for_not_bsy(10000000), 2, 0); | 
| 528 | 532 | ata_write_cbr(&ATA_PIO_DVR, 0); | 
| 529 | 533 | ata_write_cbr(&ATA_PIO_CSD, 0xec); | 
| 530 |  | -        PASS_RC(ata_wait_for_start_of_transfer(10000000), 1, 1); | 
|  | 534 | +        PASS_RC(ata_wait_for_start_of_transfer(10000000), 2, 1); | 
| 531 | 535 | for (i = 0; i < 0x100; i++) buf[i] = ata_read_cbr(&ATA_PIO_DTR); | 
|  | 536 | +        PASS_RC(ata_wait_for_end_of_transfer(100000), 2, 2); | 
| 532 | 537 | } | 
| 533 | 538 | return 0; | 
| 534 | 539 | } | 
| — | — | @@ -741,7 +746,7 @@ | 
| 742 | 747 | ceata_taskfile[0xf] = write ? 0x35 : 0x25; | 
| 743 | 748 | PASS_RC(ceata_wait_idle(), 2, 0); | 
| 744 | 749 | PASS_RC(ceata_write_multiple_register(0, ceata_taskfile, 16), 2, 1); | 
| 745 |  | -        PASS_RC(ceata_rw_multiple_block(write, buffer, cnt << 3, CEATA_COMMAND_TIMEOUT), 2, 2); | 
|  | 750 | +        PASS_RC(ceata_rw_multiple_block(write, buffer, cnt << 3, 512, CEATA_COMMAND_TIMEOUT), 2, 2); | 
| 746 | 751 | } | 
| 747 | 752 | else | 
| 748 | 753 | { | 
| — | — | @@ -1013,6 +1018,184 @@ | 
| 1014 | 1019 | return rc; | 
| 1015 | 1020 | } | 
| 1016 | 1021 |  | 
|  | 1022 | +int ata_read_taskfile(struct ata_raw_cmd_t* cmd) | 
|  | 1023 | +{ | 
|  | 1024 | +    mutex_lock(&ata_mutex, TIMEOUT_BLOCK); | 
|  | 1025 | +    if (!ata_powered) PASS_RC(ata_power_up(), 1, 0); | 
|  | 1026 | +    ata_set_active(); | 
|  | 1027 | +    cmd->result_valid = false; | 
|  | 1028 | +    if (ceata) | 
|  | 1029 | +    { | 
|  | 1030 | +        PASS_RC_MTX(ceata_read_multiple_register(0, ceata_taskfile, 16), 1, 1, &ata_mutex); | 
|  | 1031 | +        cmd->feature = ceata_taskfile[0x9]; | 
|  | 1032 | +        cmd->count = ceata_taskfile[0xa]; | 
|  | 1033 | +        cmd->lba_low = ceata_taskfile[0xb]; | 
|  | 1034 | +        cmd->lba_mid = ceata_taskfile[0xc]; | 
|  | 1035 | +        cmd->lba_high = ceata_taskfile[0xd]; | 
|  | 1036 | +        cmd->device = ceata_taskfile[0xe]; | 
|  | 1037 | +        cmd->command = ceata_taskfile[0xf]; | 
|  | 1038 | +        if (cmd->lba48) | 
|  | 1039 | +        { | 
|  | 1040 | +            cmd->feature |= ceata_taskfile[0x1] << 8; | 
|  | 1041 | +            cmd->count |= ceata_taskfile[0x2] << 8; | 
|  | 1042 | +            cmd->lba_low |= ceata_taskfile[0x3] << 8; | 
|  | 1043 | +            cmd->lba_mid |= ceata_taskfile[0x4] << 8; | 
|  | 1044 | +            cmd->lba_high |= ceata_taskfile[0x5] << 8; | 
|  | 1045 | +        } | 
|  | 1046 | +    } | 
|  | 1047 | +    else | 
|  | 1048 | +    { | 
|  | 1049 | +        cmd->feature = ata_read_cbr(&ATA_PIO_FED); | 
|  | 1050 | +        cmd->count = ata_read_cbr(&ATA_PIO_SCR); | 
|  | 1051 | +        cmd->lba_low = ata_read_cbr(&ATA_PIO_LLR); | 
|  | 1052 | +        cmd->lba_mid = ata_read_cbr(&ATA_PIO_LMR); | 
|  | 1053 | +        cmd->lba_high = ata_read_cbr(&ATA_PIO_LHR); | 
|  | 1054 | +        cmd->device = ata_read_cbr(&ATA_PIO_DVR); | 
|  | 1055 | +        cmd->command = ata_read_cbr(&ATA_PIO_CSD); | 
|  | 1056 | +        if (cmd->lba48) | 
|  | 1057 | +        { | 
|  | 1058 | +            ata_write_cbr(&ATA_PIO_DAD, BIT(7)); | 
|  | 1059 | +            cmd->feature |= ata_read_cbr(&ATA_PIO_FED) << 8; | 
|  | 1060 | +            cmd->count |= ata_read_cbr(&ATA_PIO_SCR) << 8; | 
|  | 1061 | +            cmd->lba_low |= ata_read_cbr(&ATA_PIO_LLR) << 8; | 
|  | 1062 | +            cmd->lba_mid |= ata_read_cbr(&ATA_PIO_LMR) << 8; | 
|  | 1063 | +            cmd->lba_high |= ata_read_cbr(&ATA_PIO_LHR) << 8; | 
|  | 1064 | +            ata_write_cbr(&ATA_PIO_DAD, 0); | 
|  | 1065 | +        } | 
|  | 1066 | +    } | 
|  | 1067 | +    cmd->result_valid = true; | 
|  | 1068 | +    ata_set_active(); | 
|  | 1069 | +    mutex_unlock(&ata_mutex); | 
|  | 1070 | +    return 0; | 
|  | 1071 | +} | 
|  | 1072 | + | 
|  | 1073 | +int ata_raw_cmd(struct ata_raw_cmd_t* cmd) | 
|  | 1074 | +{ | 
|  | 1075 | +    mutex_lock(&ata_mutex, TIMEOUT_BLOCK); | 
|  | 1076 | +    if (!ata_powered) PASS_RC(ata_power_up(), 3, 0); | 
|  | 1077 | +    ata_set_active(); | 
|  | 1078 | +    int rc = 0, rc2 = 0; | 
|  | 1079 | +    cmd->result_valid = false; | 
|  | 1080 | +    if (ceata) | 
|  | 1081 | +    { | 
|  | 1082 | +        memset(ceata_taskfile, 0, 16); | 
|  | 1083 | +        if (cmd->lba48) | 
|  | 1084 | +        { | 
|  | 1085 | +            ceata_taskfile[0x1] = cmd->feature >> 8; | 
|  | 1086 | +            ceata_taskfile[0x2] = cmd->count >> 8; | 
|  | 1087 | +            ceata_taskfile[0x3] = cmd->lba_low >> 8; | 
|  | 1088 | +            ceata_taskfile[0x4] = cmd->lba_mid >> 8; | 
|  | 1089 | +            ceata_taskfile[0x5] = cmd->lba_high >> 8; | 
|  | 1090 | +        } | 
|  | 1091 | +        ceata_taskfile[0x9] = cmd->feature & 0xff; | 
|  | 1092 | +        ceata_taskfile[0xa] = cmd->count & 0xff; | 
|  | 1093 | +        ceata_taskfile[0xb] = cmd->lba_low & 0xff; | 
|  | 1094 | +        ceata_taskfile[0xc] = cmd->lba_mid & 0xff; | 
|  | 1095 | +        ceata_taskfile[0xd] = cmd->lba_high & 0xff; | 
|  | 1096 | +        ceata_taskfile[0xe] = cmd->device; | 
|  | 1097 | +        ceata_taskfile[0xf] = cmd->command; | 
|  | 1098 | +        PASS_RC_MTX(ceata_wait_idle(), 3, 1, &ata_mutex); | 
|  | 1099 | +        PASS_RC_MTX(ceata_write_multiple_register(0, ceata_taskfile, 16), 3, 2, &ata_mutex); | 
|  | 1100 | +        if (cmd->transfer) | 
|  | 1101 | +            rc = ceata_rw_multiple_block(cmd->send, cmd->buffer, cmd->size, cmd->blksize, CEATA_COMMAND_TIMEOUT); | 
|  | 1102 | +        else rc = ceata_wait_idle(); | 
|  | 1103 | +        if (IS_ERR(rc)) rc = ERR_RC((rc << 3) | 3); | 
|  | 1104 | +        rc2 = ata_read_taskfile(cmd); | 
|  | 1105 | +        if (IS_ERR(rc2) && !IS_ERR(rc)) rc = ERR_RC((rc2 << 3) | 4); | 
|  | 1106 | +    } | 
|  | 1107 | +    else | 
|  | 1108 | +    { | 
|  | 1109 | +        PASS_RC_MTX(ata_wait_for_rdy(100000), 3, 1, &ata_mutex); | 
|  | 1110 | +        ata_write_cbr(&ATA_PIO_DVR, 0); | 
|  | 1111 | +        if (cmd->lba48) | 
|  | 1112 | +        { | 
|  | 1113 | +            ata_write_cbr(&ATA_PIO_FED, cmd->feature >> 8); | 
|  | 1114 | +            ata_write_cbr(&ATA_PIO_SCR, cmd->count >> 8); | 
|  | 1115 | +            ata_write_cbr(&ATA_PIO_LLR, cmd->lba_low >> 8); | 
|  | 1116 | +            ata_write_cbr(&ATA_PIO_LMR, cmd->lba_mid >> 8); | 
|  | 1117 | +            ata_write_cbr(&ATA_PIO_LHR, cmd->lba_high >> 8); | 
|  | 1118 | +        } | 
|  | 1119 | +        ata_write_cbr(&ATA_PIO_FED, cmd->feature & 0xff); | 
|  | 1120 | +        ata_write_cbr(&ATA_PIO_SCR, cmd->count & 0xff); | 
|  | 1121 | +        ata_write_cbr(&ATA_PIO_LLR, cmd->lba_low & 0xff); | 
|  | 1122 | +        ata_write_cbr(&ATA_PIO_LMR, cmd->lba_mid & 0xff); | 
|  | 1123 | +        ata_write_cbr(&ATA_PIO_LHR, cmd->lba_high & 0xff); | 
|  | 1124 | +        ata_write_cbr(&ATA_PIO_DVR, cmd->device); | 
|  | 1125 | +        ata_write_cbr(&ATA_PIO_CSD, cmd->command); | 
|  | 1126 | +        sleep(cmd->delay); | 
|  | 1127 | +        if (cmd->transfer) | 
|  | 1128 | +        { | 
|  | 1129 | +            if (cmd->dma) | 
|  | 1130 | +            { | 
|  | 1131 | +                rc = ata_wait_for_start_of_transfer(500000); | 
|  | 1132 | +                if (IS_ERR(rc)) rc = ERR_RC((rc << 3) | 2); | 
|  | 1133 | +                else | 
|  | 1134 | +                { | 
|  | 1135 | +                    if (cmd->send) | 
|  | 1136 | +                    { | 
|  | 1137 | +                        clean_dcache(); | 
|  | 1138 | +                        ATA_SBUF_START = cmd->buffer; | 
|  | 1139 | +                        ATA_SBUF_SIZE = cmd->size * cmd->blksize; | 
|  | 1140 | +                        ATA_CFG |= BIT(4); | 
|  | 1141 | +                    } | 
|  | 1142 | +                    else | 
|  | 1143 | +                    { | 
|  | 1144 | +                        invalidate_dcache(); | 
|  | 1145 | +                        ATA_TBUF_START = cmd->buffer; | 
|  | 1146 | +                        ATA_TBUF_SIZE = cmd->size * cmd->blksize; | 
|  | 1147 | +                        ATA_CFG &= ~BIT(4); | 
|  | 1148 | +                    } | 
|  | 1149 | +                    ATA_XFR_NUM = cmd->blksize * cmd->size - 1; | 
|  | 1150 | +                    ATA_CFG |= ata_dma_flags; | 
|  | 1151 | +                    ATA_CFG &= ~(BIT(7) | BIT(8)); | 
|  | 1152 | +                    wakeup_wait(&ata_wakeup, TIMEOUT_NONE); | 
|  | 1153 | +                    ATA_IRQ = BITRANGE(0, 4); | 
|  | 1154 | +                    ATA_IRQ_MASK = BIT(0); | 
|  | 1155 | +                    ATA_COMMAND = BIT(0); | 
|  | 1156 | +                    if (wakeup_wait(&ata_wakeup, 500000) == THREAD_TIMEOUT) rc = ERR_RC(3); | 
|  | 1157 | +                    ATA_COMMAND = BIT(1); | 
|  | 1158 | +                    ATA_CFG &= ~(BITRANGE(2, 3) | BIT(12)); | 
|  | 1159 | +                } | 
|  | 1160 | +            } | 
|  | 1161 | +            else | 
|  | 1162 | +            { | 
|  | 1163 | +                ATA_CFG &= ~ata_dma_flags; | 
|  | 1164 | +                while (cmd->size--) | 
|  | 1165 | +                { | 
|  | 1166 | +                    rc = ata_wait_for_start_of_transfer(500000); | 
|  | 1167 | +                    if (IS_ERR(rc)) | 
|  | 1168 | +                    { | 
|  | 1169 | +                        rc = ERR_RC((rc << 3) | 4); | 
|  | 1170 | +                        break; | 
|  | 1171 | +                    } | 
|  | 1172 | +                    int i; | 
|  | 1173 | +                    if (cmd->send) | 
|  | 1174 | +                        for (i = 0; i < (cmd->blksize >> 1); i++) | 
|  | 1175 | +                            ata_write_cbr(&ATA_PIO_DTR, ((uint16_t*)cmd->buffer)[i]); | 
|  | 1176 | +                    else | 
|  | 1177 | +                        for (i = 0; i < (cmd->blksize >> 1); i++) | 
|  | 1178 | +                            ((uint16_t*)cmd->buffer)[i] = ata_read_cbr(&ATA_PIO_DTR); | 
|  | 1179 | +                    cmd->buffer += cmd->blksize; | 
|  | 1180 | +                } | 
|  | 1181 | +            } | 
|  | 1182 | +            if (!IS_ERR(rc)) | 
|  | 1183 | +            { | 
|  | 1184 | +                rc = ata_wait_for_end_of_transfer(100000); | 
|  | 1185 | +                if (IS_ERR(rc)) rc = ERR_RC((rc << 3) | 5); | 
|  | 1186 | +            } | 
|  | 1187 | +        } | 
|  | 1188 | +        else | 
|  | 1189 | +        { | 
|  | 1190 | +            rc = ata_wait_for_rdy(500000); | 
|  | 1191 | +            if (IS_ERR(rc)) rc = ERR_RC((rc << 3) | 6); | 
|  | 1192 | +        } | 
|  | 1193 | +        ata_read_taskfile(cmd);  // Cannot fail for PATA | 
|  | 1194 | +    } | 
|  | 1195 | +    ata_set_active(); | 
|  | 1196 | +    mutex_unlock(&ata_mutex); | 
|  | 1197 | +    return rc; | 
|  | 1198 | +} | 
|  | 1199 | + | 
| 1017 | 1200 | int ata_read_sectors(IF_MD2(int drive,) unsigned long start, int incount, | 
| 1018 | 1201 | void* inbuf) | 
| 1019 | 1202 | { | 
| Index: emcore/trunk/target/ipodclassic/config.h | 
| — | — | @@ -38,6 +38,7 @@ | 
| 39 | 39 |  | 
| 40 | 40 |  | 
| 41 | 41 | #define ATA_HAVE_BBT | 
|  | 42 | +#define TEST_FAT | 
| 42 | 43 |  | 
| 43 | 44 |  | 
| 44 | 45 | #endif | 
| Index: emcore/trunk/target/ipodclassic/storage_ata-target.h | 
| — | — | @@ -27,6 +27,27 @@ | 
| 28 | 28 | #include "../global.h" | 
| 29 | 29 |  | 
| 30 | 30 |  | 
|  | 31 | +struct __attribute__((packed)) ata_raw_cmd_t | 
|  | 32 | +{ | 
|  | 33 | +    uint8_t lba48; | 
|  | 34 | +    uint8_t transfer; | 
|  | 35 | +    uint8_t send; | 
|  | 36 | +    uint8_t dma; | 
|  | 37 | +    uint32_t delay; | 
|  | 38 | +    void* buffer; | 
|  | 39 | +    uint32_t size; | 
|  | 40 | +    uint32_t blksize; | 
|  | 41 | +    uint16_t feature; | 
|  | 42 | +    uint16_t count; | 
|  | 43 | +    uint16_t lba_low; | 
|  | 44 | +    uint16_t lba_mid; | 
|  | 45 | +    uint16_t lba_high; | 
|  | 46 | +    uint8_t device; | 
|  | 47 | +    uint8_t command; | 
|  | 48 | +    uint8_t result_valid; | 
|  | 49 | +    uint8_t reserved[3]; | 
|  | 50 | +}; | 
|  | 51 | + | 
| 31 | 52 | struct ata_target_driverinfo | 
| 32 | 53 | { | 
| 33 | 54 | void (*srst_after_error)(bool enable); | 
| — | — | @@ -34,6 +55,10 @@ | 
| 35 | 56 | int (*bbt_translate)(uint64_t sector, uint32_t count, uint64_t* phys, uint32_t* physcount); | 
| 36 | 57 | int (*bbt_reload)(); | 
| 37 | 58 | void (*bbt_disable)(); | 
|  | 59 | +    int (*soft_reset)(); | 
|  | 60 | +    int (*hard_reset)(); | 
|  | 61 | +    int (*read_taskfile)(struct ata_raw_cmd_t* cmd); | 
|  | 62 | +    int (*raw_cmd)(struct ata_raw_cmd_t* cmd); | 
| 38 | 63 | }; | 
| 39 | 64 |  | 
| 40 | 65 |  | 
| — | — | @@ -41,8 +66,12 @@ | 
| 42 | 67 | extern uint64_t ata_total_sectors; | 
| 43 | 68 | extern struct mutex ata_mutex; | 
| 44 | 69 |  | 
| 45 |  | -void ata_set_retries(int retries);
 | 
| 46 |  | -void ata_srst_after_error(bool enable);
 | 
|  | 70 | +extern void ata_set_retries(int retries); | 
|  | 71 | +extern void ata_srst_after_error(bool enable); | 
|  | 72 | +extern int ata_soft_reset(); | 
|  | 73 | +extern int ata_hard_reset(); | 
|  | 74 | +extern int ata_read_taskfile(struct ata_raw_cmd_t* cmd); | 
|  | 75 | +extern int ata_raw_cmd(struct ata_raw_cmd_t* cmd); | 
| 47 | 76 |  | 
| 48 | 77 | #ifdef ATA_HAVE_BBT | 
| 49 | 78 | extern uint16_t (*ata_bbt)[0x20]; | 
| Index: emcore/trunk/export/syscallapi.h | 
| — | — | @@ -74,7 +74,7 @@ | 
| 75 | 75 | #endif | 
| 76 | 76 |  | 
| 77 | 77 | /* increase this every time the api struct changes */ | 
| 78 |  | -#define EMCORE_API_VERSION 8 | 
|  | 78 | +#define EMCORE_API_VERSION 9 | 
| 79 | 79 |  | 
| 80 | 80 | /* update this to latest version if a change to the api struct breaks | 
| 81 | 81 | backwards compatibility (and please take the opportunity to sort in any |