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

📄 qlogicfc.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
		cmd->dataseg[0].d_count = cpu_to_le32(Cmnd->request_bufflen);		cmd->segment_cnt = cpu_to_le16(1);	} else {		cmd->dataseg[0].d_base = 0;#if PCI64_DMA_BITS > 32		cmd->dataseg[0].d_base_hi = 0;#endif		cmd->segment_cnt = cpu_to_le16(1); /* Shouldn't this be 0? */	}	switch (Cmnd->cmnd[0]) {	case TEST_UNIT_READY:	case START_STOP:	        break;	case WRITE_10:	case WRITE_6:	case WRITE_BUFFER:	case MODE_SELECT:		cmd->control_flags = cpu_to_le16(CFLAG_WRITE);		break;	default:		cmd->control_flags = cpu_to_le16(CFLAG_READ);		break;	}	if (Cmnd->device->tagged_supported) {		if ((jiffies - hostdata->tag_ages[Cmnd->target]) > (2 * SCSI_TIMEOUT)) {			cmd->control_flags |= cpu_to_le16(CFLAG_ORDERED_TAG);			hostdata->tag_ages[Cmnd->target] = jiffies;		} else			switch (Cmnd->tag) {			case HEAD_OF_QUEUE_TAG:				cmd->control_flags |= cpu_to_le16(CFLAG_HEAD_TAG);				break;			case ORDERED_QUEUE_TAG:				cmd->control_flags |= cpu_to_le16(CFLAG_ORDERED_TAG);				break;			default:				cmd->control_flags |= cpu_to_le16(CFLAG_SIMPLE_TAG);				break;		}	}	/*	 * TEST_UNIT_READY commands from scsi_scan will fail due to "overlapped	 * commands attempted" unless we setup at least a simple queue (midlayer 	 * will embelish this once it can do an INQUIRY command to the device)	 */	else		cmd->control_flags |= cpu_to_le16(CFLAG_SIMPLE_TAG);	outw(in_ptr, host->io_port + MBOX4);	hostdata->req_in_ptr = in_ptr;	hostdata->queued++;	num_free = QLOGICFC_REQ_QUEUE_LEN - REQ_QUEUE_DEPTH(in_ptr, out_ptr);	num_free = (num_free > 2) ? num_free - 2 : 0;	host->can_queue = hostdata->queued + num_free;	if (host->can_queue > QLOGICFC_REQ_QUEUE_LEN)		host->can_queue = QLOGICFC_REQ_QUEUE_LEN;	host->sg_tablesize = QLOGICFC_MAX_SG(num_free);	/* this is really gross */	if (host->can_queue <= host->host_busy){	        if (host->can_queue+2 < host->host_busy) 			DEBUG(printk("qlogicfc%d.c crosses its fingers.\n", hostdata->host_id));		host->can_queue = host->host_busy + 1;	}	LEAVE("isp2x00_queuecommand");	return 0;}/* we have received an event, such as a lip or an RSCN, which may mean that * our port database is incorrect so the port database must be recreated. */static void redo_port_db(unsigned long arg){        struct Scsi_Host * host = (struct Scsi_Host *) arg;	struct isp2x00_hostdata * hostdata;	unsigned long flags;	int i;	hostdata = (struct isp2x00_hostdata *) host->hostdata;	hostdata->explore_timer.data = 0;	del_timer(&hostdata->explore_timer);	spin_lock_irqsave(&io_request_lock, flags);	if (hostdata->adapter_state & AS_REDO_FABRIC_PORTDB || hostdata->adapter_state & AS_REDO_LOOP_PORTDB) {		isp2x00_make_portdb(host);		printk("qlogicfc%d : Port Database\n", hostdata->host_id);		for (i = 0; hostdata->port_db[i].wwn != 0; i++) {			printk("wwn: %08x%08x  scsi_id: %x  loop_id: ", (u_int) (hostdata->port_db[i].wwn >> 32), (u_int) hostdata->port_db[i].wwn, i);			if (hostdata->port_db[i].loop_id != hostdata->port_db[0].loop_id || i == 0)			        printk("%x", hostdata->port_db[i].loop_id);			else			        printk("Not Available");			printk("\n");		}			        for (i = 0; i < QLOGICFC_REQ_QUEUE_LEN; i++){ 		        if (hostdata->handle_ptrs[i] && (hostdata->port_db[hostdata->handle_ptrs[i]->target].loop_id > QLOGICFC_MAX_LOOP_ID || hostdata->adapter_state & AS_REDO_LOOP_PORTDB)){                                if (hostdata->port_db[hostdata->handle_ptrs[i]->target].loop_id != hostdata->port_db[0].loop_id){					 hostdata->handle_ptrs[i]->result = DID_SOFT_ERROR << 16;					 if (hostdata->handle_ptrs[i]->scsi_done){					   (*hostdata->handle_ptrs[i]->scsi_done) (hostdata->handle_ptrs[i]);					 }					 else printk("qlogicfc%d : done is null?\n", hostdata->host_id);					 hostdata->handle_ptrs[i] = NULL;					 hostdata->handle_serials[i] = 0;				}			}		}				hostdata->adapter_state = AS_LOOP_GOOD;	}	spin_unlock_irqrestore(&io_request_lock, flags);}#define ASYNC_EVENT_INTERRUPT	0x01void do_isp2x00_intr_handler(int irq, void *dev_id, struct pt_regs *regs){	unsigned long flags;	spin_lock_irqsave(&io_request_lock, flags);	isp2x00_intr_handler(irq, dev_id, regs);	spin_unlock_irqrestore(&io_request_lock, flags);}void isp2x00_intr_handler(int irq, void *dev_id, struct pt_regs *regs){	Scsi_Cmnd *Cmnd;	struct Status_Entry *sts;	struct Scsi_Host *host = dev_id;	struct isp2x00_hostdata *hostdata;	u_int in_ptr, out_ptr, handle, num_free;	u_short status;	ENTER_INTR("isp2x00_intr_handler");	hostdata = (struct isp2x00_hostdata *) host->hostdata;	DEBUG_INTR(printk("qlogicfc%d : interrupt on line %d\n", hostdata->host_id, irq));	if (!(inw(host->io_port + PCI_INTER_STS) & 0x08)) {		/* spurious interrupts can happen legally */		DEBUG_INTR(printk("qlogicfc%d : got spurious interrupt\n", hostdata->host_id));		return;	}	in_ptr = inw(host->io_port + MBOX5);	out_ptr = hostdata->res_out_ptr;	if ((inw(host->io_port + PCI_SEMAPHORE) & ASYNC_EVENT_INTERRUPT)) {		status = inw(host->io_port + MBOX0);		DEBUG_INTR(printk("qlogicfc%d : mbox completion status: %x\n",				  hostdata->host_id, status));		switch (status) {		case LOOP_UP:		case POINT_TO_POINT_UP:		        printk("qlogicfc%d : Link is Up\n", hostdata->host_id);			hostdata->adapter_state = AS_REDO_FABRIC_PORTDB | AS_REDO_LOOP_PORTDB;			break;		case LOOP_DOWN:		        printk("qlogicfc%d : Link is Down\n", hostdata->host_id);			hostdata->adapter_state = AS_LOOP_DOWN;			break;		case CONNECTION_MODE:		        printk("received CONNECTION_MODE irq %x\n", inw(host->io_port + MBOX1));			break;		case CHANGE_NOTIFICATION:		        printk("qlogicfc%d : RSCN Received\n", hostdata->host_id);			if (hostdata->adapter_state == AS_LOOP_GOOD)				hostdata->adapter_state = AS_REDO_FABRIC_PORTDB;			break;		        		case LIP_OCCURED:		case LIP_RECEIVED:		        printk("qlogicfc%d : Loop Reinitialized\n", hostdata->host_id);			if (hostdata->adapter_state == AS_LOOP_GOOD)				hostdata->adapter_state = AS_REDO_LOOP_PORTDB;			break;		case SYSTEM_ERROR:			printk("qlogicfc%d : The firmware just choked.\n", hostdata->host_id);			hostdata->adapter_state = AS_FIRMWARE_DEAD;			break;		case SCSI_COMMAND_COMPLETE:			handle = inw(host->io_port + MBOX1) | (inw(host->io_port + MBOX2) << 16);			Cmnd = hostdata->handle_ptrs[handle];			hostdata->handle_ptrs[handle] = NULL;			hostdata->handle_serials[handle] = 0;			hostdata->queued--;			if (Cmnd != NULL) {				Cmnd->result = 0x0;				(*Cmnd->scsi_done) (Cmnd);			} else				printk("qlogicfc%d.c : got a null value out of handle_ptrs, this sucks\n", hostdata->host_id);			break;		case MBOX_COMMAND_COMPLETE:		case INVALID_COMMAND:		case HOST_INTERFACE_ERROR:		case TEST_FAILED:		case COMMAND_ERROR:		case COMMAND_PARAM_ERROR:		case PORT_ID_USED:		case LOOP_ID_USED:		case ALL_IDS_USED:			hostdata->mbox_done = 1;			outw(HCCR_CLEAR_RISC_INTR, host->io_port + HOST_HCCR);			return;		default:			printk("qlogicfc%d : got an unknown status? %x\n", hostdata->host_id, status);		}		if ((hostdata->adapter_state & AS_REDO_LOOP_PORTDB || hostdata->adapter_state & AS_REDO_FABRIC_PORTDB) && hostdata->explore_timer.data == 0){                        hostdata->explore_timer.function = redo_port_db;			hostdata->explore_timer.data = (unsigned long)host;			hostdata->explore_timer.expires = jiffies + (HZ/4);			init_timer(&hostdata->explore_timer);			add_timer(&hostdata->explore_timer);		}		outw(0x0, host->io_port + PCI_SEMAPHORE);	} else {		DEBUG_INTR(printk("qlogicfc%d : response queue update\n", hostdata->host_id));		DEBUG_INTR(printk("qlogicfc%d : response queue depth %d\n", hostdata->host_id, RES_QUEUE_DEPTH(in_ptr, out_ptr)));		while (out_ptr != in_ptr) {			unsigned le_hand;			sts = (struct Status_Entry *) &hostdata->res[out_ptr*QUEUE_ENTRY_LEN];			out_ptr = (out_ptr + 1) & RES_QUEUE_LEN;                 			TRACE("done", out_ptr, Cmnd);			DEBUG_INTR(isp2x00_print_status_entry(sts));			le_hand = le32_to_cpu(sts->handle);			if (sts->hdr.entry_type == ENTRY_STATUS && (Cmnd = hostdata->handle_ptrs[le_hand])) {				Cmnd->result = isp2x00_return_status(Cmnd, sts);				hostdata->queued--;				if (Cmnd->use_sg)					pci64_unmap_sg(hostdata->pci_dev,						       (struct scatterlist *)Cmnd->buffer, Cmnd->use_sg,						       scsi_to_pci_dma_dir(Cmnd->sc_data_direction));				else if (Cmnd->request_bufflen && Cmnd->sc_data_direction != PCI_DMA_NONE)					pci64_unmap_single(hostdata->pci_dev, *(dma64_addr_t *)&Cmnd->SCp,							   Cmnd->request_bufflen,							   scsi_to_pci_dma_dir(Cmnd->sc_data_direction));				/* 				 * if any of the following are true we do not				 * call scsi_done.  if the status is CS_ABORTED				 * we dont have to call done because the upper				 * level should already know its aborted.				 */				if (hostdata->handle_serials[le_hand] != Cmnd->serial_number 				    || le16_to_cpu(sts->completion_status) == CS_ABORTED){					hostdata->handle_serials[le_hand] = 0;					hostdata->handle_ptrs[le_hand] = NULL;					outw(out_ptr, host->io_port + MBOX5);					continue;				}				/*				 * if we get back an error indicating the port				 * is not there or if the link is down and 				 * this is a device that used to be there 				 * allow the command to timeout.				 * the device may well be back in a couple of				 * seconds.				 */				if ((hostdata->adapter_state == AS_LOOP_DOWN || sts->completion_status == cpu_to_le16(CS_PORT_UNAVAILABLE) || sts->completion_status == cpu_to_le16(CS_PORT_LOGGED_OUT) || sts->completion_status == cpu_to_le16(CS_PORT_CONFIG_CHANGED)) && hostdata->port_db[Cmnd->target].wwn){					outw(out_ptr, host->io_port + MBOX5);					continue;				}			} else {				outw(out_ptr, host->io_port + MBOX5);				continue;			}			hostdata->handle_ptrs[le_hand] = NULL;			if (sts->completion_status == cpu_to_le16(CS_RESET_OCCURRED)			    || (sts->status_flags & cpu_to_le16(STF_BUS_RESET)))				hostdata->send_marker = 1;			if (le16_to_cpu(sts->scsi_status) & 0x0200)				memcpy(Cmnd->sense_buffer, sts->req_sense_data,				       sizeof(Cmnd->sense_buffer));			outw(out_ptr, host->io_port + MBOX5);			if (Cmnd->scsi_done != NULL) {				(*Cmnd->scsi_done) (Cmnd);			} else				printk("qlogicfc%d : Ouch, scsi done is NULL\n", hostdata->host_id);		}		hostdata->res_out_ptr = out_ptr;	}	out_ptr = inw(host->io_port + MBOX4);	in_ptr = hostdata->req_in_ptr;	num_free = QLOGICFC_REQ_QUEUE_LEN - REQ_QUEUE_DEPTH(in_ptr, out_ptr);	num_free = (num_free > 2) ? num_free - 2 : 0;	host->can_queue = hostdata->queued + num_free;	if (host->can_queue > QLOGICFC_REQ_QUEUE_LEN)		host->can_queue = QLOGICFC_REQ_QUEUE_LEN;	host->sg_tablesize = QLOGICFC_MAX_SG(num_free);	if (host->can_queue <= host->host_busy){	        if (host->can_queue+2 < host->host_busy) 		        DEBUG(printk("qlogicfc%d : crosses its fingers.\n", hostdata->host_id));		host->can_queue = host->host_busy + 1;	}	outw(HCCR_CLEAR_RISC_INTR, host->io_port + HOST_HCCR);	LEAVE_INTR("isp2x00_intr_handler");}static int isp2x00_return_status(Scsi_Cmnd *Cmnd, struct Status_Entry *sts){	int host_status = DID_ERROR;#if DEBUG_ISP2x00_INTR	static char *reason[] =	{		"DID_OK",		"DID_NO_CONNECT",		"DID_BUS_BUSY",		"DID_TIME_OUT",		"DID_BAD_TARGET",		"DID_ABORT",		"DID_PARITY",		"DID_ERROR",		"DID_RESET",		"DID_BAD_INTR"	};#endif				/* DEBUG_ISP2x00_INTR */	ENTER("isp2x00_return_status");	DEBUG(printk("qlogicfc : completion status = 0x%04x\n",		     le16_to_cpu(sts->completion_status)));	switch (le16_to_cpu(sts->completion_status)) {	case CS_COMPLETE:		host_status = DID_OK;		break;	case CS_DMA_ERROR:		host_status = DID_ERROR;		break;	case CS_RESET_OCCURRED:		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:		host_status = DID_ERROR;		break;	case CS_DATA_UNDERRUN:	        if (Cmnd->underflow <= (Cmnd->request_bufflen - le32_to_cpu(sts->residual)))		        host_status = DID_OK;		else		        host_status = DID_ERROR;		break;	case CS_PORT_UNAVAILABLE:	case CS_PORT_LOGGED_OUT:	case CS_PORT_CONFIG_CHANGED:		host_status = DID_BAD_TARGET;		break;	case CS_QUEUE_FULL:		host_status = DID_ERROR;		break;	default:		printk("qlogicfc : unknown completion status 0x%04x\n",		       le16_to_cpu(sts->completion_status));		host_status = DID_ERROR;		break;	}	DEBUG_INTR(printk("qlogicfc : host status (%s) scsi status %x\n",			  reason[host_status], le16_to_cpu(sts->scsi_status)));	LEAVE("isp2x00_return_status");	return (le16_to_cpu(sts->scsi_status) & STATUS_MASK) | (host_status << 16);}int isp2x00_abort(Scsi_Cmnd * Cmnd){	u_short param[8];	int i;	struct Scsi_Host *host;	struct isp2x00_hostdata *hostdata;	int return_status = SUCCESS;	ENTER("isp2x00_abort");	host = Cmnd->host;	hostdata = (struct isp2x00_hostdata *) host->hostdata;	for (i = 0; i < QLOGICFC_REQ_QUEUE_LEN; i++)		if (hostdata->handle_ptrs[i] == Cmnd)			break;	if (i == QLOGICFC_REQ_QUEUE_LEN){		return SUCCESS;	}	isp2x00_disable_irqs(host);	param[0] = MBOX_ABORT_IOCB;#if ISP2x00_PORTDB	param[1] = (((u_short) hostdata->port_db[Cmnd->target].loop_id) << 8) | Cmnd->lun;#else	param[1] = (((u_short) Cmnd->target) << 8) | Cmnd->lun;#endif	param[2] = i & 0xffff;	param[3] = i >> 16;	isp2x00_mbox_command(host, param);	if (param[0] != MBOX_COMMAND_COMPLETE) {		printk("qlogicfc%d : scsi abort failure: %x\n", hostdata->host_id, param[0]);		if (param[0] == 0x4005)			Cmnd->result = DID_ERROR << 16;		if (param[0] == 0x4006)			Cmnd->result = DID_BAD_TARGET << 16;		return_status = FAILED;	}

⌨️ 快捷键说明

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