static void wbsd_send_command(struct wbsd_host *host, struct mmc_command *cmd) { int i; u8 status, isr; /* * Clear accumulated ISR. The interrupt routine * will fill this one with events that occur during * transfer. */ host->isr = 0; /* * Send the command (CRC calculated by host). */ outb(cmd->opcode, host->base + WBSD_CMDR); for (i = 3; i >= 0; i--) outb((cmd->arg >> (i * 8)) & 0xff, host->base + WBSD_CMDR); cmd->error = 0; /* * Wait for the request to complete. */ do { status = wbsd_read_index(host, WBSD_IDX_STATUS); } while (status & WBSD_CARDTRAFFIC); /* * Do we expect a reply? */ if (cmd->flags & MMC_RSP_PRESENT) { /* * Read back status. */ isr = host->isr; /* Card removed? */ if (isr & WBSD_INT_CARD) cmd->error = -ENOMEDIUM; /* Timeout? */ else if (isr & WBSD_INT_TIMEOUT) cmd->error = -ETIMEDOUT; /* CRC? */ else if ((cmd->flags & MMC_RSP_CRC) && (isr & WBSD_INT_CRC)) cmd->error = -EILSEQ; /* All ok */ else { if (cmd->flags & MMC_RSP_136) wbsd_get_long_reply(host, cmd); else wbsd_get_short_reply(host, cmd); } } }
static void wbsd_send_command(struct wbsd_host* host, struct mmc_command* cmd) { int i; u8 status, eir, isr; DBGF("Sending cmd (%x)\n", cmd->opcode); /* * Disable interrupts as the interrupt routine * will destroy the contents of ISR. */ eir = inb(host->base + WBSD_EIR); outb(0, host->base + WBSD_EIR); /* * Send the command (CRC calculated by host). */ outb(cmd->opcode, host->base + WBSD_CMDR); for (i = 3;i >= 0;i--) outb((cmd->arg >> (i * 8)) & 0xff, host->base + WBSD_CMDR); cmd->error = MMC_ERR_NONE; /* * Wait for the request to complete. */ do { status = wbsd_read_index(host, WBSD_IDX_STATUS); } while (status & WBSD_CARDTRAFFIC); /* * Do we expect a reply? */ if ((cmd->flags & MMC_RSP_MASK) != MMC_RSP_NONE) { /* * Read back status. */ isr = inb(host->base + WBSD_ISR); /* Card removed? */ if (isr & WBSD_INT_CARD) cmd->error = MMC_ERR_TIMEOUT; /* Timeout? */ else if (isr & WBSD_INT_TIMEOUT) cmd->error = MMC_ERR_TIMEOUT; /* CRC? */ else if ((cmd->flags & MMC_RSP_CRC) && (isr & WBSD_INT_CRC)) cmd->error = MMC_ERR_BADCRC; /* All ok */ else { if ((cmd->flags & MMC_RSP_MASK) == MMC_RSP_SHORT) wbsd_get_short_reply(host, cmd); else wbsd_get_long_reply(host, cmd); } } /* * Restore interrupt mask to previous value. */ outb(eir, host->base + WBSD_EIR); /* * Call the interrupt routine to jump start * interrupts. */ wbsd_irq(0, host, NULL); DBGF("Sent cmd (%x), res %d\n", cmd->opcode, cmd->error); }