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

📄 macserial.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 5 页
字号:
 * This workaround attempts to recover from the lockup condition by placing * the SCC in synchronous loopback mode with a fast clock before programming * any of the asynchronous modes. */static void fix_zero_bug_scc(struct mac_serial * info){	write_zsreg(info->zs_channel, 9,		    (info->zs_channel == info->zs_chan_a? CHRA: CHRB));	udelay(10);	write_zsreg(info->zs_channel, 9,		    ((info->zs_channel == info->zs_chan_a? CHRA: CHRB) | NV));	write_zsreg(info->zs_channel, 4, (X1CLK | EXTSYNC));	/* I think this is wrong....but, I just copying code....	*/	write_zsreg(info->zs_channel, 3, (8 & ~RxENABLE));	write_zsreg(info->zs_channel, 5, (8 & ~TxENAB));	write_zsreg(info->zs_channel, 9, NV);	/* Didn't we already do this? */	write_zsreg(info->zs_channel, 11, (RCBR | TCBR));	write_zsreg(info->zs_channel, 12, 0);	write_zsreg(info->zs_channel, 13, 0);	write_zsreg(info->zs_channel, 14, (LOOPBAK | SSBR));	write_zsreg(info->zs_channel, 14, (LOOPBAK | SSBR | BRENABL));	write_zsreg(info->zs_channel, 3, (8 | RxENABLE));	write_zsreg(info->zs_channel, 0, RES_EXT_INT);	write_zsreg(info->zs_channel, 0, RES_EXT_INT);	/* to kill some time */	/* The channel should be OK now, but it is probably receiving	 * loopback garbage.	 * Switch to asynchronous mode, disable the receiver,	 * and discard everything in the receive buffer.	 */	write_zsreg(info->zs_channel, 9, NV);	write_zsreg(info->zs_channel, 4, PAR_ENA);	write_zsreg(info->zs_channel, 3, (8 & ~RxENABLE));	while (read_zsreg(info->zs_channel, 0) & Rx_CH_AV) {		(void)read_zsreg(info->zs_channel, 8);		write_zsreg(info->zs_channel, 0, RES_EXT_INT);		write_zsreg(info->zs_channel, 0, ERR_RES);	}}static int setup_scc(struct mac_serial * info){	unsigned long flags;	OPNDBG("setting up ttyS%d SCC...\n", info->line);	save_flags(flags); cli(); /* Disable interrupts */	/* Nice buggy HW ... */	fix_zero_bug_scc(info);	/*	 * Reset the chip.	 */	write_zsreg(info->zs_channel, 9,		    (info->zs_channel == info->zs_chan_a? CHRA: CHRB));	udelay(10);	write_zsreg(info->zs_channel, 9, 0);	/*	 * Clear the receive FIFO.	 */	ZS_CLEARFIFO(info->zs_channel);	info->xmit_fifo_size = 1;	/*	 * Reset DMAs	 */	if (info->has_dma)		dma_init(info);	/*	 * Clear the interrupt registers.	 */	write_zsreg(info->zs_channel, 0, ERR_RES);	write_zsreg(info->zs_channel, 0, RES_H_IUS);	/*	 * Turn on RTS and DTR.	 */	if (!info->is_irda)		zs_rtsdtr(info, 1);	/*	 * Finally, enable sequencing and interrupts	 */	if (!info->dma_initted) {		/* interrupt on ext/status changes, all received chars,		   transmit ready */		info->curregs[1] = (info->curregs[1] & ~0x18)				| (EXT_INT_ENAB | INT_ALL_Rx | TxINT_ENAB);	} else {		/* interrupt on ext/status changes, W/Req pin is		   receive DMA request */		info->curregs[1] = (info->curregs[1] & ~(0x18 | TxINT_ENAB))				| (EXT_INT_ENAB | WT_RDY_RT | WT_FN_RDYFN);		write_zsreg(info->zs_channel, 1, info->curregs[1]);		/* enable W/Req pin */		info->curregs[1] |= WT_RDY_ENAB;		write_zsreg(info->zs_channel, 1, info->curregs[1]);		/* enable interrupts on transmit ready and receive errors */		info->curregs[1] |= INT_ERR_Rx | TxINT_ENAB;	}	info->pendregs[1] = info->curregs[1];	info->curregs[3] |= (RxENABLE | Rx8);	info->pendregs[3] = info->curregs[3];	info->curregs[5] |= (TxENAB | Tx8);	info->pendregs[5] = info->curregs[5];	info->curregs[9] |= (NV | MIE);	info->pendregs[9] = info->curregs[9];	write_zsreg(info->zs_channel, 3, info->curregs[3]);	write_zsreg(info->zs_channel, 5, info->curregs[5]);	write_zsreg(info->zs_channel, 9, info->curregs[9]);	if (info->tty)		clear_bit(TTY_IO_ERROR, &info->tty->flags);	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;	/*	 * Set the speed of the serial port	 */	change_speed(info, 0);	/* Save the current value of RR0 */	info->read_reg_zero = read_zsreg(info->zs_channel, 0);	restore_flags(flags);	if (info->dma_initted) {		spin_lock_irqsave(&info->rx_dma_lock, flags);		rxdma_start(info, 0);		info->poll_dma_timer.expires = RX_DMA_TIMER;		add_timer(&info->poll_dma_timer);		spin_unlock_irqrestore(&info->rx_dma_lock, flags);	}	return 0;}/* * This routine will shutdown a serial port; interrupts are disabled, and * DTR is dropped if the hangup on close termio flag is on. */static void shutdown(struct mac_serial * info){	OPNDBG("Shutting down serial port %d (irq %d)....\n", info->line,	       info->irq);	if (!(info->flags & ZILOG_INITIALIZED)) {		OPNDBG("(already shutdown)\n");		return;	}	if (info->has_dma) {		del_timer(&info->poll_dma_timer);		dbdma_reset(info->tx_dma);		dbdma_reset(&info->rx->dma);		disable_irq(info->tx_dma_irq);		disable_irq(info->rx_dma_irq);	}	disable_irq(info->irq);	info->pendregs[1] = info->curregs[1] = 0;	write_zsreg(info->zs_channel, 1, 0);	/* no interrupts */	info->curregs[3] &= ~RxENABLE;	info->pendregs[3] = info->curregs[3];	write_zsreg(info->zs_channel, 3, info->curregs[3]);	info->curregs[5] &= ~TxENAB;	if (!info->tty || C_HUPCL(info->tty))		info->curregs[5] &= ~DTR;	info->pendregs[5] = info->curregs[5];	write_zsreg(info->zs_channel, 5, info->curregs[5]);	if (info->tty)		set_bit(TTY_IO_ERROR, &info->tty->flags);	set_scc_power(info, 0);	if (info->xmit_buf) {		free_page((unsigned long) info->xmit_buf);		info->xmit_buf = 0;	}	if (info->has_dma && info->dma_priv) {		kfree(info->dma_priv);		info->dma_priv = NULL;		info->dma_initted = 0;	}	memset(info->curregs, 0, sizeof(info->curregs));	memset(info->pendregs, 0, sizeof(info->pendregs));	info->flags &= ~ZILOG_INITIALIZED;}/* * Turn power on or off to the SCC and associated stuff * (port drivers, modem, IR port, etc.) * Returns the number of milliseconds we should wait before * trying to use the port. */static int set_scc_power(struct mac_serial * info, int state){	int delay = 0;	if (state) {		PWRDBG("ttyS%d: powering up hardware\n", info->line);		pmac_call_feature(			PMAC_FTR_SCC_ENABLE,			info->dev_node, info->port_type, 1);		if (info->is_internal_modem) {			pmac_call_feature(				PMAC_FTR_MODEM_ENABLE,				info->dev_node, 0, 1);			delay = 2500;	/* wait for 2.5s before using */		} else if (info->is_irda)			mdelay(50);	/* Do better here once the problems			                 * with blocking have been ironed out			                 */	} else {		/* TODO: Make that depend on a timer, don't power down		 * immediately		 */		PWRDBG("ttyS%d: shutting down hardware\n", info->line);		if (info->is_internal_modem) {			PWRDBG("ttyS%d: shutting down modem\n", info->line);			pmac_call_feature(				PMAC_FTR_MODEM_ENABLE,				info->dev_node, 0, 0);		}		pmac_call_feature(			PMAC_FTR_SCC_ENABLE,			info->dev_node, info->port_type, 0);	}	return delay;}static void irda_rts_pulses(struct mac_serial *info, int w){	unsigned long flags;	udelay(w);	save_flags(flags); cli();	write_zsreg(info->zs_channel, 5, Tx8 | TxENAB);	udelay(2);	write_zsreg(info->zs_channel, 5, Tx8 | TxENAB | RTS);	udelay(8);	write_zsreg(info->zs_channel, 5, Tx8 | TxENAB);	udelay(4);	write_zsreg(info->zs_channel, 5, Tx8 | TxENAB | RTS);	restore_flags(flags);}/* * Set the irda codec on the imac to the specified baud rate. */static void irda_setup(struct mac_serial *info){	int code, speed, t;	unsigned long flags;	speed = info->tty->termios->c_cflag & CBAUD;	if (speed < B2400 || speed > B115200)		return;	code = 0x4d + B115200 - speed;	/* disable serial interrupts and receive DMA */	write_zsreg(info->zs_channel, 1, info->curregs[1] & ~0x9f);	/* wait for transmitter to drain */	t = 10000;	while ((read_zsreg(info->zs_channel, 0) & Tx_BUF_EMP) == 0	       || (read_zsreg(info->zs_channel, 1) & ALL_SNT) == 0) {		if (--t <= 0) {			printk(KERN_ERR "transmitter didn't drain\n");			return;		}		udelay(10);	}	udelay(100);	/* set to 8 bits, no parity, 19200 baud, RTS on, DTR off */	write_zsreg(info->zs_channel, 4, X16CLK | SB1);	write_zsreg(info->zs_channel, 11, TCBR | RCBR);	t = BPS_TO_BRG(19200, ZS_CLOCK/16);	write_zsreg(info->zs_channel, 12, t);	write_zsreg(info->zs_channel, 13, t >> 8);	write_zsreg(info->zs_channel, 14, BRENABL);	write_zsreg(info->zs_channel, 3, Rx8 | RxENABLE);	write_zsreg(info->zs_channel, 5, Tx8 | TxENAB | RTS);	/* set TxD low for ~104us and pulse RTS */	udelay(1000);	save_flags(flags); cli();	write_zsdata(info->zs_channel, 0xfe);	irda_rts_pulses(info, 150);	restore_flags(flags);	irda_rts_pulses(info, 180);	irda_rts_pulses(info, 50);	udelay(100);	/* assert DTR, wait 30ms, talk to the chip */	write_zsreg(info->zs_channel, 5, Tx8 | TxENAB | RTS | DTR);	mdelay(30);	while (read_zsreg(info->zs_channel, 0) & Rx_CH_AV)		read_zsdata(info->zs_channel);	write_zsdata(info->zs_channel, 1);	t = 1000;	while ((read_zsreg(info->zs_channel, 0) & Rx_CH_AV) == 0) {		if (--t <= 0) {			printk(KERN_ERR "irda_setup timed out on 1st byte\n");			goto out;		}		udelay(10);	}	t = read_zsdata(info->zs_channel);	if (t != 4)		printk(KERN_ERR "irda_setup 1st byte = %x\n", t);	write_zsdata(info->zs_channel, code);	t = 1000;	while ((read_zsreg(info->zs_channel, 0) & Rx_CH_AV) == 0) {		if (--t <= 0) {			printk(KERN_ERR "irda_setup timed out on 2nd byte\n");			goto out;		}		udelay(10);	}	t = read_zsdata(info->zs_channel);	if (t != code)		printk(KERN_ERR "irda_setup 2nd byte = %x (%x)\n", t, code);	/* Drop DTR again and do some more RTS pulses */ out:	udelay(100);	write_zsreg(info->zs_channel, 5, Tx8 | TxENAB | RTS);	irda_rts_pulses(info, 80);	/* We should be right to go now.  We assume that load_zsregs	   will get called soon to load up the correct baud rate etc. */	info->curregs[5] = (info->curregs[5] | RTS) & ~DTR;	info->pendregs[5] = info->curregs[5];}/* * 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 mac_serial *info, struct termios *old_termios){	unsigned cflag;	int	bits;	int	brg, baud;	unsigned long flags;	if (!info->tty || !info->tty->termios)		return;	cflag = info->tty->termios->c_cflag;	baud = tty_get_baud_rate(info->tty);	if (baud == 0) {		if (old_termios) {			info->tty->termios->c_cflag &= ~CBAUD;			info->tty->termios->c_cflag |= (old_termios->c_cflag & CBAUD);			cflag = info->tty->termios->c_cflag;			baud = tty_get_baud_rate(info->tty);		}		else			baud = info->zs_baud;	}	if (baud > 230400)		baud = 230400;	else if (baud == 0)		baud = 38400;	save_flags(flags); cli();	info->zs_baud = baud;	info->clk_divisor = 16;	BAUDBG(KERN_DEBUG "set speed to %d bds, ", baud);	switch (baud) {	case ZS_CLOCK/16:	/* 230400 */		info->curregs[4] = X16CLK;		info->curregs[11] = 0;		break;	case ZS_CLOCK/32:	/* 115200 */		info->curregs[4] = X32CLK;		info->curregs[11] = 0;		break;	default:		info->curregs[4] = X16CLK;		info->curregs[11] = TCBR | RCBR;		brg = BPS_TO_BRG(baud, ZS_CLOCK/info->clk_divisor);		info->curregs[12] = (brg & 255);		info->curregs[13] = ((brg >> 8) & 255);		info->curregs[14] = BRENABL;	}	/* byte size and parity */	info->curregs[3] &= ~RxNBITS_MASK;	info->curregs[5] &= ~TxNBITS_MASK;	switch (cflag & CSIZE) {	case CS5:		info->curregs[3] |= Rx5;		info->curregs[5] |= Tx5;		BAUDBG("5 bits, ");		bits = 7;		break;	case CS6:		info->curregs[3] |= Rx6;		info->curregs[5] |= Tx6;		BAUDBG("6 bits, ");		bits = 8;		break;	case CS7:		info->curregs[3] |= Rx7;		info->curregs[5] |= Tx7;		BAUDBG("7 bits, ");		bits = 9;		break;	case CS8:	default: /* defaults to 8 bits */		info->curregs[3] |= Rx8;		info->curregs[5] |= Tx8;		BAUDBG("8 bits, ");		bits = 10;		break;	}	info->pendregs[3] = info->curregs[3];	info->pendregs[5] = info->curregs[5];	info->curregs[4] &= ~(SB_MASK | PAR_ENA | PAR_EVEN);	if (cflag & CSTOPB) {		info->curregs[4] |= SB2;		bits++;		BAUDBG("2 stop, ");	} else {		info->curregs[4] |= SB1;		BAUDBG("1 stop, ");	}	if (cflag & PARENB) {		bits++; 		info->curregs[4] |= PAR_ENA;		BAUDBG("parity, ");	}	if (!(cflag & PARODD)) {		info->curregs[4] |= PAR_EVEN;	}	info->pendregs[4] = info->curregs[4];	if (!(cflag & CLOCAL)) {		if (!(info->curregs[15] & DCDIE))			info->read_reg_zero = read_zsreg(info->zs_channel, 0);		info->curregs[15] |= DCDIE;	} else		info->curregs[15] &= ~DCDIE;	if (cflag & CRTSCTS) {		info->curregs[15] |= CTSIE;		if ((read_zsreg(info->zs_channel, 0) & CTS) != 0)			info->tx_stopped = 1;	} else {		info->curregs[15] &= ~CTSIE;		info->tx_stopped = 0;	}	info->pendregs[15] = info->curregs[15];	/* Calc timeout value. This is pretty broken with high baud rates with HZ=100.	   This code would love a larger HZ and a >1 fifo size, but this is not	   a priority. The resulting value must be >HZ/2	 */	info->timeout = ((info->xmit_fifo_size*HZ*bits) / baud);	info->timeout += HZ/50+1;	/* Add .02 seconds of slop */	BAUDBG("timeout=%d/%ds, base:%d\n", (int)info->timeout, (int)HZ,	       (int)info->baud_base);	/* set the irda codec to the right rate */	if (info->is_irda)		irda_setup(info);	/* Load up the new values */	load_zsregs(info->zs_channel, info->curregs);	restore_flags(flags);

⌨️ 快捷键说明

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