📄 ip2main.c
字号:
CHANNEL_OF(tempCommand) = 0; PTYPE_OF(tempCommand) = PTYPE_BYPASS; CMD_COUNT_OF(tempCommand) = 1; (CMD_OF(tempCommand))[0] = 84; /* get BOX_IDS */ iiWriteBuf(pB, tempCommand, 3);#ifdef XXX // enable heartbeat for test porpoises CHANNEL_OF(tempCommand) = 0; PTYPE_OF(tempCommand) = PTYPE_BYPASS; CMD_COUNT_OF(tempCommand) = 2; (CMD_OF(tempCommand))[0] = 44; /* get ping */ (CMD_OF(tempCommand))[1] = 200; /* 200 ms */ WRITE_LOCK_IRQSAVE(&pB->write_fifo_spinlock,flags); iiWriteBuf(pB, tempCommand, 4); WRITE_UNLOCK_IRQRESTORE(&pB->write_fifo_spinlock,flags);#endif iiEnableMailIrq(pB); iiSendPendingMail(pB);}/******************************************************************************//* Interrupt Handler Section *//******************************************************************************/static inline voidservice_all_boards(){ int i; i2eBordStrPtr pB; /* Service every board on the list */ for( i = 0; i < IP2_MAX_BOARDS; ++i ) { pB = i2BoardPtrTable[i]; if ( pB ) { i2ServiceBoard( pB ); } }}#ifdef USE_IQIstatic struct tq_struct senior_service ={ // it's the death that worse than fate NULL, 0, (void(*)(void*)) service_all_boards, NULL, //later - board address XXX};#endif/******************************************************************************//* Function: ip2_interrupt(int irq, void *dev_id, struct pt_regs * regs) *//* Parameters: irq - interrupt number *//* pointer to optional device ID structure *//* pointer to register structure *//* Returns: Nothing *//* *//* Description: *//* *//* *//******************************************************************************/static voidip2_interrupt(int irq, void *dev_id, struct pt_regs * regs){ int i; i2eBordStrPtr pB;#ifdef IP2DEBUG_TRACE ip2trace (ITRC_NO_PORT, ITRC_INTR, 99, 1, irq );#endif#ifdef USE_IQI queue_task(&senior_service, &tq_immediate); mark_bh(IMMEDIATE_BH);#else /* Service just the boards on the list using this irq */ for( i = 0; i < i2nBoards; ++i ) { pB = i2BoardPtrTable[i]; if ( pB && (pB->i2eUsingIrq == irq) ) { i2ServiceBoard( pB ); } }#endif /* USE_IQI */ ++irq_counter;#ifdef IP2DEBUG_TRACE ip2trace (ITRC_NO_PORT, ITRC_INTR, ITRC_RETURN, 0 );#endif}/******************************************************************************//* Function: ip2_poll(unsigned long arg) *//* Parameters: ? *//* Returns: Nothing *//* *//* Description: *//* This function calls the library routine i2ServiceBoard for each board in *//* the board table. This is used instead of the interrupt routine when polled *//* mode is specified. *//******************************************************************************/static voidip2_poll(unsigned long arg){#ifdef IP2DEBUG_TRACE ip2trace (ITRC_NO_PORT, ITRC_INTR, 100, 0 );#endif TimerOn = 0; // it's the truth but not checked in service bh_counter++; #ifdef USE_IQI queue_task(&senior_service, &tq_immediate); mark_bh(IMMEDIATE_BH);#else // Just polled boards, service_all might be better ip2_interrupt(0, NULL, NULL);#endif /* USE_IQI */ PollTimer.expires = POLL_TIMEOUT; add_timer( &PollTimer ); TimerOn = 1;#ifdef IP2DEBUG_TRACE ip2trace (ITRC_NO_PORT, ITRC_INTR, ITRC_RETURN, 0 );#endif}static inline void do_input( i2ChanStrPtr pCh ){ unsigned long flags;#ifdef IP2DEBUG_TRACE ip2trace(CHANN, ITRC_INPUT, 21, 0 );#endif // Data input if ( pCh->pTTY != NULL ) { READ_LOCK_IRQSAVE(&pCh->Ibuf_spinlock,flags) if (!pCh->throttled && (pCh->Ibuf_stuff != pCh->Ibuf_strip)) { READ_UNLOCK_IRQRESTORE(&pCh->Ibuf_spinlock,flags) i2Input( pCh ); } else READ_UNLOCK_IRQRESTORE(&pCh->Ibuf_spinlock,flags) } else {#ifdef IP2DEBUG_TRACE ip2trace(CHANN, ITRC_INPUT, 22, 0 );#endif i2InputFlush( pCh ); }}// code duplicated from n_tty (ldisc)static inline void isig(int sig, struct tty_struct *tty, int flush){ if (tty->pgrp > 0) kill_pg(tty->pgrp, sig, 1); if (flush || !L_NOFLSH(tty)) { if ( tty->ldisc.flush_buffer ) tty->ldisc.flush_buffer(tty); i2InputFlush( tty->driver_data ); }}static inline voiddo_status( i2ChanStrPtr pCh ){ int status; status = i2GetStatus( pCh, (I2_BRK|I2_PAR|I2_FRA|I2_OVR) );#ifdef IP2DEBUG_TRACE ip2trace (CHANN, ITRC_STATUS, 21, 1, status );#endif if (pCh->pTTY && (status & (I2_BRK|I2_PAR|I2_FRA|I2_OVR)) ) { if ( (status & I2_BRK) ) { // code duplicated from n_tty (ldisc) if (I_IGNBRK(pCh->pTTY)) goto skip_this; if (I_BRKINT(pCh->pTTY)) { isig(SIGINT, pCh->pTTY, 1); goto skip_this; } wake_up_interruptible(&pCh->pTTY->read_wait); }#ifdef NEVER_HAPPENS_AS_SETUP_XXX // and can't work because we don't know the_char // as the_char is reported on a seperate path // The intelligent board does this stuff as setup { char brkf = TTY_NORMAL; unsigned char brkc = '\0'; unsigned char tmp; if ( (status & I2_BRK) ) { brkf = TTY_BREAK; brkc = '\0'; } else if (status & I2_PAR) { brkf = TTY_PARITY; brkc = the_char; } else if (status & I2_FRA) { brkf = TTY_FRAME; brkc = the_char; } else if (status & I2_OVR) { brkf = TTY_OVERRUN; brkc = the_char; } tmp = pCh->pTTY->real_raw; pCh->pTTY->real_raw = 0; pCh->pTTY->ldisc.receive_buf( pCh->pTTY, &brkc, &brkf, 1 ); pCh->pTTY->real_raw = tmp; }#endif /* NEVER_HAPPENS_AS_SETUP_XXX */ }skip_this: if ( status & (I2_DDCD | I2_DDSR | I2_DCTS | I2_DRI) ) { wake_up_interruptible(&pCh->delta_msr_wait); if ( (pCh->flags & ASYNC_CHECK_CD) && (status & I2_DDCD) ) { if ( status & I2_DCD ) { if ( pCh->wopen ) { wake_up_interruptible ( &pCh->open_wait ); } } else if ( !(pCh->flags & ASYNC_CALLOUT_ACTIVE) ) { if (pCh->pTTY && (!(pCh->pTTY->termios->c_cflag & CLOCAL)) ) { tty_hangup( pCh->pTTY ); } } } }#ifdef IP2DEBUG_TRACE ip2trace (CHANN, ITRC_STATUS, 26, 0 );#endif}/******************************************************************************//* Device Open/Close/Ioctl Entry Point Section *//******************************************************************************//******************************************************************************//* Function: open_sanity_check() *//* Parameters: Pointer to tty structure *//* Pointer to file structure *//* Returns: Success or failure *//* *//* Description: *//* Verifies the structure magic numbers and cross links. *//******************************************************************************/#ifdef IP2DEBUG_OPENstatic void open_sanity_check( i2ChanStrPtr pCh, i2eBordStrPtr pBrd ){ if ( pBrd->i2eValid != I2E_MAGIC ) { printk(KERN_ERR "IP2: invalid board structure\n" ); } else if ( pBrd != pCh->pMyBord ) { printk(KERN_ERR "IP2: board structure pointer mismatch (%p)\n", pCh->pMyBord ); } else if ( pBrd->i2eChannelCnt < pCh->port_index ) { printk(KERN_ERR "IP2: bad device index (%d)\n", pCh->port_index ); } else if (&((i2ChanStrPtr)pBrd->i2eChannelPtr)[pCh->port_index] != pCh) { } else { printk(KERN_INFO "IP2: all pointers check out!\n" ); }}#endif/******************************************************************************//* Function: ip2_open() *//* Parameters: Pointer to tty structure *//* Pointer to file structure *//* Returns: Success or failure *//* *//* Description: (MANDATORY) *//* A successful device open has to run a gauntlet of checks before it *//* completes. After some sanity checking and pointer setup, the function *//* blocks until all conditions are satisfied. It then initialises the port to *//* the default characteristics and returns. *//******************************************************************************/static intip2_open( PTTY tty, struct file *pFile ){ int rc = 0; int do_clocal = 0; i2ChanStrPtr pCh = DevTable[MINOR(tty->device)];#ifdef IP2DEBUG_TRACE ip2trace (MINOR(tty->device), ITRC_OPEN, ITRC_ENTER, 0 );#endif if ( pCh == NULL ) { return -ENODEV; } /* Setup pointer links in device and tty structures */ pCh->pTTY = tty; tty->driver_data = pCh; MOD_INC_USE_COUNT;#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. */ if ( tty_hung_up_p(pFile) || ( pCh->flags & ASYNC_CLOSING )) { if ( pCh->flags & ASYNC_CLOSING ) { interruptible_sleep_on( &pCh->close_wait); } if ( tty_hung_up_p(pFile) ) { return( pCh->flags & ASYNC_HUP_NOTIFY ) ? -EAGAIN : -ERESTARTSYS; } } /* * 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; for(;;) { if ( !(pCh->flags & ASYNC_CALLOUT_ACTIVE)) { i2QueueCommands(PTYPE_INLINE, pCh, 100, 2, CMD_DTRUP, CMD_RTSUP); pCh->dataSetOut |= (I2_DTR | I2_RTS); serviceOutgoingFifo( pCh->pMyBord ); } if ( tty_hung_up_p(pFile) ) { 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",
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -