static void au1xmmc_send_pio(struct au1xmmc_host *host) { struct mmc_data *data = 0; int sg_len, max, count = 0; unsigned char *sg_ptr; u32 status = 0; struct scatterlist *sg; data = host->mrq->data; if (!(host->flags & HOST_F_XMIT)) return; /* This is the pointer to the data buffer */ sg = &data->sg[host->pio.index]; sg_ptr = page_address(sg->page) + sg->offset + host->pio.offset; /* This is the space left inside the buffer */ sg_len = data->sg[host->pio.index].length - host->pio.offset; /* Check to if we need less then the size of the sg_buffer */ max = (sg_len > host->pio.len) ? host->pio.len : sg_len; if (max > AU1XMMC_MAX_TRANSFER) max = AU1XMMC_MAX_TRANSFER; for(count = 0; count < max; count++ ) { unsigned char val; status = au_readl(HOST_STATUS(host)); if (!(status & SD_STATUS_TH)) break; val = *sg_ptr++; au_writel((unsigned long) val, HOST_TXPORT(host)); au_sync(); } host->pio.len -= count; host->pio.offset += count; if (count == sg_len) { host->pio.index++; host->pio.offset = 0; } if (host->pio.len == 0) { IRQ_OFF(host, SD_CONFIG_TH); if (host->flags & HOST_F_STOP) SEND_STOP(host); tasklet_schedule(&host->data_task); } }
static void pmpmci_data_complete(struct pmpmci_host *host, unsigned int status) { struct mmc_request *mrq = host->mrq; struct sd_data_s *sd_data= host->platdata; struct mmc_data *data; unsigned int crc; int timeout = 100000; #if 1 //printk("\n%s,%s():%d, enter host stutus=0x%x.", __FILE__, __FUNCTION__, __LINE__, host->status ); /*WARN_ON((host->status != HOST_S_DATA) && (host->status != HOST_S_STOP));*/ while ((host->status != HOST_S_DATA_SEND) && (host->status != HOST_S_STOP) && timeout > 0) { timeout--; //tasklet_schedule(&host->data_task); } if(timeout <= 0) { printk("\nSD CMD not complete, dma interrupt run, wait timeout!!"); return; } #endif if (host->mrq == NULL) return; data = mrq->cmd->data; data->error = 0; dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len, host->dma.dir); //sync_cache(); /* Process any errors */ crc = (status & SD_MMC_S_DATA_CRCERR); if (crc) data->error = -EILSEQ; /* Clear the CRC bits */ sd_data->ops->clearStatus(&(sd_data->info),SD_MMC_S_DATA_CRCERR); data->bytes_xfered = 0; host->flags &= ~(HOST_F_XMIT | HOST_F_RECV); if (!data->error) { if (host->flags & HOST_F_DMA) { data->bytes_xfered = host->dma.totalxfer; } else data->bytes_xfered = (data->blocks * data->blksz) - host->pio.len; } sd_data->ops->stopTxCmd(&(sd_data->info)); if (host->flags & HOST_F_STOP) { SEND_STOP(host); printk("\n%s(),%d.", __FUNCTION__, __LINE__); return; } pmpmci_finish_request(host); //printk("\n%s(),%d.", __FUNCTION__, __LINE__); }
static void au1xmmc_send_pio(struct au1xmmc_host *host) { struct mmc_data *data; int sg_len, max, count; unsigned char *sg_ptr, val; u32 status; struct scatterlist *sg; data = host->mrq->data; if (!(host->flags & HOST_F_XMIT)) return; sg = &data->sg[host->pio.index]; sg_ptr = sg_virt(sg) + host->pio.offset; sg_len = data->sg[host->pio.index].length - host->pio.offset; max = (sg_len > host->pio.len) ? host->pio.len : sg_len; if (max > AU1XMMC_MAX_TRANSFER) max = AU1XMMC_MAX_TRANSFER; for (count = 0; count < max; count++) { status = au_readl(HOST_STATUS(host)); if (!(status & SD_STATUS_TH)) break; val = *sg_ptr++; au_writel((unsigned long)val, HOST_TXPORT(host)); au_sync(); } host->pio.len -= count; host->pio.offset += count; if (count == sg_len) { host->pio.index++; host->pio.offset = 0; } if (host->pio.len == 0) { IRQ_OFF(host, SD_CONFIG_TH); if (host->flags & HOST_F_STOP) SEND_STOP(host); tasklet_schedule(&host->data_task); } }
static void au1xmmc_receive_pio(struct au1xmmc_host *host) { struct mmc_data *data; int max, count, sg_len = 0; unsigned char *sg_ptr = NULL; u32 status, val; struct scatterlist *sg; data = host->mrq->data; if (!(host->flags & HOST_F_RECV)) return; max = host->pio.len; if (host->pio.index < host->dma.len) { sg = &data->sg[host->pio.index]; sg_ptr = sg_virt(sg) + host->pio.offset; /* This is the space left inside the buffer */ sg_len = sg_dma_len(&data->sg[host->pio.index]) - host->pio.offset; /* Check if we need less than the size of the sg_buffer */ if (sg_len < max) max = sg_len; } if (max > AU1XMMC_MAX_TRANSFER) max = AU1XMMC_MAX_TRANSFER; for (count = 0; count < max; count++) { status = au_readl(HOST_STATUS(host)); if (!(status & SD_STATUS_NE)) break; if (status & SD_STATUS_RC) { DBG("RX CRC Error [%d + %d].\n", host->pdev->id, host->pio.len, count); break; } if (status & SD_STATUS_RO) { DBG("RX Overrun [%d + %d]\n", host->pdev->id, host->pio.len, count); break; } else if (status & SD_STATUS_RU) { DBG("RX Underrun [%d + %d]\n", host->pdev->id, host->pio.len, count); break; } val = au_readl(HOST_RXPORT(host)); if (sg_ptr) *sg_ptr++ = (unsigned char)(val & 0xFF); } host->pio.len -= count; host->pio.offset += count; if (sg_len && count == sg_len) { host->pio.index++; host->pio.offset = 0; } if (host->pio.len == 0) { /* IRQ_OFF(host, SD_CONFIG_RA | SD_CONFIG_RF); */ IRQ_OFF(host, SD_CONFIG_NE); if (host->flags & HOST_F_STOP) SEND_STOP(host); tasklet_schedule(&host->data_task); } }