📄 moxa.c
字号:
/*****************************************************************************//* * moxa.c -- MOXA Intellio family multiport serial driver. * * Copyright (C) 1999-2001 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. * * Original Release 12/08/99 * * 02/06/01 Support closing wait. * 02/06/01 Fix the bug for driver initialization of ISA boards. * 02/06/01 Fix the compiling warning when CONFIG_PCI * don't be defined.*/#define VERSION_CODE(ver,rel,seq) ((ver << 16) | (rel << 8) | seq)#ifdef MODULE#ifdef MODVERSIONS#include <linux/modversions.h>#endif#include <linux/module.h>#else#define MOD_INC_USE_COUNT#define MOD_DEC_USE_COUNT#endif#include <linux/types.h>#include <linux/autoconf.h>#include <linux/version.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>#if (LINUX_VERSION_CODE < VERSION_CODE(2,4,0))#include <linux/config.h>#endif#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 <asm/system.h>#include <asm/io.h>#include <asm/segment.h>#include <asm/bitops.h>#define MOXA_VERSION "5.4"#define MOXAMAJOR 31 #define MOXACUMAJOR 37 #ifdef CONFIG_PCI#if (LINUX_VERSION_CODE < VERSION_CODE(2,1,0))#include <linux/bios32.h>#endif#include <linux/pci.h>#endif /* ENABLE_PCI */#if (LINUX_VERSION_CODE < VERSION_CODE(2,1,0))#define copy_from_user memcpy_fromfs#define copy_to_user memcpy_tofs#define put_to_user(arg1, arg2) put_fs_long(arg1, (unsigned long *)arg2)#define get_from_user(arg1, arg2) arg1 = get_fs_long((unsigned long *)arg2)#define ioremap vremap#define iounmap vfree#define schedule_timeout(x) {current->timeout = jiffies + (x); schedule();}#define signal_pending(x) ((x)->signal & ~(x)->blocked)#else#include <asm/uaccess.h>#define put_to_user(arg1, arg2) put_user(arg1, (unsigned long *)arg2)#define get_from_user(arg1, arg2) get_user(arg1, (unsigned int *)arg2)#endif #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_PCItypedef struct { unsigned short vendor_id; unsigned short device_id; unsigned short board_type;} moxa_pciinfo;static moxa_pciinfo moxa_pcibrds[] = { {PCI_VENDOR_ID_MOXA,PCI_DEVICE_ID_C218 ,MOXA_BOARD_C218_PCI}, {PCI_VENDOR_ID_MOXA,PCI_DEVICE_ID_C320 ,MOXA_BOARD_C320_PCI}, {PCI_VENDOR_ID_MOXA,PCI_DEVICE_ID_CP204J ,MOXA_BOARD_CP204J},};#endiftypedef struct _moxa_isa_board_conf { int boardType; int numPorts; unsigned long baseAddr;} moxa_isa_board_conf;static moxa_isa_board_conf moxa_isa_boards[] = { {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}/* {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];static int loadstat[MAX_BOARDS]={0,0,0,0};struct moxa_str { int type; int port; int close_delay; unsigned short closing_wait; int count; int blocked_open;#if (LINUX_VERSION_CODE < VERSION_CODE(2,4,0)) int event;#else long event;#endif int asyncflags; long session; long pgrp; unsigned long statusflags; struct tty_struct *tty; struct termios normal_termios; struct termios callout_termios;#if (LINUX_VERSION_CODE < VERSION_CODE(2,4,0)) struct wait_queue *open_wait; struct wait_queue *close_wait;#else wait_queue_head_t open_wait; wait_queue_head_t close_wait;#endif struct tq_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 SERIAL_TYPE_CALLOUT 2#define WAKEUP_CHARS 256#define PORTNO(x) (MINOR((x)->device) - (x)->driver.minor_start)static int verbose = 0;static int ttymajor = MOXAMAJOR;static int calloutmajor = MOXACUMAJOR;#ifdef MODULE/* Variables for insmod */static int baseaddr[] = {0, 0, 0, 0};static int type[] = {0, 0, 0, 0};static int numports[] = {0, 0, 0, 0};# if (LINUX_VERSION_CODE > VERSION_CODE(2,1,11))MODULE_AUTHOR("William Chen");MODULE_DESCRIPTION("MOXA Intellio Family Multiport Board Device Driver");MODULE_PARM(type, "1-4i");MODULE_PARM(baseaddr, "1-4i");MODULE_PARM(numports, "1-4i");MODULE_PARM(ttymajor, "i");MODULE_PARM(calloutmajor,"i");MODULE_PARM(verbose,"i");# endif#endif //MODULEstatic struct tty_driver moxaDriver;static struct tty_driver moxaCallout;static struct tty_struct * moxaTable[MAX_PORTS+1];static struct termios * moxaTermios[MAX_PORTS+1];static struct termios * moxaTermiosLocked[MAX_PORTS+1];static struct moxa_str moxaChannels[MAX_PORTS];static int moxaRefcount;static unsigned char * moxaXmitBuff;static int moxaTimer_on;static int moxaEmptyTimer_on[MAX_PORTS];static struct timer_list moxaEmptyTimer[MAX_PORTS];static struct timer_list moxaTimer;#if (LINUX_VERSION_CODE >= VERSION_CODE(2,4,0))static struct semaphore moxaBuffSem;#elsestatic struct semaphore moxaBuffSem = MUTEX;#endifint moxa_init(void);#ifdef MODULEint init_module(void);void cleanup_module(void);#endif/* * static functions: */#ifdef CONFIG_PCIstatic int moxa_get_PCI_conf(int ,int ,int ,moxa_board_conf *);#endifstatic 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 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 *);#if (LINUX_VERSION_CODE > VERSION_CODE(2,1,0))static void mx_wait_until_sent(struct tty_struct *tty, int timeout);#endif/* * 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 void MoxaPortFlushData2(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 *);static int moxa_set_serial_info(struct moxa_str *, struct serial_struct *);static void MoxaSetFifo(int port, int enable);#ifdef MODULEint init_module(void){ int ret; if (verbose) printk("Loading module moxa ...\n"); ret = moxa_init(); if (verbose) printk("Done\n"); return (ret);}void cleanup_module(void){ int i; if (verbose) printk("Unloading module moxa ...\n"); 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(&moxaCallout)) printk("Couldn't unregister MOXA Intellio family callout driver\n"); if (tty_unregister_driver(&moxaDriver)) printk("Couldn't unregister MOXA Intellio family serial driver\n"); if (verbose) printk("Done\n");}#endifint moxa_init(void){ int i,numBoards; struct moxa_str *ch; int ret1,ret2;#ifdef CONFIG_PCI int n,index; unsigned char busnum,devnum;#endif printk("MOXA Intellio family driver version %s\n", MOXA_VERSION);#if (LINUX_VERSION_CODE >= VERSION_CODE(2,4,0)) init_MUTEX(&moxaBuffSem);#endif memset(&moxaDriver, 0, sizeof(struct tty_driver)); memset(&moxaCallout, 0, sizeof(struct tty_driver)); moxaDriver.magic = TTY_DRIVER_MAGIC; moxaDriver.name = "ttya"; moxaDriver.major = ttymajor; moxaDriver.minor_start = 0; moxaDriver.num = MAX_PORTS + 1; 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; moxaDriver.refcount = &moxaRefcount; moxaDriver.table = moxaTable; moxaDriver.termios = moxaTermios; moxaDriver.termios_locked = moxaTermiosLocked; moxaDriver.open = moxa_open; moxaDriver.close = moxa_close; moxaDriver.write = moxa_write; moxaDriver.write_room = moxa_write_room; moxaDriver.flush_buffer = moxa_flush_buffer; moxaDriver.chars_in_buffer = moxa_chars_in_buffer; moxaDriver.flush_chars = moxa_flush_chars; moxaDriver.put_char = moxa_put_char; moxaDriver.ioctl = moxa_ioctl; moxaDriver.throttle = moxa_throttle; moxaDriver.unthrottle = moxa_unthrottle; moxaDriver.set_termios = moxa_set_termios; moxaDriver.stop = moxa_stop; moxaDriver.start = moxa_start; moxaDriver.hangup = moxa_hangup;# if (LINUX_VERSION_CODE > VERSION_CODE(2,1,0)) moxaDriver.wait_until_sent = mx_wait_until_sent;#endif moxaCallout = moxaDriver; moxaCallout.name = "ttyA"; moxaCallout.major = calloutmajor; moxaCallout.subtype = SERIAL_TYPE_CALLOUT; moxaXmitBuff = 0; for (i = 0, ch = moxaChannels; i < MAX_PORTS; i++, ch++) { ch->type = PORT_16550A; ch->port = i; ch->tqueue.routine = do_moxa_softint; ch->tqueue.data = ch; ch->tty = 0; ch->close_delay = 5*HZ/10; ch->closing_wait = 0; ch->count = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -