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

📄 68328serial.c

📁 这是一个SIGMA方案的PMP播放器的UCLINUX程序,可播放DVD,VCD,CD MP3...有很好的参考价值.
💻 C
📖 第 1 页 / 共 3 页
字号:
	m68328_uart *uart = &uart_addr[info->line];	unsigned long	flags;	uart->ustcnt = 0; /* All off! */	if (!(info->flags & S_INITIALIZED))		return;	save_flags(flags); cli(); /* Disable interrupts */		if (info->xmit_buf) {		free_page((unsigned long) info->xmit_buf);		info->xmit_buf = 0;	}	if (info->tty)		set_bit(TTY_IO_ERROR, &info->tty->flags);		info->flags &= ~S_INITIALIZED;	restore_flags(flags);}struct {	int divisor, prescale;}#ifndef CONFIG_M68VZ328 hw_baud_table[18] = {	{0,0}, /* 0 */	{0,0}, /* 50 */	{0,0}, /* 75 */	{0,0}, /* 110 */	{0,0}, /* 134 */	{0,0}, /* 150 */	{0,0}, /* 200 */	{7,0x26}, /* 300 */	{6,0x26}, /* 600 */	{5,0x26}, /* 1200 */	{0,0}, /* 1800 */	{4,0x26}, /* 2400 */	{3,0x26}, /* 4800 */	{2,0x26}, /* 9600 */	{1,0x26}, /* 19200 */	{0,0x26}, /* 38400 */	{1,0x38}, /* 57600 */	{0,0x38}, /* 115200 */};#else hw_baud_table[18] = {                 {0,0}, /* 0 */                 {0,0}, /* 50 */                 {0,0}, /* 75 */                 {0,0}, /* 110 */                 {0,0}, /* 134 */                 {0,0}, /* 150 */                 {0,0}, /* 200 */                 {0,0}, /* 300 */                 {7,0x26}, /* 600 */                 {6,0x26}, /* 1200 */                 {0,0}, /* 1800 */                 {5,0x26}, /* 2400 */                 {4,0x26}, /* 4800 */                 {3,0x26}, /* 9600 */                 {2,0x26}, /* 19200 */                 {1,0x26}, /* 38400 */                 {0,0x26}, /* 57600 */                 {1,0x38}, /* 115200 */}; #endif/* rate = 1036800 / ((65 - prescale) * (1<<divider)) *//* * This routine is called to set the UART divisor registers to match * the specified baud rate for a serial port. */static void change_speed(struct m68k_serial *info){	m68328_uart *uart = &uart_addr[info->line];	unsigned short port;	unsigned short ustcnt;	unsigned cflag;	int	i;	if (!info->tty || !info->tty->termios)		return;	cflag = info->tty->termios->c_cflag;	if (!(port = info->port))		return;	ustcnt = uart->ustcnt;	uart->ustcnt = ustcnt & ~USTCNT_TXEN;	i = cflag & CBAUD;        if (i & CBAUDEX) {                i = (i & ~CBAUDEX) + B38400;        }	info->baud = baud_table[i];	uart->ubaud = PUT_FIELD(UBAUD_DIVIDE,    hw_baud_table[i].divisor) | 		PUT_FIELD(UBAUD_PRESCALER, hw_baud_table[i].prescale);	ustcnt &= ~(USTCNT_PARITYEN | USTCNT_ODD_EVEN | USTCNT_STOP | USTCNT_8_7);		if ((cflag & CSIZE) == CS8)		ustcnt |= USTCNT_8_7;			if (cflag & CSTOPB)		ustcnt |= USTCNT_STOP;	if (cflag & PARENB)		ustcnt |= USTCNT_PARITYEN;	if (cflag & PARODD)		ustcnt |= USTCNT_ODD_EVEN;	#ifdef CONFIG_68328_SERIAL_RTS_CTS	if (cflag & CRTSCTS) {		uart->utx.w &= ~ UTX_NOCTS;	} else {		uart->utx.w |= UTX_NOCTS;	}#endif	ustcnt |= USTCNT_TXEN;		uart->ustcnt = ustcnt;	return;}/* * Fair output driver allows a process to speak. */static void rs_fair_output(void){	int left;		/* Output no more than that */	unsigned long flags;	struct m68k_serial *info = &m68k_soft[0];	char c;	if (info == 0) return;	if (info->xmit_buf == 0) return;	save_flags(flags);  cli();	left = info->xmit_cnt;	while (left != 0) {		c = info->xmit_buf[info->xmit_tail];		info->xmit_tail = (info->xmit_tail+1) & (SERIAL_XMIT_SIZE-1);		info->xmit_cnt--;		restore_flags(flags);		rs_put_char(c);		save_flags(flags);  cli();		left = MIN(info->xmit_cnt, left-1);	}	/* Last character is being transmitted now (hopefully). */	udelay(5);	restore_flags(flags);	return;}/* * m68k_console_print is registered for printk. */void console_print_68328(const char *p){	char c;		while((c=*(p++)) != 0) {		if(c == '\n')			rs_put_char('\r');		rs_put_char(c);	}	/* Comment this if you want to have a strict interrupt-driven output */	rs_fair_output();	return;}static void rs_set_ldisc(struct tty_struct *tty){	struct m68k_serial *info = (struct m68k_serial *)tty->driver_data;	if (serial_paranoia_check(info, tty->device, "rs_set_ldisc"))		return;	info->is_cons = (tty->termios->c_line == N_TTY);		printk("ttyS%d console mode %s\n", info->line, info->is_cons ? "on" : "off");}static void rs_flush_chars(struct tty_struct *tty){	struct m68k_serial *info = (struct m68k_serial *)tty->driver_data;	m68328_uart *uart = &uart_addr[info->line];	unsigned long flags;	if (serial_paranoia_check(info, tty->device, "rs_flush_chars"))		return;#ifndef USE_INTS	for(;;) {#endif	if (info->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped ||	    !info->xmit_buf)		return;	/* Enable transmitter */	save_flags(flags); cli();#ifdef USE_INTS	uart->ustcnt |= USTCNT_TXEN | USTCNT_TX_INTR_MASK;#else	uart->ustcnt |= USTCNT_TXEN;#endif#ifdef USE_INTS	if (uart->utx.w & UTX_TX_AVAIL) {#else	if (1) {#endif		/* Send char */		uart->utx.b.txdata = info->xmit_buf[info->xmit_tail++];		info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE-1);		info->xmit_cnt--;	}#ifndef USE_INTS	while (!(uart->utx.w & UTX_TX_AVAIL)) udelay(5);	}#endif	restore_flags(flags);}extern void console_printn(const char * b, int count);static int rs_write(struct tty_struct * tty, int from_user,		    const unsigned char *buf, int count){	int	c, total = 0;	struct m68k_serial *info = (struct m68k_serial *)tty->driver_data;	m68328_uart *uart = &uart_addr[info->line];	unsigned long flags;	if (serial_paranoia_check(info, tty->device, "rs_write"))		return 0;	if (!tty || !info->xmit_buf)		return 0;	save_flags(flags);	while (1) {		cli();				c = MIN(count, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,				   SERIAL_XMIT_SIZE - info->xmit_head));		if (c <= 0)			break;		if (from_user) {			down(&tmp_buf_sem);			copy_from_user(tmp_buf, buf, c);			c = MIN(c, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,				       SERIAL_XMIT_SIZE - info->xmit_head));			memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c);			up(&tmp_buf_sem);		} else			memcpy(info->xmit_buf + info->xmit_head, buf, c);		info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1);		info->xmit_cnt += c;		restore_flags(flags);		buf += c;		count -= c;		total += c;	}	if (info->xmit_cnt && !tty->stopped && !tty->hw_stopped) {		/* Enable transmitter */		cli();		#ifndef USE_INTS		while(info->xmit_cnt) {#endif		uart->ustcnt |= USTCNT_TXEN;#ifdef USE_INTS		uart->ustcnt |= USTCNT_TX_INTR_MASK;#else		while (!(uart->utx.w & UTX_TX_AVAIL)) udelay(5);#endif		if (uart->utx.w & UTX_TX_AVAIL) {			uart->utx.b.txdata = info->xmit_buf[info->xmit_tail++];			info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE-1);			info->xmit_cnt--;		}#ifndef USE_INTS		}#endif		restore_flags(flags);	}	restore_flags(flags);	return total;}static int rs_write_room(struct tty_struct *tty){	struct m68k_serial *info = (struct m68k_serial *)tty->driver_data;	int	ret;					if (serial_paranoia_check(info, tty->device, "rs_write_room"))		return 0;	ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1;	if (ret < 0)		ret = 0;	return ret;}static int rs_chars_in_buffer(struct tty_struct *tty){	struct m68k_serial *info = (struct m68k_serial *)tty->driver_data;					if (serial_paranoia_check(info, tty->device, "rs_chars_in_buffer"))		return 0;	return info->xmit_cnt;}static void rs_flush_buffer(struct tty_struct *tty){	struct m68k_serial *info = (struct m68k_serial *)tty->driver_data;					if (serial_paranoia_check(info, tty->device, "rs_flush_buffer"))		return;	cli();	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;	sti();	wake_up_interruptible(&tty->write_wait);	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&	    tty->ldisc.write_wakeup)		(tty->ldisc.write_wakeup)(tty);}/* * ------------------------------------------------------------ * rs_throttle() *  * This routine is called by the upper-layer tty layer to signal that * incoming characters should be throttled. * ------------------------------------------------------------ */static void rs_throttle(struct tty_struct * tty){	struct m68k_serial *info = (struct m68k_serial *)tty->driver_data;	if (serial_paranoia_check(info, tty->device, "rs_throttle"))		return;		if (I_IXOFF(tty))		info->x_char = STOP_CHAR(tty);	/* Turn off RTS line (do this atomic) */}static void rs_unthrottle(struct tty_struct * tty){	struct m68k_serial *info = (struct m68k_serial *)tty->driver_data;	if (serial_paranoia_check(info, tty->device, "rs_unthrottle"))		return;		if (I_IXOFF(tty)) {		if (info->x_char)			info->x_char = 0;		else			info->x_char = START_CHAR(tty);	}	/* Assert RTS line (do this atomic) */}/* * ------------------------------------------------------------ * rs_ioctl() and friends * ------------------------------------------------------------ */static int get_serial_info(struct m68k_serial * info,			   struct serial_struct * retinfo){	struct serial_struct tmp;  	if (!retinfo)		return -EFAULT;	memset(&tmp, 0, sizeof(tmp));	tmp.type = info->type;	tmp.line = info->line;	tmp.port = info->port;	tmp.irq = info->irq;	tmp.flags = info->flags;	tmp.baud_base = info->baud_base;	tmp.close_delay = info->close_delay;	tmp.closing_wait = info->closing_wait;	tmp.custom_divisor = info->custom_divisor;	copy_to_user(retinfo,&tmp,sizeof(*retinfo));	return 0;}static int set_serial_info(struct m68k_serial * info,			   struct serial_struct * new_info){	struct serial_struct new_serial;	struct m68k_serial old_info;	int 			retval = 0;	if (!new_info)		return -EFAULT;	copy_from_user(&new_serial,new_info,sizeof(new_serial));	old_info = *info;	if (!suser()) {		if ((new_serial.baud_base != info->baud_base) ||		    (new_serial.type != info->type) ||		    (new_serial.close_delay != info->close_delay) ||		    ((new_serial.flags & ~S_USR_MASK) !=		     (info->flags & ~S_USR_MASK)))			return -EPERM;		info->flags = ((info->flags & ~S_USR_MASK) |			       (new_serial.flags & S_USR_MASK));		info->custom_divisor = new_serial.custom_divisor;		goto check_and_exit;	}	if (info->count > 1)		return -EBUSY;	/*	 * OK, past this point, all the error checking has been done.	 * At this point, we start making changes.....	 */	info->baud_base = new_serial.baud_base;	info->flags = ((info->flags & ~S_FLAGS) |			(new_serial.flags & S_FLAGS));	info->type = new_serial.type;	info->close_delay = new_serial.close_delay;	info->closing_wait = new_serial.closing_wait;check_and_exit:	retval = startup(info);	return retval;}/* * get_lsr_info - get line status register info * * Purpose: Let user call ioctl() to get info when the UART physically * 	    is emptied.  On bus types like RS485, the transmitter must * 	    release the bus after transmitting. This must be done when * 	    the transmit shift register is empty, not be done when the * 	    transmit holding register is empty.  This functionality * 	    allows an RS485 driver to be written in user space.  */static int get_lsr_info(struct m68k_serial * info, unsigned int *value){#ifdef CONFIG_68328_SERIAL_RTS_CTS	m68328_uart *uart = &uart_addr[info->line];#endif	unsigned char status;	cli();#ifdef CONFIG_68328_SERIAL_RTS_CTS	status = (uart->utx.w & UTX_CTS_STAT) ? 1 : 0;#else	status = 0;#endif	sti();	put_user(status,value);	return 0;}/* * This routine sends a break character out the serial port. */static void send_break(	struct m68k_serial * info, int duration){	m68328_uart *uart = &uart_addr[info->line];        unsigned long flags;        if (!info->port)                return;        current->state = TASK_INTERRUPTIBLE;        save_flags(flags);        cli();#ifdef USE_INTS		uart->utx.w |= UTX_SEND_BREAK;        schedule_timeout(duration);	uart->utx.w &= ~UTX_SEND_BREAK;#endif		        restore_flags(flags);}static int rs_ioctl(struct tty_struct *tty, struct file * file,		    unsigned int cmd, unsigned long arg){	int error;	struct m68k_serial * info = (struct m68k_serial *)tty->driver_data;	int retval;	if (serial_paranoia_check(info, tty->device, "rs_ioctl"))		return -ENODEV;	if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&	    (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGWILD)  &&	    (cmd != TIOCSERSWILD) && (cmd != TIOCSERGSTRUCT)) {		if (tty->flags & (1 << TTY_IO_ERROR))		    return -EIO;	}		switch (cmd) {		case TCSBRK:	/* SVID version: non-zero arg --> no break */			retval = tty_check_change(tty);			if (retval)				return retval;			tty_wait_until_sent(tty, 0);			if (!arg)				send_break(info, HZ/4);	/* 1/4 second */			return 0;		case TCSBRKP:	/* support for POSIX tcsendbreak() */			retval = tty_check_change(tty);			if (retval)				return retval;			tty_wait_until_sent(tty, 0);			send_break(info, arg ? arg*(HZ/10) : HZ/4);			return 0;		case TIOCGSOFTCAR:			error = verify_area(VERIFY_WRITE, (void *) arg,sizeof(long));			if (error)				return error;			put_user(C_CLOCAL(tty) ? 1 : 0,				    (unsigned long *) arg);			return 0;		case TIOCSSOFTCAR:			get_user(arg, (unsigned long *) arg);			tty->termios->c_cflag =				((tty->termios->c_cflag & ~CLOCAL) |				 (arg ? CLOCAL : 0));			return 0;		case TIOCGSERIAL:			error = verify_area(VERIFY_WRITE, (void *) arg,						sizeof(struct serial_struct));			if (error)				return error;			return get_serial_info(info,					       (struct serial_struct *) arg);		case TIOCSSERIAL:			return set_serial_info(info,					       (struct serial_struct *) arg);		case TIOCSERGETLSR: /* Get line status register */			error = verify_area(VERIFY_WRITE, (void *) arg,				sizeof(unsigned int));

⌨️ 快捷键说明

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