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

📄 serial_netarm.c

📁 这是一个SIGMA方案的PMP播放器的UCLINUX程序,可播放DVD,VCD,CD MP3...有很好的参考价值.
💻 C
📖 第 1 页 / 共 5 页
字号:
		tty->flip.flag_buf_ptr++;		tty->flip.char_buf_ptr++;		fifo_char++ ;		icount->rx++;	    }#if defined(CONFIG_SERIAL_NETARM_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)	ignore_char:#endif	    /* read status anew */	    *status = regs->status_a ;	}	while ((*status & NETARM_SER_STATA_RX_RDY) 	      && (tty->flip.count < TTY_FLIPBUF_SIZE));	tty_flip_buffer_push(tty);}static _INLINE_ voidcheck_modem_status(struct netarm_async_struct *info){	int	status;	struct	async_icount *icount;		status = info->SCSRA;	if (status & (NETARM_SER_STATA_RI|NETARM_SER_STATA_DSR	             |NETARM_SER_STATA_DCD|NETARM_SER_STATA_CTS))	{		icount = &info->state->icount;		/* update input line counters */		if (status & NETARM_SER_STATA_RI)			icount->rng++;		if (status & NETARM_SER_STATA_DSR)			icount->dsr++;		if (status & NETARM_SER_STATA_DCD)			icount->dcd++;		if (status & NETARM_SER_STATA_CTS)			icount->cts++;		wake_up_interruptible(&info->delta_msr_wait);	}	if ((info->flags & ASYNC_CHECK_CD) && (status & NETARM_SER_STATA_DCD)) {#if (defined(SERIAL_DEBUG_OPEN) || defined(SERIAL_DEBUG_INTR))		printk("ttys%d CD now %s...", info->line,		       (status & NETARM_SER_STATA_DCD) ? "on" : "off");#endif				if (status & NETARM_SER_STATA_DCD)			wake_up_interruptible(&info->open_wait);		else if (!((info->flags & ASYNC_CALLOUT_ACTIVE) &&			   (info->flags & ASYNC_CALLOUT_NOHUP))) {#ifdef SERIAL_DEBUG_OPEN			printk("doing serial hangup...");#endif			if (info->tty)				tty_hangup(info->tty);		}	}	if (info->flags & ASYNC_CTS_FLOW) {		if (info->tty->hw_stopped) {			if (status & NETARM_SER_STATA_CTS) {#if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW))				printk("CTS tx start...");#endif				info->tty->hw_stopped = 0;			/* FIXME: do we need rs_sched_event() here?				info->IER |= UART_IER_THRI;				serial_out(info, UART_IER, info->IER);				rs_sched_event(info, RS_EVENT_WRITE_WAKEUP);*/				return;			}		} else {			if (!(status & NETARM_SER_STATA_CTS)) {#if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW))				printk("CTS tx stop...");#endif				info->tty->hw_stopped = 1;			/*	info->IER &= ~UART_IER_THRI;				serial_out(info, UART_IER, info->IER);*/			}		}	}}/* * ------------------------------------------------------------------- * This is the serial driver's interrupt routine for a single port * ------------------------------------------------------------------- */static _INLINE_ voidnas_rx_interrupt(struct netarm_async_struct *info, struct pt_regs *regs){ 	int status;	int pass_counter = 0;		if (!info || !info->tty) return;	do	{ 		status = info->SCSRA;#ifdef SERIAL_DEBUG_INTR		printk("status = %x...", status);#endif		if (status & (NETARM_SER_STATA_RX_RDY		             |NETARM_SER_STATA_RX_HALF			     |NETARM_SER_STATA_RX_FULL))			receive_chars(info, &status, regs);/* FIXME:   do we need check_modem_status() if we don't want to transmit anything?		check_modem_status(info);		if (status & UART_LSR_THRE)			transmit_chars(info, 0);*/		if (pass_counter++ > RS_ISR_PASS_LIMIT)		{#if 0			printk("rs_single loop break.\n");#endif			break;		}#ifdef SERIAL_DEBUG_INTR		printk("STAT_A = %x...", info->registers->status_a);#endif	}	while (NETARM_SER_STATA_RX_RDY & (info->SCSRA = info->registers->status_a));	info->last_active = jiffies;#ifdef SERIAL_DEBUG_INTR	printk("end.\n");#endif}static voidnas_rx_interrupt_1(int irq, void *dev_id, struct pt_regs *regs){#if (defined(SERIAL_DEBUG_INTR) && defined(NAS_DEBUG_VERBOSE))  printk(" nas_rx_interrupt_1: int!\n");#endif  nas_rx_interrupt(&NAS_ports[0], regs) ;}static voidnas_rx_interrupt_2(int irq, void *dev_id, struct pt_regs *regs){#if (defined(SERIAL_DEBUG_INTR) && defined(NAS_DEBUG_VERBOSE))  printk(" nas_rx_interrupt_2: int!\n");#endif  nas_rx_interrupt(&NAS_ports[1], regs) ;}/* * ------------------------------------------------------------------- * Here end the serial interrupt routines * ------------------------------------------------------------------- *//* * This routine is used to handle the "bottom half" processing for the * serial driver, known also the "software interrupt" processing. * This processing is done at the kernel interrupt level, after the * rs_interrupt() has returned, BUT WITH INTERRUPTS TURNED ON.  This * is where time-consuming activities which can not be done in the * interrupt driver proper are done; the interrupt driver schedules * them using rs_sched_event(), and they get done here. */static voiddo_serial_bh(void){	run_task_queue(&tq_serial);}static voiddo_softint(void *private_){	struct netarm_async_struct *info = (struct netarm_async_struct *) private_;	struct tty_struct          *tty;		tty = info->tty;	if (!tty)		return;	if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event)) {		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&		    tty->ldisc.write_wakeup)			(tty->ldisc.write_wakeup)(tty);		wake_up_interruptible(&tty->write_wait);#ifdef SERIAL_HAVE_POLL_WAIT		wake_up_interruptible(&tty->poll_wait);#endif	}}/* * --------------------------------------------------------------- * Low level utility subroutines for the serial driver:  routines * to initialize and startup a serial port, and routines to shutdown a * serial port.  Useful stuff like that. * --------------------------------------------------------------- */static int nas_validate_baud(int baud){  if (baud >= MIN_BAUD_RATE && baud <= MAX_BAUD_RATE) return 0;  return 1;}/* * This is used to figure out the divisor speeds and the timeouts */static int nas_baud_table[] = {	0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,	9600, 19200, 38400, 57600, 115200, 0 };static int nas_n_baud_table = sizeof(nas_baud_table)/sizeof(int);/* nas_tty_get_baud_rate is borrowed from 2.2.12 tty_io.c		*//* since the netarm serial driver is based upon the 2.2.x source 	*//* rather than the 2.0.X. The reasons for this are purely historical 	*/intnas_tty_get_baud_rate(struct tty_struct *tty){	unsigned int cflag, i;	cflag = tty->termios->c_cflag;	i = cflag & CBAUD;	if (i & CBAUDEX)	{		i &= ~CBAUDEX;		if (i < 1 || i+15 >= nas_n_baud_table) 			tty->termios->c_cflag &= ~CBAUDEX;		else			i += 15;	}	return nas_baud_table[i];}static intstartup(struct netarm_async_struct * info){	unsigned long		flags;	int			baud, retval=0;	struct serial_state 	*state = info->state;	unsigned long 		page;	volatile netarm_serial_channel_t *regs;	/* check the baud rate */	baud = nas_tty_get_baud_rate(info->tty);	if (nas_validate_baud(baud) != 0)	{	    printk("nas_startup_port: invalid baud rate from tty struct: %d\n", baud);	    return -EINVAL;	}	info->baud = baud;	page = get_zeroed_page(GFP_KERNEL);	if (!page)		return -ENOMEM;	save_flags(flags); cli();	if (info->flags & ASYNC_INITIALIZED) {		free_page(page);		goto errout;	}	if (!CONFIGURED_SERIAL_PORT(state) || !state->type) {		if (info->tty)			set_bit(TTY_IO_ERROR, &info->tty->flags);		free_page(page);		goto errout;	}	if (info->xmit.buf)		free_page(page);	else		info->xmit.buf = (unsigned char *) page;#ifdef SERIAL_DEBUG_OPEN	printk("Starting up ttyS%d (irq %d) at %d baud...\n",	        info->line, state->irq, info->baud);#endif	/* Wake up and initialize SER module */	regs = info->registers;	regs->rx_match = 0;	regs->rx_buf_timer = 0;	regs->bitrate = NETARM_SER_BR_X16(baud);	regs->rx_char_timer = NETARM_SER_RXGAP(baud);	regs->ctrl_b = NETARM_SER_CTLB_RCGT_EN | NETARM_SER_CTLB_UART_MODE;#ifdef POLLED_SERIAL	regs->ctrl_a |= NETARM_SER_CTLA_ENABLE ;#else	/* enable interrupts */	regs->ctrl_a |= NETARM_SER_CTLA_ENABLE | NETARM_SER_CTLA_IE_RX_RDY | 	                NETARM_SER_CTLA_IE_RX_FULL ;#endif	/*	 * Set up the tty->alt_speed kludge	 */	if (info->tty) {		if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)			info->tty->alt_speed = 57600;		if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)			info->tty->alt_speed = 115200;		if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)			info->tty->alt_speed = 230400;		if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)			info->tty->alt_speed = 460800;	}	/*	 * and set the speed of the serial port	 */	change_speed(info, 0);	info->flags |= ASYNC_INITIALIZED;	restore_flags(flags);	return 0;errout:	restore_flags(flags);	return retval;}/* * This routine will shutdown a serial port; interrupts are disabled, and * DTR is dropped if the hangup on close termio flag is on. */static voidshutdown(struct netarm_async_struct * info){	unsigned long flags;	struct serial_state *state;	volatile netarm_serial_channel_t *regs;	if (!(info->flags & ASYNC_INITIALIZED))		return;	state = info->state;	regs  = info->registers;#ifdef SERIAL_DEBUG_OPEN	printk("Shutting down serial port %d (irq %d)...\n", info->line,	       state->irq);#endif		save_flags(flags); cli(); /* Disable interrupts */	/*	 * clear delta_msr_wait queue to avoid mem leaks: we may free the irq	 * here so the queue might never be waken up	 */	wake_up_interruptible(&info->delta_msr_wait);		if (info->xmit.buf) {		unsigned long pg = (unsigned long) info->xmit.buf;		info->xmit.buf = 0;		free_page(pg);	}	/* turn off the port */	regs->ctrl_a &= ~NETARM_SER_CTLA_ENABLE ;			if (info->tty)		set_bit(TTY_IO_ERROR, &info->tty->flags);	info->flags &= ~ASYNC_INITIALIZED;	restore_flags(flags);}/* * This routine is called to set the specified baud rate for a serial port. */static voidchange_speed(struct netarm_async_struct *info, struct termios *old_termios){	volatile netarm_serial_channel_t *regs;	int	quot = 0, baud_base, baud;	unsigned cflag, cval;	int	bits;	unsigned long flags;	regs  = info->registers;	if (!info->tty || !info->tty->termios)		return;	cflag = info->tty->termios->c_cflag;	if (!CONFIGURED_NAS_PORT(info))		return;	/* byte size and parity */	switch (cflag & CSIZE) {	      case CS5: cval = NETARM_SER_CTLA_5BITS; bits = 7; break;	      case CS6: cval = NETARM_SER_CTLA_6BITS; bits = 8; break;	      case CS7: cval = NETARM_SER_CTLA_7BITS; bits = 9; break;	      case CS8: cval = NETARM_SER_CTLA_8BITS; bits = 10; break;	      /* Never happens, but GCC is too dumb to figure it out */	      default:  cval = NETARM_SER_CTLA_5BITS; bits = 7; break;	}	if (cflag & CSTOPB) {		cval |= NETARM_SER_CTLA_2STOP;		bits++;	}	if (cflag & PARENB) {		cval |= NETARM_SER_CTLA_P_ODD;		bits++;		if (!(cflag & PARODD))			cval |= NETARM_SER_CTLA_P_EVEN;	}	/* Determine divisor based on baud rate */	baud = nas_tty_get_baud_rate(info->tty);	if (!baud)		baud = 9600;#ifdef SERIAL_DEBUG_OPEN	printk("change_speed: cflag %d, baud rate %d\n", cflag, baud);#endif	baud_base = info->state->baud_base;	quot = baud_base / baud;	/* As a last resort, if the quotient is zero, default to 9600 bps */	if (!quot) quot = baud_base / 9600;		info->quot = quot;	info->timeout = ((info->xmit_fifo_size*HZ*bits*quot) / baud_base);	info->timeout += HZ/50;		/* Add .02 seconds of slop */	/* CTS flow control flag and modem status interrupts */	if (cflag & CRTSCTS)		cval |= NETARM_SER_CTLA_CTSTX | NETARM_SER_CTLA_RTSRX;	/*	 * Set up parity check flag	 */#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))	save_flags(flags); cli();	regs = info->registers;	regs->rx_match = 0;	regs->rx_buf_timer = 0;	regs->bitrate = NETARM_SER_BR_X16(baud);	regs->rx_char_timer = NETARM_SER_RXGAP(baud);	regs->ctrl_b = NETARM_SER_CTLB_RCGT_EN | NETARM_SER_CTLB_UART_MODE;#ifdef POLLED_SERIAL	regs->ctrl_a = NETARM_SER_CTLA_ENABLE | cval;#else	/* enable interrupts */	regs->ctrl_a = NETARM_SER_CTLA_ENABLE | NETARM_SER_CTLA_IE_RX_RDY | 	               NETARM_SER_CTLA_IE_RX_FULL | cval;#endif#ifdef SERIAL_DEBUG_OPEN	printk("change_speed: bitrate %x, rxgap %x\n",		regs->bitrate, regs->rx_char_timer );#endif	restore_flags(flags);}/* Output a single character to the device */static voidrs_put_char(struct tty_struct *tty, unsigned char ch){	struct netarm_async_struct *info = (struct netarm_async_struct *)tty->driver_data; 	volatile netarm_serial_channel_t *regs;	unsigned char *fifo;#ifdef	NAS_DEBUG_VERBOSE  printk(" rs_put_char called\n");#endif	regs = info->registers;	fifo = (unsigned char *)&(regs->fifo);	/* write the character (polled) */	NAS_TX_WAIT_RDY(regs);        *fifo = ch;}/* not needed in polled output: */static voidrs_flush_chars(struct tty_struct *tty){	struct netarm_async_struct *info = (struct netarm_async_struct *)tty->driver_data;					serial_paranoia_check(info, tty->device, "rs_flush_chars");

⌨️ 快捷键说明

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