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

📄 wd33c93.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 5 页
字号:
      case CSR_DISC:/* Make sure that reselection is enabled at this point - it may * have been turned off for the command that just completed. */         write_wd33c93(regs, WD_SOURCE_ID, SRCID_ER);DB(DB_INTR,printk("DISC-%ld",cmd->pid))         if (cmd == NULL) {            printk(" - Already disconnected! ");            hostdata->state = S_UNCONNECTED;            }         switch (hostdata->state) {            case S_PRE_CMP_DISC:               hostdata->connected = NULL;               hostdata->busy[cmd->target] &= ~(1 << cmd->lun);               hostdata->state = S_UNCONNECTED;DB(DB_INTR,printk(":%d",cmd->SCp.Status))               if (cmd->cmnd[0] == REQUEST_SENSE && cmd->SCp.Status != GOOD)                  cmd->result = (cmd->result & 0x00ffff) | (DID_ERROR << 16);               else                  cmd->result = cmd->SCp.Status | (cmd->SCp.Message << 8);               cmd->scsi_done(cmd);          restore_flags(flags);               break;            case S_PRE_TMP_DISC:            case S_RUNNING_LEVEL2:               cmd->host_scribble = (uchar *)hostdata->disconnected_Q;               hostdata->disconnected_Q = cmd;               hostdata->connected = NULL;               hostdata->state = S_UNCONNECTED;#ifdef PROC_STATISTICS               hostdata->disc_done_cnt[cmd->target]++;#endif               break;            default:               printk("*** Unexpected DISCONNECT interrupt! ***");               hostdata->state = S_UNCONNECTED;            }/* We are no longer connected to a target - check to see if * there are commands waiting to be executed. */         wd33c93_execute(instance);         break;      case CSR_RESEL_AM:      case CSR_RESEL:DB(DB_INTR,printk("RESEL%s", sr == CSR_RESEL_AM ? "_AM" : ""))   /* Old chips (pre -A ???) don't have advanced features and will    * generate CSR_RESEL.  In that case we have to extract the LUN the    * hard way (see below).    * First we have to make sure this reselection didn't    * happen during Arbitration/Selection of some other device.    * If yes, put losing command back on top of input_Q.    */         if (hostdata->level2 <= L2_NONE) {            if (hostdata->selecting) {               cmd = (Scsi_Cmnd *)hostdata->selecting;               hostdata->selecting = NULL;               hostdata->busy[cmd->target] &= ~(1 << cmd->lun);               cmd->host_scribble = (uchar *)hostdata->input_Q;               hostdata->input_Q = cmd;               }            }         else {            if (cmd) {               if (phs == 0x00) {                  hostdata->busy[cmd->target] &= ~(1 << cmd->lun);                  cmd->host_scribble = (uchar *)hostdata->input_Q;                  hostdata->input_Q = cmd;                  }               else {                  printk("---%02x:%02x:%02x-TROUBLE: Intrusive ReSelect!---",asr,sr,phs);                  while (1)                     printk("\r");                  }               }            }   /* OK - find out which device reselected us. */         id = read_wd33c93(regs, WD_SOURCE_ID);         id &= SRCID_MASK;   /* and extract the lun from the ID message. (Note that we don't    * bother to check for a valid message here - I guess this is    * not the right way to go, but...)    */         if (sr == CSR_RESEL_AM) {            lun = read_wd33c93(regs, WD_DATA);            if (hostdata->level2 < L2_RESELECT)               write_wd33c93_cmd(regs, WD_CMD_NEGATE_ACK);            lun &= 7;         }         else {            /* Old chip; wait for msgin phase to pick up the LUN. */            for (lun = 255; lun; lun--) {               if ((asr = READ_AUX_STAT()) & ASR_INT)                  break;               udelay(10);            }            if (!(asr & ASR_INT)) {               printk("wd33c93: Reselected without IDENTIFY\n");               lun = 0;            }            else {               /* Verify this is a change to MSG_IN and read the message */               sr = read_wd33c93(regs, WD_SCSI_STATUS);               if (sr == (CSR_ABORT   | PHS_MESS_IN) ||                   sr == (CSR_UNEXP   | PHS_MESS_IN) ||                   sr == (CSR_SRV_REQ | PHS_MESS_IN)) {                  /* Got MSG_IN, grab target LUN */                  lun = read_1_byte(regs);                  /* Now we expect a 'paused with ACK asserted' int.. */                  asr = READ_AUX_STAT();                  if (!(asr & ASR_INT)) {                     udelay(10);                     asr = READ_AUX_STAT();                     if (!(asr & ASR_INT))                        printk("wd33c93: No int after LUN on RESEL (%02x)\n",                              asr);                  }                  sr = read_wd33c93(regs, WD_SCSI_STATUS);                  if (sr != CSR_MSGIN)                     printk("wd33c93: Not paused with ACK on RESEL (%02x)\n",                           sr);                  lun &= 7;                  write_wd33c93_cmd(regs, WD_CMD_NEGATE_ACK);               }               else {                  printk("wd33c93: Not MSG_IN on reselect (%02x)\n", sr);                  lun = 0;               }            }         }   /* Now we look for the command that's reconnecting. */         cmd = (Scsi_Cmnd *)hostdata->disconnected_Q;         patch = NULL;         while (cmd) {            if (id == cmd->target && lun == cmd->lun)               break;            patch = cmd;            cmd = (Scsi_Cmnd *)cmd->host_scribble;            }   /* Hmm. Couldn't find a valid command.... What to do? */         if (!cmd) {            printk("---TROUBLE: target %d.%d not in disconnect queue---",id,lun);            return;            }   /* Ok, found the command - now start it up again. */         if (patch)            patch->host_scribble = cmd->host_scribble;         else            hostdata->disconnected_Q = (Scsi_Cmnd *)cmd->host_scribble;         hostdata->connected = cmd;   /* We don't need to worry about 'initialize_SCp()' or 'hostdata->busy[]'    * because these things are preserved over a disconnect.    * But we DO need to fix the DPD bit so it's correct for this command.    */         if (is_dir_out(cmd))            write_wd33c93(regs, WD_DESTINATION_ID, cmd->target);         else            write_wd33c93(regs, WD_DESTINATION_ID, cmd->target | DSTID_DPD);         if (hostdata->level2 >= L2_RESELECT) {            write_wd33c93_count(regs, 0);  /* we want a DATA_PHASE interrupt */            write_wd33c93(regs, WD_COMMAND_PHASE, 0x45);            write_wd33c93_cmd(regs, WD_CMD_SEL_ATN_XFER);            hostdata->state = S_RUNNING_LEVEL2;            }         else            hostdata->state = S_CONNECTED;DB(DB_INTR,printk("-%ld",cmd->pid))         break;               default:         printk("--UNKNOWN INTERRUPT:%02x:%02x:%02x--",asr,sr,phs);      }DB(DB_INTR,printk("} "))}static void reset_wd33c93(struct Scsi_Host *instance){struct WD33C93_hostdata *hostdata = (struct WD33C93_hostdata *)instance->hostdata;const wd33c93_regs regs = hostdata->regs;uchar sr;   write_wd33c93(regs, WD_OWN_ID, OWNID_EAF | OWNID_RAF |                 instance->this_id | hostdata->clock_freq);   write_wd33c93(regs, WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_POLLED);   write_wd33c93(regs, WD_SYNCHRONOUS_TRANSFER,                 calc_sync_xfer(hostdata->default_sx_per/4,DEFAULT_SX_OFF));   write_wd33c93(regs, WD_COMMAND, WD_CMD_RESET);#ifdef CONFIG_MVME147_SCSI   udelay(25); /* The old wd33c93 on MVME147 needs this, at least */#endif   while (!(READ_AUX_STAT() & ASR_INT))      ;   sr = read_wd33c93(regs, WD_SCSI_STATUS);   hostdata->microcode = read_wd33c93(regs, WD_CDB_1);   if (sr == 0x00)      hostdata->chip = C_WD33C93;   else if (sr == 0x01) {      write_wd33c93(regs, WD_QUEUE_TAG, 0xa5);  /* any random number */      sr = read_wd33c93(regs, WD_QUEUE_TAG);      if (sr == 0xa5) {         hostdata->chip = C_WD33C93B;         write_wd33c93(regs, WD_QUEUE_TAG, 0);         }      else         hostdata->chip = C_WD33C93A;      }   else      hostdata->chip = C_UNKNOWN_CHIP;   write_wd33c93(regs, WD_TIMEOUT_PERIOD, TIMEOUT_PERIOD_VALUE);   write_wd33c93(regs, WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_POLLED);}int wd33c93_reset(Scsi_Cmnd *SCpnt, unsigned int reset_flags){struct Scsi_Host *instance;struct WD33C93_hostdata *hostdata;int i;   instance = SCpnt->host;   hostdata = (struct WD33C93_hostdata *)instance->hostdata;   printk("scsi%d: reset. ", instance->host_no);   disable_irq(instance->irq);   ((struct WD33C93_hostdata *)instance->hostdata)->dma_stop(instance,NULL,0);   for (i = 0; i < 8; i++) {      hostdata->busy[i] = 0;      hostdata->sync_xfer[i] = calc_sync_xfer(DEFAULT_SX_PER/4,DEFAULT_SX_OFF);      hostdata->sync_stat[i] = SS_UNSET;  /* using default sync values */      }   hostdata->input_Q = NULL;   hostdata->selecting = NULL;   hostdata->connected = NULL;   hostdata->disconnected_Q = NULL;   hostdata->state = S_UNCONNECTED;   hostdata->dma = D_DMA_OFF;   hostdata->incoming_ptr = 0;   hostdata->outgoing_len = 0;   reset_wd33c93(instance);   SCpnt->result = DID_RESET << 16;   enable_irq(instance->irq);   return 0;}int wd33c93_abort (Scsi_Cmnd *cmd){struct Scsi_Host *instance;struct WD33C93_hostdata *hostdata;wd33c93_regs regs;Scsi_Cmnd *tmp, *prev;   disable_irq(cmd->host->irq);   instance = cmd->host;   hostdata = (struct WD33C93_hostdata *)instance->hostdata;   regs = hostdata->regs;/* * Case 1 : If the command hasn't been issued yet, we simply remove it *     from the input_Q. */   tmp = (Scsi_Cmnd *)hostdata->input_Q;   prev = 0;   while (tmp) {      if (tmp == cmd) {         if (prev)            prev->host_scribble = cmd->host_scribble;	 else            hostdata->input_Q = (Scsi_Cmnd *)cmd->host_scribble;         cmd->host_scribble = NULL;         cmd->result = DID_ABORT << 16;         printk("scsi%d: Abort - removing command %ld from input_Q. ",           instance->host_no, cmd->pid);    enable_irq(cmd->host->irq);         cmd->scsi_done(cmd);         return SCSI_ABORT_SUCCESS;         }      prev = tmp;      tmp = (Scsi_Cmnd *)tmp->host_scribble;      }/* * Case 2 : If the command is connected, we're going to fail the abort *     and let the high level SCSI driver retry at a later time or *     issue a reset. * *     Timeouts, and therefore aborted commands, will be highly unlikely *     and handling them cleanly in this situation would make the common *     case of noresets less efficient, and would pollute our code.  So, *     we fail. */   if (hostdata->connected == cmd) {      uchar sr, asr;      unsigned long timeout;      printk("scsi%d: Aborting connected command %ld - ",              instance->host_no, cmd->pid);      printk("stopping DMA - ");      if (hostdata->dma == D_DMA_RUNNING) {         hostdata->dma_stop(instance, cmd, 0);         hostdata->dma = D_DMA_OFF;         }      printk("sending wd33c93 ABORT command - ");      write_wd33c93(regs, WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_POLLED);      write_wd33c93_cmd(regs, WD_CMD_ABORT);/* Now we have to attempt to flush out the FIFO... */      printk("flushing fifo - ");      timeout = 1000000;      do {         asr = READ_AUX_STAT();         if (asr & ASR_DBR)            read_wd33c93(regs, WD_DATA);         } while (!(asr & ASR_INT) && timeout-- > 0);      sr = read_wd33c93(regs, WD_SCSI_STATUS);      printk("asr=%02x, sr=%02x, %ld bytes un-transferred (timeout=%ld) - ",             asr, sr, read_wd33c93_count(regs), timeout);   /*    * Abort command processed.    * Still connected.    * We must disconnect.    */      printk("sending wd33c93 DISCONNECT command - ");      write_wd33c93_cmd(regs, WD_CMD_DISCONNECT);      timeout = 1000000;      asr = READ_AUX_STAT();      while ((asr & ASR_CIP) && timeout-- > 0)         asr = READ_AUX_STAT();      sr = read_wd33c93(regs, WD_SCSI_STATUS);      printk("asr=%02x, sr=%02x.",asr,sr);      hostdata->busy[cmd->target] &= ~(1 << cmd->lun);      hostdata->connected = NULL;      hostdata->state = S_UNCONNECTED;      cmd->result = DID_ABORT << 16;/*      sti();*/      wd33c93_execute (instance);      enable_irq(cmd->host->irq);      cmd->scsi_done(cmd);      return SCSI_ABORT_SUCCESS;      }/* * Case 3: If the command is currently disconnected from the bus, * we're not going to expend much effort here: Let's just return * an ABORT_SNOOZE and hope for the best... */   tmp = (Scsi_Cmnd *)hostdata->disconnected_Q;   while (tmp) {      if (tmp == cmd) {         printk("scsi%d: Abort - command %ld found on disconnected_Q - ",

⌨️ 快捷键说明

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