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

📄 wd33c93.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 5 页
字号:
/* Respond to the specific WD3393 interrupt - there are quite a few! */   switch (sr) {      case CSR_TIMEOUT:DB(DB_INTR,printk("TIMEOUT"))         if (hostdata->state == S_RUNNING_LEVEL2)            hostdata->connected = NULL;         else {            cmd = (Scsi_Cmnd *)hostdata->selecting;   /* get a valid cmd */            hostdata->selecting = NULL;            }         cmd->result = DID_NO_CONNECT << 16;         hostdata->busy[cmd->target] &= ~(1 << cmd->lun);         hostdata->state = S_UNCONNECTED;         cmd->scsi_done(cmd);    /* From esp.c:     * There is a window of time within the scsi_done() path     * of execution where interrupts are turned back on full     * blast and left that way.  During that time we could     * reconnect to a disconnected command, then we'd bomb     * out below.  We could also end up executing two commands     * at _once_.  ...just so you know why the restore_flags()     * is here...     */    restore_flags(flags);/* We are not connected to a target - check to see if there * are commands waiting to be executed. */         wd33c93_execute(instance);         break;/* Note: this interrupt should not occur in a LEVEL2 command */      case CSR_SELECT:DB(DB_INTR,printk("SELECT"))         hostdata->connected = cmd = (Scsi_Cmnd *)hostdata->selecting;         hostdata->selecting = NULL;      /* construct an IDENTIFY message with correct disconnect bit */         hostdata->outgoing_msg[0] = (0x80 | 0x00 | cmd->lun);         if (cmd->SCp.phase)            hostdata->outgoing_msg[0] |= 0x40;         if (hostdata->sync_stat[cmd->target] == SS_FIRST) {#ifdef SYNC_DEBUGprintk(" sending SDTR ");#endif            hostdata->sync_stat[cmd->target] = SS_WAITING;/* Tack on a 2nd message to ask about synchronous transfers. If we've * been asked to do only asynchronous transfers on this device, we * request a fifo depth of 0, which is equivalent to async - should * solve the problems some people have had with GVP's Guru ROM. */            hostdata->outgoing_msg[1] = EXTENDED_MESSAGE;            hostdata->outgoing_msg[2] = 3;            hostdata->outgoing_msg[3] = EXTENDED_SDTR;            if (hostdata->no_sync & (1 << cmd->target)) {               hostdata->outgoing_msg[4] = hostdata->default_sx_per/4;               hostdata->outgoing_msg[5] = 0;               }            else {            hostdata->outgoing_msg[4] = OPTIMUM_SX_PER/4;            hostdata->outgoing_msg[5] = OPTIMUM_SX_OFF;               }            hostdata->outgoing_len = 6;            }         else            hostdata->outgoing_len = 1;         hostdata->state = S_CONNECTED;         break;      case CSR_XFER_DONE|PHS_DATA_IN:      case CSR_UNEXP    |PHS_DATA_IN:      case CSR_SRV_REQ  |PHS_DATA_IN:DB(DB_INTR,printk("IN-%d.%d",cmd->SCp.this_residual,cmd->SCp.buffers_residual))         transfer_bytes(regs, cmd, DATA_IN_DIR);         if (hostdata->state != S_RUNNING_LEVEL2)            hostdata->state = S_CONNECTED;         break;      case CSR_XFER_DONE|PHS_DATA_OUT:      case CSR_UNEXP    |PHS_DATA_OUT:      case CSR_SRV_REQ  |PHS_DATA_OUT:DB(DB_INTR,printk("OUT-%d.%d",cmd->SCp.this_residual,cmd->SCp.buffers_residual))         transfer_bytes(regs, cmd, DATA_OUT_DIR);         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(regs, 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(regs);DB(DB_INTR,printk("%02x",cmd->SCp.Status))         if (hostdata->level2 >= L2_BASIC) {            sr = read_wd33c93(regs, WD_SCSI_STATUS);  /* clear interrupt */            hostdata->state = S_RUNNING_LEVEL2;            write_wd33c93(regs, WD_COMMAND_PHASE, 0x50);            write_wd33c93_cmd(regs, 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(regs);         sr = read_wd33c93(regs, 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_wd33c93_cmd(regs, WD_CMD_NEGATE_ACK);               hostdata->state = S_PRE_CMP_DISC;               break;            case SAVE_POINTERS:DB(DB_INTR,printk("SDP"))               write_wd33c93_cmd(regs, WD_CMD_NEGATE_ACK);               hostdata->state = S_CONNECTED;               break;            case RESTORE_POINTERS:DB(DB_INTR,printk("RDP"))               if (hostdata->level2 >= L2_BASIC) {                  write_wd33c93(regs, WD_COMMAND_PHASE, 0x45);                  write_wd33c93_cmd(regs, WD_CMD_SEL_ATN_XFER);                  hostdata->state = S_RUNNING_LEVEL2;                  }               else {                  write_wd33c93_cmd(regs, WD_CMD_NEGATE_ACK);                  hostdata->state = S_CONNECTED;                  }               break;            case DISCONNECT:DB(DB_INTR,printk("DIS"))               cmd->device->disconnect = 1;               write_wd33c93_cmd(regs, 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_wd33c93_cmd(regs, 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_wd33c93_cmd(regs, 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_wd33c93_cmd(regs, WD_CMD_NEGATE_ACK);                        hostdata->state = S_CONNECTED;                        break;                     case EXTENDED_WDTR:                        write_wd33c93_cmd(regs, 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_wd33c93_cmd(regs, WD_CMD_NEGATE_ACK);                        hostdata->state = S_CONNECTED;                        break;                     default:                        write_wd33c93_cmd(regs, 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_wd33c93_cmd(regs, 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_wd33c93_cmd(regs, WD_CMD_NEGATE_ACK);                  hostdata->state = S_CONNECTED;                  }               break;            default:               printk("Rejecting Unknown Message(%02x) ",msg);               write_wd33c93_cmd(regs, WD_CMD_ASSERT_ATN); /* want MESS_OUT */               hostdata->outgoing_msg[0] = MESSAGE_REJECT;               hostdata->outgoing_len = 1;               write_wd33c93_cmd(regs, WD_CMD_NEGATE_ACK);               hostdata->state = S_CONNECTED;            }         restore_flags(flags);         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_wd33c93(regs, WD_SOURCE_ID, SRCID_ER);         if (phs == 0x60) {DB(DB_INTR,printk("SX-DONE-%ld",cmd->pid))            cmd->SCp.Message = COMMAND_COMPLETE;            lun = read_wd33c93(regs, 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. */       restore_flags(flags);            wd33c93_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_wd33c93(regs, WD_COMMAND_PHASE, 0x41);            write_wd33c93_cmd(regs, 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(regs, 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_wd33c93(regs, WD_SOURCE_ID, SRCID_ER);         if (cmd == NULL) {            printk(" - Already disconnected! ");            hostdata->state = S_UNCONNECTED;            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. */    /* look above for comments on scsi_done() */    restore_flags(flags);         wd33c93_execute(instance);         break;

⌨️ 快捷键说明

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