| 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 |