synclinkmp.c

来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 2,458 行 · 第 1/5 页

C
2,458
字号
		ret += sprintf(buf+ret, "\tASYNC tx:%d rx:%d",			      info->icount.tx, info->icount.rx);		if (info->icount.frame)			ret += sprintf(buf+ret, " fe:%d", info->icount.frame);		if (info->icount.parity)			ret += sprintf(buf+ret, " pe:%d", info->icount.parity);		if (info->icount.brk)			ret += sprintf(buf+ret, " brk:%d", info->icount.brk);		if (info->icount.overrun)			ret += sprintf(buf+ret, " oe:%d", info->icount.overrun);	}	/* Append serial signal status to end */	ret += sprintf(buf+ret, " %s\n", stat_buf+1);	ret += sprintf(buf+ret, "\ttxactive=%d bh_req=%d bh_run=%d pending_bh=%x\n",	 info->tx_active,info->bh_requested,info->bh_running,	 info->pending_bh);	return ret;}/* Called to print information about devices */int read_proc(char *page, char **start, off_t off, int count,	      int *eof, void *data){	int len = 0, l;	off_t	begin = 0;	SLMP_INFO *info;	len += sprintf(page, "synclinkmp driver:%s\n", driver_version);	info = synclinkmp_device_list;	while( info ) {		l = line_info(page + len, info);		len += l;		if (len+begin > off+count)			goto done;		if (len+begin < off) {			begin += len;			len = 0;		}		info = info->next_device;	}	*eof = 1;done:	if (off >= len+begin)		return 0;	*start = page + (off-begin);	return ((count < begin+len-off) ? count : begin+len-off);}/* Return the count of bytes in transmit buffer */static int chars_in_buffer(struct tty_struct *tty){	SLMP_INFO *info = (SLMP_INFO *)tty->driver_data;	if (sanity_check(info, tty->name, "chars_in_buffer"))		return 0;	if (debug_level >= DEBUG_LEVEL_INFO)		printk("%s(%d):%s chars_in_buffer()=%d\n",		       __FILE__, __LINE__, info->device_name, info->tx_count);	return info->tx_count;}/* Signal remote device to throttle send data (our receive data) */static void throttle(struct tty_struct * tty){	SLMP_INFO *info = (SLMP_INFO *)tty->driver_data;	unsigned long flags;	if (debug_level >= DEBUG_LEVEL_INFO)		printk("%s(%d):%s throttle() entry\n",			 __FILE__,__LINE__, info->device_name );	if (sanity_check(info, tty->name, "throttle"))		return;	if (I_IXOFF(tty))		send_xchar(tty, STOP_CHAR(tty)); 	if (tty->termios->c_cflag & CRTSCTS) {		spin_lock_irqsave(&info->lock,flags);		info->serial_signals &= ~SerialSignal_RTS;	 	set_signals(info);		spin_unlock_irqrestore(&info->lock,flags);	}}/* Signal remote device to stop throttling send data (our receive data) */static void unthrottle(struct tty_struct * tty){	SLMP_INFO *info = (SLMP_INFO *)tty->driver_data;	unsigned long flags;	if (debug_level >= DEBUG_LEVEL_INFO)		printk("%s(%d):%s unthrottle() entry\n",			 __FILE__,__LINE__, info->device_name );	if (sanity_check(info, tty->name, "unthrottle"))		return;	if (I_IXOFF(tty)) {		if (info->x_char)			info->x_char = 0;		else			send_xchar(tty, START_CHAR(tty));	} 	if (tty->termios->c_cflag & CRTSCTS) {		spin_lock_irqsave(&info->lock,flags);		info->serial_signals |= SerialSignal_RTS;	 	set_signals(info);		spin_unlock_irqrestore(&info->lock,flags);	}}/* set or clear transmit break condition * break_state	-1=set break condition, 0=clear */static void set_break(struct tty_struct *tty, int break_state){	unsigned char RegValue;	SLMP_INFO * info = (SLMP_INFO *)tty->driver_data;	unsigned long flags;	if (debug_level >= DEBUG_LEVEL_INFO)		printk("%s(%d):%s set_break(%d)\n",			 __FILE__,__LINE__, info->device_name, break_state);	if (sanity_check(info, tty->name, "set_break"))		return;	spin_lock_irqsave(&info->lock,flags);	RegValue = read_reg(info, CTL); 	if (break_state == -1)		RegValue |= BIT3;	else		RegValue &= ~BIT3;	write_reg(info, CTL, RegValue);	spin_unlock_irqrestore(&info->lock,flags);}#ifdef CONFIG_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){	SLMP_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;	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){	SLMP_INFO *info = dev_to_port(dev);	struct net_device_stats *stats = hdlc_stats(dev);	unsigned long flags;	if (debug_level >= DEBUG_LEVEL_INFO)		printk(KERN_INFO "%s:hdlc_xmit(%s)\n",__FILE__,dev->name);	/* stop sending until this frame completes */	netif_stop_queue(dev);	/* copy data to device buffers */	info->tx_count = skb->len;	tx_load_dma_buffer(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){	SLMP_INFO *info = dev_to_port(dev);	int rc;	unsigned long flags;	if (debug_level >= DEBUG_LEVEL_INFO)		printk("%s:hdlcdev_open(%s)\n",__FILE__,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) {		printk(KERN_WARNING "%s: hdlc_open returning 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->serial_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);	hdlc_set_carrier(info->serial_signals & SerialSignal_DCD, 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){	SLMP_INFO *info = dev_to_port(dev);	unsigned long flags;	if (debug_level >= DEBUG_LEVEL_INFO)		printk("%s:hdlcdev_close(%s)\n",__FILE__,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);	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;	SLMP_INFO *info = dev_to_port(dev);	unsigned int flags;	if (debug_level >= DEBUG_LEVEL_INFO)		printk("%s:hdlcdev_ioctl(%s)\n",__FILE__,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){	SLMP_INFO *info = dev_to_port(dev);	struct net_device_stats *stats = hdlc_stats(dev);	unsigned long flags;	if (debug_level >= DEBUG_LEVEL_INFO)		printk("hdlcdev_tx_timeout(%s)\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(SLMP_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(SLMP_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);	if (debug_level >= DEBUG_LEVEL_INFO)		printk("hdlcdev_rx(%s)\n",dev->name);	if (skb == NULL) {		printk(KERN_NOTICE "%s: can't alloc skb, dropping packet\n", dev->name);		stats->rx_dropped++;		return;	}

⌨️ 快捷键说明

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