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

📄 moxa.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
				printk("Board %2d: %s board(baseAddr=%lx)\n",				       numBoards + 1,				       moxa_brdname[type[i] - 1],				       (unsigned long) baseaddr[i]);			if (numBoards >= MAX_BOARDS) {				if (verbose)					printk("More than %d MOXA Intellio family boards found. Board is ignored.", MAX_BOARDS);				continue;			}			moxa_boards[numBoards].boardType = type[i];			if (moxa_isa_boards[i].boardType == MOXA_BOARD_C218_ISA)				moxa_boards[numBoards].numPorts = 8;			else				moxa_boards[numBoards].numPorts = numports[i];			moxa_boards[numBoards].busType = MOXA_BUS_TYPE_ISA;			moxa_boards[numBoards].baseAddr = baseaddr[i];			numBoards++;		}	}#endif	/* Find PCI boards here */#ifdef CONFIG_PCI	{		struct pci_dev *p = NULL;		n = sizeof(moxa_pcibrds) / sizeof(moxa_pciinfo);		i = 0;		while (i < n) {			while((p = pci_find_device(moxa_pcibrds[i].vendor_id, moxa_pcibrds[i].device_id, p))!=NULL)			{				if (pci_enable_device(p))					continue;				if (numBoards >= MAX_BOARDS) {					if (verbose)						printk("More than %d MOXA Intellio family boards found. Board is ignored.", MAX_BOARDS);				} else {					moxa_get_PCI_conf(p, moxa_pcibrds[i].board_type,						&moxa_boards[numBoards]);					numBoards++;				}			}			i++;		}	}#endif	for (i = 0; i < numBoards; i++) {		moxaBaseAddr[i] = (unsigned long) ioremap((unsigned long) moxa_boards[i].baseAddr, 0x4000);	}	return (0);}static int moxa_get_PCI_conf(struct pci_dev *p, int board_type, moxa_board_conf * board){	board->baseAddr = pci_resource_start (p, 2);	board->boardType = board_type;	switch (board_type) {	case MOXA_BOARD_C218_ISA:	case MOXA_BOARD_C218_PCI:		board->numPorts = 8;		break;	case MOXA_BOARD_CP204J:		board->numPorts = 4;		break;	default:		board->numPorts = 0;		break;	}	board->busType = MOXA_BUS_TYPE_PCI;	board->pciInfo.busNum = p->bus->number;	board->pciInfo.devNum = p->devfn >> 3;	return (0);}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 | ASYNC_CALLOUT_ACTIVE);		}	}	MOD_DEC_USE_COUNT;}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) {		MOD_INC_USE_COUNT;		return (0);	}	if (!MoxaPortIsValid(port)) {		tty->driver_data = NULL;		return (-ENODEV);	}	down(&moxaBuffSem);	if (!moxaXmitBuff) {		page = get_free_page(GFP_KERNEL);		if (!page) {			up(&moxaBuffSem);			return (-ENOMEM);		}		if (moxaXmitBuff)			free_page(page);		else			moxaXmitBuff = (unsigned char *) page;	}	up(&moxaBuffSem);	MOD_INC_USE_COUNT;	ch = &moxaChannels[port];	ch->count++;	tty->driver_data = ch;	ch->tty = tty;	if (ch->count == 1 && (ch->asyncflags & ASYNC_SPLIT_TERMIOS)) {		if (tty->driver.subtype == SERIAL_TYPE_NORMAL)			*tty->termios = ch->normal_termios;		else			*tty->termios = ch->callout_termios;	}	ch->session = current->session;	ch->pgrp = current->pgrp;	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) {		MOD_DEC_USE_COUNT;		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)) {		MOD_DEC_USE_COUNT;		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, minor=%d\n",		       MINOR(tty->device));		ch->count = 0;	}	if (ch->count) {		MOD_DEC_USE_COUNT;		return;	}	ch->asyncflags |= ASYNC_CLOSING;	/*	 * Save the termios structure, since this port may have	 * separate termios for callout and dialin.	 */	if (ch->asyncflags & ASYNC_NORMAL_ACTIVE)		ch->normal_termios = *tty->termios;	if (ch->asyncflags & ASYNC_CALLOUT_ACTIVE)		ch->callout_termios = *tty->termios;	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);	if (tty->ldisc.flush_buffer)		tty->ldisc.flush_buffer(tty);	tty->closing = 0;	ch->event = 0;	ch->tty = 0;	if (ch->blocked_open) {		if (ch->close_delay) {			current->state = TASK_INTERRUPTIBLE;			schedule_timeout(ch->close_delay);		}		wake_up_interruptible(&ch->open_wait);	}	ch->asyncflags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CALLOUT_ACTIVE |			    ASYNC_CLOSING);	wake_up_interruptible(&ch->close_wait);	MOD_DEC_USE_COUNT;}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;	unsigned char *temp;	ch = (struct moxa_str *) tty->driver_data;	if (ch == NULL)		return (0);	port = ch->port;	save_flags(flags);	cli();	if (from_user) {		copy_from_user(moxaXmitBuff, buf, count);		temp = moxaXmitBuff;	} else		temp = (unsigned char *) buf;	len = MoxaPortWriteData(port, temp, 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);	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&	    tty->ldisc.write_wakeup)		(tty->ldisc.write_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_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;	int retval, dtr, rts;	unsigned long flag;	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 *) arg);	case TIOCSSOFTCAR:		if(get_user(retval, (unsigned long *) arg))			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 TIOCMGET:		flag = 0;		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 put_user(flag, (unsigned int *) arg);	case TIOCMBIS:		if(get_user(retval, (unsigned int *) arg))			return -EFAULT;		MoxaPortGetLineOut(ch->port, &dtr, &rts);		if (retval & TIOCM_RTS)			rts = 1;		if (retval & TIOCM_DTR)			dtr = 1;		MoxaPortLineCtrl(ch->port, dtr, rts);		return (0);	case TIOCMBIC:		if(get_user(retval, (unsigned int *) arg))			return -EFAULT;		MoxaPortGetLineOut(ch->port, &dtr, &rts);		if (retval & TIOCM_RTS)			rts = 0;		if (retval & TIOCM_DTR)			dtr = 0;		MoxaPortLineCtrl(ch->port, dtr, rts);		return (0);	case TIOCMSET:		if(get_user(retval, (unsigned long *) arg))			return -EFAULT;		dtr = rts = 0;		if (retval & TIOCM_RTS)			rts = 1;		if (retval & TIOCM_DTR)			dtr = 1;		MoxaPortLineCtrl(ch->port, dtr, rts);		return (0);	case TIOCGSERIAL:		return (moxa_get_serial_info(ch, (struct serial_struct *) arg));	case TIOCSSERIAL:		return (moxa_set_serial_info(ch, (struct serial_struct *) arg));	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) &&

⌨️ 快捷键说明

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