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

📄 qla1280.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
📖 第 1 页 / 共 5 页
字号:
		       "qla1280: dma direction bits don't match\n");		return 0;	}#ifdef MODULE	/*	 * If we are called as a module, the qla1280 pointer may not be null	 * and it would point to our bootup string, just like on the lilo	 * command line.  IF not NULL, then process this config string with	 * qla1280_setup	 *	 * Boot time Options	 * To add options at boot time add a line to your lilo.conf file like:	 * append="qla1280=verbose,max_tags:{{255,255,255,255},{255,255,255,255}}"	 * which will result in the first four devices on the first two	 * controllers being set to a tagged queue depth of 32.	 */	if (qla1280)		qla1280_setup(qla1280);#endif	/* First Initialize QLA12160 on PCI Bus 1 Dev 2 */	while ((pdev = pci_find_device(id->vendor, id->device, pdev))) {		if (pdev->bus->number == 1 && PCI_SLOT(pdev->devfn) == 2) {			if (!qla1280_probe_one(pdev, id))				num_hosts++;		}	}	pdev = NULL;	/* Try and find each different type of adapter we support */	for (id = &qla1280_pci_tbl[0]; id->device; id++) {		while ((pdev = pci_find_device(id->vendor, id->device, pdev))) {			/*			 * skip QLA12160 already initialized on			 * PCI Bus 1 Dev 2 since we already initialized			 * and presented it			 */			if (id->device == PCI_DEVICE_ID_QLOGIC_ISP12160 &&			    pdev->bus->number == 1 &&			    PCI_SLOT(pdev->devfn) == 2)				continue;			if (!qla1280_probe_one(pdev, id))				num_hosts++;		}	}	return num_hosts;}/* * This looks a bit ugly as we could just pass down host to * qla1280_remove_one, but I want to keep qla1280_release purely a wrapper * around pci_driver::remove as used from 2.6 onwards. */static intqla1280_release(struct Scsi_Host *host){	struct scsi_qla_host *ha = (struct scsi_qla_host *)host->hostdata;	qla1280_remove_one(ha->pdev);	return 0;}static intqla1280_biosparam_old(Disk * disk, kdev_t dev, int geom[]){	return qla1280_biosparam(disk->device, NULL, disk->capacity, geom);}static intqla1280_proc_info_old(char *buffer, char **start, off_t offset, int length,		      int hostno, int inout){	struct Scsi_Host *host;	for (host = scsi_hostlist; host; host = host->next) {		if (host->host_no == hostno) {			return qla1280_proc_info(host, buffer, start,						 offset, length, inout);		}	}	return -ESRCH;}#endif/************************************************************************** * qla1280_intr_handler *   Handles the H/W interrupt **************************************************************************/static irqreturn_tqla1280_intr_handler(int irq, void *dev_id, struct pt_regs *regs){	struct scsi_qla_host *ha;	struct device_reg *reg;	u16 data;	int handled = 0;	ENTER_INTR ("qla1280_intr_handler");	ha = (struct scsi_qla_host *)dev_id;	spin_lock(HOST_LOCK);	ha->isr_count++;	reg = ha->iobase;	WRT_REG_WORD(&reg->ictrl, 0);	/* disable our interrupt. */	data = qla1280_debounce_register(&reg->istatus);	/* Check for pending interrupts. */	if (data & RISC_INT) {			qla1280_isr(ha, &ha->done_q);		handled = 1;	}	if (!list_empty(&ha->done_q))		qla1280_done(ha);	spin_unlock(HOST_LOCK);	/* enable our interrupt. */	WRT_REG_WORD(&reg->ictrl, (ISP_EN_INT | ISP_EN_RISC));	LEAVE_INTR("qla1280_intr_handler");	return IRQ_RETVAL(handled);}static intqla1280_set_target_parameters(struct scsi_qla_host *ha, int bus, int target){	uint8_t mr;	uint16_t mb[MAILBOX_REGISTER_COUNT];	struct nvram *nv;	int status;	nv = &ha->nvram;	mr = BIT_3 | BIT_2 | BIT_1 | BIT_0;	/* Set Target Parameters. */	mb[0] = MBC_SET_TARGET_PARAMETERS;	mb[1] = (uint16_t) (bus ? target | BIT_7 : target);	mb[1] <<= 8;	mb[2] = (nv->bus[bus].target[target].parameter.c << 8);	if (IS_ISP1x160(ha)) {		mb[2] |= nv->bus[bus].target[target].ppr_1x160.flags.enable_ppr << 5;		mb[3] =	(nv->bus[bus].target[target].flags.flags1x160.sync_offset << 8) |			 nv->bus[bus].target[target].sync_period;		mb[6] =	(nv->bus[bus].target[target].ppr_1x160.flags.ppr_options << 8) |			 nv->bus[bus].target[target].ppr_1x160.flags.ppr_bus_width;		mr |= BIT_6;	} else {		mb[3] =	(nv->bus[bus].target[target].flags.flags1x80.sync_offset << 8) |			 nv->bus[bus].target[target].sync_period;	}	status = qla1280_mailbox_command(ha, mr, &mb[0]);	if (status)		printk(KERN_WARNING "scsi(%ld:%i:%i): "		       "qla1280_set_target_parameters() failed\n",		       ha->host_no, bus, target);	return status;}/************************************************************************** *   qla1280_slave_configure * * Description: *   Determines the queue depth for a given device.  There are two ways *   a queue depth can be obtained for a tagged queueing device.  One *   way is the default queue depth which is determined by whether *   If it is defined, then it is used *   as the default queue depth.  Otherwise, we use either 4 or 8 as the *   default queue depth (dependent on the number of hardware SCBs). **************************************************************************/static intqla1280_slave_configure(struct scsi_device *device){	struct scsi_qla_host *ha;	int default_depth = 3;	int bus = device->channel;	int target = device->id;	int status = 0;	struct nvram *nv;	unsigned long flags;	ha = (struct scsi_qla_host *)device->host->hostdata;	nv = &ha->nvram;	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);	}#if LINUX_VERSION_CODE > 0x020500	nv->bus[bus].target[target].parameter.f.enable_sync = device->sdtr;	nv->bus[bus].target[target].parameter.f.enable_wide = device->wdtr;	nv->bus[bus].target[target].ppr_1x160.flags.enable_ppr = device->ppr;#endif	if (driver_setup.no_sync ||	    (driver_setup.sync_mask &&	     (~driver_setup.sync_mask & (1 << target))))		nv->bus[bus].target[target].parameter.f.enable_sync = 0;	if (driver_setup.no_wide ||	    (driver_setup.wide_mask &&	     (~driver_setup.wide_mask & (1 << target))))		nv->bus[bus].target[target].parameter.f.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(HOST_LOCK, flags);	if (nv->bus[bus].target[target].parameter.f.enable_sync)		status = qla1280_set_target_parameters(ha, bus, target);	qla1280_get_target_parameters(ha, device);	spin_unlock_irqrestore(HOST_LOCK, flags);	return status;}#if LINUX_VERSION_CODE < 0x020545/************************************************************************** *   qla1280_select_queue_depth * *   Sets the queue depth for each SCSI device hanging off the input *   host adapter.  We use a queue depth of 2 for devices that do not *   support tagged queueing. **************************************************************************/static voidqla1280_select_queue_depth(struct Scsi_Host *host, struct scsi_device *sdev_q){	struct scsi_qla_host *ha = (struct scsi_qla_host *)host->hostdata;	struct scsi_device *sdev;	ENTER("qla1280_select_queue_depth");	for (sdev = sdev_q; sdev; sdev = sdev->next)		if (sdev->host == host)			qla1280_slave_configure(sdev);	if (sdev_q)		qla1280_check_for_dead_scsi_bus(ha, sdev_q->channel);	LEAVE("qla1280_select_queue_depth");}#endif/* * qla1280_done *      Process completed commands. * * Input: *      ha           = adapter block pointer. *      done_q       = done queue. */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 */		if (cmd->use_sg) {			dprintk(3, "S/G unmap_sg cmd=%p\n", cmd);			pci_unmap_sg(ha->pdev, cmd->request_buffer,				     cmd->use_sg, cmd->sc_data_direction);		} else if (cmd->request_bufflen) {			/*dprintk(1, "No S/G unmap_single cmd=%x saved_dma_handle=%lx\n",			  cmd, sp->saved_dma_handle); */			pci_unmap_page(ha->pdev, sp->saved_dma_handle,				       cmd->request_bufflen, cmd->sc_data_direction);		}		/* Call the mid-level driver interrupt handler */		CMD_HANDLE(sp->cmd) = (unsigned char *)INVALID_HANDLE;		ha->actthreads--;#if LINUX_VERSION_CODE < 0x020500		if (cmd->cmnd[0] == INQUIRY)			qla1280_get_target_options(cmd, ha);#endif		(*(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);	uint16_t residual_length = le16_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_isr: response packet data\n");		qla1280_dump_buffer(2, (char *)sts, RESPONSE_ENTRY_SIZE);		host_status = DID_ERROR;		break;	case CS_DATA_UNDERRUN:		if ((cp->request_bufflen - residual_length) <		    cp->underflow) {			printk(KERN_WARNING			       "scsi: Underflow detected - retrying "			       "command.\n");			host_status = DID_ERROR;		} else			host_status = DID_OK;		break;

⌨️ 快捷键说明

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