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

📄 mptbase.c

📁 linux-2.4.29操作系统的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
			printk("\n");		}#endif		mf_dma_addr = iocp->req_frames_low_dma + req_offset;		CHIPREG_WRITE32(&iocp->chip->RequestFifo, mf_dma_addr);	} else {		printk (KERN_ERR "mpt_put_msg_frame: Invalid iocid=%d\n", iocid);	}}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** *	mpt_free_msg_frame - Place MPT request frame back on FreeQ. *	@handle: Handle of registered MPT protocol driver *	@iocid: IOC unique identifier (integer) *	@mf: Pointer to MPT request frame * *	This routine places a MPT request frame back on the MPT adapter's *	FreeQ. */voidmpt_free_msg_frame(int handle, int iocid, MPT_FRAME_HDR *mf){	MPT_ADAPTER *iocp;	unsigned long flags;	iocp = mpt_adapters[iocid];	if (iocp != NULL) {		/*  Put Request back on FreeQ!  */		spin_lock_irqsave(&iocp->FreeQlock, flags);		Q_ADD_TAIL(&iocp->FreeQ, &mf->u.frame.linkage, MPT_FRAME_HDR);#ifdef MFCNT		iocp->mfcnt--;#endif		spin_unlock_irqrestore(&iocp->FreeQlock, flags);	}}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** *	mpt_add_sge - Place a simple SGE at address pAddr. *	@pAddr: virtual address for SGE *	@flagslength: SGE flags and data transfer length *	@dma_addr: Physical address * *	This routine places a MPT request frame back on the MPT adapter's *	FreeQ. */voidmpt_add_sge(char *pAddr, u32 flagslength, dma_addr_t dma_addr){	if (sizeof(dma_addr_t) == sizeof(u64)) {		SGESimple64_t *pSge = (SGESimple64_t *) pAddr;		u32 tmp = dma_addr & 0xFFFFFFFF;		pSge->FlagsLength = cpu_to_le32(flagslength);		pSge->Address.Low = cpu_to_le32(tmp);		tmp = (u32) ((u64)dma_addr >> 32);		pSge->Address.High = cpu_to_le32(tmp);	} else {		SGESimple32_t *pSge = (SGESimple32_t *) pAddr;		pSge->FlagsLength = cpu_to_le32(flagslength);		pSge->Address = cpu_to_le32(dma_addr);	}}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** *	mpt_add_chain - Place a chain SGE at address pAddr. *	@pAddr: virtual address for SGE *	@next: nextChainOffset value (u32's) *	@length: length of next SGL segment *	@dma_addr: Physical address * *	This routine places a MPT request frame back on the MPT adapter's *	FreeQ. */voidmpt_add_chain(char *pAddr, u8 next, u16 length, dma_addr_t dma_addr){	if (sizeof(dma_addr_t) == sizeof(u64)) {		SGEChain64_t *pChain = (SGEChain64_t *) pAddr;		u32 tmp = dma_addr & 0xFFFFFFFF;		pChain->Length = cpu_to_le16(length);		pChain->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT | mpt_addr_size();		pChain->NextChainOffset = next;		pChain->Address.Low = cpu_to_le32(tmp);		tmp = (u32) ((u64)dma_addr >> 32);		pChain->Address.High = cpu_to_le32(tmp);	} else {		SGEChain32_t *pChain = (SGEChain32_t *) pAddr;		pChain->Length = cpu_to_le16(length);		pChain->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT | mpt_addr_size();		pChain->NextChainOffset = next;		pChain->Address = cpu_to_le32(dma_addr);	}}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** *	mpt_send_handshake_request - Send MPT request via doorbell *	handshake method. *	@handle: Handle of registered MPT protocol driver *	@iocid: IOC unique identifier (integer) *	@reqBytes: Size of the request in bytes *	@req: Pointer to MPT request frame *	@sleepFlag: Use schedule if CAN_SLEEP else use udelay. * *	This routine is used exclusively to send MptScsiTaskMgmt *	requests since they are required to be sent via doorbell handshake. * *	NOTE: It is the callers responsibility to byte-swap fields in the *	request which are greater than 1 byte in size. * *	Returns 0 for success, non-zero for failure. */intmpt_send_handshake_request(int handle, int iocid, int reqBytes, u32 *req, int sleepFlag){	MPT_ADAPTER	*iocp;	int		 r = 0;	iocp = mpt_adapters[iocid];	if (iocp != NULL) {		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(iocp,(MPT_FRAME_HDR*)req);		if (reqBytes >= 12 && ii >= 0 && ii < iocp->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(&iocp->chip->IntStatus, 0);		CHIPREG_WRITE32(&iocp->chip->Doorbell,				((MPI_FUNCTION_HANDSHAKE<<MPI_DOORBELL_FUNCTION_SHIFT) |				 ((reqBytes/4)<<MPI_DOORBELL_ADD_DWORDS_SHIFT)));		/* Wait for IOC doorbell int */		if ((ii = WaitForDoorbellInt(iocp, 5, sleepFlag)) < 0) {			return ii;		}		/* Read doorbell and check for active bit */		if (!(CHIPREG_READ32(&iocp->chip->Doorbell) & MPI_DOORBELL_ACTIVE))				return -5;		dhsprintk((KERN_INFO MYNAM ": %s: mpt_send_handshake_request start, WaitCnt=%d\n",				iocp->name, ii));		CHIPREG_WRITE32(&iocp->chip->IntStatus, 0);		if ((r = WaitForDoorbellAck(iocp, 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(&iocp->chip->Doorbell, word);			if ((r = WaitForDoorbellAck(iocp, 5, sleepFlag)) < 0) {				r = -3;				break;			}		}		if (r >= 0 && WaitForDoorbellInt(iocp, 10, sleepFlag) >= 0)			r = 0;		else			r = -4;		/* Make sure there are no doorbells */		CHIPREG_WRITE32(&iocp->chip->IntStatus, 0);	}	return r;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** *	mpt_adapter_find_first - Find first MPT adapter pointer. * *	Returns first MPT adapter pointer or %NULL if no MPT adapters *	are present. */MPT_ADAPTER *mpt_adapter_find_first(void){	MPT_ADAPTER *this;	if (! Q_IS_EMPTY(&MptAdapters))		this = MptAdapters.head;	else		this = NULL;	return this;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** *	mpt_adapter_find_next - Find next MPT adapter pointer. *	@prev: Pointer to previous MPT adapter * *	Returns next MPT adapter pointer or %NULL if there are no more. */MPT_ADAPTER *mpt_adapter_find_next(MPT_ADAPTER *prev){	MPT_ADAPTER *next;	if (prev && (prev->forw != (MPT_ADAPTER*)&MptAdapters.head))		next = prev->forw;	else		next = NULL;	return next;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//* *	mpt_pci_scan - Scan PCI devices for MPT adapters. * *	Returns count of MPT adapters found, keying off of PCI vendor and *	device_id's. */static int __initmpt_pci_scan(void){	struct pci_dev *pdev;	struct pci_dev *pdev2;	int found = 0;	int count = 0;	int r;	dprintk((KERN_INFO MYNAM ": Checking for MPT adapters...\n"));	/*	 *  NOTE: The 929, 929X, 1030 and 1035 will appear as 2 separate PCI devices,	 *  one for each channel.	 */	pci_for_each_dev(pdev) {		pdev2 = NULL;		if (pdev->vendor != 0x1000)			continue;		if ((pdev->device != MPI_MANUFACTPAGE_DEVICEID_FC909) &&		    (pdev->device != MPI_MANUFACTPAGE_DEVICEID_FC929) &&		    (pdev->device != MPI_MANUFACTPAGE_DEVICEID_FC919) &&		    (pdev->device != MPI_MANUFACTPAGE_DEVICEID_FC929X) &&		    (pdev->device != MPI_MANUFACTPAGE_DEVICEID_FC919X) &&		    (pdev->device != MPI_MANUFACTPAGE_DEVID_53C1030) &&		    (pdev->device != MPI_MANUFACTPAGE_DEVID_1030_53C1035) &&		    1) {			dprintk((KERN_INFO MYNAM ": Skipping LSI device=%04xh\n", pdev->device));			continue;		}		/* GRRRRR		 * dual function devices (929, 929X, 1030, 1035) may be presented in Func 1,0 order,		 * but we'd really really rather have them in Func 0,1 order.		 * Do some kind of look ahead here...		 */		if (pdev->devfn & 1) {			pdev2 = pci_peek_next_dev(pdev);			if (pdev2 && (pdev2->vendor == 0x1000) &&			    (PCI_SLOT(pdev2->devfn) == PCI_SLOT(pdev->devfn)) &&			    (pdev2->device == pdev->device) &&			    (pdev2->bus->number == pdev->bus->number) &&			    !(pdev2->devfn & 1)) {				dprintk((KERN_INFO MYNAM ": MPT adapter found: PCI bus/dfn=%02x/%02xh, class=%08x, id=%xh\n",					pdev2->bus->number, pdev2->devfn, pdev2->class, pdev2->device));				found++;				if ((r = mpt_adapter_install(pdev2)) == 0)					count++;			} else {				pdev2 = NULL;			}		}		dprintk((KERN_INFO MYNAM ": MPT adapter found: PCI bus/dfn=%02x/%02xh, class=%08x, id=%xh\n",			 pdev->bus->number, pdev->devfn, pdev->class, pdev->device));		found++;		if ((r = mpt_adapter_install(pdev)) == 0)			count++;		if (pdev2)			pdev = pdev2;	}	printk(KERN_INFO MYNAM ": %d MPT adapter%s found, %d installed.\n",		 found, (found==1) ? "" : "s", count);	if (!found || !count) {		fusion_exit();		return -ENODEV;	}#ifdef CONFIG_PROC_FS	(void) procmpt_create();#endif	return count;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** *	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 *p;	*iocpp = NULL;	if (iocid >= MPT_MAX_ADAPTERS)		return -1;	p = mpt_adapters[iocid];	if (p == NULL)		return -1;	*iocpp = p;	return iocid;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//* *	mpt_adapter_install - 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 */static int __initmpt_adapter_install(struct pci_dev *pdev){	MPT_ADAPTER	*ioc;	u8		*mem;	unsigned long	 mem_phys;	unsigned long	 port;	u32		 msize;	u32		 psize;	int		 ii;	int		 r = -ENODEV;	u64		 mask = 0xffffffffffffffffULL;	u8		 revision;	u8		 pcixcmd;	if (pci_enable_device(pdev))		return r;	/* For some kernels, broken kernel limits memory allocation for target mode	 * driver. Shirron. Fixed in 2.4.20-8	 * if ((sizeof(dma_addr_t) == sizeof(u64)) && (!pci_set_dma_mask(pdev, mask))) {	 */	if ((!pci_set_dma_mask(pdev, mask))) {		dprintk((KERN_INFO MYNAM ": 64 BIT PCI BUS DMA ADDRESSING SUPPORTED\n"));	} else {		if (pci_set_dma_mask(pdev, (u64) 0xffffffff)) {			printk(KERN_WARNING MYNAM				": 32 BIT PCI BUS DMA ADDRESSING NOT SUPPORTED\n");			return r;		}	}	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);	/* 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(ScsiCfgData));	/* Initialize the running configQ head.	 */	Q_INIT(&ioc->configQ, Q_ITEM);	/* Find lookup slot. */	for (ii=0; ii < MPT_MAX_ADAPTERS; ii++) {		if (mpt_adapters[ii] == NULL) {			ioc->id = ii;		/* Assign adapter unique id (lookup) */			break;		}	}	if (ii == MPT_MAX_ADAPTERS) {		printk(KERN_ERR MYNAM ": ERROR - mpt_adapters[%d] table overflow!\n", ii);		kfree(ioc);		return -ENFILE;	}

⌨️ 快捷键说明

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