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

📄 serial_atmel.c

📁 这是一个SIGMA方案的PMP播放器的UCLINUX程序,可播放DVD,VCD,CD MP3...有很好的参考价值.
💻 C
📖 第 1 页 / 共 4 页
字号:
		if (info->flags & S_NORMAL_ACTIVE)			return -EBUSY;		if ((info->flags & S_CALLOUT_ACTIVE) &&			(info->flags & S_SESSION_LOCKOUT) &&			(info->session != current->session)) return -EBUSY;		if ((info->flags & S_CALLOUT_ACTIVE) &&			(info->flags & S_PGRP_LOCKOUT) &&			(info->pgrp != current->pgrp)) return -EBUSY;		info->flags |= S_CALLOUT_ACTIVE;		return 0;	}	/*	 * If non-blocking mode is set, or the port is not enabled,	 * then make the check up front and then exit.	 */	if ((filp->f_flags & O_NONBLOCK) || (tty->flags & (1 << TTY_IO_ERROR))) {		if (info->flags & S_CALLOUT_ACTIVE)			return -EBUSY;		info->flags |= S_NORMAL_ACTIVE;		return 0;	}	if (info->flags & S_CALLOUT_ACTIVE) {		if (info->normal_termios.c_cflag & CLOCAL)			do_clocal = 1;	} else {		if (tty->termios->c_cflag & CLOCAL)			do_clocal = 1;	}	/*	 * Block waiting for the carrier detect and the line to become	 * free (i.e., not in use by the callout).  While we are in	 * this loop, info->count is dropped by one, so that	 * rs_close() knows when to free things.  We restore it upon	 * exit, either normal or abnormal.	 */	retval = 0;	add_wait_queue(&info->open_wait, &wait);#ifdef SERIAL_DEBUG_OPEN	printk("block_til_ready before block: ttyS%d, count = %d\n",		   info->line, info->count);#endif	info->count--;	info->blocked_open++;	while (1) {#ifdef US_RTS		save_flags(flags);		cli();		if (!(info->flags & S_CALLOUT_ACTIVE))			atmel_rtsdtr(info, 1);		restore_flags(flags);#endif		current->state = TASK_INTERRUPTIBLE;		if (tty_hung_up_p(filp) || !(info->flags & S_INITIALIZED)) {#ifdef SERIAL_DO_RESTART			if (info->flags & S_HUP_NOTIFY)				retval = -EAGAIN;			else				retval = -ERESTARTSYS;#else			retval = -EAGAIN;#endif			break;		}		if (!(info->flags & S_CALLOUT_ACTIVE) &&			!(info->flags & S_CLOSING) && do_clocal)			break;		if (signal_pending(current)) {			retval = -ERESTARTSYS;			break;		}#ifdef SERIAL_DEBUG_OPEN		printk("block_til_ready blocking: ttyS%d, count = %d\n",			   info->line, info->count);#endif		schedule();	}	current->state = TASK_RUNNING;	remove_wait_queue(&info->open_wait, &wait);	if (!tty_hung_up_p(filp))		info->count++;	info->blocked_open--;#ifdef SERIAL_DEBUG_OPEN	printk("block_til_ready after blocking: ttyS%d, count = %d\n",		   info->line, info->count);#endif	if (retval)		return retval;	info->flags |= S_NORMAL_ACTIVE;	if (!info->use_ints) {		serialpoll.data = (void *) info;		queue_task(&serialpoll, &tq_timer);	}	return 0;}/* * This routine is called whenever a serial port is opened.  It * enables interrupts for a serial port, linking in its S structure into * the IRQ chain.   It also performs the serial-specific * initialization for the tty structure. */int rs_open(struct tty_struct *tty, struct file *filp){	struct atmel_serial *info;	int retval, line;	line = MINOR(tty->device) - tty->driver.minor_start;	// check if line is sane	if (line < 0 || line >= AT91_USART_CNT)		return -ENODEV;	info = &atmel_info[line];#if 0	/* Is the kgdb running over this line? */	if (info->kgdb_channel)		return -ENODEV;#endif	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->count);#endif	info->count++;	tty->driver_data = info;	info->tty = tty;	/*	 * Start up serial port	 */	set_ints_mode(1, info);		retval = startup(info);	if (retval)		return retval;	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		return retval;	}	if ((info->count == 1) && (info->flags & S_SPLIT_TERMIOS)) {		if (tty->driver.subtype == SERIAL_TYPE_NORMAL)			*tty->termios = info->normal_termios;		else			*tty->termios = info->callout_termios;		change_speed(info);	}	info->session = current->session;	info->pgrp = current->pgrp;#ifdef SERIAL_DEBUG_OPEN	printk("rs_open ttyS%d successful...\n", info->line);#endif	return 0;}#if 0static inline void rs_cons_check(struct atmel_serial *ss, int channel){	int i, o, io;	static consout_registered = 0;	static msg_printed = 0;	i = o = io = 0;	/* Is this one of the serial console lines? */	if ((atmel_cons_chanout != channel) && (atmel_cons_chanin != channel))		return;	atmel_conschan = ss->atmel_channel;	atmel_consinfo = ss;	/* Register the console output putchar, if necessary */	if ((atmel_cons_chanout == channel)) {		o = 1;		/* double whee.. */		if (!consout_registered) {			register_console(atmel_console_print);			consout_registered = 1;		}	}	/* If this is console input, we handle the break received	 * status interrupt on this line to mean prom_halt().	 */	if (atmel_cons_chanin == channel) {		ss->break_abort = 1;		i = 1;	}	if (o && i)		io = 1;	if (ss->baud != 9600)		panic("Console baud rate weirdness");	/* Set flag variable for this port so that it cannot be	 * opened for other uses by accident.	 */	ss->is_cons = 1;	if (io) {		if (!msg_printed) {			printk("zs%d: console I/O\n", ((channel >> 1) & 1));			msg_printed = 1;		}	} else {		printk("zs%d: console %s\n", ((channel >> 1) & 1),			   (i == 1 ? "input" : (o == 1 ? "output" : "WEIRD")));	}}#endifstatic struct irqaction irq_usart0 =	{ rs_interrupta, 0, 0, "usart0", NULL, NULL };static struct irqaction irq_usart1 =	{ rs_interruptb, 0, 0, "usart1", NULL, NULL };extern int setup_arm_irq(int, struct irqaction *);static void interrupts_init(void){	setup_arm_irq(IRQ_USART0, &irq_usart0);	setup_arm_irq(IRQ_USART1, &irq_usart1);}static void show_serial_version(void){	printk("Atmel USART driver version 0.99\n");}/* rs_init inits the driver */static int  __init rs_atmel_init(void){	int flags, i;	struct atmel_serial *info;	/* initialise PIO for serial port */	HW_AT91_USART_INIT 	/* Setup base handler, and timer table. */	init_bh(SERIAL_BH, do_serial_bh);	//xxx timer_table[RS_TIMER].fn = rs_timer;	//xxx timer_table[RS_TIMER].expires = 0;	// FIXME - do this right	rx_buf_table[0] = rx_buf1;	rx_buf_table[1] = rx_buf2;		show_serial_version();	/* Initialize the tty_driver structure */	// set the tty_struct pointers to NULL to let the layer	// above allocate the structs.	for (i=0; i < AT91_USART_CNT; i++)		serial_table[i] = NULL;			memset(&serial_driver, 0, sizeof(struct tty_driver));	serial_driver.magic = TTY_DRIVER_MAGIC;	serial_driver.name = "ttyS";	serial_driver.major = TTY_MAJOR;	serial_driver.minor_start = 64;#ifdef CONFIG_CONSOLE_ON_SC28L91		serial_driver.minor_start += 1;#endif	serial_driver.num = 2;	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 =		B9600 | CS8 | CREAD | HUPCL | CLOCAL;	serial_driver.flags = TTY_DRIVER_REAL_RAW;	serial_driver.refcount = &serial_refcount;	serial_driver.table = serial_table;	serial_driver.termios = serial_termios;	serial_driver.termios_locked = serial_termios_locked;	serial_driver.open = rs_open;	serial_driver.close = rs_close;	serial_driver.write = rs_write;	serial_driver.flush_chars = rs_flush_chars;	serial_driver.write_room = rs_write_room;	serial_driver.chars_in_buffer = rs_chars_in_buffer;	serial_driver.flush_buffer = rs_flush_buffer;	serial_driver.ioctl = rs_ioctl;	serial_driver.throttle = rs_throttle;	serial_driver.unthrottle = rs_unthrottle;	serial_driver.set_termios = rs_set_termios;	serial_driver.stop = rs_stop;	serial_driver.start = rs_start;	serial_driver.hangup = rs_hangup;	serial_driver.set_ldisc = rs_set_ldisc;	/*	 * The callout device is just like normal device except for	 * major number and the subtype code.	 */	callout_driver = serial_driver;	callout_driver.name = "cua";	callout_driver.major = TTYAUX_MAJOR;	callout_driver.subtype = SERIAL_TYPE_CALLOUT;	if (tty_register_driver(&serial_driver))		panic("Couldn't register serial driver\n");	if (tty_register_driver(&callout_driver))		panic("Couldn't register callout driver\n");	save_flags(flags);	cli();	for (i = 0; i < 2; i++) {		info = &atmel_info[i];		info->magic = SERIAL_MAGIC;		info->usart = usarts[i];		info->tty = 0;		info->irqmask = (i) ? (1<<IRQ_USART1) : (1<<IRQ_USART0);		info->irq = (i) ? IRQ_USART1 : IRQ_USART0;#ifdef CONFIG_SWAP_ATMEL_PORTS		info->port = (i) ? 2 : 1;		info->line = !i;#ifdef CONFIG_CONSOLE_ON_ATMEL		info->is_cons = i;#else		info->is_cons = 0;#endif	#else		info->port = (i) ? 1 : 2;		info->line = i;#ifdef CONFIG_CONSOLE_ON_ATMEL		info->is_cons = !i;#else		info->is_cons = 0;#endif	#endif#ifdef CONFIG_CONSOLE_ON_SC28L91		info->line += 1;#endif		set_ints_mode(0, info);		info->custom_divisor = 16;		info->close_delay = 50;		info->closing_wait = 3000;		info->cts_state = 1;		info->x_char = 0;		info->event = 0;		info->count = 0;		info->blocked_open = 0;		info->tqueue.routine = do_softint;		info->tqueue.data = info;		info->tqueue_hangup.routine = do_serial_hangup;		info->tqueue_hangup.data = info;		info->callout_termios = callout_driver.init_termios;		info->normal_termios = serial_driver.init_termios;		init_waitqueue_head(&info->open_wait);		init_waitqueue_head(&info->close_wait);		info->rx_buf = rx_buf_table[i];		printk("%s%d at 0x%p (irq = %d)", serial_driver.name, info->line,			   info->usart, info->irq);		printk(" is a builtin Atmel APB USART\n");	}		// FIXME	info->usart->cr = 0x1ac; // reset, disable	info->usart->idr = 0xffffffff; // disable all interrupts	info->usart->tcr = 0; // stop transmit	info->usart->rcr = 0; // stop receive		interrupts_init();	restore_flags(flags);	// hack to do polling	serialpoll.routine = serpoll;	serialpoll.data = 0;	return 0;}module_init(rs_atmel_init);#if 0/* * register_serial and unregister_serial allows for serial ports to be * configured at run-time, to support PCMCIA modems. *//* SPARC: Unused at this time, just here to make things link. */static int register_serial(struct serial_struct *req){	return -1;}static void unregister_serial(int line){	return;}static void dbg_putc(int ch){	static char tmp[2];#define US_TPR  (0x38) /* Transmit Pointer Register */#define US_TCR  (0x3C) /* Transmit Counter Register */	tmp[0] = ch;	outl_t((unsigned long) tmp, (USART0_BASE + US_TPR) );	outl_t(1, (USART0_BASE + US_TCR) );	while (inl_t((USART0_BASE + US_TCR) )) {	}}static void dbg_print(const char *str){	const char *p;	for (p = str; *p; p++) {		if (*p == '\n') {			dbg_putc('\r');		}		dbg_putc(*p);	}}static void dbg_printk(const char *fmt, ...){	char tmp[256];	va_list args;	va_start(args, fmt);	vsprintf(tmp, fmt, args);	va_end(args);	dbg_print(tmp);}static void rs_atmel_print(const char *str){	dbg_printk(str);}static void dump_a(unsigned long a, unsigned int s){	unsigned long q;	for (q = 0; q < s; q++) {		if (q % 16 == 0) {			dbg_printk("%08X: ", q + a);		}		if (q % 16 == 7) {			dbg_printk("%02X-", *(unsigned char *) (q + a));		} else {			dbg_printk("%02X ", *(unsigned char *) (q + a));		}		if (q % 16 == 15) {			dbg_printk(" :\n");		}	}	if (q % 16) {		dbg_printk(" :\n");	}}#endifstatic kdev_t atmel_console_device(struct console *c){	return MKDEV(TTY_MAJOR, 64 + c->index);}int atmel_console_setup(void){  HW_AT91_USART_INIT  return 0;}void atmel_console_write (struct console *co, const char *str,			   unsigned int count){	char c;	struct atmel_serial *info;#ifdef CONFIG_SWAP_ATMEL_PORTS	info = &atmel_info[1];#else	info = &atmel_info[0];#endif	if (!atmel_console_initialized) {		init_console(info);		uart_init(info);		info->baud = 9600;		tx_stop(info->usart);		rx_stop(info->usart);		uart_speed(info, 0xffff);		tx_start(info->usart, info->use_ints);		rx_start(info->usart, info->use_ints);	}    	while (count--) {        	if (*str == '\n')           		rs_put_char(info,'\r');        	rs_put_char(info, *str++ );    	}}static struct console atmel_driver = {	name:		"ttyS",	write:		atmel_console_write,	read:		NULL,	device:		atmel_console_device,	wait_key:	NULL,	unblank:	NULL,	setup:		atmel_console_setup,	flags:		CON_PRINTBUFFER,	index:		-1,	cflag:		0,	next:		NULL};void atmel_console_init(void){	register_console(&atmel_driver);}

⌨️ 快捷键说明

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