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

📄 mpsc.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
				flag = TTY_BREAK;			else if (cmdstat & SDMA_DESC_CMDSTAT_FR)				flag = TTY_FRAME;			else if (cmdstat & SDMA_DESC_CMDSTAT_OR)				flag = TTY_OVERRUN;			else if (cmdstat & SDMA_DESC_CMDSTAT_PE)				flag = TTY_PARITY;		}		if (uart_handle_sysrq_char(&pi->port, *bp)) {			bp++;			bytes_in--;			goto next_frame;		}		if ((unlikely(cmdstat & (SDMA_DESC_CMDSTAT_BR						| SDMA_DESC_CMDSTAT_FR						| SDMA_DESC_CMDSTAT_OR)))				&& !(cmdstat & pi->port.ignore_status_mask)) {			tty_insert_flip_char(tty, *bp, flag);		} else {			for (i=0; i<bytes_in; i++)				tty_insert_flip_char(tty, *bp++, TTY_NORMAL);			pi->port.icount.rx += bytes_in;		}next_frame:		rxre->bytecnt = cpu_to_be16(0);		wmb();		rxre->cmdstat = cpu_to_be32(SDMA_DESC_CMDSTAT_O				| SDMA_DESC_CMDSTAT_EI | SDMA_DESC_CMDSTAT_F				| SDMA_DESC_CMDSTAT_L);		wmb();		dma_cache_sync(pi->port.dev, (void *)rxre, MPSC_RXRE_SIZE,				DMA_BIDIRECTIONAL);#if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)		if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */			flush_dcache_range((ulong)rxre,					(ulong)rxre + MPSC_RXRE_SIZE);#endif		/* Advance to next descriptor */		pi->rxr_posn = (pi->rxr_posn + 1) & (MPSC_RXR_ENTRIES - 1);		rxre = (struct mpsc_rx_desc *)			(pi->rxr + (pi->rxr_posn * MPSC_RXRE_SIZE));		dma_cache_sync(pi->port.dev, (void *)rxre, MPSC_RXRE_SIZE,				DMA_FROM_DEVICE);#if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)		if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */			invalidate_dcache_range((ulong)rxre,					(ulong)rxre + MPSC_RXRE_SIZE);#endif		rc = 1;	}	/* Restart rx engine, if its stopped */	if ((readl(pi->sdma_base + SDMA_SDCM) & SDMA_SDCM_ERD) == 0)		mpsc_start_rx(pi);	tty_flip_buffer_push(tty);	return rc;}static void mpsc_setup_tx_desc(struct mpsc_port_info *pi, u32 count, u32 intr){	struct mpsc_tx_desc *txre;	txre = (struct mpsc_tx_desc *)(pi->txr			+ (pi->txr_head * MPSC_TXRE_SIZE));	txre->bytecnt = cpu_to_be16(count);	txre->shadow = txre->bytecnt;	wmb();			/* ensure cmdstat is last field updated */	txre->cmdstat = cpu_to_be32(SDMA_DESC_CMDSTAT_O | SDMA_DESC_CMDSTAT_F			| SDMA_DESC_CMDSTAT_L			| ((intr) ? SDMA_DESC_CMDSTAT_EI : 0));	wmb();	dma_cache_sync(pi->port.dev, (void *)txre, MPSC_TXRE_SIZE,			DMA_BIDIRECTIONAL);#if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)	if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */		flush_dcache_range((ulong)txre,				(ulong)txre + MPSC_TXRE_SIZE);#endif}static void mpsc_copy_tx_data(struct mpsc_port_info *pi){	struct circ_buf *xmit = &pi->port.info->xmit;	u8 *bp;	u32 i;	/* Make sure the desc ring isn't full */	while (CIRC_CNT(pi->txr_head, pi->txr_tail, MPSC_TXR_ENTRIES)			< (MPSC_TXR_ENTRIES - 1)) {		if (pi->port.x_char) {			/*			 * Ideally, we should use the TCS field in			 * CHR_1 to put the x_char out immediately but			 * errata prevents us from being able to read			 * CHR_2 to know that its safe to write to			 * CHR_1.  Instead, just put it in-band with			 * all the other Tx data.			 */			bp = pi->txb + (pi->txr_head * MPSC_TXBE_SIZE);			*bp = pi->port.x_char;			pi->port.x_char = 0;			i = 1;		} else if (!uart_circ_empty(xmit)				&& !uart_tx_stopped(&pi->port)) {			i = min((u32)MPSC_TXBE_SIZE,				(u32)uart_circ_chars_pending(xmit));			i = min(i, (u32)CIRC_CNT_TO_END(xmit->head, xmit->tail,				UART_XMIT_SIZE));			bp = pi->txb + (pi->txr_head * MPSC_TXBE_SIZE);			memcpy(bp, &xmit->buf[xmit->tail], i);			xmit->tail = (xmit->tail + i) & (UART_XMIT_SIZE - 1);			if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)				uart_write_wakeup(&pi->port);		} else { /* All tx data copied into ring bufs */			return;		}		dma_cache_sync(pi->port.dev, (void *)bp, MPSC_TXBE_SIZE,				DMA_BIDIRECTIONAL);#if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)		if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */			flush_dcache_range((ulong)bp,					(ulong)bp + MPSC_TXBE_SIZE);#endif		mpsc_setup_tx_desc(pi, i, 1);		/* Advance to next descriptor */		pi->txr_head = (pi->txr_head + 1) & (MPSC_TXR_ENTRIES - 1);	}}static int mpsc_tx_intr(struct mpsc_port_info *pi){	struct mpsc_tx_desc *txre;	int rc = 0;	unsigned long iflags;	spin_lock_irqsave(&pi->tx_lock, iflags);	if (!mpsc_sdma_tx_active(pi)) {		txre = (struct mpsc_tx_desc *)(pi->txr				+ (pi->txr_tail * MPSC_TXRE_SIZE));		dma_cache_sync(pi->port.dev, (void *)txre, MPSC_TXRE_SIZE,				DMA_FROM_DEVICE);#if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)		if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */			invalidate_dcache_range((ulong)txre,					(ulong)txre + MPSC_TXRE_SIZE);#endif		while (!(be32_to_cpu(txre->cmdstat) & SDMA_DESC_CMDSTAT_O)) {			rc = 1;			pi->port.icount.tx += be16_to_cpu(txre->bytecnt);			pi->txr_tail = (pi->txr_tail+1) & (MPSC_TXR_ENTRIES-1);			/* If no more data to tx, fall out of loop */			if (pi->txr_head == pi->txr_tail)				break;			txre = (struct mpsc_tx_desc *)(pi->txr					+ (pi->txr_tail * MPSC_TXRE_SIZE));			dma_cache_sync(pi->port.dev, (void *)txre,					MPSC_TXRE_SIZE, DMA_FROM_DEVICE);#if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)			if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */				invalidate_dcache_range((ulong)txre,						(ulong)txre + MPSC_TXRE_SIZE);#endif		}		mpsc_copy_tx_data(pi);		mpsc_sdma_start_tx(pi);	/* start next desc if ready */	}	spin_unlock_irqrestore(&pi->tx_lock, iflags);	return rc;}/* * This is the driver's interrupt handler.  To avoid a race, we first clear * the interrupt, then handle any completed Rx/Tx descriptors.  When done * handling those descriptors, we restart the Rx/Tx engines if they're stopped. */static irqreturn_t mpsc_sdma_intr(int irq, void *dev_id){	struct mpsc_port_info *pi = dev_id;	ulong iflags;	int rc = IRQ_NONE;	pr_debug("mpsc_sdma_intr[%d]: SDMA Interrupt Received\n",pi->port.line);	spin_lock_irqsave(&pi->port.lock, iflags);	mpsc_sdma_intr_ack(pi);	if (mpsc_rx_intr(pi))		rc = IRQ_HANDLED;	if (mpsc_tx_intr(pi))		rc = IRQ_HANDLED;	spin_unlock_irqrestore(&pi->port.lock, iflags);	pr_debug("mpsc_sdma_intr[%d]: SDMA Interrupt Handled\n", pi->port.line);	return rc;}/* ****************************************************************************** * * serial_core.c Interface routines * ****************************************************************************** */static uint mpsc_tx_empty(struct uart_port *port){	struct mpsc_port_info *pi = (struct mpsc_port_info *)port;	ulong iflags;	uint rc;	spin_lock_irqsave(&pi->port.lock, iflags);	rc = mpsc_sdma_tx_active(pi) ? 0 : TIOCSER_TEMT;	spin_unlock_irqrestore(&pi->port.lock, iflags);	return rc;}static void mpsc_set_mctrl(struct uart_port *port, uint mctrl){	/* Have no way to set modem control lines AFAICT */}static uint mpsc_get_mctrl(struct uart_port *port){	struct mpsc_port_info *pi = (struct mpsc_port_info *)port;	u32 mflags, status;	status = (pi->mirror_regs) ? pi->MPSC_CHR_10_m		: readl(pi->mpsc_base + MPSC_CHR_10);	mflags = 0;	if (status & 0x1)		mflags |= TIOCM_CTS;	if (status & 0x2)		mflags |= TIOCM_CAR;	return mflags | TIOCM_DSR;	/* No way to tell if DSR asserted */}static void mpsc_stop_tx(struct uart_port *port){	struct mpsc_port_info *pi = (struct mpsc_port_info *)port;	pr_debug("mpsc_stop_tx[%d]\n", port->line);	mpsc_freeze(pi);}static void mpsc_start_tx(struct uart_port *port){	struct mpsc_port_info *pi = (struct mpsc_port_info *)port;	unsigned long iflags;	spin_lock_irqsave(&pi->tx_lock, iflags);	mpsc_unfreeze(pi);	mpsc_copy_tx_data(pi);	mpsc_sdma_start_tx(pi);	spin_unlock_irqrestore(&pi->tx_lock, iflags);	pr_debug("mpsc_start_tx[%d]\n", port->line);}static void mpsc_start_rx(struct mpsc_port_info *pi){	pr_debug("mpsc_start_rx[%d]: Starting...\n", pi->port.line);	if (pi->rcv_data) {		mpsc_enter_hunt(pi);		mpsc_sdma_cmd(pi, SDMA_SDCM_ERD);	}}static void mpsc_stop_rx(struct uart_port *port){	struct mpsc_port_info *pi = (struct mpsc_port_info *)port;	pr_debug("mpsc_stop_rx[%d]: Stopping...\n", port->line);	if (pi->mirror_regs) {		writel(pi->MPSC_CHR_2_m | MPSC_CHR_2_RA,				pi->mpsc_base + MPSC_CHR_2);		/* Erratum prevents reading CHR_2 so just delay for a while */		udelay(100);	} else {		writel(readl(pi->mpsc_base + MPSC_CHR_2) | MPSC_CHR_2_RA,				pi->mpsc_base + MPSC_CHR_2);		while (readl(pi->mpsc_base + MPSC_CHR_2) & MPSC_CHR_2_RA)			udelay(10);	}	mpsc_sdma_cmd(pi, SDMA_SDCM_AR);}static void mpsc_enable_ms(struct uart_port *port){}static void mpsc_break_ctl(struct uart_port *port, int ctl){	struct mpsc_port_info *pi = (struct mpsc_port_info *)port;	ulong	flags;	u32	v;	v = ctl ? 0x00ff0000 : 0;	spin_lock_irqsave(&pi->port.lock, flags);	if (pi->mirror_regs)		pi->MPSC_CHR_1_m = v;	writel(v, pi->mpsc_base + MPSC_CHR_1);	spin_unlock_irqrestore(&pi->port.lock, flags);}static int mpsc_startup(struct uart_port *port){	struct mpsc_port_info *pi = (struct mpsc_port_info *)port;	u32 flag = 0;	int rc;	pr_debug("mpsc_startup[%d]: Starting up MPSC, irq: %d\n",		port->line, pi->port.irq);	if ((rc = mpsc_make_ready(pi)) == 0) {		/* Setup IRQ handler */		mpsc_sdma_intr_ack(pi);		/* If irq's are shared, need to set flag */		if (mpsc_ports[0].port.irq == mpsc_ports[1].port.irq)			flag = IRQF_SHARED;		if (request_irq(pi->port.irq, mpsc_sdma_intr, flag,					"mpsc-sdma", pi))			printk(KERN_ERR "MPSC: Can't get SDMA IRQ %d\n",					pi->port.irq);		mpsc_sdma_intr_unmask(pi, 0xf);		mpsc_sdma_set_rx_ring(pi, (struct mpsc_rx_desc *)(pi->rxr_p					+ (pi->rxr_posn * MPSC_RXRE_SIZE)));	}	return rc;}static void mpsc_shutdown(struct uart_port *port){	struct mpsc_port_info *pi = (struct mpsc_port_info *)port;	pr_debug("mpsc_shutdown[%d]: Shutting down MPSC\n", port->line);	mpsc_sdma_stop(pi);	free_irq(pi->port.irq, pi);}static void mpsc_set_termios(struct uart_port *port, struct ktermios *termios,		 struct ktermios *old){	struct mpsc_port_info *pi = (struct mpsc_port_info *)port;	u32 baud;	ulong flags;	u32 chr_bits, stop_bits, par;	pi->c_iflag = termios->c_iflag;	pi->c_cflag = termios->c_cflag;	switch (termios->c_cflag & CSIZE) {	case CS5:		chr_bits = MPSC_MPCR_CL_5;		break;	case CS6:		chr_bits = MPSC_MPCR_CL_6;		break;	case CS7:		chr_bits = MPSC_MPCR_CL_7;		break;	case CS8:	default:		chr_bits = MPSC_MPCR_CL_8;		break;	}	if (termios->c_cflag & CSTOPB)		stop_bits = MPSC_MPCR_SBL_2;	else		stop_bits = MPSC_MPCR_SBL_1;	par = MPSC_CHR_2_PAR_EVEN;	if (termios->c_cflag & PARENB)		if (termios->c_cflag & PARODD)			par = MPSC_CHR_2_PAR_ODD;#ifdef	CMSPAR		if (termios->c_cflag & CMSPAR) {			if (termios->c_cflag & PARODD)				par = MPSC_CHR_2_PAR_MARK;			else				par = MPSC_CHR_2_PAR_SPACE;		}#endif	baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk);	spin_lock_irqsave(&pi->port.lock, flags);	uart_update_timeout(port, termios->c_cflag, baud);	mpsc_set_char_length(pi, chr_bits);	mpsc_set_stop_bit_length(pi, stop_bits);	mpsc_set_parity(pi, par);	mpsc_set_baudrate(pi, baud);	/* Characters/events to read */	pi->port.read_status_mask = SDMA_DESC_CMDSTAT_OR;	if (termios->c_iflag & INPCK)		pi->port.read_status_mask |= SDMA_DESC_CMDSTAT_PE			| SDMA_DESC_CMDSTAT_FR;	if (termios->c_iflag & (BRKINT | PARMRK))		pi->port.read_status_mask |= SDMA_DESC_CMDSTAT_BR;	/* Characters/events to ignore */	pi->port.ignore_status_mask = 0;	if (termios->c_iflag & IGNPAR)		pi->port.ignore_status_mask |= SDMA_DESC_CMDSTAT_PE			| SDMA_DESC_CMDSTAT_FR;	if (termios->c_iflag & IGNBRK) {		pi->port.ignore_status_mask |= SDMA_DESC_CMDSTAT_BR;		if (termios->c_iflag & IGNPAR)			pi->port.ignore_status_mask |= SDMA_DESC_CMDSTAT_OR;	}	if ((termios->c_cflag & CREAD)) {		if (!pi->rcv_data) {			pi->rcv_data = 1;			mpsc_start_rx(pi);		}	} else if (pi->rcv_data) {		mpsc_stop_rx(port);		pi->rcv_data = 0;	}	spin_unlock_irqrestore(&pi->port.lock, flags);}static const char *mpsc_type(struct uart_port *port){	pr_debug("mpsc_type[%d]: port type: %s\n", port->line,MPSC_DRIVER_NAME);	return MPSC_DRIVER_NAME;}static int mpsc_request_port(struct uart_port *port){	/* Should make chip/platform specific call */	return 0;}static void mpsc_release_port(struct uart_port *port){	struct mpsc_port_info *pi = (struct mpsc_port_info *)port;	if (pi->ready) {		mpsc_uninit_rings(pi);		mpsc_free_ring_mem(pi);		pi->ready = 0;	}}static void mpsc_config_port(struct uart_port *port, int flags){}static int mpsc_verify_port(struct uart_port *port, struct serial_struct *ser){	struct mpsc_port_info *pi = (struct mpsc_port_info *)port;	int rc = 0;	pr_debug("mpsc_verify_port[%d]: Verifying port data\n", pi->port.line);	if (ser->type != PORT_UNKNOWN && ser->type != PORT_MPSC)		rc = -EINVAL;	else if (pi->port.irq != ser->irq)		rc = -EINVAL;	else if (ser->io_type != SERIAL_IO_MEM)		rc = -EINVAL;

⌨️ 快捷键说明

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