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 |