freemyipod r301 - Code Review

Jump to: navigation, search
Repository:freemyipod
Revision:r300‎ | r301 | r302 >
Date:19:24, 1 December 2010
Author:theseven
Status:new
Tags:
Comment:
emBIOS: iPod Classic hard disk driver
Modified paths:
  • /embios/trunk/SOURCES (modified) (history)
  • /embios/trunk/storage_ata.h (added) (history)
  • /embios/trunk/target/ipodclassic/storage_ata.c (added) (history)
  • /embios/trunk/target/ipodclassic/target.h (modified) (history)
  • /embios/trunk/target/ipodnano3g/interrupt.c (modified) (history)
  • /embios/trunk/target/ipodnano3g/s5l8702.h (modified) (history)

Diff [purge]

Index: embios/trunk/target/ipodnano3g/s5l8702.h
@@ -533,6 +533,41 @@
534534 #define LCDWDATA (*((uint32_t volatile*)(0x38300040)))
535535
536536
 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+
537572 /////CLOCK GATES/////
538573 #define CLOCKGATE_USB_1 2
539574 #define CLOCKGATE_USB_2 35
@@ -544,6 +579,7 @@
545580 #define IRQ_DMAC(d) 16 + d
546581 #define IRQ_DMAC0 16
547582 #define IRQ_DMAC1 17
 583+#define IRQ_ATA 29
548584
549585
550586 #endif
Index: embios/trunk/target/ipodnano3g/interrupt.c
@@ -78,7 +78,7 @@
7979 default_interrupt(INT_IRQ26);
8080 default_interrupt(INT_IRQ27);
8181 default_interrupt(INT_IRQ28);
82 -default_interrupt(INT_IRQ29);
 82+default_interrupt(INT_ATA);
8383 default_interrupt(INT_IRQ30);
8484 default_interrupt(INT_IRQ31);
8585 default_interrupt(INT_IRQ32);
@@ -179,7 +179,7 @@
180180 INT_IRQ0,INT_IRQ1,INT_IRQ2,INT_IRQ3,INT_IRQ4,INT_IRQ5,INT_IRQ6,INT_IRQ7,
181181 INT_TIMER,INT_IRQ9,INT_IRQ10,INT_IRQ11,INT_IRQ12,INT_IRQ13,INT_IRQ14,INT_IRQ15,
182182 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,
184184 INT_IRQ32,INT_IRQ33,INT_IRQ34,INT_IRQ35,INT_IRQ36,INT_IRQ37,INT_IRQ38,INT_IRQ39,
185185 INT_IRQ40,INT_IRQ41,INT_IRQ42,INT_IRQ43,INT_IRQ55,INT_IRQ56,INT_IRQ57,INT_IRQ58,
186186 INT_IRQ48,INT_IRQ49,INT_IRQ50,INT_IRQ51,INT_IRQ52,INT_IRQ53,INT_IRQ54,INT_IRQ55,
@@ -231,6 +231,9 @@
232232 VIC0INTENABLE = 1 << IRQ_TIMER;
233233 VIC0INTENABLE = 1 << IRQ_DMAC0;
234234 VIC0INTENABLE = 1 << IRQ_DMAC1;
 235+#ifdef TARGET_ipodclassic
 236+ VIC0INTENABLE = 1 << IRQ_ATA;
 237+#endif
235238 }
236239
237240 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 @@
6161
6262 #define HAVE_BOOTFLASH
6363
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
7070
7171 //#define HAVE_TARGETINIT_LATE
7272
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 @@
5252 usb/synopsysotg.c
5353 #endif
5454
 55+#ifdef TARGET_ipodclassic
 56+target/ipodclassic/storage_ata.c
 57+#endif
 58+
5559 #ifdef ARM_ARCH
5660 arm/arm-support.S
5761 arm/contextswitch.S