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

📄 mptbase.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
		CONFIGPARMS *pCfg;		unsigned long flags;		dcprintk((MYIOC_s_INFO_FMT "config_complete (mf=%p,mr=%p)\n",				ioc->name, mf, reply));		pCfg = * ((CONFIGPARMS **)((u8 *) mf + ioc->req_sz - sizeof(void *)));		if (pCfg) {			/* disable timer and remove from linked list */			del_timer(&pCfg->timer);			spin_lock_irqsave(&ioc->FreeQlock, flags);			list_del(&pCfg->linkage);			spin_unlock_irqrestore(&ioc->FreeQlock, flags);			/*			 *	If IOC Status is SUCCESS, save the header			 *	and set the status code to GOOD.			 */			pCfg->status = MPT_CONFIG_ERROR;			if (reply) {				ConfigReply_t	*pReply = (ConfigReply_t *)reply;				u16		 status;				status = le16_to_cpu(pReply->IOCStatus) & MPI_IOCSTATUS_MASK;				dcprintk((KERN_NOTICE "  IOCStatus=%04xh, IOCLogInfo=%08xh\n",				     status, le32_to_cpu(pReply->IOCLogInfo)));				pCfg->status = status;				if (status == MPI_IOCSTATUS_SUCCESS) {					if ((pReply->Header.PageType &					    MPI_CONFIG_PAGETYPE_MASK) ==					    MPI_CONFIG_PAGETYPE_EXTENDED) {						pCfg->cfghdr.ehdr->ExtPageLength =						    le16_to_cpu(pReply->ExtPageLength);						pCfg->cfghdr.ehdr->ExtPageType =						    pReply->ExtPageType;					}					pCfg->cfghdr.hdr->PageVersion = pReply->Header.PageVersion;					/* If this is a regular header, save PageLength. */					/* LMP Do this better so not using a reserved field! */					pCfg->cfghdr.hdr->PageLength = pReply->Header.PageLength;					pCfg->cfghdr.hdr->PageNumber = pReply->Header.PageNumber;					pCfg->cfghdr.hdr->PageType = pReply->Header.PageType;				}			}			/*			 *	Wake up the original calling thread			 */			pCfg->wait_done = 1;			wake_up(&mpt_waitq);		}	} else if (func == MPI_FUNCTION_SAS_IO_UNIT_CONTROL) {		/* we should be always getting a reply frame */		memcpy(ioc->persist_reply_frame, reply,		    min(MPT_DEFAULT_FRAME_SIZE,		    4*reply->u.reply.MsgLength));		del_timer(&ioc->persist_timer);		ioc->persist_wait_done = 1;		wake_up(&mpt_waitq);	} else {		printk(MYIOC_s_ERR_FMT "Unexpected msg function (=%02Xh) reply received!\n",				ioc->name, func);	}	/*	 *	Conditionally tell caller to free the original	 *	EventNotification/EventAck/unexpected request frame!	 */	return freereq;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** *	mpt_register - Register protocol-specific main callback handler. *	@cbfunc: callback function pointer *	@dclass: Protocol driver's class (%MPT_DRIVER_CLASS enum value) * *	This routine is called by a protocol-specific driver (SCSI host, *	LAN, SCSI target) to register it's reply callback routine.  Each *	protocol-specific driver must do this before it will be able to *	use any IOC resources, such as obtaining request frames. * *	NOTES: The SCSI protocol driver currently calls this routine thrice *	in order to register separate callbacks; one for "normal" SCSI IO; *	one for MptScsiTaskMgmt requests; one for Scan/DV requests. * *	Returns a positive integer valued "handle" in the *	range (and S.O.D. order) {N,...,7,6,5,...,1} if successful. *	Any non-positive return value (including zero!) should be considered *	an error by the caller. */intmpt_register(MPT_CALLBACK cbfunc, MPT_DRIVER_CLASS dclass){	int i;	last_drv_idx = -1;	/*	 *  Search for empty callback slot in this order: {N,...,7,6,5,...,1}	 *  (slot/handle 0 is reserved!)	 */	for (i = MPT_MAX_PROTOCOL_DRIVERS-1; i; i--) {		if (MptCallbacks[i] == NULL) {			MptCallbacks[i] = cbfunc;			MptDriverClass[i] = dclass;			MptEvHandlers[i] = NULL;			last_drv_idx = i;			break;		}	}	return last_drv_idx;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** *	mpt_deregister - Deregister a protocol drivers resources. *	@cb_idx: previously registered callback handle * *	Each protocol-specific driver should call this routine when it's *	module is unloaded. */voidmpt_deregister(int cb_idx){	if ((cb_idx >= 0) && (cb_idx < MPT_MAX_PROTOCOL_DRIVERS)) {		MptCallbacks[cb_idx] = NULL;		MptDriverClass[cb_idx] = MPTUNKNOWN_DRIVER;		MptEvHandlers[cb_idx] = NULL;		last_drv_idx++;	}}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** *	mpt_event_register - Register protocol-specific event callback *	handler. *	@cb_idx: previously registered (via mpt_register) callback handle *	@ev_cbfunc: callback function * *	This routine can be called by one or more protocol-specific drivers *	if/when they choose to be notified of MPT events. * *	Returns 0 for success. */intmpt_event_register(int cb_idx, MPT_EVHANDLER ev_cbfunc){	if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)		return -1;	MptEvHandlers[cb_idx] = ev_cbfunc;	return 0;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** *	mpt_event_deregister - Deregister protocol-specific event callback *	handler. *	@cb_idx: previously registered callback handle * *	Each protocol-specific driver should call this routine *	when it does not (or can no longer) handle events, *	or when it's module is unloaded. */voidmpt_event_deregister(int cb_idx){	if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)		return;	MptEvHandlers[cb_idx] = NULL;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** *	mpt_reset_register - Register protocol-specific IOC reset handler. *	@cb_idx: previously registered (via mpt_register) callback handle *	@reset_func: reset function * *	This routine can be called by one or more protocol-specific drivers *	if/when they choose to be notified of IOC resets. * *	Returns 0 for success. */intmpt_reset_register(int cb_idx, MPT_RESETHANDLER reset_func){	if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)		return -1;	MptResetHandlers[cb_idx] = reset_func;	return 0;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** *	mpt_reset_deregister - Deregister protocol-specific IOC reset handler. *	@cb_idx: previously registered callback handle * *	Each protocol-specific driver should call this routine *	when it does not (or can no longer) handle IOC reset handling, *	or when it's module is unloaded. */voidmpt_reset_deregister(int cb_idx){	if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)		return;	MptResetHandlers[cb_idx] = NULL;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** *	mpt_device_driver_register - Register device driver hooks */intmpt_device_driver_register(struct mpt_pci_driver * dd_cbfunc, int cb_idx){	MPT_ADAPTER	*ioc;	if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS) {		return -EINVAL;	}	MptDeviceDriverHandlers[cb_idx] = dd_cbfunc;	/* call per pci device probe entry point */	list_for_each_entry(ioc, &ioc_list, list) {		if(dd_cbfunc->probe) {			dd_cbfunc->probe(ioc->pcidev,			  ioc->pcidev->driver->id_table);  		}	 }	return 0;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** *	mpt_device_driver_deregister - DeRegister device driver hooks */voidmpt_device_driver_deregister(int cb_idx){	struct mpt_pci_driver *dd_cbfunc;	MPT_ADAPTER	*ioc;	if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)		return;	dd_cbfunc = MptDeviceDriverHandlers[cb_idx];	list_for_each_entry(ioc, &ioc_list, list) {		if (dd_cbfunc->remove)			dd_cbfunc->remove(ioc->pcidev);	}	MptDeviceDriverHandlers[cb_idx] = NULL;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** *	mpt_get_msg_frame - Obtain a MPT request frame from the pool (of 1024) *	allocated per MPT adapter. *	@handle: Handle of registered MPT protocol driver *	@ioc: Pointer to MPT adapter structure * *	Returns pointer to a MPT request frame or %NULL if none are available *	or IOC is not active. */MPT_FRAME_HDR*mpt_get_msg_frame(int handle, MPT_ADAPTER *ioc){	MPT_FRAME_HDR *mf;	unsigned long flags;	u16	 req_idx;	/* Request index */	/* validate handle and ioc identifier */#ifdef MFCNT	if (!ioc->active)		printk(KERN_WARNING "IOC Not Active! mpt_get_msg_frame returning NULL!\n");#endif	/* If interrupts are not attached, do not return a request frame */	if (!ioc->active)		return NULL;	spin_lock_irqsave(&ioc->FreeQlock, flags);	if (!list_empty(&ioc->FreeQ)) {		int req_offset;		mf = list_entry(ioc->FreeQ.next, MPT_FRAME_HDR,				u.frame.linkage.list);		list_del(&mf->u.frame.linkage.list);		mf->u.frame.linkage.arg1 = 0;		mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle;	/* byte */		req_offset = (u8 *)mf - (u8 *)ioc->req_frames;								/* u16! */		req_idx = req_offset / ioc->req_sz;		mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(req_idx);		mf->u.frame.hwhdr.msgctxu.fld.rsvd = 0;		ioc->RequestNB[req_idx] = ioc->NB_for_64_byte_frame; /* Default, will be changed if necessary in SG generation */#ifdef MFCNT		ioc->mfcnt++;#endif	}	else		mf = NULL;	spin_unlock_irqrestore(&ioc->FreeQlock, flags);#ifdef MFCNT	if (mf == NULL)		printk(KERN_WARNING "IOC Active. No free Msg Frames! Count 0x%x Max 0x%x\n", ioc->mfcnt, ioc->req_depth);	mfcounter++;	if (mfcounter == PRINT_MF_COUNT)		printk(KERN_INFO "MF Count 0x%x Max 0x%x \n", ioc->mfcnt, ioc->req_depth);#endif	dmfprintk((KERN_INFO MYNAM ": %s: mpt_get_msg_frame(%d,%d), got mf=%p\n",			ioc->name, handle, ioc->id, mf));	return mf;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** *	mpt_put_msg_frame - Send a protocol specific MPT request frame *	to a IOC. *	@handle: Handle of registered MPT protocol driver *	@ioc: Pointer to MPT adapter structure *	@mf: Pointer to MPT request frame * *	This routine posts a MPT request frame to the request post FIFO of a *	specific MPT adapter. */voidmpt_put_msg_frame(int handle, MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf){	u32 mf_dma_addr;	int req_offset;	u16	 req_idx;	/* Request index */	/* ensure values are reset properly! */	mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle;		/* byte */	req_offset = (u8 *)mf - (u8 *)ioc->req_frames;								/* u16! */	req_idx = req_offset / ioc->req_sz;	mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(req_idx);	mf->u.frame.hwhdr.msgctxu.fld.rsvd = 0;#ifdef MPT_DEBUG_MSG_FRAME	{		u32	*m = mf->u.frame.hwhdr.__hdr;		int	 ii, n;		printk(KERN_INFO MYNAM ": %s: About to Put msg frame @ %p:\n" KERN_INFO " ",				ioc->name, m);		n = ioc->req_sz/4 - 1;		while (m[n] == 0)			n--;		for (ii=0; ii<=n; ii++) {			if (ii && ((ii%8)==0))				printk("\n" KERN_INFO " ");			printk(" %08x", le32_to_cpu(m[ii]));		}		printk("\n");	}#endif	mf_dma_addr = (ioc->req_frames_low_dma + req_offset) | ioc->RequestNB[req_idx];	dsgprintk((MYIOC_s_INFO_FMT "mf_dma_addr=%x req_idx=%d RequestNB=%x\n", ioc->name, mf_dma_addr, req_idx, ioc->RequestNB[req_idx]));	CHIPREG_WRITE32(&ioc->chip->RequestFifo, mf_dma_addr);}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** *	mpt_free_msg_frame - Place MPT request frame back on FreeQ. *	@handle: Handle of registered MPT protocol driver *	@ioc: Pointer to MPT adapter structure *	@mf: Pointer to MPT request frame * *	This routine places a MPT request frame back on the MPT adapter's *	FreeQ. */voidmpt_free_msg_frame(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf){	unsigned long flags;	/*  Put Request back on FreeQ!  */	spin_lock_irqsave(&ioc->FreeQlock, flags);	mf->u.frame.linkage.arg1 = 0xdeadbeaf; /* signature to know if this mf is freed */	list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeQ);#ifdef MFCNT	ioc->mfcnt--;#endif	spin_unlock_irqrestore(&ioc->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_send_handshake_request - Send MPT request via doorbell *	handshake method. *	@handle: Handle of registered MPT protocol driver *	@ioc: Pointer to MPT adapter structure *	@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. *

⌨️ 快捷键说明

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