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

📄 mptbase.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
 *	Returns 0 for success, non-zero for failure. */intmpt_send_handshake_request(int handle, MPT_ADAPTER *ioc, int reqBytes, u32 *req, int sleepFlag){	int		 r = 0;	u8	*req_as_bytes;	int	 ii;	/* State is known to be good upon entering	 * this function so issue the bus reset	 * request.	 */	/*	 * Emulate what mpt_put_msg_frame() does /wrt to sanity	 * setting cb_idx/req_idx.  But ONLY if this request	 * is in proper (pre-alloc'd) request buffer range...	 */	ii = MFPTR_2_MPT_INDEX(ioc,(MPT_FRAME_HDR*)req);	if (reqBytes >= 12 && ii >= 0 && ii < ioc->req_depth) {		MPT_FRAME_HDR *mf = (MPT_FRAME_HDR*)req;		mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(ii);		mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle;	}	/* Make sure there are no doorbells */	CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);	CHIPREG_WRITE32(&ioc->chip->Doorbell,			((MPI_FUNCTION_HANDSHAKE<<MPI_DOORBELL_FUNCTION_SHIFT) |			 ((reqBytes/4)<<MPI_DOORBELL_ADD_DWORDS_SHIFT)));	/* Wait for IOC doorbell int */	if ((ii = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0) {		return ii;	}	/* Read doorbell and check for active bit */	if (!(CHIPREG_READ32(&ioc->chip->Doorbell) & MPI_DOORBELL_ACTIVE))		return -5;	dhsprintk((KERN_INFO MYNAM ": %s: mpt_send_handshake_request start, WaitCnt=%d\n",		ioc->name, ii));	CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);	if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) {		return -2;	}	/* Send request via doorbell handshake */	req_as_bytes = (u8 *) req;	for (ii = 0; ii < reqBytes/4; ii++) {		u32 word;		word = ((req_as_bytes[(ii*4) + 0] <<  0) |			(req_as_bytes[(ii*4) + 1] <<  8) |			(req_as_bytes[(ii*4) + 2] << 16) |			(req_as_bytes[(ii*4) + 3] << 24));		CHIPREG_WRITE32(&ioc->chip->Doorbell, word);		if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) {			r = -3;			break;		}	}	if (r >= 0 && WaitForDoorbellInt(ioc, 10, sleepFlag) >= 0)		r = 0;	else		r = -4;	/* Make sure there are no doorbells */	CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);	return r;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** * mpt_host_page_access_control - provides mechanism for the host * driver to control the IOC's Host Page Buffer access. * @ioc: Pointer to MPT adapter structure * @access_control_value: define bits below * * Access Control Value - bits[15:12] * 0h Reserved * 1h Enable Access { MPI_DB_HPBAC_ENABLE_ACCESS } * 2h Disable Access { MPI_DB_HPBAC_DISABLE_ACCESS } * 3h Free Buffer { MPI_DB_HPBAC_FREE_BUFFER } * * Returns 0 for success, non-zero for failure. */static intmpt_host_page_access_control(MPT_ADAPTER *ioc, u8 access_control_value, int sleepFlag){	int	 r = 0;	/* return if in use */	if (CHIPREG_READ32(&ioc->chip->Doorbell)	    & MPI_DOORBELL_ACTIVE)	    return -1;	CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);	CHIPREG_WRITE32(&ioc->chip->Doorbell,		((MPI_FUNCTION_HOST_PAGEBUF_ACCESS_CONTROL		 <<MPI_DOORBELL_FUNCTION_SHIFT) |		 (access_control_value<<12)));	/* Wait for IOC to clear Doorbell Status bit */	if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) {		return -2;	}else		return 0;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** *	mpt_host_page_alloc - allocate system memory for the fw *	If we already allocated memory in past, then resend the same pointer. *	ioc@: Pointer to pointer to IOC adapter *	ioc_init@: Pointer to ioc init config page * *	Returns 0 for success, non-zero for failure. */static intmpt_host_page_alloc(MPT_ADAPTER *ioc, pIOCInit_t ioc_init){	char	*psge;	int	flags_length;	u32	host_page_buffer_sz=0;	if(!ioc->HostPageBuffer) {		host_page_buffer_sz =		    le32_to_cpu(ioc->facts.HostPageBufferSGE.FlagsLength) & 0xFFFFFF;		if(!host_page_buffer_sz)			return 0; /* fw doesn't need any host buffers */		/* spin till we get enough memory */		while(host_page_buffer_sz > 0) {			if((ioc->HostPageBuffer = pci_alloc_consistent(			    ioc->pcidev,			    host_page_buffer_sz,			    &ioc->HostPageBuffer_dma)) != NULL) {				dinitprintk((MYIOC_s_INFO_FMT				    "host_page_buffer @ %p, dma @ %x, sz=%d bytes\n",				    ioc->name,				    ioc->HostPageBuffer,				    ioc->HostPageBuffer_dma,				    host_page_buffer_sz));				ioc->alloc_total += host_page_buffer_sz;				ioc->HostPageBuffer_sz = host_page_buffer_sz;				break;			}			host_page_buffer_sz -= (4*1024);		}	}	if(!ioc->HostPageBuffer) {		printk(MYIOC_s_ERR_FMT		    "Failed to alloc memory for host_page_buffer!\n",		    ioc->name);		return -999;	}	psge = (char *)&ioc_init->HostPageBufferSGE;	flags_length = MPI_SGE_FLAGS_SIMPLE_ELEMENT |	    MPI_SGE_FLAGS_SYSTEM_ADDRESS |	    MPI_SGE_FLAGS_32_BIT_ADDRESSING |	    MPI_SGE_FLAGS_HOST_TO_IOC |	    MPI_SGE_FLAGS_END_OF_BUFFER;	if (sizeof(dma_addr_t) == sizeof(u64)) {	    flags_length |= MPI_SGE_FLAGS_64_BIT_ADDRESSING;	}	flags_length = flags_length << MPI_SGE_FLAGS_SHIFT;	flags_length |= ioc->HostPageBuffer_sz;	mpt_add_sge(psge, flags_length, ioc->HostPageBuffer_dma);	ioc->facts.HostPageBufferSGE = ioc_init->HostPageBufferSGE;return 0;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** *	mpt_verify_adapter - Given a unique IOC identifier, set pointer to *	the associated MPT adapter structure. *	@iocid: IOC unique identifier (integer) *	@iocpp: Pointer to pointer to IOC adapter * *	Returns iocid and sets iocpp. */intmpt_verify_adapter(int iocid, MPT_ADAPTER **iocpp){	MPT_ADAPTER *ioc;	list_for_each_entry(ioc,&ioc_list,list) {		if (ioc->id == iocid) {			*iocpp =ioc;			return iocid;		}	}	*iocpp = NULL;	return -1;}intmpt_alt_ioc_wait(MPT_ADAPTER *ioc){	int loop_count = 30 * 4;  /* Wait 30 seconds */	int status = -1; /* -1 means failed to get board READY */	do {		spin_lock(&ioc->initializing_hba_lock);		if (ioc->initializing_hba_lock_flag == 0) {			ioc->initializing_hba_lock_flag=1;			spin_unlock(&ioc->initializing_hba_lock);			status = 0;			break;		}		spin_unlock(&ioc->initializing_hba_lock);		set_current_state(TASK_INTERRUPTIBLE);		schedule_timeout(HZ/4);	} while (--loop_count);	return status;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//* *	mpt_bringup_adapter - This is a wrapper function for mpt_do_ioc_recovery *	@ioc: Pointer to MPT adapter structure *	@sleepFlag: Use schedule if CAN_SLEEP else use udelay. * *	This routine performs all the steps necessary to bring the IOC *	to a OPERATIONAL state. * *      Special Note: This function was added with spin lock's so as to allow *      the dv(domain validation) work thread to succeed on the other channel *      that maybe occuring at the same time when this function is called. *      Without this lock, the dv would fail when message frames were *      requested during hba bringup on the alternate ioc. */static intmpt_bringup_adapter(MPT_ADAPTER *ioc, int sleepFlag){	int r;	if(ioc->alt_ioc) {		if((r=mpt_alt_ioc_wait(ioc->alt_ioc)!=0))			return r;	}	r = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_BRINGUP,	    CAN_SLEEP);	if(ioc->alt_ioc) {		spin_lock(&ioc->alt_ioc->initializing_hba_lock);		ioc->alt_ioc->initializing_hba_lock_flag=0;		spin_unlock(&ioc->alt_ioc->initializing_hba_lock);	}return r;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//* *	mpt_attach - Install a PCI intelligent MPT adapter. *	@pdev: Pointer to pci_dev structure * *	This routine performs all the steps necessary to bring the IOC of *	a MPT adapter to a OPERATIONAL state.  This includes registering *	memory regions, registering the interrupt, and allocating request *	and reply memory pools. * *	This routine also pre-fetches the LAN MAC address of a Fibre Channel *	MPT adapter. * *	Returns 0 for success, non-zero for failure. * *	TODO: Add support for polled controllers */intmpt_attach(struct pci_dev *pdev, const struct pci_device_id *id){	MPT_ADAPTER	*ioc;	u8		__iomem *mem;	unsigned long	 mem_phys;	unsigned long	 port;	u32		 msize;	u32		 psize;	int		 ii;	int		 r = -ENODEV;	u8		 revision;	u8		 pcixcmd;	static int	 mpt_ids = 0;#ifdef CONFIG_PROC_FS	struct proc_dir_entry *dent, *ent;#endif	if (pci_enable_device(pdev))		return r;	dinitprintk((KERN_WARNING MYNAM ": mpt_adapter_install\n"));	if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) {		dprintk((KERN_INFO MYNAM			": 64 BIT PCI BUS DMA ADDRESSING SUPPORTED\n"));	} else if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {		printk(KERN_WARNING MYNAM ": 32 BIT PCI BUS DMA ADDRESSING NOT SUPPORTED\n");		return r;	}	if (!pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK))		dprintk((KERN_INFO MYNAM			": Using 64 bit consistent mask\n"));	else		dprintk((KERN_INFO MYNAM			": Not using 64 bit consistent mask\n"));	ioc = kmalloc(sizeof(MPT_ADAPTER), GFP_ATOMIC);	if (ioc == NULL) {		printk(KERN_ERR MYNAM ": ERROR - Insufficient memory to add adapter!\n");		return -ENOMEM;	}	memset(ioc, 0, sizeof(MPT_ADAPTER));	ioc->alloc_total = sizeof(MPT_ADAPTER);	ioc->req_sz = MPT_DEFAULT_FRAME_SIZE;		/* avoid div by zero! */	ioc->reply_sz = MPT_REPLY_FRAME_SIZE;	ioc->pcidev = pdev;	ioc->diagPending = 0;	spin_lock_init(&ioc->diagLock);	spin_lock_init(&ioc->initializing_hba_lock);	/* Initialize the event logging.	 */	ioc->eventTypes = 0;	/* None */	ioc->eventContext = 0;	ioc->eventLogSize = 0;	ioc->events = NULL;#ifdef MFCNT	ioc->mfcnt = 0;#endif	ioc->cached_fw = NULL;	/* Initilize SCSI Config Data structure	 */	memset(&ioc->spi_data, 0, sizeof(SpiCfgData));	/* Initialize the running configQ head.	 */	INIT_LIST_HEAD(&ioc->configQ);	/* Find lookup slot. */	INIT_LIST_HEAD(&ioc->list);	ioc->id = mpt_ids++;	mem_phys = msize = 0;	port = psize = 0;	for (ii=0; ii < DEVICE_COUNT_RESOURCE; ii++) {		if (pci_resource_flags(pdev, ii) & PCI_BASE_ADDRESS_SPACE_IO) {			/* Get I/O space! */			port = pci_resource_start(pdev, ii);			psize = pci_resource_len(pdev,ii);		} else {			/* Get memmap */			mem_phys = pci_resource_start(pdev, ii);			msize = pci_resource_len(pdev,ii);			break;		}	}	ioc->mem_size = msize;	if (ii == DEVICE_COUNT_RESOURCE) {		printk(KERN_ERR MYNAM ": ERROR - MPT adapter has no memory regions defined!\n");		kfree(ioc);		return -EINVAL;	}	dinitprintk((KERN_INFO MYNAM ": MPT adapter @ %lx, msize=%dd bytes\n", mem_phys, msize));	dinitprintk((KERN_INFO MYNAM ": (port i/o @ %lx, psize=%dd bytes)\n", port, psize));	mem = NULL;	/* Get logical ptr for PciMem0 space */	/*mem = ioremap(mem_phys, msize);*/	mem = ioremap(mem_phys, 0x100);	if (mem == NULL) {		printk(KERN_ERR MYNAM ": ERROR - Unable to map adapter memory!\n");		kfree(ioc);		return -EINVAL;	}	ioc->memmap = mem;	dinitprintk((KERN_INFO MYNAM ": mem = %p, mem_phys = %lx\n", mem, mem_phys));	dinitprintk((KERN_INFO MYNAM ": facts @ %p, pfacts[0] @ %p\n",			&ioc->facts, &ioc->pfacts[0]));	ioc->mem_phys = mem_phys;	ioc->chip = (SYSIF_REGS __iomem *)mem;	/* Save Port IO values in case we need to do downloadboot */	{		u8 *pmem = (u8*)port;		ioc->pio_mem_phys = port;		ioc->pio_chip = (SYSIF_REGS __iomem *)pmem;	}	if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC909) {		ioc->prod_name = "LSIFC909";		ioc->bus_type = FC;	}	else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC929) {		ioc->prod_name = "LSIFC929";		ioc->bus_type = FC;	}	else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC919) {		ioc->prod_name = "LSIFC919";		ioc->bus_type = FC;	}	else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC929X) {		pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision);		ioc->bus_type = FC;		if (revision < XL_929) {			ioc->prod_name = "LSIFC929X";			/* 929X Chip Fix. Set Split transactions level		 	* for PCIX. Set MOST bits to zero.		 	*/			pci_read_config_byte(pdev, 0x6a, &pcixcmd);			pcixcmd &= 0x8F;			pci_write_config_byte(pdev, 0x6a, pcixcmd);		} else {			ioc->prod_name = "LSIFC929XL";			/* 929XL Chip Fix. Set MMRBC to 0x08.		 	*/			pci_read_config_byte(pdev, 0x6a, &pcixcmd);			pcixcmd |= 0x08;			pci_write_config_byte(pdev, 0x6a, pcixcmd);		}	}	else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC919X) {		ioc->prod_name = "LSIFC919X";		ioc->bus_type = FC;

⌨️ 快捷键说明

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