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);
}