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

📄 io_edgeport.c

📁 h内核
💻 C
📖 第 1 页 / 共 5 页
字号:
	__u32 lastCount;	int timeout = HZ/10;	int wait = 30;	while (1) {		// Save Last count		lastCount = fifo->count;		// Is the Edgeport Buffer empty?		if (lastCount == 0) {			dbg("%s - TX Buffer Empty", __FUNCTION__);			return;		}		// Block the thread for a while		interruptible_sleep_on_timeout (&edge_port->wait_chase, timeout);		dbg("%s wait", __FUNCTION__);		if (lastCount == fifo->count) {			// No activity.. count down.			wait--;			if (wait == 0) {				dbg("%s - TIMEOUT", __FUNCTION__);				return;			}		} else {			// Reset timout value back to seconds			wait = 30;		}	}}/***************************************************************************** * edge_close *	this function is called by the tty driver when a port is closed *****************************************************************************/static void edge_close (struct usb_serial_port *port, struct file * filp){	struct edgeport_serial *edge_serial;	struct edgeport_port *edge_port;	int status;	dbg("%s - port %d", __FUNCTION__, port->number);			 	edge_serial = usb_get_serial_data(port->serial);	edge_port = usb_get_serial_port_data(port);	if ((edge_serial == NULL) || (edge_port == NULL))		return;		// block until tx is empty	block_until_tx_empty(edge_port);	edge_port->closePending = TRUE;	/* flush and chase */	edge_port->chaseResponsePending = TRUE;	dbg("%s - Sending IOSP_CMD_CHASE_PORT", __FUNCTION__);	status = send_iosp_ext_cmd (edge_port, IOSP_CMD_CHASE_PORT, 0);	if (status == 0) {		// block until chase finished		block_until_chase_response(edge_port);	} else {		edge_port->chaseResponsePending = FALSE;	}	/* close the port */	dbg("%s - Sending IOSP_CMD_CLOSE_PORT", __FUNCTION__);	send_iosp_ext_cmd (edge_port, IOSP_CMD_CLOSE_PORT, 0);	//port->close = TRUE;	edge_port->closePending = FALSE;	edge_port->open = FALSE;	edge_port->openPending = FALSE;	if (edge_port->write_urb) {		usb_kill_urb(edge_port->write_urb);	}	if (edge_port->write_urb) {		/* if this urb had a transfer buffer already (old transfer) free it */		if (edge_port->write_urb->transfer_buffer != NULL) {			kfree(edge_port->write_urb->transfer_buffer);		}		usb_free_urb   (edge_port->write_urb);		edge_port->write_urb = NULL;	}	if (edge_port->txfifo.fifo) {		kfree(edge_port->txfifo.fifo);		edge_port->txfifo.fifo = NULL;	}	dbg("%s exited", __FUNCTION__);}   /***************************************************************************** * SerialWrite *	this function is called by the tty driver when data should be written to *	the port. *	If successful, we return the number of bytes written, otherwise we return *	a negative error number. *****************************************************************************/static int edge_write (struct usb_serial_port *port, const unsigned char *data, int count){	struct edgeport_port *edge_port = usb_get_serial_port_data(port);	struct TxFifo *fifo;	int copySize;	int bytesleft;	int firsthalf;	int secondhalf;	unsigned long flags;	dbg("%s - port %d", __FUNCTION__, port->number);	if (edge_port == NULL)		return -ENODEV;	// get a pointer to the Tx fifo	fifo = &edge_port->txfifo;	spin_lock_irqsave(&edge_port->ep_lock, flags);	// calculate number of bytes to put in fifo	copySize = min ((unsigned int)count, (edge_port->txCredits - fifo->count));	dbg("%s(%d) of %d byte(s) Fifo room  %d -- will copy %d bytes", __FUNCTION__, 	    port->number, count, edge_port->txCredits - fifo->count, copySize);	/* catch writes of 0 bytes which the tty driver likes to give us, and when txCredits is empty */	if (copySize == 0) {		dbg("%s - copySize = Zero", __FUNCTION__);		goto finish_write;	}	// queue the data		// since we can never overflow the buffer we do not have to check for full condition	// the copy is done is two parts -- first fill to the end of the buffer	// then copy the reset from the start of the buffer 	bytesleft = fifo->size - fifo->head;	firsthalf = min (bytesleft, copySize);	dbg("%s - copy %d bytes of %d into fifo ", __FUNCTION__, firsthalf, bytesleft);	/* now copy our data */	memcpy(&fifo->fifo[fifo->head], data, firsthalf);	usb_serial_debug_data(debug, &port->dev, __FUNCTION__, firsthalf, &fifo->fifo[fifo->head]);	// update the index and size	fifo->head  += firsthalf;	fifo->count += firsthalf;	// wrap the index	if (fifo->head == fifo->size) {		fifo->head = 0;	}	secondhalf = copySize-firsthalf;	if (secondhalf) {		dbg("%s - copy rest of data %d", __FUNCTION__, secondhalf);		memcpy(&fifo->fifo[fifo->head], &data[firsthalf], secondhalf);		usb_serial_debug_data(debug, &port->dev, __FUNCTION__, secondhalf, &fifo->fifo[fifo->head]);		// update the index and size		fifo->count += secondhalf;		fifo->head  += secondhalf;		// No need to check for wrap since we can not get to end of fifo in this part	}finish_write:	spin_unlock_irqrestore(&edge_port->ep_lock, flags);	send_more_port_data((struct edgeport_serial *)usb_get_serial_data(port->serial), edge_port);	dbg("%s wrote %d byte(s) TxCredits %d, Fifo %d", __FUNCTION__, copySize, edge_port->txCredits, fifo->count);	return copySize;   }/************************************************************************ * * send_more_port_data() * *	This routine attempts to write additional UART transmit data *	to a port over the USB bulk pipe. It is called (1) when new *	data has been written to a port's TxBuffer from higher layers *	(2) when the peripheral sends us additional TxCredits indicating *	that it can accept more	Tx data for a given port; and (3) when *	a bulk write completes successfully and we want to see if we *	can transmit more. * ************************************************************************/static void send_more_port_data(struct edgeport_serial *edge_serial, struct edgeport_port *edge_port){	struct TxFifo	*fifo = &edge_port->txfifo;	struct urb	*urb;	unsigned char	*buffer;	int		status;	int		count;	int		bytesleft;	int		firsthalf;	int		secondhalf;	unsigned long	flags;	dbg("%s(%d)", __FUNCTION__, edge_port->port->number);	spin_lock_irqsave(&edge_port->ep_lock, flags);	if (edge_port->write_in_progress ||	    !edge_port->open             ||	    (fifo->count == 0)) {		dbg("%s(%d) EXIT - fifo %d, PendingWrite = %d", __FUNCTION__, edge_port->port->number, fifo->count, edge_port->write_in_progress);		goto exit_send;	}	// since the amount of data in the fifo will always fit into the	// edgeport buffer we do not need to check the write length	//	Do we have enough credits for this port to make it worthwhile	//	to bother queueing a write. If it's too small, say a few bytes,	//	it's better to wait for more credits so we can do a larger	//	write.	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;	/* if this urb had a transfer buffer already (old transfer) free it */	if (urb->transfer_buffer != NULL) {		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__);

⌨️ 快捷键说明

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