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

📄 io_edgeport.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
	if (edge_port->txCredits < EDGE_FW_GET_TX_CREDITS_SEND_THRESHOLD(edge_port->maxTxCredits,EDGE_FW_BULK_MAX_PACKET_SIZE)) {		dbg("%s(%d) Not enough credit - fifo %d TxCredit %d", __FUNCTION__, edge_port->port->number, fifo->count, edge_port->txCredits );		goto exit_send;	}	// lock this write	edge_port->write_in_progress = TRUE;	// get a pointer to the write_urb	urb = edge_port->write_urb;	/* make sure transfer buffer is freed */	kfree(urb->transfer_buffer);	urb->transfer_buffer = NULL;	/* build the data header for the buffer and port that we are about to send out */	count = fifo->count;	buffer = kmalloc (count+2, GFP_ATOMIC);	if (buffer == NULL) {		dev_err(&edge_port->port->dev, "%s - no more kernel memory...\n", __FUNCTION__);		edge_port->write_in_progress = FALSE;		goto exit_send;	}	buffer[0] = IOSP_BUILD_DATA_HDR1 (edge_port->port->number - edge_port->port->serial->minor, count);	buffer[1] = IOSP_BUILD_DATA_HDR2 (edge_port->port->number - edge_port->port->serial->minor, count);	/* now copy our data */	bytesleft =  fifo->size - fifo->tail;	firsthalf = min (bytesleft, count);	memcpy(&buffer[2], &fifo->fifo[fifo->tail], firsthalf);	fifo->tail  += firsthalf;	fifo->count -= firsthalf;	if (fifo->tail == fifo->size) {		fifo->tail = 0;	}	secondhalf = count-firsthalf;	if (secondhalf) {		memcpy(&buffer[2+firsthalf], &fifo->fifo[fifo->tail], secondhalf);		fifo->tail  += secondhalf;		fifo->count -= secondhalf;	}	if (count)		usb_serial_debug_data(debug, &edge_port->port->dev, __FUNCTION__, count, &buffer[2]);	/* fill up the urb with all of our data and submit it */	usb_fill_bulk_urb (urb, edge_serial->serial->dev, 		       usb_sndbulkpipe(edge_serial->serial->dev, edge_serial->bulk_out_endpoint),		       buffer, count+2, edge_bulk_out_data_callback, edge_port);	/* decrement the number of credits we have by the number we just sent */	edge_port->txCredits -= count;	edge_port->icount.tx += count;	urb->dev = edge_serial->serial->dev;	status = usb_submit_urb(urb, GFP_ATOMIC);	if (status) {		/* something went wrong */		dev_err(&edge_port->port->dev, "%s - usb_submit_urb(write bulk) failed, status = %d, data lost\n", __FUNCTION__, status);		edge_port->write_in_progress = FALSE;		/* revert the credits as something bad happened. */		edge_port->txCredits += count;		edge_port->icount.tx -= count;	}	dbg("%s wrote %d byte(s) TxCredit %d, Fifo %d", __FUNCTION__, count, edge_port->txCredits, fifo->count);exit_send:	spin_unlock_irqrestore(&edge_port->ep_lock, flags);}/***************************************************************************** * edge_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 *	(the txCredits),  *	Otherwise we return a negative error number. *****************************************************************************/static int edge_write_room (struct usb_serial_port *port){	struct edgeport_port *edge_port = usb_get_serial_port_data(port);	int room;	unsigned long flags;	dbg("%s", __FUNCTION__);	if (edge_port == NULL)		return -ENODEV;	if (edge_port->closePending == TRUE)		return -ENODEV;	dbg("%s - port %d", __FUNCTION__, port->number);	if (!edge_port->open) {		dbg("%s - port not opened", __FUNCTION__);		return -EINVAL;	}	// total of both buffers is still txCredit	spin_lock_irqsave(&edge_port->ep_lock, flags);	room = edge_port->txCredits - edge_port->txfifo.count;	spin_unlock_irqrestore(&edge_port->ep_lock, flags);	dbg("%s - returns %d", __FUNCTION__, room);	return room;}/***************************************************************************** * edge_chars_in_buffer *	this function is called by the tty driver when it wants to know how many *	bytes of data we currently have outstanding in the port (data that has *	been written, but hasn't made it out the port yet) *	If successful, we return the number of bytes left to be written in the  *	system,  *	Otherwise we return a negative error number. *****************************************************************************/static int edge_chars_in_buffer (struct usb_serial_port *port){	struct edgeport_port *edge_port = usb_get_serial_port_data(port);	int num_chars;	unsigned long flags;	dbg("%s", __FUNCTION__);	if (edge_port == NULL)		return -ENODEV;	if (edge_port->closePending == TRUE)		return -ENODEV;	if (!edge_port->open) {		dbg("%s - port not opened", __FUNCTION__);		return -EINVAL;	}	spin_lock_irqsave(&edge_port->ep_lock, flags);	num_chars = edge_port->maxTxCredits - edge_port->txCredits + edge_port->txfifo.count;	spin_unlock_irqrestore(&edge_port->ep_lock, flags);	if (num_chars) {		dbg("%s(port %d) - returns %d", __FUNCTION__, port->number, num_chars);	}	return num_chars;}/***************************************************************************** * SerialThrottle *	this function is called by the tty driver when it wants to stop the data *	being read from the port. *****************************************************************************/static void edge_throttle (struct usb_serial_port *port){	struct edgeport_port *edge_port = usb_get_serial_port_data(port);	struct tty_struct *tty;	int status;	dbg("%s - port %d", __FUNCTION__, port->number);	if (edge_port == NULL)		return;	if (!edge_port->open) {		dbg("%s - port not opened", __FUNCTION__);		return;	}	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 = edge_write (port, &stop_char, 1);		if (status <= 0) {			return;		}	}	/* if we are implementing RTS/CTS, toggle that line */	if (tty->termios->c_cflag & CRTSCTS) {		edge_port->shadowMCR &= ~MCR_RTS;		status = send_cmd_write_uart_register(edge_port, MCR, edge_port->shadowMCR);		if (status != 0) {			return;		}	}	return;}/***************************************************************************** * edge_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 edge_unthrottle (struct usb_serial_port *port){	struct edgeport_port *edge_port = usb_get_serial_port_data(port);	struct tty_struct *tty;	int status;	dbg("%s - port %d", __FUNCTION__, port->number);	if (edge_port == NULL)		return;	if (!edge_port->open) {		dbg("%s - port not opened", __FUNCTION__);		return;	}	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 = edge_write (port, &start_char, 1);		if (status <= 0) {			return;		}	}	/* if we are implementing RTS/CTS, toggle that line */	if (tty->termios->c_cflag & CRTSCTS) {		edge_port->shadowMCR |= MCR_RTS;		status = send_cmd_write_uart_register(edge_port, MCR, edge_port->shadowMCR);		if (status != 0) {			return;		}	}	return;}/***************************************************************************** * SerialSetTermios *	this function is called by the tty driver when it wants to change the termios structure *****************************************************************************/static void edge_set_termios (struct usb_serial_port *port, struct termios *old_termios){	struct edgeport_port *edge_port = usb_get_serial_port_data(port);	struct tty_struct *tty = port->tty;	unsigned int cflag;	if (!port->tty || !port->tty->termios) {		dbg ("%s - no tty or termios", __FUNCTION__);		return;	}	cflag = tty->termios->c_cflag;	/* check that they really want us to change something */	if (old_termios) {		if (cflag == old_termios->c_cflag &&		    tty->termios->c_iflag == old_termios->c_iflag) {			dbg("%s - nothing to change", __FUNCTION__);			return;		}	}	dbg("%s - clfag %08x iflag %08x", __FUNCTION__, 	    tty->termios->c_cflag, tty->termios->c_iflag);	if (old_termios) {		dbg("%s - old clfag %08x old iflag %08x", __FUNCTION__,		    old_termios->c_cflag, old_termios->c_iflag);	}	dbg("%s - port %d", __FUNCTION__, port->number);	if (edge_port == NULL)		return;	if (!edge_port->open) {		dbg("%s - port not opened", __FUNCTION__);		return;	}	/* change the port settings to the new ones specified */	change_port_settings (edge_port, old_termios);	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 edgeport_port *edge_port, unsigned int __user *value){	unsigned int result = 0;	unsigned long flags;	spin_lock_irqsave(&edge_port->ep_lock, flags);	if (edge_port->maxTxCredits == edge_port->txCredits &&	    edge_port->txfifo.count == 0) {		dbg("%s -- Empty", __FUNCTION__);		result = TIOCSER_TEMT;	}	spin_unlock_irqrestore(&edge_port->ep_lock, flags);	if (copy_to_user(value, &result, sizeof(int)))		return -EFAULT;	return 0;}static int get_number_bytes_avail(struct edgeport_port *edge_port, unsigned int __user *value){	unsigned int result = 0;	struct tty_struct *tty = edge_port->port->tty;	if (!tty)		return -ENOIOCTLCMD;	result = tty->read_cnt;	dbg("%s(%d) = %d", __FUNCTION__,  edge_port->port->number, result);	if (copy_to_user(value, &result, sizeof(int)))		return -EFAULT;	//return 0;	return -ENOIOCTLCMD;}static int edge_tiocmset (struct usb_serial_port *port, struct file *file, unsigned int set, unsigned int clear){	struct edgeport_port *edge_port = usb_get_serial_port_data(port);	unsigned int mcr;	dbg("%s - port %d", __FUNCTION__, port->number);	mcr = edge_port->shadowMCR;	if (set & TIOCM_RTS)		mcr |= MCR_RTS;	if (set & TIOCM_DTR)		mcr |= MCR_DTR;	if (set & TIOCM_LOOP)		mcr |= MCR_LOOPBACK;	if (clear & TIOCM_RTS)		mcr &= ~MCR_RTS;	if (clear & TIOCM_DTR)		mcr &= ~MCR_DTR;	if (clear & TIOCM_LOOP)		mcr &= ~MCR_LOOPBACK;	edge_port->shadowMCR = mcr;	send_cmd_write_uart_register(edge_port, MCR, edge_port->shadowMCR);	return 0;}static int edge_tiocmget(struct usb_serial_port *port, struct file *file){	struct edgeport_port *edge_port = usb_get_serial_port_data(port);	unsigned int result = 0;	unsigned int msr;	unsigned int mcr;	dbg("%s - port %d", __FUNCTION__, port->number);	msr = edge_port->shadowMSR;	mcr = edge_port->shadowMCR;	result = ((mcr & MCR_DTR)	? TIOCM_DTR: 0)	  /* 0x002 */		  | ((mcr & MCR_RTS)	? TIOCM_RTS: 0)   /* 0x004 */		  | ((msr & EDGEPORT_MSR_CTS)	? TIOCM_CTS: 0)   /* 0x020 */		  | ((msr & EDGEPORT_MSR_CD)	? TIOCM_CAR: 0)   /* 0x040 */		  | ((msr & EDGEPORT_MSR_RI)	? TIOCM_RI:  0)   /* 0x080 */		  | ((msr & EDGEPORT_MSR_DSR)	? TIOCM_DSR: 0);  /* 0x100 */	dbg("%s -- %x", __FUNCTION__, result);	return result;}static int get_serial_info(struct edgeport_port *edge_port, struct serial_struct __user *retinfo)

⌨️ 快捷键说明

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