ip2main.c
来自「LINUX 2.6.17.4的源码」· C语言 代码 · 共 1,945 行 · 第 1/5 页
C
1,945 行
/******************************************************************************//* Function: ip2_close() *//* Parameters: Pointer to tty structure *//* Pointer to file structure *//* Returns: Nothing *//* *//* Description: *//* *//* *//******************************************************************************/static voidip2_close( PTTY tty, struct file *pFile ){ i2ChanStrPtr pCh = tty->driver_data; if ( !pCh ) { return; } ip2trace (CHANN, ITRC_CLOSE, ITRC_ENTER, 0 );#ifdef IP2DEBUG_OPEN printk(KERN_DEBUG "IP2:close %s:\n",tty->name);#endif if ( tty_hung_up_p ( pFile ) ) { ip2trace (CHANN, ITRC_CLOSE, 2, 1, 2 ); return; } if ( tty->count > 1 ) { /* not the last close */ ip2trace (CHANN, ITRC_CLOSE, 2, 1, 3 ); return; } pCh->flags |= ASYNC_CLOSING; // last close actually tty->closing = 1; if (pCh->ClosingWaitTime != ASYNC_CLOSING_WAIT_NONE) { /* * Before we drop DTR, make sure the transmitter has completely drained. * This uses an timeout, after which the close * completes. */ ip2_wait_until_sent(tty, pCh->ClosingWaitTime ); } /* * At this point we stop accepting input. Here we flush the channel * input buffer which will allow the board to send up more data. Any * additional input is tossed at interrupt/poll time. */ i2InputFlush( pCh ); /* disable DSS reporting */ i2QueueCommands(PTYPE_INLINE, pCh, 100, 4, CMD_DCD_NREP, CMD_CTS_NREP, CMD_DSR_NREP, CMD_RI_NREP); if ( !tty || (tty->termios->c_cflag & HUPCL) ) { i2QueueCommands(PTYPE_INLINE, pCh, 100, 2, CMD_RTSDN, CMD_DTRDN); pCh->dataSetOut &= ~(I2_DTR | I2_RTS); i2QueueCommands( PTYPE_INLINE, pCh, 100, 1, CMD_PAUSE(25)); } serviceOutgoingFifo ( pCh->pMyBord ); if ( tty->driver->flush_buffer ) tty->driver->flush_buffer(tty); if ( tty->ldisc.flush_buffer ) tty->ldisc.flush_buffer(tty); tty->closing = 0; pCh->pTTY = NULL; if (pCh->wopen) { if (pCh->ClosingDelay) { msleep_interruptible(jiffies_to_msecs(pCh->ClosingDelay)); } wake_up_interruptible(&pCh->open_wait); } pCh->flags &=~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); wake_up_interruptible(&pCh->close_wait);#ifdef IP2DEBUG_OPEN DBG_CNT("ip2_close: after wakeups--");#endif ip2trace (CHANN, ITRC_CLOSE, ITRC_RETURN, 1, 1 ); return;}/******************************************************************************//* Function: ip2_hangup() *//* Parameters: Pointer to tty structure *//* Returns: Nothing *//* *//* Description: *//* *//* *//******************************************************************************/static voidip2_hangup ( PTTY tty ){ i2ChanStrPtr pCh = tty->driver_data; if( !pCh ) { return; } ip2trace (CHANN, ITRC_HANGUP, ITRC_ENTER, 0 ); ip2_flush_buffer(tty); /* disable DSS reporting */ i2QueueCommands(PTYPE_BYPASS, pCh, 0, 1, CMD_DCD_NREP); i2QueueCommands(PTYPE_INLINE, pCh, 0, 2, CMD_CTSFL_DSAB, CMD_RTSFL_DSAB); if ( (tty->termios->c_cflag & HUPCL) ) { i2QueueCommands(PTYPE_BYPASS, pCh, 0, 2, CMD_RTSDN, CMD_DTRDN); pCh->dataSetOut &= ~(I2_DTR | I2_RTS); i2QueueCommands( PTYPE_INLINE, pCh, 100, 1, CMD_PAUSE(25)); } i2QueueCommands(PTYPE_INLINE, pCh, 1, 3, CMD_CTS_NREP, CMD_DSR_NREP, CMD_RI_NREP); serviceOutgoingFifo ( pCh->pMyBord ); wake_up_interruptible ( &pCh->delta_msr_wait ); pCh->flags &= ~ASYNC_NORMAL_ACTIVE; pCh->pTTY = NULL; wake_up_interruptible ( &pCh->open_wait ); ip2trace (CHANN, ITRC_HANGUP, ITRC_RETURN, 0 );}/******************************************************************************//******************************************************************************//* Device Output Section *//******************************************************************************//******************************************************************************//******************************************************************************//* Function: ip2_write() *//* Parameters: Pointer to tty structure *//* Flag denoting data is in user (1) or kernel (0) space *//* Pointer to data *//* Number of bytes to write *//* Returns: Number of bytes actually written *//* *//* Description: (MANDATORY) *//* *//* *//******************************************************************************/static intip2_write( PTTY tty, const unsigned char *pData, int count){ i2ChanStrPtr pCh = tty->driver_data; int bytesSent = 0; unsigned long flags; ip2trace (CHANN, ITRC_WRITE, ITRC_ENTER, 2, count, -1 ); /* Flush out any buffered data left over from ip2_putchar() calls. */ ip2_flush_chars( tty ); /* This is the actual move bit. Make sure it does what we need!!!!! */ WRITE_LOCK_IRQSAVE(&pCh->Pbuf_spinlock,flags); bytesSent = i2Output( pCh, pData, count, 0 ); WRITE_UNLOCK_IRQRESTORE(&pCh->Pbuf_spinlock,flags); ip2trace (CHANN, ITRC_WRITE, ITRC_RETURN, 1, bytesSent ); return bytesSent > 0 ? bytesSent : 0;}/******************************************************************************//* Function: ip2_putchar() *//* Parameters: Pointer to tty structure *//* Character to write *//* Returns: Nothing *//* *//* Description: *//* *//* *//******************************************************************************/static voidip2_putchar( PTTY tty, unsigned char ch ){ i2ChanStrPtr pCh = tty->driver_data; unsigned long flags;// ip2trace (CHANN, ITRC_PUTC, ITRC_ENTER, 1, ch ); WRITE_LOCK_IRQSAVE(&pCh->Pbuf_spinlock,flags); pCh->Pbuf[pCh->Pbuf_stuff++] = ch; if ( pCh->Pbuf_stuff == sizeof pCh->Pbuf ) { WRITE_UNLOCK_IRQRESTORE(&pCh->Pbuf_spinlock,flags); ip2_flush_chars( tty ); } else WRITE_UNLOCK_IRQRESTORE(&pCh->Pbuf_spinlock,flags);// ip2trace (CHANN, ITRC_PUTC, ITRC_RETURN, 1, ch );}/******************************************************************************//* Function: ip2_flush_chars() *//* Parameters: Pointer to tty structure *//* Returns: Nothing *//* *//* Description: *//* *//******************************************************************************/static voidip2_flush_chars( PTTY tty ){ int strip; i2ChanStrPtr pCh = tty->driver_data; unsigned long flags; WRITE_LOCK_IRQSAVE(&pCh->Pbuf_spinlock,flags); if ( pCh->Pbuf_stuff ) {// ip2trace (CHANN, ITRC_PUTC, 10, 1, strip ); // // We may need to restart i2Output if it does not fullfill this request // strip = i2Output( pCh, pCh->Pbuf, pCh->Pbuf_stuff, 0 ); if ( strip != pCh->Pbuf_stuff ) { memmove( pCh->Pbuf, &pCh->Pbuf[strip], pCh->Pbuf_stuff - strip ); } pCh->Pbuf_stuff -= strip; } WRITE_UNLOCK_IRQRESTORE(&pCh->Pbuf_spinlock,flags);}/******************************************************************************//* Function: ip2_write_room() *//* Parameters: Pointer to tty structure *//* Returns: Number of bytes that the driver can accept *//* *//* Description: *//* *//******************************************************************************/static intip2_write_room ( PTTY tty ){ int bytesFree; i2ChanStrPtr pCh = tty->driver_data; unsigned long flags; READ_LOCK_IRQSAVE(&pCh->Pbuf_spinlock,flags); bytesFree = i2OutputFree( pCh ) - pCh->Pbuf_stuff; READ_UNLOCK_IRQRESTORE(&pCh->Pbuf_spinlock,flags); ip2trace (CHANN, ITRC_WRITE, 11, 1, bytesFree ); return ((bytesFree > 0) ? bytesFree : 0);}/******************************************************************************//* Function: ip2_chars_in_buf() *//* Parameters: Pointer to tty structure *//* Returns: Number of bytes queued for transmission *//* *//* Description: *//* *//* *//******************************************************************************/static intip2_chars_in_buf ( PTTY tty ){ i2ChanStrPtr pCh = tty->driver_data; int rc; unsigned long flags; ip2trace (CHANN, ITRC_WRITE, 12, 1, pCh->Obuf_char_count + pCh->Pbuf_stuff );#ifdef IP2DEBUG_WRITE printk (KERN_DEBUG "IP2: chars in buffer = %d (%d,%d)\n", pCh->Obuf_char_count + pCh->Pbuf_stuff, pCh->Obuf_char_count, pCh->Pbuf_stuff );#endif READ_LOCK_IRQSAVE(&pCh->Obuf_spinlock,flags); rc = pCh->Obuf_char_count; READ_UNLOCK_IRQRESTORE(&pCh->Obuf_spinlock,flags); READ_LOCK_IRQSAVE(&pCh->Pbuf_spinlock,flags); rc += pCh->Pbuf_stuff; READ_UNLOCK_IRQRESTORE(&pCh->Pbuf_spinlock,flags); return rc;}/******************************************************************************//* Function: ip2_flush_buffer() *//* Parameters: Pointer to tty structure *//* Returns: Nothing *//* *//* Description: *//* *//* *//******************************************************************************/static voidip2_flush_buffer( PTTY tty ){ i2ChanStrPtr pCh = tty->driver_data; unsigned long flags; ip2trace (CHANN, ITRC_FLUSH, ITRC_ENTER, 0 );#ifdef IP2DEBUG_WRITE printk (KERN_DEBUG "IP2: flush buffer\n" );#endif WRITE_LOCK_IRQSAVE(&pCh->Pbuf_spinlock,flags); pCh->Pbuf_stuff = 0; WRITE_UNLOCK_IRQRESTORE(&pCh->Pbuf_spinlock,flags); i2FlushOutput( pCh ); ip2_owake(tty); ip2trace (CHANN, ITRC_FLUSH, ITRC_RETURN, 0 );}/******************************************************************************//* Function: ip2_wait_until_sent() *//* Parameters: Pointer to tty structure *//* Timeout for wait. *//* Returns: Nothing *//* *//* Description: *//* This function is used in place of the normal tty_wait_until_sent, which *//* only waits for the driver buffers to be empty (or rather, those buffers *//* reported by chars_in_buffer) which doesn't work for IP2 due to the *//* indeterminate number of bytes buffered on the board. *//******************************************************************************/static voidip2_wait_until_sent ( PTTY tty, int timeout ){ int i = jiffies; i2ChanStrPtr pCh = tty->driver_data; tty_wait_until_sent(tty, timeout ); if ( (i = timeout - (jiffies -i)) > 0) i2DrainOutput( pCh, i );}/******************************************************************************//******************************************************************************//* Device Input Section *//******************************************************************************//******************************************************************************//******************************************************************************//* Function: ip2_throttle() *//* Parameters: Pointer to tty structure *//* Returns: Nothing *//* *//* Description: *//* *//* *//******************************************************************************/static voidip2_throttle ( PTTY tty ){ i2ChanStrPtr pCh = tty->driver_data;#ifdef IP2DEBUG_READ printk (KERN_DEBUG "IP2: throttle\n" );#endif /* * Signal the poll/interrupt handlers not to forward incoming data to * the line discipline. This will cause the buffers to fill up in the * library and thus cause the library routines to send the flow control * stuff. */ pCh->throttled = 1;}/******************************************************************************//* Function: ip2_unthrottle() *//* Parameters: Pointer to tty structure *//* Returns: Nothing *//* *//* Description: *//*
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?