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

📄 qla1280.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	if (qla1280_check_for_dead_scsi_bus(ha, bus))		return 1;	if (device->tagged_supported &&	    (ha->bus_settings[bus].qtag_enables & (BIT_0 << target))) {		scsi_adjust_queue_depth(device, MSG_ORDERED_TAG,					ha->bus_settings[bus].hiwat);	} else {		scsi_adjust_queue_depth(device, 0, default_depth);	}	nv->bus[bus].target[target].parameter.enable_sync = device->sdtr;	nv->bus[bus].target[target].parameter.enable_wide = device->wdtr;	nv->bus[bus].target[target].ppr_1x160.flags.enable_ppr = device->ppr;	if (driver_setup.no_sync ||	    (driver_setup.sync_mask &&	     (~driver_setup.sync_mask & (1 << target))))		nv->bus[bus].target[target].parameter.enable_sync = 0;	if (driver_setup.no_wide ||	    (driver_setup.wide_mask &&	     (~driver_setup.wide_mask & (1 << target))))		nv->bus[bus].target[target].parameter.enable_wide = 0;	if (IS_ISP1x160(ha)) {		if (driver_setup.no_ppr ||		    (driver_setup.ppr_mask &&		     (~driver_setup.ppr_mask & (1 << target))))			nv->bus[bus].target[target].ppr_1x160.flags.enable_ppr = 0;	}	spin_lock_irqsave(ha->host->host_lock, flags);	if (nv->bus[bus].target[target].parameter.enable_sync)		status = qla1280_set_target_parameters(ha, bus, target);	qla1280_get_target_parameters(ha, device);	spin_unlock_irqrestore(ha->host->host_lock, flags);	return status;}/* * qla1280_done *      Process completed commands. * * Input: *      ha           = adapter block pointer. */static voidqla1280_done(struct scsi_qla_host *ha){	struct srb *sp;	struct list_head *done_q;	int bus, target, lun;	struct scsi_cmnd *cmd;	ENTER("qla1280_done");	done_q = &ha->done_q;	while (!list_empty(done_q)) {		sp = list_entry(done_q->next, struct srb, list);		list_del(&sp->list);			cmd = sp->cmd;		bus = SCSI_BUS_32(cmd);		target = SCSI_TCN_32(cmd);		lun = SCSI_LUN_32(cmd);		switch ((CMD_RESULT(cmd) >> 16)) {		case DID_RESET:			/* Issue marker command. */			qla1280_marker(ha, bus, target, 0, MK_SYNC_ID);			break;		case DID_ABORT:			sp->flags &= ~SRB_ABORT_PENDING;			sp->flags |= SRB_ABORTED;			if (sp->flags & SRB_TIMEOUT)				CMD_RESULT(sp->cmd) = DID_TIME_OUT << 16;			break;		default:			break;		}		/* Release memory used for this I/O */		scsi_dma_unmap(cmd);		/* Call the mid-level driver interrupt handler */		CMD_HANDLE(sp->cmd) = (unsigned char *)INVALID_HANDLE;		ha->actthreads--;		(*(cmd)->scsi_done)(cmd);		if(sp->wait != NULL)			complete(sp->wait);	}	LEAVE("qla1280_done");}/* * Translates a ISP error to a Linux SCSI error */static intqla1280_return_status(struct response * sts, struct scsi_cmnd *cp){	int host_status = DID_ERROR;	uint16_t comp_status = le16_to_cpu(sts->comp_status);	uint16_t state_flags = le16_to_cpu(sts->state_flags);	uint32_t residual_length = le32_to_cpu(sts->residual_length);	uint16_t scsi_status = le16_to_cpu(sts->scsi_status);#if DEBUG_QLA1280_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_QLA1280_INTR */	ENTER("qla1280_return_status");#if DEBUG_QLA1280_INTR	/*	  dprintk(1, "qla1280_return_status: compl status = 0x%04x\n",	  comp_status);	*/#endif	switch (comp_status) {	case CS_COMPLETE:		host_status = DID_OK;		break;	case CS_INCOMPLETE:		if (!(state_flags & SF_GOT_BUS))			host_status = DID_NO_CONNECT;		else if (!(state_flags & SF_GOT_TARGET))			host_status = DID_BAD_TARGET;		else if (!(state_flags & SF_SENT_CDB))			host_status = DID_ERROR;		else if (!(state_flags & SF_TRANSFERRED_DATA))			host_status = DID_ERROR;		else if (!(state_flags & SF_GOT_STATUS))			host_status = DID_ERROR;		else if (!(state_flags & SF_GOT_SENSE))			host_status = DID_ERROR;		break;	case CS_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:		dprintk(2, "Data overrun 0x%x\n", residual_length);		dprintk(2, "qla1280_return_status: response packet data\n");		qla1280_dump_buffer(2, (char *)sts, RESPONSE_ENTRY_SIZE);		host_status = DID_ERROR;		break;	case CS_DATA_UNDERRUN:		if ((scsi_bufflen(cp) - residual_length) <		    cp->underflow) {			printk(KERN_WARNING			       "scsi: Underflow detected - retrying "			       "command.\n");			host_status = DID_ERROR;		} else {			scsi_set_resid(cp, residual_length);			host_status = DID_OK;		}		break;	default:		host_status = DID_ERROR;		break;	}#if DEBUG_QLA1280_INTR	dprintk(1, "qla1280 ISP status: host status (%s) scsi status %x\n",		reason[host_status], scsi_status);#endif	LEAVE("qla1280_return_status");	return (scsi_status & 0xff) | (host_status << 16);}/****************************************************************************//*                QLogic ISP1280 Hardware Support Functions.                *//****************************************************************************//* * qla1280_initialize_adapter *      Initialize board. * * Input: *      ha = adapter block pointer. * * Returns: *      0 = success */static int __devinitqla1280_initialize_adapter(struct scsi_qla_host *ha){	struct device_reg __iomem *reg;	int status;	int bus;	unsigned long flags;	ENTER("qla1280_initialize_adapter");	/* Clear adapter flags. */	ha->flags.online = 0;	ha->flags.disable_host_adapter = 0;	ha->flags.reset_active = 0;	ha->flags.abort_isp_active = 0;#if defined(CONFIG_IA64_GENERIC) || defined(CONFIG_IA64_SGI_SN2)	if (ia64_platform_is("sn2")) {		printk(KERN_INFO "scsi(%li): Enabling SN2 PCI DMA "		       "dual channel lockup workaround\n", ha->host_no);		ha->flags.use_pci_vchannel = 1;		driver_setup.no_nvram = 1;	}#endif	/* TODO: implement support for the 1040 nvram format */	if (IS_ISP1040(ha))		driver_setup.no_nvram = 1;	dprintk(1, "Configure PCI space for adapter...\n");	reg = ha->iobase;	/* Insure mailbox registers are free. */	WRT_REG_WORD(&reg->semaphore, 0);	WRT_REG_WORD(&reg->host_cmd, HC_CLR_RISC_INT);	WRT_REG_WORD(&reg->host_cmd, HC_CLR_HOST_INT);	RD_REG_WORD(&reg->host_cmd);	if (qla1280_read_nvram(ha)) {		dprintk(2, "qla1280_initialize_adapter: failed to read "			"NVRAM\n");	}	/*	 * It's necessary to grab the spin here as qla1280_mailbox_command	 * needs to be able to drop the lock unconditionally to wait	 * for completion.	 */	spin_lock_irqsave(ha->host->host_lock, flags);	status = qla1280_load_firmware(ha);	if (status) {		printk(KERN_ERR "scsi(%li): initialize: pci probe failed!\n",		       ha->host_no);		goto out;	}	/* Setup adapter based on NVRAM parameters. */	dprintk(1, "scsi(%ld): Configure NVRAM parameters\n", ha->host_no);	qla1280_nvram_config(ha);	if (ha->flags.disable_host_adapter) {		status = 1;		goto out;	}	status = qla1280_init_rings(ha);	if (status)		goto out;	/* Issue SCSI reset, if we can't reset twice then bus is dead */	for (bus = 0; bus < ha->ports; bus++) {		if (!ha->bus_settings[bus].disable_scsi_reset &&		    qla1280_bus_reset(ha, bus) &&		    qla1280_bus_reset(ha, bus))			ha->bus_settings[bus].scsi_bus_dead = 1;	}	ha->flags.online = 1; out:	spin_unlock_irqrestore(ha->host->host_lock, flags);	if (status)		dprintk(2, "qla1280_initialize_adapter: **** FAILED ****\n");	LEAVE("qla1280_initialize_adapter");	return status;}/* * Chip diagnostics *      Test chip for proper operation. * * Input: *      ha = adapter block pointer. * * Returns: *      0 = success. */static intqla1280_chip_diag(struct scsi_qla_host *ha){	uint16_t mb[MAILBOX_REGISTER_COUNT];	struct device_reg __iomem *reg = ha->iobase;	int status = 0;	int cnt;	uint16_t data;	dprintk(3, "qla1280_chip_diag: testing device at 0x%p \n", &reg->id_l);	dprintk(1, "scsi(%ld): Verifying chip\n", ha->host_no);	/* Soft reset chip and wait for it to finish. */	WRT_REG_WORD(&reg->ictrl, ISP_RESET);	/*	 * We can't do a traditional PCI write flush here by reading	 * back the register. The card will not respond once the reset	 * is in action and we end up with a machine check exception	 * instead. Nothing to do but wait and hope for the best.	 * A portable pci_write_flush(pdev) call would be very useful here.	 */	udelay(20);	data = qla1280_debounce_register(&reg->ictrl);	/*	 * Yet another QLogic gem ;-(	 */	for (cnt = 1000000; cnt && data & ISP_RESET; cnt--) {		udelay(5);		data = RD_REG_WORD(&reg->ictrl);	}	if (!cnt)		goto fail;	/* Reset register cleared by chip reset. */	dprintk(3, "qla1280_chip_diag: reset register cleared by chip reset\n");	WRT_REG_WORD(&reg->cfg_1, 0);	/* Reset RISC and disable BIOS which	   allows RISC to execute out of RAM. */	WRT_REG_WORD(&reg->host_cmd, HC_RESET_RISC |		     HC_RELEASE_RISC | HC_DISABLE_BIOS);	RD_REG_WORD(&reg->id_l);	/* Flush PCI write */	data = qla1280_debounce_register(&reg->mailbox0);	/*	 * I *LOVE* this code!	 */	for (cnt = 1000000; cnt && data == MBS_BUSY; cnt--) {		udelay(5);		data = RD_REG_WORD(&reg->mailbox0);	}	if (!cnt)		goto fail;	/* Check product ID of chip */	dprintk(3, "qla1280_chip_diag: Checking product ID of chip\n");	if (RD_REG_WORD(&reg->mailbox1) != PROD_ID_1 ||	    (RD_REG_WORD(&reg->mailbox2) != PROD_ID_2 &&	     RD_REG_WORD(&reg->mailbox2) != PROD_ID_2a) ||	    RD_REG_WORD(&reg->mailbox3) != PROD_ID_3 ||	    RD_REG_WORD(&reg->mailbox4) != PROD_ID_4) {		printk(KERN_INFO "qla1280: Wrong product ID = "		       "0x%x,0x%x,0x%x,0x%x\n",		       RD_REG_WORD(&reg->mailbox1),		       RD_REG_WORD(&reg->mailbox2),		       RD_REG_WORD(&reg->mailbox3),		       RD_REG_WORD(&reg->mailbox4));		goto fail;	}	/*	 * Enable ints early!!!	 */	qla1280_enable_intrs(ha);	dprintk(1, "qla1280_chip_diag: Checking mailboxes of chip\n");	/* Wrap Incoming Mailboxes Test. */	mb[0] = MBC_MAILBOX_REGISTER_TEST;	mb[1] = 0xAAAA;	mb[2] = 0x5555;	mb[3] = 0xAA55;	mb[4] = 0x55AA;	mb[5] = 0xA5A5;	mb[6] = 0x5A5A;	mb[7] = 0x2525;	status = qla1280_mailbox_command(ha, 0xff, mb);	if (status)

⌨️ 快捷键说明

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