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

📄 am79970.c

📁 mips架构的bootloader,99左右的版本 但源代码现在没人更新了
💻 C
字号:
/************************************************************* * File: lib/am79970.c * Purpose: A tftp driver for the Am79C970A Ethernet controller * Author: Phil Bunce (pjb@carmel.com) * Revision History: *	980615	Created from sonic.c *	981114	Functional for big endian. *	981125	Functional for little endian. *	981127	Moved the GETRXREC swapPkt to ether.c *	981216	Omit all of initDA if already done. This fixes the prob *		of IDON timeout on second Ether download. *	990317	Updated value in initDA(). */#include <string.h>#include <utypes.h>#include <mips.h>#if 0 /* debug */#define STATIC /* */#else#define STATIC static#endif/*#define VERBOSE	/* turn on verbose mode *//* * This file contains the low-level driver for the Am79C970A * Ethernet controller. It is called by functions in lib/ether.c. * When used this way, it is used to provide PMON with a method to * support download using tftp via Ethernet.  *//*  * Everything on this chip is accessed via 4 registers. RDP, RAP, RESET, * and BDP. RDP and RAP are used to access the CSR regs, RAP and BDP are * used to access the BCR regs. CSR1&2 point to the INIT block. The * rdr and tdr pointers in the INIT block point to the rx and tx descriptor * rings. Note that the byte-count fields hold the 2's complement of the * byte count. Visit www.amd.com for a full technical manual on the Am79C970A. */#define ETHER_BASE 	0xbfe00000#ifdef CHECKS_ON#include <assert.h>#else#define assert(x)#endif#define inw(a)		(*((Ulong *)(a)))#define outw(a,v)	(*((Ulong *)(a))=(v))#define outh(a,v)	(*((Ushort *)(a))=(v))#define swap32(n) ( \	((((Ulong)(n))>>24)&0x000000ff) | \	((((Ulong)(n))>>8)&0x0000ff00) |  \	((((Ulong)(n))<<8)&0x00ff0000) |  \	((((Ulong)(n))<<24)&0xff000000)   \	)#ifdef ETHERNET	/* skip the entire file if ethernet is not enabled */#define ALIGNED(n,a)	(((Ulong)(a))&(n-1))?0:1typedef volatile struct RDrec { /* 16-byte align */	Ulong cw1;	/* RCC RPC MCNT */	Ulong cw2;	/* OWN ...... BCNT */	char *buf;	int resv;	} RDrec;#define MCNTMASK  0xfff	/* RD cw1 */typedef volatile struct TDrec { /* 16-byte align */	Ulong cw1;	/* BUFF .... TRC */	Ulong cw2;	/* OWN ...... BCNT */	char *buf;	int resv;	} TDrec;/* pointed to by CSR2:CSR1 */typedef volatile struct INITrec { /* 4-byte align */	Ulong cw;	/* TLE RLE MODE */	Ulong padr0;	/* mac addr - ls byte is 1st byte of adr */	Ulong padr1;	/* mac addr - last 2 bytes */	Ulong ladr0;	/* multicast only - mbz */	Ulong ladr1;	/* multicast only - mbz */	RDrec *rdr;	TDrec *tdr;	Ulong resv;	} INITrec;#define TDRSIZE 3	/* 2^N of TDR size. ie. 2=4 3=8 4=16 5=32 */#define RDRSIZE 3	/* 2^N of RDR size. ie. 2=4 3=8 4=16 5=32 */#define RBUFSIZE 1500#define TBUFSIZE 64#define ATDRSIZE (1<<TDRSIZE)	/* actual tdr size */#define ARDRSIZE (1<<RDRSIZE)	/* actual rdr size *//* TD cw1 */#define BUFF (1<<31)#define UFLO (1<<30)#define EXDEF (1<<29)#define LCOL (1<<28)#define LCAR (1<<27)#define RTRY (1<<26)#define TDRMASK (0x3fff<12)/* TD cw2 */#define OWN (1<<31)#define ERR (1<<30)#define ADD (1<<29)#define MORE (1<<28)#define ONE (1<<27)#define DEF (1<<26)#define STP (1<<25)#define ENP (1<<24)#define BCNTMASK  0xfff	/* RD & TD cw2: rx max buffer, tx bytes in buffer */#define ONES (0xf<<12)	/* must be ones. required. RD & TD cw2 *//* INIT cw */#define TLE_SHFT	28#define RLE_SHFT	20TDrec *next_TD,*base_TD;int next_TDcnt;RDrec *next_RD,*base_RD;int next_RDcnt;/*************** Ethernet stuff ******************************/#include <ether.h>/****************** Globals **********************************/extern int vflag;static INITrec *init_ptr;/****************** Forward Declarations *********************/#define M_RDP	(ETHER_BASE+0x10)#define M_RAP	(ETHER_BASE+0x14)#define M_RESET	(ETHER_BASE+0x18)#define M_BDP	(ETHER_BASE+0x1c)/* PCI Configuration Space Definitions */#define PCI_VENDORID            (0x00)#define PCI_DEVICEID            (0x02)#define PCI_COMMAND             (0x04)#define PCI_STATUS              (0x06)#define PCI_REVID               (0x08)#define PCI_PIR                 (0x09)     /* Not used on AMD controller */#define PCI_SUBCLASS            (0x0a)#define PCI_BASECLASS           (0x0b)#define PCI_CACHELINE           (0x0c)#define PCI_LATENCY             (0x0d)#define PCI_HEADERTYPE          (0x0e)#define PCI_BIST                (0x0f)     /* Not used on AMD controller */#define PCI_BASEADDRESS0        (0x10)#define PCI_BASEADDRESS1        (0x14)#define PCI_BASEADDRESS2        (0x18)     /* Not used on AMD controller */#define PCI_BASEADDRESS3        (0x1c)     /* Not used on AMD controller */#define PCI_BASEADDRESS4        (0x20)     /* Not used on AMD controller */#define PCI_BASEADDRESS5        (0x24)     /* Not used on AMD controller */#define PCI_CARDBUSCIS          (0x28)     /* Not used on AMD controller */#define PCI_SUBVENDORID         (0x2c)     /* Not used on AMD controller */#define PCI_SUBSYSID            (0x2e)     /* Not used on AMD controller */#define PCI_EXPANSIONROM        (0x30)#define PCI_INTLINE             (0x3c)#define PCI_INTPIN              (0x3d)#define PCI_MINGNT              (0x3e)#define PCI_MAXLAT              (0x3f)#define TYPE0                   0x00#define TYPE1                   0x01#define AMDDEVAD                0xbfe90000   /* Ethernet controller has */                                             /* IDSEL connected to AD16 */#define AMD_VENDOR_ID           0x20001022#define CSR0_ERR    (1<<15)#define CSR0_BABL   (1<<14)#define CSR0_CERR   (1<<13)#define CSR0_MISS   (1<<12)#define CSR0_MERR   (1<<11)#define CSR0_RINT   (1<<10)#define CSR0_TINT   (1<<9)#define CSR0_IDON   (1<<8)#define CSR0_INTR   (1<<7)#define CSR0_IENA   (1<<6)#define CSR0_RXON   (1<<5)#define CSR0_TXON   (1<<4)#define CSR0_TDMD   (1<<3)#define CSR0_STOP   (1<<2)#define CSR0_STRT   (1<<1)#define CSR0_INIT   (1<<0)#define CSR_STATUS   0	/* 16-bit */#define CSR_INIT     1	/* 32-bit */#define CSR_RDRBASE 24	/* 32-bit */#define CSR_RDRNEXT 26	/* 32-bit */#define CSR_RDRCUR  28	/* 32-bit */#define CSR_TDRBASE 30	/* 32-bit */#define CSR_TDRCUR  34	/* 32-bit */#define CSR_RDRCNT  72	/* 16-bit */#define CSR_TDRCNT  74	/* 16-bit */#define CSR_RDRLEN  76	/* 16-bit */#define CSR_TDRLEN  78	/* 16-bit */#define CSR3_BSWP  (1<<2)	/* byte swap */#define BCR20_SSIZE32 (1<<8)#define SWSTYLE_3   3/* csr15 is programmed via word0 of the init block */#define CSR15_PROM 	(1<<15)	/* enable promiscuous mode */#define CSR15_DRCVBC 	(1<<14)	/* disable rx broadcast */#define CSR15_DRCVPA 	(1<<13)	/* disable rx phy adr */#define CSR15_DLNKTST 	(1<<12)	/* disable link status */#define CSR15_DAPC 	(1<<11)	/* disable auto pol corr */#define CSR15_MENDECL 	(1<<10)	/* mendec loopback mode */#define CSR15_LRT 	(1<<9)	/* low rx threshold (T-MAU) */#define CSR15_TSEL 	(1<<9)	/* low rx threshold (AUI) */#define CSR15_PORTSELMSK 	(3<<7)	/* port select bits */#define CSR15_INTL 	(1<<6)	/* internal loopback */#define CSR15_DRTY 	(1<<5)	/* disable retry */#define CSR15_FCOLL 	(1<<4)	/* force collision */#define CSR15_DXMTFCS 	(1<<3)	/* disable tx crc */#define CSR15_LOOP 	(1<<2)	/* loopback mode */#define CSR15_DTX 	(1<<1)	/* disable tx */#define CSR15_DRX 	(1<<0)	/* disable rx *//**************************************************************  void *xalloc(int size)*	On bdmr4102, can't use std malloc as that allocs from sdram. *	PCI Ethernet controller can't access sdram. Use 128KB of sram *	at 0xae000000 instead.*/void *xalloc(int size){static void *bufptr;void *v;if (bufptr == 0) bufptr = (void *)0xae000000;v = bufptr;size = (size+16)&~15;((char *)bufptr) += size;if (bufptr >= (void *)0xae020000) return(0);return(v);}/**************************************************************/STATIC Ushort getCSR(int n){Ushort v;outw(M_RAP,n);v = inw(M_RDP);return(v);}/**************************************************************/STATIC Ulong getCSRw(int n){Ulong v;v = (getCSR(n+1)<<16)|getCSR(n);return(v);}/**************************************************************/STATIC void putCSR(int n,Ulong v){outw(M_RAP,n);outw(M_RDP,v);}/**************************************************************/STATIC void putCSRw(int n,Ulong v){putCSR(n+1,v>>16);putCSR(n,v&0xffff);}/**************************************************************/STATIC Ushort getBCR(int n){outw(M_RAP,n);return(inw(M_BDP));}/**************************************************************/STATIC void putBCR(int n,Ushort v){outw(M_RAP,n);outw(M_BDP,v);}#ifdef VERBOSE/**************************************************************/STATIC void printRD(RDrec *r){if (((Ulong)r)&0xf) printf("error: RDrec not aligned.\n");printf("RDrec %08x: ",r);printf("cw1=%08x ",r->cw1);printf("cw2=%08x ",r->cw2);printf("buf=%08x ",r->buf);printf("resv=%x ",r->resv);printf("\n");}/**************************************************************/STATIC void printTD(TDrec *r){if (((Ulong)r)&0xf) printf("error: TDrec not aligned.\n");printf("TDrec %08x: ",r);printf("cw1=%08x ",r->cw1);printf("cw2=%08x ",r->cw2);printf("buf=%08x ",r->buf);printf("resv=%x ",r->resv);printf("\n");}/**************************************************************/STATIC printINIT(INITrec *r){if (((Ulong)r)&0x3) printf("error: INITrec not aligned.\n");printf("INITrec %08x:\n\t",r);printf("cw=%08x ",r->cw);printf("mac=%04x%08x ",r->padr1,r->padr0);printf("ladr=%x.%x ",r->ladr1,r->ladr0);printf("rdr=%08x ",r->rdr);printf("tdr=%08x ",r->tdr);printf("\n");}/**************************************************************/STATIC void printCSRs(){int i;for (i=0;i<32;i++) {	if ((i%8)==0) printf("\n%2d - ",i);	printf("%04x ",getCSR(i));	}printf("\n");}#endif/**************************************************************/STATIC int initDA(Uchar *macadr){INITrec *ir;RDrec *rr;TDrec *tr;int i;Ulong v;if (init_ptr) return(1); /* 981216 only do this the first time *//* # Setup Ethernet PCI Configuration Space  # # Since this is an embedded application with no expansion slots this  # code forgoes the process of scanning all PCI devices.  We do a   # detect of the the AMD ethernet controller as Device 20 which has  # IDSEL pin hardwired to AD16 on the eval board.  The routine then  # maps the ethernet registers to 0x1fbb0000 and IO space starting at 0x0, # configures timing, disables the expansion ROM, and configures interrupts. # The routine finishs by configuring the Fbus unit #     #         Set up Bus Unit for Configuration Transaction *//* Map all 1fexxxxx memory space to PCI */outw(M_FBUSCMP,0x000f1fe0);/* map cfg space starting at 0x1e000000 - 0x1effffff */outw(M_FBUSAC,0x40071fe8);/* Configure FBUS unit. Burst length set to 1 and Ext Ack. Mmaster */outw(M_FBUSCFG,0x08); /* 990317 was 0x0c */     /* Perform a PCI Device Detect */v = inw(AMDDEVAD+PCI_VENDORID);if (v != AMD_VENDOR_ID) {	printf("failed device detect %08x\n",v);	return(0);	}/* Disconnect Controller from all but configuration cycles */outw(AMDDEVAD+PCI_COMMAND,0);/*  #          Even though there is no IO space in MIPS we will initialize #          the register to begin at zero.  The bus controller on the 4102 #          supports IO space so if somebody wants to use it, it starts at 0x0 */outw(AMDDEVAD+PCI_BASEADDRESS0,0);outw(AMDDEVAD+PCI_BASEADDRESS0+4,0);/* #          Assign AMD Ethernet Controller to 0x1fe00000 #          There are 32 bytes of address locations required */  outw(AMDDEVAD+PCI_BASEADDRESS1,ETHER_BASE-0xa0000000);outw(AMDDEVAD+PCI_BASEADDRESS1+4,0);/* #          Disable Expansion ROM */outw(AMDDEVAD+PCI_EXPANSIONROM,0);/* #          Configure Latency Timer */v = inw(AMDDEVAD+PCI_CACHELINE);v &= 0xffff00ff;outw(AMDDEVAD+PCI_CACHELINE,v);/* #          Configure Command Register */outw(AMDDEVAD+PCI_COMMAND,0x07);/* Enable Bus Mastering, Memory Access, IO Access. Disable Parity,  * SERR, VGA, etc.	 */outw(M_RDP,0);	/* switch to DWORD mode *//* 981216 I used to wrap an if !init_ptr around just this section */ir = (INITrec *)xalloc(sizeof(INITrec));if (!ir || !ALIGNED(4,ir)) return(0);rr = (RDrec *)xalloc(sizeof(RDrec)*ARDRSIZE);if (!rr || !ALIGNED(16,rr)) return(0);ir->rdr = (log2phy(rr));base_RD = next_RD = rr;for (i=0;i<ARDRSIZE;i++,rr++) {	rr->buf = (log2phy(xalloc(RBUFSIZE)));	if (!rr->buf) return(0);	rr->cw1 = rr->resv = 0;	rr->cw2 = (OWN|ONES|((0-RBUFSIZE)&0xfff));	}tr = (TDrec *)xalloc(sizeof(TDrec)*ATDRSIZE);if (!tr || !ALIGNED(16,rr)) return(0);ir->tdr = (log2phy(tr));base_TD = next_TD = tr;for (i=0;i<ATDRSIZE;i++,tr++) {	tr->buf = (log2phy(xalloc(TBUFSIZE)));	if (!tr->buf) return(0);	tr->cw1 = tr->resv = 0;	tr->cw2 = (ONES|((0-TBUFSIZE)&0xfff));	}init_ptr = ir;putBCR(20,BCR20_SSIZE32|SWSTYLE_3);putBCR(6,1);  /* led2 = collisions */#ifdef MIPSEBputCSR(3,CSR3_BSWP); /* byte swap */#endifir->cw = (TDRSIZE<<TLE_SHFT)|(RDRSIZE<<RLE_SHFT);#ifdef PROMISCUOUSir->cw |= CSR15_PROM;#endifir->padr0 = ((macadr[3]<<24)|(macadr[2]<<16)|(macadr[1]<<8)|macadr[0]);ir->padr1 = ((macadr[5]<<8)|macadr[4]);ir->ladr0 = ir->ladr1 = ir->resv = 0;putCSRw(CSR_INIT,(Ulong)log2phy(ir));putCSR(0,CSR0_STRT|CSR0_INIT);for (i=0;i<1000000;i++) if (getCSR(0)&CSR0_IDON) break;if (i >= 1000000) {	printf("timeout waiting for IDON.\n");	putCSR(0,CSR0_STOP);#ifdef VERBOSE	printCSRs();	printINIT(ir);#endif	return(0);	}return(1);}/**************************************************************  volatile void *am79970_driver(int op,void *vp1,void *vp2)*	Main entry point for the driver.*/volatile void *am79970_driver(int op,void *vp1,void *vp2){char *macAddr = vp1;RDrec *rr = vp1;int *pLen = vp2;TDrec *tr;int n;switch (op) {	case ETHER_INIT :		/* int ether_driver(ETHER_INIT,Uchar *macAddr,void) */		if (!initDA(macAddr)) return(0);		return((void *)1);	case ETHER_GETTBA :		/* char *ether_driver(ETHER_GETTBA,void, int *len) */		tr = next_TD;		if (tr->cw2&OWN) return(0);		n = *pLen;		tr->cw2 = ONES|STP|ENP|((0-n)&0xfff);		return(phy2k1(tr->buf));	case ETHER_TBARDY :		/* int ether_driver(ETHER_TBRDY,void,void) */		tr = next_TD;		tr->cw2 |= OWN;		putCSR(CSR_STATUS,getCSR(CSR_STATUS)|CSR0_TDMD); 				/* inform the chip */		next_TD++;		next_TDcnt++;		if (next_TDcnt >= ATDRSIZE) {			next_TD = base_TD;			next_TDcnt = 0;			}		return((void *)1);	case ETHER_GETRXREC :		/* RXREC *ether_driver(ETHER_GETRXREC,void,void) */		rr = next_RD;		if (rr->cw2&OWN) return(0);		return(rr);	case ETHER_GETRBA :		/* char *ether_driver(ETHER_GETRBA,RXrec *rr,int *len) */		*pLen = rr->cw1&MCNTMASK;		return(phy2k1(rr->buf));	case ETHER_RXDONE :		/* int ether_driver(ETHER_RXDONE,RXrec *rr,void) */		rr->cw2 |= OWN;		next_RD++;		next_RDcnt++;		if (next_RDcnt >= ARDRSIZE) {			next_RD = base_RD;			next_RDcnt = 0;			}		return((void *)1);	case ETHER_RXRDY :		/* int ether_driver(ETHER_RXRDY,void,void) */		rr = next_RD;		if (rr->cw2&OWN) return(0);		return((void *)1);	default : return(0);	}return(0);}#elseam79970_foobar() {}#endif /* ETHERNET */

⌨️ 快捷键说明

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