Beispiel #1
0
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);
		}
	}
}
Beispiel #2
0
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);
}