Subversion Repositories freemyipod

Rev

Rev 429 | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 429 Rev 430
Line 40... Line 40...
40
static uint32_t ata_stack[0x80] STACK_ATTR;
40
static uint32_t ata_stack[0x80] STACK_ATTR;
41
static bool ata_powered;
41
static bool ata_powered;
42
 
42
 
43
#ifdef ATA_HAVE_BBT
43
#ifdef ATA_HAVE_BBT
44
#include "panic.h"
44
#include "panic.h"
45
uint16_t ata_bbt[ATA_BBT_PAGES][0x20];
45
uint16_t (*ata_bbt)[0x20];
46
uint64_t ata_virtual_sectors;
46
uint64_t ata_virtual_sectors;
47
uint32_t ata_last_offset;
47
uint32_t ata_last_offset;
48
uint64_t ata_last_phys;
48
uint64_t ata_last_phys;
49
 
49
 
50
void ata_bbt_read_sectors(uint32_t sector, uint32_t count, void* buffer)
50
void ata_bbt_read_sectors(uint32_t sector, uint32_t count, void* buffer)
Line 335... Line 335...
335
 
335
 
336
int ata_rw_sectors(uint64_t sector, uint32_t count, void* buffer, bool write)
336
int ata_rw_sectors(uint64_t sector, uint32_t count, void* buffer, bool write)
337
{
337
{
338
#ifdef ATA_HAVE_BBT
338
#ifdef ATA_HAVE_BBT
339
    if (sector + count > ata_virtual_sectors) RET_ERR(0);
339
    if (sector + count > ata_virtual_sectors) RET_ERR(0);
340
    while (count)
340
    if (ata_bbt)
341
    {
-
 
342
        uint32_t offset;
341
        while (count)
343
        uint32_t l0idx = sector >> 15;
-
 
344
        uint32_t l0offs = sector & 0x7fff;
-
 
345
        uint32_t cnt = MIN(count, 0x8000 - l0offs);
-
 
346
        uint32_t l0data = ata_bbt[0][l0idx << 1];
-
 
347
        uint32_t base = ata_bbt[0][(l0idx << 1) | 1] << 12;
-
 
348
        if (l0data < 0x8000) offset = l0data + base;
-
 
349
        else
-
 
350
        {
342
        {
-
 
343
            uint32_t offset;
351
            uint32_t l1idx = (sector >> 10) & 0x1f;
344
            uint32_t l0idx = sector >> 15;
352
            uint32_t l1offs = sector & 0x3ff;
345
            uint32_t l0offs = sector & 0x7fff;
353
            cnt = MIN(count, 0x400 - l1offs);
346
            uint32_t cnt = MIN(count, 0x8000 - l0offs);
354
            uint32_t l1data = ata_bbt[l0data & 0x7fff][l1idx];
347
            uint32_t l0data = ata_bbt[0][l0idx << 1];
-
 
348
            uint32_t base = ata_bbt[0][(l0idx << 1) | 1] << 12;
355
            if (l1data < 0x8000) offset = l1data + base;
349
            if (l0data < 0x8000) offset = l0data + base;
356
            else
350
            else
357
            {
351
            {
358
                uint32_t l2idx = (sector >> 5) & 0x1f;
352
                uint32_t l1idx = (sector >> 10) & 0x1f;
359
                uint32_t l2offs = sector & 0x1f;
353
                uint32_t l1offs = sector & 0x3ff;
360
                cnt = MIN(count, 0x20 - l2offs);
354
                cnt = MIN(count, 0x400 - l1offs);
361
                uint32_t l2data = ata_bbt[l1data & 0x7fff][l2idx];
355
                uint32_t l1data = ata_bbt[l0data & 0x7fff][l1idx];
362
                if (l2data < 0x8000) offset = l2data + base;
356
                if (l1data < 0x8000) offset = l1data + base;
363
                else
357
                else
364
                {
358
                {
-
 
359
                    uint32_t l2idx = (sector >> 5) & 0x1f;
-
 
360
                    uint32_t l2offs = sector & 0x1f;
-
 
361
                    cnt = MIN(count, 0x20 - l2offs);
-
 
362
                    uint32_t l2data = ata_bbt[l1data & 0x7fff][l2idx];
-
 
363
                    if (l2data < 0x8000) offset = l2data + base;
-
 
364
                    else
-
 
365
                    {
365
                    uint32_t l3idx = sector & 0x1f;
366
                        uint32_t l3idx = sector & 0x1f;
366
                    uint32_t l3data = ata_bbt[l2data & 0x7fff][l3idx];
367
                        uint32_t l3data = ata_bbt[l2data & 0x7fff][l3idx];
367
                    for (cnt = 1; cnt < count && l3idx + cnt < 0x20; cnt++)
368
                        for (cnt = 1; cnt < count && l3idx + cnt < 0x20; cnt++)
368
                        if (ata_bbt[l2data & 0x7fff][l3idx + cnt] != l3data)
369
                            if (ata_bbt[l2data & 0x7fff][l3idx + cnt] != l3data)
369
                            break;
370
                                break;
370
                    offset = l3data + base;
371
                        offset = l3data + base;
-
 
372
                    }
371
                }
373
                }
372
            }
374
            }
-
 
375
            uint64_t phys = sector + offset;
-
 
376
            if (offset != ata_last_offset && phys - ata_last_phys < 64) ata_soft_reset();
-
 
377
            ata_last_offset = offset;
-
 
378
            ata_last_phys = phys + cnt;
-
 
379
            PASS_RC(ata_rw_sectors_internal(phys, cnt, buffer, write), 0, 0);
-
 
380
            buffer += cnt * SECTOR_SIZE;
-
 
381
            sector += cnt;
-
 
382
            count -= cnt;
373
        }
383
        }
374
        uint64_t phys = sector + offset;
-
 
375
        if (offset != ata_last_offset && phys - ata_last_phys < 64) ata_soft_reset();
-
 
376
        ata_last_offset = offset;
-
 
377
        ata_last_phys = phys + cnt;
-
 
378
        PASS_RC(ata_rw_sectors_internal(phys, cnt, buffer, write), 0, 0);
384
    else PASS_RC(ata_rw_sectors_internal(sector, count, buffer, write), 0, 0);
379
        buffer += cnt * SECTOR_SIZE;
-
 
380
        sector += cnt;
-
 
381
        count -= cnt;
-
 
382
    }
-
 
383
    return 0;
385
    return 0;
384
}
386
}
385
 
