Index: embios/trunk/target/ipodclassic/storage_ata.c |
— | — | @@ -38,7 +38,23 @@ |
39 | 39 | static uint32_t ata_stack[0x80];
|
40 | 40 | static bool ata_powered;
|
41 | 41 |
|
| 42 | +#ifdef ATA_HAVE_BBT
|
| 43 | +#include "panic.h"
|
| 44 | +uint16_t ata_bbt[ATA_BBT_PAGES][0x20];
|
| 45 | +uint32_t ata_virtual_sectors;
|
42 | 46 |
|
| 47 | +int ata_rw_sectors_internal(uint64_t sector, uint32_t count, void* buffer, bool write);
|
| 48 | +
|
| 49 | +void ata_bbt_read_sectors(uint32_t sector, uint32_t count, void* buffer)
|
| 50 | +{
|
| 51 | + int rc = ata_rw_sectors_internal(sector, count, buffer, false);
|
| 52 | + if (IS_ERR(rc))
|
| 53 | + panicf(PANIC_KILLTHREAD, "ATA: Error %08X while reading BBT (sector %d, count %d)\n",
|
| 54 | + rc, sector, count);
|
| 55 | +}
|
| 56 | +#endif
|
| 57 | +
|
| 58 | +
|
43 | 59 | static uint16_t ata_read_cbr(uint32_t volatile* reg)
|
44 | 60 | {
|
45 | 61 | while (!(ATA_PIO_READY & 2)) yield();
|
— | — | @@ -159,6 +175,7 @@ |
160 | 176 | | (((uint64_t)ata_identify_data[102]) << 32)
|
161 | 177 | | (((uint64_t)ata_identify_data[103]) << 48);
|
162 | 178 | else ata_total_sectors = ata_identify_data[60] | (((uint32_t)ata_identify_data[61]) << 16);
|
| 179 | + ata_total_sectors >>= 3;
|
163 | 180 | if (ata_identify_data[53] & BIT(1))
|
164 | 181 | {
|
165 | 182 | if (ata_identify_data[64] & BIT(1)) piotime = 0x2072;
|
— | — | @@ -209,8 +226,8 @@ |
210 | 227 | }
|
211 | 228 | ata_dma = param ? true : false;
|
212 | 229 | PASS_RC(ata_set_feature(0xef, param), 2, 1);
|
213 | | - if (ata_identify_data[82] & BIT(5)) PASS_RC(ata_set_feature(2, 0), 2, 2);
|
214 | | - if (ata_identify_data[82] & BIT(6)) PASS_RC(ata_set_feature(0x55, 0), 2, 3);
|
| 230 | + if (ata_identify_data[82] & BIT(5)) PASS_RC(ata_set_feature(0x82, 0), 2, 2);
|
| 231 | + if (ata_identify_data[82] & BIT(6)) PASS_RC(ata_set_feature(0xaa, 0), 2, 3);
|
215 | 232 | ATA_PIO_TIME = piotime;
|
216 | 233 | ATA_MDMA_TIME = mdmatime;
|
217 | 234 | ATA_UDMA_TIME = udmatime;
|
— | — | @@ -235,6 +252,53 @@ |
236 | 253 |
|
237 | 254 | int ata_rw_sectors(uint64_t sector, uint32_t count, void* buffer, bool write)
|
238 | 255 | {
|
| 256 | +#ifdef ATA_HAVE_BBT
|
| 257 | + if (sector + count > ata_virtual_sectors) RET_ERR(0);
|
| 258 | + while (count)
|
| 259 | + {
|
| 260 | + uint32_t l0idx = sector >> 15;
|
| 261 | + uint32_t l0offs = sector & 0x7fff;
|
| 262 | + uint32_t cnt = MIN(count, 0x8000 - l0offs);
|
| 263 | + uint32_t l0data = ata_bbt[0][l0idx << 1];
|
| 264 | + uint32_t base = ata_bbt[0][(l0idx << 1) | 1] << 12;
|
| 265 | + uint32_t phys;
|
| 266 | + if (l0data < 0x8000) phys = sector + l0data + base;
|
| 267 | + else
|
| 268 | + {
|
| 269 | + uint32_t l1idx = (sector >> 10) & 0x1f;
|
| 270 | + uint32_t l1offs = sector & 0x3ff;
|
| 271 | + cnt = MIN(count, 0x400 - l1offs);
|
| 272 | + uint32_t l1data = ata_bbt[l0data & 0x7fff][l1idx];
|
| 273 | + if (l1data < 0x8000) phys = sector + l1data + base;
|
| 274 | + else
|
| 275 | + {
|
| 276 | + uint32_t l2idx = (sector >> 5) & 0x1f;
|
| 277 | + uint32_t l2offs = sector & 0x1f;
|
| 278 | + cnt = MIN(count, 0x20 - l2offs);
|
| 279 | + uint32_t l2data = ata_bbt[l1data & 0x7fff][l2idx];
|
| 280 | + if (l2data < 0x8000) phys = sector + l2data + base;
|
| 281 | + else
|
| 282 | + {
|
| 283 | + uint32_t l3idx = sector & 0x1f;
|
| 284 | + phys = ata_bbt[l2data & 0x7fff][l3idx];
|
| 285 | + for (cnt = 1; cnt < count && l3idx + cnt < 0x20; cnt++)
|
| 286 | + if (ata_bbt[l2data & 0x7fff][l3idx + cnt] != phys)
|
| 287 | + break;
|
| 288 | + phys += sector + base;
|
| 289 | + }
|
| 290 | + }
|
| 291 | + }
|
| 292 | + PASS_RC(ata_rw_sectors_internal(phys, cnt, buffer, write), 0, 0);
|
| 293 | + buffer += cnt * SECTOR_SIZE;
|
| 294 | + sector += cnt;
|
| 295 | + count -= cnt;
|
| 296 | + }
|
| 297 | + return 0;
|
| 298 | +}
|
| 299 | +
|
| 300 | +int ata_rw_sectors_internal(uint64_t sector, uint32_t count, void* buffer, bool write)
|
| 301 | +{
|
| 302 | +#endif
|
239 | 303 | if (sector + count > ata_total_sectors) RET_ERR(0);
|
240 | 304 | if (!ata_powered) ata_power_up();
|
241 | 305 | ata_set_active();
|
— | — | @@ -244,7 +308,7 @@ |
245 | 309 | while (count)
|
246 | 310 | {
|
247 | 311 | uint32_t cnt = MIN(ata_lba48 ? 8192 : 32, count);
|
248 | | - PASS_RC(ata_wait_for_rdy(100000), 2, 0);
|
| 312 | + PASS_RC(ata_wait_for_rdy(100000), 2, 1);
|
249 | 313 | ata_write_cbr(&ATA_PIO_DVR, 0);
|
250 | 314 | if (ata_lba48)
|
251 | 315 | {
|
— | — | @@ -274,7 +338,7 @@ |
275 | 339 | count -= cnt;
|
276 | 340 | if (ata_dma)
|
277 | 341 | {
|
278 | | - PASS_RC(ata_wait_for_start_of_transfer(10000000), 2, 1);
|
| 342 | + PASS_RC(ata_wait_for_start_of_transfer(1500000), 2, 2);
|
279 | 343 | if (write)
|
280 | 344 | {
|
281 | 345 | ATA_SBUF_START = buffer;
|
— | — | @@ -294,11 +358,11 @@ |
295 | 359 | ATA_IRQ = BITRANGE(0, 4);
|
296 | 360 | ATA_IRQ_MASK = BIT(0);
|
297 | 361 | ATA_COMMAND = BIT(0);
|
298 | | - if (wakeup_wait(&ata_wakeup, 10000000) == THREAD_TIMEOUT)
|
| 362 | + if (wakeup_wait(&ata_wakeup, 1500000) == THREAD_TIMEOUT)
|
299 | 363 | {
|
300 | 364 | ATA_COMMAND = BIT(1);
|
301 | 365 | ATA_CFG &= ~(BITRANGE(2, 3) | BIT(12));
|
302 | | - RET_ERR(2);
|
| 366 | + RET_ERR(3);
|
303 | 367 | }
|
304 | 368 | ATA_COMMAND = BIT(1);
|
305 | 369 | ATA_CFG &= ~(BITRANGE(2, 3) | BIT(12));
|
— | — | @@ -310,7 +374,7 @@ |
311 | 375 | while (cnt--)
|
312 | 376 | {
|
313 | 377 | int i;
|
314 | | - PASS_RC(ata_wait_for_start_of_transfer(10000000), 2, 1);
|
| 378 | + PASS_RC(ata_wait_for_start_of_transfer(1500000), 2, 2);
|
315 | 379 | if (write)
|
316 | 380 | for (i = 0; i < 256; i++)
|
317 | 381 | ata_write_cbr(&ATA_PIO_DTR, ((uint16_t*)buffer)[i]);
|
— | — | @@ -356,9 +420,9 @@ |
357 | 421 | void* inbuf)
|
358 | 422 | {
|
359 | 423 | mutex_lock(&ata_mutex, TIMEOUT_BLOCK);
|
360 | | - int tries = 3;
|
| 424 | + int tries = 1;
|
361 | 425 | int rc = -1;
|
362 | | - while (--tries && rc)
|
| 426 | + while (tries-- && rc)
|
363 | 427 | {
|
364 | 428 | rc = ata_rw_sectors(start, incount, inbuf, false);
|
365 | 429 | if (rc) ata_soft_reset();
|
— | — | @@ -371,9 +435,9 @@ |
372 | 436 | const void* outbuf)
|
373 | 437 | {
|
374 | 438 | mutex_lock(&ata_mutex, TIMEOUT_BLOCK);
|
375 | | - int tries = 3;
|
| 439 | + int tries = 1;
|
376 | 440 | int rc = -1;
|
377 | | - while (--tries && rc)
|
| 441 | + while (tries-- && rc)
|
378 | 442 | {
|
379 | 443 | rc = ata_rw_sectors(start, count, (void*)((uint32_t)outbuf), true);
|
380 | 444 | if (rc) ata_soft_reset();
|
— | — | @@ -389,7 +453,6 @@ |
390 | 454 |
|
391 | 455 | void ata_sleep(void)
|
392 | 456 | {
|
393 | | - call_storage_idle_notifys(false); |
394 | 457 | mutex_lock(&ata_mutex, TIMEOUT_BLOCK);
|
395 | 458 | ata_power_down();
|
396 | 459 | mutex_unlock(&ata_mutex);
|
— | — | @@ -413,7 +476,11 @@ |
414 | 477 | void ata_get_info(IF_MD2(int drive,) struct storage_info *info)
|
415 | 478 | {
|
416 | 479 | (*info).sector_size = SECTOR_SIZE;
|
| 480 | +#ifdef ATA_HAVE_BBT
|
| 481 | + (*info).num_sectors = ata_virtual_sectors;
|
| 482 | +#else
|
417 | 483 | (*info).num_sectors = ata_total_sectors;
|
| 484 | +#endif
|
418 | 485 | (*info).vendor = "Apple";
|
419 | 486 | (*info).product = "iPod Classic";
|
420 | 487 | (*info).revision = "1.0";
|
— | — | @@ -434,6 +501,32 @@ |
435 | 502 | PCON(10) = (PCON(10) & ~0xffff) | 0x4444;
|
436 | 503 | ata_powered = false;
|
437 | 504 | ata_total_sectors = 0;
|
| 505 | +#ifdef ATA_HAVE_BBT
|
| 506 | + mutex_lock(&ata_mutex, TIMEOUT_BLOCK);
|
| 507 | + memset(ata_bbt, 0, sizeof(ata_bbt));
|
| 508 | + ata_power_up();
|
| 509 | + uint32_t* buf = (uint32_t*)(ata_bbt[ARRAYLEN(ata_bbt) - 64]);
|
| 510 | + ata_bbt_read_sectors(0, 1, buf);
|
| 511 | + if (!memcmp(buf, "emBIbbth", 8))
|
| 512 | + {
|
| 513 | + ata_virtual_sectors = buf[0x1fe];
|
| 514 | + uint32_t count = buf[0x1ff];
|
| 515 | + if (count > (ATA_BBT_PAGES >> 6))
|
| 516 | + panicf(PANIC_KILLTHREAD, "ATA: BBT too big!\n");
|
| 517 | + uint32_t i;
|
| 518 | + uint32_t cnt;
|
| 519 | + for (i = 0; i < count; i += cnt)
|
| 520 | + {
|
| 521 | + uint32_t phys = buf[0x200 + i];
|
| 522 | + for (cnt = 1; cnt < count; cnt++)
|
| 523 | + if (buf[0x200 + i + cnt] != phys + cnt)
|
| 524 | + break;
|
| 525 | + ata_bbt_read_sectors(phys, cnt, ata_bbt[i << 6]);
|
| 526 | + }
|
| 527 | + }
|
| 528 | + else ata_virtual_sectors = ata_total_sectors;
|
| 529 | + mutex_unlock(&ata_mutex);
|
| 530 | +#endif
|
438 | 531 | thread_create("ATA idle monitor", ata_thread, ata_stack,
|
439 | 532 | sizeof(ata_stack), USER_THREAD, 1, true);
|
440 | 533 | return 0;
|