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

📄 8253xnet.c

📁 microwindows移植到S3C44B0的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* -*- 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"				/* turns network packet into a pseudoethernet */				/* frame -- does ethernet stuff that 8253x does */				/* not do -- makes minimum  64 bytes add crc, etc*/int sab8253xn_write2(struct sk_buff *skb, struct net_device *dev){	size_t cnt;	unsigned int flags;	SAB_PORT *priv = (SAB_PORT*) dev->priv;	struct sk_buff *substitute;#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 0)	if(dev->tbusy != 0)		/* something of an error */	{		++(priv->Counters.tx_drops);		dev_kfree_skb_any(skb);		return -EBUSY;		/* only during release */	}#endif	if(priv->active2.transmit == NULL)	{		return -ENOMEM;	}		DEBUGPRINT((KERN_ALERT "sab8253x: sending IP packet(bytes):\n"));	DEBUGPRINT((KERN_ALERT "sab8253x: start address is %p.\n", skb->data));		cnt = skb->tail - skb->data;	cnt = MIN(cnt, sab8253xn_rbufsize);	if(cnt < ETH_ZLEN)	{		if((skb->end - skb->data) >= ETH_ZLEN)		{			skb->tail = (skb->data + ETH_ZLEN);			cnt = ETH_ZLEN;		}		else		{			substitute = dev_alloc_skb(ETH_ZLEN);			if(substitute == NULL)			{				dev_kfree_skb_any(skb);				return 0;			}			substitute->tail = (substitute->data + ETH_ZLEN);			memcpy(substitute->data, skb->data, cnt);			cnt = ETH_ZLEN;			dev_kfree_skb_any(skb);			skb = substitute;		}	}		save_flags(flags); cli();	if((priv->active2.transmit->Count & OWNER) == OWN_SAB)	{		++(priv->Counters.tx_drops);#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 0)		dev->tbusy = 1;#else		netif_stop_queue (dev);#endif		priv->tx_full = 1;		restore_flags(flags);		return 1;	}	restore_flags(flags);#ifndef FREEINTERRUPT	if(priv->active2.transmit->HostVaddr != NULL)	{		register RING_DESCRIPTOR *freeme;				freeme = priv->active2.transmit;		do		{			skb_unlink((struct sk_buff*)freeme->HostVaddr);			dev_kfree_skb_any((struct sk_buff*)freeme->HostVaddr);			freeme->HostVaddr = NULL;			freeme = (RING_DESCRIPTOR*) freeme->VNext;		}		while(((freeme->Count & OWNER) != OWN_SAB) &&		      (freeme->HostVaddr != NULL));	}#endif	dev->trans_start = jiffies;	skb_queue_head(priv->sab8253xbuflist, skb);	priv->active2.transmit->HostVaddr = skb;	priv->active2.transmit->sendcrc = 1;	priv->active2.transmit->crcindex = 0;	priv->active2.transmit->crc = fn_calc_memory_crc32(skb->data, cnt);	priv->active2.transmit->Count = (OWN_SAB|cnt); /* must be this order */	priv->active2.transmit = 		(RING_DESCRIPTOR*) priv->active2.transmit->VNext;	priv->Counters.transmitbytes += cnt;	sab8253x_start_txS(priv);	return 0;}	/* packetizes the received character */	/* stream */static void sab8253x_receive_charsN(struct sab_port *port,				    union sab8253x_irq_status *stat){	unsigned char buf[32];	int free_fifo = 0;	int reset_fifo = 0;	int msg_done = 0;	int msg_bad = 0;	int count = 0;	int total_size = 0;	int rstatus = 0;	struct sk_buff *skb;		/* Read number of BYTES (Character + Status) available. */		if((stat->images[ISR1_IDX] & SAB82532_ISR1_RDO) || (stat->images[ISR0_IDX] & SAB82532_ISR0_RFO) )	{		++msg_bad;		++free_fifo;		++reset_fifo;	}	else	{		if (stat->images[ISR0_IDX] & SAB82532_ISR0_RPF) 		{			count = port->recv_fifo_size;			++free_fifo;		}				if (stat->images[ISR0_IDX] & SAB82532_ISR0_RME) 		{			count = READB(port,rbcl);			count &= (port->recv_fifo_size - 1);			++msg_done;			++free_fifo;						total_size = READB(port, rbch);			if(total_size & SAB82532_RBCH_OV)			{				msg_bad++;			}						rstatus = READB(port, rsta);			if((rstatus & SAB82532_RSTA_VFR) == 0)			{				msg_bad++;			}			if(rstatus & SAB82532_RSTA_RDO)			{				msg_bad++;			}			if((rstatus & SAB82532_RSTA_CRC) == 0)			{				msg_bad++;			}			if(rstatus & SAB82532_RSTA_RAB)			{				msg_bad++;			}		}	}		/* Read the FIFO. */	(*port->readfifo)(port, buf, count);		/* Issue Receive Message Complete command. */		if (free_fifo) 	{		sab8253x_cec_wait(port);		WRITEB(port, cmdr, SAB82532_CMDR_RMC);	}		if(reset_fifo)	{		sab8253x_cec_wait(port);		WRITEB(port, cmdr, SAB82532_CMDR_RHR);	}		if(port->active2.receive == NULL)	{		return;	}		if(msg_bad)	{		++(port->Counters.rx_drops);		port->active2.receive->HostVaddr->tail = port->active2.receive->HostVaddr->data; /* clear the buffer */		port->active2.receive->Count = sab8253xn_rbufsize|OWN_SAB;		return;	}		memcpy(port->active2.receive->HostVaddr->tail, buf, count);	port->active2.receive->HostVaddr->tail += count;		if(msg_done)	{		port->active2.receive->Count = 			(port->active2.receive->HostVaddr->tail - port->active2.receive->HostVaddr->data);		if((port->active2.receive->Count < (ETH_ZLEN+4+3)) || /* 4 is the CRC32 size 3 bytes from the SAB part */		   (skb = dev_alloc_skb(sab8253xn_rbufsize), skb == NULL))		{			++(port->Counters.rx_drops);			port->active2.receive->HostVaddr->tail = port->active2.receive->HostVaddr->data; 				/* clear the buffer */			port->active2.receive->Count = sab8253xn_rbufsize|OWN_SAB;		}		else		{			port->active2.receive->Count -= 3;			port->active2.receive->HostVaddr->len = port->active2.receive->Count;			port->active2.receive->HostVaddr->pkt_type = PACKET_HOST;			port->active2.receive->HostVaddr->dev = port->dev;			port->active2.receive->HostVaddr->protocol = 				eth_type_trans(port->active2.receive->HostVaddr, port->dev);			port->active2.receive->HostVaddr->tail -= 3;			++(port->Counters.receivepacket);			port->Counters.receivebytes += port->active2.receive->Count;			skb_unlink(port->active2.receive->HostVaddr);						netif_rx(port->active2.receive->HostVaddr);						skb_queue_head(port->sab8253xbuflist, skb);			port->active2.receive->HostVaddr = skb;			port->active2.receive->Count = sab8253xn_rbufsize|OWN_SAB;		}	}}static void sab8253x_check_statusN(struct sab_port *port,				   union sab8253x_irq_status *stat){	int modem_change = 0;	mctlsig_t         *sig;			if (stat->images[ISR0_IDX] & SAB82532_ISR0_RFO) 	{		port->icount.buf_overrun++;	}		/* Checking DCD */	sig = &port->dcd;	if (stat->images[sig->irq] & sig->irqmask) 	{		sig->val = ISON(port,dcd);		port->icount.dcd++;		modem_change++;	}	/* Checking CTS */	sig = &port->cts;	if (stat->images[sig->irq] & sig->irqmask) 	{		sig->val = ISON(port,cts);		port->icount.cts++;		modem_change++;	}	/* Checking DSR */	sig = &port->dsr;	if (stat->images[sig->irq] & sig->irqmask) 	{		sig->val = ISON(port,dsr);		port->icount.dsr++;		modem_change++;	}	if (modem_change)	{		wake_up_interruptible(&port->delta_msr_wait);	}		sig = &port->dcd;	if ((port->flags & FLAG8253X_CHECK_CD) &&	    (stat->images[sig->irq] & sig->irqmask)) 	{				if (sig->val)		{			netif_carrier_on(port->dev);		}		else if (!((port->flags & FLAG8253X_CALLOUT_ACTIVE) &&			   (port->flags & FLAG8253X_CALLOUT_NOHUP))) 		{			netif_carrier_off(port->dev);		}	}#if 0				/* need to think about CTS/RTS stuff for a network driver */	sig = &port->cts;	if (port->flags & FLAG8253X_CTS_FLOW) 	{				/* not setting this yet */		if (port->tty->hw_stopped) 		{			if (sig->val) 			{								port->tty->hw_stopped = 0;				sab8253x_sched_event(port, RS_EVENT_WRITE_WAKEUP);				port->interrupt_mask1 &= ~(SAB82532_IMR1_XPR);				WRITEB(port, imr1, port->interrupt_mask1);				sab8253x_start_txS(port);			}		} 		else 		{			if (!(sig->val)) 			{				port->tty->hw_stopped = 1;			}		}	}#endif}static void Sab8253xCollectStats(struct net_device *dev){		struct net_device_stats *statsp = 		&((SAB_PORT*) dev->priv)->stats;	

⌨️ 快捷键说明

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