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

📄 riscom8.c

📁 powerpc内核mpc8241linux系统下char驱动程序
💻 C
📖 第 1 页 / 共 4 页
字号:
	copy_from_user(&tmp, newinfo, sizeof(tmp));	#if 0		if ((tmp.irq != bp->irq) ||	    (tmp.port != bp->base) ||	    (tmp.type != PORT_CIRRUS) ||	    (tmp.baud_base != (RC_OSCFREQ + CD180_TPC/2) / CD180_TPC) ||	    (tmp.custom_divisor != 0) ||	    (tmp.xmit_fifo_size != CD180_NFIFO) ||	    (tmp.flags & ~RISCOM_LEGAL_FLAGS))		return -EINVAL;#endif			change_speed = ((port->flags & ASYNC_SPD_MASK) !=			(tmp.flags & ASYNC_SPD_MASK));		if (!capable(CAP_SYS_ADMIN)) {		if ((tmp.close_delay != port->close_delay) ||		    (tmp.closing_wait != port->closing_wait) ||		    ((tmp.flags & ~ASYNC_USR_MASK) !=		     (port->flags & ~ASYNC_USR_MASK)))  			return -EPERM;		port->flags = ((port->flags & ~ASYNC_USR_MASK) |			       (tmp.flags & ASYNC_USR_MASK));	} else  {		port->flags = ((port->flags & ~ASYNC_FLAGS) |			       (tmp.flags & ASYNC_FLAGS));		port->close_delay = tmp.close_delay;		port->closing_wait = tmp.closing_wait;	}	if (change_speed)  {		save_flags(flags); cli();		rc_change_speed(bp, port);		restore_flags(flags);	}	return 0;}extern inline int rc_get_serial_info(struct riscom_port * port,				     struct serial_struct * retinfo){	struct serial_struct tmp;	struct riscom_board *bp = port_Board(port);	int error;		error = verify_area(VERIFY_WRITE, (void *) retinfo, sizeof(tmp));	if (error)		return error;		memset(&tmp, 0, sizeof(tmp));	tmp.type = PORT_CIRRUS;	tmp.line = port - rc_port;	tmp.port = bp->base;	tmp.irq  = bp->irq;	tmp.flags = port->flags;	tmp.baud_base = (RC_OSCFREQ + CD180_TPC/2) / CD180_TPC;	tmp.close_delay = port->close_delay * HZ/100;	tmp.closing_wait = port->closing_wait * HZ/100;	tmp.xmit_fifo_size = CD180_NFIFO;	copy_to_user(retinfo, &tmp, sizeof(tmp));	return 0;}static int rc_ioctl(struct tty_struct * tty, struct file * filp, 		    unsigned int cmd, unsigned long arg)		    {	struct riscom_port *port = (struct riscom_port *)tty->driver_data;	int error;	int retval;					if (rc_paranoia_check(port, tty->device, "rc_ioctl"))		return -ENODEV;		switch (cmd) {	 case TCSBRK:	/* SVID version: non-zero arg --> no break */		retval = tty_check_change(tty);		if (retval)			return retval;		tty_wait_until_sent(tty, 0);		if (!arg)			rc_send_break(port, HZ/4);	/* 1/4 second */		return 0;	 case TCSBRKP:	/* support for POSIX tcsendbreak() */		retval = tty_check_change(tty);		if (retval)			return retval;		tty_wait_until_sent(tty, 0);		rc_send_break(port, arg ? arg*(HZ/10) : HZ/4);		return 0;	 case TIOCGSOFTCAR:		return put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned int *) arg);	 case TIOCSSOFTCAR:		retval = get_user(arg,(unsigned int *) arg);		if (retval)			return retval;		tty->termios->c_cflag =			((tty->termios->c_cflag & ~CLOCAL) |			(arg ? CLOCAL : 0));		return 0;	 case TIOCMGET:		error = verify_area(VERIFY_WRITE, (void *) arg,				    sizeof(unsigned int));		if (error)			return error;		return rc_get_modem_info(port, (unsigned int *) arg);	 case TIOCMBIS:	 case TIOCMBIC:	 case TIOCMSET:		return rc_set_modem_info(port, cmd, (unsigned int *) arg);	 case TIOCGSERIAL:			return rc_get_serial_info(port, (struct serial_struct *) arg);	 case TIOCSSERIAL:			return rc_set_serial_info(port, (struct serial_struct *) arg);	 default:		return -ENOIOCTLCMD;	}	return 0;}static void rc_throttle(struct tty_struct * tty){	struct riscom_port *port = (struct riscom_port *)tty->driver_data;	struct riscom_board *bp;	unsigned long flags;					if (rc_paranoia_check(port, tty->device, "rc_throttle"))		return;		bp = port_Board(port);		save_flags(flags); cli();	port->MSVR &= ~MSVR_RTS;	rc_out(bp, CD180_CAR, port_No(port));	if (I_IXOFF(tty))  {		rc_wait_CCR(bp);		rc_out(bp, CD180_CCR, CCR_SSCH2);		rc_wait_CCR(bp);	}	rc_out(bp, CD180_MSVR, port->MSVR);	restore_flags(flags);}static void rc_unthrottle(struct tty_struct * tty){	struct riscom_port *port = (struct riscom_port *)tty->driver_data;	struct riscom_board *bp;	unsigned long flags;					if (rc_paranoia_check(port, tty->device, "rc_unthrottle"))		return;		bp = port_Board(port);		save_flags(flags); cli();	port->MSVR |= MSVR_RTS;	rc_out(bp, CD180_CAR, port_No(port));	if (I_IXOFF(tty))  {		rc_wait_CCR(bp);		rc_out(bp, CD180_CCR, CCR_SSCH1);		rc_wait_CCR(bp);	}	rc_out(bp, CD180_MSVR, port->MSVR);	restore_flags(flags);}static void rc_stop(struct tty_struct * tty){	struct riscom_port *port = (struct riscom_port *)tty->driver_data;	struct riscom_board *bp;	unsigned long flags;					if (rc_paranoia_check(port, tty->device, "rc_stop"))		return;		bp = port_Board(port);		save_flags(flags); cli();	port->IER &= ~IER_TXRDY;	rc_out(bp, CD180_CAR, port_No(port));	rc_out(bp, CD180_IER, port->IER);	restore_flags(flags);}static void rc_start(struct tty_struct * tty){	struct riscom_port *port = (struct riscom_port *)tty->driver_data;	struct riscom_board *bp;	unsigned long flags;					if (rc_paranoia_check(port, tty->device, "rc_start"))		return;		bp = port_Board(port);		save_flags(flags); cli();	if (port->xmit_cnt && port->xmit_buf && !(port->IER & IER_TXRDY))  {		port->IER |= IER_TXRDY;		rc_out(bp, CD180_CAR, port_No(port));		rc_out(bp, CD180_IER, port->IER);	}	restore_flags(flags);}/* * This routine is called from the scheduler tqueue when the interrupt * routine has signalled that a hangup has occurred.  The path of * hangup processing is: * * 	serial interrupt routine -> (scheduler tqueue) -> * 	do_rc_hangup() -> tty->hangup() -> rc_hangup() *  */static void do_rc_hangup(void *private_){	struct riscom_port	*port = (struct riscom_port *) private_;	struct tty_struct	*tty;		tty = port->tty;	if (!tty)		return;	tty_hangup(tty);}static void rc_hangup(struct tty_struct * tty){	struct riscom_port *port = (struct riscom_port *)tty->driver_data;	struct riscom_board *bp;					if (rc_paranoia_check(port, tty->device, "rc_hangup"))		return;		bp = port_Board(port);		rc_shutdown_port(bp, port);	port->event = 0;	port->count = 0;	port->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE);	port->tty = 0;	wake_up_interruptible(&port->open_wait);}static void rc_set_termios(struct tty_struct * tty, struct termios * old_termios){	struct riscom_port *port = (struct riscom_port *)tty->driver_data;	unsigned long flags;					if (rc_paranoia_check(port, tty->device, "rc_set_termios"))		return;		if (tty->termios->c_cflag == old_termios->c_cflag &&	    tty->termios->c_iflag == old_termios->c_iflag)		return;	save_flags(flags); cli();	rc_change_speed(port_Board(port), port);	restore_flags(flags);	if ((old_termios->c_cflag & CRTSCTS) &&	    !(tty->termios->c_cflag & CRTSCTS)) {		tty->hw_stopped = 0;		rc_start(tty);	}}static void do_riscom_bh(void){	 run_task_queue(&tq_riscom);}static void do_softint(void *private_){	struct riscom_port	*port = (struct riscom_port *) private_;	struct tty_struct	*tty;		if(!(tty = port->tty)) 		return;	if (test_and_clear_bit(RS_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);	}}static inline int rc_init_drivers(void){	int error;	int i;		if (!(tmp_buf = (unsigned char *) get_free_page(GFP_KERNEL))) {		printk("rc: Couldn't get free page.\n");		return 1;	}	init_bh(RISCOM8_BH, do_riscom_bh);	memset(IRQ_to_board, 0, sizeof(IRQ_to_board));	memset(&riscom_driver, 0, sizeof(riscom_driver));	riscom_driver.magic = TTY_DRIVER_MAGIC;	riscom_driver.name = "ttyL";	riscom_driver.major = RISCOM8_NORMAL_MAJOR;	riscom_driver.num = RC_NBOARD * RC_NPORT;	riscom_driver.type = TTY_DRIVER_TYPE_SERIAL;	riscom_driver.subtype = RISCOM_TYPE_NORMAL;	riscom_driver.init_termios = tty_std_termios;	riscom_driver.init_termios.c_cflag =		B9600 | CS8 | CREAD | HUPCL | CLOCAL;	riscom_driver.flags = TTY_DRIVER_REAL_RAW;	riscom_driver.refcount = &riscom_refcount;	riscom_driver.table = riscom_table;	riscom_driver.termios = riscom_termios;	riscom_driver.termios_locked = riscom_termios_locked;	riscom_driver.open  = rc_open;	riscom_driver.close = rc_close;	riscom_driver.write = rc_write;	riscom_driver.put_char = rc_put_char;	riscom_driver.flush_chars = rc_flush_chars;	riscom_driver.write_room = rc_write_room;	riscom_driver.chars_in_buffer = rc_chars_in_buffer;	riscom_driver.flush_buffer = rc_flush_buffer;	riscom_driver.ioctl = rc_ioctl;	riscom_driver.throttle = rc_throttle;	riscom_driver.unthrottle = rc_unthrottle;	riscom_driver.set_termios = rc_set_termios;	riscom_driver.stop = rc_stop;	riscom_driver.start = rc_start;	riscom_driver.hangup = rc_hangup;	riscom_callout_driver = riscom_driver;	riscom_callout_driver.name = "cul";	riscom_callout_driver.major = RISCOM8_CALLOUT_MAJOR;	riscom_callout_driver.subtype = RISCOM_TYPE_CALLOUT;		if ((error = tty_register_driver(&riscom_driver)))  {		free_page((unsigned long)tmp_buf);		printk("rc: Couldn't register RISCom/8 driver, error = %d\n",		       error);		return 1;	}	if ((error = tty_register_driver(&riscom_callout_driver)))  {		free_page((unsigned long)tmp_buf);		tty_unregister_driver(&riscom_driver);		printk("rc: Couldn't register RISCom/8 callout driver, error = %d\n",		       error);		return 1;	}		memset(rc_port, 0, sizeof(rc_port));	for (i = 0; i < RC_NPORT * RC_NBOARD; i++)  {		rc_port[i].callout_termios = riscom_callout_driver.init_termios;		rc_port[i].normal_termios  = riscom_driver.init_termios;		rc_port[i].magic = RISCOM8_MAGIC;		rc_port[i].tqueue.routine = do_softint;		rc_port[i].tqueue.data = &rc_port[i];		rc_port[i].tqueue_hangup.routine = do_rc_hangup;		rc_port[i].tqueue_hangup.data = &rc_port[i];		rc_port[i].close_delay = 50 * HZ/100;		rc_port[i].closing_wait = 3000 * HZ/100;	}		return 0;}static void rc_release_drivers(void){	unsigned long flags;	save_flags(flags);	cli();	remove_bh(RISCOM8_BH);	free_page((unsigned long)tmp_buf);	tty_unregister_driver(&riscom_driver);	tty_unregister_driver(&riscom_callout_driver);	restore_flags(flags);}#ifndef MODULE/* * Called at boot time. *  * You can specify IO base for up to RC_NBOARD cards, * using line "riscom8=0xiobase1,0xiobase2,.." at LILO prompt. * Note that there will be no probing at default * addresses in this case. * */ __initfunc(void riscom8_setup(char *str, int * ints)){	int i;	for (i = 0; i < RC_NBOARD; i++) {		if (i < ints[0])			rc_board[i].base = ints[i+1];		else 			rc_board[i].base = 0;	}}#endif/*  * This routine must be called by kernel at boot time  */__initfunc(int riscom8_init(void)){	int i;	int found = 0;	printk("rc: SDL RISCom/8 card driver v1.0, (c) D.Gorodchanin 1994-1996.\n");	if (rc_init_drivers()) 		return -EIO;	for (i = 0; i < RC_NBOARD; i++) 		if (rc_board[i].base && !rc_probe(&rc_board[i]))  			found++;		if (!found)  {		rc_release_drivers();		printk("rc: No RISCom/8 boards detected.\n");		return -EIO;	}	return 0;}#ifdef MODULEint iobase  = 0;int iobase1 = 0;int iobase2 = 0;int iobase3 = 0;MODULE_PARM(iobase, "i");MODULE_PARM(iobase1, "i");MODULE_PARM(iobase2, "i");MODULE_PARM(iobase3, "i");/* * You can setup up to 4 boards (current value of RC_NBOARD) * by specifying "iobase=0xXXX iobase1=0xXXX ..." as insmod parameter. * */int init_module(void) {	int i;	if (iobase || iobase1 || iobase2 || iobase3) {		for(i = 0; i < RC_NBOARD; i++)			rc_board[0].base = 0;	}	if (iobase)		rc_board[0].base = iobase;	if (iobase1)		rc_board[1].base = iobase1;	if (iobase2)		rc_board[2].base = iobase2;	if (iobase3)		rc_board[3].base = iobase3;		return riscom8_init();}	void cleanup_module(void){	int i;		rc_release_drivers();	for (i = 0; i < RC_NBOARD; i++)  		if (rc_board[i].flags & RC_BOARD_PRESENT) 			rc_release_io_range(&rc_board[i]);	}#endif /* MODULE */

⌨️ 快捷键说明

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