示例#1
0
static int
at91_mci_request(device_t brdev, device_t reqdev, struct mmc_request *req)
{
	struct at91_mci_softc *sc = device_get_softc(brdev);

	AT91_MCI_LOCK(sc);
	if (sc->req != NULL) {
		AT91_MCI_UNLOCK(sc);
		return (EBUSY);
	}
	//printf("new req\n");
	sc->req = req;
	sc->flags = PENDING_CMD;
	if (sc->req->stop)
		sc->flags |= PENDING_STOP;
	at91_mci_next_operation(sc);
	AT91_MCI_UNLOCK(sc);
	return (0);
}
示例#2
0
static int
at91_mci_release_host(device_t brdev, device_t reqdev)
{
	struct at91_mci_softc *sc = device_get_softc(brdev);

	AT91_MCI_LOCK(sc);
	sc->bus_busy--;
	wakeup(sc);
	AT91_MCI_UNLOCK(sc);
	return (0);
}
示例#3
0
static int
at91_mci_acquire_host(device_t brdev, device_t reqdev)
{
	struct at91_mci_softc *sc = device_get_softc(brdev);
	int err = 0;

	AT91_MCI_LOCK(sc);
	while (sc->bus_busy)
		msleep(sc, &sc->sc_mtx, PZERO, "mciah", hz / 5);
	sc->bus_busy++;
	AT91_MCI_UNLOCK(sc);
	return (err);
}
示例#4
0
static void
at91_mci_intr(void *arg)
{
	struct at91_mci_softc *sc = (struct at91_mci_softc*)arg;
	struct mmc_command *cmd = sc->curcmd;
	uint32_t sr, isr;

	AT91_MCI_LOCK(sc);

	sr = RD4(sc, MCI_SR);
	isr = sr & RD4(sc, MCI_IMR);

	if (mci_debug)
		printf("i 0x%x sr 0x%x\n", isr, sr);

	/*
	 * All interrupts are one-shot; disable it now.
	 * The next operation will re-enable whatever interrupts it wants.
	 */
	WR4(sc, MCI_IDR, isr);
	if (isr & MCI_SR_ERROR) {
		if (isr & (MCI_SR_RTOE | MCI_SR_DTOE))
			cmd->error = MMC_ERR_TIMEOUT;
		else if (isr & (MCI_SR_RCRCE | MCI_SR_DCRCE))
			cmd->error = MMC_ERR_BADCRC;
		else if (isr & (MCI_SR_OVRE | MCI_SR_UNRE))
			cmd->error = MMC_ERR_FIFO;
		else
			cmd->error = MMC_ERR_FAILED;
		/*
		 * CMD8 is used to probe for SDHC cards, a standard SD card
		 * will get a response timeout; don't report it because it's a
		 * normal and expected condition.  One might argue that all
		 * error reporting should be left to higher levels, but when
		 * they report at all it's always EIO, which isn't very
		 * helpful. XXX bootverbose?
		 */
		if (cmd->opcode != 8) {
			device_printf(sc->dev,
			    "IO error; status MCI_SR = 0x%x cmd opcode = %d%s\n",
			    sr, cmd->opcode,
			    (cmd->opcode != 12) ? "" :
			    (sc->flags & CMD_MULTIREAD) ? " after read" : " after write");
			at91_mci_reset(sc);
		}
		at91_mci_next_operation(sc);
	} else {
		if (isr & MCI_SR_TXBUFE) {
//			printf("TXBUFE\n");
			/*
			 * We need to wait for a BLKE that follows TXBUFE
			 * (intermediate BLKEs might happen after ENDTXes if
			 * we're chaining multiple buffers).  If BLKE is also
			 * asserted at the time we get TXBUFE, we can avoid
			 * another interrupt and process it right away, below.
			 */
			if (sr & MCI_SR_BLKE)
				isr |= MCI_SR_BLKE;
			else
				WR4(sc, MCI_IER, MCI_SR_BLKE);
		}
		if (isr & MCI_SR_RXBUFF) {
//			printf("RXBUFF\n");
		}
		if (isr & MCI_SR_ENDTX) {
//			printf("ENDTX\n");
		}
		if (isr & MCI_SR_ENDRX) {
//			printf("ENDRX\n");
			at91_mci_read_done(sc, sr);
		}
		if (isr & MCI_SR_NOTBUSY) {
//			printf("NOTBUSY\n");
			at91_mci_notbusy(sc);
		}
		if (isr & MCI_SR_DTIP) {
//			printf("Data transfer in progress\n");
		}
		if (isr & MCI_SR_BLKE) {
//			printf("Block transfer end\n");
			at91_mci_write_done(sc, sr);
		}
		if (isr & MCI_SR_TXRDY) {
//			printf("Ready to transmit\n");
		}
		if (isr & MCI_SR_RXRDY) {
//			printf("Ready to receive\n");
		}
		if (isr & MCI_SR_CMDRDY) {
//			printf("Command ready\n");
			at91_mci_cmdrdy(sc, sr);
		}
	}
	AT91_MCI_UNLOCK(sc);
}