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

📄 synclink.c

📁 powerpc内核mpc8241linux系统下char驱动程序
💻 C
📖 第 1 页 / 共 5 页
字号:
			usc_set_serial_signals( info );		}		info->drop_rts_on_tx_done = 0;	}			if (info->tty->stopped || info->tty->hw_stopped) {		usc_stop_transmitter(info);		return;	}		mgsl_bh_queue_put(info, BH_TYPE_TRANSMIT_STATUS, status);}	/* 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)			icount->rng++;		if (status & MISCSTATUS_DSR_LATCHED)			icount->dsr++;		if (status & MISCSTATUS_DCD_LATCHED) {			icount->dcd++;#ifdef CONFIG_HARD_PPS			if ((info->flags & ASYNC_HARDPPS_CD) &&			    (status & MISCSTATUS_DCD_LATCHED))				hardpps();#endif		}		if (status & MISCSTATUS_CTS_LATCHED)			icount->cts++;		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...");					info->tty->hw_stopped = 0;					usc_start_transmitter(info);					mgsl_bh_queue_put( info, BH_TYPE_TRANSMIT_DATA, status );					return;				}			} else {				if (!(status & MISCSTATUS_CTS)) {					if ( debug_level >= DEBUG_LEVEL_ISR )						printk("CTS tx stop...");					info->tty->hw_stopped = 1;					usc_stop_transmitter(info);				}			}		}	}	/* 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)		mgsl_bh_queue_put(info, BH_TYPE_TRANSMIT_DATA, (unsigned short)(info->xmit_cnt));}	/* 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 ) {#if LINUX_VERSION_CODE >= VERSION(2,1,0)		tty_flip_buffer_push(tty);#else				queue_task(&tty->flip.tqueue, &tq_timer); #endif			}	}	/* end of mgsl_isr_receive_data() *//* 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);				/* Post a receive event for BH processing. */	mgsl_bh_queue_put( info, BH_TYPE_RECEIVE_DMA, status );		if ( status & BIT3 )		info->rx_overflow = 1;}	/* end of mgsl_isr_receive_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 */		if ( UscVector )			(*UscIsrTable[UscVector])(info);		else			mgsl_isr_receive_dma(info);		if ( info->isr_overflow ) {			printk(KERN_ERR"%s(%d):%s isr overflow irq=%d\n",				__FILE__,__LINE__,info->device_name, irq);				/* Interrupt overflow. Reset adapter and exit. *///				UscReset(info);//				break;		}	}		/* Request bottom half processing if there's something 	 * for it to do and the bh is not already running	 */	if ( info->bh_queue_head && !info->bh_running && !info->bh_requested ) {		if ( debug_level >= DEBUG_LEVEL_ISR )				printk("%s(%d):%s queueing bh task.\n",				__FILE__,__LINE__,info->device_name);		queue_task(&info->task, &tq_immediate);		mark_bh(IMMEDIATE_BH);		info->bh_requested = 1;	}	spin_unlock(&info->irq_spinlock);		if ( debug_level >= DEBUG_LEVEL_ISR )			printk("%s(%d):mgsl_interrupt(%d)exit.\n",			__FILE__,__LINE__,irq);}	/* end of mgsl_interrupt() *//* startup() *  * 	Initialize and start device. * 	 * Arguments:		info	pointer to device instance data * Return Value:	0 if success, otherwise error code */static int startup(struct mgsl_struct * info){	int retval = 0;		if ( debug_level >= DEBUG_LEVEL_INFO )		printk("%s(%d):mgsl_startup(%s)\n",__FILE__,__LINE__,info->device_name);			if (info->flags & ASYNC_INITIALIZED)		return 0;		if (!info->xmit_buf) {		/* allocate a page of memory for a transmit buffer */		info->xmit_buf = (unsigned char *)get_free_page(GFP_KERNEL);		if (!info->xmit_buf) {			printk(KERN_ERR"%s(%d):%s can't allocate transmit buffer\n",				__FILE__,__LINE__,info->device_name);			return -ENOMEM;		}	}	mgsl_format_bh_queue(info);		init_timer(&info->tx_timer);	info->tx_timer.data = (unsigned long)info;	info->tx_timer.function = mgsl_tx_timeout;		/* Allocate and claim adapter resources */	retval = mgsl_claim_resources(info);

⌨️ 快捷键说明

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