blob: 81b3234127db2fae1839568960bbae4110641298 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*****************************************************************************/
2
3/*
4 * stallion.c -- stallion multiport serial driver.
5 *
6 * Copyright (C) 1996-1999 Stallion Technologies
7 * Copyright (C) 1994-1996 Greg Ungerer.
8 *
9 * This code is loosely based on the Linux serial driver, written by
10 * Linus Torvalds, Theodore T'so and others.
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 */
26
27/*****************************************************************************/
28
Linus Torvalds1da177e2005-04-16 15:20:36 -070029#include <linux/module.h>
30#include <linux/slab.h>
31#include <linux/interrupt.h>
32#include <linux/tty.h>
33#include <linux/tty_flip.h>
34#include <linux/serial.h>
35#include <linux/cd1400.h>
36#include <linux/sc26198.h>
37#include <linux/comstats.h>
38#include <linux/stallion.h>
39#include <linux/ioport.h>
40#include <linux/init.h>
41#include <linux/smp_lock.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070042#include <linux/device.h>
43#include <linux/delay.h>
Jiri Slaby843b5682006-12-08 02:39:12 -080044#include <linux/ctype.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070045
46#include <asm/io.h>
47#include <asm/uaccess.h>
48
Linus Torvalds1da177e2005-04-16 15:20:36 -070049#include <linux/pci.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070050
51/*****************************************************************************/
52
53/*
54 * Define different board types. Use the standard Stallion "assigned"
55 * board numbers. Boards supported in this driver are abbreviated as
56 * EIO = EasyIO and ECH = EasyConnection 8/32.
57 */
58#define BRD_EASYIO 20
59#define BRD_ECH 21
60#define BRD_ECHMC 22
61#define BRD_ECHPCI 26
62#define BRD_ECH64PCI 27
63#define BRD_EASYIOPCI 28
64
Jiri Slaby843b5682006-12-08 02:39:12 -080065struct stlconf {
Jiri Slaby6b2c9452006-12-08 02:39:15 -080066 unsigned int brdtype;
Linus Torvalds1da177e2005-04-16 15:20:36 -070067 int ioaddr1;
68 int ioaddr2;
69 unsigned long memaddr;
70 int irq;
71 int irqtype;
Linus Torvalds1da177e2005-04-16 15:20:36 -070072};
73
Jiri Slaby843b5682006-12-08 02:39:12 -080074static unsigned int stl_nrbrds;
Linus Torvalds1da177e2005-04-16 15:20:36 -070075
76/*****************************************************************************/
77
78/*
79 * Define some important driver characteristics. Device major numbers
80 * allocated as per Linux Device Registry.
81 */
82#ifndef STL_SIOMEMMAJOR
83#define STL_SIOMEMMAJOR 28
84#endif
85#ifndef STL_SERIALMAJOR
86#define STL_SERIALMAJOR 24
87#endif
88#ifndef STL_CALLOUTMAJOR
89#define STL_CALLOUTMAJOR 25
90#endif
91
92/*
93 * Set the TX buffer size. Bigger is better, but we don't want
94 * to chew too much memory with buffers!
95 */
96#define STL_TXBUFLOW 512
97#define STL_TXBUFSIZE 4096
98
99/*****************************************************************************/
100
101/*
102 * Define our local driver identity first. Set up stuff to deal with
103 * all the local structures required by a serial tty driver.
104 */
105static char *stl_drvtitle = "Stallion Multiport Serial Driver";
106static char *stl_drvname = "stallion";
107static char *stl_drvversion = "5.6.0";
108
109static struct tty_driver *stl_serial;
110
111/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700112 * Define a local default termios struct. All ports will be created
113 * with this termios initially. Basically all it defines is a raw port
114 * at 9600, 8 data bits, 1 stop bit.
115 */
Alan Cox606d0992006-12-08 02:38:45 -0800116static struct ktermios stl_deftermios = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700117 .c_cflag = (B9600 | CS8 | CREAD | HUPCL | CLOCAL),
118 .c_cc = INIT_C_CC,
Alan Cox606d0992006-12-08 02:38:45 -0800119 .c_ispeed = 9600,
120 .c_ospeed = 9600,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700121};
122
123/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700124 * Define global place to put buffer overflow characters.
125 */
126static char stl_unwanted[SC26198_RXFIFOSIZE];
127
128/*****************************************************************************/
129
Jiri Slaby79cfe7a2006-12-08 02:39:14 -0800130static DEFINE_MUTEX(stl_brdslock);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800131static struct stlbrd *stl_brds[STL_MAXBRDS];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700132
133/*
134 * Per board state flags. Used with the state field of the board struct.
135 * Not really much here!
136 */
137#define BRD_FOUND 0x1
Jiri Slabyfc06b5c2006-12-08 02:39:13 -0800138#define STL_PROBED 0x2
139
Linus Torvalds1da177e2005-04-16 15:20:36 -0700140
141/*
142 * Define the port structure istate flags. These set of flags are
143 * modified at interrupt time - so setting and reseting them needs
144 * to be atomic. Use the bit clear/setting routines for this.
145 */
146#define ASYI_TXBUSY 1
147#define ASYI_TXLOW 2
Jiri Slabyccfea3c2008-02-07 00:16:39 -0800148#define ASYI_TXFLOWED 3
Linus Torvalds1da177e2005-04-16 15:20:36 -0700149
150/*
151 * Define an array of board names as printable strings. Handy for
152 * referencing boards when printing trace and stuff.
153 */
154static char *stl_brdnames[] = {
Jiri Slaby615e4a72006-12-08 02:38:38 -0800155 NULL,
156 NULL,
157 NULL,
158 NULL,
159 NULL,
160 NULL,
161 NULL,
162 NULL,
163 NULL,
164 NULL,
165 NULL,
166 NULL,
167 NULL,
168 NULL,
169 NULL,
170 NULL,
171 NULL,
172 NULL,
173 NULL,
174 NULL,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700175 "EasyIO",
176 "EC8/32-AT",
177 "EC8/32-MC",
Jiri Slaby615e4a72006-12-08 02:38:38 -0800178 NULL,
179 NULL,
180 NULL,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700181 "EC8/32-PCI",
182 "EC8/64-PCI",
183 "EasyIO-PCI",
184};
185
186/*****************************************************************************/
187
188/*
189 * Define some string labels for arguments passed from the module
190 * load line. These allow for easy board definitions, and easy
191 * modification of the io, memory and irq resoucres.
192 */
Jiri Slaby6b2c9452006-12-08 02:39:15 -0800193static unsigned int stl_nargs;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700194static char *board0[4];
195static char *board1[4];
196static char *board2[4];
197static char *board3[4];
198
199static char **stl_brdsp[] = {
200 (char **) &board0,
201 (char **) &board1,
202 (char **) &board2,
203 (char **) &board3
204};
205
206/*
207 * Define a set of common board names, and types. This is used to
208 * parse any module arguments.
209 */
210
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800211static struct {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700212 char *name;
213 int type;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800214} stl_brdstr[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700215 { "easyio", BRD_EASYIO },
216 { "eio", BRD_EASYIO },
217 { "20", BRD_EASYIO },
218 { "ec8/32", BRD_ECH },
219 { "ec8/32-at", BRD_ECH },
220 { "ec8/32-isa", BRD_ECH },
221 { "ech", BRD_ECH },
222 { "echat", BRD_ECH },
223 { "21", BRD_ECH },
224 { "ec8/32-mc", BRD_ECHMC },
225 { "ec8/32-mca", BRD_ECHMC },
226 { "echmc", BRD_ECHMC },
227 { "echmca", BRD_ECHMC },
228 { "22", BRD_ECHMC },
229 { "ec8/32-pc", BRD_ECHPCI },
230 { "ec8/32-pci", BRD_ECHPCI },
231 { "26", BRD_ECHPCI },
232 { "ec8/64-pc", BRD_ECH64PCI },
233 { "ec8/64-pci", BRD_ECH64PCI },
234 { "ech-pci", BRD_ECH64PCI },
235 { "echpci", BRD_ECH64PCI },
236 { "echpc", BRD_ECH64PCI },
237 { "27", BRD_ECH64PCI },
238 { "easyio-pc", BRD_EASYIOPCI },
239 { "easyio-pci", BRD_EASYIOPCI },
240 { "eio-pci", BRD_EASYIOPCI },
241 { "eiopci", BRD_EASYIOPCI },
242 { "28", BRD_EASYIOPCI },
243};
244
245/*
246 * Define the module agruments.
247 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700248
249module_param_array(board0, charp, &stl_nargs, 0);
250MODULE_PARM_DESC(board0, "Board 0 config -> name[,ioaddr[,ioaddr2][,irq]]");
251module_param_array(board1, charp, &stl_nargs, 0);
252MODULE_PARM_DESC(board1, "Board 1 config -> name[,ioaddr[,ioaddr2][,irq]]");
253module_param_array(board2, charp, &stl_nargs, 0);
254MODULE_PARM_DESC(board2, "Board 2 config -> name[,ioaddr[,ioaddr2][,irq]]");
255module_param_array(board3, charp, &stl_nargs, 0);
256MODULE_PARM_DESC(board3, "Board 3 config -> name[,ioaddr[,ioaddr2][,irq]]");
257
258/*****************************************************************************/
259
260/*
261 * Hardware ID bits for the EasyIO and ECH boards. These defines apply
262 * to the directly accessible io ports of these boards (not the uarts -
263 * they are in cd1400.h and sc26198.h).
264 */
265#define EIO_8PORTRS 0x04
266#define EIO_4PORTRS 0x05
267#define EIO_8PORTDI 0x00
268#define EIO_8PORTM 0x06
269#define EIO_MK3 0x03
270#define EIO_IDBITMASK 0x07
271
272#define EIO_BRDMASK 0xf0
273#define ID_BRD4 0x10
274#define ID_BRD8 0x20
275#define ID_BRD16 0x30
276
277#define EIO_INTRPEND 0x08
278#define EIO_INTEDGE 0x00
279#define EIO_INTLEVEL 0x08
280#define EIO_0WS 0x10
281
282#define ECH_ID 0xa0
283#define ECH_IDBITMASK 0xe0
284#define ECH_BRDENABLE 0x08
285#define ECH_BRDDISABLE 0x00
286#define ECH_INTENABLE 0x01
287#define ECH_INTDISABLE 0x00
288#define ECH_INTLEVEL 0x02
289#define ECH_INTEDGE 0x00
290#define ECH_INTRPEND 0x01
291#define ECH_BRDRESET 0x01
292
293#define ECHMC_INTENABLE 0x01
294#define ECHMC_BRDRESET 0x02
295
296#define ECH_PNLSTATUS 2
297#define ECH_PNL16PORT 0x20
298#define ECH_PNLIDMASK 0x07
299#define ECH_PNLXPID 0x40
300#define ECH_PNLINTRPEND 0x80
301
302#define ECH_ADDR2MASK 0x1e0
303
304/*
305 * Define the vector mapping bits for the programmable interrupt board
306 * hardware. These bits encode the interrupt for the board to use - it
307 * is software selectable (except the EIO-8M).
308 */
309static unsigned char stl_vecmap[] = {
310 0xff, 0xff, 0xff, 0x04, 0x06, 0x05, 0xff, 0x07,
311 0xff, 0xff, 0x00, 0x02, 0x01, 0xff, 0xff, 0x03
312};
313
314/*
Alan Coxb65b5b52006-06-27 02:54:05 -0700315 * Lock ordering is that you may not take stallion_lock holding
316 * brd_lock.
317 */
318
319static spinlock_t brd_lock; /* Guard the board mapping */
320static spinlock_t stallion_lock; /* Guard the tty driver */
321
322/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700323 * Set up enable and disable macros for the ECH boards. They require
324 * the secondary io address space to be activated and deactivated.
325 * This way all ECH boards can share their secondary io region.
326 * If this is an ECH-PCI board then also need to set the page pointer
327 * to point to the correct page.
328 */
329#define BRDENABLE(brdnr,pagenr) \
330 if (stl_brds[(brdnr)]->brdtype == BRD_ECH) \
331 outb((stl_brds[(brdnr)]->ioctrlval | ECH_BRDENABLE), \
332 stl_brds[(brdnr)]->ioctrl); \
333 else if (stl_brds[(brdnr)]->brdtype == BRD_ECHPCI) \
334 outb((pagenr), stl_brds[(brdnr)]->ioctrl);
335
336#define BRDDISABLE(brdnr) \
337 if (stl_brds[(brdnr)]->brdtype == BRD_ECH) \
338 outb((stl_brds[(brdnr)]->ioctrlval | ECH_BRDDISABLE), \
339 stl_brds[(brdnr)]->ioctrl);
340
341#define STL_CD1400MAXBAUD 230400
342#define STL_SC26198MAXBAUD 460800
343
344#define STL_BAUDBASE 115200
345#define STL_CLOSEDELAY (5 * HZ / 10)
346
347/*****************************************************************************/
348
Linus Torvalds1da177e2005-04-16 15:20:36 -0700349/*
350 * Define the Stallion PCI vendor and device IDs.
351 */
352#ifndef PCI_VENDOR_ID_STALLION
353#define PCI_VENDOR_ID_STALLION 0x124d
354#endif
355#ifndef PCI_DEVICE_ID_ECHPCI832
356#define PCI_DEVICE_ID_ECHPCI832 0x0000
357#endif
358#ifndef PCI_DEVICE_ID_ECHPCI864
359#define PCI_DEVICE_ID_ECHPCI864 0x0002
360#endif
361#ifndef PCI_DEVICE_ID_EIOPCI
362#define PCI_DEVICE_ID_EIOPCI 0x0003
363#endif
364
365/*
366 * Define structure to hold all Stallion PCI boards.
367 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700368
Jiri Slabyb1b84fe2006-12-08 02:39:09 -0800369static struct pci_device_id stl_pcibrds[] = {
370 { PCI_DEVICE(PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_ECHPCI864),
371 .driver_data = BRD_ECH64PCI },
372 { PCI_DEVICE(PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_EIOPCI),
373 .driver_data = BRD_EASYIOPCI },
374 { PCI_DEVICE(PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_ECHPCI832),
375 .driver_data = BRD_ECHPCI },
376 { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87410),
377 .driver_data = BRD_ECHPCI },
378 { }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700379};
Jiri Slabyb1b84fe2006-12-08 02:39:09 -0800380MODULE_DEVICE_TABLE(pci, stl_pcibrds);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700381
382/*****************************************************************************/
383
384/*
385 * Define macros to extract a brd/port number from a minor number.
386 */
387#define MINOR2BRD(min) (((min) & 0xc0) >> 6)
388#define MINOR2PORT(min) ((min) & 0x3f)
389
390/*
391 * Define a baud rate table that converts termios baud rate selector
392 * into the actual baud rate value. All baud rate calculations are
393 * based on the actual baud rate required.
394 */
395static unsigned int stl_baudrates[] = {
396 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
397 9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600
398};
399
Linus Torvalds1da177e2005-04-16 15:20:36 -0700400/*****************************************************************************/
401
402/*
403 * Declare all those functions in this driver!
404 */
405
Linus Torvalds1da177e2005-04-16 15:20:36 -0700406static int stl_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800407static int stl_brdinit(struct stlbrd *brdp);
Alan Coxd18a7502008-10-13 10:40:07 +0100408static int stl_getportstats(struct tty_struct *tty, struct stlport *portp, comstats_t __user *cp);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800409static int stl_clrportstats(struct stlport *portp, comstats_t __user *cp);
Alan Coxd18a7502008-10-13 10:40:07 +0100410static int stl_waitcarrier(struct tty_struct *tty, struct stlport *portp, struct file *filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700411
Linus Torvalds1da177e2005-04-16 15:20:36 -0700412/*
413 * CD1400 uart specific handling functions.
414 */
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800415static void stl_cd1400setreg(struct stlport *portp, int regnr, int value);
416static int stl_cd1400getreg(struct stlport *portp, int regnr);
417static int stl_cd1400updatereg(struct stlport *portp, int regnr, int value);
418static int stl_cd1400panelinit(struct stlbrd *brdp, struct stlpanel *panelp);
419static void stl_cd1400portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp);
Alan Cox606d0992006-12-08 02:38:45 -0800420static void stl_cd1400setport(struct stlport *portp, struct ktermios *tiosp);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800421static int stl_cd1400getsignals(struct stlport *portp);
422static void stl_cd1400setsignals(struct stlport *portp, int dtr, int rts);
423static void stl_cd1400ccrwait(struct stlport *portp);
424static void stl_cd1400enablerxtx(struct stlport *portp, int rx, int tx);
425static void stl_cd1400startrxtx(struct stlport *portp, int rx, int tx);
426static void stl_cd1400disableintrs(struct stlport *portp);
427static void stl_cd1400sendbreak(struct stlport *portp, int len);
428static void stl_cd1400flowctrl(struct stlport *portp, int state);
429static void stl_cd1400sendflow(struct stlport *portp, int state);
430static void stl_cd1400flush(struct stlport *portp);
431static int stl_cd1400datastate(struct stlport *portp);
432static void stl_cd1400eiointr(struct stlpanel *panelp, unsigned int iobase);
433static void stl_cd1400echintr(struct stlpanel *panelp, unsigned int iobase);
434static void stl_cd1400txisr(struct stlpanel *panelp, int ioaddr);
435static void stl_cd1400rxisr(struct stlpanel *panelp, int ioaddr);
436static void stl_cd1400mdmisr(struct stlpanel *panelp, int ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700437
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800438static inline int stl_cd1400breakisr(struct stlport *portp, int ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700439
440/*
441 * SC26198 uart specific handling functions.
442 */
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800443static void stl_sc26198setreg(struct stlport *portp, int regnr, int value);
444static int stl_sc26198getreg(struct stlport *portp, int regnr);
445static int stl_sc26198updatereg(struct stlport *portp, int regnr, int value);
446static int stl_sc26198getglobreg(struct stlport *portp, int regnr);
447static int stl_sc26198panelinit(struct stlbrd *brdp, struct stlpanel *panelp);
448static void stl_sc26198portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp);
Alan Cox606d0992006-12-08 02:38:45 -0800449static void stl_sc26198setport(struct stlport *portp, struct ktermios *tiosp);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800450static int stl_sc26198getsignals(struct stlport *portp);
451static void stl_sc26198setsignals(struct stlport *portp, int dtr, int rts);
452static void stl_sc26198enablerxtx(struct stlport *portp, int rx, int tx);
453static void stl_sc26198startrxtx(struct stlport *portp, int rx, int tx);
454static void stl_sc26198disableintrs(struct stlport *portp);
455static void stl_sc26198sendbreak(struct stlport *portp, int len);
456static void stl_sc26198flowctrl(struct stlport *portp, int state);
457static void stl_sc26198sendflow(struct stlport *portp, int state);
458static void stl_sc26198flush(struct stlport *portp);
459static int stl_sc26198datastate(struct stlport *portp);
460static void stl_sc26198wait(struct stlport *portp);
461static void stl_sc26198txunflow(struct stlport *portp, struct tty_struct *tty);
462static void stl_sc26198intr(struct stlpanel *panelp, unsigned int iobase);
463static void stl_sc26198txisr(struct stlport *port);
464static void stl_sc26198rxisr(struct stlport *port, unsigned int iack);
465static void stl_sc26198rxbadch(struct stlport *portp, unsigned char status, char ch);
466static void stl_sc26198rxbadchars(struct stlport *portp);
467static void stl_sc26198otherisr(struct stlport *port, unsigned int iack);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700468
469/*****************************************************************************/
470
471/*
472 * Generic UART support structure.
473 */
474typedef struct uart {
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800475 int (*panelinit)(struct stlbrd *brdp, struct stlpanel *panelp);
476 void (*portinit)(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp);
Alan Cox606d0992006-12-08 02:38:45 -0800477 void (*setport)(struct stlport *portp, struct ktermios *tiosp);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800478 int (*getsignals)(struct stlport *portp);
479 void (*setsignals)(struct stlport *portp, int dtr, int rts);
480 void (*enablerxtx)(struct stlport *portp, int rx, int tx);
481 void (*startrxtx)(struct stlport *portp, int rx, int tx);
482 void (*disableintrs)(struct stlport *portp);
483 void (*sendbreak)(struct stlport *portp, int len);
484 void (*flowctrl)(struct stlport *portp, int state);
485 void (*sendflow)(struct stlport *portp, int state);
486 void (*flush)(struct stlport *portp);
487 int (*datastate)(struct stlport *portp);
488 void (*intr)(struct stlpanel *panelp, unsigned int iobase);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700489} uart_t;
490
491/*
492 * Define some macros to make calling these functions nice and clean.
493 */
494#define stl_panelinit (* ((uart_t *) panelp->uartp)->panelinit)
495#define stl_portinit (* ((uart_t *) portp->uartp)->portinit)
496#define stl_setport (* ((uart_t *) portp->uartp)->setport)
497#define stl_getsignals (* ((uart_t *) portp->uartp)->getsignals)
498#define stl_setsignals (* ((uart_t *) portp->uartp)->setsignals)
499#define stl_enablerxtx (* ((uart_t *) portp->uartp)->enablerxtx)
500#define stl_startrxtx (* ((uart_t *) portp->uartp)->startrxtx)
501#define stl_disableintrs (* ((uart_t *) portp->uartp)->disableintrs)
502#define stl_sendbreak (* ((uart_t *) portp->uartp)->sendbreak)
503#define stl_flowctrl (* ((uart_t *) portp->uartp)->flowctrl)
504#define stl_sendflow (* ((uart_t *) portp->uartp)->sendflow)
505#define stl_flush (* ((uart_t *) portp->uartp)->flush)
506#define stl_datastate (* ((uart_t *) portp->uartp)->datastate)
507
508/*****************************************************************************/
509
510/*
511 * CD1400 UART specific data initialization.
512 */
513static uart_t stl_cd1400uart = {
514 stl_cd1400panelinit,
515 stl_cd1400portinit,
516 stl_cd1400setport,
517 stl_cd1400getsignals,
518 stl_cd1400setsignals,
519 stl_cd1400enablerxtx,
520 stl_cd1400startrxtx,
521 stl_cd1400disableintrs,
522 stl_cd1400sendbreak,
523 stl_cd1400flowctrl,
524 stl_cd1400sendflow,
525 stl_cd1400flush,
526 stl_cd1400datastate,
527 stl_cd1400eiointr
528};
529
530/*
531 * Define the offsets within the register bank of a cd1400 based panel.
532 * These io address offsets are common to the EasyIO board as well.
533 */
534#define EREG_ADDR 0
535#define EREG_DATA 4
536#define EREG_RXACK 5
537#define EREG_TXACK 6
538#define EREG_MDACK 7
539
540#define EREG_BANKSIZE 8
541
542#define CD1400_CLK 25000000
543#define CD1400_CLK8M 20000000
544
545/*
546 * Define the cd1400 baud rate clocks. These are used when calculating
547 * what clock and divisor to use for the required baud rate. Also
548 * define the maximum baud rate allowed, and the default base baud.
549 */
550static int stl_cd1400clkdivs[] = {
551 CD1400_CLK0, CD1400_CLK1, CD1400_CLK2, CD1400_CLK3, CD1400_CLK4
552};
553
554/*****************************************************************************/
555
556/*
557 * SC26198 UART specific data initization.
558 */
559static uart_t stl_sc26198uart = {
560 stl_sc26198panelinit,
561 stl_sc26198portinit,
562 stl_sc26198setport,
563 stl_sc26198getsignals,
564 stl_sc26198setsignals,
565 stl_sc26198enablerxtx,
566 stl_sc26198startrxtx,
567 stl_sc26198disableintrs,
568 stl_sc26198sendbreak,
569 stl_sc26198flowctrl,
570 stl_sc26198sendflow,
571 stl_sc26198flush,
572 stl_sc26198datastate,
573 stl_sc26198intr
574};
575
576/*
577 * Define the offsets within the register bank of a sc26198 based panel.
578 */
579#define XP_DATA 0
580#define XP_ADDR 1
581#define XP_MODID 2
582#define XP_STATUS 2
583#define XP_IACK 3
584
585#define XP_BANKSIZE 4
586
587/*
588 * Define the sc26198 baud rate table. Offsets within the table
589 * represent the actual baud rate selector of sc26198 registers.
590 */
591static unsigned int sc26198_baudtable[] = {
592 50, 75, 150, 200, 300, 450, 600, 900, 1200, 1800, 2400, 3600,
593 4800, 7200, 9600, 14400, 19200, 28800, 38400, 57600, 115200,
594 230400, 460800, 921600
595};
596
Tobias Klauserfe971072006-01-09 20:54:02 -0800597#define SC26198_NRBAUDS ARRAY_SIZE(sc26198_baudtable)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700598
599/*****************************************************************************/
600
601/*
602 * Define the driver info for a user level control device. Used mainly
603 * to get at port stats - only not using the port device itself.
604 */
Arjan van de Ven62322d22006-07-03 00:24:21 -0700605static const struct file_operations stl_fsiomem = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700606 .owner = THIS_MODULE,
607 .ioctl = stl_memioctl,
608};
609
gregkh@suse.deca8eca62005-03-23 09:53:09 -0800610static struct class *stallion_class;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700611
Jiri Slabyccfea3c2008-02-07 00:16:39 -0800612static void stl_cd_change(struct stlport *portp)
613{
614 unsigned int oldsigs = portp->sigs;
Alan Coxd18a7502008-10-13 10:40:07 +0100615 struct tty_struct *tty = tty_port_tty_get(&portp->port);
Jiri Slabyccfea3c2008-02-07 00:16:39 -0800616
Alan Coxd18a7502008-10-13 10:40:07 +0100617 if (!tty)
Jiri Slabyccfea3c2008-02-07 00:16:39 -0800618 return;
619
620 portp->sigs = stl_getsignals(portp);
621
622 if ((portp->sigs & TIOCM_CD) && ((oldsigs & TIOCM_CD) == 0))
Alan Coxf8ae4762008-07-16 21:56:37 +0100623 wake_up_interruptible(&portp->port.open_wait);
Jiri Slabyccfea3c2008-02-07 00:16:39 -0800624
625 if ((oldsigs & TIOCM_CD) && ((portp->sigs & TIOCM_CD) == 0))
Alan Coxf8ae4762008-07-16 21:56:37 +0100626 if (portp->port.flags & ASYNC_CHECK_CD)
Alan Coxd18a7502008-10-13 10:40:07 +0100627 tty_hangup(tty);
628 tty_kref_put(tty);
Jiri Slabyccfea3c2008-02-07 00:16:39 -0800629}
630
Linus Torvalds1da177e2005-04-16 15:20:36 -0700631/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700632 * Check for any arguments passed in on the module load command line.
633 */
634
Linus Torvalds1da177e2005-04-16 15:20:36 -0700635/*****************************************************************************/
636
637/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700638 * Parse the supplied argument string, into the board conf struct.
639 */
640
Jiri Slaby40e82652006-12-08 02:38:41 -0800641static int __init stl_parsebrd(struct stlconf *confp, char **argp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700642{
643 char *sp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -0800644 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700645
Jiri Slabya0564e12006-12-08 02:38:37 -0800646 pr_debug("stl_parsebrd(confp=%p,argp=%p)\n", confp, argp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700647
Jiri Slaby615e4a72006-12-08 02:38:38 -0800648 if ((argp[0] == NULL) || (*argp[0] == 0))
Jesper Juhl014c2542006-01-15 02:37:08 +0100649 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700650
Jiri Slabyc62429d2006-12-08 02:39:14 -0800651 for (sp = argp[0], i = 0; (*sp != 0) && (i < 25); sp++, i++)
Jiri Slaby843b5682006-12-08 02:39:12 -0800652 *sp = tolower(*sp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700653
Jiri Slabyc62429d2006-12-08 02:39:14 -0800654 for (i = 0; i < ARRAY_SIZE(stl_brdstr); i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700655 if (strcmp(stl_brdstr[i].name, argp[0]) == 0)
656 break;
Jiri Slabyc62429d2006-12-08 02:39:14 -0800657
Tobias Klauserfe971072006-01-09 20:54:02 -0800658 if (i == ARRAY_SIZE(stl_brdstr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700659 printk("STALLION: unknown board name, %s?\n", argp[0]);
Tobias Klauserfe971072006-01-09 20:54:02 -0800660 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700661 }
662
663 confp->brdtype = stl_brdstr[i].type;
664
665 i = 1;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800666 if ((argp[i] != NULL) && (*argp[i] != 0))
Jiri Slaby843b5682006-12-08 02:39:12 -0800667 confp->ioaddr1 = simple_strtoul(argp[i], NULL, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700668 i++;
669 if (confp->brdtype == BRD_ECH) {
Jiri Slaby615e4a72006-12-08 02:38:38 -0800670 if ((argp[i] != NULL) && (*argp[i] != 0))
Jiri Slaby843b5682006-12-08 02:39:12 -0800671 confp->ioaddr2 = simple_strtoul(argp[i], NULL, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700672 i++;
673 }
Jiri Slaby615e4a72006-12-08 02:38:38 -0800674 if ((argp[i] != NULL) && (*argp[i] != 0))
Jiri Slaby843b5682006-12-08 02:39:12 -0800675 confp->irq = simple_strtoul(argp[i], NULL, 0);
Jesper Juhl014c2542006-01-15 02:37:08 +0100676 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700677}
678
679/*****************************************************************************/
680
681/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700682 * Allocate a new board structure. Fill out the basic info in it.
683 */
684
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800685static struct stlbrd *stl_allocbrd(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700686{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800687 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700688
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800689 brdp = kzalloc(sizeof(struct stlbrd), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -0800690 if (!brdp) {
Alan Coxb65b5b52006-06-27 02:54:05 -0700691 printk("STALLION: failed to allocate memory (size=%Zd)\n",
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800692 sizeof(struct stlbrd));
Tobias Klauserb0b4ed72006-03-31 02:30:56 -0800693 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700694 }
695
Linus Torvalds1da177e2005-04-16 15:20:36 -0700696 brdp->magic = STL_BOARDMAGIC;
Jesper Juhl014c2542006-01-15 02:37:08 +0100697 return brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700698}
699
700/*****************************************************************************/
701
702static int stl_open(struct tty_struct *tty, struct file *filp)
703{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800704 struct stlport *portp;
705 struct stlbrd *brdp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -0800706 unsigned int minordev, brdnr, panelnr;
707 int portnr, rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700708
Jiri Slabya0564e12006-12-08 02:38:37 -0800709 pr_debug("stl_open(tty=%p,filp=%p): device=%s\n", tty, filp, tty->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700710
711 minordev = tty->index;
712 brdnr = MINOR2BRD(minordev);
713 if (brdnr >= stl_nrbrds)
Jesper Juhl014c2542006-01-15 02:37:08 +0100714 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700715 brdp = stl_brds[brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -0800716 if (brdp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +0100717 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700718 minordev = MINOR2PORT(minordev);
Jiri Slabyc62429d2006-12-08 02:39:14 -0800719 for (portnr = -1, panelnr = 0; panelnr < STL_MAXPANELS; panelnr++) {
Jiri Slaby615e4a72006-12-08 02:38:38 -0800720 if (brdp->panels[panelnr] == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700721 break;
722 if (minordev < brdp->panels[panelnr]->nrports) {
723 portnr = minordev;
724 break;
725 }
726 minordev -= brdp->panels[panelnr]->nrports;
727 }
728 if (portnr < 0)
Jesper Juhl014c2542006-01-15 02:37:08 +0100729 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700730
731 portp = brdp->panels[panelnr]->ports[portnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -0800732 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +0100733 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700734
735/*
736 * On the first open of the device setup the port hardware, and
737 * initialize the per port data structure.
738 */
Alan Coxd18a7502008-10-13 10:40:07 +0100739 tty_port_tty_set(&portp->port, tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700740 tty->driver_data = portp;
Alan Coxf8ae4762008-07-16 21:56:37 +0100741 portp->port.count++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700742
Alan Coxf8ae4762008-07-16 21:56:37 +0100743 if ((portp->port.flags & ASYNC_INITIALIZED) == 0) {
Tobias Klauserb0b4ed72006-03-31 02:30:56 -0800744 if (!portp->tx.buf) {
745 portp->tx.buf = kmalloc(STL_TXBUFSIZE, GFP_KERNEL);
746 if (!portp->tx.buf)
Jesper Juhl014c2542006-01-15 02:37:08 +0100747 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700748 portp->tx.head = portp->tx.buf;
749 portp->tx.tail = portp->tx.buf;
750 }
751 stl_setport(portp, tty->termios);
752 portp->sigs = stl_getsignals(portp);
753 stl_setsignals(portp, 1, 1);
754 stl_enablerxtx(portp, 1, 1);
755 stl_startrxtx(portp, 1, 0);
756 clear_bit(TTY_IO_ERROR, &tty->flags);
Alan Coxf8ae4762008-07-16 21:56:37 +0100757 portp->port.flags |= ASYNC_INITIALIZED;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700758 }
759
760/*
761 * Check if this port is in the middle of closing. If so then wait
762 * until it is closed then return error status, based on flag settings.
763 * The sleep here does not need interrupt protection since the wakeup
764 * for it is done with the same context.
765 */
Alan Coxf8ae4762008-07-16 21:56:37 +0100766 if (portp->port.flags & ASYNC_CLOSING) {
767 interruptible_sleep_on(&portp->port.close_wait);
768 if (portp->port.flags & ASYNC_HUP_NOTIFY)
Jesper Juhl014c2542006-01-15 02:37:08 +0100769 return -EAGAIN;
770 return -ERESTARTSYS;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700771 }
772
773/*
774 * Based on type of open being done check if it can overlap with any
775 * previous opens still in effect. If we are a normal serial device
776 * then also we might have to wait for carrier.
777 */
Jiri Slabyc62429d2006-12-08 02:39:14 -0800778 if (!(filp->f_flags & O_NONBLOCK))
Alan Coxd18a7502008-10-13 10:40:07 +0100779 if ((rc = stl_waitcarrier(tty, portp, filp)) != 0)
Jesper Juhl014c2542006-01-15 02:37:08 +0100780 return rc;
Jiri Slabyc62429d2006-12-08 02:39:14 -0800781
Alan Coxf8ae4762008-07-16 21:56:37 +0100782 portp->port.flags |= ASYNC_NORMAL_ACTIVE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700783
Jesper Juhl014c2542006-01-15 02:37:08 +0100784 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700785}
786
787/*****************************************************************************/
788
789/*
790 * Possibly need to wait for carrier (DCD signal) to come high. Say
791 * maybe because if we are clocal then we don't need to wait...
792 */
793
Alan Coxd18a7502008-10-13 10:40:07 +0100794static int stl_waitcarrier(struct tty_struct *tty, struct stlport *portp,
795 struct file *filp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700796{
797 unsigned long flags;
798 int rc, doclocal;
799
Jiri Slabya0564e12006-12-08 02:38:37 -0800800 pr_debug("stl_waitcarrier(portp=%p,filp=%p)\n", portp, filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700801
802 rc = 0;
803 doclocal = 0;
804
Alan Coxb65b5b52006-06-27 02:54:05 -0700805 spin_lock_irqsave(&stallion_lock, flags);
806
Alan Coxd18a7502008-10-13 10:40:07 +0100807 if (tty->termios->c_cflag & CLOCAL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700808 doclocal++;
809
Linus Torvalds1da177e2005-04-16 15:20:36 -0700810 portp->openwaitcnt++;
811 if (! tty_hung_up_p(filp))
Alan Coxf8ae4762008-07-16 21:56:37 +0100812 portp->port.count--;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700813
814 for (;;) {
Alan Coxb65b5b52006-06-27 02:54:05 -0700815 /* Takes brd_lock internally */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700816 stl_setsignals(portp, 1, 1);
817 if (tty_hung_up_p(filp) ||
Alan Coxf8ae4762008-07-16 21:56:37 +0100818 ((portp->port.flags & ASYNC_INITIALIZED) == 0)) {
819 if (portp->port.flags & ASYNC_HUP_NOTIFY)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700820 rc = -EBUSY;
821 else
822 rc = -ERESTARTSYS;
823 break;
824 }
Alan Coxf8ae4762008-07-16 21:56:37 +0100825 if (((portp->port.flags & ASYNC_CLOSING) == 0) &&
Jiri Slabyc62429d2006-12-08 02:39:14 -0800826 (doclocal || (portp->sigs & TIOCM_CD)))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700827 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700828 if (signal_pending(current)) {
829 rc = -ERESTARTSYS;
830 break;
831 }
Alan Coxb65b5b52006-06-27 02:54:05 -0700832 /* FIXME */
Alan Coxf8ae4762008-07-16 21:56:37 +0100833 interruptible_sleep_on(&portp->port.open_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700834 }
835
836 if (! tty_hung_up_p(filp))
Alan Coxf8ae4762008-07-16 21:56:37 +0100837 portp->port.count++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700838 portp->openwaitcnt--;
Alan Coxb65b5b52006-06-27 02:54:05 -0700839 spin_unlock_irqrestore(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700840
Jesper Juhl014c2542006-01-15 02:37:08 +0100841 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700842}
843
844/*****************************************************************************/
845
Jiri Slaby96b066b2006-12-08 02:38:42 -0800846static void stl_flushbuffer(struct tty_struct *tty)
847{
848 struct stlport *portp;
849
850 pr_debug("stl_flushbuffer(tty=%p)\n", tty);
851
852 if (tty == NULL)
853 return;
854 portp = tty->driver_data;
855 if (portp == NULL)
856 return;
857
858 stl_flush(portp);
859 tty_wakeup(tty);
860}
861
862/*****************************************************************************/
863
864static void stl_waituntilsent(struct tty_struct *tty, int timeout)
865{
866 struct stlport *portp;
867 unsigned long tend;
868
869 pr_debug("stl_waituntilsent(tty=%p,timeout=%d)\n", tty, timeout);
870
871 if (tty == NULL)
872 return;
873 portp = tty->driver_data;
874 if (portp == NULL)
875 return;
876
877 if (timeout == 0)
878 timeout = HZ;
879 tend = jiffies + timeout;
880
Alan Cox978e5952008-04-30 00:53:59 -0700881 lock_kernel();
Jiri Slaby96b066b2006-12-08 02:38:42 -0800882 while (stl_datastate(portp)) {
883 if (signal_pending(current))
884 break;
885 msleep_interruptible(20);
886 if (time_after_eq(jiffies, tend))
887 break;
888 }
Alan Cox978e5952008-04-30 00:53:59 -0700889 unlock_kernel();
Jiri Slaby96b066b2006-12-08 02:38:42 -0800890}
891
892/*****************************************************************************/
893
Linus Torvalds1da177e2005-04-16 15:20:36 -0700894static void stl_close(struct tty_struct *tty, struct file *filp)
895{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800896 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700897 unsigned long flags;
898
Jiri Slabya0564e12006-12-08 02:38:37 -0800899 pr_debug("stl_close(tty=%p,filp=%p)\n", tty, filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700900
901 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800902 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700903 return;
904
Alan Coxb65b5b52006-06-27 02:54:05 -0700905 spin_lock_irqsave(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700906 if (tty_hung_up_p(filp)) {
Alan Coxb65b5b52006-06-27 02:54:05 -0700907 spin_unlock_irqrestore(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700908 return;
909 }
Alan Coxf8ae4762008-07-16 21:56:37 +0100910 if ((tty->count == 1) && (portp->port.count != 1))
911 portp->port.count = 1;
912 if (portp->port.count-- > 1) {
Alan Coxb65b5b52006-06-27 02:54:05 -0700913 spin_unlock_irqrestore(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700914 return;
915 }
916
Alan Coxf8ae4762008-07-16 21:56:37 +0100917 portp->port.count = 0;
918 portp->port.flags |= ASYNC_CLOSING;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700919
920/*
921 * May want to wait for any data to drain before closing. The BUSY
922 * flag keeps track of whether we are still sending or not - it is
923 * very accurate for the cd1400, not quite so for the sc26198.
924 * (The sc26198 has no "end-of-data" interrupt only empty FIFO)
925 */
926 tty->closing = 1;
Alan Coxb65b5b52006-06-27 02:54:05 -0700927
928 spin_unlock_irqrestore(&stallion_lock, flags);
929
Linus Torvalds1da177e2005-04-16 15:20:36 -0700930 if (portp->closing_wait != ASYNC_CLOSING_WAIT_NONE)
931 tty_wait_until_sent(tty, portp->closing_wait);
932 stl_waituntilsent(tty, (HZ / 2));
933
Alan Coxb65b5b52006-06-27 02:54:05 -0700934
935 spin_lock_irqsave(&stallion_lock, flags);
Alan Coxf8ae4762008-07-16 21:56:37 +0100936 portp->port.flags &= ~ASYNC_INITIALIZED;
Alan Coxb65b5b52006-06-27 02:54:05 -0700937 spin_unlock_irqrestore(&stallion_lock, flags);
938
Linus Torvalds1da177e2005-04-16 15:20:36 -0700939 stl_disableintrs(portp);
940 if (tty->termios->c_cflag & HUPCL)
941 stl_setsignals(portp, 0, 0);
942 stl_enablerxtx(portp, 0, 0);
943 stl_flushbuffer(tty);
944 portp->istate = 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800945 if (portp->tx.buf != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700946 kfree(portp->tx.buf);
Jiri Slaby615e4a72006-12-08 02:38:38 -0800947 portp->tx.buf = NULL;
948 portp->tx.head = NULL;
949 portp->tx.tail = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700950 }
951 set_bit(TTY_IO_ERROR, &tty->flags);
952 tty_ldisc_flush(tty);
953
954 tty->closing = 0;
Alan Coxd18a7502008-10-13 10:40:07 +0100955 tty_port_tty_set(&portp->port, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700956
957 if (portp->openwaitcnt) {
958 if (portp->close_delay)
959 msleep_interruptible(jiffies_to_msecs(portp->close_delay));
Alan Coxf8ae4762008-07-16 21:56:37 +0100960 wake_up_interruptible(&portp->port.open_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700961 }
962
Alan Coxf8ae4762008-07-16 21:56:37 +0100963 portp->port.flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
964 wake_up_interruptible(&portp->port.close_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700965}
966
967/*****************************************************************************/
968
969/*
970 * Write routine. Take data and stuff it in to the TX ring queue.
971 * If transmit interrupts are not running then start them.
972 */
973
974static int stl_write(struct tty_struct *tty, const unsigned char *buf, int count)
975{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800976 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700977 unsigned int len, stlen;
978 unsigned char *chbuf;
979 char *head, *tail;
980
Jiri Slabya0564e12006-12-08 02:38:37 -0800981 pr_debug("stl_write(tty=%p,buf=%p,count=%d)\n", tty, buf, count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700982
Linus Torvalds1da177e2005-04-16 15:20:36 -0700983 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800984 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +0100985 return 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800986 if (portp->tx.buf == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +0100987 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700988
989/*
990 * If copying direct from user space we must cater for page faults,
991 * causing us to "sleep" here for a while. To handle this copy in all
992 * the data we need now, into a local buffer. Then when we got it all
993 * copy it into the TX buffer.
994 */
995 chbuf = (unsigned char *) buf;
996
997 head = portp->tx.head;
998 tail = portp->tx.tail;
999 if (head >= tail) {
1000 len = STL_TXBUFSIZE - (head - tail) - 1;
1001 stlen = STL_TXBUFSIZE - (head - portp->tx.buf);
1002 } else {
1003 len = tail - head - 1;
1004 stlen = len;
1005 }
1006
Jiri Slaby843b5682006-12-08 02:39:12 -08001007 len = min(len, (unsigned int)count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001008 count = 0;
1009 while (len > 0) {
Jiri Slaby843b5682006-12-08 02:39:12 -08001010 stlen = min(len, stlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001011 memcpy(head, chbuf, stlen);
1012 len -= stlen;
1013 chbuf += stlen;
1014 count += stlen;
1015 head += stlen;
1016 if (head >= (portp->tx.buf + STL_TXBUFSIZE)) {
1017 head = portp->tx.buf;
1018 stlen = tail - head;
1019 }
1020 }
1021 portp->tx.head = head;
1022
1023 clear_bit(ASYI_TXLOW, &portp->istate);
1024 stl_startrxtx(portp, -1, 1);
1025
Jesper Juhl014c2542006-01-15 02:37:08 +01001026 return count;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001027}
1028
1029/*****************************************************************************/
1030
David Howells4a561222008-07-22 11:18:43 +01001031static int stl_putchar(struct tty_struct *tty, unsigned char ch)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001032{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001033 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001034 unsigned int len;
1035 char *head, *tail;
1036
Jiri Slabya0564e12006-12-08 02:38:37 -08001037 pr_debug("stl_putchar(tty=%p,ch=%x)\n", tty, ch);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001038
Jiri Slaby615e4a72006-12-08 02:38:38 -08001039 if (tty == NULL)
David Howells4a561222008-07-22 11:18:43 +01001040 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001041 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001042 if (portp == NULL)
David Howells4a561222008-07-22 11:18:43 +01001043 return -EINVAL;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001044 if (portp->tx.buf == NULL)
David Howells4a561222008-07-22 11:18:43 +01001045 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001046
1047 head = portp->tx.head;
1048 tail = portp->tx.tail;
1049
1050 len = (head >= tail) ? (STL_TXBUFSIZE - (head - tail)) : (tail - head);
1051 len--;
1052
1053 if (len > 0) {
1054 *head++ = ch;
1055 if (head >= (portp->tx.buf + STL_TXBUFSIZE))
1056 head = portp->tx.buf;
1057 }
1058 portp->tx.head = head;
David Howells4a561222008-07-22 11:18:43 +01001059 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001060}
1061
1062/*****************************************************************************/
1063
1064/*
1065 * If there are any characters in the buffer then make sure that TX
1066 * interrupts are on and get'em out. Normally used after the putchar
1067 * routine has been called.
1068 */
1069
1070static void stl_flushchars(struct tty_struct *tty)
1071{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001072 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001073
Jiri Slabya0564e12006-12-08 02:38:37 -08001074 pr_debug("stl_flushchars(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001075
Jiri Slaby615e4a72006-12-08 02:38:38 -08001076 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001077 return;
1078 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001079 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001080 return;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001081 if (portp->tx.buf == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001082 return;
1083
Linus Torvalds1da177e2005-04-16 15:20:36 -07001084 stl_startrxtx(portp, -1, 1);
1085}
1086
1087/*****************************************************************************/
1088
1089static int stl_writeroom(struct tty_struct *tty)
1090{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001091 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001092 char *head, *tail;
1093
Jiri Slabya0564e12006-12-08 02:38:37 -08001094 pr_debug("stl_writeroom(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001095
Jiri Slaby615e4a72006-12-08 02:38:38 -08001096 if (tty == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001097 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001098 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001099 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001100 return 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001101 if (portp->tx.buf == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001102 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001103
1104 head = portp->tx.head;
1105 tail = portp->tx.tail;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001106 return (head >= tail) ? (STL_TXBUFSIZE - (head - tail) - 1) : (tail - head - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001107}
1108
1109/*****************************************************************************/
1110
1111/*
1112 * Return number of chars in the TX buffer. Normally we would just
1113 * calculate the number of chars in the buffer and return that, but if
1114 * the buffer is empty and TX interrupts are still on then we return
1115 * that the buffer still has 1 char in it. This way whoever called us
1116 * will not think that ALL chars have drained - since the UART still
1117 * must have some chars in it (we are busy after all).
1118 */
1119
1120static int stl_charsinbuffer(struct tty_struct *tty)
1121{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001122 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001123 unsigned int size;
1124 char *head, *tail;
1125
Jiri Slabya0564e12006-12-08 02:38:37 -08001126 pr_debug("stl_charsinbuffer(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001127
Jiri Slaby615e4a72006-12-08 02:38:38 -08001128 if (tty == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001129 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001130 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001131 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001132 return 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001133 if (portp->tx.buf == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001134 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001135
1136 head = portp->tx.head;
1137 tail = portp->tx.tail;
1138 size = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
1139 if ((size == 0) && test_bit(ASYI_TXBUSY, &portp->istate))
1140 size = 1;
Jesper Juhl014c2542006-01-15 02:37:08 +01001141 return size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001142}
1143
1144/*****************************************************************************/
1145
1146/*
1147 * Generate the serial struct info.
1148 */
1149
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001150static int stl_getserial(struct stlport *portp, struct serial_struct __user *sp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001151{
1152 struct serial_struct sio;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001153 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001154
Jiri Slabya0564e12006-12-08 02:38:37 -08001155 pr_debug("stl_getserial(portp=%p,sp=%p)\n", portp, sp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001156
1157 memset(&sio, 0, sizeof(struct serial_struct));
1158 sio.line = portp->portnr;
1159 sio.port = portp->ioaddr;
Alan Coxf8ae4762008-07-16 21:56:37 +01001160 sio.flags = portp->port.flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001161 sio.baud_base = portp->baud_base;
1162 sio.close_delay = portp->close_delay;
1163 sio.closing_wait = portp->closing_wait;
1164 sio.custom_divisor = portp->custom_divisor;
1165 sio.hub6 = 0;
1166 if (portp->uartp == &stl_cd1400uart) {
1167 sio.type = PORT_CIRRUS;
1168 sio.xmit_fifo_size = CD1400_TXFIFOSIZE;
1169 } else {
1170 sio.type = PORT_UNKNOWN;
1171 sio.xmit_fifo_size = SC26198_TXFIFOSIZE;
1172 }
1173
1174 brdp = stl_brds[portp->brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001175 if (brdp != NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001176 sio.irq = brdp->irq;
1177
1178 return copy_to_user(sp, &sio, sizeof(struct serial_struct)) ? -EFAULT : 0;
1179}
1180
1181/*****************************************************************************/
1182
1183/*
1184 * Set port according to the serial struct info.
1185 * At this point we do not do any auto-configure stuff, so we will
1186 * just quietly ignore any requests to change irq, etc.
1187 */
1188
Alan Coxd18a7502008-10-13 10:40:07 +01001189static int stl_setserial(struct tty_struct *tty, struct serial_struct __user *sp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001190{
Alan Coxd18a7502008-10-13 10:40:07 +01001191 struct stlport * portp = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001192 struct serial_struct sio;
1193
Jiri Slabya0564e12006-12-08 02:38:37 -08001194 pr_debug("stl_setserial(portp=%p,sp=%p)\n", portp, sp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001195
1196 if (copy_from_user(&sio, sp, sizeof(struct serial_struct)))
1197 return -EFAULT;
1198 if (!capable(CAP_SYS_ADMIN)) {
1199 if ((sio.baud_base != portp->baud_base) ||
1200 (sio.close_delay != portp->close_delay) ||
1201 ((sio.flags & ~ASYNC_USR_MASK) !=
Alan Coxf8ae4762008-07-16 21:56:37 +01001202 (portp->port.flags & ~ASYNC_USR_MASK)))
Jesper Juhl014c2542006-01-15 02:37:08 +01001203 return -EPERM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001204 }
1205
Alan Coxf8ae4762008-07-16 21:56:37 +01001206 portp->port.flags = (portp->port.flags & ~ASYNC_USR_MASK) |
Linus Torvalds1da177e2005-04-16 15:20:36 -07001207 (sio.flags & ASYNC_USR_MASK);
1208 portp->baud_base = sio.baud_base;
1209 portp->close_delay = sio.close_delay;
1210 portp->closing_wait = sio.closing_wait;
1211 portp->custom_divisor = sio.custom_divisor;
Alan Coxd18a7502008-10-13 10:40:07 +01001212 stl_setport(portp, tty->termios);
Jesper Juhl014c2542006-01-15 02:37:08 +01001213 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001214}
1215
1216/*****************************************************************************/
1217
1218static int stl_tiocmget(struct tty_struct *tty, struct file *file)
1219{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001220 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001221
Jiri Slaby615e4a72006-12-08 02:38:38 -08001222 if (tty == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001223 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001224 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001225 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001226 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001227 if (tty->flags & (1 << TTY_IO_ERROR))
Jesper Juhl014c2542006-01-15 02:37:08 +01001228 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001229
1230 return stl_getsignals(portp);
1231}
1232
1233static int stl_tiocmset(struct tty_struct *tty, struct file *file,
1234 unsigned int set, unsigned int clear)
1235{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001236 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001237 int rts = -1, dtr = -1;
1238
Jiri Slaby615e4a72006-12-08 02:38:38 -08001239 if (tty == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001240 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001241 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001242 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001243 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001244 if (tty->flags & (1 << TTY_IO_ERROR))
Jesper Juhl014c2542006-01-15 02:37:08 +01001245 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001246
1247 if (set & TIOCM_RTS)
1248 rts = 1;
1249 if (set & TIOCM_DTR)
1250 dtr = 1;
1251 if (clear & TIOCM_RTS)
1252 rts = 0;
1253 if (clear & TIOCM_DTR)
1254 dtr = 0;
1255
1256 stl_setsignals(portp, dtr, rts);
1257 return 0;
1258}
1259
1260static int stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg)
1261{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001262 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001263 int rc;
1264 void __user *argp = (void __user *)arg;
1265
Jiri Slabya0564e12006-12-08 02:38:37 -08001266 pr_debug("stl_ioctl(tty=%p,file=%p,cmd=%x,arg=%lx)\n", tty, file, cmd,
1267 arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001268
Jiri Slaby615e4a72006-12-08 02:38:38 -08001269 if (tty == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001270 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001271 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001272 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001273 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001274
1275 if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
Jiri Slabyc62429d2006-12-08 02:39:14 -08001276 (cmd != COM_GETPORTSTATS) && (cmd != COM_CLRPORTSTATS))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001277 if (tty->flags & (1 << TTY_IO_ERROR))
Jesper Juhl014c2542006-01-15 02:37:08 +01001278 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001279
1280 rc = 0;
1281
Alan Coxf433c652008-04-30 00:53:23 -07001282 lock_kernel();
1283
Linus Torvalds1da177e2005-04-16 15:20:36 -07001284 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001285 case TIOCGSERIAL:
1286 rc = stl_getserial(portp, argp);
1287 break;
1288 case TIOCSSERIAL:
Alan Coxd18a7502008-10-13 10:40:07 +01001289 rc = stl_setserial(tty, argp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001290 break;
1291 case COM_GETPORTSTATS:
Alan Coxd18a7502008-10-13 10:40:07 +01001292 rc = stl_getportstats(tty, portp, argp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001293 break;
1294 case COM_CLRPORTSTATS:
1295 rc = stl_clrportstats(portp, argp);
1296 break;
1297 case TIOCSERCONFIG:
1298 case TIOCSERGWILD:
1299 case TIOCSERSWILD:
1300 case TIOCSERGETLSR:
1301 case TIOCSERGSTRUCT:
1302 case TIOCSERGETMULTI:
1303 case TIOCSERSETMULTI:
1304 default:
1305 rc = -ENOIOCTLCMD;
1306 break;
1307 }
Alan Coxf433c652008-04-30 00:53:23 -07001308 unlock_kernel();
Jesper Juhl014c2542006-01-15 02:37:08 +01001309 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001310}
1311
1312/*****************************************************************************/
1313
Jiri Slaby96b066b2006-12-08 02:38:42 -08001314/*
1315 * Start the transmitter again. Just turn TX interrupts back on.
1316 */
1317
1318static void stl_start(struct tty_struct *tty)
1319{
1320 struct stlport *portp;
1321
1322 pr_debug("stl_start(tty=%p)\n", tty);
1323
1324 if (tty == NULL)
1325 return;
1326 portp = tty->driver_data;
1327 if (portp == NULL)
1328 return;
1329 stl_startrxtx(portp, -1, 1);
1330}
1331
1332/*****************************************************************************/
1333
Alan Cox606d0992006-12-08 02:38:45 -08001334static void stl_settermios(struct tty_struct *tty, struct ktermios *old)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001335{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001336 struct stlport *portp;
Alan Cox606d0992006-12-08 02:38:45 -08001337 struct ktermios *tiosp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001338
Jiri Slabya0564e12006-12-08 02:38:37 -08001339 pr_debug("stl_settermios(tty=%p,old=%p)\n", tty, old);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001340
Jiri Slaby615e4a72006-12-08 02:38:38 -08001341 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001342 return;
1343 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001344 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001345 return;
1346
1347 tiosp = tty->termios;
1348 if ((tiosp->c_cflag == old->c_cflag) &&
1349 (tiosp->c_iflag == old->c_iflag))
1350 return;
1351
1352 stl_setport(portp, tiosp);
1353 stl_setsignals(portp, ((tiosp->c_cflag & (CBAUD & ~CBAUDEX)) ? 1 : 0),
1354 -1);
1355 if ((old->c_cflag & CRTSCTS) && ((tiosp->c_cflag & CRTSCTS) == 0)) {
1356 tty->hw_stopped = 0;
1357 stl_start(tty);
1358 }
1359 if (((old->c_cflag & CLOCAL) == 0) && (tiosp->c_cflag & CLOCAL))
Alan Coxf8ae4762008-07-16 21:56:37 +01001360 wake_up_interruptible(&portp->port.open_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001361}
1362
1363/*****************************************************************************/
1364
1365/*
1366 * Attempt to flow control who ever is sending us data. Based on termios
1367 * settings use software or/and hardware flow control.
1368 */
1369
1370static void stl_throttle(struct tty_struct *tty)
1371{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001372 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001373
Jiri Slabya0564e12006-12-08 02:38:37 -08001374 pr_debug("stl_throttle(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001375
Jiri Slaby615e4a72006-12-08 02:38:38 -08001376 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001377 return;
1378 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001379 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001380 return;
1381 stl_flowctrl(portp, 0);
1382}
1383
1384/*****************************************************************************/
1385
1386/*
1387 * Unflow control the device sending us data...
1388 */
1389
1390static void stl_unthrottle(struct tty_struct *tty)
1391{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001392 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001393
Jiri Slabya0564e12006-12-08 02:38:37 -08001394 pr_debug("stl_unthrottle(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001395
Jiri Slaby615e4a72006-12-08 02:38:38 -08001396 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001397 return;
1398 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001399 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001400 return;
1401 stl_flowctrl(portp, 1);
1402}
1403
1404/*****************************************************************************/
1405
1406/*
1407 * Stop the transmitter. Basically to do this we will just turn TX
1408 * interrupts off.
1409 */
1410
1411static void stl_stop(struct tty_struct *tty)
1412{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001413 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001414
Jiri Slabya0564e12006-12-08 02:38:37 -08001415 pr_debug("stl_stop(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001416
Jiri Slaby615e4a72006-12-08 02:38:38 -08001417 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001418 return;
1419 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001420 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001421 return;
1422 stl_startrxtx(portp, -1, 0);
1423}
1424
1425/*****************************************************************************/
1426
1427/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001428 * Hangup this port. This is pretty much like closing the port, only
1429 * a little more brutal. No waiting for data to drain. Shutdown the
1430 * port and maybe drop signals.
1431 */
1432
1433static void stl_hangup(struct tty_struct *tty)
1434{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001435 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001436
Jiri Slabya0564e12006-12-08 02:38:37 -08001437 pr_debug("stl_hangup(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001438
Jiri Slaby615e4a72006-12-08 02:38:38 -08001439 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001440 return;
1441 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001442 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001443 return;
1444
Alan Coxf8ae4762008-07-16 21:56:37 +01001445 portp->port.flags &= ~ASYNC_INITIALIZED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001446 stl_disableintrs(portp);
1447 if (tty->termios->c_cflag & HUPCL)
1448 stl_setsignals(portp, 0, 0);
1449 stl_enablerxtx(portp, 0, 0);
1450 stl_flushbuffer(tty);
1451 portp->istate = 0;
1452 set_bit(TTY_IO_ERROR, &tty->flags);
Jiri Slaby615e4a72006-12-08 02:38:38 -08001453 if (portp->tx.buf != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001454 kfree(portp->tx.buf);
Jiri Slaby615e4a72006-12-08 02:38:38 -08001455 portp->tx.buf = NULL;
1456 portp->tx.head = NULL;
1457 portp->tx.tail = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001458 }
Alan Coxd18a7502008-10-13 10:40:07 +01001459 tty_port_tty_set(&portp->port, NULL);
Alan Coxf8ae4762008-07-16 21:56:37 +01001460 portp->port.flags &= ~ASYNC_NORMAL_ACTIVE;
1461 portp->port.count = 0;
1462 wake_up_interruptible(&portp->port.open_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001463}
1464
1465/*****************************************************************************/
1466
David Howells4a561222008-07-22 11:18:43 +01001467static int stl_breakctl(struct tty_struct *tty, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001468{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001469 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001470
Jiri Slabya0564e12006-12-08 02:38:37 -08001471 pr_debug("stl_breakctl(tty=%p,state=%d)\n", tty, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001472
Jiri Slaby615e4a72006-12-08 02:38:38 -08001473 if (tty == NULL)
David Howells4a561222008-07-22 11:18:43 +01001474 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001475 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001476 if (portp == NULL)
David Howells4a561222008-07-22 11:18:43 +01001477 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001478
1479 stl_sendbreak(portp, ((state == -1) ? 1 : 2));
David Howells4a561222008-07-22 11:18:43 +01001480 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001481}
1482
1483/*****************************************************************************/
1484
Linus Torvalds1da177e2005-04-16 15:20:36 -07001485static void stl_sendxchar(struct tty_struct *tty, char ch)
1486{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001487 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001488
Jiri Slabya0564e12006-12-08 02:38:37 -08001489 pr_debug("stl_sendxchar(tty=%p,ch=%x)\n", tty, ch);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001490
Jiri Slaby615e4a72006-12-08 02:38:38 -08001491 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001492 return;
1493 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001494 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001495 return;
1496
1497 if (ch == STOP_CHAR(tty))
1498 stl_sendflow(portp, 0);
1499 else if (ch == START_CHAR(tty))
1500 stl_sendflow(portp, 1);
1501 else
1502 stl_putchar(tty, ch);
1503}
1504
1505/*****************************************************************************/
1506
1507#define MAXLINE 80
1508
1509/*
1510 * Format info for a specified port. The line is deliberately limited
1511 * to 80 characters. (If it is too long it will be truncated, if too
1512 * short then padded with spaces).
1513 */
1514
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001515static int stl_portinfo(struct stlport *portp, int portnr, char *pos)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001516{
1517 char *sp;
1518 int sigs, cnt;
1519
1520 sp = pos;
1521 sp += sprintf(sp, "%d: uart:%s tx:%d rx:%d",
1522 portnr, (portp->hwid == 1) ? "SC26198" : "CD1400",
1523 (int) portp->stats.txtotal, (int) portp->stats.rxtotal);
1524
1525 if (portp->stats.rxframing)
1526 sp += sprintf(sp, " fe:%d", (int) portp->stats.rxframing);
1527 if (portp->stats.rxparity)
1528 sp += sprintf(sp, " pe:%d", (int) portp->stats.rxparity);
1529 if (portp->stats.rxbreaks)
1530 sp += sprintf(sp, " brk:%d", (int) portp->stats.rxbreaks);
1531 if (portp->stats.rxoverrun)
1532 sp += sprintf(sp, " oe:%d", (int) portp->stats.rxoverrun);
1533
1534 sigs = stl_getsignals(portp);
1535 cnt = sprintf(sp, "%s%s%s%s%s ",
1536 (sigs & TIOCM_RTS) ? "|RTS" : "",
1537 (sigs & TIOCM_CTS) ? "|CTS" : "",
1538 (sigs & TIOCM_DTR) ? "|DTR" : "",
1539 (sigs & TIOCM_CD) ? "|DCD" : "",
1540 (sigs & TIOCM_DSR) ? "|DSR" : "");
1541 *sp = ' ';
1542 sp += cnt;
1543
Jiri Slabyc62429d2006-12-08 02:39:14 -08001544 for (cnt = sp - pos; cnt < (MAXLINE - 1); cnt++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001545 *sp++ = ' ';
1546 if (cnt >= MAXLINE)
1547 pos[(MAXLINE - 2)] = '+';
1548 pos[(MAXLINE - 1)] = '\n';
1549
Jesper Juhl014c2542006-01-15 02:37:08 +01001550 return MAXLINE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001551}
1552
1553/*****************************************************************************/
1554
1555/*
1556 * Port info, read from the /proc file system.
1557 */
1558
1559static int stl_readproc(char *page, char **start, off_t off, int count, int *eof, void *data)
1560{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001561 struct stlbrd *brdp;
1562 struct stlpanel *panelp;
1563 struct stlport *portp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001564 unsigned int brdnr, panelnr, portnr;
1565 int totalport, curoff, maxoff;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001566 char *pos;
1567
Jiri Slabya0564e12006-12-08 02:38:37 -08001568 pr_debug("stl_readproc(page=%p,start=%p,off=%lx,count=%d,eof=%p,"
1569 "data=%p\n", page, start, off, count, eof, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001570
1571 pos = page;
1572 totalport = 0;
1573 curoff = 0;
1574
1575 if (off == 0) {
1576 pos += sprintf(pos, "%s: version %s", stl_drvtitle,
1577 stl_drvversion);
1578 while (pos < (page + MAXLINE - 1))
1579 *pos++ = ' ';
1580 *pos++ = '\n';
1581 }
1582 curoff = MAXLINE;
1583
1584/*
1585 * We scan through for each board, panel and port. The offset is
1586 * calculated on the fly, and irrelevant ports are skipped.
1587 */
Jiri Slabyc62429d2006-12-08 02:39:14 -08001588 for (brdnr = 0; brdnr < stl_nrbrds; brdnr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001589 brdp = stl_brds[brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001590 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001591 continue;
1592 if (brdp->state == 0)
1593 continue;
1594
1595 maxoff = curoff + (brdp->nrports * MAXLINE);
1596 if (off >= maxoff) {
1597 curoff = maxoff;
1598 continue;
1599 }
1600
1601 totalport = brdnr * STL_MAXPORTS;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001602 for (panelnr = 0; panelnr < brdp->nrpanels; panelnr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001603 panelp = brdp->panels[panelnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001604 if (panelp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001605 continue;
1606
1607 maxoff = curoff + (panelp->nrports * MAXLINE);
1608 if (off >= maxoff) {
1609 curoff = maxoff;
1610 totalport += panelp->nrports;
1611 continue;
1612 }
1613
Jiri Slabyc62429d2006-12-08 02:39:14 -08001614 for (portnr = 0; portnr < panelp->nrports; portnr++,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001615 totalport++) {
1616 portp = panelp->ports[portnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001617 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001618 continue;
1619 if (off >= (curoff += MAXLINE))
1620 continue;
1621 if ((pos - page + MAXLINE) > count)
1622 goto stl_readdone;
1623 pos += stl_portinfo(portp, totalport, pos);
1624 }
1625 }
1626 }
1627
1628 *eof = 1;
1629
1630stl_readdone:
1631 *start = page;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001632 return pos - page;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001633}
1634
1635/*****************************************************************************/
1636
1637/*
1638 * All board interrupts are vectored through here first. This code then
1639 * calls off to the approrpriate board interrupt handlers.
1640 */
1641
David Howells7d12e782006-10-05 14:55:46 +01001642static irqreturn_t stl_intr(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001643{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001644 struct stlbrd *brdp = dev_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001645
Jeff Garzika6f97b22007-10-31 05:20:49 -04001646 pr_debug("stl_intr(brdp=%p,irq=%d)\n", brdp, brdp->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001647
1648 return IRQ_RETVAL((* brdp->isr)(brdp));
1649}
1650
1651/*****************************************************************************/
1652
1653/*
1654 * Interrupt service routine for EasyIO board types.
1655 */
1656
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001657static int stl_eiointr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001658{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001659 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001660 unsigned int iobase;
1661 int handled = 0;
1662
Alan Coxb65b5b52006-06-27 02:54:05 -07001663 spin_lock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001664 panelp = brdp->panels[0];
1665 iobase = panelp->iobase;
1666 while (inb(brdp->iostatus) & EIO_INTRPEND) {
1667 handled = 1;
1668 (* panelp->isr)(panelp, iobase);
1669 }
Alan Coxb65b5b52006-06-27 02:54:05 -07001670 spin_unlock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001671 return handled;
1672}
1673
1674/*****************************************************************************/
1675
1676/*
1677 * Interrupt service routine for ECH-AT board types.
1678 */
1679
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001680static int stl_echatintr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001681{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001682 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001683 unsigned int ioaddr, bnknr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001684 int handled = 0;
1685
1686 outb((brdp->ioctrlval | ECH_BRDENABLE), brdp->ioctrl);
1687
1688 while (inb(brdp->iostatus) & ECH_INTRPEND) {
1689 handled = 1;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001690 for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001691 ioaddr = brdp->bnkstataddr[bnknr];
1692 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1693 panelp = brdp->bnk2panel[bnknr];
1694 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1695 }
1696 }
1697 }
1698
1699 outb((brdp->ioctrlval | ECH_BRDDISABLE), brdp->ioctrl);
1700
1701 return handled;
1702}
1703
1704/*****************************************************************************/
1705
1706/*
1707 * Interrupt service routine for ECH-MCA board types.
1708 */
1709
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001710static int stl_echmcaintr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001711{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001712 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001713 unsigned int ioaddr, bnknr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001714 int handled = 0;
1715
1716 while (inb(brdp->iostatus) & ECH_INTRPEND) {
1717 handled = 1;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001718 for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001719 ioaddr = brdp->bnkstataddr[bnknr];
1720 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1721 panelp = brdp->bnk2panel[bnknr];
1722 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1723 }
1724 }
1725 }
1726 return handled;
1727}
1728
1729/*****************************************************************************/
1730
1731/*
1732 * Interrupt service routine for ECH-PCI board types.
1733 */
1734
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001735static int stl_echpciintr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001736{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001737 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001738 unsigned int ioaddr, bnknr, recheck;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001739 int handled = 0;
1740
1741 while (1) {
1742 recheck = 0;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001743 for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001744 outb(brdp->bnkpageaddr[bnknr], brdp->ioctrl);
1745 ioaddr = brdp->bnkstataddr[bnknr];
1746 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1747 panelp = brdp->bnk2panel[bnknr];
1748 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1749 recheck++;
1750 handled = 1;
1751 }
1752 }
1753 if (! recheck)
1754 break;
1755 }
1756 return handled;
1757}
1758
1759/*****************************************************************************/
1760
1761/*
1762 * Interrupt service routine for ECH-8/64-PCI board types.
1763 */
1764
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001765static int stl_echpci64intr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001766{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001767 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001768 unsigned int ioaddr, bnknr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001769 int handled = 0;
1770
1771 while (inb(brdp->ioctrl) & 0x1) {
1772 handled = 1;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001773 for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001774 ioaddr = brdp->bnkstataddr[bnknr];
1775 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1776 panelp = brdp->bnk2panel[bnknr];
1777 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1778 }
1779 }
1780 }
1781
1782 return handled;
1783}
1784
1785/*****************************************************************************/
1786
1787/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001788 * Initialize all the ports on a panel.
1789 */
1790
Jiri Slaby705c1862006-12-08 02:39:11 -08001791static int __devinit stl_initports(struct stlbrd *brdp, struct stlpanel *panelp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001792{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001793 struct stlport *portp;
1794 unsigned int i;
1795 int chipmask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001796
Jiri Slabya0564e12006-12-08 02:38:37 -08001797 pr_debug("stl_initports(brdp=%p,panelp=%p)\n", brdp, panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001798
1799 chipmask = stl_panelinit(brdp, panelp);
1800
1801/*
1802 * All UART's are initialized (if found!). Now go through and setup
1803 * each ports data structures.
1804 */
Jiri Slabyc62429d2006-12-08 02:39:14 -08001805 for (i = 0; i < panelp->nrports; i++) {
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001806 portp = kzalloc(sizeof(struct stlport), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08001807 if (!portp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001808 printk("STALLION: failed to allocate memory "
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001809 "(size=%Zd)\n", sizeof(struct stlport));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001810 break;
1811 }
Alan Coxd18a7502008-10-13 10:40:07 +01001812 tty_port_init(&portp->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001813 portp->magic = STL_PORTMAGIC;
1814 portp->portnr = i;
1815 portp->brdnr = panelp->brdnr;
1816 portp->panelnr = panelp->panelnr;
1817 portp->uartp = panelp->uartp;
1818 portp->clk = brdp->clk;
1819 portp->baud_base = STL_BAUDBASE;
1820 portp->close_delay = STL_CLOSEDELAY;
1821 portp->closing_wait = 30 * HZ;
Alan Coxf8ae4762008-07-16 21:56:37 +01001822 init_waitqueue_head(&portp->port.open_wait);
1823 init_waitqueue_head(&portp->port.close_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001824 portp->stats.brd = portp->brdnr;
1825 portp->stats.panel = portp->panelnr;
1826 portp->stats.port = portp->portnr;
1827 panelp->ports[i] = portp;
1828 stl_portinit(brdp, panelp, portp);
1829 }
1830
Jiri Slabyc62429d2006-12-08 02:39:14 -08001831 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001832}
1833
Jiri Slaby3b85b342006-12-08 02:39:10 -08001834static void stl_cleanup_panels(struct stlbrd *brdp)
1835{
1836 struct stlpanel *panelp;
1837 struct stlport *portp;
1838 unsigned int j, k;
Alan Coxd18a7502008-10-13 10:40:07 +01001839 struct tty_struct *tty;
Jiri Slaby3b85b342006-12-08 02:39:10 -08001840
1841 for (j = 0; j < STL_MAXPANELS; j++) {
1842 panelp = brdp->panels[j];
1843 if (panelp == NULL)
1844 continue;
1845 for (k = 0; k < STL_PORTSPERPANEL; k++) {
1846 portp = panelp->ports[k];
1847 if (portp == NULL)
1848 continue;
Alan Coxd18a7502008-10-13 10:40:07 +01001849 tty = tty_port_tty_get(&portp->port);
1850 if (tty != NULL) {
1851 stl_hangup(tty);
1852 tty_kref_put(tty);
1853 }
Jiri Slaby3b85b342006-12-08 02:39:10 -08001854 kfree(portp->tx.buf);
1855 kfree(portp);
1856 }
1857 kfree(panelp);
1858 }
1859}
1860
Linus Torvalds1da177e2005-04-16 15:20:36 -07001861/*****************************************************************************/
1862
1863/*
1864 * Try to find and initialize an EasyIO board.
1865 */
1866
Jiri Slaby705c1862006-12-08 02:39:11 -08001867static int __devinit stl_initeio(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001868{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001869 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001870 unsigned int status;
1871 char *name;
Jiri Slaby3b85b342006-12-08 02:39:10 -08001872 int retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001873
Jiri Slabya0564e12006-12-08 02:38:37 -08001874 pr_debug("stl_initeio(brdp=%p)\n", brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001875
1876 brdp->ioctrl = brdp->ioaddr1 + 1;
1877 brdp->iostatus = brdp->ioaddr1 + 2;
1878
1879 status = inb(brdp->iostatus);
1880 if ((status & EIO_IDBITMASK) == EIO_MK3)
1881 brdp->ioctrl++;
1882
1883/*
1884 * Handle board specific stuff now. The real difference is PCI
1885 * or not PCI.
1886 */
1887 if (brdp->brdtype == BRD_EASYIOPCI) {
1888 brdp->iosize1 = 0x80;
1889 brdp->iosize2 = 0x80;
1890 name = "serial(EIO-PCI)";
1891 outb(0x41, (brdp->ioaddr2 + 0x4c));
1892 } else {
1893 brdp->iosize1 = 8;
1894 name = "serial(EIO)";
1895 if ((brdp->irq < 0) || (brdp->irq > 15) ||
1896 (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
1897 printk("STALLION: invalid irq=%d for brd=%d\n",
1898 brdp->irq, brdp->brdnr);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001899 retval = -EINVAL;
1900 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001901 }
1902 outb((stl_vecmap[brdp->irq] | EIO_0WS |
1903 ((brdp->irqtype) ? EIO_INTLEVEL : EIO_INTEDGE)),
1904 brdp->ioctrl);
1905 }
1906
Jiri Slaby3b85b342006-12-08 02:39:10 -08001907 retval = -EBUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001908 if (!request_region(brdp->ioaddr1, brdp->iosize1, name)) {
1909 printk(KERN_WARNING "STALLION: Warning, board %d I/O address "
1910 "%x conflicts with another device\n", brdp->brdnr,
1911 brdp->ioaddr1);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001912 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001913 }
1914
1915 if (brdp->iosize2 > 0)
1916 if (!request_region(brdp->ioaddr2, brdp->iosize2, name)) {
1917 printk(KERN_WARNING "STALLION: Warning, board %d I/O "
1918 "address %x conflicts with another device\n",
1919 brdp->brdnr, brdp->ioaddr2);
1920 printk(KERN_WARNING "STALLION: Warning, also "
1921 "releasing board %d I/O address %x \n",
1922 brdp->brdnr, brdp->ioaddr1);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001923 goto err_rel1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001924 }
1925
1926/*
1927 * Everything looks OK, so let's go ahead and probe for the hardware.
1928 */
1929 brdp->clk = CD1400_CLK;
1930 brdp->isr = stl_eiointr;
1931
Jiri Slaby3b85b342006-12-08 02:39:10 -08001932 retval = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001933 switch (status & EIO_IDBITMASK) {
1934 case EIO_8PORTM:
1935 brdp->clk = CD1400_CLK8M;
1936 /* fall thru */
1937 case EIO_8PORTRS:
1938 case EIO_8PORTDI:
1939 brdp->nrports = 8;
1940 break;
1941 case EIO_4PORTRS:
1942 brdp->nrports = 4;
1943 break;
1944 case EIO_MK3:
1945 switch (status & EIO_BRDMASK) {
1946 case ID_BRD4:
1947 brdp->nrports = 4;
1948 break;
1949 case ID_BRD8:
1950 brdp->nrports = 8;
1951 break;
1952 case ID_BRD16:
1953 brdp->nrports = 16;
1954 break;
1955 default:
Jiri Slaby3b85b342006-12-08 02:39:10 -08001956 goto err_rel2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001957 }
1958 break;
1959 default:
Jiri Slaby3b85b342006-12-08 02:39:10 -08001960 goto err_rel2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001961 }
1962
1963/*
1964 * We have verified that the board is actually present, so now we
1965 * can complete the setup.
1966 */
1967
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001968 panelp = kzalloc(sizeof(struct stlpanel), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08001969 if (!panelp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001970 printk(KERN_WARNING "STALLION: failed to allocate memory "
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001971 "(size=%Zd)\n", sizeof(struct stlpanel));
Jiri Slaby3b85b342006-12-08 02:39:10 -08001972 retval = -ENOMEM;
1973 goto err_rel2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001974 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001975
1976 panelp->magic = STL_PANELMAGIC;
1977 panelp->brdnr = brdp->brdnr;
1978 panelp->panelnr = 0;
1979 panelp->nrports = brdp->nrports;
1980 panelp->iobase = brdp->ioaddr1;
1981 panelp->hwid = status;
1982 if ((status & EIO_IDBITMASK) == EIO_MK3) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08001983 panelp->uartp = &stl_sc26198uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001984 panelp->isr = stl_sc26198intr;
1985 } else {
Jiri Slaby615e4a72006-12-08 02:38:38 -08001986 panelp->uartp = &stl_cd1400uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001987 panelp->isr = stl_cd1400eiointr;
1988 }
1989
1990 brdp->panels[0] = panelp;
1991 brdp->nrpanels = 1;
1992 brdp->state |= BRD_FOUND;
1993 brdp->hwid = status;
Thomas Gleixner0f2ed4c2006-07-01 19:29:33 -07001994 if (request_irq(brdp->irq, stl_intr, IRQF_SHARED, name, brdp) != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001995 printk("STALLION: failed to register interrupt "
1996 "routine for %s irq=%d\n", name, brdp->irq);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001997 retval = -ENODEV;
1998 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001999 }
Jiri Slaby3b85b342006-12-08 02:39:10 -08002000
2001 return 0;
2002err_fr:
2003 stl_cleanup_panels(brdp);
2004err_rel2:
2005 if (brdp->iosize2 > 0)
2006 release_region(brdp->ioaddr2, brdp->iosize2);
2007err_rel1:
2008 release_region(brdp->ioaddr1, brdp->iosize1);
2009err:
2010 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002011}
2012
2013/*****************************************************************************/
2014
2015/*
2016 * Try to find an ECH board and initialize it. This code is capable of
2017 * dealing with all types of ECH board.
2018 */
2019
Jiri Slaby705c1862006-12-08 02:39:11 -08002020static int __devinit stl_initech(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002021{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002022 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002023 unsigned int status, nxtid, ioaddr, conflict, panelnr, banknr, i;
2024 int retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002025 char *name;
2026
Jiri Slabya0564e12006-12-08 02:38:37 -08002027 pr_debug("stl_initech(brdp=%p)\n", brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002028
2029 status = 0;
2030 conflict = 0;
2031
2032/*
2033 * Set up the initial board register contents for boards. This varies a
2034 * bit between the different board types. So we need to handle each
2035 * separately. Also do a check that the supplied IRQ is good.
2036 */
2037 switch (brdp->brdtype) {
2038
2039 case BRD_ECH:
2040 brdp->isr = stl_echatintr;
2041 brdp->ioctrl = brdp->ioaddr1 + 1;
2042 brdp->iostatus = brdp->ioaddr1 + 1;
2043 status = inb(brdp->iostatus);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002044 if ((status & ECH_IDBITMASK) != ECH_ID) {
2045 retval = -ENODEV;
2046 goto err;
2047 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002048 if ((brdp->irq < 0) || (brdp->irq > 15) ||
2049 (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
2050 printk("STALLION: invalid irq=%d for brd=%d\n",
2051 brdp->irq, brdp->brdnr);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002052 retval = -EINVAL;
2053 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002054 }
2055 status = ((brdp->ioaddr2 & ECH_ADDR2MASK) >> 1);
2056 status |= (stl_vecmap[brdp->irq] << 1);
2057 outb((status | ECH_BRDRESET), brdp->ioaddr1);
2058 brdp->ioctrlval = ECH_INTENABLE |
2059 ((brdp->irqtype) ? ECH_INTLEVEL : ECH_INTEDGE);
Jiri Slabyc62429d2006-12-08 02:39:14 -08002060 for (i = 0; i < 10; i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002061 outb((brdp->ioctrlval | ECH_BRDENABLE), brdp->ioctrl);
2062 brdp->iosize1 = 2;
2063 brdp->iosize2 = 32;
2064 name = "serial(EC8/32)";
2065 outb(status, brdp->ioaddr1);
2066 break;
2067
2068 case BRD_ECHMC:
2069 brdp->isr = stl_echmcaintr;
2070 brdp->ioctrl = brdp->ioaddr1 + 0x20;
2071 brdp->iostatus = brdp->ioctrl;
2072 status = inb(brdp->iostatus);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002073 if ((status & ECH_IDBITMASK) != ECH_ID) {
2074 retval = -ENODEV;
2075 goto err;
2076 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002077 if ((brdp->irq < 0) || (brdp->irq > 15) ||
2078 (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
2079 printk("STALLION: invalid irq=%d for brd=%d\n",
2080 brdp->irq, brdp->brdnr);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002081 retval = -EINVAL;
2082 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002083 }
2084 outb(ECHMC_BRDRESET, brdp->ioctrl);
2085 outb(ECHMC_INTENABLE, brdp->ioctrl);
2086 brdp->iosize1 = 64;
2087 name = "serial(EC8/32-MC)";
2088 break;
2089
2090 case BRD_ECHPCI:
2091 brdp->isr = stl_echpciintr;
2092 brdp->ioctrl = brdp->ioaddr1 + 2;
2093 brdp->iosize1 = 4;
2094 brdp->iosize2 = 8;
2095 name = "serial(EC8/32-PCI)";
2096 break;
2097
2098 case BRD_ECH64PCI:
2099 brdp->isr = stl_echpci64intr;
2100 brdp->ioctrl = brdp->ioaddr2 + 0x40;
2101 outb(0x43, (brdp->ioaddr1 + 0x4c));
2102 brdp->iosize1 = 0x80;
2103 brdp->iosize2 = 0x80;
2104 name = "serial(EC8/64-PCI)";
2105 break;
2106
2107 default:
2108 printk("STALLION: unknown board type=%d\n", brdp->brdtype);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002109 retval = -EINVAL;
2110 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002111 }
2112
2113/*
2114 * Check boards for possible IO address conflicts and return fail status
2115 * if an IO conflict found.
2116 */
Jiri Slaby3b85b342006-12-08 02:39:10 -08002117 retval = -EBUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002118 if (!request_region(brdp->ioaddr1, brdp->iosize1, name)) {
2119 printk(KERN_WARNING "STALLION: Warning, board %d I/O address "
2120 "%x conflicts with another device\n", brdp->brdnr,
2121 brdp->ioaddr1);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002122 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002123 }
2124
2125 if (brdp->iosize2 > 0)
2126 if (!request_region(brdp->ioaddr2, brdp->iosize2, name)) {
2127 printk(KERN_WARNING "STALLION: Warning, board %d I/O "
2128 "address %x conflicts with another device\n",
2129 brdp->brdnr, brdp->ioaddr2);
2130 printk(KERN_WARNING "STALLION: Warning, also "
2131 "releasing board %d I/O address %x \n",
2132 brdp->brdnr, brdp->ioaddr1);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002133 goto err_rel1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002134 }
2135
2136/*
2137 * Scan through the secondary io address space looking for panels.
2138 * As we find'em allocate and initialize panel structures for each.
2139 */
2140 brdp->clk = CD1400_CLK;
2141 brdp->hwid = status;
2142
2143 ioaddr = brdp->ioaddr2;
2144 banknr = 0;
2145 panelnr = 0;
2146 nxtid = 0;
2147
Jiri Slabyc62429d2006-12-08 02:39:14 -08002148 for (i = 0; i < STL_MAXPANELS; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002149 if (brdp->brdtype == BRD_ECHPCI) {
2150 outb(nxtid, brdp->ioctrl);
2151 ioaddr = brdp->ioaddr2;
2152 }
2153 status = inb(ioaddr + ECH_PNLSTATUS);
2154 if ((status & ECH_PNLIDMASK) != nxtid)
Jiri Slaby64834b22007-06-08 13:46:52 -07002155 break;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002156 panelp = kzalloc(sizeof(struct stlpanel), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08002157 if (!panelp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002158 printk("STALLION: failed to allocate memory "
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002159 "(size=%Zd)\n", sizeof(struct stlpanel));
Jiri Slaby49277b12007-06-08 13:46:53 -07002160 retval = -ENOMEM;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002161 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002162 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002163 panelp->magic = STL_PANELMAGIC;
2164 panelp->brdnr = brdp->brdnr;
2165 panelp->panelnr = panelnr;
2166 panelp->iobase = ioaddr;
2167 panelp->pagenr = nxtid;
2168 panelp->hwid = status;
2169 brdp->bnk2panel[banknr] = panelp;
2170 brdp->bnkpageaddr[banknr] = nxtid;
2171 brdp->bnkstataddr[banknr++] = ioaddr + ECH_PNLSTATUS;
2172
2173 if (status & ECH_PNLXPID) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08002174 panelp->uartp = &stl_sc26198uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002175 panelp->isr = stl_sc26198intr;
2176 if (status & ECH_PNL16PORT) {
2177 panelp->nrports = 16;
2178 brdp->bnk2panel[banknr] = panelp;
2179 brdp->bnkpageaddr[banknr] = nxtid;
2180 brdp->bnkstataddr[banknr++] = ioaddr + 4 +
2181 ECH_PNLSTATUS;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002182 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002183 panelp->nrports = 8;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002184 } else {
Jiri Slaby615e4a72006-12-08 02:38:38 -08002185 panelp->uartp = &stl_cd1400uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002186 panelp->isr = stl_cd1400echintr;
2187 if (status & ECH_PNL16PORT) {
2188 panelp->nrports = 16;
2189 panelp->ackmask = 0x80;
2190 if (brdp->brdtype != BRD_ECHPCI)
2191 ioaddr += EREG_BANKSIZE;
2192 brdp->bnk2panel[banknr] = panelp;
2193 brdp->bnkpageaddr[banknr] = ++nxtid;
2194 brdp->bnkstataddr[banknr++] = ioaddr +
2195 ECH_PNLSTATUS;
2196 } else {
2197 panelp->nrports = 8;
2198 panelp->ackmask = 0xc0;
2199 }
2200 }
2201
2202 nxtid++;
2203 ioaddr += EREG_BANKSIZE;
2204 brdp->nrports += panelp->nrports;
2205 brdp->panels[panelnr++] = panelp;
2206 if ((brdp->brdtype != BRD_ECHPCI) &&
Jiri Slaby49277b12007-06-08 13:46:53 -07002207 (ioaddr >= (brdp->ioaddr2 + brdp->iosize2))) {
2208 retval = -EINVAL;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002209 goto err_fr;
Jiri Slaby49277b12007-06-08 13:46:53 -07002210 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002211 }
2212
2213 brdp->nrpanels = panelnr;
2214 brdp->nrbnks = banknr;
2215 if (brdp->brdtype == BRD_ECH)
2216 outb((brdp->ioctrlval | ECH_BRDDISABLE), brdp->ioctrl);
2217
2218 brdp->state |= BRD_FOUND;
Thomas Gleixner0f2ed4c2006-07-01 19:29:33 -07002219 if (request_irq(brdp->irq, stl_intr, IRQF_SHARED, name, brdp) != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002220 printk("STALLION: failed to register interrupt "
2221 "routine for %s irq=%d\n", name, brdp->irq);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002222 retval = -ENODEV;
2223 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002224 }
2225
Jiri Slaby3b85b342006-12-08 02:39:10 -08002226 return 0;
2227err_fr:
2228 stl_cleanup_panels(brdp);
2229 if (brdp->iosize2 > 0)
2230 release_region(brdp->ioaddr2, brdp->iosize2);
2231err_rel1:
2232 release_region(brdp->ioaddr1, brdp->iosize1);
2233err:
2234 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002235}
2236
2237/*****************************************************************************/
2238
2239/*
2240 * Initialize and configure the specified board.
2241 * Scan through all the boards in the configuration and see what we
2242 * can find. Handle EIO and the ECH boards a little differently here
2243 * since the initial search and setup is very different.
2244 */
2245
Jiri Slaby705c1862006-12-08 02:39:11 -08002246static int __devinit stl_brdinit(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002247{
Jiri Slaby3b85b342006-12-08 02:39:10 -08002248 int i, retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002249
Jiri Slabya0564e12006-12-08 02:38:37 -08002250 pr_debug("stl_brdinit(brdp=%p)\n", brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002251
2252 switch (brdp->brdtype) {
2253 case BRD_EASYIO:
2254 case BRD_EASYIOPCI:
Jiri Slaby3b85b342006-12-08 02:39:10 -08002255 retval = stl_initeio(brdp);
2256 if (retval)
2257 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002258 break;
2259 case BRD_ECH:
2260 case BRD_ECHMC:
2261 case BRD_ECHPCI:
2262 case BRD_ECH64PCI:
Jiri Slaby3b85b342006-12-08 02:39:10 -08002263 retval = stl_initech(brdp);
2264 if (retval)
2265 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002266 break;
2267 default:
2268 printk("STALLION: board=%d is unknown board type=%d\n",
2269 brdp->brdnr, brdp->brdtype);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002270 retval = -ENODEV;
2271 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002272 }
2273
Linus Torvalds1da177e2005-04-16 15:20:36 -07002274 if ((brdp->state & BRD_FOUND) == 0) {
2275 printk("STALLION: %s board not found, board=%d io=%x irq=%d\n",
2276 stl_brdnames[brdp->brdtype], brdp->brdnr,
2277 brdp->ioaddr1, brdp->irq);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002278 goto err_free;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002279 }
2280
Jiri Slabyc62429d2006-12-08 02:39:14 -08002281 for (i = 0; i < STL_MAXPANELS; i++)
Jiri Slaby615e4a72006-12-08 02:38:38 -08002282 if (brdp->panels[i] != NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002283 stl_initports(brdp, brdp->panels[i]);
2284
2285 printk("STALLION: %s found, board=%d io=%x irq=%d "
2286 "nrpanels=%d nrports=%d\n", stl_brdnames[brdp->brdtype],
2287 brdp->brdnr, brdp->ioaddr1, brdp->irq, brdp->nrpanels,
2288 brdp->nrports);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002289
2290 return 0;
2291err_free:
2292 free_irq(brdp->irq, brdp);
2293
2294 stl_cleanup_panels(brdp);
2295
2296 release_region(brdp->ioaddr1, brdp->iosize1);
2297 if (brdp->iosize2 > 0)
2298 release_region(brdp->ioaddr2, brdp->iosize2);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002299err:
2300 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002301}
2302
2303/*****************************************************************************/
2304
2305/*
2306 * Find the next available board number that is free.
2307 */
2308
Jiri Slaby705c1862006-12-08 02:39:11 -08002309static int __devinit stl_getbrdnr(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002310{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002311 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002312
Jiri Slabyc62429d2006-12-08 02:39:14 -08002313 for (i = 0; i < STL_MAXBRDS; i++)
Jiri Slaby615e4a72006-12-08 02:38:38 -08002314 if (stl_brds[i] == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002315 if (i >= stl_nrbrds)
2316 stl_nrbrds = i + 1;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002317 return i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002318 }
Jiri Slabyc62429d2006-12-08 02:39:14 -08002319
2320 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002321}
2322
2323/*****************************************************************************/
Linus Torvalds1da177e2005-04-16 15:20:36 -07002324/*
2325 * We have a Stallion board. Allocate a board structure and
2326 * initialize it. Read its IO and IRQ resources from PCI
2327 * configuration space.
2328 */
2329
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002330static int __devinit stl_pciprobe(struct pci_dev *pdev,
2331 const struct pci_device_id *ent)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002332{
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002333 struct stlbrd *brdp;
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08002334 unsigned int i, brdtype = ent->driver_data;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002335 int brdnr, retval = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002336
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002337 if ((pdev->class >> 8) == PCI_CLASS_STORAGE_IDE)
Jiri Slaby3b85b342006-12-08 02:39:10 -08002338 goto err;
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002339
Jiri Slaby3b85b342006-12-08 02:39:10 -08002340 retval = pci_enable_device(pdev);
2341 if (retval)
2342 goto err;
2343 brdp = stl_allocbrd();
2344 if (brdp == NULL) {
2345 retval = -ENOMEM;
2346 goto err;
2347 }
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002348 mutex_lock(&stl_brdslock);
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002349 brdnr = stl_getbrdnr();
2350 if (brdnr < 0) {
Jiri Slabyfefaf9a2006-12-08 02:39:09 -08002351 dev_err(&pdev->dev, "too many boards found, "
Linus Torvalds1da177e2005-04-16 15:20:36 -07002352 "maximum supported %d\n", STL_MAXBRDS);
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002353 mutex_unlock(&stl_brdslock);
Jiri Slaby49277b12007-06-08 13:46:53 -07002354 retval = -ENODEV;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002355 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002356 }
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002357 brdp->brdnr = (unsigned int)brdnr;
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002358 stl_brds[brdp->brdnr] = brdp;
2359 mutex_unlock(&stl_brdslock);
2360
Linus Torvalds1da177e2005-04-16 15:20:36 -07002361 brdp->brdtype = brdtype;
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08002362 brdp->state |= STL_PROBED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002363
2364/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002365 * We have all resources from the board, so let's setup the actual
2366 * board structure now.
2367 */
2368 switch (brdtype) {
2369 case BRD_ECHPCI:
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002370 brdp->ioaddr2 = pci_resource_start(pdev, 0);
2371 brdp->ioaddr1 = pci_resource_start(pdev, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002372 break;
2373 case BRD_ECH64PCI:
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002374 brdp->ioaddr2 = pci_resource_start(pdev, 2);
2375 brdp->ioaddr1 = pci_resource_start(pdev, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002376 break;
2377 case BRD_EASYIOPCI:
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002378 brdp->ioaddr1 = pci_resource_start(pdev, 2);
2379 brdp->ioaddr2 = pci_resource_start(pdev, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002380 break;
2381 default:
Jiri Slabyfefaf9a2006-12-08 02:39:09 -08002382 dev_err(&pdev->dev, "unknown PCI board type=%u\n", brdtype);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002383 break;
2384 }
2385
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002386 brdp->irq = pdev->irq;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002387 retval = stl_brdinit(brdp);
2388 if (retval)
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002389 goto err_null;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002390
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002391 pci_set_drvdata(pdev, brdp);
2392
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08002393 for (i = 0; i < brdp->nrports; i++)
2394 tty_register_device(stl_serial,
2395 brdp->brdnr * STL_MAXPORTS + i, &pdev->dev);
2396
Jiri Slaby3b85b342006-12-08 02:39:10 -08002397 return 0;
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002398err_null:
2399 stl_brds[brdp->brdnr] = NULL;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002400err_fr:
2401 kfree(brdp);
2402err:
2403 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002404}
2405
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002406static void __devexit stl_pciremove(struct pci_dev *pdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002407{
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002408 struct stlbrd *brdp = pci_get_drvdata(pdev);
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08002409 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002410
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002411 free_irq(brdp->irq, brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002412
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002413 stl_cleanup_panels(brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002414
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002415 release_region(brdp->ioaddr1, brdp->iosize1);
2416 if (brdp->iosize2 > 0)
2417 release_region(brdp->ioaddr2, brdp->iosize2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002418
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08002419 for (i = 0; i < brdp->nrports; i++)
2420 tty_unregister_device(stl_serial,
2421 brdp->brdnr * STL_MAXPORTS + i);
2422
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002423 stl_brds[brdp->brdnr] = NULL;
2424 kfree(brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002425}
2426
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002427static struct pci_driver stl_pcidriver = {
2428 .name = "stallion",
2429 .id_table = stl_pcibrds,
2430 .probe = stl_pciprobe,
2431 .remove = __devexit_p(stl_pciremove)
2432};
Linus Torvalds1da177e2005-04-16 15:20:36 -07002433
2434/*****************************************************************************/
2435
2436/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002437 * Return the board stats structure to user app.
2438 */
2439
2440static int stl_getbrdstats(combrd_t __user *bp)
2441{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002442 combrd_t stl_brdstats;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002443 struct stlbrd *brdp;
2444 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002445 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002446
2447 if (copy_from_user(&stl_brdstats, bp, sizeof(combrd_t)))
2448 return -EFAULT;
2449 if (stl_brdstats.brd >= STL_MAXBRDS)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002450 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002451 brdp = stl_brds[stl_brdstats.brd];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002452 if (brdp == NULL)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002453 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002454
2455 memset(&stl_brdstats, 0, sizeof(combrd_t));
2456 stl_brdstats.brd = brdp->brdnr;
2457 stl_brdstats.type = brdp->brdtype;
2458 stl_brdstats.hwid = brdp->hwid;
2459 stl_brdstats.state = brdp->state;
2460 stl_brdstats.ioaddr = brdp->ioaddr1;
2461 stl_brdstats.ioaddr2 = brdp->ioaddr2;
2462 stl_brdstats.irq = brdp->irq;
2463 stl_brdstats.nrpanels = brdp->nrpanels;
2464 stl_brdstats.nrports = brdp->nrports;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002465 for (i = 0; i < brdp->nrpanels; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002466 panelp = brdp->panels[i];
2467 stl_brdstats.panels[i].panel = i;
2468 stl_brdstats.panels[i].hwid = panelp->hwid;
2469 stl_brdstats.panels[i].nrports = panelp->nrports;
2470 }
2471
2472 return copy_to_user(bp, &stl_brdstats, sizeof(combrd_t)) ? -EFAULT : 0;
2473}
2474
2475/*****************************************************************************/
2476
2477/*
2478 * Resolve the referenced port number into a port struct pointer.
2479 */
2480
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002481static struct stlport *stl_getport(int brdnr, int panelnr, int portnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002482{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002483 struct stlbrd *brdp;
2484 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002485
Jiri Slabyc62429d2006-12-08 02:39:14 -08002486 if (brdnr < 0 || brdnr >= STL_MAXBRDS)
2487 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002488 brdp = stl_brds[brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002489 if (brdp == NULL)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002490 return NULL;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002491 if (panelnr < 0 || (unsigned int)panelnr >= brdp->nrpanels)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002492 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002493 panelp = brdp->panels[panelnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002494 if (panelp == NULL)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002495 return NULL;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002496 if (portnr < 0 || (unsigned int)portnr >= panelp->nrports)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002497 return NULL;
2498 return panelp->ports[portnr];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002499}
2500
2501/*****************************************************************************/
2502
2503/*
2504 * Return the port stats structure to user app. A NULL port struct
2505 * pointer passed in means that we need to find out from the app
2506 * what port to get stats for (used through board control device).
2507 */
2508
Alan Coxd18a7502008-10-13 10:40:07 +01002509static int stl_getportstats(struct tty_struct *tty, struct stlport *portp, comstats_t __user *cp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002510{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002511 comstats_t stl_comstats;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002512 unsigned char *head, *tail;
2513 unsigned long flags;
2514
2515 if (!portp) {
2516 if (copy_from_user(&stl_comstats, cp, sizeof(comstats_t)))
2517 return -EFAULT;
2518 portp = stl_getport(stl_comstats.brd, stl_comstats.panel,
2519 stl_comstats.port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08002520 if (portp == NULL)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002521 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002522 }
2523
2524 portp->stats.state = portp->istate;
Alan Coxf8ae4762008-07-16 21:56:37 +01002525 portp->stats.flags = portp->port.flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002526 portp->stats.hwid = portp->hwid;
2527
2528 portp->stats.ttystate = 0;
2529 portp->stats.cflags = 0;
2530 portp->stats.iflags = 0;
2531 portp->stats.oflags = 0;
2532 portp->stats.lflags = 0;
2533 portp->stats.rxbuffered = 0;
2534
Alan Coxb65b5b52006-06-27 02:54:05 -07002535 spin_lock_irqsave(&stallion_lock, flags);
Alan Coxd18a7502008-10-13 10:40:07 +01002536 if (tty != NULL && portp->port.tty == tty) {
2537 portp->stats.ttystate = tty->flags;
2538 /* No longer available as a statistic */
2539 portp->stats.rxbuffered = 1; /*tty->flip.count; */
2540 if (tty->termios != NULL) {
2541 portp->stats.cflags = tty->termios->c_cflag;
2542 portp->stats.iflags = tty->termios->c_iflag;
2543 portp->stats.oflags = tty->termios->c_oflag;
2544 portp->stats.lflags = tty->termios->c_lflag;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002545 }
Alan Coxd18a7502008-10-13 10:40:07 +01002546 }
Alan Coxb65b5b52006-06-27 02:54:05 -07002547 spin_unlock_irqrestore(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002548
2549 head = portp->tx.head;
2550 tail = portp->tx.tail;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002551 portp->stats.txbuffered = (head >= tail) ? (head - tail) :
2552 (STL_TXBUFSIZE - (tail - head));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002553
2554 portp->stats.signals = (unsigned long) stl_getsignals(portp);
2555
2556 return copy_to_user(cp, &portp->stats,
2557 sizeof(comstats_t)) ? -EFAULT : 0;
2558}
2559
2560/*****************************************************************************/
2561
2562/*
2563 * Clear the port stats structure. We also return it zeroed out...
2564 */
2565
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002566static int stl_clrportstats(struct stlport *portp, comstats_t __user *cp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002567{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002568 comstats_t stl_comstats;
2569
Linus Torvalds1da177e2005-04-16 15:20:36 -07002570 if (!portp) {
2571 if (copy_from_user(&stl_comstats, cp, sizeof(comstats_t)))
2572 return -EFAULT;
2573 portp = stl_getport(stl_comstats.brd, stl_comstats.panel,
2574 stl_comstats.port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08002575 if (portp == NULL)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002576 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002577 }
2578
2579 memset(&portp->stats, 0, sizeof(comstats_t));
2580 portp->stats.brd = portp->brdnr;
2581 portp->stats.panel = portp->panelnr;
2582 portp->stats.port = portp->portnr;
2583 return copy_to_user(cp, &portp->stats,
2584 sizeof(comstats_t)) ? -EFAULT : 0;
2585}
2586
2587/*****************************************************************************/
2588
2589/*
2590 * Return the entire driver ports structure to a user app.
2591 */
2592
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002593static int stl_getportstruct(struct stlport __user *arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002594{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002595 struct stlport stl_dummyport;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002596 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002597
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002598 if (copy_from_user(&stl_dummyport, arg, sizeof(struct stlport)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002599 return -EFAULT;
2600 portp = stl_getport(stl_dummyport.brdnr, stl_dummyport.panelnr,
2601 stl_dummyport.portnr);
2602 if (!portp)
2603 return -ENODEV;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002604 return copy_to_user(arg, portp, sizeof(struct stlport)) ? -EFAULT : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002605}
2606
2607/*****************************************************************************/
2608
2609/*
2610 * Return the entire driver board structure to a user app.
2611 */
2612
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002613static int stl_getbrdstruct(struct stlbrd __user *arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002614{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002615 struct stlbrd stl_dummybrd;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002616 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002617
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002618 if (copy_from_user(&stl_dummybrd, arg, sizeof(struct stlbrd)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002619 return -EFAULT;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002620 if (stl_dummybrd.brdnr >= STL_MAXBRDS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002621 return -ENODEV;
2622 brdp = stl_brds[stl_dummybrd.brdnr];
2623 if (!brdp)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002624 return -ENODEV;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002625 return copy_to_user(arg, brdp, sizeof(struct stlbrd)) ? -EFAULT : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002626}
2627
2628/*****************************************************************************/
2629
2630/*
2631 * The "staliomem" device is also required to do some special operations
2632 * on the board and/or ports. In this driver it is mostly used for stats
2633 * collection.
2634 */
2635
2636static int stl_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg)
2637{
2638 int brdnr, rc;
2639 void __user *argp = (void __user *)arg;
2640
Jiri Slabya0564e12006-12-08 02:38:37 -08002641 pr_debug("stl_memioctl(ip=%p,fp=%p,cmd=%x,arg=%lx)\n", ip, fp, cmd,arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002642
2643 brdnr = iminor(ip);
2644 if (brdnr >= STL_MAXBRDS)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002645 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002646 rc = 0;
2647
2648 switch (cmd) {
2649 case COM_GETPORTSTATS:
Alan Coxd18a7502008-10-13 10:40:07 +01002650 rc = stl_getportstats(NULL, NULL, argp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002651 break;
2652 case COM_CLRPORTSTATS:
2653 rc = stl_clrportstats(NULL, argp);
2654 break;
2655 case COM_GETBRDSTATS:
2656 rc = stl_getbrdstats(argp);
2657 break;
2658 case COM_READPORT:
2659 rc = stl_getportstruct(argp);
2660 break;
2661 case COM_READBOARD:
2662 rc = stl_getbrdstruct(argp);
2663 break;
2664 default:
2665 rc = -ENOIOCTLCMD;
2666 break;
2667 }
2668
Jiri Slabyc62429d2006-12-08 02:39:14 -08002669 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002670}
2671
Jeff Dikeb68e31d2006-10-02 02:17:18 -07002672static const struct tty_operations stl_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002673 .open = stl_open,
2674 .close = stl_close,
2675 .write = stl_write,
2676 .put_char = stl_putchar,
2677 .flush_chars = stl_flushchars,
2678 .write_room = stl_writeroom,
2679 .chars_in_buffer = stl_charsinbuffer,
2680 .ioctl = stl_ioctl,
2681 .set_termios = stl_settermios,
2682 .throttle = stl_throttle,
2683 .unthrottle = stl_unthrottle,
2684 .stop = stl_stop,
2685 .start = stl_start,
2686 .hangup = stl_hangup,
2687 .flush_buffer = stl_flushbuffer,
2688 .break_ctl = stl_breakctl,
2689 .wait_until_sent = stl_waituntilsent,
2690 .send_xchar = stl_sendxchar,
2691 .read_proc = stl_readproc,
2692 .tiocmget = stl_tiocmget,
2693 .tiocmset = stl_tiocmset,
2694};
2695
2696/*****************************************************************************/
Linus Torvalds1da177e2005-04-16 15:20:36 -07002697/* CD1400 HARDWARE FUNCTIONS */
2698/*****************************************************************************/
2699
2700/*
2701 * These functions get/set/update the registers of the cd1400 UARTs.
2702 * Access to the cd1400 registers is via an address/data io port pair.
2703 * (Maybe should make this inline...)
2704 */
2705
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002706static int stl_cd1400getreg(struct stlport *portp, int regnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002707{
2708 outb((regnr + portp->uartaddr), portp->ioaddr);
Jesper Juhl014c2542006-01-15 02:37:08 +01002709 return inb(portp->ioaddr + EREG_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002710}
2711
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002712static void stl_cd1400setreg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002713{
Jiri Slabyc62429d2006-12-08 02:39:14 -08002714 outb(regnr + portp->uartaddr, portp->ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002715 outb(value, portp->ioaddr + EREG_DATA);
2716}
2717
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002718static int stl_cd1400updatereg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002719{
Jiri Slabyc62429d2006-12-08 02:39:14 -08002720 outb(regnr + portp->uartaddr, portp->ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002721 if (inb(portp->ioaddr + EREG_DATA) != value) {
2722 outb(value, portp->ioaddr + EREG_DATA);
Jesper Juhl014c2542006-01-15 02:37:08 +01002723 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002724 }
Jesper Juhl014c2542006-01-15 02:37:08 +01002725 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002726}
2727
2728/*****************************************************************************/
2729
2730/*
2731 * Inbitialize the UARTs in a panel. We don't care what sort of board
2732 * these ports are on - since the port io registers are almost
2733 * identical when dealing with ports.
2734 */
2735
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002736static int stl_cd1400panelinit(struct stlbrd *brdp, struct stlpanel *panelp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002737{
2738 unsigned int gfrcr;
2739 int chipmask, i, j;
2740 int nrchips, uartaddr, ioaddr;
Alan Coxb65b5b52006-06-27 02:54:05 -07002741 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002742
Jiri Slabya0564e12006-12-08 02:38:37 -08002743 pr_debug("stl_panelinit(brdp=%p,panelp=%p)\n", brdp, panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002744
Alan Coxb65b5b52006-06-27 02:54:05 -07002745 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002746 BRDENABLE(panelp->brdnr, panelp->pagenr);
2747
2748/*
2749 * Check that each chip is present and started up OK.
2750 */
2751 chipmask = 0;
2752 nrchips = panelp->nrports / CD1400_PORTS;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002753 for (i = 0; i < nrchips; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002754 if (brdp->brdtype == BRD_ECHPCI) {
2755 outb((panelp->pagenr + (i >> 1)), brdp->ioctrl);
2756 ioaddr = panelp->iobase;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002757 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002758 ioaddr = panelp->iobase + (EREG_BANKSIZE * (i >> 1));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002759 uartaddr = (i & 0x01) ? 0x080 : 0;
2760 outb((GFRCR + uartaddr), ioaddr);
2761 outb(0, (ioaddr + EREG_DATA));
2762 outb((CCR + uartaddr), ioaddr);
2763 outb(CCR_RESETFULL, (ioaddr + EREG_DATA));
2764 outb(CCR_RESETFULL, (ioaddr + EREG_DATA));
2765 outb((GFRCR + uartaddr), ioaddr);
Jiri Slabyc62429d2006-12-08 02:39:14 -08002766 for (j = 0; j < CCR_MAXWAIT; j++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002767 if ((gfrcr = inb(ioaddr + EREG_DATA)) != 0)
2768 break;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002769
Linus Torvalds1da177e2005-04-16 15:20:36 -07002770 if ((j >= CCR_MAXWAIT) || (gfrcr < 0x40) || (gfrcr > 0x60)) {
2771 printk("STALLION: cd1400 not responding, "
2772 "brd=%d panel=%d chip=%d\n",
2773 panelp->brdnr, panelp->panelnr, i);
2774 continue;
2775 }
2776 chipmask |= (0x1 << i);
2777 outb((PPR + uartaddr), ioaddr);
2778 outb(PPR_SCALAR, (ioaddr + EREG_DATA));
2779 }
2780
2781 BRDDISABLE(panelp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07002782 spin_unlock_irqrestore(&brd_lock, flags);
Jesper Juhl014c2542006-01-15 02:37:08 +01002783 return chipmask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002784}
2785
2786/*****************************************************************************/
2787
2788/*
2789 * Initialize hardware specific port registers.
2790 */
2791
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002792static void stl_cd1400portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002793{
Alan Coxb65b5b52006-06-27 02:54:05 -07002794 unsigned long flags;
Jiri Slabya0564e12006-12-08 02:38:37 -08002795 pr_debug("stl_cd1400portinit(brdp=%p,panelp=%p,portp=%p)\n", brdp,
2796 panelp, portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002797
Jiri Slaby615e4a72006-12-08 02:38:38 -08002798 if ((brdp == NULL) || (panelp == NULL) ||
2799 (portp == NULL))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002800 return;
2801
Alan Coxb65b5b52006-06-27 02:54:05 -07002802 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002803 portp->ioaddr = panelp->iobase + (((brdp->brdtype == BRD_ECHPCI) ||
2804 (portp->portnr < 8)) ? 0 : EREG_BANKSIZE);
2805 portp->uartaddr = (portp->portnr & 0x04) << 5;
2806 portp->pagenr = panelp->pagenr + (portp->portnr >> 3);
2807
2808 BRDENABLE(portp->brdnr, portp->pagenr);
2809 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
2810 stl_cd1400setreg(portp, LIVR, (portp->portnr << 3));
2811 portp->hwid = stl_cd1400getreg(portp, GFRCR);
2812 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07002813 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002814}
2815
2816/*****************************************************************************/
2817
2818/*
2819 * Wait for the command register to be ready. We will poll this,
2820 * since it won't usually take too long to be ready.
2821 */
2822
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002823static void stl_cd1400ccrwait(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002824{
2825 int i;
2826
Jiri Slabyc62429d2006-12-08 02:39:14 -08002827 for (i = 0; i < CCR_MAXWAIT; i++)
2828 if (stl_cd1400getreg(portp, CCR) == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002829 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002830
2831 printk("STALLION: cd1400 not responding, port=%d panel=%d brd=%d\n",
2832 portp->portnr, portp->panelnr, portp->brdnr);
2833}
2834
2835/*****************************************************************************/
2836
2837/*
2838 * Set up the cd1400 registers for a port based on the termios port
2839 * settings.
2840 */
2841
Alan Cox606d0992006-12-08 02:38:45 -08002842static void stl_cd1400setport(struct stlport *portp, struct ktermios *tiosp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002843{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002844 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002845 unsigned long flags;
2846 unsigned int clkdiv, baudrate;
2847 unsigned char cor1, cor2, cor3;
2848 unsigned char cor4, cor5, ccr;
2849 unsigned char srer, sreron, sreroff;
2850 unsigned char mcor1, mcor2, rtpr;
2851 unsigned char clk, div;
2852
2853 cor1 = 0;
2854 cor2 = 0;
2855 cor3 = 0;
2856 cor4 = 0;
2857 cor5 = 0;
2858 ccr = 0;
2859 rtpr = 0;
2860 clk = 0;
2861 div = 0;
2862 mcor1 = 0;
2863 mcor2 = 0;
2864 sreron = 0;
2865 sreroff = 0;
2866
2867 brdp = stl_brds[portp->brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002868 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002869 return;
2870
2871/*
2872 * Set up the RX char ignore mask with those RX error types we
2873 * can ignore. We can get the cd1400 to help us out a little here,
2874 * it will ignore parity errors and breaks for us.
2875 */
2876 portp->rxignoremsk = 0;
2877 if (tiosp->c_iflag & IGNPAR) {
2878 portp->rxignoremsk |= (ST_PARITY | ST_FRAMING | ST_OVERRUN);
2879 cor1 |= COR1_PARIGNORE;
2880 }
2881 if (tiosp->c_iflag & IGNBRK) {
2882 portp->rxignoremsk |= ST_BREAK;
2883 cor4 |= COR4_IGNBRK;
2884 }
2885
2886 portp->rxmarkmsk = ST_OVERRUN;
2887 if (tiosp->c_iflag & (INPCK | PARMRK))
2888 portp->rxmarkmsk |= (ST_PARITY | ST_FRAMING);
2889 if (tiosp->c_iflag & BRKINT)
2890 portp->rxmarkmsk |= ST_BREAK;
2891
2892/*
2893 * Go through the char size, parity and stop bits and set all the
2894 * option register appropriately.
2895 */
2896 switch (tiosp->c_cflag & CSIZE) {
2897 case CS5:
2898 cor1 |= COR1_CHL5;
2899 break;
2900 case CS6:
2901 cor1 |= COR1_CHL6;
2902 break;
2903 case CS7:
2904 cor1 |= COR1_CHL7;
2905 break;
2906 default:
2907 cor1 |= COR1_CHL8;
2908 break;
2909 }
2910
2911 if (tiosp->c_cflag & CSTOPB)
2912 cor1 |= COR1_STOP2;
2913 else
2914 cor1 |= COR1_STOP1;
2915
2916 if (tiosp->c_cflag & PARENB) {
2917 if (tiosp->c_cflag & PARODD)
2918 cor1 |= (COR1_PARENB | COR1_PARODD);
2919 else
2920 cor1 |= (COR1_PARENB | COR1_PAREVEN);
2921 } else {
2922 cor1 |= COR1_PARNONE;
2923 }
2924
2925/*
2926 * Set the RX FIFO threshold at 6 chars. This gives a bit of breathing
2927 * space for hardware flow control and the like. This should be set to
2928 * VMIN. Also here we will set the RX data timeout to 10ms - this should
2929 * really be based on VTIME.
2930 */
2931 cor3 |= FIFO_RXTHRESHOLD;
2932 rtpr = 2;
2933
2934/*
2935 * Calculate the baud rate timers. For now we will just assume that
2936 * the input and output baud are the same. Could have used a baud
2937 * table here, but this way we can generate virtually any baud rate
2938 * we like!
2939 */
2940 baudrate = tiosp->c_cflag & CBAUD;
2941 if (baudrate & CBAUDEX) {
2942 baudrate &= ~CBAUDEX;
2943 if ((baudrate < 1) || (baudrate > 4))
2944 tiosp->c_cflag &= ~CBAUDEX;
2945 else
2946 baudrate += 15;
2947 }
2948 baudrate = stl_baudrates[baudrate];
2949 if ((tiosp->c_cflag & CBAUD) == B38400) {
Alan Coxf8ae4762008-07-16 21:56:37 +01002950 if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002951 baudrate = 57600;
Alan Coxf8ae4762008-07-16 21:56:37 +01002952 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002953 baudrate = 115200;
Alan Coxf8ae4762008-07-16 21:56:37 +01002954 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002955 baudrate = 230400;
Alan Coxf8ae4762008-07-16 21:56:37 +01002956 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002957 baudrate = 460800;
Alan Coxf8ae4762008-07-16 21:56:37 +01002958 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002959 baudrate = (portp->baud_base / portp->custom_divisor);
2960 }
2961 if (baudrate > STL_CD1400MAXBAUD)
2962 baudrate = STL_CD1400MAXBAUD;
2963
2964 if (baudrate > 0) {
Jiri Slabyc62429d2006-12-08 02:39:14 -08002965 for (clk = 0; clk < CD1400_NUMCLKS; clk++) {
2966 clkdiv = (portp->clk / stl_cd1400clkdivs[clk]) / baudrate;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002967 if (clkdiv < 0x100)
2968 break;
2969 }
2970 div = (unsigned char) clkdiv;
2971 }
2972
2973/*
2974 * Check what form of modem signaling is required and set it up.
2975 */
2976 if ((tiosp->c_cflag & CLOCAL) == 0) {
2977 mcor1 |= MCOR1_DCD;
2978 mcor2 |= MCOR2_DCD;
2979 sreron |= SRER_MODEM;
Alan Coxf8ae4762008-07-16 21:56:37 +01002980 portp->port.flags |= ASYNC_CHECK_CD;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002981 } else
Alan Coxf8ae4762008-07-16 21:56:37 +01002982 portp->port.flags &= ~ASYNC_CHECK_CD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002983
2984/*
2985 * Setup cd1400 enhanced modes if we can. In particular we want to
2986 * handle as much of the flow control as possible automatically. As
2987 * well as saving a few CPU cycles it will also greatly improve flow
2988 * control reliability.
2989 */
2990 if (tiosp->c_iflag & IXON) {
2991 cor2 |= COR2_TXIBE;
2992 cor3 |= COR3_SCD12;
2993 if (tiosp->c_iflag & IXANY)
2994 cor2 |= COR2_IXM;
2995 }
2996
2997 if (tiosp->c_cflag & CRTSCTS) {
2998 cor2 |= COR2_CTSAE;
2999 mcor1 |= FIFO_RTSTHRESHOLD;
3000 }
3001
3002/*
3003 * All cd1400 register values calculated so go through and set
3004 * them all up.
3005 */
3006
Jiri Slabya0564e12006-12-08 02:38:37 -08003007 pr_debug("SETPORT: portnr=%d panelnr=%d brdnr=%d\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003008 portp->portnr, portp->panelnr, portp->brdnr);
Jiri Slabya0564e12006-12-08 02:38:37 -08003009 pr_debug(" cor1=%x cor2=%x cor3=%x cor4=%x cor5=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003010 cor1, cor2, cor3, cor4, cor5);
Jiri Slabya0564e12006-12-08 02:38:37 -08003011 pr_debug(" mcor1=%x mcor2=%x rtpr=%x sreron=%x sreroff=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003012 mcor1, mcor2, rtpr, sreron, sreroff);
Jiri Slabya0564e12006-12-08 02:38:37 -08003013 pr_debug(" tcor=%x tbpr=%x rcor=%x rbpr=%x\n", clk, div, clk, div);
3014 pr_debug(" schr1=%x schr2=%x schr3=%x schr4=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003015 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP],
3016 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003017
Alan Coxb65b5b52006-06-27 02:54:05 -07003018 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003019 BRDENABLE(portp->brdnr, portp->pagenr);
3020 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x3));
3021 srer = stl_cd1400getreg(portp, SRER);
3022 stl_cd1400setreg(portp, SRER, 0);
3023 if (stl_cd1400updatereg(portp, COR1, cor1))
3024 ccr = 1;
3025 if (stl_cd1400updatereg(portp, COR2, cor2))
3026 ccr = 1;
3027 if (stl_cd1400updatereg(portp, COR3, cor3))
3028 ccr = 1;
3029 if (ccr) {
3030 stl_cd1400ccrwait(portp);
3031 stl_cd1400setreg(portp, CCR, CCR_CORCHANGE);
3032 }
3033 stl_cd1400setreg(portp, COR4, cor4);
3034 stl_cd1400setreg(portp, COR5, cor5);
3035 stl_cd1400setreg(portp, MCOR1, mcor1);
3036 stl_cd1400setreg(portp, MCOR2, mcor2);
3037 if (baudrate > 0) {
3038 stl_cd1400setreg(portp, TCOR, clk);
3039 stl_cd1400setreg(portp, TBPR, div);
3040 stl_cd1400setreg(portp, RCOR, clk);
3041 stl_cd1400setreg(portp, RBPR, div);
3042 }
3043 stl_cd1400setreg(portp, SCHR1, tiosp->c_cc[VSTART]);
3044 stl_cd1400setreg(portp, SCHR2, tiosp->c_cc[VSTOP]);
3045 stl_cd1400setreg(portp, SCHR3, tiosp->c_cc[VSTART]);
3046 stl_cd1400setreg(portp, SCHR4, tiosp->c_cc[VSTOP]);
3047 stl_cd1400setreg(portp, RTPR, rtpr);
3048 mcor1 = stl_cd1400getreg(portp, MSVR1);
3049 if (mcor1 & MSVR1_DCD)
3050 portp->sigs |= TIOCM_CD;
3051 else
3052 portp->sigs &= ~TIOCM_CD;
3053 stl_cd1400setreg(portp, SRER, ((srer & ~sreroff) | sreron));
3054 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003055 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003056}
3057
3058/*****************************************************************************/
3059
3060/*
3061 * Set the state of the DTR and RTS signals.
3062 */
3063
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003064static void stl_cd1400setsignals(struct stlport *portp, int dtr, int rts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003065{
3066 unsigned char msvr1, msvr2;
3067 unsigned long flags;
3068
Jiri Slabya0564e12006-12-08 02:38:37 -08003069 pr_debug("stl_cd1400setsignals(portp=%p,dtr=%d,rts=%d)\n",
3070 portp, dtr, rts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003071
3072 msvr1 = 0;
3073 msvr2 = 0;
3074 if (dtr > 0)
3075 msvr1 = MSVR1_DTR;
3076 if (rts > 0)
3077 msvr2 = MSVR2_RTS;
3078
Alan Coxb65b5b52006-06-27 02:54:05 -07003079 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003080 BRDENABLE(portp->brdnr, portp->pagenr);
3081 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3082 if (rts >= 0)
3083 stl_cd1400setreg(portp, MSVR2, msvr2);
3084 if (dtr >= 0)
3085 stl_cd1400setreg(portp, MSVR1, msvr1);
3086 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003087 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003088}
3089
3090/*****************************************************************************/
3091
3092/*
3093 * Return the state of the signals.
3094 */
3095
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003096static int stl_cd1400getsignals(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003097{
3098 unsigned char msvr1, msvr2;
3099 unsigned long flags;
3100 int sigs;
3101
Jiri Slabya0564e12006-12-08 02:38:37 -08003102 pr_debug("stl_cd1400getsignals(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003103
Alan Coxb65b5b52006-06-27 02:54:05 -07003104 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003105 BRDENABLE(portp->brdnr, portp->pagenr);
3106 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3107 msvr1 = stl_cd1400getreg(portp, MSVR1);
3108 msvr2 = stl_cd1400getreg(portp, MSVR2);
3109 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003110 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003111
3112 sigs = 0;
3113 sigs |= (msvr1 & MSVR1_DCD) ? TIOCM_CD : 0;
3114 sigs |= (msvr1 & MSVR1_CTS) ? TIOCM_CTS : 0;
3115 sigs |= (msvr1 & MSVR1_DTR) ? TIOCM_DTR : 0;
3116 sigs |= (msvr2 & MSVR2_RTS) ? TIOCM_RTS : 0;
3117#if 0
3118 sigs |= (msvr1 & MSVR1_RI) ? TIOCM_RI : 0;
3119 sigs |= (msvr1 & MSVR1_DSR) ? TIOCM_DSR : 0;
3120#else
3121 sigs |= TIOCM_DSR;
3122#endif
Jesper Juhl014c2542006-01-15 02:37:08 +01003123 return sigs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003124}
3125
3126/*****************************************************************************/
3127
3128/*
3129 * Enable/Disable the Transmitter and/or Receiver.
3130 */
3131
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003132static void stl_cd1400enablerxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003133{
3134 unsigned char ccr;
3135 unsigned long flags;
3136
Jiri Slabya0564e12006-12-08 02:38:37 -08003137 pr_debug("stl_cd1400enablerxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
3138
Linus Torvalds1da177e2005-04-16 15:20:36 -07003139 ccr = 0;
3140
3141 if (tx == 0)
3142 ccr |= CCR_TXDISABLE;
3143 else if (tx > 0)
3144 ccr |= CCR_TXENABLE;
3145 if (rx == 0)
3146 ccr |= CCR_RXDISABLE;
3147 else if (rx > 0)
3148 ccr |= CCR_RXENABLE;
3149
Alan Coxb65b5b52006-06-27 02:54:05 -07003150 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003151 BRDENABLE(portp->brdnr, portp->pagenr);
3152 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3153 stl_cd1400ccrwait(portp);
3154 stl_cd1400setreg(portp, CCR, ccr);
3155 stl_cd1400ccrwait(portp);
3156 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003157 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003158}
3159
3160/*****************************************************************************/
3161
3162/*
3163 * Start/stop the Transmitter and/or Receiver.
3164 */
3165
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003166static void stl_cd1400startrxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003167{
3168 unsigned char sreron, sreroff;
3169 unsigned long flags;
3170
Jiri Slabya0564e12006-12-08 02:38:37 -08003171 pr_debug("stl_cd1400startrxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003172
3173 sreron = 0;
3174 sreroff = 0;
3175 if (tx == 0)
3176 sreroff |= (SRER_TXDATA | SRER_TXEMPTY);
3177 else if (tx == 1)
3178 sreron |= SRER_TXDATA;
3179 else if (tx >= 2)
3180 sreron |= SRER_TXEMPTY;
3181 if (rx == 0)
3182 sreroff |= SRER_RXDATA;
3183 else if (rx > 0)
3184 sreron |= SRER_RXDATA;
3185
Alan Coxb65b5b52006-06-27 02:54:05 -07003186 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003187 BRDENABLE(portp->brdnr, portp->pagenr);
3188 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3189 stl_cd1400setreg(portp, SRER,
3190 ((stl_cd1400getreg(portp, SRER) & ~sreroff) | sreron));
3191 BRDDISABLE(portp->brdnr);
3192 if (tx > 0)
3193 set_bit(ASYI_TXBUSY, &portp->istate);
Alan Coxb65b5b52006-06-27 02:54:05 -07003194 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003195}
3196
3197/*****************************************************************************/
3198
3199/*
3200 * Disable all interrupts from this port.
3201 */
3202
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003203static void stl_cd1400disableintrs(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003204{
3205 unsigned long flags;
3206
Jiri Slabya0564e12006-12-08 02:38:37 -08003207 pr_debug("stl_cd1400disableintrs(portp=%p)\n", portp);
3208
Alan Coxb65b5b52006-06-27 02:54:05 -07003209 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003210 BRDENABLE(portp->brdnr, portp->pagenr);
3211 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3212 stl_cd1400setreg(portp, SRER, 0);
3213 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003214 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003215}
3216
3217/*****************************************************************************/
3218
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003219static void stl_cd1400sendbreak(struct stlport *portp, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003220{
3221 unsigned long flags;
3222
Jiri Slabya0564e12006-12-08 02:38:37 -08003223 pr_debug("stl_cd1400sendbreak(portp=%p,len=%d)\n", portp, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003224
Alan Coxb65b5b52006-06-27 02:54:05 -07003225 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003226 BRDENABLE(portp->brdnr, portp->pagenr);
3227 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3228 stl_cd1400setreg(portp, SRER,
3229 ((stl_cd1400getreg(portp, SRER) & ~SRER_TXDATA) |
3230 SRER_TXEMPTY));
3231 BRDDISABLE(portp->brdnr);
3232 portp->brklen = len;
3233 if (len == 1)
3234 portp->stats.txbreaks++;
Alan Coxb65b5b52006-06-27 02:54:05 -07003235 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003236}
3237
3238/*****************************************************************************/
3239
3240/*
3241 * Take flow control actions...
3242 */
3243
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003244static void stl_cd1400flowctrl(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003245{
3246 struct tty_struct *tty;
3247 unsigned long flags;
3248
Jiri Slabya0564e12006-12-08 02:38:37 -08003249 pr_debug("stl_cd1400flowctrl(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003250
Jiri Slaby615e4a72006-12-08 02:38:38 -08003251 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003252 return;
Alan Coxd18a7502008-10-13 10:40:07 +01003253 tty = tty_port_tty_get(&portp->port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08003254 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003255 return;
3256
Alan Coxb65b5b52006-06-27 02:54:05 -07003257 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003258 BRDENABLE(portp->brdnr, portp->pagenr);
3259 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3260
3261 if (state) {
3262 if (tty->termios->c_iflag & IXOFF) {
3263 stl_cd1400ccrwait(portp);
3264 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR1);
3265 portp->stats.rxxon++;
3266 stl_cd1400ccrwait(portp);
3267 }
3268/*
3269 * Question: should we return RTS to what it was before? It may
3270 * have been set by an ioctl... Suppose not, since if you have
3271 * hardware flow control set then it is pretty silly to go and
3272 * set the RTS line by hand.
3273 */
3274 if (tty->termios->c_cflag & CRTSCTS) {
3275 stl_cd1400setreg(portp, MCOR1,
3276 (stl_cd1400getreg(portp, MCOR1) |
3277 FIFO_RTSTHRESHOLD));
3278 stl_cd1400setreg(portp, MSVR2, MSVR2_RTS);
3279 portp->stats.rxrtson++;
3280 }
3281 } else {
3282 if (tty->termios->c_iflag & IXOFF) {
3283 stl_cd1400ccrwait(portp);
3284 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR2);
3285 portp->stats.rxxoff++;
3286 stl_cd1400ccrwait(portp);
3287 }
3288 if (tty->termios->c_cflag & CRTSCTS) {
3289 stl_cd1400setreg(portp, MCOR1,
3290 (stl_cd1400getreg(portp, MCOR1) & 0xf0));
3291 stl_cd1400setreg(portp, MSVR2, 0);
3292 portp->stats.rxrtsoff++;
3293 }
3294 }
3295
3296 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003297 spin_unlock_irqrestore(&brd_lock, flags);
Alan Coxd18a7502008-10-13 10:40:07 +01003298 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003299}
3300
3301/*****************************************************************************/
3302
3303/*
3304 * Send a flow control character...
3305 */
3306
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003307static void stl_cd1400sendflow(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003308{
3309 struct tty_struct *tty;
3310 unsigned long flags;
3311
Jiri Slabya0564e12006-12-08 02:38:37 -08003312 pr_debug("stl_cd1400sendflow(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003313
Jiri Slaby615e4a72006-12-08 02:38:38 -08003314 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003315 return;
Alan Coxd18a7502008-10-13 10:40:07 +01003316 tty = tty_port_tty_get(&portp->port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08003317 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003318 return;
3319
Alan Coxb65b5b52006-06-27 02:54:05 -07003320 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003321 BRDENABLE(portp->brdnr, portp->pagenr);
3322 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3323 if (state) {
3324 stl_cd1400ccrwait(portp);
3325 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR1);
3326 portp->stats.rxxon++;
3327 stl_cd1400ccrwait(portp);
3328 } else {
3329 stl_cd1400ccrwait(portp);
3330 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR2);
3331 portp->stats.rxxoff++;
3332 stl_cd1400ccrwait(portp);
3333 }
3334 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003335 spin_unlock_irqrestore(&brd_lock, flags);
Alan Coxd18a7502008-10-13 10:40:07 +01003336 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003337}
3338
3339/*****************************************************************************/
3340
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003341static void stl_cd1400flush(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003342{
3343 unsigned long flags;
3344
Jiri Slabya0564e12006-12-08 02:38:37 -08003345 pr_debug("stl_cd1400flush(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003346
Jiri Slaby615e4a72006-12-08 02:38:38 -08003347 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003348 return;
3349
Alan Coxb65b5b52006-06-27 02:54:05 -07003350 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003351 BRDENABLE(portp->brdnr, portp->pagenr);
3352 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3353 stl_cd1400ccrwait(portp);
3354 stl_cd1400setreg(portp, CCR, CCR_TXFLUSHFIFO);
3355 stl_cd1400ccrwait(portp);
3356 portp->tx.tail = portp->tx.head;
3357 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003358 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003359}
3360
3361/*****************************************************************************/
3362
3363/*
3364 * Return the current state of data flow on this port. This is only
3365 * really interresting when determining if data has fully completed
3366 * transmission or not... This is easy for the cd1400, it accurately
3367 * maintains the busy port flag.
3368 */
3369
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003370static int stl_cd1400datastate(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003371{
Jiri Slabya0564e12006-12-08 02:38:37 -08003372 pr_debug("stl_cd1400datastate(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003373
Jiri Slaby615e4a72006-12-08 02:38:38 -08003374 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01003375 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003376
Jesper Juhl014c2542006-01-15 02:37:08 +01003377 return test_bit(ASYI_TXBUSY, &portp->istate) ? 1 : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003378}
3379
3380/*****************************************************************************/
3381
3382/*
3383 * Interrupt service routine for cd1400 EasyIO boards.
3384 */
3385
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003386static void stl_cd1400eiointr(struct stlpanel *panelp, unsigned int iobase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003387{
3388 unsigned char svrtype;
3389
Jiri Slabya0564e12006-12-08 02:38:37 -08003390 pr_debug("stl_cd1400eiointr(panelp=%p,iobase=%x)\n", panelp, iobase);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003391
Alan Coxb65b5b52006-06-27 02:54:05 -07003392 spin_lock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003393 outb(SVRR, iobase);
3394 svrtype = inb(iobase + EREG_DATA);
3395 if (panelp->nrports > 4) {
3396 outb((SVRR + 0x80), iobase);
3397 svrtype |= inb(iobase + EREG_DATA);
3398 }
3399
3400 if (svrtype & SVRR_RX)
3401 stl_cd1400rxisr(panelp, iobase);
3402 else if (svrtype & SVRR_TX)
3403 stl_cd1400txisr(panelp, iobase);
3404 else if (svrtype & SVRR_MDM)
3405 stl_cd1400mdmisr(panelp, iobase);
Alan Coxb65b5b52006-06-27 02:54:05 -07003406
3407 spin_unlock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003408}
3409
3410/*****************************************************************************/
3411
3412/*
3413 * Interrupt service routine for cd1400 panels.
3414 */
3415
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003416static void stl_cd1400echintr(struct stlpanel *panelp, unsigned int iobase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003417{
3418 unsigned char svrtype;
3419
Jiri Slabya0564e12006-12-08 02:38:37 -08003420 pr_debug("stl_cd1400echintr(panelp=%p,iobase=%x)\n", panelp, iobase);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003421
3422 outb(SVRR, iobase);
3423 svrtype = inb(iobase + EREG_DATA);
3424 outb((SVRR + 0x80), iobase);
3425 svrtype |= inb(iobase + EREG_DATA);
3426 if (svrtype & SVRR_RX)
3427 stl_cd1400rxisr(panelp, iobase);
3428 else if (svrtype & SVRR_TX)
3429 stl_cd1400txisr(panelp, iobase);
3430 else if (svrtype & SVRR_MDM)
3431 stl_cd1400mdmisr(panelp, iobase);
3432}
3433
3434
3435/*****************************************************************************/
3436
3437/*
3438 * Unfortunately we need to handle breaks in the TX data stream, since
3439 * this is the only way to generate them on the cd1400.
3440 */
3441
Jiri Slaby60be4812006-12-08 02:38:40 -08003442static int stl_cd1400breakisr(struct stlport *portp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003443{
3444 if (portp->brklen == 1) {
3445 outb((COR2 + portp->uartaddr), ioaddr);
3446 outb((inb(ioaddr + EREG_DATA) | COR2_ETC),
3447 (ioaddr + EREG_DATA));
3448 outb((TDR + portp->uartaddr), ioaddr);
3449 outb(ETC_CMD, (ioaddr + EREG_DATA));
3450 outb(ETC_STARTBREAK, (ioaddr + EREG_DATA));
3451 outb((SRER + portp->uartaddr), ioaddr);
3452 outb((inb(ioaddr + EREG_DATA) & ~(SRER_TXDATA | SRER_TXEMPTY)),
3453 (ioaddr + EREG_DATA));
Jesper Juhl014c2542006-01-15 02:37:08 +01003454 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003455 } else if (portp->brklen > 1) {
3456 outb((TDR + portp->uartaddr), ioaddr);
3457 outb(ETC_CMD, (ioaddr + EREG_DATA));
3458 outb(ETC_STOPBREAK, (ioaddr + EREG_DATA));
3459 portp->brklen = -1;
Jesper Juhl014c2542006-01-15 02:37:08 +01003460 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003461 } else {
3462 outb((COR2 + portp->uartaddr), ioaddr);
3463 outb((inb(ioaddr + EREG_DATA) & ~COR2_ETC),
3464 (ioaddr + EREG_DATA));
3465 portp->brklen = 0;
3466 }
Jesper Juhl014c2542006-01-15 02:37:08 +01003467 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003468}
3469
3470/*****************************************************************************/
3471
3472/*
3473 * Transmit interrupt handler. This has gotta be fast! Handling TX
3474 * chars is pretty simple, stuff as many as possible from the TX buffer
3475 * into the cd1400 FIFO. Must also handle TX breaks here, since they
3476 * are embedded as commands in the data stream. Oh no, had to use a goto!
3477 * This could be optimized more, will do when I get time...
3478 * In practice it is possible that interrupts are enabled but that the
3479 * port has been hung up. Need to handle not having any TX buffer here,
3480 * this is done by using the side effect that head and tail will also
3481 * be NULL if the buffer has been freed.
3482 */
3483
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003484static void stl_cd1400txisr(struct stlpanel *panelp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003485{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003486 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003487 int len, stlen;
3488 char *head, *tail;
3489 unsigned char ioack, srer;
Alan Coxd18a7502008-10-13 10:40:07 +01003490 struct tty_struct *tty;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003491
Jiri Slabya0564e12006-12-08 02:38:37 -08003492 pr_debug("stl_cd1400txisr(panelp=%p,ioaddr=%x)\n", panelp, ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003493
3494 ioack = inb(ioaddr + EREG_TXACK);
3495 if (((ioack & panelp->ackmask) != 0) ||
3496 ((ioack & ACK_TYPMASK) != ACK_TYPTX)) {
3497 printk("STALLION: bad TX interrupt ack value=%x\n", ioack);
3498 return;
3499 }
3500 portp = panelp->ports[(ioack >> 3)];
3501
3502/*
3503 * Unfortunately we need to handle breaks in the data stream, since
3504 * this is the only way to generate them on the cd1400. Do it now if
3505 * a break is to be sent.
3506 */
3507 if (portp->brklen != 0)
3508 if (stl_cd1400breakisr(portp, ioaddr))
3509 goto stl_txalldone;
3510
3511 head = portp->tx.head;
3512 tail = portp->tx.tail;
3513 len = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
3514 if ((len == 0) || ((len < STL_TXBUFLOW) &&
3515 (test_bit(ASYI_TXLOW, &portp->istate) == 0))) {
3516 set_bit(ASYI_TXLOW, &portp->istate);
Alan Coxd18a7502008-10-13 10:40:07 +01003517 tty = tty_port_tty_get(&portp->port);
3518 if (tty) {
3519 tty_wakeup(tty);
3520 tty_kref_put(tty);
3521 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003522 }
3523
3524 if (len == 0) {
3525 outb((SRER + portp->uartaddr), ioaddr);
3526 srer = inb(ioaddr + EREG_DATA);
3527 if (srer & SRER_TXDATA) {
3528 srer = (srer & ~SRER_TXDATA) | SRER_TXEMPTY;
3529 } else {
3530 srer &= ~(SRER_TXDATA | SRER_TXEMPTY);
3531 clear_bit(ASYI_TXBUSY, &portp->istate);
3532 }
3533 outb(srer, (ioaddr + EREG_DATA));
3534 } else {
Jiri Slaby843b5682006-12-08 02:39:12 -08003535 len = min(len, CD1400_TXFIFOSIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003536 portp->stats.txtotal += len;
Jiri Slaby319fe7c2008-02-07 00:16:36 -08003537 stlen = min_t(unsigned int, len,
3538 (portp->tx.buf + STL_TXBUFSIZE) - tail);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003539 outb((TDR + portp->uartaddr), ioaddr);
3540 outsb((ioaddr + EREG_DATA), tail, stlen);
3541 len -= stlen;
3542 tail += stlen;
3543 if (tail >= (portp->tx.buf + STL_TXBUFSIZE))
3544 tail = portp->tx.buf;
3545 if (len > 0) {
3546 outsb((ioaddr + EREG_DATA), tail, len);
3547 tail += len;
3548 }
3549 portp->tx.tail = tail;
3550 }
3551
3552stl_txalldone:
3553 outb((EOSRR + portp->uartaddr), ioaddr);
3554 outb(0, (ioaddr + EREG_DATA));
3555}
3556
3557/*****************************************************************************/
3558
3559/*
3560 * Receive character interrupt handler. Determine if we have good chars
3561 * or bad chars and then process appropriately. Good chars are easy
3562 * just shove the lot into the RX buffer and set all status byte to 0.
3563 * If a bad RX char then process as required. This routine needs to be
3564 * fast! In practice it is possible that we get an interrupt on a port
3565 * that is closed. This can happen on hangups - since they completely
3566 * shutdown a port not in user context. Need to handle this case.
3567 */
3568
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003569static void stl_cd1400rxisr(struct stlpanel *panelp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003570{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003571 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003572 struct tty_struct *tty;
3573 unsigned int ioack, len, buflen;
3574 unsigned char status;
3575 char ch;
3576
Jiri Slabya0564e12006-12-08 02:38:37 -08003577 pr_debug("stl_cd1400rxisr(panelp=%p,ioaddr=%x)\n", panelp, ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003578
3579 ioack = inb(ioaddr + EREG_RXACK);
3580 if ((ioack & panelp->ackmask) != 0) {
3581 printk("STALLION: bad RX interrupt ack value=%x\n", ioack);
3582 return;
3583 }
3584 portp = panelp->ports[(ioack >> 3)];
Alan Coxd18a7502008-10-13 10:40:07 +01003585 tty = tty_port_tty_get(&portp->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003586
3587 if ((ioack & ACK_TYPMASK) == ACK_TYPRXGOOD) {
3588 outb((RDCR + portp->uartaddr), ioaddr);
3589 len = inb(ioaddr + EREG_DATA);
Alan Cox33f0f882006-01-09 20:54:13 -08003590 if (tty == NULL || (buflen = tty_buffer_request_room(tty, len)) == 0) {
Jiri Slaby319fe7c2008-02-07 00:16:36 -08003591 len = min_t(unsigned int, len, sizeof(stl_unwanted));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003592 outb((RDSR + portp->uartaddr), ioaddr);
3593 insb((ioaddr + EREG_DATA), &stl_unwanted[0], len);
3594 portp->stats.rxlost += len;
3595 portp->stats.rxtotal += len;
3596 } else {
Jiri Slaby843b5682006-12-08 02:39:12 -08003597 len = min(len, buflen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003598 if (len > 0) {
Alan Cox33f0f882006-01-09 20:54:13 -08003599 unsigned char *ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003600 outb((RDSR + portp->uartaddr), ioaddr);
Alan Cox33f0f882006-01-09 20:54:13 -08003601 tty_prepare_flip_string(tty, &ptr, len);
3602 insb((ioaddr + EREG_DATA), ptr, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003603 tty_schedule_flip(tty);
3604 portp->stats.rxtotal += len;
3605 }
3606 }
3607 } else if ((ioack & ACK_TYPMASK) == ACK_TYPRXBAD) {
3608 outb((RDSR + portp->uartaddr), ioaddr);
3609 status = inb(ioaddr + EREG_DATA);
3610 ch = inb(ioaddr + EREG_DATA);
3611 if (status & ST_PARITY)
3612 portp->stats.rxparity++;
3613 if (status & ST_FRAMING)
3614 portp->stats.rxframing++;
3615 if (status & ST_OVERRUN)
3616 portp->stats.rxoverrun++;
3617 if (status & ST_BREAK)
3618 portp->stats.rxbreaks++;
3619 if (status & ST_SCHARMASK) {
3620 if ((status & ST_SCHARMASK) == ST_SCHAR1)
3621 portp->stats.txxon++;
3622 if ((status & ST_SCHARMASK) == ST_SCHAR2)
3623 portp->stats.txxoff++;
3624 goto stl_rxalldone;
3625 }
Alan Cox33f0f882006-01-09 20:54:13 -08003626 if (tty != NULL && (portp->rxignoremsk & status) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003627 if (portp->rxmarkmsk & status) {
3628 if (status & ST_BREAK) {
3629 status = TTY_BREAK;
Alan Coxf8ae4762008-07-16 21:56:37 +01003630 if (portp->port.flags & ASYNC_SAK) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003631 do_SAK(tty);
3632 BRDENABLE(portp->brdnr, portp->pagenr);
3633 }
Jiri Slabyc62429d2006-12-08 02:39:14 -08003634 } else if (status & ST_PARITY)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003635 status = TTY_PARITY;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003636 else if (status & ST_FRAMING)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003637 status = TTY_FRAME;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003638 else if(status & ST_OVERRUN)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003639 status = TTY_OVERRUN;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003640 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003641 status = 0;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003642 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003643 status = 0;
Alan Cox33f0f882006-01-09 20:54:13 -08003644 tty_insert_flip_char(tty, ch, status);
3645 tty_schedule_flip(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003646 }
3647 } else {
3648 printk("STALLION: bad RX interrupt ack value=%x\n", ioack);
Alan Coxd18a7502008-10-13 10:40:07 +01003649 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003650 return;
3651 }
3652
3653stl_rxalldone:
Alan Coxd18a7502008-10-13 10:40:07 +01003654 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003655 outb((EOSRR + portp->uartaddr), ioaddr);
3656 outb(0, (ioaddr + EREG_DATA));
3657}
3658
3659/*****************************************************************************/
3660
3661/*
3662 * Modem interrupt handler. The is called when the modem signal line
3663 * (DCD) has changed state. Leave most of the work to the off-level
3664 * processing routine.
3665 */
3666
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003667static void stl_cd1400mdmisr(struct stlpanel *panelp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003668{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003669 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003670 unsigned int ioack;
3671 unsigned char misr;
3672
Jiri Slabya0564e12006-12-08 02:38:37 -08003673 pr_debug("stl_cd1400mdmisr(panelp=%p)\n", panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003674
3675 ioack = inb(ioaddr + EREG_MDACK);
3676 if (((ioack & panelp->ackmask) != 0) ||
3677 ((ioack & ACK_TYPMASK) != ACK_TYPMDM)) {
3678 printk("STALLION: bad MODEM interrupt ack value=%x\n", ioack);
3679 return;
3680 }
3681 portp = panelp->ports[(ioack >> 3)];
3682
3683 outb((MISR + portp->uartaddr), ioaddr);
3684 misr = inb(ioaddr + EREG_DATA);
3685 if (misr & MISR_DCD) {
Jiri Slabyccfea3c2008-02-07 00:16:39 -08003686 stl_cd_change(portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003687 portp->stats.modem++;
3688 }
3689
3690 outb((EOSRR + portp->uartaddr), ioaddr);
3691 outb(0, (ioaddr + EREG_DATA));
3692}
3693
3694/*****************************************************************************/
3695/* SC26198 HARDWARE FUNCTIONS */
3696/*****************************************************************************/
3697
3698/*
3699 * These functions get/set/update the registers of the sc26198 UARTs.
3700 * Access to the sc26198 registers is via an address/data io port pair.
3701 * (Maybe should make this inline...)
3702 */
3703
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003704static int stl_sc26198getreg(struct stlport *portp, int regnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003705{
3706 outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
Jesper Juhl014c2542006-01-15 02:37:08 +01003707 return inb(portp->ioaddr + XP_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003708}
3709
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003710static void stl_sc26198setreg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003711{
3712 outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
3713 outb(value, (portp->ioaddr + XP_DATA));
3714}
3715
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003716static int stl_sc26198updatereg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003717{
3718 outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
3719 if (inb(portp->ioaddr + XP_DATA) != value) {
3720 outb(value, (portp->ioaddr + XP_DATA));
Jesper Juhl014c2542006-01-15 02:37:08 +01003721 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003722 }
Jesper Juhl014c2542006-01-15 02:37:08 +01003723 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003724}
3725
3726/*****************************************************************************/
3727
3728/*
3729 * Functions to get and set the sc26198 global registers.
3730 */
3731
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003732static int stl_sc26198getglobreg(struct stlport *portp, int regnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003733{
3734 outb(regnr, (portp->ioaddr + XP_ADDR));
Jesper Juhl014c2542006-01-15 02:37:08 +01003735 return inb(portp->ioaddr + XP_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003736}
3737
3738#if 0
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003739static void stl_sc26198setglobreg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003740{
3741 outb(regnr, (portp->ioaddr + XP_ADDR));
3742 outb(value, (portp->ioaddr + XP_DATA));
3743}
3744#endif
3745
3746/*****************************************************************************/
3747
3748/*
3749 * Inbitialize the UARTs in a panel. We don't care what sort of board
3750 * these ports are on - since the port io registers are almost
3751 * identical when dealing with ports.
3752 */
3753
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003754static int stl_sc26198panelinit(struct stlbrd *brdp, struct stlpanel *panelp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003755{
3756 int chipmask, i;
3757 int nrchips, ioaddr;
3758
Jiri Slabya0564e12006-12-08 02:38:37 -08003759 pr_debug("stl_sc26198panelinit(brdp=%p,panelp=%p)\n", brdp, panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003760
3761 BRDENABLE(panelp->brdnr, panelp->pagenr);
3762
3763/*
3764 * Check that each chip is present and started up OK.
3765 */
3766 chipmask = 0;
3767 nrchips = (panelp->nrports + 4) / SC26198_PORTS;
3768 if (brdp->brdtype == BRD_ECHPCI)
3769 outb(panelp->pagenr, brdp->ioctrl);
3770
Jiri Slabyc62429d2006-12-08 02:39:14 -08003771 for (i = 0; i < nrchips; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003772 ioaddr = panelp->iobase + (i * 4);
3773 outb(SCCR, (ioaddr + XP_ADDR));
3774 outb(CR_RESETALL, (ioaddr + XP_DATA));
3775 outb(TSTR, (ioaddr + XP_ADDR));
3776 if (inb(ioaddr + XP_DATA) != 0) {
3777 printk("STALLION: sc26198 not responding, "
3778 "brd=%d panel=%d chip=%d\n",
3779 panelp->brdnr, panelp->panelnr, i);
3780 continue;
3781 }
3782 chipmask |= (0x1 << i);
3783 outb(GCCR, (ioaddr + XP_ADDR));
3784 outb(GCCR_IVRTYPCHANACK, (ioaddr + XP_DATA));
3785 outb(WDTRCR, (ioaddr + XP_ADDR));
3786 outb(0xff, (ioaddr + XP_DATA));
3787 }
3788
3789 BRDDISABLE(panelp->brdnr);
Jesper Juhl014c2542006-01-15 02:37:08 +01003790 return chipmask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003791}
3792
3793/*****************************************************************************/
3794
3795/*
3796 * Initialize hardware specific port registers.
3797 */
3798
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003799static void stl_sc26198portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003800{
Jiri Slabya0564e12006-12-08 02:38:37 -08003801 pr_debug("stl_sc26198portinit(brdp=%p,panelp=%p,portp=%p)\n", brdp,
3802 panelp, portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003803
Jiri Slaby615e4a72006-12-08 02:38:38 -08003804 if ((brdp == NULL) || (panelp == NULL) ||
3805 (portp == NULL))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003806 return;
3807
3808 portp->ioaddr = panelp->iobase + ((portp->portnr < 8) ? 0 : 4);
3809 portp->uartaddr = (portp->portnr & 0x07) << 4;
3810 portp->pagenr = panelp->pagenr;
3811 portp->hwid = 0x1;
3812
3813 BRDENABLE(portp->brdnr, portp->pagenr);
3814 stl_sc26198setreg(portp, IOPCR, IOPCR_SETSIGS);
3815 BRDDISABLE(portp->brdnr);
3816}
3817
3818/*****************************************************************************/
3819
3820/*
3821 * Set up the sc26198 registers for a port based on the termios port
3822 * settings.
3823 */
3824
Alan Cox606d0992006-12-08 02:38:45 -08003825static void stl_sc26198setport(struct stlport *portp, struct ktermios *tiosp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003826{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003827 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003828 unsigned long flags;
3829 unsigned int baudrate;
3830 unsigned char mr0, mr1, mr2, clk;
3831 unsigned char imron, imroff, iopr, ipr;
3832
3833 mr0 = 0;
3834 mr1 = 0;
3835 mr2 = 0;
3836 clk = 0;
3837 iopr = 0;
3838 imron = 0;
3839 imroff = 0;
3840
3841 brdp = stl_brds[portp->brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08003842 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003843 return;
3844
3845/*
3846 * Set up the RX char ignore mask with those RX error types we
3847 * can ignore.
3848 */
3849 portp->rxignoremsk = 0;
3850 if (tiosp->c_iflag & IGNPAR)
3851 portp->rxignoremsk |= (SR_RXPARITY | SR_RXFRAMING |
3852 SR_RXOVERRUN);
3853 if (tiosp->c_iflag & IGNBRK)
3854 portp->rxignoremsk |= SR_RXBREAK;
3855
3856 portp->rxmarkmsk = SR_RXOVERRUN;
3857 if (tiosp->c_iflag & (INPCK | PARMRK))
3858 portp->rxmarkmsk |= (SR_RXPARITY | SR_RXFRAMING);
3859 if (tiosp->c_iflag & BRKINT)
3860 portp->rxmarkmsk |= SR_RXBREAK;
3861
3862/*
3863 * Go through the char size, parity and stop bits and set all the
3864 * option register appropriately.
3865 */
3866 switch (tiosp->c_cflag & CSIZE) {
3867 case CS5:
3868 mr1 |= MR1_CS5;
3869 break;
3870 case CS6:
3871 mr1 |= MR1_CS6;
3872 break;
3873 case CS7:
3874 mr1 |= MR1_CS7;
3875 break;
3876 default:
3877 mr1 |= MR1_CS8;
3878 break;
3879 }
3880
3881 if (tiosp->c_cflag & CSTOPB)
3882 mr2 |= MR2_STOP2;
3883 else
3884 mr2 |= MR2_STOP1;
3885
3886 if (tiosp->c_cflag & PARENB) {
3887 if (tiosp->c_cflag & PARODD)
3888 mr1 |= (MR1_PARENB | MR1_PARODD);
3889 else
3890 mr1 |= (MR1_PARENB | MR1_PAREVEN);
Jiri Slabyc62429d2006-12-08 02:39:14 -08003891 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003892 mr1 |= MR1_PARNONE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003893
3894 mr1 |= MR1_ERRBLOCK;
3895
3896/*
3897 * Set the RX FIFO threshold at 8 chars. This gives a bit of breathing
3898 * space for hardware flow control and the like. This should be set to
3899 * VMIN.
3900 */
3901 mr2 |= MR2_RXFIFOHALF;
3902
3903/*
3904 * Calculate the baud rate timers. For now we will just assume that
3905 * the input and output baud are the same. The sc26198 has a fixed
3906 * baud rate table, so only discrete baud rates possible.
3907 */
3908 baudrate = tiosp->c_cflag & CBAUD;
3909 if (baudrate & CBAUDEX) {
3910 baudrate &= ~CBAUDEX;
3911 if ((baudrate < 1) || (baudrate > 4))
3912 tiosp->c_cflag &= ~CBAUDEX;
3913 else
3914 baudrate += 15;
3915 }
3916 baudrate = stl_baudrates[baudrate];
3917 if ((tiosp->c_cflag & CBAUD) == B38400) {
Alan Coxf8ae4762008-07-16 21:56:37 +01003918 if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003919 baudrate = 57600;
Alan Coxf8ae4762008-07-16 21:56:37 +01003920 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003921 baudrate = 115200;
Alan Coxf8ae4762008-07-16 21:56:37 +01003922 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003923 baudrate = 230400;
Alan Coxf8ae4762008-07-16 21:56:37 +01003924 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003925 baudrate = 460800;
Alan Coxf8ae4762008-07-16 21:56:37 +01003926 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003927 baudrate = (portp->baud_base / portp->custom_divisor);
3928 }
3929 if (baudrate > STL_SC26198MAXBAUD)
3930 baudrate = STL_SC26198MAXBAUD;
3931
Jiri Slabyc62429d2006-12-08 02:39:14 -08003932 if (baudrate > 0)
3933 for (clk = 0; clk < SC26198_NRBAUDS; clk++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003934 if (baudrate <= sc26198_baudtable[clk])
3935 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003936
3937/*
3938 * Check what form of modem signaling is required and set it up.
3939 */
3940 if (tiosp->c_cflag & CLOCAL) {
Alan Coxf8ae4762008-07-16 21:56:37 +01003941 portp->port.flags &= ~ASYNC_CHECK_CD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003942 } else {
3943 iopr |= IOPR_DCDCOS;
3944 imron |= IR_IOPORT;
Alan Coxf8ae4762008-07-16 21:56:37 +01003945 portp->port.flags |= ASYNC_CHECK_CD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003946 }
3947
3948/*
3949 * Setup sc26198 enhanced modes if we can. In particular we want to
3950 * handle as much of the flow control as possible automatically. As
3951 * well as saving a few CPU cycles it will also greatly improve flow
3952 * control reliability.
3953 */
3954 if (tiosp->c_iflag & IXON) {
3955 mr0 |= MR0_SWFTX | MR0_SWFT;
3956 imron |= IR_XONXOFF;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003957 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003958 imroff |= IR_XONXOFF;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003959
Linus Torvalds1da177e2005-04-16 15:20:36 -07003960 if (tiosp->c_iflag & IXOFF)
3961 mr0 |= MR0_SWFRX;
3962
3963 if (tiosp->c_cflag & CRTSCTS) {
3964 mr2 |= MR2_AUTOCTS;
3965 mr1 |= MR1_AUTORTS;
3966 }
3967
3968/*
3969 * All sc26198 register values calculated so go through and set
3970 * them all up.
3971 */
3972
Jiri Slabya0564e12006-12-08 02:38:37 -08003973 pr_debug("SETPORT: portnr=%d panelnr=%d brdnr=%d\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003974 portp->portnr, portp->panelnr, portp->brdnr);
Jiri Slabya0564e12006-12-08 02:38:37 -08003975 pr_debug(" mr0=%x mr1=%x mr2=%x clk=%x\n", mr0, mr1, mr2, clk);
3976 pr_debug(" iopr=%x imron=%x imroff=%x\n", iopr, imron, imroff);
3977 pr_debug(" schr1=%x schr2=%x schr3=%x schr4=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003978 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP],
3979 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003980
Alan Coxb65b5b52006-06-27 02:54:05 -07003981 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003982 BRDENABLE(portp->brdnr, portp->pagenr);
3983 stl_sc26198setreg(portp, IMR, 0);
3984 stl_sc26198updatereg(portp, MR0, mr0);
3985 stl_sc26198updatereg(portp, MR1, mr1);
3986 stl_sc26198setreg(portp, SCCR, CR_RXERRBLOCK);
3987 stl_sc26198updatereg(portp, MR2, mr2);
3988 stl_sc26198updatereg(portp, IOPIOR,
3989 ((stl_sc26198getreg(portp, IOPIOR) & ~IPR_CHANGEMASK) | iopr));
3990
3991 if (baudrate > 0) {
3992 stl_sc26198setreg(portp, TXCSR, clk);
3993 stl_sc26198setreg(portp, RXCSR, clk);
3994 }
3995
3996 stl_sc26198setreg(portp, XONCR, tiosp->c_cc[VSTART]);
3997 stl_sc26198setreg(portp, XOFFCR, tiosp->c_cc[VSTOP]);
3998
3999 ipr = stl_sc26198getreg(portp, IPR);
4000 if (ipr & IPR_DCD)
4001 portp->sigs &= ~TIOCM_CD;
4002 else
4003 portp->sigs |= TIOCM_CD;
4004
4005 portp->imr = (portp->imr & ~imroff) | imron;
4006 stl_sc26198setreg(portp, IMR, portp->imr);
4007 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004008 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004009}
4010
4011/*****************************************************************************/
4012
4013/*
4014 * Set the state of the DTR and RTS signals.
4015 */
4016
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004017static void stl_sc26198setsignals(struct stlport *portp, int dtr, int rts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004018{
4019 unsigned char iopioron, iopioroff;
4020 unsigned long flags;
4021
Jiri Slabya0564e12006-12-08 02:38:37 -08004022 pr_debug("stl_sc26198setsignals(portp=%p,dtr=%d,rts=%d)\n", portp,
4023 dtr, rts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004024
4025 iopioron = 0;
4026 iopioroff = 0;
4027 if (dtr == 0)
4028 iopioroff |= IPR_DTR;
4029 else if (dtr > 0)
4030 iopioron |= IPR_DTR;
4031 if (rts == 0)
4032 iopioroff |= IPR_RTS;
4033 else if (rts > 0)
4034 iopioron |= IPR_RTS;
4035
Alan Coxb65b5b52006-06-27 02:54:05 -07004036 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004037 BRDENABLE(portp->brdnr, portp->pagenr);
4038 stl_sc26198setreg(portp, IOPIOR,
4039 ((stl_sc26198getreg(portp, IOPIOR) & ~iopioroff) | iopioron));
4040 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004041 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004042}
4043
4044/*****************************************************************************/
4045
4046/*
4047 * Return the state of the signals.
4048 */
4049
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004050static int stl_sc26198getsignals(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004051{
4052 unsigned char ipr;
4053 unsigned long flags;
4054 int sigs;
4055
Jiri Slabya0564e12006-12-08 02:38:37 -08004056 pr_debug("stl_sc26198getsignals(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004057
Alan Coxb65b5b52006-06-27 02:54:05 -07004058 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004059 BRDENABLE(portp->brdnr, portp->pagenr);
4060 ipr = stl_sc26198getreg(portp, IPR);
4061 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004062 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004063
4064 sigs = 0;
4065 sigs |= (ipr & IPR_DCD) ? 0 : TIOCM_CD;
4066 sigs |= (ipr & IPR_CTS) ? 0 : TIOCM_CTS;
4067 sigs |= (ipr & IPR_DTR) ? 0: TIOCM_DTR;
4068 sigs |= (ipr & IPR_RTS) ? 0: TIOCM_RTS;
4069 sigs |= TIOCM_DSR;
Jesper Juhl014c2542006-01-15 02:37:08 +01004070 return sigs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004071}
4072
4073/*****************************************************************************/
4074
4075/*
4076 * Enable/Disable the Transmitter and/or Receiver.
4077 */
4078
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004079static void stl_sc26198enablerxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004080{
4081 unsigned char ccr;
4082 unsigned long flags;
4083
Jiri Slabya0564e12006-12-08 02:38:37 -08004084 pr_debug("stl_sc26198enablerxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx,tx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004085
4086 ccr = portp->crenable;
4087 if (tx == 0)
4088 ccr &= ~CR_TXENABLE;
4089 else if (tx > 0)
4090 ccr |= CR_TXENABLE;
4091 if (rx == 0)
4092 ccr &= ~CR_RXENABLE;
4093 else if (rx > 0)
4094 ccr |= CR_RXENABLE;
4095
Alan Coxb65b5b52006-06-27 02:54:05 -07004096 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004097 BRDENABLE(portp->brdnr, portp->pagenr);
4098 stl_sc26198setreg(portp, SCCR, ccr);
4099 BRDDISABLE(portp->brdnr);
4100 portp->crenable = ccr;
Alan Coxb65b5b52006-06-27 02:54:05 -07004101 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004102}
4103
4104/*****************************************************************************/
4105
4106/*
4107 * Start/stop the Transmitter and/or Receiver.
4108 */
4109
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004110static void stl_sc26198startrxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004111{
4112 unsigned char imr;
4113 unsigned long flags;
4114
Jiri Slabya0564e12006-12-08 02:38:37 -08004115 pr_debug("stl_sc26198startrxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004116
4117 imr = portp->imr;
4118 if (tx == 0)
4119 imr &= ~IR_TXRDY;
4120 else if (tx == 1)
4121 imr |= IR_TXRDY;
4122 if (rx == 0)
4123 imr &= ~(IR_RXRDY | IR_RXBREAK | IR_RXWATCHDOG);
4124 else if (rx > 0)
4125 imr |= IR_RXRDY | IR_RXBREAK | IR_RXWATCHDOG;
4126
Alan Coxb65b5b52006-06-27 02:54:05 -07004127 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004128 BRDENABLE(portp->brdnr, portp->pagenr);
4129 stl_sc26198setreg(portp, IMR, imr);
4130 BRDDISABLE(portp->brdnr);
4131 portp->imr = imr;
4132 if (tx > 0)
4133 set_bit(ASYI_TXBUSY, &portp->istate);
Alan Coxb65b5b52006-06-27 02:54:05 -07004134 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004135}
4136
4137/*****************************************************************************/
4138
4139/*
4140 * Disable all interrupts from this port.
4141 */
4142
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004143static void stl_sc26198disableintrs(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004144{
4145 unsigned long flags;
4146
Jiri Slabya0564e12006-12-08 02:38:37 -08004147 pr_debug("stl_sc26198disableintrs(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004148
Alan Coxb65b5b52006-06-27 02:54:05 -07004149 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004150 BRDENABLE(portp->brdnr, portp->pagenr);
4151 portp->imr = 0;
4152 stl_sc26198setreg(portp, IMR, 0);
4153 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004154 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004155}
4156
4157/*****************************************************************************/
4158
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004159static void stl_sc26198sendbreak(struct stlport *portp, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004160{
4161 unsigned long flags;
4162
Jiri Slabya0564e12006-12-08 02:38:37 -08004163 pr_debug("stl_sc26198sendbreak(portp=%p,len=%d)\n", portp, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004164
Alan Coxb65b5b52006-06-27 02:54:05 -07004165 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004166 BRDENABLE(portp->brdnr, portp->pagenr);
4167 if (len == 1) {
4168 stl_sc26198setreg(portp, SCCR, CR_TXSTARTBREAK);
4169 portp->stats.txbreaks++;
Jiri Slabyc62429d2006-12-08 02:39:14 -08004170 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07004171 stl_sc26198setreg(portp, SCCR, CR_TXSTOPBREAK);
Jiri Slabyc62429d2006-12-08 02:39:14 -08004172
Linus Torvalds1da177e2005-04-16 15:20:36 -07004173 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004174 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004175}
4176
4177/*****************************************************************************/
4178
4179/*
4180 * Take flow control actions...
4181 */
4182
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004183static void stl_sc26198flowctrl(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004184{
4185 struct tty_struct *tty;
4186 unsigned long flags;
4187 unsigned char mr0;
4188
Jiri Slabya0564e12006-12-08 02:38:37 -08004189 pr_debug("stl_sc26198flowctrl(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004190
Jiri Slaby615e4a72006-12-08 02:38:38 -08004191 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004192 return;
Alan Coxd18a7502008-10-13 10:40:07 +01004193 tty = tty_port_tty_get(&portp->port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08004194 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004195 return;
4196
Alan Coxb65b5b52006-06-27 02:54:05 -07004197 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004198 BRDENABLE(portp->brdnr, portp->pagenr);
4199
4200 if (state) {
4201 if (tty->termios->c_iflag & IXOFF) {
4202 mr0 = stl_sc26198getreg(portp, MR0);
4203 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4204 stl_sc26198setreg(portp, SCCR, CR_TXSENDXON);
4205 mr0 |= MR0_SWFRX;
4206 portp->stats.rxxon++;
4207 stl_sc26198wait(portp);
4208 stl_sc26198setreg(portp, MR0, mr0);
4209 }
4210/*
4211 * Question: should we return RTS to what it was before? It may
4212 * have been set by an ioctl... Suppose not, since if you have
4213 * hardware flow control set then it is pretty silly to go and
4214 * set the RTS line by hand.
4215 */
4216 if (tty->termios->c_cflag & CRTSCTS) {
4217 stl_sc26198setreg(portp, MR1,
4218 (stl_sc26198getreg(portp, MR1) | MR1_AUTORTS));
4219 stl_sc26198setreg(portp, IOPIOR,
4220 (stl_sc26198getreg(portp, IOPIOR) | IOPR_RTS));
4221 portp->stats.rxrtson++;
4222 }
4223 } else {
4224 if (tty->termios->c_iflag & IXOFF) {
4225 mr0 = stl_sc26198getreg(portp, MR0);
4226 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4227 stl_sc26198setreg(portp, SCCR, CR_TXSENDXOFF);
4228 mr0 &= ~MR0_SWFRX;
4229 portp->stats.rxxoff++;
4230 stl_sc26198wait(portp);
4231 stl_sc26198setreg(portp, MR0, mr0);
4232 }
4233 if (tty->termios->c_cflag & CRTSCTS) {
4234 stl_sc26198setreg(portp, MR1,
4235 (stl_sc26198getreg(portp, MR1) & ~MR1_AUTORTS));
4236 stl_sc26198setreg(portp, IOPIOR,
4237 (stl_sc26198getreg(portp, IOPIOR) & ~IOPR_RTS));
4238 portp->stats.rxrtsoff++;
4239 }
4240 }
4241
4242 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004243 spin_unlock_irqrestore(&brd_lock, flags);
Alan Coxd18a7502008-10-13 10:40:07 +01004244 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004245}
4246
4247/*****************************************************************************/
4248
4249/*
4250 * Send a flow control character.
4251 */
4252
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004253static void stl_sc26198sendflow(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004254{
4255 struct tty_struct *tty;
4256 unsigned long flags;
4257 unsigned char mr0;
4258
Jiri Slabya0564e12006-12-08 02:38:37 -08004259 pr_debug("stl_sc26198sendflow(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004260
Jiri Slaby615e4a72006-12-08 02:38:38 -08004261 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004262 return;
Alan Coxd18a7502008-10-13 10:40:07 +01004263 tty = tty_port_tty_get(&portp->port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08004264 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004265 return;
4266
Alan Coxb65b5b52006-06-27 02:54:05 -07004267 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004268 BRDENABLE(portp->brdnr, portp->pagenr);
4269 if (state) {
4270 mr0 = stl_sc26198getreg(portp, MR0);
4271 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4272 stl_sc26198setreg(portp, SCCR, CR_TXSENDXON);
4273 mr0 |= MR0_SWFRX;
4274 portp->stats.rxxon++;
4275 stl_sc26198wait(portp);
4276 stl_sc26198setreg(portp, MR0, mr0);
4277 } else {
4278 mr0 = stl_sc26198getreg(portp, MR0);
4279 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4280 stl_sc26198setreg(portp, SCCR, CR_TXSENDXOFF);
4281 mr0 &= ~MR0_SWFRX;
4282 portp->stats.rxxoff++;
4283 stl_sc26198wait(portp);
4284 stl_sc26198setreg(portp, MR0, mr0);
4285 }
4286 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004287 spin_unlock_irqrestore(&brd_lock, flags);
Alan Coxd18a7502008-10-13 10:40:07 +01004288 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004289}
4290
4291/*****************************************************************************/
4292
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004293static void stl_sc26198flush(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004294{
4295 unsigned long flags;
4296
Jiri Slabya0564e12006-12-08 02:38:37 -08004297 pr_debug("stl_sc26198flush(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004298
Jiri Slaby615e4a72006-12-08 02:38:38 -08004299 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004300 return;
4301
Alan Coxb65b5b52006-06-27 02:54:05 -07004302 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004303 BRDENABLE(portp->brdnr, portp->pagenr);
4304 stl_sc26198setreg(portp, SCCR, CR_TXRESET);
4305 stl_sc26198setreg(portp, SCCR, portp->crenable);
4306 BRDDISABLE(portp->brdnr);
4307 portp->tx.tail = portp->tx.head;
Alan Coxb65b5b52006-06-27 02:54:05 -07004308 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004309}
4310
4311/*****************************************************************************/
4312
4313/*
4314 * Return the current state of data flow on this port. This is only
4315 * really interresting when determining if data has fully completed
4316 * transmission or not... The sc26198 interrupt scheme cannot
4317 * determine when all data has actually drained, so we need to
4318 * check the port statusy register to be sure.
4319 */
4320
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004321static int stl_sc26198datastate(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004322{
4323 unsigned long flags;
4324 unsigned char sr;
4325
Jiri Slabya0564e12006-12-08 02:38:37 -08004326 pr_debug("stl_sc26198datastate(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004327
Jiri Slaby615e4a72006-12-08 02:38:38 -08004328 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01004329 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004330 if (test_bit(ASYI_TXBUSY, &portp->istate))
Jesper Juhl014c2542006-01-15 02:37:08 +01004331 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004332
Alan Coxb65b5b52006-06-27 02:54:05 -07004333 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004334 BRDENABLE(portp->brdnr, portp->pagenr);
4335 sr = stl_sc26198getreg(portp, SR);
4336 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004337 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004338
Jesper Juhl014c2542006-01-15 02:37:08 +01004339 return (sr & SR_TXEMPTY) ? 0 : 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004340}
4341
4342/*****************************************************************************/
4343
4344/*
4345 * Delay for a small amount of time, to give the sc26198 a chance
4346 * to process a command...
4347 */
4348
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004349static void stl_sc26198wait(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004350{
4351 int i;
4352
Jiri Slabya0564e12006-12-08 02:38:37 -08004353 pr_debug("stl_sc26198wait(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004354
Jiri Slaby615e4a72006-12-08 02:38:38 -08004355 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004356 return;
4357
Jiri Slabyc62429d2006-12-08 02:39:14 -08004358 for (i = 0; i < 20; i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004359 stl_sc26198getglobreg(portp, TSTR);
4360}
4361
4362/*****************************************************************************/
4363
4364/*
4365 * If we are TX flow controlled and in IXANY mode then we may
4366 * need to unflow control here. We gotta do this because of the
4367 * automatic flow control modes of the sc26198.
4368 */
4369
Jiri Slaby60be4812006-12-08 02:38:40 -08004370static void stl_sc26198txunflow(struct stlport *portp, struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004371{
4372 unsigned char mr0;
4373
4374 mr0 = stl_sc26198getreg(portp, MR0);
4375 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4376 stl_sc26198setreg(portp, SCCR, CR_HOSTXON);
4377 stl_sc26198wait(portp);
4378 stl_sc26198setreg(portp, MR0, mr0);
4379 clear_bit(ASYI_TXFLOWED, &portp->istate);
4380}
4381
4382/*****************************************************************************/
4383
4384/*
4385 * Interrupt service routine for sc26198 panels.
4386 */
4387
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004388static void stl_sc26198intr(struct stlpanel *panelp, unsigned int iobase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004389{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004390 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004391 unsigned int iack;
4392
Alan Coxb65b5b52006-06-27 02:54:05 -07004393 spin_lock(&brd_lock);
4394
Linus Torvalds1da177e2005-04-16 15:20:36 -07004395/*
4396 * Work around bug in sc26198 chip... Cannot have A6 address
4397 * line of UART high, else iack will be returned as 0.
4398 */
4399 outb(0, (iobase + 1));
4400
4401 iack = inb(iobase + XP_IACK);
4402 portp = panelp->ports[(iack & IVR_CHANMASK) + ((iobase & 0x4) << 1)];
4403
4404 if (iack & IVR_RXDATA)
4405 stl_sc26198rxisr(portp, iack);
4406 else if (iack & IVR_TXDATA)
4407 stl_sc26198txisr(portp);
4408 else
4409 stl_sc26198otherisr(portp, iack);
Alan Coxb65b5b52006-06-27 02:54:05 -07004410
4411 spin_unlock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004412}
4413
4414/*****************************************************************************/
4415
4416/*
4417 * Transmit interrupt handler. This has gotta be fast! Handling TX
4418 * chars is pretty simple, stuff as many as possible from the TX buffer
4419 * into the sc26198 FIFO.
4420 * In practice it is possible that interrupts are enabled but that the
4421 * port has been hung up. Need to handle not having any TX buffer here,
4422 * this is done by using the side effect that head and tail will also
4423 * be NULL if the buffer has been freed.
4424 */
4425
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004426static void stl_sc26198txisr(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004427{
Alan Coxd18a7502008-10-13 10:40:07 +01004428 struct tty_struct *tty;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004429 unsigned int ioaddr;
4430 unsigned char mr0;
4431 int len, stlen;
4432 char *head, *tail;
4433
Jiri Slabya0564e12006-12-08 02:38:37 -08004434 pr_debug("stl_sc26198txisr(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004435
4436 ioaddr = portp->ioaddr;
4437 head = portp->tx.head;
4438 tail = portp->tx.tail;
4439 len = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
4440 if ((len == 0) || ((len < STL_TXBUFLOW) &&
4441 (test_bit(ASYI_TXLOW, &portp->istate) == 0))) {
4442 set_bit(ASYI_TXLOW, &portp->istate);
Alan Coxd18a7502008-10-13 10:40:07 +01004443 tty = tty_port_tty_get(&portp->port);
4444 if (tty) {
4445 tty_wakeup(tty);
4446 tty_kref_put(tty);
4447 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004448 }
4449
4450 if (len == 0) {
4451 outb((MR0 | portp->uartaddr), (ioaddr + XP_ADDR));
4452 mr0 = inb(ioaddr + XP_DATA);
4453 if ((mr0 & MR0_TXMASK) == MR0_TXEMPTY) {
4454 portp->imr &= ~IR_TXRDY;
4455 outb((IMR | portp->uartaddr), (ioaddr + XP_ADDR));
4456 outb(portp->imr, (ioaddr + XP_DATA));
4457 clear_bit(ASYI_TXBUSY, &portp->istate);
4458 } else {
4459 mr0 |= ((mr0 & ~MR0_TXMASK) | MR0_TXEMPTY);
4460 outb(mr0, (ioaddr + XP_DATA));
4461 }
4462 } else {
Jiri Slaby843b5682006-12-08 02:39:12 -08004463 len = min(len, SC26198_TXFIFOSIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004464 portp->stats.txtotal += len;
Jiri Slaby319fe7c2008-02-07 00:16:36 -08004465 stlen = min_t(unsigned int, len,
4466 (portp->tx.buf + STL_TXBUFSIZE) - tail);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004467 outb(GTXFIFO, (ioaddr + XP_ADDR));
4468 outsb((ioaddr + XP_DATA), tail, stlen);
4469 len -= stlen;
4470 tail += stlen;
4471 if (tail >= (portp->tx.buf + STL_TXBUFSIZE))
4472 tail = portp->tx.buf;
4473 if (len > 0) {
4474 outsb((ioaddr + XP_DATA), tail, len);
4475 tail += len;
4476 }
4477 portp->tx.tail = tail;
4478 }
4479}
4480
4481/*****************************************************************************/
4482
4483/*
4484 * Receive character interrupt handler. Determine if we have good chars
4485 * or bad chars and then process appropriately. Good chars are easy
4486 * just shove the lot into the RX buffer and set all status byte to 0.
4487 * If a bad RX char then process as required. This routine needs to be
4488 * fast! In practice it is possible that we get an interrupt on a port
4489 * that is closed. This can happen on hangups - since they completely
4490 * shutdown a port not in user context. Need to handle this case.
4491 */
4492
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004493static void stl_sc26198rxisr(struct stlport *portp, unsigned int iack)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004494{
4495 struct tty_struct *tty;
4496 unsigned int len, buflen, ioaddr;
4497
Jiri Slabya0564e12006-12-08 02:38:37 -08004498 pr_debug("stl_sc26198rxisr(portp=%p,iack=%x)\n", portp, iack);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004499
Alan Coxd18a7502008-10-13 10:40:07 +01004500 tty = tty_port_tty_get(&portp->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004501 ioaddr = portp->ioaddr;
4502 outb(GIBCR, (ioaddr + XP_ADDR));
4503 len = inb(ioaddr + XP_DATA) + 1;
4504
4505 if ((iack & IVR_TYPEMASK) == IVR_RXDATA) {
Alan Cox33f0f882006-01-09 20:54:13 -08004506 if (tty == NULL || (buflen = tty_buffer_request_room(tty, len)) == 0) {
Jiri Slaby319fe7c2008-02-07 00:16:36 -08004507 len = min_t(unsigned int, len, sizeof(stl_unwanted));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004508 outb(GRXFIFO, (ioaddr + XP_ADDR));
4509 insb((ioaddr + XP_DATA), &stl_unwanted[0], len);
4510 portp->stats.rxlost += len;
4511 portp->stats.rxtotal += len;
4512 } else {
Jiri Slaby843b5682006-12-08 02:39:12 -08004513 len = min(len, buflen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004514 if (len > 0) {
Alan Cox33f0f882006-01-09 20:54:13 -08004515 unsigned char *ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004516 outb(GRXFIFO, (ioaddr + XP_ADDR));
Alan Cox33f0f882006-01-09 20:54:13 -08004517 tty_prepare_flip_string(tty, &ptr, len);
4518 insb((ioaddr + XP_DATA), ptr, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004519 tty_schedule_flip(tty);
4520 portp->stats.rxtotal += len;
4521 }
4522 }
4523 } else {
4524 stl_sc26198rxbadchars(portp);
4525 }
4526
4527/*
4528 * If we are TX flow controlled and in IXANY mode then we may need
4529 * to unflow control here. We gotta do this because of the automatic
4530 * flow control modes of the sc26198.
4531 */
4532 if (test_bit(ASYI_TXFLOWED, &portp->istate)) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08004533 if ((tty != NULL) &&
4534 (tty->termios != NULL) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07004535 (tty->termios->c_iflag & IXANY)) {
4536 stl_sc26198txunflow(portp, tty);
4537 }
4538 }
Alan Coxd18a7502008-10-13 10:40:07 +01004539 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004540}
4541
4542/*****************************************************************************/
4543
4544/*
4545 * Process an RX bad character.
4546 */
4547
Jiri Slaby60be4812006-12-08 02:38:40 -08004548static void stl_sc26198rxbadch(struct stlport *portp, unsigned char status, char ch)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004549{
4550 struct tty_struct *tty;
4551 unsigned int ioaddr;
4552
Alan Coxd18a7502008-10-13 10:40:07 +01004553 tty = tty_port_tty_get(&portp->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004554 ioaddr = portp->ioaddr;
4555
4556 if (status & SR_RXPARITY)
4557 portp->stats.rxparity++;
4558 if (status & SR_RXFRAMING)
4559 portp->stats.rxframing++;
4560 if (status & SR_RXOVERRUN)
4561 portp->stats.rxoverrun++;
4562 if (status & SR_RXBREAK)
4563 portp->stats.rxbreaks++;
4564
Jiri Slaby615e4a72006-12-08 02:38:38 -08004565 if ((tty != NULL) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07004566 ((portp->rxignoremsk & status) == 0)) {
4567 if (portp->rxmarkmsk & status) {
4568 if (status & SR_RXBREAK) {
4569 status = TTY_BREAK;
Alan Coxf8ae4762008-07-16 21:56:37 +01004570 if (portp->port.flags & ASYNC_SAK) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004571 do_SAK(tty);
4572 BRDENABLE(portp->brdnr, portp->pagenr);
4573 }
Jiri Slabyc62429d2006-12-08 02:39:14 -08004574 } else if (status & SR_RXPARITY)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004575 status = TTY_PARITY;
Jiri Slabyc62429d2006-12-08 02:39:14 -08004576 else if (status & SR_RXFRAMING)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004577 status = TTY_FRAME;
Jiri Slabyc62429d2006-12-08 02:39:14 -08004578 else if(status & SR_RXOVERRUN)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004579 status = TTY_OVERRUN;
Jiri Slabyc62429d2006-12-08 02:39:14 -08004580 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07004581 status = 0;
Jiri Slabyc62429d2006-12-08 02:39:14 -08004582 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07004583 status = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004584
Alan Cox33f0f882006-01-09 20:54:13 -08004585 tty_insert_flip_char(tty, ch, status);
4586 tty_schedule_flip(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004587
4588 if (status == 0)
4589 portp->stats.rxtotal++;
4590 }
Alan Coxd18a7502008-10-13 10:40:07 +01004591 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004592}
4593
4594/*****************************************************************************/
4595
4596/*
4597 * Process all characters in the RX FIFO of the UART. Check all char
4598 * status bytes as well, and process as required. We need to check
4599 * all bytes in the FIFO, in case some more enter the FIFO while we
4600 * are here. To get the exact character error type we need to switch
4601 * into CHAR error mode (that is why we need to make sure we empty
4602 * the FIFO).
4603 */
4604
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004605static void stl_sc26198rxbadchars(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004606{
4607 unsigned char status, mr1;
4608 char ch;
4609
4610/*
4611 * To get the precise error type for each character we must switch
4612 * back into CHAR error mode.
4613 */
4614 mr1 = stl_sc26198getreg(portp, MR1);
4615 stl_sc26198setreg(portp, MR1, (mr1 & ~MR1_ERRBLOCK));
4616
4617 while ((status = stl_sc26198getreg(portp, SR)) & SR_RXRDY) {
4618 stl_sc26198setreg(portp, SCCR, CR_CLEARRXERR);
4619 ch = stl_sc26198getreg(portp, RXFIFO);
4620 stl_sc26198rxbadch(portp, status, ch);
4621 }
4622
4623/*
4624 * To get correct interrupt class we must switch back into BLOCK
4625 * error mode.
4626 */
4627 stl_sc26198setreg(portp, MR1, mr1);
4628}
4629
4630/*****************************************************************************/
4631
4632/*
4633 * Other interrupt handler. This includes modem signals, flow
4634 * control actions, etc. Most stuff is left to off-level interrupt
4635 * processing time.
4636 */
4637
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004638static void stl_sc26198otherisr(struct stlport *portp, unsigned int iack)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004639{
4640 unsigned char cir, ipr, xisr;
4641
Jiri Slabya0564e12006-12-08 02:38:37 -08004642 pr_debug("stl_sc26198otherisr(portp=%p,iack=%x)\n", portp, iack);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004643
4644 cir = stl_sc26198getglobreg(portp, CIR);
4645
4646 switch (cir & CIR_SUBTYPEMASK) {
4647 case CIR_SUBCOS:
4648 ipr = stl_sc26198getreg(portp, IPR);
4649 if (ipr & IPR_DCDCHANGE) {
Jiri Slabyccfea3c2008-02-07 00:16:39 -08004650 stl_cd_change(portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004651 portp->stats.modem++;
4652 }
4653 break;
4654 case CIR_SUBXONXOFF:
4655 xisr = stl_sc26198getreg(portp, XISR);
4656 if (xisr & XISR_RXXONGOT) {
4657 set_bit(ASYI_TXFLOWED, &portp->istate);
4658 portp->stats.txxoff++;
4659 }
4660 if (xisr & XISR_RXXOFFGOT) {
4661 clear_bit(ASYI_TXFLOWED, &portp->istate);
4662 portp->stats.txxon++;
4663 }
4664 break;
4665 case CIR_SUBBREAK:
4666 stl_sc26198setreg(portp, SCCR, CR_BREAKRESET);
4667 stl_sc26198rxbadchars(portp);
4668 break;
4669 default:
4670 break;
4671 }
4672}
4673
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004674static void stl_free_isabrds(void)
4675{
4676 struct stlbrd *brdp;
4677 unsigned int i;
4678
4679 for (i = 0; i < stl_nrbrds; i++) {
4680 if ((brdp = stl_brds[i]) == NULL || (brdp->state & STL_PROBED))
4681 continue;
4682
4683 free_irq(brdp->irq, brdp);
4684
4685 stl_cleanup_panels(brdp);
4686
4687 release_region(brdp->ioaddr1, brdp->iosize1);
4688 if (brdp->iosize2 > 0)
4689 release_region(brdp->ioaddr2, brdp->iosize2);
4690
4691 kfree(brdp);
4692 stl_brds[i] = NULL;
4693 }
4694}
4695
Jiri Slaby23b85a12006-12-08 02:38:40 -08004696/*
4697 * Loadable module initialization stuff.
4698 */
4699static int __init stallion_module_init(void)
4700{
Jiri Slaby843b5682006-12-08 02:39:12 -08004701 struct stlbrd *brdp;
4702 struct stlconf conf;
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08004703 unsigned int i, j;
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004704 int retval;
Jiri Slaby23b85a12006-12-08 02:38:40 -08004705
4706 printk(KERN_INFO "%s: version %s\n", stl_drvtitle, stl_drvversion);
4707
4708 spin_lock_init(&stallion_lock);
4709 spin_lock_init(&brd_lock);
4710
Jiri Slabye4151092007-06-08 13:46:52 -07004711 stl_serial = alloc_tty_driver(STL_MAXBRDS * STL_MAXPORTS);
4712 if (!stl_serial) {
4713 retval = -ENOMEM;
4714 goto err;
4715 }
4716
4717 stl_serial->owner = THIS_MODULE;
4718 stl_serial->driver_name = stl_drvname;
4719 stl_serial->name = "ttyE";
4720 stl_serial->major = STL_SERIALMAJOR;
4721 stl_serial->minor_start = 0;
4722 stl_serial->type = TTY_DRIVER_TYPE_SERIAL;
4723 stl_serial->subtype = SERIAL_TYPE_NORMAL;
4724 stl_serial->init_termios = stl_deftermios;
4725 stl_serial->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
4726 tty_set_operations(stl_serial, &stl_ops);
4727
4728 retval = tty_register_driver(stl_serial);
4729 if (retval) {
4730 printk("STALLION: failed to register serial driver\n");
4731 goto err_frtty;
4732 }
4733
Jiri Slaby843b5682006-12-08 02:39:12 -08004734/*
4735 * Find any dynamically supported boards. That is via module load
4736 * line options.
4737 */
4738 for (i = stl_nrbrds; i < stl_nargs; i++) {
4739 memset(&conf, 0, sizeof(conf));
4740 if (stl_parsebrd(&conf, stl_brdsp[i]) == 0)
4741 continue;
4742 if ((brdp = stl_allocbrd()) == NULL)
4743 continue;
4744 brdp->brdnr = i;
4745 brdp->brdtype = conf.brdtype;
4746 brdp->ioaddr1 = conf.ioaddr1;
4747 brdp->ioaddr2 = conf.ioaddr2;
4748 brdp->irq = conf.irq;
4749 brdp->irqtype = conf.irqtype;
Ingo Korbb08b5ad2007-06-23 17:16:35 -07004750 stl_brds[brdp->brdnr] = brdp;
4751 if (stl_brdinit(brdp)) {
4752 stl_brds[brdp->brdnr] = NULL;
Jiri Slaby843b5682006-12-08 02:39:12 -08004753 kfree(brdp);
Ingo Korbb08b5ad2007-06-23 17:16:35 -07004754 } else {
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08004755 for (j = 0; j < brdp->nrports; j++)
4756 tty_register_device(stl_serial,
4757 brdp->brdnr * STL_MAXPORTS + j, NULL);
Jiri Slaby843b5682006-12-08 02:39:12 -08004758 stl_nrbrds = i + 1;
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08004759 }
Jiri Slaby843b5682006-12-08 02:39:12 -08004760 }
Jiri Slaby23b85a12006-12-08 02:38:40 -08004761
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08004762 /* this has to be _after_ isa finding because of locking */
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08004763 retval = pci_register_driver(&stl_pcidriver);
Jiri Slabye4151092007-06-08 13:46:52 -07004764 if (retval && stl_nrbrds == 0) {
4765 printk(KERN_ERR "STALLION: can't register pci driver\n");
4766 goto err_unrtty;
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004767 }
Jiri Slaby23b85a12006-12-08 02:38:40 -08004768
4769/*
4770 * Set up a character driver for per board stuff. This is mainly used
4771 * to do stats ioctls on the ports.
4772 */
4773 if (register_chrdev(STL_SIOMEMMAJOR, "staliomem", &stl_fsiomem))
4774 printk("STALLION: failed to register serial board device\n");
4775
4776 stallion_class = class_create(THIS_MODULE, "staliomem");
Jiri Slabye4151092007-06-08 13:46:52 -07004777 if (IS_ERR(stallion_class))
4778 printk("STALLION: failed to create class\n");
Jiri Slaby23b85a12006-12-08 02:38:40 -08004779 for (i = 0; i < 4; i++)
Greg Kroah-Hartman47aa5792008-05-21 12:52:33 -07004780 device_create_drvdata(stallion_class, NULL, MKDEV(STL_SIOMEMMAJOR, i),
4781 NULL, "staliomem%d", i);
Jiri Slaby23b85a12006-12-08 02:38:40 -08004782
Jiri Slaby23b85a12006-12-08 02:38:40 -08004783 return 0;
Jiri Slabye4151092007-06-08 13:46:52 -07004784err_unrtty:
4785 tty_unregister_driver(stl_serial);
4786err_frtty:
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004787 put_tty_driver(stl_serial);
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08004788err:
4789 return retval;
Jiri Slaby23b85a12006-12-08 02:38:40 -08004790}
4791
4792static void __exit stallion_module_exit(void)
4793{
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08004794 struct stlbrd *brdp;
4795 unsigned int i, j;
Jiri Slaby23b85a12006-12-08 02:38:40 -08004796
4797 pr_debug("cleanup_module()\n");
4798
4799 printk(KERN_INFO "Unloading %s: version %s\n", stl_drvtitle,
4800 stl_drvversion);
4801
4802/*
4803 * Free up all allocated resources used by the ports. This includes
4804 * memory and interrupts. As part of this process we will also do
4805 * a hangup on every open port - to try to flush out any processes
4806 * hanging onto ports.
4807 */
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08004808 for (i = 0; i < stl_nrbrds; i++) {
4809 if ((brdp = stl_brds[i]) == NULL || (brdp->state & STL_PROBED))
4810 continue;
4811 for (j = 0; j < brdp->nrports; j++)
4812 tty_unregister_device(stl_serial,
4813 brdp->brdnr * STL_MAXPORTS + j);
4814 }
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004815
Jiri Slaby23b85a12006-12-08 02:38:40 -08004816 for (i = 0; i < 4; i++)
tonyj@suse.de07c015e2007-08-07 22:28:44 -07004817 device_destroy(stallion_class, MKDEV(STL_SIOMEMMAJOR, i));
Akinobu Mita68fc4fa2007-07-19 01:47:50 -07004818 unregister_chrdev(STL_SIOMEMMAJOR, "staliomem");
Jiri Slaby23b85a12006-12-08 02:38:40 -08004819 class_destroy(stallion_class);
4820
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08004821 pci_unregister_driver(&stl_pcidriver);
4822
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004823 stl_free_isabrds();
Jiri Slabye4151092007-06-08 13:46:52 -07004824
4825 tty_unregister_driver(stl_serial);
4826 put_tty_driver(stl_serial);
Jiri Slaby23b85a12006-12-08 02:38:40 -08004827}
4828
4829module_init(stallion_module_init);
4830module_exit(stallion_module_exit);
4831
4832MODULE_AUTHOR("Greg Ungerer");
4833MODULE_DESCRIPTION("Stallion Multiport Serial Driver");
4834MODULE_LICENSE("GPL");