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

📄 in2000.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
               }            }   /* OK - find out which device reselected us. */         id = read_3393(hostdata,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....)    */         lun = read_3393(hostdata,WD_DATA);         if (hostdata->level2 < L2_RESELECT)            write_3393_cmd(hostdata,WD_CMD_NEGATE_ACK);         lun &= 7;   /* 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);            break;            }   /* 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_3393(hostdata,WD_DESTINATION_ID,cmd->target);         else            write_3393(hostdata,WD_DESTINATION_ID,cmd->target | DSTID_DPD);         if (hostdata->level2 >= L2_RESELECT) {            write_3393_count(hostdata,0); /* we want a DATA_PHASE interrupt */            write_3393(hostdata,WD_COMMAND_PHASE, 0x45);            write_3393_cmd(hostdata,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);      }   write1_io(0, IO_LED_OFF);DB(DB_INTR,printk("} "))/* release the SMP spin_lock and restore irq state */   CLISPIN_UNLOCK(flags);}#define RESET_CARD         0#define RESET_CARD_AND_BUS 1#define B_FLAG 0x80static int reset_hardware(struct Scsi_Host *instance, int type){struct IN2000_hostdata *hostdata;int qt,x;unsigned long flags;   hostdata = (struct IN2000_hostdata *)instance->hostdata;   write1_io(0, IO_LED_ON);   if (type == RESET_CARD_AND_BUS) {      write1_io(0,IO_CARD_RESET);      x = read1_io(IO_HARDWARE);      }   x = read_3393(hostdata,WD_SCSI_STATUS);   /* clear any WD intrpt */   write_3393(hostdata,WD_OWN_ID, instance->this_id |                           OWNID_EAF | OWNID_RAF | OWNID_FS_8);   write_3393(hostdata,WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_POLLED);   write_3393(hostdata,WD_SYNCHRONOUS_TRANSFER,              calc_sync_xfer(hostdata->default_sx_per/4,DEFAULT_SX_OFF));   save_flags(flags);   cli();   write1_io(0,IO_FIFO_WRITE);            /* clear fifo counter */   write1_io(0,IO_FIFO_READ);             /* start fifo out in read mode */   write_3393(hostdata,WD_COMMAND, WD_CMD_RESET);   while (!(READ_AUX_STAT() & ASR_INT))      ;                                   /* wait for RESET to complete */   x = read_3393(hostdata,WD_SCSI_STATUS);   /* clear interrupt */   restore_flags(flags);   write_3393(hostdata,WD_QUEUE_TAG,0xa5);   /* any random number */   qt = read_3393(hostdata,WD_QUEUE_TAG);   if (qt == 0xa5) {      x |= B_FLAG;      write_3393(hostdata,WD_QUEUE_TAG,0);      }   write_3393(hostdata,WD_TIMEOUT_PERIOD, TIMEOUT_PERIOD_VALUE);   write_3393(hostdata,WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_POLLED);   write1_io(0, IO_LED_OFF);   return x;}int in2000_reset(Scsi_Cmnd *cmd, unsigned int reset_flags){unsigned long flags;struct Scsi_Host *instance;struct IN2000_hostdata *hostdata;int x;   instance = cmd->host;   hostdata = (struct IN2000_hostdata *)instance->hostdata;   printk("scsi%d: Reset. ", instance->host_no);   save_flags(flags);   cli();   /* do scsi-reset here */   reset_hardware(instance, RESET_CARD_AND_BUS);   for (x = 0; x < 8; x++) {      hostdata->busy[x] = 0;      hostdata->sync_xfer[x] = calc_sync_xfer(DEFAULT_SX_PER/4,DEFAULT_SX_OFF);      hostdata->sync_stat[x] = 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->fifo = FI_FIFO_UNUSED;   hostdata->incoming_ptr = 0;   hostdata->outgoing_len = 0;   cmd->result = DID_RESET << 16;   restore_flags(flags);   return 0;}int in2000_abort (Scsi_Cmnd *cmd){struct Scsi_Host *instance;struct IN2000_hostdata *hostdata;Scsi_Cmnd *tmp, *prev;unsigned long flags;uchar sr, asr;unsigned long timeout;   save_flags (flags);   cli();   instance = cmd->host;   hostdata = (struct IN2000_hostdata *)instance->hostdata;   printk ("scsi%d: Abort-", instance->host_no);   printk("(asr=%02x,count=%ld,resid=%d,buf_resid=%d,have_data=%d,FC=%02x)- ",            READ_AUX_STAT(),read_3393_count(hostdata),cmd->SCp.this_residual,cmd->SCp.buffers_residual,            cmd->SCp.have_data_in,read1_io(IO_FIFO_COUNT));/* * Case 1 : If the command hasn't been issued yet, we simply remove it *     from the inout_Q. */   tmp = (Scsi_Cmnd *)hostdata->input_Q;   prev = 0;   while (tmp) {      if (tmp == cmd) {         if (prev)            prev->host_scribble = 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);         cmd->scsi_done(cmd);         restore_flags(flags);         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) {      printk("scsi%d: Aborting connected command %ld - ",              instance->host_no, cmd->pid);      printk("sending wd33c93 ABORT command - ");      write_3393(hostdata, WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_POLLED);      write_3393_cmd(hostdata, 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_3393(hostdata, WD_DATA);         } while (!(asr & ASR_INT) && timeout-- > 0);      sr = read_3393(hostdata, WD_SCSI_STATUS);      printk("asr=%02x, sr=%02x, %ld bytes un-transferred (timeout=%ld) - ",             asr, sr, read_3393_count(hostdata), timeout);   /*    * Abort command processed.    * Still connected.    * We must disconnect.    */      printk("sending wd33c93 DISCONNECT command - ");      write_3393_cmd(hostdata, WD_CMD_DISCONNECT);      timeout = 1000000;      asr = READ_AUX_STAT();      while ((asr & ASR_CIP) && timeout-- > 0)         asr = READ_AUX_STAT();      sr = read_3393(hostdata, 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;      cmd->scsi_done(cmd);      in2000_execute (instance);      restore_flags(flags);      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... */   for (tmp=(Scsi_Cmnd *)hostdata->disconnected_Q; tmp;         tmp=(Scsi_Cmnd *)tmp->host_scribble)      if (cmd == tmp) {         restore_flags(flags);         printk("Sending ABORT_SNOOZE. ");         return SCSI_ABORT_SNOOZE;         }/* * Case 4 : If we reached this point, the command was not found in any of *     the queues. * * We probably reached this point because of an unlikely race condition * between the command completing successfully and the abortion code, * so we won't panic, but we will notify the user in case something really * broke. */   in2000_execute (instance);   restore_flags(flags);   printk("scsi%d: warning : SCSI command probably completed successfully"      "         before abortion. ", instance->host_no);   return SCSI_ABORT_NOT_RUNNING;}#define MAX_IN2000_HOSTS 3#define MAX_SETUP_ARGS (sizeof(setup_args) / sizeof(char *))#define SETUP_BUFFER_SIZE 200static char setup_buffer[SETUP_BUFFER_SIZE];static char setup_used[MAX_SETUP_ARGS];static int done_setup = 0;void __init in2000_setup (char *str, int *ints){int i;char *p1,*p2;   strncpy(setup_buffer,str,SETUP_BUFFER_SIZE);   setup_buffer[SETUP_BUFFER_SIZE - 1] = '\0';   p1 = setup_buffer;   i = 0;   while (*p1 && (i < MAX_SETUP_ARGS)) {      p2 = strchr(p1, ',');      if (p2) {         *p2 = '\0';         if (p1 != p2)            setup_args[i] = p1;         p1 = p2 + 1;         i++;         }      else {         setup_args[i] = p1;         break;         }      }   for (i=0; i<MAX_SETUP_ARGS; i++)      setup_used[i] = 0;   done_setup = 1;}/* check_setup_args() returns index if key found, 0 if not */static int __init check_setup_args(char *key, int *flags, int *val, char *buf){int x;char *cp;   for  (x=0; x<MAX_SETUP_ARGS; x++) {      if (setup_used[x])         continue;      if (!strncmp(setup_args[x], key, strlen(key)))         break;      }   if (x == MAX_SETUP_ARGS)      return 0;   setup_used[x] = 1;   cp = setup_args[x] + strlen(key);   *val = -1;   if (*cp != ':')      return ++x;   cp++;   if ((*cp >= '0') && (*cp <= '9')) {      *val = simple_strtoul(cp,NULL,0);      }   return ++x;}/* The "correct" (ie portable) way to access memory-mapped hardware * such as the IN2000 EPROM and dip switch is through the use of * special macros declared in 'asm/io.h'. We use readb() and readl() * when reading from the card's BIOS area in in2000_detect(). */static const unsigned int *bios_tab[] in2000__INITDATA = {   (unsigned int *)0xc8000,   (unsigned int *)0xd0000,   (unsigned int *)0xd8000,   0   };static const unsigned short base_tab[] in2000__INITDATA =

⌨️ 快捷键说明

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