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

📄 vme_scc.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	}	SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET);}static void scc_stat_int(int irq, void *data, struct pt_regs *fp){	struct scc_port *port = data;	unsigned channel = port->channel;	unsigned char	last_sr, sr, changed;	SCC_ACCESS_INIT(port);	last_sr = scc_last_status_reg[channel];	sr = scc_last_status_reg[channel] = SCCread_NB(STATUS_REG);	changed = last_sr ^ sr;	if (changed & SR_DCD) {		port->c_dcd = !!(sr & SR_DCD);		if (!(port->gs.flags & ASYNC_CHECK_CD))			;	/* Don't report DCD changes */		else if (port->c_dcd) {			if (~(port->gs.flags & ASYNC_NORMAL_ACTIVE) ||				~(port->gs.flags & ASYNC_CALLOUT_ACTIVE)) {				/* Are we blocking in open?*/				wake_up_interruptible(&port->gs.open_wait);			}		}		else {			if (!((port->gs.flags & ASYNC_CALLOUT_ACTIVE) &&					(port->gs.flags & ASYNC_CALLOUT_NOHUP))) {				if (port->gs.tty)					tty_hangup (port->gs.tty);			}		}	}	SCCwrite(COMMAND_REG, CR_EXTSTAT_RESET);	SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET);}/*--------------------------------------------------------------------------- * generic_serial.c callback funtions *--------------------------------------------------------------------------*/static void scc_disable_tx_interrupts(void *ptr){	struct scc_port *port = ptr;	unsigned long	flags;	SCC_ACCESS_INIT(port);	save_flags(flags);	cli();	SCCmod(INT_AND_DMA_REG, ~IDR_TX_INT_ENAB, 0);	port->gs.flags &= ~GS_TX_INTEN;	restore_flags(flags);}static void scc_enable_tx_interrupts(void *ptr){	struct scc_port *port = ptr;	unsigned long	flags;	SCC_ACCESS_INIT(port);	save_flags(flags);	cli();	SCCmod(INT_AND_DMA_REG, 0xff, IDR_TX_INT_ENAB);	/* restart the transmitter */	scc_tx_int (0, port, 0);	restore_flags(flags);}static void scc_disable_rx_interrupts(void *ptr){	struct scc_port *port = ptr;	unsigned long	flags;	SCC_ACCESS_INIT(port);	save_flags(flags);	cli();	SCCmod(INT_AND_DMA_REG,	    ~(IDR_RX_INT_MASK|IDR_PARERR_AS_SPCOND|IDR_EXTSTAT_INT_ENAB), 0);	restore_flags(flags);}static void scc_enable_rx_interrupts(void *ptr){	struct scc_port *port = ptr;	unsigned long	flags;	SCC_ACCESS_INIT(port);	save_flags(flags);	cli();	SCCmod(INT_AND_DMA_REG, 0xff,		IDR_EXTSTAT_INT_ENAB|IDR_PARERR_AS_SPCOND|IDR_RX_INT_ALL);	restore_flags(flags);}static int scc_get_CD(void *ptr){	struct scc_port *port = ptr;	unsigned channel = port->channel;	return !!(scc_last_status_reg[channel] & SR_DCD);}static void scc_shutdown_port(void *ptr){	struct scc_port *port = ptr;	port->gs.flags &= ~ GS_ACTIVE;	if (port->gs.tty && port->gs.tty->termios->c_cflag & HUPCL) {		scc_setsignals (port, 0, 0);	}}static int scc_set_real_termios (void *ptr){	/* the SCC has char sizes 5,7,6,8 in that order! */	static int chsize_map[4] = { 0, 2, 1, 3 };	unsigned cflag, baud, chsize, channel, brgval = 0;	unsigned long flags;	struct scc_port *port = ptr;	SCC_ACCESS_INIT(port);	if (!port->gs.tty || !port->gs.tty->termios) return 0;	channel = port->channel;	if (channel == CHANNEL_A)		return 0;		/* Settings controlled by boot PROM */	cflag  = port->gs.tty->termios->c_cflag;	baud = port->gs.baud;	chsize = (cflag & CSIZE) >> 4;	if (baud == 0) {		/* speed == 0 -> drop DTR */		save_flags(flags);		cli();		SCCmod(TX_CTRL_REG, ~TCR_DTR, 0);		restore_flags(flags);		return 0;	}	else if ((MACH_IS_MVME16x && (baud < 50 || baud > 38400)) ||		 (MACH_IS_MVME147 && (baud < 50 || baud > 19200)) ||		 (MACH_IS_BVME6000 &&(baud < 50 || baud > 76800))) {		printk("SCC: Bad speed requested, %d\n", baud);		return 0;	}	if (cflag & CLOCAL)		port->gs.flags &= ~ASYNC_CHECK_CD;	else		port->gs.flags |= ASYNC_CHECK_CD;#ifdef CONFIG_MVME147_SCC	if (MACH_IS_MVME147)		brgval = (M147_SCC_PCLK + baud/2) / (16 * 2 * baud) - 2;	else#endif#ifdef CONFIG_MVME162_SCC	if (MACH_IS_MVME16x)		brgval = (MVME_SCC_PCLK + baud/2) / (16 * 2 * baud) - 2;	else#endif#ifdef CONFIG_BVME6000_SCC	if (MACH_IS_BVME6000)		brgval = (BVME_SCC_RTxC + baud/2) / (16 * 2 * baud) - 2;#endif	/* Now we have all parameters and can go to set them: */	save_flags(flags);	cli();	/* receiver's character size and auto-enables */	SCCmod(RX_CTRL_REG, ~(RCR_CHSIZE_MASK|RCR_AUTO_ENAB_MODE),			(chsize_map[chsize] << 6) |			((cflag & CRTSCTS) ? RCR_AUTO_ENAB_MODE : 0));	/* parity and stop bits (both, Tx and Rx), clock mode never changes */	SCCmod (AUX1_CTRL_REG,		~(A1CR_PARITY_MASK | A1CR_MODE_MASK),		((cflag & PARENB		  ? (cflag & PARODD ? A1CR_PARITY_ODD : A1CR_PARITY_EVEN)		  : A1CR_PARITY_NONE)		 | (cflag & CSTOPB ? A1CR_MODE_ASYNC_2 : A1CR_MODE_ASYNC_1)));	/* sender's character size, set DTR for valid baud rate */	SCCmod(TX_CTRL_REG, ~TCR_CHSIZE_MASK, chsize_map[chsize] << 5 | TCR_DTR);	/* clock sources never change */	/* disable BRG before changing the value */	SCCmod(DPLL_CTRL_REG, ~DCR_BRG_ENAB, 0);	/* BRG value */	SCCwrite(TIMER_LOW_REG, brgval & 0xff);	SCCwrite(TIMER_HIGH_REG, (brgval >> 8) & 0xff);	/* BRG enable, and clock source never changes */	SCCmod(DPLL_CTRL_REG, 0xff, DCR_BRG_ENAB);	restore_flags(flags);	return 0;}static int scc_chars_in_buffer (void *ptr){	struct scc_port *port = ptr;	SCC_ACCESS_INIT(port);	return (SCCread (SPCOND_STATUS_REG) & SCSR_ALL_SENT) ? 0  : 1;}static void scc_hungup(void *ptr){	scc_disable_tx_interrupts(ptr);	scc_disable_rx_interrupts(ptr);	MOD_DEC_USE_COUNT;}static void scc_close(void *ptr){	scc_disable_tx_interrupts(ptr);	scc_disable_rx_interrupts(ptr);}/*--------------------------------------------------------------------------- * Internal support functions *--------------------------------------------------------------------------*/static void scc_setsignals(struct scc_port *port, int dtr, int rts){	unsigned long flags;	unsigned char t;	SCC_ACCESS_INIT(port);	save_flags(flags);	t = SCCread(TX_CTRL_REG);	if (dtr >= 0) t = dtr? (t | TCR_DTR): (t & ~TCR_DTR);	if (rts >= 0) t = rts? (t | TCR_RTS): (t & ~TCR_RTS);	SCCwrite(TX_CTRL_REG, t);	restore_flags(flags);}static void scc_send_xchar(struct tty_struct *tty, char ch){	struct scc_port *port = (struct scc_port *)tty->driver_data;	port->x_char = ch;	if (ch)		scc_enable_tx_interrupts(port);}/*--------------------------------------------------------------------------- * Driver entrypoints referenced from above *--------------------------------------------------------------------------*/static int scc_open (struct tty_struct * tty, struct file * filp){	int line = MINOR(tty->device) - SCC_MINOR_BASE;	int retval;	struct scc_port *port = &scc_ports[line];	int i, channel = port->channel;	unsigned long	flags;	SCC_ACCESS_INIT(port);#if defined(CONFIG_MVME162_SCC) || defined(CONFIG_MVME147_SCC)	static const struct {		unsigned reg, val;	} mvme_init_tab[] = {		/* Values for MVME162 and MVME147 */		/* no parity, 1 stop bit, async, 1:16 */		{ AUX1_CTRL_REG, A1CR_PARITY_NONE|A1CR_MODE_ASYNC_1|A1CR_CLKMODE_x16 },		/* parity error is special cond, ints disabled, no DMA */		{ INT_AND_DMA_REG, IDR_PARERR_AS_SPCOND | IDR_RX_INT_DISAB },		/* Rx 8 bits/char, no auto enable, Rx off */		{ RX_CTRL_REG, RCR_CHSIZE_8 },		/* DTR off, Tx 8 bits/char, RTS off, Tx off */		{ TX_CTRL_REG, TCR_CHSIZE_8 },		/* special features off */		{ AUX2_CTRL_REG, 0 },		{ CLK_CTRL_REG, CCR_RXCLK_BRG | CCR_TXCLK_BRG },		{ DPLL_CTRL_REG, DCR_BRG_ENAB | DCR_BRG_USE_PCLK },		/* Start Rx */		{ RX_CTRL_REG, RCR_RX_ENAB | RCR_CHSIZE_8 },		/* Start Tx */		{ TX_CTRL_REG, TCR_TX_ENAB | TCR_RTS | TCR_DTR | TCR_CHSIZE_8 },		/* Ext/Stat ints: DCD only */		{ INT_CTRL_REG, ICR_ENAB_DCD_INT },		/* Reset Ext/Stat ints */		{ COMMAND_REG, CR_EXTSTAT_RESET },		/* ...again */		{ COMMAND_REG, CR_EXTSTAT_RESET },	};#endif#if defined(CONFIG_BVME6000_SCC)	static const struct {		unsigned reg, val;	} bvme_init_tab[] = {		/* Values for BVME6000 */		/* no parity, 1 stop bit, async, 1:16 */		{ AUX1_CTRL_REG, A1CR_PARITY_NONE|A1CR_MODE_ASYNC_1|A1CR_CLKMODE_x16 },		/* parity error is special cond, ints disabled, no DMA */		{ INT_AND_DMA_REG, IDR_PARERR_AS_SPCOND | IDR_RX_INT_DISAB },		/* Rx 8 bits/char, no auto enable, Rx off */		{ RX_CTRL_REG, RCR_CHSIZE_8 },		/* DTR off, Tx 8 bits/char, RTS off, Tx off */		{ TX_CTRL_REG, TCR_CHSIZE_8 },		/* special features off */		{ AUX2_CTRL_REG, 0 },		{ CLK_CTRL_REG, CCR_RTxC_XTAL | CCR_RXCLK_BRG | CCR_TXCLK_BRG },		{ DPLL_CTRL_REG, DCR_BRG_ENAB },		/* Start Rx */		{ RX_CTRL_REG, RCR_RX_ENAB | RCR_CHSIZE_8 },		/* Start Tx */		{ TX_CTRL_REG, TCR_TX_ENAB | TCR_RTS | TCR_DTR | TCR_CHSIZE_8 },		/* Ext/Stat ints: DCD only */		{ INT_CTRL_REG, ICR_ENAB_DCD_INT },		/* Reset Ext/Stat ints */		{ COMMAND_REG, CR_EXTSTAT_RESET },		/* ...again */		{ COMMAND_REG, CR_EXTSTAT_RESET },	};#endif	if (!(port->gs.flags & ASYNC_INITIALIZED)) {		save_flags(flags);		cli();#if defined(CONFIG_MVME147_SCC) || defined(CONFIG_MVME162_SCC)		if (MACH_IS_MVME147 || MACH_IS_MVME16x) {			for (i=0; i<sizeof(mvme_init_tab)/sizeof(*mvme_init_tab); ++i)				SCCwrite(mvme_init_tab[i].reg, mvme_init_tab[i].val);		}#endif#if defined(CONFIG_BVME6000_SCC)		if (MACH_IS_BVME6000) {			for (i=0; i<sizeof(bvme_init_tab)/sizeof(*bvme_init_tab); ++i)				SCCwrite(bvme_init_tab[i].reg, bvme_init_tab[i].val);		}#endif		/* remember status register for detection of DCD and CTS changes */		scc_last_status_reg[channel] = SCCread(STATUS_REG);		port->c_dcd = 0;	/* Prevent initial 1->0 interrupt */		scc_setsignals (port, 1,1);		restore_flags(flags);	}	tty->driver_data = port;	port->gs.tty = tty;	port->gs.count++;	retval = gs_init_port(&port->gs);	if (retval) {		port->gs.count--;		return retval;	}	port->gs.flags |= GS_ACTIVE;	if (port->gs.count == 1) {		MOD_INC_USE_COUNT;	}	retval = block_til_ready(port, filp);	if (retval) {		MOD_DEC_USE_COUNT;		port->gs.count--;		return retval;	}	if ((port->gs.count == 1) && (port->gs.flags & ASYNC_SPLIT_TERMIOS)) {		if (tty->driver.subtype == SERIAL_TYPE_NORMAL)			*tty->termios = port->gs.normal_termios;		else 			*tty->termios = port->gs.callout_termios;		scc_set_real_termios (port);	}	port->gs.session = current->session;	port->gs.pgrp = current->pgrp;	port->c_dcd = scc_get_CD (port);	scc_enable_rx_interrupts(port);	return 0;}static void scc_throttle (struct tty_struct * tty){	struct scc_port *port = (struct scc_port *)tty->driver_data;	unsigned long	flags;	SCC_ACCESS_INIT(port);	if (tty->termios->c_cflag & CRTSCTS) {		save_flags(flags);		cli();		SCCmod(TX_CTRL_REG, ~TCR_RTS, 0);		restore_flags(flags);	}	if (I_IXOFF(tty))		scc_send_xchar(tty, STOP_CHAR(tty));}static void scc_unthrottle (struct tty_struct * tty){	struct scc_port *port = (struct scc_port *)tty->driver_data;	unsigned long	flags;	SCC_ACCESS_INIT(port);	if (tty->termios->c_cflag & CRTSCTS) {		save_flags(flags);		cli();		SCCmod(TX_CTRL_REG, 0xff, TCR_RTS);		restore_flags(flags);	}	if (I_IXOFF(tty))		scc_send_xchar(tty, START_CHAR(tty));}static int scc_ioctl(struct tty_struct *tty, struct file *file,		     unsigned int cmd, unsigned long arg){	return -ENOIOCTLCMD;}static void scc_break_ctl(struct tty_struct *tty, int break_state){	struct scc_port *port = (struct scc_port *)tty->driver_data;	unsigned long	flags;	SCC_ACCESS_INIT(port);	save_flags(flags);	cli();	SCCmod(TX_CTRL_REG, ~TCR_SEND_BREAK, 			break_state ? TCR_SEND_BREAK : 0);	restore_flags(flags);}/*--------------------------------------------------------------------------- * Serial console stuff... *--------------------------------------------------------------------------*/#define scc_delay() do { __asm__ __volatile__ (" nop; nop"); } while (0)static void scc_ch_write (char ch){	volatile char *p = NULL;	#ifdef CONFIG_MVME147_SCC	if (MACH_IS_MVME147)		p = (volatile char *)M147_SCC_A_ADDR;#endif#ifdef CONFIG_MVME162_SCC	if (MACH_IS_MVME16x)		p = (volatile char *)MVME_SCC_A_ADDR;#endif#ifdef CONFIG_BVME6000_SCC	if (MACH_IS_BVME6000)		p = (volatile char *)BVME_SCC_A_ADDR;#endif	do {		scc_delay();	}	while (!(*p & 4));	scc_delay();	*p = 8;	scc_delay();	*p = ch;}/* The console_lock must be held when we get here. */static void scc_console_write (struct console *co, const char *str, unsigned count){	unsigned long	flags;	save_flags(flags);	cli();	while (count--)	{		if (*str == '\n')			scc_ch_write ('\r');		scc_ch_write (*str++);	}	restore_flags(flags);}static int scc_console_wait_key(struct console *co){	unsigned long	flags;	volatile char *p = NULL;	int c;	#ifdef CONFIG_MVME147_SCC	if (MACH_IS_MVME147)		p = (volatile char *)M147_SCC_A_ADDR;#endif#ifdef CONFIG_MVME162_SCC	if (MACH_IS_MVME16x)		p = (volatile char *)MVME_SCC_A_ADDR;#endif#ifdef CONFIG_BVME6000_SCC	if (MACH_IS_BVME6000)		p = (volatile char *)BVME_SCC_A_ADDR;#endif	save_flags(flags);	cli();	/* wait for rx buf filled */	while ((*p & 0x01) == 0)		;	*p = 8;	scc_delay();	c = *p;	restore_flags(flags);	return c;}static kdev_t scc_console_device(struct console *c){	return MKDEV(TTY_MAJOR, SCC_MINOR_BASE + c->index);}static int __init scc_console_setup(struct console *co, char *options){	return 0;}static struct console sercons = {	name:		"ttyS",	write:		scc_console_write,	device:		scc_console_device,	wait_key:	scc_console_wait_key,	setup:		scc_console_setup,	flags:		CON_PRINTBUFFER,	index:		-1,};void __init vme_scc_console_init(void){	if (vme_brdtype == VME_TYPE_MVME147 ||			vme_brdtype == VME_TYPE_MVME162 ||			vme_brdtype == VME_TYPE_MVME172 ||			vme_brdtype == VME_TYPE_BVME4000 ||			vme_brdtype == VME_TYPE_BVME6000)		register_console(&sercons);}

⌨️ 快捷键说明

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