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

📄 isp.c

📁 这个linux源代码是很全面的~基本完整了~使用c编译的~由于时间问题我没有亲自测试~但就算用来做参考资料也是非常好的
💻 C
📖 第 1 页 / 共 5 页
字号:
/* @(#)isp.c 1.67 *//* * Machine and OS Independent (well, as best as possible) * code for the Qlogic ISP SCSI adapters. * * Copyright (c) 1997, 1998, 1999, 2000, 2001 by Matthew Jacob * Feral Software * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice immediately at the beginning of the file, without modification, *    this list of conditions, and the following disclaimer. * 2. The name of the author may not be used to endorse or promote products *    derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * 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 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. *//* * Inspiration and ideas about this driver are from Erik Moe's Linux driver * (qlogicisp.c) and Dave Miller's SBus version of same (qlogicisp.c). Some * ideas dredged from the Solaris driver. *//* * Include header file appropriate for platform we're building on. */#ifdef	__NetBSD__#include <dev/ic/isp_netbsd.h>#endif#ifdef	__FreeBSD__#include <dev/isp/isp_freebsd.h>#endif#ifdef	__OpenBSD__#include <dev/ic/isp_openbsd.h>#endif#ifdef	__linux__#include "isp_linux.h"#endif#ifdef	__svr4__#include "isp_solaris.h"#endif/* * General defines */#define	MBOX_DELAY_COUNT	1000000 / 100/* * Local static data */static const char portshift[] =    "Target %d Loop ID 0x%x (Port 0x%x) => Loop 0x%x (Port 0x%x)";static const char portdup[] =    "Target %d duplicates Target %d- killing off both";static const char retained[] =    "Retaining Loop ID 0x%x for Target %d (Port 0x%x)";static const char lretained[] =    "Retained login of Target %d (Loop ID 0x%x) Port 0x%x";static const char plogout[] =    "Logging out Target %d at Loop ID 0x%x (Port 0x%x)";static const char plogierr[] =    "Command Error in PLOGI for Port 0x%x (0x%x)";static const char nopdb[] =    "Could not get PDB for Device @ Port 0x%x";static const char pdbmfail1[] =    "PDB Loop ID info for Device @ Port 0x%x does not match up (0x%x)";static const char pdbmfail2[] =    "PDB Port info for Device @ Port 0x%x does not match up (0x%x)";static const char ldumped[] =    "Target %d (Loop ID 0x%x) Port 0x%x dumped after login info mismatch";static const char notresp[] =  "Not RESPONSE in RESPONSE Queue (type 0x%x) @ idx %d (next %d) nlooked %d";static const char xact1[] =    "HBA attempted queued transaction with disconnect not set for %d.%d.%d";static const char xact2[] =    "HBA attempted queued transaction to target routine %d on target %d bus %d";static const char xact3[] =    "HBA attempted queued cmd for %d.%d.%d when queueing disabled";static const char pskip[] =    "SCSI phase skipped for target %d.%d.%d";static const char topology[] =    "Loop ID %d, AL_PA 0x%x, Port ID 0x%x, Loop State 0x%x, Topology '%s'";static const char swrej[] =    "Fabric Nameserver rejected %s (Reason=0x%x Expl=0x%x) for Port ID 0x%x";static const char finmsg[] =    "(%d.%d.%d): FIN dl%d resid %d STS 0x%x SKEY %c XS_ERR=0x%x";static const char sc0[] =    "%s CHAN %d FTHRSH %d IID %d RESETD %d RETRYC %d RETRYD %d ASD 0x%x";static const char sc1[] =    "%s RAAN 0x%x DLAN 0x%x DDMAB 0x%x CDMAB 0x%x SELTIME %d MQD %d";static const char sc2[] = "%s CHAN %d TGT %d FLAGS 0x%x 0x%x/0x%x";static const char sc3[] = "Generated";static const char sc4[] = "NVRAM";/* * Local function prototypes. */static int isp_parse_async(struct ispsoftc *, u_int16_t);static int isp_handle_other_response(struct ispsoftc *, int, isphdr_t *,    u_int16_t *);static voidisp_parse_status(struct ispsoftc *, ispstatusreq_t *, XS_T *);static void isp_fastpost_complete(struct ispsoftc *, u_int16_t);static int isp_mbox_continue(struct ispsoftc *);static void isp_scsi_init(struct ispsoftc *);static void isp_scsi_channel_init(struct ispsoftc *, int);static void isp_fibre_init(struct ispsoftc *);static void isp_mark_getpdb_all(struct ispsoftc *);static int isp_getmap(struct ispsoftc *, fcpos_map_t *);static int isp_getpdb(struct ispsoftc *, int, isp_pdb_t *);static u_int64_t isp_get_portname(struct ispsoftc *, int, int);static int isp_fclink_test(struct ispsoftc *, int);static char *isp2100_fw_statename(int);static int isp_pdb_sync(struct ispsoftc *);static int isp_scan_loop(struct ispsoftc *);static int isp_fabric_mbox_cmd(struct ispsoftc *, mbreg_t *);static int isp_scan_fabric(struct ispsoftc *, int);static void isp_register_fc4_type(struct ispsoftc *);static void isp_fw_state(struct ispsoftc *);static void isp_mboxcmd_qnw(struct ispsoftc *, mbreg_t *, int);static void isp_mboxcmd(struct ispsoftc *, mbreg_t *, int);static void isp_update(struct ispsoftc *);static void isp_update_bus(struct ispsoftc *, int);static void isp_setdfltparm(struct ispsoftc *, int);static int isp_read_nvram(struct ispsoftc *);static void isp_rdnvram_word(struct ispsoftc *, int, u_int16_t *);static void isp_parse_nvram_1020(struct ispsoftc *, u_int8_t *);static void isp_parse_nvram_1080(struct ispsoftc *, int, u_int8_t *);static void isp_parse_nvram_12160(struct ispsoftc *, int, u_int8_t *);static void isp_parse_nvram_2100(struct ispsoftc *, u_int8_t *);/* * Reset Hardware. * * Hit the chip over the head, download new f/w if available and set it running. * * Locking done elsewhere. */voidisp_reset(struct ispsoftc *isp){	mbreg_t mbs;	u_int16_t code_org;	int loops, i, touched, dodnld = 1;	char *btype = "????";	isp->isp_state = ISP_NILSTATE;	/*	 * Basic types (SCSI, FibreChannel and PCI or SBus)	 * have been set in the MD code. We figure out more	 * here. Possibly more refined types based upon PCI	 * identification. Chip revision has been gathered.	 *	 * After we've fired this chip up, zero out the conf1 register	 * for SCSI adapters and do other settings for the 2100.	 */	/*	 * Get the current running firmware revision out of the	 * chip before we hit it over the head (if this is our	 * first time through). Note that we store this as the	 * 'ROM' firmware revision- which it may not be. In any	 * case, we don't really use this yet, but we may in	 * the future.	 */	if ((touched = isp->isp_touched) == 0) {		/*		 * First see whether or not we're sitting in the ISP PROM.		 * If we've just been reset, we'll have the string "ISP   "		 * spread through outgoing mailbox registers 1-3. We do		 * this for PCI cards because otherwise we really don't		 * know what state the card is in and we could hang if		 * we try this command otherwise.		 *		 * For SBus cards, we just do this because they almost		 * certainly will be running firmware by now.		 */		if (ISP_READ(isp, OUTMAILBOX1) != 0x4953 ||		    ISP_READ(isp, OUTMAILBOX2) != 0x5020 ||		    ISP_READ(isp, OUTMAILBOX3) != 0x2020) {			/*			 * Just in case it was paused...			 */			ISP_WRITE(isp, HCCR, HCCR_CMD_RELEASE);			mbs.param[0] = MBOX_ABOUT_FIRMWARE;			isp_mboxcmd(isp, &mbs, MBLOGNONE);			if (mbs.param[0] == MBOX_COMMAND_COMPLETE) {				isp->isp_romfw_rev[0] = mbs.param[1];				isp->isp_romfw_rev[1] = mbs.param[2];				isp->isp_romfw_rev[2] = mbs.param[3];			}		}		isp->isp_touched = 1;	}	DISABLE_INTS(isp);	/*	 * Set up default request/response queue in-pointer/out-pointer	 * register indices.	 */	if (IS_23XX(isp)) {		isp->isp_rqstinrp = BIU_REQINP;		isp->isp_rqstoutrp = BIU_REQOUTP;		isp->isp_respinrp = BIU_RSPINP;		isp->isp_respoutrp = BIU_RSPOUTP;	} else {		isp->isp_rqstinrp = INMAILBOX4;		isp->isp_rqstoutrp = OUTMAILBOX4;		isp->isp_respinrp = OUTMAILBOX5;		isp->isp_respoutrp = INMAILBOX5;	}	/*	 * Put the board into PAUSE mode (so we can read the SXP registers	 * or write FPM/FBM registers).	 */	ISP_WRITE(isp, HCCR, HCCR_CMD_PAUSE);	if (IS_FC(isp)) {		switch (isp->isp_type) {		case ISP_HA_FC_2100:			btype = "2100";			break;		case ISP_HA_FC_2200:			btype = "2200";			break;		case ISP_HA_FC_2300:			btype = "2300";			break;		case ISP_HA_FC_2312:			btype = "2312";			break;		default:			break;		}		/*		 * While we're paused, reset the FPM module and FBM fifos.		 */		ISP_WRITE(isp, BIU2100_CSR, BIU2100_FPM0_REGS);		ISP_WRITE(isp, FPM_DIAG_CONFIG, FPM_SOFT_RESET);		ISP_WRITE(isp, BIU2100_CSR, BIU2100_FB_REGS);		ISP_WRITE(isp, FBM_CMD, FBMCMD_FIFO_RESET_ALL);		ISP_WRITE(isp, BIU2100_CSR, BIU2100_RISC_REGS);	} else if (IS_1240(isp)) {		sdparam *sdp = isp->isp_param;		btype = "1240";		isp->isp_clock = 60;		sdp->isp_ultramode = 1;		sdp++;		sdp->isp_ultramode = 1;		/*		 * XXX: Should probably do some bus sensing.		 */	} else if (IS_ULTRA2(isp)) {		static const char m[] = "bus %d is in %s Mode";		u_int16_t l;		sdparam *sdp = isp->isp_param;		isp->isp_clock = 100;		if (IS_1280(isp))			btype = "1280";		else if (IS_1080(isp))			btype = "1080";		else if (IS_12160(isp))			btype = "12160";		else			btype = "<UNKLVD>";		l = ISP_READ(isp, SXP_PINS_DIFF) & ISP1080_MODE_MASK;		switch (l) {		case ISP1080_LVD_MODE:			sdp->isp_lvdmode = 1;			isp_prt(isp, ISP_LOGCONFIG, m, 0, "LVD");			break;		case ISP1080_HVD_MODE:			sdp->isp_diffmode = 1;			isp_prt(isp, ISP_LOGCONFIG, m, 0, "Differential");			break;		case ISP1080_SE_MODE:			sdp->isp_ultramode = 1;			isp_prt(isp, ISP_LOGCONFIG, m, 0, "Single-Ended");			break;		default:			isp_prt(isp, ISP_LOGERR,			    "unknown mode on bus %d (0x%x)", 0, l);			break;		}		if (IS_DUALBUS(isp)) {			sdp++;			l = ISP_READ(isp, SXP_PINS_DIFF|SXP_BANK1_SELECT);			l &= ISP1080_MODE_MASK;			switch(l) {			case ISP1080_LVD_MODE:				sdp->isp_lvdmode = 1;				isp_prt(isp, ISP_LOGCONFIG, m, 1, "LVD");				break;			case ISP1080_HVD_MODE:				sdp->isp_diffmode = 1;				isp_prt(isp, ISP_LOGCONFIG,				    m, 1, "Differential");				break;			case ISP1080_SE_MODE:				sdp->isp_ultramode = 1;				isp_prt(isp, ISP_LOGCONFIG,				    m, 1, "Single-Ended");				break;			default:				isp_prt(isp, ISP_LOGERR,				    "unknown mode on bus %d (0x%x)", 1, l);				break;			}		}	} else {		sdparam *sdp = isp->isp_param;		i = ISP_READ(isp, BIU_CONF0) & BIU_CONF0_HW_MASK;		switch (i) {		default:			isp_prt(isp, ISP_LOGALL, "Unknown Chip Type 0x%x", i);			/* FALLTHROUGH */		case 1:			btype = "1020";			isp->isp_type = ISP_HA_SCSI_1020;			isp->isp_clock = 40;			break;		case 2:			/*			 * Some 1020A chips are Ultra Capable, but don't			 * run the clock rate up for that unless told to			 * do so by the Ultra Capable bits being set.			 */			btype = "1020A";			isp->isp_type = ISP_HA_SCSI_1020A;			isp->isp_clock = 40;			break;		case 3:			btype = "1040";			isp->isp_type = ISP_HA_SCSI_1040;			isp->isp_clock = 60;			break;		case 4:			btype = "1040A";			isp->isp_type = ISP_HA_SCSI_1040A;			isp->isp_clock = 60;			break;		case 5:			btype = "1040B";			isp->isp_type = ISP_HA_SCSI_1040B;			isp->isp_clock = 60;			break;		case 6:			btype = "1040C";			isp->isp_type = ISP_HA_SCSI_1040C;			isp->isp_clock = 60;                        break;		}		/*		 * Now, while we're at it, gather info about ultra		 * and/or differential mode.		 */		if (ISP_READ(isp, SXP_PINS_DIFF) & SXP_PINS_DIFF_MODE) {			isp_prt(isp, ISP_LOGCONFIG, "Differential Mode");			sdp->isp_diffmode = 1;		} else {			sdp->isp_diffmode = 0;		}		i = ISP_READ(isp, RISC_PSR);		if (isp->isp_bustype == ISP_BT_SBUS) {			i &= RISC_PSR_SBUS_ULTRA;		} else {			i &= RISC_PSR_PCI_ULTRA;		}		if (i != 0) {			isp_prt(isp, ISP_LOGCONFIG, "Ultra Mode Capable");			sdp->isp_ultramode = 1;			/*			 * If we're in Ultra Mode, we have to be 60Mhz clock-			 * even for the SBus version.			 */			isp->isp_clock = 60;		} else {			sdp->isp_ultramode = 0;			/*			 * Clock is known. Gronk.			 */		}		/*		 * Machine dependent clock (if set) overrides		 * our generic determinations.		 */		if (isp->isp_mdvec->dv_clock) {			if (isp->isp_mdvec->dv_clock < isp->isp_clock) {				isp->isp_clock = isp->isp_mdvec->dv_clock;			}		}	}	/*	 * Clear instrumentation	 */	isp->isp_intcnt = isp->isp_intbogus = 0;	/*	 * Do MD specific pre initialization	 */	ISP_RESET0(isp);again:	/*	 * Hit the chip over the head with hammer,	 * and give the ISP a chance to recover.	 */	if (IS_SCSI(isp)) {		ISP_WRITE(isp, BIU_ICR, BIU_ICR_SOFT_RESET);		/*		 * A slight delay...		 */		USEC_DELAY(100);		/*		 * Clear data && control DMA engines.		 */		ISP_WRITE(isp, CDMA_CONTROL,		    DMA_CNTRL_CLEAR_CHAN | DMA_CNTRL_RESET_INT);		ISP_WRITE(isp, DDMA_CONTROL,		    DMA_CNTRL_CLEAR_CHAN | DMA_CNTRL_RESET_INT);	} else {		ISP_WRITE(isp, BIU2100_CSR, BIU2100_SOFT_RESET);		/*		 * A slight delay...		 */		USEC_DELAY(100);		/*		 * Clear data && control DMA engines.		 */		ISP_WRITE(isp, CDMA2100_CONTROL,			DMA_CNTRL2100_CLEAR_CHAN | DMA_CNTRL2100_RESET_INT);		ISP_WRITE(isp, TDMA2100_CONTROL,			DMA_CNTRL2100_CLEAR_CHAN | DMA_CNTRL2100_RESET_INT);		ISP_WRITE(isp, RDMA2100_CONTROL,			DMA_CNTRL2100_CLEAR_CHAN | DMA_CNTRL2100_RESET_INT);	}	/*	 * Wait for ISP to be ready to go...	 */	loops = MBOX_DELAY_COUNT;	for (;;) {		if (IS_SCSI(isp)) {			if (!(ISP_READ(isp, BIU_ICR) & BIU_ICR_SOFT_RESET))				break;		} else {			if (!(ISP_READ(isp, BIU2100_CSR) & BIU2100_SOFT_RESET))				break;		}

⌨️ 快捷键说明

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