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

📄 8253xmcs.c

📁 这个linux源代码是很全面的~基本完整了~使用c编译的~由于时间问题我没有亲自测试~但就算用来做参考资料也是非常好的
💻 C
字号:
/* -*- linux-c -*- *//*  * Copyright (C) 2001 By Joachim Martillo, Telford Tools, Inc. * * 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; either version * 2 of the License, or (at your option) any later version. * **/#include <linux/module.h>#include <linux/kernel.h>#include <linux/pci.h>#include <linux/stddef.h>#include <linux/string.h>#include <linux/sockios.h>#include <asm/io.h>#include <asm/byteorder.h>#include <asm/pgtable.h>#include <linux/skbuff.h>#include <linux/if_arp.h>#include <linux/fs.h>#include <linux/sched.h>#include <asm/uaccess.h>#include <linux/version.h>#include <linux/etherdevice.h>#include "Reg9050.h"#include "8253xctl.h"#include "ring.h"#include "8253x.h"#include "crc32dcl.h"#include "8253xmcs.h"#include "sp502.h"/* Just to guarantee that strings are null terminated */#define MEMCPY(dest, src, cnt) \{ \	memcpy((dest), (src), (cnt)); \	(dest)[cnt] = 0; \}static unsigned char sp502progbyte[] ={	SP502_OFF,	SP502_RS232,	SP502_RS422,	SP502_RS485,	SP502_RS449,	SP502_EIA530,	SP502_V35};	/* * The following routines are the multichannel server I2C serial EPROM routines. *//* * Set the clock and the data lines of the SEP. */static voidmcs_sep_set(mcs_sep_t *msp, unsigned sdavalid, unsigned sda,	    unsigned sclvalid, unsigned scl){#ifdef MAX#undef MAX#endif		/* MAX */	#define MAX(x, y)	((x) > (y) ? (x) : (y))		unsigned char csr;	unsigned int sleeptime;		/*	 * Ensure sufficient clock	 */		sleeptime = 0;		if (sclvalid) 	{		if (msp->s_scl && !scl) 		{   /* do we have a downgoing transition? */			sleeptime = MAX(1, sleeptime);		}		else if (!msp->s_scl && scl) 		{	/* upgoing */			sleeptime = MAX(2, sleeptime);		}		msp->s_scl = scl;	}		if (sdavalid) 	{		if ((msp->s_sda && !sda) || (!msp->s_sda && sda)) 		{			sleeptime = MAX(1, sleeptime);		}				msp->s_sda = sda;	}		if (sleeptime > 0) 	{		udelay(sleeptime);	}		/*	 * Construct the CSR byte.	 */	csr = 0;	if (msp->s_sda) 	{		csr |= CIMCMD_CIMCSR_SDA;	}		if (msp->s_scl) 	{		csr |= CIMCMD_CIMCSR_SCL;	}		writeb((unsigned char) csr, msp->s_wrptr);}static voidmcs_sep_start(mcs_sep_t *msp){	/*	 * Generate a START condition	 */	mcs_sep_set(msp, TRUE, TRUE, TRUE, TRUE);	mcs_sep_set(msp, TRUE, FALSE, TRUE, TRUE);}static voidmcs_sep_stop(mcs_sep_t *msp){	/*	 * Generate a STOP condition	 */	mcs_sep_set(msp, TRUE, FALSE, TRUE, TRUE);	mcs_sep_set(msp, TRUE, TRUE, TRUE, TRUE);}/* * Send out a single byte. */static voidmcs_sep_byte(mcs_sep_t *msp, unsigned char val){	register int	 bitcount;		/* Clock may be high ... lower the clock */	mcs_sep_set(msp, TRUE, FALSE, TRUE, FALSE);		bitcount = 8;		while (TRUE) 	{		mcs_sep_set(msp, TRUE, (val & 0x80) != 0, TRUE, FALSE);		mcs_sep_set(msp, TRUE, (val & 0x80) != 0, TRUE, TRUE);				bitcount--;		if (bitcount == 0) 		{			break;		}		val <<= 1;	}		/* Clock is high ... lower the clock */	mcs_sep_set(msp, FALSE, FALSE, TRUE, FALSE);}/* * Wait for an acknowledge cycle.  Expects the clock to be low. */static unsignedmcs_sep_waitsep(mcs_sep_t *msp){	int loopcount;	unsigned char cimcsr;  	/* Stop driving SDA */	mcs_sep_set(msp, TRUE, TRUE, FALSE, FALSE);	/* Raise the clock */	mcs_sep_set(msp, FALSE, FALSE, TRUE, TRUE);		loopcount = 1000;	while (loopcount != 0) 	{		cimcsr = readb(msp->s_rdptr);				if ((cimcsr & CIMCMD_CIMCSR_SDA) == 0) 		{			break;		}		loopcount--;	}		/* Lower the clock */	mcs_sep_set(msp, FALSE, FALSE, TRUE, FALSE);		if (loopcount == 0) 	{		return FALSE;	}	else 	{		return TRUE;	}}/* * Read the given CIM's SEP, starting at the given address, into *  the given buffer, for the given length. * * Returns -1 if there was a failure, otherwise the byte count. */static intmcs_sep_read(mcs_sep_t *msp, unsigned short addr, 	     unsigned char *buf, unsigned int nbytes){	unsigned char cmdaddr, val, cimcsr;	unsigned int bytecount, bitcount;		mcs_sep_start(msp);		/*	 * First, send out a dummy WRITE command with no data.	 */		cmdaddr = 0xa0 | (((addr >> 8) & 0x7) << 1) | 0x0;		mcs_sep_byte(msp, cmdaddr);		if (!mcs_sep_waitsep(msp)) 	{		return -1;	}		/*	 * Now, send the reset of the address.	 */		mcs_sep_byte(msp, (unsigned char) addr);		if (!mcs_sep_waitsep(msp)) 	{		return -1;	}		/*	 * Now, restart with a read command.	 */		mcs_sep_start(msp);		cmdaddr = 0xa0 | (((addr >> 8) & 0x7) << 1) | 0x1;		mcs_sep_byte(msp, cmdaddr);		if (!mcs_sep_waitsep(msp)) 	{		return -1;	}		/*	 * Now, start reading the bytes.	 */	bytecount = 0;	while (TRUE) 	{		bitcount = 8;		val = 0;		while (TRUE) 		{			mcs_sep_set(msp, TRUE, TRUE, TRUE, TRUE);						cimcsr = readb(msp->s_rdptr);						if ((cimcsr & CIMCMD_CIMCSR_SDA) != 0) 			{				val |= 0x01;			}						mcs_sep_set(msp, FALSE, FALSE, TRUE, FALSE);			bitcount--;						if (bitcount == 0) 			{				break;			}			val <<= 1;		}				*buf++ = val;		bytecount++;		nbytes--;				if (nbytes == 0) 		{			break;		}				/*		 * Send the acknowledge.		 */				mcs_sep_set(msp, FALSE, FALSE, TRUE, FALSE);		mcs_sep_set(msp, TRUE, FALSE, TRUE, TRUE);		mcs_sep_set(msp, FALSE, FALSE, TRUE, FALSE);	}		mcs_sep_stop(msp);		return (int) bytecount;}unsigned int mcs_ciminit(SAB_BOARD *bptr, AURA_CIM *cim){	mcs_sep_t		 ms;		ms.s_rdptr = (unsigned char *) 		(bptr->CIMCMD_REG + (CIMCMD_RDCIMCSR | (cim->ci_num << CIMCMD_CIMSHIFT)));	ms.s_wrptr = (unsigned char *) 		(bptr->CIMCMD_REG + (CIMCMD_WRCIMCSR | (cim->ci_num << CIMCMD_CIMSHIFT)));	ms.s_scl = ms.s_sda = FALSE;		if (mcs_sep_read(&ms, (unsigned short) 0, &(cim->ci_sep[0]),			 sizeof(cim->ci_sep)) != sizeof(cim->ci_sep)	    || cim->ci_sep[MCS_SEP_MAGIC] != MCS_SEP_MAGICVAL) 	{				if (cim->ci_sep[MCS_SEP_MAGIC] != MCS_SEP_MAGICVAL) 		{			DEBUGPRINT((KERN_ALERT				    "auraXX20: invalid CIM %d serial EPROM on board %d",				    cim->ci_num, bptr->board_number));		}		else 		{			DEBUGPRINT((KERN_ALERT				    "auraXX20: error reading CIM %d serial EPROM on board %d",				    cim->ci_num, bptr->board_number));		}				cim->ci_clkspeed = WANMCS_CLKSPEED;		cim->ci_clkspdsrc = -1;		cim->ci_spdgrd = 10;		cim->ci_spdgrdsrc = -1;		cim->ci_flags = 0;		cim->ci_rev[0] = '\0';		cim->ci_sn[0] = '\0';		cim->ci_mfgdate[0] = '\0';		cim->ci_mfgloc[0] = '\0';				/*		 * Diddle the port setup registers to determine if this		 *  CIM was built up for RS232 or SP502.		 */				writew((unsigned short) 0xffff, (unsigned short *) 		       (bptr->CIMCMD_REG +			(CIMCMD_WRSETUP | (cim->ci_num << CIMCMD_CIMSHIFT))));		#ifdef RICHARD_DELAY		udelay(1);#endif		/* RICHARD_DELAY */				if (readw((unsigned short *) 			  (bptr->CIMCMD_REG +			   (CIMCMD_RDSETUP | (cim->ci_num << CIMCMD_CIMSHIFT)))) == 0xffff) 		{						writew(0, (unsigned short *) 			       (bptr->CIMCMD_REG +				(CIMCMD_WRSETUP | (cim->ci_num << CIMCMD_CIMSHIFT))));			#ifdef RICHARD_DELAY			udelay(1);#endif		/* RICHARD_DELAY */						if (readw((unsigned short *) 				  (bptr->CIMCMD_REG +				   (CIMCMD_RDSETUP | (cim->ci_num << CIMCMD_CIMSHIFT)))) == 0) 			{								cim->ci_type = CIM_SP502;			}			else 			{				cim->ci_type = CIM_RS232;			}		}		else 		{			cim->ci_type = CIM_RS232;		}				if (cim->ci_type == CIM_SP502) 		{			cim->ci_flags |= CIM_SYNC;		}	}	else 	{		/*		 * Pick through the serial EPROM contents and derive		 *  the values we need.		 */		MEMCPY(&(cim->ci_rev[0]), &(cim->ci_sep[MCS_SEP_REV]),		       MCS_SEP_REVLEN);		MEMCPY(&(cim->ci_sn[0]), &(cim->ci_sep[MCS_SEP_SN]),		       MCS_SEP_SNLEN);		MEMCPY(&(cim->ci_mfgdate[0]), &(cim->ci_sep[MCS_SEP_MFGDATE]),		       MCS_SEP_MFGDATELEN);		MEMCPY(&(cim->ci_mfgloc[0]), &(cim->ci_sep[MCS_SEP_MFGLOC]),		       MCS_SEP_MFGLOCLEN);				cim->ci_clkspeed = (unsigned long) cim->ci_sep[MCS_SEP_CLKSPD]			| ((unsigned long) cim->ci_sep[MCS_SEP_CLKSPD + 1] << 8)			| ((unsigned long) cim->ci_sep[MCS_SEP_CLKSPD + 2] << 16)			| ((unsigned long) cim->ci_sep[MCS_SEP_CLKSPD + 3] << 24);				cim->ci_clkspdsrc = SEPROM;				cim->ci_spdgrd = (int) cim->ci_sep[MCS_SEP_SPDGRD];		cim->ci_spdgrdsrc = SEPROM;				cim->ci_flags = (unsigned long) cim->ci_sep[MCS_SEP_FLAGS];				cim->ci_type = (int) cim->ci_sep[MCS_SEP_TYPE];	}		/*	 * Possibly initialize the port setup registers.	 */		if (cim->ci_type == CIM_SP502) 	{		unsigned short alloff;#ifdef DEBUG_VERBOSE		unsigned short readback;#endif		int offset;				/*		 * Turn off all of the electrical interfaces.  The		 *  hardware *should* initialize to this state, but the		 *  prototype, at least, does not.  Note that this setting		 *  is reflected in the SIF_OFF setting of l_interface in		 *  mustard_lineinit, above.		 */				alloff = (unsigned short) SP502_OFF			| ((unsigned short) SP502_OFF << 4)			| ((unsigned short) SP502_OFF << 8)			| ((unsigned short) SP502_OFF << 12);		for (offset = 0; offset < 8; offset++) 		{#ifdef DEBUG_VERBOSE			DEBUGPRINT((KERN_ALERT "cim %d setup reg #%d: writing 0x%x to 0x%x",				    cim->ci_num, offset, (unsigned) alloff,				    (CIMCMD_WRSETUP | (offset << 1) |				     (cim->ci_num << CIMCMD_CIMSHIFT))));#endif		 /* DEBUG_VERBOSE */						writew((unsigned short) alloff, (unsigned short *)			       (bptr->CIMCMD_REG +				(CIMCMD_WRSETUP | (offset << 1) |				 (cim->ci_num << CIMCMD_CIMSHIFT))));#ifdef RICHARD_DELAY			udelay(1);#endif		/* RICHARD_DELAY */#ifdef DEBUG_VERBOSE			readback = readw((unsigned short *)					 (bptr->CIMCMD_REG +					  (CIMCMD_RDSETUP | (offset << 1) |					   (cim->ci_num << CIMCMD_CIMSHIFT))));			if (readback != alloff) 			{				DEBUGPRINT((KERN_ALERT "cim %d setup reg #%d: readback (0x%x) should be 0x%x",					    cim->ci_num, offset, readback, alloff));			}#endif		/* DEBUG_VERBOSE */		}	}		/*	 * Clear out the CIM CSR with the exception of the LED.	 */		writeb((unsigned char) 0, 	       (unsigned char *) (bptr->CIMCMD_REG +				  (CIMCMD_WRCIMCSR | (cim->ci_num << CIMCMD_CIMSHIFT))));		return TRUE;}int wanmcs_reset(SAB_BOARD* bptr) /* note the board is the host card not the				   * individual extension boards				   */{	int		 counter;	#if 0				/* from the ASE driver */	/*	 * Program the AMCC to deactivate the write FIFO.	 */		ASE_PUT32(cboard->b_bridgehandle,		  (aseuint32_t *) (cboard->b_bridge + AMCC_PTCR),		  ((aseuint32_t) (AMCC_PTMODE | AMCC_WRFIFODIS) << 24) |		  ((aseuint32_t) (AMCC_PTMODE | AMCC_WRFIFODIS) << 16) |		  ((aseuint32_t) (AMCC_PTMODE | AMCC_WRFIFODIS) << 8) |		  (aseuint32_t) (AMCC_PTMODE | AMCC_WRFIFODIS));#endif		/* 0 */		/*	 * First thing: do a reset of the local bus on the MIC 	 *  by diddling the Add-On Reset bit in the RCR.	 */		writel((unsigned int) AMCC_AORESET, 	       (unsigned int *)(bptr->AMCC_REG + AMCC_RCR));		udelay(10);		/* wait for 10 us. */		writel((unsigned int) 0, 	       (unsigned int *)(bptr->AMCC_REG + AMCC_RCR));		udelay(10);		/* wait for 10 us. */		/*	 * Now the PCI bridge is reset.  Try to establish	 *  a link through the Glink chipset.	 */		for (counter = 1000; counter != 0; counter--) 	{		writeb(0, (unsigned char*) (bptr->MICCMD_REG + MICCMD_MICCSR));				udelay(5);				if((readb((unsigned char*) 			  (bptr->MICCMD_REG + MICCMD_MICCSR)) & MICCMD_MICCSR_GLE) == 0)		{			break;		}	}		/*	 * Did we run out of time?	 */		if (counter == 0) 	{		printk(KERN_ALERT 		       "AMCC5920: board %p: GLink did not reset -- is the MEB on?",		       bptr);				return FALSE;	}		/*	 * Now, hit the reset in the MEB.	 */		writeb(0, (unsigned int *) (bptr->CIMCMD_REG + CIMCMD_RESETENA));		udelay(5);		writeb(0, (unsigned int *) (bptr->CIMCMD_REG + CIMCMD_RESETDIS));		/*	 * And we're done!	 */		return TRUE;}void aura_sp502_program(SAB_PORT *port, register unsigned int sigindex){	register unsigned char prognibble;	SAB_BOARD *bptr;	unsigned int cimnum;	unsigned int chipno;	unsigned int portno;	unsigned int rdaddressreceiver;	unsigned int rdaddresstransmitter;	unsigned int wraddressreceiver;	unsigned int wraddresstransmitter;	unsigned short datareceiver;	unsigned short datatransmitter;	bptr = port->board;	cimnum = port->chip->c_cim->ci_num;	chipno = (port->chip->c_chipno & 1); /* chip number relative to EB not MCS */	portno = (port->portno + (8 * chipno)); /* portno on a per EB basis */	prognibble = (sp502progbyte[sigindex] & 0x0F);				/* first 4 shorts contain receiver control bits */	rdaddressreceiver = 		(((unsigned int)bptr->CIMCMD_REG) + 		 ((cimnum << CIMCMD_CIMSHIFT) | CIMCMD_RDSETUP | ((portno/4) << CIMCMD_CTRLSHIFT)));				/* second 4 shorts contain transmitter control bits */	rdaddresstransmitter = 		(((unsigned int)bptr->CIMCMD_REG) + 		 ((cimnum << CIMCMD_CIMSHIFT) | CIMCMD_RDSETUP | ((4+(portno/4)) << CIMCMD_CTRLSHIFT)));	wraddressreceiver = 		(((unsigned int)bptr->CIMCMD_REG) + 		 ((cimnum << CIMCMD_CIMSHIFT) | CIMCMD_WRSETUP | ((portno/4) << CIMCMD_CTRLSHIFT)));	wraddresstransmitter = 		(((unsigned int)bptr->CIMCMD_REG) + 		 ((cimnum << CIMCMD_CIMSHIFT) | CIMCMD_WRSETUP | ((4+(portno/4)) << CIMCMD_CTRLSHIFT)));				/* read out the current receiver status */	datareceiver = readw((unsigned short*) rdaddressreceiver);				/* clear out nibble that corresponds to current port */	datareceiver &= (unsigned short) ~(0x0F << ((3 - (portno % 4)) * 4));				/* or in new receiver control field */	datareceiver |= (prognibble << ((3 - (portno % 4)) * 4));				/* write back the short that corresponds to 4 ports */	writew(datareceiver, (unsigned short*) wraddressreceiver);				/* just as above except that next 4 shorts correspond to transmitters */	datatransmitter = readw((unsigned short*) rdaddresstransmitter);	datatransmitter &= (unsigned short) ~(0x0F << ((3 - (portno % 4)) * 4)); 	datatransmitter |= (prognibble << ((3 - (portno % 4)) * 4));	writew(datatransmitter, (unsigned short*) wraddresstransmitter);}

⌨️ 快捷键说明

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