📄 ip2main.c
字号:
#ifdef IP2DEBUG_OPEN printk(KERN_DEBUG \ "IP2:open(tty=%p,pFile=%p):dev=%x,maj=%d,min=%d,ch=%d,idx=%d\n", tty, pFile, tty->device, MAJOR(tty->device), MINOR(tty->device), pCh->infl.hd.i2sChannel, pCh->port_index); open_sanity_check ( pCh, pCh->pMyBord );#endif i2QueueCommands(PTYPE_INLINE, pCh, 100, 3, CMD_DTRUP,CMD_RTSUP,CMD_DCD_REP); pCh->dataSetOut |= (I2_DTR | I2_RTS); serviceOutgoingFifo( pCh->pMyBord ); /* Block here until the port is ready (per serial and istallion) */ /* * 1. If the port is in the middle of closing wait for the completion * and then return the appropriate error. */ init_waitqueue_entry(&wait, current); add_wait_queue(&pCh->close_wait, &wait); set_current_state( TASK_INTERRUPTIBLE ); if ( tty_hung_up_p(pFile) || ( pCh->flags & ASYNC_CLOSING )) { if ( pCh->flags & ASYNC_CLOSING ) { schedule(); } if ( tty_hung_up_p(pFile) ) { set_current_state( TASK_RUNNING ); remove_wait_queue(&pCh->close_wait, &wait); return( pCh->flags & ASYNC_HUP_NOTIFY ) ? -EAGAIN : -ERESTARTSYS; } } set_current_state( TASK_RUNNING ); remove_wait_queue(&pCh->close_wait, &wait); /* * 2. If this is a callout device, make sure the normal port is not in * use, and that someone else doesn't have the callout device locked. * (These are the only tests the standard serial driver makes for * callout devices.) */ if ( tty->driver.subtype == SERIAL_TYPE_CALLOUT ) { if ( pCh->flags & ASYNC_NORMAL_ACTIVE ) { return -EBUSY; } if ( ( pCh->flags & ASYNC_CALLOUT_ACTIVE ) && ( pCh->flags & ASYNC_SESSION_LOCKOUT ) && ( pCh->session != current->session ) ) { return -EBUSY; } if ( ( pCh->flags & ASYNC_CALLOUT_ACTIVE ) && ( pCh->flags & ASYNC_PGRP_LOCKOUT ) && ( pCh->pgrp != current->pgrp ) ) { return -EBUSY; } pCh->flags |= ASYNC_CALLOUT_ACTIVE; goto noblock; } /* * 3. Handle a non-blocking open of a normal port. */ if ( (pFile->f_flags & O_NONBLOCK) || (tty->flags & (1<<TTY_IO_ERROR) )) { if ( pCh->flags & ASYNC_CALLOUT_ACTIVE ) { return -EBUSY; } pCh->flags |= ASYNC_NORMAL_ACTIVE; goto noblock; } /* * 4. Now loop waiting for the port to be free and carrier present * (if required). */ if ( pCh->flags & ASYNC_CALLOUT_ACTIVE ) { if ( pCh->NormalTermios.c_cflag & CLOCAL ) { do_clocal = 1; } } else { if ( tty->termios->c_cflag & CLOCAL ) { do_clocal = 1; } }#ifdef IP2DEBUG_OPEN printk(KERN_DEBUG "OpenBlock: do_clocal = %d\n", do_clocal);#endif ++pCh->wopen; init_waitqueue_entry(&wait, current); add_wait_queue(&pCh->open_wait, &wait); for(;;) { if ( !(pCh->flags & ASYNC_CALLOUT_ACTIVE)) { i2QueueCommands(PTYPE_INLINE, pCh, 100, 2, CMD_DTRUP, CMD_RTSUP); pCh->dataSetOut |= (I2_DTR | I2_RTS); set_current_state( TASK_INTERRUPTIBLE ); serviceOutgoingFifo( pCh->pMyBord ); } if ( tty_hung_up_p(pFile) ) { set_current_state( TASK_RUNNING ); remove_wait_queue(&pCh->open_wait, &wait); return ( pCh->flags & ASYNC_HUP_NOTIFY ) ? -EBUSY : -ERESTARTSYS; } if ( !(pCh->flags & ASYNC_CALLOUT_ACTIVE) && !(pCh->flags & ASYNC_CLOSING) && (do_clocal || (pCh->dataSetIn & I2_DCD) )) { rc = 0; break; }#ifdef IP2DEBUG_OPEN printk(KERN_DEBUG "ASYNC_CALLOUT_ACTIVE = %s\n", (pCh->flags & ASYNC_CALLOUT_ACTIVE)?"True":"False"); printk(KERN_DEBUG "ASYNC_CLOSING = %s\n", (pCh->flags & ASYNC_CLOSING)?"True":"False"); printk(KERN_DEBUG "OpenBlock: waiting for CD or signal\n");#endif ip2trace (CHANN, ITRC_OPEN, 3, 2, (pCh->flags & ASYNC_CALLOUT_ACTIVE), (pCh->flags & ASYNC_CLOSING) ); /* check for signal */ if (signal_pending(current)) { rc = (( pCh->flags & ASYNC_HUP_NOTIFY ) ? -EAGAIN : -ERESTARTSYS); break; } schedule(); } set_current_state( TASK_RUNNING ); remove_wait_queue(&pCh->open_wait, &wait); --pCh->wopen; //why count? ip2trace (CHANN, ITRC_OPEN, 4, 0 ); if (rc != 0 ) { return rc; } pCh->flags |= ASYNC_NORMAL_ACTIVE;noblock: /* first open - Assign termios structure to port */ if ( tty->count == 1 ) { i2QueueCommands(PTYPE_INLINE, pCh, 0, 2, CMD_CTSFL_DSAB, CMD_RTSFL_DSAB); if ( pCh->flags & ASYNC_SPLIT_TERMIOS ) { if ( tty->driver.subtype == SERIAL_TYPE_NORMAL ) { *tty->termios = pCh->NormalTermios; } else { *tty->termios = pCh->CalloutTermios; } } /* Now we must send the termios settings to the loadware */ set_params( pCh, NULL ); } /* override previous and never reset ??? */ pCh->session = current->session; pCh->pgrp = current->pgrp; /* * Now set any i2lib options. These may go away if the i2lib code ends * up rolled into the mainline. */ pCh->channelOptions |= CO_NBLOCK_WRITE;#ifdef IP2DEBUG_OPEN printk (KERN_DEBUG "IP2: open completed\n" );#endif serviceOutgoingFifo( pCh->pMyBord ); ip2trace (CHANN, ITRC_OPEN, ITRC_RETURN, 0 ); return 0;}/******************************************************************************//* 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 ttyF%02X:\n",MINOR(tty->device));#endif if ( tty_hung_up_p ( pFile ) ) { MOD_DEC_USE_COUNT; ip2trace (CHANN, ITRC_CLOSE, 2, 1, 2 ); return; } if ( tty->count > 1 ) { /* not the last close */ MOD_DEC_USE_COUNT; ip2trace (CHANN, ITRC_CLOSE, 2, 1, 3 ); return; } pCh->flags |= ASYNC_CLOSING; // last close actually /* * Save the termios structure, since this port may have separate termios * for callout and dialin. */ if (pCh->flags & ASYNC_NORMAL_ACTIVE) pCh->NormalTermios = *tty->termios; if (pCh->flags & ASYNC_CALLOUT_ACTIVE) pCh->CalloutTermios = *tty->termios; 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) { current->state = TASK_INTERRUPTIBLE; schedule_timeout(pCh->ClosingDelay); } wake_up_interruptible(&pCh->open_wait); } pCh->flags &=~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE|ASYNC_CLOSING); wake_up_interruptible(&pCh->close_wait);#ifdef IP2DEBUG_OPEN DBG_CNT("ip2_close: after wakeups--");#endif MOD_DEC_USE_COUNT; 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|ASYNC_CALLOUT_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, int user, 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, user ); 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 str
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -