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

📄 synclink.c

📁 powerpc内核mpc8241linux系统下char驱动程序
💻 C
📖 第 1 页 / 共 5 页
字号:
		/* perform existance check and diagnostics */	if ( !retval )		retval = mgsl_adapter_test(info);			if ( retval ) {#if LINUX_VERSION_CODE >= VERSION(2,1,0)  		if (capable(CAP_SYS_ADMIN) && info->tty)#else  		if (suser() && info->tty)#endif					set_bit(TTY_IO_ERROR, &info->tty->flags);		mgsl_release_resources(info);  		return retval;  	}	/* program hardware for current parameters */	mgsl_change_params(info);		if (info->tty)		clear_bit(TTY_IO_ERROR, &info->tty->flags);	info->flags |= ASYNC_INITIALIZED;		return 0;	}	/* end of startup() *//* shutdown() * * Called by mgsl_close() and mgsl_hangup() to shutdown hardware * * Arguments:		info	pointer to device instance data * Return Value:	None */static void shutdown(struct mgsl_struct * info){	unsigned long flags;		if (!(info->flags & ASYNC_INITIALIZED))		return;	if (debug_level >= DEBUG_LEVEL_INFO)		printk("%s(%d):mgsl_shutdown(%s)\n",			 __FILE__,__LINE__, info->device_name );	/* clear status wait queue because status changes */	/* can't happen after shutting down the hardware */	wake_up_interruptible(&info->status_event_wait_q);	wake_up_interruptible(&info->event_wait_q);	if (info->xmit_buf) {		free_page((unsigned long) info->xmit_buf);		info->xmit_buf = 0;	}	spin_lock_irqsave(&info->irq_spinlock,flags);	usc_DisableMasterIrqBit(info);	usc_stop_receiver(info);	usc_stop_transmitter(info);	usc_DisableInterrupts(info,RECEIVE_DATA + RECEIVE_STATUS +		TRANSMIT_DATA + TRANSMIT_STATUS + IO_PIN + MISC );	usc_DisableDmaInterrupts(info,DICR_MASTER + DICR_TRANSMIT + DICR_RECEIVE);		/* Disable DMAEN (Port 7, Bit 14) */	/* This disconnects the DMA request signal from the ISA bus */	/* on the ISA adapter. This has no effect for the PCI adapter */	usc_OutReg(info, PCR, (u16)((usc_InReg(info, PCR) | BIT15) | BIT14));		/* Disable INTEN (Port 6, Bit12) */	/* This disconnects the IRQ request signal to the ISA bus */	/* on the ISA adapter. This has no effect for the PCI adapter */	usc_OutReg(info, PCR, (u16)((usc_InReg(info, PCR) | BIT13) | BIT12));	 	if (!info->tty || info->tty->termios->c_cflag & HUPCL) { 		info->serial_signals &= ~(SerialSignal_DTR + SerialSignal_RTS);		usc_set_serial_signals(info);	}		spin_unlock_irqrestore(&info->irq_spinlock,flags);	mgsl_release_resources(info);			if (info->tty)		set_bit(TTY_IO_ERROR, &info->tty->flags);	info->flags &= ~ASYNC_INITIALIZED;	}	/* end of shutdown() *//* mgsl_change_params() * *	Reconfigure adapter based on new parameters * * Arguments:		info	pointer to device instance data * Return Value:	None */static void mgsl_change_params(struct mgsl_struct *info){	unsigned cflag;	unsigned long flags;	int bits_per_char;	if (!info->tty || !info->tty->termios)		return;			if (debug_level >= DEBUG_LEVEL_INFO)		printk("%s(%d):mgsl_change_params(%s)\n",			 __FILE__,__LINE__, info->device_name );			 	cflag = info->tty->termios->c_cflag;	/* if B0 rate (hangup) specified then negate DTR and RTS */	/* otherwise assert DTR and RTS */ 	if (cflag & CBAUD)		info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR;	else		info->serial_signals &= ~(SerialSignal_RTS + SerialSignal_DTR);		/* byte size and parity */		switch (cflag & CSIZE) {	      case CS5: info->params.data_bits = 5; break;	      case CS6: info->params.data_bits = 6; break;	      case CS7: info->params.data_bits = 7; break;	      case CS8: info->params.data_bits = 8; break;	      /* Never happens, but GCC is too dumb to figure it out */	      default:  info->params.data_bits = 7; break;	      }	      	if (cflag & CSTOPB)		info->params.stop_bits = 2;	else		info->params.stop_bits = 1;	info->params.parity = ASYNC_PARITY_NONE;	if (cflag & PARENB) {		if (cflag & PARODD)			info->params.parity = ASYNC_PARITY_ODD;		else			info->params.parity = ASYNC_PARITY_EVEN;#ifdef CMSPAR		if (cflag & CMSPAR)			info->params.parity = ASYNC_PARITY_SPACE;#endif	}	/* calculate number of jiffies to transmit a full	 * FIFO (32 bytes) at specified data rate	 */	bits_per_char = info->params.data_bits + 			info->params.stop_bits + 1;	/* if port data rate is set to 460800 or less then	 * allow tty settings to override, otherwise keep the	 * current data rate.	 */	if (info->params.data_rate <= 460800) {#if LINUX_VERSION_CODE >= VERSION(2,1,0)		info->params.data_rate = tty_get_baud_rate(info->tty);#else		int i = cflag & CBAUD;		if (i & CBAUDEX) {			i &= ~CBAUDEX;			if (i < 1 || i > 4) 				info->tty->termios->c_cflag &= ~CBAUDEX;			else				i += 15;		}		info->params.data_rate = baud_table[i];#endif		}		if ( info->params.data_rate ) {		info->timeout = (32*HZ*bits_per_char) / 				info->params.data_rate;	}	info->timeout += HZ/50;		/* Add .02 seconds of slop */	if (cflag & CRTSCTS)		info->flags |= ASYNC_CTS_FLOW;	else		info->flags &= ~ASYNC_CTS_FLOW;			if (cflag & CLOCAL)		info->flags &= ~ASYNC_CHECK_CD;	else		info->flags |= ASYNC_CHECK_CD;	/* process tty input control flags */		info->read_status_mask = RXSTATUS_OVERRUN;	if (I_INPCK(info->tty))		info->read_status_mask |= RXSTATUS_PARITY_ERROR | RXSTATUS_FRAMING_ERROR; 	if (I_BRKINT(info->tty) || I_PARMRK(info->tty)) 		info->read_status_mask |= RXSTATUS_BREAK_RECEIVED;		if (I_IGNPAR(info->tty))		info->ignore_status_mask |= RXSTATUS_PARITY_ERROR | RXSTATUS_FRAMING_ERROR;	if (I_IGNBRK(info->tty)) {		info->ignore_status_mask |= RXSTATUS_BREAK_RECEIVED;		/* If ignoring parity and break indicators, ignore 		 * overruns too.  (For real raw support).		 */		if (I_IGNPAR(info->tty))			info->ignore_status_mask |= RXSTATUS_OVERRUN;	}	/* reprogram the hardware */		spin_lock_irqsave(&info->irq_spinlock,flags);		usc_stop_receiver(info);	usc_stop_transmitter(info);	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;		if ( info->params.mode == MGSL_MODE_HDLC )		usc_set_sync_mode(info);	else		usc_set_async_mode(info);			usc_set_serial_signals(info);	/* enable modem signal IRQs and read initial signal states */	usc_EnableStatusIrqs(info,SICR_CTS+SICR_DSR+SICR_DCD+SICR_RI);			usc_EnableInterrupts(info, IO_PIN);	usc_get_serial_signals(info);			if ( cflag & CREAD )		usc_start_receiver(info);			spin_unlock_irqrestore(&info->irq_spinlock,flags);}	/* end of mgsl_change_params() *//* mgsl_put_char() *  * 	Add a character to the transmit buffer. * 	 * Arguments:		tty	pointer to tty information structure * 			ch	character to add to transmit buffer * 		 * Return Value:	None */static void mgsl_put_char(struct tty_struct *tty, unsigned char ch){	struct mgsl_struct *info = (struct mgsl_struct *)tty->driver_data;	unsigned long flags;	if ( debug_level >= DEBUG_LEVEL_INFO ) {		printk( "%s(%d):mgsl_put_char(%d) on %s\n",			__FILE__,__LINE__,ch,info->device_name);	}				if (mgsl_paranoia_check(info, tty->device, "mgsl_put_char"))		return;	if (!tty || !info->xmit_buf)		return;	spin_lock_irqsave(&info->irq_spinlock,flags);		if ( (info->params.mode != MGSL_MODE_HDLC) || 	     !info->tx_active ) {			if (info->xmit_cnt < SERIAL_XMIT_SIZE - 1) {			info->xmit_buf[info->xmit_head++] = ch;			info->xmit_head &= SERIAL_XMIT_SIZE-1;			info->xmit_cnt++;		}	}		spin_unlock_irqrestore(&info->irq_spinlock,flags);	}	/* end of mgsl_put_char() *//* mgsl_flush_chars() *  * 	Enable transmitter so remaining characters in the * 	transmit buffer are sent. * 	 * Arguments:		tty	pointer to tty information structure * Return Value:	None */static void mgsl_flush_chars(struct tty_struct *tty){	struct mgsl_struct *info = (struct mgsl_struct *)tty->driver_data;	unsigned long flags;					if ( debug_level >= DEBUG_LEVEL_INFO )		printk( "%s(%d):mgsl_flush_chars() entry on %s xmit_cnt=%d\n",			__FILE__,__LINE__,info->device_name,info->xmit_cnt);		if (mgsl_paranoia_check(info, tty->device, "mgsl_flush_chars"))		return;	if (info->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped ||	    !info->xmit_buf)		return;	if ( debug_level >= DEBUG_LEVEL_INFO )		printk( "%s(%d):mgsl_flush_chars() entry on %s starting transmitter\n",			__FILE__,__LINE__,info->device_name );	spin_lock_irqsave(&info->irq_spinlock,flags);		if (!info->tx_active) {		if ( (info->params.mode == MGSL_MODE_HDLC) &&			info->xmit_cnt ) {			/* operating in synchronous (frame oriented) mode */			/* copy data from circular xmit_buf to */			/* transmit DMA buffer. */			mgsl_load_tx_dma_buffer(info,				 info->xmit_buf,info->xmit_cnt);		}	 	usc_start_transmitter(info);	}		spin_unlock_irqrestore(&info->irq_spinlock,flags);	}	/* end of mgsl_flush_chars() *//* mgsl_write() *  * 	Send a block of data * 	 * Arguments: *  * 	tty		pointer to tty information structure * 	from_user	flag: 1 = from user process * 	buf		pointer to buffer containing send data * 	count		size of send data in bytes * 	 * Return Value:	number of characters written */static int mgsl_write(struct tty_struct * tty, int from_user,		    const unsigned char *buf, int count){	int	c, ret = 0, err;	struct mgsl_struct *info = (struct mgsl_struct *)tty->driver_data;	unsigned long flags;		if ( debug_level >= DEBUG_LEVEL_INFO )		printk( "%s(%d):mgsl_write(%s) count=%d\n",			__FILE__,__LINE__,info->device_name,count);		if (mgsl_paranoia_check(info, tty->device, "mgsl_write"))		goto cleanup;	if (!tty || !info->xmit_buf || !tmp_buf)		goto cleanup;	if ( info->params.mode == MGSL_MODE_HDLC ) {		/* operating in synchronous (frame oriented) mode */			if (info->tx_active) {			ret = 0; goto cleanup; 		}				if ( info->xmit_cnt ) {			/* Send accumulated from send_char() calls */			/* as frame and wait before accepting more data. */			ret = 0;							/* copy data from circular xmit_buf to */			/* transmit DMA buffer. */			mgsl_load_tx_dma_buffer(info,				info->xmit_buf,info->xmit_cnt);			if ( debug_level >= DEBUG_LEVEL_INFO )				printk( "%s(%d):mgsl_write(%s) sync xmit_cnt flushing\n",					__FILE__,__LINE__,info->device_name);		} else {			if ( debug_level >= DEBUG_LEVEL_INFO )				printk( "%s(%d):mgsl_write(%s) sync transmit accepted\n",					__FILE__,__LINE__,info->device_name);			ret = count;			info->xmit_cnt = count;			if (from_user) {				down(&tmp_buf_sem);				COPY_FROM_USER(err,tmp_buf, buf, count);				if (err) {					if ( debug_level >= DEBUG_LEVEL_INFO )						printk( "%s(%d):mgsl_write(%s) sync user buf copy failed\n",							__FILE__,__LINE__,info->device_name);					ret = -EFAULT;				} else					mgsl_load_tx_dma_buffer(info,tmp_buf,count);				up(&tmp_buf_sem);			}			else				mgsl_load_tx_dma_buffer(info,buf,count);		}	} else {		if (from_user) {			down(&tmp_buf_sem);			while (1) {				c = MIN(count,					MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,					    SERIAL_XMIT_SIZE - info->xmit_head));				if (c <= 0)					break;				COPY_FROM_USER(err,tmp_buf, buf, c);				c -= err;				if (!c) {					if (!ret)						ret = -EFAULT;					break;				}				spin_lock_irqsave(&info->irq_spinlock,flags);				c = MIN(c, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,					       SERIAL_XMIT_SIZE - info->xmit_head));				memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c);				info->xmit_head = ((info->xmit_head + c) &						   (SERIAL_XMIT_SIZE-1));				info->xmit_cnt += c;				spin_unlock_irqrestore(&info->irq_spinlock,flags);				buf += c;				count -= c;				ret += c;			}			up(&tmp_buf_sem);		} else {			while (1) {				spin_lock_irqsave(&info->irq_spinlock,flags);				c = MIN(count,					MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,					    SERIAL_XMIT_SIZE - info->xmit_head));				if (c <= 0) {					spin_unlock_irqrestore(&info->irq_spinlock,flags);					break;				}				memcpy(info->xmit_buf + info->xmit_head, buf, c);				info->xmit_head = ((info->xmit_head + c) &						   (SERIAL_XMIT_SIZE-1));				info->xmit_cnt += c;				spin_unlock_irqrestore(&info->irq_spinlock,flags);				buf += c;				count -= c;				

⌨️ 快捷键说明

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