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

📄 io_edgeport.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
		struct usb_serial_port *port0 = serial->port[0];				/* not set up yet, so do it now */		edge_serial->interrupt_in_buffer = port0->interrupt_in_buffer;		edge_serial->interrupt_in_endpoint = port0->interrupt_in_endpointAddress;		edge_serial->interrupt_read_urb = port0->interrupt_in_urb;		edge_serial->bulk_in_buffer = port0->bulk_in_buffer;		edge_serial->bulk_in_endpoint = port0->bulk_in_endpointAddress;		edge_serial->read_urb = port0->read_urb;		edge_serial->bulk_out_endpoint = port0->bulk_out_endpointAddress;			/* set up our interrupt urb */		usb_fill_int_urb(edge_serial->interrupt_read_urb,				 serial->dev,				 usb_rcvintpipe(serial->dev,					        port0->interrupt_in_endpointAddress),				 port0->interrupt_in_buffer,				 edge_serial->interrupt_read_urb->transfer_buffer_length,				 edge_interrupt_callback, edge_serial,				 edge_serial->interrupt_read_urb->interval);				/* set up our bulk in urb */		usb_fill_bulk_urb(edge_serial->read_urb, serial->dev,				  usb_rcvbulkpipe(serial->dev,					  	  port0->bulk_in_endpointAddress),				  port0->bulk_in_buffer,				  edge_serial->read_urb->transfer_buffer_length,				  edge_bulk_in_callback, edge_serial);		edge_serial->read_in_progress = FALSE;		/* start interrupt read for this edgeport		 * this interrupt will continue as long as the edgeport is connected */		response = usb_submit_urb (edge_serial->interrupt_read_urb, GFP_KERNEL);		if (response) {			dev_err(&port->dev, "%s - Error %d submitting control urb\n", __FUNCTION__, response);		}	}		/* initialize our wait queues */	init_waitqueue_head(&edge_port->wait_open);	init_waitqueue_head(&edge_port->wait_chase);	init_waitqueue_head(&edge_port->delta_msr_wait);	init_waitqueue_head(&edge_port->wait_command);	/* initialize our icount structure */	memset (&(edge_port->icount), 0x00, sizeof(edge_port->icount));	/* initialize our port settings */	edge_port->txCredits            = 0;			/* Can't send any data yet */	edge_port->shadowMCR            = MCR_MASTER_IE;	/* Must always set this bit to enable ints! */	edge_port->chaseResponsePending = FALSE;	/* send a open port command */	edge_port->openPending = TRUE;	edge_port->open        = FALSE;	response = send_iosp_ext_cmd (edge_port, IOSP_CMD_OPEN_PORT, 0);	if (response < 0) {		dev_err(&port->dev, "%s - error sending open port command\n", __FUNCTION__);		edge_port->openPending = FALSE;		return -ENODEV;	}	/* now wait for the port to be completely opened */	wait_event_timeout(edge_port->wait_open, (edge_port->openPending != TRUE), OPEN_TIMEOUT);	if (edge_port->open == FALSE) {		/* open timed out */		dbg("%s - open timedout", __FUNCTION__);		edge_port->openPending = FALSE;		return -ENODEV;	}	/* create the txfifo */	edge_port->txfifo.head	= 0;	edge_port->txfifo.tail	= 0;	edge_port->txfifo.count	= 0;	edge_port->txfifo.size	= edge_port->maxTxCredits;	edge_port->txfifo.fifo	= kmalloc (edge_port->maxTxCredits, GFP_KERNEL);	if (!edge_port->txfifo.fifo) {		dbg("%s - no memory", __FUNCTION__);		edge_close (port, filp);		return -ENOMEM;	}	/* Allocate a URB for the write */	edge_port->write_urb = usb_alloc_urb (0, GFP_KERNEL);	edge_port->write_in_progress = FALSE;	if (!edge_port->write_urb) {		dbg("%s - no memory", __FUNCTION__);		edge_close (port, filp);		return -ENOMEM;	}	dbg("%s(%d) - Initialize TX fifo to %d bytes", __FUNCTION__, port->number, edge_port->maxTxCredits);	dbg("%s exited", __FUNCTION__);	return 0;}/************************************************************************ * * block_until_chase_response * *	This function will block the close until one of the following: *		1. Response to our Chase comes from Edgeport *		2. A timout of 10 seconds without activity has expired *		   (1K of Edgeport data @ 2400 baud ==> 4 sec to empty) * ************************************************************************/static void block_until_chase_response(struct edgeport_port *edge_port){	DEFINE_WAIT(wait);	__u16 lastCredits;	int timeout = 1*HZ;	int loop = 10;	while (1) {		// Save Last credits		lastCredits = edge_port->txCredits;		// Did we get our Chase response		if (edge_port->chaseResponsePending == FALSE) {			dbg("%s - Got Chase Response", __FUNCTION__);			// did we get all of our credit back?			if (edge_port->txCredits == edge_port->maxTxCredits ) {				dbg("%s - Got all credits", __FUNCTION__);				return;			}		}		// Block the thread for a while		prepare_to_wait(&edge_port->wait_chase, &wait, TASK_UNINTERRUPTIBLE);		schedule_timeout(timeout);		finish_wait(&edge_port->wait_chase, &wait);		if (lastCredits == edge_port->txCredits) {			// No activity.. count down.			loop--;			if (loop == 0) {				edge_port->chaseResponsePending = FALSE;				dbg("%s - Chase TIMEOUT", __FUNCTION__);				return;			}		} else {			// Reset timout value back to 10 seconds			dbg("%s - Last %d, Current %d", __FUNCTION__, lastCredits, edge_port->txCredits);			loop = 10;		}	}}/************************************************************************ * * block_until_tx_empty * *	This function will block the close until one of the following: *		1. TX count are 0 *		2. The edgeport has stopped *		3. A timout of 3 seconds without activity has expired * ************************************************************************/static void block_until_tx_empty (struct edgeport_port *edge_port){	DEFINE_WAIT(wait);	struct TxFifo *fifo = &edge_port->txfifo;	__u32 lastCount;	int timeout = HZ/10;	int loop = 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		prepare_to_wait (&edge_port->wait_chase, &wait, TASK_UNINTERRUPTIBLE);		schedule_timeout(timeout);		finish_wait(&edge_port->wait_chase, &wait);		dbg("%s wait", __FUNCTION__);		if (lastCount == fifo->count) {			// No activity.. count down.			loop--;			if (loop == 0) {				dbg("%s - TIMEOUT", __FUNCTION__);				return;			}		} else {			// Reset timout value back to seconds			loop = 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 */		kfree(edge_port->write_urb->transfer_buffer);		usb_free_urb(edge_port->write_urb);		edge_port->write_urb = NULL;	}	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.

⌨️ 快捷键说明

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