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

📄 mos7720.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	/* Freeing Write URBs */	for (j = 0; j < NUM_URBS; ++j) {		if (mos7720_port->write_urb_pool[j]) {			kfree(mos7720_port->write_urb_pool[j]->transfer_buffer);			usb_free_urb(mos7720_port->write_urb_pool[j]);		}	}	/* While closing port, shutdown all bulk read, write  *	 * and interrupt read if they exists                  */	if (serial->dev) {		dbg("Shutdown bulk write");		usb_kill_urb(port->write_urb);		dbg("Shutdown bulk read");		usb_kill_urb(port->read_urb);	}	data = 0x00;	send_mos_cmd(serial, MOS_WRITE, port->number - port->serial->minor,		     0x04, &data);	data = 0x00;	send_mos_cmd(serial, MOS_WRITE, port->number - port->serial->minor,		     0x01, &data);	mos7720_port->open = 0;	dbg("Leaving %s", __FUNCTION__);}static void mos7720_break(struct usb_serial_port *port, int break_state){        unsigned char data;	struct usb_serial *serial;	struct moschip_port *mos7720_port;	dbg("Entering %s", __FUNCTION__);	serial = port->serial;	mos7720_port = usb_get_serial_port_data(port);	if (mos7720_port == NULL)		return;	if (break_state == -1)		data = mos7720_port->shadowLCR | UART_LCR_SBC;	else		data = mos7720_port->shadowLCR & ~UART_LCR_SBC;	mos7720_port->shadowLCR  = data;	send_mos_cmd(serial, MOS_WRITE, port->number - port->serial->minor,		     0x03, &data);	return;}/* * mos7720_write_room *	this function is called by the tty driver when it wants to know how many *	bytes of data we can accept for a specific port. *	If successful, we return the amount of room that we have for this port *	Otherwise we return a negative error number. */static int mos7720_write_room(struct usb_serial_port *port){	struct moschip_port *mos7720_port;	int room = 0;	int i;	dbg("%s:entering ...........", __FUNCTION__);	mos7720_port = usb_get_serial_port_data(port);	if (mos7720_port == NULL) {		dbg("%s:leaving ...........", __FUNCTION__);		return -ENODEV;	}	for (i = 0; i < NUM_URBS; ++i) {		if (mos7720_port->write_urb_pool[i] && mos7720_port->write_urb_pool[i]->status != -EINPROGRESS)			room += URB_TRANSFER_BUFFER_SIZE;	}	dbg("%s - returns %d", __FUNCTION__, room);	return room;}static int mos7720_write(struct usb_serial_port *port,			 const unsigned char *data, int count){	int status;	int i;	int bytes_sent = 0;	int transfer_size;	struct moschip_port *mos7720_port;	struct usb_serial *serial;	struct urb    *urb;	const unsigned char *current_position = data;	dbg("%s:entering ...........", __FUNCTION__);	serial = port->serial;	mos7720_port = usb_get_serial_port_data(port);	if (mos7720_port == NULL) {		dbg("mos7720_port is NULL");		return -ENODEV;	}	/* try to find a free urb in the list */	urb = NULL;	for (i = 0; i < NUM_URBS; ++i) {		if (mos7720_port->write_urb_pool[i] && mos7720_port->write_urb_pool[i]->status != -EINPROGRESS) {			urb = mos7720_port->write_urb_pool[i];			dbg("URB:%d",i);			break;		}	}	if (urb == NULL) {		dbg("%s - no more free urbs", __FUNCTION__);		goto exit;	}	if (urb->transfer_buffer == NULL) {		urb->transfer_buffer = kmalloc(URB_TRANSFER_BUFFER_SIZE,					       GFP_KERNEL);		if (urb->transfer_buffer == NULL) {			err("%s no more kernel memory...", __FUNCTION__);			goto exit;		}	}	transfer_size = min (count, URB_TRANSFER_BUFFER_SIZE);	memcpy(urb->transfer_buffer, current_position, transfer_size);	usb_serial_debug_data(debug, &port->dev, __FUNCTION__, transfer_size,			      urb->transfer_buffer);	/* fill urb with data and submit  */	usb_fill_bulk_urb(urb, serial->dev,			  usb_sndbulkpipe(serial->dev,			  		  port->bulk_out_endpointAddress),			  urb->transfer_buffer, transfer_size,			  mos7720_bulk_out_data_callback, mos7720_port);	/* send it down the pipe */	status = usb_submit_urb(urb,GFP_ATOMIC);	if (status) {		err("%s - usb_submit_urb(write bulk) failed with status = %d",		    __FUNCTION__, status);		bytes_sent = status;		goto exit;	}	bytes_sent = transfer_size;exit:	return bytes_sent;}static void mos7720_throttle(struct usb_serial_port *port){	struct moschip_port *mos7720_port;	struct tty_struct *tty;	int status;	dbg("%s- port %d\n", __FUNCTION__, port->number);	mos7720_port = usb_get_serial_port_data(port);	if (mos7720_port == NULL)		return;	if (!mos7720_port->open) {		dbg("port not opened");		return;	}	dbg("%s: Entering ..........", __FUNCTION__);	tty = port->tty;	if (!tty) {		dbg("%s - no tty available", __FUNCTION__);		return;	}	/* if we are implementing XON/XOFF, send the stop character */	if (I_IXOFF(tty)) {		unsigned char stop_char = STOP_CHAR(tty);		status = mos7720_write(port, &stop_char, 1);		if (status <= 0)			return;	}	/* if we are implementing RTS/CTS, toggle that line */	if (tty->termios->c_cflag & CRTSCTS) {		mos7720_port->shadowMCR &= ~UART_MCR_RTS;		status = send_mos_cmd(port->serial, MOS_WRITE,				      port->number - port->serial->minor,				      UART_MCR, &mos7720_port->shadowMCR);		if (status != 0)			return;	}}static void mos7720_unthrottle(struct usb_serial_port *port){	struct tty_struct *tty;	int status;	struct moschip_port *mos7720_port = usb_get_serial_port_data(port);	if (mos7720_port == NULL)		return;	if (!mos7720_port->open) {		dbg("%s - port not opened", __FUNCTION__);		return;	}	dbg("%s: Entering ..........", __FUNCTION__);	tty = port->tty;	if (!tty) {		dbg("%s - no tty available", __FUNCTION__);		return;	}	/* if we are implementing XON/XOFF, send the start character */	if (I_IXOFF(tty)) {		unsigned char start_char = START_CHAR(tty);		status = mos7720_write(port, &start_char, 1);		if (status <= 0)			return;	}	/* if we are implementing RTS/CTS, toggle that line */	if (tty->termios->c_cflag & CRTSCTS) {		mos7720_port->shadowMCR |= UART_MCR_RTS;		status = send_mos_cmd(port->serial, MOS_WRITE,				      port->number - port->serial->minor,				      UART_MCR, &mos7720_port->shadowMCR);		if (status != 0)			return;	}}static int set_higher_rates(struct moschip_port *mos7720_port,			    unsigned int baud){	unsigned char data;	struct usb_serial_port *port;	struct usb_serial *serial;	int port_number;	if (mos7720_port == NULL)		return -EINVAL;	port = mos7720_port->port;	serial = port->serial;        /***********************************************         *      Init Sequence for higher rates         ***********************************************/	dbg("Sending Setting Commands ..........");	port_number = port->number - port->serial->minor;	data = 0x000;	send_mos_cmd(serial, MOS_WRITE, port_number, 0x01, &data);	data = 0x000;	send_mos_cmd(serial, MOS_WRITE, port_number, 0x02, &data);	data = 0x0CF;	send_mos_cmd(serial, MOS_WRITE, port->number, 0x02, &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);	data = 0x000;	send_mos_cmd(serial, MOS_READ, MOS_MAX_PORT, 0x08, &data);	data = 0x000;	send_mos_cmd(serial, MOS_WRITE, MOS_MAX_PORT, 0x08, &data);        /***********************************************         *              Set for higher rates           *         ***********************************************/	data = baud * 0x10;	send_mos_cmd(serial, MOS_WRITE, MOS_MAX_PORT, port_number + 1,&data);	data = 0x003;	send_mos_cmd(serial, MOS_READ, MOS_MAX_PORT, 0x08, &data);	data = 0x003;	send_mos_cmd(serial, MOS_WRITE, MOS_MAX_PORT, 0x08, &data);	data = 0x02b;        mos7720_port->shadowMCR  = data;	send_mos_cmd(serial, MOS_WRITE, port_number, 0x04, &data);	data = 0x02b;	send_mos_cmd(serial, MOS_WRITE, port_number, 0x04, &data);        /***********************************************         *              Set DLL/DLM         ***********************************************/	data = mos7720_port->shadowLCR | UART_LCR_DLAB;        mos7720_port->shadowLCR  = data;	send_mos_cmd(serial, MOS_WRITE, port_number, 0x03, &data);	data =  0x001; /* DLL */        send_mos_cmd(serial, MOS_WRITE, port_number, 0x00, &data);	data =  0x000; /* DLM */        send_mos_cmd(serial, MOS_WRITE, port_number, 0x01, &data);	data = mos7720_port->shadowLCR & ~UART_LCR_DLAB;        mos7720_port->shadowLCR  = data;	send_mos_cmd(serial, MOS_WRITE, port_number, 0x03, &data);	return 0;}/* baud rate information */struct divisor_table_entry{	__u32  baudrate;	__u16  divisor;};/* Define table of divisors for moschip 7720 hardware	   * * These assume a 3.6864MHz crystal, the standard /16, and * * MCR.7 = 0.						   */static struct divisor_table_entry divisor_table[] = {	{   50,		2304},	{   110,	1047},	/* 2094.545455 => 230450   => .0217 % over */	{   134,	857},	/* 1713.011152 => 230398.5 => .00065% under */	{   150,	768},	{   300,	384},	{   600,	192},	{   1200,	96},	{   1800,	64},	{   2400,	48},	{   4800,	24},	{   7200,	16},	{   9600,	12},	{   19200,	6},	{   38400,	3},	{   57600,	2},	{   115200,	1},};/***************************************************************************** * calc_baud_rate_divisor *	this function calculates the proper baud rate divisor for the specified *	baud rate. *****************************************************************************/static int calc_baud_rate_divisor(int baudrate, int *divisor){	int i;	__u16 custom;	__u16 round1;	__u16 round;	dbg("%s - %d", __FUNCTION__, baudrate);	for (i = 0; i < ARRAY_SIZE(divisor_table); i++) {		if (divisor_table[i].baudrate == baudrate) {			*divisor = divisor_table[i].divisor;			return 0;		}	}        /* After trying for all the standard baud rates    *         * Try calculating the divisor for this baud rate  */	if (baudrate > 75 &&  baudrate < 230400) {		/* get the divisor */		custom = (__u16)(230400L  / baudrate);		/* Check for round off */		round1 = (__u16)(2304000L / baudrate);		round = (__u16)(round1 - (custom * 10));		if (round > 4)			custom++;		*divisor = custom;		dbg("Baud %d = %d",baudrate, custom);		return 0;	}	dbg("Baud calculation Failed...");	return -EINVAL;}/* * send_cmd_write_baud_rate *	this function sends the proper command to change the baud rate of the *	specified port. */static int send_cmd_write_baud_rate(struct moschip_port *mos7720_port,				    int baudrate){	struct usb_serial_port *port;	struct usb_serial *serial;	int divisor;	int status;	unsigned char data;	unsigned char number;	if (mos7720_port == NULL)		return -1;	port = mos7720_port->port;	serial = port->serial;	dbg("%s: Entering ..........", __FUNCTION__);	number = port->number - port->serial->minor;	dbg("%s - port = %d, baud = %d", __FUNCTION__, port->number, baudrate);        /* Calculate the Divisor */	status = calc_baud_rate_divisor(baudrate, &divisor);	if (status) {		err("%s - bad baud rate", __FUNCTION__);		return status;	}        /* Enable access to divisor latch */        data = mos7720_port->shadowLCR | UART_LCR_DLAB;        mos7720_port->shadowLCR  = data;        send_mos_cmd(serial, MOS_WRITE, number, UART_LCR, &data);	/* Write the divisor */	data = ((unsigned char)(divisor & 0xff));        send_mos_cmd(serial, MOS_WRITE, number, 0x00, &data);	data = ((unsigned char)((divisor & 0xff00) >> 8));        send_mos_cmd(serial, MOS_WRITE, number, 0x01, &data);        /* Disable access to divisor latch */        data = mos7720_port->shadowLCR & ~UART_LCR_DLAB;        mos7720_port->shadowLCR = data;        send_mos_cmd(serial, MOS_WRITE, number, 0x03, &data);	return status;}/* * change_port_settings *	This routine is called to set the UART on the device to match *      the specified new settings. */static void change_port_settings(struct moschip_port *mos7720_port,				 struct ktermios *old_termios){	struct usb_serial_port *port;	struct usb_serial *serial;	struct tty_struct *tty;	int baud;	unsigned cflag;	unsigned iflag;	__u8 mask = 0xff;	__u8 lData;	__u8 lParity;	__u8 lStop;	int status;	int port_number;	char data;	if (mos7720_port == NULL)		return ;	port = mos7720_port->port;	serial = port->serial;	port_number = port->number - port->serial->minor;	dbg("%s - port %d", __FUNCTION__, port->number);	if (!mos7720_port->open) {		dbg("%s - port not opened", __FUNCTION__);		return;	}	tty = mos7720_port->port->tty;	if ((!tty) || (!tty->termios)) {		dbg("%s - no tty structures", __FUNCTION__);		return;	}	dbg("%s: Entering ..........", __FUNCTION__);	lData = UART_LCR_WLEN8;	lStop = 0x00;	/* 1 stop bit */	lParity = 0x00;	/* No parity */	cflag = tty->termios->c_cflag;	iflag = tty->termios->c_iflag;	/* Change the number of bits */	switch (cflag & CSIZE) {	case CS5:		lData = UART_LCR_WLEN5;		mask = 0x1f;		break;	case CS6:		lData = UART_LCR_WLEN6;		mask = 0x3f;		break;	case CS7:		lData = UART_LCR_WLEN7;		mask = 0x7f;		break;	default:	case CS8:		lData = UART_LCR_WLEN8;		break;	}	/* Change the Parity bit */	if (cflag & PARENB) {		if (cflag & PARODD) {			lParity = UART_LCR_PARITY;			dbg("%s - parity = odd", __FUNCTION__);		} else {			lParity = (UART_LCR_EPAR | UART_LCR_PARITY);			dbg("%s - parity = even", __FUNCTION__);		}	} else {		dbg("%s - parity = none", __FUNCTION__);	}	if (cflag & CMSPAR)		lParity = lParity | 0x20;	/* Change the Stop bit */	if (cflag & CSTOPB) {		lStop = UART_LCR_STOP;		dbg("%s - stop bits = 2", __FUNCTION__);	} else {		lStop = 0x00;		dbg("%s - stop bits = 1", __FUNCTION__);	}#define LCR_BITS_MASK		0x03	/* Mask for bits/char field */#define LCR_STOP_MASK		0x04	/* Mask for stop bits field */#define LCR_PAR_MASK		0x38	/* Mask for parity field */	/* Update the LCR with the correct value */	mos7720_port->shadowLCR &= ~(LCR_BITS_MASK | LCR_STOP_MASK | LCR_PAR_MASK);	mos7720_port->shadowLCR |= (lData | lParity | lStop);	/* Disable Interrupts */

⌨️ 快捷键说明

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