blob: 963b03fb29e5583aa45e83f056c6cf1ff412ba43 [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
Jiri Slaby96b066b2006-12-08 02:38:42 -0800852 portp = tty->driver_data;
853 if (portp == NULL)
854 return;
855
856 stl_flush(portp);
857 tty_wakeup(tty);
858}
859
860/*****************************************************************************/
861
862static void stl_waituntilsent(struct tty_struct *tty, int timeout)
863{
864 struct stlport *portp;
865 unsigned long tend;
866
867 pr_debug("stl_waituntilsent(tty=%p,timeout=%d)\n", tty, timeout);
868
Jiri Slaby96b066b2006-12-08 02:38:42 -0800869 portp = tty->driver_data;
870 if (portp == NULL)
871 return;
872
873 if (timeout == 0)
874 timeout = HZ;
875 tend = jiffies + timeout;
876
Alan Cox978e5952008-04-30 00:53:59 -0700877 lock_kernel();
Jiri Slaby96b066b2006-12-08 02:38:42 -0800878 while (stl_datastate(portp)) {
879 if (signal_pending(current))
880 break;
881 msleep_interruptible(20);
882 if (time_after_eq(jiffies, tend))
883 break;
884 }
Alan Cox978e5952008-04-30 00:53:59 -0700885 unlock_kernel();
Jiri Slaby96b066b2006-12-08 02:38:42 -0800886}
887
888/*****************************************************************************/
889
Linus Torvalds1da177e2005-04-16 15:20:36 -0700890static void stl_close(struct tty_struct *tty, struct file *filp)
891{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800892 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700893 unsigned long flags;
894
Jiri Slabya0564e12006-12-08 02:38:37 -0800895 pr_debug("stl_close(tty=%p,filp=%p)\n", tty, filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700896
897 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800898 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700899 return;
900
Alan Coxb65b5b52006-06-27 02:54:05 -0700901 spin_lock_irqsave(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700902 if (tty_hung_up_p(filp)) {
Alan Coxb65b5b52006-06-27 02:54:05 -0700903 spin_unlock_irqrestore(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700904 return;
905 }
Alan Coxf8ae4762008-07-16 21:56:37 +0100906 if ((tty->count == 1) && (portp->port.count != 1))
907 portp->port.count = 1;
908 if (portp->port.count-- > 1) {
Alan Coxb65b5b52006-06-27 02:54:05 -0700909 spin_unlock_irqrestore(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700910 return;
911 }
912
Alan Coxf8ae4762008-07-16 21:56:37 +0100913 portp->port.count = 0;
914 portp->port.flags |= ASYNC_CLOSING;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700915
916/*
917 * May want to wait for any data to drain before closing. The BUSY
918 * flag keeps track of whether we are still sending or not - it is
919 * very accurate for the cd1400, not quite so for the sc26198.
920 * (The sc26198 has no "end-of-data" interrupt only empty FIFO)
921 */
922 tty->closing = 1;
Alan Coxb65b5b52006-06-27 02:54:05 -0700923
924 spin_unlock_irqrestore(&stallion_lock, flags);
925
Linus Torvalds1da177e2005-04-16 15:20:36 -0700926 if (portp->closing_wait != ASYNC_CLOSING_WAIT_NONE)
927 tty_wait_until_sent(tty, portp->closing_wait);
928 stl_waituntilsent(tty, (HZ / 2));
929
Alan Coxb65b5b52006-06-27 02:54:05 -0700930
931 spin_lock_irqsave(&stallion_lock, flags);
Alan Coxf8ae4762008-07-16 21:56:37 +0100932 portp->port.flags &= ~ASYNC_INITIALIZED;
Alan Coxb65b5b52006-06-27 02:54:05 -0700933 spin_unlock_irqrestore(&stallion_lock, flags);
934
Linus Torvalds1da177e2005-04-16 15:20:36 -0700935 stl_disableintrs(portp);
936 if (tty->termios->c_cflag & HUPCL)
937 stl_setsignals(portp, 0, 0);
938 stl_enablerxtx(portp, 0, 0);
939 stl_flushbuffer(tty);
940 portp->istate = 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800941 if (portp->tx.buf != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700942 kfree(portp->tx.buf);
Jiri Slaby615e4a72006-12-08 02:38:38 -0800943 portp->tx.buf = NULL;
944 portp->tx.head = NULL;
945 portp->tx.tail = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700946 }
947 set_bit(TTY_IO_ERROR, &tty->flags);
948 tty_ldisc_flush(tty);
949
950 tty->closing = 0;
Alan Coxd18a7502008-10-13 10:40:07 +0100951 tty_port_tty_set(&portp->port, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700952
953 if (portp->openwaitcnt) {
954 if (portp->close_delay)
955 msleep_interruptible(jiffies_to_msecs(portp->close_delay));
Alan Coxf8ae4762008-07-16 21:56:37 +0100956 wake_up_interruptible(&portp->port.open_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700957 }
958
Alan Coxf8ae4762008-07-16 21:56:37 +0100959 portp->port.flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
960 wake_up_interruptible(&portp->port.close_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700961}
962
963/*****************************************************************************/
964
965/*
966 * Write routine. Take data and stuff it in to the TX ring queue.
967 * If transmit interrupts are not running then start them.
968 */
969
970static int stl_write(struct tty_struct *tty, const unsigned char *buf, int count)
971{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800972 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700973 unsigned int len, stlen;
974 unsigned char *chbuf;
975 char *head, *tail;
976
Jiri Slabya0564e12006-12-08 02:38:37 -0800977 pr_debug("stl_write(tty=%p,buf=%p,count=%d)\n", tty, buf, count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700978
Linus Torvalds1da177e2005-04-16 15:20:36 -0700979 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800980 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +0100981 return 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800982 if (portp->tx.buf == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +0100983 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700984
985/*
986 * If copying direct from user space we must cater for page faults,
987 * causing us to "sleep" here for a while. To handle this copy in all
988 * the data we need now, into a local buffer. Then when we got it all
989 * copy it into the TX buffer.
990 */
991 chbuf = (unsigned char *) buf;
992
993 head = portp->tx.head;
994 tail = portp->tx.tail;
995 if (head >= tail) {
996 len = STL_TXBUFSIZE - (head - tail) - 1;
997 stlen = STL_TXBUFSIZE - (head - portp->tx.buf);
998 } else {
999 len = tail - head - 1;
1000 stlen = len;
1001 }
1002
Jiri Slaby843b5682006-12-08 02:39:12 -08001003 len = min(len, (unsigned int)count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001004 count = 0;
1005 while (len > 0) {
Jiri Slaby843b5682006-12-08 02:39:12 -08001006 stlen = min(len, stlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001007 memcpy(head, chbuf, stlen);
1008 len -= stlen;
1009 chbuf += stlen;
1010 count += stlen;
1011 head += stlen;
1012 if (head >= (portp->tx.buf + STL_TXBUFSIZE)) {
1013 head = portp->tx.buf;
1014 stlen = tail - head;
1015 }
1016 }
1017 portp->tx.head = head;
1018
1019 clear_bit(ASYI_TXLOW, &portp->istate);
1020 stl_startrxtx(portp, -1, 1);
1021
Jesper Juhl014c2542006-01-15 02:37:08 +01001022 return count;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001023}
1024
1025/*****************************************************************************/
1026
David Howells4a561222008-07-22 11:18:43 +01001027static int stl_putchar(struct tty_struct *tty, unsigned char ch)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001028{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001029 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001030 unsigned int len;
1031 char *head, *tail;
1032
Jiri Slabya0564e12006-12-08 02:38:37 -08001033 pr_debug("stl_putchar(tty=%p,ch=%x)\n", tty, ch);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001034
Linus Torvalds1da177e2005-04-16 15:20:36 -07001035 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001036 if (portp == NULL)
David Howells4a561222008-07-22 11:18:43 +01001037 return -EINVAL;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001038 if (portp->tx.buf == NULL)
David Howells4a561222008-07-22 11:18:43 +01001039 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001040
1041 head = portp->tx.head;
1042 tail = portp->tx.tail;
1043
1044 len = (head >= tail) ? (STL_TXBUFSIZE - (head - tail)) : (tail - head);
1045 len--;
1046
1047 if (len > 0) {
1048 *head++ = ch;
1049 if (head >= (portp->tx.buf + STL_TXBUFSIZE))
1050 head = portp->tx.buf;
1051 }
1052 portp->tx.head = head;
David Howells4a561222008-07-22 11:18:43 +01001053 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001054}
1055
1056/*****************************************************************************/
1057
1058/*
1059 * If there are any characters in the buffer then make sure that TX
1060 * interrupts are on and get'em out. Normally used after the putchar
1061 * routine has been called.
1062 */
1063
1064static void stl_flushchars(struct tty_struct *tty)
1065{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001066 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001067
Jiri Slabya0564e12006-12-08 02:38:37 -08001068 pr_debug("stl_flushchars(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001069
Linus Torvalds1da177e2005-04-16 15:20:36 -07001070 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001071 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001072 return;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001073 if (portp->tx.buf == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001074 return;
1075
Linus Torvalds1da177e2005-04-16 15:20:36 -07001076 stl_startrxtx(portp, -1, 1);
1077}
1078
1079/*****************************************************************************/
1080
1081static int stl_writeroom(struct tty_struct *tty)
1082{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001083 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001084 char *head, *tail;
1085
Jiri Slabya0564e12006-12-08 02:38:37 -08001086 pr_debug("stl_writeroom(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001087
Linus Torvalds1da177e2005-04-16 15:20:36 -07001088 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001089 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001090 return 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001091 if (portp->tx.buf == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001092 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001093
1094 head = portp->tx.head;
1095 tail = portp->tx.tail;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001096 return (head >= tail) ? (STL_TXBUFSIZE - (head - tail) - 1) : (tail - head - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001097}
1098
1099/*****************************************************************************/
1100
1101/*
1102 * Return number of chars in the TX buffer. Normally we would just
1103 * calculate the number of chars in the buffer and return that, but if
1104 * the buffer is empty and TX interrupts are still on then we return
1105 * that the buffer still has 1 char in it. This way whoever called us
1106 * will not think that ALL chars have drained - since the UART still
1107 * must have some chars in it (we are busy after all).
1108 */
1109
1110static int stl_charsinbuffer(struct tty_struct *tty)
1111{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001112 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001113 unsigned int size;
1114 char *head, *tail;
1115
Jiri Slabya0564e12006-12-08 02:38:37 -08001116 pr_debug("stl_charsinbuffer(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001117
Linus Torvalds1da177e2005-04-16 15:20:36 -07001118 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001119 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001120 return 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001121 if (portp->tx.buf == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001122 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001123
1124 head = portp->tx.head;
1125 tail = portp->tx.tail;
1126 size = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
1127 if ((size == 0) && test_bit(ASYI_TXBUSY, &portp->istate))
1128 size = 1;
Jesper Juhl014c2542006-01-15 02:37:08 +01001129 return size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001130}
1131
1132/*****************************************************************************/
1133
1134/*
1135 * Generate the serial struct info.
1136 */
1137
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001138static int stl_getserial(struct stlport *portp, struct serial_struct __user *sp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001139{
1140 struct serial_struct sio;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001141 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001142
Jiri Slabya0564e12006-12-08 02:38:37 -08001143 pr_debug("stl_getserial(portp=%p,sp=%p)\n", portp, sp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001144
1145 memset(&sio, 0, sizeof(struct serial_struct));
1146 sio.line = portp->portnr;
1147 sio.port = portp->ioaddr;
Alan Coxf8ae4762008-07-16 21:56:37 +01001148 sio.flags = portp->port.flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001149 sio.baud_base = portp->baud_base;
1150 sio.close_delay = portp->close_delay;
1151 sio.closing_wait = portp->closing_wait;
1152 sio.custom_divisor = portp->custom_divisor;
1153 sio.hub6 = 0;
1154 if (portp->uartp == &stl_cd1400uart) {
1155 sio.type = PORT_CIRRUS;
1156 sio.xmit_fifo_size = CD1400_TXFIFOSIZE;
1157 } else {
1158 sio.type = PORT_UNKNOWN;
1159 sio.xmit_fifo_size = SC26198_TXFIFOSIZE;
1160 }
1161
1162 brdp = stl_brds[portp->brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001163 if (brdp != NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001164 sio.irq = brdp->irq;
1165
1166 return copy_to_user(sp, &sio, sizeof(struct serial_struct)) ? -EFAULT : 0;
1167}
1168
1169/*****************************************************************************/
1170
1171/*
1172 * Set port according to the serial struct info.
1173 * At this point we do not do any auto-configure stuff, so we will
1174 * just quietly ignore any requests to change irq, etc.
1175 */
1176
Alan Coxd18a7502008-10-13 10:40:07 +01001177static int stl_setserial(struct tty_struct *tty, struct serial_struct __user *sp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001178{
Alan Coxd18a7502008-10-13 10:40:07 +01001179 struct stlport * portp = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001180 struct serial_struct sio;
1181
Jiri Slabya0564e12006-12-08 02:38:37 -08001182 pr_debug("stl_setserial(portp=%p,sp=%p)\n", portp, sp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001183
1184 if (copy_from_user(&sio, sp, sizeof(struct serial_struct)))
1185 return -EFAULT;
1186 if (!capable(CAP_SYS_ADMIN)) {
1187 if ((sio.baud_base != portp->baud_base) ||
1188 (sio.close_delay != portp->close_delay) ||
1189 ((sio.flags & ~ASYNC_USR_MASK) !=
Alan Coxf8ae4762008-07-16 21:56:37 +01001190 (portp->port.flags & ~ASYNC_USR_MASK)))
Jesper Juhl014c2542006-01-15 02:37:08 +01001191 return -EPERM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001192 }
1193
Alan Coxf8ae4762008-07-16 21:56:37 +01001194 portp->port.flags = (portp->port.flags & ~ASYNC_USR_MASK) |
Linus Torvalds1da177e2005-04-16 15:20:36 -07001195 (sio.flags & ASYNC_USR_MASK);
1196 portp->baud_base = sio.baud_base;
1197 portp->close_delay = sio.close_delay;
1198 portp->closing_wait = sio.closing_wait;
1199 portp->custom_divisor = sio.custom_divisor;
Alan Coxd18a7502008-10-13 10:40:07 +01001200 stl_setport(portp, tty->termios);
Jesper Juhl014c2542006-01-15 02:37:08 +01001201 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001202}
1203
1204/*****************************************************************************/
1205
1206static int stl_tiocmget(struct tty_struct *tty, struct file *file)
1207{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001208 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001209
Linus Torvalds1da177e2005-04-16 15:20:36 -07001210 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001211 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001212 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001213 if (tty->flags & (1 << TTY_IO_ERROR))
Jesper Juhl014c2542006-01-15 02:37:08 +01001214 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001215
1216 return stl_getsignals(portp);
1217}
1218
1219static int stl_tiocmset(struct tty_struct *tty, struct file *file,
1220 unsigned int set, unsigned int clear)
1221{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001222 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001223 int rts = -1, dtr = -1;
1224
Linus Torvalds1da177e2005-04-16 15:20:36 -07001225 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001226 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001227 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001228 if (tty->flags & (1 << TTY_IO_ERROR))
Jesper Juhl014c2542006-01-15 02:37:08 +01001229 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001230
1231 if (set & TIOCM_RTS)
1232 rts = 1;
1233 if (set & TIOCM_DTR)
1234 dtr = 1;
1235 if (clear & TIOCM_RTS)
1236 rts = 0;
1237 if (clear & TIOCM_DTR)
1238 dtr = 0;
1239
1240 stl_setsignals(portp, dtr, rts);
1241 return 0;
1242}
1243
1244static int stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg)
1245{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001246 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001247 int rc;
1248 void __user *argp = (void __user *)arg;
1249
Jiri Slabya0564e12006-12-08 02:38:37 -08001250 pr_debug("stl_ioctl(tty=%p,file=%p,cmd=%x,arg=%lx)\n", tty, file, cmd,
1251 arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001252
Linus Torvalds1da177e2005-04-16 15:20:36 -07001253 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001254 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001255 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001256
1257 if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
Jiri Slabyc62429d2006-12-08 02:39:14 -08001258 (cmd != COM_GETPORTSTATS) && (cmd != COM_CLRPORTSTATS))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001259 if (tty->flags & (1 << TTY_IO_ERROR))
Jesper Juhl014c2542006-01-15 02:37:08 +01001260 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001261
1262 rc = 0;
1263
Alan Coxf433c652008-04-30 00:53:23 -07001264 lock_kernel();
1265
Linus Torvalds1da177e2005-04-16 15:20:36 -07001266 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001267 case TIOCGSERIAL:
1268 rc = stl_getserial(portp, argp);
1269 break;
1270 case TIOCSSERIAL:
Alan Coxd18a7502008-10-13 10:40:07 +01001271 rc = stl_setserial(tty, argp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001272 break;
1273 case COM_GETPORTSTATS:
Alan Coxd18a7502008-10-13 10:40:07 +01001274 rc = stl_getportstats(tty, portp, argp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001275 break;
1276 case COM_CLRPORTSTATS:
1277 rc = stl_clrportstats(portp, argp);
1278 break;
1279 case TIOCSERCONFIG:
1280 case TIOCSERGWILD:
1281 case TIOCSERSWILD:
1282 case TIOCSERGETLSR:
1283 case TIOCSERGSTRUCT:
1284 case TIOCSERGETMULTI:
1285 case TIOCSERSETMULTI:
1286 default:
1287 rc = -ENOIOCTLCMD;
1288 break;
1289 }
Alan Coxf433c652008-04-30 00:53:23 -07001290 unlock_kernel();
Jesper Juhl014c2542006-01-15 02:37:08 +01001291 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001292}
1293
1294/*****************************************************************************/
1295
Jiri Slaby96b066b2006-12-08 02:38:42 -08001296/*
1297 * Start the transmitter again. Just turn TX interrupts back on.
1298 */
1299
1300static void stl_start(struct tty_struct *tty)
1301{
1302 struct stlport *portp;
1303
1304 pr_debug("stl_start(tty=%p)\n", tty);
1305
Jiri Slaby96b066b2006-12-08 02:38:42 -08001306 portp = tty->driver_data;
1307 if (portp == NULL)
1308 return;
1309 stl_startrxtx(portp, -1, 1);
1310}
1311
1312/*****************************************************************************/
1313
Alan Cox606d0992006-12-08 02:38:45 -08001314static void stl_settermios(struct tty_struct *tty, struct ktermios *old)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001315{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001316 struct stlport *portp;
Alan Cox606d0992006-12-08 02:38:45 -08001317 struct ktermios *tiosp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001318
Jiri Slabya0564e12006-12-08 02:38:37 -08001319 pr_debug("stl_settermios(tty=%p,old=%p)\n", tty, old);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001320
Linus Torvalds1da177e2005-04-16 15:20:36 -07001321 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001322 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001323 return;
1324
1325 tiosp = tty->termios;
1326 if ((tiosp->c_cflag == old->c_cflag) &&
1327 (tiosp->c_iflag == old->c_iflag))
1328 return;
1329
1330 stl_setport(portp, tiosp);
1331 stl_setsignals(portp, ((tiosp->c_cflag & (CBAUD & ~CBAUDEX)) ? 1 : 0),
1332 -1);
1333 if ((old->c_cflag & CRTSCTS) && ((tiosp->c_cflag & CRTSCTS) == 0)) {
1334 tty->hw_stopped = 0;
1335 stl_start(tty);
1336 }
1337 if (((old->c_cflag & CLOCAL) == 0) && (tiosp->c_cflag & CLOCAL))
Alan Coxf8ae4762008-07-16 21:56:37 +01001338 wake_up_interruptible(&portp->port.open_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001339}
1340
1341/*****************************************************************************/
1342
1343/*
1344 * Attempt to flow control who ever is sending us data. Based on termios
1345 * settings use software or/and hardware flow control.
1346 */
1347
1348static void stl_throttle(struct tty_struct *tty)
1349{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001350 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001351
Jiri Slabya0564e12006-12-08 02:38:37 -08001352 pr_debug("stl_throttle(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001353
Linus Torvalds1da177e2005-04-16 15:20:36 -07001354 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001355 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001356 return;
1357 stl_flowctrl(portp, 0);
1358}
1359
1360/*****************************************************************************/
1361
1362/*
1363 * Unflow control the device sending us data...
1364 */
1365
1366static void stl_unthrottle(struct tty_struct *tty)
1367{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001368 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001369
Jiri Slabya0564e12006-12-08 02:38:37 -08001370 pr_debug("stl_unthrottle(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001371
Linus Torvalds1da177e2005-04-16 15:20:36 -07001372 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001373 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001374 return;
1375 stl_flowctrl(portp, 1);
1376}
1377
1378/*****************************************************************************/
1379
1380/*
1381 * Stop the transmitter. Basically to do this we will just turn TX
1382 * interrupts off.
1383 */
1384
1385static void stl_stop(struct tty_struct *tty)
1386{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001387 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001388
Jiri Slabya0564e12006-12-08 02:38:37 -08001389 pr_debug("stl_stop(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001390
Linus Torvalds1da177e2005-04-16 15:20:36 -07001391 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001392 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001393 return;
1394 stl_startrxtx(portp, -1, 0);
1395}
1396
1397/*****************************************************************************/
1398
1399/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001400 * Hangup this port. This is pretty much like closing the port, only
1401 * a little more brutal. No waiting for data to drain. Shutdown the
1402 * port and maybe drop signals.
1403 */
1404
1405static void stl_hangup(struct tty_struct *tty)
1406{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001407 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001408
Jiri Slabya0564e12006-12-08 02:38:37 -08001409 pr_debug("stl_hangup(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001410
Linus Torvalds1da177e2005-04-16 15:20:36 -07001411 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001412 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001413 return;
1414
Alan Coxf8ae4762008-07-16 21:56:37 +01001415 portp->port.flags &= ~ASYNC_INITIALIZED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001416 stl_disableintrs(portp);
1417 if (tty->termios->c_cflag & HUPCL)
1418 stl_setsignals(portp, 0, 0);
1419 stl_enablerxtx(portp, 0, 0);
1420 stl_flushbuffer(tty);
1421 portp->istate = 0;
1422 set_bit(TTY_IO_ERROR, &tty->flags);
Jiri Slaby615e4a72006-12-08 02:38:38 -08001423 if (portp->tx.buf != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001424 kfree(portp->tx.buf);
Jiri Slaby615e4a72006-12-08 02:38:38 -08001425 portp->tx.buf = NULL;
1426 portp->tx.head = NULL;
1427 portp->tx.tail = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001428 }
Alan Coxd18a7502008-10-13 10:40:07 +01001429 tty_port_tty_set(&portp->port, NULL);
Alan Coxf8ae4762008-07-16 21:56:37 +01001430 portp->port.flags &= ~ASYNC_NORMAL_ACTIVE;
1431 portp->port.count = 0;
1432 wake_up_interruptible(&portp->port.open_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001433}
1434
1435/*****************************************************************************/
1436
David Howells4a561222008-07-22 11:18:43 +01001437static int stl_breakctl(struct tty_struct *tty, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001438{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001439 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001440
Jiri Slabya0564e12006-12-08 02:38:37 -08001441 pr_debug("stl_breakctl(tty=%p,state=%d)\n", tty, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001442
Linus Torvalds1da177e2005-04-16 15:20:36 -07001443 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001444 if (portp == NULL)
David Howells4a561222008-07-22 11:18:43 +01001445 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001446
1447 stl_sendbreak(portp, ((state == -1) ? 1 : 2));
David Howells4a561222008-07-22 11:18:43 +01001448 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001449}
1450
1451/*****************************************************************************/
1452
Linus Torvalds1da177e2005-04-16 15:20:36 -07001453static void stl_sendxchar(struct tty_struct *tty, char ch)
1454{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001455 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001456
Jiri Slabya0564e12006-12-08 02:38:37 -08001457 pr_debug("stl_sendxchar(tty=%p,ch=%x)\n", tty, ch);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001458
Linus Torvalds1da177e2005-04-16 15:20:36 -07001459 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001460 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001461 return;
1462
1463 if (ch == STOP_CHAR(tty))
1464 stl_sendflow(portp, 0);
1465 else if (ch == START_CHAR(tty))
1466 stl_sendflow(portp, 1);
1467 else
1468 stl_putchar(tty, ch);
1469}
1470
1471/*****************************************************************************/
1472
1473#define MAXLINE 80
1474
1475/*
1476 * Format info for a specified port. The line is deliberately limited
1477 * to 80 characters. (If it is too long it will be truncated, if too
1478 * short then padded with spaces).
1479 */
1480
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001481static int stl_portinfo(struct stlport *portp, int portnr, char *pos)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001482{
1483 char *sp;
1484 int sigs, cnt;
1485
1486 sp = pos;
1487 sp += sprintf(sp, "%d: uart:%s tx:%d rx:%d",
1488 portnr, (portp->hwid == 1) ? "SC26198" : "CD1400",
1489 (int) portp->stats.txtotal, (int) portp->stats.rxtotal);
1490
1491 if (portp->stats.rxframing)
1492 sp += sprintf(sp, " fe:%d", (int) portp->stats.rxframing);
1493 if (portp->stats.rxparity)
1494 sp += sprintf(sp, " pe:%d", (int) portp->stats.rxparity);
1495 if (portp->stats.rxbreaks)
1496 sp += sprintf(sp, " brk:%d", (int) portp->stats.rxbreaks);
1497 if (portp->stats.rxoverrun)
1498 sp += sprintf(sp, " oe:%d", (int) portp->stats.rxoverrun);
1499
1500 sigs = stl_getsignals(portp);
1501 cnt = sprintf(sp, "%s%s%s%s%s ",
1502 (sigs & TIOCM_RTS) ? "|RTS" : "",
1503 (sigs & TIOCM_CTS) ? "|CTS" : "",
1504 (sigs & TIOCM_DTR) ? "|DTR" : "",
1505 (sigs & TIOCM_CD) ? "|DCD" : "",
1506 (sigs & TIOCM_DSR) ? "|DSR" : "");
1507 *sp = ' ';
1508 sp += cnt;
1509
Jiri Slabyc62429d2006-12-08 02:39:14 -08001510 for (cnt = sp - pos; cnt < (MAXLINE - 1); cnt++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001511 *sp++ = ' ';
1512 if (cnt >= MAXLINE)
1513 pos[(MAXLINE - 2)] = '+';
1514 pos[(MAXLINE - 1)] = '\n';
1515
Jesper Juhl014c2542006-01-15 02:37:08 +01001516 return MAXLINE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001517}
1518
1519/*****************************************************************************/
1520
1521/*
1522 * Port info, read from the /proc file system.
1523 */
1524
1525static int stl_readproc(char *page, char **start, off_t off, int count, int *eof, void *data)
1526{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001527 struct stlbrd *brdp;
1528 struct stlpanel *panelp;
1529 struct stlport *portp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001530 unsigned int brdnr, panelnr, portnr;
1531 int totalport, curoff, maxoff;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001532 char *pos;
1533
Jiri Slabya0564e12006-12-08 02:38:37 -08001534 pr_debug("stl_readproc(page=%p,start=%p,off=%lx,count=%d,eof=%p,"
1535 "data=%p\n", page, start, off, count, eof, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001536
1537 pos = page;
1538 totalport = 0;
1539 curoff = 0;
1540
1541 if (off == 0) {
1542 pos += sprintf(pos, "%s: version %s", stl_drvtitle,
1543 stl_drvversion);
1544 while (pos < (page + MAXLINE - 1))
1545 *pos++ = ' ';
1546 *pos++ = '\n';
1547 }
1548 curoff = MAXLINE;
1549
1550/*
1551 * We scan through for each board, panel and port. The offset is
1552 * calculated on the fly, and irrelevant ports are skipped.
1553 */
Jiri Slabyc62429d2006-12-08 02:39:14 -08001554 for (brdnr = 0; brdnr < stl_nrbrds; brdnr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001555 brdp = stl_brds[brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001556 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001557 continue;
1558 if (brdp->state == 0)
1559 continue;
1560
1561 maxoff = curoff + (brdp->nrports * MAXLINE);
1562 if (off >= maxoff) {
1563 curoff = maxoff;
1564 continue;
1565 }
1566
1567 totalport = brdnr * STL_MAXPORTS;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001568 for (panelnr = 0; panelnr < brdp->nrpanels; panelnr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001569 panelp = brdp->panels[panelnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001570 if (panelp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001571 continue;
1572
1573 maxoff = curoff + (panelp->nrports * MAXLINE);
1574 if (off >= maxoff) {
1575 curoff = maxoff;
1576 totalport += panelp->nrports;
1577 continue;
1578 }
1579
Jiri Slabyc62429d2006-12-08 02:39:14 -08001580 for (portnr = 0; portnr < panelp->nrports; portnr++,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001581 totalport++) {
1582 portp = panelp->ports[portnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001583 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001584 continue;
1585 if (off >= (curoff += MAXLINE))
1586 continue;
1587 if ((pos - page + MAXLINE) > count)
1588 goto stl_readdone;
1589 pos += stl_portinfo(portp, totalport, pos);
1590 }
1591 }
1592 }
1593
1594 *eof = 1;
1595
1596stl_readdone:
1597 *start = page;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001598 return pos - page;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001599}
1600
1601/*****************************************************************************/
1602
1603/*
1604 * All board interrupts are vectored through here first. This code then
1605 * calls off to the approrpriate board interrupt handlers.
1606 */
1607
David Howells7d12e782006-10-05 14:55:46 +01001608static irqreturn_t stl_intr(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001609{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001610 struct stlbrd *brdp = dev_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001611
Jeff Garzika6f97b22007-10-31 05:20:49 -04001612 pr_debug("stl_intr(brdp=%p,irq=%d)\n", brdp, brdp->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001613
1614 return IRQ_RETVAL((* brdp->isr)(brdp));
1615}
1616
1617/*****************************************************************************/
1618
1619/*
1620 * Interrupt service routine for EasyIO board types.
1621 */
1622
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001623static int stl_eiointr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001624{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001625 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001626 unsigned int iobase;
1627 int handled = 0;
1628
Alan Coxb65b5b52006-06-27 02:54:05 -07001629 spin_lock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001630 panelp = brdp->panels[0];
1631 iobase = panelp->iobase;
1632 while (inb(brdp->iostatus) & EIO_INTRPEND) {
1633 handled = 1;
1634 (* panelp->isr)(panelp, iobase);
1635 }
Alan Coxb65b5b52006-06-27 02:54:05 -07001636 spin_unlock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001637 return handled;
1638}
1639
1640/*****************************************************************************/
1641
1642/*
1643 * Interrupt service routine for ECH-AT board types.
1644 */
1645
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001646static int stl_echatintr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001647{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001648 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001649 unsigned int ioaddr, bnknr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001650 int handled = 0;
1651
1652 outb((brdp->ioctrlval | ECH_BRDENABLE), brdp->ioctrl);
1653
1654 while (inb(brdp->iostatus) & ECH_INTRPEND) {
1655 handled = 1;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001656 for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001657 ioaddr = brdp->bnkstataddr[bnknr];
1658 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1659 panelp = brdp->bnk2panel[bnknr];
1660 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1661 }
1662 }
1663 }
1664
1665 outb((brdp->ioctrlval | ECH_BRDDISABLE), brdp->ioctrl);
1666
1667 return handled;
1668}
1669
1670/*****************************************************************************/
1671
1672/*
1673 * Interrupt service routine for ECH-MCA board types.
1674 */
1675
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001676static int stl_echmcaintr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001677{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001678 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001679 unsigned int ioaddr, bnknr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001680 int handled = 0;
1681
1682 while (inb(brdp->iostatus) & ECH_INTRPEND) {
1683 handled = 1;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001684 for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001685 ioaddr = brdp->bnkstataddr[bnknr];
1686 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1687 panelp = brdp->bnk2panel[bnknr];
1688 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1689 }
1690 }
1691 }
1692 return handled;
1693}
1694
1695/*****************************************************************************/
1696
1697/*
1698 * Interrupt service routine for ECH-PCI board types.
1699 */
1700
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001701static int stl_echpciintr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001702{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001703 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001704 unsigned int ioaddr, bnknr, recheck;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001705 int handled = 0;
1706
1707 while (1) {
1708 recheck = 0;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001709 for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001710 outb(brdp->bnkpageaddr[bnknr], brdp->ioctrl);
1711 ioaddr = brdp->bnkstataddr[bnknr];
1712 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1713 panelp = brdp->bnk2panel[bnknr];
1714 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1715 recheck++;
1716 handled = 1;
1717 }
1718 }
1719 if (! recheck)
1720 break;
1721 }
1722 return handled;
1723}
1724
1725/*****************************************************************************/
1726
1727/*
1728 * Interrupt service routine for ECH-8/64-PCI board types.
1729 */
1730
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001731static int stl_echpci64intr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001732{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001733 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001734 unsigned int ioaddr, bnknr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001735 int handled = 0;
1736
1737 while (inb(brdp->ioctrl) & 0x1) {
1738 handled = 1;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001739 for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001740 ioaddr = brdp->bnkstataddr[bnknr];
1741 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1742 panelp = brdp->bnk2panel[bnknr];
1743 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1744 }
1745 }
1746 }
1747
1748 return handled;
1749}
1750
1751/*****************************************************************************/
1752
1753/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001754 * Initialize all the ports on a panel.
1755 */
1756
Jiri Slaby705c1862006-12-08 02:39:11 -08001757static int __devinit stl_initports(struct stlbrd *brdp, struct stlpanel *panelp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001758{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001759 struct stlport *portp;
1760 unsigned int i;
1761 int chipmask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001762
Jiri Slabya0564e12006-12-08 02:38:37 -08001763 pr_debug("stl_initports(brdp=%p,panelp=%p)\n", brdp, panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001764
1765 chipmask = stl_panelinit(brdp, panelp);
1766
1767/*
1768 * All UART's are initialized (if found!). Now go through and setup
1769 * each ports data structures.
1770 */
Jiri Slabyc62429d2006-12-08 02:39:14 -08001771 for (i = 0; i < panelp->nrports; i++) {
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001772 portp = kzalloc(sizeof(struct stlport), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08001773 if (!portp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001774 printk("STALLION: failed to allocate memory "
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001775 "(size=%Zd)\n", sizeof(struct stlport));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001776 break;
1777 }
Alan Coxd18a7502008-10-13 10:40:07 +01001778 tty_port_init(&portp->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001779 portp->magic = STL_PORTMAGIC;
1780 portp->portnr = i;
1781 portp->brdnr = panelp->brdnr;
1782 portp->panelnr = panelp->panelnr;
1783 portp->uartp = panelp->uartp;
1784 portp->clk = brdp->clk;
1785 portp->baud_base = STL_BAUDBASE;
1786 portp->close_delay = STL_CLOSEDELAY;
1787 portp->closing_wait = 30 * HZ;
Alan Coxf8ae4762008-07-16 21:56:37 +01001788 init_waitqueue_head(&portp->port.open_wait);
1789 init_waitqueue_head(&portp->port.close_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001790 portp->stats.brd = portp->brdnr;
1791 portp->stats.panel = portp->panelnr;
1792 portp->stats.port = portp->portnr;
1793 panelp->ports[i] = portp;
1794 stl_portinit(brdp, panelp, portp);
1795 }
1796
Jiri Slabyc62429d2006-12-08 02:39:14 -08001797 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001798}
1799
Jiri Slaby3b85b342006-12-08 02:39:10 -08001800static void stl_cleanup_panels(struct stlbrd *brdp)
1801{
1802 struct stlpanel *panelp;
1803 struct stlport *portp;
1804 unsigned int j, k;
Alan Coxd18a7502008-10-13 10:40:07 +01001805 struct tty_struct *tty;
Jiri Slaby3b85b342006-12-08 02:39:10 -08001806
1807 for (j = 0; j < STL_MAXPANELS; j++) {
1808 panelp = brdp->panels[j];
1809 if (panelp == NULL)
1810 continue;
1811 for (k = 0; k < STL_PORTSPERPANEL; k++) {
1812 portp = panelp->ports[k];
1813 if (portp == NULL)
1814 continue;
Alan Coxd18a7502008-10-13 10:40:07 +01001815 tty = tty_port_tty_get(&portp->port);
1816 if (tty != NULL) {
1817 stl_hangup(tty);
1818 tty_kref_put(tty);
1819 }
Jiri Slaby3b85b342006-12-08 02:39:10 -08001820 kfree(portp->tx.buf);
1821 kfree(portp);
1822 }
1823 kfree(panelp);
1824 }
1825}
1826
Linus Torvalds1da177e2005-04-16 15:20:36 -07001827/*****************************************************************************/
1828
1829/*
1830 * Try to find and initialize an EasyIO board.
1831 */
1832
Jiri Slaby705c1862006-12-08 02:39:11 -08001833static int __devinit stl_initeio(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001834{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001835 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001836 unsigned int status;
1837 char *name;
Jiri Slaby3b85b342006-12-08 02:39:10 -08001838 int retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001839
Jiri Slabya0564e12006-12-08 02:38:37 -08001840 pr_debug("stl_initeio(brdp=%p)\n", brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001841
1842 brdp->ioctrl = brdp->ioaddr1 + 1;
1843 brdp->iostatus = brdp->ioaddr1 + 2;
1844
1845 status = inb(brdp->iostatus);
1846 if ((status & EIO_IDBITMASK) == EIO_MK3)
1847 brdp->ioctrl++;
1848
1849/*
1850 * Handle board specific stuff now. The real difference is PCI
1851 * or not PCI.
1852 */
1853 if (brdp->brdtype == BRD_EASYIOPCI) {
1854 brdp->iosize1 = 0x80;
1855 brdp->iosize2 = 0x80;
1856 name = "serial(EIO-PCI)";
1857 outb(0x41, (brdp->ioaddr2 + 0x4c));
1858 } else {
1859 brdp->iosize1 = 8;
1860 name = "serial(EIO)";
1861 if ((brdp->irq < 0) || (brdp->irq > 15) ||
1862 (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
1863 printk("STALLION: invalid irq=%d for brd=%d\n",
1864 brdp->irq, brdp->brdnr);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001865 retval = -EINVAL;
1866 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001867 }
1868 outb((stl_vecmap[brdp->irq] | EIO_0WS |
1869 ((brdp->irqtype) ? EIO_INTLEVEL : EIO_INTEDGE)),
1870 brdp->ioctrl);
1871 }
1872
Jiri Slaby3b85b342006-12-08 02:39:10 -08001873 retval = -EBUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001874 if (!request_region(brdp->ioaddr1, brdp->iosize1, name)) {
1875 printk(KERN_WARNING "STALLION: Warning, board %d I/O address "
1876 "%x conflicts with another device\n", brdp->brdnr,
1877 brdp->ioaddr1);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001878 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001879 }
1880
1881 if (brdp->iosize2 > 0)
1882 if (!request_region(brdp->ioaddr2, brdp->iosize2, name)) {
1883 printk(KERN_WARNING "STALLION: Warning, board %d I/O "
1884 "address %x conflicts with another device\n",
1885 brdp->brdnr, brdp->ioaddr2);
1886 printk(KERN_WARNING "STALLION: Warning, also "
1887 "releasing board %d I/O address %x \n",
1888 brdp->brdnr, brdp->ioaddr1);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001889 goto err_rel1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001890 }
1891
1892/*
1893 * Everything looks OK, so let's go ahead and probe for the hardware.
1894 */
1895 brdp->clk = CD1400_CLK;
1896 brdp->isr = stl_eiointr;
1897
Jiri Slaby3b85b342006-12-08 02:39:10 -08001898 retval = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001899 switch (status & EIO_IDBITMASK) {
1900 case EIO_8PORTM:
1901 brdp->clk = CD1400_CLK8M;
1902 /* fall thru */
1903 case EIO_8PORTRS:
1904 case EIO_8PORTDI:
1905 brdp->nrports = 8;
1906 break;
1907 case EIO_4PORTRS:
1908 brdp->nrports = 4;
1909 break;
1910 case EIO_MK3:
1911 switch (status & EIO_BRDMASK) {
1912 case ID_BRD4:
1913 brdp->nrports = 4;
1914 break;
1915 case ID_BRD8:
1916 brdp->nrports = 8;
1917 break;
1918 case ID_BRD16:
1919 brdp->nrports = 16;
1920 break;
1921 default:
Jiri Slaby3b85b342006-12-08 02:39:10 -08001922 goto err_rel2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001923 }
1924 break;
1925 default:
Jiri Slaby3b85b342006-12-08 02:39:10 -08001926 goto err_rel2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001927 }
1928
1929/*
1930 * We have verified that the board is actually present, so now we
1931 * can complete the setup.
1932 */
1933
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001934 panelp = kzalloc(sizeof(struct stlpanel), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08001935 if (!panelp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001936 printk(KERN_WARNING "STALLION: failed to allocate memory "
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001937 "(size=%Zd)\n", sizeof(struct stlpanel));
Jiri Slaby3b85b342006-12-08 02:39:10 -08001938 retval = -ENOMEM;
1939 goto err_rel2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001940 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001941
1942 panelp->magic = STL_PANELMAGIC;
1943 panelp->brdnr = brdp->brdnr;
1944 panelp->panelnr = 0;
1945 panelp->nrports = brdp->nrports;
1946 panelp->iobase = brdp->ioaddr1;
1947 panelp->hwid = status;
1948 if ((status & EIO_IDBITMASK) == EIO_MK3) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08001949 panelp->uartp = &stl_sc26198uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001950 panelp->isr = stl_sc26198intr;
1951 } else {
Jiri Slaby615e4a72006-12-08 02:38:38 -08001952 panelp->uartp = &stl_cd1400uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001953 panelp->isr = stl_cd1400eiointr;
1954 }
1955
1956 brdp->panels[0] = panelp;
1957 brdp->nrpanels = 1;
1958 brdp->state |= BRD_FOUND;
1959 brdp->hwid = status;
Thomas Gleixner0f2ed4c2006-07-01 19:29:33 -07001960 if (request_irq(brdp->irq, stl_intr, IRQF_SHARED, name, brdp) != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001961 printk("STALLION: failed to register interrupt "
1962 "routine for %s irq=%d\n", name, brdp->irq);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001963 retval = -ENODEV;
1964 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001965 }
Jiri Slaby3b85b342006-12-08 02:39:10 -08001966
1967 return 0;
1968err_fr:
1969 stl_cleanup_panels(brdp);
1970err_rel2:
1971 if (brdp->iosize2 > 0)
1972 release_region(brdp->ioaddr2, brdp->iosize2);
1973err_rel1:
1974 release_region(brdp->ioaddr1, brdp->iosize1);
1975err:
1976 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001977}
1978
1979/*****************************************************************************/
1980
1981/*
1982 * Try to find an ECH board and initialize it. This code is capable of
1983 * dealing with all types of ECH board.
1984 */
1985
Jiri Slaby705c1862006-12-08 02:39:11 -08001986static int __devinit stl_initech(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001987{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001988 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001989 unsigned int status, nxtid, ioaddr, conflict, panelnr, banknr, i;
1990 int retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001991 char *name;
1992
Jiri Slabya0564e12006-12-08 02:38:37 -08001993 pr_debug("stl_initech(brdp=%p)\n", brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001994
1995 status = 0;
1996 conflict = 0;
1997
1998/*
1999 * Set up the initial board register contents for boards. This varies a
2000 * bit between the different board types. So we need to handle each
2001 * separately. Also do a check that the supplied IRQ is good.
2002 */
2003 switch (brdp->brdtype) {
2004
2005 case BRD_ECH:
2006 brdp->isr = stl_echatintr;
2007 brdp->ioctrl = brdp->ioaddr1 + 1;
2008 brdp->iostatus = brdp->ioaddr1 + 1;
2009 status = inb(brdp->iostatus);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002010 if ((status & ECH_IDBITMASK) != ECH_ID) {
2011 retval = -ENODEV;
2012 goto err;
2013 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002014 if ((brdp->irq < 0) || (brdp->irq > 15) ||
2015 (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
2016 printk("STALLION: invalid irq=%d for brd=%d\n",
2017 brdp->irq, brdp->brdnr);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002018 retval = -EINVAL;
2019 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002020 }
2021 status = ((brdp->ioaddr2 & ECH_ADDR2MASK) >> 1);
2022 status |= (stl_vecmap[brdp->irq] << 1);
2023 outb((status | ECH_BRDRESET), brdp->ioaddr1);
2024 brdp->ioctrlval = ECH_INTENABLE |
2025 ((brdp->irqtype) ? ECH_INTLEVEL : ECH_INTEDGE);
Jiri Slabyc62429d2006-12-08 02:39:14 -08002026 for (i = 0; i < 10; i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002027 outb((brdp->ioctrlval | ECH_BRDENABLE), brdp->ioctrl);
2028 brdp->iosize1 = 2;
2029 brdp->iosize2 = 32;
2030 name = "serial(EC8/32)";
2031 outb(status, brdp->ioaddr1);
2032 break;
2033
2034 case BRD_ECHMC:
2035 brdp->isr = stl_echmcaintr;
2036 brdp->ioctrl = brdp->ioaddr1 + 0x20;
2037 brdp->iostatus = brdp->ioctrl;
2038 status = inb(brdp->iostatus);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002039 if ((status & ECH_IDBITMASK) != ECH_ID) {
2040 retval = -ENODEV;
2041 goto err;
2042 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002043 if ((brdp->irq < 0) || (brdp->irq > 15) ||
2044 (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
2045 printk("STALLION: invalid irq=%d for brd=%d\n",
2046 brdp->irq, brdp->brdnr);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002047 retval = -EINVAL;
2048 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002049 }
2050 outb(ECHMC_BRDRESET, brdp->ioctrl);
2051 outb(ECHMC_INTENABLE, brdp->ioctrl);
2052 brdp->iosize1 = 64;
2053 name = "serial(EC8/32-MC)";
2054 break;
2055
2056 case BRD_ECHPCI:
2057 brdp->isr = stl_echpciintr;
2058 brdp->ioctrl = brdp->ioaddr1 + 2;
2059 brdp->iosize1 = 4;
2060 brdp->iosize2 = 8;
2061 name = "serial(EC8/32-PCI)";
2062 break;
2063
2064 case BRD_ECH64PCI:
2065 brdp->isr = stl_echpci64intr;
2066 brdp->ioctrl = brdp->ioaddr2 + 0x40;
2067 outb(0x43, (brdp->ioaddr1 + 0x4c));
2068 brdp->iosize1 = 0x80;
2069 brdp->iosize2 = 0x80;
2070 name = "serial(EC8/64-PCI)";
2071 break;
2072
2073 default:
2074 printk("STALLION: unknown board type=%d\n", brdp->brdtype);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002075 retval = -EINVAL;
2076 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002077 }
2078
2079/*
2080 * Check boards for possible IO address conflicts and return fail status
2081 * if an IO conflict found.
2082 */
Jiri Slaby3b85b342006-12-08 02:39:10 -08002083 retval = -EBUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002084 if (!request_region(brdp->ioaddr1, brdp->iosize1, name)) {
2085 printk(KERN_WARNING "STALLION: Warning, board %d I/O address "
2086 "%x conflicts with another device\n", brdp->brdnr,
2087 brdp->ioaddr1);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002088 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002089 }
2090
2091 if (brdp->iosize2 > 0)
2092 if (!request_region(brdp->ioaddr2, brdp->iosize2, name)) {
2093 printk(KERN_WARNING "STALLION: Warning, board %d I/O "
2094 "address %x conflicts with another device\n",
2095 brdp->brdnr, brdp->ioaddr2);
2096 printk(KERN_WARNING "STALLION: Warning, also "
2097 "releasing board %d I/O address %x \n",
2098 brdp->brdnr, brdp->ioaddr1);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002099 goto err_rel1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002100 }
2101
2102/*
2103 * Scan through the secondary io address space looking for panels.
2104 * As we find'em allocate and initialize panel structures for each.
2105 */
2106 brdp->clk = CD1400_CLK;
2107 brdp->hwid = status;
2108
2109 ioaddr = brdp->ioaddr2;
2110 banknr = 0;
2111 panelnr = 0;
2112 nxtid = 0;
2113
Jiri Slabyc62429d2006-12-08 02:39:14 -08002114 for (i = 0; i < STL_MAXPANELS; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002115 if (brdp->brdtype == BRD_ECHPCI) {
2116 outb(nxtid, brdp->ioctrl);
2117 ioaddr = brdp->ioaddr2;
2118 }
2119 status = inb(ioaddr + ECH_PNLSTATUS);
2120 if ((status & ECH_PNLIDMASK) != nxtid)
Jiri Slaby64834b22007-06-08 13:46:52 -07002121 break;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002122 panelp = kzalloc(sizeof(struct stlpanel), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08002123 if (!panelp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002124 printk("STALLION: failed to allocate memory "
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002125 "(size=%Zd)\n", sizeof(struct stlpanel));
Jiri Slaby49277b12007-06-08 13:46:53 -07002126 retval = -ENOMEM;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002127 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002128 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002129 panelp->magic = STL_PANELMAGIC;
2130 panelp->brdnr = brdp->brdnr;
2131 panelp->panelnr = panelnr;
2132 panelp->iobase = ioaddr;
2133 panelp->pagenr = nxtid;
2134 panelp->hwid = status;
2135 brdp->bnk2panel[banknr] = panelp;
2136 brdp->bnkpageaddr[banknr] = nxtid;
2137 brdp->bnkstataddr[banknr++] = ioaddr + ECH_PNLSTATUS;
2138
2139 if (status & ECH_PNLXPID) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08002140 panelp->uartp = &stl_sc26198uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002141 panelp->isr = stl_sc26198intr;
2142 if (status & ECH_PNL16PORT) {
2143 panelp->nrports = 16;
2144 brdp->bnk2panel[banknr] = panelp;
2145 brdp->bnkpageaddr[banknr] = nxtid;
2146 brdp->bnkstataddr[banknr++] = ioaddr + 4 +
2147 ECH_PNLSTATUS;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002148 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002149 panelp->nrports = 8;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002150 } else {
Jiri Slaby615e4a72006-12-08 02:38:38 -08002151 panelp->uartp = &stl_cd1400uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002152 panelp->isr = stl_cd1400echintr;
2153 if (status & ECH_PNL16PORT) {
2154 panelp->nrports = 16;
2155 panelp->ackmask = 0x80;
2156 if (brdp->brdtype != BRD_ECHPCI)
2157 ioaddr += EREG_BANKSIZE;
2158 brdp->bnk2panel[banknr] = panelp;
2159 brdp->bnkpageaddr[banknr] = ++nxtid;
2160 brdp->bnkstataddr[banknr++] = ioaddr +
2161 ECH_PNLSTATUS;
2162 } else {
2163 panelp->nrports = 8;
2164 panelp->ackmask = 0xc0;
2165 }
2166 }
2167
2168 nxtid++;
2169 ioaddr += EREG_BANKSIZE;
2170 brdp->nrports += panelp->nrports;
2171 brdp->panels[panelnr++] = panelp;
2172 if ((brdp->brdtype != BRD_ECHPCI) &&
Jiri Slaby49277b12007-06-08 13:46:53 -07002173 (ioaddr >= (brdp->ioaddr2 + brdp->iosize2))) {
2174 retval = -EINVAL;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002175 goto err_fr;
Jiri Slaby49277b12007-06-08 13:46:53 -07002176 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002177 }
2178
2179 brdp->nrpanels = panelnr;
2180 brdp->nrbnks = banknr;
2181 if (brdp->brdtype == BRD_ECH)
2182 outb((brdp->ioctrlval | ECH_BRDDISABLE), brdp->ioctrl);
2183
2184 brdp->state |= BRD_FOUND;
Thomas Gleixner0f2ed4c2006-07-01 19:29:33 -07002185 if (request_irq(brdp->irq, stl_intr, IRQF_SHARED, name, brdp) != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002186 printk("STALLION: failed to register interrupt "
2187 "routine for %s irq=%d\n", name, brdp->irq);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002188 retval = -ENODEV;
2189 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002190 }
2191
Jiri Slaby3b85b342006-12-08 02:39:10 -08002192 return 0;
2193err_fr:
2194 stl_cleanup_panels(brdp);
2195 if (brdp->iosize2 > 0)
2196 release_region(brdp->ioaddr2, brdp->iosize2);
2197err_rel1:
2198 release_region(brdp->ioaddr1, brdp->iosize1);
2199err:
2200 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002201}
2202
2203/*****************************************************************************/
2204
2205/*
2206 * Initialize and configure the specified board.
2207 * Scan through all the boards in the configuration and see what we
2208 * can find. Handle EIO and the ECH boards a little differently here
2209 * since the initial search and setup is very different.
2210 */
2211
Jiri Slaby705c1862006-12-08 02:39:11 -08002212static int __devinit stl_brdinit(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002213{
Jiri Slaby3b85b342006-12-08 02:39:10 -08002214 int i, retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002215
Jiri Slabya0564e12006-12-08 02:38:37 -08002216 pr_debug("stl_brdinit(brdp=%p)\n", brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002217
2218 switch (brdp->brdtype) {
2219 case BRD_EASYIO:
2220 case BRD_EASYIOPCI:
Jiri Slaby3b85b342006-12-08 02:39:10 -08002221 retval = stl_initeio(brdp);
2222 if (retval)
2223 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002224 break;
2225 case BRD_ECH:
2226 case BRD_ECHMC:
2227 case BRD_ECHPCI:
2228 case BRD_ECH64PCI:
Jiri Slaby3b85b342006-12-08 02:39:10 -08002229 retval = stl_initech(brdp);
2230 if (retval)
2231 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002232 break;
2233 default:
2234 printk("STALLION: board=%d is unknown board type=%d\n",
2235 brdp->brdnr, brdp->brdtype);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002236 retval = -ENODEV;
2237 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002238 }
2239
Linus Torvalds1da177e2005-04-16 15:20:36 -07002240 if ((brdp->state & BRD_FOUND) == 0) {
2241 printk("STALLION: %s board not found, board=%d io=%x irq=%d\n",
2242 stl_brdnames[brdp->brdtype], brdp->brdnr,
2243 brdp->ioaddr1, brdp->irq);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002244 goto err_free;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002245 }
2246
Jiri Slabyc62429d2006-12-08 02:39:14 -08002247 for (i = 0; i < STL_MAXPANELS; i++)
Jiri Slaby615e4a72006-12-08 02:38:38 -08002248 if (brdp->panels[i] != NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002249 stl_initports(brdp, brdp->panels[i]);
2250
2251 printk("STALLION: %s found, board=%d io=%x irq=%d "
2252 "nrpanels=%d nrports=%d\n", stl_brdnames[brdp->brdtype],
2253 brdp->brdnr, brdp->ioaddr1, brdp->irq, brdp->nrpanels,
2254 brdp->nrports);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002255
2256 return 0;
2257err_free:
2258 free_irq(brdp->irq, brdp);
2259
2260 stl_cleanup_panels(brdp);
2261
2262 release_region(brdp->ioaddr1, brdp->iosize1);
2263 if (brdp->iosize2 > 0)
2264 release_region(brdp->ioaddr2, brdp->iosize2);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002265err:
2266 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002267}
2268
2269/*****************************************************************************/
2270
2271/*
2272 * Find the next available board number that is free.
2273 */
2274
Jiri Slaby705c1862006-12-08 02:39:11 -08002275static int __devinit stl_getbrdnr(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002276{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002277 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002278
Jiri Slabyc62429d2006-12-08 02:39:14 -08002279 for (i = 0; i < STL_MAXBRDS; i++)
Jiri Slaby615e4a72006-12-08 02:38:38 -08002280 if (stl_brds[i] == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002281 if (i >= stl_nrbrds)
2282 stl_nrbrds = i + 1;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002283 return i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002284 }
Jiri Slabyc62429d2006-12-08 02:39:14 -08002285
2286 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002287}
2288
2289/*****************************************************************************/
Linus Torvalds1da177e2005-04-16 15:20:36 -07002290/*
2291 * We have a Stallion board. Allocate a board structure and
2292 * initialize it. Read its IO and IRQ resources from PCI
2293 * configuration space.
2294 */
2295
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002296static int __devinit stl_pciprobe(struct pci_dev *pdev,
2297 const struct pci_device_id *ent)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002298{
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002299 struct stlbrd *brdp;
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08002300 unsigned int i, brdtype = ent->driver_data;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002301 int brdnr, retval = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002302
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002303 if ((pdev->class >> 8) == PCI_CLASS_STORAGE_IDE)
Jiri Slaby3b85b342006-12-08 02:39:10 -08002304 goto err;
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002305
Jiri Slaby3b85b342006-12-08 02:39:10 -08002306 retval = pci_enable_device(pdev);
2307 if (retval)
2308 goto err;
2309 brdp = stl_allocbrd();
2310 if (brdp == NULL) {
2311 retval = -ENOMEM;
2312 goto err;
2313 }
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002314 mutex_lock(&stl_brdslock);
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002315 brdnr = stl_getbrdnr();
2316 if (brdnr < 0) {
Jiri Slabyfefaf9a2006-12-08 02:39:09 -08002317 dev_err(&pdev->dev, "too many boards found, "
Linus Torvalds1da177e2005-04-16 15:20:36 -07002318 "maximum supported %d\n", STL_MAXBRDS);
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002319 mutex_unlock(&stl_brdslock);
Jiri Slaby49277b12007-06-08 13:46:53 -07002320 retval = -ENODEV;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002321 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002322 }
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002323 brdp->brdnr = (unsigned int)brdnr;
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002324 stl_brds[brdp->brdnr] = brdp;
2325 mutex_unlock(&stl_brdslock);
2326
Linus Torvalds1da177e2005-04-16 15:20:36 -07002327 brdp->brdtype = brdtype;
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08002328 brdp->state |= STL_PROBED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002329
2330/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002331 * We have all resources from the board, so let's setup the actual
2332 * board structure now.
2333 */
2334 switch (brdtype) {
2335 case BRD_ECHPCI:
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002336 brdp->ioaddr2 = pci_resource_start(pdev, 0);
2337 brdp->ioaddr1 = pci_resource_start(pdev, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002338 break;
2339 case BRD_ECH64PCI:
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002340 brdp->ioaddr2 = pci_resource_start(pdev, 2);
2341 brdp->ioaddr1 = pci_resource_start(pdev, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002342 break;
2343 case BRD_EASYIOPCI:
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002344 brdp->ioaddr1 = pci_resource_start(pdev, 2);
2345 brdp->ioaddr2 = pci_resource_start(pdev, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002346 break;
2347 default:
Jiri Slabyfefaf9a2006-12-08 02:39:09 -08002348 dev_err(&pdev->dev, "unknown PCI board type=%u\n", brdtype);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002349 break;
2350 }
2351
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002352 brdp->irq = pdev->irq;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002353 retval = stl_brdinit(brdp);
2354 if (retval)
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002355 goto err_null;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002356
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002357 pci_set_drvdata(pdev, brdp);
2358
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08002359 for (i = 0; i < brdp->nrports; i++)
2360 tty_register_device(stl_serial,
2361 brdp->brdnr * STL_MAXPORTS + i, &pdev->dev);
2362
Jiri Slaby3b85b342006-12-08 02:39:10 -08002363 return 0;
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002364err_null:
2365 stl_brds[brdp->brdnr] = NULL;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002366err_fr:
2367 kfree(brdp);
2368err:
2369 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002370}
2371
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002372static void __devexit stl_pciremove(struct pci_dev *pdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002373{
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002374 struct stlbrd *brdp = pci_get_drvdata(pdev);
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08002375 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002376
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002377 free_irq(brdp->irq, brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002378
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002379 stl_cleanup_panels(brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002380
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002381 release_region(brdp->ioaddr1, brdp->iosize1);
2382 if (brdp->iosize2 > 0)
2383 release_region(brdp->ioaddr2, brdp->iosize2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002384
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08002385 for (i = 0; i < brdp->nrports; i++)
2386 tty_unregister_device(stl_serial,
2387 brdp->brdnr * STL_MAXPORTS + i);
2388
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002389 stl_brds[brdp->brdnr] = NULL;
2390 kfree(brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002391}
2392
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002393static struct pci_driver stl_pcidriver = {
2394 .name = "stallion",
2395 .id_table = stl_pcibrds,
2396 .probe = stl_pciprobe,
2397 .remove = __devexit_p(stl_pciremove)
2398};
Linus Torvalds1da177e2005-04-16 15:20:36 -07002399
2400/*****************************************************************************/
2401
2402/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002403 * Return the board stats structure to user app.
2404 */
2405
2406static int stl_getbrdstats(combrd_t __user *bp)
2407{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002408 combrd_t stl_brdstats;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002409 struct stlbrd *brdp;
2410 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002411 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002412
2413 if (copy_from_user(&stl_brdstats, bp, sizeof(combrd_t)))
2414 return -EFAULT;
2415 if (stl_brdstats.brd >= STL_MAXBRDS)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002416 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002417 brdp = stl_brds[stl_brdstats.brd];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002418 if (brdp == NULL)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002419 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002420
2421 memset(&stl_brdstats, 0, sizeof(combrd_t));
2422 stl_brdstats.brd = brdp->brdnr;
2423 stl_brdstats.type = brdp->brdtype;
2424 stl_brdstats.hwid = brdp->hwid;
2425 stl_brdstats.state = brdp->state;
2426 stl_brdstats.ioaddr = brdp->ioaddr1;
2427 stl_brdstats.ioaddr2 = brdp->ioaddr2;
2428 stl_brdstats.irq = brdp->irq;
2429 stl_brdstats.nrpanels = brdp->nrpanels;
2430 stl_brdstats.nrports = brdp->nrports;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002431 for (i = 0; i < brdp->nrpanels; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002432 panelp = brdp->panels[i];
2433 stl_brdstats.panels[i].panel = i;
2434 stl_brdstats.panels[i].hwid = panelp->hwid;
2435 stl_brdstats.panels[i].nrports = panelp->nrports;
2436 }
2437
2438 return copy_to_user(bp, &stl_brdstats, sizeof(combrd_t)) ? -EFAULT : 0;
2439}
2440
2441/*****************************************************************************/
2442
2443/*
2444 * Resolve the referenced port number into a port struct pointer.
2445 */
2446
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002447static struct stlport *stl_getport(int brdnr, int panelnr, int portnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002448{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002449 struct stlbrd *brdp;
2450 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002451
Jiri Slabyc62429d2006-12-08 02:39:14 -08002452 if (brdnr < 0 || brdnr >= STL_MAXBRDS)
2453 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002454 brdp = stl_brds[brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002455 if (brdp == NULL)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002456 return NULL;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002457 if (panelnr < 0 || (unsigned int)panelnr >= brdp->nrpanels)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002458 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002459 panelp = brdp->panels[panelnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002460 if (panelp == NULL)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002461 return NULL;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002462 if (portnr < 0 || (unsigned int)portnr >= panelp->nrports)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002463 return NULL;
2464 return panelp->ports[portnr];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002465}
2466
2467/*****************************************************************************/
2468
2469/*
2470 * Return the port stats structure to user app. A NULL port struct
2471 * pointer passed in means that we need to find out from the app
2472 * what port to get stats for (used through board control device).
2473 */
2474
Alan Coxd18a7502008-10-13 10:40:07 +01002475static int stl_getportstats(struct tty_struct *tty, struct stlport *portp, comstats_t __user *cp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002476{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002477 comstats_t stl_comstats;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002478 unsigned char *head, *tail;
2479 unsigned long flags;
2480
2481 if (!portp) {
2482 if (copy_from_user(&stl_comstats, cp, sizeof(comstats_t)))
2483 return -EFAULT;
2484 portp = stl_getport(stl_comstats.brd, stl_comstats.panel,
2485 stl_comstats.port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08002486 if (portp == NULL)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002487 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002488 }
2489
2490 portp->stats.state = portp->istate;
Alan Coxf8ae4762008-07-16 21:56:37 +01002491 portp->stats.flags = portp->port.flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002492 portp->stats.hwid = portp->hwid;
2493
2494 portp->stats.ttystate = 0;
2495 portp->stats.cflags = 0;
2496 portp->stats.iflags = 0;
2497 portp->stats.oflags = 0;
2498 portp->stats.lflags = 0;
2499 portp->stats.rxbuffered = 0;
2500
Alan Coxb65b5b52006-06-27 02:54:05 -07002501 spin_lock_irqsave(&stallion_lock, flags);
Alan Coxd18a7502008-10-13 10:40:07 +01002502 if (tty != NULL && portp->port.tty == tty) {
2503 portp->stats.ttystate = tty->flags;
2504 /* No longer available as a statistic */
2505 portp->stats.rxbuffered = 1; /*tty->flip.count; */
2506 if (tty->termios != NULL) {
2507 portp->stats.cflags = tty->termios->c_cflag;
2508 portp->stats.iflags = tty->termios->c_iflag;
2509 portp->stats.oflags = tty->termios->c_oflag;
2510 portp->stats.lflags = tty->termios->c_lflag;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002511 }
Alan Coxd18a7502008-10-13 10:40:07 +01002512 }
Alan Coxb65b5b52006-06-27 02:54:05 -07002513 spin_unlock_irqrestore(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002514
2515 head = portp->tx.head;
2516 tail = portp->tx.tail;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002517 portp->stats.txbuffered = (head >= tail) ? (head - tail) :
2518 (STL_TXBUFSIZE - (tail - head));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002519
2520 portp->stats.signals = (unsigned long) stl_getsignals(portp);
2521
2522 return copy_to_user(cp, &portp->stats,
2523 sizeof(comstats_t)) ? -EFAULT : 0;
2524}
2525
2526/*****************************************************************************/
2527
2528/*
2529 * Clear the port stats structure. We also return it zeroed out...
2530 */
2531
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002532static int stl_clrportstats(struct stlport *portp, comstats_t __user *cp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002533{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002534 comstats_t stl_comstats;
2535
Linus Torvalds1da177e2005-04-16 15:20:36 -07002536 if (!portp) {
2537 if (copy_from_user(&stl_comstats, cp, sizeof(comstats_t)))
2538 return -EFAULT;
2539 portp = stl_getport(stl_comstats.brd, stl_comstats.panel,
2540 stl_comstats.port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08002541 if (portp == NULL)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002542 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002543 }
2544
2545 memset(&portp->stats, 0, sizeof(comstats_t));
2546 portp->stats.brd = portp->brdnr;
2547 portp->stats.panel = portp->panelnr;
2548 portp->stats.port = portp->portnr;
2549 return copy_to_user(cp, &portp->stats,
2550 sizeof(comstats_t)) ? -EFAULT : 0;
2551}
2552
2553/*****************************************************************************/
2554
2555/*
2556 * Return the entire driver ports structure to a user app.
2557 */
2558
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002559static int stl_getportstruct(struct stlport __user *arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002560{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002561 struct stlport stl_dummyport;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002562 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002563
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002564 if (copy_from_user(&stl_dummyport, arg, sizeof(struct stlport)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002565 return -EFAULT;
2566 portp = stl_getport(stl_dummyport.brdnr, stl_dummyport.panelnr,
2567 stl_dummyport.portnr);
2568 if (!portp)
2569 return -ENODEV;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002570 return copy_to_user(arg, portp, sizeof(struct stlport)) ? -EFAULT : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002571}
2572
2573/*****************************************************************************/
2574
2575/*
2576 * Return the entire driver board structure to a user app.
2577 */
2578
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002579static int stl_getbrdstruct(struct stlbrd __user *arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002580{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002581 struct stlbrd stl_dummybrd;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002582 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002583
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002584 if (copy_from_user(&stl_dummybrd, arg, sizeof(struct stlbrd)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002585 return -EFAULT;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002586 if (stl_dummybrd.brdnr >= STL_MAXBRDS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002587 return -ENODEV;
2588 brdp = stl_brds[stl_dummybrd.brdnr];
2589 if (!brdp)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002590 return -ENODEV;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002591 return copy_to_user(arg, brdp, sizeof(struct stlbrd)) ? -EFAULT : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002592}
2593
2594/*****************************************************************************/
2595
2596/*
2597 * The "staliomem" device is also required to do some special operations
2598 * on the board and/or ports. In this driver it is mostly used for stats
2599 * collection.
2600 */
2601
2602static int stl_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg)
2603{
2604 int brdnr, rc;
2605 void __user *argp = (void __user *)arg;
2606
Jiri Slabya0564e12006-12-08 02:38:37 -08002607 pr_debug("stl_memioctl(ip=%p,fp=%p,cmd=%x,arg=%lx)\n", ip, fp, cmd,arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002608
2609 brdnr = iminor(ip);
2610 if (brdnr >= STL_MAXBRDS)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002611 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002612 rc = 0;
2613
2614 switch (cmd) {
2615 case COM_GETPORTSTATS:
Alan Coxd18a7502008-10-13 10:40:07 +01002616 rc = stl_getportstats(NULL, NULL, argp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002617 break;
2618 case COM_CLRPORTSTATS:
2619 rc = stl_clrportstats(NULL, argp);
2620 break;
2621 case COM_GETBRDSTATS:
2622 rc = stl_getbrdstats(argp);
2623 break;
2624 case COM_READPORT:
2625 rc = stl_getportstruct(argp);
2626 break;
2627 case COM_READBOARD:
2628 rc = stl_getbrdstruct(argp);
2629 break;
2630 default:
2631 rc = -ENOIOCTLCMD;
2632 break;
2633 }
2634
Jiri Slabyc62429d2006-12-08 02:39:14 -08002635 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002636}
2637
Jeff Dikeb68e31d2006-10-02 02:17:18 -07002638static const struct tty_operations stl_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002639 .open = stl_open,
2640 .close = stl_close,
2641 .write = stl_write,
2642 .put_char = stl_putchar,
2643 .flush_chars = stl_flushchars,
2644 .write_room = stl_writeroom,
2645 .chars_in_buffer = stl_charsinbuffer,
2646 .ioctl = stl_ioctl,
2647 .set_termios = stl_settermios,
2648 .throttle = stl_throttle,
2649 .unthrottle = stl_unthrottle,
2650 .stop = stl_stop,
2651 .start = stl_start,
2652 .hangup = stl_hangup,
2653 .flush_buffer = stl_flushbuffer,
2654 .break_ctl = stl_breakctl,
2655 .wait_until_sent = stl_waituntilsent,
2656 .send_xchar = stl_sendxchar,
2657 .read_proc = stl_readproc,
2658 .tiocmget = stl_tiocmget,
2659 .tiocmset = stl_tiocmset,
2660};
2661
2662/*****************************************************************************/
Linus Torvalds1da177e2005-04-16 15:20:36 -07002663/* CD1400 HARDWARE FUNCTIONS */
2664/*****************************************************************************/
2665
2666/*
2667 * These functions get/set/update the registers of the cd1400 UARTs.
2668 * Access to the cd1400 registers is via an address/data io port pair.
2669 * (Maybe should make this inline...)
2670 */
2671
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002672static int stl_cd1400getreg(struct stlport *portp, int regnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002673{
2674 outb((regnr + portp->uartaddr), portp->ioaddr);
Jesper Juhl014c2542006-01-15 02:37:08 +01002675 return inb(portp->ioaddr + EREG_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002676}
2677
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002678static void stl_cd1400setreg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002679{
Jiri Slabyc62429d2006-12-08 02:39:14 -08002680 outb(regnr + portp->uartaddr, portp->ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002681 outb(value, portp->ioaddr + EREG_DATA);
2682}
2683
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002684static int stl_cd1400updatereg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002685{
Jiri Slabyc62429d2006-12-08 02:39:14 -08002686 outb(regnr + portp->uartaddr, portp->ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002687 if (inb(portp->ioaddr + EREG_DATA) != value) {
2688 outb(value, portp->ioaddr + EREG_DATA);
Jesper Juhl014c2542006-01-15 02:37:08 +01002689 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002690 }
Jesper Juhl014c2542006-01-15 02:37:08 +01002691 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002692}
2693
2694/*****************************************************************************/
2695
2696/*
2697 * Inbitialize the UARTs in a panel. We don't care what sort of board
2698 * these ports are on - since the port io registers are almost
2699 * identical when dealing with ports.
2700 */
2701
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002702static int stl_cd1400panelinit(struct stlbrd *brdp, struct stlpanel *panelp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002703{
2704 unsigned int gfrcr;
2705 int chipmask, i, j;
2706 int nrchips, uartaddr, ioaddr;
Alan Coxb65b5b52006-06-27 02:54:05 -07002707 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002708
Jiri Slabya0564e12006-12-08 02:38:37 -08002709 pr_debug("stl_panelinit(brdp=%p,panelp=%p)\n", brdp, panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002710
Alan Coxb65b5b52006-06-27 02:54:05 -07002711 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002712 BRDENABLE(panelp->brdnr, panelp->pagenr);
2713
2714/*
2715 * Check that each chip is present and started up OK.
2716 */
2717 chipmask = 0;
2718 nrchips = panelp->nrports / CD1400_PORTS;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002719 for (i = 0; i < nrchips; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002720 if (brdp->brdtype == BRD_ECHPCI) {
2721 outb((panelp->pagenr + (i >> 1)), brdp->ioctrl);
2722 ioaddr = panelp->iobase;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002723 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002724 ioaddr = panelp->iobase + (EREG_BANKSIZE * (i >> 1));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002725 uartaddr = (i & 0x01) ? 0x080 : 0;
2726 outb((GFRCR + uartaddr), ioaddr);
2727 outb(0, (ioaddr + EREG_DATA));
2728 outb((CCR + uartaddr), ioaddr);
2729 outb(CCR_RESETFULL, (ioaddr + EREG_DATA));
2730 outb(CCR_RESETFULL, (ioaddr + EREG_DATA));
2731 outb((GFRCR + uartaddr), ioaddr);
Jiri Slabyc62429d2006-12-08 02:39:14 -08002732 for (j = 0; j < CCR_MAXWAIT; j++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002733 if ((gfrcr = inb(ioaddr + EREG_DATA)) != 0)
2734 break;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002735
Linus Torvalds1da177e2005-04-16 15:20:36 -07002736 if ((j >= CCR_MAXWAIT) || (gfrcr < 0x40) || (gfrcr > 0x60)) {
2737 printk("STALLION: cd1400 not responding, "
2738 "brd=%d panel=%d chip=%d\n",
2739 panelp->brdnr, panelp->panelnr, i);
2740 continue;
2741 }
2742 chipmask |= (0x1 << i);
2743 outb((PPR + uartaddr), ioaddr);
2744 outb(PPR_SCALAR, (ioaddr + EREG_DATA));
2745 }
2746
2747 BRDDISABLE(panelp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07002748 spin_unlock_irqrestore(&brd_lock, flags);
Jesper Juhl014c2542006-01-15 02:37:08 +01002749 return chipmask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002750}
2751
2752/*****************************************************************************/
2753
2754/*
2755 * Initialize hardware specific port registers.
2756 */
2757
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002758static void stl_cd1400portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002759{
Alan Coxb65b5b52006-06-27 02:54:05 -07002760 unsigned long flags;
Jiri Slabya0564e12006-12-08 02:38:37 -08002761 pr_debug("stl_cd1400portinit(brdp=%p,panelp=%p,portp=%p)\n", brdp,
2762 panelp, portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002763
Jiri Slaby615e4a72006-12-08 02:38:38 -08002764 if ((brdp == NULL) || (panelp == NULL) ||
2765 (portp == NULL))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002766 return;
2767
Alan Coxb65b5b52006-06-27 02:54:05 -07002768 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002769 portp->ioaddr = panelp->iobase + (((brdp->brdtype == BRD_ECHPCI) ||
2770 (portp->portnr < 8)) ? 0 : EREG_BANKSIZE);
2771 portp->uartaddr = (portp->portnr & 0x04) << 5;
2772 portp->pagenr = panelp->pagenr + (portp->portnr >> 3);
2773
2774 BRDENABLE(portp->brdnr, portp->pagenr);
2775 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
2776 stl_cd1400setreg(portp, LIVR, (portp->portnr << 3));
2777 portp->hwid = stl_cd1400getreg(portp, GFRCR);
2778 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07002779 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002780}
2781
2782/*****************************************************************************/
2783
2784/*
2785 * Wait for the command register to be ready. We will poll this,
2786 * since it won't usually take too long to be ready.
2787 */
2788
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002789static void stl_cd1400ccrwait(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002790{
2791 int i;
2792
Jiri Slabyc62429d2006-12-08 02:39:14 -08002793 for (i = 0; i < CCR_MAXWAIT; i++)
2794 if (stl_cd1400getreg(portp, CCR) == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002795 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002796
2797 printk("STALLION: cd1400 not responding, port=%d panel=%d brd=%d\n",
2798 portp->portnr, portp->panelnr, portp->brdnr);
2799}
2800
2801/*****************************************************************************/
2802
2803/*
2804 * Set up the cd1400 registers for a port based on the termios port
2805 * settings.
2806 */
2807
Alan Cox606d0992006-12-08 02:38:45 -08002808static void stl_cd1400setport(struct stlport *portp, struct ktermios *tiosp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002809{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002810 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002811 unsigned long flags;
2812 unsigned int clkdiv, baudrate;
2813 unsigned char cor1, cor2, cor3;
2814 unsigned char cor4, cor5, ccr;
2815 unsigned char srer, sreron, sreroff;
2816 unsigned char mcor1, mcor2, rtpr;
2817 unsigned char clk, div;
2818
2819 cor1 = 0;
2820 cor2 = 0;
2821 cor3 = 0;
2822 cor4 = 0;
2823 cor5 = 0;
2824 ccr = 0;
2825 rtpr = 0;
2826 clk = 0;
2827 div = 0;
2828 mcor1 = 0;
2829 mcor2 = 0;
2830 sreron = 0;
2831 sreroff = 0;
2832
2833 brdp = stl_brds[portp->brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002834 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002835 return;
2836
2837/*
2838 * Set up the RX char ignore mask with those RX error types we
2839 * can ignore. We can get the cd1400 to help us out a little here,
2840 * it will ignore parity errors and breaks for us.
2841 */
2842 portp->rxignoremsk = 0;
2843 if (tiosp->c_iflag & IGNPAR) {
2844 portp->rxignoremsk |= (ST_PARITY | ST_FRAMING | ST_OVERRUN);
2845 cor1 |= COR1_PARIGNORE;
2846 }
2847 if (tiosp->c_iflag & IGNBRK) {
2848 portp->rxignoremsk |= ST_BREAK;
2849 cor4 |= COR4_IGNBRK;
2850 }
2851
2852 portp->rxmarkmsk = ST_OVERRUN;
2853 if (tiosp->c_iflag & (INPCK | PARMRK))
2854 portp->rxmarkmsk |= (ST_PARITY | ST_FRAMING);
2855 if (tiosp->c_iflag & BRKINT)
2856 portp->rxmarkmsk |= ST_BREAK;
2857
2858/*
2859 * Go through the char size, parity and stop bits and set all the
2860 * option register appropriately.
2861 */
2862 switch (tiosp->c_cflag & CSIZE) {
2863 case CS5:
2864 cor1 |= COR1_CHL5;
2865 break;
2866 case CS6:
2867 cor1 |= COR1_CHL6;
2868 break;
2869 case CS7:
2870 cor1 |= COR1_CHL7;
2871 break;
2872 default:
2873 cor1 |= COR1_CHL8;
2874 break;
2875 }
2876
2877 if (tiosp->c_cflag & CSTOPB)
2878 cor1 |= COR1_STOP2;
2879 else
2880 cor1 |= COR1_STOP1;
2881
2882 if (tiosp->c_cflag & PARENB) {
2883 if (tiosp->c_cflag & PARODD)
2884 cor1 |= (COR1_PARENB | COR1_PARODD);
2885 else
2886 cor1 |= (COR1_PARENB | COR1_PAREVEN);
2887 } else {
2888 cor1 |= COR1_PARNONE;
2889 }
2890
2891/*
2892 * Set the RX FIFO threshold at 6 chars. This gives a bit of breathing
2893 * space for hardware flow control and the like. This should be set to
2894 * VMIN. Also here we will set the RX data timeout to 10ms - this should
2895 * really be based on VTIME.
2896 */
2897 cor3 |= FIFO_RXTHRESHOLD;
2898 rtpr = 2;
2899
2900/*
2901 * Calculate the baud rate timers. For now we will just assume that
2902 * the input and output baud are the same. Could have used a baud
2903 * table here, but this way we can generate virtually any baud rate
2904 * we like!
2905 */
2906 baudrate = tiosp->c_cflag & CBAUD;
2907 if (baudrate & CBAUDEX) {
2908 baudrate &= ~CBAUDEX;
2909 if ((baudrate < 1) || (baudrate > 4))
2910 tiosp->c_cflag &= ~CBAUDEX;
2911 else
2912 baudrate += 15;
2913 }
2914 baudrate = stl_baudrates[baudrate];
2915 if ((tiosp->c_cflag & CBAUD) == B38400) {
Alan Coxf8ae4762008-07-16 21:56:37 +01002916 if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002917 baudrate = 57600;
Alan Coxf8ae4762008-07-16 21:56:37 +01002918 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002919 baudrate = 115200;
Alan Coxf8ae4762008-07-16 21:56:37 +01002920 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002921 baudrate = 230400;
Alan Coxf8ae4762008-07-16 21:56:37 +01002922 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002923 baudrate = 460800;
Alan Coxf8ae4762008-07-16 21:56:37 +01002924 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002925 baudrate = (portp->baud_base / portp->custom_divisor);
2926 }
2927 if (baudrate > STL_CD1400MAXBAUD)
2928 baudrate = STL_CD1400MAXBAUD;
2929
2930 if (baudrate > 0) {
Jiri Slabyc62429d2006-12-08 02:39:14 -08002931 for (clk = 0; clk < CD1400_NUMCLKS; clk++) {
2932 clkdiv = (portp->clk / stl_cd1400clkdivs[clk]) / baudrate;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002933 if (clkdiv < 0x100)
2934 break;
2935 }
2936 div = (unsigned char) clkdiv;
2937 }
2938
2939/*
2940 * Check what form of modem signaling is required and set it up.
2941 */
2942 if ((tiosp->c_cflag & CLOCAL) == 0) {
2943 mcor1 |= MCOR1_DCD;
2944 mcor2 |= MCOR2_DCD;
2945 sreron |= SRER_MODEM;
Alan Coxf8ae4762008-07-16 21:56:37 +01002946 portp->port.flags |= ASYNC_CHECK_CD;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002947 } else
Alan Coxf8ae4762008-07-16 21:56:37 +01002948 portp->port.flags &= ~ASYNC_CHECK_CD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002949
2950/*
2951 * Setup cd1400 enhanced modes if we can. In particular we want to
2952 * handle as much of the flow control as possible automatically. As
2953 * well as saving a few CPU cycles it will also greatly improve flow
2954 * control reliability.
2955 */
2956 if (tiosp->c_iflag & IXON) {
2957 cor2 |= COR2_TXIBE;
2958 cor3 |= COR3_SCD12;
2959 if (tiosp->c_iflag & IXANY)
2960 cor2 |= COR2_IXM;
2961 }
2962
2963 if (tiosp->c_cflag & CRTSCTS) {
2964 cor2 |= COR2_CTSAE;
2965 mcor1 |= FIFO_RTSTHRESHOLD;
2966 }
2967
2968/*
2969 * All cd1400 register values calculated so go through and set
2970 * them all up.
2971 */
2972
Jiri Slabya0564e12006-12-08 02:38:37 -08002973 pr_debug("SETPORT: portnr=%d panelnr=%d brdnr=%d\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002974 portp->portnr, portp->panelnr, portp->brdnr);
Jiri Slabya0564e12006-12-08 02:38:37 -08002975 pr_debug(" cor1=%x cor2=%x cor3=%x cor4=%x cor5=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002976 cor1, cor2, cor3, cor4, cor5);
Jiri Slabya0564e12006-12-08 02:38:37 -08002977 pr_debug(" mcor1=%x mcor2=%x rtpr=%x sreron=%x sreroff=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002978 mcor1, mcor2, rtpr, sreron, sreroff);
Jiri Slabya0564e12006-12-08 02:38:37 -08002979 pr_debug(" tcor=%x tbpr=%x rcor=%x rbpr=%x\n", clk, div, clk, div);
2980 pr_debug(" schr1=%x schr2=%x schr3=%x schr4=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002981 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP],
2982 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002983
Alan Coxb65b5b52006-06-27 02:54:05 -07002984 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002985 BRDENABLE(portp->brdnr, portp->pagenr);
2986 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x3));
2987 srer = stl_cd1400getreg(portp, SRER);
2988 stl_cd1400setreg(portp, SRER, 0);
2989 if (stl_cd1400updatereg(portp, COR1, cor1))
2990 ccr = 1;
2991 if (stl_cd1400updatereg(portp, COR2, cor2))
2992 ccr = 1;
2993 if (stl_cd1400updatereg(portp, COR3, cor3))
2994 ccr = 1;
2995 if (ccr) {
2996 stl_cd1400ccrwait(portp);
2997 stl_cd1400setreg(portp, CCR, CCR_CORCHANGE);
2998 }
2999 stl_cd1400setreg(portp, COR4, cor4);
3000 stl_cd1400setreg(portp, COR5, cor5);
3001 stl_cd1400setreg(portp, MCOR1, mcor1);
3002 stl_cd1400setreg(portp, MCOR2, mcor2);
3003 if (baudrate > 0) {
3004 stl_cd1400setreg(portp, TCOR, clk);
3005 stl_cd1400setreg(portp, TBPR, div);
3006 stl_cd1400setreg(portp, RCOR, clk);
3007 stl_cd1400setreg(portp, RBPR, div);
3008 }
3009 stl_cd1400setreg(portp, SCHR1, tiosp->c_cc[VSTART]);
3010 stl_cd1400setreg(portp, SCHR2, tiosp->c_cc[VSTOP]);
3011 stl_cd1400setreg(portp, SCHR3, tiosp->c_cc[VSTART]);
3012 stl_cd1400setreg(portp, SCHR4, tiosp->c_cc[VSTOP]);
3013 stl_cd1400setreg(portp, RTPR, rtpr);
3014 mcor1 = stl_cd1400getreg(portp, MSVR1);
3015 if (mcor1 & MSVR1_DCD)
3016 portp->sigs |= TIOCM_CD;
3017 else
3018 portp->sigs &= ~TIOCM_CD;
3019 stl_cd1400setreg(portp, SRER, ((srer & ~sreroff) | sreron));
3020 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003021 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003022}
3023
3024/*****************************************************************************/
3025
3026/*
3027 * Set the state of the DTR and RTS signals.
3028 */
3029
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003030static void stl_cd1400setsignals(struct stlport *portp, int dtr, int rts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003031{
3032 unsigned char msvr1, msvr2;
3033 unsigned long flags;
3034
Jiri Slabya0564e12006-12-08 02:38:37 -08003035 pr_debug("stl_cd1400setsignals(portp=%p,dtr=%d,rts=%d)\n",
3036 portp, dtr, rts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003037
3038 msvr1 = 0;
3039 msvr2 = 0;
3040 if (dtr > 0)
3041 msvr1 = MSVR1_DTR;
3042 if (rts > 0)
3043 msvr2 = MSVR2_RTS;
3044
Alan Coxb65b5b52006-06-27 02:54:05 -07003045 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003046 BRDENABLE(portp->brdnr, portp->pagenr);
3047 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3048 if (rts >= 0)
3049 stl_cd1400setreg(portp, MSVR2, msvr2);
3050 if (dtr >= 0)
3051 stl_cd1400setreg(portp, MSVR1, msvr1);
3052 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003053 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003054}
3055
3056/*****************************************************************************/
3057
3058/*
3059 * Return the state of the signals.
3060 */
3061
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003062static int stl_cd1400getsignals(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003063{
3064 unsigned char msvr1, msvr2;
3065 unsigned long flags;
3066 int sigs;
3067
Jiri Slabya0564e12006-12-08 02:38:37 -08003068 pr_debug("stl_cd1400getsignals(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003069
Alan Coxb65b5b52006-06-27 02:54:05 -07003070 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003071 BRDENABLE(portp->brdnr, portp->pagenr);
3072 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3073 msvr1 = stl_cd1400getreg(portp, MSVR1);
3074 msvr2 = stl_cd1400getreg(portp, MSVR2);
3075 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003076 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003077
3078 sigs = 0;
3079 sigs |= (msvr1 & MSVR1_DCD) ? TIOCM_CD : 0;
3080 sigs |= (msvr1 & MSVR1_CTS) ? TIOCM_CTS : 0;
3081 sigs |= (msvr1 & MSVR1_DTR) ? TIOCM_DTR : 0;
3082 sigs |= (msvr2 & MSVR2_RTS) ? TIOCM_RTS : 0;
3083#if 0
3084 sigs |= (msvr1 & MSVR1_RI) ? TIOCM_RI : 0;
3085 sigs |= (msvr1 & MSVR1_DSR) ? TIOCM_DSR : 0;
3086#else
3087 sigs |= TIOCM_DSR;
3088#endif
Jesper Juhl014c2542006-01-15 02:37:08 +01003089 return sigs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003090}
3091
3092/*****************************************************************************/
3093
3094/*
3095 * Enable/Disable the Transmitter and/or Receiver.
3096 */
3097
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003098static void stl_cd1400enablerxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003099{
3100 unsigned char ccr;
3101 unsigned long flags;
3102
Jiri Slabya0564e12006-12-08 02:38:37 -08003103 pr_debug("stl_cd1400enablerxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
3104
Linus Torvalds1da177e2005-04-16 15:20:36 -07003105 ccr = 0;
3106
3107 if (tx == 0)
3108 ccr |= CCR_TXDISABLE;
3109 else if (tx > 0)
3110 ccr |= CCR_TXENABLE;
3111 if (rx == 0)
3112 ccr |= CCR_RXDISABLE;
3113 else if (rx > 0)
3114 ccr |= CCR_RXENABLE;
3115
Alan Coxb65b5b52006-06-27 02:54:05 -07003116 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003117 BRDENABLE(portp->brdnr, portp->pagenr);
3118 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3119 stl_cd1400ccrwait(portp);
3120 stl_cd1400setreg(portp, CCR, ccr);
3121 stl_cd1400ccrwait(portp);
3122 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003123 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003124}
3125
3126/*****************************************************************************/
3127
3128/*
3129 * Start/stop the Transmitter and/or Receiver.
3130 */
3131
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003132static void stl_cd1400startrxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003133{
3134 unsigned char sreron, sreroff;
3135 unsigned long flags;
3136
Jiri Slabya0564e12006-12-08 02:38:37 -08003137 pr_debug("stl_cd1400startrxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003138
3139 sreron = 0;
3140 sreroff = 0;
3141 if (tx == 0)
3142 sreroff |= (SRER_TXDATA | SRER_TXEMPTY);
3143 else if (tx == 1)
3144 sreron |= SRER_TXDATA;
3145 else if (tx >= 2)
3146 sreron |= SRER_TXEMPTY;
3147 if (rx == 0)
3148 sreroff |= SRER_RXDATA;
3149 else if (rx > 0)
3150 sreron |= SRER_RXDATA;
3151
Alan Coxb65b5b52006-06-27 02:54:05 -07003152 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003153 BRDENABLE(portp->brdnr, portp->pagenr);
3154 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3155 stl_cd1400setreg(portp, SRER,
3156 ((stl_cd1400getreg(portp, SRER) & ~sreroff) | sreron));
3157 BRDDISABLE(portp->brdnr);
3158 if (tx > 0)
3159 set_bit(ASYI_TXBUSY, &portp->istate);
Alan Coxb65b5b52006-06-27 02:54:05 -07003160 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003161}
3162
3163/*****************************************************************************/
3164
3165/*
3166 * Disable all interrupts from this port.
3167 */
3168
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003169static void stl_cd1400disableintrs(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003170{
3171 unsigned long flags;
3172
Jiri Slabya0564e12006-12-08 02:38:37 -08003173 pr_debug("stl_cd1400disableintrs(portp=%p)\n", portp);
3174
Alan Coxb65b5b52006-06-27 02:54:05 -07003175 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003176 BRDENABLE(portp->brdnr, portp->pagenr);
3177 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3178 stl_cd1400setreg(portp, SRER, 0);
3179 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003180 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003181}
3182
3183/*****************************************************************************/
3184
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003185static void stl_cd1400sendbreak(struct stlport *portp, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003186{
3187 unsigned long flags;
3188
Jiri Slabya0564e12006-12-08 02:38:37 -08003189 pr_debug("stl_cd1400sendbreak(portp=%p,len=%d)\n", portp, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003190
Alan Coxb65b5b52006-06-27 02:54:05 -07003191 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003192 BRDENABLE(portp->brdnr, portp->pagenr);
3193 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3194 stl_cd1400setreg(portp, SRER,
3195 ((stl_cd1400getreg(portp, SRER) & ~SRER_TXDATA) |
3196 SRER_TXEMPTY));
3197 BRDDISABLE(portp->brdnr);
3198 portp->brklen = len;
3199 if (len == 1)
3200 portp->stats.txbreaks++;
Alan Coxb65b5b52006-06-27 02:54:05 -07003201 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003202}
3203
3204/*****************************************************************************/
3205
3206/*
3207 * Take flow control actions...
3208 */
3209
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003210static void stl_cd1400flowctrl(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003211{
3212 struct tty_struct *tty;
3213 unsigned long flags;
3214
Jiri Slabya0564e12006-12-08 02:38:37 -08003215 pr_debug("stl_cd1400flowctrl(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003216
Jiri Slaby615e4a72006-12-08 02:38:38 -08003217 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003218 return;
Alan Coxd18a7502008-10-13 10:40:07 +01003219 tty = tty_port_tty_get(&portp->port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08003220 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003221 return;
3222
Alan Coxb65b5b52006-06-27 02:54:05 -07003223 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003224 BRDENABLE(portp->brdnr, portp->pagenr);
3225 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3226
3227 if (state) {
3228 if (tty->termios->c_iflag & IXOFF) {
3229 stl_cd1400ccrwait(portp);
3230 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR1);
3231 portp->stats.rxxon++;
3232 stl_cd1400ccrwait(portp);
3233 }
3234/*
3235 * Question: should we return RTS to what it was before? It may
3236 * have been set by an ioctl... Suppose not, since if you have
3237 * hardware flow control set then it is pretty silly to go and
3238 * set the RTS line by hand.
3239 */
3240 if (tty->termios->c_cflag & CRTSCTS) {
3241 stl_cd1400setreg(portp, MCOR1,
3242 (stl_cd1400getreg(portp, MCOR1) |
3243 FIFO_RTSTHRESHOLD));
3244 stl_cd1400setreg(portp, MSVR2, MSVR2_RTS);
3245 portp->stats.rxrtson++;
3246 }
3247 } else {
3248 if (tty->termios->c_iflag & IXOFF) {
3249 stl_cd1400ccrwait(portp);
3250 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR2);
3251 portp->stats.rxxoff++;
3252 stl_cd1400ccrwait(portp);
3253 }
3254 if (tty->termios->c_cflag & CRTSCTS) {
3255 stl_cd1400setreg(portp, MCOR1,
3256 (stl_cd1400getreg(portp, MCOR1) & 0xf0));
3257 stl_cd1400setreg(portp, MSVR2, 0);
3258 portp->stats.rxrtsoff++;
3259 }
3260 }
3261
3262 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003263 spin_unlock_irqrestore(&brd_lock, flags);
Alan Coxd18a7502008-10-13 10:40:07 +01003264 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003265}
3266
3267/*****************************************************************************/
3268
3269/*
3270 * Send a flow control character...
3271 */
3272
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003273static void stl_cd1400sendflow(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003274{
3275 struct tty_struct *tty;
3276 unsigned long flags;
3277
Jiri Slabya0564e12006-12-08 02:38:37 -08003278 pr_debug("stl_cd1400sendflow(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003279
Jiri Slaby615e4a72006-12-08 02:38:38 -08003280 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003281 return;
Alan Coxd18a7502008-10-13 10:40:07 +01003282 tty = tty_port_tty_get(&portp->port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08003283 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003284 return;
3285
Alan Coxb65b5b52006-06-27 02:54:05 -07003286 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003287 BRDENABLE(portp->brdnr, portp->pagenr);
3288 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3289 if (state) {
3290 stl_cd1400ccrwait(portp);
3291 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR1);
3292 portp->stats.rxxon++;
3293 stl_cd1400ccrwait(portp);
3294 } else {
3295 stl_cd1400ccrwait(portp);
3296 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR2);
3297 portp->stats.rxxoff++;
3298 stl_cd1400ccrwait(portp);
3299 }
3300 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003301 spin_unlock_irqrestore(&brd_lock, flags);
Alan Coxd18a7502008-10-13 10:40:07 +01003302 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003303}
3304
3305/*****************************************************************************/
3306
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003307static void stl_cd1400flush(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003308{
3309 unsigned long flags;
3310
Jiri Slabya0564e12006-12-08 02:38:37 -08003311 pr_debug("stl_cd1400flush(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003312
Jiri Slaby615e4a72006-12-08 02:38:38 -08003313 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003314 return;
3315
Alan Coxb65b5b52006-06-27 02:54:05 -07003316 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003317 BRDENABLE(portp->brdnr, portp->pagenr);
3318 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3319 stl_cd1400ccrwait(portp);
3320 stl_cd1400setreg(portp, CCR, CCR_TXFLUSHFIFO);
3321 stl_cd1400ccrwait(portp);
3322 portp->tx.tail = portp->tx.head;
3323 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003324 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003325}
3326
3327/*****************************************************************************/
3328
3329/*
3330 * Return the current state of data flow on this port. This is only
3331 * really interresting when determining if data has fully completed
3332 * transmission or not... This is easy for the cd1400, it accurately
3333 * maintains the busy port flag.
3334 */
3335
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003336static int stl_cd1400datastate(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003337{
Jiri Slabya0564e12006-12-08 02:38:37 -08003338 pr_debug("stl_cd1400datastate(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003339
Jiri Slaby615e4a72006-12-08 02:38:38 -08003340 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01003341 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003342
Jesper Juhl014c2542006-01-15 02:37:08 +01003343 return test_bit(ASYI_TXBUSY, &portp->istate) ? 1 : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003344}
3345
3346/*****************************************************************************/
3347
3348/*
3349 * Interrupt service routine for cd1400 EasyIO boards.
3350 */
3351
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003352static void stl_cd1400eiointr(struct stlpanel *panelp, unsigned int iobase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003353{
3354 unsigned char svrtype;
3355
Jiri Slabya0564e12006-12-08 02:38:37 -08003356 pr_debug("stl_cd1400eiointr(panelp=%p,iobase=%x)\n", panelp, iobase);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003357
Alan Coxb65b5b52006-06-27 02:54:05 -07003358 spin_lock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003359 outb(SVRR, iobase);
3360 svrtype = inb(iobase + EREG_DATA);
3361 if (panelp->nrports > 4) {
3362 outb((SVRR + 0x80), iobase);
3363 svrtype |= inb(iobase + EREG_DATA);
3364 }
3365
3366 if (svrtype & SVRR_RX)
3367 stl_cd1400rxisr(panelp, iobase);
3368 else if (svrtype & SVRR_TX)
3369 stl_cd1400txisr(panelp, iobase);
3370 else if (svrtype & SVRR_MDM)
3371 stl_cd1400mdmisr(panelp, iobase);
Alan Coxb65b5b52006-06-27 02:54:05 -07003372
3373 spin_unlock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003374}
3375
3376/*****************************************************************************/
3377
3378/*
3379 * Interrupt service routine for cd1400 panels.
3380 */
3381
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003382static void stl_cd1400echintr(struct stlpanel *panelp, unsigned int iobase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003383{
3384 unsigned char svrtype;
3385
Jiri Slabya0564e12006-12-08 02:38:37 -08003386 pr_debug("stl_cd1400echintr(panelp=%p,iobase=%x)\n", panelp, iobase);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003387
3388 outb(SVRR, iobase);
3389 svrtype = inb(iobase + EREG_DATA);
3390 outb((SVRR + 0x80), iobase);
3391 svrtype |= inb(iobase + EREG_DATA);
3392 if (svrtype & SVRR_RX)
3393 stl_cd1400rxisr(panelp, iobase);
3394 else if (svrtype & SVRR_TX)
3395 stl_cd1400txisr(panelp, iobase);
3396 else if (svrtype & SVRR_MDM)
3397 stl_cd1400mdmisr(panelp, iobase);
3398}
3399
3400
3401/*****************************************************************************/
3402
3403/*
3404 * Unfortunately we need to handle breaks in the TX data stream, since
3405 * this is the only way to generate them on the cd1400.
3406 */
3407
Jiri Slaby60be4812006-12-08 02:38:40 -08003408static int stl_cd1400breakisr(struct stlport *portp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003409{
3410 if (portp->brklen == 1) {
3411 outb((COR2 + portp->uartaddr), ioaddr);
3412 outb((inb(ioaddr + EREG_DATA) | COR2_ETC),
3413 (ioaddr + EREG_DATA));
3414 outb((TDR + portp->uartaddr), ioaddr);
3415 outb(ETC_CMD, (ioaddr + EREG_DATA));
3416 outb(ETC_STARTBREAK, (ioaddr + EREG_DATA));
3417 outb((SRER + portp->uartaddr), ioaddr);
3418 outb((inb(ioaddr + EREG_DATA) & ~(SRER_TXDATA | SRER_TXEMPTY)),
3419 (ioaddr + EREG_DATA));
Jesper Juhl014c2542006-01-15 02:37:08 +01003420 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003421 } else if (portp->brklen > 1) {
3422 outb((TDR + portp->uartaddr), ioaddr);
3423 outb(ETC_CMD, (ioaddr + EREG_DATA));
3424 outb(ETC_STOPBREAK, (ioaddr + EREG_DATA));
3425 portp->brklen = -1;
Jesper Juhl014c2542006-01-15 02:37:08 +01003426 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003427 } else {
3428 outb((COR2 + portp->uartaddr), ioaddr);
3429 outb((inb(ioaddr + EREG_DATA) & ~COR2_ETC),
3430 (ioaddr + EREG_DATA));
3431 portp->brklen = 0;
3432 }
Jesper Juhl014c2542006-01-15 02:37:08 +01003433 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003434}
3435
3436/*****************************************************************************/
3437
3438/*
3439 * Transmit interrupt handler. This has gotta be fast! Handling TX
3440 * chars is pretty simple, stuff as many as possible from the TX buffer
3441 * into the cd1400 FIFO. Must also handle TX breaks here, since they
3442 * are embedded as commands in the data stream. Oh no, had to use a goto!
3443 * This could be optimized more, will do when I get time...
3444 * In practice it is possible that interrupts are enabled but that the
3445 * port has been hung up. Need to handle not having any TX buffer here,
3446 * this is done by using the side effect that head and tail will also
3447 * be NULL if the buffer has been freed.
3448 */
3449
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003450static void stl_cd1400txisr(struct stlpanel *panelp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003451{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003452 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003453 int len, stlen;
3454 char *head, *tail;
3455 unsigned char ioack, srer;
Alan Coxd18a7502008-10-13 10:40:07 +01003456 struct tty_struct *tty;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003457
Jiri Slabya0564e12006-12-08 02:38:37 -08003458 pr_debug("stl_cd1400txisr(panelp=%p,ioaddr=%x)\n", panelp, ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003459
3460 ioack = inb(ioaddr + EREG_TXACK);
3461 if (((ioack & panelp->ackmask) != 0) ||
3462 ((ioack & ACK_TYPMASK) != ACK_TYPTX)) {
3463 printk("STALLION: bad TX interrupt ack value=%x\n", ioack);
3464 return;
3465 }
3466 portp = panelp->ports[(ioack >> 3)];
3467
3468/*
3469 * Unfortunately we need to handle breaks in the data stream, since
3470 * this is the only way to generate them on the cd1400. Do it now if
3471 * a break is to be sent.
3472 */
3473 if (portp->brklen != 0)
3474 if (stl_cd1400breakisr(portp, ioaddr))
3475 goto stl_txalldone;
3476
3477 head = portp->tx.head;
3478 tail = portp->tx.tail;
3479 len = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
3480 if ((len == 0) || ((len < STL_TXBUFLOW) &&
3481 (test_bit(ASYI_TXLOW, &portp->istate) == 0))) {
3482 set_bit(ASYI_TXLOW, &portp->istate);
Alan Coxd18a7502008-10-13 10:40:07 +01003483 tty = tty_port_tty_get(&portp->port);
3484 if (tty) {
3485 tty_wakeup(tty);
3486 tty_kref_put(tty);
3487 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003488 }
3489
3490 if (len == 0) {
3491 outb((SRER + portp->uartaddr), ioaddr);
3492 srer = inb(ioaddr + EREG_DATA);
3493 if (srer & SRER_TXDATA) {
3494 srer = (srer & ~SRER_TXDATA) | SRER_TXEMPTY;
3495 } else {
3496 srer &= ~(SRER_TXDATA | SRER_TXEMPTY);
3497 clear_bit(ASYI_TXBUSY, &portp->istate);
3498 }
3499 outb(srer, (ioaddr + EREG_DATA));
3500 } else {
Jiri Slaby843b5682006-12-08 02:39:12 -08003501 len = min(len, CD1400_TXFIFOSIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003502 portp->stats.txtotal += len;
Jiri Slaby319fe7c2008-02-07 00:16:36 -08003503 stlen = min_t(unsigned int, len,
3504 (portp->tx.buf + STL_TXBUFSIZE) - tail);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003505 outb((TDR + portp->uartaddr), ioaddr);
3506 outsb((ioaddr + EREG_DATA), tail, stlen);
3507 len -= stlen;
3508 tail += stlen;
3509 if (tail >= (portp->tx.buf + STL_TXBUFSIZE))
3510 tail = portp->tx.buf;
3511 if (len > 0) {
3512 outsb((ioaddr + EREG_DATA), tail, len);
3513 tail += len;
3514 }
3515 portp->tx.tail = tail;
3516 }
3517
3518stl_txalldone:
3519 outb((EOSRR + portp->uartaddr), ioaddr);
3520 outb(0, (ioaddr + EREG_DATA));
3521}
3522
3523/*****************************************************************************/
3524
3525/*
3526 * Receive character interrupt handler. Determine if we have good chars
3527 * or bad chars and then process appropriately. Good chars are easy
3528 * just shove the lot into the RX buffer and set all status byte to 0.
3529 * If a bad RX char then process as required. This routine needs to be
3530 * fast! In practice it is possible that we get an interrupt on a port
3531 * that is closed. This can happen on hangups - since they completely
3532 * shutdown a port not in user context. Need to handle this case.
3533 */
3534
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003535static void stl_cd1400rxisr(struct stlpanel *panelp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003536{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003537 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003538 struct tty_struct *tty;
3539 unsigned int ioack, len, buflen;
3540 unsigned char status;
3541 char ch;
3542
Jiri Slabya0564e12006-12-08 02:38:37 -08003543 pr_debug("stl_cd1400rxisr(panelp=%p,ioaddr=%x)\n", panelp, ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003544
3545 ioack = inb(ioaddr + EREG_RXACK);
3546 if ((ioack & panelp->ackmask) != 0) {
3547 printk("STALLION: bad RX interrupt ack value=%x\n", ioack);
3548 return;
3549 }
3550 portp = panelp->ports[(ioack >> 3)];
Alan Coxd18a7502008-10-13 10:40:07 +01003551 tty = tty_port_tty_get(&portp->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003552
3553 if ((ioack & ACK_TYPMASK) == ACK_TYPRXGOOD) {
3554 outb((RDCR + portp->uartaddr), ioaddr);
3555 len = inb(ioaddr + EREG_DATA);
Alan Cox33f0f882006-01-09 20:54:13 -08003556 if (tty == NULL || (buflen = tty_buffer_request_room(tty, len)) == 0) {
Jiri Slaby319fe7c2008-02-07 00:16:36 -08003557 len = min_t(unsigned int, len, sizeof(stl_unwanted));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003558 outb((RDSR + portp->uartaddr), ioaddr);
3559 insb((ioaddr + EREG_DATA), &stl_unwanted[0], len);
3560 portp->stats.rxlost += len;
3561 portp->stats.rxtotal += len;
3562 } else {
Jiri Slaby843b5682006-12-08 02:39:12 -08003563 len = min(len, buflen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003564 if (len > 0) {
Alan Cox33f0f882006-01-09 20:54:13 -08003565 unsigned char *ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003566 outb((RDSR + portp->uartaddr), ioaddr);
Alan Cox33f0f882006-01-09 20:54:13 -08003567 tty_prepare_flip_string(tty, &ptr, len);
3568 insb((ioaddr + EREG_DATA), ptr, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003569 tty_schedule_flip(tty);
3570 portp->stats.rxtotal += len;
3571 }
3572 }
3573 } else if ((ioack & ACK_TYPMASK) == ACK_TYPRXBAD) {
3574 outb((RDSR + portp->uartaddr), ioaddr);
3575 status = inb(ioaddr + EREG_DATA);
3576 ch = inb(ioaddr + EREG_DATA);
3577 if (status & ST_PARITY)
3578 portp->stats.rxparity++;
3579 if (status & ST_FRAMING)
3580 portp->stats.rxframing++;
3581 if (status & ST_OVERRUN)
3582 portp->stats.rxoverrun++;
3583 if (status & ST_BREAK)
3584 portp->stats.rxbreaks++;
3585 if (status & ST_SCHARMASK) {
3586 if ((status & ST_SCHARMASK) == ST_SCHAR1)
3587 portp->stats.txxon++;
3588 if ((status & ST_SCHARMASK) == ST_SCHAR2)
3589 portp->stats.txxoff++;
3590 goto stl_rxalldone;
3591 }
Alan Cox33f0f882006-01-09 20:54:13 -08003592 if (tty != NULL && (portp->rxignoremsk & status) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003593 if (portp->rxmarkmsk & status) {
3594 if (status & ST_BREAK) {
3595 status = TTY_BREAK;
Alan Coxf8ae4762008-07-16 21:56:37 +01003596 if (portp->port.flags & ASYNC_SAK) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003597 do_SAK(tty);
3598 BRDENABLE(portp->brdnr, portp->pagenr);
3599 }
Jiri Slabyc62429d2006-12-08 02:39:14 -08003600 } else if (status & ST_PARITY)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003601 status = TTY_PARITY;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003602 else if (status & ST_FRAMING)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003603 status = TTY_FRAME;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003604 else if(status & ST_OVERRUN)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003605 status = TTY_OVERRUN;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003606 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003607 status = 0;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003608 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003609 status = 0;
Alan Cox33f0f882006-01-09 20:54:13 -08003610 tty_insert_flip_char(tty, ch, status);
3611 tty_schedule_flip(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003612 }
3613 } else {
3614 printk("STALLION: bad RX interrupt ack value=%x\n", ioack);
Alan Coxd18a7502008-10-13 10:40:07 +01003615 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003616 return;
3617 }
3618
3619stl_rxalldone:
Alan Coxd18a7502008-10-13 10:40:07 +01003620 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003621 outb((EOSRR + portp->uartaddr), ioaddr);
3622 outb(0, (ioaddr + EREG_DATA));
3623}
3624
3625/*****************************************************************************/
3626
3627/*
3628 * Modem interrupt handler. The is called when the modem signal line
3629 * (DCD) has changed state. Leave most of the work to the off-level
3630 * processing routine.
3631 */
3632
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003633static void stl_cd1400mdmisr(struct stlpanel *panelp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003634{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003635 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003636 unsigned int ioack;
3637 unsigned char misr;
3638
Jiri Slabya0564e12006-12-08 02:38:37 -08003639 pr_debug("stl_cd1400mdmisr(panelp=%p)\n", panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003640
3641 ioack = inb(ioaddr + EREG_MDACK);
3642 if (((ioack & panelp->ackmask) != 0) ||
3643 ((ioack & ACK_TYPMASK) != ACK_TYPMDM)) {
3644 printk("STALLION: bad MODEM interrupt ack value=%x\n", ioack);
3645 return;
3646 }
3647 portp = panelp->ports[(ioack >> 3)];
3648
3649 outb((MISR + portp->uartaddr), ioaddr);
3650 misr = inb(ioaddr + EREG_DATA);
3651 if (misr & MISR_DCD) {
Jiri Slabyccfea3c2008-02-07 00:16:39 -08003652 stl_cd_change(portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003653 portp->stats.modem++;
3654 }
3655
3656 outb((EOSRR + portp->uartaddr), ioaddr);
3657 outb(0, (ioaddr + EREG_DATA));
3658}
3659
3660/*****************************************************************************/
3661/* SC26198 HARDWARE FUNCTIONS */
3662/*****************************************************************************/
3663
3664/*
3665 * These functions get/set/update the registers of the sc26198 UARTs.
3666 * Access to the sc26198 registers is via an address/data io port pair.
3667 * (Maybe should make this inline...)
3668 */
3669
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003670static int stl_sc26198getreg(struct stlport *portp, int regnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003671{
3672 outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
Jesper Juhl014c2542006-01-15 02:37:08 +01003673 return inb(portp->ioaddr + XP_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003674}
3675
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003676static void stl_sc26198setreg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003677{
3678 outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
3679 outb(value, (portp->ioaddr + XP_DATA));
3680}
3681
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003682static int stl_sc26198updatereg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003683{
3684 outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
3685 if (inb(portp->ioaddr + XP_DATA) != value) {
3686 outb(value, (portp->ioaddr + XP_DATA));
Jesper Juhl014c2542006-01-15 02:37:08 +01003687 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003688 }
Jesper Juhl014c2542006-01-15 02:37:08 +01003689 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003690}
3691
3692/*****************************************************************************/
3693
3694/*
3695 * Functions to get and set the sc26198 global registers.
3696 */
3697
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003698static int stl_sc26198getglobreg(struct stlport *portp, int regnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003699{
3700 outb(regnr, (portp->ioaddr + XP_ADDR));
Jesper Juhl014c2542006-01-15 02:37:08 +01003701 return inb(portp->ioaddr + XP_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003702}
3703
3704#if 0
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003705static void stl_sc26198setglobreg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003706{
3707 outb(regnr, (portp->ioaddr + XP_ADDR));
3708 outb(value, (portp->ioaddr + XP_DATA));
3709}
3710#endif
3711
3712/*****************************************************************************/
3713
3714/*
3715 * Inbitialize the UARTs in a panel. We don't care what sort of board
3716 * these ports are on - since the port io registers are almost
3717 * identical when dealing with ports.
3718 */
3719
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003720static int stl_sc26198panelinit(struct stlbrd *brdp, struct stlpanel *panelp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003721{
3722 int chipmask, i;
3723 int nrchips, ioaddr;
3724
Jiri Slabya0564e12006-12-08 02:38:37 -08003725 pr_debug("stl_sc26198panelinit(brdp=%p,panelp=%p)\n", brdp, panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003726
3727 BRDENABLE(panelp->brdnr, panelp->pagenr);
3728
3729/*
3730 * Check that each chip is present and started up OK.
3731 */
3732 chipmask = 0;
3733 nrchips = (panelp->nrports + 4) / SC26198_PORTS;
3734 if (brdp->brdtype == BRD_ECHPCI)
3735 outb(panelp->pagenr, brdp->ioctrl);
3736
Jiri Slabyc62429d2006-12-08 02:39:14 -08003737 for (i = 0; i < nrchips; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003738 ioaddr = panelp->iobase + (i * 4);
3739 outb(SCCR, (ioaddr + XP_ADDR));
3740 outb(CR_RESETALL, (ioaddr + XP_DATA));
3741 outb(TSTR, (ioaddr + XP_ADDR));
3742 if (inb(ioaddr + XP_DATA) != 0) {
3743 printk("STALLION: sc26198 not responding, "
3744 "brd=%d panel=%d chip=%d\n",
3745 panelp->brdnr, panelp->panelnr, i);
3746 continue;
3747 }
3748 chipmask |= (0x1 << i);
3749 outb(GCCR, (ioaddr + XP_ADDR));
3750 outb(GCCR_IVRTYPCHANACK, (ioaddr + XP_DATA));
3751 outb(WDTRCR, (ioaddr + XP_ADDR));
3752 outb(0xff, (ioaddr + XP_DATA));
3753 }
3754
3755 BRDDISABLE(panelp->brdnr);
Jesper Juhl014c2542006-01-15 02:37:08 +01003756 return chipmask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003757}
3758
3759/*****************************************************************************/
3760
3761/*
3762 * Initialize hardware specific port registers.
3763 */
3764
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003765static void stl_sc26198portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003766{
Jiri Slabya0564e12006-12-08 02:38:37 -08003767 pr_debug("stl_sc26198portinit(brdp=%p,panelp=%p,portp=%p)\n", brdp,
3768 panelp, portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003769
Jiri Slaby615e4a72006-12-08 02:38:38 -08003770 if ((brdp == NULL) || (panelp == NULL) ||
3771 (portp == NULL))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003772 return;
3773
3774 portp->ioaddr = panelp->iobase + ((portp->portnr < 8) ? 0 : 4);
3775 portp->uartaddr = (portp->portnr & 0x07) << 4;
3776 portp->pagenr = panelp->pagenr;
3777 portp->hwid = 0x1;
3778
3779 BRDENABLE(portp->brdnr, portp->pagenr);
3780 stl_sc26198setreg(portp, IOPCR, IOPCR_SETSIGS);
3781 BRDDISABLE(portp->brdnr);
3782}
3783
3784/*****************************************************************************/
3785
3786/*
3787 * Set up the sc26198 registers for a port based on the termios port
3788 * settings.
3789 */
3790
Alan Cox606d0992006-12-08 02:38:45 -08003791static void stl_sc26198setport(struct stlport *portp, struct ktermios *tiosp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003792{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003793 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003794 unsigned long flags;
3795 unsigned int baudrate;
3796 unsigned char mr0, mr1, mr2, clk;
3797 unsigned char imron, imroff, iopr, ipr;
3798
3799 mr0 = 0;
3800 mr1 = 0;
3801 mr2 = 0;
3802 clk = 0;
3803 iopr = 0;
3804 imron = 0;
3805 imroff = 0;
3806
3807 brdp = stl_brds[portp->brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08003808 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003809 return;
3810
3811/*
3812 * Set up the RX char ignore mask with those RX error types we
3813 * can ignore.
3814 */
3815 portp->rxignoremsk = 0;
3816 if (tiosp->c_iflag & IGNPAR)
3817 portp->rxignoremsk |= (SR_RXPARITY | SR_RXFRAMING |
3818 SR_RXOVERRUN);
3819 if (tiosp->c_iflag & IGNBRK)
3820 portp->rxignoremsk |= SR_RXBREAK;
3821
3822 portp->rxmarkmsk = SR_RXOVERRUN;
3823 if (tiosp->c_iflag & (INPCK | PARMRK))
3824 portp->rxmarkmsk |= (SR_RXPARITY | SR_RXFRAMING);
3825 if (tiosp->c_iflag & BRKINT)
3826 portp->rxmarkmsk |= SR_RXBREAK;
3827
3828/*
3829 * Go through the char size, parity and stop bits and set all the
3830 * option register appropriately.
3831 */
3832 switch (tiosp->c_cflag & CSIZE) {
3833 case CS5:
3834 mr1 |= MR1_CS5;
3835 break;
3836 case CS6:
3837 mr1 |= MR1_CS6;
3838 break;
3839 case CS7:
3840 mr1 |= MR1_CS7;
3841 break;
3842 default:
3843 mr1 |= MR1_CS8;
3844 break;
3845 }
3846
3847 if (tiosp->c_cflag & CSTOPB)
3848 mr2 |= MR2_STOP2;
3849 else
3850 mr2 |= MR2_STOP1;
3851
3852 if (tiosp->c_cflag & PARENB) {
3853 if (tiosp->c_cflag & PARODD)
3854 mr1 |= (MR1_PARENB | MR1_PARODD);
3855 else
3856 mr1 |= (MR1_PARENB | MR1_PAREVEN);
Jiri Slabyc62429d2006-12-08 02:39:14 -08003857 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003858 mr1 |= MR1_PARNONE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003859
3860 mr1 |= MR1_ERRBLOCK;
3861
3862/*
3863 * Set the RX FIFO threshold at 8 chars. This gives a bit of breathing
3864 * space for hardware flow control and the like. This should be set to
3865 * VMIN.
3866 */
3867 mr2 |= MR2_RXFIFOHALF;
3868
3869/*
3870 * Calculate the baud rate timers. For now we will just assume that
3871 * the input and output baud are the same. The sc26198 has a fixed
3872 * baud rate table, so only discrete baud rates possible.
3873 */
3874 baudrate = tiosp->c_cflag & CBAUD;
3875 if (baudrate & CBAUDEX) {
3876 baudrate &= ~CBAUDEX;
3877 if ((baudrate < 1) || (baudrate > 4))
3878 tiosp->c_cflag &= ~CBAUDEX;
3879 else
3880 baudrate += 15;
3881 }
3882 baudrate = stl_baudrates[baudrate];
3883 if ((tiosp->c_cflag & CBAUD) == B38400) {
Alan Coxf8ae4762008-07-16 21:56:37 +01003884 if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003885 baudrate = 57600;
Alan Coxf8ae4762008-07-16 21:56:37 +01003886 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003887 baudrate = 115200;
Alan Coxf8ae4762008-07-16 21:56:37 +01003888 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003889 baudrate = 230400;
Alan Coxf8ae4762008-07-16 21:56:37 +01003890 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003891 baudrate = 460800;
Alan Coxf8ae4762008-07-16 21:56:37 +01003892 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003893 baudrate = (portp->baud_base / portp->custom_divisor);
3894 }
3895 if (baudrate > STL_SC26198MAXBAUD)
3896 baudrate = STL_SC26198MAXBAUD;
3897
Jiri Slabyc62429d2006-12-08 02:39:14 -08003898 if (baudrate > 0)
3899 for (clk = 0; clk < SC26198_NRBAUDS; clk++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003900 if (baudrate <= sc26198_baudtable[clk])
3901 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003902
3903/*
3904 * Check what form of modem signaling is required and set it up.
3905 */
3906 if (tiosp->c_cflag & CLOCAL) {
Alan Coxf8ae4762008-07-16 21:56:37 +01003907 portp->port.flags &= ~ASYNC_CHECK_CD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003908 } else {
3909 iopr |= IOPR_DCDCOS;
3910 imron |= IR_IOPORT;
Alan Coxf8ae4762008-07-16 21:56:37 +01003911 portp->port.flags |= ASYNC_CHECK_CD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003912 }
3913
3914/*
3915 * Setup sc26198 enhanced modes if we can. In particular we want to
3916 * handle as much of the flow control as possible automatically. As
3917 * well as saving a few CPU cycles it will also greatly improve flow
3918 * control reliability.
3919 */
3920 if (tiosp->c_iflag & IXON) {
3921 mr0 |= MR0_SWFTX | MR0_SWFT;
3922 imron |= IR_XONXOFF;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003923 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003924 imroff |= IR_XONXOFF;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003925
Linus Torvalds1da177e2005-04-16 15:20:36 -07003926 if (tiosp->c_iflag & IXOFF)
3927 mr0 |= MR0_SWFRX;
3928
3929 if (tiosp->c_cflag & CRTSCTS) {
3930 mr2 |= MR2_AUTOCTS;
3931 mr1 |= MR1_AUTORTS;
3932 }
3933
3934/*
3935 * All sc26198 register values calculated so go through and set
3936 * them all up.
3937 */
3938
Jiri Slabya0564e12006-12-08 02:38:37 -08003939 pr_debug("SETPORT: portnr=%d panelnr=%d brdnr=%d\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003940 portp->portnr, portp->panelnr, portp->brdnr);
Jiri Slabya0564e12006-12-08 02:38:37 -08003941 pr_debug(" mr0=%x mr1=%x mr2=%x clk=%x\n", mr0, mr1, mr2, clk);
3942 pr_debug(" iopr=%x imron=%x imroff=%x\n", iopr, imron, imroff);
3943 pr_debug(" schr1=%x schr2=%x schr3=%x schr4=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003944 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP],
3945 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003946
Alan Coxb65b5b52006-06-27 02:54:05 -07003947 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003948 BRDENABLE(portp->brdnr, portp->pagenr);
3949 stl_sc26198setreg(portp, IMR, 0);
3950 stl_sc26198updatereg(portp, MR0, mr0);
3951 stl_sc26198updatereg(portp, MR1, mr1);
3952 stl_sc26198setreg(portp, SCCR, CR_RXERRBLOCK);
3953 stl_sc26198updatereg(portp, MR2, mr2);
3954 stl_sc26198updatereg(portp, IOPIOR,
3955 ((stl_sc26198getreg(portp, IOPIOR) & ~IPR_CHANGEMASK) | iopr));
3956
3957 if (baudrate > 0) {
3958 stl_sc26198setreg(portp, TXCSR, clk);
3959 stl_sc26198setreg(portp, RXCSR, clk);
3960 }
3961
3962 stl_sc26198setreg(portp, XONCR, tiosp->c_cc[VSTART]);
3963 stl_sc26198setreg(portp, XOFFCR, tiosp->c_cc[VSTOP]);
3964
3965 ipr = stl_sc26198getreg(portp, IPR);
3966 if (ipr & IPR_DCD)
3967 portp->sigs &= ~TIOCM_CD;
3968 else
3969 portp->sigs |= TIOCM_CD;
3970
3971 portp->imr = (portp->imr & ~imroff) | imron;
3972 stl_sc26198setreg(portp, IMR, portp->imr);
3973 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003974 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003975}
3976
3977/*****************************************************************************/
3978
3979/*
3980 * Set the state of the DTR and RTS signals.
3981 */
3982
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003983static void stl_sc26198setsignals(struct stlport *portp, int dtr, int rts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003984{
3985 unsigned char iopioron, iopioroff;
3986 unsigned long flags;
3987
Jiri Slabya0564e12006-12-08 02:38:37 -08003988 pr_debug("stl_sc26198setsignals(portp=%p,dtr=%d,rts=%d)\n", portp,
3989 dtr, rts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003990
3991 iopioron = 0;
3992 iopioroff = 0;
3993 if (dtr == 0)
3994 iopioroff |= IPR_DTR;
3995 else if (dtr > 0)
3996 iopioron |= IPR_DTR;
3997 if (rts == 0)
3998 iopioroff |= IPR_RTS;
3999 else if (rts > 0)
4000 iopioron |= IPR_RTS;
4001
Alan Coxb65b5b52006-06-27 02:54:05 -07004002 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004003 BRDENABLE(portp->brdnr, portp->pagenr);
4004 stl_sc26198setreg(portp, IOPIOR,
4005 ((stl_sc26198getreg(portp, IOPIOR) & ~iopioroff) | iopioron));
4006 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004007 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004008}
4009
4010/*****************************************************************************/
4011
4012/*
4013 * Return the state of the signals.
4014 */
4015
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004016static int stl_sc26198getsignals(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004017{
4018 unsigned char ipr;
4019 unsigned long flags;
4020 int sigs;
4021
Jiri Slabya0564e12006-12-08 02:38:37 -08004022 pr_debug("stl_sc26198getsignals(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004023
Alan Coxb65b5b52006-06-27 02:54:05 -07004024 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004025 BRDENABLE(portp->brdnr, portp->pagenr);
4026 ipr = stl_sc26198getreg(portp, IPR);
4027 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004028 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004029
4030 sigs = 0;
4031 sigs |= (ipr & IPR_DCD) ? 0 : TIOCM_CD;
4032 sigs |= (ipr & IPR_CTS) ? 0 : TIOCM_CTS;
4033 sigs |= (ipr & IPR_DTR) ? 0: TIOCM_DTR;
4034 sigs |= (ipr & IPR_RTS) ? 0: TIOCM_RTS;
4035 sigs |= TIOCM_DSR;
Jesper Juhl014c2542006-01-15 02:37:08 +01004036 return sigs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004037}
4038
4039/*****************************************************************************/
4040
4041/*
4042 * Enable/Disable the Transmitter and/or Receiver.
4043 */
4044
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004045static void stl_sc26198enablerxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004046{
4047 unsigned char ccr;
4048 unsigned long flags;
4049
Jiri Slabya0564e12006-12-08 02:38:37 -08004050 pr_debug("stl_sc26198enablerxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx,tx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004051
4052 ccr = portp->crenable;
4053 if (tx == 0)
4054 ccr &= ~CR_TXENABLE;
4055 else if (tx > 0)
4056 ccr |= CR_TXENABLE;
4057 if (rx == 0)
4058 ccr &= ~CR_RXENABLE;
4059 else if (rx > 0)
4060 ccr |= CR_RXENABLE;
4061
Alan Coxb65b5b52006-06-27 02:54:05 -07004062 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004063 BRDENABLE(portp->brdnr, portp->pagenr);
4064 stl_sc26198setreg(portp, SCCR, ccr);
4065 BRDDISABLE(portp->brdnr);
4066 portp->crenable = ccr;
Alan Coxb65b5b52006-06-27 02:54:05 -07004067 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004068}
4069
4070/*****************************************************************************/
4071
4072/*
4073 * Start/stop the Transmitter and/or Receiver.
4074 */
4075
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004076static void stl_sc26198startrxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004077{
4078 unsigned char imr;
4079 unsigned long flags;
4080
Jiri Slabya0564e12006-12-08 02:38:37 -08004081 pr_debug("stl_sc26198startrxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004082
4083 imr = portp->imr;
4084 if (tx == 0)
4085 imr &= ~IR_TXRDY;
4086 else if (tx == 1)
4087 imr |= IR_TXRDY;
4088 if (rx == 0)
4089 imr &= ~(IR_RXRDY | IR_RXBREAK | IR_RXWATCHDOG);
4090 else if (rx > 0)
4091 imr |= IR_RXRDY | IR_RXBREAK | IR_RXWATCHDOG;
4092
Alan Coxb65b5b52006-06-27 02:54:05 -07004093 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004094 BRDENABLE(portp->brdnr, portp->pagenr);
4095 stl_sc26198setreg(portp, IMR, imr);
4096 BRDDISABLE(portp->brdnr);
4097 portp->imr = imr;
4098 if (tx > 0)
4099 set_bit(ASYI_TXBUSY, &portp->istate);
Alan Coxb65b5b52006-06-27 02:54:05 -07004100 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004101}
4102
4103/*****************************************************************************/
4104
4105/*
4106 * Disable all interrupts from this port.
4107 */
4108
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004109static void stl_sc26198disableintrs(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004110{
4111 unsigned long flags;
4112
Jiri Slabya0564e12006-12-08 02:38:37 -08004113 pr_debug("stl_sc26198disableintrs(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004114
Alan Coxb65b5b52006-06-27 02:54:05 -07004115 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004116 BRDENABLE(portp->brdnr, portp->pagenr);
4117 portp->imr = 0;
4118 stl_sc26198setreg(portp, IMR, 0);
4119 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004120 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004121}
4122
4123/*****************************************************************************/
4124
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004125static void stl_sc26198sendbreak(struct stlport *portp, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004126{
4127 unsigned long flags;
4128
Jiri Slabya0564e12006-12-08 02:38:37 -08004129 pr_debug("stl_sc26198sendbreak(portp=%p,len=%d)\n", portp, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004130
Alan Coxb65b5b52006-06-27 02:54:05 -07004131 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004132 BRDENABLE(portp->brdnr, portp->pagenr);
4133 if (len == 1) {
4134 stl_sc26198setreg(portp, SCCR, CR_TXSTARTBREAK);
4135 portp->stats.txbreaks++;
Jiri Slabyc62429d2006-12-08 02:39:14 -08004136 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07004137 stl_sc26198setreg(portp, SCCR, CR_TXSTOPBREAK);
Jiri Slabyc62429d2006-12-08 02:39:14 -08004138
Linus Torvalds1da177e2005-04-16 15:20:36 -07004139 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004140 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004141}
4142
4143/*****************************************************************************/
4144
4145/*
4146 * Take flow control actions...
4147 */
4148
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004149static void stl_sc26198flowctrl(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004150{
4151 struct tty_struct *tty;
4152 unsigned long flags;
4153 unsigned char mr0;
4154
Jiri Slabya0564e12006-12-08 02:38:37 -08004155 pr_debug("stl_sc26198flowctrl(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004156
Jiri Slaby615e4a72006-12-08 02:38:38 -08004157 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004158 return;
Alan Coxd18a7502008-10-13 10:40:07 +01004159 tty = tty_port_tty_get(&portp->port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08004160 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004161 return;
4162
Alan Coxb65b5b52006-06-27 02:54:05 -07004163 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004164 BRDENABLE(portp->brdnr, portp->pagenr);
4165
4166 if (state) {
4167 if (tty->termios->c_iflag & IXOFF) {
4168 mr0 = stl_sc26198getreg(portp, MR0);
4169 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4170 stl_sc26198setreg(portp, SCCR, CR_TXSENDXON);
4171 mr0 |= MR0_SWFRX;
4172 portp->stats.rxxon++;
4173 stl_sc26198wait(portp);
4174 stl_sc26198setreg(portp, MR0, mr0);
4175 }
4176/*
4177 * Question: should we return RTS to what it was before? It may
4178 * have been set by an ioctl... Suppose not, since if you have
4179 * hardware flow control set then it is pretty silly to go and
4180 * set the RTS line by hand.
4181 */
4182 if (tty->termios->c_cflag & CRTSCTS) {
4183 stl_sc26198setreg(portp, MR1,
4184 (stl_sc26198getreg(portp, MR1) | MR1_AUTORTS));
4185 stl_sc26198setreg(portp, IOPIOR,
4186 (stl_sc26198getreg(portp, IOPIOR) | IOPR_RTS));
4187 portp->stats.rxrtson++;
4188 }
4189 } else {
4190 if (tty->termios->c_iflag & IXOFF) {
4191 mr0 = stl_sc26198getreg(portp, MR0);
4192 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4193 stl_sc26198setreg(portp, SCCR, CR_TXSENDXOFF);
4194 mr0 &= ~MR0_SWFRX;
4195 portp->stats.rxxoff++;
4196 stl_sc26198wait(portp);
4197 stl_sc26198setreg(portp, MR0, mr0);
4198 }
4199 if (tty->termios->c_cflag & CRTSCTS) {
4200 stl_sc26198setreg(portp, MR1,
4201 (stl_sc26198getreg(portp, MR1) & ~MR1_AUTORTS));
4202 stl_sc26198setreg(portp, IOPIOR,
4203 (stl_sc26198getreg(portp, IOPIOR) & ~IOPR_RTS));
4204 portp->stats.rxrtsoff++;
4205 }
4206 }
4207
4208 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004209 spin_unlock_irqrestore(&brd_lock, flags);
Alan Coxd18a7502008-10-13 10:40:07 +01004210 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004211}
4212
4213/*****************************************************************************/
4214
4215/*
4216 * Send a flow control character.
4217 */
4218
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004219static void stl_sc26198sendflow(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004220{
4221 struct tty_struct *tty;
4222 unsigned long flags;
4223 unsigned char mr0;
4224
Jiri Slabya0564e12006-12-08 02:38:37 -08004225 pr_debug("stl_sc26198sendflow(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004226
Jiri Slaby615e4a72006-12-08 02:38:38 -08004227 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004228 return;
Alan Coxd18a7502008-10-13 10:40:07 +01004229 tty = tty_port_tty_get(&portp->port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08004230 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004231 return;
4232
Alan Coxb65b5b52006-06-27 02:54:05 -07004233 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004234 BRDENABLE(portp->brdnr, portp->pagenr);
4235 if (state) {
4236 mr0 = stl_sc26198getreg(portp, MR0);
4237 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4238 stl_sc26198setreg(portp, SCCR, CR_TXSENDXON);
4239 mr0 |= MR0_SWFRX;
4240 portp->stats.rxxon++;
4241 stl_sc26198wait(portp);
4242 stl_sc26198setreg(portp, MR0, mr0);
4243 } else {
4244 mr0 = stl_sc26198getreg(portp, MR0);
4245 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4246 stl_sc26198setreg(portp, SCCR, CR_TXSENDXOFF);
4247 mr0 &= ~MR0_SWFRX;
4248 portp->stats.rxxoff++;
4249 stl_sc26198wait(portp);
4250 stl_sc26198setreg(portp, MR0, mr0);
4251 }
4252 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004253 spin_unlock_irqrestore(&brd_lock, flags);
Alan Coxd18a7502008-10-13 10:40:07 +01004254 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004255}
4256
4257/*****************************************************************************/
4258
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004259static void stl_sc26198flush(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004260{
4261 unsigned long flags;
4262
Jiri Slabya0564e12006-12-08 02:38:37 -08004263 pr_debug("stl_sc26198flush(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004264
Jiri Slaby615e4a72006-12-08 02:38:38 -08004265 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004266 return;
4267
Alan Coxb65b5b52006-06-27 02:54:05 -07004268 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004269 BRDENABLE(portp->brdnr, portp->pagenr);
4270 stl_sc26198setreg(portp, SCCR, CR_TXRESET);
4271 stl_sc26198setreg(portp, SCCR, portp->crenable);
4272 BRDDISABLE(portp->brdnr);
4273 portp->tx.tail = portp->tx.head;
Alan Coxb65b5b52006-06-27 02:54:05 -07004274 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004275}
4276
4277/*****************************************************************************/
4278
4279/*
4280 * Return the current state of data flow on this port. This is only
4281 * really interresting when determining if data has fully completed
4282 * transmission or not... The sc26198 interrupt scheme cannot
4283 * determine when all data has actually drained, so we need to
4284 * check the port statusy register to be sure.
4285 */
4286
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004287static int stl_sc26198datastate(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004288{
4289 unsigned long flags;
4290 unsigned char sr;
4291
Jiri Slabya0564e12006-12-08 02:38:37 -08004292 pr_debug("stl_sc26198datastate(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004293
Jiri Slaby615e4a72006-12-08 02:38:38 -08004294 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01004295 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004296 if (test_bit(ASYI_TXBUSY, &portp->istate))
Jesper Juhl014c2542006-01-15 02:37:08 +01004297 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004298
Alan Coxb65b5b52006-06-27 02:54:05 -07004299 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004300 BRDENABLE(portp->brdnr, portp->pagenr);
4301 sr = stl_sc26198getreg(portp, SR);
4302 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004303 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004304
Jesper Juhl014c2542006-01-15 02:37:08 +01004305 return (sr & SR_TXEMPTY) ? 0 : 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004306}
4307
4308/*****************************************************************************/
4309
4310/*
4311 * Delay for a small amount of time, to give the sc26198 a chance
4312 * to process a command...
4313 */
4314
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004315static void stl_sc26198wait(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004316{
4317 int i;
4318
Jiri Slabya0564e12006-12-08 02:38:37 -08004319 pr_debug("stl_sc26198wait(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004320
Jiri Slaby615e4a72006-12-08 02:38:38 -08004321 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004322 return;
4323
Jiri Slabyc62429d2006-12-08 02:39:14 -08004324 for (i = 0; i < 20; i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004325 stl_sc26198getglobreg(portp, TSTR);
4326}
4327
4328/*****************************************************************************/
4329
4330/*
4331 * If we are TX flow controlled and in IXANY mode then we may
4332 * need to unflow control here. We gotta do this because of the
4333 * automatic flow control modes of the sc26198.
4334 */
4335
Jiri Slaby60be4812006-12-08 02:38:40 -08004336static void stl_sc26198txunflow(struct stlport *portp, struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004337{
4338 unsigned char mr0;
4339
4340 mr0 = stl_sc26198getreg(portp, MR0);
4341 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4342 stl_sc26198setreg(portp, SCCR, CR_HOSTXON);
4343 stl_sc26198wait(portp);
4344 stl_sc26198setreg(portp, MR0, mr0);
4345 clear_bit(ASYI_TXFLOWED, &portp->istate);
4346}
4347
4348/*****************************************************************************/
4349
4350/*
4351 * Interrupt service routine for sc26198 panels.
4352 */
4353
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004354static void stl_sc26198intr(struct stlpanel *panelp, unsigned int iobase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004355{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004356 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004357 unsigned int iack;
4358
Alan Coxb65b5b52006-06-27 02:54:05 -07004359 spin_lock(&brd_lock);
4360
Linus Torvalds1da177e2005-04-16 15:20:36 -07004361/*
4362 * Work around bug in sc26198 chip... Cannot have A6 address
4363 * line of UART high, else iack will be returned as 0.
4364 */
4365 outb(0, (iobase + 1));
4366
4367 iack = inb(iobase + XP_IACK);
4368 portp = panelp->ports[(iack & IVR_CHANMASK) + ((iobase & 0x4) << 1)];
4369
4370 if (iack & IVR_RXDATA)
4371 stl_sc26198rxisr(portp, iack);
4372 else if (iack & IVR_TXDATA)
4373 stl_sc26198txisr(portp);
4374 else
4375 stl_sc26198otherisr(portp, iack);
Alan Coxb65b5b52006-06-27 02:54:05 -07004376
4377 spin_unlock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004378}
4379
4380/*****************************************************************************/
4381
4382/*
4383 * Transmit interrupt handler. This has gotta be fast! Handling TX
4384 * chars is pretty simple, stuff as many as possible from the TX buffer
4385 * into the sc26198 FIFO.
4386 * In practice it is possible that interrupts are enabled but that the
4387 * port has been hung up. Need to handle not having any TX buffer here,
4388 * this is done by using the side effect that head and tail will also
4389 * be NULL if the buffer has been freed.
4390 */
4391
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004392static void stl_sc26198txisr(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004393{
Alan Coxd18a7502008-10-13 10:40:07 +01004394 struct tty_struct *tty;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004395 unsigned int ioaddr;
4396 unsigned char mr0;
4397 int len, stlen;
4398 char *head, *tail;
4399
Jiri Slabya0564e12006-12-08 02:38:37 -08004400 pr_debug("stl_sc26198txisr(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004401
4402 ioaddr = portp->ioaddr;
4403 head = portp->tx.head;
4404 tail = portp->tx.tail;
4405 len = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
4406 if ((len == 0) || ((len < STL_TXBUFLOW) &&
4407 (test_bit(ASYI_TXLOW, &portp->istate) == 0))) {
4408 set_bit(ASYI_TXLOW, &portp->istate);
Alan Coxd18a7502008-10-13 10:40:07 +01004409 tty = tty_port_tty_get(&portp->port);
4410 if (tty) {
4411 tty_wakeup(tty);
4412 tty_kref_put(tty);
4413 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004414 }
4415
4416 if (len == 0) {
4417 outb((MR0 | portp->uartaddr), (ioaddr + XP_ADDR));
4418 mr0 = inb(ioaddr + XP_DATA);
4419 if ((mr0 & MR0_TXMASK) == MR0_TXEMPTY) {
4420 portp->imr &= ~IR_TXRDY;
4421 outb((IMR | portp->uartaddr), (ioaddr + XP_ADDR));
4422 outb(portp->imr, (ioaddr + XP_DATA));
4423 clear_bit(ASYI_TXBUSY, &portp->istate);
4424 } else {
4425 mr0 |= ((mr0 & ~MR0_TXMASK) | MR0_TXEMPTY);
4426 outb(mr0, (ioaddr + XP_DATA));
4427 }
4428 } else {
Jiri Slaby843b5682006-12-08 02:39:12 -08004429 len = min(len, SC26198_TXFIFOSIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004430 portp->stats.txtotal += len;
Jiri Slaby319fe7c2008-02-07 00:16:36 -08004431 stlen = min_t(unsigned int, len,
4432 (portp->tx.buf + STL_TXBUFSIZE) - tail);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004433 outb(GTXFIFO, (ioaddr + XP_ADDR));
4434 outsb((ioaddr + XP_DATA), tail, stlen);
4435 len -= stlen;
4436 tail += stlen;
4437 if (tail >= (portp->tx.buf + STL_TXBUFSIZE))
4438 tail = portp->tx.buf;
4439 if (len > 0) {
4440 outsb((ioaddr + XP_DATA), tail, len);
4441 tail += len;
4442 }
4443 portp->tx.tail = tail;
4444 }
4445}
4446
4447/*****************************************************************************/
4448
4449/*
4450 * Receive character interrupt handler. Determine if we have good chars
4451 * or bad chars and then process appropriately. Good chars are easy
4452 * just shove the lot into the RX buffer and set all status byte to 0.
4453 * If a bad RX char then process as required. This routine needs to be
4454 * fast! In practice it is possible that we get an interrupt on a port
4455 * that is closed. This can happen on hangups - since they completely
4456 * shutdown a port not in user context. Need to handle this case.
4457 */
4458
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004459static void stl_sc26198rxisr(struct stlport *portp, unsigned int iack)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004460{
4461 struct tty_struct *tty;
4462 unsigned int len, buflen, ioaddr;
4463
Jiri Slabya0564e12006-12-08 02:38:37 -08004464 pr_debug("stl_sc26198rxisr(portp=%p,iack=%x)\n", portp, iack);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004465
Alan Coxd18a7502008-10-13 10:40:07 +01004466 tty = tty_port_tty_get(&portp->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004467 ioaddr = portp->ioaddr;
4468 outb(GIBCR, (ioaddr + XP_ADDR));
4469 len = inb(ioaddr + XP_DATA) + 1;
4470
4471 if ((iack & IVR_TYPEMASK) == IVR_RXDATA) {
Alan Cox33f0f882006-01-09 20:54:13 -08004472 if (tty == NULL || (buflen = tty_buffer_request_room(tty, len)) == 0) {
Jiri Slaby319fe7c2008-02-07 00:16:36 -08004473 len = min_t(unsigned int, len, sizeof(stl_unwanted));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004474 outb(GRXFIFO, (ioaddr + XP_ADDR));
4475 insb((ioaddr + XP_DATA), &stl_unwanted[0], len);
4476 portp->stats.rxlost += len;
4477 portp->stats.rxtotal += len;
4478 } else {
Jiri Slaby843b5682006-12-08 02:39:12 -08004479 len = min(len, buflen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004480 if (len > 0) {
Alan Cox33f0f882006-01-09 20:54:13 -08004481 unsigned char *ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004482 outb(GRXFIFO, (ioaddr + XP_ADDR));
Alan Cox33f0f882006-01-09 20:54:13 -08004483 tty_prepare_flip_string(tty, &ptr, len);
4484 insb((ioaddr + XP_DATA), ptr, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004485 tty_schedule_flip(tty);
4486 portp->stats.rxtotal += len;
4487 }
4488 }
4489 } else {
4490 stl_sc26198rxbadchars(portp);
4491 }
4492
4493/*
4494 * If we are TX flow controlled and in IXANY mode then we may need
4495 * to unflow control here. We gotta do this because of the automatic
4496 * flow control modes of the sc26198.
4497 */
4498 if (test_bit(ASYI_TXFLOWED, &portp->istate)) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08004499 if ((tty != NULL) &&
4500 (tty->termios != NULL) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07004501 (tty->termios->c_iflag & IXANY)) {
4502 stl_sc26198txunflow(portp, tty);
4503 }
4504 }
Alan Coxd18a7502008-10-13 10:40:07 +01004505 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004506}
4507
4508/*****************************************************************************/
4509
4510/*
4511 * Process an RX bad character.
4512 */
4513
Jiri Slaby60be4812006-12-08 02:38:40 -08004514static void stl_sc26198rxbadch(struct stlport *portp, unsigned char status, char ch)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004515{
4516 struct tty_struct *tty;
4517 unsigned int ioaddr;
4518
Alan Coxd18a7502008-10-13 10:40:07 +01004519 tty = tty_port_tty_get(&portp->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004520 ioaddr = portp->ioaddr;
4521
4522 if (status & SR_RXPARITY)
4523 portp->stats.rxparity++;
4524 if (status & SR_RXFRAMING)
4525 portp->stats.rxframing++;
4526 if (status & SR_RXOVERRUN)
4527 portp->stats.rxoverrun++;
4528 if (status & SR_RXBREAK)
4529 portp->stats.rxbreaks++;
4530
Jiri Slaby615e4a72006-12-08 02:38:38 -08004531 if ((tty != NULL) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07004532 ((portp->rxignoremsk & status) == 0)) {
4533 if (portp->rxmarkmsk & status) {
4534 if (status & SR_RXBREAK) {
4535 status = TTY_BREAK;
Alan Coxf8ae4762008-07-16 21:56:37 +01004536 if (portp->port.flags & ASYNC_SAK) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004537 do_SAK(tty);
4538 BRDENABLE(portp->brdnr, portp->pagenr);
4539 }
Jiri Slabyc62429d2006-12-08 02:39:14 -08004540 } else if (status & SR_RXPARITY)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004541 status = TTY_PARITY;
Jiri Slabyc62429d2006-12-08 02:39:14 -08004542 else if (status & SR_RXFRAMING)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004543 status = TTY_FRAME;
Jiri Slabyc62429d2006-12-08 02:39:14 -08004544 else if(status & SR_RXOVERRUN)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004545 status = TTY_OVERRUN;
Jiri Slabyc62429d2006-12-08 02:39:14 -08004546 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07004547 status = 0;
Jiri Slabyc62429d2006-12-08 02:39:14 -08004548 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07004549 status = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004550
Alan Cox33f0f882006-01-09 20:54:13 -08004551 tty_insert_flip_char(tty, ch, status);
4552 tty_schedule_flip(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004553
4554 if (status == 0)
4555 portp->stats.rxtotal++;
4556 }
Alan Coxd18a7502008-10-13 10:40:07 +01004557 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004558}
4559
4560/*****************************************************************************/
4561
4562/*
4563 * Process all characters in the RX FIFO of the UART. Check all char
4564 * status bytes as well, and process as required. We need to check
4565 * all bytes in the FIFO, in case some more enter the FIFO while we
4566 * are here. To get the exact character error type we need to switch
4567 * into CHAR error mode (that is why we need to make sure we empty
4568 * the FIFO).
4569 */
4570
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004571static void stl_sc26198rxbadchars(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004572{
4573 unsigned char status, mr1;
4574 char ch;
4575
4576/*
4577 * To get the precise error type for each character we must switch
4578 * back into CHAR error mode.
4579 */
4580 mr1 = stl_sc26198getreg(portp, MR1);
4581 stl_sc26198setreg(portp, MR1, (mr1 & ~MR1_ERRBLOCK));
4582
4583 while ((status = stl_sc26198getreg(portp, SR)) & SR_RXRDY) {
4584 stl_sc26198setreg(portp, SCCR, CR_CLEARRXERR);
4585 ch = stl_sc26198getreg(portp, RXFIFO);
4586 stl_sc26198rxbadch(portp, status, ch);
4587 }
4588
4589/*
4590 * To get correct interrupt class we must switch back into BLOCK
4591 * error mode.
4592 */
4593 stl_sc26198setreg(portp, MR1, mr1);
4594}
4595
4596/*****************************************************************************/
4597
4598/*
4599 * Other interrupt handler. This includes modem signals, flow
4600 * control actions, etc. Most stuff is left to off-level interrupt
4601 * processing time.
4602 */
4603
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004604static void stl_sc26198otherisr(struct stlport *portp, unsigned int iack)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004605{
4606 unsigned char cir, ipr, xisr;
4607
Jiri Slabya0564e12006-12-08 02:38:37 -08004608 pr_debug("stl_sc26198otherisr(portp=%p,iack=%x)\n", portp, iack);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004609
4610 cir = stl_sc26198getglobreg(portp, CIR);
4611
4612 switch (cir & CIR_SUBTYPEMASK) {
4613 case CIR_SUBCOS:
4614 ipr = stl_sc26198getreg(portp, IPR);
4615 if (ipr & IPR_DCDCHANGE) {
Jiri Slabyccfea3c2008-02-07 00:16:39 -08004616 stl_cd_change(portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004617 portp->stats.modem++;
4618 }
4619 break;
4620 case CIR_SUBXONXOFF:
4621 xisr = stl_sc26198getreg(portp, XISR);
4622 if (xisr & XISR_RXXONGOT) {
4623 set_bit(ASYI_TXFLOWED, &portp->istate);
4624 portp->stats.txxoff++;
4625 }
4626 if (xisr & XISR_RXXOFFGOT) {
4627 clear_bit(ASYI_TXFLOWED, &portp->istate);
4628 portp->stats.txxon++;
4629 }
4630 break;
4631 case CIR_SUBBREAK:
4632 stl_sc26198setreg(portp, SCCR, CR_BREAKRESET);
4633 stl_sc26198rxbadchars(portp);
4634 break;
4635 default:
4636 break;
4637 }
4638}
4639
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004640static void stl_free_isabrds(void)
4641{
4642 struct stlbrd *brdp;
4643 unsigned int i;
4644
4645 for (i = 0; i < stl_nrbrds; i++) {
4646 if ((brdp = stl_brds[i]) == NULL || (brdp->state & STL_PROBED))
4647 continue;
4648
4649 free_irq(brdp->irq, brdp);
4650
4651 stl_cleanup_panels(brdp);
4652
4653 release_region(brdp->ioaddr1, brdp->iosize1);
4654 if (brdp->iosize2 > 0)
4655 release_region(brdp->ioaddr2, brdp->iosize2);
4656
4657 kfree(brdp);
4658 stl_brds[i] = NULL;
4659 }
4660}
4661
Jiri Slaby23b85a12006-12-08 02:38:40 -08004662/*
4663 * Loadable module initialization stuff.
4664 */
4665static int __init stallion_module_init(void)
4666{
Jiri Slaby843b5682006-12-08 02:39:12 -08004667 struct stlbrd *brdp;
4668 struct stlconf conf;
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08004669 unsigned int i, j;
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004670 int retval;
Jiri Slaby23b85a12006-12-08 02:38:40 -08004671
4672 printk(KERN_INFO "%s: version %s\n", stl_drvtitle, stl_drvversion);
4673
4674 spin_lock_init(&stallion_lock);
4675 spin_lock_init(&brd_lock);
4676
Jiri Slabye4151092007-06-08 13:46:52 -07004677 stl_serial = alloc_tty_driver(STL_MAXBRDS * STL_MAXPORTS);
4678 if (!stl_serial) {
4679 retval = -ENOMEM;
4680 goto err;
4681 }
4682
4683 stl_serial->owner = THIS_MODULE;
4684 stl_serial->driver_name = stl_drvname;
4685 stl_serial->name = "ttyE";
4686 stl_serial->major = STL_SERIALMAJOR;
4687 stl_serial->minor_start = 0;
4688 stl_serial->type = TTY_DRIVER_TYPE_SERIAL;
4689 stl_serial->subtype = SERIAL_TYPE_NORMAL;
4690 stl_serial->init_termios = stl_deftermios;
4691 stl_serial->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
4692 tty_set_operations(stl_serial, &stl_ops);
4693
4694 retval = tty_register_driver(stl_serial);
4695 if (retval) {
4696 printk("STALLION: failed to register serial driver\n");
4697 goto err_frtty;
4698 }
4699
Jiri Slaby843b5682006-12-08 02:39:12 -08004700/*
4701 * Find any dynamically supported boards. That is via module load
4702 * line options.
4703 */
4704 for (i = stl_nrbrds; i < stl_nargs; i++) {
4705 memset(&conf, 0, sizeof(conf));
4706 if (stl_parsebrd(&conf, stl_brdsp[i]) == 0)
4707 continue;
4708 if ((brdp = stl_allocbrd()) == NULL)
4709 continue;
4710 brdp->brdnr = i;
4711 brdp->brdtype = conf.brdtype;
4712 brdp->ioaddr1 = conf.ioaddr1;
4713 brdp->ioaddr2 = conf.ioaddr2;
4714 brdp->irq = conf.irq;
4715 brdp->irqtype = conf.irqtype;
Ingo Korbb08b5ad2007-06-23 17:16:35 -07004716 stl_brds[brdp->brdnr] = brdp;
4717 if (stl_brdinit(brdp)) {
4718 stl_brds[brdp->brdnr] = NULL;
Jiri Slaby843b5682006-12-08 02:39:12 -08004719 kfree(brdp);
Ingo Korbb08b5ad2007-06-23 17:16:35 -07004720 } else {
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08004721 for (j = 0; j < brdp->nrports; j++)
4722 tty_register_device(stl_serial,
4723 brdp->brdnr * STL_MAXPORTS + j, NULL);
Jiri Slaby843b5682006-12-08 02:39:12 -08004724 stl_nrbrds = i + 1;
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08004725 }
Jiri Slaby843b5682006-12-08 02:39:12 -08004726 }
Jiri Slaby23b85a12006-12-08 02:38:40 -08004727
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08004728 /* this has to be _after_ isa finding because of locking */
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08004729 retval = pci_register_driver(&stl_pcidriver);
Jiri Slabye4151092007-06-08 13:46:52 -07004730 if (retval && stl_nrbrds == 0) {
4731 printk(KERN_ERR "STALLION: can't register pci driver\n");
4732 goto err_unrtty;
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004733 }
Jiri Slaby23b85a12006-12-08 02:38:40 -08004734
4735/*
4736 * Set up a character driver for per board stuff. This is mainly used
4737 * to do stats ioctls on the ports.
4738 */
4739 if (register_chrdev(STL_SIOMEMMAJOR, "staliomem", &stl_fsiomem))
4740 printk("STALLION: failed to register serial board device\n");
4741
4742 stallion_class = class_create(THIS_MODULE, "staliomem");
Jiri Slabye4151092007-06-08 13:46:52 -07004743 if (IS_ERR(stallion_class))
4744 printk("STALLION: failed to create class\n");
Jiri Slaby23b85a12006-12-08 02:38:40 -08004745 for (i = 0; i < 4; i++)
Greg Kroah-Hartman03457cd2008-07-21 20:03:34 -07004746 device_create(stallion_class, NULL, MKDEV(STL_SIOMEMMAJOR, i),
4747 NULL, "staliomem%d", i);
Jiri Slaby23b85a12006-12-08 02:38:40 -08004748
Jiri Slaby23b85a12006-12-08 02:38:40 -08004749 return 0;
Jiri Slabye4151092007-06-08 13:46:52 -07004750err_unrtty:
4751 tty_unregister_driver(stl_serial);
4752err_frtty:
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004753 put_tty_driver(stl_serial);
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08004754err:
4755 return retval;
Jiri Slaby23b85a12006-12-08 02:38:40 -08004756}
4757
4758static void __exit stallion_module_exit(void)
4759{
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08004760 struct stlbrd *brdp;
4761 unsigned int i, j;
Jiri Slaby23b85a12006-12-08 02:38:40 -08004762
4763 pr_debug("cleanup_module()\n");
4764
4765 printk(KERN_INFO "Unloading %s: version %s\n", stl_drvtitle,
4766 stl_drvversion);
4767
4768/*
4769 * Free up all allocated resources used by the ports. This includes
4770 * memory and interrupts. As part of this process we will also do
4771 * a hangup on every open port - to try to flush out any processes
4772 * hanging onto ports.
4773 */
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08004774 for (i = 0; i < stl_nrbrds; i++) {
4775 if ((brdp = stl_brds[i]) == NULL || (brdp->state & STL_PROBED))
4776 continue;
4777 for (j = 0; j < brdp->nrports; j++)
4778 tty_unregister_device(stl_serial,
4779 brdp->brdnr * STL_MAXPORTS + j);
4780 }
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004781
Jiri Slaby23b85a12006-12-08 02:38:40 -08004782 for (i = 0; i < 4; i++)
tonyj@suse.de07c015e2007-08-07 22:28:44 -07004783 device_destroy(stallion_class, MKDEV(STL_SIOMEMMAJOR, i));
Akinobu Mita68fc4fa2007-07-19 01:47:50 -07004784 unregister_chrdev(STL_SIOMEMMAJOR, "staliomem");
Jiri Slaby23b85a12006-12-08 02:38:40 -08004785 class_destroy(stallion_class);
4786
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08004787 pci_unregister_driver(&stl_pcidriver);
4788
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004789 stl_free_isabrds();
Jiri Slabye4151092007-06-08 13:46:52 -07004790
4791 tty_unregister_driver(stl_serial);
4792 put_tty_driver(stl_serial);
Jiri Slaby23b85a12006-12-08 02:38:40 -08004793}
4794
4795module_init(stallion_module_init);
4796module_exit(stallion_module_exit);
4797
4798MODULE_AUTHOR("Greg Ungerer");
4799MODULE_DESCRIPTION("Stallion Multiport Serial Driver");
4800MODULE_LICENSE("GPL");