📄 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/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>#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 <asm/system.h>#include <asm/io.h>#include <asm/segment.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",};typedef 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},};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; long session; long pgrp; unsigned long statusflags; struct tty_struct *tty; struct termios normal_termios; struct termios callout_termios; wait_queue_head_t open_wait; wait_queue_head_t close_wait; 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};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 //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 struct timer_list moxaTimer;static int moxaEmptyTimer_on[MAX_PORTS];static struct timer_list moxaEmptyTimer[MAX_PORTS];static struct semaphore moxaBuffSem;int moxa_init(void);#ifdef MODULEint init_module(void);void cleanup_module(void);#endif/* * static functions: */static int moxa_get_PCI_conf(struct pci_dev *, int, moxa_board_conf *);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 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 *);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, n, numBoards; struct moxa_str *ch; int ret1, ret2; printk(KERN_INFO "MOXA Intellio family driver version %s\n", MOXA_VERSION); init_MUTEX(&moxaBuffSem); 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; 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 = 30 * HZ; ch->count = 0; ch->blocked_open = 0; ch->callout_termios = moxaCallout.init_termios; ch->normal_termios = moxaDriver.init_termios; 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, callout devices major number = %d\n", ttymajor, calloutmajor); ret1 = 0; ret2 = 0; if ((ret1 = tty_register_driver(&moxaDriver))) { printk(KERN_ERR "Couldn't install MOXA Smartio family driver !\n"); } else if ((ret2 = tty_register_driver(&moxaCallout))) { tty_unregister_driver(&moxaDriver); printk(KERN_ERR "Couldn't install MOXA Smartio family callout driver !\n"); } if (ret1 || ret2) { 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)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -