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

📄 sh-sci.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 3 页
字号:
	mark_bh(IMMEDIATE_BH);}static void sci_transmit_chars(struct sci_port *port){	int count, i;	int txroom;	unsigned long flags;	unsigned short status;	unsigned short ctrl;	unsigned char c;	status = sci_in(port, SCxSR);	if (!(status & SCxSR_TDxE(port))) {		save_and_cli(flags);		ctrl = sci_in(port, SCSCR);		if (port->gs.xmit_cnt == 0) {			ctrl &= ~SCI_CTRL_FLAGS_TIE;			port->gs.flags &= ~GS_TX_INTEN;		} else			ctrl |= SCI_CTRL_FLAGS_TIE;		sci_out(port, SCSCR, ctrl);		restore_flags(flags);		return;	}	while (1) {		count = port->gs.xmit_cnt;		if (port->type == PORT_SCIF) {			txroom = 16 - (sci_in(port, SCFDR)>>8);		} else {			txroom = (sci_in(port, SCxSR) & SCI_TDRE)?1:0;		}		if (count > txroom)			count = txroom;		/* Don't copy pas the end of the source buffer */		if (count > SERIAL_XMIT_SIZE - port->gs.xmit_tail)                	count = SERIAL_XMIT_SIZE - port->gs.xmit_tail;		/* If for one reason or another, we can't copy more data, we're done! */		if (count == 0)			break;		for (i=0; i<count; i++) {			c = port->gs.xmit_buf[port->gs.xmit_tail + i];			sci_out(port, SCxTDR, c);		}		sci_out(port, SCxSR, SCxSR_TDxE_CLEAR(port));		port->icount.tx += count;		/* Update the kernel buffer end */		port->gs.xmit_tail = (port->gs.xmit_tail + count) & (SERIAL_XMIT_SIZE-1);		/* This one last. (this is essential)		   It would allow others to start putting more data into the buffer! */		port->gs.xmit_cnt -= count;	}	if (port->gs.xmit_cnt <= port->gs.wakeup_chars)		sci_sched_event(port, SCI_EVENT_WRITE_WAKEUP);	save_and_cli(flags);	ctrl = sci_in(port, SCSCR);	if (port->gs.xmit_cnt == 0) {		ctrl &= ~SCI_CTRL_FLAGS_TIE;		port->gs.flags &= ~GS_TX_INTEN;	} else {		if (port->type == PORT_SCIF) {			sci_in(port, SCxSR); /* Dummy read */			sci_out(port, SCxSR, SCxSR_TDxE_CLEAR(port));		}		ctrl |= SCI_CTRL_FLAGS_TIE;	}	sci_out(port, SCSCR, ctrl);	restore_flags(flags);}static inline void sci_receive_chars(struct sci_port *port){	int i, count;	struct tty_struct *tty;	int copied=0;	unsigned short status;	status = sci_in(port, SCxSR);	if (!(status & SCxSR_RDxF(port)))		return;	tty = port->gs.tty;	while (1) {		if (port->type == PORT_SCIF) {			count = sci_in(port, SCFDR)&0x001f;		} else {			count = (sci_in(port, SCxSR)&SCxSR_RDxF(port))?1:0;		}		/* Don't copy more bytes than there is room for in the buffer */		if (tty->flip.count + count > TTY_FLIPBUF_SIZE)			count = TTY_FLIPBUF_SIZE - tty->flip.count;		/* If for one reason or another, we can't copy more data, we're done! */		if (count == 0)			break;		if (port->type == PORT_SCI) {			tty->flip.char_buf_ptr[0] = sci_in(port, SCxRDR);			tty->flip.flag_buf_ptr[0] = TTY_NORMAL;		} else {			for (i=0; i<count; i++) {				tty->flip.char_buf_ptr[i] = sci_in(port, SCxRDR);				status = sci_in(port, SCxSR);				if (status&SCxSR_FER(port)) {					tty->flip.flag_buf_ptr[i] = TTY_FRAME;					dprintk("sci: frame error\n");				} else if (status&SCxSR_PER(port)) {					tty->flip.flag_buf_ptr[i] = TTY_PARITY;					dprintk("sci: parity error\n");				} else {					tty->flip.flag_buf_ptr[i] = TTY_NORMAL;				}			}		}		sci_in(port, SCxSR); /* dummy read */		sci_out(port, SCxSR, SCxSR_RDxF_CLEAR(port));		/* Update the kernel buffer end */		tty->flip.count += count;		tty->flip.char_buf_ptr += count;		tty->flip.flag_buf_ptr += count;		copied += count;		port->icount.rx += count;	}	if (copied)		/* Tell the rest of the system the news. New characters! */		tty_flip_buffer_push(tty);}static inline int sci_handle_errors(struct sci_port *port){	int copied = 0;	unsigned short status = sci_in(port, SCxSR);	struct tty_struct *tty = port->gs.tty;	if (status&SCxSR_ORER(port) && tty->flip.count<TTY_FLIPBUF_SIZE) {		/* overrun error */		copied++;		*tty->flip.flag_buf_ptr++ = TTY_OVERRUN;		dprintk("sci: overrun error\n");	}	if (status&SCxSR_FER(port) && tty->flip.count<TTY_FLIPBUF_SIZE) {		if (sci_rxd_in(port) == 0) {			/* Notify of BREAK */			copied++;			*tty->flip.flag_buf_ptr++ = TTY_BREAK;			dprintk("sci: BREAK detected\n");		}		else {			/* frame error */			copied++;			*tty->flip.flag_buf_ptr++ = TTY_FRAME;			dprintk("sci: frame error\n");		}	}	if (status&SCxSR_PER(port) && tty->flip.count<TTY_FLIPBUF_SIZE) {		/* parity error */		copied++;		*tty->flip.flag_buf_ptr++ = TTY_PARITY;		dprintk("sci: parity error\n");	}	if (copied) {		tty->flip.count += copied;		tty_flip_buffer_push(tty);	}	return copied;}static inline int sci_handle_breaks(struct sci_port *port){	int copied = 0;	unsigned short status = sci_in(port, SCxSR);	struct tty_struct *tty = port->gs.tty;	if (status&SCxSR_BRK(port) && tty->flip.count<TTY_FLIPBUF_SIZE) {		/* Notify of BREAK */		copied++;		*tty->flip.flag_buf_ptr++ = TTY_BREAK;		dprintk("sci: BREAK detected\n");	}#if defined(CONFIG_CPU_SUBTYPE_SH7750) || defined(CONFIG_CPU_SUBTYPE_ST40STB1)	/* XXX: Handle SCIF overrun error */	if (port->type == PORT_SCIF && (sci_in(port, SCLSR) & SCIF_ORER) != 0) {		sci_out(port, SCLSR, 0);		if(tty->flip.count<TTY_FLIPBUF_SIZE) {			copied++;			*tty->flip.flag_buf_ptr++ = TTY_OVERRUN;			dprintk("sci: overrun error\n");		}	}#endif	if (copied) {		tty->flip.count += copied;		tty_flip_buffer_push(tty);	}	return copied;}static void sci_rx_interrupt(int irq, void *ptr, struct pt_regs *regs){	struct sci_port *port = ptr;	if (port->gs.flags & GS_ACTIVE)		if (!(port->gs.flags & SCI_RX_THROTTLE)) {			sci_receive_chars(port);			return;		}	sci_disable_rx_interrupts(port);}static void sci_tx_interrupt(int irq, void *ptr, struct pt_regs *regs){	struct sci_port *port = ptr;	if (port->gs.flags & GS_ACTIVE)		sci_transmit_chars(port);	else {		sci_disable_tx_interrupts(port);	}}static void sci_er_interrupt(int irq, void *ptr, struct pt_regs *regs){	struct sci_port *port = ptr;	/* Handle errors */	if (port->type == PORT_SCI) {		if(sci_handle_errors(port)) {			/* discard character in rx buffer */			sci_in(port, SCxSR);			sci_out(port, SCxSR, SCxSR_RDxF_CLEAR(port));		}	}	else		sci_rx_interrupt(irq, ptr, regs);			sci_out(port, SCxSR, SCxSR_ERROR_CLEAR(port));	/* Kick the transmission */	sci_tx_interrupt(irq, ptr, regs);}static void sci_br_interrupt(int irq, void *ptr, struct pt_regs *regs){	struct sci_port *port = ptr;	/* Handle BREAKs */	sci_handle_breaks(port);	sci_out(port, SCxSR, SCxSR_BREAK_CLEAR(port));}static void do_softint(void *private_){	struct sci_port *port = (struct sci_port *) private_;	struct tty_struct	*tty;		tty = port->gs.tty;	if (!tty)		return;	if (test_and_clear_bit(SCI_EVENT_WRITE_WAKEUP, &port->event)) {		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&		    tty->ldisc.write_wakeup)			(tty->ldisc.write_wakeup)(tty);		wake_up_interruptible(&tty->write_wait);	}}/* ********************************************************************** * *                Here are the routines that actually                     * *              interface with the generic_serial driver                  * * ********************************************************************** */static void sci_disable_tx_interrupts(void *ptr){	struct sci_port *port = ptr;	unsigned long flags;	unsigned short ctrl;	/* Clear TIE (Transmit Interrupt Enable) bit in SCSCR */	save_and_cli(flags);	ctrl = sci_in(port, SCSCR);	ctrl &= ~SCI_CTRL_FLAGS_TIE;	sci_out(port, SCSCR, ctrl);	restore_flags(flags);}static void sci_enable_tx_interrupts(void *ptr){	struct sci_port *port = ptr; 	disable_irq(port->irqs[SCIx_TXI_IRQ]);	sci_transmit_chars(port);	enable_irq(port->irqs[SCIx_TXI_IRQ]);}static void sci_disable_rx_interrupts(void * ptr){	struct sci_port *port = ptr;	unsigned long flags;	unsigned short ctrl;	/* Clear RIE (Receive Interrupt Enable) bit in SCSCR */	save_and_cli(flags);	ctrl = sci_in(port, SCSCR);	ctrl &= ~SCI_CTRL_FLAGS_RIE;	sci_out(port, SCSCR, ctrl);	restore_flags(flags);}static void sci_enable_rx_interrupts(void * ptr){	struct sci_port *port = ptr;	unsigned long flags;	unsigned short ctrl;	/* Set RIE (Receive Interrupt Enable) bit in SCSCR */	save_and_cli(flags);	ctrl = sci_in(port, SCSCR);	ctrl |= SCI_CTRL_FLAGS_RIE;	sci_out(port, SCSCR, ctrl);	restore_flags(flags);}static int sci_get_CD(void * ptr){	/* If you have signal for CD (Carrier Detect), please change here. */	return 1;}static int sci_chars_in_buffer(void * ptr){	struct sci_port *port = ptr;	if (port->type == PORT_SCIF) {		return (sci_in(port, SCFDR) >> 8) + ((sci_in(port, SCxSR) & SCxSR_TEND(port))? 0: 1);	} else {		return (sci_in(port, SCxSR) & SCxSR_TEND(port))? 0: 1;	}}static void sci_shutdown_port(void * ptr){	struct sci_port *port = ptr; 	port->gs.flags &= ~ GS_ACTIVE;	if (port->gs.tty && port->gs.tty->termios->c_cflag & HUPCL)		sci_setsignals(port, 0, 0);	sci_free_irq(port);}/* ********************************************************************** * *                Here are the routines that actually                     * *               interface with the rest of the system                    * * ********************************************************************** */static int sci_open(struct tty_struct * tty, struct file * filp){	struct sci_port *port;	int retval, line;	line = MINOR(tty->device) - SCI_MINOR_START;	if ((line < 0) || (line >= SCI_NPORTS))		return -ENODEV;	port = &sci_ports[line];	tty->driver_data = port;	port->gs.tty = tty;	port->gs.count++;	port->event = 0;	port->tqueue.routine = do_softint;	port->tqueue.data = port;	/*	 * Start up serial port	 */	retval = gs_init_port(&port->gs);	if (retval) {		goto failed_1;	}	port->gs.flags |= GS_ACTIVE;	sci_setsignals(port, 1,1);	if (port->gs.count == 1) {		MOD_INC_USE_COUNT;		retval = sci_request_irq(port);		if (retval) {			goto failed_2;		}	}	retval = gs_block_til_ready(port, filp);	if (retval) {		goto failed_3;	}	if ((port->gs.count == 1) && (port->gs.flags & ASYNC_SPLIT_TERMIOS)) {		if (tty->driver.subtype == SERIAL_TYPE_NORMAL)			*tty->termios = port->gs.normal_termios;		else 			*tty->termios = port->gs.callout_termios;		sci_set_real_termios(port);	}#ifdef CONFIG_SERIAL_CONSOLE	if (sercons.cflag && sercons.index == line) {		tty->termios->c_cflag = sercons.cflag;		port->gs.baud = sercons_baud;

⌨️ 快捷键说明

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