⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 am53c974.c

📁 GNU Mach 微内核源代码, 基于美国卡内基美隆大学的 Mach 研究项目
💻 C
📖 第 1 页 / 共 5 页
字号:
* Purpose : interrupt handler                                           **                                                                       ** Inputs : irq - interrupt line, regs - ?                               **                                                                       ** Returns : nothing                                                     *************************************************************************/static void AM53C974_intr(int irq, void *dev_id, struct pt_regs *regs){AM53C974_local_declare(); struct Scsi_Host         *instance;struct AM53C974_hostdata *hostdata;unsigned char            cmdreg, dmastatus, statreg, isreg, instreg, cfifo;/* find AM53C974 hostadapter responsible for this interrupt */for (instance = first_instance; instance; instance = instance->next)    if ((instance->irq == irq) && (instance->hostt == the_template)) goto FOUND;sti();return;/* found; now decode and process */FOUND:hostdata = (struct AM53C974_hostdata *)instance->hostdata;AM53C974_setio(instance);dmastatus = AM53C974_read_8(DMASTATUS);DEB_INTR(printk(SEPARATOR_LINE));DEB_INTR(printk("AM53C974 interrupt; dmastatus=0x%02x\n", dmastatus));KEYWAIT();/*** DMA related interrupts ***/if (hostdata->connected && (dmastatus & (DMASTATUS_ERROR | DMASTATUS_PWDN |                                          DMASTATUS_ABORT))) {   /* DMA error or POWERDOWN */   printk("scsi%d: DMA error or powerdown; dmastatus: 0x%02x\n",          instance->host_no, dmastatus);#ifdef AM53C974_DEBUG   deb_stop = 1;#endif   panic("scsi%d: cannot recover\n", instance->host_no); }if (hostdata->connected && (dmastatus & DMASTATUS_DONE)) {        /* DMA transfer done */   unsigned long residual;   cli();   if (!(AM53C974_read_8(DMACMD) & DMACMD_DIR)) {      do {         dmastatus = AM53C974_read_8(DMASTATUS);         residual  = AM53C974_read_8(CTCLREG) | (AM53C974_read_8(CTCMREG) << 8) |                    (AM53C974_read_8(CTCHREG) << 16);         residual += AM53C974_read_8(CFIREG) & CFIREG_CF;         } while (!(dmastatus & DMASTATUS_SCSIINT) && residual);      residual = AM53C974_read_8(CTCLREG) | (AM53C974_read_8(CTCMREG) << 8) |                 (AM53C974_read_8(CTCHREG) << 16);      residual += AM53C974_read_8(CFIREG) & CFIREG_CF;      }     else      residual = 0;   hostdata->connected->SCp.ptr += hostdata->connected->SCp.this_residual - residual;   hostdata->connected->SCp.this_residual = residual;   AM53C974_write_8(DMACMD, DMACMD_IDLE);   /* if service request missed before, process it now (ugly) */   if (hostdata->dma_busy) {      hostdata->dma_busy = 0;      cmdreg = AM53C974_read_8(CMDREG);      statreg = AM53C974_read_8(STATREG);      isreg = AM53C974_read_8(ISREG);      instreg = AM53C974_read_8(INSTREG);      cfifo = AM53C974_cfifo();      AM53C974_information_transfer(instance, statreg, isreg, instreg, cfifo,                                    dmastatus); }   sti();   }   if (!(dmastatus & DMASTATUS_SCSIINT)) {   sti();   return; }/*** SCSI related interrupts ***/cmdreg = AM53C974_read_8(CMDREG);statreg = AM53C974_read_8(STATREG);isreg = AM53C974_read_8(ISREG);instreg = AM53C974_read_8(INSTREG);cfifo = AM53C974_cfifo();DEB_INTR(printk("scsi%d: statreg: 0x%02x; isreg: 0x%02x; instreg: 0x%02x; cfifo: 0x%02x\n",                instance->host_no, statreg, isreg, instreg, cfifo));if (statreg & STATREG_PE) {   /* parity error */#ifdef AM53C974_DEBUG   deb_stop = 1;#endif   printk("scsi%d : PARITY error\n", instance->host_no);   if (hostdata->connected) hostdata->sync_off[hostdata->connected->target] = 0; /* setup asynchronous transfer */   hostdata->aborted = 1; }if (statreg & STATREG_IOE) {   /* illegal operation error */#ifdef AM53C974_DEBUG   deb_stop = 1;#endif   printk("scsi%d : ILLEGAL OPERATION error\n", instance->host_no);   printk("cmdreg:  0x%02x; dmacmd:  0x%02x; statreg: 0x%02x; \n"          "isreg:   0x%02x; instreg: 0x%02x; cfifo:   0x%02x\n",           cmdreg, AM53C974_read_8(DMACMD), statreg, isreg, instreg, cfifo); }if (hostdata->in_reset && (instreg & INSTREG_SRST)) {   /* RESET INTERRUPT */#ifdef AM53C974_DEBUG   deb_stop = 1;#endif   DEB(printk("Bus reset interrupt received\n"));   AM53C974_intr_bus_reset(instance);   cli();   if (hostdata->connected) {      hostdata->connected->result = DID_RESET << 16;      hostdata->connected->scsi_done((Scsi_Cmnd *)hostdata->connected);      hostdata->connected = NULL; }     else {       if (hostdata->sel_cmd) {         hostdata->sel_cmd->result = DID_RESET << 16;         hostdata->sel_cmd->scsi_done((Scsi_Cmnd *)hostdata->sel_cmd);         hostdata->sel_cmd = NULL; }      }   sti();   if (hostdata->in_reset == 1) goto EXIT;     else return;   }if (instreg & INSTREG_ICMD) {   /* INVALID COMMAND INTERRUPT */#ifdef AM53C974_DEBUG   deb_stop = 1;#endif   printk("scsi%d: Invalid command interrupt\n", instance->host_no);   printk("cmdreg:  0x%02x; dmacmd:  0x%02x; statreg: 0x%02x; dmastatus: 0x%02x; \n"          "isreg:   0x%02x; instreg: 0x%02x; cfifo:   0x%02x\n",           cmdreg, AM53C974_read_8(DMACMD), statreg, dmastatus, isreg, instreg, cfifo);   panic("scsi%d: cannot recover\n", instance->host_no); }if (instreg & INSTREG_DIS) {   /* DISCONNECT INTERRUPT */   DEB_INTR(printk("Disconnect interrupt received; "));   cli();   AM53C974_intr_disconnect(instance);   sti();   goto EXIT; }if (instreg & INSTREG_RESEL) {   /* RESELECTION INTERRUPT */   DEB_INTR(printk("Reselection interrupt received\n"));   cli();   AM53C974_intr_reselect(instance, statreg);   sti();   goto EXIT; }if (instreg & INSTREG_SO) {   DEB_INTR(printk("Successful operation interrupt received\n"));   if (hostdata->selecting) {      DEB_INTR(printk("DSR completed, starting select\n"));      cli();      AM53C974_select(instance, (Scsi_Cmnd *)hostdata->sel_cmd,                          (hostdata->sel_cmd->cmnd[0] == REQUEST_SENSE) ?                                                   TAG_NONE : TAG_NEXT);      hostdata->selecting = 0;      AM53C974_set_sync(instance, hostdata->sel_cmd->target);      sti();      return; }   if (hostdata->sel_cmd != NULL) {      if ( ((isreg & ISREG_IS) != ISREG_OK_NO_STOP) &&           ((isreg & ISREG_IS) != ISREG_OK_STOP) ) {         /* UNSUCCESSFUL SELECTION */         DEB_INTR(printk("unsuccessful selection\n"));         cli();         hostdata->dma_busy = 0;	 LIST(hostdata->sel_cmd, hostdata->issue_queue);	 hostdata->sel_cmd->host_scribble = (unsigned char *)hostdata->issue_queue;         hostdata->issue_queue = hostdata->sel_cmd;         hostdata->sel_cmd = NULL;         hostdata->selecting = 0;         sti();         goto EXIT; }        else {         /* SUCCESSFUL SELECTION */         DEB(printk("successful selection; cmd=0x%02lx\n", (long)hostdata->sel_cmd));         cli();         hostdata->dma_busy = 0;         hostdata->disconnecting = 0;         hostdata->connected = hostdata->sel_cmd;         hostdata->sel_cmd = NULL;         hostdata->selecting = 0;#ifdef SCSI2         if (!hostdata->connected->device->tagged_queue)#endif                hostdata->busy[hostdata->connected->target] |= (1 << hostdata->connected->lun);         /* very strange -- use_sg is sometimes nonzero for request sense commands !! */         if ((hostdata->connected->cmnd[0] == REQUEST_SENSE) && hostdata->connected->use_sg) {            DEB(printk("scsi%d: REQUEST_SENSE command with nonzero use_sg\n", instance->host_no));            KEYWAIT();            hostdata->connected->use_sg = 0; }         initialize_SCp((Scsi_Cmnd *)hostdata->connected);         hostdata->connected->SCp.phase = PHASE_CMDOUT;         AM53C974_information_transfer(instance, statreg, isreg, instreg, cfifo, dmastatus);         sti();         return; }      }     else {      cli();      AM53C974_information_transfer(instance, statreg, isreg, instreg, cfifo, dmastatus);      sti();      return; }   }    if (instreg & INSTREG_SR) {   DEB_INTR(printk("Service request interrupt received, "));   if (hostdata->connected) {      DEB_INTR(printk("calling information_transfer\n"));      cli();      AM53C974_information_transfer(instance, statreg, isreg, instreg, cfifo, dmastatus);      sti(); }     else {      printk("scsi%d: weird: service request when no command connected\n", instance->host_no);      AM53C974_write_8(CMDREG, CMDREG_CFIFO); }   /* clear FIFO */   return;   }EXIT:  DEB_INTR(printk("intr: starting main\n"));  run_main();  DEB_INTR(printk("end of intr\n"));}/************************************************************************** * Function : AM53C974_intr_disconnect(struct Scsi_Host *instance)** Purpose : manage target disconnection** Inputs : instance -- which AM53C974* * Returns : nothing**************************************************************************/static void AM53C974_intr_disconnect(struct Scsi_Host *instance) {AM53C974_local_declare(); struct AM53C974_hostdata *hostdata = (struct AM53C974_hostdata *)instance->hostdata;Scsi_Cmnd                *cmd;AM53C974_setio(instance);if (hostdata->sel_cmd != NULL) {   /* normal selection timeout, typical for nonexisting targets */   cmd = (Scsi_Cmnd *)hostdata->sel_cmd;   DEB_INTR(printk("bad target\n"));   cmd->result = DID_BAD_TARGET << 16;   goto EXIT_FINISHED; }if (!hostdata->connected) {   /* can happen if controller was reset, a device tried to reconnect,      failed and disconnects now */   AM53C974_write_8(CMDREG, CMDREG_CFIFO);   return; }if (hostdata->disconnecting) {   /* target sent disconnect message, so we are prepared */   cmd = (Scsi_Cmnd *)hostdata->connected;   AM53C974_set_async(instance, cmd->target);   DEB_INTR(printk("scsi%d : disc. from cmnd %d for ta %d, lun %d\n",   	           instance->host_no, cmd->cmnd[0], cmd->target, cmd->lun));   if (cmd->device->disconnect) {      /* target wants to reselect later */      DEB_INTR(printk("ok, re-enabling selection\n"));      LIST(cmd,hostdata->disconnected_queue);      cmd->host_scribble = (unsigned char *)hostdata->disconnected_queue;      hostdata->disconnected_queue = cmd;      DEB_QUEUE(printk("scsi%d : command for target %d lun %d this %d was moved from connected to"   	               "  the disconnected_queue\n", instance->host_no, cmd->target,                        cmd->lun, hostdata->disconnected_queue->SCp.this_residual));      DEB_QUEUE(AM53C974_print_queues(instance));      goto EXIT_UNFINISHED; }     else {      /* target does not want to reselect later, we are really finished */#ifdef AM53C974_DEBUG      if (cmd->cmnd[0] == REQUEST_SENSE) {        int i;        printk("Request sense data dump:\n");        for (i = 0; i < cmd->request_bufflen; i++) {             printk("%02x ", *((char *)(cmd->request_buffer) + i));             if (i && !(i % 16)) printk("\n"); }        printk("\n"); }#endif      goto EXIT_FINISHED; } /* !cmd->device->disconnect */   } /* if (hostdata->disconnecting) *//* no disconnect message received; unexpected disconnection */cmd = (Scsi_Cmnd *)hostdata->connected;if (cmd) {#ifdef AM53C974_DEBUG   deb_stop = 1;#endif   AM53C974_set_async(instance, cmd->target);   printk("scsi%d: Unexpected disconnect; phase: %d; target: %d; this_residual: %d; buffers_residual: %d; message: %d\n",           instance->host_no, cmd->SCp.phase, cmd->target, cmd->SCp.this_residual, cmd->SCp.buffers_residual,           cmd->SCp.Message);   printk("cmdreg: 0x%02x; statreg: 0x%02x; isreg: 0x%02x; cfifo: 0x%02x\n",          AM53C974_read_8(CMDREG), AM53C974_read_8(STATREG), AM53C974_read_8(ISREG),           AM53C974_read_8(CFIREG) & CFIREG_CF);    if ((hostdata->last_message[0] == EXTENDED_MESSAGE) &&         (hostdata->last_message[2] == EXTENDED_SDTR)) {        /* sync. negotiation was aborted, setup asynchronous transfer with target */        hostdata->sync_off[cmd->target] = 0; }   if (hostdata->aborted || hostdata->msgout[0] == ABORT)      cmd->result = DID_ABORT << 16;     else      cmd->result = DID_ERROR << 16;   goto EXIT_FINISHED; }EXIT_FINISHED:hostdata->aborted = 0;hostdata->msgout[0] = NOP;hostdata->sel_cmd = NULL;hostdata->connected = NULL;hostdata->selecting = 0;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -