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

📄 ips.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
   }   return (SUCCESS);#endif /* NO_IPS_RESET */}/****************************************************************************//*                                                                          *//* Routine Name: ips_queue                                                  *//*                                                                          *//* Routine Description:                                                     *//*                                                                          *//*   Send a command to the controller                                       *//*                                                                          *//* NOTE:                                                                    *//*    Linux obtains io_request_lock before calling this function            *//*                                                                          *//****************************************************************************/intips_queue(Scsi_Cmnd *SC, void (*done) (Scsi_Cmnd *)) {   ips_ha_t         *ha;   u32               cpu_flags;   DECLARE_MUTEX_LOCKED(sem);   METHOD_TRACE("ips_queue", 1);   ha = (ips_ha_t *) SC->host->hostdata;   if (!ha)      return (1);   if (!ha->active)      return (DID_ERROR);#ifndef NO_IPS_CMDLINE   if (ips_is_passthru(SC)) {      IPS_QUEUE_LOCK(&ha->copp_waitlist);      if (ha->copp_waitlist.count == IPS_MAX_IOCTL_QUEUE) {         IPS_QUEUE_UNLOCK(&ha->copp_waitlist);         SC->result = DID_BUS_BUSY << 16;         done(SC);         return (0);      } else {         IPS_QUEUE_UNLOCK(&ha->copp_waitlist);      }   } else {#endif      IPS_QUEUE_LOCK(&ha->scb_waitlist);      if (ha->scb_waitlist.count == IPS_MAX_QUEUE) {         IPS_QUEUE_UNLOCK(&ha->scb_waitlist);         SC->result = DID_BUS_BUSY << 16;         done(SC);         return (0);      } else {         IPS_QUEUE_UNLOCK(&ha->scb_waitlist);      }#ifndef NO_IPS_CMDLINE   }#endif   SC->scsi_done = done;   DEBUG_VAR(2, "(%s%d): ips_queue: cmd 0x%X (%d %d %d)",             ips_name,             ha->host_num,             SC->cmnd[0],             SC->channel,             SC->target,             SC->lun);   /* Check for command to initiator IDs */   if ((SC->channel > 0) && (SC->target == ha->ha_id[SC->channel])) {      SC->result = DID_NO_CONNECT << 16;      done(SC);      return (0);   }#ifndef NO_IPS_CMDLINE   if (ips_is_passthru(SC)) {      ips_copp_wait_item_t *scratch;      /* allocate space for the scribble */      scratch = kmalloc(sizeof(ips_copp_wait_item_t), GFP_ATOMIC);      if (!scratch) {         SC->result = DID_ERROR << 16;         done(SC);         return (0);      }      scratch->scsi_cmd = SC;      scratch->sem = &sem;      scratch->next = NULL;      ips_putq_copp_tail(&ha->copp_waitlist, scratch);   }   else#endif      ips_putq_wait_tail(&ha->scb_waitlist, SC);   IPS_HA_LOCK(cpu_flags);   if ((!test_bit(IPS_IN_INTR, &ha->flags)) &&       (!test_bit(IPS_IN_ABORT, &ha->flags)) &&       (!test_bit(IPS_IN_RESET, &ha->flags))) {      IPS_HA_UNLOCK(cpu_flags);      ips_next(ha, IPS_INTR_IORL);   } else {      IPS_HA_UNLOCK(cpu_flags);   }   /*    * If this request was a new style IOCTL wait    * for it to finish.    *    * NOTE: we relinquished the lock above so this should    * not cause contention problems    */   if (ips_is_passthru(SC) && SC->cmnd[0] == IPS_IOCTL_NEW_COMMAND) {      char *user_area;      char *kern_area;      u32   datasize;      /* free io_request_lock */      spin_unlock_irq(&io_request_lock);      /* wait for the command to finish */      down(&sem);      /* reobtain the lock */      spin_lock_irq(&io_request_lock);      /* command finished -- copy back */      user_area = *((char **) &SC->cmnd[4]);      kern_area = ha->ioctl_data;      datasize = *((u32 *) &SC->cmnd[8]);      if (copy_to_user(user_area, kern_area, datasize) > 0) {         DEBUG_VAR(1, "(%s%d) passthru failed - unable to copy out user data",                   ips_name, ha->host_num);         SC->result = DID_ERROR << 16;         SC->scsi_done(SC);      } else {         SC->scsi_done(SC);      }   }   return (0);}/****************************************************************************//*                                                                          *//* Routine Name: ips_biosparam                                              *//*                                                                          *//* Routine Description:                                                     *//*                                                                          *//*   Set bios geometry for the controller                                   *//*                                                                          *//****************************************************************************/intips_biosparam(Disk *disk, kdev_t dev, int geom[]) {   ips_ha_t         *ha;   int               heads;   int               sectors;   int               cylinders;   METHOD_TRACE("ips_biosparam", 1);   ha = (ips_ha_t *) disk->device->host->hostdata;   if (!ha)      /* ?!?! host adater info invalid */      return (0);   if (!ha->active)      return (0);   if (!ips_read_adapter_status(ha, IPS_INTR_ON))      /* ?!?! Enquiry command failed */      return (0);   if ((disk->capacity > 0x400000) &&       ((ha->enq->ucMiscFlag & 0x8) == 0)) {      heads = IPS_NORM_HEADS;      sectors = IPS_NORM_SECTORS;   } else {      heads = IPS_COMP_HEADS;      sectors = IPS_COMP_SECTORS;   }   cylinders = disk->capacity / (heads * sectors);   DEBUG_VAR(2, "Geometry: heads: %d, sectors: %d, cylinders: %d",             heads, sectors, cylinders);   geom[0] = heads;   geom[1] = sectors;   geom[2] = cylinders;   return (0);}/****************************************************************************//*                                                                          *//* Routine Name: ips_select_queue_depth                                     *//*                                                                          *//* Routine Description:                                                     *//*                                                                          *//*   Select queue depths for the devices on the contoller                   *//*                                                                          *//****************************************************************************/static voidips_select_queue_depth(struct Scsi_Host *host, Scsi_Device *scsi_devs) {   Scsi_Device *device;   ips_ha_t    *ha;   int          count = 0;   ha = IPS_HA(host);   for (device = scsi_devs; device; device = device->next) {     if (device->host == host) {        if ((device->channel == 0) && (device->type == 0))           count++;     }   }   for (device = scsi_devs; device; device = device->next) {      if (device->host == host) {         if ((device->channel == 0) && (device->type == 0))            device->queue_depth = ha->max_cmds / count - 1;         else            device->queue_depth = 2;      }   }}/****************************************************************************//*                                                                          *//* Routine Name: do_ipsintr                                                 *//*                                                                          *//* Routine Description:                                                     *//*                                                                          *//*   Wrapper for the interrupt handler                                      *//*                                                                          *//****************************************************************************/voiddo_ipsintr(int irq, void *dev_id, struct pt_regs *regs) {   ips_ha_t         *ha;   u32               cpu_flags;   METHOD_TRACE("do_ipsintr", 2);   ha = (ips_ha_t *) dev_id;   spin_lock_irqsave(&io_request_lock, cpu_flags);   if (test_and_set_bit(IPS_IN_INTR, &ha->flags)) {      spin_unlock_irqrestore(&io_request_lock, cpu_flags);      return ;   }   if (!ha) {      clear_bit(IPS_IN_INTR, &ha->flags);      spin_unlock_irqrestore(&io_request_lock, cpu_flags);      return;   }   if (!ha->active) {      clear_bit(IPS_IN_INTR, &ha->flags);      spin_unlock_irqrestore(&io_request_lock, cpu_flags);      return;   }   (*ha->func.intr)(ha);   clear_bit(IPS_IN_INTR, &ha->flags);   spin_unlock_irqrestore(&io_request_lock, cpu_flags);   /* start the next command */   ips_next(ha, IPS_INTR_ON);}/****************************************************************************//*                                                                          *//* Routine Name: ips_intr_copperhead                                        *//*                                                                          *//* Routine Description:                                                     *//*                                                                          *//*   Polling interrupt handler                                              *//*                                                                          *//*   ASSUMES interrupts are disabled                                        *//*                                                                          *//****************************************************************************/voidips_intr_copperhead(ips_ha_t *ha) {   ips_stat_t       *sp;   ips_scb_t        *scb;   IPS_STATUS        cstatus;   int               intrstatus;   u32               cpu_flags;   METHOD_TRACE("ips_intr", 2);   if (!ha)      return;   if (!ha->active)      return;   IPS_HA_LOCK(cpu_flags);   intrstatus = (*ha->func.isintr)(ha);   if (!intrstatus) {      /*       * Unexpected/Shared interrupt       */      IPS_HA_UNLOCK(cpu_flags);      return;   }   while (TRUE) {      sp = &ha->sp;      intrstatus = (*ha->func.isintr)(ha);      if (!intrstatus)         break;      else         cstatus.value = (*ha->func.statupd)(ha);      if (cstatus.fields.command_id > (IPS_MAX_CMDS - 1)) {         printk(KERN_WARNING "(%s%d) Spurious interrupt; no ccb.\n",                ips_name, ha->host_num);         continue;      }      ips_chkstatus(ha, &cstatus);      scb = (ips_scb_t *) sp->scb_addr;      /*       * use the callback function to finish things up       * NOTE: interrupts are OFF for this       */      IPS_HA_UNLOCK(cpu_flags);      (*scb->callback) (ha, scb);      IPS_HA_LOCK(cpu_flags);   } /* end while */   IPS_HA_UNLOCK(cpu_flags);}/****************************************************************************//*                                                                          *//* Routine Name: ips_intr_morpheus                                          *//*                                                                          *//* Routine Description:                              

⌨️ 快捷键说明

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