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

📄 hdlcdrv.c

📁 linux-2.4.29操作系统的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
		return;	}	if ((--s->hdlctx.slotcnt) > 0)		return;	s->hdlctx.slotcnt = s->ch_params.slottime;	if ((random_num() % 256) > s->ch_params.ppersist)		return;	start_tx(dev, s);}/* --------------------------------------------------------------------- *//* * ===================== network driver interface ========================= */static inline int hdlcdrv_paranoia_check(struct net_device *dev,					const char *routine){	if (!dev || !dev->priv || 	    ((struct hdlcdrv_state *)dev->priv)->magic != HDLCDRV_MAGIC) {		printk(KERN_ERR "hdlcdrv: bad magic number for hdlcdrv_state "		       "struct in routine %s\n", routine);		return 1;	}	return 0;}/* --------------------------------------------------------------------- */static int hdlcdrv_send_packet(struct sk_buff *skb, struct net_device *dev){	struct hdlcdrv_state *sm;	if (hdlcdrv_paranoia_check(dev, "hdlcdrv_send_packet"))		return 0;	sm = (struct hdlcdrv_state *)dev->priv;	if (skb->data[0] != 0) {		do_kiss_params(sm, skb->data, skb->len);		dev_kfree_skb(skb);		return 0;	}	if (sm->skb)		return -1;	netif_stop_queue(dev);	sm->skb = skb;	return 0;}/* --------------------------------------------------------------------- */static int hdlcdrv_set_mac_address(struct net_device *dev, void *addr){	struct sockaddr *sa = (struct sockaddr *)addr;	/* addr is an AX.25 shifted ASCII mac address */	memcpy(dev->dev_addr, sa->sa_data, dev->addr_len); 	return 0;                                         }/* --------------------------------------------------------------------- */static struct net_device_stats *hdlcdrv_get_stats(struct net_device *dev){	struct hdlcdrv_state *sm;	if (hdlcdrv_paranoia_check(dev, "hdlcdrv_get_stats"))		return NULL;	sm = (struct hdlcdrv_state *)dev->priv;	/* 	 * Get the current statistics.  This may be called with the	 * card open or closed. 	 */	return &sm->stats;}/* --------------------------------------------------------------------- *//* * Open/initialize the board. This is called (in the current kernel) * sometime after booting when the 'ifconfig' program is run. * * This routine should set everything up anew at each open, even * registers that "should" only need to be set once at boot, so that * there is non-reboot way to recover if something goes wrong. */static int hdlcdrv_open(struct net_device *dev){	struct hdlcdrv_state *s;	int i;	if (hdlcdrv_paranoia_check(dev, "hdlcdrv_open"))		return -EINVAL;	s = (struct hdlcdrv_state *)dev->priv;	if (!s->ops || !s->ops->open)		return -ENODEV;	/*	 * initialise some variables	 */	s->hdlcrx.hbuf.rd = s->hdlcrx.hbuf.wr = 0;	s->hdlcrx.in_hdlc_rx = 0;	s->hdlcrx.rx_state = 0;		s->hdlctx.hbuf.rd = s->hdlctx.hbuf.wr = 0;	s->hdlctx.in_hdlc_tx = 0;	s->hdlctx.tx_state = 1;	s->hdlctx.numflags = 0;	s->hdlctx.bitstream = s->hdlctx.bitbuf = s->hdlctx.numbits = 0;	s->hdlctx.ptt = 0;	s->hdlctx.slotcnt = s->ch_params.slottime;	s->hdlctx.calibrate = 0;	i = s->ops->open(dev);	if (i)		return i;	netif_start_queue(dev);	return 0;}/* --------------------------------------------------------------------- *//*  * The inverse routine to hdlcdrv_open().  */static int hdlcdrv_close(struct net_device *dev){	struct hdlcdrv_state *s;	int i = 0;	if (hdlcdrv_paranoia_check(dev, "hdlcdrv_close"))		return -EINVAL;	s = (struct hdlcdrv_state *)dev->priv;	if (s->ops && s->ops->close)		i = s->ops->close(dev);	if (s->skb)		dev_kfree_skb(s->skb);	s->skb = NULL;	return i;}/* --------------------------------------------------------------------- */static int hdlcdrv_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd){	struct hdlcdrv_state *s;	struct hdlcdrv_ioctl bi;			if (hdlcdrv_paranoia_check(dev, "hdlcdrv_ioctl"))		return -EINVAL;	s = (struct hdlcdrv_state *)dev->priv;	if (cmd != SIOCDEVPRIVATE) {		if (s->ops && s->ops->ioctl)			return s->ops->ioctl(dev, ifr, &bi, cmd);		return -ENOIOCTLCMD;	}	if (copy_from_user(&bi, ifr->ifr_data, sizeof(bi)))		return -EFAULT;	switch (bi.cmd) {	default:		if (s->ops && s->ops->ioctl)			return s->ops->ioctl(dev, ifr, &bi, cmd);		return -ENOIOCTLCMD;	case HDLCDRVCTL_GETCHANNELPAR:		bi.data.cp.tx_delay = s->ch_params.tx_delay;		bi.data.cp.tx_tail = s->ch_params.tx_tail;		bi.data.cp.slottime = s->ch_params.slottime;		bi.data.cp.ppersist = s->ch_params.ppersist;		bi.data.cp.fulldup = s->ch_params.fulldup;		break;	case HDLCDRVCTL_SETCHANNELPAR:		if (!capable(CAP_NET_ADMIN))			return -EACCES;		s->ch_params.tx_delay = bi.data.cp.tx_delay;		s->ch_params.tx_tail = bi.data.cp.tx_tail;		s->ch_params.slottime = bi.data.cp.slottime;		s->ch_params.ppersist = bi.data.cp.ppersist;		s->ch_params.fulldup = bi.data.cp.fulldup;		s->hdlctx.slotcnt = 1;		return 0;			case HDLCDRVCTL_GETMODEMPAR:		bi.data.mp.iobase = dev->base_addr;		bi.data.mp.irq = dev->irq;		bi.data.mp.dma = dev->dma;		bi.data.mp.dma2 = s->ptt_out.dma2;		bi.data.mp.seriobase = s->ptt_out.seriobase;		bi.data.mp.pariobase = s->ptt_out.pariobase;		bi.data.mp.midiiobase = s->ptt_out.midiiobase;		break;	case HDLCDRVCTL_SETMODEMPAR:		if ((!capable(CAP_SYS_RAWIO)) || netif_running(dev))			return -EACCES;		dev->base_addr = bi.data.mp.iobase;		dev->irq = bi.data.mp.irq;		dev->dma = bi.data.mp.dma;		s->ptt_out.dma2 = bi.data.mp.dma2;		s->ptt_out.seriobase = bi.data.mp.seriobase;		s->ptt_out.pariobase = bi.data.mp.pariobase;		s->ptt_out.midiiobase = bi.data.mp.midiiobase;		return 0;			case HDLCDRVCTL_GETSTAT:		bi.data.cs.ptt = hdlcdrv_ptt(s);		bi.data.cs.dcd = s->hdlcrx.dcd;		bi.data.cs.ptt_keyed = s->ptt_keyed;		bi.data.cs.tx_packets = s->stats.tx_packets;		bi.data.cs.tx_errors = s->stats.tx_errors;		bi.data.cs.rx_packets = s->stats.rx_packets;		bi.data.cs.rx_errors = s->stats.rx_errors;		break;			case HDLCDRVCTL_OLDGETSTAT:		bi.data.ocs.ptt = hdlcdrv_ptt(s);		bi.data.ocs.dcd = s->hdlcrx.dcd;		bi.data.ocs.ptt_keyed = s->ptt_keyed;		break;			case HDLCDRVCTL_CALIBRATE:		if(!capable(CAP_SYS_RAWIO))			return -EPERM;		s->hdlctx.calibrate = bi.data.calibrate * s->par.bitrate / 16;		return 0;	case HDLCDRVCTL_GETSAMPLES:#ifndef HDLCDRV_DEBUG		return -EPERM;#else /* HDLCDRV_DEBUG */		if (s->bitbuf_channel.rd == s->bitbuf_channel.wr) 			return -EAGAIN;		bi.data.bits = 			s->bitbuf_channel.buffer[s->bitbuf_channel.rd];		s->bitbuf_channel.rd = (s->bitbuf_channel.rd+1) %			sizeof(s->bitbuf_channel.buffer);		break;#endif /* HDLCDRV_DEBUG */					case HDLCDRVCTL_GETBITS:#ifndef HDLCDRV_DEBUG		return -EPERM;#else /* HDLCDRV_DEBUG */		if (s->bitbuf_hdlc.rd == s->bitbuf_hdlc.wr) 			return -EAGAIN;		bi.data.bits = 			s->bitbuf_hdlc.buffer[s->bitbuf_hdlc.rd];		s->bitbuf_hdlc.rd = (s->bitbuf_hdlc.rd+1) %			sizeof(s->bitbuf_hdlc.buffer);		break;		#endif /* HDLCDRV_DEBUG */	case HDLCDRVCTL_DRIVERNAME:		if (s->ops && s->ops->drvname) {			strncpy(bi.data.drivername, s->ops->drvname, 				sizeof(bi.data.drivername));			break;		}		bi.data.drivername[0] = '\0';		break;			}	if (copy_to_user(ifr->ifr_data, &bi, sizeof(bi)))		return -EFAULT;	return 0;}/* --------------------------------------------------------------------- *//* * Check for a network adaptor of this type, and return '0' if one exists. * If dev->base_addr == 0, probe all likely locations. * If dev->base_addr == 1, always return failure. * If dev->base_addr == 2, allocate space for the device and return success * (detachable devices only). */static int hdlcdrv_probe(struct net_device *dev){	const struct hdlcdrv_channel_params dflt_ch_params = { 		20, 2, 10, 40, 0 	};	struct hdlcdrv_state *s;	if (!dev)		return -ENXIO;	/*	 * not a real probe! only initialize data structures	 */	s = (struct hdlcdrv_state *)dev->priv;	/*	 * initialize the hdlcdrv_state struct	 */	s->ch_params = dflt_ch_params;	s->ptt_keyed = 0;	spin_lock_init(&s->hdlcrx.hbuf.lock);	s->hdlcrx.hbuf.rd = s->hdlcrx.hbuf.wr = 0;	s->hdlcrx.in_hdlc_rx = 0;	s->hdlcrx.rx_state = 0;		spin_lock_init(&s->hdlctx.hbuf.lock);	s->hdlctx.hbuf.rd = s->hdlctx.hbuf.wr = 0;	s->hdlctx.in_hdlc_tx = 0;	s->hdlctx.tx_state = 1;	s->hdlctx.numflags = 0;	s->hdlctx.bitstream = s->hdlctx.bitbuf = s->hdlctx.numbits = 0;	s->hdlctx.ptt = 0;	s->hdlctx.slotcnt = s->ch_params.slottime;	s->hdlctx.calibrate = 0;#ifdef HDLCDRV_DEBUG	s->bitbuf_channel.rd = s->bitbuf_channel.wr = 0;	s->bitbuf_channel.shreg = 0x80;	s->bitbuf_hdlc.rd = s->bitbuf_hdlc.wr = 0;	s->bitbuf_hdlc.shreg = 0x80;#endif /* HDLCDRV_DEBUG */	/*	 * initialize the device struct	 */	dev->open = hdlcdrv_open;	dev->stop = hdlcdrv_close;	dev->do_ioctl = hdlcdrv_ioctl;	dev->hard_start_xmit = hdlcdrv_send_packet;	dev->get_stats = hdlcdrv_get_stats;	/* Fill in the fields of the device structure */	s->skb = NULL;	#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)	dev->hard_header = ax25_encapsulate;	dev->rebuild_header = ax25_rebuild_header;#else /* CONFIG_AX25 || CONFIG_AX25_MODULE */	dev->hard_header = NULL;	dev->rebuild_header = NULL;#endif /* CONFIG_AX25 || CONFIG_AX25_MODULE */	dev->set_mac_address = hdlcdrv_set_mac_address;		dev->type = ARPHRD_AX25;           /* AF_AX25 device */	dev->hard_header_len = AX25_MAX_HEADER_LEN + AX25_BPQ_HEADER_LEN;	dev->mtu = AX25_DEF_PACLEN;        /* eth_mtu is the default */	dev->addr_len = AX25_ADDR_LEN;     /* sizeof an ax.25 address */	memcpy(dev->broadcast, ax25_bcast, AX25_ADDR_LEN);	memcpy(dev->dev_addr, ax25_nocall, AX25_ADDR_LEN);	dev->tx_queue_len = 16;	/* New style flags */	dev->flags = 0;	return 0;}/* --------------------------------------------------------------------- */int hdlcdrv_register_hdlcdrv(struct net_device *dev, const struct hdlcdrv_ops *ops,			     unsigned int privsize, char *ifname,			     unsigned int baseaddr, unsigned int irq, 			     unsigned int dma) {	struct hdlcdrv_state *s;	if (!dev || !ops)		return -EACCES;	if (privsize < sizeof(struct hdlcdrv_state))		privsize = sizeof(struct hdlcdrv_state);	memset(dev, 0, sizeof(struct net_device));	if (!(s = dev->priv = kmalloc(privsize, GFP_KERNEL)))		return -ENOMEM;	/*	 * initialize part of the hdlcdrv_state struct	 */	memset(s, 0, privsize);	s->magic = HDLCDRV_MAGIC;	strncpy(dev->name, ifname, sizeof(dev->name));	s->ops = ops;	/*	 * initialize part of the device struct	 */	dev->if_port = 0;	dev->init = hdlcdrv_probe;	dev->base_addr = baseaddr;	dev->irq = irq;	dev->dma = dma;	if (register_netdev(dev)) {		printk(KERN_WARNING "hdlcdrv: cannot register net "		       "device %s\n", dev->name);		kfree(dev->priv);		return -ENXIO;	}	MOD_INC_USE_COUNT;	return 0;}/* --------------------------------------------------------------------- */int hdlcdrv_unregister_hdlcdrv(struct net_device *dev) {	struct hdlcdrv_state *s;	if (!dev)		return -EINVAL;	if (!(s = (struct hdlcdrv_state *)dev->priv))		return -EINVAL;	if (s->magic != HDLCDRV_MAGIC)		return -EINVAL;	if (s->ops->close)		s->ops->close(dev);	unregister_netdev(dev);	kfree(s);	MOD_DEC_USE_COUNT;	return 0;}/* --------------------------------------------------------------------- */EXPORT_SYMBOL(hdlcdrv_receiver);EXPORT_SYMBOL(hdlcdrv_transmitter);EXPORT_SYMBOL(hdlcdrv_arbitrate);EXPORT_SYMBOL(hdlcdrv_register_hdlcdrv);EXPORT_SYMBOL(hdlcdrv_unregister_hdlcdrv);/* --------------------------------------------------------------------- */static int __init hdlcdrv_init_driver(void){	printk(KERN_INFO "hdlcdrv: (C) 1996-2000 Thomas Sailer HB9JNX/AE4WA\n");	printk(KERN_INFO "hdlcdrv: version 0.8 compiled " __TIME__ " " __DATE__ "\n");	return 0;}/* --------------------------------------------------------------------- */static void __exit hdlcdrv_cleanup_driver(void){	printk(KERN_INFO "hdlcdrv: cleanup\n");}/* --------------------------------------------------------------------- */MODULE_AUTHOR("Thomas M. Sailer, sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu");MODULE_DESCRIPTION("Packet Radio network interface HDLC encoder/decoder");MODULE_LICENSE("GPL");module_init(hdlcdrv_init_driver);module_exit(hdlcdrv_cleanup_driver);/* --------------------------------------------------------------------- */

⌨️ 快捷键说明

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