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

📄 68360serial.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
 * 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 struct tty_struct *serial_console_device(struct console *c, int *index){	*index = c->index;	return serial_driver;}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;static const struct tty_operations rs_360_ops = {	.owner = THIS_MODULE,	.open = rs_360_open,	.close = rs_360_close,	.write = rs_360_write,	.put_char = rs_360_put_char,	.write_room = rs_360_write_room,	.chars_in_buffer = rs_360_chars_in_buffer,	.flush_buffer = rs_360_flush_buffer,	.ioctl = rs_360_ioctl,	.throttle = rs_360_throttle,	.unthrottle = rs_360_unthrottle,	/* .send_xchar = rs_360_send_xchar, */	.set_termios = rs_360_set_termios,	.stop = rs_360_stop,	.start = rs_360_start,	.hangup = rs_360_hangup,	/* .wait_until_sent = rs_360_wait_until_sent, */	/* .read_proc = rs_360_read_proc, */	.tiocmget = rs_360_tiocmget,	.tiocmset = rs_360_tiocmset,};static int __init rs_360_init(void){	struct serial_state * state;	ser_info_t	*info;	void       *mem_addr;	uint 		dp_addr, iobits;	int		    i, j, idx;	ushort		chan;	QUICC_BD	*bdp;	volatile	QUICC		*cp;	volatile	struct smc_regs	*sp;	volatile	struct smc_uart_pram	*up;	volatile	struct scc_regs	*scp;	volatile	struct uart_pram	*sup;	/* volatile	immap_t		*immap; */		serial_driver = alloc_tty_driver(NR_PORTS);	if (!serial_driver)		return -1;	show_serial_version();	serial_driver->name = "ttyS";	serial_driver->major = TTY_MAJOR;	serial_driver->minor_start = 64;	serial_driver->type = TTY_DRIVER_TYPE_SERIAL;	serial_driver->subtype = SERIAL_TYPE_NORMAL;	serial_driver->init_termios = tty_std_termios;	serial_driver->init_termios.c_cflag =		baud_idx | CS8 | CREAD | HUPCL | CLOCAL;	serial_driver->flags = TTY_DRIVER_REAL_RAW;	tty_set_operations(serial_driver, &rs_360_ops);		if (tty_register_driver(serial_driver))		panic("Couldn't register serial driver\n");	cp = pquicc;	/* Get pointer to Communication Processor */	/* immap = (immap_t *)IMAP_ADDR; */	/* and to internal registers */	/* Configure SCC2, SCC3, and SCC4 instead of port A parallel I/O.	 */	/* The "standard" configuration through the 860.	*//* 	immap->im_ioport.iop_papar |= 0x00fc; *//* 	immap->im_ioport.iop_padir &= ~0x00fc; *//* 	immap->im_ioport.iop_paodr &= ~0x00fc; */	cp->pio_papar |= 0x00fc;	cp->pio_padir &= ~0x00fc;	/* cp->pio_paodr &= ~0x00fc; */	/* Since we don't yet do modem control, connect the port C pins	 * as general purpose I/O.  This will assert CTS and CD for the	 * SCC ports.	 */	/* FIXME: see 360um p.7-365 and 860um p.34-12 	 * I can't make sense of these bits - mleslie*//* 	immap->im_ioport.iop_pcdir |= 0x03c6; *//* 	immap->im_ioport.iop_pcpar &= ~0x03c6; *//* 	cp->pio_pcdir |= 0x03c6; *//* 	cp->pio_pcpar &= ~0x03c6; */	/* Connect SCC2 and SCC3 to NMSI.  Connect BRG3 to SCC2 and	 * BRG4 to SCC3.	 */	cp->si_sicr &= ~0x00ffff00;	cp->si_sicr |=  0x001b1200;#ifdef CONFIG_PP04	/* Frequentis PP04 forced to RS-232 until we know better.	 * Port C 12 and 13 low enables RS-232 on SCC3 and SCC4.	 */	immap->im_ioport.iop_pcdir |= 0x000c;	immap->im_ioport.iop_pcpar &= ~0x000c;	immap->im_ioport.iop_pcdat &= ~0x000c;	/* This enables the TX driver.	*/	cp->cp_pbpar &= ~0x6000;	cp->cp_pbdat &= ~0x6000;#endif	for (i = 0, state = rs_table; i < NR_PORTS; i++,state++) {		state->magic = SSTATE_MAGIC;		state->line = i;		state->type = PORT_UNKNOWN;		state->custom_divisor = 0;		state->close_delay = 5*HZ/10;		state->closing_wait = 30*HZ;		state->icount.cts = state->icount.dsr = 			state->icount.rng = state->icount.dcd = 0;		state->icount.rx = state->icount.tx = 0;		state->icount.frame = state->icount.parity = 0;		state->icount.overrun = state->icount.brk = 0;		printk(KERN_INFO "ttyS%d at irq 0x%02x is an %s\n",		       i, (unsigned int)(state->irq),		       (state->smc_scc_num & NUM_IS_SCC) ? "SCC" : "SMC");#ifdef CONFIG_SERIAL_CONSOLE		/* If we just printed the message on the console port, and		 * we are about to initialize it for general use, we have		 * to wait a couple of character times for the CR/NL to		 * make it out of the transmit buffer.		 */		if (i == CONFIG_SERIAL_CONSOLE_PORT)			mdelay(8);/* 		idx = PORT_NUM(info->state->smc_scc_num); *//* 		if (info->state->smc_scc_num & NUM_IS_SCC) *//* 			chan = scc_chan_map[idx]; *//* 		else *//* 			chan = smc_chan_map[idx]; *//* 		cp->cp_cr = mk_cr_cmd(chan, CPM_CR_STOP_TX) | CPM_CR_FLG; *//* 		while (cp->cp_cr & CPM_CR_FLG); */#endif		/* info = kmalloc(sizeof(ser_info_t), GFP_KERNEL); */		info = &quicc_ser_info[i];		if (info) {			memset (info, 0, sizeof(ser_info_t));			info->magic = SERIAL_MAGIC;			info->line = i;			info->flags = state->flags;			INIT_WORK(&info->tqueue, do_softint, info);			INIT_WORK(&info->tqueue_hangup, do_serial_hangup, info);			init_waitqueue_head(&info->open_wait);			init_waitqueue_head(&info->close_wait);			info->state = state;			state->info = (struct async_struct *)info;			/* We need to allocate a transmit and receive buffer			 * descriptors from dual port ram, and a character			 * buffer area from host mem.			 */			dp_addr = m360_cpm_dpalloc(sizeof(QUICC_BD) * RX_NUM_FIFO);			/* Allocate space for FIFOs in the host memory.			 *  (for now this is from a static array of buffers :(			 */			/* mem_addr = m360_cpm_hostalloc(RX_NUM_FIFO * R

⌨️ 快捷键说明

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