📄 ips.c
字号:
} 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 + -