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

📄 in2000.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
         if (hostdata->state != S_RUNNING_LEVEL2)            hostdata->state = S_CONNECTED;         break;/* Note: this interrupt should not occur in a LEVEL2 command */      case CSR_XFER_DONE|PHS_COMMAND:      case CSR_UNEXP    |PHS_COMMAND:      case CSR_SRV_REQ  |PHS_COMMAND:DB(DB_INTR,printk("CMND-%02x,%ld",cmd->cmnd[0],cmd->pid))         transfer_pio(cmd->cmnd, cmd->cmd_len, DATA_OUT_DIR, hostdata);         hostdata->state = S_CONNECTED;         break;      case CSR_XFER_DONE|PHS_STATUS:      case CSR_UNEXP    |PHS_STATUS:      case CSR_SRV_REQ  |PHS_STATUS:DB(DB_INTR,printk("STATUS="))         cmd->SCp.Status = read_1_byte(hostdata);DB(DB_INTR,printk("%02x",cmd->SCp.Status))         if (hostdata->level2 >= L2_BASIC) {            sr = read_3393(hostdata,WD_SCSI_STATUS);  /* clear interrupt */            hostdata->state = S_RUNNING_LEVEL2;            write_3393(hostdata,WD_COMMAND_PHASE, 0x50);            write_3393_cmd(hostdata,WD_CMD_SEL_ATN_XFER);            }         else {            hostdata->state = S_CONNECTED;            }         break;      case CSR_XFER_DONE|PHS_MESS_IN:      case CSR_UNEXP    |PHS_MESS_IN:      case CSR_SRV_REQ  |PHS_MESS_IN:DB(DB_INTR,printk("MSG_IN="))         msg = read_1_byte(hostdata);         sr = read_3393(hostdata,WD_SCSI_STATUS);  /* clear interrupt */         hostdata->incoming_msg[hostdata->incoming_ptr] = msg;         if (hostdata->incoming_msg[0] == EXTENDED_MESSAGE)            msg = EXTENDED_MESSAGE;         else            hostdata->incoming_ptr = 0;         cmd->SCp.Message = msg;         switch (msg) {            case COMMAND_COMPLETE:DB(DB_INTR,printk("CCMP-%ld",cmd->pid))               write_3393_cmd(hostdata,WD_CMD_NEGATE_ACK);               hostdata->state = S_PRE_CMP_DISC;               break;            case SAVE_POINTERS:DB(DB_INTR,printk("SDP"))               write_3393_cmd(hostdata,WD_CMD_NEGATE_ACK);               hostdata->state = S_CONNECTED;               break;            case RESTORE_POINTERS:DB(DB_INTR,printk("RDP"))               if (hostdata->level2 >= L2_BASIC) {                  write_3393(hostdata,WD_COMMAND_PHASE, 0x45);                  write_3393_cmd(hostdata,WD_CMD_SEL_ATN_XFER);                  hostdata->state = S_RUNNING_LEVEL2;                  }               else {                  write_3393_cmd(hostdata,WD_CMD_NEGATE_ACK);                  hostdata->state = S_CONNECTED;                  }               break;            case DISCONNECT:DB(DB_INTR,printk("DIS"))               cmd->device->disconnect = 1;               write_3393_cmd(hostdata,WD_CMD_NEGATE_ACK);               hostdata->state = S_PRE_TMP_DISC;               break;            case MESSAGE_REJECT:DB(DB_INTR,printk("REJ"))#ifdef SYNC_DEBUGprintk("-REJ-");#endif               if (hostdata->sync_stat[cmd->target] == SS_WAITING)                  hostdata->sync_stat[cmd->target] = SS_SET;               write_3393_cmd(hostdata,WD_CMD_NEGATE_ACK);               hostdata->state = S_CONNECTED;               break;            case EXTENDED_MESSAGE:DB(DB_INTR,printk("EXT"))               ucp = hostdata->incoming_msg;#ifdef SYNC_DEBUGprintk("%02x",ucp[hostdata->incoming_ptr]);#endif         /* Is this the last byte of the extended message? */               if ((hostdata->incoming_ptr >= 2) &&                   (hostdata->incoming_ptr == (ucp[1] + 1))) {                  switch (ucp[2]) {   /* what's the EXTENDED code? */                     case EXTENDED_SDTR:                        id = calc_sync_xfer(ucp[3],ucp[4]);                        if (hostdata->sync_stat[cmd->target] != SS_WAITING) {/* A device has sent an unsolicited SDTR message; rather than go * through the effort of decoding it and then figuring out what * our reply should be, we're just gonna say that we have a * synchronous fifo depth of 0. This will result in asynchronous * transfers - not ideal but so much easier. * Actually, this is OK because it assures us that if we don't * specifically ask for sync transfers, we won't do any. */                           write_3393_cmd(hostdata,WD_CMD_ASSERT_ATN); /* want MESS_OUT */                           hostdata->outgoing_msg[0] = EXTENDED_MESSAGE;                           hostdata->outgoing_msg[1] = 3;                           hostdata->outgoing_msg[2] = EXTENDED_SDTR;                           hostdata->outgoing_msg[3] = hostdata->default_sx_per/4;                           hostdata->outgoing_msg[4] = 0;                           hostdata->outgoing_len = 5;                           hostdata->sync_xfer[cmd->target] =                                       calc_sync_xfer(hostdata->default_sx_per/4,0);                           }                        else {                           hostdata->sync_xfer[cmd->target] = id;                           }#ifdef SYNC_DEBUGprintk("sync_xfer=%02x",hostdata->sync_xfer[cmd->target]);#endif                        hostdata->sync_stat[cmd->target] = SS_SET;                        write_3393_cmd(hostdata,WD_CMD_NEGATE_ACK);                        hostdata->state = S_CONNECTED;                        break;                     case EXTENDED_WDTR:                        write_3393_cmd(hostdata,WD_CMD_ASSERT_ATN); /* want MESS_OUT */                        printk("sending WDTR ");                        hostdata->outgoing_msg[0] = EXTENDED_MESSAGE;                        hostdata->outgoing_msg[1] = 2;                        hostdata->outgoing_msg[2] = EXTENDED_WDTR;                        hostdata->outgoing_msg[3] = 0;   /* 8 bit transfer width */                        hostdata->outgoing_len = 4;                        write_3393_cmd(hostdata,WD_CMD_NEGATE_ACK);                        hostdata->state = S_CONNECTED;                        break;                     default:                        write_3393_cmd(hostdata,WD_CMD_ASSERT_ATN); /* want MESS_OUT */                        printk("Rejecting Unknown Extended Message(%02x). ",ucp[2]);                        hostdata->outgoing_msg[0] = MESSAGE_REJECT;                        hostdata->outgoing_len = 1;                        write_3393_cmd(hostdata,WD_CMD_NEGATE_ACK);                        hostdata->state = S_CONNECTED;                        break;                     }                  hostdata->incoming_ptr = 0;                  }         /* We need to read more MESS_IN bytes for the extended message */               else {                  hostdata->incoming_ptr++;                  write_3393_cmd(hostdata,WD_CMD_NEGATE_ACK);                  hostdata->state = S_CONNECTED;                  }               break;            default:               printk("Rejecting Unknown Message(%02x) ",msg);               write_3393_cmd(hostdata,WD_CMD_ASSERT_ATN); /* want MESS_OUT */               hostdata->outgoing_msg[0] = MESSAGE_REJECT;               hostdata->outgoing_len = 1;               write_3393_cmd(hostdata,WD_CMD_NEGATE_ACK);               hostdata->state = S_CONNECTED;            }         break;/* Note: this interrupt will occur only after a LEVEL2 command */      case CSR_SEL_XFER_DONE:/* Make sure that reselection is enabled at this point - it may * have been turned off for the command that just completed. */         write_3393(hostdata,WD_SOURCE_ID, SRCID_ER);         if (phs == 0x60) {DB(DB_INTR,printk("SX-DONE-%ld",cmd->pid))            cmd->SCp.Message = COMMAND_COMPLETE;            lun = read_3393(hostdata,WD_TARGET_LUN);DB(DB_INTR,printk(":%d.%d",cmd->SCp.Status,lun))            hostdata->connected = NULL;            hostdata->busy[cmd->target] &= ~(1 << cmd->lun);            hostdata->state = S_UNCONNECTED;            if (cmd->SCp.Status == ILLEGAL_STATUS_BYTE)               cmd->SCp.Status = lun;            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);/* We are no longer connected to a target - check to see if * there are commands waiting to be executed. */            in2000_execute(instance);            }         else {            printk("%02x:%02x:%02x-%ld: Unknown SEL_XFER_DONE phase!!---",asr,sr,phs,cmd->pid);            }         break;/* Note: this interrupt will occur only after a LEVEL2 command */      case CSR_SDP:DB(DB_INTR,printk("SDP"))            hostdata->state = S_RUNNING_LEVEL2;            write_3393(hostdata,WD_COMMAND_PHASE, 0x41);            write_3393_cmd(hostdata,WD_CMD_SEL_ATN_XFER);         break;      case CSR_XFER_DONE|PHS_MESS_OUT:      case CSR_UNEXP    |PHS_MESS_OUT:      case CSR_SRV_REQ  |PHS_MESS_OUT:DB(DB_INTR,printk("MSG_OUT="))/* To get here, we've probably requested MESSAGE_OUT and have * already put the correct bytes in outgoing_msg[] and filled * in outgoing_len. We simply send them out to the SCSI bus. * Sometimes we get MESSAGE_OUT phase when we're not expecting * it - like when our SDTR message is rejected by a target. Some * targets send the REJECT before receiving all of the extended * message, and then seem to go back to MESSAGE_OUT for a byte * or two. Not sure why, or if I'm doing something wrong to * cause this to happen. Regardless, it seems that sending * NOP messages in these situations results in no harm and * makes everyone happy. */         if (hostdata->outgoing_len == 0) {            hostdata->outgoing_len = 1;            hostdata->outgoing_msg[0] = NOP;            }         transfer_pio(hostdata->outgoing_msg, hostdata->outgoing_len,                      DATA_OUT_DIR, hostdata);DB(DB_INTR,printk("%02x",hostdata->outgoing_msg[0]))         hostdata->outgoing_len = 0;         hostdata->state = S_CONNECTED;         break;       case CSR_UNEXP_DISC:/* I think I've seen this after a request-sense that was in response * to an error condition, but not sure. We certainly need to do * something when we get this interrupt - the question is 'what?'. * Let's think positively, and assume some command has finished * in a legal manner (like a command that provokes a request-sense), * so we treat it as a normal command-complete-disconnect. *//* Make sure that reselection is enabled at this point - it may * have been turned off for the command that just completed. */         write_3393(hostdata,WD_SOURCE_ID, SRCID_ER);         if (cmd == NULL) {            printk(" - Already disconnected! ");            hostdata->state = S_UNCONNECTED;/* release the SMP spin_lock and restore irq state */            CLISPIN_UNLOCK(flags);            return;            }DB(DB_INTR,printk("UNEXP_DISC-%ld",cmd->pid))         hostdata->connected = NULL;         hostdata->busy[cmd->target] &= ~(1 << cmd->lun);         hostdata->state = S_UNCONNECTED;         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);/* We are no longer connected to a target - check to see if * there are commands waiting to be executed. */         in2000_execute(instance);         break;      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_3393(hostdata,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);               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. */         in2000_execute(instance);         break;      case CSR_RESEL_AM:DB(DB_INTR,printk("RESEL"))   /* 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");                  }

⌨️ 快捷键说明

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