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

📄 mos7840.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	Data |= SERIAL_LCR_DLAB;	//data latch enable in LCR 0x80	status = 0;	status = mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, Data);	//Data = 0x0c;	//status = mos7840_set_uart_reg(port,DIVISOR_LATCH_LSB,Data);	Data = 0x00;	status = 0;	status = mos7840_get_uart_reg(port, DIVISOR_LATCH_LSB, &Data);	dbg("mos7840_write:DLL value is %x\n", Data);	Data = 0x0;	status = 0;	status = mos7840_get_uart_reg(port, DIVISOR_LATCH_MSB, &Data);	dbg("mos7840_write:DLM value is %x\n", Data);	Data = Data & ~SERIAL_LCR_DLAB;	dbg("mos7840_write: mos7840_port->shadowLCR is %x\n",	    mos7840_port->shadowLCR);	status = 0;	status = mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, Data);#endif	if (mos7840_port_paranoia_check(port, __FUNCTION__)) {		dbg("%s", "Port Paranoia failed \n");		return -1;	}	serial = port->serial;	if (mos7840_serial_paranoia_check(serial, __FUNCTION__)) {		dbg("%s", "Serial Paranoia failed \n");		return -1;	}	mos7840_port = mos7840_get_port_private(port);	if (mos7840_port == NULL) {		dbg("%s", "mos7840_port is NULL\n");		return -1;	}	/* try to find a free urb in the list */	urb = NULL;	spin_lock_irqsave(&mos7840_port->pool_lock, flags);	for (i = 0; i < NUM_URBS; ++i) {		if (!mos7840_port->busy[i]) {			mos7840_port->busy[i] = 1;			urb = mos7840_port->write_urb_pool[i];			dbg("\nURB:%d", i);			break;		}	}	spin_unlock_irqrestore(&mos7840_port->pool_lock, flags);	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);	/* 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,			  mos7840_bulk_out_data_callback, mos7840_port);	data1 = urb->transfer_buffer;	dbg("\nbulkout endpoint is %d", port->bulk_out_endpointAddress);	/* send it down the pipe */	status = usb_submit_urb(urb, GFP_ATOMIC);	if (status) {		mos7840_port->busy[i] = 0;		err("%s - usb_submit_urb(write bulk) failed with status = %d",		    __FUNCTION__, status);		bytes_sent = status;		goto exit;	}	bytes_sent = transfer_size;	mos7840_port->icount.tx += transfer_size;	smp_wmb();	dbg("mos7840_port->icount.tx is %d:\n", mos7840_port->icount.tx);      exit:	return bytes_sent;}/***************************************************************************** * mos7840_throttle *	this function is called by the tty driver when it wants to stop the data *	being read from the port. *****************************************************************************/static void mos7840_throttle(struct usb_serial_port *port){	struct moschip_port *mos7840_port;	struct tty_struct *tty;	int status;	if (mos7840_port_paranoia_check(port, __FUNCTION__)) {		dbg("%s", "Invalid port \n");		return;	}	dbg("- port %d\n", port->number);	mos7840_port = mos7840_get_port_private(port);	if (mos7840_port == NULL)		return;	if (!mos7840_port->open) {		dbg("%s\n", "port not opened");		return;	}	dbg("%s", "Entering .......... \n");	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 = mos7840_write(port, &stop_char, 1);		if (status <= 0) {			return;		}	}	/* if we are implementing RTS/CTS, toggle that line */	if (tty->termios->c_cflag & CRTSCTS) {		mos7840_port->shadowMCR &= ~MCR_RTS;		status = 0;		status =		    mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER,					 mos7840_port->shadowMCR);		if (status < 0) {			return;		}	}	return;}/***************************************************************************** * mos7840_unthrottle *	this function is called by the tty driver when it wants to resume the data *	being read from the port (called after SerialThrottle is called) *****************************************************************************/static void mos7840_unthrottle(struct usb_serial_port *port){	struct tty_struct *tty;	int status;	struct moschip_port *mos7840_port = mos7840_get_port_private(port);	if (mos7840_port_paranoia_check(port, __FUNCTION__)) {		dbg("%s", "Invalid port \n");		return;	}	if (mos7840_port == NULL)		return;	if (!mos7840_port->open) {		dbg("%s - port not opened", __FUNCTION__);		return;	}	dbg("%s", "Entering .......... \n");	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 = mos7840_write(port, &start_char, 1);		if (status <= 0) {			return;		}	}	/* if we are implementing RTS/CTS, toggle that line */	if (tty->termios->c_cflag & CRTSCTS) {		mos7840_port->shadowMCR |= MCR_RTS;		status = 0;		status =		    mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER,					 mos7840_port->shadowMCR);		if (status < 0) {			return;		}	}	return;}static int mos7840_tiocmget(struct usb_serial_port *port, struct file *file){	struct moschip_port *mos7840_port;	unsigned int result;	__u16 msr;	__u16 mcr;	int status = 0;	mos7840_port = mos7840_get_port_private(port);	dbg("%s - port %d", __FUNCTION__, port->number);	if (mos7840_port == NULL)		return -ENODEV;	status = mos7840_get_uart_reg(port, MODEM_STATUS_REGISTER, &msr);	status = mos7840_get_uart_reg(port, MODEM_CONTROL_REGISTER, &mcr);	result = ((mcr & MCR_DTR) ? TIOCM_DTR : 0)	    | ((mcr & MCR_RTS) ? TIOCM_RTS : 0)	    | ((mcr & MCR_LOOPBACK) ? TIOCM_LOOP : 0)	    | ((msr & MOS7840_MSR_CTS) ? TIOCM_CTS : 0)	    | ((msr & MOS7840_MSR_CD) ? TIOCM_CAR : 0)	    | ((msr & MOS7840_MSR_RI) ? TIOCM_RI : 0)	    | ((msr & MOS7840_MSR_DSR) ? TIOCM_DSR : 0);	dbg("%s - 0x%04X", __FUNCTION__, result);	return result;}static int mos7840_tiocmset(struct usb_serial_port *port, struct file *file,			    unsigned int set, unsigned int clear){	struct moschip_port *mos7840_port;	unsigned int mcr;	unsigned int status;	dbg("%s - port %d", __FUNCTION__, port->number);	mos7840_port = mos7840_get_port_private(port);	if (mos7840_port == NULL)		return -ENODEV;	mcr = mos7840_port->shadowMCR;	if (clear & TIOCM_RTS)		mcr &= ~MCR_RTS;	if (clear & TIOCM_DTR)		mcr &= ~MCR_DTR;	if (clear & TIOCM_LOOP)		mcr &= ~MCR_LOOPBACK;	if (set & TIOCM_RTS)		mcr |= MCR_RTS;	if (set & TIOCM_DTR)		mcr |= MCR_DTR;	if (set & TIOCM_LOOP)		mcr |= MCR_LOOPBACK;	mos7840_port->shadowMCR = mcr;	status = 0;	status = mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, mcr);	if (status < 0) {		dbg("setting MODEM_CONTROL_REGISTER Failed\n");		return -1;	}	return 0;}/***************************************************************************** * mos7840_calc_baud_rate_divisor *	this function calculates the proper baud rate divisor for the specified *	baud rate. *****************************************************************************/static int mos7840_calc_baud_rate_divisor(int baudRate, int *divisor,					  __u16 * clk_sel_val){	dbg("%s - %d", __FUNCTION__, baudRate);	if (baudRate <= 115200) {		*divisor = 115200 / baudRate;		*clk_sel_val = 0x0;	}	if ((baudRate > 115200) && (baudRate <= 230400)) {		*divisor = 230400 / baudRate;		*clk_sel_val = 0x10;	} else if ((baudRate > 230400) && (baudRate <= 403200)) {		*divisor = 403200 / baudRate;		*clk_sel_val = 0x20;	} else if ((baudRate > 403200) && (baudRate <= 460800)) {		*divisor = 460800 / baudRate;		*clk_sel_val = 0x30;	} else if ((baudRate > 460800) && (baudRate <= 806400)) {		*divisor = 806400 / baudRate;		*clk_sel_val = 0x40;	} else if ((baudRate > 806400) && (baudRate <= 921600)) {		*divisor = 921600 / baudRate;		*clk_sel_val = 0x50;	} else if ((baudRate > 921600) && (baudRate <= 1572864)) {		*divisor = 1572864 / baudRate;		*clk_sel_val = 0x60;	} else if ((baudRate > 1572864) && (baudRate <= 3145728)) {		*divisor = 3145728 / baudRate;		*clk_sel_val = 0x70;	}	return 0;#ifdef NOTMCS7840	for (i = 0; i < ARRAY_SIZE(mos7840_divisor_table); i++) {		if (mos7840_divisor_table[i].BaudRate == baudrate) {			*divisor = mos7840_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\n", baudrate, custom);		return 0;	}	dbg("%s\n", " Baud calculation Failed...");	return -1;#endif}/***************************************************************************** * mos7840_send_cmd_write_baud_rate *	this function sends the proper command to change the baud rate of the *	specified port. *****************************************************************************/static int mos7840_send_cmd_write_baud_rate(struct moschip_port *mos7840_port,					    int baudRate){	int divisor = 0;	int status;	__u16 Data;	unsigned char number;	__u16 clk_sel_val;	struct usb_serial_port *port;	if (mos7840_port == NULL)		return -1;	port = (struct usb_serial_port *)mos7840_port->port;	if (mos7840_port_paranoia_check(port, __FUNCTION__)) {		dbg("%s", "Invalid port \n");		return -1;	}	if (mos7840_serial_paranoia_check(port->serial, __FUNCTION__)) {		dbg("%s", "Invalid Serial \n");		return -1;	}	dbg("%s", "Entering .......... \n");	number = mos7840_port->port->number - mos7840_port->port->serial->minor;	dbg("%s - port = %d, baud = %d", __FUNCTION__,	    mos7840_port->port->number, baudRate);	//reset clk_uart_sel in spregOffset	if (baudRate > 115200) {#ifdef HW_flow_control		//NOTE: need to see the pther register to modify		//setting h/w flow control bit to 1;		status = 0;		Data = 0x2b;		mos7840_port->shadowMCR = Data;		status =		    mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, Data);		if (status < 0) {			dbg("Writing spreg failed in set_serial_baud\n");			return -1;		}#endif	} else {#ifdef HW_flow_control		//setting h/w flow control bit to 0;		status = 0;		Data = 0xb;		mos7840_port->shadowMCR = Data;		status =		    mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, Data);		if (status < 0) {			dbg("Writing spreg failed in set_serial_baud\n");			return -1;		}#endif	}	if (1)			//baudRate <= 115200)	{		clk_sel_val = 0x0;		Data = 0x0;		status = 0;		status =		    mos7840_calc_baud_rate_divisor(baudRate, &divisor,						   &clk_sel_val);		status =		    mos7840_get_reg_sync(port, mos7840_port->SpRegOffset,					 &Data);		if (status < 0) {			dbg("reading spreg failed in set_serial_baud\n");			return -1;		}		Data = (Data & 0x8f) | clk_sel_val;		status = 0;		status =		    mos7840_set_reg_sync(port, mos7840_port->SpRegOffset, Data);		if (status < 0) {			dbg("Writing spreg failed in set_serial_baud\n");			return -1;		}		/* Calculate the Divisor */		if (status) {			err("%s - bad baud rate", __FUNCTION__);			dbg("%s\n", "bad baud rate");			return status;		}		/* Enable access to divisor latch */		Data = mos7840_port->shadowLCR | SERIAL_LCR_DLAB;		mos7840_port->shadowLCR = Data;		mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, Data);		/* Write the divisor */		Data = (unsigned char)(divisor & 0xff);		dbg("set_serial_baud Value to write DLL is %x\n", Data);		mos7840_set_uart_reg(port, DIVISOR_LATCH_LSB, Data);		Data = (unsigned char)((divisor & 0xff00) >> 8);		dbg("set_serial_baud Value to write DLM is %x\n", Data);		mos7840_set_uart_reg(port, DIVISOR_LATCH_MSB, Data);		/* Disable access to divisor latch */		Data = mos7840_port->shadowLCR & ~SERIAL_LCR_DLAB;		mos7840_port->shadowLCR = Data;		mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, Data);	}

⌨️ 快捷键说明

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