ips.c
来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 1,776 行 · 第 1/5 页
C
1,776 行
METHOD_TRACE("ips_queue", 1); ha = (ips_ha_t *) SC->device->host->hostdata; if (!ha) return (1); if (!ha->active) return (DID_ERROR); if (ips_is_passthru(SC)) { if (ha->copp_waitlist.count == IPS_MAX_IOCTL_QUEUE) { SC->result = DID_BUS_BUSY << 16; done(SC); return (0); } } else if (ha->scb_waitlist.count == IPS_MAX_QUEUE) { SC->result = DID_BUS_BUSY << 16; done(SC); return (0); } 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->device->channel, SC->device->id, SC->device->lun); /* Check for command to initiator IDs */ if ((SC->device->channel > 0) && (SC->device->id == ha->ha_id[SC->device->channel])) { SC->result = DID_NO_CONNECT << 16; done(SC); return (0); } if (ips_is_passthru(SC)) { ips_copp_wait_item_t *scratch; /* A Reset IOCTL is only sent by the boot CD in extreme cases. */ /* There can never be any system activity ( network or disk ), but check */ /* anyway just as a good practice. */ pt = (ips_passthru_t *) SC->request_buffer; if ((pt->CoppCP.cmd.reset.op_code == IPS_CMD_RESET_CHANNEL) && (pt->CoppCP.cmd.reset.adapter_flag == 1)) { if (ha->scb_activelist.count != 0) { SC->result = DID_BUS_BUSY << 16; done(SC); return (0); } ha->ioctl_reset = 1; /* This reset request is from an IOCTL */ ips_eh_reset(SC); SC->result = DID_OK << 16; SC->scsi_done(SC); return (0); } /* 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->next = NULL; ips_putq_copp_tail(&ha->copp_waitlist, scratch); } else { ips_putq_wait_tail(&ha->scb_waitlist, SC); } ips_next(ha, IPS_INTR_IORL); return (0);}/****************************************************************************//* *//* Routine Name: ips_biosparam *//* *//* Routine Description: *//* *//* Set bios geometry for the controller *//* *//****************************************************************************/static int#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)ips_biosparam(Disk * disk, kdev_t dev, int geom[]){ ips_ha_t *ha = (ips_ha_t *) disk->device->host->hostdata; unsigned long capacity = disk->capacity;#elseips_biosparam(struct scsi_device *sdev, struct block_device *bdev, sector_t capacity, int geom[]){ ips_ha_t *ha = (ips_ha_t *) sdev->host->hostdata;#endif int heads; int sectors; int cylinders; METHOD_TRACE("ips_biosparam", 1); 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 ((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 = (unsigned long) 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);}#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)/* ips_proc24_info is a wrapper around ips_proc_info * * for compatibility with the 2.4 scsi parameters */static intips_proc24_info(char *buffer, char **start, off_t offset, int length, int hostno, int func){ int i; for (i = 0; i < ips_next_controller; i++) { if (ips_sh[i] && ips_sh[i]->host_no == hostno) { return ips_proc_info(ips_sh[i], buffer, start, offset, length, func); } } return -EINVAL; }/****************************************************************************//* *//* 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; int min; ha = IPS_HA(host); min = ha->max_cmds / 4; 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 - 1) / count; if (device->queue_depth < min) device->queue_depth = min; } else { device->queue_depth = 2; } if (device->queue_depth < 2) device->queue_depth = 2; } }}#else/****************************************************************************//* *//* Routine Name: ips_slave_configure *//* *//* Routine Description: *//* *//* Set queue depths on devices once scan is complete *//* *//****************************************************************************/intips_slave_configure(Scsi_Device * SDptr){ ips_ha_t *ha; int min; ha = IPS_HA(SDptr->host); if (SDptr->tagged_supported && SDptr->type == TYPE_DISK) { min = ha->max_cmds / 2; if (ha->enq->ucLogDriveCount <= 2) min = ha->max_cmds - 1; scsi_adjust_queue_depth(SDptr, MSG_ORDERED_TAG, min); } return 0;}#endif/****************************************************************************//* *//* Routine Name: do_ipsintr *//* *//* Routine Description: *//* *//* Wrapper for the interrupt handler *//* *//****************************************************************************/irqreturn_tdo_ipsintr(int irq, void *dev_id, struct pt_regs * regs){ ips_ha_t *ha; unsigned long cpu_flags; struct Scsi_Host *host; int irqstatus; METHOD_TRACE("do_ipsintr", 2); ha = (ips_ha_t *) dev_id; if (!ha) return IRQ_NONE; host = ips_sh[ha->host_num]; /* interrupt during initialization */ if (!host) { (*ha->func.intr) (ha); return IRQ_HANDLED; } IPS_LOCK_SAVE(host->host_lock, cpu_flags); if (!ha->active) { IPS_UNLOCK_RESTORE(host->host_lock, cpu_flags); return IRQ_HANDLED; } irqstatus = (*ha->func.intr) (ha); IPS_UNLOCK_RESTORE(host->host_lock, cpu_flags); /* start the next command */ ips_next(ha, IPS_INTR_ON); return IRQ_RETVAL(irqstatus);}/****************************************************************************//* *//* Routine Name: ips_intr_copperhead *//* *//* Routine Description: *//* *//* Polling interrupt handler *//* *//* ASSUMES interrupts are disabled *//* *//****************************************************************************/intips_intr_copperhead(ips_ha_t * ha){ ips_stat_t *sp; ips_scb_t *scb; IPS_STATUS cstatus; int intrstatus; METHOD_TRACE("ips_intr", 2); if (!ha) return 0; if (!ha->active) return 0; intrstatus = (*ha->func.isintr) (ha); if (!intrstatus) { /* * Unexpected/Shared interrupt */ return 0; } 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)) { /* Spurious Interupt ? */ 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 */ (*scb->callback) (ha, scb); } /* end while */ return 1;}/****************************************************************************//* *//* Routine Name: ips_intr_morpheus *//* *//* Routine Description: *//* *//* Polling interrupt handler *//* *//* ASSUMES interrupts are disabled *//* *//****************************************************************************/int
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?