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

📄 moxa.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
📖 第 1 页 / 共 5 页
字号:
	if (moxaTimer_on)		del_timer(&moxaTimer);	for (i = 0; i < MAX_PORTS; i++)		if (moxaEmptyTimer_on[i])			del_timer(&moxaEmptyTimer[i]);	if (tty_unregister_driver(moxaDriver))		printk("Couldn't unregister MOXA Intellio family serial driver\n");	put_tty_driver(moxaDriver);	if (verbose)		printk("Done\n");}module_init(moxa_init);module_exit(moxa_exit);static void do_moxa_softint(void *private_){	struct moxa_str *ch = (struct moxa_str *) private_;	struct tty_struct *tty;	if (ch && (tty = ch->tty)) {		if (test_and_clear_bit(MOXA_EVENT_HANGUP, &ch->event)) {			tty_hangup(tty);	/* FIXME: module removal race here - AKPM */			wake_up_interruptible(&ch->open_wait);			ch->asyncflags &= ~ASYNC_NORMAL_ACTIVE;		}	}}static int moxa_open(struct tty_struct *tty, struct file *filp){	struct moxa_str *ch;	int port;	int retval;	unsigned long page;	port = PORTNO(tty);	if (port == MAX_PORTS) {		return (0);	}	if (!MoxaPortIsValid(port)) {		tty->driver_data = NULL;		return (-ENODEV);	}	down(&moxaBuffSem);	if (!moxaXmitBuff) {		page = get_zeroed_page(GFP_KERNEL);		if (!page) {			up(&moxaBuffSem);			return (-ENOMEM);		}		/* This test is guarded by the BuffSem so no longer needed		   delete me in 2.5 */		if (moxaXmitBuff)			free_page(page);		else			moxaXmitBuff = (unsigned char *) page;	}	up(&moxaBuffSem);	ch = &moxaChannels[port];	ch->count++;	tty->driver_data = ch;	ch->tty = tty;	if (!(ch->asyncflags & ASYNC_INITIALIZED)) {		ch->statusflags = 0;		set_tty_param(tty);		MoxaPortLineCtrl(ch->port, 1, 1);		MoxaPortEnable(ch->port);		ch->asyncflags |= ASYNC_INITIALIZED;	}	retval = block_till_ready(tty, filp, ch);	moxa_unthrottle(tty);	if (ch->type == PORT_16550A) {		MoxaSetFifo(ch->port, 1);	} else {		MoxaSetFifo(ch->port, 0);	}	return (retval);}static void moxa_close(struct tty_struct *tty, struct file *filp){	struct moxa_str *ch;	int port;	port = PORTNO(tty);	if (port == MAX_PORTS) {		return;	}	if (!MoxaPortIsValid(port)) {#ifdef SERIAL_DEBUG_CLOSE		printk("Invalid portno in moxa_close\n");#endif		tty->driver_data = NULL;		return;	}	if (tty->driver_data == NULL) {		return;	}	if (tty_hung_up_p(filp)) {		return;	}	ch = (struct moxa_str *) tty->driver_data;	if ((tty->count == 1) && (ch->count != 1)) {		printk("moxa_close: bad serial port count; tty->count is 1, "		       "ch->count is %d\n", ch->count);		ch->count = 1;	}	if (--ch->count < 0) {		printk("moxa_close: bad serial port count, device=%s\n",		       tty->name);		ch->count = 0;	}	if (ch->count) {		return;	}	ch->asyncflags |= ASYNC_CLOSING;	ch->cflag = tty->termios->c_cflag;	if (ch->asyncflags & ASYNC_INITIALIZED) {		setup_empty_event(tty);		tty_wait_until_sent(tty, 30 * HZ);	/* 30 seconds timeout */		moxaEmptyTimer_on[ch->port] = 0;		del_timer(&moxaEmptyTimer[ch->port]);	}	shut_down(ch);	MoxaPortFlushData(port, 2);	if (tty->driver->flush_buffer)		tty->driver->flush_buffer(tty);	tty_ldisc_flush(tty);				tty->closing = 0;	ch->event = 0;	ch->tty = NULL;	if (ch->blocked_open) {		if (ch->close_delay) {			set_current_state(TASK_INTERRUPTIBLE);			schedule_timeout(ch->close_delay);		}		wake_up_interruptible(&ch->open_wait);	}	ch->asyncflags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING);	wake_up_interruptible(&ch->close_wait);}static int moxa_write(struct tty_struct *tty, int from_user,		      const unsigned char *buf, int count){	struct moxa_str *ch;	int len, port;	unsigned long flags;	ch = (struct moxa_str *) tty->driver_data;	if (ch == NULL)		return (0);	port = ch->port;	save_flags(flags);	if (from_user) {		if (count > PAGE_SIZE)			count = PAGE_SIZE;		down(&moxaBuffSem);		if (copy_from_user(moxaXmitBuff, buf, count)) {			len = -EFAULT;		} else {			cli();			len = MoxaPortWriteData(port, moxaXmitBuff, count);			restore_flags(flags);		}		up(&moxaBuffSem);		if (len < 0)			return len;	} else {		cli();		len = MoxaPortWriteData(port, (unsigned char *) buf, count);		restore_flags(flags);	}	/*********************************************	if ( !(ch->statusflags & LOWWAIT) &&	     ((len != count) || (MoxaPortTxFree(port) <= 100)) )	************************************************/	ch->statusflags |= LOWWAIT;	return (len);}static int moxa_write_room(struct tty_struct *tty){	struct moxa_str *ch;	if (tty->stopped)		return (0);	ch = (struct moxa_str *) tty->driver_data;	if (ch == NULL)		return (0);	return (MoxaPortTxFree(ch->port));}static void moxa_flush_buffer(struct tty_struct *tty){	struct moxa_str *ch = (struct moxa_str *) tty->driver_data;	if (ch == NULL)		return;	MoxaPortFlushData(ch->port, 1);	tty_wakeup(tty);	wake_up_interruptible(&tty->write_wait);}static int moxa_chars_in_buffer(struct tty_struct *tty){	int chars;	struct moxa_str *ch = (struct moxa_str *) tty->driver_data;	/*	 * Sigh...I have to check if driver_data is NULL here, because	 * if an open() fails, the TTY subsystem eventually calls	 * tty_wait_until_sent(), which calls the driver's chars_in_buffer()	 * routine.  And since the open() failed, we return 0 here.  TDJ	 */	if (ch == NULL)		return (0);	chars = MoxaPortTxQueue(ch->port);	if (chars) {		/*		 * Make it possible to wakeup anything waiting for output		 * in tty_ioctl.c, etc.		 */		if (!(ch->statusflags & EMPTYWAIT))			setup_empty_event(tty);	}	return (chars);}static void moxa_flush_chars(struct tty_struct *tty){	/*	 * Don't think I need this, because this is called to empty the TX	 * buffer for the 16450, 16550, etc.	 */}static void moxa_put_char(struct tty_struct *tty, unsigned char c){	struct moxa_str *ch;	int port;	unsigned long flags;	ch = (struct moxa_str *) tty->driver_data;	if (ch == NULL)		return;	port = ch->port;	save_flags(flags);	cli();	moxaXmitBuff[0] = c;	MoxaPortWriteData(port, moxaXmitBuff, 1);	restore_flags(flags);	/************************************************	if ( !(ch->statusflags & LOWWAIT) && (MoxaPortTxFree(port) <= 100) )	*************************************************/	ch->statusflags |= LOWWAIT;}static int moxa_tiocmget(struct tty_struct *tty, struct file *file){	struct moxa_str *ch = (struct moxa_str *) tty->driver_data;	int port;	int flag = 0, dtr, rts;	port = PORTNO(tty);	if ((port != MAX_PORTS) && (!ch))		return (-EINVAL);	MoxaPortGetLineOut(ch->port, &dtr, &rts);	if (dtr)		flag |= TIOCM_DTR;	if (rts)		flag |= TIOCM_RTS;	dtr = MoxaPortLineStatus(ch->port);	if (dtr & 1)		flag |= TIOCM_CTS;	if (dtr & 2)		flag |= TIOCM_DSR;	if (dtr & 4)		flag |= TIOCM_CD;	return flag;}static int moxa_tiocmset(struct tty_struct *tty, struct file *file,			 unsigned int set, unsigned int clear){	struct moxa_str *ch = (struct moxa_str *) tty->driver_data;	int port;	int dtr, rts;	port = PORTNO(tty);	if ((port != MAX_PORTS) && (!ch))		return (-EINVAL);	MoxaPortGetLineOut(ch->port, &dtr, &rts);	if (set & TIOCM_RTS)		rts = 1;	if (set & TIOCM_DTR)		dtr = 1;	if (clear & TIOCM_RTS)		rts = 0;	if (clear & TIOCM_DTR)		dtr = 0;	MoxaPortLineCtrl(ch->port, dtr, rts);	return 0;}static int moxa_ioctl(struct tty_struct *tty, struct file *file,		      unsigned int cmd, unsigned long arg){	struct moxa_str *ch = (struct moxa_str *) tty->driver_data;	register int port;	void __user *argp = (void __user *)arg;	int retval;	port = PORTNO(tty);	if ((port != MAX_PORTS) && (!ch))		return (-EINVAL);	switch (cmd) {	case TCSBRK:		/* SVID version: non-zero arg --> no break */		retval = tty_check_change(tty);		if (retval)			return (retval);		setup_empty_event(tty);		tty_wait_until_sent(tty, 0);		if (!arg)			MoxaPortSendBreak(ch->port, 0);		return (0);	case TCSBRKP:		/* support for POSIX tcsendbreak() */		retval = tty_check_change(tty);		if (retval)			return (retval);		setup_empty_event(tty);		tty_wait_until_sent(tty, 0);		MoxaPortSendBreak(ch->port, arg);		return (0);	case TIOCGSOFTCAR:		return put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long __user *) argp);	case TIOCSSOFTCAR:		if(get_user(retval, (unsigned long __user *) argp))			return -EFAULT;		arg = retval;		tty->termios->c_cflag = ((tty->termios->c_cflag & ~CLOCAL) |					 (arg ? CLOCAL : 0));		if (C_CLOCAL(tty))			ch->asyncflags &= ~ASYNC_CHECK_CD;		else			ch->asyncflags |= ASYNC_CHECK_CD;		return (0);	case TIOCGSERIAL:		return moxa_get_serial_info(ch, argp);	case TIOCSSERIAL:		return moxa_set_serial_info(ch, argp);	default:		retval = MoxaDriverIoctl(cmd, arg, port);	}	return (retval);}static void moxa_throttle(struct tty_struct *tty){	struct moxa_str *ch = (struct moxa_str *) tty->driver_data;	ch->statusflags |= THROTTLE;}static void moxa_unthrottle(struct tty_struct *tty){	struct moxa_str *ch = (struct moxa_str *) tty->driver_data;	ch->statusflags &= ~THROTTLE;}static void moxa_set_termios(struct tty_struct *tty,			     struct termios *old_termios){	struct moxa_str *ch = (struct moxa_str *) tty->driver_data;	if (ch == NULL)		return;	set_tty_param(tty);	if (!(old_termios->c_cflag & CLOCAL) &&	    (tty->termios->c_cflag & CLOCAL))		wake_up_interruptible(&ch->open_wait);}static void moxa_stop(struct tty_struct *tty){	struct moxa_str *ch = (struct moxa_str *) tty->driver_data;	if (ch == NULL)		return;	MoxaPortTxDisable(ch->port);	ch->statusflags |= TXSTOPPED;}static void moxa_start(struct tty_struct *tty){	struct moxa_str *ch = (struct moxa_str *) tty->driver_data;	if (ch == NULL)		return;	if (!(ch->statusflags & TXSTOPPED))		return;	MoxaPortTxEnable(ch->port);	ch->statusflags &= ~TXSTOPPED;}static void moxa_hangup(struct tty_struct *tty){	struct moxa_str *ch = (struct moxa_str *) tty->driver_data;	moxa_flush_buffer(tty);	shut_down(ch);	ch->event = 0;	ch->count = 0;	ch->asyncflags &= ~ASYNC_NORMAL_ACTIVE;	ch->tty = NULL;	wake_up_interruptible(&ch->open_wait);}static void moxa_poll(unsigned long ignored){	register int card;	struct moxa_str *ch;	struct tty_struct *tp;	int i, ports;	moxaTimer_on = 0;	del_timer(&moxaTimer);	if (MoxaDriverPoll() < 0) {		moxaTimer.function = moxa_poll;		moxaTimer.expires = jiffies + (HZ / 50);		moxaTimer_on = 1;		add_timer(&moxaTimer);		return;	}	for (card = 0; card < MAX_BOARDS; card++) {		if ((ports = MoxaPortsOfCard(card)) <= 0)			continue;		ch = &moxaChannels[card * MAX_PORTS_PER_BOARD];		for (i = 0; i < ports; i++, ch++) {			if ((ch->asyncflags & ASYNC_INITIALIZED) == 0)				continue;			if (!(ch->statusflags & THROTTLE) &&			    (MoxaPortRxQueue(ch->port) > 0))				receive_data(ch);			if ((tp = ch->tty) == 0)				continue;			if (ch->statusflags & LOWWAIT) {				if (MoxaPortTxQueue(ch->port) <= WAKEUP_CHARS) {					if (!tp->stopped) {						ch->statusflags &= ~LOWWAIT;						tty_wakeup(tp);						wake_up_interruptible(&tp->write_wait);					}				}			}			if (!I_IGNBRK(tp) && (MoxaPortResetBrkCnt(ch->port) > 0)) {				tty_insert_flip_char(tp, 0, TTY_BREAK);				tty_schedule_flip(tp);

⌨️ 快捷键说明

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