void INT_SD(void)
{
    const int status = SD_INT;

    SD_INT = 0; /* disable sd interrupts, clear pending interrupts */

    /* cmd and response status pending */
    if(status & CMD_RES_STAT)
    {
        /* get the status */
        cmd_error = SD_CMDRES;
        semaphore_release(&command_completion_signal);
    }

    /* data transfer status pending */
    if(status & DATA_XFER_STAT)
    {
        cmd_error = SD_DATAT;
        if (cmd_error & DATA_XFER_ERR)
            retry = true;

        semaphore_release(&transfer_completion_signal);
    }

    SD_INT |= CMD_RES_INT_EN | DATA_XFER_INT_EN;
}

static bool send_cmd(const int cmd, const int arg, const int res,
        unsigned long *response)
{
    //int card_no;

    //if ((flags & MCI_ACMD) && /* send SD_APP_CMD first */
    //    !send_cmd(drive, SD_APP_CMD, card_info[drive].rca, RES_R1, response))
    //    return false;

    SD_CMD = arg;

    if (res > 0)
       SD_CMDREST = CMD_XFER_START | RES_XFER_START | res | cmd;
    else
       SD_CMDREST = CMD_XFER_START | RES_XFER_END | RES_R1 | cmd;

    semaphore_wait(&command_completion_signal, TIMEOUT_BLOCK);

    /*  Handle command responses & errors */
    if(res != RES_NO)
    {
        if(cmd_error & STAT_CMD_RES_ERR)
            return false;

        if(res == RES_R2)
        {
            response[0] = SD_RES3;
            response[1] = SD_RES2;
            response[2] = SD_RES1;
            response[3] = SD_RES0;
        }
        else
            response[0] = SD_RES3;
    }
    return true;
}

static int sd_wait_for_tran_state(void)
{
    unsigned long response;
    unsigned int timeout = current_tick + 5*HZ;
    int cmd_retry = 10;
    int i = 0;

    while (1)
    {
        while (!send_cmd(SD_SEND_STATUS, card_info.rca, RES_R1,
                         &response) && cmd_retry > 0)
        {
            printf("SD_SEND_STATUS retry");
            cmd_retry--;
        }
printf ("sd_wait_for_tran: 0x%0x, %d", ((response >> 9) & 0xf), i++);
        if (cmd_retry <= 0)
        {
            printf("error SD_SEND_STATUS: 0x%0x", cmd_error);
            return -1;
        }

        if (((response >> 9) & 0xf) == SD_TRAN)
            return 0;

        if(TIME_AFTER(current_tick, timeout))
            return -10 * ((response >> 9) & 0xf);

        //last_disk_activity = current_tick;
    }
}

