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

📄 amd79c970.c

📁 RTEMS (Real-Time Executive for Multiprocessor Systems) is a free open source real-time operating sys
💻 C
📖 第 1 页 / 共 2 页
字号:
					dp->txBdTail = 0;			}		}		if (++i == dp->txBdCount)		{			i = 0;		}	}}/* * Send raw packet (caller provides header). * This code runs in the context of the interface transmit * task or in the context of the network task. */static intamd79c970_raw (struct iface *iface, struct mbuf **bpp){	amd79c970Context_t *dp;	struct mbuf *bp;	tmde_t *firstTxBd, *txBd;	unsigned16 status;	int nAdded;	dp = pAmd79c970Context[iface->dev];	/*	 * Fill in some logging data	 */	iface->rawsndcnt++;	iface->lastsent = secclock ();	dump (iface, IF_TRACE_OUT, *bpp);	/*	 * It would not do to have two tasks active in the transmit	 * loop at the same time.	 * The blocking is simple-minded since the odds of two tasks	 * simultaneously attempting to use this code are low.  The only	 * way that two tasks can try to run here is:	 *	1) Task A enters this code and ends up having to	 *	   wait for a transmit buffer descriptor.	 *	2) Task B  gains control and tries to transmit a packet.	 * The RTEMS/KA9Q scheduling semaphore ensures that there	 * are no race conditions associated with manipulating the	 * txWaitTid variable.	 */	if (dp->txWaitTid) {		dp->txRawWait++;		while (dp->txWaitTid)			rtems_ka9q_ppause (10);	}	/*	 * Free up buffer descriptors	 */	amd79c970_retire_tx_bd (dp);	/*	 * Set up the transmit buffer descriptors.	 * No need to pad out short packets since the	 * hardware takes care of that automatically.	 * No need to copy the packet to a contiguous buffer	 * since the hardware is capable of scatter/gather DMA.	 */	bp = *bpp;	nAdded = 0;	txBd = firstTxBd = dp->txBdBase + dp->txBdHead;	for (;;) {		/*		 * Wait for buffer descriptor to become available.		 */		if ((dp->txBdActiveCount + nAdded) == dp->txBdCount) {			/*			 * Find out who we are			 */			if (dp->txWaitTid == 0)				rtems_task_ident (0, 0, &dp->txWaitTid);			/*			 * Wait for buffer descriptor to become available.			 * Note that the buffer descriptors are checked			 * *before* * entering the wait loop -- this catches			 * the possibility that a buffer descriptor became			 * available between the `if' above, and the clearing			 * of the event register.			 * Also, the event receive doesn't wait forever.			 * This is to catch the case where the transmitter			 * stops in the middle of a frame -- and only the			 * last buffer descriptor in a frame can generate			 * an interrupt.			 */			amd79c970_retire_tx_bd (dp);			while ((dp->txBdActiveCount + nAdded) == dp->txBdCount) {				rtems_ka9q_event_receive (INTERRUPT_EVENT,					RTEMS_WAIT|RTEMS_EVENT_ANY,					1 + 1000000/BSP_Configuration.microseconds_per_tick);				amd79c970_retire_tx_bd (dp);			}		}		/*		 * Fill in the buffer descriptor		 */		txBd->tmde_addr=Swap32((unsigned32)bp->data+PCI_SYS_MEM_BASE);		txBd->tmde_bcnt=Swap16(-bp->cnt);		dp->txMbuf[dp->txBdHead] = bp;		nAdded++;		if (++dp->txBdHead == dp->txBdCount)		{			dp->txBdHead = 0;		}		/*		 * Set the transmit buffer status.		 * Break out of the loop if this mbuf is the last in the frame.		 */		if ((bp = bp->next) == NULL) {			if(txBd==firstTxBd)			{				/*				 * There is only one frame				 */				txBd->tmde_status=Swap16(TST_OWN |							 TST_STP |							 TST_ENP);			}			else			{				/*				 * Mark the last buffer				 */				txBd->tmde_status=Swap16(TST_OWN |							 TST_ENP);				/*				 * Trigger the first transmit				 */				firstTxBd->tmde_status=Swap16(TST_OWN |							      TST_STP);			}			/*			 * Sync instruction required to overcome the Grackle			 * stale data bug			 */			asm volatile("sync");			dp->txBdActiveCount += nAdded;			break;		}		else if(txBd!=firstTxBd)		{			txBd->tmde_status = Swap16(TST_OWN);		}		txBd = dp->txBdBase + dp->txBdHead;	}	/*	 * Show that we've finished with the packet	 */	dp->txWaitTid = 0;	*bpp = NULL;	return 0;}/* * PC-NET reader task */static voidamd79c970_rx (int dev, void *p1, void *p2){	struct iface *iface=(struct iface *)p1;	amd79c970Context_t *dp=(amd79c970Context_t *)p2;	struct mbuf *bp;	rtems_unsigned16 status;	rmde_t *rxBd;	int rxBdIndex;	int continuousCount;	/*	 * Input packet handling loop	 */	continuousCount=0;	rxBdIndex=0;	while(TRUE)	{		rxBd=&dp->rxBdBase[rxBdIndex];		/*		 * Wait for packet if there's not one ready		 */		if((status=Swap16(rxBd->rmde_flags)) & RFLG_OWN)		{			/*			 * Reset `continuous-packet' count			 */			continuousCount=0;			/*			 * Wait for packet			 * Note that the buffer descriptor is checked			 * *before* the event wait -- this catches the			 * possibility that a packet arrived between the			 * `if' above, and the clearing of the event register.			 */			while ((status=Swap16(rxBd->rmde_flags)) & RFLG_OWN)			{				rtems_ka9q_event_receive (INTERRUPT_EVENT,						RTEMS_WAIT|RTEMS_EVENT_ANY,						RTEMS_NO_TIMEOUT);			}		}		/*		 * Check that packet is valid		 */		if((status & RFLG_ERR) ||		   ((status & (RFLG_STP|RFLG_ENP)) != (RFLG_STP|RFLG_ENP)))		{			/*			 * Something went wrong with the reception			 */			if(!(status & RFLG_ENP))				dp->rxNotLast++;			if(!(status & RFLG_STP))				dp->rxNotFirst++;			if(status & RFLG_OFLO)				dp->rxGiant++;			if(status & RFLG_FRAM)				dp->rxNonOctet++;			if(status & RFLG_CRC)				dp->rxBadCRC++;			if(status & RFLG_BUFF)				dp->rxOverrun++;		}		else		{			/*			 * Pass the packet up the chain			 * The mbuf count is reduced to remove			 * the frame check sequence at the end			 * of the packet.			 */			bp=dp->rxMbuf[rxBdIndex];			bp->cnt=Swap16(rxBd->rmde_mcnt) - sizeof (uint32);			net_route (iface, &bp);			/*			 * Give the network code a chance to digest the			 * packet.  This guards against a flurry of 			 * incoming packets (usually an ARP storm) from			 * using up all the available memory.			 */			if(++continuousCount >= dp->rxBdCount)				kwait_null ();			/*			 * Allocate a new mbuf			 * FIXME: It seems to me that it would be better			 * if there were some way to limit number of mbufs			 * in use by this interface, but I don't see any			 * way of determining when the mbuf we pass up			 * is freed.			 */			dp->rxMbuf[rxBdIndex]=bp=ambufw (RBUF_SIZE);			bp->data += sizeof (struct iface *);			rxBd->rmde_addr=Swap32(				(unsigned32)bp->data+PCI_SYS_MEM_BASE);			rxBd->rmde_bcnt=Swap16(				-(bp->size-sizeof (struct iface *)));		}		/*		 * Reenable the buffer descriptor		 */		rxBd->rmde_flags=Swap16(RFLG_OWN);		/*		 * Move to next buffer descriptor		 */		if(++rxBdIndex==dp->rxBdCount)			rxBdIndex=0;	}}/* * Shut down the interface * FIXME: This is a pretty simple-minded routine.  It doesn't worry * about cleaning up mbufs, shutting down daemons, etc. */static intamd79c970_stop (struct iface *iface){	amd79c970Context_t *dp;	unsigned32	ulCSR0;	int		i;	dp=pAmd79c970Context[iface->dev];	/*	 * Stop the device	 */	WR_CSR32(dp, CSR0, CSR0_STOP);	/*	 * Wait for 100mS for the device to stop	 */	for(i=0; i<100; i++)	{		RD_CSR32(dp, CSR0, ulCSR0);		if(!(ulCSR0 & (CSR0_RXON | CSR0_TXON)))		{			break;		}		rtems_ka9q_ppause(1); /* 1mS */	}	if(i >= 100)	{		return(-1);	}	/*	 * Free up all the mbufs we've allocated	 */	for(i=0; i<dp->rxBdCount; i++)	{		free_mbuf(&dp->rxMbuf[i]);	}	return 0;}/* * Show interface statistics */static voidamd79c970_show (struct iface *iface){	int i;	i=iface->dev;	printf ("      Rx Interrupts:%-8lu", pAmd79c970Context[i]->rxInterrupts);	printf ("       Not First:%-8lu", pAmd79c970Context[i]->rxNotFirst);	printf ("        Not Last:%-8lu\n", pAmd79c970Context[i]->rxNotLast);	printf ("              Giant:%-8lu", pAmd79c970Context[i]->rxGiant);	printf ("            Runt:%-8lu", pAmd79c970Context[i]->rxRunt);	printf ("       Non-octet:%-8lu\n", pAmd79c970Context[i]->rxNonOctet);	printf ("            Bad CRC:%-8lu", pAmd79c970Context[i]->rxBadCRC);	printf ("         Overrun:%-8lu", pAmd79c970Context[i]->rxOverrun);	printf ("       Collision:%-8lu\n", pAmd79c970Context[i]->rxCollision);	printf ("          Discarded:%-8lu\n", pAmd79c970Context[i]->rxDiscarded);	printf ("      Tx Interrupts:%-8lu", pAmd79c970Context[i]->txInterrupts);	printf ("        Deferred:%-8lu", pAmd79c970Context[i]->txDeferred);	printf (" Missed Hearbeat:%-8lu\n", pAmd79c970Context[i]->txHeartbeat);	printf ("         No Carrier:%-8lu", pAmd79c970Context[i]->txLostCarrier);	printf ("Retransmit Limit:%-8lu", pAmd79c970Context[i]->txRetryLimit);	printf ("  Late Collision:%-8lu\n", pAmd79c970Context[i]->txLateCollision);	printf ("           Underrun:%-8lu", pAmd79c970Context[i]->txUnderrun);	printf (" Raw output wait:%-8lu\n", pAmd79c970Context[i]->txRawWait);}/* * Attach an PC-NET driver to the system * This is the only `extern' function in the driver. * * argv[0]: interface label, e.g., "amd79c970" * argv[1]: maximum transmission unit, bytes, e.g., "1500" * argv[2]: accept ("broadcast") or ignore ("nobroadcast") broadcast packets * Following arguments are optional, but if present, must appear in * the following order: * Following arguments are optional, but if Ethernet address is * specified, Internet address must also be specified.  * ###.###.###.###   -- IP address * ##:##:##:##:##:## -- Ethernet address */intrtems_ka9q_driver_attach (int argc, char *argv[], void *p){	struct iface *iface;	struct amd79c970Context *dp;	char *cp;	int i;	int argIndex;	int broadcastFlag;	/*	 * Find a free driver	 */	for(i=0; i<NPCNETDRIVER; i++)	{		if(pAmd79c970Context[i]==NULL)			break;	}	if(i==NPCNETDRIVER)	{		printf ("Too many PC-NET drivers.\n");		return -1;	}	if(if_lookup (argv[0]) != NULL)	{		printf ("Interface %s already exists\n", argv[0]);		return -1;	}	/*	 * Note that this structure must be aligned to a 16 byte boundary	 */	pAmd79c970Context[i]=(amd79c970Context_t *)		(((unsigned32)callocw(1,				      sizeof(amd79c970Context_t)+16)+16) & ~15);	dp=pAmd79c970Context[i];	/*	 * Create an interface descriptor	 */	iface=callocw (1, sizeof *iface);	iface->name=strdup (argv[0]);	iface->mtu=atoi (argv[1]);	/*	 * Select broadcast packet handling	 */	cp=argv[2];	if(strnicmp (cp, "broadcast", strlen (cp))==0)	{		broadcastFlag=1;	}	else if(strnicmp (cp, "nobroadcast", strlen (cp))==0)	{		broadcastFlag=0;	}	else {		printf ("Argument `%s' is neither `broadcast' nor `nobroadcast'.\n", cp);		return -1;	}	argIndex=3;	/*	 * Set receive buffer descriptor count	 */	dp->rxBdCount=RX_RING_SIZE;			/*	 * Set transmit buffer descriptor count	 */	dp->txWaitTid=0;	dp->txBdCount=TX_RING_SIZE;	/*	 * Set Internet address	 */	if(argIndex<argc)		iface->addr=resolve (argv[argIndex++]);	else		iface->addr=Ip_addr;	/*	 * Set Ethernet address	 */	if(argIndex<argc)	{		iface->hwaddr=mallocw (EADDR_LEN);		gether (iface->hwaddr, argv[argIndex++]);	}	iface->dev=i;	iface->raw=amd79c970_raw;	iface->stop=amd79c970_stop;	iface->show=amd79c970_show;	dp->iface=iface;	setencap (iface, "Ethernet");	/*	 * Set up PC-NET hardware	 */	if(!amd79c970_initialize_hardware (i, broadcastFlag))	{		printf ("Unable to initialize hardware for %s\n", argv[0]);		return -1;	}	/*	 * Chain onto list of interfaces	 */	iface->next=Ifaces;	Ifaces=iface;	/*	 * Start I/O daemons	 */	cp=if_name (iface, " tx");	iface->txproc=newproc (cp, 1024, if_tx, iface->dev, iface, NULL, 0);	free (cp);	cp=if_name (iface, " rx");	iface->rxproc=newproc (cp, 1024, amd79c970_rx, iface->dev, iface, dp, 0);	free (cp);	return 0;}/* * FIXME: There should be an ioctl routine to allow things like * enabling/disabling reception of broadcast packets. */

⌨️ 快捷键说明

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