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

📄 jsm_tty.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
/************************************************************************ * Copyright 2003 Digi International (www.digi.com) * * Copyright (C) 2004 IBM Corporation. All rights reserved. * * 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, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR * PURPOSE.  See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 * Temple Place - Suite 330, Boston, * MA  02111-1307, USA. * * Contact Information: * Scott H Kilau <Scott_Kilau@digi.com> * Wendy Xiong   <wendyx@us.ltcfwd.linux.ibm.com> * ***********************************************************************/#include <linux/tty.h>#include <linux/tty_flip.h>#include <linux/serial_reg.h>#include <linux/delay.h>	/* For udelay */#include <linux/pci.h>#include "jsm.h"static void jsm_carrier(struct jsm_channel *ch);static inline int jsm_get_mstat(struct jsm_channel *ch){	unsigned char mstat;	unsigned result;	jsm_printk(IOCTL, INFO, &ch->ch_bd->pci_dev, "start\n");	mstat = (ch->ch_mostat | ch->ch_mistat);	result = 0;	if (mstat & UART_MCR_DTR)		result |= TIOCM_DTR;	if (mstat & UART_MCR_RTS)		result |= TIOCM_RTS;	if (mstat & UART_MSR_CTS)		result |= TIOCM_CTS;	if (mstat & UART_MSR_DSR)		result |= TIOCM_DSR;	if (mstat & UART_MSR_RI)		result |= TIOCM_RI;	if (mstat & UART_MSR_DCD)		result |= TIOCM_CD;	jsm_printk(IOCTL, INFO, &ch->ch_bd->pci_dev, "finish\n");	return result;}static unsigned int jsm_tty_tx_empty(struct uart_port *port){	return TIOCSER_TEMT;}/* * Return modem signals to ld. */static unsigned int jsm_tty_get_mctrl(struct uart_port *port){	int result;	struct jsm_channel *channel = (struct jsm_channel *)port;	jsm_printk(IOCTL, INFO, &channel->ch_bd->pci_dev, "start\n");	result = jsm_get_mstat(channel);	if (result < 0)		return -ENXIO;	jsm_printk(IOCTL, INFO, &channel->ch_bd->pci_dev, "finish\n");	return result;}/* * jsm_set_modem_info() * * Set modem signals, called by ld. */static void jsm_tty_set_mctrl(struct uart_port *port, unsigned int mctrl){	struct jsm_channel *channel = (struct jsm_channel *)port;	jsm_printk(IOCTL, INFO, &channel->ch_bd->pci_dev, "start\n");	if (mctrl & TIOCM_RTS)		channel->ch_mostat |= UART_MCR_RTS;	else		channel->ch_mostat &= ~UART_MCR_RTS;	if (mctrl & TIOCM_DTR)		channel->ch_mostat |= UART_MCR_DTR;	else		channel->ch_mostat &= ~UART_MCR_DTR;	channel->ch_bd->bd_ops->assert_modem_signals(channel);	jsm_printk(IOCTL, INFO, &channel->ch_bd->pci_dev, "finish\n");	udelay(10);}static void jsm_tty_start_tx(struct uart_port *port){	struct jsm_channel *channel = (struct jsm_channel *)port;	jsm_printk(IOCTL, INFO, &channel->ch_bd->pci_dev, "start\n");	channel->ch_flags &= ~(CH_STOP);	jsm_tty_write(port);	jsm_printk(IOCTL, INFO, &channel->ch_bd->pci_dev, "finish\n");}static void jsm_tty_stop_tx(struct uart_port *port){	struct jsm_channel *channel = (struct jsm_channel *)port;	jsm_printk(IOCTL, INFO, &channel->ch_bd->pci_dev, "start\n");	channel->ch_flags |= (CH_STOP);	jsm_printk(IOCTL, INFO, &channel->ch_bd->pci_dev, "finish\n");}static void jsm_tty_send_xchar(struct uart_port *port, char ch){	unsigned long lock_flags;	struct jsm_channel *channel = (struct jsm_channel *)port;	spin_lock_irqsave(&port->lock, lock_flags);	if (ch == port->info->tty->termios->c_cc[VSTART])		channel->ch_bd->bd_ops->send_start_character(channel);	if (ch == port->info->tty->termios->c_cc[VSTOP])		channel->ch_bd->bd_ops->send_stop_character(channel);	spin_unlock_irqrestore(&port->lock, lock_flags);}static void jsm_tty_stop_rx(struct uart_port *port){	struct jsm_channel *channel = (struct jsm_channel *)port;	channel->ch_bd->bd_ops->disable_receiver(channel);}static void jsm_tty_break(struct uart_port *port, int break_state){	unsigned long lock_flags;	struct jsm_channel *channel = (struct jsm_channel *)port;	spin_lock_irqsave(&port->lock, lock_flags);	if (break_state == -1)		channel->ch_bd->bd_ops->send_break(channel);	else		channel->ch_bd->bd_ops->clear_break(channel, 0);	spin_unlock_irqrestore(&port->lock, lock_flags);}static int jsm_tty_open(struct uart_port *port){	struct jsm_board *brd;	int rc = 0;	struct jsm_channel *channel = (struct jsm_channel *)port;	/* Get board pointer from our array of majors we have allocated */	brd = channel->ch_bd;	/*	 * Allocate channel buffers for read/write/error.	 * Set flag, so we don't get trounced on.	 */	channel->ch_flags |= (CH_OPENING);	/* Drop locks, as malloc with GFP_KERNEL can sleep */	if (!channel->ch_rqueue) {		channel->ch_rqueue = (u8 *) kmalloc(RQUEUESIZE, GFP_KERNEL);		if (!channel->ch_rqueue) {			jsm_printk(INIT, ERR, &channel->ch_bd->pci_dev,				"unable to allocate read queue buf");			return -ENOMEM;		}		memset(channel->ch_rqueue, 0, RQUEUESIZE);	}	if (!channel->ch_equeue) {		channel->ch_equeue = (u8 *) kmalloc(EQUEUESIZE, GFP_KERNEL);		if (!channel->ch_equeue) {			jsm_printk(INIT, ERR, &channel->ch_bd->pci_dev,				"unable to allocate error queue buf");			return -ENOMEM;		}		memset(channel->ch_equeue, 0, EQUEUESIZE);	}	if (!channel->ch_wqueue) {		channel->ch_wqueue = (u8 *) kmalloc(WQUEUESIZE, GFP_KERNEL);		if (!channel->ch_wqueue) {			jsm_printk(INIT, ERR, &channel->ch_bd->pci_dev,				"unable to allocate write queue buf");			return -ENOMEM;		}		memset(channel->ch_wqueue, 0, WQUEUESIZE);	}	channel->ch_flags &= ~(CH_OPENING);	/*	 * Initialize if neither terminal is open.	 */	jsm_printk(OPEN, INFO, &channel->ch_bd->pci_dev,		"jsm_open: initializing channel in open...\n");	/*	 * Flush input queues.	 */	channel->ch_r_head = channel->ch_r_tail = 0;	channel->ch_e_head = channel->ch_e_tail = 0;	channel->ch_w_head = channel->ch_w_tail = 0;	brd->bd_ops->flush_uart_write(channel);	brd->bd_ops->flush_uart_read(channel);	channel->ch_flags = 0;	channel->ch_cached_lsr = 0;	channel->ch_stops_sent = 0;	channel->ch_c_cflag	= port->info->tty->termios->c_cflag;	channel->ch_c_iflag	= port->info->tty->termios->c_iflag;	channel->ch_c_oflag	= port->info->tty->termios->c_oflag;	channel->ch_c_lflag	= port->info->tty->termios->c_lflag;	channel->ch_startc = port->info->tty->termios->c_cc[VSTART];	channel->ch_stopc = port->info->tty->termios->c_cc[VSTOP];	/* Tell UART to init itself */	brd->bd_ops->uart_init(channel);	/*	 * Run param in case we changed anything	 */	brd->bd_ops->param(channel);	jsm_carrier(channel);	channel->ch_open_count++;	jsm_printk(OPEN, INFO, &channel->ch_bd->pci_dev, "finish\n");	return rc;}static void jsm_tty_close(struct uart_port *port){	struct jsm_board *bd;	struct termios *ts;	struct jsm_channel *channel = (struct jsm_channel *)port;	jsm_printk(CLOSE, INFO, &channel->ch_bd->pci_dev, "start\n");	bd = channel->ch_bd;	ts = channel->uart_port.info->tty->termios;	channel->ch_flags &= ~(CH_STOPI);	channel->ch_open_count--;	/*	 * If we have HUPCL set, lower DTR and RTS	 */	if (channel->ch_c_cflag & HUPCL) {		jsm_printk(CLOSE, INFO, &channel->ch_bd->pci_dev,			"Close. HUPCL set, dropping DTR/RTS\n");		/* Drop RTS/DTR */		channel->ch_mostat &= ~(UART_MCR_DTR | UART_MCR_RTS);		bd->bd_ops->assert_modem_signals(channel);	}	channel->ch_old_baud = 0;	/* Turn off UART interrupts for this port */	channel->ch_bd->bd_ops->uart_off(channel);	jsm_printk(CLOSE, INFO, &channel->ch_bd->pci_dev, "finish\n");}static void jsm_tty_set_termios(struct uart_port *port,				 struct termios *termios,				 struct termios *old_termios){	unsigned long lock_flags;	struct jsm_channel *channel = (struct jsm_channel *)port;	spin_lock_irqsave(&port->lock, lock_flags);	channel->ch_c_cflag	= termios->c_cflag;	channel->ch_c_iflag	= termios->c_iflag;	channel->ch_c_oflag	= termios->c_oflag;	channel->ch_c_lflag	= termios->c_lflag;	channel->ch_startc	= termios->c_cc[VSTART];	channel->ch_stopc	= termios->c_cc[VSTOP];	channel->ch_bd->bd_ops->param(channel);	jsm_carrier(channel);	spin_unlock_irqrestore(&port->lock, lock_flags);}static const char *jsm_tty_type(struct uart_port *port){	return "jsm";}static void jsm_tty_release_port(struct uart_port *port){}static int jsm_tty_request_port(struct uart_port *port){	return 0;}static void jsm_config_port(struct uart_port *port, int flags){	port->type = PORT_JSM;}static struct uart_ops jsm_ops = {	.tx_empty	= jsm_tty_tx_empty,	.set_mctrl	= jsm_tty_set_mctrl,	.get_mctrl	= jsm_tty_get_mctrl,	.stop_tx	= jsm_tty_stop_tx,	.start_tx	= jsm_tty_start_tx,	.send_xchar	= jsm_tty_send_xchar,	.stop_rx	= jsm_tty_stop_rx,	.break_ctl	= jsm_tty_break,	.startup	= jsm_tty_open,	.shutdown	= jsm_tty_close,	.set_termios	= jsm_tty_set_termios,	.type		= jsm_tty_type,	.release_port	= jsm_tty_release_port,	.request_port	= jsm_tty_request_port,	.config_port	= jsm_config_port,};/* * jsm_tty_init() * * Init the tty subsystem.  Called once per board after board has been * downloaded and init'ed. */int jsm_tty_init(struct jsm_board *brd){	int i;	void __iomem *vaddr;	struct jsm_channel *ch;	if (!brd)		return -ENXIO;	jsm_printk(INIT, INFO, &brd->pci_dev, "start\n");	/*	 * Initialize board structure elements.	 */	brd->nasync = brd->maxports;	/*	 * Allocate channel memory that might not have been allocated	 * when the driver was first loaded.	 */	for (i = 0; i < brd->nasync; i++) {		if (!brd->channels[i]) {			/*			 * Okay to malloc with GFP_KERNEL, we are not at			 * interrupt context, and there are no locks held.			 */			brd->channels[i] = kmalloc(sizeof(struct jsm_channel), GFP_KERNEL);			if (!brd->channels[i]) {				jsm_printk(CORE, ERR, &brd->pci_dev,					"%s:%d Unable to allocate memory for channel struct\n",							 __FILE__, __LINE__);			}			memset(brd->channels[i], 0, sizeof(struct jsm_channel));		}	}	ch = brd->channels[0];	vaddr = brd->re_map_membase;	/* Set up channel variables */	for (i = 0; i < brd->nasync; i++, ch = brd->channels[i]) {		if (!brd->channels[i])			continue;		spin_lock_init(&ch->ch_lock);		if (brd->bd_uart_offset == 0x200)			ch->ch_neo_uart =  vaddr + (brd->bd_uart_offset * i);		ch->ch_bd = brd;		ch->ch_portnum = i;		/* .25 second delay */		ch->ch_close_delay = 250;		init_waitqueue_head(&ch->ch_flags_wait);	}	jsm_printk(INIT, INFO, &brd->pci_dev, "finish\n");	return 0;}int jsm_uart_port_init(struct jsm_board *brd){	int i;	struct jsm_channel *ch;	if (!brd)		return -ENXIO;	jsm_printk(INIT, INFO, &brd->pci_dev, "start\n");	/*	 * Initialize board structure elements.	 */	brd->nasync = brd->maxports;	/* Set up channel variables */	for (i = 0; i < brd->nasync; i++, ch = brd->channels[i]) {		if (!brd->channels[i])			continue;		brd->channels[i]->uart_port.irq = brd->irq;		brd->channels[i]->uart_port.type = PORT_JSM;		brd->channels[i]->uart_port.iotype = UPIO_MEM;		brd->channels[i]->uart_port.membase = brd->re_map_membase;		brd->channels[i]->uart_port.fifosize = 16;		brd->channels[i]->uart_port.ops = &jsm_ops;		brd->channels[i]->uart_port.line = brd->channels[i]->ch_portnum + brd->boardnum * 2;		if (uart_add_one_port (&jsm_uart_driver, &brd->channels[i]->uart_port))			printk(KERN_INFO "Added device failed\n");		else			printk(KERN_INFO "Added device \n");	}	jsm_printk(INIT, INFO, &brd->pci_dev, "finish\n");	return 0;}int jsm_remove_uart_port(struct jsm_board *brd){	int i;	struct jsm_channel *ch;	if (!brd)		return -ENXIO;	jsm_printk(INIT, INFO, &brd->pci_dev, "start\n");	/*	 * Initialize board structure elements.	 */	brd->nasync = brd->maxports;	/* Set up channel variables */	for (i = 0; i < brd->nasync; i++) {		if (!brd->channels[i])			continue;		ch = brd->channels[i];		uart_remove_one_port(&jsm_uart_driver, &brd->channels[i]->uart_port);	}	jsm_printk(INIT, INFO, &brd->pci_dev, "finish\n");	return 0;}void jsm_input(struct jsm_channel *ch){	struct jsm_board *bd;	struct tty_struct *tp;	u32 rmask;	u16 head;	u16 tail;	int data_len;	unsigned long lock_flags;	int flip_len;	int len = 0;	int n = 0;	char *buf = NULL;	char *buf2 = NULL;

⌨️ 快捷键说明

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