void main(void)
{

    _backlight_init();


    system_init();
    kernel_init();
    enable_irq();

    lcd_init_device();
    _backlight_on();
    font_init();
    lcd_setfont(FONT_SYSFIXED);

    long init_timeout, response;
    bool sd_v2 = false;
    int i;

    SCU_RSTCFG |= (1<<9);
    sleep(1);
    SCU_RSTCFG &= ~(1<<9);

    SCU_IOMUXA_CON |= IOMUX_SD;

    INTC_IMR |= (1<<10); //SD
    INTC_IECR |= (1<<10);

    SD_CTRL = SD_PWR_CPU | SD_DETECT_MECH | SD_CLOCK_EN | 0x7C;
    SD_INT = CMD_RES_INT_EN | DATA_XFER_INT_EN;
    SD_CARD = SD_CARD_SELECT | SD_CARD_PWR_EN;

   if(!send_cmd(SD_GO_IDLE_STATE, 0, RES_NO, NULL))
       printf("error SD_GO_IDLE_STATE");

   sleep(1);

    if(send_cmd(SD_SEND_IF_COND, 0x1AA, RES_R6, &response))
    {
        if((response & 0xFFF) == 0x1AA)
        {
        printf("response: 0x%x", response);

            sd_v2 = true;
        }
    }
    init_timeout = current_tick + HZ;

    do {
        /* this timeout is the only valid error for this loop*/
        if(TIME_AFTER(current_tick, init_timeout))
            printf("timeout");
        if(!send_cmd(SD_APP_CMD, card_info.rca, RES_R1, &response))
            printf("error SD_APP_CMD");

        sleep(1); /* bus conflict otherwise */

         /* ACMD41 For v2 cards set HCS bit[30] & send host voltage range to all */
        if(!send_cmd(SD_APP_OP_COND, (0x00FF8000 | (sd_v2 ? 1<<30 : 0)),
                     RES_R3, &card_info.ocr))
        {
            printf("error ACMD41: 0x%0x", cmd_error);
            break;
        }
    } while(!(card_info.ocr & (1<<31)) );

    if(!send_cmd(SD_ALL_SEND_CID, 0, RES_R2, card_info.cid))
        printf("error SD_ALL_SEND_CID: 0x%0x", cmd_error);

    if(!send_cmd(SD_SEND_RELATIVE_ADDR, 0, RES_R6, &card_info.rca))
        printf("error SD_SEND_RELATIVE_ADDR: 0x%0x", cmd_error);

    /*  Card back to full speed  25MHz*/
    SD_CTRL = (SD_CTRL & ~0x7FF) | 1;
        /* CMD9 send CSD */
    if(!send_cmd(SD_SEND_CSD, card_info.rca,
                 RES_R2, card_info.csd))
        printf("error SD_SEND_CSD: 0x%0x", cmd_error);

    sd_parse_csd(&card_info);

    card_info.initialized = 1;

    const int csd_version = card_extract_bits(card_info.csd, 127, 2);

    printf("CSD%d.0 numblocks:%ld speed:%ld", csd_version+1, card_info.numblocks, card_info.speed);
    printf("nsac: %d taac: %ld r2w: %d", card_info.nsac, card_info.taac, card_info.r2w_factor);

// Sdmmc_send_cmd(MMC_SELECT_CARD, SdmmcCardRca)) CMD7
    if(!send_cmd(SD_SELECT_CARD, card_info.rca, RES_R1, &response))
        printf("error SD_SELECT_CARD: 0x%0x", cmd_error);

    printf("SD_SELECT: 0x%0x, stat: 0x%0x", response, cmd_error);

    send_cmd(SD_SEND_STATUS, card_info.rca, RES_R1, &response);

    printf("SD_STATUS: 0x%0x", response);
// Sdmmc_send_cmd(MMC_SET_BLOCKLEN, 512))
    if(!send_cmd(SD_SET_BLOCKLEN, 512, RES_R1, &response))
        printf("error SD_SET_BLOCKLEN: 0x%0x", cmd_error);

// Sdmmc_send_cmd(MMC_APP_CMD, SdmmcCardRca)
    if(!send_cmd(SD_APP_CMD, card_info.rca, RES_R1, &response))
        printf("error 2SD_APP_CMD: 0x%0x", cmd_error);

// Sdmmc_send_cmd(SD_APP_SET_BUS_WIDTH, SD_BUS_WIDTH_1) SD_BUS_WIDTH_1 = 0
    if(!send_cmd(SD_SET_BUS_WIDTH, card_info.rca, RES_R1, &response))
        printf("error SD_SET_BUS_WIDTH: 0x%0x", cmd_error);

    printf("SD initialization end");

    MMU_PNRI = 0x1ff;
    MMU_PNRII = 0x1ff;
    MMU_CTRL = MMU_MMU0_BUFII | MMU_CPU_BUFI | MMU_BUFII_RESET | MMU_BUFII_BYTE | MMU_BUFI_RESET | MMU_BUFI_WORD;

    SD_DATAT = DATA_XFER_START | DATA_XFER_READ | DATA_BUS_1LINE | DATA_XFER_DMA_DIS | DATA_XFER_SINGLE;


    printf("sd_wait_for_tran_state");
    i = sd_wait_for_tran_state();
    printf("sd_wait_for_tran_state end");

    if (i <0)
        printf("error waiting for tran state: %d", i);

    // Sdmmc_send_cmd(MMC_READ_MULTIPLE_BLOCK, LBA))
    if (!send_cmd(SD_READ_MULTIPLE_BLOCK, 0, RES_R1, &response))
        printf("error SD_READ_MULTIPLE_BLOCK: 0x%0x", cmd_error);

    printf("semafore_wait");
    semaphore_wait(&transfer_completion_signal, TIMEOUT_BLOCK);
    printf("semafore_wait end");

    if (!send_cmd(SD_STOP_TRANSMISSION, 0, RES_R1, &response))
        printf("error SD_STOP_TRANSMISSION: 0x%0x", cmd_error);

    for (i=0; i<16; i++)
    {
        printf("%d: 0x%0x", i, MMU_DATA);
    }

while(1);
}