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

📄 mptbase.c

📁 上传linux-jx2410的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* *  linux/drivers/message/fusion/mptbase.c *      High performance SCSI + LAN / Fibre Channel device drivers. *      This is the Fusion MPT base driver which supports multiple *      (SCSI + LAN) specialized protocol drivers. *      For use with PCI chip/adapter(s): *          LSIFC9xx/LSI409xx Fibre Channel *      running LSI Logic Fusion MPT (Message Passing Technology) firmware. * *  Credits: *      There are lots of people not mentioned below that deserve credit *      and thanks but won't get it here - sorry in advance that you *      got overlooked. * *      This driver would not exist if not for Alan Cox's development *      of the linux i2o driver. * *      A special thanks to Noah Romer (LSI Logic) for tons of work *      and tough debugging on the LAN driver, especially early on;-) *      And to Roger Hickerson (LSI Logic) for tirelessly supporting *      this driver project. * *      All manner of help from Stephen Shirron (LSI Logic): *      low-level FC analysis, debug + various fixes in FCxx firmware, *      initial port to alpha platform, various driver code optimizations, *      being a faithful sounding board on all sorts of issues & ideas, *      etc. * *      A huge debt of gratitude is owed to David S. Miller (DaveM) *      for fixing much of the stupid and broken stuff in the early *      driver while porting to sparc64 platform.  THANK YOU! * *      Special thanks goes to the I2O LAN driver people at the *      University of Helsinki, who, unbeknownst to them, provided *      the inspiration and initial structure for this driver. * *      A really huge debt of gratitude is owed to Eddie C. Dost *      for gobs of hard work fixing and optimizing LAN code. *      THANK YOU! * *  Copyright (c) 1999-2001 LSI Logic Corporation *  Originally By: Steven J. Ralston *  (mailto:Steve.Ralston@lsil.com) * *  $Id: mptbase.c,v 1.1.1.1 2004/02/04 12:56:22 laputa Exp $ *//*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//*    This program is free software; you can redistribute it and/or modify    it under the terms of the GNU General Public License as published by    the Free Software Foundation; version 2 of the License.    This program is distributed in the hope that it will be useful,    but WITHOUT ANY WARRANTY; without even the implied warranty of    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    GNU General Public License for more details.    NO WARRANTY    THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR    CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT    LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,    MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is    solely responsible for determining the appropriateness of using and    distributing the Program and assumes all risks associated with its    exercise of rights under this Agreement, including but not limited to    the risks and costs of program errors, damage to or loss of data,    programs or equipment, and unavailability or interruption of operations.    DISCLAIMER OF LIABILITY    NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY    DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL    DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND    ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR    TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE    USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED    HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES    You should have received a copy of the GNU General Public License    along with this program; if not, write to the Free Software    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA*//*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/#include <linux/config.h>#include <linux/version.h>#include <linux/kernel.h>#include <linux/module.h>#include <linux/errno.h>#include <linux/init.h>#include <linux/slab.h>#include <linux/types.h>#include <linux/pci.h>#include <linux/kdev_t.h>#include <linux/blkdev.h>#include <linux/delay.h>#include <linux/proc_fs.h>#include <asm/io.h>#ifdef CONFIG_MTRR#include <asm/mtrr.h>#endif#include "mptbase.h"/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/#define my_NAME		"Fusion MPT base driver"#define my_VERSION	MPT_LINUX_VERSION_COMMON#define MYNAM		"mptbase"MODULE_AUTHOR(MODULEAUTHOR);MODULE_DESCRIPTION(my_NAME);MODULE_LICENSE("GPL");/* *  cmd line parameters */MODULE_PARM(PortIo, "0-1i");MODULE_PARM_DESC(PortIo, "[0]=Use mmap, 1=Use port io");MODULE_PARM(HardReset, "0-1i");MODULE_PARM_DESC(HardReset, "0=Disable HardReset, [1]=Enable HardReset");static int PortIo = 0;static int HardReset = 1;/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//* *  Public data... */int mpt_lan_index = 0;int mpt_stm_index = 0;void *mpt_v_ASCQ_TablePtr = NULL;const char **mpt_ScsiOpcodesPtr = NULL;int mpt_ASCQ_TableSz = 0;#define WHOINIT_UNKNOWN		0xAA/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//* *  Private data... */					/* Adapter lookup table */static MPT_ADAPTER		*mpt_adapters[MPT_MAX_ADAPTERS] = {0};static MPT_ADAPTER_TRACKER	 MptAdapters;					/* Callback lookup table */static MPT_CALLBACK		 MptCallbacks[MPT_MAX_PROTOCOL_DRIVERS];					/* Protocol driver class lookup table */static int	 		 MptDriverClass[MPT_MAX_PROTOCOL_DRIVERS];					/* Event handler lookup table */static MPT_EVHANDLER		 MptEvHandlers[MPT_MAX_PROTOCOL_DRIVERS];					/* Reset handler lookup table */static MPT_RESETHANDLER		 MptResetHandlers[MPT_MAX_PROTOCOL_DRIVERS];static int	FusionInitCalled = 0;static int	mpt_base_index = -1;/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//* *  Forward protos... */static void	mpt_interrupt(int irq, void *bus_id, struct pt_regs *r);static int	mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply);static int 	mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason);static int 	mpt_adapter_install(struct pci_dev *pdev);static void	mpt_detect_929_bound_ports(MPT_ADAPTER *this, struct pci_dev *pdev);static void	mpt_adapter_disable(MPT_ADAPTER *ioc, int freeup);static void	mpt_adapter_dispose(MPT_ADAPTER *ioc);static void	MptDisplayIocCapabilities(MPT_ADAPTER *ioc);static int	MakeIocReady(MPT_ADAPTER *ioc, int force);static u32	GetIocState(MPT_ADAPTER *ioc, int cooked);static int	GetIocFacts(MPT_ADAPTER *ioc);static int	GetPortFacts(MPT_ADAPTER *ioc, int portnum);static int	SendIocInit(MPT_ADAPTER *ioc);static int	SendPortEnable(MPT_ADAPTER *ioc, int portnum);static int	mpt_fc9x9_reset(MPT_ADAPTER *ioc, int ignore);static int	KickStart(MPT_ADAPTER *ioc, int ignore);static int	SendIocReset(MPT_ADAPTER *ioc, u8 reset_type);static int	PrimeIocFifos(MPT_ADAPTER *ioc);static int	HandShakeReqAndReply(MPT_ADAPTER *ioc, int reqBytes, u32 *req, int replyBytes, u16 *u16reply, int maxwait);static int	WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong);static int	WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong);static int	WaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong);static int	GetLanConfigPages(MPT_ADAPTER *ioc);static int	SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch);static int	SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp);static int	procmpt_create(void);#ifdef CONFIG_PROC_FSstatic int	procmpt_destroy(void);#endifstatic int	procmpt_read_summary(char *page, char **start, off_t off, int count, int *eof, void *data);static int	procmpt_read_dbg(char *page, char **start, off_t off, int count, int *eof, void *data);/*static int	procmpt_info(char *buf, char **start, off_t offset, int len);*/static int	ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *evReply, int *evHandlers);static void	mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info);static void	mpt_sp_log_info(MPT_ADAPTER *ioc, u32 log_info);static struct proc_dir_entry	*procmpt_root_dir = NULL;int		fusion_init(void);static void	fusion_exit(void);/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//* 20000207 -sralston *  GRRRRR...  IOSpace (port i/o) register access (for the 909) is back! * 20000517 -sralston *  Let's trying going back to default mmap register access... */static inline u32 CHIPREG_READ32(volatile u32 *a){	if (PortIo)		return inl((unsigned long)a);	else		return readl(a);}static inline void CHIPREG_WRITE32(volatile u32 *a, u32 v){	if (PortIo)		outl(v, (unsigned long)a);	else		writel(v, a);}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** *	mpt_interrupt - MPT adapter (IOC) specific interrupt handler. *	@irq: irq number (not used) *	@bus_id: bus identifier cookie == pointer to MPT_ADAPTER structure *	@r: pt_regs pointer (not used) * *	This routine is registered via the request_irq() kernel API call, *	and handles all interrupts generated from a specific MPT adapter *	(also referred to as a IO Controller or IOC). *	This routine must clear the interrupt from the adapter and does *	so by reading the reply FIFO.  Multiple replies may be processed *	per single call to this routine; up to MPT_MAX_REPLIES_PER_ISR *	which is currently set to 32 in mptbase.h. * *	This routine handles register-level access of the adapter but *	dispatches (calls) a protocol-specific callback routine to handle *	the protocol-specific details of the MPT request completion. */static voidmpt_interrupt(int irq, void *bus_id, struct pt_regs *r){	MPT_ADAPTER	*ioc;	MPT_FRAME_HDR	*mf;	MPT_FRAME_HDR	*mr;	u32		 pa;	u32		*m;	int		 req_idx;	int		 cb_idx;	int		 type;	int		 freeme;	int		 count = 0;	ioc = bus_id;	/*	 *  Drain the reply FIFO!	 *	 * NOTES: I've seen up to 10 replies processed in this loop, so far...	 * Update: I've seen up to 9182 replies processed in this loop! ??	 * Update: Limit ourselves to processing max of N replies	 *	(bottom of loop).	 */	while (1) {		if ((pa = CHIPREG_READ32(&ioc->chip->ReplyFifo)) == 0xFFFFFFFF)			return;		cb_idx = 0;		freeme = 0;		/*		 *  Check for non-TURBO reply!		 */		if (pa & MPI_ADDRESS_REPLY_A_BIT) {			dma_addr_t reply_dma_addr;			u16 ioc_stat;			/* non-TURBO reply!  Hmmm, something may be up...			 *  Newest turbo reply mechanism; get address			 *  via left shift 1 (get rid of MPI_ADDRESS_REPLY_A_BIT)!			 */			reply_dma_addr = (pa = (pa << 1));			/* Map DMA address of reply header to cpu address. */			m = (u32 *) ((u8 *)ioc->reply_frames +					(reply_dma_addr - ioc->reply_frames_dma));			mr = (MPT_FRAME_HDR *) m;			req_idx = le16_to_cpu(mr->u.frame.hwhdr.msgctxu.fld.req_idx);			cb_idx = mr->u.frame.hwhdr.msgctxu.fld.cb_idx;			mf = MPT_INDEX_2_MFPTR(ioc, req_idx);			dprintk((KERN_INFO MYNAM ": %s: Got non-TURBO reply=%p\n",					ioc->name, mr));			DBG_DUMP_REPLY_FRAME(mr)			/* NEW!  20010301 -sralston			 *  Check/log IOC log info			 */			ioc_stat = le16_to_cpu(mr->u.reply.IOCStatus);	 		if (ioc_stat & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {				u32	 log_info = le32_to_cpu(mr->u.reply.IOCLogInfo);				if ((int)ioc->chip_type <= (int)FC929)					mpt_fc_log_info(ioc, log_info);				else					mpt_sp_log_info(ioc, log_info);			}		} else {			/*			 *  Process turbo (context) reply...			 */			dirqprintk((KERN_INFO MYNAM ": %s: Got TURBO reply(=%08x)\n", ioc->name, pa));			type = (pa >> MPI_CONTEXT_REPLY_TYPE_SHIFT);			if (type == MPI_CONTEXT_REPLY_TYPE_SCSI_TARGET) {				cb_idx = mpt_stm_index;				mf = NULL;				mr = (MPT_FRAME_HDR *) CAST_U32_TO_PTR(pa);			} else if (type == MPI_CONTEXT_REPLY_TYPE_LAN) {				cb_idx = mpt_lan_index;				/*				 * BUG FIX!  20001218 -sralston				 *  Blind set of mf to NULL here was fatal				 *  after lan_reply says "freeme"				 *  Fix sort of combined with an optimization here;				 *  added explicit check for case where lan_reply				 *  was just returning 1 and doing nothing else.				 *  For this case skip the callback, but set up				 *  proper mf value first here:-)				 */				if ((pa & 0x58000000) == 0x58000000) {					req_idx = pa & 0x0000FFFF;					mf = MPT_INDEX_2_MFPTR(ioc, req_idx);					freeme = 1;					/*					 *  IMPORTANT!  Invalidate the callback!					 */					cb_idx = 0;				} else {					mf = NULL;				}				mr = (MPT_FRAME_HDR *) CAST_U32_TO_PTR(pa);			} else {				req_idx = pa & 0x0000FFFF;				cb_idx = (pa & 0x00FF0000) >> 16;				mf = MPT_INDEX_2_MFPTR(ioc, req_idx);				mr = NULL;			}			pa = 0;					/* No reply flush! */		}		/*  Check for (valid) IO callback!  */		if (cb_idx) {			/*  Do the callback!  */			freeme = (*(MptCallbacks[cb_idx]))(ioc, mf, mr);		}		if (pa) {			/*  Flush (non-TURBO) reply with a WRITE!  */			CHIPREG_WRITE32(&ioc->chip->ReplyFifo, pa);		}		if (freeme) {			unsigned long flags;			/*  Put Request back on FreeQ!  */			spin_lock_irqsave(&ioc->FreeQlock, flags);			Q_ADD_TAIL(&ioc->FreeQ, &mf->u.frame.linkage, MPT_FRAME_HDR);			spin_unlock_irqrestore(&ioc->FreeQlock, flags);		}		count++;		dirqprintk((KERN_INFO MYNAM ": %s: ISR processed frame #%d\n", ioc->name, count));		mb();		if (count >= MPT_MAX_REPLIES_PER_ISR) {			dirqprintk((KERN_INFO MYNAM ": %s: ISR processed %d replies.",					ioc->name, count));			dirqprintk((" Giving this ISR a break!\n"));			return;		}	}	/* drain reply FIFO */}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//* *	mpt_base_reply - MPT base driver's callback routine; all base driver *	"internal" request/reply processing is routed here. *	Currently used for EventNotification and EventAck handling. *	@ioc: Pointer to MPT_ADAPTER structure *	@mf: Pointer to original MPT request frame *	@reply: Pointer to MPT reply frame (NULL if TurboReply) * *	Returns 1 indicating original alloc'd request frame ptr *	should be freed, or 0 if it shouldn't. */static intmpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply){	int freereq = 1;	u8 func;	dprintk((KERN_INFO MYNAM ": %s: mpt_base_reply() called\n", ioc->name));	if ((mf == NULL) ||	    (mf >= MPT_INDEX_2_MFPTR(ioc, ioc->req_depth))) {		printk(KERN_ERR MYNAM ": %s: ERROR - NULL or BAD request frame ptr! (=%p)\n",				ioc->name, mf);		return 1;	}	if (reply == NULL) {		dprintk((KERN_ERR MYNAM ": %s: ERROR - Unexpected NULL Event (turbo?) reply!\n",				ioc->name));		return 1;	}	if (!(reply->u.hdr.MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY)) {		dmfprintk((KERN_INFO MYNAM ": Original request frame (@%p) header\n", mf));		DBG_DUMP_REQUEST_FRAME_HDR(mf)	}	func = reply->u.hdr.Function;	dprintk((KERN_INFO MYNAM ": %s: mpt_base_reply, Function=%02Xh\n",			ioc->name, func));	if (func == MPI_FUNCTION_EVENT_NOTIFICATION) {		EventNotificationReply_t *pEvReply = (EventNotificationReply_t *) reply;		int evHandlers = 0;		int results;		results = ProcessEventNotification(ioc, pEvReply, &evHandlers);		if (results != evHandlers) {			/* CHECKME! Any special handling needed here? */			dprintk((KERN_WARNING MYNAM ": %s: Hmmm... Called %d event handlers, sum results = %d\n",

⌨️ 快捷键说明

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