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

📄 dscc4.c

📁 内核linux2.4.20,可跟rtlinux3.2打补丁 组成实时linux系统,编译内核
💻 C
📖 第 1 页 / 共 4 页
字号:
	dev_id = dpriv->dev_id;	writel(0x00050000, ioaddr + SCC_REG_START(dev_id) + CCR2);	writel(MTFi|Rdr|Rdt, ioaddr + CH0CFG + dev_id*0x0c); /* Reset Rx/Tx */	writel(0x00000001, ioaddr + GCMDR);	dscc4_release_ring(dpriv);	MOD_DEC_USE_COUNT;	return 0;}static int dscc4_set_clock(struct net_device *dev, u32 *bps, u32 *state){	struct dscc4_dev_priv *dpriv = (struct dscc4_dev_priv *)dev->priv;	u32 brr;	*state &= ~Ccr0ClockMask;	if (*bps) { /* DCE */		u32 n = 0, m = 0, divider;		int xtal;		xtal = dpriv->pci_priv->xtal_hz;		if (!xtal)			return -1;		divider = xtal / *bps;		if (divider > BRR_DIVIDER_MAX) {			divider >>= 4;			*state |= 0x00000036; /* Clock mode 6b (BRG/16) */		} else			*state |= 0x00000037; /* Clock mode 7b (BRG) */		if (divider >> 22) {			n = 63;			m = 15;		} else if (divider) {			/* Extraction of the 6 highest weighted bits */			m = 0;			while (0xffffffc0 & divider) {				m++;				divider >>= 1;			}			n = divider;		}		brr = (m << 8) | n;		divider = n << m;		if (!(*state & 0x00000001)) /* Clock mode 6b */			divider <<= 4;		*bps = xtal / divider;	} else { /* DTE */		/* 		 * "state" already reflects Clock mode 0a. 		 * Nothing more to be done 		 */		brr = 0;	}	writel(brr, dev->base_addr + BRR + SCC_REG_START(dpriv->dev_id));	return 0;}#ifdef LATER_PLEASE/* * -*- [RFC] Configuring Synchronous Interfaces in Linux -*- */// FIXME: MEDIA already defined in linux/hdlc.h#define HDLC_MEDIA_V35		0#define HDLC_MEDIA_RS232	1#define HDLC_MEDIA_X21		2#define HDLC_MEDIA_E1		3#define HDLC_MEDIA_HSSI		4#define HDLC_CODING_NRZ		0#define HDLC_CODING_NRZI	1#define HDLC_CODING_FM0		2#define HDLC_CODING_FM1		3#define HDLC_CODING_MANCHESTER	4#define HDLC_CRC_NONE		0#define HDLC_CRC_16		1#define HDLC_CRC_32		2#define HDLC_CRC_CCITT		3/* RFC: add the crc reset value ? */struct hdlc_physical {	u8 media;	u8 coding;	u32 rate;	u8 crc;	u8 crc_siz;		/* 2 or 4 bytes */	u8 shared_flags;	/* Discouraged on the DSCC4 */};// FIXME: PROTO already defined in linux/hdlc.h#define HDLC_PROTO_RAW		0#define HDLC_PROTO_FR		1#define HDLC_PROTO_X25		2#define HDLC_PROTO_PPP		3#define HDLC_PROTO_CHDLC	4struct hdlc_protocol {	u8 proto; 		union {	} u;};struct screq {	u16 media_group;	union {		struct hdlc_physical hdlc_phy;		struct hdlc_protocol hdlc_proto;	} u;};// FIXME: go sub-module static struct {	u16 coding;	u16 bits;} map[] = {	{HDLC_CODING_NRZ,		0x00},	{HDLC_CODING_NRZI,		0x20},	{HDLC_CODING_FM0,		0x40},	{HDLC_CODING_FM1,		0x50},	{HDLC_CODING_MANCHESTER,	0x60},	{65535,	0x00}};#endif /* LATER_PLEASE */static int dscc4_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd){	struct dscc4_dev_priv *dpriv = dev->priv;	u32 state, ioaddr;        if (dev->flags & IFF_UP)                return -EBUSY;	switch (cmd) {		/* Set built-in quartz frequency */		case SIOCDEVPRIVATE: {			u32 hz;			hz = ifr->ifr_ifru.ifru_ivalue;			if (hz >= 33000000) /* 33 MHz */				return -EOPNOTSUPP;			dpriv->pci_priv->xtal_hz = hz;			return 0;		}		/* Set/unset loopback */		case SIOCDEVPRIVATE+1: {			u32 flags;				ioaddr = dev->base_addr + CCR1 +				 SCC_REG_START(dpriv->dev_id);			state = readl(ioaddr);			flags = ifr->ifr_ifru.ifru_ivalue;			if (flags & 0x00000001) {				printk(KERN_DEBUG "%s: loopback\n", dev->name);				state |= 0x00000100;			} else {				printk(KERN_DEBUG "%s: normal\n", dev->name);				state &= ~0x00000100;			}			writel(state, ioaddr);			return 0;		}#ifdef LATER_PLEASE		case SIOCDEVPRIVATE+2: {		{			struct screq scr;			err = copy_from_user(&scr, ifr->ifr_ifru.ifru_data, sizeof(struct screq));			if (err)				return err;			do {				if (scr.u.hdlc_phy.coding == map[i].coding)					break;			} while (map[++i].coding != 65535);			if (!map[i].coding)				return -EOPNOTSUPP;						ioaddr = dev->base_addr + CCR0 +				 SCC_REG_START(dpriv->dev_id);			state = readl(ioaddr) & ~EncodingMask;			state |= (u32)map[i].bits << 16;			writel(state, ioaddr);				printk("state: %08x\n", state); /* DEBUG */			return 0;		}		case SIOCDEVPRIVATE+3: {			struct screq *scr = (struct screq *)ifr->ifr_ifru.ifru_data;			ioaddr = dev->base_addr + CCR0 +				 SCC_REG_START(dpriv->dev_id);			state = (readl(ioaddr) & EncodingMask) >> 16;			do {				if (state == map[i].bits)					break;			} while (map[++i].coding);			return put_user(map[i].coding, (u16 *)scr->u.hdlc_phy.coding);		}#endif /* LATER_PLEASE */		case HDLCSCLOCKRATE:		{			u32 state, bps; 			bps = ifr->ifr_ifru.ifru_ivalue;			ioaddr = dev->base_addr + CCR0 +				 SCC_REG_START(dpriv->dev_id);			state = readl(ioaddr);			if(dscc4_set_clock(dev, &bps, &state) < 0)				return -EOPNOTSUPP;			if (bps) { /* DCE */				printk(KERN_DEBUG "%s: generated RxClk (DCE)\n",				       dev->name);				ifr->ifr_ifru.ifru_ivalue = bps;			} else { /* DTE */				state = 0x80001000;				printk(KERN_DEBUG "%s: external RxClk (DTE)\n",				       dev->name);			}			writel(state, ioaddr);				return 0;		}		case HDLCGCLOCKRATE: {			u32 brr;			int bps;			brr = readl(dev->base_addr + BRR + 				    SCC_REG_START(dpriv->dev_id));			bps = dpriv->pci_priv->xtal_hz >> (brr >> 8);			bps /= (brr & 0x3f) + 1;			ifr->ifr_ifru.ifru_ivalue = bps;			return 0;		}		default:			return -EOPNOTSUPP;	}}static int dscc4_change_mtu(struct net_device *dev, int mtu){	/* FIXME: chainsaw coded... */	if ((mtu <= 3) || (mtu > 65531))		return -EINVAL;        if(dev->flags & IFF_UP)                return -EBUSY;	dev->mtu = mtu;        return(0);}static void dscc4_irq(int irq, void *dev_instance, struct pt_regs *ptregs){	struct net_device *dev = dev_instance;	struct dscc4_pci_priv *priv;	u32 ioaddr, state;	unsigned long flags;	int i;	priv = ((struct dscc4_dev_priv *)dev->priv)->pci_priv;	/* 	 * FIXME: shorten the protected area (set some bit telling we're	 * in an interrupt or increment some work-to-do counter etc...)	 */	spin_lock_irqsave(&priv->lock, flags);	ioaddr = dev->base_addr;	state = readl(ioaddr + GSTAR);	if (!state)		goto out;	writel(state, ioaddr + GSTAR);	if (state & Arf) { 		printk(KERN_ERR "%s: failure (Arf). Harass the maintener\n",		       dev->name);		goto out;	}	state &= ~ArAck;	if (state & Cfg) {		if (debug)			printk(KERN_DEBUG "CfgIV\n");		if (priv->iqcfg[priv->cfg_cur++%IRQ_RING_SIZE] & Arf)			printk(KERN_ERR "%s: %s failed\n", dev->name, "CFG");		if (!(state &= ~Cfg))			goto out;	}	if (state & RxEvt) {		i = dev_per_card - 1;		do {			dscc4_rx_irq(priv, dev + i);		} while (--i >= 0);		state &= ~RxEvt;	}	if (state & TxEvt) {		i = dev_per_card - 1;		do {			dscc4_tx_irq(priv, dev + i);		} while (--i >= 0);		state &= ~TxEvt;	}out:	spin_unlock_irqrestore(&priv->lock, flags);}static __inline__ void dscc4_tx_irq(struct dscc4_pci_priv *ppriv, 				    struct net_device *dev){	struct dscc4_dev_priv *dpriv = dev->priv;	u32 state;	int cur, loop = 0;try:	cur = dpriv->iqtx_current%IRQ_RING_SIZE;	state = dpriv->iqtx[cur];	if (!state) {#ifdef DEBUG		if (loop > 1)			printk(KERN_DEBUG "%s: Tx irq loop=%d\n", dev->name, loop);#endif		if (loop && netif_queue_stopped(dev))			if ((dpriv->tx_dirty + 8) >= dpriv->tx_current)				netif_wake_queue(dev);		return;	}	loop++;	dpriv->iqtx[cur] = 0;	dpriv->iqtx_current++;#ifdef DEBUG_PARANOID	if (SOURCE_ID(state) != dpriv->dev_id) {		printk(KERN_DEBUG "%s (Tx): Source Id=%d, state=%08x\n",		       dev->name, SOURCE_ID(state), state );		return;	}	if (state & 0x0df80c00) {		printk(KERN_DEBUG "%s (Tx): state=%08x (UFO alert)\n",		       dev->name, state);		return;	}#endif	// state &= 0x0fffffff; /* Tracking the analyzed bits */	if (state & SccEvt) {		if (state & Alls) {			struct TxFD *tx_fd;			struct sk_buff *skb;			cur = dpriv->tx_dirty%TX_RING_SIZE;			tx_fd = dpriv->tx_fd + cur;			skb = dpriv->tx_skbuff[cur];			/* XXX: hideous kludge - to be removed "later" */			if (!skb) {				printk(KERN_ERR "%s: NULL skb in tx_irq at index %d\n", dev->name, cur);				goto try;			}			dpriv->tx_dirty++; // MUST be after skb test			/* Happens sometime. Don't know what triggers it */			if (!(tx_fd->complete & DataComplete)) {				u32 ioaddr, isr;				ioaddr = dev->base_addr + 					 SCC_REG_START(dpriv->dev_id) + ISR;				isr = readl(ioaddr);				printk(KERN_DEBUG 				       "%s: DataComplete=0 cur=%d isr=%08x state=%08x\n",				       dev->name, cur, isr, state);				writel(isr, ioaddr);				dpriv->stats.tx_dropped++;			} else {				tx_fd->complete &= ~DataComplete;				if (tx_fd->state & FrameEnd) {					dpriv->stats.tx_packets++;					dpriv->stats.tx_bytes += skb->len;				}			}			dpriv->tx_skbuff[cur] = NULL;			pci_unmap_single(ppriv->pdev, tx_fd->data, skb->len,					 PCI_DMA_TODEVICE);			tx_fd->data = 0; /* DEBUG */			dev_kfree_skb_irq(skb);{ // DEBUG			cur = (dpriv->tx_dirty-1)%TX_RING_SIZE;			tx_fd = dpriv->tx_fd + cur;			tx_fd->state |= Hold;}			if (!(state &= ~Alls))				goto try;		}		/* 		 * Transmit Data Underrun		 */		if (state & Xdu) {			printk(KERN_ERR "dscc4: XDU. Contact maintainer\n");			dpriv->flags = NeedIDT; 			/* Tx reset */			writel(MTFi | Rdt, 			       dev->base_addr + 0x0c*dpriv->dev_id + CH0CFG);			writel(0x00000001, dev->base_addr + GCMDR);			return;		}		if (state & Xmr) {			/* Frame needs to be sent again - FIXME */			//dscc4_start_xmit(dpriv->tx_skbuff[dpriv->tx_dirty], dev);			if (!(state &= ~0x00002000)) /* DEBUG */				goto try;		}		if (state & Xpr) {			unsigned long ioaddr = dev->base_addr;			unsigned long scc_offset;			u32 scc_addr;			scc_offset = ioaddr + SCC_REG_START(dpriv->dev_id);			scc_addr = ioaddr + 0x0c*dpriv->dev_id;			if (readl(scc_offset + STAR) & SccBusy)				printk(KERN_DEBUG "%s busy. Fatal\n", 				       dev->name);			/*			 * Keep this order: IDT before IDR			 */			if (dpriv->flags & NeedIDT) {				writel(MTFi | Idt, scc_addr + CH0CFG);				writel(dpriv->tx_fd_dma + 				       (dpriv->tx_dirty%TX_RING_SIZE)*				       sizeof(struct TxFD), scc_addr + CH0BTDA);				if(dscc4_do_action(dev, "IDT"))					goto err_xpr;				dpriv->flags &= ~NeedIDT;				mb();			}			if (dpriv->flags & NeedIDR) {				writel(MTFi | Idr, scc_addr + CH0CFG);				writel(dpriv->rx_fd_dma + 				       (dpriv->rx_current%RX_RING_SIZE)*				       sizeof(struct RxFD), scc_addr + CH0BRDA);

⌨️ 快捷键说明

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