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

📄 sym_hipd.c

📁 内核linux2.4.20,可跟rtlinux3.2打补丁 组成实时linux系统,编译内核
💻 C
📖 第 1 页 / 共 5 页
字号:
	int f = 0;	/*	 *  For now, we only need to know about the actual 	 *  PCI BUS clock frequency for C1010-66 chips.	 */#if 1	if (np->features & FE_66MHZ) {#else	if (1) {#endif		OUTB (nc_stest1, SCLK);	/* Use the PCI clock as SCSI clock */		f = (int) sym_getfreq (np);		OUTB (nc_stest1, 0);	}	np->pciclk_khz = f;	return f;}/* *  SYMBIOS chip clock divisor table. * *  Divisors are multiplied by 10,000,000 in order to make  *  calculations more simple. */#define _5M 5000000static u32 div_10M[] = {2*_5M, 3*_5M, 4*_5M, 6*_5M, 8*_5M, 12*_5M, 16*_5M};/* *  Get clock factor and sync divisor for a given  *  synchronous factor period. */static int sym_getsync(hcb_p np, u_char dt, u_char sfac, u_char *divp, u_char *fakp){	u32	clk = np->clock_khz;	/* SCSI clock frequency in kHz	*/	int	div = np->clock_divn;	/* Number of divisors supported	*/	u32	fak;			/* Sync factor in sxfer		*/	u32	per;			/* Period in tenths of ns	*/	u32	kpc;			/* (per * clk)			*/	int	ret;	/*	 *  Compute the synchronous period in tenths of nano-seconds	 */	if (dt && sfac <= 9)	per = 125;	else if	(sfac <= 10)	per = 250;	else if	(sfac == 11)	per = 303;	else if	(sfac == 12)	per = 500;	else			per = 40 * sfac;	ret = per;	kpc = per * clk;	if (dt)		kpc <<= 1;	/*	 *  For earliest C10 revision 0, we cannot use extra 	 *  clocks for the setting of the SCSI clocking.	 *  Note that this limits the lowest sync data transfer 	 *  to 5 Mega-transfers per second and may result in	 *  using higher clock divisors.	 */#if 1	if ((np->features & (FE_C10|FE_U3EN)) == FE_C10) {		/*		 *  Look for the lowest clock divisor that allows an 		 *  output speed not faster than the period.		 */		while (div > 0) {			--div;			if (kpc > (div_10M[div] << 2)) {				++div;				break;			}		}		fak = 0;			/* No extra clocks */		if (div == np->clock_divn) {	/* Are we too fast ? */			ret = -1;		}		*divp = div;		*fakp = fak;		return ret;	}#endif	/*	 *  Look for the greatest clock divisor that allows an 	 *  input speed faster than the period.	 */	while (div-- > 0)		if (kpc >= (div_10M[div] << 2)) break;	/*	 *  Calculate the lowest clock factor that allows an output 	 *  speed not faster than the period, and the max output speed.	 *  If fak >= 1 we will set both XCLKH_ST and XCLKH_DT.	 *  If fak >= 2 we will also set XCLKS_ST and XCLKS_DT.	 */	if (dt) {		fak = (kpc - 1) / (div_10M[div] << 1) + 1 - 2;		/* ret = ((2+fak)*div_10M[div])/np->clock_khz; */	}	else {		fak = (kpc - 1) / div_10M[div] + 1 - 4;		/* ret = ((4+fak)*div_10M[div])/np->clock_khz; */	}	/*	 *  Check against our hardware limits, or bugs :).	 */	if (fak < 0)	{fak = 0; ret = -1;}	if (fak > 2)	{fak = 2; ret = -1;}	/*	 *  Compute and return sync parameters.	 */	*divp = div;	*fakp = fak;	return ret;}/* *  SYMBIOS chips allow burst lengths of 2, 4, 8, 16, 32, 64, *  128 transfers. All chips support at least 16 transfers  *  bursts. The 825A, 875 and 895 chips support bursts of up  *  to 128 transfers and the 895A and 896 support bursts of up *  to 64 transfers. All other chips support up to 16  *  transfers bursts. * *  For PCI 32 bit data transfers each transfer is a DWORD. *  It is a QUADWORD (8 bytes) for PCI 64 bit data transfers. * *  We use log base 2 (burst length) as internal code, with  *  value 0 meaning "burst disabled". *//* *  Burst length from burst code. */#define burst_length(bc) (!(bc))? 0 : 1 << (bc)/* *  Burst code from io register bits. */#define burst_code(dmode, ctest4, ctest5) \	(ctest4) & 0x80? 0 : (((dmode) & 0xc0) >> 6) + ((ctest5) & 0x04) + 1/* *  Set initial io register bits from burst code. */static __inline void sym_init_burst(hcb_p np, u_char bc){	np->rv_ctest4	&= ~0x80;	np->rv_dmode	&= ~(0x3 << 6);	np->rv_ctest5	&= ~0x4;	if (!bc) {		np->rv_ctest4	|= 0x80;	}	else {		--bc;		np->rv_dmode	|= ((bc & 0x3) << 6);		np->rv_ctest5	|= (bc & 0x4);	}}/* * Print out the list of targets that have some flag disabled by user. */static void sym_print_targets_flag(hcb_p np, int mask, char *msg){	int cnt;	int i;	for (cnt = 0, i = 0 ; i < SYM_CONF_MAX_TARGET ; i++) {		if (i == np->myaddr)			continue;		if (np->target[i].usrflags & mask) {			if (!cnt++)				printf("%s: %s disabled for targets",					sym_name(np), msg);			printf(" %d", i);		}	}	if (cnt)		printf(".\n");}/* *  Save initial settings of some IO registers. *  Assumed to have been set by BIOS. *  We cannot reset the chip prior to reading the  *  IO registers, since informations will be lost. *  Since the SCRIPTS processor may be running, this  *  is not safe on paper, but it seems to work quite  *  well. :) */static void sym_save_initial_setting (hcb_p np){	np->sv_scntl0	= INB(nc_scntl0) & 0x0a;	np->sv_scntl3	= INB(nc_scntl3) & 0x07;	np->sv_dmode	= INB(nc_dmode)  & 0xce;	np->sv_dcntl	= INB(nc_dcntl)  & 0xa8;	np->sv_ctest3	= INB(nc_ctest3) & 0x01;	np->sv_ctest4	= INB(nc_ctest4) & 0x80;	np->sv_gpcntl	= INB(nc_gpcntl);	np->sv_stest1	= INB(nc_stest1);	np->sv_stest2	= INB(nc_stest2) & 0x20;	np->sv_stest4	= INB(nc_stest4);	if (np->features & FE_C10) {	/* Always large DMA fifo + ultra3 */		np->sv_scntl4	= INB(nc_scntl4);		np->sv_ctest5	= INB(nc_ctest5) & 0x04;	}	else		np->sv_ctest5	= INB(nc_ctest5) & 0x24;}/* *  Prepare io register values used by sym_start_up()  *  according to selected and supported features. */static int sym_prepare_setting(hcb_p np, struct sym_nvram *nvram){	u_char	burst_max;	u32	period;	int i;	/*	 *  Wide ?	 */	np->maxwide	= (np->features & FE_WIDE)? 1 : 0;	/*	 *  Guess the frequency of the chip's clock.	 */	if	(np->features & (FE_ULTRA3 | FE_ULTRA2))		np->clock_khz = 160000;	else if	(np->features & FE_ULTRA)		np->clock_khz = 80000;	else		np->clock_khz = 40000;	/*	 *  Get the clock multiplier factor. 	 */	if	(np->features & FE_QUAD)		np->multiplier	= 4;	else if	(np->features & FE_DBLR)		np->multiplier	= 2;	else		np->multiplier	= 1;	/*	 *  Measure SCSI clock frequency for chips 	 *  it may vary from assumed one.	 */	if (np->features & FE_VARCLK)		sym_getclock(np, np->multiplier);	/*	 * Divisor to be used for async (timer pre-scaler).	 */	i = np->clock_divn - 1;	while (--i >= 0) {		if (10ul * SYM_CONF_MIN_ASYNC * np->clock_khz > div_10M[i]) {			++i;			break;		}	}	np->rv_scntl3 = i+1;	/*	 * The C1010 uses hardwired divisors for async.	 * So, we just throw away, the async. divisor.:-)	 */	if (np->features & FE_C10)		np->rv_scntl3 = 0;	/*	 * Minimum synchronous period factor supported by the chip.	 * Btw, 'period' is in tenths of nanoseconds.	 */	period = (4 * div_10M[0] + np->clock_khz - 1) / np->clock_khz;	if	(period <= 250)		np->minsync = 10;	else if	(period <= 303)		np->minsync = 11;	else if	(period <= 500)		np->minsync = 12;	else				np->minsync = (period + 40 - 1) / 40;	/*	 * Check against chip SCSI standard support (SCSI-2,ULTRA,ULTRA2).	 */	if	(np->minsync < 25 &&		 !(np->features & (FE_ULTRA|FE_ULTRA2|FE_ULTRA3)))		np->minsync = 25;	else if	(np->minsync < 12 &&		 !(np->features & (FE_ULTRA2|FE_ULTRA3)))		np->minsync = 12;	/*	 * Maximum synchronous period factor supported by the chip.	 */	period = (11 * div_10M[np->clock_divn - 1]) / (4 * np->clock_khz);	np->maxsync = period > 2540 ? 254 : period / 10;	/*	 * If chip is a C1010, guess the sync limits in DT mode.	 */	if ((np->features & (FE_C10|FE_ULTRA3)) == (FE_C10|FE_ULTRA3)) {		if (np->clock_khz == 160000) {			np->minsync_dt = 9;			np->maxsync_dt = 50;			np->maxoffs_dt = nvram->type ? 62 : 31;		}	}		/*	 *  64 bit addressing  (895A/896/1010) ?	 */	if (np->features & FE_DAC) {#if   SYM_CONF_DMA_ADDRESSING_MODE == 0		np->rv_ccntl1	|= (DDAC);#elif SYM_CONF_DMA_ADDRESSING_MODE == 1		if (!np->use_dac)			np->rv_ccntl1	|= (DDAC);		else			np->rv_ccntl1	|= (XTIMOD | EXTIBMV);#elif SYM_CONF_DMA_ADDRESSING_MODE == 2		if (!np->use_dac)			np->rv_ccntl1	|= (DDAC);		else			np->rv_ccntl1	|= (0 | EXTIBMV);#endif	}	/*	 *  Phase mismatch handled by SCRIPTS (895A/896/1010) ?  	 */	if (np->features & FE_NOPM)		np->rv_ccntl0	|= (ENPMJ); 	/*	 *  C1010-33 Errata: Part Number:609-039638 (rev. 1) is fixed.	 *  In dual channel mode, contention occurs if internal cycles	 *  are used. Disable internal cycles.	 */	if (np->device_id == PCI_ID_LSI53C1010 &&	    np->revision_id < 0x1)		np->rv_ccntl0	|=  DILS;	/*	 *  Select burst length (dwords)	 */	burst_max	= SYM_SETUP_BURST_ORDER;	if (burst_max == 255)		burst_max = burst_code(np->sv_dmode, np->sv_ctest4,				       np->sv_ctest5);	if (burst_max > 7)		burst_max = 7;	if (burst_max > np->maxburst)		burst_max = np->maxburst;	/*	 *  DEL 352 - 53C810 Rev x11 - Part Number 609-0392140 - ITEM 2.	 *  This chip and the 860 Rev 1 may wrongly use PCI cache line 	 *  based transactions on LOAD/STORE instructions. So we have 	 *  to prevent these chips from using such PCI transactions in 	 *  this driver. The generic ncr driver that does not use 	 *  LOAD/STORE instructions does not need this work-around.	 */	if ((np->device_id == PCI_ID_SYM53C810 &&	     np->revision_id >= 0x10 && np->revision_id <= 0x11) ||	    (np->device_id == PCI_ID_SYM53C860 &&	     np->revision_id <= 0x1))		np->features &= ~(FE_WRIE|FE_ERL|FE_ERMP);	/*	 *  Select all supported special features.	 *  If we are using on-board RAM for scripts, prefetch (PFEN) 	 *  does not help, but burst op fetch (BOF) does.	 *  Disabling PFEN makes sure BOF will be used.	 */	if (np->features & FE_ERL)		np->rv_dmode	|= ERL;		/* Enable Read Line */	if (np->features & FE_BOF)		np->rv_dmode	|= BOF;		/* Burst Opcode Fetch */	if (np->features & FE_ERMP)		np->rv_dmode	|= ERMP;	/* Enable Read Multiple */#if 1	if ((np->features & FE_PFEN) && !np->ram_ba)#else	if (np->features & FE_PFEN)#endif		np->rv_dcntl	|= PFEN;	/* Prefetch Enable */	if (np->features & FE_CLSE)		np->rv_dcntl	|= CLSE;	/* Cache Line Size Enable */	if (np->features & FE_WRIE)		np->rv_ctest3	|= WRIE;	/* Write and Invalidate */	if (np->features & FE_DFS)		np->rv_ctest5	|= DFS;		/* Dma Fifo Size */	/*	 *  Select some other	 */	if (SYM_SETUP_PCI_PARITY)		np->rv_ctest4	|= MPEE; /* Master parity checking */	if (SYM_SETUP_SCSI_PARITY)		np->rv_scntl0	|= 0x0a; /*  full arb., ena parity, par->ATN  */	/*	 *  Get parity checking, host ID and verbose mode from NVRAM	 */	np->myaddr = 255;	sym_nvram_setup_host (np, nvram);	/*	 *  Get SCSI addr of host adapter (set by bios?).	 */	if (np->myaddr == 255) {		np->myaddr = INB(nc_scid) & 0x07;		if (!np->myaddr)			np->myaddr = SYM_SETUP_HOST_ID;	}	/*	 *  Prepare initial io register bits for burst length	 */	sym_init_burst(np, burst_max);	/*	 *  Set SCSI BUS mode.	 *  - LVD capable chips (895/895A/896/1010) report the 	 *    current BUS mode through the STEST4 IO register.	 *  - For previous generation chips (825/825A/875), 	 *    user has to tell us how to check against HVD, 	 *    since a 100% safe algorithm is not possible.	 */	np->scsi_mode = SMODE_SE;	if (np->features & (FE_ULTRA2|FE_ULTRA3))		np->scsi_mode = (np->sv_stest4 & SMODE);	else if	(np->features & FE_DIFF) {		if (SYM_SETUP_SCSI_DIFF == 1) {			if (np->sv_scntl3) {				if (np->sv_stest2 & 0x20)					np->scsi_mode = SMODE_HVD;			}			else if (nvram->type == SYM_SYMBIOS_NVRAM) {				if (!(INB(nc_gpreg) & 0x08))					np->scsi_mode = SMODE_HVD;			}		}		else if	(SYM_SETUP_SCSI_DIFF == 2)			np->scsi_mode = SMODE_HVD;	}	if (np->scsi_mode == SMODE_HVD)		np->rv_stest2 |= 0x20;	/*	 *  Set LED support from SCRIPTS.	 *  Ignore this feature for boards known to use a 	 *  specific GPIO wiring and for the 895A, 896 	 *  and 1010 that drive the LED directly.	 */	if ((SYM_SETUP_SCSI_LED || 	     (nvram->type == SYM_SYMBIOS_NVRAM ||	      (nvram->type == SYM_TEKRAM_NVRAM &&	       np->device_id == PCI_ID_SYM53C895))) &&	    !(np->features & FE_LEDC) && !(np->sv_gpcntl & 0x01))		np->features |= FE_LED0;	/*	 *  Set irq mode.	 */	switch(SYM_SETUP_IRQ_MODE & 3) {	case 2:		np->rv_dcntl	|= IRQM;		break;	case 1:		np->rv_dcntl	|= (np->sv_dcntl & IRQM);		break;	default:		break;	}	/*	 *  Configure targets according to driver setup.	 *  If NVRAM present get targets setup from NVRAM.	 */	for (i = 0 ; i < SYM_CONF_MAX_TARGET ; i++) {		tcb_p tp = &np->target[i];		tp->tinfo.user.scsi_version = tp->tinfo.curr.scsi_version= 2;		tp->tinfo.user.spi_version  = tp->tinfo.curr.spi_version = 2;		tp->tinfo.user.period = np->minsync;		tp->tinfo.user.offset = np->maxoffs;		tp->tinfo.user.width  = np->maxwide ? BUS_16_BIT : BUS_8_BIT;		tp->usrflags |= (SYM_DISC_ENABLED | SYM_TAGS_ENABLED);		tp->usrtags = SYM_SETUP_MAX_TAG;		sym_nvram_setup_target (np, i, nvram);		/*		 *  For now, guess PPR/DT support from the period 		 *  and BUS width.		 */		if (np->features & FE_ULTRA3) {			if (tp->tinfo.user.period <= 9	&&			    tp->tinfo.user.width == BUS_16_BIT) {				tp->tinfo.user.options |= PPR_OPT_DT;				tp->tinfo.user.offset   = np->maxoffs_dt;				tp->tinfo.user.spi_version = 3;			}

⌨️ 快捷键说明

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