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 + -
显示快捷键?