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

📄 synclink_cs.c

📁 这个linux源代码是很全面的~基本完整了~使用c编译的~由于时间问题我没有亲自测试~但就算用来做参考资料也是非常好的
💻 C
📖 第 1 页 / 共 5 页
字号:
		info->bh_running = 1;	while((action = bh_action(info)) != 0) {			/* Process work item */		if ( debug_level >= DEBUG_LEVEL_BH )			printk( "%s(%d):bh_handler() work item action=%d\n",				__FILE__,__LINE__,action);		switch (action) {				case BH_RECEIVE:			while(rx_get_frame(info));			break;		case BH_TRANSMIT:			bh_transmit(info);			break;		case BH_STATUS:			bh_status(info);			break;		default:			/* unknown work item ID */			printk("Unknown work item ID=%08X!\n", action);			break;		}	}	if (debug_level >= DEBUG_LEVEL_BH)		printk( "%s(%d):bh_handler(%s) exit\n",			__FILE__,__LINE__,info->device_name);}void bh_transmit(MGSLPC_INFO *info){	struct tty_struct *tty = info->tty;	if (debug_level >= DEBUG_LEVEL_BH)		printk("bh_transmit() entry on %s\n", info->device_name);	if (tty) {		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&		    tty->ldisc.write_wakeup) {			if ( debug_level >= DEBUG_LEVEL_BH )				printk( "%s(%d):calling ldisc.write_wakeup on %s\n",					__FILE__,__LINE__,info->device_name);			(tty->ldisc.write_wakeup)(tty);		}		wake_up_interruptible(&tty->write_wait);	}}void bh_status(MGSLPC_INFO *info){	info->ri_chkcount = 0;	info->dsr_chkcount = 0;	info->dcd_chkcount = 0;	info->cts_chkcount = 0;}/* eom: non-zero = end of frame */ void rx_ready_hdlc(MGSLPC_INFO *info, int eom) {	unsigned char data[2];	unsigned char fifo_count, read_count, i;	RXBUF *buf = (RXBUF*)(info->rx_buf + (info->rx_put * info->rx_buf_size));	if (debug_level >= DEBUG_LEVEL_ISR)		printk("%s(%d):rx_ready_hdlc(eom=%d)\n",__FILE__,__LINE__,eom);		if (!info->rx_enabled)		return;	if (info->rx_frame_count >= info->rx_buf_count) {		/* no more free buffers */		issue_command(info, CHA, CMD_RXRESET);		info->pending_bh |= BH_RECEIVE;		info->rx_overflow = 1;		info->icount.buf_overrun++;		return;	}	if (eom) {		/* end of frame, get FIFO count from RBCL register */ 		if (!(fifo_count = (unsigned char)(read_reg(info, CHA+RBCL) & 0x1f)))			fifo_count = 32;	} else		fifo_count = 32;		do {		if (fifo_count == 1) {			read_count = 1;			data[0] = read_reg(info, CHA + RXFIFO);		} else {			read_count = 2;			*((unsigned short *) data) = read_reg16(info, CHA + RXFIFO);		}		fifo_count -= read_count;		if (!fifo_count && eom)			buf->status = data[--read_count];		for (i = 0; i < read_count; i++) {			if (buf->count >= info->max_frame_size) {				/* frame too large, reset receiver and reset current buffer */				issue_command(info, CHA, CMD_RXRESET);				buf->count = 0;				return;			}			*(buf->data + buf->count) = data[i];			buf->count++;		}	} while (fifo_count);	if (eom) {		info->pending_bh |= BH_RECEIVE;		info->rx_frame_count++;		info->rx_put++;		if (info->rx_put >= info->rx_buf_count)			info->rx_put = 0;	}	issue_command(info, CHA, CMD_RXFIFO);}void rx_ready_async(MGSLPC_INFO *info, int tcd) {	unsigned char data, status;	int fifo_count; 	struct tty_struct *tty = info->tty; 	struct mgsl_icount *icount = &info->icount;	if (tcd) {		/* early termination, get FIFO count from RBCL register */ 		fifo_count = (unsigned char)(read_reg(info, CHA+RBCL) & 0x1f);		/* Zero fifo count could mean 0 or 32 bytes available.		 * If BIT5 of STAR is set then at least 1 byte is available.		 */		if (!fifo_count && (read_reg(info,CHA+STAR) & BIT5))			fifo_count = 32;	} else		fifo_count = 32;		/* Flush received async data to receive data buffer. */ 	while (fifo_count) {		data   = read_reg(info, CHA + RXFIFO);		status = read_reg(info, CHA + RXFIFO);		fifo_count -= 2;		if (tty->flip.count >= TTY_FLIPBUF_SIZE)			break;					*tty->flip.char_buf_ptr = data;		icount->rx++;				*tty->flip.flag_buf_ptr = 0;		// if no frameing/crc error then save data		// BIT7:parity error		// BIT6:framing error		if (status & (BIT7 + BIT6)) {			if (status & BIT7) 				icount->parity++;			else				icount->frame++;			/* discard char if tty control flags say so */			if (status & info->ignore_status_mask)				continue;							status &= info->read_status_mask;			if (status & BIT7)				*tty->flip.flag_buf_ptr = TTY_PARITY;			else if (status & BIT6)				*tty->flip.flag_buf_ptr = TTY_FRAME;		}				tty->flip.flag_buf_ptr++;		tty->flip.char_buf_ptr++;		tty->flip.count++;	}	issue_command(info, CHA, CMD_RXFIFO);	if (debug_level >= DEBUG_LEVEL_ISR) {		printk("%s(%d):rx_ready_async 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);}void tx_done(MGSLPC_INFO *info) {	if (!info->tx_active)		return;				info->tx_active = 0;	info->tx_aborting = 0;	if (info->params.mode == MGSL_MODE_ASYNC)		return;	info->tx_count = info->tx_put = info->tx_get = 0;	del_timer(&info->tx_timer);			if (info->drop_rts_on_tx_done) {		get_signals(info);		if (info->serial_signals & SerialSignal_RTS) {			info->serial_signals &= ~SerialSignal_RTS;			set_signals(info);		}		info->drop_rts_on_tx_done = 0;	}#ifdef CONFIG_SYNCLINK_SYNCPPP		if (info->netcount)		mgslpc_sppp_tx_done(info);	else #endif	{		if (info->tty->stopped || info->tty->hw_stopped) {			tx_stop(info);			return;		}		info->pending_bh |= BH_TRANSMIT;	}}void tx_ready(MGSLPC_INFO *info) {	unsigned char fifo_count = 32;	int c;	if (debug_level >= DEBUG_LEVEL_ISR)		printk("%s(%d):tx_ready(%s)\n", __FILE__,__LINE__,info->device_name);	if (info->params.mode == MGSL_MODE_HDLC) {		if (!info->tx_active)			return;	} else {		if (info->tty->stopped || info->tty->hw_stopped) {			tx_stop(info);			return;		}		if (!info->tx_count)			info->tx_active = 0;	}	if (!info->tx_count)		return;	while (info->tx_count && fifo_count) {		c = MIN(2, MIN(fifo_count, MIN(info->tx_count, TXBUFSIZE - info->tx_get)));				if (c == 1) {			write_reg(info, CHA + TXFIFO, *(info->tx_buf + info->tx_get));		} else {			write_reg16(info, CHA + TXFIFO,					  *((unsigned short*)(info->tx_buf + info->tx_get)));		}		info->tx_count -= c;		info->tx_get = (info->tx_get + c) & (TXBUFSIZE - 1);		fifo_count -= c;	}	if (info->params.mode == MGSL_MODE_ASYNC) {		if (info->tx_count < WAKEUP_CHARS)			info->pending_bh |= BH_TRANSMIT;		issue_command(info, CHA, CMD_TXFIFO);	} else {		if (info->tx_count)			issue_command(info, CHA, CMD_TXFIFO);		else			issue_command(info, CHA, CMD_TXFIFO + CMD_TXEOM);	}}void cts_change(MGSLPC_INFO *info) {	get_signals(info);	if ((info->cts_chkcount)++ >= IO_PIN_SHUTDOWN_LIMIT)		irq_disable(info, CHB, IRQ_CTS);	info->icount.cts++;	if (info->serial_signals & SerialSignal_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_CTS_FLOW) {		if (info->tty->hw_stopped) {			if (info->serial_signals & SerialSignal_CTS) {				if (debug_level >= DEBUG_LEVEL_ISR)					printk("CTS tx start...");				if (info->tty)					info->tty->hw_stopped = 0;				tx_start(info);				info->pending_bh |= BH_TRANSMIT;				return;			}		} else {			if (!(info->serial_signals & SerialSignal_CTS)) {				if (debug_level >= DEBUG_LEVEL_ISR)					printk("CTS tx stop...");				if (info->tty)					info->tty->hw_stopped = 1;				tx_stop(info);			}		}	}	info->pending_bh |= BH_STATUS;}void dcd_change(MGSLPC_INFO *info) {	get_signals(info);	if ((info->dcd_chkcount)++ >= IO_PIN_SHUTDOWN_LIMIT)		irq_disable(info, CHB, IRQ_DCD);	info->icount.dcd++;	if (info->serial_signals & SerialSignal_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++;	wake_up_interruptible(&info->status_event_wait_q);	wake_up_interruptible(&info->event_wait_q);	if (info->flags & ASYNC_CHECK_CD) {		if (debug_level >= DEBUG_LEVEL_ISR)			printk("%s CD now %s...", info->device_name,			       (info->serial_signals & SerialSignal_DCD) ? "on" : "off");		if (info->serial_signals & SerialSignal_DCD)			wake_up_interruptible(&info->open_wait);		else if (!(info->flags & (ASYNC_CALLOUT_ACTIVE | ASYNC_CALLOUT_NOHUP))) {			if (debug_level >= DEBUG_LEVEL_ISR)				printk("doing serial hangup...");			if (info->tty)				tty_hangup(info->tty);		}	}	info->pending_bh |= BH_STATUS;}void dsr_change(MGSLPC_INFO *info) {	get_signals(info);	if ((info->dsr_chkcount)++ >= IO_PIN_SHUTDOWN_LIMIT)		port_irq_disable(info, PVR_DSR);	info->icount.dsr++;	if (info->serial_signals & SerialSignal_DSR)		info->input_signal_events.dsr_up++;	else		info->input_signal_events.dsr_down++;	wake_up_interruptible(&info->status_event_wait_q);	wake_up_interruptible(&info->event_wait_q);	info->pending_bh |= BH_STATUS;}void ri_change(MGSLPC_INFO *info) {	get_signals(info);	if ((info->ri_chkcount)++ >= IO_PIN_SHUTDOWN_LIMIT)		port_irq_disable(info, PVR_RI);	info->icount.rng++;	if (info->serial_signals & SerialSignal_RI)		info->input_signal_events.ri_up++;	else		info->input_signal_events.ri_down++;	wake_up_interruptible(&info->status_event_wait_q);	wake_up_interruptible(&info->event_wait_q);	info->pending_bh |= BH_STATUS;}/* Interrupt service routine entry point. * 	 * Arguments: *  * irq     interrupt number that caused interrupt * dev_id  device ID supplied during interrupt registration * regs    interrupted processor context */static void mgslpc_isr(int irq, void *dev_id, struct pt_regs * regs){	MGSLPC_INFO * info = (MGSLPC_INFO *)dev_id;	unsigned short isr;	unsigned char gis, pis;	int count=0;	if (debug_level >= DEBUG_LEVEL_ISR)			printk("mgslpc_isr(%d) entry.\n", irq);	if (!info)		return;			if (!(info->link.state & DEV_CONFIG))		return;	spin_lock(&info->lock);	while ((gis = read_reg(info, CHA + GIS))) {		if (debug_level >= DEBUG_LEVEL_ISR)				printk("mgslpc_isr %s gis=%04X\n", info->device_name,gis);		if ((gis & 0x70) || count > 1000) {			printk("synclink_cs:hardware failed or ejected\n");			break;		}		count++;		if (gis & (BIT1 + BIT0)) {			isr = read_reg16(info, CHB + ISR);			if (isr & IRQ_DCD)				dcd_change(info);			if (isr & IRQ_CTS)				cts_change(info);		}		if (gis & (BIT3 + BIT2))		{			isr = read_reg16(info, CHA + ISR);			if (isr & IRQ_TIMER) {				info->irq_occurred = 1;				irq_disable(info, CHA, IRQ_TIMER);			}			/* receive IRQs */ 			if (isr & IRQ_EXITHUNT) {				info->icount.exithunt++;				wake_up_interruptible(&info->event_wait_q);			}			if (isr & IRQ_BREAK_ON) {				info->icount.brk++;				if (info->flags & ASYNC_SAK)					do_SAK(info->tty);			}			if (isr & IRQ_RXTIME) {				issue_command(info, CHA, CMD_RXFIFO_READ);			}			if (isr & (IRQ_RXEOM + IRQ_RXFIFO)) {				if (info->params.mode == MGSL_MODE_HDLC)					rx_ready_hdlc(info, isr & IRQ_RXEOM); 				else					rx_ready_async(info, isr & IRQ_RXEOM);			}			/* transmit IRQs */ 			if (isr & IRQ_UNDERRUN) {				if (info->tx_aborting)					info->icount.txabort++;				else					info->icount.txunder++;				tx_done(info);			}			else if (isr & IRQ_ALLSENT) {				info->icount.txok++;				tx_done(info);			}			else if (isr & IRQ_TXFIFO)				tx_ready(info);		}		if (gis & BIT7) {			pis = read_reg(info, CHA + PIS);			if (pis & BIT1)				dsr_change(info);			if (pis & BIT2)				ri_change(info);		}	}		/* Request bottom half processing if there's something 	 * for it to do and the bh is not already running	 */	if (info->pending_bh && !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->lock);

⌨️ 快捷键说明

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