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

📄 mos7840.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * 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 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; 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 * * Clean ups from Moschip version and a few ioctl implementations by: *	Paul B Schroeder <pschroeder "at" uplogix "dot" com> * * Originally based on drivers/usb/serial/io_edgeport.c which is: *      Copyright (C) 2000 Inside Out Networks, All rights reserved. *      Copyright (C) 2001-2002 Greg Kroah-Hartman <greg@kroah.com> * */#include <linux/kernel.h>#include <linux/errno.h>#include <linux/init.h>#include <linux/slab.h>#include <linux/tty.h>#include <linux/tty_driver.h>#include <linux/tty_flip.h>#include <linux/module.h>#include <linux/serial.h>#include <linux/usb.h>#include <linux/usb/serial.h>#include <asm/uaccess.h>/* * Version Information */#define DRIVER_VERSION "1.3.1"#define DRIVER_DESC "Moschip 7840/7820 USB Serial Driver"/* * 16C50 UART register defines */#define LCR_BITS_5             0x00	/* 5 bits/char */#define LCR_BITS_6             0x01	/* 6 bits/char */#define LCR_BITS_7             0x02	/* 7 bits/char */#define LCR_BITS_8             0x03	/* 8 bits/char */#define LCR_BITS_MASK          0x03	/* Mask for bits/char field */#define LCR_STOP_1             0x00	/* 1 stop bit */#define LCR_STOP_1_5           0x04	/* 1.5 stop bits (if 5   bits/char) */#define LCR_STOP_2             0x04	/* 2 stop bits   (if 6-8 bits/char) */#define LCR_STOP_MASK          0x04	/* Mask for stop bits field */#define LCR_PAR_NONE           0x00	/* No parity */#define LCR_PAR_ODD            0x08	/* Odd parity */#define LCR_PAR_EVEN           0x18	/* Even parity */#define LCR_PAR_MARK           0x28	/* Force parity bit to 1 */#define LCR_PAR_SPACE          0x38	/* Force parity bit to 0 */#define LCR_PAR_MASK           0x38	/* Mask for parity field */#define LCR_SET_BREAK          0x40	/* Set Break condition */#define LCR_DL_ENABLE          0x80	/* Enable access to divisor latch */#define MCR_DTR                0x01	/* Assert DTR */#define MCR_RTS                0x02	/* Assert RTS */#define MCR_OUT1               0x04	/* Loopback only: Sets state of RI */#define MCR_MASTER_IE          0x08	/* Enable interrupt outputs */#define MCR_LOOPBACK           0x10	/* Set internal (digital) loopback mode */#define MCR_XON_ANY            0x20	/* Enable any char to exit XOFF mode */#define MOS7840_MSR_CTS        0x10	/* Current state of CTS */#define MOS7840_MSR_DSR        0x20	/* Current state of DSR */#define MOS7840_MSR_RI         0x40	/* Current state of RI */#define MOS7840_MSR_CD         0x80	/* Current state of CD *//* * Defines used for sending commands to port */#define WAIT_FOR_EVER   (HZ * 0 )	/* timeout urb is wait for ever */#define MOS_WDR_TIMEOUT (HZ * 5 )	/* default urb timeout */#define MOS_PORT1       0x0200#define MOS_PORT2       0x0300#define MOS_VENREG      0x0000#define MOS_MAX_PORT	0x02#define MOS_WRITE       0x0E#define MOS_READ        0x0D/* Requests */#define MCS_RD_RTYPE    0xC0#define MCS_WR_RTYPE    0x40#define MCS_RDREQ       0x0D#define MCS_WRREQ       0x0E#define MCS_CTRL_TIMEOUT        500#define VENDOR_READ_LENGTH      (0x01)#define MAX_NAME_LEN    64#define ZLP_REG1  0x3A		//Zero_Flag_Reg1    58#define ZLP_REG5  0x3E		//Zero_Flag_Reg5    62/* For higher baud Rates use TIOCEXBAUD */#define TIOCEXBAUD     0x5462/* vendor id and device id defines */#define USB_VENDOR_ID_MOSCHIP           0x9710#define MOSCHIP_DEVICE_ID_7840          0x7840#define MOSCHIP_DEVICE_ID_7820          0x7820/* Interrupt Rotinue Defines    */#define SERIAL_IIR_RLS      0x06#define SERIAL_IIR_MS       0x00/* *  Emulation of the bit mask on the LINE STATUS REGISTER. */#define SERIAL_LSR_DR       0x0001#define SERIAL_LSR_OE       0x0002#define SERIAL_LSR_PE       0x0004#define SERIAL_LSR_FE       0x0008#define SERIAL_LSR_BI       0x0010#define MOS_MSR_DELTA_CTS   0x10#define MOS_MSR_DELTA_DSR   0x20#define MOS_MSR_DELTA_RI    0x40#define MOS_MSR_DELTA_CD    0x80// Serial Port register Address#define INTERRUPT_ENABLE_REGISTER  ((__u16)(0x01))#define FIFO_CONTROL_REGISTER      ((__u16)(0x02))#define LINE_CONTROL_REGISTER      ((__u16)(0x03))#define MODEM_CONTROL_REGISTER     ((__u16)(0x04))#define LINE_STATUS_REGISTER       ((__u16)(0x05))#define MODEM_STATUS_REGISTER      ((__u16)(0x06))#define SCRATCH_PAD_REGISTER       ((__u16)(0x07))#define DIVISOR_LATCH_LSB          ((__u16)(0x00))#define DIVISOR_LATCH_MSB          ((__u16)(0x01))#define CLK_MULTI_REGISTER         ((__u16)(0x02))#define CLK_START_VALUE_REGISTER   ((__u16)(0x03))#define SERIAL_LCR_DLAB            ((__u16)(0x0080))/* * URB POOL related defines */#define NUM_URBS                        16	/* URB Count */#define URB_TRANSFER_BUFFER_SIZE        32	/* URB Size  */static struct usb_device_id moschip_port_id_table[] = {	{USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7840)},	{USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7820)},	{}			/* terminating entry */};static __devinitdata struct usb_device_id moschip_id_table_combined[] = {	{USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7840)},	{USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7820)},	{}			/* terminating entry */};MODULE_DEVICE_TABLE(usb, moschip_id_table_combined);/* This structure holds all of the local port information */struct moschip_port {	int port_num;		/*Actual port number in the device(1,2,etc) */	struct urb *write_urb;	/* write URB for this port */	struct urb *read_urb;	/* read URB for this port */	struct urb *int_urb;	__u8 shadowLCR;		/* last LCR value received */	__u8 shadowMCR;		/* last MCR value received */	char open;	char open_ports;	char zombie;	wait_queue_head_t wait_chase;	/* for handling sleeping while waiting for chase to finish */	wait_queue_head_t delta_msr_wait;	/* for handling sleeping while waiting for msr change to happen */	int delta_msr_cond;	struct async_icount icount;	struct usb_serial_port *port;	/* loop back to the owner of this object */	/*Offsets */	__u8 SpRegOffset;	__u8 ControlRegOffset;	__u8 DcrRegOffset;	//for processing control URBS in interrupt context	struct urb *control_urb;	struct usb_ctrlrequest *dr;	char *ctrl_buf;	int MsrLsr;	spinlock_t pool_lock;	struct urb *write_urb_pool[NUM_URBS];	char busy[NUM_URBS];};static int debug;/* * mos7840_set_reg_sync * 	To set the Control register by calling usb_fill_control_urb function *	by passing usb_sndctrlpipe function as parameter. */static int mos7840_set_reg_sync(struct usb_serial_port *port, __u16 reg,				__u16 val){	struct usb_device *dev = port->serial->dev;	val = val & 0x00ff;	dbg("mos7840_set_reg_sync offset is %x, value %x\n", reg, val);	return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), MCS_WRREQ,			       MCS_WR_RTYPE, val, reg, NULL, 0,			       MOS_WDR_TIMEOUT);}/* * mos7840_get_reg_sync * 	To set the Uart register by calling usb_fill_control_urb function by *	passing usb_rcvctrlpipe function as parameter. */static int mos7840_get_reg_sync(struct usb_serial_port *port, __u16 reg,				__u16 * val){	struct usb_device *dev = port->serial->dev;	int ret = 0;	ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), MCS_RDREQ,			      MCS_RD_RTYPE, 0, reg, val, VENDOR_READ_LENGTH,			      MOS_WDR_TIMEOUT);	dbg("mos7840_get_reg_sync offset is %x, return val %x\n", reg, *val);	*val = (*val) & 0x00ff;	return ret;}/* * mos7840_set_uart_reg *	To set the Uart register by calling usb_fill_control_urb function by *	passing usb_sndctrlpipe function as parameter. */static int mos7840_set_uart_reg(struct usb_serial_port *port, __u16 reg,				__u16 val){	struct usb_device *dev = port->serial->dev;	val = val & 0x00ff;	// For the UART control registers, the application number need to be Or'ed	if (port->serial->num_ports == 4) {		val |=		    (((__u16) port->number - (__u16) (port->serial->minor)) +		     1) << 8;		dbg("mos7840_set_uart_reg application number is %x\n", val);	} else {		if (((__u16) port->number - (__u16) (port->serial->minor)) == 0) {			val |=			    (((__u16) port->number -			      (__u16) (port->serial->minor)) + 1) << 8;			dbg("mos7840_set_uart_reg application number is %x\n",			    val);		} else {			val |=			    (((__u16) port->number -			      (__u16) (port->serial->minor)) + 2) << 8;			dbg("mos7840_set_uart_reg application number is %x\n",			    val);		}	}	return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), MCS_WRREQ,			       MCS_WR_RTYPE, val, reg, NULL, 0,			       MOS_WDR_TIMEOUT);}/* * mos7840_get_uart_reg *	To set the Control register by calling usb_fill_control_urb function *	by passing usb_rcvctrlpipe function as parameter. */static int mos7840_get_uart_reg(struct usb_serial_port *port, __u16 reg,				__u16 * val){	struct usb_device *dev = port->serial->dev;	int ret = 0;	__u16 Wval;	//dbg("application number is %4x \n",(((__u16)port->number - (__u16)(port->serial->minor))+1)<<8);	/*Wval  is same as application number */	if (port->serial->num_ports == 4) {		Wval =		    (((__u16) port->number - (__u16) (port->serial->minor)) +		     1) << 8;		dbg("mos7840_get_uart_reg application number is %x\n", Wval);	} else {		if (((__u16) port->number - (__u16) (port->serial->minor)) == 0) {			Wval =			    (((__u16) port->number -			      (__u16) (port->serial->minor)) + 1) << 8;			dbg("mos7840_get_uart_reg application number is %x\n",			    Wval);		} else {			Wval =			    (((__u16) port->number -			      (__u16) (port->serial->minor)) + 2) << 8;			dbg("mos7840_get_uart_reg application number is %x\n",			    Wval);		}	}	ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), MCS_RDREQ,			      MCS_RD_RTYPE, Wval, reg, val, VENDOR_READ_LENGTH,			      MOS_WDR_TIMEOUT);	*val = (*val) & 0x00ff;	return ret;}static void mos7840_dump_serial_port(struct moschip_port *mos7840_port){	dbg("***************************************\n");	dbg("SpRegOffset is %2x\n", mos7840_port->SpRegOffset);	dbg("ControlRegOffset is %2x \n", mos7840_port->ControlRegOffset);	dbg("DCRRegOffset is %2x \n", mos7840_port->DcrRegOffset);	dbg("***************************************\n");}/************************************************************************//************************************************************************//*             I N T E R F A C E   F U N C T I O N S			*//*             I N T E R F A C E   F U N C T I O N S			*//************************************************************************//************************************************************************/static inline void mos7840_set_port_private(struct usb_serial_port *port,					    struct moschip_port *data){	usb_set_serial_port_data(port, (void *)data);}static inline struct moschip_port *mos7840_get_port_private(struct							    usb_serial_port							    *port){	return (struct moschip_port *)usb_get_serial_port_data(port);}static void mos7840_handle_new_msr(struct moschip_port *port, __u8 new_msr){	struct moschip_port *mos7840_port;	struct async_icount *icount;	mos7840_port = port;	icount = &mos7840_port->icount;	if (new_msr &	    (MOS_MSR_DELTA_CTS | MOS_MSR_DELTA_DSR | MOS_MSR_DELTA_RI |	     MOS_MSR_DELTA_CD)) {		icount = &mos7840_port->icount;		/* update input line counters */		if (new_msr & MOS_MSR_DELTA_CTS) {			icount->cts++;			smp_wmb();		}		if (new_msr & MOS_MSR_DELTA_DSR) {			icount->dsr++;			smp_wmb();		}		if (new_msr & MOS_MSR_DELTA_CD) {			icount->dcd++;			smp_wmb();		}		if (new_msr & MOS_MSR_DELTA_RI) {			icount->rng++;			smp_wmb();		}	}}static void mos7840_handle_new_lsr(struct moschip_port *port, __u8 new_lsr){	struct async_icount *icount;	dbg("%s - %02x", __FUNCTION__, new_lsr);	if (new_lsr & SERIAL_LSR_BI) {		//		// Parity and Framing errors only count if they		// occur exclusive of a break being		// received.		//		new_lsr &= (__u8) (SERIAL_LSR_OE | SERIAL_LSR_BI);	}	/* update input line counters */	icount = &port->icount;	if (new_lsr & SERIAL_LSR_BI) {		icount->brk++;		smp_wmb();	}	if (new_lsr & SERIAL_LSR_OE) {		icount->overrun++;		smp_wmb();	}	if (new_lsr & SERIAL_LSR_PE) {		icount->parity++;		smp_wmb();	}	if (new_lsr & SERIAL_LSR_FE) {		icount->frame++;		smp_wmb();	}}/************************************************************************//************************************************************************//*            U S B  C A L L B A C K   F U N C T I O N S                *//*            U S B  C A L L B A C K   F U N C T I O N S                *//************************************************************************//************************************************************************/static void mos7840_control_callback(struct urb *urb){	unsigned char *data;	struct moschip_port *mos7840_port;	__u8 regval = 0x0;	int result = 0;	int status = urb->status;	mos7840_port = (struct moschip_port *)urb->context;	switch (status) {	case 0:		/* success */		break;	case -ECONNRESET:	case -ENOENT:	case -ESHUTDOWN:		/* this urb is terminated, clean up */		dbg("%s - urb shutting down with status: %d", __FUNCTION__,		    status);		return;	default:		dbg("%s - nonzero urb status received: %d", __FUNCTION__,		    status);		goto exit;	}	dbg("%s urb buffer size is %d\n", __FUNCTION__, urb->actual_length);	dbg("%s mos7840_port->MsrLsr is %d port %d\n", __FUNCTION__,	    mos7840_port->MsrLsr, mos7840_port->port_num);	data = urb->transfer_buffer;	regval = (__u8) data[0];	dbg("%s data is %x\n", __FUNCTION__, regval);	if (mos7840_port->MsrLsr == 0)		mos7840_handle_new_msr(mos7840_port, regval);	else if (mos7840_port->MsrLsr == 1)		mos7840_handle_new_lsr(mos7840_port, regval);exit:	spin_lock(&mos7840_port->pool_lock);	if (!mos7840_port->zombie)		result = usb_submit_urb(mos7840_port->int_urb, GFP_ATOMIC);	spin_unlock(&mos7840_port->pool_lock);	if (result) {		dev_err(&urb->dev->dev,			"%s - Error %d submitting interrupt urb\n",			__FUNCTION__, result);	}}static int mos7840_get_reg(struct moschip_port *mcs, __u16 Wval, __u16 reg,			   __u16 * val)

⌨️ 快捷键说明

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