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

📄 mos7720.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	data = 0x00;        send_mos_cmd(serial,MOS_WRITE,port->number - port->serial->minor, UART_IER, &data);	data = 0x00;        send_mos_cmd(serial, MOS_WRITE, port_number, UART_FCR, &data);	data = 0xcf;        send_mos_cmd(serial, MOS_WRITE, port_number, UART_FCR, &data);	/* Send the updated LCR value to the mos7720 */	data = mos7720_port->shadowLCR;        send_mos_cmd(serial, MOS_WRITE, port_number, UART_LCR, &data);        data = 0x00b;        mos7720_port->shadowMCR = data;        send_mos_cmd(serial, MOS_WRITE, port_number, 0x04, &data);        data = 0x00b;        send_mos_cmd(serial, MOS_WRITE, port_number, 0x04, &data);	/* set up the MCR register and send it to the mos7720 */	mos7720_port->shadowMCR = UART_MCR_OUT2;	if (cflag & CBAUD)		mos7720_port->shadowMCR |= (UART_MCR_DTR | UART_MCR_RTS);	if (cflag & CRTSCTS) {		mos7720_port->shadowMCR |= (UART_MCR_XONANY);                /* To set hardware flow control to the specified *                 * serial port, in SP1/2_CONTROL_REG             */		if (port->number) {			data = 0x001;			send_mos_cmd(serial, MOS_WRITE, MOS_MAX_PORT,				     0x08, &data);		} else {			data = 0x002;			send_mos_cmd(serial, MOS_WRITE, MOS_MAX_PORT,				     0x08, &data);		}	} else {		mos7720_port->shadowMCR &= ~(UART_MCR_XONANY);	}	data = mos7720_port->shadowMCR;	send_mos_cmd(serial, MOS_WRITE, port_number, UART_MCR, &data);	/* Determine divisor based on baud rate */	baud = tty_get_baud_rate(tty);	if (!baud) {		/* pick a default, any default... */		dbg("Picked default baud...");		baud = 9600;	}	if (baud >= 230400) {		set_higher_rates(mos7720_port, baud);		/* Enable Interrupts */		data = 0x0c;		send_mos_cmd(serial, MOS_WRITE, port_number, UART_IER, &data);		return;	}	dbg("%s - baud rate = %d", __FUNCTION__, baud);	status = send_cmd_write_baud_rate(mos7720_port, baud);	/* Enable Interrupts */	data = 0x0c;	send_mos_cmd(serial, MOS_WRITE, port_number, UART_IER, &data);	if (port->read_urb->status != -EINPROGRESS) {		port->read_urb->dev = serial->dev;		status = usb_submit_urb(port->read_urb, GFP_ATOMIC);		if (status)			dbg("usb_submit_urb(read bulk) failed, status = %d",			    status);	}	return;}/* * mos7720_set_termios *	this function is called by the tty driver when it wants to change the *	termios structure. */static void mos7720_set_termios(struct usb_serial_port *port,				struct ktermios *old_termios){	int status;	unsigned int cflag;	struct usb_serial *serial;	struct moschip_port *mos7720_port;	struct tty_struct *tty;	serial = port->serial;	mos7720_port = usb_get_serial_port_data(port);	if (mos7720_port == NULL)		return;	tty = port->tty;	if (!port->tty || !port->tty->termios) {		dbg("%s - no tty or termios", __FUNCTION__);		return;	}	if (!mos7720_port->open) {		dbg("%s - port not opened", __FUNCTION__);		return;	}	dbg("%s\n","setting termios - ASPIRE");	cflag = tty->termios->c_cflag;	if (!cflag) {		printk("%s %s\n",__FUNCTION__,"cflag is NULL");		return;	}	dbg("%s - clfag %08x iflag %08x", __FUNCTION__,	    tty->termios->c_cflag,	    RELEVANT_IFLAG(tty->termios->c_iflag));	if (old_termios)		dbg("%s - old clfag %08x old iflag %08x", __FUNCTION__,		    old_termios->c_cflag,		    RELEVANT_IFLAG(old_termios->c_iflag));	dbg("%s - port %d", __FUNCTION__, port->number);	/* change the port settings to the new ones specified */	change_port_settings(mos7720_port, old_termios);	if(!port->read_urb) {		dbg("%s","URB KILLED !!!!!\n");		return;	}	if(port->read_urb->status != -EINPROGRESS) {		port->read_urb->dev = serial->dev;		status = usb_submit_urb(port->read_urb, GFP_ATOMIC);		if (status)			dbg("usb_submit_urb(read bulk) failed, status = %d",			    status);	}	return;}/* * get_lsr_info - get line status register info * * Purpose: Let user call ioctl() to get info when the UART physically * 	    is emptied.  On bus types like RS485, the transmitter must * 	    release the bus after transmitting. This must be done when * 	    the transmit shift register is empty, not be done when the * 	    transmit holding register is empty.  This functionality * 	    allows an RS485 driver to be written in user space. */static int get_lsr_info(struct moschip_port *mos7720_port,			unsigned int __user *value){	int count;	unsigned int result = 0;	count = mos7720_chars_in_buffer(mos7720_port->port);	if (count == 0) {		dbg("%s -- Empty", __FUNCTION__);		result = TIOCSER_TEMT;	}	if (copy_to_user(value, &result, sizeof(int)))		return -EFAULT;	return 0;}/* * get_number_bytes_avail - get number of bytes available * * Purpose: Let user call ioctl to get the count of number of bytes available. */static int get_number_bytes_avail(struct moschip_port *mos7720_port,				  unsigned int __user *value){	unsigned int result = 0;	struct tty_struct *tty = mos7720_port->port->tty;	if (!tty)		return -ENOIOCTLCMD;	result = tty->read_cnt;	dbg("%s(%d) = %d", __FUNCTION__,  mos7720_port->port->number, result);	if (copy_to_user(value, &result, sizeof(int)))		return -EFAULT;	return -ENOIOCTLCMD;}static int set_modem_info(struct moschip_port *mos7720_port, unsigned int cmd,			  unsigned int __user *value){	unsigned int mcr ;	unsigned int arg;	unsigned char data;	struct usb_serial_port *port;	if (mos7720_port == NULL)		return -1;	port = (struct usb_serial_port*)mos7720_port->port;	mcr = mos7720_port->shadowMCR;	if (copy_from_user(&arg, value, sizeof(int)))		return -EFAULT;	switch (cmd) {	case TIOCMBIS:		if (arg & TIOCM_RTS)			mcr |= UART_MCR_RTS;		if (arg & TIOCM_DTR)			mcr |= UART_MCR_RTS;		if (arg & TIOCM_LOOP)			mcr |= UART_MCR_LOOP;		break;	case TIOCMBIC:		if (arg & TIOCM_RTS)			mcr &= ~UART_MCR_RTS;		if (arg & TIOCM_DTR)			mcr &= ~UART_MCR_RTS;		if (arg & TIOCM_LOOP)			mcr &= ~UART_MCR_LOOP;		break;	case TIOCMSET:		/* turn off the RTS and DTR and LOOPBACK		 * and then only turn on what was asked to */		mcr &=  ~(UART_MCR_RTS | UART_MCR_DTR | UART_MCR_LOOP);		mcr |= ((arg & TIOCM_RTS) ? UART_MCR_RTS : 0);		mcr |= ((arg & TIOCM_DTR) ? UART_MCR_DTR : 0);		mcr |= ((arg & TIOCM_LOOP) ? UART_MCR_LOOP : 0);		break;	}	mos7720_port->shadowMCR = mcr;	data = mos7720_port->shadowMCR;	send_mos_cmd(port->serial, MOS_WRITE,		     port->number - port->serial->minor, UART_MCR, &data);	return 0;}static int get_modem_info(struct moschip_port *mos7720_port,			  unsigned int __user *value){	unsigned int result = 0;	unsigned int msr = mos7720_port->shadowMSR;	unsigned int mcr = mos7720_port->shadowMCR;	result = ((mcr & UART_MCR_DTR)	? TIOCM_DTR: 0)	  /* 0x002 */		  | ((mcr & UART_MCR_RTS)	? TIOCM_RTS: 0)   /* 0x004 */		  | ((msr & UART_MSR_CTS)	? TIOCM_CTS: 0)   /* 0x020 */		  | ((msr & UART_MSR_DCD)	? TIOCM_CAR: 0)   /* 0x040 */		  | ((msr & UART_MSR_RI)	? TIOCM_RI:  0)   /* 0x080 */		  | ((msr & UART_MSR_DSR)	? TIOCM_DSR: 0);  /* 0x100 */	dbg("%s -- %x", __FUNCTION__, result);	if (copy_to_user(value, &result, sizeof(int)))		return -EFAULT;	return 0;}static int get_serial_info(struct moschip_port *mos7720_port,			   struct serial_struct __user *retinfo){	struct serial_struct tmp;	if (!retinfo)		return -EFAULT;	memset(&tmp, 0, sizeof(tmp));	tmp.type		= PORT_16550A;	tmp.line		= mos7720_port->port->serial->minor;	tmp.port		= mos7720_port->port->number;	tmp.irq			= 0;	tmp.flags		= ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ;        tmp.xmit_fifo_size	= NUM_URBS * URB_TRANSFER_BUFFER_SIZE;	tmp.baud_base		= 9600;	tmp.close_delay		= 5*HZ;	tmp.closing_wait	= 30*HZ;	if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))		return -EFAULT;	return 0;}static int mos7720_ioctl(struct usb_serial_port *port, struct file *file,			 unsigned int cmd, unsigned long arg){	struct moschip_port *mos7720_port;	struct async_icount cnow;	struct async_icount cprev;	struct serial_icounter_struct icount;	mos7720_port = usb_get_serial_port_data(port);	if (mos7720_port == NULL)		return -ENODEV;	dbg("%s - port %d, cmd = 0x%x", __FUNCTION__, port->number, cmd);	switch (cmd) {	case TIOCINQ:		/* return number of bytes available */		dbg("%s (%d) TIOCINQ", __FUNCTION__,  port->number);		return get_number_bytes_avail(mos7720_port,					      (unsigned int __user *)arg);		break;	case TIOCSERGETLSR:		dbg("%s (%d) TIOCSERGETLSR", __FUNCTION__,  port->number);		return get_lsr_info(mos7720_port, (unsigned int __user *)arg);		return 0;	case TIOCMBIS:	case TIOCMBIC:	case TIOCMSET:		dbg("%s (%d) TIOCMSET/TIOCMBIC/TIOCMSET", __FUNCTION__,		    port->number);		return set_modem_info(mos7720_port, cmd,				      (unsigned int __user *)arg);	case TIOCMGET:		dbg("%s (%d) TIOCMGET", __FUNCTION__,  port->number);		return get_modem_info(mos7720_port,				      (unsigned int __user *)arg);	case TIOCGSERIAL:		dbg("%s (%d) TIOCGSERIAL", __FUNCTION__,  port->number);		return get_serial_info(mos7720_port,				       (struct serial_struct __user *)arg);	case TIOCSSERIAL:		dbg("%s (%d) TIOCSSERIAL", __FUNCTION__,  port->number);		break;	case TIOCMIWAIT:		dbg("%s (%d) TIOCMIWAIT", __FUNCTION__,  port->number);		cprev = mos7720_port->icount;		while (1) {			if (signal_pending(current))				return -ERESTARTSYS;			cnow = mos7720_port->icount;			if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&			    cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)				return -EIO; /* no change => error */			if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||			    ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||			    ((arg & TIOCM_CD)  && (cnow.dcd != cprev.dcd)) ||			    ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)) ) {				return 0;			}			cprev = cnow;		}		/* NOTREACHED */		break;	case TIOCGICOUNT:		cnow = mos7720_port->icount;		icount.cts = cnow.cts;		icount.dsr = cnow.dsr;		icount.rng = cnow.rng;		icount.dcd = cnow.dcd;		icount.rx = cnow.rx;		icount.tx = cnow.tx;		icount.frame = cnow.frame;		icount.overrun = cnow.overrun;		icount.parity = cnow.parity;		icount.brk = cnow.brk;		icount.buf_overrun = cnow.buf_overrun;		dbg("%s (%d) TIOCGICOUNT RX=%d, TX=%d", __FUNCTION__,		    port->number, icount.rx, icount.tx );		if (copy_to_user((void __user *)arg, &icount, sizeof(icount)))			return -EFAULT;		return 0;	}	return -ENOIOCTLCMD;}static int mos7720_startup(struct usb_serial *serial){	struct moschip_serial *mos7720_serial;	struct moschip_port *mos7720_port;	struct usb_device *dev;	int i;	char data;	dbg("%s: Entering ..........", __FUNCTION__);	if (!serial) {		dbg("Invalid Handler");		return -ENODEV;	}	dev = serial->dev;	/* create our private serial structure */	mos7720_serial = kzalloc(sizeof(struct moschip_serial), GFP_KERNEL);	if (mos7720_serial == NULL) {		err("%s - Out of memory", __FUNCTION__);		return -ENOMEM;	}	usb_set_serial_data(serial, mos7720_serial);	/* we set up the pointers to the endpoints in the mos7720_open *	 * function, as the structures aren't created yet.             */	/* set up port private structures */	for (i = 0; i < serial->num_ports; ++i) {		mos7720_port = kzalloc(sizeof(struct moschip_port), GFP_KERNEL);		if (mos7720_port == NULL) {			err("%s - Out of memory", __FUNCTION__);			usb_set_serial_data(serial, NULL);			kfree(mos7720_serial);			return -ENOMEM;		}		/* Initialize all port interrupt end point to port 0 int		 * endpoint.  Our device has only one interrupt endpoint		 * comman to all ports */		serial->port[i]->interrupt_in_endpointAddress = serial->port[0]->interrupt_in_endpointAddress;		mos7720_port->port = serial->port[i];		usb_set_serial_port_data(serial->port[i], mos7720_port);		dbg("port number is %d", serial->port[i]->number);		dbg("serial number is %d", serial->minor);	}	/* setting configuration feature to one */	usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),			(__u8)0x03, 0x00,0x01,0x00, NULL, 0x00, 5*HZ);	send_mos_cmd(serial,MOS_READ,0x00, UART_LSR, &data);  // LSR For Port 1	dbg("LSR:%x",data);	send_mos_cmd(serial,MOS_READ,0x01, UART_LSR, &data);  // LSR For Port 2	dbg("LSR:%x",data);	return 0;}static void mos7720_shutdown(struct usb_serial *serial){	int i;	/* free private structure allocated for serial port */	for (i=0; i < serial->num_ports; ++i) {		kfree(usb_get_serial_port_data(serial->port[i]));		usb_set_serial_port_data(serial->port[i], NULL);	}	/* free private structure allocated for serial device */	kfree(usb_get_serial_data(serial));	usb_set_serial_data(serial, NULL);}static struct usb_driver usb_driver = {	.name =		"moschip7720",	.probe =	usb_serial_probe,	.disconnect =	usb_serial_disconnect,	.id_table =	moschip_port_id_table,	.no_dynamic_id =	1,};static struct usb_serial_driver moschip7720_2port_driver = {	.driver = {		.owner =	THIS_MODULE,		.name =		"moschip7720",	},	.description		= "Moschip 2 port adapter",	.usb_driver		= &usb_driver,	.id_table		= moschip_port_id_table,	.num_interrupt_in	= 1,	.num_bulk_in		= 2,	.num_bulk_out		= 2,	.num_ports		= 2,	.open			= mos7720_open,	.close			= mos7720_close,	.throttle		= mos7720_throttle,	.unthrottle		= mos7720_unthrottle,	.attach			= mos7720_startup,	.shutdown		= mos7720_shutdown,	.ioctl			= mos7720_ioctl,	.set_termios		= mos7720_set_termios,	.write			= mos7720_write,	.write_room		= mos7720_write_room,	.chars_in_buffer	= mos7720_chars_in_buffer,	.break_ctl		= mos7720_break,	.read_bulk_callback	= mos7720_bulk_in_callback,	.read_int_callback	= mos7720_interrupt_callback,};static int __init moschip7720_init(void){	int retval;	dbg("%s: Entering ..........", __FUNCTION__);	/* Register with the usb serial */	retval = usb_serial_register(&moschip7720_2port_driver);	if (retval)		goto failed_port_device_register;	info(DRIVER_DESC " " DRIVER_VERSION);	/* Register with the usb */	retval = usb_register(&usb_driver);	if (retval)		goto failed_usb_register;	return 0;failed_usb_register:	usb_serial_deregister(&moschip7720_2port_driver);failed_port_device_register:	return retval;}static void __exit moschip7720_exit(void){	usb_deregister(&usb_driver);	usb_serial_deregister(&moschip7720_2port_driver);}module_init(moschip7720_init);module_exit(moschip7720_exit);/* Module information */MODULE_AUTHOR( DRIVER_AUTHOR );MODULE_DESCRIPTION( DRIVER_DESC );MODULE_LICENSE("GPL");module_param(debug, bool, S_IRUGO | S_IWUSR);MODULE_PARM_DESC(debug, "Debug enabled or not");

⌨️ 快捷键说明

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