Index: embios/trunk/target/ipodnano3g/s5l8702.h |
— | — | @@ -533,6 +533,41 @@ |
534 | 534 | #define LCDWDATA (*((uint32_t volatile*)(0x38300040)))
|
535 | 535 |
|
536 | 536 |
|
| 537 | +/////ATA/////
|
| 538 | +#define ATA_CONTROL (*((uint32_t volatile*)(0x38700000)))
|
| 539 | +#define ATA_STATUS (*((uint32_t volatile*)(0x38700004)))
|
| 540 | +#define ATA_COMMAND (*((uint32_t volatile*)(0x38700008)))
|
| 541 | +#define ATA_SWRST (*((uint32_t volatile*)(0x3870000c)))
|
| 542 | +#define ATA_IRQ (*((uint32_t volatile*)(0x38700010)))
|
| 543 | +#define ATA_IRQ_MASK (*((uint32_t volatile*)(0x38700014)))
|
| 544 | +#define ATA_CFG (*((uint32_t volatile*)(0x38700018)))
|
| 545 | +#define ATA_MDMA_TIME (*((uint32_t volatile*)(0x38700028)))
|
| 546 | +#define ATA_PIO_TIME (*((uint32_t volatile*)(0x3870002c)))
|
| 547 | +#define ATA_UDMA_TIME (*((uint32_t volatile*)(0x38700030)))
|
| 548 | +#define ATA_XFR_NUM (*((uint32_t volatile*)(0x38700034)))
|
| 549 | +#define ATA_XFR_CNT (*((uint32_t volatile*)(0x38700038)))
|
| 550 | +#define ATA_TBUF_START (*((void* volatile*)(0x3870003c)))
|
| 551 | +#define ATA_TBUF_SIZE (*((uint32_t volatile*)(0x38700040)))
|
| 552 | +#define ATA_SBUF_START (*((void* volatile*)(0x38700044)))
|
| 553 | +#define ATA_SBUF_SIZE (*((uint32_t volatile*)(0x38700048)))
|
| 554 | +#define ATA_CADR_TBUF (*((void* volatile*)(0x3870004c)))
|
| 555 | +#define ATA_CADR_SBUF (*((void* volatile*)(0x38700050)))
|
| 556 | +#define ATA_PIO_DTR (*((uint32_t volatile*)(0x38700054)))
|
| 557 | +#define ATA_PIO_FED (*((uint32_t volatile*)(0x38700058)))
|
| 558 | +#define ATA_PIO_SCR (*((uint32_t volatile*)(0x3870005c)))
|
| 559 | +#define ATA_PIO_LLR (*((uint32_t volatile*)(0x38700060)))
|
| 560 | +#define ATA_PIO_LMR (*((uint32_t volatile*)(0x38700064)))
|
| 561 | +#define ATA_PIO_LHR (*((uint32_t volatile*)(0x38700068)))
|
| 562 | +#define ATA_PIO_DVR (*((uint32_t volatile*)(0x3870006c)))
|
| 563 | +#define ATA_PIO_CSD (*((uint32_t volatile*)(0x38700070)))
|
| 564 | +#define ATA_PIO_DAD (*((uint32_t volatile*)(0x38700074)))
|
| 565 | +#define ATA_PIO_READY (*((uint32_t volatile*)(0x38700078)))
|
| 566 | +#define ATA_PIO_RDATA (*((uint32_t volatile*)(0x3870007c)))
|
| 567 | +#define ATA_BUS_FIFO_STATUS (*((uint32_t volatile*)(0x38700080)))
|
| 568 | +#define ATA_FIFO_STATUS (*((uint32_t volatile*)(0x38700084)))
|
| 569 | +#define ATA_DMA_ADDR (*((void* volatile*)(0x38700088)))
|
| 570 | +
|
| 571 | +
|
537 | 572 | /////CLOCK GATES/////
|
538 | 573 | #define CLOCKGATE_USB_1 2
|
539 | 574 | #define CLOCKGATE_USB_2 35
|
— | — | @@ -544,6 +579,7 @@ |
545 | 580 | #define IRQ_DMAC(d) 16 + d
|
546 | 581 | #define IRQ_DMAC0 16
|
547 | 582 | #define IRQ_DMAC1 17
|
| 583 | +#define IRQ_ATA 29
|
548 | 584 |
|
549 | 585 |
|
550 | 586 | #endif
|
Index: embios/trunk/target/ipodnano3g/interrupt.c |
— | — | @@ -78,7 +78,7 @@ |
79 | 79 | default_interrupt(INT_IRQ26);
|
80 | 80 | default_interrupt(INT_IRQ27);
|
81 | 81 | default_interrupt(INT_IRQ28);
|
82 | | -default_interrupt(INT_IRQ29);
|
| 82 | +default_interrupt(INT_ATA);
|
83 | 83 | default_interrupt(INT_IRQ30);
|
84 | 84 | default_interrupt(INT_IRQ31);
|
85 | 85 | default_interrupt(INT_IRQ32);
|
— | — | @@ -179,7 +179,7 @@ |
180 | 180 | INT_IRQ0,INT_IRQ1,INT_IRQ2,INT_IRQ3,INT_IRQ4,INT_IRQ5,INT_IRQ6,INT_IRQ7,
|
181 | 181 | INT_TIMER,INT_IRQ9,INT_IRQ10,INT_IRQ11,INT_IRQ12,INT_IRQ13,INT_IRQ14,INT_IRQ15,
|
182 | 182 | INT_DMAC0,INT_DMAC1,INT_IRQ18,INT_USB_FUNC,INT_IRQ20,INT_IRQ21,INT_IRQ22,INT_IRQ23,
|
183 | | - INT_IRQ24,INT_IRQ25,INT_IRQ26,INT_IRQ27,INT_IRQ28,INT_IRQ29,INT_IRQ30,INT_IRQ31,
|
| 183 | + INT_IRQ24,INT_IRQ25,INT_IRQ26,INT_IRQ27,INT_IRQ28,INT_ATA,INT_IRQ30,INT_IRQ31,
|
184 | 184 | INT_IRQ32,INT_IRQ33,INT_IRQ34,INT_IRQ35,INT_IRQ36,INT_IRQ37,INT_IRQ38,INT_IRQ39,
|
185 | 185 | INT_IRQ40,INT_IRQ41,INT_IRQ42,INT_IRQ43,INT_IRQ55,INT_IRQ56,INT_IRQ57,INT_IRQ58,
|
186 | 186 | INT_IRQ48,INT_IRQ49,INT_IRQ50,INT_IRQ51,INT_IRQ52,INT_IRQ53,INT_IRQ54,INT_IRQ55,
|
— | — | @@ -231,6 +231,9 @@ |
232 | 232 | VIC0INTENABLE = 1 << IRQ_TIMER;
|
233 | 233 | VIC0INTENABLE = 1 << IRQ_DMAC0;
|
234 | 234 | VIC0INTENABLE = 1 << IRQ_DMAC1;
|
| 235 | +#ifdef TARGET_ipodclassic
|
| 236 | + VIC0INTENABLE = 1 << IRQ_ATA;
|
| 237 | +#endif
|
235 | 238 | }
|
236 | 239 |
|
237 | 240 | void interrupt_shutdown(void)
|
Index: embios/trunk/target/ipodclassic/storage_ata.c |
— | — | @@ -0,0 +1,452 @@ |
| 2 | +/***************************************************************************
|
| 3 | + * __________ __ ___.
|
| 4 | + * Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
| 5 | + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
| 6 | + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
| 7 | + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
| 8 | + * \/ \/ \/ \/ \/
|
| 9 | + * $Id$
|
| 10 | + *
|
| 11 | + * Copyright (C) 2007 Dave Chapman
|
| 12 | + *
|
| 13 | + * This program is free software; you can redistribute it and/or
|
| 14 | + * modify it under the terms of the GNU General Public License
|
| 15 | + * as published by the Free Software Foundation; either version 2
|
| 16 | + * of the License, or (at your option) any later version.
|
| 17 | + *
|
| 18 | + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
| 19 | + * KIND, either express or implied.
|
| 20 | + *
|
| 21 | + ****************************************************************************/
|
| 22 | +#include "global.h"
|
| 23 | +#include "thread.h"
|
| 24 | +#include "disk.h"
|
| 25 | +#include "storage.h"
|
| 26 | +#include "timer.h"
|
| 27 | +#include "../ipodnano3g/s5l8702.h"
|
| 28 | +
|
| 29 | +/** static, private data **/
|
| 30 | +uint16_t ata_identify_data[0x100];
|
| 31 | +bool ata_lba48;
|
| 32 | +bool ata_dma;
|
| 33 | +uint64_t ata_total_sectors;
|
| 34 | +static struct mutex ata_mutex;
|
| 35 | +static struct wakeup ata_wakeup;
|
| 36 | +static uint32_t ata_dma_flags;
|
| 37 | +static long ata_last_activity_value = -1;
|
| 38 | +static long ata_sleep_timeout = 20000000;
|
| 39 | +static uint32_t ata_stack[0x80];
|
| 40 | +static bool ata_powered;
|
| 41 | +
|
| 42 | +
|
| 43 | +static uint16_t ata_read_cbr(uint32_t volatile* reg)
|
| 44 | +{
|
| 45 | + while (!(ATA_PIO_READY & 2)) sleep(0);
|
| 46 | + volatile uint32_t dummy = *reg;
|
| 47 | + while (!(ATA_PIO_READY & 1)) sleep(0);
|
| 48 | + return ATA_PIO_RDATA;
|
| 49 | +}
|
| 50 | +
|
| 51 | +static void ata_write_cbr(uint32_t volatile* reg, uint16_t data)
|
| 52 | +{
|
| 53 | + while (!(ATA_PIO_READY & 2)) sleep(0);
|
| 54 | + *reg = data;
|
| 55 | +}
|
| 56 | +
|
| 57 | +static int ata_wait_for_not_bsy(long timeout)
|
| 58 | +{
|
| 59 | + long startusec = USEC_TIMER;
|
| 60 | + while (true)
|
| 61 | + {
|
| 62 | + uint8_t csd = ata_read_cbr(&ATA_PIO_CSD);
|
| 63 | + if (!(csd & BIT(7))) return 0;
|
| 64 | + if (TIMEOUT_EXPIRED(startusec, timeout)) RET_ERR(0);
|
| 65 | + sleep(100);
|
| 66 | + }
|
| 67 | +}
|
| 68 | +
|
| 69 | +static int ata_wait_for_rdy(long timeout)
|
| 70 | +{
|
| 71 | + long startusec = USEC_TIMER;
|
| 72 | + PASS_RC(ata_wait_for_not_bsy(timeout), 1, 0);
|
| 73 | + while (true)
|
| 74 | + {
|
| 75 | + uint8_t dad = ata_read_cbr(&ATA_PIO_DAD);
|
| 76 | + if (dad & BIT(6)) return 0;
|
| 77 | + if (TIMEOUT_EXPIRED(startusec, timeout)) RET_ERR(1);
|
| 78 | + sleep(100);
|
| 79 | + }
|
| 80 | +}
|
| 81 | +
|
| 82 | +static int ata_wait_for_start_of_transfer(long timeout)
|
| 83 | +{
|
| 84 | + long startusec = USEC_TIMER;
|
| 85 | + PASS_RC(ata_wait_for_not_bsy(timeout), 2, 0);
|
| 86 | + while (true)
|
| 87 | + {
|
| 88 | + uint8_t dad = ata_read_cbr(&ATA_PIO_DAD);
|
| 89 | + if (dad & BIT(0)) RET_ERR(1);
|
| 90 | + if ((dad & (BIT(7) | BIT(3))) == BIT(3)) return 0;
|
| 91 | + if (TIMEOUT_EXPIRED(startusec, timeout)) RET_ERR(2);
|
| 92 | + sleep(100);
|
| 93 | + }
|
| 94 | +}
|
| 95 | +
|
| 96 | +static int ata_wait_for_end_of_transfer(long timeout)
|
| 97 | +{
|
| 98 | + PASS_RC(ata_wait_for_not_bsy(timeout), 2, 0);
|
| 99 | + uint8_t dad = ata_read_cbr(&ATA_PIO_DAD);
|
| 100 | + if (dad & BIT(0)) RET_ERR(1);
|
| 101 | + if ((dad & (BIT(3) | BITRANGE(5, 7))) == BIT(6)) return 0;
|
| 102 | + RET_ERR(2);
|
| 103 | +}
|
| 104 | +
|
| 105 | +int ata_identify(uint16_t* buf)
|
| 106 | +{
|
| 107 | + int i;
|
| 108 | + PASS_RC(ata_wait_for_not_bsy(10000000), 1, 0);
|
| 109 | + ata_write_cbr(&ATA_PIO_DVR, 0);
|
| 110 | + ata_write_cbr(&ATA_PIO_CSD, 0xec);
|
| 111 | + PASS_RC(ata_wait_for_start_of_transfer(10000000), 1, 1);
|
| 112 | + for (i = 0; i < 0x100; i++)
|
| 113 | + {
|
| 114 | + uint16_t word = ata_read_cbr(&ATA_PIO_DTR);
|
| 115 | + buf[i] = (word >> 8) | (word << 8);
|
| 116 | + }
|
| 117 | +}
|
| 118 | +
|
| 119 | +void ata_set_active(void)
|
| 120 | +{
|
| 121 | + ata_last_activity_value = USEC_TIMER;
|
| 122 | +}
|
| 123 | +
|
| 124 | +int ata_power_up()
|
| 125 | +{
|
| 126 | + ata_set_active();
|
| 127 | + i2c_sendbyte(0, 0xe6, 0x1b, 1);
|
| 128 | + clockgate_enable(5, true);
|
| 129 | + ATA_CFG = BIT(0);
|
| 130 | + sleep(1000);
|
| 131 | + ATA_CFG = 0;
|
| 132 | + sleep(6000);
|
| 133 | + ATA_SWRST = BIT(0);
|
| 134 | + sleep(500);
|
| 135 | + ATA_SWRST = 0;
|
| 136 | + sleep(90000);
|
| 137 | + ATA_CONTROL = BIT(0);
|
| 138 | + sleep(200000);
|
| 139 | + ATA_PIO_TIME = 0x191f7;
|
| 140 | + ATA_PIO_LHR = 0;
|
| 141 | + while (!(ATA_PIO_READY & BIT(1))) sleep(100);
|
| 142 | + PASS_RC(ata_identify(ata_identify_data), 2, 0);
|
| 143 | + uint32_t piotime = 0x11f3;
|
| 144 | + uint32_t mdmatime = 0x1c175;
|
| 145 | + uint32_t udmatime = 0x5071152;
|
| 146 | + uint32_t param = 0;
|
| 147 | + ata_dma_flags = 0;
|
| 148 | + ata_lba48 = ata_identify_data[83] & BIT(10) ? true : false;
|
| 149 | + if (ata_lba48)
|
| 150 | + ata_total_sectors = ata_identify_data[100]
|
| 151 | + | (((uint64_t)ata_identify_data[101]) << 16)
|
| 152 | + | (((uint64_t)ata_identify_data[102]) << 32)
|
| 153 | + | (((uint64_t)ata_identify_data[103]) << 48);
|
| 154 | + else ata_total_sectors = ata_identify_data[60] | (((uint32_t)ata_identify_data[61]) << 16);
|
| 155 | + if (ata_identify_data[53] & BIT(1))
|
| 156 | + {
|
| 157 | + if (ata_identify_data[64] & BIT(1)) piotime = 0x2072;
|
| 158 | + else if (ata_identify_data[64] & BIT(0)) piotime = 0x7083;
|
| 159 | + }
|
| 160 | + if (ata_identify_data[63] & BIT(2))
|
| 161 | + {
|
| 162 | + mdmatime = 0x5072;
|
| 163 | + param = 0x22;
|
| 164 | + }
|
| 165 | + else if (ata_identify_data[63] & BIT(1))
|
| 166 | + {
|
| 167 | + mdmatime = 0x7083;
|
| 168 | + param = 0x21;
|
| 169 | + }
|
| 170 | + if (ata_identify_data[63] & BITRANGE(0, 2))
|
| 171 | + {
|
| 172 | + ata_dma_flags = BIT(3) | BIT(10);
|
| 173 | + param |= 0x20;
|
| 174 | + }
|
| 175 | + if (ata_identify_data[53] & BIT(2))
|
| 176 | + {
|
| 177 | + if (ata_identify_data[88] & BIT(4))
|
| 178 | + {
|
| 179 | + udmatime = 0x2010a52;
|
| 180 | + param = 0x44;
|
| 181 | + }
|
| 182 | + else if (ata_identify_data[88] & BIT(3))
|
| 183 | + {
|
| 184 | + udmatime = 0x2020a52;
|
| 185 | + param = 0x43;
|
| 186 | + }
|
| 187 | + else if (ata_identify_data[88] & BIT(2))
|
| 188 | + {
|
| 189 | + udmatime = 0x3030a52;
|
| 190 | + param = 0x42;
|
| 191 | + }
|
| 192 | + else if (ata_identify_data[88] & BIT(1))
|
| 193 | + {
|
| 194 | + udmatime = 0x3050a52;
|
| 195 | + param = 0x41;
|
| 196 | + }
|
| 197 | + if (ata_identify_data[88] & BITRANGE(0, 4))
|
| 198 | + {
|
| 199 | + ata_dma_flags = BIT(2) | BIT(3) | BIT(9) | BIT(10);
|
| 200 | + param |= 0x40;
|
| 201 | + }
|
| 202 | + }
|
| 203 | + ata_dma = param ? true : false;
|
| 204 | + PASS_RC(ata_wait_for_rdy(500000), 2, 1);
|
| 205 | + ata_write_cbr(&ATA_PIO_DVR, 0);
|
| 206 | + ata_write_cbr(&ATA_PIO_FED, 3);
|
| 207 | + ata_write_cbr(&ATA_PIO_SCR, param);
|
| 208 | + ata_write_cbr(&ATA_PIO_CSD, 0xef);
|
| 209 | + PASS_RC(ata_wait_for_rdy(500000), 2, 2);
|
| 210 | + ATA_PIO_TIME = piotime;
|
| 211 | + ATA_MDMA_TIME = mdmatime;
|
| 212 | + ATA_UDMA_TIME = udmatime;
|
| 213 | + ata_powered = true;
|
| 214 | + ata_set_active();
|
| 215 | + return 0;
|
| 216 | +}
|
| 217 | +
|
| 218 | +void ata_power_down()
|
| 219 | +{
|
| 220 | + ata_powered = false;
|
| 221 | + ata_wait_for_rdy(1000000);
|
| 222 | + ata_write_cbr(&ATA_PIO_DVR, 0);
|
| 223 | + ata_write_cbr(&ATA_PIO_CSD, 0xe0);
|
| 224 | + ata_wait_for_rdy(1000000);
|
| 225 | + sleep(30000);
|
| 226 | + ATA_CONTROL = 0;
|
| 227 | + while (!(ATA_CONTROL & BIT(1))) sleep(0);
|
| 228 | + clockgate_enable(5, false);
|
| 229 | + i2c_sendbyte(0, 0xe6, 0x1b, 0);
|
| 230 | +}
|
| 231 | +
|
| 232 | +int ata_rw_sectors(uint64_t sector, uint32_t count, void* buffer, bool write)
|
| 233 | +{
|
| 234 | + if (sector + count > ata_total_sectors) RET_ERR(0);
|
| 235 | + if (!ata_powered) ata_power_up();
|
| 236 | + ata_set_active();
|
| 237 | + if (ata_dma && write) clean_dcache();
|
| 238 | + else if (ata_dma) invalidate_dcache();
|
| 239 | + ATA_COMMAND = BIT(1);
|
| 240 | + while (count)
|
| 241 | + {
|
| 242 | + uint32_t cnt = MIN(64, count);
|
| 243 | + PASS_RC(ata_wait_for_rdy(100000), 2, 0);
|
| 244 | + ata_write_cbr(&ATA_PIO_DVR, 0);
|
| 245 | + if (ata_lba48)
|
| 246 | + {
|
| 247 | + ata_write_cbr(&ATA_PIO_SCR, cnt >> 5);
|
| 248 | + ata_write_cbr(&ATA_PIO_SCR, (cnt << 3) & 0xff);
|
| 249 | + ata_write_cbr(&ATA_PIO_LHR, (sector >> 37) & 0xff);
|
| 250 | + ata_write_cbr(&ATA_PIO_LMR, (sector >> 29) & 0xff);
|
| 251 | + ata_write_cbr(&ATA_PIO_LLR, (sector >> 21) & 0xff);
|
| 252 | + ata_write_cbr(&ATA_PIO_LHR, (sector >> 13) & 0xff);
|
| 253 | + ata_write_cbr(&ATA_PIO_LMR, (sector >> 5) & 0xff);
|
| 254 | + ata_write_cbr(&ATA_PIO_LLR, (sector << 3) & 0xff);
|
| 255 | + ata_write_cbr(&ATA_PIO_DVR, BIT(6));
|
| 256 | + if (write) ata_write_cbr(&ATA_PIO_CSD, ata_dma ? 0x35 : 0x39);
|
| 257 | + else ata_write_cbr(&ATA_PIO_CSD, ata_dma ? 0x25 : 0x29);
|
| 258 | + }
|
| 259 | + else
|
| 260 | + {
|
| 261 | + ata_write_cbr(&ATA_PIO_SCR, (cnt << 3) & 0xff);
|
| 262 | + ata_write_cbr(&ATA_PIO_LHR, (sector >> 13) & 0xff);
|
| 263 | + ata_write_cbr(&ATA_PIO_LMR, (sector >> 5) & 0xff);
|
| 264 | + ata_write_cbr(&ATA_PIO_LLR, (sector << 3) & 0xff);
|
| 265 | + ata_write_cbr(&ATA_PIO_DVR, BIT(6) | ((sector >> 21) & 0xf));
|
| 266 | + if (write) ata_write_cbr(&ATA_PIO_CSD, ata_dma ? 0xca : 0x30);
|
| 267 | + else ata_write_cbr(&ATA_PIO_CSD, ata_dma ? 0xc8 : 0xc4);
|
| 268 | + }
|
| 269 | + sector += cnt;
|
| 270 | + count -= cnt;
|
| 271 | + if (ata_dma)
|
| 272 | + {
|
| 273 | + if (write)
|
| 274 | + {
|
| 275 | + ATA_SBUF_START = buffer;
|
| 276 | + ATA_SBUF_SIZE = SECTOR_SIZE * cnt;
|
| 277 | + ATA_CFG |= BIT(4);
|
| 278 | + }
|
| 279 | + else
|
| 280 | + {
|
| 281 | + ATA_TBUF_START = buffer;
|
| 282 | + ATA_TBUF_SIZE = SECTOR_SIZE * cnt;
|
| 283 | + ATA_CFG &= ~BIT(4);
|
| 284 | + }
|
| 285 | + ATA_XFR_NUM = SECTOR_SIZE * cnt - 1;
|
| 286 | + ATA_CFG |= ata_dma_flags;
|
| 287 | + ATA_CFG &= ~(BIT(7) | BIT(8));
|
| 288 | + wakeup_wait(&ata_wakeup, TIMEOUT_NONE);
|
| 289 | + ATA_IRQ = BITRANGE(0, 4);
|
| 290 | + ATA_IRQ_MASK = BIT(0);
|
| 291 | + ATA_COMMAND = BIT(0);
|
| 292 | + if (wakeup_wait(&ata_wakeup, 3000000) == THREAD_TIMEOUT)
|
| 293 | + {
|
| 294 | + ATA_COMMAND = BIT(1);
|
| 295 | + ATA_CFG &= ~(BITRANGE(2, 3) | BIT(12));
|
| 296 | + RET_ERR(2);
|
| 297 | + }
|
| 298 | + ATA_COMMAND = BIT(1);
|
| 299 | + ATA_CFG &= ~(BITRANGE(2, 3) | BIT(12));
|
| 300 | + buffer += SECTOR_SIZE * cnt;
|
| 301 | + }
|
| 302 | + else
|
| 303 | + {
|
| 304 | + cnt *= SECTOR_SIZE / 512;
|
| 305 | + while (cnt--)
|
| 306 | + {
|
| 307 | + int i;
|
| 308 | + PASS_RC(ata_wait_for_start_of_transfer(3000000), 2, 1);
|
| 309 | + if (write)
|
| 310 | + for (i = 0; i < 256; i++)
|
| 311 | + ata_write_cbr(&ATA_PIO_DTR, ((uint16_t*)buffer)[i]);
|
| 312 | + else
|
| 313 | + for (i = 0; i < 256; i++)
|
| 314 | + ((uint16_t*)buffer)[i] = ata_read_cbr(&ATA_PIO_DTR);
|
| 315 | + buffer += 512;
|
| 316 | + }
|
| 317 | + }
|
| 318 | + PASS_RC(ata_wait_for_end_of_transfer(100000), 2, 3);
|
| 319 | + }
|
| 320 | + ata_set_active();
|
| 321 | + return 0;
|
| 322 | +}
|
| 323 | +
|
| 324 | +static void ata_thread(void)
|
| 325 | +{
|
| 326 | + while (true)
|
| 327 | + {
|
| 328 | + mutex_lock(&ata_mutex, TIMEOUT_BLOCK);
|
| 329 | + if (TIME_AFTER(USEC_TIMER, ata_last_activity_value + ata_sleep_timeout) && ata_powered)
|
| 330 | + ata_power_down();
|
| 331 | + mutex_unlock(&ata_mutex);
|
| 332 | + sleep(1000000);
|
| 333 | + }
|
| 334 | +}
|
| 335 | +
|
| 336 | +/* API Functions */
|
| 337 | +int ata_soft_reset()
|
| 338 | +{
|
| 339 | + mutex_lock(&ata_mutex, TIMEOUT_BLOCK);
|
| 340 | + if (!ata_powered) ata_power_up();
|
| 341 | + ata_set_active();
|
| 342 | + ata_write_cbr(&ATA_PIO_DAD, BIT(1) | BIT(2));
|
| 343 | + sleep(10);
|
| 344 | + ata_write_cbr(&ATA_PIO_DAD, 0);
|
| 345 | + PASS_RC_MTX(ata_wait_for_rdy(5000000), 0, 0, &ata_mutex);
|
| 346 | + ata_set_active();
|
| 347 | + mutex_unlock(&ata_mutex);
|
| 348 | +}
|
| 349 | +
|
| 350 | +int ata_read_sectors(IF_MD2(int drive,) unsigned long start, int incount,
|
| 351 | + void* inbuf)
|
| 352 | +{
|
| 353 | + mutex_lock(&ata_mutex, TIMEOUT_BLOCK);
|
| 354 | + int tries = 5;
|
| 355 | + int rc = -1;
|
| 356 | + while (--tries && rc)
|
| 357 | + {
|
| 358 | + rc = ata_rw_sectors(start, incount, inbuf, false);
|
| 359 | + if (rc) ata_soft_reset();
|
| 360 | + }
|
| 361 | + mutex_unlock(&ata_mutex);
|
| 362 | + return rc;
|
| 363 | +}
|
| 364 | +
|
| 365 | +int ata_write_sectors(IF_MD2(int drive,) unsigned long start, int count,
|
| 366 | + const void* outbuf)
|
| 367 | +{
|
| 368 | + mutex_lock(&ata_mutex, TIMEOUT_BLOCK);
|
| 369 | + int tries = 5;
|
| 370 | + int rc = -1;
|
| 371 | + while (--tries && rc)
|
| 372 | + {
|
| 373 | + rc = ata_rw_sectors(start, count, (void*)((uint32_t)outbuf), true);
|
| 374 | + if (rc) ata_soft_reset();
|
| 375 | + }
|
| 376 | + mutex_unlock(&ata_mutex);
|
| 377 | + return rc;
|
| 378 | +}
|
| 379 | +
|
| 380 | +void ata_spindown(int seconds) |
| 381 | +{ |
| 382 | + ata_sleep_timeout = seconds * 1000000; |
| 383 | +} |
| 384 | +
|
| 385 | +void ata_sleep(void)
|
| 386 | +{
|
| 387 | + call_storage_idle_notifys(false); |
| 388 | + mutex_lock(&ata_mutex, TIMEOUT_BLOCK);
|
| 389 | + ata_power_down();
|
| 390 | + mutex_unlock(&ata_mutex);
|
| 391 | +}
|
| 392 | +
|
| 393 | +void ata_sleepnow(void)
|
| 394 | +{
|
| 395 | + ata_sleep();
|
| 396 | +}
|
| 397 | +
|
| 398 | +void ata_close(void)
|
| 399 | +{
|
| 400 | + ata_sleep();
|
| 401 | +}
|
| 402 | +
|
| 403 | +void ata_spin(void)
|
| 404 | +{
|
| 405 | + ata_power_up();
|
| 406 | +}
|
| 407 | +
|
| 408 | +void ata_get_info(IF_MD2(int drive,) struct storage_info *info)
|
| 409 | +{
|
| 410 | + (*info).sector_size = SECTOR_SIZE;
|
| 411 | + (*info).num_sectors = ata_total_sectors;
|
| 412 | + (*info).vendor = "Apple";
|
| 413 | + (*info).product = "iPod Classic";
|
| 414 | + (*info).revision = "1.0";
|
| 415 | +}
|
| 416 | +
|
| 417 | +long ata_last_disk_activity(void)
|
| 418 | +{
|
| 419 | + return ata_last_activity_value;
|
| 420 | +}
|
| 421 | +
|
| 422 | +int ata_init(void)
|
| 423 | +{
|
| 424 | + mutex_init(&ata_mutex);
|
| 425 | + wakeup_init(&ata_wakeup);
|
| 426 | + PCON(7) = 0x44444444;
|
| 427 | + PCON(8) = 0x44444444;
|
| 428 | + PCON(9) = 0x44444444;
|
| 429 | + PCON(10) = (PCON(10) & ~0xffff) | 0x4444;
|
| 430 | + ata_powered = false;
|
| 431 | + ata_total_sectors = 0;
|
| 432 | + thread_create("ATA idle monitor", ata_thread, ata_stack,
|
| 433 | + sizeof(ata_stack), USER_THREAD, 1, true);
|
| 434 | + return 0;
|
| 435 | +}
|
| 436 | +
|
| 437 | +#ifdef CONFIG_STORAGE_MULTI
|
| 438 | +int ata_num_drives(int first_drive)
|
| 439 | +{
|
| 440 | + /* We don't care which logical drive number(s) we have been assigned */
|
| 441 | + (void)first_drive;
|
| 442 | +
|
| 443 | + return 1;
|
| 444 | +}
|
| 445 | +#endif
|
| 446 | +
|
| 447 | +void INT_ATA()
|
| 448 | +{
|
| 449 | + uint32_t ata_irq = ATA_IRQ;
|
| 450 | + ATA_IRQ = ata_irq;
|
| 451 | + if (ata_irq & ATA_IRQ_MASK) wakeup_signal(&ata_wakeup);
|
| 452 | + ATA_IRQ_MASK = 0;
|
| 453 | +}
|
Index: embios/trunk/target/ipodclassic/target.h |
— | — | @@ -60,12 +60,12 @@ |
61 | 61 |
|
62 | 62 | #define HAVE_BOOTFLASH
|
63 | 63 |
|
64 | | -//#define HAVE_STORAGE
|
65 | | -//#define HAVE_HDD_STORAGE
|
66 | | -//#define HAVE_STORAGE_FLUSH
|
67 | | -//#define HAVE_HOTSWAP
|
68 | | -//#define CONFIG_STORAGE STORAGE_ATA
|
69 | | -//#define SECTOR_SIZE 4096
|
| 64 | +#define HAVE_STORAGE
|
| 65 | +#define HAVE_HDD_STORAGE
|
| 66 | +#define HAVE_STORAGE_FLUSH
|
| 67 | +#define HAVE_HOTSWAP
|
| 68 | +#define CONFIG_STORAGE STORAGE_ATA
|
| 69 | +#define SECTOR_SIZE 4096
|
70 | 70 |
|
71 | 71 | //#define HAVE_TARGETINIT_LATE
|
72 | 72 |
|
Index: embios/trunk/storage_ata.h |
— | — | @@ -0,0 +1,54 @@ |
| 2 | +/***************************************************************************
|
| 3 | + * __________ __ ___.
|
| 4 | + * Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
| 5 | + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
| 6 | + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
| 7 | + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
| 8 | + * \/ \/ \/ \/ \/
|
| 9 | + * $Id$
|
| 10 | + *
|
| 11 | + * Copyright (C) 2002 by Alan Korr
|
| 12 | + * Copyright (C) 2008 by Frank Gevaerts
|
| 13 | + *
|
| 14 | + * This program is free software; you can redistribute it and/or
|
| 15 | + * modify it under the terms of the GNU General Public License
|
| 16 | + * as published by the Free Software Foundation; either version 2
|
| 17 | + * of the License, or (at your option) any later version.
|
| 18 | + *
|
| 19 | + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
| 20 | + * KIND, either express or implied.
|
| 21 | + *
|
| 22 | + ****************************************************************************/
|
| 23 | +#ifndef __STORAGE_ATA_H__
|
| 24 | +#define __STORAGE_ATA_H__
|
| 25 | +
|
| 26 | +#include "global.h"
|
| 27 | +#include "mv.h" /* for HAVE_MULTIDRIVE or not */
|
| 28 | +
|
| 29 | +struct storage_info;
|
| 30 | +
|
| 31 | +void ata_spindown(int seconds);
|
| 32 | +void ata_sleep(void);
|
| 33 | +void ata_sleepnow(void);
|
| 34 | +bool ata_disk_is_active(void);
|
| 35 | +int ata_soft_reset(void);
|
| 36 | +int ata_init(void);
|
| 37 | +void ata_close(void);
|
| 38 | +int ata_read_sectors(IF_MD2(int drive,) unsigned long start, int count, void* buf);
|
| 39 | +int ata_write_sectors(IF_MD2(int drive,) unsigned long start, int count, const void* buf);
|
| 40 | +#ifdef HAVE_STORAGE_FLUSH
|
| 41 | +int ata_flush(void);
|
| 42 | +#endif
|
| 43 | +void ata_spin(void);
|
| 44 | +
|
| 45 | +#ifdef STORAGE_GET_INFO
|
| 46 | +void ata_get_info(IF_MD2(int drive,) struct storage_info *info);
|
| 47 | +#endif
|
| 48 | +
|
| 49 | +long ata_last_disk_activity(void);
|
| 50 | +
|
| 51 | +#ifdef CONFIG_STORAGE_MULTI
|
| 52 | +int ata_num_drives(int first_drive);
|
| 53 | +#endif
|
| 54 | +
|
| 55 | +#endif |
\ No newline at end of file |
Index: embios/trunk/SOURCES |
— | — | @@ -51,6 +51,10 @@ |
52 | 52 | usb/synopsysotg.c
|
53 | 53 | #endif
|
54 | 54 |
|
| 55 | +#ifdef TARGET_ipodclassic
|
| 56 | +target/ipodclassic/storage_ata.c
|
| 57 | +#endif
|
| 58 | +
|
55 | 59 | #ifdef ARM_ARCH
|
56 | 60 | arm/arm-support.S
|
57 | 61 | arm/contextswitch.S
|