?? stallion.c
字號:
/*****************************************************************************//* * stallion.c -- stallion multiport serial driver. * * Copyright (C) 1996-1999 Stallion Technologies (support@stallion.oz.au). * Copyright (C) 1994-1996 Greg Ungerer (gerg@stallion.oz.au). * * 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. *//*****************************************************************************/#include <linux/config.h>#include <linux/module.h>#include <linux/malloc.h>#include <linux/interrupt.h>#include <linux/tty_flip.h>#include <linux/serial.h>#include <linux/cd1400.h>#include <linux/sc26198.h>#include <linux/comstats.h>#include <linux/stallion.h>#include <linux/ioport.h>#include <linux/init.h>#include <linux/smp_lock.h>#include <asm/io.h>#include <asm/uaccess.h>#ifdef CONFIG_PCI#include <linux/pci.h>#endif/*****************************************************************************//* * Define different board types. Use the standard Stallion "assigned" * board numbers. Boards supported in this driver are abbreviated as * EIO = EasyIO and ECH = EasyConnection 8/32. */#define BRD_EASYIO 20#define BRD_ECH 21#define BRD_ECHMC 22#define BRD_ECHPCI 26#define BRD_ECH64PCI 27#define BRD_EASYIOPCI 28/* * Define a configuration structure to hold the board configuration. * Need to set this up in the code (for now) with the boards that are * to be configured into the system. This is what needs to be modified * when adding/removing/modifying boards. Each line entry in the * stl_brdconf[] array is a board. Each line contains io/irq/memory * ranges for that board (as well as what type of board it is). * Some examples: * { BRD_EASYIO, 0x2a0, 0, 0, 10, 0 }, * This line would configure an EasyIO board (4 or 8, no difference), * at io address 2a0 and irq 10. * Another example: * { BRD_ECH, 0x2a8, 0x280, 0, 12, 0 }, * This line will configure an EasyConnection 8/32 board at primary io * address 2a8, secondary io address 280 and irq 12. * Enter as many lines into this array as you want (only the first 4 * will actually be used!). Any combination of EasyIO and EasyConnection * boards can be specified. EasyConnection 8/32 boards can share their * secondary io addresses between each other. * * NOTE: there is no need to put any entries in this table for PCI * boards. They will be found automatically by the driver - provided * PCI BIOS32 support is compiled into the kernel. */typedef struct { int brdtype; int ioaddr1; int ioaddr2; unsigned long memaddr; int irq; int irqtype;} stlconf_t;static stlconf_t stl_brdconf[] = { /*{ BRD_EASYIO, 0x2a0, 0, 0, 10, 0 },*/};static int stl_nrbrds = sizeof(stl_brdconf) / sizeof(stlconf_t);/*****************************************************************************//* * Define some important driver characteristics. Device major numbers * allocated as per Linux Device Registry. */#ifndef STL_SIOMEMMAJOR#define STL_SIOMEMMAJOR 28#endif#ifndef STL_SERIALMAJOR#define STL_SERIALMAJOR 24#endif#ifndef STL_CALLOUTMAJOR#define STL_CALLOUTMAJOR 25#endif#define STL_DRVTYPSERIAL 1#define STL_DRVTYPCALLOUT 2/* * Set the TX buffer size. Bigger is better, but we don't want * to chew too much memory with buffers! */#define STL_TXBUFLOW 512#define STL_TXBUFSIZE 4096/*****************************************************************************//* * Define our local driver identity first. Set up stuff to deal with * all the local structures required by a serial tty driver. */static char *stl_drvtitle = "Stallion Multiport Serial Driver";static char *stl_drvname = "stallion";static char *stl_drvversion = "5.5.1";static char *stl_serialname = "ttyE";static char *stl_calloutname = "cue";static struct tty_driver stl_serial;static struct tty_driver stl_callout;static struct tty_struct *stl_ttys[STL_MAXDEVS];static struct termios *stl_termios[STL_MAXDEVS];static struct termios *stl_termioslocked[STL_MAXDEVS];static int stl_refcount = 0;/* * We will need to allocate a temporary write buffer for chars that * come direct from user space. The problem is that a copy from user * space might cause a page fault (typically on a system that is * swapping!). All ports will share one buffer - since if the system * is already swapping a shared buffer won't make things any worse. */static char *stl_tmpwritebuf;static struct semaphore stl_tmpwritesem = MUTEX;/* * Define a local default termios struct. All ports will be created * with this termios initially. Basically all it defines is a raw port * at 9600, 8 data bits, 1 stop bit. */static struct termios stl_deftermios = { 0, 0, (B9600 | CS8 | CREAD | HUPCL | CLOCAL), 0, 0, INIT_C_CC};/* * Define global stats structures. Not used often, and can be * re-used for each stats call. */static comstats_t stl_comstats;static combrd_t stl_brdstats;static stlbrd_t stl_dummybrd;static stlport_t stl_dummyport;/* * Define global place to put buffer overflow characters. */static char stl_unwanted[SC26198_RXFIFOSIZE];/* * Keep track of what interrupts we have requested for us. * We don't need to request an interrupt twice if it is being * shared with another Stallion board. */static int stl_gotintrs[STL_MAXBRDS];static int stl_numintrs = 0;/*****************************************************************************/static stlbrd_t *stl_brds[STL_MAXBRDS];/* * Per board state flags. Used with the state field of the board struct. * Not really much here! */#define BRD_FOUND 0x1/* * Define the port structure istate flags. These set of flags are * modified at interrupt time - so setting and reseting them needs * to be atomic. Use the bit clear/setting routines for this. */#define ASYI_TXBUSY 1#define ASYI_TXLOW 2#define ASYI_DCDCHANGE 3#define ASYI_TXFLOWED 4/* * Define an array of board names as printable strings. Handy for * referencing boards when printing trace and stuff. */static char *stl_brdnames[] = { (char *) NULL, (char *) NULL, (char *) NULL, (char *) NULL, (char *) NULL, (char *) NULL, (char *) NULL, (char *) NULL, (char *) NULL, (char *) NULL, (char *) NULL, (char *) NULL, (char *) NULL, (char *) NULL, (char *) NULL, (char *) NULL, (char *) NULL, (char *) NULL, (char *) NULL, (char *) NULL, "EasyIO", "EC8/32-AT", "EC8/32-MC", (char *) NULL, (char *) NULL, (char *) NULL, "EC8/32-PCI", "EC8/64-PCI", "EasyIO-PCI",};/*****************************************************************************/#ifdef MODULE/* * Define some string labels for arguments passed from the module * load line. These allow for easy board definitions, and easy * modification of the io, memory and irq resoucres. */static char *board0[4];static char *board1[4];static char *board2[4];static char *board3[4];static char **stl_brdsp[] = { (char **) &board0, (char **) &board1, (char **) &board2, (char **) &board3};/* * Define a set of common board names, and types. This is used to * parse any module arguments. */typedef struct stlbrdtype { char *name; int type;} stlbrdtype_t;static stlbrdtype_t stl_brdstr[] = { { "easyio", BRD_EASYIO }, { "eio", BRD_EASYIO }, { "20", BRD_EASYIO }, { "ec8/32", BRD_ECH }, { "ec8/32-at", BRD_ECH }, { "ec8/32-isa", BRD_ECH }, { "ech", BRD_ECH }, { "echat", BRD_ECH }, { "21", BRD_ECH }, { "ec8/32-mc", BRD_ECHMC }, { "ec8/32-mca", BRD_ECHMC }, { "echmc", BRD_ECHMC }, { "echmca", BRD_ECHMC }, { "22", BRD_ECHMC }, { "ec8/32-pc", BRD_ECHPCI }, { "ec8/32-pci", BRD_ECHPCI }, { "26", BRD_ECHPCI }, { "ec8/64-pc", BRD_ECH64PCI }, { "ec8/64-pci", BRD_ECH64PCI }, { "ech-pci", BRD_ECH64PCI }, { "echpci", BRD_ECH64PCI }, { "echpc", BRD_ECH64PCI }, { "27", BRD_ECH64PCI }, { "easyio-pc", BRD_EASYIOPCI }, { "easyio-pci", BRD_EASYIOPCI }, { "eio-pci", BRD_EASYIOPCI }, { "eiopci", BRD_EASYIOPCI }, { "28", BRD_EASYIOPCI },};/* * Define the module agruments. */MODULE_AUTHOR("Greg Ungerer");MODULE_DESCRIPTION("Stallion Multiport Serial Driver");MODULE_PARM(board0, "1-4s");MODULE_PARM_DESC(board0, "Board 0 config -> name[,ioaddr[,ioaddr2][,irq]]");MODULE_PARM(board1, "1-4s");MODULE_PARM_DESC(board1, "Board 1 config -> name[,ioaddr[,ioaddr2][,irq]]");MODULE_PARM(board2, "1-4s");MODULE_PARM_DESC(board2, "Board 2 config -> name[,ioaddr[,ioaddr2][,irq]]");MODULE_PARM(board3, "1-4s");MODULE_PARM_DESC(board3, "Board 3 config -> name[,ioaddr[,ioaddr2][,irq]]");#endif/*****************************************************************************//* * Hardware ID bits for the EasyIO and ECH boards. These defines apply * to the directly accessible io ports of these boards (not the uarts - * they are in cd1400.h and sc26198.h). */#define EIO_8PORTRS 0x04#define EIO_4PORTRS 0x05#define EIO_8PORTDI 0x00#define EIO_8PORTM 0x06#define EIO_MK3 0x03#define EIO_IDBITMASK 0x07#define EIO_BRDMASK 0xf0#define ID_BRD4 0x10#define ID_BRD8 0x20#define ID_BRD16 0x30#define EIO_INTRPEND 0x08#define EIO_INTEDGE 0x00#define EIO_INTLEVEL 0x08#define EIO_0WS 0x10#define ECH_ID 0xa0#define ECH_IDBITMASK 0xe0#define ECH_BRDENABLE 0x08#define ECH_BRDDISABLE 0x00#define ECH_INTENABLE 0x01#define ECH_INTDISABLE 0x00#define ECH_INTLEVEL 0x02#define ECH_INTEDGE 0x00#define ECH_INTRPEND 0x01#define ECH_BRDRESET 0x01#define ECHMC_INTENABLE 0x01#define ECHMC_BRDRESET 0x02#define ECH_PNLSTATUS 2#define ECH_PNL16PORT 0x20#define ECH_PNLIDMASK 0x07#define ECH_PNLXPID 0x40#define ECH_PNLINTRPEND 0x80#define ECH_ADDR2MASK 0x1e0/* * Define the vector mapping bits for the programmable interrupt board * hardware. These bits encode the interrupt for the board to use - it * is software selectable (except the EIO-8M). */static unsigned char stl_vecmap[] = { 0xff, 0xff, 0xff, 0x04, 0x06, 0x05, 0xff, 0x07, 0xff, 0xff, 0x00, 0x02, 0x01, 0xff, 0xff, 0x03};/* * Set up enable and disable macros for the ECH boards. They require * the secondary io address space to be activated and deactivated. * This way all ECH boards can share their secondary io region. * If this is an ECH-PCI board then also need to set the page pointer * to point to the correct page. */#define BRDENABLE(brdnr,pagenr) \ if (stl_brds[(brdnr)]->brdtype == BRD_ECH) \ outb((stl_brds[(brdnr)]->ioctrlval | ECH_BRDENABLE), \ stl_brds[(brdnr)]->ioctrl); \ else if (stl_brds[(brdnr)]->brdtype == BRD_ECHPCI) \ outb((pagenr), stl_brds[(brdnr)]->ioctrl);#define BRDDISABLE(brdnr) \ if (stl_brds[(brdnr)]->brdtype == BRD_ECH) \ outb((stl_brds[(brdnr)]->ioctrlval | ECH_BRDDISABLE), \ stl_brds[(brdnr)]->ioctrl);#define STL_CD1400MAXBAUD 230400#define STL_SC26198MAXBAUD 460800#define STL_BAUDBASE 115200#define STL_CLOSEDELAY (5 * HZ / 10)/*****************************************************************************/#ifdef CONFIG_PCI/* * Define the Stallion PCI vendor and device IDs. */#ifndef PCI_VENDOR_ID_STALLION#define PCI_VENDOR_ID_STALLION 0x124d#endif#ifndef PCI_DEVICE_ID_ECHPCI832#define PCI_DEVICE_ID_ECHPCI832 0x0000#endif#ifndef PCI_DEVICE_ID_ECHPCI864#define PCI_DEVICE_ID_ECHPCI864 0x0002#endif#ifndef PCI_DEVICE_ID_EIOPCI#define PCI_DEVICE_ID_EIOPCI 0x0003#endif/* * Define structure to hold all Stallion PCI boards. */typedef struct stlpcibrd { unsigned short vendid; unsigned short devid; int brdtype;} stlpcibrd_t;static stlpcibrd_t stl_pcibrds[] = { { PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_ECHPCI864, BRD_ECH64PCI }, { PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_EIOPCI, BRD_EASYIOPCI }, { PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_ECHPCI832, BRD_ECHPCI }, { PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87410, BRD_ECHPCI },};static int stl_nrpcibrds = sizeof(stl_pcibrds) / sizeof(stlpcibrd_t);#endif/*****************************************************************************//* * Define macros to extract a brd/port number from a minor number. */#define MINOR2BRD(min) (((min) & 0xc0) >> 6)#define MINOR2PORT(min) ((min) & 0x3f)/* * Define a baud rate table that converts termios baud rate selector * into the actual baud rate value. All baud rate calculations are * based on the actual baud rate required. */static unsigned int stl_baudrates[] = { 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, 9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600};/* * Define some handy local macros... */#undef MIN#define MIN(a,b) (((a) <= (b)) ? (a) : (b))#undef TOLOWER#define TOLOWER(x) ((((x) >= 'A') && ((x) <= 'Z')) ? ((x) + 0x20) : (x))/*****************************************************************************//* * Declare all those functions in this driver! */#ifdef MODULEint init_module(void);void cleanup_module(void);static void stl_argbrds(void);static int stl_parsebrd(stlconf_t *confp, char **argp);static unsigned long stl_atol(char *str);#endifint stl_init(void);static int stl_open(struct tty_struct *tty, struct file *filp);static void stl_close(struct tty_struct *tty, struct file *filp);static int stl_write(struct tty_struct *tty, int from_user, const unsigned char *buf, int count);
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -