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

📄 qlogicpti.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 3 页
字号:
}/* Do it to it baby. */static inline int load_cmd(Scsi_Cmnd *Cmnd, struct Command_Entry *cmd,			   struct qlogicpti *qpti, u_int in_ptr, u_int out_ptr){	struct dataseg *ds;	struct scatterlist *sg;	int i, n;	if (Cmnd->use_sg) {		int sg_count;		sg = (struct scatterlist *) Cmnd->buffer;		sg_count = sbus_map_sg(qpti->sdev, sg, Cmnd->use_sg, scsi_to_sbus_dma_dir(Cmnd->sc_data_direction));		ds = cmd->dataseg;		cmd->segment_cnt = sg_count;		/* Fill in first four sg entries: */		n = sg_count;		if (n > 4)			n = 4;		for (i = 0; i < n; i++, sg++) {			ds[i].d_base = sg_dma_address(sg);			ds[i].d_count = sg_dma_len(sg);		}		sg_count -= 4;		while (sg_count > 0) {			struct Continuation_Entry *cont;			++cmd->hdr.entry_cnt;			cont = (struct Continuation_Entry *) &qpti->req_cpu[in_ptr];			in_ptr = NEXT_REQ_PTR(in_ptr);			if (in_ptr == out_ptr)				return -1;			cont->hdr.entry_type = ENTRY_CONTINUATION;			cont->hdr.entry_cnt = 0;			cont->hdr.sys_def_1 = 0;			cont->hdr.flags = 0;			cont->reserved = 0;			ds = cont->dataseg;			n = sg_count;			if (n > 7)				n = 7;			for (i = 0; i < n; i++, sg++) {				ds[i].d_base = sg_dma_address(sg);				ds[i].d_count = sg_dma_len(sg);			}			sg_count -= n;		}	} else if (Cmnd->request_bufflen) {		Cmnd->SCp.ptr = (char *)(unsigned long)			sbus_map_single(qpti->sdev,					Cmnd->request_buffer,					Cmnd->request_bufflen,					scsi_to_sbus_dma_dir(Cmnd->sc_data_direction));		cmd->dataseg[0].d_base = (u32) ((unsigned long)Cmnd->SCp.ptr);		cmd->dataseg[0].d_count = Cmnd->request_bufflen;		cmd->segment_cnt = 1;	} else {		cmd->dataseg[0].d_base = 0;		cmd->dataseg[0].d_count = 0;		cmd->segment_cnt = 1; /* Shouldn't this be 0? */	}	/* Committed, record Scsi_Cmd so we can find it later. */	cmd->handle = in_ptr;	qpti->cmd_slots[in_ptr] = Cmnd;	qpti->cmd_count[Cmnd->target]++;	sbus_writew(in_ptr, qpti->qregs + MBOX4);	qpti->req_in_ptr = in_ptr;	return in_ptr;}static inline void update_can_queue(struct Scsi_Host *host, u_int in_ptr, u_int out_ptr){	/* Temporary workaround until bug is found and fixed (one bug has been found	   already, but fixing it makes things even worse) -jj */	int num_free = QLOGICPTI_REQ_QUEUE_LEN - REQ_QUEUE_DEPTH(in_ptr, out_ptr) - 64;	host->can_queue = host->host_busy + num_free;	host->sg_tablesize = QLOGICPTI_MAX_SG(num_free);}/* * Until we scan the entire bus with inquiries, go throught this fella... */static void ourdone(Scsi_Cmnd *Cmnd){	struct qlogicpti *qpti = (struct qlogicpti *) Cmnd->host->hostdata;	int tgt = Cmnd->target;	void (*done) (Scsi_Cmnd *);	/* This grot added by DaveM, blame him for ugliness.	 * The issue is that in the 2.3.x driver we use the	 * host_scribble portion of the scsi command as a	 * completion linked list at interrupt service time,	 * so we have to store the done function pointer elsewhere.	 */	done = (void (*)(Scsi_Cmnd *))		(((unsigned long) Cmnd->SCp.Message)#ifdef __sparc_v9__		 | ((unsigned long) Cmnd->SCp.Status << 32UL)#endif		 );	if ((qpti->sbits & (1 << tgt)) == 0) {		int ok = host_byte(Cmnd->result) == DID_OK;		if (Cmnd->cmnd[0] == 0x12 && ok) {			unsigned char *iqd;			if (Cmnd->use_sg == 0) {				iqd = ((unsigned char *)Cmnd->buffer);			} else {				iqd = ((struct scatterlist *) Cmnd->request_buffer)->address;			}			/* tags handled in midlayer */			/* enable sync mode? */			if (iqd[7] & 0x10) {				qpti->dev_param[tgt].device_flags |= 0x10;			} else {				qpti->dev_param[tgt].synchronous_offset = 0;				qpti->dev_param[tgt].synchronous_period = 0;			}			/* are we wide capable? */			if (iqd[7] & 0x20) {				qpti->dev_param[tgt].device_flags |= 0x20;			}			qpti->sbits |= (1 << tgt);		} else if (!ok) {			qpti->sbits |= (1 << tgt);		}	}	done(Cmnd);}int qlogicpti_queuecommand_slow(Scsi_Cmnd *Cmnd, void (*done)(Scsi_Cmnd *)){	unsigned long flags;	struct qlogicpti *qpti = (struct qlogicpti *) Cmnd->host->hostdata;	/*	 * done checking this host adapter?	 * If not, then rewrite the command	 * to finish through ourdone so we	 * can peek at Inquiry data results.	 */	if (qpti->sbits && qpti->sbits != 0xffff) {		/* See above about in ourdone this ugliness... */		Cmnd->SCp.Message = ((unsigned long)done) & 0xffffffff;#ifdef __sparc_v9__		Cmnd->SCp.Status = ((unsigned long)done >> 32UL) & 0xffffffff;#endif		return qlogicpti_queuecommand(Cmnd, ourdone);	}	save_flags(flags); cli();	/*	 * We've peeked at all targets for this bus- time	 * to set parameters for devices for real now.	 */	if (qpti->sbits == 0xffff) {		int i;		for(i = 0; i < MAX_TARGETS; i++) {			u_short param[6];			param[0] = MBOX_SET_TARGET_PARAMS;			param[1] = (i << 8);			param[2] = (qpti->dev_param[i].device_flags << 8);			if (qpti->dev_param[i].device_flags & 0x10) {				param[3] = (qpti->dev_param[i].synchronous_offset << 8) |					qpti->dev_param[i].synchronous_period;			} else {				param[3] = 0;			}			(void) qlogicpti_mbox_command(qpti, param, 0);		}		/*		 * set to zero so any traverse through ourdone		 * doesn't start the whole process again,		 */		qpti->sbits = 0;	}	/* check to see if we're done with all adapters... */	for (qpti = qptichain; qpti != NULL; qpti = qpti->next) {		if (qpti->sbits) {			break;		}	}	/*	 * if we hit the end of the chain w/o finding adapters still	 * capability-configuring, then we're done with all adapters	 * and can rock on..	 */	if (qpti == NULL)		Cmnd->host->hostt->queuecommand = qlogicpti_queuecommand;	restore_flags(flags);	return qlogicpti_queuecommand(Cmnd, done);}/* * The middle SCSI layer ensures that queuecommand never gets invoked * concurrently with itself or the interrupt handler (though the * interrupt handler may call this routine as part of * request-completion handling). * * "This code must fly." -davem */int qlogicpti_queuecommand(Scsi_Cmnd *Cmnd, void (*done)(Scsi_Cmnd *)){	struct Scsi_Host *host = Cmnd->host;	struct qlogicpti *qpti = (struct qlogicpti *) host->hostdata;	struct Command_Entry *cmd;	unsigned long flags;	u_int out_ptr;	int in_ptr;	Cmnd->scsi_done = done;	spin_lock_irqsave(&qpti->lock, flags);	in_ptr = qpti->req_in_ptr;	cmd = (struct Command_Entry *) &qpti->req_cpu[in_ptr];	out_ptr = sbus_readw(qpti->qregs + MBOX4);	in_ptr = NEXT_REQ_PTR(in_ptr);	if (in_ptr == out_ptr)		goto toss_command;	if (qpti->send_marker) {		marker_frob(cmd);		qpti->send_marker = 0;		if (NEXT_REQ_PTR(in_ptr) == out_ptr) {			sbus_writew(in_ptr, qpti->qregs + MBOX4);			qpti->req_in_ptr = in_ptr;			goto toss_command;		}		cmd = (struct Command_Entry *) &qpti->req_cpu[in_ptr];		in_ptr = NEXT_REQ_PTR(in_ptr);	}	cmd_frob(cmd, Cmnd, qpti);	if ((in_ptr = load_cmd(Cmnd, cmd, qpti, in_ptr, out_ptr)) == -1)		goto toss_command;	update_can_queue(host, in_ptr, out_ptr);	spin_unlock_irqrestore(&qpti->lock, flags);	return 0;toss_command:	printk(KERN_EMERG "qlogicpti%d: request queue overflow\n",	       qpti->qpti_id);	spin_unlock_irqrestore(&qpti->lock, flags);	/* Unfortunately, unless you use the new EH code, which	 * we don't, the midlayer will ignore the return value,	 * which is insane.  We pick up the pieces like this.	 */	Cmnd->result = DID_BUS_BUSY;	done(Cmnd);	return 1;}static int qlogicpti_return_status(struct Status_Entry *sts, int id){	int host_status = DID_ERROR;	switch (sts->completion_status) {	      case CS_COMPLETE:		host_status = DID_OK;		break;	      case CS_INCOMPLETE:		if (!(sts->state_flags & SF_GOT_BUS))			host_status = DID_NO_CONNECT;		else if (!(sts->state_flags & SF_GOT_TARGET))			host_status = DID_BAD_TARGET;		else if (!(sts->state_flags & SF_SENT_CDB))			host_status = DID_ERROR;		else if (!(sts->state_flags & SF_TRANSFERRED_DATA))			host_status = DID_ERROR;		else if (!(sts->state_flags & SF_GOT_STATUS))			host_status = DID_ERROR;		else if (!(sts->state_flags & SF_GOT_SENSE))			host_status = DID_ERROR;		break;	      case CS_DMA_ERROR:	      case CS_TRANSPORT_ERROR:		host_status = DID_ERROR;		break;	      case CS_RESET_OCCURRED:	      case CS_BUS_RESET:		host_status = DID_RESET;		break;	      case CS_ABORTED:		host_status = DID_ABORT;		break;	      case CS_TIMEOUT:		host_status = DID_TIME_OUT;		break;	      case CS_DATA_OVERRUN:	      case CS_COMMAND_OVERRUN:	      case CS_STATUS_OVERRUN:	      case CS_BAD_MESSAGE:	      case CS_NO_MESSAGE_OUT:	      case CS_EXT_ID_FAILED:	      case CS_IDE_MSG_FAILED:	      case CS_ABORT_MSG_FAILED:	      case CS_NOP_MSG_FAILED:	      case CS_PARITY_ERROR_MSG_FAILED:	      case CS_DEVICE_RESET_MSG_FAILED:	      case CS_ID_MSG_FAILED:	      case CS_UNEXP_BUS_FREE:		host_status = DID_ERROR;		break;	      case CS_DATA_UNDERRUN:		host_status = DID_OK;		break;	      default:		printk(KERN_EMERG "qpti%d: unknown completion status 0x%04x\n",		       id, sts->completion_status);		host_status = DID_ERROR;		break;	}	return (sts->scsi_status & STATUS_MASK) | (host_status << 16);}static Scsi_Cmnd *qlogicpti_intr_handler(struct qlogicpti *qpti){	Scsi_Cmnd *Cmnd, *done_queue = NULL;	struct Status_Entry *sts;	u_int in_ptr, out_ptr;	if (!(sbus_readw(qpti->qregs + SBUS_STAT) & SBUS_STAT_RINT))		return NULL;			in_ptr = sbus_readw(qpti->qregs + MBOX5);	sbus_writew(HCCTRL_CRIRQ, qpti->qregs + HCCTRL);	if (sbus_readw(qpti->qregs + SBUS_SEMAPHORE) & SBUS_SEMAPHORE_LCK) {		switch (sbus_readw(qpti->qregs + MBOX0)) {		case ASYNC_SCSI_BUS_RESET:		case EXECUTION_TIMEOUT_RESET:			qpti->send_marker = 1;			break;		case INVALID_COMMAND:		case HOST_INTERFACE_ERROR:		case COMMAND_ERROR:		case COMMAND_PARAM_ERROR:			break;		};		sbus_writew(0, qpti->qregs + SBUS_SEMAPHORE);	}	/* This looks like a network driver! */	out_ptr = qpti->res_out_ptr;	while (out_ptr != in_ptr) {		u_int cmd_slot;		sts = (struct Status_Entry *) &qpti->res_cpu[out_ptr];		out_ptr = NEXT_RES_PTR(out_ptr);		/* We store an index in the handle, not the pointer in		 * some form.  This avoids problems due to the fact		 * that the handle provided is only 32-bits. -DaveM		 */		cmd_slot = sts->handle;		Cmnd = qpti->cmd_slots[cmd_slot];		qpti->cmd_slots[cmd_slot] = NULL;		if (sts->completion_status == CS_RESET_OCCURRED ||		    sts->completion_status == CS_ABORTED ||		    (sts->status_flags & STF_BUS_RESET))			qpti->send_marker = 1;		if (sts->state_flags & SF_GOT_SENSE)			memcpy(Cmnd->sense_buffer, sts->req_sense_data,			       sizeof(Cmnd->sense_buffer));		if (sts->hdr.entry_type == ENTRY_STATUS)			Cmnd->result =			    qlogicpti_return_status(sts, qpti->qpti_id);		else			Cmnd->result = DID_ERROR << 16;		if (Cmnd->use_sg) {			sbus_unmap_sg(qpti->sdev,				      (struct scatterlist *)Cmnd->buffer,				      Cmnd->use_sg,				      scsi_to_sbus_dma_dir(Cmnd->sc_data_direction));		} else {			sbus_unmap_single(qpti->sdev,					  (__u32)((unsigned long)Cmnd->SCp.ptr),					  Cmnd->request_bufflen,					  scsi_to_sbus_dma_dir(Cmnd->sc_data_direction));		}		qpti->cmd_count[Cmnd->target]--;		sbus_writew(out_ptr, qpti->qregs + MBOX5);		Cmnd->host_scribble = (unsigned char *) done_queue;		done_queue = Cmnd;	}	qpti->res_out_ptr = out_ptr;	return done_queue;}static void qpti_intr(int irq, void *dev_id, struct pt_regs *regs){	struct qlogicpti *qpti = dev_id;	unsigned long flags;	Scsi_Cmnd *dq;	spin_lock_irqsave(&qpti->lock, flags);	dq = qlogicpti_intr_handler(qpti);	spin_unlock(&qpti->lock);	if (dq != NULL) {		spin_lock(&io_request_lock);		do {			Scsi_Cmnd *next;			next = (Scsi_Cmnd *) dq->host_scribble;			dq->scsi_done(dq);			dq = next;		} while (dq != NULL);		spin_unlock(&io_request_lock);	}	__restore_flags(flags);}int qlogicpti_abort(Scsi_Cmnd *Cmnd){	u_short param[6];	struct Scsi_Host *host = Cmnd->host;	struct qlogicpti *qpti = (struct qlogicpti *) host->hostdata;	int return_status = SCSI_ABORT_SUCCESS;	unsigned long flags;	u32 cmd_cookie;	int i;	printk(KERN_WARNING "qlogicpti : Aborting cmd for tgt[%d] lun[%d]\n",	       (int)Cmnd->target, (int)Cmnd->lun);	spin_lock_irqsave(&qpti->lock, flags);	qlogicpti_disable_irqs(qpti);	/* Find the 32-bit cookie we gave to the firmware for	 * this command.	 */	for (i = 0; i < QLOGICPTI_REQ_QUEUE_LEN + 1; i++)		if (qpti->cmd_slots[i] == Cmnd)			break;	cmd_cookie = i;	param[0] = MBOX_ABORT;	param[1] = (((u_short) Cmnd->target) << 8) | Cmnd->lun;	param[2] = cmd_cookie >> 16;	param[3] = cmd_cookie & 0xffff;	if (qlogicpti_mbox_command(qpti, param, 0) ||	    (param[0] != MBOX_COMMAND_COMPLETE)) {		printk(KERN_EMERG "qlogicpti : scsi abort failure: %x\n", param[0]);		return_status = SCSI_ABORT_ERROR;	}	qlogicpti_enable_irqs(qpti);	spin_unlock_irqrestore(&qpti->lock, flags);	return return_status;}int qlogicpti_reset(Scsi_Cmnd *Cmnd, unsigned int reset_flags){	u_short param[6];	struct Scsi_Host *host = Cmnd->host;	struct qlogicpti *qpti = (struct qlogicpti *) host->hostdata;	int return_status = SCSI_RESET_SUCCESS;	unsigned long flags;	printk(KERN_WARNING "qlogicpti : Resetting SCSI bus!\n");	spin_lock_irqsave(&qpti->lock, flags);	qlogicpti_disable_irqs(qpti);	param[0] = MBOX_BUS_RESET;	param[1] = qpti->host_param.bus_reset_delay;	if (qlogicpti_mbox_command(qpti, param, 0) ||	   (param[0] != MBOX_COMMAND_COMPLETE)) {		printk(KERN_EMERG "qlogicisp : scsi bus reset failure: %x\n", param[0]);		return_status = SCSI_RESET_ERROR;	}	qlogicpti_enable_irqs(qpti);	spin_unlock_irqrestore(&qpti->lock, flags);	return return_status;}static Scsi_Host_Template driver_template = QLOGICPTI;#include "scsi_module.c"EXPORT_NO_SYMBOLS;

⌨️ 快捷键说明

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