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

📄 uart.c

📁 microwindows移植到S3C44B0的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
	line = MINOR(tty->device) - tty->driver.minor_start;	if ((line < 0) || (line >= NR_PORTS))		return -ENODEV;	retval = get_async_struct(line, &info);	if (retval)		return retval;	if (serial_paranoia_check(info, tty->device, "rs_open"))		return -ENODEV;#ifdef SERIAL_DEBUG_OPEN	printk("rs_open %s%d, count = %d\n", tty->driver.name, info->line,	       info->state->count);#endif	tty->driver_data = info;	info->tty = tty;	/*	 * Start up serial port	 */	retval = startup(info);	if (retval)		return retval;	MOD_INC_USE_COUNT;	retval = block_til_ready(tty, filp, info);	if (retval) {#ifdef SERIAL_DEBUG_OPEN		printk("rs_open returning after block_til_ready with %d\n",		       retval);#endif		MOD_DEC_USE_COUNT;		return retval;	}	if ((info->state->count == 1) &&	    (info->flags & ASYNC_SPLIT_TERMIOS)) {		if (tty->driver.subtype == SERIAL_TYPE_NORMAL)			*tty->termios = info->state->normal_termios;		else 			*tty->termios = info->state->callout_termios;		change_speed(info);	}	info->session = current->session;	info->pgrp = current->pgrp;#ifdef SERIAL_DEBUG_OPEN	printk("rs_open ttys%d successful...", info->line);#endif	return 0;}/* * /proc fs routines.... */static int inline line_info(char *buf, struct serial_state *state){#ifdef notdef	struct async_struct *info = state->info, scr_info;	char	stat_buf[30], control, status;#endif	int	ret;	ret = sprintf(buf, "%d: uart:%s port:%X irq:%d",		      state->line,		      (state->smc_scc_num & NUM_IS_SCC) ? "SCC" : "SMC",		      (unsigned int)(state->port), state->irq);	if (!state->port || (state->type == PORT_UNKNOWN)) {		ret += sprintf(buf+ret, "\n");		return ret;	}#ifdef notdef	/*	 * Figure out the current RS-232 lines	 */	if (!info) {		info = &scr_info;	/* This is just for serial_{in,out} */		info->magic = SERIAL_MAGIC;		info->port = state->port;		info->flags = state->flags;		info->quot = 0;		info->tty = 0;	}	cli();	status = serial_in(info, UART_MSR);	control = info ? info->MCR : serial_in(info, UART_MCR);	sti();		stat_buf[0] = 0;	stat_buf[1] = 0;	if (control & UART_MCR_RTS)		strcat(stat_buf, "|RTS");	if (status & UART_MSR_CTS)		strcat(stat_buf, "|CTS");	if (control & UART_MCR_DTR)		strcat(stat_buf, "|DTR");	if (status & UART_MSR_DSR)		strcat(stat_buf, "|DSR");	if (status & UART_MSR_DCD)		strcat(stat_buf, "|CD");	if (status & UART_MSR_RI)		strcat(stat_buf, "|RI");	if (info->quot) {		ret += sprintf(buf+ret, " baud:%d",			       state->baud_base / info->quot);	}	ret += sprintf(buf+ret, " tx:%d rx:%d",		      state->icount.tx, state->icount.rx);	if (state->icount.frame)		ret += sprintf(buf+ret, " fe:%d", state->icount.frame);		if (state->icount.parity)		ret += sprintf(buf+ret, " pe:%d", state->icount.parity);		if (state->icount.brk)		ret += sprintf(buf+ret, " brk:%d", state->icount.brk);		if (state->icount.overrun)		ret += sprintf(buf+ret, " oe:%d", state->icount.overrun);	/*	 * Last thing is the RS-232 status lines	 */	ret += sprintf(buf+ret, " %s\n", stat_buf+1);#endif	return ret;}int rs_360_read_proc(char *page, char **start, off_t off, int count,		 int *eof, void *data){	int i, len = 0;	off_t	begin = 0;	len += sprintf(page, "serinfo:1.0 driver:%s\n", serial_version);	for (i = 0; i < NR_PORTS && len < 4000; i++) {		len += line_info(page + len, &rs_table[i]);		if (len+begin > off+count)			goto done;		if (len+begin < off) {			begin += len;			len = 0;		}	}	*eof = 1;done:	if (off >= len+begin)		return 0;	*start = page + (begin-off);	return ((count < begin+len-off) ? count : begin+len-off);}/* * --------------------------------------------------------------------- * rs_init() and friends * * rs_init() is called at boot-time to initialize the serial driver. * --------------------------------------------------------------------- *//* * This routine prints out the appropriate serial driver version * number, and identifies which options were configured into this * driver. */static _INLINE_ void show_serial_version(void){ 	printk(KERN_INFO "%s version %s\n", serial_name, serial_version);}/* * The serial console driver used during boot.  Note that these names * clash with those found in "serial.c", so we currently can't support * the 16xxx uarts and these at the same time.  I will fix this to become * an indirect function call from tty_io.c (or something). */#ifdef CONFIG_SERIAL_CONSOLE/* * Print a string to the serial port trying not to disturb any possible * real use of the port... */static void my_console_write(int idx, const char *s,				unsigned count){	struct		serial_state	*ser;	ser_info_t		*info;	unsigned		i;	QUICC_BD		*bdp, *bdbase;	volatile struct smc_uart_pram	*up;	volatile	u_char		*cp;	ser = rs_table + idx;	/* If the port has been initialized for general use, we have	 * to use the buffer descriptors allocated there.  Otherwise,	 * we simply use the single buffer allocated.	 */	if ((info = (ser_info_t *)ser->info) != NULL) {		bdp = info->tx_cur;		bdbase = info->tx_bd_base;	}	else {		/* Pointer to UART in parameter ram.		*/		/* up = (smc_uart_t *)&cpmp->cp_dparam[ser->port]; */		up = &pquicc->pram[ser->port].scc.pothers.idma_smc.psmc.u;		/* Get the address of the host memory buffer.		 */		bdp = bdbase = (QUICC_BD *)((uint)pquicc + (uint)up->tbase);	}	/*	 * We need to gracefully shut down the transmitter, disable	 * interrupts, then send our bytes out.	 */	/*	 * Now, do each character.  This is not as bad as it looks	 * since this is a holding FIFO and not a transmitting FIFO.	 * We could add the complexity of filling the entire transmit	 * buffer, but we would just wait longer between accesses......	 */	for (i = 0; i < count; i++, s++) {		/* Wait for transmitter fifo to empty.		 * Ready indicates output is ready, and xmt is doing		 * that, not that it is ready for us to send.		 */		while (bdp->status & BD_SC_READY);		/* Send the character out.		 */		cp = bdp->buf;		*cp = *s;				bdp->length = 1;		bdp->status |= BD_SC_READY;		if (bdp->status & BD_SC_WRAP)			bdp = bdbase;		else			bdp++;		/* if a LF, also do CR... */		if (*s == 10) {			while (bdp->status & BD_SC_READY);			/* cp = __va(bdp->buf); */			cp = bdp->buf;			*cp = 13;			bdp->length = 1;			bdp->status |= BD_SC_READY;			if (bdp->status & BD_SC_WRAP) {				bdp = bdbase;			}			else {				bdp++;			}		}	}	/*	 * Finally, Wait for transmitter & holding register to empty	 *  and restore the IER	 */	while (bdp->status & BD_SC_READY);	if (info)		info->tx_cur = (QUICC_BD *)bdp;}static void serial_console_write(struct console *c, const char *s,				unsigned count){#ifdef CONFIG_KGDB	/* Try to let stub handle output. Returns true if it did. */ 	if (kgdb_output_string(s, count))		return;#endif	my_console_write(c->index, s, count);}/*void console_print_68360(const char *p){	const char *cp = p;	int i;	for (i=0;cp[i]!=0;i++);	serial_console_write (p, i);	//Comment this if you want to have a strict interrupt-driven output	//rs_fair_output();	return;}*/#ifdef CONFIG_XMONintxmon_360_write(const char *s, unsigned count){	my_console_write(0, s, count);	return(count);}#endif#ifdef CONFIG_KGDBvoidputDebugChar(char ch){	my_console_write(0, &ch, 1);}#endif/* * Receive character from the serial port.  This only works well * before the port is initialized for real use. */static int my_console_wait_key(int idx, int xmon, char *obuf){	struct serial_state		*ser;	u_char			c, *cp;	ser_info_t		*info;	QUICC_BD		*bdp;	volatile struct smc_uart_pram	*up;	int				i;	ser = rs_table + idx;	/* Get the address of the host memory buffer.	 * If the port has been initialized for general use, we must	 * use information from the port structure.	 */	if ((info = (ser_info_t *)ser->info))		bdp = info->rx_cur;	else		/* bdp = (QUICC_BD *)&cpmp->cp_dpmem[up->smc_rbase]; */		bdp = (QUICC_BD *)((uint)pquicc + (uint)up->tbase);	/* Pointer to UART in parameter ram.	 */	/* up = (smc_uart_t *)&cpmp->cp_dparam[ser->port]; */	up = &pquicc->pram[info->state->port].scc.pothers.idma_smc.psmc.u;	/*	 * We need to gracefully shut down the receiver, disable	 * interrupts, then read the input.	 * XMON just wants a poll.  If no character, return -1, else	 * return the character.	 */	if (!xmon) {		while (bdp->status & BD_SC_EMPTY);	}	else {		if (bdp->status & BD_SC_EMPTY)			return -1;	}	cp = (char *)bdp->buf;	if (obuf) {		i = c = bdp->length;		while (i-- > 0)			*obuf++ = *cp++;	}	else {		c = *cp;	}	bdp->status |= BD_SC_EMPTY;	if (info) {		if (bdp->status & BD_SC_WRAP) {			bdp = info->rx_bd_base;		}		else {			bdp++;		}		info->rx_cur = (QUICC_BD *)bdp;	}	return((int)c);}static int serial_console_wait_key(struct console *co){	return(my_console_wait_key(co->index, 0, NULL));}#ifdef CONFIG_XMONintxmon_360_read_poll(void){	return(my_console_wait_key(0, 1, NULL));}intxmon_360_read_char(void){	return(my_console_wait_key(0, 0, NULL));}#endif#ifdef CONFIG_KGDBstatic char kgdb_buf[RX_BUF_SIZE], *kgdp;static int kgdb_chars;unsigned chargetDebugChar(void){	if (kgdb_chars <= 0) {		kgdb_chars = my_console_wait_key(0, 0, kgdb_buf);		kgdp = kgdb_buf;	}	kgdb_chars--;	return(*kgdp++);}void kgdb_interruptible(int state){}void kgdb_map_scc(void){	struct		serial_state *ser;	uint		mem_addr;	volatile	QUICC_BD		*bdp;	volatile	smc_uart_t	*up;	cpmp = (cpm360_t *)&(((immap_t *)IMAP_ADDR)->im_cpm);	/* To avoid data cache CPM DMA coherency problems, allocate a	 * buffer in the CPM DPRAM.  This will work until the CPM and	 * serial ports are initialized.  At that time a memory buffer	 * will be allocated.	 * The port is already initialized from the boot procedure, all	 * we do here is give it a different buffer and make it a FIFO.	 */	ser = rs_table;	/* Right now, assume we are using SMCs.	*/	up = (smc_uart_t *)&cpmp->cp_dparam[ser->port];	/* Allocate space for an input FIFO, plus a few bytes for output.	 * Allocate bytes to maintain word alignment.	 */	mem_addr = (uint)(&cpmp->cp_dpmem[0x1000]);	/* Set the physical address of the host memory buffers in	 * the buffer descriptors.	 */	bdp = (QUICC_BD *)&cpmp->cp_dpmem[up->smc_rbase];	bdp->buf = mem_addr;	bdp = (QUICC_BD *)&cpmp->cp_dpmem[up->smc_tbase];	bdp->buf = mem_addr+RX_BUF_SIZE;	up->smc_mrblr = RX_BUF_SIZE;		/* receive buffer length */	up->smc_maxidl = RX_BUF_SIZE;}#endifstatic kdev_t serial_console_device(struct console *c){	return MKDEV(TTY_MAJOR, 64 + c->index);}struct console sercons = { 	name:		"ttyS", 	write:		serial_console_write, 	device:		serial_console_device, 	wait_key:	serial_console_wait_key, 	setup:		serial_console_setup, 	flags:		CON_PRINTBUFFER, 	index:		CONFIG_SERIAL_CONSOLE_PORT, };/* *	Register console. */long console_360_init(long kmem_start, long kmem_end){	register_console(&sercons);	/*register_console (console_print_68360); - 2.0.38 only required a write      function pointer. */	return kmem_start;}#endif/* Index in baud rate table of the default console baud rate.*/static	int	baud_idx;/* int _

⌨️ 快捷键说明

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