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

📄 synclink_gt.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	else		value &= ~BIT6;	wr_reg16(info, TCR, value);	spin_unlock_irqrestore(&info->lock,flags);}#if SYNCLINK_GENERIC_HDLC/** * called by generic HDLC layer when protocol selected (PPP, frame relay, etc.) * set encoding and frame check sequence (FCS) options * * dev       pointer to network device structure * encoding  serial encoding setting * parity    FCS setting * * returns 0 if success, otherwise error code */static int hdlcdev_attach(struct net_device *dev, unsigned short encoding,			  unsigned short parity){	struct slgt_info *info = dev_to_port(dev);	unsigned char  new_encoding;	unsigned short new_crctype;	/* return error if TTY interface open */	if (info->count)		return -EBUSY;	DBGINFO(("%s hdlcdev_attach\n", info->device_name));	switch (encoding)	{	case ENCODING_NRZ:        new_encoding = HDLC_ENCODING_NRZ; break;	case ENCODING_NRZI:       new_encoding = HDLC_ENCODING_NRZI_SPACE; break;	case ENCODING_FM_MARK:    new_encoding = HDLC_ENCODING_BIPHASE_MARK; break;	case ENCODING_FM_SPACE:   new_encoding = HDLC_ENCODING_BIPHASE_SPACE; break;	case ENCODING_MANCHESTER: new_encoding = HDLC_ENCODING_BIPHASE_LEVEL; break;	default: return -EINVAL;	}	switch (parity)	{	case PARITY_NONE:            new_crctype = HDLC_CRC_NONE; break;	case PARITY_CRC16_PR1_CCITT: new_crctype = HDLC_CRC_16_CCITT; break;	case PARITY_CRC32_PR1_CCITT: new_crctype = HDLC_CRC_32_CCITT; break;	default: return -EINVAL;	}	info->params.encoding = new_encoding;	info->params.crc_type = new_crctype;	/* if network interface up, reprogram hardware */	if (info->netcount)		program_hw(info);	return 0;}/** * called by generic HDLC layer to send frame * * skb  socket buffer containing HDLC frame * dev  pointer to network device structure * * returns 0 if success, otherwise error code */static int hdlcdev_xmit(struct sk_buff *skb, struct net_device *dev){	struct slgt_info *info = dev_to_port(dev);	struct net_device_stats *stats = hdlc_stats(dev);	unsigned long flags;	DBGINFO(("%s hdlc_xmit\n", dev->name));	/* stop sending until this frame completes */	netif_stop_queue(dev);	/* copy data to device buffers */	info->tx_count = skb->len;	tx_load(info, skb->data, skb->len);	/* update network statistics */	stats->tx_packets++;	stats->tx_bytes += skb->len;	/* done with socket buffer, so free it */	dev_kfree_skb(skb);	/* save start time for transmit timeout detection */	dev->trans_start = jiffies;	/* start hardware transmitter if necessary */	spin_lock_irqsave(&info->lock,flags);	if (!info->tx_active)	 	tx_start(info);	spin_unlock_irqrestore(&info->lock,flags);	return 0;}/** * called by network layer when interface enabled * claim resources and initialize hardware * * dev  pointer to network device structure * * returns 0 if success, otherwise error code */static int hdlcdev_open(struct net_device *dev){	struct slgt_info *info = dev_to_port(dev);	int rc;	unsigned long flags;	if (!try_module_get(THIS_MODULE))		return -EBUSY;	DBGINFO(("%s hdlcdev_open\n", dev->name));	/* generic HDLC layer open processing */	if ((rc = hdlc_open(dev)))		return rc;	/* arbitrate between network and tty opens */	spin_lock_irqsave(&info->netlock, flags);	if (info->count != 0 || info->netcount != 0) {		DBGINFO(("%s hdlc_open busy\n", dev->name));		spin_unlock_irqrestore(&info->netlock, flags);		return -EBUSY;	}	info->netcount=1;	spin_unlock_irqrestore(&info->netlock, flags);	/* claim resources and init adapter */	if ((rc = startup(info)) != 0) {		spin_lock_irqsave(&info->netlock, flags);		info->netcount=0;		spin_unlock_irqrestore(&info->netlock, flags);		return rc;	}	/* assert DTR and RTS, apply hardware settings */	info->signals |= SerialSignal_RTS + SerialSignal_DTR;	program_hw(info);	/* enable network layer transmit */	dev->trans_start = jiffies;	netif_start_queue(dev);	/* inform generic HDLC layer of current DCD status */	spin_lock_irqsave(&info->lock, flags);	get_signals(info);	spin_unlock_irqrestore(&info->lock, flags);	if (info->signals & SerialSignal_DCD)		netif_carrier_on(dev);	else		netif_carrier_off(dev);	return 0;}/** * called by network layer when interface is disabled * shutdown hardware and release resources * * dev  pointer to network device structure * * returns 0 if success, otherwise error code */static int hdlcdev_close(struct net_device *dev){	struct slgt_info *info = dev_to_port(dev);	unsigned long flags;	DBGINFO(("%s hdlcdev_close\n", dev->name));	netif_stop_queue(dev);	/* shutdown adapter and release resources */	shutdown(info);	hdlc_close(dev);	spin_lock_irqsave(&info->netlock, flags);	info->netcount=0;	spin_unlock_irqrestore(&info->netlock, flags);	module_put(THIS_MODULE);	return 0;}/** * called by network layer to process IOCTL call to network device * * dev  pointer to network device structure * ifr  pointer to network interface request structure * cmd  IOCTL command code * * returns 0 if success, otherwise error code */static int hdlcdev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd){	const size_t size = sizeof(sync_serial_settings);	sync_serial_settings new_line;	sync_serial_settings __user *line = ifr->ifr_settings.ifs_ifsu.sync;	struct slgt_info *info = dev_to_port(dev);	unsigned int flags;	DBGINFO(("%s hdlcdev_ioctl\n", dev->name));	/* return error if TTY interface open */	if (info->count)		return -EBUSY;	if (cmd != SIOCWANDEV)		return hdlc_ioctl(dev, ifr, cmd);	switch(ifr->ifr_settings.type) {	case IF_GET_IFACE: /* return current sync_serial_settings */		ifr->ifr_settings.type = IF_IFACE_SYNC_SERIAL;		if (ifr->ifr_settings.size < size) {			ifr->ifr_settings.size = size; /* data size wanted */			return -ENOBUFS;		}		flags = info->params.flags & (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL |					      HDLC_FLAG_RXC_BRG    | HDLC_FLAG_RXC_TXCPIN |					      HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL |					      HDLC_FLAG_TXC_BRG    | HDLC_FLAG_TXC_RXCPIN);		switch (flags){		case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_TXCPIN): new_line.clock_type = CLOCK_EXT; break;		case (HDLC_FLAG_RXC_BRG    | HDLC_FLAG_TXC_BRG):    new_line.clock_type = CLOCK_INT; break;		case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_BRG):    new_line.clock_type = CLOCK_TXINT; break;		case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_RXCPIN): new_line.clock_type = CLOCK_TXFROMRX; break;		default: new_line.clock_type = CLOCK_DEFAULT;		}		new_line.clock_rate = info->params.clock_speed;		new_line.loopback   = info->params.loopback ? 1:0;		if (copy_to_user(line, &new_line, size))			return -EFAULT;		return 0;	case IF_IFACE_SYNC_SERIAL: /* set sync_serial_settings */		if(!capable(CAP_NET_ADMIN))			return -EPERM;		if (copy_from_user(&new_line, line, size))			return -EFAULT;		switch (new_line.clock_type)		{		case CLOCK_EXT:      flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_TXCPIN; break;		case CLOCK_TXFROMRX: flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_RXCPIN; break;		case CLOCK_INT:      flags = HDLC_FLAG_RXC_BRG    | HDLC_FLAG_TXC_BRG;    break;		case CLOCK_TXINT:    flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_BRG;    break;		case CLOCK_DEFAULT:  flags = info->params.flags &					     (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL |					      HDLC_FLAG_RXC_BRG    | HDLC_FLAG_RXC_TXCPIN |					      HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL |					      HDLC_FLAG_TXC_BRG    | HDLC_FLAG_TXC_RXCPIN); break;		default: return -EINVAL;		}		if (new_line.loopback != 0 && new_line.loopback != 1)			return -EINVAL;		info->params.flags &= ~(HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL |					HDLC_FLAG_RXC_BRG    | HDLC_FLAG_RXC_TXCPIN |					HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL |					HDLC_FLAG_TXC_BRG    | HDLC_FLAG_TXC_RXCPIN);		info->params.flags |= flags;		info->params.loopback = new_line.loopback;		if (flags & (HDLC_FLAG_RXC_BRG | HDLC_FLAG_TXC_BRG))			info->params.clock_speed = new_line.clock_rate;		else			info->params.clock_speed = 0;		/* if network interface up, reprogram hardware */		if (info->netcount)			program_hw(info);		return 0;	default:		return hdlc_ioctl(dev, ifr, cmd);	}}/** * called by network layer when transmit timeout is detected * * dev  pointer to network device structure */static void hdlcdev_tx_timeout(struct net_device *dev){	struct slgt_info *info = dev_to_port(dev);	struct net_device_stats *stats = hdlc_stats(dev);	unsigned long flags;	DBGINFO(("%s hdlcdev_tx_timeout\n", dev->name));	stats->tx_errors++;	stats->tx_aborted_errors++;	spin_lock_irqsave(&info->lock,flags);	tx_stop(info);	spin_unlock_irqrestore(&info->lock,flags);	netif_wake_queue(dev);}/** * called by device driver when transmit completes * reenable network layer transmit if stopped * * info  pointer to device instance information */static void hdlcdev_tx_done(struct slgt_info *info){	if (netif_queue_stopped(info->netdev))		netif_wake_queue(info->netdev);}/** * called by device driver when frame received * pass frame to network layer * * info  pointer to device instance information * buf   pointer to buffer contianing frame data * size  count of data bytes in buf */static void hdlcdev_rx(struct slgt_info *info, char *buf, int size){	struct sk_buff *skb = dev_alloc_skb(size);	struct net_device *dev = info->netdev;	struct net_device_stats *stats = hdlc_stats(dev);	DBGINFO(("%s hdlcdev_rx\n", dev->name));	if (skb == NULL) {		DBGERR(("%s: can't alloc skb, drop packet\n", dev->name));		stats->rx_dropped++;		return;	}	memcpy(skb_put(skb, size),buf,size);	skb->protocol = hdlc_type_trans(skb, info->netdev);	stats->rx_packets++;	stats->rx_bytes += size;	netif_rx(skb);	info->netdev->last_rx = jiffies;}/** * called by device driver when adding device instance * do generic HDLC initialization * * info  pointer to device instance information * * returns 0 if success, otherwise error code */static int hdlcdev_init(struct slgt_info *info){	int rc;	struct net_device *dev;	hdlc_device *hdlc;	/* allocate and initialize network and HDLC layer objects */	if (!(dev = alloc_hdlcdev(info))) {		printk(KERN_ERR "%s hdlc device alloc failure\n", info->device_name);		return -ENOMEM;	}	/* for network layer reporting purposes only */	dev->mem_start = info->phys_reg_addr;	dev->mem_end   = info->phys_reg_addr + SLGT_REG_SIZE - 1;	dev->irq       = info->irq_level;	/* network layer callbacks and settings */	dev->do_ioctl       = hdlcdev_ioctl;	dev->open           = hdlcdev_open;	dev->stop           = hdlcdev_close;	dev->tx_timeout     = hdlcdev_tx_timeout;	dev->watchdog_timeo = 10*HZ;	dev->tx_queue_len   = 50;	/* generic HDLC layer callbacks and settings */	hdlc         = dev_to_hdlc(dev);	hdlc->attach = hdlcdev_attach;	hdlc->xmit   = hdlcdev_xmit;	/* register objects with HDLC layer */	if ((rc = register_hdlc_device(dev))) {		printk(KERN_WARNING "%s:unable to register hdlc device\n",__FILE__);		free_netdev(dev);		return rc;	}	info->netdev = dev;	return 0;}/** * called by device driver when removing device instance * do generic HDLC cleanup * * info  pointer to device instance information */static void hdlcdev_exit(struct slgt_info *info){	unregister_hdlc_device(info->netdev);	free_netdev(info->netdev);	info->netdev = NULL;}#endif /* ifdef CONFIG_HDLC *//* * get async data from rx DMA buffers */static void rx_async(struct slgt_info *info){ 	struct tty_struct *tty = info->tty; 	struct mgsl_icount *icount = &info->icount;	unsigned int start, end;	unsigned char *p;	unsigned char status;	struct slgt_desc *bufs = info->rbufs;	int i, count;	int chars = 0;	int stat;	unsigned char ch;	start = end = info->rbuf_current;	while(desc_complete(bufs[end])) {		count = desc_count(bufs[end]) - info->rbuf_index;		p     = bufs[end].buf + info->rbuf_index;		DBGISR(("%s rx_async count=%d\n", info->device_name, count));		DBGDATA(info, p, count, "rx");		for(i=0 ; i < count; i+=2, p+=2) {			ch = *p;			icount->rx++;			stat = 0;			if ((status = *(p+1) & (BIT1 + BIT0))) {				if (status & BIT1)					icount->parity++;				else if (status & BIT0)					icount->frame++;				/* discard char if tty control flags say so */				if (status & info->ignore_status_mask)					continue;				if (status & BIT1)					stat = TTY_PARITY;				else if (status & BIT0)					stat = TTY_FRAME;			}			if (tty) {				tty_insert_flip_char(tty, ch, stat);				chars++;			}		}		if (i < count) {			/* receive buffer not completed */			info->rbuf_index += i;			mod_timer(&info->rx_timer, jiffies + 1);			break;		}

⌨️ 快捷键说明

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