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

📄 sonic.c

📁 mips架构的bootloader,99左右的版本 但源代码现在没人更新了
💻 C
字号:
/************************************************************* * File: lib/sonic.c * Purpose: A tftp driver for the Sonic Ethernet controller * Author: Phil Bunce (pjb@carmel.com) * Revision History: *	930507	Created *	960909	Made globals be malloc'd *	970221	Added ifdefs for SONIC_DW32 *	970325	Removed typedefs for Ulong etc. Now included by ether.h *	970325	ANDed byte with 0xff in printMem *	970509	Added arp support. *	970617	Added ping support *	970822	Changed RDASIZE to 16 to fix slow dl on large networks *	971115	Removed LE ifdefs around re_sonic code *	971115	Fixed n/4 prob in swap32n *	971118	Fixed bad ether_header messages from swapPkt *	980611	Added casts on free to supress warnings on Tasking cc3 *	980611	Removed cast in call to Qput4 in addRRrec (Tasking). *	980611	Removed assert in retry pack case. *	980615	Renamed re_sonic re_ether *	980615	Added ether_is_sonic. open etc via ptr now. *	980615	Made most stuff static *	981001	Moved all of the chip-independent stuff to ether.c *	981127	Move the GETRXREC swapPkt to ether.c */#include <malloc.h>#include <mips.h>#include <string.h>#include <termio.h>#include <utypes.h>/* * This file contains a very simple driver for the National Sonic * Ethernet controller. It is used to provide PMON with a method to * support download using tftp via Ethernet. It is intended to be * called from ether.c. *//* * This module will not work if the global data that it uses (RRA etc)  * crosses a 64KB boundary. i.e. The upper 16 address bits must not change. * That is the reason that these global data areas are malloc'd. *//* All our boards have the Sonic at the same base address */#ifndef ETHERADDR#define ETHERADDR 0xbc000000#endif#ifdef MIPSEB#define SONIC_BASE 	((volatile Ushort *)(ETHERADDR+2))#else#define SONIC_BASE 	((volatile Ushort *)ETHERADDR)#endif#define getlo(x)	(((Ulong)(x))&0xffff)#define gethi(x)	(((Ulong)(x))>>16)/*#define PROMISCUOUS 	/* enable promiscuous mode */#define HDRONLY		/* print headers only *//*#define VERBOSE		/* be verbose *//*#define CHECKS_ON	/* do runtime checks */#ifdef CHECKS_ON#include <assert.h>#else#define assert(x)#endif#ifdef PROMISCUOUS#define VERBOSE#endif#define RRASIZE         8       /* min 4 */#define RBSIZE          2048    /* receive buffer size (min 2048) */#define RDASIZE         16      /* min 2. 970822 */#define TDASIZE         4       /* min 1 */#define TBSIZE          128             /* transmit buffer size */#ifdef ETHERNET	/* skip the entire file if ethernet is not enabled *//*************** Ethernet stuff ******************************/#include <ether.h>#include <sonic.h>/* receive resource area */static RRrec *RRA;	/* receive resource area */static char *RBA_data;/* receive descriptor area */static RXrec *RDA;	/* receive descriptor area *//* transmit descriptor area */static TXrec *TDA;	/* transmit resource area */static char *TBA_data;static Ulong CamData[5];/* this scoreboard is used to determine whether an RBA is completely free */typedef struct SBrec {	int seq;	int cnt;	int tot;	Ulong addr;	} SBrec;static SBrec scorebd[RRASIZE];static SBrec *putScorebd(),*getScorebd();static RXrec *RDA_add;		/* start adding new descriptors here */static RXrec *RDA_new;		/* start checking for FULL descriptors here */static TXrec *TDA_done;	/* start checking transmitted packets here */static TXrec *TDA_next;	/* next available packet for transmission *//*************** Queues **************************************/typedef struct Queue4 {	volatile int ip;	volatile int op;	int size;	Ulong *ptr;	} Queue4;#define Qempty4(q)	(((q)->ip == (q)->op)?1:0)static Ulong Qget4();static Qput4();static Queue4 Rxq,*rxq,Rbq,*rbq;static Ulong RxqD[RDASIZE+1],RbqD[RRASIZE+1];/****************** Globals **********************************/extern int vflag;/****************** Forward Declarations *********************/static initHw(),initDA();static pktrx();static pkttx();static rtnRXpkt();static SBrec *putScorebd();static SBrec *getScorebd();static addRXrec();static addRRrec();/**************************************************************  pktrx()*	Packet received.*	Add it to the rxq queue.*/static pktrx(){#if 0if (! IS_K1SEG(RDA_new)) printf("pktrx: %08x: not k1seg\n",RDA_new);#endifwhile (RDA_new->in_use == FULL) {	Qput4(rxq,(Ulong)RDA_new);	RDA_new = getRXlink(RDA_new);	}SONIC_ISR = ISR_PKTRX; /* clear pkt rec'd bit */}/**************************************************************  pkttx()*	clear up after a pkt was transmitted*/static pkttx(){#if 0if (! IS_K1SEG(TDA_done)) printf("pkttx: %08x: not k1seg\n",TDA_done);#endifwhile (TDA_done->status != 0) {	if (vflag) printf("pkttx ");	/* aught to check the status here */	TDA_done->status = 0;	TDA_done = getTXlink(TDA_done);	}SONIC_ISR = ISR_TXDN; /* clear pkt transmitted bit */}/**************************************************************  rtnRXpkt(q)*/static rtnRXpkt(q)RXrec *q;{SBrec *p;Ulong rseq;assert(q != 0);rseq = getRXrseq(q);p = getScorebd(rseq);if (p) assert(p->addr != 0);if (!p) p = putScorebd(rseq,Qget4(rbq));assert(p != 0);assert(p->addr != 0);if (q->status&LPKT) { /* last packet in buffer */	p->tot = getRXpseq(q)+1;	}p->cnt++;if (p->tot && p->tot == p->cnt) {	addRRrec((char *)p->addr,RBSIZE);	p->addr = 0;	}addRXrec(q);}/**************************************************************  SBrec *putScorebd(seq,addr)*/static SBrec *putScorebd(seq,addr)Ulong seq,addr;{int i;assert(addr != 0);for (i=0;i<RRASIZE;i++) {	if (scorebd[i].addr == 0) break;	assert(scorebd[i].addr != addr);	assert(scorebd[i].seq != seq);	}assert(i < RRASIZE);scorebd[i].addr = addr;scorebd[i].seq = seq;scorebd[i].cnt = 0;scorebd[i].tot = 0;return(&scorebd[i]);}/**************************************************************  SBrec *getScorebd(seq)*/static SBrec *getScorebd(seq)Ulong seq;{int i;for (i=0;i<RRASIZE;i++) {	if (scorebd[i].addr && scorebd[i].seq == seq) return(&scorebd[i]);	}return(0);}/**************************************************************  addRXrec(q)*	put RDA back on list for use by SONIC*	RDA_new is behind (or equal to) CRDA in the chain. *	RDA_add is always ahead of (or equal to) CRDA in the chain.*	Thus RDA_new always points the latest packet that has been*		received, and RDA_add is where new (empty) packets*		are added to the chain.*/static addRXrec(q)RXrec *q;{assert(q != 0);q = k1RXrec(q); /* make sure that it is non cachable *//* prepare descriptor for use */q->link = EOL;q->in_use = EMPTY;if (RDA_add) putRXlink(RDA_add,q);else {	putCRDA(q);	RDA_new = q;	}RDA_add = q;}/**************************************************************  addRRrec(p,size)*/static addRRrec(p,size)char *p;int size;{RRrec *q;int is_empty;assert(p != 0);p = (char *)k02k1(p);Qput4(rbq,p);q = getRWP();if (q == getRRP()) is_empty = 1;else is_empty = 0;putRRptr(q,p);putRRwc(q,size);if (q+1 >= getREA()) q = getRSA();else q++;putRWP(q);if (is_empty) SONIC_ISR = ISR_RBE; /* clear RBE bit */}/**************************************************************  static Qput4(q,v)*	put a word into a queue*/static Qput4(q,v)Queue4 *q;Ulong v;{assert(q != 0);q->ptr[q->ip] = v;if (q->ip+1 > q->size) q->ip = 0;else q->ip++;assert(q->ip != q->op); /* queue full */}/**************************************************************  static Ulong Qget4(q)*	get a word from a queue*/static Ulong Qget4(q)Queue4 *q;{Ulong v;assert(q != 0);while (q->ip == q->op) ; /* wait while empty */v = q->ptr[q->op];if (q->op+1 > q->size) q->op = 0;else q->op++;assert(v != 0);return(v);}/**************************************************************  static int initDA(void)*	initialize all the data areas*/static int initDA(void){int i;char *p,*fl[5];Ulong t;rxq = &Rxq;Rxq.size = RDASIZE;Rxq.ip = Rxq.op = 0;Rxq.ptr = RxqD;rbq = &Rbq;Rbq.size = RRASIZE;Rbq.ip = Rbq.op = 0;Rbq.ptr = RbqD;/*  * These data structures must not cross a 64KB boundary. Therefore * we request them again if they do. */if (!RRA) {	for (i=0;;i++) {		RRA = (RRrec *)malloc(RRASIZE*sizeof(RRrec));		RBA_data = (char *)malloc(RBSIZE*(RRASIZE-1));		RDA = (RXrec *)malloc(RDASIZE*sizeof(RXrec));		TDA = (TXrec *)malloc(TDASIZE*sizeof(TXrec));		TBA_data = (char *)malloc(TBSIZE*TDASIZE);		if (!RRA || !RBA_data || !RDA || !TDA || !TBA_data) {			printf("initDA: malloc failure\n");			return(0);			}		/* check to see if it is ok */		t = (Ulong)malloc(4); free((void *)t);		if ((t>>16) == (((Ulong)RRA)>>16)) break;		/* not ok. so dealloc them */		free(RRA);free(RBA_data);free(RDA);free(TDA);free(TBA_data);		if (i > 0) { /* too many attempts */			printf("initDA: 2nd malloc failure\n");			return(0);			}		/* malloc enough to take us to the 64KB boundary */		t = (Ulong)malloc(4); free((void *)t);		malloc(0x10000-(t&0xffff));		}	}#if 0printf("RRA=%08x RBA_data=%08x RDA=%08x TDA=%08x TBA_data=%08x\n",	RRA, RBA_data, RDA, TDA, TBA_data);#endif		RDA_add = 0;putCRDA(RDA);for (i=0;i<RDASIZE;i++) addRXrec(&RDA[i]);putRSA(RRA);putREA(RRA+RRASIZE);SONIC_RRP = SONIC_RSA;SONIC_RWP = SONIC_RSA;p = RBA_data;for (i=0;i<RRASIZE-1;i++) {	addRRrec(p,RBSIZE);	p += RBSIZE;	}bzero(scorebd,sizeof(SBrec)+RRASIZE);/* set transmit descriptors up as a circular list */p = (char *)k02k1(TBA_data);for (i=0;i<TDASIZE;i++) {	putTXptr(&TDA[i],p);	TDA[i].status = 0;	TDA[i].config = 0;	TDA[i].frag_count = 1;	if (i == TDASIZE-1) putTXlink(&TDA[i],&TDA[0],1);	else putTXlink(&TDA[i],&TDA[i+1],1);	p += TBSIZE;	}SONIC_CTDA = (getlo(log2phy(&TDA[0]))|1);SONIC_UTDA = gethi(log2phy(&TDA[0]));TDA_done = k1TXrec(&TDA[0]);TDA_next = k1TXrec(&TDA[0]);return(1);}/**************************************************************  static initHw(macAddr)*	init the SONIC chip*/static initHw(Uchar *macAddr){int i,n;char tmp[26],*p;#ifdef SONIC_DW32Ulong *ulp;#elseUshort *ulp;#endifSONIC_CR = CR_RST;			/* Turn ON RESET *//* Data Control */#ifdef SONIC_DW32SONIC_DCR = (DCR_WAIT0 | DCR_DW32 | DCR_TFT1 | DCR_TFT0 |		DCR_STERM | DCR_PO0 | DCR_PO1);	#elseSONIC_DCR = (DCR_WAIT0 | DCR_TFT1 | DCR_TFT0 | DCR_STERM | DCR_PO0 | DCR_PO1);#endifSONIC_ISR = 0x7fff;			/* Clear ISR */SONIC_IMR = 0;				/* All Interrupts Masked */SONIC_CRCT = 0xffff;			/* Clear Tally */SONIC_FAET = 0xffff;			/* Clear Tally */SONIC_MPT = 0xffff;			/* Clear Tally */SONIC_RSC = 0;SONIC_EOBC = 760;			/* largest Ethernet packet */SONIC_CR &= ~CR_RST;			/* Turn OFF RESET */SONIC_CR = CR_RRRA;			/* prime SONIC with RRA read *//* load CAM */i = 0;#ifdef SONIC_DW32ulp = (Ulong *)k02k1(CamData);#elseulp = (Ushort *)k02k1(CamData);#endifulp[i++] = 0;ulp[i++] = (macAddr[1] << 8) | macAddr[0];ulp[i++] = (macAddr[3] << 8) | macAddr[2];ulp[i++] = (macAddr[5] << 8) | macAddr[4];ulp[i] = 0x1;	/* Enable entry 0 */SONIC_CDC = 1;				/* One entry */SONIC_CDP = getlo(CamData);SONIC_CR = CR_LCAM;				/*Load CAM*/for (i=0;(SONIC_ISR & ISR_LCD) == 0 && i < 4000000;i++) ;if (i >= 4000000) {	printf("sonic: unable to load CAM\n");	return(0);	}SONIC_ISR = ISR_LCD;				/* Clear ISR bit */#ifdef PROMISCUOUS /* Enable Promiscuous mode*/SONIC_RCR = RCR_BRD | RCR_PRO;#elseSONIC_RCR = RCR_BRD;	/* 970509 */#endifSONIC_MPT = 0xffff;SONIC_CRCT = 0xffff;SONIC_FAET = 0xffff;SONIC_CR = CR_RXEN;				/* Turn on Receiver */return(1);}/**************************************************************  void *sonic_driver(int op,void *vp1,void *vp2)*	Main entry point for this driver. Everything else in this*	module should be static.*/void *sonic_driver(int op,void *vp1,void *vp2){RXrec *rr;char *rxptr;Ushort isr;Uchar *macAddr = vp1;isr = SONIC_ISR;if (isr&ISR_PKTRX) pktrx();if (isr&ISR_TXDN) pkttx();switch (op) {	case ETHER_INIT :		/* int ether_driver(ETHER_INIT,Uchar *macAddr,void) */		if (!initDA()) return(0);		if (!initHw(macAddr)) return(0);		SONIC_ISR = 0xffff;	/* clear all current int requests */		return((void *)1);	case ETHER_GETTBA :		/* char *ether_driver(ETHER_GETTBA,int *len,void) */		TDA_next->pkt_size = TDA_next->frag_size = *((int *)vp2);		return getTXptr(TDA_next);	case ETHER_TBARDY :		/* int ether_driver(ETHER_TBRDY,void,void) */		SONIC_CR=CR_TXP;		TDA_next = getTXlink(TDA_next);		assert(TDA_next != 0);		return((void *)1);	case ETHER_GETRXREC :		/* RXrec *ether_driver(ETHER_GETRXREC,void,void) */		rr = (RXrec *)Qget4(rxq);		rxptr = (char *)getRXptr(rr);		if (re_ether) swap32n(rxptr,rr->byte_count);		if (vflag) printMem(rxptr,rr->byte_count);#ifdef VERBOSE		printPkt(rxptr,rr->byte_count);#endif		return(rr);	case ETHER_GETRBA :		/* char *ether_driver(ETHER_GETRBA,RXrec *q,int *len) */		rr = (RXrec *)vp1;		*((int *)vp2) = rr->byte_count;		return(getRXptr(rr));	case ETHER_RXDONE :		/* int ether_driver(ETHER_RXDONE,RXrec *q,void) */		rr = (RXrec *)vp1;		rtnRXpkt(rr);		return((void *)1);	case ETHER_RXRDY :		/* int ether_driver(ETHER_RXRDY,void,void) */		if (!Qempty4(rxq)) return((void *)1);		return(0);	default : return(0);	}return(0);}#else /* Tasking tools don't like empty files (sigh) */sonic_foobar() {}#endif /* ETHERNET */

⌨️ 快捷键说明

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