📄 moxa.c
字号:
/*****************************************************************************//* * moxa.c -- MOXA Intellio family multiport serial driver. * * Copyright (C) 1999-2000 Moxa Technologies (support@moxa.com.tw). * * This code is loosely based on the Linux serial driver, written by * Linus Torvalds, Theodore T'so and others. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *//* * MOXA Intellio Series Driver * for : LINUX * date : 1999/1/7 * version : 5.1 */#include <linux/config.h>#include <linux/module.h>#include <linux/types.h>#include <linux/mm.h>#include <linux/ioport.h>#include <linux/errno.h>#include <linux/signal.h>#include <linux/sched.h>#include <linux/timer.h>#include <linux/interrupt.h>#include <linux/tty.h>#include <linux/tty_flip.h>#include <linux/major.h>#include <linux/string.h>#include <linux/fcntl.h>#include <linux/ptrace.h>#include <linux/serial.h>#include <linux/tty_driver.h>#include <linux/delay.h>#include <linux/pci.h>#include <linux/init.h>#include <asm/system.h>#include <asm/io.h>#include <asm/bitops.h>#include <asm/uaccess.h>#define MOXA_VERSION "5.1k"#define MOXAMAJOR 172#define MOXACUMAJOR 173#define put_to_user(arg1, arg2) put_user(arg1, (unsigned long *)arg2)#define get_from_user(arg1, arg2) get_user(arg1, (unsigned int *)arg2)#define MAX_BOARDS 4 /* Don't change this value */#define MAX_PORTS_PER_BOARD 32 /* Don't change this value */#define MAX_PORTS 128 /* Don't change this value *//* * Define the Moxa PCI vendor and device IDs. */#define MOXA_BUS_TYPE_ISA 0#define MOXA_BUS_TYPE_PCI 1#ifndef PCI_VENDOR_ID_MOXA#define PCI_VENDOR_ID_MOXA 0x1393#endif#ifndef PCI_DEVICE_ID_CP204J#define PCI_DEVICE_ID_CP204J 0x2040#endif#ifndef PCI_DEVICE_ID_C218#define PCI_DEVICE_ID_C218 0x2180#endif#ifndef PCI_DEVICE_ID_C320#define PCI_DEVICE_ID_C320 0x3200#endifenum { MOXA_BOARD_C218_PCI = 1, MOXA_BOARD_C218_ISA, MOXA_BOARD_C320_PCI, MOXA_BOARD_C320_ISA, MOXA_BOARD_CP204J,};static char *moxa_brdname[] ={ "C218 Turbo PCI series", "C218 Turbo ISA series", "C320 Turbo PCI series", "C320 Turbo ISA series", "CP-204J series",};#ifdef CONFIG_PCIstatic struct pci_device_id moxa_pcibrds[] = { { PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_C218, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MOXA_BOARD_C218_PCI }, { PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_C320, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MOXA_BOARD_C320_PCI }, { PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_CP204J, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MOXA_BOARD_CP204J }, { 0 }};MODULE_DEVICE_TABLE(pci, moxa_pcibrds);#endif /* CONFIG_PCI */typedef struct _moxa_isa_board_conf { int boardType; int numPorts; unsigned long baseAddr;} moxa_isa_board_conf;static moxa_isa_board_conf moxa_isa_boards[] ={/* {MOXA_BOARD_C218_ISA,8,0xDC000}, */};typedef struct _moxa_pci_devinfo { ushort busNum; ushort devNum;} moxa_pci_devinfo;typedef struct _moxa_board_conf { int boardType; int numPorts; unsigned long baseAddr; int busType; moxa_pci_devinfo pciInfo;} moxa_board_conf;static moxa_board_conf moxa_boards[MAX_BOARDS];static unsigned long moxaBaseAddr[MAX_BOARDS];struct moxa_str { int type; int port; int close_delay; unsigned short closing_wait; int count; int blocked_open; long event; /* long req'd for set_bit --RR */ int asyncflags; unsigned long statusflags; struct tty_struct *tty; int cflag; wait_queue_head_t open_wait; wait_queue_head_t close_wait; struct work_struct tqueue;};struct mxser_mstatus { tcflag_t cflag; int cts; int dsr; int ri; int dcd;};static struct mxser_mstatus GMStatus[MAX_PORTS];/* statusflags */#define TXSTOPPED 0x1#define LOWWAIT 0x2#define EMPTYWAIT 0x4#define THROTTLE 0x8/* event */#define MOXA_EVENT_HANGUP 1#define SERIAL_DO_RESTART#define SERIAL_TYPE_NORMAL 1#define WAKEUP_CHARS 256#define PORTNO(x) ((x)->index)static int verbose = 0;static int ttymajor = MOXAMAJOR;/* Variables for insmod */#ifdef MODULEstatic int baseaddr[] = {0, 0, 0, 0};static int type[] = {0, 0, 0, 0};static int numports[] = {0, 0, 0, 0};#endifMODULE_AUTHOR("William Chen");MODULE_DESCRIPTION("MOXA Intellio Family Multiport Board Device Driver");MODULE_LICENSE("GPL");MODULE_PARM(type, "1-4i");MODULE_PARM(baseaddr, "1-4i");MODULE_PARM(numports, "1-4i");MODULE_PARM(ttymajor, "i");MODULE_PARM(verbose, "i");static struct tty_driver *moxaDriver;static struct moxa_str moxaChannels[MAX_PORTS];static unsigned char *moxaXmitBuff;static int moxaTimer_on;static struct timer_list moxaTimer;static int moxaEmptyTimer_on[MAX_PORTS];static struct timer_list moxaEmptyTimer[MAX_PORTS];static struct semaphore moxaBuffSem;/* * static functions: */static void do_moxa_softint(void *);static int moxa_open(struct tty_struct *, struct file *);static void moxa_close(struct tty_struct *, struct file *);static int moxa_write(struct tty_struct *, int, const unsigned char *, int);static int moxa_write_room(struct tty_struct *);static void moxa_flush_buffer(struct tty_struct *);static int moxa_chars_in_buffer(struct tty_struct *);static void moxa_flush_chars(struct tty_struct *);static void moxa_put_char(struct tty_struct *, unsigned char);static int moxa_ioctl(struct tty_struct *, struct file *, unsigned int, unsigned long);static void moxa_throttle(struct tty_struct *);static void moxa_unthrottle(struct tty_struct *);static void moxa_set_termios(struct tty_struct *, struct termios *);static void moxa_stop(struct tty_struct *);static void moxa_start(struct tty_struct *);static void moxa_hangup(struct tty_struct *);static int moxa_tiocmget(struct tty_struct *tty, struct file *file);static int moxa_tiocmset(struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear);static void moxa_poll(unsigned long);static void set_tty_param(struct tty_struct *);static int block_till_ready(struct tty_struct *, struct file *, struct moxa_str *);static void setup_empty_event(struct tty_struct *);static void check_xmit_empty(unsigned long);static void shut_down(struct moxa_str *);static void receive_data(struct moxa_str *);/* * moxa board interface functions: */static void MoxaDriverInit(void);static int MoxaDriverIoctl(unsigned int, unsigned long, int);static int MoxaDriverPoll(void);static int MoxaPortsOfCard(int);static int MoxaPortIsValid(int);static void MoxaPortEnable(int);static void MoxaPortDisable(int);static long MoxaPortGetMaxBaud(int);static long MoxaPortSetBaud(int, long);static int MoxaPortSetTermio(int, struct termios *);static int MoxaPortGetLineOut(int, int *, int *);static void MoxaPortLineCtrl(int, int, int);static void MoxaPortFlowCtrl(int, int, int, int, int, int);static int MoxaPortLineStatus(int);static int MoxaPortDCDChange(int);static int MoxaPortDCDON(int);static void MoxaPortFlushData(int, int);static int MoxaPortWriteData(int, unsigned char *, int);static int MoxaPortReadData(int, unsigned char *, int);static int MoxaPortTxQueue(int);static int MoxaPortRxQueue(int);static int MoxaPortTxFree(int);static void MoxaPortTxDisable(int);static void MoxaPortTxEnable(int);static int MoxaPortResetBrkCnt(int);static void MoxaPortSendBreak(int, int);static int moxa_get_serial_info(struct moxa_str *, struct serial_struct __user *);static int moxa_set_serial_info(struct moxa_str *, struct serial_struct __user *);static void MoxaSetFifo(int port, int enable);static struct tty_operations moxa_ops = { .open = moxa_open, .close = moxa_close, .write = moxa_write, .write_room = moxa_write_room, .flush_buffer = moxa_flush_buffer, .chars_in_buffer = moxa_chars_in_buffer, .flush_chars = moxa_flush_chars, .put_char = moxa_put_char, .ioctl = moxa_ioctl, .throttle = moxa_throttle, .unthrottle = moxa_unthrottle, .set_termios = moxa_set_termios, .stop = moxa_stop, .start = moxa_start, .hangup = moxa_hangup, .tiocmget = moxa_tiocmget, .tiocmset = moxa_tiocmset,};#ifdef CONFIG_PCIstatic 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);}#endif /* CONFIG_PCI */static int __init moxa_init(void){ int i, numBoards; struct moxa_str *ch; printk(KERN_INFO "MOXA Intellio family driver version %s\n", MOXA_VERSION); moxaDriver = alloc_tty_driver(MAX_PORTS + 1); if (!moxaDriver) return -ENOMEM; init_MUTEX(&moxaBuffSem); moxaDriver->owner = THIS_MODULE; moxaDriver->name = "ttya"; moxaDriver->devfs_name = "tts/a"; moxaDriver->major = ttymajor; moxaDriver->minor_start = 0; moxaDriver->type = TTY_DRIVER_TYPE_SERIAL; moxaDriver->subtype = SERIAL_TYPE_NORMAL; moxaDriver->init_termios = tty_std_termios; moxaDriver->init_termios.c_iflag = 0; moxaDriver->init_termios.c_oflag = 0; moxaDriver->init_termios.c_cflag = B9600 | CS8 | CREAD | CLOCAL | HUPCL; moxaDriver->init_termios.c_lflag = 0; moxaDriver->flags = TTY_DRIVER_REAL_RAW; tty_set_operations(moxaDriver, &moxa_ops); moxaXmitBuff = NULL; for (i = 0, ch = moxaChannels; i < MAX_PORTS; i++, ch++) { ch->type = PORT_16550A; ch->port = i; INIT_WORK(&ch->tqueue, do_moxa_softint, ch); ch->tty = NULL; ch->close_delay = 5 * HZ / 10; ch->closing_wait = 30 * HZ; ch->count = 0; ch->blocked_open = 0; ch->cflag = B9600 | CS8 | CREAD | CLOCAL | HUPCL; init_waitqueue_head(&ch->open_wait); init_waitqueue_head(&ch->close_wait); } for (i = 0; i < MAX_BOARDS; i++) { moxa_boards[i].boardType = 0; moxa_boards[i].numPorts = 0; moxa_boards[i].baseAddr = 0; moxa_boards[i].busType = 0; moxa_boards[i].pciInfo.busNum = 0; moxa_boards[i].pciInfo.devNum = 0; } MoxaDriverInit(); printk("Tty devices major number = %d\n", ttymajor); if (tty_register_driver(moxaDriver)) { printk(KERN_ERR "Couldn't install MOXA Smartio family driver !\n"); put_tty_driver(moxaDriver); return -1; } for (i = 0; i < MAX_PORTS; i++) { init_timer(&moxaEmptyTimer[i]); moxaEmptyTimer[i].function = check_xmit_empty; moxaEmptyTimer[i].data = (unsigned long) & moxaChannels[i]; moxaEmptyTimer_on[i] = 0; } init_timer(&moxaTimer); moxaTimer.function = moxa_poll; moxaTimer.expires = jiffies + (HZ / 50); moxaTimer_on = 1; add_timer(&moxaTimer); /* Find the boards defined in source code */ numBoards = 0; for (i = 0; i < MAX_BOARDS; i++) { if ((moxa_isa_boards[i].boardType == MOXA_BOARD_C218_ISA) || (moxa_isa_boards[i].boardType == MOXA_BOARD_C320_ISA)) { moxa_boards[numBoards].boardType = moxa_isa_boards[i].boardType; if (moxa_isa_boards[i].boardType == MOXA_BOARD_C218_ISA) moxa_boards[numBoards].numPorts = 8; else moxa_boards[numBoards].numPorts = moxa_isa_boards[i].numPorts; moxa_boards[numBoards].busType = MOXA_BUS_TYPE_ISA; moxa_boards[numBoards].baseAddr = moxa_isa_boards[i].baseAddr; if (verbose) printk("Board %2d: %s board(baseAddr=%lx)\n", numBoards + 1, moxa_brdname[moxa_boards[numBoards].boardType - 1], moxa_boards[numBoards].baseAddr); numBoards++; } } /* Find the boards defined form module args. */#ifdef MODULE for (i = 0; i < MAX_BOARDS; i++) { if ((type[i] == MOXA_BOARD_C218_ISA) || (type[i] == MOXA_BOARD_C320_ISA)) { if (verbose) 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; int n = (sizeof(moxa_pcibrds) / sizeof(moxa_pcibrds[0])) - 1; i = 0; while (i < n) { while ((p = pci_find_device(moxa_pcibrds[i].vendor, moxa_pcibrds[i].device, 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].driver_data, &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 void __exit moxa_exit(void){ int i; if (verbose) printk("Unloading module moxa ...\n");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -