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

📄 riscom8.c

📁 powerpc内核mpc8241linux系统下char驱动程序
💻 C
📖 第 1 页 / 共 4 页
字号:
		port->IER &= ~IER_TXRDY;		rc_out(bp, CD180_IER, port->IER);		return;	}		if (port->break_length)  {		if (port->break_length > 0)  {			if (port->COR2 & COR2_ETC)  {				rc_out(bp, CD180_TDR, CD180_C_ESC);				rc_out(bp, CD180_TDR, CD180_C_SBRK);				port->COR2 &= ~COR2_ETC;			}			count = MIN(port->break_length, 0xff);			rc_out(bp, CD180_TDR, CD180_C_ESC);			rc_out(bp, CD180_TDR, CD180_C_DELAY);			rc_out(bp, CD180_TDR, count);			if (!(port->break_length -= count))				port->break_length--;		} else  {			rc_out(bp, CD180_TDR, CD180_C_ESC);			rc_out(bp, CD180_TDR, CD180_C_EBRK);			rc_out(bp, CD180_COR2, port->COR2);			rc_wait_CCR(bp);			rc_out(bp, CD180_CCR, CCR_CORCHG2);			port->break_length = 0;		}		return;	}		count = CD180_NFIFO;	do {		rc_out(bp, CD180_TDR, port->xmit_buf[port->xmit_tail++]);		port->xmit_tail = port->xmit_tail & (SERIAL_XMIT_SIZE-1);		if (--port->xmit_cnt <= 0)			break;	} while (--count > 0);		if (port->xmit_cnt <= 0)  {		rc_out(bp, CD180_CAR, port_No(port));		port->IER &= ~IER_TXRDY;		rc_out(bp, CD180_IER, port->IER);	}	if (port->xmit_cnt <= port->wakeup_chars)		rc_mark_event(port, RS_EVENT_WRITE_WAKEUP);}extern inline void rc_check_modem(struct riscom_board const * bp){	struct riscom_port *port;	struct tty_struct *tty;	unsigned char mcr;		if (!(port = rc_get_port(bp, "Modem")))		return;		tty = port->tty;		mcr = rc_in(bp, CD180_MCR);	if (mcr & MCR_CDCHG)  {		if (rc_in(bp, CD180_MSVR) & MSVR_CD) 			wake_up_interruptible(&port->open_wait);		else if (!((port->flags & ASYNC_CALLOUT_ACTIVE) &&			   (port->flags & ASYNC_CALLOUT_NOHUP)))			queue_task(&port->tqueue_hangup,  &tq_scheduler);      	}	#ifdef RISCOM_BRAIN_DAMAGED_CTS	if (mcr & MCR_CTSCHG)  {		if (rc_in(bp, CD180_MSVR) & MSVR_CTS)  {			tty->hw_stopped = 0;			port->IER |= IER_TXRDY;			if (port->xmit_cnt <= port->wakeup_chars)				rc_mark_event(port, RS_EVENT_WRITE_WAKEUP);		} else  {			tty->hw_stopped = 1;			port->IER &= ~IER_TXRDY;		}		rc_out(bp, CD180_IER, port->IER);	}	if (mcr & MCR_DSRCHG)  {		if (rc_in(bp, CD180_MSVR) & MSVR_DSR)  {			tty->hw_stopped = 0;			port->IER |= IER_TXRDY;			if (port->xmit_cnt <= port->wakeup_chars)				rc_mark_event(port, RS_EVENT_WRITE_WAKEUP);		} else  {			tty->hw_stopped = 1;			port->IER &= ~IER_TXRDY;		}		rc_out(bp, CD180_IER, port->IER);	}#endif /* RISCOM_BRAIN_DAMAGED_CTS */		/* Clear change bits */	rc_out(bp, CD180_MCR, 0);}/* The main interrupt processing routine */static void rc_interrupt(int irq, void * dev_id, struct pt_regs * regs){	unsigned char status;	unsigned char ack;	struct riscom_board *bp;	unsigned long loop = 0;		bp = IRQ_to_board[irq];		if (!bp || !(bp->flags & RC_BOARD_ACTIVE))  {		return;	}		while ((++loop < 16) && ((status = ~(rc_in(bp, RC_BSR))) &				 (RC_BSR_TOUT | RC_BSR_TINT |				  RC_BSR_MINT | RC_BSR_RINT))) {			if (status & RC_BSR_TOUT) 			printk("rc%d: Got timeout. Hardware error ?\n", board_No(bp));				else if (status & RC_BSR_RINT) {			ack = rc_in(bp, RC_ACK_RINT);					if (ack == (RC_ID | GIVR_IT_RCV))				rc_receive(bp);			else if (ack == (RC_ID | GIVR_IT_REXC))				rc_receive_exc(bp);			else				printk("rc%d: Bad receive ack 0x%02x.\n",				       board_No(bp), ack);				} else if (status & RC_BSR_TINT) {			ack = rc_in(bp, RC_ACK_TINT);					if (ack == (RC_ID | GIVR_IT_TX))				rc_transmit(bp);			else				printk("rc%d: Bad transmit ack 0x%02x.\n",				       board_No(bp), ack);				} else /* if (status & RC_BSR_MINT) */ {			ack = rc_in(bp, RC_ACK_MINT);					if (ack == (RC_ID | GIVR_IT_MODEM)) 				rc_check_modem(bp);			else				printk("rc%d: Bad modem ack 0x%02x.\n",				       board_No(bp), ack);				} 		rc_out(bp, CD180_EOIR, 0);   /* Mark end of interrupt */		rc_out(bp, RC_CTOUT, 0);     /* Clear timeout flag    */	}}/* *  Routines for open & close processing. *//* Called with disabled interrupts */extern inline int rc_setup_board(struct riscom_board * bp){	int error;	if (bp->flags & RC_BOARD_ACTIVE) 		return 0;		error = request_irq(bp->irq, rc_interrupt, SA_INTERRUPT, "RISCom/8", NULL);	if (error) 		return error;		rc_out(bp, RC_CTOUT, 0);       		/* Just in case         */	bp->DTR = ~0;	rc_out(bp, RC_DTR, bp->DTR);	        /* Drop DTR on all ports */		IRQ_to_board[bp->irq] = bp;	bp->flags |= RC_BOARD_ACTIVE;		MOD_INC_USE_COUNT;	return 0;}/* Called with disabled interrupts */extern inline void rc_shutdown_board(struct riscom_board *bp){	if (!(bp->flags & RC_BOARD_ACTIVE))		return;		bp->flags &= ~RC_BOARD_ACTIVE;		free_irq(bp->irq, NULL);	IRQ_to_board[bp->irq] = NULL;		bp->DTR = ~0;	rc_out(bp, RC_DTR, bp->DTR);	       /* Drop DTR on all ports */		MOD_DEC_USE_COUNT;}/* * Setting up port characteristics.  * Must be called with disabled interrupts */static void rc_change_speed(struct riscom_board *bp, struct riscom_port *port){	struct tty_struct *tty;	unsigned long baud;	long tmp;	unsigned char cor1 = 0, cor3 = 0;	unsigned char mcor1 = 0, mcor2 = 0;		if (!(tty = port->tty) || !tty->termios)		return;	port->IER  = 0;	port->COR2 = 0;	port->MSVR = MSVR_RTS;		baud = C_BAUD(tty);		if (baud & CBAUDEX) {		baud &= ~CBAUDEX;		if (baud < 1 || baud > 2) 			port->tty->termios->c_cflag &= ~CBAUDEX;		else			baud += 15;	}	if (baud == 15)  {		if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)			baud ++;		if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)			baud += 2;	}		/* Select port on the board */	rc_out(bp, CD180_CAR, port_No(port));		if (!baud_table[baud])  {		/* Drop DTR & exit */		bp->DTR |= (1u << port_No(port));		rc_out(bp, RC_DTR, bp->DTR);		return;	} else  {		/* Set DTR on */		bp->DTR &= ~(1u << port_No(port));		rc_out(bp, RC_DTR, bp->DTR);	}		/*	 * Now we must calculate some speed depended things 	 */		/* Set baud rate for port */	tmp = (((RC_OSCFREQ + baud_table[baud]/2) / baud_table[baud] +		CD180_TPC/2) / CD180_TPC);	rc_out(bp, CD180_RBPRH, (tmp >> 8) & 0xff); 	rc_out(bp, CD180_TBPRH, (tmp >> 8) & 0xff); 	rc_out(bp, CD180_RBPRL, tmp & 0xff); 	rc_out(bp, CD180_TBPRL, tmp & 0xff);		baud = (baud_table[baud] + 5) / 10;   /* Estimated CPS */		/* Two timer ticks seems enough to wakeup something like SLIP driver */	tmp = ((baud + HZ/2) / HZ) * 2 - CD180_NFIFO;			port->wakeup_chars = (tmp < 0) ? 0 : ((tmp >= SERIAL_XMIT_SIZE) ?					      SERIAL_XMIT_SIZE - 1 : tmp);		/* Receiver timeout will be transmission time for 1.5 chars */	tmp = (RISCOM_TPS + RISCOM_TPS/2 + baud/2) / baud;	tmp = (tmp > 0xff) ? 0xff : tmp;	rc_out(bp, CD180_RTPR, tmp);		switch (C_CSIZE(tty))  {	 case CS5:		cor1 |= COR1_5BITS;		break;	 case CS6:		cor1 |= COR1_6BITS;		break;	 case CS7:		cor1 |= COR1_7BITS;		break;	 case CS8:		cor1 |= COR1_8BITS;		break;	}		if (C_CSTOPB(tty)) 		cor1 |= COR1_2SB;		cor1 |= COR1_IGNORE;	if (C_PARENB(tty))  {		cor1 |= COR1_NORMPAR;		if (C_PARODD(tty)) 			cor1 |= COR1_ODDP;		if (I_INPCK(tty)) 			cor1 &= ~COR1_IGNORE;	}	/* Set marking of some errors */	port->mark_mask = RCSR_OE | RCSR_TOUT;	if (I_INPCK(tty)) 		port->mark_mask |= RCSR_FE | RCSR_PE;	if (I_BRKINT(tty) || I_PARMRK(tty)) 		port->mark_mask |= RCSR_BREAK;	if (I_IGNPAR(tty)) 		port->mark_mask &= ~(RCSR_FE | RCSR_PE);	if (I_IGNBRK(tty))  {		port->mark_mask &= ~RCSR_BREAK;		if (I_IGNPAR(tty)) 			/* Real raw mode. Ignore all */			port->mark_mask &= ~RCSR_OE;	}	/* Enable Hardware Flow Control */	if (C_CRTSCTS(tty))  {#ifdef RISCOM_BRAIN_DAMAGED_CTS		port->IER |= IER_DSR | IER_CTS;		mcor1 |= MCOR1_DSRZD | MCOR1_CTSZD;		mcor2 |= MCOR2_DSROD | MCOR2_CTSOD;		tty->hw_stopped = !(rc_in(bp, CD180_MSVR) & (MSVR_CTS|MSVR_DSR));#else		port->COR2 |= COR2_CTSAE;#endif	}	/* Enable Software Flow Control. FIXME: I'm not sure about this */	/* Some people reported that it works, but I still doubt */	if (I_IXON(tty))  {		port->COR2 |= COR2_TXIBE;		cor3 |= (COR3_FCT | COR3_SCDE);		if (I_IXANY(tty))			port->COR2 |= COR2_IXM;		rc_out(bp, CD180_SCHR1, START_CHAR(tty));		rc_out(bp, CD180_SCHR2, STOP_CHAR(tty));		rc_out(bp, CD180_SCHR3, START_CHAR(tty));		rc_out(bp, CD180_SCHR4, STOP_CHAR(tty));	}	if (!C_CLOCAL(tty))  {		/* Enable CD check */		port->IER |= IER_CD;		mcor1 |= MCOR1_CDZD;		mcor2 |= MCOR2_CDOD;	}		if (C_CREAD(tty)) 		/* Enable receiver */		port->IER |= IER_RXD;		/* Set input FIFO size (1-8 bytes) */	cor3 |= RISCOM_RXFIFO; 	/* Setting up CD180 channel registers */	rc_out(bp, CD180_COR1, cor1);	rc_out(bp, CD180_COR2, port->COR2);	rc_out(bp, CD180_COR3, cor3);	/* Make CD180 know about registers change */	rc_wait_CCR(bp);	rc_out(bp, CD180_CCR, CCR_CORCHG1 | CCR_CORCHG2 | CCR_CORCHG3);	/* Setting up modem option registers */	rc_out(bp, CD180_MCOR1, mcor1);	rc_out(bp, CD180_MCOR2, mcor2);	/* Enable CD180 transmitter & receiver */	rc_wait_CCR(bp);	rc_out(bp, CD180_CCR, CCR_TXEN | CCR_RXEN);	/* Enable interrupts */	rc_out(bp, CD180_IER, port->IER);	/* And finally set RTS on */	rc_out(bp, CD180_MSVR, port->MSVR);}/* Must be called with interrupts enabled */static int rc_setup_port(struct riscom_board *bp, struct riscom_port *port){	unsigned long flags;		if (port->flags & ASYNC_INITIALIZED)		return 0;		if (!port->xmit_buf) {		/* We may sleep in get_free_page() */		unsigned long tmp;				if (!(tmp = get_free_page(GFP_KERNEL)))			return -ENOMEM;		    		if (port->xmit_buf) {			free_page(tmp);			return -ERESTARTSYS;		}		port->xmit_buf = (unsigned char *) tmp;	}			save_flags(flags); cli();			if (port->tty) 		clear_bit(TTY_IO_ERROR, &port->tty->flags);			if (port->count == 1) 		bp->count++;			port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;	rc_change_speed(bp, port);	port->flags |= ASYNC_INITIALIZED;			restore_flags(flags);	return 0;}/* Must be called with interrupts disabled */static void rc_shutdown_port(struct riscom_board *bp, struct riscom_port *port){	struct tty_struct *tty;		if (!(port->flags & ASYNC_INITIALIZED)) 		return;	#ifdef RC_REPORT_OVERRUN	printk("rc%d: port %d: Total %ld overruns were detected.\n",	       board_No(bp), port_No(port), port->overrun);#endif	#ifdef RC_REPORT_FIFO	{		int i;				printk("rc%d: port %d: FIFO hits [ ",		       board_No(bp), port_No(port));		for (i = 0; i < 10; i++)  {			printk("%ld ", port->hits[i]);		}		printk("].\n");	}#endif		if (port->xmit_buf)  {		free_page((unsigned long) port->xmit_buf);		port->xmit_buf = NULL;	}	if (!(tty = port->tty) || C_HUPCL(tty))  {		/* Drop DTR */		bp->DTR |= (1u << port_No(port));		rc_out(bp, RC_DTR, bp->DTR);	}	        /* Select port */	rc_out(bp, CD180_CAR, port_No(port));	/* Reset port */	rc_wait_CCR(bp);	rc_out(bp, CD180_CCR, CCR_SOFTRESET);	/* Disable all interrupts from this port */	port->IER = 0;	rc_out(bp, CD180_IER, port->IER);		if (tty)  		set_bit(TTY_IO_ERROR, &tty->flags);	port->flags &= ~ASYNC_INITIALIZED;		if (--bp->count < 0)  {		printk("rc%d: rc_shutdown_port: bad board count: %d\n",		       board_No(bp), bp->count);		bp->count = 0;	}		/*	 * If this is the last opened port on the board	 * shutdown whole board	 */	if (!bp->count) 		rc_shutdown_board(bp);}	static int block_til_ready(struct tty_struct *tty, struct file * filp,			   struct riscom_port *port){	struct wait_queue wait = { current, NULL };	struct riscom_board *bp = port_Board(port);	int    retval;	int    do_clocal = 0;	int    CD;

⌨️ 快捷键说明

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