387
 
386
int ata_rw_sectors_internal(uint64_t sector, uint32_t count, void* buffer, bool write)
388
int ata_rw_sectors_internal(uint64_t sector, uint32_t count, void* buffer, bool write)
387
{
389
{
Line 527... Line 529...
527
    PCON(10) = (PCON(10) & ~0xffff) | 0x4444;
529
    PCON(10) = (PCON(10) & ~0xffff) | 0x4444;
528
    ata_powered = false;
530
    ata_powered = false;
529
    ata_total_sectors = 0;
531
    ata_total_sectors = 0;
530
#ifdef ATA_HAVE_BBT
532
#ifdef ATA_HAVE_BBT
531
    mutex_lock(&ata_mutex, TIMEOUT_BLOCK);
533
    mutex_lock(&ata_mutex, TIMEOUT_BLOCK);
532
    memset(ata_bbt, 0, sizeof(ata_bbt));
534
    ata_bbt = NULL;
533
    ata_power_up();
535
    ata_power_up();
534
    uint32_t* buf = (uint32_t*)(ata_bbt[ARRAYLEN(ata_bbt) - 64]);
536
    uint32_t* buf = (uint32_t*)memalign(0x10, 0x1000);
-
 
537
    if (buf)
-
 
538
    {
535
    ata_bbt_read_sectors(0, 1, buf);
539
        ata_bbt_read_sectors(0, 1, buf);
536
    if (!memcmp(buf, "emBIbbth", 8))
540
        if (!memcmp(buf, "emBIbbth", 8))
537
    {
541
        {
538
        ata_virtual_sectors = (((uint64_t)buf[0x1fd]) << 32) | buf[0x1fc];
542
            ata_virtual_sectors = (((uint64_t)buf[0x1fd]) << 32) | buf[0x1fc];
539
        uint32_t count = buf[0x1ff];
543
            uint32_t count = buf[0x1ff];
540
        if (count > (ATA_BBT_PAGES >> 6))
-
 
541
            panicf(PANIC_KILLTHREAD, "ATA: BBT too big! (%d pages, limit: %d)\n", count << 6, ATA_BBT_PAGES);
544
            ata_bbt = (typeof(ata_bbt))memalign(0x10, 0x1000 * count);
542
        uint32_t i;
545
            uint32_t i;
543
        uint32_t cnt;
546
            uint32_t cnt;
544
        for (i = 0; i < count; i += cnt)
547
            for (i = 0; i < count; i += cnt)
545
        {
548
            {
546
            uint32_t phys = buf[0x200 + i];
549
                uint32_t phys = buf[0x200 + i];
547
            for (cnt = 1; cnt < count; cnt++)
550
                for (cnt = 1; cnt < count; cnt++)
548
                if (buf[0x200 + i + cnt] != phys + cnt)
551
                    if (buf[0x200 + i + cnt] != phys + cnt)
549
                    break;
552
                        break;
550
            ata_bbt_read_sectors(phys, cnt, ata_bbt[i << 6]);
553
                ata_bbt_read_sectors(phys, cnt, ata_bbt[i << 6]);
-
 
554
            }
551
        }
555
        }
-
 
556
        else ata_virtual_sectors = ata_total_sectors;
-
 
557
        free(buf);
552
    }
558
    }
553
    else ata_virtual_sectors = ata_total_sectors;
-
 
554
    mutex_unlock(&ata_mutex);
559
    mutex_unlock(&ata_mutex);
555
#endif
560
#endif
556
    thread_create(&ata_thread_handle, "ATA idle monitor", ata_thread, ata_stack,
561
    thread_create(&ata_thread_handle, "ATA idle monitor", ata_thread, ata_stack,
557
                  sizeof(ata_stack), USER_THREAD, 1, true);
562
                  sizeof(ata_stack), USER_THREAD, 1, true);
558
    return 0;
563
    return 0;