SD卡驱动之中断函数

来源:互联网 发布:暴风影音软件 编辑:程序博客网 时间:2024/06/05 11:42
 

static irqreturn_t s3cmci_irq(int irq, void *dev_id)
{
 struct s3cmci_host *host = dev_id;
 struct mmc_command *cmd;

//SDI命令状态寄存器,数据状态寄存器,FIFO状态寄存器,数据持续计数器寄存器,中断屏蔽寄存器。
 u32 mci_csta, mci_dsta, mci_fsta, mci_dcnt, mci_imsk;


 u32 mci_cclear = 0, mci_dclear;
 unsigned long iflags;

//获取数据状态寄存器和中断屏蔽寄存器的值

 mci_dsta = readl(host->base + S3C2410_SDIDSTA);
 mci_imsk = readl(host->base + host->sdiimsk);

 

 if (mci_dsta & S3C2410_SDIDSTA_SDIOIRQDETECT) {//如果发生了中断继续下一步
  if (mci_imsk & S3C2410_SDIIMSK_SDIOIRQ) {//IntDet 中断使能。

       mci_dclear = S3C2410_SDIDSTA_SDIOIRQDETECT;//清除中断发现的值
       writel(mci_dclear, host->base + S3C2410_SDIDSTA);

   mmc_signal_sdio_irq(host->mmc);//发现了SD后的相关程序
   return IRQ_HANDLED;
  }
 }

 spin_lock_irqsave(&host->complete_lock, iflags);//获取锁和中断状态

 mci_csta = readl(host->base + S3C2410_SDICMDSTAT);//获取命令状态状态寄存器
 mci_dcnt = readl(host->base + S3C2410_SDIDCNT);//获取数据持续计数寄存器
 mci_fsta = readl(host->base + S3C2410_SDIFSTA);//获取FIFO状态寄存器
 mci_dclear = 0;

 if ((host->complete_what == COMPLETION_NONE) ||
     (host->complete_what == COMPLETION_FINALIZE)) {
  host->status = "nothing to complete";//如果host->complete_what的值等于COMPLETION_NONE,COMPLETION_FINALIZE,说明还没传输等,然后中断标志,退出。
  clear_imask(host);
  goto irq_out;
 }

 if (!host->mrq) {//当前请求为空退出
  host->status = "no active mrq";
  clear_imask(host);
  goto irq_out;
 }

 cmd = host->cmd_is_stop ? host->mrq->stop : host->mrq->cmd;

 if (!cmd) {
  host->status = "no active cmd";
  clear_imask(host);
  goto irq_out;
 }

 if (!s3cmci_host_usedma(host)) {//假如设置使用PIO模式传输进入程序里面。
  if ((host->pio_active == XFER_WRITE) &&
      (mci_fsta & S3C2410_SDIFSTA_TFDET)) {

   disable_imask(host, S3C2410_SDIIMSK_TXFIFOHALF);
   tasklet_schedule(&host->pio_tasklet);
   host->status = "pio tx";
  }

  if ((host->pio_active == XFER_READ) &&
      (mci_fsta & S3C2410_SDIFSTA_RFDET)) {

   disable_imask(host,
          S3C2410_SDIIMSK_RXFIFOHALF |
          S3C2410_SDIIMSK_RXFIFOLAST);

   tasklet_schedule(&host->pio_tasklet);
   host->status = "pio rx";
  }
 }

 

 if (mci_csta & S3C2410_SDICMDSTAT_CMDTIMEOUT) {//命令超时
  dbg(host, dbg_err, "CMDSTAT: error CMDTIMEOUT\n");
  cmd->error = -ETIMEDOUT;
  host->status = "error: command timeout";
  goto fail_transfer;
 }

 if (mci_csta & S3C2410_SDICMDSTAT_CMDSENT) {//命令发送了
  if (host->complete_what == COMPLETION_CMDSENT) {
   host->status = "ok: command sent";
   goto close_transfer;
  }

  mci_cclear |= S3C2410_SDICMDSTAT_CMDSENT;
 }

 if (mci_csta & S3C2410_SDICMDSTAT_CRCFAIL) {//响应CRC失败
  if (cmd->flags & MMC_RSP_CRC) {
   if (host->mrq->cmd->flags & MMC_RSP_136) {
    dbg(host, dbg_irq,
        "fixup: ignore CRC fail with long rsp\n");
   } else {
    
   }
  }

  mci_cclear |= S3C2410_SDICMDSTAT_CRCFAIL;
 }

 if (mci_csta & S3C2410_SDICMDSTAT_RSPFIN) {//响应接受结束
  if (host->complete_what == COMPLETION_RSPFIN) {
   host->status = "ok: command response received";
   goto close_transfer;
  }

  if (host->complete_what == COMPLETION_XFERFINISH_RSPFIN)
   host->complete_what = COMPLETION_XFERFINISH;

  mci_cclear |= S3C2410_SDICMDSTAT_RSPFIN;
 }

 

 if (!cmd->data)
  goto clear_status_bits;

 

下面的是FIFO出错处理程序

 
 if (host->is2440) {//主机是2440下一步
  if (mci_fsta & S3C2440_SDIFSTA_FIFOFAIL) {//FIFO 失败错误,当FIFO 发生溢出/欠载(underrun)数据保存时FIFO失败错误。
   dbg(host, dbg_err, "FIFO failure\n");
   host->mrq->data->error = -EILSEQ;
   host->status = "error: 2440 fifo failure";
   goto fail_transfer;
  }
 } else {
  if (mci_dsta & S3C2410_SDIDSTA_FIFOFAIL) {
   dbg(host, dbg_err, "FIFO failure\n");
   cmd->data->error = -EILSEQ;
   host->status = "error:  fifo failure";
   goto fail_transfer;
  }
 }

 if (mci_dsta & S3C2410_SDIDSTA_RXCRCFAIL) {//数据接收CRC校验失败

  dbg(host, dbg_err, "bad data crc (outgoing)\n");
  cmd->data->error = -EILSEQ;
  host->status = "error: bad data crc (outgoing)";
  goto fail_transfer;
 }

 if (mci_dsta & S3C2410_SDIDSTA_CRCFAIL) { //CRC状态失败,当数据块发送时CRC状态错误(CRC 校验失败)。

 

  dbg(host, dbg_err, "bad data crc (incoming)\n");
  cmd->data->error = -EILSEQ;
  host->status = "error: bad data crc (incoming)";
  goto fail_transfer;
 }

 if (mci_dsta & S3C2410_SDIDSTA_DATATIMEOUT) { //数据接收超时

  dbg(host, dbg_err, "data timeout\n");
  cmd->data->error = -ETIMEDOUT;
  host->status = "error: data timeout";
  goto fail_transfer;
 }

 if (mci_dsta & S3C2410_SDIDSTA_XFERFINISH) {//数据传输结束
  if (host->complete_what == COMPLETION_XFERFINISH) {//
   host->status = "ok: data transfer completed";
   goto close_transfer;
  }

  if (host->complete_what == COMPLETION_XFERFINISH_RSPFIN)
   host->complete_what = COMPLETION_RSPFIN;

  mci_dclear |= S3C2410_SDIDSTA_XFERFINISH;
 }

clear_status_bits:
 writel(mci_cclear, host->base + S3C2410_SDICMDSTAT);
 writel(mci_dclear, host->base + S3C2410_SDIDSTA);

 goto irq_out;

fail_transfer:
 host->pio_active = XFER_NONE;

close_transfer:
 host->complete_what = COMPLETION_FINALIZE;

 clear_imask(host);
 tasklet_schedule(&host->pio_tasklet);

 goto irq_out;

irq_out:
 dbg(host, dbg_irq,
     "csta:0xx dsta:0xx fsta:0xx dcnt:0xx status:%s.\n",
     mci_csta, mci_dsta, mci_fsta, mci_dcnt, host->status);

 spin_unlock_irqrestore(&host->complete_lock, iflags);
 return IRQ_HANDLED;

}

原创粉丝点击