📄 synclink.c
字号:
} /* end of mgsl_isr_transmit_status() *//* mgsl_isr_io_pin() * * Service an Input/Output pin interrupt. The type of * interrupt is indicated by bits in the MISR * * Arguments: info pointer to device instance data * Return Value: None */void mgsl_isr_io_pin( struct mgsl_struct *info ){ struct mgsl_icount *icount; u16 status = usc_InReg( info, MISR ); if ( debug_level >= DEBUG_LEVEL_ISR ) printk("%s(%d):mgsl_isr_io_pin status=%04X\n", __FILE__,__LINE__,status); usc_ClearIrqPendingBits( info, IO_PIN ); usc_UnlatchIostatusBits( info, status ); if (status & (MISCSTATUS_CTS_LATCHED | MISCSTATUS_DCD_LATCHED | MISCSTATUS_DSR_LATCHED | MISCSTATUS_RI_LATCHED) ) { icount = &info->icount; /* update input line counters */ if (status & MISCSTATUS_RI_LATCHED) { if ((info->ri_chkcount)++ >= IO_PIN_SHUTDOWN_LIMIT) usc_DisablestatusIrqs(info,SICR_RI); icount->rng++; if ( status & MISCSTATUS_RI ) info->input_signal_events.ri_up++; else info->input_signal_events.ri_down++; } if (status & MISCSTATUS_DSR_LATCHED) { if ((info->dsr_chkcount)++ >= IO_PIN_SHUTDOWN_LIMIT) usc_DisablestatusIrqs(info,SICR_DSR); icount->dsr++; if ( status & MISCSTATUS_DSR ) info->input_signal_events.dsr_up++; else info->input_signal_events.dsr_down++; } if (status & MISCSTATUS_DCD_LATCHED) { if ((info->dcd_chkcount)++ >= IO_PIN_SHUTDOWN_LIMIT) usc_DisablestatusIrqs(info,SICR_DCD); icount->dcd++; if (status & MISCSTATUS_DCD) { info->input_signal_events.dcd_up++;#ifdef CONFIG_SYNCLINK_SYNCPPP if (info->netcount) sppp_reopen(info->netdev);#endif } else info->input_signal_events.dcd_down++; } if (status & MISCSTATUS_CTS_LATCHED) { if ((info->cts_chkcount)++ >= IO_PIN_SHUTDOWN_LIMIT) usc_DisablestatusIrqs(info,SICR_CTS); icount->cts++; if ( status & MISCSTATUS_CTS ) info->input_signal_events.cts_up++; else info->input_signal_events.cts_down++; } wake_up_interruptible(&info->status_event_wait_q); wake_up_interruptible(&info->event_wait_q); if ( (info->flags & ASYNC_CHECK_CD) && (status & MISCSTATUS_DCD_LATCHED) ) { if ( debug_level >= DEBUG_LEVEL_ISR ) printk("%s CD now %s...", info->device_name, (status & MISCSTATUS_DCD) ? "on" : "off"); if (status & MISCSTATUS_DCD) wake_up_interruptible(&info->open_wait); else if (!((info->flags & ASYNC_CALLOUT_ACTIVE) && (info->flags & ASYNC_CALLOUT_NOHUP))) { if ( debug_level >= DEBUG_LEVEL_ISR ) printk("doing serial hangup..."); if (info->tty) tty_hangup(info->tty); } } if ( (info->flags & ASYNC_CTS_FLOW) && (status & MISCSTATUS_CTS_LATCHED) ) { if (info->tty->hw_stopped) { if (status & MISCSTATUS_CTS) { if ( debug_level >= DEBUG_LEVEL_ISR ) printk("CTS tx start..."); if (info->tty) info->tty->hw_stopped = 0; usc_start_transmitter(info); info->pending_bh |= BH_TRANSMIT; return; } } else { if (!(status & MISCSTATUS_CTS)) { if ( debug_level >= DEBUG_LEVEL_ISR ) printk("CTS tx stop..."); if (info->tty) info->tty->hw_stopped = 1; usc_stop_transmitter(info); } } } } info->pending_bh |= BH_STATUS; /* for diagnostics set IRQ flag */ if ( status & MISCSTATUS_TXC_LATCHED ){ usc_OutReg( info, SICR, (unsigned short)(usc_InReg(info,SICR) & ~(SICR_TXC_ACTIVE+SICR_TXC_INACTIVE)) ); usc_UnlatchIostatusBits( info, MISCSTATUS_TXC_LATCHED ); info->irq_occurred = 1; }} /* end of mgsl_isr_io_pin() *//* mgsl_isr_transmit_data() * * Service a transmit data interrupt (async mode only). * * Arguments: info pointer to device instance data * Return Value: None */void mgsl_isr_transmit_data( struct mgsl_struct *info ){ if ( debug_level >= DEBUG_LEVEL_ISR ) printk("%s(%d):mgsl_isr_transmit_data xmit_cnt=%d\n", __FILE__,__LINE__,info->xmit_cnt); usc_ClearIrqPendingBits( info, TRANSMIT_DATA ); if (info->tty->stopped || info->tty->hw_stopped) { usc_stop_transmitter(info); return; } if ( info->xmit_cnt ) usc_load_txfifo( info ); else info->tx_active = 0; if (info->xmit_cnt < WAKEUP_CHARS) info->pending_bh |= BH_TRANSMIT;} /* end of mgsl_isr_transmit_data() *//* mgsl_isr_receive_data() * * Service a receive data interrupt. This occurs * when operating in asynchronous interrupt transfer mode. * The receive data FIFO is flushed to the receive data buffers. * * Arguments: info pointer to device instance data * Return Value: None */void mgsl_isr_receive_data( struct mgsl_struct *info ){ int Fifocount; u16 status; unsigned char DataByte; struct tty_struct *tty = info->tty; struct mgsl_icount *icount = &info->icount; if ( debug_level >= DEBUG_LEVEL_ISR ) printk("%s(%d):mgsl_isr_receive_data\n", __FILE__,__LINE__); usc_ClearIrqPendingBits( info, RECEIVE_DATA ); /* select FIFO status for RICR readback */ usc_RCmd( info, RCmd_SelectRicrRxFifostatus ); /* clear the Wordstatus bit so that status readback */ /* only reflects the status of this byte */ usc_OutReg( info, RICR+LSBONLY, (u16)(usc_InReg(info, RICR+LSBONLY) & ~BIT3 )); /* flush the receive FIFO */ while( (Fifocount = (usc_InReg(info,RICR) >> 8)) ) { /* read one byte from RxFIFO */ outw( (inw(info->io_base + CCAR) & 0x0780) | (RDR+LSBONLY), info->io_base + CCAR ); DataByte = inb( info->io_base + CCAR ); /* get the status of the received byte */ status = usc_InReg(info, RCSR); if ( status & (RXSTATUS_FRAMING_ERROR + RXSTATUS_PARITY_ERROR + RXSTATUS_OVERRUN + RXSTATUS_BREAK_RECEIVED) ) usc_UnlatchRxstatusBits(info,RXSTATUS_ALL); if (tty->flip.count >= TTY_FLIPBUF_SIZE) continue; *tty->flip.char_buf_ptr = DataByte; icount->rx++; *tty->flip.flag_buf_ptr = 0; if ( status & (RXSTATUS_FRAMING_ERROR + RXSTATUS_PARITY_ERROR + RXSTATUS_OVERRUN + RXSTATUS_BREAK_RECEIVED) ) { printk("rxerr=%04X\n",status); /* update error statistics */ if ( status & RXSTATUS_BREAK_RECEIVED ) { status &= ~(RXSTATUS_FRAMING_ERROR + RXSTATUS_PARITY_ERROR); icount->brk++; } else if (status & RXSTATUS_PARITY_ERROR) icount->parity++; else if (status & RXSTATUS_FRAMING_ERROR) icount->frame++; else if (status & RXSTATUS_OVERRUN) { /* must issue purge fifo cmd before */ /* 16C32 accepts more receive chars */ usc_RTCmd(info,RTCmd_PurgeRxFifo); icount->overrun++; } /* discard char if tty control flags say so */ if (status & info->ignore_status_mask) continue; status &= info->read_status_mask; if (status & RXSTATUS_BREAK_RECEIVED) { *tty->flip.flag_buf_ptr = TTY_BREAK; if (info->flags & ASYNC_SAK) do_SAK(tty); } else if (status & RXSTATUS_PARITY_ERROR) *tty->flip.flag_buf_ptr = TTY_PARITY; else if (status & RXSTATUS_FRAMING_ERROR) *tty->flip.flag_buf_ptr = TTY_FRAME; if (status & RXSTATUS_OVERRUN) { /* Overrun is special, since it's * reported immediately, and doesn't * affect the current character */ if (tty->flip.count < TTY_FLIPBUF_SIZE) { tty->flip.count++; tty->flip.flag_buf_ptr++; tty->flip.char_buf_ptr++; *tty->flip.flag_buf_ptr = TTY_OVERRUN; } } } /* end of if (error) */ tty->flip.flag_buf_ptr++; tty->flip.char_buf_ptr++; tty->flip.count++; } if ( debug_level >= DEBUG_LEVEL_ISR ) { printk("%s(%d):mgsl_isr_receive_data flip count=%d\n", __FILE__,__LINE__,tty->flip.count); printk("%s(%d):rx=%d brk=%d parity=%d frame=%d overrun=%d\n", __FILE__,__LINE__,icount->rx,icount->brk, icount->parity,icount->frame,icount->overrun); } if ( tty->flip.count ) tty_flip_buffer_push(tty);}/* mgsl_isr_misc() * * Service a miscellaneos interrupt source. * * Arguments: info pointer to device extension (instance data) * Return Value: None */void mgsl_isr_misc( struct mgsl_struct *info ){ u16 status = usc_InReg( info, MISR ); if ( debug_level >= DEBUG_LEVEL_ISR ) printk("%s(%d):mgsl_isr_misc status=%04X\n", __FILE__,__LINE__,status); usc_ClearIrqPendingBits( info, MISC ); usc_UnlatchMiscstatusBits( info, status );} /* end of mgsl_isr_misc() *//* mgsl_isr_null() * * Services undefined interrupt vectors from the * USC. (hence this function SHOULD never be called) * * Arguments: info pointer to device extension (instance data) * Return Value: None */void mgsl_isr_null( struct mgsl_struct *info ){} /* end of mgsl_isr_null() *//* mgsl_isr_receive_dma() * * Service a receive DMA channel interrupt. * For this driver there are two sources of receive DMA interrupts * as identified in the Receive DMA mode Register (RDMR): * * BIT3 EOA/EOL End of List, all receive buffers in receive * buffer list have been filled (no more free buffers * available). The DMA controller has shut down. * * BIT2 EOB End of Buffer. This interrupt occurs when a receive * DMA buffer is terminated in response to completion * of a good frame or a frame with errors. The status * of the frame is stored in the buffer entry in the * list of receive buffer entries. * * Arguments: info pointer to device instance data * Return Value: None */void mgsl_isr_receive_dma( struct mgsl_struct *info ){ u16 status; /* clear interrupt pending and IUS bit for Rx DMA IRQ */ usc_OutDmaReg( info, CDIR, BIT9+BIT1 ); /* Read the receive DMA status to identify interrupt type. */ /* This also clears the status bits. */ status = usc_InDmaReg( info, RDMR ); if ( debug_level >= DEBUG_LEVEL_ISR ) printk("%s(%d):mgsl_isr_receive_dma(%s) status=%04X\n", __FILE__,__LINE__,info->device_name,status); info->pending_bh |= BH_RECEIVE; if ( status & BIT3 ) { info->rx_overflow = 1; info->icount.buf_overrun++; }} /* end of mgsl_isr_receive_dma() *//* mgsl_isr_transmit_dma() * * This function services a transmit DMA channel interrupt. * * For this driver there is one source of transmit DMA interrupts * as identified in the Transmit DMA Mode Register (TDMR): * * BIT2 EOB End of Buffer. This interrupt occurs when a * transmit DMA buffer has been emptied. * * The driver maintains enough transmit DMA buffers to hold at least * one max frame size transmit frame. When operating in a buffered * transmit mode, there may be enough transmit DMA buffers to hold at * least two or more max frame size frames. On an EOB condition, * determine if there are any queued transmit buffers and copy into * transmit DMA buffers if we have room. * * Arguments: info pointer to device instance data * Return Value: None */void mgsl_isr_transmit_dma( struct mgsl_struct *info ){ u16 status; /* clear interrupt pending and IUS bit for Tx DMA IRQ */ usc_OutDmaReg(info, CDIR, BIT8+BIT0 ); /* Read the transmit DMA status to identify interrupt type. */ /* This also clears the status bits. */ status = usc_InDmaReg( info, TDMR ); if ( debug_level >= DEBUG_LEVEL_ISR ) printk("%s(%d):mgsl_isr_transmit_dma(%s) status=%04X\n", __FILE__,__LINE__,info->device_name,status); if ( status & BIT2 ) { --info->tx_dma_buffers_used; /* if there are transmit frames queued, * try to load the next one */ if ( load_next_tx_holding_buffer(info) ) { /* if call returns non-zero value, we have * at least one free tx holding buffer */ info->pending_bh |= BH_TRANSMIT; } }} /* end of mgsl_isr_transmit_dma() *//* mgsl_interrupt() * * Interrupt service routine entry point. * * Arguments: * * irq interrupt number that caused interrupt * dev_id device ID supplied during interrupt registration * regs interrupted processor context * * Return Value: None */static void mgsl_interrupt(int irq, void *dev_id, struct pt_regs * regs){ struct mgsl_struct * info; u16 UscVector; u16 DmaVector; if ( debug_level >= DEBUG_LEVEL_ISR ) printk("%s(%d):mgsl_interrupt(%d)entry.\n", __FILE__,__LINE__,irq); info = (struct mgsl_struct *)dev_id; if (!info) return; spin_lock(&info->irq_spinlock); for(;;) { /* Read the interrupt vectors from hardware. */ UscVector = usc_InReg(info, IVR) >> 9; DmaVector = usc_InDmaReg(info, DIVR); if ( debug_level >= DEBUG_LEVEL_ISR ) printk("%s(%d):%s UscVector=%08X DmaVector=%08X\n", __FILE__,__LINE__,info->device_name,UscVector,DmaVector); if ( !UscVector && !DmaVector ) break; /* Dispatch interrupt vector */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -